@preference-sl/pref-viewer 2.10.0-beta.16 → 2.10.0-beta.18
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/gltf-storage.js +150 -71
- package/src/index.js +48 -35
package/package.json
CHANGED
package/src/gltf-storage.js
CHANGED
|
@@ -1,137 +1,214 @@
|
|
|
1
|
-
//
|
|
2
|
-
|
|
1
|
+
// wwwroot/js/gltf-storage.js
|
|
2
|
+
|
|
3
|
+
// Public, inspectable namespace
|
|
4
|
+
const PC = (globalThis.PrefConfigurator ??= {});
|
|
5
|
+
PC.version = PC.version ?? "1.0.1"; // bump if your schema changes!!
|
|
6
|
+
PC.db = PC.db ?? null;
|
|
7
|
+
|
|
8
|
+
function _getDbOrThrow() {
|
|
9
|
+
const db = PC.db;
|
|
10
|
+
if (!db) throw new Error("Database not initialized. Call initDb(...) first.");
|
|
11
|
+
return db;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
// --- internal helpers -------------------------------------------------------
|
|
15
|
+
function _openEnsuringStore(dbName, storeName) {
|
|
3
16
|
return new Promise((resolve, reject) => {
|
|
4
|
-
const
|
|
17
|
+
const open = indexedDB.open(dbName, 5);
|
|
5
18
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
resolve();
|
|
10
|
-
}
|
|
19
|
+
open.onblocked = () => reject(new Error("Open blocked by another tab or worker"));
|
|
20
|
+
open.onerror = () => reject(open.error);
|
|
21
|
+
open.onsuccess = (e) => {
|
|
22
|
+
resolve(e.target.result);
|
|
23
|
+
}
|
|
24
|
+
open.onupgradeneeded = (ev) => {
|
|
25
|
+
const upgradeDb = ev.target.result;
|
|
11
26
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
const store = db.createObjectStore(storeName, { keyPath: "id" });
|
|
16
|
-
store.createIndex("type", "type", { unique: false });
|
|
17
|
-
store.createIndex("timestamp", "timestamp", { unique: false });
|
|
27
|
+
// Eliminar la object store si ya existe
|
|
28
|
+
if (upgradeDb.objectStoreNames.contains(storeName)) {
|
|
29
|
+
upgradeDb.deleteObjectStore(storeName);
|
|
18
30
|
}
|
|
31
|
+
|
|
32
|
+
const store = upgradeDb.createObjectStore(storeName, { keyPath: 'id' });
|
|
33
|
+
store.createIndex('expirationTimeStamp', 'expirationTimeStamp', { unique: false });
|
|
19
34
|
};
|
|
20
35
|
});
|
|
21
36
|
}
|
|
22
37
|
|
|
38
|
+
// --- public API -------------------------------------------------------------
|
|
39
|
+
|
|
40
|
+
// Inicializar IndexedDB y dejar el handle en PrefConfigurator.db (público)
|
|
41
|
+
export async function initDb(dbName, storeName) {
|
|
42
|
+
const db = await _openEnsuringStore(dbName, storeName);
|
|
43
|
+
// Close any previous handle to avoid versionchange blocking
|
|
44
|
+
try { PC.db?.close?.(); } catch { }
|
|
45
|
+
PC.db = db;
|
|
46
|
+
|
|
47
|
+
// If another tab upgrades, close gracefully so next call can re-init
|
|
48
|
+
db.onversionchange = () => {
|
|
49
|
+
try { db.close(); } catch { }
|
|
50
|
+
if (PC.db === db) PC.db = null;
|
|
51
|
+
console.warn("[PrefConfigurator] DB connection closed due to versionchange. Re-run initDb().");
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
|
|
23
55
|
// Guardar modelo
|
|
24
56
|
export async function saveModel(modelDataStr, storeName) {
|
|
25
57
|
return new Promise((resolve, reject) => {
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
58
|
+
let db;
|
|
59
|
+
try { db = _getDbOrThrow(); } catch (e) { reject(e); return; }
|
|
60
|
+
|
|
61
|
+
let modelData;
|
|
62
|
+
try { modelData = JSON.parse(modelDataStr); }
|
|
63
|
+
catch (e) { reject(new Error("saveModel: modelDataStr is not valid JSON")); return; }
|
|
31
64
|
|
|
32
65
|
const dataToStore = {
|
|
33
66
|
...modelData,
|
|
34
67
|
data: modelData.data,
|
|
35
|
-
size: modelData
|
|
36
|
-
timestamp: new Date().toISOString(),
|
|
68
|
+
size: (modelData?.data?.length ?? 0)
|
|
37
69
|
};
|
|
38
70
|
|
|
39
|
-
const
|
|
40
|
-
const store =
|
|
41
|
-
const
|
|
71
|
+
const tx = db.transaction([storeName], "readwrite");
|
|
72
|
+
const store = tx.objectStore(storeName);
|
|
73
|
+
const req = store.put(dataToStore);
|
|
42
74
|
|
|
43
|
-
|
|
44
|
-
|
|
75
|
+
req.onerror = () => reject(req.error);
|
|
76
|
+
req.onsuccess = () => resolve();
|
|
45
77
|
});
|
|
46
78
|
}
|
|
47
79
|
|
|
48
80
|
// Cargar modelo
|
|
49
81
|
export function loadModel(modelId, storeName) {
|
|
50
82
|
return new Promise((resolve, reject) => {
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
const tx = globalThis.gltfDB.transaction([storeName], "readonly");
|
|
83
|
+
let db;
|
|
84
|
+
try { db = _getDbOrThrow(); } catch (e) { reject(e); return; }
|
|
85
|
+
|
|
86
|
+
const tx = db.transaction([storeName], "readonly");
|
|
56
87
|
const store = tx.objectStore(storeName);
|
|
57
88
|
const req = store.get(modelId);
|
|
89
|
+
|
|
58
90
|
req.onerror = () => reject(req.error);
|
|
59
91
|
req.onsuccess = () => resolve(req.result ?? null);
|
|
60
92
|
});
|
|
61
93
|
}
|
|
62
94
|
|
|
95
|
+
// Descargar archivo desde base64
|
|
63
96
|
export function downloadFileFromBytes(fileName, bytesBase64, mimeType) {
|
|
64
97
|
const link = document.createElement("a");
|
|
65
98
|
link.download = fileName;
|
|
66
99
|
link.href = `data:${mimeType};base64,${bytesBase64}`;
|
|
67
100
|
document.body.appendChild(link);
|
|
68
101
|
link.click();
|
|
69
|
-
|
|
102
|
+
link.remove();
|
|
70
103
|
}
|
|
71
104
|
|
|
72
105
|
// Obtener todos los modelos (solo metadata)
|
|
73
106
|
export async function getAllModels(storeName) {
|
|
74
107
|
return new Promise((resolve, reject) => {
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
return;
|
|
78
|
-
}
|
|
108
|
+
let db;
|
|
109
|
+
try { db = _getDbOrThrow(); } catch (e) { reject(e); return; }
|
|
79
110
|
|
|
80
|
-
const
|
|
81
|
-
const store =
|
|
82
|
-
const
|
|
111
|
+
const tx = db.transaction([storeName], "readonly");
|
|
112
|
+
const store = tx.objectStore(storeName);
|
|
113
|
+
const req = store.getAll();
|
|
83
114
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
const results =
|
|
115
|
+
req.onerror = () => reject(req.error);
|
|
116
|
+
req.onsuccess = () => {
|
|
117
|
+
const items = Array.isArray(req.result) ? req.result : [];
|
|
118
|
+
const results = items.map(item => ({
|
|
88
119
|
id: item.id,
|
|
89
120
|
metadata: item.metadata,
|
|
90
|
-
|
|
91
|
-
size: item.size
|
|
92
|
-
type: item.type,
|
|
121
|
+
timeStamp: item.timeStamp,
|
|
122
|
+
size: item.size
|
|
93
123
|
}));
|
|
124
|
+
// keep old behavior: return JSON string
|
|
94
125
|
resolve(JSON.stringify(results));
|
|
95
126
|
};
|
|
96
127
|
});
|
|
97
128
|
}
|
|
98
129
|
|
|
99
|
-
// Eliminar modelo
|
|
130
|
+
// Eliminar modelo por id
|
|
100
131
|
export async function deleteModel(modelId, storeName) {
|
|
101
132
|
return new Promise((resolve, reject) => {
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
return;
|
|
105
|
-
}
|
|
133
|
+
let db;
|
|
134
|
+
try { db = _getDbOrThrow(); } catch (e) { reject(e); return; }
|
|
106
135
|
|
|
107
|
-
const
|
|
108
|
-
const store =
|
|
109
|
-
const
|
|
136
|
+
const tx = db.transaction([storeName], "readwrite");
|
|
137
|
+
const store = tx.objectStore(storeName);
|
|
138
|
+
const req = store.delete(modelId);
|
|
110
139
|
|
|
111
|
-
|
|
112
|
-
|
|
140
|
+
req.onerror = () => reject(req.error);
|
|
141
|
+
req.onsuccess = () => resolve();
|
|
113
142
|
});
|
|
114
143
|
}
|
|
115
144
|
|
|
116
|
-
// Limpiar toda la
|
|
145
|
+
// Limpiar toda la store
|
|
117
146
|
export async function clearAll(storeName) {
|
|
118
147
|
return new Promise((resolve, reject) => {
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
148
|
+
let db;
|
|
149
|
+
try { db = _getDbOrThrow(); } catch (e) { reject(e); return; }
|
|
150
|
+
|
|
151
|
+
const tx = db.transaction([storeName], "readwrite");
|
|
152
|
+
const store = tx.objectStore(storeName);
|
|
153
|
+
const req = store.clear();
|
|
154
|
+
|
|
155
|
+
req.onerror = () => reject(req.error);
|
|
156
|
+
req.onsuccess = () => resolve();
|
|
157
|
+
});
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
// Borrar modelos expirados usando el índice "expirationTimeStamp"
|
|
161
|
+
export async function cleanExpiredModels(storeName) {
|
|
162
|
+
return new Promise((resolve, reject) => {
|
|
163
|
+
let db;
|
|
164
|
+
try { db = _getDbOrThrow(); } catch (e) { reject(e); return; }
|
|
165
|
+
|
|
166
|
+
const tx = db.transaction([storeName], "readwrite");
|
|
167
|
+
const store = tx.objectStore(storeName);
|
|
168
|
+
|
|
169
|
+
const index = store.index("expirationTimeStamp");
|
|
170
|
+
const now = Date.now();
|
|
171
|
+
const range = IDBKeyRange.upperBound(now);
|
|
172
|
+
const cursorRequest = index.openCursor(range);
|
|
173
|
+
|
|
174
|
+
cursorRequest.onerror = () => reject(cursorRequest.error);
|
|
175
|
+
cursorRequest.onsuccess = (event) => {
|
|
176
|
+
const cursor = event.target.result;
|
|
177
|
+
if (cursor) {
|
|
178
|
+
cursor.delete();
|
|
179
|
+
cursor.continue();
|
|
180
|
+
}
|
|
181
|
+
};
|
|
182
|
+
|
|
183
|
+
tx.oncomplete = () => resolve();
|
|
184
|
+
tx.onerror = () => reject(tx.error);
|
|
185
|
+
});
|
|
186
|
+
}
|
|
123
187
|
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
188
|
+
// Utilidades opcionales y visibles (por si las quieres usar en consola)
|
|
189
|
+
export function closeDb() {
|
|
190
|
+
if (PC.db) {
|
|
191
|
+
try { PC.db.close(); } catch { }
|
|
192
|
+
PC.db = null;
|
|
193
|
+
}
|
|
194
|
+
}
|
|
127
195
|
|
|
128
|
-
|
|
129
|
-
|
|
196
|
+
export function deleteDatabase(dbName) {
|
|
197
|
+
return new Promise((resolve, reject) => {
|
|
198
|
+
// Close current handle if points to this DB
|
|
199
|
+
if (PC.db && PC.db.name === dbName) {
|
|
200
|
+
try { PC.db.close(); } catch { }
|
|
201
|
+
PC.db = null;
|
|
202
|
+
}
|
|
203
|
+
const req = indexedDB.deleteDatabase(dbName);
|
|
204
|
+
req.onblocked = () => reject(new Error("Delete blocked by another tab or worker"));
|
|
205
|
+
req.onerror = () => reject(req.error);
|
|
206
|
+
req.onsuccess = () => resolve();
|
|
130
207
|
});
|
|
131
208
|
}
|
|
132
209
|
|
|
210
|
+
// Attach a frozen, public API (no private state)
|
|
133
211
|
(function attachPublicAPI(global) {
|
|
134
|
-
const root = (global.PrefConfigurator ??= {});
|
|
135
212
|
const storage = {
|
|
136
213
|
initDb,
|
|
137
214
|
saveModel,
|
|
@@ -139,10 +216,12 @@ export async function clearAll(storeName) {
|
|
|
139
216
|
getAllModels,
|
|
140
217
|
deleteModel,
|
|
141
218
|
clearAll,
|
|
219
|
+
cleanExpiredModels,
|
|
142
220
|
downloadFileFromBytes,
|
|
221
|
+
// extras
|
|
222
|
+
closeDb,
|
|
223
|
+
deleteDatabase,
|
|
143
224
|
};
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
root.version = root.version ?? "1.0.0";
|
|
147
|
-
root.storage = Object.freeze(storage);
|
|
225
|
+
// free to inspect PC.db in devtools
|
|
226
|
+
global.PrefConfigurator.storage = Object.freeze(storage);
|
|
148
227
|
})(globalThis);
|
package/src/index.js
CHANGED
|
@@ -60,7 +60,7 @@ class PrefViewer extends HTMLElement {
|
|
|
60
60
|
storage: null,
|
|
61
61
|
visible: false,
|
|
62
62
|
size: null,
|
|
63
|
-
|
|
63
|
+
timeStamp: null,
|
|
64
64
|
changed: false,
|
|
65
65
|
},
|
|
66
66
|
environment: {
|
|
@@ -70,7 +70,7 @@ class PrefViewer extends HTMLElement {
|
|
|
70
70
|
storage: null,
|
|
71
71
|
visible: false,
|
|
72
72
|
size: null,
|
|
73
|
-
|
|
73
|
+
timeStamp: null,
|
|
74
74
|
changed: false,
|
|
75
75
|
},
|
|
76
76
|
materials: {
|
|
@@ -80,7 +80,7 @@ class PrefViewer extends HTMLElement {
|
|
|
80
80
|
show: true,
|
|
81
81
|
visible: false,
|
|
82
82
|
size: null,
|
|
83
|
-
|
|
83
|
+
timeStamp: null,
|
|
84
84
|
changed: false,
|
|
85
85
|
},
|
|
86
86
|
},
|
|
@@ -299,7 +299,6 @@ class PrefViewer extends HTMLElement {
|
|
|
299
299
|
}
|
|
300
300
|
|
|
301
301
|
#setStatusOptionsLoaded() {
|
|
302
|
-
|
|
303
302
|
const toLoadDetail = {
|
|
304
303
|
inneWallMaterial: !!this.#data.options.materials.innerWall.changed,
|
|
305
304
|
outerWallMaterial: !!this.#data.options.materials.outerWall.changed,
|
|
@@ -310,7 +309,7 @@ class PrefViewer extends HTMLElement {
|
|
|
310
309
|
inneWallMaterial: !!this.#data.options.materials.innerWall.changed?.success,
|
|
311
310
|
outerWallMaterial: !!this.#data.options.materials.outerWall.changed?.success,
|
|
312
311
|
innerFloorMaterial: !!this.#data.options.materials.innerFloor.changed?.success,
|
|
313
|
-
|
|
312
|
+
outerFloorMaterial: !!this.#data.options.materials.outerFloor.changed?.success,
|
|
314
313
|
};
|
|
315
314
|
|
|
316
315
|
const detail = {
|
|
@@ -354,10 +353,17 @@ class PrefViewer extends HTMLElement {
|
|
|
354
353
|
return someChanged;
|
|
355
354
|
}
|
|
356
355
|
|
|
357
|
-
#storeChangedFlagsForContainer(container) {
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
356
|
+
#storeChangedFlagsForContainer(container, success) {
|
|
357
|
+
if (success) {
|
|
358
|
+
container.timeStamp = container.changed.timeStamp;
|
|
359
|
+
container.size = container.changed.size;
|
|
360
|
+
container.changed.success = success;
|
|
361
|
+
} else if(container.changed) {
|
|
362
|
+
container.source = container.changed.source;
|
|
363
|
+
container.changed.success = success;
|
|
364
|
+
} else {
|
|
365
|
+
container.changed = { success: success };
|
|
366
|
+
}
|
|
361
367
|
}
|
|
362
368
|
|
|
363
369
|
#resetChangedFlags() {
|
|
@@ -451,6 +457,7 @@ class PrefViewer extends HTMLElement {
|
|
|
451
457
|
}
|
|
452
458
|
|
|
453
459
|
#createLights() {
|
|
460
|
+
|
|
454
461
|
// 1) Stronger ambient fill
|
|
455
462
|
this.#hemiLight = new HemisphericLight("hemiLight", new Vector3(-10, 10, -10), this.#scene);
|
|
456
463
|
this.#hemiLight.intensity = 0.6;
|
|
@@ -503,8 +510,8 @@ class PrefViewer extends HTMLElement {
|
|
|
503
510
|
xhr.onload = () => {
|
|
504
511
|
if (xhr.status === 200) {
|
|
505
512
|
const size = parseInt(xhr.getResponseHeader("Content-Length"));
|
|
506
|
-
const
|
|
507
|
-
resolve([size,
|
|
513
|
+
const timeStamp = new Date(xhr.getResponseHeader("Last-Modified")).toISOString();
|
|
514
|
+
resolve([size, timeStamp]);
|
|
508
515
|
} else {
|
|
509
516
|
resolve([0, null]);
|
|
510
517
|
}
|
|
@@ -564,7 +571,6 @@ class PrefViewer extends HTMLElement {
|
|
|
564
571
|
}
|
|
565
572
|
|
|
566
573
|
#setOptionsMaterial(optionMaterial) {
|
|
567
|
-
debugger;
|
|
568
574
|
if (!optionMaterial || !optionMaterial.prefix || !optionMaterial.value) {
|
|
569
575
|
return false;
|
|
570
576
|
}
|
|
@@ -680,10 +686,10 @@ class PrefViewer extends HTMLElement {
|
|
|
680
686
|
await this.#initStorage(storage.db, storage.table);
|
|
681
687
|
const object = await loadModel(storage.id, storage.table);
|
|
682
688
|
source = object.data;
|
|
683
|
-
if (object.
|
|
689
|
+
if (object.timeStamp === container.timeStamp) {
|
|
684
690
|
return false;
|
|
685
691
|
} else {
|
|
686
|
-
container.changed
|
|
692
|
+
Object.assign(container.changed, { timeStamp: object.timeStamp, size: object.size, success: false });
|
|
687
693
|
}
|
|
688
694
|
}
|
|
689
695
|
|
|
@@ -699,20 +705,20 @@ class PrefViewer extends HTMLElement {
|
|
|
699
705
|
type: blob.type,
|
|
700
706
|
});
|
|
701
707
|
if (!container.changed) {
|
|
702
|
-
if (container.
|
|
708
|
+
if (container.timeStamp === null && container.size === size) {
|
|
703
709
|
return false;
|
|
704
710
|
} else {
|
|
705
|
-
container.changed
|
|
711
|
+
Object.assign(container.changed, { timeStamp: null, size: size, success: false });
|
|
706
712
|
}
|
|
707
713
|
}
|
|
708
714
|
} else {
|
|
709
715
|
const extMatch = source.match(/\.(gltf|glb)(\?|#|$)/i);
|
|
710
716
|
extension = extMatch ? `.${extMatch[1].toLowerCase()}` : ".gltf";
|
|
711
717
|
const [fileSize, fileTimestamp ] = await this.#getServerFileDataHeader(source);
|
|
712
|
-
if (container.size === fileSize && container.
|
|
718
|
+
if (container.size === fileSize && container.timeStamp === fileTimestamp) {
|
|
713
719
|
return false;
|
|
714
720
|
} else {
|
|
715
|
-
container.changed
|
|
721
|
+
Object.assign(container.changed, { timeStamp: fileTimestamp, size: fileSize, success: false });
|
|
716
722
|
}
|
|
717
723
|
}
|
|
718
724
|
|
|
@@ -730,24 +736,12 @@ class PrefViewer extends HTMLElement {
|
|
|
730
736
|
}
|
|
731
737
|
|
|
732
738
|
async #loadContainers(loadModel = true, loadEnvironment = true, loadMaterials = true) {
|
|
739
|
+
this.#setStatusSceneLoading();
|
|
740
|
+
|
|
733
741
|
const promiseArray = [];
|
|
734
742
|
promiseArray.push(loadModel ? this.#loadAssetContainer(this.#data.containers.model) : false);
|
|
735
743
|
promiseArray.push(loadEnvironment ? this.#loadAssetContainer(this.#data.containers.environment) : false);
|
|
736
744
|
promiseArray.push(loadMaterials ? this.#loadAssetContainer(this.#data.containers.materials) : false);
|
|
737
|
-
debugger;
|
|
738
|
-
const loadingDetail = {
|
|
739
|
-
model: !!this.#data.containers.model.changed,
|
|
740
|
-
environment: !!this.#data.containers.environment.changed,
|
|
741
|
-
materials: !!this.#data.containers.materials.changed,
|
|
742
|
-
options: {
|
|
743
|
-
camera: !!this.#data.options.camera.changed,
|
|
744
|
-
inneWallMaterial: !!this.#data.options.materials.innerWall.changed,
|
|
745
|
-
outerWallMaterial: !!this.#data.options.materials.outerWall.changed,
|
|
746
|
-
innerFloorMaterial: !!this.#data.options.materials.innerFloor.changed,
|
|
747
|
-
outerFloorMaterial: !!this.#data.options.materials.outerFloor.changed,
|
|
748
|
-
},
|
|
749
|
-
};
|
|
750
|
-
this.#setStatusSceneLoading(loadingDetail);
|
|
751
745
|
|
|
752
746
|
Promise.allSettled(promiseArray)
|
|
753
747
|
.then(async (values) => {
|
|
@@ -757,21 +751,25 @@ debugger;
|
|
|
757
751
|
|
|
758
752
|
if (modelContainer.status === "fulfilled" && modelContainer.value) {
|
|
759
753
|
this.#replaceContainer(this.#data.containers.model, modelContainer.value);
|
|
760
|
-
this.#storeChangedFlagsForContainer(this.#data.containers.model);
|
|
754
|
+
this.#storeChangedFlagsForContainer(this.#data.containers.model, true);
|
|
761
755
|
} else {
|
|
762
756
|
this.#data.containers.model.show ? this.#addContainer(this.#data.containers.model) : this.#removeContainer(this.#data.containers.model);
|
|
757
|
+
this.#storeChangedFlagsForContainer(this.#data.containers.model, false);
|
|
763
758
|
}
|
|
764
759
|
|
|
765
760
|
if (environmentContainer.status === "fulfilled" && environmentContainer.value) {
|
|
766
761
|
this.#replaceContainer(this.#data.containers.environment, environmentContainer.value);
|
|
767
|
-
this.#storeChangedFlagsForContainer(this.#data.containers.environment);
|
|
762
|
+
this.#storeChangedFlagsForContainer(this.#data.containers.environment, true);
|
|
768
763
|
} else {
|
|
769
764
|
this.#data.containers.environment.show ? this.#addContainer(this.#data.containers.environment) : this.#removeContainer(this.#data.containers.environment);
|
|
765
|
+
this.#storeChangedFlagsForContainer(this.#data.containers.environment, false);
|
|
770
766
|
}
|
|
771
767
|
|
|
772
768
|
if (materialsContainer.status === "fulfilled" && materialsContainer.value) {
|
|
773
769
|
this.#replaceContainer(this.#data.containers.materials, materialsContainer.value);
|
|
774
|
-
this.#storeChangedFlagsForContainer(this.#data.containers.materials);
|
|
770
|
+
this.#storeChangedFlagsForContainer(this.#data.containers.materials, true);
|
|
771
|
+
} else {
|
|
772
|
+
this.#storeChangedFlagsForContainer(this.#data.containers.materials, false);
|
|
775
773
|
}
|
|
776
774
|
|
|
777
775
|
this.#setOptionsMaterials();
|
|
@@ -802,10 +800,13 @@ debugger;
|
|
|
802
800
|
}
|
|
803
801
|
|
|
804
802
|
// Containers
|
|
803
|
+
this.#data.containers.model.changed = { storage: this.#data.containers.model.storage || null };
|
|
805
804
|
this.#data.containers.model.storage = config.model?.storage || null;
|
|
806
805
|
this.#data.containers.model.show = config.model?.visible !== undefined ? config.model.visible : this.#data.containers.model.show;
|
|
806
|
+
this.#data.containers.environment.changed = { storage: this.#data.containers.environment.storage || null };
|
|
807
807
|
this.#data.containers.environment.storage = config.scene?.storage || null;
|
|
808
808
|
this.#data.containers.environment.show = config.scene?.visible !== undefined ? config.scene.visible : this.#data.containers.environment.show;
|
|
809
|
+
this.#data.containers.materials.changed = { storage: this.#data.containers.materials.storage || null };
|
|
809
810
|
this.#data.containers.materials.storage = config.materials?.storage || null;
|
|
810
811
|
|
|
811
812
|
// Options
|
|
@@ -843,6 +844,7 @@ debugger;
|
|
|
843
844
|
if (!model) {
|
|
844
845
|
return false;
|
|
845
846
|
}
|
|
847
|
+
this.#data.containers.model.changed = { storage: this.#data.containers.model.storage || null };
|
|
846
848
|
this.#data.containers.model.storage = model.storage || null;
|
|
847
849
|
this.#data.containers.model.show = model.visible !== undefined ? model.visible : this.#data.containers.model.show;
|
|
848
850
|
this.initialized && this.#loadContainers(true, false, false);
|
|
@@ -853,11 +855,22 @@ debugger;
|
|
|
853
855
|
if (!scene) {
|
|
854
856
|
return false;
|
|
855
857
|
}
|
|
858
|
+
this.#data.containers.environment.changed = { storage: this.#data.containers.environment.storage || null };
|
|
856
859
|
this.#data.containers.environment.storage = scene.storage || null;
|
|
857
860
|
this.#data.containers.environment.show = scene.visible !== undefined ? scene.visible : this.#data.containers.environment.show;
|
|
858
861
|
this.initialized && this.#loadContainers(false, true, false);
|
|
859
862
|
}
|
|
860
863
|
|
|
864
|
+
loadMaterials(materials) {
|
|
865
|
+
materials = typeof materials === "string" ? JSON.parse(materials) : materials;
|
|
866
|
+
if (!materials) {
|
|
867
|
+
return false;
|
|
868
|
+
}
|
|
869
|
+
this.#data.containers.materials.changed = { storage: this.#data.containers.materials.storage || null };
|
|
870
|
+
this.#data.containers.materials.storage = materials.storage || null;
|
|
871
|
+
this.initialized && this.#loadContainers(false, false, true);
|
|
872
|
+
}
|
|
873
|
+
|
|
861
874
|
showModel() {
|
|
862
875
|
this.#data.containers.model.show = true;
|
|
863
876
|
this.#addContainer(this.#data.containers.model);
|