@pascal-app/viewer 1.0.4 → 1.0.6

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 (183) hide show
  1. package/dist/capture/capture-runtime.js +1 -1
  2. package/dist/components/error-boundary.d.ts.map +1 -1
  3. package/dist/components/renderers/node-renderer.d.ts +1 -1
  4. package/dist/components/renderers/node-renderer.d.ts.map +1 -1
  5. package/dist/components/renderers/node-renderer.js +4 -1
  6. package/dist/components/renderers/parametric-node-renderer.d.ts.map +1 -1
  7. package/dist/components/viewer/bvh-ecctrl.d.ts.map +1 -1
  8. package/dist/components/viewer/frame-limiter.d.ts.map +1 -1
  9. package/dist/components/viewer/glb-interactive.js +1 -1
  10. package/dist/components/viewer/glb-reference-nodes.js +1 -1
  11. package/dist/components/viewer/glb-replace-instances.js +1 -1
  12. package/dist/components/viewer/glb-scene.d.ts.map +1 -1
  13. package/dist/components/viewer/glb-scene.js +2 -3
  14. package/dist/components/viewer/glb-walkthrough-controller.js +1 -1
  15. package/dist/components/viewer/index.d.ts +10 -1
  16. package/dist/components/viewer/index.d.ts.map +1 -1
  17. package/dist/components/viewer/index.js +28 -12
  18. package/dist/components/viewer/lights.d.ts.map +1 -1
  19. package/dist/components/viewer/lights.js +107 -21
  20. package/dist/components/viewer/perf-panel.d.ts.map +1 -1
  21. package/dist/components/viewer/perf-panel.js +1 -1
  22. package/dist/components/viewer/post-processing.d.ts.map +1 -1
  23. package/dist/components/viewer/post-processing.js +96 -33
  24. package/dist/components/viewer/registered-systems.js +1 -1
  25. package/dist/components/viewer/scene-bvh.d.ts.map +1 -1
  26. package/dist/components/viewer/scene-bvh.js +1 -1
  27. package/dist/components/viewer/scene-environment.d.ts.map +1 -1
  28. package/dist/components/viewer/scene-environment.js +31 -11
  29. package/dist/components/viewer/selection-manager.js +15 -7
  30. package/dist/components/viewer/underground-ambiance.d.ts +9 -0
  31. package/dist/components/viewer/underground-ambiance.d.ts.map +1 -0
  32. package/dist/components/viewer/underground-ambiance.js +105 -0
  33. package/dist/components/viewer/viewer-camera.d.ts.map +1 -1
  34. package/dist/components/viewer/viewer-camera.js +1 -1
  35. package/dist/components/viewer/viewer-presentations.d.ts.map +1 -1
  36. package/dist/hooks/use-gltf-ktx2.d.ts.map +1 -1
  37. package/dist/hooks/use-gltf-ktx2.js +2 -0
  38. package/dist/hooks/use-node-events.d.ts.map +1 -1
  39. package/dist/index.d.ts +16 -7
  40. package/dist/index.d.ts.map +1 -1
  41. package/dist/index.js +16 -7
  42. package/dist/lib/backdrop.d.ts +17 -0
  43. package/dist/lib/backdrop.d.ts.map +1 -1
  44. package/dist/lib/backdrop.js +18 -1
  45. package/dist/lib/construction-dust.d.ts +57 -0
  46. package/dist/lib/construction-dust.d.ts.map +1 -0
  47. package/dist/lib/construction-dust.js +187 -0
  48. package/dist/lib/csg-utils.js +1 -1
  49. package/dist/lib/foundation-materials.d.ts +26 -0
  50. package/dist/lib/foundation-materials.d.ts.map +1 -0
  51. package/dist/lib/foundation-materials.js +65 -0
  52. package/dist/lib/gltf-unlit.d.ts +10 -0
  53. package/dist/lib/gltf-unlit.d.ts.map +1 -0
  54. package/dist/lib/gltf-unlit.js +23 -0
  55. package/dist/lib/ground-window.d.ts +33 -0
  56. package/dist/lib/ground-window.d.ts.map +1 -0
  57. package/dist/lib/ground-window.js +114 -0
  58. package/dist/lib/hero-pose.d.ts +1 -1
  59. package/dist/lib/hero-pose.d.ts.map +1 -1
  60. package/dist/lib/ink-edges.d.ts +2 -1
  61. package/dist/lib/ink-edges.d.ts.map +1 -1
  62. package/dist/lib/ktx2-loader.d.ts +7 -0
  63. package/dist/lib/ktx2-loader.d.ts.map +1 -1
  64. package/dist/lib/ktx2-loader.js +35 -0
  65. package/dist/lib/layer-pass.d.ts.map +1 -1
  66. package/dist/lib/layers.d.ts +11 -7
  67. package/dist/lib/layers.d.ts.map +1 -1
  68. package/dist/lib/layers.js +16 -6
  69. package/dist/lib/materials.d.ts +5 -0
  70. package/dist/lib/materials.d.ts.map +1 -1
  71. package/dist/lib/materials.js +34 -4
  72. package/dist/lib/merged-outline-node.d.ts +5 -0
  73. package/dist/lib/merged-outline-node.d.ts.map +1 -1
  74. package/dist/lib/merged-outline-node.js +80 -2
  75. package/dist/lib/pointer-events.d.ts +20 -4
  76. package/dist/lib/pointer-events.d.ts.map +1 -1
  77. package/dist/lib/pointer-events.js +78 -14
  78. package/dist/lib/post-processing-resources.d.ts.map +1 -1
  79. package/dist/lib/reveal-candidates.d.ts +80 -0
  80. package/dist/lib/reveal-candidates.d.ts.map +1 -0
  81. package/dist/lib/reveal-candidates.js +524 -0
  82. package/dist/lib/reveal-ghost.d.ts +9 -0
  83. package/dist/lib/reveal-ghost.d.ts.map +1 -0
  84. package/dist/lib/reveal-ghost.js +62 -0
  85. package/dist/lib/reveal-pending.d.ts +12 -0
  86. package/dist/lib/reveal-pending.d.ts.map +1 -0
  87. package/dist/lib/reveal-pending.js +12 -0
  88. package/dist/lib/reveal-pose.d.ts +70 -0
  89. package/dist/lib/reveal-pose.d.ts.map +1 -0
  90. package/dist/lib/reveal-pose.js +248 -0
  91. package/dist/lib/reveal-schedule.d.ts +208 -0
  92. package/dist/lib/reveal-schedule.d.ts.map +1 -0
  93. package/dist/lib/reveal-schedule.js +410 -0
  94. package/dist/lib/reveal-texture-scale.d.ts +5 -0
  95. package/dist/lib/reveal-texture-scale.d.ts.map +1 -0
  96. package/dist/lib/reveal-texture-scale.js +113 -0
  97. package/dist/lib/reveal-windows.d.ts +23 -0
  98. package/dist/lib/reveal-windows.d.ts.map +1 -0
  99. package/dist/lib/reveal-windows.js +31 -0
  100. package/dist/lib/reveal-wipe.d.ts +71 -0
  101. package/dist/lib/reveal-wipe.d.ts.map +1 -0
  102. package/dist/lib/reveal-wipe.js +105 -0
  103. package/dist/lib/scene-pass-mrt.d.ts +12 -0
  104. package/dist/lib/scene-pass-mrt.d.ts.map +1 -0
  105. package/dist/lib/scene-pass-mrt.js +23 -0
  106. package/dist/lib/scene-themes.d.ts +30 -8
  107. package/dist/lib/scene-themes.d.ts.map +1 -1
  108. package/dist/lib/scene-themes.js +36 -0
  109. package/dist/lib/scene-visibility.d.ts +11 -1
  110. package/dist/lib/scene-visibility.d.ts.map +1 -1
  111. package/dist/lib/scene-visibility.js +38 -0
  112. package/dist/lib/site-surfaces.d.ts +32 -0
  113. package/dist/lib/site-surfaces.d.ts.map +1 -0
  114. package/dist/lib/site-surfaces.js +70 -0
  115. package/dist/lib/snapshot-pipeline.d.ts +2 -1
  116. package/dist/lib/snapshot-pipeline.d.ts.map +1 -1
  117. package/dist/lib/snapshot-pipeline.js +35 -15
  118. package/dist/lib/tsl-compat.d.ts +2 -2
  119. package/dist/lib/tsl-compat.d.ts.map +1 -1
  120. package/dist/lib/underground-ambiance.d.ts +168 -0
  121. package/dist/lib/underground-ambiance.d.ts.map +1 -0
  122. package/dist/lib/underground-ambiance.js +334 -0
  123. package/dist/store/use-viewer.d.ts +184 -27
  124. package/dist/store/use-viewer.d.ts.map +1 -1
  125. package/dist/store/use-viewer.js +155 -19
  126. package/dist/systems/ceiling/ceiling-system.d.ts.map +1 -1
  127. package/dist/systems/ceiling/ceiling-system.js +2 -0
  128. package/dist/systems/construction-reveal/construction-dust.d.ts +16 -0
  129. package/dist/systems/construction-reveal/construction-dust.d.ts.map +1 -0
  130. package/dist/systems/construction-reveal/construction-dust.js +92 -0
  131. package/dist/systems/construction-reveal/construction-reveal.d.ts +276 -0
  132. package/dist/systems/construction-reveal/construction-reveal.d.ts.map +1 -0
  133. package/dist/systems/construction-reveal/construction-reveal.js +2383 -0
  134. package/dist/systems/construction-reveal/dust-material.d.ts +10 -0
  135. package/dist/systems/construction-reveal/dust-material.d.ts.map +1 -0
  136. package/dist/systems/construction-reveal/dust-material.js +17 -0
  137. package/dist/systems/construction-reveal/ghost-dress.d.ts +10 -0
  138. package/dist/systems/construction-reveal/ghost-dress.d.ts.map +1 -0
  139. package/dist/systems/construction-reveal/ghost-dress.js +24 -0
  140. package/dist/systems/elevator/elevator-interaction-system.d.ts +7 -0
  141. package/dist/systems/elevator/elevator-interaction-system.d.ts.map +1 -1
  142. package/dist/systems/elevator/elevator-interaction-system.js +18 -1
  143. package/dist/systems/geometry/geometry-system.d.ts.map +1 -1
  144. package/dist/systems/interactive/control-widget.d.ts.map +1 -1
  145. package/dist/systems/interactive/interactive-system.d.ts.map +1 -1
  146. package/dist/systems/interactive/interactive-system.js +16 -6
  147. package/dist/systems/interactive/scripted-clips.js +1 -1
  148. package/dist/systems/item-light/item-light-system.js +1 -1
  149. package/dist/systems/level/level-hold.d.ts +4 -0
  150. package/dist/systems/level/level-hold.d.ts.map +1 -0
  151. package/dist/systems/level/level-hold.js +14 -0
  152. package/dist/systems/level/level-system.d.ts.map +1 -1
  153. package/dist/systems/level/level-system.js +16 -1
  154. package/dist/systems/level/level-utils.d.ts +13 -3
  155. package/dist/systems/level/level-utils.d.ts.map +1 -1
  156. package/dist/systems/level/level-utils.js +56 -8
  157. package/dist/systems/roof/__fixtures__/roof-plane-cases.d.ts +103 -0
  158. package/dist/systems/roof/__fixtures__/roof-plane-cases.d.ts.map +1 -0
  159. package/dist/systems/roof/__fixtures__/roof-plane-cases.js +317 -0
  160. package/dist/systems/roof/roof-materials.d.ts +4 -2
  161. package/dist/systems/roof/roof-materials.d.ts.map +1 -1
  162. package/dist/systems/roof/roof-materials.js +18 -24
  163. package/dist/systems/roof/roof-system.d.ts +8 -1
  164. package/dist/systems/roof/roof-system.d.ts.map +1 -1
  165. package/dist/systems/roof/roof-system.js +195 -45
  166. package/dist/systems/wall/wall-cutout-cache.d.ts +32 -3
  167. package/dist/systems/wall/wall-cutout-cache.d.ts.map +1 -1
  168. package/dist/systems/wall/wall-cutout-cache.js +95 -2
  169. package/dist/systems/wall/wall-cutout.d.ts.map +1 -1
  170. package/dist/systems/wall/wall-material-variant.d.ts.map +1 -1
  171. package/dist/systems/wall/wall-materials.d.ts.map +1 -1
  172. package/dist/systems/wall/wall-materials.js +39 -4
  173. package/dist/systems/wall/wall-placeholder-sweep.d.ts.map +1 -1
  174. package/dist/systems/wall/wall-system.d.ts +5 -0
  175. package/dist/systems/wall/wall-system.d.ts.map +1 -1
  176. package/dist/systems/wall/wall-system.js +42 -19
  177. package/dist/systems/window/corner-frame.d.ts +10 -0
  178. package/dist/systems/window/corner-frame.d.ts.map +1 -0
  179. package/dist/systems/window/corner-frame.js +17 -0
  180. package/dist/systems/window/window-system.d.ts +1 -1
  181. package/dist/systems/window/window-system.d.ts.map +1 -1
  182. package/dist/systems/window/window-system.js +31 -6
  183. package/package.json +8 -8
@@ -0,0 +1,10 @@
1
+ import type { InstancedBufferAttribute } from 'three';
2
+ import { MeshBasicNodeMaterial } from 'three/webgpu';
3
+ /**
4
+ * A soft disc on a quad, faded per sprite by `alpha`. It draws into the scene pass so walls in front
5
+ * hide it, and writes nothing to that pass's normals and diffuse colour (alpha 0 under their material
6
+ * blending): the ink reads the normals, and the whole quad, not just its disc, was an edge there.
7
+ * `output` is named too: a pass without MRT draws what this node names and nothing else.
8
+ */
9
+ export declare function createDustMaterial(alpha: InstancedBufferAttribute): MeshBasicNodeMaterial;
10
+ //# sourceMappingURL=dust-material.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dust-material.d.ts","sourceRoot":"","sources":["../../../src/systems/construction-reveal/dust-material.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,OAAO,CAAA;AAErD,OAAO,EAAE,qBAAqB,EAAE,MAAM,cAAc,CAAA;AAIpD;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,wBAAwB,yBAOjE"}
@@ -0,0 +1,17 @@
1
+ import { color, float, instancedDynamicBufferAttribute, mrt, output, uv, vec4 } from 'three/tsl';
2
+ import { MeshBasicNodeMaterial } from 'three/webgpu';
3
+ const DUST_COLOR = '#d9cdb8';
4
+ /**
5
+ * A soft disc on a quad, faded per sprite by `alpha`. It draws into the scene pass so walls in front
6
+ * hide it, and writes nothing to that pass's normals and diffuse colour (alpha 0 under their material
7
+ * blending): the ink reads the normals, and the whole quad, not just its disc, was an edge there.
8
+ * `output` is named too: a pass without MRT draws what this node names and nothing else.
9
+ */
10
+ export function createDustMaterial(alpha) {
11
+ const material = new MeshBasicNodeMaterial({ transparent: true, depthWrite: false });
12
+ material.colorNode = color(DUST_COLOR);
13
+ const edge = float(1).sub(uv().sub(0.5).length().mul(2)).clamp(0, 1);
14
+ material.opacityNode = edge.mul(edge).mul(instancedDynamicBufferAttribute(alpha, 'float'));
15
+ material.mrtNode = mrt({ output, diffuseColor: vec4(0), normal: vec4(0) });
16
+ return material;
17
+ }
@@ -0,0 +1,10 @@
1
+ import type { Object3D } from 'three';
2
+ /**
3
+ * The picture a deleted node plays out is a copy of what stood there, and a copy wears the
4
+ * material its source had in that frame. A node the cutaway was hiding wears its stipple, so its
5
+ * deletion would play as faint dots: when its source carries a visible variant (the wall cutout
6
+ * keeps one, `visibleMaterialsOf`), the copy wears that instead, the one a capture draws, for as long
7
+ * as it plays. What the cutaway showed, and any other wall mode, keep what they wear.
8
+ */
9
+ export declare function dressDeletionGhost(source: Object3D, clone: Object3D): void;
10
+ //# sourceMappingURL=ghost-dress.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ghost-dress.d.ts","sourceRoot":"","sources":["../../../src/systems/construction-reveal/ghost-dress.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAQ,QAAQ,EAAE,MAAM,OAAO,CAAA;AAK3C;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,QAAQ,EAAE,KAAK,EAAE,QAAQ,QAenE"}
@@ -0,0 +1,24 @@
1
+ import { hasMaterialsForGroups } from '../../lib/pointer-events';
2
+ import useViewer from '../../store/use-viewer';
3
+ import { visibleMaterialsOf } from '../wall/wall-cutout-cache';
4
+ /**
5
+ * The picture a deleted node plays out is a copy of what stood there, and a copy wears the
6
+ * material its source had in that frame. A node the cutaway was hiding wears its stipple, so its
7
+ * deletion would play as faint dots: when its source carries a visible variant (the wall cutout
8
+ * keeps one, `visibleMaterialsOf`), the copy wears that instead, the one a capture draws, for as long
9
+ * as it plays. What the cutaway showed, and any other wall mode, keep what they wear.
10
+ */
11
+ export function dressDeletionGhost(source, clone) {
12
+ const visible = visibleMaterialsOf.get(source);
13
+ const mesh = clone;
14
+ if (visible &&
15
+ useViewer.getState().wallMode === 'cutaway' &&
16
+ source.userData.wallHidden === true &&
17
+ mesh.isMesh &&
18
+ mesh.geometry &&
19
+ // A room-wide paint preview can leave the source with more groups than the palette has
20
+ // entries; a copy with a group and no material throws on every raycast over it (see
21
+ // `WallCutoutCache.mayAssign`), so it keeps what it wears then.
22
+ hasMaterialsForGroups(mesh, visible))
23
+ mesh.material = visible;
24
+ }
@@ -1,2 +1,9 @@
1
+ import { type Object3D } from 'three';
2
+ /**
3
+ * The roots of every elevator button under `object`. Any button along the ray
4
+ * takes the click, so only they are raycast — never the rest of the scene,
5
+ * whose meshes this capture-phase listener must not trip over.
6
+ */
7
+ export declare function collectElevatorButtons(object: Object3D, into?: Object3D[]): Object3D[];
1
8
  export declare function ElevatorInteractionSystem(): null;
2
9
  //# sourceMappingURL=elevator-interaction-system.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"elevator-interaction-system.d.ts","sourceRoot":"","sources":["../../../src/systems/elevator/elevator-interaction-system.tsx"],"names":[],"mappings":"AAkCA,wBAAgB,yBAAyB,SA0DxC"}
1
+ {"version":3,"file":"elevator-interaction-system.d.ts","sourceRoot":"","sources":["../../../src/systems/elevator/elevator-interaction-system.tsx"],"names":[],"mappings":"AAUA,OAAO,EAAE,KAAK,QAAQ,EAAsB,MAAM,OAAO,CAAA;AAwBzD;;;;GAIG;AACH,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,QAAQ,EAAE,IAAI,GAAE,QAAQ,EAAO,GAAG,QAAQ,EAAE,CAO1F;AAED,wBAAgB,yBAAyB,SA6DxC"}
@@ -12,6 +12,20 @@ function getElevatorButtonData(object) {
12
12
  }
13
13
  return null;
14
14
  }
15
+ /**
16
+ * The roots of every elevator button under `object`. Any button along the ray
17
+ * takes the click, so only they are raycast — never the rest of the scene,
18
+ * whose meshes this capture-phase listener must not trip over.
19
+ */
20
+ export function collectElevatorButtons(object, into = []) {
21
+ if (object.userData.elevatorButton) {
22
+ into.push(object);
23
+ return into;
24
+ }
25
+ for (const child of object.children)
26
+ collectElevatorButtons(child, into);
27
+ return into;
28
+ }
15
29
  export function ElevatorInteractionSystem() {
16
30
  const camera = useThree((state) => state.camera);
17
31
  const gl = useThree((state) => state.gl);
@@ -23,6 +37,9 @@ export function ElevatorInteractionSystem() {
23
37
  const handlePointerDown = (event) => {
24
38
  if (event.button !== 0)
25
39
  return;
40
+ const buttons = collectElevatorButtons(scene);
41
+ if (buttons.length === 0)
42
+ return;
26
43
  const rect = canvas.getBoundingClientRect();
27
44
  const pointer = pointerRef.current;
28
45
  pointer.x = ((event.clientX - rect.left) / rect.width) * 2 - 1;
@@ -30,7 +47,7 @@ export function ElevatorInteractionSystem() {
30
47
  const raycaster = raycasterRef.current;
31
48
  raycaster.setFromCamera(pointer, camera);
32
49
  const button = raycaster
33
- .intersectObjects(scene.children, true)
50
+ .intersectObjects(buttons, true)
34
51
  .map((intersection) => getElevatorButtonData(intersection.object))
35
52
  .find((data) => data !== null);
36
53
  if (!button || button.disabled)
@@ -1 +1 @@
1
- {"version":3,"file":"geometry-system.d.ts","sourceRoot":"","sources":["../../../src/systems/geometry/geometry-system.tsx"],"names":[],"mappings":"AAkBA,OAAO,EAAa,KAAK,KAAK,EAA4B,KAAK,QAAQ,EAAE,MAAM,OAAO,CAAA;AAatF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,eAAO,MAAM,cAAc,YA8N1B,CAAA;AA+KD,eAAe,cAAc,CAAA;AAE7B,MAAM,MAAM,uBAAuB,GAAG;IACpC,KAAK,EAAE,KAAK,CAAA;IACZ,GAAG,EAAE,MAAM,CAAA;CACZ,CAAA;AAED,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,QAAQ,GAAG,IAAI,CAY7D;AAED,wBAAgB,wBAAwB,CACtC,KAAK,EAAE,GAAG,CAAC,MAAM,EAAE,uBAAuB,CAAC,EAC3C,EAAE,EAAE,MAAM,EACV,KAAK,EAAE,KAAK,EACZ,GAAG,EAAE,MAAM,GACV,OAAO,CAKT"}
1
+ {"version":3,"file":"geometry-system.d.ts","sourceRoot":"","sources":["../../../src/systems/geometry/geometry-system.tsx"],"names":[],"mappings":"AAkBA,OAAO,EAAa,KAAK,KAAK,EAA4B,KAAK,QAAQ,EAAE,MAAM,OAAO,CAAA;AAatF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,eAAO,MAAM,cAAc,YA8N1B,CAAA;eA+Kc,cAAc;AAE7B,MAAM,MAAM,uBAAuB,GAAG;IACpC,KAAK,EAAE,KAAK,CAAA;IACZ,GAAG,EAAE,MAAM,CAAA;CACZ,CAAA;AAED,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,QAAQ,GAAG,IAAI,CAY7D;AAED,wBAAgB,wBAAwB,CACtC,KAAK,EAAE,GAAG,CAAC,MAAM,EAAE,uBAAuB,CAAC,EAC3C,EAAE,EAAE,MAAM,EACV,KAAK,EAAE,KAAK,EACZ,GAAG,EAAE,MAAM,GACV,OAAO,CAKT"}
@@ -1 +1 @@
1
- {"version":3,"file":"control-widget.d.ts","sourceRoot":"","sources":["../../../src/systems/interactive/control-widget.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAA;AAE7D;;8EAE8E;AAC9E,eAAO,MAAM,aAAa,GAAI,+BAI3B;IACD,OAAO,EAAE,OAAO,CAAA;IAChB,KAAK,EAAE,YAAY,CAAA;IACnB,QAAQ,EAAE,CAAC,CAAC,EAAE,YAAY,KAAK,IAAI,CAAA;CACpC,uCAuEA,CAAA"}
1
+ {"version":3,"file":"control-widget.d.ts","sourceRoot":"","sources":["../../../src/systems/interactive/control-widget.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAA;AAE7D;;8EAE8E;AAC9E,eAAO,MAAM,aAAa,kCAIvB;IACD,OAAO,EAAE,OAAO,CAAA;IAChB,KAAK,EAAE,YAAY,CAAA;IACnB,QAAQ,EAAE,CAAC,CAAC,EAAE,YAAY,KAAK,IAAI,CAAA;CACpC,uCAuEA,CAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"interactive-system.d.ts","sourceRoot":"","sources":["../../../src/systems/interactive/interactive-system.tsx"],"names":[],"mappings":"AAmCA,eAAO,MAAM,iBAAiB,mCAmC7B,CAAA"}
1
+ {"version":3,"file":"interactive-system.d.ts","sourceRoot":"","sources":["../../../src/systems/interactive/interactive-system.tsx"],"names":[],"mappings":"AAwCA,eAAO,MAAM,iBAAiB,mCAoC7B,CAAA"}
@@ -1,6 +1,6 @@
1
1
  'use client';
2
- import { jsx as _jsx, Fragment as _Fragment } from "react/jsx-runtime";
3
- import { pointInPolygon, sceneRegistry, useInteractive, useScene, } from '@pascal-app/core';
2
+ import { Fragment as _Fragment, jsx as _jsx } from "react/jsx-runtime";
3
+ import { isScriptedNode, pointInPolygon, sceneRegistry, scriptedOrigin, scriptedSize, scriptInteractive, useInteractive, useScene, } from '@pascal-app/core';
4
4
  import { evaluateRecipe, operableParts, } from '@pascal-app/core/procedural-items';
5
5
  import { Html } from '@react-three/drei';
6
6
  import { createPortal, useFrame } from '@react-three/fiber';
@@ -29,7 +29,8 @@ export const InteractiveSystem = () => {
29
29
  return z?.polygon ?? null;
30
30
  });
31
31
  const interactiveNodeIds = useScene(useShallow((state) => Object.values(state.nodes)
32
- .filter((n) => (n.type === 'item' && n.asset.interactive != null) ||
32
+ .filter((n) => (isScriptedNode(n) && scriptInteractive(n.source.manifest) != null) ||
33
+ (n.type === 'item' && n.asset.interactive != null) ||
33
34
  (n.type === 'procedural-item' &&
34
35
  (operableParts(n.recipe).length > 0 || n.recipe.parts.some((part) => part.light))))
35
36
  .map((n) => n.id)));
@@ -61,14 +62,23 @@ const ItemControlsOverlay = ({ nodeId, zonePolygon, isSelected, }) => {
61
62
  ]);
62
63
  let descriptors = [];
63
64
  let height = 0;
64
- if (node?.type === 'item' && node.asset.interactive && controlValues) {
65
- descriptors = node.asset.interactive.controls.map((control, i) => ({
65
+ const interactive = isScriptedNode(node)
66
+ ? scriptInteractive(node.source.manifest, scriptedOrigin(node))
67
+ : node?.type === 'item'
68
+ ? node.asset.interactive
69
+ : undefined;
70
+ if (interactive && controlValues) {
71
+ descriptors = interactive.controls.map((control, i) => ({
66
72
  key: String(i),
67
73
  control,
68
74
  value: controlValues[i] ?? false,
69
75
  onChange: (value) => setControlValue(nodeId, i, value),
70
76
  }));
71
- height = node.asset.dimensions[1];
77
+ height = isScriptedNode(node)
78
+ ? scriptedSize(node.source.manifest)[1] + scriptedOrigin(node)[1]
79
+ : node?.type === 'item'
80
+ ? node.asset.dimensions[1]
81
+ : 0;
72
82
  }
73
83
  else if (node?.type === 'procedural-item') {
74
84
  descriptors = proceduralControlDescriptors(node.recipe, proceduralState, (partId) => togglePart(nodeId, partId), () => toggleLights(nodeId), lampDefault);
@@ -1,5 +1,5 @@
1
1
  'use client';
2
- import { jsx as _jsx, Fragment as _Fragment } from "react/jsx-runtime";
2
+ import { Fragment as _Fragment, jsx as _jsx } from "react/jsx-runtime";
3
3
  import { useInteractive, } from '@pascal-app/core';
4
4
  import { useFrame } from '@react-three/fiber';
5
5
  import { useEffect, useLayoutEffect, useMemo, useRef } from 'react';
@@ -1,4 +1,4 @@
1
- import { jsx as _jsx, Fragment as _Fragment } from "react/jsx-runtime";
1
+ import { Fragment as _Fragment, jsx as _jsx } from "react/jsx-runtime";
2
2
  import { findLevelAncestorId, sceneRegistry, useScene } from '@pascal-app/core';
3
3
  import { useFrame, useThree } from '@react-three/fiber';
4
4
  import { useRef } from 'react';
@@ -0,0 +1,4 @@
1
+ export declare const setHeldLevelY: (levelId: string, y: number) => void;
2
+ export declare const heldLevelY: (levelId: string) => number | undefined;
3
+ export declare const releaseLevel: (levelId: string) => void;
4
+ //# sourceMappingURL=level-hold.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"level-hold.d.ts","sourceRoot":"","sources":["../../../src/systems/level/level-hold.ts"],"names":[],"mappings":"AAQA,eAAO,MAAM,aAAa,YAAa,MAAM,KAAK,MAAM,SAEvD,CAAA;AAED,eAAO,MAAM,UAAU,YAAa,MAAM,KAAG,MAAM,GAAG,SAA+B,CAAA;AAErF,eAAO,MAAM,YAAY,YAAa,MAAM,SAE3C,CAAA"}
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Levels a construction reveal presents at a height of its own: the levels above a floor being taken
3
+ * apart stay where they stood until it has gone, then the reveal brings them down onto what is below,
4
+ * writing the height every frame. `LevelSystem` reads `heldLevelY` ahead of the stacked elevation, so a
5
+ * held level is neither lerped nor snapped. Presentation only: no scene write.
6
+ */
7
+ const heldY = new Map();
8
+ export const setHeldLevelY = (levelId, y) => {
9
+ heldY.set(levelId, y);
10
+ };
11
+ export const heldLevelY = (levelId) => heldY.get(levelId);
12
+ export const releaseLevel = (levelId) => {
13
+ heldY.delete(levelId);
14
+ };
@@ -1 +1 @@
1
- {"version":3,"file":"level-system.d.ts","sourceRoot":"","sources":["../../../src/systems/level/level-system.tsx"],"names":[],"mappings":"AAQA,eAAO,MAAM,WAAW,YA+DvB,CAAA"}
1
+ {"version":3,"file":"level-system.d.ts","sourceRoot":"","sources":["../../../src/systems/level/level-system.tsx"],"names":[],"mappings":"AAWA,eAAO,MAAM,WAAW,YAyEvB,CAAA"}
@@ -3,14 +3,17 @@ import { useFrame } from '@react-three/fiber';
3
3
  import { lerp } from 'three/src/math/MathUtils.js';
4
4
  import { applyShadowOnly, clearShadowOnly } from '../../lib/shadow-only';
5
5
  import useViewer from '../../store/use-viewer';
6
+ import { heldLevelY } from './level-hold';
6
7
  import { EXPLODED_GAP, resolveLevelVisibility } from './level-utils';
7
8
  import { shadowOnlyLevels } from './shadow-only-levels';
9
+ const placed = new WeakSet();
8
10
  export const LevelSystem = () => {
9
11
  useFrame((_, delta) => {
10
12
  const nodes = useScene.getState().nodes;
11
13
  const levelMode = useViewer.getState().levelMode;
12
14
  const hideAbove = useViewer.getState().hideLevelsAboveSelection;
13
15
  const selectedLevel = useViewer.getState().selection.levelId;
16
+ const levelsRevealing = useViewer.getState().levelsRevealing;
14
17
  const levelElevations = getLevelElevations(nodes);
15
18
  const entries = [];
16
19
  sceneRegistry.byType.level.forEach((levelId) => {
@@ -24,6 +27,10 @@ export const LevelSystem = () => {
24
27
  });
25
28
  }
26
29
  });
30
+ // A level that has just mounted (a restored floor, a new storey) cuts every level to its height
31
+ // together: sliding them from where they were would run the floor and the levels above through
32
+ // each other.
33
+ const appeared = entries.some(({ obj }) => !placed.has(obj));
27
34
  const selectedIndex = selectedLevel
28
35
  ? entries.find((e) => e.levelId === selectedLevel)?.index
29
36
  : undefined;
@@ -38,7 +45,14 @@ export const LevelSystem = () => {
38
45
  // oscillated kilometers off-screen and the level-fit camera followed
39
46
  // (blank viewport). Clamping keeps every step a contraction: identical
40
47
  // feel at 60 fps, exact snap instead of overshoot on slow frames.
41
- obj.position.y = lerp(obj.position.y, targetY, Math.min(1, delta * 12));
48
+ const held = heldLevelY(levelId);
49
+ if (held !== undefined)
50
+ obj.position.y = held;
51
+ else if (appeared)
52
+ obj.position.y = targetY;
53
+ else
54
+ obj.position.y = lerp(obj.position.y, targetY, Math.min(1, delta * 12));
55
+ placed.add(obj);
42
56
  const { visible, shadowOnly } = resolveLevelVisibility({
43
57
  levelMode,
44
58
  hideAbove,
@@ -47,6 +61,7 @@ export const LevelSystem = () => {
47
61
  index,
48
62
  selectedIndex,
49
63
  nodeVisible: level?.visible !== false,
64
+ revealing: levelsRevealing.includes(levelId),
50
65
  });
51
66
  if (shadowOnly) {
52
67
  applyShadowOnly(obj);
@@ -1,4 +1,5 @@
1
- export declare const EXPLODED_GAP = 5;
1
+ import { type SceneViewPresentation } from '@pascal-app/core/agent-operations';
2
+ export { EXPLODED_GAP } from '@pascal-app/core';
2
3
  /**
3
4
  * The Y a level settles at under the given presentation mode — its stacked
4
5
  * elevation plus the exploded gap. Analytic (scene store + mode), never a
@@ -19,8 +20,12 @@ export declare function getLevelPresentationY(levelId: string, nodes: Record<str
19
20
  * shadow map so the sun still shadows the selected floor through them.
20
21
  * A level the author hid never enters that shadow-caster branch: its shadows
21
22
  * on the floor below would be exactly what hiding it was meant to remove.
23
+ *
24
+ * A level a construction reveal is playing on (`revealing`) shows whatever the
25
+ * presentation hides, so the animation is seen; only the author's own hiding
26
+ * keeps it out.
22
27
  */
23
- export declare function resolveLevelVisibility({ levelMode, hideAbove, hasSelectedLevel, isSelected, index, selectedIndex, nodeVisible, }: {
28
+ export declare function resolveLevelVisibility({ levelMode, hideAbove, hasSelectedLevel, isSelected, index, selectedIndex, nodeVisible, revealing, }: {
24
29
  levelMode: 'stacked' | 'exploded' | 'solo' | 'manual';
25
30
  hideAbove: boolean;
26
31
  hasSelectedLevel: boolean;
@@ -28,6 +33,7 @@ export declare function resolveLevelVisibility({ levelMode, hideAbove, hasSelect
28
33
  index: number;
29
34
  selectedIndex: number | undefined;
30
35
  nodeVisible: boolean;
36
+ revealing: boolean;
31
37
  }): {
32
38
  visible: boolean;
33
39
  shadowOnly: boolean;
@@ -46,5 +52,9 @@ export declare function resolveLevelVisibility({ levelMode, hideAbove, hasSelect
46
52
  * renderer.render(scene, camera)
47
53
  * restore()
48
54
  */
49
- export declare function snapLevelsToTruePositions(): () => void;
55
+ export declare function snapLevelsToTruePositions({ readOnly, }?: {
56
+ readOnly?: boolean;
57
+ }): () => void;
58
+ /** The viewer's settled level presentation for one render, without changing saved preferences. */
59
+ export declare function presentLevelsForCapture(presentation: SceneViewPresentation): () => void;
50
60
  //# sourceMappingURL=level-utils.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"level-utils.d.ts","sourceRoot":"","sources":["../../../src/systems/level/level-utils.ts"],"names":[],"mappings":"AAIA,eAAO,MAAM,YAAY,IAAI,CAAA;AAE7B;;;;;;GAMG;AACH,wBAAgB,qBAAqB,CACnC,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC9B,SAAS,EAAE,SAAS,GAAG,UAAU,GAAG,MAAM,GAAG,QAAQ,GACpD,MAAM,CAKR;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,sBAAsB,CAAC,EACrC,SAAS,EACT,SAAS,EACT,gBAAgB,EAChB,UAAU,EACV,KAAK,EACL,aAAa,EACb,WAAW,GACZ,EAAE;IACD,SAAS,EAAE,SAAS,GAAG,UAAU,GAAG,MAAM,GAAG,QAAQ,CAAA;IACrD,SAAS,EAAE,OAAO,CAAA;IAClB,gBAAgB,EAAE,OAAO,CAAA;IACzB,UAAU,EAAE,OAAO,CAAA;IACnB,KAAK,EAAE,MAAM,CAAA;IACb,aAAa,EAAE,MAAM,GAAG,SAAS,CAAA;IACjC,WAAW,EAAE,OAAO,CAAA;CACrB,GAAG;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,UAAU,EAAE,OAAO,CAAA;CAAE,CAQ5C;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,yBAAyB,IAAI,MAAM,IAAI,CA+CtD"}
1
+ {"version":3,"file":"level-utils.d.ts","sourceRoot":"","sources":["../../../src/systems/level/level-utils.ts"],"names":[],"mappings":"AAOA,OAAO,EACL,KAAK,qBAAqB,EAE3B,MAAM,mCAAmC,CAAA;AAS1C,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAA;AAE/C;;;;;;GAMG;AACH,wBAAgB,qBAAqB,CACnC,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC9B,SAAS,EAAE,SAAS,GAAG,UAAU,GAAG,MAAM,GAAG,QAAQ,GACpD,MAAM,CAKR;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,sBAAsB,CAAC,EACrC,SAAS,EACT,SAAS,EACT,gBAAgB,EAChB,UAAU,EACV,KAAK,EACL,aAAa,EACb,WAAW,EACX,SAAS,GACV,EAAE;IACD,SAAS,EAAE,SAAS,GAAG,UAAU,GAAG,MAAM,GAAG,QAAQ,CAAA;IACrD,SAAS,EAAE,OAAO,CAAA;IAClB,gBAAgB,EAAE,OAAO,CAAA;IACzB,UAAU,EAAE,OAAO,CAAA;IACnB,KAAK,EAAE,MAAM,CAAA;IACb,aAAa,EAAE,MAAM,GAAG,SAAS,CAAA;IACjC,WAAW,EAAE,OAAO,CAAA;IACpB,SAAS,EAAE,OAAO,CAAA;CACnB,GAAG;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,UAAU,EAAE,OAAO,CAAA;CAAE,CAS5C;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,yBAAyB,CAAC,EACxC,QAAgB,GACjB,GAAE;IACD,QAAQ,CAAC,EAAE,OAAO,CAAA;CACd,GAAG,MAAM,IAAI,CAiDlB;AAED,kGAAkG;AAClG,wBAAgB,uBAAuB,CAAC,YAAY,EAAE,qBAAqB,GAAG,MAAM,IAAI,CAiCvF"}
@@ -1,7 +1,9 @@
1
- import { getLevelElevations, sceneRegistry, useScene } from '@pascal-app/core';
1
+ import { EXPLODED_GAP, getLevelElevations, sceneRegistry, useScene, } from '@pascal-app/core';
2
+ import { sceneViewPresentationLevel, } from '@pascal-app/core/agent-operations';
3
+ import { temporarilyHideFromScene, temporarilyShowPresentation, temporarilyShowShadowOnly, } from '../../lib/scene-visibility';
2
4
  import { applyShadowOnly, clearShadowOnly } from '../../lib/shadow-only';
3
5
  import { shadowOnlyLevels } from './shadow-only-levels';
4
- export const EXPLODED_GAP = 5;
6
+ export { EXPLODED_GAP } from '@pascal-app/core';
5
7
  /**
6
8
  * The Y a level settles at under the given presentation mode — its stacked
7
9
  * elevation plus the exploded gap. Analytic (scene store + mode), never a
@@ -27,10 +29,16 @@ export function getLevelPresentationY(levelId, nodes, levelMode) {
27
29
  * shadow map so the sun still shadows the selected floor through them.
28
30
  * A level the author hid never enters that shadow-caster branch: its shadows
29
31
  * on the floor below would be exactly what hiding it was meant to remove.
32
+ *
33
+ * A level a construction reveal is playing on (`revealing`) shows whatever the
34
+ * presentation hides, so the animation is seen; only the author's own hiding
35
+ * keeps it out.
30
36
  */
31
- export function resolveLevelVisibility({ levelMode, hideAbove, hasSelectedLevel, isSelected, index, selectedIndex, nodeVisible, }) {
37
+ export function resolveLevelVisibility({ levelMode, hideAbove, hasSelectedLevel, isSelected, index, selectedIndex, nodeVisible, revealing, }) {
32
38
  if (!nodeVisible)
33
39
  return { visible: false, shadowOnly: false };
40
+ if (revealing)
41
+ return { visible: true, shadowOnly: false };
34
42
  const hidden = (levelMode === 'solo' && hasSelectedLevel && !isSelected) ||
35
43
  (hideAbove && selectedIndex !== undefined && index > selectedIndex);
36
44
  const shadowOnly = hidden && selectedIndex !== undefined && index > selectedIndex;
@@ -50,7 +58,7 @@ export function resolveLevelVisibility({ levelMode, hideAbove, hasSelectedLevel,
50
58
  * renderer.render(scene, camera)
51
59
  * restore()
52
60
  */
53
- export function snapLevelsToTruePositions() {
61
+ export function snapLevelsToTruePositions({ readOnly = false, } = {}) {
54
62
  const nodes = useScene.getState().nodes;
55
63
  const entries = [];
56
64
  sceneRegistry.byType.level.forEach((levelId) => {
@@ -74,8 +82,10 @@ export function snapLevelsToTruePositions() {
74
82
  obj.position.y = levelElevations.get(levelId)?.baseY ?? 0;
75
83
  obj.visible = nodeVisible;
76
84
  }
77
- for (const { obj } of shadowOnly)
78
- clearShadowOnly(obj);
85
+ const restoreMasks = readOnly ? shadowOnly.map(({ obj }) => temporarilyShowShadowOnly(obj)) : [];
86
+ if (!readOnly)
87
+ for (const { obj } of shadowOnly)
88
+ clearShadowOnly(obj);
79
89
  return () => {
80
90
  for (const { levelId, obj } of entries) {
81
91
  const saved = snapshot.get(levelId);
@@ -84,7 +94,45 @@ export function snapLevelsToTruePositions() {
84
94
  obj.visible = saved.visible;
85
95
  }
86
96
  }
87
- for (const { obj } of shadowOnly)
88
- applyShadowOnly(obj);
97
+ if (readOnly)
98
+ for (const restore of restoreMasks.reverse())
99
+ restore();
100
+ else
101
+ for (const { obj } of shadowOnly)
102
+ applyShadowOnly(obj);
103
+ };
104
+ }
105
+ /** The viewer's settled level presentation for one render, without changing saved preferences. */
106
+ export function presentLevelsForCapture(presentation) {
107
+ const nodes = useScene.getState().nodes;
108
+ const selected = sceneViewPresentationLevel(nodes, presentation);
109
+ if (selected &&
110
+ (!sceneRegistry.nodes.has(selected.id) || !sceneRegistry.byType.level?.has(selected.id)))
111
+ throw new Error('The level to capture is not ready in this renderer. Try again.');
112
+ const restores = [snapLevelsToTruePositions({ readOnly: true })];
113
+ for (const levelId of sceneRegistry.byType.level ?? []) {
114
+ const obj = sceneRegistry.nodes.get(levelId);
115
+ const level = nodes[levelId];
116
+ if (!obj || level?.type !== 'level')
117
+ continue;
118
+ obj.position.y = getLevelPresentationY(levelId, nodes, presentation.mode);
119
+ const { visible, shadowOnly } = resolveLevelVisibility({
120
+ levelMode: presentation.mode,
121
+ hideAbove: false,
122
+ hasSelectedLevel: Boolean(selected),
123
+ isSelected: level.id === selected?.id,
124
+ index: level.level,
125
+ selectedIndex: selected?.type === 'level' ? selected.level : undefined,
126
+ nodeVisible: level.visible !== false,
127
+ revealing: false,
128
+ });
129
+ obj.visible = visible;
130
+ restores.push(level.id === selected?.id ? temporarilyShowPresentation(obj) : temporarilyShowShadowOnly(obj));
131
+ if (shadowOnly)
132
+ restores.push(temporarilyHideFromScene(obj, 'shadow-only'));
133
+ }
134
+ return () => {
135
+ for (const restore of restores.reverse())
136
+ restore();
89
137
  };
90
138
  }
@@ -0,0 +1,103 @@
1
+ /**
2
+ * Every roof the hosted Architect plugin's `hip_roof_planes` and `gable_roof_planes` built, each
3
+ * beside the `roof_segment_add` call that covers it and the roof segment that call writes, so the
4
+ * two plane tools can retire into it (catalogue slice R). No stored thread called either tool, so
5
+ * the cases are what their contracts take (both ridge axes, a hip either way and square, the
6
+ * default, wide, flush and wider-than-the-eaves gable overhangs, a thickness, an eave on the plate,
7
+ * over it and on posts) and the plugin's own call (a hip at the walls' 2.6 m tops).
8
+ *
9
+ * The plane tools took the rectangle of the walls' outside faces, a rise per 12, the overhang past
10
+ * those faces in metres (a gable's ends their own), a thickness square to the slope (0.29 m by
11
+ * default) and an eave height that was the roof's SURFACE at the outside wall face. The segment
12
+ * takes the same rectangle (`rectAt: 'outside'`), the pitch, the overhangs and the thickness in
13
+ * any unit, and an eave that is the plate it bears on, its default the walls' tops; the walls'
14
+ * thickness, which it reads from the walls along those faces (6.5 in where none stand, a porch on
15
+ * posts), puts their centre lines inside the faces.
16
+ *
17
+ * A plane call whose roof stood on its walls, or over them, is the same roof as a segment: same
18
+ * outline, surface, ridge and thickness (`lift` 0).
19
+ *
20
+ * Not reproduced, on purpose (no stored call made either, so each is a call a model could make):
21
+ * - A plane call with its eave at the walls' tops, the plugin's own and the likeliest, sank its roof
22
+ * into them: its slab's underside stood `thickness / cos(pitch)` under the plate at the wall face.
23
+ * A segment is never sunk under the walls it sits on (`eave_under_walls`); the replacement leaves
24
+ * the eave out and the roof sits on them, the same outline, pitch and thickness, its surface
25
+ * `lift` higher. Those rows say so.
26
+ * - Planes over a storey with another over it stood inside that storey; a segment refuses that
27
+ * (`into_storey_above`). The hosted table checks the refusal.
28
+ * - The plane tools answered each plane's id, so one slope could be edited or painted on its own
29
+ * (`update_roof_plane`). A segment is one mass whose slopes change together; one slope on its own
30
+ * is `create_roof_plane`'s, which stays, and the retired tools' answer says so.
31
+ *
32
+ * The viewer runs the segments through the roof geometry against the planes' own geometry
33
+ * (`roof-plane-cases.test.ts`); the hosted plugin runs each replacement call through
34
+ * `roof_segment_add` and reads back the segment it wrote.
35
+ */
36
+ type Rect = [number, number, number, number];
37
+ /** The walls' thickness, a 2x6 wall finished: what `roof_segment_add` reads from them. */
38
+ export declare const ROOF_PLANE_WALL_THICKNESS: number;
39
+ /** The covering a segment lays over its deck, in the thickness the plane tools took whole. */
40
+ export declare const ROOF_PLANE_COVERING = 0.02;
41
+ export type RoofPlaneCall = {
42
+ tool: 'hip_roof_planes' | 'gable_roof_planes';
43
+ rect: Rect;
44
+ ridgeAxis?: 'x' | 'z';
45
+ /** Rise per 12. */
46
+ pitch: number;
47
+ /** The roof's surface at the outside wall face, metres above the storey's floor. */
48
+ eaveHeight: number;
49
+ overhang?: number;
50
+ gableOverhang?: number;
51
+ thickness?: number;
52
+ name?: string;
53
+ };
54
+ export type RoofSegmentAddCall = {
55
+ roofType: 'hip' | 'gable';
56
+ name: string;
57
+ rect: Rect;
58
+ rectAt: 'outside';
59
+ ridgeAxis: 'x' | 'z';
60
+ pitchTwelfths: number;
61
+ overhangIn: string;
62
+ gableOverhangIn?: string;
63
+ thicknessIn: string;
64
+ eaveHeight?: number;
65
+ };
66
+ /** The segment a replacement call writes, in its storey's plan and metres. */
67
+ export type ExpectedRoofSegment = {
68
+ roofType: 'hip' | 'gable';
69
+ name: string;
70
+ /** The centre of its wall centre-line rectangle. */
71
+ centre: [number, number];
72
+ /** Along its ridge axis and across it, at the wall centre lines. */
73
+ width: number;
74
+ depth: number;
75
+ rotation: number;
76
+ /** Degrees. */
77
+ pitch: number;
78
+ /** Along the slope, as the node stores it. */
79
+ overhang: number;
80
+ /** In plan past the gable-end walls' outside faces; none on a hip. */
81
+ gableOverhang?: number;
82
+ wallThickness: number;
83
+ deckThickness: number;
84
+ shingleThickness: number;
85
+ /** The plate it bears on, metres above the storey's floor. */
86
+ eave: number;
87
+ };
88
+ export type RoofPlaneCase = {
89
+ name: string;
90
+ /** The walls under the roof: their outside faces and how tall they stand (none: posts). */
91
+ walls: {
92
+ rect: Rect;
93
+ height: number;
94
+ } | null;
95
+ call: RoofPlaneCall;
96
+ replacement: RoofSegmentAddCall;
97
+ segment: ExpectedRoofSegment;
98
+ /** How far the segment's surface stands over the planes' (0: the same roof). */
99
+ lift: number;
100
+ };
101
+ export declare const ROOF_PLANE_CASES: readonly RoofPlaneCase[];
102
+ export {};
103
+ //# sourceMappingURL=roof-plane-cases.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"roof-plane-cases.d.ts","sourceRoot":"","sources":["../../../../src/systems/roof/__fixtures__/roof-plane-cases.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AAEH,KAAK,IAAI,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAA;AAG5C,0FAA0F;AAC1F,eAAO,MAAM,yBAAyB,QAAW,CAAA;AACjD,8FAA8F;AAC9F,eAAO,MAAM,mBAAmB,OAAO,CAAA;AAMvC,MAAM,MAAM,aAAa,GAAG;IAC1B,IAAI,EAAE,iBAAiB,GAAG,mBAAmB,CAAA;IAC7C,IAAI,EAAE,IAAI,CAAA;IACV,SAAS,CAAC,EAAE,GAAG,GAAG,GAAG,CAAA;IACrB,mBAAmB;IACnB,KAAK,EAAE,MAAM,CAAA;IACb,oFAAoF;IACpF,UAAU,EAAE,MAAM,CAAA;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,IAAI,CAAC,EAAE,MAAM,CAAA;CACd,CAAA;AAED,MAAM,MAAM,kBAAkB,GAAG;IAC/B,QAAQ,EAAE,KAAK,GAAG,OAAO,CAAA;IACzB,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,IAAI,CAAA;IACV,MAAM,EAAE,SAAS,CAAA;IACjB,SAAS,EAAE,GAAG,GAAG,GAAG,CAAA;IACpB,aAAa,EAAE,MAAM,CAAA;IACrB,UAAU,EAAE,MAAM,CAAA;IAClB,eAAe,CAAC,EAAE,MAAM,CAAA;IACxB,WAAW,EAAE,MAAM,CAAA;IACnB,UAAU,CAAC,EAAE,MAAM,CAAA;CACpB,CAAA;AAED,8EAA8E;AAC9E,MAAM,MAAM,mBAAmB,GAAG;IAChC,QAAQ,EAAE,KAAK,GAAG,OAAO,CAAA;IACzB,IAAI,EAAE,MAAM,CAAA;IACZ,oDAAoD;IACpD,MAAM,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IACxB,oEAAoE;IACpE,KAAK,EAAE,MAAM,CAAA;IACb,KAAK,EAAE,MAAM,CAAA;IACb,QAAQ,EAAE,MAAM,CAAA;IAChB,eAAe;IACf,KAAK,EAAE,MAAM,CAAA;IACb,8CAA8C;IAC9C,QAAQ,EAAE,MAAM,CAAA;IAChB,sEAAsE;IACtE,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,aAAa,EAAE,MAAM,CAAA;IACrB,aAAa,EAAE,MAAM,CAAA;IACrB,gBAAgB,EAAE,MAAM,CAAA;IACxB,8DAA8D;IAC9D,IAAI,EAAE,MAAM,CAAA;CACb,CAAA;AAED,MAAM,MAAM,aAAa,GAAG;IAC1B,IAAI,EAAE,MAAM,CAAA;IACZ,2FAA2F;IAC3F,KAAK,EAAE;QAAE,IAAI,EAAE,IAAI,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAA;IAC5C,IAAI,EAAE,aAAa,CAAA;IACnB,WAAW,EAAE,kBAAkB,CAAA;IAC/B,OAAO,EAAE,mBAAmB,CAAA;IAC5B,gFAAgF;IAChF,IAAI,EAAE,MAAM,CAAA;CACb,CAAA;AA0ED,eAAO,MAAM,gBAAgB,EAAE,SAAS,aAAa,EAsRpD,CAAA"}