pixi-effects 0.26.2 → 0.27.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 +28 -0
- package/README.md +8 -10
- package/ai/CHAT.md +1 -1
- package/ai/chat-template.html +4 -6
- package/ai/tools/render.mjs +16 -11
- package/dist/{Base-CpdDs4HT.d.ts → Base-CVezIEdo.d.ts} +2 -4
- package/dist/{Base-TbBhHPrG.d.cts → Base-DzC3i919.d.cts} +2 -4
- package/dist/Composition-4TYDRRRY.js +7 -0
- package/dist/{Composition-H4QA24MV.js.map → Composition-4TYDRRRY.js.map} +1 -1
- package/dist/Composition-QCOWQSDB.cjs +16 -0
- package/dist/{Composition-HM4YT5L7.cjs.map → Composition-QCOWQSDB.cjs.map} +1 -1
- package/dist/Controller.d.cts +2 -3
- package/dist/Controller.d.ts +2 -3
- package/dist/{Movie-i05Oh9mJ.d.cts → Movie-CQ0Nz62a.d.cts} +12 -6
- package/dist/{Movie-DVeDTdnc.d.ts → Movie-M9dKm9dI.d.ts} +12 -6
- package/dist/Presenter.d.cts +2 -3
- package/dist/Presenter.d.ts +2 -3
- package/dist/{blendModes-YV43K6E7.cjs → blendModes-HDOP6R7T.cjs} +5 -5
- package/dist/{blendModes-YV43K6E7.cjs.map → blendModes-HDOP6R7T.cjs.map} +1 -1
- package/dist/{blendModes-G3NOAU3T.js → blendModes-PAVTW3BO.js} +4 -4
- package/dist/{blendModes-G3NOAU3T.js.map → blendModes-PAVTW3BO.js.map} +1 -1
- package/dist/{chunk-TLYTYBWX.js → chunk-45QKLD6M.js} +9 -11
- package/dist/chunk-45QKLD6M.js.map +1 -0
- package/dist/{chunk-GBUM7X2S.js → chunk-CKTS6G6I.js} +7 -11
- package/dist/chunk-CKTS6G6I.js.map +1 -0
- package/dist/{chunk-555URQHQ.cjs → chunk-NDR2VQFV.cjs} +91 -95
- package/dist/chunk-NDR2VQFV.cjs.map +1 -0
- package/dist/{chunk-3DLYAPK7.cjs → chunk-P4GY3Z4G.cjs} +5 -5
- package/dist/{chunk-3DLYAPK7.cjs.map → chunk-P4GY3Z4G.cjs.map} +1 -1
- package/dist/{chunk-WPXDRSGN.cjs → chunk-RQMI7EJT.cjs} +1170 -280
- package/dist/chunk-RQMI7EJT.cjs.map +1 -0
- package/dist/{chunk-X3HB4DSR.js → chunk-TGJACVLD.js} +1150 -263
- package/dist/chunk-TGJACVLD.js.map +1 -0
- package/dist/{chunk-AXZUKNXF.js → chunk-TYWFKCPY.js} +4 -4
- package/dist/{chunk-AXZUKNXF.js.map → chunk-TYWFKCPY.js.map} +1 -1
- package/dist/{chunk-ECA2WNRX.cjs → chunk-ZMAD3KJU.cjs} +9 -11
- package/dist/chunk-ZMAD3KJU.cjs.map +1 -0
- package/dist/index.cjs +189 -116
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +16 -14
- package/dist/index.d.ts +16 -14
- package/dist/index.js +136 -45
- package/dist/index.js.map +1 -1
- package/dist/loader.css +1 -1
- package/dist/three.cjs +6 -6
- package/dist/three.d.cts +2 -3
- package/dist/three.d.ts +2 -3
- package/dist/three.js +2 -2
- package/dist/{types-DSGwN5w1.d.ts → types-DUVefWiB.d.cts} +128 -3
- package/dist/{types-DSGwN5w1.d.cts → types-DUVefWiB.d.ts} +128 -3
- package/docs/api.md +16 -6
- package/docs/dsl.md +14 -14
- package/llms-full.txt +38 -28
- package/llms.txt +1 -1
- package/package.json +3 -4
- package/skills/pixi-effects/SKILL.md +1 -1
- package/skills/pixi-effects/reference/cheatsheet.md +3 -3
- package/skills/pixi-effects/reference/pitfalls.md +3 -3
- package/skills/pixi-effects/reference/recipes.md +1 -1
- package/skills/pixi-effects/template.html +6 -8
- package/dist/Composition-H4QA24MV.js +0 -7
- package/dist/Composition-HM4YT5L7.cjs +0 -16
- package/dist/chunk-555URQHQ.cjs.map +0 -1
- package/dist/chunk-ECA2WNRX.cjs.map +0 -1
- package/dist/chunk-GBUM7X2S.js.map +0 -1
- package/dist/chunk-TLYTYBWX.js.map +0 -1
- package/dist/chunk-WPXDRSGN.cjs.map +0 -1
- package/dist/chunk-X3HB4DSR.js.map +0 -1
|
@@ -1,43 +1,9 @@
|
|
|
1
|
-
import { collectPropKeys, describeLayer } from './chunk-
|
|
1
|
+
import { collectPropKeys, describeLayer } from './chunk-45QKLD6M.js';
|
|
2
2
|
import { suggestName, warnUnknownOptions } from './chunk-BXOCEZ4U.js';
|
|
3
3
|
import * as PIXI from 'pixi.js';
|
|
4
4
|
import { Rectangle, Container, Color, GraphicsPath, Sprite, Texture, Graphics, Assets, FillGradient, Text, Filter, GlProgram, defaultFilterVert, GpuProgram, UniformGroup } from 'pixi.js';
|
|
5
|
-
import { gsap } from 'gsap';
|
|
6
5
|
|
|
7
|
-
// src/
|
|
8
|
-
function mix(h) {
|
|
9
|
-
h = Math.imul(h ^ h >>> 16, 2246822507);
|
|
10
|
-
h = Math.imul(h ^ h >>> 13, 3266489909);
|
|
11
|
-
return (h ^ h >>> 16) >>> 0;
|
|
12
|
-
}
|
|
13
|
-
function fold(n) {
|
|
14
|
-
if (!Number.isFinite(n)) return 0;
|
|
15
|
-
const i = Math.floor(n);
|
|
16
|
-
const f = n - i;
|
|
17
|
-
return (i | 0) ^ Math.imul(Math.floor(f * 1048576), 2654435761);
|
|
18
|
-
}
|
|
19
|
-
function rand(seed) {
|
|
20
|
-
return mix(fold(seed) + 2654435769) / 4294967296;
|
|
21
|
-
}
|
|
22
|
-
function random(seed) {
|
|
23
|
-
let a = fold(seed) + 1831565813 | 0;
|
|
24
|
-
return () => {
|
|
25
|
-
a = a + 1831565813 | 0;
|
|
26
|
-
let t = Math.imul(a ^ a >>> 15, 1 | a);
|
|
27
|
-
t = t + Math.imul(t ^ t >>> 7, 61 | t) ^ t;
|
|
28
|
-
return ((t ^ t >>> 14) >>> 0) / 4294967296;
|
|
29
|
-
};
|
|
30
|
-
}
|
|
31
|
-
function noise(x, seed = 0) {
|
|
32
|
-
if (!Number.isFinite(x)) return 0;
|
|
33
|
-
const i = Math.floor(x);
|
|
34
|
-
const f = x - i;
|
|
35
|
-
const s = fold(seed) * 668265261;
|
|
36
|
-
const a = mix((i | 0) + s) / 2147483648 - 1;
|
|
37
|
-
const b = mix((i + 1 | 0) + s) / 2147483648 - 1;
|
|
38
|
-
const u = f * f * f * (f * (f * 6 - 15) + 10);
|
|
39
|
-
return a + (b - a) * u;
|
|
40
|
-
}
|
|
6
|
+
// src/core/spring.ts
|
|
41
7
|
var SETTLE_TOL = 5e-3;
|
|
42
8
|
var DEFAULTS = { mass: 1, stiffness: 100, damping: 10 };
|
|
43
9
|
function springResponse(t, { mass: m, stiffness: k, damping: c }) {
|
|
@@ -119,19 +85,6 @@ function parseSpring(name) {
|
|
|
119
85
|
const [mass, stiffness, damping] = (m[2] ?? "").split(",").map((s) => s.trim()).filter(Boolean).map(Number);
|
|
120
86
|
return complete({ mass, stiffness, damping });
|
|
121
87
|
}
|
|
122
|
-
var registered = false;
|
|
123
|
-
function registerSpringEases() {
|
|
124
|
-
if (registered) return;
|
|
125
|
-
registered = true;
|
|
126
|
-
const base = springEase();
|
|
127
|
-
const ease = (p) => base(p);
|
|
128
|
-
ease.config = (mass, stiffness, damping) => {
|
|
129
|
-
const bad = [mass, stiffness, damping].some((v) => v !== void 0 && !(typeof v === "number" && v > 0 && Number.isFinite(v)));
|
|
130
|
-
return springEase(bad ? {} : { mass, stiffness, damping });
|
|
131
|
-
};
|
|
132
|
-
gsap.registerEase("spring", ease);
|
|
133
|
-
for (const [name, p] of Object.entries(SPRING_PRESETS)) gsap.registerEase(`spring.${name}`, springEase(p));
|
|
134
|
-
}
|
|
135
88
|
var autoWarned = /* @__PURE__ */ new Set();
|
|
136
89
|
function kfDuration(kf) {
|
|
137
90
|
if (kf.duration !== "auto") return kf.duration ?? 0;
|
|
@@ -144,7 +97,837 @@ function kfDuration(kf) {
|
|
|
144
97
|
}
|
|
145
98
|
return 0.5;
|
|
146
99
|
}
|
|
147
|
-
|
|
100
|
+
|
|
101
|
+
// src/core/cubicBezier.ts
|
|
102
|
+
function cubicBezierEase(x1, y1, x2, y2) {
|
|
103
|
+
const cx = 3 * x1, bx = 3 * (x2 - x1) - cx, ax = 1 - cx - bx;
|
|
104
|
+
const cy = 3 * y1, by = 3 * (y2 - y1) - cy, ay = 1 - cy - by;
|
|
105
|
+
const X = (t) => ((ax * t + bx) * t + cx) * t;
|
|
106
|
+
const Y = (t) => ((ay * t + by) * t + cy) * t;
|
|
107
|
+
const dX = (t) => (3 * ax * t + 2 * bx) * t + cx;
|
|
108
|
+
return (p) => {
|
|
109
|
+
if (p <= 0) return 0;
|
|
110
|
+
if (p >= 1) return 1;
|
|
111
|
+
let t = p;
|
|
112
|
+
for (let i = 0; i < 8; i++) {
|
|
113
|
+
const err = X(t) - p;
|
|
114
|
+
if (Math.abs(err) < 1e-9) return Y(t);
|
|
115
|
+
const d = dX(t);
|
|
116
|
+
if (Math.abs(d) < 1e-6) break;
|
|
117
|
+
t -= err / d;
|
|
118
|
+
}
|
|
119
|
+
let lo = 0, hi = 1;
|
|
120
|
+
t = p;
|
|
121
|
+
for (let i = 0; i < 60; i++) {
|
|
122
|
+
const x = X(t);
|
|
123
|
+
if (Math.abs(x - p) < 1e-10) break;
|
|
124
|
+
if (x < p) lo = t;
|
|
125
|
+
else hi = t;
|
|
126
|
+
t = (lo + hi) / 2;
|
|
127
|
+
}
|
|
128
|
+
return Y(t);
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
var NUM = String.raw`\s*(-?(?:\d+\.?\d*|\.\d+)(?:e[-+]?\d+)?)\s*`;
|
|
132
|
+
var RE = new RegExp(`^\\s*cubic-bezier\\(${NUM},${NUM},${NUM},${NUM}\\)\\s*$`, "i");
|
|
133
|
+
function parseCubicBezier(name) {
|
|
134
|
+
const m = RE.exec(name);
|
|
135
|
+
return m && !cubicBezierProblem(name) ? [Number(m[1]), Number(m[2]), Number(m[3]), Number(m[4])] : null;
|
|
136
|
+
}
|
|
137
|
+
function cubicBezierProblem(name) {
|
|
138
|
+
const m = RE.exec(name);
|
|
139
|
+
if (!m) return 'expected "cubic-bezier(x1, y1, x2, y2)" with four numbers, like CSS';
|
|
140
|
+
const x1 = Number(m[1]), x2 = Number(m[3]);
|
|
141
|
+
if (x1 < 0 || x1 > 1 || x2 < 0 || x2 > 1) return "x1 and x2 must be between 0 and 1 (y1 and y2 may overshoot)";
|
|
142
|
+
return null;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
// src/core/pure/ease.ts
|
|
146
|
+
var PI = Math.PI;
|
|
147
|
+
var power = (strength) => ({
|
|
148
|
+
in: (p) => Math.pow(p, strength),
|
|
149
|
+
out: (p) => 1 - Math.pow(1 - p, strength),
|
|
150
|
+
inOut: (p) => p < 0.5 ? 0.5 * Math.pow(2 * p, strength) : 1 - 0.5 * Math.pow(2 * (1 - p), strength)
|
|
151
|
+
});
|
|
152
|
+
var fromOut = (out) => ({
|
|
153
|
+
in: (p) => 1 - out(1 - p),
|
|
154
|
+
out,
|
|
155
|
+
inOut: (p) => p < 0.5 ? 0.5 * (1 - out(1 - 2 * p)) : 0.5 + 0.5 * out(2 * p - 1)
|
|
156
|
+
});
|
|
157
|
+
var mirrored = (easeIn) => ({
|
|
158
|
+
in: easeIn,
|
|
159
|
+
out: (p) => 1 - easeIn(1 - p),
|
|
160
|
+
inOut: (p) => p < 0.5 ? easeIn(p * 2) / 2 : 1 - easeIn((1 - p) * 2) / 2
|
|
161
|
+
});
|
|
162
|
+
var sine = mirrored((p) => p === 1 ? 1 : -Math.cos(p * PI / 2) + 1);
|
|
163
|
+
var circ = mirrored((p) => -(Math.sqrt(1 - p * p) - 1));
|
|
164
|
+
var expoIn = (p) => Math.pow(2, 10 * (p - 1)) * p + p * p * p * p * p * p * (1 - p);
|
|
165
|
+
var expo = {
|
|
166
|
+
in: expoIn,
|
|
167
|
+
out: (p) => 1 - expoIn(1 - p),
|
|
168
|
+
inOut: (p) => p < 0.5 ? expoIn(p * 2) / 2 : 1 - expoIn((1 - p) * 2) / 2
|
|
169
|
+
};
|
|
170
|
+
var bounceOut = (p) => {
|
|
171
|
+
if (p < 1 / 2.75) return 7.5625 * p * p;
|
|
172
|
+
if (p < 2 / 2.75) {
|
|
173
|
+
p -= 1.5 / 2.75;
|
|
174
|
+
return 7.5625 * p * p + 0.75;
|
|
175
|
+
}
|
|
176
|
+
if (p < 2.5 / 2.75) {
|
|
177
|
+
p -= 2.25 / 2.75;
|
|
178
|
+
return 7.5625 * p * p + 0.9375;
|
|
179
|
+
}
|
|
180
|
+
p -= 2.625 / 2.75;
|
|
181
|
+
return 7.5625 * p * p + 0.984375;
|
|
182
|
+
};
|
|
183
|
+
var bounce = fromOut(bounceOut);
|
|
184
|
+
function back(s = 1.70158) {
|
|
185
|
+
const out = (p) => p ? (p -= 1, p * p * ((s + 1) * p + s) + 1) : 0;
|
|
186
|
+
return fromOut(out);
|
|
187
|
+
}
|
|
188
|
+
function elastic(amplitude, period) {
|
|
189
|
+
const make = (per0) => {
|
|
190
|
+
const amp = amplitude ?? 1;
|
|
191
|
+
const a = amp >= 1 ? amp : 1;
|
|
192
|
+
const per = per0 / (amp < 1 ? amp : 1);
|
|
193
|
+
const s = per / (2 * PI) * Math.asin(1 / a);
|
|
194
|
+
const k = 2 * PI / per;
|
|
195
|
+
return fromOut((p) => p === 0 ? 0 : p === 1 ? 1 : a * Math.pow(2, -10 * p) * Math.sin((p - s) * k) + 1);
|
|
196
|
+
};
|
|
197
|
+
const usual = make(period ?? 0.3);
|
|
198
|
+
return { in: usual.in, out: usual.out, inOut: period === void 0 ? make(0.45).inOut : usual.inOut };
|
|
199
|
+
}
|
|
200
|
+
function steps(n) {
|
|
201
|
+
const count = Math.max(1, Math.floor(n) || 1);
|
|
202
|
+
return (p) => p <= 0 ? 0 : p >= 1 ? 1 : Math.min(1, Math.floor(p * (count + 1)) / count);
|
|
203
|
+
}
|
|
204
|
+
var FAMILY = {
|
|
205
|
+
power1: () => power(2),
|
|
206
|
+
power2: () => power(3),
|
|
207
|
+
power3: () => power(4),
|
|
208
|
+
power4: () => power(5),
|
|
209
|
+
quad: () => power(2),
|
|
210
|
+
cubic: () => power(3),
|
|
211
|
+
quart: () => power(4),
|
|
212
|
+
quint: () => power(5),
|
|
213
|
+
strong: () => power(5),
|
|
214
|
+
sine: () => sine,
|
|
215
|
+
circ: () => circ,
|
|
216
|
+
expo: () => expo,
|
|
217
|
+
bounce: () => bounce,
|
|
218
|
+
back: (a) => back(a[0]),
|
|
219
|
+
elastic: (a) => elastic(a[0], a[1])
|
|
220
|
+
};
|
|
221
|
+
var LINEAR = (p) => p;
|
|
222
|
+
var DEFAULT = power(2).out;
|
|
223
|
+
var cache = /* @__PURE__ */ new Map();
|
|
224
|
+
function lookup(name) {
|
|
225
|
+
let hit = cache.get(name);
|
|
226
|
+
if (hit === void 0) {
|
|
227
|
+
hit = parse(name.trim());
|
|
228
|
+
cache.set(name, hit);
|
|
229
|
+
}
|
|
230
|
+
return hit;
|
|
231
|
+
}
|
|
232
|
+
function pureEase(name) {
|
|
233
|
+
return (typeof name === "string" ? lookup(name) : null) ?? DEFAULT;
|
|
234
|
+
}
|
|
235
|
+
function isEaseName(name) {
|
|
236
|
+
return typeof name === "string" && lookup(name) !== null;
|
|
237
|
+
}
|
|
238
|
+
function parse(raw) {
|
|
239
|
+
const s = raw.toLowerCase();
|
|
240
|
+
if (s === "none" || s === "linear" || s === "linear.easenone") return LINEAR;
|
|
241
|
+
if (/^spring/.test(s)) {
|
|
242
|
+
const sp = parseSpring(raw);
|
|
243
|
+
return sp ? springEase(sp) : null;
|
|
244
|
+
}
|
|
245
|
+
if (/^cubic-bezier/.test(s)) {
|
|
246
|
+
const c = parseCubicBezier(raw);
|
|
247
|
+
return c ? cubicBezierEase(...c) : LINEAR;
|
|
248
|
+
}
|
|
249
|
+
const st = /^steps\(\s*([^)]*)\)$/.exec(s);
|
|
250
|
+
if (st) return steps(Number(st[1]));
|
|
251
|
+
if (/^[a-z][a-z0-9]*$/.test(raw) && FAMILY[raw]) return FAMILY[raw]([]).out;
|
|
252
|
+
const m = /^([a-z0-9]+)\.(?:ease)?(in|out|inout)(?:\(([^)]*)\))?$/.exec(s);
|
|
253
|
+
if (!m) return null;
|
|
254
|
+
const make = FAMILY[m[1]];
|
|
255
|
+
if (!make) return null;
|
|
256
|
+
const args = (m[3] ?? "").split(",").map((x) => x.trim()).filter(Boolean).map(Number).filter((n) => Number.isFinite(n));
|
|
257
|
+
const trio = make(args);
|
|
258
|
+
return m[2] === "in" ? trio.in : m[2] === "out" ? trio.out : trio.inOut;
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
// src/core/pure/colorLerp.ts
|
|
262
|
+
function parseCssColor(s) {
|
|
263
|
+
const v = s.trim();
|
|
264
|
+
let m = /^#([0-9a-f]{3,4})$/i.exec(v);
|
|
265
|
+
if (m) {
|
|
266
|
+
const h = m[1];
|
|
267
|
+
const d = (i) => parseInt(h[i] + h[i], 16);
|
|
268
|
+
return [d(0), d(1), d(2), h.length === 4 ? d(3) / 255 : 1];
|
|
269
|
+
}
|
|
270
|
+
m = /^#([0-9a-f]{6})([0-9a-f]{2})?$/i.exec(v);
|
|
271
|
+
if (m) {
|
|
272
|
+
const n = parseInt(m[1], 16);
|
|
273
|
+
return [n >> 16 & 255, n >> 8 & 255, n & 255, m[2] ? parseInt(m[2], 16) / 255 : 1];
|
|
274
|
+
}
|
|
275
|
+
m = /^rgba?\(\s*(-?[\d.]+)\s*,\s*(-?[\d.]+)\s*,\s*(-?[\d.]+)\s*(?:,\s*(-?[\d.]+)\s*)?\)$/i.exec(v);
|
|
276
|
+
if (m) return [Number(m[1]), Number(m[2]), Number(m[3]), m[4] === void 0 ? 1 : Number(m[4])];
|
|
277
|
+
return null;
|
|
278
|
+
}
|
|
279
|
+
function rgbInterp(a, b, fallback = () => null) {
|
|
280
|
+
const ca = parseCssColor(a) ?? fallback(a), cb = parseCssColor(b) ?? fallback(b);
|
|
281
|
+
if (!ca || !cb) return (p) => p >= 1 ? b : a;
|
|
282
|
+
return (p) => {
|
|
283
|
+
if (p === 0) return a;
|
|
284
|
+
if (p === 1) return b;
|
|
285
|
+
const ch = (i) => Math.round(ca[i] + (cb[i] - ca[i]) * p);
|
|
286
|
+
const al = Math.round((ca[3] + (cb[3] - ca[3]) * p) * 1e4) / 1e4;
|
|
287
|
+
return `rgba(${ch(0)},${ch(1)},${ch(2)},${al})`;
|
|
288
|
+
};
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
// src/core/pure/props.ts
|
|
292
|
+
var DEG = Math.PI / 180;
|
|
293
|
+
var num = (obj, key, id, unit = 1) => ({
|
|
294
|
+
id,
|
|
295
|
+
kind: "num",
|
|
296
|
+
unit,
|
|
297
|
+
round: 1e6,
|
|
298
|
+
get: () => Number(obj()?.[key]),
|
|
299
|
+
set: (v) => {
|
|
300
|
+
const o = obj();
|
|
301
|
+
if (o) o[key] = v;
|
|
302
|
+
}
|
|
303
|
+
});
|
|
304
|
+
function xy(target, base, which, unit = 1) {
|
|
305
|
+
const o = () => target[base];
|
|
306
|
+
const ax = num(o, "x", `${base}.x`, unit), ay = num(o, "y", `${base}.y`, unit);
|
|
307
|
+
return which === "x" ? [ax] : which === "y" ? [ay] : [ax, ay];
|
|
308
|
+
}
|
|
309
|
+
var VEC = [
|
|
310
|
+
["scale", "scale", 1],
|
|
311
|
+
["anchor", "anchor", 1],
|
|
312
|
+
["pivot", "pivot", 1],
|
|
313
|
+
["skew", "skew", DEG],
|
|
314
|
+
["position", "position", 1],
|
|
315
|
+
["tilePosition", "tilePosition", 1],
|
|
316
|
+
["tileScale", "tileScale", 1]
|
|
317
|
+
];
|
|
318
|
+
var PIXI_INERT = /* @__PURE__ */ new Set(["fillColor", "fillAlpha"]);
|
|
319
|
+
function pixiAccessors(target, key) {
|
|
320
|
+
for (const [name, base, unit] of VEC) {
|
|
321
|
+
if (key === name) return xy(target, base, "both", unit);
|
|
322
|
+
if (key === `${name}X`) return xy(target, base, "x", unit);
|
|
323
|
+
if (key === `${name}Y`) return xy(target, base, "y", unit);
|
|
324
|
+
}
|
|
325
|
+
switch (key) {
|
|
326
|
+
case "rotation":
|
|
327
|
+
return [{ id: "rotation", kind: "num", unit: DEG, round: 1e5, exactEnd: true, get: () => Number(target.rotation), set: (v) => {
|
|
328
|
+
target.rotation = v;
|
|
329
|
+
} }];
|
|
330
|
+
case "tint":
|
|
331
|
+
return [{ id: "tint", kind: "color", unit: 1, round: 1, get: () => Number(target.tint), set: (v) => {
|
|
332
|
+
target.tint = v;
|
|
333
|
+
} }];
|
|
334
|
+
case "autoAlpha":
|
|
335
|
+
return [
|
|
336
|
+
{ id: "alpha", kind: "num", unit: 1, round: 1e6, get: () => Number(target.alpha), set: (v) => {
|
|
337
|
+
target.alpha = v;
|
|
338
|
+
} },
|
|
339
|
+
// `visible` follows the autoAlpha tweens only, not a plain `alpha` tween on the same layer: a channel of its own
|
|
340
|
+
{ id: "visible#auto", kind: "num", unit: 1, round: 1e6, always: true, get: () => Number(target.alpha), set: (v) => {
|
|
341
|
+
target.visible = v !== 0;
|
|
342
|
+
} }
|
|
343
|
+
];
|
|
344
|
+
default:
|
|
345
|
+
return null;
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
function rawAccessor(target, key) {
|
|
349
|
+
return { id: key, kind: "raw", unit: 1, round: 1, get: () => target[key], set: (v) => {
|
|
350
|
+
target[key] = v;
|
|
351
|
+
} };
|
|
352
|
+
}
|
|
353
|
+
function cssAccessor(target, key) {
|
|
354
|
+
return { id: key, kind: "css", unit: 1, round: 1, get: () => target[key], set: (v) => {
|
|
355
|
+
target[key] = v;
|
|
356
|
+
} };
|
|
357
|
+
}
|
|
358
|
+
function plainAccessor(target, key) {
|
|
359
|
+
return { id: key, kind: "num", unit: 1, round: 1e6, get: () => Number(target[key]), set: (v) => {
|
|
360
|
+
target[key] = v;
|
|
361
|
+
} };
|
|
362
|
+
}
|
|
363
|
+
function parseColor(v) {
|
|
364
|
+
if (typeof v === "number") return v;
|
|
365
|
+
if (typeof v !== "string") return null;
|
|
366
|
+
const s = v.trim();
|
|
367
|
+
let m = /^#([0-9a-f]{3})$/i.exec(s);
|
|
368
|
+
if (m) {
|
|
369
|
+
const h = m[1];
|
|
370
|
+
return parseInt(h[0] + h[0] + h[1] + h[1] + h[2] + h[2], 16);
|
|
371
|
+
}
|
|
372
|
+
m = /^#([0-9a-f]{6})(?:[0-9a-f]{2})?$/i.exec(s);
|
|
373
|
+
if (m) return parseInt(m[1], 16);
|
|
374
|
+
m = /^rgba?\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)/i.exec(s);
|
|
375
|
+
if (m) return Number(m[1]) << 16 | Number(m[2]) << 8 | Number(m[3]);
|
|
376
|
+
return null;
|
|
377
|
+
}
|
|
378
|
+
function lerpColor(from, to, p) {
|
|
379
|
+
const r = lerpByte(from >> 16 & 255, to >> 16 & 255, p);
|
|
380
|
+
const g = lerpByte(from >> 8 & 255, to >> 8 & 255, p);
|
|
381
|
+
const b = lerpByte(from & 255, to & 255, p);
|
|
382
|
+
return r << 16 | g << 8 | b;
|
|
383
|
+
}
|
|
384
|
+
function lerpByte(a, b, p) {
|
|
385
|
+
return Math.trunc(a + (b - a) * p);
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
// src/core/pure/PureTimeline.ts
|
|
389
|
+
var quantize = (x) => Math.round(x * 1e7) / 1e7 || 0;
|
|
390
|
+
var TINY = 1e-8;
|
|
391
|
+
var spacer = (duration) => ({ spacer: true, duration });
|
|
392
|
+
var parseRel = (v) => {
|
|
393
|
+
if (typeof v === "number") return { rel: false, n: v };
|
|
394
|
+
if (typeof v === "string") {
|
|
395
|
+
const m = /^([+-])=\s*(-?\d*\.?\d+(?:e[+-]?\d+)?)$/i.exec(v.trim());
|
|
396
|
+
if (m) return { rel: true, n: (m[1] === "-" ? -1 : 1) * parseFloat(m[2]) };
|
|
397
|
+
const n = parseFloat(v);
|
|
398
|
+
if (Number.isFinite(n) && String(n) === v.trim()) return { rel: false, n };
|
|
399
|
+
}
|
|
400
|
+
return null;
|
|
401
|
+
};
|
|
402
|
+
var RESERVED = /* @__PURE__ */ new Set(["duration", "ease", "repeat", "yoyo", "repeatDelay", "onUpdate", "delay"]);
|
|
403
|
+
var CALLBACKS = ["onStart", "onComplete", "onRepeat", "onReverseComplete"];
|
|
404
|
+
var saidCallbacks = false;
|
|
405
|
+
var PureTimeline = class _PureTimeline {
|
|
406
|
+
defaultEase;
|
|
407
|
+
channels = /* @__PURE__ */ new Map();
|
|
408
|
+
channelList = [];
|
|
409
|
+
children = [];
|
|
410
|
+
spans = 0;
|
|
411
|
+
now = 0;
|
|
412
|
+
order = 0;
|
|
413
|
+
killed = false;
|
|
414
|
+
prepared = false;
|
|
415
|
+
constructor(opts = {}) {
|
|
416
|
+
this.defaultEase = opts.defaults?.ease ?? "none";
|
|
417
|
+
}
|
|
418
|
+
// --- building ------------------------------------------------------------------------------------------
|
|
419
|
+
/** Adds a child timeline (played with its local time) or a spacer that lengthens this one. */
|
|
420
|
+
add(child, at) {
|
|
421
|
+
const start = at ?? this.spans;
|
|
422
|
+
if ("spacer" in child) {
|
|
423
|
+
this.spans = Math.max(this.spans, start + child.duration);
|
|
424
|
+
} else if (!(child instanceof _PureTimeline)) {
|
|
425
|
+
this.spans = Math.max(this.spans, start + child.duration());
|
|
426
|
+
} else {
|
|
427
|
+
this.children.push({ child, start: quantize(start), order: this.order++, exclusive: false, last: NaN });
|
|
428
|
+
this.prepared = false;
|
|
429
|
+
this.spans = Math.max(this.spans, start + child.duration());
|
|
430
|
+
}
|
|
431
|
+
return this;
|
|
432
|
+
}
|
|
433
|
+
set(target, vars, at) {
|
|
434
|
+
return this.build(target, null, { ...vars, duration: 0 }, at, "set");
|
|
435
|
+
}
|
|
436
|
+
to(target, vars, at) {
|
|
437
|
+
return this.build(target, null, vars, at, "to");
|
|
438
|
+
}
|
|
439
|
+
from(target, vars, at) {
|
|
440
|
+
return this.build(target, null, vars, at, "from");
|
|
441
|
+
}
|
|
442
|
+
fromTo(target, fromVars, toVars, at) {
|
|
443
|
+
return this.build(target, fromVars, toVars, at, "fromTo");
|
|
444
|
+
}
|
|
445
|
+
build(target, fromVars, vars, at, kind) {
|
|
446
|
+
const t = target;
|
|
447
|
+
const start = quantize((at ?? this.spans) + (Number(vars.delay) || 0));
|
|
448
|
+
const dur = quantize(Math.max(0, vars.duration ?? 0));
|
|
449
|
+
for (const cb of CALLBACKS) if (cb in vars) {
|
|
450
|
+
if (!saidCallbacks) {
|
|
451
|
+
saidCallbacks = true;
|
|
452
|
+
console.warn(`pixi-effects: the timeline does not run ${cb}: what a tween does must be a value of the time (use onUpdate for a redraw); it is ignored`);
|
|
453
|
+
}
|
|
454
|
+
}
|
|
455
|
+
const repeat = Math.max(0, Math.floor(vars.repeat ?? 0));
|
|
456
|
+
const yoyo = !!vars.yoyo;
|
|
457
|
+
const repeatDelay = Math.max(0, vars.repeatDelay ?? 0);
|
|
458
|
+
const easeName = vars.ease ?? this.defaultEase;
|
|
459
|
+
const ease = typeof easeName === "function" ? easeName : pureEase(easeName);
|
|
460
|
+
const given = (v) => {
|
|
461
|
+
const out = /* @__PURE__ */ new Map();
|
|
462
|
+
for (const key of Object.keys(v)) {
|
|
463
|
+
if (RESERVED.has(key) || key === "pixi" || CALLBACKS.includes(key)) continue;
|
|
464
|
+
const value = v[key];
|
|
465
|
+
const acc = parseRel(value) ? plainAccessor(t, key) : typeof value === "string" && parseCssColor(value) ? cssAccessor(t, key) : rawAccessor(t, key);
|
|
466
|
+
out.set(acc.id, { acc, value });
|
|
467
|
+
}
|
|
468
|
+
if (v.pixi) for (const key of Object.keys(v.pixi)) {
|
|
469
|
+
const accs = pixiAccessors(t, key);
|
|
470
|
+
if (!accs) {
|
|
471
|
+
if (!PIXI_INERT.has(key)) console.warn(`pixi-effects: the timeline has no "${key}" shorthand yet; it is ignored`);
|
|
472
|
+
continue;
|
|
473
|
+
}
|
|
474
|
+
for (const acc of accs) out.set(acc.id, { acc, value: v.pixi[key] });
|
|
475
|
+
}
|
|
476
|
+
return out;
|
|
477
|
+
};
|
|
478
|
+
const ends = given(vars);
|
|
479
|
+
const starts = fromVars ? given(fromVars) : /* @__PURE__ */ new Map();
|
|
480
|
+
const ids = kind === "fromTo" ? [.../* @__PURE__ */ new Set([...starts.keys(), ...ends.keys()])] : [...ends.keys()];
|
|
481
|
+
let lastAlpha;
|
|
482
|
+
for (const id of ids) {
|
|
483
|
+
const e = ends.get(id), f = starts.get(id);
|
|
484
|
+
const acc = (e ?? f).acc;
|
|
485
|
+
const ch = this.channel(t, acc);
|
|
486
|
+
const cur = acc.get();
|
|
487
|
+
const color = acc.kind === "color";
|
|
488
|
+
const endSpec = e ? read(e.value, acc) : null;
|
|
489
|
+
if (e && !endSpec && acc.kind === "color") console.warn(`pixi-effects: the timeline cannot read the colour ${JSON.stringify(e.value)} (use #rgb, #rrggbb, rgb(...) or a number); this tween is skipped`);
|
|
490
|
+
const fromSpec = f ? read(f.value, acc) : null;
|
|
491
|
+
let from = null, to, toRel = false;
|
|
492
|
+
if (kind === "from") {
|
|
493
|
+
const g = endSpec ?? { rel: false, n: cur };
|
|
494
|
+
from = g.rel ? cur + g.n : g.n;
|
|
495
|
+
to = cur;
|
|
496
|
+
acc.set(from);
|
|
497
|
+
} else if (kind === "fromTo") {
|
|
498
|
+
if (fromSpec) from = fromSpec.rel ? cur + fromSpec.n : fromSpec.n;
|
|
499
|
+
if (endSpec) {
|
|
500
|
+
to = endSpec.n;
|
|
501
|
+
toRel = endSpec.rel;
|
|
502
|
+
} else to = cur;
|
|
503
|
+
if (from !== null) acc.set(from);
|
|
504
|
+
} else {
|
|
505
|
+
if (!endSpec) continue;
|
|
506
|
+
to = endSpec.n;
|
|
507
|
+
toRel = endSpec.rel;
|
|
508
|
+
}
|
|
509
|
+
if (color && toRel) toRel = false;
|
|
510
|
+
const seg = {
|
|
511
|
+
channel: ch,
|
|
512
|
+
kind,
|
|
513
|
+
createCur: cur,
|
|
514
|
+
start,
|
|
515
|
+
dur,
|
|
516
|
+
ease,
|
|
517
|
+
repeat,
|
|
518
|
+
yoyo,
|
|
519
|
+
repeatDelay,
|
|
520
|
+
from,
|
|
521
|
+
to,
|
|
522
|
+
toRel,
|
|
523
|
+
from0: from,
|
|
524
|
+
to0: to,
|
|
525
|
+
toRel0: toRel,
|
|
526
|
+
onUpdate: vars.onUpdate,
|
|
527
|
+
order: this.order++
|
|
528
|
+
};
|
|
529
|
+
if (id === "visible#auto") seg.partner = lastAlpha;
|
|
530
|
+
else if (id === "alpha") lastAlpha = seg;
|
|
531
|
+
ch.segs.push(seg);
|
|
532
|
+
ch.dirty = true;
|
|
533
|
+
this.prepared = false;
|
|
534
|
+
}
|
|
535
|
+
const total = dur * (repeat + 1) + repeatDelay * repeat;
|
|
536
|
+
this.spans = Math.max(this.spans, start + total);
|
|
537
|
+
return this;
|
|
538
|
+
}
|
|
539
|
+
channel(target, acc) {
|
|
540
|
+
let m = this.channels.get(target);
|
|
541
|
+
if (!m) this.channels.set(target, m = /* @__PURE__ */ new Map());
|
|
542
|
+
let ch = m.get(acc.id);
|
|
543
|
+
if (!ch) {
|
|
544
|
+
ch = { target, acc, pre: NaN, last: NaN, segs: [], dirty: false };
|
|
545
|
+
m.set(acc.id, ch);
|
|
546
|
+
this.channelList.push(ch);
|
|
547
|
+
}
|
|
548
|
+
return ch;
|
|
549
|
+
}
|
|
550
|
+
/**
|
|
551
|
+
* A property moved by a function of the caller (a colour in OKLab, a gradient): `to` and `from` say how to get the two ends from
|
|
552
|
+
* the value before the segment, `make` the interpolator between them. The value is only written while the segment is the last
|
|
553
|
+
* one that has started, so nothing is read or kept between two frames.
|
|
554
|
+
*/
|
|
555
|
+
tweenValue(spec) {
|
|
556
|
+
const acc = { id: spec.id, kind: "fn", unit: 1, round: 1, get: spec.get, set: spec.set, make: spec.make };
|
|
557
|
+
const ch = this.channel(spec.holder, acc);
|
|
558
|
+
const start = quantize(spec.at);
|
|
559
|
+
const dur = quantize(Math.max(0, spec.duration));
|
|
560
|
+
const repeat = Math.max(0, Math.floor(spec.repeat ?? 0));
|
|
561
|
+
const repeatDelay = Math.max(0, spec.repeatDelay ?? 0);
|
|
562
|
+
const ease = typeof spec.ease === "function" ? spec.ease : pureEase(spec.ease);
|
|
563
|
+
ch.segs.push({
|
|
564
|
+
channel: ch,
|
|
565
|
+
kind: "to",
|
|
566
|
+
createCur: null,
|
|
567
|
+
start,
|
|
568
|
+
dur,
|
|
569
|
+
ease,
|
|
570
|
+
repeat,
|
|
571
|
+
yoyo: !!spec.yoyo,
|
|
572
|
+
repeatDelay,
|
|
573
|
+
from: null,
|
|
574
|
+
to: null,
|
|
575
|
+
toRel: false,
|
|
576
|
+
from0: null,
|
|
577
|
+
to0: null,
|
|
578
|
+
toRel0: false,
|
|
579
|
+
order: this.order++,
|
|
580
|
+
fnFrom: spec.from,
|
|
581
|
+
fnTo: spec.to,
|
|
582
|
+
fnMake: spec.make,
|
|
583
|
+
write: spec.set
|
|
584
|
+
});
|
|
585
|
+
ch.dirty = true;
|
|
586
|
+
this.prepared = false;
|
|
587
|
+
this.spans = Math.max(this.spans, start + dur * (repeat + 1) + repeatDelay * repeat);
|
|
588
|
+
return this;
|
|
589
|
+
}
|
|
590
|
+
/**
|
|
591
|
+
* A write that is undone when time goes back before it: the property is `value` from `at` on, and what it was before otherwise.
|
|
592
|
+
* `holder` and `id` name the property, so a set and the tweens of the same property are one channel; `write` is the way the caller
|
|
593
|
+
* writes it (it may do more than assign: redraw), and runs again whenever this set is what the property shows.
|
|
594
|
+
*/
|
|
595
|
+
setValue(holder, id, at, read2, write2, value) {
|
|
596
|
+
const acc = { id, kind: typeof value === "number" ? "num" : "raw", unit: 1, round: 1e6, get: read2, set: write2 };
|
|
597
|
+
const ch = this.channel(holder, acc);
|
|
598
|
+
ch.segs.push({
|
|
599
|
+
channel: ch,
|
|
600
|
+
kind: "set",
|
|
601
|
+
createCur: null,
|
|
602
|
+
start: quantize(at),
|
|
603
|
+
dur: 0,
|
|
604
|
+
ease: pureEase("none"),
|
|
605
|
+
repeat: 0,
|
|
606
|
+
yoyo: false,
|
|
607
|
+
repeatDelay: 0,
|
|
608
|
+
from: null,
|
|
609
|
+
to: value,
|
|
610
|
+
toRel: false,
|
|
611
|
+
from0: null,
|
|
612
|
+
to0: value,
|
|
613
|
+
toRel0: false,
|
|
614
|
+
order: this.order++,
|
|
615
|
+
step: true,
|
|
616
|
+
write: write2,
|
|
617
|
+
onUpdate: () => write2(read2())
|
|
618
|
+
});
|
|
619
|
+
ch.dirty = true;
|
|
620
|
+
this.prepared = false;
|
|
621
|
+
this.spans = Math.max(this.spans, quantize(at));
|
|
622
|
+
return this;
|
|
623
|
+
}
|
|
624
|
+
// --- reading -------------------------------------------------------------------------------------------
|
|
625
|
+
/** What the timeline will write, for tools and tests: every segment of this timeline and of the ones under it, starts in this timeline's time. */
|
|
626
|
+
segments(offset = 0) {
|
|
627
|
+
const out = [];
|
|
628
|
+
for (const ch of this.channelList) {
|
|
629
|
+
for (const s of ch.segs) {
|
|
630
|
+
out.push({ target: ch.target, id: ch.acc.id, start: s.start + offset, duration: s.dur, repeat: s.repeat, yoyo: s.yoyo, repeatDelay: s.repeatDelay, kind: s.step ? "set" : s.kind });
|
|
631
|
+
}
|
|
632
|
+
}
|
|
633
|
+
for (const c of this.children) out.push(...c.child.segments(offset + c.start));
|
|
634
|
+
return out;
|
|
635
|
+
}
|
|
636
|
+
/** How many timelines are directly under this one. */
|
|
637
|
+
timelines() {
|
|
638
|
+
return this.children.length;
|
|
639
|
+
}
|
|
640
|
+
duration() {
|
|
641
|
+
return this.spans;
|
|
642
|
+
}
|
|
643
|
+
time(value) {
|
|
644
|
+
if (value === void 0) return this.now;
|
|
645
|
+
if (this.killed) return this;
|
|
646
|
+
this.now = value;
|
|
647
|
+
if (!this.prepared) {
|
|
648
|
+
this.prepareDeep();
|
|
649
|
+
const counts = /* @__PURE__ */ new Map();
|
|
650
|
+
this.countChannels(counts);
|
|
651
|
+
this.markExclusive(counts);
|
|
652
|
+
}
|
|
653
|
+
this.evaluate(quantize(value));
|
|
654
|
+
return this;
|
|
655
|
+
}
|
|
656
|
+
/** GSAP's name for `time(t)`. */
|
|
657
|
+
seek(t) {
|
|
658
|
+
return this.time(t);
|
|
659
|
+
}
|
|
660
|
+
progress(p) {
|
|
661
|
+
if (p === void 0) return this.spans > 0 ? this.now / this.spans : 0;
|
|
662
|
+
return this.time(p * this.spans);
|
|
663
|
+
}
|
|
664
|
+
kill() {
|
|
665
|
+
this.killed = true;
|
|
666
|
+
this.channels.clear();
|
|
667
|
+
this.channelList.length = 0;
|
|
668
|
+
this.children.length = 0;
|
|
669
|
+
}
|
|
670
|
+
// --- evaluation ----------------------------------------------------------------------------------------
|
|
671
|
+
/**
|
|
672
|
+
* What GSAP ended up with once it had been played to the end and back (what Movie used to do at build), as rules that depend
|
|
673
|
+
* on the segments of a property only:
|
|
674
|
+
* - a `from` / `fromTo` shows its start from the moment it is built, so a `to` that comes first starts at the start of the
|
|
675
|
+
* `from` built last, else at the property's own value;
|
|
676
|
+
* - a `to` (and a `set`) starts where the segment before it ended;
|
|
677
|
+
* - a `from` ends where the segment before it ended, or, with none before, where the property was when it was built;
|
|
678
|
+
* - before the first segment the property shows that segment's start.
|
|
679
|
+
*/
|
|
680
|
+
prepare(ch) {
|
|
681
|
+
if (!ch.dirty) return;
|
|
682
|
+
ch.segs.sort((a, b) => a.start - b.start || a.order - b.order);
|
|
683
|
+
ch.dirty = false;
|
|
684
|
+
let latest = null;
|
|
685
|
+
for (const s of ch.segs) if ((s.kind === "from" || s.kind === "fromTo") && s.from0 !== null && (!latest || s.order > latest.order)) latest = s;
|
|
686
|
+
ch.base0 ??= { v: ch.acc.get() };
|
|
687
|
+
let cur = latest ? latest.from0 : ch.base0.v;
|
|
688
|
+
const base = cur;
|
|
689
|
+
let first = true;
|
|
690
|
+
for (const s of ch.segs) {
|
|
691
|
+
const before = cur;
|
|
692
|
+
s.from = s.from0;
|
|
693
|
+
s.to = s.to0;
|
|
694
|
+
s.toRel = s.toRel0;
|
|
695
|
+
if (s.fnTo) {
|
|
696
|
+
s.from = s.fnFrom ? s.fnFrom(cur) : cur;
|
|
697
|
+
s.to = s.fnTo(s.from, before, base);
|
|
698
|
+
s.interp = void 0;
|
|
699
|
+
} else {
|
|
700
|
+
if (s.partner) {
|
|
701
|
+
s.from = s.partner.from;
|
|
702
|
+
s.to = s.partner.to;
|
|
703
|
+
}
|
|
704
|
+
if (s.from === null) s.from = cur;
|
|
705
|
+
if (s.kind === "from") s.to = first ? s.createCur : cur;
|
|
706
|
+
if (s.toRel) {
|
|
707
|
+
s.to = s.from + s.to;
|
|
708
|
+
s.toRel = false;
|
|
709
|
+
}
|
|
710
|
+
}
|
|
711
|
+
if (first) ch.pre = s.fnTo ? before : s.from;
|
|
712
|
+
cur = endValue(s);
|
|
713
|
+
first = false;
|
|
714
|
+
}
|
|
715
|
+
}
|
|
716
|
+
/** Every channel of this timeline and of its children reads the property it starts from before any of them writes. */
|
|
717
|
+
prepareDeep() {
|
|
718
|
+
if (this.prepared) return;
|
|
719
|
+
this.prepared = true;
|
|
720
|
+
for (const ch of this.channelList) this.prepare(ch);
|
|
721
|
+
this.children.sort((a, b) => a.start - b.start || a.order - b.order);
|
|
722
|
+
for (const c of this.children) {
|
|
723
|
+
c.last = NaN;
|
|
724
|
+
c.child.prepareDeep();
|
|
725
|
+
}
|
|
726
|
+
}
|
|
727
|
+
/** How many channels write each (target, property) in this timeline and everything under it. */
|
|
728
|
+
countChannels(into) {
|
|
729
|
+
for (const ch of this.channelList) {
|
|
730
|
+
let m = into.get(ch.target);
|
|
731
|
+
if (!m) into.set(ch.target, m = /* @__PURE__ */ new Map());
|
|
732
|
+
m.set(ch.acc.id, (m.get(ch.acc.id) ?? 0) + 1);
|
|
733
|
+
}
|
|
734
|
+
for (const c of this.children) c.child.countChannels(into);
|
|
735
|
+
}
|
|
736
|
+
isExclusive(counts) {
|
|
737
|
+
for (const ch of this.channelList) if ((counts.get(ch.target)?.get(ch.acc.id) ?? 0) > 1) return false;
|
|
738
|
+
return this.children.every((c) => c.child.isExclusive(counts));
|
|
739
|
+
}
|
|
740
|
+
markExclusive(counts) {
|
|
741
|
+
for (const c of this.children) {
|
|
742
|
+
c.exclusive = c.child.isExclusive(counts);
|
|
743
|
+
c.child.markExclusive(counts);
|
|
744
|
+
}
|
|
745
|
+
}
|
|
746
|
+
evaluate(t) {
|
|
747
|
+
this.prepareDeep();
|
|
748
|
+
for (const ch of this.channelList) {
|
|
749
|
+
const segs = ch.segs;
|
|
750
|
+
let lo = 0, hi = segs.length;
|
|
751
|
+
while (lo < hi) {
|
|
752
|
+
const mid = lo + hi >> 1;
|
|
753
|
+
if (segs[mid].start <= t + TINY) lo = mid + 1;
|
|
754
|
+
else hi = mid;
|
|
755
|
+
}
|
|
756
|
+
let k = lo - 1;
|
|
757
|
+
while (k >= 0 && segs[k].repeat > 0 && t - segs[k].start <= TINY) k--;
|
|
758
|
+
const seg = k >= 0 ? segs[k] : null;
|
|
759
|
+
if (!seg) {
|
|
760
|
+
const pre = settle(ch.acc, ch.pre);
|
|
761
|
+
write(ch, segs[0], pre);
|
|
762
|
+
const head = segs[0];
|
|
763
|
+
if (pre !== ch.last) {
|
|
764
|
+
ch.last = pre;
|
|
765
|
+
head?.onUpdate?.();
|
|
766
|
+
}
|
|
767
|
+
continue;
|
|
768
|
+
}
|
|
769
|
+
const v = mix(seg, ratioAt(seg, t), over);
|
|
770
|
+
write(ch, seg, v);
|
|
771
|
+
if (v !== ch.last) {
|
|
772
|
+
ch.last = v;
|
|
773
|
+
seg.onUpdate?.();
|
|
774
|
+
}
|
|
775
|
+
}
|
|
776
|
+
for (const c of this.children) {
|
|
777
|
+
const local = Math.min(Math.max(t - c.start, 0), c.child.duration());
|
|
778
|
+
if (c.exclusive && local === c.last) continue;
|
|
779
|
+
c.last = local;
|
|
780
|
+
c.child.now = local;
|
|
781
|
+
c.child.evaluate(quantize(local));
|
|
782
|
+
}
|
|
783
|
+
}
|
|
784
|
+
};
|
|
785
|
+
function write(ch, seg, v) {
|
|
786
|
+
if (!ch.acc.always && ch.acc.get() === v) return;
|
|
787
|
+
(seg?.write ?? ch.acc.set)(v);
|
|
788
|
+
}
|
|
789
|
+
function endValue(s) {
|
|
790
|
+
if (s.dur === 0 && s.repeat === 0) return s.to;
|
|
791
|
+
return s.yoyo && s.repeat % 2 === 1 ? s.from : s.to;
|
|
792
|
+
}
|
|
793
|
+
function read(value, acc) {
|
|
794
|
+
if (acc.kind === "raw" || acc.kind === "css") return { rel: false, n: value };
|
|
795
|
+
if (acc.kind === "color") {
|
|
796
|
+
const c = parseColor(value);
|
|
797
|
+
return c === null ? null : { rel: false, n: c };
|
|
798
|
+
}
|
|
799
|
+
const r = parseRel(value);
|
|
800
|
+
return r ? { rel: r.rel, n: r.n * acc.unit } : null;
|
|
801
|
+
}
|
|
802
|
+
function settle(acc, v) {
|
|
803
|
+
return acc.kind !== "num" ? v : Math.round(v * acc.round) / acc.round;
|
|
804
|
+
}
|
|
805
|
+
var over = false;
|
|
806
|
+
function mix(s, r, ended) {
|
|
807
|
+
const acc = s.channel.acc;
|
|
808
|
+
if (s.step) return s.to;
|
|
809
|
+
if (s.fnMake) {
|
|
810
|
+
const interp = s.interp ??= s.fnMake(s.from, s.to);
|
|
811
|
+
return interp(Math.round(r * 1e6) / 1e6);
|
|
812
|
+
}
|
|
813
|
+
if (acc.kind === "raw") return s.to;
|
|
814
|
+
if (acc.kind === "css") return (s.interp ??= rgbInterp(String(s.from), String(s.to)))(r);
|
|
815
|
+
if (acc.kind === "color") return ended ? endValue(s) : lerpColor(s.from, s.to, r);
|
|
816
|
+
if ((ended || r === 1) && acc.exactEnd) return endValue(s);
|
|
817
|
+
const k = acc.round;
|
|
818
|
+
return Math.round((s.from + (s.to - s.from) * r) * k) / k;
|
|
819
|
+
}
|
|
820
|
+
function ratioAt(s, t) {
|
|
821
|
+
const lt = t - s.start;
|
|
822
|
+
over = true;
|
|
823
|
+
if (s.dur === 0) return 1;
|
|
824
|
+
const total = s.dur * (s.repeat + 1) + s.repeatDelay * s.repeat;
|
|
825
|
+
if (quantize(lt) >= quantize(total) - TINY) return endRatio(s);
|
|
826
|
+
over = false;
|
|
827
|
+
let i = 0;
|
|
828
|
+
let within = lt;
|
|
829
|
+
if (s.repeat > 0) {
|
|
830
|
+
const period = s.dur + s.repeatDelay;
|
|
831
|
+
const q = quantize(lt);
|
|
832
|
+
i = Math.min(s.repeat, Math.max(0, Math.floor(lt / period)));
|
|
833
|
+
while (i > 0 && q <= quantize(i * period)) i--;
|
|
834
|
+
while (i < s.repeat && q > quantize((i + 1) * period)) i++;
|
|
835
|
+
within = quantize(lt - i * period);
|
|
836
|
+
}
|
|
837
|
+
let p = within >= s.dur ? 1 : within <= 0 ? 0 : within / s.dur;
|
|
838
|
+
if (s.yoyo && i % 2 === 1) p = 1 - p;
|
|
839
|
+
return s.ease(p);
|
|
840
|
+
}
|
|
841
|
+
function endRatio(s) {
|
|
842
|
+
return s.yoyo && s.repeat % 2 === 1 ? 0 : 1;
|
|
843
|
+
}
|
|
844
|
+
|
|
845
|
+
// src/core/timelineEngine.ts
|
|
846
|
+
function createTimeline(opts = {}) {
|
|
847
|
+
return new PureTimeline({ paused: opts.paused, defaults: { ease: opts.defaults?.ease ?? "power1.out" } });
|
|
848
|
+
}
|
|
849
|
+
function lengthen(timeline, duration) {
|
|
850
|
+
timeline.add(spacer(duration));
|
|
851
|
+
}
|
|
852
|
+
function parseEase(name) {
|
|
853
|
+
return pureEase(name);
|
|
854
|
+
}
|
|
855
|
+
function setNow(target, vars) {
|
|
856
|
+
const t = target;
|
|
857
|
+
for (const key of Object.keys(vars)) {
|
|
858
|
+
if (key === "pixi") {
|
|
859
|
+
for (const k of Object.keys(vars.pixi)) {
|
|
860
|
+
const accs = pixiAccessors(t, k);
|
|
861
|
+
if (!accs) {
|
|
862
|
+
if (!PIXI_INERT.has(k)) console.warn(`pixi-effects: "${k}" is not a property a keyframe or initial can set; it is ignored`);
|
|
863
|
+
continue;
|
|
864
|
+
}
|
|
865
|
+
const raw = vars.pixi[k];
|
|
866
|
+
for (const acc of accs) {
|
|
867
|
+
const n = acc.kind === "color" ? colorNumber(raw) : Number(raw) * acc.unit;
|
|
868
|
+
if (!Number.isNaN(n)) acc.set(n);
|
|
869
|
+
}
|
|
870
|
+
}
|
|
871
|
+
} else {
|
|
872
|
+
const v = vars[key];
|
|
873
|
+
plainAccessor(t, key).set(typeof v === "number" ? Math.round(v * 1e6) / 1e6 : v);
|
|
874
|
+
}
|
|
875
|
+
}
|
|
876
|
+
}
|
|
877
|
+
function colorNumber(v) {
|
|
878
|
+
const c = parseColor(v);
|
|
879
|
+
if (c === null) {
|
|
880
|
+
console.warn(`pixi-effects: cannot read the colour ${JSON.stringify(v)} (use #rgb, #rrggbb, rgb(...) or a number); it is left as it was`);
|
|
881
|
+
return NaN;
|
|
882
|
+
}
|
|
883
|
+
return c;
|
|
884
|
+
}
|
|
885
|
+
function viaPixi(s) {
|
|
886
|
+
try {
|
|
887
|
+
const [r, g, b, a] = new Color(s).toArray();
|
|
888
|
+
return [Math.round(r * 255), Math.round(g * 255), Math.round(b * 255), a];
|
|
889
|
+
} catch {
|
|
890
|
+
return null;
|
|
891
|
+
}
|
|
892
|
+
}
|
|
893
|
+
function interpolateColors(a, b) {
|
|
894
|
+
return rgbInterp(a, b, viaPixi);
|
|
895
|
+
}
|
|
896
|
+
|
|
897
|
+
// src/expr/random.ts
|
|
898
|
+
function mix2(h) {
|
|
899
|
+
h = Math.imul(h ^ h >>> 16, 2246822507);
|
|
900
|
+
h = Math.imul(h ^ h >>> 13, 3266489909);
|
|
901
|
+
return (h ^ h >>> 16) >>> 0;
|
|
902
|
+
}
|
|
903
|
+
function fold(n) {
|
|
904
|
+
if (!Number.isFinite(n)) return 0;
|
|
905
|
+
const i = Math.floor(n);
|
|
906
|
+
const f = n - i;
|
|
907
|
+
return (i | 0) ^ Math.imul(Math.floor(f * 1048576), 2654435761);
|
|
908
|
+
}
|
|
909
|
+
function rand(seed) {
|
|
910
|
+
return mix2(fold(seed) + 2654435769) / 4294967296;
|
|
911
|
+
}
|
|
912
|
+
function random(seed) {
|
|
913
|
+
let a = fold(seed) + 1831565813 | 0;
|
|
914
|
+
return () => {
|
|
915
|
+
a = a + 1831565813 | 0;
|
|
916
|
+
let t = Math.imul(a ^ a >>> 15, 1 | a);
|
|
917
|
+
t = t + Math.imul(t ^ t >>> 7, 61 | t) ^ t;
|
|
918
|
+
return ((t ^ t >>> 14) >>> 0) / 4294967296;
|
|
919
|
+
};
|
|
920
|
+
}
|
|
921
|
+
function noise(x, seed = 0) {
|
|
922
|
+
if (!Number.isFinite(x)) return 0;
|
|
923
|
+
const i = Math.floor(x);
|
|
924
|
+
const f = x - i;
|
|
925
|
+
const s = fold(seed) * 668265261;
|
|
926
|
+
const a = mix2((i | 0) + s) / 2147483648 - 1;
|
|
927
|
+
const b = mix2((i + 1 | 0) + s) / 2147483648 - 1;
|
|
928
|
+
const u = f * f * f * (f * (f * 6 - 15) + 10);
|
|
929
|
+
return a + (b - a) * u;
|
|
930
|
+
}
|
|
148
931
|
|
|
149
932
|
// src/expr/Parser.ts
|
|
150
933
|
var FUNCS = {
|
|
@@ -305,7 +1088,7 @@ function parsePrimary(c) {
|
|
|
305
1088
|
}
|
|
306
1089
|
throw new Error(`unexpected token "${t.type}"`);
|
|
307
1090
|
}
|
|
308
|
-
function
|
|
1091
|
+
function parse2(src) {
|
|
309
1092
|
const c = new Cursor(tokenize(src));
|
|
310
1093
|
const node = parseExpr(c);
|
|
311
1094
|
if (c.peek()) throw new Error("trailing input");
|
|
@@ -355,7 +1138,7 @@ function evaluateExpr(source, scope) {
|
|
|
355
1138
|
let ast = astCache.get(source);
|
|
356
1139
|
if (ast === void 0) {
|
|
357
1140
|
try {
|
|
358
|
-
ast =
|
|
1141
|
+
ast = parse2(source);
|
|
359
1142
|
} catch (e) {
|
|
360
1143
|
console.warn(`pixi-effects: expression failed: ${source}`, e);
|
|
361
1144
|
ast = ZERO_NODE;
|
|
@@ -373,19 +1156,29 @@ function evaluateExpr(source, scope) {
|
|
|
373
1156
|
// src/expr/normalizeProps.ts
|
|
374
1157
|
function normalizeProps(input, scope, options = {}) {
|
|
375
1158
|
const skip = new Set(options.skipKeys ?? []);
|
|
376
|
-
return walk(input, scope, skip, null);
|
|
1159
|
+
return walk(input, scope, skip, null, options);
|
|
377
1160
|
}
|
|
378
|
-
|
|
1161
|
+
var RELATIVE = /^\s*([+-])=([\s\S]*)$/;
|
|
1162
|
+
function walk(value, scope, skip, currentKey, options) {
|
|
379
1163
|
if (Array.isArray(value)) {
|
|
380
|
-
return value.map((v) => walk(v, scope, skip, currentKey));
|
|
1164
|
+
return value.map((v) => walk(v, scope, skip, currentKey, options));
|
|
381
1165
|
}
|
|
382
1166
|
if (value !== null && typeof value === "object") {
|
|
383
1167
|
const out = {};
|
|
384
1168
|
for (const k of Object.keys(value)) {
|
|
385
|
-
out[k] = walk(value[k], scope, skip, k);
|
|
1169
|
+
out[k] = walk(value[k], scope, skip, k, options);
|
|
386
1170
|
}
|
|
387
1171
|
return out;
|
|
388
1172
|
}
|
|
1173
|
+
if (typeof value === "string" && !(currentKey !== null && skip.has(currentKey))) {
|
|
1174
|
+
const rel = RELATIVE.exec(value);
|
|
1175
|
+
if (rel) {
|
|
1176
|
+
const n = evaluateExpr(rel[2].trim(), scope);
|
|
1177
|
+
if (options.relative === "allow") return `${rel[1]}=${n}`;
|
|
1178
|
+
console.warn(`pixi-effects: "${value.trim()}"${currentKey ? ` (${currentKey})` : ""} is a relative value (measured from where the layer is): it works in a keyframe's to / from / set, not in ${options.where ?? "an initial or a style"}; it is read as the number ${rel[1] === "-" ? -n : n}`);
|
|
1179
|
+
return rel[1] === "-" ? -n : n;
|
|
1180
|
+
}
|
|
1181
|
+
}
|
|
389
1182
|
if (isExpr(value) && !(currentKey !== null && skip.has(currentKey))) {
|
|
390
1183
|
if (looksLikeColorString(value)) return value;
|
|
391
1184
|
return evaluateExpr(value, scope);
|
|
@@ -397,56 +1190,6 @@ function looksLikeColorString(s) {
|
|
|
397
1190
|
if (s.charCodeAt(0) === 35) return true;
|
|
398
1191
|
return /^(rgb|hsl|oklab|oklch|lab|lch)\b/i.test(s);
|
|
399
1192
|
}
|
|
400
|
-
function cubicBezierEase(x1, y1, x2, y2) {
|
|
401
|
-
const cx = 3 * x1, bx = 3 * (x2 - x1) - cx, ax = 1 - cx - bx;
|
|
402
|
-
const cy = 3 * y1, by = 3 * (y2 - y1) - cy, ay = 1 - cy - by;
|
|
403
|
-
const X = (t) => ((ax * t + bx) * t + cx) * t;
|
|
404
|
-
const Y = (t) => ((ay * t + by) * t + cy) * t;
|
|
405
|
-
const dX = (t) => (3 * ax * t + 2 * bx) * t + cx;
|
|
406
|
-
return (p) => {
|
|
407
|
-
if (p <= 0) return 0;
|
|
408
|
-
if (p >= 1) return 1;
|
|
409
|
-
let t = p;
|
|
410
|
-
for (let i = 0; i < 8; i++) {
|
|
411
|
-
const err = X(t) - p;
|
|
412
|
-
if (Math.abs(err) < 1e-9) return Y(t);
|
|
413
|
-
const d = dX(t);
|
|
414
|
-
if (Math.abs(d) < 1e-6) break;
|
|
415
|
-
t -= err / d;
|
|
416
|
-
}
|
|
417
|
-
let lo = 0, hi = 1;
|
|
418
|
-
t = p;
|
|
419
|
-
for (let i = 0; i < 60; i++) {
|
|
420
|
-
const x = X(t);
|
|
421
|
-
if (Math.abs(x - p) < 1e-10) break;
|
|
422
|
-
if (x < p) lo = t;
|
|
423
|
-
else hi = t;
|
|
424
|
-
t = (lo + hi) / 2;
|
|
425
|
-
}
|
|
426
|
-
return Y(t);
|
|
427
|
-
};
|
|
428
|
-
}
|
|
429
|
-
var NUM = String.raw`\s*(-?(?:\d+\.?\d*|\.\d+)(?:e[-+]?\d+)?)\s*`;
|
|
430
|
-
var RE = new RegExp(`^\\s*cubic-bezier\\(${NUM},${NUM},${NUM},${NUM}\\)\\s*$`, "i");
|
|
431
|
-
function cubicBezierProblem(name) {
|
|
432
|
-
const m = RE.exec(name);
|
|
433
|
-
if (!m) return 'expected "cubic-bezier(x1, y1, x2, y2)" with four numbers, like CSS';
|
|
434
|
-
const x1 = Number(m[1]), x2 = Number(m[3]);
|
|
435
|
-
if (x1 < 0 || x1 > 1 || x2 < 0 || x2 > 1) return "x1 and x2 must be between 0 and 1 (y1 and y2 may overshoot)";
|
|
436
|
-
return null;
|
|
437
|
-
}
|
|
438
|
-
var registered2 = false;
|
|
439
|
-
function registerCubicBezierEase() {
|
|
440
|
-
if (registered2) return;
|
|
441
|
-
registered2 = true;
|
|
442
|
-
const base = ((p) => p);
|
|
443
|
-
base.config = (x1, y1, x2, y2) => {
|
|
444
|
-
const bad = [x1, y1, x2, y2].some((v) => typeof v !== "number" || !Number.isFinite(v)) || x1 < 0 || x1 > 1 || x2 < 0 || x2 > 1;
|
|
445
|
-
return bad ? (p) => p : cubicBezierEase(x1, y1, x2, y2);
|
|
446
|
-
};
|
|
447
|
-
gsap.registerEase("cubic-bezier", base);
|
|
448
|
-
}
|
|
449
|
-
registerCubicBezierEase();
|
|
450
1193
|
|
|
451
1194
|
// src/core/ease.ts
|
|
452
1195
|
var FAMILIES = ["power1", "power2", "power3", "power4", "back", "elastic", "bounce", "circ", "expo", "sine"];
|
|
@@ -458,7 +1201,7 @@ function checkEase(ease, where) {
|
|
|
458
1201
|
const problem = springProblem(ease);
|
|
459
1202
|
if (!problem || warned.has(ease)) return;
|
|
460
1203
|
warned.add(ease);
|
|
461
|
-
console.warn(`pixi-effects: ${where}: unknown ease "${ease}" \u2014 ${problem}.
|
|
1204
|
+
console.warn(`pixi-effects: ${where}: unknown ease "${ease}" \u2014 ${problem}. It runs as its default ease, power1.out.`);
|
|
462
1205
|
return;
|
|
463
1206
|
}
|
|
464
1207
|
if (/^\s*cubic-bezier/i.test(ease)) {
|
|
@@ -468,20 +1211,19 @@ function checkEase(ease, where) {
|
|
|
468
1211
|
console.warn(`pixi-effects: ${where}: unknown ease "${ease}" \u2014 ${problem}. It runs as 'none' (a straight line).`);
|
|
469
1212
|
return;
|
|
470
1213
|
}
|
|
471
|
-
|
|
472
|
-
if (typeof found === "function") return;
|
|
1214
|
+
if (isEaseName(ease)) return;
|
|
473
1215
|
if (warned.has(ease)) return;
|
|
474
1216
|
warned.add(ease);
|
|
475
1217
|
if (ease === "") {
|
|
476
|
-
console.warn(`pixi-effects: ${where}: an empty ease (
|
|
1218
|
+
console.warn(`pixi-effects: ${where}: an empty ease (it would run as power1.out): write 'none' for no easing, or a name such as 'power2.out'`);
|
|
477
1219
|
return;
|
|
478
1220
|
}
|
|
479
|
-
if (
|
|
1221
|
+
if (/^(power[1-4]|quad|cubic|quart|quint|strong|back|elastic|bounce|circ|expo|sine)$/i.test(ease)) {
|
|
480
1222
|
console.warn(`pixi-effects: ${where}: "${ease}" is a family, not an ease \u2014 write ${ease.toLowerCase()}.out, ${ease.toLowerCase()}.in or ${ease.toLowerCase()}.inOut`);
|
|
481
1223
|
return;
|
|
482
1224
|
}
|
|
483
1225
|
const guess = suggestName(ease, EASE_NAMES);
|
|
484
|
-
console.warn(`pixi-effects: ${where}: unknown ease "${ease}"${guess ? ` \u2014 did you mean "${guess}"?` : ""} (
|
|
1226
|
+
console.warn(`pixi-effects: ${where}: unknown ease "${ease}"${guess ? ` \u2014 did you mean "${guess}"?` : ""} (it runs as its default ease, power1.out). Examples: ${EASE_NAMES.slice(0, 7).join(", ")}, back.out(1.7), elastic.out(1, 0.3), steps(8)`);
|
|
485
1227
|
}
|
|
486
1228
|
|
|
487
1229
|
// src/core/Timeline.ts
|
|
@@ -583,16 +1325,7 @@ var PIXI_SHORTHANDS = /* @__PURE__ */ new Set([
|
|
|
583
1325
|
"tileScaleX",
|
|
584
1326
|
"tileScaleY",
|
|
585
1327
|
"tint",
|
|
586
|
-
"colorize",
|
|
587
|
-
"colorizeAmount",
|
|
588
|
-
"colorMatrixFilter",
|
|
589
|
-
"blur",
|
|
590
|
-
"blurX",
|
|
591
|
-
"blurY",
|
|
592
|
-
"blurPadding",
|
|
593
1328
|
"autoAlpha",
|
|
594
|
-
"lineColor",
|
|
595
|
-
"lineAlpha",
|
|
596
1329
|
"fillColor",
|
|
597
1330
|
"fillAlpha"
|
|
598
1331
|
]);
|
|
@@ -616,7 +1349,7 @@ function applyKeyframes(timeline, target, keyframes, parentDuration, scope, skip
|
|
|
616
1349
|
const kf = normalizeKeyframe(raw, parentDuration);
|
|
617
1350
|
const at = offset + kf.at;
|
|
618
1351
|
if (kf.kind === "set") {
|
|
619
|
-
const resolved = normalizeProps(kf.set, scope, { skipKeys });
|
|
1352
|
+
const resolved = normalizeProps(kf.set, scope, { skipKeys, relative: "allow" });
|
|
620
1353
|
const { rest, routed } = splitRouted(resolved, routers);
|
|
621
1354
|
for (const r of routed) timeline.set(r.target, { [r.prop]: r.value }, at);
|
|
622
1355
|
const { ownProps, filterProps } = partitionProps(rest);
|
|
@@ -627,7 +1360,7 @@ function applyKeyframes(timeline, target, keyframes, parentDuration, scope, skip
|
|
|
627
1360
|
timeline.set(f, props, at);
|
|
628
1361
|
}
|
|
629
1362
|
} else if (kf.kind === "to") {
|
|
630
|
-
const resolved = normalizeProps(kf.to, scope, { skipKeys });
|
|
1363
|
+
const resolved = normalizeProps(kf.to, scope, { skipKeys, relative: "allow" });
|
|
631
1364
|
const { rest, routed } = splitRouted(resolved, routers);
|
|
632
1365
|
for (const r of routed)
|
|
633
1366
|
timeline.to(r.target, { [r.prop]: r.value, duration: kf.duration, ease: kf.ease, ...kf.loop }, at);
|
|
@@ -640,7 +1373,7 @@ function applyKeyframes(timeline, target, keyframes, parentDuration, scope, skip
|
|
|
640
1373
|
timeline.to(f, { ...props, duration: kf.duration, ease: kf.ease, ...kf.loop }, at);
|
|
641
1374
|
}
|
|
642
1375
|
} else if (kf.kind === "from") {
|
|
643
|
-
const resolved = normalizeProps(kf.from, scope, { skipKeys });
|
|
1376
|
+
const resolved = normalizeProps(kf.from, scope, { skipKeys, relative: "allow" });
|
|
644
1377
|
const { rest, routed } = splitRouted(resolved, routers);
|
|
645
1378
|
for (const r of routed)
|
|
646
1379
|
timeline.from(r.target, { [r.prop]: r.value, duration: kf.duration, ease: kf.ease, ...kf.loop }, at);
|
|
@@ -653,8 +1386,8 @@ function applyKeyframes(timeline, target, keyframes, parentDuration, scope, skip
|
|
|
653
1386
|
timeline.from(f, { ...props, duration: kf.duration, ease: kf.ease, ...kf.loop }, at);
|
|
654
1387
|
}
|
|
655
1388
|
} else {
|
|
656
|
-
const fromResolved = normalizeProps(kf.from, scope, { skipKeys });
|
|
657
|
-
const toResolved = normalizeProps(kf.to, scope, { skipKeys });
|
|
1389
|
+
const fromResolved = normalizeProps(kf.from, scope, { skipKeys, where: "the from side of a from + to keyframe" });
|
|
1390
|
+
const toResolved = normalizeProps(kf.to, scope, { skipKeys, relative: "allow" });
|
|
658
1391
|
const fromRouted = splitRouted(fromResolved, routers);
|
|
659
1392
|
const toRouted = splitRouted(toResolved, routers);
|
|
660
1393
|
const fromByKey = new Map(fromRouted.routed.map((r) => [r.key, r]));
|
|
@@ -704,15 +1437,15 @@ function applyKeyframes(timeline, target, keyframes, parentDuration, scope, skip
|
|
|
704
1437
|
}
|
|
705
1438
|
function applyInitial(target, initial, scope, skipKeys = [], routers) {
|
|
706
1439
|
if (!initial) return;
|
|
707
|
-
const resolved = normalizeProps(initial, scope, { skipKeys });
|
|
1440
|
+
const resolved = normalizeProps(initial, scope, { skipKeys, where: "initial" });
|
|
708
1441
|
const { rest, routed } = splitRouted(resolved, routers);
|
|
709
|
-
for (const r of routed)
|
|
1442
|
+
for (const r of routed) setNow(r.target, { [r.prop]: r.value });
|
|
710
1443
|
const { ownProps, filterProps } = partitionProps(rest);
|
|
711
|
-
if (Object.keys(ownProps).length > 0)
|
|
1444
|
+
if (Object.keys(ownProps).length > 0) setNow(target, pixiwrap(ownProps));
|
|
712
1445
|
for (const [name, props] of Object.entries(filterProps)) {
|
|
713
1446
|
const f = findFilter(target, name);
|
|
714
1447
|
if (!f) continue;
|
|
715
|
-
|
|
1448
|
+
setNow(f, props);
|
|
716
1449
|
}
|
|
717
1450
|
}
|
|
718
1451
|
|
|
@@ -1147,7 +1880,7 @@ var GrainFilter = class extends Filter {
|
|
|
1147
1880
|
};
|
|
1148
1881
|
var WARP_KINDS = ["wave", "haze"];
|
|
1149
1882
|
var OPTION_KEYS = ["kind", "strength", "scale", "speed", "angle", "seed"];
|
|
1150
|
-
var
|
|
1883
|
+
var DEG2 = Math.PI / 180;
|
|
1151
1884
|
var HASH_GL2 = `
|
|
1152
1885
|
uint hash(uint x) { x ^= x >> 16; x *= 0x7feb352du; x ^= x >> 15; x *= 0x846ca68bu; x ^= x >> 16; return x; }
|
|
1153
1886
|
float lattice(ivec2 p, uint k) {
|
|
@@ -1319,7 +2052,7 @@ var WarpFilter = class extends Filter {
|
|
|
1319
2052
|
uStrength: { value: strength, type: "f32" },
|
|
1320
2053
|
uScale: { value: scale, type: "f32" },
|
|
1321
2054
|
uSpeed: { value: speed, type: "f32" },
|
|
1322
|
-
uAngle: { value: angle *
|
|
2055
|
+
uAngle: { value: angle * DEG2, type: "f32" },
|
|
1323
2056
|
uSeed: { value: Math.floor(seed), type: "f32" },
|
|
1324
2057
|
uMode: { value: kind === "haze" ? 1 : 0, type: "f32" },
|
|
1325
2058
|
uTime: { value: 0, type: "f32" }
|
|
@@ -1357,10 +2090,10 @@ var WarpFilter = class extends Filter {
|
|
|
1357
2090
|
this.u.uSpeed = v;
|
|
1358
2091
|
}
|
|
1359
2092
|
get angle() {
|
|
1360
|
-
return this.u.uAngle /
|
|
2093
|
+
return this.u.uAngle / DEG2;
|
|
1361
2094
|
}
|
|
1362
2095
|
set angle(v) {
|
|
1363
|
-
this.u.uAngle = v *
|
|
2096
|
+
this.u.uAngle = v * DEG2;
|
|
1364
2097
|
}
|
|
1365
2098
|
get seed() {
|
|
1366
2099
|
return this.u.uSeed;
|
|
@@ -1638,6 +2371,8 @@ var NullSequence = class extends Sequence {
|
|
|
1638
2371
|
this.buildFilters();
|
|
1639
2372
|
}
|
|
1640
2373
|
};
|
|
2374
|
+
|
|
2375
|
+
// src/core/remap.ts
|
|
1641
2376
|
var BAGS = ["set", "to", "from"];
|
|
1642
2377
|
function timeRemapOf(spec, prop = "time") {
|
|
1643
2378
|
const hasInitial = !!spec.initial && "time" in spec.initial;
|
|
@@ -1718,7 +2453,7 @@ function bindClock(timeline, clock, prop, remap, duration, at, scope) {
|
|
|
1718
2453
|
timeline.fromTo(clock, { [prop]: from }, { [prop]: from + s * duration, duration, ease: "none" }, at);
|
|
1719
2454
|
}
|
|
1720
2455
|
function clockTable(remap, prop, duration, at, scope, to) {
|
|
1721
|
-
const probe =
|
|
2456
|
+
const probe = createTimeline({ paused: true });
|
|
1722
2457
|
const clock = { [prop]: remap.start ?? 0 };
|
|
1723
2458
|
bindClock(probe, clock, prop, remap, duration, at, scope);
|
|
1724
2459
|
probe.time(probe.duration());
|
|
@@ -1750,7 +2485,7 @@ function clockTable(remap, prop, duration, at, scope, to) {
|
|
|
1750
2485
|
}
|
|
1751
2486
|
|
|
1752
2487
|
// src/space/math.ts
|
|
1753
|
-
var
|
|
2488
|
+
var DEG3 = Math.PI / 180;
|
|
1754
2489
|
var DEFAULT_FOV = 40;
|
|
1755
2490
|
var MIN_FOV = 1;
|
|
1756
2491
|
var MAX_FOV = 179;
|
|
@@ -1760,7 +2495,7 @@ function clampFov(fov) {
|
|
|
1760
2495
|
return Math.min(MAX_FOV, Math.max(MIN_FOV, fov));
|
|
1761
2496
|
}
|
|
1762
2497
|
function homeDistance(compHeight, fovDeg) {
|
|
1763
|
-
return compHeight / 2 / Math.tan(clampFov(fovDeg) *
|
|
2498
|
+
return compHeight / 2 / Math.tan(clampFov(fovDeg) * DEG3 / 2);
|
|
1764
2499
|
}
|
|
1765
2500
|
function homeCamera(compW, compH, fov = DEFAULT_FOV) {
|
|
1766
2501
|
return {
|
|
@@ -1814,7 +2549,7 @@ function cameraBasis(cam, compW, compH) {
|
|
|
1814
2549
|
fx,
|
|
1815
2550
|
fy,
|
|
1816
2551
|
fz,
|
|
1817
|
-
focal: compH / 2 / Math.tan(clampFov(cam.fov) *
|
|
2552
|
+
focal: compH / 2 / Math.tan(clampFov(cam.fov) * DEG3 / 2),
|
|
1818
2553
|
halfW: compW / 2,
|
|
1819
2554
|
halfH: compH / 2
|
|
1820
2555
|
};
|
|
@@ -1878,12 +2613,12 @@ function looksLikeLayerName(s) {
|
|
|
1878
2613
|
var isName = (v, known) => typeof v === "string" && (known.has(v) || looksLikeLayerName(v));
|
|
1879
2614
|
function focusNames(props, known) {
|
|
1880
2615
|
const out = [];
|
|
1881
|
-
const
|
|
2616
|
+
const read2 = (bag) => {
|
|
1882
2617
|
const v = bag?.focus;
|
|
1883
2618
|
if (isName(v, known)) out.push(v);
|
|
1884
2619
|
};
|
|
1885
|
-
|
|
1886
|
-
for (const kf of props.keyframes ?? []) for (const bag of [kf.set, kf.to, kf.from])
|
|
2620
|
+
read2(props.initial);
|
|
2621
|
+
for (const kf of props.keyframes ?? []) for (const bag of [kf.set, kf.to, kf.from]) read2(bag);
|
|
1887
2622
|
return out;
|
|
1888
2623
|
}
|
|
1889
2624
|
function withFocusResolved(props, zOf, known = /* @__PURE__ */ new Set()) {
|
|
@@ -2048,7 +2783,7 @@ function smoothstep(e0, e1, x) {
|
|
|
2048
2783
|
const t = Math.min(1, Math.max(0, (x - e0) / (e1 - e0)));
|
|
2049
2784
|
return t * t * (3 - 2 * t);
|
|
2050
2785
|
}
|
|
2051
|
-
var
|
|
2786
|
+
var DEG4 = Math.PI / 180;
|
|
2052
2787
|
function norm(v) {
|
|
2053
2788
|
const l = Math.hypot(v.x, v.y, v.z) || 1;
|
|
2054
2789
|
return { x: v.x / l, y: v.y / l, z: v.z / l };
|
|
@@ -2056,7 +2791,7 @@ function norm(v) {
|
|
|
2056
2791
|
var dot = (a, b) => a.x * b.x + a.y * b.y + a.z * b.z;
|
|
2057
2792
|
var sub = (a, b) => ({ x: a.x - b.x, y: a.y - b.y, z: a.z - b.z });
|
|
2058
2793
|
function coneCos(l) {
|
|
2059
|
-
const half = Math.min(179, Math.max(0, l.coneAngle)) *
|
|
2794
|
+
const half = Math.min(179, Math.max(0, l.coneAngle)) * DEG4 / 2;
|
|
2060
2795
|
const inner = half * (1 - Math.min(1, Math.max(0, l.coneFeather)));
|
|
2061
2796
|
const cosOuter = Math.cos(half);
|
|
2062
2797
|
const cosInner = Math.max(Math.cos(inner), cosOuter + 1e-4);
|
|
@@ -2190,24 +2925,8 @@ var LightSequence = class extends Sequence {
|
|
|
2190
2925
|
};
|
|
2191
2926
|
|
|
2192
2927
|
// src/core/revertibleSet.ts
|
|
2193
|
-
function revertibleSet(timeline, at,
|
|
2194
|
-
|
|
2195
|
-
let before;
|
|
2196
|
-
const proxy = {
|
|
2197
|
-
get p() {
|
|
2198
|
-
return p;
|
|
2199
|
-
},
|
|
2200
|
-
set p(next) {
|
|
2201
|
-
if (next >= 1 && p < 1) {
|
|
2202
|
-
before = read();
|
|
2203
|
-
write(value);
|
|
2204
|
-
} else if (next < 1 && p >= 1) {
|
|
2205
|
-
write(before);
|
|
2206
|
-
}
|
|
2207
|
-
p = next;
|
|
2208
|
-
}
|
|
2209
|
-
};
|
|
2210
|
-
timeline.set(proxy, { p: 1 }, at);
|
|
2928
|
+
function revertibleSet(timeline, at, read2, write2, value, property) {
|
|
2929
|
+
timeline.setValue(property?.[0] ?? read2, property?.[1] ?? "set", at, read2, write2, value);
|
|
2211
2930
|
}
|
|
2212
2931
|
|
|
2213
2932
|
// src/expr/colorInterp.ts
|
|
@@ -2346,30 +3065,26 @@ function shortestHueDelta(from, to) {
|
|
|
2346
3065
|
// src/expr/colorTween.ts
|
|
2347
3066
|
var css = (c) => typeof c === "number" ? "#" + c.toString(16).padStart(6, "0") : c;
|
|
2348
3067
|
function tweenColor(timeline, target, key, fromValue, toValue, duration, ease, at, colorSpace, onUpdate, loop = {}) {
|
|
2349
|
-
|
|
2350
|
-
|
|
2351
|
-
|
|
2352
|
-
|
|
2353
|
-
|
|
2354
|
-
{
|
|
2355
|
-
|
|
2356
|
-
|
|
2357
|
-
|
|
2358
|
-
...loop,
|
|
2359
|
-
onStart: () => {
|
|
2360
|
-
const start = fromValue !== void 0 ? fromValue : target[key];
|
|
2361
|
-
if (start === void 0) return;
|
|
2362
|
-
interp = colorSpace === "rgb" ? gsap.utils.interpolate(css(start), css(toValue)) : buildColorInterp(start, toValue, colorSpace);
|
|
2363
|
-
},
|
|
2364
|
-
onUpdate: () => {
|
|
2365
|
-
if (interp) {
|
|
2366
|
-
target[key] = interp(proxy.p);
|
|
2367
|
-
if (onUpdate) onUpdate();
|
|
2368
|
-
}
|
|
2369
|
-
}
|
|
3068
|
+
const none = () => void 0;
|
|
3069
|
+
timeline.tweenValue({
|
|
3070
|
+
holder: target,
|
|
3071
|
+
id: key,
|
|
3072
|
+
get: () => target[key],
|
|
3073
|
+
set: (v) => {
|
|
3074
|
+
if (v === void 0) return;
|
|
3075
|
+
target[key] = v;
|
|
3076
|
+
if (onUpdate) onUpdate();
|
|
2370
3077
|
},
|
|
2371
|
-
|
|
2372
|
-
|
|
3078
|
+
from: fromValue !== void 0 ? () => fromValue : void 0,
|
|
3079
|
+
to: () => toValue,
|
|
3080
|
+
make: (a, b) => a === void 0 ? none : colorSpace === "rgb" ? interpolateColors(css(a), css(b)) : buildColorInterp(a, b, colorSpace),
|
|
3081
|
+
duration,
|
|
3082
|
+
ease,
|
|
3083
|
+
at,
|
|
3084
|
+
repeat: loop.repeat,
|
|
3085
|
+
yoyo: loop.yoyo,
|
|
3086
|
+
repeatDelay: loop.repeatDelay
|
|
3087
|
+
});
|
|
2373
3088
|
}
|
|
2374
3089
|
|
|
2375
3090
|
// src/sequences/Image.ts
|
|
@@ -2412,7 +3127,7 @@ var ImageSequence = class extends Sequence {
|
|
|
2412
3127
|
const sprite = this.target;
|
|
2413
3128
|
revertibleSet(timeline, at, () => sprite.tint, (c) => {
|
|
2414
3129
|
sprite.tint = c;
|
|
2415
|
-
}, setTint);
|
|
3130
|
+
}, setTint, [sprite, "tint"]);
|
|
2416
3131
|
}
|
|
2417
3132
|
if (toTint !== void 0) {
|
|
2418
3133
|
tweenColor(
|
|
@@ -2567,37 +3282,37 @@ function validateGradientKeyframes(spec, who, warn = (m) => console.warn(m), kin
|
|
|
2567
3282
|
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)");
|
|
2568
3283
|
}
|
|
2569
3284
|
function tweenGradient(timeline, holder, fromPatch, toPatch, duration, ease, at, colorSpace, onChange, loop = {}) {
|
|
2570
|
-
|
|
2571
|
-
|
|
2572
|
-
|
|
2573
|
-
|
|
2574
|
-
|
|
2575
|
-
|
|
2576
|
-
|
|
2577
|
-
ease,
|
|
2578
|
-
...loop,
|
|
2579
|
-
onStart: () => {
|
|
2580
|
-
const live = holder.grad;
|
|
2581
|
-
a = fromPatch !== void 0 ? mergeGrad(live, fromPatch) : live;
|
|
2582
|
-
if (toPatch === void 0) resting ??= live;
|
|
2583
|
-
b = toPatch !== void 0 ? mergeGrad(a, toPatch) : resting;
|
|
2584
|
-
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));
|
|
3285
|
+
timeline.tweenValue({
|
|
3286
|
+
holder,
|
|
3287
|
+
id: "grad",
|
|
3288
|
+
get: () => holder.grad,
|
|
3289
|
+
set: (g) => {
|
|
3290
|
+
holder.grad = g;
|
|
3291
|
+
onChange();
|
|
2585
3292
|
},
|
|
2586
|
-
|
|
2587
|
-
|
|
2588
|
-
|
|
2589
|
-
const
|
|
2590
|
-
|
|
2591
|
-
|
|
2592
|
-
|
|
2593
|
-
|
|
2594
|
-
|
|
2595
|
-
|
|
2596
|
-
|
|
3293
|
+
from: fromPatch !== void 0 ? (prev) => mergeGrad(prev, fromPatch) : void 0,
|
|
3294
|
+
to: (start, prev) => toPatch !== void 0 ? mergeGrad(start, toPatch) : prev,
|
|
3295
|
+
make: (a, b) => {
|
|
3296
|
+
const colors = a.stops.map((s, i) => colorSpace === "rgb" ? interpolateColors(s.color, b.stops[i].color) : buildColorInterp(s.color, b.stops[i].color, colorSpace));
|
|
3297
|
+
return (t) => {
|
|
3298
|
+
const l = (x, y) => x + (y - x) * t;
|
|
3299
|
+
return {
|
|
3300
|
+
type: a.type,
|
|
3301
|
+
angle: l(a.angle, b.angle),
|
|
3302
|
+
center: [l(a.center[0], b.center[0]), l(a.center[1], b.center[1])],
|
|
3303
|
+
innerRadius: l(a.innerRadius, b.innerRadius),
|
|
3304
|
+
radius: l(a.radius, b.radius),
|
|
3305
|
+
stops: a.stops.map((s, i) => ({ offset: l(s.offset, b.stops[i].offset), color: colors[i](t) }))
|
|
3306
|
+
};
|
|
2597
3307
|
};
|
|
2598
|
-
|
|
2599
|
-
|
|
2600
|
-
|
|
3308
|
+
},
|
|
3309
|
+
duration,
|
|
3310
|
+
ease,
|
|
3311
|
+
at,
|
|
3312
|
+
repeat: loop.repeat,
|
|
3313
|
+
yoyo: loop.yoyo,
|
|
3314
|
+
repeatDelay: loop.repeatDelay
|
|
3315
|
+
});
|
|
2601
3316
|
}
|
|
2602
3317
|
var PAINT_SIZE = 512;
|
|
2603
3318
|
var GradientPainter = class {
|
|
@@ -2642,16 +3357,20 @@ function bindGradientKeyframes(timeline, holder, keyframes, duration, offset, co
|
|
|
2642
3357
|
const at = offset + resolveAt(kf.at, duration);
|
|
2643
3358
|
const setV = bag(kf.set), fromV = bag(kf.from), toV = bag(kf.to);
|
|
2644
3359
|
if (setV !== void 0) {
|
|
2645
|
-
|
|
2646
|
-
|
|
2647
|
-
|
|
2648
|
-
() =>
|
|
2649
|
-
(
|
|
2650
|
-
holder.grad =
|
|
3360
|
+
timeline.tweenValue({
|
|
3361
|
+
holder,
|
|
3362
|
+
id: "grad",
|
|
3363
|
+
get: () => holder.grad,
|
|
3364
|
+
set: (g) => {
|
|
3365
|
+
holder.grad = g;
|
|
2651
3366
|
onChange();
|
|
2652
3367
|
},
|
|
2653
|
-
|
|
2654
|
-
|
|
3368
|
+
to: (start) => mergeGrad(start, setV),
|
|
3369
|
+
make: (_a, b) => () => b,
|
|
3370
|
+
duration: 0,
|
|
3371
|
+
ease: "none",
|
|
3372
|
+
at
|
|
3373
|
+
});
|
|
2655
3374
|
}
|
|
2656
3375
|
if (fromV !== void 0 || toV !== void 0) {
|
|
2657
3376
|
tweenGradient(timeline, holder, fromV, toV, kfDuration(kf), kf.ease ?? "none", at, colorSpace, onChange, loopVars(kf));
|
|
@@ -2843,7 +3562,7 @@ function bindCounterKeyframes(timeline, state, key, refresh, keyframes, parentDu
|
|
|
2843
3562
|
revertibleSet(timeline, at, () => state[key], (n) => {
|
|
2844
3563
|
state[key] = n;
|
|
2845
3564
|
refresh();
|
|
2846
|
-
}, v);
|
|
3565
|
+
}, v, [state, key]);
|
|
2847
3566
|
}
|
|
2848
3567
|
if (toV !== void 0 && fromV !== void 0) {
|
|
2849
3568
|
timeline.fromTo(
|
|
@@ -2859,7 +3578,7 @@ function bindCounterKeyframes(timeline, state, key, refresh, keyframes, parentDu
|
|
|
2859
3578
|
}
|
|
2860
3579
|
}
|
|
2861
3580
|
}
|
|
2862
|
-
function bindTextKeyframes(timeline, keyframes, parentDuration, origin,
|
|
3581
|
+
function bindTextKeyframes(timeline, keyframes, parentDuration, origin, read2, write2, who) {
|
|
2863
3582
|
for (const kf of keyframes) {
|
|
2864
3583
|
for (const [what, props] of [["to", kf.to], ["from", kf.from]]) {
|
|
2865
3584
|
if (props && props.text !== void 0) {
|
|
@@ -2868,7 +3587,7 @@ function bindTextKeyframes(timeline, keyframes, parentDuration, origin, read, wr
|
|
|
2868
3587
|
}
|
|
2869
3588
|
const t = kf.set?.text;
|
|
2870
3589
|
if (t === void 0) continue;
|
|
2871
|
-
revertibleSet(timeline, origin + resolveAt(kf.at, parentDuration),
|
|
3590
|
+
revertibleSet(timeline, origin + resolveAt(kf.at, parentDuration), read2, write2, String(t));
|
|
2872
3591
|
}
|
|
2873
3592
|
}
|
|
2874
3593
|
function animates(keyframes, key) {
|
|
@@ -2890,7 +3609,7 @@ function bindFillKeyframes(timeline, text, keyframes, parentDuration, offset, co
|
|
|
2890
3609
|
revertibleSet(timeline, at, () => state.fill, (c) => {
|
|
2891
3610
|
state.fill = c;
|
|
2892
3611
|
writeFill();
|
|
2893
|
-
}, setFill);
|
|
3612
|
+
}, setFill, [state, "fill"]);
|
|
2894
3613
|
}
|
|
2895
3614
|
if (toFill !== void 0) {
|
|
2896
3615
|
tweenColor(
|
|
@@ -3046,6 +3765,9 @@ var BUDGET_BYTES = 96 * 1024 * 1024;
|
|
|
3046
3765
|
var MIN_HELD = 3;
|
|
3047
3766
|
var JUMP_SECONDS = 1;
|
|
3048
3767
|
var EPS = 1e-6;
|
|
3768
|
+
var LOW_BEHIND = 14;
|
|
3769
|
+
var MIN_HELD_TO_READ_BACK = 20;
|
|
3770
|
+
var MIN_HELD_TO_READ_START = 9;
|
|
3049
3771
|
function reportDecodeError(err, time) {
|
|
3050
3772
|
const isTransient = err instanceof DOMException && (err.name === "EncodingError" || err.name === "NotSupportedError");
|
|
3051
3773
|
if (isTransient) console.debug("pixi-effects: transient video decode failure at", time, "s \u2014", err.name);
|
|
@@ -3064,9 +3786,22 @@ var FrameCache = class {
|
|
|
3064
3786
|
_held = 0;
|
|
3065
3787
|
_lock = Promise.resolve();
|
|
3066
3788
|
_lastTime = null;
|
|
3789
|
+
_dir = 0;
|
|
3790
|
+
_gen = 0;
|
|
3791
|
+
_backBusy = false;
|
|
3792
|
+
_backGen = 0;
|
|
3793
|
+
_standbyBusy = false;
|
|
3794
|
+
/** A second pass at the start of the file, ready for the moment a looping video comes round. */
|
|
3795
|
+
_standby = null;
|
|
3796
|
+
_duration;
|
|
3797
|
+
_loop;
|
|
3798
|
+
/** How often it had to wait for a decoder (`restarts`, `singles`) and how many reads ahead it made: for tests and for `check`. */
|
|
3799
|
+
stats = { restarts: 0, singles: 0, prefetches: 0 };
|
|
3067
3800
|
constructor(sink, options = {}) {
|
|
3068
3801
|
this.sink = sink;
|
|
3069
3802
|
this.capacity = options.capacity ?? 30;
|
|
3803
|
+
this._duration = options.duration ?? null;
|
|
3804
|
+
this._loop = !!options.loop;
|
|
3070
3805
|
}
|
|
3071
3806
|
/** How many decoded frames are held right now (the sequential reader's own list, plus the exact-time cache of the old path). */
|
|
3072
3807
|
get heldFrames() {
|
|
@@ -3136,24 +3871,157 @@ var FrameCache = class {
|
|
|
3136
3871
|
return null;
|
|
3137
3872
|
}
|
|
3138
3873
|
async _sequentialAt(time) {
|
|
3874
|
+
const last = this._lastTime;
|
|
3875
|
+
this._lastTime = time;
|
|
3876
|
+
if (last !== null && Math.abs(time - last) <= JUMP_SECONDS) this._dir = time > last + EPS ? 1 : time < last - EPS ? -1 : this._dir;
|
|
3877
|
+
let frame;
|
|
3139
3878
|
try {
|
|
3140
|
-
|
|
3141
|
-
this._lastTime = time;
|
|
3142
|
-
const hit = this._covering(time);
|
|
3143
|
-
if (hit) return hit.frame;
|
|
3144
|
-
if (last === null || Math.abs(time - last) > JUMP_SECONDS) return await this._single(time);
|
|
3145
|
-
const cur = this._cur;
|
|
3146
|
-
if (this._iter && cur && time >= cur.ts && time - cur.ts <= JUMP_SECONDS) return await this._advance(time);
|
|
3147
|
-
const backwards = !!cur && time < cur.ts;
|
|
3148
|
-
return await this._restart(time, backwards ? Math.max(0, time - this._held / 30) : time);
|
|
3879
|
+
frame = await this._serve(time, last);
|
|
3149
3880
|
} catch (err) {
|
|
3150
3881
|
reportDecodeError(err, time);
|
|
3151
3882
|
await this._closeIter();
|
|
3152
3883
|
return null;
|
|
3153
3884
|
}
|
|
3885
|
+
this._maybeReadAhead(time);
|
|
3886
|
+
return frame;
|
|
3887
|
+
}
|
|
3888
|
+
async _serve(time, last) {
|
|
3889
|
+
const hit = this._covering(time);
|
|
3890
|
+
if (hit) return hit.frame;
|
|
3891
|
+
const sb = this._standby;
|
|
3892
|
+
if (sb && time >= sb.cur.ts - EPS && time - sb.cur.ts <= JUMP_SECONDS && (!this._iter || !this._cur || this._cur.ts > time + JUMP_SECONDS)) return await this._adoptStandby(time);
|
|
3893
|
+
if (last === null || Math.abs(time - last) > JUMP_SECONDS) return await this._single(time);
|
|
3894
|
+
const cur = this._cur;
|
|
3895
|
+
if (this._iter && cur && time >= cur.ts && time - cur.ts <= JUMP_SECONDS) return await this._advance(time);
|
|
3896
|
+
const backwards = !!cur && time < cur.ts;
|
|
3897
|
+
return await this._restart(time, backwards ? Math.max(0, time - Math.max(1, this._held - 1) / 30) : time);
|
|
3898
|
+
}
|
|
3899
|
+
// ── reading ahead ────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
|
|
3900
|
+
_maybeReadAhead(time) {
|
|
3901
|
+
if (this._held === 0) return;
|
|
3902
|
+
if (this._dir === -1) {
|
|
3903
|
+
this._dropStandby();
|
|
3904
|
+
let behind = 0, passed = 0, earliest = Infinity;
|
|
3905
|
+
for (const e of this._frames) {
|
|
3906
|
+
if (e.ts < time - EPS) behind++;
|
|
3907
|
+
else if (e.ts > time + EPS) passed++;
|
|
3908
|
+
if (e.ts < earliest) earliest = e.ts;
|
|
3909
|
+
}
|
|
3910
|
+
if (this._held >= MIN_HELD_TO_READ_BACK && behind < LOW_BEHIND && passed >= 3 && earliest > EPS && !this._backBusy) void this._readBack(earliest, passed);
|
|
3911
|
+
} else if (this._held >= MIN_HELD_TO_READ_START && this._dir === 1 && this._loop && this._duration !== null && time >= this._duration - JUMP_SECONDS && !this._standby && !this._standbyBusy) {
|
|
3912
|
+
void this._readStart();
|
|
3913
|
+
}
|
|
3914
|
+
}
|
|
3915
|
+
/** In the background: the window of frames before the earliest one held (reverse play comes to it next). */
|
|
3916
|
+
async _readBack(earliest, room) {
|
|
3917
|
+
this._backBusy = true;
|
|
3918
|
+
this.stats.prefetches++;
|
|
3919
|
+
const gen = this._gen, bg = this._backGen;
|
|
3920
|
+
const want = Math.max(3, Math.min(Math.floor(this._held * 0.6), room));
|
|
3921
|
+
let iter = null;
|
|
3922
|
+
const got = [];
|
|
3923
|
+
try {
|
|
3924
|
+
iter = this.sink.samples(Math.max(0, earliest - want / 30));
|
|
3925
|
+
for (; ; ) {
|
|
3926
|
+
const r = await iter.next();
|
|
3927
|
+
if (r.done) break;
|
|
3928
|
+
if (gen !== this._gen || r.value.timestamp >= earliest - EPS) {
|
|
3929
|
+
r.value.close?.();
|
|
3930
|
+
break;
|
|
3931
|
+
}
|
|
3932
|
+
got.push(r.value);
|
|
3933
|
+
if (bg !== this._backGen) break;
|
|
3934
|
+
}
|
|
3935
|
+
if (gen === this._gen && bg === this._backGen) {
|
|
3936
|
+
for (let k = 0; k < got.length; k++) {
|
|
3937
|
+
const s = got[k];
|
|
3938
|
+
const frame = s.toVideoFrame();
|
|
3939
|
+
this._keep({ ts: s.timestamp, end: got[k + 1]?.timestamp ?? earliest, frame }, frame);
|
|
3940
|
+
}
|
|
3941
|
+
}
|
|
3942
|
+
} catch (err) {
|
|
3943
|
+
reportDecodeError(err, earliest);
|
|
3944
|
+
} finally {
|
|
3945
|
+
for (const s of got) s.close?.();
|
|
3946
|
+
this._backBusy = false;
|
|
3947
|
+
try {
|
|
3948
|
+
await iter?.return?.(void 0);
|
|
3949
|
+
} catch {
|
|
3950
|
+
}
|
|
3951
|
+
}
|
|
3952
|
+
}
|
|
3953
|
+
/** In the background: the first frames of the file and a pass that stands behind them; held (pinned) until the loop comes round. */
|
|
3954
|
+
async _readStart() {
|
|
3955
|
+
this._standbyBusy = true;
|
|
3956
|
+
this.stats.prefetches++;
|
|
3957
|
+
const gen = this._gen;
|
|
3958
|
+
const want = Math.max(3, Math.min(10, Math.floor(this._held / 3)));
|
|
3959
|
+
let iter = null;
|
|
3960
|
+
const got = [];
|
|
3961
|
+
let keep = false;
|
|
3962
|
+
try {
|
|
3963
|
+
iter = this.sink.samples(0);
|
|
3964
|
+
for (; got.length < want + 1; ) {
|
|
3965
|
+
const r = await iter.next();
|
|
3966
|
+
if (r.done) break;
|
|
3967
|
+
if (gen !== this._gen) {
|
|
3968
|
+
r.value.close?.();
|
|
3969
|
+
break;
|
|
3970
|
+
}
|
|
3971
|
+
got.push(r.value);
|
|
3972
|
+
}
|
|
3973
|
+
if (gen === this._gen && got.length >= 2) {
|
|
3974
|
+
const next = got.pop();
|
|
3975
|
+
let cur = null;
|
|
3976
|
+
got.forEach((s, k) => {
|
|
3977
|
+
const frame = s.toVideoFrame();
|
|
3978
|
+
s.close?.();
|
|
3979
|
+
const entry = { ts: s.timestamp, end: (got[k + 1] ?? next).timestamp, frame, pinned: true };
|
|
3980
|
+
this._keep(entry, frame);
|
|
3981
|
+
cur = entry;
|
|
3982
|
+
});
|
|
3983
|
+
got.length = 0;
|
|
3984
|
+
if (cur) {
|
|
3985
|
+
this._standby = { iter, cur, next };
|
|
3986
|
+
keep = true;
|
|
3987
|
+
}
|
|
3988
|
+
}
|
|
3989
|
+
} catch (err) {
|
|
3990
|
+
reportDecodeError(err, 0);
|
|
3991
|
+
} finally {
|
|
3992
|
+
for (const s of got) s.close?.();
|
|
3993
|
+
this._standbyBusy = false;
|
|
3994
|
+
if (!keep) {
|
|
3995
|
+
try {
|
|
3996
|
+
await iter?.return?.(void 0);
|
|
3997
|
+
} catch {
|
|
3998
|
+
}
|
|
3999
|
+
}
|
|
4000
|
+
}
|
|
4001
|
+
}
|
|
4002
|
+
async _adoptStandby(time) {
|
|
4003
|
+
const sb = this._standby;
|
|
4004
|
+
this._standby = null;
|
|
4005
|
+
await this._closeIter();
|
|
4006
|
+
for (const e of this._frames) e.pinned = false;
|
|
4007
|
+
this._iter = sb.iter;
|
|
4008
|
+
this._next = sb.next;
|
|
4009
|
+
this._cur = sb.cur;
|
|
4010
|
+
return this._advance(time);
|
|
4011
|
+
}
|
|
4012
|
+
_dropStandby() {
|
|
4013
|
+
const sb = this._standby;
|
|
4014
|
+
if (!sb) return;
|
|
4015
|
+
this._standby = null;
|
|
4016
|
+
sb.next?.close?.();
|
|
4017
|
+
for (const e of this._frames.filter((x) => x.pinned)) {
|
|
4018
|
+
e.pinned = false;
|
|
4019
|
+
}
|
|
4020
|
+
void sb.iter.return?.(void 0);
|
|
3154
4021
|
}
|
|
3155
4022
|
/** One frame by itself (a seek): getSample, kept so that asking again for the same time costs nothing. The running pass, if any, is closed: it no longer follows the playhead. */
|
|
3156
4023
|
async _single(time) {
|
|
4024
|
+
this.stats.singles++;
|
|
3157
4025
|
await this._closeIter();
|
|
3158
4026
|
this._cur = null;
|
|
3159
4027
|
const sample = await this.sink.getSample(time);
|
|
@@ -3165,6 +4033,8 @@ var FrameCache = class {
|
|
|
3165
4033
|
}
|
|
3166
4034
|
/** Start a pass at `time` (a seek and the frames of one group of pictures), keeping what is still held for a step back. */
|
|
3167
4035
|
async _restart(time, from = time) {
|
|
4036
|
+
this.stats.restarts++;
|
|
4037
|
+
this._backGen++;
|
|
3168
4038
|
await this._closeIter();
|
|
3169
4039
|
this._cur = null;
|
|
3170
4040
|
const iter = this.sink.samples(from);
|
|
@@ -3228,12 +4098,27 @@ var FrameCache = class {
|
|
|
3228
4098
|
}
|
|
3229
4099
|
this._frames.push(entry);
|
|
3230
4100
|
while (this._frames.length > this._held) {
|
|
3231
|
-
const
|
|
3232
|
-
if (!
|
|
3233
|
-
this._frames.splice(this._frames.indexOf(
|
|
3234
|
-
|
|
4101
|
+
const victim = this._victim(entry);
|
|
4102
|
+
if (!victim) break;
|
|
4103
|
+
this._frames.splice(this._frames.indexOf(victim), 1);
|
|
4104
|
+
victim.frame.close?.();
|
|
3235
4105
|
}
|
|
3236
4106
|
}
|
|
4107
|
+
/**
|
|
4108
|
+
* The frame to let go: one the playhead has already passed (going forward those before it, going back those after it), the furthest
|
|
4109
|
+
* behind first; when there is none, the one furthest ahead of the playhead (the last to be needed). Least recently used when the
|
|
4110
|
+
* direction is not known. Frames of the standby (pinned) and the frame the pass stands on are never chosen.
|
|
4111
|
+
*/
|
|
4112
|
+
_victim(except) {
|
|
4113
|
+
const cand = this._frames.filter((e) => e !== this._cur && e !== except && !e.pinned);
|
|
4114
|
+
if (cand.length === 0) return null;
|
|
4115
|
+
if (this._dir === 0) return cand[0];
|
|
4116
|
+
const at = this._lastTime ?? 0;
|
|
4117
|
+
const passed = cand.filter((e) => this._dir === 1 ? e.ts < at - EPS : e.ts > at + EPS);
|
|
4118
|
+
const farthest = (list, sign) => list.reduce((a, b) => sign * (b.ts - a.ts) > 0 ? b : a);
|
|
4119
|
+
if (passed.length) return farthest(passed, this._dir === 1 ? -1 : 1);
|
|
4120
|
+
return farthest(cand, this._dir === 1 ? 1 : -1);
|
|
4121
|
+
}
|
|
3237
4122
|
async _closeIter() {
|
|
3238
4123
|
const iter = this._iter;
|
|
3239
4124
|
this._iter = null;
|
|
@@ -3256,6 +4141,8 @@ var FrameCache = class {
|
|
|
3256
4141
|
}
|
|
3257
4142
|
}
|
|
3258
4143
|
dispose() {
|
|
4144
|
+
this._gen++;
|
|
4145
|
+
this._dropStandby();
|
|
3259
4146
|
for (const f of this.cache.values()) f?.close?.();
|
|
3260
4147
|
this.cache.clear();
|
|
3261
4148
|
this._pending.clear();
|
|
@@ -3297,7 +4184,7 @@ var VideoSequence = class extends Sequence {
|
|
|
3297
4184
|
this._sourceDuration = data.duration;
|
|
3298
4185
|
this._remap = remapOf(this.spec, "currentTime", this._sourceDuration);
|
|
3299
4186
|
this._audioBuffer = this.spec.audio !== false ? data.audioBuffer : null;
|
|
3300
|
-
this._cache = new FrameCache(data.sink, { capacity: 30 });
|
|
4187
|
+
this._cache = new FrameCache(data.sink, { capacity: 30, duration: data.duration, loop: !!this.spec.loop });
|
|
3301
4188
|
const probeFrame = await this._cache.getFrameAt(0);
|
|
3302
4189
|
const w = probeFrame?.displayWidth ?? 1920;
|
|
3303
4190
|
const h = probeFrame?.displayHeight ?? 1080;
|
|
@@ -3327,8 +4214,8 @@ var VideoSequence = class extends Sequence {
|
|
|
3327
4214
|
currentTime = v;
|
|
3328
4215
|
seq._cur = v;
|
|
3329
4216
|
const mySeq = ++seq._drawSeq;
|
|
3330
|
-
const
|
|
3331
|
-
seq._cache.getFrameAt(
|
|
4217
|
+
const lookup2 = sourceLookup(v, seq._sourceDuration, !!seq.spec.loop);
|
|
4218
|
+
seq._cache.getFrameAt(lookup2).then((frame) => {
|
|
3332
4219
|
if (mySeq !== seq._drawSeq) return;
|
|
3333
4220
|
if (!frame || !seq._ctx) return;
|
|
3334
4221
|
seq._ctx.drawImage(frame, 0, 0);
|
|
@@ -3382,10 +4269,10 @@ var VideoSequence = class extends Sequence {
|
|
|
3382
4269
|
const time = this._cur;
|
|
3383
4270
|
if (!this.keepHidden && !this.target?.renderable) return;
|
|
3384
4271
|
const mySeq = ++this._drawSeq;
|
|
3385
|
-
const
|
|
4272
|
+
const lookup2 = sourceLookup(time, this._sourceDuration, !!this.spec.loop);
|
|
3386
4273
|
let frame = null;
|
|
3387
4274
|
try {
|
|
3388
|
-
frame = await this._cache.getFrameAt(
|
|
4275
|
+
frame = await this._cache.getFrameAt(lookup2);
|
|
3389
4276
|
} catch (err) {
|
|
3390
4277
|
console.warn("pixi-effects: awaitFrameAt failed at", time, "s \u2014", err);
|
|
3391
4278
|
return;
|
|
@@ -3793,7 +4680,7 @@ function seedGeometry(state, spec, scope) {
|
|
|
3793
4680
|
const initial = spec.initial ?? {};
|
|
3794
4681
|
for (const k of keys) {
|
|
3795
4682
|
const v = spec[k] ?? initial[k];
|
|
3796
|
-
if (v !== void 0) state[k] =
|
|
4683
|
+
if (v !== void 0) state[k] = num2(v, scope);
|
|
3797
4684
|
}
|
|
3798
4685
|
}
|
|
3799
4686
|
var STROKE_CAPS = ["butt", "round", "square"];
|
|
@@ -3911,7 +4798,7 @@ function drawEllipseFromState(g, s) {
|
|
|
3911
4798
|
const ay = s.anchorY ?? 0.5;
|
|
3912
4799
|
g.ellipse((0.5 - ax) * 2 * rx, (0.5 - ay) * 2 * ry, rx, ry);
|
|
3913
4800
|
}
|
|
3914
|
-
var
|
|
4801
|
+
var DEG5 = Math.PI / 180;
|
|
3915
4802
|
function drawArcFromState(g, s) {
|
|
3916
4803
|
const r = s.radius ?? 0;
|
|
3917
4804
|
const ri = Math.max(0, Math.min(s.innerRadius ?? 0, r));
|
|
@@ -3926,7 +4813,7 @@ function drawArcFromState(g, s) {
|
|
|
3926
4813
|
}
|
|
3927
4814
|
endDeg = startDeg + Math.sign(endDeg - startDeg) * 359.999;
|
|
3928
4815
|
}
|
|
3929
|
-
const a0 = startDeg *
|
|
4816
|
+
const a0 = startDeg * DEG5, a1 = endDeg * DEG5;
|
|
3930
4817
|
const ccw = a1 < a0;
|
|
3931
4818
|
if (filled) g.moveTo(r * Math.cos(a0), r * Math.sin(a0));
|
|
3932
4819
|
g.arc(0, 0, r, a0, a1, ccw);
|
|
@@ -3940,10 +4827,10 @@ function drawArcFromState(g, s) {
|
|
|
3940
4827
|
g.closePath();
|
|
3941
4828
|
}
|
|
3942
4829
|
function makeLineDraw(spec, scope) {
|
|
3943
|
-
const fx =
|
|
3944
|
-
const fy =
|
|
3945
|
-
const tx =
|
|
3946
|
-
const ty =
|
|
4830
|
+
const fx = num2(spec.from[0], scope);
|
|
4831
|
+
const fy = num2(spec.from[1], scope);
|
|
4832
|
+
const tx = num2(spec.to[0], scope);
|
|
4833
|
+
const ty = num2(spec.to[1], scope);
|
|
3947
4834
|
return (g) => {
|
|
3948
4835
|
g.moveTo(fx, fy);
|
|
3949
4836
|
g.lineTo(tx, ty);
|
|
@@ -3953,7 +4840,7 @@ function makePolygonDraw(spec, scope) {
|
|
|
3953
4840
|
if (spec.points.length === 0) return () => {
|
|
3954
4841
|
};
|
|
3955
4842
|
const flat = [];
|
|
3956
|
-
for (const [x, y] of spec.points) flat.push(
|
|
4843
|
+
for (const [x, y] of spec.points) flat.push(num2(x, scope), num2(y, scope));
|
|
3957
4844
|
const closed = !spec.open;
|
|
3958
4845
|
return (g) => {
|
|
3959
4846
|
g.poly(flat, closed);
|
|
@@ -4019,12 +4906,12 @@ function makeOutline(spec, scope, s, morph) {
|
|
|
4019
4906
|
return [ellipseOutline((0.5 - (s.anchorX ?? 0.5)) * 2 * rx, (0.5 - (s.anchorY ?? 0.5)) * 2 * ry, rx, ry)];
|
|
4020
4907
|
};
|
|
4021
4908
|
case "line": {
|
|
4022
|
-
const lines = [{ pts: [
|
|
4909
|
+
const lines = [{ pts: [num2(spec.from[0], scope), num2(spec.from[1], scope), num2(spec.to[0], scope), num2(spec.to[1], scope)], closed: false }];
|
|
4023
4910
|
return () => lines;
|
|
4024
4911
|
}
|
|
4025
4912
|
case "polygon": {
|
|
4026
4913
|
const pts = [];
|
|
4027
|
-
for (const [x, y] of spec.points) pts.push(
|
|
4914
|
+
for (const [x, y] of spec.points) pts.push(num2(x, scope), num2(y, scope));
|
|
4028
4915
|
const lines = pts.length >= 4 ? [{ pts, closed: !spec.open }] : [];
|
|
4029
4916
|
return () => lines;
|
|
4030
4917
|
}
|
|
@@ -4052,7 +4939,7 @@ function bindLiveKeyframes(timeline, state, liveKeys, keyframes, parentDuration,
|
|
|
4052
4939
|
const live2 = state;
|
|
4053
4940
|
revertibleSet(timeline, at, () => live2[k], (v2) => {
|
|
4054
4941
|
live2[k] = v2;
|
|
4055
|
-
}, resolved);
|
|
4942
|
+
}, resolved, [live2, k]);
|
|
4056
4943
|
}
|
|
4057
4944
|
}
|
|
4058
4945
|
}
|
|
@@ -4096,7 +4983,7 @@ function tweenLiveKey(timeline, state, key, fromValue, toValue, duration, ease,
|
|
|
4096
4983
|
}
|
|
4097
4984
|
}
|
|
4098
4985
|
}
|
|
4099
|
-
function
|
|
4986
|
+
function num2(v, scope) {
|
|
4100
4987
|
if (typeof v === "number") return v;
|
|
4101
4988
|
if (isExpr(v)) return evaluateExpr(v, scope);
|
|
4102
4989
|
const parsed = parseFloat(v);
|
|
@@ -4104,7 +4991,7 @@ function num(v, scope) {
|
|
|
4104
4991
|
}
|
|
4105
4992
|
function numOrZero(v, scope) {
|
|
4106
4993
|
if (typeof v === "number") return v;
|
|
4107
|
-
if (typeof v === "string") return
|
|
4994
|
+
if (typeof v === "string") return num2(v, scope);
|
|
4108
4995
|
return 0;
|
|
4109
4996
|
}
|
|
4110
4997
|
|
|
@@ -4153,13 +5040,13 @@ var SHADER_BUILTINS = ["iResolution", "iTime", "iFrame"];
|
|
|
4153
5040
|
var SHADER_MISSING = ["iMouse", "iChannel0", "iChannel1", "iChannel2", "iChannel3", "iDate", "iTimeDelta", "iSampleRate"];
|
|
4154
5041
|
var IDENT = /^[A-Za-z_][A-Za-z0-9_]*$/;
|
|
4155
5042
|
var HEX = /^#(?:[0-9a-fA-F]{3}|[0-9a-fA-F]{6})$/;
|
|
4156
|
-
var
|
|
5043
|
+
var RESERVED2 = new Set(`attribute const uniform varying break continue do for while if else in out inout float int void bool true false discard return
|
|
4157
5044
|
mat2 mat3 mat4 mat2x2 mat2x3 mat2x4 mat3x2 mat3x3 mat3x4 mat4x2 mat4x3 mat4x4 vec2 vec3 vec4 ivec2 ivec3 ivec4 bvec2 bvec3 bvec4 uvec2 uvec3 uvec4 uint
|
|
4158
5045
|
sampler2D sampler3D samplerCube sampler2DShadow samplerCubeShadow sampler2DArray sampler2DArrayShadow isampler2D isampler3D isamplerCube isampler2DArray
|
|
4159
5046
|
usampler2D usampler3D usamplerCube usampler2DArray struct layout centroid flat smooth precision invariant highp mediump lowp
|
|
4160
5047
|
sample patch subroutine common partition active asm class union enum typedef template this resource goto inline noinline public static extern external
|
|
4161
5048
|
interface long short double half fixed unsigned superp input output hvec2 hvec3 hvec4 fvec2 fvec3 fvec4 dvec2 dvec3 dvec4 filter sizeof cast namespace using`.split(/\s+/));
|
|
4162
|
-
var isIdent = (name) => IDENT.test(name) && !name.startsWith("gl_") && !name.includes("__") && !
|
|
5049
|
+
var isIdent = (name) => IDENT.test(name) && !name.startsWith("gl_") && !name.includes("__") && !RESERVED2.has(name) && !SHADER_BUILTINS.includes(name);
|
|
4163
5050
|
function uniformType(v) {
|
|
4164
5051
|
if (typeof v === "number") return Number.isFinite(v) ? "float" : null;
|
|
4165
5052
|
if (typeof v === "string") return HEX.test(v) ? "vec3" : null;
|
|
@@ -4497,7 +5384,7 @@ function resolveDim(v, scope) {
|
|
|
4497
5384
|
var _CompositionSequence = null;
|
|
4498
5385
|
async function getCompositionSequence() {
|
|
4499
5386
|
if (!_CompositionSequence) {
|
|
4500
|
-
_CompositionSequence = (await import('./Composition-
|
|
5387
|
+
_CompositionSequence = (await import('./Composition-4TYDRRRY.js')).CompositionSequence;
|
|
4501
5388
|
}
|
|
4502
5389
|
return _CompositionSequence;
|
|
4503
5390
|
}
|
|
@@ -4539,6 +5426,6 @@ async function buildSequenceTree(specs, parent, root) {
|
|
|
4539
5426
|
return out;
|
|
4540
5427
|
}
|
|
4541
5428
|
|
|
4542
|
-
export { CameraSequence, DEFAULT_FOV,
|
|
4543
|
-
//# sourceMappingURL=chunk-
|
|
4544
|
-
//# sourceMappingURL=chunk-
|
|
5429
|
+
export { CameraSequence, DEFAULT_FOV, DEG3 as DEG, FALLOFFS, LIGHT_KINDS, LIGHT_PROPS, LightSequence, MANY_BLURRED, MAX_BLUR, MAX_CASTERS, MAX_LIGHTS, MIN_BLUR, NEAR, NullSequence, SHADOW_TAPS, Sequence, bindClock, blurRadius, buildScope, buildSequenceTree, cameraBasis, checkEase, clockTable, contentLength, createTimeline, ensureFilterLibrary, evaluateExpr, flattenSvgPath, focusProblems, homeCamera, homeDistance, layerInitialZ, layerToWorld, lengthen, lightLevel, noise, packLights, parseEase, projectLayer, projectPoint, rand, random, registerSequenceType, remapOf, resolveAt, timeRemapOf };
|
|
5430
|
+
//# sourceMappingURL=chunk-TGJACVLD.js.map
|
|
5431
|
+
//# sourceMappingURL=chunk-TGJACVLD.js.map
|