Skip to content

Commit 5f34f88

Browse files
committed
WIP
1 parent e347a8b commit 5f34f88

File tree

5 files changed

+177
-93
lines changed

5 files changed

+177
-93
lines changed

crates/bevy_mod_scripting_core/src/bindings/reference.rs

Lines changed: 78 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -28,15 +28,14 @@ use bevy::{
2828
},
2929
ptr::Ptr,
3030
reflect::{
31-
Access, ParsedPath, PartialReflect, Reflect, ReflectFromPtr, ReflectPath, ReflectPathError,
32-
TypeInfo, TypeRegistry,
31+
Access, DynamicEnum, DynamicTuple, ParsedPath, PartialReflect, Reflect, ReflectFromPtr, ReflectPath, ReflectPathError, TypeInfo, TypeRegistry
3332
},
3433
};
3534
use smallvec::SmallVec;
3635

3736
use crate::{
3837
bindings::{ReflectAllocation, ReflectAllocationId},
39-
prelude::{ReflectAllocator, ScriptError, ScriptResult}, reflection_extensions::TypeIdExtensions,
38+
prelude::{ReflectAllocator, ScriptError, ScriptResult}, reflection_extensions::{PartialReflectExt, TypeIdExtensions},
4039
};
4140

4241
use super::{
@@ -64,6 +63,16 @@ impl ReflectReference {
6463
ReflectRefIter::new_indexed(self)
6564
}
6665

66+
/// Attempts to insert into the reflected value, if the underlying supports inserting at usize indices
67+
pub fn insert_at(&mut self, world: &WorldAccessGuard, index: usize, elem: ReflectReference) -> ScriptResult<()> {
68+
self.with_reflect_mut(world, |target, type_registry, allocator| {
69+
elem.with_reflect_only(world, type_registry, allocator, |other,_,_| {
70+
target.insert_at(index, other.clone_value())
71+
})?
72+
})??;
73+
Ok(())
74+
}
75+
6776
/// Prints the reference using the world to resolve type names.
6877
pub fn print_with_world(&self, world: &WorldAccessGuard) -> String {
6978
world.with_resource(|_, type_registry: Mut<AppTypeRegistry>| {
@@ -119,10 +128,23 @@ impl ReflectReference {
119128

120129
/// A form of [`Self::reflect`] which does the access checks for you.
121130
#[track_caller]
122-
pub fn with_reflect<O, F: FnOnce(&dyn PartialReflect, &TypeRegistry , &ReflectAllocator) -> O>(
131+
pub fn with_reflect<O, F: FnOnce(&dyn PartialReflect, &TypeRegistry , &mut ReflectAllocator) -> O>(
123132
&self,
124133
world: &WorldAccessGuard,
125134
f: F,
135+
) -> ScriptResult<O> {
136+
world.with_allocator_and_type_registry(|world, type_registry, mut allocator| {
137+
let type_registry = type_registry.write();
138+
self.with_reflect_only(world, &type_registry, &mut allocator, f)
139+
})
140+
}
141+
142+
pub fn with_reflect_only<O, F: FnOnce(&dyn PartialReflect, &TypeRegistry , &mut ReflectAllocator) -> O>(
143+
&self,
144+
world: &WorldAccessGuard,
145+
type_registry: &TypeRegistry,
146+
allocator: &mut ReflectAllocator,
147+
f: F,
126148
) -> ScriptResult<O> {
127149
let access = world
128150
.get_access_timeout(
@@ -131,51 +153,54 @@ impl ReflectReference {
131153
DEFAULT_INTERVAL,
132154
);
133155

134-
let out = world.with_allocator_and_type_registry(|_, type_registry, allocator| {
135-
let type_registry = type_registry.read();
136-
let reflect = self
137-
.reflect(
138-
world.as_unsafe_world_cell(),
139-
&access,
140-
&type_registry,
141-
Some(&allocator),
142-
)?;
143-
let o = f(reflect, &type_registry, &allocator);
144-
145-
Ok(o)
146-
});
156+
let reflect = self
157+
.reflect(
158+
world.as_unsafe_world_cell(),
159+
&access,
160+
type_registry,
161+
Some(allocator),
162+
).map(|r| f(r, type_registry, allocator));
147163

148164
world.release_access(access);
149-
out
165+
reflect
150166
}
151167

152168
#[track_caller]
153169
pub fn with_reflect_mut<O, F: FnOnce(&mut dyn PartialReflect, &TypeRegistry, &mut ReflectAllocator) -> O>(
154170
&self,
155171
world: &WorldAccessGuard,
156172
f: F,
173+
) -> ScriptResult<O> {
174+
world.with_allocator_and_type_registry(|_, type_registry, mut allocator| {
175+
let type_registry = type_registry.read();
176+
self.with_reflect_mut_only(world, &type_registry, &mut allocator, f)
177+
})
178+
}
179+
180+
pub fn with_reflect_mut_only<O, F: FnOnce(&mut dyn PartialReflect, &TypeRegistry, &mut ReflectAllocator) -> O>(
181+
&self,
182+
world: &WorldAccessGuard,
183+
type_registry: &TypeRegistry,
184+
allocator: &mut ReflectAllocator,
185+
f: F,
157186
) -> ScriptResult<O> {
158187
let mut access = world
159188
.get_access_timeout(
160189
self.base.base_id.get_reflect_access_id(),
161190
DEFAULT_TIMEOUT,
162191
DEFAULT_INTERVAL,
163192
);
164-
let out = world.with_allocator_and_type_registry(|_, type_registry, mut allocator| {
165-
let type_registry = type_registry.read();
166-
let reflect = self
167-
.reflect_mut(
168-
world.as_unsafe_world_cell(),
169-
&mut access,
170-
&type_registry,
171-
Some(&allocator),
172-
)?;
173-
let o = f(reflect, &type_registry, &mut allocator);
174-
Ok(o)
175-
});
176193

194+
let reflect = self
195+
.reflect_mut(
196+
world.as_unsafe_world_cell(),
197+
&mut access,
198+
type_registry,
199+
Some(allocator),
200+
).map(|r| f(r, type_registry, allocator));
201+
177202
world.release_access(access);
178-
out
203+
reflect
179204
}
180205

181206
/// Returns `Ok(())` if the given access is sufficient to read the value or an appropriate error otherwise
@@ -456,12 +481,14 @@ impl ReflectBase {
456481
}
457482

458483
/// An element in the reflection path, the base reference included
459-
#[derive(Clone, PartialEq, Eq, Debug)]
484+
#[derive(Clone, Debug, PartialEq, Eq)]
460485
pub enum ReflectionPathElem {
461486
/// A standard reflection path, i.e. `.field_name[vec_index]`, pre-parsed since we construct once potentially use many times
462487
Reflection(ParsedPath),
463488
/// a deferred reflection
464489
DeferredReflection(DeferredReflection),
490+
/// a no-op reflection, i.e. a reference to the base object, useful identity to have
491+
Identity
465492
}
466493

467494
impl ReflectionPathElem {
@@ -511,6 +538,7 @@ impl<'a> ReflectPath<'a> for &'a ReflectionPathElem {
511538
match self {
512539
ReflectionPathElem::Reflection(path) => path.reflect_element(root),
513540
ReflectionPathElem::DeferredReflection(f) => (f.get)(root),
541+
ReflectionPathElem::Identity => Ok(root),
514542
}
515543
}
516544

@@ -521,6 +549,7 @@ impl<'a> ReflectPath<'a> for &'a ReflectionPathElem {
521549
match self {
522550
ReflectionPathElem::Reflection(path) => path.reflect_element_mut(root),
523551
ReflectionPathElem::DeferredReflection(defref) => (defref.get_mut)(root),
552+
ReflectionPathElem::Identity => Ok(root)
524553
}
525554
}
526555
}
@@ -542,6 +571,22 @@ pub struct DeferredReflection {
542571
>,
543572
}
544573

574+
/// Given a function, repeats it with a mutable reference for the get_mut deferred variant
575+
#[macro_export]
576+
macro_rules! new_deferred_reflection {
577+
(|$root:ident| {$($get:tt)*}) => {
578+
DeferredReflection::from((
579+
|$root: &dyn PartialReflect| -> Result<&dyn PartialReflect, ReflectPathError<'static>> {
580+
$($get)*
581+
},
582+
|$root: &mut dyn PartialReflect| -> Result<&mut dyn PartialReflect, ReflectPathError<'static>> {
583+
$($get)*
584+
},
585+
))
586+
};
587+
}
588+
589+
545590
impl Debug for DeferredReflection {
546591
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
547592
f.write_str("DeferredReflection")
@@ -614,6 +659,6 @@ impl Iterator for ReflectRefIter {
614659
}
615660
};
616661

617-
return Some(result);
662+
Some(result)
618663
}
619664
}

crates/bevy_mod_scripting_core/src/reflection_extensions.rs

Lines changed: 58 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,11 @@ pub trait PartialReflectExt {
3333
other: Box<dyn PartialReflect>,
3434
apply: F,
3535
) -> Result<(), ScriptError>;
36-
}
36+
3737

38+
/// Inserts into the type at the given key, if the type supports inserting with the given key
39+
fn insert_at(&mut self, index: usize, value: Box<dyn PartialReflect>) -> Result<(), ScriptError>;
40+
}
3841
pub trait TypeIdExtensions {
3942
fn type_id_or_dummy(&self) -> TypeId;
4043
}
@@ -129,7 +132,6 @@ impl<T: PartialReflect + ?Sized> PartialReflectExt for T {
129132
match (self.reflect_mut(), other.reflect_mut()) {
130133
(bevy::reflect::ReflectMut::List(l), bevy::reflect::ReflectMut::List(r)) => {
131134

132-
let excess_elems = max(l.len() as isize - r.len() as isize, 0) as usize;
133135
let to_be_inserted_elems = max(r.len() as isize - l.len() as isize, 0) as usize;
134136
let apply_range = 0..(r.len() - to_be_inserted_elems);
135137

@@ -153,20 +155,6 @@ impl<T: PartialReflect + ?Sized> PartialReflectExt for T {
153155
for i in apply_range {
154156
apply(l.get_mut(i).expect("invariant"), r.get(i).expect("invariant"))?;
155157
};
156-
157-
158-
159-
// for right_elem in r.iter() {
160-
// if let Some(left_elem) = l.get_mut(i) {
161-
// apply(left_elem, right_elem)?
162-
// } else {
163-
// shorter = true;
164-
// break;
165-
// }
166-
// i+=1;
167-
// };
168-
169-
170158

171159
Ok(())
172160
}
@@ -178,29 +166,27 @@ impl<T: PartialReflect + ?Sized> PartialReflectExt for T {
178166
}
179167
}
180168

181-
// fn set_as_list<I: IntoIterator<Item = Box<dyn PartialReflect>>>(
182-
// &mut self,
183-
// other: I,
184-
// ) -> Result<(), ScriptError> {
185-
// if let bevy::reflect::ReflectMut::List(list) = self.reflect_mut() {
186-
// let mut left_index = 0;
187-
// for i in other {
188-
// if let Some(left_item) = list.get_mut(left_index) {
189-
// left_item.apply
190-
// } else {
191-
// }
192-
// left_index += 1;
193-
// }
194-
// Ok(())
195-
// } else {
196-
// Err(ScriptError::new_runtime_error(format!(
197-
// "Expected list-like type from crate core, but got {}",
198-
// self.get_represented_type_info()
199-
// .map(|ti| ti.type_path())
200-
// .unwrap_or_else(|| "dynamic type with no type information")
201-
// )))
202-
// }
203-
// }
169+
fn insert_at(&mut self, index: usize, value: Box<dyn PartialReflect>) -> Result<(), ScriptError> {
170+
match self.reflect_mut() {
171+
bevy::reflect::ReflectMut::List(l) => {
172+
l.insert(index, value);
173+
Ok(())
174+
},
175+
bevy::reflect::ReflectMut::Map(m) => {
176+
m.insert_boxed(Box::new(index), value);
177+
Ok(())
178+
},
179+
bevy::reflect::ReflectMut::Set(s) => {
180+
s.insert_boxed(value);
181+
Ok(())
182+
},
183+
_ => Err(ScriptError::new_reflection_error(format!(
184+
"Could not insert into {}. The type does not support insertion at a key.",
185+
self.reflect_type_path()
186+
))),
187+
}
188+
}
189+
204190
}
205191

206192

@@ -344,4 +330,37 @@ mod test {
344330
.unwrap();
345331
assert_eq!(other, list);
346332
}
333+
334+
#[test]
335+
fn test_insert_at_vec() {
336+
let mut list = vec![1, 2, 3];
337+
let value = 4;
338+
let value_ref: Box<dyn PartialReflect> = Box::new(value);
339+
list.insert_at(&1, value_ref).unwrap();
340+
assert_eq!(vec![1, 4, 2, 3], list);
341+
}
342+
343+
#[test]
344+
fn test_insert_at_map() {
345+
let mut map = std::collections::HashMap::<i32, i32>::default();
346+
let value = 4;
347+
let value_ref: Box<dyn PartialReflect> = Box::new(value);
348+
map.insert(1, 2);
349+
map.insert(2, 3);
350+
map.insert(3, 4);
351+
map.insert_at(&1, value_ref).unwrap();
352+
assert_eq!(4, map[&1]);
353+
}
354+
355+
#[test]
356+
fn test_insert_at_set() {
357+
let mut set = std::collections::HashSet::<i32>::default();
358+
let value = 4;
359+
let value_ref: Box<dyn PartialReflect> = Box::new(value);
360+
set.insert(1);
361+
set.insert(2);
362+
set.insert(3);
363+
set.insert_at(&1, value_ref).unwrap();
364+
assert!(set.contains(&4));
365+
}
347366
}

crates/languages/bevy_mod_scripting_lua/src/bindings/reference.rs

Lines changed: 12 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -108,9 +108,10 @@ impl LuaReflectReference {
108108
}) {
109109
bevy::log::debug!("Setting value with ReflectLuaValue registration");
110110
let other = (type_data.from_value)(value, lua)?;
111-
let o = self
112-
.0
113-
.with_reflect_mut(&world, |r, _, _| r.try_apply(other.as_partial_reflect()))?;
111+
self.0.with_reflect_mut(&world, |r, _, _| {
112+
r.try_apply(other.as_partial_reflect())
113+
.map_err(ScriptError::new_reflection_error)
114+
})??;
114115
} else if let Some(type_data) =
115116
world.with_resource::<AppTypeRegistry, _, _>(|_, type_registry| {
116117
type_registry
@@ -193,6 +194,7 @@ impl LuaReflectReference {
193194
}
194195
}
195196
}
197+
196198
impl_userdata_from_lua!(LuaReflectReference);
197199

198200
impl LuaProxied for ReflectReference {
@@ -211,16 +213,6 @@ impl From<ReflectReference> for LuaReflectReference {
211213
}
212214
}
213215

214-
#[derive(Debug, Clone, tealr::mlu::UserData, tealr::ToTypename)]
215-
pub struct LuaReflectRefIter(pub ReflectRefIter);
216-
impl_userdata_from_lua!(LuaReflectRefIter);
217-
218-
impl TealData for LuaReflectRefIter {
219-
fn add_methods<'lua, T: tealr::mlu::TealDataMethods<'lua, Self>>(_methods: &mut T) {}
220-
221-
fn add_fields<'lua, F: tealr::mlu::TealDataFields<'lua, Self>>(_fields: &mut F) {}
222-
}
223-
224216
impl TealData for LuaReflectReference {
225217
fn add_methods<'lua, T: tealr::mlu::TealDataMethods<'lua, Self>>(m: &mut T) {
226218
m.add_meta_function(
@@ -256,6 +248,13 @@ impl TealData for LuaReflectReference {
256248
},
257249
);
258250

251+
m.add_function_mut(
252+
"insert",
253+
|l, (mut self_, key): (LuaReflectReference, usize, LuaReflect)| {
254+
self_.0.insert_at(key, l.get_world())
255+
},
256+
);
257+
259258
m.add_meta_function(MetaMethod::Len, |l, self_: LuaReflectReference| {
260259
self_.len(l)
261260
});

crates/languages/bevy_mod_scripting_lua/src/lib.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,9 @@ impl<A: LuaEventArg> Plugin for LuaScriptingPlugin<A> {
8282

8383
fn cleanup(&self, app: &mut App) {
8484
let mut type_registry = app.world_mut().get_resource_mut().unwrap();
85+
86+
// we register up to two levels of nesting, if more are needed, the user will have to do this manually
87+
pre_register_common_containers(&mut type_registry);
8588
pre_register_common_containers(&mut type_registry);
8689
}
8790
}

0 commit comments

Comments
 (0)