Skip to content

UI in the scene graph

vgai’s visual UI editor stores UI in the scene — a ui field on the .vscn document (packages/engine/src/scene/schema/ui.ts) — and renders it with one React runtime used both in the editor (WYSIWYG) and at game time (SceneUI.tsx).

A canvas root holds containers which hold controls
canvas → containers → controls.

A UI root is a canvas (space: screen or world-tracked) holding a nested tree:

  • Containersbox, grid, stack, scroll, panel, center, wrap, aspect, tab, sizebox.
  • Controlstext, richtext, button, image, input, toggle, slider, dropdown, progress, and component (a hand-authored React component).
Equal anchors fix size; split anchors stretch; flow children use flex
The anchor + offset model on top of a flex auto-layout engine.

Each node has a layout mode:

  • flow — laid out by its parent container’s flexbox (direction row/column[-reverse], justify, align, wrap, columns for grid; children set grow/shrink/basis/alignSelf).
  • absolute — anchored free placement: an anchor (edge fractions 0..1 of the parent) plus a pixel offset per edge. Equal anchors fix the size; split anchors stretch. A pivot sets the rotation/scale origin.

This is the Godot/Unity-style anchor model mapped directly onto CSS flexbox — no parallel unit system.

The same SceneUI React renderer draws the tree in the editor preview and in the running game, so what you author is what ships. (At game time it mounts into ctx.uiContainer — see React HUD.)