From d819249d07b8e3041b2674c908d39fbecd940ffe Mon Sep 17 00:00:00 2001 From: wass08 Date: Fri, 20 Feb 2026 18:34:49 +0900 Subject: [PATCH] fix level window tools --- .../components/tools/window/move-window-tool.tsx | 10 ++++++++-- apps/editor/components/tools/window/window-math.ts | 9 ++++++--- apps/editor/components/tools/window/window-tool.tsx | 9 +++++++-- 3 files changed, 21 insertions(+), 7 deletions(-) diff --git a/apps/editor/components/tools/window/move-window-tool.tsx b/apps/editor/components/tools/window/move-window-tool.tsx index 3090c131..be2d343f 100644 --- a/apps/editor/components/tools/window/move-window-tool.tsx +++ b/apps/editor/components/tools/window/move-window-tool.tsx @@ -1,6 +1,7 @@ import { type AnyNodeId, emitter, + sceneRegistry, useScene, type WallEvent, WindowNode, @@ -77,6 +78,11 @@ export const MoveWindowTool: React.FC<{ node: WindowNode }> = ({ node: movingWin if (wallId) useScene.getState().dirtyNodes.add(wallId as AnyNodeId) } + const getLevelYOffset = () => { + const id = useViewer.getState().selection.levelId + return id ? (sceneRegistry.nodes.get(id as AnyNodeId)?.position.y ?? 0) : 0 + } + const hideCursor = () => { if (cursorGroupRef.current) cursorGroupRef.current.visible = false } @@ -128,7 +134,7 @@ export const MoveWindowTool: React.FC<{ node: WindowNode }> = ({ node: movingWin movingWindowNode.id, ) - updateCursor(wallLocalToWorld(event.node, clampedX, clampedY), cursorRotation, valid) + updateCursor(wallLocalToWorld(event.node, clampedX, clampedY, getLevelYOffset()), cursorRotation, valid) event.stopPropagation() } @@ -166,7 +172,7 @@ export const MoveWindowTool: React.FC<{ node: WindowNode }> = ({ node: movingWin movingWindowNode.id, ) - updateCursor(wallLocalToWorld(event.node, clampedX, clampedY), cursorRotation, valid) + updateCursor(wallLocalToWorld(event.node, clampedX, clampedY, getLevelYOffset()), cursorRotation, valid) event.stopPropagation() } diff --git a/apps/editor/components/tools/window/window-math.ts b/apps/editor/components/tools/window/window-math.ts index 9456b92f..5419dfd4 100644 --- a/apps/editor/components/tools/window/window-math.ts +++ b/apps/editor/components/tools/window/window-math.ts @@ -1,13 +1,16 @@ import { type AnyNodeId, type ItemNode, useScene, type WallNode, type WindowNode } from '@pascal-app/core' /** - * Converts wall-local (X along wall, Y = height) to world XYZ. - * Wall-local Y maps directly to world Y; X maps along the wall direction. + * Converts wall-local (X along wall, Y = height above level floor) to world XYZ. + * 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 + * correct world height when the cursor group is at the scene root. */ export function wallLocalToWorld( wallNode: WallNode, localX: number, localY: number, + levelYOffset = 0, ): [number, number, number] { const wallAngle = Math.atan2( wallNode.end[1] - wallNode.start[1], @@ -15,7 +18,7 @@ export function wallLocalToWorld( ) return [ wallNode.start[0] + localX * Math.cos(wallAngle), - localY, + localY + levelYOffset, wallNode.start[1] + localX * Math.sin(wallAngle), ] } diff --git a/apps/editor/components/tools/window/window-tool.tsx b/apps/editor/components/tools/window/window-tool.tsx index 285be100..3d275456 100644 --- a/apps/editor/components/tools/window/window-tool.tsx +++ b/apps/editor/components/tools/window/window-tool.tsx @@ -1,6 +1,7 @@ import { type AnyNodeId, emitter, + sceneRegistry, useScene, type WallEvent, WindowNode, @@ -39,6 +40,10 @@ export const WindowTool: React.FC = () => { useScene.temporal.getState().pause() const getLevelId = () => useViewer.getState().selection.levelId + const getLevelYOffset = () => { + const id = getLevelId() + return id ? (sceneRegistry.nodes.get(id as AnyNodeId)?.position.y ?? 0) : 0 + } const markWallDirty = (wallId: string) => { useScene.getState().dirtyNodes.add(wallId as AnyNodeId) @@ -103,7 +108,7 @@ export const WindowTool: React.FC = () => { const valid = !hasWallChildOverlap(event.node.id, clampedX, clampedY, width, height, node.id) - updateCursor(wallLocalToWorld(event.node, clampedX, clampedY), cursorRotation, valid) + updateCursor(wallLocalToWorld(event.node, clampedX, clampedY, getLevelYOffset()), cursorRotation, valid) event.stopPropagation() } @@ -137,7 +142,7 @@ export const WindowTool: React.FC = () => { draftRef.current?.id, ) - updateCursor(wallLocalToWorld(event.node, clampedX, clampedY), cursorRotation, valid) + updateCursor(wallLocalToWorld(event.node, clampedX, clampedY, getLevelYOffset()), cursorRotation, valid) event.stopPropagation() }