# Scene System Source: `src/dusk/scene/` ## Overview The scene system is the top-level coordinator for a running game state. It manages one active scene at a time. Scenes are JS scripts -- each scene is a `.js` asset file that exports an object with lifecycle hooks. The scene system loads, ticks, and tears down these scripts, while the C side runs the ECS and render pipeline on each tick. ## Scene lifecycle (C side) ```c extern scene_t SCENE; errorret_t sceneInit(void); // initialise the scene manager errorret_t sceneUpdate(void); // process pending transition, tick active scene errorret_t sceneRender(void); // render entities + render pipeline + UI errorret_t sceneDispose(void); // dispose the active scene immediately ``` `sceneUpdate` each tick: 1. Checks for a pending scene transition and performs it (dispose old, load and init new). 2. Calls the JS scene's `update()` hook. 3. Calls `entityManagerUpdate()` to fire all entity update callbacks. `sceneRender` each tick: 1. Binds the screen. 2. Calls `sceneRenderPipeline()` -- renders all entities with a `COMPONENT_TYPE_RENDERABLE` in priority order. 3. Renders UI. 4. Calls the JS scene's `render()` hook (for any custom drawing). 5. Unbinds the screen. ## Scene lifecycle (JS side) A scene file exports a plain object with these optional hooks: ```js var scene = {}; scene.init = async function() { // Load assets, create entities, set up state. // May be async -- await asset loads here. }; scene.update = function() { // Called each fixed-timestep tick. }; scene.render = function() { // Called each render tick, after ECS renderables. }; scene.dispose = function() { // Clean up entities and state. }; module.exports = scene; ``` See `CLAUDE.md` -- "JavaScript (asset scripts)" for JS style rules. ## Render pipeline (`scenerenderpipeline.h`) `sceneRenderPipeline(cameraEntityId)` gathers all active `COMPONENT_TYPE_RENDERABLE` components, sorts them by effective priority, and draws each one using its shader. **Priority rules:** - `renderable.priority != 0` -- use that value directly. - `renderable.priority == 0` -- auto-derive: opaque geometry sorts before transparent geometry; sprite batches sort before shader materials; etc. - Lower priority number = drawn first (behind); higher = drawn last (on top). The shader used for each renderable: - `ENTITY_RENDERABLE_TYPE_SPRITEBATCH` and `CUSTOM` default to `SHADER_LIST_SHADER_UNLIT`. - `ENTITY_RENDERABLE_TYPE_SHADER_MATERIAL` uses the shader indexed by `renderable.data.material.shaderType` in `SHADER_LIST_DEFS`. ## Transitioning between scenes To move to a new scene from JS, call the scene module's transition function (exact API in the `scene` JS module). The C side defers the actual switch to the start of the next `sceneUpdate` call so the current tick completes cleanly before any dispose runs. ## Relationship to the engine loop ``` engineUpdate() timeUpdate() inputUpdate() physicsManagerUpdate() scriptUpdate() <- runs JS microjobs sceneUpdate() <- JS update + ECS entity updates engineUpdate() -> sceneRender() screenBind() sceneRenderPipeline() <- ECS renderables sorted by priority uiRender() sceneRender (JS hook) screenUnbind / screenRender ```