68 lines
2.2 KiB
TypeScript
68 lines
2.2 KiB
TypeScript
import { AnyNode } from "../../schema";
|
|
import useScene from "../../store/use-scene";
|
|
import { spatialGridManager } from "./spatial-grid-manager";
|
|
|
|
function resolveLevelId(node: AnyNode, nodes: Record<string, AnyNode>): string {
|
|
// If the node itself is a level
|
|
if (node.type === "level") return node.id;
|
|
|
|
// Walk up parent chain to find level
|
|
// This assumes you track parentId or can derive it
|
|
let current: AnyNode | undefined = node;
|
|
|
|
while (current) {
|
|
if (current.type === "level") return current.id;
|
|
// Find parent (you might need to add parentId to your schema or derive it)
|
|
if (!current.parentId) {
|
|
current = undefined;
|
|
} else {
|
|
current = nodes[current.parentId];
|
|
}
|
|
}
|
|
|
|
return "default"; // fallback for orphaned items
|
|
}
|
|
|
|
// Call this once at app initialization
|
|
export function initSpatialGridSync() {
|
|
const store = useScene;
|
|
|
|
// Subscribe to all changes
|
|
store.subscribe((state, prevState) => {
|
|
// Detect added nodes
|
|
for (const [id, node] of Object.entries(state.nodes)) {
|
|
if (!prevState.nodes[id as AnyNode["id"]]) {
|
|
const levelId = resolveLevelId(node, state.nodes);
|
|
spatialGridManager.handleNodeCreated(node, levelId);
|
|
}
|
|
}
|
|
|
|
// Detect removed nodes
|
|
for (const [id, node] of Object.entries(prevState.nodes)) {
|
|
if (!state.nodes[id as AnyNode["id"]]) {
|
|
const levelId = resolveLevelId(node, prevState.nodes);
|
|
spatialGridManager.handleNodeDeleted(id, node.type, levelId);
|
|
}
|
|
}
|
|
|
|
// Detect updated nodes (items with position/rotation/parentId changes)
|
|
for (const [id, node] of Object.entries(state.nodes)) {
|
|
const prev = prevState.nodes[id as AnyNode["id"]];
|
|
if (prev && node.type === "item" && prev.type === "item") {
|
|
if (
|
|
!arraysEqual(node.position, prev.position) ||
|
|
!arraysEqual(node.rotation, prev.rotation) ||
|
|
node.parentId !== prev.parentId
|
|
) {
|
|
const levelId = resolveLevelId(node, state.nodes);
|
|
spatialGridManager.handleNodeUpdated(node, levelId);
|
|
}
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
function arraysEqual(a: number[], b: number[]): boolean {
|
|
return a.length === b.length && a.every((v, i) => v === b[i]);
|
|
}
|