@preference-sl/pref-viewer 2.16.2 → 2.17.0-beta.1
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.
- package/README.md +184 -22
- package/index.d.ts +11 -1
- package/package.json +1 -1
- package/src/babylonjs-animation-controller.js +12 -163
- package/src/babylonjs-animation-opening-menu.js +8 -1
- package/src/babylonjs-animation-opening.js +21 -1
- package/src/babylonjs-animation-overlay-controller.js +145 -0
- package/src/babylonjs-camera-framing.js +171 -0
- package/src/babylonjs-camera-zoom-controller.js +272 -0
- package/src/babylonjs-controller.js +640 -378
- package/src/babylonjs-selection-controller.js +215 -0
- package/src/babylonjs-view-cube-controller.js +810 -0
- package/src/file-storage.js +13 -0
- package/src/gltf-storage.js +97 -0
- package/src/localization/i18n.js +147 -74
- package/src/localization/translations.js +18 -0
- package/src/material-utils.js +67 -60
- package/src/panzoom-controller.js +14 -1
- package/src/pref-viewer-2d.js +16 -4
- package/src/pref-viewer-3d-data.js +166 -0
- package/src/pref-viewer-3d.js +40 -5
- package/src/pref-viewer-dialog.js +7 -1
- package/src/pref-viewer-menu-3d.js +57 -37
- package/src/pref-viewer.js +155 -44
- package/src/render-math.js +130 -117
- package/src/styles.js +94 -3
- package/src/svg-resolver.js +5 -4
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { PrefViewerMenu3DStyles } from "./styles.js";
|
|
2
2
|
import BabylonJSController from "./babylonjs-controller.js";
|
|
3
|
-
import
|
|
3
|
+
import I18n from "./localization/i18n.js";
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* PrefViewerMenu3D - Localized floating control panel for Babylon.js render settings.
|
|
@@ -55,15 +55,16 @@ export default class PrefViewerMenu3D extends HTMLElement {
|
|
|
55
55
|
onColorSliderInput: null,
|
|
56
56
|
onLightingSliderInput: null,
|
|
57
57
|
onLightingPlayClick: null,
|
|
58
|
+
onLightingTick: null,
|
|
58
59
|
onHostLeave: null,
|
|
59
60
|
onPanelEnter: null,
|
|
60
61
|
onSwitchChange: null,
|
|
61
62
|
onToggleEnter: null,
|
|
62
63
|
};
|
|
63
64
|
|
|
64
|
-
#DEFAULT_RENDER_SETTINGS = { ...BabylonJSController.
|
|
65
|
+
#DEFAULT_RENDER_SETTINGS = { ...BabylonJSController.config.render.defaultSettings };
|
|
65
66
|
// Only include boolean settings as switches; scalar settings are handled by sliders.
|
|
66
|
-
#MENU_SWITCHES = Object.keys(this.#DEFAULT_RENDER_SETTINGS).filter(key =>
|
|
67
|
+
#MENU_SWITCHES = Object.keys(this.#DEFAULT_RENDER_SETTINGS).filter(key =>
|
|
67
68
|
typeof this.#DEFAULT_RENDER_SETTINGS[key] === "boolean"
|
|
68
69
|
);
|
|
69
70
|
#settings = { ...this.#DEFAULT_RENDER_SETTINGS };
|
|
@@ -77,9 +78,9 @@ export default class PrefViewerMenu3D extends HTMLElement {
|
|
|
77
78
|
#lightingPlaybackBase = 0.5;
|
|
78
79
|
#lightingPlaybackDurationMs = 15000;
|
|
79
80
|
|
|
80
|
-
#culture = DEFAULT_LOCALE;
|
|
81
|
+
#culture = I18n.DEFAULT_LOCALE;
|
|
81
82
|
#texts = {};
|
|
82
|
-
|
|
83
|
+
|
|
83
84
|
/**
|
|
84
85
|
* Creates the menu custom element.
|
|
85
86
|
* Rendering is deferred until connectedCallback() so attributes can be set before the UI is built.
|
|
@@ -87,8 +88,9 @@ export default class PrefViewerMenu3D extends HTMLElement {
|
|
|
87
88
|
*/
|
|
88
89
|
constructor() {
|
|
89
90
|
super();
|
|
91
|
+
this.#handles.onLightingTick = this.#tickLightingPlayback.bind(this);
|
|
90
92
|
}
|
|
91
|
-
|
|
93
|
+
|
|
92
94
|
/**
|
|
93
95
|
* Returns the list of attributes to observe for changes.
|
|
94
96
|
* @public
|
|
@@ -97,7 +99,7 @@ export default class PrefViewerMenu3D extends HTMLElement {
|
|
|
97
99
|
static get observedAttributes() {
|
|
98
100
|
return ["culture"];
|
|
99
101
|
}
|
|
100
|
-
|
|
102
|
+
|
|
101
103
|
/**
|
|
102
104
|
* Reacts to observed attribute mutations and mirrors them into the internal settings/UI state.
|
|
103
105
|
* @public
|
|
@@ -109,7 +111,7 @@ export default class PrefViewerMenu3D extends HTMLElement {
|
|
|
109
111
|
attributeChangedCallback(name, _old, value) {
|
|
110
112
|
switch (name) {
|
|
111
113
|
case "culture":
|
|
112
|
-
this.#setCultureInternal(value || DEFAULT_LOCALE);
|
|
114
|
+
this.#setCultureInternal(value || I18n.DEFAULT_LOCALE);
|
|
113
115
|
break;
|
|
114
116
|
}
|
|
115
117
|
}
|
|
@@ -194,7 +196,7 @@ export default class PrefViewerMenu3D extends HTMLElement {
|
|
|
194
196
|
/**
|
|
195
197
|
* Generates the HTML fragment for a single boolean render-setting switch.
|
|
196
198
|
* @private
|
|
197
|
-
* @param {string} key - Render setting key from BabylonJSController.
|
|
199
|
+
* @param {string} key - Render setting key from BabylonJSController.config.render.defaultSettings.
|
|
198
200
|
* @param {Record<string, {label?: string, helper?: string}>} copy - Locale-aware feature copy used for labels.
|
|
199
201
|
* @returns {string} HTML string representing the switch row.
|
|
200
202
|
*/
|
|
@@ -222,7 +224,7 @@ export default class PrefViewerMenu3D extends HTMLElement {
|
|
|
222
224
|
* @returns {object} Resolved `prefViewer.menu3d` translation object or an empty fallback.
|
|
223
225
|
*/
|
|
224
226
|
#getMenuNamespace() {
|
|
225
|
-
const namespace = translate("prefViewer.menu3d", { locale: this.#culture });
|
|
227
|
+
const namespace = I18n.translate("prefViewer.menu3d", { locale: this.#culture });
|
|
226
228
|
return namespace && typeof namespace === "object" ? namespace : {};
|
|
227
229
|
}
|
|
228
230
|
|
|
@@ -291,11 +293,11 @@ export default class PrefViewerMenu3D extends HTMLElement {
|
|
|
291
293
|
/**
|
|
292
294
|
* Resolves and applies a locale internally, updating texts when it changes.
|
|
293
295
|
* @private
|
|
294
|
-
* @param {string} [cultureId=DEFAULT_LOCALE] - Desired locale identifier.
|
|
296
|
+
* @param {string} [cultureId=I18n.DEFAULT_LOCALE] - Desired locale identifier.
|
|
295
297
|
* @returns {string} The applied locale.
|
|
296
298
|
*/
|
|
297
|
-
#setCultureInternal(cultureId = DEFAULT_LOCALE) {
|
|
298
|
-
const resolved = resolveLocale(cultureId);
|
|
299
|
+
#setCultureInternal(cultureId = I18n.DEFAULT_LOCALE) {
|
|
300
|
+
const resolved = I18n.resolveLocale(cultureId);
|
|
299
301
|
if (resolved === this.#culture) {
|
|
300
302
|
return this.#culture;
|
|
301
303
|
}
|
|
@@ -333,7 +335,7 @@ export default class PrefViewerMenu3D extends HTMLElement {
|
|
|
333
335
|
this.#elements.sliderWrappers["highlightColor"] = this.querySelector(".menu-slider[data-setting='highlightColor']");
|
|
334
336
|
this.#elements.sliders["lightingTimeOfDay"] = this.querySelector("input[data-setting='lightingTimeOfDay']");
|
|
335
337
|
this.#elements.sliderWrappers["lightingTimeOfDay"] = this.querySelector(".menu-slider[data-setting='lightingTimeOfDay']");
|
|
336
|
-
|
|
338
|
+
|
|
337
339
|
this.#MENU_SWITCHES.forEach((key) => {
|
|
338
340
|
this.#elements.switches[key] = this.querySelector(`input[data-setting="${key}"]`);
|
|
339
341
|
const wrapper = this.querySelector(`.menu-switch[data-setting="${key}"]`);
|
|
@@ -499,19 +501,26 @@ export default class PrefViewerMenu3D extends HTMLElement {
|
|
|
499
501
|
this.#lightingPlaybackBase = this.#settings.lightingTimeOfDay ?? 0.5;
|
|
500
502
|
this.#lightingPlaybackStart = typeof performance !== "undefined" && performance.now ? performance.now() : Date.now();
|
|
501
503
|
this.#updateLightingPlayButtonUI();
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
504
|
+
|
|
505
|
+
this.#lightingAnimationFrame = requestAnimationFrame(this.#handles.onLightingTick);
|
|
506
|
+
}
|
|
507
|
+
|
|
508
|
+
/**
|
|
509
|
+
* Advances the time-of-day playback cycle and emits transient settings while playback remains active.
|
|
510
|
+
* @private
|
|
511
|
+
* @returns {void}
|
|
512
|
+
*/
|
|
513
|
+
#tickLightingPlayback() {
|
|
514
|
+
if (!this.#isLightingPlaying) {
|
|
515
|
+
return;
|
|
516
|
+
}
|
|
517
|
+
const now = typeof performance !== "undefined" && performance.now ? performance.now() : Date.now();
|
|
518
|
+
const elapsed = now - this.#lightingPlaybackStart;
|
|
519
|
+
const cycle = (this.#lightingPlaybackBase + (elapsed / this.#lightingPlaybackDurationMs)) % 1;
|
|
520
|
+
this.#settings.lightingTimeOfDay = cycle;
|
|
521
|
+
this.#updateLightingSliderUI(cycle);
|
|
522
|
+
this.#emitApply({ lightingTimeOfDay: cycle, persist: false }, { partial: true });
|
|
523
|
+
this.#lightingAnimationFrame = requestAnimationFrame(this.#handles.onLightingTick);
|
|
515
524
|
}
|
|
516
525
|
|
|
517
526
|
/**
|
|
@@ -555,11 +564,22 @@ export default class PrefViewerMenu3D extends HTMLElement {
|
|
|
555
564
|
static #hueToHex(hue) {
|
|
556
565
|
const h = ((hue % 360) + 360) % 360;
|
|
557
566
|
const a = Math.min(0.5, 1 - 0.5);
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
567
|
+
|
|
568
|
+
return '#' + [0, 8, 4].map((phase) => PrefViewerMenu3D.#hueChannel(phase, h, a)).map((v) => Math.round(v * 255).toString(16).padStart(2, '0')).join('');
|
|
569
|
+
}
|
|
570
|
+
|
|
571
|
+
/**
|
|
572
|
+
* Computes a normalized RGB channel from the current hue.
|
|
573
|
+
* @private
|
|
574
|
+
* @static
|
|
575
|
+
* @param {number} phase - Channel phase offset.
|
|
576
|
+
* @param {number} hue - Normalized hue angle in degrees.
|
|
577
|
+
* @param {number} amplitude - RGB channel amplitude.
|
|
578
|
+
* @returns {number}
|
|
579
|
+
*/
|
|
580
|
+
static #hueChannel(phase, hue, amplitude) {
|
|
581
|
+
const k = (phase + hue / 30) % 12;
|
|
582
|
+
return 0.5 - amplitude * Math.max(Math.min(k - 3, 9 - k, 1), -1);
|
|
563
583
|
}
|
|
564
584
|
|
|
565
585
|
/**
|
|
@@ -724,21 +744,21 @@ export default class PrefViewerMenu3D extends HTMLElement {
|
|
|
724
744
|
this.#isApplying = isApplying;
|
|
725
745
|
this.toggleAttribute("data-applying", isApplying);
|
|
726
746
|
}
|
|
727
|
-
|
|
747
|
+
|
|
728
748
|
/**
|
|
729
749
|
* Sets the locale used for menu labels and helper text.
|
|
730
750
|
* @public
|
|
731
751
|
* @param {string} cultureId - Locale identifier, e.g., "en-EN".
|
|
732
752
|
* @returns {void}
|
|
733
753
|
*/
|
|
734
|
-
setCulture(cultureId = DEFAULT_LOCALE) {
|
|
735
|
-
const resolved = resolveLocale(cultureId);
|
|
754
|
+
setCulture(cultureId = I18n.DEFAULT_LOCALE) {
|
|
755
|
+
const resolved = I18n.resolveLocale(cultureId);
|
|
736
756
|
const applied = this.#setCultureInternal(resolved);
|
|
737
757
|
if (this.getAttribute("culture") !== applied) {
|
|
738
758
|
this.setAttribute("culture", applied);
|
|
739
759
|
}
|
|
740
760
|
}
|
|
741
|
-
|
|
761
|
+
|
|
742
762
|
/**
|
|
743
763
|
* Enables or disables the menu entirely, hiding it when 3D mode is unavailable.
|
|
744
764
|
* @public
|
|
@@ -774,7 +794,7 @@ export default class PrefViewerMenu3D extends HTMLElement {
|
|
|
774
794
|
this.#updateLightingPlayButtonUI();
|
|
775
795
|
this.setApplying(false);
|
|
776
796
|
}
|
|
777
|
-
|
|
797
|
+
|
|
778
798
|
/**
|
|
779
799
|
* Receives viewer hover state so the menu only opens when the user interacts with the 3D viewport.
|
|
780
800
|
* @public
|