From d36e4add8b4b8426f7cb5ff048e953808b26ec46 Mon Sep 17 00:00:00 2001 From: Nicola Papale Date: Tue, 13 Jun 2023 09:21:55 +0200 Subject: [PATCH] Split the bevy_ecs reflect.rs module --- crates/bevy_ecs/src/reflect.rs | 471 -------------------- crates/bevy_ecs/src/reflect/component.rs | 269 +++++++++++ crates/bevy_ecs/src/reflect/map_entities.rs | 66 +++ crates/bevy_ecs/src/reflect/mod.rs | 17 + crates/bevy_ecs/src/reflect/resource.rs | 190 ++++++++ 5 files changed, 542 insertions(+), 471 deletions(-) delete mode 100644 crates/bevy_ecs/src/reflect.rs create mode 100644 crates/bevy_ecs/src/reflect/component.rs create mode 100644 crates/bevy_ecs/src/reflect/map_entities.rs create mode 100644 crates/bevy_ecs/src/reflect/mod.rs create mode 100644 crates/bevy_ecs/src/reflect/resource.rs diff --git a/crates/bevy_ecs/src/reflect.rs b/crates/bevy_ecs/src/reflect.rs deleted file mode 100644 index cebe950b2bce6..0000000000000 --- a/crates/bevy_ecs/src/reflect.rs +++ /dev/null @@ -1,471 +0,0 @@ -//! Types that enable reflection support. - -use crate::{ - change_detection::Mut, - component::Component, - entity::{Entity, EntityMap, EntityMapper, MapEntities}, - system::Resource, - world::{ - unsafe_world_cell::{UnsafeEntityCell, UnsafeWorldCell}, - EntityMut, EntityRef, FromWorld, World, - }, -}; -use bevy_reflect::{ - impl_from_reflect_value, impl_reflect_value, FromType, Reflect, ReflectDeserialize, - ReflectSerialize, -}; - -/// A struct used to operate on reflected [`Component`] of a type. -/// -/// A [`ReflectComponent`] for type `T` can be obtained via -/// [`bevy_reflect::TypeRegistration::data`]. -#[derive(Clone)] -pub struct ReflectComponent(ReflectComponentFns); - -/// The raw function pointers needed to make up a [`ReflectComponent`]. -/// -/// This is used when creating custom implementations of [`ReflectComponent`] with -/// [`ReflectComponent::new()`]. -/// -/// > **Note:** -/// > Creating custom implementations of [`ReflectComponent`] is an advanced feature that most users -/// > will not need. -/// > Usually a [`ReflectComponent`] is created for a type by deriving [`Reflect`] -/// > and adding the `#[reflect(Component)]` attribute. -/// > After adding the component to the [`TypeRegistry`][bevy_reflect::TypeRegistry], -/// > its [`ReflectComponent`] can then be retrieved when needed. -/// -/// Creating a custom [`ReflectComponent`] may be useful if you need to create new component types -/// at runtime, for example, for scripting implementations. -/// -/// By creating a custom [`ReflectComponent`] and inserting it into a type's -/// [`TypeRegistration`][bevy_reflect::TypeRegistration], -/// you can modify the way that reflected components of that type will be inserted into the Bevy -/// world. -#[derive(Clone)] -pub struct ReflectComponentFns { - /// Function pointer implementing [`ReflectComponent::from_world()`]. - pub from_world: fn(&mut World) -> Box, - /// Function pointer implementing [`ReflectComponent::insert()`]. - pub insert: fn(&mut EntityMut, &dyn Reflect), - /// Function pointer implementing [`ReflectComponent::apply()`]. - pub apply: fn(&mut EntityMut, &dyn Reflect), - /// Function pointer implementing [`ReflectComponent::apply_or_insert()`]. - pub apply_or_insert: fn(&mut EntityMut, &dyn Reflect), - /// Function pointer implementing [`ReflectComponent::remove()`]. - pub remove: fn(&mut EntityMut), - /// Function pointer implementing [`ReflectComponent::contains()`]. - pub contains: fn(EntityRef) -> bool, - /// Function pointer implementing [`ReflectComponent::reflect()`]. - pub reflect: fn(EntityRef) -> Option<&dyn Reflect>, - /// Function pointer implementing [`ReflectComponent::reflect_mut()`]. - pub reflect_mut: for<'a> fn(&'a mut EntityMut<'_>) -> Option>, - /// Function pointer implementing [`ReflectComponent::reflect_unchecked_mut()`]. - /// - /// # Safety - /// The function may only be called with an [`UnsafeEntityCell`] that can be used to mutably access the relevant component on the given entity. - pub reflect_unchecked_mut: unsafe fn(UnsafeEntityCell<'_>) -> Option>, - /// Function pointer implementing [`ReflectComponent::copy()`]. - pub copy: fn(&World, &mut World, Entity, Entity), -} - -impl ReflectComponentFns { - /// Get the default set of [`ReflectComponentFns`] for a specific component type using its - /// [`FromType`] implementation. - /// - /// This is useful if you want to start with the default implementation before overriding some - /// of the functions to create a custom implementation. - pub fn new() -> Self { - >::from_type().0 - } -} - -impl ReflectComponent { - /// Constructs default reflected [`Component`] from world using [`from_world()`](FromWorld::from_world). - pub fn from_world(&self, world: &mut World) -> Box { - (self.0.from_world)(world) - } - - /// Insert a reflected [`Component`] into the entity like [`insert()`](crate::world::EntityMut::insert). - pub fn insert(&self, entity: &mut EntityMut, component: &dyn Reflect) { - (self.0.insert)(entity, component); - } - - /// Uses reflection to set the value of this [`Component`] type in the entity to the given value. - /// - /// # Panics - /// - /// Panics if there is no [`Component`] of the given type. - pub fn apply(&self, entity: &mut EntityMut, component: &dyn Reflect) { - (self.0.apply)(entity, component); - } - - /// Uses reflection to set the value of this [`Component`] type in the entity to the given value or insert a new one if it does not exist. - pub fn apply_or_insert(&self, entity: &mut EntityMut, component: &dyn Reflect) { - (self.0.apply_or_insert)(entity, component); - } - - /// Removes this [`Component`] type from the entity. Does nothing if it doesn't exist. - pub fn remove(&self, entity: &mut EntityMut) { - (self.0.remove)(entity); - } - - /// Returns whether entity contains this [`Component`] - pub fn contains(&self, entity: EntityRef) -> bool { - (self.0.contains)(entity) - } - - /// Gets the value of this [`Component`] type from the entity as a reflected reference. - pub fn reflect<'a>(&self, entity: EntityRef<'a>) -> Option<&'a dyn Reflect> { - (self.0.reflect)(entity) - } - - /// Gets the value of this [`Component`] type from the entity as a mutable reflected reference. - pub fn reflect_mut<'a>(&self, entity: &'a mut EntityMut<'_>) -> Option> { - (self.0.reflect_mut)(entity) - } - - /// # Safety - /// This method does not prevent you from having two mutable pointers to the same data, - /// violating Rust's aliasing rules. To avoid this: - /// * Only call this method with a [`UnsafeEntityCell`] that may be used to mutably access the component on the entity `entity` - /// * Don't call this method more than once in the same scope for a given [`Component`]. - pub unsafe fn reflect_unchecked_mut<'a>( - &self, - entity: UnsafeEntityCell<'a>, - ) -> Option> { - // SAFETY: safety requirements deferred to caller - (self.0.reflect_unchecked_mut)(entity) - } - - /// Gets the value of this [`Component`] type from entity from `source_world` and [applies](Self::apply()) it to the value of this [`Component`] type in entity in `destination_world`. - /// - /// # Panics - /// - /// Panics if there is no [`Component`] of the given type or either entity does not exist. - pub fn copy( - &self, - source_world: &World, - destination_world: &mut World, - source_entity: Entity, - destination_entity: Entity, - ) { - (self.0.copy)( - source_world, - destination_world, - source_entity, - destination_entity, - ); - } - - /// Create a custom implementation of [`ReflectComponent`]. - /// - /// This is an advanced feature, - /// useful for scripting implementations, - /// that should not be used by most users - /// unless you know what you are doing. - /// - /// Usually you should derive [`Reflect`] and add the `#[reflect(Component)]` component - /// to generate a [`ReflectComponent`] implementation automatically. - /// - /// See [`ReflectComponentFns`] for more information. - pub fn new(fns: ReflectComponentFns) -> Self { - Self(fns) - } -} - -impl FromType for ReflectComponent { - fn from_type() -> Self { - ReflectComponent(ReflectComponentFns { - from_world: |world| Box::new(C::from_world(world)), - insert: |entity, reflected_component| { - let mut component = entity.world_scope(|world| C::from_world(world)); - component.apply(reflected_component); - entity.insert(component); - }, - apply: |entity, reflected_component| { - let mut component = entity.get_mut::().unwrap(); - component.apply(reflected_component); - }, - apply_or_insert: |entity, reflected_component| { - if let Some(mut component) = entity.get_mut::() { - component.apply(reflected_component); - } else { - let mut component = entity.world_scope(|world| C::from_world(world)); - component.apply(reflected_component); - entity.insert(component); - } - }, - remove: |entity| { - entity.remove::(); - }, - contains: |entity| entity.contains::(), - copy: |source_world, destination_world, source_entity, destination_entity| { - let source_component = source_world.get::(source_entity).unwrap(); - let mut destination_component = C::from_world(destination_world); - destination_component.apply(source_component); - destination_world - .entity_mut(destination_entity) - .insert(destination_component); - }, - reflect: |entity| entity.get::().map(|c| c as &dyn Reflect), - reflect_mut: |entity| { - entity.get_mut::().map(|c| Mut { - value: c.value as &mut dyn Reflect, - ticks: c.ticks, - }) - }, - reflect_unchecked_mut: |entity| { - // SAFETY: reflect_unchecked_mut is an unsafe function pointer used by - // `reflect_unchecked_mut` which must be called with an UnsafeEntityCell with access to the the component `C` on the `entity` - unsafe { - entity.get_mut::().map(|c| Mut { - value: c.value as &mut dyn Reflect, - ticks: c.ticks, - }) - } - }, - }) - } -} - -/// A struct used to operate on reflected [`Resource`] of a type. -/// -/// A [`ReflectResource`] for type `T` can be obtained via -/// [`bevy_reflect::TypeRegistration::data`]. -#[derive(Clone)] -pub struct ReflectResource(ReflectResourceFns); - -/// The raw function pointers needed to make up a [`ReflectResource`]. -/// -/// This is used when creating custom implementations of [`ReflectResource`] with -/// [`ReflectResource::new()`]. -/// -/// > **Note:** -/// > Creating custom implementations of [`ReflectResource`] is an advanced feature that most users -/// > will not need. -/// > Usually a [`ReflectResource`] is created for a type by deriving [`Reflect`] -/// > and adding the `#[reflect(Resource)]` attribute. -/// > After adding the component to the [`TypeRegistry`][bevy_reflect::TypeRegistry], -/// > its [`ReflectResource`] can then be retrieved when needed. -/// -/// Creating a custom [`ReflectResource`] may be useful if you need to create new resource types at -/// runtime, for example, for scripting implementations. -/// -/// By creating a custom [`ReflectResource`] and inserting it into a type's -/// [`TypeRegistration`][bevy_reflect::TypeRegistration], -/// you can modify the way that reflected resources of that type will be inserted into the bevy -/// world. -#[derive(Clone)] -pub struct ReflectResourceFns { - /// Function pointer implementing [`ReflectResource::insert()`]. - pub insert: fn(&mut World, &dyn Reflect), - /// Function pointer implementing [`ReflectResource::apply()`]. - pub apply: fn(&mut World, &dyn Reflect), - /// Function pointer implementing [`ReflectResource::apply_or_insert()`]. - pub apply_or_insert: fn(&mut World, &dyn Reflect), - /// Function pointer implementing [`ReflectResource::remove()`]. - pub remove: fn(&mut World), - /// Function pointer implementing [`ReflectResource::reflect()`]. - pub reflect: fn(&World) -> Option<&dyn Reflect>, - /// Function pointer implementing [`ReflectResource::reflect_unchecked_mut()`]. - /// - /// # Safety - /// The function may only be called with an [`UnsafeWorldCell`] that can be used to mutably access the relevant resource. - pub reflect_unchecked_mut: unsafe fn(UnsafeWorldCell<'_>) -> Option>, - /// Function pointer implementing [`ReflectResource::copy()`]. - pub copy: fn(&World, &mut World), -} - -impl ReflectResourceFns { - /// Get the default set of [`ReflectResourceFns`] for a specific resource type using its - /// [`FromType`] implementation. - /// - /// This is useful if you want to start with the default implementation before overriding some - /// of the functions to create a custom implementation. - pub fn new() -> Self { - >::from_type().0 - } -} - -impl ReflectResource { - /// Insert a reflected [`Resource`] into the world like [`insert()`](World::insert_resource). - pub fn insert(&self, world: &mut World, resource: &dyn Reflect) { - (self.0.insert)(world, resource); - } - - /// Uses reflection to set the value of this [`Resource`] type in the world to the given value. - /// - /// # Panics - /// - /// Panics if there is no [`Resource`] of the given type. - pub fn apply(&self, world: &mut World, resource: &dyn Reflect) { - (self.0.apply)(world, resource); - } - - /// Uses reflection to set the value of this [`Resource`] type in the world to the given value or insert a new one if it does not exist. - pub fn apply_or_insert(&self, world: &mut World, resource: &dyn Reflect) { - (self.0.apply_or_insert)(world, resource); - } - - /// Removes this [`Resource`] type from the world. Does nothing if it doesn't exist. - pub fn remove(&self, world: &mut World) { - (self.0.remove)(world); - } - - /// Gets the value of this [`Resource`] type from the world as a reflected reference. - pub fn reflect<'a>(&self, world: &'a World) -> Option<&'a dyn Reflect> { - (self.0.reflect)(world) - } - - /// Gets the value of this [`Resource`] type from the world as a mutable reflected reference. - pub fn reflect_mut<'a>(&self, world: &'a mut World) -> Option> { - // SAFETY: unique world access - unsafe { (self.0.reflect_unchecked_mut)(world.as_unsafe_world_cell()) } - } - - /// # Safety - /// This method does not prevent you from having two mutable pointers to the same data, - /// violating Rust's aliasing rules. To avoid this: - /// * Only call this method with an [`UnsafeWorldCell`] which can be used to mutably access the resource. - /// * Don't call this method more than once in the same scope for a given [`Resource`]. - pub unsafe fn reflect_unchecked_mut<'w>( - &self, - world: UnsafeWorldCell<'w>, - ) -> Option> { - // SAFETY: caller promises to uphold uniqueness guarantees - (self.0.reflect_unchecked_mut)(world) - } - - /// Gets the value of this [`Resource`] type from `source_world` and [applies](Self::apply()) it to the value of this [`Resource`] type in `destination_world`. - /// - /// # Panics - /// - /// Panics if there is no [`Resource`] of the given type. - pub fn copy(&self, source_world: &World, destination_world: &mut World) { - (self.0.copy)(source_world, destination_world); - } - - /// Create a custom implementation of [`ReflectResource`]. - /// - /// This is an advanced feature, - /// useful for scripting implementations, - /// that should not be used by most users - /// unless you know what you are doing. - /// - /// Usually you should derive [`Reflect`] and add the `#[reflect(Resource)]` component - /// to generate a [`ReflectResource`] implementation automatically. - /// - /// See [`ReflectResourceFns`] for more information. - pub fn new(&self, fns: ReflectResourceFns) -> Self { - Self(fns) - } -} - -impl FromType for ReflectResource { - fn from_type() -> Self { - ReflectResource(ReflectResourceFns { - insert: |world, reflected_resource| { - let mut resource = C::from_world(world); - resource.apply(reflected_resource); - world.insert_resource(resource); - }, - apply: |world, reflected_resource| { - let mut resource = world.resource_mut::(); - resource.apply(reflected_resource); - }, - apply_or_insert: |world, reflected_resource| { - if let Some(mut resource) = world.get_resource_mut::() { - resource.apply(reflected_resource); - } else { - let mut resource = C::from_world(world); - resource.apply(reflected_resource); - world.insert_resource(resource); - } - }, - remove: |world| { - world.remove_resource::(); - }, - reflect: |world| world.get_resource::().map(|res| res as &dyn Reflect), - reflect_unchecked_mut: |world| { - // SAFETY: all usages of `reflect_unchecked_mut` guarantee that there is either a single mutable - // reference or multiple immutable ones alive at any given point - unsafe { - world.get_resource_mut::().map(|res| Mut { - value: res.value as &mut dyn Reflect, - ticks: res.ticks, - }) - } - }, - copy: |source_world, destination_world| { - let source_resource = source_world.resource::(); - let mut destination_resource = C::from_world(destination_world); - destination_resource.apply(source_resource); - destination_world.insert_resource(destination_resource); - }, - }) - } -} - -impl_reflect_value!((in bevy_ecs) Entity(Hash, PartialEq, Serialize, Deserialize)); -impl_from_reflect_value!(Entity); - -/// For a specific type of component, this maps any fields with values of type [`Entity`] to a new world. -/// Since a given `Entity` ID is only valid for the world it came frome, when performing deserialization -/// any stored IDs need to be re-allocated in the destination world. -/// -/// See [`MapEntities`] for more information. -#[derive(Clone)] -pub struct ReflectMapEntities { - map_all_entities: fn(&mut World, &mut EntityMapper), - map_entities: fn(&mut World, &mut EntityMapper, &[Entity]), -} - -impl ReflectMapEntities { - /// A general method for applying [`MapEntities`] behavior to all elements in an [`EntityMap`]. - /// - /// Be mindful in its usage: Works best in situations where the entities in the [`EntityMap`] are newly - /// created, before systems have a chance to add new components. If some of the entities referred to - /// by the [`EntityMap`] might already contain valid entity references, you should use [`map_entities`](Self::map_entities). - /// - /// An example of this: A scene can be loaded with `Parent` components, but then a `Parent` component can be added - /// to these entities after they have been loaded. If you reload the scene using [`map_all_entities`](Self::map_all_entities), those `Parent` - /// components with already valid entity references could be updated to point at something else entirely. - pub fn map_all_entities(&self, world: &mut World, entity_map: &mut EntityMap) { - entity_map.world_scope(world, self.map_all_entities); - } - - /// A general method for applying [`MapEntities`] behavior to elements in an [`EntityMap`]. Unlike - /// [`map_all_entities`](Self::map_all_entities), this is applied to specific entities, not all values - /// in the [`EntityMap`]. - /// - /// This is useful mostly for when you need to be careful not to update components that already contain valid entity - /// values. See [`map_all_entities`](Self::map_all_entities) for more details. - pub fn map_entities(&self, world: &mut World, entity_map: &mut EntityMap, entities: &[Entity]) { - entity_map.world_scope(world, |world, mapper| { - (self.map_entities)(world, mapper, entities); - }); - } -} - -impl FromType for ReflectMapEntities { - fn from_type() -> Self { - ReflectMapEntities { - map_entities: |world, entity_mapper, entities| { - for &entity in entities { - if let Some(mut component) = world.get_mut::(entity) { - component.map_entities(entity_mapper); - } - } - }, - map_all_entities: |world, entity_mapper| { - let entities = entity_mapper.get_map().values().collect::>(); - for entity in &entities { - if let Some(mut component) = world.get_mut::(*entity) { - component.map_entities(entity_mapper); - } - } - }, - } - } -} diff --git a/crates/bevy_ecs/src/reflect/component.rs b/crates/bevy_ecs/src/reflect/component.rs new file mode 100644 index 0000000000000..03b3601773180 --- /dev/null +++ b/crates/bevy_ecs/src/reflect/component.rs @@ -0,0 +1,269 @@ +//! Definitions for [`Component`] reflection. +//! +//! This module exports two types: [`ReflectComponentFns`] and [`ReflectComponent`]. +//! +//! # Architecture +//! +//! [`ReflectComponent`] wraps a [`ReflectComponentFns`]. In fact, each method on +//! [`ReflectComponent`] wraps a call to a function pointer field in `ReflectComponentFns`. +//! +//! ## Who creates `ReflectComponent`s? +//! +//! When a user adds the `#[reflect(Component)]` attribute to their `#[derive(Reflect)]` +//! type, it tells the derive macro for `Reflect` to add the following single line to its +//! [`get_type_registration`] method (see the relevant code[^1]). +//! +//! ```ignore +//! registration.insert::(FromType::::from_type()); +//! ``` +//! +//! This line adds a `ReflectComponent` to the registration data for the type in question. +//! The user can access the `ReflectComponent` for type `T` through the type registry, +//! as per the `trait_reflection.rs` example. +//! +//! The `FromType::::from_type()` in the previous line calls the `FromType` +//! implementation of `ReflectComponent`. +//! +//! The `FromType` impl creates a function per field of [`ReflectComponentFns`]. +//! In those functions, we call generic methods on [`World`] and [`EntityMut`]. +//! +//! The result is a `ReflectComponent` completely independent of `C`, yet capable +//! of using generic ECS methods such as `entity.get::()` to get `&dyn Reflect` +//! with underlying type `C`, without the `C` appearing in the type signature. +//! +//! ## A note on code generation +//! +//! A downside of this approach is that monomorphized code (ie: concrete code +//! for generics) is generated **unconditionally**, regardless of whether it ends +//! up used or not. +//! +//! Adding `N` fields on `ReflectComponentFns` will generate `N × M` additional +//! functions, where `M` is how many types derive `#[reflect(Component)]`. +//! +//! Those functions will increase the size of the final app binary. +//! +//! [^1]: `crates/bevy_reflect/bevy_reflect_derive/src/registration.rs` +//! +//! [`get_type_registration`]: bevy_reflect::GetTypeRegistration::get_type_registration + +use crate::{ + change_detection::Mut, + component::Component, + entity::Entity, + world::{unsafe_world_cell::UnsafeEntityCell, EntityMut, EntityRef, FromWorld, World}, +}; +use bevy_reflect::{FromType, Reflect}; + +/// A struct used to operate on reflected [`Component`] of a type. +/// +/// A [`ReflectComponent`] for type `T` can be obtained via +/// [`bevy_reflect::TypeRegistration::data`]. +#[derive(Clone)] +pub struct ReflectComponent(ReflectComponentFns); + +/// The raw function pointers needed to make up a [`ReflectComponent`]. +/// +/// This is used when creating custom implementations of [`ReflectComponent`] with +/// [`ReflectComponent::new()`]. +/// +/// > **Note:** +/// > Creating custom implementations of [`ReflectComponent`] is an advanced feature that most users +/// > will not need. +/// > Usually a [`ReflectComponent`] is created for a type by deriving [`Reflect`] +/// > and adding the `#[reflect(Component)]` attribute. +/// > After adding the component to the [`TypeRegistry`][bevy_reflect::TypeRegistry], +/// > its [`ReflectComponent`] can then be retrieved when needed. +/// +/// Creating a custom [`ReflectComponent`] may be useful if you need to create new component types +/// at runtime, for example, for scripting implementations. +/// +/// By creating a custom [`ReflectComponent`] and inserting it into a type's +/// [`TypeRegistration`][bevy_reflect::TypeRegistration], +/// you can modify the way that reflected components of that type will be inserted into the Bevy +/// world. +#[derive(Clone)] +pub struct ReflectComponentFns { + /// Function pointer implementing [`ReflectComponent::from_world()`]. + pub from_world: fn(&mut World) -> Box, + /// Function pointer implementing [`ReflectComponent::insert()`]. + pub insert: fn(&mut EntityMut, &dyn Reflect), + /// Function pointer implementing [`ReflectComponent::apply()`]. + pub apply: fn(&mut EntityMut, &dyn Reflect), + /// Function pointer implementing [`ReflectComponent::apply_or_insert()`]. + pub apply_or_insert: fn(&mut EntityMut, &dyn Reflect), + /// Function pointer implementing [`ReflectComponent::remove()`]. + pub remove: fn(&mut EntityMut), + /// Function pointer implementing [`ReflectComponent::contains()`]. + pub contains: fn(EntityRef) -> bool, + /// Function pointer implementing [`ReflectComponent::reflect()`]. + pub reflect: fn(EntityRef) -> Option<&dyn Reflect>, + /// Function pointer implementing [`ReflectComponent::reflect_mut()`]. + pub reflect_mut: for<'a> fn(&'a mut EntityMut<'_>) -> Option>, + /// Function pointer implementing [`ReflectComponent::reflect_unchecked_mut()`]. + /// + /// # Safety + /// The function may only be called with an [`UnsafeEntityCell`] that can be used to mutably access the relevant component on the given entity. + pub reflect_unchecked_mut: unsafe fn(UnsafeEntityCell<'_>) -> Option>, + /// Function pointer implementing [`ReflectComponent::copy()`]. + pub copy: fn(&World, &mut World, Entity, Entity), +} + +impl ReflectComponentFns { + /// Get the default set of [`ReflectComponentFns`] for a specific component type using its + /// [`FromType`] implementation. + /// + /// This is useful if you want to start with the default implementation before overriding some + /// of the functions to create a custom implementation. + pub fn new() -> Self { + >::from_type().0 + } +} + +impl ReflectComponent { + /// Constructs default reflected [`Component`] from world using [`from_world()`](FromWorld::from_world). + pub fn from_world(&self, world: &mut World) -> Box { + (self.0.from_world)(world) + } + + /// Insert a reflected [`Component`] into the entity like [`insert()`](crate::world::EntityMut::insert). + pub fn insert(&self, entity: &mut EntityMut, component: &dyn Reflect) { + (self.0.insert)(entity, component); + } + + /// Uses reflection to set the value of this [`Component`] type in the entity to the given value. + /// + /// # Panics + /// + /// Panics if there is no [`Component`] of the given type. + pub fn apply(&self, entity: &mut EntityMut, component: &dyn Reflect) { + (self.0.apply)(entity, component); + } + + /// Uses reflection to set the value of this [`Component`] type in the entity to the given value or insert a new one if it does not exist. + pub fn apply_or_insert(&self, entity: &mut EntityMut, component: &dyn Reflect) { + (self.0.apply_or_insert)(entity, component); + } + + /// Removes this [`Component`] type from the entity. Does nothing if it doesn't exist. + pub fn remove(&self, entity: &mut EntityMut) { + (self.0.remove)(entity); + } + + /// Returns whether entity contains this [`Component`] + pub fn contains(&self, entity: EntityRef) -> bool { + (self.0.contains)(entity) + } + + /// Gets the value of this [`Component`] type from the entity as a reflected reference. + pub fn reflect<'a>(&self, entity: EntityRef<'a>) -> Option<&'a dyn Reflect> { + (self.0.reflect)(entity) + } + + /// Gets the value of this [`Component`] type from the entity as a mutable reflected reference. + pub fn reflect_mut<'a>(&self, entity: &'a mut EntityMut<'_>) -> Option> { + (self.0.reflect_mut)(entity) + } + + /// # Safety + /// This method does not prevent you from having two mutable pointers to the same data, + /// violating Rust's aliasing rules. To avoid this: + /// * Only call this method with a [`UnsafeEntityCell`] that may be used to mutably access the component on the entity `entity` + /// * Don't call this method more than once in the same scope for a given [`Component`]. + pub unsafe fn reflect_unchecked_mut<'a>( + &self, + entity: UnsafeEntityCell<'a>, + ) -> Option> { + // SAFETY: safety requirements deferred to caller + (self.0.reflect_unchecked_mut)(entity) + } + + /// Gets the value of this [`Component`] type from entity from `source_world` and [applies](Self::apply()) it to the value of this [`Component`] type in entity in `destination_world`. + /// + /// # Panics + /// + /// Panics if there is no [`Component`] of the given type or either entity does not exist. + pub fn copy( + &self, + source_world: &World, + destination_world: &mut World, + source_entity: Entity, + destination_entity: Entity, + ) { + (self.0.copy)( + source_world, + destination_world, + source_entity, + destination_entity, + ); + } + + /// Create a custom implementation of [`ReflectComponent`]. + /// + /// This is an advanced feature, + /// useful for scripting implementations, + /// that should not be used by most users + /// unless you know what you are doing. + /// + /// Usually you should derive [`Reflect`] and add the `#[reflect(Component)]` component + /// to generate a [`ReflectComponent`] implementation automatically. + /// + /// See [`ReflectComponentFns`] for more information. + pub fn new(fns: ReflectComponentFns) -> Self { + Self(fns) + } +} + +impl FromType for ReflectComponent { + fn from_type() -> Self { + ReflectComponent(ReflectComponentFns { + from_world: |world| Box::new(C::from_world(world)), + insert: |entity, reflected_component| { + let mut component = entity.world_scope(|world| C::from_world(world)); + component.apply(reflected_component); + entity.insert(component); + }, + apply: |entity, reflected_component| { + let mut component = entity.get_mut::().unwrap(); + component.apply(reflected_component); + }, + apply_or_insert: |entity, reflected_component| { + if let Some(mut component) = entity.get_mut::() { + component.apply(reflected_component); + } else { + let mut component = entity.world_scope(|world| C::from_world(world)); + component.apply(reflected_component); + entity.insert(component); + } + }, + remove: |entity| { + entity.remove::(); + }, + contains: |entity| entity.contains::(), + copy: |source_world, destination_world, source_entity, destination_entity| { + let source_component = source_world.get::(source_entity).unwrap(); + let mut destination_component = C::from_world(destination_world); + destination_component.apply(source_component); + destination_world + .entity_mut(destination_entity) + .insert(destination_component); + }, + reflect: |entity| entity.get::().map(|c| c as &dyn Reflect), + reflect_mut: |entity| { + entity.get_mut::().map(|c| Mut { + value: c.value as &mut dyn Reflect, + ticks: c.ticks, + }) + }, + reflect_unchecked_mut: |entity| { + // SAFETY: reflect_unchecked_mut is an unsafe function pointer used by + // `reflect_unchecked_mut` which must be called with an UnsafeEntityCell with access to the the component `C` on the `entity` + unsafe { + entity.get_mut::().map(|c| Mut { + value: c.value as &mut dyn Reflect, + ticks: c.ticks, + }) + } + }, + }) + } +} diff --git a/crates/bevy_ecs/src/reflect/map_entities.rs b/crates/bevy_ecs/src/reflect/map_entities.rs new file mode 100644 index 0000000000000..fe02e4794fce2 --- /dev/null +++ b/crates/bevy_ecs/src/reflect/map_entities.rs @@ -0,0 +1,66 @@ +use crate::{ + component::Component, + entity::{Entity, EntityMap, EntityMapper, MapEntities}, + world::World, +}; +use bevy_reflect::FromType; + +/// For a specific type of component, this maps any fields with values of type [`Entity`] to a new world. +/// Since a given `Entity` ID is only valid for the world it came frome, when performing deserialization +/// any stored IDs need to be re-allocated in the destination world. +/// +/// See [`MapEntities`] for more information. +#[derive(Clone)] +pub struct ReflectMapEntities { + map_all_entities: fn(&mut World, &mut EntityMapper), + map_entities: fn(&mut World, &mut EntityMapper, &[Entity]), +} + +impl ReflectMapEntities { + /// A general method for applying [`MapEntities`] behavior to all elements in an [`EntityMap`]. + /// + /// Be mindful in its usage: Works best in situations where the entities in the [`EntityMap`] are newly + /// created, before systems have a chance to add new components. If some of the entities referred to + /// by the [`EntityMap`] might already contain valid entity references, you should use [`map_entities`](Self::map_entities). + /// + /// An example of this: A scene can be loaded with `Parent` components, but then a `Parent` component can be added + /// to these entities after they have been loaded. If you reload the scene using [`map_all_entities`](Self::map_all_entities), those `Parent` + /// components with already valid entity references could be updated to point at something else entirely. + pub fn map_all_entities(&self, world: &mut World, entity_map: &mut EntityMap) { + entity_map.world_scope(world, self.map_all_entities); + } + + /// A general method for applying [`MapEntities`] behavior to elements in an [`EntityMap`]. Unlike + /// [`map_all_entities`](Self::map_all_entities), this is applied to specific entities, not all values + /// in the [`EntityMap`]. + /// + /// This is useful mostly for when you need to be careful not to update components that already contain valid entity + /// values. See [`map_all_entities`](Self::map_all_entities) for more details. + pub fn map_entities(&self, world: &mut World, entity_map: &mut EntityMap, entities: &[Entity]) { + entity_map.world_scope(world, |world, mapper| { + (self.map_entities)(world, mapper, entities); + }); + } +} + +impl FromType for ReflectMapEntities { + fn from_type() -> Self { + ReflectMapEntities { + map_entities: |world, entity_mapper, entities| { + for &entity in entities { + if let Some(mut component) = world.get_mut::(entity) { + component.map_entities(entity_mapper); + } + } + }, + map_all_entities: |world, entity_mapper| { + let entities = entity_mapper.get_map().values().collect::>(); + for entity in &entities { + if let Some(mut component) = world.get_mut::(*entity) { + component.map_entities(entity_mapper); + } + } + }, + } + } +} diff --git a/crates/bevy_ecs/src/reflect/mod.rs b/crates/bevy_ecs/src/reflect/mod.rs new file mode 100644 index 0000000000000..665e9e47dcd70 --- /dev/null +++ b/crates/bevy_ecs/src/reflect/mod.rs @@ -0,0 +1,17 @@ +//! Types that enable reflection support. + +use crate::entity::Entity; +use bevy_reflect::{ + impl_from_reflect_value, impl_reflect_value, ReflectDeserialize, ReflectSerialize, +}; + +mod component; +mod map_entities; +mod resource; + +pub use component::{ReflectComponent, ReflectComponentFns}; +pub use map_entities::ReflectMapEntities; +pub use resource::{ReflectResource, ReflectResourceFns}; + +impl_reflect_value!((in bevy_ecs) Entity(Hash, PartialEq, Serialize, Deserialize)); +impl_from_reflect_value!(Entity); diff --git a/crates/bevy_ecs/src/reflect/resource.rs b/crates/bevy_ecs/src/reflect/resource.rs new file mode 100644 index 0000000000000..64dc8c1017778 --- /dev/null +++ b/crates/bevy_ecs/src/reflect/resource.rs @@ -0,0 +1,190 @@ +//! Definitions for [`Resource`] reflection. +//! +//! # Architecture +//! +//! See the module doc for [`crate::reflect::component`]. + +use crate::{ + change_detection::Mut, + system::Resource, + world::{unsafe_world_cell::UnsafeWorldCell, FromWorld, World}, +}; +use bevy_reflect::{FromType, Reflect}; + +/// A struct used to operate on reflected [`Resource`] of a type. +/// +/// A [`ReflectResource`] for type `T` can be obtained via +/// [`bevy_reflect::TypeRegistration::data`]. +#[derive(Clone)] +pub struct ReflectResource(ReflectResourceFns); + +/// The raw function pointers needed to make up a [`ReflectResource`]. +/// +/// This is used when creating custom implementations of [`ReflectResource`] with +/// [`ReflectResource::new()`]. +/// +/// > **Note:** +/// > Creating custom implementations of [`ReflectResource`] is an advanced feature that most users +/// > will not need. +/// > Usually a [`ReflectResource`] is created for a type by deriving [`Reflect`] +/// > and adding the `#[reflect(Resource)]` attribute. +/// > After adding the component to the [`TypeRegistry`][bevy_reflect::TypeRegistry], +/// > its [`ReflectResource`] can then be retrieved when needed. +/// +/// Creating a custom [`ReflectResource`] may be useful if you need to create new resource types at +/// runtime, for example, for scripting implementations. +/// +/// By creating a custom [`ReflectResource`] and inserting it into a type's +/// [`TypeRegistration`][bevy_reflect::TypeRegistration], +/// you can modify the way that reflected resources of that type will be inserted into the bevy +/// world. +#[derive(Clone)] +pub struct ReflectResourceFns { + /// Function pointer implementing [`ReflectResource::insert()`]. + pub insert: fn(&mut World, &dyn Reflect), + /// Function pointer implementing [`ReflectResource::apply()`]. + pub apply: fn(&mut World, &dyn Reflect), + /// Function pointer implementing [`ReflectResource::apply_or_insert()`]. + pub apply_or_insert: fn(&mut World, &dyn Reflect), + /// Function pointer implementing [`ReflectResource::remove()`]. + pub remove: fn(&mut World), + /// Function pointer implementing [`ReflectResource::reflect()`]. + pub reflect: fn(&World) -> Option<&dyn Reflect>, + /// Function pointer implementing [`ReflectResource::reflect_unchecked_mut()`]. + /// + /// # Safety + /// The function may only be called with an [`UnsafeWorldCell`] that can be used to mutably access the relevant resource. + pub reflect_unchecked_mut: unsafe fn(UnsafeWorldCell<'_>) -> Option>, + /// Function pointer implementing [`ReflectResource::copy()`]. + pub copy: fn(&World, &mut World), +} + +impl ReflectResourceFns { + /// Get the default set of [`ReflectResourceFns`] for a specific resource type using its + /// [`FromType`] implementation. + /// + /// This is useful if you want to start with the default implementation before overriding some + /// of the functions to create a custom implementation. + pub fn new() -> Self { + >::from_type().0 + } +} + +impl ReflectResource { + /// Insert a reflected [`Resource`] into the world like [`insert()`](World::insert_resource). + pub fn insert(&self, world: &mut World, resource: &dyn Reflect) { + (self.0.insert)(world, resource); + } + + /// Uses reflection to set the value of this [`Resource`] type in the world to the given value. + /// + /// # Panics + /// + /// Panics if there is no [`Resource`] of the given type. + pub fn apply(&self, world: &mut World, resource: &dyn Reflect) { + (self.0.apply)(world, resource); + } + + /// Uses reflection to set the value of this [`Resource`] type in the world to the given value or insert a new one if it does not exist. + pub fn apply_or_insert(&self, world: &mut World, resource: &dyn Reflect) { + (self.0.apply_or_insert)(world, resource); + } + + /// Removes this [`Resource`] type from the world. Does nothing if it doesn't exist. + pub fn remove(&self, world: &mut World) { + (self.0.remove)(world); + } + + /// Gets the value of this [`Resource`] type from the world as a reflected reference. + pub fn reflect<'a>(&self, world: &'a World) -> Option<&'a dyn Reflect> { + (self.0.reflect)(world) + } + + /// Gets the value of this [`Resource`] type from the world as a mutable reflected reference. + pub fn reflect_mut<'a>(&self, world: &'a mut World) -> Option> { + // SAFETY: unique world access + unsafe { (self.0.reflect_unchecked_mut)(world.as_unsafe_world_cell()) } + } + + /// # Safety + /// This method does not prevent you from having two mutable pointers to the same data, + /// violating Rust's aliasing rules. To avoid this: + /// * Only call this method with an [`UnsafeWorldCell`] which can be used to mutably access the resource. + /// * Don't call this method more than once in the same scope for a given [`Resource`]. + pub unsafe fn reflect_unchecked_mut<'w>( + &self, + world: UnsafeWorldCell<'w>, + ) -> Option> { + // SAFETY: caller promises to uphold uniqueness guarantees + (self.0.reflect_unchecked_mut)(world) + } + + /// Gets the value of this [`Resource`] type from `source_world` and [applies](Self::apply()) it to the value of this [`Resource`] type in `destination_world`. + /// + /// # Panics + /// + /// Panics if there is no [`Resource`] of the given type. + pub fn copy(&self, source_world: &World, destination_world: &mut World) { + (self.0.copy)(source_world, destination_world); + } + + /// Create a custom implementation of [`ReflectResource`]. + /// + /// This is an advanced feature, + /// useful for scripting implementations, + /// that should not be used by most users + /// unless you know what you are doing. + /// + /// Usually you should derive [`Reflect`] and add the `#[reflect(Resource)]` component + /// to generate a [`ReflectResource`] implementation automatically. + /// + /// See [`ReflectResourceFns`] for more information. + pub fn new(&self, fns: ReflectResourceFns) -> Self { + Self(fns) + } +} + +impl FromType for ReflectResource { + fn from_type() -> Self { + ReflectResource(ReflectResourceFns { + insert: |world, reflected_resource| { + let mut resource = C::from_world(world); + resource.apply(reflected_resource); + world.insert_resource(resource); + }, + apply: |world, reflected_resource| { + let mut resource = world.resource_mut::(); + resource.apply(reflected_resource); + }, + apply_or_insert: |world, reflected_resource| { + if let Some(mut resource) = world.get_resource_mut::() { + resource.apply(reflected_resource); + } else { + let mut resource = C::from_world(world); + resource.apply(reflected_resource); + world.insert_resource(resource); + } + }, + remove: |world| { + world.remove_resource::(); + }, + reflect: |world| world.get_resource::().map(|res| res as &dyn Reflect), + reflect_unchecked_mut: |world| { + // SAFETY: all usages of `reflect_unchecked_mut` guarantee that there is either a single mutable + // reference or multiple immutable ones alive at any given point + unsafe { + world.get_resource_mut::().map(|res| Mut { + value: res.value as &mut dyn Reflect, + ticks: res.ticks, + }) + } + }, + copy: |source_world, destination_world| { + let source_resource = source_world.resource::(); + let mut destination_resource = C::from_world(destination_world); + destination_resource.apply(source_resource); + destination_world.insert_resource(destination_resource); + }, + }) + } +}