pixi-effects 0.4.0 → 0.6.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 +45 -1
- package/README.md +11 -6
- package/ai/SKILL.md +7 -4
- package/ai/reference/cheatsheet.md +18 -5
- package/ai/reference/pitfalls.md +16 -11
- package/ai/reference/recipes.md +153 -1
- package/ai/template.html +6 -3
- package/ai/tools/check.mjs +385 -0
- package/dist/{Base-DhY9oMxr.d.ts → Base-4vNLl4tH.d.cts} +6 -1
- package/dist/{Base-5R7C5pHR.d.cts → Base-CD4AoT5-.d.ts} +6 -1
- package/dist/Composition-7SO5WYHU.js +4 -0
- package/dist/{Composition-RGTRZ2JX.js.map → Composition-7SO5WYHU.js.map} +1 -1
- package/dist/Composition-Y5VZSDDP.cjs +13 -0
- package/dist/{Composition-D7RCAGEA.cjs.map → Composition-Y5VZSDDP.cjs.map} +1 -1
- package/dist/Controller.cjs +47 -15
- package/dist/Controller.cjs.map +1 -1
- package/dist/Controller.d.cts +5 -2
- package/dist/Controller.d.ts +5 -2
- package/dist/Controller.js +47 -15
- package/dist/Controller.js.map +1 -1
- package/dist/{Movie-DRZtIGU7.d.ts → Movie-CADDBfpl.d.cts} +58 -2
- package/dist/{Movie-CghFXprP.d.cts → Movie-Ch2SUI1h.d.ts} +58 -2
- package/dist/{chunk-QGBOC5YL.cjs → chunk-4AGJF5RK.cjs} +33 -21
- package/dist/chunk-4AGJF5RK.cjs.map +1 -0
- package/dist/{chunk-ZQX7WIYL.js → chunk-7IJHJXDI.js} +380 -64
- package/dist/chunk-7IJHJXDI.js.map +1 -0
- package/dist/{chunk-A574IA4F.js → chunk-B2FTJLNB.js} +18 -6
- package/dist/chunk-B2FTJLNB.js.map +1 -0
- package/dist/chunk-DKGG7WD4.js +61 -0
- package/dist/chunk-DKGG7WD4.js.map +1 -0
- package/dist/{chunk-6BQ6IEW2.cjs → chunk-KQM2ZZMK.cjs} +380 -63
- package/dist/chunk-KQM2ZZMK.cjs.map +1 -0
- package/dist/chunk-UQBGW5DO.cjs +64 -0
- package/dist/chunk-UQBGW5DO.cjs.map +1 -0
- package/dist/index.cjs +333 -89
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +54 -5
- package/dist/index.d.ts +54 -5
- package/dist/index.js +317 -75
- package/dist/index.js.map +1 -1
- package/dist/sfx-MZJZXYY3.cjs +446 -0
- package/dist/sfx-MZJZXYY3.cjs.map +1 -0
- package/dist/sfx-S37DDC66.js +434 -0
- package/dist/sfx-S37DDC66.js.map +1 -0
- package/dist/three.cjs +5 -5
- package/dist/three.d.cts +2 -2
- package/dist/three.d.ts +2 -2
- package/dist/three.js +1 -1
- package/dist/{types-CRE9WKd4.d.ts → types-DrW9QeKU.d.cts} +118 -12
- package/dist/{types-CRE9WKd4.d.cts → types-DrW9QeKU.d.ts} +118 -12
- package/docs/api.md +37 -0
- package/docs/dsl.md +70 -10
- package/llms-full.txt +300 -30
- package/llms.txt +1 -1
- package/package.json +2 -1
- package/dist/Composition-D7RCAGEA.cjs +0 -13
- package/dist/Composition-RGTRZ2JX.js +0 -4
- package/dist/chunk-6BQ6IEW2.cjs.map +0 -1
- package/dist/chunk-A574IA4F.js.map +0 -1
- package/dist/chunk-QGBOC5YL.cjs.map +0 -1
- package/dist/chunk-ZQX7WIYL.js.map +0 -1
|
@@ -739,6 +739,11 @@ var Sequence = class {
|
|
|
739
739
|
* (not a normal child) by PIXI when `target.mask = maskSequence.target`.
|
|
740
740
|
*/
|
|
741
741
|
maskSequence = null;
|
|
742
|
+
/**
|
|
743
|
+
* Set by the parent composition on a sprite-based (image / video) mask. PIXI hides such a mask with
|
|
744
|
+
* `renderable = false`; the lifespan toggles must not switch it back on, or the mask is drawn as a picture.
|
|
745
|
+
*/
|
|
746
|
+
keepHidden = false;
|
|
742
747
|
/**
|
|
743
748
|
* Absolute start time on the global timeline (offset + at), recorded by
|
|
744
749
|
* bindTimeline. Movie._awaitVideoFrames uses it to determine the correct
|
|
@@ -783,6 +788,7 @@ var Sequence = class {
|
|
|
783
788
|
applyKeyframes(timeline, this.target, this.spec.keyframes, this.duration, scope, [], startTime, routers);
|
|
784
789
|
const endTime = startTime + this.duration;
|
|
785
790
|
this.absoluteStart = startTime;
|
|
791
|
+
if (this.keepHidden) return;
|
|
786
792
|
this.target.renderable = startTime <= 0;
|
|
787
793
|
timeline.set(this.target, { renderable: true }, startTime);
|
|
788
794
|
timeline.set(this.target, { renderable: false }, endTime);
|
|
@@ -835,6 +841,7 @@ function lintTiming(spec, parentDuration, warn = defaultWarn) {
|
|
|
835
841
|
if (at >= parentDuration) {
|
|
836
842
|
warn(`pixi-effects: ${who} starts at ${at}s, after its composition ends (${parentDuration}s), so it is never visible`);
|
|
837
843
|
}
|
|
844
|
+
if (spec.type === "audio" && spec.sfx !== void 0 && spec.duration === void 0) return;
|
|
838
845
|
const duration = spec.duration ?? parentDuration;
|
|
839
846
|
(spec.keyframes ?? []).forEach((kf, i) => {
|
|
840
847
|
const kat = kf.at ?? 0;
|
|
@@ -852,7 +859,12 @@ function summarizeWarnings(messages, shown = 3) {
|
|
|
852
859
|
}
|
|
853
860
|
function lintText(spec, warn = defaultWarn) {
|
|
854
861
|
if (spec.type !== "text") return;
|
|
855
|
-
|
|
862
|
+
const strings = [spec.text ?? "", ...(spec.keyframes ?? []).map((kf) => String(kf.set?.text ?? ""))];
|
|
863
|
+
const hasPlaceholder = strings.some((t) => t.includes("{value}"));
|
|
864
|
+
if (hasPlaceholder && !collectPropKeys(spec).has("value")) {
|
|
865
|
+
warn(`pixi-effects: ${describeLayer(spec)}: the text has a {value} placeholder but nothing sets or animates \`value\`, so it prints 0. Set initial: { value: \u2026 } or animate it; {value} is reserved for counters (there is no way to print a literal "{value}").`);
|
|
866
|
+
}
|
|
867
|
+
if (collectPropKeys(spec).has("value") && !hasPlaceholder) {
|
|
856
868
|
warn(`pixi-effects: ${describeLayer(spec)}: \`value\` is set or animated but the text has no {value} placeholder, so nothing shows it. Use text: '{value}' (or e.g. '{value} users').`);
|
|
857
869
|
}
|
|
858
870
|
}
|
|
@@ -1046,6 +1058,8 @@ function revertibleSet(timeline, at, read, write, value) {
|
|
|
1046
1058
|
}
|
|
1047
1059
|
|
|
1048
1060
|
// src/expr/colorInterp.ts
|
|
1061
|
+
var CHROMA_FLOOR = 0.03;
|
|
1062
|
+
var CHROMA_FULL = 0.08;
|
|
1049
1063
|
function buildColorInterp(from, to, space) {
|
|
1050
1064
|
const fromRGBA = parseToRGBA(from);
|
|
1051
1065
|
const toRGBA = parseToRGBA(to);
|
|
@@ -1062,8 +1076,9 @@ function buildColorInterp(from, to, space) {
|
|
|
1062
1076
|
}
|
|
1063
1077
|
const fromLCH = oklabToOklch(fromOk);
|
|
1064
1078
|
const toLCH = oklabToOklch(toOk);
|
|
1065
|
-
|
|
1066
|
-
|
|
1079
|
+
const fromHue = fromLCH.h, toHue = toLCH.h;
|
|
1080
|
+
fromLCH.h = borrowHue(fromHue, fromLCH.C, toHue);
|
|
1081
|
+
toLCH.h = borrowHue(toHue, toLCH.C, fromHue);
|
|
1067
1082
|
const hueDelta = shortestHueDelta(fromLCH.h, toLCH.h);
|
|
1068
1083
|
return (t) => {
|
|
1069
1084
|
const L = lerp(fromLCH.L, toLCH.L, t);
|
|
@@ -1074,6 +1089,11 @@ function buildColorInterp(from, to, space) {
|
|
|
1074
1089
|
return rgbaString(oklabToRgb(ab), alpha);
|
|
1075
1090
|
};
|
|
1076
1091
|
}
|
|
1092
|
+
function borrowHue(own, chroma, other) {
|
|
1093
|
+
const u = Math.min(1, Math.max(0, (chroma - CHROMA_FLOOR) / (CHROMA_FULL - CHROMA_FLOOR)));
|
|
1094
|
+
const keep = u * u * (3 - 2 * u);
|
|
1095
|
+
return own + shortestHueDelta(own, other) * (1 - keep);
|
|
1096
|
+
}
|
|
1077
1097
|
function parseToRGBA(input) {
|
|
1078
1098
|
if (typeof input === "number") {
|
|
1079
1099
|
return { r: (input >> 16 & 255) / 255, g: (input >> 8 & 255) / 255, b: (input & 255) / 255, a: 1 };
|
|
@@ -1258,6 +1278,7 @@ var ImageSequence = class extends Sequence {
|
|
|
1258
1278
|
}
|
|
1259
1279
|
this.absoluteStart = startTime;
|
|
1260
1280
|
const endTime = startTime + this.duration;
|
|
1281
|
+
if (this.keepHidden) return;
|
|
1261
1282
|
this.target.renderable = startTime <= 0;
|
|
1262
1283
|
timeline.set(this.target, { renderable: true }, startTime);
|
|
1263
1284
|
timeline.set(this.target, { renderable: false }, endTime);
|
|
@@ -1302,19 +1323,31 @@ var STYLE_OPAQUE_KEYS = [
|
|
|
1302
1323
|
];
|
|
1303
1324
|
function formatValue(v, f) {
|
|
1304
1325
|
const fixed = v.toFixed(Math.max(0, Math.floor(f?.decimals ?? 0)));
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
|
|
1326
|
+
const pad = Math.max(0, Math.floor(f?.pad ?? 0));
|
|
1327
|
+
if (!f?.grouping && !pad) return fixed;
|
|
1328
|
+
const [signed, frac] = fixed.split(".");
|
|
1329
|
+
const sign = signed.startsWith("-") ? "-" : "";
|
|
1330
|
+
let int = sign ? signed.slice(1) : signed;
|
|
1331
|
+
if (pad) int = int.padStart(pad, "0");
|
|
1332
|
+
if (f?.grouping) int = int.replace(/\B(?=(\d{3})+(?!\d))/g, ",");
|
|
1333
|
+
return sign + int + (frac !== void 0 ? "." + frac : "");
|
|
1308
1334
|
}
|
|
1309
1335
|
var TextSequence = class extends Sequence {
|
|
1310
|
-
/**
|
|
1311
|
-
|
|
1336
|
+
/** `value`: the number for the `{value}` placeholder; `visibleChars`: how many characters show (typewriter). Both tweened by keyframes. */
|
|
1337
|
+
_counters = { value: 0, visibleChars: 0 };
|
|
1338
|
+
/** The string now on the layer (before `{value}` / `visibleChars`): `text`, or the last `set: { text }`. */
|
|
1339
|
+
_template = "";
|
|
1340
|
+
/** `visibleChars` is in play (initial or animated): otherwise the whole text shows. */
|
|
1341
|
+
_typed = false;
|
|
1312
1342
|
_lastText = "";
|
|
1313
|
-
/**
|
|
1343
|
+
/** A typewriter that has typed nothing yet: the layer is empty on purpose (inspect must not call that "no size"). */
|
|
1344
|
+
get showsNothingYet() {
|
|
1345
|
+
return this._typed && this._lastText === "" && this._template !== "";
|
|
1346
|
+
}
|
|
1347
|
+
/** Rewrite the displayed string from the template, the current `value` and `visibleChars`. */
|
|
1314
1348
|
_refreshText() {
|
|
1315
|
-
|
|
1316
|
-
if (
|
|
1317
|
-
const next = template.split("{value}").join(formatValue(this._value.value, this.spec.format));
|
|
1349
|
+
let next = this._template.includes("{value}") ? this._template.split("{value}").join(formatValue(this._counters.value, this.spec.format)) : this._template;
|
|
1350
|
+
if (this._typed) next = Array.from(next).slice(0, Math.max(0, Math.floor(this._counters.visibleChars))).join("");
|
|
1318
1351
|
if (next === this._lastText) return;
|
|
1319
1352
|
this._lastText = next;
|
|
1320
1353
|
this.target.text = next;
|
|
@@ -1326,8 +1359,10 @@ var TextSequence = class extends Sequence {
|
|
|
1326
1359
|
fill: "#ffffff",
|
|
1327
1360
|
align: "center"
|
|
1328
1361
|
};
|
|
1362
|
+
const initialProps = this.spec.initial ?? {};
|
|
1363
|
+
this._template = String(initialProps.text ?? this.spec.text ?? "");
|
|
1329
1364
|
const text = new Text({
|
|
1330
|
-
text: this.
|
|
1365
|
+
text: this._template,
|
|
1331
1366
|
style: baseStyle,
|
|
1332
1367
|
label: this.spec.name
|
|
1333
1368
|
});
|
|
@@ -1339,10 +1374,10 @@ var TextSequence = class extends Sequence {
|
|
|
1339
1374
|
this.duration = this.parent?.duration ?? this.root.duration;
|
|
1340
1375
|
}
|
|
1341
1376
|
if (this.spec.style) {
|
|
1342
|
-
const
|
|
1377
|
+
const scope2 = this.scope();
|
|
1343
1378
|
const resolved = normalizeProps(
|
|
1344
1379
|
this.spec.style,
|
|
1345
|
-
|
|
1380
|
+
scope2,
|
|
1346
1381
|
{ skipKeys: STYLE_OPAQUE_KEYS }
|
|
1347
1382
|
);
|
|
1348
1383
|
for (const k of Object.keys(resolved)) {
|
|
@@ -1351,22 +1386,36 @@ var TextSequence = class extends Sequence {
|
|
|
1351
1386
|
this.intrinsicWidth = text.width;
|
|
1352
1387
|
this.intrinsicHeight = text.height;
|
|
1353
1388
|
}
|
|
1354
|
-
const
|
|
1355
|
-
if (
|
|
1389
|
+
const scope = this.scope();
|
|
1390
|
+
if (initialProps.value !== void 0) this._counters.value = resolveNumber(initialProps.value, scope);
|
|
1391
|
+
this._typed = initialProps.visibleChars !== void 0 || animates(this.spec.keyframes, "visibleChars");
|
|
1392
|
+
if (initialProps.visibleChars !== void 0) this._counters.visibleChars = resolveNumber(initialProps.visibleChars, scope);
|
|
1393
|
+
const typed = this._typed;
|
|
1394
|
+
this._typed = false;
|
|
1356
1395
|
this._refreshText();
|
|
1357
1396
|
if (this._lastText !== "") {
|
|
1358
1397
|
this.intrinsicWidth = text.width;
|
|
1359
1398
|
this.intrinsicHeight = text.height;
|
|
1360
1399
|
}
|
|
1400
|
+
this._typed = typed;
|
|
1401
|
+
this._refreshText();
|
|
1361
1402
|
this.buildFilters();
|
|
1362
1403
|
}
|
|
1363
1404
|
bindTimeline(timeline, offset = 0) {
|
|
1364
1405
|
if (!this.target) return;
|
|
1365
1406
|
const colorSpace = this.spec.colorSpace ?? "rgb";
|
|
1366
|
-
const stripped = stripKeys2(this.spec, ["fill", "value"]);
|
|
1407
|
+
const stripped = stripKeys2(this.spec, ["fill", "value", "text", "visibleChars"]);
|
|
1367
1408
|
runSuperWithStrippedSpec(this, stripped, timeline, offset);
|
|
1368
|
-
|
|
1369
|
-
|
|
1409
|
+
const keyframes = this.spec.keyframes ?? [];
|
|
1410
|
+
const origin = offset + this.at;
|
|
1411
|
+
bindFillKeyframes(timeline, this.target, keyframes, this.duration, origin, colorSpace);
|
|
1412
|
+
const refresh = () => this._refreshText();
|
|
1413
|
+
bindCounterKeyframes(timeline, this._counters, "value", refresh, keyframes, this.duration, origin, this.scope());
|
|
1414
|
+
bindCounterKeyframes(timeline, this._counters, "visibleChars", refresh, keyframes, this.duration, origin, this.scope());
|
|
1415
|
+
bindTextKeyframes(timeline, keyframes, this.duration, origin, () => this._template, (t) => {
|
|
1416
|
+
this._template = t;
|
|
1417
|
+
refresh();
|
|
1418
|
+
}, describeLayer(this.spec));
|
|
1370
1419
|
}
|
|
1371
1420
|
};
|
|
1372
1421
|
function runSuperWithStrippedSpec(inst, strippedSpec, timeline, offset) {
|
|
@@ -1402,11 +1451,11 @@ function resolveNumber(v, scope) {
|
|
|
1402
1451
|
const out = normalizeProps({ v }, scope).v;
|
|
1403
1452
|
return typeof out === "number" ? out : Number(out) || 0;
|
|
1404
1453
|
}
|
|
1405
|
-
function
|
|
1454
|
+
function bindCounterKeyframes(timeline, state, key, refresh, keyframes, parentDuration, origin, scope) {
|
|
1406
1455
|
for (const kf of keyframes) {
|
|
1407
|
-
const setV = kf.set?.
|
|
1408
|
-
const fromV = kf.from?.
|
|
1409
|
-
const toV = kf.to?.
|
|
1456
|
+
const setV = kf.set?.[key];
|
|
1457
|
+
const fromV = kf.from?.[key];
|
|
1458
|
+
const toV = kf.to?.[key];
|
|
1410
1459
|
if (setV === void 0 && fromV === void 0 && toV === void 0) continue;
|
|
1411
1460
|
const at = origin + resolveAt(kf.at, parentDuration);
|
|
1412
1461
|
const duration = kf.duration ?? 0;
|
|
@@ -1414,25 +1463,40 @@ function bindValueKeyframes(timeline, state, refresh, keyframes, parentDuration,
|
|
|
1414
1463
|
const loop = loopVars(kf);
|
|
1415
1464
|
if (setV !== void 0) {
|
|
1416
1465
|
const v = resolveNumber(setV, scope);
|
|
1417
|
-
revertibleSet(timeline, at, () => state
|
|
1418
|
-
state
|
|
1466
|
+
revertibleSet(timeline, at, () => state[key], (n) => {
|
|
1467
|
+
state[key] = n;
|
|
1419
1468
|
refresh();
|
|
1420
1469
|
}, v);
|
|
1421
1470
|
}
|
|
1422
1471
|
if (toV !== void 0 && fromV !== void 0) {
|
|
1423
1472
|
timeline.fromTo(
|
|
1424
1473
|
state,
|
|
1425
|
-
{
|
|
1426
|
-
{
|
|
1474
|
+
{ [key]: resolveNumber(fromV, scope) },
|
|
1475
|
+
{ [key]: resolveNumber(toV, scope), duration, ease, ...loop, onUpdate: refresh },
|
|
1427
1476
|
at
|
|
1428
1477
|
);
|
|
1429
1478
|
} else if (toV !== void 0) {
|
|
1430
|
-
timeline.to(state, {
|
|
1479
|
+
timeline.to(state, { [key]: resolveNumber(toV, scope), duration, ease, ...loop, onUpdate: refresh }, at);
|
|
1431
1480
|
} else if (fromV !== void 0) {
|
|
1432
|
-
timeline.from(state, {
|
|
1481
|
+
timeline.from(state, { [key]: resolveNumber(fromV, scope), duration, ease, ...loop, onUpdate: refresh }, at);
|
|
1433
1482
|
}
|
|
1434
1483
|
}
|
|
1435
1484
|
}
|
|
1485
|
+
function bindTextKeyframes(timeline, keyframes, parentDuration, origin, read, write, who) {
|
|
1486
|
+
for (const kf of keyframes) {
|
|
1487
|
+
for (const [what, props] of [["to", kf.to], ["from", kf.from]]) {
|
|
1488
|
+
if (props && props.text !== void 0) {
|
|
1489
|
+
console.warn(`pixi-effects: ${who}: a keyframe's ${what}: { text } cannot tween a string: use set: { text: '\u2026' } at the time it should change`);
|
|
1490
|
+
}
|
|
1491
|
+
}
|
|
1492
|
+
const t = kf.set?.text;
|
|
1493
|
+
if (t === void 0) continue;
|
|
1494
|
+
revertibleSet(timeline, origin + resolveAt(kf.at, parentDuration), read, write, String(t));
|
|
1495
|
+
}
|
|
1496
|
+
}
|
|
1497
|
+
function animates(keyframes, key) {
|
|
1498
|
+
return (keyframes ?? []).some((kf) => [kf.set, kf.to, kf.from].some((p) => p && p[key] !== void 0));
|
|
1499
|
+
}
|
|
1436
1500
|
function bindFillKeyframes(timeline, text, keyframes, parentDuration, offset, colorSpace) {
|
|
1437
1501
|
const state = { fill: text.style.fill };
|
|
1438
1502
|
const writeFill = () => {
|
|
@@ -1476,28 +1540,64 @@ function pickFill(props) {
|
|
|
1476
1540
|
}
|
|
1477
1541
|
var AudioSequence = class extends Sequence {
|
|
1478
1542
|
_audioBuffer = null;
|
|
1543
|
+
_synth = null;
|
|
1544
|
+
_source = "";
|
|
1479
1545
|
async build() {
|
|
1480
|
-
|
|
1546
|
+
this.target = null;
|
|
1547
|
+
if (this.spec.sfx !== void 0) return this._buildSfx(this.spec);
|
|
1548
|
+
const spec = this.spec;
|
|
1549
|
+
this._source = `asset "${spec.asset}"`;
|
|
1550
|
+
const data = await Assets.get(spec.asset);
|
|
1481
1551
|
this._audioBuffer = data.audioBuffer;
|
|
1482
1552
|
if (this.duration === void 0) {
|
|
1483
1553
|
const rest = Math.max(0, (this.parent?.duration ?? this.root.duration) - this.at);
|
|
1484
|
-
this.duration =
|
|
1554
|
+
this.duration = spec.duration ?? (spec.loop ? rest : data.duration) ?? this.root.duration;
|
|
1485
1555
|
}
|
|
1486
|
-
if (!
|
|
1556
|
+
if (!spec.loop && data.duration !== void 0 && this.duration > data.duration + 0.05) {
|
|
1487
1557
|
console.warn(
|
|
1488
|
-
`pixi-effects: ${describeLayer(
|
|
1558
|
+
`pixi-effects: ${describeLayer(spec)}: audio asset "${spec.asset}" is ${data.duration.toFixed(1)}s but the layer lasts ${this.duration.toFixed(1)}s, so it goes silent after ${data.duration.toFixed(1)}s. Add loop: true, or shorten the layer's duration.`
|
|
1489
1559
|
);
|
|
1490
1560
|
}
|
|
1491
|
-
|
|
1561
|
+
}
|
|
1562
|
+
async _buildSfx(spec) {
|
|
1563
|
+
const who = describeLayer(spec);
|
|
1564
|
+
const raw = spec;
|
|
1565
|
+
if (raw.asset !== void 0) console.warn(`pixi-effects: ${who}: has both asset and sfx \u2014 the sfx plays; remove one`);
|
|
1566
|
+
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)`);
|
|
1567
|
+
const { resolveSfx, renderSfx, sfxKey } = await import('./sfx-S37DDC66.js');
|
|
1568
|
+
const sfx = resolveSfx(spec.sfx, spec.duration, who);
|
|
1569
|
+
if (!sfx) return;
|
|
1570
|
+
this.duration = sfx.length;
|
|
1571
|
+
this._source = `sfx "${sfx.preset ?? "custom"}"`;
|
|
1572
|
+
this._synth = { key: sfxKey(sfx), render: (sr) => renderSfx(sfx, sr) };
|
|
1573
|
+
(spec.keyframes ?? []).forEach((kf, i) => {
|
|
1574
|
+
if ((kf.at ?? 0) >= sfx.length) {
|
|
1575
|
+
console.warn(`pixi-effects: ${who}: keyframes[${i}] starts at ${kf.at}s, after the sound ends (${sfx.length}s), so it never plays`);
|
|
1576
|
+
} else if ((kf.at ?? 0) < 0 && sfx.length + (kf.at ?? 0) < 0) {
|
|
1577
|
+
console.warn(`pixi-effects: ${who}: keyframes[${i}] starts ${-kf.at}s before the END of a ${sfx.length}s sound, which is before the sound begins (a negative \`at\` counts back from the end of the layer). Use a shorter \`at\`, or stretch the sound with \`duration\`.`);
|
|
1578
|
+
}
|
|
1579
|
+
});
|
|
1492
1580
|
}
|
|
1493
1581
|
bindTimeline(_timeline) {
|
|
1494
1582
|
}
|
|
1495
1583
|
collectAudio(out, baseTime) {
|
|
1496
|
-
if (!this._audioBuffer) return;
|
|
1497
|
-
const initialVolume = this.spec.volume ?? 1;
|
|
1498
|
-
const volumeKeyframes = [];
|
|
1499
|
-
const dur = this.duration;
|
|
1584
|
+
if (!this._audioBuffer && !this._synth) return;
|
|
1585
|
+
const initialVolume = this.spec.volume ?? this.spec.initial?.volume ?? 1;
|
|
1500
1586
|
const t0 = baseTime + this.at;
|
|
1587
|
+
const dur = this.duration;
|
|
1588
|
+
out.push({
|
|
1589
|
+
...this._audioBuffer ? { buffer: this._audioBuffer } : { synth: this._synth },
|
|
1590
|
+
layer: describeLayer(this.spec),
|
|
1591
|
+
source: this._source,
|
|
1592
|
+
loop: !this._synth && !!this.spec.loop,
|
|
1593
|
+
start: t0,
|
|
1594
|
+
end: t0 + dur,
|
|
1595
|
+
initialVolume,
|
|
1596
|
+
volumeKeyframes: this._volumePoints(t0, dur, initialVolume)
|
|
1597
|
+
});
|
|
1598
|
+
}
|
|
1599
|
+
_volumePoints(t0, dur, initialVolume) {
|
|
1600
|
+
const volumeKeyframes = [];
|
|
1501
1601
|
const keyframes = (this.spec.keyframes ?? []).map((raw) => normalizeKeyframe(raw, dur)).filter((kf) => [kf.set, kf.to, kf.from].some((p) => p && "volume" in p)).sort((x, y) => x.at - y.at);
|
|
1502
1602
|
let current = initialVolume;
|
|
1503
1603
|
const point = (time, value) => {
|
|
@@ -1525,17 +1625,11 @@ var AudioSequence = class extends Sequence {
|
|
|
1525
1625
|
point(end, current);
|
|
1526
1626
|
}
|
|
1527
1627
|
}
|
|
1528
|
-
|
|
1529
|
-
buffer: this._audioBuffer,
|
|
1530
|
-
loop: !!this.spec.loop,
|
|
1531
|
-
start: baseTime + this.at,
|
|
1532
|
-
end: baseTime + this.at + dur,
|
|
1533
|
-
initialVolume,
|
|
1534
|
-
volumeKeyframes
|
|
1535
|
-
});
|
|
1628
|
+
return volumeKeyframes;
|
|
1536
1629
|
}
|
|
1537
1630
|
destroy() {
|
|
1538
1631
|
this._audioBuffer = null;
|
|
1632
|
+
this._synth = null;
|
|
1539
1633
|
}
|
|
1540
1634
|
};
|
|
1541
1635
|
|
|
@@ -1684,6 +1778,8 @@ var VideoSequence = class extends Sequence {
|
|
|
1684
1778
|
const initialVolume = this.spec.volume ?? 1;
|
|
1685
1779
|
out.push({
|
|
1686
1780
|
buffer: this._audioBuffer,
|
|
1781
|
+
layer: describeLayer(this.spec),
|
|
1782
|
+
source: `video "${this.spec.asset}"`,
|
|
1687
1783
|
loop: !!this.spec.loop,
|
|
1688
1784
|
start: baseTime + this.at,
|
|
1689
1785
|
end: baseTime + this.at + this.duration,
|
|
@@ -1764,19 +1860,107 @@ function makeGradientFill(g) {
|
|
|
1764
1860
|
}
|
|
1765
1861
|
return new FillGradient(gradientOptions(g));
|
|
1766
1862
|
}
|
|
1863
|
+
var CURVE_STEPS = 24;
|
|
1864
|
+
var ELLIPSE_STEPS = 128;
|
|
1865
|
+
function flattenSvgPath(d) {
|
|
1866
|
+
const prims = new GraphicsPath(d).shapePath.shapePrimitives;
|
|
1867
|
+
const out = [];
|
|
1868
|
+
for (const { shape } of prims) {
|
|
1869
|
+
const poly = shape;
|
|
1870
|
+
if (poly.points && poly.points.length >= 4) out.push({ pts: poly.points.slice(), closed: poly.closePath === true });
|
|
1871
|
+
}
|
|
1872
|
+
return out;
|
|
1873
|
+
}
|
|
1874
|
+
function rectOutline(x, y, w, h, radius) {
|
|
1875
|
+
const r = Math.max(0, Math.min(radius, Math.abs(w) / 2, Math.abs(h) / 2));
|
|
1876
|
+
if (r === 0) return { pts: [x, y, x + w, y, x + w, y + h, x, y + h], closed: true };
|
|
1877
|
+
const pts = [];
|
|
1878
|
+
const corner = (cx, cy, from) => {
|
|
1879
|
+
for (let i = 0; i <= CURVE_STEPS; i++) {
|
|
1880
|
+
const a = from + i / CURVE_STEPS * (Math.PI / 2);
|
|
1881
|
+
pts.push(cx + r * Math.cos(a), cy + r * Math.sin(a));
|
|
1882
|
+
}
|
|
1883
|
+
};
|
|
1884
|
+
corner(x + w - r, y + r, -Math.PI / 2);
|
|
1885
|
+
corner(x + w - r, y + h - r, 0);
|
|
1886
|
+
corner(x + r, y + h - r, Math.PI / 2);
|
|
1887
|
+
corner(x + r, y + r, Math.PI);
|
|
1888
|
+
const startAt = pts.length - 2;
|
|
1889
|
+
const rotated = pts.slice(startAt).concat(pts.slice(0, startAt));
|
|
1890
|
+
return { pts: rotated, closed: true };
|
|
1891
|
+
}
|
|
1892
|
+
function ellipseOutline(cx, cy, rx, ry) {
|
|
1893
|
+
const pts = [];
|
|
1894
|
+
for (let i = 0; i < ELLIPSE_STEPS; i++) {
|
|
1895
|
+
const a = -Math.PI / 2 + i / ELLIPSE_STEPS * Math.PI * 2;
|
|
1896
|
+
pts.push(cx + rx * Math.cos(a), cy + ry * Math.sin(a));
|
|
1897
|
+
}
|
|
1898
|
+
return { pts, closed: true };
|
|
1899
|
+
}
|
|
1900
|
+
function trimPolylines(lines, start, end) {
|
|
1901
|
+
const s = Math.max(0, Math.min(1, start)), e = Math.max(0, Math.min(1, end));
|
|
1902
|
+
if (!(e > s)) return [];
|
|
1903
|
+
const lengths = lines.map(polylineLength);
|
|
1904
|
+
const total = lengths.reduce((a, b) => a + b, 0);
|
|
1905
|
+
if (!(total > 0)) return [];
|
|
1906
|
+
const from = s * total, to = e * total;
|
|
1907
|
+
const out = [];
|
|
1908
|
+
let offset = 0;
|
|
1909
|
+
lines.forEach((line, i) => {
|
|
1910
|
+
const len = lengths[i];
|
|
1911
|
+
const a = Math.max(from - offset, 0), b = Math.min(to - offset, len);
|
|
1912
|
+
offset += len;
|
|
1913
|
+
if (!(b > a) || len === 0) return;
|
|
1914
|
+
if (line.closed && a <= 0 && b >= len) {
|
|
1915
|
+
out.push({ pts: line.pts.slice(), closed: true });
|
|
1916
|
+
return;
|
|
1917
|
+
}
|
|
1918
|
+
out.push({ pts: slice(line, a, b), closed: false });
|
|
1919
|
+
});
|
|
1920
|
+
return out;
|
|
1921
|
+
}
|
|
1922
|
+
function points(line) {
|
|
1923
|
+
return line.closed ? [...line.pts, line.pts[0], line.pts[1]] : line.pts;
|
|
1924
|
+
}
|
|
1925
|
+
function polylineLength(line) {
|
|
1926
|
+
const p = points(line);
|
|
1927
|
+
let len = 0;
|
|
1928
|
+
for (let i = 2; i < p.length; i += 2) len += Math.hypot(p[i] - p[i - 2], p[i + 1] - p[i - 1]);
|
|
1929
|
+
return len;
|
|
1930
|
+
}
|
|
1931
|
+
function slice(line, a, b) {
|
|
1932
|
+
const p = points(line);
|
|
1933
|
+
const out = [];
|
|
1934
|
+
let at = 0;
|
|
1935
|
+
for (let i = 2; i < p.length; i += 2) {
|
|
1936
|
+
const x0 = p[i - 2], y0 = p[i - 1], x1 = p[i], y1 = p[i + 1];
|
|
1937
|
+
const seg = Math.hypot(x1 - x0, y1 - y0);
|
|
1938
|
+
const segEnd = at + seg;
|
|
1939
|
+
if (segEnd > a && at < b && seg > 0) {
|
|
1940
|
+
const t0 = Math.max(a - at, 0) / seg, t1 = Math.min(b - at, seg) / seg;
|
|
1941
|
+
if (out.length === 0) out.push(x0 + (x1 - x0) * t0, y0 + (y1 - y0) * t0);
|
|
1942
|
+
out.push(x0 + (x1 - x0) * t1, y0 + (y1 - y0) * t1);
|
|
1943
|
+
}
|
|
1944
|
+
at = segEnd;
|
|
1945
|
+
if (at >= b) break;
|
|
1946
|
+
}
|
|
1947
|
+
return out;
|
|
1948
|
+
}
|
|
1767
1949
|
|
|
1768
1950
|
// src/sequences/Shape.ts
|
|
1769
1951
|
var STYLE_KEYS = ["fillColor", "fillAlpha", "strokeColor", "strokeAlpha", "strokeWidth"];
|
|
1770
1952
|
var COLOR_KEYS = /* @__PURE__ */ new Set(["fillColor", "strokeColor"]);
|
|
1953
|
+
var TRIM_KEYS = ["trimStart", "trimEnd"];
|
|
1771
1954
|
var GEOMETRY_KEYS_BY_SHAPE = {
|
|
1772
|
-
rect: ["width", "height", "cornerRadius", "anchorX", "anchorY"],
|
|
1773
|
-
circle: ["radius", "anchorX", "anchorY"],
|
|
1774
|
-
ellipse: ["radiusX", "radiusY", "anchorX", "anchorY"],
|
|
1775
|
-
|
|
1776
|
-
|
|
1777
|
-
|
|
1955
|
+
rect: ["width", "height", "cornerRadius", "anchorX", "anchorY", ...TRIM_KEYS],
|
|
1956
|
+
circle: ["radius", "anchorX", "anchorY", ...TRIM_KEYS],
|
|
1957
|
+
ellipse: ["radiusX", "radiusY", "anchorX", "anchorY", ...TRIM_KEYS],
|
|
1958
|
+
arc: ["radius", "innerRadius", "startAngle", "endAngle"],
|
|
1959
|
+
line: [...TRIM_KEYS],
|
|
1960
|
+
polygon: [...TRIM_KEYS],
|
|
1961
|
+
path: [...TRIM_KEYS]
|
|
1778
1962
|
};
|
|
1779
|
-
var ANCHORED_SHAPES = /* @__PURE__ */ new Set(["rect", "circle", "ellipse"]);
|
|
1963
|
+
var ANCHORED_SHAPES = /* @__PURE__ */ new Set(["rect", "circle", "ellipse", "arc"]);
|
|
1780
1964
|
var ShapeSequence = class extends Sequence {
|
|
1781
1965
|
_state = {
|
|
1782
1966
|
fillColor: void 0,
|
|
@@ -1803,12 +1987,30 @@ var ShapeSequence = class extends Sequence {
|
|
|
1803
1987
|
for (const k of geomKeys) this._liveKeys.add(k);
|
|
1804
1988
|
seedGeometry(this._state, this.spec, scope);
|
|
1805
1989
|
seedStyle(this._state, this.spec.initial ?? {}, scope);
|
|
1990
|
+
seedStrokeStyle(this._state, this.spec, this.spec.initial ?? {}, describeLayer(this.spec));
|
|
1991
|
+
if (this.spec.shape === "arc") {
|
|
1992
|
+
this._state.startAngle ??= 0;
|
|
1993
|
+
this._state.endAngle ??= 360;
|
|
1994
|
+
const top = this.spec, ini = this.spec.initial ?? {};
|
|
1995
|
+
if ("trimStart" in top || "trimEnd" in top || "trimStart" in ini || "trimEnd" in ini) {
|
|
1996
|
+
console.warn(`pixi-effects: ${describeLayer(this.spec)}: trimStart / trimEnd do not apply to an arc: animate its endAngle (and startAngle) instead`);
|
|
1997
|
+
}
|
|
1998
|
+
} else {
|
|
1999
|
+
this._state.trimStart ??= 0;
|
|
2000
|
+
this._state.trimEnd ??= 1;
|
|
2001
|
+
}
|
|
1806
2002
|
const gradientSpec = this.spec.fillGradient ?? this.spec.initial?.fillGradient;
|
|
1807
2003
|
if (gradientSpec) this._state.fillStyle = makeGradientFill(gradientSpec);
|
|
1808
2004
|
this._drawGeometry = makeDrawGeometry(this.spec, scope, this._state);
|
|
2005
|
+
this._outline = makeOutline(this.spec, scope, this._state);
|
|
2006
|
+
const { trimStart, trimEnd } = this._state;
|
|
2007
|
+
this._state.trimStart = 0;
|
|
2008
|
+
this._state.trimEnd = 1;
|
|
1809
2009
|
this._drawGeometry(graphics);
|
|
1810
2010
|
applyState(graphics, this._state);
|
|
1811
2011
|
const bounds = graphics.getLocalBounds();
|
|
2012
|
+
this._state.trimStart = trimStart;
|
|
2013
|
+
this._state.trimEnd = trimEnd;
|
|
1812
2014
|
this.intrinsicWidth = bounds.width;
|
|
1813
2015
|
this.intrinsicHeight = bounds.height;
|
|
1814
2016
|
if (!ANCHORED_SHAPES.has(this.spec.shape)) {
|
|
@@ -1826,14 +2028,37 @@ var ShapeSequence = class extends Sequence {
|
|
|
1826
2028
|
}
|
|
1827
2029
|
this._redraw();
|
|
1828
2030
|
};
|
|
2031
|
+
this._redraw();
|
|
1829
2032
|
this.buildFilters();
|
|
1830
2033
|
}
|
|
1831
2034
|
_fresh = false;
|
|
2035
|
+
_outline = null;
|
|
1832
2036
|
_redraw() {
|
|
1833
2037
|
const graphics = this.target;
|
|
2038
|
+
const s = this._state;
|
|
1834
2039
|
graphics.clear();
|
|
1835
|
-
|
|
1836
|
-
|
|
2040
|
+
const trimmed = (s.trimStart ?? 0) > 0 || (s.trimEnd ?? 1) < 1;
|
|
2041
|
+
if (!trimmed || !this._outline || !(s.strokeColor !== void 0 && s.strokeWidth > 0)) {
|
|
2042
|
+
this._drawGeometry(graphics);
|
|
2043
|
+
applyState(graphics, s);
|
|
2044
|
+
return;
|
|
2045
|
+
}
|
|
2046
|
+
if (s.fillStyle || s.fillColor !== void 0) {
|
|
2047
|
+
this._drawGeometry(graphics);
|
|
2048
|
+
applyFill(graphics, s);
|
|
2049
|
+
graphics.beginPath();
|
|
2050
|
+
}
|
|
2051
|
+
const parts = trimPolylines(this._outline(), s.trimStart ?? 0, s.trimEnd ?? 1);
|
|
2052
|
+
if (parts.length === 0) return;
|
|
2053
|
+
for (const part of parts) {
|
|
2054
|
+
if (part.closed) {
|
|
2055
|
+
graphics.poly(part.pts, true);
|
|
2056
|
+
continue;
|
|
2057
|
+
}
|
|
2058
|
+
graphics.moveTo(part.pts[0], part.pts[1]);
|
|
2059
|
+
for (let i = 2; i < part.pts.length; i += 2) graphics.lineTo(part.pts[i], part.pts[i + 1]);
|
|
2060
|
+
}
|
|
2061
|
+
applyStroke(graphics, s);
|
|
1837
2062
|
}
|
|
1838
2063
|
/**
|
|
1839
2064
|
* Draw from the tweened `_state` before the culler runs. The culler measures the geometry as last
|
|
@@ -1871,6 +2096,21 @@ function seedGeometry(state, spec, scope) {
|
|
|
1871
2096
|
if (v !== void 0) state[k] = num(v, scope);
|
|
1872
2097
|
}
|
|
1873
2098
|
}
|
|
2099
|
+
var STROKE_CAPS = ["butt", "round", "square"];
|
|
2100
|
+
var STROKE_JOINS = ["miter", "round", "bevel"];
|
|
2101
|
+
function seedStrokeStyle(state, spec, initial, who) {
|
|
2102
|
+
const top = spec;
|
|
2103
|
+
const ini = initial;
|
|
2104
|
+
const pick = (key, valid) => {
|
|
2105
|
+
const v = top[key] ?? ini[key];
|
|
2106
|
+
if (v === void 0) return void 0;
|
|
2107
|
+
if (valid.includes(String(v))) return String(v);
|
|
2108
|
+
console.warn(`pixi-effects: ${who}: ${key} "${v}" is not one of ${valid.join(", ")}; ignored`);
|
|
2109
|
+
return void 0;
|
|
2110
|
+
};
|
|
2111
|
+
state.strokeCap = pick("strokeCap", STROKE_CAPS);
|
|
2112
|
+
state.strokeJoin = pick("strokeJoin", STROKE_JOINS);
|
|
2113
|
+
}
|
|
1874
2114
|
function seedStyle(state, initial, scope) {
|
|
1875
2115
|
for (const k of STYLE_KEYS) {
|
|
1876
2116
|
const v = initial[k];
|
|
@@ -1879,8 +2119,8 @@ function seedStyle(state, initial, scope) {
|
|
|
1879
2119
|
}
|
|
1880
2120
|
}
|
|
1881
2121
|
function stripGradient(props) {
|
|
1882
|
-
if (!props || !("fillGradient" in props)) return props;
|
|
1883
|
-
const { fillGradient: _drop, ...rest } = props;
|
|
2122
|
+
if (!props || !("fillGradient" in props || "strokeCap" in props || "strokeJoin" in props)) return props;
|
|
2123
|
+
const { fillGradient: _drop, strokeCap: _cap, strokeJoin: _join, ...rest } = props;
|
|
1884
2124
|
return rest;
|
|
1885
2125
|
}
|
|
1886
2126
|
function stripLive(props, liveKeys) {
|
|
@@ -1921,13 +2161,25 @@ function resolveLiveValue(key, value, scope) {
|
|
|
1921
2161
|
return numOrZero(value, scope);
|
|
1922
2162
|
}
|
|
1923
2163
|
function applyState(g, s) {
|
|
2164
|
+
applyFill(g, s);
|
|
2165
|
+
applyStroke(g, s);
|
|
2166
|
+
}
|
|
2167
|
+
function applyFill(g, s) {
|
|
1924
2168
|
if (s.fillStyle) {
|
|
1925
2169
|
g.fill(s.fillStyle);
|
|
1926
2170
|
} else if (s.fillColor !== void 0) {
|
|
1927
2171
|
g.fill({ color: s.fillColor, alpha: s.fillAlpha });
|
|
1928
2172
|
}
|
|
2173
|
+
}
|
|
2174
|
+
function applyStroke(g, s) {
|
|
1929
2175
|
if (s.strokeColor !== void 0 && s.strokeWidth > 0) {
|
|
1930
|
-
g.stroke({
|
|
2176
|
+
g.stroke({
|
|
2177
|
+
color: s.strokeColor,
|
|
2178
|
+
alpha: s.strokeAlpha,
|
|
2179
|
+
width: s.strokeWidth,
|
|
2180
|
+
...s.strokeCap ? { cap: s.strokeCap } : {},
|
|
2181
|
+
...s.strokeJoin ? { join: s.strokeJoin } : {}
|
|
2182
|
+
});
|
|
1931
2183
|
}
|
|
1932
2184
|
}
|
|
1933
2185
|
function drawRectFromState(g, s) {
|
|
@@ -1954,6 +2206,34 @@ function drawEllipseFromState(g, s) {
|
|
|
1954
2206
|
const ay = s.anchorY ?? 0.5;
|
|
1955
2207
|
g.ellipse((0.5 - ax) * 2 * rx, (0.5 - ay) * 2 * ry, rx, ry);
|
|
1956
2208
|
}
|
|
2209
|
+
var DEG2 = Math.PI / 180;
|
|
2210
|
+
function drawArcFromState(g, s) {
|
|
2211
|
+
const r = s.radius ?? 0;
|
|
2212
|
+
const ri = Math.max(0, Math.min(s.innerRadius ?? 0, r));
|
|
2213
|
+
const startDeg = s.startAngle ?? 0;
|
|
2214
|
+
let endDeg = s.endAngle ?? 360;
|
|
2215
|
+
if (!(r > 0) || endDeg === startDeg) return;
|
|
2216
|
+
const filled = !!s.fillStyle || s.fillColor !== void 0;
|
|
2217
|
+
if (Math.abs(endDeg - startDeg) >= 360) {
|
|
2218
|
+
if (!filled) {
|
|
2219
|
+
g.circle(0, 0, r);
|
|
2220
|
+
return;
|
|
2221
|
+
}
|
|
2222
|
+
endDeg = startDeg + Math.sign(endDeg - startDeg) * 359.999;
|
|
2223
|
+
}
|
|
2224
|
+
const a0 = startDeg * DEG2, a1 = endDeg * DEG2;
|
|
2225
|
+
const ccw = a1 < a0;
|
|
2226
|
+
if (filled) g.moveTo(r * Math.cos(a0), r * Math.sin(a0));
|
|
2227
|
+
g.arc(0, 0, r, a0, a1, ccw);
|
|
2228
|
+
if (!filled) return;
|
|
2229
|
+
if (ri > 0) {
|
|
2230
|
+
g.lineTo(ri * Math.cos(a1), ri * Math.sin(a1));
|
|
2231
|
+
g.arc(0, 0, ri, a1, a0, !ccw);
|
|
2232
|
+
} else {
|
|
2233
|
+
g.lineTo(0, 0);
|
|
2234
|
+
}
|
|
2235
|
+
g.closePath();
|
|
2236
|
+
}
|
|
1957
2237
|
function makeLineDraw(spec, scope) {
|
|
1958
2238
|
const fx = num(spec.from[0], scope);
|
|
1959
2239
|
const fy = num(spec.from[1], scope);
|
|
@@ -1982,7 +2262,8 @@ function makePathDraw(spec) {
|
|
|
1982
2262
|
var STATE_DRAWERS = {
|
|
1983
2263
|
rect: drawRectFromState,
|
|
1984
2264
|
circle: drawCircleFromState,
|
|
1985
|
-
ellipse: drawEllipseFromState
|
|
2265
|
+
ellipse: drawEllipseFromState,
|
|
2266
|
+
arc: drawArcFromState
|
|
1986
2267
|
};
|
|
1987
2268
|
function makeDrawGeometry(spec, scope, state) {
|
|
1988
2269
|
const stateDrawer = STATE_DRAWERS[spec.shape];
|
|
@@ -1998,6 +2279,41 @@ function makeDrawGeometry(spec, scope, state) {
|
|
|
1998
2279
|
return () => {
|
|
1999
2280
|
};
|
|
2000
2281
|
}
|
|
2282
|
+
function makeOutline(spec, scope, s) {
|
|
2283
|
+
switch (spec.shape) {
|
|
2284
|
+
case "rect":
|
|
2285
|
+
return () => {
|
|
2286
|
+
const w = s.width ?? 0, h = s.height ?? 0;
|
|
2287
|
+
return [rectOutline(0 - (s.anchorX ?? 0.5) * w, 0 - (s.anchorY ?? 0.5) * h, w, h, s.cornerRadius ?? 0)];
|
|
2288
|
+
};
|
|
2289
|
+
case "circle":
|
|
2290
|
+
return () => {
|
|
2291
|
+
const r = s.radius ?? 0;
|
|
2292
|
+
return [ellipseOutline((0.5 - (s.anchorX ?? 0.5)) * 2 * r, (0.5 - (s.anchorY ?? 0.5)) * 2 * r, r, r)];
|
|
2293
|
+
};
|
|
2294
|
+
case "ellipse":
|
|
2295
|
+
return () => {
|
|
2296
|
+
const rx = s.radiusX ?? 0, ry = s.radiusY ?? 0;
|
|
2297
|
+
return [ellipseOutline((0.5 - (s.anchorX ?? 0.5)) * 2 * rx, (0.5 - (s.anchorY ?? 0.5)) * 2 * ry, rx, ry)];
|
|
2298
|
+
};
|
|
2299
|
+
case "line": {
|
|
2300
|
+
const lines = [{ pts: [num(spec.from[0], scope), num(spec.from[1], scope), num(spec.to[0], scope), num(spec.to[1], scope)], closed: false }];
|
|
2301
|
+
return () => lines;
|
|
2302
|
+
}
|
|
2303
|
+
case "polygon": {
|
|
2304
|
+
const pts = [];
|
|
2305
|
+
for (const [x, y] of spec.points) pts.push(num(x, scope), num(y, scope));
|
|
2306
|
+
const lines = pts.length >= 4 ? [{ pts, closed: !spec.open }] : [];
|
|
2307
|
+
return () => lines;
|
|
2308
|
+
}
|
|
2309
|
+
case "path": {
|
|
2310
|
+
let lines = null;
|
|
2311
|
+
return () => lines ??= flattenSvgPath(spec.d);
|
|
2312
|
+
}
|
|
2313
|
+
default:
|
|
2314
|
+
return null;
|
|
2315
|
+
}
|
|
2316
|
+
}
|
|
2001
2317
|
function bindLiveKeyframes(timeline, state, liveKeys, keyframes, parentDuration, scope, offset, colorSpace) {
|
|
2002
2318
|
for (const kf of keyframes) {
|
|
2003
2319
|
const at = offset + resolveAt(kf.at, parentDuration);
|
|
@@ -2071,7 +2387,7 @@ function numOrZero(v, scope) {
|
|
|
2071
2387
|
var _CompositionSequence = null;
|
|
2072
2388
|
async function getCompositionSequence() {
|
|
2073
2389
|
if (!_CompositionSequence) {
|
|
2074
|
-
_CompositionSequence = (await import('./Composition-
|
|
2390
|
+
_CompositionSequence = (await import('./Composition-7SO5WYHU.js')).CompositionSequence;
|
|
2075
2391
|
}
|
|
2076
2392
|
return _CompositionSequence;
|
|
2077
2393
|
}
|
|
@@ -2108,6 +2424,6 @@ async function buildSequenceTree(specs, parent, root) {
|
|
|
2108
2424
|
return out;
|
|
2109
2425
|
}
|
|
2110
2426
|
|
|
2111
|
-
export { CameraSequence, DEFAULT_FOV, DEG, Sequence, buildScope, buildSequenceTree, cameraBasis, collectPropKeys, describeLayer, evaluateExpr, homeCamera, homeDistance, lintText, lintTiming, projectLayer, registerSequenceType, resolveAt, summarizeWarnings };
|
|
2112
|
-
//# sourceMappingURL=chunk-
|
|
2113
|
-
//# sourceMappingURL=chunk-
|
|
2427
|
+
export { CameraSequence, DEFAULT_FOV, DEG, NEAR, Sequence, buildScope, buildSequenceTree, cameraBasis, collectPropKeys, describeLayer, evaluateExpr, homeCamera, homeDistance, lintText, lintTiming, projectLayer, registerSequenceType, resolveAt, summarizeWarnings };
|
|
2428
|
+
//# sourceMappingURL=chunk-7IJHJXDI.js.map
|
|
2429
|
+
//# sourceMappingURL=chunk-7IJHJXDI.js.map
|