use super::World;
use std::any::TypeId;
#[derive(Debug, Clone)]
pub struct ComponentSummary {
pub type_id: TypeId,
pub name: &'static str,
pub item_size: usize,
pub count: usize,
pub bytes: usize,
}
impl ComponentSummary {
pub fn short_name(&self) -> &str {
short_type_name(self.name)
}
}
#[derive(Debug, Clone)]
pub struct ArchetypeSummary {
pub id: u32,
pub entity_count: usize,
pub bytes: usize,
pub components: Vec<ComponentSummary>,
}
#[derive(Debug, Clone, Default, PartialEq)]
pub struct WorldStats {
pub entities: usize,
pub archetypes: usize,
pub non_empty_archetypes: usize,
pub registered_components: usize,
pub sparse_set_components: usize,
pub resources: usize,
pub component_bytes: usize,
pub tick: u32,
}
pub fn short_type_name(full: &str) -> &str {
let head_end = full.find('<').unwrap_or(full.len());
let head = &full[..head_end];
match head.rfind("::") {
Some(pos) => &full[pos + 2..],
None => full,
}
}
impl World {
#[inline]
pub fn stored_entity_count(&self) -> usize {
self.archetype_index
.archetypes
.iter()
.map(|a| a.len())
.sum()
}
#[inline]
pub fn archetype_count(&self) -> usize {
self.archetype_index.archetypes.len()
}
#[inline]
pub fn resource_count(&self) -> usize {
self.resources.len()
}
#[inline]
pub fn component_type_name(&self, type_id: TypeId) -> Option<&'static str> {
self.component_infos.get(&type_id).map(|i| i.type_name)
}
pub fn world_stats(&self) -> WorldStats {
let mut entities = 0usize;
let mut non_empty = 0usize;
let mut component_bytes = 0usize;
for arch in &self.archetype_index.archetypes {
let n = arch.len();
if n == 0 {
continue;
}
non_empty += 1;
entities += n;
for type_id in arch.component_types() {
if let Some(info) = self.component_infos.get(&type_id) {
component_bytes += info.layout.size() * n;
}
}
}
WorldStats {
entities,
archetypes: self.archetype_index.archetypes.len(),
non_empty_archetypes: non_empty,
registered_components: self.component_infos.len(),
sparse_set_components: self.sparse_sets.len(),
resources: self.resources.len(),
component_bytes,
tick: self.tick,
}
}
pub fn archetype_summaries(&self) -> Vec<ArchetypeSummary> {
let mut out = Vec::new();
for arch in &self.archetype_index.archetypes {
let n = arch.len();
if n == 0 {
continue;
}
let mut components = Vec::new();
let mut arch_bytes = 0usize;
for type_id in arch.component_types() {
let (name, item_size) = match self.component_infos.get(&type_id) {
Some(info) => (info.type_name, info.layout.size()),
None => ("<unregistered>", 0),
};
let bytes = item_size * n;
arch_bytes += bytes;
components.push(ComponentSummary {
type_id,
name,
item_size,
count: n,
bytes,
});
}
components.sort_by(|a, b| b.bytes.cmp(&a.bytes).then_with(|| a.name.cmp(b.name)));
out.push(ArchetypeSummary {
id: arch.id,
entity_count: n,
bytes: arch_bytes,
components,
});
}
out.sort_by(|a, b| b.entity_count.cmp(&a.entity_count).then(a.id.cmp(&b.id)));
out
}
}
#[cfg(test)]
mod tests {
use crate::world::World;
#[derive(Clone)]
struct Position {
_x: f32,
_y: f32,
_z: f32,
}
#[derive(Clone)]
struct Velocity {
_v: [f32; 3],
}
impl crate::component::Component for Position {}
impl crate::component::Component for Velocity {}
#[test]
fn introspection_reports_entities_archetypes_and_names() {
let mut world = World::new();
let a = world.spawn();
world.add_component(a, Position { _x: 0.0, _y: 0.0, _z: 0.0 });
let b = world.spawn();
world.add_component(b, Position { _x: 1.0, _y: 0.0, _z: 0.0 });
world.add_component(b, Velocity { _v: [0.0; 3] });
let stats = world.world_stats();
assert_eq!(stats.entities, 2);
assert!(stats.registered_components >= 2);
assert!(stats.component_bytes >= std::mem::size_of::<Position>() * 2);
let summaries = world.archetype_summaries();
assert_eq!(summaries.len(), 2);
let has_position = summaries.iter().any(|s| {
s.components
.iter()
.any(|c| c.short_name() == "Position" && c.item_size == std::mem::size_of::<Position>())
});
assert!(has_position, "Position component adı/boyutu çözülemedi");
let total: usize = summaries.iter().map(|s| s.entity_count).sum();
assert_eq!(total, 2);
}
#[test]
fn short_type_name_strips_path_keeps_generics_tail() {
use super::short_type_name;
assert_eq!(short_type_name("gizmo_physics_core::Transform"), "Transform");
assert_eq!(short_type_name("Foo"), "Foo");
}
}