pixi-effects 0.41.0 → 0.42.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 +9 -0
- package/README.md +5 -5
- package/ai/chat-template.html +3 -3
- package/dist/Controller.d.cts +1 -1
- package/dist/Controller.d.ts +1 -1
- package/dist/{Movie-DWtxRiJ2.d.cts → Movie-BHGhg-fJ.d.cts} +44 -3
- package/dist/{Movie-CwqRLOzE.d.ts → Movie-CBVFZ1kg.d.ts} +44 -3
- package/dist/{chunk-Y2N6U3X5.js → chunk-NFJKBWYO.js} +150 -8
- package/dist/chunk-NFJKBWYO.js.map +1 -0
- package/dist/{chunk-RN5FWGGM.cjs → chunk-WVZLAIKK.cjs} +150 -8
- package/dist/chunk-WVZLAIKK.cjs.map +1 -0
- package/dist/index.cjs +25 -25
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/loader.css +1 -1
- package/dist/present.cjs +1 -1
- package/dist/present.d.cts +1 -1
- package/dist/present.d.ts +1 -1
- package/dist/present.js +1 -1
- package/dist/three.cjs +34 -1
- package/dist/three.cjs.map +1 -1
- package/dist/three.d.cts +11 -0
- package/dist/three.d.ts +11 -0
- package/dist/three.js +35 -2
- package/dist/three.js.map +1 -1
- package/docs/api.md +23 -3
- package/llms-full.txt +144 -15
- package/package.json +1 -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
|
@@ -1732,6 +1732,23 @@ function inspectScene(root, frame, time, canvas, opts = {}) {
|
|
|
1732
1732
|
}
|
|
1733
1733
|
|
|
1734
1734
|
// src/core/pick.ts
|
|
1735
|
+
var scratch;
|
|
1736
|
+
var saidBlind = /* @__PURE__ */ new Set();
|
|
1737
|
+
var readResourceAlpha = (resource, x, y) => {
|
|
1738
|
+
try {
|
|
1739
|
+
if (scratch === void 0) {
|
|
1740
|
+
const c = document.createElement("canvas");
|
|
1741
|
+
c.width = c.height = 1;
|
|
1742
|
+
scratch = c.getContext("2d", { willReadFrequently: true });
|
|
1743
|
+
}
|
|
1744
|
+
if (!scratch) return null;
|
|
1745
|
+
scratch.clearRect(0, 0, 1, 1);
|
|
1746
|
+
scratch.drawImage(resource, x, y, 1, 1, 0, 0, 1, 1);
|
|
1747
|
+
return scratch.getImageData(0, 0, 1, 1).data[3] / 255;
|
|
1748
|
+
} catch {
|
|
1749
|
+
return null;
|
|
1750
|
+
}
|
|
1751
|
+
};
|
|
1735
1752
|
function pointInQuad(q, x, y) {
|
|
1736
1753
|
let pos = 0, neg = 0;
|
|
1737
1754
|
for (let i = 0; i < 4; i++) {
|
|
@@ -1756,11 +1773,14 @@ var above = (a, b) => {
|
|
|
1756
1773
|
}
|
|
1757
1774
|
return b.length - a.length;
|
|
1758
1775
|
};
|
|
1759
|
-
function pickScene(root, x, y, opts = {}) {
|
|
1776
|
+
function pickScene(root, x, y, opts = {}, deps = {}) {
|
|
1777
|
+
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}`);
|
|
1778
|
+
const readAlpha = deps.readAlpha ?? readResourceAlpha;
|
|
1760
1779
|
const found = [];
|
|
1780
|
+
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
1781
|
const wanted = (name, path) => {
|
|
1762
|
-
if (opts.ignore && (opts.ignore
|
|
1763
|
-
if (opts.only && !(opts.only
|
|
1782
|
+
if (opts.ignore && names(opts.ignore, name, path)) return false;
|
|
1783
|
+
if (opts.only && !names(opts.only, name, path)) return false;
|
|
1764
1784
|
return true;
|
|
1765
1785
|
};
|
|
1766
1786
|
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 +1810,34 @@ function pickScene(root, x, y, opts = {}) {
|
|
|
1790
1810
|
const lb = d.getLocalBounds();
|
|
1791
1811
|
if (inside(lb, local)) {
|
|
1792
1812
|
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
|
-
|
|
1813
|
+
if (three) {
|
|
1814
|
+
const planeOf = seq.dragPlane;
|
|
1815
|
+
if (planeOf) {
|
|
1816
|
+
three.grab = (plane = "screen") => {
|
|
1817
|
+
const along = planeOf.call(seq, three.point, plane);
|
|
1818
|
+
return { move: (cx, cy) => {
|
|
1819
|
+
const lp = d.toLocal({ x: cx, y: cy });
|
|
1820
|
+
const b = d.getLocalBounds();
|
|
1821
|
+
return along((lp.x - b.x) / b.width, (lp.y - b.y) / b.height);
|
|
1822
|
+
} };
|
|
1823
|
+
};
|
|
1824
|
+
}
|
|
1825
|
+
hit = { name, path, type: seq.spec.type, kind: "three", point, three };
|
|
1826
|
+
} else if (three === void 0 && (typeof d.containsPoint !== "function" || d.containsPoint(local))) {
|
|
1827
|
+
let opaque = true;
|
|
1828
|
+
const tex = opts.alpha !== void 0 && seq.spec.type !== "shader" ? d.texture : void 0;
|
|
1829
|
+
if (tex?.source?.resource) {
|
|
1830
|
+
const res = tex.source.resolution ?? 1;
|
|
1831
|
+
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);
|
|
1832
|
+
if (a === null) {
|
|
1833
|
+
if (!saidBlind.has(path)) {
|
|
1834
|
+
saidBlind.add(path);
|
|
1835
|
+
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`);
|
|
1836
|
+
}
|
|
1837
|
+
} else opaque = a > opts.alpha;
|
|
1838
|
+
}
|
|
1839
|
+
if (opaque) hit = { name, path, type: seq.spec.type, kind: "flat", point, local: { x: local.x - lb.x, y: local.y - lb.y } };
|
|
1840
|
+
}
|
|
1795
1841
|
}
|
|
1796
1842
|
}
|
|
1797
1843
|
if (!hit) return;
|
|
@@ -1805,6 +1851,82 @@ function pickScene(root, x, y, opts = {}) {
|
|
|
1805
1851
|
return found.sort((a, b) => above(a.order, b.order)).map((f) => f.hit);
|
|
1806
1852
|
}
|
|
1807
1853
|
|
|
1854
|
+
// src/core/hover.ts
|
|
1855
|
+
var keyOf = (h) => h ? `${h.path}${h.three ? `#${h.three.object}` : ""}` : null;
|
|
1856
|
+
function startHover(host, opts = {}) {
|
|
1857
|
+
const { canvas } = host;
|
|
1858
|
+
const request = host.requestFrame ?? ((fn) => requestAnimationFrame(fn));
|
|
1859
|
+
const cancel = host.cancelFrame ?? ((id) => cancelAnimationFrame(id));
|
|
1860
|
+
const cursor = opts.cursor === true ? "pointer" : opts.cursor || "";
|
|
1861
|
+
const pickOpts = {};
|
|
1862
|
+
if (opts.only) pickOpts.only = opts.only;
|
|
1863
|
+
if (opts.ignore) pickOpts.ignore = opts.ignore;
|
|
1864
|
+
let current = null;
|
|
1865
|
+
let last = null;
|
|
1866
|
+
let loop = null;
|
|
1867
|
+
let said = false;
|
|
1868
|
+
const call = (fn, hit) => {
|
|
1869
|
+
if (!fn) return;
|
|
1870
|
+
try {
|
|
1871
|
+
fn(hit);
|
|
1872
|
+
} catch (err) {
|
|
1873
|
+
if (!said) {
|
|
1874
|
+
said = true;
|
|
1875
|
+
console.warn("pixi-effects: movie.hover: a handler threw (said once) \u2014", err);
|
|
1876
|
+
}
|
|
1877
|
+
}
|
|
1878
|
+
};
|
|
1879
|
+
const setCursor = (on) => {
|
|
1880
|
+
if (cursor) canvas.style.cursor = on ? cursor : "";
|
|
1881
|
+
};
|
|
1882
|
+
const evaluate = () => {
|
|
1883
|
+
if (!last) return;
|
|
1884
|
+
const [x, y] = host.point(last);
|
|
1885
|
+
const hit = host.pick(x, y, pickOpts);
|
|
1886
|
+
if (keyOf(hit) === keyOf(current)) {
|
|
1887
|
+
current = hit ?? current;
|
|
1888
|
+
return;
|
|
1889
|
+
}
|
|
1890
|
+
const was = current;
|
|
1891
|
+
current = hit;
|
|
1892
|
+
if (was) call(opts.onLeave, was);
|
|
1893
|
+
if (hit) call(opts.onEnter, hit);
|
|
1894
|
+
setCursor(!!hit);
|
|
1895
|
+
};
|
|
1896
|
+
const tick = () => {
|
|
1897
|
+
loop = null;
|
|
1898
|
+
if (last) {
|
|
1899
|
+
evaluate();
|
|
1900
|
+
loop = request(tick);
|
|
1901
|
+
}
|
|
1902
|
+
};
|
|
1903
|
+
const onMove = (event) => {
|
|
1904
|
+
last = event;
|
|
1905
|
+
evaluate();
|
|
1906
|
+
if (loop === null) loop = request(tick);
|
|
1907
|
+
};
|
|
1908
|
+
const onLeave = () => {
|
|
1909
|
+
last = null;
|
|
1910
|
+
if (loop !== null) {
|
|
1911
|
+
cancel(loop);
|
|
1912
|
+
loop = null;
|
|
1913
|
+
}
|
|
1914
|
+
const was = current;
|
|
1915
|
+
current = null;
|
|
1916
|
+
if (was) call(opts.onLeave, was);
|
|
1917
|
+
setCursor(false);
|
|
1918
|
+
};
|
|
1919
|
+
canvas.addEventListener("pointermove", onMove);
|
|
1920
|
+
canvas.addEventListener("pointerdown", onMove);
|
|
1921
|
+
canvas.addEventListener("pointerleave", onLeave);
|
|
1922
|
+
return () => {
|
|
1923
|
+
canvas.removeEventListener("pointermove", onMove);
|
|
1924
|
+
canvas.removeEventListener("pointerdown", onMove);
|
|
1925
|
+
canvas.removeEventListener("pointerleave", onLeave);
|
|
1926
|
+
onLeave();
|
|
1927
|
+
};
|
|
1928
|
+
}
|
|
1929
|
+
|
|
1808
1930
|
// src/core/timelineChart.ts
|
|
1809
1931
|
var GROUP_MIN = 4;
|
|
1810
1932
|
var MAX_KEYS = 200;
|
|
@@ -2859,6 +2981,14 @@ var Movie = class {
|
|
|
2859
2981
|
await this._goto(frame);
|
|
2860
2982
|
this.emit("seeked", { frame: this.currentFrame, totalFrames: this.totalFrames });
|
|
2861
2983
|
}
|
|
2984
|
+
/**
|
|
2985
|
+
* 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
|
|
2986
|
+
* state (a dragged object's place) shows it after `await movie.redraw()`. A playing movie needs no call: the next frame draws it.
|
|
2987
|
+
*/
|
|
2988
|
+
async redraw() {
|
|
2989
|
+
this._requireReady("redraw");
|
|
2990
|
+
await this._quietly(() => this.gotoFrame(this.currentFrame, true));
|
|
2991
|
+
}
|
|
2862
2992
|
/** Run `fn` with `seeking` / `seeked` silenced: the movie is moving its own playhead, not answering a seek. */
|
|
2863
2993
|
async _quietly(fn) {
|
|
2864
2994
|
this._quiet++;
|
|
@@ -3072,11 +3202,23 @@ var Movie = class {
|
|
|
3072
3202
|
}
|
|
3073
3203
|
/** Every layer under the canvas point, the one on top first (see `pick`). */
|
|
3074
3204
|
pickAll(x, y, opts = {}) {
|
|
3075
|
-
chunkTWZNOUM7_cjs.warnUnknownOptions("movie.pick()", opts, ["only", "ignore"]);
|
|
3205
|
+
chunkTWZNOUM7_cjs.warnUnknownOptions("movie.pick()", opts, ["only", "ignore", "alpha"]);
|
|
3076
3206
|
this._requireReady("pick");
|
|
3077
3207
|
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
3208
|
return pickScene(this._rootSequence, x, y, opts);
|
|
3079
3209
|
}
|
|
3210
|
+
/**
|
|
3211
|
+
* 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
|
|
3212
|
+
* 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.
|
|
3213
|
+
* `{ 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.
|
|
3214
|
+
*/
|
|
3215
|
+
hover(opts = {}) {
|
|
3216
|
+
chunkTWZNOUM7_cjs.warnUnknownOptions("movie.hover()", opts, ["onEnter", "onLeave", "cursor", "only", "ignore"]);
|
|
3217
|
+
this._requireReady("hover");
|
|
3218
|
+
const canvas = this.app?.canvas;
|
|
3219
|
+
if (!canvas) throw new Error("pixi-effects: movie.hover needs the movie's canvas");
|
|
3220
|
+
return startHover({ canvas, pick: (x, y, o) => this.pick(x, y, o), point: (e) => this.canvasPoint(e) }, opts);
|
|
3221
|
+
}
|
|
3080
3222
|
/** 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
3223
|
canvasPoint(event) {
|
|
3082
3224
|
this._requireReady("canvasPoint");
|
|
@@ -4607,5 +4749,5 @@ exports.splitText = splitText;
|
|
|
4607
4749
|
exports.stagger = stagger;
|
|
4608
4750
|
exports.wiggle = wiggle;
|
|
4609
4751
|
exports.withFade = withFade;
|
|
4610
|
-
//# sourceMappingURL=chunk-
|
|
4611
|
-
//# sourceMappingURL=chunk-
|
|
4752
|
+
//# sourceMappingURL=chunk-WVZLAIKK.cjs.map
|
|
4753
|
+
//# sourceMappingURL=chunk-WVZLAIKK.cjs.map
|