@pascal-app/viewer 0.8.0 → 0.9.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/error-boundary.d.ts +6 -0
- package/dist/components/error-boundary.d.ts.map +1 -1
- package/dist/components/error-boundary.js +6 -0
- package/dist/components/renderers/node-renderer.d.ts +6 -2
- package/dist/components/renderers/node-renderer.d.ts.map +1 -1
- package/dist/components/renderers/node-renderer.js +41 -22
- package/dist/components/renderers/parametric-node-renderer.d.ts +5 -0
- package/dist/components/renderers/parametric-node-renderer.d.ts.map +1 -0
- package/dist/components/renderers/parametric-node-renderer.js +37 -0
- package/dist/components/renderers/scene-renderer.d.ts +1 -1
- package/dist/components/renderers/scene-renderer.d.ts.map +1 -1
- package/dist/components/viewer/bvh-ecctrl.d.ts +77 -0
- package/dist/components/viewer/bvh-ecctrl.d.ts.map +1 -0
- package/dist/components/viewer/bvh-ecctrl.js +552 -0
- package/dist/components/viewer/frame-limiter.d.ts.map +1 -1
- package/dist/components/viewer/frame-limiter.js +39 -4
- package/dist/components/viewer/glb-interactive.d.ts +41 -0
- package/dist/components/viewer/glb-interactive.d.ts.map +1 -0
- package/dist/components/viewer/glb-interactive.js +394 -0
- package/dist/components/viewer/glb-reference-nodes.d.ts +29 -0
- package/dist/components/viewer/glb-reference-nodes.d.ts.map +1 -0
- package/dist/components/viewer/glb-reference-nodes.js +80 -0
- package/dist/components/viewer/glb-replace-instances.d.ts +18 -0
- package/dist/components/viewer/glb-replace-instances.d.ts.map +1 -0
- package/dist/components/viewer/glb-replace-instances.js +61 -0
- package/dist/components/viewer/glb-scene.d.ts +54 -0
- package/dist/components/viewer/glb-scene.d.ts.map +1 -0
- package/dist/components/viewer/glb-scene.js +920 -0
- package/dist/components/viewer/glb-walkthrough-controller.d.ts +12 -0
- package/dist/components/viewer/glb-walkthrough-controller.d.ts.map +1 -0
- package/dist/components/viewer/glb-walkthrough-controller.js +357 -0
- package/dist/components/viewer/index.d.ts +56 -3
- package/dist/components/viewer/index.d.ts.map +1 -1
- package/dist/components/viewer/index.js +280 -65
- package/dist/components/viewer/lights.d.ts +1 -1
- package/dist/components/viewer/lights.d.ts.map +1 -1
- package/dist/components/viewer/lights.js +201 -43
- package/dist/components/viewer/perf-monitor.d.ts +1 -1
- package/dist/components/viewer/perf-monitor.d.ts.map +1 -1
- package/dist/components/viewer/perf-monitor.js +115 -12
- package/dist/components/viewer/post-processing.d.ts +7 -1
- package/dist/components/viewer/post-processing.d.ts.map +1 -1
- package/dist/components/viewer/post-processing.js +395 -63
- package/dist/components/viewer/registered-systems.d.ts +12 -0
- package/dist/components/viewer/registered-systems.d.ts.map +1 -0
- package/dist/components/viewer/registered-systems.js +49 -0
- package/dist/components/viewer/scene-bvh.d.ts +18 -0
- package/dist/components/viewer/scene-bvh.d.ts.map +1 -0
- package/dist/components/viewer/scene-bvh.js +97 -0
- package/dist/components/viewer/scene-bvh.test.d.ts +2 -0
- package/dist/components/viewer/scene-bvh.test.d.ts.map +1 -0
- package/dist/components/viewer/scene-bvh.test.js +13 -0
- package/dist/components/viewer/scene-environment.d.ts +2 -0
- package/dist/components/viewer/scene-environment.d.ts.map +1 -0
- package/dist/components/viewer/scene-environment.js +79 -0
- package/dist/components/viewer/selection-manager.d.ts +1 -1
- package/dist/components/viewer/selection-manager.d.ts.map +1 -1
- package/dist/components/viewer/selection-manager.js +37 -14
- package/dist/components/viewer/viewer-camera.d.ts +1 -1
- package/dist/components/viewer/viewer-camera.d.ts.map +1 -1
- package/dist/components/viewer/walkthrough-controls.d.ts +2 -1
- package/dist/components/viewer/walkthrough-controls.d.ts.map +1 -1
- package/dist/components/viewer/walkthrough-controls.js +20 -0
- package/dist/hooks/use-gltf-ktx2.d.ts.map +1 -1
- package/dist/hooks/use-gltf-ktx2.js +3 -22
- package/dist/hooks/use-node-events.d.ts +6 -74
- package/dist/hooks/use-node-events.d.ts.map +1 -1
- package/dist/hooks/use-node-events.js +28 -8
- package/dist/index.d.ts +48 -5
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +82 -4
- package/dist/lib/backdrop.d.ts +33 -0
- package/dist/lib/backdrop.d.ts.map +1 -0
- package/dist/lib/backdrop.js +92 -0
- package/dist/lib/box-uv.d.ts +13 -0
- package/dist/lib/box-uv.d.ts.map +1 -0
- package/dist/lib/box-uv.js +32 -0
- package/dist/lib/csg-utils.d.ts +10 -0
- package/dist/lib/csg-utils.d.ts.map +1 -0
- package/dist/lib/csg-utils.js +93 -0
- package/dist/lib/csg-utils.test.d.ts +2 -0
- package/dist/lib/csg-utils.test.d.ts.map +1 -0
- package/dist/lib/csg-utils.test.js +45 -0
- package/dist/lib/drawable-geometry.d.ts +21 -0
- package/dist/lib/drawable-geometry.d.ts.map +1 -0
- package/dist/lib/drawable-geometry.js +22 -0
- package/dist/lib/edge-style.d.ts +4 -0
- package/dist/lib/edge-style.d.ts.map +1 -0
- package/dist/lib/edge-style.js +31 -0
- package/dist/lib/gpu-perf.d.ts +4 -0
- package/dist/lib/gpu-perf.d.ts.map +1 -0
- package/dist/lib/gpu-perf.js +23 -0
- package/dist/lib/ink-edges.d.ts +9 -0
- package/dist/lib/ink-edges.d.ts.map +1 -0
- package/dist/lib/ink-edges.js +49 -0
- package/dist/lib/isolation.d.ts +39 -0
- package/dist/lib/isolation.d.ts.map +1 -0
- package/dist/lib/isolation.js +103 -0
- package/dist/lib/ktx2-loader.d.ts +43 -0
- package/dist/lib/ktx2-loader.d.ts.map +1 -0
- package/dist/lib/ktx2-loader.js +136 -0
- package/dist/lib/layers.d.ts +28 -0
- package/dist/lib/layers.d.ts.map +1 -1
- package/dist/lib/layers.js +28 -0
- package/dist/lib/materials.d.ts +38 -15
- package/dist/lib/materials.d.ts.map +1 -1
- package/dist/lib/materials.js +364 -72
- package/dist/lib/merged-outline-node.d.ts.map +1 -1
- package/dist/lib/merged-outline-node.js +7 -0
- package/dist/lib/polygon-union.d.ts +4 -0
- package/dist/lib/polygon-union.d.ts.map +1 -0
- package/dist/lib/polygon-union.js +289 -0
- package/dist/lib/polygon-union.test.d.ts +2 -0
- package/dist/lib/polygon-union.test.d.ts.map +1 -0
- package/dist/lib/polygon-union.test.js +105 -0
- package/dist/lib/scene-themes.d.ts +30 -0
- package/dist/lib/scene-themes.d.ts.map +1 -0
- package/dist/lib/scene-themes.js +202 -0
- package/dist/lib/shadow-only.d.ts +4 -0
- package/dist/lib/shadow-only.d.ts.map +1 -0
- package/dist/lib/shadow-only.js +36 -0
- package/dist/lib/tsl-compat.d.ts +12 -0
- package/dist/lib/tsl-compat.d.ts.map +1 -0
- package/dist/lib/tsl-compat.js +13 -0
- package/dist/store/use-viewer.d.ts +92 -12
- package/dist/store/use-viewer.d.ts.map +1 -1
- package/dist/store/use-viewer.js +201 -6
- package/dist/store/use-viewer.test.d.ts +2 -0
- package/dist/store/use-viewer.test.d.ts.map +1 -0
- package/dist/store/use-viewer.test.js +42 -0
- package/dist/systems/ceiling/ceiling-system.d.ts +6 -2
- package/dist/systems/ceiling/ceiling-system.d.ts.map +1 -1
- package/dist/systems/ceiling/ceiling-system.js +66 -13
- package/dist/systems/door/door-animation.test.d.ts +2 -0
- package/dist/systems/door/door-animation.test.d.ts.map +1 -0
- package/dist/systems/door/door-animation.test.js +51 -0
- package/dist/systems/door/door-floor-alignment.test.d.ts +2 -0
- package/dist/systems/door/door-floor-alignment.test.d.ts.map +1 -0
- package/dist/systems/door/door-floor-alignment.test.js +50 -0
- package/dist/systems/door/door-system.d.ts +24 -0
- package/dist/systems/door/door-system.d.ts.map +1 -1
- package/dist/systems/door/door-system.js +864 -180
- package/dist/systems/elevator/elevator-interaction-system.d.ts +2 -0
- package/dist/systems/elevator/elevator-interaction-system.d.ts.map +1 -0
- package/dist/systems/elevator/elevator-interaction-system.js +62 -0
- package/dist/systems/fence/fence-system.d.ts +20 -0
- package/dist/systems/fence/fence-system.d.ts.map +1 -1
- package/dist/systems/fence/fence-system.js +229 -57
- package/dist/systems/floor-elevation/floor-elevation-system.d.ts +20 -0
- package/dist/systems/floor-elevation/floor-elevation-system.d.ts.map +1 -0
- package/dist/systems/floor-elevation/floor-elevation-system.js +78 -0
- package/dist/systems/geometry/geometry-system.d.ts +41 -0
- package/dist/systems/geometry/geometry-system.d.ts.map +1 -0
- package/dist/systems/geometry/geometry-system.js +348 -0
- package/dist/systems/geometry/geometry-system.test.d.ts +2 -0
- package/dist/systems/geometry/geometry-system.test.d.ts.map +1 -0
- package/dist/systems/geometry/geometry-system.test.js +30 -0
- package/dist/systems/interactive/control-widget.d.ts +10 -0
- package/dist/systems/interactive/control-widget.d.ts.map +1 -0
- package/dist/systems/interactive/control-widget.js +35 -0
- package/dist/systems/interactive/interactive-system.d.ts +1 -1
- package/dist/systems/interactive/interactive-system.d.ts.map +1 -1
- package/dist/systems/interactive/interactive-system.js +55 -56
- package/dist/systems/item/item-system.d.ts +7 -0
- package/dist/systems/item/item-system.d.ts.map +1 -1
- package/dist/systems/item/item-system.js +28 -17
- package/dist/systems/item-light/item-light-system.d.ts +1 -1
- package/dist/systems/item-light/item-light-system.d.ts.map +1 -1
- package/dist/systems/item-light/item-light-system.js +18 -5
- package/dist/systems/level/level-system.d.ts.map +1 -1
- package/dist/systems/level/level-system.js +28 -4
- package/dist/systems/level/level-utils.d.ts +0 -3
- package/dist/systems/level/level-utils.d.ts.map +1 -1
- package/dist/systems/level/level-utils.js +2 -41
- package/dist/systems/roof/roof-materials.d.ts +3 -2
- package/dist/systems/roof/roof-materials.d.ts.map +1 -1
- package/dist/systems/roof/roof-materials.js +59 -14
- package/dist/systems/roof/roof-system.d.ts +46 -6
- package/dist/systems/roof/roof-system.d.ts.map +1 -1
- package/dist/systems/roof/roof-system.js +1365 -170
- package/dist/systems/slab/slab-system.d.ts +5 -3
- package/dist/systems/slab/slab-system.d.ts.map +1 -1
- package/dist/systems/slab/slab-system.js +204 -68
- package/dist/systems/slab/slab-system.test.d.ts +2 -0
- package/dist/systems/slab/slab-system.test.d.ts.map +1 -0
- package/dist/systems/slab/slab-system.test.js +63 -0
- package/dist/systems/stair/stair-materials.d.ts +4 -3
- package/dist/systems/stair/stair-materials.d.ts.map +1 -1
- package/dist/systems/stair/stair-materials.js +30 -15
- package/dist/systems/stair/stair-system.d.ts.map +1 -1
- package/dist/systems/stair/stair-system.js +55 -63
- package/dist/systems/surface-hole-geometry.d.ts +3 -0
- package/dist/systems/surface-hole-geometry.d.ts.map +1 -0
- package/dist/systems/surface-hole-geometry.js +4 -0
- package/dist/systems/wall/opening-cutout-geometry.d.ts +31 -0
- package/dist/systems/wall/opening-cutout-geometry.d.ts.map +1 -0
- package/dist/systems/wall/opening-cutout-geometry.js +167 -0
- package/dist/systems/wall/opening-cutout-geometry.test.d.ts +2 -0
- package/dist/systems/wall/opening-cutout-geometry.test.d.ts.map +1 -0
- package/dist/systems/wall/opening-cutout-geometry.test.js +172 -0
- package/dist/systems/wall/wall-cutout.d.ts.map +1 -1
- package/dist/systems/wall/wall-cutout.js +62 -17
- package/dist/systems/wall/wall-materials.d.ts +12 -7
- package/dist/systems/wall/wall-materials.d.ts.map +1 -1
- package/dist/systems/wall/wall-materials.js +279 -46
- package/dist/systems/wall/wall-opening-cutout.test.d.ts +2 -0
- package/dist/systems/wall/wall-opening-cutout.test.d.ts.map +1 -0
- package/dist/systems/wall/wall-opening-cutout.test.js +59 -0
- package/dist/systems/wall/wall-support-extension.test.d.ts +2 -0
- package/dist/systems/wall/wall-support-extension.test.d.ts.map +1 -0
- package/dist/systems/wall/wall-support-extension.test.js +48 -0
- package/dist/systems/wall/wall-system.d.ts +2 -2
- package/dist/systems/wall/wall-system.d.ts.map +1 -1
- package/dist/systems/wall/wall-system.js +493 -193
- package/dist/systems/window/window-animation-system.d.ts +12 -0
- package/dist/systems/window/window-animation-system.d.ts.map +1 -1
- package/dist/systems/window/window-animation-system.js +16 -5
- package/dist/systems/window/window-system.d.ts +7 -0
- package/dist/systems/window/window-system.d.ts.map +1 -1
- package/dist/systems/window/window-system.js +308 -18
- package/package.json +5 -6
- package/dist/components/renderers/building/building-renderer.d.ts +0 -5
- package/dist/components/renderers/building/building-renderer.d.ts.map +0 -1
- package/dist/components/renderers/building/building-renderer.js +0 -11
- package/dist/components/renderers/ceiling/ceiling-renderer.d.ts +0 -5
- package/dist/components/renderers/ceiling/ceiling-renderer.d.ts.map +0 -1
- package/dist/components/renderers/ceiling/ceiling-renderer.js +0 -58
- package/dist/components/renderers/column/column-renderer.d.ts +0 -5
- package/dist/components/renderers/column/column-renderer.d.ts.map +0 -1
- package/dist/components/renderers/column/column-renderer.js +0 -597
- package/dist/components/renderers/door/door-renderer.d.ts +0 -5
- package/dist/components/renderers/door/door-renderer.d.ts.map +0 -1
- package/dist/components/renderers/door/door-renderer.js +0 -16
- package/dist/components/renderers/fence/fence-renderer.d.ts +0 -5
- package/dist/components/renderers/fence/fence-renderer.d.ts.map +0 -1
- package/dist/components/renderers/fence/fence-renderer.js +0 -15
- package/dist/components/renderers/guide/guide-renderer.d.ts +0 -5
- package/dist/components/renderers/guide/guide-renderer.d.ts.map +0 -1
- package/dist/components/renderers/guide/guide-renderer.js +0 -38
- package/dist/components/renderers/item/item-renderer.d.ts +0 -5
- package/dist/components/renderers/item/item-renderer.d.ts.map +0 -1
- package/dist/components/renderers/item/item-renderer.js +0 -172
- package/dist/components/renderers/level/level-renderer.d.ts +0 -5
- package/dist/components/renderers/level/level-renderer.d.ts.map +0 -1
- package/dist/components/renderers/level/level-renderer.js +0 -11
- package/dist/components/renderers/roof/roof-materials.d.ts +0 -4
- package/dist/components/renderers/roof/roof-materials.d.ts.map +0 -1
- package/dist/components/renderers/roof/roof-materials.js +0 -16
- package/dist/components/renderers/roof/roof-renderer.d.ts +0 -5
- package/dist/components/renderers/roof/roof-renderer.d.ts.map +0 -1
- package/dist/components/renderers/roof/roof-renderer.js +0 -32
- package/dist/components/renderers/roof-segment/roof-segment-renderer.d.ts +0 -5
- package/dist/components/renderers/roof-segment/roof-segment-renderer.d.ts.map +0 -1
- package/dist/components/renderers/roof-segment/roof-segment-renderer.js +0 -40
- package/dist/components/renderers/scan/scan-renderer.d.ts +0 -5
- package/dist/components/renderers/scan/scan-renderer.d.ts.map +0 -1
- package/dist/components/renderers/scan/scan-renderer.js +0 -54
- package/dist/components/renderers/site/site-renderer.d.ts +0 -5
- package/dist/components/renderers/site/site-renderer.d.ts.map +0 -1
- package/dist/components/renderers/site/site-renderer.js +0 -106
- package/dist/components/renderers/slab/slab-renderer.d.ts +0 -5
- package/dist/components/renderers/slab/slab-renderer.d.ts.map +0 -1
- package/dist/components/renderers/slab/slab-renderer.js +0 -58
- package/dist/components/renderers/spawn/spawn-renderer.d.ts +0 -5
- package/dist/components/renderers/spawn/spawn-renderer.d.ts.map +0 -1
- package/dist/components/renderers/spawn/spawn-renderer.js +0 -32
- package/dist/components/renderers/stair/stair-renderer.d.ts +0 -5
- package/dist/components/renderers/stair/stair-renderer.d.ts.map +0 -1
- package/dist/components/renderers/stair/stair-renderer.js +0 -603
- package/dist/components/renderers/stair-segment/stair-segment-renderer.d.ts +0 -5
- package/dist/components/renderers/stair-segment/stair-segment-renderer.d.ts.map +0 -1
- package/dist/components/renderers/stair-segment/stair-segment-renderer.js +0 -51
- package/dist/components/renderers/wall/wall-renderer.d.ts +0 -5
- package/dist/components/renderers/wall/wall-renderer.d.ts.map +0 -1
- package/dist/components/renderers/wall/wall-renderer.js +0 -16
- package/dist/components/renderers/window/window-renderer.d.ts +0 -5
- package/dist/components/renderers/window/window-renderer.d.ts.map +0 -1
- package/dist/components/renderers/window/window-renderer.js +0 -21
- package/dist/components/renderers/zone/zone-renderer.d.ts +0 -5
- package/dist/components/renderers/zone/zone-renderer.d.ts.map +0 -1
- package/dist/components/renderers/zone/zone-renderer.js +0 -181
- package/dist/components/viewer/ground-occluder.d.ts +0 -2
- package/dist/components/viewer/ground-occluder.d.ts.map +0 -1
- package/dist/components/viewer/ground-occluder.js +0 -79
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import { sceneRegistry, useScene } from '@pascal-app/core';
|
|
1
|
+
import { getEffectiveNode, nodeRegistry, sceneRegistry, useLiveTransforms, useScene, } from '@pascal-app/core';
|
|
2
2
|
import { useFrame } from '@react-three/fiber';
|
|
3
3
|
import * as THREE from 'three';
|
|
4
|
+
import { mergeSurfaceHolePolygons } from '../surface-hole-geometry';
|
|
4
5
|
function ensureUv2Attribute(geometry) {
|
|
5
6
|
const uv = geometry.getAttribute('uv');
|
|
6
7
|
if (!uv)
|
|
@@ -20,11 +21,16 @@ export const CeilingSystem = () => {
|
|
|
20
21
|
// Process dirty ceilings
|
|
21
22
|
dirtyNodes.forEach((id) => {
|
|
22
23
|
const node = nodes[id];
|
|
23
|
-
if (
|
|
24
|
+
if (node?.type !== 'ceiling')
|
|
24
25
|
return;
|
|
25
26
|
const mesh = sceneRegistry.nodes.get(id);
|
|
26
27
|
if (mesh) {
|
|
27
|
-
|
|
28
|
+
// Merge any live drag override so the polygon / height resize
|
|
29
|
+
// arrow rebuilds the mesh at pointer rate — zustand only learns
|
|
30
|
+
// the final value on commit. Mirrors WallSystem / GeometrySystem.
|
|
31
|
+
const effective = getEffectiveNode(node);
|
|
32
|
+
const itemHoles = collectCeilingHoles(effective, nodes);
|
|
33
|
+
updateCeilingGeometry(effective, mesh, itemHoles);
|
|
28
34
|
clearDirty(id);
|
|
29
35
|
}
|
|
30
36
|
// If mesh not found, keep it dirty for next frame
|
|
@@ -32,28 +38,73 @@ export const CeilingSystem = () => {
|
|
|
32
38
|
});
|
|
33
39
|
return null;
|
|
34
40
|
};
|
|
41
|
+
/**
|
|
42
|
+
* Collects ceiling-hole polygons from child nodes that declare the `ceilingCut`
|
|
43
|
+
* capability. Each child's `buildCeilingHole` returns a rotated-rectangle
|
|
44
|
+
* footprint in ceiling-local [x, z] space (or `null` to opt out), which is
|
|
45
|
+
* merged as an extra hole before triangulation.
|
|
46
|
+
*
|
|
47
|
+
* The viewer never branches on `child.type` — the dispatch goes through
|
|
48
|
+
* `nodeRegistry`, so any future kind (a heat lamp, a skylight panel, …) can
|
|
49
|
+
* participate just by declaring `capabilities.ceilingCut` on its definition.
|
|
50
|
+
*/
|
|
51
|
+
function collectCeilingHoles(ceiling, nodes) {
|
|
52
|
+
const holes = [];
|
|
53
|
+
for (const childId of ceiling.children ?? []) {
|
|
54
|
+
const child = nodes[childId];
|
|
55
|
+
if (!child)
|
|
56
|
+
continue;
|
|
57
|
+
const def = nodeRegistry.get(child.type);
|
|
58
|
+
const hole = def?.capabilities?.ceilingCut?.buildCeilingHole(child);
|
|
59
|
+
if (hole)
|
|
60
|
+
holes.push(hole);
|
|
61
|
+
}
|
|
62
|
+
return holes;
|
|
63
|
+
}
|
|
35
64
|
/**
|
|
36
65
|
* Updates the geometry for a single ceiling
|
|
37
66
|
*/
|
|
38
|
-
function updateCeilingGeometry(node, mesh) {
|
|
39
|
-
const newGeo = generateCeilingGeometry(node);
|
|
67
|
+
function updateCeilingGeometry(node, mesh, extraHoles = []) {
|
|
68
|
+
const newGeo = generateCeilingGeometry(node, extraHoles);
|
|
40
69
|
mesh.geometry.dispose();
|
|
41
70
|
mesh.geometry = newGeo;
|
|
42
71
|
const gridMesh = mesh.getObjectByName('ceiling-grid');
|
|
43
72
|
if (gridMesh) {
|
|
44
73
|
gridMesh.geometry.dispose();
|
|
45
|
-
gridMesh.geometry = newGeo;
|
|
74
|
+
gridMesh.geometry = newGeo.clone();
|
|
46
75
|
}
|
|
47
|
-
// Position at the ceiling height
|
|
48
|
-
|
|
76
|
+
// Position at the ceiling height and reset X/Z so live-drag mesh
|
|
77
|
+
// offsets (set by move tools during the drag) don't leak into the
|
|
78
|
+
// canonical position after the rebuild. Matches the pattern used by
|
|
79
|
+
// FenceSystem.updateFenceGeometry / GeometrySystem (both fully reset
|
|
80
|
+
// position+rotation after rebuild).
|
|
81
|
+
const liveTransform = useLiveTransforms.getState().get(node.id);
|
|
82
|
+
mesh.position.x = liveTransform?.position[0] ?? 0;
|
|
83
|
+
mesh.position.z = liveTransform?.position[2] ?? 0;
|
|
84
|
+
mesh.position.y = (node.height ?? 2.5) - 0.01 + (liveTransform?.position[1] ?? 0); // Slight offset to avoid z-fighting with upper-level slabs
|
|
49
85
|
}
|
|
50
86
|
/**
|
|
51
|
-
* Generates flat ceiling geometry from polygon (no extrusion)
|
|
87
|
+
* Generates flat ceiling geometry from polygon (no extrusion).
|
|
88
|
+
*
|
|
89
|
+
* `extraHoles` are transient, derived cutouts (e.g. recessed-fixture
|
|
90
|
+
* footprints) that are cut alongside the node's persisted `holes` but never
|
|
91
|
+
* stored on the node — they are recomputed on every rebuild.
|
|
52
92
|
*/
|
|
53
|
-
export function generateCeilingGeometry(ceilingNode) {
|
|
93
|
+
export function generateCeilingGeometry(ceilingNode, extraHoles = []) {
|
|
54
94
|
const polygon = ceilingNode.polygon;
|
|
55
95
|
if (polygon.length < 3) {
|
|
56
|
-
|
|
96
|
+
// A degenerate ceiling (fewer than 3 points, e.g. mid-edit) still gets a
|
|
97
|
+
// non-empty position buffer — three zero-vertices forming one invisible
|
|
98
|
+
// triangle. An empty attribute (count 0) would leave WebGPU vertex buffer
|
|
99
|
+
// slot 0 unbound when this mesh (and its cloned grid overlay) is drawn,
|
|
100
|
+
// which the validator rejects ("slot 0 … was not set") and which poisons
|
|
101
|
+
// the whole command encoder.
|
|
102
|
+
const degenerate = new THREE.BufferGeometry();
|
|
103
|
+
degenerate.setAttribute('position', new THREE.Float32BufferAttribute(new Float32Array(9), 3));
|
|
104
|
+
degenerate.setAttribute('normal', new THREE.Float32BufferAttribute(new Float32Array(9), 3));
|
|
105
|
+
degenerate.setAttribute('uv', new THREE.Float32BufferAttribute(new Float32Array(6), 2));
|
|
106
|
+
degenerate.setAttribute('uv2', new THREE.Float32BufferAttribute(new Float32Array(6), 2));
|
|
107
|
+
return degenerate;
|
|
57
108
|
}
|
|
58
109
|
// Create shape from polygon
|
|
59
110
|
// Shape is in X-Y plane, we'll rotate to X-Z plane
|
|
@@ -66,8 +117,10 @@ export function generateCeilingGeometry(ceilingNode) {
|
|
|
66
117
|
shape.lineTo(pt[0], -pt[1]);
|
|
67
118
|
}
|
|
68
119
|
shape.closePath();
|
|
69
|
-
// Add holes to the shape
|
|
70
|
-
|
|
120
|
+
// Add holes to the shape: persisted structural openings (stair/elevator/
|
|
121
|
+
// manual, merged to dissolve overlaps) plus transient recessed-fixture
|
|
122
|
+
// cutouts. Both are in the same ceiling-local [x, z] space.
|
|
123
|
+
const holes = [...mergeSurfaceHolePolygons(ceilingNode.holes || []), ...extraHoles];
|
|
71
124
|
for (const holePolygon of holes) {
|
|
72
125
|
if (holePolygon.length < 3)
|
|
73
126
|
continue;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"door-animation.test.d.ts","sourceRoot":"","sources":["../../../src/systems/door/door-animation.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
// @ts-expect-error — bun:test is provided by the Bun runtime; viewer does not
|
|
2
|
+
// depend on @types/bun so the import type is unresolved at compile time.
|
|
3
|
+
import { describe, expect, test } from 'bun:test';
|
|
4
|
+
import { DoorNode } from '@pascal-app/core';
|
|
5
|
+
import * as THREE from 'three';
|
|
6
|
+
import { buildDoorPreviewMesh, poseDoorMovingParts } from '../../index';
|
|
7
|
+
// The named moving group each operation-door builder emits at the closed pose.
|
|
8
|
+
const MOVING_GROUP = {
|
|
9
|
+
sliding: 'door-sliding-active',
|
|
10
|
+
pocket: 'door-pocket-leaf',
|
|
11
|
+
barn: 'door-barn-leaf',
|
|
12
|
+
'garage-tiltup': 'door-tiltup-leaf',
|
|
13
|
+
folding: 'door-fold-0',
|
|
14
|
+
'garage-sectional': 'door-sectional-0',
|
|
15
|
+
'garage-rollup': 'door-rollup-curtain',
|
|
16
|
+
};
|
|
17
|
+
function worldPosition(object) {
|
|
18
|
+
object.updateMatrixWorld(true);
|
|
19
|
+
return object.getWorldPosition(new THREE.Vector3());
|
|
20
|
+
}
|
|
21
|
+
describe('operation door open kinematics', () => {
|
|
22
|
+
// Each operation door builds its moving parts in a named group at the closed
|
|
23
|
+
// pose; `poseDoorMovingParts` then drives the open motion (the single source
|
|
24
|
+
// of truth shared by the live system and the GLB exporter). This guards the
|
|
25
|
+
// build-once + pose-at-t contract: the group exists, rests closed, and moves.
|
|
26
|
+
for (const doorType of Object.keys(MOVING_GROUP)) {
|
|
27
|
+
test(`${doorType} builds a moving group that opens`, () => {
|
|
28
|
+
const node = DoorNode.parse({ id: `door_${doorType}`, doorType, operationState: 0 });
|
|
29
|
+
const mesh = buildDoorPreviewMesh(node);
|
|
30
|
+
const group = mesh.getObjectByName(MOVING_GROUP[doorType]);
|
|
31
|
+
expect(group).toBeDefined();
|
|
32
|
+
// Closed snapshot.
|
|
33
|
+
poseDoorMovingParts(node, mesh, 0);
|
|
34
|
+
const closedPos = worldPosition(group);
|
|
35
|
+
const closedScaleY = group.scale.y;
|
|
36
|
+
const closedRotX = group.rotation.x;
|
|
37
|
+
const closedRotY = group.rotation.y;
|
|
38
|
+
// Open snapshot — at least one of translation / rotation / scale changes.
|
|
39
|
+
poseDoorMovingParts(node, mesh, 1);
|
|
40
|
+
const openPos = worldPosition(group);
|
|
41
|
+
const moved = closedPos.distanceTo(openPos) > 0.05 ||
|
|
42
|
+
Math.abs(closedScaleY - group.scale.y) > 0.1 ||
|
|
43
|
+
Math.abs(closedRotX - group.rotation.x) > 0.05 ||
|
|
44
|
+
Math.abs(closedRotY - group.rotation.y) > 0.05;
|
|
45
|
+
expect(moved).toBe(true);
|
|
46
|
+
// Posing back to closed is the identity of the rest pose.
|
|
47
|
+
poseDoorMovingParts(node, mesh, 0);
|
|
48
|
+
expect(worldPosition(group).distanceTo(closedPos)).toBeLessThan(1e-6);
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"door-floor-alignment.test.d.ts","sourceRoot":"","sources":["../../../src/systems/door/door-floor-alignment.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
// @ts-expect-error — bun:test is provided by the Bun runtime; viewer does not
|
|
2
|
+
// depend on @types/bun so the import type is unresolved at compile time.
|
|
3
|
+
import { describe, expect, test } from 'bun:test';
|
|
4
|
+
import { DoorNode } from '@pascal-app/core';
|
|
5
|
+
import * as THREE from 'three';
|
|
6
|
+
import { buildDoorPreviewMesh } from '../../index';
|
|
7
|
+
const DOOR_TYPES = [
|
|
8
|
+
'hinged',
|
|
9
|
+
'double',
|
|
10
|
+
'french',
|
|
11
|
+
'folding',
|
|
12
|
+
'pocket',
|
|
13
|
+
'barn',
|
|
14
|
+
'sliding',
|
|
15
|
+
'garage-sectional',
|
|
16
|
+
'garage-rollup',
|
|
17
|
+
'garage-tiltup',
|
|
18
|
+
];
|
|
19
|
+
function visibleBounds(mesh) {
|
|
20
|
+
mesh.updateMatrixWorld(true);
|
|
21
|
+
const bounds = new THREE.Box3();
|
|
22
|
+
for (const child of mesh.children) {
|
|
23
|
+
if (child.name === 'cutout')
|
|
24
|
+
continue;
|
|
25
|
+
bounds.expandByObject(child, true);
|
|
26
|
+
}
|
|
27
|
+
return bounds;
|
|
28
|
+
}
|
|
29
|
+
describe('door floor alignment', () => {
|
|
30
|
+
for (const doorType of DOOR_TYPES) {
|
|
31
|
+
test(`${doorType} does not extend below the opening floor`, () => {
|
|
32
|
+
const node = DoorNode.parse({
|
|
33
|
+
id: `door_floor-alignment-${doorType}`,
|
|
34
|
+
doorType,
|
|
35
|
+
operationState: 0,
|
|
36
|
+
threshold: true,
|
|
37
|
+
});
|
|
38
|
+
const mesh = buildDoorPreviewMesh(node);
|
|
39
|
+
const bounds = visibleBounds(mesh);
|
|
40
|
+
expect(bounds.min.y).toBeGreaterThanOrEqual(-node.height / 2 - 1e-6);
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
test('keeps the wall cutout bottom locked to the opening floor', () => {
|
|
44
|
+
const node = DoorNode.parse({ id: 'door_floor-alignment-cutout' });
|
|
45
|
+
const mesh = buildDoorPreviewMesh(node);
|
|
46
|
+
const cutout = mesh.getObjectByName('cutout');
|
|
47
|
+
cutout.geometry.computeBoundingBox();
|
|
48
|
+
expect(cutout.geometry.boundingBox?.min.y).toBeCloseTo(-node.height / 2, 6);
|
|
49
|
+
});
|
|
50
|
+
});
|
|
@@ -1,2 +1,26 @@
|
|
|
1
|
+
import { type DoorNode } from '@pascal-app/core';
|
|
2
|
+
import * as THREE from 'three';
|
|
1
3
|
export declare const DoorSystem: () => null;
|
|
4
|
+
/**
|
|
5
|
+
* Pose an operation door's moving parts (sliding/pocket/barn leaf, tilt-up and
|
|
6
|
+
* sectional panels, folding chain, roll-up curtain) at `value` (0 = closed,
|
|
7
|
+
* 1 = open) by transforming the named groups its builder emitted at the closed
|
|
8
|
+
* pose. Returns true when the door type has a pose path and its groups exist.
|
|
9
|
+
*
|
|
10
|
+
* Mirrors `poseWindowMovingParts`: the live door system calls it after a
|
|
11
|
+
* (re)build so `operationState` is reflected, and the GLB exporter calls it on a
|
|
12
|
+
* clone to sample keyframes. Swing doors are not handled here — their leaf group
|
|
13
|
+
* carries a `pascalSwingLeaf` marker the exporter reads directly.
|
|
14
|
+
*
|
|
15
|
+
* Roll-up is the one type whose live geometry changes (slats vanish onto a
|
|
16
|
+
* drum), which a glTF clip can't express; the baked approximation scales the
|
|
17
|
+
* curtain up into the lintel. The live roll-up animation keeps its full-detail
|
|
18
|
+
* rebuild and is intentionally NOT routed through this scale.
|
|
19
|
+
*/
|
|
20
|
+
export declare function poseDoorMovingParts(node: DoorNode, mesh: THREE.Object3D | undefined, value: number): boolean;
|
|
21
|
+
/**
|
|
22
|
+
* Build a fresh door mesh for preview/ghost rendering.
|
|
23
|
+
* Returns a mesh with an invisible hitbox root and visible children (frame, panels, hardware).
|
|
24
|
+
*/
|
|
25
|
+
export declare function buildDoorPreviewMesh(node: DoorNode): THREE.Mesh;
|
|
2
26
|
//# sourceMappingURL=door-system.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"door-system.d.ts","sourceRoot":"","sources":["../../../src/systems/door/door-system.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"door-system.d.ts","sourceRoot":"","sources":["../../../src/systems/door/door-system.tsx"],"names":[],"mappings":"AAAA,OAAO,EAIL,KAAK,QAAQ,EAYd,MAAM,kBAAkB,CAAA;AAGzB,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AA0D9B,eAAO,MAAM,UAAU,YA6GtB,CAAA;AAupCD;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,mBAAmB,CACjC,IAAI,EAAE,QAAQ,EACd,IAAI,EAAE,KAAK,CAAC,QAAQ,GAAG,SAAS,EAChC,KAAK,EAAE,MAAM,GACZ,OAAO,CA6GT;AAyuCD;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,QAAQ,GAAG,KAAK,CAAC,IAAI,CAI/D"}
|