From a796c0fd0addcc1b78b016e67516f517f710c36c Mon Sep 17 00:00:00 2001 From: sudhir Date: Mon, 27 Apr 2026 10:57:50 +0530 Subject: [PATCH] Move item dimensions into local item overlays --- .../src/components/editor/floorplan-panel.tsx | 29 +++++++------- .../tools/item/use-placement-coordinator.tsx | 38 +++++++++++++------ 2 files changed, 40 insertions(+), 27 deletions(-) diff --git a/packages/editor/src/components/editor/floorplan-panel.tsx b/packages/editor/src/components/editor/floorplan-panel.tsx index c9f04231..ff326927 100644 --- a/packages/editor/src/components/editor/floorplan-panel.tsx +++ b/packages/editor/src/components/editor/floorplan-panel.tsx @@ -4137,6 +4137,7 @@ const FloorplanNodeLayer = memo(function FloorplanNodeLayer({ palette, selectedIdSet, stairEntries, + unit, }: { canFocusItems: boolean canFocusStairs: boolean @@ -4161,12 +4162,15 @@ const FloorplanNodeLayer = memo(function FloorplanNodeLayer({ palette: FloorplanPalette selectedIdSet: ReadonlySet stairEntries: FloorplanStairEntry[] + unit: 'metric' | 'imperial' }) { if (itemEntries.length === 0 && stairEntries.length === 0) { return null } - const itemNodes = itemEntries.map(({ item, points, polygon }) => { + const itemNodes = itemEntries.map((itemEntry) => { + const { item, points, polygon } = itemEntry + const itemDimensionMeasurements = getItemDimensionMeasurementOverlays(itemEntry, unit) const isSelected = selectedIdSet.has(item.id) const isHighlighted = highlightedIdSet.has(item.id) const isHovered = hoveredItemId === item.id @@ -4309,6 +4313,13 @@ const FloorplanNodeLayer = memo(function FloorplanNodeLayer({ y2={toSvgY(diagonalBEnd.y)} /> )} + {itemDimensionMeasurements.length > 0 ? ( + + ) : null} ) }) @@ -6776,15 +6787,6 @@ export function FloorplanPanel() { isFenceEndpointMoveActive || isFloorItemBuildActive || isFloorItemMoveActive - const itemPlacementDimensionMeasurements = useMemo(() => { - if (!isItemPlacementPreviewActive) { - return [] as LinearMeasurementOverlay[] - } - - return floorplanItemEntries.flatMap((itemEntry) => - getItemDimensionMeasurementOverlays(itemEntry, unit), - ) - }, [floorplanItemEntries, isItemPlacementPreviewActive, unit]) const floorplanPreviewStairSegment = useMemo( () => StairSegmentNodeSchema.parse({ @@ -11988,6 +11990,7 @@ export function FloorplanPanel() { palette={palette} selectedIdSet={selectedIdSet} stairEntries={renderedFloorplanStairEntries} + unit={unit} /> - - (null) const meshPreviewAppliedRef = useRef(false) const dimensionBoundsRef = useRef(null) + const [measurementTargetState, setMeasurementTargetState] = useState<{ + id: string + object: Object3D + } | null>(null) // Store config callbacks in refs to avoid re-running effect when they change const configRef = useRef(config) @@ -1172,6 +1176,12 @@ export function usePlacementCoordinator(config: PlacementCoordinatorConfig): Rea if (!draftNode.current) return const mesh = sceneRegistry.nodes.get(draftNode.current.id) if (!mesh) return + if ( + measurementTargetState?.id !== draftNode.current.id || + measurementTargetState.object !== mesh + ) { + setMeasurementTargetState({ id: draftNode.current.id, object: mesh }) + } if (!meshPreviewAppliedRef.current) { const previewBounds = getPreviewBoundsFromObject(mesh) @@ -1207,10 +1217,6 @@ export function usePlacementCoordinator(config: PlacementCoordinatorConfig): Rea draftNode.current.rotation, ) mesh.position.y = slabElevation - // Cursor group is at the world root (not inside a level group), so add the - // level group's current world Y to convert from level-local to world space. - const levelGroup = sceneRegistry.nodes.get(levelId as AnyNodeId) - cursorGroupRef.current.position.y = slabElevation + (levelGroup?.position.y ?? 0) } } }) @@ -1247,11 +1253,12 @@ export function usePlacementCoordinator(config: PlacementCoordinatorConfig): Rea initialDimensionBounds.center[2] - initialDimensionBounds.dimensions[2] / 2, ] - return ( - - - - + const measurementTarget = + draftNode.current && measurementTargetState?.id === draftNode.current.id + ? measurementTargetState.object + : null + const measurementContent = ( + <> + + ) + + return ( + + + + + {measurementTarget ? createPortal(measurementContent, measurementTarget) : measurementContent}