describe data structure blocks
This commit is contained in:
@@ -0,0 +1,159 @@
|
||||
# Block Coding — Database Save Format
|
||||
|
||||
This document describes the JSON structure stored in the Supabase `rooms` table under the `graphical_coding` column for the block coding system (replacing the old node-graph format).
|
||||
|
||||
---
|
||||
|
||||
## Top-level shape
|
||||
|
||||
```json
|
||||
{
|
||||
"scripts": [ ...BlockScript ]
|
||||
}
|
||||
```
|
||||
|
||||
The entire block coding state is one JSON blob — a flat array of scripts. Each script is self-contained (trigger + effects) with no cross-script references.
|
||||
|
||||
---
|
||||
|
||||
## `BlockScript`
|
||||
|
||||
```json
|
||||
{
|
||||
"id": "bl-1-1234567890",
|
||||
"trigger": { ...TriggerBlock },
|
||||
"effects": [ ...EffectBlock ]
|
||||
}
|
||||
```
|
||||
|
||||
| Field | Type | Description |
|
||||
|---|---|---|
|
||||
| `id` | `string` | Unique script identifier, format `bl-<index>-<timestamp>` |
|
||||
| `trigger` | `TriggerBlock` | The single trigger block at the top of the script |
|
||||
| `effects` | `EffectBlock[]` | Ordered list of effect blocks stacked below the trigger |
|
||||
|
||||
---
|
||||
|
||||
## `TriggerBlock`
|
||||
|
||||
```json
|
||||
{
|
||||
"id": "bl-2-1234567890",
|
||||
"event": "clicked",
|
||||
"sourceItemId": 3,
|
||||
"radius": 5,
|
||||
"exitRadius": 5,
|
||||
"cooldown": 500
|
||||
}
|
||||
```
|
||||
|
||||
| Field | Type | Description |
|
||||
|---|---|---|
|
||||
| `id` | `string` | Unique block identifier |
|
||||
| `event` | `"clicked" \| "proximity_enter" \| "proximity_exit"` | The interaction event to watch for |
|
||||
| `sourceItemId` | `number \| null` | Scene item ID to watch (`null` = no item selected yet) |
|
||||
| `radius` | `number` | Proximity enter radius in metres (only used when `event` is `"proximity_enter"`) |
|
||||
| `exitRadius` | `number` | Proximity exit radius in metres (only used when `event` is `"proximity_exit"`) |
|
||||
| `cooldown` | `number` | Minimum milliseconds between consecutive firings |
|
||||
|
||||
---
|
||||
|
||||
## `EffectBlock`
|
||||
|
||||
All fields are always present regardless of `effectProp`. Fields that are irrelevant to the chosen property are stored but ignored at runtime.
|
||||
|
||||
```json
|
||||
{
|
||||
"id": "bl-3-1234567890",
|
||||
"effectProp": "color",
|
||||
"targetObjectType": "item",
|
||||
"targetItemId": 7,
|
||||
"targetColor": "#ff3366",
|
||||
"positionAxis": "x",
|
||||
"targetPositionValue": 0,
|
||||
"rotationAxis": "x",
|
||||
"targetRotationValue": 0,
|
||||
"targetScale": 1,
|
||||
"targetVisibility": true,
|
||||
"toggle": true
|
||||
}
|
||||
```
|
||||
|
||||
| Field | Type | Description |
|
||||
|---|---|---|
|
||||
| `id` | `string` | Unique block identifier |
|
||||
| `effectProp` | `"color" \| "position" \| "rotation" \| "scale" \| "visibility"` | Which property this block modifies |
|
||||
| `targetObjectType` | `"item" \| "sky"` | Whether to target a scene item or the sky color |
|
||||
| `targetItemId` | `number \| null` | Scene item ID (only relevant when `targetObjectType` is `"item"`) |
|
||||
| `targetColor` | `string` | Target hex color (used when `effectProp` is `"color"`) |
|
||||
| `positionAxis` | `"x" \| "y" \| "z"` | Axis to move along (used when `effectProp` is `"position"`) |
|
||||
| `targetPositionValue` | `number` | Target position on the chosen axis in world units |
|
||||
| `rotationAxis` | `"x" \| "y" \| "z"` | Axis to rotate around (used when `effectProp` is `"rotation"`) |
|
||||
| `targetRotationValue` | `number` | Target rotation angle in degrees |
|
||||
| `targetScale` | `number` | Uniform scale multiplier (used when `effectProp` is `"scale"`) |
|
||||
| `targetVisibility` | `boolean` | `true` = visible, `false` = hidden (used when `effectProp` is `"visibility"`) |
|
||||
| `toggle` | `boolean` | When `true`, each trigger alternates between current state and target value instead of always applying the target. Not available for `"visibility"`. |
|
||||
|
||||
---
|
||||
|
||||
## Full example
|
||||
|
||||
A script that changes a cube's color and moves it along X when a visitor clicks it, using toggle mode so each click alternates between states:
|
||||
|
||||
```json
|
||||
{
|
||||
"scripts": [
|
||||
{
|
||||
"id": "bl-1-1700000000001",
|
||||
"trigger": {
|
||||
"id": "bl-2-1700000000002",
|
||||
"event": "clicked",
|
||||
"sourceItemId": 4,
|
||||
"radius": 5,
|
||||
"exitRadius": 5,
|
||||
"cooldown": 300
|
||||
},
|
||||
"effects": [
|
||||
{
|
||||
"id": "bl-3-1700000000003",
|
||||
"effectProp": "color",
|
||||
"targetObjectType": "item",
|
||||
"targetItemId": 4,
|
||||
"targetColor": "#c05580",
|
||||
"positionAxis": "x",
|
||||
"targetPositionValue": 0,
|
||||
"rotationAxis": "x",
|
||||
"targetRotationValue": 0,
|
||||
"targetScale": 1,
|
||||
"targetVisibility": true,
|
||||
"toggle": true
|
||||
},
|
||||
{
|
||||
"id": "bl-4-1700000000004",
|
||||
"effectProp": "position",
|
||||
"targetObjectType": "item",
|
||||
"targetItemId": 4,
|
||||
"targetColor": "#ffffff",
|
||||
"positionAxis": "x",
|
||||
"targetPositionValue": 3.0,
|
||||
"rotationAxis": "x",
|
||||
"targetRotationValue": 0,
|
||||
"targetScale": 1,
|
||||
"targetVisibility": true,
|
||||
"toggle": true
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Persistence notes
|
||||
|
||||
- **Column:** `graphical_coding` (JSONB) in the Supabase `rooms` table — same column as the old node-graph format; the schema is distinguished by the presence of `scripts` (block coding) vs `nodes`/`connections` (legacy).
|
||||
- **Save:** the Zustand `blockCoding` store value is JSON-stringified and sent as `graphical_coding` in the `FormData` of `PATCH /api/save-room/[id]`, which writes it directly to the `graphical_coding` column.
|
||||
- **Load:** `roomData.graphical_coding` is read in `creator.tsx` and hydrated into `setBlockCoding(gc)` in the Zustand store.
|
||||
- **Local cache:** Zustand's `persist` middleware also writes the value to `localStorage` under the key `"scene-storage"`, so edits survive a page refresh before an explicit save.
|
||||
- **TypeScript types:** defined inline in `components/creator/graphical-coding/graphical-coding-panel.tsx` as `TriggerBlock`, `EffectBlock`, and `BlockScript`.
|
||||
Reference in New Issue
Block a user