@preference-sl/pref-viewer 2.10.0-beta.3 → 2.10.0-beta.5
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/index.js +315 -85
package/package.json
CHANGED
package/src/index.js
CHANGED
|
@@ -49,18 +49,68 @@ import { initDb, loadModel } from "./gltf-storage.js";
|
|
|
49
49
|
class PrefViewer extends HTMLElement {
|
|
50
50
|
#initialized = false;
|
|
51
51
|
|
|
52
|
-
#
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
52
|
+
#data = {
|
|
53
|
+
containers: {
|
|
54
|
+
model: {
|
|
55
|
+
name: "model",
|
|
56
|
+
container: null,
|
|
57
|
+
show: true,
|
|
58
|
+
storage: null,
|
|
59
|
+
visible: false,
|
|
60
|
+
size: null,
|
|
61
|
+
timestamp: null,
|
|
62
|
+
changed: false,
|
|
63
|
+
},
|
|
64
|
+
environment: {
|
|
65
|
+
name: "environment",
|
|
66
|
+
container: null,
|
|
67
|
+
show: true,
|
|
68
|
+
storage: null,
|
|
69
|
+
visible: false,
|
|
70
|
+
size: null,
|
|
71
|
+
timestamp: null,
|
|
72
|
+
changed: false,
|
|
73
|
+
},
|
|
74
|
+
materials: {
|
|
75
|
+
name: "materials",
|
|
76
|
+
container: null,
|
|
77
|
+
storage: null,
|
|
78
|
+
show: true,
|
|
79
|
+
visible: false,
|
|
80
|
+
size: null,
|
|
81
|
+
timestamp: null,
|
|
82
|
+
changed: false,
|
|
83
|
+
},
|
|
84
|
+
},
|
|
85
|
+
options: {
|
|
86
|
+
camera: {
|
|
87
|
+
value: null,
|
|
88
|
+
locked: true,
|
|
89
|
+
changed: false,
|
|
90
|
+
},
|
|
91
|
+
materials: {
|
|
92
|
+
innerWall: {
|
|
93
|
+
value: null,
|
|
94
|
+
prefix: "innerWall",
|
|
95
|
+
changed: false,
|
|
96
|
+
},
|
|
97
|
+
outerWall: {
|
|
98
|
+
value: null,
|
|
99
|
+
prefix: "outerWall",
|
|
100
|
+
changed: false,
|
|
101
|
+
},
|
|
102
|
+
innerFloor: {
|
|
103
|
+
value: null,
|
|
104
|
+
prefix: "innerFloor",
|
|
105
|
+
changed: false,
|
|
106
|
+
},
|
|
107
|
+
outerFloor: {
|
|
108
|
+
value: null,
|
|
109
|
+
prefix: "outerFloor",
|
|
110
|
+
changed: false,
|
|
111
|
+
},
|
|
112
|
+
},
|
|
113
|
+
},
|
|
64
114
|
};
|
|
65
115
|
|
|
66
116
|
// DOM elements
|
|
@@ -115,7 +165,7 @@ class PrefViewer extends HTMLElement {
|
|
|
115
165
|
if (this.#initialized) {
|
|
116
166
|
data ? this.showModel() : this.hideModel();
|
|
117
167
|
} else {
|
|
118
|
-
this.#model.show = data;
|
|
168
|
+
this.#data.containers.model.show = data;
|
|
119
169
|
}
|
|
120
170
|
break;
|
|
121
171
|
case "show-scene":
|
|
@@ -123,7 +173,7 @@ class PrefViewer extends HTMLElement {
|
|
|
123
173
|
if (this.#initialized) {
|
|
124
174
|
data ? this.showScene() : this.hideScene();
|
|
125
175
|
} else {
|
|
126
|
-
this.#environment.show = data;
|
|
176
|
+
this.#data.containers.environment.show = data;
|
|
127
177
|
}
|
|
128
178
|
break;
|
|
129
179
|
}
|
|
@@ -144,7 +194,7 @@ class PrefViewer extends HTMLElement {
|
|
|
144
194
|
}
|
|
145
195
|
|
|
146
196
|
this.#initializeBabylon();
|
|
147
|
-
this.#loadContainers(true, true);
|
|
197
|
+
this.#loadContainers(true, true, true);
|
|
148
198
|
this.#initialized = true;
|
|
149
199
|
}
|
|
150
200
|
|
|
@@ -174,8 +224,43 @@ class PrefViewer extends HTMLElement {
|
|
|
174
224
|
this.#wrapper.appendChild(this.#canvas);
|
|
175
225
|
this.shadowRoot.append(this.#wrapper);
|
|
176
226
|
}
|
|
177
|
-
|
|
178
|
-
//
|
|
227
|
+
|
|
228
|
+
// Data
|
|
229
|
+
#checkCameraChanged(options) {
|
|
230
|
+
if (!options || !options.camera) {
|
|
231
|
+
return false;
|
|
232
|
+
}
|
|
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;
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
#checkMaterialsChanged(options) {
|
|
239
|
+
if (!options) {
|
|
240
|
+
return false;
|
|
241
|
+
}
|
|
242
|
+
let someChanged = false;
|
|
243
|
+
Object.keys(this.#data.options.materials).forEach((material) => {
|
|
244
|
+
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;
|
|
247
|
+
someChanged = someChanged || this.#data.options.materials[material].changed;
|
|
248
|
+
});
|
|
249
|
+
return someChanged;
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
#storeChangedFlagsForContainer(container) {
|
|
253
|
+
container.timestamp = container.changed.timestamp;
|
|
254
|
+
container.size = container.changed.size;
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
#resetChangedFlags() {
|
|
258
|
+
Object.values(this.#data.containers).forEach((container) => (container.changed = false));
|
|
259
|
+
Object.values(this.#data.options.materials).forEach((material) => (material.changed = false));
|
|
260
|
+
this.#data.options.camera.changed = false;
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
// Babylon.js
|
|
179
264
|
async #initializeBabylon() {
|
|
180
265
|
this.#engine = new Engine(this.#canvas, true, { alpha: true });
|
|
181
266
|
this.#scene = new Scene(this.#engine);
|
|
@@ -183,15 +268,14 @@ class PrefViewer extends HTMLElement {
|
|
|
183
268
|
this.#createCamera();
|
|
184
269
|
this.#createLights();
|
|
185
270
|
this.#setupInteraction();
|
|
186
|
-
|
|
271
|
+
|
|
187
272
|
this.#engine.runRenderLoop(() => this.#scene && this.#scene.render());
|
|
188
273
|
this.#canvasResizeObserver.observe(this.#canvas);
|
|
189
274
|
|
|
190
275
|
await this.#createXRExperience();
|
|
191
|
-
|
|
192
276
|
}
|
|
193
277
|
|
|
194
|
-
addStylesToARButton(){
|
|
278
|
+
addStylesToARButton() {
|
|
195
279
|
const css = '.babylonVRicon { color: #868686; border-color: #868686; border-style: solid; margin-left: 10px; height: 50px; width: 80px; background-color: rgba(51,51,51,0.7); background-image: url(data:image/svg+xml;charset=UTF-8,%3Csvg%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20width%3D%222048%22%20height%3D%221152%22%20viewBox%3D%220%200%202048%201152%22%20version%3D%221.1%22%3E%3Cpath%20transform%3D%22rotate%28180%201024%2C576.0000000000001%29%22%20d%3D%22m1109%2C896q17%2C0%2030%2C-12t13%2C-30t-12.5%2C-30.5t-30.5%2C-12.5l-170%2C0q-18%2C0%20-30.5%2C12.5t-12.5%2C30.5t13%2C30t30%2C12l170%2C0zm-85%2C256q59%2C0%20132.5%2C-1.5t154.5%2C-5.5t164.5%2C-11.5t163%2C-20t150%2C-30t124.5%2C-41.5q23%2C-11%2042%2C-24t38%2C-30q27%2C-25%2041%2C-61.5t14%2C-72.5l0%2C-257q0%2C-123%20-47%2C-232t-128%2C-190t-190%2C-128t-232%2C-47l-81%2C0q-37%2C0%20-68.5%2C14t-60.5%2C34.5t-55.5%2C45t-53%2C45t-53%2C34.5t-55.5%2C14t-55.5%2C-14t-53%2C-34.5t-53%2C-45t-55.5%2C-45t-60.5%2C-34.5t-68.5%2C-14l-81%2C0q-123%2C0%20-232%2C47t-190%2C128t-128%2C190t-47%2C232l0%2C257q0%2C68%2038%2C115t97%2C73q54%2C24%20124.5%2C41.5t150%2C30t163%2C20t164.5%2C11.5t154.5%2C5.5t132.5%2C1.5zm939%2C-298q0%2C39%20-24.5%2C67t-58.5%2C42q-54%2C23%20-122%2C39.5t-143.5%2C28t-155.5%2C19t-157%2C11t-148.5%2C5t-129.5%2C1.5q-59%2C0%20-130%2C-1.5t-148%2C-5t-157%2C-11t-155.5%2C-19t-143.5%2C-28t-122%2C-39.5q-34%2C-14%20-58.5%2C-42t-24.5%2C-67l0%2C-257q0%2C-106%2040.5%2C-199t110%2C-162.5t162.5%2C-109.5t199%2C-40l81%2C0q27%2C0%2052%2C14t50%2C34.5t51%2C44.5t55.5%2C44.5t63.5%2C34.5t74%2C14t74%2C-14t63.5%2C-34.5t55.5%2C-44.5t51%2C-44.5t50%2C-34.5t52%2C-14l14%2C0q37%2C0%2070%2C0.5t64.5%2C4.5t63.5%2C12t68%2C23q71%2C30%20128.5%2C78.5t98.5%2C110t63.5%2C133.5t22.5%2C149l0%2C257z%22%20fill%3D%22white%22%20/%3E%3C/svg%3E%0A); background-size: 80%; background-repeat:no-repeat; background-position: center; border: none; outline: none; transition: transform 0.125s ease-out } .babylonVRicon:hover { transform: scale(1.05) } .babylonVRicon:active {background-color: rgba(51,51,51,1) } .babylonVRicon:focus {background-color: rgba(51,51,51,1) }.babylonVRicon.vrdisplaypresenting { background-image: none;} .vrdisplaypresenting::after { content: "EXIT"} .xr-error::after { content: "ERROR"}';
|
|
196
280
|
const style = document.createElement("style");
|
|
197
281
|
style.appendChild(document.createTextNode(css));
|
|
@@ -202,14 +286,14 @@ class PrefViewer extends HTMLElement {
|
|
|
202
286
|
if (this.#XRExperience) {
|
|
203
287
|
return true;
|
|
204
288
|
}
|
|
205
|
-
|
|
289
|
+
|
|
206
290
|
const sessionMode = "immersive-ar";
|
|
207
291
|
const sessionSupported = await WebXRSessionManager.IsSessionSupportedAsync(sessionMode);
|
|
208
292
|
if (!sessionSupported) {
|
|
209
293
|
console.info("PrefViewer: WebXR in mode AR is not supported");
|
|
210
294
|
return false;
|
|
211
295
|
}
|
|
212
|
-
|
|
296
|
+
|
|
213
297
|
try {
|
|
214
298
|
const ground = MeshBuilder.CreateGround("ground", { width: 1000, height: 1000 }, this.#scene);
|
|
215
299
|
ground.isVisible = false;
|
|
@@ -231,7 +315,6 @@ class PrefViewer extends HTMLElement {
|
|
|
231
315
|
xrInput: this.#XRExperience.input,
|
|
232
316
|
floorMeshes: [ground],
|
|
233
317
|
timeToTeleport: 1500,
|
|
234
|
-
useMainComponentOnly: true,
|
|
235
318
|
});
|
|
236
319
|
|
|
237
320
|
this.#XRExperience.baseExperience.sessionManager.onXRReady.add(() => {
|
|
@@ -251,11 +334,13 @@ class PrefViewer extends HTMLElement {
|
|
|
251
334
|
#canvasResizeObserver = new ResizeObserver(() => this.#engine && this.#engine.resize());
|
|
252
335
|
|
|
253
336
|
#createCamera() {
|
|
254
|
-
this.#camera = new ArcRotateCamera("camera", 3 * Math.PI / 2, Math.PI * 0.47, 10, Vector3.Zero(), this.#scene);
|
|
337
|
+
this.#camera = new ArcRotateCamera("camera", (3 * Math.PI) / 2, Math.PI * 0.47, 10, Vector3.Zero(), this.#scene);
|
|
255
338
|
this.#camera.upperBetaLimit = Math.PI * 0.48;
|
|
256
339
|
this.#camera.lowerBetaLimit = Math.PI * 0.25;
|
|
257
340
|
this.#camera.lowerRadiusLimit = 5;
|
|
258
341
|
this.#camera.upperRadiusLimit = 20;
|
|
342
|
+
this.#camera.metadata = { locked: false }
|
|
343
|
+
this.#camera = this.#camera;
|
|
259
344
|
this.#camera.attachControl(this.#canvas, true);
|
|
260
345
|
}
|
|
261
346
|
|
|
@@ -283,10 +368,14 @@ class PrefViewer extends HTMLElement {
|
|
|
283
368
|
|
|
284
369
|
#setupInteraction() {
|
|
285
370
|
this.#canvas.addEventListener("wheel", (event) => {
|
|
286
|
-
if (!this.#scene || !this.#camera)
|
|
287
|
-
|
|
371
|
+
if (!this.#scene || !this.#camera) {
|
|
372
|
+
return false;
|
|
373
|
+
}
|
|
374
|
+
//const pick = this.#scene.pick(this.#scene.pointerX, this.#scene.pointerY);
|
|
288
375
|
//this.#camera.target = pick.hit ? pick.pickedPoint.clone() : this.#camera.target;
|
|
289
|
-
this.#
|
|
376
|
+
if (!this.#scene.activeCamera.metadata?.locked) {
|
|
377
|
+
this.#scene.activeCamera.inertialRadiusOffset -= event.deltaY * this.#scene.activeCamera.wheelPrecision * 0.001;
|
|
378
|
+
}
|
|
290
379
|
event.preventDefault();
|
|
291
380
|
});
|
|
292
381
|
}
|
|
@@ -300,6 +389,27 @@ class PrefViewer extends HTMLElement {
|
|
|
300
389
|
}
|
|
301
390
|
|
|
302
391
|
// Utility methods for loading gltf/glb
|
|
392
|
+
async #getServerFileDataHeader(uri) {
|
|
393
|
+
return new Promise((resolve) => {
|
|
394
|
+
const xhr = new XMLHttpRequest();
|
|
395
|
+
xhr.open("HEAD", uri, true);
|
|
396
|
+
xhr.responseType = "blob";
|
|
397
|
+
xhr.onload = () => {
|
|
398
|
+
if (xhr.status === 200) {
|
|
399
|
+
const size = parseInt(xhr.getResponseHeader("Content-Length"));
|
|
400
|
+
const timestamp = new Date(xhr.getResponseHeader("Last-Modified")).toISOString();
|
|
401
|
+
resolve(size, timestamp);
|
|
402
|
+
} else {
|
|
403
|
+
resolve(0, null);
|
|
404
|
+
}
|
|
405
|
+
};
|
|
406
|
+
xhr.onerror = () => {
|
|
407
|
+
resolve(0, null);
|
|
408
|
+
};
|
|
409
|
+
xhr.send();
|
|
410
|
+
});
|
|
411
|
+
}
|
|
412
|
+
|
|
303
413
|
#transformUrl(url) {
|
|
304
414
|
return new Promise((resolve) => {
|
|
305
415
|
resolve(url.replace(/^blob:[^/]+\//i, "").replace(/\\/g, "/"));
|
|
@@ -312,10 +422,11 @@ class PrefViewer extends HTMLElement {
|
|
|
312
422
|
let decoded = "";
|
|
313
423
|
let blob = null;
|
|
314
424
|
let extension = null;
|
|
425
|
+
let size = raw.length;
|
|
315
426
|
try {
|
|
316
427
|
decoded = atob(raw);
|
|
317
428
|
} catch {
|
|
318
|
-
return { blob, extension };
|
|
429
|
+
return { blob, extension, size };
|
|
319
430
|
}
|
|
320
431
|
let isJson = false;
|
|
321
432
|
try {
|
|
@@ -326,7 +437,7 @@ class PrefViewer extends HTMLElement {
|
|
|
326
437
|
const type = isJson ? "model/gltf+json" : "model/gltf-binary";
|
|
327
438
|
const array = Uint8Array.from(decoded, (c) => c.charCodeAt(0));
|
|
328
439
|
blob = new Blob([array], { type });
|
|
329
|
-
return { blob, extension };
|
|
440
|
+
return { blob, extension, size };
|
|
330
441
|
}
|
|
331
442
|
|
|
332
443
|
async #initStorage(db, table) {
|
|
@@ -338,41 +449,103 @@ class PrefViewer extends HTMLElement {
|
|
|
338
449
|
|
|
339
450
|
// Methods for managing Asset Containers
|
|
340
451
|
#setVisibilityOfWallAndFloorInModel(show) {
|
|
341
|
-
if (this.#model.
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
452
|
+
if (!this.#data.containers.model.assetContainer || !this.#data.containers.model.visible) {
|
|
453
|
+
return false;
|
|
454
|
+
}
|
|
455
|
+
show = show !== undefined ? show : this.#data.containers.environment.visible;
|
|
456
|
+
const prefixes = Object.values(this.#data.options.materials).map((material) => material.prefix);
|
|
457
|
+
this.#data.containers.model.assetContainer.meshes.filter((meshToFilter) => prefixes.some((prefix) => meshToFilter.name.startsWith(prefix))).forEach((mesh) => mesh.setEnabled(show));
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
#setOptionsMaterial(optionMaterial) {
|
|
461
|
+
if (!optionMaterial || !optionMaterial.prefix || !optionMaterial.value) {
|
|
462
|
+
return false;
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
const material = this.#data.containers.materials.assetContainer?.materials.find((mat) => mat.name === optionMaterial.value) || null;
|
|
466
|
+
if (!material) {
|
|
467
|
+
return false;
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
const containers = [];
|
|
471
|
+
if (this.#data.containers.model.assetContainer && (this.#data.containers.model.assetContainer.changed || optionMaterial.changed)) {
|
|
472
|
+
containers.push(this.#data.containers.model.assetContainer);
|
|
473
|
+
}
|
|
474
|
+
if (this.#data.containers.environment.assetContainer && (this.#data.containers.environment.assetContainer.changed || optionMaterial.changed)) {
|
|
475
|
+
containers.push(this.#data.containers.environment.assetContainer);
|
|
476
|
+
}
|
|
477
|
+
if (containers.length === 0) {
|
|
478
|
+
return false;
|
|
348
479
|
}
|
|
480
|
+
|
|
481
|
+
let someSetted = false;
|
|
482
|
+
containers.forEach((container) =>
|
|
483
|
+
container.meshes
|
|
484
|
+
.filter((meshToFilter) => meshToFilter.name.startsWith(optionMaterial.prefix))
|
|
485
|
+
.forEach((mesh) => {
|
|
486
|
+
mesh.material = material;
|
|
487
|
+
someSetted = true;
|
|
488
|
+
})
|
|
489
|
+
);
|
|
490
|
+
|
|
491
|
+
return someSetted;
|
|
492
|
+
}
|
|
493
|
+
|
|
494
|
+
#setOptionsMaterials() {
|
|
495
|
+
let someSetted = false;
|
|
496
|
+
Object.values(this.#data.options.materials).forEach((material) => {
|
|
497
|
+
let settedMaterial = this.#setOptionsMaterial(material);
|
|
498
|
+
someSetted = someSetted || settedMaterial;
|
|
499
|
+
});
|
|
500
|
+
return someSetted;
|
|
349
501
|
}
|
|
350
502
|
|
|
351
|
-
#
|
|
352
|
-
if (
|
|
353
|
-
|
|
354
|
-
|
|
503
|
+
#setOptionsCamera() {
|
|
504
|
+
if (!this.#data.options.camera.value || (!this.#data.options.camera.changed && !this.#data.containers.model.assetContainer.changed)) {
|
|
505
|
+
return false;
|
|
506
|
+
}
|
|
507
|
+
|
|
508
|
+
let camera = this.#data.containers.model.assetContainer?.cameras.find((cam) => cam.name === this.#data.options.camera.value) || null;
|
|
509
|
+
if (!camera) {
|
|
510
|
+
return false;
|
|
511
|
+
}
|
|
512
|
+
|
|
513
|
+
camera.metadata = { locked: this.#data.options.camera.locked };
|
|
514
|
+
if (!this.#data.options.camera.locked) {
|
|
515
|
+
camera.attachControl(this.#canvas, true);
|
|
355
516
|
}
|
|
517
|
+
this.#scene.activeCamera = camera;
|
|
518
|
+
|
|
519
|
+
return true;
|
|
356
520
|
}
|
|
357
521
|
|
|
358
|
-
#
|
|
359
|
-
if (
|
|
360
|
-
|
|
361
|
-
|
|
522
|
+
#addContainer(container) {
|
|
523
|
+
if (container.assetContainer && !container.visible && container.show) {
|
|
524
|
+
container.assetContainer.addAllToScene();
|
|
525
|
+
container.visible = true;
|
|
362
526
|
}
|
|
363
527
|
}
|
|
364
528
|
|
|
365
|
-
#
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
529
|
+
#removeContainer(container) {
|
|
530
|
+
if (container.assetContainer && container.visible) {
|
|
531
|
+
container.assetContainer.removeAllFromScene();
|
|
532
|
+
container.visible = false;
|
|
533
|
+
}
|
|
534
|
+
}
|
|
535
|
+
|
|
536
|
+
#replaceContainer(container, newAssetContainer) {
|
|
537
|
+
this.#removeContainer(container);
|
|
538
|
+
container.assetContainer = newAssetContainer;
|
|
539
|
+
container.assetContainer.meshes.forEach((mesh) => {
|
|
369
540
|
mesh.receiveShadows = true;
|
|
370
541
|
this.#shadowGen.addShadowCaster(mesh, true);
|
|
371
542
|
});
|
|
372
|
-
this.#addContainer(
|
|
543
|
+
this.#addContainer(container);
|
|
373
544
|
}
|
|
374
545
|
|
|
375
|
-
async #loadAssetContainer(
|
|
546
|
+
async #loadAssetContainer(container) {
|
|
547
|
+
let storage = container?.storage;
|
|
548
|
+
|
|
376
549
|
if (!storage) {
|
|
377
550
|
return false;
|
|
378
551
|
}
|
|
@@ -383,6 +556,11 @@ class PrefViewer extends HTMLElement {
|
|
|
383
556
|
await this.#initStorage(storage.db, storage.table);
|
|
384
557
|
const object = await loadModel(storage.id, storage.table);
|
|
385
558
|
source = object.data;
|
|
559
|
+
if (object.timestamp === container.timestamp) {
|
|
560
|
+
return false;
|
|
561
|
+
} else {
|
|
562
|
+
container.changed = { timestamp: object.timestamp, size: object.size };
|
|
563
|
+
}
|
|
386
564
|
}
|
|
387
565
|
|
|
388
566
|
if (!source) {
|
|
@@ -391,20 +569,34 @@ class PrefViewer extends HTMLElement {
|
|
|
391
569
|
|
|
392
570
|
let file = null;
|
|
393
571
|
|
|
394
|
-
let { blob, extension } = this.#decodeBase64(source);
|
|
572
|
+
let { blob, extension, size } = this.#decodeBase64(source);
|
|
395
573
|
if (blob && extension) {
|
|
396
|
-
file = new File([blob],
|
|
574
|
+
file = new File([blob], `${container.name}${extension}`, {
|
|
397
575
|
type: blob.type,
|
|
398
576
|
});
|
|
577
|
+
if (!container.changed) {
|
|
578
|
+
if (container.timestamp === null && container.size === size) {
|
|
579
|
+
return false;
|
|
580
|
+
} else {
|
|
581
|
+
container.changed = { timestamp: null, size: size };
|
|
582
|
+
}
|
|
583
|
+
}
|
|
399
584
|
} else {
|
|
400
585
|
const extMatch = source.match(/\.(gltf|glb)(\?|#|$)/i);
|
|
401
586
|
extension = extMatch ? `.${extMatch[1].toLowerCase()}` : ".gltf";
|
|
587
|
+
const { fileSize, fileTimestamp } = await this.#getServerFileDataHeader(source);
|
|
588
|
+
if (container.timestamp === fileTimestamp && container.size === fileSize) {
|
|
589
|
+
return false;
|
|
590
|
+
} else {
|
|
591
|
+
container.changed = { timestamp: fileTimestamp, size: fileSize };
|
|
592
|
+
}
|
|
402
593
|
}
|
|
403
594
|
|
|
404
595
|
let options = {
|
|
405
596
|
pluginExtension: extension,
|
|
406
597
|
pluginOptions: {
|
|
407
598
|
gltf: {
|
|
599
|
+
loadAllMaterials: true,
|
|
408
600
|
preprocessUrlAsync: this.#transformUrl,
|
|
409
601
|
},
|
|
410
602
|
},
|
|
@@ -413,27 +605,43 @@ class PrefViewer extends HTMLElement {
|
|
|
413
605
|
return LoadAssetContainerAsync(file || source, this.#scene, options);
|
|
414
606
|
}
|
|
415
607
|
|
|
416
|
-
async #loadContainers(loadModel = true, loadEnvironment = true) {
|
|
608
|
+
async #loadContainers(loadModel = true, loadEnvironment = true, loadMaterials = true) {
|
|
417
609
|
const promiseArray = [];
|
|
418
|
-
|
|
419
|
-
promiseArray.push(
|
|
420
|
-
promiseArray.push(
|
|
610
|
+
promiseArray.push(loadModel ? this.#loadAssetContainer(this.#data.containers.model) : false);
|
|
611
|
+
promiseArray.push(loadEnvironment ? this.#loadAssetContainer(this.#data.containers.environment) : false);
|
|
612
|
+
promiseArray.push(loadMaterials ? this.#loadAssetContainer(this.#data.containers.materials) : false);
|
|
421
613
|
|
|
422
614
|
Promise.allSettled(promiseArray)
|
|
423
615
|
.then(async (values) => {
|
|
424
616
|
const modelContainer = values[0];
|
|
425
617
|
const environmentContainer = values[1];
|
|
618
|
+
const materialsContainer = values[2];
|
|
426
619
|
|
|
427
620
|
if (modelContainer.status === "fulfilled" && modelContainer.value) {
|
|
428
|
-
this.#replaceContainer(this.#model, modelContainer.value);
|
|
621
|
+
this.#replaceContainer(this.#data.containers.model, modelContainer.value);
|
|
622
|
+
this.#storeChangedFlagsForContainer(this.#data.containers.model);
|
|
623
|
+
} else {
|
|
624
|
+
this.#data.containers.model.show ? this.#addContainer(this.#data.containers.model) : this.#removeContainer(this.#data.containers.model);
|
|
429
625
|
}
|
|
430
626
|
|
|
431
627
|
if (environmentContainer.status === "fulfilled" && environmentContainer.value) {
|
|
432
|
-
this.#replaceContainer(this.#environment, environmentContainer.value);
|
|
628
|
+
this.#replaceContainer(this.#data.containers.environment, environmentContainer.value);
|
|
629
|
+
this.#storeChangedFlagsForContainer(this.#data.containers.environment);
|
|
630
|
+
} else {
|
|
631
|
+
this.#data.containers.environment.show ? this.#addContainer(this.#data.containers.environment) : this.#removeContainer(this.#data.containers.environment);
|
|
632
|
+
}
|
|
633
|
+
|
|
634
|
+
if (materialsContainer.status === "fulfilled" && materialsContainer.value) {
|
|
635
|
+
this.#replaceContainer(this.#data.containers.materials, materialsContainer.value);
|
|
636
|
+
this.#storeChangedFlagsForContainer(this.#data.containers.materials);
|
|
433
637
|
}
|
|
434
638
|
|
|
639
|
+
this.#setOptionsMaterials();
|
|
640
|
+
this.#setOptionsCamera();
|
|
435
641
|
this.#setVisibilityOfWallAndFloorInModel();
|
|
436
|
-
|
|
642
|
+
|
|
643
|
+
this.#resetChangedFlags();
|
|
644
|
+
|
|
437
645
|
this.dispatchEvent(
|
|
438
646
|
new CustomEvent("model-loaded", {
|
|
439
647
|
detail: { success: "" },
|
|
@@ -460,11 +668,37 @@ class PrefViewer extends HTMLElement {
|
|
|
460
668
|
if (!config) {
|
|
461
669
|
return false;
|
|
462
670
|
}
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
this.#
|
|
466
|
-
this.#
|
|
467
|
-
this.#
|
|
671
|
+
|
|
672
|
+
// Containers
|
|
673
|
+
this.#data.containers.model.storage = config.model?.storage || null;
|
|
674
|
+
this.#data.containers.model.show = config.model?.visible !== undefined ? config.model.visible : this.#data.containers.model.show;
|
|
675
|
+
this.#data.containers.environment.storage = config.scene?.storage || null;
|
|
676
|
+
this.#data.containers.environment.show = config.scene?.visible !== undefined ? config.scene.visible : this.#data.containers.environment.show;
|
|
677
|
+
this.#data.containers.materials.storage = config.materials?.storage || null;
|
|
678
|
+
|
|
679
|
+
// Options
|
|
680
|
+
if (config.options) {
|
|
681
|
+
this.#checkCameraChanged(config.options);
|
|
682
|
+
this.#checkMaterialsChanged(config.options);
|
|
683
|
+
}
|
|
684
|
+
|
|
685
|
+
this.#initialized && this.#loadContainers(true, true, true);
|
|
686
|
+
}
|
|
687
|
+
|
|
688
|
+
setOptions(options) {
|
|
689
|
+
if (!options) {
|
|
690
|
+
return false;
|
|
691
|
+
}
|
|
692
|
+
let someSetted = false;
|
|
693
|
+
if (this.#checkCameraChanged(options)) {
|
|
694
|
+
someSetted = someSetted || this.#setOptionsCamera();
|
|
695
|
+
}
|
|
696
|
+
if (this.#checkMaterialsChanged(options)) {
|
|
697
|
+
someSetted = someSetted || this.#setOptionsMaterials();
|
|
698
|
+
}
|
|
699
|
+
this.#resetChangedFlags();
|
|
700
|
+
debugger;
|
|
701
|
+
return someSetted;
|
|
468
702
|
}
|
|
469
703
|
|
|
470
704
|
loadModel(model) {
|
|
@@ -472,9 +706,9 @@ class PrefViewer extends HTMLElement {
|
|
|
472
706
|
if (!model) {
|
|
473
707
|
return false;
|
|
474
708
|
}
|
|
475
|
-
this.#model.storage = model.storage || null;
|
|
476
|
-
this.#model.show = model.visible !== undefined ? model.visible : this.#model.show;
|
|
477
|
-
this.#initialized && this.#loadContainers(true, false);
|
|
709
|
+
this.#data.containers.model.storage = model.storage || null;
|
|
710
|
+
this.#data.containers.model.show = model.visible !== undefined ? model.visible : this.#data.containers.model.show;
|
|
711
|
+
this.#initialized && this.#loadContainers(true, false, false);
|
|
478
712
|
}
|
|
479
713
|
|
|
480
714
|
loadScene(scene) {
|
|
@@ -482,43 +716,41 @@ class PrefViewer extends HTMLElement {
|
|
|
482
716
|
if (!scene) {
|
|
483
717
|
return false;
|
|
484
718
|
}
|
|
485
|
-
this.#environment.storage = scene.storage || null;
|
|
486
|
-
this.#environment.show = scene.visible !== undefined ? scene.visible : this.#environment.show;
|
|
487
|
-
this.#initialized && this.#loadContainers(false, true);
|
|
719
|
+
this.#data.containers.environment.storage = scene.storage || null;
|
|
720
|
+
this.#data.containers.environment.show = scene.visible !== undefined ? scene.visible : this.#data.containers.environment.show;
|
|
721
|
+
this.#initialized && this.#loadContainers(false, true, false);
|
|
488
722
|
}
|
|
489
723
|
|
|
490
724
|
showModel() {
|
|
491
|
-
this.#model.show = true;
|
|
492
|
-
this.#addContainer(this.#model);
|
|
725
|
+
this.#data.containers.model.show = true;
|
|
726
|
+
this.#addContainer(this.#data.containers.model);
|
|
493
727
|
}
|
|
494
728
|
|
|
495
729
|
hideModel() {
|
|
496
|
-
this.#model.show = false;
|
|
497
|
-
this.#removeContainer(this.#model);
|
|
730
|
+
this.#data.containers.model.show = false;
|
|
731
|
+
this.#removeContainer(this.#data.containers.model);
|
|
498
732
|
}
|
|
499
733
|
|
|
500
734
|
showScene() {
|
|
501
|
-
this.#environment.show = true;
|
|
502
|
-
this.#addContainer(this.#environment);
|
|
735
|
+
this.#data.containers.environment.show = true;
|
|
736
|
+
this.#addContainer(this.#data.containers.environment);
|
|
503
737
|
this.#setVisibilityOfWallAndFloorInModel();
|
|
504
738
|
}
|
|
505
739
|
|
|
506
740
|
hideScene() {
|
|
507
|
-
this.#environment.show = false;
|
|
508
|
-
this.#removeContainer(this.#environment);
|
|
741
|
+
this.#data.containers.environment.show = false;
|
|
742
|
+
this.#removeContainer(this.#data.containers.environment);
|
|
509
743
|
this.#setVisibilityOfWallAndFloorInModel();
|
|
510
744
|
}
|
|
511
745
|
|
|
512
746
|
downloadModelGLB() {
|
|
513
747
|
const fileName = "model";
|
|
514
|
-
GLTF2Export.GLBAsync(this.#model.
|
|
515
|
-
glb.downloadFiles();
|
|
516
|
-
});
|
|
748
|
+
GLTF2Export.GLBAsync(this.#data.containers.model.assetContainer, fileName, { exportWithoutWaitingForScene: true }).then((glb) => glb.downloadFiles());
|
|
517
749
|
}
|
|
518
750
|
|
|
519
751
|
downloadModelUSDZ() {
|
|
520
752
|
const fileName = "model";
|
|
521
|
-
USDZExportAsync(this.#model.
|
|
753
|
+
USDZExportAsync(this.#data.containers.model.assetContainer).then((response) => {
|
|
522
754
|
if (response) {
|
|
523
755
|
Tools.Download(new Blob([response], { type: "model/vnd.usdz+zip" }), `${fileName}.usdz`);
|
|
524
756
|
}
|
|
@@ -536,9 +768,7 @@ class PrefViewer extends HTMLElement {
|
|
|
536
768
|
|
|
537
769
|
downloadModelAndSceneGLB() {
|
|
538
770
|
const fileName = "scene";
|
|
539
|
-
GLTF2Export.GLBAsync(this.#scene, fileName, { exportWithoutWaitingForScene: true }).then((glb) =>
|
|
540
|
-
glb.downloadFiles();
|
|
541
|
-
});
|
|
771
|
+
GLTF2Export.GLBAsync(this.#scene, fileName, { exportWithoutWaitingForScene: true }).then((glb) => glb.downloadFiles());
|
|
542
772
|
}
|
|
543
773
|
}
|
|
544
774
|
|