Allow registering of resources via ReflectResource / ReflectComponent (#15496)
# Objective - Resolves #15453 ## Solution - Added new `World::resource_id` and `World::register_resource` methods to support this feature - Added new `ReflectResource::register_resource` method, and new pointer to this new function - Added new `ReflectComponent::register_component` ## Testing - Tested this locally, but couldn't test the entire crate locally, just this new feature, expect that CI will do the rest of the work. --- ## Showcase ```rs #[derive(Component, Reflect)] #[reflect(Component)] struct MyComp; let mut world = World::new(); let mut registry = TypeRegistration::of::<MyComp>(); registry.insert::<ReflectComponent>(FromType::<MyComp>::from_type()); let data = registry.data::<ReflectComponent>().unwrap(); // Its now possible to register the Component in the world this way let component_id = data.register_component(&mut world); // They will be the same assert_eq!(component_id, world.component_id::<MyComp>().unwrap()); ``` ```rs #[derive(Resource, Reflect)] #[reflect(Resource)] struct MyResource; let mut world = World::new(); let mut registry = TypeRegistration::of::<MyResource>(); registry.insert::<ReflectResource>(FromType::<MyResource>::from_type()); let data = registry.data::<ReflectResource>().unwrap(); // Same with resources let component_id = data.register_resource(&mut world); // They match assert_eq!(component_id, world.resource_id::<MyResource>().unwrap()); ```
This commit is contained in:
		
							parent
							
								
									c1486654d7
								
							
						
					
					
						commit
						c32e0b9ec2
					
				| @ -60,7 +60,7 @@ | ||||
| use super::from_reflect_with_fallback; | ||||
| use crate::{ | ||||
|     change_detection::Mut, | ||||
|     component::Component, | ||||
|     component::{Component, ComponentId}, | ||||
|     entity::Entity, | ||||
|     world::{ | ||||
|         unsafe_world_cell::UnsafeEntityCell, EntityMut, EntityWorldMut, FilteredEntityMut, | ||||
| @ -119,6 +119,8 @@ pub struct ReflectComponentFns { | ||||
|     pub reflect_unchecked_mut: unsafe fn(UnsafeEntityCell<'_>) -> Option<Mut<'_, dyn Reflect>>, | ||||
|     /// Function pointer implementing [`ReflectComponent::copy()`].
 | ||||
|     pub copy: fn(&World, &mut World, Entity, Entity, &TypeRegistry), | ||||
|     /// Function pointer implementing [`ReflectComponent::register_component()`].
 | ||||
|     pub register_component: fn(&mut World) -> ComponentId, | ||||
| } | ||||
| 
 | ||||
| impl ReflectComponentFns { | ||||
| @ -220,6 +222,11 @@ impl ReflectComponent { | ||||
|         ); | ||||
|     } | ||||
| 
 | ||||
|     /// Register the type of this [`Component`] in [`World`], returning its [`ComponentId`].
 | ||||
|     pub fn register_component(&self, world: &mut World) -> ComponentId { | ||||
|         (self.0.register_component)(world) | ||||
|     } | ||||
| 
 | ||||
|     /// Create a custom implementation of [`ReflectComponent`].
 | ||||
|     ///
 | ||||
|     /// This is an advanced feature,
 | ||||
| @ -303,6 +310,9 @@ impl<C: Component + Reflect + TypePath> FromType<C> for ReflectComponent { | ||||
|                 let c = unsafe { entity.get_mut::<C>() }; | ||||
|                 c.map(|c| c.map_unchanged(|value| value as &mut dyn Reflect)) | ||||
|             }, | ||||
|             register_component: |world: &mut World| -> ComponentId { | ||||
|                 world.register_component::<C>() | ||||
|             }, | ||||
|         }) | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -6,6 +6,7 @@ | ||||
| 
 | ||||
| use crate::{ | ||||
|     change_detection::Mut, | ||||
|     component::ComponentId, | ||||
|     system::Resource, | ||||
|     world::{unsafe_world_cell::UnsafeWorldCell, World}, | ||||
| }; | ||||
| @ -59,6 +60,8 @@ pub struct ReflectResourceFns { | ||||
|     pub reflect_unchecked_mut: unsafe fn(UnsafeWorldCell<'_>) -> Option<Mut<'_, dyn Reflect>>, | ||||
|     /// Function pointer implementing [`ReflectResource::copy()`].
 | ||||
|     pub copy: fn(&World, &mut World, &TypeRegistry), | ||||
|     /// Function pointer implementing [`ReflectResource::register_resource()`].
 | ||||
|     pub register_resource: fn(&mut World) -> ComponentId, | ||||
| } | ||||
| 
 | ||||
| impl ReflectResourceFns { | ||||
| @ -145,6 +148,11 @@ impl ReflectResource { | ||||
|         (self.0.copy)(source_world, destination_world, registry); | ||||
|     } | ||||
| 
 | ||||
|     /// Register the type of this [`Resource`] in [`World`], returning the [`ComponentId`]
 | ||||
|     pub fn register_resource(&self, world: &mut World) -> ComponentId { | ||||
|         (self.0.register_resource)(world) | ||||
|     } | ||||
| 
 | ||||
|     /// Create a custom implementation of [`ReflectResource`].
 | ||||
|     ///
 | ||||
|     /// This is an advanced feature,
 | ||||
| @ -217,6 +225,10 @@ impl<R: Resource + FromReflect + TypePath> FromType<R> for ReflectResource { | ||||
|                     from_reflect_with_fallback::<R>(source_resource, destination_world, registry); | ||||
|                 destination_world.insert_resource(destination_resource); | ||||
|             }, | ||||
| 
 | ||||
|             register_resource: |world: &mut World| -> ComponentId { | ||||
|                 world.register_resource::<R>() | ||||
|             }, | ||||
|         }) | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -334,6 +334,25 @@ impl World { | ||||
|         self.components.component_id::<T>() | ||||
|     } | ||||
| 
 | ||||
|     /// Registers a new [`Resource`] type and returns the [`ComponentId`] created for it.
 | ||||
|     ///
 | ||||
|     /// Note that the resource doesn't have a value in world, it's only registered.
 | ||||
|     /// if you want to insert the [`Resource`] in the [`World`], use [`World::init_resource`] or [`World::insert_resource`] instead.
 | ||||
|     pub fn register_resource<R: Resource>(&mut self) -> ComponentId { | ||||
|         self.components.register_resource::<R>() | ||||
|     } | ||||
| 
 | ||||
|     /// Returns the [`ComponentId`] of the given [`Resource`] type `T`.
 | ||||
|     ///
 | ||||
|     /// The returned `ComponentId` is specific to the `World` instance
 | ||||
|     /// it was retrieved from and should not be used with another `World` instance.
 | ||||
|     ///
 | ||||
|     /// Returns [`None`] if the `Resource` type has not yet been initialized within
 | ||||
|     /// the `World` using [`World::register_resource`], [`World::init_resource`] or [`World::insert_resource`].
 | ||||
|     pub fn resource_id<T: Resource>(&self) -> Option<ComponentId> { | ||||
|         self.components.get_resource_id(TypeId::of::<T>()) | ||||
|     } | ||||
| 
 | ||||
|     /// Retrieves an [`EntityRef`] that exposes read-only operations for the given `entity`.
 | ||||
|     /// This will panic if the `entity` does not exist. Use [`World::get_entity`] if you want
 | ||||
|     /// to check for entity existence instead of implicitly panic-ing.
 | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user
	 Pablo Reinhardt
						Pablo Reinhardt