pixi-effects 0.18.0 → 0.19.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 +24 -0
- package/README.md +6 -6
- package/ai/CHAT.md +1 -1
- package/ai/SKILL.md +1 -1
- package/ai/chat-template.html +4 -4
- package/ai/reference/cheatsheet.md +5 -5
- package/ai/reference/pitfalls.md +5 -1
- package/ai/reference/recipes.md +65 -0
- package/ai/template.html +5 -5
- package/ai/tools/check.mjs +14 -3
- package/dist/{Base-BQUodYZK.d.ts → Base-B4WbUJO2.d.ts} +1 -1
- package/dist/{Base-OHqp8qvX.d.cts → Base-i88XXaiP.d.cts} +1 -1
- package/dist/Composition-KYNPRWK3.cjs +14 -0
- package/dist/{Composition-6JMXWNVV.cjs.map → Composition-KYNPRWK3.cjs.map} +1 -1
- package/dist/Composition-QBKEEJBV.js +5 -0
- package/dist/{Composition-MLBHYYFF.js.map → Composition-QBKEEJBV.js.map} +1 -1
- package/dist/Controller.d.cts +2 -2
- package/dist/Controller.d.ts +2 -2
- package/dist/{Movie-DlHQ9C02.d.ts → Movie-8IrqL3kO.d.ts} +6 -1
- package/dist/{Movie-K2YuVAdg.d.cts → Movie-CpmdNadg.d.cts} +6 -1
- package/dist/Presenter.d.cts +2 -2
- package/dist/Presenter.d.ts +2 -2
- package/dist/{chunk-UXDR3ZDU.js → chunk-B3YB2TNY.js} +4 -3
- package/dist/chunk-B3YB2TNY.js.map +1 -0
- package/dist/{chunk-JW67MDHQ.cjs → chunk-CTZRFSVU.cjs} +27 -26
- package/dist/chunk-CTZRFSVU.cjs.map +1 -0
- package/dist/{chunk-ANO5R2E6.cjs → chunk-VTBT6NNE.cjs} +755 -48
- package/dist/chunk-VTBT6NNE.cjs.map +1 -0
- package/dist/{chunk-SG3Y66FN.js → chunk-YRXTKOV5.js} +757 -51
- package/dist/chunk-YRXTKOV5.js.map +1 -0
- package/dist/index.cjs +73 -36
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +5 -5
- package/dist/index.d.ts +5 -5
- package/dist/index.js +50 -13
- package/dist/index.js.map +1 -1
- package/dist/loader.css +1 -1
- package/dist/three.cjs +5 -5
- package/dist/three.d.cts +2 -2
- package/dist/three.d.ts +2 -2
- package/dist/three.js +1 -1
- package/dist/{types-SS51lP6O.d.cts → types-bzLJ7aUx.d.cts} +16 -6
- package/dist/{types-SS51lP6O.d.ts → types-bzLJ7aUx.d.ts} +16 -6
- package/docs/dsl.md +36 -5
- package/llms-full.txt +112 -11
- package/package.json +1 -1
- package/dist/Composition-6JMXWNVV.cjs +0 -14
- package/dist/Composition-MLBHYYFF.js +0 -5
- package/dist/chunk-ANO5R2E6.cjs.map +0 -1
- package/dist/chunk-JW67MDHQ.cjs.map +0 -1
- package/dist/chunk-SG3Y66FN.js.map +0 -1
- package/dist/chunk-UXDR3ZDU.js.map +0 -1
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { suggestName } from './chunk-DKGG7WD4.js';
|
|
1
|
+
import { suggestName, warnUnknownOptions } from './chunk-DKGG7WD4.js';
|
|
2
2
|
import * as PIXI from 'pixi.js';
|
|
3
|
-
import { Rectangle, Container, GraphicsPath, Graphics, Assets, Texture, Sprite, Text, Filter, GlProgram, defaultFilterVert, GpuProgram, UniformGroup,
|
|
3
|
+
import { Rectangle, Container, GraphicsPath, Graphics, Assets, Texture, Sprite, FillGradient, Text, Filter, GlProgram, defaultFilterVert, GpuProgram, UniformGroup, Color } from 'pixi.js';
|
|
4
4
|
import { gsap } from 'gsap';
|
|
5
5
|
|
|
6
6
|
// src/expr/random.ts
|
|
@@ -37,6 +37,113 @@ function noise(x, seed = 0) {
|
|
|
37
37
|
const u = f * f * f * (f * (f * 6 - 15) + 10);
|
|
38
38
|
return a + (b - a) * u;
|
|
39
39
|
}
|
|
40
|
+
var SETTLE_TOL = 5e-3;
|
|
41
|
+
var DEFAULTS = { mass: 1, stiffness: 100, damping: 10 };
|
|
42
|
+
function springResponse(t, { mass: m, stiffness: k, damping: c }) {
|
|
43
|
+
if (t <= 0) return 0;
|
|
44
|
+
const w0 = Math.sqrt(k / m);
|
|
45
|
+
const zeta = c / (2 * Math.sqrt(k * m));
|
|
46
|
+
if (Math.abs(zeta - 1) < 1e-6) return 1 - Math.exp(-w0 * t) * (1 + w0 * t);
|
|
47
|
+
if (zeta < 1) {
|
|
48
|
+
const wd = w0 * Math.sqrt(1 - zeta * zeta);
|
|
49
|
+
return 1 - Math.exp(-zeta * w0 * t) * (Math.cos(wd * t) + zeta * w0 / wd * Math.sin(wd * t));
|
|
50
|
+
}
|
|
51
|
+
const s = w0 * Math.sqrt(zeta * zeta - 1);
|
|
52
|
+
const r1 = -zeta * w0 + s, r2 = -zeta * w0 - s;
|
|
53
|
+
return 1 - (r2 * Math.exp(r1 * t) - r1 * Math.exp(r2 * t)) / (r2 - r1);
|
|
54
|
+
}
|
|
55
|
+
function complete(p) {
|
|
56
|
+
return { mass: p.mass ?? DEFAULTS.mass, stiffness: p.stiffness ?? DEFAULTS.stiffness, damping: p.damping ?? DEFAULTS.damping };
|
|
57
|
+
}
|
|
58
|
+
function springDuration(params = {}, tol = SETTLE_TOL) {
|
|
59
|
+
const p = complete(params);
|
|
60
|
+
const w0 = Math.sqrt(p.stiffness / p.mass);
|
|
61
|
+
const zeta = p.damping / (2 * Math.sqrt(p.stiffness * p.mass));
|
|
62
|
+
const bad = (t) => Math.abs(1 - springResponse(t, p)) > tol;
|
|
63
|
+
let lo, hi;
|
|
64
|
+
if (zeta < 1 - 1e-6) {
|
|
65
|
+
const wd = w0 * Math.sqrt(1 - zeta * zeta);
|
|
66
|
+
const decay = Math.PI * zeta / Math.sqrt(1 - zeta * zeta);
|
|
67
|
+
const n = Math.max(1, Math.ceil(Math.log(1 / tol) / decay));
|
|
68
|
+
lo = (n - 1) * Math.PI / wd;
|
|
69
|
+
hi = n * Math.PI / wd;
|
|
70
|
+
} else {
|
|
71
|
+
lo = 0;
|
|
72
|
+
hi = 1 / w0;
|
|
73
|
+
while (bad(hi)) {
|
|
74
|
+
lo = hi;
|
|
75
|
+
hi *= 2;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
for (let i = 0; i < 60; i++) {
|
|
79
|
+
const mid = (lo + hi) / 2;
|
|
80
|
+
if (bad(mid)) lo = mid;
|
|
81
|
+
else hi = mid;
|
|
82
|
+
}
|
|
83
|
+
return hi;
|
|
84
|
+
}
|
|
85
|
+
function springEase(params = {}) {
|
|
86
|
+
const sp = complete(params);
|
|
87
|
+
const T = springDuration(sp);
|
|
88
|
+
const end = springResponse(T, sp);
|
|
89
|
+
return (p) => p <= 0 ? 0 : p >= 1 ? 1 : springResponse(p * T, sp) / end;
|
|
90
|
+
}
|
|
91
|
+
var SPRING_PRESETS = {
|
|
92
|
+
gentle: { mass: 1, stiffness: 100, damping: 15 },
|
|
93
|
+
// zeta .75, one soft overshoot
|
|
94
|
+
snappy: { mass: 1, stiffness: 300, damping: 28 },
|
|
95
|
+
// zeta .81, quick, barely rings
|
|
96
|
+
bouncy: { mass: 1, stiffness: 170, damping: 10 },
|
|
97
|
+
// zeta .38
|
|
98
|
+
wobbly: { mass: 1, stiffness: 120, damping: 6 },
|
|
99
|
+
// zeta .27, rings several times
|
|
100
|
+
slow: { mass: 1, stiffness: 60, damping: 18 }
|
|
101
|
+
// zeta 1.16, no overshoot
|
|
102
|
+
};
|
|
103
|
+
var SPRING_RE = /^spring(?:\.(\w+)|\(([^)]*)\))?$/;
|
|
104
|
+
function springProblem(name) {
|
|
105
|
+
const m = SPRING_RE.exec(name.trim());
|
|
106
|
+
if (!m) return 'expected "spring(mass, stiffness, damping)" or "spring.<preset>"';
|
|
107
|
+
if (m[1] && !SPRING_PRESETS[m[1]]) return `no preset "${m[1]}" (presets: ${Object.keys(SPRING_PRESETS).join(", ")})`;
|
|
108
|
+
if (m[2] !== void 0 && m[2].trim() !== "") {
|
|
109
|
+
const nums = m[2].split(",").map((s) => Number(s.trim()));
|
|
110
|
+
if (nums.length > 3 || nums.some((n) => !Number.isFinite(n) || n <= 0)) return "mass, stiffness and damping must be 1 to 3 numbers greater than 0";
|
|
111
|
+
}
|
|
112
|
+
return null;
|
|
113
|
+
}
|
|
114
|
+
function parseSpring(name) {
|
|
115
|
+
if (typeof name !== "string" || !/^\s*spring/.test(name) || springProblem(name)) return null;
|
|
116
|
+
const m = SPRING_RE.exec(name.trim());
|
|
117
|
+
if (m[1]) return SPRING_PRESETS[m[1]];
|
|
118
|
+
const [mass, stiffness, damping] = (m[2] ?? "").split(",").map((s) => s.trim()).filter(Boolean).map(Number);
|
|
119
|
+
return complete({ mass, stiffness, damping });
|
|
120
|
+
}
|
|
121
|
+
var registered = false;
|
|
122
|
+
function registerSpringEases() {
|
|
123
|
+
if (registered) return;
|
|
124
|
+
registered = true;
|
|
125
|
+
const base = springEase();
|
|
126
|
+
const ease = (p) => base(p);
|
|
127
|
+
ease.config = (mass, stiffness, damping) => {
|
|
128
|
+
const bad = [mass, stiffness, damping].some((v) => v !== void 0 && !(typeof v === "number" && v > 0 && Number.isFinite(v)));
|
|
129
|
+
return springEase(bad ? {} : { mass, stiffness, damping });
|
|
130
|
+
};
|
|
131
|
+
gsap.registerEase("spring", ease);
|
|
132
|
+
for (const [name, p] of Object.entries(SPRING_PRESETS)) gsap.registerEase(`spring.${name}`, springEase(p));
|
|
133
|
+
}
|
|
134
|
+
var autoWarned = /* @__PURE__ */ new Set();
|
|
135
|
+
function kfDuration(kf) {
|
|
136
|
+
if (kf.duration !== "auto") return kf.duration ?? 0;
|
|
137
|
+
const sp = parseSpring(kf.ease);
|
|
138
|
+
if (sp) return Math.round(springDuration(sp) * 1e3) / 1e3;
|
|
139
|
+
const name = String(kf.ease ?? "none");
|
|
140
|
+
if (!/^\s*spring/.test(name) && !autoWarned.has(name)) {
|
|
141
|
+
autoWarned.add(name);
|
|
142
|
+
console.warn(`pixi-effects: keyframe duration 'auto' needs a spring ease (ease: 'spring(1, 170, 12)' or 'spring.bouncy'), got ease ${JSON.stringify(name)} \u2014 using 0.5 s.`);
|
|
143
|
+
}
|
|
144
|
+
return 0.5;
|
|
145
|
+
}
|
|
146
|
+
registerSpringEases();
|
|
40
147
|
|
|
41
148
|
// src/expr/Parser.ts
|
|
42
149
|
var FUNCS = {
|
|
@@ -294,6 +401,13 @@ var EASE_NAMES = ["none", ...FAMILIES.flatMap((f) => [`${f}.in`, `${f}.out`, `${
|
|
|
294
401
|
var warned = /* @__PURE__ */ new Set();
|
|
295
402
|
function checkEase(ease, where) {
|
|
296
403
|
if (typeof ease !== "string") return;
|
|
404
|
+
if (/^\s*spring/.test(ease)) {
|
|
405
|
+
const problem = springProblem(ease);
|
|
406
|
+
if (!problem || warned.has(ease)) return;
|
|
407
|
+
warned.add(ease);
|
|
408
|
+
console.warn(`pixi-effects: ${where}: unknown ease "${ease}" \u2014 ${problem}. GSAP would run it as its default ease, power1.out.`);
|
|
409
|
+
return;
|
|
410
|
+
}
|
|
297
411
|
const found = gsap.parseEase(ease);
|
|
298
412
|
if (typeof found === "function") return;
|
|
299
413
|
if (warned.has(ease)) return;
|
|
@@ -334,7 +448,7 @@ function resolveAt(at, duration) {
|
|
|
334
448
|
}
|
|
335
449
|
function normalizeKeyframe(kf, parentDuration) {
|
|
336
450
|
const at = resolveAt(kf.at, parentDuration);
|
|
337
|
-
const duration = kf
|
|
451
|
+
const duration = kfDuration(kf);
|
|
338
452
|
const ease = kf.ease ?? "none";
|
|
339
453
|
checkEase(ease, "a keyframe");
|
|
340
454
|
const hasSet = !!kf.set;
|
|
@@ -764,8 +878,217 @@ var ChromaKeyFilter = class extends Filter {
|
|
|
764
878
|
u[2] = rgb[2];
|
|
765
879
|
}
|
|
766
880
|
};
|
|
881
|
+
var HASH_GL = `
|
|
882
|
+
uint hash(uint x) { x ^= x >> 16; x *= 0x7feb352du; x ^= x >> 15; x *= 0x846ca68bu; x ^= x >> 16; return x; }
|
|
883
|
+
// one gaussian-ish value (sum of the four bytes of a hash), mean 0, std 1
|
|
884
|
+
float gauss(ivec2 p, uint k) {
|
|
885
|
+
uint h = hash(uint(p.x) + hash(uint(p.y) + hash(k)));
|
|
886
|
+
float s = float(h & 255u) + float((h >> 8) & 255u) + float((h >> 16) & 255u) + float(h >> 24);
|
|
887
|
+
return (s / 255.0 - 2.0) * 1.7320508;
|
|
888
|
+
}
|
|
889
|
+
// the grain value at a pixel: cells of size pixels, smoothly blended
|
|
890
|
+
float cell(vec2 pos, float size, uint k) {
|
|
891
|
+
vec2 q = pos / size - 0.5;
|
|
892
|
+
vec2 i = floor(q);
|
|
893
|
+
vec2 f = fract(q);
|
|
894
|
+
ivec2 p = ivec2(i);
|
|
895
|
+
float a = gauss(p, k), b = gauss(p + ivec2(1, 0), k), c = gauss(p + ivec2(0, 1), k), d = gauss(p + ivec2(1, 1), k);
|
|
896
|
+
float v = mix(mix(a, b, f.x), mix(c, d, f.x), f.y);
|
|
897
|
+
vec2 wx = vec2(1.0 - f.x, f.x), wy = vec2(1.0 - f.y, f.y);
|
|
898
|
+
return v * inversesqrt(dot(wx, wx) * dot(wy, wy)); // blending lowers the spread: keep std exactly 1 at every pixel
|
|
899
|
+
}`;
|
|
900
|
+
var GL_VERTEX = `#version 300 es
|
|
901
|
+
in vec2 aPosition;
|
|
902
|
+
out vec2 vTextureCoord;
|
|
903
|
+
uniform vec4 uInputSize;
|
|
904
|
+
uniform vec4 uOutputFrame;
|
|
905
|
+
uniform vec4 uOutputTexture;
|
|
906
|
+
void main(void) {
|
|
907
|
+
vec2 position = aPosition * uOutputFrame.zw + uOutputFrame.xy;
|
|
908
|
+
position.x = position.x * (2.0 / uOutputTexture.x) - 1.0;
|
|
909
|
+
position.y = position.y * (2.0 * uOutputTexture.z / uOutputTexture.y) - uOutputTexture.z;
|
|
910
|
+
gl_Position = vec4(position, 0.0, 1.0);
|
|
911
|
+
vTextureCoord = aPosition * (uOutputFrame.zw * uInputSize.zw);
|
|
912
|
+
}`;
|
|
913
|
+
var GL_FRAGMENT2 = `#version 300 es
|
|
914
|
+
precision highp float;
|
|
915
|
+
precision highp int;
|
|
916
|
+
in vec2 vTextureCoord;
|
|
917
|
+
uniform sampler2D uTexture;
|
|
918
|
+
uniform vec4 uInputSize;
|
|
919
|
+
uniform float uAmount;
|
|
920
|
+
uniform float uSize;
|
|
921
|
+
uniform float uSeed;
|
|
922
|
+
uniform float uFrame;
|
|
923
|
+
uniform float uColor;
|
|
924
|
+
out vec4 finalColor;
|
|
925
|
+
${HASH_GL}
|
|
926
|
+
void main(void) {
|
|
927
|
+
vec4 raw = texture(uTexture, vTextureCoord);
|
|
928
|
+
vec3 rgb = raw.a > 0.0 ? raw.rgb / raw.a : vec3(0.0);
|
|
929
|
+
float L = dot(rgb, vec3(0.2126, 0.7152, 0.0722));
|
|
930
|
+
float w = clamp(4.0 * L * (1.0 - L), 0.0, 1.0);
|
|
931
|
+
vec2 pos = vTextureCoord * uInputSize.xy;
|
|
932
|
+
uint k = hash(uint(uSeed) * 0x9E3779B1u + uint(uFrame));
|
|
933
|
+
float n0 = cell(pos, uSize, k);
|
|
934
|
+
vec3 n = vec3(n0);
|
|
935
|
+
if (uColor > 0.0) {
|
|
936
|
+
vec3 nc = vec3(cell(pos, uSize, k + 1u), cell(pos, uSize, k + 2u), cell(pos, uSize, k + 3u));
|
|
937
|
+
n = mix(n, nc, uColor);
|
|
938
|
+
}
|
|
939
|
+
rgb = clamp(rgb + n * (uAmount * w), 0.0, 1.0);
|
|
940
|
+
finalColor = vec4(rgb * raw.a, raw.a);
|
|
941
|
+
}`;
|
|
942
|
+
var WGSL_SOURCE2 = `
|
|
943
|
+
struct GlobalFilterUniforms {
|
|
944
|
+
uInputSize: vec4<f32>,
|
|
945
|
+
uInputPixel: vec4<f32>,
|
|
946
|
+
uInputClamp: vec4<f32>,
|
|
947
|
+
uOutputFrame: vec4<f32>,
|
|
948
|
+
uGlobalFrame: vec4<f32>,
|
|
949
|
+
uOutputTexture: vec4<f32>,
|
|
950
|
+
};
|
|
951
|
+
struct GrainUniforms {
|
|
952
|
+
uAmount: f32,
|
|
953
|
+
uSize: f32,
|
|
954
|
+
uSeed: f32,
|
|
955
|
+
uFrame: f32,
|
|
956
|
+
uColor: f32,
|
|
957
|
+
};
|
|
958
|
+
@group(0) @binding(0) var<uniform> gfu: GlobalFilterUniforms;
|
|
959
|
+
@group(0) @binding(1) var uTexture: texture_2d<f32>;
|
|
960
|
+
@group(0) @binding(2) var uSampler : sampler;
|
|
961
|
+
@group(1) @binding(0) var<uniform> grainUniforms : GrainUniforms;
|
|
962
|
+
|
|
963
|
+
struct VSOutput {
|
|
964
|
+
@builtin(position) position: vec4<f32>,
|
|
965
|
+
@location(0) uv : vec2<f32>,
|
|
966
|
+
};
|
|
967
|
+
fn filterVertexPosition(aPosition : vec2<f32>) -> vec4<f32> {
|
|
968
|
+
var position = aPosition * gfu.uOutputFrame.zw + gfu.uOutputFrame.xy;
|
|
969
|
+
position.x = position.x * (2.0 / gfu.uOutputTexture.x) - 1.0;
|
|
970
|
+
position.y = position.y * (2.0 * gfu.uOutputTexture.z / gfu.uOutputTexture.y) - gfu.uOutputTexture.z;
|
|
971
|
+
return vec4<f32>(position, 0.0, 1.0);
|
|
972
|
+
}
|
|
973
|
+
fn filterTextureCoord(aPosition : vec2<f32>) -> vec2<f32> {
|
|
974
|
+
return aPosition * (gfu.uOutputFrame.zw * gfu.uInputSize.zw);
|
|
975
|
+
}
|
|
976
|
+
@vertex
|
|
977
|
+
fn mainVertex(
|
|
978
|
+
@location(0) aPosition : vec2<f32>,
|
|
979
|
+
) -> VSOutput {
|
|
980
|
+
return VSOutput(
|
|
981
|
+
filterVertexPosition(aPosition),
|
|
982
|
+
filterTextureCoord(aPosition),
|
|
983
|
+
);
|
|
984
|
+
}
|
|
985
|
+
|
|
986
|
+
fn hash(xIn: u32) -> u32 {
|
|
987
|
+
var x = xIn;
|
|
988
|
+
x = x ^ (x >> 16u); x = x * 0x7feb352du; x = x ^ (x >> 15u); x = x * 0x846ca68bu; x = x ^ (x >> 16u);
|
|
989
|
+
return x;
|
|
990
|
+
}
|
|
991
|
+
fn gauss(p: vec2<i32>, k: u32) -> f32 {
|
|
992
|
+
let h = hash(u32(p.x) + hash(u32(p.y) + hash(k)));
|
|
993
|
+
let s = f32(h & 255u) + f32((h >> 8u) & 255u) + f32((h >> 16u) & 255u) + f32(h >> 24u);
|
|
994
|
+
return (s / 255.0 - 2.0) * 1.7320508;
|
|
995
|
+
}
|
|
996
|
+
fn cell(pos: vec2<f32>, size: f32, k: u32) -> f32 {
|
|
997
|
+
let q = pos / size - vec2<f32>(0.5);
|
|
998
|
+
let i = floor(q);
|
|
999
|
+
let f = fract(q);
|
|
1000
|
+
let p = vec2<i32>(i);
|
|
1001
|
+
let a = gauss(p, k);
|
|
1002
|
+
let b = gauss(p + vec2<i32>(1, 0), k);
|
|
1003
|
+
let c = gauss(p + vec2<i32>(0, 1), k);
|
|
1004
|
+
let d = gauss(p + vec2<i32>(1, 1), k);
|
|
1005
|
+
let v = mix(mix(a, b, f.x), mix(c, d, f.x), f.y);
|
|
1006
|
+
let wx = vec2<f32>(1.0 - f.x, f.x);
|
|
1007
|
+
let wy = vec2<f32>(1.0 - f.y, f.y);
|
|
1008
|
+
return v * inverseSqrt(dot(wx, wx) * dot(wy, wy));
|
|
1009
|
+
}
|
|
1010
|
+
|
|
1011
|
+
@fragment
|
|
1012
|
+
fn mainFragment(@location(0) uv : vec2<f32>) -> @location(0) vec4<f32> {
|
|
1013
|
+
let raw = textureSample(uTexture, uSampler, uv);
|
|
1014
|
+
var rgb = vec3<f32>(0.0);
|
|
1015
|
+
if (raw.a > 0.0) { rgb = raw.rgb / raw.a; }
|
|
1016
|
+
let L = dot(rgb, vec3<f32>(0.2126, 0.7152, 0.0722));
|
|
1017
|
+
let w = clamp(4.0 * L * (1.0 - L), 0.0, 1.0);
|
|
1018
|
+
let pos = uv * gfu.uInputSize.xy;
|
|
1019
|
+
let k = hash(u32(grainUniforms.uSeed) * 0x9E3779B1u + u32(grainUniforms.uFrame));
|
|
1020
|
+
let n0 = cell(pos, grainUniforms.uSize, k);
|
|
1021
|
+
var n = vec3<f32>(n0);
|
|
1022
|
+
if (grainUniforms.uColor > 0.0) {
|
|
1023
|
+
let nc = vec3<f32>(cell(pos, grainUniforms.uSize, k + 1u), cell(pos, grainUniforms.uSize, k + 2u), cell(pos, grainUniforms.uSize, k + 3u));
|
|
1024
|
+
n = mix(n, nc, grainUniforms.uColor);
|
|
1025
|
+
}
|
|
1026
|
+
rgb = clamp(rgb + n * (grainUniforms.uAmount * w), vec3<f32>(0.0), vec3<f32>(1.0));
|
|
1027
|
+
return vec4<f32>(rgb * raw.a, raw.a);
|
|
1028
|
+
}`;
|
|
1029
|
+
var GRAIN_KEYS = ["amount", "size", "seed", "fps", "color"];
|
|
1030
|
+
var GrainFilter = class extends Filter {
|
|
1031
|
+
_fps;
|
|
1032
|
+
constructor(options = {}) {
|
|
1033
|
+
warnUnknownOptions("grain filter", options, GRAIN_KEYS);
|
|
1034
|
+
const { amount = 0.08, size = 1.5, seed = 0, fps = 24, color = 0 } = options;
|
|
1035
|
+
super({
|
|
1036
|
+
glProgram: GlProgram.from({ vertex: GL_VERTEX, fragment: GL_FRAGMENT2, name: "grain-filter" }),
|
|
1037
|
+
gpuProgram: GpuProgram.from({ vertex: { source: WGSL_SOURCE2, entryPoint: "mainVertex" }, fragment: { source: WGSL_SOURCE2, entryPoint: "mainFragment" } }),
|
|
1038
|
+
resources: {
|
|
1039
|
+
grainUniforms: new UniformGroup({
|
|
1040
|
+
uAmount: { value: amount, type: "f32" },
|
|
1041
|
+
uSize: { value: Math.max(size, 0.25), type: "f32" },
|
|
1042
|
+
uSeed: { value: Math.floor(seed), type: "f32" },
|
|
1043
|
+
uFrame: { value: 0, type: "f32" },
|
|
1044
|
+
uColor: { value: color, type: "f32" }
|
|
1045
|
+
})
|
|
1046
|
+
}
|
|
1047
|
+
});
|
|
1048
|
+
this._fps = fps;
|
|
1049
|
+
}
|
|
1050
|
+
get u() {
|
|
1051
|
+
return this.resources.grainUniforms.uniforms;
|
|
1052
|
+
}
|
|
1053
|
+
get amount() {
|
|
1054
|
+
return this.u.uAmount;
|
|
1055
|
+
}
|
|
1056
|
+
set amount(v) {
|
|
1057
|
+
this.u.uAmount = v;
|
|
1058
|
+
}
|
|
1059
|
+
get size() {
|
|
1060
|
+
return this.u.uSize;
|
|
1061
|
+
}
|
|
1062
|
+
set size(v) {
|
|
1063
|
+
this.u.uSize = Math.max(v, 0.25);
|
|
1064
|
+
}
|
|
1065
|
+
get seed() {
|
|
1066
|
+
return this.u.uSeed;
|
|
1067
|
+
}
|
|
1068
|
+
set seed(v) {
|
|
1069
|
+
this.u.uSeed = Math.floor(v);
|
|
1070
|
+
}
|
|
1071
|
+
get color() {
|
|
1072
|
+
return this.u.uColor;
|
|
1073
|
+
}
|
|
1074
|
+
set color(v) {
|
|
1075
|
+
this.u.uColor = v;
|
|
1076
|
+
}
|
|
1077
|
+
get fps() {
|
|
1078
|
+
return this._fps;
|
|
1079
|
+
}
|
|
1080
|
+
set fps(v) {
|
|
1081
|
+
this._fps = v;
|
|
1082
|
+
}
|
|
1083
|
+
/** The movie calls this with the time (s) of the frame it is about to draw: the grain is new every 1/fps s. */
|
|
1084
|
+
setTime(t) {
|
|
1085
|
+
this.u.uFrame = this._fps > 0 ? Math.floor(t * this._fps + 1e-6) : 0;
|
|
1086
|
+
}
|
|
1087
|
+
};
|
|
1088
|
+
|
|
1089
|
+
// src/filters/named.ts
|
|
767
1090
|
var CORE = { blur: "BlurFilter", noise: "NoiseFilter", alpha: "AlphaFilter" };
|
|
768
|
-
var CORE_TYPES = [...Object.keys(CORE), "colorMatrix"];
|
|
1091
|
+
var CORE_TYPES = [...Object.keys(CORE), "colorMatrix", "grain"];
|
|
769
1092
|
var LIBRARY_TYPES = [
|
|
770
1093
|
"adjustment",
|
|
771
1094
|
"advancedBloom",
|
|
@@ -882,6 +1205,7 @@ function colorGradientParams(params) {
|
|
|
882
1205
|
}
|
|
883
1206
|
function createNamedFilter(type, params) {
|
|
884
1207
|
if (lower(type) === "colormatrix") return colorMatrix(params);
|
|
1208
|
+
if (lower(type) === "grain") return new GrainFilter(params);
|
|
885
1209
|
const core = Object.entries(CORE).find(([k]) => lower(k) === lower(type));
|
|
886
1210
|
if (core) return new PIXI[core[1]](params);
|
|
887
1211
|
if (!isLibraryType(type)) throw unknownType(type);
|
|
@@ -1030,6 +1354,140 @@ function collectPropKeys(spec) {
|
|
|
1030
1354
|
return out;
|
|
1031
1355
|
}
|
|
1032
1356
|
|
|
1357
|
+
// src/core/layerKeys.ts
|
|
1358
|
+
var COMMON = ["type", "name", "parent", "at", "duration", "initial", "keyframes", "filters", "filterArea", "mask", "maskInverted", "blendMode", "threeD", "hideBehindCamera"];
|
|
1359
|
+
var VIDEO = [...COMMON, "asset", "loop", "audio", "volume"];
|
|
1360
|
+
var IMAGE = [...COMMON, "asset", "colorSpace"];
|
|
1361
|
+
var TEXT = [...COMMON, "text", "format", "style", "colorSpace", "fillGradient"];
|
|
1362
|
+
var AUDIO = [...COMMON, "volume", "asset", "loop", "sfx", "music"];
|
|
1363
|
+
var COMPOSITION = [...COMMON, "width", "height", "sequences", "transitions"];
|
|
1364
|
+
var CAMERA = [...COMMON];
|
|
1365
|
+
var NULL = [...COMMON];
|
|
1366
|
+
var SHAPE = [...COMMON, "shape", "fillGradient", "colorSpace", "strokeCap", "strokeJoin"];
|
|
1367
|
+
var TRIM = ["trimStart", "trimEnd", "trimEach"];
|
|
1368
|
+
var RECT = [...SHAPE, ...TRIM, "width", "height", "cornerRadius", "anchorX", "anchorY"];
|
|
1369
|
+
var CIRCLE = [...SHAPE, ...TRIM, "radius", "anchorX", "anchorY"];
|
|
1370
|
+
var ELLIPSE = [...SHAPE, ...TRIM, "radiusX", "radiusY", "anchorX", "anchorY"];
|
|
1371
|
+
var ARC = [...SHAPE, "radius", "innerRadius", "startAngle", "endAngle"];
|
|
1372
|
+
var LINE = [...SHAPE, ...TRIM, "from", "to"];
|
|
1373
|
+
var POLYGON = [...SHAPE, ...TRIM, "points", "open"];
|
|
1374
|
+
var PATH = [...SHAPE, ...TRIM, "d", "morphTo", "morph", "morphPoints"];
|
|
1375
|
+
var SHAPES = { rect: RECT, circle: CIRCLE, ellipse: ELLIPSE, arc: ARC, line: LINE, polygon: POLYGON, path: PATH };
|
|
1376
|
+
var BY_TYPE = { video: VIDEO, image: IMAGE, text: TEXT, audio: AUDIO, composition: COMPOSITION, camera: CAMERA, null: NULL };
|
|
1377
|
+
function kindName(spec) {
|
|
1378
|
+
return spec.type === "shape" && spec.shape ? `${spec.shape} shape` : `${spec.type} layer`;
|
|
1379
|
+
}
|
|
1380
|
+
function layerKeys(spec) {
|
|
1381
|
+
if (spec.type === "shape") return spec.shape && SHAPES[spec.shape] || null;
|
|
1382
|
+
return BY_TYPE[spec.type] ?? null;
|
|
1383
|
+
}
|
|
1384
|
+
function kindsWithKey(key) {
|
|
1385
|
+
const out = [];
|
|
1386
|
+
for (const [shape, keys] of Object.entries(SHAPES)) if (keys.includes(key)) out.push(`${shape} shape`);
|
|
1387
|
+
for (const [type, keys] of Object.entries(BY_TYPE)) if (keys.includes(key)) out.push(`${type} layer`);
|
|
1388
|
+
return out;
|
|
1389
|
+
}
|
|
1390
|
+
var PROP_KEYS = /* @__PURE__ */ new Set([
|
|
1391
|
+
// transform and look (GSAP + PixiPlugin names)
|
|
1392
|
+
"x",
|
|
1393
|
+
"y",
|
|
1394
|
+
"z",
|
|
1395
|
+
"alpha",
|
|
1396
|
+
"rotation",
|
|
1397
|
+
"rotationX",
|
|
1398
|
+
"rotationY",
|
|
1399
|
+
"width",
|
|
1400
|
+
"height",
|
|
1401
|
+
"visible",
|
|
1402
|
+
"autoAlpha",
|
|
1403
|
+
"scale",
|
|
1404
|
+
"scaleX",
|
|
1405
|
+
"scaleY",
|
|
1406
|
+
"anchor",
|
|
1407
|
+
"anchorX",
|
|
1408
|
+
"anchorY",
|
|
1409
|
+
"pivot",
|
|
1410
|
+
"pivotX",
|
|
1411
|
+
"pivotY",
|
|
1412
|
+
"skew",
|
|
1413
|
+
"skewX",
|
|
1414
|
+
"skewY",
|
|
1415
|
+
"position",
|
|
1416
|
+
"positionX",
|
|
1417
|
+
"positionY",
|
|
1418
|
+
"tint",
|
|
1419
|
+
"colorize",
|
|
1420
|
+
"colorizeAmount",
|
|
1421
|
+
"blur",
|
|
1422
|
+
"blurX",
|
|
1423
|
+
"blurY",
|
|
1424
|
+
"blurPadding",
|
|
1425
|
+
// shapes
|
|
1426
|
+
"fillColor",
|
|
1427
|
+
"fillAlpha",
|
|
1428
|
+
"strokeColor",
|
|
1429
|
+
"strokeAlpha",
|
|
1430
|
+
"strokeWidth",
|
|
1431
|
+
"lineColor",
|
|
1432
|
+
"lineAlpha",
|
|
1433
|
+
"cornerRadius",
|
|
1434
|
+
"radius",
|
|
1435
|
+
"radiusX",
|
|
1436
|
+
"radiusY",
|
|
1437
|
+
"innerRadius",
|
|
1438
|
+
"startAngle",
|
|
1439
|
+
"endAngle",
|
|
1440
|
+
"trimStart",
|
|
1441
|
+
"trimEnd",
|
|
1442
|
+
"trimEach",
|
|
1443
|
+
"morph",
|
|
1444
|
+
"fillGradient",
|
|
1445
|
+
"strokeCap",
|
|
1446
|
+
"strokeJoin",
|
|
1447
|
+
// text, audio, video
|
|
1448
|
+
"fill",
|
|
1449
|
+
"value",
|
|
1450
|
+
"visibleChars",
|
|
1451
|
+
"text",
|
|
1452
|
+
"volume",
|
|
1453
|
+
// camera
|
|
1454
|
+
"lookAtX",
|
|
1455
|
+
"lookAtY",
|
|
1456
|
+
"lookAtZ",
|
|
1457
|
+
"fov",
|
|
1458
|
+
"offsetX",
|
|
1459
|
+
"offsetY",
|
|
1460
|
+
"offsetZ",
|
|
1461
|
+
"lookOffsetX",
|
|
1462
|
+
"lookOffsetY",
|
|
1463
|
+
"lookOffsetZ"
|
|
1464
|
+
]);
|
|
1465
|
+
var STYLE_KEYS = [
|
|
1466
|
+
"fontSize",
|
|
1467
|
+
"fontFamily",
|
|
1468
|
+
"fontWeight",
|
|
1469
|
+
"fontStyle",
|
|
1470
|
+
"fontVariant",
|
|
1471
|
+
"fill",
|
|
1472
|
+
"stroke",
|
|
1473
|
+
"dropShadow",
|
|
1474
|
+
"letterSpacing",
|
|
1475
|
+
"lineHeight",
|
|
1476
|
+
"leading",
|
|
1477
|
+
"align",
|
|
1478
|
+
"wordWrap",
|
|
1479
|
+
"wordWrapWidth",
|
|
1480
|
+
"breakWords",
|
|
1481
|
+
"whiteSpace",
|
|
1482
|
+
"padding",
|
|
1483
|
+
"textBaseline",
|
|
1484
|
+
"trim",
|
|
1485
|
+
"lineJoin",
|
|
1486
|
+
"miterLimit",
|
|
1487
|
+
"filters",
|
|
1488
|
+
"tagStyles"
|
|
1489
|
+
];
|
|
1490
|
+
|
|
1033
1491
|
// src/core/lint.ts
|
|
1034
1492
|
var defaultWarn = (m) => console.warn(m);
|
|
1035
1493
|
function describeLayer(spec) {
|
|
@@ -1068,6 +1526,38 @@ function lintText(spec, warn = defaultWarn) {
|
|
|
1068
1526
|
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').`);
|
|
1069
1527
|
}
|
|
1070
1528
|
}
|
|
1529
|
+
function lintKeys(spec, warn = defaultWarn) {
|
|
1530
|
+
const who = describeLayer(spec);
|
|
1531
|
+
const valid = layerKeys(spec);
|
|
1532
|
+
if (valid) {
|
|
1533
|
+
for (const key of Object.keys(spec)) {
|
|
1534
|
+
if (valid.includes(key) || spec[key] === void 0) continue;
|
|
1535
|
+
const guess = suggestName(key, valid.filter((k) => k !== "type"));
|
|
1536
|
+
const owners = kindsWithKey(key);
|
|
1537
|
+
const belongs = owners.length ? ` (it belongs to ${owners.slice(0, 3).join(", ")})` : "";
|
|
1538
|
+
const hint = guess ? ` \u2014 did you mean "${guess}"?${belongs}` : belongs;
|
|
1539
|
+
warn(`pixi-effects: ${who}: "${key}" is not a ${kindName(spec)} key${hint}. Valid keys: ${valid.join(", ")}`);
|
|
1540
|
+
}
|
|
1541
|
+
}
|
|
1542
|
+
const said = /* @__PURE__ */ new Set();
|
|
1543
|
+
const bags = [spec.initial, ...(spec.keyframes ?? []).flatMap((kf) => [kf.set, kf.to, kf.from])];
|
|
1544
|
+
for (const bag of bags) {
|
|
1545
|
+
for (const key of Object.keys(bag ?? {})) {
|
|
1546
|
+
if (bag[key] === void 0) continue;
|
|
1547
|
+
if (PROP_KEYS.has(key) || key.includes(".") || /^gradient/i.test(key) || said.has(key)) continue;
|
|
1548
|
+
said.add(key);
|
|
1549
|
+
const guess = suggestName(key, [...PROP_KEYS]);
|
|
1550
|
+
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`);
|
|
1551
|
+
}
|
|
1552
|
+
}
|
|
1553
|
+
if (spec.type === "text" && spec.style && typeof spec.style === "object") {
|
|
1554
|
+
for (const key of Object.keys(spec.style)) {
|
|
1555
|
+
if (STYLE_KEYS.includes(key) || spec.style[key] === void 0) continue;
|
|
1556
|
+
const guess = suggestName(key, STYLE_KEYS);
|
|
1557
|
+
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(", ")}`);
|
|
1558
|
+
}
|
|
1559
|
+
}
|
|
1560
|
+
}
|
|
1071
1561
|
|
|
1072
1562
|
// src/space/math.ts
|
|
1073
1563
|
var DEG = Math.PI / 180;
|
|
@@ -1393,6 +1883,7 @@ function shortestHueDelta(from, to) {
|
|
|
1393
1883
|
}
|
|
1394
1884
|
|
|
1395
1885
|
// src/expr/colorTween.ts
|
|
1886
|
+
var css = (c) => typeof c === "number" ? "#" + c.toString(16).padStart(6, "0") : c;
|
|
1396
1887
|
function tweenColor(timeline, target, key, fromValue, toValue, duration, ease, at, colorSpace, onUpdate, loop = {}) {
|
|
1397
1888
|
let interp = null;
|
|
1398
1889
|
const proxy = { p: 0 };
|
|
@@ -1407,7 +1898,7 @@ function tweenColor(timeline, target, key, fromValue, toValue, duration, ease, a
|
|
|
1407
1898
|
onStart: () => {
|
|
1408
1899
|
const start = fromValue !== void 0 ? fromValue : target[key];
|
|
1409
1900
|
if (start === void 0) return;
|
|
1410
|
-
interp = colorSpace === "rgb" ? gsap.utils.interpolate(start, toValue) : buildColorInterp(start, toValue, colorSpace);
|
|
1901
|
+
interp = colorSpace === "rgb" ? gsap.utils.interpolate(css(start), css(toValue)) : buildColorInterp(start, toValue, colorSpace);
|
|
1411
1902
|
},
|
|
1412
1903
|
onUpdate: () => {
|
|
1413
1904
|
if (interp) {
|
|
@@ -1451,7 +1942,7 @@ var ImageSequence = class extends Sequence {
|
|
|
1451
1942
|
if (initTint !== void 0) this.target.tint = initTint;
|
|
1452
1943
|
for (const kf of this.spec.keyframes ?? []) {
|
|
1453
1944
|
const at = startTime + resolveAt(kf.at, this.duration);
|
|
1454
|
-
const duration = kf
|
|
1945
|
+
const duration = kfDuration(kf);
|
|
1455
1946
|
const ease = kf.ease ?? "none";
|
|
1456
1947
|
const fromTint = kf.from?.tint;
|
|
1457
1948
|
const toTint = kf.to?.tint;
|
|
@@ -1508,6 +1999,207 @@ function stripKeysInKeyframe(kf, keys) {
|
|
|
1508
1999
|
from: stripKeys(kf.from, keys)
|
|
1509
2000
|
};
|
|
1510
2001
|
}
|
|
2002
|
+
|
|
2003
|
+
// src/sequences/gradient.ts
|
|
2004
|
+
function cssColor(c) {
|
|
2005
|
+
return typeof c === "number" ? "#" + c.toString(16).padStart(6, "0") : c;
|
|
2006
|
+
}
|
|
2007
|
+
function normalizedStops(g) {
|
|
2008
|
+
const stops = g.stops ?? [];
|
|
2009
|
+
if (stops.length < 2) throw new Error('pixi-effects: fillGradient needs at least two colour stops, e.g. stops: [[0, "#000"], [1, "#fff"]]');
|
|
2010
|
+
return stops.map((s) => Array.isArray(s) ? { offset: s[0], color: s[1] } : { offset: s.offset, color: s.color });
|
|
2011
|
+
}
|
|
2012
|
+
function gradientOptions(g) {
|
|
2013
|
+
const colorStops = normalizedStops(g);
|
|
2014
|
+
const a = (g.angle ?? 90) * Math.PI / 180;
|
|
2015
|
+
const dx = Math.cos(a), dy = Math.sin(a);
|
|
2016
|
+
const h = (Math.abs(dx) + Math.abs(dy)) / 2;
|
|
2017
|
+
return {
|
|
2018
|
+
type: "linear",
|
|
2019
|
+
start: { x: 0.5 - dx * h, y: 0.5 - dy * h },
|
|
2020
|
+
end: { x: 0.5 + dx * h, y: 0.5 + dy * h },
|
|
2021
|
+
colorStops,
|
|
2022
|
+
textureSpace: "local"
|
|
2023
|
+
};
|
|
2024
|
+
}
|
|
2025
|
+
function paintRadial(ctx, size, g) {
|
|
2026
|
+
const stops = normalizedStops(g);
|
|
2027
|
+
const [cx, cy] = g.center ?? [0.5, 0.5];
|
|
2028
|
+
const grad = ctx.createRadialGradient(cx * size, cy * size, (g.innerRadius ?? 0) * size, cx * size, cy * size, (g.radius ?? 0.5) * size);
|
|
2029
|
+
for (const s of stops) grad.addColorStop(s.offset, cssColor(s.color));
|
|
2030
|
+
ctx.fillStyle = grad;
|
|
2031
|
+
ctx.fillRect(0, 0, size, size);
|
|
2032
|
+
}
|
|
2033
|
+
|
|
2034
|
+
// src/sequences/gradientAnim.ts
|
|
2035
|
+
var PATCH_KEYS = ["type", "angle", "center", "innerRadius", "radius", "stops"];
|
|
2036
|
+
function gradStateFrom(g) {
|
|
2037
|
+
return {
|
|
2038
|
+
type: g.type ?? "linear",
|
|
2039
|
+
angle: g.angle ?? 90,
|
|
2040
|
+
center: [...g.center ?? [0.5, 0.5]],
|
|
2041
|
+
innerRadius: g.innerRadius ?? 0,
|
|
2042
|
+
radius: g.radius ?? 0.5,
|
|
2043
|
+
stops: (g.stops ?? []).map((s) => Array.isArray(s) ? { offset: s[0], color: cssColor(s[1]) } : { offset: s.offset, color: cssColor(s.color) })
|
|
2044
|
+
};
|
|
2045
|
+
}
|
|
2046
|
+
function mergeGrad(base, patch) {
|
|
2047
|
+
const out = { ...base, center: [...base.center], stops: base.stops.map((s) => ({ ...s })) };
|
|
2048
|
+
if (patch === null || typeof patch !== "object" || Array.isArray(patch)) return out;
|
|
2049
|
+
const p = patch;
|
|
2050
|
+
if (typeof p.angle === "number") out.angle = p.angle;
|
|
2051
|
+
if (Array.isArray(p.center)) out.center = [Number(p.center[0]), Number(p.center[1])];
|
|
2052
|
+
if (typeof p.innerRadius === "number") out.innerRadius = p.innerRadius;
|
|
2053
|
+
if (typeof p.radius === "number") out.radius = p.radius;
|
|
2054
|
+
if (p.stops !== void 0) {
|
|
2055
|
+
const next = gradStateFrom({ stops: p.stops }).stops;
|
|
2056
|
+
if (next.length === base.stops.length) out.stops = next;
|
|
2057
|
+
}
|
|
2058
|
+
return out;
|
|
2059
|
+
}
|
|
2060
|
+
var objectHint = "a keyframe's fillGradient must be an object like { angle: 200, stops: [[0, '#f00'], [1, '#00f']] }";
|
|
2061
|
+
function validateGradientKeyframes(spec, who, warn = (m) => console.warn(m), kind = "shape") {
|
|
2062
|
+
const said = /* @__PURE__ */ new Set();
|
|
2063
|
+
const say = (m) => {
|
|
2064
|
+
if (!said.has(m)) {
|
|
2065
|
+
said.add(m);
|
|
2066
|
+
warn(`pixi-effects: ${who}: ${m}`);
|
|
2067
|
+
}
|
|
2068
|
+
};
|
|
2069
|
+
const startSpec = spec.fillGradient ?? spec.initial?.fillGradient;
|
|
2070
|
+
const start = startSpec && typeof startSpec === "object" && Array.isArray(startSpec.stops) ? gradStateFrom(startSpec) : null;
|
|
2071
|
+
let animated = false;
|
|
2072
|
+
if (kind === "text") {
|
|
2073
|
+
const radial = (g) => !!g && typeof g === "object" && ["type", "center", "innerRadius", "radius"].some((k) => g[k] !== void 0 && !(k === "type" && g.type === "linear"));
|
|
2074
|
+
const asked = radial(startSpec) || (spec.keyframes ?? []).some((kf) => [kf.set, kf.to, kf.from].some((b) => radial(b?.fillGradient)));
|
|
2075
|
+
if (asked) say("a text gradient is linear: type, center, innerRadius and radius are ignored (only angle and stops apply); use a shape for a radial gradient");
|
|
2076
|
+
}
|
|
2077
|
+
for (const kf of spec.keyframes ?? []) {
|
|
2078
|
+
for (const bag of [kf.set, kf.to, kf.from]) {
|
|
2079
|
+
if (!bag) continue;
|
|
2080
|
+
for (const [key, value] of Object.entries(bag)) {
|
|
2081
|
+
if (key === "fillGradient") {
|
|
2082
|
+
animated = true;
|
|
2083
|
+
if (value === null || typeof value !== "object" || Array.isArray(value)) {
|
|
2084
|
+
say(objectHint);
|
|
2085
|
+
continue;
|
|
2086
|
+
}
|
|
2087
|
+
const p = value;
|
|
2088
|
+
for (const k of Object.keys(p)) {
|
|
2089
|
+
if (PATCH_KEYS.includes(k)) continue;
|
|
2090
|
+
const guess = suggestName(k, PATCH_KEYS.filter((x) => x !== "type"));
|
|
2091
|
+
say(`fillGradient.${k} is not a gradient property${guess ? ` \u2014 did you mean "${guess}"?` : ""} (valid: ${PATCH_KEYS.join(", ")}); it is ignored`);
|
|
2092
|
+
}
|
|
2093
|
+
if (p.type !== void 0 && start && p.type !== start.type) say("fillGradient.type cannot change over time (linear <-> radial); it is ignored");
|
|
2094
|
+
if (p.stops !== void 0 && start) {
|
|
2095
|
+
const n = Array.isArray(p.stops) ? p.stops.length : 0;
|
|
2096
|
+
if (n !== start.stops.length) say(`a fillGradient keyframe must give the same number of stops as the gradient has (${start.stops.length}, got ${n}); the stops are left as they were`);
|
|
2097
|
+
}
|
|
2098
|
+
} else if (/^fillGradient\./i.test(key) || /^gradient/i.test(key)) {
|
|
2099
|
+
const tail = key.replace(/^fillGradient\./i, "").replace(/^gradient/i, "");
|
|
2100
|
+
const sub = tail ? tail[0].toLowerCase() + tail.slice(1) : "angle";
|
|
2101
|
+
say(`"${key}" is not an animatable property: write fillGradient: { ${PATCH_KEYS.includes(sub) ? sub : "angle"} } (the whole gradient is one object) in the keyframe's to / from / set`);
|
|
2102
|
+
}
|
|
2103
|
+
}
|
|
2104
|
+
}
|
|
2105
|
+
}
|
|
2106
|
+
if (animated && !start) say("a keyframe animates fillGradient but the layer has none to start from: give it a fillGradient first (top level or in initial)");
|
|
2107
|
+
}
|
|
2108
|
+
function tweenGradient(timeline, holder, fromPatch, toPatch, duration, ease, at, colorSpace, onChange, loop = {}) {
|
|
2109
|
+
let a = null, b = null;
|
|
2110
|
+
let resting = null;
|
|
2111
|
+
let colors = [];
|
|
2112
|
+
const proxy = { p: 0 };
|
|
2113
|
+
timeline.fromTo(proxy, { p: 0 }, {
|
|
2114
|
+
p: 1,
|
|
2115
|
+
duration,
|
|
2116
|
+
ease,
|
|
2117
|
+
...loop,
|
|
2118
|
+
onStart: () => {
|
|
2119
|
+
const live = holder.grad;
|
|
2120
|
+
a = fromPatch !== void 0 ? mergeGrad(live, fromPatch) : live;
|
|
2121
|
+
if (toPatch === void 0) resting ??= live;
|
|
2122
|
+
b = toPatch !== void 0 ? mergeGrad(a, toPatch) : resting;
|
|
2123
|
+
colors = a.stops.map((s, i) => colorSpace === "rgb" ? gsap.utils.interpolate(s.color, b.stops[i].color) : buildColorInterp(s.color, b.stops[i].color, colorSpace));
|
|
2124
|
+
},
|
|
2125
|
+
onUpdate: () => {
|
|
2126
|
+
if (!a || !b) return;
|
|
2127
|
+
const t = proxy.p;
|
|
2128
|
+
const l = (x, y) => x + (y - x) * t;
|
|
2129
|
+
holder.grad = {
|
|
2130
|
+
type: a.type,
|
|
2131
|
+
angle: l(a.angle, b.angle),
|
|
2132
|
+
center: [l(a.center[0], b.center[0]), l(a.center[1], b.center[1])],
|
|
2133
|
+
innerRadius: l(a.innerRadius, b.innerRadius),
|
|
2134
|
+
radius: l(a.radius, b.radius),
|
|
2135
|
+
stops: a.stops.map((s, i) => ({ offset: l(s.offset, b.stops[i].offset), color: colors[i](t) }))
|
|
2136
|
+
};
|
|
2137
|
+
onChange();
|
|
2138
|
+
}
|
|
2139
|
+
}, at);
|
|
2140
|
+
}
|
|
2141
|
+
var PAINT_SIZE = 512;
|
|
2142
|
+
var GradientPainter = class {
|
|
2143
|
+
constructor(size = PAINT_SIZE) {
|
|
2144
|
+
this.size = size;
|
|
2145
|
+
this.canvas.width = size;
|
|
2146
|
+
this.canvas.height = size;
|
|
2147
|
+
this.tex = Texture.from(this.canvas);
|
|
2148
|
+
globalThis.__gradientPainters = (globalThis.__gradientPainters ?? 0) + 1;
|
|
2149
|
+
}
|
|
2150
|
+
size;
|
|
2151
|
+
canvas = document.createElement("canvas");
|
|
2152
|
+
tex;
|
|
2153
|
+
/** Paint `g` and return what `Graphics.fill(...)` takes. */
|
|
2154
|
+
paint(g) {
|
|
2155
|
+
const ctx = this.canvas.getContext("2d"), s = this.size;
|
|
2156
|
+
if (!ctx) return new FillGradient(gradientOptions({ angle: g.angle, stops: g.stops.map((x) => [x.offset, x.color]) }));
|
|
2157
|
+
ctx.clearRect(0, 0, s, s);
|
|
2158
|
+
if (g.type === "radial") {
|
|
2159
|
+
paintRadial(ctx, s, { stops: g.stops.map((x) => [x.offset, x.color]), center: g.center, innerRadius: g.innerRadius, radius: g.radius });
|
|
2160
|
+
} else {
|
|
2161
|
+
const a = g.angle * Math.PI / 180, dx = Math.cos(a), dy = Math.sin(a);
|
|
2162
|
+
const h = (Math.abs(dx) + Math.abs(dy)) / 2;
|
|
2163
|
+
const grad = ctx.createLinearGradient((0.5 - dx * h) * s, (0.5 - dy * h) * s, (0.5 + dx * h) * s, (0.5 + dy * h) * s);
|
|
2164
|
+
for (const st of g.stops) grad.addColorStop(Math.min(1, Math.max(0, st.offset)), st.color);
|
|
2165
|
+
ctx.fillStyle = grad;
|
|
2166
|
+
ctx.fillRect(0, 0, s, s);
|
|
2167
|
+
}
|
|
2168
|
+
this.tex.source.update();
|
|
2169
|
+
return { texture: this.tex, textureSpace: "local" };
|
|
2170
|
+
}
|
|
2171
|
+
/** Give the texture and the canvas back (a layer that is destroyed must not leave them). */
|
|
2172
|
+
destroy() {
|
|
2173
|
+
this.tex.destroy(true);
|
|
2174
|
+
this.canvas.width = this.canvas.height = 0;
|
|
2175
|
+
globalThis.__gradientPainters = Math.max(0, (globalThis.__gradientPainters ?? 1) - 1);
|
|
2176
|
+
}
|
|
2177
|
+
};
|
|
2178
|
+
function bindGradientKeyframes(timeline, holder, keyframes, duration, offset, colorSpace, onChange) {
|
|
2179
|
+
const bag = (b) => b?.fillGradient;
|
|
2180
|
+
for (const kf of keyframes) {
|
|
2181
|
+
const at = offset + resolveAt(kf.at, duration);
|
|
2182
|
+
const setV = bag(kf.set), fromV = bag(kf.from), toV = bag(kf.to);
|
|
2183
|
+
if (setV !== void 0) {
|
|
2184
|
+
revertibleSet(
|
|
2185
|
+
timeline,
|
|
2186
|
+
at,
|
|
2187
|
+
() => ({ state: holder.grad }),
|
|
2188
|
+
(v) => {
|
|
2189
|
+
holder.grad = v.state ?? mergeGrad(holder.grad, v.patch);
|
|
2190
|
+
onChange();
|
|
2191
|
+
},
|
|
2192
|
+
{ patch: setV }
|
|
2193
|
+
);
|
|
2194
|
+
}
|
|
2195
|
+
if (fromV !== void 0 || toV !== void 0) {
|
|
2196
|
+
tweenGradient(timeline, holder, fromV, toV, kfDuration(kf), kf.ease ?? "none", at, colorSpace, onChange, loopVars(kf));
|
|
2197
|
+
}
|
|
2198
|
+
}
|
|
2199
|
+
}
|
|
2200
|
+
var hasGradientKeys = (keyframes) => (keyframes ?? []).some((kf) => [kf.set, kf.to, kf.from].some((b) => b && b.fillGradient !== void 0));
|
|
2201
|
+
|
|
2202
|
+
// src/sequences/Text.ts
|
|
1511
2203
|
var STYLE_OPAQUE_KEYS = [
|
|
1512
2204
|
"fontFamily",
|
|
1513
2205
|
"fill",
|
|
@@ -1542,6 +2234,21 @@ var TextSequence = class extends Sequence {
|
|
|
1542
2234
|
/** `visibleChars` is in play (initial or animated): otherwise the whole text shows. */
|
|
1543
2235
|
_typed = false;
|
|
1544
2236
|
_lastText = "";
|
|
2237
|
+
/** A gradient fill for the text (`fillGradient`, static or animated): rebuilt as a FillGradient on each change (the text is re-rasterised). */
|
|
2238
|
+
_grad = null;
|
|
2239
|
+
_fillGradient = null;
|
|
2240
|
+
_applyGradient() {
|
|
2241
|
+
const g = this._grad.grad;
|
|
2242
|
+
const next = new FillGradient(gradientOptions({ angle: g.angle, stops: g.stops.map((s) => [s.offset, s.color]) }));
|
|
2243
|
+
this.target.style.fill = next;
|
|
2244
|
+
this._fillGradient?.destroy();
|
|
2245
|
+
this._fillGradient = next;
|
|
2246
|
+
}
|
|
2247
|
+
destroy() {
|
|
2248
|
+
super.destroy();
|
|
2249
|
+
this._fillGradient?.destroy();
|
|
2250
|
+
this._fillGradient = null;
|
|
2251
|
+
}
|
|
1545
2252
|
/** A typewriter that has typed nothing yet: the layer is empty on purpose (inspect must not call that "no size"). */
|
|
1546
2253
|
get showsNothingYet() {
|
|
1547
2254
|
return this._typed && this._lastText === "" && this._template !== "";
|
|
@@ -1588,6 +2295,12 @@ var TextSequence = class extends Sequence {
|
|
|
1588
2295
|
this.intrinsicWidth = text.width;
|
|
1589
2296
|
this.intrinsicHeight = text.height;
|
|
1590
2297
|
}
|
|
2298
|
+
validateGradientKeyframes(this.spec, describeLayer(this.spec), void 0, "text");
|
|
2299
|
+
const gradientSpec = this.spec.fillGradient ?? initialProps.fillGradient;
|
|
2300
|
+
if (gradientSpec) {
|
|
2301
|
+
this._grad = { grad: gradStateFrom(gradientSpec) };
|
|
2302
|
+
this._applyGradient();
|
|
2303
|
+
}
|
|
1591
2304
|
const scope = this.scope();
|
|
1592
2305
|
if (initialProps.value !== void 0) this._counters.value = resolveNumber(initialProps.value, scope);
|
|
1593
2306
|
this._typed = initialProps.visibleChars !== void 0 || animates(this.spec.keyframes, "visibleChars");
|
|
@@ -1606,11 +2319,12 @@ var TextSequence = class extends Sequence {
|
|
|
1606
2319
|
bindTimeline(timeline, offset = 0) {
|
|
1607
2320
|
if (!this.target) return;
|
|
1608
2321
|
const colorSpace = this.spec.colorSpace ?? "rgb";
|
|
1609
|
-
const stripped = stripKeys2(this.spec, ["fill", "value", "text", "visibleChars"]);
|
|
2322
|
+
const stripped = stripKeys2(this.spec, ["fill", "value", "text", "visibleChars", "fillGradient"]);
|
|
1610
2323
|
runSuperWithStrippedSpec(this, stripped, timeline, offset);
|
|
1611
2324
|
const keyframes = this.spec.keyframes ?? [];
|
|
1612
2325
|
const origin = offset + this.at;
|
|
1613
2326
|
bindFillKeyframes(timeline, this.target, keyframes, this.duration, origin, colorSpace);
|
|
2327
|
+
if (this._grad) bindGradientKeyframes(timeline, this._grad, keyframes, this.duration, origin, colorSpace, () => this._applyGradient());
|
|
1614
2328
|
const refresh = () => this._refreshText();
|
|
1615
2329
|
bindCounterKeyframes(timeline, this._counters, "value", refresh, keyframes, this.duration, origin, this.scope());
|
|
1616
2330
|
bindCounterKeyframes(timeline, this._counters, "visibleChars", refresh, keyframes, this.duration, origin, this.scope());
|
|
@@ -1660,7 +2374,7 @@ function bindCounterKeyframes(timeline, state, key, refresh, keyframes, parentDu
|
|
|
1660
2374
|
const toV = kf.to?.[key];
|
|
1661
2375
|
if (setV === void 0 && fromV === void 0 && toV === void 0) continue;
|
|
1662
2376
|
const at = origin + resolveAt(kf.at, parentDuration);
|
|
1663
|
-
const duration = kf
|
|
2377
|
+
const duration = kfDuration(kf);
|
|
1664
2378
|
const ease = kf.ease ?? "none";
|
|
1665
2379
|
const loop = loopVars(kf);
|
|
1666
2380
|
if (setV !== void 0) {
|
|
@@ -1706,7 +2420,7 @@ function bindFillKeyframes(timeline, text, keyframes, parentDuration, offset, co
|
|
|
1706
2420
|
};
|
|
1707
2421
|
for (const kf of keyframes) {
|
|
1708
2422
|
const at = offset + resolveAt(kf.at, parentDuration);
|
|
1709
|
-
const duration = kf
|
|
2423
|
+
const duration = kfDuration(kf);
|
|
1710
2424
|
const ease = kf.ease ?? "none";
|
|
1711
2425
|
const setFill = pickFill(kf.set);
|
|
1712
2426
|
const fromFill = pickFill(kf.from);
|
|
@@ -2040,39 +2754,6 @@ var VideoSequence = class extends Sequence {
|
|
|
2040
2754
|
super.destroy();
|
|
2041
2755
|
}
|
|
2042
2756
|
};
|
|
2043
|
-
|
|
2044
|
-
// src/sequences/gradient.ts
|
|
2045
|
-
function cssColor(c) {
|
|
2046
|
-
return typeof c === "number" ? "#" + c.toString(16).padStart(6, "0") : c;
|
|
2047
|
-
}
|
|
2048
|
-
function normalizedStops(g) {
|
|
2049
|
-
const stops = g.stops ?? [];
|
|
2050
|
-
if (stops.length < 2) throw new Error('pixi-effects: fillGradient needs at least two colour stops, e.g. stops: [[0, "#000"], [1, "#fff"]]');
|
|
2051
|
-
return stops.map((s) => Array.isArray(s) ? { offset: s[0], color: s[1] } : { offset: s.offset, color: s.color });
|
|
2052
|
-
}
|
|
2053
|
-
function gradientOptions(g) {
|
|
2054
|
-
const colorStops = normalizedStops(g);
|
|
2055
|
-
const a = (g.angle ?? 90) * Math.PI / 180;
|
|
2056
|
-
const dx = Math.cos(a), dy = Math.sin(a);
|
|
2057
|
-
const h = (Math.abs(dx) + Math.abs(dy)) / 2;
|
|
2058
|
-
return {
|
|
2059
|
-
type: "linear",
|
|
2060
|
-
start: { x: 0.5 - dx * h, y: 0.5 - dy * h },
|
|
2061
|
-
end: { x: 0.5 + dx * h, y: 0.5 + dy * h },
|
|
2062
|
-
colorStops,
|
|
2063
|
-
textureSpace: "local"
|
|
2064
|
-
};
|
|
2065
|
-
}
|
|
2066
|
-
function paintRadial(ctx, size, g) {
|
|
2067
|
-
const stops = normalizedStops(g);
|
|
2068
|
-
const [cx, cy] = g.center ?? [0.5, 0.5];
|
|
2069
|
-
const grad = ctx.createRadialGradient(cx * size, cy * size, (g.innerRadius ?? 0) * size, cx * size, cy * size, (g.radius ?? 0.5) * size);
|
|
2070
|
-
for (const s of stops) grad.addColorStop(s.offset, cssColor(s.color));
|
|
2071
|
-
ctx.fillStyle = grad;
|
|
2072
|
-
ctx.fillRect(0, 0, size, size);
|
|
2073
|
-
}
|
|
2074
|
-
|
|
2075
|
-
// src/sequences/gradientFill.ts
|
|
2076
2757
|
var RADIAL_SIZE = 256;
|
|
2077
2758
|
function makeGradientFill(g) {
|
|
2078
2759
|
if (g.type === "radial") {
|
|
@@ -2264,7 +2945,7 @@ function morphAt(pairs, t) {
|
|
|
2264
2945
|
}
|
|
2265
2946
|
|
|
2266
2947
|
// src/sequences/Shape.ts
|
|
2267
|
-
var
|
|
2948
|
+
var STYLE_KEYS2 = ["fillColor", "fillAlpha", "strokeColor", "strokeAlpha", "strokeWidth"];
|
|
2268
2949
|
var COLOR_KEYS = /* @__PURE__ */ new Set(["fillColor", "strokeColor"]);
|
|
2269
2950
|
var TRIM_KEYS = ["trimStart", "trimEnd"];
|
|
2270
2951
|
var GEOMETRY_KEYS_BY_SHAPE = {
|
|
@@ -2290,7 +2971,7 @@ var ShapeSequence = class extends Sequence {
|
|
|
2290
2971
|
// by `Container.onRender`.
|
|
2291
2972
|
_drawGeometry = () => {
|
|
2292
2973
|
};
|
|
2293
|
-
_liveKeys = new Set(
|
|
2974
|
+
_liveKeys = new Set(STYLE_KEYS2);
|
|
2294
2975
|
async build() {
|
|
2295
2976
|
const graphics = new Graphics({ label: this.spec.name });
|
|
2296
2977
|
graphics.cullable = true;
|
|
@@ -2316,7 +2997,15 @@ var ShapeSequence = class extends Sequence {
|
|
|
2316
2997
|
this._state.trimEnd ??= 1;
|
|
2317
2998
|
}
|
|
2318
2999
|
const gradientSpec = this.spec.fillGradient ?? this.spec.initial?.fillGradient;
|
|
2319
|
-
|
|
3000
|
+
validateGradientKeyframes(this.spec, describeLayer(this.spec));
|
|
3001
|
+
if (gradientSpec) {
|
|
3002
|
+
if (hasGradientKeys(this.spec.keyframes)) {
|
|
3003
|
+
this._grad = { grad: gradStateFrom(gradientSpec) };
|
|
3004
|
+
this._painter = new GradientPainter();
|
|
3005
|
+
this._gradDirty = true;
|
|
3006
|
+
this._liveKeys.add("fillGradient");
|
|
3007
|
+
} else this._state.fillStyle = makeGradientFill(gradientSpec);
|
|
3008
|
+
}
|
|
2320
3009
|
const morph = this._setupMorph();
|
|
2321
3010
|
this._drawGeometry = makeDrawGeometry(this.spec, scope, this._state, morph);
|
|
2322
3011
|
this._outline = makeOutline(this.spec, scope, this._state, morph);
|
|
@@ -2375,11 +3064,23 @@ var ShapeSequence = class extends Sequence {
|
|
|
2375
3064
|
this._state.morph ??= 0;
|
|
2376
3065
|
return { pairs, to: String(top.morphTo) };
|
|
2377
3066
|
}
|
|
3067
|
+
destroy() {
|
|
3068
|
+
super.destroy();
|
|
3069
|
+
this._painter?.destroy();
|
|
3070
|
+
this._painter = null;
|
|
3071
|
+
}
|
|
2378
3072
|
_fresh = false;
|
|
3073
|
+
_grad = null;
|
|
3074
|
+
_painter = null;
|
|
3075
|
+
_gradDirty = false;
|
|
2379
3076
|
_outline = null;
|
|
2380
3077
|
_redraw() {
|
|
2381
3078
|
const graphics = this.target;
|
|
2382
3079
|
const s = this._state;
|
|
3080
|
+
if (this._grad && this._gradDirty) {
|
|
3081
|
+
s.fillStyle = this._painter.paint(this._grad.grad);
|
|
3082
|
+
this._gradDirty = false;
|
|
3083
|
+
}
|
|
2383
3084
|
graphics.clear();
|
|
2384
3085
|
const trimmed = (s.trimStart ?? 0) > 0 || (s.trimEnd ?? 1) < 1;
|
|
2385
3086
|
if (!trimmed || !this._outline || !(s.strokeColor !== void 0 && s.strokeWidth > 0)) {
|
|
@@ -2425,6 +3126,9 @@ var ShapeSequence = class extends Sequence {
|
|
|
2425
3126
|
applyKeyframes(timeline, this.target, keyframes, this.duration, scope, [], startTime);
|
|
2426
3127
|
const colorSpace = this.spec.colorSpace ?? "rgb";
|
|
2427
3128
|
bindLiveKeyframes(timeline, this._state, this._liveKeys, this.spec.keyframes ?? [], this.duration, scope, startTime, colorSpace);
|
|
3129
|
+
if (this._grad) bindGradientKeyframes(timeline, this._grad, this.spec.keyframes ?? [], this.duration, startTime, colorSpace, () => {
|
|
3130
|
+
this._gradDirty = true;
|
|
3131
|
+
});
|
|
2428
3132
|
this.absoluteStart = startTime;
|
|
2429
3133
|
const endTime = startTime + this.duration;
|
|
2430
3134
|
this.target.renderable = startTime <= 0;
|
|
@@ -2461,7 +3165,7 @@ function seedStrokeStyle(state, spec, initial, who) {
|
|
|
2461
3165
|
}
|
|
2462
3166
|
}
|
|
2463
3167
|
function seedStyle(state, initial, scope) {
|
|
2464
|
-
for (const k of
|
|
3168
|
+
for (const k of STYLE_KEYS2) {
|
|
2465
3169
|
const v = initial[k];
|
|
2466
3170
|
if (v === void 0) continue;
|
|
2467
3171
|
state[k] = COLOR_KEYS.has(k) ? v : numOrZero(v, scope);
|
|
@@ -2684,13 +3388,14 @@ function makeOutline(spec, scope, s, morph) {
|
|
|
2684
3388
|
function bindLiveKeyframes(timeline, state, liveKeys, keyframes, parentDuration, scope, offset, colorSpace) {
|
|
2685
3389
|
for (const kf of keyframes) {
|
|
2686
3390
|
const at = offset + resolveAt(kf.at, parentDuration);
|
|
2687
|
-
const duration = kf
|
|
3391
|
+
const duration = kfDuration(kf);
|
|
2688
3392
|
const ease = kf.ease ?? "none";
|
|
2689
3393
|
const loop = loopVars(kf);
|
|
2690
3394
|
if (kf.set) {
|
|
2691
3395
|
const live = pickLive(kf.set, liveKeys);
|
|
2692
3396
|
if (live) {
|
|
2693
3397
|
for (const [k, v] of Object.entries(live)) {
|
|
3398
|
+
if (k === "fillGradient") continue;
|
|
2694
3399
|
const resolved = resolveLiveValue(k, v, scope);
|
|
2695
3400
|
const live2 = state;
|
|
2696
3401
|
revertibleSet(timeline, at, () => live2[k], (v2) => {
|
|
@@ -2706,6 +3411,7 @@ function bindLiveKeyframes(timeline, state, liveKeys, keyframes, parentDuration,
|
|
|
2706
3411
|
...toLive ? Object.keys(toLive) : []
|
|
2707
3412
|
]);
|
|
2708
3413
|
for (const k of allKeys) {
|
|
3414
|
+
if (k === "fillGradient") continue;
|
|
2709
3415
|
const key = k;
|
|
2710
3416
|
const fromRaw = fromLive?.[key];
|
|
2711
3417
|
const toRaw = toLive?.[key];
|
|
@@ -2754,7 +3460,7 @@ function numOrZero(v, scope) {
|
|
|
2754
3460
|
var _CompositionSequence = null;
|
|
2755
3461
|
async function getCompositionSequence() {
|
|
2756
3462
|
if (!_CompositionSequence) {
|
|
2757
|
-
_CompositionSequence = (await import('./Composition-
|
|
3463
|
+
_CompositionSequence = (await import('./Composition-QBKEEJBV.js')).CompositionSequence;
|
|
2758
3464
|
}
|
|
2759
3465
|
return _CompositionSequence;
|
|
2760
3466
|
}
|
|
@@ -2792,6 +3498,6 @@ async function buildSequenceTree(specs, parent, root) {
|
|
|
2792
3498
|
return out;
|
|
2793
3499
|
}
|
|
2794
3500
|
|
|
2795
|
-
export { CameraSequence, DEFAULT_FOV, DEG, NEAR, NullSequence, Sequence, buildScope, buildSequenceTree, cameraBasis, checkEase, collectPropKeys, describeLayer, ensureFilterLibrary, evaluateExpr, flattenSvgPath, homeCamera, homeDistance, lintText, lintTiming, noise, projectLayer, rand, random, registerSequenceType, resolveAt, summarizeWarnings };
|
|
2796
|
-
//# sourceMappingURL=chunk-
|
|
2797
|
-
//# sourceMappingURL=chunk-
|
|
3501
|
+
export { CameraSequence, DEFAULT_FOV, DEG, NEAR, NullSequence, Sequence, buildScope, buildSequenceTree, cameraBasis, checkEase, collectPropKeys, describeLayer, ensureFilterLibrary, evaluateExpr, flattenSvgPath, homeCamera, homeDistance, lintKeys, lintText, lintTiming, noise, projectLayer, rand, random, registerSequenceType, resolveAt, summarizeWarnings };
|
|
3502
|
+
//# sourceMappingURL=chunk-YRXTKOV5.js.map
|
|
3503
|
+
//# sourceMappingURL=chunk-YRXTKOV5.js.map
|