distark-render 1.1.5 → 1.1.9
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/README.md +0 -0
- package/assets/presets/jumping-jack.json +194 -0
- package/assets/tank.json +0 -0
- package/dist/cli/animate.d.ts +0 -0
- package/dist/cli/animate.d.ts.map +1 -1
- package/dist/cli/animate.js +0 -1
- package/dist/cli/animate.js.map +1 -1
- package/dist/cli/diff.d.ts +0 -0
- package/dist/cli/diff.d.ts.map +0 -0
- package/dist/cli/diff.js +0 -0
- package/dist/cli/diff.js.map +0 -0
- package/dist/cli/distark-check.d.ts +0 -0
- package/dist/cli/distark-check.d.ts.map +0 -0
- package/dist/cli/distark-check.js +20 -14
- package/dist/cli/distark-check.js.map +1 -1
- package/dist/cli/query.d.ts +0 -0
- package/dist/cli/query.d.ts.map +0 -0
- package/dist/cli/query.js +0 -0
- package/dist/cli/query.js.map +0 -0
- package/dist/cli/record.d.ts +0 -0
- package/dist/cli/record.d.ts.map +0 -0
- package/dist/cli/record.js +0 -0
- package/dist/cli/record.js.map +0 -0
- package/dist/cli/render.d.ts +0 -0
- package/dist/cli/render.d.ts.map +0 -0
- package/dist/cli/render.js +0 -0
- package/dist/cli/render.js.map +0 -0
- package/dist/cli/scene.d.ts +15 -0
- package/dist/cli/scene.d.ts.map +1 -0
- package/dist/cli/scene.js +239 -0
- package/dist/cli/scene.js.map +1 -0
- package/dist/cli/shared.d.ts +0 -0
- package/dist/cli/shared.d.ts.map +0 -0
- package/dist/cli/shared.js +0 -0
- package/dist/cli/shared.js.map +0 -0
- package/dist/cli/test.d.ts +0 -0
- package/dist/cli/test.d.ts.map +0 -0
- package/dist/cli/test.js +0 -0
- package/dist/cli/test.js.map +0 -0
- package/dist/cli/verify.d.ts +0 -0
- package/dist/cli/verify.d.ts.map +0 -0
- package/dist/cli/verify.js +1 -1
- package/dist/cli/verify.js.map +1 -1
- package/dist/modules/adapters/p5Renderer.d.ts +0 -0
- package/dist/modules/adapters/p5Renderer.d.ts.map +0 -0
- package/dist/modules/adapters/p5Renderer.js +0 -0
- package/dist/modules/adapters/p5Renderer.js.map +0 -0
- package/dist/modules/adapters/skiaRenderer.d.ts +0 -0
- package/dist/modules/adapters/skiaRenderer.d.ts.map +0 -0
- package/dist/modules/adapters/skiaRenderer.js +0 -0
- package/dist/modules/adapters/skiaRenderer.js.map +0 -0
- package/dist/modules/animationDiff.d.ts +0 -0
- package/dist/modules/animationDiff.d.ts.map +0 -0
- package/dist/modules/animationDiff.js +1 -1
- package/dist/modules/animationDiff.js.map +1 -1
- package/dist/modules/eyeSystem.d.ts +0 -0
- package/dist/modules/eyeSystem.d.ts.map +0 -0
- package/dist/modules/eyeSystem.js +0 -0
- package/dist/modules/eyeSystem.js.map +0 -0
- package/dist/modules/imageLoad.d.ts +0 -0
- package/dist/modules/imageLoad.d.ts.map +0 -0
- package/dist/modules/imageLoad.js +0 -0
- package/dist/modules/imageLoad.js.map +0 -0
- package/dist/modules/mouthSystem.d.ts +0 -0
- package/dist/modules/mouthSystem.d.ts.map +0 -0
- package/dist/modules/mouthSystem.js +0 -0
- package/dist/modules/mouthSystem.js.map +0 -0
- package/dist/modules/renderRig.d.ts +0 -0
- package/dist/modules/renderRig.d.ts.map +1 -1
- package/dist/modules/renderRig.js +130 -145
- package/dist/modules/renderRig.js.map +1 -1
- package/dist/modules/sceneRenderer.d.ts +160 -0
- package/dist/modules/sceneRenderer.d.ts.map +1 -0
- package/dist/modules/sceneRenderer.js +616 -0
- package/dist/modules/sceneRenderer.js.map +1 -0
- package/dist/tests/helpers.d.ts +0 -0
- package/dist/tests/helpers.d.ts.map +0 -0
- package/dist/tests/helpers.js +0 -0
- package/dist/tests/helpers.js.map +0 -0
- package/dist/tests/test-animation-diff-rendering.d.ts +0 -0
- package/dist/tests/test-animation-diff-rendering.d.ts.map +0 -0
- package/dist/tests/test-animation-diff-rendering.js +0 -0
- package/dist/tests/test-animation-diff-rendering.js.map +0 -0
- package/dist/tests/test-animation-diff.d.ts +0 -0
- package/dist/tests/test-animation-diff.d.ts.map +0 -0
- package/dist/tests/test-animation-diff.js +13 -13
- package/dist/tests/test-animation-diff.js.map +1 -1
- package/dist/tests/test-autofit.d.ts +0 -0
- package/dist/tests/test-autofit.d.ts.map +0 -0
- package/dist/tests/test-autofit.js +0 -0
- package/dist/tests/test-autofit.js.map +0 -0
- package/dist/tests/test-base-autofit.d.ts +0 -0
- package/dist/tests/test-base-autofit.d.ts.map +0 -0
- package/dist/tests/test-base-autofit.js +0 -0
- package/dist/tests/test-base-autofit.js.map +0 -0
- package/dist/tests/test-cli.d.ts +0 -0
- package/dist/tests/test-cli.d.ts.map +0 -0
- package/dist/tests/test-cli.js +0 -0
- package/dist/tests/test-cli.js.map +0 -0
- package/dist/tests/test-image-loading.d.ts +0 -0
- package/dist/tests/test-image-loading.d.ts.map +0 -0
- package/dist/tests/test-image-loading.js +0 -0
- package/dist/tests/test-image-loading.js.map +0 -0
- package/dist/tests/test-joint-movement.d.ts +0 -0
- package/dist/tests/test-joint-movement.d.ts.map +0 -0
- package/dist/tests/test-joint-movement.js +0 -0
- package/dist/tests/test-joint-movement.js.map +0 -0
- package/dist/tests/test-p5-image-types.d.ts +0 -0
- package/dist/tests/test-p5-image-types.d.ts.map +0 -0
- package/dist/tests/test-p5-image-types.js +0 -0
- package/dist/tests/test-p5-image-types.js.map +0 -0
- package/dist/tests/test-scene.d.ts +13 -0
- package/dist/tests/test-scene.d.ts.map +1 -0
- package/dist/tests/test-scene.js +528 -0
- package/dist/tests/test-scene.js.map +1 -0
- package/dist/tests/test-skia.d.ts +0 -0
- package/dist/tests/test-skia.d.ts.map +0 -0
- package/dist/tests/test-skia.js +0 -0
- package/dist/tests/test-skia.js.map +0 -0
- package/dist/tests/test-torso-pivot.d.ts +11 -0
- package/dist/tests/test-torso-pivot.d.ts.map +1 -0
- package/dist/tests/test-torso-pivot.js +265 -0
- package/dist/tests/test-torso-pivot.js.map +1 -0
- package/dist/tests/test-visual-verification.d.ts +0 -0
- package/dist/tests/test-visual-verification.d.ts.map +0 -0
- package/dist/tests/test-visual-verification.js +0 -0
- package/dist/tests/test-visual-verification.js.map +0 -0
- package/dist/types.d.ts +1 -1
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +0 -0
- package/dist/types.js.map +0 -0
- package/package.json +96 -91
- package/dist/tests/test-hidden-parts.d.ts +0 -33
- package/dist/tests/test-hidden-parts.d.ts.map +0 -1
- package/dist/tests/test-hidden-parts.js +0 -204
- package/dist/tests/test-hidden-parts.js.map +0 -1
|
@@ -58,13 +58,12 @@ export class CharacterRigRenderer {
|
|
|
58
58
|
const jointOffset = rigData.jointOffset || {};
|
|
59
59
|
const zIndexValues = rigData.zIndexValues || {};
|
|
60
60
|
const eyes = rigData.eyes || {};
|
|
61
|
-
const
|
|
61
|
+
const visibility = rigData.visibility || {}; // Default: all visible if not specified
|
|
62
62
|
const flipX = rigData.flipX || false; // No flip by default
|
|
63
63
|
const flipHead = rigData.flipHead || false; // No head flip by default
|
|
64
64
|
const imageScale = rigData.imageScale ?? 1.0; // Use imageScale from rigData, default to 1.0
|
|
65
65
|
// Create array of all limbs/components with their computed transforms
|
|
66
66
|
const allObjects = [];
|
|
67
|
-
const isVisible = (partName) => hiddenValues[partName] !== true;
|
|
68
67
|
// Root transform (character position in world space)
|
|
69
68
|
const rootTransform = {
|
|
70
69
|
x: centerX,
|
|
@@ -73,35 +72,58 @@ export class CharacterRigRenderer {
|
|
|
73
72
|
scaleX: flipX ? -1 : 1,
|
|
74
73
|
scaleY: 1
|
|
75
74
|
};
|
|
75
|
+
// Torso pivot transform: allows the torso (and all children) to rotate/offset
|
|
76
|
+
// around a configurable pivot point (e.g. hip/waist area).
|
|
77
|
+
// root_torso defines where in root-local space the pivot lives.
|
|
78
|
+
// rotationValues["torso"] is the rotation angle applied around that pivot.
|
|
79
|
+
const root_torso = pivotPoints['root_torso'] || { x: 0, y: 0 };
|
|
80
|
+
const torsoPivotRot = rotations["torso"] || 0;
|
|
81
|
+
const torsoTransform = this.applyTransform(rootTransform, {
|
|
82
|
+
x: root_torso.x || 0,
|
|
83
|
+
y: root_torso.y || 0,
|
|
84
|
+
rotation: torsoPivotRot,
|
|
85
|
+
scaleX: 1,
|
|
86
|
+
scaleY: 1
|
|
87
|
+
});
|
|
76
88
|
// Torso
|
|
77
|
-
if (
|
|
89
|
+
if (visibility.torso !== false) {
|
|
78
90
|
const torsoWidth = dimensions.torso?.width || 60;
|
|
79
91
|
const torsoHeight = dimensions.torso?.height || 120;
|
|
80
92
|
const selfRot = selfRotations["torso"] || 0;
|
|
81
93
|
// CRITICAL FIX: Look up image by ACTUAL PATH from rigData, not semantic key!
|
|
82
94
|
const torsoImagePath = rigData.imagePaths?.torso;
|
|
83
95
|
const torsoImage = torsoImagePath ? loadedImages[torsoImagePath] : undefined;
|
|
96
|
+
// The torso image bottom-center is anchored at torsoTransform (= root_torso
|
|
97
|
+
// world position). Moving root_torso moves the torso image; rotating
|
|
98
|
+
// rotationValues["torso"] rotates the torso around that anchor point.
|
|
99
|
+
const torsoJointOffset = jointOffset['root_torso'] || { x: 0, y: 0 };
|
|
100
|
+
const torsoImageTransform = this.applyTransform(torsoTransform, {
|
|
101
|
+
x: torsoJointOffset.x || 0,
|
|
102
|
+
y: torsoJointOffset.y || 0,
|
|
103
|
+
rotation: selfRot,
|
|
104
|
+
scaleX: 1,
|
|
105
|
+
scaleY: 1
|
|
106
|
+
});
|
|
84
107
|
allObjects.push({
|
|
85
108
|
name: 'torso',
|
|
86
109
|
type: 'limb',
|
|
87
110
|
zIndex: zIndexValues['torso'] || 1,
|
|
88
111
|
width: torsoWidth * imageScale,
|
|
89
112
|
height: torsoHeight * imageScale,
|
|
90
|
-
x:
|
|
91
|
-
y:
|
|
92
|
-
rotation:
|
|
93
|
-
scaleX:
|
|
94
|
-
scaleY:
|
|
95
|
-
// Anchor point (where the image is drawn from - top center for torso)
|
|
113
|
+
x: torsoImageTransform.x,
|
|
114
|
+
y: torsoImageTransform.y,
|
|
115
|
+
rotation: torsoImageTransform.rotation,
|
|
116
|
+
scaleX: torsoImageTransform.scaleX,
|
|
117
|
+
scaleY: torsoImageTransform.scaleY,
|
|
96
118
|
anchorX: 0.5,
|
|
97
|
-
anchorY: 1,
|
|
119
|
+
anchorY: 1, // bottom-center sits at root_torso world position
|
|
98
120
|
imageKey: 'imagePaths.torso',
|
|
99
121
|
imageData: torsoImage,
|
|
100
122
|
selfRotation: selfRot
|
|
101
123
|
});
|
|
102
124
|
}
|
|
103
125
|
// Head
|
|
104
|
-
if (
|
|
126
|
+
if (visibility.head !== false) {
|
|
105
127
|
const connectionKey = `torso_head`;
|
|
106
128
|
const pivotPoint = pivotPoints[connectionKey] || { x: 0, y: 0 };
|
|
107
129
|
const headJointOffset = jointOffset[connectionKey] || { x: 0, y: 0 };
|
|
@@ -109,10 +131,10 @@ export class CharacterRigRenderer {
|
|
|
109
131
|
const headHeight = dimensions.head?.height || 80;
|
|
110
132
|
const headRot = rotations["head"] || 0;
|
|
111
133
|
const selfRot = selfRotations["head"] || 0;
|
|
112
|
-
// Calculate head transform
|
|
113
|
-
const headParentTransform = this.applyTransform(
|
|
114
|
-
x: pivotPoint.x || 0,
|
|
115
|
-
y: pivotPoint.y || 0,
|
|
134
|
+
// Calculate head transform — pivot is expressed in root space; convert to torso-local.
|
|
135
|
+
const headParentTransform = this.applyTransform(torsoTransform, {
|
|
136
|
+
x: (pivotPoint.x || 0) - (root_torso.x || 0),
|
|
137
|
+
y: (pivotPoint.y || 0) - (root_torso.y || 0),
|
|
116
138
|
rotation: headRot,
|
|
117
139
|
scaleX: flipHead ? -1 : 1,
|
|
118
140
|
scaleY: 1
|
|
@@ -147,7 +169,7 @@ export class CharacterRigRenderer {
|
|
|
147
169
|
});
|
|
148
170
|
}
|
|
149
171
|
// Mouth (child of head)
|
|
150
|
-
if (
|
|
172
|
+
if (visibility.mouth !== false) {
|
|
151
173
|
const headPivot = pivotPoints['torso_head'] || { x: 0, y: 0 };
|
|
152
174
|
const selfRot = selfRotations["mouth"] || 0;
|
|
153
175
|
const headRot = rotations["head"] || 0;
|
|
@@ -183,9 +205,9 @@ export class CharacterRigRenderer {
|
|
|
183
205
|
// Calculate final dimensions with size scaling
|
|
184
206
|
const finalMouthWidth = baseMouthWidth * mouthSizeScale;
|
|
185
207
|
const finalMouthHeight = baseMouthHeight * mouthSizeScale;
|
|
186
|
-
const headBaseTransform = this.applyTransform(
|
|
187
|
-
x: headPivot.x || 0,
|
|
188
|
-
y: headPivot.y || 0,
|
|
208
|
+
const headBaseTransform = this.applyTransform(torsoTransform, {
|
|
209
|
+
x: (headPivot.x || 0) - (root_torso.x || 0),
|
|
210
|
+
y: (headPivot.y || 0) - (root_torso.y || 0),
|
|
189
211
|
rotation: headRot,
|
|
190
212
|
scaleX: flipHead ? -1 : 1,
|
|
191
213
|
scaleY: 1
|
|
@@ -237,12 +259,12 @@ export class CharacterRigRenderer {
|
|
|
237
259
|
// CRITICAL FIX: Look up image by ACTUAL PATH from rigData.eyes
|
|
238
260
|
const leftEyeImagePath = eyes?.leftEyeImage;
|
|
239
261
|
const leftEyeImage = leftEyeImagePath ? loadedImages[leftEyeImagePath] : undefined;
|
|
240
|
-
if (
|
|
262
|
+
if (visibility.leftEye !== false && leftEyeImage && eyes) {
|
|
241
263
|
const headPivot = pivotPoints['torso_head'] || { x: 0, y: 0 };
|
|
242
264
|
const headRot = rotations["head"] || 0;
|
|
243
|
-
const headBaseTransform = this.applyTransform(
|
|
244
|
-
x: headPivot.x || 0,
|
|
245
|
-
y: headPivot.y || 0,
|
|
265
|
+
const headBaseTransform = this.applyTransform(torsoTransform, {
|
|
266
|
+
x: (headPivot.x || 0) - (root_torso.x || 0),
|
|
267
|
+
y: (headPivot.y || 0) - (root_torso.y || 0),
|
|
246
268
|
rotation: headRot,
|
|
247
269
|
scaleX: flipHead ? -1 : 1,
|
|
248
270
|
scaleY: 1
|
|
@@ -280,12 +302,12 @@ export class CharacterRigRenderer {
|
|
|
280
302
|
// Right Eye
|
|
281
303
|
const rightEyeImagePath = eyes?.rightEyeImage;
|
|
282
304
|
const rightEyeImage = getImage(rightEyeImagePath);
|
|
283
|
-
if (
|
|
305
|
+
if (visibility.rightEye !== false && rightEyeImage && eyes) {
|
|
284
306
|
const headPivot = pivotPoints['torso_head'] || { x: 0, y: 0 };
|
|
285
307
|
const headRot = rotations["head"] || 0;
|
|
286
|
-
const headBaseTransform = this.applyTransform(
|
|
287
|
-
x: headPivot.x || 0,
|
|
288
|
-
y: headPivot.y || 0,
|
|
308
|
+
const headBaseTransform = this.applyTransform(torsoTransform, {
|
|
309
|
+
x: (headPivot.x || 0) - (root_torso.x || 0),
|
|
310
|
+
y: (headPivot.y || 0) - (root_torso.y || 0),
|
|
289
311
|
rotation: headRot,
|
|
290
312
|
scaleX: flipHead ? -1 : 1,
|
|
291
313
|
scaleY: 1
|
|
@@ -323,12 +345,12 @@ export class CharacterRigRenderer {
|
|
|
323
345
|
// Left Iris
|
|
324
346
|
const leftIrisImagePath = eyes?.leftIris;
|
|
325
347
|
const leftIrisImage = getImage(leftIrisImagePath);
|
|
326
|
-
if (
|
|
348
|
+
if (visibility.leftIris !== false && leftIrisImage && eyes) {
|
|
327
349
|
const headPivot = pivotPoints['torso_head'] || { x: 0, y: 0 };
|
|
328
350
|
const headRot = rotations["head"] || 0;
|
|
329
|
-
const headBaseTransform = this.applyTransform(
|
|
330
|
-
x: headPivot.x || 0,
|
|
331
|
-
y: headPivot.y || 0,
|
|
351
|
+
const headBaseTransform = this.applyTransform(torsoTransform, {
|
|
352
|
+
x: (headPivot.x || 0) - (root_torso.x || 0),
|
|
353
|
+
y: (headPivot.y || 0) - (root_torso.y || 0),
|
|
332
354
|
rotation: headRot,
|
|
333
355
|
scaleX: flipHead ? -1 : 1,
|
|
334
356
|
scaleY: 1
|
|
@@ -368,12 +390,12 @@ export class CharacterRigRenderer {
|
|
|
368
390
|
// Right Iris
|
|
369
391
|
const rightIrisImagePath = eyes?.rightIris;
|
|
370
392
|
const rightIrisImage = getImage(rightIrisImagePath);
|
|
371
|
-
if (
|
|
393
|
+
if (visibility.rightIris !== false && rightIrisImage && eyes) {
|
|
372
394
|
const headPivot = pivotPoints['torso_head'] || { x: 0, y: 0 };
|
|
373
395
|
const headRot = rotations["head"] || 0;
|
|
374
|
-
const headBaseTransform = this.applyTransform(
|
|
375
|
-
x: headPivot.x || 0,
|
|
376
|
-
y: headPivot.y || 0,
|
|
396
|
+
const headBaseTransform = this.applyTransform(torsoTransform, {
|
|
397
|
+
x: (headPivot.x || 0) - (root_torso.x || 0),
|
|
398
|
+
y: (headPivot.y || 0) - (root_torso.y || 0),
|
|
377
399
|
rotation: headRot,
|
|
378
400
|
scaleX: flipHead ? -1 : 1,
|
|
379
401
|
scaleY: 1
|
|
@@ -429,12 +451,12 @@ export class CharacterRigRenderer {
|
|
|
429
451
|
getImage(eyes?.leftEyeLidHalfClosed) ||
|
|
430
452
|
getImage(eyes?.leftEyeLidClosed);
|
|
431
453
|
}
|
|
432
|
-
if (
|
|
454
|
+
if (visibility.leftEyeLid !== false && leftEyeLidImage && eyes) {
|
|
433
455
|
const headPivot = pivotPoints['torso_head'] || { x: 0, y: 0 };
|
|
434
456
|
const headRot = rotations["head"] || 0;
|
|
435
|
-
const headBaseTransform = this.applyTransform(
|
|
436
|
-
x: headPivot.x || 0,
|
|
437
|
-
y: headPivot.y || 0,
|
|
457
|
+
const headBaseTransform = this.applyTransform(torsoTransform, {
|
|
458
|
+
x: (headPivot.x || 0) - (root_torso.x || 0),
|
|
459
|
+
y: (headPivot.y || 0) - (root_torso.y || 0),
|
|
438
460
|
rotation: headRot,
|
|
439
461
|
scaleX: flipHead ? -1 : 1,
|
|
440
462
|
scaleY: 1
|
|
@@ -487,12 +509,12 @@ export class CharacterRigRenderer {
|
|
|
487
509
|
getImage(eyes?.rightEyeLidHalfClosed) ||
|
|
488
510
|
getImage(eyes?.rightEyeLidClosed);
|
|
489
511
|
}
|
|
490
|
-
if (
|
|
512
|
+
if (visibility.rightEyeLid !== false && rightEyeLidImage && eyes) {
|
|
491
513
|
const headPivot = pivotPoints['torso_head'] || { x: 0, y: 0 };
|
|
492
514
|
const headRot = rotations["head"] || 0;
|
|
493
|
-
const headBaseTransform = this.applyTransform(
|
|
494
|
-
x: headPivot.x || 0,
|
|
495
|
-
y: headPivot.y || 0,
|
|
515
|
+
const headBaseTransform = this.applyTransform(torsoTransform, {
|
|
516
|
+
x: (headPivot.x || 0) - (root_torso.x || 0),
|
|
517
|
+
y: (headPivot.y || 0) - (root_torso.y || 0),
|
|
496
518
|
rotation: headRot,
|
|
497
519
|
scaleX: flipHead ? -1 : 1,
|
|
498
520
|
scaleY: 1
|
|
@@ -529,7 +551,7 @@ export class CharacterRigRenderer {
|
|
|
529
551
|
}
|
|
530
552
|
// Left Arm chain (leftUpperArm, leftForearm, leftHand)
|
|
531
553
|
// Left Upper Arm
|
|
532
|
-
if (
|
|
554
|
+
if (visibility.leftUpperArm !== false) {
|
|
533
555
|
const connectionKey = `torso_leftUpperArm`;
|
|
534
556
|
const pivotPoint = pivotPoints[connectionKey] || { x: 0, y: 0 };
|
|
535
557
|
const jointOff = jointOffset[connectionKey] || { x: 0, y: 0 };
|
|
@@ -537,9 +559,9 @@ export class CharacterRigRenderer {
|
|
|
537
559
|
const height = dimensions.leftUpperArm?.height || 50;
|
|
538
560
|
const limbRot = rotations['leftUpperArm'] || 0;
|
|
539
561
|
const selfRot = selfRotations['leftUpperArm'] || 0;
|
|
540
|
-
const upperArmParentTransform = this.applyTransform(
|
|
541
|
-
x: pivotPoint.x || 0,
|
|
542
|
-
y: pivotPoint.y || 0,
|
|
562
|
+
const upperArmParentTransform = this.applyTransform(torsoTransform, {
|
|
563
|
+
x: (pivotPoint.x || 0) - (root_torso.x || 0),
|
|
564
|
+
y: (pivotPoint.y || 0) - (root_torso.y || 0),
|
|
543
565
|
rotation: limbRot,
|
|
544
566
|
scaleX: 1,
|
|
545
567
|
scaleY: 1
|
|
@@ -571,7 +593,7 @@ export class CharacterRigRenderer {
|
|
|
571
593
|
});
|
|
572
594
|
}
|
|
573
595
|
// Left Forearm
|
|
574
|
-
if (
|
|
596
|
+
if (visibility.leftForearm !== false) {
|
|
575
597
|
const upperConnectionKey = `torso_leftUpperArm`;
|
|
576
598
|
const upperPivot = pivotPoints[upperConnectionKey] || { x: 0, y: 0 };
|
|
577
599
|
const upperHeight = dimensions.leftUpperArm?.height || 50;
|
|
@@ -583,9 +605,9 @@ export class CharacterRigRenderer {
|
|
|
583
605
|
const height = dimensions.leftForearm?.height || 45;
|
|
584
606
|
const limbRot = rotations["leftForearm"] || 0;
|
|
585
607
|
const selfRot = selfRotations["leftForearm"] || 0;
|
|
586
|
-
const upperArmBase = this.applyTransform(
|
|
587
|
-
x: upperPivot.x || 0,
|
|
588
|
-
y: upperPivot.y || 0,
|
|
608
|
+
const upperArmBase = this.applyTransform(torsoTransform, {
|
|
609
|
+
x: (upperPivot.x || 0) - (root_torso.x || 0),
|
|
610
|
+
y: (upperPivot.y || 0) - (root_torso.y || 0),
|
|
589
611
|
rotation: upperRot,
|
|
590
612
|
scaleX: 1,
|
|
591
613
|
scaleY: 1
|
|
@@ -624,7 +646,7 @@ export class CharacterRigRenderer {
|
|
|
624
646
|
});
|
|
625
647
|
}
|
|
626
648
|
// Left Hand
|
|
627
|
-
if (
|
|
649
|
+
if (visibility.leftHand !== false) {
|
|
628
650
|
const upperConnectionKey = `torso_leftUpperArm`;
|
|
629
651
|
const upperPivot = pivotPoints[upperConnectionKey] || { x: 0, y: 0 };
|
|
630
652
|
const upperHeight = dimensions.leftUpperArm?.height || 50;
|
|
@@ -640,9 +662,9 @@ export class CharacterRigRenderer {
|
|
|
640
662
|
const height = dimensions.leftHand?.height || 30;
|
|
641
663
|
const handRot = rotations["leftHand"] || 0;
|
|
642
664
|
const selfRot = selfRotations["leftHand"] || 0;
|
|
643
|
-
const upperArmBase = this.applyTransform(
|
|
644
|
-
x: upperPivot.x || 0,
|
|
645
|
-
y: upperPivot.y || 0,
|
|
665
|
+
const upperArmBase = this.applyTransform(torsoTransform, {
|
|
666
|
+
x: (upperPivot.x || 0) - (root_torso.x || 0),
|
|
667
|
+
y: (upperPivot.y || 0) - (root_torso.y || 0),
|
|
646
668
|
rotation: upperRot,
|
|
647
669
|
scaleX: 1,
|
|
648
670
|
scaleY: 1
|
|
@@ -688,7 +710,7 @@ export class CharacterRigRenderer {
|
|
|
688
710
|
}
|
|
689
711
|
// Right Arm chain (rightUpperArm, rightForearm, rightHand)
|
|
690
712
|
// Right Upper Arm
|
|
691
|
-
if (
|
|
713
|
+
if (visibility.rightUpperArm !== false) {
|
|
692
714
|
const connectionKey = `torso_rightUpperArm`;
|
|
693
715
|
const pivotPoint = pivotPoints[connectionKey] || { x: 0, y: 0 };
|
|
694
716
|
const jointOff = jointOffset[connectionKey] || { x: 0, y: 0 };
|
|
@@ -696,9 +718,9 @@ export class CharacterRigRenderer {
|
|
|
696
718
|
const height = dimensions.rightUpperArm?.height || 50;
|
|
697
719
|
const limbRot = rotations['rightUpperArm'] || 0;
|
|
698
720
|
const selfRot = selfRotations['rightUpperArm'] || 0;
|
|
699
|
-
const upperArmParentTransform = this.applyTransform(
|
|
700
|
-
x: pivotPoint.x || 0,
|
|
701
|
-
y: pivotPoint.y || 0,
|
|
721
|
+
const upperArmParentTransform = this.applyTransform(torsoTransform, {
|
|
722
|
+
x: (pivotPoint.x || 0) - (root_torso.x || 0),
|
|
723
|
+
y: (pivotPoint.y || 0) - (root_torso.y || 0),
|
|
702
724
|
rotation: limbRot,
|
|
703
725
|
scaleX: 1,
|
|
704
726
|
scaleY: 1
|
|
@@ -730,7 +752,7 @@ export class CharacterRigRenderer {
|
|
|
730
752
|
});
|
|
731
753
|
}
|
|
732
754
|
// Right Forearm
|
|
733
|
-
if (
|
|
755
|
+
if (visibility.rightForearm !== false) {
|
|
734
756
|
const upperConnectionKey = `torso_rightUpperArm`;
|
|
735
757
|
const upperPivot = pivotPoints[upperConnectionKey] || { x: 0, y: 0 };
|
|
736
758
|
const upperHeight = dimensions.rightUpperArm?.height || 50;
|
|
@@ -742,9 +764,9 @@ export class CharacterRigRenderer {
|
|
|
742
764
|
const height = dimensions.rightForearm?.height || 45;
|
|
743
765
|
const limbRot = rotations["rightForearm"] || 0;
|
|
744
766
|
const selfRot = selfRotations["rightForearm"] || 0;
|
|
745
|
-
const upperArmBase = this.applyTransform(
|
|
746
|
-
x: upperPivot.x || 0,
|
|
747
|
-
y: upperPivot.y || 0,
|
|
767
|
+
const upperArmBase = this.applyTransform(torsoTransform, {
|
|
768
|
+
x: (upperPivot.x || 0) - (root_torso.x || 0),
|
|
769
|
+
y: (upperPivot.y || 0) - (root_torso.y || 0),
|
|
748
770
|
rotation: upperRot,
|
|
749
771
|
scaleX: 1,
|
|
750
772
|
scaleY: 1
|
|
@@ -783,7 +805,7 @@ export class CharacterRigRenderer {
|
|
|
783
805
|
});
|
|
784
806
|
}
|
|
785
807
|
// Right Hand
|
|
786
|
-
if (
|
|
808
|
+
if (visibility.rightHand !== false) {
|
|
787
809
|
const upperConnectionKey = `torso_rightUpperArm`;
|
|
788
810
|
const upperPivot = pivotPoints[upperConnectionKey] || { x: 0, y: 0 };
|
|
789
811
|
const upperHeight = dimensions.rightUpperArm?.height || 50;
|
|
@@ -799,9 +821,9 @@ export class CharacterRigRenderer {
|
|
|
799
821
|
const height = dimensions.rightHand?.height || 30;
|
|
800
822
|
const handRot = rotations["rightHand"] || 0;
|
|
801
823
|
const selfRot = selfRotations["rightHand"] || 0;
|
|
802
|
-
const upperArmBase = this.applyTransform(
|
|
803
|
-
x: upperPivot.x || 0,
|
|
804
|
-
y: upperPivot.y || 0,
|
|
824
|
+
const upperArmBase = this.applyTransform(torsoTransform, {
|
|
825
|
+
x: (upperPivot.x || 0) - (root_torso.x || 0),
|
|
826
|
+
y: (upperPivot.y || 0) - (root_torso.y || 0),
|
|
805
827
|
rotation: upperRot,
|
|
806
828
|
scaleX: 1,
|
|
807
829
|
scaleY: 1
|
|
@@ -847,7 +869,7 @@ export class CharacterRigRenderer {
|
|
|
847
869
|
}
|
|
848
870
|
// Left Leg chain (leftThigh, leftLeg)
|
|
849
871
|
// Left Thigh
|
|
850
|
-
if (
|
|
872
|
+
if (visibility.leftThigh !== false) {
|
|
851
873
|
const connectionKey = `torso_leftThigh`;
|
|
852
874
|
const pivotPoint = pivotPoints[connectionKey] || { x: 0, y: 0 };
|
|
853
875
|
const jointOff = jointOffset[connectionKey] || { x: 0, y: 0 };
|
|
@@ -889,7 +911,7 @@ export class CharacterRigRenderer {
|
|
|
889
911
|
});
|
|
890
912
|
}
|
|
891
913
|
// Left Leg
|
|
892
|
-
if (
|
|
914
|
+
if (visibility.leftLeg !== false) {
|
|
893
915
|
const upperConnectionKey = `torso_leftThigh`;
|
|
894
916
|
const upperPivot = pivotPoints[upperConnectionKey] || { x: 0, y: 0 };
|
|
895
917
|
const upperHeight = dimensions.leftThigh?.height || 60;
|
|
@@ -942,7 +964,7 @@ export class CharacterRigRenderer {
|
|
|
942
964
|
}
|
|
943
965
|
// Right Leg chain (rightThigh, rightLeg)
|
|
944
966
|
// Right Thigh
|
|
945
|
-
if (
|
|
967
|
+
if (visibility.rightThigh !== false) {
|
|
946
968
|
const connectionKey = `torso_rightThigh`;
|
|
947
969
|
const pivotPoint = pivotPoints[connectionKey] || { x: 0, y: 0 };
|
|
948
970
|
const jointOff = jointOffset[connectionKey] || { x: 0, y: 0 };
|
|
@@ -984,7 +1006,7 @@ export class CharacterRigRenderer {
|
|
|
984
1006
|
});
|
|
985
1007
|
}
|
|
986
1008
|
// Right Leg
|
|
987
|
-
if (
|
|
1009
|
+
if (visibility.rightLeg !== false) {
|
|
988
1010
|
const upperConnectionKey = `torso_rightThigh`;
|
|
989
1011
|
const upperPivot = pivotPoints[upperConnectionKey] || { x: 0, y: 0 };
|
|
990
1012
|
const upperHeight = dimensions.rightThigh?.height || 60;
|
|
@@ -1037,58 +1059,49 @@ export class CharacterRigRenderer {
|
|
|
1037
1059
|
}
|
|
1038
1060
|
// Sort all objects by zIndex
|
|
1039
1061
|
allObjects.sort((a, b) => a.zIndex - b.zIndex);
|
|
1040
|
-
// Compute pivot points in world space
|
|
1062
|
+
// Compute pivot points in world space.
|
|
1063
|
+
// All torso-attached joints are resolved via torsoTransform so they correctly
|
|
1064
|
+
// follow any torso rotation applied around root_torso.
|
|
1041
1065
|
const computedPivotPoints = [];
|
|
1042
|
-
//
|
|
1043
|
-
const
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
rotation: 0,
|
|
1066
|
+
// Helper: convert a root-space pivot offset to torso-local space, then to world.
|
|
1067
|
+
const torsoLocalPivot = (px, py, rot) => this.applyTransform(torsoTransform, {
|
|
1068
|
+
x: px - (root_torso.x || 0),
|
|
1069
|
+
y: py - (root_torso.y || 0),
|
|
1070
|
+
rotation: rot,
|
|
1048
1071
|
scaleX: 1,
|
|
1049
1072
|
scaleY: 1
|
|
1050
1073
|
});
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1074
|
+
// root_torso pivot (the torso rotation origin in world space)
|
|
1075
|
+
computedPivotPoints.push({ name: 'root_torso', x: torsoTransform.x, y: torsoTransform.y });
|
|
1076
|
+
// Head/torso pivot
|
|
1077
|
+
const torsoHead = pivotPoints['torso_head'] || { x: 0, y: 0 };
|
|
1078
|
+
const headPivotWorld = torsoLocalPivot(torsoHead.x || 0, torsoHead.y || 0, 0);
|
|
1079
|
+
computedPivotPoints.push({ name: 'torso_head', x: headPivotWorld.x, y: headPivotWorld.y });
|
|
1080
|
+
// Mouth pivot — child of head, uses applyTransform chain for correctness
|
|
1057
1081
|
const headAngle = rotations['head'] || 0;
|
|
1058
|
-
const headAngleEff = flipHead ? -headAngle : headAngle;
|
|
1059
|
-
const headOffX = 0; // head offset defaults to 0
|
|
1060
|
-
const headOffY = 0; // head offset defaults to 0
|
|
1061
|
-
const headOffEffX = flipHead ? -headOffX : headOffX;
|
|
1062
|
-
const cosH = Math.cos(headAngleEff);
|
|
1063
|
-
const sinH = Math.sin(headAngleEff);
|
|
1064
1082
|
const mouthOffset = pivotPoints['head_mouth'] || { x: 0, y: 0 };
|
|
1065
|
-
const
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
const lShoulderWorld = this.applyTransform(rootTransform, {
|
|
1075
|
-
x: lShoulder.x || 0,
|
|
1076
|
-
y: lShoulder.y || 0,
|
|
1083
|
+
const mouthHeadBase = torsoLocalPivot(torsoHead.x || 0, torsoHead.y || 0, headAngle);
|
|
1084
|
+
// Apply flipHead mirror to the head base before computing mouth
|
|
1085
|
+
const mouthHeadBaseFlipped = {
|
|
1086
|
+
...mouthHeadBase,
|
|
1087
|
+
scaleX: mouthHeadBase.scaleX * (flipHead ? -1 : 1)
|
|
1088
|
+
};
|
|
1089
|
+
const mouthPivotWorld = this.applyTransform(mouthHeadBaseFlipped, {
|
|
1090
|
+
x: mouthOffset.x || 0,
|
|
1091
|
+
y: mouthOffset.y || 0,
|
|
1077
1092
|
rotation: 0,
|
|
1078
1093
|
scaleX: 1,
|
|
1079
1094
|
scaleY: 1
|
|
1080
1095
|
});
|
|
1096
|
+
computedPivotPoints.push({ name: 'head_mouth', x: mouthPivotWorld.x, y: mouthPivotWorld.y });
|
|
1097
|
+
// Left arm chain pivots
|
|
1098
|
+
const lShoulder = pivotPoints['torso_leftUpperArm'] || { x: 0, y: 0 };
|
|
1099
|
+
const lShoulderWorld = torsoLocalPivot(lShoulder.x || 0, lShoulder.y || 0, 0);
|
|
1081
1100
|
computedPivotPoints.push({ name: 'torso_leftUpperArm', x: lShoulderWorld.x, y: lShoulderWorld.y });
|
|
1082
1101
|
const rL1 = rotations['leftUpperArm'] || 0;
|
|
1083
1102
|
const leftUpperArmHeight = dimensions.leftUpperArm?.height || 50;
|
|
1084
1103
|
const lElbowOff = pivotPoints['leftUpperArm_leftForearm'] || { x: 0, y: 0 };
|
|
1085
|
-
const lElbowBase =
|
|
1086
|
-
x: lShoulder.x || 0,
|
|
1087
|
-
y: lShoulder.y || 0,
|
|
1088
|
-
rotation: rL1,
|
|
1089
|
-
scaleX: 1,
|
|
1090
|
-
scaleY: 1
|
|
1091
|
-
});
|
|
1104
|
+
const lElbowBase = torsoLocalPivot(lShoulder.x || 0, lShoulder.y || 0, rL1);
|
|
1092
1105
|
const lElbowWorld = this.applyTransform(lElbowBase, {
|
|
1093
1106
|
x: lElbowOff.x || 0,
|
|
1094
1107
|
y: (lElbowOff.y || 0) - leftUpperArmHeight,
|
|
@@ -1116,24 +1129,12 @@ export class CharacterRigRenderer {
|
|
|
1116
1129
|
computedPivotPoints.push({ name: 'leftForearm_leftHand', x: lWristWorld.x, y: lWristWorld.y });
|
|
1117
1130
|
// Right arm chain pivots
|
|
1118
1131
|
const rShoulder = pivotPoints['torso_rightUpperArm'] || { x: 0, y: 0 };
|
|
1119
|
-
const rShoulderWorld =
|
|
1120
|
-
x: rShoulder.x || 0,
|
|
1121
|
-
y: rShoulder.y || 0,
|
|
1122
|
-
rotation: 0,
|
|
1123
|
-
scaleX: 1,
|
|
1124
|
-
scaleY: 1
|
|
1125
|
-
});
|
|
1132
|
+
const rShoulderWorld = torsoLocalPivot(rShoulder.x || 0, rShoulder.y || 0, 0);
|
|
1126
1133
|
computedPivotPoints.push({ name: 'torso_rightUpperArm', x: rShoulderWorld.x, y: rShoulderWorld.y });
|
|
1127
1134
|
const rR1 = rotations['rightUpperArm'] || 0;
|
|
1128
1135
|
const rightUpperArmHeight = dimensions.rightUpperArm?.height || 50;
|
|
1129
1136
|
const rElbowOff = pivotPoints['rightUpperArm_rightForearm'] || { x: 0, y: 0 };
|
|
1130
|
-
const rElbowBase =
|
|
1131
|
-
x: rShoulder.x || 0,
|
|
1132
|
-
y: rShoulder.y || 0,
|
|
1133
|
-
rotation: rR1,
|
|
1134
|
-
scaleX: 1,
|
|
1135
|
-
scaleY: 1
|
|
1136
|
-
});
|
|
1137
|
+
const rElbowBase = torsoLocalPivot(rShoulder.x || 0, rShoulder.y || 0, rR1);
|
|
1137
1138
|
const rElbowWorld = this.applyTransform(rElbowBase, {
|
|
1138
1139
|
x: rElbowOff.x || 0,
|
|
1139
1140
|
y: (rElbowOff.y || 0) - rightUpperArmHeight,
|
|
@@ -1159,25 +1160,17 @@ export class CharacterRigRenderer {
|
|
|
1159
1160
|
scaleY: 1
|
|
1160
1161
|
});
|
|
1161
1162
|
computedPivotPoints.push({ name: 'rightForearm_rightHand', x: rWristWorld.x, y: rWristWorld.y });
|
|
1162
|
-
// Left leg chain pivots
|
|
1163
|
+
// Left leg chain pivots — legs are rooted to rootTransform, not torsoTransform
|
|
1163
1164
|
const lHip = pivotPoints['torso_leftThigh'] || { x: 0, y: 0 };
|
|
1164
1165
|
const lHipWorld = this.applyTransform(rootTransform, {
|
|
1165
|
-
x: lHip.x || 0,
|
|
1166
|
-
y: lHip.y || 0,
|
|
1167
|
-
rotation: 0,
|
|
1168
|
-
scaleX: 1,
|
|
1169
|
-
scaleY: 1
|
|
1166
|
+
x: lHip.x || 0, y: lHip.y || 0, rotation: 0, scaleX: 1, scaleY: 1
|
|
1170
1167
|
});
|
|
1171
1168
|
computedPivotPoints.push({ name: 'torso_leftThigh', x: lHipWorld.x, y: lHipWorld.y });
|
|
1172
1169
|
const rLT1 = rotations['leftThigh'] || 0;
|
|
1173
1170
|
const leftThighHeight = dimensions.leftThigh?.height || 60;
|
|
1174
1171
|
const lKneeOff = pivotPoints['leftThigh_leftLeg'] || { x: 0, y: 0 };
|
|
1175
1172
|
const lThighBase = this.applyTransform(rootTransform, {
|
|
1176
|
-
x: lHip.x || 0,
|
|
1177
|
-
y: lHip.y || 0,
|
|
1178
|
-
rotation: rLT1,
|
|
1179
|
-
scaleX: 1,
|
|
1180
|
-
scaleY: 1
|
|
1173
|
+
x: lHip.x || 0, y: lHip.y || 0, rotation: rLT1, scaleX: 1, scaleY: 1
|
|
1181
1174
|
});
|
|
1182
1175
|
const lKneeWorld = this.applyTransform(lThighBase, {
|
|
1183
1176
|
x: lKneeOff.x || 0,
|
|
@@ -1187,25 +1180,17 @@ export class CharacterRigRenderer {
|
|
|
1187
1180
|
scaleY: 1
|
|
1188
1181
|
});
|
|
1189
1182
|
computedPivotPoints.push({ name: 'leftThigh_leftLeg', x: lKneeWorld.x, y: lKneeWorld.y });
|
|
1190
|
-
// Right leg chain pivots
|
|
1183
|
+
// Right leg chain pivots — legs are rooted to rootTransform, not torsoTransform
|
|
1191
1184
|
const rHip = pivotPoints['torso_rightThigh'] || { x: 0, y: 0 };
|
|
1192
1185
|
const rHipWorld = this.applyTransform(rootTransform, {
|
|
1193
|
-
x: rHip.x || 0,
|
|
1194
|
-
y: rHip.y || 0,
|
|
1195
|
-
rotation: 0,
|
|
1196
|
-
scaleX: 1,
|
|
1197
|
-
scaleY: 1
|
|
1186
|
+
x: rHip.x || 0, y: rHip.y || 0, rotation: 0, scaleX: 1, scaleY: 1
|
|
1198
1187
|
});
|
|
1199
1188
|
computedPivotPoints.push({ name: 'torso_rightThigh', x: rHipWorld.x, y: rHipWorld.y });
|
|
1200
1189
|
const rRT1 = rotations['rightThigh'] || 0;
|
|
1201
1190
|
const rightThighHeight = dimensions.rightThigh?.height || 60;
|
|
1202
1191
|
const rKneeOff = pivotPoints['rightThigh_rightLeg'] || { x: 0, y: 0 };
|
|
1203
1192
|
const rThighBase = this.applyTransform(rootTransform, {
|
|
1204
|
-
x: rHip.x || 0,
|
|
1205
|
-
y: rHip.y || 0,
|
|
1206
|
-
rotation: rRT1,
|
|
1207
|
-
scaleX: 1,
|
|
1208
|
-
scaleY: 1
|
|
1193
|
+
x: rHip.x || 0, y: rHip.y || 0, rotation: rRT1, scaleX: 1, scaleY: 1
|
|
1209
1194
|
});
|
|
1210
1195
|
const rKneeWorld = this.applyTransform(rThighBase, {
|
|
1211
1196
|
x: rKneeOff.x || 0,
|