Add register_resource_with_descriptor (#15501)
				
					
				
			# Objective - Fixes #15448. ## Solution - Add `World::register_resource_with_descriptor` and `Components::register_resource_with_descriptor`. ## Testing - Added a test `dynamic_resource`.
This commit is contained in:
		
							parent
							
								
									fc93e13c36
								
							
						
					
					
						commit
						0d2eb3df88
					
				| @ -836,7 +836,7 @@ pub struct Components { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| impl Components { | impl Components { | ||||||
|     /// Registers a component of type `T` with this instance.
 |     /// Registers a [`Component`] of type `T` with this instance.
 | ||||||
|     /// If a component of this type has already been registered, this will return
 |     /// If a component of this type has already been registered, this will return
 | ||||||
|     /// the ID of the pre-existing component.
 |     /// the ID of the pre-existing component.
 | ||||||
|     ///
 |     ///
 | ||||||
| @ -876,9 +876,9 @@ impl Components { | |||||||
| 
 | 
 | ||||||
|     /// Registers a component described by `descriptor`.
 |     /// Registers a component described by `descriptor`.
 | ||||||
|     ///
 |     ///
 | ||||||
|     /// ## Note
 |     /// # Note
 | ||||||
|     ///
 |     ///
 | ||||||
|     /// If this method is called multiple times with identical descriptors, a distinct `ComponentId`
 |     /// If this method is called multiple times with identical descriptors, a distinct [`ComponentId`]
 | ||||||
|     /// will be created for each one.
 |     /// will be created for each one.
 | ||||||
|     ///
 |     ///
 | ||||||
|     /// # See also
 |     /// # See also
 | ||||||
| @ -1034,6 +1034,7 @@ impl Components { | |||||||
|     /// # See also
 |     /// # See also
 | ||||||
|     ///
 |     ///
 | ||||||
|     /// * [`Components::resource_id()`]
 |     /// * [`Components::resource_id()`]
 | ||||||
|  |     /// * [`Components::register_resource_with_descriptor()`]
 | ||||||
|     #[inline] |     #[inline] | ||||||
|     pub fn register_resource<T: Resource>(&mut self) -> ComponentId { |     pub fn register_resource<T: Resource>(&mut self) -> ComponentId { | ||||||
|         // SAFETY: The [`ComponentDescriptor`] matches the [`TypeId`]
 |         // SAFETY: The [`ComponentDescriptor`] matches the [`TypeId`]
 | ||||||
| @ -1044,6 +1045,24 @@ impl Components { | |||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     /// Registers a [`Resource`] described by `descriptor`.
 | ||||||
|  |     ///
 | ||||||
|  |     /// # Note
 | ||||||
|  |     ///
 | ||||||
|  |     /// If this method is called multiple times with identical descriptors, a distinct [`ComponentId`]
 | ||||||
|  |     /// will be created for each one.
 | ||||||
|  |     ///
 | ||||||
|  |     /// # See also
 | ||||||
|  |     ///
 | ||||||
|  |     /// * [`Components::resource_id()`]
 | ||||||
|  |     /// * [`Components::register_resource()`]
 | ||||||
|  |     pub fn register_resource_with_descriptor( | ||||||
|  |         &mut self, | ||||||
|  |         descriptor: ComponentDescriptor, | ||||||
|  |     ) -> ComponentId { | ||||||
|  |         Components::register_resource_inner(&mut self.components, descriptor) | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     /// Registers a [non-send resource](crate::system::NonSend) of type `T` with this instance.
 |     /// Registers a [non-send resource](crate::system::NonSend) of type `T` with this instance.
 | ||||||
|     /// If a resource of this type has already been registered, this will return
 |     /// If a resource of this type has already been registered, this will return
 | ||||||
|     /// the ID of the pre-existing resource.
 |     /// the ID of the pre-existing resource.
 | ||||||
| @ -1069,12 +1088,20 @@ impl Components { | |||||||
|         let components = &mut self.components; |         let components = &mut self.components; | ||||||
|         *self.resource_indices.entry(type_id).or_insert_with(|| { |         *self.resource_indices.entry(type_id).or_insert_with(|| { | ||||||
|             let descriptor = func(); |             let descriptor = func(); | ||||||
|             let component_id = ComponentId(components.len()); |             Components::register_resource_inner(components, descriptor) | ||||||
|             components.push(ComponentInfo::new(component_id, descriptor)); |  | ||||||
|             component_id |  | ||||||
|         }) |         }) | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     #[inline] | ||||||
|  |     fn register_resource_inner( | ||||||
|  |         components: &mut Vec<ComponentInfo>, | ||||||
|  |         descriptor: ComponentDescriptor, | ||||||
|  |     ) -> ComponentId { | ||||||
|  |         let component_id = ComponentId(components.len()); | ||||||
|  |         components.push(ComponentInfo::new(component_id, descriptor)); | ||||||
|  |         component_id | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     /// Gets an iterator over all components registered with this instance.
 |     /// Gets an iterator over all components registered with this instance.
 | ||||||
|     pub fn iter(&self) -> impl Iterator<Item = &ComponentInfo> + '_ { |     pub fn iter(&self) -> impl Iterator<Item = &ComponentInfo> + '_ { | ||||||
|         self.components.iter() |         self.components.iter() | ||||||
|  | |||||||
| @ -1320,6 +1320,23 @@ impl World { | |||||||
|             .map(Into::into) |             .map(Into::into) | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     /// Registers a new [`Resource`] type and returns the [`ComponentId`] created for it.
 | ||||||
|  |     ///
 | ||||||
|  |     /// This enables the dynamic registration of new [`Resource`] definitions at runtime for
 | ||||||
|  |     /// advanced use cases.
 | ||||||
|  |     ///
 | ||||||
|  |     /// # Note
 | ||||||
|  |     ///
 | ||||||
|  |     /// Registering a [`Resource`] does not insert it into [`World`]. For insertion, you could use
 | ||||||
|  |     /// [`World::insert_resource_by_id`].
 | ||||||
|  |     pub fn register_resource_with_descriptor( | ||||||
|  |         &mut self, | ||||||
|  |         descriptor: ComponentDescriptor, | ||||||
|  |     ) -> ComponentId { | ||||||
|  |         self.components | ||||||
|  |             .register_resource_with_descriptor(descriptor) | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     /// Initializes a new resource and returns the [`ComponentId`] created for it.
 |     /// Initializes a new resource and returns the [`ComponentId`] created for it.
 | ||||||
|     ///
 |     ///
 | ||||||
|     /// If the resource already exists, nothing happens.
 |     /// If the resource already exists, nothing happens.
 | ||||||
| @ -3248,6 +3265,39 @@ mod tests { | |||||||
|         ); |         ); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     #[test] | ||||||
|  |     fn dynamic_resource() { | ||||||
|  |         let mut world = World::new(); | ||||||
|  | 
 | ||||||
|  |         let descriptor = ComponentDescriptor::new_resource::<TestResource>(); | ||||||
|  | 
 | ||||||
|  |         let component_id = world.register_resource_with_descriptor(descriptor); | ||||||
|  | 
 | ||||||
|  |         let value = 0; | ||||||
|  |         OwningPtr::make(value, |ptr| { | ||||||
|  |             // SAFETY: value is valid for the layout of `TestResource`
 | ||||||
|  |             unsafe { | ||||||
|  |                 world.insert_resource_by_id( | ||||||
|  |                     component_id, | ||||||
|  |                     ptr, | ||||||
|  |                     #[cfg(feature = "track_change_detection")] | ||||||
|  |                     panic::Location::caller(), | ||||||
|  |                 ); | ||||||
|  |             } | ||||||
|  |         }); | ||||||
|  | 
 | ||||||
|  |         // SAFETY: We know that the resource is of type `TestResource`
 | ||||||
|  |         let resource = unsafe { | ||||||
|  |             world | ||||||
|  |                 .get_resource_by_id(component_id) | ||||||
|  |                 .unwrap() | ||||||
|  |                 .deref::<TestResource>() | ||||||
|  |         }; | ||||||
|  |         assert_eq!(resource.0, 0); | ||||||
|  | 
 | ||||||
|  |         assert!(world.remove_resource_by_id(component_id).is_some()); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     #[test] |     #[test] | ||||||
|     fn custom_resource_with_layout() { |     fn custom_resource_with_layout() { | ||||||
|         static DROP_COUNT: AtomicU32 = AtomicU32::new(0); |         static DROP_COUNT: AtomicU32 = AtomicU32::new(0); | ||||||
| @ -3268,7 +3318,7 @@ mod tests { | |||||||
|             ) |             ) | ||||||
|         }; |         }; | ||||||
| 
 | 
 | ||||||
|         let component_id = world.register_component_with_descriptor(descriptor); |         let component_id = world.register_resource_with_descriptor(descriptor); | ||||||
| 
 | 
 | ||||||
|         let value: [u8; 8] = [0, 1, 2, 3, 4, 5, 6, 7]; |         let value: [u8; 8] = [0, 1, 2, 3, 4, 5, 6, 7]; | ||||||
|         OwningPtr::make(value, |ptr| { |         OwningPtr::make(value, |ptr| { | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user
	 Antony
						Antony