Expand description
The renderer-free half of the engine’s ECS: the storage mechanism, the per-tick context systems see, and the asset identity + registry layer the build / validate pipeline and the client runtime share.
The storage mechanism is closed-world and carries no engine domain type. It
provides the generic primitives only: entities (Entity, Entities),
typed storage columns (Column), change ticks (Tick), component masks
(ComponentMask) and a join index (JoinIndex), resources
(Resources), events (Events), and the per-system access sets
(Access) the scheduler uses to run two systems concurrently. Nothing in
that half knows about meshes, blobs, or rendering, and none of it stores a
type the project did not register at compile time: there is no TypeId-keyed
type erasure and no open-world insert of arbitrary external types.
The concrete component set is registered in registry and expanded by
define_components!, which pairs the asset-enum
dispatch with the storage half from
define_component_storage!.
On top of that sit the pieces the engine reaches for: the Component
metadata trait, the plain data types the registry and blob format are built
from (AssetOrigin, AssetPayload, PayloadLocator,
BlobAssetDef, AssetKind), the System behavior trait, and the
World: the components, resources, events, payloads, profile, and frame
scratch a tick reads and writes, plus the systems that run over them and
their schedule. The system table itself (SystemTable) names a host’s own
system types, so it is written in the client crate, whose ecs module
re-exports everything here under the historical crate::ecs::* paths
alongside the ComponentAsset value enum.
The interner that assigns asset identities keeps a per-thread table and
lives in concinnity-host. The authoring Registration record lives in
concinnity-cook, constructed from the trait’s metadata consts.
Re-exports§
pub use crate::memory::Arena;pub use locator::PayloadLocator;pub use handle::AudioClipHandle;pub use handle::ColorLutHandle;pub use handle::CubemapTextureHandle;pub use handle::EnvironmentMapHandle;pub use handle::FontHandle;pub use handle::MaterialHandle;pub use handle::MeshHandle;pub use handle::ShaderHandle;pub use handle::SkinnedMeshHandle;pub use handle::TextureHandle;pub use handle::de_audio_clip_handle_vec;pub use handle::de_opt_audio_clip_handle;pub use handle::de_opt_font_handle;pub use handle::de_opt_material_handle;pub use handle::de_opt_mesh_handle;pub use handle::de_opt_shader_handle;pub use handle::de_opt_skinned_mesh_handle;pub use handle::de_opt_texture_handle;pub use handle::de_texture_handle;pub use resolver::set_audio_clip_handle_resolver;pub use resolver::set_font_handle_resolver;pub use resolver::set_material_handle_resolver;pub use resolver::set_mesh_handle_resolver;pub use resolver::set_shader_handle_resolver;pub use resolver::set_skinned_mesh_handle_resolver;pub use resolver::set_texture_handle_resolver;pub use crate::blob::AssetKind;pub use crate::blob::BlobAssetDef;pub use crate::blob::BlobMeta;pub use crate::blob::MeshBoundsRecord;pub use crate::blob::PhysicsBudgetRecord;pub use crate::blob::ResourceKind;pub use crate::blob::ResourceRecord;pub use crate::blob::SceneGroup;
Modules§
- access_
check - Debug-build access validation hooks.
PipelineContextaccessors report each touch here; the client installs a hook that asserts the touch against the stepping system’s declaredAccess(tracked client-side, since this crate is no_std and holds no per-thread state).World::stepannounces which system is stepping through the second hook, for the same reason: the tracking is per-thread and belongs to the host. Compiled out of release builds entirely: release parallel-safety never rests on these checks, only on the executor handing conflicting systems to different waves. - asset_
id - Asset identity: names declared in world.jsonl are interned to an
AssetIdin declaration order, and the blob and the runtime carry only the integer, so every cross-reference lookup is an integer compare. - asset_
ref - A typed reference from one asset to another, declared by name.
- handle
- Per-kind resource handles.
- locator
- Where an asset’s compiled payload lives in the data blob.
- resolver
- Name -> id resolution seam.
Structs§
- Access
- A system’s declared data access.
- Atomic
Tick - The change-tick counter shared across a storage’s columns, atomic so writers
of disjoint columns can stamp edits concurrently without sharing
&mut. Relaxed ordering: the counter only supplies monotonic values; the column data it stamps is synchronized by the scheduler (join/channel edges), never by the counter itself. Values stay globally monotonic but their exact assignment is interleaving-dependent under concurrency, so tick values must never be hashed, persisted, or compared across columns. - Built
System - A constructed system and the table entry name it was built from.
- Clock
- A monotonic microsecond source, installed as a world resource by the host.
- Column
- A dense column of one component type, with its per-row change stamps.
- Column
Ticks - The tick stamps a column keeps.
changedis the maximum over every kind of write and drives whole-column change detection.addedmarks the last appended row.bulkmarks the last whole-column mutable access, after which every row must be assumed written.structuralmarks the last row add or removal, after which row positions and membership have moved. A consumer that tracks rows individually readsbulkandstructuralto decide whether the per-row stamps alone still describe what changed. - Component
Id - A component’s dense id, its bit position in a
ComponentMask. - Component
Mask - A set of component ids, one bit each.
- Component
Storage - One
Column<T>per registered component type, the entity allocator that stamps each row’s id, the change tick stamped on every structural edit, and the join index that maps an entity to its row in each column. Field columns are the caller’s field idents, reached through the$slottrait; callers never name them directly. - Cursor
State - The latest sampled cursor state (window pixels, top-left origin), published
by InputSystem after each poll. GraphicsSystem reads it when building the
next frame’s draw list:
follow_cursorsprites are positioned a frame after the input that moved them, and the in-engine cursor stops drawing once the real cursor has left the window (outside_windowis false in fullscreen, where the backend confines the cursor, and on backends without window-bounds tracking). - Desired
Cursor - The silhouette the in-engine cursor sprite should draw this frame.
- Dropdown
View - What GraphicsSystem needs to draw an open dropdown list: the anchor control
rect (reference space), the option labels top-to-bottom, the selected +
hovered OPTION indices to highlight, the scroll position (
first, the top shown option of a list longer than the layout window), and the row value label’s font / scale / color so the list text matches the row it drops from. - Entities
- The entity allocator: slot generations, the free list, and the reservation counter.
- Entity
- A live entity handle: a slot index plus the generation that slot carried when the handle was minted.
- Entity
ByName - Maps a placement’s asset identity (its declared name) to the live Entity it was loaded into. Built by the decomposition pass so later passes can resolve a name reference (a Prop parent, a PropBody owner, an audio emitter target) to an Entity without scanning.
- Event
Cursor - A reader’s position in an
Eventsqueue. - Event
Store - Type-keyed event queues, one per event type in use.
- Events
- A double-buffered event queue: events stay readable for two frames.
- Execution
Trace - What the behavior system observed over one simulated tick, published while a
TraceRequest stands.
frameincrements per published tick so the observer can tell fresh data from the stale resource a paused world leaves behind.eventsare the nodes that ran (deduplicated);varsthe world variables with their current values in slot order;localsthe requested entity’s per-behavior locals;hitthe first executed breakpoint, if any. - FlyCam
- The editor’s fly-camera state. While true (published only by the
cn editorHUD drive), InputSystem keeps the navigation keys and mouse deltas live and GraphicsSystem captures the cursor even though the world is frozen behind the editor’s menu override – the editor integrates Camera3D itself, so the viewport can be flown without running the simulation. Absent / false in a shipped runtime. - Frame
Context - Frame-scoped facilities a system may use for the duration of its
step. - Frame
Rate Cap - The live frame-rate cap in FPS (0 = unlimited), published by GraphicsSystem (from GraphicsConfig at init, refreshed by the settings row’s live change) and read by the App-level frame pacer before each world step. Independent of the quality preset (a user/hardware preference, like vsync).
- GpuMemory
Pressure - Device-memory pressure signal, published by GraphicsSystem whenever GPU work fails for lack of device memory. Renderer-free counters so the streaming valve can react (tighten budgets, evict) without naming the renderer; nothing consumes it yet.
- Hidden
Assets - Assets suppressed from rendering for this frame. GraphicsSystem collapses
each listed asset’s draw slots to a degenerate transform (so it neither
rasterizes nor casts shadows) and drops it from the PickIndex. Authored
data is untouched, and the collapse is re-derived every frame, so clearing
an id restores the object immediately. Published by the
cn editorHUD drive; absent / empty otherwise. - HudLayers
- Per-frame draw-layer overrides for HUD Sprites / TextLabels / TextInputs, keyed
by asset id and published by the
cn editorHUD so its floating panels occlude cleanly. Overlay draw calls render in two passes (all sprites, then all text), so two overlapping panels’ contents merge – one panel’s text draws over the other’s background. GraphicsSystem stable-sorts the overlay calls by this layer (higher draws on top) when the map is non-empty, so the focused panel’s whole content sits above the others’. An id absent from the map is layer 0; an empty / absent resource (the shipped runtime) leaves draw order at insertion order, unchanged. - HudPrefs
- Per-frame stats-HUD visibility, published as a resource by GraphicsSystem
(which runs first) and read by
StatHudSystemthe same tick. Each field is the effective on/off for that chip: the master “Display performance stats” toggle AND the per-readout toggle from the video settings. Absent (a HUD-only unit test with no GraphicsSystem) is treated as both shown. - Join
Index - Entity to component-row index: which components an entity has, and where each one’s row sits in its column.
- Menu
Active - Per-frame menu state, published as a resource by the overlay build (which runs
first in the schedule) and read by the simulation systems the same tick.
truewhile any world-pausing screen is open: physics and animation then freeze so they stop consuming resources behind the menu. Each system keeps its own clock aligned across the freeze, so resuming costs one normal frame – no catch-up burst, no pose jump. - Menu
Override - An external per-frame driver (the
cn editorHUD) can force the world’s “menu active” state through this resource:Some(true)frees the cursor and freezes gameplay/physics/animation (edit mode),Some(false)captures the cursor and lets the world run (play mode), both regardless of whether the world has its own menu UI. GraphicsSystem also puts the backend in menu mode while it is set, so a click frees to a UI action instead of re-capturing the camera.None(the default absence) leaves the world’s own menu logic in charge; a shipped runtime never publishes it. - NoPayloads
- A payload store holding nothing: every read errors and every release is a
no-op. What a
Worldbuilt without a blob runs on – unit tests, and worlds assembled entirely from runtime-only components. - Open
Dropdown - A settings dropdown’s open floating option list, or
Nonewhen none is open.UiInputSystemowns the interaction state (open on asetting:<key>:openclick, close on a pick / outside click / Escape / scroll) and publishes this each frame; GraphicsSystem reads it the next tick to draw the list on top of the menu. GraphicsSystem runs first, so the list appears one frame after the row is clicked (the same lag the cursor + cycle labels already carry). - Overlay
Image - One extra RGBA8 image for the sprite/text atlas pool, bound to a reserved TextureHandle the inserting tool chose. The handle space must stay clear of the compiled world’s dense texture handles (tools use a high base).
- Overlay
Images - Extra images appended to the sprite/text atlas pool at graphics init: a
sprite whose
texturenames one of these handles samples the image like any compiled texture. Opt-in like PickIndex: inserted before start (thecn editorHUD injection adds baked asset thumbnails); absent everywhere else, so a shipped runtime never pays for it. Read once at init – images added to the resource later join the pool on the next world rebuild. - Pick
Entry - One pickable entity in the PickIndex: its asset id and current world-space
AABB. Ray-tested by the editor with
gfx::pick::ray_aabb. - Pick
Index - The per-frame viewport-picking index: every renderable prop entity’s asset id
and world-space AABB, refreshed by GraphicsSystem from the live transforms.
Opt-in: GraphicsSystem only builds it when the resource is already present at
init (the
cn editorHUD injection inserts an empty one), so a shipped runtime never pays for it. Rooms, instanced clusters, and voxel chunks are not indexed; picking targets authored prop placements. - Pipeline
Context - A system’s view of the world for the duration of one
step: the five things it borrows, and the accessors that reach them. - Resources
- Type-keyed singleton storage: one value per resource type.
- Scratch
Stats - What one frame’s scratch reserve cost and whether it held. A non-zero
overflowsmeans some frame fell back to the heap, sopeakunderstates what the frame actually wanted. - Screen
Stack - The active screen stack, published by UiInputSystem at init and whenever the
stack changes, and read a frame later (the same one-frame lag screen
visibility flips already have).
layersmaps each active Screen’s id to its computed draw layer (authored layer band + stack position; screen-less HUD elements sit at 0); the overlay build spreads these onto the elements each screen owns.pauses_worldis true while any active screen pauses the world;captures_inputis true while any active screen captures input (gameplay keys are suppressed even when the world keeps simulating). Absent / empty in a world with no active screen. - SimTiming
- Fixed-timestep budget for the current frame, published by the App-level
simulation clock before each world step.
ticksis how many fixed steps the simulation systems (physics, behavior) run this frame;tick_dtis the seconds each step advances;alphais the accumulator remainder as a fraction oftick_dt, used to blend the previous and current simulated states when writing render-facing transforms. Absent (a directly-stepped world with no App), the default is exactly one tick per step with no blending, which makes bareWorld::steploops deterministic. - System
Entry - One row of the system table. Table order is run order.
- System
Table - A host’s system table and the load-time passes only the host can supply.
- Tick
- A change-detection stamp. Wraps; comparisons use a signed window bounded
by
MAX_CHANGE_AGE. - Trace
Event - One node execution: which behavior, and the node’s compile-assigned pre-order id (an index into that behavior’s TracePaths entry).
- Trace
Paths - Each behavior’s node paths, indexed by the node ids ExecutionTrace events carry. Published once when tracing is first requested (the compile that derives it runs at init either way; the publish just exposes it).
- Trace
Request - An external observer’s request for execution tracing, published per frame by
the
cn editorHUD while its Behavior panel is open and removed when it closes. While present, the behavior system records which nodes ran each simulated tick and publishes ExecutionTrace; absent (the shipped runtime, or the panel closed), the system does no recording work beyond noticing the absence.entityselects whose per-entity locals to surface;breakpointsare nodes whose execution should be reported as a ExecutionTrace::hit so the observer can pause the simulation. - Transient
Saves - Keeps a preview session out of the user’s real save files: while present and
true, the systems that persist play state (behavior variables / once flags,
story position) neither read nor write their disk saves – every session
starts fresh and leaves no trace. In-memory state is unaffected, so a
savenode still works within the session. Published by thecn editorHUD injection (sampled at each system’s init); a shipped runtime never publishes it. - View
Overrides - The viewport’s view mode + show flags, published per frame by the editor. GraphicsSystem forwards it to the backend’s FrameParams: the mode selects what the composite presents, the flags skip feature passes for the frame. Absent outside the editor, which reads as the lit default.
- World
- A world: its component storage, its resources, the compiled payloads it loads from, and the systems that run over all three.
- World
Lines - World-space lines to draw this frame (trajectories, tethers, path previews, the editor’s origin axes), republished by their producer every frame: GraphicsSystem expands whatever it finds into ribbon geometry and hands it to the backend, so a stale list would keep drawing. Absent when nothing draws lines, which keeps the line pass out of the frame graph.
- World
Physics Budget - The world’s physics reservation as cook counted it, published at blob load. Absent when the world declares no physics content, or when the world was built in memory rather than loaded from a blob; the simulation then counts the loaded components itself.
Enums§
- Asset
Origin - Where an asset comes from and whether it persists to a blob.
- Asset
Payload - Whether the asset has a compiled binary payload packed into a .cnb blob.
- Component
Asset - A loaded component of any registered type.
- Component
Tag - The component type tag: one fieldless variant per component, in list
order, so each variant’s
#[repr(u8)]discriminant is its list position (0, 1, 2, …).ComponentTag::$variant as u8is that tag, used both as the on-disk blob discriminant and as the in-memory ECSComponentId. The tag is assigned by position, not hand-written, and is not a stable on-disk contract: a build regenerates the blob, so the blob and the engine that loads it always agree. The authoringRegisteredTyperegistry derives the same tag from this enum. - Cursor
Shape - The silhouette the in-engine cursor sprite should draw this frame. Published
by the
cn editorHUD when the pointer is over a resizable panel’s edge or corner (or while a resize drag is in flight) and read by the overlay build, which draws the matching shape at the pointer in place of the arrow.Defaultis the plain arrow; the four resize shapes are double-headed arrows along a window edge (east/west), edge (north/south), and the two diagonals. A shipped runtime never publishes it, so the arrow always stands. - Frame
Vec - A frame temporary: in the scratch arena when it fit, on the heap when it did
not. Reads as
&[T]either way, so a caller never branches on which it got. - Schedule
Mode - How a tick’s independent work executes.
Parallellets systems fan their safe internal work across the job pool;Serial(or the resource being absent, the editor’s case) keeps every system’s work on the stepping thread – the determinism oracle and the escape hatch (cn run --serial-schedule). Both modes must produce identical world state; the engine’s schedule-determinism test is the gate on that claim. - Step
Result - What a system asks the world to do after its step.
- Trace
Step - One hop of a behavior-node address, mirroring the world checker’s fault
paths: object fields by key, list members by position. A node’s path walks
from the behavior’s args to the node (e.g.
do[1].if.then[0]is[Field("do"), Index(1), Field("if"), Field("then"), Index(0)]minus the node’s own trailing verb), so the editor can resolve a traced node to the same outline row / chart card its checker faults land on. Field names are the fixed authoring keys, so they borrow statically. - Trace
Val - A behavior-body value in its cross-boundary form: what
Valpublishes to an observer. Entities travel as their id bits.
Constants§
- HEADLESS_
SYSTEMS - The simulation systems a world runs with no host beyond this crate, in run
order. What
Appstarts a headless world against. - MAX_
CHANGE_ AGE - Half the u32 range. A tick older than this relative to the current tick is clamped forward so the signed-window comparison never aliases.
Traits§
- Baked
Mesh - A mesh value a world takes a baked geometry payload for, through
World::add_mesh. - Component
- Component – pure serializable data, no behavior. The runtime-facing surface
only: a component loads from its baked blob bytes and receives its injected
identity/payload hooks. All authoring metadata (origin, payload kind,
reference fields, args schema, validators) lives in the build-side registry
(concinnity-cook), derived from the
for_each_component!metadata blocks. - Component
Slot - Resolves a component type to its column inside the storage at compile
time, so the generic storage operations above need no runtime
dispatch. A registered component is exactly a type with a
$slotimpl, andDISCRIMINANTis its stable id, used as itsComponentIdin the join index.'static: components own their data, and the generic ops hand out borrows of (and owned vectors of) the type. - Payload
Store - A source of compiled payload bytes addressed by
PayloadLocator. - Resource
Asset - An asset compiled into the blob’s resource stream rather than stored as a component.
- Runtime
Component - A component a world can hold after the cook: every type an authored world declares that survives into a blob, plus every type only the runtime mints.
- System
- System – has behavior, receives a PipelineContext each tick. Every system
is internal engine code:
World::startconstructs it from world components (via the system’s ownnew(..)), so a system is never loaded from or written to a blob.initruns once atWorld::start;stepruns every tick.
Type Aliases§
- Complete
World - A host’s completion pass: it runs over the world before the gates read it, and fails the start when the world cannot be completed.
- Trace
Path - A behavior node’s address: the hops from the behavior’s args down to it.