distark-render 1.1.4 → 1.1.6
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/tank.json +0 -0
- package/dist/cli/animate.d.ts +0 -0
- package/dist/cli/animate.d.ts.map +0 -0
- package/dist/cli/animate.js +0 -0
- package/dist/cli/animate.js.map +0 -0
- 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 +14 -14
- package/dist/cli/distark-check.js.map +0 -0
- 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/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 +0 -0
- package/dist/cli/verify.js.map +0 -0
- 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 +0 -0
- package/dist/modules/animationDiff.js.map +0 -0
- 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 +110 -124
- package/dist/modules/renderRig.js.map +1 -1
- 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 +0 -0
- package/dist/tests/test-animation-diff.js.map +0 -0
- 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-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 +0 -0
- package/dist/types.d.ts.map +0 -0
- package/dist/types.js +0 -0
- package/dist/types.js.map +0 -0
- package/package.json +2 -1
- package/assets/presets/jumping-jack.json +0 -194
package/README.md
CHANGED
|
File without changes
|
package/assets/tank.json
CHANGED
|
File without changes
|
package/dist/cli/animate.d.ts
CHANGED
|
File without changes
|
|
File without changes
|
package/dist/cli/animate.js
CHANGED
|
File without changes
|
package/dist/cli/animate.js.map
CHANGED
|
File without changes
|
package/dist/cli/diff.d.ts
CHANGED
|
File without changes
|
package/dist/cli/diff.d.ts.map
CHANGED
|
File without changes
|
package/dist/cli/diff.js
CHANGED
|
File without changes
|
package/dist/cli/diff.js.map
CHANGED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
@@ -16,20 +16,20 @@ import { runDiff } from './diff.js';
|
|
|
16
16
|
import { runQuery } from './query.js';
|
|
17
17
|
import { runRecord } from './record.js';
|
|
18
18
|
import { runTest } from './test.js';
|
|
19
|
-
const USAGE = `distark-check - CLI tool for LLM-driven rig testing
|
|
20
|
-
|
|
21
|
-
Commands:
|
|
22
|
-
render <rig.json> [-o out.png] [--width N] [--height N] [--report]
|
|
23
|
-
verify <rig.json> [--checks all|bounds,visibility,proportions,zorder]
|
|
24
|
-
animate <rig.json> <animation.json> [-o frames/] [--width N] [--height N]
|
|
25
|
-
diff <before.png> <after.png> [-o diff.png] [--threshold N]
|
|
26
|
-
query <image.png|rig.json> --prompt "..." [-o report.json]
|
|
27
|
-
test <rig.json|image|video> --prompt "..." [--tries N] [-o report.json]
|
|
28
|
-
record <world.json> [--orc URL] [-o out.mp4] [--timeout 300]
|
|
29
|
-
|
|
30
|
-
Environment:
|
|
31
|
-
GEMINI_API_KEY Required for 'query' and 'test' commands
|
|
32
|
-
ORC_URL Orchestrator URL for 'record' command (default: https://orchestrator.distark.com)
|
|
19
|
+
const USAGE = `distark-check - CLI tool for LLM-driven rig testing
|
|
20
|
+
|
|
21
|
+
Commands:
|
|
22
|
+
render <rig.json> [-o out.png] [--width N] [--height N] [--report]
|
|
23
|
+
verify <rig.json> [--checks all|bounds,visibility,proportions,zorder]
|
|
24
|
+
animate <rig.json> <animation.json> [-o frames/] [--width N] [--height N]
|
|
25
|
+
diff <before.png> <after.png> [-o diff.png] [--threshold N]
|
|
26
|
+
query <image.png|rig.json> --prompt "..." [-o report.json]
|
|
27
|
+
test <rig.json|image|video> --prompt "..." [--tries N] [-o report.json]
|
|
28
|
+
record <world.json> [--orc URL] [-o out.mp4] [--timeout 300]
|
|
29
|
+
|
|
30
|
+
Environment:
|
|
31
|
+
GEMINI_API_KEY Required for 'query' and 'test' commands
|
|
32
|
+
ORC_URL Orchestrator URL for 'record' command (default: https://orchestrator.distark.com)
|
|
33
33
|
`;
|
|
34
34
|
async function main() {
|
|
35
35
|
const args = process.argv.slice(2);
|
|
File without changes
|
package/dist/cli/query.d.ts
CHANGED
|
File without changes
|
package/dist/cli/query.d.ts.map
CHANGED
|
File without changes
|
package/dist/cli/query.js
CHANGED
|
File without changes
|
package/dist/cli/query.js.map
CHANGED
|
File without changes
|
package/dist/cli/record.d.ts
CHANGED
|
File without changes
|
package/dist/cli/record.d.ts.map
CHANGED
|
File without changes
|
package/dist/cli/record.js
CHANGED
|
File without changes
|
package/dist/cli/record.js.map
CHANGED
|
File without changes
|
package/dist/cli/render.d.ts
CHANGED
|
File without changes
|
package/dist/cli/render.d.ts.map
CHANGED
|
File without changes
|
package/dist/cli/render.js
CHANGED
|
File without changes
|
package/dist/cli/render.js.map
CHANGED
|
File without changes
|
package/dist/cli/shared.d.ts
CHANGED
|
File without changes
|
package/dist/cli/shared.d.ts.map
CHANGED
|
File without changes
|
package/dist/cli/shared.js
CHANGED
|
File without changes
|
package/dist/cli/shared.js.map
CHANGED
|
File without changes
|
package/dist/cli/test.d.ts
CHANGED
|
File without changes
|
package/dist/cli/test.d.ts.map
CHANGED
|
File without changes
|
package/dist/cli/test.js
CHANGED
|
File without changes
|
package/dist/cli/test.js.map
CHANGED
|
File without changes
|
package/dist/cli/verify.d.ts
CHANGED
|
File without changes
|
package/dist/cli/verify.d.ts.map
CHANGED
|
File without changes
|
package/dist/cli/verify.js
CHANGED
|
File without changes
|
package/dist/cli/verify.js.map
CHANGED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"renderRig.d.ts","sourceRoot":"","sources":["../../modules/renderRig.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAG7C,OAAO,KAAK,EACR,OAAO,EACP,aAAa,EACb,aAAa,EAGb,QAAQ,EACR,aAAa,EAChB,MAAM,aAAa,CAAC;AAErB;;GAEG;AACH,qBAAa,oBAAoB;IAC7B,SAAS,CAAC,WAAW,EAAE,WAAW,CAAC;IAEnC;;;OAGG;gBACS,WAAW,CAAC,EAAE,WAAW;IAIrC;;;OAGG;IACH,cAAc,IAAI,WAAW;IAI7B;;OAEG;IACH,OAAO,CAAC,cAAc;IAYtB;;OAEG;IACH,uBAAuB,CACnB,OAAO,EAAE,OAAO,EAChB,OAAO,GAAE,aAAkB,GAC5B,aAAa;
|
|
1
|
+
{"version":3,"file":"renderRig.d.ts","sourceRoot":"","sources":["../../modules/renderRig.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAG7C,OAAO,KAAK,EACR,OAAO,EACP,aAAa,EACb,aAAa,EAGb,QAAQ,EACR,aAAa,EAChB,MAAM,aAAa,CAAC;AAErB;;GAEG;AACH,qBAAa,oBAAoB;IAC7B,SAAS,CAAC,WAAW,EAAE,WAAW,CAAC;IAEnC;;;OAGG;gBACS,WAAW,CAAC,EAAE,WAAW;IAIrC;;;OAGG;IACH,cAAc,IAAI,WAAW;IAI7B;;OAEG;IACH,OAAO,CAAC,cAAc;IAYtB;;OAEG;IACH,uBAAuB,CACnB,OAAO,EAAE,OAAO,EAChB,OAAO,GAAE,aAAkB,GAC5B,aAAa;IA+xChB;;;;OAIG;IACH,cAAc,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,GAAE,OAAO,CAAC,aAAa,CAAM,EAAE,OAAO,SAAK,GAAG,aAAa;IA6DnG;;;;;;;;;;;;;;;;;OAiBG;IACG,MAAM,CACR,MAAM,EAAE,iBAAiB,EACzB,OAAO,EAAE,OAAO,EAChB,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,gBAAgB,GAAG,iBAAiB,CAAC,EACnE,YAAY,GAAE,QAAyB,EACvC,eAAe,GAAE,OAAc,EAC/B,OAAO,CAAC,EAAE;QAAE,OAAO,CAAC,EAAE,OAAO,CAAA;KAAE,GAChC,OAAO,CAAC,IAAI,CAAC;CA8FnB;AAGD,eAAO,MAAM,eAAe,sBAA6B,CAAC;AAG1D,wBAAsB,kBAAkB,CACpC,MAAM,EAAE,iBAAiB,EACzB,OAAO,EAAE,OAAO,EAChB,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,gBAAgB,GAAG,iBAAiB,CAAC,EACnE,YAAY,GAAE,QAAyB,EACvC,eAAe,GAAE,OAAe,EAChC,OAAO,CAAC,EAAE;IAAE,OAAO,CAAC,EAAE,OAAO,CAAA;CAAE,GAChC,OAAO,CAAC,IAAI,CAAC,CAEf;AAGD,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,GAAE,aAAkB,GAAG,aAAa,CAEpG"}
|
|
@@ -72,6 +72,19 @@ export class CharacterRigRenderer {
|
|
|
72
72
|
scaleX: flipX ? -1 : 1,
|
|
73
73
|
scaleY: 1
|
|
74
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
|
+
});
|
|
75
88
|
// Torso
|
|
76
89
|
if (visibility.torso !== false) {
|
|
77
90
|
const torsoWidth = dimensions.torso?.width || 60;
|
|
@@ -80,20 +93,30 @@ export class CharacterRigRenderer {
|
|
|
80
93
|
// CRITICAL FIX: Look up image by ACTUAL PATH from rigData, not semantic key!
|
|
81
94
|
const torsoImagePath = rigData.imagePaths?.torso;
|
|
82
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
|
+
});
|
|
83
107
|
allObjects.push({
|
|
84
108
|
name: 'torso',
|
|
85
109
|
type: 'limb',
|
|
86
110
|
zIndex: zIndexValues['torso'] || 1,
|
|
87
111
|
width: torsoWidth * imageScale,
|
|
88
112
|
height: torsoHeight * imageScale,
|
|
89
|
-
x:
|
|
90
|
-
y:
|
|
91
|
-
rotation:
|
|
92
|
-
scaleX:
|
|
93
|
-
scaleY:
|
|
94
|
-
// 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,
|
|
95
118
|
anchorX: 0.5,
|
|
96
|
-
anchorY: 1,
|
|
119
|
+
anchorY: 1, // bottom-center sits at root_torso world position
|
|
97
120
|
imageKey: 'imagePaths.torso',
|
|
98
121
|
imageData: torsoImage,
|
|
99
122
|
selfRotation: selfRot
|
|
@@ -108,10 +131,10 @@ export class CharacterRigRenderer {
|
|
|
108
131
|
const headHeight = dimensions.head?.height || 80;
|
|
109
132
|
const headRot = rotations["head"] || 0;
|
|
110
133
|
const selfRot = selfRotations["head"] || 0;
|
|
111
|
-
// Calculate head transform
|
|
112
|
-
const headParentTransform = this.applyTransform(
|
|
113
|
-
x: pivotPoint.x || 0,
|
|
114
|
-
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),
|
|
115
138
|
rotation: headRot,
|
|
116
139
|
scaleX: flipHead ? -1 : 1,
|
|
117
140
|
scaleY: 1
|
|
@@ -182,9 +205,9 @@ export class CharacterRigRenderer {
|
|
|
182
205
|
// Calculate final dimensions with size scaling
|
|
183
206
|
const finalMouthWidth = baseMouthWidth * mouthSizeScale;
|
|
184
207
|
const finalMouthHeight = baseMouthHeight * mouthSizeScale;
|
|
185
|
-
const headBaseTransform = this.applyTransform(
|
|
186
|
-
x: headPivot.x || 0,
|
|
187
|
-
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),
|
|
188
211
|
rotation: headRot,
|
|
189
212
|
scaleX: flipHead ? -1 : 1,
|
|
190
213
|
scaleY: 1
|
|
@@ -239,9 +262,9 @@ export class CharacterRigRenderer {
|
|
|
239
262
|
if (visibility.leftEye !== false && leftEyeImage && eyes) {
|
|
240
263
|
const headPivot = pivotPoints['torso_head'] || { x: 0, y: 0 };
|
|
241
264
|
const headRot = rotations["head"] || 0;
|
|
242
|
-
const headBaseTransform = this.applyTransform(
|
|
243
|
-
x: headPivot.x || 0,
|
|
244
|
-
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),
|
|
245
268
|
rotation: headRot,
|
|
246
269
|
scaleX: flipHead ? -1 : 1,
|
|
247
270
|
scaleY: 1
|
|
@@ -282,9 +305,9 @@ export class CharacterRigRenderer {
|
|
|
282
305
|
if (visibility.rightEye !== false && rightEyeImage && eyes) {
|
|
283
306
|
const headPivot = pivotPoints['torso_head'] || { x: 0, y: 0 };
|
|
284
307
|
const headRot = rotations["head"] || 0;
|
|
285
|
-
const headBaseTransform = this.applyTransform(
|
|
286
|
-
x: headPivot.x || 0,
|
|
287
|
-
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),
|
|
288
311
|
rotation: headRot,
|
|
289
312
|
scaleX: flipHead ? -1 : 1,
|
|
290
313
|
scaleY: 1
|
|
@@ -325,9 +348,9 @@ export class CharacterRigRenderer {
|
|
|
325
348
|
if (visibility.leftIris !== false && leftIrisImage && eyes) {
|
|
326
349
|
const headPivot = pivotPoints['torso_head'] || { x: 0, y: 0 };
|
|
327
350
|
const headRot = rotations["head"] || 0;
|
|
328
|
-
const headBaseTransform = this.applyTransform(
|
|
329
|
-
x: headPivot.x || 0,
|
|
330
|
-
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),
|
|
331
354
|
rotation: headRot,
|
|
332
355
|
scaleX: flipHead ? -1 : 1,
|
|
333
356
|
scaleY: 1
|
|
@@ -370,9 +393,9 @@ export class CharacterRigRenderer {
|
|
|
370
393
|
if (visibility.rightIris !== false && rightIrisImage && eyes) {
|
|
371
394
|
const headPivot = pivotPoints['torso_head'] || { x: 0, y: 0 };
|
|
372
395
|
const headRot = rotations["head"] || 0;
|
|
373
|
-
const headBaseTransform = this.applyTransform(
|
|
374
|
-
x: headPivot.x || 0,
|
|
375
|
-
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),
|
|
376
399
|
rotation: headRot,
|
|
377
400
|
scaleX: flipHead ? -1 : 1,
|
|
378
401
|
scaleY: 1
|
|
@@ -431,9 +454,9 @@ export class CharacterRigRenderer {
|
|
|
431
454
|
if (visibility.leftEyeLid !== false && leftEyeLidImage && eyes) {
|
|
432
455
|
const headPivot = pivotPoints['torso_head'] || { x: 0, y: 0 };
|
|
433
456
|
const headRot = rotations["head"] || 0;
|
|
434
|
-
const headBaseTransform = this.applyTransform(
|
|
435
|
-
x: headPivot.x || 0,
|
|
436
|
-
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),
|
|
437
460
|
rotation: headRot,
|
|
438
461
|
scaleX: flipHead ? -1 : 1,
|
|
439
462
|
scaleY: 1
|
|
@@ -489,9 +512,9 @@ export class CharacterRigRenderer {
|
|
|
489
512
|
if (visibility.rightEyeLid !== false && rightEyeLidImage && eyes) {
|
|
490
513
|
const headPivot = pivotPoints['torso_head'] || { x: 0, y: 0 };
|
|
491
514
|
const headRot = rotations["head"] || 0;
|
|
492
|
-
const headBaseTransform = this.applyTransform(
|
|
493
|
-
x: headPivot.x || 0,
|
|
494
|
-
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),
|
|
495
518
|
rotation: headRot,
|
|
496
519
|
scaleX: flipHead ? -1 : 1,
|
|
497
520
|
scaleY: 1
|
|
@@ -536,9 +559,9 @@ export class CharacterRigRenderer {
|
|
|
536
559
|
const height = dimensions.leftUpperArm?.height || 50;
|
|
537
560
|
const limbRot = rotations['leftUpperArm'] || 0;
|
|
538
561
|
const selfRot = selfRotations['leftUpperArm'] || 0;
|
|
539
|
-
const upperArmParentTransform = this.applyTransform(
|
|
540
|
-
x: pivotPoint.x || 0,
|
|
541
|
-
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),
|
|
542
565
|
rotation: limbRot,
|
|
543
566
|
scaleX: 1,
|
|
544
567
|
scaleY: 1
|
|
@@ -582,9 +605,9 @@ export class CharacterRigRenderer {
|
|
|
582
605
|
const height = dimensions.leftForearm?.height || 45;
|
|
583
606
|
const limbRot = rotations["leftForearm"] || 0;
|
|
584
607
|
const selfRot = selfRotations["leftForearm"] || 0;
|
|
585
|
-
const upperArmBase = this.applyTransform(
|
|
586
|
-
x: upperPivot.x || 0,
|
|
587
|
-
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),
|
|
588
611
|
rotation: upperRot,
|
|
589
612
|
scaleX: 1,
|
|
590
613
|
scaleY: 1
|
|
@@ -639,9 +662,9 @@ export class CharacterRigRenderer {
|
|
|
639
662
|
const height = dimensions.leftHand?.height || 30;
|
|
640
663
|
const handRot = rotations["leftHand"] || 0;
|
|
641
664
|
const selfRot = selfRotations["leftHand"] || 0;
|
|
642
|
-
const upperArmBase = this.applyTransform(
|
|
643
|
-
x: upperPivot.x || 0,
|
|
644
|
-
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),
|
|
645
668
|
rotation: upperRot,
|
|
646
669
|
scaleX: 1,
|
|
647
670
|
scaleY: 1
|
|
@@ -695,9 +718,9 @@ export class CharacterRigRenderer {
|
|
|
695
718
|
const height = dimensions.rightUpperArm?.height || 50;
|
|
696
719
|
const limbRot = rotations['rightUpperArm'] || 0;
|
|
697
720
|
const selfRot = selfRotations['rightUpperArm'] || 0;
|
|
698
|
-
const upperArmParentTransform = this.applyTransform(
|
|
699
|
-
x: pivotPoint.x || 0,
|
|
700
|
-
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),
|
|
701
724
|
rotation: limbRot,
|
|
702
725
|
scaleX: 1,
|
|
703
726
|
scaleY: 1
|
|
@@ -741,9 +764,9 @@ export class CharacterRigRenderer {
|
|
|
741
764
|
const height = dimensions.rightForearm?.height || 45;
|
|
742
765
|
const limbRot = rotations["rightForearm"] || 0;
|
|
743
766
|
const selfRot = selfRotations["rightForearm"] || 0;
|
|
744
|
-
const upperArmBase = this.applyTransform(
|
|
745
|
-
x: upperPivot.x || 0,
|
|
746
|
-
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),
|
|
747
770
|
rotation: upperRot,
|
|
748
771
|
scaleX: 1,
|
|
749
772
|
scaleY: 1
|
|
@@ -798,9 +821,9 @@ export class CharacterRigRenderer {
|
|
|
798
821
|
const height = dimensions.rightHand?.height || 30;
|
|
799
822
|
const handRot = rotations["rightHand"] || 0;
|
|
800
823
|
const selfRot = selfRotations["rightHand"] || 0;
|
|
801
|
-
const upperArmBase = this.applyTransform(
|
|
802
|
-
x: upperPivot.x || 0,
|
|
803
|
-
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),
|
|
804
827
|
rotation: upperRot,
|
|
805
828
|
scaleX: 1,
|
|
806
829
|
scaleY: 1
|
|
@@ -1036,58 +1059,49 @@ export class CharacterRigRenderer {
|
|
|
1036
1059
|
}
|
|
1037
1060
|
// Sort all objects by zIndex
|
|
1038
1061
|
allObjects.sort((a, b) => a.zIndex - b.zIndex);
|
|
1039
|
-
// 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.
|
|
1040
1065
|
const computedPivotPoints = [];
|
|
1041
|
-
//
|
|
1042
|
-
const
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
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,
|
|
1047
1071
|
scaleX: 1,
|
|
1048
1072
|
scaleY: 1
|
|
1049
1073
|
});
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
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
|
|
1056
1081
|
const headAngle = rotations['head'] || 0;
|
|
1057
|
-
const headAngleEff = flipHead ? -headAngle : headAngle;
|
|
1058
|
-
const headOffX = 0; // head offset defaults to 0
|
|
1059
|
-
const headOffY = 0; // head offset defaults to 0
|
|
1060
|
-
const headOffEffX = flipHead ? -headOffX : headOffX;
|
|
1061
|
-
const cosH = Math.cos(headAngleEff);
|
|
1062
|
-
const sinH = Math.sin(headAngleEff);
|
|
1063
1082
|
const mouthOffset = pivotPoints['head_mouth'] || { x: 0, y: 0 };
|
|
1064
|
-
const
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
const lShoulderWorld = this.applyTransform(rootTransform, {
|
|
1074
|
-
x: lShoulder.x || 0,
|
|
1075
|
-
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,
|
|
1076
1092
|
rotation: 0,
|
|
1077
1093
|
scaleX: 1,
|
|
1078
1094
|
scaleY: 1
|
|
1079
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);
|
|
1080
1100
|
computedPivotPoints.push({ name: 'torso_leftUpperArm', x: lShoulderWorld.x, y: lShoulderWorld.y });
|
|
1081
1101
|
const rL1 = rotations['leftUpperArm'] || 0;
|
|
1082
1102
|
const leftUpperArmHeight = dimensions.leftUpperArm?.height || 50;
|
|
1083
1103
|
const lElbowOff = pivotPoints['leftUpperArm_leftForearm'] || { x: 0, y: 0 };
|
|
1084
|
-
const lElbowBase =
|
|
1085
|
-
x: lShoulder.x || 0,
|
|
1086
|
-
y: lShoulder.y || 0,
|
|
1087
|
-
rotation: rL1,
|
|
1088
|
-
scaleX: 1,
|
|
1089
|
-
scaleY: 1
|
|
1090
|
-
});
|
|
1104
|
+
const lElbowBase = torsoLocalPivot(lShoulder.x || 0, lShoulder.y || 0, rL1);
|
|
1091
1105
|
const lElbowWorld = this.applyTransform(lElbowBase, {
|
|
1092
1106
|
x: lElbowOff.x || 0,
|
|
1093
1107
|
y: (lElbowOff.y || 0) - leftUpperArmHeight,
|
|
@@ -1115,24 +1129,12 @@ export class CharacterRigRenderer {
|
|
|
1115
1129
|
computedPivotPoints.push({ name: 'leftForearm_leftHand', x: lWristWorld.x, y: lWristWorld.y });
|
|
1116
1130
|
// Right arm chain pivots
|
|
1117
1131
|
const rShoulder = pivotPoints['torso_rightUpperArm'] || { x: 0, y: 0 };
|
|
1118
|
-
const rShoulderWorld =
|
|
1119
|
-
x: rShoulder.x || 0,
|
|
1120
|
-
y: rShoulder.y || 0,
|
|
1121
|
-
rotation: 0,
|
|
1122
|
-
scaleX: 1,
|
|
1123
|
-
scaleY: 1
|
|
1124
|
-
});
|
|
1132
|
+
const rShoulderWorld = torsoLocalPivot(rShoulder.x || 0, rShoulder.y || 0, 0);
|
|
1125
1133
|
computedPivotPoints.push({ name: 'torso_rightUpperArm', x: rShoulderWorld.x, y: rShoulderWorld.y });
|
|
1126
1134
|
const rR1 = rotations['rightUpperArm'] || 0;
|
|
1127
1135
|
const rightUpperArmHeight = dimensions.rightUpperArm?.height || 50;
|
|
1128
1136
|
const rElbowOff = pivotPoints['rightUpperArm_rightForearm'] || { x: 0, y: 0 };
|
|
1129
|
-
const rElbowBase =
|
|
1130
|
-
x: rShoulder.x || 0,
|
|
1131
|
-
y: rShoulder.y || 0,
|
|
1132
|
-
rotation: rR1,
|
|
1133
|
-
scaleX: 1,
|
|
1134
|
-
scaleY: 1
|
|
1135
|
-
});
|
|
1137
|
+
const rElbowBase = torsoLocalPivot(rShoulder.x || 0, rShoulder.y || 0, rR1);
|
|
1136
1138
|
const rElbowWorld = this.applyTransform(rElbowBase, {
|
|
1137
1139
|
x: rElbowOff.x || 0,
|
|
1138
1140
|
y: (rElbowOff.y || 0) - rightUpperArmHeight,
|
|
@@ -1158,25 +1160,17 @@ export class CharacterRigRenderer {
|
|
|
1158
1160
|
scaleY: 1
|
|
1159
1161
|
});
|
|
1160
1162
|
computedPivotPoints.push({ name: 'rightForearm_rightHand', x: rWristWorld.x, y: rWristWorld.y });
|
|
1161
|
-
// Left leg chain pivots
|
|
1163
|
+
// Left leg chain pivots — legs are rooted to rootTransform, not torsoTransform
|
|
1162
1164
|
const lHip = pivotPoints['torso_leftThigh'] || { x: 0, y: 0 };
|
|
1163
1165
|
const lHipWorld = this.applyTransform(rootTransform, {
|
|
1164
|
-
x: lHip.x || 0,
|
|
1165
|
-
y: lHip.y || 0,
|
|
1166
|
-
rotation: 0,
|
|
1167
|
-
scaleX: 1,
|
|
1168
|
-
scaleY: 1
|
|
1166
|
+
x: lHip.x || 0, y: lHip.y || 0, rotation: 0, scaleX: 1, scaleY: 1
|
|
1169
1167
|
});
|
|
1170
1168
|
computedPivotPoints.push({ name: 'torso_leftThigh', x: lHipWorld.x, y: lHipWorld.y });
|
|
1171
1169
|
const rLT1 = rotations['leftThigh'] || 0;
|
|
1172
1170
|
const leftThighHeight = dimensions.leftThigh?.height || 60;
|
|
1173
1171
|
const lKneeOff = pivotPoints['leftThigh_leftLeg'] || { x: 0, y: 0 };
|
|
1174
1172
|
const lThighBase = this.applyTransform(rootTransform, {
|
|
1175
|
-
x: lHip.x || 0,
|
|
1176
|
-
y: lHip.y || 0,
|
|
1177
|
-
rotation: rLT1,
|
|
1178
|
-
scaleX: 1,
|
|
1179
|
-
scaleY: 1
|
|
1173
|
+
x: lHip.x || 0, y: lHip.y || 0, rotation: rLT1, scaleX: 1, scaleY: 1
|
|
1180
1174
|
});
|
|
1181
1175
|
const lKneeWorld = this.applyTransform(lThighBase, {
|
|
1182
1176
|
x: lKneeOff.x || 0,
|
|
@@ -1186,25 +1180,17 @@ export class CharacterRigRenderer {
|
|
|
1186
1180
|
scaleY: 1
|
|
1187
1181
|
});
|
|
1188
1182
|
computedPivotPoints.push({ name: 'leftThigh_leftLeg', x: lKneeWorld.x, y: lKneeWorld.y });
|
|
1189
|
-
// Right leg chain pivots
|
|
1183
|
+
// Right leg chain pivots — legs are rooted to rootTransform, not torsoTransform
|
|
1190
1184
|
const rHip = pivotPoints['torso_rightThigh'] || { x: 0, y: 0 };
|
|
1191
1185
|
const rHipWorld = this.applyTransform(rootTransform, {
|
|
1192
|
-
x: rHip.x || 0,
|
|
1193
|
-
y: rHip.y || 0,
|
|
1194
|
-
rotation: 0,
|
|
1195
|
-
scaleX: 1,
|
|
1196
|
-
scaleY: 1
|
|
1186
|
+
x: rHip.x || 0, y: rHip.y || 0, rotation: 0, scaleX: 1, scaleY: 1
|
|
1197
1187
|
});
|
|
1198
1188
|
computedPivotPoints.push({ name: 'torso_rightThigh', x: rHipWorld.x, y: rHipWorld.y });
|
|
1199
1189
|
const rRT1 = rotations['rightThigh'] || 0;
|
|
1200
1190
|
const rightThighHeight = dimensions.rightThigh?.height || 60;
|
|
1201
1191
|
const rKneeOff = pivotPoints['rightThigh_rightLeg'] || { x: 0, y: 0 };
|
|
1202
1192
|
const rThighBase = this.applyTransform(rootTransform, {
|
|
1203
|
-
x: rHip.x || 0,
|
|
1204
|
-
y: rHip.y || 0,
|
|
1205
|
-
rotation: rRT1,
|
|
1206
|
-
scaleX: 1,
|
|
1207
|
-
scaleY: 1
|
|
1193
|
+
x: rHip.x || 0, y: rHip.y || 0, rotation: rRT1, scaleX: 1, scaleY: 1
|
|
1208
1194
|
});
|
|
1209
1195
|
const rKneeWorld = this.applyTransform(rThighBase, {
|
|
1210
1196
|
x: rKneeOff.x || 0,
|