Simplify the ComponentIdFor type (#8845)

# Objective

`ComponentIdFor` is a type that gives you access to a component's
`ComponentId` in a system. It is currently awkward to use, since it must
be wrapped in a `Local<>` to be used.

## Solution

Make `ComponentIdFor` a proper SystemParam.

---

## Changelog

- Refactored the type `ComponentIdFor` in order to simplify how it is
used.

## Migration Guide

The type `ComponentIdFor<T>` now implements `SystemParam` instead of
`FromWorld` -- this means it should be used as the parameter for a
system directly instead of being used in a `Local`.

```rust
// Before:
fn my_system(
    component_id: Local<ComponentIdFor<MyComponent>>,
) {
    let component_id = **component_id;
}

// After:
fn my_system(
    component_id: ComponentIdFor<MyComponent>,
) {
    let component_id = component_id.get();
}
```
This commit is contained in:
JoJoJet 2023-06-15 08:57:47 -04:00 committed by GitHub
parent 13f50c7a53
commit 96a9d0405a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 31 additions and 23 deletions

View File

@ -1,9 +1,10 @@
//! Types for declaring and storing [`Component`]s. //! Types for declaring and storing [`Component`]s.
use crate::{ use crate::{
self as bevy_ecs,
change_detection::MAX_CHANGE_AGE, change_detection::MAX_CHANGE_AGE,
storage::{SparseSetIndex, Storages}, storage::{SparseSetIndex, Storages},
system::{Local, Resource}, system::{Local, Resource, SystemParam},
world::{FromWorld, World}, world::{FromWorld, World},
TypeIdMap, TypeIdMap,
}; };
@ -795,47 +796,54 @@ impl ComponentTicks {
} }
} }
/// Initialize and fetch a [`ComponentId`] for a specific type. /// A [`SystemParam`] that provides access to the [`ComponentId`] for a specific type.
/// ///
/// # Example /// # Example
/// ```rust /// ```rust
/// # use bevy_ecs::{system::Local, component::{Component, ComponentId, ComponentIdFor}}; /// # use bevy_ecs::{system::Local, component::{Component, ComponentId, ComponentIdFor}};
/// #[derive(Component)] /// #[derive(Component)]
/// struct Player; /// struct Player;
/// fn my_system(component_id: Local<ComponentIdFor<Player>>) { /// fn my_system(component_id: ComponentIdFor<Player>) {
/// let component_id: ComponentId = component_id.into(); /// let component_id: ComponentId = component_id.get();
/// // ... /// // ...
/// } /// }
/// ``` /// ```
pub struct ComponentIdFor<T: Component> { #[derive(SystemParam)]
component_id: ComponentId, pub struct ComponentIdFor<'s, T: Component>(Local<'s, InitComponentId<T>>);
phantom: PhantomData<T>,
}
impl<T: Component> FromWorld for ComponentIdFor<T> { impl<T: Component> ComponentIdFor<'_, T> {
fn from_world(world: &mut World) -> Self { /// Gets the [`ComponentId`] for the type `T`.
Self { #[inline]
component_id: world.init_component::<T>(), pub fn get(&self) -> ComponentId {
phantom: PhantomData, **self
}
} }
} }
impl<T: Component> std::ops::Deref for ComponentIdFor<T> { impl<T: Component> std::ops::Deref for ComponentIdFor<'_, T> {
type Target = ComponentId; type Target = ComponentId;
fn deref(&self) -> &Self::Target { fn deref(&self) -> &Self::Target {
&self.component_id &self.0.component_id
} }
} }
impl<T: Component> From<ComponentIdFor<T>> for ComponentId { impl<T: Component> From<ComponentIdFor<'_, T>> for ComponentId {
#[inline]
fn from(to_component_id: ComponentIdFor<T>) -> ComponentId { fn from(to_component_id: ComponentIdFor<T>) -> ComponentId {
*to_component_id *to_component_id
} }
} }
impl<'s, T: Component> From<Local<'s, ComponentIdFor<T>>> for ComponentId { /// Initializes the [`ComponentId`] for a specific type when used with [`FromWorld`].
fn from(to_component_id: Local<ComponentIdFor<T>>) -> ComponentId { struct InitComponentId<T: Component> {
**to_component_id component_id: ComponentId,
marker: PhantomData<T>,
}
impl<T: Component> FromWorld for InitComponentId<T> {
fn from_world(world: &mut World) -> Self {
Self {
component_id: world.init_component::<T>(),
marker: PhantomData,
}
} }
} }

View File

@ -136,7 +136,7 @@ impl RemovedComponentEvents {
/// ``` /// ```
#[derive(SystemParam)] #[derive(SystemParam)]
pub struct RemovedComponents<'w, 's, T: Component> { pub struct RemovedComponents<'w, 's, T: Component> {
component_id: Local<'s, ComponentIdFor<T>>, component_id: ComponentIdFor<'s, T>,
reader: Local<'s, RemovedComponentReader<T>>, reader: Local<'s, RemovedComponentReader<T>>,
event_sets: &'w RemovedComponentEvents, event_sets: &'w RemovedComponentEvents,
} }
@ -180,7 +180,7 @@ impl<'w, 's, T: Component> RemovedComponents<'w, 's, T> {
/// Fetch underlying [`Events`]. /// Fetch underlying [`Events`].
pub fn events(&self) -> Option<&Events<RemovedComponentEntity>> { pub fn events(&self) -> Option<&Events<RemovedComponentEntity>> {
self.event_sets.get(**self.component_id) self.event_sets.get(self.component_id.get())
} }
/// Destructures to get a mutable reference to the `ManualEventReader` /// Destructures to get a mutable reference to the `ManualEventReader`
@ -195,7 +195,7 @@ impl<'w, 's, T: Component> RemovedComponents<'w, 's, T> {
&Events<RemovedComponentEntity>, &Events<RemovedComponentEntity>,
)> { )> {
self.event_sets self.event_sets
.get(**self.component_id) .get(self.component_id.get())
.map(|events| (&mut *self.reader, events)) .map(|events| (&mut *self.reader, events))
} }