@preference-sl/pref-viewer 2.10.0-beta.8 → 2.10.0
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 +5 -5
- package/src/gltf-storage.js +167 -193
- package/src/index.js +491 -115
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
|
|
@@ -39,75 +39,107 @@
|
|
|
39
39
|
* </pref-viewer>
|
|
40
40
|
* ```
|
|
41
41
|
*/
|
|
42
|
-
import { Engine, Scene, ArcRotateCamera, Vector3, Color4, HemisphericLight, DirectionalLight, PointLight, ShadowGenerator, LoadAssetContainerAsync, Tools, WebXRSessionManager, WebXRDefaultExperience, MeshBuilder, WebXRFeatureName } from "@babylonjs/core";
|
|
42
|
+
import { Engine, Scene, ArcRotateCamera, Vector3, Color4, HemisphericLight, DirectionalLight, PointLight, ShadowGenerator, LoadAssetContainerAsync, Tools, WebXRSessionManager, WebXRDefaultExperience, MeshBuilder, WebXRFeatureName, HDRCubeTexture, IblShadowsRenderPipeline } from "@babylonjs/core";
|
|
43
43
|
import "@babylonjs/loaders";
|
|
44
44
|
import { USDZExportAsync, GLTF2Export } from "@babylonjs/serializers";
|
|
45
45
|
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;
|
|
80
|
+
loaded = false;
|
|
81
|
+
loading = false;
|
|
82
|
+
#taskQueue = [];
|
|
51
83
|
|
|
52
84
|
#data = {
|
|
53
85
|
containers: {
|
|
54
86
|
model: {
|
|
55
87
|
name: "model",
|
|
56
|
-
|
|
88
|
+
assetContainer: null,
|
|
57
89
|
show: true,
|
|
58
90
|
storage: null,
|
|
59
91
|
visible: false,
|
|
60
92
|
size: null,
|
|
61
|
-
|
|
62
|
-
changed: false,
|
|
93
|
+
timeStamp: null,
|
|
94
|
+
changed: { pending: false, success: false },
|
|
63
95
|
},
|
|
64
96
|
environment: {
|
|
65
97
|
name: "environment",
|
|
66
|
-
|
|
98
|
+
assetContainer: null,
|
|
67
99
|
show: true,
|
|
68
100
|
storage: null,
|
|
69
101
|
visible: false,
|
|
70
102
|
size: null,
|
|
71
|
-
|
|
72
|
-
changed: false,
|
|
103
|
+
timeStamp: null,
|
|
104
|
+
changed: { pending: false, success: false },
|
|
73
105
|
},
|
|
74
106
|
materials: {
|
|
75
107
|
name: "materials",
|
|
76
|
-
|
|
108
|
+
assetContainer: null,
|
|
77
109
|
storage: null,
|
|
78
110
|
show: true,
|
|
79
111
|
visible: false,
|
|
80
112
|
size: null,
|
|
81
|
-
|
|
82
|
-
changed: false,
|
|
113
|
+
timeStamp: null,
|
|
114
|
+
changed: { pending: false, success: false },
|
|
83
115
|
},
|
|
84
116
|
},
|
|
85
117
|
options: {
|
|
86
118
|
camera: {
|
|
87
119
|
value: null,
|
|
88
120
|
locked: true,
|
|
89
|
-
changed: false,
|
|
121
|
+
changed: { pending: false, success: false },
|
|
90
122
|
},
|
|
91
123
|
materials: {
|
|
92
124
|
innerWall: {
|
|
93
125
|
value: null,
|
|
94
126
|
prefix: "innerWall",
|
|
95
|
-
changed: false,
|
|
127
|
+
changed: { pending: false, success: false },
|
|
96
128
|
},
|
|
97
129
|
outerWall: {
|
|
98
130
|
value: null,
|
|
99
131
|
prefix: "outerWall",
|
|
100
|
-
changed: false,
|
|
132
|
+
changed: { pending: false, success: false },
|
|
101
133
|
},
|
|
102
134
|
innerFloor: {
|
|
103
135
|
value: null,
|
|
104
136
|
prefix: "innerFloor",
|
|
105
|
-
changed: false,
|
|
137
|
+
changed: { pending: false, success: false },
|
|
106
138
|
},
|
|
107
139
|
outerFloor: {
|
|
108
140
|
value: null,
|
|
109
141
|
prefix: "outerFloor",
|
|
110
|
-
changed: false,
|
|
142
|
+
changed: { pending: false, success: false },
|
|
111
143
|
},
|
|
112
144
|
},
|
|
113
145
|
},
|
|
@@ -160,9 +192,15 @@ class PrefViewer extends HTMLElement {
|
|
|
160
192
|
case "scene":
|
|
161
193
|
this.loadScene(value);
|
|
162
194
|
break;
|
|
195
|
+
case "materials":
|
|
196
|
+
this.loadMaterials(value);
|
|
197
|
+
break;
|
|
198
|
+
case "options":
|
|
199
|
+
this.setOptions(value);
|
|
200
|
+
break;
|
|
163
201
|
case "show-model":
|
|
164
202
|
data = value.toLowerCase?.() === "true";
|
|
165
|
-
if (this
|
|
203
|
+
if (this.initialized) {
|
|
166
204
|
data ? this.showModel() : this.hideModel();
|
|
167
205
|
} else {
|
|
168
206
|
this.#data.containers.model.show = data;
|
|
@@ -170,7 +208,7 @@ class PrefViewer extends HTMLElement {
|
|
|
170
208
|
break;
|
|
171
209
|
case "show-scene":
|
|
172
210
|
data = value.toLowerCase?.() === "true";
|
|
173
|
-
if (this
|
|
211
|
+
if (this.initialized) {
|
|
174
212
|
data ? this.showScene() : this.hideScene();
|
|
175
213
|
} else {
|
|
176
214
|
this.#data.containers.environment.show = data;
|
|
@@ -184,18 +222,19 @@ class PrefViewer extends HTMLElement {
|
|
|
184
222
|
const error = 'PrefViewer: provide "models" as array of model and environment';
|
|
185
223
|
console.error(error);
|
|
186
224
|
this.dispatchEvent(
|
|
187
|
-
new CustomEvent("
|
|
188
|
-
detail: { error: new Error(error) },
|
|
225
|
+
new CustomEvent("scene-error", {
|
|
189
226
|
bubbles: true,
|
|
227
|
+
cancelable: false,
|
|
190
228
|
composed: true,
|
|
229
|
+
detail: { error: new Error(error) },
|
|
191
230
|
})
|
|
192
231
|
);
|
|
193
232
|
return false;
|
|
194
233
|
}
|
|
195
234
|
|
|
196
235
|
this.#initializeBabylon();
|
|
197
|
-
this
|
|
198
|
-
this.#
|
|
236
|
+
this.initialized = true;
|
|
237
|
+
this.#processNextTask();
|
|
199
238
|
}
|
|
200
239
|
|
|
201
240
|
disconnectedCallback() {
|
|
@@ -225,14 +264,90 @@ class PrefViewer extends HTMLElement {
|
|
|
225
264
|
this.shadowRoot.append(this.#wrapper);
|
|
226
265
|
}
|
|
227
266
|
|
|
267
|
+
#setStatusLoading() {
|
|
268
|
+
this.loaded = false;
|
|
269
|
+
this.loading = true;
|
|
270
|
+
if (this.hasAttribute("loaded")) {
|
|
271
|
+
this.removeAttribute("loaded");
|
|
272
|
+
}
|
|
273
|
+
this.setAttribute("loading", "");
|
|
274
|
+
this.dispatchEvent(
|
|
275
|
+
new CustomEvent("scene-loading", {
|
|
276
|
+
bubbles: true,
|
|
277
|
+
cancelable: false,
|
|
278
|
+
composed: true,
|
|
279
|
+
})
|
|
280
|
+
);
|
|
281
|
+
this.#engine.stopRenderLoop(this.#renderLoop);
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
async #setStatusLoaded() {
|
|
285
|
+
const toLoadDetail = {
|
|
286
|
+
container_model: !!this.#data.containers.model.changed.pending,
|
|
287
|
+
container_environment: !!this.#data.containers.environment.changed.pending,
|
|
288
|
+
container_materials: !!this.#data.containers.materials.changed.pending,
|
|
289
|
+
options_camera: !!this.#data.options.camera.changed.pending,
|
|
290
|
+
options_innerWallMaterial: !!this.#data.options.materials.innerWall.changed.pending,
|
|
291
|
+
options_outerWallMaterial: !!this.#data.options.materials.outerWall.changed.pending,
|
|
292
|
+
options_innerFloorMaterial: !!this.#data.options.materials.innerFloor.changed.pending,
|
|
293
|
+
options_outerFloorMaterial: !!this.#data.options.materials.outerFloor.changed.pending,
|
|
294
|
+
};
|
|
295
|
+
const loadedDetail = {
|
|
296
|
+
container_model: !!this.#data.containers.model.changed.success,
|
|
297
|
+
container_environment: !!this.#data.containers.environment.changed.success,
|
|
298
|
+
container_materials: !!this.#data.containers.materials.changed.success,
|
|
299
|
+
options_camera: !!this.#data.options.camera.changed.success,
|
|
300
|
+
options_innerWallMaterial: !!this.#data.options.materials.innerWall.changed.success,
|
|
301
|
+
options_outerWallMaterial: !!this.#data.options.materials.outerWall.changed.success,
|
|
302
|
+
options_innerFloorMaterial: !!this.#data.options.materials.innerFloor.changed.success,
|
|
303
|
+
options_outerFloorMaterial: !!this.#data.options.materials.outerFloor.changed.success,
|
|
304
|
+
};
|
|
305
|
+
const detail = {
|
|
306
|
+
tried: toLoadDetail,
|
|
307
|
+
success: loadedDetail,
|
|
308
|
+
};
|
|
309
|
+
|
|
310
|
+
this.dispatchEvent(
|
|
311
|
+
new CustomEvent("scene-loaded", {
|
|
312
|
+
bubbles: true,
|
|
313
|
+
cancelable: false,
|
|
314
|
+
composed: true,
|
|
315
|
+
detail: detail,
|
|
316
|
+
})
|
|
317
|
+
);
|
|
318
|
+
|
|
319
|
+
await this.#scene.whenReadyAsync();
|
|
320
|
+
this.#engine.runRenderLoop(this.#renderLoop);
|
|
321
|
+
|
|
322
|
+
this.#resetChangedFlags();
|
|
323
|
+
|
|
324
|
+
if (this.hasAttribute("loading")) {
|
|
325
|
+
this.removeAttribute("loading");
|
|
326
|
+
}
|
|
327
|
+
this.setAttribute("loaded", "");
|
|
328
|
+
|
|
329
|
+
this.loaded = true;
|
|
330
|
+
this.loading = false;
|
|
331
|
+
|
|
332
|
+
this.#processNextTask();
|
|
333
|
+
}
|
|
334
|
+
|
|
228
335
|
// Data
|
|
229
336
|
#checkCameraChanged(options) {
|
|
230
337
|
if (!options || !options.camera) {
|
|
231
338
|
return false;
|
|
232
339
|
}
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
340
|
+
const prev = this.#data.options.camera.value;
|
|
341
|
+
const changed = options.camera !== prev;
|
|
342
|
+
|
|
343
|
+
this.#data.options.camera.changed.pending = changed;
|
|
344
|
+
this.#data.options.camera.changed.success = false;
|
|
345
|
+
if (changed) {
|
|
346
|
+
this.#data.options.camera.changed.value = prev;
|
|
347
|
+
this.#data.options.camera.changed.locked = this.#data.options.camera.locked;
|
|
348
|
+
this.#data.options.camera.value = options.camera;
|
|
349
|
+
}
|
|
350
|
+
return changed;
|
|
236
351
|
}
|
|
237
352
|
|
|
238
353
|
#checkMaterialsChanged(options) {
|
|
@@ -242,40 +357,61 @@ class PrefViewer extends HTMLElement {
|
|
|
242
357
|
let someChanged = false;
|
|
243
358
|
Object.keys(this.#data.options.materials).forEach((material) => {
|
|
244
359
|
const key = `${material}Material`;
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
360
|
+
const state = this.#data.options.materials[material];
|
|
361
|
+
const prev = state.value;
|
|
362
|
+
const incoming = options[key];
|
|
363
|
+
const changed = !!incoming && incoming !== prev;
|
|
364
|
+
|
|
365
|
+
state.changed.pending = changed;
|
|
366
|
+
state.changed.success = false;
|
|
367
|
+
if (changed) {
|
|
368
|
+
state.changed.value = prev;
|
|
369
|
+
state.value = incoming;
|
|
370
|
+
}
|
|
371
|
+
someChanged = someChanged || changed;
|
|
248
372
|
});
|
|
249
373
|
return someChanged;
|
|
250
374
|
}
|
|
251
375
|
|
|
252
|
-
#storeChangedFlagsForContainer(container) {
|
|
253
|
-
|
|
254
|
-
|
|
376
|
+
#storeChangedFlagsForContainer(container, success) {
|
|
377
|
+
if (success) {
|
|
378
|
+
container.timeStamp = container.changed.timeStamp;
|
|
379
|
+
container.size = container.changed.size;
|
|
380
|
+
container.changed.success = true;
|
|
381
|
+
} else {
|
|
382
|
+
container.changed.success = false;
|
|
383
|
+
}
|
|
255
384
|
}
|
|
256
385
|
|
|
257
386
|
#resetChangedFlags() {
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
387
|
+
const reset = (node) => {
|
|
388
|
+
node.changed = { pending: false, success: false };
|
|
389
|
+
};
|
|
390
|
+
Object.values(this.#data.containers).forEach(reset);
|
|
391
|
+
Object.values(this.#data.options.materials).forEach(reset);
|
|
392
|
+
reset(this.#data.options.camera);
|
|
261
393
|
}
|
|
262
394
|
|
|
263
395
|
// Babylon.js
|
|
264
396
|
async #initializeBabylon() {
|
|
265
397
|
this.#engine = new Engine(this.#canvas, true, { alpha: true });
|
|
398
|
+
this.#engine.disableUniformBuffers = true;
|
|
266
399
|
this.#scene = new Scene(this.#engine);
|
|
267
400
|
this.#scene.clearColor = new Color4(1, 1, 1, 1);
|
|
268
401
|
this.#createCamera();
|
|
269
402
|
this.#createLights();
|
|
270
403
|
this.#setupInteraction();
|
|
271
|
-
|
|
272
|
-
this.#engine.runRenderLoop(() => this.#scene && this.#scene.render());
|
|
273
|
-
this.#canvasResizeObserver.observe(this.#canvas);
|
|
274
|
-
|
|
275
404
|
await this.#createXRExperience();
|
|
405
|
+
this.#engine.runRenderLoop(this.#renderLoop);
|
|
406
|
+
this.#canvasResizeObserver.observe(this.#canvas);
|
|
276
407
|
}
|
|
277
408
|
|
|
278
|
-
|
|
409
|
+
// If this function is defined as '#renderLoop() {}' it is not executed in 'this.#engine.runRenderLoop(this.#renderLoop)'
|
|
410
|
+
#renderLoop = () => {
|
|
411
|
+
this.#scene && this.#scene.render();
|
|
412
|
+
};
|
|
413
|
+
|
|
414
|
+
#addStylesToARButton() {
|
|
279
415
|
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"}';
|
|
280
416
|
const style = document.createElement("style");
|
|
281
417
|
style.appendChild(document.createTextNode(css));
|
|
@@ -324,7 +460,7 @@ class PrefViewer extends HTMLElement {
|
|
|
324
460
|
this.#XRExperience.baseExperience.onInitialXRPoseSetObservable.notifyObservers(this.#XRExperience.baseExperience.camera);
|
|
325
461
|
});
|
|
326
462
|
|
|
327
|
-
this
|
|
463
|
+
this.#addStylesToARButton();
|
|
328
464
|
} catch (error) {
|
|
329
465
|
console.warn("PrefViewer: failed to create WebXR experience", error);
|
|
330
466
|
this.#XRExperience = null;
|
|
@@ -339,12 +475,18 @@ class PrefViewer extends HTMLElement {
|
|
|
339
475
|
this.#camera.lowerBetaLimit = Math.PI * 0.25;
|
|
340
476
|
this.#camera.lowerRadiusLimit = 5;
|
|
341
477
|
this.#camera.upperRadiusLimit = 20;
|
|
342
|
-
this.#camera.metadata = { locked: false }
|
|
343
|
-
this.#camera = this.#camera;
|
|
478
|
+
this.#camera.metadata = { locked: false };
|
|
344
479
|
this.#camera.attachControl(this.#canvas, true);
|
|
480
|
+
this.#scene.activeCamera = this.#camera;
|
|
345
481
|
}
|
|
346
482
|
|
|
347
483
|
#createLights() {
|
|
484
|
+
this.#initEnvironmentTexture();
|
|
485
|
+
|
|
486
|
+
if (this.#scene.environmentTexture) {
|
|
487
|
+
return true;
|
|
488
|
+
}
|
|
489
|
+
|
|
348
490
|
// 1) Stronger ambient fill
|
|
349
491
|
this.#hemiLight = new HemisphericLight("hemiLight", new Vector3(-10, 10, -10), this.#scene);
|
|
350
492
|
this.#hemiLight.intensity = 0.6;
|
|
@@ -354,7 +496,7 @@ class PrefViewer extends HTMLElement {
|
|
|
354
496
|
this.#dirLight.position = new Vector3(5, 4, 5); // light is IN FRONT + ABOVE + to the RIGHT
|
|
355
497
|
this.#dirLight.intensity = 0.6;
|
|
356
498
|
|
|
357
|
-
// 3) Soft shadows
|
|
499
|
+
// // 3) Soft shadows
|
|
358
500
|
this.#shadowGen = new ShadowGenerator(1024, this.#dirLight);
|
|
359
501
|
this.#shadowGen.useBlurExponentialShadowMap = true;
|
|
360
502
|
this.#shadowGen.blurKernel = 16;
|
|
@@ -366,6 +508,94 @@ class PrefViewer extends HTMLElement {
|
|
|
366
508
|
this.#cameraLight.intensity = 0.3;
|
|
367
509
|
}
|
|
368
510
|
|
|
511
|
+
#initEnvironmentTexture() {
|
|
512
|
+
return false;
|
|
513
|
+
if (this.#scene.environmentTexture) {
|
|
514
|
+
return true;
|
|
515
|
+
}
|
|
516
|
+
const hdrTextureURI = "../src/environments/noon_grass.hdr";
|
|
517
|
+
const hdrTexture = new HDRCubeTexture(hdrTextureURI, this.#scene, 128);
|
|
518
|
+
hdrTexture.gammaSpace = true;
|
|
519
|
+
hdrTexture._noMipmap = false;
|
|
520
|
+
hdrTexture.level = 2.0;
|
|
521
|
+
this.#scene.environmentTexture = hdrTexture;
|
|
522
|
+
}
|
|
523
|
+
|
|
524
|
+
#initIBLShadows() {
|
|
525
|
+
if (!this.#scene.environmentTexture) {
|
|
526
|
+
return false;
|
|
527
|
+
}
|
|
528
|
+
|
|
529
|
+
let createIBLShadowPipeline = function (scene) {
|
|
530
|
+
const pipeline = new IblShadowsRenderPipeline(
|
|
531
|
+
"iblShadowsPipeline",
|
|
532
|
+
scene,
|
|
533
|
+
{
|
|
534
|
+
resolutionExp: 7,
|
|
535
|
+
sampleDirections: 2,
|
|
536
|
+
ssShadowsEnabled: true,
|
|
537
|
+
shadowRemanence: 0.8,
|
|
538
|
+
triPlanarVoxelization: true,
|
|
539
|
+
shadowOpacity: 0.8,
|
|
540
|
+
},
|
|
541
|
+
[scene.activeCamera]
|
|
542
|
+
);
|
|
543
|
+
pipeline.allowDebugPasses = false;
|
|
544
|
+
pipeline.gbufferDebugEnabled = true;
|
|
545
|
+
pipeline.importanceSamplingDebugEnabled = false;
|
|
546
|
+
pipeline.voxelDebugEnabled = false;
|
|
547
|
+
pipeline.voxelDebugDisplayMip = 1;
|
|
548
|
+
pipeline.voxelDebugAxis = 2;
|
|
549
|
+
pipeline.voxelTracingDebugEnabled = false;
|
|
550
|
+
pipeline.spatialBlurPassDebugEnabled = false;
|
|
551
|
+
pipeline.accumulationPassDebugEnabled = false;
|
|
552
|
+
return pipeline;
|
|
553
|
+
};
|
|
554
|
+
|
|
555
|
+
let iblShadowsPipeline = createIBLShadowPipeline(this.#scene);
|
|
556
|
+
|
|
557
|
+
this.#scene.meshes.forEach((mesh) => {
|
|
558
|
+
if (mesh.id.startsWith("__root__") || mesh.name === "hdri") {
|
|
559
|
+
return false;
|
|
560
|
+
}
|
|
561
|
+
iblShadowsPipeline.addShadowCastingMesh(mesh);
|
|
562
|
+
iblShadowsPipeline.updateSceneBounds();
|
|
563
|
+
});
|
|
564
|
+
|
|
565
|
+
this.#scene.materials.forEach((material) => {
|
|
566
|
+
iblShadowsPipeline.addShadowReceivingMaterial(material);
|
|
567
|
+
});
|
|
568
|
+
}
|
|
569
|
+
|
|
570
|
+
#initShadows() {
|
|
571
|
+
if (!this.#scene.environmentTexture) {
|
|
572
|
+
this.#initIBLShadows();
|
|
573
|
+
return true;
|
|
574
|
+
}
|
|
575
|
+
|
|
576
|
+
this.#scene.meshes.forEach((mesh) => {
|
|
577
|
+
if (mesh.id.startsWith("__root__")) {
|
|
578
|
+
return false;
|
|
579
|
+
}
|
|
580
|
+
mesh.receiveShadows = true;
|
|
581
|
+
if (!mesh.name === "hdri") {
|
|
582
|
+
this.#shadowGen.addShadowCaster(mesh, true);
|
|
583
|
+
}
|
|
584
|
+
});
|
|
585
|
+
}
|
|
586
|
+
|
|
587
|
+
#setMaxSimultaneousLights() {
|
|
588
|
+
let lightsNumber = 1; // Como mínimo una luz correspondiente a la textura de environmentTexture
|
|
589
|
+
this.#scene.lights.forEach((light) => {
|
|
590
|
+
if (light.isEnabled()) {
|
|
591
|
+
++lightsNumber;
|
|
592
|
+
}
|
|
593
|
+
});
|
|
594
|
+
if (this.#scene.materials) {
|
|
595
|
+
this.#scene.materials.forEach((material) => (material.maxSimultaneousLights = lightsNumber));
|
|
596
|
+
}
|
|
597
|
+
}
|
|
598
|
+
|
|
369
599
|
#setupInteraction() {
|
|
370
600
|
this.#canvas.addEventListener("wheel", (event) => {
|
|
371
601
|
if (!this.#scene || !this.#camera) {
|
|
@@ -397,14 +627,14 @@ class PrefViewer extends HTMLElement {
|
|
|
397
627
|
xhr.onload = () => {
|
|
398
628
|
if (xhr.status === 200) {
|
|
399
629
|
const size = parseInt(xhr.getResponseHeader("Content-Length"));
|
|
400
|
-
const
|
|
401
|
-
resolve(size,
|
|
630
|
+
const timeStamp = new Date(xhr.getResponseHeader("Last-Modified")).toISOString();
|
|
631
|
+
resolve([size, timeStamp]);
|
|
402
632
|
} else {
|
|
403
|
-
resolve(0, null);
|
|
633
|
+
resolve([0, null]);
|
|
404
634
|
}
|
|
405
635
|
};
|
|
406
636
|
xhr.onerror = () => {
|
|
407
|
-
resolve(0, null);
|
|
637
|
+
resolve([0, null]);
|
|
408
638
|
};
|
|
409
639
|
xhr.send();
|
|
410
640
|
});
|
|
@@ -432,7 +662,7 @@ class PrefViewer extends HTMLElement {
|
|
|
432
662
|
try {
|
|
433
663
|
JSON.parse(decoded);
|
|
434
664
|
isJson = true;
|
|
435
|
-
} catch {}
|
|
665
|
+
} catch { }
|
|
436
666
|
extension = isJson ? ".gltf" : ".glb";
|
|
437
667
|
const type = isJson ? "model/gltf+json" : "model/gltf-binary";
|
|
438
668
|
const array = Uint8Array.from(decoded, (c) => c.charCodeAt(0));
|
|
@@ -468,10 +698,10 @@ class PrefViewer extends HTMLElement {
|
|
|
468
698
|
}
|
|
469
699
|
|
|
470
700
|
const containers = [];
|
|
471
|
-
if (this.#data.containers.model.assetContainer && (this.#data.containers.model.
|
|
701
|
+
if (this.#data.containers.model.assetContainer && (this.#data.containers.model.changed.pending || this.#data.containers.materials.changed.pending || optionMaterial.changed.pending)) {
|
|
472
702
|
containers.push(this.#data.containers.model.assetContainer);
|
|
473
703
|
}
|
|
474
|
-
if (this.#data.containers.environment.assetContainer && (this.#data.containers.environment.
|
|
704
|
+
if (this.#data.containers.environment.assetContainer && (this.#data.containers.environment.changed.pending || this.#data.containers.materials.changed.pending || optionMaterial.changed.pending)) {
|
|
475
705
|
containers.push(this.#data.containers.environment.assetContainer);
|
|
476
706
|
}
|
|
477
707
|
if (containers.length === 0) {
|
|
@@ -488,6 +718,13 @@ class PrefViewer extends HTMLElement {
|
|
|
488
718
|
})
|
|
489
719
|
);
|
|
490
720
|
|
|
721
|
+
if (someSetted) {
|
|
722
|
+
optionMaterial.changed.success = true;
|
|
723
|
+
} else if (optionMaterial.changed.pending) {
|
|
724
|
+
optionMaterial.value = optionMaterial.changed.value;
|
|
725
|
+
optionMaterial.changed.success = false;
|
|
726
|
+
}
|
|
727
|
+
|
|
491
728
|
return someSetted;
|
|
492
729
|
}
|
|
493
730
|
|
|
@@ -501,46 +738,69 @@ class PrefViewer extends HTMLElement {
|
|
|
501
738
|
}
|
|
502
739
|
|
|
503
740
|
#setOptionsCamera() {
|
|
504
|
-
if (!this.#data.options.camera.value
|
|
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) {
|
|
505
742
|
return false;
|
|
506
743
|
}
|
|
507
744
|
|
|
508
|
-
let camera = this.#data.containers.model.assetContainer?.cameras.find((
|
|
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;
|
|
509
746
|
if (!camera) {
|
|
510
|
-
|
|
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;
|
|
749
|
+
}
|
|
750
|
+
if (camera) {
|
|
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;
|
|
754
|
+
this.#data.options.camera.changed.success = false;
|
|
755
|
+
} else {
|
|
756
|
+
camera = this.#camera;
|
|
757
|
+
this.#data.options.camera.value = null;
|
|
758
|
+
this.#data.options.camera.locked = this.#camera.metadata.locked;
|
|
759
|
+
this.#data.options.camera.changed.success = false;
|
|
760
|
+
}
|
|
761
|
+
} else {
|
|
762
|
+
camera.metadata = { locked: this.#data.options.camera.locked };
|
|
763
|
+
if (this.#data.options.camera.changed.pending) {
|
|
764
|
+
this.#data.options.camera.changed.success = true;
|
|
765
|
+
}
|
|
511
766
|
}
|
|
512
|
-
|
|
513
|
-
camera.metadata = { locked: this.#data.options.camera.locked };
|
|
514
|
-
if (!this.#data.options.camera.locked) {
|
|
767
|
+
if (!this.#data.options.camera.locked && this.#data.options.camera.value !== null) {
|
|
515
768
|
camera.attachControl(this.#canvas, true);
|
|
516
769
|
}
|
|
517
770
|
this.#scene.activeCamera = camera;
|
|
518
|
-
|
|
519
771
|
return true;
|
|
520
772
|
}
|
|
521
773
|
|
|
522
774
|
#addContainer(container) {
|
|
523
|
-
if (container.assetContainer
|
|
524
|
-
|
|
525
|
-
container.visible = true;
|
|
775
|
+
if (!container.assetContainer || container.visible || !container.show) {
|
|
776
|
+
return false;
|
|
526
777
|
}
|
|
778
|
+
|
|
779
|
+
container.assetContainer.addAllToScene();
|
|
780
|
+
container.visible = true;
|
|
781
|
+
return true;
|
|
527
782
|
}
|
|
528
783
|
|
|
529
784
|
#removeContainer(container) {
|
|
530
|
-
if (container.assetContainer
|
|
531
|
-
|
|
532
|
-
container.visible = false;
|
|
785
|
+
if (!container.assetContainer || !container.visible) {
|
|
786
|
+
return false;
|
|
533
787
|
}
|
|
788
|
+
|
|
789
|
+
container.assetContainer.removeAllFromScene();
|
|
790
|
+
container.visible = false;
|
|
791
|
+
return true;
|
|
534
792
|
}
|
|
535
793
|
|
|
536
794
|
#replaceContainer(container, newAssetContainer) {
|
|
537
|
-
|
|
795
|
+
if (container.assetContainer) {
|
|
796
|
+
this.#removeContainer(container);
|
|
797
|
+
container.assetContainer.dispose();
|
|
798
|
+
container.assetContainer = null;
|
|
799
|
+
}
|
|
800
|
+
this.#scene.getEngine().releaseEffects();
|
|
538
801
|
container.assetContainer = newAssetContainer;
|
|
539
|
-
container.assetContainer.meshes.forEach((mesh) => {
|
|
540
|
-
mesh.receiveShadows = true;
|
|
541
|
-
this.#shadowGen.addShadowCaster(mesh, true);
|
|
542
|
-
});
|
|
543
802
|
this.#addContainer(container);
|
|
803
|
+
return true;
|
|
544
804
|
}
|
|
545
805
|
|
|
546
806
|
async #loadAssetContainer(container) {
|
|
@@ -556,10 +816,11 @@ class PrefViewer extends HTMLElement {
|
|
|
556
816
|
await this.#initStorage(storage.db, storage.table);
|
|
557
817
|
const object = await loadModel(storage.id, storage.table);
|
|
558
818
|
source = object.data;
|
|
559
|
-
if (object.
|
|
819
|
+
if (object.timeStamp === container.timeStamp) {
|
|
820
|
+
container.changed = { pending: false, success: false };
|
|
560
821
|
return false;
|
|
561
822
|
} else {
|
|
562
|
-
container.changed = {
|
|
823
|
+
container.changed = { pending: true, size: object.size, success: false, timeStamp: object.timeStamp };
|
|
563
824
|
}
|
|
564
825
|
}
|
|
565
826
|
|
|
@@ -574,29 +835,34 @@ class PrefViewer extends HTMLElement {
|
|
|
574
835
|
file = new File([blob], `${container.name}${extension}`, {
|
|
575
836
|
type: blob.type,
|
|
576
837
|
});
|
|
577
|
-
if (!container.changed) {
|
|
578
|
-
if (container.
|
|
838
|
+
if (!container.changed.pending) {
|
|
839
|
+
if (container.timeStamp === null && container.size === size) {
|
|
840
|
+
container.changed = { pending: false, success: false };
|
|
579
841
|
return false;
|
|
580
842
|
} else {
|
|
581
|
-
container.changed = {
|
|
843
|
+
container.changed = { pending: true, size: size, success: false, timeStamp: null };
|
|
582
844
|
}
|
|
583
845
|
}
|
|
584
846
|
} else {
|
|
585
847
|
const extMatch = source.match(/\.(gltf|glb)(\?|#|$)/i);
|
|
586
848
|
extension = extMatch ? `.${extMatch[1].toLowerCase()}` : ".gltf";
|
|
587
|
-
const
|
|
588
|
-
if (container.
|
|
849
|
+
const [fileSize, fileTimeStamp] = await this.#getServerFileDataHeader(source);
|
|
850
|
+
if (container.size === fileSize && container.timeStamp === fileTimeStamp) {
|
|
851
|
+
container.changed = { pending: false, success: false };
|
|
589
852
|
return false;
|
|
590
853
|
} else {
|
|
591
|
-
container.changed = {
|
|
854
|
+
container.changed = { pending: true, size: fileSize, success: false, timeStamp: fileTimeStamp };
|
|
592
855
|
}
|
|
593
856
|
}
|
|
594
857
|
|
|
858
|
+
// https://doc.babylonjs.com/typedoc/interfaces/BABYLON.LoadAssetContainerOptions
|
|
595
859
|
let options = {
|
|
596
860
|
pluginExtension: extension,
|
|
597
861
|
pluginOptions: {
|
|
598
862
|
gltf: {
|
|
863
|
+
compileMaterials: true,
|
|
599
864
|
loadAllMaterials: true,
|
|
865
|
+
loadOnlyMaterials: container.name === "materials",
|
|
600
866
|
preprocessUrlAsync: this.#transformUrl,
|
|
601
867
|
},
|
|
602
868
|
},
|
|
@@ -606,75 +872,126 @@ class PrefViewer extends HTMLElement {
|
|
|
606
872
|
}
|
|
607
873
|
|
|
608
874
|
async #loadContainers(loadModel = true, loadEnvironment = true, loadMaterials = true) {
|
|
875
|
+
this.#engine.stopRenderLoop(this.#renderLoop);
|
|
876
|
+
|
|
609
877
|
const promiseArray = [];
|
|
610
878
|
promiseArray.push(loadModel ? this.#loadAssetContainer(this.#data.containers.model) : false);
|
|
611
879
|
promiseArray.push(loadEnvironment ? this.#loadAssetContainer(this.#data.containers.environment) : false);
|
|
612
880
|
promiseArray.push(loadMaterials ? this.#loadAssetContainer(this.#data.containers.materials) : false);
|
|
613
881
|
|
|
614
882
|
Promise.allSettled(promiseArray)
|
|
615
|
-
.then(
|
|
883
|
+
.then((values) => {
|
|
616
884
|
const modelContainer = values[0];
|
|
617
885
|
const environmentContainer = values[1];
|
|
618
886
|
const materialsContainer = values[2];
|
|
619
887
|
|
|
620
888
|
if (modelContainer.status === "fulfilled" && modelContainer.value) {
|
|
889
|
+
modelContainer.value.lights = [];
|
|
621
890
|
this.#replaceContainer(this.#data.containers.model, modelContainer.value);
|
|
622
|
-
this.#storeChangedFlagsForContainer(this.#data.containers.model);
|
|
891
|
+
this.#storeChangedFlagsForContainer(this.#data.containers.model, true);
|
|
623
892
|
} else {
|
|
624
|
-
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
|
+
}
|
|
896
|
+
this.#storeChangedFlagsForContainer(this.#data.containers.model, false);
|
|
625
897
|
}
|
|
626
898
|
|
|
627
899
|
if (environmentContainer.status === "fulfilled" && environmentContainer.value) {
|
|
628
900
|
this.#replaceContainer(this.#data.containers.environment, environmentContainer.value);
|
|
629
|
-
this.#storeChangedFlagsForContainer(this.#data.containers.environment);
|
|
901
|
+
this.#storeChangedFlagsForContainer(this.#data.containers.environment, true);
|
|
630
902
|
} else {
|
|
631
|
-
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
|
+
}
|
|
906
|
+
this.#storeChangedFlagsForContainer(this.#data.containers.environment, false);
|
|
632
907
|
}
|
|
633
908
|
|
|
634
909
|
if (materialsContainer.status === "fulfilled" && materialsContainer.value) {
|
|
635
910
|
this.#replaceContainer(this.#data.containers.materials, materialsContainer.value);
|
|
636
|
-
this.#storeChangedFlagsForContainer(this.#data.containers.materials);
|
|
911
|
+
this.#storeChangedFlagsForContainer(this.#data.containers.materials, true);
|
|
912
|
+
} else {
|
|
913
|
+
this.#storeChangedFlagsForContainer(this.#data.containers.materials, false);
|
|
637
914
|
}
|
|
638
915
|
|
|
639
916
|
this.#setOptionsMaterials();
|
|
640
917
|
this.#setOptionsCamera();
|
|
641
918
|
this.#setVisibilityOfWallAndFloorInModel();
|
|
642
|
-
|
|
643
|
-
this.#resetChangedFlags();
|
|
644
|
-
|
|
645
|
-
this.dispatchEvent(
|
|
646
|
-
new CustomEvent("model-loaded", {
|
|
647
|
-
detail: { success: "" },
|
|
648
|
-
bubbles: true,
|
|
649
|
-
composed: true,
|
|
650
|
-
})
|
|
651
|
-
);
|
|
652
919
|
})
|
|
653
920
|
.catch((error) => {
|
|
921
|
+
this.loaded = true;
|
|
654
922
|
console.error("PrefViewer: failed to load model", error);
|
|
655
923
|
this.dispatchEvent(
|
|
656
|
-
new CustomEvent("
|
|
657
|
-
detail: { error: error },
|
|
924
|
+
new CustomEvent("scene-error", {
|
|
658
925
|
bubbles: true,
|
|
926
|
+
cancelable: false,
|
|
659
927
|
composed: true,
|
|
928
|
+
detail: { error: error },
|
|
660
929
|
})
|
|
661
930
|
);
|
|
931
|
+
})
|
|
932
|
+
.finally(async () => {
|
|
933
|
+
this.#setMaxSimultaneousLights();
|
|
934
|
+
this.#initShadows();
|
|
935
|
+
await this.#setStatusLoaded();
|
|
662
936
|
});
|
|
663
937
|
}
|
|
664
938
|
|
|
665
|
-
//
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
if (!
|
|
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) {
|
|
669
949
|
return false;
|
|
670
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();
|
|
671
974
|
|
|
672
975
|
// Containers
|
|
673
|
-
|
|
976
|
+
const loadModel = !!config.model?.storage;
|
|
977
|
+
this.#data.containers.model.changed.pending = loadModel;
|
|
978
|
+
this.#data.containers.model.changed.success = false;
|
|
979
|
+
this.#data.containers.model.changed.storage = this.#data.containers.model.storage;
|
|
980
|
+
this.#data.containers.model.storage = loadModel ? config.model.storage : this.#data.containers.model.storage;
|
|
674
981
|
this.#data.containers.model.show = config.model?.visible !== undefined ? config.model.visible : this.#data.containers.model.show;
|
|
675
|
-
|
|
982
|
+
|
|
983
|
+
const loadEnvironment = !!config.scene?.storage;
|
|
984
|
+
this.#data.containers.environment.changed.pending = loadEnvironment;
|
|
985
|
+
this.#data.containers.environment.changed.success = false;
|
|
986
|
+
this.#data.containers.environment.changed.storage = this.#data.containers.environment.storage;
|
|
987
|
+
this.#data.containers.environment.storage = loadEnvironment ? config.scene.storage : this.#data.containers.environment.storage;
|
|
676
988
|
this.#data.containers.environment.show = config.scene?.visible !== undefined ? config.scene.visible : this.#data.containers.environment.show;
|
|
677
|
-
|
|
989
|
+
|
|
990
|
+
const loadMaterials = !!config.materials?.storage;
|
|
991
|
+
this.#data.containers.materials.changed.pending = loadMaterials;
|
|
992
|
+
this.#data.containers.materials.changed.success = false;
|
|
993
|
+
this.#data.containers.materials.changed.storage = this.#data.containers.materials.storage;
|
|
994
|
+
this.#data.containers.materials.storage = loadMaterials ? config.materials.storage : this.#data.containers.materials.storage;
|
|
678
995
|
|
|
679
996
|
// Options
|
|
680
997
|
if (config.options) {
|
|
@@ -682,13 +999,50 @@ class PrefViewer extends HTMLElement {
|
|
|
682
999
|
this.#checkMaterialsChanged(config.options);
|
|
683
1000
|
}
|
|
684
1001
|
|
|
685
|
-
this.#
|
|
1002
|
+
this.#loadContainers(loadModel, loadEnvironment, loadMaterials);
|
|
686
1003
|
}
|
|
687
1004
|
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
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;
|
|
1039
|
+
|
|
1040
|
+
this.#loadContainers(false, false, loadMaterials);
|
|
1041
|
+
}
|
|
1042
|
+
|
|
1043
|
+
async #processOptions(options) {
|
|
1044
|
+
this.#setStatusLoading();
|
|
1045
|
+
|
|
692
1046
|
let someSetted = false;
|
|
693
1047
|
if (this.#checkCameraChanged(options)) {
|
|
694
1048
|
someSetted = someSetted || this.#setOptionsCamera();
|
|
@@ -696,19 +1050,27 @@ class PrefViewer extends HTMLElement {
|
|
|
696
1050
|
if (this.#checkMaterialsChanged(options)) {
|
|
697
1051
|
someSetted = someSetted || this.#setOptionsMaterials();
|
|
698
1052
|
}
|
|
699
|
-
|
|
700
|
-
|
|
1053
|
+
|
|
1054
|
+
await this.#setStatusLoaded();
|
|
1055
|
+
|
|
701
1056
|
return someSetted;
|
|
702
1057
|
}
|
|
703
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
|
+
|
|
704
1068
|
loadModel(model) {
|
|
705
1069
|
model = typeof model === "string" ? JSON.parse(model) : model;
|
|
706
1070
|
if (!model) {
|
|
707
1071
|
return false;
|
|
708
1072
|
}
|
|
709
|
-
this.#
|
|
710
|
-
this.#data.containers.model.show = model.visible !== undefined ? model.visible : this.#data.containers.model.show;
|
|
711
|
-
this.#initialized && this.#loadContainers(true, false, false);
|
|
1073
|
+
this.#addTaskToQueue(model, "model");
|
|
712
1074
|
}
|
|
713
1075
|
|
|
714
1076
|
loadScene(scene) {
|
|
@@ -716,9 +1078,23 @@ class PrefViewer extends HTMLElement {
|
|
|
716
1078
|
if (!scene) {
|
|
717
1079
|
return false;
|
|
718
1080
|
}
|
|
719
|
-
this.#
|
|
720
|
-
|
|
721
|
-
|
|
1081
|
+
this.#addTaskToQueue(scene, "environment");
|
|
1082
|
+
}
|
|
1083
|
+
|
|
1084
|
+
loadMaterials(materials) {
|
|
1085
|
+
materials = typeof materials === "string" ? JSON.parse(materials) : materials;
|
|
1086
|
+
if (!materials) {
|
|
1087
|
+
return false;
|
|
1088
|
+
}
|
|
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");
|
|
722
1098
|
}
|
|
723
1099
|
|
|
724
1100
|
showModel() {
|