Files
xrwise-datastructure/data-structure-creator.md
luzieahrens 14de604ad2 update dcs
2026-07-04 09:03:58 +02:00

9.2 KiB
Raw Permalink Blame History

Creator Data Structure

This document describes the internal data structures used by the XRWise Creator editor.


SceneItem

A single object in the scene. Stored in the Zustand store as Record<number, SceneItem>.

type SceneItem = {
  // --- always present ---
  type:       ItemType                    // e.g. "Cube", "Camera", "Directional Light"
  category:   string                      // e.g. "Basic", "Light", "Streaming"
  position:   [number, number, number]    // world-space XYZ

  // --- transform ---
  rotation?:  number[]                    // Euler degrees [x, y, z]
  dimensions?: number[]                   // XYZ scale / size in metres

  // --- appearance ---
  color?:     string                      // hex color e.g. "#ffffff"
  opacity?:   number                      // 01

  // --- lights ---
  intensity?: number | string             // light intensity
  target?:    number[]                    // look-at point [x, y, z]

  // --- media / streaming ---
  file?:              string              // asset path or storage key
  LiveKitRoomID?:     string
  shader?:            string              // "unlit" | "lit" | "greenscreen"
  GreenScreenColor?:  string              // hex color
  GreenScreenBorderSettings?: string      // numeric string
  GreenScreenColorNear?:      string      // numeric string (01)
  widthcrop?:         number
  heightcrop?:        number
  videoJobId?:        string              // in-progress conversion job ID

  // --- text ---
  text?:       string
  fontWeight?: "light" | "regular" | "bold"
  fontSize?:   number

  // --- camera ---
  zoom?:       number                     // 110; maps to FOV = 50 / zoom

  // --- interactions ---
  grabable?:   boolean
  locked?:     boolean                    // blocks move gizmo + deletion in the editor
}

Fields by item type

Type Required fields Optional fields
Cube / Sphere / Cylinder / Cone position color, opacity, dimensions, rotation
Floor position color, opacity, dimensions, rotation
Wall position color, opacity, dimensions, rotation
Directional Light position, target color, intensity
Point Light position color, intensity
Entrance / Exit position
Billboard position, file dimensions, rotation
LiveKitStream position, LiveKitRoomID shader, GreenScreenColor, GreenScreenBorderSettings, GreenScreenColorNear, widthcrop, heightcrop, dimensions, rotation
VideoWall position file, videoJobId, widthcrop, heightcrop, dimensions, rotation
Presentation position file, dimensions, rotation
Camera position, target zoom, rotation
Text position, text color, fontSize, fontWeight, dimensions, rotation
Custom position, file dimensions, rotation
Area position dimensions (X/Z footprint only — Y is fixed), rotation

Common optional field (all types)

Field Type Description
grabable boolean Whether the item is interactable in-experience
locked boolean When true, hides the move gizmo for the item and blocks deletion until unlocked from the menubar

SceneItems

The full scene is stored as a flat map keyed by numeric ID:

type SceneItems = Record<number, SceneItem>

IDs are assigned sequentially when items are spawned and do not change.


SceneGroups

Used by the Grouping feature to let several items (or nested groups) be selected, moved, and managed as one.

type GroupChild =
  | { kind: "item"; id: number }
  | { kind: "group"; id: number }

type SceneGroup = {
  name: string
  children: GroupChild[]
}

type SceneGroups = Record<number, SceneGroup>

Group IDs are assigned sequentially from the store's nextGroupId counter, independent of item IDs. A group's children reference item/group IDs directly — there is no groupId field on SceneItem itself.


SceneStore (Zustand)

The complete editor state. Fields marked 💾 are persisted to localStorage under the key scene-storage.

Field Type Default 💾 Description
items SceneItems {} All scene objects
selected number | null null Currently selected item ID
skyColor string "#ffffff" Background color
showGrid boolean true Grid visibility
customItems CustomItem[] [] User-uploaded GLB assets
showLights boolean true Light helper visibility
showWalls boolean true Wall visibility
showAreas boolean true Area Collider visibility (Canvas Toggles)
cameraTarget number[] [0,0,0] OrbitControls look-at point
cameraRotation number[] [0,0,0] Editor camera rotation
cameraQuaternion [x,y,z,w] [0,0,0,0] Editor camera quaternion
graphicalCoding { nodes, connections } | null null Legacy node-graph coding state (superseded by blockCoding)
blockCoding { scripts: unknown[] } | null null Block Coding scripts — see Block Coding data structure
backgroundSound string | null null Uploaded ambient sound storage path (World Settings → Sound)
groups SceneGroups {} All item/group hierarchies
nextGroupId number 1 Next group ID to assign
selectedGroup number | null null Currently selected group ID
multiSelectedItems number[] [] Item IDs in a multi-select (shift-click)
multiSelectedGroups number[] [] Group IDs in a multi-select
past / future HistorySnapshot[] [] Undo/redo stacks — see Undo/Redo below
message string | null null Transient toast message
hovered number | null null Item ID currently hovered in canvas or panel
focusItem number | null null Item ID the camera should focus on
isDragging boolean false Pointer drag state
isTyping boolean false Text input focus state
orbitControls OrbitControlsImpl | null null Live OrbitControls ref
api ScreenshotAPI | null null Screenshot renderer ref

💾 reflects the partialize allowlist in lib/SceneStore.tsselectedGroup, multiSelectedItems, multiSelectedGroups, past, future, and the transient/ref fields below them are intentionally excluded, so undo history and multi-selection do not survive a page refresh.


Undo/Redo

past/future hold up to MAX_HISTORY (50) HistorySnapshots:

type HistorySnapshot = {
  items: SceneItems
  groups: SceneGroups
  nextGroupId: number
}
  • Mutations that go through setItems, updateItem, batchUpdateItems, or any group action (createGroup, createGroupFromSelection, disbandGroup, renameGroup) push the pre-change state onto past and clear future.
  • Pushes are coalesced: rapid successive edits (e.g. dragging a gizmo) within 400ms of the last push are merged into one history entry, so undo steps back per gesture rather than per frame.
  • undo()/redo() swap items/groups/nextGroupId between past/future and clear the current selection state (selectedGroup, multiSelectedItems, multiSelectedGroups).
  • History is in-memory only — it is not part of partialize and does not round-trip through save/load or the database JSON.

ITEMS_CONFIG spawn defaults

When an item is added to the scene, it is initialized with these values from items-config.tsx:

Type dimensions color rotation spawnY customAttributes
Cube [1,1,1] #ffffff [0,0,0] 0.5
Sphere [1,1,1] #ffffff [0,0,0] 0.5
Cylinder [1,1,1] #ffffff [0,0,0] 0.5
Cone [1,1,1] #ffffff [0,0,0] 0.5
Floor [10,0.1,10] #ffffff [0,0,0] 0
Wall [20,5,0.1] #ffffff [0,90,0] 2.5
Point Light [1,1,1] #ffffff [0,0,0] 5 intensity: 50, target: [0,0,0]
Directional Light [1,1,1] #ffffff [0,0,0] 5 intensity: 20, target: [0,0,0]
Entrance [1,1,1] #ffffff [0,0,0] 0.1
Exit [1,1,1] #962929 [0,0,0] 0.1
Billboard [1,1,1] #ffffff [0,0,0] 4 file: "/img/default-img.png"
LiveKitStream [1,1,1] #ffffff [0,0,0] 4 LiveKitRoomID: "Gas Station"
VideoWall [1,1,1] #ffffff [0,0,0] 4
Presentation [1,1,1] #ffffff [0,0,0] 4
Camera [1,1,1] #444444 [0,0,0] 4 zoom: 1, target: [0,0,0]
Text [0.5,0.5,0.5] black [0,0,0] 2 text: "Text", fontWeight: "regular", fontSize: 5
Custom [1,1,1] #ffffff [0,0,0] 1
Area [10,0.1,10] #ffffff [0,0,0] 0