pixi-effects 0.31.0 → 0.33.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 +29 -0
- package/README.md +5 -5
- package/ai/chat-template.html +3 -3
- package/ai/tools/lookup.mjs +29 -6
- package/ai/tools/pixi-effects.mjs +1 -1
- package/ai/tools/render.mjs +19 -2
- package/dist/{Base-jRiMHcWT.d.ts → Base-CXsMdmJB.d.ts} +1 -1
- package/dist/{Base-BKagtWc0.d.cts → Base-pNq6sVGl.d.cts} +1 -1
- package/dist/Composition-7XNPTM7L.js +7 -0
- package/dist/{Composition-DQCPJPFE.js.map → Composition-7XNPTM7L.js.map} +1 -1
- package/dist/Composition-L6OALWHI.cjs +16 -0
- package/dist/{Composition-V2XYSW6P.cjs.map → Composition-L6OALWHI.cjs.map} +1 -1
- package/dist/Controller.d.cts +2 -2
- package/dist/Controller.d.ts +2 -2
- package/dist/{Movie-BH81stkb.d.cts → Movie-CL6SsAWe.d.cts} +1 -1
- package/dist/{Movie-CfFPItoL.d.ts → Movie-f0tQG9y5.d.ts} +1 -1
- package/dist/Spans-KPZ2QDCN.js +53 -0
- package/dist/Spans-KPZ2QDCN.js.map +1 -0
- package/dist/Spans-VXNQXSI3.cjs +55 -0
- package/dist/Spans-VXNQXSI3.cjs.map +1 -0
- package/dist/{blendModes-RIVZXL5A.js → blendModes-PP5NPBXY.js} +4 -4
- package/dist/{blendModes-RIVZXL5A.js.map → blendModes-PP5NPBXY.js.map} +1 -1
- package/dist/{blendModes-ETMYWATF.cjs → blendModes-WIUCYIMC.cjs} +5 -5
- package/dist/{blendModes-ETMYWATF.cjs.map → blendModes-WIUCYIMC.cjs.map} +1 -1
- package/dist/{chunk-BGMCZA36.js → chunk-BMH4OCDX.js} +6 -6
- package/dist/chunk-BMH4OCDX.js.map +1 -0
- package/dist/{chunk-DJ5B7IKT.cjs → chunk-BVMZUPDU.cjs} +1379 -1161
- package/dist/chunk-BVMZUPDU.cjs.map +1 -0
- package/dist/{chunk-MMTESMJ5.js → chunk-E53QWHBK.js} +1363 -1151
- package/dist/chunk-E53QWHBK.js.map +1 -0
- package/dist/{chunk-LYOKH7KE.cjs → chunk-GL2AQFLQ.cjs} +57 -6
- package/dist/chunk-GL2AQFLQ.cjs.map +1 -0
- package/dist/{chunk-2DXPTKQZ.cjs → chunk-IMQJVRMT.cjs} +5 -5
- package/dist/{chunk-2DXPTKQZ.cjs.map → chunk-IMQJVRMT.cjs.map} +1 -1
- package/dist/{chunk-RCVZX2JP.js → chunk-ITDYFBB6.js} +57 -6
- package/dist/chunk-ITDYFBB6.js.map +1 -0
- package/dist/{chunk-X3WHETQ3.cjs → chunk-LD4VKNPQ.cjs} +81 -44
- package/dist/chunk-LD4VKNPQ.cjs.map +1 -0
- package/dist/{chunk-4KB3GUEK.js → chunk-RTJD3ZSW.js} +4 -4
- package/dist/{chunk-4KB3GUEK.js.map → chunk-RTJD3ZSW.js.map} +1 -1
- package/dist/{chunk-L73KRFXI.cjs → chunk-SBBXKPBP.cjs} +91 -91
- package/dist/chunk-SBBXKPBP.cjs.map +1 -0
- package/dist/{chunk-UTIBYMIO.js → chunk-WST432AP.js} +52 -15
- package/dist/chunk-WST432AP.js.map +1 -0
- package/dist/index.cjs +33 -33
- package/dist/index.d.cts +5 -5
- package/dist/index.d.ts +5 -5
- package/dist/index.js +5 -5
- package/dist/loader.css +1 -1
- package/dist/present.cjs +5 -5
- package/dist/present.d.cts +2 -2
- package/dist/present.d.ts +2 -2
- package/dist/present.js +5 -5
- package/dist/three.cjs +6 -6
- package/dist/three.d.cts +2 -2
- package/dist/three.d.ts +2 -2
- package/dist/three.js +2 -2
- package/dist/{types-CK_crNAI.d.ts → types-CavnUvd5.d.cts} +26 -1
- package/dist/{types-CK_crNAI.d.cts → types-CavnUvd5.d.ts} +26 -1
- package/docs/dsl.md +16 -4
- package/llms-full.txt +28 -12
- package/package.json +1 -1
- package/skills/pixi-effects/SKILL.md +1 -1
- package/skills/pixi-effects/reference/cheatsheet.md +2 -2
- package/skills/pixi-effects/reference/pitfalls.md +5 -3
- package/skills/pixi-effects/reference/quickstart.md +3 -2
- package/skills/pixi-effects/reference/recipes.md +1 -1
- package/skills/pixi-effects/template.html +6 -6
- package/dist/Composition-DQCPJPFE.js +0 -7
- package/dist/Composition-V2XYSW6P.cjs +0 -16
- package/dist/chunk-BGMCZA36.js.map +0 -1
- package/dist/chunk-DJ5B7IKT.cjs.map +0 -1
- package/dist/chunk-L73KRFXI.cjs.map +0 -1
- package/dist/chunk-LYOKH7KE.cjs.map +0 -1
- package/dist/chunk-MMTESMJ5.js.map +0 -1
- package/dist/chunk-RCVZX2JP.js.map +0 -1
- package/dist/chunk-UTIBYMIO.js.map +0 -1
- package/dist/chunk-X3WHETQ3.cjs.map +0 -1
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
3
|
+
var chunkGL2AQFLQ_cjs = require('./chunk-GL2AQFLQ.cjs');
|
|
4
4
|
var chunkTWZNOUM7_cjs = require('./chunk-TWZNOUM7.cjs');
|
|
5
5
|
var PIXI = require('pixi.js');
|
|
6
6
|
|
|
@@ -366,6 +366,35 @@ function pixiAccessors(target, key) {
|
|
|
366
366
|
return null;
|
|
367
367
|
}
|
|
368
368
|
}
|
|
369
|
+
function pathView(target, key) {
|
|
370
|
+
const parts = key.split(".");
|
|
371
|
+
const leaf = parts.pop();
|
|
372
|
+
const parentOf = () => {
|
|
373
|
+
let o = target;
|
|
374
|
+
for (const p of parts) {
|
|
375
|
+
o = o?.[p];
|
|
376
|
+
if (o === null || typeof o !== "object") return null;
|
|
377
|
+
}
|
|
378
|
+
return o;
|
|
379
|
+
};
|
|
380
|
+
const first = parentOf();
|
|
381
|
+
if (!first || !(leaf in first)) return null;
|
|
382
|
+
const view = {};
|
|
383
|
+
Object.defineProperty(view, leaf, {
|
|
384
|
+
get: () => parentOf()?.[leaf],
|
|
385
|
+
set: (v) => {
|
|
386
|
+
const parent = parentOf();
|
|
387
|
+
if (parent) parent[leaf] = v;
|
|
388
|
+
}
|
|
389
|
+
});
|
|
390
|
+
return { view, leaf };
|
|
391
|
+
}
|
|
392
|
+
var saidPaths = /* @__PURE__ */ new Set();
|
|
393
|
+
function warnLeadsNowhere(key) {
|
|
394
|
+
if (saidPaths.has(key)) return;
|
|
395
|
+
saidPaths.add(key);
|
|
396
|
+
console.warn(`pixi-effects: "${key}" leads nowhere on its target, so it is ignored (a point option of a filter must exist to be animated: give it in the filter's options, e.g. red: { x: 0, y: 0 })`);
|
|
397
|
+
}
|
|
369
398
|
function rawAccessor(target, key) {
|
|
370
399
|
return { id: key, kind: "raw", unit: 1, round: 1, get: () => target[key], set: (v) => {
|
|
371
400
|
target[key] = v;
|
|
@@ -483,7 +512,14 @@ var PureTimeline = class _PureTimeline {
|
|
|
483
512
|
for (const key of Object.keys(v)) {
|
|
484
513
|
if (RESERVED.has(key) || key === "pixi" || CALLBACKS.includes(key)) continue;
|
|
485
514
|
const value = v[key];
|
|
486
|
-
const
|
|
515
|
+
const path = key.includes(".") ? pathView(t, key) : null;
|
|
516
|
+
if (key.includes(".") && !path) {
|
|
517
|
+
warnLeadsNowhere(key);
|
|
518
|
+
continue;
|
|
519
|
+
}
|
|
520
|
+
const at2 = path?.view ?? t, name = path?.leaf ?? key;
|
|
521
|
+
const acc = parseRel(value) ? plainAccessor(at2, name) : typeof value === "string" && parseCssColor(value) ? cssAccessor(at2, name) : rawAccessor(at2, name);
|
|
522
|
+
acc.id = key;
|
|
487
523
|
out.set(acc.id, { acc, value });
|
|
488
524
|
}
|
|
489
525
|
if (v.pixi) for (const key of Object.keys(v.pixi)) {
|
|
@@ -891,7 +927,14 @@ function setNow(target, vars) {
|
|
|
891
927
|
}
|
|
892
928
|
} else {
|
|
893
929
|
const v = vars[key];
|
|
894
|
-
|
|
930
|
+
const value = typeof v === "number" ? Math.round(v * 1e6) / 1e6 : v;
|
|
931
|
+
if (key.includes(".")) {
|
|
932
|
+
const path = pathView(t, key);
|
|
933
|
+
if (path) path.view[path.leaf] = value;
|
|
934
|
+
else warnLeadsNowhere(key);
|
|
935
|
+
continue;
|
|
936
|
+
}
|
|
937
|
+
plainAccessor(t, key).set(value);
|
|
895
938
|
}
|
|
896
939
|
}
|
|
897
940
|
}
|
|
@@ -2269,6 +2312,13 @@ var registry = {
|
|
|
2269
2312
|
function looksLikePixiFilter(x) {
|
|
2270
2313
|
return !!x && typeof x === "object" && typeof x.apply === "function";
|
|
2271
2314
|
}
|
|
2315
|
+
function copyPlain(v) {
|
|
2316
|
+
if (Array.isArray(v)) return v.map(copyPlain);
|
|
2317
|
+
if (v && typeof v === "object" && Object.getPrototypeOf(v) === Object.prototype) {
|
|
2318
|
+
return Object.fromEntries(Object.entries(v).map(([k, x]) => [k, copyPlain(x)]));
|
|
2319
|
+
}
|
|
2320
|
+
return v;
|
|
2321
|
+
}
|
|
2272
2322
|
function createFilter(spec) {
|
|
2273
2323
|
if (spec.type === "custom") {
|
|
2274
2324
|
const inst2 = spec.filter;
|
|
@@ -2279,7 +2329,8 @@ function createFilter(spec) {
|
|
|
2279
2329
|
named._name = spec.name;
|
|
2280
2330
|
return named;
|
|
2281
2331
|
}
|
|
2282
|
-
const { type, name, ...
|
|
2332
|
+
const { type, name, ...given } = spec;
|
|
2333
|
+
const params = copyPlain(given);
|
|
2283
2334
|
const Cls = registry[type];
|
|
2284
2335
|
const inst = Cls ? new Cls(params) : createNamedFilter(type, params);
|
|
2285
2336
|
inst._name = name;
|
|
@@ -2404,694 +2455,345 @@ var NullSequence = class extends Sequence {
|
|
|
2404
2455
|
}
|
|
2405
2456
|
};
|
|
2406
2457
|
|
|
2407
|
-
// src/
|
|
2408
|
-
|
|
2409
|
-
|
|
2410
|
-
const hasInitial = !!spec.initial && "time" in spec.initial;
|
|
2411
|
-
const hasKf = (spec.keyframes ?? []).some((kf) => BAGS.some((b) => kf[b] && "time" in kf[b]));
|
|
2412
|
-
const speed = typeof spec.speed === "number" && Number.isFinite(spec.speed) && spec.speed !== 0 ? spec.speed : void 0;
|
|
2413
|
-
if (!hasInitial && !hasKf && speed === void 0) return null;
|
|
2414
|
-
const timeKfs = [];
|
|
2415
|
-
const restKfs = [];
|
|
2416
|
-
for (const kf of spec.keyframes ?? []) {
|
|
2417
|
-
const t = { ...kf }, r = { ...kf };
|
|
2418
|
-
let touched = false, left = false;
|
|
2419
|
-
for (const b of BAGS) {
|
|
2420
|
-
const bag = kf[b];
|
|
2421
|
-
if (!bag) {
|
|
2422
|
-
delete t[b];
|
|
2423
|
-
delete r[b];
|
|
2424
|
-
continue;
|
|
2425
|
-
}
|
|
2426
|
-
const { time, ...others } = bag;
|
|
2427
|
-
if ("time" in bag) {
|
|
2428
|
-
touched = true;
|
|
2429
|
-
t[b] = { [prop]: time };
|
|
2430
|
-
} else delete t[b];
|
|
2431
|
-
if (Object.keys(others).length) {
|
|
2432
|
-
r[b] = others;
|
|
2433
|
-
left = true;
|
|
2434
|
-
} else delete r[b];
|
|
2435
|
-
}
|
|
2436
|
-
if (touched) timeKfs.push(t);
|
|
2437
|
-
if (!touched || left) restKfs.push(r);
|
|
2438
|
-
}
|
|
2439
|
-
let restInitial = spec.initial;
|
|
2440
|
-
let start;
|
|
2441
|
-
if (hasInitial) {
|
|
2442
|
-
const { time, ...others } = spec.initial;
|
|
2443
|
-
start = typeof time === "number" && Number.isFinite(time) ? time : void 0;
|
|
2444
|
-
restInitial = others;
|
|
2445
|
-
}
|
|
2446
|
-
return { timeKfs, restKfs: restKfs.length ? restKfs : void 0, restInitial, start, speed };
|
|
2458
|
+
// src/sequences/gradient.ts
|
|
2459
|
+
function cssColor(c) {
|
|
2460
|
+
return typeof c === "number" ? "#" + c.toString(16).padStart(6, "0") : c;
|
|
2447
2461
|
}
|
|
2448
|
-
function
|
|
2449
|
-
const
|
|
2450
|
-
|
|
2451
|
-
|
|
2452
|
-
for (const b of BAGS) {
|
|
2453
|
-
const bag = kf[b];
|
|
2454
|
-
if (bag && prop in bag) out[b] = { ...bag, [prop]: fix(bag[prop]) };
|
|
2455
|
-
}
|
|
2456
|
-
return out;
|
|
2457
|
-
});
|
|
2458
|
-
return { ...remap, timeKfs, start: remap.start === void 0 ? void 0 : fix(remap.start) };
|
|
2462
|
+
function normalizedStops(g) {
|
|
2463
|
+
const stops = g.stops ?? [];
|
|
2464
|
+
if (stops.length < 2) throw new Error('pixi-effects: fillGradient needs at least two colour stops, e.g. stops: [[0, "#000"], [1, "#fff"]]');
|
|
2465
|
+
return stops.map((s) => Array.isArray(s) ? { offset: s[0], color: s[1] } : { offset: s.offset, color: s.color });
|
|
2459
2466
|
}
|
|
2460
|
-
function
|
|
2461
|
-
const
|
|
2462
|
-
|
|
2467
|
+
function gradientOptions(g) {
|
|
2468
|
+
const colorStops = normalizedStops(g);
|
|
2469
|
+
const a = (g.angle ?? 90) * Math.PI / 180;
|
|
2470
|
+
const dx = Math.cos(a), dy = Math.sin(a);
|
|
2471
|
+
const h = (Math.abs(dx) + Math.abs(dy)) / 2;
|
|
2472
|
+
return {
|
|
2473
|
+
type: "linear",
|
|
2474
|
+
start: { x: 0.5 - dx * h, y: 0.5 - dy * h },
|
|
2475
|
+
end: { x: 0.5 + dx * h, y: 0.5 + dy * h },
|
|
2476
|
+
colorStops,
|
|
2477
|
+
textureSpace: "local"
|
|
2478
|
+
};
|
|
2463
2479
|
}
|
|
2464
|
-
function
|
|
2465
|
-
|
|
2466
|
-
|
|
2467
|
-
|
|
2468
|
-
for (const
|
|
2469
|
-
|
|
2470
|
-
|
|
2471
|
-
|
|
2472
|
-
|
|
2473
|
-
|
|
2480
|
+
function paintRadial(ctx, size, g) {
|
|
2481
|
+
const stops = normalizedStops(g);
|
|
2482
|
+
const [cx, cy] = g.center ?? [0.5, 0.5];
|
|
2483
|
+
const grad = ctx.createRadialGradient(cx * size, cy * size, (g.innerRadius ?? 0) * size, cx * size, cy * size, (g.radius ?? 0.5) * size);
|
|
2484
|
+
for (const s of stops) grad.addColorStop(s.offset, cssColor(s.color));
|
|
2485
|
+
ctx.fillStyle = grad;
|
|
2486
|
+
ctx.fillRect(0, 0, size, size);
|
|
2487
|
+
}
|
|
2488
|
+
|
|
2489
|
+
// src/expr/colorInterp.ts
|
|
2490
|
+
var CHROMA_FLOOR = 0.03;
|
|
2491
|
+
var CHROMA_FULL = 0.08;
|
|
2492
|
+
function buildColorInterp(from, to, space) {
|
|
2493
|
+
const fromRGBA = parseToRGBA(from);
|
|
2494
|
+
const toRGBA = parseToRGBA(to);
|
|
2495
|
+
const fromOk = rgbToOklab(fromRGBA);
|
|
2496
|
+
const toOk = rgbToOklab(toRGBA);
|
|
2497
|
+
if (space === "oklab") {
|
|
2498
|
+
return (t) => {
|
|
2499
|
+
const L = lerp(fromOk.L, toOk.L, t);
|
|
2500
|
+
const a = lerp(fromOk.a, toOk.a, t);
|
|
2501
|
+
const b = lerp(fromOk.b, toOk.b, t);
|
|
2502
|
+
const alpha = lerp(fromRGBA.a, toRGBA.a, t);
|
|
2503
|
+
return rgbaString(oklabToRgb({ L, a, b }), alpha);
|
|
2504
|
+
};
|
|
2474
2505
|
}
|
|
2475
|
-
|
|
2506
|
+
const fromLCH = oklabToOklch(fromOk);
|
|
2507
|
+
const toLCH = oklabToOklch(toOk);
|
|
2508
|
+
const fromHue = fromLCH.h, toHue = toLCH.h;
|
|
2509
|
+
fromLCH.h = borrowHue(fromHue, fromLCH.C, toHue);
|
|
2510
|
+
toLCH.h = borrowHue(toHue, toLCH.C, fromHue);
|
|
2511
|
+
const hueDelta = shortestHueDelta(fromLCH.h, toLCH.h);
|
|
2512
|
+
return (t) => {
|
|
2513
|
+
const L = lerp(fromLCH.L, toLCH.L, t);
|
|
2514
|
+
const C = lerp(fromLCH.C, toLCH.C, t);
|
|
2515
|
+
const h = fromLCH.h + hueDelta * t;
|
|
2516
|
+
const alpha = lerp(fromRGBA.a, toRGBA.a, t);
|
|
2517
|
+
const ab = oklchToOklab({ L, C, h });
|
|
2518
|
+
return rgbaString(oklabToRgb(ab), alpha);
|
|
2519
|
+
};
|
|
2476
2520
|
}
|
|
2477
|
-
function
|
|
2478
|
-
|
|
2479
|
-
|
|
2480
|
-
|
|
2481
|
-
|
|
2521
|
+
function borrowHue(own, chroma, other) {
|
|
2522
|
+
const u = Math.min(1, Math.max(0, (chroma - CHROMA_FLOOR) / (CHROMA_FULL - CHROMA_FLOOR)));
|
|
2523
|
+
const keep = u * u * (3 - 2 * u);
|
|
2524
|
+
return own + shortestHueDelta(own, other) * (1 - keep);
|
|
2525
|
+
}
|
|
2526
|
+
function parseToRGBA(input) {
|
|
2527
|
+
if (typeof input === "number") {
|
|
2528
|
+
return { r: (input >> 16 & 255) / 255, g: (input >> 8 & 255) / 255, b: (input & 255) / 255, a: 1 };
|
|
2482
2529
|
}
|
|
2483
|
-
const s =
|
|
2484
|
-
|
|
2485
|
-
|
|
2530
|
+
const s = input.trim();
|
|
2531
|
+
if (s.startsWith("#")) return parseHex(s);
|
|
2532
|
+
if (s.startsWith("rgb")) return parseRgbFunc(s);
|
|
2533
|
+
return { r: 0, g: 0, b: 0, a: 1 };
|
|
2486
2534
|
}
|
|
2487
|
-
function
|
|
2488
|
-
const
|
|
2489
|
-
|
|
2490
|
-
|
|
2491
|
-
|
|
2492
|
-
|
|
2493
|
-
|
|
2494
|
-
|
|
2495
|
-
|
|
2496
|
-
|
|
2497
|
-
|
|
2498
|
-
|
|
2499
|
-
|
|
2500
|
-
tab[k] = v;
|
|
2501
|
-
const t = k * h;
|
|
2502
|
-
if (t >= at && t <= at + duration) {
|
|
2503
|
-
if (v < min) min = v;
|
|
2504
|
-
if (v > max) max = v;
|
|
2505
|
-
}
|
|
2535
|
+
function parseHex(s) {
|
|
2536
|
+
const hex = s.slice(1);
|
|
2537
|
+
let r = 0, g = 0, b = 0, a = 1;
|
|
2538
|
+
if (hex.length === 3 || hex.length === 4) {
|
|
2539
|
+
r = parseInt(hex[0] + hex[0], 16) / 255;
|
|
2540
|
+
g = parseInt(hex[1] + hex[1], 16) / 255;
|
|
2541
|
+
b = parseInt(hex[2] + hex[2], 16) / 255;
|
|
2542
|
+
if (hex.length === 4) a = parseInt(hex[3] + hex[3], 16) / 255;
|
|
2543
|
+
} else if (hex.length === 6 || hex.length === 8) {
|
|
2544
|
+
r = parseInt(hex.slice(0, 2), 16) / 255;
|
|
2545
|
+
g = parseInt(hex.slice(2, 4), 16) / 255;
|
|
2546
|
+
b = parseInt(hex.slice(4, 6), 16) / 255;
|
|
2547
|
+
if (hex.length === 8) a = parseInt(hex.slice(6, 8), 16) / 255;
|
|
2506
2548
|
}
|
|
2507
|
-
|
|
2549
|
+
return { r, g, b, a };
|
|
2550
|
+
}
|
|
2551
|
+
function parseRgbFunc(s) {
|
|
2552
|
+
const inner = s.replace(/^rgba?\(/, "").replace(/\)$/, "");
|
|
2553
|
+
const parts = inner.split(/[,\s/]+/).filter(Boolean).map(parseFloat);
|
|
2508
2554
|
return {
|
|
2509
|
-
|
|
2510
|
-
|
|
2511
|
-
|
|
2512
|
-
|
|
2513
|
-
},
|
|
2514
|
-
min: Number.isFinite(min) ? min : 0,
|
|
2515
|
-
max: Number.isFinite(max) ? max : 0
|
|
2555
|
+
r: (parts[0] ?? 0) / 255,
|
|
2556
|
+
g: (parts[1] ?? 0) / 255,
|
|
2557
|
+
b: (parts[2] ?? 0) / 255,
|
|
2558
|
+
a: parts.length > 3 ? parts[3] ?? 1 : 1
|
|
2516
2559
|
};
|
|
2517
2560
|
}
|
|
2518
|
-
|
|
2519
|
-
|
|
2520
|
-
|
|
2521
|
-
|
|
2522
|
-
|
|
2523
|
-
var MAX_FOV = 179;
|
|
2524
|
-
var NEAR = 1;
|
|
2525
|
-
function clampFov(fov) {
|
|
2526
|
-
if (!Number.isFinite(fov)) return DEFAULT_FOV;
|
|
2527
|
-
return Math.min(MAX_FOV, Math.max(MIN_FOV, fov));
|
|
2561
|
+
function rgbaString(rgb, alpha) {
|
|
2562
|
+
const r = Math.round(clamp01(rgb.r) * 255);
|
|
2563
|
+
const g = Math.round(clamp01(rgb.g) * 255);
|
|
2564
|
+
const b = Math.round(clamp01(rgb.b) * 255);
|
|
2565
|
+
return `rgba(${r},${g},${b},${alpha})`;
|
|
2528
2566
|
}
|
|
2529
|
-
function
|
|
2530
|
-
return
|
|
2567
|
+
function srgbToLinear(c) {
|
|
2568
|
+
return c <= 0.04045 ? c / 12.92 : Math.pow((c + 0.055) / 1.055, 2.4);
|
|
2531
2569
|
}
|
|
2532
|
-
function
|
|
2570
|
+
function linearToSrgb(c) {
|
|
2571
|
+
return c <= 31308e-7 ? 12.92 * c : 1.055 * Math.pow(c, 1 / 2.4) - 0.055;
|
|
2572
|
+
}
|
|
2573
|
+
function rgbToOklab(rgba) {
|
|
2574
|
+
const r = srgbToLinear(rgba.r);
|
|
2575
|
+
const g = srgbToLinear(rgba.g);
|
|
2576
|
+
const b = srgbToLinear(rgba.b);
|
|
2577
|
+
const l = 0.4122214708 * r + 0.5363325363 * g + 0.0514459929 * b;
|
|
2578
|
+
const m = 0.2119034982 * r + 0.6806995451 * g + 0.1073969566 * b;
|
|
2579
|
+
const s = 0.0883024619 * r + 0.2817188376 * g + 0.6299787005 * b;
|
|
2580
|
+
const l_ = Math.cbrt(l);
|
|
2581
|
+
const m_ = Math.cbrt(m);
|
|
2582
|
+
const s_ = Math.cbrt(s);
|
|
2533
2583
|
return {
|
|
2534
|
-
|
|
2535
|
-
|
|
2536
|
-
|
|
2537
|
-
lookAtX: compW / 2,
|
|
2538
|
-
lookAtY: compH / 2,
|
|
2539
|
-
lookAtZ: 0,
|
|
2540
|
-
fov
|
|
2584
|
+
L: 0.2104542553 * l_ + 0.793617785 * m_ - 0.0040720468 * s_,
|
|
2585
|
+
a: 1.9779984951 * l_ - 2.428592205 * m_ + 0.4505937099 * s_,
|
|
2586
|
+
b: 0.0259040371 * l_ + 0.7827717662 * m_ - 0.808675766 * s_
|
|
2541
2587
|
};
|
|
2542
2588
|
}
|
|
2543
|
-
function
|
|
2544
|
-
|
|
2545
|
-
|
|
2546
|
-
|
|
2547
|
-
|
|
2548
|
-
|
|
2549
|
-
|
|
2550
|
-
fy = 0;
|
|
2551
|
-
fz = -1;
|
|
2552
|
-
len = 1;
|
|
2553
|
-
}
|
|
2554
|
-
fx /= len;
|
|
2555
|
-
fy /= len;
|
|
2556
|
-
fz /= len;
|
|
2557
|
-
let rx = -fz;
|
|
2558
|
-
const ry = 0;
|
|
2559
|
-
let rz = fx;
|
|
2560
|
-
const rlen = Math.hypot(rx, rz);
|
|
2561
|
-
if (rlen < 1e-9) {
|
|
2562
|
-
rx = 1;
|
|
2563
|
-
rz = 0;
|
|
2564
|
-
} else {
|
|
2565
|
-
rx /= rlen;
|
|
2566
|
-
rz /= rlen;
|
|
2567
|
-
}
|
|
2568
|
-
const dx = ry * fz - rz * fy;
|
|
2569
|
-
const dy = rz * fx - rx * fz;
|
|
2570
|
-
const dz = rx * fy - ry * fx;
|
|
2589
|
+
function oklabToRgb(lab) {
|
|
2590
|
+
const l_ = lab.L + 0.3963377774 * lab.a + 0.2158037573 * lab.b;
|
|
2591
|
+
const m_ = lab.L - 0.1055613458 * lab.a - 0.0638541728 * lab.b;
|
|
2592
|
+
const s_ = lab.L - 0.0894841775 * lab.a - 1.291485548 * lab.b;
|
|
2593
|
+
const l = l_ * l_ * l_;
|
|
2594
|
+
const m = m_ * m_ * m_;
|
|
2595
|
+
const s = s_ * s_ * s_;
|
|
2571
2596
|
return {
|
|
2572
|
-
|
|
2573
|
-
|
|
2574
|
-
|
|
2575
|
-
rx,
|
|
2576
|
-
ry,
|
|
2577
|
-
rz,
|
|
2578
|
-
dx,
|
|
2579
|
-
dy,
|
|
2580
|
-
dz,
|
|
2581
|
-
fx,
|
|
2582
|
-
fy,
|
|
2583
|
-
fz,
|
|
2584
|
-
focal: compH / 2 / Math.tan(clampFov(cam.fov) * DEG3 / 2),
|
|
2585
|
-
halfW: compW / 2,
|
|
2586
|
-
halfH: compH / 2
|
|
2597
|
+
r: linearToSrgb(4.0767416621 * l - 3.3077115913 * m + 0.2309699292 * s),
|
|
2598
|
+
g: linearToSrgb(-1.2684380046 * l + 2.6097574011 * m - 0.3413193965 * s),
|
|
2599
|
+
b: linearToSrgb(-0.0041960863 * l - 0.7034186147 * m + 1.707614701 * s)
|
|
2587
2600
|
};
|
|
2588
2601
|
}
|
|
2589
|
-
function
|
|
2590
|
-
|
|
2591
|
-
let y = (py - t.pivotY) * t.scaleY;
|
|
2592
|
-
let z = 0;
|
|
2593
|
-
let c = Math.cos(t.rotationX);
|
|
2594
|
-
let s = Math.sin(t.rotationX);
|
|
2595
|
-
[y, z] = [y * c - z * s, y * s + z * c];
|
|
2596
|
-
c = Math.cos(t.rotationY);
|
|
2597
|
-
s = Math.sin(t.rotationY);
|
|
2598
|
-
[x, z] = [x * c + z * s, -x * s + z * c];
|
|
2599
|
-
c = Math.cos(t.rotationZ);
|
|
2600
|
-
s = Math.sin(t.rotationZ);
|
|
2601
|
-
[x, y] = [x * c - y * s, x * s + y * c];
|
|
2602
|
-
return { x: x + t.x, y: y + t.y, z: z + t.z };
|
|
2603
|
-
}
|
|
2604
|
-
function projectPoint(b, p) {
|
|
2605
|
-
const vx = p.x - b.cx;
|
|
2606
|
-
const vy = p.y - b.cy;
|
|
2607
|
-
const vz = p.z - b.cz;
|
|
2608
|
-
const xc = vx * b.rx + vy * b.ry + vz * b.rz;
|
|
2609
|
-
const yc = vx * b.dx + vy * b.dy + vz * b.dz;
|
|
2610
|
-
const zc = vx * b.fx + vy * b.fy + vz * b.fz;
|
|
2611
|
-
return { x: b.halfW + b.focal * xc / zc, y: b.halfH + b.focal * yc / zc, depth: zc };
|
|
2602
|
+
function oklabToOklch(lab) {
|
|
2603
|
+
return { L: lab.L, C: Math.hypot(lab.a, lab.b), h: Math.atan2(lab.b, lab.a) };
|
|
2612
2604
|
}
|
|
2613
|
-
function
|
|
2614
|
-
|
|
2615
|
-
[frame.x, frame.y],
|
|
2616
|
-
[frame.x + frame.width, frame.y],
|
|
2617
|
-
[frame.x + frame.width, frame.y + frame.height],
|
|
2618
|
-
[frame.x, frame.y + frame.height]
|
|
2619
|
-
];
|
|
2620
|
-
let visible = true;
|
|
2621
|
-
const corners = [];
|
|
2622
|
-
for (const [px, py] of pts) {
|
|
2623
|
-
const p = projectPoint(b, layerToWorld(t, px, py));
|
|
2624
|
-
if (!(p.depth > NEAR)) visible = false;
|
|
2625
|
-
corners.push(p.x, p.y);
|
|
2626
|
-
}
|
|
2627
|
-
const origin = projectPoint(b, { x: t.x, y: t.y, z: t.z });
|
|
2628
|
-
return { corners, depth: origin.depth, visible };
|
|
2605
|
+
function oklchToOklab(lch) {
|
|
2606
|
+
return { L: lch.L, a: lch.C * Math.cos(lch.h), b: lch.C * Math.sin(lch.h) };
|
|
2629
2607
|
}
|
|
2630
|
-
|
|
2631
|
-
|
|
2632
|
-
var DEFAULT_APERTURE = 30;
|
|
2633
|
-
var MIN_BLUR = 0.05;
|
|
2634
|
-
var MAX_BLUR = 32;
|
|
2635
|
-
var MANY_BLURRED = 20;
|
|
2636
|
-
function blurRadius(aperture, focal, depth, focusDepth) {
|
|
2637
|
-
if (!(aperture > 0) || !(focal > 0) || !(depth > 0) || !(focusDepth > 0)) return 0;
|
|
2638
|
-
const r = aperture * focal * Math.abs(1 / depth - 1 / focusDepth) / 2;
|
|
2639
|
-
return Math.min(r, MAX_BLUR);
|
|
2608
|
+
function lerp(a, b, t) {
|
|
2609
|
+
return a + (b - a) * t;
|
|
2640
2610
|
}
|
|
2641
|
-
|
|
2642
|
-
|
|
2643
|
-
return /^[A-Za-z_][\w-]*$/.test(s) && !SCOPE_NAMES.has(s);
|
|
2611
|
+
function clamp01(v) {
|
|
2612
|
+
return v < 0 ? 0 : v > 1 ? 1 : v;
|
|
2644
2613
|
}
|
|
2645
|
-
|
|
2646
|
-
|
|
2647
|
-
|
|
2648
|
-
|
|
2649
|
-
|
|
2650
|
-
|
|
2651
|
-
};
|
|
2652
|
-
read2(props.initial);
|
|
2653
|
-
for (const kf of props.keyframes ?? []) for (const bag of [kf.set, kf.to, kf.from]) read2(bag);
|
|
2654
|
-
return out;
|
|
2614
|
+
function shortestHueDelta(from, to) {
|
|
2615
|
+
const TWO_PI = Math.PI * 2;
|
|
2616
|
+
let d = (to - from) % TWO_PI;
|
|
2617
|
+
if (d > Math.PI) d -= TWO_PI;
|
|
2618
|
+
if (d < -Math.PI) d += TWO_PI;
|
|
2619
|
+
return d;
|
|
2655
2620
|
}
|
|
2656
|
-
|
|
2657
|
-
|
|
2658
|
-
|
|
2659
|
-
|
|
2660
|
-
if (!bag || !isName(v, known)) return bag;
|
|
2661
|
-
return { ...bag, focus: zOf(v) ?? 0 };
|
|
2662
|
-
};
|
|
2621
|
+
|
|
2622
|
+
// src/sequences/gradientAnim.ts
|
|
2623
|
+
var PATCH_KEYS = ["type", "angle", "center", "innerRadius", "radius", "stops"];
|
|
2624
|
+
function gradStateFrom(g) {
|
|
2663
2625
|
return {
|
|
2664
|
-
|
|
2665
|
-
|
|
2666
|
-
|
|
2626
|
+
type: g.type ?? "linear",
|
|
2627
|
+
angle: g.angle ?? 90,
|
|
2628
|
+
center: [...g.center ?? [0.5, 0.5]],
|
|
2629
|
+
innerRadius: g.innerRadius ?? 0,
|
|
2630
|
+
radius: g.radius ?? 0.5,
|
|
2631
|
+
stops: (g.stops ?? []).map((s) => Array.isArray(s) ? { offset: s[0], color: cssColor(s[1]) } : { offset: s.offset, color: cssColor(s.color) })
|
|
2667
2632
|
};
|
|
2668
2633
|
}
|
|
2669
|
-
function
|
|
2670
|
-
const
|
|
2671
|
-
if (typeof
|
|
2672
|
-
|
|
2673
|
-
|
|
2674
|
-
|
|
2675
|
-
|
|
2676
|
-
|
|
2677
|
-
|
|
2678
|
-
|
|
2679
|
-
|
|
2680
|
-
const known = new Set(siblings.map((s) => s.name).filter((n) => !!n));
|
|
2681
|
-
for (const name of focusNames(camera, known)) {
|
|
2682
|
-
if (said.has(name)) continue;
|
|
2683
|
-
said.add(name);
|
|
2684
|
-
const same = siblings.filter((s) => s.name === name);
|
|
2685
|
-
const hit = same.find((s) => s.threeD) ?? same[0];
|
|
2686
|
-
if (!hit) out.push({ kind: "missing", name, hint: chunkTWZNOUM7_cjs.suggestName(name, threeD) });
|
|
2687
|
-
else if (!hit.threeD) out.push({ kind: "not-threeD", name });
|
|
2688
|
-
else {
|
|
2689
|
-
if (same.length > 1) out.push({ kind: "duplicate", name, count: same.length });
|
|
2690
|
-
if (movesZ(hit)) out.push({ kind: "moving", name });
|
|
2691
|
-
}
|
|
2634
|
+
function mergeGrad(base, patch) {
|
|
2635
|
+
const out = { ...base, center: [...base.center], stops: base.stops.map((s) => ({ ...s })) };
|
|
2636
|
+
if (patch === null || typeof patch !== "object" || Array.isArray(patch)) return out;
|
|
2637
|
+
const p = patch;
|
|
2638
|
+
if (typeof p.angle === "number") out.angle = p.angle;
|
|
2639
|
+
if (Array.isArray(p.center)) out.center = [Number(p.center[0]), Number(p.center[1])];
|
|
2640
|
+
if (typeof p.innerRadius === "number") out.innerRadius = p.innerRadius;
|
|
2641
|
+
if (typeof p.radius === "number") out.radius = p.radius;
|
|
2642
|
+
if (p.stops !== void 0) {
|
|
2643
|
+
const next = gradStateFrom({ stops: p.stops }).stops;
|
|
2644
|
+
if (next.length === base.stops.length) out.stops = next;
|
|
2692
2645
|
}
|
|
2693
2646
|
return out;
|
|
2694
2647
|
}
|
|
2695
|
-
var
|
|
2696
|
-
|
|
2697
|
-
|
|
2698
|
-
|
|
2699
|
-
|
|
2700
|
-
|
|
2701
|
-
|
|
2702
|
-
/** True when the camera writes `focus` or `aperture` anywhere: depth of field is on. */
|
|
2703
|
-
dof = false;
|
|
2704
|
-
/** True when the camera writes any fog key anywhere: depth fog is on (nothing is made for a camera without fog). */
|
|
2705
|
-
fog = false;
|
|
2706
|
-
fogC = null;
|
|
2707
|
-
zOfName = null;
|
|
2708
|
-
layerNames = /* @__PURE__ */ new Set();
|
|
2709
|
-
async build() {
|
|
2710
|
-
const compW = this.parent?.width ?? this.root.width;
|
|
2711
|
-
this.compH = this.parent?.height ?? this.root.height;
|
|
2712
|
-
if (this.duration === void 0) {
|
|
2713
|
-
this.duration = this.parent?.duration ?? this.root.duration;
|
|
2714
|
-
}
|
|
2715
|
-
const home = homeCamera(compW, this.compH);
|
|
2716
|
-
const carrier = new PIXI.Container();
|
|
2717
|
-
carrier.x = home.x;
|
|
2718
|
-
carrier.y = home.y;
|
|
2719
|
-
carrier.z = home.z;
|
|
2720
|
-
carrier.lookAtX = home.lookAtX;
|
|
2721
|
-
carrier.lookAtY = home.lookAtY;
|
|
2722
|
-
carrier.lookAtZ = home.lookAtZ;
|
|
2723
|
-
carrier.fov = home.fov;
|
|
2724
|
-
carrier.focus = 0;
|
|
2725
|
-
carrier.aperture = DEFAULT_APERTURE;
|
|
2726
|
-
carrier.offsetX = carrier.offsetY = carrier.offsetZ = 0;
|
|
2727
|
-
carrier.lookOffsetX = carrier.lookOffsetY = carrier.lookOffsetZ = 0;
|
|
2728
|
-
carrier.fogNear = home.z;
|
|
2729
|
-
carrier.fogFar = home.z * 3;
|
|
2730
|
-
carrier.fogColor = "#000000";
|
|
2731
|
-
carrier.fogAmount = 1;
|
|
2732
|
-
this.target = carrier;
|
|
2733
|
-
const keys = chunkLYOKH7KE_cjs.collectPropKeys(this.spec);
|
|
2734
|
-
this.autoZ = !keys.has("z");
|
|
2735
|
-
this.dof = keys.has("focus") || keys.has("aperture");
|
|
2736
|
-
this.fog = keys.has("fogNear") || keys.has("fogFar") || keys.has("fogColor") || keys.has("fogAmount");
|
|
2737
|
-
}
|
|
2738
|
-
/** The aperture to use now: off unless depth of field is on and the value is a number of 0 or more (said once if it is not). */
|
|
2739
|
-
apertureNow(a) {
|
|
2740
|
-
if (!this.dof) return 0;
|
|
2741
|
-
if (!(a >= 0) && !this.warnedAperture) {
|
|
2742
|
-
this.warnedAperture = true;
|
|
2743
|
-
const who = this.spec.name ? ` "${this.spec.name}"` : "";
|
|
2744
|
-
console.warn(`pixi-effects: camera${who}: aperture ${a} is not a number of 0 or more; depth of field is off (it is the lens diameter in px: 30 is the default, 0 turns it off)`);
|
|
2648
|
+
var objectHint = "a keyframe's fillGradient must be an object like { angle: 200, stops: [[0, '#f00'], [1, '#00f']] }";
|
|
2649
|
+
function validateGradientKeyframes(spec, who, warn = (m) => console.warn(m), kind = "shape") {
|
|
2650
|
+
const said = /* @__PURE__ */ new Set();
|
|
2651
|
+
const say = (m) => {
|
|
2652
|
+
if (!said.has(m)) {
|
|
2653
|
+
said.add(m);
|
|
2654
|
+
warn(`pixi-effects: ${who}: ${m}`);
|
|
2745
2655
|
}
|
|
2746
|
-
|
|
2747
|
-
|
|
2748
|
-
|
|
2749
|
-
|
|
2750
|
-
|
|
2751
|
-
|
|
2752
|
-
|
|
2753
|
-
|
|
2754
|
-
const base = super.displayProps();
|
|
2755
|
-
return this.zOfName ? withFocusResolved(base, this.zOfName, this.layerNames) : base;
|
|
2656
|
+
};
|
|
2657
|
+
const startSpec = spec.fillGradient ?? spec.initial?.fillGradient;
|
|
2658
|
+
const start = startSpec && typeof startSpec === "object" && Array.isArray(startSpec.stops) ? gradStateFrom(startSpec) : null;
|
|
2659
|
+
let animated = false;
|
|
2660
|
+
if (kind === "text") {
|
|
2661
|
+
const radial = (g) => !!g && typeof g === "object" && ["type", "center", "innerRadius", "radius"].some((k) => g[k] !== void 0 && !(k === "type" && g.type === "linear"));
|
|
2662
|
+
const asked = radial(startSpec) || (spec.keyframes ?? []).some((kf) => [kf.set, kf.to, kf.from].some((b) => radial(b?.fillGradient)));
|
|
2663
|
+
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");
|
|
2756
2664
|
}
|
|
2757
|
-
|
|
2758
|
-
|
|
2759
|
-
|
|
2760
|
-
|
|
2761
|
-
|
|
2762
|
-
|
|
2763
|
-
|
|
2764
|
-
|
|
2765
|
-
|
|
2766
|
-
|
|
2767
|
-
|
|
2768
|
-
|
|
2769
|
-
|
|
2770
|
-
|
|
2771
|
-
|
|
2772
|
-
|
|
2773
|
-
|
|
2774
|
-
|
|
2775
|
-
|
|
2776
|
-
|
|
2777
|
-
|
|
2778
|
-
|
|
2779
|
-
|
|
2780
|
-
|
|
2781
|
-
|
|
2782
|
-
|
|
2783
|
-
|
|
2784
|
-
/** The fog now (colour as 0..1 channels, distances, 0..1 amount), or null when the camera writes no fog key. */
|
|
2785
|
-
fogState() {
|
|
2786
|
-
if (!this.fog) return null;
|
|
2787
|
-
const c = this.target;
|
|
2788
|
-
const fc = this.fogC ??= new PIXI.Color();
|
|
2789
|
-
try {
|
|
2790
|
-
fc.setValue(c.fogColor);
|
|
2791
|
-
} catch {
|
|
2792
|
-
fc.setValue(0);
|
|
2665
|
+
for (const kf of spec.keyframes ?? []) {
|
|
2666
|
+
for (const bag of [kf.set, kf.to, kf.from]) {
|
|
2667
|
+
if (!bag) continue;
|
|
2668
|
+
for (const [key, value] of Object.entries(bag)) {
|
|
2669
|
+
if (key === "fillGradient") {
|
|
2670
|
+
animated = true;
|
|
2671
|
+
if (value === null || typeof value !== "object" || Array.isArray(value)) {
|
|
2672
|
+
say(objectHint);
|
|
2673
|
+
continue;
|
|
2674
|
+
}
|
|
2675
|
+
const p = value;
|
|
2676
|
+
for (const k of Object.keys(p)) {
|
|
2677
|
+
if (PATCH_KEYS.includes(k)) continue;
|
|
2678
|
+
const guess = chunkTWZNOUM7_cjs.suggestName(k, PATCH_KEYS.filter((x) => x !== "type"));
|
|
2679
|
+
say(`fillGradient.${k} is not a gradient property${guess ? ` \u2014 did you mean "${guess}"?` : ""} (valid: ${PATCH_KEYS.join(", ")}); it is ignored`);
|
|
2680
|
+
}
|
|
2681
|
+
if (p.type !== void 0 && start && p.type !== start.type) say("fillGradient.type cannot change over time (linear <-> radial); it is ignored");
|
|
2682
|
+
if (p.stops !== void 0 && start) {
|
|
2683
|
+
const n = Array.isArray(p.stops) ? p.stops.length : 0;
|
|
2684
|
+
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`);
|
|
2685
|
+
}
|
|
2686
|
+
} else if (/^fillGradient\./i.test(key) || /^gradient/i.test(key)) {
|
|
2687
|
+
const tail = key.replace(/^fillGradient\./i, "").replace(/^gradient/i, "");
|
|
2688
|
+
const sub2 = tail ? tail[0].toLowerCase() + tail.slice(1) : "angle";
|
|
2689
|
+
say(`"${key}" is not an animatable property: write fillGradient: { ${PATCH_KEYS.includes(sub2) ? sub2 : "angle"} } (the whole gradient is one object) in the keyframe's to / from / set`);
|
|
2690
|
+
}
|
|
2691
|
+
}
|
|
2793
2692
|
}
|
|
2794
|
-
const [r, g, b] = fc.toArray();
|
|
2795
|
-
const amount = Number.isFinite(c.fogAmount) ? Math.min(1, Math.max(0, c.fogAmount)) : 1;
|
|
2796
|
-
return { r, g, b, near: c.fogNear, far: c.fogFar, amount };
|
|
2797
|
-
}
|
|
2798
|
-
/** Lifespan on the global timeline (valid after bindTimeline). */
|
|
2799
|
-
window() {
|
|
2800
|
-
const start = this.absoluteStart ?? this.at;
|
|
2801
|
-
return { start, end: start + (this.duration ?? 0) };
|
|
2802
2693
|
}
|
|
2803
|
-
|
|
2804
|
-
|
|
2805
|
-
// src/space/lighting.ts
|
|
2806
|
-
var LIGHT_KINDS = ["ambient", "point", "spot", "parallel"];
|
|
2807
|
-
var FALLOFFS = ["none", "smooth", "inverseSquare"];
|
|
2808
|
-
var LIGHT_PROPS = ["x", "y", "z", "lookAtX", "lookAtY", "lookAtZ", "intensity", "color", "coneAngle", "coneFeather", "radius", "falloffDistance", "shadowDarkness", "shadowDiffusion"];
|
|
2809
|
-
var MAX_LIGHTS = 8;
|
|
2810
|
-
var MAX_CASTERS = 4;
|
|
2811
|
-
var SHADOW_TAPS = 16;
|
|
2812
|
-
var FALLOFF_ID = { none: 0, smooth: 1, inverseSquare: 2 };
|
|
2813
|
-
var KIND_ID = { point: 1, spot: 2, parallel: 3 };
|
|
2814
|
-
function smoothstep(e0, e1, x) {
|
|
2815
|
-
const t = Math.min(1, Math.max(0, (x - e0) / (e1 - e0)));
|
|
2816
|
-
return t * t * (3 - 2 * t);
|
|
2817
|
-
}
|
|
2818
|
-
var DEG4 = Math.PI / 180;
|
|
2819
|
-
function norm(v) {
|
|
2820
|
-
const l = Math.hypot(v.x, v.y, v.z) || 1;
|
|
2821
|
-
return { x: v.x / l, y: v.y / l, z: v.z / l };
|
|
2694
|
+
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)");
|
|
2822
2695
|
}
|
|
2823
|
-
|
|
2824
|
-
|
|
2825
|
-
|
|
2826
|
-
|
|
2827
|
-
|
|
2828
|
-
|
|
2829
|
-
|
|
2830
|
-
|
|
2696
|
+
function tweenGradient(timeline, holder, fromPatch, toPatch, duration, ease, at, colorSpace, onChange, loop = {}) {
|
|
2697
|
+
timeline.tweenValue({
|
|
2698
|
+
holder,
|
|
2699
|
+
id: "grad",
|
|
2700
|
+
get: () => holder.grad,
|
|
2701
|
+
set: (g) => {
|
|
2702
|
+
holder.grad = g;
|
|
2703
|
+
onChange();
|
|
2704
|
+
},
|
|
2705
|
+
from: fromPatch !== void 0 ? (prev) => mergeGrad(prev, fromPatch) : void 0,
|
|
2706
|
+
to: (start, prev) => toPatch !== void 0 ? mergeGrad(start, toPatch) : prev,
|
|
2707
|
+
make: (a, b) => {
|
|
2708
|
+
const colors = a.stops.map((s, i) => colorSpace === "rgb" ? interpolateColors(s.color, b.stops[i].color) : buildColorInterp(s.color, b.stops[i].color, colorSpace));
|
|
2709
|
+
return (t) => {
|
|
2710
|
+
const l = (x, y) => x + (y - x) * t;
|
|
2711
|
+
return {
|
|
2712
|
+
type: a.type,
|
|
2713
|
+
angle: l(a.angle, b.angle),
|
|
2714
|
+
center: [l(a.center[0], b.center[0]), l(a.center[1], b.center[1])],
|
|
2715
|
+
innerRadius: l(a.innerRadius, b.innerRadius),
|
|
2716
|
+
radius: l(a.radius, b.radius),
|
|
2717
|
+
stops: a.stops.map((s, i) => ({ offset: l(s.offset, b.stops[i].offset), color: colors[i](t) }))
|
|
2718
|
+
};
|
|
2719
|
+
};
|
|
2720
|
+
},
|
|
2721
|
+
duration,
|
|
2722
|
+
ease,
|
|
2723
|
+
at,
|
|
2724
|
+
repeat: loop.repeat,
|
|
2725
|
+
yoyo: loop.yoyo,
|
|
2726
|
+
repeatDelay: loop.repeatDelay
|
|
2727
|
+
});
|
|
2831
2728
|
}
|
|
2832
|
-
|
|
2833
|
-
|
|
2834
|
-
|
|
2835
|
-
|
|
2836
|
-
|
|
2837
|
-
|
|
2838
|
-
|
|
2839
|
-
|
|
2840
|
-
ambient[2] += l.b * l.intensity;
|
|
2841
|
-
continue;
|
|
2842
|
-
}
|
|
2843
|
-
if (n >= MAX_LIGHTS) continue;
|
|
2844
|
-
const d = norm({ x: l.lookAtX - l.x, y: l.lookAtY - l.y, z: l.lookAtZ - l.z });
|
|
2845
|
-
const { cosOuter, cosInner } = coneCos(l);
|
|
2846
|
-
pos.set([l.x, l.y, l.z, KIND_ID[l.kind]], 4 * n);
|
|
2847
|
-
dir.set([d.x, d.y, d.z, cosOuter], 4 * n);
|
|
2848
|
-
col.set([l.r * l.intensity, l.g * l.intensity, l.b * l.intensity, cosInner], 4 * n);
|
|
2849
|
-
fall.set([FALLOFF_ID[l.falloff], l.radius, l.falloffDistance, l.castsShadows ? 1 : 0], 4 * n);
|
|
2850
|
-
shadow.set([l.castsShadows ? l.shadowDarkness : 0, l.shadowDiffusion, 0, 0], 4 * n);
|
|
2851
|
-
n++;
|
|
2729
|
+
var PAINT_SIZE = 512;
|
|
2730
|
+
var GradientPainter = class {
|
|
2731
|
+
constructor(size = PAINT_SIZE) {
|
|
2732
|
+
this.size = size;
|
|
2733
|
+
this.canvas.width = size;
|
|
2734
|
+
this.canvas.height = size;
|
|
2735
|
+
this.tex = PIXI.Texture.from(this.canvas);
|
|
2736
|
+
globalThis.__gradientPainters = (globalThis.__gradientPainters ?? 0) + 1;
|
|
2852
2737
|
}
|
|
2853
|
-
|
|
2854
|
-
|
|
2855
|
-
|
|
2856
|
-
|
|
2857
|
-
|
|
2858
|
-
|
|
2859
|
-
|
|
2860
|
-
|
|
2861
|
-
|
|
2862
|
-
|
|
2863
|
-
|
|
2864
|
-
|
|
2865
|
-
|
|
2866
|
-
|
|
2867
|
-
|
|
2868
|
-
|
|
2869
|
-
|
|
2870
|
-
else {
|
|
2871
|
-
const d = sub({ x: l.x, y: l.y, z: l.z }, p);
|
|
2872
|
-
dist = Math.hypot(d.x, d.y, d.z);
|
|
2873
|
-
L = { x: d.x / dist, y: d.y / dist, z: d.z / dist };
|
|
2738
|
+
size;
|
|
2739
|
+
canvas = document.createElement("canvas");
|
|
2740
|
+
tex;
|
|
2741
|
+
/** Paint `g` and return what `Graphics.fill(...)` takes. */
|
|
2742
|
+
paint(g) {
|
|
2743
|
+
const ctx = this.canvas.getContext("2d"), s = this.size;
|
|
2744
|
+
if (!ctx) return new PIXI.FillGradient(gradientOptions({ angle: g.angle, stops: g.stops.map((x) => [x.offset, x.color]) }));
|
|
2745
|
+
ctx.clearRect(0, 0, s, s);
|
|
2746
|
+
if (g.type === "radial") {
|
|
2747
|
+
paintRadial(ctx, s, { stops: g.stops.map((x) => [x.offset, x.color]), center: g.center, innerRadius: g.innerRadius, radius: g.radius });
|
|
2748
|
+
} else {
|
|
2749
|
+
const a = g.angle * Math.PI / 180, dx = Math.cos(a), dy = Math.sin(a);
|
|
2750
|
+
const h = (Math.abs(dx) + Math.abs(dy)) / 2;
|
|
2751
|
+
const grad = ctx.createLinearGradient((0.5 - dx * h) * s, (0.5 - dy * h) * s, (0.5 + dx * h) * s, (0.5 + dy * h) * s);
|
|
2752
|
+
for (const st of g.stops) grad.addColorStop(Math.min(1, Math.max(0, st.offset)), st.color);
|
|
2753
|
+
ctx.fillStyle = grad;
|
|
2754
|
+
ctx.fillRect(0, 0, s, s);
|
|
2874
2755
|
}
|
|
2875
|
-
|
|
2876
|
-
|
|
2877
|
-
|
|
2878
|
-
|
|
2879
|
-
|
|
2756
|
+
this.tex.source.update();
|
|
2757
|
+
return { texture: this.tex, textureSpace: "local" };
|
|
2758
|
+
}
|
|
2759
|
+
/** Give the texture and the canvas back (a layer that is destroyed must not leave them). */
|
|
2760
|
+
destroy() {
|
|
2761
|
+
this.tex.destroy(true);
|
|
2762
|
+
this.canvas.width = this.canvas.height = 0;
|
|
2763
|
+
globalThis.__gradientPainters = Math.max(0, (globalThis.__gradientPainters ?? 1) - 1);
|
|
2764
|
+
}
|
|
2765
|
+
};
|
|
2766
|
+
function bindGradientKeyframes(timeline, holder, keyframes, duration, offset, colorSpace, onChange) {
|
|
2767
|
+
const bag = (b) => b?.fillGradient;
|
|
2768
|
+
for (const kf of keyframes) {
|
|
2769
|
+
const at = offset + resolveAt(kf.at, duration);
|
|
2770
|
+
const setV = bag(kf.set), fromV = bag(kf.from), toV = bag(kf.to);
|
|
2771
|
+
if (setV !== void 0) {
|
|
2772
|
+
timeline.tweenValue({
|
|
2773
|
+
holder,
|
|
2774
|
+
id: "grad",
|
|
2775
|
+
get: () => holder.grad,
|
|
2776
|
+
set: (g) => {
|
|
2777
|
+
holder.grad = g;
|
|
2778
|
+
onChange();
|
|
2779
|
+
},
|
|
2780
|
+
to: (start) => mergeGrad(start, setV),
|
|
2781
|
+
make: (_a, b) => () => b,
|
|
2782
|
+
duration: 0,
|
|
2783
|
+
ease: "none",
|
|
2784
|
+
at
|
|
2785
|
+
});
|
|
2880
2786
|
}
|
|
2881
|
-
|
|
2882
|
-
|
|
2883
|
-
const { cosOuter, cosInner } = coneCos(l);
|
|
2884
|
-
cone = smoothstep(cosOuter, cosInner, -dot(L, dirLA));
|
|
2787
|
+
if (fromV !== void 0 || toV !== void 0) {
|
|
2788
|
+
tweenGradient(timeline, holder, fromV, toV, kfDuration(kf), kf.ease ?? "none", at, colorSpace, onChange, loopVars(kf));
|
|
2885
2789
|
}
|
|
2886
|
-
const k = l.intensity * ndl * att * cone;
|
|
2887
|
-
out[0] += l.r * k;
|
|
2888
|
-
out[1] += l.g * k;
|
|
2889
|
-
out[2] += l.b * k;
|
|
2890
2790
|
}
|
|
2891
|
-
return out;
|
|
2892
2791
|
}
|
|
2893
|
-
|
|
2894
|
-
|
|
2895
|
-
|
|
2896
|
-
|
|
2897
|
-
|
|
2898
|
-
}
|
|
2899
|
-
var LightSequence = class extends Sequence {
|
|
2900
|
-
color = new PIXI.Color();
|
|
2901
|
-
async build() {
|
|
2902
|
-
const w = this.parent?.width ?? this.root.width;
|
|
2903
|
-
const h = this.parent?.height ?? this.root.height;
|
|
2904
|
-
if (this.duration === void 0) this.duration = this.parent?.duration ?? this.root.duration;
|
|
2905
|
-
const c = new PIXI.Container();
|
|
2906
|
-
c.x = w * 0.3;
|
|
2907
|
-
c.y = h * 0.2;
|
|
2908
|
-
c.z = homeDistance(h, 40) * 0.6;
|
|
2909
|
-
c.lookAtX = w / 2;
|
|
2910
|
-
c.lookAtY = h / 2;
|
|
2911
|
-
c.lookAtZ = 0;
|
|
2912
|
-
c.intensity = 1;
|
|
2913
|
-
c.color = "#ffffff";
|
|
2914
|
-
c.coneAngle = 90;
|
|
2915
|
-
c.coneFeather = 0.5;
|
|
2916
|
-
c.radius = 500;
|
|
2917
|
-
c.falloffDistance = 500;
|
|
2918
|
-
c.shadowDarkness = 1;
|
|
2919
|
-
c.shadowDiffusion = 0;
|
|
2920
|
-
this.target = c;
|
|
2921
|
-
}
|
|
2922
|
-
state() {
|
|
2923
|
-
const c = this.target;
|
|
2924
|
-
try {
|
|
2925
|
-
this.color.setValue(c.color);
|
|
2926
|
-
} catch {
|
|
2927
|
-
this.color.setValue(16777215);
|
|
2928
|
-
}
|
|
2929
|
-
const [r, g, b] = this.color.toArray();
|
|
2930
|
-
return {
|
|
2931
|
-
// a kind or falloff nobody knows is the default the warning promises (the shader must never see an unknown id)
|
|
2932
|
-
kind: LIGHT_KINDS.includes(this.spec.kind) ? this.spec.kind : "point",
|
|
2933
|
-
x: c.x,
|
|
2934
|
-
y: c.y,
|
|
2935
|
-
z: c.z,
|
|
2936
|
-
lookAtX: c.lookAtX,
|
|
2937
|
-
lookAtY: c.lookAtY,
|
|
2938
|
-
lookAtZ: c.lookAtZ,
|
|
2939
|
-
r,
|
|
2940
|
-
g,
|
|
2941
|
-
b,
|
|
2942
|
-
intensity: Number.isFinite(c.intensity) ? Math.max(0, c.intensity) : 1,
|
|
2943
|
-
coneAngle: c.coneAngle,
|
|
2944
|
-
coneFeather: c.coneFeather,
|
|
2945
|
-
falloff: FALLOFFS.includes(this.spec.falloff) ? this.spec.falloff : "none",
|
|
2946
|
-
radius: c.radius,
|
|
2947
|
-
falloffDistance: c.falloffDistance,
|
|
2948
|
-
castsShadows: !!this.spec.castsShadows,
|
|
2949
|
-
shadowDarkness: Math.min(1, Math.max(0, c.shadowDarkness)),
|
|
2950
|
-
shadowDiffusion: Math.max(0, c.shadowDiffusion)
|
|
2951
|
-
};
|
|
2952
|
-
}
|
|
2953
|
-
window() {
|
|
2954
|
-
const start = this.absoluteStart ?? this.at;
|
|
2955
|
-
return { start, end: start + (this.duration ?? 0) };
|
|
2956
|
-
}
|
|
2957
|
-
};
|
|
2958
|
-
|
|
2959
|
-
// src/core/revertibleSet.ts
|
|
2960
|
-
function revertibleSet(timeline, at, read2, write2, value, property) {
|
|
2961
|
-
timeline.setValue(property?.[0] ?? read2, property?.[1] ?? "set", at, read2, write2, value);
|
|
2962
|
-
}
|
|
2963
|
-
|
|
2964
|
-
// src/expr/colorInterp.ts
|
|
2965
|
-
var CHROMA_FLOOR = 0.03;
|
|
2966
|
-
var CHROMA_FULL = 0.08;
|
|
2967
|
-
function buildColorInterp(from, to, space) {
|
|
2968
|
-
const fromRGBA = parseToRGBA(from);
|
|
2969
|
-
const toRGBA = parseToRGBA(to);
|
|
2970
|
-
const fromOk = rgbToOklab(fromRGBA);
|
|
2971
|
-
const toOk = rgbToOklab(toRGBA);
|
|
2972
|
-
if (space === "oklab") {
|
|
2973
|
-
return (t) => {
|
|
2974
|
-
const L = lerp(fromOk.L, toOk.L, t);
|
|
2975
|
-
const a = lerp(fromOk.a, toOk.a, t);
|
|
2976
|
-
const b = lerp(fromOk.b, toOk.b, t);
|
|
2977
|
-
const alpha = lerp(fromRGBA.a, toRGBA.a, t);
|
|
2978
|
-
return rgbaString(oklabToRgb({ L, a, b }), alpha);
|
|
2979
|
-
};
|
|
2980
|
-
}
|
|
2981
|
-
const fromLCH = oklabToOklch(fromOk);
|
|
2982
|
-
const toLCH = oklabToOklch(toOk);
|
|
2983
|
-
const fromHue = fromLCH.h, toHue = toLCH.h;
|
|
2984
|
-
fromLCH.h = borrowHue(fromHue, fromLCH.C, toHue);
|
|
2985
|
-
toLCH.h = borrowHue(toHue, toLCH.C, fromHue);
|
|
2986
|
-
const hueDelta = shortestHueDelta(fromLCH.h, toLCH.h);
|
|
2987
|
-
return (t) => {
|
|
2988
|
-
const L = lerp(fromLCH.L, toLCH.L, t);
|
|
2989
|
-
const C = lerp(fromLCH.C, toLCH.C, t);
|
|
2990
|
-
const h = fromLCH.h + hueDelta * t;
|
|
2991
|
-
const alpha = lerp(fromRGBA.a, toRGBA.a, t);
|
|
2992
|
-
const ab = oklchToOklab({ L, C, h });
|
|
2993
|
-
return rgbaString(oklabToRgb(ab), alpha);
|
|
2994
|
-
};
|
|
2995
|
-
}
|
|
2996
|
-
function borrowHue(own, chroma, other) {
|
|
2997
|
-
const u = Math.min(1, Math.max(0, (chroma - CHROMA_FLOOR) / (CHROMA_FULL - CHROMA_FLOOR)));
|
|
2998
|
-
const keep = u * u * (3 - 2 * u);
|
|
2999
|
-
return own + shortestHueDelta(own, other) * (1 - keep);
|
|
3000
|
-
}
|
|
3001
|
-
function parseToRGBA(input) {
|
|
3002
|
-
if (typeof input === "number") {
|
|
3003
|
-
return { r: (input >> 16 & 255) / 255, g: (input >> 8 & 255) / 255, b: (input & 255) / 255, a: 1 };
|
|
3004
|
-
}
|
|
3005
|
-
const s = input.trim();
|
|
3006
|
-
if (s.startsWith("#")) return parseHex(s);
|
|
3007
|
-
if (s.startsWith("rgb")) return parseRgbFunc(s);
|
|
3008
|
-
return { r: 0, g: 0, b: 0, a: 1 };
|
|
3009
|
-
}
|
|
3010
|
-
function parseHex(s) {
|
|
3011
|
-
const hex = s.slice(1);
|
|
3012
|
-
let r = 0, g = 0, b = 0, a = 1;
|
|
3013
|
-
if (hex.length === 3 || hex.length === 4) {
|
|
3014
|
-
r = parseInt(hex[0] + hex[0], 16) / 255;
|
|
3015
|
-
g = parseInt(hex[1] + hex[1], 16) / 255;
|
|
3016
|
-
b = parseInt(hex[2] + hex[2], 16) / 255;
|
|
3017
|
-
if (hex.length === 4) a = parseInt(hex[3] + hex[3], 16) / 255;
|
|
3018
|
-
} else if (hex.length === 6 || hex.length === 8) {
|
|
3019
|
-
r = parseInt(hex.slice(0, 2), 16) / 255;
|
|
3020
|
-
g = parseInt(hex.slice(2, 4), 16) / 255;
|
|
3021
|
-
b = parseInt(hex.slice(4, 6), 16) / 255;
|
|
3022
|
-
if (hex.length === 8) a = parseInt(hex.slice(6, 8), 16) / 255;
|
|
3023
|
-
}
|
|
3024
|
-
return { r, g, b, a };
|
|
3025
|
-
}
|
|
3026
|
-
function parseRgbFunc(s) {
|
|
3027
|
-
const inner = s.replace(/^rgba?\(/, "").replace(/\)$/, "");
|
|
3028
|
-
const parts = inner.split(/[,\s/]+/).filter(Boolean).map(parseFloat);
|
|
3029
|
-
return {
|
|
3030
|
-
r: (parts[0] ?? 0) / 255,
|
|
3031
|
-
g: (parts[1] ?? 0) / 255,
|
|
3032
|
-
b: (parts[2] ?? 0) / 255,
|
|
3033
|
-
a: parts.length > 3 ? parts[3] ?? 1 : 1
|
|
3034
|
-
};
|
|
3035
|
-
}
|
|
3036
|
-
function rgbaString(rgb, alpha) {
|
|
3037
|
-
const r = Math.round(clamp01(rgb.r) * 255);
|
|
3038
|
-
const g = Math.round(clamp01(rgb.g) * 255);
|
|
3039
|
-
const b = Math.round(clamp01(rgb.b) * 255);
|
|
3040
|
-
return `rgba(${r},${g},${b},${alpha})`;
|
|
3041
|
-
}
|
|
3042
|
-
function srgbToLinear(c) {
|
|
3043
|
-
return c <= 0.04045 ? c / 12.92 : Math.pow((c + 0.055) / 1.055, 2.4);
|
|
3044
|
-
}
|
|
3045
|
-
function linearToSrgb(c) {
|
|
3046
|
-
return c <= 31308e-7 ? 12.92 * c : 1.055 * Math.pow(c, 1 / 2.4) - 0.055;
|
|
3047
|
-
}
|
|
3048
|
-
function rgbToOklab(rgba) {
|
|
3049
|
-
const r = srgbToLinear(rgba.r);
|
|
3050
|
-
const g = srgbToLinear(rgba.g);
|
|
3051
|
-
const b = srgbToLinear(rgba.b);
|
|
3052
|
-
const l = 0.4122214708 * r + 0.5363325363 * g + 0.0514459929 * b;
|
|
3053
|
-
const m = 0.2119034982 * r + 0.6806995451 * g + 0.1073969566 * b;
|
|
3054
|
-
const s = 0.0883024619 * r + 0.2817188376 * g + 0.6299787005 * b;
|
|
3055
|
-
const l_ = Math.cbrt(l);
|
|
3056
|
-
const m_ = Math.cbrt(m);
|
|
3057
|
-
const s_ = Math.cbrt(s);
|
|
3058
|
-
return {
|
|
3059
|
-
L: 0.2104542553 * l_ + 0.793617785 * m_ - 0.0040720468 * s_,
|
|
3060
|
-
a: 1.9779984951 * l_ - 2.428592205 * m_ + 0.4505937099 * s_,
|
|
3061
|
-
b: 0.0259040371 * l_ + 0.7827717662 * m_ - 0.808675766 * s_
|
|
3062
|
-
};
|
|
3063
|
-
}
|
|
3064
|
-
function oklabToRgb(lab) {
|
|
3065
|
-
const l_ = lab.L + 0.3963377774 * lab.a + 0.2158037573 * lab.b;
|
|
3066
|
-
const m_ = lab.L - 0.1055613458 * lab.a - 0.0638541728 * lab.b;
|
|
3067
|
-
const s_ = lab.L - 0.0894841775 * lab.a - 1.291485548 * lab.b;
|
|
3068
|
-
const l = l_ * l_ * l_;
|
|
3069
|
-
const m = m_ * m_ * m_;
|
|
3070
|
-
const s = s_ * s_ * s_;
|
|
3071
|
-
return {
|
|
3072
|
-
r: linearToSrgb(4.0767416621 * l - 3.3077115913 * m + 0.2309699292 * s),
|
|
3073
|
-
g: linearToSrgb(-1.2684380046 * l + 2.6097574011 * m - 0.3413193965 * s),
|
|
3074
|
-
b: linearToSrgb(-0.0041960863 * l - 0.7034186147 * m + 1.707614701 * s)
|
|
3075
|
-
};
|
|
3076
|
-
}
|
|
3077
|
-
function oklabToOklch(lab) {
|
|
3078
|
-
return { L: lab.L, C: Math.hypot(lab.a, lab.b), h: Math.atan2(lab.b, lab.a) };
|
|
3079
|
-
}
|
|
3080
|
-
function oklchToOklab(lch) {
|
|
3081
|
-
return { L: lch.L, a: lch.C * Math.cos(lch.h), b: lch.C * Math.sin(lch.h) };
|
|
3082
|
-
}
|
|
3083
|
-
function lerp(a, b, t) {
|
|
3084
|
-
return a + (b - a) * t;
|
|
3085
|
-
}
|
|
3086
|
-
function clamp01(v) {
|
|
3087
|
-
return v < 0 ? 0 : v > 1 ? 1 : v;
|
|
3088
|
-
}
|
|
3089
|
-
function shortestHueDelta(from, to) {
|
|
3090
|
-
const TWO_PI = Math.PI * 2;
|
|
3091
|
-
let d = (to - from) % TWO_PI;
|
|
3092
|
-
if (d > Math.PI) d -= TWO_PI;
|
|
3093
|
-
if (d < -Math.PI) d += TWO_PI;
|
|
3094
|
-
return d;
|
|
2792
|
+
var hasGradientKeys = (keyframes) => (keyframes ?? []).some((kf) => [kf.set, kf.to, kf.from].some((b) => b && b.fillGradient !== void 0));
|
|
2793
|
+
|
|
2794
|
+
// src/core/revertibleSet.ts
|
|
2795
|
+
function revertibleSet(timeline, at, read2, write2, value, property) {
|
|
2796
|
+
timeline.setValue(property?.[0] ?? read2, property?.[1] ?? "set", at, read2, write2, value);
|
|
3095
2797
|
}
|
|
3096
2798
|
|
|
3097
2799
|
// src/expr/colorTween.ts
|
|
@@ -3119,557 +2821,1058 @@ function tweenColor(timeline, target, key, fromValue, toValue, duration, ease, a
|
|
|
3119
2821
|
});
|
|
3120
2822
|
}
|
|
3121
2823
|
|
|
3122
|
-
// src/
|
|
3123
|
-
var
|
|
3124
|
-
|
|
3125
|
-
|
|
3126
|
-
|
|
3127
|
-
|
|
3128
|
-
|
|
3129
|
-
|
|
3130
|
-
|
|
3131
|
-
|
|
3132
|
-
|
|
3133
|
-
|
|
3134
|
-
|
|
2824
|
+
// src/text/styleKeys.ts
|
|
2825
|
+
var STYLE_OPAQUE_KEYS = [
|
|
2826
|
+
"fontFamily",
|
|
2827
|
+
"fill",
|
|
2828
|
+
"align",
|
|
2829
|
+
"fontStyle",
|
|
2830
|
+
"fontWeight",
|
|
2831
|
+
"fontVariant",
|
|
2832
|
+
"textBaseline",
|
|
2833
|
+
"whiteSpace",
|
|
2834
|
+
"lineJoin",
|
|
2835
|
+
"join",
|
|
2836
|
+
"cap",
|
|
2837
|
+
"color",
|
|
2838
|
+
"stroke"
|
|
2839
|
+
];
|
|
2840
|
+
var TEXT_STYLE_DEFAULTS = {
|
|
2841
|
+
fontFamily: "Arial",
|
|
2842
|
+
fontSize: 36,
|
|
2843
|
+
fill: "#ffffff",
|
|
2844
|
+
align: "center"
|
|
2845
|
+
};
|
|
2846
|
+
|
|
2847
|
+
// src/sequences/Text.ts
|
|
2848
|
+
function formatValue(v, f) {
|
|
2849
|
+
const fixed = v.toFixed(Math.max(0, Math.floor(f?.decimals ?? 0)));
|
|
2850
|
+
const pad = Math.max(0, Math.floor(f?.pad ?? 0));
|
|
2851
|
+
if (!f?.grouping && !pad) return fixed;
|
|
2852
|
+
const [signed, frac] = fixed.split(".");
|
|
2853
|
+
const sign = signed.startsWith("-") ? "-" : "";
|
|
2854
|
+
let int = sign ? signed.slice(1) : signed;
|
|
2855
|
+
if (pad) int = int.padStart(pad, "0");
|
|
2856
|
+
if (f?.grouping) int = int.replace(/\B(?=(\d{3})+(?!\d))/g, ",");
|
|
2857
|
+
return sign + int + (frac !== void 0 ? "." + frac : "");
|
|
2858
|
+
}
|
|
2859
|
+
var TextSequence = class extends Sequence {
|
|
2860
|
+
/** `value`: the number for the `{value}` placeholder; `visibleChars`: how many characters show (typewriter). Both tweened by keyframes. */
|
|
2861
|
+
_counters = { value: 0, visibleChars: 0 };
|
|
2862
|
+
/** The string now on the layer (before `{value}` / `visibleChars`): `text`, or the last `set: { text }`. */
|
|
2863
|
+
_template = "";
|
|
2864
|
+
/** `visibleChars` is in play (initial or animated): otherwise the whole text shows. */
|
|
2865
|
+
_typed = false;
|
|
2866
|
+
_lastText = "";
|
|
2867
|
+
/** A gradient fill for the text (`fillGradient`, static or animated): rebuilt as a FillGradient on each change (the text is re-rasterised). */
|
|
2868
|
+
_grad = null;
|
|
2869
|
+
_fillGradient = null;
|
|
2870
|
+
_applyGradient() {
|
|
2871
|
+
const g = this._grad.grad;
|
|
2872
|
+
const next = new PIXI.FillGradient(gradientOptions({ angle: g.angle, stops: g.stops.map((s) => [s.offset, s.color]) }));
|
|
2873
|
+
this.target.style.fill = next;
|
|
2874
|
+
this._fillGradient?.destroy();
|
|
2875
|
+
this._fillGradient = next;
|
|
3135
2876
|
}
|
|
3136
|
-
|
|
3137
|
-
|
|
3138
|
-
|
|
3139
|
-
|
|
3140
|
-
|
|
3141
|
-
|
|
3142
|
-
|
|
3143
|
-
|
|
3144
|
-
|
|
3145
|
-
|
|
3146
|
-
|
|
3147
|
-
|
|
3148
|
-
|
|
3149
|
-
|
|
3150
|
-
|
|
3151
|
-
|
|
3152
|
-
|
|
3153
|
-
|
|
3154
|
-
|
|
3155
|
-
|
|
3156
|
-
|
|
3157
|
-
|
|
3158
|
-
|
|
3159
|
-
|
|
3160
|
-
|
|
3161
|
-
|
|
3162
|
-
|
|
3163
|
-
|
|
3164
|
-
|
|
3165
|
-
|
|
3166
|
-
|
|
3167
|
-
|
|
3168
|
-
|
|
3169
|
-
|
|
3170
|
-
|
|
3171
|
-
|
|
3172
|
-
|
|
3173
|
-
|
|
3174
|
-
|
|
3175
|
-
|
|
3176
|
-
|
|
3177
|
-
|
|
2877
|
+
destroy() {
|
|
2878
|
+
super.destroy();
|
|
2879
|
+
this._fillGradient?.destroy();
|
|
2880
|
+
this._fillGradient = null;
|
|
2881
|
+
}
|
|
2882
|
+
/** @internal A `spans` group that types over several pieces: this piece shows its first `n` characters (the piece was built typed). */
|
|
2883
|
+
setVisibleChars(n) {
|
|
2884
|
+
this._counters.visibleChars = n;
|
|
2885
|
+
this._refreshText();
|
|
2886
|
+
}
|
|
2887
|
+
/** A typewriter that has typed nothing yet: the layer is empty on purpose (inspect must not call that "no size"). */
|
|
2888
|
+
get showsNothingYet() {
|
|
2889
|
+
return this._typed && this._lastText === "" && this._template !== "";
|
|
2890
|
+
}
|
|
2891
|
+
/** Rewrite the displayed string from the template, the current `value` and `visibleChars`. */
|
|
2892
|
+
_refreshText() {
|
|
2893
|
+
let next = this._template.includes("{value}") ? this._template.split("{value}").join(formatValue(this._counters.value, this.spec.format)) : this._template;
|
|
2894
|
+
if (this._typed) next = Array.from(next).slice(0, Math.max(0, Math.floor(this._counters.visibleChars))).join("");
|
|
2895
|
+
if (next === this._lastText) return;
|
|
2896
|
+
this._lastText = next;
|
|
2897
|
+
this.target.text = next;
|
|
2898
|
+
}
|
|
2899
|
+
async build() {
|
|
2900
|
+
const baseStyle = { ...TEXT_STYLE_DEFAULTS };
|
|
2901
|
+
const initialProps = this.spec.initial ?? {};
|
|
2902
|
+
this._template = String(initialProps.text ?? this.spec.text ?? "");
|
|
2903
|
+
const text = new PIXI.Text({
|
|
2904
|
+
text: this._template,
|
|
2905
|
+
style: baseStyle,
|
|
2906
|
+
label: this.spec.name
|
|
2907
|
+
});
|
|
2908
|
+
text.cullable = true;
|
|
2909
|
+
this.target = text;
|
|
2910
|
+
this.intrinsicWidth = text.width;
|
|
2911
|
+
this.intrinsicHeight = text.height;
|
|
2912
|
+
if (this.duration === void 0) {
|
|
2913
|
+
this.duration = this.parent?.duration ?? this.root.duration;
|
|
2914
|
+
}
|
|
2915
|
+
if (this.spec.style) {
|
|
2916
|
+
const scope2 = this.scope();
|
|
2917
|
+
const resolved = normalizeProps(
|
|
2918
|
+
this.spec.style,
|
|
2919
|
+
scope2,
|
|
2920
|
+
{ skipKeys: STYLE_OPAQUE_KEYS }
|
|
2921
|
+
);
|
|
2922
|
+
const unset = Object.keys(resolved).filter((k) => resolved[k] === void 0);
|
|
2923
|
+
if (unset.length) console.warn(`pixi-effects: ${chunkGL2AQFLQ_cjs.describeLayer(this.spec)}: ${unset.map((k) => `style.${k}`).join(", ")} ${unset.length > 1 ? "are" : "is"} undefined (a variable that was never set?), so ${unset.length > 1 ? "they are" : "it is"} ignored and the default is used: omit the key instead`);
|
|
2924
|
+
const outline = resolved.stroke;
|
|
2925
|
+
if (outline && typeof outline === "object" && !("join" in outline) && !("lineJoin" in outline)) resolved.stroke = { ...outline, join: "round" };
|
|
2926
|
+
for (const k of Object.keys(resolved)) {
|
|
2927
|
+
if (unset.includes(k)) continue;
|
|
2928
|
+
text.style[k] = resolved[k];
|
|
3178
2929
|
}
|
|
2930
|
+
this.intrinsicWidth = text.width;
|
|
2931
|
+
this.intrinsicHeight = text.height;
|
|
3179
2932
|
}
|
|
3180
|
-
this.
|
|
3181
|
-
const
|
|
3182
|
-
if (
|
|
3183
|
-
|
|
3184
|
-
|
|
3185
|
-
|
|
2933
|
+
validateGradientKeyframes(this.spec, chunkGL2AQFLQ_cjs.describeLayer(this.spec), void 0, "text");
|
|
2934
|
+
const gradientSpec = this.spec.fillGradient ?? initialProps.fillGradient;
|
|
2935
|
+
if (gradientSpec) {
|
|
2936
|
+
this._grad = { grad: gradStateFrom(gradientSpec) };
|
|
2937
|
+
this._applyGradient();
|
|
2938
|
+
}
|
|
2939
|
+
const scope = this.scope();
|
|
2940
|
+
if (initialProps.value !== void 0) this._counters.value = resolveNumber(initialProps.value, scope);
|
|
2941
|
+
this._typed = initialProps.visibleChars !== void 0 || animates(this.spec.keyframes, "visibleChars");
|
|
2942
|
+
if (initialProps.visibleChars !== void 0) this._counters.visibleChars = resolveNumber(initialProps.visibleChars, scope);
|
|
2943
|
+
const typed = this._typed;
|
|
2944
|
+
this._typed = false;
|
|
2945
|
+
this._refreshText();
|
|
2946
|
+
if (this._lastText !== "") {
|
|
2947
|
+
this.intrinsicWidth = text.width;
|
|
2948
|
+
this.intrinsicHeight = text.height;
|
|
2949
|
+
}
|
|
2950
|
+
this._typed = typed;
|
|
2951
|
+
this._refreshText();
|
|
2952
|
+
this.buildFilters();
|
|
2953
|
+
}
|
|
2954
|
+
bindTimeline(timeline, offset = 0) {
|
|
2955
|
+
if (!this.target) return;
|
|
2956
|
+
const colorSpace = this.spec.colorSpace ?? "rgb";
|
|
2957
|
+
const stripped = stripKeys(this.spec, ["fill", "value", "text", "visibleChars", "fillGradient"]);
|
|
2958
|
+
runSuperWithStrippedSpec(this, stripped, timeline, offset);
|
|
2959
|
+
const keyframes = this.spec.keyframes ?? [];
|
|
2960
|
+
const origin = offset + this.at;
|
|
2961
|
+
bindFillKeyframes(timeline, this.target, keyframes, this.duration, origin, colorSpace);
|
|
2962
|
+
if (this._grad) bindGradientKeyframes(timeline, this._grad, keyframes, this.duration, origin, colorSpace, () => this._applyGradient());
|
|
2963
|
+
const refresh = () => this._refreshText();
|
|
2964
|
+
bindCounterKeyframes(timeline, this._counters, "value", refresh, keyframes, this.duration, origin, this.scope());
|
|
2965
|
+
bindCounterKeyframes(timeline, this._counters, "visibleChars", refresh, keyframes, this.duration, origin, this.scope());
|
|
2966
|
+
bindTextKeyframes(timeline, keyframes, this.duration, origin, () => this._template, (t) => {
|
|
2967
|
+
this._template = t;
|
|
2968
|
+
refresh();
|
|
2969
|
+
}, chunkGL2AQFLQ_cjs.describeLayer(this.spec));
|
|
3186
2970
|
}
|
|
3187
2971
|
};
|
|
3188
|
-
function
|
|
3189
|
-
|
|
3190
|
-
|
|
3191
|
-
|
|
3192
|
-
|
|
3193
|
-
|
|
3194
|
-
|
|
3195
|
-
changed = true;
|
|
3196
|
-
continue;
|
|
3197
|
-
}
|
|
3198
|
-
out[k] = props[k];
|
|
2972
|
+
function runSuperWithStrippedSpec(inst, strippedSpec, timeline, offset) {
|
|
2973
|
+
const originalSpec = inst.spec;
|
|
2974
|
+
inst.spec = strippedSpec;
|
|
2975
|
+
try {
|
|
2976
|
+
Sequence.prototype.bindTimeline.call(inst, timeline, offset);
|
|
2977
|
+
} finally {
|
|
2978
|
+
inst.spec = originalSpec;
|
|
3199
2979
|
}
|
|
3200
|
-
return changed ? out : props;
|
|
3201
|
-
}
|
|
3202
|
-
function stripKeysInKeyframe(kf, keys) {
|
|
3203
|
-
return {
|
|
3204
|
-
...kf,
|
|
3205
|
-
set: stripKeys(kf.set, keys),
|
|
3206
|
-
to: stripKeys(kf.to, keys),
|
|
3207
|
-
from: stripKeys(kf.from, keys)
|
|
3208
|
-
};
|
|
3209
|
-
}
|
|
3210
|
-
|
|
3211
|
-
// src/sequences/gradient.ts
|
|
3212
|
-
function cssColor(c) {
|
|
3213
|
-
return typeof c === "number" ? "#" + c.toString(16).padStart(6, "0") : c;
|
|
3214
|
-
}
|
|
3215
|
-
function normalizedStops(g) {
|
|
3216
|
-
const stops = g.stops ?? [];
|
|
3217
|
-
if (stops.length < 2) throw new Error('pixi-effects: fillGradient needs at least two colour stops, e.g. stops: [[0, "#000"], [1, "#fff"]]');
|
|
3218
|
-
return stops.map((s) => Array.isArray(s) ? { offset: s[0], color: s[1] } : { offset: s.offset, color: s.color });
|
|
3219
2980
|
}
|
|
3220
|
-
function
|
|
3221
|
-
const colorStops = normalizedStops(g);
|
|
3222
|
-
const a = (g.angle ?? 90) * Math.PI / 180;
|
|
3223
|
-
const dx = Math.cos(a), dy = Math.sin(a);
|
|
3224
|
-
const h = (Math.abs(dx) + Math.abs(dy)) / 2;
|
|
2981
|
+
function stripKeys(spec, keys) {
|
|
3225
2982
|
return {
|
|
3226
|
-
|
|
3227
|
-
|
|
3228
|
-
|
|
3229
|
-
|
|
3230
|
-
|
|
2983
|
+
...spec,
|
|
2984
|
+
initial: stripProps(spec.initial, keys),
|
|
2985
|
+
keyframes: spec.keyframes ? spec.keyframes.map((kf) => ({
|
|
2986
|
+
...kf,
|
|
2987
|
+
set: stripProps(kf.set, keys),
|
|
2988
|
+
to: stripProps(kf.to, keys),
|
|
2989
|
+
from: stripProps(kf.from, keys)
|
|
2990
|
+
})) : void 0
|
|
3231
2991
|
};
|
|
3232
2992
|
}
|
|
3233
|
-
function
|
|
3234
|
-
|
|
3235
|
-
|
|
3236
|
-
const
|
|
3237
|
-
for (const
|
|
3238
|
-
|
|
3239
|
-
ctx.fillRect(0, 0, size, size);
|
|
2993
|
+
function stripProps(props, keys) {
|
|
2994
|
+
if (!props) return props;
|
|
2995
|
+
if (!keys.some((k) => k in props)) return props;
|
|
2996
|
+
const out = {};
|
|
2997
|
+
for (const k of Object.keys(props)) if (!keys.includes(k)) out[k] = props[k];
|
|
2998
|
+
return out;
|
|
3240
2999
|
}
|
|
3241
|
-
|
|
3242
|
-
|
|
3243
|
-
|
|
3244
|
-
|
|
3245
|
-
return {
|
|
3246
|
-
type: g.type ?? "linear",
|
|
3247
|
-
angle: g.angle ?? 90,
|
|
3248
|
-
center: [...g.center ?? [0.5, 0.5]],
|
|
3249
|
-
innerRadius: g.innerRadius ?? 0,
|
|
3250
|
-
radius: g.radius ?? 0.5,
|
|
3251
|
-
stops: (g.stops ?? []).map((s) => Array.isArray(s) ? { offset: s[0], color: cssColor(s[1]) } : { offset: s.offset, color: cssColor(s.color) })
|
|
3252
|
-
};
|
|
3000
|
+
function resolveNumber(v, scope) {
|
|
3001
|
+
if (typeof v === "number") return v;
|
|
3002
|
+
const out = normalizeProps({ v }, scope).v;
|
|
3003
|
+
return typeof out === "number" ? out : Number(out) || 0;
|
|
3253
3004
|
}
|
|
3254
|
-
function
|
|
3255
|
-
const
|
|
3256
|
-
|
|
3257
|
-
|
|
3258
|
-
|
|
3259
|
-
|
|
3260
|
-
|
|
3261
|
-
|
|
3262
|
-
|
|
3263
|
-
const
|
|
3264
|
-
if (
|
|
3005
|
+
function bindCounterKeyframes(timeline, state, key, refresh, keyframes, parentDuration, origin, scope) {
|
|
3006
|
+
for (const kf of keyframes) {
|
|
3007
|
+
const setV = kf.set?.[key];
|
|
3008
|
+
const fromV = kf.from?.[key];
|
|
3009
|
+
const toV = kf.to?.[key];
|
|
3010
|
+
if (setV === void 0 && fromV === void 0 && toV === void 0) continue;
|
|
3011
|
+
const at = origin + resolveAt(kf.at, parentDuration);
|
|
3012
|
+
const duration = kfDuration(kf);
|
|
3013
|
+
const ease = kf.ease ?? "none";
|
|
3014
|
+
const loop = loopVars(kf);
|
|
3015
|
+
if (setV !== void 0) {
|
|
3016
|
+
const v = resolveNumber(setV, scope);
|
|
3017
|
+
revertibleSet(timeline, at, () => state[key], (n) => {
|
|
3018
|
+
state[key] = n;
|
|
3019
|
+
refresh();
|
|
3020
|
+
}, v, [state, key]);
|
|
3021
|
+
}
|
|
3022
|
+
if (toV !== void 0 && fromV !== void 0) {
|
|
3023
|
+
timeline.fromTo(
|
|
3024
|
+
state,
|
|
3025
|
+
{ [key]: resolveNumber(fromV, scope) },
|
|
3026
|
+
{ [key]: resolveNumber(toV, scope), duration, ease, ...loop, onUpdate: refresh },
|
|
3027
|
+
at
|
|
3028
|
+
);
|
|
3029
|
+
} else if (toV !== void 0) {
|
|
3030
|
+
timeline.to(state, { [key]: resolveNumber(toV, scope), duration, ease, ...loop, onUpdate: refresh }, at);
|
|
3031
|
+
} else if (fromV !== void 0) {
|
|
3032
|
+
timeline.from(state, { [key]: resolveNumber(fromV, scope), duration, ease, ...loop, onUpdate: refresh }, at);
|
|
3033
|
+
}
|
|
3265
3034
|
}
|
|
3266
|
-
return out;
|
|
3267
3035
|
}
|
|
3268
|
-
|
|
3269
|
-
|
|
3270
|
-
|
|
3271
|
-
|
|
3272
|
-
|
|
3273
|
-
|
|
3274
|
-
|
|
3036
|
+
function bindTextKeyframes(timeline, keyframes, parentDuration, origin, read2, write2, who) {
|
|
3037
|
+
for (const kf of keyframes) {
|
|
3038
|
+
for (const [what, props] of [["to", kf.to], ["from", kf.from]]) {
|
|
3039
|
+
if (props && props.text !== void 0) {
|
|
3040
|
+
console.warn(`pixi-effects: ${who}: a keyframe's ${what}: { text } cannot tween a string: use set: { text: '\u2026' } at the time it should change`);
|
|
3041
|
+
}
|
|
3042
|
+
}
|
|
3043
|
+
const t = kf.set?.text;
|
|
3044
|
+
if (t === void 0) continue;
|
|
3045
|
+
revertibleSet(timeline, origin + resolveAt(kf.at, parentDuration), read2, write2, String(t));
|
|
3046
|
+
}
|
|
3047
|
+
}
|
|
3048
|
+
function animates(keyframes, key) {
|
|
3049
|
+
return (keyframes ?? []).some((kf) => [kf.set, kf.to, kf.from].some((p) => p && p[key] !== void 0));
|
|
3050
|
+
}
|
|
3051
|
+
function bindFillKeyframes(timeline, text, keyframes, parentDuration, offset, colorSpace) {
|
|
3052
|
+
const state = { fill: text.style.fill };
|
|
3053
|
+
const writeFill = () => {
|
|
3054
|
+
text.style.fill = state.fill;
|
|
3055
|
+
};
|
|
3056
|
+
for (const kf of keyframes) {
|
|
3057
|
+
const at = offset + resolveAt(kf.at, parentDuration);
|
|
3058
|
+
const duration = kfDuration(kf);
|
|
3059
|
+
const ease = kf.ease ?? "none";
|
|
3060
|
+
const setFill = pickFill(kf.set);
|
|
3061
|
+
const fromFill = pickFill(kf.from);
|
|
3062
|
+
const toFill = pickFill(kf.to);
|
|
3063
|
+
if (setFill !== void 0) {
|
|
3064
|
+
revertibleSet(timeline, at, () => state.fill, (c) => {
|
|
3065
|
+
state.fill = c;
|
|
3066
|
+
writeFill();
|
|
3067
|
+
}, setFill, [state, "fill"]);
|
|
3068
|
+
}
|
|
3069
|
+
if (toFill !== void 0) {
|
|
3070
|
+
tweenColor(
|
|
3071
|
+
timeline,
|
|
3072
|
+
state,
|
|
3073
|
+
"fill",
|
|
3074
|
+
fromFill,
|
|
3075
|
+
toFill,
|
|
3076
|
+
duration,
|
|
3077
|
+
ease,
|
|
3078
|
+
at,
|
|
3079
|
+
colorSpace,
|
|
3080
|
+
writeFill,
|
|
3081
|
+
loopVars(kf)
|
|
3082
|
+
);
|
|
3275
3083
|
}
|
|
3276
|
-
};
|
|
3277
|
-
const startSpec = spec.fillGradient ?? spec.initial?.fillGradient;
|
|
3278
|
-
const start = startSpec && typeof startSpec === "object" && Array.isArray(startSpec.stops) ? gradStateFrom(startSpec) : null;
|
|
3279
|
-
let animated = false;
|
|
3280
|
-
if (kind === "text") {
|
|
3281
|
-
const radial = (g) => !!g && typeof g === "object" && ["type", "center", "innerRadius", "radius"].some((k) => g[k] !== void 0 && !(k === "type" && g.type === "linear"));
|
|
3282
|
-
const asked = radial(startSpec) || (spec.keyframes ?? []).some((kf) => [kf.set, kf.to, kf.from].some((b) => radial(b?.fillGradient)));
|
|
3283
|
-
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");
|
|
3284
3084
|
}
|
|
3085
|
+
}
|
|
3086
|
+
function pickFill(props) {
|
|
3087
|
+
if (!props) return void 0;
|
|
3088
|
+
const v = props.fill;
|
|
3089
|
+
if (typeof v === "string" || typeof v === "number") return v;
|
|
3090
|
+
return void 0;
|
|
3091
|
+
}
|
|
3092
|
+
|
|
3093
|
+
// src/core/remap.ts
|
|
3094
|
+
var BAGS = ["set", "to", "from"];
|
|
3095
|
+
function timeRemapOf(spec, prop = "time") {
|
|
3096
|
+
const hasInitial = !!spec.initial && "time" in spec.initial;
|
|
3097
|
+
const hasKf = (spec.keyframes ?? []).some((kf) => BAGS.some((b) => kf[b] && "time" in kf[b]));
|
|
3098
|
+
const speed = typeof spec.speed === "number" && Number.isFinite(spec.speed) && spec.speed !== 0 ? spec.speed : void 0;
|
|
3099
|
+
if (!hasInitial && !hasKf && speed === void 0) return null;
|
|
3100
|
+
const timeKfs = [];
|
|
3101
|
+
const restKfs = [];
|
|
3285
3102
|
for (const kf of spec.keyframes ?? []) {
|
|
3286
|
-
|
|
3287
|
-
|
|
3288
|
-
|
|
3289
|
-
|
|
3290
|
-
|
|
3291
|
-
|
|
3292
|
-
|
|
3293
|
-
|
|
3294
|
-
}
|
|
3295
|
-
const p = value;
|
|
3296
|
-
for (const k of Object.keys(p)) {
|
|
3297
|
-
if (PATCH_KEYS.includes(k)) continue;
|
|
3298
|
-
const guess = chunkTWZNOUM7_cjs.suggestName(k, PATCH_KEYS.filter((x) => x !== "type"));
|
|
3299
|
-
say(`fillGradient.${k} is not a gradient property${guess ? ` \u2014 did you mean "${guess}"?` : ""} (valid: ${PATCH_KEYS.join(", ")}); it is ignored`);
|
|
3300
|
-
}
|
|
3301
|
-
if (p.type !== void 0 && start && p.type !== start.type) say("fillGradient.type cannot change over time (linear <-> radial); it is ignored");
|
|
3302
|
-
if (p.stops !== void 0 && start) {
|
|
3303
|
-
const n = Array.isArray(p.stops) ? p.stops.length : 0;
|
|
3304
|
-
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`);
|
|
3305
|
-
}
|
|
3306
|
-
} else if (/^fillGradient\./i.test(key) || /^gradient/i.test(key)) {
|
|
3307
|
-
const tail = key.replace(/^fillGradient\./i, "").replace(/^gradient/i, "");
|
|
3308
|
-
const sub2 = tail ? tail[0].toLowerCase() + tail.slice(1) : "angle";
|
|
3309
|
-
say(`"${key}" is not an animatable property: write fillGradient: { ${PATCH_KEYS.includes(sub2) ? sub2 : "angle"} } (the whole gradient is one object) in the keyframe's to / from / set`);
|
|
3310
|
-
}
|
|
3103
|
+
const t = { ...kf }, r = { ...kf };
|
|
3104
|
+
let touched = false, left = false;
|
|
3105
|
+
for (const b of BAGS) {
|
|
3106
|
+
const bag = kf[b];
|
|
3107
|
+
if (!bag) {
|
|
3108
|
+
delete t[b];
|
|
3109
|
+
delete r[b];
|
|
3110
|
+
continue;
|
|
3311
3111
|
}
|
|
3112
|
+
const { time, ...others } = bag;
|
|
3113
|
+
if ("time" in bag) {
|
|
3114
|
+
touched = true;
|
|
3115
|
+
t[b] = { [prop]: time };
|
|
3116
|
+
} else delete t[b];
|
|
3117
|
+
if (Object.keys(others).length) {
|
|
3118
|
+
r[b] = others;
|
|
3119
|
+
left = true;
|
|
3120
|
+
} else delete r[b];
|
|
3312
3121
|
}
|
|
3122
|
+
if (touched) timeKfs.push(t);
|
|
3123
|
+
if (!touched || left) restKfs.push(r);
|
|
3313
3124
|
}
|
|
3314
|
-
|
|
3125
|
+
let restInitial = spec.initial;
|
|
3126
|
+
let start;
|
|
3127
|
+
if (hasInitial) {
|
|
3128
|
+
const { time, ...others } = spec.initial;
|
|
3129
|
+
start = typeof time === "number" && Number.isFinite(time) ? time : void 0;
|
|
3130
|
+
restInitial = others;
|
|
3131
|
+
}
|
|
3132
|
+
return { timeKfs, restKfs: restKfs.length ? restKfs : void 0, restInitial, start, speed };
|
|
3315
3133
|
}
|
|
3316
|
-
function
|
|
3317
|
-
|
|
3318
|
-
|
|
3319
|
-
|
|
3320
|
-
|
|
3321
|
-
|
|
3322
|
-
|
|
3323
|
-
|
|
3324
|
-
|
|
3325
|
-
from: fromPatch !== void 0 ? (prev) => mergeGrad(prev, fromPatch) : void 0,
|
|
3326
|
-
to: (start, prev) => toPatch !== void 0 ? mergeGrad(start, toPatch) : prev,
|
|
3327
|
-
make: (a, b) => {
|
|
3328
|
-
const colors = a.stops.map((s, i) => colorSpace === "rgb" ? interpolateColors(s.color, b.stops[i].color) : buildColorInterp(s.color, b.stops[i].color, colorSpace));
|
|
3329
|
-
return (t) => {
|
|
3330
|
-
const l = (x, y) => x + (y - x) * t;
|
|
3331
|
-
return {
|
|
3332
|
-
type: a.type,
|
|
3333
|
-
angle: l(a.angle, b.angle),
|
|
3334
|
-
center: [l(a.center[0], b.center[0]), l(a.center[1], b.center[1])],
|
|
3335
|
-
innerRadius: l(a.innerRadius, b.innerRadius),
|
|
3336
|
-
radius: l(a.radius, b.radius),
|
|
3337
|
-
stops: a.stops.map((s, i) => ({ offset: l(s.offset, b.stops[i].offset), color: colors[i](t) }))
|
|
3338
|
-
};
|
|
3339
|
-
};
|
|
3340
|
-
},
|
|
3341
|
-
duration,
|
|
3342
|
-
ease,
|
|
3343
|
-
at,
|
|
3344
|
-
repeat: loop.repeat,
|
|
3345
|
-
yoyo: loop.yoyo,
|
|
3346
|
-
repeatDelay: loop.repeatDelay
|
|
3134
|
+
function resolveFromEnd(remap, length, prop) {
|
|
3135
|
+
const fix = (v) => typeof v === "number" && v < 0 ? Math.max(0, length + v) : v;
|
|
3136
|
+
const timeKfs = remap.timeKfs.map((kf) => {
|
|
3137
|
+
const out = { ...kf };
|
|
3138
|
+
for (const b of BAGS) {
|
|
3139
|
+
const bag = kf[b];
|
|
3140
|
+
if (bag && prop in bag) out[b] = { ...bag, [prop]: fix(bag[prop]) };
|
|
3141
|
+
}
|
|
3142
|
+
return out;
|
|
3347
3143
|
});
|
|
3144
|
+
return { ...remap, timeKfs, start: remap.start === void 0 ? void 0 : fix(remap.start) };
|
|
3348
3145
|
}
|
|
3349
|
-
|
|
3350
|
-
|
|
3351
|
-
|
|
3352
|
-
|
|
3353
|
-
|
|
3354
|
-
|
|
3355
|
-
|
|
3356
|
-
|
|
3357
|
-
|
|
3358
|
-
|
|
3359
|
-
|
|
3360
|
-
|
|
3361
|
-
|
|
3362
|
-
paint(g) {
|
|
3363
|
-
const ctx = this.canvas.getContext("2d"), s = this.size;
|
|
3364
|
-
if (!ctx) return new PIXI.FillGradient(gradientOptions({ angle: g.angle, stops: g.stops.map((x) => [x.offset, x.color]) }));
|
|
3365
|
-
ctx.clearRect(0, 0, s, s);
|
|
3366
|
-
if (g.type === "radial") {
|
|
3367
|
-
paintRadial(ctx, s, { stops: g.stops.map((x) => [x.offset, x.color]), center: g.center, innerRadius: g.innerRadius, radius: g.radius });
|
|
3368
|
-
} else {
|
|
3369
|
-
const a = g.angle * Math.PI / 180, dx = Math.cos(a), dy = Math.sin(a);
|
|
3370
|
-
const h = (Math.abs(dx) + Math.abs(dy)) / 2;
|
|
3371
|
-
const grad = ctx.createLinearGradient((0.5 - dx * h) * s, (0.5 - dy * h) * s, (0.5 + dx * h) * s, (0.5 + dy * h) * s);
|
|
3372
|
-
for (const st of g.stops) grad.addColorStop(Math.min(1, Math.max(0, st.offset)), st.color);
|
|
3373
|
-
ctx.fillStyle = grad;
|
|
3374
|
-
ctx.fillRect(0, 0, s, s);
|
|
3146
|
+
function remapOf(spec, prop, length) {
|
|
3147
|
+
const r = timeRemapOf(spec, prop);
|
|
3148
|
+
return r && length !== null ? resolveFromEnd(r, length, prop) : r;
|
|
3149
|
+
}
|
|
3150
|
+
function contentLength(remap, duration) {
|
|
3151
|
+
let m = duration;
|
|
3152
|
+
if (remap.speed !== void 0) m = Math.max(m, Math.abs(remap.speed) * duration);
|
|
3153
|
+
if (remap.start !== void 0) m = Math.max(m, remap.start + (remap.speed ?? 1) * duration);
|
|
3154
|
+
for (const kf of remap.timeKfs) {
|
|
3155
|
+
for (const b of BAGS) {
|
|
3156
|
+
const bag = kf[b];
|
|
3157
|
+
const v = bag && Object.values(bag)[0];
|
|
3158
|
+
if (typeof v === "number") m = Math.max(m, v);
|
|
3375
3159
|
}
|
|
3376
|
-
this.tex.source.update();
|
|
3377
|
-
return { texture: this.tex, textureSpace: "local" };
|
|
3378
3160
|
}
|
|
3379
|
-
|
|
3380
|
-
|
|
3381
|
-
|
|
3382
|
-
|
|
3383
|
-
|
|
3161
|
+
return m;
|
|
3162
|
+
}
|
|
3163
|
+
function bindClock(timeline, clock, prop, remap, duration, at, scope) {
|
|
3164
|
+
if (remap.timeKfs.length) {
|
|
3165
|
+
if (remap.start !== void 0) timeline.set(clock, { [prop]: remap.start }, at);
|
|
3166
|
+
applyKeyframes(timeline, clock, remap.timeKfs, duration, scope, [], at);
|
|
3167
|
+
return;
|
|
3384
3168
|
}
|
|
3385
|
-
|
|
3386
|
-
|
|
3387
|
-
|
|
3388
|
-
|
|
3389
|
-
|
|
3390
|
-
|
|
3391
|
-
|
|
3392
|
-
|
|
3393
|
-
|
|
3394
|
-
|
|
3395
|
-
|
|
3396
|
-
|
|
3397
|
-
|
|
3398
|
-
|
|
3399
|
-
|
|
3400
|
-
|
|
3401
|
-
|
|
3402
|
-
|
|
3403
|
-
|
|
3404
|
-
|
|
3405
|
-
|
|
3406
|
-
|
|
3407
|
-
if (fromV !== void 0 || toV !== void 0) {
|
|
3408
|
-
tweenGradient(timeline, holder, fromV, toV, kfDuration(kf), kf.ease ?? "none", at, colorSpace, onChange, loopVars(kf));
|
|
3169
|
+
const s = remap.speed ?? 1;
|
|
3170
|
+
const from = remap.start ?? (s < 0 ? -s * duration : 0);
|
|
3171
|
+
timeline.fromTo(clock, { [prop]: from }, { [prop]: from + s * duration, duration, ease: "none" }, at);
|
|
3172
|
+
}
|
|
3173
|
+
function clockTable(remap, prop, duration, at, scope, to) {
|
|
3174
|
+
const probe = createTimeline({ paused: true });
|
|
3175
|
+
const clock = { [prop]: remap.start ?? 0 };
|
|
3176
|
+
bindClock(probe, clock, prop, remap, duration, at, scope);
|
|
3177
|
+
probe.time(probe.duration());
|
|
3178
|
+
probe.time(0);
|
|
3179
|
+
const h = 1 / 1e3;
|
|
3180
|
+
const n = Math.max(2, Math.ceil(to / h) + 2);
|
|
3181
|
+
const tab = new Float64Array(n);
|
|
3182
|
+
let min = Infinity, max = -Infinity;
|
|
3183
|
+
for (let k = 0; k < n; k++) {
|
|
3184
|
+
probe.time(k * h);
|
|
3185
|
+
const v = clock[prop];
|
|
3186
|
+
tab[k] = v;
|
|
3187
|
+
const t = k * h;
|
|
3188
|
+
if (t >= at && t <= at + duration) {
|
|
3189
|
+
if (v < min) min = v;
|
|
3190
|
+
if (v > max) max = v;
|
|
3409
3191
|
}
|
|
3410
3192
|
}
|
|
3193
|
+
probe.kill();
|
|
3194
|
+
return {
|
|
3195
|
+
at(t) {
|
|
3196
|
+
const x = Math.min(Math.max(t / h, 0), n - 1.000001);
|
|
3197
|
+
const k = Math.floor(x), f = x - k;
|
|
3198
|
+
return tab[k] * (1 - f) + tab[k + 1] * f;
|
|
3199
|
+
},
|
|
3200
|
+
min: Number.isFinite(min) ? min : 0,
|
|
3201
|
+
max: Number.isFinite(max) ? max : 0
|
|
3202
|
+
};
|
|
3411
3203
|
}
|
|
3412
|
-
var hasGradientKeys = (keyframes) => (keyframes ?? []).some((kf) => [kf.set, kf.to, kf.from].some((b) => b && b.fillGradient !== void 0));
|
|
3413
3204
|
|
|
3414
|
-
// src/
|
|
3415
|
-
var
|
|
3416
|
-
|
|
3417
|
-
|
|
3418
|
-
|
|
3419
|
-
|
|
3420
|
-
|
|
3421
|
-
|
|
3422
|
-
|
|
3423
|
-
"whiteSpace",
|
|
3424
|
-
"lineJoin",
|
|
3425
|
-
"join",
|
|
3426
|
-
"cap",
|
|
3427
|
-
"color",
|
|
3428
|
-
"stroke"
|
|
3429
|
-
];
|
|
3430
|
-
function formatValue(v, f) {
|
|
3431
|
-
const fixed = v.toFixed(Math.max(0, Math.floor(f?.decimals ?? 0)));
|
|
3432
|
-
const pad = Math.max(0, Math.floor(f?.pad ?? 0));
|
|
3433
|
-
if (!f?.grouping && !pad) return fixed;
|
|
3434
|
-
const [signed, frac] = fixed.split(".");
|
|
3435
|
-
const sign = signed.startsWith("-") ? "-" : "";
|
|
3436
|
-
let int = sign ? signed.slice(1) : signed;
|
|
3437
|
-
if (pad) int = int.padStart(pad, "0");
|
|
3438
|
-
if (f?.grouping) int = int.replace(/\B(?=(\d{3})+(?!\d))/g, ",");
|
|
3439
|
-
return sign + int + (frac !== void 0 ? "." + frac : "");
|
|
3205
|
+
// src/space/math.ts
|
|
3206
|
+
var DEG3 = Math.PI / 180;
|
|
3207
|
+
var DEFAULT_FOV = 40;
|
|
3208
|
+
var MIN_FOV = 1;
|
|
3209
|
+
var MAX_FOV = 179;
|
|
3210
|
+
var NEAR = 1;
|
|
3211
|
+
function clampFov(fov) {
|
|
3212
|
+
if (!Number.isFinite(fov)) return DEFAULT_FOV;
|
|
3213
|
+
return Math.min(MAX_FOV, Math.max(MIN_FOV, fov));
|
|
3440
3214
|
}
|
|
3441
|
-
|
|
3442
|
-
|
|
3443
|
-
|
|
3444
|
-
|
|
3445
|
-
|
|
3446
|
-
|
|
3447
|
-
|
|
3448
|
-
|
|
3449
|
-
|
|
3450
|
-
|
|
3451
|
-
|
|
3452
|
-
|
|
3453
|
-
|
|
3454
|
-
|
|
3455
|
-
|
|
3456
|
-
|
|
3457
|
-
|
|
3215
|
+
function homeDistance(compHeight, fovDeg) {
|
|
3216
|
+
return compHeight / 2 / Math.tan(clampFov(fovDeg) * DEG3 / 2);
|
|
3217
|
+
}
|
|
3218
|
+
function homeCamera(compW, compH, fov = DEFAULT_FOV) {
|
|
3219
|
+
return {
|
|
3220
|
+
x: compW / 2,
|
|
3221
|
+
y: compH / 2,
|
|
3222
|
+
z: homeDistance(compH, fov),
|
|
3223
|
+
lookAtX: compW / 2,
|
|
3224
|
+
lookAtY: compH / 2,
|
|
3225
|
+
lookAtZ: 0,
|
|
3226
|
+
fov
|
|
3227
|
+
};
|
|
3228
|
+
}
|
|
3229
|
+
function cameraBasis(cam, compW, compH) {
|
|
3230
|
+
let fx = cam.lookAtX - cam.x;
|
|
3231
|
+
let fy = cam.lookAtY - cam.y;
|
|
3232
|
+
let fz = cam.lookAtZ - cam.z;
|
|
3233
|
+
let len = Math.hypot(fx, fy, fz);
|
|
3234
|
+
if (len < 1e-9) {
|
|
3235
|
+
fx = 0;
|
|
3236
|
+
fy = 0;
|
|
3237
|
+
fz = -1;
|
|
3238
|
+
len = 1;
|
|
3458
3239
|
}
|
|
3459
|
-
|
|
3460
|
-
|
|
3461
|
-
|
|
3462
|
-
|
|
3240
|
+
fx /= len;
|
|
3241
|
+
fy /= len;
|
|
3242
|
+
fz /= len;
|
|
3243
|
+
let rx = -fz;
|
|
3244
|
+
const ry = 0;
|
|
3245
|
+
let rz = fx;
|
|
3246
|
+
const rlen = Math.hypot(rx, rz);
|
|
3247
|
+
if (rlen < 1e-9) {
|
|
3248
|
+
rx = 1;
|
|
3249
|
+
rz = 0;
|
|
3250
|
+
} else {
|
|
3251
|
+
rx /= rlen;
|
|
3252
|
+
rz /= rlen;
|
|
3463
3253
|
}
|
|
3464
|
-
|
|
3465
|
-
|
|
3466
|
-
|
|
3254
|
+
const dx = ry * fz - rz * fy;
|
|
3255
|
+
const dy = rz * fx - rx * fz;
|
|
3256
|
+
const dz = rx * fy - ry * fx;
|
|
3257
|
+
return {
|
|
3258
|
+
cx: cam.x,
|
|
3259
|
+
cy: cam.y,
|
|
3260
|
+
cz: cam.z,
|
|
3261
|
+
rx,
|
|
3262
|
+
ry,
|
|
3263
|
+
rz,
|
|
3264
|
+
dx,
|
|
3265
|
+
dy,
|
|
3266
|
+
dz,
|
|
3267
|
+
fx,
|
|
3268
|
+
fy,
|
|
3269
|
+
fz,
|
|
3270
|
+
focal: compH / 2 / Math.tan(clampFov(cam.fov) * DEG3 / 2),
|
|
3271
|
+
halfW: compW / 2,
|
|
3272
|
+
halfH: compH / 2
|
|
3273
|
+
};
|
|
3274
|
+
}
|
|
3275
|
+
function layerToWorld(t, px, py) {
|
|
3276
|
+
let x = (px - t.pivotX) * t.scaleX;
|
|
3277
|
+
let y = (py - t.pivotY) * t.scaleY;
|
|
3278
|
+
let z = 0;
|
|
3279
|
+
let c = Math.cos(t.rotationX);
|
|
3280
|
+
let s = Math.sin(t.rotationX);
|
|
3281
|
+
[y, z] = [y * c - z * s, y * s + z * c];
|
|
3282
|
+
c = Math.cos(t.rotationY);
|
|
3283
|
+
s = Math.sin(t.rotationY);
|
|
3284
|
+
[x, z] = [x * c + z * s, -x * s + z * c];
|
|
3285
|
+
c = Math.cos(t.rotationZ);
|
|
3286
|
+
s = Math.sin(t.rotationZ);
|
|
3287
|
+
[x, y] = [x * c - y * s, x * s + y * c];
|
|
3288
|
+
return { x: x + t.x, y: y + t.y, z: z + t.z };
|
|
3289
|
+
}
|
|
3290
|
+
function projectPoint(b, p) {
|
|
3291
|
+
const vx = p.x - b.cx;
|
|
3292
|
+
const vy = p.y - b.cy;
|
|
3293
|
+
const vz = p.z - b.cz;
|
|
3294
|
+
const xc = vx * b.rx + vy * b.ry + vz * b.rz;
|
|
3295
|
+
const yc = vx * b.dx + vy * b.dy + vz * b.dz;
|
|
3296
|
+
const zc = vx * b.fx + vy * b.fy + vz * b.fz;
|
|
3297
|
+
return { x: b.halfW + b.focal * xc / zc, y: b.halfH + b.focal * yc / zc, depth: zc };
|
|
3298
|
+
}
|
|
3299
|
+
function projectLayer(t, frame, b) {
|
|
3300
|
+
const pts = [
|
|
3301
|
+
[frame.x, frame.y],
|
|
3302
|
+
[frame.x + frame.width, frame.y],
|
|
3303
|
+
[frame.x + frame.width, frame.y + frame.height],
|
|
3304
|
+
[frame.x, frame.y + frame.height]
|
|
3305
|
+
];
|
|
3306
|
+
let visible = true;
|
|
3307
|
+
const corners = [];
|
|
3308
|
+
for (const [px, py] of pts) {
|
|
3309
|
+
const p = projectPoint(b, layerToWorld(t, px, py));
|
|
3310
|
+
if (!(p.depth > NEAR)) visible = false;
|
|
3311
|
+
corners.push(p.x, p.y);
|
|
3467
3312
|
}
|
|
3468
|
-
|
|
3469
|
-
|
|
3470
|
-
|
|
3471
|
-
|
|
3472
|
-
|
|
3473
|
-
|
|
3474
|
-
|
|
3313
|
+
const origin = projectPoint(b, { x: t.x, y: t.y, z: t.z });
|
|
3314
|
+
return { corners, depth: origin.depth, visible };
|
|
3315
|
+
}
|
|
3316
|
+
|
|
3317
|
+
// src/space/focus.ts
|
|
3318
|
+
var DEFAULT_APERTURE = 30;
|
|
3319
|
+
var MIN_BLUR = 0.05;
|
|
3320
|
+
var MAX_BLUR = 32;
|
|
3321
|
+
var MANY_BLURRED = 20;
|
|
3322
|
+
function blurRadius(aperture, focal, depth, focusDepth) {
|
|
3323
|
+
if (!(aperture > 0) || !(focal > 0) || !(depth > 0) || !(focusDepth > 0)) return 0;
|
|
3324
|
+
const r = aperture * focal * Math.abs(1 / depth - 1 / focusDepth) / 2;
|
|
3325
|
+
return Math.min(r, MAX_BLUR);
|
|
3326
|
+
}
|
|
3327
|
+
var SCOPE_NAMES = /* @__PURE__ */ new Set(["w", "h", "W", "H", "GW", "GH", "contain", "cover", "t", "d", "T"]);
|
|
3328
|
+
function looksLikeLayerName(s) {
|
|
3329
|
+
return /^[A-Za-z_][\w-]*$/.test(s) && !SCOPE_NAMES.has(s);
|
|
3330
|
+
}
|
|
3331
|
+
var isName = (v, known) => typeof v === "string" && (known.has(v) || looksLikeLayerName(v));
|
|
3332
|
+
function focusNames(props, known) {
|
|
3333
|
+
const out = [];
|
|
3334
|
+
const read2 = (bag) => {
|
|
3335
|
+
const v = bag?.focus;
|
|
3336
|
+
if (isName(v, known)) out.push(v);
|
|
3337
|
+
};
|
|
3338
|
+
read2(props.initial);
|
|
3339
|
+
for (const kf of props.keyframes ?? []) for (const bag of [kf.set, kf.to, kf.from]) read2(bag);
|
|
3340
|
+
return out;
|
|
3341
|
+
}
|
|
3342
|
+
function withFocusResolved(props, zOf, known = /* @__PURE__ */ new Set()) {
|
|
3343
|
+
if (focusNames(props, known).length === 0) return props;
|
|
3344
|
+
const fix = (bag) => {
|
|
3345
|
+
const v = bag?.focus;
|
|
3346
|
+
if (!bag || !isName(v, known)) return bag;
|
|
3347
|
+
return { ...bag, focus: zOf(v) ?? 0 };
|
|
3348
|
+
};
|
|
3349
|
+
return {
|
|
3350
|
+
...props,
|
|
3351
|
+
initial: fix(props.initial),
|
|
3352
|
+
keyframes: props.keyframes?.map((kf) => ({ ...kf, set: fix(kf.set), to: fix(kf.to), from: fix(kf.from) }))
|
|
3353
|
+
};
|
|
3354
|
+
}
|
|
3355
|
+
function layerInitialZ(spec, scope) {
|
|
3356
|
+
const z = spec.initial?.z;
|
|
3357
|
+
if (typeof z === "number") return z;
|
|
3358
|
+
if (typeof z === "string") return evaluateExpr(z, scope);
|
|
3359
|
+
return 0;
|
|
3360
|
+
}
|
|
3361
|
+
var movesZ = (spec) => (spec.keyframes ?? []).some((kf) => [kf.set, kf.to, kf.from].some((bag) => bag && "z" in bag));
|
|
3362
|
+
function focusProblems(camera, siblings) {
|
|
3363
|
+
const out = [];
|
|
3364
|
+
const said = /* @__PURE__ */ new Set();
|
|
3365
|
+
const threeD = siblings.filter((s) => s.threeD && s.name).map((s) => s.name);
|
|
3366
|
+
const known = new Set(siblings.map((s) => s.name).filter((n) => !!n));
|
|
3367
|
+
for (const name of focusNames(camera, known)) {
|
|
3368
|
+
if (said.has(name)) continue;
|
|
3369
|
+
said.add(name);
|
|
3370
|
+
const same = siblings.filter((s) => s.name === name);
|
|
3371
|
+
const hit = same.find((s) => s.threeD) ?? same[0];
|
|
3372
|
+
if (!hit) out.push({ kind: "missing", name, hint: chunkTWZNOUM7_cjs.suggestName(name, threeD) });
|
|
3373
|
+
else if (!hit.threeD) out.push({ kind: "not-threeD", name });
|
|
3374
|
+
else {
|
|
3375
|
+
if (same.length > 1) out.push({ kind: "duplicate", name, count: same.length });
|
|
3376
|
+
if (movesZ(hit)) out.push({ kind: "moving", name });
|
|
3377
|
+
}
|
|
3475
3378
|
}
|
|
3379
|
+
return out;
|
|
3380
|
+
}
|
|
3381
|
+
var CameraSequence = class extends Sequence {
|
|
3382
|
+
/** True when `z` is never specified anywhere: z then follows `fov`. */
|
|
3383
|
+
autoZ = true;
|
|
3384
|
+
compH = 0;
|
|
3385
|
+
warnedFov = false;
|
|
3386
|
+
warnedLookAt = false;
|
|
3387
|
+
warnedAperture = false;
|
|
3388
|
+
/** True when the camera writes `focus` or `aperture` anywhere: depth of field is on. */
|
|
3389
|
+
dof = false;
|
|
3390
|
+
/** True when the camera writes any fog key anywhere: depth fog is on (nothing is made for a camera without fog). */
|
|
3391
|
+
fog = false;
|
|
3392
|
+
fogC = null;
|
|
3393
|
+
zOfName = null;
|
|
3394
|
+
layerNames = /* @__PURE__ */ new Set();
|
|
3476
3395
|
async build() {
|
|
3477
|
-
const
|
|
3478
|
-
|
|
3479
|
-
fontSize: 36,
|
|
3480
|
-
fill: "#ffffff",
|
|
3481
|
-
align: "center"
|
|
3482
|
-
};
|
|
3483
|
-
const initialProps = this.spec.initial ?? {};
|
|
3484
|
-
this._template = String(initialProps.text ?? this.spec.text ?? "");
|
|
3485
|
-
const text = new PIXI.Text({
|
|
3486
|
-
text: this._template,
|
|
3487
|
-
style: baseStyle,
|
|
3488
|
-
label: this.spec.name
|
|
3489
|
-
});
|
|
3490
|
-
text.cullable = true;
|
|
3491
|
-
this.target = text;
|
|
3492
|
-
this.intrinsicWidth = text.width;
|
|
3493
|
-
this.intrinsicHeight = text.height;
|
|
3396
|
+
const compW = this.parent?.width ?? this.root.width;
|
|
3397
|
+
this.compH = this.parent?.height ?? this.root.height;
|
|
3494
3398
|
if (this.duration === void 0) {
|
|
3495
3399
|
this.duration = this.parent?.duration ?? this.root.duration;
|
|
3496
3400
|
}
|
|
3497
|
-
|
|
3498
|
-
|
|
3499
|
-
|
|
3500
|
-
|
|
3501
|
-
|
|
3502
|
-
|
|
3503
|
-
|
|
3504
|
-
|
|
3505
|
-
|
|
3506
|
-
|
|
3507
|
-
|
|
3508
|
-
|
|
3509
|
-
|
|
3510
|
-
|
|
3511
|
-
|
|
3512
|
-
|
|
3513
|
-
|
|
3401
|
+
const home = homeCamera(compW, this.compH);
|
|
3402
|
+
const carrier = new PIXI.Container();
|
|
3403
|
+
carrier.x = home.x;
|
|
3404
|
+
carrier.y = home.y;
|
|
3405
|
+
carrier.z = home.z;
|
|
3406
|
+
carrier.lookAtX = home.lookAtX;
|
|
3407
|
+
carrier.lookAtY = home.lookAtY;
|
|
3408
|
+
carrier.lookAtZ = home.lookAtZ;
|
|
3409
|
+
carrier.fov = home.fov;
|
|
3410
|
+
carrier.focus = 0;
|
|
3411
|
+
carrier.aperture = DEFAULT_APERTURE;
|
|
3412
|
+
carrier.offsetX = carrier.offsetY = carrier.offsetZ = 0;
|
|
3413
|
+
carrier.lookOffsetX = carrier.lookOffsetY = carrier.lookOffsetZ = 0;
|
|
3414
|
+
carrier.fogNear = home.z;
|
|
3415
|
+
carrier.fogFar = home.z * 3;
|
|
3416
|
+
carrier.fogColor = "#000000";
|
|
3417
|
+
carrier.fogAmount = 1;
|
|
3418
|
+
this.target = carrier;
|
|
3419
|
+
const keys = chunkGL2AQFLQ_cjs.collectPropKeys(this.spec);
|
|
3420
|
+
this.autoZ = !keys.has("z");
|
|
3421
|
+
this.dof = keys.has("focus") || keys.has("aperture");
|
|
3422
|
+
this.fog = keys.has("fogNear") || keys.has("fogFar") || keys.has("fogColor") || keys.has("fogAmount");
|
|
3423
|
+
}
|
|
3424
|
+
/** The aperture to use now: off unless depth of field is on and the value is a number of 0 or more (said once if it is not). */
|
|
3425
|
+
apertureNow(a) {
|
|
3426
|
+
if (!this.dof) return 0;
|
|
3427
|
+
if (!(a >= 0) && !this.warnedAperture) {
|
|
3428
|
+
this.warnedAperture = true;
|
|
3429
|
+
const who = this.spec.name ? ` "${this.spec.name}"` : "";
|
|
3430
|
+
console.warn(`pixi-effects: camera${who}: aperture ${a} is not a number of 0 or more; depth of field is off (it is the lens diameter in px: 30 is the default, 0 turns it off)`);
|
|
3514
3431
|
}
|
|
3515
|
-
|
|
3516
|
-
|
|
3517
|
-
|
|
3518
|
-
|
|
3519
|
-
|
|
3432
|
+
return a > 0 ? a : 0;
|
|
3433
|
+
}
|
|
3434
|
+
/** Called by the composition once its children exist: how a layer name in `focus` becomes the z of that layer. */
|
|
3435
|
+
resolveFocusNames(zOf, names = /* @__PURE__ */ new Set()) {
|
|
3436
|
+
this.zOfName = zOf;
|
|
3437
|
+
this.layerNames = names;
|
|
3438
|
+
}
|
|
3439
|
+
displayProps() {
|
|
3440
|
+
const base = super.displayProps();
|
|
3441
|
+
return this.zOfName ? withFocusResolved(base, this.zOfName, this.layerNames) : base;
|
|
3442
|
+
}
|
|
3443
|
+
/** The camera's state at the current timeline position. */
|
|
3444
|
+
state() {
|
|
3445
|
+
const c = this.target;
|
|
3446
|
+
if (!this.warnedFov && !(c.fov >= MIN_FOV && c.fov <= MAX_FOV)) {
|
|
3447
|
+
this.warnedFov = true;
|
|
3448
|
+
const who = this.spec.name ? ` "${this.spec.name}"` : "";
|
|
3449
|
+
console.warn(`pixi-effects: camera${who}: fov ${c.fov} is outside [${MIN_FOV}, ${MAX_FOV}]; clamped`);
|
|
3520
3450
|
}
|
|
3521
|
-
const
|
|
3522
|
-
|
|
3523
|
-
this.
|
|
3524
|
-
|
|
3525
|
-
|
|
3526
|
-
|
|
3527
|
-
|
|
3528
|
-
|
|
3529
|
-
|
|
3530
|
-
|
|
3451
|
+
const fov = clampFov(c.fov);
|
|
3452
|
+
const z = this.autoZ ? homeDistance(this.compH, fov) : c.z;
|
|
3453
|
+
if (!this.warnedLookAt && c.lookAtX === c.x && c.lookAtY === c.y && c.lookAtZ === z) {
|
|
3454
|
+
this.warnedLookAt = true;
|
|
3455
|
+
const who = this.spec.name ? ` "${this.spec.name}"` : "";
|
|
3456
|
+
console.warn(`pixi-effects: camera${who}: lookAt equals the camera position; looking along -z instead`);
|
|
3457
|
+
}
|
|
3458
|
+
return {
|
|
3459
|
+
x: c.x + c.offsetX,
|
|
3460
|
+
y: c.y + c.offsetY,
|
|
3461
|
+
z: z + c.offsetZ,
|
|
3462
|
+
lookAtX: c.lookAtX + c.lookOffsetX,
|
|
3463
|
+
lookAtY: c.lookAtY + c.lookOffsetY,
|
|
3464
|
+
lookAtZ: c.lookAtZ + c.lookOffsetZ,
|
|
3465
|
+
fov,
|
|
3466
|
+
focus: Number.isFinite(c.focus) ? c.focus : 0,
|
|
3467
|
+
aperture: this.apertureNow(c.aperture)
|
|
3468
|
+
};
|
|
3469
|
+
}
|
|
3470
|
+
/** The fog now (colour as 0..1 channels, distances, 0..1 amount), or null when the camera writes no fog key. */
|
|
3471
|
+
fogState() {
|
|
3472
|
+
if (!this.fog) return null;
|
|
3473
|
+
const c = this.target;
|
|
3474
|
+
const fc = this.fogC ??= new PIXI.Color();
|
|
3475
|
+
try {
|
|
3476
|
+
fc.setValue(c.fogColor);
|
|
3477
|
+
} catch {
|
|
3478
|
+
fc.setValue(0);
|
|
3479
|
+
}
|
|
3480
|
+
const [r, g, b] = fc.toArray();
|
|
3481
|
+
const amount = Number.isFinite(c.fogAmount) ? Math.min(1, Math.max(0, c.fogAmount)) : 1;
|
|
3482
|
+
return { r, g, b, near: c.fogNear, far: c.fogFar, amount };
|
|
3483
|
+
}
|
|
3484
|
+
/** Lifespan on the global timeline (valid after bindTimeline). */
|
|
3485
|
+
window() {
|
|
3486
|
+
const start = this.absoluteStart ?? this.at;
|
|
3487
|
+
return { start, end: start + (this.duration ?? 0) };
|
|
3488
|
+
}
|
|
3489
|
+
};
|
|
3490
|
+
|
|
3491
|
+
// src/space/lighting.ts
|
|
3492
|
+
var LIGHT_KINDS = ["ambient", "point", "spot", "parallel"];
|
|
3493
|
+
var FALLOFFS = ["none", "smooth", "inverseSquare"];
|
|
3494
|
+
var LIGHT_PROPS = ["x", "y", "z", "lookAtX", "lookAtY", "lookAtZ", "intensity", "color", "coneAngle", "coneFeather", "radius", "falloffDistance", "shadowDarkness", "shadowDiffusion"];
|
|
3495
|
+
var MAX_LIGHTS = 8;
|
|
3496
|
+
var MAX_CASTERS = 4;
|
|
3497
|
+
var SHADOW_TAPS = 16;
|
|
3498
|
+
var FALLOFF_ID = { none: 0, smooth: 1, inverseSquare: 2 };
|
|
3499
|
+
var KIND_ID = { point: 1, spot: 2, parallel: 3 };
|
|
3500
|
+
function smoothstep(e0, e1, x) {
|
|
3501
|
+
const t = Math.min(1, Math.max(0, (x - e0) / (e1 - e0)));
|
|
3502
|
+
return t * t * (3 - 2 * t);
|
|
3503
|
+
}
|
|
3504
|
+
var DEG4 = Math.PI / 180;
|
|
3505
|
+
function norm(v) {
|
|
3506
|
+
const l = Math.hypot(v.x, v.y, v.z) || 1;
|
|
3507
|
+
return { x: v.x / l, y: v.y / l, z: v.z / l };
|
|
3508
|
+
}
|
|
3509
|
+
var dot = (a, b) => a.x * b.x + a.y * b.y + a.z * b.z;
|
|
3510
|
+
var sub = (a, b) => ({ x: a.x - b.x, y: a.y - b.y, z: a.z - b.z });
|
|
3511
|
+
function coneCos(l) {
|
|
3512
|
+
const half = Math.min(179, Math.max(0, l.coneAngle)) * DEG4 / 2;
|
|
3513
|
+
const inner = half * (1 - Math.min(1, Math.max(0, l.coneFeather)));
|
|
3514
|
+
const cosOuter = Math.cos(half);
|
|
3515
|
+
const cosInner = Math.max(Math.cos(inner), cosOuter + 1e-4);
|
|
3516
|
+
return { cosOuter, cosInner };
|
|
3517
|
+
}
|
|
3518
|
+
function packLights(lights) {
|
|
3519
|
+
const pos = new Float32Array(4 * MAX_LIGHTS), dir = new Float32Array(4 * MAX_LIGHTS), col = new Float32Array(4 * MAX_LIGHTS), fall = new Float32Array(4 * MAX_LIGHTS), shadow = new Float32Array(4 * MAX_LIGHTS);
|
|
3520
|
+
const ambient = [0, 0, 0];
|
|
3521
|
+
let n = 0;
|
|
3522
|
+
for (const l of lights) {
|
|
3523
|
+
if (l.kind === "ambient") {
|
|
3524
|
+
ambient[0] += l.r * l.intensity;
|
|
3525
|
+
ambient[1] += l.g * l.intensity;
|
|
3526
|
+
ambient[2] += l.b * l.intensity;
|
|
3527
|
+
continue;
|
|
3528
|
+
}
|
|
3529
|
+
if (n >= MAX_LIGHTS) continue;
|
|
3530
|
+
const d = norm({ x: l.lookAtX - l.x, y: l.lookAtY - l.y, z: l.lookAtZ - l.z });
|
|
3531
|
+
const { cosOuter, cosInner } = coneCos(l);
|
|
3532
|
+
pos.set([l.x, l.y, l.z, KIND_ID[l.kind]], 4 * n);
|
|
3533
|
+
dir.set([d.x, d.y, d.z, cosOuter], 4 * n);
|
|
3534
|
+
col.set([l.r * l.intensity, l.g * l.intensity, l.b * l.intensity, cosInner], 4 * n);
|
|
3535
|
+
fall.set([FALLOFF_ID[l.falloff], l.radius, l.falloffDistance, l.castsShadows ? 1 : 0], 4 * n);
|
|
3536
|
+
shadow.set([l.castsShadows ? l.shadowDarkness : 0, l.shadowDiffusion, 0, 0], 4 * n);
|
|
3537
|
+
n++;
|
|
3538
|
+
}
|
|
3539
|
+
return { count: n, ambient, pos, dir, col, fall, shadow };
|
|
3540
|
+
}
|
|
3541
|
+
function shadeReference(p, n, cam, lights) {
|
|
3542
|
+
let N = norm(n);
|
|
3543
|
+
if (dot(N, sub(cam, p)) < 0) N = { x: -N.x, y: -N.y, z: -N.z };
|
|
3544
|
+
const out = [0, 0, 0];
|
|
3545
|
+
for (const l of lights) {
|
|
3546
|
+
if (l.kind === "ambient") {
|
|
3547
|
+
out[0] += l.r * l.intensity;
|
|
3548
|
+
out[1] += l.g * l.intensity;
|
|
3549
|
+
out[2] += l.b * l.intensity;
|
|
3550
|
+
continue;
|
|
3551
|
+
}
|
|
3552
|
+
const dirLA = norm({ x: l.lookAtX - l.x, y: l.lookAtY - l.y, z: l.lookAtZ - l.z });
|
|
3553
|
+
let L;
|
|
3554
|
+
let dist = 0;
|
|
3555
|
+
if (l.kind === "parallel") L = { x: -dirLA.x, y: -dirLA.y, z: -dirLA.z };
|
|
3556
|
+
else {
|
|
3557
|
+
const d = sub({ x: l.x, y: l.y, z: l.z }, p);
|
|
3558
|
+
dist = Math.hypot(d.x, d.y, d.z);
|
|
3559
|
+
L = { x: d.x / dist, y: d.y / dist, z: d.z / dist };
|
|
3560
|
+
}
|
|
3561
|
+
const ndl = Math.max(0, dot(N, L));
|
|
3562
|
+
let att = 1;
|
|
3563
|
+
if (l.kind !== "parallel") {
|
|
3564
|
+
if (l.falloff === "smooth") att = 1 - smoothstep(l.radius, l.radius + Math.max(l.falloffDistance, 1e-3), dist);
|
|
3565
|
+
else if (l.falloff === "inverseSquare") att = Math.min(1, l.radius * l.radius / Math.max(dist * dist, 1e-6));
|
|
3566
|
+
}
|
|
3567
|
+
let cone = 1;
|
|
3568
|
+
if (l.kind === "spot") {
|
|
3569
|
+
const { cosOuter, cosInner } = coneCos(l);
|
|
3570
|
+
cone = smoothstep(cosOuter, cosInner, -dot(L, dirLA));
|
|
3571
|
+
}
|
|
3572
|
+
const k = l.intensity * ndl * att * cone;
|
|
3573
|
+
out[0] += l.r * k;
|
|
3574
|
+
out[1] += l.g * k;
|
|
3575
|
+
out[2] += l.b * k;
|
|
3576
|
+
}
|
|
3577
|
+
return out;
|
|
3578
|
+
}
|
|
3579
|
+
function lightLevel(frame, cam, lights) {
|
|
3580
|
+
const mid = { x: frame.o.x + 0.5 * frame.u.x + 0.5 * frame.v.x, y: frame.o.y + 0.5 * frame.u.y + 0.5 * frame.v.y, z: frame.o.z + 0.5 * frame.u.z + 0.5 * frame.v.z };
|
|
3581
|
+
const n = { x: frame.u.y * frame.v.z - frame.u.z * frame.v.y, y: frame.u.z * frame.v.x - frame.u.x * frame.v.z, z: frame.u.x * frame.v.y - frame.u.y * frame.v.x };
|
|
3582
|
+
const m = shadeReference(mid, n, cam, lights);
|
|
3583
|
+
return 0.2126 * m[0] + 0.7152 * m[1] + 0.0722 * m[2];
|
|
3584
|
+
}
|
|
3585
|
+
var LightSequence = class extends Sequence {
|
|
3586
|
+
color = new PIXI.Color();
|
|
3587
|
+
async build() {
|
|
3588
|
+
const w = this.parent?.width ?? this.root.width;
|
|
3589
|
+
const h = this.parent?.height ?? this.root.height;
|
|
3590
|
+
if (this.duration === void 0) this.duration = this.parent?.duration ?? this.root.duration;
|
|
3591
|
+
const c = new PIXI.Container();
|
|
3592
|
+
c.x = w * 0.3;
|
|
3593
|
+
c.y = h * 0.2;
|
|
3594
|
+
c.z = homeDistance(h, 40) * 0.6;
|
|
3595
|
+
c.lookAtX = w / 2;
|
|
3596
|
+
c.lookAtY = h / 2;
|
|
3597
|
+
c.lookAtZ = 0;
|
|
3598
|
+
c.intensity = 1;
|
|
3599
|
+
c.color = "#ffffff";
|
|
3600
|
+
c.coneAngle = 90;
|
|
3601
|
+
c.coneFeather = 0.5;
|
|
3602
|
+
c.radius = 500;
|
|
3603
|
+
c.falloffDistance = 500;
|
|
3604
|
+
c.shadowDarkness = 1;
|
|
3605
|
+
c.shadowDiffusion = 0;
|
|
3606
|
+
this.target = c;
|
|
3607
|
+
}
|
|
3608
|
+
state() {
|
|
3609
|
+
const c = this.target;
|
|
3610
|
+
try {
|
|
3611
|
+
this.color.setValue(c.color);
|
|
3612
|
+
} catch {
|
|
3613
|
+
this.color.setValue(16777215);
|
|
3531
3614
|
}
|
|
3532
|
-
|
|
3533
|
-
|
|
3534
|
-
|
|
3615
|
+
const [r, g, b] = this.color.toArray();
|
|
3616
|
+
return {
|
|
3617
|
+
// a kind or falloff nobody knows is the default the warning promises (the shader must never see an unknown id)
|
|
3618
|
+
kind: LIGHT_KINDS.includes(this.spec.kind) ? this.spec.kind : "point",
|
|
3619
|
+
x: c.x,
|
|
3620
|
+
y: c.y,
|
|
3621
|
+
z: c.z,
|
|
3622
|
+
lookAtX: c.lookAtX,
|
|
3623
|
+
lookAtY: c.lookAtY,
|
|
3624
|
+
lookAtZ: c.lookAtZ,
|
|
3625
|
+
r,
|
|
3626
|
+
g,
|
|
3627
|
+
b,
|
|
3628
|
+
intensity: Number.isFinite(c.intensity) ? Math.max(0, c.intensity) : 1,
|
|
3629
|
+
coneAngle: c.coneAngle,
|
|
3630
|
+
coneFeather: c.coneFeather,
|
|
3631
|
+
falloff: FALLOFFS.includes(this.spec.falloff) ? this.spec.falloff : "none",
|
|
3632
|
+
radius: c.radius,
|
|
3633
|
+
falloffDistance: c.falloffDistance,
|
|
3634
|
+
castsShadows: !!this.spec.castsShadows,
|
|
3635
|
+
shadowDarkness: Math.min(1, Math.max(0, c.shadowDarkness)),
|
|
3636
|
+
shadowDiffusion: Math.max(0, c.shadowDiffusion)
|
|
3637
|
+
};
|
|
3535
3638
|
}
|
|
3536
|
-
|
|
3537
|
-
|
|
3538
|
-
|
|
3539
|
-
const stripped = stripKeys2(this.spec, ["fill", "value", "text", "visibleChars", "fillGradient"]);
|
|
3540
|
-
runSuperWithStrippedSpec(this, stripped, timeline, offset);
|
|
3541
|
-
const keyframes = this.spec.keyframes ?? [];
|
|
3542
|
-
const origin = offset + this.at;
|
|
3543
|
-
bindFillKeyframes(timeline, this.target, keyframes, this.duration, origin, colorSpace);
|
|
3544
|
-
if (this._grad) bindGradientKeyframes(timeline, this._grad, keyframes, this.duration, origin, colorSpace, () => this._applyGradient());
|
|
3545
|
-
const refresh = () => this._refreshText();
|
|
3546
|
-
bindCounterKeyframes(timeline, this._counters, "value", refresh, keyframes, this.duration, origin, this.scope());
|
|
3547
|
-
bindCounterKeyframes(timeline, this._counters, "visibleChars", refresh, keyframes, this.duration, origin, this.scope());
|
|
3548
|
-
bindTextKeyframes(timeline, keyframes, this.duration, origin, () => this._template, (t) => {
|
|
3549
|
-
this._template = t;
|
|
3550
|
-
refresh();
|
|
3551
|
-
}, chunkLYOKH7KE_cjs.describeLayer(this.spec));
|
|
3639
|
+
window() {
|
|
3640
|
+
const start = this.absoluteStart ?? this.at;
|
|
3641
|
+
return { start, end: start + (this.duration ?? 0) };
|
|
3552
3642
|
}
|
|
3553
3643
|
};
|
|
3554
|
-
|
|
3555
|
-
|
|
3556
|
-
|
|
3557
|
-
|
|
3558
|
-
|
|
3559
|
-
|
|
3560
|
-
|
|
3644
|
+
var defaultWarn = (m) => console.warn(m);
|
|
3645
|
+
var SPAN_STYLE_KEYS = ["fill", "fontWeight", "fontStyle", "fontVariant", "letterSpacing", "dropShadow"];
|
|
3646
|
+
var LINE_KEYS = ["fontSize", "fontFamily", "lineHeight", "wordWrap", "wordWrapWidth", "align", "leading", "textBaseline", "whiteSpace", "stroke", "padding"];
|
|
3647
|
+
var spansMeta = /* @__PURE__ */ new WeakMap();
|
|
3648
|
+
var widthOf = (text, style) => PIXI.CanvasTextMetrics.measureText(text, style).width;
|
|
3649
|
+
function normalize(spans, who, warn) {
|
|
3650
|
+
if (!Array.isArray(spans) || spans.length === 0) {
|
|
3651
|
+
warn(`pixi-effects: ${who}: spans is empty: write an array of strings and { text, fill \u2026 } objects (nothing is drawn)`);
|
|
3652
|
+
return [];
|
|
3561
3653
|
}
|
|
3562
|
-
|
|
3563
|
-
|
|
3564
|
-
|
|
3565
|
-
|
|
3566
|
-
|
|
3567
|
-
|
|
3568
|
-
...kf,
|
|
3569
|
-
set: stripProps(kf.set, keys),
|
|
3570
|
-
to: stripProps(kf.to, keys),
|
|
3571
|
-
from: stripProps(kf.from, keys)
|
|
3572
|
-
})) : void 0
|
|
3573
|
-
};
|
|
3574
|
-
}
|
|
3575
|
-
function stripProps(props, keys) {
|
|
3576
|
-
if (!props) return props;
|
|
3577
|
-
if (!keys.some((k) => k in props)) return props;
|
|
3578
|
-
const out = {};
|
|
3579
|
-
for (const k of Object.keys(props)) if (!keys.includes(k)) out[k] = props[k];
|
|
3580
|
-
return out;
|
|
3581
|
-
}
|
|
3582
|
-
function resolveNumber(v, scope) {
|
|
3583
|
-
if (typeof v === "number") return v;
|
|
3584
|
-
const out = normalizeProps({ v }, scope).v;
|
|
3585
|
-
return typeof out === "number" ? out : Number(out) || 0;
|
|
3586
|
-
}
|
|
3587
|
-
function bindCounterKeyframes(timeline, state, key, refresh, keyframes, parentDuration, origin, scope) {
|
|
3588
|
-
for (const kf of keyframes) {
|
|
3589
|
-
const setV = kf.set?.[key];
|
|
3590
|
-
const fromV = kf.from?.[key];
|
|
3591
|
-
const toV = kf.to?.[key];
|
|
3592
|
-
if (setV === void 0 && fromV === void 0 && toV === void 0) continue;
|
|
3593
|
-
const at = origin + resolveAt(kf.at, parentDuration);
|
|
3594
|
-
const duration = kfDuration(kf);
|
|
3595
|
-
const ease = kf.ease ?? "none";
|
|
3596
|
-
const loop = loopVars(kf);
|
|
3597
|
-
if (setV !== void 0) {
|
|
3598
|
-
const v = resolveNumber(setV, scope);
|
|
3599
|
-
revertibleSet(timeline, at, () => state[key], (n) => {
|
|
3600
|
-
state[key] = n;
|
|
3601
|
-
refresh();
|
|
3602
|
-
}, v, [state, key]);
|
|
3654
|
+
const out = [];
|
|
3655
|
+
const lineKeys = /* @__PURE__ */ new Set();
|
|
3656
|
+
spans.forEach((sp, i) => {
|
|
3657
|
+
if (typeof sp === "string") {
|
|
3658
|
+
out.push({ text: sp, overrides: {} });
|
|
3659
|
+
return;
|
|
3603
3660
|
}
|
|
3604
|
-
if (
|
|
3605
|
-
|
|
3606
|
-
|
|
3607
|
-
{ [key]: resolveNumber(fromV, scope) },
|
|
3608
|
-
{ [key]: resolveNumber(toV, scope), duration, ease, ...loop, onUpdate: refresh },
|
|
3609
|
-
at
|
|
3610
|
-
);
|
|
3611
|
-
} else if (toV !== void 0) {
|
|
3612
|
-
timeline.to(state, { [key]: resolveNumber(toV, scope), duration, ease, ...loop, onUpdate: refresh }, at);
|
|
3613
|
-
} else if (fromV !== void 0) {
|
|
3614
|
-
timeline.from(state, { [key]: resolveNumber(fromV, scope), duration, ease, ...loop, onUpdate: refresh }, at);
|
|
3661
|
+
if (!sp || typeof sp !== "object" || typeof sp.text !== "string") {
|
|
3662
|
+
warn(`pixi-effects: ${who}: spans[${i}] must be a string or { text: '\u2026', fill: '#\u2026' }, got ${JSON.stringify(sp)}; skipped`);
|
|
3663
|
+
return;
|
|
3615
3664
|
}
|
|
3616
|
-
|
|
3665
|
+
const { text, ...rest } = sp;
|
|
3666
|
+
const overrides = {};
|
|
3667
|
+
for (const [k, v] of Object.entries(rest)) {
|
|
3668
|
+
if (v === void 0) continue;
|
|
3669
|
+
if (SPAN_STYLE_KEYS.includes(k)) overrides[k] = v;
|
|
3670
|
+
else if (LINE_KEYS.includes(k)) lineKeys.add(k);
|
|
3671
|
+
else {
|
|
3672
|
+
const guess = chunkTWZNOUM7_cjs.suggestName(k, [...SPAN_STYLE_KEYS]);
|
|
3673
|
+
warn(`pixi-effects: ${who}: spans[${i}]: "${k}" is not a span key${guess ? ` \u2014 did you mean "${guess}"?` : ""} (it is ignored). A span takes text and ${SPAN_STYLE_KEYS.join(", ")}`);
|
|
3674
|
+
}
|
|
3675
|
+
}
|
|
3676
|
+
out.push({ text, overrides });
|
|
3677
|
+
});
|
|
3678
|
+
if (lineKeys.size) warn(`pixi-effects: ${who}: a span cannot set ${[...lineKeys].join(", ")}: they move the baseline, the line or the pieces' places (a stroke shifts a piece by half its width); put them in the style of the layer (one size, one font and one outline per layer). They are ignored`);
|
|
3679
|
+
return out;
|
|
3617
3680
|
}
|
|
3618
|
-
function
|
|
3619
|
-
|
|
3620
|
-
|
|
3621
|
-
|
|
3622
|
-
|
|
3681
|
+
function layoutSpans(spans, style, align2, who, warn = defaultWarn) {
|
|
3682
|
+
const clean = normalize(spans, who, warn);
|
|
3683
|
+
const base = new PIXI.TextStyle(style);
|
|
3684
|
+
const m = PIXI.CanvasTextMetrics.measureText("M", base);
|
|
3685
|
+
const lineHeight = m.lineHeight ?? m.height;
|
|
3686
|
+
const sentinel = (ts) => widthOf("|", ts);
|
|
3687
|
+
const measure = (text, ts) => widthOf(text + "|", ts) - sentinel(ts);
|
|
3688
|
+
const pieces = [];
|
|
3689
|
+
let line = 0, chars = 0, x = 0;
|
|
3690
|
+
clean.forEach((sp, spanIdx) => {
|
|
3691
|
+
const ts = Object.keys(sp.overrides).length ? new PIXI.TextStyle({ ...style, ...sp.overrides }) : base;
|
|
3692
|
+
sp.text.split("\n").forEach((part, k) => {
|
|
3693
|
+
if (k > 0) {
|
|
3694
|
+
line++;
|
|
3695
|
+
x = 0;
|
|
3696
|
+
chars += 1;
|
|
3697
|
+
}
|
|
3698
|
+
if (part === "") return;
|
|
3699
|
+
const width2 = measure(part, ts);
|
|
3700
|
+
const length = Array.from(part).length;
|
|
3701
|
+
pieces.push({ text: part, x, y: line * lineHeight, width: width2, line, span: spanIdx, start: chars, length, style: sp.overrides, blank: part.trim() === "" });
|
|
3702
|
+
x += width2;
|
|
3703
|
+
chars += length;
|
|
3704
|
+
});
|
|
3705
|
+
});
|
|
3706
|
+
const lineWidth = /* @__PURE__ */ new Map();
|
|
3707
|
+
for (const p of pieces) lineWidth.set(p.line, Math.max(lineWidth.get(p.line) ?? 0, p.x + p.width));
|
|
3708
|
+
const width = Math.max(0, ...lineWidth.values());
|
|
3709
|
+
for (const p of pieces) {
|
|
3710
|
+
const room = width - (lineWidth.get(p.line) ?? 0);
|
|
3711
|
+
p.x += align2 === "center" ? room / 2 : align2 === "right" ? room : 0;
|
|
3712
|
+
}
|
|
3713
|
+
return { pieces, width, height: pieces.length ? (line + 1) * lineHeight : 0, lineHeight, chars };
|
|
3714
|
+
}
|
|
3715
|
+
function resolveSpansStyle(style, scope, who, warn = defaultWarn) {
|
|
3716
|
+
const out = { ...TEXT_STYLE_DEFAULTS };
|
|
3717
|
+
for (const [k, raw] of Object.entries(style)) {
|
|
3718
|
+
if (raw === void 0) continue;
|
|
3719
|
+
let v = raw;
|
|
3720
|
+
if (scope) {
|
|
3721
|
+
try {
|
|
3722
|
+
v = normalizeProps({ [k]: raw }, scope, { skipKeys: STYLE_OPAQUE_KEYS })[k];
|
|
3723
|
+
} catch (e) {
|
|
3724
|
+
v = NaN;
|
|
3725
|
+
if (!(k in TEXT_STYLE_DEFAULTS) || k === "fontSize") warn(`pixi-effects: ${who}: style.${k} ${JSON.stringify(raw)} could not be resolved (${e.message}); ${k === "fontSize" ? `the default, ${TEXT_STYLE_DEFAULTS.fontSize}, is used` : "it is left out"}`);
|
|
3726
|
+
continue;
|
|
3623
3727
|
}
|
|
3624
3728
|
}
|
|
3625
|
-
|
|
3626
|
-
|
|
3627
|
-
|
|
3729
|
+
if (["fontSize", "letterSpacing", "lineHeight"].includes(k) && (typeof v !== "number" || !Number.isFinite(v) || k !== "letterSpacing" && v <= 0)) {
|
|
3730
|
+
warn(`pixi-effects: ${who}: style.${k} ${JSON.stringify(raw)} is not a usable number here (a name that is not declared counts as 0; spans measure the text when the layer is built); ${k === "fontSize" ? `the default, ${TEXT_STYLE_DEFAULTS.fontSize}, is used` : "it is left out"}`);
|
|
3731
|
+
continue;
|
|
3732
|
+
}
|
|
3733
|
+
out[k] = v;
|
|
3628
3734
|
}
|
|
3735
|
+
return out;
|
|
3629
3736
|
}
|
|
3630
|
-
|
|
3631
|
-
|
|
3632
|
-
|
|
3633
|
-
|
|
3634
|
-
const
|
|
3635
|
-
|
|
3636
|
-
|
|
3737
|
+
var TEXT_ONLY = ["type", "spans", "text", "style", "format", "colorSpace", "fillGradient", "initial", "keyframes"];
|
|
3738
|
+
var NOT_FOR_A_GROUP = ["fill", "text", "value", "fillGradient"];
|
|
3739
|
+
function expandSpans(spec, warn = defaultWarn, scope) {
|
|
3740
|
+
const who = chunkGL2AQFLQ_cjs.describeLayer(spec);
|
|
3741
|
+
const s = spec;
|
|
3742
|
+
if (s.text !== void 0) warn(`pixi-effects: ${who}: "text" is ignored when the layer has spans: write the text as spans`);
|
|
3743
|
+
const style = resolveSpansStyle(s.style ?? {}, scope, who, warn);
|
|
3744
|
+
const noLayout = ["wordWrap", "wordWrapWidth", "leading"].filter((k) => style[k] !== void 0 && style[k] !== false && style[k] !== 0);
|
|
3745
|
+
for (const k of ["wordWrap", "wordWrapWidth", "leading"]) delete style[k];
|
|
3746
|
+
if (noLayout.length) warn(`pixi-effects: ${who}: style.${noLayout.join(", style.")} ${noLayout.length > 1 ? "do" : "does"} not apply to a spans layer (the lines are the \\n of the spans); break the lines with \\n. ${noLayout.length > 1 ? "They are" : "It is"} ignored`);
|
|
3747
|
+
const layout = layoutSpans(s.spans, style, style.align, who, warn);
|
|
3748
|
+
const dropped = new Set(["fillGradient", "format", "colorSpace"].filter((k) => s[k] !== void 0));
|
|
3749
|
+
const clean = (bag) => {
|
|
3750
|
+
if (!bag) return bag;
|
|
3751
|
+
const out = {};
|
|
3752
|
+
for (const [k, v] of Object.entries(bag)) {
|
|
3753
|
+
if (NOT_FOR_A_GROUP.includes(k)) dropped.add(k);
|
|
3754
|
+
else out[k] = v;
|
|
3755
|
+
}
|
|
3756
|
+
return out;
|
|
3637
3757
|
};
|
|
3638
|
-
|
|
3639
|
-
|
|
3640
|
-
|
|
3641
|
-
|
|
3642
|
-
|
|
3643
|
-
|
|
3644
|
-
|
|
3645
|
-
if (
|
|
3646
|
-
|
|
3647
|
-
|
|
3648
|
-
|
|
3649
|
-
}
|
|
3758
|
+
const initial = clean(s.initial) ?? {};
|
|
3759
|
+
const keyframes = (s.keyframes ?? []).map((kf) => ({ ...kf, set: clean(kf.set), to: clean(kf.to), from: clean(kf.from) }));
|
|
3760
|
+
if (dropped.size) warn(`pixi-effects: ${who}: ${[...dropped].join(", ")} do not apply to a spans layer (it is a group of text layers): use a separate text layer, or put the colour in a span`);
|
|
3761
|
+
const typed = initial.visibleChars !== void 0 || keyframes.some((kf) => [kf.set, kf.to, kf.from].some((p) => p && p.visibleChars !== void 0));
|
|
3762
|
+
const width = Math.max(1, layout.width), height = Math.max(1, layout.height);
|
|
3763
|
+
for (const [a, pivot, size] of [["anchorX", "pivotX", width], ["anchorY", "pivotY", height]]) {
|
|
3764
|
+
if (initial[a] === void 0) continue;
|
|
3765
|
+
if (typeof initial[a] === "number") {
|
|
3766
|
+
initial[pivot] = initial[a] * size;
|
|
3767
|
+
delete initial[a];
|
|
3768
|
+
} else {
|
|
3769
|
+
warn(`pixi-effects: ${who}: initial.${a} ${JSON.stringify(initial[a])} must be a number on a spans layer (it becomes the pivot of the block); it is ignored`);
|
|
3770
|
+
delete initial[a];
|
|
3771
|
+
}
|
|
3772
|
+
}
|
|
3773
|
+
const animatedAnchors = ["anchorX", "anchorY"].filter((a) => keyframes.some((kf) => [kf.set, kf.to, kf.from].some((p) => p && p[a] !== void 0)));
|
|
3774
|
+
if (animatedAnchors.length) warn(`pixi-effects: ${who}: ${animatedAnchors.join(", ")} cannot be keyframed on a spans layer (the anchor is the pivot of the block, set once in initial); the keyframes do nothing`);
|
|
3775
|
+
const baseName = typeof s.name === "string" && s.name ? s.name : "spans";
|
|
3776
|
+
const drawn = layout.pieces.filter((p) => !p.blank);
|
|
3777
|
+
const sequences = drawn.map((p, i) => ({
|
|
3778
|
+
type: "text",
|
|
3779
|
+
name: `${baseName}.${i}`,
|
|
3780
|
+
text: p.text,
|
|
3781
|
+
style: { ...style, ...p.style },
|
|
3782
|
+
initial: { x: p.x, y: p.y, ...typed ? { visibleChars: p.length } : {} }
|
|
3783
|
+
}));
|
|
3784
|
+
const rest = {};
|
|
3785
|
+
for (const [k, v] of Object.entries(s)) if (!TEXT_ONLY.includes(k)) rest[k] = v;
|
|
3786
|
+
const group = { type: "composition", ...rest, width, height, initial, keyframes, sequences };
|
|
3787
|
+
spansMeta.set(group, { typed, pieces: drawn.map((p) => ({ start: p.start, length: p.length })), preview: layout.pieces.map((p, i) => (i > 0 && p.line !== layout.pieces[i - 1].line ? " " : "") + p.text).join("") });
|
|
3788
|
+
return group;
|
|
3789
|
+
}
|
|
3790
|
+
var ImageSequence = class extends Sequence {
|
|
3791
|
+
async build() {
|
|
3792
|
+
const texture = await PIXI.Assets.get(this.spec.asset);
|
|
3793
|
+
const sprite = new PIXI.Sprite({ texture, label: this.spec.name });
|
|
3794
|
+
sprite.cullable = true;
|
|
3795
|
+
this.target = sprite;
|
|
3796
|
+
this.intrinsicWidth = texture.width;
|
|
3797
|
+
this.intrinsicHeight = texture.height;
|
|
3798
|
+
if (this.duration === void 0) {
|
|
3799
|
+
this.duration = this.parent?.duration ?? this.root.duration;
|
|
3650
3800
|
}
|
|
3651
|
-
|
|
3652
|
-
|
|
3653
|
-
|
|
3654
|
-
|
|
3655
|
-
|
|
3656
|
-
|
|
3657
|
-
|
|
3658
|
-
|
|
3659
|
-
|
|
3660
|
-
|
|
3661
|
-
|
|
3662
|
-
|
|
3663
|
-
|
|
3664
|
-
|
|
3801
|
+
this.buildFilters();
|
|
3802
|
+
}
|
|
3803
|
+
bindTimeline(timeline, offset = 0) {
|
|
3804
|
+
if (!this.target) return;
|
|
3805
|
+
const colorSpace = this.spec.colorSpace;
|
|
3806
|
+
if (!colorSpace || colorSpace === "rgb") {
|
|
3807
|
+
super.bindTimeline(timeline, offset);
|
|
3808
|
+
return;
|
|
3809
|
+
}
|
|
3810
|
+
const scope = this.scope();
|
|
3811
|
+
const startTime = offset + this.at;
|
|
3812
|
+
const initial = stripKeys2(this.spec.initial, ["tint"]);
|
|
3813
|
+
const keyframes = this.spec.keyframes ? this.spec.keyframes.map((kf) => stripKeysInKeyframe(kf, ["tint"])) : void 0;
|
|
3814
|
+
applyInitial(this.target, initial, scope);
|
|
3815
|
+
applyKeyframes(timeline, this.target, keyframes, this.duration, scope, [], startTime);
|
|
3816
|
+
const initTint = this.spec.initial?.tint;
|
|
3817
|
+
if (initTint !== void 0) this.target.tint = initTint;
|
|
3818
|
+
for (const kf of this.spec.keyframes ?? []) {
|
|
3819
|
+
const at = startTime + resolveAt(kf.at, this.duration);
|
|
3820
|
+
const duration = kfDuration(kf);
|
|
3821
|
+
const ease = kf.ease ?? "none";
|
|
3822
|
+
const fromTint = kf.from?.tint;
|
|
3823
|
+
const toTint = kf.to?.tint;
|
|
3824
|
+
const setTint = kf.set?.tint;
|
|
3825
|
+
if (setTint !== void 0) {
|
|
3826
|
+
const sprite = this.target;
|
|
3827
|
+
revertibleSet(timeline, at, () => sprite.tint, (c) => {
|
|
3828
|
+
sprite.tint = c;
|
|
3829
|
+
}, setTint, [sprite, "tint"]);
|
|
3830
|
+
}
|
|
3831
|
+
if (toTint !== void 0) {
|
|
3832
|
+
tweenColor(
|
|
3833
|
+
timeline,
|
|
3834
|
+
this.target,
|
|
3835
|
+
"tint",
|
|
3836
|
+
fromTint,
|
|
3837
|
+
toTint,
|
|
3838
|
+
duration,
|
|
3839
|
+
ease,
|
|
3840
|
+
at,
|
|
3841
|
+
colorSpace,
|
|
3842
|
+
void 0,
|
|
3843
|
+
loopVars(kf)
|
|
3844
|
+
);
|
|
3845
|
+
}
|
|
3846
|
+
}
|
|
3847
|
+
this.absoluteStart = startTime;
|
|
3848
|
+
const endTime = startTime + this.duration;
|
|
3849
|
+
if (this.keepHidden) return;
|
|
3850
|
+
this.target.renderable = startTime <= 0;
|
|
3851
|
+
timeline.set(this.target, { renderable: true }, startTime);
|
|
3852
|
+
timeline.set(this.target, { renderable: false }, endTime);
|
|
3853
|
+
}
|
|
3854
|
+
};
|
|
3855
|
+
function stripKeys2(props, keys) {
|
|
3856
|
+
if (!props) return props;
|
|
3857
|
+
const drop = new Set(keys);
|
|
3858
|
+
const out = {};
|
|
3859
|
+
let changed = false;
|
|
3860
|
+
for (const k of Object.keys(props)) {
|
|
3861
|
+
if (drop.has(k)) {
|
|
3862
|
+
changed = true;
|
|
3863
|
+
continue;
|
|
3665
3864
|
}
|
|
3865
|
+
out[k] = props[k];
|
|
3666
3866
|
}
|
|
3867
|
+
return changed ? out : props;
|
|
3667
3868
|
}
|
|
3668
|
-
function
|
|
3669
|
-
|
|
3670
|
-
|
|
3671
|
-
|
|
3672
|
-
|
|
3869
|
+
function stripKeysInKeyframe(kf, keys) {
|
|
3870
|
+
return {
|
|
3871
|
+
...kf,
|
|
3872
|
+
set: stripKeys2(kf.set, keys),
|
|
3873
|
+
to: stripKeys2(kf.to, keys),
|
|
3874
|
+
from: stripKeys2(kf.from, keys)
|
|
3875
|
+
};
|
|
3673
3876
|
}
|
|
3674
3877
|
var AudioSequence = class extends Sequence {
|
|
3675
3878
|
_audioBuffer = null;
|
|
@@ -3694,12 +3897,12 @@ var AudioSequence = class extends Sequence {
|
|
|
3694
3897
|
const playable = this._remap && this._remap.timeKfs.length > 0 ? Infinity : (data.duration ?? Infinity) / constant;
|
|
3695
3898
|
if (!spec.loop && Number.isFinite(playable) && this.duration > playable + 0.05) {
|
|
3696
3899
|
console.warn(
|
|
3697
|
-
`pixi-effects: ${
|
|
3900
|
+
`pixi-effects: ${chunkGL2AQFLQ_cjs.describeLayer(spec)}: audio asset "${spec.asset}" plays for ${playable.toFixed(1)}s (${data.duration.toFixed(1)}s at speed ${constant}) but the layer lasts ${this.duration.toFixed(1)}s, so it goes silent after ${playable.toFixed(1)}s. Add loop: true, or shorten the layer's duration.`
|
|
3698
3901
|
);
|
|
3699
3902
|
}
|
|
3700
3903
|
}
|
|
3701
3904
|
async _buildSfx(spec) {
|
|
3702
|
-
const who =
|
|
3905
|
+
const who = chunkGL2AQFLQ_cjs.describeLayer(spec);
|
|
3703
3906
|
const raw = spec;
|
|
3704
3907
|
if (raw.asset !== void 0) console.warn(`pixi-effects: ${who}: has both asset and sfx \u2014 the sfx plays; remove one`);
|
|
3705
3908
|
if (raw.loop) console.warn(`pixi-effects: ${who}: loop has no effect on an sfx \u2014 to repeat it, add one audio layer per hit (a JS loop)`);
|
|
@@ -3718,7 +3921,7 @@ var AudioSequence = class extends Sequence {
|
|
|
3718
3921
|
});
|
|
3719
3922
|
}
|
|
3720
3923
|
async _buildMusic(spec) {
|
|
3721
|
-
const who =
|
|
3924
|
+
const who = chunkGL2AQFLQ_cjs.describeLayer(spec);
|
|
3722
3925
|
const raw = spec;
|
|
3723
3926
|
if (raw.asset !== void 0) console.warn(`pixi-effects: ${who}: has both asset and music \u2014 the music plays; remove one`);
|
|
3724
3927
|
if (raw.sfx !== void 0) console.warn(`pixi-effects: ${who}: has both sfx and music \u2014 the music plays; remove one`);
|
|
@@ -3753,7 +3956,7 @@ var AudioSequence = class extends Sequence {
|
|
|
3753
3956
|
out.push({
|
|
3754
3957
|
...sourceMap ? { sourceMap } : {},
|
|
3755
3958
|
...this._audioBuffer ? { buffer: this._audioBuffer } : { synth: this._synth },
|
|
3756
|
-
layer:
|
|
3959
|
+
layer: chunkGL2AQFLQ_cjs.describeLayer(this.spec),
|
|
3757
3960
|
source: this._source,
|
|
3758
3961
|
...this._music ? { music: this._music } : {},
|
|
3759
3962
|
loop: !this._synth && !!this.spec.loop,
|
|
@@ -4295,7 +4498,7 @@ var VideoSequence = class extends Sequence {
|
|
|
4295
4498
|
out.push({
|
|
4296
4499
|
...sourceMap ? { sourceMap } : {},
|
|
4297
4500
|
buffer: this._audioBuffer,
|
|
4298
|
-
layer:
|
|
4501
|
+
layer: chunkGL2AQFLQ_cjs.describeLayer(this.spec),
|
|
4299
4502
|
source: `video "${this.spec.asset}"`,
|
|
4300
4503
|
loop: !!this.spec.loop,
|
|
4301
4504
|
start: baseTime + this.at,
|
|
@@ -4563,20 +4766,20 @@ var ShapeSequence = class extends Sequence {
|
|
|
4563
4766
|
for (const k of geomKeys) this._liveKeys.add(k);
|
|
4564
4767
|
seedGeometry(this._state, this.spec, scope);
|
|
4565
4768
|
seedStyle(this._state, this.spec.initial ?? {}, scope);
|
|
4566
|
-
seedStrokeStyle(this._state, this.spec, this.spec.initial ?? {},
|
|
4769
|
+
seedStrokeStyle(this._state, this.spec, this.spec.initial ?? {}, chunkGL2AQFLQ_cjs.describeLayer(this.spec));
|
|
4567
4770
|
if (this.spec.shape === "arc") {
|
|
4568
4771
|
this._state.startAngle ??= 0;
|
|
4569
4772
|
this._state.endAngle ??= 360;
|
|
4570
4773
|
const top = this.spec, ini = this.spec.initial ?? {};
|
|
4571
4774
|
if ("trimStart" in top || "trimEnd" in top || "trimStart" in ini || "trimEnd" in ini) {
|
|
4572
|
-
console.warn(`pixi-effects: ${
|
|
4775
|
+
console.warn(`pixi-effects: ${chunkGL2AQFLQ_cjs.describeLayer(this.spec)}: trimStart / trimEnd do not apply to an arc: animate its endAngle (and startAngle) instead`);
|
|
4573
4776
|
}
|
|
4574
4777
|
} else {
|
|
4575
4778
|
this._state.trimStart ??= 0;
|
|
4576
4779
|
this._state.trimEnd ??= 1;
|
|
4577
4780
|
}
|
|
4578
4781
|
const gradientSpec = this.spec.fillGradient ?? this.spec.initial?.fillGradient;
|
|
4579
|
-
validateGradientKeyframes(this.spec,
|
|
4782
|
+
validateGradientKeyframes(this.spec, chunkGL2AQFLQ_cjs.describeLayer(this.spec));
|
|
4580
4783
|
if (gradientSpec) {
|
|
4581
4784
|
if (hasGradientKeys(this.spec.keyframes)) {
|
|
4582
4785
|
this._grad = { grad: gradStateFrom(gradientSpec) };
|
|
@@ -4618,9 +4821,9 @@ var ShapeSequence = class extends Sequence {
|
|
|
4618
4821
|
}
|
|
4619
4822
|
/** The prepared morph between `d` and `morphTo`, or null (and a warning when the spec asked for one that cannot work). */
|
|
4620
4823
|
_setupMorph() {
|
|
4621
|
-
const who =
|
|
4824
|
+
const who = chunkGL2AQFLQ_cjs.describeLayer(this.spec);
|
|
4622
4825
|
const top = this.spec;
|
|
4623
|
-
const wanted = this.spec.shape === "path" && (this._state.morph !== void 0 ||
|
|
4826
|
+
const wanted = this.spec.shape === "path" && (this._state.morph !== void 0 || chunkGL2AQFLQ_cjs.collectPropKeys(this.spec).has("morph"));
|
|
4624
4827
|
if (this.spec.shape !== "path") {
|
|
4625
4828
|
if ("morphTo" in top) console.warn(`pixi-effects: ${who}: morphTo only works on a path shape (shape: 'path'); ignored`);
|
|
4626
4829
|
return null;
|
|
@@ -5230,7 +5433,7 @@ var ShaderSequence = class extends Sequence {
|
|
|
5230
5433
|
}
|
|
5231
5434
|
async build() {
|
|
5232
5435
|
const spec = this.shaderSpec;
|
|
5233
|
-
const who =
|
|
5436
|
+
const who = chunkGL2AQFLQ_cjs.describeLayer(spec);
|
|
5234
5437
|
for (const m of shaderProblems(spec)) console.warn(`pixi-effects: ${who}: ${m}`);
|
|
5235
5438
|
if (this.duration === void 0) this.duration = this.parent?.duration ?? this.root.duration;
|
|
5236
5439
|
const scope = buildScope(this, this.parent, this.root);
|
|
@@ -5274,7 +5477,7 @@ var ShaderSequence = class extends Sequence {
|
|
|
5274
5477
|
const warn = (why) => {
|
|
5275
5478
|
if (this.warnedPaths.has(path)) return;
|
|
5276
5479
|
this.warnedPaths.add(path);
|
|
5277
|
-
console.warn(`pixi-effects: ${
|
|
5480
|
+
console.warn(`pixi-effects: ${chunkGL2AQFLQ_cjs.describeLayer(this.spec)}: keyframe path uniforms.${path} ${why}; skipped`);
|
|
5278
5481
|
};
|
|
5279
5482
|
if (slot === void 0) {
|
|
5280
5483
|
const guess = chunkTWZNOUM7_cjs.suggestName(name, Object.keys(this.carrier));
|
|
@@ -5309,7 +5512,7 @@ var ShaderSequence = class extends Sequence {
|
|
|
5309
5512
|
this.failed = true;
|
|
5310
5513
|
if (!this.warnedNoGl) {
|
|
5311
5514
|
this.warnedNoGl = true;
|
|
5312
|
-
console.warn(`pixi-effects: ${
|
|
5515
|
+
console.warn(`pixi-effects: ${chunkGL2AQFLQ_cjs.describeLayer(this.spec)}: this browser has no WebGL2, so the shader cannot run; the layer is drawn as a checkerboard`);
|
|
5313
5516
|
}
|
|
5314
5517
|
}
|
|
5315
5518
|
compile() {
|
|
@@ -5340,7 +5543,7 @@ var ShaderSequence = class extends Sequence {
|
|
|
5340
5543
|
gl.deleteProgram(p);
|
|
5341
5544
|
this.failed = true;
|
|
5342
5545
|
this.prog = null;
|
|
5343
|
-
console.warn(`pixi-effects: ${
|
|
5546
|
+
console.warn(`pixi-effects: ${chunkGL2AQFLQ_cjs.describeLayer(this.spec)}: the fragment shader did not compile (the line numbers are the lines of your code):
|
|
5344
5547
|
${glslErrors(log).join("\n")}
|
|
5345
5548
|
The layer is drawn as a checkerboard until it is fixed.`);
|
|
5346
5549
|
return;
|
|
@@ -5424,10 +5627,15 @@ function resolveDim(v, scope) {
|
|
|
5424
5627
|
var _CompositionSequence = null;
|
|
5425
5628
|
async function getCompositionSequence() {
|
|
5426
5629
|
if (!_CompositionSequence) {
|
|
5427
|
-
_CompositionSequence = (await import('./Composition-
|
|
5630
|
+
_CompositionSequence = (await import('./Composition-L6OALWHI.cjs')).CompositionSequence;
|
|
5428
5631
|
}
|
|
5429
5632
|
return _CompositionSequence;
|
|
5430
5633
|
}
|
|
5634
|
+
var _SpansSequence = null;
|
|
5635
|
+
async function getSpansSequence() {
|
|
5636
|
+
if (!_SpansSequence) _SpansSequence = (await import('./Spans-VXNQXSI3.cjs')).SpansSequence;
|
|
5637
|
+
return _SpansSequence;
|
|
5638
|
+
}
|
|
5431
5639
|
var staticTypes = {
|
|
5432
5640
|
image: ImageSequence,
|
|
5433
5641
|
text: TextSequence,
|
|
@@ -5445,8 +5653,12 @@ function registerSequenceType(type, ctor) {
|
|
|
5445
5653
|
}
|
|
5446
5654
|
async function buildSequenceTree(specs, parent, root) {
|
|
5447
5655
|
const out = [];
|
|
5448
|
-
for (
|
|
5656
|
+
for (let spec of specs) {
|
|
5449
5657
|
let Cls = staticTypes[spec.type] ?? registry2[spec.type];
|
|
5658
|
+
if (spec.type === "text" && spec.spans !== void 0) {
|
|
5659
|
+
spec = expandSpans(spec, void 0, buildScope({ intrinsicWidth: 0, intrinsicHeight: 0, at: spec.at, duration: spec.duration }, parent, root));
|
|
5660
|
+
Cls = await getSpansSequence();
|
|
5661
|
+
}
|
|
5450
5662
|
if (!Cls && spec.type === "composition") {
|
|
5451
5663
|
Cls = await getCompositionSequence();
|
|
5452
5664
|
}
|
|
@@ -5483,7 +5695,9 @@ exports.NEAR = NEAR;
|
|
|
5483
5695
|
exports.NullSequence = NullSequence;
|
|
5484
5696
|
exports.SHADOW_TAPS = SHADOW_TAPS;
|
|
5485
5697
|
exports.Sequence = Sequence;
|
|
5698
|
+
exports.TextSequence = TextSequence;
|
|
5486
5699
|
exports.bindClock = bindClock;
|
|
5700
|
+
exports.bindCounterKeyframes = bindCounterKeyframes;
|
|
5487
5701
|
exports.blurRadius = blurRadius;
|
|
5488
5702
|
exports.buildScope = buildScope;
|
|
5489
5703
|
exports.buildSequenceTree = buildSequenceTree;
|
|
@@ -5505,6 +5719,7 @@ exports.lightLevel = lightLevel;
|
|
|
5505
5719
|
exports.noise = noise;
|
|
5506
5720
|
exports.packLights = packLights;
|
|
5507
5721
|
exports.parseEase = parseEase;
|
|
5722
|
+
exports.parseSpring = parseSpring;
|
|
5508
5723
|
exports.projectLayer = projectLayer;
|
|
5509
5724
|
exports.projectPoint = projectPoint;
|
|
5510
5725
|
exports.rand = rand;
|
|
@@ -5512,6 +5727,9 @@ exports.random = random;
|
|
|
5512
5727
|
exports.registerSequenceType = registerSequenceType;
|
|
5513
5728
|
exports.remapOf = remapOf;
|
|
5514
5729
|
exports.resolveAt = resolveAt;
|
|
5730
|
+
exports.resolveNumber = resolveNumber;
|
|
5731
|
+
exports.spansMeta = spansMeta;
|
|
5732
|
+
exports.springDuration = springDuration;
|
|
5515
5733
|
exports.timeRemapOf = timeRemapOf;
|
|
5516
|
-
//# sourceMappingURL=chunk-
|
|
5517
|
-
//# sourceMappingURL=chunk-
|
|
5734
|
+
//# sourceMappingURL=chunk-BVMZUPDU.cjs.map
|
|
5735
|
+
//# sourceMappingURL=chunk-BVMZUPDU.cjs.map
|