From 51c67d44c4753d5d4f7dbe027fd195cb0f89518b Mon Sep 17 00:00:00 2001 From: makspll Date: Wed, 2 Apr 2025 08:48:24 +0100 Subject: [PATCH] refactor: reflect reference internally --- .../src/bindings/pretty_print.rs | 2 +- .../src/bindings/reference.rs | 101 ++++++++++++------ 2 files changed, 72 insertions(+), 31 deletions(-) diff --git a/crates/bevy_mod_scripting_core/src/bindings/pretty_print.rs b/crates/bevy_mod_scripting_core/src/bindings/pretty_print.rs index 65d83c426d..72e9d808a9 100644 --- a/crates/bevy_mod_scripting_core/src/bindings/pretty_print.rs +++ b/crates/bevy_mod_scripting_core/src/bindings/pretty_print.rs @@ -123,7 +123,7 @@ impl ReflectReferencePrinter { } fn pretty_print_base(base: &ReflectBaseType, world: Option, out: &mut String) { - let type_id = base.type_id; + let type_id = base.type_id(); let type_path = if let Some(world) = world { type_id.display_with_world(world.clone()) } else { diff --git a/crates/bevy_mod_scripting_core/src/bindings/reference.rs b/crates/bevy_mod_scripting_core/src/bindings/reference.rs index ea5899da27..9df1e2fbdc 100644 --- a/crates/bevy_mod_scripting_core/src/bindings/reference.rs +++ b/crates/bevy_mod_scripting_core/src/bindings/reference.rs @@ -33,6 +33,7 @@ use std::{any::TypeId, fmt::Debug}; /// Bindings defined on this type, apply to ALL references. #[derive(Debug, Clone, PartialEq, Eq, Reflect)] #[reflect(Default, opaque)] +#[non_exhaustive] pub struct ReflectReference { /// The base type and id of the value we want to access pub base: ReflectBaseType, @@ -124,19 +125,10 @@ impl ReflectReference { value: Box, allocator: &mut ReflectAllocator, ) -> Result { - match value.get_represented_type_info() { - Some(i) => { - let id = allocator.allocate_boxed(value); - Ok(ReflectReference { - base: ReflectBaseType { - type_id: i.type_id(), - base_id: ReflectBase::Owned(id), - }, - reflect_path: ParsedPath(Vec::default()), - }) - } - None => Err(InteropError::unsupported_operation(None, Some(value), "Tried to create a reference to a partial reflect value with no represented type info")), - } + Ok(ReflectReference { + base: ReflectBaseType::new_allocated_base_partial(value, allocator)?, + reflect_path: ParsedPath(Vec::default()), + }) } /// Create a new reference to a value by allocating it. @@ -144,25 +136,16 @@ impl ReflectReference { value: Box, allocator: &mut ReflectAllocator, ) -> ReflectReference { - let type_id = value.type_id(); - let id = allocator.allocate_boxed(value.into_partial_reflect()); ReflectReference { - base: ReflectBaseType { - type_id, - base_id: ReflectBase::Owned(id), - }, + base: ReflectBaseType::new_allocated_base(value, allocator), reflect_path: ParsedPath(Vec::default()), } } /// Create a new reference to resource pub fn new_resource_ref(world: WorldGuard) -> Result { - let reflect_id = ReflectAccessId::for_resource::(&world.as_unsafe_world_cell()?)?; Ok(Self { - base: ReflectBaseType { - type_id: TypeId::of::(), - base_id: ReflectBase::Resource(reflect_id.into()), - }, + base: ReflectBaseType::new_resource_base::(world)?, reflect_path: ParsedPath(Vec::default()), }) } @@ -172,12 +155,8 @@ impl ReflectReference { entity: Entity, world: WorldGuard, ) -> Result { - let reflect_id = ReflectAccessId::for_component::(&world.as_unsafe_world_cell()?)?; Ok(Self { - base: ReflectBaseType { - type_id: TypeId::of::(), - base_id: ReflectBase::Component(entity, reflect_id.into()), - }, + base: ReflectBaseType::new_component_base::(entity, world)?, reflect_path: ParsedPath(Vec::default()), }) } @@ -407,6 +386,7 @@ impl ReflectReference { self.base.type_id, "Invariant violated" ); + let base = unsafe { from_ptr_data.as_reflect_mut(ptr.into_inner()) }; drop(type_registry); self.walk_path_mut(base.as_partial_reflect_mut()) @@ -435,11 +415,72 @@ impl ReflectReference { /// The type id and base id of the value we want to access pub struct ReflectBaseType { /// The type id of the value we want to access - pub type_id: TypeId, + /// This MUST always be inline with the type id we are pointing to + pub(crate) type_id: TypeId, /// The base kind of the value we want to access pub base_id: ReflectBase, } +impl ReflectBaseType { + #[inline] + /// Returns the type id of the value pointed to by the base + pub fn type_id(&self) -> TypeId { + self.type_id + } + + /// Create a new reflection base pointing to a component on the given entity + pub fn new_component_base( + entity: Entity, + world: WorldGuard, + ) -> Result { + let reflect_id = ReflectAccessId::for_component::(&world.as_unsafe_world_cell()?)?; + Ok(Self { + type_id: TypeId::of::(), + base_id: ReflectBase::Component(entity, reflect_id.into()), + }) + } + + /// Create a new reflection base pointing to a resource + pub fn new_resource_base(world: WorldGuard) -> Result { + let reflect_id = ReflectAccessId::for_resource::(&world.as_unsafe_world_cell()?)?; + Ok(Self { + type_id: TypeId::of::(), + base_id: ReflectBase::Resource(reflect_id.into()), + }) + } + + /// Create a new reflection base pointing to a value which will be allocated in the allocator + pub fn new_allocated_base(value: Box, allocator: &mut ReflectAllocator) -> Self { + let type_id = value.type_id(); + let id = allocator.allocate_boxed(value.into_partial_reflect()); + Self { + type_id, + base_id: ReflectBase::Owned(id), + } + } + + /// Create a new reflection base pointing to a value which will be allocated in the allocator + pub fn new_allocated_base_partial( + value: Box, + allocator: &mut ReflectAllocator, + ) -> Result { + match value.get_represented_type_info() { + Some(i) => { + let id = allocator.allocate_boxed(value); + Ok(Self { + type_id: i.type_id(), + base_id: ReflectBase::Owned(id), + }) + } + None => Err(InteropError::unsupported_operation( + None, + Some(value), + "Tried to create a reference base to a partial reflect value with no represented type info", + )), + } + } +} + /// The Id of the kind of reflection base being pointed to #[derive(Clone, Debug, PartialEq, Eq, PartialOrd)] pub enum ReflectBase {