Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -466,7 +466,7 @@ export function usePlacementCoordinator(config: PlacementCoordinatorConfig): Rea
draftItem: draftNode.current,
gridPosition: gridPosition.current,
state: { ...placementState.current },
currentCursorRotationY: cursorGroupRef.current.rotation.y,
currentCursorRotationY: cursorGroupRef.current?.rotation.y ?? 0,
})

const getActiveValidators = () =>
Expand Down Expand Up @@ -496,6 +496,7 @@ export function usePlacementCoordinator(config: PlacementCoordinatorConfig): Rea
}

const applyTransition = (result: TransitionResult) => {
if (!cursorGroupRef.current) return
Object.assign(placementState.current, result.stateUpdate)
gridPosition.current.set(...result.gridPosition)

Expand All @@ -512,6 +513,7 @@ export function usePlacementCoordinator(config: PlacementCoordinatorConfig): Rea
}

const ensureDraft = (result: TransitionResult) => {
if (!cursorGroupRef.current) return
gridPosition.current.set(...result.gridPosition)
const c = worldToBuildingLocal(...result.cursorPosition)
cursorGroupRef.current.position.set(c.x, c.y, c.z)
Expand Down Expand Up @@ -571,6 +573,7 @@ export function usePlacementCoordinator(config: PlacementCoordinatorConfig): Rea

has3DPointerDrivenMoveRef.current = true
lastRawPos.current.set(event.localPosition[0], event.localPosition[1], event.localPosition[2])
if (!cursorGroupRef.current) return
const result = floorStrategy.move(getContext(), event)
if (!result) return

Expand Down Expand Up @@ -598,19 +601,20 @@ export function usePlacementCoordinator(config: PlacementCoordinatorConfig): Rea
if (draft) {
useLiveTransforms.getState().set(draft.id, {
position: result.gridPosition,
rotation: cursorGroupRef.current.rotation.y,
rotation: cursorGroupRef.current?.rotation.y ?? 0,
})
}

revalidate()
}

const onGridClick = (event: GridEvent) => {
if (!cursorGroupRef.current) return
const result = floorStrategy.click(getContext(), event, getActiveValidators())
if (!result) return

// Preserve cursor rotation for the next draft
const currentRotation: [number, number, number] = [0, cursorGroupRef.current.rotation.y, 0]
const currentRotation: [number, number, number] = [0, cursorGroupRef.current?.rotation.y ?? 0, 0]

// Clear live transform before commit
if (draftNode.current) {
Expand All @@ -628,6 +632,7 @@ export function usePlacementCoordinator(config: PlacementCoordinatorConfig): Rea

const onWallEnter = (event: WallEvent) => {
has3DPointerDrivenMoveRef.current = true
if (!cursorGroupRef.current) return
const nodes = useScene.getState().nodes
const result = wallStrategy.enter(
getContext(),
Expand All @@ -654,6 +659,7 @@ export function usePlacementCoordinator(config: PlacementCoordinatorConfig): Rea

const onWallMove = (event: WallEvent) => {
has3DPointerDrivenMoveRef.current = true
if (!cursorGroupRef.current) return
const ctx = getContext()

if (ctx.state.surface !== 'wall') {
Expand Down Expand Up @@ -754,6 +760,7 @@ export function usePlacementCoordinator(config: PlacementCoordinatorConfig): Rea
}

const onWallClick = (event: WallEvent) => {
if (!cursorGroupRef.current) return
const result = wallStrategy.click(getContext(), event, getActiveValidators())
if (!result) return

Expand Down Expand Up @@ -785,6 +792,7 @@ export function usePlacementCoordinator(config: PlacementCoordinatorConfig): Rea
}

const onWallLeave = (event: WallEvent) => {
if (!cursorGroupRef.current) return
const result = wallStrategy.leave(getContext())
if (!result) return

Expand Down Expand Up @@ -843,6 +851,7 @@ export function usePlacementCoordinator(config: PlacementCoordinatorConfig): Rea
}

const onItemEnter = (event: ItemEvent) => {
if (!cursorGroupRef.current) return
if (event.node.id === draftNode.current?.id) return
has3DPointerDrivenMoveRef.current = true
const result = itemSurfaceStrategy.enter(getContext(), event)
Expand All @@ -860,6 +869,7 @@ export function usePlacementCoordinator(config: PlacementCoordinatorConfig): Rea
}

const onItemMove = (event: ItemEvent) => {
if (!cursorGroupRef.current) return
if (event.node.id === draftNode.current?.id) return
has3DPointerDrivenMoveRef.current = true
const ctx = getContext()
Expand Down Expand Up @@ -931,6 +941,7 @@ export function usePlacementCoordinator(config: PlacementCoordinatorConfig): Rea
}

const onItemLeave = (event: ItemEvent) => {
if (!cursorGroupRef.current) return
if (event.node.id === draftNode.current?.id) return
if (placementState.current.surface !== 'item-surface') return

Expand Down Expand Up @@ -1040,7 +1051,8 @@ export function usePlacementCoordinator(config: PlacementCoordinatorConfig): Rea
}
return
}

if (!cursorGroupRef.current) return
if (event.node.id === draftNode.current?.id) return
const result = itemSurfaceStrategy.click(getContext(), event)
if (!result) return

Expand All @@ -1066,6 +1078,7 @@ export function usePlacementCoordinator(config: PlacementCoordinatorConfig): Rea

const onCeilingEnter = (event: CeilingEvent) => {
has3DPointerDrivenMoveRef.current = true
if (!cursorGroupRef.current) return
const nodes = useScene.getState().nodes
const result = ceilingStrategy.enter(getContext(), event, resolveLevelId, nodes)
if (!result) return
Expand All @@ -1086,6 +1099,7 @@ export function usePlacementCoordinator(config: PlacementCoordinatorConfig): Rea

const onCeilingMove = (event: CeilingEvent) => {
has3DPointerDrivenMoveRef.current = true
if (!cursorGroupRef.current) return
if (!draftNode.current && placementState.current.surface === 'ceiling') {
const nodes = useScene.getState().nodes
const setup = ceilingStrategy.enter(getContext(), event, resolveLevelId, nodes)
Expand Down Expand Up @@ -1127,12 +1141,13 @@ export function usePlacementCoordinator(config: PlacementCoordinatorConfig): Rea
// Publish live transform for 2D floorplan
useLiveTransforms.getState().set(draft.id, {
position: result.cursorPosition,
rotation: cursorGroupRef.current.rotation.y,
rotation: cursorGroupRef.current?.rotation.y ?? 0,
})
}
}

const onCeilingClick = (event: CeilingEvent) => {
if (!cursorGroupRef.current) return
const result = ceilingStrategy.click(getContext(), event, getActiveValidators())
if (!result) return

Expand All @@ -1155,6 +1170,7 @@ export function usePlacementCoordinator(config: PlacementCoordinatorConfig): Rea
}

const onCeilingLeave = (event: CeilingEvent) => {
if (!cursorGroupRef.current) return
const result = ceilingStrategy.leave(getContext())
if (!result) return

Expand Down Expand Up @@ -1282,6 +1298,7 @@ export function usePlacementCoordinator(config: PlacementCoordinatorConfig): Rea

const ROTATION_STEP = Math.PI / 2
const onKeyDown = (event: KeyboardEvent) => {
if (!cursorGroupRef.current) return
if (event.key === 'Shift') {
shiftFreeRef.current = true
revalidate()
Expand Down Expand Up @@ -1372,6 +1389,7 @@ export function usePlacementCoordinator(config: PlacementCoordinatorConfig): Rea
}

const onKeyUp = (event: KeyboardEvent) => {
if (!cursorGroupRef.current) return
if (event.key === 'Shift') {
shiftFreeRef.current = false
revalidate()
Expand All @@ -1383,6 +1401,7 @@ export function usePlacementCoordinator(config: PlacementCoordinatorConfig): Rea

// ---- tool:cancel (Escape / programmatic) ----
const onCancel = () => {
if (!cursorGroupRef.current) return
if (configRef.current.onCancel) {
configRef.current.onCancel()
}
Expand All @@ -1391,6 +1410,7 @@ export function usePlacementCoordinator(config: PlacementCoordinatorConfig): Rea

// ---- Right-click cancel ----
const onContextMenu = (event: MouseEvent) => {
if (!cursorGroupRef.current) return
if (configRef.current.onCancel) {
event.preventDefault()
configRef.current.onCancel()
Expand Down Expand Up @@ -1517,6 +1537,7 @@ export function usePlacementCoordinator(config: PlacementCoordinatorConfig): Rea

useFrame((_, delta) => {
if (!asset) return
if (!cursorGroupRef.current) return
if (!draftNode.current) return
// The mesh-position lerp below only makes sense once this coordinator
// owns the move via a 3D pointer event. Skip until then so that
Expand Down
1 change: 1 addition & 0 deletions packages/nodes/src/wall/tool.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,7 @@ export const WallTool: React.FC = () => {
}

const onGridClick = (event: GridEvent) => {
if (!wallPreviewRef.current) return
const walls = getCurrentLevelWalls()
const localClick: WallPlanPoint = [event.localPosition[0], event.localPosition[2]]

Expand Down