@preference-sl/pref-viewer 2.10.0-beta.14 → 2.10.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.
Files changed (2) hide show
  1. package/package.json +1 -1
  2. package/src/index.js +182 -45
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@preference-sl/pref-viewer",
3
- "version": "2.10.0-beta.14",
3
+ "version": "2.10.0-beta.16",
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
@@ -47,7 +47,9 @@ import { DracoCompression } from "@babylonjs/core/Meshes/Compression/dracoCompre
47
47
  import { initDb, loadModel } from "./gltf-storage.js";
48
48
 
49
49
  class PrefViewer extends HTMLElement {
50
- #initialized = false;
50
+ initialized = false;
51
+ loaded = false;
52
+ loading = false;
51
53
 
52
54
  #data = {
53
55
  containers: {
@@ -162,7 +164,7 @@ class PrefViewer extends HTMLElement {
162
164
  break;
163
165
  case "show-model":
164
166
  data = value.toLowerCase?.() === "true";
165
- if (this.#initialized) {
167
+ if (this.initialized) {
166
168
  data ? this.showModel() : this.hideModel();
167
169
  } else {
168
170
  this.#data.containers.model.show = data;
@@ -170,7 +172,7 @@ class PrefViewer extends HTMLElement {
170
172
  break;
171
173
  case "show-scene":
172
174
  data = value.toLowerCase?.() === "true";
173
- if (this.#initialized) {
175
+ if (this.initialized) {
174
176
  data ? this.showScene() : this.hideScene();
175
177
  } else {
176
178
  this.#data.containers.environment.show = data;
@@ -184,18 +186,19 @@ class PrefViewer extends HTMLElement {
184
186
  const error = 'PrefViewer: provide "models" as array of model and environment';
185
187
  console.error(error);
186
188
  this.dispatchEvent(
187
- new CustomEvent("model-error", {
188
- detail: { error: new Error(error) },
189
+ new CustomEvent("scene-error", {
189
190
  bubbles: true,
191
+ cancelable: false,
190
192
  composed: true,
193
+ detail: { error: new Error(error) },
191
194
  })
192
195
  );
193
196
  return false;
194
197
  }
195
198
 
196
199
  this.#initializeBabylon();
200
+ this.initialized = true;
197
201
  this.#loadContainers(true, true, true);
198
- this.#initialized = true;
199
202
  }
200
203
 
201
204
  disconnectedCallback() {
@@ -225,14 +228,115 @@ class PrefViewer extends HTMLElement {
225
228
  this.shadowRoot.append(this.#wrapper);
226
229
  }
227
230
 
231
+ #setStatusSceneLoading() {
232
+ this.loaded = false;
233
+ this.loading = true;
234
+ if (this.hasAttribute("loaded")) {
235
+ this.removeAttribute("loaded");
236
+ }
237
+ this.setAttribute("loading", "");
238
+ this.dispatchEvent(
239
+ new CustomEvent("scene-loading", {
240
+ bubbles: true,
241
+ cancelable: false,
242
+ composed: true,
243
+ })
244
+ );
245
+ }
246
+
247
+ #setStatusSceneLoaded() {
248
+ this.loaded = true;
249
+ this.loading = false;
250
+
251
+ const toLoadDetail = {
252
+ container_model: !!this.#data.containers.model.changed,
253
+ container_environment: !!this.#data.containers.environment.changed,
254
+ container_materials: !!this.#data.containers.materials.changed,
255
+ options_camera: !!this.#data.options.camera.changed,
256
+ options_inneWallMaterial: !!this.#data.options.materials.innerWall.changed,
257
+ options_outerWallMaterial: !!this.#data.options.materials.outerWall.changed,
258
+ options_innerFloorMaterial: !!this.#data.options.materials.innerFloor.changed,
259
+ options_outerFloorMaterial: !!this.#data.options.materials.outerFloor.changed,
260
+ };
261
+ const loadedDetail = {
262
+ container_model: !!this.#data.containers.model.changed?.success,
263
+ container_environment: !!this.#data.containers.environment.changed?.success,
264
+ container_materials: !!this.#data.containers.materials.changed?.success,
265
+ options_camera: !!this.#data.options.camera.changed?.success,
266
+ options_inneWallMaterial: !!this.#data.options.materials.innerWall.changed?.success,
267
+ options_outerWallMaterial: !!this.#data.options.materials.outerWall.changed?.success,
268
+ options_innerFloorMaterial: !!this.#data.options.materials.innerFloor.changed?.success,
269
+ options_outerFloorMaterial: !!this.#data.options.materials.outerFloor.changed?.success,
270
+ };
271
+
272
+ const detail = {
273
+ tried: toLoadDetail,
274
+ success: loadedDetail,
275
+ };
276
+
277
+ if (this.hasAttribute("loading")) {
278
+ this.removeAttribute("loading");
279
+ }
280
+ this.setAttribute("loaded", "");
281
+ this.dispatchEvent(
282
+ new CustomEvent("scene-loaded", {
283
+ bubbles: true,
284
+ cancelable: false,
285
+ composed: true,
286
+ detail: detail,
287
+ })
288
+ );
289
+ }
290
+
291
+ #setStatusOptionsLoading() {
292
+ this.dispatchEvent(
293
+ new CustomEvent("options-loading", {
294
+ bubbles: true,
295
+ cancelable: false,
296
+ composed: true,
297
+ })
298
+ );
299
+ }
300
+
301
+ #setStatusOptionsLoaded() {
302
+
303
+ const toLoadDetail = {
304
+ inneWallMaterial: !!this.#data.options.materials.innerWall.changed,
305
+ outerWallMaterial: !!this.#data.options.materials.outerWall.changed,
306
+ innerFloorMaterial: !!this.#data.options.materials.innerFloor.changed,
307
+ outerFloorMaterial: !!this.#data.options.materials.outerFloor.changed,
308
+ };
309
+ const loadedDetail = {
310
+ inneWallMaterial: !!this.#data.options.materials.innerWall.changed?.success,
311
+ outerWallMaterial: !!this.#data.options.materials.outerWall.changed?.success,
312
+ innerFloorMaterial: !!this.#data.options.materials.innerFloor.changed?.success,
313
+ _outerFloorMaterial: !!this.#data.options.materials.outerFloor.changed?.success,
314
+ };
315
+
316
+ const detail = {
317
+ tried: toLoadDetail,
318
+ success: loadedDetail,
319
+ };
320
+
321
+ this.dispatchEvent(
322
+ new CustomEvent("options-loaded", {
323
+ bubbles: true,
324
+ cancelable: false,
325
+ composed: true,
326
+ detail: detail,
327
+ })
328
+ );
329
+ }
330
+
228
331
  // Data
229
332
  #checkCameraChanged(options) {
230
333
  if (!options || !options.camera) {
231
334
  return false;
232
335
  }
233
- this.#data.options.camera.changed = options.camera && options.camera !== this.#data.options.camera.value ? true : false;
234
- this.#data.options.camera.value = this.#data.options.camera.changed ? options.camera : this.#data.options.camera.value;
235
- return this.#data.options.camera.changed;
336
+ const cameraChanged = options.camera && options.camera !== this.#data.options.camera.value ? true : false
337
+ this.#data.options.camera.changed = cameraChanged ? { oldValue: this.#data.options.camera.value, success: false } : false;
338
+ this.#data.options.camera.value = cameraChanged ? options.camera : this.#data.options.camera.value;
339
+ return cameraChanged;
236
340
  }
237
341
 
238
342
  #checkMaterialsChanged(options) {
@@ -242,8 +346,9 @@ class PrefViewer extends HTMLElement {
242
346
  let someChanged = false;
243
347
  Object.keys(this.#data.options.materials).forEach((material) => {
244
348
  const key = `${material}Material`;
245
- this.#data.options.materials[material].changed = options[key] && options[key] !== this.#data.options.materials[material].value ? true : false;
246
- this.#data.options.materials[material].value = this.#data.options.materials[material].changed ? options[key] : this.#data.options.materials[material].value;
349
+ const materialChanged = options[key] && options[key] !== this.#data.options.materials[material].value ? true : false;
350
+ this.#data.options.materials[material].changed = materialChanged ? { oldValue: this.#data.options.materials[material].value, success: false } : false;
351
+ this.#data.options.materials[material].value = materialChanged ? options[key] : this.#data.options.materials[material].value;
247
352
  someChanged = someChanged || this.#data.options.materials[material].changed;
248
353
  });
249
354
  return someChanged;
@@ -252,6 +357,7 @@ class PrefViewer extends HTMLElement {
252
357
  #storeChangedFlagsForContainer(container) {
253
358
  container.timestamp = container.changed.timestamp;
254
359
  container.size = container.changed.size;
360
+ container.changed.success = true;
255
361
  }
256
362
 
257
363
  #resetChangedFlags() {
@@ -340,8 +446,8 @@ class PrefViewer extends HTMLElement {
340
446
  this.#camera.lowerRadiusLimit = 5;
341
447
  this.#camera.upperRadiusLimit = 20;
342
448
  this.#camera.metadata = { locked: false }
343
- this.#camera = this.#camera;
344
449
  this.#camera.attachControl(this.#canvas, true);
450
+ this.#scene.activeCamera = this.#camera;
345
451
  }
346
452
 
347
453
  #createLights() {
@@ -398,13 +504,13 @@ class PrefViewer extends HTMLElement {
398
504
  if (xhr.status === 200) {
399
505
  const size = parseInt(xhr.getResponseHeader("Content-Length"));
400
506
  const timestamp = new Date(xhr.getResponseHeader("Last-Modified")).toISOString();
401
- resolve(size, timestamp);
507
+ resolve([size, timestamp]);
402
508
  } else {
403
- resolve(0, null);
509
+ resolve([0, null]);
404
510
  }
405
511
  };
406
512
  xhr.onerror = () => {
407
- resolve(0, null);
513
+ resolve([0, null]);
408
514
  };
409
515
  xhr.send();
410
516
  });
@@ -458,6 +564,7 @@ class PrefViewer extends HTMLElement {
458
564
  }
459
565
 
460
566
  #setOptionsMaterial(optionMaterial) {
567
+ debugger;
461
568
  if (!optionMaterial || !optionMaterial.prefix || !optionMaterial.value) {
462
569
  return false;
463
570
  }
@@ -468,10 +575,10 @@ class PrefViewer extends HTMLElement {
468
575
  }
469
576
 
470
577
  const containers = [];
471
- if (this.#data.containers.model.assetContainer && (this.#data.containers.model.assetContainer.changed || optionMaterial.changed)) {
578
+ if (this.#data.containers.model.assetContainer && (this.#data.containers.model.changed || this.#data.containers.materials.changed || optionMaterial.changed)) {
472
579
  containers.push(this.#data.containers.model.assetContainer);
473
580
  }
474
- if (this.#data.containers.environment.assetContainer && (this.#data.containers.environment.assetContainer.changed || optionMaterial.changed)) {
581
+ if (this.#data.containers.environment.assetContainer && (this.#data.containers.environment.changed || this.#data.containers.materials.changed || optionMaterial.changed)) {
475
582
  containers.push(this.#data.containers.environment.assetContainer);
476
583
  }
477
584
  if (containers.length === 0) {
@@ -488,6 +595,12 @@ class PrefViewer extends HTMLElement {
488
595
  })
489
596
  );
490
597
 
598
+ if (someSetted) {
599
+ optionMaterial.changed.success = true;
600
+ } else {
601
+ optionMaterial.value = optionMaterial.changed.oldValue;
602
+ }
603
+
491
604
  return someSetted;
492
605
  }
493
606
 
@@ -501,21 +614,32 @@ class PrefViewer extends HTMLElement {
501
614
  }
502
615
 
503
616
  #setOptionsCamera() {
504
- if (!this.#data.options.camera.value || (!this.#data.options.camera.changed && !this.#data.containers.model.assetContainer.changed)) {
617
+ if (!this.#data.options.camera.value || (!this.#data.options.camera.changed && !this.#data.containers.model.changed && !this.#data.containers.environment.changed)) {
505
618
  return false;
506
619
  }
507
620
 
508
- let camera = this.#data.containers.model.assetContainer?.cameras.find((cam) => cam.name === this.#data.options.camera.value) || null;
621
+ 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;
509
622
  if (!camera) {
510
- return false;
623
+ if (this.#data.options.camera.changed?.oldValue && this.#data.options.camera.changed?.oldValue !== this.#data.options.camera.value) {
624
+ 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 === his.#data.options.camera.changed.oldValue) || null;
625
+ }
626
+ if (camera){
627
+ camera.metadata = { locked: this.#data.options.camera.changed.oldLocked };
628
+ this.#data.options.camera.value = this.#data.options.camera.changed.oldValue;
629
+ this.#data.options.camera.locked = this.#data.options.camera.changed.oldLocked;
630
+ } else {
631
+ camera = this.#camera;
632
+ this.#data.options.camera.value = null;
633
+ this.#data.options.camera.locked = this.#camera.metadata.locked;
634
+ }
635
+ this.#data.options.camera.changed.success = false;
636
+ } else {
637
+ camera.metadata = { locked: this.#data.options.camera.locked };
511
638
  }
512
-
513
- camera.metadata = { locked: this.#data.options.camera.locked };
514
- if (!this.#data.options.camera.locked) {
639
+ if (!this.#data.options.camera.locked && this.#data.options.camera.value !== null) {
515
640
  camera.attachControl(this.#canvas, true);
516
641
  }
517
642
  this.#scene.activeCamera = camera;
518
-
519
643
  return true;
520
644
  }
521
645
 
@@ -559,7 +683,7 @@ class PrefViewer extends HTMLElement {
559
683
  if (object.timestamp === container.timestamp) {
560
684
  return false;
561
685
  } else {
562
- container.changed = { timestamp: object.timestamp, size: object.size };
686
+ container.changed = { timestamp: object.timestamp, size: object.size, success: false };
563
687
  }
564
688
  }
565
689
 
@@ -578,17 +702,17 @@ class PrefViewer extends HTMLElement {
578
702
  if (container.timestamp === null && container.size === size) {
579
703
  return false;
580
704
  } else {
581
- container.changed = { timestamp: null, size: size };
705
+ container.changed = { timestamp: null, size: size, success: false };
582
706
  }
583
707
  }
584
708
  } else {
585
709
  const extMatch = source.match(/\.(gltf|glb)(\?|#|$)/i);
586
710
  extension = extMatch ? `.${extMatch[1].toLowerCase()}` : ".gltf";
587
- const { fileSize, fileTimestamp } = await this.#getServerFileDataHeader(source);
588
- if (container.timestamp === fileTimestamp && container.size === fileSize) {
711
+ const [fileSize, fileTimestamp ] = await this.#getServerFileDataHeader(source);
712
+ if (container.size === fileSize && container.timestamp === fileTimestamp) {
589
713
  return false;
590
714
  } else {
591
- container.changed = { timestamp: fileTimestamp, size: fileSize };
715
+ container.changed = { timestamp: fileTimestamp, size: fileSize, success: false };
592
716
  }
593
717
  }
594
718
 
@@ -605,11 +729,25 @@ class PrefViewer extends HTMLElement {
605
729
  return LoadAssetContainerAsync(file || source, this.#scene, options);
606
730
  }
607
731
 
608
- async #loadContainers(loadModel = true, loadEnvironment = true, loadMaterials = true) {
732
+ async #loadContainers(loadModel = true, loadEnvironment = true, loadMaterials = true) {
609
733
  const promiseArray = [];
610
734
  promiseArray.push(loadModel ? this.#loadAssetContainer(this.#data.containers.model) : false);
611
735
  promiseArray.push(loadEnvironment ? this.#loadAssetContainer(this.#data.containers.environment) : false);
612
736
  promiseArray.push(loadMaterials ? this.#loadAssetContainer(this.#data.containers.materials) : false);
737
+ debugger;
738
+ const loadingDetail = {
739
+ model: !!this.#data.containers.model.changed,
740
+ environment: !!this.#data.containers.environment.changed,
741
+ materials: !!this.#data.containers.materials.changed,
742
+ options: {
743
+ camera: !!this.#data.options.camera.changed,
744
+ inneWallMaterial: !!this.#data.options.materials.innerWall.changed,
745
+ outerWallMaterial: !!this.#data.options.materials.outerWall.changed,
746
+ innerFloorMaterial: !!this.#data.options.materials.innerFloor.changed,
747
+ outerFloorMaterial: !!this.#data.options.materials.outerFloor.changed,
748
+ },
749
+ };
750
+ this.#setStatusSceneLoading(loadingDetail);
613
751
 
614
752
  Promise.allSettled(promiseArray)
615
753
  .then(async (values) => {
@@ -639,24 +777,18 @@ class PrefViewer extends HTMLElement {
639
777
  this.#setOptionsMaterials();
640
778
  this.#setOptionsCamera();
641
779
  this.#setVisibilityOfWallAndFloorInModel();
642
-
780
+ this.#setStatusSceneLoaded();
643
781
  this.#resetChangedFlags();
644
-
645
- this.dispatchEvent(
646
- new CustomEvent("model-loaded", {
647
- detail: { success: "" },
648
- bubbles: true,
649
- composed: true,
650
- })
651
- );
652
782
  })
653
783
  .catch((error) => {
784
+ this.loaded = true;
654
785
  console.error("PrefViewer: failed to load model", error);
655
786
  this.dispatchEvent(
656
- new CustomEvent("model-error", {
657
- detail: { error: error },
787
+ new CustomEvent("scene-error", {
658
788
  bubbles: true,
789
+ cancelable: false,
659
790
  composed: true,
791
+ detail: { error: error },
660
792
  })
661
793
  );
662
794
  });
@@ -682,13 +814,16 @@ class PrefViewer extends HTMLElement {
682
814
  this.#checkMaterialsChanged(config.options);
683
815
  }
684
816
 
685
- this.#initialized && this.#loadContainers(true, true, true);
817
+ this.initialized && this.#loadContainers(true, true, true);
686
818
  }
687
819
 
688
820
  setOptions(options) {
689
821
  if (!options) {
690
822
  return false;
691
823
  }
824
+
825
+ this.#setStatusOptionsLoading();
826
+
692
827
  let someSetted = false;
693
828
  if (this.#checkCameraChanged(options)) {
694
829
  someSetted = someSetted || this.#setOptionsCamera();
@@ -696,8 +831,10 @@ class PrefViewer extends HTMLElement {
696
831
  if (this.#checkMaterialsChanged(options)) {
697
832
  someSetted = someSetted || this.#setOptionsMaterials();
698
833
  }
834
+
835
+ this.#setStatusOptionsLoaded();
699
836
  this.#resetChangedFlags();
700
- debugger;
837
+
701
838
  return someSetted;
702
839
  }
703
840
 
@@ -708,7 +845,7 @@ class PrefViewer extends HTMLElement {
708
845
  }
709
846
  this.#data.containers.model.storage = model.storage || null;
710
847
  this.#data.containers.model.show = model.visible !== undefined ? model.visible : this.#data.containers.model.show;
711
- this.#initialized && this.#loadContainers(true, false, false);
848
+ this.initialized && this.#loadContainers(true, false, false);
712
849
  }
713
850
 
714
851
  loadScene(scene) {
@@ -718,7 +855,7 @@ class PrefViewer extends HTMLElement {
718
855
  }
719
856
  this.#data.containers.environment.storage = scene.storage || null;
720
857
  this.#data.containers.environment.show = scene.visible !== undefined ? scene.visible : this.#data.containers.environment.show;
721
- this.#initialized && this.#loadContainers(false, true, false);
858
+ this.initialized && this.#loadContainers(false, true, false);
722
859
  }
723
860
 
724
861
  showModel() {