@pascal-app/viewer 1.0.6 → 1.1.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 (238) hide show
  1. package/README.md +54 -21
  2. package/dist/components/viewer/daylight-atmosphere.d.ts +9 -0
  3. package/dist/components/viewer/daylight-atmosphere.d.ts.map +1 -0
  4. package/dist/components/viewer/daylight-atmosphere.js +315 -0
  5. package/dist/components/viewer/drone-controller.d.ts +15 -0
  6. package/dist/components/viewer/drone-controller.d.ts.map +1 -0
  7. package/dist/components/viewer/drone-controller.js +194 -0
  8. package/dist/components/viewer/glb-interactive.d.ts +4 -18
  9. package/dist/components/viewer/glb-interactive.d.ts.map +1 -1
  10. package/dist/components/viewer/glb-interactive.js +32 -268
  11. package/dist/components/viewer/glb-replace-instances.d.ts +6 -3
  12. package/dist/components/viewer/glb-replace-instances.d.ts.map +1 -1
  13. package/dist/components/viewer/glb-replace-instances.js +5 -4
  14. package/dist/components/viewer/glb-scene-motion.d.ts +8 -0
  15. package/dist/components/viewer/glb-scene-motion.d.ts.map +1 -0
  16. package/dist/components/viewer/glb-scene-motion.js +57 -0
  17. package/dist/components/viewer/glb-scene.d.ts +5 -1
  18. package/dist/components/viewer/glb-scene.d.ts.map +1 -1
  19. package/dist/components/viewer/glb-scene.js +290 -49
  20. package/dist/components/viewer/glb-selection-callout.d.ts +17 -0
  21. package/dist/components/viewer/glb-selection-callout.d.ts.map +1 -0
  22. package/dist/components/viewer/glb-selection-callout.js +54 -0
  23. package/dist/components/viewer/glb-walkthrough-controller.d.ts.map +1 -1
  24. package/dist/components/viewer/glb-walkthrough-controller.js +6 -3
  25. package/dist/components/viewer/index.d.ts +5 -0
  26. package/dist/components/viewer/index.d.ts.map +1 -1
  27. package/dist/components/viewer/index.js +38 -10
  28. package/dist/components/viewer/lights.d.ts.map +1 -1
  29. package/dist/components/viewer/lights.js +192 -5
  30. package/dist/components/viewer/post-processing.d.ts.map +1 -1
  31. package/dist/components/viewer/post-processing.js +150 -94
  32. package/dist/components/viewer/registered-systems.d.ts.map +1 -1
  33. package/dist/components/viewer/registered-systems.js +2 -2
  34. package/dist/components/viewer/scene-environment.js +4 -5
  35. package/dist/components/viewer/selection-callout.d.ts +51 -0
  36. package/dist/components/viewer/selection-callout.d.ts.map +1 -0
  37. package/dist/components/viewer/selection-callout.js +197 -0
  38. package/dist/components/viewer/unsupported-gpu-fallback.d.ts.map +1 -1
  39. package/dist/components/viewer/unsupported-gpu-fallback.js +21 -1
  40. package/dist/components/viewer/use-daylight-rooms.d.ts +13 -0
  41. package/dist/components/viewer/use-daylight-rooms.d.ts.map +1 -0
  42. package/dist/components/viewer/use-daylight-rooms.js +278 -0
  43. package/dist/components/viewer/viewer-camera.d.ts.map +1 -1
  44. package/dist/components/viewer/viewer-camera.js +12 -1
  45. package/dist/hooks/use-gltf-ktx2.d.ts.map +1 -1
  46. package/dist/hooks/use-gltf-ktx2.js +2 -1
  47. package/dist/index.d.ts +26 -8
  48. package/dist/index.d.ts.map +1 -1
  49. package/dist/index.js +28 -8
  50. package/dist/lib/asset-url.d.ts +0 -1
  51. package/dist/lib/asset-url.d.ts.map +1 -1
  52. package/dist/lib/asset-url.js +3 -3
  53. package/dist/lib/daylight/ground.d.ts +21 -0
  54. package/dist/lib/daylight/ground.d.ts.map +1 -0
  55. package/dist/lib/daylight/ground.js +53 -0
  56. package/dist/lib/daylight/location.d.ts +32 -0
  57. package/dist/lib/daylight/location.d.ts.map +1 -0
  58. package/dist/lib/daylight/location.js +74 -0
  59. package/dist/lib/daylight/look.d.ts +33 -0
  60. package/dist/lib/daylight/look.d.ts.map +1 -0
  61. package/dist/lib/daylight/look.js +13 -0
  62. package/dist/lib/daylight/material-hooks.d.ts +2 -0
  63. package/dist/lib/daylight/material-hooks.d.ts.map +1 -0
  64. package/dist/lib/daylight/material-hooks.js +150 -0
  65. package/dist/lib/daylight/room-context.d.ts +12 -0
  66. package/dist/lib/daylight/room-context.d.ts.map +1 -0
  67. package/dist/lib/daylight/room-context.js +54 -0
  68. package/dist/lib/daylight/room-map.d.ts +124 -0
  69. package/dist/lib/daylight/room-map.d.ts.map +1 -0
  70. package/dist/lib/daylight/room-map.js +630 -0
  71. package/dist/lib/daylight/room-scene.d.ts +56 -0
  72. package/dist/lib/daylight/room-scene.d.ts.map +1 -0
  73. package/dist/lib/daylight/room-scene.js +391 -0
  74. package/dist/lib/daylight/rooms.d.ts +292 -0
  75. package/dist/lib/daylight/rooms.d.ts.map +1 -0
  76. package/dist/lib/daylight/rooms.js +1268 -0
  77. package/dist/lib/daylight/runtime.d.ts +33 -0
  78. package/dist/lib/daylight/runtime.d.ts.map +1 -0
  79. package/dist/lib/daylight/runtime.js +42 -0
  80. package/dist/lib/daylight/sky.d.ts +26 -0
  81. package/dist/lib/daylight/sky.d.ts.map +1 -0
  82. package/dist/lib/daylight/sky.js +217 -0
  83. package/dist/lib/daylight/solar.d.ts +46 -0
  84. package/dist/lib/daylight/solar.d.ts.map +1 -0
  85. package/dist/lib/daylight/solar.js +156 -0
  86. package/dist/lib/device-tier.d.ts +29 -0
  87. package/dist/lib/device-tier.d.ts.map +1 -0
  88. package/dist/lib/device-tier.js +71 -0
  89. package/dist/lib/dispose-object3d.d.ts.map +1 -1
  90. package/dist/lib/dispose-object3d.js +4 -2
  91. package/dist/lib/drone-flight.d.ts +44 -0
  92. package/dist/lib/drone-flight.d.ts.map +1 -0
  93. package/dist/lib/drone-flight.js +121 -0
  94. package/dist/lib/editor-highlight.d.ts +16 -0
  95. package/dist/lib/editor-highlight.d.ts.map +1 -0
  96. package/dist/lib/editor-highlight.js +33 -0
  97. package/dist/lib/foundation-materials.d.ts.map +1 -1
  98. package/dist/lib/foundation-materials.js +2 -4
  99. package/dist/lib/glb-merge.d.ts +23 -0
  100. package/dist/lib/glb-merge.d.ts.map +1 -0
  101. package/dist/lib/glb-merge.js +184 -0
  102. package/dist/lib/hardware-geometry.d.ts +21 -0
  103. package/dist/lib/hardware-geometry.d.ts.map +1 -0
  104. package/dist/lib/hardware-geometry.js +283 -0
  105. package/dist/lib/ktx2-loader.d.ts.map +1 -1
  106. package/dist/lib/ktx2-loader.js +2 -1
  107. package/dist/lib/layer-pass.d.ts +2 -0
  108. package/dist/lib/layer-pass.d.ts.map +1 -1
  109. package/dist/lib/layer-pass.js +20 -0
  110. package/dist/lib/materials.d.ts.map +1 -1
  111. package/dist/lib/materials.js +50 -23
  112. package/dist/lib/measurement-label.d.ts +4 -0
  113. package/dist/lib/measurement-label.d.ts.map +1 -0
  114. package/dist/lib/measurement-label.js +54 -0
  115. package/dist/lib/measurement-presentation.d.ts +5 -0
  116. package/dist/lib/measurement-presentation.d.ts.map +1 -0
  117. package/dist/lib/measurement-presentation.js +8 -0
  118. package/dist/lib/merged-outline-node.d.ts.map +1 -1
  119. package/dist/lib/merged-outline-node.js +7 -1
  120. package/dist/lib/occlusion-culler.d.ts +34 -0
  121. package/dist/lib/occlusion-culler.d.ts.map +1 -0
  122. package/dist/lib/occlusion-culler.js +698 -0
  123. package/dist/lib/pointer-events.d.ts.map +1 -1
  124. package/dist/lib/pointer-events.js +3 -3
  125. package/dist/lib/post-processing-resources.d.ts +4 -0
  126. package/dist/lib/post-processing-resources.d.ts.map +1 -1
  127. package/dist/lib/post-processing-resources.js +5 -0
  128. package/dist/lib/readback-rows.d.ts +14 -0
  129. package/dist/lib/readback-rows.d.ts.map +1 -0
  130. package/dist/lib/readback-rows.js +31 -0
  131. package/dist/lib/reveal-pose.d.ts.map +1 -1
  132. package/dist/lib/reveal-pose.js +3 -0
  133. package/dist/lib/scene-matrices.d.ts +12 -0
  134. package/dist/lib/scene-matrices.d.ts.map +1 -0
  135. package/dist/lib/scene-matrices.js +287 -0
  136. package/dist/lib/scene-pass-mrt.d.ts +5 -2
  137. package/dist/lib/scene-pass-mrt.d.ts.map +1 -1
  138. package/dist/lib/scene-pass-mrt.js +7 -2
  139. package/dist/lib/scene-themes.d.ts +0 -2
  140. package/dist/lib/scene-themes.d.ts.map +1 -1
  141. package/dist/lib/scene-themes.js +0 -2
  142. package/dist/lib/scene-visibility.d.ts +2 -0
  143. package/dist/lib/scene-visibility.d.ts.map +1 -1
  144. package/dist/lib/scene-visibility.js +12 -3
  145. package/dist/lib/site-surfaces.d.ts +1 -8
  146. package/dist/lib/site-surfaces.d.ts.map +1 -1
  147. package/dist/lib/site-surfaces.js +0 -19
  148. package/dist/lib/snapshot-pipeline.d.ts.map +1 -1
  149. package/dist/lib/snapshot-pipeline.js +24 -40
  150. package/dist/lib/texture-reference.d.ts.map +1 -1
  151. package/dist/lib/texture-reference.js +13 -10
  152. package/dist/lib/underground-ambiance.d.ts +0 -2
  153. package/dist/lib/underground-ambiance.d.ts.map +1 -1
  154. package/dist/lib/underground-ambiance.js +0 -2
  155. package/dist/lib/viewer-config.d.ts +21 -0
  156. package/dist/lib/viewer-config.d.ts.map +1 -0
  157. package/dist/lib/viewer-config.js +21 -0
  158. package/dist/lib/viewer-preference-storage.d.ts +7 -0
  159. package/dist/lib/viewer-preference-storage.d.ts.map +1 -0
  160. package/dist/lib/viewer-preference-storage.js +23 -0
  161. package/dist/store/use-item-light-pool.d.ts +3 -6
  162. package/dist/store/use-item-light-pool.d.ts.map +1 -1
  163. package/dist/store/use-item-light-pool.js +12 -0
  164. package/dist/store/use-viewer.d.ts +62 -59
  165. package/dist/store/use-viewer.d.ts.map +1 -1
  166. package/dist/store/use-viewer.js +106 -19
  167. package/dist/systems/ceiling/ceiling-system.d.ts +5 -0
  168. package/dist/systems/ceiling/ceiling-system.d.ts.map +1 -1
  169. package/dist/systems/ceiling/ceiling-system.js +11 -1
  170. package/dist/systems/door/door-system.d.ts.map +1 -1
  171. package/dist/systems/door/door-system.js +501 -145
  172. package/dist/systems/door/leaf-profile.d.ts +11 -0
  173. package/dist/systems/door/leaf-profile.d.ts.map +1 -0
  174. package/dist/systems/door/leaf-profile.js +140 -0
  175. package/dist/systems/elevator/elevator-interaction-system.d.ts +16 -2
  176. package/dist/systems/elevator/elevator-interaction-system.d.ts.map +1 -1
  177. package/dist/systems/elevator/elevator-interaction-system.js +41 -8
  178. package/dist/systems/geometry/geometry-status.d.ts +8 -0
  179. package/dist/systems/geometry/geometry-status.d.ts.map +1 -0
  180. package/dist/systems/geometry/geometry-status.js +24 -0
  181. package/dist/systems/interactive/callout-actions.d.ts +72 -0
  182. package/dist/systems/interactive/callout-actions.d.ts.map +1 -0
  183. package/dist/systems/interactive/callout-actions.js +212 -0
  184. package/dist/systems/interactive/interactive-system.d.ts +5 -1
  185. package/dist/systems/interactive/interactive-system.d.ts.map +1 -1
  186. package/dist/systems/interactive/interactive-system.js +44 -121
  187. package/dist/systems/interactive/opening-settled.d.ts +16 -0
  188. package/dist/systems/interactive/opening-settled.d.ts.map +1 -0
  189. package/dist/systems/interactive/opening-settled.js +53 -0
  190. package/dist/systems/item-light/item-light-system.d.ts.map +1 -1
  191. package/dist/systems/item-light/item-light-system.js +22 -214
  192. package/dist/systems/item-light/pooled-lights.d.ts +70 -0
  193. package/dist/systems/item-light/pooled-lights.d.ts.map +1 -0
  194. package/dist/systems/item-light/pooled-lights.js +449 -0
  195. package/dist/systems/level/level-system.d.ts.map +1 -1
  196. package/dist/systems/level/level-system.js +19 -1
  197. package/dist/systems/roof/roof-material-slots.d.ts +14 -0
  198. package/dist/systems/roof/roof-material-slots.d.ts.map +1 -0
  199. package/dist/systems/roof/roof-material-slots.js +13 -0
  200. package/dist/systems/roof/roof-materials.d.ts +25 -2
  201. package/dist/systems/roof/roof-materials.d.ts.map +1 -1
  202. package/dist/systems/roof/roof-materials.js +85 -26
  203. package/dist/systems/roof/roof-system.d.ts +34 -1
  204. package/dist/systems/roof/roof-system.d.ts.map +1 -1
  205. package/dist/systems/roof/roof-system.js +582 -168
  206. package/dist/systems/wall/opening-casing-geometry.d.ts +14 -0
  207. package/dist/systems/wall/opening-casing-geometry.d.ts.map +1 -0
  208. package/dist/systems/wall/opening-casing-geometry.js +102 -0
  209. package/dist/systems/wall/opening-cutout-geometry.d.ts +9 -0
  210. package/dist/systems/wall/opening-cutout-geometry.d.ts.map +1 -1
  211. package/dist/systems/wall/opening-cutout-geometry.js +7 -3
  212. package/dist/systems/wall/wall-materials.d.ts.map +1 -1
  213. package/dist/systems/wall/wall-materials.js +28 -35
  214. package/dist/systems/wall/wall-system.d.ts +11 -0
  215. package/dist/systems/wall/wall-system.d.ts.map +1 -1
  216. package/dist/systems/wall/wall-system.js +86 -25
  217. package/dist/systems/wall/wall-t-junctions.d.ts +15 -0
  218. package/dist/systems/wall/wall-t-junctions.d.ts.map +1 -0
  219. package/dist/systems/wall/wall-t-junctions.js +149 -0
  220. package/dist/systems/window/window-animation-system.d.ts +3 -12
  221. package/dist/systems/window/window-animation-system.d.ts.map +1 -1
  222. package/dist/systems/window/window-animation-system.js +37 -122
  223. package/dist/systems/window/window-pose.d.ts +31 -0
  224. package/dist/systems/window/window-pose.d.ts.map +1 -0
  225. package/dist/systems/window/window-pose.js +152 -0
  226. package/dist/systems/window/window-roller-shutter.d.ts +8 -0
  227. package/dist/systems/window/window-roller-shutter.d.ts.map +1 -0
  228. package/dist/systems/window/window-roller-shutter.js +64 -0
  229. package/dist/systems/window/window-system.d.ts +2 -11
  230. package/dist/systems/window/window-system.d.ts.map +1 -1
  231. package/dist/systems/window/window-system.js +470 -303
  232. package/package.json +6 -6
  233. package/dist/systems/interactive/control-widget.d.ts +0 -10
  234. package/dist/systems/interactive/control-widget.d.ts.map +0 -1
  235. package/dist/systems/interactive/control-widget.js +0 -35
  236. package/dist/systems/interactive/procedural-controls.d.ts +0 -13
  237. package/dist/systems/interactive/procedural-controls.d.ts.map +0 -1
  238. package/dist/systems/interactive/procedural-controls.js +0 -17
@@ -1,9 +1,9 @@
1
- import { findLevelBelowId, getEffectiveRoofSurfaceMaterial, getLevelElevations, parseMaterialRef, wallAssemblyFinishRef, } from '@pascal-app/core';
1
+ import { findLevelBelowId, getEffectiveRoofSurfaceMaterial, getLevelElevations, getRoofWallBandMaterial, parseMaterialRef, wallAssemblyFinishRef, } from '@pascal-app/core';
2
2
  import { createMaterial, createSurfaceRoleMaterial, resolveMaterialRef, resolveSlotDefaultMaterial, } from '../../lib/materials';
3
3
  // Declared catalog defaults for an unpainted roof, per the 4-slot layout
4
4
  // (0 wall/trim · 1 deck · 2 interior soffit · 3 shingle top). The wall/trim
5
- // band mirrors the wall kind's default (WALL_SLOT_DEFAULT = concrete-drywall)
6
- // so a roof reads as continuous with the walls below it.
5
+ // band is bare drywall, the wall faces' default before they took the interior
6
+ // paint; over walls with a cladding it takes theirs (`levelWallCladdingRef`).
7
7
  const ROOF_DEFAULT_REFS = [
8
8
  'library:concrete-drywall',
9
9
  'library:preset-softwhite',
@@ -32,30 +32,12 @@ function createResolvedMaterial(material, materialPreset, sceneMaterials, shadin
32
32
  }
33
33
  return null;
34
34
  }
35
- /**
36
- * The cladding the walls under a roof declare through their ASSEMBLIES
37
- * (`wall.assembly.exterior.finish` → catalog ref), so the roof's gable band —
38
- * the triangle of wall above the plate that the roof kind builds — is skinned
39
- * like the walls it sits on instead of the bare drywall default. The walls are
40
- * the roof's level's, or for a roof on a level of its own (a building's roof
41
- * level), the storey's directly below. The most common ref among them wins;
42
- * null when none declares one.
43
- */
44
- export function levelWallCladdingRef(nodes, roof) {
45
- const levelId = roof.parentId;
46
- if (!levelId)
47
- return null;
48
- const wallsOn = (id) => Object.values(nodes).filter((node) => node?.type === 'wall' && node.parentId === id);
49
- const own = wallsOn(levelId);
50
- const walls = own.length
51
- ? own
52
- : wallsOn(findLevelBelowId(levelId, getLevelElevations(nodes)));
35
+ /** The most common ref, the first seen winning a tie; null when there is none. */
36
+ function mostCommonRef(refs) {
53
37
  const counts = new Map();
54
- for (const wall of walls) {
55
- const ref = wallAssemblyFinishRef(wall);
38
+ for (const ref of refs)
56
39
  if (ref)
57
40
  counts.set(ref, (counts.get(ref) ?? 0) + 1);
58
- }
59
41
  let best = null;
60
42
  let bestCount = 0;
61
43
  for (const [ref, count] of counts) {
@@ -66,18 +48,77 @@ export function levelWallCladdingRef(nodes, roof) {
66
48
  }
67
49
  return best;
68
50
  }
51
+ // Every roof and segment renderer reads these on each store change: one scan per
52
+ // level per nodes snapshot, shared by all of them.
53
+ const levelWallRefsCache = new WeakMap();
54
+ function levelWallRefs(nodes, levelId) {
55
+ let byLevel = levelWallRefsCache.get(nodes);
56
+ if (!byLevel) {
57
+ byLevel = new Map();
58
+ levelWallRefsCache.set(nodes, byLevel);
59
+ }
60
+ const cached = byLevel.get(levelId);
61
+ if (cached)
62
+ return cached;
63
+ const wallsOn = (id) => Object.values(nodes).filter((node) => node?.type === 'wall' && node.parentId === id);
64
+ const own = wallsOn(levelId);
65
+ const walls = own.length
66
+ ? own
67
+ : wallsOn(findLevelBelowId(levelId, getLevelElevations(nodes)));
68
+ const refs = {
69
+ cladding: mostCommonRef(walls.map((wall) => wallAssemblyFinishRef(wall))),
70
+ face: mostCommonRef(walls.map((wall) => {
71
+ // Face a is the front (+normal) side; an unresolved wall's exterior is face b.
72
+ const exterior = wall.frontSide === 'exterior' && wall.backSide !== 'exterior' ? 'a' : 'b';
73
+ const painted = wall.slots?.[exterior];
74
+ return typeof painted === 'string' ? painted : wallAssemblyFinishRef(wall);
75
+ })),
76
+ };
77
+ byLevel.set(levelId, refs);
78
+ return refs;
79
+ }
80
+ /**
81
+ * The cladding the walls under a roof declare through their ASSEMBLIES
82
+ * (`wall.assembly.exterior.finish` → catalog ref), so the roof's gable band —
83
+ * the triangle of wall above the plate that the roof kind builds — is skinned
84
+ * like the walls it sits on instead of the bare drywall default. The walls are
85
+ * the roof's level's, or for a roof on a level of its own (a building's roof
86
+ * level), the storey's directly below. The most common ref among them wins;
87
+ * null when none declares one.
88
+ */
89
+ export function levelWallCladdingRef(nodes, roof) {
90
+ return roof.parentId ? levelWallRefs(nodes, roof.parentId).cladding : null;
91
+ }
92
+ /**
93
+ * What the walls under a roof show outside, for the heel band — the strip of
94
+ * wall between their top plate and the eaves, which is wall, not trim: their
95
+ * exterior face's paint, else the cladding their assembly declares
96
+ * (`levelWallCladdingRef`'s walls). The most common wins; null when none has
97
+ * either.
98
+ */
99
+ export function levelWallFaceRef(nodes, roof) {
100
+ return roof.parentId ? levelWallRefs(nodes, roof.parentId).face : null;
101
+ }
69
102
  export function getRoofMaterialArray(node, shading = 'rendered', textures = true, colorPreset = 'clay', sceneTheme,
70
103
  /** Catalog ref for the gable/trim band when unpainted — see `levelWallCladdingRef`. */
71
- wallCladdingRef = null, sceneMaterials) {
104
+ wallCladdingRef = null, sceneMaterials,
105
+ /** Catalog ref for the heel band when unpainted — see `levelWallFaceRef`. */
106
+ wallFaceRef = null) {
72
107
  const top = getEffectiveRoofSurfaceMaterial(node, 'top');
73
108
  const edge = getEffectiveRoofSurfaceMaterial(node, 'edge');
74
109
  const wall = getEffectiveRoofSurfaceMaterial(node, 'wall');
110
+ const heel = getRoofWallBandMaterial(node, 'heel') ?? {
111
+ material: undefined,
112
+ materialPreset: undefined,
113
+ };
75
114
  const cacheKey = JSON.stringify({
76
115
  shading,
77
116
  textures,
78
117
  colorPreset,
79
118
  sceneTheme,
80
119
  wallCladdingRef,
120
+ wallFaceRef,
121
+ heel: getSurfaceMaterialSignature(heel, sceneMaterials),
81
122
  top: getSurfaceMaterialSignature(top, sceneMaterials),
82
123
  edge: getSurfaceMaterialSignature(edge, sceneMaterials),
83
124
  wall: getSurfaceMaterialSignature(wall, sceneMaterials),
@@ -95,6 +136,10 @@ wallCladdingRef = null, sceneMaterials) {
95
136
  ceilingMaterial,
96
137
  ceilingMaterial,
97
138
  roofMaterial,
139
+ // The bands drew in the wall/trim slot before they had slots of their own.
140
+ roofMaterial,
141
+ roofMaterial,
142
+ roofMaterial,
98
143
  ];
99
144
  // Textures-off (monochrome) is the guaranteed escape hatch: themed role
100
145
  // colours, no catalog finishes.
@@ -106,6 +151,7 @@ wallCladdingRef = null, sceneMaterials) {
106
151
  const topMaterial = resolve(top);
107
152
  const edgeMaterial = resolve(edge);
108
153
  const wallMaterial = resolve(wall);
154
+ const heelMaterial = resolve(heel);
109
155
  // Each slot resolves to its own role only, then the declared default — never
110
156
  // another role. Cross-role fallback here used to splatter a single painted
111
157
  // surface (e.g. the edge) across the shingle and soffit slots. The legacy
@@ -113,11 +159,24 @@ wallCladdingRef = null, sceneMaterials) {
113
159
  // returns it for top/edge/wall alike.
114
160
  // Resolve an unpainted slot's catalog default lazily: painted roofs must
115
161
  // not load unused finish assets (or make capture readiness depend on them).
162
+ const trimDefaultRef = wallCladdingRef ?? ROOF_DEFAULT_REFS[0];
163
+ const trim = edgeMaterial ?? resolveSlotDefaultMaterial(trimDefaultRef, shading);
164
+ // The heel band is wall: unpainted, it follows the walls below, never the gable / fascia
165
+ // trim. A roof with no edge paint over walls with no face paint draws it exactly as it did
166
+ // when the band was part of the wall/trim slot — the very same material.
167
+ const heelDefaultRef = wallFaceRef ?? trimDefaultRef;
168
+ const heelSlot = heelMaterial ??
169
+ (!edgeMaterial && heelDefaultRef === trimDefaultRef
170
+ ? trim
171
+ : resolveSlotDefaultMaterial(heelDefaultRef, shading));
116
172
  const materialArray = [
117
- edgeMaterial ?? resolveSlotDefaultMaterial(wallCladdingRef ?? ROOF_DEFAULT_REFS[0], shading),
173
+ trim,
118
174
  wallMaterial ?? resolveSlotDefaultMaterial(ROOF_DEFAULT_REFS[1], shading),
119
175
  wallMaterial ?? resolveSlotDefaultMaterial(ROOF_DEFAULT_REFS[2], shading),
120
176
  topMaterial ?? resolveSlotDefaultMaterial(ROOF_DEFAULT_REFS[3], shading),
177
+ heelSlot,
178
+ trim,
179
+ trim,
121
180
  ];
122
181
  roofMaterialArrayCache.set(cacheKey, materialArray);
123
182
  return materialArray;
@@ -49,15 +49,48 @@ export declare function mapRoofGroupMaterialIndex(groupMaterialIndex: number | u
49
49
  * same trim, in the same segment-local frame.
50
50
  */
51
51
  export declare function clipGeometryBySegmentTrim(geometry: THREE.BufferGeometry | null, segment: RoofSegmentNode): THREE.BufferGeometry | null;
52
+ /**
53
+ * How deep a roof plane's deck opens under its sheathing while the viewer shows the frame
54
+ * (`useViewer.framingShown`), square to the slope: the structure its layers name
55
+ * (`roofStructureDepth`: its rafters, or its trusses' top chords on their heel), else Bones' default
56
+ * 2x6. A deck no deeper keeps its top 7/16 in; a plane finished underneath (a cathedral ceiling)
57
+ * stays closed, the frame hidden behind its finish, and so does a form `FRAMING_OPEN_ROOF_TYPES`
58
+ * leaves out. 0 when nothing opens.
59
+ */
60
+ export declare function roofFramingDepth(node: RoofSegmentNode): number;
52
61
  /**
53
62
  * `fascia`: build the segment's fascia boards into its deck. Only the roof
54
63
  * renderer asks; a dormer, a chimney or a sibling's clip takes the bare shell.
64
+ * `framing`: the structure band to open (`roofFramingDepth`), the roof
65
+ * renderer's while the frame is shown. Inside the walls the deck keeps only the
66
+ * band over it, so the rafters show from the attic; over the walls and in the
67
+ * overhangs it stays whole, closing the band at the walls' inner faces.
55
68
  */
56
69
  export declare function getRoofSegmentBrushes(node: RoofSegmentNode, options?: {
57
70
  fascia?: boolean;
71
+ framing?: number;
58
72
  }): RoofSegmentBrushSet | null;
59
- export declare function generateRoofSegmentGeometry(node: RoofSegmentNode, nodes?: Record<string, AnyNode>): THREE.BufferGeometry;
73
+ /**
74
+ * `framing`: the frame is shown (`useViewer.framingShown`), so the deck opens its structure band
75
+ * (`roofFramingDepth`). Only the roof system asks; a picture of the plan or a section takes the
76
+ * closed deck.
77
+ */
78
+ export declare function generateRoofSegmentGeometry(node: RoofSegmentNode, nodes?: Record<string, AnyNode>, options?: {
79
+ framing?: boolean;
80
+ }): THREE.BufferGeometry;
60
81
  export declare function clipDirectRoofGeometryAgainstSiblings(geometry: THREE.BufferGeometry, node: RoofSegmentNode, nodes: Record<string, AnyNode>, space: 'roof' | 'segment'): THREE.BufferGeometry;
82
+ type WallBandSegment = {
83
+ node: RoofSegmentNode;
84
+ /** Geometry space → segment-local (identity for a segment's own mesh). */
85
+ inverse: THREE.Matrix4 | null;
86
+ };
87
+ /**
88
+ * Split the wall bands off slot 0 (see `ROOF_HEEL_MATERIAL_INDEX`): the heel
89
+ * band always, each gable end when `gables` (a segment's own mesh, where they
90
+ * paint apart; on the merged shell they stay the edge role's). Runs on the
91
+ * finished shell, after every slot remap that folds indices back into 0–3.
92
+ */
93
+ export declare function splitRoofWallBandFaces(geometry: THREE.BufferGeometry, segments: readonly WallBandSegment[], gables: boolean): void;
61
94
  export declare function remapRoofShellFaces(geometry: THREE.BufferGeometry, node: RoofSegmentNode): void;
62
95
  export type SurfaceFrame = {
63
96
  point: THREE.Vector3;
@@ -1 +1 @@
1
- {"version":3,"file":"roof-system.d.ts","sourceRoot":"","sources":["../../../src/systems/roof/roof-system.tsx"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,OAAO,EA6BZ,KAAK,eAAe,EAQrB,MAAM,kBAAkB,CAAA;AAEzB,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAE9B,OAAO,EAAY,KAAK,EAA0B,MAAM,eAAe,CAAA;AA4JvE;;;;;GAKG;AACH,wBAAgB,wBAAwB,IAAI,MAAM,CAIjD;AAED,wBAAgB,sBAAsB,CACpC,OAAO,EAAE,QAAQ,CAAC,MAAM,CAAC,EACzB,OAAO,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,KAAK,CAAC,QAAQ,GAAG,SAAS,GAClD,MAAM,CAIR;AAiFD,0EAA0E;AAC1E,MAAM,MAAM,mBAAmB,GAAG;IAChC,YAAY,EAAE,CAAC,IAAI,EAAE,eAAe,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,KAAK,IAAI,CAAA;CAChE,CAAA;AAED,eAAO,MAAM,UAAU,yBAAyB;IAAE,eAAe,CAAC,EAAE,mBAAmB,CAAA;CAAE,SA0JxF,CAAA;AAqbD;;;;;;;GAOG;AACH,eAAO,MAAM,gBAAgB,EAAE;IAC7B,KAAK,CAAC,iBAAiB;IACvB,KAAK,CAAC,iBAAiB;IACvB,KAAK,CAAC,iBAAiB;IACvB,KAAK,CAAC,iBAAiB;CAMxB,CAAA;AAID,eAAO,MAAM,wBAAwB,IAAI,CAAA;AAEzC,KAAK,mBAAmB,GAAG;IACzB,QAAQ,EAAE,KAAK,CAAA;IACf,QAAQ,EAAE,KAAK,CAAA;IACf,SAAS,EAAE,KAAK,CAAA;IAChB,UAAU,EAAE,KAAK,CAAA;IACjB,UAAU,EAAE,KAAK,CAAC,cAAc,GAAG,IAAI,CAAA;CACxC,CAAA;AA4FD,wBAAgB,yBAAyB,CACvC,kBAAkB,EAAE,MAAM,GAAG,SAAS,EACtC,YAAY,EAAE,KAAK,CAAC,QAAQ,EAAE,EAC9B,UAAU,EAAE,GAAG,CAAC,KAAK,CAAC,QAAQ,EAAE,MAAM,CAAC,GACtC,MAAM,CAuBR;AA4XD;;;;;;;;GAQG;AACH,wBAAgB,yBAAyB,CACvC,QAAQ,EAAE,KAAK,CAAC,cAAc,GAAG,IAAI,EACrC,OAAO,EAAE,eAAe,GACvB,KAAK,CAAC,cAAc,GAAG,IAAI,CAgC7B;AAuHD;;;GAGG;AACH,wBAAgB,qBAAqB,CACnC,IAAI,EAAE,eAAe,EACrB,OAAO,GAAE;IAAE,MAAM,CAAC,EAAE,OAAO,CAAA;CAAO,GACjC,mBAAmB,GAAG,IAAI,CA4V5B;AAkFD,wBAAgB,2BAA2B,CACzC,IAAI,EAAE,eAAe,EACrB,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC9B,KAAK,CAAC,cAAc,CA8GtB;AAED,wBAAgB,qCAAqC,CACnD,QAAQ,EAAE,KAAK,CAAC,cAAc,EAC9B,IAAI,EAAE,eAAe,EACrB,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC9B,KAAK,EAAE,MAAM,GAAG,SAAS,GACxB,KAAK,CAAC,cAAc,CAiCtB;AA+vCD,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,KAAK,CAAC,cAAc,EAAE,IAAI,EAAE,eAAe,QA0ExF;AAirBD,MAAM,MAAM,YAAY,GAAG;IACzB,KAAK,EAAE,KAAK,CAAC,OAAO,CAAA;IACpB,MAAM,EAAE,KAAK,CAAC,OAAO,CAAA;CACtB,CAAA;AAED;;;;GAIG;AACH,wBAAgB,+BAA+B,CAC7C,OAAO,EAAE,eAAe,EACxB,EAAE,EAAE,MAAM,EACV,EAAE,EAAE,MAAM,GACT,YAAY,CA+Ld"}
1
+ {"version":3,"file":"roof-system.d.ts","sourceRoot":"","sources":["../../../src/systems/roof/roof-system.tsx"],"names":[],"mappings":"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"}