DocsAPI reference

cinder.scene

cinder.scene #

Source: cinder/scene/__init__.mojo

Scene files: versioned text and binary formats with migrations, over the ECS world.

cinder.scene.format #

Source: cinder/scene/format.mojo

Scene serialisation: a human-diffable text format and a binary format, versioned, with migrations. Both formats carry the same intermediate representation (SceneDoc: entities with component records of typed fields), so a document can be read in either format, migrated version by version, and written in either. Component types take part by implementing SceneComponent and being registered in a SceneRegistry, which stores type-erased read/write functions. Text format (version 2): cinder-scene 2 entity 0 Position x=1.5 y=-2 Label text="hello \"world\"" entity 1 Parent entity=#0 Floats are written as the shortest decimal that round-trips, or as 0x... IEEE bits when the decimal form does not reproduce the value exactly. Entity references (#n) are file-local indices remapped on load. Binary: magic CSCN, version, then the same records with type tags.

  • comptime SCENE_VERSION = 2 — Version this engine writes and instantiates; older documents are upgraded by SceneRegistry.migrate, newer ones are rejected.
  • comptime MAGIC = "CSCN" — The four bytes that open a binary scene file.
  • comptime KIND_FLOAT = 1 — A single Float32 in Field.floats[0] (also mirrored in Field.number).
  • comptime KIND_INT = 2 — A signed 64-bit integer in Field.integer.
  • comptime KIND_BOOL = 3 — A boolean in Field.integer (0 or 1); true/false in the text format.
  • comptime KIND_STRING = 4 — Text in Field.text; written quoted and escaped in the text format.
  • comptime KIND_ENTITY = 5 — A file-local entity index in Field.integer (-1 = no entity); #n in the text format.
  • comptime KIND_FLOATS = 6 — A fixed list of floats (vec3, vec4, mat4 ...).

struct Field #

mojo
struct Field(Copyable, Movable)

One named, typed value of a component record. kind is a KIND_* constant and selects which of number, integer, text or floats holds the value; the others keep their zero defaults.

Fields:

  • name: String

  • kind: Int

  • number: Float64

  • integer: Int64

  • text: String

  • floats: List[Float32]

  • __init__ __init__(out self, name: String, kind: Int)

struct ComponentRecord #

mojo
struct ComponentRecord(Copyable, Movable)

A component as stored in a scene: its scene name and its fields in write order.

Fields:

  • name: String

  • fields: List[Field]

  • __init__ __init__(out self, name: String)

  • find find(self, name: String) -> Int
    Index of the field called name, or -1.

  • rename_field rename_field(mut self, old: String, new: String) -> Bool
    Renames field old to new (for migrations); returns False when there is no field old. An existing field called new is not checked for.

struct EntityRecord #

mojo
struct EntityRecord(Copyable, Movable)

One entity of a scene: the records of the components it carries.

Fields:

  • components: List[ComponentRecord]

  • __init__ __init__(out self)

  • find find(self, name: String) -> Int
    Index of the component record called name, or -1.

struct SceneDoc #

mojo
struct SceneDoc(Movable)

The format-independent scene: a version and the entities in file order. Entity fields hold indices into entities. Produced by SceneRegistry.to_doc, read_text and read_binary; consumed by SceneRegistry.migrate, SceneRegistry.instantiate, write_text and write_binary.

Fields:

  • version: Int

  • entities: List[EntityRecord]

  • __init__ __init__(out self, version: Int = SCENE_VERSION)

struct FieldWriter #

mojo
struct FieldWriter(Movable)

Collects a component's fields. Entities are written as file-local indices.

Fields:

  • record: ComponentRecord

  • index_of: Pointer[List[Int], MutUntrackedOrigin] — Entity slot index -> file-local index (-1 when not in the file).

  • __init__ __init__( out self, name: String, index_of: Pointer[List[Int], MutUntrackedOrigin] )

  • float float(mut self, name: String, v: Float32)
    Appends a KIND_FLOAT field.

  • int int(mut self, name: String, v: Int)
    Appends a KIND_INT field.

  • bool bool(mut self, name: String, v: Bool)
    Appends a KIND_BOOL field (stored as 0 or 1).

  • string string(mut self, name: String, v: String)
    Appends a KIND_STRING field.

  • entity entity(mut self, name: String, e: Entity)
    Appends a KIND_ENTITY field with e's file-local index: -1 when e is null, beyond the index table or not part of the snapshot. Only the slot index is looked up; the generation is not checked.

  • floats floats(mut self, name: String, values: List[Float32])
    Appends a KIND_FLOATS field holding a copy of values.

  • vec3 vec3(mut self, name: String, v: Vec3)
    Appends v as a three-float KIND_FLOATS field.

  • mat4 mat4(mut self, name: String, m: Mat4)
    Appends m as a 16-float KIND_FLOATS field in column-major order.

struct FieldReader #

mojo
struct FieldReader(Movable)

Reads a component's fields by name; missing fields take the given default.

Fields:

  • record: ComponentRecord

  • entities: Pointer[List[Entity], MutUntrackedOrigin] — File-local index -> spawned entity.

  • error: String

  • __init__ __init__( out self, var record: ComponentRecord, entities: Pointer[List[Entity], MutUntrackedOrigin], )

  • float float(mut self, name: String, default: Float32) -> Float32
    Field name as a float, or default when absent. An integer field is converted; any other kind sets error and returns default.

  • int int(mut self, name: String, default: Int) -> Int
    Field name as an integer, or default when absent; another kind sets error and returns default.

  • bool bool(mut self, name: String, default: Bool) -> Bool
    Field name as a boolean, or default when absent; another kind sets error and returns default.

  • string string(mut self, name: String, default: String) -> String
    Field name as a string, or default when absent; another kind sets error and returns default.

  • entity entity(mut self, name: String) -> Entity
    Field name remapped to the spawned entity. Returns the null entity when the field is absent, not an entity field, -1 or out of range; never sets error.

  • floats floats(mut self, name: String, count: Int) -> List[Float32]
    The count floats of field name. Returns count zeros when the field is absent, and also when it is not a KIND_FLOATS field of exactly count values, in which case error is set.

  • vec3 vec3(mut self, name: String, default: Vec3) -> Vec3
    Field name as a Vec3, or default when absent; a field of another shape sets error and yields zero.

  • mat4 mat4(mut self, name: String) -> Mat4
    Field name as a column-major Mat4, or identity when absent; a field of another shape sets error and yields an all-zero matrix.

trait SceneComponent #

mojo
trait SceneComponent(Component)

A component that can be saved: name, field writer and reader.

  • scene_name scene_name() -> String
    The component's name in scene files, matched against component records on load.

  • write_scene write_scene(self, mut w: FieldWriter)
    Writes the component's fields into w.

  • read_scene read_scene(mut r: FieldReader) -> Self
    Builds the component from r, with defaults for missing fields. When r.error is set afterwards (the typed getters set it on a kind mismatch) the component is not added and SceneRegistry.instantiate raises.

  • comptime WriteFn = def( Pointer[World, MutUntrackedOrigin], Entity, Pointer[FieldWriter, MutUntrackedOrigin], ) thin -> Bool — Type-erased writer of one component type: fills the FieldWriter and returns False when the entity lacks the component or writing it raised.

  • comptime ReadFn = def( Pointer[World, MutUntrackedOrigin], Entity, Pointer[FieldReader, MutUntrackedOrigin], ) thin -> Bool — Type-erased reader of one component type: builds the component from the FieldReader, adds it to the entity and returns False when the reader recorded an error or the add failed.

  • comptime MigrationFn = def(Pointer[SceneDoc, MutUntrackedOrigin]) thin -> None — Upgrades a SceneDoc in place from one version to the next; SceneRegistry.migrate then increments version itself.

struct SceneRegistry #

mojo
struct SceneRegistry(Movable)

Known component types and version migrations.

Fields:

  • types: List[_Registered]

  • migrations: List[Tuple[Int, MigrationFn]] — (from_version, migration) pairs; each converts a document from from_version to +1.

  • __init__ __init__(out self)

  • register register[T: SceneComponent](mut self)
    Makes T saveable under T.scene_name(). Duplicate names are not rejected; lookups on load use the first registration.

  • add_migration add_migration(mut self, from_version: Int, migration: MigrationFn)
    Registers migration to upgrade documents at from_version to from_version + 1.

  • to_doc to_doc(self, mut world: World) raises -> SceneDoc
    Snapshots every live entity (in archetype order) with its registered components.

  • migrate migrate(self, mut doc: SceneDoc) raises
    Applies registered migrations until the document is at SCENE_VERSION.

  • instantiate instantiate( self, mut world: World, doc: SceneDoc ) raises -> List[Entity]
    Spawns the document's entities (after migration) and returns them in file order.

def format_float #

mojo
def format_float(v: Float32) -> String

Shortest decimal that round-trips, else the IEEE bits as 0x....

def parse_float #

mojo
def parse_float(text: String) raises -> Float32

Parses a float written by format_float: a decimal, or 0x followed by up to 8 hex digits of IEEE bits. Raises on malformed text.

def bitcast_u32_to_f32 #

mojo
def bitcast_u32_to_f32(bits: UInt32) -> Float32

Reinterprets IEEE-754 single-precision bits as a Float32.

def write_text #

mojo
def write_text(doc: SceneDoc) -> String

Serialises doc in the text format described in the module docstring: a cinder-scene N header, one entity i line per entity and one indented Name key=value ... line per component.

def read_text #

mojo
def read_text(text: String) raises -> SceneDoc

Parses the text format into a SceneDoc at the file's version (not migrated). Blank lines and lines starting with # are skipped. Raises on a missing header, entities out of order, a component line before any entity, an unterminated quote or bracket, a token without =, or a value that does not parse.

def write_binary #

mojo
def write_binary(doc: SceneDoc) -> List[UInt8]

Serialises doc in the binary format: MAGIC, then little-endian u32 version and entity count; per entity a component count, per component its name and field count, per field its name, a u8 kind and the value. Strings are a u32 byte length plus bytes; integers, bools and entities are 64-bit (low word first); float lists carry a u32 count.

def read_binary #

mojo
def read_binary(var data: List[UInt8]) raises -> SceneDoc

Parses the binary format written by write_binary into a SceneDoc at the file's version (not migrated). Raises on a bad magic, truncated data, an unknown field kind, or implausible counts (over 10 million entities, 10 000 components per entity or fields per component, or 1 million floats per field). Trailing bytes are ignored.

cinder.scene.gltf_spawn #

Source: cinder/scene/gltf_spawn.mojo

Spawning a glTF asset into the ECS: one entity per node (transform hierarchy) and one child entity per mesh primitive (MeshRenderer), plus static collision triangles for level geometry.

struct SpawnedGltf #

mojo
struct SpawnedGltf(Movable)

Result of spawn_gltf: the root entity, the entity of each glTF node and of each mesh primitive, and the renderer ids of the upload. The entities stay in the world after this value is dropped.

Fields:

  • root: Entity — Carries root_transform; every glTF root node is its child.

  • node_entities: List[Entity] — Entity per glTF node (nodes outside the scene graph get the null entity).

  • primitive_entities: List[Entity] — Every primitive entity, in node then primitive order.

  • uploaded: UploadedGltf

  • __init__ __init__(out self, root: Entity, var uploaded: UploadedGltf)

  • entity_of_node entity_of_node(self, node: Int) -> Entity
    Entity spawned for glTF node node; the null entity for an out-of-range index or a node outside the scene graph.

def spawn_gltf #

mojo
def spawn_gltf( mut renderer: Renderer, mut res: Resources, asset: GltfAsset, mut world: World, root_transform: Mat4 = Mat4.identity(), lods: Bool = True, cast_shadows: Bool = True, skinned_meshes: Bool = True, ) raises -> SpawnedGltf

Uploads the asset and spawns its node hierarchy. Skinned mesh nodes get a MeshRenderer too (the caller attaches an AnimatorRef so the animation system publishes their palette) unless skinned_meshes is False. Every node is spawned at most once, even when the file reaches it twice (a root that is also a child, a node shared by two parents, or a cycle); a node whose glTF parent has not been spawned yet hangs under root, so the Parent links never form a cycle.

def collision_triangles #

mojo
def collision_triangles( asset: GltfAsset, root_transform: Mat4 = Mat4.identity() ) -> Tuple[List[Vec3], List[UInt32]]

World-space triangles of every non-skinned mesh node, for a static mesh collider.

cinder.scene.render_sync #

Source: cinder/scene/render_sync.mojo

Bridge from the ECS world to a RenderScene: render components and their collection. Components: MeshRenderer (renderer mesh and material indices, shadow flag), LightSource, CameraComponent. build_render_scene reads WorldTransform (propagated beforehand) and fills the renderer's scene lists in one pass; it allocates nothing in steady state because the scene's lists are cleared and refilled in place.

struct MeshRenderer #

mojo
struct MeshRenderer(Component)

Draws renderer mesh mesh with material material at the entity's WorldTransform; cast_shadows is passed to the render instance.

Fields:

  • mesh: Int

  • material: Int

  • cast_shadows: Bool

  • component_id component_id() -> Int

struct LightSource #

mojo
struct LightSource(Component)

A light positioned by the entity's world transform (direction = transform's -Z).

Fields:

  • kind: LightKind

  • color: Vec3

  • intensity: Float32

  • range: Float32

  • inner_angle: Float32

  • outer_angle: Float32

  • cast_shadows: Bool

  • component_id component_id() -> Int

struct CameraComponent #

mojo
struct CameraComponent(Component)

A camera at the entity's world transform, looking down its -Z with its +Y up. RenderBridge.build uses the first active one it finds, keeping the scene camera's current aspect ratio.

Fields:

  • fov_y: Float32

  • near: Float32

  • active: Bool

  • component_id component_id() -> Int

struct JointPalette #

mojo
struct JointPalette(Component)

Skinning matrices and morph weights for an entity's mesh, written by the animation system each frame and consumed by build_render_scene.

Fields:

  • joints: List[Mat4]

  • morph_weights: List[Float32]

  • component_id component_id() -> Int

struct RenderBridge #

mojo
struct RenderBridge(Movable)

ECS -> RenderScene with persistent query specs and chunk scratch (no steady-state allocations). build_render_scene is a convenience wrapper around a temporary instance.

Fields:

  • __init__ __init__(out self)
  • build build(mut self, world: World, mut scene: RenderScene) raises -> Int
    Fills scene.instances, scene.joints and scene.lights from the world and sets the camera from the first active CameraComponent. Returns the number of instances.

def build_render_scene #

mojo
def build_render_scene(world: World, mut scene: RenderScene) raises -> Int

One-off bridge build (tests); the App keeps a RenderBridge.

View as MarkdownSource: docs/api/scene.md