@preference-sl/pref-viewer 2.10.0-beta.12 → 2.10.0-beta.14
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 +10 -192
package/package.json
CHANGED
package/src/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* =============================================================================
|
|
3
|
-
* PrefViewer Web Component (JavaScript)
|
|
3
|
+
* PrefViewer Web Component (JavaScript)
|
|
4
4
|
* =============================================================================
|
|
5
5
|
*
|
|
6
6
|
* Overview
|
|
@@ -49,76 +49,6 @@ import { initDb, loadModel } from "./gltf-storage.js";
|
|
|
49
49
|
class PrefViewer extends HTMLElement {
|
|
50
50
|
#initialized = false;
|
|
51
51
|
|
|
52
|
-
// --- Logging -------------------------------------------------------------
|
|
53
|
-
#debugEnabled = false;
|
|
54
|
-
#logPrefix = "PrefViewer";
|
|
55
|
-
#timers = new Map();
|
|
56
|
-
#log = {
|
|
57
|
-
debug: () => {},
|
|
58
|
-
info: () => {},
|
|
59
|
-
warn: () => {},
|
|
60
|
-
error: () => {},
|
|
61
|
-
time: () => {},
|
|
62
|
-
timeEnd: () => {},
|
|
63
|
-
group: () => {},
|
|
64
|
-
groupEnd: () => {},
|
|
65
|
-
};
|
|
66
|
-
|
|
67
|
-
#enableDebug(enable) {
|
|
68
|
-
const on = !!enable;
|
|
69
|
-
this.#debugEnabled = on;
|
|
70
|
-
if (!on) {
|
|
71
|
-
this.#log = {
|
|
72
|
-
debug: () => {},
|
|
73
|
-
info: () => {},
|
|
74
|
-
warn: () => {},
|
|
75
|
-
error: () => {},
|
|
76
|
-
time: () => {},
|
|
77
|
-
timeEnd: () => {},
|
|
78
|
-
group: () => {},
|
|
79
|
-
groupEnd: () => {},
|
|
80
|
-
};
|
|
81
|
-
return;
|
|
82
|
-
}
|
|
83
|
-
const tag = (lvl, args) => {
|
|
84
|
-
if (!args || !args.length) return [`${this.#logPrefix}:`];
|
|
85
|
-
const [first, ...rest] = args;
|
|
86
|
-
if (typeof first === "string") return [`${this.#logPrefix} [${lvl}] ${first}`, ...rest];
|
|
87
|
-
return [`${this.#logPrefix} [${lvl}]`, first, ...rest];
|
|
88
|
-
};
|
|
89
|
-
this.#log = {
|
|
90
|
-
debug: (...a) => console.debug(...tag("debug", a)),
|
|
91
|
-
info: (...a) => console.info(...tag("info", a)),
|
|
92
|
-
warn: (...a) => console.warn(...tag("warn", a)),
|
|
93
|
-
error: (...a) => console.error(...tag("error", a)),
|
|
94
|
-
time: (label) => {
|
|
95
|
-
const key = `${label}`;
|
|
96
|
-
this.#timers.set(key, performance.now());
|
|
97
|
-
console.debug(`${this.#logPrefix} [time] ${key} start`);
|
|
98
|
-
},
|
|
99
|
-
timeEnd: (label) => {
|
|
100
|
-
const key = `${label}`;
|
|
101
|
-
if (this.#timers.has(key)) {
|
|
102
|
-
const delta = (performance.now() - this.#timers.get(key)).toFixed(2);
|
|
103
|
-
console.debug(`${this.#logPrefix} [time] ${key} ${delta}ms`);
|
|
104
|
-
this.#timers.delete(key);
|
|
105
|
-
} else {
|
|
106
|
-
console.debug(`${this.#logPrefix} [time] ${key} (no start)`);
|
|
107
|
-
}
|
|
108
|
-
},
|
|
109
|
-
group: (title) => console.group?.(`${this.#logPrefix} ${title}`),
|
|
110
|
-
groupEnd: () => console.groupEnd?.(),
|
|
111
|
-
};
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
#readDebugAttribute() {
|
|
115
|
-
const v = (this.getAttribute("debug") || "").trim().toLowerCase();
|
|
116
|
-
// true/1/yes/on
|
|
117
|
-
const enabled = v === "true" || v === "1" || v === "yes" || v === "on" || v === "debug";
|
|
118
|
-
this.#enableDebug(enabled);
|
|
119
|
-
}
|
|
120
|
-
// ------------------------------------------------------------------------
|
|
121
|
-
|
|
122
52
|
#data = {
|
|
123
53
|
containers: {
|
|
124
54
|
model: {
|
|
@@ -200,8 +130,6 @@ class PrefViewer extends HTMLElement {
|
|
|
200
130
|
constructor() {
|
|
201
131
|
super();
|
|
202
132
|
this.attachShadow({ mode: "open" });
|
|
203
|
-
this.#readDebugAttribute();
|
|
204
|
-
this.#log.info("constructor()");
|
|
205
133
|
this.#createCanvas();
|
|
206
134
|
this.#wrapCanvas();
|
|
207
135
|
// Point to whichever version you packaged or want to use:
|
|
@@ -214,24 +142,13 @@ class PrefViewer extends HTMLElement {
|
|
|
214
142
|
// JS fallback if WASM isn’t available
|
|
215
143
|
fallbackUrl: `${DRACO_BASE}/draco_decoder_gltf.js`,
|
|
216
144
|
};
|
|
217
|
-
this.#log.debug("Draco decoder configured", DracoCompression.Configuration.decoder);
|
|
218
145
|
}
|
|
219
146
|
|
|
220
147
|
static get observedAttributes() {
|
|
221
|
-
|
|
222
|
-
return ["config", "model", "scene", "show-model", "show-scene", "debug"];
|
|
148
|
+
return ["config", "model", "scene", "show-model", "show-scene"];
|
|
223
149
|
}
|
|
224
150
|
|
|
225
151
|
attributeChangedCallback(name, _old, value) {
|
|
226
|
-
// Nota: el cambio de "debug" debe ocurrir antes de loguear otras cosas.
|
|
227
|
-
if (name === "debug") {
|
|
228
|
-
this.#enableDebug((value || "").toLowerCase() === "true" || value === "1" || value === "yes" || value === "on" || value === "debug");
|
|
229
|
-
this.#log.info(`attributeChanged: debug -> ${this.#debugEnabled}`);
|
|
230
|
-
return;
|
|
231
|
-
}
|
|
232
|
-
|
|
233
|
-
this.#log.debug("attributeChangedCallback()", { name, oldValue: _old, value });
|
|
234
|
-
|
|
235
152
|
let data = null;
|
|
236
153
|
switch (name) {
|
|
237
154
|
case "config":
|
|
@@ -246,7 +163,6 @@ class PrefViewer extends HTMLElement {
|
|
|
246
163
|
case "show-model":
|
|
247
164
|
data = value.toLowerCase?.() === "true";
|
|
248
165
|
if (this.#initialized) {
|
|
249
|
-
this.#log.info(`attr show-model -> ${data}`);
|
|
250
166
|
data ? this.showModel() : this.hideModel();
|
|
251
167
|
} else {
|
|
252
168
|
this.#data.containers.model.show = data;
|
|
@@ -255,7 +171,6 @@ class PrefViewer extends HTMLElement {
|
|
|
255
171
|
case "show-scene":
|
|
256
172
|
data = value.toLowerCase?.() === "true";
|
|
257
173
|
if (this.#initialized) {
|
|
258
|
-
this.#log.info(`attr show-scene -> ${data}`);
|
|
259
174
|
data ? this.showScene() : this.hideScene();
|
|
260
175
|
} else {
|
|
261
176
|
this.#data.containers.environment.show = data;
|
|
@@ -265,7 +180,6 @@ class PrefViewer extends HTMLElement {
|
|
|
265
180
|
}
|
|
266
181
|
|
|
267
182
|
connectedCallback() {
|
|
268
|
-
this.#log.info("connectedCallback()");
|
|
269
183
|
if (!this.hasAttribute("config")) {
|
|
270
184
|
const error = 'PrefViewer: provide "models" as array of model and environment';
|
|
271
185
|
console.error(error);
|
|
@@ -282,18 +196,15 @@ class PrefViewer extends HTMLElement {
|
|
|
282
196
|
this.#initializeBabylon();
|
|
283
197
|
this.#loadContainers(true, true, true);
|
|
284
198
|
this.#initialized = true;
|
|
285
|
-
this.#log.info("initialized = true");
|
|
286
199
|
}
|
|
287
200
|
|
|
288
201
|
disconnectedCallback() {
|
|
289
|
-
this.#log.info("disconnectedCallback()");
|
|
290
202
|
this.#disposeEngine();
|
|
291
203
|
this.#canvasResizeObserver.disconnect();
|
|
292
204
|
}
|
|
293
205
|
|
|
294
206
|
// Web Component
|
|
295
207
|
#createCanvas() {
|
|
296
|
-
this.#log.debug("#createCanvas()");
|
|
297
208
|
this.#canvas = document.createElement("canvas");
|
|
298
209
|
Object.assign(this.#canvas.style, {
|
|
299
210
|
width: "100%",
|
|
@@ -304,7 +215,6 @@ class PrefViewer extends HTMLElement {
|
|
|
304
215
|
}
|
|
305
216
|
|
|
306
217
|
#wrapCanvas() {
|
|
307
|
-
this.#log.debug("#wrapCanvas()");
|
|
308
218
|
this.#wrapper = document.createElement("div");
|
|
309
219
|
Object.assign(this.#wrapper.style, {
|
|
310
220
|
width: "100%",
|
|
@@ -320,10 +230,8 @@ class PrefViewer extends HTMLElement {
|
|
|
320
230
|
if (!options || !options.camera) {
|
|
321
231
|
return false;
|
|
322
232
|
}
|
|
323
|
-
|
|
324
|
-
this.#data.options.camera.
|
|
325
|
-
this.#data.options.camera.value = this.#data.options.camera.changed ? options.camera : prev;
|
|
326
|
-
this.#log.debug("#checkCameraChanged()", { prev, next: this.#data.options.camera.value, changed: this.#data.options.camera.changed });
|
|
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;
|
|
327
235
|
return this.#data.options.camera.changed;
|
|
328
236
|
}
|
|
329
237
|
|
|
@@ -334,23 +242,19 @@ class PrefViewer extends HTMLElement {
|
|
|
334
242
|
let someChanged = false;
|
|
335
243
|
Object.keys(this.#data.options.materials).forEach((material) => {
|
|
336
244
|
const key = `${material}Material`;
|
|
337
|
-
|
|
338
|
-
this.#data.options.materials[material].
|
|
339
|
-
this.#data.options.materials[material].value = this.#data.options.materials[material].changed ? options[key] : prev;
|
|
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;
|
|
340
247
|
someChanged = someChanged || this.#data.options.materials[material].changed;
|
|
341
248
|
});
|
|
342
|
-
this.#log.debug("#checkMaterialsChanged()", { someChanged, values: this.#data.options.materials });
|
|
343
249
|
return someChanged;
|
|
344
250
|
}
|
|
345
251
|
|
|
346
252
|
#storeChangedFlagsForContainer(container) {
|
|
347
|
-
this.#log.debug("#storeChangedFlagsForContainer()", { name: container.name, changed: container.changed });
|
|
348
253
|
container.timestamp = container.changed.timestamp;
|
|
349
254
|
container.size = container.changed.size;
|
|
350
255
|
}
|
|
351
256
|
|
|
352
257
|
#resetChangedFlags() {
|
|
353
|
-
this.#log.debug("#resetChangedFlags()");
|
|
354
258
|
Object.values(this.#data.containers).forEach((container) => (container.changed = false));
|
|
355
259
|
Object.values(this.#data.options.materials).forEach((material) => (material.changed = false));
|
|
356
260
|
this.#data.options.camera.changed = false;
|
|
@@ -358,8 +262,6 @@ class PrefViewer extends HTMLElement {
|
|
|
358
262
|
|
|
359
263
|
// Babylon.js
|
|
360
264
|
async #initializeBabylon() {
|
|
361
|
-
this.#log.group("#initializeBabylon()");
|
|
362
|
-
this.#log.time("babylon:init");
|
|
363
265
|
this.#engine = new Engine(this.#canvas, true, { alpha: true });
|
|
364
266
|
this.#scene = new Scene(this.#engine);
|
|
365
267
|
this.#scene.clearColor = new Color4(1, 1, 1, 1);
|
|
@@ -371,12 +273,9 @@ class PrefViewer extends HTMLElement {
|
|
|
371
273
|
this.#canvasResizeObserver.observe(this.#canvas);
|
|
372
274
|
|
|
373
275
|
await this.#createXRExperience();
|
|
374
|
-
this.#log.timeEnd("babylon:init");
|
|
375
|
-
this.#log.groupEnd();
|
|
376
276
|
}
|
|
377
277
|
|
|
378
278
|
addStylesToARButton() {
|
|
379
|
-
this.#log.debug("addStylesToARButton()");
|
|
380
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"}';
|
|
381
280
|
const style = document.createElement("style");
|
|
382
281
|
style.appendChild(document.createTextNode(css));
|
|
@@ -389,7 +288,6 @@ class PrefViewer extends HTMLElement {
|
|
|
389
288
|
}
|
|
390
289
|
|
|
391
290
|
const sessionMode = "immersive-ar";
|
|
392
|
-
this.#log.info("#createXRExperience()", { sessionMode });
|
|
393
291
|
const sessionSupported = await WebXRSessionManager.IsSessionSupportedAsync(sessionMode);
|
|
394
292
|
if (!sessionSupported) {
|
|
395
293
|
console.info("PrefViewer: WebXR in mode AR is not supported");
|
|
@@ -397,7 +295,6 @@ class PrefViewer extends HTMLElement {
|
|
|
397
295
|
}
|
|
398
296
|
|
|
399
297
|
try {
|
|
400
|
-
this.#log.time("xr:create");
|
|
401
298
|
const ground = MeshBuilder.CreateGround("ground", { width: 1000, height: 1000 }, this.#scene);
|
|
402
299
|
ground.isVisible = false;
|
|
403
300
|
|
|
@@ -421,7 +318,6 @@ class PrefViewer extends HTMLElement {
|
|
|
421
318
|
});
|
|
422
319
|
|
|
423
320
|
this.#XRExperience.baseExperience.sessionManager.onXRReady.add(() => {
|
|
424
|
-
this.#log.info("XR onXRReady");
|
|
425
321
|
// Set the initial position of xrCamera: use nonVRCamera, which contains a copy of the original this.#scene.activeCamera before entering XR
|
|
426
322
|
this.#XRExperience.baseExperience.camera.setTransformationFromNonVRCamera(this.#XRExperience.baseExperience._nonVRCamera);
|
|
427
323
|
this.#XRExperience.baseExperience.camera.setTarget(Vector3.Zero());
|
|
@@ -429,21 +325,15 @@ class PrefViewer extends HTMLElement {
|
|
|
429
325
|
});
|
|
430
326
|
|
|
431
327
|
this.addStylesToARButton();
|
|
432
|
-
this.#log.timeEnd("xr:create");
|
|
433
328
|
} catch (error) {
|
|
434
329
|
console.warn("PrefViewer: failed to create WebXR experience", error);
|
|
435
|
-
this.#log.error("XR creation failed", error);
|
|
436
330
|
this.#XRExperience = null;
|
|
437
331
|
}
|
|
438
332
|
}
|
|
439
333
|
|
|
440
|
-
#canvasResizeObserver = new ResizeObserver(() =>
|
|
441
|
-
this.#log.debug("ResizeObserver -> engine.resize()");
|
|
442
|
-
this.#engine && this.#engine.resize();
|
|
443
|
-
});
|
|
334
|
+
#canvasResizeObserver = new ResizeObserver(() => this.#engine && this.#engine.resize());
|
|
444
335
|
|
|
445
336
|
#createCamera() {
|
|
446
|
-
this.#log.debug("#createCamera()");
|
|
447
337
|
this.#camera = new ArcRotateCamera("camera", (3 * Math.PI) / 2, Math.PI * 0.47, 10, Vector3.Zero(), this.#scene);
|
|
448
338
|
this.#camera.upperBetaLimit = Math.PI * 0.48;
|
|
449
339
|
this.#camera.lowerBetaLimit = Math.PI * 0.25;
|
|
@@ -455,7 +345,6 @@ class PrefViewer extends HTMLElement {
|
|
|
455
345
|
}
|
|
456
346
|
|
|
457
347
|
#createLights() {
|
|
458
|
-
this.#log.debug("#createLights()");
|
|
459
348
|
// 1) Stronger ambient fill
|
|
460
349
|
this.#hemiLight = new HemisphericLight("hemiLight", new Vector3(-10, 10, -10), this.#scene);
|
|
461
350
|
this.#hemiLight.intensity = 0.6;
|
|
@@ -478,11 +367,12 @@ class PrefViewer extends HTMLElement {
|
|
|
478
367
|
}
|
|
479
368
|
|
|
480
369
|
#setupInteraction() {
|
|
481
|
-
this.#log.debug("#setupInteraction()");
|
|
482
370
|
this.#canvas.addEventListener("wheel", (event) => {
|
|
483
371
|
if (!this.#scene || !this.#camera) {
|
|
484
372
|
return false;
|
|
485
373
|
}
|
|
374
|
+
//const pick = this.#scene.pick(this.#scene.pointerX, this.#scene.pointerY);
|
|
375
|
+
//this.#camera.target = pick.hit ? pick.pickedPoint.clone() : this.#camera.target;
|
|
486
376
|
if (!this.#scene.activeCamera.metadata?.locked) {
|
|
487
377
|
this.#scene.activeCamera.inertialRadiusOffset -= event.deltaY * this.#scene.activeCamera.wheelPrecision * 0.001;
|
|
488
378
|
}
|
|
@@ -492,7 +382,6 @@ class PrefViewer extends HTMLElement {
|
|
|
492
382
|
|
|
493
383
|
#disposeEngine() {
|
|
494
384
|
if (!this.#engine) return;
|
|
495
|
-
this.#log.info("#disposeEngine()");
|
|
496
385
|
this.#engine.dispose();
|
|
497
386
|
this.#engine = this.#scene = this.#camera = null;
|
|
498
387
|
this.#hemiLight = this.#dirLight = this.#cameraLight = null;
|
|
@@ -501,7 +390,6 @@ class PrefViewer extends HTMLElement {
|
|
|
501
390
|
|
|
502
391
|
// Utility methods for loading gltf/glb
|
|
503
392
|
async #getServerFileDataHeader(uri) {
|
|
504
|
-
this.#log.debug("#getServerFileDataHeader()", { uri });
|
|
505
393
|
return new Promise((resolve) => {
|
|
506
394
|
const xhr = new XMLHttpRequest();
|
|
507
395
|
xhr.open("HEAD", uri, true);
|
|
@@ -510,15 +398,12 @@ class PrefViewer extends HTMLElement {
|
|
|
510
398
|
if (xhr.status === 200) {
|
|
511
399
|
const size = parseInt(xhr.getResponseHeader("Content-Length"));
|
|
512
400
|
const timestamp = new Date(xhr.getResponseHeader("Last-Modified")).toISOString();
|
|
513
|
-
this.#log.debug("HEAD ok", { size, timestamp });
|
|
514
401
|
resolve(size, timestamp);
|
|
515
402
|
} else {
|
|
516
|
-
this.#log.warn("HEAD failed", { status: xhr.status });
|
|
517
403
|
resolve(0, null);
|
|
518
404
|
}
|
|
519
405
|
};
|
|
520
406
|
xhr.onerror = () => {
|
|
521
|
-
this.#log.error("HEAD network error");
|
|
522
407
|
resolve(0, null);
|
|
523
408
|
};
|
|
524
409
|
xhr.send();
|
|
@@ -526,14 +411,12 @@ class PrefViewer extends HTMLElement {
|
|
|
526
411
|
}
|
|
527
412
|
|
|
528
413
|
#transformUrl(url) {
|
|
529
|
-
this.#log.debug("#transformUrl()", { url });
|
|
530
414
|
return new Promise((resolve) => {
|
|
531
415
|
resolve(url.replace(/^blob:[^/]+\//i, "").replace(/\\/g, "/"));
|
|
532
416
|
});
|
|
533
417
|
}
|
|
534
418
|
|
|
535
419
|
#decodeBase64(base64) {
|
|
536
|
-
this.#log.debug("#decodeBase64()", { length: (base64 || "").length });
|
|
537
420
|
const [, payload] = base64.split(",");
|
|
538
421
|
const raw = payload || base64;
|
|
539
422
|
let decoded = "";
|
|
@@ -543,7 +426,6 @@ class PrefViewer extends HTMLElement {
|
|
|
543
426
|
try {
|
|
544
427
|
decoded = atob(raw);
|
|
545
428
|
} catch {
|
|
546
|
-
this.#log.warn("atob failed (not base64?)");
|
|
547
429
|
return { blob, extension, size };
|
|
548
430
|
}
|
|
549
431
|
let isJson = false;
|
|
@@ -559,7 +441,6 @@ class PrefViewer extends HTMLElement {
|
|
|
559
441
|
}
|
|
560
442
|
|
|
561
443
|
async #initStorage(db, table) {
|
|
562
|
-
this.#log.debug("#initStorage()", { db, table });
|
|
563
444
|
if (window.gltfDB && window.gltfDB.name === db && window.gltfDB.objectStoreNames.contains(table)) {
|
|
564
445
|
return true;
|
|
565
446
|
}
|
|
@@ -568,7 +449,6 @@ class PrefViewer extends HTMLElement {
|
|
|
568
449
|
|
|
569
450
|
// Methods for managing Asset Containers
|
|
570
451
|
#setVisibilityOfWallAndFloorInModel(show) {
|
|
571
|
-
this.#log.debug("#setVisibilityOfWallAndFloorInModel()", { show });
|
|
572
452
|
if (!this.#data.containers.model.assetContainer || !this.#data.containers.model.visible) {
|
|
573
453
|
return false;
|
|
574
454
|
}
|
|
@@ -581,11 +461,9 @@ class PrefViewer extends HTMLElement {
|
|
|
581
461
|
if (!optionMaterial || !optionMaterial.prefix || !optionMaterial.value) {
|
|
582
462
|
return false;
|
|
583
463
|
}
|
|
584
|
-
this.#log.debug("#setOptionsMaterial()", optionMaterial);
|
|
585
464
|
|
|
586
465
|
const material = this.#data.containers.materials.assetContainer?.materials.find((mat) => mat.name === optionMaterial.value) || null;
|
|
587
466
|
if (!material) {
|
|
588
|
-
this.#log.warn("material not found", { wanted: optionMaterial.value });
|
|
589
467
|
return false;
|
|
590
468
|
}
|
|
591
469
|
|
|
@@ -614,7 +492,6 @@ class PrefViewer extends HTMLElement {
|
|
|
614
492
|
}
|
|
615
493
|
|
|
616
494
|
#setOptionsMaterials() {
|
|
617
|
-
this.#log.debug("#setOptionsMaterials()");
|
|
618
495
|
let someSetted = false;
|
|
619
496
|
Object.values(this.#data.options.materials).forEach((material) => {
|
|
620
497
|
let settedMaterial = this.#setOptionsMaterial(material);
|
|
@@ -624,14 +501,12 @@ class PrefViewer extends HTMLElement {
|
|
|
624
501
|
}
|
|
625
502
|
|
|
626
503
|
#setOptionsCamera() {
|
|
627
|
-
this.#log.debug("#setOptionsCamera()", this.#data.options.camera);
|
|
628
504
|
if (!this.#data.options.camera.value || (!this.#data.options.camera.changed && !this.#data.containers.model.assetContainer.changed)) {
|
|
629
505
|
return false;
|
|
630
506
|
}
|
|
631
507
|
|
|
632
508
|
let camera = this.#data.containers.model.assetContainer?.cameras.find((cam) => cam.name === this.#data.options.camera.value) || null;
|
|
633
509
|
if (!camera) {
|
|
634
|
-
this.#log.warn("camera not found", { wanted: this.#data.options.camera.value });
|
|
635
510
|
return false;
|
|
636
511
|
}
|
|
637
512
|
|
|
@@ -646,7 +521,6 @@ class PrefViewer extends HTMLElement {
|
|
|
646
521
|
|
|
647
522
|
#addContainer(container) {
|
|
648
523
|
if (container.assetContainer && !container.visible && container.show) {
|
|
649
|
-
this.#log.debug("#addContainer()", { name: container.name });
|
|
650
524
|
container.assetContainer.addAllToScene();
|
|
651
525
|
container.visible = true;
|
|
652
526
|
}
|
|
@@ -654,14 +528,12 @@ class PrefViewer extends HTMLElement {
|
|
|
654
528
|
|
|
655
529
|
#removeContainer(container) {
|
|
656
530
|
if (container.assetContainer && container.visible) {
|
|
657
|
-
this.#log.debug("#removeContainer()", { name: container.name });
|
|
658
531
|
container.assetContainer.removeAllFromScene();
|
|
659
532
|
container.visible = false;
|
|
660
533
|
}
|
|
661
534
|
}
|
|
662
535
|
|
|
663
536
|
#replaceContainer(container, newAssetContainer) {
|
|
664
|
-
this.#log.debug("#replaceContainer()", { name: container.name });
|
|
665
537
|
this.#removeContainer(container);
|
|
666
538
|
container.assetContainer = newAssetContainer;
|
|
667
539
|
container.assetContainer.meshes.forEach((mesh) => {
|
|
@@ -672,12 +544,9 @@ class PrefViewer extends HTMLElement {
|
|
|
672
544
|
}
|
|
673
545
|
|
|
674
546
|
async #loadAssetContainer(container) {
|
|
675
|
-
this.#log.group(`#loadAssetContainer(${container?.name})`);
|
|
676
547
|
let storage = container?.storage;
|
|
677
548
|
|
|
678
549
|
if (!storage) {
|
|
679
|
-
this.#log.warn("no storage provided");
|
|
680
|
-
this.#log.groupEnd();
|
|
681
550
|
return false;
|
|
682
551
|
}
|
|
683
552
|
|
|
@@ -688,8 +557,6 @@ class PrefViewer extends HTMLElement {
|
|
|
688
557
|
const object = await loadModel(storage.id, storage.table);
|
|
689
558
|
source = object.data;
|
|
690
559
|
if (object.timestamp === container.timestamp) {
|
|
691
|
-
this.#log.info("no change from IndexedDB (timestamp match)");
|
|
692
|
-
this.#log.groupEnd();
|
|
693
560
|
return false;
|
|
694
561
|
} else {
|
|
695
562
|
container.changed = { timestamp: object.timestamp, size: object.size };
|
|
@@ -697,8 +564,6 @@ class PrefViewer extends HTMLElement {
|
|
|
697
564
|
}
|
|
698
565
|
|
|
699
566
|
if (!source) {
|
|
700
|
-
this.#log.warn("no source URL or data");
|
|
701
|
-
this.#log.groupEnd();
|
|
702
567
|
return false;
|
|
703
568
|
}
|
|
704
569
|
|
|
@@ -706,14 +571,11 @@ class PrefViewer extends HTMLElement {
|
|
|
706
571
|
|
|
707
572
|
let { blob, extension, size } = this.#decodeBase64(source);
|
|
708
573
|
if (blob && extension) {
|
|
709
|
-
this.#log.debug("source is base64", { extension, size });
|
|
710
574
|
file = new File([blob], `${container.name}${extension}`, {
|
|
711
575
|
type: blob.type,
|
|
712
576
|
});
|
|
713
577
|
if (!container.changed) {
|
|
714
578
|
if (container.timestamp === null && container.size === size) {
|
|
715
|
-
this.#log.info("no change (base64 size match)");
|
|
716
|
-
this.#log.groupEnd();
|
|
717
579
|
return false;
|
|
718
580
|
} else {
|
|
719
581
|
container.changed = { timestamp: null, size: size };
|
|
@@ -724,8 +586,6 @@ class PrefViewer extends HTMLElement {
|
|
|
724
586
|
extension = extMatch ? `.${extMatch[1].toLowerCase()}` : ".gltf";
|
|
725
587
|
const { fileSize, fileTimestamp } = await this.#getServerFileDataHeader(source);
|
|
726
588
|
if (container.timestamp === fileTimestamp && container.size === fileSize) {
|
|
727
|
-
this.#log.info("no change (remote HEAD match)");
|
|
728
|
-
this.#log.groupEnd();
|
|
729
589
|
return false;
|
|
730
590
|
} else {
|
|
731
591
|
container.changed = { timestamp: fileTimestamp, size: fileSize };
|
|
@@ -742,15 +602,10 @@ class PrefViewer extends HTMLElement {
|
|
|
742
602
|
},
|
|
743
603
|
};
|
|
744
604
|
|
|
745
|
-
this.#
|
|
746
|
-
const res = LoadAssetContainerAsync(file || source, this.#scene, options);
|
|
747
|
-
this.#log.groupEnd();
|
|
748
|
-
return res;
|
|
605
|
+
return LoadAssetContainerAsync(file || source, this.#scene, options);
|
|
749
606
|
}
|
|
750
607
|
|
|
751
608
|
async #loadContainers(loadModel = true, loadEnvironment = true, loadMaterials = true) {
|
|
752
|
-
this.#log.group("#loadContainers()");
|
|
753
|
-
this.#log.debug("flags", { loadModel, loadEnvironment, loadMaterials });
|
|
754
609
|
const promiseArray = [];
|
|
755
610
|
promiseArray.push(loadModel ? this.#loadAssetContainer(this.#data.containers.model) : false);
|
|
756
611
|
promiseArray.push(loadEnvironment ? this.#loadAssetContainer(this.#data.containers.environment) : false);
|
|
@@ -763,29 +618,22 @@ class PrefViewer extends HTMLElement {
|
|
|
763
618
|
const materialsContainer = values[2];
|
|
764
619
|
|
|
765
620
|
if (modelContainer.status === "fulfilled" && modelContainer.value) {
|
|
766
|
-
this.#log.timeEnd(`babylon:LoadAssetContainerAsync:model`);
|
|
767
621
|
this.#replaceContainer(this.#data.containers.model, modelContainer.value);
|
|
768
622
|
this.#storeChangedFlagsForContainer(this.#data.containers.model);
|
|
769
623
|
} else {
|
|
770
|
-
this.#log.debug("model container unchanged / not loaded");
|
|
771
624
|
this.#data.containers.model.show ? this.#addContainer(this.#data.containers.model) : this.#removeContainer(this.#data.containers.model);
|
|
772
625
|
}
|
|
773
626
|
|
|
774
627
|
if (environmentContainer.status === "fulfilled" && environmentContainer.value) {
|
|
775
|
-
this.#log.timeEnd(`babylon:LoadAssetContainerAsync:environment`);
|
|
776
628
|
this.#replaceContainer(this.#data.containers.environment, environmentContainer.value);
|
|
777
629
|
this.#storeChangedFlagsForContainer(this.#data.containers.environment);
|
|
778
630
|
} else {
|
|
779
|
-
this.#log.debug("environment container unchanged / not loaded");
|
|
780
631
|
this.#data.containers.environment.show ? this.#addContainer(this.#data.containers.environment) : this.#removeContainer(this.#data.containers.environment);
|
|
781
632
|
}
|
|
782
633
|
|
|
783
634
|
if (materialsContainer.status === "fulfilled" && materialsContainer.value) {
|
|
784
|
-
this.#log.timeEnd(`babylon:LoadAssetContainerAsync:materials`);
|
|
785
635
|
this.#replaceContainer(this.#data.containers.materials, materialsContainer.value);
|
|
786
636
|
this.#storeChangedFlagsForContainer(this.#data.containers.materials);
|
|
787
|
-
} else if (loadMaterials) {
|
|
788
|
-
this.#log.debug("materials container unchanged / not loaded");
|
|
789
637
|
}
|
|
790
638
|
|
|
791
639
|
this.#setOptionsMaterials();
|
|
@@ -794,7 +642,6 @@ class PrefViewer extends HTMLElement {
|
|
|
794
642
|
|
|
795
643
|
this.#resetChangedFlags();
|
|
796
644
|
|
|
797
|
-
this.#log.info("dispatch: model-loaded");
|
|
798
645
|
this.dispatchEvent(
|
|
799
646
|
new CustomEvent("model-loaded", {
|
|
800
647
|
detail: { success: "" },
|
|
@@ -802,11 +649,9 @@ class PrefViewer extends HTMLElement {
|
|
|
802
649
|
composed: true,
|
|
803
650
|
})
|
|
804
651
|
);
|
|
805
|
-
this.#log.groupEnd();
|
|
806
652
|
})
|
|
807
653
|
.catch((error) => {
|
|
808
654
|
console.error("PrefViewer: failed to load model", error);
|
|
809
|
-
this.#log.error("failed to load model", error);
|
|
810
655
|
this.dispatchEvent(
|
|
811
656
|
new CustomEvent("model-error", {
|
|
812
657
|
detail: { error: error },
|
|
@@ -814,17 +659,13 @@ class PrefViewer extends HTMLElement {
|
|
|
814
659
|
composed: true,
|
|
815
660
|
})
|
|
816
661
|
);
|
|
817
|
-
this.#log.groupEnd();
|
|
818
662
|
});
|
|
819
663
|
}
|
|
820
664
|
|
|
821
665
|
// Public Methods
|
|
822
666
|
loadConfig(config) {
|
|
823
|
-
this.#log.group("loadConfig()");
|
|
824
667
|
config = typeof config === "string" ? JSON.parse(config) : config;
|
|
825
668
|
if (!config) {
|
|
826
|
-
this.#log.warn("no config");
|
|
827
|
-
this.#log.groupEnd();
|
|
828
669
|
return false;
|
|
829
670
|
}
|
|
830
671
|
|
|
@@ -841,16 +682,11 @@ class PrefViewer extends HTMLElement {
|
|
|
841
682
|
this.#checkMaterialsChanged(config.options);
|
|
842
683
|
}
|
|
843
684
|
|
|
844
|
-
this.#log.debug("config applied", { containers: this.#data.containers, options: this.#data.options });
|
|
845
685
|
this.#initialized && this.#loadContainers(true, true, true);
|
|
846
|
-
this.#log.groupEnd();
|
|
847
686
|
}
|
|
848
687
|
|
|
849
688
|
setOptions(options) {
|
|
850
|
-
this.#log.group("setOptions()");
|
|
851
689
|
if (!options) {
|
|
852
|
-
this.#log.warn("no options");
|
|
853
|
-
this.#log.groupEnd();
|
|
854
690
|
return false;
|
|
855
691
|
}
|
|
856
692
|
let someSetted = false;
|
|
@@ -862,73 +698,57 @@ class PrefViewer extends HTMLElement {
|
|
|
862
698
|
}
|
|
863
699
|
this.#resetChangedFlags();
|
|
864
700
|
debugger;
|
|
865
|
-
this.#log.debug("setOptions result", { someSetted });
|
|
866
|
-
this.#log.groupEnd();
|
|
867
701
|
return someSetted;
|
|
868
702
|
}
|
|
869
703
|
|
|
870
704
|
loadModel(model) {
|
|
871
|
-
this.#log.group("loadModel()");
|
|
872
705
|
model = typeof model === "string" ? JSON.parse(model) : model;
|
|
873
706
|
if (!model) {
|
|
874
|
-
this.#log.warn("no model");
|
|
875
|
-
this.#log.groupEnd();
|
|
876
707
|
return false;
|
|
877
708
|
}
|
|
878
709
|
this.#data.containers.model.storage = model.storage || null;
|
|
879
710
|
this.#data.containers.model.show = model.visible !== undefined ? model.visible : this.#data.containers.model.show;
|
|
880
711
|
this.#initialized && this.#loadContainers(true, false, false);
|
|
881
|
-
this.#log.groupEnd();
|
|
882
712
|
}
|
|
883
713
|
|
|
884
714
|
loadScene(scene) {
|
|
885
|
-
this.#log.group("loadScene()");
|
|
886
715
|
scene = typeof scene === "string" ? JSON.parse(scene) : scene;
|
|
887
716
|
if (!scene) {
|
|
888
|
-
this.#log.warn("no scene");
|
|
889
|
-
this.#log.groupEnd();
|
|
890
717
|
return false;
|
|
891
718
|
}
|
|
892
719
|
this.#data.containers.environment.storage = scene.storage || null;
|
|
893
720
|
this.#data.containers.environment.show = scene.visible !== undefined ? scene.visible : this.#data.containers.environment.show;
|
|
894
721
|
this.#initialized && this.#loadContainers(false, true, false);
|
|
895
|
-
this.#log.groupEnd();
|
|
896
722
|
}
|
|
897
723
|
|
|
898
724
|
showModel() {
|
|
899
|
-
this.#log.info("showModel()");
|
|
900
725
|
this.#data.containers.model.show = true;
|
|
901
726
|
this.#addContainer(this.#data.containers.model);
|
|
902
727
|
}
|
|
903
728
|
|
|
904
729
|
hideModel() {
|
|
905
|
-
this.#log.info("hideModel()");
|
|
906
730
|
this.#data.containers.model.show = false;
|
|
907
731
|
this.#removeContainer(this.#data.containers.model);
|
|
908
732
|
}
|
|
909
733
|
|
|
910
734
|
showScene() {
|
|
911
|
-
this.#log.info("showScene()");
|
|
912
735
|
this.#data.containers.environment.show = true;
|
|
913
736
|
this.#addContainer(this.#data.containers.environment);
|
|
914
737
|
this.#setVisibilityOfWallAndFloorInModel();
|
|
915
738
|
}
|
|
916
739
|
|
|
917
740
|
hideScene() {
|
|
918
|
-
this.#log.info("hideScene()");
|
|
919
741
|
this.#data.containers.environment.show = false;
|
|
920
742
|
this.#removeContainer(this.#data.containers.environment);
|
|
921
743
|
this.#setVisibilityOfWallAndFloorInModel();
|
|
922
744
|
}
|
|
923
745
|
|
|
924
746
|
downloadModelGLB() {
|
|
925
|
-
this.#log.info("downloadModelGLB()");
|
|
926
747
|
const fileName = "model";
|
|
927
748
|
GLTF2Export.GLBAsync(this.#data.containers.model.assetContainer, fileName, { exportWithoutWaitingForScene: true }).then((glb) => glb.downloadFiles());
|
|
928
749
|
}
|
|
929
750
|
|
|
930
751
|
downloadModelUSDZ() {
|
|
931
|
-
this.#log.info("downloadModelUSDZ()");
|
|
932
752
|
const fileName = "model";
|
|
933
753
|
USDZExportAsync(this.#data.containers.model.assetContainer).then((response) => {
|
|
934
754
|
if (response) {
|
|
@@ -938,7 +758,6 @@ class PrefViewer extends HTMLElement {
|
|
|
938
758
|
}
|
|
939
759
|
|
|
940
760
|
downloadModelAndSceneUSDZ() {
|
|
941
|
-
this.#log.info("downloadModelAndSceneUSDZ()");
|
|
942
761
|
const fileName = "scene";
|
|
943
762
|
USDZExportAsync(this.#scene).then((response) => {
|
|
944
763
|
if (response) {
|
|
@@ -948,7 +767,6 @@ class PrefViewer extends HTMLElement {
|
|
|
948
767
|
}
|
|
949
768
|
|
|
950
769
|
downloadModelAndSceneGLB() {
|
|
951
|
-
this.#log.info("downloadModelAndSceneGLB()");
|
|
952
770
|
const fileName = "scene";
|
|
953
771
|
GLTF2Export.GLBAsync(this.#scene, fileName, { exportWithoutWaitingForScene: true }).then((glb) => glb.downloadFiles());
|
|
954
772
|
}
|