diff --git a/crates/bevy_ecs/src/reflect/component.rs b/crates/bevy_ecs/src/reflect/component.rs index b3422208d1..a735aa7532 100644 --- a/crates/bevy_ecs/src/reflect/component.rs +++ b/crates/bevy_ecs/src/reflect/component.rs @@ -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>, /// 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 FromType for ReflectComponent { let c = unsafe { entity.get_mut::() }; c.map(|c| c.map_unchanged(|value| value as &mut dyn Reflect)) }, + register_component: |world: &mut World| -> ComponentId { + world.register_component::() + }, }) } } diff --git a/crates/bevy_ecs/src/reflect/resource.rs b/crates/bevy_ecs/src/reflect/resource.rs index e55ffb964a..f9da7adc7c 100644 --- a/crates/bevy_ecs/src/reflect/resource.rs +++ b/crates/bevy_ecs/src/reflect/resource.rs @@ -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>, /// 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 FromType for ReflectResource { from_reflect_with_fallback::(source_resource, destination_world, registry); destination_world.insert_resource(destination_resource); }, + + register_resource: |world: &mut World| -> ComponentId { + world.register_resource::() + }, }) } } diff --git a/crates/bevy_ecs/src/world/mod.rs b/crates/bevy_ecs/src/world/mod.rs index 80a05e2a18..3867905685 100644 --- a/crates/bevy_ecs/src/world/mod.rs +++ b/crates/bevy_ecs/src/world/mod.rs @@ -334,6 +334,25 @@ impl World { self.components.component_id::() } + /// 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(&mut self) -> ComponentId { + self.components.register_resource::() + } + + /// 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(&self) -> Option { + self.components.get_resource_id(TypeId::of::()) + } + /// 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.