@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,612 @@
1
+ import * as THREE from 'three';
2
+ import { checkHandleHover, getIsDragging } from './rig-mouse-handler';
3
+ import { getState } from '../state/scene-state';
4
+ import {
5
+ bones,
6
+ boneMaterial,
7
+ lockedBones,
8
+ boneSideMaterial,
9
+ boneVisualsGroup,
10
+ updateAllBoneMatrices,
11
+ restoreLockedBoneRotations,
12
+ clearBoneVisualsGroup
13
+ } from './bone-kinematics';
14
+ import { createBoneLabels, createJointLabels } from './rig-label-factory';
15
+ import { deduplicateItemsByName } from '../data/duplicate-handler';
16
+ import { clearPrimaryRigHandle, primaryRigHandle } from './rig-handle-factory';
17
+
18
+ export let rigDetails = null;
19
+ export const labelGroups = new Map(); // Map to store different types of label groups (joint, bone)
20
+
21
+ // Variables used for rig visualization
22
+ export const rigOptions = {
23
+ displayRig: true,
24
+ forceZ: true,
25
+ wireframe: false,
26
+ primaryColor: 0x4CAF50,
27
+ secondaryColor: 0xFFFF00,
28
+ jointColor: 0x00FFFF,
29
+ showJointLabels: false,
30
+ showBoneLabels: false,
31
+ normalColor: 0xFF0000,
32
+ hoverColor: 0x00FF00,
33
+ activeColor: 0x0000FF,
34
+ worldGravity: 1.0
35
+ };
36
+
37
+ /**
38
+ * Update one or multiple rig options
39
+ * @param {Object} options - Object containing the options to update
40
+ */
41
+ export function updateRigOptions(options) {
42
+ if (!options) return;
43
+
44
+ // Update each property
45
+ if (options.displayRig !== undefined) rigOptions.displayRig = options.displayRig;
46
+ if (options.forceZ !== undefined) rigOptions.forceZ = options.forceZ;
47
+ if (options.wireframe !== undefined) rigOptions.wireframe = options.wireframe;
48
+ if (options.primaryColor !== undefined) rigOptions.primaryColor = options.primaryColor;
49
+ if (options.secondaryColor !== undefined) rigOptions.secondaryColor = options.secondaryColor;
50
+ if (options.jointColor !== undefined) rigOptions.jointColor = options.jointColor;
51
+ if (options.showJointLabels !== undefined) rigOptions.showJointLabels = options.showJointLabels;
52
+ if (options.showBoneLabels !== undefined) rigOptions.showBoneLabels = options.showBoneLabels;
53
+ if (options.normalColor !== undefined) rigOptions.normalColor = options.normalColor;
54
+ if (options.hoverColor !== undefined) rigOptions.hoverColor = options.hoverColor;
55
+ if (options.activeColor !== undefined) rigOptions.activeColor = options.activeColor;
56
+ if (options.worldGravity !== undefined) rigOptions.worldGravity = options.worldGravity;
57
+
58
+ console.log('Rig options updated:', rigOptions);
59
+
60
+ // Dispatch an event to notify other components of the change
61
+ const event = new CustomEvent('rigOptionsChange', {
62
+ detail: rigOptions
63
+ });
64
+ document.dispatchEvent(event);
65
+ }
66
+
67
+ /**
68
+ * Update the rig visualization based on option changes
69
+ */
70
+ export function updateRigVisualization() {
71
+ if (!boneVisualsGroup) return;
72
+
73
+ console.log('Updating rig visualization with options:', JSON.stringify(rigOptions));
74
+
75
+ // Toggle rig visibility without affecting creation or forceZ
76
+ if (boneVisualsGroup) {
77
+ boneVisualsGroup.visible = rigOptions.displayRig;
78
+ }
79
+
80
+ if (primaryRigHandle) {
81
+ primaryRigHandle.visible = rigOptions.displayRig;
82
+ }
83
+
84
+ // Update joint labels visibility using the dedicated functions
85
+ if (rigOptions.showJointLabels && rigOptions.displayRig) {
86
+ console.log('Showing joint labels');
87
+ showLabels('joint');
88
+ } else {
89
+ console.log('Hiding joint labels');
90
+ hideLabels('joint');
91
+ }
92
+
93
+ // Update bone labels visibility using the dedicated functions
94
+ if (rigOptions.showBoneLabels && rigOptions.displayRig) {
95
+ console.log('Showing bone labels');
96
+ showLabels('bone');
97
+ } else {
98
+ console.log('Hiding bone labels');
99
+ hideLabels('bone');
100
+ }
101
+
102
+ // Create labels if needed but don't exist yet
103
+ const state = getState();
104
+
105
+ // Joint labels
106
+ const jointLabelGroup = state.scene ? state.scene.getObjectByName("JointLabels") : null;
107
+
108
+ if (jointLabelGroup) {
109
+ console.log('Updating joint labels visibility to:', rigOptions.showJointLabels && rigOptions.displayRig);
110
+
111
+ // Update individual label positions
112
+ jointLabelGroup.children.forEach(label => {
113
+ if (label.userData && label.userData.updatePosition) {
114
+ label.userData.updatePosition();
115
+ }
116
+ });
117
+ } else if (rigOptions.displayRig && state.scene) {
118
+ // If we don't have labels but rig is displayed, create them
119
+ console.log('No joint label group found, creating new joint labels');
120
+ createJointLabels(state.scene);
121
+
122
+ // Set visibility based on showJointLabels option
123
+ if (rigOptions.showJointLabels) {
124
+ showLabels('joint');
125
+ } else {
126
+ hideLabels('joint');
127
+ }
128
+ }
129
+
130
+ // Bone labels
131
+ const boneLabelGroup = state.scene ? state.scene.getObjectByName("BoneLabels") : null;
132
+
133
+ if (boneLabelGroup) {
134
+ console.log('Updating bone labels visibility to:', rigOptions.showBoneLabels && rigOptions.displayRig);
135
+
136
+ // Update individual label positions
137
+ boneLabelGroup.children.forEach(label => {
138
+ if (label.userData && label.userData.updatePosition) {
139
+ label.userData.updatePosition();
140
+ }
141
+ });
142
+ } else if (rigOptions.displayRig && state.scene) {
143
+ // If we don't have bone labels but rig is displayed, create them
144
+ console.log('No bone label group found, creating new bone labels');
145
+ createBoneLabels(state.scene);
146
+
147
+ // Set visibility based on showBoneLabels option
148
+ if (rigOptions.showBoneLabels) {
149
+ showLabels('bone');
150
+ } else {
151
+ hideLabels('bone');
152
+ }
153
+ }
154
+
155
+ // Refresh the joints data
156
+ refreshJointsData();
157
+
158
+ // Update primary and secondary colors and wireframe state
159
+ if (boneMaterial) {
160
+ boneMaterial.color.setHex(rigOptions.primaryColor);
161
+ boneMaterial.wireframe = rigOptions.wireframe;
162
+ boneMaterial.needsUpdate = true;
163
+ }
164
+
165
+ if (boneSideMaterial) {
166
+ boneSideMaterial.color.setHex(rigOptions.secondaryColor);
167
+ boneSideMaterial.wireframe = rigOptions.wireframe;
168
+ boneSideMaterial.needsUpdate = true;
169
+ }
170
+
171
+ boneVisualsGroup.traverse(object => {
172
+ // Update bone sides
173
+ if (object.isMesh && object.userData.bonePart === 'side') {
174
+ // Update color of alternating sides
175
+ if (!object.userData.sideIndex || object.userData.sideIndex % 2 === 0) {
176
+ // Even sides use primary color
177
+ object.material.color.setHex(rigOptions.primaryColor);
178
+ } else {
179
+ // Odd sides use secondary color
180
+ object.material.color.setHex(rigOptions.secondaryColor);
181
+ }
182
+
183
+ // Update wireframe setting
184
+ object.material.wireframe = rigOptions.wireframe;
185
+ object.material.needsUpdate = true;
186
+ }
187
+
188
+ // Update joint materials
189
+ if (object.isMesh && object.userData.bonePart === 'cap') {
190
+ object.material.color.setHex(rigOptions.jointColor);
191
+ object.material.wireframe = rigOptions.wireframe;
192
+ object.material.needsUpdate = true;
193
+
194
+ // Force update visibility of joint labels
195
+ if (object.userData.label) {
196
+ object.userData.label.visible = rigOptions.showJointLabels && rigOptions.displayRig;
197
+
198
+ // Make sure the label appears on top when Force Z is enabled
199
+ if (rigOptions.forceZ) {
200
+ object.userData.label.renderOrder = 1025; // Higher than joint spheres but lower than control handle
201
+ object.userData.label.material.depthTest = false;
202
+ } else {
203
+ object.userData.label.renderOrder = 500;
204
+ object.userData.label.material.depthTest = false; // Always render on top
205
+ }
206
+ object.userData.label.material.needsUpdate = true;
207
+ }
208
+ }
209
+ });
210
+
211
+ // Apply Force Z settings regardless of rig visibility
212
+ if (boneVisualsGroup) {
213
+ if (rigOptions.forceZ) {
214
+ console.log('Applying Force Z index to rig');
215
+ // Move the rig to render on top by setting renderOrder to a high value
216
+ // and disabling depth test for materials
217
+ boneVisualsGroup.renderOrder = 1000; // High value to render after other objects
218
+
219
+ if (boneMaterial) {
220
+ boneMaterial.depthTest = false;
221
+ boneMaterial.needsUpdate = true;
222
+ }
223
+
224
+ if (boneSideMaterial) {
225
+ boneSideMaterial.depthTest = false;
226
+ boneSideMaterial.needsUpdate = true;
227
+ }
228
+
229
+ // Set renderOrder and disable depth test for EVERY mesh in the group
230
+ boneVisualsGroup.traverse(object => {
231
+ if (object.isMesh) {
232
+ if (object.userData.bonePart === 'cap') {
233
+ // Joint spheres get higher renderOrder
234
+ object.renderOrder = 1020;
235
+ } else if (object.userData.bonePart === 'side') {
236
+ // Bone sides get lower renderOrder
237
+ object.renderOrder = 1010;
238
+ } else {
239
+ // Everything else
240
+ object.renderOrder = 1000;
241
+ }
242
+
243
+ if (object.material) {
244
+ object.material.depthTest = false;
245
+ object.material.needsUpdate = true;
246
+ }
247
+ }
248
+ });
249
+
250
+ if (primaryRigHandle && primaryRigHandle.material) {
251
+ // Control handle gets highest renderOrder
252
+ primaryRigHandle.renderOrder = 1030;
253
+ primaryRigHandle.material.depthTest = false;
254
+ primaryRigHandle.material.needsUpdate = true;
255
+ }
256
+ } else {
257
+ console.log('Resetting Force Z index for rig');
258
+ // Reset normal depth behavior
259
+ boneVisualsGroup.renderOrder = 0;
260
+
261
+ if (boneMaterial) {
262
+ boneMaterial.depthTest = true;
263
+ boneMaterial.needsUpdate = true;
264
+ }
265
+
266
+ if (boneSideMaterial) {
267
+ boneSideMaterial.depthTest = true;
268
+ boneSideMaterial.needsUpdate = true;
269
+ }
270
+
271
+ // Reset renderOrder and enable depth test for EVERY mesh in the group
272
+ boneVisualsGroup.traverse(object => {
273
+ if (object.isMesh) {
274
+ if (object.userData.bonePart === 'cap') {
275
+ // Even without force-Z, joints should be on top of bones
276
+ object.renderOrder = 10;
277
+ } else {
278
+ object.renderOrder = 0;
279
+ }
280
+
281
+ if (object.material) {
282
+ object.material.depthTest = true;
283
+ object.material.needsUpdate = true;
284
+ }
285
+ }
286
+ });
287
+
288
+ if (primaryRigHandle && primaryRigHandle.material) {
289
+ // Control handle should still be above everything else
290
+ primaryRigHandle.renderOrder = 20;
291
+ primaryRigHandle.material.depthTest = true;
292
+ primaryRigHandle.material.needsUpdate = true;
293
+ }
294
+ }
295
+ }
296
+ }
297
+
298
+
299
+ /**
300
+ * Reset the rig to its initial position
301
+ */
302
+ export function resetRig() {
303
+ if (!bones.length) return;
304
+
305
+ console.log('Resetting rig to initial position from GLB');
306
+
307
+ // Reset all bone rotations to their initial values from when the model was loaded
308
+ bones.forEach(bone => {
309
+ // Skip locked bones
310
+ if (lockedBones.has(bone.uuid)) return;
311
+
312
+ // If we have stored initial rotation, use it
313
+ if (bone.userData.initialRotation) {
314
+ bone.rotation.set(
315
+ bone.userData.initialRotation.x,
316
+ bone.userData.initialRotation.y,
317
+ bone.userData.initialRotation.z
318
+ );
319
+ bone.rotation.order = bone.userData.initialRotation.order;
320
+ } else {
321
+ // Fallback to identity if no initial rotation stored
322
+ bone.rotation.set(0, 0, 0);
323
+ }
324
+ });
325
+
326
+ // Update all matrices
327
+ updateAllBoneMatrices();
328
+
329
+ // If there's a furthest bone handle, update its position
330
+ if (primaryRigHandle && primaryRigHandle.userData.updatePosition) {
331
+ primaryRigHandle.userData.updatePosition();
332
+ }
333
+
334
+ console.log('Rig reset complete');
335
+ }
336
+
337
+ /**
338
+ * Update a label's position to follow its joint
339
+ * @param {Object} label - The label to update
340
+ * @param {Object} joint - The joint the label is attached to
341
+ */
342
+ export function updateLabelPosition(label, joint) {
343
+ if (!label || !joint) return;
344
+
345
+ // Get the joint's world position
346
+ const jointPos = new THREE.Vector3();
347
+ joint.getWorldPosition(jointPos);
348
+
349
+ // Position the label slightly above the joint
350
+ label.position.copy(jointPos);
351
+
352
+ // Get default offset in case geometry is missing
353
+ let offset = 0.2;
354
+
355
+ // Add offset based on joint position and geometry if available
356
+ if (joint.geometry && joint.geometry.parameters) {
357
+ // Use the joint's geometry parameters when available
358
+ if (joint.geometry.parameters.radius) {
359
+ offset = joint.geometry.parameters.radius * 2;
360
+ } else if (joint.geometry.parameters.radiusTop) {
361
+ offset = joint.geometry.parameters.radiusTop * 2;
362
+ }
363
+ }
364
+
365
+ // Apply offset based on joint position (top or bottom)
366
+ if (joint.position && joint.position.y > 0) {
367
+ // Top joint - place above
368
+ label.position.y += offset;
369
+ } else {
370
+ // Bottom joint - place to the side
371
+ label.position.x += offset;
372
+ }
373
+ }
374
+
375
+ /**
376
+ * Update animation for rig visuals
377
+ */
378
+ export function updateRigAnimation() {
379
+ // Set visibility based on displayRig flag
380
+ // But keep force Z settings applied regardless of visibility
381
+ if (!rigOptions.displayRig) {
382
+ // When displayRig is off, hide visuals but maintain ForceZ settings
383
+ if (primaryRigHandle) {
384
+ primaryRigHandle.visible = false;
385
+ }
386
+ if (boneVisualsGroup) {
387
+ boneVisualsGroup.visible = false;
388
+
389
+ // Still update positions even when hidden to ensure ForceZ works properly
390
+ // when the rig becomes visible again
391
+ boneVisualsGroup.children.forEach(boneGroup => {
392
+ if (boneGroup.userData.updatePosition) {
393
+ boneGroup.userData.updatePosition();
394
+ }
395
+ });
396
+ }
397
+ return;
398
+ }
399
+
400
+ // When displayRig is on, update and show everything
401
+ if (boneVisualsGroup) {
402
+ boneVisualsGroup.visible = true;
403
+ boneVisualsGroup.children.forEach(boneGroup => {
404
+ if (boneGroup.userData.updatePosition) {
405
+ boneGroup.userData.updatePosition();
406
+ }
407
+ });
408
+ }
409
+
410
+ // Update furthest bone handle
411
+ if (primaryRigHandle) {
412
+ primaryRigHandle.visible = true;
413
+ if (primaryRigHandle.userData.updatePosition && !getIsDragging()) {
414
+ // Only update handle position when not dragging
415
+ primaryRigHandle.userData.updatePosition();
416
+ }
417
+ }
418
+
419
+ // Update joint labels
420
+ const state = getState();
421
+
422
+ // Update all label groups
423
+ for (const [type, group] of labelGroups) {
424
+ if (group) {
425
+ group.children.forEach(label => {
426
+ if (label.userData && label.userData.updatePosition) {
427
+ label.userData.updatePosition();
428
+ }
429
+ });
430
+ }
431
+ }
432
+
433
+ // Apply locked rotations to bones
434
+ restoreLockedBoneRotations();
435
+
436
+ // Check handle hover on each frame
437
+ checkHandleHover();
438
+ }
439
+
440
+ /**
441
+ * Clear existing rig visualization from the scene
442
+ * @param {Object} scene - The Three.js scene
443
+ */
444
+ export function clearRigVisualization(scene) {
445
+ if (boneVisualsGroup) {
446
+ scene.remove(boneVisualsGroup);
447
+ clearBoneVisualsGroup();
448
+ }
449
+ if (primaryRigHandle) {
450
+ scene.remove(primaryRigHandle);
451
+ clearPrimaryRigHandle();
452
+ }
453
+ }
454
+
455
+ /**
456
+ * Refresh the joints data based on current bone visualizations
457
+ */
458
+ function refreshJointsData() {
459
+ // Clear existing joints data
460
+ if (rigDetails && rigDetails.joints) {
461
+ rigDetails.joints = [];
462
+
463
+ // Collect joint data from all bone visualizations
464
+ if (boneVisualsGroup) {
465
+ boneVisualsGroup.traverse(object => {
466
+ if (object.userData && object.userData.isVisualBone) {
467
+ // Get the parent and child bones
468
+ const parentBone = object.userData.parentBone;
469
+ const childBone = object.userData.childBone;
470
+
471
+ if (parentBone && childBone) {
472
+ // Regular joint between parent and child
473
+ const jointName = `Joint_${parentBone.name}_to_${childBone.name}`;
474
+
475
+ // Create joint data (without constraint type)
476
+ const jointData = {
477
+ name: jointName,
478
+ parentBone: parentBone.name,
479
+ childBone: childBone.name,
480
+ position: [object.position.x, object.position.y, object.position.z],
481
+ count: 1
482
+ };
483
+
484
+ rigDetails.joints.push(jointData);
485
+ } else if (object.userData.rootBone) {
486
+ // Root joint
487
+ const rootBone = object.userData.rootBone;
488
+ const jointName = `Root_Joint_${rootBone.name}`;
489
+
490
+ // Create joint data (without constraint type)
491
+ const jointData = {
492
+ name: jointName,
493
+ parentBone: "Scene Root",
494
+ childBone: rootBone.name,
495
+ position: [object.position.x, object.position.y, object.position.z],
496
+ count: 1,
497
+ isRoot: true
498
+ };
499
+
500
+ rigDetails.joints.push(jointData);
501
+ }
502
+ }
503
+ });
504
+ }
505
+
506
+ // Deduplicate the joints data
507
+ rigDetails.joints = deduplicateItemsByName(rigDetails.joints);
508
+ }
509
+ }
510
+
511
+ /**
512
+ * Set a label group
513
+ * @param {string|Object} typeOrName - The type of label group ('joint' or 'bone') or the name for backward compatibility
514
+ * @param {string|Object} nameOrScene - The name of the label group or the scene for backward compatibility
515
+ * @param {Object} [sceneParam] - The Three.js scene (optional for backward compatibility)
516
+ */
517
+ export function setLabelGroup(typeOrName, nameOrScene, sceneParam) {
518
+ // Handle backward compatibility with old function signature
519
+ let type, name, scene;
520
+
521
+ if (typeof typeOrName === 'string' && (typeOrName === 'joint' || typeOrName === 'bone')) {
522
+ // New signature: (type, name, scene)
523
+ type = typeOrName;
524
+ name = nameOrScene;
525
+ scene = sceneParam;
526
+ } else {
527
+ // Old signature: (name, scene)
528
+ type = 'joint';
529
+ name = typeOrName;
530
+ scene = nameOrScene;
531
+ }
532
+
533
+ const group = new THREE.Group();
534
+ group.name = name;
535
+
536
+ // Initialize visibility based on current settings
537
+ const isVisible = type === 'joint'
538
+ ? rigOptions.showJointLabels && rigOptions.displayRig
539
+ : rigOptions.showBoneLabels && rigOptions.displayRig;
540
+
541
+ group.visible = isVisible;
542
+ console.log(`Creating ${type} label group with initial visibility:`, group.visible);
543
+
544
+ scene.add(group);
545
+ labelGroups.set(type, group);
546
+ }
547
+
548
+
549
+
550
+ /**
551
+ * Update the rig details object with new values
552
+ * @param {Object} newDetails - The new rig details object
553
+ */
554
+ export function updateRigDetails(newDetails) {
555
+ rigDetails = newDetails;
556
+ }
557
+
558
+ /**
559
+ * Clear all labels of a specific type from the scene
560
+ * @param {string} type - The type of labels to clear ('joint' or 'bone')
561
+ * @param {Object} scene - The Three.js scene
562
+ */
563
+ export function clearLabels(type, scene) {
564
+ const name = type === 'joint' ? "JointLabels" : "BoneLabels";
565
+ const existingLabels = scene.getObjectByName(name);
566
+ if (existingLabels) {
567
+ scene.remove(existingLabels);
568
+ if (labelGroups.has(type)) {
569
+ labelGroups.delete(type);
570
+ }
571
+ }
572
+ }
573
+
574
+ /**
575
+ * Show labels of a specific type
576
+ * @param {string} type - The type of labels to show ('joint' or 'bone')
577
+ */
578
+ export function showLabels(type) {
579
+ const group = labelGroups.get(type);
580
+ if (group) {
581
+ console.log(`Explicitly showing ${type} labels`);
582
+ group.visible = true; // Force visibility regardless of other settings
583
+
584
+ // Also ensure each individual label is visible
585
+ group.children.forEach(label => {
586
+ if (label) {
587
+ label.visible = true;
588
+ }
589
+ });
590
+ }
591
+ }
592
+
593
+ /**
594
+ * Hide labels of a specific type
595
+ * @param {string} type - The type of labels to hide ('joint' or 'bone')
596
+ */
597
+ export function hideLabels(type) {
598
+ const group = labelGroups.get(type);
599
+ if (group) {
600
+ console.log(`Explicitly hiding ${type} labels`);
601
+ group.visible = false;
602
+ }
603
+ }
604
+
605
+ /**
606
+ * Get a specific label group
607
+ * @param {string} type - The type of label group to retrieve ('joint' or 'bone')
608
+ * @returns {Object} The requested label group or null if not found
609
+ */
610
+ export function getLabelGroup(type) {
611
+ return labelGroups.get(type);
612
+ }