Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions crates/bevy_ecs/src/name.rs
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,11 @@ impl Name {
pub fn as_str(&self) -> &str {
&self.0 .0
}
/// Get the precomputed hash of this names string, useful for raw entry operations on [`PreHashMap`](bevy_utils::map::PreHashMap)
#[inline(always)]
pub fn pre_hash(&self) -> u64 {
self.0 .0.hash()
}
}

impl core::fmt::Display for Name {
Expand Down Expand Up @@ -283,6 +288,7 @@ mod tests {
use super::*;
use crate::world::World;
use alloc::string::ToString;
use bevy_platform::hash::fixed_hash_one;

#[test]
fn test_display_of_debug_name() {
Expand All @@ -298,6 +304,11 @@ mod tests {
// NameOrEntity Display for entities with a Name should be the Name
assert_eq!(d2.to_string(), "MyName");
}
#[test]
fn test_name_hash_is_fixed() {
let str = "foobar";
assert_eq!(Name::from(str).pre_hash(), fixed_hash_one(str));
}
}

#[cfg(all(test, feature = "serialize"))]
Expand Down
47 changes: 33 additions & 14 deletions crates/bevy_ecs/src/template.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,6 @@

use core::{hash::Hash, ops::Deref};

pub use bevy_ecs_macros::FromTemplate;
use bevy_platform::{collections::hash_map::RawEntryMut, hash::Hashed};
use bevy_utils::PreHashMap;
use indexmap::Equivalent;

use crate::{
component::Mutable,
entity::Entity,
Expand All @@ -15,6 +10,10 @@ use crate::{
world::{EntityWorldMut, Mut, World},
};
use alloc::vec::Vec;
pub use bevy_ecs_macros::FromTemplate;
use bevy_platform::{collections::hash_map::RawEntryMut, hash::Hashed};
use bevy_utils::PreHashMap;
use indexmap::Equivalent;
use variadics_please::all_tuples;

/// A [`Template`] is something that, given a spawn context (target [`Entity`], [`World`], etc), can produce a [`Template::Output`].
Expand Down Expand Up @@ -133,8 +132,12 @@ impl SceneEntityReferences {
/// A unique reference for a named entity in a scene.
/// Usually used by `bevy_scene` in generated code
///
/// Hashed here should allow implementing compile-time hashing in the future, and
/// encourage constant-folding until then
/// Hashed here should allow implementing compile-time hashing in the future
///
/// The uniqueness of this is ensured by the following factors:
/// - macro invocation location: filename, line and column
/// - the `name_id` should uniquely identify a name in the individual macros scope
/// - runtime, per-scope counter for each runtime call (usually from a static `AtomicU64`)
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
pub struct SceneEntityReference(Hashed<InnerSceneEntityReference>);

Expand All @@ -144,26 +147,31 @@ pub struct InnerSceneEntityReference {
file: &'static str,
line: usize,
column: usize,
local: usize,
name_id: usize,
runtime: u64,
}

impl SceneEntityReference {
/// Create a new [`SceneEntityReference`] from the invocation location and a local (per-macro) counter for names
pub fn new((file, line, column): (&'static str, usize, usize), local: usize) -> Self {
/// Create a new [`SceneEntityReference`] from the invocation location, runtime time, and a local (per-macro) counter for names
pub fn new(
(file, line, column): (&'static str, usize, usize),
name_id: usize,
runtime: u64,
) -> Self {
Self(Hashed::new(InnerSceneEntityReference {
file,
line,
column,
local,
name_id,
runtime,
}))
}
}

impl core::fmt::Display for SceneEntityReference {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.write_fmt(format_args!(
"global={}:{}:{} local={}",
self.file, self.line, self.column, self.local
"global={}:{}:{} name_id={} runtime={:?}",
self.file, self.line, self.column, self.name_id, self.runtime
))
}
}
Expand Down Expand Up @@ -420,6 +428,17 @@ pub enum EntityTemplate {
}
impl Unpin for EntityTemplate where for<'a> [()]: SpecializeFromTemplate {}

impl EntityTemplate {
/// Create a [`EntityTemplate::SceneEntityReference`] from the data needed for [`SceneEntityReference`]
pub fn from_reference(
invocation: (&'static str, usize, usize),
name_id: usize,
runtime: u64,
) -> Self {
Self::SceneEntityReference(SceneEntityReference::new(invocation, name_id, runtime))
}
}

impl From<Entity> for EntityTemplate {
fn from(entity: Entity) -> Self {
Self::Entity(entity)
Expand Down
5 changes: 5 additions & 0 deletions crates/bevy_platform/src/hash.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,11 @@ impl BuildHasher for FixedHasher {
}
}

/// Hashes one value with the deterministic [`FixedHasher`].
pub fn fixed_hash_one(x: impl Hash) -> u64 {
FixedHasher.hash_one(x)
}

/// A pre-hashed value of a specific type. Pre-hashing enables memoization of hashes that are expensive to compute.
///
/// It also enables faster [`PartialEq`] comparisons by short circuiting on hash equality.
Expand Down
4 changes: 2 additions & 2 deletions crates/bevy_scene/macros/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,6 @@ proc-macro = true
bevy_macro_utils = { path = "../../bevy_macro_utils", version = "0.19.0-dev" }
bevy_ecs_macro_logic = { path = "../../bevy_ecs/macro_logic", version = "0.19.0-dev" }

syn = { version = "2.0", features = ["full", "extra-traits"] }
proc-macro2 = "1.0"
proc-macro2 = { version = "1.0", features = ["span-locations"] }
quote = "1.0"
syn = { version = "2.0", features = ["full", "extra-traits"] }
Loading
Loading