pixi-effects 0.19.0 → 0.20.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 +6 -6
- package/ai/SKILL.md +1 -0
- package/ai/chat-template.html +3 -3
- package/ai/reference/cheatsheet.md +7 -6
- package/ai/reference/pitfalls.md +5 -0
- package/ai/reference/recipes.md +52 -0
- package/ai/template.html +5 -5
- package/ai/tools/check.mjs +15 -3
- package/dist/{Base-B4WbUJO2.d.ts → Base-CzfLGoDr.d.ts} +9 -1
- package/dist/{Base-i88XXaiP.d.cts → Base-wYJQ2g5Q.d.cts} +9 -1
- package/dist/Composition-6PA4C4TV.js +5 -0
- package/dist/{Composition-QBKEEJBV.js.map → Composition-6PA4C4TV.js.map} +1 -1
- package/dist/Composition-LL2XXU5N.cjs +14 -0
- package/dist/{Composition-KYNPRWK3.cjs.map → Composition-LL2XXU5N.cjs.map} +1 -1
- package/dist/Controller.cjs +2 -2
- package/dist/Controller.d.cts +2 -2
- package/dist/Controller.d.ts +2 -2
- package/dist/Controller.js +1 -1
- package/dist/{Movie-8IrqL3kO.d.ts → Movie-CBxGH5ms.d.ts} +8 -2
- package/dist/{Movie-CpmdNadg.d.cts → Movie-CzzJw8A-.d.cts} +8 -2
- package/dist/Presenter.cjs +2 -2
- package/dist/Presenter.d.cts +2 -2
- package/dist/Presenter.d.ts +2 -2
- package/dist/Presenter.js +1 -1
- package/dist/{chunk-YRXTKOV5.js → chunk-DQHXVNOI.js} +282 -23
- package/dist/chunk-DQHXVNOI.js.map +1 -0
- package/dist/{chunk-CTZRFSVU.cjs → chunk-FFYA3UBU.cjs} +144 -37
- package/dist/chunk-FFYA3UBU.cjs.map +1 -0
- package/dist/{chunk-DKGG7WD4.js → chunk-MNM56B3X.js} +6 -3
- package/dist/chunk-MNM56B3X.js.map +1 -0
- package/dist/{chunk-VTBT6NNE.cjs → chunk-NO26HWR7.cjs} +294 -30
- package/dist/chunk-NO26HWR7.cjs.map +1 -0
- package/dist/{chunk-B3YB2TNY.js → chunk-TSPMKV2F.js} +120 -13
- package/dist/chunk-TSPMKV2F.js.map +1 -0
- package/dist/{chunk-UQBGW5DO.cjs → chunk-WTRKDIKH.cjs} +6 -3
- package/dist/chunk-WTRKDIKH.cjs.map +1 -0
- package/dist/index.cjs +213 -90
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +4 -4
- package/dist/index.d.ts +4 -4
- package/dist/index.js +154 -31
- package/dist/index.js.map +1 -1
- package/dist/loader.css +1 -1
- package/dist/{music-4HDFULNR.js → music-CFEC7HKL.js} +3 -3
- package/dist/{music-4HDFULNR.js.map → music-CFEC7HKL.js.map} +1 -1
- package/dist/{music-3OF5C6X5.cjs → music-UAN7DXK4.cjs} +7 -7
- package/dist/{music-3OF5C6X5.cjs.map → music-UAN7DXK4.cjs.map} +1 -1
- package/dist/{sfx-MZJZXYY3.cjs → sfx-EX4PUBMV.cjs} +8 -8
- package/dist/{sfx-MZJZXYY3.cjs.map → sfx-EX4PUBMV.cjs.map} +1 -1
- package/dist/{sfx-S37DDC66.js → sfx-U3GM2MED.js} +3 -3
- package/dist/{sfx-S37DDC66.js.map → sfx-U3GM2MED.js.map} +1 -1
- package/dist/three.cjs +6 -6
- package/dist/three.d.cts +2 -2
- package/dist/three.d.ts +2 -2
- package/dist/three.js +2 -2
- package/dist/{types-bzLJ7aUx.d.ts → types-YmUaViL1.d.cts} +24 -0
- package/dist/{types-bzLJ7aUx.d.cts → types-YmUaViL1.d.ts} +24 -0
- package/docs/dsl.md +22 -0
- package/llms-full.txt +87 -6
- package/package.json +3 -1
- package/dist/Composition-KYNPRWK3.cjs +0 -14
- package/dist/Composition-QBKEEJBV.js +0 -5
- package/dist/chunk-B3YB2TNY.js.map +0 -1
- package/dist/chunk-CTZRFSVU.cjs.map +0 -1
- package/dist/chunk-DKGG7WD4.js.map +0 -1
- package/dist/chunk-UQBGW5DO.cjs.map +0 -1
- package/dist/chunk-VTBT6NNE.cjs.map +0 -1
- package/dist/chunk-YRXTKOV5.js.map +0 -1
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
3
|
+
var chunkWTRKDIKH_cjs = require('./chunk-WTRKDIKH.cjs');
|
|
4
4
|
var PIXI = require('pixi.js');
|
|
5
5
|
var gsap = require('gsap');
|
|
6
6
|
|
|
@@ -417,6 +417,58 @@ function looksLikeColorString(s) {
|
|
|
417
417
|
if (s.charCodeAt(0) === 35) return true;
|
|
418
418
|
return /^(rgb|hsl|oklab|oklch|lab|lch)\b/i.test(s);
|
|
419
419
|
}
|
|
420
|
+
function cubicBezierEase(x1, y1, x2, y2) {
|
|
421
|
+
const cx = 3 * x1, bx = 3 * (x2 - x1) - cx, ax = 1 - cx - bx;
|
|
422
|
+
const cy = 3 * y1, by = 3 * (y2 - y1) - cy, ay = 1 - cy - by;
|
|
423
|
+
const X = (t) => ((ax * t + bx) * t + cx) * t;
|
|
424
|
+
const Y = (t) => ((ay * t + by) * t + cy) * t;
|
|
425
|
+
const dX = (t) => (3 * ax * t + 2 * bx) * t + cx;
|
|
426
|
+
return (p) => {
|
|
427
|
+
if (p <= 0) return 0;
|
|
428
|
+
if (p >= 1) return 1;
|
|
429
|
+
let t = p;
|
|
430
|
+
for (let i = 0; i < 8; i++) {
|
|
431
|
+
const err = X(t) - p;
|
|
432
|
+
if (Math.abs(err) < 1e-9) return Y(t);
|
|
433
|
+
const d = dX(t);
|
|
434
|
+
if (Math.abs(d) < 1e-6) break;
|
|
435
|
+
t -= err / d;
|
|
436
|
+
}
|
|
437
|
+
let lo = 0, hi = 1;
|
|
438
|
+
t = p;
|
|
439
|
+
for (let i = 0; i < 60; i++) {
|
|
440
|
+
const x = X(t);
|
|
441
|
+
if (Math.abs(x - p) < 1e-10) break;
|
|
442
|
+
if (x < p) lo = t;
|
|
443
|
+
else hi = t;
|
|
444
|
+
t = (lo + hi) / 2;
|
|
445
|
+
}
|
|
446
|
+
return Y(t);
|
|
447
|
+
};
|
|
448
|
+
}
|
|
449
|
+
var NUM = String.raw`\s*(-?(?:\d+\.?\d*|\.\d+)(?:e[-+]?\d+)?)\s*`;
|
|
450
|
+
var RE = new RegExp(`^\\s*cubic-bezier\\(${NUM},${NUM},${NUM},${NUM}\\)\\s*$`, "i");
|
|
451
|
+
function cubicBezierProblem(name) {
|
|
452
|
+
const m = RE.exec(name);
|
|
453
|
+
if (!m) return 'expected "cubic-bezier(x1, y1, x2, y2)" with four numbers, like CSS';
|
|
454
|
+
const x1 = Number(m[1]), x2 = Number(m[3]);
|
|
455
|
+
if (x1 < 0 || x1 > 1 || x2 < 0 || x2 > 1) return "x1 and x2 must be between 0 and 1 (y1 and y2 may overshoot)";
|
|
456
|
+
return null;
|
|
457
|
+
}
|
|
458
|
+
var registered2 = false;
|
|
459
|
+
function registerCubicBezierEase() {
|
|
460
|
+
if (registered2) return;
|
|
461
|
+
registered2 = true;
|
|
462
|
+
const base = ((p) => p);
|
|
463
|
+
base.config = (x1, y1, x2, y2) => {
|
|
464
|
+
const bad = [x1, y1, x2, y2].some((v) => typeof v !== "number" || !Number.isFinite(v)) || x1 < 0 || x1 > 1 || x2 < 0 || x2 > 1;
|
|
465
|
+
return bad ? (p) => p : cubicBezierEase(x1, y1, x2, y2);
|
|
466
|
+
};
|
|
467
|
+
gsap.gsap.registerEase("cubic-bezier", base);
|
|
468
|
+
}
|
|
469
|
+
registerCubicBezierEase();
|
|
470
|
+
|
|
471
|
+
// src/core/ease.ts
|
|
420
472
|
var FAMILIES = ["power1", "power2", "power3", "power4", "back", "elastic", "bounce", "circ", "expo", "sine"];
|
|
421
473
|
var EASE_NAMES = ["none", ...FAMILIES.flatMap((f) => [`${f}.in`, `${f}.out`, `${f}.inOut`])];
|
|
422
474
|
var warned = /* @__PURE__ */ new Set();
|
|
@@ -429,6 +481,13 @@ function checkEase(ease, where) {
|
|
|
429
481
|
console.warn(`pixi-effects: ${where}: unknown ease "${ease}" \u2014 ${problem}. GSAP would run it as its default ease, power1.out.`);
|
|
430
482
|
return;
|
|
431
483
|
}
|
|
484
|
+
if (/^\s*cubic-bezier/i.test(ease)) {
|
|
485
|
+
const problem = cubicBezierProblem(ease);
|
|
486
|
+
if (!problem || warned.has(ease)) return;
|
|
487
|
+
warned.add(ease);
|
|
488
|
+
console.warn(`pixi-effects: ${where}: unknown ease "${ease}" \u2014 ${problem}. It runs as 'none' (a straight line).`);
|
|
489
|
+
return;
|
|
490
|
+
}
|
|
432
491
|
const found = gsap.gsap.parseEase(ease);
|
|
433
492
|
if (typeof found === "function") return;
|
|
434
493
|
if (warned.has(ease)) return;
|
|
@@ -441,7 +500,7 @@ function checkEase(ease, where) {
|
|
|
441
500
|
console.warn(`pixi-effects: ${where}: "${ease}" is a family, not an ease \u2014 write ${ease.toLowerCase()}.out, ${ease.toLowerCase()}.in or ${ease.toLowerCase()}.inOut`);
|
|
442
501
|
return;
|
|
443
502
|
}
|
|
444
|
-
const guess =
|
|
503
|
+
const guess = chunkWTRKDIKH_cjs.suggestName(ease, EASE_NAMES);
|
|
445
504
|
console.warn(`pixi-effects: ${where}: unknown ease "${ease}"${guess ? ` \u2014 did you mean "${guess}"?` : ""} (GSAP would run it as its default ease, power1.out). Examples: ${EASE_NAMES.slice(0, 7).join(", ")}, back.out(1.7), elastic.out(1, 0.3), steps(8)`);
|
|
446
505
|
}
|
|
447
506
|
|
|
@@ -1051,7 +1110,7 @@ var GRAIN_KEYS = ["amount", "size", "seed", "fps", "color"];
|
|
|
1051
1110
|
var GrainFilter = class extends PIXI.Filter {
|
|
1052
1111
|
_fps;
|
|
1053
1112
|
constructor(options = {}) {
|
|
1054
|
-
|
|
1113
|
+
chunkWTRKDIKH_cjs.warnUnknownOptions("grain filter", options, GRAIN_KEYS);
|
|
1055
1114
|
const { amount = 0.08, size = 1.5, seed = 0, fps = 24, color = 0 } = options;
|
|
1056
1115
|
super({
|
|
1057
1116
|
glProgram: PIXI.GlProgram.from({ vertex: GL_VERTEX, fragment: GL_FRAGMENT2, name: "grain-filter" }),
|
|
@@ -1103,7 +1162,7 @@ var GrainFilter = class extends PIXI.Filter {
|
|
|
1103
1162
|
}
|
|
1104
1163
|
/** The movie calls this with the time (s) of the frame it is about to draw: the grain is new every 1/fps s. */
|
|
1105
1164
|
setTime(t) {
|
|
1106
|
-
this.u.uFrame = this._fps > 0 ? Math.floor(t * this._fps + 1e-
|
|
1165
|
+
this.u.uFrame = this._fps > 0 ? Math.floor(t * this._fps + 1e-3) : 0;
|
|
1107
1166
|
}
|
|
1108
1167
|
};
|
|
1109
1168
|
|
|
@@ -1159,7 +1218,7 @@ function isNamedFilterType(t) {
|
|
|
1159
1218
|
return !NOT_NAMED.has(t);
|
|
1160
1219
|
}
|
|
1161
1220
|
function unknownType(t) {
|
|
1162
|
-
const guess =
|
|
1221
|
+
const guess = chunkWTRKDIKH_cjs.suggestName(t, FILTER_TYPES);
|
|
1163
1222
|
return new Error(`pixi-effects: unknown filter type "${t}"${guess ? ` \u2014 did you mean "${guess}"?` : ""} (valid: ${[...FILTER_TYPES, "chromaKey", "custom"].join(", ")})`);
|
|
1164
1223
|
}
|
|
1165
1224
|
var library = null;
|
|
@@ -1208,7 +1267,7 @@ function colorMatrix(params) {
|
|
|
1208
1267
|
const preset = params.preset;
|
|
1209
1268
|
if (preset !== void 0) {
|
|
1210
1269
|
if (!MATRIX_PRESETS.includes(preset)) {
|
|
1211
|
-
const guess =
|
|
1270
|
+
const guess = chunkWTRKDIKH_cjs.suggestName(preset, MATRIX_PRESETS);
|
|
1212
1271
|
throw new Error(`pixi-effects: colorMatrix preset "${preset}" is not one of ${MATRIX_PRESETS.join(", ")}${guess ? ` \u2014 did you mean "${guess}"?` : ""}`);
|
|
1213
1272
|
}
|
|
1214
1273
|
f[preset === "grayscale" ? "desaturate" : preset].call(f);
|
|
@@ -1318,13 +1377,21 @@ var Sequence = class {
|
|
|
1318
1377
|
pathRouters() {
|
|
1319
1378
|
return {};
|
|
1320
1379
|
}
|
|
1380
|
+
/**
|
|
1381
|
+
* The `initial` and `keyframes` that go onto the display object. A layer whose `time` runs a clock (video, composition) takes `time`
|
|
1382
|
+
* out of them: it is not a property of the display object.
|
|
1383
|
+
*/
|
|
1384
|
+
displayProps() {
|
|
1385
|
+
return { initial: this.spec.initial, keyframes: this.spec.keyframes };
|
|
1386
|
+
}
|
|
1321
1387
|
bindTimeline(timeline, offset = 0) {
|
|
1322
1388
|
if (!this.target) return;
|
|
1323
1389
|
const scope = this.scope();
|
|
1324
1390
|
const routers = this.pathRouters();
|
|
1325
1391
|
const startTime = offset + this.at;
|
|
1326
|
-
|
|
1327
|
-
|
|
1392
|
+
const { initial, keyframes } = this.displayProps();
|
|
1393
|
+
applyInitial(this.target, initial, scope, [], routers);
|
|
1394
|
+
applyKeyframes(timeline, this.target, keyframes, this.duration, scope, [], startTime, routers);
|
|
1328
1395
|
const endTime = startTime + this.duration;
|
|
1329
1396
|
this.absoluteStart = startTime;
|
|
1330
1397
|
if (this.keepHidden) return;
|
|
@@ -1377,11 +1444,11 @@ function collectPropKeys(spec) {
|
|
|
1377
1444
|
|
|
1378
1445
|
// src/core/layerKeys.ts
|
|
1379
1446
|
var COMMON = ["type", "name", "parent", "at", "duration", "initial", "keyframes", "filters", "filterArea", "mask", "maskInverted", "blendMode", "threeD", "hideBehindCamera"];
|
|
1380
|
-
var VIDEO = [...COMMON, "asset", "loop", "audio", "volume"];
|
|
1447
|
+
var VIDEO = [...COMMON, "asset", "loop", "audio", "volume", "speed"];
|
|
1381
1448
|
var IMAGE = [...COMMON, "asset", "colorSpace"];
|
|
1382
1449
|
var TEXT = [...COMMON, "text", "format", "style", "colorSpace", "fillGradient"];
|
|
1383
|
-
var AUDIO = [...COMMON, "volume", "asset", "loop", "sfx", "music"];
|
|
1384
|
-
var COMPOSITION = [...COMMON, "width", "height", "sequences", "transitions"];
|
|
1450
|
+
var AUDIO = [...COMMON, "volume", "asset", "loop", "sfx", "music", "speed"];
|
|
1451
|
+
var COMPOSITION = [...COMMON, "width", "height", "sequences", "transitions", "speed"];
|
|
1385
1452
|
var CAMERA = [...COMMON];
|
|
1386
1453
|
var NULL = [...COMMON];
|
|
1387
1454
|
var SHAPE = [...COMMON, "shape", "fillGradient", "colorSpace", "strokeCap", "strokeJoin"];
|
|
@@ -1471,6 +1538,7 @@ var PROP_KEYS = /* @__PURE__ */ new Set([
|
|
|
1471
1538
|
"visibleChars",
|
|
1472
1539
|
"text",
|
|
1473
1540
|
"volume",
|
|
1541
|
+
"time",
|
|
1474
1542
|
// camera
|
|
1475
1543
|
"lookAtX",
|
|
1476
1544
|
"lookAtY",
|
|
@@ -1547,38 +1615,191 @@ function lintText(spec, warn = defaultWarn) {
|
|
|
1547
1615
|
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').`);
|
|
1548
1616
|
}
|
|
1549
1617
|
}
|
|
1618
|
+
var REMAPPABLE = /* @__PURE__ */ new Set(["video", "audio", "composition"]);
|
|
1619
|
+
var REMAP_NAMES = /* @__PURE__ */ new Set(["time", "timeRemap", "reverse"]);
|
|
1620
|
+
var TIME_BAGS = ["set", "to", "from"];
|
|
1621
|
+
function lintRemap(spec, warn) {
|
|
1622
|
+
const s = spec;
|
|
1623
|
+
const who = describeLayer(spec);
|
|
1624
|
+
const kfs = s.keyframes ?? [];
|
|
1625
|
+
const bags = [s.initial, ...kfs.flatMap((kf) => TIME_BAGS.map((b) => kf[b]))];
|
|
1626
|
+
const timeInInitial = !!s.initial && s.initial.time !== void 0;
|
|
1627
|
+
const timeInKeyframes = kfs.some((kf) => TIME_BAGS.some((b) => kf[b] && kf[b].time !== void 0));
|
|
1628
|
+
const timed = timeInInitial || timeInKeyframes;
|
|
1629
|
+
if (bags.some((bag) => bag && bag.speed !== void 0)) {
|
|
1630
|
+
warn(`pixi-effects: ${who}: speed is a fixed setting, not an animatable property: write it on the layer (speed: 2); to change the speed over time, animate time (keyframes: [{ at: 0, from: { time: 0 }, to: { time: 4 }, duration: 2, ease: 'power2.in' }])`);
|
|
1631
|
+
}
|
|
1632
|
+
if (!REMAPPABLE.has(spec.type)) {
|
|
1633
|
+
if (timed) warn(`pixi-effects: ${who}: "time" only works on video, audio and composition layers; put this layer in a composition and remap that (it is ignored here)`);
|
|
1634
|
+
return;
|
|
1635
|
+
}
|
|
1636
|
+
if (s.reverse !== void 0) warn(`pixi-effects: ${who}: "reverse" is not a key: write speed: -1 to play backward`);
|
|
1637
|
+
if (s.timeRemap !== void 0) warn(`pixi-effects: ${who}: "timeRemap" is not a key: animate time in keyframes (from / to / set), or write speed`);
|
|
1638
|
+
if (s.time !== void 0) warn(`pixi-effects: ${who}: "time" belongs in initial or keyframes (initial: { time: 2 }), not on the layer`);
|
|
1639
|
+
if (spec.type === "audio" && (s.sfx !== void 0 || s.music !== void 0) && (s.speed !== void 0 || timed)) {
|
|
1640
|
+
warn(`pixi-effects: ${who}: speed and time do not apply to a synthesised sound (sfx, music); change an sfx's pitch with pitch (semitones), or put it in a composition and remap that`);
|
|
1641
|
+
return;
|
|
1642
|
+
}
|
|
1643
|
+
if (s.speed !== void 0 && (typeof s.speed !== "number" || !Number.isFinite(s.speed) || s.speed === 0)) {
|
|
1644
|
+
warn(`pixi-effects: ${who}: speed ${JSON.stringify(s.speed)} cannot be used: write a number other than 0 (negative plays backward); to hold a moment, key time to the same value twice`);
|
|
1645
|
+
}
|
|
1646
|
+
if (s.speed !== void 0 && timeInKeyframes) {
|
|
1647
|
+
warn(`pixi-effects: ${who}: speed and keyframed time are both set; time wins and speed is ignored. Use one of them`);
|
|
1648
|
+
}
|
|
1649
|
+
if (timeInInitial && typeof s.initial.time !== "number") {
|
|
1650
|
+
warn(`pixi-effects: ${who}: initial.time must be a number of seconds, got ${JSON.stringify(s.initial.time)}`);
|
|
1651
|
+
}
|
|
1652
|
+
kfs.forEach((kf, i) => {
|
|
1653
|
+
for (const b of TIME_BAGS) {
|
|
1654
|
+
const v = kf[b]?.time;
|
|
1655
|
+
if (v !== void 0 && typeof v !== "number" && typeof v !== "string") warn(`pixi-effects: ${who}: keyframes[${i}].${b}.time must be a number of seconds, got ${JSON.stringify(v)}`);
|
|
1656
|
+
}
|
|
1657
|
+
});
|
|
1658
|
+
}
|
|
1550
1659
|
function lintKeys(spec, warn = defaultWarn) {
|
|
1551
1660
|
const who = describeLayer(spec);
|
|
1552
1661
|
const valid = layerKeys(spec);
|
|
1553
1662
|
if (valid) {
|
|
1554
1663
|
for (const key of Object.keys(spec)) {
|
|
1555
1664
|
if (valid.includes(key) || spec[key] === void 0) continue;
|
|
1556
|
-
|
|
1665
|
+
if (REMAPPABLE.has(spec.type) && REMAP_NAMES.has(key)) continue;
|
|
1666
|
+
const guess = chunkWTRKDIKH_cjs.suggestName(key, valid.filter((k) => k !== "type"));
|
|
1557
1667
|
const owners = kindsWithKey(key);
|
|
1558
1668
|
const belongs = owners.length ? ` (it belongs to ${owners.slice(0, 3).join(", ")})` : "";
|
|
1559
1669
|
const hint = guess ? ` \u2014 did you mean "${guess}"?${belongs}` : belongs;
|
|
1560
1670
|
warn(`pixi-effects: ${who}: "${key}" is not a ${kindName(spec)} key${hint}. Valid keys: ${valid.join(", ")}`);
|
|
1561
1671
|
}
|
|
1562
1672
|
}
|
|
1673
|
+
lintRemap(spec, warn);
|
|
1563
1674
|
const said = /* @__PURE__ */ new Set();
|
|
1564
1675
|
const bags = [spec.initial, ...(spec.keyframes ?? []).flatMap((kf) => [kf.set, kf.to, kf.from])];
|
|
1565
1676
|
for (const bag of bags) {
|
|
1566
1677
|
for (const key of Object.keys(bag ?? {})) {
|
|
1567
1678
|
if (bag[key] === void 0) continue;
|
|
1568
|
-
if (PROP_KEYS.has(key) || key.includes(".") || /^gradient/i.test(key) || said.has(key)) continue;
|
|
1679
|
+
if (PROP_KEYS.has(key) || key.includes(".") || /^gradient/i.test(key) || said.has(key) || key === "speed") continue;
|
|
1569
1680
|
said.add(key);
|
|
1570
|
-
const guess =
|
|
1681
|
+
const guess = chunkWTRKDIKH_cjs.suggestName(key, [...PROP_KEYS]);
|
|
1571
1682
|
warn(`pixi-effects: ${who}: "${key}" is not an animatable property${guess ? ` \u2014 did you mean "${guess}"?` : ""} (in initial, set, to or from). See the cheatsheet for the properties of this kind of layer`);
|
|
1572
1683
|
}
|
|
1573
1684
|
}
|
|
1574
1685
|
if (spec.type === "text" && spec.style && typeof spec.style === "object") {
|
|
1575
1686
|
for (const key of Object.keys(spec.style)) {
|
|
1576
1687
|
if (STYLE_KEYS.includes(key) || spec.style[key] === void 0) continue;
|
|
1577
|
-
const guess =
|
|
1688
|
+
const guess = chunkWTRKDIKH_cjs.suggestName(key, STYLE_KEYS);
|
|
1578
1689
|
warn(`pixi-effects: ${who}: style.${key} is not a text style key${guess ? ` \u2014 did you mean "${guess}"?` : ""} (it is ignored). Keys: ${STYLE_KEYS.join(", ")}`);
|
|
1579
1690
|
}
|
|
1580
1691
|
}
|
|
1581
1692
|
}
|
|
1693
|
+
var BAGS = ["set", "to", "from"];
|
|
1694
|
+
function timeRemapOf(spec, prop = "time") {
|
|
1695
|
+
const hasInitial = !!spec.initial && "time" in spec.initial;
|
|
1696
|
+
const hasKf = (spec.keyframes ?? []).some((kf) => BAGS.some((b) => kf[b] && "time" in kf[b]));
|
|
1697
|
+
const speed = typeof spec.speed === "number" && Number.isFinite(spec.speed) && spec.speed !== 0 ? spec.speed : void 0;
|
|
1698
|
+
if (!hasInitial && !hasKf && speed === void 0) return null;
|
|
1699
|
+
const timeKfs = [];
|
|
1700
|
+
const restKfs = [];
|
|
1701
|
+
for (const kf of spec.keyframes ?? []) {
|
|
1702
|
+
const t = { ...kf }, r = { ...kf };
|
|
1703
|
+
let touched = false, left = false;
|
|
1704
|
+
for (const b of BAGS) {
|
|
1705
|
+
const bag = kf[b];
|
|
1706
|
+
if (!bag) {
|
|
1707
|
+
delete t[b];
|
|
1708
|
+
delete r[b];
|
|
1709
|
+
continue;
|
|
1710
|
+
}
|
|
1711
|
+
const { time, ...others } = bag;
|
|
1712
|
+
if ("time" in bag) {
|
|
1713
|
+
touched = true;
|
|
1714
|
+
t[b] = { [prop]: time };
|
|
1715
|
+
} else delete t[b];
|
|
1716
|
+
if (Object.keys(others).length) {
|
|
1717
|
+
r[b] = others;
|
|
1718
|
+
left = true;
|
|
1719
|
+
} else delete r[b];
|
|
1720
|
+
}
|
|
1721
|
+
if (touched) timeKfs.push(t);
|
|
1722
|
+
if (!touched || left) restKfs.push(r);
|
|
1723
|
+
}
|
|
1724
|
+
let restInitial = spec.initial;
|
|
1725
|
+
let start;
|
|
1726
|
+
if (hasInitial) {
|
|
1727
|
+
const { time, ...others } = spec.initial;
|
|
1728
|
+
start = typeof time === "number" && Number.isFinite(time) ? time : void 0;
|
|
1729
|
+
restInitial = others;
|
|
1730
|
+
}
|
|
1731
|
+
return { timeKfs, restKfs: restKfs.length ? restKfs : void 0, restInitial, start, speed };
|
|
1732
|
+
}
|
|
1733
|
+
function resolveFromEnd(remap, length, prop) {
|
|
1734
|
+
const fix = (v) => typeof v === "number" && v < 0 ? Math.max(0, length + v) : v;
|
|
1735
|
+
const timeKfs = remap.timeKfs.map((kf) => {
|
|
1736
|
+
const out = { ...kf };
|
|
1737
|
+
for (const b of BAGS) {
|
|
1738
|
+
const bag = kf[b];
|
|
1739
|
+
if (bag && prop in bag) out[b] = { ...bag, [prop]: fix(bag[prop]) };
|
|
1740
|
+
}
|
|
1741
|
+
return out;
|
|
1742
|
+
});
|
|
1743
|
+
return { ...remap, timeKfs, start: remap.start === void 0 ? void 0 : fix(remap.start) };
|
|
1744
|
+
}
|
|
1745
|
+
function remapOf(spec, prop, length) {
|
|
1746
|
+
const r = timeRemapOf(spec, prop);
|
|
1747
|
+
return r && length !== null ? resolveFromEnd(r, length, prop) : r;
|
|
1748
|
+
}
|
|
1749
|
+
function contentLength(remap, duration) {
|
|
1750
|
+
let m = duration;
|
|
1751
|
+
if (remap.speed !== void 0) m = Math.max(m, Math.abs(remap.speed) * duration);
|
|
1752
|
+
if (remap.start !== void 0) m = Math.max(m, remap.start + (remap.speed ?? 1) * duration);
|
|
1753
|
+
for (const kf of remap.timeKfs) {
|
|
1754
|
+
for (const b of BAGS) {
|
|
1755
|
+
const bag = kf[b];
|
|
1756
|
+
const v = bag && Object.values(bag)[0];
|
|
1757
|
+
if (typeof v === "number") m = Math.max(m, v);
|
|
1758
|
+
}
|
|
1759
|
+
}
|
|
1760
|
+
return m;
|
|
1761
|
+
}
|
|
1762
|
+
function bindClock(timeline, clock, prop, remap, duration, at, scope) {
|
|
1763
|
+
if (remap.timeKfs.length) {
|
|
1764
|
+
if (remap.start !== void 0) timeline.set(clock, { [prop]: remap.start }, at);
|
|
1765
|
+
applyKeyframes(timeline, clock, remap.timeKfs, duration, scope, [], at);
|
|
1766
|
+
return;
|
|
1767
|
+
}
|
|
1768
|
+
const s = remap.speed ?? 1;
|
|
1769
|
+
const from = remap.start ?? (s < 0 ? -s * duration : 0);
|
|
1770
|
+
timeline.fromTo(clock, { [prop]: from }, { [prop]: from + s * duration, duration, ease: "none" }, at);
|
|
1771
|
+
}
|
|
1772
|
+
function clockTable(remap, prop, duration, at, scope, to) {
|
|
1773
|
+
const probe = gsap.gsap.timeline({ paused: true });
|
|
1774
|
+
const clock = { [prop]: remap.start ?? 0 };
|
|
1775
|
+
bindClock(probe, clock, prop, remap, duration, at, scope);
|
|
1776
|
+
probe.time(probe.duration());
|
|
1777
|
+
probe.time(0);
|
|
1778
|
+
const h = 1 / 1e3;
|
|
1779
|
+
const n = Math.max(2, Math.ceil(to / h) + 2);
|
|
1780
|
+
const tab = new Float64Array(n);
|
|
1781
|
+
let min = Infinity, max = -Infinity;
|
|
1782
|
+
for (let k = 0; k < n; k++) {
|
|
1783
|
+
probe.time(k * h);
|
|
1784
|
+
const v = clock[prop];
|
|
1785
|
+
tab[k] = v;
|
|
1786
|
+
const t = k * h;
|
|
1787
|
+
if (t >= at && t <= at + duration) {
|
|
1788
|
+
if (v < min) min = v;
|
|
1789
|
+
if (v > max) max = v;
|
|
1790
|
+
}
|
|
1791
|
+
}
|
|
1792
|
+
probe.kill();
|
|
1793
|
+
return {
|
|
1794
|
+
at(t) {
|
|
1795
|
+
const x = Math.min(Math.max(t / h, 0), n - 1.000001);
|
|
1796
|
+
const k = Math.floor(x), f = x - k;
|
|
1797
|
+
return tab[k] * (1 - f) + tab[k + 1] * f;
|
|
1798
|
+
},
|
|
1799
|
+
min: Number.isFinite(min) ? min : 0,
|
|
1800
|
+
max: Number.isFinite(max) ? max : 0
|
|
1801
|
+
};
|
|
1802
|
+
}
|
|
1582
1803
|
|
|
1583
1804
|
// src/space/math.ts
|
|
1584
1805
|
var DEG = Math.PI / 180;
|
|
@@ -2108,7 +2329,7 @@ function validateGradientKeyframes(spec, who, warn = (m) => console.warn(m), kin
|
|
|
2108
2329
|
const p = value;
|
|
2109
2330
|
for (const k of Object.keys(p)) {
|
|
2110
2331
|
if (PATCH_KEYS.includes(k)) continue;
|
|
2111
|
-
const guess =
|
|
2332
|
+
const guess = chunkWTRKDIKH_cjs.suggestName(k, PATCH_KEYS.filter((x) => x !== "type"));
|
|
2112
2333
|
say(`fillGradient.${k} is not a gradient property${guess ? ` \u2014 did you mean "${guess}"?` : ""} (valid: ${PATCH_KEYS.join(", ")}); it is ignored`);
|
|
2113
2334
|
}
|
|
2114
2335
|
if (p.type !== void 0 && start && p.type !== start.type) say("fillGradient.type cannot change over time (linear <-> radial); it is ignored");
|
|
@@ -2479,6 +2700,7 @@ var AudioSequence = class extends Sequence {
|
|
|
2479
2700
|
_audioBuffer = null;
|
|
2480
2701
|
_synth = null;
|
|
2481
2702
|
_source = "";
|
|
2703
|
+
_remap = null;
|
|
2482
2704
|
async build() {
|
|
2483
2705
|
this.target = null;
|
|
2484
2706
|
if (this.spec.music !== void 0) return this._buildMusic(this.spec);
|
|
@@ -2487,13 +2709,16 @@ var AudioSequence = class extends Sequence {
|
|
|
2487
2709
|
this._source = `asset "${spec.asset}"`;
|
|
2488
2710
|
const data = await PIXI.Assets.get(spec.asset);
|
|
2489
2711
|
this._audioBuffer = data.audioBuffer;
|
|
2712
|
+
this._remap = remapOf(spec, "time", data.duration ?? null);
|
|
2713
|
+
const constant = this._remap && this._remap.timeKfs.length === 0 ? Math.abs(this._remap.speed ?? 1) : 1;
|
|
2490
2714
|
if (this.duration === void 0) {
|
|
2491
2715
|
const rest = Math.max(0, (this.parent?.duration ?? this.root.duration) - this.at);
|
|
2492
|
-
this.duration = spec.duration ?? (spec.loop ? rest : data.duration) ?? this.root.duration;
|
|
2716
|
+
this.duration = spec.duration ?? (spec.loop ? rest : data.duration !== void 0 ? data.duration / constant : void 0) ?? this.root.duration;
|
|
2493
2717
|
}
|
|
2494
|
-
|
|
2718
|
+
const playable = this._remap && this._remap.timeKfs.length > 0 ? Infinity : (data.duration ?? Infinity) / constant;
|
|
2719
|
+
if (!spec.loop && Number.isFinite(playable) && this.duration > playable + 0.05) {
|
|
2495
2720
|
console.warn(
|
|
2496
|
-
`pixi-effects: ${describeLayer(spec)}: audio asset "${spec.asset}"
|
|
2721
|
+
`pixi-effects: ${describeLayer(spec)}: audio asset "${spec.asset}" plays for ${playable.toFixed(1)}s (${data.duration.toFixed(1)}s at speed ${constant}) but the layer lasts ${this.duration.toFixed(1)}s, so it goes silent after ${playable.toFixed(1)}s. Add loop: true, or shorten the layer's duration.`
|
|
2497
2722
|
);
|
|
2498
2723
|
}
|
|
2499
2724
|
}
|
|
@@ -2502,7 +2727,7 @@ var AudioSequence = class extends Sequence {
|
|
|
2502
2727
|
const raw = spec;
|
|
2503
2728
|
if (raw.asset !== void 0) console.warn(`pixi-effects: ${who}: has both asset and sfx \u2014 the sfx plays; remove one`);
|
|
2504
2729
|
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)`);
|
|
2505
|
-
const { resolveSfx, renderSfx, sfxKey } = await import('./sfx-
|
|
2730
|
+
const { resolveSfx, renderSfx, sfxKey } = await import('./sfx-EX4PUBMV.cjs');
|
|
2506
2731
|
const sfx = resolveSfx(spec.sfx, spec.duration, who);
|
|
2507
2732
|
if (!sfx) return;
|
|
2508
2733
|
this.duration = sfx.length;
|
|
@@ -2521,7 +2746,7 @@ var AudioSequence = class extends Sequence {
|
|
|
2521
2746
|
const raw = spec;
|
|
2522
2747
|
if (raw.asset !== void 0) console.warn(`pixi-effects: ${who}: has both asset and music \u2014 the music plays; remove one`);
|
|
2523
2748
|
if (raw.sfx !== void 0) console.warn(`pixi-effects: ${who}: has both sfx and music \u2014 the music plays; remove one`);
|
|
2524
|
-
const { resolveMusic, renderMusic, musicLength, musicKey } = await import('./music-
|
|
2749
|
+
const { resolveMusic, renderMusic, musicLength, musicKey } = await import('./music-UAN7DXK4.cjs');
|
|
2525
2750
|
const music = resolveMusic(spec.music, who);
|
|
2526
2751
|
if (!music) return;
|
|
2527
2752
|
const natural = musicLength(music);
|
|
@@ -2547,7 +2772,9 @@ var AudioSequence = class extends Sequence {
|
|
|
2547
2772
|
const initialVolume = this.spec.volume ?? this.spec.initial?.volume ?? 1;
|
|
2548
2773
|
const t0 = baseTime + this.at;
|
|
2549
2774
|
const dur = this.duration;
|
|
2775
|
+
const sourceMap = this._remap ? clockTable(this._remap, "time", dur, t0, this.scope(), t0 + dur).at : void 0;
|
|
2550
2776
|
out.push({
|
|
2777
|
+
...sourceMap ? { sourceMap } : {},
|
|
2551
2778
|
...this._audioBuffer ? { buffer: this._audioBuffer } : { synth: this._synth },
|
|
2552
2779
|
layer: describeLayer(this.spec),
|
|
2553
2780
|
source: this._source,
|
|
@@ -2606,7 +2833,7 @@ var FrameCache = class {
|
|
|
2606
2833
|
this.capacity = options.capacity ?? 30;
|
|
2607
2834
|
}
|
|
2608
2835
|
_key(time) {
|
|
2609
|
-
return Math.round(time *
|
|
2836
|
+
return Math.round(time * 1e6);
|
|
2610
2837
|
}
|
|
2611
2838
|
async getFrameAt(time) {
|
|
2612
2839
|
const key = this._key(time);
|
|
@@ -2671,6 +2898,15 @@ var FrameCache = class {
|
|
|
2671
2898
|
}
|
|
2672
2899
|
};
|
|
2673
2900
|
|
|
2901
|
+
// src/core/sourceTime.ts
|
|
2902
|
+
var FRAME_EPS = 5e-5;
|
|
2903
|
+
function sourceLookup(v, sourceDuration, loop) {
|
|
2904
|
+
if (!(sourceDuration > 0)) return Math.max(0, v);
|
|
2905
|
+
const w = v + FRAME_EPS;
|
|
2906
|
+
if (loop) return (w % sourceDuration + sourceDuration) % sourceDuration;
|
|
2907
|
+
return Math.min(Math.max(w, 0), sourceDuration);
|
|
2908
|
+
}
|
|
2909
|
+
|
|
2674
2910
|
// src/sequences/Video.ts
|
|
2675
2911
|
var VideoSequence = class extends Sequence {
|
|
2676
2912
|
_sourceDuration = 0;
|
|
@@ -2679,9 +2915,15 @@ var VideoSequence = class extends Sequence {
|
|
|
2679
2915
|
_canvas = null;
|
|
2680
2916
|
_ctx = null;
|
|
2681
2917
|
_drawSeq = 0;
|
|
2918
|
+
/** The playhead value (seconds in the file) the timeline last wrote: already remapped, and local inside a remapped composition. */
|
|
2919
|
+
_cur = 0;
|
|
2920
|
+
_remap = null;
|
|
2921
|
+
/** Movie asks this layer to draw the frame its own timeline is at, not the one for a time it computed. */
|
|
2922
|
+
selfTimed = true;
|
|
2682
2923
|
async build() {
|
|
2683
2924
|
const data = await PIXI.Assets.get(this.spec.asset);
|
|
2684
2925
|
this._sourceDuration = data.duration;
|
|
2926
|
+
this._remap = remapOf(this.spec, "currentTime", this._sourceDuration);
|
|
2685
2927
|
this._audioBuffer = this.spec.audio !== false ? data.audioBuffer : null;
|
|
2686
2928
|
this._cache = new FrameCache(data.sink, { capacity: 30 });
|
|
2687
2929
|
const probeFrame = await this._cache.getFrameAt(0);
|
|
@@ -2700,7 +2942,8 @@ var VideoSequence = class extends Sequence {
|
|
|
2700
2942
|
this.intrinsicWidth = w;
|
|
2701
2943
|
this.intrinsicHeight = h;
|
|
2702
2944
|
if (this.duration === void 0) {
|
|
2703
|
-
this.
|
|
2945
|
+
const constant = this._remap && this._remap.timeKfs.length === 0 ? Math.abs(this._remap.speed ?? 1) : 1;
|
|
2946
|
+
this.duration = this.spec.duration ?? (data.duration ?? this.root.duration * constant) / constant;
|
|
2704
2947
|
}
|
|
2705
2948
|
let currentTime = 0;
|
|
2706
2949
|
const seq = this;
|
|
@@ -2710,8 +2953,9 @@ var VideoSequence = class extends Sequence {
|
|
|
2710
2953
|
},
|
|
2711
2954
|
set(v) {
|
|
2712
2955
|
currentTime = v;
|
|
2956
|
+
seq._cur = v;
|
|
2713
2957
|
const mySeq = ++seq._drawSeq;
|
|
2714
|
-
const lookup =
|
|
2958
|
+
const lookup = sourceLookup(v, seq._sourceDuration, !!seq.spec.loop);
|
|
2715
2959
|
seq._cache.getFrameAt(lookup).then((frame) => {
|
|
2716
2960
|
if (mySeq !== seq._drawSeq) return;
|
|
2717
2961
|
if (!frame || !seq._ctx) return;
|
|
@@ -2724,21 +2968,33 @@ var VideoSequence = class extends Sequence {
|
|
|
2724
2968
|
});
|
|
2725
2969
|
this.buildFilters();
|
|
2726
2970
|
}
|
|
2971
|
+
displayProps() {
|
|
2972
|
+
const r = this._remap;
|
|
2973
|
+
return r ? { initial: r.restInitial, keyframes: r.restKfs } : super.displayProps();
|
|
2974
|
+
}
|
|
2727
2975
|
bindTimeline(timeline, offset = 0) {
|
|
2728
2976
|
super.bindTimeline(timeline, offset);
|
|
2977
|
+
const at = offset + this.at;
|
|
2978
|
+
if (this._remap) {
|
|
2979
|
+
bindClock(timeline, this.target, "currentTime", this._remap, this.duration, at, this.scope());
|
|
2980
|
+
return;
|
|
2981
|
+
}
|
|
2729
2982
|
const playDuration = this.spec.loop ? this.duration : Math.min(this.duration, this._sourceDuration);
|
|
2730
2983
|
timeline.fromTo(
|
|
2731
2984
|
this.target,
|
|
2732
2985
|
{ currentTime: 0 },
|
|
2733
2986
|
{ currentTime: playDuration, duration: playDuration, ease: "none" },
|
|
2734
|
-
|
|
2987
|
+
at
|
|
2735
2988
|
// offset = start of the enclosing composition(s); dropping it misplaced videos inside nested compositions
|
|
2736
2989
|
);
|
|
2737
2990
|
}
|
|
2738
2991
|
collectAudio(out, baseTime) {
|
|
2739
2992
|
if (!this._audioBuffer) return;
|
|
2740
2993
|
const initialVolume = this.spec.volume ?? 1;
|
|
2994
|
+
const t0 = baseTime + this.at;
|
|
2995
|
+
const sourceMap = this._remap ? clockTable(this._remap, "currentTime", this.duration, t0, this.scope(), t0 + this.duration).at : void 0;
|
|
2741
2996
|
out.push({
|
|
2997
|
+
...sourceMap ? { sourceMap } : {},
|
|
2742
2998
|
buffer: this._audioBuffer,
|
|
2743
2999
|
layer: describeLayer(this.spec),
|
|
2744
3000
|
source: `video "${this.spec.asset}"`,
|
|
@@ -2749,9 +3005,12 @@ var VideoSequence = class extends Sequence {
|
|
|
2749
3005
|
volumeKeyframes: []
|
|
2750
3006
|
});
|
|
2751
3007
|
}
|
|
2752
|
-
|
|
3008
|
+
/** Draw the frame the playhead is at NOW (`_cur`). The argument (a time Movie worked out for layers that need it) is not used. */
|
|
3009
|
+
async awaitFrameAt(_time) {
|
|
3010
|
+
const time = this._cur;
|
|
3011
|
+
if (!this.keepHidden && !this.target?.renderable) return;
|
|
2753
3012
|
const mySeq = ++this._drawSeq;
|
|
2754
|
-
const lookup =
|
|
3013
|
+
const lookup = sourceLookup(time, this._sourceDuration, !!this.spec.loop);
|
|
2755
3014
|
let frame = null;
|
|
2756
3015
|
try {
|
|
2757
3016
|
frame = await this._cache.getFrameAt(lookup);
|
|
@@ -3481,7 +3740,7 @@ function numOrZero(v, scope) {
|
|
|
3481
3740
|
var _CompositionSequence = null;
|
|
3482
3741
|
async function getCompositionSequence() {
|
|
3483
3742
|
if (!_CompositionSequence) {
|
|
3484
|
-
_CompositionSequence = (await import('./Composition-
|
|
3743
|
+
_CompositionSequence = (await import('./Composition-LL2XXU5N.cjs')).CompositionSequence;
|
|
3485
3744
|
}
|
|
3486
3745
|
return _CompositionSequence;
|
|
3487
3746
|
}
|
|
@@ -3525,11 +3784,14 @@ exports.DEG = DEG;
|
|
|
3525
3784
|
exports.NEAR = NEAR;
|
|
3526
3785
|
exports.NullSequence = NullSequence;
|
|
3527
3786
|
exports.Sequence = Sequence;
|
|
3787
|
+
exports.bindClock = bindClock;
|
|
3528
3788
|
exports.buildScope = buildScope;
|
|
3529
3789
|
exports.buildSequenceTree = buildSequenceTree;
|
|
3530
3790
|
exports.cameraBasis = cameraBasis;
|
|
3531
3791
|
exports.checkEase = checkEase;
|
|
3792
|
+
exports.clockTable = clockTable;
|
|
3532
3793
|
exports.collectPropKeys = collectPropKeys;
|
|
3794
|
+
exports.contentLength = contentLength;
|
|
3533
3795
|
exports.describeLayer = describeLayer;
|
|
3534
3796
|
exports.ensureFilterLibrary = ensureFilterLibrary;
|
|
3535
3797
|
exports.evaluateExpr = evaluateExpr;
|
|
@@ -3544,7 +3806,9 @@ exports.projectLayer = projectLayer;
|
|
|
3544
3806
|
exports.rand = rand;
|
|
3545
3807
|
exports.random = random;
|
|
3546
3808
|
exports.registerSequenceType = registerSequenceType;
|
|
3809
|
+
exports.remapOf = remapOf;
|
|
3547
3810
|
exports.resolveAt = resolveAt;
|
|
3548
3811
|
exports.summarizeWarnings = summarizeWarnings;
|
|
3549
|
-
|
|
3550
|
-
//# sourceMappingURL=chunk-
|
|
3812
|
+
exports.timeRemapOf = timeRemapOf;
|
|
3813
|
+
//# sourceMappingURL=chunk-NO26HWR7.cjs.map
|
|
3814
|
+
//# sourceMappingURL=chunk-NO26HWR7.cjs.map
|