@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.
@@ -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;
@@ -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 next = { ...anim, duration, tracks: anim.tracks.map((t) => same(t) ? { ...t, keys } : t), preset: void 0 };
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, ease2 = "linear") {
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: ease2 });
2959
+ keys.push({ t, v: +f(t).toFixed(4) + 0, ease: "linear" });
2906
2960
  }
2907
2961
  return keys;
2908
2962
  }
2909
- function boneTrack(bone, prop, keys) {
2910
- return { target: "bone", id: bone.id, prop, keys };
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), "ease_in_out")));
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), "ease_in_out")));
2941
- tracks.push(boneTrack(torso, "scaleX", sampled(T2, 8, (t) => r.scaleX - p.amplitude * 0.4 * Math.sin(w * t), "ease_in_out")));
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), "ease_in_out")));
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), "ease_in_out")));
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), "ease_in_out")));
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, "ease_out"]];
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), "ease_out"], [t0 + per * 0.5, r.scaleX * (1 - s * 0.6), "ease_in"], [t0 + per * 0.95, r.scaleX * (1 + s), "ease_out"]);
2964
- syK.push([t0 + per * 0.08, r.scaleY * (1 - s), "ease_out"], [t0 + per * 0.5, r.scaleY * (1 + s * 0.6), "ease_in"], [t0 + per * 0.95, r.scaleY * (1 - s), "ease_out"]);
2965
- yK.push([t0 + per * 0.08, r.y, "ease_out"], [t0 + per * 0.5, r.y - h, "ease_in"], [t0 + per * 0.95, r.y, "ease_out"]);
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, "back_out"], [p.duration * 0.6, h.transform.rotation + 4], [p.duration, h.transform.rotation])));
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), "linear")));
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), "linear")));
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), "ease_in_out")));
3029
- if (p.tilt) tracks.push(boneTrack(b, "rotation", sampled(T2, 8, (t) => r.rotation + p.tilt * Math.sin(w * t), "ease_in_out")));
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), "ease_in_out")));
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, "ease_out"], [d * 0.2, rest * (1 + p.pop), "ease_in_out"], [d * 0.5, rest * (1 - p.pop * 0.3), "ease_out"], [d, 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), "ease_in_out");
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 TrackRef = { interpolation: z3.enum(["segment", "pchip"]).optional().describe("pchip: smooth through numeric keys, preserving extrema; segment: per-key easing"), target: z3.enum(["bone", "slot", "deform", "ik", "transform", "path", "drawOrder", "control"]), id: z3.string(), prop: z3.string() };
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
- { path: Path, animation: z3.string().optional().describe("limit to one animation (rest pose is always checked)"), fps: z3.number().positive().optional(), deformFps: z3.number().positive().optional(), secondaryBones: z3.array(z3.string()).optional(), frontOf: z3.array(z3.tuple([z3.string(), z3.string()])).optional(), landmarks: z3.record(z3.record(z3.tuple([z3.number(), z3.number()]))).optional(), landmarkTolerance: z3.number().nonnegative().optional() },
5805
- async ({ path, ...opts }) => {
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(summarize(checkRig(await load(path), opts), 100));
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(), ...TrackRef, times: z3.array(z3.number()).min(1) },
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(