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 ornullfirst— first child entityprev/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
- Systems update local transforms (e.g., velocity system).
UpdateWorldTransforms()traverses the hierarchy and computesWorldTransform.- 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 linksparent(string) — parent entity idtag(string) —Tagcomponent valueposition(vec3)rotation(radians) orrotation_deg(degrees)scale(vec3)model—cube,sphere,plane, or file pathmodel_asset(string) — asset key for modelsmodel_id(int) — numeric model idmodel_size(vec3) for cubes/planesradius,rings,slicesfor spherescolor— hex0xRRGGBBAA(matches script colors)outline_size— optional model outlineshader_vs,shader_fs— optional shader pathsshader_asset(string) — asset key for shadersshader_id(int) — numeric shader idtexture(string) — texture pathtexture_asset(string) — asset key for texturestexture_id(int) — numeric texture idmaterial_asset(string) — asset key for materialsmaterial_id(int) — numeric material iduv_scale(vec2)uv_offset(vec2)uv_rotation(radians)script(string) — per-entity script pathscript_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.