mirror of
https://github.com/bevyengine/bevy
synced 2024-11-26 06:30:19 +00:00
Add component_id function to World and Components (#5066)
# Objective - Simplify the process of obtaining a `ComponentId` instance corresponding to a `Component`. - Resolves #5060. ## Solution - Add a `component_id::<T: Component>(&self)` function to both `World` and `Components` to retrieve the `ComponentId` associated with `T` from a immutable reference. --- ## Changelog - Added `World::component_id::<C>()` and `Components::component_id::<C>()` to retrieve a `Component`'s corresponding `ComponentId` if it exists.
This commit is contained in:
parent
f8fa229465
commit
fa56a5cd51
2 changed files with 79 additions and 0 deletions
|
@ -214,6 +214,23 @@ impl ComponentInfo {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A semi-opaque value which uniquely identifies the type of a [`Component`] within a
|
||||||
|
/// [`World`](crate::world::World).
|
||||||
|
///
|
||||||
|
/// Each time a new `Component` type is registered within a `World` using
|
||||||
|
/// [`World::init_component`](crate::world::World::init_component) or
|
||||||
|
/// [`World::init_component_with_descriptor`](crate::world::World::init_component_with_descriptor),
|
||||||
|
/// a corresponding `ComponentId` is created to track it.
|
||||||
|
///
|
||||||
|
/// While the distinction between `ComponentId` and [`TypeId`] may seem superficial, breaking them
|
||||||
|
/// into two separate but related concepts allows components to exist outside of Rust's type system.
|
||||||
|
/// Each Rust type registered as a `Component` will have a corresponding `ComponentId`, but additional
|
||||||
|
/// `ComponentId`s may exist in a `World` to track components which cannot be
|
||||||
|
/// represented as Rust types for scripting or other advanced use-cases.
|
||||||
|
///
|
||||||
|
/// A `ComponentId` is tightly coupled to its parent `World`. Attempting to use a `ComponentId` from
|
||||||
|
/// one `World` to access the metadata of a `Component` in a different `World` is undefined behaviour
|
||||||
|
/// and must not be attempted.
|
||||||
#[derive(Debug, Copy, Clone, Hash, Ord, PartialOrd, Eq, PartialEq)]
|
#[derive(Debug, Copy, Clone, Hash, Ord, PartialOrd, Eq, PartialEq)]
|
||||||
pub struct ComponentId(usize);
|
pub struct ComponentId(usize);
|
||||||
|
|
||||||
|
@ -422,11 +439,38 @@ impl Components {
|
||||||
self.components.get_unchecked(id.0)
|
self.components.get_unchecked(id.0)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Type-erased equivalent of [`Components::component_id`].
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn get_id(&self, type_id: TypeId) -> Option<ComponentId> {
|
pub fn get_id(&self, type_id: TypeId) -> Option<ComponentId> {
|
||||||
self.indices.get(&type_id).map(|index| ComponentId(*index))
|
self.indices.get(&type_id).map(|index| ComponentId(*index))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns the [`ComponentId`] of the given [`Component`] type `T`.
|
||||||
|
///
|
||||||
|
/// The returned `ComponentId` is specific to the `Components` instance
|
||||||
|
/// it was retrieved from and should not be used with another `Components`
|
||||||
|
/// instance.
|
||||||
|
///
|
||||||
|
/// Returns [`None`] if the `Component` type has not
|
||||||
|
/// yet been initialized using [`Components::init_component`].
|
||||||
|
///
|
||||||
|
/// ```rust
|
||||||
|
/// use bevy_ecs::prelude::*;
|
||||||
|
///
|
||||||
|
/// let mut world = World::new();
|
||||||
|
///
|
||||||
|
/// #[derive(Component)]
|
||||||
|
/// struct ComponentA;
|
||||||
|
///
|
||||||
|
/// let component_a_id = world.init_component::<ComponentA>();
|
||||||
|
///
|
||||||
|
/// assert_eq!(component_a_id, world.components().component_id::<ComponentA>().unwrap())
|
||||||
|
/// ```
|
||||||
|
#[inline]
|
||||||
|
pub fn component_id<T: Component>(&self) -> Option<ComponentId> {
|
||||||
|
self.get_id(TypeId::of::<T>())
|
||||||
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn get_resource_id(&self, type_id: TypeId) -> Option<ComponentId> {
|
pub fn get_resource_id(&self, type_id: TypeId) -> Option<ComponentId> {
|
||||||
self.resource_indices
|
self.resource_indices
|
||||||
|
|
|
@ -177,10 +177,20 @@ impl World {
|
||||||
WorldCell::new(self)
|
WorldCell::new(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Initializes a new [`Component`] type and returns the [`ComponentId`] created for it.
|
||||||
pub fn init_component<T: Component>(&mut self) -> ComponentId {
|
pub fn init_component<T: Component>(&mut self) -> ComponentId {
|
||||||
self.components.init_component::<T>(&mut self.storages)
|
self.components.init_component::<T>(&mut self.storages)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Initializes a new [`Component`] type and returns the [`ComponentId`] created for it.
|
||||||
|
///
|
||||||
|
/// This method differs from [`World::init_component`] in that it uses a [`ComponentDescriptor`]
|
||||||
|
/// to initialize the new component type instead of statically available type information. This
|
||||||
|
/// enables the dynamic initialization of new component definitions at runtime for advanced use cases.
|
||||||
|
///
|
||||||
|
/// While the option to initialize a component from a descriptor is useful in type-erased
|
||||||
|
/// contexts, the standard `World::init_component` function should always be used instead
|
||||||
|
/// when type information is available at compile time.
|
||||||
pub fn init_component_with_descriptor(
|
pub fn init_component_with_descriptor(
|
||||||
&mut self,
|
&mut self,
|
||||||
descriptor: ComponentDescriptor,
|
descriptor: ComponentDescriptor,
|
||||||
|
@ -189,6 +199,31 @@ impl World {
|
||||||
.init_component_with_descriptor(&mut self.storages, descriptor)
|
.init_component_with_descriptor(&mut self.storages, descriptor)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns the [`ComponentId`] of the given [`Component`] 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 `Component` type has not yet been initialized within
|
||||||
|
/// the `World` using [`World::init_component`].
|
||||||
|
///
|
||||||
|
/// ```rust
|
||||||
|
/// use bevy_ecs::prelude::*;
|
||||||
|
///
|
||||||
|
/// let mut world = World::new();
|
||||||
|
///
|
||||||
|
/// #[derive(Component)]
|
||||||
|
/// struct ComponentA;
|
||||||
|
///
|
||||||
|
/// let component_a_id = world.init_component::<ComponentA>();
|
||||||
|
///
|
||||||
|
/// assert_eq!(component_a_id, world.component_id::<ComponentA>().unwrap())
|
||||||
|
/// ```
|
||||||
|
#[inline]
|
||||||
|
pub fn component_id<T: Component>(&self) -> Option<ComponentId> {
|
||||||
|
self.components.component_id::<T>()
|
||||||
|
}
|
||||||
|
|
||||||
/// Retrieves an [`EntityRef`] that exposes read-only operations for the given `entity`.
|
/// 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
|
/// 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.
|
/// to check for entity existence instead of implicitly panic-ing.
|
||||||
|
|
Loading…
Reference in a new issue