excellent selection

This commit is contained in:
wass08
2026-01-30 09:01:17 +09:00
parent be6a766586
commit bda893fcf5
4 changed files with 183 additions and 36 deletions
+29 -29
View File
@@ -26,38 +26,38 @@ interface ViewerProps {
const Viewer: React.FC<ViewerProps> = ({ children, selectionManager = 'default' }) => {
return (
<Canvas
className={'bg-[#303035]'}
gl={async (props) => {
const renderer = new THREE.WebGPURenderer(props as any)
await renderer.init()
return renderer
}}
shadows
camera={{ position: [50, 50, 50], fov: 50 }}
>
<color attach="background" args={['#ececec']} />
<ViewerCamera />
className={'bg-[#303035]'}
gl={async (props) => {
const renderer = new THREE.WebGPURenderer(props as any)
await renderer.init()
return renderer
}}
shadows
camera={{ position: [50, 50, 50], fov: 50 }}
>
<color attach="background" args={['#ececec']} />
<ViewerCamera />
<directionalLight position={[10, 10, 5]} intensity={0.5} castShadow />
<Environment preset="sunset" environmentIntensity={0.3} />
<Bvh>
<SceneRenderer />
</Bvh>
<directionalLight position={[10, 10, 5]} intensity={0.5} castShadow />
<Environment preset="sunset" environmentIntensity={0.3} />
<Bvh>
<SceneRenderer />
</Bvh>
{/* Default Systems */}
<LevelSystem />
<GuideSystem />
<ScanSystem />
{/* Core systems */}
<CeilingSystem />
<ItemSystem />
<RoofSystem />
<SlabSystem />
<WallSystem />
<PostProcessing />
{/* Default Systems */}
<LevelSystem />
<GuideSystem />
<ScanSystem />
{/* Core systems */}
<CeilingSystem />
<ItemSystem />
<RoofSystem />
<SlabSystem />
<WallSystem />
<PostProcessing />
{selectionManager === 'default' && <SelectionManager />}
{children}
{selectionManager === 'default' && <SelectionManager />}
{children}
</Canvas>
)
}
@@ -111,14 +111,26 @@ const getStrategy = (): SelectionStrategy | null => {
}
}
// Zone selected -> can hover contents (walls, items, slabs, ceilings, roofs)
// Zone selected -> can select/hover contents (walls, items, slabs, ceilings, roofs)
return {
types: ['wall', 'item', 'slab', 'ceiling', 'roof'],
handleClick: () => {
// No action on click at zone content level
handleClick: (node) => {
const { selectedIds } = useViewer.getState().selection
// Toggle selection - if already selected, deselect; otherwise select
if (selectedIds.includes(node.id)) {
useViewer.getState().setSelection({ selectedIds: selectedIds.filter((id) => id !== node.id) })
} else {
useViewer.getState().setSelection({ selectedIds: [node.id] })
}
},
handleDeselect: () => {
useViewer.getState().setSelection({ zoneId: null })
const { selectedIds } = useViewer.getState().selection
// If items are selected, deselect them first; otherwise go back to level
if (selectedIds.length > 0) {
useViewer.getState().setSelection({ selectedIds: [] })
} else {
useViewer.getState().setSelection({ zoneId: null })
}
},
isValid: (node) => {
const validTypes = ['wall', 'item', 'slab', 'ceiling', 'roof']
@@ -222,12 +234,17 @@ const PointerMissedHandler = ({ clickHandledRef }: { clickHandledRef: React.Muta
}
const OutlinerSync = () => {
const selection = useViewer((s) => s.selection)
const hoveredId = useViewer((s) => s.hoveredId)
const outliner = useViewer((s) => s.outliner)
useEffect(() => {
// Clear selected objects - we only show hover in viewer
// Sync selected objects
outliner.selectedObjects.length = 0
for (const id of selection.selectedIds) {
const obj = sceneRegistry.nodes.get(id)
if (obj) outliner.selectedObjects.push(obj)
}
// Sync hovered objects
outliner.hoveredObjects.length = 0
@@ -235,7 +252,7 @@ const OutlinerSync = () => {
const obj = sceneRegistry.nodes.get(hoveredId)
if (obj) outliner.hoveredObjects.push(obj)
}
}, [hoveredId, outliner])
}, [selection, hoveredId, outliner])
return null
}