diff --git a/flecs_ecs/src/core/entity_view/entity_view_const.rs b/flecs_ecs/src/core/entity_view/entity_view_const.rs index 33fd21ba..970ed10a 100644 --- a/flecs_ecs/src/core/entity_view/entity_view_const.rs +++ b/flecs_ecs/src/core/entity_view/entity_view_const.rs @@ -31,18 +31,18 @@ impl<'a> DerefMut for EntityView<'a> { } } -impl<'a> std::fmt::Display for EntityView<'a> { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { +impl<'a> core::fmt::Display for EntityView<'a> { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { if let Some(name) = self.get_name() { - write!(f, "{}", name) + write!(f, "#{} | {}", self.id, name) } else { - write!(f, "{}", *self.id) + write!(f, "#{}", self.id) } } } -impl<'a> std::fmt::Debug for EntityView<'a> { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { +impl<'a> core::fmt::Debug for EntityView<'a> { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { let entity_display = match self.get_name() { Some(name_str) => format!("Entity: #{} | \"{}\"", self.id, name_str), None => format!("Entity: #{}", self.id), @@ -58,6 +58,16 @@ impl<'a> std::fmt::Debug for EntityView<'a> { } }); }); + + if children.is_empty() { + return write!( + f, + "\n {}\n Archetype:\n - {}\n", + entity_display, + archetype_types_str.join("\n - "), + ); + } + write!( f, "\n {}\n Archetype:\n - {}\n Children:\n - {}\n", diff --git a/flecs_ecs/src/core/entity_view/macros.rs b/flecs_ecs/src/core/entity_view/macros.rs new file mode 100644 index 00000000..a1dbfd17 --- /dev/null +++ b/flecs_ecs/src/core/entity_view/macros.rs @@ -0,0 +1,74 @@ +/// A macro to generate a newtype wrapper for `EntityView` with various utility implementations. +/// +/// This macro creates a new struct with the specified name that wraps around `EntityView<'a>`. +/// It also provides implementations for common traits like `Deref`, `DerefMut`, `From`, `Debug` and `Display` +/// to make working with the new type seamless. +/// +/// # Parameters +/// - `$name`: The name of the new struct that wraps `EntityView<'a>`. +/// +/// # Generated Code +/// +/// - A struct named `$name` is created, wrapping an `EntityView<'a>`. +/// - A constructor `new` that takes an `EntityView<'a>` is generated for the newtype. +/// - Implements `Deref` and `DerefMut` traits to allow easy access to the underlying `EntityView<'a>`. +/// - Implements `From` for both conversions between `EntityView<'a>` and the new type, and between the new type and `Entity`. +/// - Provides `Debug` and `Display` implementations for better formatting support. +#[macro_export] +macro_rules! newtype_of_entity_view { + ($name:ident) => { + #[derive(Clone, Copy)] + pub struct $name<'a>(pub EntityView<'a>); + + impl<'a> $name<'a> { + pub fn new(entity: EntityView<'a>) -> Self { + Self(entity) + } + } + + impl<'a> core::ops::Deref for $name<'a> { + type Target = EntityView<'a>; + + fn deref(&self) -> &Self::Target { + &self.0 + } + } + + impl<'a> core::ops::DerefMut for $name<'a> { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.0 + } + } + + impl<'a> From> for $name<'a> { + fn from(entity: EntityView<'a>) -> Self { + Self::new(entity) + } + } + + impl<'a> From<$name<'a>> for EntityView<'a> { + fn from(entity: $name<'a>) -> Self { + entity.0 + } + } + + impl From<$name<'_>> for Entity { + #[inline] + fn from(name: $name) -> Self { + name.0.id() + } + } + + impl<'a> core::fmt::Debug for $name<'a> { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + write!(f, "{:?}", self.0) + } + } + + impl<'a> core::fmt::Display for $name<'a> { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + write!(f, "{}", self.0) + } + } + }; +} diff --git a/flecs_ecs/src/core/entity_view/mod.rs b/flecs_ecs/src/core/entity_view/mod.rs index 6fe3dd30..beae789d 100644 --- a/flecs_ecs/src/core/entity_view/mod.rs +++ b/flecs_ecs/src/core/entity_view/mod.rs @@ -4,6 +4,7 @@ mod bulk_entity_builder; mod entity_view_const; mod entity_view_impl; mod entity_view_mut; +mod macros; pub use entity_view_const::EntityView; pub use entity_view_const::EntityViewGet; diff --git a/flecs_ecs/src/core/utility/functions.rs b/flecs_ecs/src/core/utility/functions.rs index 3d4ba50e..c44403bf 100644 --- a/flecs_ecs/src/core/utility/functions.rs +++ b/flecs_ecs/src/core/utility/functions.rs @@ -518,7 +518,9 @@ pub(crate) fn has_default_hook(world: *const sys::ecs_world_t, id: u64) -> bool pub fn debug_separate_archetype_types_into_strings(archetype: &Archetype) -> Vec { let mut result = Vec::with_capacity(archetype.count()); let mut skip_next = false; // To skip the next part after joining - let archetype_str = archetype.to_string().unwrap_or_else(|| "empty".to_string()); + let archetype_str = archetype + .to_string() + .unwrap_or_else(|| "empty entity | no components".to_string()); let parts: Vec<&str> = archetype_str.split(',').map(|s| s.trim()).collect();