@pascal-app/viewer 1.0.5 → 1.0.7

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 (199) hide show
  1. package/dist/components/viewer/daylight-atmosphere.d.ts +9 -0
  2. package/dist/components/viewer/daylight-atmosphere.d.ts.map +1 -0
  3. package/dist/components/viewer/daylight-atmosphere.js +315 -0
  4. package/dist/components/viewer/drone-controller.d.ts +15 -0
  5. package/dist/components/viewer/drone-controller.d.ts.map +1 -0
  6. package/dist/components/viewer/drone-controller.js +194 -0
  7. package/dist/components/viewer/glb-interactive.d.ts +4 -18
  8. package/dist/components/viewer/glb-interactive.d.ts.map +1 -1
  9. package/dist/components/viewer/glb-interactive.js +32 -268
  10. package/dist/components/viewer/glb-scene-motion.d.ts +8 -0
  11. package/dist/components/viewer/glb-scene-motion.d.ts.map +1 -0
  12. package/dist/components/viewer/glb-scene-motion.js +57 -0
  13. package/dist/components/viewer/glb-scene.d.ts +3 -1
  14. package/dist/components/viewer/glb-scene.d.ts.map +1 -1
  15. package/dist/components/viewer/glb-scene.js +289 -49
  16. package/dist/components/viewer/glb-selection-callout.d.ts +17 -0
  17. package/dist/components/viewer/glb-selection-callout.d.ts.map +1 -0
  18. package/dist/components/viewer/glb-selection-callout.js +54 -0
  19. package/dist/components/viewer/glb-walkthrough-controller.d.ts.map +1 -1
  20. package/dist/components/viewer/glb-walkthrough-controller.js +6 -3
  21. package/dist/components/viewer/index.d.ts +5 -0
  22. package/dist/components/viewer/index.d.ts.map +1 -1
  23. package/dist/components/viewer/index.js +30 -6
  24. package/dist/components/viewer/lights.d.ts.map +1 -1
  25. package/dist/components/viewer/lights.js +192 -5
  26. package/dist/components/viewer/post-processing.d.ts.map +1 -1
  27. package/dist/components/viewer/post-processing.js +150 -94
  28. package/dist/components/viewer/scene-environment.js +4 -5
  29. package/dist/components/viewer/selection-callout.d.ts +51 -0
  30. package/dist/components/viewer/selection-callout.d.ts.map +1 -0
  31. package/dist/components/viewer/selection-callout.js +197 -0
  32. package/dist/components/viewer/use-daylight-rooms.d.ts +13 -0
  33. package/dist/components/viewer/use-daylight-rooms.d.ts.map +1 -0
  34. package/dist/components/viewer/use-daylight-rooms.js +236 -0
  35. package/dist/components/viewer/viewer-camera.d.ts.map +1 -1
  36. package/dist/components/viewer/viewer-camera.js +12 -1
  37. package/dist/index.d.ts +21 -7
  38. package/dist/index.d.ts.map +1 -1
  39. package/dist/index.js +23 -7
  40. package/dist/lib/daylight/ground.d.ts +21 -0
  41. package/dist/lib/daylight/ground.d.ts.map +1 -0
  42. package/dist/lib/daylight/ground.js +53 -0
  43. package/dist/lib/daylight/location.d.ts +32 -0
  44. package/dist/lib/daylight/location.d.ts.map +1 -0
  45. package/dist/lib/daylight/location.js +74 -0
  46. package/dist/lib/daylight/look.d.ts +33 -0
  47. package/dist/lib/daylight/look.d.ts.map +1 -0
  48. package/dist/lib/daylight/look.js +13 -0
  49. package/dist/lib/daylight/material-hooks.d.ts +2 -0
  50. package/dist/lib/daylight/material-hooks.d.ts.map +1 -0
  51. package/dist/lib/daylight/material-hooks.js +150 -0
  52. package/dist/lib/daylight/room-context.d.ts +12 -0
  53. package/dist/lib/daylight/room-context.d.ts.map +1 -0
  54. package/dist/lib/daylight/room-context.js +53 -0
  55. package/dist/lib/daylight/room-scene.d.ts +54 -0
  56. package/dist/lib/daylight/room-scene.d.ts.map +1 -0
  57. package/dist/lib/daylight/room-scene.js +356 -0
  58. package/dist/lib/daylight/rooms.d.ts +262 -0
  59. package/dist/lib/daylight/rooms.d.ts.map +1 -0
  60. package/dist/lib/daylight/rooms.js +1223 -0
  61. package/dist/lib/daylight/runtime.d.ts +33 -0
  62. package/dist/lib/daylight/runtime.d.ts.map +1 -0
  63. package/dist/lib/daylight/runtime.js +42 -0
  64. package/dist/lib/daylight/sky.d.ts +26 -0
  65. package/dist/lib/daylight/sky.d.ts.map +1 -0
  66. package/dist/lib/daylight/sky.js +217 -0
  67. package/dist/lib/daylight/solar.d.ts +46 -0
  68. package/dist/lib/daylight/solar.d.ts.map +1 -0
  69. package/dist/lib/daylight/solar.js +156 -0
  70. package/dist/lib/device-tier.d.ts +29 -0
  71. package/dist/lib/device-tier.d.ts.map +1 -0
  72. package/dist/lib/device-tier.js +71 -0
  73. package/dist/lib/dispose-object3d.d.ts.map +1 -1
  74. package/dist/lib/dispose-object3d.js +4 -2
  75. package/dist/lib/drone-flight.d.ts +44 -0
  76. package/dist/lib/drone-flight.d.ts.map +1 -0
  77. package/dist/lib/drone-flight.js +121 -0
  78. package/dist/lib/editor-highlight.d.ts +16 -0
  79. package/dist/lib/editor-highlight.d.ts.map +1 -0
  80. package/dist/lib/editor-highlight.js +33 -0
  81. package/dist/lib/foundation-materials.d.ts.map +1 -1
  82. package/dist/lib/foundation-materials.js +2 -4
  83. package/dist/lib/glb-merge.d.ts +23 -0
  84. package/dist/lib/glb-merge.d.ts.map +1 -0
  85. package/dist/lib/glb-merge.js +184 -0
  86. package/dist/lib/hardware-geometry.d.ts +21 -0
  87. package/dist/lib/hardware-geometry.d.ts.map +1 -0
  88. package/dist/lib/hardware-geometry.js +283 -0
  89. package/dist/lib/layer-pass.d.ts +2 -0
  90. package/dist/lib/layer-pass.d.ts.map +1 -1
  91. package/dist/lib/layer-pass.js +20 -0
  92. package/dist/lib/materials.d.ts.map +1 -1
  93. package/dist/lib/materials.js +50 -23
  94. package/dist/lib/merged-outline-node.d.ts.map +1 -1
  95. package/dist/lib/merged-outline-node.js +7 -1
  96. package/dist/lib/occlusion-culler.d.ts +34 -0
  97. package/dist/lib/occlusion-culler.d.ts.map +1 -0
  98. package/dist/lib/occlusion-culler.js +698 -0
  99. package/dist/lib/post-processing-resources.d.ts +4 -0
  100. package/dist/lib/post-processing-resources.d.ts.map +1 -1
  101. package/dist/lib/post-processing-resources.js +5 -0
  102. package/dist/lib/readback-rows.d.ts +14 -0
  103. package/dist/lib/readback-rows.d.ts.map +1 -0
  104. package/dist/lib/readback-rows.js +31 -0
  105. package/dist/lib/reveal-pose.d.ts.map +1 -1
  106. package/dist/lib/reveal-pose.js +3 -0
  107. package/dist/lib/scene-matrices.d.ts +12 -0
  108. package/dist/lib/scene-matrices.d.ts.map +1 -0
  109. package/dist/lib/scene-matrices.js +287 -0
  110. package/dist/lib/scene-pass-mrt.d.ts +5 -2
  111. package/dist/lib/scene-pass-mrt.d.ts.map +1 -1
  112. package/dist/lib/scene-pass-mrt.js +7 -2
  113. package/dist/lib/scene-themes.d.ts +0 -2
  114. package/dist/lib/scene-themes.d.ts.map +1 -1
  115. package/dist/lib/scene-themes.js +0 -2
  116. package/dist/lib/scene-visibility.d.ts +2 -0
  117. package/dist/lib/scene-visibility.d.ts.map +1 -1
  118. package/dist/lib/scene-visibility.js +12 -3
  119. package/dist/lib/site-surfaces.d.ts +1 -8
  120. package/dist/lib/site-surfaces.d.ts.map +1 -1
  121. package/dist/lib/site-surfaces.js +0 -19
  122. package/dist/lib/snapshot-pipeline.d.ts.map +1 -1
  123. package/dist/lib/snapshot-pipeline.js +24 -40
  124. package/dist/lib/texture-reference.d.ts.map +1 -1
  125. package/dist/lib/texture-reference.js +10 -8
  126. package/dist/lib/underground-ambiance.d.ts +0 -2
  127. package/dist/lib/underground-ambiance.d.ts.map +1 -1
  128. package/dist/lib/underground-ambiance.js +0 -2
  129. package/dist/store/use-item-light-pool.d.ts +3 -6
  130. package/dist/store/use-item-light-pool.d.ts.map +1 -1
  131. package/dist/store/use-item-light-pool.js +12 -0
  132. package/dist/store/use-viewer.d.ts +72 -15
  133. package/dist/store/use-viewer.d.ts.map +1 -1
  134. package/dist/store/use-viewer.js +103 -18
  135. package/dist/systems/ceiling/ceiling-system.d.ts +5 -0
  136. package/dist/systems/ceiling/ceiling-system.d.ts.map +1 -1
  137. package/dist/systems/ceiling/ceiling-system.js +11 -1
  138. package/dist/systems/door/door-system.d.ts.map +1 -1
  139. package/dist/systems/door/door-system.js +501 -145
  140. package/dist/systems/door/leaf-profile.d.ts +11 -0
  141. package/dist/systems/door/leaf-profile.d.ts.map +1 -0
  142. package/dist/systems/door/leaf-profile.js +140 -0
  143. package/dist/systems/interactive/callout-actions.d.ts +72 -0
  144. package/dist/systems/interactive/callout-actions.d.ts.map +1 -0
  145. package/dist/systems/interactive/callout-actions.js +212 -0
  146. package/dist/systems/interactive/interactive-system.d.ts +5 -1
  147. package/dist/systems/interactive/interactive-system.d.ts.map +1 -1
  148. package/dist/systems/interactive/interactive-system.js +44 -121
  149. package/dist/systems/interactive/opening-settled.d.ts +16 -0
  150. package/dist/systems/interactive/opening-settled.d.ts.map +1 -0
  151. package/dist/systems/interactive/opening-settled.js +53 -0
  152. package/dist/systems/item-light/item-light-system.d.ts.map +1 -1
  153. package/dist/systems/item-light/item-light-system.js +22 -214
  154. package/dist/systems/item-light/pooled-lights.d.ts +70 -0
  155. package/dist/systems/item-light/pooled-lights.d.ts.map +1 -0
  156. package/dist/systems/item-light/pooled-lights.js +449 -0
  157. package/dist/systems/level/level-system.d.ts.map +1 -1
  158. package/dist/systems/level/level-system.js +19 -1
  159. package/dist/systems/roof/roof-material-slots.d.ts +14 -0
  160. package/dist/systems/roof/roof-material-slots.d.ts.map +1 -0
  161. package/dist/systems/roof/roof-material-slots.js +13 -0
  162. package/dist/systems/roof/roof-materials.d.ts +25 -2
  163. package/dist/systems/roof/roof-materials.d.ts.map +1 -1
  164. package/dist/systems/roof/roof-materials.js +85 -26
  165. package/dist/systems/roof/roof-system.d.ts +34 -1
  166. package/dist/systems/roof/roof-system.d.ts.map +1 -1
  167. package/dist/systems/roof/roof-system.js +477 -105
  168. package/dist/systems/wall/opening-casing-geometry.d.ts +14 -0
  169. package/dist/systems/wall/opening-casing-geometry.d.ts.map +1 -0
  170. package/dist/systems/wall/opening-casing-geometry.js +102 -0
  171. package/dist/systems/wall/opening-cutout-geometry.d.ts +9 -0
  172. package/dist/systems/wall/opening-cutout-geometry.d.ts.map +1 -1
  173. package/dist/systems/wall/opening-cutout-geometry.js +7 -3
  174. package/dist/systems/wall/wall-materials.d.ts.map +1 -1
  175. package/dist/systems/wall/wall-materials.js +28 -35
  176. package/dist/systems/wall/wall-system.d.ts.map +1 -1
  177. package/dist/systems/wall/wall-system.js +34 -19
  178. package/dist/systems/wall/wall-t-junctions.d.ts +15 -0
  179. package/dist/systems/wall/wall-t-junctions.d.ts.map +1 -0
  180. package/dist/systems/wall/wall-t-junctions.js +149 -0
  181. package/dist/systems/window/window-animation-system.d.ts +3 -12
  182. package/dist/systems/window/window-animation-system.d.ts.map +1 -1
  183. package/dist/systems/window/window-animation-system.js +37 -122
  184. package/dist/systems/window/window-pose.d.ts +31 -0
  185. package/dist/systems/window/window-pose.d.ts.map +1 -0
  186. package/dist/systems/window/window-pose.js +152 -0
  187. package/dist/systems/window/window-roller-shutter.d.ts +8 -0
  188. package/dist/systems/window/window-roller-shutter.d.ts.map +1 -0
  189. package/dist/systems/window/window-roller-shutter.js +64 -0
  190. package/dist/systems/window/window-system.d.ts +2 -11
  191. package/dist/systems/window/window-system.d.ts.map +1 -1
  192. package/dist/systems/window/window-system.js +470 -303
  193. package/package.json +6 -6
  194. package/dist/systems/interactive/control-widget.d.ts +0 -10
  195. package/dist/systems/interactive/control-widget.d.ts.map +0 -1
  196. package/dist/systems/interactive/control-widget.js +0 -35
  197. package/dist/systems/interactive/procedural-controls.d.ts +0 -13
  198. package/dist/systems/interactive/procedural-controls.d.ts.map +0 -1
  199. package/dist/systems/interactive/procedural-controls.js +0 -17
@@ -2,6 +2,29 @@
2
2
  import { create } from 'zustand';
3
3
  import { persist } from 'zustand/middleware';
4
4
  import { getSceneTheme, projectSceneTheme, SCENE_THEME_IDS, } from '../lib/scene-themes';
5
+ const TIMES_OF_DAY = ['golden', 'midday', 'blue', 'night'];
6
+ const WEATHERS = ['clear', 'fair', 'cloudy', 'overcast'];
7
+ const RENDER_QUALITY_CHOICES = ['auto', 'low', 'medium', 'high'];
8
+ /** Until the renderer is up and the device detected: touch devices Medium, others High. */
9
+ function provisionalRenderQuality() {
10
+ if (typeof window === 'undefined' || !window.matchMedia)
11
+ return 'high';
12
+ return window.matchMedia('(pointer: coarse)').matches ? 'medium' : 'high';
13
+ }
14
+ function effectiveRenderQuality(choice, detected) {
15
+ return choice === 'auto' ? (detected ?? provisionalRenderQuality()) : choice;
16
+ }
17
+ function normalizeLatLng(value) {
18
+ if (!value || typeof value !== 'object')
19
+ return null;
20
+ const { lat, lng } = value;
21
+ return typeof lat === 'number' &&
22
+ typeof lng === 'number' &&
23
+ Number.isFinite(lat) &&
24
+ Number.isFinite(lng)
25
+ ? { lat, lng }
26
+ : null;
27
+ }
5
28
  const CAMERA_MODES = ['perspective', 'orthographic'];
6
29
  const RENDER_SHADINGS = ['solid', 'rendered'];
7
30
  const COLOR_PRESETS = ['clay', 'white', 'mono', 'blueprint'];
@@ -127,7 +150,7 @@ function normalizePersistedViewerState(value) {
127
150
  shadingByContext: normalizeShadingByContext(state.shadingByContext),
128
151
  textures: typeof state.textures === 'boolean' ? state.textures : true,
129
152
  colorPreset: pickString(state.colorPreset, COLOR_PRESETS, 'clay'),
130
- edges: pickString(state.edges, EDGE_MODES, 'soft'),
153
+ edges: state.edges === 'off' ? 'off' : 'soft',
131
154
  shadows: typeof state.shadows === 'boolean' ? state.shadows : true,
132
155
  unit: pickString(state.unit, UNITS, detectDefaultUnit()),
133
156
  metricNotation: pickString(state.metricNotation, METRIC_NOTATIONS, 'meters'),
@@ -135,8 +158,25 @@ function normalizePersistedViewerState(value) {
135
158
  levelMode: pickString(state.levelMode, LEVEL_MODES, 'stacked'),
136
159
  wallMode: pickString(state.wallMode, WALL_MODES, 'up'),
137
160
  projectPreferences: normalizeProjectPreferences(state.projectPreferences),
161
+ timeOfDay: pickString(state.timeOfDay, TIMES_OF_DAY, 'midday'),
162
+ timeOfDayMinutes: typeof state.timeOfDayMinutes === 'number' &&
163
+ state.timeOfDayMinutes >= 0 &&
164
+ state.timeOfDayMinutes <= 1440
165
+ ? state.timeOfDayMinutes
166
+ : null,
167
+ skyLive: state.skyLive === true,
168
+ weather: pickString(state.weather, WEATHERS, 'fair'),
169
+ deviceLocation: normalizeLatLng(state.deviceLocation),
170
+ // Solid shading was retired into the quality tiers: a saved Solid pick becomes Low.
171
+ renderQualityChoice: pickString(state.renderQuality, RENDER_QUALITY_CHOICES, persistedSolid(state) ? 'low' : 'auto'),
138
172
  };
139
173
  }
174
+ function persistedSolid(state) {
175
+ const byContext = state.shadingByContext;
176
+ return (!!byContext &&
177
+ typeof byContext === 'object' &&
178
+ Object.values(byContext).includes('solid'));
179
+ }
140
180
  /** The owner's pick (16 Oct): the section cut's clean edge over earth walls, and the simple fade. */
141
181
  export const DEFAULT_UNDERGROUND_LOOK = {
142
182
  edge: 'section-earth',
@@ -152,14 +192,16 @@ function resolveLook(state, patch) {
152
192
  savedSceneTheme: savedTheme,
153
193
  sceneTheme: theme.id,
154
194
  sceneAppearance: projectSceneTheme(theme, next.previewSceneTheme === null && !local?.theme ? next.projectPresentation : undefined),
155
- shading: local?.shadingByContext?.[next.renderContext] ??
156
- next.projectPresentation?.shading ??
157
- next.shadingByContext[next.renderContext] ??
158
- next.contextDefaultShading,
159
- edges: local?.edges ?? next.projectPresentation?.edges ?? next.lookDefaults.edges,
195
+ // Solid (Lambert) shading is retired: the quality tiers replace it (Low is the cheap one).
196
+ shading: 'rendered',
197
+ // Edges are on (soft ink) or off; a saved 'strong' reads as on.
198
+ edges: onOffEdges(local?.edges ?? next.projectPresentation?.edges ?? next.lookDefaults.edges),
160
199
  shadows: local?.shadows ?? next.projectPresentation?.shadows ?? next.lookDefaults.shadows,
161
200
  };
162
201
  }
202
+ function onOffEdges(edges) {
203
+ return edges === 'off' ? 'off' : 'soft';
204
+ }
163
205
  function chooseLook(state, look) {
164
206
  const key = state.projectId ?? '';
165
207
  const previous = state.projectPreferences[key];
@@ -243,11 +285,17 @@ const useViewer = create()(persist((set) => ({
243
285
  setRenderPaused: (value) => set({ renderPaused: value }),
244
286
  shading: 'rendered',
245
287
  shadingByContext: {},
246
- setShading: (shading) => set((state) => chooseLook(state, {
247
- shadingByContext: {
248
- ...state.projectPreferences[state.projectId ?? '']?.look?.shadingByContext,
249
- [state.renderContext]: shading,
250
- },
288
+ // Solid is retired into the quality tiers: asking for it picks the Low tier.
289
+ setShading: (shading) => set((state) => ({
290
+ ...chooseLook(state, {
291
+ shadingByContext: {
292
+ ...state.projectPreferences[state.projectId ?? '']?.look?.shadingByContext,
293
+ [state.renderContext]: shading,
294
+ },
295
+ }),
296
+ ...(shading === 'solid'
297
+ ? { renderQuality: 'low', renderQualityChoice: 'low' }
298
+ : {}),
251
299
  })),
252
300
  textures: true,
253
301
  setTextures: (textures) => set({ textures }),
@@ -276,7 +324,6 @@ const useViewer = create()(persist((set) => ({
276
324
  hasLevelBelowGrade: false,
277
325
  diveAvailable: false,
278
326
  eyeUnderGround: false,
279
- pluginFoundationLevelIds: [],
280
327
  ambianceActive: false,
281
328
  undergroundLook: DEFAULT_UNDERGROUND_LOOK,
282
329
  setUndergroundLook: (look) => set((state) => ({ undergroundLook: { ...state.undergroundLook, ...look } })),
@@ -328,8 +375,37 @@ const useViewer = create()(persist((set) => ({
328
375
  }),
329
376
  showZones: true,
330
377
  setShowZones: (show) => set({ showZones: show }),
378
+ showCeilingTops: false,
379
+ setShowCeilingTops: (show) => set({ showCeilingTops: show }),
380
+ framingOnly: false,
381
+ setFramingOnly: (on) => set({ framingOnly: on }),
382
+ framingShown: false,
383
+ setFramingShown: (on) => set((state) => (state.framingShown === on ? state : { framingShown: on })),
331
384
  transparentBackground: false,
332
385
  setTransparentBackground: (transparent) => set({ transparentBackground: transparent }),
386
+ timeOfDay: 'midday',
387
+ setTimeOfDay: (timeOfDay) => set({ timeOfDay, timeOfDayMinutes: null, skyLive: false }),
388
+ timeOfDayMinutes: null,
389
+ setTimeOfDayMinutes: (timeOfDayMinutes) => set({ timeOfDayMinutes, skyLive: false }),
390
+ skyLive: false,
391
+ setSkyLive: (skyLive) => set({ skyLive }),
392
+ weather: 'fair',
393
+ setWeather: (weather) => set({ weather }),
394
+ deviceLocation: null,
395
+ setDeviceLocation: (deviceLocation) => set({ deviceLocation }),
396
+ renderQuality: provisionalRenderQuality(),
397
+ renderQualityChoice: 'auto',
398
+ detectedRenderQuality: null,
399
+ softwareRenderer: false,
400
+ setRenderQuality: (renderQualityChoice) => set((state) => ({
401
+ renderQualityChoice,
402
+ renderQuality: effectiveRenderQuality(renderQualityChoice, state.detectedRenderQuality),
403
+ })),
404
+ setDetectedRenderQuality: (detectedRenderQuality, softwareRenderer = false) => set((state) => ({
405
+ detectedRenderQuality,
406
+ softwareRenderer,
407
+ renderQuality: effectiveRenderQuality(state.renderQualityChoice, detectedRenderQuality),
408
+ })),
333
409
  inkOpacity: null,
334
410
  setInkOpacity: (opacity) => set({ inkOpacity: opacity }),
335
411
  projectId: null,
@@ -343,6 +419,8 @@ const useViewer = create()(persist((set) => ({
343
419
  projectPreferences,
344
420
  projectPresentation: undefined,
345
421
  previewSceneTheme: null,
422
+ framingOnly: false,
423
+ framingShown: false,
346
424
  showScans: prefs.showScans ?? true,
347
425
  showGuides: prefs.showGuides ?? true,
348
426
  showGrid: prefs.showGrid ?? true,
@@ -390,7 +468,11 @@ const useViewer = create()(persist((set) => ({
390
468
  debugColors: false,
391
469
  setDebugColors: (enabled) => set({ debugColors: enabled }),
392
470
  walkthroughMode: false,
393
- setWalkthroughMode: (mode) => set({ walkthroughMode: mode, walkthroughSuspended: false }),
471
+ setWalkthroughMode: (mode) => set(mode
472
+ ? { walkthroughMode: true, walkthroughSuspended: false }
473
+ : { walkthroughMode: false, walkthroughSuspended: false, walkthroughMovement: 'walk' }),
474
+ walkthroughMovement: 'walk',
475
+ setWalkthroughMovement: (movement) => set({ walkthroughMovement: movement }),
394
476
  walkthroughSuspended: false,
395
477
  setWalkthroughSuspended: (suspended) => set({ walkthroughSuspended: suspended }),
396
478
  cameraDragging: false,
@@ -401,9 +483,11 @@ const useViewer = create()(persist((set) => ({
401
483
  name: 'viewer-preferences',
402
484
  merge: (persistedState, currentState) => {
403
485
  const persisted = normalizePersistedViewerState(persistedState);
486
+ const renderQualityChoice = persisted.renderQualityChoice ?? currentState.renderQualityChoice;
404
487
  return {
405
488
  ...currentState,
406
489
  ...persisted,
490
+ renderQuality: effectiveRenderQuality(renderQualityChoice, currentState.detectedRenderQuality),
407
491
  ...resolveLook(currentState, {
408
492
  ...persisted,
409
493
  lookDefaults: {
@@ -427,6 +511,12 @@ const useViewer = create()(persist((set) => ({
427
511
  levelMode: state.levelMode,
428
512
  wallMode: state.wallMode,
429
513
  projectPreferences: Object.fromEntries(Object.entries(state.projectPreferences).filter(([key]) => key !== '')),
514
+ timeOfDay: state.timeOfDay,
515
+ timeOfDayMinutes: state.timeOfDayMinutes,
516
+ skyLive: state.skyLive,
517
+ weather: state.weather,
518
+ deviceLocation: state.deviceLocation,
519
+ renderQuality: state.renderQualityChoice,
430
520
  }),
431
521
  }));
432
522
  /**
@@ -441,11 +531,6 @@ export function groundVeiled(state) {
441
531
  state.gradeStanding !== 'partly-below-grade' &&
442
532
  state.walkthroughMode !== true);
443
533
  }
444
- /** Whether any ground is veiled now, wholesale or through the eye's window. */
445
- export function anyGroundVeiled(state) {
446
- return (groundVeiled(state) ||
447
- (state.groundMode === 'auto' && state.groundWindowVeiled && state.walkthroughMode !== true));
448
- }
449
534
  /**
450
535
  * Whether the site draws its own ground. `showGround: false` says other geometry supplies the
451
536
  * ground (an authored landscape), which stands on a level above a basement; while a level below
@@ -2,6 +2,11 @@ import { type CeilingNode, type CeilingSurfaceCell, useScene } from '@pascal-app
2
2
  import * as THREE from 'three';
3
3
  /** Name of the meshes a ceiling draws its paint regions with, one per region. */
4
4
  export declare const CEILING_REGION_MESH = "ceiling-region";
5
+ /**
6
+ * Name of the mesh that draws a ceiling's upper face while `showCeilingTops` is on. It shares the
7
+ * grid's geometry, which covers the whole ceiling, and stands on top of the ceiling's build-up.
8
+ */
9
+ export declare const CEILING_CAP_MESH = "ceiling-cap";
5
10
  /**
6
11
  * The material a ceiling draws a region finish with. The ceiling's renderer
7
12
  * owns materials (theme, textures, scene materials) and leaves this on the
@@ -1 +1 @@
1
- {"version":3,"file":"ceiling-system.d.ts","sourceRoot":"","sources":["../../../src/systems/ceiling/ceiling-system.tsx"],"names":[],"mappings":"AAAA,OAAO,EAIL,KAAK,WAAW,EAChB,KAAK,kBAAkB,EAYvB,QAAQ,EACT,MAAM,kBAAkB,CAAA;AAEzB,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAI9B,iFAAiF;AACjF,eAAO,MAAM,mBAAmB,mBAAmB,CAAA;AAEnD;;;;GAIG;AACH,MAAM,MAAM,qBAAqB,GAAG,CAAC,MAAM,EAAE,kBAAkB,CAAC,QAAQ,CAAC,KAAK,KAAK,CAAC,QAAQ,CAAA;AAE5F,KAAK,UAAU,GAAG,UAAU,CAAC,OAAO,QAAQ,CAAC,QAAQ,CAAC,CAAC,OAAO,CAAC,CAAA;AAa/D,eAAO,MAAM,aAAa,YA4BzB,CAAA;AAsCD;;GAEG;AACH,wBAAgB,qBAAqB,CACnC,IAAI,EAAE,WAAW,EACjB,IAAI,EAAE,KAAK,CAAC,IAAI,EAChB,UAAU,GAAE,KAAK,CAAC,KAAK,CAAC,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAM,EAC/C,KAAK,GAAE,UAAsC,QA8C9C;AAuDD;;;;;;GAMG;AACH,wBAAgB,uBAAuB,CACrC,WAAW,EAAE,WAAW,EACxB,UAAU,GAAE,KAAK,CAAC,KAAK,CAAC,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAM,GAC9C,KAAK,CAAC,cAAc,CA6DtB"}
1
+ {"version":3,"file":"ceiling-system.d.ts","sourceRoot":"","sources":["../../../src/systems/ceiling/ceiling-system.tsx"],"names":[],"mappings":"AAAA,OAAO,EAIL,KAAK,WAAW,EAChB,KAAK,kBAAkB,EAavB,QAAQ,EACT,MAAM,kBAAkB,CAAA;AAEzB,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAI9B,iFAAiF;AACjF,eAAO,MAAM,mBAAmB,mBAAmB,CAAA;AAEnD;;;GAGG;AACH,eAAO,MAAM,gBAAgB,gBAAgB,CAAA;AAE7C;;;;GAIG;AACH,MAAM,MAAM,qBAAqB,GAAG,CAAC,MAAM,EAAE,kBAAkB,CAAC,QAAQ,CAAC,KAAK,KAAK,CAAC,QAAQ,CAAA;AAE5F,KAAK,UAAU,GAAG,UAAU,CAAC,OAAO,QAAQ,CAAC,QAAQ,CAAC,CAAC,OAAO,CAAC,CAAA;AAa/D,eAAO,MAAM,aAAa,YA4BzB,CAAA;AAsCD;;GAEG;AACH,wBAAgB,qBAAqB,CACnC,IAAI,EAAE,WAAW,EACjB,IAAI,EAAE,KAAK,CAAC,IAAI,EAChB,UAAU,GAAE,KAAK,CAAC,KAAK,CAAC,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAM,EAC/C,KAAK,GAAE,UAAsC,QAmD9C;AAuDD;;;;;;GAMG;AACH,wBAAgB,uBAAuB,CACrC,WAAW,EAAE,WAAW,EACxB,UAAU,GAAE,KAAK,CAAC,KAAK,CAAC,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAM,GAC9C,KAAK,CAAC,cAAc,CA6DtB"}
@@ -1,10 +1,15 @@
1
- import { CEILING_DRAW_OFFSET, CEILING_SURFACE_ROLE, ceilingPaintRegions, computeCeilingSurfaceCells, getEffectiveCutterNode, getEffectiveNode, hostedCutterHoles, isScriptedNode, nodeRegistry, resolveCeilingHeight, sceneRegistry, useLiveTransforms, useScene, } from '@pascal-app/core';
1
+ import { CEILING_DRAW_OFFSET, CEILING_SURFACE_ROLE, ceilingCapLift, ceilingPaintRegions, computeCeilingSurfaceCells, getEffectiveCutterNode, getEffectiveNode, hostedCutterHoles, isScriptedNode, nodeRegistry, resolveCeilingHeight, sceneRegistry, useLiveTransforms, useScene, } from '@pascal-app/core';
2
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
  import { mergeSurfaceHolePolygons } from '../surface-hole-geometry';
6
6
  /** Name of the meshes a ceiling draws its paint regions with, one per region. */
7
7
  export const CEILING_REGION_MESH = 'ceiling-region';
8
+ /**
9
+ * Name of the mesh that draws a ceiling's upper face while `showCeilingTops` is on. It shares the
10
+ * grid's geometry, which covers the whole ceiling, and stands on top of the ceiling's build-up.
11
+ */
12
+ export const CEILING_CAP_MESH = 'ceiling-cap';
8
13
  function ensureUv2Attribute(geometry) {
9
14
  const uv = geometry.getAttribute('uv');
10
15
  if (!uv)
@@ -96,6 +101,11 @@ export function updateCeilingGeometry(node, mesh, extraHoles = [], nodes = useSc
96
101
  if (gridMesh) {
97
102
  gridMesh.geometry.dispose();
98
103
  gridMesh.geometry = cells ? newGeo : newGeo.clone();
104
+ const capMesh = mesh.getObjectByName(CEILING_CAP_MESH);
105
+ if (capMesh) {
106
+ capMesh.geometry = gridMesh.geometry;
107
+ capMesh.position.y = ceilingCapLift(node, nodes);
108
+ }
99
109
  }
100
110
  else if (cells) {
101
111
  newGeo.dispose();
@@ -1 +1 @@
1
- {"version":3,"file":"door-system.d.ts","sourceRoot":"","sources":["../../../src/systems/door/door-system.tsx"],"names":[],"mappings":"AAAA,OAAO,EAIL,KAAK,QAAQ,EAcd,MAAM,kBAAkB,CAAA;AAGzB,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AA6D9B,eAAO,MAAM,UAAU,YAyHtB,CAAA;AAiqCD;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,mBAAmB,CACjC,IAAI,EAAE,QAAQ,EACd,IAAI,EAAE,KAAK,CAAC,QAAQ,GAAG,SAAS,EAChC,KAAK,EAAE,MAAM,GACZ,OAAO,CA6GT;AA6wCD;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,QAAQ,GAAG,KAAK,CAAC,IAAI,CAI/D"}
1
+ {"version":3,"file":"door-system.d.ts","sourceRoot":"","sources":["../../../src/systems/door/door-system.tsx"],"names":[],"mappings":"AAAA,OAAO,EAIL,KAAK,QAAQ,EAmBd,MAAM,kBAAkB,CAAA;AAIzB,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AA6E9B,eAAO,MAAM,UAAU,YAyHtB,CAAA;AAggDD;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,mBAAmB,CACjC,IAAI,EAAE,QAAQ,EACd,IAAI,EAAE,KAAK,CAAC,QAAQ,GAAG,SAAS,EAChC,KAAK,EAAE,MAAM,GACZ,OAAO,CAmHT;AAo3CD;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,QAAQ,GAAG,KAAK,CAAC,IAAI,CAI/D"}