feat(editor): MEP placement migration — Shift=cycle / mode-driven snapping
Migrate all 9 MEP kinds' placement tools onto the unified snapping model:
declare snapProfile ('item' for point-placed hvac-equipment / duct-terminal /
duct-fitting / pipe-fitting / pipe-trap; 'structural' for directional runs
duct-segment / pipe-segment / liquid-line / lineset), and replace the legacy
shiftKey-bypass reads with mode-driven isGridSnapActive / isMagneticSnapActive /
isAngleSnapActive. For runs the 45° lock becomes the cyclable 'angles' mode;
Alt stays the vertical-riser modifier (run drafting has no validity gate to
force). Port mating gated on "mode != off". Dropped stale "⇧ smooth/free" hints.
The bespoke MEP move-tool/selection (endpoint) tools stay on the legacy model —
they use setMovingNode(null) so no moving-scope context resolves yet; migrating
them needs scope-wiring first (follow-up).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
76096ffe72
commit
2fdbcf03c3
@@ -20,6 +20,7 @@ export const ductTerminalDefinition: NodeDefinition<typeof DuctTerminalNode> = {
|
||||
schema: DuctTerminalNode,
|
||||
category: 'utility',
|
||||
distributionRole: 'terminal',
|
||||
snapProfile: 'item',
|
||||
|
||||
defaults: () => ({
|
||||
object: 'node',
|
||||
|
||||
@@ -13,6 +13,8 @@ import {
|
||||
import {
|
||||
CursorSphere,
|
||||
getFloorStackPreviewPosition,
|
||||
isGridSnapActive,
|
||||
isMagneticSnapActive,
|
||||
triggerSFX,
|
||||
useEditor,
|
||||
} from '@pascal-app/editor'
|
||||
@@ -256,19 +258,22 @@ const DuctTerminalTool = () => {
|
||||
hit = hitLocalPlane(nativeEvent, y)
|
||||
}
|
||||
if (!hit) return null
|
||||
const step = nativeEvent.shiftKey ? 0 : useEditor.getState().gridSnapStep
|
||||
const step = isGridSnapActive() ? useEditor.getState().gridSnapStep : 0
|
||||
// Grid-snap, then layer Figma-style alignment so a floor / ceiling
|
||||
// register lines up with ducts, equipment, and items (Shift = free).
|
||||
// register lines up with ducts, equipment, and items. Grid + lines
|
||||
// follow the active snapping mode (the contextual HUD chip — Shift
|
||||
// cycles it); `'off'` is the no-snap bypass.
|
||||
const position = alignDrawPoint([snap(hit.x, step), y, snap(hit.z, step)], {
|
||||
applySnap: true,
|
||||
bypass: nativeEvent.shiftKey === true,
|
||||
bypass: !isMagneticSnapActive(),
|
||||
})
|
||||
// Magnetic port snap: if a duct run end / fitting collar is in range,
|
||||
// the port's direction picks the mount (floor / ceiling / wall) and
|
||||
// hops the whole register so its collar mates exactly onto it. Takes
|
||||
// precedence over grid / alignment and the manual M mount; Shift
|
||||
// bypasses.
|
||||
if (!nativeEvent.shiftKey) {
|
||||
// precedence over grid / alignment and the manual M mount; the
|
||||
// raw-cursor `'off'` mode bypasses it.
|
||||
const snapEnabled = isGridSnapActive() || isMagneticSnapActive()
|
||||
if (snapEnabled) {
|
||||
const mated = resolvePortSnap(position, yawRef.current)
|
||||
if (mated) {
|
||||
return { position: mated.position, yaw: mated.yaw, mount: mated.mount, snapped: true }
|
||||
|
||||
Reference in New Issue
Block a user