pixi-effects 0.41.0 → 0.43.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 +16 -0
- package/README.md +5 -5
- package/ai/chat-template.html +3 -3
- package/dist/{Base-Jgkud1Aw.d.ts → Base-DKFQtqzW.d.ts} +1 -1
- package/dist/{Base-DQWIJ6bJ.d.cts → Base-lb5Uhaqu.d.cts} +1 -1
- package/dist/Controller.d.cts +2 -2
- package/dist/Controller.d.ts +2 -2
- package/dist/{Movie-CwqRLOzE.d.ts → Movie-B_qQIYV6.d.ts} +47 -4
- package/dist/{Movie-DWtxRiJ2.d.cts → Movie-BdUm2Mc9.d.cts} +47 -4
- package/dist/{chunk-Y2N6U3X5.js → chunk-6N5ZBUOU.js} +169 -8
- package/dist/chunk-6N5ZBUOU.js.map +1 -0
- package/dist/{chunk-RN5FWGGM.cjs → chunk-BEGOKE7Q.cjs} +169 -8
- package/dist/chunk-BEGOKE7Q.cjs.map +1 -0
- package/dist/index.cjs +25 -25
- package/dist/index.d.cts +4 -4
- package/dist/index.d.ts +4 -4
- package/dist/index.js +1 -1
- package/dist/loader.css +1 -1
- package/dist/present.cjs +1 -1
- package/dist/present.d.cts +2 -2
- package/dist/present.d.ts +2 -2
- package/dist/present.js +1 -1
- package/dist/three.cjs +115 -24
- package/dist/three.cjs.map +1 -1
- package/dist/three.d.cts +28 -2
- package/dist/three.d.ts +28 -2
- package/dist/three.js +117 -26
- package/dist/three.js.map +1 -1
- package/dist/{types-DIh93lFb.d.cts → types-DiNHtdrS.d.cts} +19 -0
- package/dist/{types-DIh93lFb.d.ts → types-DiNHtdrS.d.ts} +19 -0
- package/docs/api.md +23 -3
- package/docs/dsl.md +3 -2
- package/llms-full.txt +147 -17
- package/package.json +2 -1
- package/skills/pixi-effects/SKILL.md +2 -1
- package/skills/pixi-effects/reference/cheatsheet.md +2 -0
- package/skills/pixi-effects/reference/recipes.md +117 -11
- package/skills/pixi-effects/template.html +6 -6
- package/dist/chunk-RN5FWGGM.cjs.map +0 -1
- package/dist/chunk-Y2N6U3X5.js.map +0 -1
|
@@ -9,6 +9,21 @@ var chunkTWZNOUM7_cjs = require('./chunk-TWZNOUM7.cjs');
|
|
|
9
9
|
var pixi_js = require('pixi.js');
|
|
10
10
|
var mediabunny = require('mediabunny');
|
|
11
11
|
|
|
12
|
+
// src/core/gpuShare.ts
|
|
13
|
+
function sharedGpuOf(renderer) {
|
|
14
|
+
const r = renderer;
|
|
15
|
+
if (!r || r.name !== "webgpu" || !r.gpu?.device) return void 0;
|
|
16
|
+
const uid = r.uid;
|
|
17
|
+
return {
|
|
18
|
+
device: r.gpu.device,
|
|
19
|
+
adopt(source, texture) {
|
|
20
|
+
const data = source._gpuData;
|
|
21
|
+
if (!data || typeof data !== "object") throw new Error("this PixiJS keeps no _gpuData on its texture sources");
|
|
22
|
+
data[uid] = { textureView: null, textureViews: /* @__PURE__ */ Object.create(null), gpuTexture: texture, destroy() {
|
|
23
|
+
} };
|
|
24
|
+
}
|
|
25
|
+
};
|
|
26
|
+
}
|
|
12
27
|
var registered = false;
|
|
13
28
|
function ensureLoadersRegistered(audioContext) {
|
|
14
29
|
if (registered) return;
|
|
@@ -1636,6 +1651,7 @@ function inspectScene(root, frame, time, canvas, opts = {}) {
|
|
|
1636
1651
|
if (typeof drawn.renderer === "string") {
|
|
1637
1652
|
info.renderer = drawn.renderer;
|
|
1638
1653
|
if (typeof drawn.backend === "string") info.backend = drawn.backend;
|
|
1654
|
+
if (info.renderer === "webgpu") info.sharedGpu = drawn.sharedGpu === true;
|
|
1639
1655
|
}
|
|
1640
1656
|
layers.push(info);
|
|
1641
1657
|
chainAlpha.set(info, parentAlpha * alpha);
|
|
@@ -1732,6 +1748,23 @@ function inspectScene(root, frame, time, canvas, opts = {}) {
|
|
|
1732
1748
|
}
|
|
1733
1749
|
|
|
1734
1750
|
// src/core/pick.ts
|
|
1751
|
+
var scratch;
|
|
1752
|
+
var saidBlind = /* @__PURE__ */ new Set();
|
|
1753
|
+
var readResourceAlpha = (resource, x, y) => {
|
|
1754
|
+
try {
|
|
1755
|
+
if (scratch === void 0) {
|
|
1756
|
+
const c = document.createElement("canvas");
|
|
1757
|
+
c.width = c.height = 1;
|
|
1758
|
+
scratch = c.getContext("2d", { willReadFrequently: true });
|
|
1759
|
+
}
|
|
1760
|
+
if (!scratch) return null;
|
|
1761
|
+
scratch.clearRect(0, 0, 1, 1);
|
|
1762
|
+
scratch.drawImage(resource, x, y, 1, 1, 0, 0, 1, 1);
|
|
1763
|
+
return scratch.getImageData(0, 0, 1, 1).data[3] / 255;
|
|
1764
|
+
} catch {
|
|
1765
|
+
return null;
|
|
1766
|
+
}
|
|
1767
|
+
};
|
|
1735
1768
|
function pointInQuad(q, x, y) {
|
|
1736
1769
|
let pos = 0, neg = 0;
|
|
1737
1770
|
for (let i = 0; i < 4; i++) {
|
|
@@ -1756,11 +1789,14 @@ var above = (a, b) => {
|
|
|
1756
1789
|
}
|
|
1757
1790
|
return b.length - a.length;
|
|
1758
1791
|
};
|
|
1759
|
-
function pickScene(root, x, y, opts = {}) {
|
|
1792
|
+
function pickScene(root, x, y, opts = {}, deps = {}) {
|
|
1793
|
+
if (opts.alpha !== void 0 && !(opts.alpha >= 0 && opts.alpha <= 1)) throw new Error(`pixi-effects: pick: alpha must be a number from 0 to 1 (a pixel at or below it is not a hit), got ${opts.alpha}`);
|
|
1794
|
+
const readAlpha = deps.readAlpha ?? readResourceAlpha;
|
|
1760
1795
|
const found = [];
|
|
1796
|
+
const names = (list, name, path) => list.some((e) => e === path || name !== void 0 && e === name || path.startsWith(e + "/") || path.split("/").slice(0, -1).includes(e));
|
|
1761
1797
|
const wanted = (name, path) => {
|
|
1762
|
-
if (opts.ignore && (opts.ignore
|
|
1763
|
-
if (opts.only && !(opts.only
|
|
1798
|
+
if (opts.ignore && names(opts.ignore, name, path)) return false;
|
|
1799
|
+
if (opts.only && !names(opts.only, name, path)) return false;
|
|
1764
1800
|
return true;
|
|
1765
1801
|
};
|
|
1766
1802
|
const inside = (b, p) => p.x >= b.x && p.x <= b.x + b.width && p.y >= b.y && p.y <= b.y + b.height;
|
|
@@ -1790,8 +1826,34 @@ function pickScene(root, x, y, opts = {}) {
|
|
|
1790
1826
|
const lb = d.getLocalBounds();
|
|
1791
1827
|
if (inside(lb, local)) {
|
|
1792
1828
|
const three = typeof seq.pickAt === "function" ? seq.pickAt((local.x - lb.x) / lb.width, (local.y - lb.y) / lb.height) : void 0;
|
|
1793
|
-
if (three)
|
|
1794
|
-
|
|
1829
|
+
if (three) {
|
|
1830
|
+
const planeOf = seq.dragPlane;
|
|
1831
|
+
if (planeOf) {
|
|
1832
|
+
three.grab = (plane = "screen") => {
|
|
1833
|
+
const along = planeOf.call(seq, three.point, plane);
|
|
1834
|
+
return { move: (cx, cy) => {
|
|
1835
|
+
const lp = d.toLocal({ x: cx, y: cy });
|
|
1836
|
+
const b = d.getLocalBounds();
|
|
1837
|
+
return along((lp.x - b.x) / b.width, (lp.y - b.y) / b.height);
|
|
1838
|
+
} };
|
|
1839
|
+
};
|
|
1840
|
+
}
|
|
1841
|
+
hit = { name, path, type: seq.spec.type, kind: "three", point, three };
|
|
1842
|
+
} else if (three === void 0 && (typeof d.containsPoint !== "function" || d.containsPoint(local))) {
|
|
1843
|
+
let opaque = true;
|
|
1844
|
+
const tex = opts.alpha !== void 0 && seq.spec.type !== "shader" ? d.texture : void 0;
|
|
1845
|
+
if (tex?.source?.resource) {
|
|
1846
|
+
const res = tex.source.resolution ?? 1;
|
|
1847
|
+
const a = readAlpha(tex.source.resource, (tex.frame.x + (local.x - lb.x) / lb.width * tex.frame.width) * res, (tex.frame.y + (local.y - lb.y) / lb.height * tex.frame.height) * res);
|
|
1848
|
+
if (a === null) {
|
|
1849
|
+
if (!saidBlind.has(path)) {
|
|
1850
|
+
saidBlind.add(path);
|
|
1851
|
+
console.warn(`pixi-effects: pick: the picture of layer "${path}" cannot be read for { alpha } (a picture from another origin: load it with crossorigin="anonymous" or from the same site), so the box counts as the picture`);
|
|
1852
|
+
}
|
|
1853
|
+
} else opaque = a > opts.alpha;
|
|
1854
|
+
}
|
|
1855
|
+
if (opaque) hit = { name, path, type: seq.spec.type, kind: "flat", point, local: { x: local.x - lb.x, y: local.y - lb.y } };
|
|
1856
|
+
}
|
|
1795
1857
|
}
|
|
1796
1858
|
}
|
|
1797
1859
|
if (!hit) return;
|
|
@@ -1805,6 +1867,82 @@ function pickScene(root, x, y, opts = {}) {
|
|
|
1805
1867
|
return found.sort((a, b) => above(a.order, b.order)).map((f) => f.hit);
|
|
1806
1868
|
}
|
|
1807
1869
|
|
|
1870
|
+
// src/core/hover.ts
|
|
1871
|
+
var keyOf = (h) => h ? `${h.path}${h.three ? `#${h.three.object}` : ""}` : null;
|
|
1872
|
+
function startHover(host, opts = {}) {
|
|
1873
|
+
const { canvas } = host;
|
|
1874
|
+
const request = host.requestFrame ?? ((fn) => requestAnimationFrame(fn));
|
|
1875
|
+
const cancel = host.cancelFrame ?? ((id) => cancelAnimationFrame(id));
|
|
1876
|
+
const cursor = opts.cursor === true ? "pointer" : opts.cursor || "";
|
|
1877
|
+
const pickOpts = {};
|
|
1878
|
+
if (opts.only) pickOpts.only = opts.only;
|
|
1879
|
+
if (opts.ignore) pickOpts.ignore = opts.ignore;
|
|
1880
|
+
let current = null;
|
|
1881
|
+
let last = null;
|
|
1882
|
+
let loop = null;
|
|
1883
|
+
let said = false;
|
|
1884
|
+
const call = (fn, hit) => {
|
|
1885
|
+
if (!fn) return;
|
|
1886
|
+
try {
|
|
1887
|
+
fn(hit);
|
|
1888
|
+
} catch (err) {
|
|
1889
|
+
if (!said) {
|
|
1890
|
+
said = true;
|
|
1891
|
+
console.warn("pixi-effects: movie.hover: a handler threw (said once) \u2014", err);
|
|
1892
|
+
}
|
|
1893
|
+
}
|
|
1894
|
+
};
|
|
1895
|
+
const setCursor = (on) => {
|
|
1896
|
+
if (cursor) canvas.style.cursor = on ? cursor : "";
|
|
1897
|
+
};
|
|
1898
|
+
const evaluate = () => {
|
|
1899
|
+
if (!last) return;
|
|
1900
|
+
const [x, y] = host.point(last);
|
|
1901
|
+
const hit = host.pick(x, y, pickOpts);
|
|
1902
|
+
if (keyOf(hit) === keyOf(current)) {
|
|
1903
|
+
current = hit ?? current;
|
|
1904
|
+
return;
|
|
1905
|
+
}
|
|
1906
|
+
const was = current;
|
|
1907
|
+
current = hit;
|
|
1908
|
+
if (was) call(opts.onLeave, was);
|
|
1909
|
+
if (hit) call(opts.onEnter, hit);
|
|
1910
|
+
setCursor(!!hit);
|
|
1911
|
+
};
|
|
1912
|
+
const tick = () => {
|
|
1913
|
+
loop = null;
|
|
1914
|
+
if (last) {
|
|
1915
|
+
evaluate();
|
|
1916
|
+
loop = request(tick);
|
|
1917
|
+
}
|
|
1918
|
+
};
|
|
1919
|
+
const onMove = (event) => {
|
|
1920
|
+
last = event;
|
|
1921
|
+
evaluate();
|
|
1922
|
+
if (loop === null) loop = request(tick);
|
|
1923
|
+
};
|
|
1924
|
+
const onLeave = () => {
|
|
1925
|
+
last = null;
|
|
1926
|
+
if (loop !== null) {
|
|
1927
|
+
cancel(loop);
|
|
1928
|
+
loop = null;
|
|
1929
|
+
}
|
|
1930
|
+
const was = current;
|
|
1931
|
+
current = null;
|
|
1932
|
+
if (was) call(opts.onLeave, was);
|
|
1933
|
+
setCursor(false);
|
|
1934
|
+
};
|
|
1935
|
+
canvas.addEventListener("pointermove", onMove);
|
|
1936
|
+
canvas.addEventListener("pointerdown", onMove);
|
|
1937
|
+
canvas.addEventListener("pointerleave", onLeave);
|
|
1938
|
+
return () => {
|
|
1939
|
+
canvas.removeEventListener("pointermove", onMove);
|
|
1940
|
+
canvas.removeEventListener("pointerdown", onMove);
|
|
1941
|
+
canvas.removeEventListener("pointerleave", onLeave);
|
|
1942
|
+
onLeave();
|
|
1943
|
+
};
|
|
1944
|
+
}
|
|
1945
|
+
|
|
1808
1946
|
// src/core/timelineChart.ts
|
|
1809
1947
|
var GROUP_MIN = 4;
|
|
1810
1948
|
var MAX_KEYS = 200;
|
|
@@ -2607,12 +2745,15 @@ var Movie = class {
|
|
|
2607
2745
|
*/
|
|
2608
2746
|
async _construct(composition, vars, width, height, lp, sizeWins = this._resized) {
|
|
2609
2747
|
const spec = applyVars(composition, vars);
|
|
2748
|
+
const gpu = sharedGpuOf(this.app?.renderer);
|
|
2749
|
+
const gpuField = gpu ? { gpu } : {};
|
|
2610
2750
|
const rootShape = {
|
|
2611
2751
|
width,
|
|
2612
2752
|
height,
|
|
2613
2753
|
duration: this.duration,
|
|
2614
2754
|
frameRate: this.frameRate,
|
|
2615
2755
|
vars: numericVars(vars),
|
|
2756
|
+
...gpuField,
|
|
2616
2757
|
...lp ? { onLayerBuilt: async () => {
|
|
2617
2758
|
lp.tick();
|
|
2618
2759
|
await lp.yieldIfDue();
|
|
@@ -2859,6 +3000,14 @@ var Movie = class {
|
|
|
2859
3000
|
await this._goto(frame);
|
|
2860
3001
|
this.emit("seeked", { frame: this.currentFrame, totalFrames: this.totalFrames });
|
|
2861
3002
|
}
|
|
3003
|
+
/**
|
|
3004
|
+
* Draw the frame on screen again, quietly (no `seeking` / `seeked`). For a paused movie when something outside it that a layer reads has changed: a `three` layer whose `update` reads the page's own
|
|
3005
|
+
* state (a dragged object's place) shows it after `await movie.redraw()`. A playing movie needs no call: the next frame draws it.
|
|
3006
|
+
*/
|
|
3007
|
+
async redraw() {
|
|
3008
|
+
this._requireReady("redraw");
|
|
3009
|
+
await this._quietly(() => this.gotoFrame(this.currentFrame, true));
|
|
3010
|
+
}
|
|
2862
3011
|
/** Run `fn` with `seeking` / `seeked` silenced: the movie is moving its own playhead, not answering a seek. */
|
|
2863
3012
|
async _quietly(fn) {
|
|
2864
3013
|
this._quiet++;
|
|
@@ -3072,11 +3221,23 @@ var Movie = class {
|
|
|
3072
3221
|
}
|
|
3073
3222
|
/** Every layer under the canvas point, the one on top first (see `pick`). */
|
|
3074
3223
|
pickAll(x, y, opts = {}) {
|
|
3075
|
-
chunkTWZNOUM7_cjs.warnUnknownOptions("movie.pick()", opts, ["only", "ignore"]);
|
|
3224
|
+
chunkTWZNOUM7_cjs.warnUnknownOptions("movie.pick()", opts, ["only", "ignore", "alpha"]);
|
|
3076
3225
|
this._requireReady("pick");
|
|
3077
3226
|
if (!Number.isFinite(x) || !Number.isFinite(y)) throw new Error(`pixi-effects: movie.pick(x, y) needs two numbers (canvas pixels), got ${x}, ${y}. For a pointer event: movie.pick(...movie.canvasPoint(event))`);
|
|
3078
3227
|
return pickScene(this._rootSequence, x, y, opts);
|
|
3079
3228
|
}
|
|
3229
|
+
/**
|
|
3230
|
+
* Which layer the pointer is over, as callbacks: `onEnter(hit)` when the layer (or, in a `three` layer, the object) under the pointer changes to another, `onLeave(hit)` for the one it
|
|
3231
|
+
* left (also when the pointer leaves the picture). While the pointer rests inside, it is asked again on every frame, so a picture that moves under a still pointer is followed.
|
|
3232
|
+
* `{ only, ignore }` as for `pick`; `cursor: true` (or a CSS cursor) shows it while something is hovered. Returns the function that stops it. A page-side tool: an exported video has no pointer.
|
|
3233
|
+
*/
|
|
3234
|
+
hover(opts = {}) {
|
|
3235
|
+
chunkTWZNOUM7_cjs.warnUnknownOptions("movie.hover()", opts, ["onEnter", "onLeave", "cursor", "only", "ignore"]);
|
|
3236
|
+
this._requireReady("hover");
|
|
3237
|
+
const canvas = this.app?.canvas;
|
|
3238
|
+
if (!canvas) throw new Error("pixi-effects: movie.hover needs the movie's canvas");
|
|
3239
|
+
return startHover({ canvas, pick: (x, y, o) => this.pick(x, y, o), point: (e) => this.canvasPoint(e) }, opts);
|
|
3240
|
+
}
|
|
3080
3241
|
/** A pointer event's place in canvas pixels (the canvas may be shown larger or smaller than its own size): `movie.pick(...movie.canvasPoint(event))`. */
|
|
3081
3242
|
canvasPoint(event) {
|
|
3082
3243
|
this._requireReady("canvasPoint");
|
|
@@ -4607,5 +4768,5 @@ exports.splitText = splitText;
|
|
|
4607
4768
|
exports.stagger = stagger;
|
|
4608
4769
|
exports.wiggle = wiggle;
|
|
4609
4770
|
exports.withFade = withFade;
|
|
4610
|
-
//# sourceMappingURL=chunk-
|
|
4611
|
-
//# sourceMappingURL=chunk-
|
|
4771
|
+
//# sourceMappingURL=chunk-BEGOKE7Q.cjs.map
|
|
4772
|
+
//# sourceMappingURL=chunk-BEGOKE7Q.cjs.map
|