Support duplicating and moving new walls

This commit is contained in:
sudhir
2026-04-17 11:08:01 +05:30
parent 096f4c161a
commit 0effda29fe
2 changed files with 35 additions and 8 deletions
@@ -14,7 +14,7 @@ import {
StairSegmentNode,
sceneRegistry,
useScene,
type WallNode,
WallNode,
WindowNode,
} from '@pascal-app/core'
import { useViewer } from '@pascal-app/viewer'
@@ -210,6 +210,8 @@ export function FloatingActionMenu() {
duplicate = WindowNode.parse(duplicateInfo)
} else if (node.type === 'item') {
duplicate = ItemNode.parse(duplicateInfo)
} else if (node.type === 'wall') {
duplicate = WallNode.parse(duplicateInfo)
} else if (node.type === 'fence') {
duplicate = FenceNode.parse(duplicateInfo)
duplicate.start = [duplicate.start[0] + 1, duplicate.start[1] + 1]
@@ -241,6 +243,8 @@ export function FloatingActionMenu() {
if (duplicate) {
if (duplicate.type === 'door' || duplicate.type === 'window') {
useScene.getState().createNode(duplicate, duplicate.parentId as AnyNodeId)
} else if (duplicate.type === 'wall') {
useScene.getState().createNode(duplicate, duplicate.parentId as AnyNodeId)
} else if (duplicate.type === 'fence') {
useScene.getState().createNode(duplicate, duplicate.parentId as AnyNodeId)
} else if (
@@ -310,6 +314,7 @@ export function FloatingActionMenu() {
}
if (
duplicate.type === 'item' ||
duplicate.type === 'wall' ||
duplicate.type === 'fence' ||
duplicate.type === 'window' ||
duplicate.type === 'door' ||
@@ -19,6 +19,16 @@ function samePoint(a: [number, number], b: [number, number]) {
return a[0] === b[0] && a[1] === b[1]
}
function stripWallIsNewMetadata(meta: WallNode['metadata']): WallNode['metadata'] {
if (!meta || typeof meta !== 'object' || Array.isArray(meta)) {
return meta
}
const nextMeta = { ...(meta as Record<string, unknown>) }
delete nextMeta.isNew
return nextMeta
}
type LinkedWallSnapshot = {
id: WallNode['id']
start: [number, number]
@@ -86,6 +96,11 @@ function getLinkedWallUpdates(
}
export const MoveWallTool: React.FC<{ node: WallNode }> = ({ node }) => {
const meta =
typeof node.metadata === 'object' && node.metadata !== null && !Array.isArray(node.metadata)
? (node.metadata as Record<string, unknown>)
: {}
const isNew = !!meta.isNew
const activatedAtRef = useRef<number>(Date.now())
const previousGridPosRef = useRef<[number, number] | null>(null)
const originalStartRef = useRef<[number, number]>([...node.start] as [number, number])
@@ -99,12 +114,14 @@ export const MoveWallTool: React.FC<{ node: WallNode }> = ({ node }) => {
(node.end[1] - node.start[1]) / 2,
])
const linkedOriginalsRef = useRef(
getLinkedWallSnapshots({
wallId: node.id,
wallParentId: node.parentId ?? null,
originalStart: node.start,
originalEnd: node.end,
}),
isNew
? []
: getLinkedWallSnapshots({
wallId: node.id,
wallParentId: node.parentId ?? null,
originalStart: node.start,
originalEnd: node.end,
}),
)
const dragAnchorRef = useRef<[number, number] | null>(null)
const nodeIdRef = useRef(node.id)
@@ -223,6 +240,11 @@ export const MoveWallTool: React.FC<{ node: WallNode }> = ({ node }) => {
preview.end,
),
])
if (isNew) {
useScene.getState().updateNode(nodeId, {
metadata: stripWallIsNewMetadata(node.metadata),
})
}
useScene.temporal.getState().pause()
sfxEmitter.emit('sfx:item-place')
@@ -295,7 +317,7 @@ export const MoveWallTool: React.FC<{ node: WallNode }> = ({ node }) => {
window.removeEventListener('keydown', onKeyDown)
window.removeEventListener('keyup', onKeyUp)
}
}, [exitMoveMode])
}, [exitMoveMode, isNew, node.metadata])
return (
<group>