pixi-effects 0.2.0 → 0.3.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/CHANGELOG.md +31 -0
- package/README.md +15 -5
- package/ai/SKILL.md +44 -0
- package/ai/reference/cheatsheet.md +120 -0
- package/ai/reference/pitfalls.md +54 -0
- package/ai/reference/recipes.md +375 -0
- package/ai/template.html +82 -0
- package/ai/tools/save-image.py +24 -0
- package/dist/{Base-B1Tdn0Cv.d.cts → Base-BDw6dKRB.d.cts} +1 -1
- package/dist/{Base-Bh_VSusi.d.ts → Base-Ba4Ta4ap.d.ts} +1 -1
- package/dist/Composition-6FDH5OPM.cjs +13 -0
- package/dist/{Composition-BI5HZJFL.cjs.map → Composition-6FDH5OPM.cjs.map} +1 -1
- package/dist/Composition-FEYAUMFI.js +4 -0
- package/dist/{Composition-IO7ZN32J.js.map → Composition-FEYAUMFI.js.map} +1 -1
- package/dist/Controller.d.cts +2 -2
- package/dist/Controller.d.ts +2 -2
- package/dist/Movie-DMpaT67V.d.ts +179 -0
- package/dist/Movie-W8ISiEBB.d.cts +179 -0
- package/dist/{chunk-H55V3U56.js → chunk-DIJG2RSF.js} +28 -11
- package/dist/chunk-DIJG2RSF.js.map +1 -0
- package/dist/{chunk-VJCDG6YG.js → chunk-PN5A6QA7.js} +248 -64
- package/dist/chunk-PN5A6QA7.js.map +1 -0
- package/dist/{chunk-7OIWYXGV.cjs → chunk-SIRVULFF.cjs} +251 -62
- package/dist/chunk-SIRVULFF.cjs.map +1 -0
- package/dist/{chunk-64IHCYYN.cjs → chunk-ZL262ZRM.cjs} +37 -20
- package/dist/chunk-ZL262ZRM.cjs.map +1 -0
- package/dist/index.cjs +324 -24
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +61 -31
- package/dist/index.d.ts +61 -31
- package/dist/index.js +321 -22
- package/dist/index.js.map +1 -1
- package/dist/three.cjs +5 -5
- package/dist/three.d.cts +2 -2
- package/dist/three.d.ts +2 -2
- package/dist/three.js +1 -1
- package/dist/{types-CNBilhpz.d.cts → types-3c8Vymgw.d.cts} +53 -6
- package/dist/{types-CNBilhpz.d.ts → types-3c8Vymgw.d.ts} +53 -6
- package/docs/api.md +333 -0
- package/docs/dsl.md +1017 -0
- package/llms-full.txt +1966 -0
- package/llms.txt +30 -0
- package/package.json +4 -3
- package/dist/Composition-BI5HZJFL.cjs +0 -13
- package/dist/Composition-IO7ZN32J.js +0 -4
- package/dist/Movie-CcR6h2jO.d.cts +0 -82
- package/dist/Movie-D-n8glA6.d.ts +0 -82
- package/dist/chunk-64IHCYYN.cjs.map +0 -1
- package/dist/chunk-7OIWYXGV.cjs.map +0 -1
- package/dist/chunk-H55V3U56.js.map +0 -1
- package/dist/chunk-VJCDG6YG.js.map +0 -1
|
@@ -246,6 +246,23 @@ function looksLikeColorString(s) {
|
|
|
246
246
|
}
|
|
247
247
|
|
|
248
248
|
// src/core/Timeline.ts
|
|
249
|
+
function loopVars(kf) {
|
|
250
|
+
const out = {};
|
|
251
|
+
let repeat = 0;
|
|
252
|
+
if (kf.repeat !== void 0) {
|
|
253
|
+
if (Number.isFinite(kf.repeat) && kf.repeat >= 0) {
|
|
254
|
+
repeat = Math.floor(kf.repeat);
|
|
255
|
+
out.repeat = repeat;
|
|
256
|
+
} else {
|
|
257
|
+
console.warn(`pixi-effects: keyframe repeat ${String(kf.repeat)} ignored \u2014 repeat must be a finite count >= 0 (the timeline needs a fixed length; for endless motion repeat many times).`);
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
if (repeat > 0) {
|
|
261
|
+
if (kf.yoyo !== void 0) out.yoyo = kf.yoyo;
|
|
262
|
+
if (kf.repeatDelay !== void 0 && kf.repeatDelay > 0) out.repeatDelay = kf.repeatDelay;
|
|
263
|
+
}
|
|
264
|
+
return out;
|
|
265
|
+
}
|
|
249
266
|
function resolveAt(at, duration) {
|
|
250
267
|
if (at === void 0 || at === null) return 0;
|
|
251
268
|
return at < 0 ? duration + at : at;
|
|
@@ -263,7 +280,7 @@ function normalizeKeyframe(kf, parentDuration) {
|
|
|
263
280
|
else if (hasFrom) kind = "from";
|
|
264
281
|
else if (hasTo) kind = "to";
|
|
265
282
|
else kind = "to";
|
|
266
|
-
return { at, duration, ease, kind, set: kf.set, from: kf.from, to: kf.to };
|
|
283
|
+
return { at, duration, ease, loop: loopVars(kf), kind, set: kf.set, from: kf.from, to: kf.to };
|
|
267
284
|
}
|
|
268
285
|
function partitionProps(props) {
|
|
269
286
|
const ownProps = {};
|
|
@@ -373,27 +390,27 @@ function applyKeyframes(timeline, target, keyframes, parentDuration, scope, skip
|
|
|
373
390
|
const resolved = normalizeProps(kf.to, scope, { skipKeys });
|
|
374
391
|
const { rest, routed } = splitRouted(resolved, routers);
|
|
375
392
|
for (const r of routed)
|
|
376
|
-
timeline.to(r.target, { [r.prop]: r.value, duration: kf.duration, ease: kf.ease }, at);
|
|
393
|
+
timeline.to(r.target, { [r.prop]: r.value, duration: kf.duration, ease: kf.ease, ...kf.loop }, at);
|
|
377
394
|
const { ownProps, filterProps } = partitionProps(rest);
|
|
378
395
|
if (Object.keys(ownProps).length > 0)
|
|
379
|
-
timeline.to(target, { ...pixiwrap(ownProps), duration: kf.duration, ease: kf.ease }, at);
|
|
396
|
+
timeline.to(target, { ...pixiwrap(ownProps), duration: kf.duration, ease: kf.ease, ...kf.loop }, at);
|
|
380
397
|
for (const [name, props] of Object.entries(filterProps)) {
|
|
381
398
|
const f = findFilter(target, name);
|
|
382
399
|
if (!f) continue;
|
|
383
|
-
timeline.to(f, { ...props, duration: kf.duration, ease: kf.ease }, at);
|
|
400
|
+
timeline.to(f, { ...props, duration: kf.duration, ease: kf.ease, ...kf.loop }, at);
|
|
384
401
|
}
|
|
385
402
|
} else if (kf.kind === "from") {
|
|
386
403
|
const resolved = normalizeProps(kf.from, scope, { skipKeys });
|
|
387
404
|
const { rest, routed } = splitRouted(resolved, routers);
|
|
388
405
|
for (const r of routed)
|
|
389
|
-
timeline.from(r.target, { [r.prop]: r.value, duration: kf.duration, ease: kf.ease }, at);
|
|
406
|
+
timeline.from(r.target, { [r.prop]: r.value, duration: kf.duration, ease: kf.ease, ...kf.loop }, at);
|
|
390
407
|
const { ownProps, filterProps } = partitionProps(rest);
|
|
391
408
|
if (Object.keys(ownProps).length > 0)
|
|
392
|
-
timeline.from(target, { ...pixiwrap(ownProps), duration: kf.duration, ease: kf.ease }, at);
|
|
409
|
+
timeline.from(target, { ...pixiwrap(ownProps), duration: kf.duration, ease: kf.ease, ...kf.loop }, at);
|
|
393
410
|
for (const [name, props] of Object.entries(filterProps)) {
|
|
394
411
|
const f = findFilter(target, name);
|
|
395
412
|
if (!f) continue;
|
|
396
|
-
timeline.from(f, { ...props, duration: kf.duration, ease: kf.ease }, at);
|
|
413
|
+
timeline.from(f, { ...props, duration: kf.duration, ease: kf.ease, ...kf.loop }, at);
|
|
397
414
|
}
|
|
398
415
|
} else {
|
|
399
416
|
const fromResolved = normalizeProps(kf.from, scope, { skipKeys });
|
|
@@ -408,15 +425,15 @@ function applyKeyframes(timeline, target, keyframes, parentDuration, scope, skip
|
|
|
408
425
|
timeline.fromTo(
|
|
409
426
|
r.target,
|
|
410
427
|
{ [r.prop]: f.value },
|
|
411
|
-
{ [r.prop]: r.value, duration: kf.duration, ease: kf.ease },
|
|
428
|
+
{ [r.prop]: r.value, duration: kf.duration, ease: kf.ease, ...kf.loop },
|
|
412
429
|
at
|
|
413
430
|
);
|
|
414
431
|
} else {
|
|
415
|
-
timeline.to(r.target, { [r.prop]: r.value, duration: kf.duration, ease: kf.ease }, at);
|
|
432
|
+
timeline.to(r.target, { [r.prop]: r.value, duration: kf.duration, ease: kf.ease, ...kf.loop }, at);
|
|
416
433
|
}
|
|
417
434
|
}
|
|
418
435
|
for (const f of fromByKey.values())
|
|
419
|
-
timeline.from(f.target, { [f.prop]: f.value, duration: kf.duration, ease: kf.ease }, at);
|
|
436
|
+
timeline.from(f.target, { [f.prop]: f.value, duration: kf.duration, ease: kf.ease, ...kf.loop }, at);
|
|
420
437
|
const fromSplit = partitionProps(fromRouted.rest);
|
|
421
438
|
const toSplit = partitionProps(toRouted.rest);
|
|
422
439
|
const ownKeys = /* @__PURE__ */ new Set([...Object.keys(fromSplit.ownProps), ...Object.keys(toSplit.ownProps)]);
|
|
@@ -424,7 +441,7 @@ function applyKeyframes(timeline, target, keyframes, parentDuration, scope, skip
|
|
|
424
441
|
timeline.fromTo(
|
|
425
442
|
target,
|
|
426
443
|
{ ...pixiwrap(fromSplit.ownProps) },
|
|
427
|
-
{ ...pixiwrap(toSplit.ownProps), duration: kf.duration, ease: kf.ease },
|
|
444
|
+
{ ...pixiwrap(toSplit.ownProps), duration: kf.duration, ease: kf.ease, ...kf.loop },
|
|
428
445
|
at
|
|
429
446
|
);
|
|
430
447
|
}
|
|
@@ -438,7 +455,7 @@ function applyKeyframes(timeline, target, keyframes, parentDuration, scope, skip
|
|
|
438
455
|
timeline.fromTo(
|
|
439
456
|
f,
|
|
440
457
|
{ ...fromSplit.filterProps[name] ?? {} },
|
|
441
|
-
{ ...toSplit.filterProps[name] ?? {}, duration: kf.duration, ease: kf.ease },
|
|
458
|
+
{ ...toSplit.filterProps[name] ?? {}, duration: kf.duration, ease: kf.ease, ...kf.loop },
|
|
442
459
|
at
|
|
443
460
|
);
|
|
444
461
|
}
|
|
@@ -763,9 +780,9 @@ var Sequence = class {
|
|
|
763
780
|
if (!this.target) return;
|
|
764
781
|
const scope = this.scope();
|
|
765
782
|
const routers = this.pathRouters();
|
|
766
|
-
applyInitial(this.target, this.spec.initial, scope, [], routers);
|
|
767
|
-
applyKeyframes(timeline, this.target, this.spec.keyframes, this.duration, scope, [], offset, routers);
|
|
768
783
|
const startTime = offset + this.at;
|
|
784
|
+
applyInitial(this.target, this.spec.initial, scope, [], routers);
|
|
785
|
+
applyKeyframes(timeline, this.target, this.spec.keyframes, this.duration, scope, [], startTime, routers);
|
|
769
786
|
const endTime = startTime + this.duration;
|
|
770
787
|
this.absoluteStart = startTime;
|
|
771
788
|
this.target.renderable = startTime <= 0;
|
|
@@ -789,6 +806,46 @@ var Sequence = class {
|
|
|
789
806
|
}
|
|
790
807
|
};
|
|
791
808
|
|
|
809
|
+
// src/space/specKeys.ts
|
|
810
|
+
function collectPropKeys(spec) {
|
|
811
|
+
const out = /* @__PURE__ */ new Set();
|
|
812
|
+
for (const k of Object.keys(spec.initial ?? {})) out.add(k);
|
|
813
|
+
for (const kf of spec.keyframes ?? []) {
|
|
814
|
+
for (const bag of [kf.set, kf.to, kf.from]) {
|
|
815
|
+
for (const k of Object.keys(bag ?? {})) out.add(k);
|
|
816
|
+
}
|
|
817
|
+
}
|
|
818
|
+
return out;
|
|
819
|
+
}
|
|
820
|
+
|
|
821
|
+
// src/core/lint.ts
|
|
822
|
+
var defaultWarn = (m) => console.warn(m);
|
|
823
|
+
function describeLayer(spec) {
|
|
824
|
+
return spec.name ? `layer "${spec.name}"` : `unnamed ${spec.type} layer`;
|
|
825
|
+
}
|
|
826
|
+
function lintTiming(spec, parentDuration, warn = defaultWarn) {
|
|
827
|
+
const who = describeLayer(spec);
|
|
828
|
+
const at = spec.at ?? 0;
|
|
829
|
+
if (at >= parentDuration) {
|
|
830
|
+
warn(`pixi-effects: ${who} starts at ${at}s, after its composition ends (${parentDuration}s), so it is never visible`);
|
|
831
|
+
}
|
|
832
|
+
const duration = spec.duration ?? parentDuration;
|
|
833
|
+
(spec.keyframes ?? []).forEach((kf, i) => {
|
|
834
|
+
const kat = kf.at ?? 0;
|
|
835
|
+
if (kat >= duration) {
|
|
836
|
+
warn(
|
|
837
|
+
`pixi-effects: ${who}: keyframes[${i}] starts at ${kat}s, after the layer ends (duration ${duration}s), so it never plays. Keyframe \`at\` is measured from the start of this layer, not from the start of the composition.`
|
|
838
|
+
);
|
|
839
|
+
}
|
|
840
|
+
});
|
|
841
|
+
}
|
|
842
|
+
function lintText(spec, warn = defaultWarn) {
|
|
843
|
+
if (spec.type !== "text") return;
|
|
844
|
+
if (collectPropKeys(spec).has("value") && !(spec.text ?? "").includes("{value}")) {
|
|
845
|
+
warn(`pixi-effects: ${describeLayer(spec)}: \`value\` is set or animated but the text has no {value} placeholder, so nothing shows it. Use text: '{value}' (or e.g. '{value} users').`);
|
|
846
|
+
}
|
|
847
|
+
}
|
|
848
|
+
|
|
792
849
|
// src/space/math.ts
|
|
793
850
|
var DEG = Math.PI / 180;
|
|
794
851
|
var DEFAULT_FOV = 40;
|
|
@@ -900,20 +957,6 @@ function projectLayer(t, frame, b) {
|
|
|
900
957
|
const origin = projectPoint(b, { x: t.x, y: t.y, z: t.z });
|
|
901
958
|
return { corners, depth: origin.depth, visible };
|
|
902
959
|
}
|
|
903
|
-
|
|
904
|
-
// src/space/specKeys.ts
|
|
905
|
-
function collectPropKeys(spec) {
|
|
906
|
-
const out = /* @__PURE__ */ new Set();
|
|
907
|
-
for (const k of Object.keys(spec.initial ?? {})) out.add(k);
|
|
908
|
-
for (const kf of spec.keyframes ?? []) {
|
|
909
|
-
for (const bag of [kf.set, kf.to, kf.from]) {
|
|
910
|
-
for (const k of Object.keys(bag ?? {})) out.add(k);
|
|
911
|
-
}
|
|
912
|
-
}
|
|
913
|
-
return out;
|
|
914
|
-
}
|
|
915
|
-
|
|
916
|
-
// src/space/CameraSequence.ts
|
|
917
960
|
var CameraSequence = class extends Sequence {
|
|
918
961
|
/** True when `z` is never specified anywhere: z then follows `fov`. */
|
|
919
962
|
autoZ = true;
|
|
@@ -1096,7 +1139,7 @@ function shortestHueDelta(from, to) {
|
|
|
1096
1139
|
}
|
|
1097
1140
|
|
|
1098
1141
|
// src/expr/colorTween.ts
|
|
1099
|
-
function tweenColor(timeline, target, key, fromValue, toValue, duration, ease, at, colorSpace, onUpdate) {
|
|
1142
|
+
function tweenColor(timeline, target, key, fromValue, toValue, duration, ease, at, colorSpace, onUpdate, loop = {}) {
|
|
1100
1143
|
let interp = null;
|
|
1101
1144
|
const proxy = { p: 0 };
|
|
1102
1145
|
timeline.fromTo(
|
|
@@ -1106,6 +1149,7 @@ function tweenColor(timeline, target, key, fromValue, toValue, duration, ease, a
|
|
|
1106
1149
|
p: 1,
|
|
1107
1150
|
duration,
|
|
1108
1151
|
ease,
|
|
1152
|
+
...loop,
|
|
1109
1153
|
onStart: () => {
|
|
1110
1154
|
const start = fromValue !== void 0 ? fromValue : target[key];
|
|
1111
1155
|
if (start === void 0) return;
|
|
@@ -1144,14 +1188,15 @@ var ImageSequence = class extends Sequence {
|
|
|
1144
1188
|
return;
|
|
1145
1189
|
}
|
|
1146
1190
|
const scope = this.scope();
|
|
1191
|
+
const startTime = offset + this.at;
|
|
1147
1192
|
const initial = stripKeys(this.spec.initial, ["tint"]);
|
|
1148
1193
|
const keyframes = this.spec.keyframes ? this.spec.keyframes.map((kf) => stripKeysInKeyframe(kf, ["tint"])) : void 0;
|
|
1149
1194
|
applyInitial(this.target, initial, scope);
|
|
1150
|
-
applyKeyframes(timeline, this.target, keyframes, this.duration, scope, [],
|
|
1195
|
+
applyKeyframes(timeline, this.target, keyframes, this.duration, scope, [], startTime);
|
|
1151
1196
|
const initTint = this.spec.initial?.tint;
|
|
1152
1197
|
if (initTint !== void 0) this.target.tint = initTint;
|
|
1153
1198
|
for (const kf of this.spec.keyframes ?? []) {
|
|
1154
|
-
const at =
|
|
1199
|
+
const at = startTime + resolveAt(kf.at, this.duration);
|
|
1155
1200
|
const duration = kf.duration ?? 0;
|
|
1156
1201
|
const ease = kf.ease ?? "none";
|
|
1157
1202
|
const fromTint = kf.from?.tint;
|
|
@@ -1172,11 +1217,12 @@ var ImageSequence = class extends Sequence {
|
|
|
1172
1217
|
duration,
|
|
1173
1218
|
ease,
|
|
1174
1219
|
at,
|
|
1175
|
-
colorSpace
|
|
1220
|
+
colorSpace,
|
|
1221
|
+
void 0,
|
|
1222
|
+
loopVars(kf)
|
|
1176
1223
|
);
|
|
1177
1224
|
}
|
|
1178
1225
|
}
|
|
1179
|
-
const startTime = offset + this.at;
|
|
1180
1226
|
this.absoluteStart = startTime;
|
|
1181
1227
|
const endTime = startTime + this.duration;
|
|
1182
1228
|
this.target.renderable = startTime <= 0;
|
|
@@ -1207,7 +1253,25 @@ function stripKeysInKeyframe(kf, keys) {
|
|
|
1207
1253
|
};
|
|
1208
1254
|
}
|
|
1209
1255
|
var STYLE_OPAQUE_KEYS = ["fontFamily", "fill", "align", "fontStyle", "fontWeight"];
|
|
1256
|
+
function formatValue(v, f) {
|
|
1257
|
+
const fixed = v.toFixed(Math.max(0, Math.floor(f?.decimals ?? 0)));
|
|
1258
|
+
if (!f?.grouping) return fixed;
|
|
1259
|
+
const [int, frac] = fixed.split(".");
|
|
1260
|
+
return int.replace(/\B(?=(\d{3})+(?!\d))/g, ",") + (frac !== void 0 ? "." + frac : "");
|
|
1261
|
+
}
|
|
1210
1262
|
var TextSequence = class extends Sequence {
|
|
1263
|
+
/** Current number for the `{value}` placeholder (tweened by `value` keyframes). */
|
|
1264
|
+
_value = { value: 0 };
|
|
1265
|
+
_lastText = "";
|
|
1266
|
+
/** Rewrite the displayed string from the template and the current `value`. */
|
|
1267
|
+
_refreshText() {
|
|
1268
|
+
const template = this.spec.text ?? "";
|
|
1269
|
+
if (!template.includes("{value}")) return;
|
|
1270
|
+
const next = template.split("{value}").join(formatValue(this._value.value, this.spec.format));
|
|
1271
|
+
if (next === this._lastText) return;
|
|
1272
|
+
this._lastText = next;
|
|
1273
|
+
this.target.text = next;
|
|
1274
|
+
}
|
|
1211
1275
|
async build() {
|
|
1212
1276
|
const baseStyle = {
|
|
1213
1277
|
fontFamily: "Arial",
|
|
@@ -1237,15 +1301,25 @@ var TextSequence = class extends Sequence {
|
|
|
1237
1301
|
for (const k of Object.keys(resolved)) {
|
|
1238
1302
|
text.style[k] = resolved[k];
|
|
1239
1303
|
}
|
|
1304
|
+
this.intrinsicWidth = text.width;
|
|
1305
|
+
this.intrinsicHeight = text.height;
|
|
1306
|
+
}
|
|
1307
|
+
const initialValue = this.spec.initial?.value;
|
|
1308
|
+
if (initialValue !== void 0) this._value.value = resolveNumber(initialValue, this.scope());
|
|
1309
|
+
this._refreshText();
|
|
1310
|
+
if (this._lastText !== "") {
|
|
1311
|
+
this.intrinsicWidth = text.width;
|
|
1312
|
+
this.intrinsicHeight = text.height;
|
|
1240
1313
|
}
|
|
1241
1314
|
this.buildFilters();
|
|
1242
1315
|
}
|
|
1243
1316
|
bindTimeline(timeline, offset = 0) {
|
|
1244
1317
|
if (!this.target) return;
|
|
1245
1318
|
const colorSpace = this.spec.colorSpace ?? "rgb";
|
|
1246
|
-
const stripped =
|
|
1319
|
+
const stripped = stripKeys2(this.spec, ["fill", "value"]);
|
|
1247
1320
|
runSuperWithStrippedSpec(this, stripped, timeline, offset);
|
|
1248
|
-
bindFillKeyframes(timeline, this.target, this.spec.keyframes ?? [], this.duration, offset, colorSpace);
|
|
1321
|
+
bindFillKeyframes(timeline, this.target, this.spec.keyframes ?? [], this.duration, offset + this.at, colorSpace);
|
|
1322
|
+
bindValueKeyframes(timeline, this._value, () => this._refreshText(), this.spec.keyframes ?? [], this.duration, offset + this.at, this.scope());
|
|
1249
1323
|
}
|
|
1250
1324
|
};
|
|
1251
1325
|
function runSuperWithStrippedSpec(inst, strippedSpec, timeline, offset) {
|
|
@@ -1257,25 +1331,61 @@ function runSuperWithStrippedSpec(inst, strippedSpec, timeline, offset) {
|
|
|
1257
1331
|
inst.spec = originalSpec;
|
|
1258
1332
|
}
|
|
1259
1333
|
}
|
|
1260
|
-
function
|
|
1334
|
+
function stripKeys2(spec, keys) {
|
|
1261
1335
|
return {
|
|
1262
1336
|
...spec,
|
|
1263
|
-
initial:
|
|
1337
|
+
initial: stripProps(spec.initial, keys),
|
|
1264
1338
|
keyframes: spec.keyframes ? spec.keyframes.map((kf) => ({
|
|
1265
1339
|
...kf,
|
|
1266
|
-
set:
|
|
1267
|
-
to:
|
|
1268
|
-
from:
|
|
1340
|
+
set: stripProps(kf.set, keys),
|
|
1341
|
+
to: stripProps(kf.to, keys),
|
|
1342
|
+
from: stripProps(kf.from, keys)
|
|
1269
1343
|
})) : void 0
|
|
1270
1344
|
};
|
|
1271
1345
|
}
|
|
1272
|
-
function
|
|
1346
|
+
function stripProps(props, keys) {
|
|
1273
1347
|
if (!props) return props;
|
|
1274
|
-
if (!(
|
|
1348
|
+
if (!keys.some((k) => k in props)) return props;
|
|
1275
1349
|
const out = {};
|
|
1276
|
-
for (const k of Object.keys(props)) if (k
|
|
1350
|
+
for (const k of Object.keys(props)) if (!keys.includes(k)) out[k] = props[k];
|
|
1277
1351
|
return out;
|
|
1278
1352
|
}
|
|
1353
|
+
function resolveNumber(v, scope) {
|
|
1354
|
+
if (typeof v === "number") return v;
|
|
1355
|
+
const out = normalizeProps({ v }, scope).v;
|
|
1356
|
+
return typeof out === "number" ? out : Number(out) || 0;
|
|
1357
|
+
}
|
|
1358
|
+
function bindValueKeyframes(timeline, state, refresh, keyframes, parentDuration, origin, scope) {
|
|
1359
|
+
for (const kf of keyframes) {
|
|
1360
|
+
const setV = kf.set?.value;
|
|
1361
|
+
const fromV = kf.from?.value;
|
|
1362
|
+
const toV = kf.to?.value;
|
|
1363
|
+
if (setV === void 0 && fromV === void 0 && toV === void 0) continue;
|
|
1364
|
+
const at = origin + resolveAt(kf.at, parentDuration);
|
|
1365
|
+
const duration = kf.duration ?? 0;
|
|
1366
|
+
const ease = kf.ease ?? "none";
|
|
1367
|
+
const loop = loopVars(kf);
|
|
1368
|
+
if (setV !== void 0) {
|
|
1369
|
+
const v = resolveNumber(setV, scope);
|
|
1370
|
+
timeline.call(() => {
|
|
1371
|
+
state.value = v;
|
|
1372
|
+
refresh();
|
|
1373
|
+
}, [], at);
|
|
1374
|
+
}
|
|
1375
|
+
if (toV !== void 0 && fromV !== void 0) {
|
|
1376
|
+
timeline.fromTo(
|
|
1377
|
+
state,
|
|
1378
|
+
{ value: resolveNumber(fromV, scope) },
|
|
1379
|
+
{ value: resolveNumber(toV, scope), duration, ease, ...loop, onUpdate: refresh },
|
|
1380
|
+
at
|
|
1381
|
+
);
|
|
1382
|
+
} else if (toV !== void 0) {
|
|
1383
|
+
timeline.to(state, { value: resolveNumber(toV, scope), duration, ease, ...loop, onUpdate: refresh }, at);
|
|
1384
|
+
} else if (fromV !== void 0) {
|
|
1385
|
+
timeline.from(state, { value: resolveNumber(fromV, scope), duration, ease, ...loop, onUpdate: refresh }, at);
|
|
1386
|
+
}
|
|
1387
|
+
}
|
|
1388
|
+
}
|
|
1279
1389
|
function bindFillKeyframes(timeline, text, keyframes, parentDuration, offset, colorSpace) {
|
|
1280
1390
|
const state = { fill: text.style.fill };
|
|
1281
1391
|
const writeFill = () => {
|
|
@@ -1305,7 +1415,8 @@ function bindFillKeyframes(timeline, text, keyframes, parentDuration, offset, co
|
|
|
1305
1415
|
ease,
|
|
1306
1416
|
at,
|
|
1307
1417
|
colorSpace,
|
|
1308
|
-
writeFill
|
|
1418
|
+
writeFill,
|
|
1419
|
+
loopVars(kf)
|
|
1309
1420
|
);
|
|
1310
1421
|
}
|
|
1311
1422
|
}
|
|
@@ -1324,6 +1435,11 @@ var AudioSequence = class extends Sequence {
|
|
|
1324
1435
|
if (this.duration === void 0) {
|
|
1325
1436
|
this.duration = this.spec.duration ?? data.duration ?? this.root.duration;
|
|
1326
1437
|
}
|
|
1438
|
+
if (!this.spec.loop && data.duration !== void 0 && this.duration > data.duration + 0.05) {
|
|
1439
|
+
console.warn(
|
|
1440
|
+
`pixi-effects: ${describeLayer(this.spec)}: audio asset "${this.spec.asset}" is ${data.duration.toFixed(1)}s but the layer lasts ${this.duration.toFixed(1)}s, so it goes silent after ${data.duration.toFixed(1)}s. Add loop: true, or shorten the layer's duration.`
|
|
1441
|
+
);
|
|
1442
|
+
}
|
|
1327
1443
|
this.target = null;
|
|
1328
1444
|
}
|
|
1329
1445
|
bindTimeline(_timeline) {
|
|
@@ -1493,14 +1609,15 @@ var VideoSequence = class extends Sequence {
|
|
|
1493
1609
|
});
|
|
1494
1610
|
this.buildFilters();
|
|
1495
1611
|
}
|
|
1496
|
-
bindTimeline(timeline) {
|
|
1497
|
-
super.bindTimeline(timeline);
|
|
1612
|
+
bindTimeline(timeline, offset = 0) {
|
|
1613
|
+
super.bindTimeline(timeline, offset);
|
|
1498
1614
|
const playDuration = this.spec.loop ? this.duration : Math.min(this.duration, this._sourceDuration);
|
|
1499
1615
|
timeline.fromTo(
|
|
1500
1616
|
this.target,
|
|
1501
1617
|
{ currentTime: 0 },
|
|
1502
1618
|
{ currentTime: playDuration, duration: playDuration, ease: "none" },
|
|
1503
|
-
this.at
|
|
1619
|
+
offset + this.at
|
|
1620
|
+
// offset = start of the enclosing composition(s); dropping it misplaced videos inside nested compositions
|
|
1504
1621
|
);
|
|
1505
1622
|
}
|
|
1506
1623
|
collectAudio(out, baseTime) {
|
|
@@ -1541,6 +1658,55 @@ var VideoSequence = class extends Sequence {
|
|
|
1541
1658
|
super.destroy();
|
|
1542
1659
|
}
|
|
1543
1660
|
};
|
|
1661
|
+
|
|
1662
|
+
// src/sequences/gradient.ts
|
|
1663
|
+
function cssColor(c) {
|
|
1664
|
+
return typeof c === "number" ? "#" + c.toString(16).padStart(6, "0") : c;
|
|
1665
|
+
}
|
|
1666
|
+
function normalizedStops(g) {
|
|
1667
|
+
const stops = g.stops ?? [];
|
|
1668
|
+
if (stops.length < 2) throw new Error('pixi-effects: fillGradient needs at least two colour stops, e.g. stops: [[0, "#000"], [1, "#fff"]]');
|
|
1669
|
+
return stops.map((s) => Array.isArray(s) ? { offset: s[0], color: s[1] } : { offset: s.offset, color: s.color });
|
|
1670
|
+
}
|
|
1671
|
+
function gradientOptions(g) {
|
|
1672
|
+
const colorStops = normalizedStops(g);
|
|
1673
|
+
const a = (g.angle ?? 90) * Math.PI / 180;
|
|
1674
|
+
const dx = Math.cos(a), dy = Math.sin(a);
|
|
1675
|
+
const h = (Math.abs(dx) + Math.abs(dy)) / 2;
|
|
1676
|
+
return {
|
|
1677
|
+
type: "linear",
|
|
1678
|
+
start: { x: 0.5 - dx * h, y: 0.5 - dy * h },
|
|
1679
|
+
end: { x: 0.5 + dx * h, y: 0.5 + dy * h },
|
|
1680
|
+
colorStops,
|
|
1681
|
+
textureSpace: "local"
|
|
1682
|
+
};
|
|
1683
|
+
}
|
|
1684
|
+
function paintRadial(ctx, size, g) {
|
|
1685
|
+
const stops = normalizedStops(g);
|
|
1686
|
+
const [cx, cy] = g.center ?? [0.5, 0.5];
|
|
1687
|
+
const grad = ctx.createRadialGradient(cx * size, cy * size, (g.innerRadius ?? 0) * size, cx * size, cy * size, (g.radius ?? 0.5) * size);
|
|
1688
|
+
for (const s of stops) grad.addColorStop(s.offset, cssColor(s.color));
|
|
1689
|
+
ctx.fillStyle = grad;
|
|
1690
|
+
ctx.fillRect(0, 0, size, size);
|
|
1691
|
+
}
|
|
1692
|
+
|
|
1693
|
+
// src/sequences/gradientFill.ts
|
|
1694
|
+
var RADIAL_SIZE = 256;
|
|
1695
|
+
function makeGradientFill(g) {
|
|
1696
|
+
if (g.type === "radial") {
|
|
1697
|
+
const canvas = document.createElement("canvas");
|
|
1698
|
+
canvas.width = RADIAL_SIZE;
|
|
1699
|
+
canvas.height = RADIAL_SIZE;
|
|
1700
|
+
const ctx = canvas.getContext("2d");
|
|
1701
|
+
if (ctx) {
|
|
1702
|
+
paintRadial(ctx, RADIAL_SIZE, g);
|
|
1703
|
+
return { texture: pixi_js.Texture.from(canvas), textureSpace: "local" };
|
|
1704
|
+
}
|
|
1705
|
+
}
|
|
1706
|
+
return new pixi_js.FillGradient(gradientOptions(g));
|
|
1707
|
+
}
|
|
1708
|
+
|
|
1709
|
+
// src/sequences/Shape.ts
|
|
1544
1710
|
var STYLE_KEYS = ["fillColor", "fillAlpha", "strokeColor", "strokeAlpha", "strokeWidth"];
|
|
1545
1711
|
var COLOR_KEYS = /* @__PURE__ */ new Set(["fillColor", "strokeColor"]);
|
|
1546
1712
|
var GEOMETRY_KEYS_BY_SHAPE = {
|
|
@@ -1578,6 +1744,8 @@ var ShapeSequence = class extends Sequence {
|
|
|
1578
1744
|
for (const k of geomKeys) this._liveKeys.add(k);
|
|
1579
1745
|
seedGeometry(this._state, this.spec, scope);
|
|
1580
1746
|
seedStyle(this._state, this.spec.initial ?? {}, scope);
|
|
1747
|
+
const gradientSpec = this.spec.fillGradient ?? this.spec.initial?.fillGradient;
|
|
1748
|
+
if (gradientSpec) this._state.fillStyle = makeGradientFill(gradientSpec);
|
|
1581
1749
|
this._drawGeometry = makeDrawGeometry(this.spec, scope, this._state);
|
|
1582
1750
|
this._drawGeometry(graphics);
|
|
1583
1751
|
applyState(graphics, this._state);
|
|
@@ -1585,7 +1753,12 @@ var ShapeSequence = class extends Sequence {
|
|
|
1585
1753
|
this.intrinsicWidth = bounds.width;
|
|
1586
1754
|
this.intrinsicHeight = bounds.height;
|
|
1587
1755
|
if (!ANCHORED_SHAPES.has(this.spec.shape)) {
|
|
1588
|
-
|
|
1756
|
+
const cx = bounds.x + bounds.width / 2;
|
|
1757
|
+
const cy = bounds.y + bounds.height / 2;
|
|
1758
|
+
graphics.pivot.set(cx, cy);
|
|
1759
|
+
const init = this.spec.initial ?? {};
|
|
1760
|
+
if (init.x === void 0) graphics.x = cx;
|
|
1761
|
+
if (init.y === void 0) graphics.y = cy;
|
|
1589
1762
|
}
|
|
1590
1763
|
graphics.onRender = () => {
|
|
1591
1764
|
graphics.clear();
|
|
@@ -1597,13 +1770,13 @@ var ShapeSequence = class extends Sequence {
|
|
|
1597
1770
|
bindTimeline(timeline, offset = 0) {
|
|
1598
1771
|
if (!this.target) return;
|
|
1599
1772
|
const scope = this.scope();
|
|
1600
|
-
const
|
|
1773
|
+
const startTime = offset + this.at;
|
|
1774
|
+
const initial = stripLive(stripGradient(this.spec.initial), this._liveKeys);
|
|
1601
1775
|
const keyframes = this.spec.keyframes ? this.spec.keyframes.map((kf) => stripLiveKeyframe(kf, this._liveKeys)) : void 0;
|
|
1602
1776
|
applyInitial(this.target, initial, scope);
|
|
1603
|
-
applyKeyframes(timeline, this.target, keyframes, this.duration, scope, [],
|
|
1777
|
+
applyKeyframes(timeline, this.target, keyframes, this.duration, scope, [], startTime);
|
|
1604
1778
|
const colorSpace = this.spec.colorSpace ?? "rgb";
|
|
1605
|
-
bindLiveKeyframes(timeline, this._state, this._liveKeys, this.spec.keyframes ?? [], this.duration, scope,
|
|
1606
|
-
const startTime = offset + this.at;
|
|
1779
|
+
bindLiveKeyframes(timeline, this._state, this._liveKeys, this.spec.keyframes ?? [], this.duration, scope, startTime, colorSpace);
|
|
1607
1780
|
this.absoluteStart = startTime;
|
|
1608
1781
|
const endTime = startTime + this.duration;
|
|
1609
1782
|
this.target.renderable = startTime <= 0;
|
|
@@ -1613,8 +1786,9 @@ var ShapeSequence = class extends Sequence {
|
|
|
1613
1786
|
};
|
|
1614
1787
|
function seedGeometry(state, spec, scope) {
|
|
1615
1788
|
const keys = GEOMETRY_KEYS_BY_SHAPE[spec.shape];
|
|
1789
|
+
const initial = spec.initial ?? {};
|
|
1616
1790
|
for (const k of keys) {
|
|
1617
|
-
const v = spec[k];
|
|
1791
|
+
const v = spec[k] ?? initial[k];
|
|
1618
1792
|
if (v !== void 0) state[k] = num(v, scope);
|
|
1619
1793
|
}
|
|
1620
1794
|
}
|
|
@@ -1625,6 +1799,11 @@ function seedStyle(state, initial, scope) {
|
|
|
1625
1799
|
state[k] = COLOR_KEYS.has(k) ? v : numOrZero(v, scope);
|
|
1626
1800
|
}
|
|
1627
1801
|
}
|
|
1802
|
+
function stripGradient(props) {
|
|
1803
|
+
if (!props || !("fillGradient" in props)) return props;
|
|
1804
|
+
const { fillGradient: _drop, ...rest } = props;
|
|
1805
|
+
return rest;
|
|
1806
|
+
}
|
|
1628
1807
|
function stripLive(props, liveKeys) {
|
|
1629
1808
|
if (!props) return props;
|
|
1630
1809
|
const out = {};
|
|
@@ -1663,7 +1842,9 @@ function resolveLiveValue(key, value, scope) {
|
|
|
1663
1842
|
return numOrZero(value, scope);
|
|
1664
1843
|
}
|
|
1665
1844
|
function applyState(g, s) {
|
|
1666
|
-
if (s.
|
|
1845
|
+
if (s.fillStyle) {
|
|
1846
|
+
g.fill(s.fillStyle);
|
|
1847
|
+
} else if (s.fillColor !== void 0) {
|
|
1667
1848
|
g.fill({ color: s.fillColor, alpha: s.fillAlpha });
|
|
1668
1849
|
}
|
|
1669
1850
|
if (s.strokeColor !== void 0 && s.strokeWidth > 0) {
|
|
@@ -1743,6 +1924,7 @@ function bindLiveKeyframes(timeline, state, liveKeys, keyframes, parentDuration,
|
|
|
1743
1924
|
const at = offset + resolveAt(kf.at, parentDuration);
|
|
1744
1925
|
const duration = kf.duration ?? 0;
|
|
1745
1926
|
const ease = kf.ease ?? "none";
|
|
1927
|
+
const loop = loopVars(kf);
|
|
1746
1928
|
if (kf.set) {
|
|
1747
1929
|
const live = pickLive(kf.set, liveKeys);
|
|
1748
1930
|
if (live) {
|
|
@@ -1766,11 +1948,11 @@ function bindLiveKeyframes(timeline, state, liveKeys, keyframes, parentDuration,
|
|
|
1766
1948
|
const toRaw = toLive?.[key];
|
|
1767
1949
|
const fromValue = fromRaw !== void 0 ? resolveLiveValue(key, fromRaw, scope) : void 0;
|
|
1768
1950
|
const toValue = toRaw !== void 0 ? resolveLiveValue(key, toRaw, scope) : void 0;
|
|
1769
|
-
tweenLiveKey(timeline, state, key, fromValue, toValue, duration, ease, at, colorSpace);
|
|
1951
|
+
tweenLiveKey(timeline, state, key, fromValue, toValue, duration, ease, at, colorSpace, loop);
|
|
1770
1952
|
}
|
|
1771
1953
|
}
|
|
1772
1954
|
}
|
|
1773
|
-
function tweenLiveKey(timeline, state, key, fromValue, toValue, duration, ease, at, colorSpace) {
|
|
1955
|
+
function tweenLiveKey(timeline, state, key, fromValue, toValue, duration, ease, at, colorSpace, loop) {
|
|
1774
1956
|
if (COLOR_KEYS.has(key) && toValue !== void 0) {
|
|
1775
1957
|
tweenColor(
|
|
1776
1958
|
timeline,
|
|
@@ -1781,13 +1963,15 @@ function tweenLiveKey(timeline, state, key, fromValue, toValue, duration, ease,
|
|
|
1781
1963
|
duration,
|
|
1782
1964
|
ease,
|
|
1783
1965
|
at,
|
|
1784
|
-
colorSpace
|
|
1966
|
+
colorSpace,
|
|
1967
|
+
void 0,
|
|
1968
|
+
loop
|
|
1785
1969
|
);
|
|
1786
1970
|
} else if (toValue !== void 0) {
|
|
1787
1971
|
if (fromValue !== void 0) {
|
|
1788
|
-
timeline.fromTo(state, { [key]: fromValue }, { [key]: toValue, duration, ease }, at);
|
|
1972
|
+
timeline.fromTo(state, { [key]: fromValue }, { [key]: toValue, duration, ease, ...loop }, at);
|
|
1789
1973
|
} else {
|
|
1790
|
-
timeline.to(state, { [key]: toValue, duration, ease }, at);
|
|
1974
|
+
timeline.to(state, { [key]: toValue, duration, ease, ...loop }, at);
|
|
1791
1975
|
}
|
|
1792
1976
|
}
|
|
1793
1977
|
}
|
|
@@ -1807,7 +1991,7 @@ function numOrZero(v, scope) {
|
|
|
1807
1991
|
var _CompositionSequence = null;
|
|
1808
1992
|
async function getCompositionSequence() {
|
|
1809
1993
|
if (!_CompositionSequence) {
|
|
1810
|
-
_CompositionSequence = (await import('./Composition-
|
|
1994
|
+
_CompositionSequence = (await import('./Composition-6FDH5OPM.cjs')).CompositionSequence;
|
|
1811
1995
|
}
|
|
1812
1996
|
return _CompositionSequence;
|
|
1813
1997
|
}
|
|
@@ -1845,16 +2029,21 @@ async function buildSequenceTree(specs, parent, root) {
|
|
|
1845
2029
|
}
|
|
1846
2030
|
|
|
1847
2031
|
exports.CameraSequence = CameraSequence;
|
|
2032
|
+
exports.DEFAULT_FOV = DEFAULT_FOV;
|
|
1848
2033
|
exports.DEG = DEG;
|
|
1849
2034
|
exports.Sequence = Sequence;
|
|
1850
2035
|
exports.buildScope = buildScope;
|
|
1851
2036
|
exports.buildSequenceTree = buildSequenceTree;
|
|
1852
2037
|
exports.cameraBasis = cameraBasis;
|
|
1853
2038
|
exports.collectPropKeys = collectPropKeys;
|
|
2039
|
+
exports.describeLayer = describeLayer;
|
|
1854
2040
|
exports.evaluateExpr = evaluateExpr;
|
|
1855
2041
|
exports.homeCamera = homeCamera;
|
|
2042
|
+
exports.homeDistance = homeDistance;
|
|
2043
|
+
exports.lintText = lintText;
|
|
2044
|
+
exports.lintTiming = lintTiming;
|
|
1856
2045
|
exports.projectLayer = projectLayer;
|
|
1857
2046
|
exports.registerSequenceType = registerSequenceType;
|
|
1858
2047
|
exports.resolveAt = resolveAt;
|
|
1859
|
-
//# sourceMappingURL=chunk-
|
|
1860
|
-
//# sourceMappingURL=chunk-
|
|
2048
|
+
//# sourceMappingURL=chunk-SIRVULFF.cjs.map
|
|
2049
|
+
//# sourceMappingURL=chunk-SIRVULFF.cjs.map
|