"use client"; import { create } from "zustand"; import { BuildingNode, ItemNode } from "../schema"; import { LevelNode } from "../schema/nodes/level"; import { WallNode } from "../schema/nodes/wall"; import { AnyNode, AnyNodeId } from "../schema/types"; type SceneState = { // 1. The Data: A flat dictionary of all nodes nodes: Record; // 2. The Root: Which nodes are at the top level? rootNodeIds: AnyNodeId[]; // 3. The "Dirty" Set: For the Wall/Physics systems dirtyNodes: Set; // Actions loadScene: () => void; markDirty: (id: AnyNodeId) => void; clearDirty: (id: AnyNodeId) => void; }; const useScene = create()((set, get) => ({ // 1. Flat dictionary of all nodes nodes: {}, // 2. Root node IDs rootNodeIds: [], // 3. Dirty set dirtyNodes: new Set(), loadScene: () => { const building = BuildingNode.parse({ children: [], }); const level0 = LevelNode.parse({ level: 0, children: [], }); const level1 = LevelNode.parse({ level: 1, children: [], }); const level2 = LevelNode.parse({ level: 2, children: [], }); const wall0 = WallNode.parse({ start: [0, 0], end: [5, 0], children: [], }); const wall1 = WallNode.parse({ start: [0, 0], end: [0, 5], children: [], }); const wall2 = WallNode.parse({ start: [5, 5], end: [0, 5], children: [], }); const wall3 = WallNode.parse({ start: [5, 5], end: [5, 0], children: [], }); const window1 = ItemNode.parse({ type: "item", name: "Window", position: [2.5, 0.5, 0], asset: { category: "windows", attachTo: "wall", src: "/items/window-round/model.glb", }, }); wall0.children.push(window1.id); level0.children.push(wall0.id, wall1.id, wall2.id, wall3.id); building.children.push(level0.id, level1.id, level2.id); // Define all nodes flat const nodes: Record = { [building.id]: building, [level0.id]: level0, [level1.id]: level1, [level2.id]: level2, [wall0.id]: wall0, [wall1.id]: wall1, [wall2.id]: wall2, [wall3.id]: wall3, [window1.id]: window1, }; // Root nodes are the levels const rootNodeIds = [building.id]; get().dirtyNodes.add(wall0.id); get().dirtyNodes.add(wall1.id); get().dirtyNodes.add(wall2.id); get().dirtyNodes.add(wall3.id); set({ nodes, rootNodeIds }); }, markDirty: (id) => { get().dirtyNodes.add(id); }, clearDirty: (id) => { get().dirtyNodes.delete(id); }, })); useScene.getState().loadScene(); export default useScene;