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
|
@@ -739,6 +739,11 @@ var Sequence = class {
|
|
|
739
739
|
* (not a normal child) by PIXI when `target.mask = maskSequence.target`.
|
|
740
740
|
*/
|
|
741
741
|
maskSequence = null;
|
|
742
|
+
/**
|
|
743
|
+
* Set by the parent composition on a sprite-based (image / video) mask. PIXI hides such a mask with
|
|
744
|
+
* `renderable = false`; the lifespan toggles must not switch it back on, or the mask is drawn as a picture.
|
|
745
|
+
*/
|
|
746
|
+
keepHidden = false;
|
|
742
747
|
/**
|
|
743
748
|
* Absolute start time on the global timeline (offset + at), recorded by
|
|
744
749
|
* bindTimeline. Movie._awaitVideoFrames uses it to determine the correct
|
|
@@ -783,6 +788,7 @@ var Sequence = class {
|
|
|
783
788
|
applyKeyframes(timeline, this.target, this.spec.keyframes, this.duration, scope, [], startTime, routers);
|
|
784
789
|
const endTime = startTime + this.duration;
|
|
785
790
|
this.absoluteStart = startTime;
|
|
791
|
+
if (this.keepHidden) return;
|
|
786
792
|
this.target.renderable = startTime <= 0;
|
|
787
793
|
timeline.set(this.target, { renderable: true }, startTime);
|
|
788
794
|
timeline.set(this.target, { renderable: false }, endTime);
|
|
@@ -796,6 +802,14 @@ var Sequence = class {
|
|
|
796
802
|
*/
|
|
797
803
|
updateSpace(_t, _host) {
|
|
798
804
|
}
|
|
805
|
+
/**
|
|
806
|
+
* Runs once per rendered frame, after the timeline seek and before the cull. Layers whose drawn
|
|
807
|
+
* geometry follows tweened state (shapes) redraw here, so the culler measures where the layer is NOW
|
|
808
|
+
* and not where it was drawn at the previous render.
|
|
809
|
+
*/
|
|
810
|
+
syncFrame() {
|
|
811
|
+
this.maskSequence?.syncFrame();
|
|
812
|
+
}
|
|
799
813
|
destroy() {
|
|
800
814
|
this.maskSequence?.destroy();
|
|
801
815
|
this.maskSequence = null;
|
|
@@ -827,18 +841,27 @@ function lintTiming(spec, parentDuration, warn = defaultWarn) {
|
|
|
827
841
|
if (at >= parentDuration) {
|
|
828
842
|
warn(`pixi-effects: ${who} starts at ${at}s, after its composition ends (${parentDuration}s), so it is never visible`);
|
|
829
843
|
}
|
|
844
|
+
if (spec.type === "audio" && spec.sfx !== void 0 && spec.duration === void 0) return;
|
|
830
845
|
const duration = spec.duration ?? parentDuration;
|
|
831
846
|
(spec.keyframes ?? []).forEach((kf, i) => {
|
|
832
847
|
const kat = kf.at ?? 0;
|
|
833
848
|
if (kat >= duration) {
|
|
834
849
|
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
|
|
850
|
+
`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.`,
|
|
851
|
+
"late-keyframe"
|
|
836
852
|
);
|
|
837
853
|
}
|
|
838
854
|
});
|
|
839
855
|
}
|
|
856
|
+
function summarizeWarnings(messages, shown = 3) {
|
|
857
|
+
if (messages.length <= shown) return messages;
|
|
858
|
+
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.`];
|
|
859
|
+
}
|
|
840
860
|
function lintText(spec, warn = defaultWarn) {
|
|
841
861
|
if (spec.type !== "text") return;
|
|
862
|
+
if ((spec.text ?? "").includes("{value}") && !collectPropKeys(spec).has("value")) {
|
|
863
|
+
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}").`);
|
|
864
|
+
}
|
|
842
865
|
if (collectPropKeys(spec).has("value") && !(spec.text ?? "").includes("{value}")) {
|
|
843
866
|
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
867
|
}
|
|
@@ -1011,7 +1034,30 @@ var CameraSequence = class extends Sequence {
|
|
|
1011
1034
|
}
|
|
1012
1035
|
};
|
|
1013
1036
|
|
|
1037
|
+
// src/core/revertibleSet.ts
|
|
1038
|
+
function revertibleSet(timeline, at, read, write, value) {
|
|
1039
|
+
let p = 0;
|
|
1040
|
+
let before;
|
|
1041
|
+
const proxy = {
|
|
1042
|
+
get p() {
|
|
1043
|
+
return p;
|
|
1044
|
+
},
|
|
1045
|
+
set p(next) {
|
|
1046
|
+
if (next >= 1 && p < 1) {
|
|
1047
|
+
before = read();
|
|
1048
|
+
write(value);
|
|
1049
|
+
} else if (next < 1 && p >= 1) {
|
|
1050
|
+
write(before);
|
|
1051
|
+
}
|
|
1052
|
+
p = next;
|
|
1053
|
+
}
|
|
1054
|
+
};
|
|
1055
|
+
timeline.set(proxy, { p: 1 }, at);
|
|
1056
|
+
}
|
|
1057
|
+
|
|
1014
1058
|
// src/expr/colorInterp.ts
|
|
1059
|
+
var CHROMA_FLOOR = 0.03;
|
|
1060
|
+
var CHROMA_FULL = 0.08;
|
|
1015
1061
|
function buildColorInterp(from, to, space) {
|
|
1016
1062
|
const fromRGBA = parseToRGBA(from);
|
|
1017
1063
|
const toRGBA = parseToRGBA(to);
|
|
@@ -1028,8 +1074,9 @@ function buildColorInterp(from, to, space) {
|
|
|
1028
1074
|
}
|
|
1029
1075
|
const fromLCH = oklabToOklch(fromOk);
|
|
1030
1076
|
const toLCH = oklabToOklch(toOk);
|
|
1031
|
-
|
|
1032
|
-
|
|
1077
|
+
const fromHue = fromLCH.h, toHue = toLCH.h;
|
|
1078
|
+
fromLCH.h = borrowHue(fromHue, fromLCH.C, toHue);
|
|
1079
|
+
toLCH.h = borrowHue(toHue, toLCH.C, fromHue);
|
|
1033
1080
|
const hueDelta = shortestHueDelta(fromLCH.h, toLCH.h);
|
|
1034
1081
|
return (t) => {
|
|
1035
1082
|
const L = lerp(fromLCH.L, toLCH.L, t);
|
|
@@ -1040,6 +1087,11 @@ function buildColorInterp(from, to, space) {
|
|
|
1040
1087
|
return rgbaString(oklabToRgb(ab), alpha);
|
|
1041
1088
|
};
|
|
1042
1089
|
}
|
|
1090
|
+
function borrowHue(own, chroma, other) {
|
|
1091
|
+
const u = Math.min(1, Math.max(0, (chroma - CHROMA_FLOOR) / (CHROMA_FULL - CHROMA_FLOOR)));
|
|
1092
|
+
const keep = u * u * (3 - 2 * u);
|
|
1093
|
+
return own + shortestHueDelta(own, other) * (1 - keep);
|
|
1094
|
+
}
|
|
1043
1095
|
function parseToRGBA(input) {
|
|
1044
1096
|
if (typeof input === "number") {
|
|
1045
1097
|
return { r: (input >> 16 & 255) / 255, g: (input >> 8 & 255) / 255, b: (input & 255) / 255, a: 1 };
|
|
@@ -1201,9 +1253,10 @@ var ImageSequence = class extends Sequence {
|
|
|
1201
1253
|
const toTint = kf.to?.tint;
|
|
1202
1254
|
const setTint = kf.set?.tint;
|
|
1203
1255
|
if (setTint !== void 0) {
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1256
|
+
const sprite = this.target;
|
|
1257
|
+
revertibleSet(timeline, at, () => sprite.tint, (c) => {
|
|
1258
|
+
sprite.tint = c;
|
|
1259
|
+
}, setTint);
|
|
1207
1260
|
}
|
|
1208
1261
|
if (toTint !== void 0) {
|
|
1209
1262
|
tweenColor(
|
|
@@ -1223,6 +1276,7 @@ var ImageSequence = class extends Sequence {
|
|
|
1223
1276
|
}
|
|
1224
1277
|
this.absoluteStart = startTime;
|
|
1225
1278
|
const endTime = startTime + this.duration;
|
|
1279
|
+
if (this.keepHidden) return;
|
|
1226
1280
|
this.target.renderable = startTime <= 0;
|
|
1227
1281
|
timeline.set(this.target, { renderable: true }, startTime);
|
|
1228
1282
|
timeline.set(this.target, { renderable: false }, endTime);
|
|
@@ -1250,12 +1304,31 @@ function stripKeysInKeyframe(kf, keys) {
|
|
|
1250
1304
|
from: stripKeys(kf.from, keys)
|
|
1251
1305
|
};
|
|
1252
1306
|
}
|
|
1253
|
-
var STYLE_OPAQUE_KEYS = [
|
|
1307
|
+
var STYLE_OPAQUE_KEYS = [
|
|
1308
|
+
"fontFamily",
|
|
1309
|
+
"fill",
|
|
1310
|
+
"align",
|
|
1311
|
+
"fontStyle",
|
|
1312
|
+
"fontWeight",
|
|
1313
|
+
"fontVariant",
|
|
1314
|
+
"textBaseline",
|
|
1315
|
+
"whiteSpace",
|
|
1316
|
+
"lineJoin",
|
|
1317
|
+
"join",
|
|
1318
|
+
"cap",
|
|
1319
|
+
"color",
|
|
1320
|
+
"stroke"
|
|
1321
|
+
];
|
|
1254
1322
|
function formatValue(v, f) {
|
|
1255
1323
|
const fixed = v.toFixed(Math.max(0, Math.floor(f?.decimals ?? 0)));
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
|
|
1324
|
+
const pad = Math.max(0, Math.floor(f?.pad ?? 0));
|
|
1325
|
+
if (!f?.grouping && !pad) return fixed;
|
|
1326
|
+
const [signed, frac] = fixed.split(".");
|
|
1327
|
+
const sign = signed.startsWith("-") ? "-" : "";
|
|
1328
|
+
let int = sign ? signed.slice(1) : signed;
|
|
1329
|
+
if (pad) int = int.padStart(pad, "0");
|
|
1330
|
+
if (f?.grouping) int = int.replace(/\B(?=(\d{3})+(?!\d))/g, ",");
|
|
1331
|
+
return sign + int + (frac !== void 0 ? "." + frac : "");
|
|
1259
1332
|
}
|
|
1260
1333
|
var TextSequence = class extends Sequence {
|
|
1261
1334
|
/** Current number for the `{value}` placeholder (tweened by `value` keyframes). */
|
|
@@ -1365,10 +1438,10 @@ function bindValueKeyframes(timeline, state, refresh, keyframes, parentDuration,
|
|
|
1365
1438
|
const loop = loopVars(kf);
|
|
1366
1439
|
if (setV !== void 0) {
|
|
1367
1440
|
const v = resolveNumber(setV, scope);
|
|
1368
|
-
timeline.
|
|
1369
|
-
state.value =
|
|
1441
|
+
revertibleSet(timeline, at, () => state.value, (n) => {
|
|
1442
|
+
state.value = n;
|
|
1370
1443
|
refresh();
|
|
1371
|
-
},
|
|
1444
|
+
}, v);
|
|
1372
1445
|
}
|
|
1373
1446
|
if (toV !== void 0 && fromV !== void 0) {
|
|
1374
1447
|
timeline.fromTo(
|
|
@@ -1397,10 +1470,10 @@ function bindFillKeyframes(timeline, text, keyframes, parentDuration, offset, co
|
|
|
1397
1470
|
const fromFill = pickFill(kf.from);
|
|
1398
1471
|
const toFill = pickFill(kf.to);
|
|
1399
1472
|
if (setFill !== void 0) {
|
|
1400
|
-
timeline.
|
|
1401
|
-
state.fill =
|
|
1473
|
+
revertibleSet(timeline, at, () => state.fill, (c) => {
|
|
1474
|
+
state.fill = c;
|
|
1402
1475
|
writeFill();
|
|
1403
|
-
},
|
|
1476
|
+
}, setFill);
|
|
1404
1477
|
}
|
|
1405
1478
|
if (toFill !== void 0) {
|
|
1406
1479
|
tweenColor(
|
|
@@ -1427,54 +1500,96 @@ function pickFill(props) {
|
|
|
1427
1500
|
}
|
|
1428
1501
|
var AudioSequence = class extends Sequence {
|
|
1429
1502
|
_audioBuffer = null;
|
|
1503
|
+
_synth = null;
|
|
1504
|
+
_source = "";
|
|
1430
1505
|
async build() {
|
|
1431
|
-
|
|
1506
|
+
this.target = null;
|
|
1507
|
+
if (this.spec.sfx !== void 0) return this._buildSfx(this.spec);
|
|
1508
|
+
const spec = this.spec;
|
|
1509
|
+
this._source = `asset "${spec.asset}"`;
|
|
1510
|
+
const data = await Assets.get(spec.asset);
|
|
1432
1511
|
this._audioBuffer = data.audioBuffer;
|
|
1433
1512
|
if (this.duration === void 0) {
|
|
1434
|
-
|
|
1513
|
+
const rest = Math.max(0, (this.parent?.duration ?? this.root.duration) - this.at);
|
|
1514
|
+
this.duration = spec.duration ?? (spec.loop ? rest : data.duration) ?? this.root.duration;
|
|
1435
1515
|
}
|
|
1436
|
-
if (!
|
|
1516
|
+
if (!spec.loop && data.duration !== void 0 && this.duration > data.duration + 0.05) {
|
|
1437
1517
|
console.warn(
|
|
1438
|
-
`pixi-effects: ${describeLayer(
|
|
1518
|
+
`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.`
|
|
1439
1519
|
);
|
|
1440
1520
|
}
|
|
1441
|
-
|
|
1521
|
+
}
|
|
1522
|
+
async _buildSfx(spec) {
|
|
1523
|
+
const who = describeLayer(spec);
|
|
1524
|
+
const raw = spec;
|
|
1525
|
+
if (raw.asset !== void 0) console.warn(`pixi-effects: ${who}: has both asset and sfx \u2014 the sfx plays; remove one`);
|
|
1526
|
+
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)`);
|
|
1527
|
+
const { resolveSfx, renderSfx, sfxKey } = await import('./sfx-S37DDC66.js');
|
|
1528
|
+
const sfx = resolveSfx(spec.sfx, spec.duration, who);
|
|
1529
|
+
if (!sfx) return;
|
|
1530
|
+
this.duration = sfx.length;
|
|
1531
|
+
this._source = `sfx "${sfx.preset ?? "custom"}"`;
|
|
1532
|
+
this._synth = { key: sfxKey(sfx), render: (sr) => renderSfx(sfx, sr) };
|
|
1533
|
+
(spec.keyframes ?? []).forEach((kf, i) => {
|
|
1534
|
+
if ((kf.at ?? 0) >= sfx.length) {
|
|
1535
|
+
console.warn(`pixi-effects: ${who}: keyframes[${i}] starts at ${kf.at}s, after the sound ends (${sfx.length}s), so it never plays`);
|
|
1536
|
+
} else if ((kf.at ?? 0) < 0 && sfx.length + (kf.at ?? 0) < 0) {
|
|
1537
|
+
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\`.`);
|
|
1538
|
+
}
|
|
1539
|
+
});
|
|
1442
1540
|
}
|
|
1443
1541
|
bindTimeline(_timeline) {
|
|
1444
1542
|
}
|
|
1445
1543
|
collectAudio(out, baseTime) {
|
|
1446
|
-
if (!this._audioBuffer) return;
|
|
1447
|
-
const initialVolume = this.spec.volume ?? 1;
|
|
1448
|
-
const
|
|
1544
|
+
if (!this._audioBuffer && !this._synth) return;
|
|
1545
|
+
const initialVolume = this.spec.volume ?? this.spec.initial?.volume ?? 1;
|
|
1546
|
+
const t0 = baseTime + this.at;
|
|
1449
1547
|
const dur = this.duration;
|
|
1450
|
-
for (const raw of this.spec.keyframes ?? []) {
|
|
1451
|
-
const kf = normalizeKeyframe(raw, dur);
|
|
1452
|
-
const set = kf.set;
|
|
1453
|
-
const to = kf.to;
|
|
1454
|
-
const from = kf.from;
|
|
1455
|
-
if (kf.kind === "set" && set && "volume" in set) {
|
|
1456
|
-
volumeKeyframes.push({ time: baseTime + this.at + kf.at, value: set.volume });
|
|
1457
|
-
} else if (kf.kind === "to" && to && "volume" in to) {
|
|
1458
|
-
volumeKeyframes.push({ time: baseTime + this.at + kf.at + kf.duration, value: to.volume });
|
|
1459
|
-
} else if (kf.kind === "fromTo" && to && "volume" in to) {
|
|
1460
|
-
volumeKeyframes.push({ time: baseTime + this.at + kf.at, value: from?.volume ?? initialVolume });
|
|
1461
|
-
volumeKeyframes.push({ time: baseTime + this.at + kf.at + kf.duration, value: to.volume });
|
|
1462
|
-
} else if (kf.kind === "from" && from && "volume" in from) {
|
|
1463
|
-
volumeKeyframes.push({ time: baseTime + this.at + kf.at, value: from.volume });
|
|
1464
|
-
volumeKeyframes.push({ time: baseTime + this.at + kf.at + kf.duration, value: initialVolume });
|
|
1465
|
-
}
|
|
1466
|
-
}
|
|
1467
1548
|
out.push({
|
|
1468
|
-
buffer: this._audioBuffer,
|
|
1469
|
-
|
|
1470
|
-
|
|
1471
|
-
|
|
1549
|
+
...this._audioBuffer ? { buffer: this._audioBuffer } : { synth: this._synth },
|
|
1550
|
+
layer: describeLayer(this.spec),
|
|
1551
|
+
source: this._source,
|
|
1552
|
+
loop: !this._synth && !!this.spec.loop,
|
|
1553
|
+
start: t0,
|
|
1554
|
+
end: t0 + dur,
|
|
1472
1555
|
initialVolume,
|
|
1473
|
-
volumeKeyframes
|
|
1556
|
+
volumeKeyframes: this._volumePoints(t0, dur, initialVolume)
|
|
1474
1557
|
});
|
|
1475
1558
|
}
|
|
1559
|
+
_volumePoints(t0, dur, initialVolume) {
|
|
1560
|
+
const volumeKeyframes = [];
|
|
1561
|
+
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);
|
|
1562
|
+
let current = initialVolume;
|
|
1563
|
+
const point = (time, value) => {
|
|
1564
|
+
volumeKeyframes.push({ time, value });
|
|
1565
|
+
};
|
|
1566
|
+
for (const kf of keyframes) {
|
|
1567
|
+
const start = t0 + kf.at;
|
|
1568
|
+
const end = start + kf.duration;
|
|
1569
|
+
const set = kf.set?.volume;
|
|
1570
|
+
const to = kf.to?.volume;
|
|
1571
|
+
const from = kf.from?.volume;
|
|
1572
|
+
point(start, current);
|
|
1573
|
+
if (kf.kind === "set" && set !== void 0) {
|
|
1574
|
+
point(start, set);
|
|
1575
|
+
current = set;
|
|
1576
|
+
} else if (kf.kind === "to" && to !== void 0) {
|
|
1577
|
+
point(end, to);
|
|
1578
|
+
current = to;
|
|
1579
|
+
} else if (kf.kind === "fromTo" && to !== void 0) {
|
|
1580
|
+
point(start, from ?? current);
|
|
1581
|
+
point(end, to);
|
|
1582
|
+
current = to;
|
|
1583
|
+
} else if (kf.kind === "from" && from !== void 0) {
|
|
1584
|
+
point(start, from);
|
|
1585
|
+
point(end, current);
|
|
1586
|
+
}
|
|
1587
|
+
}
|
|
1588
|
+
return volumeKeyframes;
|
|
1589
|
+
}
|
|
1476
1590
|
destroy() {
|
|
1477
1591
|
this._audioBuffer = null;
|
|
1592
|
+
this._synth = null;
|
|
1478
1593
|
}
|
|
1479
1594
|
};
|
|
1480
1595
|
|
|
@@ -1623,6 +1738,8 @@ var VideoSequence = class extends Sequence {
|
|
|
1623
1738
|
const initialVolume = this.spec.volume ?? 1;
|
|
1624
1739
|
out.push({
|
|
1625
1740
|
buffer: this._audioBuffer,
|
|
1741
|
+
layer: describeLayer(this.spec),
|
|
1742
|
+
source: `video "${this.spec.asset}"`,
|
|
1626
1743
|
loop: !!this.spec.loop,
|
|
1627
1744
|
start: baseTime + this.at,
|
|
1628
1745
|
end: baseTime + this.at + this.duration,
|
|
@@ -1711,11 +1828,12 @@ var GEOMETRY_KEYS_BY_SHAPE = {
|
|
|
1711
1828
|
rect: ["width", "height", "cornerRadius", "anchorX", "anchorY"],
|
|
1712
1829
|
circle: ["radius", "anchorX", "anchorY"],
|
|
1713
1830
|
ellipse: ["radiusX", "radiusY", "anchorX", "anchorY"],
|
|
1831
|
+
arc: ["radius", "innerRadius", "startAngle", "endAngle"],
|
|
1714
1832
|
line: [],
|
|
1715
1833
|
polygon: [],
|
|
1716
1834
|
path: []
|
|
1717
1835
|
};
|
|
1718
|
-
var ANCHORED_SHAPES = /* @__PURE__ */ new Set(["rect", "circle", "ellipse"]);
|
|
1836
|
+
var ANCHORED_SHAPES = /* @__PURE__ */ new Set(["rect", "circle", "ellipse", "arc"]);
|
|
1719
1837
|
var ShapeSequence = class extends Sequence {
|
|
1720
1838
|
_state = {
|
|
1721
1839
|
fillColor: void 0,
|
|
@@ -1742,6 +1860,11 @@ var ShapeSequence = class extends Sequence {
|
|
|
1742
1860
|
for (const k of geomKeys) this._liveKeys.add(k);
|
|
1743
1861
|
seedGeometry(this._state, this.spec, scope);
|
|
1744
1862
|
seedStyle(this._state, this.spec.initial ?? {}, scope);
|
|
1863
|
+
seedStrokeStyle(this._state, this.spec, this.spec.initial ?? {}, describeLayer(this.spec));
|
|
1864
|
+
if (this.spec.shape === "arc") {
|
|
1865
|
+
this._state.startAngle ??= 0;
|
|
1866
|
+
this._state.endAngle ??= 360;
|
|
1867
|
+
}
|
|
1745
1868
|
const gradientSpec = this.spec.fillGradient ?? this.spec.initial?.fillGradient;
|
|
1746
1869
|
if (gradientSpec) this._state.fillStyle = makeGradientFill(gradientSpec);
|
|
1747
1870
|
this._drawGeometry = makeDrawGeometry(this.spec, scope, this._state);
|
|
@@ -1759,12 +1882,32 @@ var ShapeSequence = class extends Sequence {
|
|
|
1759
1882
|
if (init.y === void 0) graphics.y = cy;
|
|
1760
1883
|
}
|
|
1761
1884
|
graphics.onRender = () => {
|
|
1762
|
-
|
|
1763
|
-
|
|
1764
|
-
|
|
1885
|
+
if (this._fresh) {
|
|
1886
|
+
this._fresh = false;
|
|
1887
|
+
return;
|
|
1888
|
+
}
|
|
1889
|
+
this._redraw();
|
|
1765
1890
|
};
|
|
1766
1891
|
this.buildFilters();
|
|
1767
1892
|
}
|
|
1893
|
+
_fresh = false;
|
|
1894
|
+
_redraw() {
|
|
1895
|
+
const graphics = this.target;
|
|
1896
|
+
graphics.clear();
|
|
1897
|
+
this._drawGeometry(graphics);
|
|
1898
|
+
applyState(graphics, this._state);
|
|
1899
|
+
}
|
|
1900
|
+
/**
|
|
1901
|
+
* Draw from the tweened `_state` before the culler runs. The culler measures the geometry as last
|
|
1902
|
+
* drawn; a layer drawn only inside `onRender` is culled on stale bounds (a rect growing from
|
|
1903
|
+
* `width: 0` at the left edge was skipped after a jump seek, and one frame late in playback).
|
|
1904
|
+
*/
|
|
1905
|
+
syncFrame() {
|
|
1906
|
+
super.syncFrame();
|
|
1907
|
+
if (!this.target?.renderable) return;
|
|
1908
|
+
this._redraw();
|
|
1909
|
+
this._fresh = true;
|
|
1910
|
+
}
|
|
1768
1911
|
bindTimeline(timeline, offset = 0) {
|
|
1769
1912
|
if (!this.target) return;
|
|
1770
1913
|
const scope = this.scope();
|
|
@@ -1790,6 +1933,21 @@ function seedGeometry(state, spec, scope) {
|
|
|
1790
1933
|
if (v !== void 0) state[k] = num(v, scope);
|
|
1791
1934
|
}
|
|
1792
1935
|
}
|
|
1936
|
+
var STROKE_CAPS = ["butt", "round", "square"];
|
|
1937
|
+
var STROKE_JOINS = ["miter", "round", "bevel"];
|
|
1938
|
+
function seedStrokeStyle(state, spec, initial, who) {
|
|
1939
|
+
const top = spec;
|
|
1940
|
+
const ini = initial;
|
|
1941
|
+
const pick = (key, valid) => {
|
|
1942
|
+
const v = top[key] ?? ini[key];
|
|
1943
|
+
if (v === void 0) return void 0;
|
|
1944
|
+
if (valid.includes(String(v))) return String(v);
|
|
1945
|
+
console.warn(`pixi-effects: ${who}: ${key} "${v}" is not one of ${valid.join(", ")}; ignored`);
|
|
1946
|
+
return void 0;
|
|
1947
|
+
};
|
|
1948
|
+
state.strokeCap = pick("strokeCap", STROKE_CAPS);
|
|
1949
|
+
state.strokeJoin = pick("strokeJoin", STROKE_JOINS);
|
|
1950
|
+
}
|
|
1793
1951
|
function seedStyle(state, initial, scope) {
|
|
1794
1952
|
for (const k of STYLE_KEYS) {
|
|
1795
1953
|
const v = initial[k];
|
|
@@ -1798,8 +1956,8 @@ function seedStyle(state, initial, scope) {
|
|
|
1798
1956
|
}
|
|
1799
1957
|
}
|
|
1800
1958
|
function stripGradient(props) {
|
|
1801
|
-
if (!props || !("fillGradient" in props)) return props;
|
|
1802
|
-
const { fillGradient: _drop, ...rest } = props;
|
|
1959
|
+
if (!props || !("fillGradient" in props || "strokeCap" in props || "strokeJoin" in props)) return props;
|
|
1960
|
+
const { fillGradient: _drop, strokeCap: _cap, strokeJoin: _join, ...rest } = props;
|
|
1803
1961
|
return rest;
|
|
1804
1962
|
}
|
|
1805
1963
|
function stripLive(props, liveKeys) {
|
|
@@ -1846,7 +2004,13 @@ function applyState(g, s) {
|
|
|
1846
2004
|
g.fill({ color: s.fillColor, alpha: s.fillAlpha });
|
|
1847
2005
|
}
|
|
1848
2006
|
if (s.strokeColor !== void 0 && s.strokeWidth > 0) {
|
|
1849
|
-
g.stroke({
|
|
2007
|
+
g.stroke({
|
|
2008
|
+
color: s.strokeColor,
|
|
2009
|
+
alpha: s.strokeAlpha,
|
|
2010
|
+
width: s.strokeWidth,
|
|
2011
|
+
...s.strokeCap ? { cap: s.strokeCap } : {},
|
|
2012
|
+
...s.strokeJoin ? { join: s.strokeJoin } : {}
|
|
2013
|
+
});
|
|
1850
2014
|
}
|
|
1851
2015
|
}
|
|
1852
2016
|
function drawRectFromState(g, s) {
|
|
@@ -1873,6 +2037,34 @@ function drawEllipseFromState(g, s) {
|
|
|
1873
2037
|
const ay = s.anchorY ?? 0.5;
|
|
1874
2038
|
g.ellipse((0.5 - ax) * 2 * rx, (0.5 - ay) * 2 * ry, rx, ry);
|
|
1875
2039
|
}
|
|
2040
|
+
var DEG2 = Math.PI / 180;
|
|
2041
|
+
function drawArcFromState(g, s) {
|
|
2042
|
+
const r = s.radius ?? 0;
|
|
2043
|
+
const ri = Math.max(0, Math.min(s.innerRadius ?? 0, r));
|
|
2044
|
+
const startDeg = s.startAngle ?? 0;
|
|
2045
|
+
let endDeg = s.endAngle ?? 360;
|
|
2046
|
+
if (!(r > 0) || endDeg === startDeg) return;
|
|
2047
|
+
const filled = !!s.fillStyle || s.fillColor !== void 0;
|
|
2048
|
+
if (Math.abs(endDeg - startDeg) >= 360) {
|
|
2049
|
+
if (!filled) {
|
|
2050
|
+
g.circle(0, 0, r);
|
|
2051
|
+
return;
|
|
2052
|
+
}
|
|
2053
|
+
endDeg = startDeg + Math.sign(endDeg - startDeg) * 359.999;
|
|
2054
|
+
}
|
|
2055
|
+
const a0 = startDeg * DEG2, a1 = endDeg * DEG2;
|
|
2056
|
+
const ccw = a1 < a0;
|
|
2057
|
+
if (filled) g.moveTo(r * Math.cos(a0), r * Math.sin(a0));
|
|
2058
|
+
g.arc(0, 0, r, a0, a1, ccw);
|
|
2059
|
+
if (!filled) return;
|
|
2060
|
+
if (ri > 0) {
|
|
2061
|
+
g.lineTo(ri * Math.cos(a1), ri * Math.sin(a1));
|
|
2062
|
+
g.arc(0, 0, ri, a1, a0, !ccw);
|
|
2063
|
+
} else {
|
|
2064
|
+
g.lineTo(0, 0);
|
|
2065
|
+
}
|
|
2066
|
+
g.closePath();
|
|
2067
|
+
}
|
|
1876
2068
|
function makeLineDraw(spec, scope) {
|
|
1877
2069
|
const fx = num(spec.from[0], scope);
|
|
1878
2070
|
const fy = num(spec.from[1], scope);
|
|
@@ -1901,7 +2093,8 @@ function makePathDraw(spec) {
|
|
|
1901
2093
|
var STATE_DRAWERS = {
|
|
1902
2094
|
rect: drawRectFromState,
|
|
1903
2095
|
circle: drawCircleFromState,
|
|
1904
|
-
ellipse: drawEllipseFromState
|
|
2096
|
+
ellipse: drawEllipseFromState,
|
|
2097
|
+
arc: drawArcFromState
|
|
1905
2098
|
};
|
|
1906
2099
|
function makeDrawGeometry(spec, scope, state) {
|
|
1907
2100
|
const stateDrawer = STATE_DRAWERS[spec.shape];
|
|
@@ -1928,9 +2121,10 @@ function bindLiveKeyframes(timeline, state, liveKeys, keyframes, parentDuration,
|
|
|
1928
2121
|
if (live) {
|
|
1929
2122
|
for (const [k, v] of Object.entries(live)) {
|
|
1930
2123
|
const resolved = resolveLiveValue(k, v, scope);
|
|
1931
|
-
|
|
1932
|
-
|
|
1933
|
-
|
|
2124
|
+
const live2 = state;
|
|
2125
|
+
revertibleSet(timeline, at, () => live2[k], (v2) => {
|
|
2126
|
+
live2[k] = v2;
|
|
2127
|
+
}, resolved);
|
|
1934
2128
|
}
|
|
1935
2129
|
}
|
|
1936
2130
|
}
|
|
@@ -1989,7 +2183,7 @@ function numOrZero(v, scope) {
|
|
|
1989
2183
|
var _CompositionSequence = null;
|
|
1990
2184
|
async function getCompositionSequence() {
|
|
1991
2185
|
if (!_CompositionSequence) {
|
|
1992
|
-
_CompositionSequence = (await import('./Composition-
|
|
2186
|
+
_CompositionSequence = (await import('./Composition-TUCRSMJU.js')).CompositionSequence;
|
|
1993
2187
|
}
|
|
1994
2188
|
return _CompositionSequence;
|
|
1995
2189
|
}
|
|
@@ -2026,6 +2220,6 @@ async function buildSequenceTree(specs, parent, root) {
|
|
|
2026
2220
|
return out;
|
|
2027
2221
|
}
|
|
2028
2222
|
|
|
2029
|
-
export { CameraSequence, DEFAULT_FOV, DEG, Sequence, buildScope, buildSequenceTree, cameraBasis, collectPropKeys, describeLayer, evaluateExpr, homeCamera, homeDistance, lintText, lintTiming, projectLayer, registerSequenceType, resolveAt };
|
|
2030
|
-
//# sourceMappingURL=chunk-
|
|
2031
|
-
//# sourceMappingURL=chunk-
|
|
2223
|
+
export { CameraSequence, DEFAULT_FOV, DEG, NEAR, Sequence, buildScope, buildSequenceTree, cameraBasis, collectPropKeys, describeLayer, evaluateExpr, homeCamera, homeDistance, lintText, lintTiming, projectLayer, registerSequenceType, resolveAt, summarizeWarnings };
|
|
2224
|
+
//# sourceMappingURL=chunk-UBPZLGLU.js.map
|
|
2225
|
+
//# sourceMappingURL=chunk-UBPZLGLU.js.map
|