From 2f57443b0ec19a0628da808eb0ac032d732af5e1 Mon Sep 17 00:00:00 2001 From: Victoron <59878206+Victoronz@users.noreply.github.com> Date: Fri, 20 Dec 2024 19:55:47 +0100 Subject: [PATCH] impl EntityBorrow for more types --- crates/bevy_ecs/src/world/entity_ref.rs | 259 +++++++++++++++++- .../bevy_ecs/src/world/unsafe_world_cell.rs | 6 +- crates/bevy_render/src/sync_world.rs | 21 +- crates/bevy_window/src/window.rs | 7 +- 4 files changed, 283 insertions(+), 10 deletions(-) diff --git a/crates/bevy_ecs/src/world/entity_ref.rs b/crates/bevy_ecs/src/world/entity_ref.rs index 64dd16149a0ca..13a1a55e6bb0e 100644 --- a/crates/bevy_ecs/src/world/entity_ref.rs +++ b/crates/bevy_ecs/src/world/entity_ref.rs @@ -3,7 +3,9 @@ use crate::{ bundle::{Bundle, BundleId, BundleInfo, BundleInserter, DynamicBundle, InsertMode}, change_detection::MutUntyped, component::{Component, ComponentId, ComponentTicks, Components, Mutable, StorageType}, - entity::{Entities, Entity, EntityCloneBuilder, EntityLocation}, + entity::{ + Entities, Entity, EntityBorrow, EntityCloneBuilder, EntityLocation, TrustedEntityBorrow, + }, event::Event, observer::Observer, query::{Access, ReadOnlyQueryData}, @@ -17,7 +19,14 @@ use bevy_ptr::{OwningPtr, Ptr}; use bevy_utils::{HashMap, HashSet}; #[cfg(feature = "track_change_detection")] use core::panic::Location; -use core::{any::TypeId, marker::PhantomData, mem::MaybeUninit}; +use core::{ + any::TypeId, + borrow::Borrow, + cmp::Ordering, + hash::{Hash, Hasher}, + marker::PhantomData, + mem::MaybeUninit, +}; use thiserror::Error; use super::{unsafe_world_cell::UnsafeEntityCell, Ref, ON_REMOVE, ON_REPLACE}; @@ -369,6 +378,47 @@ impl<'a> TryFrom<&'a FilteredEntityMut<'_>> for EntityRef<'a> { } } +impl PartialEq for EntityRef<'_> { + fn eq(&self, other: &Self) -> bool { + self.entity() == other.entity() + } +} + +impl Eq for EntityRef<'_> {} + +impl PartialOrd for EntityRef<'_> { + fn partial_cmp(&self, other: &Self) -> Option { + self.entity().partial_cmp(&other.entity()) + } +} + +impl Ord for EntityRef<'_> { + fn cmp(&self, other: &Self) -> Ordering { + self.entity().cmp(&other.entity()) + } +} + +impl Hash for EntityRef<'_> { + fn hash(&self, state: &mut H) { + self.entity().hash(state); + } +} + +impl Borrow for EntityRef<'_> { + fn borrow(&self) -> &Entity { + &self.0.entity + } +} + +impl EntityBorrow for EntityRef<'_> { + fn entity(&self) -> Entity { + self.id() + } +} + +// SAFETY: This type represents one Entity. We implement the comparison traits based on that Entity. +unsafe impl TrustedEntityBorrow for EntityRef<'_> {} + /// Provides mutable access to a single entity and all of its components. /// /// Contrast with [`EntityWorldMut`], which allows adding and removing components, @@ -869,6 +919,47 @@ impl<'a> TryFrom<&'a mut FilteredEntityMut<'_>> for EntityMut<'a> { } } +impl PartialEq for EntityMut<'_> { + fn eq(&self, other: &Self) -> bool { + self.entity() == other.entity() + } +} + +impl Eq for EntityMut<'_> {} + +impl PartialOrd for EntityMut<'_> { + fn partial_cmp(&self, other: &Self) -> Option { + self.entity().partial_cmp(&other.entity()) + } +} + +impl Ord for EntityMut<'_> { + fn cmp(&self, other: &Self) -> Ordering { + self.entity().cmp(&other.entity()) + } +} + +impl Hash for EntityMut<'_> { + fn hash(&self, state: &mut H) { + self.entity().hash(state); + } +} + +impl Borrow for EntityMut<'_> { + fn borrow(&self) -> &Entity { + &self.0.entity + } +} + +impl EntityBorrow for EntityMut<'_> { + fn entity(&self) -> Entity { + self.id() + } +} + +// SAFETY: This type represents one Entity. We implement the comparison traits based on that Entity. +unsafe impl TrustedEntityBorrow for EntityMut<'_> {} + /// A mutable reference to a particular [`Entity`], and the entire world. /// /// This is essentially a performance-optimized `(Entity, &mut World)` tuple, @@ -2969,6 +3060,47 @@ impl<'a> From<&'a EntityWorldMut<'_>> for FilteredEntityRef<'a> { } } +impl PartialEq for FilteredEntityRef<'_> { + fn eq(&self, other: &Self) -> bool { + self.entity() == other.entity() + } +} + +impl Eq for FilteredEntityRef<'_> {} + +impl PartialOrd for FilteredEntityRef<'_> { + fn partial_cmp(&self, other: &Self) -> Option { + self.entity().partial_cmp(&other.entity()) + } +} + +impl Ord for FilteredEntityRef<'_> { + fn cmp(&self, other: &Self) -> Ordering { + self.entity().cmp(&other.entity()) + } +} + +impl Hash for FilteredEntityRef<'_> { + fn hash(&self, state: &mut H) { + self.entity().hash(state); + } +} + +impl Borrow for FilteredEntityRef<'_> { + fn borrow(&self) -> &Entity { + &self.entity.entity + } +} + +impl EntityBorrow for FilteredEntityRef<'_> { + fn entity(&self) -> Entity { + self.id() + } +} + +// SAFETY: This type represents one Entity. We implement the comparison traits based on that Entity. +unsafe impl TrustedEntityBorrow for FilteredEntityRef<'_> {} + /// Provides mutable access to a single entity and some of its components defined by the contained [`Access`]. /// /// To define the access when used as a [`QueryData`](crate::query::QueryData), @@ -3258,6 +3390,47 @@ impl<'a> From<&'a mut EntityWorldMut<'_>> for FilteredEntityMut<'a> { } } +impl PartialEq for FilteredEntityMut<'_> { + fn eq(&self, other: &Self) -> bool { + self.entity() == other.entity() + } +} + +impl Eq for FilteredEntityMut<'_> {} + +impl PartialOrd for FilteredEntityMut<'_> { + fn partial_cmp(&self, other: &Self) -> Option { + self.entity().partial_cmp(&other.entity()) + } +} + +impl Ord for FilteredEntityMut<'_> { + fn cmp(&self, other: &Self) -> Ordering { + self.entity().cmp(&other.entity()) + } +} + +impl Hash for FilteredEntityMut<'_> { + fn hash(&self, state: &mut H) { + self.entity().hash(state); + } +} + +impl Borrow for FilteredEntityMut<'_> { + fn borrow(&self) -> &Entity { + &self.entity.entity + } +} + +impl EntityBorrow for FilteredEntityMut<'_> { + fn entity(&self) -> Entity { + self.id() + } +} + +// SAFETY: This type represents one Entity. We implement the comparison traits based on that Entity. +unsafe impl TrustedEntityBorrow for FilteredEntityMut<'_> {} + /// Error type returned by [`TryFrom`] conversions from filtered entity types /// ([`FilteredEntityRef`]/[`FilteredEntityMut`]) to full-access entity types /// ([`EntityRef`]/[`EntityMut`]). @@ -3361,6 +3534,47 @@ where } } +impl PartialEq for EntityRefExcept<'_, B> { + fn eq(&self, other: &Self) -> bool { + self.entity() == other.entity() + } +} + +impl Eq for EntityRefExcept<'_, B> {} + +impl PartialOrd for EntityRefExcept<'_, B> { + fn partial_cmp(&self, other: &Self) -> Option { + self.entity().partial_cmp(&other.entity()) + } +} + +impl Ord for EntityRefExcept<'_, B> { + fn cmp(&self, other: &Self) -> Ordering { + self.entity().cmp(&other.entity()) + } +} + +impl Hash for EntityRefExcept<'_, B> { + fn hash(&self, state: &mut H) { + self.entity().hash(state); + } +} + +impl Borrow for EntityRefExcept<'_, B> { + fn borrow(&self) -> &Entity { + &self.entity.entity + } +} + +impl EntityBorrow for EntityRefExcept<'_, B> { + fn entity(&self) -> Entity { + self.id() + } +} + +// SAFETY: This type represents one Entity. We implement the comparison traits based on that Entity. +unsafe impl TrustedEntityBorrow for EntityRefExcept<'_, B> {} + /// Provides mutable access to all components of an entity, with the exception /// of an explicit set. /// @@ -3464,6 +3678,47 @@ where } } +impl PartialEq for EntityMutExcept<'_, B> { + fn eq(&self, other: &Self) -> bool { + self.entity() == other.entity() + } +} + +impl Eq for EntityMutExcept<'_, B> {} + +impl PartialOrd for EntityMutExcept<'_, B> { + fn partial_cmp(&self, other: &Self) -> Option { + self.entity().partial_cmp(&other.entity()) + } +} + +impl Ord for EntityMutExcept<'_, B> { + fn cmp(&self, other: &Self) -> Ordering { + self.entity().cmp(&other.entity()) + } +} + +impl Hash for EntityMutExcept<'_, B> { + fn hash(&self, state: &mut H) { + self.entity().hash(state); + } +} + +impl Borrow for EntityMutExcept<'_, B> { + fn borrow(&self) -> &Entity { + &self.entity.entity + } +} + +impl EntityBorrow for EntityMutExcept<'_, B> { + fn entity(&self) -> Entity { + self.id() + } +} + +// SAFETY: This type represents one Entity. We implement the comparison traits based on that Entity. +unsafe impl TrustedEntityBorrow for EntityMutExcept<'_, B> {} + fn bundle_contains_component(components: &Components, query_id: ComponentId) -> bool where B: Bundle, diff --git a/crates/bevy_ecs/src/world/unsafe_world_cell.rs b/crates/bevy_ecs/src/world/unsafe_world_cell.rs index 82593961c51c8..aa106f52ff558 100644 --- a/crates/bevy_ecs/src/world/unsafe_world_cell.rs +++ b/crates/bevy_ecs/src/world/unsafe_world_cell.rs @@ -650,9 +650,9 @@ impl Debug for UnsafeWorldCell<'_> { /// A interior-mutable reference to a particular [`Entity`] and all of its components #[derive(Copy, Clone)] pub struct UnsafeEntityCell<'w> { - world: UnsafeWorldCell<'w>, - entity: Entity, - location: EntityLocation, + pub(crate) world: UnsafeWorldCell<'w>, + pub(crate) entity: Entity, + pub(crate) location: EntityLocation, } impl<'w> UnsafeEntityCell<'w> { diff --git a/crates/bevy_render/src/sync_world.rs b/crates/bevy_render/src/sync_world.rs index b3948c5c513ca..8229daa82e8ea 100644 --- a/crates/bevy_render/src/sync_world.rs +++ b/crates/bevy_render/src/sync_world.rs @@ -3,7 +3,7 @@ use bevy_derive::{Deref, DerefMut}; use bevy_ecs::entity::EntityHash; use bevy_ecs::{ component::Component, - entity::Entity, + entity::{Entity, EntityBorrow, TrustedEntityBorrow}, observer::Trigger, query::With, reflect::ReflectComponent, @@ -140,6 +140,16 @@ impl From for RenderEntity { } } +impl EntityBorrow for RenderEntity { + fn entity(&self) -> Entity { + self.id() + } +} + + +// SAFETY: RenderEntity is a newtype around Entity that derives its comparison traits. +unsafe impl TrustedEntityBorrow for RenderEntity {} + /// Component added on the render world entities to keep track of the corresponding main world entity. /// /// Can also be used as a newtype wrapper for main world entities. @@ -158,6 +168,15 @@ impl From for MainEntity { } } +impl EntityBorrow for MainEntity { + fn entity(&self) -> Entity { + self.id() + } +} + +// SAFETY: RenderEntity is a newtype around Entity that derives its comparison traits. +unsafe impl TrustedEntityBorrow for MainEntity {} + /// A [`HashMap`](hashbrown::HashMap) pre-configured to use [`EntityHash`] hashing with a [`MainEntity`]. pub type MainEntityHashMap = hashbrown::HashMap; diff --git a/crates/bevy_window/src/window.rs b/crates/bevy_window/src/window.rs index 97e4cf3c3ea19..49bd325e600d5 100644 --- a/crates/bevy_window/src/window.rs +++ b/crates/bevy_window/src/window.rs @@ -1,7 +1,7 @@ use core::num::NonZero; use bevy_ecs::{ - entity::{Entity, VisitEntities, VisitEntitiesMut}, + entity::{Entity, EntityBorrow, VisitEntities, VisitEntitiesMut}, prelude::{Component, ReflectComponent}, }; use bevy_math::{CompassOctant, DVec2, IVec2, UVec2, Vec2}; @@ -88,9 +88,8 @@ impl VisitEntitiesMut for WindowRef { )] pub struct NormalizedWindowRef(Entity); -impl NormalizedWindowRef { - /// Fetch the entity of this window reference - pub fn entity(&self) -> Entity { +impl EntityBorrow for NormalizedWindowRef { + fn entity(&self) -> Entity { self.0 } }