diff --git a/crates/bevy_ecs/src/reflect.rs b/crates/bevy_ecs/src/reflect.rs index a967c60449c8a..8dc53c2ba20f6 100644 --- a/crates/bevy_ecs/src/reflect.rs +++ b/crates/bevy_ecs/src/reflect.rs @@ -1,4 +1,4 @@ -//! Types that enable reflection support. +//! Types that enable run-time type reflection of ECS data. pub use crate::change_detection::ReflectMut; use crate::{ @@ -8,9 +8,23 @@ use crate::{ }; use bevy_reflect::{impl_reflect_value, FromType, Reflect, ReflectDeserialize}; +/// A runtime type-reflectable component +/// +/// Intended for use with [`bevy_reflect`], +/// a [`ReflectComponent`] is a type-erased version of a component's data, +/// can be transformed into ['dyn Reflect'](Reflect) trait objects, +/// which can be worked with generically +/// and loaded from disk in a type-safe fashion. +/// +/// [`ReflectComponent`] objects are created for a particular [`Component`] type (`C`) using the [`from_type`](FromType::from_type) method. +/// That type `C` is implicitly stored in the function pointers held within the private fields of this type; +/// it cannot be changed after creation. +/// +/// Once a [`ReflectComponent`] object has been created, you can use that concrete struct +/// to use the methods on this type, which always implicitly affect only the component type originally used to create this struct. #[derive(Clone)] pub struct ReflectComponent { - add_component: fn(&mut World, Entity, &dyn Reflect), + insert_component: fn(&mut World, Entity, &dyn Reflect), apply_component: fn(&mut World, Entity, &dyn Reflect), remove_component: fn(&mut World, Entity), reflect_component: fn(&World, Entity) -> Option<&dyn Reflect>, @@ -19,18 +33,31 @@ pub struct ReflectComponent { } impl ReflectComponent { - pub fn add_component(&self, world: &mut World, entity: Entity, component: &dyn Reflect) { - (self.add_component)(world, entity, component); + /// Inserts the non-erased value of `component` (with type `C`) into the `entity` + /// + /// # Panics + /// `component` must have the same type `C` as the type used to create this struct + pub fn insert_component(&self, world: &mut World, entity: Entity, component: &dyn Reflect) { + (self.insert_component)(world, entity, component); } + /// Sets the existing value of type `C` found on `entity` to the non-erased value of `component` + /// + /// # Panics + /// `component` must have the same type `C` as the type used to create this struct + /// Additionally, a component of type `C` must already exist on `entity. pub fn apply_component(&self, world: &mut World, entity: Entity, component: &dyn Reflect) { (self.apply_component)(world, entity, component); } + /// Removes any component of type `C` from the `entity` pub fn remove_component(&self, world: &mut World, entity: Entity) { (self.remove_component)(world, entity); } + /// Fetches an immutable reference to the component of type `C` on `entity` + /// + /// If the `Entity` does not have a component of the specified type, `None` is returned instead. pub fn reflect_component<'a>( &self, world: &'a World, @@ -39,6 +66,9 @@ impl ReflectComponent { (self.reflect_component)(world, entity) } + /// Fetches a mutable reference to the component of type `C` on `entity` + /// + /// If the [`Entity`] does not have a component of the specified type, `None` is returned instead. pub fn reflect_component_mut<'a>( &self, world: &'a mut World, @@ -48,6 +78,13 @@ impl ReflectComponent { unsafe { (self.reflect_component_mut)(world, entity) } } + /// Fetches a mutable reference to the component of type `C` on `entity` without guaranteeing unique mutable access to the `world` + /// + /// This method does not require exclusive [`World`] access, and so multiple mutable references can be alive at once. + /// If possible, please prefer the safe version of this method, [`reflect_component_mut`](Self::reflect_component_mut). + /// + /// If the [`Entity`] does not have a component of the specified type, [`None`] is returned instead. + /// /// # Safety /// This method does not prevent you from having two mutable pointers to the same data, /// violating Rust's aliasing rules. To avoid this: @@ -62,6 +99,17 @@ impl ReflectComponent { (self.reflect_component_mut)(world, entity) } + /// Directly copies the value of the component of type `C` to a new entity + /// + /// This method creates a new component of type `C` using the [`FromWorld`] trait, + /// sets its value to the value of the component of type `C` on the `source_entity`, + /// and then inserts the new component into the `destination_entity`. + /// + /// **Note**: this method uses [`Reflect`] to create a shallow value-based copy of the component and will not respect `Clone` implementations. + /// This can have unexpected negative consequences if you are relying on ref-counting or the like. + /// + /// # Panics + /// The `source_entity` in the `source_world` must have a component of type `C` pub fn copy_component( &self, source_world: &World, @@ -81,7 +129,7 @@ impl ReflectComponent { impl FromType for ReflectComponent { fn from_type() -> Self { ReflectComponent { - add_component: |world, entity, reflected_component| { + insert_component: |world, entity, reflected_component| { let mut component = C::from_world(world); component.apply(reflected_component); world.entity_mut(entity).insert(component); @@ -122,6 +170,7 @@ impl FromType for ReflectComponent { impl_reflect_value!(Entity(Hash, PartialEq, Serialize, Deserialize)); +/// A reflected [EntityMap] #[derive(Clone)] pub struct ReflectMapEntities { map_entities: fn(&mut World, &EntityMap) -> Result<(), MapEntitiesError>, diff --git a/crates/bevy_scene/src/dynamic_scene.rs b/crates/bevy_scene/src/dynamic_scene.rs index 69c6b817ce71e..7197d000754bc 100644 --- a/crates/bevy_scene/src/dynamic_scene.rs +++ b/crates/bevy_scene/src/dynamic_scene.rs @@ -87,7 +87,7 @@ impl DynamicScene { { reflect_component.apply_component(world, entity, &**component); } else { - reflect_component.add_component(world, entity, &**component); + reflect_component.insert_component(world, entity, &**component); } } }