68 lines
2.2 KiB
TypeScript
68 lines
2.2 KiB
TypeScript
import type { AnyNode } from '../../schema'
|
|
import useScene from '../../store/use-scene'
|
|
import { spatialGridManager } from './spatial-grid-manager'
|
|
|
|
export 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])
|
|
}
|