pixi-effects 0.17.0 → 0.18.1
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 +32 -0
- package/README.md +6 -6
- package/ai/CHAT.md +3 -0
- package/ai/SKILL.md +2 -2
- package/ai/chat-template.html +8 -4
- package/ai/reference/cheatsheet.md +3 -1
- package/ai/reference/pitfalls.md +1 -1
- package/ai/template.html +5 -5
- package/ai/tools/check.mjs +25 -109
- package/ai/tools/render.mjs +1 -0
- package/dist/Composition-6JMXWNVV.cjs +14 -0
- package/dist/{Composition-LMVEASHF.cjs.map → Composition-6JMXWNVV.cjs.map} +1 -1
- package/dist/Composition-MLBHYYFF.js +5 -0
- package/dist/{Composition-HYAOYPAX.js.map → Composition-MLBHYYFF.js.map} +1 -1
- package/dist/Controller.d.cts +1 -1
- package/dist/Controller.d.ts +1 -1
- package/dist/{Movie-DHJRrUfI.d.ts → Movie-DlHQ9C02.d.ts} +46 -2
- package/dist/{Movie-CoxF2Z7t.d.cts → Movie-K2YuVAdg.d.cts} +46 -2
- package/dist/Presenter.d.cts +1 -1
- package/dist/Presenter.d.ts +1 -1
- package/dist/{chunk-LBJRXU7N.cjs → chunk-ANO5R2E6.cjs} +14 -4
- package/dist/chunk-ANO5R2E6.cjs.map +1 -0
- package/dist/{chunk-ETAIVOHP.cjs → chunk-JW67MDHQ.cjs} +26 -26
- package/dist/{chunk-ETAIVOHP.cjs.map → chunk-JW67MDHQ.cjs.map} +1 -1
- package/dist/{chunk-ORTYBA42.js → chunk-SG3Y66FN.js} +14 -4
- package/dist/chunk-SG3Y66FN.js.map +1 -0
- package/dist/{chunk-Q3IVBYT7.js → chunk-UXDR3ZDU.js} +3 -3
- package/dist/{chunk-Q3IVBYT7.js.map → chunk-UXDR3ZDU.js.map} +1 -1
- package/dist/index.cjs +152 -31
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +129 -8
- package/dist/index.js.map +1 -1
- package/dist/loader.css +1 -1
- package/dist/three.cjs +5 -5
- package/dist/three.js +1 -1
- package/llms-full.txt +6 -3
- package/package.json +1 -1
- package/dist/Composition-HYAOYPAX.js +0 -5
- package/dist/Composition-LMVEASHF.cjs +0 -14
- package/dist/chunk-LBJRXU7N.cjs.map +0 -1
- package/dist/chunk-ORTYBA42.js.map +0 -1
package/dist/index.cjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
4
|
-
var
|
|
3
|
+
var chunkJW67MDHQ_cjs = require('./chunk-JW67MDHQ.cjs');
|
|
4
|
+
var chunkANO5R2E6_cjs = require('./chunk-ANO5R2E6.cjs');
|
|
5
5
|
var chunkUQBGW5DO_cjs = require('./chunk-UQBGW5DO.cjs');
|
|
6
6
|
var PIXI = require('pixi.js');
|
|
7
7
|
var gsap = require('gsap');
|
|
@@ -466,19 +466,22 @@ function inspectFonts(root) {
|
|
|
466
466
|
if (face.status === "error") failed.add(face.family.replace(/^["']|["']$/g, ""));
|
|
467
467
|
});
|
|
468
468
|
const missing = [];
|
|
469
|
+
const used = /* @__PURE__ */ new Set();
|
|
469
470
|
const walk2 = (seq, index) => {
|
|
470
471
|
const spec = seq.spec;
|
|
471
472
|
if (spec.type === "text") {
|
|
472
473
|
const raw = spec.style?.fontFamily;
|
|
473
474
|
const family2 = Array.isArray(raw) ? raw.join(", ") : typeof raw === "string" ? raw : "";
|
|
474
475
|
const list = family2.split(",").map((f) => f.trim()).filter(Boolean);
|
|
476
|
+
for (const f of list) used.add(f.replace(/^["']|["']$/g, "").toLowerCase());
|
|
475
477
|
if (list.length && !list.some(fontAvailable) && !list.some((f) => failed.has(f.replace(/^["']|["']$/g, "")))) missing.push({ layer: spec.name ?? `text#${index}`, family: family2 });
|
|
476
478
|
}
|
|
477
479
|
if (seq.maskSequence) walk2(seq.maskSequence, index);
|
|
478
480
|
(seq._children ?? []).forEach((child, i) => walk2(child, i));
|
|
479
481
|
};
|
|
480
482
|
walk2(root, 0);
|
|
481
|
-
|
|
483
|
+
const all = [...failed];
|
|
484
|
+
return { missing, failed: all.filter((f) => used.has(f.toLowerCase())), failedUnused: all.filter((f) => !used.has(f.toLowerCase())) };
|
|
482
485
|
}
|
|
483
486
|
|
|
484
487
|
// src/core/scenes.ts
|
|
@@ -486,6 +489,92 @@ function namedScenes(rows) {
|
|
|
486
489
|
return rows.filter((r) => r.depth === 0 && r.type === "composition" && !/[#×]/.test(r.name) && r.end - r.start >= 1).map((r) => ({ name: r.name, start: r.start, end: r.end }));
|
|
487
490
|
}
|
|
488
491
|
|
|
492
|
+
// src/core/review.ts
|
|
493
|
+
function sampleFrames({ totalFrames, frameRate, scenes = [], step = 0.25, cap = 240 }) {
|
|
494
|
+
const last = totalFrames;
|
|
495
|
+
const clamp2 = (f) => Math.max(0, Math.min(last, Math.round(f)));
|
|
496
|
+
const edges = /* @__PURE__ */ new Set([0, last]);
|
|
497
|
+
for (const s of scenes) {
|
|
498
|
+
edges.add(clamp2(s.start * frameRate));
|
|
499
|
+
edges.add(clamp2(s.end * frameRate - 1));
|
|
500
|
+
}
|
|
501
|
+
const room = Math.max(0, cap - edges.size);
|
|
502
|
+
const seconds = totalFrames / frameRate;
|
|
503
|
+
const wanted = Math.floor(seconds / step) + 1;
|
|
504
|
+
const stride = wanted <= room ? step : seconds / Math.max(1, room);
|
|
505
|
+
const frames = new Set(edges);
|
|
506
|
+
for (let t = stride; frames.size < cap && t < seconds; t += stride) frames.add(clamp2(t * frameRate));
|
|
507
|
+
return [...frames].sort((a, b) => a - b);
|
|
508
|
+
}
|
|
509
|
+
var AT_HELP = "use seconds (3.5), a percentage (50%), a frame (f120) or a layer's start / mid / end (name@end)";
|
|
510
|
+
function resolveAtList(list, ctx) {
|
|
511
|
+
const { frameRate: fps, totalFrames, duration, rows } = ctx;
|
|
512
|
+
const out = [], used = /* @__PURE__ */ new Set();
|
|
513
|
+
const named = rows.flatMap((r) => r.parts && r.partNames ? r.partNames.map((name, i) => ({ name, start: r.parts[i].start, end: r.parts[i].end })) : [r]);
|
|
514
|
+
for (const raw of String(list).split(",").map((s) => s.trim()).filter(Boolean)) {
|
|
515
|
+
let frame, label, m;
|
|
516
|
+
if (m = raw.match(/^(.+)@(start|mid|end)$/)) {
|
|
517
|
+
const row = named.find((r) => r.name === m[1]);
|
|
518
|
+
if (!row) throw new Error(`--at "${raw}": no layer named "${m[1]}" (names: ${named.slice(0, 40).map((r) => r.name).join(", ")}${named.length > 40 ? ", \u2026" : ""})`);
|
|
519
|
+
const t = m[2] === "start" ? row.start : m[2] === "mid" ? (row.start + row.end) / 2 : row.end - 1 / fps;
|
|
520
|
+
frame = Math.round(t * fps);
|
|
521
|
+
label = `${m[1]}-${m[2]}`;
|
|
522
|
+
} else if (m = raw.match(/^(\d+(?:\.\d+)?)%$/)) {
|
|
523
|
+
frame = Math.round(Number(m[1]) / 100 * totalFrames);
|
|
524
|
+
label = `${m[1]}pct`;
|
|
525
|
+
} else if (m = raw.match(/^f(\d+)$/i)) {
|
|
526
|
+
frame = Number(m[1]);
|
|
527
|
+
label = `f${m[1]}`;
|
|
528
|
+
} else if (/^\d+(\.\d+)?$/.test(raw)) {
|
|
529
|
+
frame = Math.round(Number(raw) * fps);
|
|
530
|
+
label = `${Number(raw).toFixed(2)}s`;
|
|
531
|
+
} else throw new Error(`--at: cannot read "${raw}": ${AT_HELP}`);
|
|
532
|
+
if (frame > totalFrames || frame < 0) throw new Error(`--at "${raw}" is past the end: the movie is ${duration} s (${totalFrames} frames)`);
|
|
533
|
+
label = label.replace(/[\\/:*?"<>|]+/g, "-");
|
|
534
|
+
let unique = label, n = 2;
|
|
535
|
+
while (used.has(unique)) unique = `${label}-${n++}`;
|
|
536
|
+
used.add(unique);
|
|
537
|
+
out.push({ label: unique, frame });
|
|
538
|
+
}
|
|
539
|
+
return out;
|
|
540
|
+
}
|
|
541
|
+
function groupIssues(perFrame) {
|
|
542
|
+
const groups = /* @__PURE__ */ new Map();
|
|
543
|
+
for (const { frame, issues } of perFrame) {
|
|
544
|
+
for (const message of issues) {
|
|
545
|
+
const key = message.replace(/-?\d+(\.\d+)?/g, "#");
|
|
546
|
+
const g = groups.get(key);
|
|
547
|
+
if (g) {
|
|
548
|
+
g.count++;
|
|
549
|
+
g.lastFrame = frame;
|
|
550
|
+
} else groups.set(key, { message, count: 1, firstFrame: frame, lastFrame: frame });
|
|
551
|
+
}
|
|
552
|
+
}
|
|
553
|
+
return [...groups.values()];
|
|
554
|
+
}
|
|
555
|
+
function splitIssues(groups, strict = false) {
|
|
556
|
+
if (strict) return { problems: groups, review: [] };
|
|
557
|
+
const overlap = (g) => /\boverlap\b/.test(g.message);
|
|
558
|
+
return { problems: groups.filter((g) => !overlap(g)), review: groups.filter(overlap) };
|
|
559
|
+
}
|
|
560
|
+
async function reviewMovie(movie, opts = {}) {
|
|
561
|
+
const rows = movie.timelineData().rows;
|
|
562
|
+
const at = opts.at ? resolveAtList(opts.at, { frameRate: movie.frameRate, totalFrames: movie.totalFrames, duration: movie.duration, rows }) : [];
|
|
563
|
+
const frames = sampleFrames({ totalFrames: movie.totalFrames, frameRate: movie.frameRate, scenes: namedScenes(rows) });
|
|
564
|
+
const perFrame = [];
|
|
565
|
+
for (const frame of frames) {
|
|
566
|
+
const r = await movie.inspect(frame, { layers: "none" });
|
|
567
|
+
if (r.issues.length) perFrame.push({ frame, issues: r.issues });
|
|
568
|
+
}
|
|
569
|
+
const grouped = splitIssues(groupIssues(perFrame), !!opts.strict);
|
|
570
|
+
const fonts = movie.inspectFonts();
|
|
571
|
+
for (const f of fonts.failedUnused) grouped.review.push({ message: `web font "${f}" failed to load, but no text layer uses it (a broken or unused @font-face)`, count: 1, firstFrame: 0, lastFrame: 0 });
|
|
572
|
+
for (const m of fonts.missing) {
|
|
573
|
+
(opts.strict ? grouped.problems : grouped.review).push({ message: `layer "${m.layer}": none of the fonts "${m.family}" is available here (it is drawn in a fallback font)`, count: 1, firstFrame: 0, lastFrame: 0 });
|
|
574
|
+
}
|
|
575
|
+
return { frames: frames.length, problems: grouped.problems, review: grouped.review, fonts, audio: movie.audioBuffer ? movie.inspectAudio() : null, at };
|
|
576
|
+
}
|
|
577
|
+
|
|
489
578
|
// src/core/onion.ts
|
|
490
579
|
function onionTimes(from, to, count) {
|
|
491
580
|
if (count <= 1) return [from];
|
|
@@ -522,9 +611,9 @@ function resolveRange(range2, ctx) {
|
|
|
522
611
|
if (range2 === void 0) return { fromFrame: 0, toFrame: totalFrames, fromSec: 0, toSec: duration, partial: false };
|
|
523
612
|
let from, to;
|
|
524
613
|
if (typeof range2 === "string") {
|
|
525
|
-
const rows = (ctx.rows ?? []).filter((r) => r.depth === 0);
|
|
614
|
+
const rows = (ctx.rows ?? []).filter((r) => r.depth === 0).flatMap((r) => r.parts && r.partNames ? r.partNames.map((name, i) => ({ name, start: r.parts[i].start, end: r.parts[i].end })) : [r]);
|
|
526
615
|
const row = rows.find((r) => r.name === range2);
|
|
527
|
-
if (!row) throw new Error(`pixi-effects: render({ range: "${range2}" }): no layer named "${range2}" at the top level (names: ${rows.map((r) => r.name).join(", ") || "none"})`);
|
|
616
|
+
if (!row) throw new Error(`pixi-effects: render({ range: "${range2}" }): no layer named "${range2}" at the top level (names: ${rows.slice(0, 40).map((r) => r.name).join(", ") || "none"}${rows.length > 40 ? ", \u2026" : ""})`);
|
|
528
617
|
from = row.start;
|
|
529
618
|
to = row.end;
|
|
530
619
|
} else {
|
|
@@ -689,7 +778,7 @@ async function exportFrames(movie, options = {}) {
|
|
|
689
778
|
}
|
|
690
779
|
await canvasSource.close();
|
|
691
780
|
await output.finalize();
|
|
692
|
-
if (mb) await movie.gotoFrame(
|
|
781
|
+
if (mb) await movie.gotoFrame(range2.toFrame, true);
|
|
693
782
|
return new Blob([output.target.buffer], { type: output.format.mimeType });
|
|
694
783
|
} finally {
|
|
695
784
|
movie.app.ticker.start();
|
|
@@ -1136,16 +1225,16 @@ function expandTransitions(spec) {
|
|
|
1136
1225
|
if (toUses > 1) {
|
|
1137
1226
|
throw new Error(`pixi-effects: ${tag} sequence "${t.to}" is used as \`to\` in more than one transition`);
|
|
1138
1227
|
}
|
|
1139
|
-
const tStart =
|
|
1228
|
+
const tStart = chunkANO5R2E6_cjs.resolveAt(t.at, parentDuration);
|
|
1140
1229
|
const tEnd = tStart + t.duration;
|
|
1141
1230
|
const fromSeq = fromEntry.seq;
|
|
1142
|
-
const fromStart =
|
|
1231
|
+
const fromStart = chunkANO5R2E6_cjs.resolveAt(fromSeq.at, parentDuration);
|
|
1143
1232
|
const fromEnd = fromStart + (fromSeq.duration ?? parentDuration);
|
|
1144
1233
|
if (tStart < fromStart - EPS || tEnd > fromEnd + EPS) {
|
|
1145
1234
|
throw new Error(`pixi-effects: ${tag} window [${tStart}, ${tEnd}] is not covered by \`from\` "${t.from}" (lives [${fromStart}, ${fromEnd}], so it ends at ${fromEnd})`);
|
|
1146
1235
|
}
|
|
1147
1236
|
const toSeq = toEntry.seq;
|
|
1148
|
-
const toStart =
|
|
1237
|
+
const toStart = chunkANO5R2E6_cjs.resolveAt(toSeq.at, parentDuration);
|
|
1149
1238
|
const toEnd = toStart + (toSeq.duration ?? parentDuration);
|
|
1150
1239
|
if (tStart < toStart - EPS || tEnd > toEnd + EPS) {
|
|
1151
1240
|
throw new Error(`pixi-effects: ${tag} window [${tStart}, ${tEnd}] is not covered by \`to\` "${t.to}" (lives [${toStart}, ${toEnd}], so it starts at ${toStart})`);
|
|
@@ -1485,9 +1574,9 @@ function inspectScene(root, frame, time, canvas, opts = {}) {
|
|
|
1485
1574
|
onCanvas = inter === 0 && area > 0 ? "none" : inter >= area - 1e-6 ? "full" : "partial";
|
|
1486
1575
|
if (area === 0) onCanvas = "none";
|
|
1487
1576
|
}
|
|
1488
|
-
const keys =
|
|
1577
|
+
const keys = chunkANO5R2E6_cjs.collectPropKeys(seq.spec);
|
|
1489
1578
|
const carried = carriers.some((c) => {
|
|
1490
|
-
const k =
|
|
1579
|
+
const k = chunkANO5R2E6_cjs.collectPropKeys(c.spec);
|
|
1491
1580
|
return (c.spec.keyframes ?? []).length > 0 && (k.has("x") || k.has("y") || k.has("rotation") || k.has("scale"));
|
|
1492
1581
|
});
|
|
1493
1582
|
const moving = parentMoving || carried || (seq.spec.keyframes ?? []).length > 0 && (keys.has("x") || keys.has("y"));
|
|
@@ -1508,7 +1597,7 @@ function inspectScene(root, frame, time, canvas, opts = {}) {
|
|
|
1508
1597
|
const group = parentScene ?? (name !== void 0 && blending.has(name) ? name : void 0);
|
|
1509
1598
|
if (group) scene.set(info, group);
|
|
1510
1599
|
if (zero || seq.showsNothingYet) scaledToNothing.add(info);
|
|
1511
|
-
if (seq instanceof
|
|
1600
|
+
if (seq instanceof chunkJW67MDHQ_cjs.CompositionSequence) walk2(seq, prefix + label + "/", insideThreeD || threeD, visible, group, moving, zero);
|
|
1512
1601
|
});
|
|
1513
1602
|
};
|
|
1514
1603
|
walk2(root, "", false, true);
|
|
@@ -1569,10 +1658,10 @@ function walk(comp, parentStart, parentEnd, depth, prefix, rows, transitions) {
|
|
|
1569
1658
|
const start = parentStart + (seq.at ?? 0);
|
|
1570
1659
|
const end = Math.min(parentEnd, seq.duration !== void 0 ? start + seq.duration : parentEnd);
|
|
1571
1660
|
const span = end - start;
|
|
1572
|
-
const keys = (seq.spec.keyframes ?? []).map((kf) => round(start +
|
|
1661
|
+
const keys = (seq.spec.keyframes ?? []).map((kf) => round(start + chunkANO5R2E6_cjs.resolveAt(kf.at, span))).sort((a, b) => a - b).slice(0, MAX_KEYS);
|
|
1573
1662
|
const row = { path: prefix + name, name, type: seq.spec.type, depth, start: round(start), end: round(end), keys, detail: detailOf(seq) };
|
|
1574
1663
|
const inner = [];
|
|
1575
|
-
const isComp = seq instanceof
|
|
1664
|
+
const isComp = seq instanceof chunkJW67MDHQ_cjs.CompositionSequence;
|
|
1576
1665
|
if (isComp) walk(seq, start, end, depth + 1, prefix + name + "/", inner, transitions);
|
|
1577
1666
|
entries.push({ row, inner, groupable: !isComp });
|
|
1578
1667
|
});
|
|
@@ -1605,7 +1694,8 @@ function groupFamilies(entries) {
|
|
|
1605
1694
|
start: Math.min(...members.map((x) => x.start)),
|
|
1606
1695
|
end: Math.max(...members.map((x) => x.end)),
|
|
1607
1696
|
keys: members.flatMap((x) => x.keys).sort((a, b) => a - b).slice(0, MAX_KEYS),
|
|
1608
|
-
parts: members.map((x) => ({ start: x.start, end: x.end }))
|
|
1697
|
+
parts: members.map((x) => ({ start: x.start, end: x.end })),
|
|
1698
|
+
partNames: members.map((x) => x.name)
|
|
1609
1699
|
});
|
|
1610
1700
|
} else {
|
|
1611
1701
|
out.push(e.row, ...e.inner);
|
|
@@ -2120,7 +2210,7 @@ var Movie = class {
|
|
|
2120
2210
|
height: options.composition.height ?? this.height,
|
|
2121
2211
|
duration: options.composition.duration ?? this.duration
|
|
2122
2212
|
} : void 0;
|
|
2123
|
-
await
|
|
2213
|
+
await chunkANO5R2E6_cjs.ensureFilterLibrary(seededComposition);
|
|
2124
2214
|
const userComposition = seededComposition ? expandTransitions(seededComposition) : void 0;
|
|
2125
2215
|
const rootSeqSpec = {
|
|
2126
2216
|
type: "composition",
|
|
@@ -2130,7 +2220,7 @@ var Movie = class {
|
|
|
2130
2220
|
...userComposition
|
|
2131
2221
|
};
|
|
2132
2222
|
if (userComposition) carryTransitionWindows(userComposition, rootSeqSpec);
|
|
2133
|
-
const composition = new
|
|
2223
|
+
const composition = new chunkJW67MDHQ_cjs.CompositionSequence(rootSeqSpec, null, rootShape);
|
|
2134
2224
|
await composition.build();
|
|
2135
2225
|
this._rootSequence = composition;
|
|
2136
2226
|
if (composition.target) root.addChild(composition.target);
|
|
@@ -2425,6 +2515,27 @@ var Movie = class {
|
|
|
2425
2515
|
* The soundtrack, measured: when every audio layer plays, how loud the mix is over time, and `issues`
|
|
2426
2516
|
* (limiting, inaudible layers, sounds cut off by the end). Use it to CHECK sound you cannot hear.
|
|
2427
2517
|
*/
|
|
2518
|
+
/** The pictures to look at for moments such as `3.5`, `50%`, `f120`, `title@end` (comma-separated). A mistake says what could not be read. */
|
|
2519
|
+
resolveAt(list) {
|
|
2520
|
+
this._requireReady("resolveAt");
|
|
2521
|
+
return resolveAtList(list, { frameRate: this.frameRate, totalFrames: this.totalFrames, duration: this.duration, rows: this.timelineData().rows });
|
|
2522
|
+
}
|
|
2523
|
+
/**
|
|
2524
|
+
* One call that looks at everything `pixi-effects-check` looks at inside the page: layout issues over the whole timeline (every
|
|
2525
|
+
* scene's first and last frame and a frame every 0.25 s), fonts and the sound. See `ReviewReport`. Page warnings are in `window.__logs`. The movie is left as it was.
|
|
2526
|
+
*/
|
|
2527
|
+
async review(opts = {}) {
|
|
2528
|
+
chunkUQBGW5DO_cjs.warnUnknownOptions("movie.review()", opts, ["at", "strict"]);
|
|
2529
|
+
this._requireReady("review");
|
|
2530
|
+
const back = this.currentFrame, wasAtPoster = this._atPoster;
|
|
2531
|
+
try {
|
|
2532
|
+
return await reviewMovie(this, opts);
|
|
2533
|
+
} finally {
|
|
2534
|
+
this.currentFrame = back;
|
|
2535
|
+
if (wasAtPoster) await this._showPoster();
|
|
2536
|
+
else await this._quietly(() => this.gotoFrame(back, true));
|
|
2537
|
+
}
|
|
2538
|
+
}
|
|
2428
2539
|
/**
|
|
2429
2540
|
* The fonts of the text layers: `missing` lists layers none of whose `fontFamily` entries is available in this browser (they are
|
|
2430
2541
|
* drawn in a fallback font), `failed` lists web fonts (`@font-face`) whose file could not be loaded.
|
|
@@ -2916,7 +3027,7 @@ function clamp(v, lo, hi) {
|
|
|
2916
3027
|
return Math.max(lo, Math.min(hi, v));
|
|
2917
3028
|
}
|
|
2918
3029
|
function parseEase(name) {
|
|
2919
|
-
|
|
3030
|
+
chunkANO5R2E6_cjs.checkEase(name, "a preset");
|
|
2920
3031
|
return gsap.gsap.parseEase(name);
|
|
2921
3032
|
}
|
|
2922
3033
|
|
|
@@ -2939,17 +3050,17 @@ function orbit(opts) {
|
|
|
2939
3050
|
throw new Error("pixi-effects: orbit() cannot combine `radius` with `dollyZoom` \u2014 the radius follows the animated fov");
|
|
2940
3051
|
}
|
|
2941
3052
|
const [cx, cy] = opts.center ?? [width / 2, height / 2];
|
|
2942
|
-
const fixedR = opts.radius ??
|
|
3053
|
+
const fixedR = opts.radius ?? chunkANO5R2E6_cjs.homeDistance(height, fov ?? chunkANO5R2E6_cjs.DEFAULT_FOV);
|
|
2943
3054
|
const start = opts.start ?? -degrees / 2;
|
|
2944
3055
|
const steps = Math.max(1, Math.round(duration * stepsPerSecond));
|
|
2945
3056
|
const easeFn = parseEase(ease);
|
|
2946
3057
|
const dollyEase = dolly ? parseEase(dolly.ease ?? ease) : null;
|
|
2947
3058
|
const pos = (i) => {
|
|
2948
3059
|
const p = i / steps;
|
|
2949
|
-
const a = (start + degrees * easeFn(p)) *
|
|
3060
|
+
const a = (start + degrees * easeFn(p)) * chunkANO5R2E6_cjs.DEG;
|
|
2950
3061
|
if (!dolly) return { x: cx + fixedR * Math.sin(a), z: fixedR * Math.cos(a) };
|
|
2951
3062
|
const f = dolly.from + (dolly.to - dolly.from) * dollyEase(p);
|
|
2952
|
-
const R =
|
|
3063
|
+
const R = chunkANO5R2E6_cjs.homeDistance(height, f);
|
|
2953
3064
|
return { x: cx + R * Math.sin(a), z: R * Math.cos(a), fov: f };
|
|
2954
3065
|
};
|
|
2955
3066
|
const keyframes = [];
|
|
@@ -3004,7 +3115,7 @@ function particles(opts) {
|
|
|
3004
3115
|
const round3 = (v) => Math.round(v * 1e6) / 1e6;
|
|
3005
3116
|
const out = [];
|
|
3006
3117
|
for (let i = 0; i < count; i++) {
|
|
3007
|
-
const r =
|
|
3118
|
+
const r = chunkANO5R2E6_cjs.random(seed * 1000003 + i * 7919 + 17);
|
|
3008
3119
|
const pick = ([a2, b]) => a2 + r() * (b - a2);
|
|
3009
3120
|
const born = at + r() * emit;
|
|
3010
3121
|
const lifetime = pick(life);
|
|
@@ -3017,7 +3128,7 @@ function particles(opts) {
|
|
|
3017
3128
|
const turn = spin ? pick(spin) : 0;
|
|
3018
3129
|
const startAngle = spin ? r() * 360 : 0;
|
|
3019
3130
|
const swayAmp = sway?.amp ?? 0, swayFreq = sway?.freq ?? 1;
|
|
3020
|
-
const n0 = sway ?
|
|
3131
|
+
const n0 = sway ? chunkANO5R2E6_cjs.noise(0, seed * 1000003 + i) : 0;
|
|
3021
3132
|
const at_ = (t) => {
|
|
3022
3133
|
const axis = (p0, v0, acc) => {
|
|
3023
3134
|
if (drag > 0) {
|
|
@@ -3026,7 +3137,7 @@ function particles(opts) {
|
|
|
3026
3137
|
}
|
|
3027
3138
|
return p0 + v0 * t + 0.5 * acc * t * t;
|
|
3028
3139
|
};
|
|
3029
|
-
const sw = sway ? swayAmp * (
|
|
3140
|
+
const sw = sway ? swayAmp * (chunkANO5R2E6_cjs.noise(t * swayFreq, seed * 1000003 + i) - n0) : 0;
|
|
3030
3141
|
return { x: axis(x0, vx, wind) + sw, y: axis(y0, vy, gravity) };
|
|
3031
3142
|
};
|
|
3032
3143
|
const kfs = [];
|
|
@@ -3088,7 +3199,7 @@ function followPath(opts) {
|
|
|
3088
3199
|
if (steps > MAX_STEPS) throw new Error(`followPath(): ${steps} samples is too many (max ${MAX_STEPS}); lower frameRate or duration`);
|
|
3089
3200
|
const segments = [];
|
|
3090
3201
|
let total = 0;
|
|
3091
|
-
for (const line of
|
|
3202
|
+
for (const line of chunkANO5R2E6_cjs.flattenSvgPath(d)) {
|
|
3092
3203
|
const p = line.closed ? [...line.pts, line.pts[0], line.pts[1]] : line.pts;
|
|
3093
3204
|
for (let i = 2; i < p.length; i += 2) {
|
|
3094
3205
|
const len = Math.hypot(p[i] - p[i - 2], p[i + 1] - p[i - 1]);
|
|
@@ -3241,7 +3352,7 @@ function distances(n, from, grid, seed) {
|
|
|
3241
3352
|
if (n === 0) return [];
|
|
3242
3353
|
if (from === "random") {
|
|
3243
3354
|
const order = Array.from({ length: n }, (_, i) => i);
|
|
3244
|
-
const r =
|
|
3355
|
+
const r = chunkANO5R2E6_cjs.random(seed);
|
|
3245
3356
|
for (let i = n - 1; i > 0; i--) {
|
|
3246
3357
|
const j = Math.floor(r() * (i + 1));
|
|
3247
3358
|
[order[i], order[j]] = [order[j], order[i]];
|
|
@@ -3303,7 +3414,7 @@ function wiggle(opts) {
|
|
|
3303
3414
|
to[n] = p.around;
|
|
3304
3415
|
return;
|
|
3305
3416
|
}
|
|
3306
|
-
const off = (
|
|
3417
|
+
const off = (chunkANO5R2E6_cjs.rand(seed * 7919 + pi * 104729 + s * 31 + 1) * 2 - 1) * p.amp;
|
|
3307
3418
|
to[n] = typeof p.around === "number" ? p.around + off : `(${p.around}) ${off < 0 ? "-" : "+"} ${Math.abs(off)}`;
|
|
3308
3419
|
});
|
|
3309
3420
|
out.push({ at: at + s * stepLen, to, duration: stepLen, ease });
|
|
@@ -3312,6 +3423,8 @@ function wiggle(opts) {
|
|
|
3312
3423
|
}
|
|
3313
3424
|
|
|
3314
3425
|
// src/presets/animateText.ts
|
|
3426
|
+
var TWEEN_KEYS = ["preset", "from", "to", "duration", "ease"];
|
|
3427
|
+
var TIME_KEYS = ["at", "delay", "start", "begin", "time"];
|
|
3315
3428
|
var KEYS5 = ["by", "x", "y", "align", "name", "at", "duration", "in", "out", "stagger", "idle", "styleFor"];
|
|
3316
3429
|
var PRESETS = {
|
|
3317
3430
|
rise: { from: { y: 40, alpha: 0 }, duration: 0.5, ease: "back.out(2)" },
|
|
@@ -3395,6 +3508,14 @@ function animateText(text, style, options) {
|
|
|
3395
3508
|
}
|
|
3396
3509
|
function resolveTween(spec, which) {
|
|
3397
3510
|
const t = typeof spec === "string" ? { preset: spec } : spec;
|
|
3511
|
+
if (typeof spec === "object" && spec) {
|
|
3512
|
+
for (const key of Object.keys(spec)) {
|
|
3513
|
+
if (TWEEN_KEYS.includes(key)) continue;
|
|
3514
|
+
if (TIME_KEYS.includes(key)) {
|
|
3515
|
+
console.warn(`pixi-effects: animateText(): ${which}.${key} ("${key}") is ignored: ${which === "out" ? "an out leaves from the END of the layer (at + duration), so to make the text gone at a time T set duration to T \u2212 at" : "the entrance starts when the piece starts (the options' at, plus the stagger)"}`);
|
|
3516
|
+
} else chunkUQBGW5DO_cjs.warnUnknownOptions(`animateText() ${which}`, { [key]: 1 }, TWEEN_KEYS);
|
|
3517
|
+
}
|
|
3518
|
+
}
|
|
3398
3519
|
if (t.preset !== void 0 && !(t.preset in PRESETS)) {
|
|
3399
3520
|
const guess = chunkUQBGW5DO_cjs.suggestName(String(t.preset), PRESET_NAMES);
|
|
3400
3521
|
throw new Error(`animateText(): ${which} "${t.preset}" is not a preset${guess ? `; did you mean "${guess}"?` : ""} (presets: ${PRESET_NAMES.map((n) => `"${n}"`).join(", ")})`);
|
|
@@ -3768,19 +3889,19 @@ function withFade(spec, opts) {
|
|
|
3768
3889
|
|
|
3769
3890
|
Object.defineProperty(exports, "noise", {
|
|
3770
3891
|
enumerable: true,
|
|
3771
|
-
get: function () { return
|
|
3892
|
+
get: function () { return chunkANO5R2E6_cjs.noise; }
|
|
3772
3893
|
});
|
|
3773
3894
|
Object.defineProperty(exports, "rand", {
|
|
3774
3895
|
enumerable: true,
|
|
3775
|
-
get: function () { return
|
|
3896
|
+
get: function () { return chunkANO5R2E6_cjs.rand; }
|
|
3776
3897
|
});
|
|
3777
3898
|
Object.defineProperty(exports, "random", {
|
|
3778
3899
|
enumerable: true,
|
|
3779
|
-
get: function () { return
|
|
3900
|
+
get: function () { return chunkANO5R2E6_cjs.random; }
|
|
3780
3901
|
});
|
|
3781
3902
|
Object.defineProperty(exports, "registerSequenceType", {
|
|
3782
3903
|
enumerable: true,
|
|
3783
|
-
get: function () { return
|
|
3904
|
+
get: function () { return chunkANO5R2E6_cjs.registerSequenceType; }
|
|
3784
3905
|
});
|
|
3785
3906
|
exports.Movie = Movie;
|
|
3786
3907
|
exports.animateText = animateText;
|