Skip to content

Commit 4223a38

Browse files
authored
Merge branch 'makspll:main' into main
2 parents 4370b80 + 9033243 commit 4223a38

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

44 files changed

+2926
-488
lines changed

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,7 @@ members = [
9393
"crates/ladfile",
9494
"crates/lad_backends/mdbook_lad_preprocessor",
9595
"crates/ladfile_builder",
96+
"crates/bevy_system_reflection",
9697
]
9798
resolver = "2"
9899
exclude = ["crates/bevy_api_gen", "crates/macro_tests"]
Lines changed: 240 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,240 @@
1+
// perfect application of AI
2+
// helps proompting LLMs to do good for this project
3+
4+
# Convert lua to rhai script
5+
Convert the current test to a rhai test. below are examples and instructions on the conversions necessary:
6+
7+
## Dynamic function calls
8+
Functions which are not native to rhai MUST be explicitly called using the below syntax:
9+
10+
```rhai
11+
type.function.call(arguments...)
12+
```
13+
14+
native rhai functions MUST NOT be converted using the syntax above.
15+
16+
Below is a list of some of the native functions their argument names and some constants available in rhai:
17+
18+
```csv
19+
function,arguments
20+
is_odd,
21+
is_even,
22+
min,"a, b"
23+
max,"a, b"
24+
to_float,
25+
to_decimal,
26+
abs,value
27+
sign,value
28+
is_zero,
29+
sin,angle
30+
cos,angle
31+
tan,angle
32+
sinh,angle
33+
cosh,angle
34+
tanh,angle
35+
hypot,"x, y"
36+
asin,value
37+
acos,value
38+
atan,value
39+
atan,"x, y"
40+
asinh,value
41+
acosh,value
42+
atanh,value
43+
sqrt,value
44+
exp,value
45+
ln,value
46+
log,value
47+
floor,
48+
ceiling,
49+
round,
50+
round,decimal_points
51+
int,
52+
fraction,
53+
round_up,decimal_points
54+
round_down,decimal_points
55+
round_half_up,decimal_points
56+
round_half_down,decimal_points
57+
to_int,
58+
to_decimal,
59+
to_float,
60+
to_degrees,
61+
to_radians,
62+
is_nan,
63+
is_finite,
64+
is_infinite,
65+
parse_int,"string, [radix]"
66+
parse_float,string
67+
parse_decimal,string
68+
to_binary,value
69+
to_octal,value
70+
to_hex,value
71+
PI,
72+
E,
73+
```
74+
75+
## Operators
76+
Operators are different in lua and rhai, below is a list of operators supported:
77+
78+
```
79+
Operators Assignment operators Supported types
80+
(see standard types)
81+
+, +=
82+
83+
INT
84+
FLOAT (if not no_float)
85+
Decimal (requires decimal)
86+
char
87+
string
88+
89+
-, *, /, %, **, -=, *=, /=, %=, **=
90+
91+
INT
92+
FLOAT (if not no_float)
93+
Decimal (requires decimal)
94+
95+
<<, >> <<=, >>=
96+
97+
INT
98+
99+
&, |, ^ &=, |=, ^=
100+
101+
INT (bit-wise)
102+
bool (non-short-circuiting)
103+
104+
&&, ||
105+
106+
bool (short-circuits)
107+
108+
==, !=
109+
110+
INT
111+
FLOAT (if not no_float)
112+
Decimal (requires decimal)
113+
bool
114+
char
115+
string
116+
BLOB
117+
numeric range
118+
()
119+
120+
>, >=, <, <=
121+
122+
INT
123+
FLOAT (if not no_float)
124+
Decimal (requires decimal)
125+
char
126+
string
127+
()
128+
```
129+
130+
## Function syntax
131+
Functions in rhai look like this:
132+
133+
```rhai
134+
fn function_name(arg1, arg2) {
135+
return value;
136+
}
137+
```
138+
139+
## Semicolons
140+
Every statement must end in a semicolon
141+
142+
143+
Below is a new section on Rhai strings that you can add to the prompt:
144+
145+
## Rhai Strings
146+
147+
Rhai supports different string types such as raw strings (enclosed by matching `#` and double-quotes), multi-line literal strings (enclosed by backticks to preserve exact formatting), and strings with interpolation (using `${…}` inside multi-line literals). These variants allow you to easily include complex content like newlines, quotes, and even embedded expressions while keeping the original formatting. Here are three examples:
148+
149+
````rhai
150+
// Raw string example:
151+
let raw_str = #"Hello, raw string! \n No escape sequences here."#;
152+
````
153+
154+
````rhai
155+
// Multi-line literal string example:
156+
let multi_line = `
157+
This is a multi-line literal string,
158+
which preserves whitespaces, newlines, and "quotes" exactly.
159+
`;
160+
````
161+
162+
````rhai
163+
// String interpolation example:
164+
let value = 42;
165+
let interpolated = `The answer is ${value}, which is computed dynamically.`;
166+
````
167+
168+
## Null Checks
169+
null checks can be performed by checking `type_of(value) == "()"`
170+
171+
## Examples
172+
Below is an example lua test and its equivalent rhai script:
173+
174+
### Lua
175+
```lua
176+
local entity_a = world.spawn()
177+
local entity_b = world.spawn()
178+
local entity_c = world.spawn()
179+
local entity_d = world._get_entity_with_test_component("CompWithFromWorldAndComponentData")
180+
181+
local component_with = world.get_type_by_name("CompWithFromWorldAndComponentData")
182+
local component_without = world.get_type_by_name("CompWithDefaultAndComponentData")
183+
184+
world.add_default_component(entity_a, component_with)
185+
world.add_default_component(entity_b, component_with)
186+
world.add_default_component(entity_c, component_with)
187+
188+
world.add_default_component(entity_b, component_without)
189+
190+
local found_entities = {}
191+
for i,result in pairs(world.query():component(component_with):without(component_without):build()) do
192+
table.insert(found_entities, result:entity())
193+
end
194+
195+
assert(#found_entities == 3, "Expected 3 entities, got " .. #found_entities)
196+
197+
expected_entities = {
198+
entity_c,
199+
entity_d,
200+
entity_a,
201+
}
202+
203+
for i, entity in ipairs(found_entities) do
204+
assert(entity:index() == expected_entities[i]:index(), "Expected entity " .. expected_entities[i]:index() .. " but got " .. entity:index())
205+
end
206+
```
207+
208+
### Rhai
209+
```rhai
210+
let entity_a = world.spawn_.call();
211+
let entity_b = world.spawn_.call();
212+
let entity_c = world.spawn_.call();
213+
let entity_d = world._get_entity_with_test_component.call("CompWithFromWorldAndComponentData");
214+
215+
let component_with = world.get_type_by_name.call("CompWithFromWorldAndComponentData");
216+
let component_without = world.get_type_by_name.call("CompWithDefaultAndComponentData");
217+
218+
world.add_default_component.call(entity_a, component_with);
219+
world.add_default_component.call(entity_b, component_with);
220+
world.add_default_component.call(entity_c, component_with);
221+
222+
world.add_default_component.call(entity_b, component_without);
223+
224+
let found_entities = [];
225+
for (result, i) in world.query.call().component.call(component_with).without.call(component_without).build.call() {
226+
found_entities.push(result.entity.call());
227+
}
228+
229+
assert(found_entities.len == 3, "Expected 3 entities, got " + found_entities.len);
230+
231+
let expected_entities = [
232+
entity_d,
233+
entity_a,
234+
entity_c,
235+
];
236+
237+
for (entity, i) in found_entities {
238+
assert(entity.index.call() == expected_entities[i].index.call(), "Expected entity " + expected_entities[i].index.call() + " but got " + entity.index.call());
239+
}
240+
```
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
2+
function on_test()
3+
local post_update_schedule = world.get_schedule_by_name("PostUpdate")
4+
5+
local test_system = post_update_schedule:get_system_by_name("on_test_post_update")
6+
7+
local system_a = world.add_system(
8+
post_update_schedule,
9+
system_builder("custom_system_a", script_id)
10+
:after(test_system)
11+
)
12+
13+
local system_b = world.add_system(
14+
post_update_schedule,
15+
system_builder("custom_system_b", script_id)
16+
:after(test_system)
17+
)
18+
19+
-- generate a schedule graph and verify it's what we expect
20+
local dot_graph = post_update_schedule:render_dot()
21+
22+
local expected_dot_graph = [[
23+
digraph {
24+
node_0 [label="bevy_mod_scripting_core::bindings::allocator::garbage_collector"];
25+
node_1 [label="on_test_post_update"];
26+
node_2 [label="script_integration_test_harness::dummy_before_post_update_system"];
27+
node_3 [label="script_integration_test_harness::dummy_post_update_system"];
28+
node_4 [label="custom_system_a"];
29+
node_5 [label="custom_system_b"];
30+
node_6 [label="SystemSet GarbageCollection"];
31+
node_7 [label="SystemSet ScriptSystem(custom_system_a)"];
32+
node_8 [label="SystemSet ScriptSystem(custom_system_b)"];
33+
node_0 -> node_6 [color=red, label="child of", arrowhead=diamond];
34+
node_4 -> node_7 [color=red, label="child of", arrowhead=diamond];
35+
node_5 -> node_8 [color=red, label="child of", arrowhead=diamond];
36+
node_1 -> node_4 [color=blue, label="runs before", arrowhead=normal];
37+
node_1 -> node_5 [color=blue, label="runs before", arrowhead=normal];
38+
node_2 -> node_3 [color=blue, label="runs before", arrowhead=normal];
39+
}
40+
]]
41+
42+
assert_str_eq(dot_graph, expected_dot_graph, "Expected the schedule graph to match the expected graph")
43+
end
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
fn on_test() {
2+
let post_update_schedule = world.get_schedule_by_name.call("PostUpdate");
3+
4+
let test_system = post_update_schedule.get_system_by_name.call("on_test_post_update");
5+
6+
let system_a = world.add_system.call(
7+
post_update_schedule,
8+
system_builder.call("custom_system_a", script_id)
9+
.after.call(test_system)
10+
);
11+
12+
let system_b = world.add_system.call(
13+
post_update_schedule,
14+
system_builder.call("custom_system_b", script_id)
15+
.after.call(test_system)
16+
);
17+
18+
// generate a schedule graph and verify it's what we expect
19+
let dot_graph = post_update_schedule.render_dot.call();
20+
21+
let expected_dot_graph = `
22+
digraph {
23+
node_0 [label="bevy_mod_scripting_core::bindings::allocator::garbage_collector"];
24+
node_1 [label="on_test_post_update"];
25+
node_2 [label="script_integration_test_harness::dummy_before_post_update_system"];
26+
node_3 [label="script_integration_test_harness::dummy_post_update_system"];
27+
node_4 [label="custom_system_a"];
28+
node_5 [label="custom_system_b"];
29+
node_6 [label="SystemSet GarbageCollection"];
30+
node_7 [label="SystemSet ScriptSystem(custom_system_a)"];
31+
node_8 [label="SystemSet ScriptSystem(custom_system_b)"];
32+
node_0 -> node_6 [color=red, label="child of", arrowhead=diamond];
33+
node_4 -> node_7 [color=red, label="child of", arrowhead=diamond];
34+
node_5 -> node_8 [color=red, label="child of", arrowhead=diamond];
35+
node_1 -> node_4 [color=blue, label="runs before", arrowhead=normal];
36+
node_1 -> node_5 [color=blue, label="runs before", arrowhead=normal];
37+
node_2 -> node_3 [color=blue, label="runs before", arrowhead=normal];
38+
}`;
39+
40+
assert_str_eq.call(dot_graph, expected_dot_graph, "Expected the schedule graph to match the expected graph");
41+
}

assets/tests/add_system/adds_system_in_correct_order.lua

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,13 @@ function on_test()
2020
system_builder("custom_system_before", script_id)
2121
:before(test_system)
2222
)
23+
24+
local script_system_between = world.add_system(
25+
post_update_schedule,
26+
system_builder("custom_system_between", script_id)
27+
:after(test_system)
28+
:before(system_after)
29+
)
2330
end
2431

2532

@@ -39,10 +46,16 @@ function custom_system_after()
3946
runs[#runs + 1] = "custom_system_after"
4047
end
4148

49+
function custom_system_between()
50+
print("custom_system_between")
51+
runs[#runs + 1] = "custom_system_between"
52+
end
53+
4254
-- runs in the `Last` bevy schedule
4355
function on_test_last()
44-
assert(#runs == 3, "Expected 3 runs, got: " .. #runs)
56+
assert(#runs == 4, "Expected 4 runs, got: " .. #runs)
4557
assert(runs[1] == "custom_system_before", "Expected custom_system_before to run first, got: " .. runs[1])
4658
assert(runs[2] == "on_test_post_update", "Expected on_test_post_update to run second, got: " .. runs[2])
47-
assert(runs[3] == "custom_system_after", "Expected custom_system_after to run third, got: " .. runs[3])
59+
assert(runs[3] == "custom_system_between", "Expected custom_system_between to run third, got: " .. runs[3])
60+
assert(runs[4] == "custom_system_after", "Expected custom_system_after to run second, got: " .. runs[4])
4861
end

0 commit comments

Comments
 (0)