@pascal-app/viewer 0.7.0 → 0.8.0

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.
Files changed (55) hide show
  1. package/dist/components/renderers/column/column-renderer.d.ts.map +1 -1
  2. package/dist/components/renderers/column/column-renderer.js +5 -2
  3. package/dist/components/renderers/fence/fence-renderer.d.ts.map +1 -1
  4. package/dist/components/renderers/fence/fence-renderer.js +2 -16
  5. package/dist/components/renderers/slab/slab-renderer.js +1 -1
  6. package/dist/components/renderers/stair/stair-renderer.js +3 -3
  7. package/dist/components/renderers/stair-segment/stair-segment-renderer.d.ts.map +1 -1
  8. package/dist/components/renderers/stair-segment/stair-segment-renderer.js +20 -1
  9. package/dist/components/viewer/frame-limiter.d.ts.map +1 -1
  10. package/dist/components/viewer/frame-limiter.js +5 -1
  11. package/dist/components/viewer/index.d.ts +1 -0
  12. package/dist/components/viewer/index.d.ts.map +1 -1
  13. package/dist/components/viewer/index.js +7 -7
  14. package/dist/components/viewer/post-processing.d.ts.map +1 -1
  15. package/dist/components/viewer/post-processing.js +0 -21
  16. package/dist/index.d.ts +1 -1
  17. package/dist/index.d.ts.map +1 -1
  18. package/dist/index.js +1 -1
  19. package/dist/lib/materials.d.ts.map +1 -1
  20. package/dist/lib/materials.js +2 -3
  21. package/dist/lib/merged-outline-node.d.ts.map +1 -1
  22. package/dist/lib/merged-outline-node.js +4 -11
  23. package/dist/systems/ceiling/ceiling-system.d.ts.map +1 -1
  24. package/dist/systems/ceiling/ceiling-system.js +1 -1
  25. package/dist/systems/fence/fence-system.d.ts.map +1 -1
  26. package/dist/systems/fence/fence-system.js +1 -1
  27. package/dist/systems/guide/guide-system.d.ts.map +1 -1
  28. package/dist/systems/guide/guide-system.js +1 -26
  29. package/dist/systems/item/item-system.js +1 -1
  30. package/dist/systems/roof/roof-system.d.ts.map +1 -1
  31. package/dist/systems/roof/roof-system.js +16 -13
  32. package/dist/systems/scan/scan-system.d.ts.map +1 -1
  33. package/dist/systems/scan/scan-system.js +1 -26
  34. package/dist/systems/slab/slab-system.d.ts.map +1 -1
  35. package/dist/systems/slab/slab-system.js +1 -1
  36. package/dist/systems/stair/stair-system.js +9 -11
  37. package/dist/systems/wall/wall-system.d.ts +1 -1
  38. package/dist/systems/wall/wall-system.d.ts.map +1 -1
  39. package/dist/systems/wall/wall-system.js +8 -5
  40. package/package.json +3 -3
  41. package/dist/lib/suppress-three-clock-warning.d.ts +0 -25
  42. package/dist/lib/suppress-three-clock-warning.d.ts.map +0 -1
  43. package/dist/lib/suppress-three-clock-warning.js +0 -51
  44. package/dist/systems/export/export-system.d.ts +0 -2
  45. package/dist/systems/export/export-system.d.ts.map +0 -1
  46. package/dist/systems/export/export-system.js +0 -60
  47. package/dist/systems/item-mesh-metadata/compute-item-mesh-metadata.d.ts +0 -14
  48. package/dist/systems/item-mesh-metadata/compute-item-mesh-metadata.d.ts.map +0 -1
  49. package/dist/systems/item-mesh-metadata/compute-item-mesh-metadata.js +0 -155
  50. package/dist/systems/item-mesh-metadata/item-mesh-metadata-system.d.ts +0 -6
  51. package/dist/systems/item-mesh-metadata/item-mesh-metadata-system.d.ts.map +0 -1
  52. package/dist/systems/item-mesh-metadata/item-mesh-metadata-system.js +0 -75
  53. package/dist/systems/item-mesh-metadata/sync-request.d.ts +0 -7
  54. package/dist/systems/item-mesh-metadata/sync-request.d.ts.map +0 -1
  55. package/dist/systems/item-mesh-metadata/sync-request.js +0 -25
@@ -1 +1 @@
1
- {"version":3,"file":"column-renderer.d.ts","sourceRoot":"","sources":["../../../../src/components/renderers/column/column-renderer.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,UAAU,EAAkC,MAAM,kBAAkB,CAAA;AA64ClF,eAAO,MAAM,cAAc,GAAI,UAAU;IAAE,IAAI,EAAE,UAAU,CAAA;CAAE,4CA0E5D,CAAA"}
1
+ {"version":3,"file":"column-renderer.d.ts","sourceRoot":"","sources":["../../../../src/components/renderers/column/column-renderer.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,UAAU,EAAkC,MAAM,kBAAkB,CAAA;AAs6ClF,eAAO,MAAM,cAAc,GAAI,UAAU;IAAE,IAAI,EAAE,UAAU,CAAA;CAAE,4CA0E5D,CAAA"}
@@ -348,6 +348,9 @@ function Flutes({ node, shaftY, shaftHeight, }) {
348
348
  return (_jsx(MappedCylinder, { height: shaftHeight * 0.92, position: [x, shaftY + shaftHeight / 2, z], radius: fluteRadius, segments: 8 }, index));
349
349
  }) }));
350
350
  }
351
+ function DravidianPanelFace({ position, rotation = 0, panelHeight, panelWidth, rail, reliefDepth, panelShape, }) {
352
+ return (_jsxs("group", { position: position, rotation: [0, rotation, 0], children: [_jsx(MappedBox, { depth: reliefDepth, height: rail, position: [0, panelHeight / 2, 0], softenEdges: false, width: panelWidth }), _jsx(MappedBox, { depth: reliefDepth, height: rail, position: [0, -panelHeight / 2, 0], softenEdges: false, width: panelWidth }), _jsx(MappedBox, { depth: reliefDepth, height: panelHeight, position: [panelWidth / 2, 0, 0], softenEdges: false, width: rail }), _jsx(MappedBox, { depth: reliefDepth, height: panelHeight, position: [-panelWidth / 2, 0, 0], softenEdges: false, width: rail }), panelShape === 'diamond' && (_jsx(MappedBox, { depth: reliefDepth, height: panelHeight * 0.42, position: [0, 0, 0], rotation: [0, 0, Math.PI / 4], softenEdges: false, width: rail * 1.2 })), panelShape === 'arched' && (_jsx(MappedTorus, { arc: Math.PI, position: [0, panelHeight * 0.28, 0], ringRadius: panelWidth * 0.42, scaleX: panelWidth * 0.42, scaleY: rail, scaleZ: reliefDepth, tubeRadius: Math.max(rail, reliefDepth) * 0.18 }))] }));
353
+ }
351
354
  function DravidianShaftPanels({ node, shaftY, shaftHeight, }) {
352
355
  const panelCount = Math.max(node.panelCount ?? 0, node.style === 'dravidian-carved' || node.shaftDetail === 'panelled' ? 3 : 0);
353
356
  if (panelCount <= 0 || shaftHeight <= 0)
@@ -360,10 +363,10 @@ function DravidianShaftPanels({ node, shaftY, shaftHeight, }) {
360
363
  const reliefDepth = Math.max(0.012, node.panelInsetDepth ?? node.width * 0.025);
361
364
  const rows = Array.from({ length: panelCount }, (_, index) => (index + 1) / (panelCount + 1));
362
365
  const panelShape = node.panelShape ?? 'rectangle';
363
- const PanelFace = ({ position, rotation = 0, }) => (_jsxs("group", { position: position, rotation: [0, rotation, 0], children: [_jsx(MappedBox, { depth: reliefDepth, height: rail, position: [0, panelHeight / 2, 0], softenEdges: false, width: panelWidth }), _jsx(MappedBox, { depth: reliefDepth, height: rail, position: [0, -panelHeight / 2, 0], softenEdges: false, width: panelWidth }), _jsx(MappedBox, { depth: reliefDepth, height: panelHeight, position: [panelWidth / 2, 0, 0], softenEdges: false, width: rail }), _jsx(MappedBox, { depth: reliefDepth, height: panelHeight, position: [-panelWidth / 2, 0, 0], softenEdges: false, width: rail }), panelShape === 'diamond' && (_jsx(MappedBox, { depth: reliefDepth, height: panelHeight * 0.42, position: [0, 0, 0], rotation: [0, 0, Math.PI / 4], softenEdges: false, width: rail * 1.2 })), panelShape === 'arched' && (_jsx(MappedTorus, { arc: Math.PI, position: [0, panelHeight * 0.28, 0], ringRadius: panelWidth * 0.42, scaleX: panelWidth * 0.42, scaleY: rail, scaleZ: reliefDepth, tubeRadius: Math.max(rail, reliefDepth) * 0.18 }))] }));
366
+ const faceProps = { panelHeight, panelWidth, rail, reliefDepth, panelShape };
364
367
  return (_jsx("group", { children: rows.map((t, rowIndex) => {
365
368
  const y = shaftY + shaftHeight * t;
366
- return (_jsxs("group", { children: [_jsx(PanelFace, { position: [0, y, shaftDepth / 2 + reliefDepth / 2] }), _jsx(PanelFace, { position: [0, y, -shaftDepth / 2 - reliefDepth / 2] }), _jsx(PanelFace, { position: [shaftWidth / 2 + reliefDepth / 2, y, 0], rotation: Math.PI / 2 }), _jsx(PanelFace, { position: [-shaftWidth / 2 - reliefDepth / 2, y, 0], rotation: Math.PI / 2 })] }, rowIndex));
369
+ return (_jsxs("group", { children: [_jsx(DravidianPanelFace, { position: [0, y, shaftDepth / 2 + reliefDepth / 2], ...faceProps }), _jsx(DravidianPanelFace, { position: [0, y, -shaftDepth / 2 - reliefDepth / 2], ...faceProps }), _jsx(DravidianPanelFace, { position: [shaftWidth / 2 + reliefDepth / 2, y, 0], rotation: Math.PI / 2, ...faceProps }), _jsx(DravidianPanelFace, { position: [-shaftWidth / 2 - reliefDepth / 2, y, 0], rotation: Math.PI / 2, ...faceProps })] }, rowIndex));
367
370
  }) }));
368
371
  }
369
372
  function SpiralRibs({ node, shaftY, shaftHeight, }) {
@@ -1 +1 @@
1
- {"version":3,"file":"fence-renderer.d.ts","sourceRoot":"","sources":["../../../../src/components/renderers/fence/fence-renderer.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,SAAS,EAAyB,MAAM,kBAAkB,CAAA;AAUxE,eAAO,MAAM,aAAa,GAAI,UAAU;IAAE,IAAI,EAAE,SAAS,CAAA;CAAE,4CAkC1D,CAAA"}
1
+ {"version":3,"file":"fence-renderer.d.ts","sourceRoot":"","sources":["../../../../src/components/renderers/fence/fence-renderer.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,SAAS,EAAyB,MAAM,kBAAkB,CAAA;AAMxE,eAAO,MAAM,aAAa,GAAI,UAAU;IAAE,IAAI,EAAE,SAAS,CAAA;CAAE,4CAsB1D,CAAA"}
@@ -2,25 +2,11 @@ import { jsx as _jsx } from "react/jsx-runtime";
2
2
  import { useRegistry, useScene } from '@pascal-app/core';
3
3
  import { useLayoutEffect, useMemo, useRef } from 'react';
4
4
  import { useNodeEvents } from '../../../hooks/use-node-events';
5
- import { createMaterial, createMaterialFromPresetRef, DEFAULT_STAIR_MATERIAL, } from '../../../lib/materials';
5
+ import { DEFAULT_STAIR_MATERIAL } from '../../../lib/materials';
6
6
  export const FenceRenderer = ({ node }) => {
7
7
  const ref = useRef(null);
8
8
  const handlers = useNodeEvents(node, 'fence');
9
- const material = useMemo(() => {
10
- const presetMaterial = createMaterialFromPresetRef(node.materialPreset);
11
- if (presetMaterial)
12
- return presetMaterial;
13
- const mat = node.material;
14
- if (!mat)
15
- return DEFAULT_STAIR_MATERIAL;
16
- return createMaterial(mat);
17
- }, [
18
- node.materialPreset,
19
- node.material,
20
- node.material?.preset,
21
- node.material?.properties,
22
- node.material?.texture,
23
- ]);
9
+ const material = useMemo(() => DEFAULT_STAIR_MATERIAL, []);
24
10
  useRegistry(node.id, 'fence', ref);
25
11
  useLayoutEffect(() => {
26
12
  useScene.getState().markDirty(node.id);
@@ -1,6 +1,6 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
2
  import { getMaterialPresetByRef, useRegistry } from '@pascal-app/core';
3
- import { useMemo, useRef } from 'react';
3
+ import { useEffect, useMemo, useRef } from 'react';
4
4
  import * as THREE from 'three';
5
5
  import { useNodeEvents } from '../../../hooks/use-node-events';
6
6
  import { applyMaterialPresetToMaterials, createMaterial, DEFAULT_SLAB_MATERIAL, } from '../../../lib/materials';
@@ -43,7 +43,7 @@ export const StairRenderer = ({ node }) => {
43
43
  straightPlaceholderGeometry.dispose();
44
44
  };
45
45
  }, [straightPlaceholderGeometry]);
46
- return (_jsxs("group", { "position-x": node.position[0], "position-z": node.position[2], ref: ref, "rotation-y": node.rotation, visible: node.visible, ...handlers, children: [isSegmentBasedStair ? (_jsx("mesh", { castShadow: true, geometry: straightPlaceholderGeometry, material: straightBodyMaterials, name: "merged-stair", receiveShadow: true })) : null, !isSegmentBasedStair ? (_jsx(CurvedStairBody, { bodyMaterials: straightBodyMaterials, stair: node })) : null, _jsx(StairRailings, { material: railingMaterial, stair: node }), isSegmentBasedStair ? (_jsx("group", { name: "segments-wrapper", visible: false, children: (node.children ?? []).map((childId) => (_jsx(NodeRenderer, { nodeId: childId }, childId))) })) : null] }));
46
+ return (_jsxs("group", { "position-x": node.position[0], "position-z": node.position[2], ref: ref, "rotation-y": node.rotation, visible: node.visible, ...handlers, children: [isSegmentBasedStair ? (_jsx("mesh", { castShadow: true, geometry: straightPlaceholderGeometry, material: straightBodyMaterials, name: "merged-stair", receiveShadow: true })) : null, isSegmentBasedStair ? null : (_jsx(CurvedStairBody, { bodyMaterials: straightBodyMaterials, stair: node })), _jsx(StairRailings, { material: railingMaterial, stair: node }), isSegmentBasedStair ? (_jsx("group", { name: "segments-wrapper", visible: false, children: (node.children ?? []).map((childId) => (_jsx(NodeRenderer, { nodeId: childId }, childId))) })) : null] }));
47
47
  };
48
48
  function StairRailings({ stair, material }) {
49
49
  const nodes = useScene((state) => state.nodes);
@@ -107,7 +107,7 @@ function StairRailings({ stair, material }) {
107
107
  return (_jsxs("group", { children: [_jsx(RailSegment, { end: [nextPoint[2], nextPoint[1] + railHeight, nextPoint[0]], material: material, radius: railRadius, start: [point[2], point[1] + railHeight, point[0]] }), _jsx(RailSegment, { end: [nextPoint[2], nextPoint[1] + midRailHeight, nextPoint[0]], material: material, radius: railRadius * 0.8, start: [point[2], point[1] + midRailHeight, point[0]] })] }, `${segmentPath.layout.segment.id}-${sidePath.side}-rail-${pointIndex}`));
108
108
  })] }, `${segmentPath.layout.segment.id}-${sidePath.side}-${sideIndex}`))) }, `${segmentPath.layout.segment.id}-railing`))), railPaths.slice(1).map((segmentPath, index) => {
109
109
  const previousPath = railPaths[index];
110
- if (!previousPath || !segmentPath.connectFromPrevious)
110
+ if (!(previousPath && segmentPath.connectFromPrevious))
111
111
  return null;
112
112
  if (previousPath.layout.segment.segmentType === 'landing')
113
113
  return null;
@@ -191,7 +191,7 @@ function CurvedStairBody({ stair, bodyMaterials, }) {
191
191
  const spiralLandingThickness = isSpiral && (stair.topLandingMode ?? 'none') === 'integrated'
192
192
  ? Math.max(0.02, totalRise - spiralLastStepTop)
193
193
  : 0;
194
- return (_jsxs("group", { name: isSpiral ? 'spiral-stair' : 'curved-stair', children: [isSpiral && (stair.showCenterColumn ?? true) ? (_jsx("mesh", { castShadow: true, receiveShadow: true, material: sideMaterial, name: "stair-side", position: [0, spiralColumnHeight / 2, 0], children: _jsx("cylinderGeometry", { args: [spiralColumnRadius, spiralColumnRadius, spiralColumnHeight, 10] }) })) : null, Array.from({ length: stepCount }).map((_, index) => {
194
+ return (_jsxs("group", { name: isSpiral ? 'spiral-stair' : 'curved-stair', children: [isSpiral && (stair.showCenterColumn ?? true) ? (_jsx("mesh", { castShadow: true, material: sideMaterial, name: "stair-side", position: [0, spiralColumnHeight / 2, 0], receiveShadow: true, children: _jsx("cylinderGeometry", { args: [spiralColumnRadius, spiralColumnRadius, spiralColumnHeight, 10] }) })) : null, Array.from({ length: stepCount }).map((_, index) => {
195
195
  const currentHeight = stepHeight * (index + 1);
196
196
  const actualStepHeight = isSpiral
197
197
  ? thickness
@@ -1 +1 @@
1
- {"version":3,"file":"stair-segment-renderer.d.ts","sourceRoot":"","sources":["../../../../src/components/renderers/stair-segment/stair-segment-renderer.tsx"],"names":[],"mappings":"AAAA,OAAO,EAGL,KAAK,gBAAgB,EAGtB,MAAM,kBAAkB,CAAA;AAMzB,eAAO,MAAM,oBAAoB,GAAI,UAAU;IAAE,IAAI,EAAE,gBAAgB,CAAA;CAAE,4CA4CxE,CAAA"}
1
+ {"version":3,"file":"stair-segment-renderer.d.ts","sourceRoot":"","sources":["../../../../src/components/renderers/stair-segment/stair-segment-renderer.tsx"],"names":[],"mappings":"AAAA,OAAO,EAGL,KAAK,gBAAgB,EAGtB,MAAM,kBAAkB,CAAA;AAMzB,eAAO,MAAM,oBAAoB,GAAI,UAAU;IAAE,IAAI,EAAE,gBAAgB,CAAA;CAAE,4CA6DxE,CAAA"}
@@ -15,7 +15,26 @@ export const StairSegmentRenderer = ({ node }) => {
15
15
  const parentNode = node.parentId
16
16
  ? nodes[node.parentId]
17
17
  : undefined;
18
- const material = useMemo(() => getStraightStairSegmentBodyMaterials(node, parentNode), [node, parentNode]);
18
+ const material = useMemo(() => {
19
+ return getStraightStairSegmentBodyMaterials(node, parentNode);
20
+ }, [
21
+ node.materialPreset,
22
+ node.material,
23
+ node.material?.preset,
24
+ node.material?.properties,
25
+ node.material?.texture,
26
+ parentNode?.materialPreset,
27
+ parentNode?.material,
28
+ parentNode?.material?.preset,
29
+ parentNode?.material?.properties,
30
+ parentNode?.material?.texture,
31
+ parentNode?.railingMaterialPreset,
32
+ parentNode?.railingMaterial,
33
+ parentNode?.sideMaterialPreset,
34
+ parentNode?.sideMaterial,
35
+ parentNode?.treadMaterialPreset,
36
+ parentNode?.treadMaterial,
37
+ ]);
19
38
  const placeholderGeometry = useMemo(() => {
20
39
  const geometry = new THREE.BufferGeometry();
21
40
  geometry.setAttribute('position', new THREE.Float32BufferAttribute([], 3));
@@ -1 +1 @@
1
- {"version":3,"file":"frame-limiter.d.ts","sourceRoot":"","sources":["../../../src/components/viewer/frame-limiter.tsx"],"names":[],"mappings":"AAGA,KAAK,iBAAiB,GAAG;IACvB,GAAG,CAAC,EAAE,MAAM,CAAA;CACb,CAAA;AAED,QAAA,MAAM,YAAY,EAAE,KAAK,CAAC,EAAE,CAAC,iBAAiB,CAgC7C,CAAA;AAED,eAAe,YAAY,CAAA"}
1
+ {"version":3,"file":"frame-limiter.d.ts","sourceRoot":"","sources":["../../../src/components/viewer/frame-limiter.tsx"],"names":[],"mappings":"AAGA,KAAK,iBAAiB,GAAG;IACvB,GAAG,CAAC,EAAE,MAAM,CAAA;CACb,CAAA;AAED,QAAA,MAAM,YAAY,EAAE,KAAK,CAAC,EAAE,CAAC,iBAAiB,CAiC7C,CAAA;AAED,eAAe,YAAY,CAAA"}
@@ -1,7 +1,8 @@
1
1
  import { useThree } from '@react-three/fiber';
2
2
  import { useLayoutEffect } from 'react';
3
3
  const FrameLimiter = ({ fps = 50 }) => {
4
- const { advance, set, frameloop: initFrameloop } = useThree();
4
+ const { advance, set, frameloop: initFrameloop, scene, clock } = useThree();
5
+ const renderer = useThree((state) => state.gl);
5
6
  useLayoutEffect(() => {
6
7
  let elapsed = 0;
7
8
  let then = 0;
@@ -17,8 +18,11 @@ const FrameLimiter = ({ fps = 50 }) => {
17
18
  then = t - (elapsed % interval);
18
19
  }
19
20
  }
21
+ // Set frameloop to never, it will shut down the default render loop
20
22
  set({ frameloop: 'never' });
23
+ // Kick off custom render loop
21
24
  raf = requestAnimationFrame(tick);
25
+ // Restore initial setting
22
26
  return () => {
23
27
  if (raf) {
24
28
  cancelAnimationFrame(raf);
@@ -10,6 +10,7 @@ interface ViewerProps {
10
10
  hoverStyles?: HoverStyles;
11
11
  selectionManager?: 'default' | 'custom';
12
12
  perf?: boolean;
13
+ useBvh?: boolean;
13
14
  }
14
15
  declare const Viewer: React.FC<ViewerProps>;
15
16
  export default Viewer;
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/viewer/index.tsx"],"names":[],"mappings":"AAGA,OAAO,EAAkB,KAAK,kBAAkB,EAAsB,MAAM,oBAAoB,CAAA;AAEhG,OAAO,KAAK,KAAK,MAAM,cAAc,CAAA;AAwBrC,OAAuB,EAAwB,KAAK,WAAW,EAAE,MAAM,mBAAmB,CAAA;AA+B1F,OAAO,QAAQ,oBAAoB,CAAC;IAClC,UAAU,aAAc,SAAQ,kBAAkB,CAAC,OAAO,KAAK,CAAC;KAAG;CACpE;AAkFD,UAAU,WAAW;IACnB,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;IAC1B,WAAW,CAAC,EAAE,WAAW,CAAA;IACzB,gBAAgB,CAAC,EAAE,SAAS,GAAG,QAAQ,CAAA;IACvC,IAAI,CAAC,EAAE,OAAO,CAAA;CACf;AAED,QAAA,MAAM,MAAM,EAAE,KAAK,CAAC,EAAE,CAAC,WAAW,CAmGjC,CAAA;AASD,eAAe,MAAM,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/viewer/index.tsx"],"names":[],"mappings":"AAGA,OAAO,EAAkB,KAAK,kBAAkB,EAAsB,MAAM,oBAAoB,CAAA;AAEhG,OAAO,KAAK,KAAK,MAAM,cAAc,CAAA;AAwBrC,OAAuB,EAAwB,KAAK,WAAW,EAAE,MAAM,mBAAmB,CAAA;AA+B1F,OAAO,QAAQ,oBAAoB,CAAC;IAClC,UAAU,aAAc,SAAQ,kBAAkB,CAAC,OAAO,KAAK,CAAC;KAAG;CACpE;AAkFD,UAAU,WAAW;IACnB,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;IAC1B,WAAW,CAAC,EAAE,WAAW,CAAA;IACzB,gBAAgB,CAAC,EAAE,SAAS,GAAG,QAAQ,CAAA;IACvC,IAAI,CAAC,EAAE,OAAO,CAAA;IACd,MAAM,CAAC,EAAE,OAAO,CAAA;CACjB;AAED,QAAA,MAAM,MAAM,EAAE,KAAK,CAAC,EAAE,CAAC,WAAW,CAwGjC,CAAA;AASD,eAAe,MAAM,CAAA"}
@@ -81,25 +81,25 @@ function GPUDeviceWatcher() {
81
81
  }
82
82
  console.log('[viewer] WebGPU device ready', {
83
83
  label: device.label,
84
- features: device.features ? Array.from(device.features) : [],
84
+ features: Array.from(device.features ?? []),
85
85
  });
86
86
  device.lost.then((info) => {
87
- console.error(`[viewer] WebGPU device lost: reason="${info.reason ?? 'unknown'}", message="${info.message ?? ''}". ` +
87
+ console.error(`[viewer] WebGPU device lost: reason="${info.reason}", message="${info.message}". ` +
88
88
  'The page must be reloaded to recover the GPU context.');
89
89
  });
90
90
  // Uncaptured errors are normally silent (only console-warned by Chrome at
91
91
  // best). Pipe them to console.error so silent mobile crashes show up.
92
92
  const onUncapturedError = (event) => {
93
- console.error('[viewer] WebGPU uncaptured error:', event?.error?.message, event?.error);
93
+ console.error('[viewer] WebGPU uncaptured error:', event.error.message, event.error);
94
94
  };
95
- device.addEventListener?.('uncapturederror', onUncapturedError);
95
+ device.addEventListener('uncapturederror', onUncapturedError);
96
96
  return () => {
97
- device.removeEventListener?.('uncapturederror', onUncapturedError);
97
+ device.removeEventListener('uncapturederror', onUncapturedError);
98
98
  };
99
99
  }, [gl]);
100
100
  return null;
101
101
  }
102
- const Viewer = ({ children, hoverStyles = DEFAULT_HOVER_STYLES, selectionManager = 'default', perf = false, }) => {
102
+ const Viewer = ({ children, hoverStyles = DEFAULT_HOVER_STYLES, selectionManager = 'default', perf = false, useBvh = true, }) => {
103
103
  const theme = useViewer((state) => state.theme);
104
104
  return (_jsxs(Canvas, { camera: { position: [50, 50, 50], fov: 50 }, className: `transition-colors duration-700 ${theme === 'dark' ? 'bg-[#1f2433]' : 'bg-[#fafafa]'}`, dpr: [1, 1.5], frameloop: "never", gl: ((props) => {
105
105
  const canvas = props.canvas;
@@ -144,7 +144,7 @@ const Viewer = ({ children, hoverStyles = DEFAULT_HOVER_STYLES, selectionManager
144
144
  }, shadows: {
145
145
  type: THREE.PCFShadowMap,
146
146
  enabled: true,
147
- }, children: [_jsx(FrameLimiter, { fps: 50 }), _jsx(ViewerCamera, {}), _jsx(GPUDeviceWatcher, {}), _jsxs(ErrorBoundary, { fallback: null, scope: "viewer-scene", children: [_jsx(Lights, {}), _jsx(Bvh, { children: _jsx(SceneRenderer, {}) }), _jsx(LevelSystem, {}), _jsx(GuideSystem, {}), _jsx(ScanSystem, {}), _jsx(WallCutout, {}), _jsx(CeilingSystem, {}), _jsx(DoorAnimationSystem, {}), _jsx(WindowAnimationSystem, {}), _jsx(DoorSystem, {}), _jsx(FenceSystem, {}), _jsx(ItemSystem, {}), _jsx(RoofSystem, {}), _jsx(SlabSystem, {}), _jsx(StairSystem, {}), _jsx(WallSystem, {}), _jsx(WindowSystem, {}), _jsx(ZoneSystem, {}), _jsx(PostProcessing, { hoverStyles: hoverStyles }), _jsx(ItemLightSystem, {}), selectionManager === 'default' && _jsx(SelectionManager, {}), perf && _jsx(PerfMonitor, {}), children] })] }));
147
+ }, children: [_jsx(FrameLimiter, { fps: 50 }), _jsx(ViewerCamera, {}), _jsx(GPUDeviceWatcher, {}), _jsxs(ErrorBoundary, { fallback: null, scope: "viewer-scene", children: [_jsx(Lights, {}), useBvh ? (_jsx(Bvh, { children: _jsx(SceneRenderer, {}) })) : (_jsx(SceneRenderer, {})), _jsx(LevelSystem, {}), _jsx(GuideSystem, {}), _jsx(ScanSystem, {}), _jsx(WallCutout, {}), _jsx(CeilingSystem, {}), _jsx(DoorAnimationSystem, {}), _jsx(WindowAnimationSystem, {}), _jsx(DoorSystem, {}), _jsx(FenceSystem, {}), _jsx(ItemSystem, {}), _jsx(RoofSystem, {}), _jsx(SlabSystem, {}), _jsx(StairSystem, {}), _jsx(WallSystem, {}), _jsx(WindowSystem, {}), _jsx(ZoneSystem, {}), _jsx(PostProcessing, { hoverStyles: hoverStyles }), _jsx(ItemLightSystem, {}), selectionManager === 'default' && _jsx(SelectionManager, {}), perf && _jsx(PerfMonitor, {}), children] })] }));
148
148
  };
149
149
  const DebugRenderer = () => {
150
150
  useFrame(({ gl, scene, camera }) => {
@@ -1 +1 @@
1
- {"version":3,"file":"post-processing.d.ts","sourceRoot":"","sources":["../../../src/components/viewer/post-processing.tsx"],"names":[],"mappings":"AA4BA,eAAO,MAAM,WAAW;;;;;;;;;;;;;CAavB,CAAA;AAQD,MAAM,MAAM,UAAU,GAAG;IACvB,YAAY,EAAE,MAAM,CAAA;IACpB,WAAW,EAAE,MAAM,CAAA;IACnB,QAAQ,EAAE,MAAM,CAAA;IAChB,KAAK,EAAE,OAAO,CAAA;CACf,CAAA;AAED,MAAM,MAAM,WAAW,GAAG;IACxB,OAAO,EAAE,UAAU,CAAA;CACpB,GAAG,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,CAAA;AAS9B,eAAO,MAAM,oBAAoB,EAAE,WAElC,CAAA;AAiBD,QAAA,MAAM,oBAAoB,GAAI,kBAE3B;IACD,WAAW,CAAC,EAAE,WAAW,CAAA;CAC1B,SAkVA,CAAA;AAED,eAAe,oBAAoB,CAAA"}
1
+ {"version":3,"file":"post-processing.d.ts","sourceRoot":"","sources":["../../../src/components/viewer/post-processing.tsx"],"names":[],"mappings":"AA4BA,eAAO,MAAM,WAAW;;;;;;;;;;;;;CAavB,CAAA;AAQD,MAAM,MAAM,UAAU,GAAG;IACvB,YAAY,EAAE,MAAM,CAAA;IACpB,WAAW,EAAE,MAAM,CAAA;IACnB,QAAQ,EAAE,MAAM,CAAA;IAChB,KAAK,EAAE,OAAO,CAAA;CACf,CAAA;AAED,MAAM,MAAM,WAAW,GAAG;IACxB,OAAO,EAAE,UAAU,CAAA;CACpB,GAAG,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,CAAA;AAS9B,eAAO,MAAM,oBAAoB,EAAE,WAElC,CAAA;AAiBD,QAAA,MAAM,oBAAoB,GAAI,kBAE3B;IACD,WAAW,CAAC,EAAE,WAAW,CAAA;CAC1B,SAyTA,CAAA;AAED,eAAe,oBAAoB,CAAA"}
@@ -83,8 +83,6 @@ const PostProcessingPasses = ({ hoverStyles = DEFAULT_HOVER_STYLES, }) => {
83
83
  }, []);
84
84
  // Reset retry state when project changes
85
85
  useEffect(() => {
86
- // Intentionally touch projectId so the effect reruns on project switches.
87
- void projectId;
88
86
  retryCountRef.current = 0;
89
87
  if (rebuildTimeoutRef.current !== null) {
90
88
  clearTimeout(rebuildTimeoutRef.current);
@@ -117,10 +115,6 @@ const PostProcessingPasses = ({ hoverStyles = DEFAULT_HOVER_STYLES, }) => {
117
115
  ]);
118
116
  // Build / rebuild the post-processing pipeline
119
117
  useEffect(() => {
120
- // Intentionally touch these so React/biome treat project switches and retry bumps
121
- // as explicit rebuild triggers instead of accidental extra dependencies.
122
- void projectId;
123
- void pipelineVersion;
124
118
  if (!(renderer && scene && camera)) {
125
119
  console.warn('[viewer/post-processing] Skipping pipeline build — missing dependency.', {
126
120
  hasRenderer: !!renderer,
@@ -137,21 +131,6 @@ const PostProcessingPasses = ({ hoverStyles = DEFAULT_HOVER_STYLES, }) => {
137
131
  rendererCtor: renderer.constructor?.name,
138
132
  });
139
133
  hasPipelineErrorRef.current = false;
140
- // WebGPU availability check: SSGI, denoise, and RenderPipeline are all
141
- // WebGPU-only APIs. When the browser falls back to WebGL2 (no
142
- // `navigator.gpu`, or the device couldn't be created), building the
143
- // pipeline either throws silently or produces a broken output where
144
- // the scene renders for a few frames and then goes black as the retry
145
- // loop fights the direct-render fallback path. Short-circuit here so
146
- // `useFrame` uses the direct `renderer.render(scene, camera)` path
147
- // exclusively and never attempts the TSL pipeline.
148
- const hasWebGPU = typeof navigator !== 'undefined' && 'gpu' in navigator;
149
- if (!hasWebGPU) {
150
- console.warn('[viewer] WebGPU unavailable — rendering without post-processing (SSGI, outlines, denoise).');
151
- hasPipelineErrorRef.current = true;
152
- renderPipelineRef.current = null;
153
- return;
154
- }
155
134
  // Clear outliner arrays synchronously to prevent stale Object3D refs
156
135
  // from the previous project leaking into the new pipeline's outline passes.
157
136
  const outliner = useViewer.getState().outliner;
package/dist/index.d.ts CHANGED
@@ -4,7 +4,7 @@ export { DEFAULT_HOVER_STYLES, SSGI_PARAMS, } from './components/viewer/post-pro
4
4
  export { WalkthroughControls } from './components/viewer/walkthrough-controls';
5
5
  export { ASSETS_CDN_URL, resolveAssetUrl, resolveCdnUrl } from './lib/asset-url';
6
6
  export { SCENE_LAYER, ZONE_LAYER } from './lib/layers';
7
- export { applyMaterialPresetToMaterials, clearMaterialCache, createDefaultMaterial, createMaterial, createMaterialFromPresetRef, DEFAULT_CEILING_MATERIAL, DEFAULT_DOOR_MATERIAL, DEFAULT_ROOF_MATERIAL, DEFAULT_SLAB_MATERIAL, DEFAULT_WALL_MATERIAL, DEFAULT_WINDOW_MATERIAL, disposeMaterial, } from './lib/materials';
7
+ export { applyMaterialPresetToMaterials, clearMaterialCache, createDefaultMaterial, createMaterial, createMaterialFromPresetRef, DEFAULT_CEILING_MATERIAL, DEFAULT_DOOR_MATERIAL, DEFAULT_ROOF_MATERIAL, DEFAULT_SLAB_MATERIAL, DEFAULT_WALL_MATERIAL, DEFAULT_WINDOW_MATERIAL, disposeMaterial, glassMaterial, } from './lib/materials';
8
8
  export { mergedOutline } from './lib/merged-outline-node';
9
9
  export { default as useViewer } from './store/use-viewer';
10
10
  export { InteractiveSystem } from './systems/interactive/interactive-system';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,IAAI,MAAM,EAAE,MAAM,qBAAqB,CAAA;AACvD,YAAY,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,qCAAqC,CAAA;AAClF,OAAO,EACL,oBAAoB,EACpB,WAAW,GACZ,MAAM,qCAAqC,CAAA;AAC5C,OAAO,EAAE,mBAAmB,EAAE,MAAM,0CAA0C,CAAA;AAC9E,OAAO,EAAE,cAAc,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAA;AAChF,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,cAAc,CAAA;AACtD,OAAO,EACL,8BAA8B,EAC9B,kBAAkB,EAClB,qBAAqB,EACrB,cAAc,EACd,2BAA2B,EAC3B,wBAAwB,EACxB,qBAAqB,EACrB,qBAAqB,EACrB,qBAAqB,EACrB,qBAAqB,EACrB,uBAAuB,EACvB,eAAe,GAChB,MAAM,iBAAiB,CAAA;AACxB,OAAO,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAA;AACzD,OAAO,EAAE,OAAO,IAAI,SAAS,EAAE,MAAM,oBAAoB,CAAA;AACzD,OAAO,EAAE,iBAAiB,EAAE,MAAM,0CAA0C,CAAA;AAC5E,OAAO,EAAE,yBAAyB,EAAE,MAAM,6BAA6B,CAAA;AACvE,OAAO,EAAE,oBAAoB,EAAE,MAAM,+BAA+B,CAAA;AACpE,OAAO,EAAE,qBAAqB,EAAE,uBAAuB,EAAE,MAAM,iCAAiC,CAAA;AAChG,OAAO,EAAE,uBAAuB,EAAE,MAAM,+BAA+B,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,IAAI,MAAM,EAAE,MAAM,qBAAqB,CAAA;AACvD,YAAY,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,qCAAqC,CAAA;AAClF,OAAO,EACL,oBAAoB,EACpB,WAAW,GACZ,MAAM,qCAAqC,CAAA;AAC5C,OAAO,EAAE,mBAAmB,EAAE,MAAM,0CAA0C,CAAA;AAC9E,OAAO,EAAE,cAAc,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAA;AAChF,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,cAAc,CAAA;AACtD,OAAO,EACL,8BAA8B,EAC9B,kBAAkB,EAClB,qBAAqB,EACrB,cAAc,EACd,2BAA2B,EAC3B,wBAAwB,EACxB,qBAAqB,EACrB,qBAAqB,EACrB,qBAAqB,EACrB,qBAAqB,EACrB,uBAAuB,EACvB,eAAe,EACf,aAAa,GACd,MAAM,iBAAiB,CAAA;AACxB,OAAO,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAA;AACzD,OAAO,EAAE,OAAO,IAAI,SAAS,EAAE,MAAM,oBAAoB,CAAA;AACzD,OAAO,EAAE,iBAAiB,EAAE,MAAM,0CAA0C,CAAA;AAC5E,OAAO,EAAE,yBAAyB,EAAE,MAAM,6BAA6B,CAAA;AACvE,OAAO,EAAE,oBAAoB,EAAE,MAAM,+BAA+B,CAAA;AACpE,OAAO,EAAE,qBAAqB,EAAE,uBAAuB,EAAE,MAAM,iCAAiC,CAAA;AAChG,OAAO,EAAE,uBAAuB,EAAE,MAAM,+BAA+B,CAAA"}
package/dist/index.js CHANGED
@@ -3,7 +3,7 @@ export { DEFAULT_HOVER_STYLES, SSGI_PARAMS, } from './components/viewer/post-pro
3
3
  export { WalkthroughControls } from './components/viewer/walkthrough-controls';
4
4
  export { ASSETS_CDN_URL, resolveAssetUrl, resolveCdnUrl } from './lib/asset-url';
5
5
  export { SCENE_LAYER, ZONE_LAYER } from './lib/layers';
6
- export { applyMaterialPresetToMaterials, clearMaterialCache, createDefaultMaterial, createMaterial, createMaterialFromPresetRef, DEFAULT_CEILING_MATERIAL, DEFAULT_DOOR_MATERIAL, DEFAULT_ROOF_MATERIAL, DEFAULT_SLAB_MATERIAL, DEFAULT_WALL_MATERIAL, DEFAULT_WINDOW_MATERIAL, disposeMaterial, } from './lib/materials';
6
+ export { applyMaterialPresetToMaterials, clearMaterialCache, createDefaultMaterial, createMaterial, createMaterialFromPresetRef, DEFAULT_CEILING_MATERIAL, DEFAULT_DOOR_MATERIAL, DEFAULT_ROOF_MATERIAL, DEFAULT_SLAB_MATERIAL, DEFAULT_WALL_MATERIAL, DEFAULT_WINDOW_MATERIAL, disposeMaterial, glassMaterial, } from './lib/materials';
7
7
  export { mergedOutline } from './lib/merged-outline-node';
8
8
  export { default as useViewer } from './store/use-viewer';
9
9
  export { InteractiveSystem } from './systems/interactive/interactive-system';
@@ -1 +1 @@
1
- {"version":3,"file":"materials.d.ts","sourceRoot":"","sources":["../../src/lib/materials.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,qBAAqB,EAE1B,KAAK,cAAc,EAGpB,MAAM,kBAAkB,CAAA;AACzB,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAC9B,OAAO,EAAE,wBAAwB,EAAE,MAAM,cAAc,CAAA;AAEvD,eAAO,MAAM,YAAY,0BAIvB,CAAA;AAEF,eAAO,MAAM,aAAa,0BAOxB,CAAA;AA2MF,wBAAgB,8BAA8B,CAC5C,aAAa,EAAE,KAAK,CAAC,QAAQ,GAAG,KAAK,CAAC,QAAQ,EAAE,EAChD,MAAM,EAAE,qBAAqB,GAAG,IAAI,GAAG,SAAS,QAcjD;AAED,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,qBAAqB,GAAG,KAAK,CAAC,oBAAoB,CAWlG;AAED,wBAAgB,2BAA2B,CAAC,cAAc,CAAC,EAAE,MAAM,GAAG,KAAK,CAAC,oBAAoB,GAAG,IAAI,CAItG;AAED,wBAAgB,cAAc,CAAC,QAAQ,CAAC,EAAE,cAAc,GAAG,KAAK,CAAC,oBAAoB,CAsBpF;AAED,wBAAgB,qBAAqB,CACnC,KAAK,SAAY,EACjB,SAAS,SAAM,GACd,KAAK,CAAC,oBAAoB,CAO5B;AAED,eAAO,MAAM,qBAAqB,4BAAwC,CAAA;AAC1E,eAAO,MAAM,qBAAqB,4BAAwC,CAAA;AAC1E,eAAO,MAAM,qBAAqB,4BAAwC,CAAA;AAC1E,eAAO,MAAM,uBAAuB,4BAOlC,CAAA;AACF,eAAO,MAAM,wBAAwB,4BAAyC,CAAA;AAC9E,eAAO,MAAM,qBAAqB,4BAAyC,CAAA;AAC3E,eAAO,MAAM,sBAAsB,4BAAwC,CAAA;AAE3E,wBAAgB,eAAe,CAAC,QAAQ,EAAE,KAAK,CAAC,QAAQ,GAAG,IAAI,CAE9D;AAED,wBAAgB,kBAAkB,IAAI,IAAI,CAWzC"}
1
+ {"version":3,"file":"materials.d.ts","sourceRoot":"","sources":["../../src/lib/materials.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,KAAK,qBAAqB,EAE1B,KAAK,cAAc,EAEpB,MAAM,kBAAkB,CAAA;AACzB,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAC9B,OAAO,EAAE,wBAAwB,EAAE,MAAM,cAAc,CAAA;AAEvD,eAAO,MAAM,YAAY,0BAIvB,CAAA;AAEF,eAAO,MAAM,aAAa,0BAOxB,CAAA;AAkNF,wBAAgB,8BAA8B,CAC5C,aAAa,EAAE,KAAK,CAAC,QAAQ,GAAG,KAAK,CAAC,QAAQ,EAAE,EAChD,MAAM,EAAE,qBAAqB,GAAG,IAAI,GAAG,SAAS,QAcjD;AAED,wBAAgB,wBAAwB,CACtC,MAAM,EAAE,qBAAqB,GAC5B,KAAK,CAAC,oBAAoB,CAW5B;AAED,wBAAgB,2BAA2B,CACzC,cAAc,CAAC,EAAE,MAAM,GACtB,KAAK,CAAC,oBAAoB,GAAG,IAAI,CAInC;AAED,wBAAgB,cAAc,CAAC,QAAQ,CAAC,EAAE,cAAc,GAAG,KAAK,CAAC,oBAAoB,CAsBpF;AAED,wBAAgB,qBAAqB,CACnC,KAAK,SAAY,EACjB,SAAS,SAAM,GACd,KAAK,CAAC,oBAAoB,CAO5B;AAED,eAAO,MAAM,qBAAqB,4BAAwC,CAAA;AAC1E,eAAO,MAAM,qBAAqB,4BAAwC,CAAA;AAC1E,eAAO,MAAM,qBAAqB,4BAAwC,CAAA;AAC1E,eAAO,MAAM,uBAAuB,4BAOlC,CAAA;AACF,eAAO,MAAM,wBAAwB,4BAAyC,CAAA;AAC9E,eAAO,MAAM,qBAAqB,4BAAyC,CAAA;AAC3E,eAAO,MAAM,sBAAsB,4BAAwC,CAAA;AAE3E,wBAAgB,eAAe,CAAC,QAAQ,EAAE,KAAK,CAAC,QAAQ,GAAG,IAAI,CAE9D;AAED,wBAAgB,kBAAkB,IAAI,IAAI,CAWzC"}
@@ -59,8 +59,7 @@ function getTexture(material) {
59
59
  return texture;
60
60
  }
61
61
  function isStandardMaterial(material) {
62
- return (material instanceof THREE.MeshStandardMaterial ||
63
- material instanceof THREE.MeshPhysicalMaterial);
62
+ return (material instanceof THREE.MeshStandardMaterial || material instanceof THREE.MeshPhysicalMaterial);
64
63
  }
65
64
  function applyTextureProperties(texture, props, slot) {
66
65
  texture.wrapS = wrapMap[props.wrapS];
@@ -123,7 +122,7 @@ function queueTextureAssignment(material, slot, path, props) {
123
122
  return;
124
123
  }
125
124
  material[slot] = null;
126
- void loadPresetTexture(path, props, slot).then((texture) => {
125
+ loadPresetTexture(path, props, slot).then((texture) => {
127
126
  if (!texture)
128
127
  return;
129
128
  material[slot] = texture;
@@ -1 +1 @@
1
- {"version":3,"file":"merged-outline-node.d.ts","sourceRoot":"","sources":["../../src/lib/merged-outline-node.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"merged-outline-node.d.ts","sourceRoot":"","sources":["../../src/lib/merged-outline-node.ts"],"names":[],"mappings":"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"}
@@ -460,17 +460,10 @@ export class MergedOutlineNode extends TempNode {
460
460
  }
461
461
  _buildCache(objects, cache) {
462
462
  for (const obj of objects) {
463
- if (!obj || !obj.traverse)
464
- continue;
465
- try {
466
- obj.traverse((child) => {
467
- if (child.isMesh || child.isSprite)
468
- cache.add(child);
469
- });
470
- }
471
- catch {
472
- // Skip objects that were disposed or removed from the scene graph
473
- }
463
+ obj.traverse((child) => {
464
+ if (child.isMesh || child.isSprite)
465
+ cache.add(child);
466
+ });
474
467
  }
475
468
  }
476
469
  }
@@ -1 +1 @@
1
- {"version":3,"file":"ceiling-system.d.ts","sourceRoot":"","sources":["../../../src/systems/ceiling/ceiling-system.tsx"],"names":[],"mappings":"AACA,OAAO,EAAkB,KAAK,WAAW,EAA2B,MAAM,kBAAkB,CAAA;AAC5F,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAa9B,eAAO,MAAM,aAAa,YAuBzB,CAAA;AAqBD;;GAEG;AACH,wBAAgB,uBAAuB,CAAC,WAAW,EAAE,WAAW,GAAG,KAAK,CAAC,cAAc,CAgDtF"}
1
+ {"version":3,"file":"ceiling-system.d.ts","sourceRoot":"","sources":["../../../src/systems/ceiling/ceiling-system.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAkB,KAAK,WAAW,EAA2B,MAAM,kBAAkB,CAAA;AAE5F,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAa9B,eAAO,MAAM,aAAa,YAuBzB,CAAA;AAqBD;;GAEG;AACH,wBAAgB,uBAAuB,CAAC,WAAW,EAAE,WAAW,GAAG,KAAK,CAAC,cAAc,CAgDtF"}
@@ -1,5 +1,5 @@
1
- import { useFrame } from '@react-three/fiber';
2
1
  import { sceneRegistry, useScene } from '@pascal-app/core';
2
+ import { useFrame } from '@react-three/fiber';
3
3
  import * as THREE from 'three';
4
4
  function ensureUv2Attribute(geometry) {
5
5
  const uv = geometry.getAttribute('uv');
@@ -1 +1 @@
1
- {"version":3,"file":"fence-system.d.ts","sourceRoot":"","sources":["../../../src/systems/fence/fence-system.tsx"],"names":[],"mappings":"AA6QA,eAAO,MAAM,WAAW,YAiBvB,CAAA"}
1
+ {"version":3,"file":"fence-system.d.ts","sourceRoot":"","sources":["../../../src/systems/fence/fence-system.tsx"],"names":[],"mappings":"AA+QA,eAAO,MAAM,WAAW,YAiBvB,CAAA"}
@@ -1,5 +1,5 @@
1
- import { useFrame } from '@react-three/fiber';
2
1
  import { getWallCurveFrameAt, getWallCurveLength, sceneRegistry, useScene, } from '@pascal-app/core';
2
+ import { useFrame } from '@react-three/fiber';
3
3
  import * as THREE from 'three';
4
4
  import { mergeGeometries } from 'three/examples/jsm/utils/BufferGeometryUtils.js';
5
5
  const MIN_CURVE_SEGMENT_LENGTH = 0.18;
@@ -1 +1 @@
1
- {"version":3,"file":"guide-system.d.ts","sourceRoot":"","sources":["../../../src/systems/guide/guide-system.tsx"],"names":[],"mappings":"AAIA,eAAO,MAAM,WAAW,YAsCvB,CAAA"}
1
+ {"version":3,"file":"guide-system.d.ts","sourceRoot":"","sources":["../../../src/systems/guide/guide-system.tsx"],"names":[],"mappings":"AAIA,eAAO,MAAM,WAAW,YAcvB,CAAA"}
@@ -1,4 +1,4 @@
1
- import { emitter, sceneRegistry } from '@pascal-app/core';
1
+ import { sceneRegistry } from '@pascal-app/core';
2
2
  import { useEffect } from 'react';
3
3
  import useViewer from '../../store/use-viewer';
4
4
  export const GuideSystem = () => {
@@ -12,30 +12,5 @@ export const GuideSystem = () => {
12
12
  }
13
13
  });
14
14
  }, [showGuides]);
15
- useEffect(() => {
16
- const hideForCapture = () => {
17
- const guides = sceneRegistry.byType.guide || new Set();
18
- guides.forEach((guideId) => {
19
- const node = sceneRegistry.nodes.get(guideId);
20
- if (node)
21
- node.visible = false;
22
- });
23
- };
24
- const restoreAfterCapture = () => {
25
- const showGuidesNow = useViewer.getState().showGuides;
26
- const guides = sceneRegistry.byType.guide || new Set();
27
- guides.forEach((guideId) => {
28
- const node = sceneRegistry.nodes.get(guideId);
29
- if (node)
30
- node.visible = showGuidesNow;
31
- });
32
- };
33
- emitter.on('thumbnail:before-capture', hideForCapture);
34
- emitter.on('thumbnail:after-capture', restoreAfterCapture);
35
- return () => {
36
- emitter.off('thumbnail:before-capture', hideForCapture);
37
- emitter.off('thumbnail:after-capture', restoreAfterCapture);
38
- };
39
- }, []);
40
15
  return null;
41
16
  };
@@ -1,5 +1,5 @@
1
- import { useFrame } from '@react-three/fiber';
2
1
  import { getScaledDimensions, resolveLevelId, sceneRegistry, spatialGridManager, useScene, } from '@pascal-app/core';
2
+ import { useFrame } from '@react-three/fiber';
3
3
  // ============================================================================
4
4
  // ITEM SYSTEM
5
5
  // ============================================================================
@@ -1 +1 @@
1
- {"version":3,"file":"roof-system.d.ts","sourceRoot":"","sources":["../../../src/systems/roof/roof-system.tsx"],"names":[],"mappings":"AACA,OAAO,EAIL,KAAK,eAAe,EAIrB,MAAM,kBAAkB,CAAA;AACzB,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAE9B,OAAO,EAAY,KAAK,EAA0B,MAAM,eAAe,CAAA;AAmCvE,eAAO,MAAM,UAAU,YAsFtB,CAAA;AAuLD;;;GAGG;AACH,wBAAgB,qBAAqB,CACnC,IAAI,EAAE,eAAe,GACpB;IAAE,QAAQ,EAAE,KAAK,CAAC;IAAC,QAAQ,EAAE,KAAK,CAAC;IAAC,SAAS,EAAE,KAAK,CAAC;IAAC,UAAU,EAAE,KAAK,CAAA;CAAE,GAAG,IAAI,CAqRlF;AAED,wBAAgB,2BAA2B,CAAC,IAAI,EAAE,eAAe,GAAG,KAAK,CAAC,cAAc,CAqDvF"}
1
+ {"version":3,"file":"roof-system.d.ts","sourceRoot":"","sources":["../../../src/systems/roof/roof-system.tsx"],"names":[],"mappings":"AAAA,OAAO,EAIL,KAAK,eAAe,EAIrB,MAAM,kBAAkB,CAAA;AAEzB,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAE9B,OAAO,EAAY,KAAK,EAA0B,MAAM,eAAe,CAAA;AA4CvE,eAAO,MAAM,UAAU,YAsFtB,CAAA;AAqLD;;;GAGG;AACH,wBAAgB,qBAAqB,CACnC,IAAI,EAAE,eAAe,GACpB;IAAE,QAAQ,EAAE,KAAK,CAAC;IAAC,QAAQ,EAAE,KAAK,CAAC;IAAC,SAAS,EAAE,KAAK,CAAC;IAAC,UAAU,EAAE,KAAK,CAAA;CAAE,GAAG,IAAI,CAqRlF;AAED,wBAAgB,2BAA2B,CAAC,IAAI,EAAE,eAAe,GAAG,KAAK,CAAC,cAAc,CAmDvF"}
@@ -1,9 +1,16 @@
1
- import { useFrame } from '@react-three/fiber';
2
1
  import { sceneRegistry, useScene, } from '@pascal-app/core';
2
+ import { useFrame } from '@react-three/fiber';
3
3
  import * as THREE from 'three';
4
4
  import { mergeVertices } from 'three/examples/jsm/utils/BufferGeometryUtils.js';
5
5
  import { ADDITION, Brush, Evaluator, SUBTRACTION } from 'three-bvh-csg';
6
6
  import { computeBoundsTree } from 'three-mesh-bvh';
7
+ function csgGeometry(brush) {
8
+ return brush.geometry;
9
+ }
10
+ function csgMaterials(brush) {
11
+ const mat = brush.material;
12
+ return Array.isArray(mat) ? mat : [mat];
13
+ }
7
14
  const csgEvaluator = new Evaluator();
8
15
  csgEvaluator.useGroups = true;
9
16
  csgEvaluator.consolidateGroups = false; // shared dummyMats across brushes causes consolidation to misalign groupIndices vs groupOrder indices → crash
@@ -151,7 +158,7 @@ function updateMergedRoofGeometry(roofNode, group, nodes) {
151
158
  continue;
152
159
  _matrix.compose(_position.set(child.position[0], child.position[1], child.position[2]), _quaternion.setFromAxisAngle(_yAxis, child.rotation), _scale);
153
160
  const applyTransform = (brush) => {
154
- brush.geometry.applyMatrix4(_matrix);
161
+ csgGeometry(brush).applyMatrix4(_matrix);
155
162
  brush.updateMatrixWorld();
156
163
  };
157
164
  applyTransform(brushes.shinSlab);
@@ -206,10 +213,8 @@ function updateMergedRoofGeometry(roofNode, group, nodes) {
206
213
  const finalWallTrimmed = csgEvaluator.evaluate(totalWall, totalInner, SUBTRACTION);
207
214
  const shinDeck = csgEvaluator.evaluate(finalShinTrimmed, finalDeckTrimmed, ADDITION);
208
215
  const combined = csgEvaluator.evaluate(shinDeck, finalWallTrimmed, ADDITION);
209
- const resultGeo = combined.geometry;
210
- const resultMaterials = Array.isArray(combined.material)
211
- ? combined.material
212
- : [combined.material];
216
+ const resultGeo = csgGeometry(combined);
217
+ const resultMaterials = csgMaterials(combined);
213
218
  const matToIndex = new Map([
214
219
  [dummyMats[0], 0],
215
220
  [dummyMats[1], 1],
@@ -219,8 +224,8 @@ function updateMergedRoofGeometry(roofNode, group, nodes) {
219
224
  for (const g of resultGeo.groups) {
220
225
  g.materialIndex = mapRoofGroupMaterialIndex(g.materialIndex, resultMaterials, matToIndex);
221
226
  }
222
- ensureUv2Attribute(resultGeo);
223
227
  resultGeo.computeVertexNormals();
228
+ ensureUv2Attribute(resultGeo);
224
229
  mergedMesh.geometry.dispose();
225
230
  mergedMesh.geometry = resultGeo;
226
231
  finalShinTrimmed.geometry.dispose();
@@ -477,10 +482,8 @@ export function generateRoofSegmentGeometry(node) {
477
482
  const hollowWall = csgEvaluator.evaluate(wallBrush, innerBrush, SUBTRACTION);
478
483
  const shinDeck = csgEvaluator.evaluate(shinSlab, deckSlab, ADDITION);
479
484
  const combined = csgEvaluator.evaluate(shinDeck, hollowWall, ADDITION);
480
- resultGeo = combined.geometry;
481
- const resultMaterials = Array.isArray(combined.material)
482
- ? combined.material
483
- : [combined.material];
485
+ resultGeo = csgGeometry(combined);
486
+ const resultMaterials = csgMaterials(combined);
484
487
  const matToIndex = new Map([
485
488
  [dummyMats[0], 0],
486
489
  [dummyMats[1], 1],
@@ -496,14 +499,14 @@ export function generateRoofSegmentGeometry(node) {
496
499
  }
497
500
  catch (e) {
498
501
  console.error('Roof CSG failed:', e);
499
- resultGeo = wallBrush.geometry.clone();
502
+ resultGeo = csgGeometry(wallBrush).clone();
500
503
  }
501
504
  deckSlab.geometry.dispose();
502
505
  shinSlab.geometry.dispose();
503
506
  wallBrush.geometry.dispose();
504
507
  innerBrush.geometry.dispose();
505
- ensureUv2Attribute(resultGeo);
506
508
  resultGeo.computeVertexNormals();
509
+ ensureUv2Attribute(resultGeo);
507
510
  return resultGeo;
508
511
  }
509
512
  function remapRoofShellFaces(geometry, node) {
@@ -1 +1 @@
1
- {"version":3,"file":"scan-system.d.ts","sourceRoot":"","sources":["../../../src/systems/scan/scan-system.tsx"],"names":[],"mappings":"AAIA,eAAO,MAAM,UAAU,YAsCtB,CAAA"}
1
+ {"version":3,"file":"scan-system.d.ts","sourceRoot":"","sources":["../../../src/systems/scan/scan-system.tsx"],"names":[],"mappings":"AAIA,eAAO,MAAM,UAAU,YActB,CAAA"}
@@ -1,4 +1,4 @@
1
- import { emitter, sceneRegistry } from '@pascal-app/core';
1
+ import { sceneRegistry } from '@pascal-app/core';
2
2
  import { useEffect } from 'react';
3
3
  import useViewer from '../../store/use-viewer';
4
4
  export const ScanSystem = () => {
@@ -12,30 +12,5 @@ export const ScanSystem = () => {
12
12
  }
13
13
  });
14
14
  }, [showScans]);
15
- useEffect(() => {
16
- const hideForCapture = () => {
17
- const scans = sceneRegistry.byType.scan || new Set();
18
- scans.forEach((scanId) => {
19
- const node = sceneRegistry.nodes.get(scanId);
20
- if (node)
21
- node.visible = false;
22
- });
23
- };
24
- const restoreAfterCapture = () => {
25
- const showScansNow = useViewer.getState().showScans;
26
- const scans = sceneRegistry.byType.scan || new Set();
27
- scans.forEach((scanId) => {
28
- const node = sceneRegistry.nodes.get(scanId);
29
- if (node)
30
- node.visible = showScansNow;
31
- });
32
- };
33
- emitter.on('thumbnail:before-capture', hideForCapture);
34
- emitter.on('thumbnail:after-capture', restoreAfterCapture);
35
- return () => {
36
- emitter.off('thumbnail:before-capture', hideForCapture);
37
- emitter.off('thumbnail:after-capture', restoreAfterCapture);
38
- };
39
- }, []);
40
15
  return null;
41
16
  };
@@ -1 +1 @@
1
- {"version":3,"file":"slab-system.d.ts","sourceRoot":"","sources":["../../../src/systems/slab/slab-system.tsx"],"names":[],"mappings":"AACA,OAAO,EAIL,KAAK,QAAQ,EAEd,MAAM,kBAAkB,CAAA;AACzB,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAa9B,eAAO,MAAM,UAAU,YAwBtB,CAAA;AAkBD;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,QAAQ,GAAG,KAAK,CAAC,cAAc,CAG7E"}
1
+ {"version":3,"file":"slab-system.d.ts","sourceRoot":"","sources":["../../../src/systems/slab/slab-system.tsx"],"names":[],"mappings":"AAAA,OAAO,EAGL,KAAK,QAAQ,EAGd,MAAM,kBAAkB,CAAA;AAEzB,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAa9B,eAAO,MAAM,UAAU,YAwBtB,CAAA;AAkBD;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,QAAQ,GAAG,KAAK,CAAC,cAAc,CAG7E"}
@@ -1,5 +1,5 @@
1
- import { useFrame } from '@react-three/fiber';
2
1
  import { getRenderableSlabPolygon, sceneRegistry, useScene, } from '@pascal-app/core';
2
+ import { useFrame } from '@react-three/fiber';
3
3
  import * as THREE from 'three';
4
4
  function ensureUv2Attribute(geometry) {
5
5
  const uv = geometry.getAttribute('uv');