Zenbu

Entities and Components
Login

Entities and Components

Retained data, immediate drawing

Canvas_Scene stores an arena-backed array of Canvas_Entity. Each entity has:

The scene is retained, but the draw list is rebuilt every frame. This keeps interaction and context state stable while allowing normal Raylib immediate-mode drawing.

Each entity also owns lifecycle state. visibility_amount eases from zero to one after creation. Delete and developer Clear mark entities as removing, ease them back to zero, then compact the retained array. Raylib colors, native CEF texture tints, and WebAssembly overlay opacity all consume the same eased value.

Treat animation as part of every entity state transition, not optional polish. State changes set retained targets; frame updates ease visual geometry and opacity toward those targets. Do not snap expandable, collapsible, selected, hovered, created, removed, or otherwise stateful entities between layouts. Conversation collapse/expand uses the same smoothstep height interpolation as accordions, while preserving its final semantic active state for context.

Adding a component

Wire every relevant surface, not only drawing:

  1. Add the enum value in canvas.h.
  2. Set useful size, text, and state defaults in Canvas_Scene_Add().
  3. Add bounds/picking behavior in Canvas_Entity_Bounds() and Canvas_Entity_Contains().
  4. Add click behavior in Canvas_Scene_Activate() and specialized update logic in Canvas_Scene_Update_Interaction() when needed.
  5. Draw it in Canvas_Draw_Entity() and support selection in Canvas_Draw_Selection().
  6. Return a readable label from Canvas_Entity_Type_Name().
  7. Serialize meaningful state in Canvas_Context_Append_Entity_State().
  8. Add focused tests in canvas_test.c.
  9. If it owns external pixels or DOM, extend both web-surface backends and key resources by stable entity ID.

Prefer a single entity for large compound views. The Lucide gallery is one entity with virtualized internal rows, not 1,767 independently draggable scene objects.

Input ownership

Input is resolved from most specialized to most general:

Open developer dropdowns and the snapshot-name editor are modal because Raygui consumes keyboard or outside-click input while editing. While either is open, native web surfaces, canvas entities, dictation hotkeys, and camera movement do not receive that input.

Text editing blocks WASD/arrow camera movement. Scrollable entities consume an unmodified wheel. Ctrl/Cmd + wheel remains available to the camera for anchored zoom; an unmodified wheel outside a scrollable entity pans vertically.

Text areas keep cursor, selection anchor, and vertical scroll state on the entity. Their visual-line layout is shared by drawing, hit testing, vertical cursor movement, and caret visibility, so wrapped text and mouse selection use the same geometry. Ctrl on Windows/Linux and Cmd on macOS drive select/copy/ cut/paste shortcuts; Ctrl or Option performs word navigation. A selected text area exposes a bottom-right resize handle. Dragging it changes both dimensions, reflows wrapped lines immediately, and keeps the caret within the scrollable viewport.

Snapshot boundary

Developer Controls saves named native snapshots under the user state directory as versioned .zmap files. The encoder writes explicit little-endian fields rather than copying Canvas_Entity memory, then uses a payload checksum, bounded entity count, finite geometry validation, and an atomic temporary-file rename. Loading is transactional: the live scene is not cleared until the entire snapshot validates.

The current snapshot preserves numeric canvas entity IDs because conversation routing uses them. Those IDs are canvas-local handles, not final cross-workspace identities. Domain data should eventually normalize into stable keys such as conversation_id, asset_id, and component_id; an entity snapshot should retain only the typed key plus its visual state.

Transient pointers, CEF surfaces, Copilot SDK sessions, hover state, active agent work, and removal animations are never serialized. Browser and image surfaces reconstruct from their retained HTTP(S) source after load.