Squash merge of 3 commits: 1. useLiveTransforms store for 2D/3D decoupling + floorplan overhaul + Sentry crash fixes 2. Comprehensive 59-file sync bringing editor to full monorepo parity (selection highlights, delete tool, furnish/zone modes, keyboard shortcuts, all panels) 3. Missing files fix (materials.ts, merged-outline-node.ts, type fix) 75 files changed, ~6K additions.
49 lines
1.7 KiB
TypeScript
Executable File
49 lines
1.7 KiB
TypeScript
Executable File
'use client'
|
|
|
|
import { sceneRegistry, useScene, type ZoneNode } from '@pascal-app/core'
|
|
import { useViewer } from '@pascal-app/viewer'
|
|
import { useFrame } from '@react-three/fiber'
|
|
import type { Mesh } from 'three'
|
|
import useEditor from '../store/use-editor'
|
|
|
|
export const ViewerZoneSystem = () => {
|
|
useFrame(() => {
|
|
const { levelId, zoneId } = useViewer.getState().selection
|
|
const structureLayer = useEditor.getState().structureLayer
|
|
const nodes = useScene.getState().nodes
|
|
|
|
sceneRegistry.byType.zone.forEach((id) => {
|
|
const obj = sceneRegistry.nodes.get(id)
|
|
if (!obj) return
|
|
|
|
const zone = nodes[id as ZoneNode['id']] as ZoneNode | undefined
|
|
if (!zone) return
|
|
|
|
const isOnSelectedLevel = zone.parentId === levelId
|
|
|
|
// Keep group visible (so <Html> labels stay active), hide/show meshes only.
|
|
// Zone geometry: visible in zone mode on the right level, OR when this zone is selected.
|
|
// The editor ZoneSystem handles the selected zone's opacity animation.
|
|
const isSelected = id === zoneId
|
|
const shouldShowGeometry =
|
|
(structureLayer === 'zones' && !!levelId && isOnSelectedLevel) || isSelected
|
|
if (!obj.visible) obj.visible = true
|
|
obj.traverse((child) => {
|
|
if ((child as Mesh).isMesh) {
|
|
child.visible = shouldShowGeometry
|
|
}
|
|
})
|
|
|
|
// Labels: always visible on the current level (regardless of mode or zone selection)
|
|
const showLabel = !!levelId && isOnSelectedLevel
|
|
const targetOpacity = showLabel ? '1' : '0'
|
|
const labelEl = document.getElementById(`${id}-label`)
|
|
if (labelEl && labelEl.style.opacity !== targetOpacity) {
|
|
labelEl.style.opacity = targetOpacity
|
|
}
|
|
})
|
|
})
|
|
|
|
return null
|
|
}
|