Fix spawn floorplan move handle
This commit is contained in:
@@ -31,6 +31,7 @@ describe('spawn definition', () => {
|
|||||||
expect(spawnDefinition.schemaVersion).toBe(1)
|
expect(spawnDefinition.schemaVersion).toBe(1)
|
||||||
expect(spawnDefinition.category).toBe('site')
|
expect(spawnDefinition.category).toBe('site')
|
||||||
expect(spawnDefinition.schema).toBe(SpawnNode)
|
expect(spawnDefinition.schema).toBe(SpawnNode)
|
||||||
|
expect(typeof spawnDefinition.floorplanMoveTarget).toBe('function')
|
||||||
})
|
})
|
||||||
|
|
||||||
test('defaults() returns a value that the schema accepts', () => {
|
test('defaults() returns a value that the schema accepts', () => {
|
||||||
@@ -111,6 +112,7 @@ describe('spawn definition', () => {
|
|||||||
|
|
||||||
const flat = flattenFloorplan(geometry)
|
const flat = flattenFloorplan(geometry)
|
||||||
expect(flat.some((entry) => entry.kind === 'path' && entry.stroke === '#818cf8')).toBe(true)
|
expect(flat.some((entry) => entry.kind === 'path' && entry.stroke === '#818cf8')).toBe(true)
|
||||||
|
expect(flat.some((entry) => entry.kind === 'move-handle')).toBe(true)
|
||||||
expect(flat.some((entry) => entry.kind === 'rotate-arrow')).toBe(true)
|
expect(flat.some((entry) => entry.kind === 'rotate-arrow')).toBe(true)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import type { HandleDescriptor, NodeDefinition, SpawnNode as SpawnNodeType } from '@pascal-app/core'
|
import type { HandleDescriptor, NodeDefinition, SpawnNode as SpawnNodeType } from '@pascal-app/core'
|
||||||
import { buildSpawnFloorplan } from './floorplan'
|
import { buildSpawnFloorplan } from './floorplan'
|
||||||
import { spawnRotateAffordance } from './floorplan-affordances'
|
import { spawnRotateAffordance } from './floorplan-affordances'
|
||||||
|
import { spawnFloorplanMoveTarget } from './floorplan-move'
|
||||||
import { spawnParametrics } from './parametrics'
|
import { spawnParametrics } from './parametrics'
|
||||||
import { SpawnNode } from './schema'
|
import { SpawnNode } from './schema'
|
||||||
|
|
||||||
@@ -92,6 +93,7 @@ export const spawnDefinition: NodeDefinition<typeof SpawnNode> = {
|
|||||||
// delete. Legacy spawn click handlers in FloorplanNodeLayer become
|
// delete. Legacy spawn click handlers in FloorplanNodeLayer become
|
||||||
// dead code once Phase 6 cleanup removes the [] entries path.
|
// dead code once Phase 6 cleanup removes the [] entries path.
|
||||||
floorplan: buildSpawnFloorplan,
|
floorplan: buildSpawnFloorplan,
|
||||||
|
floorplanMoveTarget: spawnFloorplanMoveTarget,
|
||||||
floorplanAffordances: {
|
floorplanAffordances: {
|
||||||
'spawn-rotate': spawnRotateAffordance,
|
'spawn-rotate': spawnRotateAffordance,
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -0,0 +1,39 @@
|
|||||||
|
import {
|
||||||
|
type AnyNodeId,
|
||||||
|
type FloorplanMoveTarget,
|
||||||
|
type FloorplanMoveTargetSession,
|
||||||
|
type SpawnNode,
|
||||||
|
snapScalar,
|
||||||
|
useScene,
|
||||||
|
} from '@pascal-app/core'
|
||||||
|
import { getSegmentGridStep } from '@pascal-app/editor'
|
||||||
|
|
||||||
|
export const spawnFloorplanMoveTarget: FloorplanMoveTarget<SpawnNode> = ({ node }) => {
|
||||||
|
const spawnId = node.id as AnyNodeId
|
||||||
|
const startY = node.position[1]
|
||||||
|
const originalPosition: [number, number, number] = [...node.position]
|
||||||
|
let lastPosition: [number, number, number] | null = null
|
||||||
|
|
||||||
|
const session: FloorplanMoveTargetSession = {
|
||||||
|
affectedIds: [spawnId],
|
||||||
|
apply({ planPoint, modifiers }) {
|
||||||
|
const step = getSegmentGridStep()
|
||||||
|
const snap = (value: number) => (modifiers.shiftKey ? value : snapScalar(value, step))
|
||||||
|
const next: [number, number, number] = [snap(planPoint[0]), startY, snap(planPoint[1])]
|
||||||
|
|
||||||
|
if (lastPosition && lastPosition[0] === next[0] && lastPosition[2] === next[2]) return
|
||||||
|
lastPosition = next
|
||||||
|
useScene.getState().updateNodes([{ id: spawnId, data: { position: next } }])
|
||||||
|
},
|
||||||
|
canCommit() {
|
||||||
|
if (!lastPosition) return false
|
||||||
|
return lastPosition[0] !== originalPosition[0] || lastPosition[2] !== originalPosition[2]
|
||||||
|
},
|
||||||
|
commit() {
|
||||||
|
if (!lastPosition) return
|
||||||
|
useScene.getState().updateNodes([{ id: spawnId, data: { position: lastPosition } }])
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
return session
|
||||||
|
}
|
||||||
@@ -113,6 +113,11 @@ export function buildSpawnFloorplan(node: SpawnNode, ctx: GeometryContext): Floo
|
|||||||
]
|
]
|
||||||
|
|
||||||
if (isSelected) {
|
if (isSelected) {
|
||||||
|
children.push({
|
||||||
|
kind: 'move-handle',
|
||||||
|
point: [px, pz],
|
||||||
|
})
|
||||||
|
|
||||||
const cornerLocalX = 0.34 + ROTATE_ARROW_CORNER_OFFSET
|
const cornerLocalX = 0.34 + ROTATE_ARROW_CORNER_OFFSET
|
||||||
const cornerLocalZ = 0.34 + ROTATE_ARROW_CORNER_OFFSET
|
const cornerLocalZ = 0.34 + ROTATE_ARROW_CORNER_OFFSET
|
||||||
const [cornerX, cornerZ] = rotatePlanVector(cornerLocalX, cornerLocalZ, planRotation)
|
const [cornerX, cornerZ] = rotatePlanVector(cornerLocalX, cornerLocalZ, planRotation)
|
||||||
|
|||||||
Reference in New Issue
Block a user