fix stair building rotation
This commit is contained in:
@@ -29,9 +29,13 @@ export const MoveRoofTool: React.FC<{
|
||||
const [cursorWorldPos, setCursorWorldPos] = useState<[number, number, number]>(() => {
|
||||
const obj = sceneRegistry.nodes.get(movingNode.id)
|
||||
if (obj) {
|
||||
const pos = new THREE.Vector3()
|
||||
obj.getWorldPosition(pos)
|
||||
return [pos.x, pos.y, pos.z]
|
||||
const worldPos = obj.getWorldPosition(new THREE.Vector3())
|
||||
// Cursor renders inside the building-local ToolManager group, so convert
|
||||
// world → building-local to honor any building rotation.
|
||||
const buildingId = useViewer.getState().selection.buildingId
|
||||
const buildingObj = buildingId ? sceneRegistry.nodes.get(buildingId as AnyNodeId) : null
|
||||
if (buildingObj) buildingObj.worldToLocal(worldPos)
|
||||
return [worldPos.x, worldPos.y, worldPos.z]
|
||||
}
|
||||
// Fallback if not registered (e.g. newly created duplicate without mesh yet)
|
||||
if (
|
||||
@@ -114,10 +118,15 @@ export const MoveRoofTool: React.FC<{
|
||||
}
|
||||
}
|
||||
|
||||
const computeLocal = (gridX: number, gridZ: number, y: number): [number, number] => {
|
||||
let localX = gridX
|
||||
let localZ = gridZ
|
||||
|
||||
const computeLocal = (
|
||||
gridX: number,
|
||||
gridZ: number,
|
||||
y: number,
|
||||
buildingLocalX: number,
|
||||
buildingLocalZ: number,
|
||||
): [number, number] => {
|
||||
// Segments have a transformed parent (stair/roof). Convert world → parent-local
|
||||
// via Three.js hierarchy so the segment's stored position stays parent-relative.
|
||||
if (
|
||||
(movingNode.type === 'roof-segment' || movingNode.type === 'stair-segment') &&
|
||||
movingNode.parentId
|
||||
@@ -128,19 +137,21 @@ export const MoveRoofTool: React.FC<{
|
||||
if (parentObj) {
|
||||
const worldVec = new THREE.Vector3(gridX, y, gridZ)
|
||||
parentObj.worldToLocal(worldVec)
|
||||
localX = worldVec.x
|
||||
localZ = worldVec.z
|
||||
} else {
|
||||
return [worldVec.x, worldVec.z]
|
||||
}
|
||||
const dx = gridX - (parentNode.position[0] as number)
|
||||
const dz = gridZ - (parentNode.position[2] as number)
|
||||
const angle = -(parentNode.rotation as number)
|
||||
localX = dx * Math.cos(angle) - dz * Math.sin(angle)
|
||||
localZ = dx * Math.sin(angle) + dz * Math.cos(angle)
|
||||
}
|
||||
return [
|
||||
dx * Math.cos(angle) - dz * Math.sin(angle),
|
||||
dx * Math.sin(angle) + dz * Math.cos(angle),
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
return [localX, localZ]
|
||||
// Stair/roof live directly in the level — their stored position is building-local.
|
||||
// event.localPosition is already building-local, so using it handles building rotation.
|
||||
return [buildingLocalX, buildingLocalZ]
|
||||
}
|
||||
|
||||
const onGridMove = (event: GridEvent) => {
|
||||
@@ -161,7 +172,7 @@ export const MoveRoofTool: React.FC<{
|
||||
const lz = Math.round(event.localPosition[2] * 2) / 2
|
||||
setCursorWorldPos([lx, event.localPosition[1], lz])
|
||||
|
||||
const [localX, localZ] = computeLocal(gridX, gridZ, y)
|
||||
const [localX, localZ] = computeLocal(gridX, gridZ, y, lx, lz)
|
||||
|
||||
// Directly update the Three.js mesh — no store update during drag
|
||||
const mesh = sceneRegistry.nodes.get(movingNode.id)
|
||||
@@ -181,8 +192,10 @@ export const MoveRoofTool: React.FC<{
|
||||
const gridX = Math.round(event.position[0] * 2) / 2 // world, for computeLocal
|
||||
const gridZ = Math.round(event.position[2] * 2) / 2
|
||||
const y = event.position[1]
|
||||
const lx = Math.round(event.localPosition[0] * 2) / 2
|
||||
const lz = Math.round(event.localPosition[2] * 2) / 2
|
||||
|
||||
const [localX, localZ] = computeLocal(gridX, gridZ, y)
|
||||
const [localX, localZ] = computeLocal(gridX, gridZ, y, lx, lz)
|
||||
|
||||
wasCommitted = true
|
||||
|
||||
|
||||
Reference in New Issue
Block a user