@preference-sl/pref-viewer 2.10.0-beta.27 → 2.10.0-beta.29

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 (2) hide show
  1. package/package.json +1 -1
  2. package/src/index.js +202 -149
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@preference-sl/pref-viewer",
3
- "version": "2.10.0-beta.27",
3
+ "version": "2.10.0-beta.29",
4
4
  "description": "Web Component to preview GLTF models with Babylon.js",
5
5
  "author": "Alex Moreno Palacio <amoreno@preference.es>",
6
6
  "scripts": {
package/src/index.js CHANGED
@@ -22,7 +22,7 @@
22
22
  * style="width:800px; height:600px;">
23
23
  * </pref-viewer>
24
24
  * ```
25
- *
25
+ *
26
26
  * Load scene a URL:
27
27
  * ```html
28
28
  * <pref-viewer
@@ -46,16 +46,46 @@ import "@babylonjs/loaders/glTF/2.0/Extensions/KHR_draco_mesh_compression";
46
46
  import { DracoCompression } from "@babylonjs/core/Meshes/Compression/dracoCompression";
47
47
  import { initDb, loadModel } from "./gltf-storage.js";
48
48
 
49
+ class PrefViewerTask {
50
+ static Types = Object.freeze({
51
+ Config: "config",
52
+ Environment: "environment",
53
+ Materials: "materials",
54
+ Model: "model",
55
+ Options: "options",
56
+ });
57
+
58
+ /**
59
+ * value: any payload for the task
60
+ * type: must match one of PrefViewerTask.Types values (case-insensitive)
61
+ */
62
+ constructor(value, type) {
63
+ this.value = value;
64
+
65
+ const t = typeof type === "string" ? type.toLowerCase() : String(type).toLowerCase();
66
+ const allowed = Object.values(PrefViewerTask.Types);
67
+ if (!allowed.includes(t)) {
68
+ throw new TypeError(
69
+ `PrefViewerTask: invalid type "${type}". Allowed types: ${allowed.join(", ")}`
70
+ );
71
+ }
72
+ this.type = t;
73
+
74
+ Object.freeze(this);
75
+ }
76
+ }
77
+
49
78
  class PrefViewer extends HTMLElement {
50
79
  initialized = false;
51
80
  loaded = false;
52
81
  loading = false;
82
+ #taskQueue = [];
53
83
 
54
84
  #data = {
55
85
  containers: {
56
86
  model: {
57
87
  name: "model",
58
- container: null,
88
+ assetContainer: null,
59
89
  show: true,
60
90
  storage: null,
61
91
  visible: false,
@@ -65,7 +95,7 @@ class PrefViewer extends HTMLElement {
65
95
  },
66
96
  environment: {
67
97
  name: "environment",
68
- container: null,
98
+ assetContainer: null,
69
99
  show: true,
70
100
  storage: null,
71
101
  visible: false,
@@ -75,7 +105,7 @@ class PrefViewer extends HTMLElement {
75
105
  },
76
106
  materials: {
77
107
  name: "materials",
78
- container: null,
108
+ assetContainer: null,
79
109
  storage: null,
80
110
  show: true,
81
111
  visible: false,
@@ -88,28 +118,28 @@ class PrefViewer extends HTMLElement {
88
118
  camera: {
89
119
  value: null,
90
120
  locked: true,
91
- changed: { pending: false, success: false, oldValue: null, oldLocked: true },
121
+ changed: { pending: false, success: false },
92
122
  },
93
123
  materials: {
94
124
  innerWall: {
95
125
  value: null,
96
126
  prefix: "innerWall",
97
- changed: { pending: false, success: false, oldValue: null },
127
+ changed: { pending: false, success: false },
98
128
  },
99
129
  outerWall: {
100
130
  value: null,
101
131
  prefix: "outerWall",
102
- changed: { pending: false, success: false, oldValue: null },
132
+ changed: { pending: false, success: false },
103
133
  },
104
134
  innerFloor: {
105
135
  value: null,
106
136
  prefix: "innerFloor",
107
- changed: { pending: false, success: false, oldValue: null },
137
+ changed: { pending: false, success: false },
108
138
  },
109
139
  outerFloor: {
110
140
  value: null,
111
141
  prefix: "outerFloor",
112
- changed: { pending: false, success: false, oldValue: null },
142
+ changed: { pending: false, success: false },
113
143
  },
114
144
  },
115
145
  },
@@ -162,6 +192,12 @@ class PrefViewer extends HTMLElement {
162
192
  case "scene":
163
193
  this.loadScene(value);
164
194
  break;
195
+ case "materials":
196
+ this.loadMaterials(value);
197
+ break;
198
+ case "options":
199
+ this.setOptions(value);
200
+ break;
165
201
  case "show-model":
166
202
  data = value.toLowerCase?.() === "true";
167
203
  if (this.initialized) {
@@ -198,7 +234,7 @@ class PrefViewer extends HTMLElement {
198
234
 
199
235
  this.#initializeBabylon();
200
236
  this.initialized = true;
201
- this.#loadContainers(true, true, true);
237
+ this.#processNextTask();
202
238
  }
203
239
 
204
240
  disconnectedCallback() {
@@ -228,7 +264,7 @@ class PrefViewer extends HTMLElement {
228
264
  this.shadowRoot.append(this.#wrapper);
229
265
  }
230
266
 
231
- #setStatusSceneLoading() {
267
+ #setStatusLoading() {
232
268
  this.loaded = false;
233
269
  this.loading = true;
234
270
  if (this.hasAttribute("loaded")) {
@@ -242,12 +278,10 @@ class PrefViewer extends HTMLElement {
242
278
  composed: true,
243
279
  })
244
280
  );
281
+ this.#engine.stopRenderLoop(this.#renderLoop);
245
282
  }
246
283
 
247
- #setStatusSceneLoaded() {
248
- this.loaded = true;
249
- this.loading = false;
250
-
284
+ async #setStatusLoaded() {
251
285
  const toLoadDetail = {
252
286
  container_model: !!this.#data.containers.model.changed.pending,
253
287
  container_environment: !!this.#data.containers.environment.changed.pending,
@@ -268,16 +302,11 @@ class PrefViewer extends HTMLElement {
268
302
  options_innerFloorMaterial: !!this.#data.options.materials.innerFloor.changed.success,
269
303
  options_outerFloorMaterial: !!this.#data.options.materials.outerFloor.changed.success,
270
304
  };
271
-
272
305
  const detail = {
273
306
  tried: toLoadDetail,
274
307
  success: loadedDetail,
275
308
  };
276
-
277
- if (this.hasAttribute("loading")) {
278
- this.removeAttribute("loading");
279
- }
280
- this.setAttribute("loaded", "");
309
+
281
310
  this.dispatchEvent(
282
311
  new CustomEvent("scene-loaded", {
283
312
  bubbles: true,
@@ -286,49 +315,21 @@ class PrefViewer extends HTMLElement {
286
315
  detail: detail,
287
316
  })
288
317
  );
289
- this.#resetChangedFlags();
290
- }
291
318
 
292
- #setStatusOptionsLoading() {
293
- this.dispatchEvent(
294
- new CustomEvent("options-loading", {
295
- bubbles: true,
296
- cancelable: false,
297
- composed: true,
298
- })
299
- );
300
- }
319
+ await this.#scene.whenReadyAsync();
320
+ this.#engine.runRenderLoop(this.#renderLoop);
321
+
322
+ this.#resetChangedFlags();
301
323
 
302
- #setStatusOptionsLoaded() {
303
- const toLoadDetail = {
304
- camera: !!this.#data.options.camera.changed.pending,
305
- innerWallMaterial: !!this.#data.options.materials.innerWall.changed.pending,
306
- outerWallMaterial: !!this.#data.options.materials.outerWall.changed.pending,
307
- innerFloorMaterial: !!this.#data.options.materials.innerFloor.changed.pending,
308
- outerFloorMaterial: !!this.#data.options.materials.outerFloor.changed.pending,
309
- };
310
- const loadedDetail = {
311
- camera: !!this.#data.options.camera.changed.success,
312
- innerWallMaterial: !!this.#data.options.materials.innerWall.changed.success,
313
- outerWallMaterial: !!this.#data.options.materials.outerWall.changed.success,
314
- innerFloorMaterial: !!this.#data.options.materials.innerFloor.changed.success,
315
- outerFloorMaterial: !!this.#data.options.materials.outerFloor.changed.success,
316
- };
324
+ if (this.hasAttribute("loading")) {
325
+ this.removeAttribute("loading");
326
+ }
327
+ this.setAttribute("loaded", "");
317
328
 
318
- const detail = {
319
- tried: toLoadDetail,
320
- success: loadedDetail,
321
- };
329
+ this.loaded = true;
330
+ this.loading = false;
322
331
 
323
- this.dispatchEvent(
324
- new CustomEvent("options-loaded", {
325
- bubbles: true,
326
- cancelable: false,
327
- composed: true,
328
- detail: detail,
329
- })
330
- );
331
- this.#resetChangedFlags();
332
+ this.#processNextTask();
332
333
  }
333
334
 
334
335
  // Data
@@ -342,8 +343,8 @@ class PrefViewer extends HTMLElement {
342
343
  this.#data.options.camera.changed.pending = changed;
343
344
  this.#data.options.camera.changed.success = false;
344
345
  if (changed) {
345
- this.#data.options.camera.changed.oldValue = prev;
346
- this.#data.options.camera.changed.oldLocked = this.#data.options.camera.locked;
346
+ this.#data.options.camera.changed.value = prev;
347
+ this.#data.options.camera.changed.locked = this.#data.options.camera.locked;
347
348
  this.#data.options.camera.value = options.camera;
348
349
  }
349
350
  return changed;
@@ -359,15 +360,15 @@ class PrefViewer extends HTMLElement {
359
360
  const state = this.#data.options.materials[material];
360
361
  const prev = state.value;
361
362
  const incoming = options[key];
362
- const materialChanged = !!incoming && incoming !== prev;
363
+ const changed = !!incoming && incoming !== prev;
363
364
 
364
- state.changed.pending = materialChanged;
365
+ state.changed.pending = changed;
365
366
  state.changed.success = false;
366
- if (materialChanged) {
367
- state.changed.oldValue = prev;
367
+ if (changed) {
368
+ state.changed.value = prev;
368
369
  state.value = incoming;
369
370
  }
370
- someChanged = someChanged || materialChanged;
371
+ someChanged = someChanged || changed;
371
372
  });
372
373
  return someChanged;
373
374
  }
@@ -377,18 +378,14 @@ class PrefViewer extends HTMLElement {
377
378
  container.timeStamp = container.changed.timeStamp;
378
379
  container.size = container.changed.size;
379
380
  container.changed.success = true;
380
- container.changed.pending = false;
381
381
  } else {
382
382
  container.changed.success = false;
383
- container.changed.pending = false;
384
383
  }
385
384
  }
386
385
 
387
386
  #resetChangedFlags() {
388
387
  const reset = (node) => {
389
- if (!node.changed) node.changed = {};
390
- node.changed.pending = false;
391
- node.changed.success = false;
388
+ node.changed = { pending: false, success: false };
392
389
  };
393
390
  Object.values(this.#data.containers).forEach(reset);
394
391
  Object.values(this.#data.options.materials).forEach(reset);
@@ -723,11 +720,9 @@ class PrefViewer extends HTMLElement {
723
720
 
724
721
  if (someSetted) {
725
722
  optionMaterial.changed.success = true;
726
- optionMaterial.changed.pending = false;
727
723
  } else if (optionMaterial.changed.pending) {
728
- optionMaterial.value = optionMaterial.changed.oldValue;
724
+ optionMaterial.value = optionMaterial.changed.value;
729
725
  optionMaterial.changed.success = false;
730
- optionMaterial.changed.pending = false;
731
726
  }
732
727
 
733
728
  return someSetted;
@@ -743,38 +738,30 @@ class PrefViewer extends HTMLElement {
743
738
  }
744
739
 
745
740
  #setOptionsCamera() {
746
- if (
747
- !this.#data.options.camera.value &&
748
- !this.#data.options.camera.changed.pending &&
749
- !this.#data.containers.model.changed.pending &&
750
- !this.#data.containers.environment.changed.pending
751
- ) {
741
+ if (!this.#data.options.camera.value && !this.#data.options.camera.changed.pending && !this.#data.containers.model.changed.pending && !this.#data.containers.environment.changed.pending) {
752
742
  return false;
753
743
  }
754
744
 
755
745
  let camera = this.#data.containers.model.assetContainer?.cameras.find((thisCamera) => thisCamera.name === this.#data.options.camera.value) || this.#data.containers.environment.assetContainer?.cameras.find((thisCamera) => thisCamera.name === this.#data.options.camera.value) || null;
756
746
  if (!camera) {
757
- if (this.#data.options.camera.changed?.oldValue && this.#data.options.camera.changed?.oldValue !== this.#data.options.camera.value) {
758
- camera = this.#data.containers.model.assetContainer?.cameras.find((thisCamera) => thisCamera.name === this.#data.options.camera.changed.oldValue) || this.#data.containers.environment.assetContainer?.cameras.find((thisCamera) => thisCamera.name === this.#data.options.camera.changed.oldValue) || null;
747
+ if (this.#data.options.camera.changed.value && this.#data.options.camera.changed.value !== this.#data.options.camera.value) {
748
+ camera = this.#data.containers.model.assetContainer?.cameras.find((thisCamera) => thisCamera.name === this.#data.options.camera.changed.value) || this.#data.containers.environment.assetContainer?.cameras.find((thisCamera) => thisCamera.name === this.#data.options.camera.changed.value) || null;
759
749
  }
760
750
  if (camera) {
761
- camera.metadata = { locked: this.#data.options.camera.changed.oldLocked };
762
- this.#data.options.camera.value = this.#data.options.camera.changed.oldValue;
763
- this.#data.options.camera.locked = this.#data.options.camera.changed.oldLocked;
751
+ camera.metadata = { locked: this.#data.options.camera.changed.locked };
752
+ this.#data.options.camera.value = this.#data.options.camera.changed.value;
753
+ this.#data.options.camera.locked = this.#data.options.camera.changed.locked;
764
754
  this.#data.options.camera.changed.success = false;
765
- this.#data.options.camera.changed.pending = false;
766
755
  } else {
767
756
  camera = this.#camera;
768
757
  this.#data.options.camera.value = null;
769
758
  this.#data.options.camera.locked = this.#camera.metadata.locked;
770
759
  this.#data.options.camera.changed.success = false;
771
- this.#data.options.camera.changed.pending = false;
772
760
  }
773
761
  } else {
774
762
  camera.metadata = { locked: this.#data.options.camera.locked };
775
763
  if (this.#data.options.camera.changed.pending) {
776
764
  this.#data.options.camera.changed.success = true;
777
- this.#data.options.camera.changed.pending = false;
778
765
  }
779
766
  }
780
767
  if (!this.#data.options.camera.locked && this.#data.options.camera.value !== null) {
@@ -785,27 +772,35 @@ class PrefViewer extends HTMLElement {
785
772
  }
786
773
 
787
774
  #addContainer(container) {
788
- if (container.assetContainer && !container.visible && container.show) {
789
- container.assetContainer.addAllToScene();
790
- container.visible = true;
775
+ if (!container.assetContainer || container.visible || !container.show) {
776
+ return false;
791
777
  }
778
+
779
+ container.assetContainer.addAllToScene();
780
+ container.visible = true;
781
+ return true;
792
782
  }
793
783
 
794
784
  #removeContainer(container) {
795
- if (container.assetContainer && container.visible) {
796
- container.assetContainer.removeAllFromScene();
797
- container.visible = false;
785
+ if (!container.assetContainer || !container.visible) {
786
+ return false;
798
787
  }
788
+
789
+ container.assetContainer.removeAllFromScene();
790
+ container.visible = false;
791
+ return true;
799
792
  }
800
793
 
801
794
  #replaceContainer(container, newAssetContainer) {
802
795
  if (container.assetContainer) {
796
+ this.#removeContainer(container);
803
797
  container.assetContainer.dispose();
804
798
  container.assetContainer = null;
805
799
  }
806
800
  this.#scene.getEngine().releaseEffects();
807
801
  container.assetContainer = newAssetContainer;
808
802
  this.#addContainer(container);
803
+ return true;
809
804
  }
810
805
 
811
806
  async #loadAssetContainer(container) {
@@ -822,11 +817,10 @@ class PrefViewer extends HTMLElement {
822
817
  const object = await loadModel(storage.id, storage.table);
823
818
  source = object.data;
824
819
  if (object.timeStamp === container.timeStamp) {
825
- container.changed.pending = false;
826
- container.changed.success = false;
820
+ container.changed = { pending: false, success: false };
827
821
  return false;
828
822
  } else {
829
- Object.assign(container.changed, { timeStamp: object.timeStamp, size: object.size, success: false, pending: true });
823
+ container.changed = { pending: true, size: object.size, success: false, timeStamp: object.timeStamp };
830
824
  }
831
825
  }
832
826
 
@@ -843,11 +837,10 @@ class PrefViewer extends HTMLElement {
843
837
  });
844
838
  if (!container.changed.pending) {
845
839
  if (container.timeStamp === null && container.size === size) {
846
- container.changed.pending = false;
847
- container.changed.success = false;
840
+ container.changed = { pending: false, success: false };
848
841
  return false;
849
842
  } else {
850
- Object.assign(container.changed, { timeStamp: null, size: size, success: false, pending: true });
843
+ container.changed = { pending: true, size: size, success: false, timeStamp: null };
851
844
  }
852
845
  }
853
846
  } else {
@@ -855,11 +848,10 @@ class PrefViewer extends HTMLElement {
855
848
  extension = extMatch ? `.${extMatch[1].toLowerCase()}` : ".gltf";
856
849
  const [fileSize, fileTimeStamp] = await this.#getServerFileDataHeader(source);
857
850
  if (container.size === fileSize && container.timeStamp === fileTimeStamp) {
858
- container.changed.pending = false;
859
- container.changed.success = false;
851
+ container.changed = { pending: false, success: false };
860
852
  return false;
861
853
  } else {
862
- Object.assign(container.changed, { timeStamp: fileTimeStamp, size: fileSize, success: false, pending: true });
854
+ container.changed = { pending: true, size: fileSize, success: false, timeStamp: fileTimeStamp };
863
855
  }
864
856
  }
865
857
 
@@ -868,7 +860,9 @@ class PrefViewer extends HTMLElement {
868
860
  pluginExtension: extension,
869
861
  pluginOptions: {
870
862
  gltf: {
863
+ compileMaterials: true,
871
864
  loadAllMaterials: true,
865
+ loadOnlyMaterials: container.name === "materials",
872
866
  preprocessUrlAsync: this.#transformUrl,
873
867
  },
874
868
  },
@@ -878,7 +872,6 @@ class PrefViewer extends HTMLElement {
878
872
  }
879
873
 
880
874
  async #loadContainers(loadModel = true, loadEnvironment = true, loadMaterials = true) {
881
- this.#setStatusSceneLoading();
882
875
  this.#engine.stopRenderLoop(this.#renderLoop);
883
876
 
884
877
  const promiseArray = [];
@@ -887,21 +880,19 @@ class PrefViewer extends HTMLElement {
887
880
  promiseArray.push(loadMaterials ? this.#loadAssetContainer(this.#data.containers.materials) : false);
888
881
 
889
882
  Promise.allSettled(promiseArray)
890
- .then(async (values) => {
883
+ .then((values) => {
891
884
  const modelContainer = values[0];
892
885
  const environmentContainer = values[1];
893
886
  const materialsContainer = values[2];
894
887
 
895
- this.#removeContainer(this.#data.containers.model);
896
- this.#removeContainer(this.#data.containers.environment);
897
- this.#removeContainer(this.#data.containers.materials);
898
-
899
888
  if (modelContainer.status === "fulfilled" && modelContainer.value) {
900
889
  modelContainer.value.lights = [];
901
890
  this.#replaceContainer(this.#data.containers.model, modelContainer.value);
902
891
  this.#storeChangedFlagsForContainer(this.#data.containers.model, true);
903
892
  } else {
904
- this.#addContainer(this.#data.containers.model);
893
+ if (this.#data.containers.model.assetContainer && this.#data.containers.model.show !== this.#data.containers.model.visible) {
894
+ this.#data.containers.model.show ? this.#addContainer(this.#data.containers.model) : this.#removeContainer(this.#data.containers.model);
895
+ }
905
896
  this.#storeChangedFlagsForContainer(this.#data.containers.model, false);
906
897
  }
907
898
 
@@ -909,7 +900,9 @@ class PrefViewer extends HTMLElement {
909
900
  this.#replaceContainer(this.#data.containers.environment, environmentContainer.value);
910
901
  this.#storeChangedFlagsForContainer(this.#data.containers.environment, true);
911
902
  } else {
912
- this.#addContainer(this.#data.containers.environment);
903
+ if (this.#data.containers.environment.assetContainer && this.#data.containers.environment.show !== this.#data.containers.environment.visible) {
904
+ this.#data.containers.environment.show ? this.#addContainer(this.#data.containers.environment) : this.#removeContainer(this.#data.containers.environment);
905
+ }
913
906
  this.#storeChangedFlagsForContainer(this.#data.containers.environment, false);
914
907
  }
915
908
 
@@ -917,7 +910,6 @@ class PrefViewer extends HTMLElement {
917
910
  this.#replaceContainer(this.#data.containers.materials, materialsContainer.value);
918
911
  this.#storeChangedFlagsForContainer(this.#data.containers.materials, true);
919
912
  } else {
920
- this.#addContainer(this.#data.containers.materials);
921
913
  this.#storeChangedFlagsForContainer(this.#data.containers.materials, false);
922
914
  }
923
915
 
@@ -937,24 +929,51 @@ class PrefViewer extends HTMLElement {
937
929
  })
938
930
  );
939
931
  })
940
- .finally(() => {
932
+ .finally(async () => {
941
933
  this.#setMaxSimultaneousLights();
942
934
  this.#initShadows();
943
- this.#setStatusSceneLoaded();
944
- this.#engine.runRenderLoop(this.#renderLoop);
935
+ await this.#setStatusLoaded();
945
936
  });
946
937
  }
947
938
 
948
- // Public Methods
949
- loadConfig(config) {
950
- config = typeof config === "string" ? JSON.parse(config) : config;
951
- if (!config) {
939
+ // Tasks
940
+ #addTaskToQueue(value, type) {
941
+ this.#taskQueue.push(new PrefViewerTask(value, type));
942
+ if (this.initialized && !this.loading) {
943
+ this.#processNextTask();
944
+ }
945
+ }
946
+
947
+ #processNextTask() {
948
+ if (!this.#taskQueue.length) {
952
949
  return false;
953
950
  }
951
+ const task = this.#taskQueue[0];
952
+ this.#taskQueue.shift();
953
+ switch (task.type) {
954
+ case PrefViewerTask.Types.Config:
955
+ this.#processConfig(task.value);
956
+ break;
957
+ case PrefViewerTask.Types.Model:
958
+ this.#processModel(task.value);
959
+ break;
960
+ case PrefViewerTask.Types.Environment:
961
+ this.#processEnvironment(task.value);
962
+ break;
963
+ case PrefViewerTask.Types.Materials:
964
+ this.#processMaterials(task.value);
965
+ break;
966
+ case PrefViewerTask.Types.Options:
967
+ this.#processOptions(task.value);
968
+ break;
969
+ }
970
+ }
971
+
972
+ #processConfig(config) {
973
+ this.#setStatusLoading();
954
974
 
955
975
  // Containers
956
976
  const loadModel = !!config.model?.storage;
957
- // CHANGED: marcar pending, no boolean
958
977
  this.#data.containers.model.changed.pending = loadModel;
959
978
  this.#data.containers.model.changed.success = false;
960
979
  this.#data.containers.model.changed.storage = this.#data.containers.model.storage;
@@ -980,15 +999,49 @@ class PrefViewer extends HTMLElement {
980
999
  this.#checkMaterialsChanged(config.options);
981
1000
  }
982
1001
 
983
- this.initialized && this.#loadContainers(loadModel, loadEnvironment, loadMaterials);
1002
+ this.#loadContainers(loadModel, loadEnvironment, loadMaterials);
984
1003
  }
985
1004
 
986
- setOptions(options) {
987
- if (!options) {
988
- return false;
989
- }
1005
+ #processModel(model) {
1006
+ this.#setStatusLoading();
1007
+
1008
+ const loadModel = !!model.storage;
1009
+ this.#data.containers.model.changed.pending = loadModel;
1010
+ this.#data.containers.model.changed.success = false;
1011
+ this.#data.containers.model.changed.storage = this.#data.containers.model.storage;
1012
+ this.#data.containers.model.storage = loadModel ? model.storage : this.#data.containers.model.storage;
1013
+ this.#data.containers.model.show = model.visible !== undefined ? model.visible : this.#data.containers.model.show;
1014
+
1015
+ this.initialized && this.#loadContainers(loadModel, false, false);
1016
+ }
1017
+
1018
+ #processEnvironment(environment) {
1019
+ this.#setStatusLoading();
1020
+
1021
+ const loadEnvironment = !!environment.storage;
1022
+ this.#data.containers.environment.changed.pending = loadEnvironment;
1023
+ this.#data.containers.environment.changed.success = false;
1024
+ this.#data.containers.environment.changed.storage = this.#data.containers.environment.storage;
1025
+ this.#data.containers.environment.storage = loadEnvironment ? environment.storage : this.#data.containers.environment.storage;
1026
+ this.#data.containers.environment.show = environment.visible !== undefined ? environment.visible : this.#data.containers.environment.show;
1027
+
1028
+ this.#loadContainers(false, loadEnvironment, false);
1029
+ }
1030
+
1031
+ #processMaterials(materials) {
1032
+ this.#setStatusLoading();
1033
+
1034
+ const loadMaterials = !!materials.storage;
1035
+ this.#data.containers.materials.changed.pending = loadMaterials;
1036
+ this.#data.containers.materials.changed.success = false;
1037
+ this.#data.containers.materials.changed.storage = this.#data.containers.materials.storage;
1038
+ this.#data.containers.materials.storage = loadMaterials ? materials.storage : this.#data.containers.materials.storage;
990
1039
 
991
- this.#setStatusOptionsLoading();
1040
+ this.#loadContainers(false, false, loadMaterials);
1041
+ }
1042
+
1043
+ async #processOptions(options) {
1044
+ this.#setStatusLoading();
992
1045
 
993
1046
  let someSetted = false;
994
1047
  if (this.#checkCameraChanged(options)) {
@@ -997,24 +1050,27 @@ class PrefViewer extends HTMLElement {
997
1050
  if (this.#checkMaterialsChanged(options)) {
998
1051
  someSetted = someSetted || this.#setOptionsMaterials();
999
1052
  }
1000
-
1001
- this.#setStatusOptionsLoaded();
1053
+
1054
+ await this.#setStatusLoaded();
1002
1055
 
1003
1056
  return someSetted;
1004
1057
  }
1005
1058
 
1059
+ // Public Methods
1060
+ loadConfig(config) {
1061
+ config = typeof config === "string" ? JSON.parse(config) : config;
1062
+ if (!config) {
1063
+ return false;
1064
+ }
1065
+ this.#addTaskToQueue(config, "config");
1066
+ }
1067
+
1006
1068
  loadModel(model) {
1007
1069
  model = typeof model === "string" ? JSON.parse(model) : model;
1008
1070
  if (!model) {
1009
1071
  return false;
1010
1072
  }
1011
- const loadModel = !!model.storage;
1012
- this.#data.containers.model.changed.pending = loadModel;
1013
- this.#data.containers.model.changed.success = false;
1014
- this.#data.containers.model.changed.storage = this.#data.containers.model.storage;
1015
- this.#data.containers.model.storage = loadModel ? model.storage : this.#data.containers.model.storage;
1016
- this.#data.containers.model.show = model.visible !== undefined ? model.visible : this.#data.containers.model.show;
1017
- this.initialized && this.#loadContainers(loadModel, false, false);
1073
+ this.#addTaskToQueue(model, "model");
1018
1074
  }
1019
1075
 
1020
1076
  loadScene(scene) {
@@ -1022,13 +1078,7 @@ class PrefViewer extends HTMLElement {
1022
1078
  if (!scene) {
1023
1079
  return false;
1024
1080
  }
1025
- const loadEnvironment = !!scene.storage;
1026
- this.#data.containers.environment.changed.pending = loadEnvironment;
1027
- this.#data.containers.environment.changed.success = false;
1028
- this.#data.containers.environment.changed.storage = this.#data.containers.environment.storage;
1029
- this.#data.containers.environment.storage = loadEnvironment ? scene.storage : this.#data.containers.environment.storage;
1030
- this.#data.containers.environment.show = scene.visible !== undefined ? scene.visible : this.#data.containers.environment.show;
1031
- this.initialized && this.#loadContainers(false, loadEnvironment, false);
1081
+ this.#addTaskToQueue(scene, "environment");
1032
1082
  }
1033
1083
 
1034
1084
  loadMaterials(materials) {
@@ -1036,12 +1086,15 @@ class PrefViewer extends HTMLElement {
1036
1086
  if (!materials) {
1037
1087
  return false;
1038
1088
  }
1039
- const loadMaterials = !!materials.storage;
1040
- this.#data.containers.materials.changed.pending = loadMaterials;
1041
- this.#data.containers.materials.changed.success = false;
1042
- this.#data.containers.materials.changed.storage = this.#data.containers.materials.storage;
1043
- this.#data.containers.materials.storage = loadMaterials ? materials.storage : this.#data.containers.materials.storage;
1044
- this.initialized && this.#loadContainers(false, false, loadMaterials);
1089
+ this.#addTaskToQueue(materials, "materials");
1090
+ }
1091
+
1092
+ setOptions(options) {
1093
+ options = typeof options === "string" ? JSON.parse(options) : options;
1094
+ if (!options) {
1095
+ return false;
1096
+ }
1097
+ this.#addTaskToQueue(options, "options");
1045
1098
  }
1046
1099
 
1047
1100
  showModel() {