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
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Rectangle, Container, Graphics, Assets, Texture, Sprite, Text, Filter, GlProgram, defaultFilterVert, GpuProgram, UniformGroup, Color, GraphicsPath } from 'pixi.js';
|
|
1
|
+
import { Rectangle, Container, Graphics, Assets, Texture, Sprite, Text, Filter, GlProgram, defaultFilterVert, GpuProgram, UniformGroup, FillGradient, Color, GraphicsPath } from 'pixi.js';
|
|
2
2
|
import { gsap } from 'gsap';
|
|
3
3
|
|
|
4
4
|
// src/sequences/Base.ts
|
|
@@ -244,6 +244,23 @@ function looksLikeColorString(s) {
|
|
|
244
244
|
}
|
|
245
245
|
|
|
246
246
|
// src/core/Timeline.ts
|
|
247
|
+
function loopVars(kf) {
|
|
248
|
+
const out = {};
|
|
249
|
+
let repeat = 0;
|
|
250
|
+
if (kf.repeat !== void 0) {
|
|
251
|
+
if (Number.isFinite(kf.repeat) && kf.repeat >= 0) {
|
|
252
|
+
repeat = Math.floor(kf.repeat);
|
|
253
|
+
out.repeat = repeat;
|
|
254
|
+
} else {
|
|
255
|
+
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).`);
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
if (repeat > 0) {
|
|
259
|
+
if (kf.yoyo !== void 0) out.yoyo = kf.yoyo;
|
|
260
|
+
if (kf.repeatDelay !== void 0 && kf.repeatDelay > 0) out.repeatDelay = kf.repeatDelay;
|
|
261
|
+
}
|
|
262
|
+
return out;
|
|
263
|
+
}
|
|
247
264
|
function resolveAt(at, duration) {
|
|
248
265
|
if (at === void 0 || at === null) return 0;
|
|
249
266
|
return at < 0 ? duration + at : at;
|
|
@@ -261,7 +278,7 @@ function normalizeKeyframe(kf, parentDuration) {
|
|
|
261
278
|
else if (hasFrom) kind = "from";
|
|
262
279
|
else if (hasTo) kind = "to";
|
|
263
280
|
else kind = "to";
|
|
264
|
-
return { at, duration, ease, kind, set: kf.set, from: kf.from, to: kf.to };
|
|
281
|
+
return { at, duration, ease, loop: loopVars(kf), kind, set: kf.set, from: kf.from, to: kf.to };
|
|
265
282
|
}
|
|
266
283
|
function partitionProps(props) {
|
|
267
284
|
const ownProps = {};
|
|
@@ -371,27 +388,27 @@ function applyKeyframes(timeline, target, keyframes, parentDuration, scope, skip
|
|
|
371
388
|
const resolved = normalizeProps(kf.to, scope, { skipKeys });
|
|
372
389
|
const { rest, routed } = splitRouted(resolved, routers);
|
|
373
390
|
for (const r of routed)
|
|
374
|
-
timeline.to(r.target, { [r.prop]: r.value, duration: kf.duration, ease: kf.ease }, at);
|
|
391
|
+
timeline.to(r.target, { [r.prop]: r.value, duration: kf.duration, ease: kf.ease, ...kf.loop }, at);
|
|
375
392
|
const { ownProps, filterProps } = partitionProps(rest);
|
|
376
393
|
if (Object.keys(ownProps).length > 0)
|
|
377
|
-
timeline.to(target, { ...pixiwrap(ownProps), duration: kf.duration, ease: kf.ease }, at);
|
|
394
|
+
timeline.to(target, { ...pixiwrap(ownProps), duration: kf.duration, ease: kf.ease, ...kf.loop }, at);
|
|
378
395
|
for (const [name, props] of Object.entries(filterProps)) {
|
|
379
396
|
const f = findFilter(target, name);
|
|
380
397
|
if (!f) continue;
|
|
381
|
-
timeline.to(f, { ...props, duration: kf.duration, ease: kf.ease }, at);
|
|
398
|
+
timeline.to(f, { ...props, duration: kf.duration, ease: kf.ease, ...kf.loop }, at);
|
|
382
399
|
}
|
|
383
400
|
} else if (kf.kind === "from") {
|
|
384
401
|
const resolved = normalizeProps(kf.from, scope, { skipKeys });
|
|
385
402
|
const { rest, routed } = splitRouted(resolved, routers);
|
|
386
403
|
for (const r of routed)
|
|
387
|
-
timeline.from(r.target, { [r.prop]: r.value, duration: kf.duration, ease: kf.ease }, at);
|
|
404
|
+
timeline.from(r.target, { [r.prop]: r.value, duration: kf.duration, ease: kf.ease, ...kf.loop }, at);
|
|
388
405
|
const { ownProps, filterProps } = partitionProps(rest);
|
|
389
406
|
if (Object.keys(ownProps).length > 0)
|
|
390
|
-
timeline.from(target, { ...pixiwrap(ownProps), duration: kf.duration, ease: kf.ease }, at);
|
|
407
|
+
timeline.from(target, { ...pixiwrap(ownProps), duration: kf.duration, ease: kf.ease, ...kf.loop }, at);
|
|
391
408
|
for (const [name, props] of Object.entries(filterProps)) {
|
|
392
409
|
const f = findFilter(target, name);
|
|
393
410
|
if (!f) continue;
|
|
394
|
-
timeline.from(f, { ...props, duration: kf.duration, ease: kf.ease }, at);
|
|
411
|
+
timeline.from(f, { ...props, duration: kf.duration, ease: kf.ease, ...kf.loop }, at);
|
|
395
412
|
}
|
|
396
413
|
} else {
|
|
397
414
|
const fromResolved = normalizeProps(kf.from, scope, { skipKeys });
|
|
@@ -406,15 +423,15 @@ function applyKeyframes(timeline, target, keyframes, parentDuration, scope, skip
|
|
|
406
423
|
timeline.fromTo(
|
|
407
424
|
r.target,
|
|
408
425
|
{ [r.prop]: f.value },
|
|
409
|
-
{ [r.prop]: r.value, duration: kf.duration, ease: kf.ease },
|
|
426
|
+
{ [r.prop]: r.value, duration: kf.duration, ease: kf.ease, ...kf.loop },
|
|
410
427
|
at
|
|
411
428
|
);
|
|
412
429
|
} else {
|
|
413
|
-
timeline.to(r.target, { [r.prop]: r.value, duration: kf.duration, ease: kf.ease }, at);
|
|
430
|
+
timeline.to(r.target, { [r.prop]: r.value, duration: kf.duration, ease: kf.ease, ...kf.loop }, at);
|
|
414
431
|
}
|
|
415
432
|
}
|
|
416
433
|
for (const f of fromByKey.values())
|
|
417
|
-
timeline.from(f.target, { [f.prop]: f.value, duration: kf.duration, ease: kf.ease }, at);
|
|
434
|
+
timeline.from(f.target, { [f.prop]: f.value, duration: kf.duration, ease: kf.ease, ...kf.loop }, at);
|
|
418
435
|
const fromSplit = partitionProps(fromRouted.rest);
|
|
419
436
|
const toSplit = partitionProps(toRouted.rest);
|
|
420
437
|
const ownKeys = /* @__PURE__ */ new Set([...Object.keys(fromSplit.ownProps), ...Object.keys(toSplit.ownProps)]);
|
|
@@ -422,7 +439,7 @@ function applyKeyframes(timeline, target, keyframes, parentDuration, scope, skip
|
|
|
422
439
|
timeline.fromTo(
|
|
423
440
|
target,
|
|
424
441
|
{ ...pixiwrap(fromSplit.ownProps) },
|
|
425
|
-
{ ...pixiwrap(toSplit.ownProps), duration: kf.duration, ease: kf.ease },
|
|
442
|
+
{ ...pixiwrap(toSplit.ownProps), duration: kf.duration, ease: kf.ease, ...kf.loop },
|
|
426
443
|
at
|
|
427
444
|
);
|
|
428
445
|
}
|
|
@@ -436,7 +453,7 @@ function applyKeyframes(timeline, target, keyframes, parentDuration, scope, skip
|
|
|
436
453
|
timeline.fromTo(
|
|
437
454
|
f,
|
|
438
455
|
{ ...fromSplit.filterProps[name] ?? {} },
|
|
439
|
-
{ ...toSplit.filterProps[name] ?? {}, duration: kf.duration, ease: kf.ease },
|
|
456
|
+
{ ...toSplit.filterProps[name] ?? {}, duration: kf.duration, ease: kf.ease, ...kf.loop },
|
|
440
457
|
at
|
|
441
458
|
);
|
|
442
459
|
}
|
|
@@ -761,9 +778,9 @@ var Sequence = class {
|
|
|
761
778
|
if (!this.target) return;
|
|
762
779
|
const scope = this.scope();
|
|
763
780
|
const routers = this.pathRouters();
|
|
764
|
-
applyInitial(this.target, this.spec.initial, scope, [], routers);
|
|
765
|
-
applyKeyframes(timeline, this.target, this.spec.keyframes, this.duration, scope, [], offset, routers);
|
|
766
781
|
const startTime = offset + this.at;
|
|
782
|
+
applyInitial(this.target, this.spec.initial, scope, [], routers);
|
|
783
|
+
applyKeyframes(timeline, this.target, this.spec.keyframes, this.duration, scope, [], startTime, routers);
|
|
767
784
|
const endTime = startTime + this.duration;
|
|
768
785
|
this.absoluteStart = startTime;
|
|
769
786
|
this.target.renderable = startTime <= 0;
|
|
@@ -787,6 +804,46 @@ var Sequence = class {
|
|
|
787
804
|
}
|
|
788
805
|
};
|
|
789
806
|
|
|
807
|
+
// src/space/specKeys.ts
|
|
808
|
+
function collectPropKeys(spec) {
|
|
809
|
+
const out = /* @__PURE__ */ new Set();
|
|
810
|
+
for (const k of Object.keys(spec.initial ?? {})) out.add(k);
|
|
811
|
+
for (const kf of spec.keyframes ?? []) {
|
|
812
|
+
for (const bag of [kf.set, kf.to, kf.from]) {
|
|
813
|
+
for (const k of Object.keys(bag ?? {})) out.add(k);
|
|
814
|
+
}
|
|
815
|
+
}
|
|
816
|
+
return out;
|
|
817
|
+
}
|
|
818
|
+
|
|
819
|
+
// src/core/lint.ts
|
|
820
|
+
var defaultWarn = (m) => console.warn(m);
|
|
821
|
+
function describeLayer(spec) {
|
|
822
|
+
return spec.name ? `layer "${spec.name}"` : `unnamed ${spec.type} layer`;
|
|
823
|
+
}
|
|
824
|
+
function lintTiming(spec, parentDuration, warn = defaultWarn) {
|
|
825
|
+
const who = describeLayer(spec);
|
|
826
|
+
const at = spec.at ?? 0;
|
|
827
|
+
if (at >= parentDuration) {
|
|
828
|
+
warn(`pixi-effects: ${who} starts at ${at}s, after its composition ends (${parentDuration}s), so it is never visible`);
|
|
829
|
+
}
|
|
830
|
+
const duration = spec.duration ?? parentDuration;
|
|
831
|
+
(spec.keyframes ?? []).forEach((kf, i) => {
|
|
832
|
+
const kat = kf.at ?? 0;
|
|
833
|
+
if (kat >= duration) {
|
|
834
|
+
warn(
|
|
835
|
+
`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.`
|
|
836
|
+
);
|
|
837
|
+
}
|
|
838
|
+
});
|
|
839
|
+
}
|
|
840
|
+
function lintText(spec, warn = defaultWarn) {
|
|
841
|
+
if (spec.type !== "text") return;
|
|
842
|
+
if (collectPropKeys(spec).has("value") && !(spec.text ?? "").includes("{value}")) {
|
|
843
|
+
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').`);
|
|
844
|
+
}
|
|
845
|
+
}
|
|
846
|
+
|
|
790
847
|
// src/space/math.ts
|
|
791
848
|
var DEG = Math.PI / 180;
|
|
792
849
|
var DEFAULT_FOV = 40;
|
|
@@ -898,20 +955,6 @@ function projectLayer(t, frame, b) {
|
|
|
898
955
|
const origin = projectPoint(b, { x: t.x, y: t.y, z: t.z });
|
|
899
956
|
return { corners, depth: origin.depth, visible };
|
|
900
957
|
}
|
|
901
|
-
|
|
902
|
-
// src/space/specKeys.ts
|
|
903
|
-
function collectPropKeys(spec) {
|
|
904
|
-
const out = /* @__PURE__ */ new Set();
|
|
905
|
-
for (const k of Object.keys(spec.initial ?? {})) out.add(k);
|
|
906
|
-
for (const kf of spec.keyframes ?? []) {
|
|
907
|
-
for (const bag of [kf.set, kf.to, kf.from]) {
|
|
908
|
-
for (const k of Object.keys(bag ?? {})) out.add(k);
|
|
909
|
-
}
|
|
910
|
-
}
|
|
911
|
-
return out;
|
|
912
|
-
}
|
|
913
|
-
|
|
914
|
-
// src/space/CameraSequence.ts
|
|
915
958
|
var CameraSequence = class extends Sequence {
|
|
916
959
|
/** True when `z` is never specified anywhere: z then follows `fov`. */
|
|
917
960
|
autoZ = true;
|
|
@@ -1094,7 +1137,7 @@ function shortestHueDelta(from, to) {
|
|
|
1094
1137
|
}
|
|
1095
1138
|
|
|
1096
1139
|
// src/expr/colorTween.ts
|
|
1097
|
-
function tweenColor(timeline, target, key, fromValue, toValue, duration, ease, at, colorSpace, onUpdate) {
|
|
1140
|
+
function tweenColor(timeline, target, key, fromValue, toValue, duration, ease, at, colorSpace, onUpdate, loop = {}) {
|
|
1098
1141
|
let interp = null;
|
|
1099
1142
|
const proxy = { p: 0 };
|
|
1100
1143
|
timeline.fromTo(
|
|
@@ -1104,6 +1147,7 @@ function tweenColor(timeline, target, key, fromValue, toValue, duration, ease, a
|
|
|
1104
1147
|
p: 1,
|
|
1105
1148
|
duration,
|
|
1106
1149
|
ease,
|
|
1150
|
+
...loop,
|
|
1107
1151
|
onStart: () => {
|
|
1108
1152
|
const start = fromValue !== void 0 ? fromValue : target[key];
|
|
1109
1153
|
if (start === void 0) return;
|
|
@@ -1142,14 +1186,15 @@ var ImageSequence = class extends Sequence {
|
|
|
1142
1186
|
return;
|
|
1143
1187
|
}
|
|
1144
1188
|
const scope = this.scope();
|
|
1189
|
+
const startTime = offset + this.at;
|
|
1145
1190
|
const initial = stripKeys(this.spec.initial, ["tint"]);
|
|
1146
1191
|
const keyframes = this.spec.keyframes ? this.spec.keyframes.map((kf) => stripKeysInKeyframe(kf, ["tint"])) : void 0;
|
|
1147
1192
|
applyInitial(this.target, initial, scope);
|
|
1148
|
-
applyKeyframes(timeline, this.target, keyframes, this.duration, scope, [],
|
|
1193
|
+
applyKeyframes(timeline, this.target, keyframes, this.duration, scope, [], startTime);
|
|
1149
1194
|
const initTint = this.spec.initial?.tint;
|
|
1150
1195
|
if (initTint !== void 0) this.target.tint = initTint;
|
|
1151
1196
|
for (const kf of this.spec.keyframes ?? []) {
|
|
1152
|
-
const at =
|
|
1197
|
+
const at = startTime + resolveAt(kf.at, this.duration);
|
|
1153
1198
|
const duration = kf.duration ?? 0;
|
|
1154
1199
|
const ease = kf.ease ?? "none";
|
|
1155
1200
|
const fromTint = kf.from?.tint;
|
|
@@ -1170,11 +1215,12 @@ var ImageSequence = class extends Sequence {
|
|
|
1170
1215
|
duration,
|
|
1171
1216
|
ease,
|
|
1172
1217
|
at,
|
|
1173
|
-
colorSpace
|
|
1218
|
+
colorSpace,
|
|
1219
|
+
void 0,
|
|
1220
|
+
loopVars(kf)
|
|
1174
1221
|
);
|
|
1175
1222
|
}
|
|
1176
1223
|
}
|
|
1177
|
-
const startTime = offset + this.at;
|
|
1178
1224
|
this.absoluteStart = startTime;
|
|
1179
1225
|
const endTime = startTime + this.duration;
|
|
1180
1226
|
this.target.renderable = startTime <= 0;
|
|
@@ -1205,7 +1251,25 @@ function stripKeysInKeyframe(kf, keys) {
|
|
|
1205
1251
|
};
|
|
1206
1252
|
}
|
|
1207
1253
|
var STYLE_OPAQUE_KEYS = ["fontFamily", "fill", "align", "fontStyle", "fontWeight"];
|
|
1254
|
+
function formatValue(v, f) {
|
|
1255
|
+
const fixed = v.toFixed(Math.max(0, Math.floor(f?.decimals ?? 0)));
|
|
1256
|
+
if (!f?.grouping) return fixed;
|
|
1257
|
+
const [int, frac] = fixed.split(".");
|
|
1258
|
+
return int.replace(/\B(?=(\d{3})+(?!\d))/g, ",") + (frac !== void 0 ? "." + frac : "");
|
|
1259
|
+
}
|
|
1208
1260
|
var TextSequence = class extends Sequence {
|
|
1261
|
+
/** Current number for the `{value}` placeholder (tweened by `value` keyframes). */
|
|
1262
|
+
_value = { value: 0 };
|
|
1263
|
+
_lastText = "";
|
|
1264
|
+
/** Rewrite the displayed string from the template and the current `value`. */
|
|
1265
|
+
_refreshText() {
|
|
1266
|
+
const template = this.spec.text ?? "";
|
|
1267
|
+
if (!template.includes("{value}")) return;
|
|
1268
|
+
const next = template.split("{value}").join(formatValue(this._value.value, this.spec.format));
|
|
1269
|
+
if (next === this._lastText) return;
|
|
1270
|
+
this._lastText = next;
|
|
1271
|
+
this.target.text = next;
|
|
1272
|
+
}
|
|
1209
1273
|
async build() {
|
|
1210
1274
|
const baseStyle = {
|
|
1211
1275
|
fontFamily: "Arial",
|
|
@@ -1235,15 +1299,25 @@ var TextSequence = class extends Sequence {
|
|
|
1235
1299
|
for (const k of Object.keys(resolved)) {
|
|
1236
1300
|
text.style[k] = resolved[k];
|
|
1237
1301
|
}
|
|
1302
|
+
this.intrinsicWidth = text.width;
|
|
1303
|
+
this.intrinsicHeight = text.height;
|
|
1304
|
+
}
|
|
1305
|
+
const initialValue = this.spec.initial?.value;
|
|
1306
|
+
if (initialValue !== void 0) this._value.value = resolveNumber(initialValue, this.scope());
|
|
1307
|
+
this._refreshText();
|
|
1308
|
+
if (this._lastText !== "") {
|
|
1309
|
+
this.intrinsicWidth = text.width;
|
|
1310
|
+
this.intrinsicHeight = text.height;
|
|
1238
1311
|
}
|
|
1239
1312
|
this.buildFilters();
|
|
1240
1313
|
}
|
|
1241
1314
|
bindTimeline(timeline, offset = 0) {
|
|
1242
1315
|
if (!this.target) return;
|
|
1243
1316
|
const colorSpace = this.spec.colorSpace ?? "rgb";
|
|
1244
|
-
const stripped =
|
|
1317
|
+
const stripped = stripKeys2(this.spec, ["fill", "value"]);
|
|
1245
1318
|
runSuperWithStrippedSpec(this, stripped, timeline, offset);
|
|
1246
|
-
bindFillKeyframes(timeline, this.target, this.spec.keyframes ?? [], this.duration, offset, colorSpace);
|
|
1319
|
+
bindFillKeyframes(timeline, this.target, this.spec.keyframes ?? [], this.duration, offset + this.at, colorSpace);
|
|
1320
|
+
bindValueKeyframes(timeline, this._value, () => this._refreshText(), this.spec.keyframes ?? [], this.duration, offset + this.at, this.scope());
|
|
1247
1321
|
}
|
|
1248
1322
|
};
|
|
1249
1323
|
function runSuperWithStrippedSpec(inst, strippedSpec, timeline, offset) {
|
|
@@ -1255,25 +1329,61 @@ function runSuperWithStrippedSpec(inst, strippedSpec, timeline, offset) {
|
|
|
1255
1329
|
inst.spec = originalSpec;
|
|
1256
1330
|
}
|
|
1257
1331
|
}
|
|
1258
|
-
function
|
|
1332
|
+
function stripKeys2(spec, keys) {
|
|
1259
1333
|
return {
|
|
1260
1334
|
...spec,
|
|
1261
|
-
initial:
|
|
1335
|
+
initial: stripProps(spec.initial, keys),
|
|
1262
1336
|
keyframes: spec.keyframes ? spec.keyframes.map((kf) => ({
|
|
1263
1337
|
...kf,
|
|
1264
|
-
set:
|
|
1265
|
-
to:
|
|
1266
|
-
from:
|
|
1338
|
+
set: stripProps(kf.set, keys),
|
|
1339
|
+
to: stripProps(kf.to, keys),
|
|
1340
|
+
from: stripProps(kf.from, keys)
|
|
1267
1341
|
})) : void 0
|
|
1268
1342
|
};
|
|
1269
1343
|
}
|
|
1270
|
-
function
|
|
1344
|
+
function stripProps(props, keys) {
|
|
1271
1345
|
if (!props) return props;
|
|
1272
|
-
if (!(
|
|
1346
|
+
if (!keys.some((k) => k in props)) return props;
|
|
1273
1347
|
const out = {};
|
|
1274
|
-
for (const k of Object.keys(props)) if (k
|
|
1348
|
+
for (const k of Object.keys(props)) if (!keys.includes(k)) out[k] = props[k];
|
|
1275
1349
|
return out;
|
|
1276
1350
|
}
|
|
1351
|
+
function resolveNumber(v, scope) {
|
|
1352
|
+
if (typeof v === "number") return v;
|
|
1353
|
+
const out = normalizeProps({ v }, scope).v;
|
|
1354
|
+
return typeof out === "number" ? out : Number(out) || 0;
|
|
1355
|
+
}
|
|
1356
|
+
function bindValueKeyframes(timeline, state, refresh, keyframes, parentDuration, origin, scope) {
|
|
1357
|
+
for (const kf of keyframes) {
|
|
1358
|
+
const setV = kf.set?.value;
|
|
1359
|
+
const fromV = kf.from?.value;
|
|
1360
|
+
const toV = kf.to?.value;
|
|
1361
|
+
if (setV === void 0 && fromV === void 0 && toV === void 0) continue;
|
|
1362
|
+
const at = origin + resolveAt(kf.at, parentDuration);
|
|
1363
|
+
const duration = kf.duration ?? 0;
|
|
1364
|
+
const ease = kf.ease ?? "none";
|
|
1365
|
+
const loop = loopVars(kf);
|
|
1366
|
+
if (setV !== void 0) {
|
|
1367
|
+
const v = resolveNumber(setV, scope);
|
|
1368
|
+
timeline.call(() => {
|
|
1369
|
+
state.value = v;
|
|
1370
|
+
refresh();
|
|
1371
|
+
}, [], at);
|
|
1372
|
+
}
|
|
1373
|
+
if (toV !== void 0 && fromV !== void 0) {
|
|
1374
|
+
timeline.fromTo(
|
|
1375
|
+
state,
|
|
1376
|
+
{ value: resolveNumber(fromV, scope) },
|
|
1377
|
+
{ value: resolveNumber(toV, scope), duration, ease, ...loop, onUpdate: refresh },
|
|
1378
|
+
at
|
|
1379
|
+
);
|
|
1380
|
+
} else if (toV !== void 0) {
|
|
1381
|
+
timeline.to(state, { value: resolveNumber(toV, scope), duration, ease, ...loop, onUpdate: refresh }, at);
|
|
1382
|
+
} else if (fromV !== void 0) {
|
|
1383
|
+
timeline.from(state, { value: resolveNumber(fromV, scope), duration, ease, ...loop, onUpdate: refresh }, at);
|
|
1384
|
+
}
|
|
1385
|
+
}
|
|
1386
|
+
}
|
|
1277
1387
|
function bindFillKeyframes(timeline, text, keyframes, parentDuration, offset, colorSpace) {
|
|
1278
1388
|
const state = { fill: text.style.fill };
|
|
1279
1389
|
const writeFill = () => {
|
|
@@ -1303,7 +1413,8 @@ function bindFillKeyframes(timeline, text, keyframes, parentDuration, offset, co
|
|
|
1303
1413
|
ease,
|
|
1304
1414
|
at,
|
|
1305
1415
|
colorSpace,
|
|
1306
|
-
writeFill
|
|
1416
|
+
writeFill,
|
|
1417
|
+
loopVars(kf)
|
|
1307
1418
|
);
|
|
1308
1419
|
}
|
|
1309
1420
|
}
|
|
@@ -1322,6 +1433,11 @@ var AudioSequence = class extends Sequence {
|
|
|
1322
1433
|
if (this.duration === void 0) {
|
|
1323
1434
|
this.duration = this.spec.duration ?? data.duration ?? this.root.duration;
|
|
1324
1435
|
}
|
|
1436
|
+
if (!this.spec.loop && data.duration !== void 0 && this.duration > data.duration + 0.05) {
|
|
1437
|
+
console.warn(
|
|
1438
|
+
`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.`
|
|
1439
|
+
);
|
|
1440
|
+
}
|
|
1325
1441
|
this.target = null;
|
|
1326
1442
|
}
|
|
1327
1443
|
bindTimeline(_timeline) {
|
|
@@ -1491,14 +1607,15 @@ var VideoSequence = class extends Sequence {
|
|
|
1491
1607
|
});
|
|
1492
1608
|
this.buildFilters();
|
|
1493
1609
|
}
|
|
1494
|
-
bindTimeline(timeline) {
|
|
1495
|
-
super.bindTimeline(timeline);
|
|
1610
|
+
bindTimeline(timeline, offset = 0) {
|
|
1611
|
+
super.bindTimeline(timeline, offset);
|
|
1496
1612
|
const playDuration = this.spec.loop ? this.duration : Math.min(this.duration, this._sourceDuration);
|
|
1497
1613
|
timeline.fromTo(
|
|
1498
1614
|
this.target,
|
|
1499
1615
|
{ currentTime: 0 },
|
|
1500
1616
|
{ currentTime: playDuration, duration: playDuration, ease: "none" },
|
|
1501
|
-
this.at
|
|
1617
|
+
offset + this.at
|
|
1618
|
+
// offset = start of the enclosing composition(s); dropping it misplaced videos inside nested compositions
|
|
1502
1619
|
);
|
|
1503
1620
|
}
|
|
1504
1621
|
collectAudio(out, baseTime) {
|
|
@@ -1539,6 +1656,55 @@ var VideoSequence = class extends Sequence {
|
|
|
1539
1656
|
super.destroy();
|
|
1540
1657
|
}
|
|
1541
1658
|
};
|
|
1659
|
+
|
|
1660
|
+
// src/sequences/gradient.ts
|
|
1661
|
+
function cssColor(c) {
|
|
1662
|
+
return typeof c === "number" ? "#" + c.toString(16).padStart(6, "0") : c;
|
|
1663
|
+
}
|
|
1664
|
+
function normalizedStops(g) {
|
|
1665
|
+
const stops = g.stops ?? [];
|
|
1666
|
+
if (stops.length < 2) throw new Error('pixi-effects: fillGradient needs at least two colour stops, e.g. stops: [[0, "#000"], [1, "#fff"]]');
|
|
1667
|
+
return stops.map((s) => Array.isArray(s) ? { offset: s[0], color: s[1] } : { offset: s.offset, color: s.color });
|
|
1668
|
+
}
|
|
1669
|
+
function gradientOptions(g) {
|
|
1670
|
+
const colorStops = normalizedStops(g);
|
|
1671
|
+
const a = (g.angle ?? 90) * Math.PI / 180;
|
|
1672
|
+
const dx = Math.cos(a), dy = Math.sin(a);
|
|
1673
|
+
const h = (Math.abs(dx) + Math.abs(dy)) / 2;
|
|
1674
|
+
return {
|
|
1675
|
+
type: "linear",
|
|
1676
|
+
start: { x: 0.5 - dx * h, y: 0.5 - dy * h },
|
|
1677
|
+
end: { x: 0.5 + dx * h, y: 0.5 + dy * h },
|
|
1678
|
+
colorStops,
|
|
1679
|
+
textureSpace: "local"
|
|
1680
|
+
};
|
|
1681
|
+
}
|
|
1682
|
+
function paintRadial(ctx, size, g) {
|
|
1683
|
+
const stops = normalizedStops(g);
|
|
1684
|
+
const [cx, cy] = g.center ?? [0.5, 0.5];
|
|
1685
|
+
const grad = ctx.createRadialGradient(cx * size, cy * size, (g.innerRadius ?? 0) * size, cx * size, cy * size, (g.radius ?? 0.5) * size);
|
|
1686
|
+
for (const s of stops) grad.addColorStop(s.offset, cssColor(s.color));
|
|
1687
|
+
ctx.fillStyle = grad;
|
|
1688
|
+
ctx.fillRect(0, 0, size, size);
|
|
1689
|
+
}
|
|
1690
|
+
|
|
1691
|
+
// src/sequences/gradientFill.ts
|
|
1692
|
+
var RADIAL_SIZE = 256;
|
|
1693
|
+
function makeGradientFill(g) {
|
|
1694
|
+
if (g.type === "radial") {
|
|
1695
|
+
const canvas = document.createElement("canvas");
|
|
1696
|
+
canvas.width = RADIAL_SIZE;
|
|
1697
|
+
canvas.height = RADIAL_SIZE;
|
|
1698
|
+
const ctx = canvas.getContext("2d");
|
|
1699
|
+
if (ctx) {
|
|
1700
|
+
paintRadial(ctx, RADIAL_SIZE, g);
|
|
1701
|
+
return { texture: Texture.from(canvas), textureSpace: "local" };
|
|
1702
|
+
}
|
|
1703
|
+
}
|
|
1704
|
+
return new FillGradient(gradientOptions(g));
|
|
1705
|
+
}
|
|
1706
|
+
|
|
1707
|
+
// src/sequences/Shape.ts
|
|
1542
1708
|
var STYLE_KEYS = ["fillColor", "fillAlpha", "strokeColor", "strokeAlpha", "strokeWidth"];
|
|
1543
1709
|
var COLOR_KEYS = /* @__PURE__ */ new Set(["fillColor", "strokeColor"]);
|
|
1544
1710
|
var GEOMETRY_KEYS_BY_SHAPE = {
|
|
@@ -1576,6 +1742,8 @@ var ShapeSequence = class extends Sequence {
|
|
|
1576
1742
|
for (const k of geomKeys) this._liveKeys.add(k);
|
|
1577
1743
|
seedGeometry(this._state, this.spec, scope);
|
|
1578
1744
|
seedStyle(this._state, this.spec.initial ?? {}, scope);
|
|
1745
|
+
const gradientSpec = this.spec.fillGradient ?? this.spec.initial?.fillGradient;
|
|
1746
|
+
if (gradientSpec) this._state.fillStyle = makeGradientFill(gradientSpec);
|
|
1579
1747
|
this._drawGeometry = makeDrawGeometry(this.spec, scope, this._state);
|
|
1580
1748
|
this._drawGeometry(graphics);
|
|
1581
1749
|
applyState(graphics, this._state);
|
|
@@ -1583,7 +1751,12 @@ var ShapeSequence = class extends Sequence {
|
|
|
1583
1751
|
this.intrinsicWidth = bounds.width;
|
|
1584
1752
|
this.intrinsicHeight = bounds.height;
|
|
1585
1753
|
if (!ANCHORED_SHAPES.has(this.spec.shape)) {
|
|
1586
|
-
|
|
1754
|
+
const cx = bounds.x + bounds.width / 2;
|
|
1755
|
+
const cy = bounds.y + bounds.height / 2;
|
|
1756
|
+
graphics.pivot.set(cx, cy);
|
|
1757
|
+
const init = this.spec.initial ?? {};
|
|
1758
|
+
if (init.x === void 0) graphics.x = cx;
|
|
1759
|
+
if (init.y === void 0) graphics.y = cy;
|
|
1587
1760
|
}
|
|
1588
1761
|
graphics.onRender = () => {
|
|
1589
1762
|
graphics.clear();
|
|
@@ -1595,13 +1768,13 @@ var ShapeSequence = class extends Sequence {
|
|
|
1595
1768
|
bindTimeline(timeline, offset = 0) {
|
|
1596
1769
|
if (!this.target) return;
|
|
1597
1770
|
const scope = this.scope();
|
|
1598
|
-
const
|
|
1771
|
+
const startTime = offset + this.at;
|
|
1772
|
+
const initial = stripLive(stripGradient(this.spec.initial), this._liveKeys);
|
|
1599
1773
|
const keyframes = this.spec.keyframes ? this.spec.keyframes.map((kf) => stripLiveKeyframe(kf, this._liveKeys)) : void 0;
|
|
1600
1774
|
applyInitial(this.target, initial, scope);
|
|
1601
|
-
applyKeyframes(timeline, this.target, keyframes, this.duration, scope, [],
|
|
1775
|
+
applyKeyframes(timeline, this.target, keyframes, this.duration, scope, [], startTime);
|
|
1602
1776
|
const colorSpace = this.spec.colorSpace ?? "rgb";
|
|
1603
|
-
bindLiveKeyframes(timeline, this._state, this._liveKeys, this.spec.keyframes ?? [], this.duration, scope,
|
|
1604
|
-
const startTime = offset + this.at;
|
|
1777
|
+
bindLiveKeyframes(timeline, this._state, this._liveKeys, this.spec.keyframes ?? [], this.duration, scope, startTime, colorSpace);
|
|
1605
1778
|
this.absoluteStart = startTime;
|
|
1606
1779
|
const endTime = startTime + this.duration;
|
|
1607
1780
|
this.target.renderable = startTime <= 0;
|
|
@@ -1611,8 +1784,9 @@ var ShapeSequence = class extends Sequence {
|
|
|
1611
1784
|
};
|
|
1612
1785
|
function seedGeometry(state, spec, scope) {
|
|
1613
1786
|
const keys = GEOMETRY_KEYS_BY_SHAPE[spec.shape];
|
|
1787
|
+
const initial = spec.initial ?? {};
|
|
1614
1788
|
for (const k of keys) {
|
|
1615
|
-
const v = spec[k];
|
|
1789
|
+
const v = spec[k] ?? initial[k];
|
|
1616
1790
|
if (v !== void 0) state[k] = num(v, scope);
|
|
1617
1791
|
}
|
|
1618
1792
|
}
|
|
@@ -1623,6 +1797,11 @@ function seedStyle(state, initial, scope) {
|
|
|
1623
1797
|
state[k] = COLOR_KEYS.has(k) ? v : numOrZero(v, scope);
|
|
1624
1798
|
}
|
|
1625
1799
|
}
|
|
1800
|
+
function stripGradient(props) {
|
|
1801
|
+
if (!props || !("fillGradient" in props)) return props;
|
|
1802
|
+
const { fillGradient: _drop, ...rest } = props;
|
|
1803
|
+
return rest;
|
|
1804
|
+
}
|
|
1626
1805
|
function stripLive(props, liveKeys) {
|
|
1627
1806
|
if (!props) return props;
|
|
1628
1807
|
const out = {};
|
|
@@ -1661,7 +1840,9 @@ function resolveLiveValue(key, value, scope) {
|
|
|
1661
1840
|
return numOrZero(value, scope);
|
|
1662
1841
|
}
|
|
1663
1842
|
function applyState(g, s) {
|
|
1664
|
-
if (s.
|
|
1843
|
+
if (s.fillStyle) {
|
|
1844
|
+
g.fill(s.fillStyle);
|
|
1845
|
+
} else if (s.fillColor !== void 0) {
|
|
1665
1846
|
g.fill({ color: s.fillColor, alpha: s.fillAlpha });
|
|
1666
1847
|
}
|
|
1667
1848
|
if (s.strokeColor !== void 0 && s.strokeWidth > 0) {
|
|
@@ -1741,6 +1922,7 @@ function bindLiveKeyframes(timeline, state, liveKeys, keyframes, parentDuration,
|
|
|
1741
1922
|
const at = offset + resolveAt(kf.at, parentDuration);
|
|
1742
1923
|
const duration = kf.duration ?? 0;
|
|
1743
1924
|
const ease = kf.ease ?? "none";
|
|
1925
|
+
const loop = loopVars(kf);
|
|
1744
1926
|
if (kf.set) {
|
|
1745
1927
|
const live = pickLive(kf.set, liveKeys);
|
|
1746
1928
|
if (live) {
|
|
@@ -1764,11 +1946,11 @@ function bindLiveKeyframes(timeline, state, liveKeys, keyframes, parentDuration,
|
|
|
1764
1946
|
const toRaw = toLive?.[key];
|
|
1765
1947
|
const fromValue = fromRaw !== void 0 ? resolveLiveValue(key, fromRaw, scope) : void 0;
|
|
1766
1948
|
const toValue = toRaw !== void 0 ? resolveLiveValue(key, toRaw, scope) : void 0;
|
|
1767
|
-
tweenLiveKey(timeline, state, key, fromValue, toValue, duration, ease, at, colorSpace);
|
|
1949
|
+
tweenLiveKey(timeline, state, key, fromValue, toValue, duration, ease, at, colorSpace, loop);
|
|
1768
1950
|
}
|
|
1769
1951
|
}
|
|
1770
1952
|
}
|
|
1771
|
-
function tweenLiveKey(timeline, state, key, fromValue, toValue, duration, ease, at, colorSpace) {
|
|
1953
|
+
function tweenLiveKey(timeline, state, key, fromValue, toValue, duration, ease, at, colorSpace, loop) {
|
|
1772
1954
|
if (COLOR_KEYS.has(key) && toValue !== void 0) {
|
|
1773
1955
|
tweenColor(
|
|
1774
1956
|
timeline,
|
|
@@ -1779,13 +1961,15 @@ function tweenLiveKey(timeline, state, key, fromValue, toValue, duration, ease,
|
|
|
1779
1961
|
duration,
|
|
1780
1962
|
ease,
|
|
1781
1963
|
at,
|
|
1782
|
-
colorSpace
|
|
1964
|
+
colorSpace,
|
|
1965
|
+
void 0,
|
|
1966
|
+
loop
|
|
1783
1967
|
);
|
|
1784
1968
|
} else if (toValue !== void 0) {
|
|
1785
1969
|
if (fromValue !== void 0) {
|
|
1786
|
-
timeline.fromTo(state, { [key]: fromValue }, { [key]: toValue, duration, ease }, at);
|
|
1970
|
+
timeline.fromTo(state, { [key]: fromValue }, { [key]: toValue, duration, ease, ...loop }, at);
|
|
1787
1971
|
} else {
|
|
1788
|
-
timeline.to(state, { [key]: toValue, duration, ease }, at);
|
|
1972
|
+
timeline.to(state, { [key]: toValue, duration, ease, ...loop }, at);
|
|
1789
1973
|
}
|
|
1790
1974
|
}
|
|
1791
1975
|
}
|
|
@@ -1805,7 +1989,7 @@ function numOrZero(v, scope) {
|
|
|
1805
1989
|
var _CompositionSequence = null;
|
|
1806
1990
|
async function getCompositionSequence() {
|
|
1807
1991
|
if (!_CompositionSequence) {
|
|
1808
|
-
_CompositionSequence = (await import('./Composition-
|
|
1992
|
+
_CompositionSequence = (await import('./Composition-FEYAUMFI.js')).CompositionSequence;
|
|
1809
1993
|
}
|
|
1810
1994
|
return _CompositionSequence;
|
|
1811
1995
|
}
|
|
@@ -1842,6 +2026,6 @@ async function buildSequenceTree(specs, parent, root) {
|
|
|
1842
2026
|
return out;
|
|
1843
2027
|
}
|
|
1844
2028
|
|
|
1845
|
-
export { CameraSequence, DEG, Sequence, buildScope, buildSequenceTree, cameraBasis, collectPropKeys, evaluateExpr, homeCamera, projectLayer, registerSequenceType, resolveAt };
|
|
1846
|
-
//# sourceMappingURL=chunk-
|
|
1847
|
-
//# sourceMappingURL=chunk-
|
|
2029
|
+
export { CameraSequence, DEFAULT_FOV, DEG, Sequence, buildScope, buildSequenceTree, cameraBasis, collectPropKeys, describeLayer, evaluateExpr, homeCamera, homeDistance, lintText, lintTiming, projectLayer, registerSequenceType, resolveAt };
|
|
2030
|
+
//# sourceMappingURL=chunk-PN5A6QA7.js.map
|
|
2031
|
+
//# sourceMappingURL=chunk-PN5A6QA7.js.map
|