pixi-effects 0.3.0 → 0.5.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 +53 -0
- package/README.md +10 -6
- package/ai/SKILL.md +9 -4
- package/ai/reference/cheatsheet.md +19 -7
- package/ai/reference/pitfalls.md +32 -7
- package/ai/reference/recipes.md +117 -0
- package/ai/template.html +6 -3
- package/ai/tools/check.mjs +385 -0
- package/dist/{Base-BDw6dKRB.d.cts → Base-CPSFBkPm.d.ts} +12 -1
- package/dist/{Base-Ba4Ta4ap.d.ts → Base-DnRAxroQ.d.cts} +12 -1
- package/dist/Composition-63EXHNJJ.cjs +13 -0
- package/dist/{Composition-6FDH5OPM.cjs.map → Composition-63EXHNJJ.cjs.map} +1 -1
- package/dist/Composition-TUCRSMJU.js +4 -0
- package/dist/{Composition-FEYAUMFI.js.map → Composition-TUCRSMJU.js.map} +1 -1
- package/dist/Controller.cjs +37 -13
- package/dist/Controller.cjs.map +1 -1
- package/dist/Controller.d.cts +4 -2
- package/dist/Controller.d.ts +4 -2
- package/dist/Controller.js +37 -13
- package/dist/Controller.js.map +1 -1
- package/dist/{Movie-W8ISiEBB.d.cts → Movie-CuU_aaCm.d.cts} +56 -2
- package/dist/{Movie-DMpaT67V.d.ts → Movie-VyDiUYOj.d.ts} +56 -2
- package/dist/{chunk-ZL262ZRM.cjs → chunk-23M5QTWW.cjs} +70 -20
- package/dist/chunk-23M5QTWW.cjs.map +1 -0
- package/dist/{chunk-SIRVULFF.cjs → chunk-2RR43OIN.cjs} +256 -60
- package/dist/chunk-2RR43OIN.cjs.map +1 -0
- package/dist/{chunk-DIJG2RSF.js → chunk-5Q5XZG7Z.js} +59 -9
- package/dist/chunk-5Q5XZG7Z.js.map +1 -0
- package/dist/chunk-DKGG7WD4.js +61 -0
- package/dist/chunk-DKGG7WD4.js.map +1 -0
- package/dist/{chunk-PN5A6QA7.js → chunk-UBPZLGLU.js} +255 -61
- package/dist/chunk-UBPZLGLU.js.map +1 -0
- package/dist/chunk-UQBGW5DO.cjs +64 -0
- package/dist/chunk-UQBGW5DO.cjs.map +1 -0
- package/dist/index.cjs +336 -89
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +54 -5
- package/dist/index.d.ts +54 -5
- package/dist/index.js +320 -75
- package/dist/index.js.map +1 -1
- package/dist/sfx-MZJZXYY3.cjs +446 -0
- package/dist/sfx-MZJZXYY3.cjs.map +1 -0
- package/dist/sfx-S37DDC66.js +434 -0
- package/dist/sfx-S37DDC66.js.map +1 -0
- 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-3c8Vymgw.d.ts → types-7VtTEKUW.d.cts} +102 -6
- package/dist/{types-3c8Vymgw.d.cts → types-7VtTEKUW.d.ts} +102 -6
- package/docs/api.md +36 -0
- package/docs/dsl.md +56 -4
- package/llms-full.txt +268 -21
- package/llms.txt +1 -1
- package/package.json +3 -1
- package/dist/Composition-6FDH5OPM.cjs +0 -13
- package/dist/Composition-FEYAUMFI.js +0 -4
- package/dist/chunk-DIJG2RSF.js.map +0 -1
- package/dist/chunk-PN5A6QA7.js.map +0 -1
- package/dist/chunk-SIRVULFF.cjs.map +0 -1
- package/dist/chunk-ZL262ZRM.cjs.map +0 -1
|
@@ -741,6 +741,11 @@ var Sequence = class {
|
|
|
741
741
|
* (not a normal child) by PIXI when `target.mask = maskSequence.target`.
|
|
742
742
|
*/
|
|
743
743
|
maskSequence = null;
|
|
744
|
+
/**
|
|
745
|
+
* Set by the parent composition on a sprite-based (image / video) mask. PIXI hides such a mask with
|
|
746
|
+
* `renderable = false`; the lifespan toggles must not switch it back on, or the mask is drawn as a picture.
|
|
747
|
+
*/
|
|
748
|
+
keepHidden = false;
|
|
744
749
|
/**
|
|
745
750
|
* Absolute start time on the global timeline (offset + at), recorded by
|
|
746
751
|
* bindTimeline. Movie._awaitVideoFrames uses it to determine the correct
|
|
@@ -785,6 +790,7 @@ var Sequence = class {
|
|
|
785
790
|
applyKeyframes(timeline, this.target, this.spec.keyframes, this.duration, scope, [], startTime, routers);
|
|
786
791
|
const endTime = startTime + this.duration;
|
|
787
792
|
this.absoluteStart = startTime;
|
|
793
|
+
if (this.keepHidden) return;
|
|
788
794
|
this.target.renderable = startTime <= 0;
|
|
789
795
|
timeline.set(this.target, { renderable: true }, startTime);
|
|
790
796
|
timeline.set(this.target, { renderable: false }, endTime);
|
|
@@ -798,6 +804,14 @@ var Sequence = class {
|
|
|
798
804
|
*/
|
|
799
805
|
updateSpace(_t, _host) {
|
|
800
806
|
}
|
|
807
|
+
/**
|
|
808
|
+
* Runs once per rendered frame, after the timeline seek and before the cull. Layers whose drawn
|
|
809
|
+
* geometry follows tweened state (shapes) redraw here, so the culler measures where the layer is NOW
|
|
810
|
+
* and not where it was drawn at the previous render.
|
|
811
|
+
*/
|
|
812
|
+
syncFrame() {
|
|
813
|
+
this.maskSequence?.syncFrame();
|
|
814
|
+
}
|
|
801
815
|
destroy() {
|
|
802
816
|
this.maskSequence?.destroy();
|
|
803
817
|
this.maskSequence = null;
|
|
@@ -829,18 +843,27 @@ function lintTiming(spec, parentDuration, warn = defaultWarn) {
|
|
|
829
843
|
if (at >= parentDuration) {
|
|
830
844
|
warn(`pixi-effects: ${who} starts at ${at}s, after its composition ends (${parentDuration}s), so it is never visible`);
|
|
831
845
|
}
|
|
846
|
+
if (spec.type === "audio" && spec.sfx !== void 0 && spec.duration === void 0) return;
|
|
832
847
|
const duration = spec.duration ?? parentDuration;
|
|
833
848
|
(spec.keyframes ?? []).forEach((kf, i) => {
|
|
834
849
|
const kat = kf.at ?? 0;
|
|
835
850
|
if (kat >= duration) {
|
|
836
851
|
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
|
|
852
|
+
`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.`,
|
|
853
|
+
"late-keyframe"
|
|
838
854
|
);
|
|
839
855
|
}
|
|
840
856
|
});
|
|
841
857
|
}
|
|
858
|
+
function summarizeWarnings(messages, shown = 3) {
|
|
859
|
+
if (messages.length <= shown) return messages;
|
|
860
|
+
return [...messages.slice(0, shown), `pixi-effects: ${messages.length - shown} more layers with the same problem (the same loop or helper is probably building them): fix the ones above and these go away.`];
|
|
861
|
+
}
|
|
842
862
|
function lintText(spec, warn = defaultWarn) {
|
|
843
863
|
if (spec.type !== "text") return;
|
|
864
|
+
if ((spec.text ?? "").includes("{value}") && !collectPropKeys(spec).has("value")) {
|
|
865
|
+
warn(`pixi-effects: ${describeLayer(spec)}: the text has a {value} placeholder but nothing sets or animates \`value\`, so it prints 0. Set initial: { value: \u2026 } or animate it; {value} is reserved for counters (there is no way to print a literal "{value}").`);
|
|
866
|
+
}
|
|
844
867
|
if (collectPropKeys(spec).has("value") && !(spec.text ?? "").includes("{value}")) {
|
|
845
868
|
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
869
|
}
|
|
@@ -1013,7 +1036,30 @@ var CameraSequence = class extends Sequence {
|
|
|
1013
1036
|
}
|
|
1014
1037
|
};
|
|
1015
1038
|
|
|
1039
|
+
// src/core/revertibleSet.ts
|
|
1040
|
+
function revertibleSet(timeline, at, read, write, value) {
|
|
1041
|
+
let p = 0;
|
|
1042
|
+
let before;
|
|
1043
|
+
const proxy = {
|
|
1044
|
+
get p() {
|
|
1045
|
+
return p;
|
|
1046
|
+
},
|
|
1047
|
+
set p(next) {
|
|
1048
|
+
if (next >= 1 && p < 1) {
|
|
1049
|
+
before = read();
|
|
1050
|
+
write(value);
|
|
1051
|
+
} else if (next < 1 && p >= 1) {
|
|
1052
|
+
write(before);
|
|
1053
|
+
}
|
|
1054
|
+
p = next;
|
|
1055
|
+
}
|
|
1056
|
+
};
|
|
1057
|
+
timeline.set(proxy, { p: 1 }, at);
|
|
1058
|
+
}
|
|
1059
|
+
|
|
1016
1060
|
// src/expr/colorInterp.ts
|
|
1061
|
+
var CHROMA_FLOOR = 0.03;
|
|
1062
|
+
var CHROMA_FULL = 0.08;
|
|
1017
1063
|
function buildColorInterp(from, to, space) {
|
|
1018
1064
|
const fromRGBA = parseToRGBA(from);
|
|
1019
1065
|
const toRGBA = parseToRGBA(to);
|
|
@@ -1030,8 +1076,9 @@ function buildColorInterp(from, to, space) {
|
|
|
1030
1076
|
}
|
|
1031
1077
|
const fromLCH = oklabToOklch(fromOk);
|
|
1032
1078
|
const toLCH = oklabToOklch(toOk);
|
|
1033
|
-
|
|
1034
|
-
|
|
1079
|
+
const fromHue = fromLCH.h, toHue = toLCH.h;
|
|
1080
|
+
fromLCH.h = borrowHue(fromHue, fromLCH.C, toHue);
|
|
1081
|
+
toLCH.h = borrowHue(toHue, toLCH.C, fromHue);
|
|
1035
1082
|
const hueDelta = shortestHueDelta(fromLCH.h, toLCH.h);
|
|
1036
1083
|
return (t) => {
|
|
1037
1084
|
const L = lerp(fromLCH.L, toLCH.L, t);
|
|
@@ -1042,6 +1089,11 @@ function buildColorInterp(from, to, space) {
|
|
|
1042
1089
|
return rgbaString(oklabToRgb(ab), alpha);
|
|
1043
1090
|
};
|
|
1044
1091
|
}
|
|
1092
|
+
function borrowHue(own, chroma, other) {
|
|
1093
|
+
const u = Math.min(1, Math.max(0, (chroma - CHROMA_FLOOR) / (CHROMA_FULL - CHROMA_FLOOR)));
|
|
1094
|
+
const keep = u * u * (3 - 2 * u);
|
|
1095
|
+
return own + shortestHueDelta(own, other) * (1 - keep);
|
|
1096
|
+
}
|
|
1045
1097
|
function parseToRGBA(input) {
|
|
1046
1098
|
if (typeof input === "number") {
|
|
1047
1099
|
return { r: (input >> 16 & 255) / 255, g: (input >> 8 & 255) / 255, b: (input & 255) / 255, a: 1 };
|
|
@@ -1203,9 +1255,10 @@ var ImageSequence = class extends Sequence {
|
|
|
1203
1255
|
const toTint = kf.to?.tint;
|
|
1204
1256
|
const setTint = kf.set?.tint;
|
|
1205
1257
|
if (setTint !== void 0) {
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
1258
|
+
const sprite = this.target;
|
|
1259
|
+
revertibleSet(timeline, at, () => sprite.tint, (c) => {
|
|
1260
|
+
sprite.tint = c;
|
|
1261
|
+
}, setTint);
|
|
1209
1262
|
}
|
|
1210
1263
|
if (toTint !== void 0) {
|
|
1211
1264
|
tweenColor(
|
|
@@ -1225,6 +1278,7 @@ var ImageSequence = class extends Sequence {
|
|
|
1225
1278
|
}
|
|
1226
1279
|
this.absoluteStart = startTime;
|
|
1227
1280
|
const endTime = startTime + this.duration;
|
|
1281
|
+
if (this.keepHidden) return;
|
|
1228
1282
|
this.target.renderable = startTime <= 0;
|
|
1229
1283
|
timeline.set(this.target, { renderable: true }, startTime);
|
|
1230
1284
|
timeline.set(this.target, { renderable: false }, endTime);
|
|
@@ -1252,12 +1306,31 @@ function stripKeysInKeyframe(kf, keys) {
|
|
|
1252
1306
|
from: stripKeys(kf.from, keys)
|
|
1253
1307
|
};
|
|
1254
1308
|
}
|
|
1255
|
-
var STYLE_OPAQUE_KEYS = [
|
|
1309
|
+
var STYLE_OPAQUE_KEYS = [
|
|
1310
|
+
"fontFamily",
|
|
1311
|
+
"fill",
|
|
1312
|
+
"align",
|
|
1313
|
+
"fontStyle",
|
|
1314
|
+
"fontWeight",
|
|
1315
|
+
"fontVariant",
|
|
1316
|
+
"textBaseline",
|
|
1317
|
+
"whiteSpace",
|
|
1318
|
+
"lineJoin",
|
|
1319
|
+
"join",
|
|
1320
|
+
"cap",
|
|
1321
|
+
"color",
|
|
1322
|
+
"stroke"
|
|
1323
|
+
];
|
|
1256
1324
|
function formatValue(v, f) {
|
|
1257
1325
|
const fixed = v.toFixed(Math.max(0, Math.floor(f?.decimals ?? 0)));
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
|
-
|
|
1326
|
+
const pad = Math.max(0, Math.floor(f?.pad ?? 0));
|
|
1327
|
+
if (!f?.grouping && !pad) return fixed;
|
|
1328
|
+
const [signed, frac] = fixed.split(".");
|
|
1329
|
+
const sign = signed.startsWith("-") ? "-" : "";
|
|
1330
|
+
let int = sign ? signed.slice(1) : signed;
|
|
1331
|
+
if (pad) int = int.padStart(pad, "0");
|
|
1332
|
+
if (f?.grouping) int = int.replace(/\B(?=(\d{3})+(?!\d))/g, ",");
|
|
1333
|
+
return sign + int + (frac !== void 0 ? "." + frac : "");
|
|
1261
1334
|
}
|
|
1262
1335
|
var TextSequence = class extends Sequence {
|
|
1263
1336
|
/** Current number for the `{value}` placeholder (tweened by `value` keyframes). */
|
|
@@ -1367,10 +1440,10 @@ function bindValueKeyframes(timeline, state, refresh, keyframes, parentDuration,
|
|
|
1367
1440
|
const loop = loopVars(kf);
|
|
1368
1441
|
if (setV !== void 0) {
|
|
1369
1442
|
const v = resolveNumber(setV, scope);
|
|
1370
|
-
timeline.
|
|
1371
|
-
state.value =
|
|
1443
|
+
revertibleSet(timeline, at, () => state.value, (n) => {
|
|
1444
|
+
state.value = n;
|
|
1372
1445
|
refresh();
|
|
1373
|
-
},
|
|
1446
|
+
}, v);
|
|
1374
1447
|
}
|
|
1375
1448
|
if (toV !== void 0 && fromV !== void 0) {
|
|
1376
1449
|
timeline.fromTo(
|
|
@@ -1399,10 +1472,10 @@ function bindFillKeyframes(timeline, text, keyframes, parentDuration, offset, co
|
|
|
1399
1472
|
const fromFill = pickFill(kf.from);
|
|
1400
1473
|
const toFill = pickFill(kf.to);
|
|
1401
1474
|
if (setFill !== void 0) {
|
|
1402
|
-
timeline.
|
|
1403
|
-
state.fill =
|
|
1475
|
+
revertibleSet(timeline, at, () => state.fill, (c) => {
|
|
1476
|
+
state.fill = c;
|
|
1404
1477
|
writeFill();
|
|
1405
|
-
},
|
|
1478
|
+
}, setFill);
|
|
1406
1479
|
}
|
|
1407
1480
|
if (toFill !== void 0) {
|
|
1408
1481
|
tweenColor(
|
|
@@ -1429,54 +1502,96 @@ function pickFill(props) {
|
|
|
1429
1502
|
}
|
|
1430
1503
|
var AudioSequence = class extends Sequence {
|
|
1431
1504
|
_audioBuffer = null;
|
|
1505
|
+
_synth = null;
|
|
1506
|
+
_source = "";
|
|
1432
1507
|
async build() {
|
|
1433
|
-
|
|
1508
|
+
this.target = null;
|
|
1509
|
+
if (this.spec.sfx !== void 0) return this._buildSfx(this.spec);
|
|
1510
|
+
const spec = this.spec;
|
|
1511
|
+
this._source = `asset "${spec.asset}"`;
|
|
1512
|
+
const data = await pixi_js.Assets.get(spec.asset);
|
|
1434
1513
|
this._audioBuffer = data.audioBuffer;
|
|
1435
1514
|
if (this.duration === void 0) {
|
|
1436
|
-
|
|
1515
|
+
const rest = Math.max(0, (this.parent?.duration ?? this.root.duration) - this.at);
|
|
1516
|
+
this.duration = spec.duration ?? (spec.loop ? rest : data.duration) ?? this.root.duration;
|
|
1437
1517
|
}
|
|
1438
|
-
if (!
|
|
1518
|
+
if (!spec.loop && data.duration !== void 0 && this.duration > data.duration + 0.05) {
|
|
1439
1519
|
console.warn(
|
|
1440
|
-
`pixi-effects: ${describeLayer(
|
|
1520
|
+
`pixi-effects: ${describeLayer(spec)}: audio asset "${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
1521
|
);
|
|
1442
1522
|
}
|
|
1443
|
-
|
|
1523
|
+
}
|
|
1524
|
+
async _buildSfx(spec) {
|
|
1525
|
+
const who = describeLayer(spec);
|
|
1526
|
+
const raw = spec;
|
|
1527
|
+
if (raw.asset !== void 0) console.warn(`pixi-effects: ${who}: has both asset and sfx \u2014 the sfx plays; remove one`);
|
|
1528
|
+
if (raw.loop) console.warn(`pixi-effects: ${who}: loop has no effect on an sfx \u2014 to repeat it, add one audio layer per hit (a JS loop)`);
|
|
1529
|
+
const { resolveSfx, renderSfx, sfxKey } = await import('./sfx-MZJZXYY3.cjs');
|
|
1530
|
+
const sfx = resolveSfx(spec.sfx, spec.duration, who);
|
|
1531
|
+
if (!sfx) return;
|
|
1532
|
+
this.duration = sfx.length;
|
|
1533
|
+
this._source = `sfx "${sfx.preset ?? "custom"}"`;
|
|
1534
|
+
this._synth = { key: sfxKey(sfx), render: (sr) => renderSfx(sfx, sr) };
|
|
1535
|
+
(spec.keyframes ?? []).forEach((kf, i) => {
|
|
1536
|
+
if ((kf.at ?? 0) >= sfx.length) {
|
|
1537
|
+
console.warn(`pixi-effects: ${who}: keyframes[${i}] starts at ${kf.at}s, after the sound ends (${sfx.length}s), so it never plays`);
|
|
1538
|
+
} else if ((kf.at ?? 0) < 0 && sfx.length + (kf.at ?? 0) < 0) {
|
|
1539
|
+
console.warn(`pixi-effects: ${who}: keyframes[${i}] starts ${-kf.at}s before the END of a ${sfx.length}s sound, which is before the sound begins (a negative \`at\` counts back from the end of the layer). Use a shorter \`at\`, or stretch the sound with \`duration\`.`);
|
|
1540
|
+
}
|
|
1541
|
+
});
|
|
1444
1542
|
}
|
|
1445
1543
|
bindTimeline(_timeline) {
|
|
1446
1544
|
}
|
|
1447
1545
|
collectAudio(out, baseTime) {
|
|
1448
|
-
if (!this._audioBuffer) return;
|
|
1449
|
-
const initialVolume = this.spec.volume ?? 1;
|
|
1450
|
-
const
|
|
1546
|
+
if (!this._audioBuffer && !this._synth) return;
|
|
1547
|
+
const initialVolume = this.spec.volume ?? this.spec.initial?.volume ?? 1;
|
|
1548
|
+
const t0 = baseTime + this.at;
|
|
1451
1549
|
const dur = this.duration;
|
|
1452
|
-
for (const raw of this.spec.keyframes ?? []) {
|
|
1453
|
-
const kf = normalizeKeyframe(raw, dur);
|
|
1454
|
-
const set = kf.set;
|
|
1455
|
-
const to = kf.to;
|
|
1456
|
-
const from = kf.from;
|
|
1457
|
-
if (kf.kind === "set" && set && "volume" in set) {
|
|
1458
|
-
volumeKeyframes.push({ time: baseTime + this.at + kf.at, value: set.volume });
|
|
1459
|
-
} else if (kf.kind === "to" && to && "volume" in to) {
|
|
1460
|
-
volumeKeyframes.push({ time: baseTime + this.at + kf.at + kf.duration, value: to.volume });
|
|
1461
|
-
} else if (kf.kind === "fromTo" && to && "volume" in to) {
|
|
1462
|
-
volumeKeyframes.push({ time: baseTime + this.at + kf.at, value: from?.volume ?? initialVolume });
|
|
1463
|
-
volumeKeyframes.push({ time: baseTime + this.at + kf.at + kf.duration, value: to.volume });
|
|
1464
|
-
} else if (kf.kind === "from" && from && "volume" in from) {
|
|
1465
|
-
volumeKeyframes.push({ time: baseTime + this.at + kf.at, value: from.volume });
|
|
1466
|
-
volumeKeyframes.push({ time: baseTime + this.at + kf.at + kf.duration, value: initialVolume });
|
|
1467
|
-
}
|
|
1468
|
-
}
|
|
1469
1550
|
out.push({
|
|
1470
|
-
buffer: this._audioBuffer,
|
|
1471
|
-
|
|
1472
|
-
|
|
1473
|
-
|
|
1551
|
+
...this._audioBuffer ? { buffer: this._audioBuffer } : { synth: this._synth },
|
|
1552
|
+
layer: describeLayer(this.spec),
|
|
1553
|
+
source: this._source,
|
|
1554
|
+
loop: !this._synth && !!this.spec.loop,
|
|
1555
|
+
start: t0,
|
|
1556
|
+
end: t0 + dur,
|
|
1474
1557
|
initialVolume,
|
|
1475
|
-
volumeKeyframes
|
|
1558
|
+
volumeKeyframes: this._volumePoints(t0, dur, initialVolume)
|
|
1476
1559
|
});
|
|
1477
1560
|
}
|
|
1561
|
+
_volumePoints(t0, dur, initialVolume) {
|
|
1562
|
+
const volumeKeyframes = [];
|
|
1563
|
+
const keyframes = (this.spec.keyframes ?? []).map((raw) => normalizeKeyframe(raw, dur)).filter((kf) => [kf.set, kf.to, kf.from].some((p) => p && "volume" in p)).sort((x, y) => x.at - y.at);
|
|
1564
|
+
let current = initialVolume;
|
|
1565
|
+
const point = (time, value) => {
|
|
1566
|
+
volumeKeyframes.push({ time, value });
|
|
1567
|
+
};
|
|
1568
|
+
for (const kf of keyframes) {
|
|
1569
|
+
const start = t0 + kf.at;
|
|
1570
|
+
const end = start + kf.duration;
|
|
1571
|
+
const set = kf.set?.volume;
|
|
1572
|
+
const to = kf.to?.volume;
|
|
1573
|
+
const from = kf.from?.volume;
|
|
1574
|
+
point(start, current);
|
|
1575
|
+
if (kf.kind === "set" && set !== void 0) {
|
|
1576
|
+
point(start, set);
|
|
1577
|
+
current = set;
|
|
1578
|
+
} else if (kf.kind === "to" && to !== void 0) {
|
|
1579
|
+
point(end, to);
|
|
1580
|
+
current = to;
|
|
1581
|
+
} else if (kf.kind === "fromTo" && to !== void 0) {
|
|
1582
|
+
point(start, from ?? current);
|
|
1583
|
+
point(end, to);
|
|
1584
|
+
current = to;
|
|
1585
|
+
} else if (kf.kind === "from" && from !== void 0) {
|
|
1586
|
+
point(start, from);
|
|
1587
|
+
point(end, current);
|
|
1588
|
+
}
|
|
1589
|
+
}
|
|
1590
|
+
return volumeKeyframes;
|
|
1591
|
+
}
|
|
1478
1592
|
destroy() {
|
|
1479
1593
|
this._audioBuffer = null;
|
|
1594
|
+
this._synth = null;
|
|
1480
1595
|
}
|
|
1481
1596
|
};
|
|
1482
1597
|
|
|
@@ -1625,6 +1740,8 @@ var VideoSequence = class extends Sequence {
|
|
|
1625
1740
|
const initialVolume = this.spec.volume ?? 1;
|
|
1626
1741
|
out.push({
|
|
1627
1742
|
buffer: this._audioBuffer,
|
|
1743
|
+
layer: describeLayer(this.spec),
|
|
1744
|
+
source: `video "${this.spec.asset}"`,
|
|
1628
1745
|
loop: !!this.spec.loop,
|
|
1629
1746
|
start: baseTime + this.at,
|
|
1630
1747
|
end: baseTime + this.at + this.duration,
|
|
@@ -1713,11 +1830,12 @@ var GEOMETRY_KEYS_BY_SHAPE = {
|
|
|
1713
1830
|
rect: ["width", "height", "cornerRadius", "anchorX", "anchorY"],
|
|
1714
1831
|
circle: ["radius", "anchorX", "anchorY"],
|
|
1715
1832
|
ellipse: ["radiusX", "radiusY", "anchorX", "anchorY"],
|
|
1833
|
+
arc: ["radius", "innerRadius", "startAngle", "endAngle"],
|
|
1716
1834
|
line: [],
|
|
1717
1835
|
polygon: [],
|
|
1718
1836
|
path: []
|
|
1719
1837
|
};
|
|
1720
|
-
var ANCHORED_SHAPES = /* @__PURE__ */ new Set(["rect", "circle", "ellipse"]);
|
|
1838
|
+
var ANCHORED_SHAPES = /* @__PURE__ */ new Set(["rect", "circle", "ellipse", "arc"]);
|
|
1721
1839
|
var ShapeSequence = class extends Sequence {
|
|
1722
1840
|
_state = {
|
|
1723
1841
|
fillColor: void 0,
|
|
@@ -1744,6 +1862,11 @@ var ShapeSequence = class extends Sequence {
|
|
|
1744
1862
|
for (const k of geomKeys) this._liveKeys.add(k);
|
|
1745
1863
|
seedGeometry(this._state, this.spec, scope);
|
|
1746
1864
|
seedStyle(this._state, this.spec.initial ?? {}, scope);
|
|
1865
|
+
seedStrokeStyle(this._state, this.spec, this.spec.initial ?? {}, describeLayer(this.spec));
|
|
1866
|
+
if (this.spec.shape === "arc") {
|
|
1867
|
+
this._state.startAngle ??= 0;
|
|
1868
|
+
this._state.endAngle ??= 360;
|
|
1869
|
+
}
|
|
1747
1870
|
const gradientSpec = this.spec.fillGradient ?? this.spec.initial?.fillGradient;
|
|
1748
1871
|
if (gradientSpec) this._state.fillStyle = makeGradientFill(gradientSpec);
|
|
1749
1872
|
this._drawGeometry = makeDrawGeometry(this.spec, scope, this._state);
|
|
@@ -1761,12 +1884,32 @@ var ShapeSequence = class extends Sequence {
|
|
|
1761
1884
|
if (init.y === void 0) graphics.y = cy;
|
|
1762
1885
|
}
|
|
1763
1886
|
graphics.onRender = () => {
|
|
1764
|
-
|
|
1765
|
-
|
|
1766
|
-
|
|
1887
|
+
if (this._fresh) {
|
|
1888
|
+
this._fresh = false;
|
|
1889
|
+
return;
|
|
1890
|
+
}
|
|
1891
|
+
this._redraw();
|
|
1767
1892
|
};
|
|
1768
1893
|
this.buildFilters();
|
|
1769
1894
|
}
|
|
1895
|
+
_fresh = false;
|
|
1896
|
+
_redraw() {
|
|
1897
|
+
const graphics = this.target;
|
|
1898
|
+
graphics.clear();
|
|
1899
|
+
this._drawGeometry(graphics);
|
|
1900
|
+
applyState(graphics, this._state);
|
|
1901
|
+
}
|
|
1902
|
+
/**
|
|
1903
|
+
* Draw from the tweened `_state` before the culler runs. The culler measures the geometry as last
|
|
1904
|
+
* drawn; a layer drawn only inside `onRender` is culled on stale bounds (a rect growing from
|
|
1905
|
+
* `width: 0` at the left edge was skipped after a jump seek, and one frame late in playback).
|
|
1906
|
+
*/
|
|
1907
|
+
syncFrame() {
|
|
1908
|
+
super.syncFrame();
|
|
1909
|
+
if (!this.target?.renderable) return;
|
|
1910
|
+
this._redraw();
|
|
1911
|
+
this._fresh = true;
|
|
1912
|
+
}
|
|
1770
1913
|
bindTimeline(timeline, offset = 0) {
|
|
1771
1914
|
if (!this.target) return;
|
|
1772
1915
|
const scope = this.scope();
|
|
@@ -1792,6 +1935,21 @@ function seedGeometry(state, spec, scope) {
|
|
|
1792
1935
|
if (v !== void 0) state[k] = num(v, scope);
|
|
1793
1936
|
}
|
|
1794
1937
|
}
|
|
1938
|
+
var STROKE_CAPS = ["butt", "round", "square"];
|
|
1939
|
+
var STROKE_JOINS = ["miter", "round", "bevel"];
|
|
1940
|
+
function seedStrokeStyle(state, spec, initial, who) {
|
|
1941
|
+
const top = spec;
|
|
1942
|
+
const ini = initial;
|
|
1943
|
+
const pick = (key, valid) => {
|
|
1944
|
+
const v = top[key] ?? ini[key];
|
|
1945
|
+
if (v === void 0) return void 0;
|
|
1946
|
+
if (valid.includes(String(v))) return String(v);
|
|
1947
|
+
console.warn(`pixi-effects: ${who}: ${key} "${v}" is not one of ${valid.join(", ")}; ignored`);
|
|
1948
|
+
return void 0;
|
|
1949
|
+
};
|
|
1950
|
+
state.strokeCap = pick("strokeCap", STROKE_CAPS);
|
|
1951
|
+
state.strokeJoin = pick("strokeJoin", STROKE_JOINS);
|
|
1952
|
+
}
|
|
1795
1953
|
function seedStyle(state, initial, scope) {
|
|
1796
1954
|
for (const k of STYLE_KEYS) {
|
|
1797
1955
|
const v = initial[k];
|
|
@@ -1800,8 +1958,8 @@ function seedStyle(state, initial, scope) {
|
|
|
1800
1958
|
}
|
|
1801
1959
|
}
|
|
1802
1960
|
function stripGradient(props) {
|
|
1803
|
-
if (!props || !("fillGradient" in props)) return props;
|
|
1804
|
-
const { fillGradient: _drop, ...rest } = props;
|
|
1961
|
+
if (!props || !("fillGradient" in props || "strokeCap" in props || "strokeJoin" in props)) return props;
|
|
1962
|
+
const { fillGradient: _drop, strokeCap: _cap, strokeJoin: _join, ...rest } = props;
|
|
1805
1963
|
return rest;
|
|
1806
1964
|
}
|
|
1807
1965
|
function stripLive(props, liveKeys) {
|
|
@@ -1848,7 +2006,13 @@ function applyState(g, s) {
|
|
|
1848
2006
|
g.fill({ color: s.fillColor, alpha: s.fillAlpha });
|
|
1849
2007
|
}
|
|
1850
2008
|
if (s.strokeColor !== void 0 && s.strokeWidth > 0) {
|
|
1851
|
-
g.stroke({
|
|
2009
|
+
g.stroke({
|
|
2010
|
+
color: s.strokeColor,
|
|
2011
|
+
alpha: s.strokeAlpha,
|
|
2012
|
+
width: s.strokeWidth,
|
|
2013
|
+
...s.strokeCap ? { cap: s.strokeCap } : {},
|
|
2014
|
+
...s.strokeJoin ? { join: s.strokeJoin } : {}
|
|
2015
|
+
});
|
|
1852
2016
|
}
|
|
1853
2017
|
}
|
|
1854
2018
|
function drawRectFromState(g, s) {
|
|
@@ -1875,6 +2039,34 @@ function drawEllipseFromState(g, s) {
|
|
|
1875
2039
|
const ay = s.anchorY ?? 0.5;
|
|
1876
2040
|
g.ellipse((0.5 - ax) * 2 * rx, (0.5 - ay) * 2 * ry, rx, ry);
|
|
1877
2041
|
}
|
|
2042
|
+
var DEG2 = Math.PI / 180;
|
|
2043
|
+
function drawArcFromState(g, s) {
|
|
2044
|
+
const r = s.radius ?? 0;
|
|
2045
|
+
const ri = Math.max(0, Math.min(s.innerRadius ?? 0, r));
|
|
2046
|
+
const startDeg = s.startAngle ?? 0;
|
|
2047
|
+
let endDeg = s.endAngle ?? 360;
|
|
2048
|
+
if (!(r > 0) || endDeg === startDeg) return;
|
|
2049
|
+
const filled = !!s.fillStyle || s.fillColor !== void 0;
|
|
2050
|
+
if (Math.abs(endDeg - startDeg) >= 360) {
|
|
2051
|
+
if (!filled) {
|
|
2052
|
+
g.circle(0, 0, r);
|
|
2053
|
+
return;
|
|
2054
|
+
}
|
|
2055
|
+
endDeg = startDeg + Math.sign(endDeg - startDeg) * 359.999;
|
|
2056
|
+
}
|
|
2057
|
+
const a0 = startDeg * DEG2, a1 = endDeg * DEG2;
|
|
2058
|
+
const ccw = a1 < a0;
|
|
2059
|
+
if (filled) g.moveTo(r * Math.cos(a0), r * Math.sin(a0));
|
|
2060
|
+
g.arc(0, 0, r, a0, a1, ccw);
|
|
2061
|
+
if (!filled) return;
|
|
2062
|
+
if (ri > 0) {
|
|
2063
|
+
g.lineTo(ri * Math.cos(a1), ri * Math.sin(a1));
|
|
2064
|
+
g.arc(0, 0, ri, a1, a0, !ccw);
|
|
2065
|
+
} else {
|
|
2066
|
+
g.lineTo(0, 0);
|
|
2067
|
+
}
|
|
2068
|
+
g.closePath();
|
|
2069
|
+
}
|
|
1878
2070
|
function makeLineDraw(spec, scope) {
|
|
1879
2071
|
const fx = num(spec.from[0], scope);
|
|
1880
2072
|
const fy = num(spec.from[1], scope);
|
|
@@ -1903,7 +2095,8 @@ function makePathDraw(spec) {
|
|
|
1903
2095
|
var STATE_DRAWERS = {
|
|
1904
2096
|
rect: drawRectFromState,
|
|
1905
2097
|
circle: drawCircleFromState,
|
|
1906
|
-
ellipse: drawEllipseFromState
|
|
2098
|
+
ellipse: drawEllipseFromState,
|
|
2099
|
+
arc: drawArcFromState
|
|
1907
2100
|
};
|
|
1908
2101
|
function makeDrawGeometry(spec, scope, state) {
|
|
1909
2102
|
const stateDrawer = STATE_DRAWERS[spec.shape];
|
|
@@ -1930,9 +2123,10 @@ function bindLiveKeyframes(timeline, state, liveKeys, keyframes, parentDuration,
|
|
|
1930
2123
|
if (live) {
|
|
1931
2124
|
for (const [k, v] of Object.entries(live)) {
|
|
1932
2125
|
const resolved = resolveLiveValue(k, v, scope);
|
|
1933
|
-
|
|
1934
|
-
|
|
1935
|
-
|
|
2126
|
+
const live2 = state;
|
|
2127
|
+
revertibleSet(timeline, at, () => live2[k], (v2) => {
|
|
2128
|
+
live2[k] = v2;
|
|
2129
|
+
}, resolved);
|
|
1936
2130
|
}
|
|
1937
2131
|
}
|
|
1938
2132
|
}
|
|
@@ -1991,7 +2185,7 @@ function numOrZero(v, scope) {
|
|
|
1991
2185
|
var _CompositionSequence = null;
|
|
1992
2186
|
async function getCompositionSequence() {
|
|
1993
2187
|
if (!_CompositionSequence) {
|
|
1994
|
-
_CompositionSequence = (await import('./Composition-
|
|
2188
|
+
_CompositionSequence = (await import('./Composition-63EXHNJJ.cjs')).CompositionSequence;
|
|
1995
2189
|
}
|
|
1996
2190
|
return _CompositionSequence;
|
|
1997
2191
|
}
|
|
@@ -2031,6 +2225,7 @@ async function buildSequenceTree(specs, parent, root) {
|
|
|
2031
2225
|
exports.CameraSequence = CameraSequence;
|
|
2032
2226
|
exports.DEFAULT_FOV = DEFAULT_FOV;
|
|
2033
2227
|
exports.DEG = DEG;
|
|
2228
|
+
exports.NEAR = NEAR;
|
|
2034
2229
|
exports.Sequence = Sequence;
|
|
2035
2230
|
exports.buildScope = buildScope;
|
|
2036
2231
|
exports.buildSequenceTree = buildSequenceTree;
|
|
@@ -2045,5 +2240,6 @@ exports.lintTiming = lintTiming;
|
|
|
2045
2240
|
exports.projectLayer = projectLayer;
|
|
2046
2241
|
exports.registerSequenceType = registerSequenceType;
|
|
2047
2242
|
exports.resolveAt = resolveAt;
|
|
2048
|
-
|
|
2049
|
-
//# sourceMappingURL=chunk-
|
|
2243
|
+
exports.summarizeWarnings = summarizeWarnings;
|
|
2244
|
+
//# sourceMappingURL=chunk-2RR43OIN.cjs.map
|
|
2245
|
+
//# sourceMappingURL=chunk-2RR43OIN.cjs.map
|