Phase 5 Stage C continued: wall, door, window now in registry floor plan
Three remaining kinds at Stage C this session: wall → C - buildWallFloorplan: uses ctx.siblings to gather other walls in the level, runs calculateLevelMiters, computes plan footprint via getWallPlanFootprint. Same visual output as legacy. - getFloorplanWall thickness exaggeration inlined (~25 lines from editor/lib/floorplan/walls.ts) to keep nodes/wall self-contained. - floorplan-panel.tsx's wallPolygons short-circuits to [] when wall is registered. - Performance note: recomputes level miter data per wall (O(N²) for N walls in a level). Acceptable for typical scenes; ctx.levelData?. miters optimization deferred to Stage B's wall design pass. door → C - buildDoorFloorplan: inlines getOpeningFootprint math from floorplan-panel.tsx (40 lines, pure math). Uses ctx.parent as the wall to compute direction + perpendicular for the cutout footprint. - Returns null when parent isn't a wall (orphaned doors during placement). window → C - buildWindowFloorplan: same shape as door, glass-blue tint to distinguish visually. Both share the legacy openingsPolygons gating: - floorplan-panel.tsx's openingsPolygons useMemo filters per kind so a partial migration still works (e.g., if only door registers, only doors get skipped). When both registered, returns [] entirely. Item C intentionally deferred — needs parent-chain transform helpers (buildFloorplanItemEntry / getItemFloorplanTransform from editor/lib/ floorplan/items.ts) exposed publicly or moved into core. A focused session is the right place to design that boundary. Stage B for door / window / wall still pending — each is a focused session per kind (large geometry math extractions, wall needs ctx. levelData design). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.7
parent
969b154b08
commit
9bcb25d0aa
@@ -8486,19 +8486,21 @@ export function FloorplanPanel() {
|
||||
return [{ fence: displayFence, centerline, markerFrames, path }]
|
||||
})
|
||||
}, [fences, movingFloorplanNodeRevision])
|
||||
const wallPolygons = useMemo(
|
||||
() =>
|
||||
walls.map((wall) => {
|
||||
const floorplanWall = floorplanWallById.get(wall.id) ?? getFloorplanWall(wall)
|
||||
const polygon = getWallPlanFootprint(floorplanWall, wallMiterData)
|
||||
return {
|
||||
points: formatPolygonPoints(polygon),
|
||||
wall,
|
||||
polygon,
|
||||
}
|
||||
}),
|
||||
[floorplanWallById, wallMiterData, walls],
|
||||
)
|
||||
const wallPolygons = useMemo(() => {
|
||||
// Wall migrated to def.floorplan (Phase 5 Stage C). When registered,
|
||||
// FloorplanRegistryLayer renders the mitered wall polygon; this
|
||||
// legacy path short-circuits. Removed entirely in Phase 6 cleanup.
|
||||
if (nodeRegistry.has('wall')) return []
|
||||
return walls.map((wall) => {
|
||||
const floorplanWall = floorplanWallById.get(wall.id) ?? getFloorplanWall(wall)
|
||||
const polygon = getWallPlanFootprint(floorplanWall, wallMiterData)
|
||||
return {
|
||||
points: formatPolygonPoints(polygon),
|
||||
wall,
|
||||
polygon,
|
||||
}
|
||||
})
|
||||
}, [floorplanWallById, wallMiterData, walls])
|
||||
const displayWallPolygons = useMemo(() => {
|
||||
if (!(wallEndpointDraft || wallCurveDraft)) {
|
||||
return wallPolygons
|
||||
@@ -8547,41 +8549,49 @@ export function FloorplanPanel() {
|
||||
)
|
||||
}, [displayWallById, wallCurveDraft, wallEndpointDraft, wallPolygons])
|
||||
|
||||
const openingsPolygons = useMemo(
|
||||
() =>
|
||||
openings.flatMap((opening) => {
|
||||
const wall = displayFloorplanWallById.get(opening.parentId as WallNode['id'])
|
||||
if (!wall) return []
|
||||
const live = useLiveTransforms.getState().get(opening.id)
|
||||
const displayOpening =
|
||||
live &&
|
||||
(movingNode?.type === 'door' || movingNode?.type === 'window') &&
|
||||
movingNode.id === opening.id
|
||||
? {
|
||||
...opening,
|
||||
position: [
|
||||
live.position[0],
|
||||
opening.position[1],
|
||||
live.position[2],
|
||||
] as typeof opening.position,
|
||||
rotation: [
|
||||
opening.rotation[0],
|
||||
live.rotation,
|
||||
opening.rotation[2],
|
||||
] as typeof opening.rotation,
|
||||
}
|
||||
: opening
|
||||
const polygon = getOpeningFootprint(wall, displayOpening)
|
||||
return [
|
||||
{
|
||||
opening: displayOpening,
|
||||
points: formatPolygonPoints(polygon),
|
||||
polygon,
|
||||
},
|
||||
]
|
||||
}),
|
||||
[displayFloorplanWallById, movingFloorplanNodeRevision, movingNode, openings],
|
||||
)
|
||||
const openingsPolygons = useMemo(() => {
|
||||
// Doors + windows migrated to def.floorplan (Phase 5 Stage C). When
|
||||
// both registered, FloorplanRegistryLayer renders each opening's
|
||||
// polygon via its kind's builder; this legacy path short-circuits
|
||||
// to avoid double-render. Filter per kind so a partial migration
|
||||
// would still work.
|
||||
const doorRegistered = nodeRegistry.has('door')
|
||||
const windowRegistered = nodeRegistry.has('window')
|
||||
if (doorRegistered && windowRegistered) return []
|
||||
return openings.flatMap((opening) => {
|
||||
if (doorRegistered && opening.type === 'door') return []
|
||||
if (windowRegistered && opening.type === 'window') return []
|
||||
const wall = displayFloorplanWallById.get(opening.parentId as WallNode['id'])
|
||||
if (!wall) return []
|
||||
const live = useLiveTransforms.getState().get(opening.id)
|
||||
const displayOpening =
|
||||
live &&
|
||||
(movingNode?.type === 'door' || movingNode?.type === 'window') &&
|
||||
movingNode.id === opening.id
|
||||
? {
|
||||
...opening,
|
||||
position: [
|
||||
live.position[0],
|
||||
opening.position[1],
|
||||
live.position[2],
|
||||
] as typeof opening.position,
|
||||
rotation: [
|
||||
opening.rotation[0],
|
||||
live.rotation,
|
||||
opening.rotation[2],
|
||||
] as typeof opening.rotation,
|
||||
}
|
||||
: opening
|
||||
const polygon = getOpeningFootprint(wall, displayOpening)
|
||||
return [
|
||||
{
|
||||
opening: displayOpening,
|
||||
points: formatPolygonPoints(polygon),
|
||||
polygon,
|
||||
},
|
||||
]
|
||||
})
|
||||
}, [displayFloorplanWallById, movingFloorplanNodeRevision, movingNode, openings])
|
||||
const slabPolygons = useMemo(() => {
|
||||
// Slab migrated to def.floorplan (Phase 5 Stage C). When registered,
|
||||
// FloorplanRegistryLayer renders the slab polygon; this legacy
|
||||
|
||||
Reference in New Issue
Block a user