Files
editor/packages/nodes/src/slab/floorplan-affordances.ts
T
Wassim SAMADandClaude Opus 4.8 ac14443fa6 fix(editor): polygon vertex/edge edit honors the active snapping mode
The shared polygon-vertex affordance snapped via snapPointToGrid(rawPoint), whose
default step is the hardcoded WALL_GRID_STEP (0.5m) — so slab/zone/ceiling vertex,
edge, and add-vertex edits always quantized to half-meters regardless of the
active mode OR the user's grid-step setting (plan open bugs #1-2). Use the
mode-aware getSegmentGridStep() (0 in non-grid modes) so grid quantizes to the
live step, lines/off pass through to the wall-snap/alignment resolver. Drop the
legacy shiftKey bypass from the slab/ceiling magnetic resolvers (they already
gate on isMagneticSnapActive).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-25 14:46:16 -04:00

58 lines
1.9 KiB
TypeScript

import { type AnyNode, resolveLevelId, type SlabNode } from '@pascal-app/core'
import { resolveSlabPlanPointSnap } from '@pascal-app/editor'
import {
createPolygonAddVertexAffordance,
createPolygonMoveEdgeAffordance,
createPolygonVertexAffordance,
type PolygonAffordanceSnapContext,
} from '../shared/polygon-vertex-affordance'
/**
* 2D drag affordances for slab. Three operations, each accepting an
* optional `holeIndex` in the payload so they target the boundary
* polygon or a specific hole:
*
* - `move-vertex` — drag an existing vertex.
* - `add-vertex` — insert a new vertex at a midpoint then drag.
* - `move-edge` — drag a whole edge perpendicular to itself.
*
* Holes are surfaced inline alongside the boundary in `def.floorplan`
* (no separate "hole edit mode" state machine like the legacy) — when
* the slab is selected, every hole's handles appear at the same time.
* Simpler model, no UX downside in practice.
*/
const slabSnapOptions = {
resolvePlanPoint({
node,
nodes,
rawPoint,
fallbackPoint,
modifiers,
}: PolygonAffordanceSnapContext<SlabNode>) {
const sceneNodes = nodes as Record<string, AnyNode>
return resolveSlabPlanPointSnap({
rawPoint,
fallbackPoint,
levelId: resolveLevelId(node, sceneNodes),
excludeId: node.id,
nodes: sceneNodes,
// Magnetic wall-snap/alignment gates on `isMagneticSnapActive()` (the
// `lines` mode), so no Shift bypass — Alt still force-skips alignment.
altKey: modifiers.altKey,
}).point
},
}
export const slabMoveVertexAffordance = createPolygonVertexAffordance<SlabNode>(
'slab',
slabSnapOptions,
)
export const slabAddVertexAffordance = createPolygonAddVertexAffordance<SlabNode>(
'slab',
slabSnapOptions,
)
export const slabMoveEdgeAffordance = createPolygonMoveEdgeAffordance<SlabNode>(
'slab',
slabSnapOptions,
)