Skip to content

Commit 75bded4

Browse files
committed
hashset support and better magic functions
1 parent 64c0221 commit 75bded4

File tree

8 files changed

+321
-163
lines changed

8 files changed

+321
-163
lines changed
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
local Resource = world.get_type_by_name("TestResourceWithVariousFields")
2+
local resource = world.get_resource(Resource)
3+
4+
-- Check if "apple" exists in the set (should return Some(apple))
5+
local result = resource.string_set["apple"]
6+
assert(result ~= nil, "Expected to find 'apple' in set")
7+
8+
-- Check if "banana" exists in the set (should return Some(banana))
9+
local result2 = resource.string_set["banana"]
10+
assert(result2 ~= nil, "Expected to find 'banana' in set")
11+
12+
-- Check if "nonexistent" doesn't exist in the set (should return None)
13+
local result3 = resource.string_set["nonexistent"]
14+
assert(result3 == nil, "Expected not to find 'nonexistent' in set")
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
let Resource = world.get_type_by_name.call("TestResourceWithVariousFields");
2+
let resource = world.get_resource.call(Resource);
3+
4+
// Check if "apple" exists in the set (should return Some(apple))
5+
let result = resource.string_set["apple"];
6+
assert(result != (), "Expected to find 'apple' in set");
7+
8+
// Check if "banana" exists in the set (should return Some(banana))
9+
let result2 = resource.string_set["banana"];
10+
assert(result2 != (), "Expected to find 'banana' in set");
11+
12+
// Check if "nonexistent" doesn't exist in the set (should return None)
13+
let result3 = resource.string_set["nonexistent"];
14+
assert(result3 == (), "Expected not to find 'nonexistent' in set");
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
local Resource = world.get_type_by_name("TestResourceWithVariousFields")
2+
local resource = world.get_resource(Resource)
3+
4+
-- Insert new values into the set
5+
resource.string_set["orange"] = "orange"
6+
resource.string_set["grape"] = "grape"
7+
8+
local resource_changed = world.get_resource(Resource)
9+
10+
-- Verify the new values were added
11+
local orange = resource_changed.string_set["orange"]
12+
assert(orange ~= nil, "Expected to find 'orange' in set after insertion")
13+
14+
local grape = resource_changed.string_set["grape"]
15+
assert(grape ~= nil, "Expected to find 'grape' in set after insertion")
16+
17+
-- Verify original values are still there
18+
local apple = resource_changed.string_set["apple"]
19+
assert(apple ~= nil, "Expected 'apple' to still be in set")
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
let Resource = world.get_type_by_name.call("TestResourceWithVariousFields");
2+
let resource = world.get_resource.call(Resource);
3+
4+
// Insert new values into the set
5+
resource.string_set["orange"] = "orange";
6+
resource.string_set["grape"] = "grape";
7+
8+
let resource_changed = world.get_resource.call(Resource);
9+
10+
// Verify the new values were added
11+
let orange = resource_changed.string_set["orange"];
12+
assert(orange != (), "Expected to find 'orange' in set after insertion");
13+
14+
let grape = resource_changed.string_set["grape"];
15+
assert(grape != (), "Expected to find 'grape' in set after insertion");
16+
17+
// Verify original values are still there
18+
let apple = resource_changed.string_set["apple"];
19+
assert(apple != (), "Expected 'apple' to still be in set");

crates/bevy_mod_scripting_bindings/src/function/magic_functions.rs

Lines changed: 4 additions & 114 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,7 @@
11
//! All the switchable special functions used by language implementors
2-
use super::{FromScriptRef, FunctionCallContext, IntoScriptRef};
3-
use crate::{error::InteropError, PartialReflectExt, ReflectReference, ReflectionPathExt, ScriptValue};
2+
use super::FunctionCallContext;
3+
use crate::{error::InteropError, ReflectReference, ScriptValue};
44
use bevy_mod_scripting_derive::DebugWithTypeInfo;
5-
use bevy_mod_scripting_display::OrFakeId;
6-
use bevy_reflect::{ParsedPath, PartialReflect, ReflectRef};
75

86
/// A list of magic methods, these only have one replacable implementation, and apply to all `ReflectReferences`.
97
/// It's up to the language implementer to call these in the right order (after any type specific overrides).
@@ -64,56 +62,7 @@ impl MagicFunctions {
6462
key: ScriptValue,
6563
) -> Result<ScriptValue, InteropError> {
6664
let world = ctxt.world()?;
67-
68-
// Check if the reference is a map type
69-
let is_map = reference.with_reflect(world.clone(), |r| {
70-
matches!(r.reflect_ref(), ReflectRef::Map(_))
71-
})?;
72-
73-
if is_map {
74-
// Handle map indexing specially - need to get the key type and convert the script value
75-
let key = <Box<dyn PartialReflect>>::from_script_ref(
76-
reference.key_type_id(world.clone())?.ok_or_else(|| {
77-
InteropError::unsupported_operation(
78-
reference.tail_type_id(world.clone()).unwrap_or_default(),
79-
Some(Box::new(key.clone())),
80-
"Could not get key type id. Are you trying to index into a type that's not a map?".to_owned(),
81-
)
82-
})?,
83-
key,
84-
world.clone(),
85-
)?;
86-
87-
reference.with_reflect(world.clone(), |s| match s.try_map_get(key.as_ref())? {
88-
Some(value) => {
89-
let reference = {
90-
let allocator = world.allocator();
91-
let mut allocator = allocator.write();
92-
let owned_value = <dyn PartialReflect>::from_reflect(value, world.clone())?;
93-
ReflectReference::new_allocated_boxed(owned_value, &mut allocator)
94-
};
95-
ReflectReference::into_script_ref(reference, world)
96-
}
97-
None => {
98-
// Return None option if key doesn't exist
99-
let none_option: Option<()> = None;
100-
let reference = {
101-
let allocator = world.allocator();
102-
let mut allocator = allocator.write();
103-
ReflectReference::new_allocated_boxed(Box::new(none_option), &mut allocator)
104-
};
105-
ReflectReference::into_script_ref(reference, world)
106-
}
107-
})?
108-
} else {
109-
// Handle path-based indexing for non-map types
110-
let mut path: ParsedPath = key.try_into()?;
111-
if ctxt.convert_to_0_indexed() {
112-
path.convert_to_0_indexed();
113-
}
114-
reference.index_path(path);
115-
ReflectReference::into_script_ref(reference, world)
116-
}
65+
reference.get_indexed(key, world, ctxt.convert_to_0_indexed())
11766
}
11867

11968
/// Sets the value under the specified path on the underlying value.
@@ -133,66 +82,7 @@ impl MagicFunctions {
13382
value: ScriptValue,
13483
) -> Result<(), InteropError> {
13584
let world = ctxt.world()?;
136-
137-
// Check if the reference is a map type
138-
let is_map = reference.with_reflect(world.clone(), |r| {
139-
matches!(r.reflect_ref(), ReflectRef::Map(_))
140-
})?;
141-
142-
if is_map {
143-
// Handle map setting specially - need to get the key type and convert the script value
144-
let key = <Box<dyn PartialReflect>>::from_script_ref(
145-
reference.key_type_id(world.clone())?.ok_or_else(|| {
146-
InteropError::unsupported_operation(
147-
reference.tail_type_id(world.clone()).unwrap_or_default(),
148-
Some(Box::new(key.clone())),
149-
"Could not get key type id. Are you trying to index into a type that's not a map?".to_owned(),
150-
)
151-
})?,
152-
key,
153-
world.clone(),
154-
)?;
155-
156-
// Get the value type for the map and convert the script value
157-
let value_type_id = reference.element_type_id(world.clone())?.ok_or_else(|| {
158-
InteropError::unsupported_operation(
159-
reference.tail_type_id(world.clone()).unwrap_or_default(),
160-
Some(Box::new(value.clone())),
161-
"Could not get value type id. Are you trying to set a value in a type that's not a map?".to_owned(),
162-
)
163-
})?;
164-
165-
let value = <Box<dyn PartialReflect>>::from_script_ref(
166-
value_type_id,
167-
value,
168-
world.clone(),
169-
)?;
170-
171-
reference.with_reflect_mut(world, |s| {
172-
s.try_insert_boxed(key, value)
173-
})??;
174-
} else {
175-
let mut path: ParsedPath = key.try_into()?;
176-
if ctxt.convert_to_0_indexed() {
177-
path.convert_to_0_indexed();
178-
}
179-
reference.index_path(path);
180-
181-
let target_type_id = reference.with_reflect(world.clone(), |r| {
182-
r.get_represented_type_info()
183-
.map(|i| i.type_id())
184-
.or_fake_id()
185-
})?;
186-
187-
let other = <Box<dyn PartialReflect>>::from_script_ref(target_type_id, value, world.clone())?;
188-
189-
reference.with_reflect_mut(world, |r| {
190-
r.try_apply(other.as_partial_reflect())
191-
.map_err(InteropError::reflect_apply_error)
192-
})??;
193-
}
194-
195-
Ok(())
85+
reference.set_indexed(key, value, world, ctxt.convert_to_0_indexed())
19686
}
19787
}
19888

0 commit comments

Comments
 (0)