diff --git a/crates/bevy_ecs/src/entity/mod.rs b/crates/bevy_ecs/src/entity/mod.rs index be142a594cd1d..8ab45b5045d62 100644 --- a/crates/bevy_ecs/src/entity/mod.rs +++ b/crates/bevy_ecs/src/entity/mod.rs @@ -30,8 +30,11 @@ pub use map_entities::*; use crate::{archetype::ArchetypeId, storage::SparseSetIndex}; use std::{ + cmp::{Ordering as CmpOrdering, PartialEq}, convert::TryFrom, - fmt, mem, + fmt, + hash::{Hash, Hasher}, + mem, sync::atomic::{AtomicI64, Ordering}, }; @@ -44,9 +47,15 @@ use std::{ /// `Entity` can be a part of a query, e.g. `Query<(Entity, &MyComponent)>`. /// Components of a specific entity can be accessed using /// [`Query::get`](crate::system::Query::get) and related methods. -#[derive(Clone, Copy, Hash, Eq, Ord, PartialEq, PartialOrd)] +#[derive(Clone, Copy)] +#[repr(C, align(8))] pub struct Entity { + // Do not reorder the fields here. The ordering is explicitly used by repr(C) + // to make this struct equivalent to a u64. + #[cfg(target_endian = "little")] + pub(crate) id: u32, pub(crate) generation: u32, + #[cfg(target_endian = "big")] pub(crate) id: u32, } @@ -114,6 +123,7 @@ impl Entity { /// for serialization between runs. /// /// No particular structure is guaranteed for the returned bits. + #[inline(always)] pub fn to_bits(self) -> u64 { u64::from(self.generation) << 32 | u64::from(self.id) } @@ -147,6 +157,38 @@ impl Entity { } } +// Required for ordering correctness. Cannot be done with a derive macro. +impl PartialOrd for Entity { + #[inline] + fn partial_cmp(&self, other: &Self) -> Option { + Some(self.to_bits().cmp(&other.to_bits())) + } +} + +// Required for ordering correctness. Cannot be done with a derive macro. +impl Ord for Entity { + #[inline] + fn cmp(&self, other: &Self) -> CmpOrdering { + self.to_bits().cmp(&other.to_bits()) + } +} + +impl Hash for Entity { + #[inline] + fn hash(&self, hasher: &mut H) { + self.to_bits().hash(hasher) + } +} + +impl PartialEq for Entity { + #[inline] + fn eq(&self, other: &Self) -> bool { + self.to_bits() == other.to_bits() + } +} + +impl Eq for Entity {} + impl fmt::Debug for Entity { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "{}v{}", self.id, self.generation)