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 bySceneRegistry.migrate, newer ones are rejected.comptime MAGIC = "CSCN"— The four bytes that open a binary scene file.comptime KIND_FLOAT = 1— A single Float32 inField.floats[0](also mirrored inField.number).comptime KIND_INT = 2— A signed 64-bit integer inField.integer.comptime KIND_BOOL = 3— A boolean inField.integer(0 or 1);true/falsein the text format.comptime KIND_STRING = 4— Text inField.text; written quoted and escaped in the text format.comptime KIND_ENTITY = 5— A file-local entity index inField.integer(-1 = no entity);#nin the text format.comptime KIND_FLOATS = 6— A fixed list of floats (vec3, vec4, mat4 ...).
struct Field #
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 #
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) -
findfind(self, name: String) -> Int
Index of the field calledname, or -1. -
rename_fieldrename_field(mut self, old: String, new: String) -> Bool
Renames fieldoldtonew(for migrations); returns False when there is no fieldold. An existing field callednewis not checked for.
struct EntityRecord #
struct EntityRecord(Copyable, Movable)One entity of a scene: the records of the components it carries.
Fields:
-
components: List[ComponentRecord] -
__init____init__(out self) -
findfind(self, name: String) -> Int
Index of the component record calledname, or -1.
struct SceneDoc #
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 #
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] ) -
floatfloat(mut self, name: String, v: Float32)
Appends aKIND_FLOATfield. -
intint(mut self, name: String, v: Int)
Appends aKIND_INTfield. -
boolbool(mut self, name: String, v: Bool)
Appends aKIND_BOOLfield (stored as 0 or 1). -
stringstring(mut self, name: String, v: String)
Appends aKIND_STRINGfield. -
entityentity(mut self, name: String, e: Entity)
Appends aKIND_ENTITYfield withe's file-local index: -1 wheneis null, beyond the index table or not part of the snapshot. Only the slot index is looked up; the generation is not checked. -
floatsfloats(mut self, name: String, values: List[Float32])
Appends aKIND_FLOATSfield holding a copy ofvalues. -
vec3vec3(mut self, name: String, v: Vec3)
Appendsvas a three-floatKIND_FLOATSfield. -
mat4mat4(mut self, name: String, m: Mat4)
Appendsmas a 16-floatKIND_FLOATSfield in column-major order.
struct FieldReader #
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], ) -
floatfloat(mut self, name: String, default: Float32) -> Float32
Fieldnameas a float, ordefaultwhen absent. An integer field is converted; any other kind setserrorand returnsdefault. -
intint(mut self, name: String, default: Int) -> Int
Fieldnameas an integer, ordefaultwhen absent; another kind setserrorand returnsdefault. -
boolbool(mut self, name: String, default: Bool) -> Bool
Fieldnameas a boolean, ordefaultwhen absent; another kind setserrorand returnsdefault. -
stringstring(mut self, name: String, default: String) -> String
Fieldnameas a string, ordefaultwhen absent; another kind setserrorand returnsdefault. -
entityentity(mut self, name: String) -> Entity
Fieldnameremapped to the spawned entity. Returns the null entity when the field is absent, not an entity field, -1 or out of range; never setserror. -
floatsfloats(mut self, name: String, count: Int) -> List[Float32]
Thecountfloats of fieldname. Returnscountzeros when the field is absent, and also when it is not aKIND_FLOATSfield of exactlycountvalues, in which caseerroris set. -
vec3vec3(mut self, name: String, default: Vec3) -> Vec3
Fieldnameas a Vec3, ordefaultwhen absent; a field of another shape setserrorand yields zero. -
mat4mat4(mut self, name: String) -> Mat4
Fieldnameas a column-major Mat4, or identity when absent; a field of another shape setserrorand yields an all-zero matrix.
trait SceneComponent #
trait SceneComponent(Component)A component that can be saved: name, field writer and reader.
-
scene_namescene_name() -> String
The component's name in scene files, matched against component records on load. -
write_scenewrite_scene(self, mut w: FieldWriter)
Writes the component's fields intow. -
read_sceneread_scene(mut r: FieldReader) -> Self
Builds the component fromr, with defaults for missing fields. Whenr.erroris set afterwards (the typed getters set it on a kind mismatch) the component is not added andSceneRegistry.instantiateraises. -
comptime WriteFn = def( Pointer[World, MutUntrackedOrigin], Entity, Pointer[FieldWriter, MutUntrackedOrigin], ) thin -> Bool— Type-erased writer of one component type: fills theFieldWriterand 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 theFieldReader, 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 aSceneDocin place from one version to the next;SceneRegistry.migratethen incrementsversionitself.
struct SceneRegistry #
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 fromfrom_versionto +1. -
__init____init__(out self) -
registerregister[T: SceneComponent](mut self)
MakesTsaveable underT.scene_name(). Duplicate names are not rejected; lookups on load use the first registration. -
add_migrationadd_migration(mut self, from_version: Int, migration: MigrationFn)
Registersmigrationto upgrade documents atfrom_versiontofrom_version + 1. -
to_docto_doc(self, mut world: World) raises -> SceneDoc
Snapshots every live entity (in archetype order) with its registered components. -
migratemigrate(self, mut doc: SceneDoc) raises
Applies registered migrations until the document is at SCENE_VERSION. -
instantiateinstantiate( 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 #
def format_float(v: Float32) -> StringShortest decimal that round-trips, else the IEEE bits as 0x....
def parse_float #
def parse_float(text: String) raises -> Float32Parses 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 #
def bitcast_u32_to_f32(bits: UInt32) -> Float32Reinterprets IEEE-754 single-precision bits as a Float32.
def write_text #
def write_text(doc: SceneDoc) -> StringSerialises 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 #
def read_text(text: String) raises -> SceneDocParses 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 #
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 #
def read_binary(var data: List[UInt8]) raises -> SceneDocParses 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 #
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 — Carriesroot_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_nodeentity_of_node(self, node: Int) -> Entity
Entity spawned for glTF nodenode; the null entity for an out-of-range index or a node outside the scene graph.
def spawn_gltf #
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 -> SpawnedGltfUploads 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 #
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 #
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_idcomponent_id() -> Int
struct LightSource #
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_idcomponent_id() -> Int
struct CameraComponent #
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_idcomponent_id() -> Int
struct JointPalette #
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_idcomponent_id() -> Int
struct RenderBridge #
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)buildbuild(mut self, world: World, mut scene: RenderScene) raises -> Int
Fillsscene.instances,scene.jointsandscene.lightsfrom the world and sets the camera from the first activeCameraComponent. Returns the number of instances.
def build_render_scene #
def build_render_scene(world: World, mut scene: RenderScene) raises -> IntOne-off bridge build (tests); the App keeps a RenderBridge.