@energy8platform/golem 0.7.0 → 0.8.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/dist/editor.js +94 -40
- package/dist/lib/cli.js +124 -48
- package/dist/lib/cli.js.map +3 -3
- package/dist/lib/e8/agent.d.ts +1 -1
- package/dist/lib/e8-agent.js +133 -49
- package/dist/lib/e8-agent.js.map +3 -3
- package/dist/lib/e8-host.js +124 -48
- package/dist/lib/e8-host.js.map +3 -3
- package/dist/lib/e8-runtime.js +56 -1
- package/dist/lib/e8-runtime.js.map +3 -3
- package/dist/lib/editor/store.d.ts +32 -32
- package/dist/lib/editor-entry.js +124 -48
- package/dist/lib/editor-entry.js.map +3 -3
- package/dist/lib/harness.js +54 -1
- package/dist/lib/interactive-editor.js.map +1 -1
- package/dist/lib/rig-check.d.ts +11 -0
- package/dist/lib/rig-control-qa.d.ts +8 -8
- package/dist/lib/rig-format.d.ts +184 -184
- package/dist/lib/rig-symbol.d.ts +5 -2
- package/dist/lib/rig-tools.d.ts +2 -1
- package/dist/lib/runtime.js +60 -3
- package/dist/lib/runtime.js.map +3 -3
- package/dist/lib/tool-schema.d.ts +1 -1
- package/dist/lib/tools.js +131 -49
- package/dist/lib/tools.js.map +3 -3
- package/package.json +1 -1
- package/skills/e8-golem/SKILL.md +1 -1
- package/skills/golem-symbol-animation/references/motion-craft.md +5 -2
- package/skills/golem-symbol-animation/references/quantitative-qa.md +4 -1
|
@@ -192,7 +192,7 @@ export declare const doc: import("@preact/signals-core").Signal<{
|
|
|
192
192
|
id: string;
|
|
193
193
|
target: "control";
|
|
194
194
|
prop: "value";
|
|
195
|
-
interpolation?: "segment" | "pchip" | undefined;
|
|
195
|
+
interpolation?: "segment" | "pchip" | "spline" | undefined;
|
|
196
196
|
} | {
|
|
197
197
|
keys: {
|
|
198
198
|
t: number;
|
|
@@ -207,7 +207,7 @@ export declare const doc: import("@preact/signals-core").Signal<{
|
|
|
207
207
|
id: string;
|
|
208
208
|
target: "bone";
|
|
209
209
|
prop: "x" | "y" | "rotation" | "scaleX" | "scaleY" | "shearX" | "shearY";
|
|
210
|
-
interpolation?: "segment" | "pchip" | undefined;
|
|
210
|
+
interpolation?: "segment" | "pchip" | "spline" | undefined;
|
|
211
211
|
} | {
|
|
212
212
|
keys: {
|
|
213
213
|
t: number;
|
|
@@ -222,7 +222,7 @@ export declare const doc: import("@preact/signals-core").Signal<{
|
|
|
222
222
|
id: string;
|
|
223
223
|
target: "slot";
|
|
224
224
|
prop: "color" | "attachment" | "alpha" | "z";
|
|
225
|
-
interpolation?: "segment" | "pchip" | undefined;
|
|
225
|
+
interpolation?: "segment" | "pchip" | "spline" | undefined;
|
|
226
226
|
} | {
|
|
227
227
|
keys: {
|
|
228
228
|
t: number;
|
|
@@ -237,7 +237,7 @@ export declare const doc: import("@preact/signals-core").Signal<{
|
|
|
237
237
|
id: string;
|
|
238
238
|
target: "deform";
|
|
239
239
|
prop: string;
|
|
240
|
-
interpolation?: "segment" | "pchip" | undefined;
|
|
240
|
+
interpolation?: "segment" | "pchip" | "spline" | undefined;
|
|
241
241
|
} | {
|
|
242
242
|
keys: {
|
|
243
243
|
t: number;
|
|
@@ -252,7 +252,7 @@ export declare const doc: import("@preact/signals-core").Signal<{
|
|
|
252
252
|
id: string;
|
|
253
253
|
target: "ik";
|
|
254
254
|
prop: "mix" | "softness" | "bendPositive" | "compress" | "stretch";
|
|
255
|
-
interpolation?: "segment" | "pchip" | undefined;
|
|
255
|
+
interpolation?: "segment" | "pchip" | "spline" | undefined;
|
|
256
256
|
} | {
|
|
257
257
|
keys: {
|
|
258
258
|
t: number;
|
|
@@ -267,7 +267,7 @@ export declare const doc: import("@preact/signals-core").Signal<{
|
|
|
267
267
|
id: string;
|
|
268
268
|
target: "transform";
|
|
269
269
|
prop: "x" | "y" | "rotation" | "scaleX" | "scaleY" | "shearY" | "mixRotate" | "mixX" | "mixY" | "mixScaleX" | "mixScaleY" | "mixShearY";
|
|
270
|
-
interpolation?: "segment" | "pchip" | undefined;
|
|
270
|
+
interpolation?: "segment" | "pchip" | "spline" | undefined;
|
|
271
271
|
} | {
|
|
272
272
|
keys: {
|
|
273
273
|
t: number;
|
|
@@ -282,7 +282,7 @@ export declare const doc: import("@preact/signals-core").Signal<{
|
|
|
282
282
|
id: string;
|
|
283
283
|
target: "path";
|
|
284
284
|
prop: "mixRotate" | "mixX" | "mixY" | "position" | "spacing";
|
|
285
|
-
interpolation?: "segment" | "pchip" | undefined;
|
|
285
|
+
interpolation?: "segment" | "pchip" | "spline" | undefined;
|
|
286
286
|
} | {
|
|
287
287
|
keys: {
|
|
288
288
|
t: number;
|
|
@@ -297,7 +297,7 @@ export declare const doc: import("@preact/signals-core").Signal<{
|
|
|
297
297
|
id: string;
|
|
298
298
|
target: "drawOrder";
|
|
299
299
|
prop: "order";
|
|
300
|
-
interpolation?: "segment" | "pchip" | undefined;
|
|
300
|
+
interpolation?: "segment" | "pchip" | "spline" | undefined;
|
|
301
301
|
})[];
|
|
302
302
|
events: {
|
|
303
303
|
t: number;
|
|
@@ -513,7 +513,7 @@ export declare const draft: import("@preact/signals-core").Signal<{
|
|
|
513
513
|
id: string;
|
|
514
514
|
target: "control";
|
|
515
515
|
prop: "value";
|
|
516
|
-
interpolation?: "segment" | "pchip" | undefined;
|
|
516
|
+
interpolation?: "segment" | "pchip" | "spline" | undefined;
|
|
517
517
|
} | {
|
|
518
518
|
keys: {
|
|
519
519
|
t: number;
|
|
@@ -528,7 +528,7 @@ export declare const draft: import("@preact/signals-core").Signal<{
|
|
|
528
528
|
id: string;
|
|
529
529
|
target: "bone";
|
|
530
530
|
prop: "x" | "y" | "rotation" | "scaleX" | "scaleY" | "shearX" | "shearY";
|
|
531
|
-
interpolation?: "segment" | "pchip" | undefined;
|
|
531
|
+
interpolation?: "segment" | "pchip" | "spline" | undefined;
|
|
532
532
|
} | {
|
|
533
533
|
keys: {
|
|
534
534
|
t: number;
|
|
@@ -543,7 +543,7 @@ export declare const draft: import("@preact/signals-core").Signal<{
|
|
|
543
543
|
id: string;
|
|
544
544
|
target: "slot";
|
|
545
545
|
prop: "color" | "attachment" | "alpha" | "z";
|
|
546
|
-
interpolation?: "segment" | "pchip" | undefined;
|
|
546
|
+
interpolation?: "segment" | "pchip" | "spline" | undefined;
|
|
547
547
|
} | {
|
|
548
548
|
keys: {
|
|
549
549
|
t: number;
|
|
@@ -558,7 +558,7 @@ export declare const draft: import("@preact/signals-core").Signal<{
|
|
|
558
558
|
id: string;
|
|
559
559
|
target: "deform";
|
|
560
560
|
prop: string;
|
|
561
|
-
interpolation?: "segment" | "pchip" | undefined;
|
|
561
|
+
interpolation?: "segment" | "pchip" | "spline" | undefined;
|
|
562
562
|
} | {
|
|
563
563
|
keys: {
|
|
564
564
|
t: number;
|
|
@@ -573,7 +573,7 @@ export declare const draft: import("@preact/signals-core").Signal<{
|
|
|
573
573
|
id: string;
|
|
574
574
|
target: "ik";
|
|
575
575
|
prop: "mix" | "softness" | "bendPositive" | "compress" | "stretch";
|
|
576
|
-
interpolation?: "segment" | "pchip" | undefined;
|
|
576
|
+
interpolation?: "segment" | "pchip" | "spline" | undefined;
|
|
577
577
|
} | {
|
|
578
578
|
keys: {
|
|
579
579
|
t: number;
|
|
@@ -588,7 +588,7 @@ export declare const draft: import("@preact/signals-core").Signal<{
|
|
|
588
588
|
id: string;
|
|
589
589
|
target: "transform";
|
|
590
590
|
prop: "x" | "y" | "rotation" | "scaleX" | "scaleY" | "shearY" | "mixRotate" | "mixX" | "mixY" | "mixScaleX" | "mixScaleY" | "mixShearY";
|
|
591
|
-
interpolation?: "segment" | "pchip" | undefined;
|
|
591
|
+
interpolation?: "segment" | "pchip" | "spline" | undefined;
|
|
592
592
|
} | {
|
|
593
593
|
keys: {
|
|
594
594
|
t: number;
|
|
@@ -603,7 +603,7 @@ export declare const draft: import("@preact/signals-core").Signal<{
|
|
|
603
603
|
id: string;
|
|
604
604
|
target: "path";
|
|
605
605
|
prop: "mixRotate" | "mixX" | "mixY" | "position" | "spacing";
|
|
606
|
-
interpolation?: "segment" | "pchip" | undefined;
|
|
606
|
+
interpolation?: "segment" | "pchip" | "spline" | undefined;
|
|
607
607
|
} | {
|
|
608
608
|
keys: {
|
|
609
609
|
t: number;
|
|
@@ -618,7 +618,7 @@ export declare const draft: import("@preact/signals-core").Signal<{
|
|
|
618
618
|
id: string;
|
|
619
619
|
target: "drawOrder";
|
|
620
620
|
prop: "order";
|
|
621
|
-
interpolation?: "segment" | "pchip" | undefined;
|
|
621
|
+
interpolation?: "segment" | "pchip" | "spline" | undefined;
|
|
622
622
|
})[];
|
|
623
623
|
events: {
|
|
624
624
|
t: number;
|
|
@@ -834,7 +834,7 @@ export declare const shown: import("@preact/signals-core").ReadonlySignal<{
|
|
|
834
834
|
id: string;
|
|
835
835
|
target: "control";
|
|
836
836
|
prop: "value";
|
|
837
|
-
interpolation?: "segment" | "pchip" | undefined;
|
|
837
|
+
interpolation?: "segment" | "pchip" | "spline" | undefined;
|
|
838
838
|
} | {
|
|
839
839
|
keys: {
|
|
840
840
|
t: number;
|
|
@@ -849,7 +849,7 @@ export declare const shown: import("@preact/signals-core").ReadonlySignal<{
|
|
|
849
849
|
id: string;
|
|
850
850
|
target: "bone";
|
|
851
851
|
prop: "x" | "y" | "rotation" | "scaleX" | "scaleY" | "shearX" | "shearY";
|
|
852
|
-
interpolation?: "segment" | "pchip" | undefined;
|
|
852
|
+
interpolation?: "segment" | "pchip" | "spline" | undefined;
|
|
853
853
|
} | {
|
|
854
854
|
keys: {
|
|
855
855
|
t: number;
|
|
@@ -864,7 +864,7 @@ export declare const shown: import("@preact/signals-core").ReadonlySignal<{
|
|
|
864
864
|
id: string;
|
|
865
865
|
target: "slot";
|
|
866
866
|
prop: "color" | "attachment" | "alpha" | "z";
|
|
867
|
-
interpolation?: "segment" | "pchip" | undefined;
|
|
867
|
+
interpolation?: "segment" | "pchip" | "spline" | undefined;
|
|
868
868
|
} | {
|
|
869
869
|
keys: {
|
|
870
870
|
t: number;
|
|
@@ -879,7 +879,7 @@ export declare const shown: import("@preact/signals-core").ReadonlySignal<{
|
|
|
879
879
|
id: string;
|
|
880
880
|
target: "deform";
|
|
881
881
|
prop: string;
|
|
882
|
-
interpolation?: "segment" | "pchip" | undefined;
|
|
882
|
+
interpolation?: "segment" | "pchip" | "spline" | undefined;
|
|
883
883
|
} | {
|
|
884
884
|
keys: {
|
|
885
885
|
t: number;
|
|
@@ -894,7 +894,7 @@ export declare const shown: import("@preact/signals-core").ReadonlySignal<{
|
|
|
894
894
|
id: string;
|
|
895
895
|
target: "ik";
|
|
896
896
|
prop: "mix" | "softness" | "bendPositive" | "compress" | "stretch";
|
|
897
|
-
interpolation?: "segment" | "pchip" | undefined;
|
|
897
|
+
interpolation?: "segment" | "pchip" | "spline" | undefined;
|
|
898
898
|
} | {
|
|
899
899
|
keys: {
|
|
900
900
|
t: number;
|
|
@@ -909,7 +909,7 @@ export declare const shown: import("@preact/signals-core").ReadonlySignal<{
|
|
|
909
909
|
id: string;
|
|
910
910
|
target: "transform";
|
|
911
911
|
prop: "x" | "y" | "rotation" | "scaleX" | "scaleY" | "shearY" | "mixRotate" | "mixX" | "mixY" | "mixScaleX" | "mixScaleY" | "mixShearY";
|
|
912
|
-
interpolation?: "segment" | "pchip" | undefined;
|
|
912
|
+
interpolation?: "segment" | "pchip" | "spline" | undefined;
|
|
913
913
|
} | {
|
|
914
914
|
keys: {
|
|
915
915
|
t: number;
|
|
@@ -924,7 +924,7 @@ export declare const shown: import("@preact/signals-core").ReadonlySignal<{
|
|
|
924
924
|
id: string;
|
|
925
925
|
target: "path";
|
|
926
926
|
prop: "mixRotate" | "mixX" | "mixY" | "position" | "spacing";
|
|
927
|
-
interpolation?: "segment" | "pchip" | undefined;
|
|
927
|
+
interpolation?: "segment" | "pchip" | "spline" | undefined;
|
|
928
928
|
} | {
|
|
929
929
|
keys: {
|
|
930
930
|
t: number;
|
|
@@ -939,7 +939,7 @@ export declare const shown: import("@preact/signals-core").ReadonlySignal<{
|
|
|
939
939
|
id: string;
|
|
940
940
|
target: "drawOrder";
|
|
941
941
|
prop: "order";
|
|
942
|
-
interpolation?: "segment" | "pchip" | undefined;
|
|
942
|
+
interpolation?: "segment" | "pchip" | "spline" | undefined;
|
|
943
943
|
})[];
|
|
944
944
|
events: {
|
|
945
945
|
t: number;
|
|
@@ -1065,7 +1065,7 @@ export declare const currentAnim: import("@preact/signals-core").ReadonlySignal<
|
|
|
1065
1065
|
id: string;
|
|
1066
1066
|
target: "control";
|
|
1067
1067
|
prop: "value";
|
|
1068
|
-
interpolation?: "segment" | "pchip" | undefined;
|
|
1068
|
+
interpolation?: "segment" | "pchip" | "spline" | undefined;
|
|
1069
1069
|
} | {
|
|
1070
1070
|
keys: {
|
|
1071
1071
|
t: number;
|
|
@@ -1080,7 +1080,7 @@ export declare const currentAnim: import("@preact/signals-core").ReadonlySignal<
|
|
|
1080
1080
|
id: string;
|
|
1081
1081
|
target: "bone";
|
|
1082
1082
|
prop: "x" | "y" | "rotation" | "scaleX" | "scaleY" | "shearX" | "shearY";
|
|
1083
|
-
interpolation?: "segment" | "pchip" | undefined;
|
|
1083
|
+
interpolation?: "segment" | "pchip" | "spline" | undefined;
|
|
1084
1084
|
} | {
|
|
1085
1085
|
keys: {
|
|
1086
1086
|
t: number;
|
|
@@ -1095,7 +1095,7 @@ export declare const currentAnim: import("@preact/signals-core").ReadonlySignal<
|
|
|
1095
1095
|
id: string;
|
|
1096
1096
|
target: "slot";
|
|
1097
1097
|
prop: "color" | "attachment" | "alpha" | "z";
|
|
1098
|
-
interpolation?: "segment" | "pchip" | undefined;
|
|
1098
|
+
interpolation?: "segment" | "pchip" | "spline" | undefined;
|
|
1099
1099
|
} | {
|
|
1100
1100
|
keys: {
|
|
1101
1101
|
t: number;
|
|
@@ -1110,7 +1110,7 @@ export declare const currentAnim: import("@preact/signals-core").ReadonlySignal<
|
|
|
1110
1110
|
id: string;
|
|
1111
1111
|
target: "deform";
|
|
1112
1112
|
prop: string;
|
|
1113
|
-
interpolation?: "segment" | "pchip" | undefined;
|
|
1113
|
+
interpolation?: "segment" | "pchip" | "spline" | undefined;
|
|
1114
1114
|
} | {
|
|
1115
1115
|
keys: {
|
|
1116
1116
|
t: number;
|
|
@@ -1125,7 +1125,7 @@ export declare const currentAnim: import("@preact/signals-core").ReadonlySignal<
|
|
|
1125
1125
|
id: string;
|
|
1126
1126
|
target: "ik";
|
|
1127
1127
|
prop: "mix" | "softness" | "bendPositive" | "compress" | "stretch";
|
|
1128
|
-
interpolation?: "segment" | "pchip" | undefined;
|
|
1128
|
+
interpolation?: "segment" | "pchip" | "spline" | undefined;
|
|
1129
1129
|
} | {
|
|
1130
1130
|
keys: {
|
|
1131
1131
|
t: number;
|
|
@@ -1140,7 +1140,7 @@ export declare const currentAnim: import("@preact/signals-core").ReadonlySignal<
|
|
|
1140
1140
|
id: string;
|
|
1141
1141
|
target: "transform";
|
|
1142
1142
|
prop: "x" | "y" | "rotation" | "scaleX" | "scaleY" | "shearY" | "mixRotate" | "mixX" | "mixY" | "mixScaleX" | "mixScaleY" | "mixShearY";
|
|
1143
|
-
interpolation?: "segment" | "pchip" | undefined;
|
|
1143
|
+
interpolation?: "segment" | "pchip" | "spline" | undefined;
|
|
1144
1144
|
} | {
|
|
1145
1145
|
keys: {
|
|
1146
1146
|
t: number;
|
|
@@ -1155,7 +1155,7 @@ export declare const currentAnim: import("@preact/signals-core").ReadonlySignal<
|
|
|
1155
1155
|
id: string;
|
|
1156
1156
|
target: "path";
|
|
1157
1157
|
prop: "mixRotate" | "mixX" | "mixY" | "position" | "spacing";
|
|
1158
|
-
interpolation?: "segment" | "pchip" | undefined;
|
|
1158
|
+
interpolation?: "segment" | "pchip" | "spline" | undefined;
|
|
1159
1159
|
} | {
|
|
1160
1160
|
keys: {
|
|
1161
1161
|
t: number;
|
|
@@ -1170,7 +1170,7 @@ export declare const currentAnim: import("@preact/signals-core").ReadonlySignal<
|
|
|
1170
1170
|
id: string;
|
|
1171
1171
|
target: "drawOrder";
|
|
1172
1172
|
prop: "order";
|
|
1173
|
-
interpolation?: "segment" | "pchip" | undefined;
|
|
1173
|
+
interpolation?: "segment" | "pchip" | "spline" | undefined;
|
|
1174
1174
|
})[];
|
|
1175
1175
|
events: {
|
|
1176
1176
|
t: number;
|
package/dist/lib/editor-entry.js
CHANGED
|
@@ -248,7 +248,7 @@ var Key = z.object({
|
|
|
248
248
|
/** Optional independent easing for numeric-array components (for example Spine RGBA curves). */
|
|
249
249
|
componentEase: z.array(Ease).min(1).optional()
|
|
250
250
|
});
|
|
251
|
-
var Interpolation = { interpolation: z.enum(["segment", "pchip"]).optional() };
|
|
251
|
+
var Interpolation = { interpolation: z.enum(["segment", "pchip", "spline"]).optional() };
|
|
252
252
|
var Track = z.discriminatedUnion("target", [
|
|
253
253
|
z.object({ target: z.literal("control"), id: Id, prop: z.literal("value"), ...Interpolation, keys: z.array(Key).min(1) }),
|
|
254
254
|
z.object({ target: z.literal("bone"), id: Id, prop: BoneProp, ...Interpolation, keys: z.array(Key).min(1) }),
|
|
@@ -734,6 +734,57 @@ function smoothValue(track, i, t, component, loop) {
|
|
|
734
734
|
const u = (t - k[i].t) / h(i), u2 = u * u, u3 = u2 * u;
|
|
735
735
|
return (2 * u3 - 3 * u2 + 1) * v(i) + (u3 - 2 * u2 + u) * h(i) * tangent(i) + (-2 * u3 + 3 * u2) * v(i + 1) + (u3 - u2) * h(i) * tangent(i + 1);
|
|
736
736
|
}
|
|
737
|
+
function tridiagonal(a, b, c, r) {
|
|
738
|
+
const n = b.length, cp = [], x = [];
|
|
739
|
+
let beta = b[0];
|
|
740
|
+
x[0] = r[0] / beta;
|
|
741
|
+
for (let i = 1; i < n; i++) {
|
|
742
|
+
cp[i] = c[i - 1] / beta;
|
|
743
|
+
beta = b[i] - a[i] * cp[i];
|
|
744
|
+
x[i] = (r[i] - a[i] * x[i - 1]) / beta;
|
|
745
|
+
}
|
|
746
|
+
for (let i = n - 2; i >= 0; i--) x[i] -= cp[i + 1] * x[i + 1];
|
|
747
|
+
return x;
|
|
748
|
+
}
|
|
749
|
+
function splineMoments(t, v, periodic) {
|
|
750
|
+
const n = t.length, h = (j2) => t[j2 + 1] - t[j2], d = (j2) => (v[j2 + 1] - v[j2]) / h(j2);
|
|
751
|
+
if (!periodic) {
|
|
752
|
+
const a2 = [], b2 = [], c2 = [], r2 = [];
|
|
753
|
+
for (let i = 0; i < n; i++) {
|
|
754
|
+
const hp = i > 0 ? h(i - 1) : 0, hn = i < n - 1 ? h(i) : 0;
|
|
755
|
+
a2.push(hp);
|
|
756
|
+
b2.push(2 * (hp + hn));
|
|
757
|
+
c2.push(hn);
|
|
758
|
+
r2.push(6 * ((i < n - 1 ? d(i) : 0) - (i > 0 ? d(i - 1) : 0)));
|
|
759
|
+
}
|
|
760
|
+
return tridiagonal(a2, b2, c2, r2);
|
|
761
|
+
}
|
|
762
|
+
const m = n - 1, a = [], b = [], c = [], r = [];
|
|
763
|
+
for (let i = 0; i < m; i++) {
|
|
764
|
+
const p = (i + m - 1) % m;
|
|
765
|
+
a.push(h(p));
|
|
766
|
+
b.push(2 * (h(p) + h(i)));
|
|
767
|
+
c.push(h(i));
|
|
768
|
+
r.push(6 * (d(i) - d(p)));
|
|
769
|
+
}
|
|
770
|
+
const top = a[0], bottom = c[m - 1], gamma = -b[0];
|
|
771
|
+
const bb = [...b];
|
|
772
|
+
bb[0] -= gamma;
|
|
773
|
+
bb[m - 1] -= bottom * top / gamma;
|
|
774
|
+
const x = tridiagonal(a, bb, c, r), u = new Array(m).fill(0);
|
|
775
|
+
u[0] = gamma;
|
|
776
|
+
u[m - 1] = bottom;
|
|
777
|
+
const z4 = tridiagonal(a, bb, c, u);
|
|
778
|
+
const f = (x[0] + top * x[m - 1] / gamma) / (1 + z4[0] + top * z4[m - 1] / gamma);
|
|
779
|
+
const M = x.map((xi, i) => xi - f * z4[i]);
|
|
780
|
+
return [...M, M[0]];
|
|
781
|
+
}
|
|
782
|
+
function splineValue(track, i, t, component, loop) {
|
|
783
|
+
const k = track.keys, ts = k.map((x) => x.t), vs = k.map((x) => component === void 0 ? x.v : x.v[component]);
|
|
784
|
+
const M = splineMoments(ts, vs, loop && k.length > 3 && vs[0] === vs[k.length - 1]);
|
|
785
|
+
const H = ts[i + 1] - ts[i], A = (ts[i + 1] - t) / H, B = (t - ts[i]) / H;
|
|
786
|
+
return A * vs[i] + B * vs[i + 1] + ((A ** 3 - A) * M[i] + (B ** 3 - B) * M[i + 1]) * H * H / 6;
|
|
787
|
+
}
|
|
737
788
|
function sample(track, t, loop = false) {
|
|
738
789
|
const keys = track.keys;
|
|
739
790
|
if (t <= keys[0].t) return keys[0].v;
|
|
@@ -745,11 +796,13 @@ function sample(track, t, loop = false) {
|
|
|
745
796
|
if (a.ease === "step") return a.v;
|
|
746
797
|
if (typeof a.v === "number" && typeof b.v === "number") {
|
|
747
798
|
if (track.interpolation === "pchip") return smoothValue(track, i, t, void 0, loop);
|
|
799
|
+
if (track.interpolation === "spline") return splineValue(track, i, t, void 0, loop);
|
|
748
800
|
const u = ease(a.ease)((t - a.t) / (b.t - a.t));
|
|
749
801
|
return a.v + (b.v - a.v) * u;
|
|
750
802
|
}
|
|
751
803
|
if (Array.isArray(a.v) && Array.isArray(b.v) && typeof a.v[0] === "number") {
|
|
752
804
|
if (track.interpolation === "pchip") return a.v.map((_, j2) => smoothValue(track, i, t, j2, loop));
|
|
805
|
+
if (track.interpolation === "spline") return a.v.map((_, j2) => splineValue(track, i, t, j2, loop));
|
|
753
806
|
const phase = (t - a.t) / (b.t - a.t), av = a.v, bv = b.v;
|
|
754
807
|
return av.map((v, k) => v + ((bv[k] ?? v) - v) * ease(a.componentEase?.[k] ?? a.ease)(phase));
|
|
755
808
|
}
|
|
@@ -2481,7 +2534,8 @@ function adjustTrack(doc, animId, track, adj) {
|
|
|
2481
2534
|
return { ...k, t: r42(adj.timeScale ? k.t * adj.timeScale : k.t), v: r42(v) };
|
|
2482
2535
|
});
|
|
2483
2536
|
const duration = Math.max(anim.duration, keys[keys.length - 1].t);
|
|
2484
|
-
const
|
|
2537
|
+
const interpolation = track.interpolation ?? tr.interpolation;
|
|
2538
|
+
const next = { ...anim, duration, tracks: anim.tracks.map((t) => same(t) ? { ...t, keys, ...interpolation && { interpolation } } : t), preset: void 0 };
|
|
2485
2539
|
return { ...doc, animations: doc.animations.map((a) => a.id === animId ? next : a) };
|
|
2486
2540
|
}
|
|
2487
2541
|
function removeAnimation(doc, id) {
|
|
@@ -2898,19 +2952,20 @@ var requireSlot = (doc, id) => {
|
|
|
2898
2952
|
if (!s) throw new Error(`unknown slot "${id}"`);
|
|
2899
2953
|
return s;
|
|
2900
2954
|
};
|
|
2901
|
-
function sampled(duration, n, f
|
|
2955
|
+
function sampled(duration, n, f) {
|
|
2902
2956
|
const keys = [];
|
|
2903
2957
|
for (let i = 0; i <= n; i++) {
|
|
2904
2958
|
const t = +(duration * i / n).toFixed(4);
|
|
2905
|
-
keys.push({ t, v: +f(t).toFixed(4) + 0, ease:
|
|
2959
|
+
keys.push({ t, v: +f(t).toFixed(4) + 0, ease: "linear" });
|
|
2906
2960
|
}
|
|
2907
2961
|
return keys;
|
|
2908
2962
|
}
|
|
2909
|
-
|
|
2910
|
-
|
|
2963
|
+
var smooth = "spline";
|
|
2964
|
+
function boneTrack(bone, prop, keys, interpolation) {
|
|
2965
|
+
return { target: "bone", id: bone.id, prop, keys, ...interpolation && { interpolation } };
|
|
2911
2966
|
}
|
|
2912
|
-
function deformTrack(slot, prop, keys) {
|
|
2913
|
-
return slot.attachment ? { target: "deform", id: slot.attachment, prop, keys } : void 0;
|
|
2967
|
+
function deformTrack(slot, prop, keys, interpolation) {
|
|
2968
|
+
return slot.attachment ? { target: "deform", id: slot.attachment, prop, keys, ...interpolation && { interpolation } } : void 0;
|
|
2914
2969
|
}
|
|
2915
2970
|
var pushTrack = (tracks, t) => {
|
|
2916
2971
|
if (t) tracks.push(t);
|
|
@@ -2934,18 +2989,18 @@ var idleBreathing = {
|
|
|
2934
2989
|
const armsR = byRole(doc, "arm_r", "arm_upper_r");
|
|
2935
2990
|
const chest = slotOfBone(doc, torso);
|
|
2936
2991
|
if (chest?.attachment) {
|
|
2937
|
-
pushTrack(tracks, deformTrack(chest, "bulge", sampled(T2, 8, (t) => p.amplitude * Math.sin(w * t),
|
|
2992
|
+
pushTrack(tracks, deformTrack(chest, "bulge", sampled(T2, 8, (t) => p.amplitude * Math.sin(w * t)), smooth));
|
|
2938
2993
|
} else {
|
|
2939
2994
|
const r = torso.transform;
|
|
2940
|
-
tracks.push(boneTrack(torso, "scaleY", sampled(T2, 8, (t) => r.scaleY + p.amplitude * Math.sin(w * t),
|
|
2941
|
-
tracks.push(boneTrack(torso, "scaleX", sampled(T2, 8, (t) => r.scaleX - p.amplitude * 0.4 * Math.sin(w * t),
|
|
2995
|
+
tracks.push(boneTrack(torso, "scaleY", sampled(T2, 8, (t) => r.scaleY + p.amplitude * Math.sin(w * t)), smooth));
|
|
2996
|
+
tracks.push(boneTrack(torso, "scaleX", sampled(T2, 8, (t) => r.scaleX - p.amplitude * 0.4 * Math.sin(w * t)), smooth));
|
|
2942
2997
|
}
|
|
2943
2998
|
for (const h of heads)
|
|
2944
|
-
tracks.push(boneTrack(h, "y", sampled(T2, 8, (t) => h.transform.y - p.headBob * Math.sin(w * t + 0.4),
|
|
2999
|
+
tracks.push(boneTrack(h, "y", sampled(T2, 8, (t) => h.transform.y - p.headBob * Math.sin(w * t + 0.4)), smooth));
|
|
2945
3000
|
for (const a of armsL)
|
|
2946
|
-
tracks.push(boneTrack(a, "rotation", sampled(T2, 8, (t) => a.transform.rotation + p.armSway * Math.sin(w * t + 0.8),
|
|
3001
|
+
tracks.push(boneTrack(a, "rotation", sampled(T2, 8, (t) => a.transform.rotation + p.armSway * Math.sin(w * t + 0.8)), smooth));
|
|
2947
3002
|
for (const a of armsR)
|
|
2948
|
-
tracks.push(boneTrack(a, "rotation", sampled(T2, 8, (t) => a.transform.rotation - p.armSway * Math.sin(w * t + 0.8),
|
|
3003
|
+
tracks.push(boneTrack(a, "rotation", sampled(T2, 8, (t) => a.transform.rotation - p.armSway * Math.sin(w * t + 0.8)), smooth));
|
|
2949
3004
|
return finish(this.name, p.id, T2, true, tracks, p);
|
|
2950
3005
|
}
|
|
2951
3006
|
};
|
|
@@ -2954,22 +3009,20 @@ var winBounce = {
|
|
|
2954
3009
|
defaults: { id: "win", duration: 1.2, height: 40, bounces: 2, squash: 0.15 },
|
|
2955
3010
|
build(doc, p) {
|
|
2956
3011
|
const b = root(doc), r = b.transform, tracks = [];
|
|
2957
|
-
const yK = [[0, r.y,
|
|
2958
|
-
const sxK = [[0, r.scaleX, "ease_out"]];
|
|
2959
|
-
const syK = [[0, r.scaleY, "ease_out"]];
|
|
3012
|
+
const yK = [[0, r.y]], sxK = [[0, r.scaleX]], syK = [[0, r.scaleY]];
|
|
2960
3013
|
const per = p.duration / p.bounces;
|
|
2961
3014
|
for (let i = 0; i < p.bounces; i++) {
|
|
2962
3015
|
const t0 = i * per, h = p.height * 0.55 ** i, s = p.squash * 0.7 ** i;
|
|
2963
|
-
sxK.push([t0 + per * 0.08, r.scaleX * (1 + s)
|
|
2964
|
-
syK.push([t0 + per * 0.08, r.scaleY * (1 - s)
|
|
2965
|
-
yK.push([t0 + per * 0.08, r.y
|
|
3016
|
+
sxK.push([t0 + per * 0.08, r.scaleX * (1 + s)], [t0 + per * 0.5, r.scaleX * (1 - s * 0.6)], [t0 + per * 0.95, r.scaleX * (1 + s)]);
|
|
3017
|
+
syK.push([t0 + per * 0.08, r.scaleY * (1 - s)], [t0 + per * 0.5, r.scaleY * (1 + s * 0.6)], [t0 + per * 0.95, r.scaleY * (1 - s)]);
|
|
3018
|
+
yK.push([t0 + per * 0.08, r.y], [t0 + per * 0.5, r.y - h], [t0 + per * 0.95, r.y]);
|
|
2966
3019
|
}
|
|
2967
3020
|
yK.push([p.duration, r.y]);
|
|
2968
3021
|
sxK.push([p.duration, r.scaleX]);
|
|
2969
3022
|
syK.push([p.duration, r.scaleY]);
|
|
2970
|
-
tracks.push(boneTrack(b, "y", K(...yK)), boneTrack(b, "scaleX", K(...sxK)), boneTrack(b, "scaleY", K(...syK)));
|
|
3023
|
+
tracks.push(boneTrack(b, "y", K(...yK), "pchip"), boneTrack(b, "scaleX", K(...sxK), smooth), boneTrack(b, "scaleY", K(...syK), smooth));
|
|
2971
3024
|
for (const h of byRole(doc, "head"))
|
|
2972
|
-
tracks.push(boneTrack(h, "rotation", K([0, h.transform.rotation], [p.duration * 0.25, h.transform.rotation - 6
|
|
3025
|
+
tracks.push(boneTrack(h, "rotation", K([0, h.transform.rotation], [p.duration * 0.25, h.transform.rotation - 6], [p.duration * 0.6, h.transform.rotation + 4], [p.duration, h.transform.rotation]), smooth));
|
|
2973
3026
|
const anim = finish(this.name, p.id, p.duration, false, tracks, p);
|
|
2974
3027
|
anim.events.push({ t: 0, name: "win_start" }, { t: per * 0.95, name: "land" });
|
|
2975
3028
|
return anim;
|
|
@@ -2982,8 +3035,8 @@ var anticipationShake = {
|
|
|
2982
3035
|
const b = root(doc), r = b.transform, tracks = [];
|
|
2983
3036
|
const n = Math.ceil(p.duration * p.frequency * 4);
|
|
2984
3037
|
const env = (t) => p.grow ? t / p.duration : 1;
|
|
2985
|
-
tracks.push(boneTrack(b, "x", sampled(p.duration, n, (t) => r.x + p.amplitude * env(t) * Math.sin(2 * Math.PI * p.frequency * t),
|
|
2986
|
-
tracks.push(boneTrack(b, "rotation", sampled(p.duration, n, (t) => r.rotation + 0.6 * p.amplitude * env(t) * Math.sin(2 * Math.PI * p.frequency * t + 1.2),
|
|
3038
|
+
tracks.push(boneTrack(b, "x", sampled(p.duration, n, (t) => r.x + p.amplitude * env(t) * Math.sin(2 * Math.PI * p.frequency * t)), smooth));
|
|
3039
|
+
tracks.push(boneTrack(b, "rotation", sampled(p.duration, n, (t) => r.rotation + 0.6 * p.amplitude * env(t) * Math.sin(2 * Math.PI * p.frequency * t + 1.2)), smooth));
|
|
2987
3040
|
tracks.push(boneTrack(b, "scaleX", K([0, r.scaleX, "ease_in"], [p.duration, r.scaleX * p.scaleUp])));
|
|
2988
3041
|
tracks.push(boneTrack(b, "scaleY", K([0, r.scaleY, "ease_in"], [p.duration, r.scaleY * p.scaleUp])));
|
|
2989
3042
|
return finish(this.name, p.id, p.duration, false, tracks, p);
|
|
@@ -3008,6 +3061,7 @@ var mouthTalk = {
|
|
|
3008
3061
|
if (!p.frames.length) throw new Error("mouth_talk: frames must not be empty");
|
|
3009
3062
|
const n = Math.max(1, Math.round(p.duration * p.rate));
|
|
3010
3063
|
const keys = S(...Array.from({ length: n }, (_, i) => [+(i / p.rate).toFixed(4), p.frames[i % p.frames.length]]));
|
|
3064
|
+
if (keys.at(-1).t < p.duration && keys.at(-1).v !== keys[0].v) keys.push(...S([p.duration, keys[0].v]));
|
|
3011
3065
|
return finish(this.name, p.id, p.duration, true, [slotTrack(slot, "attachment", keys)], p);
|
|
3012
3066
|
}
|
|
3013
3067
|
};
|
|
@@ -3025,10 +3079,10 @@ var symbolIdle = {
|
|
|
3025
3079
|
build(doc, p) {
|
|
3026
3080
|
const b = root(doc), r = b.transform, T2 = p.period, w = 2 * Math.PI / T2, tracks = [];
|
|
3027
3081
|
const rise = (t) => 0.5 - 0.5 * Math.cos(w * t);
|
|
3028
|
-
tracks.push(boneTrack(b, "y", sampled(T2, 8, (t) => r.y - p.float * rise(t),
|
|
3029
|
-
if (p.tilt) tracks.push(boneTrack(b, "rotation", sampled(T2, 8, (t) => r.rotation + p.tilt * Math.sin(w * t),
|
|
3082
|
+
tracks.push(boneTrack(b, "y", sampled(T2, 8, (t) => r.y - p.float * rise(t)), smooth));
|
|
3083
|
+
if (p.tilt) tracks.push(boneTrack(b, "rotation", sampled(T2, 8, (t) => r.rotation + p.tilt * Math.sin(w * t)), smooth));
|
|
3030
3084
|
if (p.pulse) for (const s of doc.slots.filter((s2) => s2.bone === b.id && s2.attachment))
|
|
3031
|
-
pushTrack(tracks, deformTrack(s, "bulge", sampled(T2, 8, (t) => p.pulse * rise(t),
|
|
3085
|
+
pushTrack(tracks, deformTrack(s, "bulge", sampled(T2, 8, (t) => p.pulse * rise(t)), smooth));
|
|
3032
3086
|
return finish(this.name, p.id, T2, true, tracks, p);
|
|
3033
3087
|
}
|
|
3034
3088
|
};
|
|
@@ -3038,12 +3092,12 @@ var symbolWin = {
|
|
|
3038
3092
|
build(doc, p) {
|
|
3039
3093
|
const b = root(doc), r = b.transform, d = p.duration, tracks = [];
|
|
3040
3094
|
for (const [prop, rest] of [["scaleX", r.scaleX], ["scaleY", r.scaleY]])
|
|
3041
|
-
tracks.push(boneTrack(b, prop, K([0, rest
|
|
3095
|
+
tracks.push(boneTrack(b, prop, K([0, rest], [d * 0.2, rest * (1 + p.pop)], [d * 0.5, rest * (1 - p.pop * 0.3)], [d, rest]), smooth));
|
|
3042
3096
|
if (p.wobble) {
|
|
3043
3097
|
const n = Math.max(8, p.wobbles * 4);
|
|
3044
|
-
const keys = sampled(d, n, (t) => p.wobble * Math.exp(-3 * t / d) * Math.sin(2 * Math.PI * p.wobbles * t / d)
|
|
3098
|
+
const keys = sampled(d, n, (t) => p.wobble * Math.exp(-3 * t / d) * Math.sin(2 * Math.PI * p.wobbles * t / d));
|
|
3045
3099
|
keys[keys.length - 1].v = 0;
|
|
3046
|
-
for (const s of doc.slots.filter((s2) => s2.bone === b.id && s2.attachment)) pushTrack(tracks, deformTrack(s, "sway", keys));
|
|
3100
|
+
for (const s of doc.slots.filter((s2) => s2.bone === b.id && s2.attachment)) pushTrack(tracks, deformTrack(s, "sway", keys, smooth));
|
|
3047
3101
|
}
|
|
3048
3102
|
const anim = finish(this.name, p.id, d, false, tracks, p);
|
|
3049
3103
|
anim.events.push({ t: 0, name: "win_start" });
|
|
@@ -3057,11 +3111,11 @@ var weightShift = {
|
|
|
3057
3111
|
const T2 = p.period, w = 2 * Math.PI / T2, N = 16, tracks = [];
|
|
3058
3112
|
const hips = byRole(doc, "hips")[0] ?? root(doc), hr = hips.transform;
|
|
3059
3113
|
const s = (t) => Math.sin(w * t);
|
|
3060
|
-
tracks.push(boneTrack(hips, "x", sampled(T2, N, (t) => hr.x + p.shift * s(t))));
|
|
3061
|
-
if (p.dip) tracks.push(boneTrack(hips, "y", sampled(T2, N, (t) => hr.y + p.dip * s(t) ** 2)));
|
|
3114
|
+
tracks.push(boneTrack(hips, "x", sampled(T2, N, (t) => hr.x + p.shift * s(t)), smooth));
|
|
3115
|
+
if (p.dip) tracks.push(boneTrack(hips, "y", sampled(T2, N, (t) => hr.y + p.dip * s(t) ** 2), smooth));
|
|
3062
3116
|
const torso = byRole(doc, "torso", "body")[0];
|
|
3063
|
-
if (torso && torso !== hips) tracks.push(boneTrack(torso, "rotation", sampled(T2, N, (t) => torso.transform.rotation - p.lean * s(t))));
|
|
3064
|
-
for (const h of byRole(doc, "head")) tracks.push(boneTrack(h, "rotation", sampled(T2, N, (t) => h.transform.rotation + p.lean / 2 * s(t))));
|
|
3117
|
+
if (torso && torso !== hips) tracks.push(boneTrack(torso, "rotation", sampled(T2, N, (t) => torso.transform.rotation - p.lean * s(t)), smooth));
|
|
3118
|
+
for (const h of byRole(doc, "head")) tracks.push(boneTrack(h, "rotation", sampled(T2, N, (t) => h.transform.rotation + p.lean / 2 * s(t)), smooth));
|
|
3065
3119
|
for (const leg of byRole(doc, "leg_l", "leg_r")) {
|
|
3066
3120
|
const slot = slotOfBone(doc, leg), att = slot && doc.attachments.find((a) => a.id === slot.attachment && a.type === "region");
|
|
3067
3121
|
const asset = att && att.type === "region" ? doc.assets.find((a) => a.id === att.asset) : void 0;
|
|
@@ -3071,8 +3125,8 @@ var weightShift = {
|
|
|
3071
3125
|
length = Math.max(...[[0, -h / 2], [w2 / 2, 0], [0, h / 2], [-w2 / 2, 0]].map(([x, y]) => Math.hypot(...apply(m, x, y))));
|
|
3072
3126
|
}
|
|
3073
3127
|
if (!(length > p.shift)) continue;
|
|
3074
|
-
tracks.push(boneTrack(leg, "rotation", sampled(T2, N, (t) => leg.transform.rotation + Math.asin(p.shift * s(t) / length) * 180 / Math.PI)));
|
|
3075
|
-
if (p.dip) tracks.push(boneTrack(leg, "y", sampled(T2, N, (t) => leg.transform.y - p.dip * s(t) ** 2)));
|
|
3128
|
+
tracks.push(boneTrack(leg, "rotation", sampled(T2, N, (t) => leg.transform.rotation + Math.asin(p.shift * s(t) / length) * 180 / Math.PI), smooth));
|
|
3129
|
+
if (p.dip) tracks.push(boneTrack(leg, "y", sampled(T2, N, (t) => leg.transform.y - p.dip * s(t) ** 2), smooth));
|
|
3076
3130
|
}
|
|
3077
3131
|
return finish(this.name, p.id, T2, true, tracks, p);
|
|
3078
3132
|
}
|
|
@@ -3308,13 +3362,13 @@ function motionQuality(doc, anim, opts = {}) {
|
|
|
3308
3362
|
const before = delta(values(k.v), values(p.v)), after = delta(values(n.v), values(k.v));
|
|
3309
3363
|
const pass = before.some((v, j2) => v * after[j2] > 1e-6);
|
|
3310
3364
|
const speed = Math.max(magnitude(before) / (k.t - p.t), magnitude(after) / (n.t - k.t));
|
|
3311
|
-
if (pass && Math.max(magnitude(left), magnitude(right)) < speed * 0.02) report("pass_key_stop", id, `motion stops at a pass-through key; use track interpolation pchip or matched tangents`, k.t);
|
|
3365
|
+
if (pass && Math.max(magnitude(left), magnitude(right)) < speed * 0.02) report("pass_key_stop", id, `motion stops at a pass-through key; use track interpolation pchip or spline, or matched tangents`, k.t);
|
|
3312
3366
|
const jump = magnitude(delta(left, right));
|
|
3313
3367
|
if (jump > Math.max(0.1, speed * 0.1)) report("velocity_jump", id, `velocity jumps ${jump.toFixed(3)} units/s across this key`, k.t);
|
|
3314
3368
|
const acceleration = (a, b, c) => values(at(b)).map((v, j2) => (values(at(c))[j2] - 2 * v + values(at(a))[j2]) / (h * h));
|
|
3315
3369
|
const al = acceleration(k.t - 2 * h, k.t - h, k.t), ar = acceleration(k.t, k.t + h, k.t + 2 * h);
|
|
3316
3370
|
const aj = magnitude(delta(al, ar));
|
|
3317
|
-
if (aj > Math.max(1, speed / Math.min(k.t - p.t, n.t - k.t) * 2)) report("acceleration_jump", id, `acceleration changes by ${aj.toFixed(2)} units/s\xB2 at this key; PCHIP guarantees velocity, not acceleration continuity`, k.t, "info");
|
|
3371
|
+
if (aj > Math.max(1, speed / Math.min(k.t - p.t, n.t - k.t) * 2)) report("acceleration_jump", id, `acceleration changes by ${aj.toFixed(2)} units/s\xB2 at this key; PCHIP guarantees velocity, not acceleration continuity \u2014 spline does both`, k.t, "info");
|
|
3318
3372
|
}
|
|
3319
3373
|
}
|
|
3320
3374
|
const steps = Math.max(2, Math.ceil(D * 60));
|
|
@@ -3796,6 +3850,17 @@ function checkRig(doc, opts = {}) {
|
|
|
3796
3850
|
out.push({ level: "warn", code: "never_visible", subject: s.id, message: `slot "${s.id}" has no attachment and no animation ever shows one` });
|
|
3797
3851
|
return out;
|
|
3798
3852
|
}
|
|
3853
|
+
function summarizeIgnoring(findings, rules, max) {
|
|
3854
|
+
const hits = (r, f) => r.code === f.code && (r.subject ?? f.subject) === f.subject && (r.animation ?? f.animation) === f.animation;
|
|
3855
|
+
const kept = findings.filter((f) => !rules.some((r) => hits(r, f)));
|
|
3856
|
+
const idle = rules.filter((r) => !findings.some((f) => hits(r, f)));
|
|
3857
|
+
const notes = [
|
|
3858
|
+
...kept.length < findings.length ? [` (${findings.length - kept.length} ignored)`] : [],
|
|
3859
|
+
...idle.map((r) => ` ignore matched nothing: ${JSON.stringify(r)}`)
|
|
3860
|
+
];
|
|
3861
|
+
return [summarize(kept, max), ...notes].join("\n");
|
|
3862
|
+
}
|
|
3863
|
+
var where = (f) => `${f.subject}${f.animation ? ` in ${f.animation}` : ""}${f.time !== void 0 ? ` @${+f.time.toFixed(4)}s` : ""}`;
|
|
3799
3864
|
function summarize(findings, max = 12) {
|
|
3800
3865
|
if (!findings.length) return "check: OK";
|
|
3801
3866
|
const rank = { error: 0, warn: 1, info: 2 };
|
|
@@ -3810,7 +3875,7 @@ function summarize(findings, max = 12) {
|
|
|
3810
3875
|
const lines = [];
|
|
3811
3876
|
for (const f of sorted) {
|
|
3812
3877
|
const shown = shownPerCode.get(f.code) ?? 0;
|
|
3813
|
-
if (shown < PER_CODE) lines.push(` [${f.level}] ${f.code}: ${f.message}`);
|
|
3878
|
+
if (shown < PER_CODE) lines.push(` [${f.level}] ${f.code} ${where(f)}: ${f.message}`);
|
|
3814
3879
|
else if (shown === PER_CODE) lines.push(` \u2026 ${codeTotal.get(f.code) - PER_CODE} more ${f.code}`);
|
|
3815
3880
|
shownPerCode.set(f.code, shown + 1);
|
|
3816
3881
|
}
|
|
@@ -4001,7 +4066,7 @@ function packRects(rects, opts = {}) {
|
|
|
4001
4066
|
shelf = Math.max(shelf, r.height);
|
|
4002
4067
|
}
|
|
4003
4068
|
const height = y + shelf + pad;
|
|
4004
|
-
if (height <= max) return { width, height, frames };
|
|
4069
|
+
if (height <= max) return { width: Math.max(pad, ...[...frames.values()].map(([fx, , fw]) => fx + fw)) + pad, height, frames };
|
|
4005
4070
|
if (width >= max) throw new Error(`atlas does not fit in ${max}\xD7${max} (needs ${width}\xD7${height})`);
|
|
4006
4071
|
width *= 2;
|
|
4007
4072
|
}
|
|
@@ -5607,7 +5672,8 @@ function previewCheck(doc, animation) {
|
|
|
5607
5672
|
const a = animation ? doc.animations.find((x) => x.id === animation) : void 0;
|
|
5608
5673
|
return a ? `check: OK for "${a.id}" (${a.tracks.length} tracks, ${a.duration}s${a.loop ? " loop" : ""})` : "check: OK (rest pose)";
|
|
5609
5674
|
}
|
|
5610
|
-
var
|
|
5675
|
+
var TrackId = { target: z3.enum(["bone", "slot", "deform", "ik", "transform", "path", "drawOrder", "control"]), id: z3.string(), prop: z3.string() };
|
|
5676
|
+
var TrackRef = { interpolation: z3.enum(["segment", "pchip", "spline"]).optional().describe("segment: per-key easing; pchip: smooth through numeric keys, never past them (continuous velocity); spline: C2 cubic through them, continuous acceleration too, may overshoot between keys \u2014 for sampled curves"), ...TrackId };
|
|
5611
5677
|
tool(
|
|
5612
5678
|
"rig_set_control",
|
|
5613
5679
|
"Create or replace a semantic control with a finite min/max/default range. Animate target=control, prop=value. Changing a range requires matching binding grids.",
|
|
@@ -5800,11 +5866,21 @@ tool(
|
|
|
5800
5866
|
);
|
|
5801
5867
|
tool(
|
|
5802
5868
|
"rig_check",
|
|
5803
|
-
"Cheap self-critique without rendering: out_of_canvas (slot leaves the canvas, worst time), static_track, loop_seam, deform_flip (lattice folds over itself \u2014 an error), mesh_fold (a skinned/deformed mesh folds over itself: error when \u2265 5 % of the mesh folds, warning below \u2014 a dense mesh bent hard at a joint pinches the odd hairline triangle), weights_sum (skinned mesh vertex weights not summing to 1), patch_offset (a slot sits away from its asset's source bbox), rest_overlap, unused_asset, never_visible, and for constraints: constraint_dead (every mix is 0 at rest and no track lifts one \u2014 the solver skips it), constraint_cycle (the target is a bone the constraint drives, or hangs off one: it reads what it writes \u2014 an error), ik_unreachable (the target sits beyond the chain's reach for over 20 % of an animation, so the limb hangs straight), path_missing (a path constraint whose target slot never shows a path attachment \u2014 an error). Motion diagnostics also cover pass_key_stop, velocity_jump, acceleration_jump, loop_velocity and constraint_order; provide secondaryBones, frontOf slot pairs and named attachment UV landmarks for brief-specific frozen-motion, ordering and swap-registration checks. Findings are sorted by severity. Run it before spending vision tokens on a preview.",
|
|
5804
|
-
{
|
|
5805
|
-
|
|
5869
|
+
"Cheap self-critique without rendering: out_of_canvas (slot leaves the canvas, worst time), static_track, loop_seam, deform_flip (lattice folds over itself \u2014 an error), mesh_fold (a skinned/deformed mesh folds over itself: error when \u2265 5 % of the mesh folds, warning below \u2014 a dense mesh bent hard at a joint pinches the odd hairline triangle), weights_sum (skinned mesh vertex weights not summing to 1), patch_offset (a slot sits away from its asset's source bbox), rest_overlap, unused_asset, never_visible, and for constraints: constraint_dead (every mix is 0 at rest and no track lifts one \u2014 the solver skips it), constraint_cycle (the target is a bone the constraint drives, or hangs off one: it reads what it writes \u2014 an error), ik_unreachable (the target sits beyond the chain's reach for over 20 % of an animation, so the limb hangs straight), path_missing (a path constraint whose target slot never shows a path attachment \u2014 an error). Motion diagnostics also cover pass_key_stop, velocity_jump, acceleration_jump, loop_velocity and constraint_order; provide secondaryBones, frontOf slot pairs and named attachment UV landmarks for brief-specific frozen-motion, ordering and swap-registration checks. Findings are sorted by severity; each line names its subject (a track as target.id.prop), animation and time. `ignore` drops findings you have read and accept \u2014 by code, narrowed by subject and animation; the reply counts them and names a rule that matched nothing. Run it before spending vision tokens on a preview.",
|
|
5870
|
+
{
|
|
5871
|
+
path: Path,
|
|
5872
|
+
animation: z3.string().optional().describe("limit to one animation (rest pose is always checked)"),
|
|
5873
|
+
fps: z3.number().positive().optional(),
|
|
5874
|
+
deformFps: z3.number().positive().optional(),
|
|
5875
|
+
secondaryBones: z3.array(z3.string()).optional(),
|
|
5876
|
+
frontOf: z3.array(z3.tuple([z3.string(), z3.string()])).optional(),
|
|
5877
|
+
landmarks: z3.record(z3.record(z3.tuple([z3.number(), z3.number()]))).optional(),
|
|
5878
|
+
landmarkTolerance: z3.number().nonnegative().optional(),
|
|
5879
|
+
ignore: z3.array(z3.object({ code: z3.string(), subject: z3.string().optional(), animation: z3.string().optional() }).strict()).optional()
|
|
5880
|
+
},
|
|
5881
|
+
async ({ path, ignore = [], ...opts }) => {
|
|
5806
5882
|
try {
|
|
5807
|
-
return text(
|
|
5883
|
+
return text(summarizeIgnoring(checkRig(await load(path), opts), ignore, 100));
|
|
5808
5884
|
} catch (e) {
|
|
5809
5885
|
return fail(e);
|
|
5810
5886
|
}
|
|
@@ -6421,9 +6497,9 @@ tool(
|
|
|
6421
6497
|
);
|
|
6422
6498
|
tool(
|
|
6423
6499
|
"rig_adjust_track",
|
|
6424
|
-
"Re-tune an existing track without retyping keys: amplitude scales its deviation from the rest value (0.5 = half as strong, 2 = twice; scale props as ratios), offset adds a constant, timeScale stretches its key times (duration grows to fit). Drops the preset link.",
|
|
6500
|
+
"Re-tune an existing track without retyping keys: amplitude scales its deviation from the rest value (0.5 = half as strong, 2 = twice; scale props as ratios), offset adds a constant, timeScale stretches its key times (duration grows to fit), interpolation switches segment / pchip / spline. Drops the preset link.",
|
|
6425
6501
|
{ path: Path, animation: z3.string(), ...TrackRef, amplitude: z3.number().optional(), offset: z3.number().optional(), timeScale: z3.number().positive().optional() },
|
|
6426
|
-
async ({ path, animation, target, id, prop, ...adj }) => mutate(path, (d) => adjustTrack(d, animation, { target, id, prop }, adj))
|
|
6502
|
+
async ({ path, animation, target, id, prop, interpolation, ...adj }) => mutate(path, (d) => adjustTrack(d, animation, { target, id, prop, interpolation }, adj))
|
|
6427
6503
|
);
|
|
6428
6504
|
tool(
|
|
6429
6505
|
"rig_set_animation",
|
|
@@ -6441,7 +6517,7 @@ tool(
|
|
|
6441
6517
|
tool(
|
|
6442
6518
|
"rig_remove_keys",
|
|
6443
6519
|
"Remove the keys of one track at the given times; an emptied track is dropped. Drops the preset link.",
|
|
6444
|
-
{ path: Path, animation: z3.string(), ...
|
|
6520
|
+
{ path: Path, animation: z3.string(), ...TrackId, times: z3.array(z3.number()).min(1) },
|
|
6445
6521
|
async ({ path, animation, target, id, prop, times: times2 }) => mutate(path, (d) => removeKeys(d, animation, { target, id, prop }, times2))
|
|
6446
6522
|
);
|
|
6447
6523
|
tool(
|