Remove material strips from roof, stair, and fence panels

This commit is contained in:
sudhir
2026-05-20 00:50:47 +00:00
committed by open-pascal
parent 4fc57a6fd9
commit 023cd511e9
4 changed files with 16 additions and 105 deletions
-48
View File
@@ -3,8 +3,6 @@
import {
type AnyNode,
type AnyNodeId,
getEffectiveRoofSurfaceMaterial,
type MaterialSchema,
type RoofNode,
type RoofSegmentNode,
RoofSegmentNode as RoofSegmentNodeSchema,
@@ -33,7 +31,6 @@ export default function RoofPanel() {
const updateNode = useScene((s) => s.updateNode)
const createNode = useScene((s) => s.createNode)
const setMovingNode = useEditor((s) => s.setMovingNode)
const selectedMaterialTarget = useEditor((s) => s.selectedMaterialTarget)
const node = useScene((s) =>
selectedId ? (s.nodes[selectedId as AnyNode['id']] as RoofNode | undefined) : undefined,
@@ -56,35 +53,6 @@ export default function RoofPanel() {
[selectedId, updateNode],
)
const materialTargetRole =
selectedMaterialTarget &&
selectedMaterialTarget.nodeId === node?.id &&
(selectedMaterialTarget.role === 'top' ||
selectedMaterialTarget.role === 'edge' ||
selectedMaterialTarget.role === 'wall')
? selectedMaterialTarget.role
: null
const materialPickerValue =
node && materialTargetRole ? getEffectiveRoofSurfaceMaterial(node, materialTargetRole) : {}
const handleTargetedMaterialChange = useCallback(
(material: MaterialSchema) => {
if (!(node && materialTargetRole)) return
handleUpdate(buildRoofSurfaceMaterialPatch(node, materialTargetRole, material, undefined))
},
[handleUpdate, materialTargetRole, node],
)
const handleTargetedMaterialPresetChange = useCallback(
(materialPreset: string) => {
if (!(node && materialTargetRole)) return
handleUpdate(
buildRoofSurfaceMaterialPatch(node, materialTargetRole, undefined, materialPreset),
)
},
[handleUpdate, materialTargetRole, node],
)
const handleClose = useCallback(() => {
setSelection({ selectedIds: [] })
}, [setSelection])
@@ -260,22 +228,6 @@ export default function RoofPanel() {
/>
</ActionGroup>
</PanelSection>
<PanelSection title="Material">
{materialTargetRole ? null : (
<div className="mb-3 rounded-lg border border-border/50 bg-[#2C2C2E] px-3 py-2 text-[11px] text-muted-foreground">
Click the roof surface you want to edit. Materials apply to one target at a time.
</div>
)}
<MaterialPicker
disabled={!materialTargetRole}
hideSideControl
nodeType="roof"
onChange={handleTargetedMaterialChange}
onSelectMaterialPreset={handleTargetedMaterialPresetChange}
selectedMaterialPreset={materialPickerValue.materialPreset}
value={materialPickerValue.material}
/>
</PanelSection>
</PanelWrapper>
)
}
+5 -2
View File
@@ -1,8 +1,8 @@
'use client'
import { type RoofNode, useRegistry } from '@pascal-app/core'
import { type RoofNode, useRegistry, useScene } from '@pascal-app/core'
import { getRoofMaterialArray, NodeRenderer, useNodeEvents, useViewer } from '@pascal-app/viewer'
import { useEffect, useMemo, useRef } from 'react'
import { useEffect, useLayoutEffect, useMemo, useRef } from 'react'
import * as THREE from 'three'
import { roofDebugMaterials, roofMaterials } from './roof-materials'
@@ -10,6 +10,9 @@ export const RoofRenderer = ({ node }: { node: RoofNode }) => {
const ref = useRef<THREE.Group>(null!)
useRegistry(node.id, 'roof', ref)
useLayoutEffect(() => {
useScene.getState().markDirty(node.id)
}, [node.id])
const handlers = useNodeEvents(node, 'roof')
const debugColors = useViewer((s) => s.debugColors)
-48
View File
@@ -3,9 +3,7 @@
import {
type AnyNode,
type AnyNodeId,
getEffectiveStairSurfaceMaterial,
type LevelNode,
type MaterialSchema,
type StairNode,
type StairRailingMode,
type StairSegmentNode,
@@ -66,7 +64,6 @@ export default function StairPanel() {
const updateNode = useScene((s) => s.updateNode)
const createNode = useScene((s) => s.createNode)
const setMovingNode = useEditor((s) => s.setMovingNode)
const selectedMaterialTarget = useEditor((s) => s.selectedMaterialTarget)
const node = useScene((s) =>
selectedId ? (s.nodes[selectedId as AnyNode['id']] as StairNode | undefined) : undefined,
@@ -97,35 +94,6 @@ export default function StairPanel() {
[selectedId, updateNode],
)
const materialTargetRole =
selectedMaterialTarget &&
selectedMaterialTarget.nodeId === node?.id &&
(selectedMaterialTarget.role === 'railing' ||
selectedMaterialTarget.role === 'tread' ||
selectedMaterialTarget.role === 'side')
? selectedMaterialTarget.role
: null
const materialPickerValue =
node && materialTargetRole ? getEffectiveStairSurfaceMaterial(node, materialTargetRole) : {}
const handleTargetedMaterialChange = useCallback(
(material: MaterialSchema) => {
if (!(node && materialTargetRole)) return
handleUpdate(buildStairSurfaceMaterialPatch(node, materialTargetRole, material, undefined))
},
[handleUpdate, materialTargetRole, node],
)
const handleTargetedMaterialPresetChange = useCallback(
(materialPreset: string) => {
if (!(node && materialTargetRole)) return
handleUpdate(
buildStairSurfaceMaterialPatch(node, materialTargetRole, undefined, materialPreset),
)
},
[handleUpdate, materialTargetRole, node],
)
const handleClose = useCallback(() => {
setSelection({ selectedIds: [] })
}, [setSelection])
@@ -557,22 +525,6 @@ export default function StairPanel() {
/>
</ActionGroup>
</PanelSection>
<PanelSection title="Material">
{materialTargetRole ? null : (
<div className="mb-3 rounded-lg border border-border/50 bg-[#2C2C2E] px-3 py-2 text-[11px] text-muted-foreground">
Click the stair surface you want to edit. Materials apply to one target at a time.
</div>
)}
<MaterialPicker
disabled={!materialTargetRole}
hideSideControl
nodeType="stair"
onChange={handleTargetedMaterialChange}
onSelectMaterialPreset={handleTargetedMaterialPresetChange}
selectedMaterialPreset={materialPickerValue.materialPreset}
value={materialPickerValue.material}
/>
</PanelSection>
</PanelWrapper>
)
}
@@ -126,15 +126,19 @@ export const RoofSystem = () => {
pendingRoofUpdates.delete(id)
continue
}
const group = sceneRegistry.nodes.get(id) as THREE.Group
if (group) {
const mergedMesh = group.getObjectByName('merged-roof') as THREE.Mesh | undefined
if (mergedMesh?.visible !== false) {
// Only rebuild when visible — RoofEditSystem re-triggers via markDirty on edit mode exit
updateMergedRoofGeometry(node as RoofNode, group, nodes)
roofsProcessed++
}
if (!group) continue
const mergedMesh = group.getObjectByName('merged-roof') as THREE.Mesh | undefined
if (!mergedMesh) continue
if (mergedMesh.visible !== false) {
// Only rebuild when visible — RoofEditSystem re-triggers via markDirty on edit mode exit
updateMergedRoofGeometry(node as RoofNode, group, nodes)
roofsProcessed++
}
pendingRoofUpdates.delete(id)
}
}, 5) // Priority 5: run after all other systems have settled