@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.
- package/bin/cli.js +69 -0
- package/package.json +13 -7
- package/src/asset_debugger/axis-indicator/axis-indicator.css +6 -0
- package/src/asset_debugger/axis-indicator/axis-indicator.html +20 -0
- package/src/asset_debugger/axis-indicator/axis-indicator.js +822 -0
- package/src/asset_debugger/debugger-scene/debugger-scene.css +142 -0
- package/src/asset_debugger/debugger-scene/debugger-scene.html +80 -0
- package/src/asset_debugger/debugger-scene/debugger-scene.js +791 -0
- package/src/asset_debugger/header/header.css +73 -0
- package/src/asset_debugger/header/header.html +24 -0
- package/src/asset_debugger/header/header.js +224 -0
- package/src/asset_debugger/index.html +76 -0
- package/src/asset_debugger/landing-page/landing-page.css +396 -0
- package/src/asset_debugger/landing-page/landing-page.html +81 -0
- package/src/asset_debugger/landing-page/landing-page.js +611 -0
- package/src/asset_debugger/loading-splash/loading-splash.css +195 -0
- package/src/asset_debugger/loading-splash/loading-splash.html +22 -0
- package/src/asset_debugger/loading-splash/loading-splash.js +59 -0
- package/src/asset_debugger/loading-splash/preview-loading-splash.js +66 -0
- package/src/asset_debugger/main.css +14 -0
- package/src/asset_debugger/modals/examples-modal/examples-modal.css +41 -0
- package/src/asset_debugger/modals/examples-modal/examples-modal.html +18 -0
- package/src/asset_debugger/modals/examples-modal/examples-modal.js +111 -0
- package/src/asset_debugger/modals/examples-modal/examples.js +125 -0
- package/src/asset_debugger/modals/html-editor-modal/html-editor-modal.css +452 -0
- package/src/asset_debugger/modals/html-editor-modal/html-editor-modal.html +87 -0
- package/src/asset_debugger/modals/html-editor-modal/html-editor-modal.js +675 -0
- package/src/asset_debugger/modals/mesh-info-modal/mesh-info-modal.css +219 -0
- package/src/asset_debugger/modals/mesh-info-modal/mesh-info-modal.html +20 -0
- package/src/asset_debugger/modals/mesh-info-modal/mesh-info-modal.js +548 -0
- package/src/asset_debugger/modals/settings-modal/settings-modal.css +103 -0
- package/src/asset_debugger/modals/settings-modal/settings-modal.html +158 -0
- package/src/asset_debugger/modals/settings-modal/settings-modal.js +475 -0
- package/src/asset_debugger/panels/asset-panel/asset-panel.css +263 -0
- package/src/asset_debugger/panels/asset-panel/asset-panel.html +123 -0
- package/src/asset_debugger/panels/asset-panel/asset-panel.js +136 -0
- package/src/asset_debugger/panels/asset-panel/atlas-heading/atlas-heading.css +94 -0
- package/src/asset_debugger/panels/asset-panel/atlas-heading/atlas-heading.js +312 -0
- package/src/asset_debugger/panels/asset-panel/mesh-heading/mesh-heading.css +129 -0
- package/src/asset_debugger/panels/asset-panel/mesh-heading/mesh-heading.js +486 -0
- package/src/asset_debugger/panels/asset-panel/rig-heading/rig-heading.css +545 -0
- package/src/asset_debugger/panels/asset-panel/rig-heading/rig-heading.js +538 -0
- package/src/asset_debugger/panels/asset-panel/uv-heading/uv-heading.css +70 -0
- package/src/asset_debugger/panels/asset-panel/uv-heading/uv-heading.js +586 -0
- package/src/asset_debugger/panels/world-panel/world-panel.css +364 -0
- package/src/asset_debugger/panels/world-panel/world-panel.html +173 -0
- package/src/asset_debugger/panels/world-panel/world-panel.js +1891 -0
- package/src/asset_debugger/router.js +190 -0
- package/src/asset_debugger/util/animation/playback/animation-playback-controller.js +150 -0
- package/src/asset_debugger/util/animation/playback/animation-preview-controller.js +316 -0
- package/src/asset_debugger/util/animation/playback/css3d-bounce-controller.js +400 -0
- package/src/asset_debugger/util/animation/playback/css3d-reversal-controller.js +821 -0
- package/src/asset_debugger/util/animation/render/css3d-prerender-controller.js +696 -0
- package/src/asset_debugger/util/animation/render/debug-texture-factory.js +0 -0
- package/src/asset_debugger/util/animation/render/iframe2texture-render-controller.js +199 -0
- package/src/asset_debugger/util/animation/render/image2texture-prerender-controller.js +461 -0
- package/src/asset_debugger/util/animation/render/pbr-material-factory.js +82 -0
- package/src/asset_debugger/util/common.css +280 -0
- package/src/asset_debugger/util/data/animation-classifier.js +323 -0
- package/src/asset_debugger/util/data/duplicate-handler.js +20 -0
- package/src/asset_debugger/util/data/glb-buffer-manager.js +407 -0
- package/src/asset_debugger/util/data/glb-classifier.js +290 -0
- package/src/asset_debugger/util/data/html-formatter.js +76 -0
- package/src/asset_debugger/util/data/html-linter.js +276 -0
- package/src/asset_debugger/util/data/localstorage-manager.js +265 -0
- package/src/asset_debugger/util/data/mesh-html-manager.js +295 -0
- package/src/asset_debugger/util/data/string-serder.js +303 -0
- package/src/asset_debugger/util/data/texture-classifier.js +663 -0
- package/src/asset_debugger/util/data/upload/background-file-handler.js +292 -0
- package/src/asset_debugger/util/data/upload/dropzone-preview-controller.js +396 -0
- package/src/asset_debugger/util/data/upload/file-upload-manager.js +495 -0
- package/src/asset_debugger/util/data/upload/glb-file-handler.js +36 -0
- package/src/asset_debugger/util/data/upload/glb-preview-controller.js +317 -0
- package/src/asset_debugger/util/data/upload/lighting-file-handler.js +194 -0
- package/src/asset_debugger/util/data/upload/model-file-manager.js +104 -0
- package/src/asset_debugger/util/data/upload/texture-file-handler.js +166 -0
- package/src/asset_debugger/util/data/upload/zip-handler.js +686 -0
- package/src/asset_debugger/util/loaders/html2canvas-loader.js +107 -0
- package/src/asset_debugger/util/rig/bone-kinematics.js +403 -0
- package/src/asset_debugger/util/rig/rig-constraint-manager.js +618 -0
- package/src/asset_debugger/util/rig/rig-controller.js +612 -0
- package/src/asset_debugger/util/rig/rig-factory.js +628 -0
- package/src/asset_debugger/util/rig/rig-handle-factory.js +46 -0
- package/src/asset_debugger/util/rig/rig-label-factory.js +441 -0
- package/src/asset_debugger/util/rig/rig-mouse-handler.js +377 -0
- package/src/asset_debugger/util/rig/rig-state-manager.js +175 -0
- package/src/asset_debugger/util/rig/rig-tooltip-manager.js +267 -0
- package/src/asset_debugger/util/rig/rig-ui-factory.js +700 -0
- package/src/asset_debugger/util/scene/background-manager.js +284 -0
- package/src/asset_debugger/util/scene/camera-controller.js +243 -0
- package/src/asset_debugger/util/scene/css3d-debug-controller.js +406 -0
- package/src/asset_debugger/util/scene/css3d-frame-factory.js +113 -0
- package/src/asset_debugger/util/scene/css3d-scene-manager.js +529 -0
- package/src/asset_debugger/util/scene/glb-controller.js +208 -0
- package/src/asset_debugger/util/scene/lighting-manager.js +690 -0
- package/src/asset_debugger/util/scene/threejs-model-manager.js +437 -0
- package/src/asset_debugger/util/scene/threejs-preview-manager.js +207 -0
- package/src/asset_debugger/util/scene/threejs-preview-setup.js +478 -0
- package/src/asset_debugger/util/scene/threejs-scene-controller.js +286 -0
- package/src/asset_debugger/util/scene/ui-manager.js +107 -0
- package/src/asset_debugger/util/state/animation-state.js +128 -0
- package/src/asset_debugger/util/state/css3d-state.js +83 -0
- package/src/asset_debugger/util/state/glb-preview-state.js +31 -0
- package/src/asset_debugger/util/state/log-util.js +197 -0
- package/src/asset_debugger/util/state/scene-state.js +452 -0
- package/src/asset_debugger/util/state/threejs-state.js +54 -0
- package/src/asset_debugger/util/workers/lighting-worker.js +61 -0
- package/src/asset_debugger/util/workers/model-worker.js +109 -0
- package/src/asset_debugger/util/workers/texture-worker.js +54 -0
- package/src/asset_debugger/util/workers/worker-manager.js +212 -0
- package/src/asset_debugger/widgets/mesh-info-widget.js +280 -0
- package/src/index.html +261 -0
- package/src/index.js +8 -0
- 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
|
+
}
|