@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,7 +1,31 @@
1
1
  'use client';
2
2
  import { create } from 'zustand';
3
- import { persist } from 'zustand/middleware';
3
+ import { createJSONStorage, persist } from 'zustand/middleware';
4
4
  import { getSceneTheme, projectSceneTheme, SCENE_THEME_IDS, } from '../lib/scene-themes';
5
+ import { viewerPreferenceStorage } from '../lib/viewer-preference-storage';
6
+ const TIMES_OF_DAY = ['golden', 'midday', 'blue', 'night'];
7
+ const WEATHERS = ['clear', 'fair', 'cloudy', 'overcast'];
8
+ const RENDER_QUALITY_CHOICES = ['auto', 'low', 'medium', 'high'];
9
+ /** Until the renderer is up and the device detected: touch devices Medium, others High. */
10
+ function provisionalRenderQuality() {
11
+ if (typeof window === 'undefined' || !window.matchMedia)
12
+ return 'high';
13
+ return window.matchMedia('(pointer: coarse)').matches ? 'medium' : 'high';
14
+ }
15
+ function effectiveRenderQuality(choice, detected) {
16
+ return choice === 'auto' ? (detected ?? provisionalRenderQuality()) : choice;
17
+ }
18
+ function normalizeLatLng(value) {
19
+ if (!value || typeof value !== 'object')
20
+ return null;
21
+ const { lat, lng } = value;
22
+ return typeof lat === 'number' &&
23
+ typeof lng === 'number' &&
24
+ Number.isFinite(lat) &&
25
+ Number.isFinite(lng)
26
+ ? { lat, lng }
27
+ : null;
28
+ }
5
29
  const CAMERA_MODES = ['perspective', 'orthographic'];
6
30
  const RENDER_SHADINGS = ['solid', 'rendered'];
7
31
  const COLOR_PRESETS = ['clay', 'white', 'mono', 'blueprint'];
@@ -127,7 +151,7 @@ function normalizePersistedViewerState(value) {
127
151
  shadingByContext: normalizeShadingByContext(state.shadingByContext),
128
152
  textures: typeof state.textures === 'boolean' ? state.textures : true,
129
153
  colorPreset: pickString(state.colorPreset, COLOR_PRESETS, 'clay'),
130
- edges: pickString(state.edges, EDGE_MODES, 'soft'),
154
+ edges: state.edges === 'off' ? 'off' : 'soft',
131
155
  shadows: typeof state.shadows === 'boolean' ? state.shadows : true,
132
156
  unit: pickString(state.unit, UNITS, detectDefaultUnit()),
133
157
  metricNotation: pickString(state.metricNotation, METRIC_NOTATIONS, 'meters'),
@@ -135,8 +159,25 @@ function normalizePersistedViewerState(value) {
135
159
  levelMode: pickString(state.levelMode, LEVEL_MODES, 'stacked'),
136
160
  wallMode: pickString(state.wallMode, WALL_MODES, 'up'),
137
161
  projectPreferences: normalizeProjectPreferences(state.projectPreferences),
162
+ timeOfDay: pickString(state.timeOfDay, TIMES_OF_DAY, 'midday'),
163
+ timeOfDayMinutes: typeof state.timeOfDayMinutes === 'number' &&
164
+ state.timeOfDayMinutes >= 0 &&
165
+ state.timeOfDayMinutes <= 1440
166
+ ? state.timeOfDayMinutes
167
+ : null,
168
+ skyLive: state.skyLive === true,
169
+ weather: pickString(state.weather, WEATHERS, 'fair'),
170
+ deviceLocation: normalizeLatLng(state.deviceLocation),
171
+ // Solid shading was retired into the quality tiers: a saved Solid pick becomes Low.
172
+ renderQualityChoice: pickString(state.renderQuality, RENDER_QUALITY_CHOICES, persistedSolid(state) ? 'low' : 'auto'),
138
173
  };
139
174
  }
175
+ function persistedSolid(state) {
176
+ const byContext = state.shadingByContext;
177
+ return (!!byContext &&
178
+ typeof byContext === 'object' &&
179
+ Object.values(byContext).includes('solid'));
180
+ }
140
181
  /** The owner's pick (16 Oct): the section cut's clean edge over earth walls, and the simple fade. */
141
182
  export const DEFAULT_UNDERGROUND_LOOK = {
142
183
  edge: 'section-earth',
@@ -152,14 +193,16 @@ function resolveLook(state, patch) {
152
193
  savedSceneTheme: savedTheme,
153
194
  sceneTheme: theme.id,
154
195
  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,
196
+ // Solid (Lambert) shading is retired: the quality tiers replace it (Low is the cheap one).
197
+ shading: 'rendered',
198
+ // Edges are on (soft ink) or off; a saved 'strong' reads as on.
199
+ edges: onOffEdges(local?.edges ?? next.projectPresentation?.edges ?? next.lookDefaults.edges),
160
200
  shadows: local?.shadows ?? next.projectPresentation?.shadows ?? next.lookDefaults.shadows,
161
201
  };
162
202
  }
203
+ function onOffEdges(edges) {
204
+ return edges === 'off' ? 'off' : 'soft';
205
+ }
163
206
  function chooseLook(state, look) {
164
207
  const key = state.projectId ?? '';
165
208
  const previous = state.projectPreferences[key];
@@ -243,11 +286,17 @@ const useViewer = create()(persist((set) => ({
243
286
  setRenderPaused: (value) => set({ renderPaused: value }),
244
287
  shading: 'rendered',
245
288
  shadingByContext: {},
246
- setShading: (shading) => set((state) => chooseLook(state, {
247
- shadingByContext: {
248
- ...state.projectPreferences[state.projectId ?? '']?.look?.shadingByContext,
249
- [state.renderContext]: shading,
250
- },
289
+ // Solid is retired into the quality tiers: asking for it picks the Low tier.
290
+ setShading: (shading) => set((state) => ({
291
+ ...chooseLook(state, {
292
+ shadingByContext: {
293
+ ...state.projectPreferences[state.projectId ?? '']?.look?.shadingByContext,
294
+ [state.renderContext]: shading,
295
+ },
296
+ }),
297
+ ...(shading === 'solid'
298
+ ? { renderQuality: 'low', renderQualityChoice: 'low' }
299
+ : {}),
251
300
  })),
252
301
  textures: true,
253
302
  setTextures: (textures) => set({ textures }),
@@ -276,7 +325,6 @@ const useViewer = create()(persist((set) => ({
276
325
  hasLevelBelowGrade: false,
277
326
  diveAvailable: false,
278
327
  eyeUnderGround: false,
279
- pluginFoundationLevelIds: [],
280
328
  ambianceActive: false,
281
329
  undergroundLook: DEFAULT_UNDERGROUND_LOOK,
282
330
  setUndergroundLook: (look) => set((state) => ({ undergroundLook: { ...state.undergroundLook, ...look } })),
@@ -328,8 +376,37 @@ const useViewer = create()(persist((set) => ({
328
376
  }),
329
377
  showZones: true,
330
378
  setShowZones: (show) => set({ showZones: show }),
379
+ showCeilingTops: false,
380
+ setShowCeilingTops: (show) => set({ showCeilingTops: show }),
381
+ framingOnly: false,
382
+ setFramingOnly: (on) => set({ framingOnly: on }),
383
+ framingShown: false,
384
+ setFramingShown: (on) => set((state) => (state.framingShown === on ? state : { framingShown: on })),
331
385
  transparentBackground: false,
332
386
  setTransparentBackground: (transparent) => set({ transparentBackground: transparent }),
387
+ timeOfDay: 'midday',
388
+ setTimeOfDay: (timeOfDay) => set({ timeOfDay, timeOfDayMinutes: null, skyLive: false }),
389
+ timeOfDayMinutes: null,
390
+ setTimeOfDayMinutes: (timeOfDayMinutes) => set({ timeOfDayMinutes, skyLive: false }),
391
+ skyLive: false,
392
+ setSkyLive: (skyLive) => set({ skyLive }),
393
+ weather: 'fair',
394
+ setWeather: (weather) => set({ weather }),
395
+ deviceLocation: null,
396
+ setDeviceLocation: (deviceLocation) => set({ deviceLocation }),
397
+ renderQuality: provisionalRenderQuality(),
398
+ renderQualityChoice: 'auto',
399
+ detectedRenderQuality: null,
400
+ softwareRenderer: false,
401
+ setRenderQuality: (renderQualityChoice) => set((state) => ({
402
+ renderQualityChoice,
403
+ renderQuality: effectiveRenderQuality(renderQualityChoice, state.detectedRenderQuality),
404
+ })),
405
+ setDetectedRenderQuality: (detectedRenderQuality, softwareRenderer = false) => set((state) => ({
406
+ detectedRenderQuality,
407
+ softwareRenderer,
408
+ renderQuality: effectiveRenderQuality(state.renderQualityChoice, detectedRenderQuality),
409
+ })),
333
410
  inkOpacity: null,
334
411
  setInkOpacity: (opacity) => set({ inkOpacity: opacity }),
335
412
  projectId: null,
@@ -343,6 +420,8 @@ const useViewer = create()(persist((set) => ({
343
420
  projectPreferences,
344
421
  projectPresentation: undefined,
345
422
  previewSceneTheme: null,
423
+ framingOnly: false,
424
+ framingShown: false,
346
425
  showScans: prefs.showScans ?? true,
347
426
  showGuides: prefs.showGuides ?? true,
348
427
  showGrid: prefs.showGrid ?? true,
@@ -390,7 +469,11 @@ const useViewer = create()(persist((set) => ({
390
469
  debugColors: false,
391
470
  setDebugColors: (enabled) => set({ debugColors: enabled }),
392
471
  walkthroughMode: false,
393
- setWalkthroughMode: (mode) => set({ walkthroughMode: mode, walkthroughSuspended: false }),
472
+ setWalkthroughMode: (mode) => set(mode
473
+ ? { walkthroughMode: true, walkthroughSuspended: false }
474
+ : { walkthroughMode: false, walkthroughSuspended: false, walkthroughMovement: 'walk' }),
475
+ walkthroughMovement: 'walk',
476
+ setWalkthroughMovement: (movement) => set({ walkthroughMovement: movement }),
394
477
  walkthroughSuspended: false,
395
478
  setWalkthroughSuspended: (suspended) => set({ walkthroughSuspended: suspended }),
396
479
  cameraDragging: false,
@@ -399,11 +482,14 @@ const useViewer = create()(persist((set) => ({
399
482
  setInputDragging: (dragging) => set({ inputDragging: dragging }),
400
483
  }), {
401
484
  name: 'viewer-preferences',
485
+ storage: createJSONStorage(() => viewerPreferenceStorage),
402
486
  merge: (persistedState, currentState) => {
403
487
  const persisted = normalizePersistedViewerState(persistedState);
488
+ const renderQualityChoice = persisted.renderQualityChoice ?? currentState.renderQualityChoice;
404
489
  return {
405
490
  ...currentState,
406
491
  ...persisted,
492
+ renderQuality: effectiveRenderQuality(renderQualityChoice, currentState.detectedRenderQuality),
407
493
  ...resolveLook(currentState, {
408
494
  ...persisted,
409
495
  lookDefaults: {
@@ -427,6 +513,12 @@ const useViewer = create()(persist((set) => ({
427
513
  levelMode: state.levelMode,
428
514
  wallMode: state.wallMode,
429
515
  projectPreferences: Object.fromEntries(Object.entries(state.projectPreferences).filter(([key]) => key !== '')),
516
+ timeOfDay: state.timeOfDay,
517
+ timeOfDayMinutes: state.timeOfDayMinutes,
518
+ skyLive: state.skyLive,
519
+ weather: state.weather,
520
+ deviceLocation: state.deviceLocation,
521
+ renderQuality: state.renderQualityChoice,
430
522
  }),
431
523
  }));
432
524
  /**
@@ -441,11 +533,6 @@ export function groundVeiled(state) {
441
533
  state.gradeStanding !== 'partly-below-grade' &&
442
534
  state.walkthroughMode !== true);
443
535
  }
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
536
  /**
450
537
  * Whether the site draws its own ground. `showGround: false` says other geometry supplies the
451
538
  * 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"}