pixi-effects 0.34.0 → 0.36.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 +27 -0
- package/README.md +5 -5
- package/ai/chat-template.html +3 -3
- package/ai/tools/check.mjs +26 -7
- package/ai/tools/lookup.mjs +14 -2
- package/dist/{Base-CXsMdmJB.d.ts → Base-CdF7AJop.d.ts} +1 -1
- package/dist/{Base-pNq6sVGl.d.cts → Base-CmiFiwQM.d.cts} +1 -1
- package/dist/Composition-BMRCE5FH.js +7 -0
- package/dist/{Composition-NDXKQHB4.js.map → Composition-BMRCE5FH.js.map} +1 -1
- package/dist/Composition-XRLYR6GL.cjs +16 -0
- package/dist/{Composition-OLH7RC5Z.cjs.map → Composition-XRLYR6GL.cjs.map} +1 -1
- package/dist/Controller.cjs +130 -1
- package/dist/Controller.cjs.map +1 -1
- package/dist/Controller.d.cts +24 -2
- package/dist/Controller.d.ts +24 -2
- package/dist/Controller.js +130 -1
- package/dist/Controller.js.map +1 -1
- package/dist/{Movie-f0tQG9y5.d.ts → Movie-Bh1HPdKw.d.cts} +30 -2
- package/dist/{Movie-CL6SsAWe.d.cts → Movie-D5WFfZdZ.d.ts} +30 -2
- package/dist/{Spans-QRMN2EZO.cjs → Spans-4IRBSOLI.cjs} +11 -11
- package/dist/{Spans-QRMN2EZO.cjs.map → Spans-4IRBSOLI.cjs.map} +1 -1
- package/dist/{Spans-QHHWC2PB.js → Spans-MWP2FX3T.js} +6 -6
- package/dist/{Spans-QHHWC2PB.js.map → Spans-MWP2FX3T.js.map} +1 -1
- package/dist/{blendModes-WIUCYIMC.cjs → blendModes-KU7XLV7U.cjs} +5 -5
- package/dist/{blendModes-WIUCYIMC.cjs.map → blendModes-KU7XLV7U.cjs.map} +1 -1
- package/dist/{blendModes-PP5NPBXY.js → blendModes-OOI3T6BE.js} +4 -4
- package/dist/{blendModes-PP5NPBXY.js.map → blendModes-OOI3T6BE.js.map} +1 -1
- package/dist/{chunk-ITDYFBB6.js → chunk-2JFFKHXO.js} +5 -5
- package/dist/chunk-2JFFKHXO.js.map +1 -0
- package/dist/{chunk-GL2AQFLQ.cjs → chunk-42ML5AKN.cjs} +5 -5
- package/dist/chunk-42ML5AKN.cjs.map +1 -0
- package/dist/{chunk-XV4L72FW.js → chunk-AZ6AINSW.js} +5 -5
- package/dist/{chunk-XV4L72FW.js.map → chunk-AZ6AINSW.js.map} +1 -1
- package/dist/{chunk-FVZEBYLW.cjs → chunk-CC7SUR7Q.cjs} +237 -54
- package/dist/chunk-CC7SUR7Q.cjs.map +1 -0
- package/dist/{chunk-Y253JQOH.js → chunk-G3DX65HO.js} +110 -10
- package/dist/chunk-G3DX65HO.js.map +1 -0
- package/dist/{chunk-LEECUCTG.cjs → chunk-KJSEQVBV.cjs} +129 -29
- package/dist/chunk-KJSEQVBV.cjs.map +1 -0
- package/dist/{chunk-IMQJVRMT.cjs → chunk-NEUPEENI.cjs} +5 -5
- package/dist/{chunk-IMQJVRMT.cjs.map → chunk-NEUPEENI.cjs.map} +1 -1
- package/dist/{chunk-67LG7MN5.js → chunk-VF56PRAA.js} +205 -22
- package/dist/chunk-VF56PRAA.js.map +1 -0
- package/dist/{chunk-RTJD3ZSW.js → chunk-WIIU42FH.js} +4 -4
- package/dist/{chunk-RTJD3ZSW.js.map → chunk-WIIU42FH.js.map} +1 -1
- package/dist/{chunk-5IJENZOG.cjs → chunk-Y5UWFH6Y.cjs} +91 -91
- package/dist/{chunk-5IJENZOG.cjs.map → chunk-Y5UWFH6Y.cjs.map} +1 -1
- package/dist/index.cjs +33 -33
- package/dist/index.d.cts +20 -6
- package/dist/index.d.ts +20 -6
- package/dist/index.js +5 -5
- package/dist/loader.css +1 -1
- package/dist/present.cjs +5 -5
- package/dist/present.d.cts +2 -2
- package/dist/present.d.ts +2 -2
- package/dist/present.js +5 -5
- 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-CavnUvd5.d.ts → types-B6zDTU2V.d.cts} +14 -1
- package/dist/{types-CavnUvd5.d.cts → types-B6zDTU2V.d.ts} +14 -1
- package/docs/api.md +15 -4
- package/docs/dsl.md +7 -5
- package/llms-full.txt +95 -18
- package/package.json +1 -1
- package/skills/pixi-effects/SKILL.md +3 -3
- package/skills/pixi-effects/reference/cheatsheet.md +7 -6
- package/skills/pixi-effects/reference/pitfalls.md +3 -0
- package/skills/pixi-effects/reference/recipes.md +60 -0
- package/skills/pixi-effects/template.html +6 -6
- package/dist/Composition-NDXKQHB4.js +0 -7
- package/dist/Composition-OLH7RC5Z.cjs +0 -16
- package/dist/chunk-67LG7MN5.js.map +0 -1
- package/dist/chunk-FVZEBYLW.cjs.map +0 -1
- package/dist/chunk-GL2AQFLQ.cjs.map +0 -1
- package/dist/chunk-ITDYFBB6.js.map +0 -1
- package/dist/chunk-LEECUCTG.cjs.map +0 -1
- package/dist/chunk-Y253JQOH.js.map +0 -1
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
4
|
-
var
|
|
5
|
-
var
|
|
3
|
+
var chunkY5UWFH6Y_cjs = require('./chunk-Y5UWFH6Y.cjs');
|
|
4
|
+
var chunkKJSEQVBV_cjs = require('./chunk-KJSEQVBV.cjs');
|
|
5
|
+
var chunkNEUPEENI_cjs = require('./chunk-NEUPEENI.cjs');
|
|
6
6
|
var chunkTWZNOUM7_cjs = require('./chunk-TWZNOUM7.cjs');
|
|
7
7
|
var pixi_js = require('pixi.js');
|
|
8
8
|
var mediabunny = require('mediabunny');
|
|
@@ -392,6 +392,7 @@ function findSilences(channels, sampleRate, opts = {}) {
|
|
|
392
392
|
}
|
|
393
393
|
|
|
394
394
|
// src/core/inspectAudio.ts
|
|
395
|
+
var BURIED_DB = 12;
|
|
395
396
|
var INAUDIBLE_DB = -50;
|
|
396
397
|
var db = (x) => Math.round(10 * Math.max(-120, 20 * Math.log10(x))) / 10;
|
|
397
398
|
var mono = (chans) => {
|
|
@@ -477,6 +478,7 @@ function analyzeAudio(mix, sources, stats, movieDuration, opts = {}) {
|
|
|
477
478
|
return measure(Array.from({ length: b.numberOfChannels }, (_, c) => b.getChannelData(c)), b.sampleRate);
|
|
478
479
|
};
|
|
479
480
|
const scoreNotes = [];
|
|
481
|
+
const buried = [];
|
|
480
482
|
const list = [...sources].sort((a, b) => a.start - b.start).map((s) => {
|
|
481
483
|
const layer = s.layer ?? "an audio layer";
|
|
482
484
|
const source = s.source ?? "audio";
|
|
@@ -504,8 +506,22 @@ function analyzeAudio(mix, sources, stats, movieDuration, opts = {}) {
|
|
|
504
506
|
const over = s.music.seconds - plays;
|
|
505
507
|
if (over > 2 && over / s.music.seconds > 0.15) scoreNotes.push(`${layer} (${source}): the score is ${Math.round(s.music.seconds * 10) / 10}s long but only ${Math.round(plays * 100) / 100}s of it play, so it is cut off mid-phrase. Write fewer bars (or a faster tempo) so it ends with the movie`);
|
|
506
508
|
}
|
|
507
|
-
|
|
509
|
+
let belowMixDb;
|
|
510
|
+
if (!clock && !s.sourceMap && s.start < movieDuration && ownDb > INAUDIBLE_DB) {
|
|
511
|
+
const at = s.start + sound.loudestAt;
|
|
512
|
+
const around = db(peakIn(Math.max(0, at - 0.05), Math.min(movieDuration, at + 0.05)));
|
|
513
|
+
belowMixDb = Math.max(0, Math.round((around - ownDb) * 10) / 10);
|
|
514
|
+
if (!s.music && source.startsWith("sfx") && sound.length <= 4 && belowMixDb >= BURIED_DB) {
|
|
515
|
+
buried.push({ layer, source, ownDb, topVolume, around, belowMixDb, at: Math.round(at * 100) / 100 });
|
|
516
|
+
}
|
|
517
|
+
}
|
|
518
|
+
return { layer, source, start: s.start, end: s.end, peakDb, sound, ...belowMixDb !== void 0 ? { belowMixDb } : {}, ...s.music ? { music: s.music } : {} };
|
|
508
519
|
});
|
|
520
|
+
if (buried.length > 0) {
|
|
521
|
+
const worst = buried.reduce((a, b) => b.belowMixDb > a.belowMixDb ? b : a);
|
|
522
|
+
const names = new Set(buried.map((x) => x.layer + x.source));
|
|
523
|
+
scoreNotes.push(`${names.size === 1 ? "1 sound effect is" : `${names.size} sound effects are`} buried (${BURIED_DB} dB or more under the loudest sample of the mix around its loudest moment${buried.length > names.size ? `, ${buried.length} times in all` : ""}): the worst is ${worst.layer} (${worst.source}), its own peak ${worst.ownDb} dBFS at volume ${worst.topVolume} against ${worst.around} dBFS at ${worst.at} s, ${worst.belowMixDb} dB louder. If it is meant to be heard, raise its volume (an accent over music needs 2 to 3) or lower what plays there; every source's belowMixDb has its own number`);
|
|
524
|
+
}
|
|
509
525
|
const whole = measureLoudness(chans, sr);
|
|
510
526
|
const silences = findSilences(chans, sr, { minLength: 1 });
|
|
511
527
|
if (whole.clippedSamples > 0) issues.push(`${whole.clippedSamples} sample(s) of the mix are at full scale (clipped) \u2014 lower the volume of the layers that play loudest`);
|
|
@@ -1490,8 +1506,8 @@ function expandTransitions(spec) {
|
|
|
1490
1506
|
}
|
|
1491
1507
|
const transitions = out.transitions;
|
|
1492
1508
|
const sequences = out.sequences ?? [];
|
|
1493
|
-
const remap = out.duration !== void 0 ?
|
|
1494
|
-
const parentDuration = remap ?
|
|
1509
|
+
const remap = out.duration !== void 0 ? chunkKJSEQVBV_cjs.timeRemapOf(out) : null;
|
|
1510
|
+
const parentDuration = remap ? chunkKJSEQVBV_cjs.contentLength(remap, out.duration) : out.duration ?? Infinity;
|
|
1495
1511
|
const compW = out.width;
|
|
1496
1512
|
const compH = out.height;
|
|
1497
1513
|
const threeDByName = new Set(sequences.filter((s) => s.name && s.threeD).map((s) => s.name));
|
|
@@ -1559,16 +1575,16 @@ function expandTransitions(spec) {
|
|
|
1559
1575
|
if (toUses > 1) {
|
|
1560
1576
|
throw new Error(`pixi-effects: ${tag} sequence "${t.to}" is used as \`to\` in more than one transition`);
|
|
1561
1577
|
}
|
|
1562
|
-
const tStart =
|
|
1578
|
+
const tStart = chunkKJSEQVBV_cjs.resolveAt(t.at, parentDuration);
|
|
1563
1579
|
const tEnd = tStart + t.duration;
|
|
1564
1580
|
const fromSeq = fromEntry.seq;
|
|
1565
|
-
const fromStart =
|
|
1581
|
+
const fromStart = chunkKJSEQVBV_cjs.resolveAt(fromSeq.at, parentDuration);
|
|
1566
1582
|
const fromEnd = fromStart + (fromSeq.duration ?? parentDuration);
|
|
1567
1583
|
if (tStart < fromStart - EPS || tEnd > fromEnd + EPS) {
|
|
1568
1584
|
throw new Error(`pixi-effects: ${tag} window [${tStart}, ${tEnd}] is not covered by \`from\` "${t.from}" (lives [${fromStart}, ${fromEnd}], so it ends at ${fromEnd})`);
|
|
1569
1585
|
}
|
|
1570
1586
|
const toSeq = toEntry.seq;
|
|
1571
|
-
const toStart =
|
|
1587
|
+
const toStart = chunkKJSEQVBV_cjs.resolveAt(toSeq.at, parentDuration);
|
|
1572
1588
|
const toEnd = toStart + (toSeq.duration ?? parentDuration);
|
|
1573
1589
|
if (tStart < toStart - EPS || tEnd > toEnd + EPS) {
|
|
1574
1590
|
throw new Error(`pixi-effects: ${tag} window [${tStart}, ${tEnd}] is not covered by \`to\` "${t.to}" (lives [${toStart}, ${toEnd}], so it starts at ${toStart})`);
|
|
@@ -1628,7 +1644,7 @@ function wrapAsFullComposition(seq, compW, compH) {
|
|
|
1628
1644
|
delete inner.at;
|
|
1629
1645
|
delete inner.duration;
|
|
1630
1646
|
const m = inner.mask;
|
|
1631
|
-
const carriesMatte = m !== void 0 &&
|
|
1647
|
+
const carriesMatte = m !== void 0 && chunkY5UWFH6Y_cjs.maskSourceOf(m).kind === "refs";
|
|
1632
1648
|
if (carriesMatte) delete inner.mask;
|
|
1633
1649
|
return {
|
|
1634
1650
|
...carriesMatte ? { mask: m } : {},
|
|
@@ -1884,6 +1900,20 @@ function rejectReservedNameCollision(filters, seqName) {
|
|
|
1884
1900
|
}
|
|
1885
1901
|
|
|
1886
1902
|
// src/core/inspect.ts
|
|
1903
|
+
function chainOf(node) {
|
|
1904
|
+
const chain = [];
|
|
1905
|
+
for (let n = node; n && n.parent; n = n.parent) {
|
|
1906
|
+
const i = n.parent.children?.indexOf(n);
|
|
1907
|
+
if (i === void 0 || i < 0) return null;
|
|
1908
|
+
chain.unshift(i);
|
|
1909
|
+
}
|
|
1910
|
+
return chain.length ? chain : null;
|
|
1911
|
+
}
|
|
1912
|
+
function drawnAfter(a, b) {
|
|
1913
|
+
if (!a || !b) return null;
|
|
1914
|
+
for (let i = 0; i < Math.min(a.length, b.length); i++) if (a[i] !== b[i]) return a[i] > b[i];
|
|
1915
|
+
return null;
|
|
1916
|
+
}
|
|
1887
1917
|
var FAINT = 0.3;
|
|
1888
1918
|
var intersection = (a, b) => {
|
|
1889
1919
|
const w = Math.min(a.x + a.width, b.x + b.width) - Math.max(a.x, b.x);
|
|
@@ -1907,8 +1937,8 @@ function motionOf(keyframes, local, lives, keys = (k) => GEOMETRY.has(k)) {
|
|
|
1907
1937
|
let length = 0;
|
|
1908
1938
|
if (typeof kf.duration === "number") length = kf.duration;
|
|
1909
1939
|
else if (kf.duration === "auto") {
|
|
1910
|
-
const sp =
|
|
1911
|
-
length = sp ? Math.round(
|
|
1940
|
+
const sp = chunkKJSEQVBV_cjs.parseSpring(kf.ease);
|
|
1941
|
+
length = sp ? Math.round(chunkKJSEQVBV_cjs.springDuration(sp) * 1e3) / 1e3 : 0.5;
|
|
1912
1942
|
}
|
|
1913
1943
|
if (!(length > 0)) continue;
|
|
1914
1944
|
const kat = kf.at ?? 0;
|
|
@@ -1927,7 +1957,11 @@ function inspectScene(root, frame, time, canvas, opts = {}) {
|
|
|
1927
1957
|
const scene = /* @__PURE__ */ new Map();
|
|
1928
1958
|
const scaledToNothing = /* @__PURE__ */ new Set();
|
|
1929
1959
|
const hasMotion = /* @__PURE__ */ new Set();
|
|
1930
|
-
const
|
|
1960
|
+
const kinds = /* @__PURE__ */ new Map();
|
|
1961
|
+
const specs = /* @__PURE__ */ new Map();
|
|
1962
|
+
const chains = /* @__PURE__ */ new Map();
|
|
1963
|
+
const chainAlpha = /* @__PURE__ */ new Map();
|
|
1964
|
+
const walk2 = (comp, prefix, insideThreeD, parentVisible, parentScene, parentMotion = NO_MOTION, parentZero = false, parentAlpha = 1) => {
|
|
1931
1965
|
const blending = /* @__PURE__ */ new Set();
|
|
1932
1966
|
const now = comp.childTime(time);
|
|
1933
1967
|
const cameraMotion = (comp.spec.sequences ?? []).filter((q) => q.type === "camera").reduce((m, q) => either(m, motionOf(q.keyframes, now - comp.childBase - (q.at ?? 0), q.duration ?? comp.duration ?? Infinity, () => true)), NO_MOTION);
|
|
@@ -1971,10 +2005,14 @@ function inspectScene(root, frame, time, canvas, opts = {}) {
|
|
|
1971
2005
|
if (threeD) info.depthBlur = Number(depthBlur.toFixed(2));
|
|
1972
2006
|
if (threeD && light !== void 0) info.light = Number(light.toFixed(2));
|
|
1973
2007
|
layers.push(info);
|
|
2008
|
+
chainAlpha.set(info, parentAlpha * alpha);
|
|
2009
|
+
chains.set(info, chainOf(display));
|
|
2010
|
+
specs.set(info, seq.spec);
|
|
2011
|
+
kinds.set(info, seq.spec.type === "shape" ? String(seq.spec.shape) : seq.spec.type);
|
|
1974
2012
|
if (motion.ever) hasMotion.add(info);
|
|
1975
2013
|
let shown = bounds ? clip(bounds, view) : null;
|
|
1976
2014
|
const maskTarget = seq.maskSequence?.target;
|
|
1977
|
-
const maskSrc =
|
|
2015
|
+
const maskSrc = chunkY5UWFH6Y_cjs.maskSourceOf(seq.spec.mask);
|
|
1978
2016
|
if (shown && maskTarget && !(maskSrc.kind === "inline" && maskSrc.invert)) {
|
|
1979
2017
|
const m = maskTarget.getBounds();
|
|
1980
2018
|
shown = clip(shown, { x: m.x, y: m.y, width: m.width, height: m.height });
|
|
@@ -1983,7 +2021,7 @@ function inspectScene(root, frame, time, canvas, opts = {}) {
|
|
|
1983
2021
|
const group = parentScene ?? (name !== void 0 && blending.has(name) ? name : void 0);
|
|
1984
2022
|
if (group) scene.set(info, group);
|
|
1985
2023
|
if (zero || seq.showsNothingYet) scaledToNothing.add(info);
|
|
1986
|
-
if (seq instanceof
|
|
2024
|
+
if (seq instanceof chunkY5UWFH6Y_cjs.CompositionSequence) walk2(seq, prefix + label + "/", insideThreeD || threeD, visible, group, motion, zero, parentAlpha * alpha);
|
|
1987
2025
|
});
|
|
1988
2026
|
};
|
|
1989
2027
|
walk2(root, "", false, true);
|
|
@@ -2019,6 +2057,42 @@ function inspectScene(root, frame, time, canvas, opts = {}) {
|
|
|
2019
2057
|
if (share > 0.25) issues.push(`text layers "${texts[i].path}" and "${texts[j].path}" overlap by ${Math.round(share * 100)}% of the smaller one`);
|
|
2020
2058
|
}
|
|
2021
2059
|
}
|
|
2060
|
+
const FILLED = /* @__PURE__ */ new Set(["rect", "circle", "ellipse", "image", "video"]);
|
|
2061
|
+
for (const t of texts) {
|
|
2062
|
+
const tb = seen.get(t);
|
|
2063
|
+
if (!tb) continue;
|
|
2064
|
+
const area = tb.width * tb.height;
|
|
2065
|
+
if (!(area > 0)) continue;
|
|
2066
|
+
for (const o of layers) {
|
|
2067
|
+
if (o === t || o.type === "text" || !o.visible || !o.bounds) continue;
|
|
2068
|
+
if (o.path.startsWith(t.path + "/") || t.path.startsWith(o.path + "/")) continue;
|
|
2069
|
+
const kind = kinds.get(o) ?? o.type, spec = specs.get(o) ?? {};
|
|
2070
|
+
const initial = spec.initial ?? {};
|
|
2071
|
+
const hairline = (kind === "line" || kind === "rect") && Math.min(o.bounds.width, o.bounds.height) < 12 && Math.max(o.bounds.width, o.bounds.height) >= 40;
|
|
2072
|
+
const soft = spec.blendMode !== void 0 && spec.blendMode !== "normal" || Array.isArray(spec.filters) && spec.filters.length > 0;
|
|
2073
|
+
const filled = kind === "image" || kind === "video" || initial.fillColor !== void 0 || spec.fillGradient !== void 0 || initial.fillGradient !== void 0;
|
|
2074
|
+
if (o.threeD || t.threeD) continue;
|
|
2075
|
+
const over = drawnAfter(chains.get(o) ?? null, chains.get(t) ?? null) ?? layers.indexOf(o) > layers.indexOf(t);
|
|
2076
|
+
const opacity = chainAlpha.get(o) ?? o.alpha;
|
|
2077
|
+
const hides = FILLED.has(kind) && !hairline && filled && !soft && over && opacity >= 0.8;
|
|
2078
|
+
const cuts = hairline && !soft && over && opacity >= FAINT;
|
|
2079
|
+
if (!hides && !cuts) continue;
|
|
2080
|
+
const st = scene.get(t), so = scene.get(o);
|
|
2081
|
+
if (st && so && st !== so) continue;
|
|
2082
|
+
const ob = seen.get(o);
|
|
2083
|
+
if (!ob) continue;
|
|
2084
|
+
const covered = intersection(tb, ob) / area;
|
|
2085
|
+
if (cuts) {
|
|
2086
|
+
const horizontal = ob.width >= ob.height;
|
|
2087
|
+
const mid = horizontal ? ob.y + ob.height / 2 : ob.x + ob.width / 2;
|
|
2088
|
+
const lo = horizontal ? tb.y + tb.height * 0.2 : tb.x + tb.width * 0.2, hi = horizontal ? tb.y + tb.height * 0.8 : tb.x + tb.width * 0.8;
|
|
2089
|
+
const along = horizontal ? Math.min(ob.x + ob.width, tb.x + tb.width) - Math.max(ob.x, tb.x) : Math.min(ob.y + ob.height, tb.y + tb.height) - Math.max(ob.y, tb.y);
|
|
2090
|
+
if (mid < lo || mid > hi || along < 0.3 * (horizontal ? tb.width : tb.height)) continue;
|
|
2091
|
+
} else if (covered < 0.1) continue;
|
|
2092
|
+
const word = kind === "image" || kind === "video" ? kind : "shape";
|
|
2093
|
+
issues.push(`text layer "${t.path}" and ${word} layer "${o.path}" overlap: it covers ${Math.round(covered * 100)}% of the text (drawn ${over ? "over" : "under"} it)`);
|
|
2094
|
+
}
|
|
2095
|
+
}
|
|
2022
2096
|
const mode = opts.layers ?? "all";
|
|
2023
2097
|
const listed = mode === "none" ? [] : mode === "visible" ? layers.filter((l) => l.visible) : layers;
|
|
2024
2098
|
return { frame, time, canvas, summary: { layers: layers.length, visible: layers.filter((l) => l.visible).length }, issues, layers: listed };
|
|
@@ -2031,7 +2105,7 @@ var round = (n) => Math.round(n * 1e6) / 1e6;
|
|
|
2031
2105
|
var family = (name) => name.replace(/\d+/g, "#");
|
|
2032
2106
|
function detailOf(seq) {
|
|
2033
2107
|
const s = seq.spec;
|
|
2034
|
-
const spans =
|
|
2108
|
+
const spans = chunkKJSEQVBV_cjs.spansMeta.get(seq.spec)?.preview;
|
|
2035
2109
|
if (spans) return spans.length > 60 ? spans.slice(0, 57) + "\u2026" : spans;
|
|
2036
2110
|
if (typeof s.text === "string") return s.text.length > 60 ? s.text.slice(0, 57) + "\u2026" : s.text;
|
|
2037
2111
|
if (typeof s.asset === "string") return `asset \u201C${s.asset}\u201D`;
|
|
@@ -2047,10 +2121,10 @@ function walk(comp, parentStart, parentEnd, depth, prefix, rows, transitions, lo
|
|
|
2047
2121
|
const start = parentStart + (seq.at ?? 0);
|
|
2048
2122
|
const end = Math.min(parentEnd, seq.duration !== void 0 ? start + seq.duration : parentEnd);
|
|
2049
2123
|
const span = end - start;
|
|
2050
|
-
const keys = (seq.spec.keyframes ?? []).map((kf) => round(start +
|
|
2124
|
+
const keys = (seq.spec.keyframes ?? []).map((kf) => round(start + chunkKJSEQVBV_cjs.resolveAt(kf.at, span))).sort((a, b) => a - b).slice(0, MAX_KEYS);
|
|
2051
2125
|
const row = { path: prefix + name, name, type: seq.spec.type, depth, start: round(start), end: round(end), keys, detail: detailOf(seq), ...local ? { local } : {} };
|
|
2052
2126
|
const inner = [];
|
|
2053
|
-
const isComp = seq instanceof
|
|
2127
|
+
const isComp = seq instanceof chunkY5UWFH6Y_cjs.CompositionSequence;
|
|
2054
2128
|
if (isComp) {
|
|
2055
2129
|
const label = seq.remapLabel();
|
|
2056
2130
|
walk(seq, label ? 0 : start, label ? seq.contentSpan : end, depth + 1, prefix + name + "/", inner, transitions, label ? `${name} ${label}` : local);
|
|
@@ -2209,7 +2283,7 @@ function sheetLayout(n, columns, cellW, srcW, srcH, labelH) {
|
|
|
2209
2283
|
}
|
|
2210
2284
|
|
|
2211
2285
|
// src/core/vars.ts
|
|
2212
|
-
var RESERVED_NAMES = ["w", "h", "W", "H", "GW", "GH", "t", "d", "T", "contain", "cover", "value", ...
|
|
2286
|
+
var RESERVED_NAMES = ["w", "h", "W", "H", "GW", "GH", "t", "d", "T", "contain", "cover", "value", ...chunkKJSEQVBV_cjs.EXPRESSION_NAMES];
|
|
2213
2287
|
var NAME = /^[A-Za-z_][A-Za-z0-9_]*$/;
|
|
2214
2288
|
var isPlain = (v) => !!v && typeof v === "object" && (Object.getPrototypeOf(v) === Object.prototype || Object.getPrototypeOf(v) === null);
|
|
2215
2289
|
function normalizeVars(raw, where, warn = (m) => console.warn(m)) {
|
|
@@ -2645,6 +2719,10 @@ var Movie = class {
|
|
|
2645
2719
|
_silent = 0;
|
|
2646
2720
|
/** render() / peek() in flight: a rebuild does not swap the composition under them. */
|
|
2647
2721
|
_busy = 0;
|
|
2722
|
+
/** > 0 while the movie is moving its scene to another moment (a seek, a motion-blurred frame, the poster): a thumbnail does not start then. */
|
|
2723
|
+
_moving = 0;
|
|
2724
|
+
/** The thumbnail being drawn, if any: a seek waits for it (it has the scene on another moment for a few microtasks). */
|
|
2725
|
+
_thumbRun = null;
|
|
2648
2726
|
_idleWaiters = [];
|
|
2649
2727
|
/** What went into the mix, and its peak before limiting — kept for inspectAudio(). */
|
|
2650
2728
|
_audioSources = [];
|
|
@@ -2692,6 +2770,7 @@ var Movie = class {
|
|
|
2692
2770
|
if (this._posterFrame === null || !this.timeline) return;
|
|
2693
2771
|
const back = this.currentFrame;
|
|
2694
2772
|
this.currentFrame = this._posterFrame;
|
|
2773
|
+
this._moving++;
|
|
2695
2774
|
try {
|
|
2696
2775
|
this.timeline.time(this._timeOf(this._posterFrame));
|
|
2697
2776
|
await this._awaitVideoFrames();
|
|
@@ -2699,6 +2778,7 @@ var Movie = class {
|
|
|
2699
2778
|
this._renderNow();
|
|
2700
2779
|
} finally {
|
|
2701
2780
|
this.currentFrame = back;
|
|
2781
|
+
this._moving--;
|
|
2702
2782
|
}
|
|
2703
2783
|
this._atPoster = true;
|
|
2704
2784
|
}
|
|
@@ -2742,8 +2822,8 @@ var Movie = class {
|
|
|
2742
2822
|
this.stops = normalizeStops(applyVars(options.composition, this._vars)?.stops, this.duration, this.frameRate);
|
|
2743
2823
|
this._posterFrame = poster.frame;
|
|
2744
2824
|
this.background = options.background ?? "#000000";
|
|
2745
|
-
this.timeline =
|
|
2746
|
-
|
|
2825
|
+
this.timeline = chunkKJSEQVBV_cjs.createTimeline({ paused: true, defaults: { ease: "none" } });
|
|
2826
|
+
chunkKJSEQVBV_cjs.lengthen(this.timeline, this.duration);
|
|
2747
2827
|
const baseAppOptions = {
|
|
2748
2828
|
width: this.width,
|
|
2749
2829
|
height: this.height,
|
|
@@ -2837,8 +2917,8 @@ var Movie = class {
|
|
|
2837
2917
|
height: sizeWins ? height : spec.height ?? height,
|
|
2838
2918
|
duration: spec.duration ?? this.duration
|
|
2839
2919
|
} : void 0;
|
|
2840
|
-
await
|
|
2841
|
-
if (
|
|
2920
|
+
await chunkKJSEQVBV_cjs.ensureFilterLibrary(seededComposition);
|
|
2921
|
+
if (chunkNEUPEENI_cjs.usesAdvancedBlend(seededComposition)) await chunkNEUPEENI_cjs.enableAdvancedBlend(this.app.renderer);
|
|
2842
2922
|
const userComposition = seededComposition ? expandTransitions(seededComposition) : void 0;
|
|
2843
2923
|
const rootSeqSpec = {
|
|
2844
2924
|
type: "composition",
|
|
@@ -2848,7 +2928,7 @@ var Movie = class {
|
|
|
2848
2928
|
...userComposition
|
|
2849
2929
|
};
|
|
2850
2930
|
if (userComposition) carryTransitionWindows(userComposition, rootSeqSpec);
|
|
2851
|
-
const sequence = new
|
|
2931
|
+
const sequence = new chunkY5UWFH6Y_cjs.CompositionSequence(rootSeqSpec, null, rootShape);
|
|
2852
2932
|
lp?.begin("build", countLayers(rootSeqSpec));
|
|
2853
2933
|
try {
|
|
2854
2934
|
await sequence.build();
|
|
@@ -2984,8 +3064,8 @@ var Movie = class {
|
|
|
2984
3064
|
if (!changed) return { reason, ms: 0, audio: "none", frame: this.currentFrame, playing: this.isPlaying, unchanged: true };
|
|
2985
3065
|
sequence = await this._construct(composition, vars, width, height, void 0, this._resized || sizeChanged);
|
|
2986
3066
|
alive();
|
|
2987
|
-
const timeline =
|
|
2988
|
-
|
|
3067
|
+
const timeline = chunkKJSEQVBV_cjs.createTimeline({ paused: true, defaults: { ease: "none" } });
|
|
3068
|
+
chunkKJSEQVBV_cjs.lengthen(timeline, this.duration);
|
|
2989
3069
|
sequence.bindTimeline(timeline);
|
|
2990
3070
|
const hadSound = this.audioBuffer !== null;
|
|
2991
3071
|
const audio = await this._mixSound(sequence, this._ensureAudioContext());
|
|
@@ -3085,12 +3165,18 @@ var Movie = class {
|
|
|
3085
3165
|
this.emit("error", { where, message: error instanceof Error ? error.message : String(error), error });
|
|
3086
3166
|
}
|
|
3087
3167
|
async _goto(frame) {
|
|
3088
|
-
this.
|
|
3089
|
-
this.
|
|
3090
|
-
|
|
3091
|
-
|
|
3092
|
-
|
|
3093
|
-
|
|
3168
|
+
if (this._thumbRun) await this._thumbRun;
|
|
3169
|
+
this._moving++;
|
|
3170
|
+
try {
|
|
3171
|
+
this._atPoster = false;
|
|
3172
|
+
this.currentFrame = Math.max(0, Math.min(frame, this.totalFrames));
|
|
3173
|
+
this.timeline.time(this._timeOf(this.currentFrame));
|
|
3174
|
+
await this._awaitVideoFrames();
|
|
3175
|
+
this._updateSpace();
|
|
3176
|
+
this._renderNow();
|
|
3177
|
+
} finally {
|
|
3178
|
+
this._moving--;
|
|
3179
|
+
}
|
|
3094
3180
|
this.emit("frame", { frame: this.currentFrame, totalFrames: this.totalFrames });
|
|
3095
3181
|
}
|
|
3096
3182
|
/**
|
|
@@ -3138,6 +3224,69 @@ var Movie = class {
|
|
|
3138
3224
|
if (o.as === "imageData") return out.getContext("2d").getImageData(0, 0, out.width, out.height);
|
|
3139
3225
|
return encodeCanvas(out, o.type, o.as, o.quality);
|
|
3140
3226
|
}
|
|
3227
|
+
/**
|
|
3228
|
+
* Why `thumbnail()` is off for this movie: `'variables'` (it declares `vars`: the picture depends on them and changes when they do) or `'video'` (a video
|
|
3229
|
+
* layer: its frame must be waited for, which would seek the playing video). `null`: it works.
|
|
3230
|
+
*/
|
|
3231
|
+
get thumbnailsOff() {
|
|
3232
|
+
if (this._declared.size > 0) return "variables";
|
|
3233
|
+
if (!this._rootSequence) return null;
|
|
3234
|
+
const found = [];
|
|
3235
|
+
collectVideoSequences(this._rootSequence, found);
|
|
3236
|
+
return found.some((v) => v.spec?.type === "video") ? "video" : null;
|
|
3237
|
+
}
|
|
3238
|
+
/**
|
|
3239
|
+
* A small picture of any frame, drawn WITHOUT moving the playhead or changing what is on the canvas, so it can be made while the movie plays or is
|
|
3240
|
+
* paused (a seek-bar preview). The scene is put on that moment, drawn, copied, and put back, all within the microtasks of one task: the browser never
|
|
3241
|
+
* shows the in-between. Gives `null` when it cannot be made right now: the movie has thumbnails off (see `thumbnailsOff`), is moving somewhere else
|
|
3242
|
+
* (a seek, a render, a peek), or is another thumbnail's turn. It is the picture `snapshot()` gives at that size (without motion blur).
|
|
3243
|
+
*/
|
|
3244
|
+
async thumbnail(frame, opts = {}) {
|
|
3245
|
+
chunkTWZNOUM7_cjs.warnUnknownOptions("movie.thumbnail()", opts, ["width", "scale"]);
|
|
3246
|
+
this._requireReady("thumbnail");
|
|
3247
|
+
if (opts.width !== void 0 && !(opts.width > 0 && opts.width <= this.width * 4)) throw new Error(`pixi-effects: movie.thumbnail(): width must be above 0 and at most ${this.width * 4} px, got ${opts.width}`);
|
|
3248
|
+
if (opts.scale !== void 0 && !(opts.scale > 0 && opts.scale <= 4)) throw new Error(`pixi-effects: movie.thumbnail(): scale must be above 0 and at most 4, got ${opts.scale}`);
|
|
3249
|
+
if (this.thumbnailsOff || this._moving > 0 || this._busy > 0 || this._thumbRun) return null;
|
|
3250
|
+
const w = Math.max(1, Math.round(opts.width ?? (opts.scale !== void 0 ? this.width * opts.scale : 160)));
|
|
3251
|
+
const h = Math.max(1, Math.round(w * this.height / this.width));
|
|
3252
|
+
let done;
|
|
3253
|
+
this._thumbRun = new Promise((r) => {
|
|
3254
|
+
done = r;
|
|
3255
|
+
});
|
|
3256
|
+
try {
|
|
3257
|
+
return await this._drawThumbnail(clampFrame(frame, this.totalFrames), w, h);
|
|
3258
|
+
} finally {
|
|
3259
|
+
this._thumbRun = null;
|
|
3260
|
+
done();
|
|
3261
|
+
}
|
|
3262
|
+
}
|
|
3263
|
+
async _drawThumbnail(frame, w, h) {
|
|
3264
|
+
const stage = this.app.canvas;
|
|
3265
|
+
const out = document.createElement("canvas");
|
|
3266
|
+
out.width = w;
|
|
3267
|
+
out.height = h;
|
|
3268
|
+
const keep = this.timeline.time();
|
|
3269
|
+
const t = this._timeOf(frame);
|
|
3270
|
+
this._nominalTime = t;
|
|
3271
|
+
try {
|
|
3272
|
+
this.timeline.time(t);
|
|
3273
|
+
await this._awaitVideoFrames(t);
|
|
3274
|
+
this._updateSpace(t);
|
|
3275
|
+
this._renderNow();
|
|
3276
|
+
out.getContext("2d").drawImage(stage, 0, 0, w, h);
|
|
3277
|
+
} finally {
|
|
3278
|
+
this._nominalTime = keep;
|
|
3279
|
+
try {
|
|
3280
|
+
this.timeline.time(keep);
|
|
3281
|
+
await this._awaitVideoFrames(keep);
|
|
3282
|
+
this._updateSpace(keep);
|
|
3283
|
+
this._renderNow();
|
|
3284
|
+
} finally {
|
|
3285
|
+
this._nominalTime = null;
|
|
3286
|
+
}
|
|
3287
|
+
}
|
|
3288
|
+
return out;
|
|
3289
|
+
}
|
|
3141
3290
|
async onionSkin(opts = {}) {
|
|
3142
3291
|
chunkTWZNOUM7_cjs.warnUnknownOptions("movie.onionSkin()", opts, ["from", "to", "count", "scale", "as", "motionBlur"]);
|
|
3143
3292
|
this._requireReady("onionSkin");
|
|
@@ -3316,9 +3465,11 @@ var Movie = class {
|
|
|
3316
3465
|
async _exposeFrame(frame, mb, target, settle) {
|
|
3317
3466
|
const g = target.getContext("2d");
|
|
3318
3467
|
const stage = this.app.canvas;
|
|
3468
|
+
if (this._thumbRun) await this._thumbRun;
|
|
3319
3469
|
this._atPoster = false;
|
|
3320
3470
|
const times = blurTimes(frame, this.frameRate, mb, Math.max(0, this.duration - END_MARGIN));
|
|
3321
3471
|
this._nominalTime = this._timeOf(Math.max(0, Math.min(frame, this.totalFrames)));
|
|
3472
|
+
this._moving++;
|
|
3322
3473
|
try {
|
|
3323
3474
|
for (let k = 0; k < times.length; k++) {
|
|
3324
3475
|
const t = times[k];
|
|
@@ -3332,6 +3483,7 @@ var Movie = class {
|
|
|
3332
3483
|
}
|
|
3333
3484
|
} finally {
|
|
3334
3485
|
this._nominalTime = null;
|
|
3486
|
+
this._moving--;
|
|
3335
3487
|
}
|
|
3336
3488
|
g.globalAlpha = 1;
|
|
3337
3489
|
if (settle) await this._goto(frame);
|
|
@@ -3627,7 +3779,7 @@ function countLayers(spec) {
|
|
|
3627
3779
|
n += 1 + countLayers(s);
|
|
3628
3780
|
const spans = s.spans;
|
|
3629
3781
|
if (Array.isArray(spans)) n += spans.length;
|
|
3630
|
-
const src =
|
|
3782
|
+
const src = chunkY5UWFH6Y_cjs.maskSourceOf(mask);
|
|
3631
3783
|
if (src.kind === "inline") n += 1 + countLayers(src.spec);
|
|
3632
3784
|
}
|
|
3633
3785
|
return n;
|
|
@@ -3640,7 +3792,7 @@ function measureText(text, style = {}) {
|
|
|
3640
3792
|
return { width: m.width, height: m.height, lines: text.split("\n").length };
|
|
3641
3793
|
}
|
|
3642
3794
|
function splitText(text, style = {}, opts = {}) {
|
|
3643
|
-
chunkTWZNOUM7_cjs.warnUnknownOptions("splitText()", opts, ["by", "x", "y", "align"]);
|
|
3795
|
+
chunkTWZNOUM7_cjs.warnUnknownOptions("splitText()", opts, ["by", "x", "y", "align", "vertical"]);
|
|
3644
3796
|
let by = opts.by ?? "chars";
|
|
3645
3797
|
if (!BY.includes(by)) {
|
|
3646
3798
|
const g = chunkTWZNOUM7_cjs.suggestName(String(by), BY);
|
|
@@ -3659,6 +3811,7 @@ function splitText(text, style = {}, opts = {}) {
|
|
|
3659
3811
|
}
|
|
3660
3812
|
if (text === "") return [];
|
|
3661
3813
|
const ts = new pixi_js.TextStyle(style);
|
|
3814
|
+
if (opts.vertical) return splitVertical(text, style, ts, x0, y0, align, by);
|
|
3662
3815
|
const lineHeight = pixi_js.CanvasTextMetrics.measureText("M", ts).lineHeight ?? pixi_js.CanvasTextMetrics.measureText("M", ts).height;
|
|
3663
3816
|
const sentinel = widthOf("|", ts);
|
|
3664
3817
|
const out = [];
|
|
@@ -3682,11 +3835,41 @@ function splitText(text, style = {}, opts = {}) {
|
|
|
3682
3835
|
});
|
|
3683
3836
|
return out;
|
|
3684
3837
|
}
|
|
3838
|
+
var PUNCT = new Set("\u3001\u3002\uFF0C\uFF0E\uFF64\uFF61");
|
|
3839
|
+
var SMALL = new Set("\u3041\u3043\u3045\u3047\u3049\u3063\u3083\u3085\u3087\u308E\u30A1\u30A3\u30A5\u30A7\u30A9\u30C3\u30E3\u30E5\u30E7\u30EE\u30F5\u30F6");
|
|
3840
|
+
var TURNED = new Set("\u30FC\u2015\u2014\uFF0D\uFF5E\u301C\u2026\u2025\uFF08\uFF09()\uFF3B\uFF3D[]\uFF5B\uFF5D{}\u300C\u300D\u300E\u300F\u3008\u3009\u300A\u300B\u3010\u3011\u3014\u3015<>\u226A\u226B");
|
|
3841
|
+
function splitVertical(text, style, ts, right, top, align, by) {
|
|
3842
|
+
if (by !== "chars") console.warn(`pixi-effects: splitText(): vertical text has only a "chars" form (by "${by}" has no vertical layout); using "chars"`);
|
|
3843
|
+
const em = typeof style.fontSize === "number" ? style.fontSize : Number(ts.fontSize) || 26;
|
|
3844
|
+
const spacing = typeof style.letterSpacing === "number" ? style.letterSpacing : 0;
|
|
3845
|
+
const cell = em + spacing;
|
|
3846
|
+
const lineHeight = pixi_js.CanvasTextMetrics.measureText("M", ts).lineHeight ?? pixi_js.CanvasTextMetrics.measureText("M", ts).height;
|
|
3847
|
+
const out = [];
|
|
3848
|
+
text.split("\n").forEach((line, lineNo) => {
|
|
3849
|
+
const chars = Array.from(line);
|
|
3850
|
+
const start = align === "center" ? top - chars.length * cell / 2 : align === "right" ? top - chars.length * cell : top;
|
|
3851
|
+
const column = right - lineHeight / 2 - lineNo * lineHeight;
|
|
3852
|
+
chars.forEach((ch, i) => {
|
|
3853
|
+
if (/\s/.test(ch)) return;
|
|
3854
|
+
let cx = column, cy = start + i * cell + cell / 2;
|
|
3855
|
+
if (PUNCT.has(ch)) {
|
|
3856
|
+
cx += 0.5 * em;
|
|
3857
|
+
cy -= 0.5 * em;
|
|
3858
|
+
} else if (SMALL.has(ch)) {
|
|
3859
|
+
cx += 0.1 * em;
|
|
3860
|
+
cy -= 0.1 * em;
|
|
3861
|
+
}
|
|
3862
|
+
const width = widthOf(ch, ts);
|
|
3863
|
+
out.push({ text: ch, x: cx - width / 2, y: cy - lineHeight / 2, width, index: out.length, line: lineNo, cx, cy, rotation: TURNED.has(ch) ? 90 : 0 });
|
|
3864
|
+
});
|
|
3865
|
+
});
|
|
3866
|
+
return out;
|
|
3867
|
+
}
|
|
3685
3868
|
|
|
3686
3869
|
// src/presets/_ease.ts
|
|
3687
3870
|
function parseEase2(name) {
|
|
3688
|
-
|
|
3689
|
-
return
|
|
3871
|
+
chunkKJSEQVBV_cjs.checkEase(name, "a preset");
|
|
3872
|
+
return chunkKJSEQVBV_cjs.parseEase(name);
|
|
3690
3873
|
}
|
|
3691
3874
|
|
|
3692
3875
|
// src/presets/kenBurns.ts
|
|
@@ -3821,17 +4004,17 @@ function orbit(opts) {
|
|
|
3821
4004
|
throw new Error("pixi-effects: orbit() cannot combine `radius` with `dollyZoom` \u2014 the radius follows the animated fov");
|
|
3822
4005
|
}
|
|
3823
4006
|
const [cx, cy] = opts.center ?? [width / 2, height / 2];
|
|
3824
|
-
const fixedR = opts.radius ??
|
|
4007
|
+
const fixedR = opts.radius ?? chunkKJSEQVBV_cjs.homeDistance(height, fov ?? chunkKJSEQVBV_cjs.DEFAULT_FOV);
|
|
3825
4008
|
const start = opts.start ?? -degrees / 2;
|
|
3826
4009
|
const steps = Math.max(1, Math.round(duration * stepsPerSecond));
|
|
3827
4010
|
const easeFn = parseEase2(ease);
|
|
3828
4011
|
const dollyEase = dolly ? parseEase2(dolly.ease ?? ease) : null;
|
|
3829
4012
|
const pos = (i) => {
|
|
3830
4013
|
const p = i / steps;
|
|
3831
|
-
const a = (start + degrees * easeFn(p)) *
|
|
4014
|
+
const a = (start + degrees * easeFn(p)) * chunkKJSEQVBV_cjs.DEG;
|
|
3832
4015
|
if (!dolly) return { x: cx + fixedR * Math.sin(a), z: fixedR * Math.cos(a) };
|
|
3833
4016
|
const f = dolly.from + (dolly.to - dolly.from) * dollyEase(p);
|
|
3834
|
-
const R =
|
|
4017
|
+
const R = chunkKJSEQVBV_cjs.homeDistance(height, f);
|
|
3835
4018
|
return { x: cx + R * Math.sin(a), z: R * Math.cos(a), fov: f };
|
|
3836
4019
|
};
|
|
3837
4020
|
const keyframes = [];
|
|
@@ -3886,7 +4069,7 @@ function particles(opts) {
|
|
|
3886
4069
|
const round2 = (v) => Math.round(v * 1e6) / 1e6;
|
|
3887
4070
|
const out = [];
|
|
3888
4071
|
for (let i = 0; i < count; i++) {
|
|
3889
|
-
const r =
|
|
4072
|
+
const r = chunkKJSEQVBV_cjs.random(seed * 1000003 + i * 7919 + 17);
|
|
3890
4073
|
const pick = ([a2, b]) => a2 + r() * (b - a2);
|
|
3891
4074
|
const born = at + r() * emit;
|
|
3892
4075
|
const lifetime = pick(life);
|
|
@@ -3899,7 +4082,7 @@ function particles(opts) {
|
|
|
3899
4082
|
const turn = spin ? pick(spin) : 0;
|
|
3900
4083
|
const startAngle = spin ? r() * 360 : 0;
|
|
3901
4084
|
const swayAmp = sway?.amp ?? 0, swayFreq = sway?.freq ?? 1;
|
|
3902
|
-
const n0 = sway ?
|
|
4085
|
+
const n0 = sway ? chunkKJSEQVBV_cjs.noise(0, seed * 1000003 + i) : 0;
|
|
3903
4086
|
const at_ = (t) => {
|
|
3904
4087
|
const axis = (p0, v0, acc) => {
|
|
3905
4088
|
if (drag > 0) {
|
|
@@ -3908,7 +4091,7 @@ function particles(opts) {
|
|
|
3908
4091
|
}
|
|
3909
4092
|
return p0 + v0 * t + 0.5 * acc * t * t;
|
|
3910
4093
|
};
|
|
3911
|
-
const sw = sway ? swayAmp * (
|
|
4094
|
+
const sw = sway ? swayAmp * (chunkKJSEQVBV_cjs.noise(t * swayFreq, seed * 1000003 + i) - n0) : 0;
|
|
3912
4095
|
return { x: axis(x0, vx, wind) + sw, y: axis(y0, vy, gravity) };
|
|
3913
4096
|
};
|
|
3914
4097
|
const kfs = [];
|
|
@@ -3970,7 +4153,7 @@ function followPath(opts) {
|
|
|
3970
4153
|
if (steps > MAX_STEPS) throw new Error(`followPath(): ${steps} samples is too many (max ${MAX_STEPS}); lower frameRate or duration`);
|
|
3971
4154
|
const segments = [];
|
|
3972
4155
|
let total = 0;
|
|
3973
|
-
for (const line of
|
|
4156
|
+
for (const line of chunkKJSEQVBV_cjs.flattenSvgPath(d)) {
|
|
3974
4157
|
const p = line.closed ? [...line.pts, line.pts[0], line.pts[1]] : line.pts;
|
|
3975
4158
|
for (let i = 2; i < p.length; i += 2) {
|
|
3976
4159
|
const len = Math.hypot(p[i] - p[i - 2], p[i + 1] - p[i - 1]);
|
|
@@ -4124,7 +4307,7 @@ function distances(n, from, grid, seed) {
|
|
|
4124
4307
|
if (n === 0) return [];
|
|
4125
4308
|
if (from === "random") {
|
|
4126
4309
|
const order = Array.from({ length: n }, (_, i) => i);
|
|
4127
|
-
const r =
|
|
4310
|
+
const r = chunkKJSEQVBV_cjs.random(seed);
|
|
4128
4311
|
for (let i = n - 1; i > 0; i--) {
|
|
4129
4312
|
const j = Math.floor(r() * (i + 1));
|
|
4130
4313
|
[order[i], order[j]] = [order[j], order[i]];
|
|
@@ -4186,7 +4369,7 @@ function wiggle(opts) {
|
|
|
4186
4369
|
to[n] = p.around;
|
|
4187
4370
|
return;
|
|
4188
4371
|
}
|
|
4189
|
-
const off = (
|
|
4372
|
+
const off = (chunkKJSEQVBV_cjs.rand(seed * 7919 + pi * 104729 + s * 31 + 1) * 2 - 1) * p.amp;
|
|
4190
4373
|
to[n] = typeof p.around === "number" ? p.around + off : `(${p.around}) ${off < 0 ? "-" : "+"} ${Math.abs(off)}`;
|
|
4191
4374
|
});
|
|
4192
4375
|
out.push({ at: at + s * stepLen, to, duration: stepLen, ease });
|
|
@@ -4197,7 +4380,7 @@ function wiggle(opts) {
|
|
|
4197
4380
|
// src/presets/animateText.ts
|
|
4198
4381
|
var TWEEN_KEYS = ["preset", "from", "to", "duration", "ease"];
|
|
4199
4382
|
var TIME_KEYS = ["at", "delay", "start", "begin", "time"];
|
|
4200
|
-
var KEYS5 = ["by", "x", "y", "align", "name", "at", "duration", "in", "out", "stagger", "idle", "styleFor"];
|
|
4383
|
+
var KEYS5 = ["by", "x", "y", "align", "vertical", "name", "at", "duration", "in", "out", "stagger", "idle", "styleFor"];
|
|
4201
4384
|
var PRESETS = {
|
|
4202
4385
|
rise: { from: { y: 40, alpha: 0 }, duration: 0.5, ease: "back.out(2)" },
|
|
4203
4386
|
drop: { from: { y: -50, alpha: 0 }, duration: 0.7, ease: "bounce.out" },
|
|
@@ -4210,14 +4393,14 @@ var PRESETS = {
|
|
|
4210
4393
|
var PRESET_NAMES = Object.keys(PRESETS);
|
|
4211
4394
|
function animateText(text, style, options) {
|
|
4212
4395
|
chunkTWZNOUM7_cjs.warnUnknownOptions("animateText()", options, KEYS5);
|
|
4213
|
-
const { by = "chars", x = 0, y = 0, align = "left", name = "text", at = 0, duration, idle, styleFor } = options;
|
|
4396
|
+
const { by = "chars", x = 0, y = 0, align = "left", vertical = false, name = "text", at = 0, duration, idle, styleFor } = options;
|
|
4214
4397
|
for (const [n, v] of [["x", x], ["y", y]]) {
|
|
4215
4398
|
if (typeof v !== "number" || !Number.isFinite(v)) {
|
|
4216
4399
|
throw new Error(`animateText(): ${n} must be a number of pixels (e.g. ${n}: 640), got ${JSON.stringify(v)}. The letters are measured once, when the layers are made, so an expression such as 'GW/2' cannot be used here: compute the number (W / 2) yourself. \`y\` is the TOP of the line.`);
|
|
4217
4400
|
}
|
|
4218
4401
|
}
|
|
4219
4402
|
if (!(Number.isFinite(duration) && duration > 0)) throw new Error(`animateText(): duration must be a positive number of seconds (how long until the last piece is gone), got ${duration}`);
|
|
4220
|
-
const pieces = splitText(text, style, { by, x, y, align });
|
|
4403
|
+
const pieces = splitText(text, style, { by, x, y, align, ...vertical ? { vertical } : {} });
|
|
4221
4404
|
if (pieces.length === 0) return [];
|
|
4222
4405
|
const lineHeight = measureText("M", style).height;
|
|
4223
4406
|
const inTween = options.in === false ? null : resolveTween(options.in ?? "rise", "in");
|
|
@@ -4236,12 +4419,12 @@ function animateText(text, style, options) {
|
|
|
4236
4419
|
if (inTween && outTween.at - at < inTween.duration - 1e-9) console.warn(`pixi-effects: animateText(): out.at ${outTween.at} is before the entrance has finished (it takes ${inTween.duration} s from at ${at}): use out.at \u2265 ${+(at + inTween.duration).toFixed(3)}`);
|
|
4237
4420
|
}
|
|
4238
4421
|
return pieces.map((p, i) => {
|
|
4239
|
-
const cx = p.x + p.width / 2, cy = p.y + lineHeight / 2;
|
|
4240
|
-
const rest = { x: cx, y: cy, alpha: 1, scale: 1, scaleX: 1, scaleY: 1, rotation: 0 };
|
|
4422
|
+
const cx = p.cx ?? p.x + p.width / 2, cy = p.cy ?? p.y + lineHeight / 2;
|
|
4423
|
+
const rest = { x: cx, y: cy, alpha: 1, scale: 1, scaleX: 1, scaleY: 1, rotation: p.rotation ?? 0 };
|
|
4241
4424
|
const start = at + delays[i];
|
|
4242
4425
|
const len = end - start;
|
|
4243
4426
|
const keyframes = [];
|
|
4244
|
-
const place = (key, v) => key === "x" || key === "y" ? rest[key] + v : v;
|
|
4427
|
+
const place = (key, v) => key === "x" || key === "y" || key === "rotation" ? rest[key] + v : v;
|
|
4245
4428
|
if (inTween) {
|
|
4246
4429
|
keyframes.push({
|
|
4247
4430
|
at: 0,
|
|
@@ -4280,7 +4463,7 @@ function animateText(text, style, options) {
|
|
|
4280
4463
|
style: styleFor ? { ...style, ...styleFor(p) } : style,
|
|
4281
4464
|
at: start,
|
|
4282
4465
|
duration: len,
|
|
4283
|
-
initial: { x: cx, y: cy, anchorX: 0.5, anchorY: 0.5 },
|
|
4466
|
+
initial: { x: cx, y: cy, anchorX: 0.5, anchorY: 0.5, ...rest.rotation !== 0 ? { rotation: rest.rotation } : {} },
|
|
4284
4467
|
keyframes
|
|
4285
4468
|
};
|
|
4286
4469
|
});
|
|
@@ -4644,5 +4827,5 @@ exports.splitText = splitText;
|
|
|
4644
4827
|
exports.stagger = stagger;
|
|
4645
4828
|
exports.wiggle = wiggle;
|
|
4646
4829
|
exports.withFade = withFade;
|
|
4647
|
-
//# sourceMappingURL=chunk-
|
|
4648
|
-
//# sourceMappingURL=chunk-
|
|
4830
|
+
//# sourceMappingURL=chunk-CC7SUR7Q.cjs.map
|
|
4831
|
+
//# sourceMappingURL=chunk-CC7SUR7Q.cjs.map
|