fix wall items wrong level + elevation
This commit is contained in:
@@ -2,6 +2,7 @@ import {
|
|||||||
type AnyNodeId,
|
type AnyNodeId,
|
||||||
emitter,
|
emitter,
|
||||||
sceneRegistry,
|
sceneRegistry,
|
||||||
|
spatialGridManager,
|
||||||
useScene,
|
useScene,
|
||||||
type WallEvent,
|
type WallEvent,
|
||||||
WindowNode,
|
WindowNode,
|
||||||
@@ -78,10 +79,17 @@ export const MoveWindowTool: React.FC<{ node: WindowNode }> = ({ node: movingWin
|
|||||||
if (wallId) useScene.getState().dirtyNodes.add(wallId as AnyNodeId)
|
if (wallId) useScene.getState().dirtyNodes.add(wallId as AnyNodeId)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const getLevelId = () => useViewer.getState().selection.levelId
|
||||||
const getLevelYOffset = () => {
|
const getLevelYOffset = () => {
|
||||||
const id = useViewer.getState().selection.levelId
|
const id = getLevelId()
|
||||||
return id ? (sceneRegistry.nodes.get(id as AnyNodeId)?.position.y ?? 0) : 0
|
return id ? (sceneRegistry.nodes.get(id as AnyNodeId)?.position.y ?? 0) : 0
|
||||||
}
|
}
|
||||||
|
const getSlabElevation = (wallEvent: WallEvent) =>
|
||||||
|
spatialGridManager.getSlabElevationForWall(
|
||||||
|
wallEvent.node.parentId ?? '',
|
||||||
|
wallEvent.node.start,
|
||||||
|
wallEvent.node.end,
|
||||||
|
)
|
||||||
|
|
||||||
const hideCursor = () => {
|
const hideCursor = () => {
|
||||||
if (cursorGroupRef.current) cursorGroupRef.current.visible = false
|
if (cursorGroupRef.current) cursorGroupRef.current.visible = false
|
||||||
@@ -102,6 +110,8 @@ export const MoveWindowTool: React.FC<{ node: WindowNode }> = ({ node: movingWin
|
|||||||
|
|
||||||
const onWallEnter = (event: WallEvent) => {
|
const onWallEnter = (event: WallEvent) => {
|
||||||
if (!isValidWallSideFace(event.normal)) return
|
if (!isValidWallSideFace(event.normal)) return
|
||||||
|
// Only interact with walls on the current level
|
||||||
|
if (event.node.parentId !== getLevelId()) return
|
||||||
|
|
||||||
const side = getSideFromNormal(event.normal)
|
const side = getSideFromNormal(event.normal)
|
||||||
const itemRotation = calculateItemRotation(event.normal)
|
const itemRotation = calculateItemRotation(event.normal)
|
||||||
@@ -134,12 +144,18 @@ export const MoveWindowTool: React.FC<{ node: WindowNode }> = ({ node: movingWin
|
|||||||
movingWindowNode.id,
|
movingWindowNode.id,
|
||||||
)
|
)
|
||||||
|
|
||||||
updateCursor(wallLocalToWorld(event.node, clampedX, clampedY, getLevelYOffset()), cursorRotation, valid)
|
updateCursor(
|
||||||
|
wallLocalToWorld(event.node, clampedX, clampedY, getLevelYOffset(), getSlabElevation(event)),
|
||||||
|
cursorRotation,
|
||||||
|
valid,
|
||||||
|
)
|
||||||
event.stopPropagation()
|
event.stopPropagation()
|
||||||
}
|
}
|
||||||
|
|
||||||
const onWallMove = (event: WallEvent) => {
|
const onWallMove = (event: WallEvent) => {
|
||||||
if (!isValidWallSideFace(event.normal)) return
|
if (!isValidWallSideFace(event.normal)) return
|
||||||
|
// Only interact with walls on the current level
|
||||||
|
if (event.node.parentId !== getLevelId()) return
|
||||||
|
|
||||||
const side = getSideFromNormal(event.normal)
|
const side = getSideFromNormal(event.normal)
|
||||||
const itemRotation = calculateItemRotation(event.normal)
|
const itemRotation = calculateItemRotation(event.normal)
|
||||||
@@ -172,12 +188,18 @@ export const MoveWindowTool: React.FC<{ node: WindowNode }> = ({ node: movingWin
|
|||||||
movingWindowNode.id,
|
movingWindowNode.id,
|
||||||
)
|
)
|
||||||
|
|
||||||
updateCursor(wallLocalToWorld(event.node, clampedX, clampedY, getLevelYOffset()), cursorRotation, valid)
|
updateCursor(
|
||||||
|
wallLocalToWorld(event.node, clampedX, clampedY, getLevelYOffset(), getSlabElevation(event)),
|
||||||
|
cursorRotation,
|
||||||
|
valid,
|
||||||
|
)
|
||||||
event.stopPropagation()
|
event.stopPropagation()
|
||||||
}
|
}
|
||||||
|
|
||||||
const onWallClick = (event: WallEvent) => {
|
const onWallClick = (event: WallEvent) => {
|
||||||
if (!isValidWallSideFace(event.normal)) return
|
if (!isValidWallSideFace(event.normal)) return
|
||||||
|
// Only interact with walls on the current level
|
||||||
|
if (event.node.parentId !== getLevelId()) return
|
||||||
|
|
||||||
const side = getSideFromNormal(event.normal)
|
const side = getSideFromNormal(event.normal)
|
||||||
const itemRotation = calculateItemRotation(event.normal)
|
const itemRotation = calculateItemRotation(event.normal)
|
||||||
|
|||||||
@@ -1,16 +1,18 @@
|
|||||||
import { type AnyNodeId, type ItemNode, useScene, type WallNode, type WindowNode } from '@pascal-app/core'
|
import { type AnyNodeId, type ItemNode, useScene, type WallNode, type WindowNode } from '@pascal-app/core'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Converts wall-local (X along wall, Y = height above level floor) to world XYZ.
|
* Converts wall-local (X along wall, Y = height above wall base) to world XYZ.
|
||||||
* Wall XZ uses level-local coordinates (levels only offset in Y, not XZ).
|
* Wall XZ uses level-local coordinates (levels only offset in Y, not XZ).
|
||||||
* Pass levelYOffset (the level group's current world Y) so the cursor lands at the
|
* Pass levelYOffset (the level group's current world Y) and slabElevation (the
|
||||||
* correct world height when the cursor group is at the scene root.
|
* wall mesh's Y within the level group) so the cursor lands at the correct world
|
||||||
|
* height — matching how WallSystem positions the wall mesh at slabElevation.
|
||||||
*/
|
*/
|
||||||
export function wallLocalToWorld(
|
export function wallLocalToWorld(
|
||||||
wallNode: WallNode,
|
wallNode: WallNode,
|
||||||
localX: number,
|
localX: number,
|
||||||
localY: number,
|
localY: number,
|
||||||
levelYOffset = 0,
|
levelYOffset = 0,
|
||||||
|
slabElevation = 0,
|
||||||
): [number, number, number] {
|
): [number, number, number] {
|
||||||
const wallAngle = Math.atan2(
|
const wallAngle = Math.atan2(
|
||||||
wallNode.end[1] - wallNode.start[1],
|
wallNode.end[1] - wallNode.start[1],
|
||||||
@@ -18,7 +20,7 @@ export function wallLocalToWorld(
|
|||||||
)
|
)
|
||||||
return [
|
return [
|
||||||
wallNode.start[0] + localX * Math.cos(wallAngle),
|
wallNode.start[0] + localX * Math.cos(wallAngle),
|
||||||
localY + levelYOffset,
|
slabElevation + localY + levelYOffset,
|
||||||
wallNode.start[1] + localX * Math.sin(wallAngle),
|
wallNode.start[1] + localX * Math.sin(wallAngle),
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import {
|
|||||||
type AnyNodeId,
|
type AnyNodeId,
|
||||||
emitter,
|
emitter,
|
||||||
sceneRegistry,
|
sceneRegistry,
|
||||||
|
spatialGridManager,
|
||||||
useScene,
|
useScene,
|
||||||
type WallEvent,
|
type WallEvent,
|
||||||
WindowNode,
|
WindowNode,
|
||||||
@@ -44,6 +45,12 @@ export const WindowTool: React.FC = () => {
|
|||||||
const id = getLevelId()
|
const id = getLevelId()
|
||||||
return id ? (sceneRegistry.nodes.get(id as AnyNodeId)?.position.y ?? 0) : 0
|
return id ? (sceneRegistry.nodes.get(id as AnyNodeId)?.position.y ?? 0) : 0
|
||||||
}
|
}
|
||||||
|
const getSlabElevation = (wallEvent: WallEvent) =>
|
||||||
|
spatialGridManager.getSlabElevationForWall(
|
||||||
|
wallEvent.node.parentId ?? '',
|
||||||
|
wallEvent.node.start,
|
||||||
|
wallEvent.node.end,
|
||||||
|
)
|
||||||
|
|
||||||
const markWallDirty = (wallId: string) => {
|
const markWallDirty = (wallId: string) => {
|
||||||
useScene.getState().dirtyNodes.add(wallId as AnyNodeId)
|
useScene.getState().dirtyNodes.add(wallId as AnyNodeId)
|
||||||
@@ -79,6 +86,8 @@ export const WindowTool: React.FC = () => {
|
|||||||
if (!isValidWallSideFace(event.normal)) return
|
if (!isValidWallSideFace(event.normal)) return
|
||||||
const levelId = getLevelId()
|
const levelId = getLevelId()
|
||||||
if (!levelId) return
|
if (!levelId) return
|
||||||
|
// Only interact with walls on the current level
|
||||||
|
if (event.node.parentId !== levelId) return
|
||||||
|
|
||||||
destroyDraft()
|
destroyDraft()
|
||||||
|
|
||||||
@@ -108,12 +117,18 @@ export const WindowTool: React.FC = () => {
|
|||||||
|
|
||||||
const valid = !hasWallChildOverlap(event.node.id, clampedX, clampedY, width, height, node.id)
|
const valid = !hasWallChildOverlap(event.node.id, clampedX, clampedY, width, height, node.id)
|
||||||
|
|
||||||
updateCursor(wallLocalToWorld(event.node, clampedX, clampedY, getLevelYOffset()), cursorRotation, valid)
|
updateCursor(
|
||||||
|
wallLocalToWorld(event.node, clampedX, clampedY, getLevelYOffset(), getSlabElevation(event)),
|
||||||
|
cursorRotation,
|
||||||
|
valid,
|
||||||
|
)
|
||||||
event.stopPropagation()
|
event.stopPropagation()
|
||||||
}
|
}
|
||||||
|
|
||||||
const onWallMove = (event: WallEvent) => {
|
const onWallMove = (event: WallEvent) => {
|
||||||
if (!isValidWallSideFace(event.normal)) return
|
if (!isValidWallSideFace(event.normal)) return
|
||||||
|
// Only interact with walls on the current level
|
||||||
|
if (event.node.parentId !== getLevelId()) return
|
||||||
|
|
||||||
const side = getSideFromNormal(event.normal)
|
const side = getSideFromNormal(event.normal)
|
||||||
const itemRotation = calculateItemRotation(event.normal)
|
const itemRotation = calculateItemRotation(event.normal)
|
||||||
@@ -142,13 +157,19 @@ export const WindowTool: React.FC = () => {
|
|||||||
draftRef.current?.id,
|
draftRef.current?.id,
|
||||||
)
|
)
|
||||||
|
|
||||||
updateCursor(wallLocalToWorld(event.node, clampedX, clampedY, getLevelYOffset()), cursorRotation, valid)
|
updateCursor(
|
||||||
|
wallLocalToWorld(event.node, clampedX, clampedY, getLevelYOffset(), getSlabElevation(event)),
|
||||||
|
cursorRotation,
|
||||||
|
valid,
|
||||||
|
)
|
||||||
event.stopPropagation()
|
event.stopPropagation()
|
||||||
}
|
}
|
||||||
|
|
||||||
const onWallClick = (event: WallEvent) => {
|
const onWallClick = (event: WallEvent) => {
|
||||||
if (!draftRef.current) return
|
if (!draftRef.current) return
|
||||||
if (!isValidWallSideFace(event.normal)) return
|
if (!isValidWallSideFace(event.normal)) return
|
||||||
|
// Only interact with walls on the current level
|
||||||
|
if (event.node.parentId !== getLevelId()) return
|
||||||
|
|
||||||
const side = getSideFromNormal(event.normal)
|
const side = getSideFromNormal(event.normal)
|
||||||
const itemRotation = calculateItemRotation(event.normal)
|
const itemRotation = calculateItemRotation(event.normal)
|
||||||
|
|||||||
Reference in New Issue
Block a user