@preference-sl/pref-viewer 2.16.0-beta.10 → 2.16.0-beta.12

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.
@@ -19,20 +19,20 @@ import { PrefViewer2DStyles } from "./styles.js";
19
19
  * - visible: "true" | "false" (controls visibility and event subscription)
20
20
  *
21
21
  * Public methods
22
- * - async load(svgConfig) : Promise<boolean> — accept SVG input/config and prepare for render
22
+ * - async load(svgConfig) : Promise<{success: boolean, error: Error|null}> — accept SVG input/config and prepare for render
23
23
  * - show(), hide() — toggle visibility and event subscriptions
24
24
  * - zoomIn(), zoomOut(), zoomCenter(), zoomExtentsAll() — pan/zoom controls
25
25
  *
26
- * * Public Properties:
26
+ * Public Properties:
27
27
  * - isInitialized: Indicates whether the component has completed initialization.
28
28
  * - isLoaded: Indicates whether the SVG content is loaded and ready.
29
29
  * - isVisible: Indicates whether the component is currently visible.
30
30
  *
31
31
  * Events
32
- * - "drawing-loading": emitted before loading starts
33
- * - "drawing-loaded": emitted after content and Panzoom are ready
34
- * - "drawing-error": emitted on validation/fetch errors (detail.error: Error)
35
- * - "drawing-zoom-changed": emitted when pan/zoom state changes (detail: { moved, scaled, maximized, minimized })
32
+ * - "pref-viewer-2d-loading": emitted before loading starts. Legacy alias: "drawing-loading"
33
+ * - "pref-viewer-2d-loaded": emitted after content and Panzoom are ready. Legacy alias: "drawing-loaded"
34
+ * - "pref-viewer-2d-error": emitted on validation/fetch errors (detail.error: Error). Legacy alias: "drawing-error"
35
+ * - "pref-viewer-2d-viewport-changed": emitted when pan/zoom state changes (detail: { moved, scaled, maximized, minimized })
36
36
  *
37
37
  * Implementation notes
38
38
  * - Keeps internal state in private fields (#svg, #panzoom, #panzoomOptions, ...).
@@ -235,7 +235,8 @@ export default class PrefViewer2D extends HTMLElement {
235
235
  composed: false, // indicates whether or not the event will propagate across the shadow DOM boundary into the standard DOM
236
236
  detail: detail,
237
237
  };
238
- this.dispatchEvent(new CustomEvent("drawing-error", customEventOptions));
238
+ this.dispatchEvent(new CustomEvent("pref-viewer-2d-error", customEventOptions));
239
+ this.dispatchEvent(new CustomEvent("drawing-error", customEventOptions)); // Legacy alias for backward compatibility
239
240
  return detail;
240
241
  }
241
242
 
@@ -250,7 +251,8 @@ export default class PrefViewer2D extends HTMLElement {
250
251
  cancelable: true,
251
252
  composed: false,
252
253
  };
253
- this.dispatchEvent(new CustomEvent("drawing-loaded", customEventOptions));
254
+ this.dispatchEvent(new CustomEvent("pref-viewer-2d-loaded", customEventOptions));
255
+ this.dispatchEvent(new CustomEvent("drawing-loaded", customEventOptions)); // Legacy alias for backward compatibility
254
256
 
255
257
  this.removeAttribute("loading");
256
258
  this.setAttribute("loaded", "");
@@ -270,7 +272,8 @@ export default class PrefViewer2D extends HTMLElement {
270
272
  cancelable: true,
271
273
  composed: false,
272
274
  };
273
- this.dispatchEvent(new CustomEvent("drawing-loading", customEventOptions));
275
+ this.dispatchEvent(new CustomEvent("pref-viewer-2d-loading", customEventOptions));
276
+ this.dispatchEvent(new CustomEvent("drawing-loading", customEventOptions)); // Legacy alias for backward compatibility
274
277
 
275
278
  this.removeAttribute("loaded");
276
279
  this.setAttribute("loading", "");
@@ -283,7 +286,7 @@ export default class PrefViewer2D extends HTMLElement {
283
286
  }
284
287
 
285
288
  /**
286
- * Handles Panzoom state changes by dispatching a "prefviewer2d-zoomchanged" custom event.
289
+ * Handles Panzoom state changes by dispatching the public "pref-viewer-2d-viewport-changed" event.
287
290
  * @private
288
291
  * @param {object} state - The current Panzoom state object.
289
292
  * @returns {void}
@@ -299,17 +302,7 @@ export default class PrefViewer2D extends HTMLElement {
299
302
  detail: state,
300
303
  };
301
304
  customEventOptions.detail.desde2d = "true";
302
- this.dispatchEvent(new CustomEvent("drawing-zoom-changed", customEventOptions));
303
- }
304
-
305
- /**
306
- * Subscribe DOM events required by Panzoom and keyboard interactions.
307
- * @private
308
- * @returns {void}
309
- composed: true,
310
- detail: state,
311
- })
312
- );
305
+ this.dispatchEvent(new CustomEvent("pref-viewer-2d-viewport-changed", customEventOptions));
313
306
  }
314
307
 
315
308
  /**
@@ -25,9 +25,6 @@ import FileStorage from "./file-storage.js";
25
25
  * - show-model: Show or hide the 3D model ("true"/"false").
26
26
  * - show-scene: Show or hide the 3D environment ("true"/"false").
27
27
  * - visible: Show or hide the entire viewer ("true"/"false").
28
- * - show-animation-menu: Show or hide animation controls in the 3D controller.
29
- * - highlight-color: Hex color used for hover highlight on animated meshes.
30
- * - highlight-enabled: Enable or disable hover highlight ("true"/"false").
31
28
  *
32
29
  * Public Methods:
33
30
  * - show(): Shows the 3D viewer component.
@@ -40,6 +37,13 @@ import FileStorage from "./file-storage.js";
40
37
  * - hideModel(): Hides the 3D model.
41
38
  * - showEnvironment(): Shows the 3D environment/scene.
42
39
  * - hideEnvironment(): Hides the 3D environment/scene.
40
+ * - isIBLAvailable(): Reports whether a valid IBL environment map is currently available.
41
+ * - isAnimationMenuEnabled(): Reports whether the animation control menu is currently enabled.
42
+ * - getDebugInfo(): Returns a diagnostic snapshot of the underlying Babylon.js runtime.
43
+ * - getAnimations(): Returns a snapshot of all available animations and their current state.
44
+ * - playAnimation(name, action): Controls a named animation by applying the specified action.
45
+ * - setAnimationProgress(name, progress): Seeks a named animation to a normalized progress position (0–1).
46
+ * - setAnimationLoop(name, loop): Enables or disables loop mode for a named animation.
43
47
  * - downloadModelGLB(): Downloads the current 3D model as a GLB file.
44
48
  * - downloadModelGLTF(): Downloads the current 3D model as a glTF ZIP file.
45
49
  * - downloadModelUSDZ(): Downloads the current 3D model as a USDZ file.
@@ -60,14 +64,16 @@ import FileStorage from "./file-storage.js";
60
64
  * - #checkNeedToUpdateCamera(options): Detects camera option changes and marks them pending.
61
65
  * - #checkNeedToUpdateMaterials(options): Resolves material overrides that require updates.
62
66
  * - #checkNeedToUpdateIBL(options): Fetches HDR URLs/timestamps and enqueues IBL updates when needed.
67
+ * - #checkNeedToUpdateLighting(options): Resolves time-of-day changes and marks lighting as pending.
63
68
  * - #resetUpdateFlags(): Clears pending/success flags after loads or option-setting flows.
64
69
  * - #onLoading/#onLoaded/#onSettingOptions/#onSetOptions(): Dispatch lifecycle events and synchronize attributes.
65
70
  *
66
71
  * Events:
67
- * - "scene-loading": Dispatched when a loading operation starts.
68
- * - "scene-loaded": Dispatched when a loading operation completes.
69
- * - "scene-setting-options": Dispatched when viewer options are being set.
70
- * - "scene-set-options": Dispatched when viewer options have been set.
72
+ * - "pref-viewer-3d-loading": Dispatched when a loading operation starts. Legacy alias: "scene-loading".
73
+ * - "pref-viewer-3d-loaded": Dispatched when a loading operation completes. Legacy alias: "scene-loaded".
74
+ * - "pref-viewer-3d-options-applying": Dispatched when viewer options are being set. Legacy alias: "scene-setting-options".
75
+ * - "pref-viewer-3d-options-applied": Dispatched when viewer options have been set. Legacy alias: "scene-set-options".
76
+ * - "pref-viewer-3d-animation-changed": Dispatched by OpeningAnimation instances via the pref-viewer-3d host when an animation state, progress, or loop value changes.
71
77
  *
72
78
  * Notes:
73
79
  * - Internal state and heavy initialization are handled in connectedCallback.
@@ -101,7 +107,7 @@ export default class PrefViewer3D extends HTMLElement {
101
107
  * @returns {string[]} Array of attribute names that trigger attributeChangedCallback.
102
108
  */
103
109
  static get observedAttributes() {
104
- return ["show-model", "show-scene", "visible", "show-animation-menu", "highlight-color", "highlight-enabled"];
110
+ return ["show-model", "show-scene", "visible"];
105
111
  }
106
112
 
107
113
  /**
@@ -114,7 +120,6 @@ export default class PrefViewer3D extends HTMLElement {
114
120
  * - "show-model": shows or hides the model according to the attribute value ("true"/"false").
115
121
  * - "show-scene": shows or hides the scene according to the attribute value ("true"/"false").
116
122
  * - "visible": shows or hides the component according to the attribute value ("true"/"false").
117
- * - "show-animation-menu", "highlight-color", and "highlight-enabled": forward runtime UI/highlight settings to BabylonJSController.
118
123
  */
119
124
  attributeChangedCallback(name, _old, value) {
120
125
  switch (name) {
@@ -142,18 +147,6 @@ export default class PrefViewer3D extends HTMLElement {
142
147
  this.hide();
143
148
  }
144
149
  break;
145
- case "show-animation-menu":
146
- case "highlight-color":
147
- case "highlight-enabled":
148
- // Pass these to BabylonJSController if initialized
149
- if (this.#babylonJSController && typeof this.#babylonJSController.setIlluminationConfig === "function") {
150
- this.#babylonJSController.setIlluminationConfig({
151
- showAnimationMenu: this.getAttribute("show-animation-menu"),
152
- highlightColor: this.getAttribute("highlight-color"),
153
- highlightEnabled: this.getAttribute("highlight-enabled"),
154
- });
155
- }
156
- break;
157
150
  }
158
151
  }
159
152
 
@@ -234,8 +227,10 @@ export default class PrefViewer3D extends HTMLElement {
234
227
  outerFloor: new MaterialData("outerFloor", undefined, undefined, ["outerFloor"]),
235
228
  },
236
229
  ibl: new IBLData(),
237
- lighting: {
238
- timeOfDay: 0.5,
230
+ render: {
231
+ showAnimationMenu: false,
232
+ lightingTimeOfDay: 0.5,
233
+ showLightingTimeOfDay: false,
239
234
  },
240
235
  },
241
236
  };
@@ -250,15 +245,6 @@ export default class PrefViewer3D extends HTMLElement {
250
245
  this.#babylonJSController = new BabylonJSController(this.#canvas, this.#data.containers, this.#data.options);
251
246
  this.#babylonJSController.enable();
252
247
 
253
- // Apply highlight attributes that were set before the controller was ready
254
- const highlightColor = this.getAttribute("highlight-color");
255
- const highlightEnabled = this.getAttribute("highlight-enabled");
256
- if (highlightColor !== null || highlightEnabled !== null) {
257
- this.#babylonJSController.setIlluminationConfig({
258
- highlightColor: highlightColor ?? undefined,
259
- highlightEnabled: highlightEnabled ?? undefined,
260
- });
261
- }
262
248
  }
263
249
 
264
250
  /**
@@ -430,29 +416,37 @@ export default class PrefViewer3D extends HTMLElement {
430
416
  iblState.setValues(url, cachedUrl, intensity, shadows, timeStamp);
431
417
  }
432
418
  }
433
-
419
+
434
420
  return needUpdate;
435
421
  }
436
422
 
437
423
  /**
438
- * Resolves incoming lighting settings (time-of-day slider) and marks the option as pending when changed.
439
- * Supports both nested `options.lighting.timeOfDay` and flat `options.lightingTimeOfDay` payloads so the menu
440
- * and external API can share the same controller path.
424
+ * Checks whether any lighting-related value in `options.render` differs from the cached state.
425
+ * `options.render.showLightingTimeOfDay` updates slider visibility, while
426
+ * `options.render.lightingTimeOfDay` updates the normalized 0..1 lighting value.
441
427
  * @private
442
- * @param {object} options - Options payload containing lighting state.
443
- * @returns {boolean} True when lighting differs from the cached state, otherwise false.
428
+ * @param {object} options - Options payload containing a `render` sub-object.
429
+ * @param {boolean|string} [options.render.showLightingTimeOfDay] - Whether the time-of-day slider should be visible.
430
+ * @param {number} [options.render.lightingTimeOfDay] - Desired time-of-day, normalized to 0..1.
431
+ * @returns {boolean} True when either the visibility flag or the time value differs from the cached state.
444
432
  */
445
433
  #checkNeedToUpdateLighting(options) {
446
434
  if (!options) {
447
435
  return false;
448
436
  }
449
437
 
450
- const lightingState = this.#data.options.lighting;
451
- const incomingTime = typeof options.lightingTimeOfDay === "number"
452
- ? options.lightingTimeOfDay
453
- : typeof options.lighting?.timeOfDay === "number"
454
- ? options.lighting.timeOfDay
455
- : undefined;
438
+ const incomingTimeEnabled = options.render?.showLightingTimeOfDay;
439
+ if (incomingTimeEnabled !== undefined) {
440
+ const dataTimeEnabled = this.#data.options.render.showLightingTimeOfDay;
441
+ const needUpdate = dataTimeEnabled !== incomingTimeEnabled;
442
+ this.#data.options.render.showLightingTimeOfDay = incomingTimeEnabled;
443
+ if (needUpdate) {
444
+ return true;
445
+ }
446
+ }
447
+
448
+ const dataTime = this.#data.options.render.lightingTimeOfDay;
449
+ const incomingTime = typeof options.render?.lightingTimeOfDay === "number" ? options.render.lightingTimeOfDay : undefined;
456
450
 
457
451
  if (!Number.isFinite(incomingTime)) {
458
452
  return false;
@@ -460,9 +454,9 @@ export default class PrefViewer3D extends HTMLElement {
460
454
 
461
455
  const normalizedTime = Math.min(1, Math.max(0, incomingTime));
462
456
  const controllerTime = this.#babylonJSController?.getRenderSettings?.()?.lightingTimeOfDay;
463
- const currentTime = Number.isFinite(controllerTime) ? controllerTime : lightingState.timeOfDay;
457
+ const currentTime = Number.isFinite(controllerTime) ? controllerTime : dataTime;
464
458
  const needUpdate = normalizedTime !== currentTime;
465
- lightingState.timeOfDay = normalizedTime;
459
+ this.#data.options.render.lightingTimeOfDay = normalizedTime;
466
460
  return needUpdate;
467
461
  }
468
462
 
@@ -477,8 +471,10 @@ export default class PrefViewer3D extends HTMLElement {
477
471
  bubbles: true, // indicates whether the event bubbles up through the DOM tree or not
478
472
  cancelable: true, // indicates whether the event can be canceled, and therefore prevented as if the event never happened
479
473
  composed: false, // indicates whether or not the event will propagate across the shadow DOM boundary into the standard DOM
474
+
480
475
  };
481
- this.dispatchEvent(new CustomEvent("scene-loading", customEventOptions));
476
+ this.dispatchEvent(new CustomEvent("pref-viewer-3d-loading", customEventOptions));
477
+ this.dispatchEvent(new CustomEvent("scene-loading", customEventOptions)); // Legacy alias for backward compatibility
482
478
 
483
479
  this.removeAttribute("loaded");
484
480
  this.setAttribute("loading", "");
@@ -526,7 +522,8 @@ export default class PrefViewer3D extends HTMLElement {
526
522
  composed: false,
527
523
  detail: detail,
528
524
  };
529
- this.dispatchEvent(new CustomEvent("scene-loaded", customEventOptions));
525
+ this.dispatchEvent(new CustomEvent("pref-viewer-3d-loaded", customEventOptions));
526
+ this.dispatchEvent(new CustomEvent("scene-loaded", customEventOptions)); // Legacy alias for backward compatibility
530
527
 
531
528
  this.removeAttribute("loading");
532
529
  this.setAttribute("loaded", "");
@@ -549,7 +546,8 @@ export default class PrefViewer3D extends HTMLElement {
549
546
  cancelable: true,
550
547
  composed: false,
551
548
  };
552
- this.dispatchEvent(new CustomEvent("scene-setting-options", customEventOptions));
549
+ this.dispatchEvent(new CustomEvent("pref-viewer-3d-options-applying", customEventOptions));
550
+ this.dispatchEvent(new CustomEvent("scene-setting-options", customEventOptions)); // Legacy alias for backward compatibility
553
551
 
554
552
  this.removeAttribute("loaded");
555
553
  this.setAttribute("loading", "");
@@ -591,7 +589,8 @@ export default class PrefViewer3D extends HTMLElement {
591
589
  composed: false,
592
590
  detail: detail,
593
591
  };
594
- this.dispatchEvent(new CustomEvent("scene-set-options", customEventOptions));
592
+ this.dispatchEvent(new CustomEvent("pref-viewer-3d-options-applied", customEventOptions));
593
+ this.dispatchEvent(new CustomEvent("scene-set-options", customEventOptions)); // Legacy alias for backward compatibility
595
594
 
596
595
  this.removeAttribute("loading");
597
596
  this.setAttribute("loaded", "");
@@ -648,10 +647,15 @@ export default class PrefViewer3D extends HTMLElement {
648
647
  this.#checkNeedToUpdateContainers(config);
649
648
 
650
649
  // Options
651
- let needUpdateLighting = false;
652
650
  const iblOptions = config.scene?.ibl
653
- ? { ...(config.options ?? {}), ibl: { ...(config.options?.ibl ?? {}), ...config.scene.ibl } }
654
- : config.options;
651
+ ? { ...(config.options ?? {}), ibl: { ...(config.options?.ibl ?? {}), ...config.scene.ibl } }
652
+ : config.options;
653
+
654
+ if (iblOptions) {
655
+ await this.#checkNeedToUpdateIBL(iblOptions);
656
+ }
657
+
658
+ let needUpdateLighting = false;
655
659
 
656
660
  if (config.options) {
657
661
  this.#checkNeedToUpdateCamera(config.options);
@@ -659,16 +663,15 @@ export default class PrefViewer3D extends HTMLElement {
659
663
  needUpdateLighting = this.#checkNeedToUpdateLighting(config.options);
660
664
  }
661
665
 
662
- if (iblOptions) {
663
- await this.#checkNeedToUpdateIBL(iblOptions);
664
- }
665
-
666
- const loadDetail = await this.#babylonJSController.load(forceReload);
667
-
668
666
  if (needUpdateLighting && typeof this.#babylonJSController.setIlluminationConfig === "function") {
669
- this.#babylonJSController.setIlluminationConfig({
670
- lightingTimeOfDay: this.#data.options.lighting.timeOfDay,
671
- });
667
+ const lightingConfig = {};
668
+ if (config.options?.render?.lightingTimeOfDay !== undefined) {
669
+ lightingConfig.lightingTimeOfDay = config.options.render.lightingTimeOfDay;
670
+ }
671
+ if (config.options?.render?.showLightingTimeOfDay !== undefined) {
672
+ lightingConfig.showLightingTimeOfDay = config.options.render.showLightingTimeOfDay;
673
+ }
674
+ this.#babylonJSController.setIlluminationConfig(lightingConfig);
672
675
  }
673
676
 
674
677
  // Apply initial render settings if provided in options
@@ -676,6 +679,8 @@ export default class PrefViewer3D extends HTMLElement {
676
679
  await this.applyRenderSettings(config.options.render);
677
680
  }
678
681
 
682
+ const loadDetail = await this.#babylonJSController.load(forceReload);
683
+
679
684
  return { ...loadDetail, load: this.#onLoaded() };
680
685
  }
681
686
 
@@ -706,17 +711,22 @@ export default class PrefViewer3D extends HTMLElement {
706
711
  }
707
712
  const needUpdateLighting = this.#checkNeedToUpdateLighting(options);
708
713
  if (needUpdateLighting && typeof this.#babylonJSController.setIlluminationConfig === "function") {
709
- this.#babylonJSController.setIlluminationConfig({
710
- lightingTimeOfDay: this.#data.options.lighting.timeOfDay,
711
- });
714
+ const lightingConfig = {};
715
+ if (options.render?.lightingTimeOfDay !== undefined) {
716
+ lightingConfig.lightingTimeOfDay = options.render.lightingTimeOfDay;
717
+ }
718
+ if (options.render?.showLightingTimeOfDay !== undefined) {
719
+ lightingConfig.showLightingTimeOfDay = options.render.showLightingTimeOfDay;
720
+ }
721
+ this.#babylonJSController.setIlluminationConfig(lightingConfig);
712
722
  someSetted = true;
713
723
  }
714
-
724
+
715
725
  // Apply render settings if provided
716
726
  if (options.render) {
717
727
  await this.applyRenderSettings(options.render);
718
728
  }
719
-
729
+
720
730
  const detail = this.#onSetOptions();
721
731
  return { success: someSetted, detail: detail };
722
732
  }
@@ -949,6 +959,38 @@ export default class PrefViewer3D extends HTMLElement {
949
959
  return typeof cachedUrl === "string" ? cachedUrl.length > 0 : Boolean(cachedUrl);
950
960
  }
951
961
 
962
+ /**
963
+ * Reports whether the animation control menu is currently enabled.
964
+ * @public
965
+ * @returns {boolean} True when the animation menu option is active; otherwise false.
966
+ */
967
+ isAnimationMenuEnabled() {
968
+ const renderSettings = this.getRenderSettings?.() ?? null;
969
+ if (renderSettings?.showAnimationMenu !== undefined) {
970
+ return renderSettings.showAnimationMenu === true;
971
+ }
972
+ return false;
973
+ }
974
+
975
+ /**
976
+ * Reports whether the lighting time-of-day control should be visible and interactive.
977
+ * Requires both `showLightingTimeOfDay === true` and a finite `lightingTimeOfDay` value.
978
+ * @public
979
+ * @returns {boolean} True when the time-of-day slider is explicitly visible and has a valid value; otherwise false.
980
+ */
981
+ isLightingTimeOfDayAvailable() {
982
+ const renderSettings = this.getRenderSettings?.() ?? null;
983
+ return renderSettings?.showLightingTimeOfDay === true && Number.isFinite(renderSettings.lightingTimeOfDay);
984
+ }
985
+
986
+ /**
987
+ * Returns a diagnostic snapshot of the underlying Babylon.js runtime.
988
+ * @public
989
+ * @returns {object|null} Debug information, or null when the controller is not initialized.
990
+ */
991
+ getDebugInfo() {
992
+ return this.#babylonJSController?.getDebugInfo?.() ?? null;
993
+ }
952
994
  /**
953
995
  * Applies render settings received from PrefViewerMenu3D or another UI.
954
996
  * Highlight and time-of-day lighting values are pushed directly to BabylonJSController; AA/SSAO/IBL/shadow changes
@@ -959,8 +1001,10 @@ export default class PrefViewer3D extends HTMLElement {
959
1001
  * @param {boolean} [settings.ambientOcclusionEnabled] - Enables or disables SSAO.
960
1002
  * @param {boolean} [settings.iblEnabled] - Enables or disables image-based lighting.
961
1003
  * @param {boolean} [settings.shadowsEnabled] - Enables or disables scene shadows.
1004
+ * @param {boolean|string} [settings.showAnimationMenu] - Enables/disables the animation controls when animations are available.
962
1005
  * @param {boolean|string} [settings.highlightEnabled] - Enables or disables hover highlight; string "false" is normalized to false.
963
1006
  * @param {string} [settings.highlightColor] - Hex color used for hover highlight.
1007
+ * @param {boolean|string} [settings.showLightingTimeOfDay] - Shows/hides the lighting time-of-day control.
964
1008
  * @param {number} [settings.lightingTimeOfDay] - Normalized 0..1 time-of-day value.
965
1009
  * @param {boolean} [settings.persist=true] - False for transient lighting updates such as playback frames.
966
1010
  * @returns {Promise<{changed: boolean, success: boolean, detail?: object, controller?: object}>} Resolves with the apply/reload summary.
@@ -970,30 +1014,41 @@ export default class PrefViewer3D extends HTMLElement {
970
1014
  return { changed: false, success: false };
971
1015
  }
972
1016
 
973
- // Handle highlight settings separately for immediate effect without reload
974
- if (settings.highlightEnabled !== undefined || settings.highlightColor !== undefined) {
975
- if (typeof this.#babylonJSController.setIlluminationConfig === "function") {
976
- // Convert string "false" to boolean false
977
- const highlightEnabled = settings.highlightEnabled === "false" ? false : settings.highlightEnabled;
978
- this.#babylonJSController.setIlluminationConfig({
979
- highlightEnabled: highlightEnabled,
980
- highlightColor: settings.highlightColor,
981
- });
982
- }
1017
+ const illuminationSettings = {};
1018
+ if (settings.showAnimationMenu !== undefined) {
1019
+ illuminationSettings.showAnimationMenu = settings.showAnimationMenu;
983
1020
  }
984
-
985
- // Exclude highlight settings from the reload — they are handled above without requiring a scene reload
986
- if (settings.lightingTimeOfDay !== undefined && typeof this.#babylonJSController.setIlluminationConfig === "function") {
1021
+ if (settings.highlightEnabled !== undefined) {
1022
+ illuminationSettings.highlightEnabled = settings.highlightEnabled;
1023
+ }
1024
+ if (settings.highlightColor !== undefined) {
1025
+ illuminationSettings.highlightColor = settings.highlightColor;
1026
+ }
1027
+ if (settings.showLightingTimeOfDay !== undefined) {
1028
+ illuminationSettings.showLightingTimeOfDay = settings.showLightingTimeOfDay;
1029
+ }
1030
+ if (settings.lightingTimeOfDay !== undefined) {
987
1031
  const lightingTimeOfDay = Number(settings.lightingTimeOfDay);
988
1032
  if (Number.isFinite(lightingTimeOfDay)) {
989
- this.#babylonJSController.setIlluminationConfig({
990
- lightingTimeOfDay,
991
- persist: settings.persist !== false,
992
- });
1033
+ illuminationSettings.lightingTimeOfDay = lightingTimeOfDay;
993
1034
  }
994
1035
  }
1036
+ if (settings.persist !== undefined) {
1037
+ illuminationSettings.persist = settings.persist;
1038
+ }
1039
+ if (Object.keys(illuminationSettings).length > 0 && typeof this.#babylonJSController.setIlluminationConfig === "function") {
1040
+ this.#babylonJSController.setIlluminationConfig(illuminationSettings);
1041
+ }
995
1042
 
996
- const { highlightEnabled: _he, highlightColor: _hc, lightingTimeOfDay: _lt, lighting: _lighting, persist: _persist, ...reloadSettings } = settings;
1043
+ const {
1044
+ showAnimationMenu: _sam,
1045
+ highlightEnabled: _he,
1046
+ highlightColor: _hc,
1047
+ showLightingTimeOfDay: _slt,
1048
+ lightingTimeOfDay: _lt,
1049
+ persist: _persist,
1050
+ ...reloadSettings
1051
+ } = settings;
997
1052
  const scheduled = this.#babylonJSController.scheduleRenderSettingsReload(reloadSettings);
998
1053
  if (!scheduled.changed) {
999
1054
  return { changed: false, success: true };