Merge origin/main into feat/placement-interaction-overhaul
Resolve 7 conflicts keeping our snapping migration + floorplan perf work as source of truth, combined with main's MEP run-continuation / Alt-detach / latch handles. Rebuilt two import blocks the auto-merge silently truncated (node-arrow-handles.tsx, duct-fitting/move-tool.tsx). Verified: tsc clean across core/viewer/editor/nodes/mcp, 451 tests pass, biome clean. Floorplan view-transform re-render storm confirmed pre-existing (not introduced by this merge). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -112,6 +112,7 @@ export const DoorSystem = () => {
|
||||
// Editing a scene material a door slot references must rebuild that door
|
||||
// (door meshes are built by this system, not <GeometrySystem>).
|
||||
useEffect(() => {
|
||||
void sceneMaterials
|
||||
const nodes = useScene.getState().nodes
|
||||
for (const node of Object.values(nodes)) {
|
||||
if (node?.type !== 'door') continue
|
||||
@@ -1109,6 +1110,7 @@ function addDoorLeaf(
|
||||
hingeX,
|
||||
hingeSide,
|
||||
swingRotation,
|
||||
openRotationY,
|
||||
segments,
|
||||
contentPadding,
|
||||
handle,
|
||||
@@ -1134,6 +1136,10 @@ function addDoorLeaf(
|
||||
hingeX: number
|
||||
hingeSide: 'left' | 'right'
|
||||
swingRotation: number
|
||||
// Leaf rotation (radians, about the hinge Y axis) at fully-open. The GLB
|
||||
// exporter reads this off the leaf group to bake an open/close clip; it is
|
||||
// the kinematic endpoint, independent of the current `swingRotation`.
|
||||
openRotationY: number
|
||||
segments: DoorNode['segments']
|
||||
contentPadding: DoorNode['contentPadding']
|
||||
handle: boolean
|
||||
@@ -1164,6 +1170,10 @@ function addDoorLeaf(
|
||||
const leafGroup = new THREE.Group()
|
||||
leafGroup.position.set(hingeX, 0, 0)
|
||||
leafGroup.rotation.y = swingRotation
|
||||
// Marks this group as the swing leaf and records its fully-open angle so the
|
||||
// GLB exporter can bake an open/close animation clip from a single pose. The
|
||||
// exporter strips this marker before writing the file.
|
||||
leafGroup.userData.pascalSwingLeaf = { axis: 'y', openRotationY }
|
||||
mesh.add(leafGroup)
|
||||
|
||||
const addLeafBox = (
|
||||
@@ -2486,6 +2496,7 @@ function updateDoorMesh(rawNode: DoorNode, mesh: THREE.Mesh) {
|
||||
hingeX: -insideWidth / 2,
|
||||
hingeSide: 'left',
|
||||
swingRotation: -clampedSwingAngle * swingDirectionSign,
|
||||
openRotationY: (-Math.PI / 2) * swingDirectionSign,
|
||||
segments,
|
||||
contentPadding,
|
||||
handle,
|
||||
@@ -2514,6 +2525,7 @@ function updateDoorMesh(rawNode: DoorNode, mesh: THREE.Mesh) {
|
||||
hingeX: insideWidth / 2,
|
||||
hingeSide: 'right',
|
||||
swingRotation: clampedSwingAngle * swingDirectionSign,
|
||||
openRotationY: (Math.PI / 2) * swingDirectionSign,
|
||||
segments,
|
||||
contentPadding,
|
||||
handle,
|
||||
@@ -2545,6 +2557,7 @@ function updateDoorMesh(rawNode: DoorNode, mesh: THREE.Mesh) {
|
||||
hingeX,
|
||||
hingeSide: hingesSide,
|
||||
swingRotation: clampedSwingAngle * swingDirectionSign * hingeDirectionSign,
|
||||
openRotationY: (Math.PI / 2) * swingDirectionSign * hingeDirectionSign,
|
||||
segments,
|
||||
contentPadding,
|
||||
handle,
|
||||
|
||||
Reference in New Issue
Block a user