From 96a9d0405a9e93b4f6779b8fd9e04fbb2aa7a161 Mon Sep 17 00:00:00 2001 From: JoJoJet <21144246+JoJoJet@users.noreply.github.com> Date: Thu, 15 Jun 2023 08:57:47 -0400 Subject: [PATCH] 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` 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>, ) { let component_id = **component_id; } // After: fn my_system( component_id: ComponentIdFor, ) { let component_id = component_id.get(); } ``` --- crates/bevy_ecs/src/component.rs | 48 ++++++++++++++---------- crates/bevy_ecs/src/removal_detection.rs | 6 +-- 2 files changed, 31 insertions(+), 23 deletions(-) diff --git a/crates/bevy_ecs/src/component.rs b/crates/bevy_ecs/src/component.rs index 27917d5fd6..2e5700f2fd 100644 --- a/crates/bevy_ecs/src/component.rs +++ b/crates/bevy_ecs/src/component.rs @@ -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>) { -/// let component_id: ComponentId = component_id.into(); +/// fn my_system(component_id: ComponentIdFor) { +/// let component_id: ComponentId = component_id.get(); /// // ... /// } /// ``` -pub struct ComponentIdFor { - component_id: ComponentId, - phantom: PhantomData, -} +#[derive(SystemParam)] +pub struct ComponentIdFor<'s, T: Component>(Local<'s, InitComponentId>); -impl FromWorld for ComponentIdFor { - fn from_world(world: &mut World) -> Self { - Self { - component_id: world.init_component::(), - phantom: PhantomData, - } +impl ComponentIdFor<'_, T> { + /// Gets the [`ComponentId`] for the type `T`. + #[inline] + pub fn get(&self) -> ComponentId { + **self } } -impl std::ops::Deref for ComponentIdFor { +impl std::ops::Deref for ComponentIdFor<'_, T> { type Target = ComponentId; fn deref(&self) -> &Self::Target { - &self.component_id + &self.0.component_id } } -impl From> for ComponentId { +impl From> for ComponentId { + #[inline] fn from(to_component_id: ComponentIdFor) -> ComponentId { *to_component_id } } -impl<'s, T: Component> From>> for ComponentId { - fn from(to_component_id: Local>) -> ComponentId { - **to_component_id +/// Initializes the [`ComponentId`] for a specific type when used with [`FromWorld`]. +struct InitComponentId { + component_id: ComponentId, + marker: PhantomData, +} + +impl FromWorld for InitComponentId { + fn from_world(world: &mut World) -> Self { + Self { + component_id: world.init_component::(), + marker: PhantomData, + } } } diff --git a/crates/bevy_ecs/src/removal_detection.rs b/crates/bevy_ecs/src/removal_detection.rs index 81146371ad..5546f17eac 100644 --- a/crates/bevy_ecs/src/removal_detection.rs +++ b/crates/bevy_ecs/src/removal_detection.rs @@ -136,7 +136,7 @@ impl RemovedComponentEvents { /// ``` #[derive(SystemParam)] pub struct RemovedComponents<'w, 's, T: Component> { - component_id: Local<'s, ComponentIdFor>, + component_id: ComponentIdFor<'s, T>, reader: Local<'s, RemovedComponentReader>, 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> { - 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, )> { self.event_sets - .get(**self.component_id) + .get(self.component_id.get()) .map(|events| (&mut *self.reader, events)) }