@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,538 @@
1
+ /**
2
+ * Asset Debugger - Rig Panel
3
+ *
4
+ * This module provides rig visualization and control functionality for the Asset Debugger.
5
+ * It implements the same bone/rig/control parsing as the Rig Debugger.
6
+ */
7
+ import * as THREE from 'three';
8
+ import {
9
+ rigDetails,
10
+ updateRigDetails,
11
+ rigOptions,
12
+ updateRigVisualization,
13
+ resetRig
14
+ } from '../../../util/rig/rig-controller.js';
15
+ import { createRig } from '../../../util/rig/rig-factory.js';
16
+ import { setIsDragging, getIsDragging, checkHandleHover } from '../../../util/rig/rig-mouse-handler.js';
17
+ import { bones, findAssociatedBone } from '../../../util/rig/bone-kinematics.js';
18
+ import { saveSettings, loadSettings } from '../../../util/data/localstorage-manager.js';
19
+ import { getState } from '../../../util/state/scene-state.js';
20
+ import { hideTooltip, setupTruncationTooltips } from '../../../util/rig/rig-tooltip-manager.js';
21
+ import { addBoneConstraintControls, disableApplyButton } from '../../../util/rig/rig-ui-factory.js';
22
+ import { handleApplyConstraints } from '../../../util/rig/rig-constraint-manager.js';
23
+ import { analyzeGltfModel } from '../../../util/data/glb-classifier.js';
24
+ import { primaryRigHandle } from '../../../util/rig/rig-handle-factory.js';
25
+
26
+
27
+
28
+ // Add global state tracking for joint settings
29
+ export let jointPreviousValues = new Map(); // Map of joint name to previous value
30
+
31
+ /**
32
+ * Create a section with items for rig details
33
+ * @param {string} title - Section title
34
+ * @param {Array} items - Array of items to display
35
+ * @param {Object} details - Rig details object for constraints
36
+ * @returns {HTMLElement} Section element
37
+ */
38
+ function createSection(title, items, details) {
39
+ const section = document.createElement('div');
40
+ section.className = 'rig-section';
41
+
42
+ const sectionTitle = document.createElement('h4');
43
+ sectionTitle.textContent = title;
44
+ sectionTitle.className = 'rig-section-title';
45
+ section.appendChild(sectionTitle);
46
+
47
+ if (!items || items.length === 0) {
48
+ const noItems = document.createElement('p');
49
+ noItems.textContent = 'None found';
50
+ noItems.className = 'rig-no-items';
51
+ section.appendChild(noItems);
52
+ } else {
53
+ items.forEach(item => {
54
+ const itemElem = document.createElement('div');
55
+ itemElem.className = 'rig-item';
56
+
57
+ const nameElem = document.createElement('div');
58
+ nameElem.textContent = `Name: ${item.name}`;
59
+ nameElem.dataset.rawName = item.name;
60
+ nameElem.className = 'rig-item-name';
61
+ itemElem.appendChild(nameElem);
62
+
63
+ if (item.count > 1) {
64
+ const countElem = document.createElement('div');
65
+ countElem.textContent = `x${item.count}`;
66
+ countElem.className = 'rig-item-count';
67
+ itemElem.appendChild(countElem);
68
+ }
69
+
70
+ if (item.position) {
71
+ const posElem = document.createElement('div');
72
+ posElem.className = 'rig-item-position';
73
+ posElem.textContent = `Pos: [${item.position.map(p =>
74
+ typeof p === 'number' ? p.toFixed(2) : 'undefined').join(', ')}]`;
75
+ itemElem.appendChild(posElem);
76
+ }
77
+
78
+ if (item.type) {
79
+ const typeElem = document.createElement('div');
80
+ typeElem.className = 'rig-item-type';
81
+ typeElem.textContent = `Type: ${item.type}`;
82
+ itemElem.appendChild(typeElem);
83
+ }
84
+
85
+ if (item.constraintType) {
86
+ const constraintElem = document.createElement('div');
87
+ constraintElem.className = 'rig-constraint-type';
88
+ constraintElem.textContent = `Constraint: ${item.constraintType}`;
89
+ itemElem.appendChild(constraintElem);
90
+ }
91
+
92
+ if (title === 'Bones') {
93
+ addBoneConstraintControls(itemElem, item, details);
94
+ }
95
+
96
+ if (title === 'Joints') {
97
+ addJointRelationships(itemElem, item);
98
+ }
99
+
100
+ if (title === 'Controls/Handles') {
101
+ addControlBoneAssociations(itemElem, item, details);
102
+ }
103
+
104
+ section.appendChild(itemElem);
105
+ });
106
+
107
+ if (title === 'Joints' && details.constraints && details.constraints.length > 0) {
108
+ addConstraintsSummary(section, details);
109
+ }
110
+
111
+ if (title === 'Bones' && items.length > 0) {
112
+ addApplyConstraintsButton(section);
113
+ }
114
+ }
115
+
116
+ return section;
117
+ }
118
+
119
+
120
+
121
+ /**
122
+ * Add joint relationship information to a joint item element
123
+ * @param {HTMLElement} itemElem - The joint item element
124
+ * @param {Object} item - The joint item data
125
+ */
126
+ function addJointRelationships(itemElem, item) {
127
+ if (item.isRoot) {
128
+ const rootElem = document.createElement('div');
129
+ rootElem.className = 'rig-root-joint';
130
+ rootElem.textContent = 'Root Joint';
131
+ itemElem.appendChild(rootElem);
132
+ }
133
+
134
+ if (item.parentBone) {
135
+ const parentElem = document.createElement('div');
136
+ parentElem.textContent = `Parent: ${item.parentBone}`;
137
+ parentElem.dataset.rawName = item.parentBone;
138
+ parentElem.className = 'rig-parent-bone';
139
+ itemElem.appendChild(parentElem);
140
+ }
141
+
142
+ if (item.childBone) {
143
+ const childElem = document.createElement('div');
144
+ childElem.textContent = `Child: ${item.childBone}`;
145
+ childElem.dataset.rawName = item.childBone;
146
+ childElem.className = 'rig-child-bone';
147
+ itemElem.appendChild(childElem);
148
+ }
149
+ }
150
+
151
+ /**
152
+ * Add bone associations for control points
153
+ * @param {HTMLElement} itemElem - The control item element
154
+ * @param {Object} item - The control item data
155
+ * @param {Object} details - Rig details object
156
+ */
157
+ function addControlBoneAssociations(itemElem, item, details) {
158
+ const associatedBone = findAssociatedBone(item.name, details.bones);
159
+ if (associatedBone) {
160
+ const boneElem = document.createElement('div');
161
+ boneElem.textContent = `Controls bone: ${associatedBone.name}`;
162
+ boneElem.dataset.rawName = associatedBone.name;
163
+ boneElem.className = 'rig-associated-bone';
164
+ itemElem.appendChild(boneElem);
165
+ }
166
+
167
+ const state = getState();
168
+ if (state.model && primaryRigHandle && primaryRigHandle.userData.controlledBone) {
169
+ const controlElem = document.createElement('div');
170
+ controlElem.textContent = `Connected: ${primaryRigHandle.userData.controlledBone.name}`;
171
+ controlElem.dataset.rawName = primaryRigHandle.userData.controlledBone.name;
172
+ controlElem.className = 'rig-connected-bone';
173
+ itemElem.appendChild(controlElem);
174
+ }
175
+ }
176
+
177
+ /**
178
+ * Add constraints summary to joints section
179
+ * @param {HTMLElement} section - The section element to add summary to
180
+ * @param {Object} details - Rig details object containing constraints
181
+ */
182
+ function addConstraintsSummary(section, details) {
183
+ const constraintsSummary = document.createElement('div');
184
+ constraintsSummary.className = 'rig-constraints-summary';
185
+
186
+ const summaryTitle = document.createElement('h5');
187
+ summaryTitle.textContent = 'Detected Constraints';
188
+ summaryTitle.className = 'rig-summary-title';
189
+ constraintsSummary.appendChild(summaryTitle);
190
+
191
+ const constraintsByType = {};
192
+ details.constraints.forEach(constraint => {
193
+ if (!constraintsByType[constraint.type]) {
194
+ constraintsByType[constraint.type] = [];
195
+ }
196
+ constraintsByType[constraint.type].push(constraint.boneName || constraint.nodeName);
197
+ });
198
+
199
+ Object.keys(constraintsByType).forEach(type => {
200
+ const typeElem = document.createElement('div');
201
+ typeElem.className = 'rig-constraint-group';
202
+ typeElem.innerHTML = `<strong>${type}</strong>: ${constraintsByType[type].join(', ')}`;
203
+ constraintsSummary.appendChild(typeElem);
204
+ });
205
+
206
+ section.appendChild(constraintsSummary);
207
+ }
208
+
209
+ /**
210
+ * Add Apply Constraints button to bones section
211
+ * @param {HTMLElement} section - The section element to add button to
212
+ */
213
+ function addApplyConstraintsButton(section) {
214
+ const buttonContainer = document.createElement('div');
215
+ buttonContainer.className = 'rig-apply-button-container';
216
+
217
+ const applyButton = document.createElement('button');
218
+ applyButton.id = 'apply-bone-constraints-button';
219
+ applyButton.textContent = 'Apply Constraints';
220
+ applyButton.className = 'rig-apply-button';
221
+
222
+ disableApplyButton(applyButton);
223
+
224
+ applyButton.addEventListener('click', () => {
225
+ handleApplyConstraints(applyButton);
226
+ });
227
+
228
+ buttonContainer.appendChild(applyButton);
229
+ section.appendChild(buttonContainer);
230
+ }
231
+
232
+ /**
233
+ * Create the rig controls section with checkboxes and reset button
234
+ * @returns {HTMLElement} Controls section element
235
+ */
236
+ function createRigControlsSection() {
237
+ const controlsSection = document.createElement('div');
238
+ controlsSection.className = 'rig-controls-section';
239
+
240
+ const checkboxWrapper = document.createElement('div');
241
+ checkboxWrapper.className = 'rig-checkbox-wrapper';
242
+ controlsSection.appendChild(checkboxWrapper);
243
+
244
+ const displayRigContainer = document.createElement('div');
245
+ displayRigContainer.className = 'rig-checkbox-container';
246
+
247
+ const displayRigLabel = document.createElement('label');
248
+ displayRigLabel.textContent = 'Display Rig';
249
+ displayRigLabel.className = 'rig-checkbox-label';
250
+
251
+ const displayRigCheckbox = document.createElement('input');
252
+ displayRigCheckbox.type = 'checkbox';
253
+ displayRigCheckbox.id = 'display-rig-tab';
254
+ displayRigCheckbox.checked = rigOptions.displayRig;
255
+ displayRigCheckbox.className = 'rig-checkbox';
256
+
257
+ displayRigCheckbox.addEventListener('change', (e) => {
258
+ rigOptions.displayRig = e.target.checked;
259
+ updateRigVisualization();
260
+
261
+ const settingsModalCheckbox = document.getElementById('display-rig');
262
+ if (settingsModalCheckbox && settingsModalCheckbox.checked !== e.target.checked) {
263
+ settingsModalCheckbox.checked = e.target.checked;
264
+ }
265
+
266
+ saveRigOptionToLocalStorage('displayRig', e.target.checked);
267
+ });
268
+
269
+ displayRigLabel.setAttribute('for', 'display-rig-tab');
270
+ displayRigContainer.appendChild(displayRigLabel);
271
+ displayRigContainer.appendChild(displayRigCheckbox);
272
+
273
+ const forceZContainer = document.createElement('div');
274
+ forceZContainer.className = 'rig-checkbox-container';
275
+
276
+ const forceZLabel = document.createElement('label');
277
+ forceZLabel.textContent = 'Force Z-index';
278
+ forceZLabel.className = 'rig-checkbox-label';
279
+
280
+ const forceZCheckbox = document.createElement('input');
281
+ forceZCheckbox.type = 'checkbox';
282
+ forceZCheckbox.id = 'force-z-tab';
283
+ forceZCheckbox.checked = rigOptions.forceZ;
284
+ forceZCheckbox.className = 'rig-checkbox';
285
+
286
+ forceZCheckbox.addEventListener('change', (e) => {
287
+ rigOptions.forceZ = e.target.checked;
288
+ updateRigVisualization();
289
+
290
+ const settingsModalCheckbox = document.getElementById('force-z');
291
+ if (settingsModalCheckbox && settingsModalCheckbox.checked !== e.target.checked) {
292
+ settingsModalCheckbox.checked = e.target.checked;
293
+ }
294
+
295
+ saveRigOptionToLocalStorage('forceZ', e.target.checked);
296
+ });
297
+
298
+ forceZLabel.setAttribute('for', 'force-z-tab');
299
+ forceZContainer.appendChild(forceZLabel);
300
+ forceZContainer.appendChild(forceZCheckbox);
301
+
302
+ checkboxWrapper.appendChild(displayRigContainer);
303
+ checkboxWrapper.appendChild(forceZContainer);
304
+
305
+ const resetButton = document.createElement('button');
306
+ resetButton.textContent = 'Reset Physics';
307
+ resetButton.className = 'rig-reset-button';
308
+
309
+ resetButton.addEventListener('click', () => {
310
+ resetRig();
311
+ });
312
+
313
+ controlsSection.appendChild(resetButton);
314
+
315
+ return controlsSection;
316
+ }
317
+
318
+ /**
319
+ * Create the rig details content
320
+ * @param {HTMLElement} container - Container to append rig details to
321
+ * @param {Object} details - Rig details object from analyzeGltfModel
322
+ */
323
+ function createRigDetailsContent(container, details) {
324
+ if (!details) {
325
+ container.innerHTML = '<p>No rig data found.</p>';
326
+ return;
327
+ }
328
+
329
+ container.innerHTML = '';
330
+
331
+ const controlsSection = createRigControlsSection();
332
+ container.appendChild(controlsSection);
333
+
334
+ const detailsSection = document.createElement('div');
335
+ detailsSection.className = 'rig-details-section';
336
+
337
+ const detailsTitle = document.createElement('h3');
338
+ detailsTitle.textContent = 'Rig Details';
339
+ detailsTitle.className = 'rig-details-title';
340
+ detailsSection.appendChild(detailsTitle);
341
+
342
+ const detailsContent = document.createElement('div');
343
+ detailsSection.appendChild(detailsContent);
344
+
345
+ detailsContent.appendChild(createSection('Bones', details.bones, details));
346
+
347
+ const jointsData = details.joints || [];
348
+ detailsContent.appendChild(createSection('Joints', jointsData, details));
349
+
350
+ detailsContent.appendChild(createSection('Rigs', details.rigs, details));
351
+ detailsContent.appendChild(createSection('Roots', details.roots, details));
352
+ detailsContent.appendChild(createSection('Controls/Handles', details.controls, details));
353
+
354
+ container.appendChild(detailsSection);
355
+
356
+ setTimeout(() => {
357
+ setupTruncationTooltips(container);
358
+ }, 50);
359
+ }
360
+
361
+ /**
362
+ * Update the rig panel with the latest model information
363
+ */
364
+ export function updateRigPanel() {
365
+ console.log('updateRigPanel called');
366
+ const state = getState();
367
+ console.log('State in updateRigPanel:', state);
368
+ console.log('model in state:', state.model);
369
+ console.log('Rig options on panel init:', JSON.stringify(rigOptions));
370
+
371
+ const rigContent = document.getElementById('rig-content');
372
+
373
+ if (!rigContent) {
374
+ console.error('No rig-content element found');
375
+ return;
376
+ }
377
+
378
+ // Clear any existing analysis if we're explicitly updating
379
+ if (rigDetails) {
380
+ console.log('Clearing existing rig details for fresh analysis');
381
+ updateRigDetails(null);
382
+ }
383
+
384
+ // If we don't have rig details yet, try to analyze the model
385
+ if (!rigDetails && state.model) {
386
+ console.log('Analyzing model:', state.model);
387
+
388
+ try {
389
+ // Create a proper GLTF-like structure that analyzeGltfModel expects
390
+ const gltfData = { scene: state.model };
391
+ console.log('Created GLTF-like object for analysis:', gltfData);
392
+
393
+ // Analyze the model to extract rig information using the imported function
394
+ const newRigDetails = analyzeGltfModel(gltfData);
395
+ console.log('Rig analysis complete, results:', newRigDetails);
396
+
397
+ // Update the rig details using the exported function
398
+ updateRigDetails(newRigDetails);
399
+
400
+ // Create the rig visualization if we have bones
401
+ if (rigDetails && rigDetails.bones && rigDetails.bones.length > 0) {
402
+ console.log('Creating rig visualization with', rigDetails.bones.length, 'bones');
403
+ console.log('Force Z setting before creating rig:', rigOptions.forceZ);
404
+ createRig(state.model, state.scene);
405
+ console.log('Rig visualization created, Force Z is now:', rigOptions.forceZ);
406
+ } else {
407
+ console.log('No bones found in rigDetails, not creating visualization');
408
+ // Even if no bones are found, display what we did find
409
+ if (rigDetails) {
410
+ console.log('Showing rig details even though no bones found');
411
+ createRigDetailsContent(rigContent, rigDetails);
412
+ } else {
413
+ // If analysis completely failed, show error
414
+ console.error('Rig analysis failed completely');
415
+ rigContent.innerHTML = '<p>Error analyzing rig data. No rig information found.</p>';
416
+ }
417
+ return;
418
+ }
419
+ } catch (error) {
420
+ console.error('Error analyzing rig:', error);
421
+ rigContent.innerHTML = '<p>Error analyzing rig: ' + error.message + '</p>';
422
+ return;
423
+ }
424
+ } else if (!state.model) {
425
+ console.log('No model available for rig analysis');
426
+ rigContent.innerHTML = '<p>No model loaded. Please load a GLB model with a rig.</p>';
427
+ return;
428
+ } else {
429
+ console.log('Using existing rig details:', rigDetails);
430
+ }
431
+
432
+ // Create the rig details content
433
+ createRigDetailsContent(rigContent, rigDetails);
434
+
435
+ // Process truncated text elements for tooltips
436
+ setupTruncationTooltips(rigContent);
437
+ }
438
+
439
+ // Global event listener for rig options changes
440
+ document.addEventListener('rigOptionsChange', function(e) {
441
+ console.log('Rig options change event received:', e.detail);
442
+
443
+ // Update rig options
444
+ if (e.detail) {
445
+ if (e.detail.displayRig !== undefined) {
446
+ rigOptions.displayRig = e.detail.displayRig;
447
+
448
+ // Sync with rig tab checkbox
449
+ const rigTabCheckbox = document.getElementById('display-rig-tab');
450
+ if (rigTabCheckbox && rigTabCheckbox.checked !== e.detail.displayRig) {
451
+ rigTabCheckbox.checked = e.detail.displayRig;
452
+ }
453
+ }
454
+
455
+ if (e.detail.forceZ !== undefined) {
456
+ rigOptions.forceZ = e.detail.forceZ;
457
+
458
+ // Sync with rig tab checkbox
459
+ const rigTabCheckbox = document.getElementById('force-z-tab');
460
+ if (rigTabCheckbox && rigTabCheckbox.checked !== e.detail.forceZ) {
461
+ rigTabCheckbox.checked = e.detail.forceZ;
462
+ }
463
+ }
464
+
465
+ if (e.detail.wireframe !== undefined) rigOptions.wireframe = e.detail.wireframe;
466
+ if (e.detail.primaryColor !== undefined) rigOptions.primaryColor = e.detail.primaryColor;
467
+ if (e.detail.secondaryColor !== undefined) rigOptions.secondaryColor = e.detail.secondaryColor;
468
+ if (e.detail.jointColor !== undefined) rigOptions.jointColor = e.detail.jointColor;
469
+
470
+ // Special handling for joint labels
471
+ if (e.detail.showJointLabels !== undefined) {
472
+ console.log(`Updating showJointLabels from ${rigOptions.showJointLabels} to ${e.detail.showJointLabels}`);
473
+ rigOptions.showJointLabels = e.detail.showJointLabels;
474
+
475
+ // Update any checkbox in the UI
476
+ const jointLabelsCheckbox = document.getElementById('show-joint-labels-tab');
477
+ if (jointLabelsCheckbox && jointLabelsCheckbox.checked !== e.detail.showJointLabels) {
478
+ jointLabelsCheckbox.checked = e.detail.showJointLabels;
479
+ }
480
+ }
481
+
482
+ // Special handling for bone labels - handle from settings modal only
483
+ if (e.detail.showBoneLabels !== undefined) {
484
+ console.log(`Updating showBoneLabels from ${rigOptions.showBoneLabels} to ${e.detail.showBoneLabels}`);
485
+ rigOptions.showBoneLabels = e.detail.showBoneLabels;
486
+ }
487
+
488
+ // Update control handle colors
489
+ if (e.detail.normalColor !== undefined) rigOptions.normalColor = e.detail.normalColor;
490
+ if (e.detail.hoverColor !== undefined) rigOptions.hoverColor = e.detail.hoverColor;
491
+ if (e.detail.activeColor !== undefined) rigOptions.activeColor = e.detail.activeColor;
492
+
493
+ // Apply the changes
494
+ updateRigVisualization();
495
+ }
496
+ });
497
+
498
+ // Event listener for reset rig button
499
+ document.addEventListener('resetRig', function() {
500
+ console.log('Reset rig event received');
501
+ resetRig();
502
+ });
503
+
504
+ /**
505
+ * Save a specific rig option to localStorage
506
+ * @param {string} optionName - The name of the rig option to save
507
+ * @param {any} value - The value to save
508
+ */
509
+ function saveRigOptionToLocalStorage(optionName, value) {
510
+ // Load current settings from localStorage
511
+ const currentSettings = loadSettings() || {};
512
+
513
+ // Initialize rigOptions if it doesn't exist
514
+ if (!currentSettings.rigOptions) {
515
+ currentSettings.rigOptions = {};
516
+ }
517
+
518
+ // Update the specific option
519
+ currentSettings.rigOptions[optionName] = value;
520
+
521
+ // Save updated settings back to localStorage
522
+ console.log(`Saving ${optionName}=${value} to localStorage`);
523
+ saveSettings(currentSettings);
524
+ }
525
+
526
+ // Cleanup tooltips when page unloads
527
+ window.addEventListener('beforeunload', () => {
528
+ // Clear all tooltip timers if they exist
529
+ if (typeof tooltipTimers !== 'undefined' && tooltipTimers) {
530
+ tooltipTimers.forEach(timerId => clearTimeout(timerId));
531
+ tooltipTimers.clear();
532
+ }
533
+
534
+ // Remove tooltip element if it exists
535
+ if (typeof tooltipElement !== 'undefined' && tooltipElement && tooltipElement.parentNode) {
536
+ tooltipElement.parentNode.removeChild(tooltipElement);
537
+ }
538
+ });
@@ -0,0 +1,70 @@
1
+ .uv-note {
2
+ font-size: 11px;
3
+ color: var(--label-text);
4
+ margin-top: 5px;
5
+ font-style: italic;
6
+ }
7
+
8
+
9
+ /* Shared UV Controls */
10
+ .uv-info-container {
11
+ margin-bottom: 15px;
12
+ font-size: 13px;
13
+ color: var(--text-color);
14
+ }
15
+
16
+ .uv-control-group {
17
+ margin-bottom: 15px;
18
+ padding: 10px;
19
+ background-color: rgba(0, 0, 0, 0.2);
20
+ border: 1px solid var(--panel-border);
21
+ }
22
+
23
+ .uv-control-group label {
24
+ display: block;
25
+ margin-bottom: 8px;
26
+ font-size: 0.85em;
27
+ font-weight: bold;
28
+ color: #aaa;
29
+ }
30
+
31
+ .uv-control-group select {
32
+ width: 100%;
33
+ background-color: #333;
34
+ color: #fff;
35
+ border: 1px solid #555;
36
+ padding: 6px;
37
+ border-radius: 3px;
38
+ }
39
+
40
+ .uv-control-row {
41
+ display: flex;
42
+ flex-wrap: wrap;
43
+ align-items: center;
44
+ margin-bottom: 8px;
45
+ gap: 8px;
46
+ }
47
+
48
+ .uv-control-row label {
49
+ width: 70px;
50
+ font-size: 0.85em;
51
+ color: #aaa;
52
+ }
53
+
54
+ .uv-control-row span {
55
+ width: 20px;
56
+ text-align: center;
57
+ color: var(--text-color);
58
+ font-weight: bold;
59
+ }
60
+
61
+ .uv-control-row input {
62
+ flex: 1;
63
+ width: 60px;
64
+ padding: 5px;
65
+ border: 1px solid #555;
66
+ background-color: #333;
67
+ color: #fff;
68
+ border-radius: 3px;
69
+ font-family: monospace;
70
+ }