@preference-sl/pref-viewer 2.13.0-beta.14 → 2.13.0-beta.16
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/package.json +1 -1
- package/src/babylonjs-controller.js +15 -13
- package/src/pref-viewer-3d.js +30 -6
- package/src/pref-viewer.js +113 -13
package/package.json
CHANGED
|
@@ -1485,10 +1485,10 @@ export default class BabylonJSController {
|
|
|
1485
1485
|
* @returns {void}
|
|
1486
1486
|
*/
|
|
1487
1487
|
#onKeyUp(event) {
|
|
1488
|
-
// CTRL + ALT + letter
|
|
1489
|
-
if (event.ctrlKey && event.altKey && event.
|
|
1490
|
-
switch (event.
|
|
1491
|
-
case "
|
|
1488
|
+
// CTRL + ALT + letter (uses event.code for physical key, layout-independent — fixes Mac Option+D producing "∂" instead of "d")
|
|
1489
|
+
if (event.ctrlKey && event.altKey && event.code !== undefined) {
|
|
1490
|
+
switch (event.code) {
|
|
1491
|
+
case "KeyD":
|
|
1492
1492
|
this.#openDownloadDialog();
|
|
1493
1493
|
break;
|
|
1494
1494
|
default:
|
|
@@ -2087,7 +2087,7 @@ export default class BabylonJSController {
|
|
|
2087
2087
|
* Applies material and camera options, sets wall/floor visibility, and initializes lights and shadows.
|
|
2088
2088
|
* Returns an object with success status and error details.
|
|
2089
2089
|
*/
|
|
2090
|
-
async #loadContainers() {
|
|
2090
|
+
async #loadContainers(force = false) {
|
|
2091
2091
|
this.#detachAnimationChangedListener();
|
|
2092
2092
|
await this.#stopRender();
|
|
2093
2093
|
|
|
@@ -2096,7 +2096,7 @@ export default class BabylonJSController {
|
|
|
2096
2096
|
|
|
2097
2097
|
const promiseArray = [];
|
|
2098
2098
|
Object.values(this.#containers).forEach((container) => {
|
|
2099
|
-
promiseArray.push(this.#loadAssetContainer(container));
|
|
2099
|
+
promiseArray.push(this.#loadAssetContainer(container, force));
|
|
2100
2100
|
});
|
|
2101
2101
|
|
|
2102
2102
|
let detail = {
|
|
@@ -2594,8 +2594,8 @@ export default class BabylonJSController {
|
|
|
2594
2594
|
* @public
|
|
2595
2595
|
* @returns {Promise<boolean>} Resolves to true if loading succeeds, false otherwise.
|
|
2596
2596
|
*/
|
|
2597
|
-
async load() {
|
|
2598
|
-
return await this.#loadContainers();
|
|
2597
|
+
async load(force = false) {
|
|
2598
|
+
return await this.#loadContainers(force);
|
|
2599
2599
|
}
|
|
2600
2600
|
|
|
2601
2601
|
/**
|
|
@@ -2630,11 +2630,13 @@ export default class BabylonJSController {
|
|
|
2630
2630
|
* @public
|
|
2631
2631
|
* @returns {boolean} True if IBL options were set successfully, false otherwise.
|
|
2632
2632
|
*/
|
|
2633
|
-
setIBLOptions() {
|
|
2634
|
-
this.#stopRender();
|
|
2635
|
-
|
|
2636
|
-
|
|
2637
|
-
|
|
2633
|
+
async setIBLOptions() {
|
|
2634
|
+
await this.#stopRender();
|
|
2635
|
+
try {
|
|
2636
|
+
return await this.#setOptions_IBL();
|
|
2637
|
+
} finally {
|
|
2638
|
+
await this.#startRender();
|
|
2639
|
+
}
|
|
2638
2640
|
}
|
|
2639
2641
|
|
|
2640
2642
|
/**
|
package/src/pref-viewer-3d.js
CHANGED
|
@@ -75,6 +75,7 @@ export default class PrefViewer3D extends HTMLElement {
|
|
|
75
75
|
#isInitialized = false;
|
|
76
76
|
#isLoaded = false;
|
|
77
77
|
#isVisible = false;
|
|
78
|
+
#lastLoadTimestamp = undefined;
|
|
78
79
|
|
|
79
80
|
#wrapper = null;
|
|
80
81
|
#canvas = null;
|
|
@@ -230,6 +231,27 @@ export default class PrefViewer3D extends HTMLElement {
|
|
|
230
231
|
this.#babylonJSController.enable();
|
|
231
232
|
}
|
|
232
233
|
|
|
234
|
+
/**
|
|
235
|
+
* Determines whether the next 3D load should bypass cache checks.
|
|
236
|
+
* @private
|
|
237
|
+
* @param {object} config - Incoming config payload.
|
|
238
|
+
* @returns {boolean} True when force reload should be enabled.
|
|
239
|
+
*/
|
|
240
|
+
#shouldForceReload(config) {
|
|
241
|
+
if (!config || typeof config !== "object") {
|
|
242
|
+
return false;
|
|
243
|
+
}
|
|
244
|
+
if (config.forceReload === true) {
|
|
245
|
+
return true;
|
|
246
|
+
}
|
|
247
|
+
if (config.timestamp === undefined || config.timestamp === null) {
|
|
248
|
+
return false;
|
|
249
|
+
}
|
|
250
|
+
const changed = config.timestamp !== this.#lastLoadTimestamp;
|
|
251
|
+
this.#lastLoadTimestamp = config.timestamp;
|
|
252
|
+
return changed;
|
|
253
|
+
}
|
|
254
|
+
|
|
233
255
|
/**
|
|
234
256
|
* Resets update flags for all containers and material/camera options after loading or setting options.
|
|
235
257
|
* @private
|
|
@@ -558,6 +580,7 @@ export default class PrefViewer3D extends HTMLElement {
|
|
|
558
580
|
}
|
|
559
581
|
|
|
560
582
|
this.#onLoading();
|
|
583
|
+
const forceReload = this.#shouldForceReload(config);
|
|
561
584
|
|
|
562
585
|
// Containers
|
|
563
586
|
this.#checkNeedToUpdateContainers(config);
|
|
@@ -566,10 +589,10 @@ export default class PrefViewer3D extends HTMLElement {
|
|
|
566
589
|
if (config.options) {
|
|
567
590
|
this.#checkNeedToUpdateCamera(config.options);
|
|
568
591
|
this.#checkNeedToUpdateMaterials(config.options);
|
|
569
|
-
this.#checkNeedToUpdateIBL(config.options);
|
|
592
|
+
await this.#checkNeedToUpdateIBL(config.options);
|
|
570
593
|
}
|
|
571
594
|
|
|
572
|
-
const loadDetail = await this.#babylonJSController.load();
|
|
595
|
+
const loadDetail = await this.#babylonJSController.load(forceReload);
|
|
573
596
|
|
|
574
597
|
return { ...loadDetail, load: this.#onLoaded() };
|
|
575
598
|
}
|
|
@@ -579,9 +602,9 @@ export default class PrefViewer3D extends HTMLElement {
|
|
|
579
602
|
* Updates internal states, triggers option setting events, and returns the result.
|
|
580
603
|
* @public
|
|
581
604
|
* @param {object} options - Options object containing camera and material settings.
|
|
582
|
-
* @returns {object} Object containing success status and details of set options.
|
|
605
|
+
* @returns {Promise<object>} Object containing success status and details of set options.
|
|
583
606
|
*/
|
|
584
|
-
setOptions(options) {
|
|
607
|
+
async setOptions(options) {
|
|
585
608
|
if (!this.#babylonJSController) {
|
|
586
609
|
return;
|
|
587
610
|
}
|
|
@@ -595,8 +618,9 @@ export default class PrefViewer3D extends HTMLElement {
|
|
|
595
618
|
if (this.#checkNeedToUpdateMaterials(options)) {
|
|
596
619
|
someSetted = someSetted || this.#babylonJSController.setMaterialOptions();
|
|
597
620
|
}
|
|
598
|
-
|
|
599
|
-
|
|
621
|
+
const needUpdateIBL = await this.#checkNeedToUpdateIBL(options);
|
|
622
|
+
if (needUpdateIBL) {
|
|
623
|
+
someSetted = someSetted || (await this.#babylonJSController.setIBLOptions());
|
|
600
624
|
}
|
|
601
625
|
const detail = this.#onSetOptions();
|
|
602
626
|
return { success: someSetted, detail: detail };
|
package/src/pref-viewer.js
CHANGED
|
@@ -81,6 +81,7 @@ export default class PrefViewer extends HTMLElement {
|
|
|
81
81
|
onViewerHoverStart: null,
|
|
82
82
|
onViewerHoverEnd: null,
|
|
83
83
|
on3DSceneLoaded: null,
|
|
84
|
+
on3DSceneError: null,
|
|
84
85
|
};
|
|
85
86
|
|
|
86
87
|
/**
|
|
@@ -136,6 +137,9 @@ export default class PrefViewer extends HTMLElement {
|
|
|
136
137
|
this.loadMaterials(value);
|
|
137
138
|
break;
|
|
138
139
|
case "mode":
|
|
140
|
+
if (typeof value !== "string") {
|
|
141
|
+
return;
|
|
142
|
+
}
|
|
139
143
|
if (_old === value || value.toLowerCase() === this.#mode) {
|
|
140
144
|
return;
|
|
141
145
|
}
|
|
@@ -151,6 +155,9 @@ export default class PrefViewer extends HTMLElement {
|
|
|
151
155
|
this.setOptions(value);
|
|
152
156
|
break;
|
|
153
157
|
case "show-model":
|
|
158
|
+
if (typeof value !== "string") {
|
|
159
|
+
return;
|
|
160
|
+
}
|
|
154
161
|
if (_old === value) {
|
|
155
162
|
return;
|
|
156
163
|
}
|
|
@@ -158,6 +165,9 @@ export default class PrefViewer extends HTMLElement {
|
|
|
158
165
|
showModel ? this.showModel() : this.hideModel();
|
|
159
166
|
break;
|
|
160
167
|
case "show-scene":
|
|
168
|
+
if (typeof value !== "string") {
|
|
169
|
+
return;
|
|
170
|
+
}
|
|
161
171
|
if (_old === value) {
|
|
162
172
|
return;
|
|
163
173
|
}
|
|
@@ -213,6 +223,7 @@ export default class PrefViewer extends HTMLElement {
|
|
|
213
223
|
}
|
|
214
224
|
if (this.#component3D) {
|
|
215
225
|
this.#component3D.removeEventListener("scene-loaded", this.#handlers.on3DSceneLoaded);
|
|
226
|
+
this.#component3D.removeEventListener("scene-error", this.#handlers.on3DSceneError);
|
|
216
227
|
this.#component3D.remove();
|
|
217
228
|
}
|
|
218
229
|
if (this.#menu3D) {
|
|
@@ -249,7 +260,11 @@ export default class PrefViewer extends HTMLElement {
|
|
|
249
260
|
this.#menu3DSyncSettings();
|
|
250
261
|
this.#menu3D?.setApplying(false);
|
|
251
262
|
};
|
|
263
|
+
this.#handlers.on3DSceneError = () => {
|
|
264
|
+
this.#menu3D?.setApplying(false, true);
|
|
265
|
+
};
|
|
252
266
|
this.#component3D.addEventListener("scene-loaded", this.#handlers.on3DSceneLoaded);
|
|
267
|
+
this.#component3D.addEventListener("scene-error", this.#handlers.on3DSceneError);
|
|
253
268
|
this.#wrapper.appendChild(this.#component3D);
|
|
254
269
|
}
|
|
255
270
|
|
|
@@ -454,7 +469,14 @@ export default class PrefViewer extends HTMLElement {
|
|
|
454
469
|
* @returns {void}
|
|
455
470
|
*/
|
|
456
471
|
#addTaskToQueue(value, type) {
|
|
457
|
-
|
|
472
|
+
const task = new PrefViewerTask(value, type);
|
|
473
|
+
if (
|
|
474
|
+
task.type === PrefViewerTask.Types.Options ||
|
|
475
|
+
task.type === PrefViewerTask.Types.Drawing
|
|
476
|
+
) {
|
|
477
|
+
this.#taskQueue = this.#taskQueue.filter((queuedTask) => queuedTask.type !== task.type);
|
|
478
|
+
}
|
|
479
|
+
this.#taskQueue.push(task);
|
|
458
480
|
if (this.#isInitialized && !this.#isLoading) {
|
|
459
481
|
this.#processNextTask();
|
|
460
482
|
}
|
|
@@ -552,6 +574,32 @@ export default class PrefViewer extends HTMLElement {
|
|
|
552
574
|
this.dispatchEvent(new CustomEvent("scene-loaded", customEventOptions));
|
|
553
575
|
}
|
|
554
576
|
|
|
577
|
+
/**
|
|
578
|
+
* Handles 3D load errors.
|
|
579
|
+
* Clears loading state and dispatches a "scene-error" event.
|
|
580
|
+
* @private
|
|
581
|
+
* @param {object} [detail] - Optional details about the failure.
|
|
582
|
+
* @returns {void}
|
|
583
|
+
*/
|
|
584
|
+
#on3DError(detail) {
|
|
585
|
+
this.#isLoaded = false;
|
|
586
|
+
this.#isLoading = false;
|
|
587
|
+
this.#menu3D?.setApplying(false, true);
|
|
588
|
+
|
|
589
|
+
this.removeAttribute("loading-3d");
|
|
590
|
+
this.removeAttribute("loaded-3d");
|
|
591
|
+
|
|
592
|
+
const customEventOptions = {
|
|
593
|
+
bubbles: true,
|
|
594
|
+
cancelable: true,
|
|
595
|
+
composed: true,
|
|
596
|
+
};
|
|
597
|
+
if (detail) {
|
|
598
|
+
customEventOptions.detail = detail;
|
|
599
|
+
}
|
|
600
|
+
this.dispatchEvent(new CustomEvent("scene-error", customEventOptions));
|
|
601
|
+
}
|
|
602
|
+
|
|
555
603
|
/**
|
|
556
604
|
* Handles the start of a 2D loading operation.
|
|
557
605
|
* Updates loading state, sets attributes, and dispatches a "drawing-loading" event.
|
|
@@ -598,6 +646,31 @@ export default class PrefViewer extends HTMLElement {
|
|
|
598
646
|
this.dispatchEvent(new CustomEvent("drawing-loaded", customEventOptions));
|
|
599
647
|
}
|
|
600
648
|
|
|
649
|
+
/**
|
|
650
|
+
* Handles 2D load errors.
|
|
651
|
+
* Clears loading state and dispatches a "drawing-error" event.
|
|
652
|
+
* @private
|
|
653
|
+
* @param {object} [detail] - Optional details about the failure.
|
|
654
|
+
* @returns {void}
|
|
655
|
+
*/
|
|
656
|
+
#on2DError(detail) {
|
|
657
|
+
this.#isLoaded = false;
|
|
658
|
+
this.#isLoading = false;
|
|
659
|
+
|
|
660
|
+
this.removeAttribute("loading-2d");
|
|
661
|
+
this.removeAttribute("loaded-2d");
|
|
662
|
+
|
|
663
|
+
const customEventOptions = {
|
|
664
|
+
bubbles: true,
|
|
665
|
+
cancelable: true,
|
|
666
|
+
composed: true,
|
|
667
|
+
};
|
|
668
|
+
if (detail) {
|
|
669
|
+
customEventOptions.detail = detail;
|
|
670
|
+
}
|
|
671
|
+
this.dispatchEvent(new CustomEvent("drawing-error", customEventOptions));
|
|
672
|
+
}
|
|
673
|
+
|
|
601
674
|
/**
|
|
602
675
|
* Handles the "drawing-zoom-changed" event from the 2D viewer component.
|
|
603
676
|
* Dispatches a custom "drawing-zoom-changed" event from the PrefViewer element, forwarding the event detail to external listeners.
|
|
@@ -640,16 +713,27 @@ export default class PrefViewer extends HTMLElement {
|
|
|
640
713
|
* @param {object} config - The configuration object to process.
|
|
641
714
|
* @returns {void}
|
|
642
715
|
*/
|
|
643
|
-
#processConfig(config) {
|
|
716
|
+
async #processConfig(config) {
|
|
644
717
|
if (!this.#component3D) {
|
|
718
|
+
this.#processNextTask();
|
|
645
719
|
return;
|
|
646
720
|
}
|
|
647
721
|
|
|
648
722
|
this.#on3DLoading();
|
|
649
|
-
|
|
650
|
-
this.#
|
|
723
|
+
try {
|
|
724
|
+
const detail = await this.#component3D.load(config);
|
|
725
|
+
if (detail?.success === false) {
|
|
726
|
+
this.#on3DError(detail);
|
|
727
|
+
} else {
|
|
728
|
+
this.#on3DLoaded(detail);
|
|
729
|
+
}
|
|
730
|
+
} catch (error) {
|
|
731
|
+
this.#on3DError({
|
|
732
|
+
error: error instanceof Error ? error : new Error(String(error)),
|
|
733
|
+
});
|
|
734
|
+
} finally {
|
|
651
735
|
this.#processNextTask();
|
|
652
|
-
}
|
|
736
|
+
}
|
|
653
737
|
}
|
|
654
738
|
|
|
655
739
|
/**
|
|
@@ -670,16 +754,23 @@ export default class PrefViewer extends HTMLElement {
|
|
|
670
754
|
* @param {object} drawing - The drawing object to process.
|
|
671
755
|
* @returns {void}
|
|
672
756
|
*/
|
|
673
|
-
#processDrawing(drawing) {
|
|
757
|
+
async #processDrawing(drawing) {
|
|
674
758
|
if (!this.#component2D) {
|
|
759
|
+
this.#processNextTask();
|
|
675
760
|
return;
|
|
676
761
|
}
|
|
677
762
|
|
|
678
763
|
this.#on2DLoading();
|
|
679
|
-
|
|
764
|
+
try {
|
|
765
|
+
const detail = await this.#component2D.load(drawing);
|
|
680
766
|
this.#on2DLoaded(detail);
|
|
767
|
+
} catch (error) {
|
|
768
|
+
this.#on2DError({
|
|
769
|
+
error: error instanceof Error ? error : new Error(String(error)),
|
|
770
|
+
});
|
|
771
|
+
} finally {
|
|
681
772
|
this.#processNextTask();
|
|
682
|
-
}
|
|
773
|
+
}
|
|
683
774
|
}
|
|
684
775
|
|
|
685
776
|
/**
|
|
@@ -725,15 +816,23 @@ export default class PrefViewer extends HTMLElement {
|
|
|
725
816
|
* @param {object} options - The options object to process.
|
|
726
817
|
* @returns {void}
|
|
727
818
|
*/
|
|
728
|
-
#processOptions(options) {
|
|
819
|
+
async #processOptions(options) {
|
|
729
820
|
if (!this.#component3D) {
|
|
821
|
+
this.#processNextTask();
|
|
730
822
|
return;
|
|
731
823
|
}
|
|
732
824
|
|
|
733
825
|
this.#on3DLoading();
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
826
|
+
try {
|
|
827
|
+
const detail = await this.#component3D.setOptions(options);
|
|
828
|
+
this.#on3DLoaded(detail);
|
|
829
|
+
} catch (error) {
|
|
830
|
+
this.#on3DError({
|
|
831
|
+
error: error instanceof Error ? error : new Error(String(error)),
|
|
832
|
+
});
|
|
833
|
+
} finally {
|
|
834
|
+
this.#processNextTask();
|
|
835
|
+
}
|
|
737
836
|
}
|
|
738
837
|
|
|
739
838
|
/**
|
|
@@ -745,6 +844,7 @@ export default class PrefViewer extends HTMLElement {
|
|
|
745
844
|
*/
|
|
746
845
|
#processVisibility(config) {
|
|
747
846
|
if (!this.#component3D) {
|
|
847
|
+
this.#processNextTask();
|
|
748
848
|
return;
|
|
749
849
|
}
|
|
750
850
|
const showModel = config.model?.visible;
|
|
@@ -974,7 +1074,7 @@ export default class PrefViewer extends HTMLElement {
|
|
|
974
1074
|
* @returns {void}
|
|
975
1075
|
*/
|
|
976
1076
|
setMode(mode = this.#mode) {
|
|
977
|
-
mode = mode.toLowerCase();
|
|
1077
|
+
mode = typeof mode === "string" ? mode.toLowerCase() : this.#mode;
|
|
978
1078
|
if (mode !== "2d" && mode !== "3d") {
|
|
979
1079
|
console.warn(`PrefViewer: invalid mode "${mode}". Allowed modes are "2d" and "3d".`);
|
|
980
1080
|
mode = this.#mode;
|