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.
use crate::{
self as bevy_ecs,
change_detection::MAX_CHANGE_AGE,
storage::{SparseSetIndex, Storages},
system::{Local, Resource},
system::{Local, Resource, SystemParam},
world::{FromWorld, World},
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
/// ```rust
/// # use bevy_ecs::{system::Local, component::{Component, ComponentId, ComponentIdFor}};
/// #[derive(Component)]
/// struct Player;
/// fn my_system(component_id: Local<ComponentIdFor<Player>>) {
/// let component_id: ComponentId = component_id.into();
/// fn my_system(component_id: ComponentIdFor<Player>) {
/// let component_id: ComponentId = component_id.get();
/// // ...
/// }
/// ```
pub struct ComponentIdFor<T: Component> {
component_id: ComponentId,
phantom: PhantomData<T>,
}
#[derive(SystemParam)]
pub struct ComponentIdFor<'s, T: Component>(Local<'s, InitComponentId<T>>);
impl<T: Component> FromWorld for ComponentIdFor<T> {
fn from_world(world: &mut World) -> Self {
Self {
component_id: world.init_component::<T>(),
phantom: PhantomData,
}
impl<T: Component> ComponentIdFor<'_, T> {
/// Gets the [`ComponentId`] for the type `T`.
#[inline]
pub fn get(&self) -> ComponentId {
**self
}
}
impl<T: Component> std::ops::Deref for ComponentIdFor<T> {
impl<T: Component> std::ops::Deref for ComponentIdFor<'_, T> {
type Target = ComponentId;
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 {
*to_component_id
}
}
impl<'s, T: Component> From<Local<'s, ComponentIdFor<T>>> for ComponentId {
fn from(to_component_id: Local<ComponentIdFor<T>>) -> ComponentId {
**to_component_id
/// Initializes the [`ComponentId`] for a specific type when used with [`FromWorld`].
struct InitComponentId<T: Component> {
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)]
pub struct RemovedComponents<'w, 's, T: Component> {
component_id: Local<'s, ComponentIdFor<T>>,
component_id: ComponentIdFor<'s, T>,
reader: Local<'s, RemovedComponentReader<T>>,
event_sets: &'w RemovedComponentEvents,
}
@ -180,7 +180,7 @@ impl<'w, 's, T: Component> RemovedComponents<'w, 's, T> {
/// Fetch underlying [`Events`].
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`
@ -195,7 +195,7 @@ impl<'w, 's, T: Component> RemovedComponents<'w, 's, T> {
&Events<RemovedComponentEntity>,
)> {
self.event_sets
.get(**self.component_id)
.get(self.component_id.get())
.map(|events| (&mut *self.reader, events))
}