@littlecarlito/blorktools 0.50.4 → 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,548 @@
1
+ /**
2
+ * Mesh Info Modal
3
+ *
4
+ * This module handles the functionality of the mesh info modal.
5
+ * It displays detailed information about a selected mesh.
6
+ */
7
+
8
+ import * as THREE from 'three';
9
+ import { getState } from '../../util/state/scene-state.js';
10
+ import { getHtmlSettingsForMesh } from '../../util/data/mesh-html-manager.js';
11
+ import { CSS3DDebugController } from '../../util/scene/css3d-debug-controller.js';
12
+
13
+ let listenersInitialized = false;
14
+ let css3dDebugController = null;
15
+
16
+ export async function openMeshInfoModal(meshName, meshId) {
17
+ console.log(`openMeshInfoModal called for mesh: ${meshName} (ID: ${meshId})`);
18
+
19
+ const container = document.getElementById('mesh-info-modal-container');
20
+ const modal = document.getElementById('mesh-info-modal');
21
+
22
+ console.log('DOM state check:', {
23
+ containerExists: !!container,
24
+ containerHasContent: container ? container.innerHTML.length > 0 : false,
25
+ modalExists: !!modal,
26
+ modalParent: modal ? modal.parentNode?.id : 'no parent'
27
+ });
28
+
29
+ try {
30
+ if (!modal) {
31
+ console.error('Mesh Info Modal element not found in the DOM');
32
+ console.error('Available modal-related elements:',
33
+ Array.from(document.querySelectorAll('[id*="modal"]')).map(el => el.id));
34
+ alert('Error: Could not find Mesh Info Modal. Please try again.');
35
+ return;
36
+ }
37
+
38
+ const meshNameEl = document.getElementById('mesh-info-mesh-name');
39
+ const contentEl = document.getElementById('mesh-info-content');
40
+
41
+ console.log('Found all required modal elements:', {
42
+ modal: !!modal,
43
+ meshNameEl: !!meshNameEl,
44
+ contentEl: !!contentEl
45
+ });
46
+
47
+ if (meshNameEl) meshNameEl.textContent = meshName;
48
+
49
+ modal.dataset.meshId = meshId;
50
+
51
+ const infoContent = generateMeshInfoContent(meshId);
52
+ if (contentEl) contentEl.innerHTML = infoContent;
53
+
54
+ updateDebugButtonStates(meshId);
55
+
56
+ modal.classList.add('visible');
57
+ console.log('Mesh Info Modal opened successfully');
58
+
59
+ try {
60
+ const htmlSettings = await getHtmlSettingsForMesh(meshId);
61
+ const placeholder = document.getElementById(`html-settings-placeholder-${meshId}`);
62
+ if (placeholder) {
63
+ let htmlSettingsContent = '';
64
+ if (htmlSettings && Object.keys(htmlSettings).length > 0) {
65
+ htmlSettingsContent = `
66
+ <div class="info-row"><span class="info-label">Render Mode:</span> <span class="info-value">${htmlSettings.previewMode || 'threejs'}</span></div>
67
+ <div class="info-row"><span class="info-label">Playback Speed:</span> <span class="info-value">${htmlSettings.playbackSpeed || '1.0'}</span></div>
68
+ <div class="info-row"><span class="info-label">Animation:</span> <span class="info-value">${htmlSettings.animation?.type || 'none'}</span></div>
69
+ <div class="info-row"><span class="info-label">Show Borders:</span> <span class="info-value">${htmlSettings.display?.showBorders !== false ? 'Yes' : 'No'}</span></div>
70
+ <div class="info-row"><span class="info-label">Display on Mesh:</span> <span class="info-value">${htmlSettings.display?.displayOnMesh === true ? 'Yes' : 'No'}</span></div>
71
+ <div class="info-row"><span class="info-label">Rig Control Node:</span> <span class="info-value">${htmlSettings.display?.rigControlNode === true ? 'Yes' : 'No'}</span></div>
72
+ `;
73
+ } else {
74
+ htmlSettingsContent = '<div class="info-row">No HTML settings configured</div>';
75
+ }
76
+ placeholder.innerHTML = htmlSettingsContent;
77
+ }
78
+ } catch (error) {
79
+ console.error('Error loading HTML settings:', error);
80
+ const placeholder = document.getElementById(`html-settings-placeholder-${meshId}`);
81
+ if (placeholder) {
82
+ placeholder.innerHTML = '<div class="info-row">Error loading HTML settings</div>';
83
+ }
84
+ }
85
+
86
+ } catch (error) {
87
+ console.error('Error opening Mesh Info Modal:', error);
88
+ alert('Failed to open Mesh Info Modal. See console for details.');
89
+ }
90
+ }
91
+
92
+ function updateDebugButtonStates(meshId) {
93
+ updateDebugTextureButtonState(meshId);
94
+ updateCSS3DDebugButtonState(meshId);
95
+ }
96
+
97
+ function updateDebugTextureButtonState(meshId) {
98
+ const debugBtn = document.getElementById('mesh-info-debug-texture');
99
+ if (!debugBtn) return;
100
+
101
+ const state = getState();
102
+ const mesh = state.meshes ? state.meshes[meshId] : null;
103
+
104
+ if (!mesh) {
105
+ debugBtn.textContent = 'Enable Debug Texture';
106
+ debugBtn.disabled = true;
107
+ return;
108
+ }
109
+
110
+ debugBtn.disabled = false;
111
+
112
+ const hasDebugTexture = mesh.userData && mesh.userData.hasDebugTexture;
113
+
114
+ if (hasDebugTexture) {
115
+ debugBtn.textContent = 'Disable Debug Texture';
116
+ debugBtn.classList.add('debug-active');
117
+ } else {
118
+ debugBtn.textContent = 'Enable Debug Texture';
119
+ debugBtn.classList.remove('debug-active');
120
+ }
121
+ }
122
+
123
+ function updateCSS3DDebugButtonState(meshId) {
124
+ const css3dBtn = document.getElementById('mesh-info-css3d-debug');
125
+ if (!css3dBtn) return;
126
+
127
+ const state = getState();
128
+ const mesh = state.meshes ? state.meshes[meshId] : null;
129
+
130
+ if (!mesh) {
131
+ css3dBtn.textContent = 'Enable CSS3D Debug';
132
+ css3dBtn.disabled = true;
133
+ return;
134
+ }
135
+
136
+ const isDisplayMesh = mesh.name && mesh.name.toLowerCase().includes('display');
137
+
138
+ if (!isDisplayMesh) {
139
+ css3dBtn.textContent = 'Enable CSS3D Debug';
140
+ css3dBtn.disabled = true;
141
+ css3dBtn.title = 'CSS3D Debug only available for display meshes';
142
+ return;
143
+ }
144
+
145
+ css3dBtn.disabled = false;
146
+ css3dBtn.title = 'Toggle CSS3D Debug Frame';
147
+
148
+ const hasCSS3DDebug = css3dDebugController && css3dDebugController.isActive();
149
+
150
+ if (hasCSS3DDebug) {
151
+ css3dBtn.textContent = 'Disable CSS3D Debug';
152
+ css3dBtn.classList.add('debug-active');
153
+ } else {
154
+ css3dBtn.textContent = 'Enable CSS3D Debug';
155
+ css3dBtn.classList.remove('debug-active');
156
+ }
157
+ }
158
+
159
+ function handleDebugTextureToggle() {
160
+ const modal = document.getElementById('mesh-info-modal');
161
+ const meshId = parseInt(modal.dataset.meshId);
162
+
163
+ if (isNaN(meshId)) {
164
+ console.error('Invalid mesh ID');
165
+ return;
166
+ }
167
+
168
+ const state = getState();
169
+ const mesh = state.meshes ? state.meshes[meshId] : null;
170
+
171
+ if (!mesh) {
172
+ console.error(`Mesh not found at index ${meshId}`);
173
+ return;
174
+ }
175
+
176
+ const hasDebugTexture = mesh.userData && mesh.userData.hasDebugTexture;
177
+
178
+ if (hasDebugTexture) {
179
+ disableDebugTexture(meshId);
180
+ } else {
181
+ enableDebugTexture(meshId);
182
+ }
183
+
184
+ updateDebugTextureButtonState(meshId);
185
+ }
186
+
187
+ function handleCSS3DDebugToggle() {
188
+ const modal = document.getElementById('mesh-info-modal');
189
+ const meshId = parseInt(modal.dataset.meshId);
190
+
191
+ if (isNaN(meshId)) {
192
+ console.error('Invalid mesh ID');
193
+ return;
194
+ }
195
+
196
+ const state = getState();
197
+ const mesh = state.meshes ? state.meshes[meshId] : null;
198
+
199
+ if (!mesh) {
200
+ console.error(`Mesh not found at index ${meshId}`);
201
+ return;
202
+ }
203
+
204
+ const isDisplayMesh = mesh.name && mesh.name.toLowerCase().includes('display');
205
+
206
+ if (!isDisplayMesh) {
207
+ console.error('CSS3D Debug is only available for display meshes');
208
+ return;
209
+ }
210
+
211
+ const isActive = css3dDebugController && css3dDebugController.isActive();
212
+
213
+ if (isActive) {
214
+ disableCSS3DDebug();
215
+ } else {
216
+ enableCSS3DDebug();
217
+ }
218
+
219
+ updateCSS3DDebugButtonState(meshId);
220
+ }
221
+
222
+ function enableCSS3DDebug() {
223
+ try {
224
+ if (!css3dDebugController) {
225
+ css3dDebugController = new CSS3DDebugController();
226
+ }
227
+
228
+ if (css3dDebugController.isActive()) {
229
+ console.log('CSS3D Debug already active');
230
+ return;
231
+ }
232
+
233
+ const mainContainer = document.getElementById('main-container') || document.body;
234
+ css3dDebugController.init(mainContainer);
235
+
236
+ console.log('CSS3D Debug enabled');
237
+ } catch (error) {
238
+ console.error('Error enabling CSS3D Debug:', error);
239
+ }
240
+ }
241
+
242
+ function disableCSS3DDebug() {
243
+ try {
244
+ if (css3dDebugController && css3dDebugController.isActive()) {
245
+ css3dDebugController.cleanup();
246
+ console.log('CSS3D Debug disabled');
247
+ }
248
+ } catch (error) {
249
+ console.error('Error disabling CSS3D Debug:', error);
250
+ }
251
+ }
252
+
253
+ function enableDebugTexture(meshId) {
254
+ const state = getState();
255
+ const mesh = state.meshes ? state.meshes[meshId] : null;
256
+
257
+ if (!mesh || !mesh.material) {
258
+ console.error('Cannot enable debug texture: mesh or material not found');
259
+ return;
260
+ }
261
+
262
+ if (!mesh.userData.originalMaterial) {
263
+ if (Array.isArray(mesh.material)) {
264
+ mesh.userData.originalMaterial = mesh.material.map(mat => mat.clone());
265
+ } else {
266
+ mesh.userData.originalMaterial = mesh.material.clone();
267
+ }
268
+ }
269
+
270
+ const canvas = document.createElement('canvas');
271
+ canvas.width = 512;
272
+ canvas.height = 512;
273
+
274
+ const ctx = canvas.getContext('2d');
275
+ ctx.fillStyle = '#ff0000';
276
+ ctx.fillRect(0, 0, 512, 512);
277
+
278
+ ctx.fillStyle = '#ffff00';
279
+ for (let i = 0; i < 512; i += 64) {
280
+ ctx.fillRect(i, 0, 32, 512);
281
+ }
282
+
283
+ const debugTexture = new THREE.CanvasTexture(canvas);
284
+ debugTexture.encoding = THREE.sRGBEncoding;
285
+ debugTexture.wrapS = THREE.RepeatWrapping;
286
+ debugTexture.wrapT = THREE.RepeatWrapping;
287
+ debugTexture.needsUpdate = true;
288
+
289
+ if (Array.isArray(mesh.material)) {
290
+ mesh.material.forEach(material => {
291
+ material.map = debugTexture;
292
+ material.color = new THREE.Color(0xffffff);
293
+ material.needsUpdate = true;
294
+ });
295
+ } else {
296
+ mesh.material.map = debugTexture;
297
+ mesh.material.color = new THREE.Color(0xffffff);
298
+ mesh.material.needsUpdate = true;
299
+ }
300
+
301
+ mesh.userData.hasDebugTexture = true;
302
+
303
+ console.log(`Debug texture enabled for mesh ${meshId}`);
304
+ }
305
+
306
+ function disableDebugTexture(meshId) {
307
+ const state = getState();
308
+ const mesh = state.meshes ? state.meshes[meshId] : null;
309
+
310
+ if (!mesh) {
311
+ console.error('Cannot disable debug texture: mesh not found');
312
+ return;
313
+ }
314
+
315
+ if (mesh.userData.originalMaterial) {
316
+ if (Array.isArray(mesh.userData.originalMaterial)) {
317
+ mesh.material = mesh.userData.originalMaterial.map(mat => mat.clone());
318
+ } else {
319
+ mesh.material = mesh.userData.originalMaterial.clone();
320
+ }
321
+ } else {
322
+ if (Array.isArray(mesh.material)) {
323
+ mesh.material.forEach(material => {
324
+ material.map = null;
325
+ material.color = new THREE.Color(0xcccccc);
326
+ material.needsUpdate = true;
327
+ });
328
+ } else {
329
+ mesh.material.map = null;
330
+ mesh.material.color = new THREE.Color(0xcccccc);
331
+ mesh.material.needsUpdate = true;
332
+ }
333
+ }
334
+
335
+ mesh.userData.hasDebugTexture = false;
336
+
337
+ console.log(`Debug texture disabled for mesh ${meshId}`);
338
+ }
339
+
340
+ function generateMeshInfoContent(meshId) {
341
+ const state = getState();
342
+ const mesh = state.meshes ? state.meshes[meshId] : null;
343
+
344
+ if (!mesh) {
345
+ return '<div class="info-section">Mesh not found</div>';
346
+ }
347
+
348
+ const sections = [];
349
+
350
+ sections.push(`
351
+ <div class="info-section">
352
+ <strong>Basic Information</strong>
353
+ <div class="info-row"><span class="info-label">Name:</span> <span class="info-value">${mesh.name || 'Unnamed'}</span></div>
354
+ <div class="info-row"><span class="info-label">ID:</span> <span class="info-value">${meshId}</span></div>
355
+ <div class="info-row"><span class="info-label">Visible:</span> <span class="info-value">${mesh.visible ? 'Yes' : 'No'}</span></div>
356
+ </div>
357
+ `);
358
+
359
+ let dimensionsContent = '';
360
+ if (mesh.geometry) {
361
+ if (!mesh.geometry.boundingBox) {
362
+ mesh.geometry.computeBoundingBox();
363
+ }
364
+
365
+ if (mesh.geometry.boundingBox) {
366
+ const box = mesh.geometry.boundingBox;
367
+ const width = box.max.x - box.min.x;
368
+ const height = box.max.y - box.min.y;
369
+ const depth = box.max.z - box.min.z;
370
+
371
+ dimensionsContent = `
372
+ <div class="info-row"><span class="info-label">Width (X):</span> <span class="info-value transform-value">${width.toFixed(3)}</span></div>
373
+ <div class="info-row"><span class="info-label">Height (Y):</span> <span class="info-value transform-value">${height.toFixed(3)}</span></div>
374
+ <div class="info-row"><span class="info-label">Depth (Z):</span> <span class="info-value transform-value">${depth.toFixed(3)}</span></div>
375
+ `;
376
+ } else {
377
+ dimensionsContent = '<div class="info-row">Unable to calculate dimensions</div>';
378
+ }
379
+ } else {
380
+ dimensionsContent = '<div class="info-row">No geometry data available</div>';
381
+ }
382
+
383
+ sections.push(`
384
+ <div class="info-section">
385
+ <strong>Dimensions</strong>
386
+ ${dimensionsContent}
387
+ </div>
388
+ `);
389
+
390
+ let geometryContent = '';
391
+ if (mesh.geometry) {
392
+ const vertexCount = mesh.geometry.attributes && mesh.geometry.attributes.position ?
393
+ mesh.geometry.attributes.position.count : 'Unknown';
394
+
395
+ let faceCount = 'Unknown';
396
+ if (mesh.geometry.index) {
397
+ faceCount = Math.floor(mesh.geometry.index.count / 3);
398
+ } else if (mesh.geometry.attributes && mesh.geometry.attributes.position) {
399
+ faceCount = Math.floor(mesh.geometry.attributes.position.count / 3);
400
+ }
401
+
402
+ geometryContent = `
403
+ <div class="geometry-info">
404
+ <div class="info-row"><span class="info-label">Type:</span> <span class="info-value">${mesh.geometry.type || 'Unknown'}</span></div>
405
+ <div class="info-row"><span class="info-label">Vertices:</span> <span class="info-value">${vertexCount}</span></div>
406
+ <div class="info-row"><span class="info-label">Faces:</span> <span class="info-value">${faceCount}</span></div>
407
+ </div>
408
+ `;
409
+ } else {
410
+ geometryContent = '<div class="info-row">No geometry data available</div>';
411
+ }
412
+
413
+ sections.push(`
414
+ <div class="info-section">
415
+ <strong>Geometry</strong>
416
+ ${geometryContent}
417
+ </div>
418
+ `);
419
+
420
+ let materialContent = '';
421
+ if (mesh.material) {
422
+ const materials = Array.isArray(mesh.material) ? mesh.material : [mesh.material];
423
+
424
+ materialContent = `<div class="material-info">`;
425
+ materialContent += `<div class="info-row"><span class="info-label">Count:</span> <span class="info-value">${materials.length}</span></div>`;
426
+
427
+ materials.forEach((material, index) => {
428
+ if (materials.length > 1) {
429
+ materialContent += `<div class="info-row" style="margin-top: 10px;"><strong>Material ${index + 1}:</strong></div>`;
430
+ }
431
+
432
+ materialContent += `<div class="info-row"><span class="info-label">Type:</span> <span class="info-value">${material.type || 'Unknown'}</span></div>`;
433
+ materialContent += `<div class="info-row"><span class="info-label">Double Sided:</span> <span class="info-value">${material.side === THREE.DoubleSide ? 'Yes' : 'No'}</span></div>`;
434
+ materialContent += `<div class="info-row"><span class="info-label">Transparent:</span> <span class="info-value">${material.transparent ? 'Yes' : 'No'}</span></div>`;
435
+
436
+ if (material.color) {
437
+ const colorHex = '#' + material.color.getHexString();
438
+ materialContent += `<div class="info-row"><span class="info-label">Color:</span> <span class="color-swatch" style="background-color:${colorHex}"></span><span class="info-value">${colorHex}</span></div>`;
439
+ }
440
+ });
441
+
442
+ materialContent += `</div>`;
443
+ } else {
444
+ materialContent = '<div class="info-row">No material data available</div>';
445
+ }
446
+
447
+ sections.push(`
448
+ <div class="info-section">
449
+ <strong>Material</strong>
450
+ ${materialContent}
451
+ </div>
452
+ `);
453
+
454
+ const transformContent = `
455
+ <div class="info-row">
456
+ <span class="info-label">Position:</span>
457
+ X:<span class="transform-value">${mesh.position.x.toFixed(3)}</span>
458
+ Y:<span class="transform-value">${mesh.position.y.toFixed(3)}</span>
459
+ Z:<span class="transform-value">${mesh.position.z.toFixed(3)}</span>
460
+ </div>
461
+ <div class="info-row">
462
+ <span class="info-label">Rotation:</span>
463
+ X:<span class="transform-value">${(mesh.rotation.x * 180 / Math.PI).toFixed(1)}°</span>
464
+ Y:<span class="transform-value">${(mesh.rotation.y * 180 / Math.PI).toFixed(1)}°</span>
465
+ Z:<span class="transform-value">${(mesh.rotation.z * 180 / Math.PI).toFixed(1)}°</span>
466
+ </div>
467
+ <div class="info-row">
468
+ <span class="info-label">Scale:</span>
469
+ X:<span class="transform-value">${mesh.scale.x.toFixed(3)}</span>
470
+ Y:<span class="transform-value">${mesh.scale.y.toFixed(3)}</span>
471
+ Z:<span class="transform-value">${mesh.scale.z.toFixed(3)}</span>
472
+ </div>
473
+ `;
474
+
475
+ sections.push(`
476
+ <div class="info-section">
477
+ <strong>Transform</strong>
478
+ ${transformContent}
479
+ </div>
480
+ `);
481
+
482
+ sections.push(`
483
+ <div class="info-section">
484
+ <strong>HTML Settings</strong>
485
+ <div id="html-settings-placeholder-${meshId}" class="html-settings-info">
486
+ <div class="info-row">Loading...</div>
487
+ </div>
488
+ </div>
489
+ `);
490
+
491
+
492
+ return sections.join('');
493
+ }
494
+
495
+ export function initMeshInfoModal() {
496
+ console.log('Initializing Mesh Info Modal');
497
+
498
+ const modal = document.getElementById('mesh-info-modal');
499
+ const closeBtn = document.getElementById('mesh-info-close');
500
+ const okBtn = document.getElementById('mesh-info-ok');
501
+ const debugBtn = document.getElementById('mesh-info-debug-texture');
502
+ const css3dBtn = document.getElementById('mesh-info-css3d-debug');
503
+
504
+ window.openMeshInfoModal = openMeshInfoModal;
505
+ console.log('Registered global function: window.openMeshInfoModal =',
506
+ typeof window.openMeshInfoModal === 'function' ? 'Function successfully registered' : 'Failed to register function');
507
+
508
+ if (!modal) {
509
+ console.error('Mesh Info Modal not found in the DOM');
510
+ return;
511
+ }
512
+
513
+ if (listenersInitialized) {
514
+ console.log('Mesh Info Modal event listeners already initialized, skipping');
515
+ return;
516
+ }
517
+
518
+ closeBtn.addEventListener('click', closeModal);
519
+ okBtn.addEventListener('click', closeModal);
520
+
521
+ if (debugBtn) {
522
+ debugBtn.addEventListener('click', handleDebugTextureToggle);
523
+ }
524
+
525
+ if (css3dBtn) {
526
+ css3dBtn.addEventListener('click', handleCSS3DDebugToggle);
527
+ }
528
+
529
+ modal.addEventListener('click', function(e) {
530
+ if (e.target === modal) {
531
+ closeModal();
532
+ }
533
+ });
534
+
535
+ listenersInitialized = true;
536
+ console.log('Mesh Info Modal event listeners initialized successfully');
537
+ }
538
+
539
+ function closeModal() {
540
+ const modal = document.getElementById('mesh-info-modal');
541
+ modal.classList.remove('visible');
542
+ console.log('Mesh Info Modal closed');
543
+ }
544
+
545
+ export function resetInitialization() {
546
+ listenersInitialized = false;
547
+ console.log('Mesh Info Modal initialization flag reset');
548
+ }
@@ -0,0 +1,103 @@
1
+ .settings-tabs {
2
+ display: flex;
3
+ border-bottom: 1px solid var(--panel-border);
4
+ margin-bottom: 15px;
5
+ }
6
+
7
+ .settings-tab-button {
8
+ background: transparent;
9
+ border: none;
10
+ color: var(--text-color);
11
+ padding: 10px 15px;
12
+ cursor: pointer;
13
+ font-size: 14px;
14
+ border-bottom: 2px solid transparent;
15
+ outline: none;
16
+ transition: all 0.2s ease;
17
+ font-family: monospace;
18
+ }
19
+
20
+ .settings-tab-button.active {
21
+ color: var(--button-color);
22
+ border-bottom: 2px solid var(--button-color);
23
+ background-color: rgba(30, 136, 229, 0.1);
24
+ }
25
+
26
+ .settings-row {
27
+ display: flex;
28
+ flex-wrap: wrap;
29
+ margin-bottom: 15px;
30
+ justify-content: space-between;
31
+ align-items: center;
32
+ }
33
+
34
+ .settings-checkbox {
35
+ margin-left: 10px;
36
+ width: 18px;
37
+ height: 18px;
38
+ cursor: pointer;
39
+ accent-color: var(--button-color);
40
+ flex: 0 0 18px;
41
+ }
42
+
43
+ .settings-color-picker {
44
+ margin-left: 10px;
45
+ width: 40px;
46
+ height: 25px;
47
+ padding: 0;
48
+ border: 1px solid var(--panel-border);
49
+ cursor: pointer;
50
+ background-color: transparent;
51
+ flex: 0 0 40px;
52
+ }
53
+
54
+ .reset-button {
55
+ background-color: var(--button-color);
56
+ color: white;
57
+ border: none;
58
+ padding: 6px 12px;
59
+ cursor: pointer;
60
+ font-weight: bold;
61
+ transition: background-color 0.3s;
62
+ font-family: monospace;
63
+ }
64
+
65
+ .reset-button:hover {
66
+ background-color: #0d74c7;
67
+ }
68
+
69
+ .text-center {
70
+ text-align: center;
71
+ justify-content: center;
72
+ }
73
+
74
+ .text-center button {
75
+ width: 50%;
76
+ }
77
+
78
+ .settings-subheading {
79
+ font-size: 14px;
80
+ margin: 0 0 10px 0;
81
+ padding-bottom: 5px;
82
+ border-bottom: 1px solid var(--panel-border);
83
+ width: 100%;
84
+ color: var(--primary-color);
85
+ }
86
+
87
+ /* Shared settings Tab Styles */
88
+ .settings-tab-content {
89
+ display: none;
90
+ }
91
+
92
+ .settings-tab-content.active {
93
+ display: block;
94
+ }
95
+
96
+ .settings-option.full-width {
97
+ flex: 0 0 100%;
98
+ justify-content: flex-start;
99
+ }
100
+
101
+ .settings-option.full-width label {
102
+ width: 120px;
103
+ }