Clone
6
Scenegraph
Simian CI edited this page 2026-03-12 20:31:05 +00:00

Scenegraph

This project uses a lightweight hierarchy component to model parent/child relationships in ECS. The scenegraph is EnTT-friendly and uses a linked-list structure for children.

Components

Hierarchy

Each entity can have a Hierarchy component with these fields:

  • parent — parent entity or null
  • first — first child entity
  • prev / next — sibling links

This mirrors the common EnTT scenegraph pattern and avoids storing vectors of children inside a component.

ECSTransform (local)

Stores local position/scale and a Y-axis rotation (radians).

WorldTransform (computed)

Computed each frame from the hierarchy and local transform. Rendering uses WorldTransform so children move with parents.

Update Order

  1. Systems update local transforms (e.g., velocity system).
  2. UpdateWorldTransforms() traverses the hierarchy and computes WorldTransform.
  3. Rendering draws from WorldTransform + ModelRenderer.

Script API

ECS::SetParent(child, parent);
ECS::ClearParent(child);
uint p = ECS::GetParent(child);
bool has = ECS::HasParent(child);

Scene File Format (TOML)

Scenes are stored in scenes/*.toml using a minimal TOML-like structure. Example:

scene_script = "scripts/scene.as"

[[entity]]
id = "root"
tag = "Root"
position = [0.0, 0.0, 0.0]
rotation_deg = 0.0
scale = [1.0, 1.0, 1.0]

[[entity]]
id = "parent"
parent = "root"
tag = "Parent"
position = [2.0, 0.0, 0.0]
model = "cube"
model_asset = "unit_cube"
model_size = [1.0, 1.0, 1.0]
color = 0x00FF00FF
shader_vs = "shaders/toon.vs"
shader_fs = "shaders/toon.fs"
shader_asset = "toon"
texture = "assets/textures/grid.png"
texture_asset = "grid"
uv_scale = [2.0, 2.0]
uv_offset = [0.0, 0.0]
material_asset = "toon_mat"

[[entity]]
id = "child"
parent = "parent"
tag = "Child"
position = [0.0, 1.25, 0.0]
model = "sphere"
radius = 0.5
color = 0xFF0000FF
shader_vs = "shaders/toon.vs"
shader_fs = "shaders/toon.fs"

Supported Keys

  • scene_script (string) — scene-level script path (outside entity blocks)
  • id (string) — unique identifier for parent links
  • parent (string) — parent entity id
  • tag (string) — Tag component value
  • position (vec3)
  • rotation (radians) or rotation_deg (degrees)
  • scale (vec3)
  • modelcube, sphere, plane, or file path
  • model_asset (string) — asset key for models
  • model_id (int) — numeric model id
  • model_size (vec3) for cubes/planes
  • radius, rings, slices for spheres
  • color — hex 0xRRGGBBAA (matches script colors)
  • outline_size — optional model outline
  • shader_vs, shader_fs — optional shader paths
  • shader_asset (string) — asset key for shaders
  • shader_id (int) — numeric shader id
  • texture (string) — texture path
  • texture_asset (string) — asset key for textures
  • texture_id (int) — numeric texture id
  • material_asset (string) — asset key for materials
  • material_id (int) — numeric material id
  • uv_scale (vec2)
  • uv_offset (vec2)
  • uv_rotation (radians)
  • script (string) — per-entity script path
  • script_enabled (bool)
  • script_class (string)
  • script_var_* (string) — per-field overrides for script-editable values

Loading a Scene

uint root = Scene::Load("scenes/demo.toml");

Scene::Load returns a root entity that parents all top-level entities. Use ECS::IsValid(root) to check success on the scene load.

Editor

Run the app with --editor to open the ImGui editor. The Scene window shows the hierarchy tree, supports drag-and-drop reparenting, and lets you create/delete entities. The Inspector window shows components for the selected entity and allows live editing.