@littlecarlito/blorktools 0.50.3 → 0.51.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.
Files changed (114) hide show
  1. package/bin/cli.js +69 -0
  2. package/package.json +13 -7
  3. package/src/asset_debugger/axis-indicator/axis-indicator.css +6 -0
  4. package/src/asset_debugger/axis-indicator/axis-indicator.html +20 -0
  5. package/src/asset_debugger/axis-indicator/axis-indicator.js +822 -0
  6. package/src/asset_debugger/debugger-scene/debugger-scene.css +142 -0
  7. package/src/asset_debugger/debugger-scene/debugger-scene.html +80 -0
  8. package/src/asset_debugger/debugger-scene/debugger-scene.js +791 -0
  9. package/src/asset_debugger/header/header.css +73 -0
  10. package/src/asset_debugger/header/header.html +24 -0
  11. package/src/asset_debugger/header/header.js +224 -0
  12. package/src/asset_debugger/index.html +76 -0
  13. package/src/asset_debugger/landing-page/landing-page.css +396 -0
  14. package/src/asset_debugger/landing-page/landing-page.html +81 -0
  15. package/src/asset_debugger/landing-page/landing-page.js +611 -0
  16. package/src/asset_debugger/loading-splash/loading-splash.css +195 -0
  17. package/src/asset_debugger/loading-splash/loading-splash.html +22 -0
  18. package/src/asset_debugger/loading-splash/loading-splash.js +59 -0
  19. package/src/asset_debugger/loading-splash/preview-loading-splash.js +66 -0
  20. package/src/asset_debugger/main.css +14 -0
  21. package/src/asset_debugger/modals/examples-modal/examples-modal.css +41 -0
  22. package/src/asset_debugger/modals/examples-modal/examples-modal.html +18 -0
  23. package/src/asset_debugger/modals/examples-modal/examples-modal.js +111 -0
  24. package/src/asset_debugger/modals/examples-modal/examples.js +125 -0
  25. package/src/asset_debugger/modals/html-editor-modal/html-editor-modal.css +452 -0
  26. package/src/asset_debugger/modals/html-editor-modal/html-editor-modal.html +87 -0
  27. package/src/asset_debugger/modals/html-editor-modal/html-editor-modal.js +675 -0
  28. package/src/asset_debugger/modals/mesh-info-modal/mesh-info-modal.css +219 -0
  29. package/src/asset_debugger/modals/mesh-info-modal/mesh-info-modal.html +20 -0
  30. package/src/asset_debugger/modals/mesh-info-modal/mesh-info-modal.js +548 -0
  31. package/src/asset_debugger/modals/settings-modal/settings-modal.css +103 -0
  32. package/src/asset_debugger/modals/settings-modal/settings-modal.html +158 -0
  33. package/src/asset_debugger/modals/settings-modal/settings-modal.js +475 -0
  34. package/src/asset_debugger/panels/asset-panel/asset-panel.css +263 -0
  35. package/src/asset_debugger/panels/asset-panel/asset-panel.html +123 -0
  36. package/src/asset_debugger/panels/asset-panel/asset-panel.js +136 -0
  37. package/src/asset_debugger/panels/asset-panel/atlas-heading/atlas-heading.css +94 -0
  38. package/src/asset_debugger/panels/asset-panel/atlas-heading/atlas-heading.js +312 -0
  39. package/src/asset_debugger/panels/asset-panel/mesh-heading/mesh-heading.css +129 -0
  40. package/src/asset_debugger/panels/asset-panel/mesh-heading/mesh-heading.js +486 -0
  41. package/src/asset_debugger/panels/asset-panel/rig-heading/rig-heading.css +545 -0
  42. package/src/asset_debugger/panels/asset-panel/rig-heading/rig-heading.js +538 -0
  43. package/src/asset_debugger/panels/asset-panel/uv-heading/uv-heading.css +70 -0
  44. package/src/asset_debugger/panels/asset-panel/uv-heading/uv-heading.js +586 -0
  45. package/src/asset_debugger/panels/world-panel/world-panel.css +364 -0
  46. package/src/asset_debugger/panels/world-panel/world-panel.html +173 -0
  47. package/src/asset_debugger/panels/world-panel/world-panel.js +1891 -0
  48. package/src/asset_debugger/router.js +190 -0
  49. package/src/asset_debugger/util/animation/playback/animation-playback-controller.js +150 -0
  50. package/src/asset_debugger/util/animation/playback/animation-preview-controller.js +316 -0
  51. package/src/asset_debugger/util/animation/playback/css3d-bounce-controller.js +400 -0
  52. package/src/asset_debugger/util/animation/playback/css3d-reversal-controller.js +821 -0
  53. package/src/asset_debugger/util/animation/render/css3d-prerender-controller.js +696 -0
  54. package/src/asset_debugger/util/animation/render/debug-texture-factory.js +0 -0
  55. package/src/asset_debugger/util/animation/render/iframe2texture-render-controller.js +199 -0
  56. package/src/asset_debugger/util/animation/render/image2texture-prerender-controller.js +461 -0
  57. package/src/asset_debugger/util/animation/render/pbr-material-factory.js +82 -0
  58. package/src/asset_debugger/util/common.css +280 -0
  59. package/src/asset_debugger/util/data/animation-classifier.js +323 -0
  60. package/src/asset_debugger/util/data/duplicate-handler.js +20 -0
  61. package/src/asset_debugger/util/data/glb-buffer-manager.js +407 -0
  62. package/src/asset_debugger/util/data/glb-classifier.js +290 -0
  63. package/src/asset_debugger/util/data/html-formatter.js +76 -0
  64. package/src/asset_debugger/util/data/html-linter.js +276 -0
  65. package/src/asset_debugger/util/data/localstorage-manager.js +265 -0
  66. package/src/asset_debugger/util/data/mesh-html-manager.js +295 -0
  67. package/src/asset_debugger/util/data/string-serder.js +303 -0
  68. package/src/asset_debugger/util/data/texture-classifier.js +663 -0
  69. package/src/asset_debugger/util/data/upload/background-file-handler.js +292 -0
  70. package/src/asset_debugger/util/data/upload/dropzone-preview-controller.js +396 -0
  71. package/src/asset_debugger/util/data/upload/file-upload-manager.js +495 -0
  72. package/src/asset_debugger/util/data/upload/glb-file-handler.js +36 -0
  73. package/src/asset_debugger/util/data/upload/glb-preview-controller.js +317 -0
  74. package/src/asset_debugger/util/data/upload/lighting-file-handler.js +194 -0
  75. package/src/asset_debugger/util/data/upload/model-file-manager.js +104 -0
  76. package/src/asset_debugger/util/data/upload/texture-file-handler.js +166 -0
  77. package/src/asset_debugger/util/data/upload/zip-handler.js +686 -0
  78. package/src/asset_debugger/util/loaders/html2canvas-loader.js +107 -0
  79. package/src/asset_debugger/util/rig/bone-kinematics.js +403 -0
  80. package/src/asset_debugger/util/rig/rig-constraint-manager.js +618 -0
  81. package/src/asset_debugger/util/rig/rig-controller.js +612 -0
  82. package/src/asset_debugger/util/rig/rig-factory.js +628 -0
  83. package/src/asset_debugger/util/rig/rig-handle-factory.js +46 -0
  84. package/src/asset_debugger/util/rig/rig-label-factory.js +441 -0
  85. package/src/asset_debugger/util/rig/rig-mouse-handler.js +377 -0
  86. package/src/asset_debugger/util/rig/rig-state-manager.js +175 -0
  87. package/src/asset_debugger/util/rig/rig-tooltip-manager.js +267 -0
  88. package/src/asset_debugger/util/rig/rig-ui-factory.js +700 -0
  89. package/src/asset_debugger/util/scene/background-manager.js +284 -0
  90. package/src/asset_debugger/util/scene/camera-controller.js +243 -0
  91. package/src/asset_debugger/util/scene/css3d-debug-controller.js +406 -0
  92. package/src/asset_debugger/util/scene/css3d-frame-factory.js +113 -0
  93. package/src/asset_debugger/util/scene/css3d-scene-manager.js +529 -0
  94. package/src/asset_debugger/util/scene/glb-controller.js +208 -0
  95. package/src/asset_debugger/util/scene/lighting-manager.js +690 -0
  96. package/src/asset_debugger/util/scene/threejs-model-manager.js +437 -0
  97. package/src/asset_debugger/util/scene/threejs-preview-manager.js +207 -0
  98. package/src/asset_debugger/util/scene/threejs-preview-setup.js +478 -0
  99. package/src/asset_debugger/util/scene/threejs-scene-controller.js +286 -0
  100. package/src/asset_debugger/util/scene/ui-manager.js +107 -0
  101. package/src/asset_debugger/util/state/animation-state.js +128 -0
  102. package/src/asset_debugger/util/state/css3d-state.js +83 -0
  103. package/src/asset_debugger/util/state/glb-preview-state.js +31 -0
  104. package/src/asset_debugger/util/state/log-util.js +197 -0
  105. package/src/asset_debugger/util/state/scene-state.js +452 -0
  106. package/src/asset_debugger/util/state/threejs-state.js +54 -0
  107. package/src/asset_debugger/util/workers/lighting-worker.js +61 -0
  108. package/src/asset_debugger/util/workers/model-worker.js +109 -0
  109. package/src/asset_debugger/util/workers/texture-worker.js +54 -0
  110. package/src/asset_debugger/util/workers/worker-manager.js +212 -0
  111. package/src/asset_debugger/widgets/mesh-info-widget.js +280 -0
  112. package/src/index.html +261 -0
  113. package/src/index.js +8 -0
  114. package/vite.config.js +66 -0
@@ -0,0 +1,791 @@
1
+ import * as THREE from 'three';
2
+ import { loadSettings, saveSettings } from '../util/data/localstorage-manager.js';
3
+ import { SettingsModal } from '../modals/settings-modal/settings-modal.js';
4
+ import { initAssetPanel } from '../panels/asset-panel/asset-panel.js';
5
+ import { initHtmlEditorModal } from '../modals/html-editor-modal/html-editor-modal.js';
6
+ import { initWorldPanel } from '../panels/world-panel/world-panel.js';
7
+ import { getState, printStateReport, hasFiles } from '../util/state/scene-state.js';
8
+ import { initUiManager } from '../util/scene/ui-manager.js';
9
+ import { hideLoadingSplash, showLoadingSplash, updateLoadingProgress } from '../loading-splash/loading-splash.js';
10
+ import { terminateAllWorkers } from '../util/workers/worker-manager.js';
11
+ import { CSS3DDebugController } from '../util/scene/css3d-debug-controller.js';
12
+ import * as sceneController from '../util/scene/threejs-scene-controller.js';
13
+ import * as cameraController from '../util/scene/camera-controller.js';
14
+ import * as rigController from '../util/rig/rig-controller.js';
15
+ import * as lightingManager from '../util/scene/lighting-manager.js';
16
+ import * as backgroundManager from '../util/scene/background-manager.js';
17
+ import * as modelHandler from '../util/scene/threejs-model-manager.js';
18
+ import * as textureHandler from '../util/data/upload/texture-file-handler.js';
19
+ import * as worldPanel from '../panels/world-panel/world-panel.js';
20
+ import * as assetPanel from '../panels/asset-panel/asset-panel.js';
21
+ import * as htmlEditorModule from '../modals/html-editor-modal/html-editor-modal.js';
22
+ import * as meshInfoModule from '../modals/mesh-info-modal/mesh-info-modal.js'
23
+ import * as stateModule from '../util/state/scene-state.js';
24
+ import { initModelIntegration } from '../util/scene/glb-controller.js';
25
+
26
+ const DEBUG_LIGHTING = false;
27
+
28
+ let css3dDebugController = null;
29
+
30
+ const componentsLoaded = {
31
+ worldPanel: false,
32
+ assetPanel: false,
33
+ settingsModal: false,
34
+ htmlEditor: false,
35
+ meshInfo:false,
36
+ scene: false
37
+ };
38
+
39
+ const resourcesLoaded = {
40
+ componentsLoaded: false,
41
+ sceneInitialized: false,
42
+ lightingLoaded: false,
43
+ backgroundLoaded: false,
44
+ modelLoaded: false,
45
+ controlsReady: false
46
+ };
47
+
48
+ let loadingComplete = false;
49
+ let isPageUnloading = false;
50
+
51
+ export function setupDebuggerScene() {
52
+ showLoadingSplash("Setting up debugging environment");
53
+ resetThreeJSState();
54
+
55
+ getState();
56
+ printStateReport('debugger-scene');
57
+
58
+ updateLoadingProgress("Initializing UI");
59
+ initUiManager();
60
+
61
+ updateLoadingProgress("Loading HTML components");
62
+ loadComponentHtml();
63
+
64
+ updateLoadingProgress("Setting up 3D scene");
65
+ initializeScene();
66
+
67
+ updateLoadingProgress("Setting up event listeners");
68
+ const restartDebugBtn = document.getElementById('restart-debug');
69
+ if (restartDebugBtn) {
70
+ restartDebugBtn.addEventListener('click', restartDebugging);
71
+ }
72
+
73
+ setTimeout(ensureCollapsibleHeadersWork, 500);
74
+
75
+ updateLoadingProgress("Finalizing startup");
76
+ return cleanupDebuggerScene;
77
+ }
78
+
79
+ export function getCSS3DDebugController() {
80
+ return css3dDebugController;
81
+ }
82
+
83
+ export function setCSS3DDebugController(controller) {
84
+ css3dDebugController = controller;
85
+ }
86
+
87
+ function resetThreeJSState() {
88
+ const state = stateModule.getState();
89
+
90
+ if (state.scene) {
91
+ while(state.scene.children && state.scene.children.length > 0) {
92
+ state.scene.remove(state.scene.children[0]);
93
+ }
94
+ }
95
+
96
+ if (state.renderer) {
97
+ state.renderer.dispose();
98
+ }
99
+
100
+ if (state.controls) {
101
+ state.controls.dispose();
102
+ }
103
+
104
+ stateModule.updateState('scene', null);
105
+ stateModule.updateState('camera', null);
106
+ stateModule.updateState('renderer', null);
107
+ stateModule.updateState('controls', null);
108
+ stateModule.updateState('cube', null);
109
+ stateModule.updateState('animating', false);
110
+
111
+ setTimeout(() => {
112
+ const noneRadioBtn = document.querySelector('input[name="bg-option"][value="none"]');
113
+ if (noneRadioBtn) {
114
+ noneRadioBtn.checked = true;
115
+ }
116
+
117
+ const bgPreviewCanvas = document.getElementById('bg-preview-canvas');
118
+ const hdrPreviewCanvas = document.getElementById('hdr-preview-canvas');
119
+
120
+ if (bgPreviewCanvas) bgPreviewCanvas.style.opacity = '0.3';
121
+ if (hdrPreviewCanvas) hdrPreviewCanvas.style.opacity = '0.3';
122
+ }, 100);
123
+ }
124
+
125
+ function cleanupDebuggerScene() {
126
+ isPageUnloading = true;
127
+
128
+ cleanupCSS3DComponents();
129
+
130
+ if (htmlEditorModule.resetInitialization) {
131
+ htmlEditorModule.resetInitialization();
132
+ }
133
+
134
+ const debugControls = document.querySelector('.debug-controls');
135
+ if (debugControls) {
136
+ debugControls.style.display = 'none';
137
+ }
138
+
139
+ terminateAllWorkers();
140
+
141
+ setTimeout(() => {
142
+ if (worldPanel.cleanupWorldPanel) {
143
+ worldPanel.cleanupWorldPanel();
144
+ }
145
+
146
+ if (stateModule.clearAllFiles) {
147
+ stateModule.clearAllFiles(true);
148
+ }
149
+
150
+ const state = stateModule.getState();
151
+
152
+ if (state.animating && sceneController.stopAnimation) {
153
+ sceneController.stopAnimation();
154
+ }
155
+
156
+ if (state.renderer) {
157
+ state.renderer.dispose();
158
+ stateModule.updateState('renderer', null);
159
+ }
160
+
161
+ const controls = state.controls;
162
+ if (controls) {
163
+ if (cameraController.disposeControls) {
164
+ cameraController.disposeControls();
165
+ }
166
+ if (controls.dispose) {
167
+ controls.dispose();
168
+ }
169
+ stateModule.updateState('controls', null);
170
+ }
171
+
172
+ if (state.scene) {
173
+ while(state.scene.children && state.scene.children.length > 0) {
174
+ const obj = state.scene.children[0];
175
+ if (obj.geometry) obj.geometry.dispose();
176
+ if (obj.material) {
177
+ if (Array.isArray(obj.material)) {
178
+ obj.material.forEach(mat => mat.dispose());
179
+ } else {
180
+ obj.material.dispose();
181
+ }
182
+ }
183
+ state.scene.remove(obj);
184
+ }
185
+ stateModule.updateState('scene', null);
186
+ }
187
+
188
+ const canvasElements = document.querySelectorAll('canvas[data-animation-id]');
189
+ canvasElements.forEach(canvas => {
190
+ if (typeof canvas.cleanup === 'function') {
191
+ canvas.cleanup();
192
+ }
193
+
194
+ const animId = canvas.getAttribute('data-animation-id');
195
+ if (animId) {
196
+ cancelAnimationFrame(parseInt(animId, 10));
197
+ }
198
+ });
199
+
200
+ const noneRadioBtn = document.querySelector('input[name="bg-option"][value="none"]');
201
+ if (noneRadioBtn) {
202
+ noneRadioBtn.checked = true;
203
+ }
204
+
205
+ const bgPreviewCanvas = document.getElementById('bg-preview-canvas');
206
+ const hdrPreviewCanvas = document.getElementById('hdr-preview-canvas');
207
+
208
+ if (bgPreviewCanvas) bgPreviewCanvas.style.opacity = '0.3';
209
+ if (hdrPreviewCanvas) hdrPreviewCanvas.style.opacity = '0.3';
210
+ }, 0);
211
+
212
+ return null;
213
+ }
214
+
215
+ function cleanupCSS3DComponents() {
216
+ if (css3dDebugController) {
217
+ css3dDebugController.cleanup();
218
+ css3dDebugController = null;
219
+ }
220
+
221
+ const css3dElements = document.querySelectorAll('[style*="position: absolute"][style*="z-index: 1000"]');
222
+ css3dElements.forEach(element => {
223
+ if (element.parentNode) {
224
+ element.parentNode.removeChild(element);
225
+ }
226
+ });
227
+
228
+ const css3dIframes = document.querySelectorAll('iframe[style*="border: 2px solid #00ff88"]');
229
+ css3dIframes.forEach(iframe => {
230
+ if (iframe.parentNode) {
231
+ iframe.parentNode.removeChild(iframe);
232
+ }
233
+ });
234
+
235
+ const css3dRenderers = document.querySelectorAll('div[style*="position: absolute"][style*="pointer-events: none"]');
236
+ css3dRenderers.forEach(renderer => {
237
+ if (renderer.parentNode && renderer.style.zIndex === '1000') {
238
+ renderer.parentNode.removeChild(renderer);
239
+ }
240
+ });
241
+ }
242
+
243
+ function loadComponentHtml() {
244
+ const worldPanelPromise = fetch('./panels/world-panel/world-panel.html')
245
+ .then(response => response.text())
246
+ .then(html => {
247
+ document.getElementById('world-tab-container').innerHTML = html;
248
+ initWorldPanel(true);
249
+ componentsLoaded.worldPanel = true;
250
+ });
251
+
252
+ const assetPanelPromise = fetch('./panels/asset-panel/asset-panel.html')
253
+ .then(response => response.text())
254
+ .then(html => {
255
+ document.getElementById('asset-tab-container').innerHTML = html;
256
+ initAssetPanel();
257
+ componentsLoaded.assetPanel = true;
258
+ });
259
+
260
+ const settingsModalPromise = fetch('./modals/settings-modal/settings-modal.html')
261
+ .then(response => response.text())
262
+ .then(html => {
263
+ const container = document.getElementById('settings-modal-container');
264
+ if (container) {
265
+ container.innerHTML = html;
266
+ setTimeout(() => new SettingsModal(), 0);
267
+ }
268
+ componentsLoaded.settingsModal = true;
269
+ });
270
+
271
+ const axisIndicatorPromise = fetch('./axis-indicator/axis-indicator.html')
272
+ .then(response => response.text())
273
+ .then(html => {
274
+ const axisSettingsContainer = document.getElementById('axis-settings-container');
275
+ if (axisSettingsContainer) {
276
+ axisSettingsContainer.innerHTML = html;
277
+
278
+ const axisTabButton = document.querySelector('.settings-tab-button[data-tab="axis-settings"]');
279
+ if (axisTabButton && axisTabButton.classList.contains('active')) {
280
+ const axisSettings = document.getElementById('axis-settings');
281
+ if (axisSettings) {
282
+ axisSettings.classList.add('active');
283
+ }
284
+ }
285
+ }
286
+ });
287
+
288
+ const htmlEditorPromise = fetch('./modals/html-editor-modal/html-editor-modal.html')
289
+ .then(response => response.text())
290
+ .then(html => {
291
+ document.getElementById('html-editor-modal-container').innerHTML = html;
292
+
293
+ const modalElement = document.getElementById('html-editor-modal');
294
+ if (modalElement) {
295
+ modalElement.style.display = 'none';
296
+
297
+ if (htmlEditorModule.resetInitialization) {
298
+ htmlEditorModule.resetInitialization();
299
+ }
300
+ initHtmlEditorModal();
301
+ initModelIntegration();
302
+ componentsLoaded.htmlEditor = true;
303
+ } else {
304
+ throw new Error('HTML editor modal element not found');
305
+ }
306
+ });
307
+
308
+ const meshInfoPromise = fetch('./modals/mesh-info-modal/mesh-info-modal.html')
309
+ .then(response => response.text())
310
+ .then(html => {
311
+ const container = document.getElementById('mesh-info-modal-container');
312
+
313
+ if (container) {
314
+ container.innerHTML = html;
315
+
316
+ const modalElement = document.getElementById('mesh-info-modal');
317
+
318
+ if (modalElement) {
319
+ modalElement.style.display = 'none';
320
+
321
+ if (meshInfoModule.resetInitialization) {
322
+ meshInfoModule.resetInitialization();
323
+ }
324
+
325
+ meshInfoModule.initMeshInfoModal();
326
+
327
+ componentsLoaded.meshInfo = true;
328
+ } else {
329
+ throw new Error('Mesh info modal element not found');
330
+ }
331
+ } else {
332
+ throw new Error('Mesh info modal container not found');
333
+ }
334
+ })
335
+ .catch(error => {
336
+ componentsLoaded.meshInfo = false;
337
+ });
338
+
339
+ Promise.all([
340
+ worldPanelPromise,
341
+ assetPanelPromise,
342
+ settingsModalPromise,
343
+ axisIndicatorPromise,
344
+ htmlEditorPromise,
345
+ meshInfoPromise
346
+ ])
347
+ .then(() => {
348
+ resourcesLoaded.componentsLoaded = true;
349
+ startDebugging();
350
+ })
351
+ .catch(errors => {
352
+ resourcesLoaded.componentsLoaded = true;
353
+ startDebugging();
354
+ });
355
+ }
356
+
357
+ function checkAllResourcesLoaded() {
358
+ if (resourcesLoaded.componentsLoaded &&
359
+ resourcesLoaded.sceneInitialized &&
360
+ resourcesLoaded.lightingLoaded &&
361
+ resourcesLoaded.backgroundLoaded &&
362
+ resourcesLoaded.modelLoaded &&
363
+ resourcesLoaded.controlsReady) {
364
+
365
+ if (!loadingComplete) {
366
+ loadingComplete = true;
367
+ hideLoadingSplash();
368
+ }
369
+ }
370
+ }
371
+
372
+ function initializeScene() {
373
+ const viewport = document.getElementById('viewport');
374
+
375
+ const ensureViewportSize = () => {
376
+ if (viewport.offsetWidth === 0 || viewport.offsetHeight === 0) {
377
+ setTimeout(ensureViewportSize, 50);
378
+ return;
379
+ }
380
+
381
+ sceneController.initScene(viewport, false);
382
+ sceneController.startAnimation();
383
+ componentsLoaded.scene = true;
384
+ resourcesLoaded.sceneInitialized = true;
385
+ checkAllResourcesLoaded();
386
+
387
+ setTimeout(() => {
388
+ if (hasFiles() && cameraController.resetControls) {
389
+ cameraController.resetControls();
390
+ }
391
+ resourcesLoaded.controlsReady = true;
392
+ checkAllResourcesLoaded();
393
+ }, 500);
394
+ };
395
+
396
+ ensureViewportSize();
397
+ }
398
+
399
+ function startDebugging() {
400
+ const savedSettings = loadSettings();
401
+
402
+ if (savedSettings && savedSettings.rigOptions) {
403
+ rigController.updateRigOptions(savedSettings.rigOptions);
404
+ }
405
+
406
+ initializeDebugger(savedSettings);
407
+
408
+ const waitForSceneAndProcessFiles = () => {
409
+ if (!resourcesLoaded.sceneInitialized) {
410
+ setTimeout(waitForSceneAndProcessFiles, 100);
411
+ return;
412
+ }
413
+ processFilesFromState();
414
+ };
415
+
416
+ waitForSceneAndProcessFiles();
417
+ }
418
+
419
+ function processFilesFromState() {
420
+ if (isPageUnloading) {
421
+ resourcesLoaded.lightingLoaded = true;
422
+ resourcesLoaded.backgroundLoaded = true;
423
+ resourcesLoaded.modelLoaded = true;
424
+ resourcesLoaded.controlsReady = true;
425
+ checkAllResourcesLoaded();
426
+ return;
427
+ }
428
+
429
+ const currentState = stateModule.getState();
430
+
431
+ resourcesLoaded.lightingLoaded = false;
432
+ resourcesLoaded.backgroundLoaded = false;
433
+ resourcesLoaded.modelLoaded = false;
434
+
435
+ let promiseChain = Promise.resolve();
436
+
437
+ const checkContinueProcessing = () => {
438
+ if (isPageUnloading) {
439
+ throw new Error('Page unloading - processing aborted');
440
+ }
441
+ return true;
442
+ };
443
+
444
+ if (stateModule.hasLightingFile() && checkContinueProcessing()) {
445
+ const lightingFile = stateModule.getLightingFile();
446
+ promiseChain = promiseChain.then(() => {
447
+ return lightingManager.setupEnvironmentLighting(lightingFile)
448
+ .then(texture => {
449
+ const state = stateModule.getState();
450
+ if (state && state.scene && texture && !state.scene.environment) {
451
+ state.scene.environment = texture;
452
+ }
453
+
454
+ if (worldPanel.updateLightingInfo) {
455
+ const lightingMetadata = {
456
+ fileName: lightingFile.name,
457
+ type: lightingFile.name.split('.').pop().toUpperCase(),
458
+ fileSizeBytes: lightingFile.size,
459
+ dimensions: texture && texture.image ? {
460
+ width: texture.image.width || 0,
461
+ height: texture.image.height || 0
462
+ } : { width: 0, height: 0 }
463
+ };
464
+
465
+ worldPanel.updateLightingInfo(lightingMetadata);
466
+
467
+ if (worldPanel.toggleOptionVisibility) {
468
+ worldPanel.toggleOptionVisibility('hdr-option', true);
469
+ }
470
+ }
471
+ return texture;
472
+ });
473
+ })
474
+ .then(() => {
475
+ resourcesLoaded.lightingLoaded = true;
476
+ checkAllResourcesLoaded();
477
+ })
478
+ .catch(error => {
479
+ resourcesLoaded.lightingLoaded = true;
480
+ checkAllResourcesLoaded();
481
+ });
482
+ } else {
483
+ resourcesLoaded.lightingLoaded = true;
484
+ checkAllResourcesLoaded();
485
+ }
486
+
487
+ if (stateModule.hasBackgroundFile() && checkContinueProcessing()) {
488
+ const backgroundFile = stateModule.getBackgroundFile();
489
+ promiseChain = promiseChain.then(() => {
490
+ return backgroundManager.setupBackgroundImage(backgroundFile)
491
+ .then(texture => {
492
+ if (texture) {
493
+ const event = new CustomEvent('background-updated', {
494
+ detail: { texture, file: backgroundFile }
495
+ });
496
+ document.dispatchEvent(event);
497
+ }
498
+ return texture;
499
+ });
500
+ })
501
+ .then(() => {
502
+ resourcesLoaded.backgroundLoaded = true;
503
+ checkAllResourcesLoaded();
504
+ })
505
+ .catch(error => {
506
+ resourcesLoaded.backgroundLoaded = true;
507
+ checkAllResourcesLoaded();
508
+ });
509
+ } else {
510
+ resourcesLoaded.backgroundLoaded = true;
511
+ checkAllResourcesLoaded();
512
+ }
513
+
514
+ if (stateModule.hasModelFile() && checkContinueProcessing()) {
515
+ promiseChain = promiseChain.then(() => {
516
+ return modelHandler.loadDebugModel();
517
+ })
518
+ .then(() => {
519
+ resourcesLoaded.modelLoaded = true;
520
+ checkAllResourcesLoaded();
521
+ })
522
+ .catch(error => {
523
+ resourcesLoaded.modelLoaded = true;
524
+ checkAllResourcesLoaded();
525
+ });
526
+ } else {
527
+ resourcesLoaded.modelLoaded = true;
528
+ checkAllResourcesLoaded();
529
+ }
530
+
531
+ if ((stateModule.hasBaseColorFile() || stateModule.hasOrmFile() || stateModule.hasNormalFile()) && checkContinueProcessing()) {
532
+ promiseChain = promiseChain.then(() => {
533
+ const promises = [];
534
+
535
+ if (stateModule.hasBaseColorFile()) {
536
+ promises.push(textureHandler.loadTextureFromFile(stateModule.getBaseColorFile(), 'baseColor'));
537
+ }
538
+ if (stateModule.hasOrmFile()) {
539
+ promises.push(textureHandler.loadTextureFromFile(stateModule.getOrmFile(), 'orm'));
540
+ }
541
+ if (stateModule.hasNormalFile()) {
542
+ promises.push(textureHandler.loadTextureFromFile(stateModule.getNormalFile(), 'normal'));
543
+ }
544
+
545
+ return Promise.all(promises);
546
+ });
547
+ }
548
+
549
+ promiseChain = promiseChain.then(() => {
550
+ if (worldPanel.initWorldPanel) {
551
+ worldPanel.initWorldPanel(false);
552
+
553
+ if (worldPanel.updateWorldPanel) {
554
+ worldPanel.updateWorldPanel();
555
+ }
556
+
557
+ const state = stateModule.getState();
558
+ if (state.lightingFile && worldPanel.toggleOptionVisibility) {
559
+ worldPanel.toggleOptionVisibility('hdr-option', true);
560
+
561
+ if (state.lightingFile && worldPanel.updateLightingInfo) {
562
+ const lightingMetadata = {
563
+ fileName: state.lightingFile.name,
564
+ type: state.lightingFile.name.split('.').pop().toUpperCase(),
565
+ fileSizeBytes: state.lightingFile.size
566
+ };
567
+ worldPanel.updateLightingInfo(lightingMetadata);
568
+ }
569
+
570
+ const noneRadio = document.querySelector('input[name="bg-option"][value="none"]');
571
+ if (noneRadio) {
572
+ noneRadio.checked = true;
573
+ }
574
+ }
575
+ }
576
+
577
+ if (assetPanel.initAssetPanel) {
578
+ assetPanel.initAssetPanel();
579
+ }
580
+ });
581
+
582
+ return promiseChain.catch(error => {
583
+ resourcesLoaded.lightingLoaded = true;
584
+ resourcesLoaded.backgroundLoaded = true;
585
+ resourcesLoaded.modelLoaded = true;
586
+ checkAllResourcesLoaded();
587
+ });
588
+ }
589
+
590
+ function initializeDebugger(settings) {
591
+ const uploadSection = document.getElementById('upload-section');
592
+
593
+ const checkHeaderAndInit = () => {
594
+ const debugControls = document.querySelector('.debug-controls');
595
+ const viewport = document.getElementById('viewport');
596
+ const tabContainer = document.getElementById('tab-container');
597
+
598
+ if (!debugControls) {
599
+ setTimeout(checkHeaderAndInit, 50);
600
+ return;
601
+ }
602
+
603
+ if (uploadSection) {
604
+ uploadSection.style.display = 'none';
605
+ }
606
+
607
+ if (debugControls) {
608
+ debugControls.style.display = 'flex';
609
+ }
610
+
611
+ if (viewport) {
612
+ viewport.style.display = 'block';
613
+ }
614
+
615
+ if (tabContainer) {
616
+ const isPanelHidden = settings && settings.tabPanelHidden;
617
+
618
+ if (isPanelHidden) {
619
+ tabContainer.style.cssText = 'display: none !important; visibility: hidden !important; opacity: 0 !important;';
620
+ } else {
621
+ tabContainer.style.cssText = 'display: flex !important; visibility: visible !important; opacity: 1 !important;';
622
+ }
623
+ }
624
+
625
+ setupTabNavigation();
626
+ setupTogglePanelButton();
627
+ };
628
+
629
+ checkHeaderAndInit();
630
+ }
631
+
632
+ function restartDebugging() {
633
+ window.location.reload();
634
+ }
635
+
636
+ function setupTabNavigation() {
637
+ const worldTabButton = document.getElementById('world-tab-button');
638
+ const assetTabButton = document.getElementById('asset-tab-button');
639
+
640
+ function getTabElements() {
641
+ return {
642
+ worldTab: document.getElementById('world-tab-container'),
643
+ worldContent: document.getElementById('world-tab'),
644
+ assetTab: document.getElementById('asset-tab-container'),
645
+ assetContent: document.getElementById('asset-tab')
646
+ };
647
+ }
648
+
649
+ function hideAllTabs() {
650
+ const tabs = getTabElements();
651
+ Object.values(tabs).forEach(tab => {
652
+ if (tab) tab.classList.remove('active');
653
+ });
654
+ }
655
+
656
+ if (worldTabButton) {
657
+ worldTabButton.addEventListener('click', () => {
658
+ worldTabButton.classList.add('active');
659
+ assetTabButton.classList.remove('active');
660
+
661
+ hideAllTabs();
662
+
663
+ const tabs = getTabElements();
664
+ if (tabs.worldTab) tabs.worldTab.classList.add('active');
665
+ if (tabs.worldContent) tabs.worldContent.classList.add('active');
666
+ });
667
+ }
668
+
669
+ if (assetTabButton) {
670
+ assetTabButton.addEventListener('click', () => {
671
+ worldTabButton.classList.remove('active');
672
+ assetTabButton.classList.add('active');
673
+
674
+ hideAllTabs();
675
+
676
+ const tabs = getTabElements();
677
+ if (tabs.assetTab) tabs.assetTab.classList.add('active');
678
+ if (tabs.assetContent) tabs.assetContent.classList.add('active');
679
+ });
680
+ }
681
+
682
+ activateWorldTab();
683
+ }
684
+
685
+ function activateWorldTab() {
686
+ function getTabElements() {
687
+ return {
688
+ worldTab: document.getElementById('world-tab-container'),
689
+ worldContent: document.getElementById('world-tab'),
690
+ assetTab: document.getElementById('asset-tab-container'),
691
+ assetContent: document.getElementById('asset-tab')
692
+ };
693
+ }
694
+
695
+ function hideAllTabs() {
696
+ const tabs = getTabElements();
697
+ Object.values(tabs).forEach(tab => {
698
+ if (tab) tab.classList.remove('active');
699
+ });
700
+ }
701
+
702
+ hideAllTabs();
703
+
704
+ const tabs = getTabElements();
705
+ if (tabs.worldTab) tabs.worldTab.classList.add('active');
706
+ if (tabs.worldContent) tabs.worldContent.classList.add('active');
707
+
708
+ const worldTabButton = document.getElementById('world-tab-button');
709
+ const assetTabButton = document.getElementById('asset-tab-button');
710
+
711
+ if (worldTabButton) worldTabButton.classList.add('active');
712
+ if (assetTabButton) assetTabButton.classList.remove('active');
713
+ }
714
+
715
+ function setupTogglePanelButton() {
716
+ const DEBUG_TOGGLE_PANEL = false;
717
+
718
+ const toggleButton = document.getElementById('toggle-panel');
719
+ const tabContainer = document.getElementById('tab-container');
720
+
721
+ if (!toggleButton || !tabContainer) {
722
+ return;
723
+ }
724
+
725
+ const settings = loadSettings() || {};
726
+ let isPanelHidden = settings.tabPanelHidden || false;
727
+
728
+ if (isPanelHidden) {
729
+ tabContainer.style.cssText = 'display: none !important; visibility: hidden !important; opacity: 0 !important;';
730
+ toggleButton.classList.add('active');
731
+ toggleButton.setAttribute('title', 'Show Side Panel');
732
+ } else {
733
+ tabContainer.style.cssText = 'display: flex !important; visibility: visible !important; opacity: 1 !important;';
734
+ toggleButton.classList.remove('active');
735
+ toggleButton.setAttribute('title', 'Hide Side Panel');
736
+ }
737
+
738
+ toggleButton.addEventListener('click', function() {
739
+ isPanelHidden = !isPanelHidden;
740
+
741
+ if (isPanelHidden) {
742
+ tabContainer.style.cssText = 'display: none !important; visibility: hidden !important; opacity: 0 !important;';
743
+ toggleButton.classList.add('active');
744
+ toggleButton.setAttribute('title', 'Show Side Panel');
745
+ } else {
746
+ tabContainer.style.cssText = 'display: flex !important; visibility: visible !important; opacity: 1 !important;';
747
+ toggleButton.classList.remove('active');
748
+ toggleButton.setAttribute('title', 'Hide Side Panel');
749
+ }
750
+
751
+ settings.tabPanelHidden = isPanelHidden;
752
+ saveSettings(settings);
753
+ });
754
+ }
755
+
756
+ function ensureCollapsibleHeadersWork() {
757
+ const headers = document.querySelectorAll('.collapsible-header');
758
+
759
+ headers.forEach(header => {
760
+ const newHeader = header.cloneNode(true);
761
+ header.parentNode.replaceChild(newHeader, header);
762
+
763
+ newHeader.addEventListener('click', function(event) {
764
+ event.preventDefault();
765
+ event.stopPropagation();
766
+
767
+ const content = this.nextElementSibling;
768
+ if (!content || !content.classList.contains('metadata-content')) {
769
+ return;
770
+ }
771
+
772
+ const currentDisplay = window.getComputedStyle(content).display;
773
+
774
+ if (currentDisplay === 'none') {
775
+ content.style.display = 'block';
776
+ const indicator = this.querySelector('.collapse-indicator');
777
+ if (indicator) {
778
+ indicator.textContent = '[-]';
779
+ }
780
+ } else {
781
+ content.style.display = 'none';
782
+ const indicator = this.querySelector('.collapse-indicator');
783
+ if (indicator) {
784
+ indicator.textContent = '[+]';
785
+ }
786
+ }
787
+
788
+ return false;
789
+ }, true);
790
+ });
791
+ }