feat(editor): MEP move-tools — mode-driven snapping (drop Shift=bypass)
The 5 bespoke MEP movers (duct/pipe-segment, liquid-line, lineset, duct-fitting)
now read the active snapping mode (isGridSnapActive / isMagneticSnapActive)
instead of shiftKey=bypass. The moving scope already carries the node
(setMovingNode → begin('moving')), so the per-kind context resolves with no
extra wiring. Grid and alignment are now independent reads.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
2fdbcf03c3
commit
8e9a45a9d5
@@ -13,6 +13,8 @@ import {
|
||||
import {
|
||||
DragBoundingBox,
|
||||
EDITOR_LAYER,
|
||||
isGridSnapActive,
|
||||
isMagneticSnapActive,
|
||||
markToolCancelConsumed,
|
||||
stripPlacementMetadataFlags,
|
||||
triggerSFX,
|
||||
@@ -177,14 +179,14 @@ export const MoveDuctFittingTool: React.FC<{ node: AnyNode }> = ({ node }) => {
|
||||
let lastPos: Vec3 = originalPosition
|
||||
|
||||
const onMove = (event: GridEvent) => {
|
||||
const bypass = event.nativeEvent?.shiftKey === true
|
||||
const snap = bypass ? (v: number) => v : snapToGridStep
|
||||
const snap = isGridSnapActive() ? snapToGridStep : (v: number) => v
|
||||
let x = snap(event.localPosition[0])
|
||||
let z = snap(event.localPosition[2])
|
||||
|
||||
// Alignment: snap the footprint box edges onto nearby geometry and
|
||||
// publish guides (Alt / Shift bypass).
|
||||
if (!bypass) {
|
||||
// Magnetic alignment: snap the footprint box edges onto nearby geometry
|
||||
// and publish guides. Grid follows the snapping mode; lines follow
|
||||
// magnetic alignment — the two are independent.
|
||||
if (isMagneticSnapActive()) {
|
||||
const proposed: Aabb2D = {
|
||||
minX: x + ox - hx,
|
||||
maxX: x + ox + hx,
|
||||
@@ -200,7 +202,11 @@ export const MoveDuctFittingTool: React.FC<{ node: AnyNode }> = ({ node }) => {
|
||||
}
|
||||
|
||||
const next: Vec3 = [x, originalPosition[1], z]
|
||||
if (next[0] !== lastPos[0] || next[2] !== lastPos[2]) triggerSFX('sfx:grid-snap')
|
||||
if (
|
||||
(isGridSnapActive() || isMagneticSnapActive()) &&
|
||||
(next[0] !== lastPos[0] || next[2] !== lastPos[2])
|
||||
)
|
||||
triggerSFX('sfx:grid-snap')
|
||||
lastPos = next
|
||||
hasMoved = true
|
||||
setCursorPos(next)
|
||||
|
||||
@@ -13,6 +13,8 @@ import {
|
||||
import {
|
||||
DragBoundingBox,
|
||||
EDITOR_LAYER,
|
||||
isGridSnapActive,
|
||||
isMagneticSnapActive,
|
||||
markToolCancelConsumed,
|
||||
stripPlacementMetadataFlags,
|
||||
triggerSFX,
|
||||
@@ -144,14 +146,14 @@ export const MoveDuctSegmentTool: React.FC<{ node: AnyNode }> = ({ node }) => {
|
||||
}
|
||||
|
||||
const onMove = (event: GridEvent) => {
|
||||
const bypass = event.nativeEvent?.shiftKey === true
|
||||
const snap = bypass ? (v: number) => v : snapToGridStep
|
||||
const snap = isGridSnapActive() ? snapToGridStep : (v: number) => v
|
||||
let dx = snap(event.localPosition[0] - centerX)
|
||||
let dz = snap(event.localPosition[2] - centerZ)
|
||||
|
||||
// Figma-style alignment: snap the run's footprint box edges onto
|
||||
// nearby geometry and publish the guides (Alt / Shift bypass).
|
||||
if (!bypass) {
|
||||
// Figma-style magnetic alignment: snap the run's footprint box edges onto
|
||||
// nearby geometry and publish the guides. Grid follows the snapping mode;
|
||||
// lines follow magnetic alignment — the two are independent.
|
||||
if (isMagneticSnapActive()) {
|
||||
const proposed: Aabb2D = {
|
||||
minX: baseAabb.minX + dx,
|
||||
maxX: baseAabb.maxX + dx,
|
||||
@@ -168,7 +170,7 @@ export const MoveDuctSegmentTool: React.FC<{ node: AnyNode }> = ({ node }) => {
|
||||
|
||||
const cur: [number, number] = [centerX + dx, centerZ + dz]
|
||||
if (
|
||||
!bypass &&
|
||||
(isGridSnapActive() || isMagneticSnapActive()) &&
|
||||
(!prevSnapRef.current ||
|
||||
prevSnapRef.current[0] !== cur[0] ||
|
||||
prevSnapRef.current[1] !== cur[1])
|
||||
|
||||
@@ -13,6 +13,8 @@ import {
|
||||
import {
|
||||
DragBoundingBox,
|
||||
EDITOR_LAYER,
|
||||
isGridSnapActive,
|
||||
isMagneticSnapActive,
|
||||
markToolCancelConsumed,
|
||||
stripPlacementMetadataFlags,
|
||||
triggerSFX,
|
||||
@@ -143,14 +145,14 @@ export const MoveLinesetTool: React.FC<{ node: AnyNode }> = ({ node }) => {
|
||||
}
|
||||
|
||||
const onMove = (event: GridEvent) => {
|
||||
const bypass = event.nativeEvent?.shiftKey === true
|
||||
const snap = bypass ? (v: number) => v : snapToGridStep
|
||||
const snap = isGridSnapActive() ? snapToGridStep : (v: number) => v
|
||||
let dx = snap(event.localPosition[0] - centerX)
|
||||
let dz = snap(event.localPosition[2] - centerZ)
|
||||
|
||||
// Figma-style alignment: snap the run's footprint box edges onto
|
||||
// nearby geometry and publish the guides (Shift bypass).
|
||||
if (!bypass) {
|
||||
// Figma-style magnetic alignment: snap the run's footprint box edges onto
|
||||
// nearby geometry and publish the guides. Grid follows the snapping mode;
|
||||
// lines follow magnetic alignment — the two are independent.
|
||||
if (isMagneticSnapActive()) {
|
||||
const proposed: Aabb2D = {
|
||||
minX: baseAabb.minX + dx,
|
||||
maxX: baseAabb.maxX + dx,
|
||||
@@ -167,7 +169,7 @@ export const MoveLinesetTool: React.FC<{ node: AnyNode }> = ({ node }) => {
|
||||
|
||||
const cur: [number, number] = [centerX + dx, centerZ + dz]
|
||||
if (
|
||||
!bypass &&
|
||||
(isGridSnapActive() || isMagneticSnapActive()) &&
|
||||
(!prevSnapRef.current ||
|
||||
prevSnapRef.current[0] !== cur[0] ||
|
||||
prevSnapRef.current[1] !== cur[1])
|
||||
|
||||
@@ -13,6 +13,8 @@ import {
|
||||
import {
|
||||
DragBoundingBox,
|
||||
EDITOR_LAYER,
|
||||
isGridSnapActive,
|
||||
isMagneticSnapActive,
|
||||
markToolCancelConsumed,
|
||||
stripPlacementMetadataFlags,
|
||||
triggerSFX,
|
||||
@@ -139,14 +141,14 @@ export const MoveLiquidLineTool: React.FC<{ node: AnyNode }> = ({ node }) => {
|
||||
}
|
||||
|
||||
const onMove = (event: GridEvent) => {
|
||||
const bypass = event.nativeEvent?.shiftKey === true
|
||||
const snap = bypass ? (v: number) => v : snapToGridStep
|
||||
const snap = isGridSnapActive() ? snapToGridStep : (v: number) => v
|
||||
let dx = snap(event.localPosition[0] - centerX)
|
||||
let dz = snap(event.localPosition[2] - centerZ)
|
||||
|
||||
// Figma-style alignment: snap the run's footprint box edges onto nearby
|
||||
// geometry and publish the guides (Shift bypass).
|
||||
if (!bypass) {
|
||||
// Figma-style magnetic alignment: snap the run's footprint box edges onto
|
||||
// nearby geometry and publish the guides. Grid follows the snapping mode;
|
||||
// lines follow magnetic alignment — the two are independent.
|
||||
if (isMagneticSnapActive()) {
|
||||
const proposed: Aabb2D = {
|
||||
minX: baseAabb.minX + dx,
|
||||
maxX: baseAabb.maxX + dx,
|
||||
@@ -163,7 +165,7 @@ export const MoveLiquidLineTool: React.FC<{ node: AnyNode }> = ({ node }) => {
|
||||
|
||||
const cur: [number, number] = [centerX + dx, centerZ + dz]
|
||||
if (
|
||||
!bypass &&
|
||||
(isGridSnapActive() || isMagneticSnapActive()) &&
|
||||
(!prevSnapRef.current ||
|
||||
prevSnapRef.current[0] !== cur[0] ||
|
||||
prevSnapRef.current[1] !== cur[1])
|
||||
|
||||
@@ -13,6 +13,8 @@ import {
|
||||
import {
|
||||
DragBoundingBox,
|
||||
EDITOR_LAYER,
|
||||
isGridSnapActive,
|
||||
isMagneticSnapActive,
|
||||
markToolCancelConsumed,
|
||||
stripPlacementMetadataFlags,
|
||||
triggerSFX,
|
||||
@@ -141,14 +143,14 @@ export const MovePipeSegmentTool: React.FC<{ node: AnyNode }> = ({ node }) => {
|
||||
}
|
||||
|
||||
const onMove = (event: GridEvent) => {
|
||||
const bypass = event.nativeEvent?.shiftKey === true
|
||||
const snap = bypass ? (v: number) => v : snapToGridStep
|
||||
const snap = isGridSnapActive() ? snapToGridStep : (v: number) => v
|
||||
let dx = snap(event.localPosition[0] - centerX)
|
||||
let dz = snap(event.localPosition[2] - centerZ)
|
||||
|
||||
// Figma-style alignment: snap the run's footprint box edges onto
|
||||
// nearby geometry and publish the guides (Shift bypass).
|
||||
if (!bypass) {
|
||||
// Figma-style magnetic alignment: snap the run's footprint box edges onto
|
||||
// nearby geometry and publish the guides. Grid follows the snapping mode;
|
||||
// lines follow magnetic alignment — the two are independent.
|
||||
if (isMagneticSnapActive()) {
|
||||
const proposed: Aabb2D = {
|
||||
minX: baseAabb.minX + dx,
|
||||
maxX: baseAabb.maxX + dx,
|
||||
@@ -165,7 +167,7 @@ export const MovePipeSegmentTool: React.FC<{ node: AnyNode }> = ({ node }) => {
|
||||
|
||||
const cur: [number, number] = [centerX + dx, centerZ + dz]
|
||||
if (
|
||||
!bypass &&
|
||||
(isGridSnapActive() || isMagneticSnapActive()) &&
|
||||
(!prevSnapRef.current ||
|
||||
prevSnapRef.current[0] !== cur[0] ||
|
||||
prevSnapRef.current[1] !== cur[1])
|
||||
|
||||
Reference in New Issue
Block a user