From 9c5f8dde79cb9a3f74267021bab2ec62f562d7f2 Mon Sep 17 00:00:00 2001 From: luzieahrens Date: Tue, 9 Jun 2026 08:46:59 +0200 Subject: [PATCH] Initial commit: creator and database data structure docs --- data-structure-creator.md | 139 ++++++++++++++++++++++++++++++++++++ data-structure-database.md | 142 +++++++++++++++++++++++++++++++++++++ 2 files changed, 281 insertions(+) create mode 100644 data-structure-creator.md create mode 100644 data-structure-database.md diff --git a/data-structure-creator.md b/data-structure-creator.md new file mode 100644 index 0000000..70e4f90 --- /dev/null +++ b/data-structure-creator.md @@ -0,0 +1,139 @@ +# 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`. + +```ts +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 // 0–1 + + // --- 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 (0–1) + widthcrop?: number + heightcrop?: number + videoJobId?: string // in-progress conversion job ID + + // --- text --- + text?: string + fontWeight?: "light" | "regular" | "bold" + fontSize?: number + + // --- camera --- + zoom?: number // 1–10; maps to FOV = 50 / zoom + + // --- interactions --- + grabable?: boolean +} +``` + +### 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` | + +### Common optional field (all types) + +| Field | Type | Description | +|---|---|---| +| `grabable` | `boolean` | Whether the item is interactable in-experience | + +--- + +## `SceneItems` + +The full scene is stored as a flat map keyed by numeric ID: + +```ts +type SceneItems = Record +``` + +IDs are assigned sequentially when items are spawned and do not change. + +--- + +## `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 | +| `showDummy` | `boolean` | `false` | ✅ | Stickman dummy visibility | +| `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 | +| `message` | `string \| null` | `null` | — | Transient toast message | +| `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 | + +--- + +## `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` | — | diff --git a/data-structure-database.md b/data-structure-database.md new file mode 100644 index 0000000..d6fdec7 --- /dev/null +++ b/data-structure-database.md @@ -0,0 +1,142 @@ +# Database Data Structure + +This document describes the JSON format saved to and loaded from the database. + +--- + +## Top-level: `RoomExport` + +```json +{ + "guid": "string", + "skybox": "string | null", + "sky-color": "#rrggbb", + "jsonversion": 2.0, + "items": [ ...RoomItem ] +} +``` + +| Field | Type | Description | +|---|---|---| +| `guid` | `string` | Unique room identifier | +| `skybox` | `string \| null` | Skybox asset path (currently unused) | +| `sky-color` | `string` | Background hex color | +| `jsonversion` | `number` | Schema version (`2.0`) | +| `items` | `RoomItem[]` | All objects in the room | + +--- + +## `RoomItem` + +Every item in the `items` array shares this base shape: + +```json +{ + "position": { "x": 0.0, "y": 0.0, "z": 0.0 }, + "rotation": { "x": 0.0, "y": 0.0, "z": 0.0 }, + "scale": { "x": 1.0, "y": 1.0, "z": 1.0 }, + "type": "pre-defined | user-defined", + "resourcename": "string", + "item-custom-args": [ ...ItemArg ], + "item-custom-args-adv": null +} +``` + +> **Coordinate system note:** The X-axis is flipped on save (`x` = `-creator_x`) and un-flipped on load. Y-axis rotation is also negated. + +### `ItemArg` + +```json +{ "argument": "key", "value": "value_as_string" } +``` + +All values are serialized as strings. + +--- + +## Per-type `resourcename` and custom args + +### Basic shapes + +| Creator type | `resourcename` | Custom args | +|---|---|---| +| `Cube` | `Cube` | `color`, `opacity` | +| `Sphere` | `Sphere` | `color` | +| `Cylinder` | `Cylinder` | `color` | +| `Cone` | `Cone` | `color` | +| `Floor` | `Plane` | `color`, `opacity` | +| `Wall` | `Wall` | `color`, `opacity` | + +### Lights + +| Creator type | `resourcename` | Custom args | +|---|---|---| +| `Directional Light` | `Directional Light` | `color`, `intensity`, `target` (`"x,y,z"`) | +| `Point Light` | `Point Light` | `color`, `intensity` | + +### Room access + +| Creator type | `resourcename` | Custom args | +|---|---|---| +| `Entrance` | `Entrance` | _(none)_ | +| `Exit` | _(not implemented in save)_ | — | + +### Streaming / media + +| Creator type | `resourcename` | Custom args | +|---|---|---| +| `Billboard` | `Billboard` | `url` (file path) | +| `LiveKitStream` | `LiveKitStream` | `LiveKitRoomID`, `shader`, `GreenScreenColor`, `GreenScreenBorderSettings`, `GreenScreenColorNear`, `widthcrop`, `heightcrop` | +| `VideoWall` | `VideoWall` | `file`, `widthcrop`, `heightcrop` | +| `Presentation` | `Presentation` | `file` | +| `Camera` | `CCTVCamera` | `target` (`"x,y,z"`), `fov` (derived: `zoom * 60`) | + +### Other + +| Creator type | `resourcename` | `type` field | Custom args | +|---|---|---|---| +| `Text` | `Text` | `pre-defined` | `text`, `color`, `fontSize`, `fontWeight` | +| `Custom` | _(the asset filename)_ | `user-defined` | `file` | + +### Common optional arg (all types) + +| Arg | Type | Description | +|---|---|---| +| `grabable` | `"true" \| "false"` | Whether the item can be grabbed in-experience | + +--- + +## Example — Directional Light + +```json +{ + "position": { "x": 0, "y": 5, "z": 0 }, + "rotation": { "x": 0, "y": 0, "z": 0 }, + "scale": { "x": 1, "y": 1, "z": 1 }, + "type": "pre-defined", + "resourcename": "Directional Light", + "item-custom-args": [ + { "argument": "color", "value": "#ffffff" }, + { "argument": "intensity", "value": "20" }, + { "argument": "target", "value": "0,0,0" } + ], + "item-custom-args-adv": null +} +``` + +## Example — CCTV Camera + +```json +{ + "position": { "x": 0, "y": 4, "z": 0 }, + "rotation": { "x": 0, "y": 0, "z": 0 }, + "scale": { "x": 1, "y": 1, "z": 1 }, + "type": "pre-defined", + "resourcename": "CCTVCamera", + "item-custom-args": [ + { "argument": "target", "value": "0,0,0" }, + { "argument": "fov", "value": "60" } + ], + "item-custom-args-adv": null +} +```