wall cutout
This commit is contained in:
@@ -21,6 +21,7 @@ export const ViewerOverlay = () => {
|
||||
const showGuides = useViewer((s) => s.showGuides)
|
||||
const cameraMode = useViewer((s) => s.cameraMode)
|
||||
const levelMode = useViewer((s) => s.levelMode)
|
||||
const wallMode = useViewer((s) => s.wallMode)
|
||||
|
||||
const building = selection.buildingId ? (nodes[selection.buildingId] as BuildingNode | undefined) : null
|
||||
const level = selection.levelId ? (nodes[selection.levelId] as LevelNode | undefined) : null
|
||||
@@ -202,6 +203,38 @@ export const ViewerOverlay = () => {
|
||||
Solo
|
||||
</button>
|
||||
</div>
|
||||
|
||||
{/* Wall Mode */}
|
||||
<div className="flex flex-col gap-1 bg-white/80 backdrop-blur-sm rounded-lg p-2 shadow-sm border border-neutral-200">
|
||||
<span className="text-xs text-neutral-500 px-2 pb-1">Wall Mode</span>
|
||||
<button
|
||||
onClick={() => useViewer.getState().setWallMode('cutaway')}
|
||||
className={`flex items-center gap-2 px-2 py-1 rounded text-sm transition-colors ${
|
||||
wallMode === 'cutaway' ? 'bg-blue-500 text-white' : 'text-neutral-700 hover:bg-neutral-100'
|
||||
}`}
|
||||
>
|
||||
<img alt="Cutaway" height={16} src="/icons/wallcut.png" width={16} className="w-4 h-4" />
|
||||
Cutaway
|
||||
</button>
|
||||
<button
|
||||
onClick={() => useViewer.getState().setWallMode('up')}
|
||||
className={`flex items-center gap-2 px-2 py-1 rounded text-sm transition-colors ${
|
||||
wallMode === 'up' ? 'bg-blue-500 text-white' : 'text-neutral-700 hover:bg-neutral-100'
|
||||
}`}
|
||||
>
|
||||
<img alt="Full Height" height={16} src="/icons/room.png" width={16} className="w-4 h-4" />
|
||||
Full Height
|
||||
</button>
|
||||
<button
|
||||
onClick={() => useViewer.getState().setWallMode('down')}
|
||||
className={`flex items-center gap-2 px-2 py-1 rounded text-sm transition-colors ${
|
||||
wallMode === 'down' ? 'bg-blue-500 text-white' : 'text-neutral-700 hover:bg-neutral-100'
|
||||
}`}
|
||||
>
|
||||
<img alt="Low" height={16} src="/icons/walllow.png" width={16} className="w-4 h-4" />
|
||||
Low
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
)
|
||||
|
||||
@@ -18,11 +18,39 @@ const levelModeLabels: Record<'stacked' | 'exploded' | 'solo', string> = {
|
||||
|
||||
const levelModeOrder: ('stacked' | 'exploded' | 'solo')[] = ['stacked', 'exploded', 'solo']
|
||||
|
||||
type WallMode = 'up' | 'cutaway' | 'down'
|
||||
|
||||
const wallModeConfig: Record<
|
||||
WallMode,
|
||||
{ icon: React.FC<React.ComponentProps<'img'>>; label: string }
|
||||
> = {
|
||||
up: {
|
||||
icon: (props) => (
|
||||
<img alt="Full Height" height={20} src="/icons/room.png" width={20} {...props} />
|
||||
),
|
||||
label: 'Full Height',
|
||||
},
|
||||
cutaway: {
|
||||
icon: (props) => (
|
||||
<img alt="Cutaway" height={20} src="/icons/wallcut.png" width={20} {...props} />
|
||||
),
|
||||
label: 'Cutaway',
|
||||
},
|
||||
down: {
|
||||
icon: (props) => <img alt="Low" height={20} src="/icons/walllow.png" width={20} {...props} />,
|
||||
label: 'Low',
|
||||
},
|
||||
}
|
||||
|
||||
const wallModeOrder: WallMode[] = ['cutaway', 'up', 'down']
|
||||
|
||||
export function ViewToggles() {
|
||||
const cameraMode = useViewer((state) => state.cameraMode)
|
||||
const setCameraMode = useViewer((state) => state.setCameraMode)
|
||||
const levelMode = useViewer((state) => state.levelMode)
|
||||
const setLevelMode = useViewer((state) => state.setLevelMode)
|
||||
const wallMode = useViewer((state) => state.wallMode)
|
||||
const setWallMode = useViewer((state) => state.setWallMode)
|
||||
const showScans = useViewer((state) => state.showScans)
|
||||
const setShowScans = useViewer((state) => state.setShowScans)
|
||||
const showGuides = useViewer((state) => state.showGuides)
|
||||
@@ -43,6 +71,13 @@ export function ViewToggles() {
|
||||
if (nextMode) setLevelMode(nextMode)
|
||||
}
|
||||
|
||||
const cycleWallMode = () => {
|
||||
const currentIndex = wallModeOrder.indexOf(wallMode)
|
||||
const nextIndex = (currentIndex + 1) % wallModeOrder.length
|
||||
const nextMode = wallModeOrder[nextIndex]
|
||||
if (nextMode) setWallMode(nextMode)
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="flex items-center gap-1">
|
||||
{/* Camera Mode */}
|
||||
@@ -91,6 +126,31 @@ export function ViewToggles() {
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
|
||||
{/* Wall Mode */}
|
||||
<Tooltip>
|
||||
<TooltipTrigger asChild>
|
||||
<Button
|
||||
className={cn(
|
||||
'h-8 w-8 text-zinc-400 transition-all p-0',
|
||||
wallMode !== 'cutaway'
|
||||
? 'bg-emerald-500/20 text-emerald-400'
|
||||
: 'hover:bg-zinc-800',
|
||||
)}
|
||||
onClick={cycleWallMode}
|
||||
size="icon"
|
||||
variant="ghost"
|
||||
>
|
||||
{(() => {
|
||||
const Icon = wallModeConfig[wallMode].icon
|
||||
return <Icon className="h-5 w-5" />
|
||||
})()}
|
||||
</Button>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent>
|
||||
<p>Walls: {wallModeConfig[wallMode].label}</p>
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
|
||||
{/* Show Scans */}
|
||||
<Tooltip>
|
||||
<TooltipTrigger asChild>
|
||||
|
||||
Reference in New Issue
Block a user