wall tool draft

This commit is contained in:
wass08
2026-02-17 16:22:45 +09:00
parent 13fd1848d1
commit dd5f63df64
19 changed files with 553 additions and 11 deletions
@@ -11,6 +11,7 @@ import { ScanRenderer } from './scan/scan-renderer'
import { SiteRenderer } from './site/site-renderer'
import { SlabRenderer } from './slab/slab-renderer'
import { WallRenderer } from './wall/wall-renderer'
import { WindowRenderer } from './window/window-renderer'
import { ZoneRenderer } from './zone/zone-renderer'
export const NodeRenderer = ({ nodeId }: { nodeId: AnyNode['id'] }) => {
@@ -27,6 +28,7 @@ export const NodeRenderer = ({ nodeId }: { nodeId: AnyNode['id'] }) => {
{node.type === 'item' && <ItemRenderer node={node} />}
{node.type === 'slab' && <SlabRenderer node={node} />}
{node.type === 'wall' && <WallRenderer node={node} />}
{node.type === 'window' && <WindowRenderer node={node} />}
{node.type === 'zone' && <ZoneRenderer node={node} />}
{node.type === 'roof' && <RoofRenderer node={node} />}
{node.type === 'scan' && <ScanRenderer node={node} />}
@@ -0,0 +1,24 @@
import { useRegistry, type WindowNode } from '@pascal-app/core'
import { useRef } from 'react'
import type { Mesh } from 'three'
export const WindowRenderer = ({ node }: { node: WindowNode }) => {
const ref = useRef<Mesh>(null!)
useRegistry(node.id, 'window', ref)
return (
<mesh
ref={ref}
castShadow
receiveShadow
visible={node.visible}
position={node.position}
rotation={node.rotation}
>
{/* WindowSystem replaces this geometry each time the node is dirty */}
<boxGeometry args={[0, 0, 0]} />
<meshStandardMaterial color="#d1d5db" />
</mesh>
)
}
@@ -1,6 +1,6 @@
'use client'
import { CeilingSystem, ItemSystem, RoofSystem, SlabSystem, WallSystem } from '@pascal-app/core'
import { CeilingSystem, ItemSystem, RoofSystem, SlabSystem, WallSystem, WindowSystem } from '@pascal-app/core'
import { Bvh } from '@react-three/drei'
import { Canvas, extend, type ThreeToJSXElements } from '@react-three/fiber'
import * as THREE from 'three/webgpu'
@@ -65,6 +65,7 @@ const Viewer: React.FC<ViewerProps> = ({ children, selectionManager = 'default'
<RoofSystem />
<SlabSystem />
<WallSystem />
<WindowSystem />
<ZoneSystem />
<PostProcessing />
@@ -28,6 +28,7 @@ type SelectableNodeType =
| 'level'
| 'zone'
| 'wall'
| 'window'
| 'item'
| 'slab'
| 'ceiling'
@@ -192,9 +193,9 @@ const getStrategy = (): SelectionStrategy | null => {
}
}
// Zone selected -> can select/hover contents (walls, items, slabs, ceilings, roofs)
// Zone selected -> can select/hover contents (walls, items, slabs, ceilings, roofs, windows)
return {
types: ['wall', 'item', 'slab', 'ceiling', 'roof'],
types: ['wall', 'item', 'slab', 'ceiling', 'roof', 'window'],
handleClick: (node) => {
const { selectedIds } = useViewer.getState().selection
// Toggle selection - if already selected, deselect; otherwise select
@@ -216,7 +217,7 @@ const getStrategy = (): SelectionStrategy | null => {
}
},
isValid: (node) => {
const validTypes = ['wall', 'item', 'slab', 'ceiling', 'roof']
const validTypes = ['wall', 'item', 'slab', 'ceiling', 'roof', 'window']
if (!validTypes.includes(node.type)) return false
return isNodeInZone(node, levelId, zoneId)
},
@@ -268,6 +269,7 @@ export const SelectionManager = () => {
'slab',
'ceiling',
'roof',
'window',
]
for (const type of allTypes) {
emitter.on(`${type}:enter`, onEnter)