Skip to main content

unlit_ecs/
info.rs

1//! Plain-data summaries of a world's shape.
2//!
3//! A world stores components behind type-erased columns, so a caller that only
4//! has a scope can count entities and archetypes but cannot name a component:
5//! the names live in a side table keyed by [`TypeId`]. These structures put a
6//! name back on every column and borrow nothing from the world, which is what a
7//! bridge that reports a world over JSON needs.
8//!
9//! Every count here is what one scope sees, not what the world holds: a scope of a
10//! scene reports that scene. The two root entities are reported by handle so
11//! that a caller can tell why the count is two higher than the content.
12//!
13//! They are deliberately shallow. Nothing here reaches into a component's own
14//! fields -- that is the caller's business, and a caller that wants it derives
15//! its own reflection.
16//!
17//! [`TypeId`]: core::any::TypeId
18
19use crate::entity::Entity;
20
21/// A live entity's location and component names.
22///
23/// Only a live, visible entity has one: [`Scope::entity_info`] answers
24/// [`EntityAccessError::NotAlive`] or [`EntityAccessError::NotVisible`] for a
25/// handle that is neither, so there is no `alive` field to report.
26///
27/// [`EntityAccessError::NotAlive`]: crate::EntityAccessError::NotAlive
28/// [`EntityAccessError::NotVisible`]: crate::EntityAccessError::NotVisible
29///
30/// [`Scope::entity_info`]: crate::Scope::entity_info
31#[derive(Clone, Debug, PartialEq, Eq)]
32#[cfg_attr(feature = "reflect", derive(facet::Facet))]
33pub struct EntityInfo {
34    /// The entity's handle.
35    #[cfg_attr(feature = "reflect", facet(opaque, proxy = crate::EntityProxy))]
36    pub entity: Entity,
37    /// The entity's name, which its handle carries but its bits do not, so a
38    /// reader of this listing sees the label the entity was spawned with even
39    /// though the handle travels as a bare integer.
40    pub name: &'static str,
41    /// The archetype the entity lives in, as [`Location::archetype`].
42    ///
43    /// [`Location::archetype`]: crate::Location::archetype
44    pub archetype: u32,
45    /// The entity's row in that archetype, as [`Location::row`].
46    ///
47    /// [`Location::row`]: crate::Location::row
48    pub row: usize,
49    /// The entity's scope: the entity it lives in, which is its parent in the
50    /// scope tree.
51    ///
52    /// An entity's scope is deliberately not a component, so it is reported
53    /// here instead: a client reading a listing sees the same relation a
54    /// [`Scope`](crate::Scope) traverses.
55    #[cfg_attr(feature = "reflect", facet(opaque, proxy = crate::EntityProxy))]
56    pub scope: Entity,
57    /// The component names of the entity's archetype, in column order.
58    pub components: Vec<&'static str>,
59}
60
61/// One archetype: its id, how many of its rows a scope sees, and its component
62/// names.
63#[derive(Clone, Debug, PartialEq, Eq)]
64#[cfg_attr(feature = "reflect", derive(facet::Facet))]
65pub struct ArchetypeInfo {
66    /// The archetype id, the value [`EntityInfo::archetype`] carries.
67    pub index: u32,
68    /// The number of rows visible from the scope, not the archetype's total.
69    ///
70    /// This is the only definition under which the lengths sum to
71    /// [`WorldInfo::entities`].
72    pub len: usize,
73    /// Its component names, in column order.
74    pub components: Vec<&'static str>,
75}
76
77/// A scope's high-level shape.
78#[derive(Clone, Debug, PartialEq, Eq)]
79#[cfg_attr(feature = "reflect", derive(facet::Facet))]
80pub struct WorldInfo {
81    /// The number of live entities visible from the scope, the roots included.
82    pub entities: usize,
83    /// The number of archetypes with at least one visible row.
84    pub archetypes: usize,
85    /// The names of the component types this scope can see, sorted.
86    ///
87    /// A type is named here when an archetype holding at least one visible row
88    /// carries it, which is the same rule as [`WorldInfo::archetypes`]: the two
89    /// describe the rows the scope reaches, not the types that ever entered the
90    /// world.
91    pub components: Vec<&'static str>,
92    /// The root entity, which owns everything.
93    #[cfg_attr(feature = "reflect", facet(opaque, proxy = crate::EntityProxy))]
94    pub root: Entity,
95    /// The shared entity, whose subtree every scope sees.
96    #[cfg_attr(feature = "reflect", facet(opaque, proxy = crate::EntityProxy))]
97    pub shared: Entity,
98}