pixi-effects 0.42.0 → 0.44.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 +17 -0
- package/README.md +5 -5
- package/ai/chat-template.html +3 -3
- package/ai/tools/check.mjs +131 -2
- package/dist/Controller.d.cts +2 -2
- package/dist/Controller.d.ts +2 -2
- package/dist/{Movie-BHGhg-fJ.d.cts → Movie-B3VOAgwc.d.cts} +5 -3
- package/dist/{Movie-CBVFZ1kg.d.ts → Movie-CQCVUqRs.d.ts} +5 -3
- package/dist/{chunk-NFJKBWYO.js → chunk-4MBTYREC.js} +100 -31
- package/dist/chunk-4MBTYREC.js.map +1 -0
- package/dist/{chunk-WVZLAIKK.cjs → chunk-MAAM45ZX.cjs} +99 -30
- package/dist/chunk-MAAM45ZX.cjs.map +1 -0
- package/dist/index.cjs +25 -25
- package/dist/index.d.cts +3 -4
- package/dist/index.d.ts +3 -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 +166 -38
- package/dist/three.cjs.map +1 -1
- package/dist/three.d.cts +37 -2
- package/dist/three.d.ts +37 -2
- package/dist/three.js +168 -40
- package/dist/three.js.map +1 -1
- package/dist/{types-DIh93lFb.d.cts → types-C5xo0fzb.d.cts} +92 -1
- package/dist/{types-DIh93lFb.d.ts → types-C5xo0fzb.d.ts} +92 -1
- package/docs/api.md +4 -2
- package/docs/dsl.md +4 -2
- package/llms-full.txt +12 -8
- package/package.json +2 -1
- package/skills/pixi-effects/SKILL.md +2 -2
- package/skills/pixi-effects/reference/recipes.md +2 -2
- package/skills/pixi-effects/template.html +6 -6
- package/dist/Base-DQWIJ6bJ.d.cts +0 -60
- package/dist/Base-Jgkud1Aw.d.ts +0 -60
- package/dist/chunk-NFJKBWYO.js.map +0 -1
- package/dist/chunk-WVZLAIKK.cjs.map +0 -1
package/dist/three.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { Sequence, buildScope, evaluateExpr, registerSequenceType } from './chunk-4QVQ5UJJ.js';
|
|
2
2
|
import './chunk-32MMNDDN.js';
|
|
3
3
|
import './chunk-BXOCEZ4U.js';
|
|
4
|
-
import { Texture, Sprite } from 'pixi.js';
|
|
5
|
-
import { WebGLRenderer, Scene, PerspectiveCamera, Raycaster, Vector2, Vector3, Quaternion, Plane, Box3, Group, AnimationMixer, LoopOnce, LoopRepeat, AmbientLight, DirectionalLight, SpotLight, PointLight, Color, SRGBColorSpace, Fog } from 'three';
|
|
4
|
+
import { Texture, Sprite, TextureSource } from 'pixi.js';
|
|
5
|
+
import { WebGLRenderer, Scene, PerspectiveCamera, Raycaster, Vector2, Vector3, Quaternion, Plane, Box3, RenderTarget, Group, AnimationMixer, LoopOnce, LoopRepeat, AmbientLight, DirectionalLight, SpotLight, PointLight, Color, SRGBColorSpace, Fog } from 'three';
|
|
6
6
|
|
|
7
7
|
// src/three/defaults.ts
|
|
8
8
|
var pageRenderer = "webgl";
|
|
@@ -159,7 +159,7 @@ function trackThree(kind) {
|
|
|
159
159
|
live[kind]++;
|
|
160
160
|
if (live[kind] > WARN_ABOVE[kind] && !warned.has(kind)) {
|
|
161
161
|
warned.add(kind);
|
|
162
|
-
console.warn(`pixi-effects: ${live[kind]} three layers are alive with renderer: '${kind}', and a browser keeps ${LIMIT[kind]} for the whole page; layers beyond that draw nothing, without an error. Put several objects in one three layer, destroy layers that are over, ` + (kind === "webgl" ? `or use renderer: 'webgpu' for some (its limit is about 32)` : `or use renderer: 'webgl' for some of them (a different pool of contexts)`));
|
|
162
|
+
console.warn(`pixi-effects: ${live[kind]} three layers are alive with renderer: '${kind}', and a browser keeps ${LIMIT[kind]} for the whole page; layers beyond that draw nothing, without an error. Put several objects in one three layer, destroy layers that are over, ` + (kind === "webgl" ? `or use renderer: 'webgpu' for some (in a movie PixiJS draws on WebGPU they share its GPU device and have no limit; otherwise it is about 32)` : `or use renderer: 'webgl' for some of them (a different pool of contexts), or leave shareGpu on in a movie PixiJS draws on WebGPU (the layers then share its device)`));
|
|
163
163
|
}
|
|
164
164
|
}
|
|
165
165
|
function releaseThree(kind) {
|
|
@@ -176,6 +176,19 @@ var ThreeSequence = class extends Sequence {
|
|
|
176
176
|
backend = null;
|
|
177
177
|
_gpu = false;
|
|
178
178
|
// renderer: 'webgpu': async init and async render
|
|
179
|
+
/** True when the layer draws on PixiJS's own GPU device into a texture PixiJS samples directly (no canvas of its own, no copy, no share of the page's context cap). */
|
|
180
|
+
sharedGpu = false;
|
|
181
|
+
_rt = null;
|
|
182
|
+
// the texture a shared layer draws into
|
|
183
|
+
_sharedTexture = null;
|
|
184
|
+
_texture = null;
|
|
185
|
+
// what the layer's sprite shows (the canvas's, or the shared render target's)
|
|
186
|
+
/** What a rebuilt layer is compared with to take this one's place (core/reuse.ts); null: this layer is never kept (`reuse: false`, no `name`). */
|
|
187
|
+
_key = null;
|
|
188
|
+
/** The layer of the tree being replaced whose state this one is using until the new tree is on stage (`commitReuse`): not this layer's to let go. */
|
|
189
|
+
_borrowed = null;
|
|
190
|
+
/** True once another layer owns this layer's state: destroying this one must not let it go. */
|
|
191
|
+
_donated = false;
|
|
179
192
|
_scene = null;
|
|
180
193
|
_camera = null;
|
|
181
194
|
_ctx = null;
|
|
@@ -207,12 +220,18 @@ var ThreeSequence = class extends Sequence {
|
|
|
207
220
|
const width = resolveDim(spec.width, scope) ?? this.parent?.width ?? this.root.width;
|
|
208
221
|
const height = resolveDim(spec.height, scope) ?? this.parent?.height ?? this.root.height;
|
|
209
222
|
const resolution = spec.resolution ?? 1;
|
|
210
|
-
const canvas = document.createElement("canvas");
|
|
211
223
|
const antialias = spec.antialias ?? true;
|
|
212
224
|
const kind = spec.renderer ?? getPageRenderer();
|
|
213
225
|
checkRendererKind(kind, "a three layer's renderer");
|
|
214
226
|
this._gpu = kind === "webgpu";
|
|
215
227
|
this.renderer = kind;
|
|
228
|
+
this._key = spec.reuse === false || !spec.name ? null : JSON.stringify([spec.name, idOf(spec.setup), width, height, resolution, antialias, kind, spec.shareGpu !== false && !!this.root.gpu, !!spec.followCamera, !!spec.followLights, !!spec.followFog]);
|
|
229
|
+
const donor = this._key !== null ? this.root.reuse?.claim(this._key) : null;
|
|
230
|
+
if (donor && donor._lendable()) {
|
|
231
|
+
this._borrow(donor, width, height, spec.name);
|
|
232
|
+
return;
|
|
233
|
+
}
|
|
234
|
+
const canvas = document.createElement("canvas");
|
|
216
235
|
let renderer;
|
|
217
236
|
if (this._gpu) {
|
|
218
237
|
let mod;
|
|
@@ -221,24 +240,36 @@ var ThreeSequence = class extends Sequence {
|
|
|
221
240
|
} catch (err) {
|
|
222
241
|
throw new Error(`pixi-effects: renderer: 'webgpu' needs three 0.17x or later with "three/webgpu" in the import map (${err instanceof Error ? err.message : err})`);
|
|
223
242
|
}
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
243
|
+
let shared = spec.shareGpu === false ? void 0 : this.root.gpu;
|
|
244
|
+
for (; ; ) {
|
|
245
|
+
renderer = new mod.WebGPURenderer(shared ? { device: shared.device, alpha: true, antialias } : { canvas, alpha: true, antialias });
|
|
246
|
+
this._renderer = renderer;
|
|
247
|
+
if (!shared) this._track();
|
|
248
|
+
const warn = console.warn;
|
|
249
|
+
let noGpu = false;
|
|
250
|
+
console.warn = (...args) => {
|
|
251
|
+
if (/WebGPU is not available/.test(String(args[0]))) noGpu = true;
|
|
252
|
+
else warn.apply(console, args);
|
|
253
|
+
};
|
|
254
|
+
try {
|
|
255
|
+
await renderer.init();
|
|
256
|
+
if (shared) {
|
|
257
|
+
renderer.setSize(Math.round(width * resolution), Math.round(height * resolution), false);
|
|
258
|
+
renderer.setClearColor(0, 0);
|
|
259
|
+
this._prepareShared(renderer, shared, width, height, resolution, antialias);
|
|
260
|
+
}
|
|
261
|
+
this.backend = noGpu ? "webgl2" : "webgpu";
|
|
262
|
+
break;
|
|
263
|
+
} catch (err) {
|
|
264
|
+
this._disposeRenderer();
|
|
265
|
+
if (!shared) throw err;
|
|
266
|
+
console.warn(`pixi-effects: three layer${spec.name ? ` "${spec.name}"` : ""}: could not draw on PixiJS's GPU device (${err instanceof Error ? err.message : err}); it uses a canvas of its own (shareGpu: false does this on purpose)`);
|
|
267
|
+
shared = void 0;
|
|
268
|
+
this._closing = false;
|
|
269
|
+
} finally {
|
|
270
|
+
console.warn = warn;
|
|
271
|
+
}
|
|
240
272
|
}
|
|
241
|
-
this.backend = noGpu ? "webgl2" : "webgpu";
|
|
242
273
|
} else {
|
|
243
274
|
renderer = new WebGLRenderer({ canvas, alpha: true, antialias });
|
|
244
275
|
this._renderer = renderer;
|
|
@@ -272,20 +303,59 @@ var ThreeSequence = class extends Sequence {
|
|
|
272
303
|
if (!("camera" in this._objects)) this._objects.camera = this._camera;
|
|
273
304
|
if (this._gpu) this._checkWebGpuMaterials(scene, spec.name);
|
|
274
305
|
this._draw(0);
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
sprite.cullable = true;
|
|
278
|
-
sprite.width = width;
|
|
279
|
-
sprite.height = height;
|
|
280
|
-
this.target = sprite;
|
|
281
|
-
this.intrinsicWidth = width;
|
|
282
|
-
this.intrinsicHeight = height;
|
|
283
|
-
this.buildFilters();
|
|
306
|
+
this._texture = this._sharedTexture ?? Texture.from(canvas);
|
|
307
|
+
this._makeSprite(this._texture, width, height, spec.name);
|
|
284
308
|
} catch (err) {
|
|
285
309
|
this._disposeRenderer();
|
|
286
310
|
throw err;
|
|
287
311
|
}
|
|
288
312
|
}
|
|
313
|
+
_makeSprite(texture, width, height, name) {
|
|
314
|
+
const sprite = new Sprite({ texture, label: name });
|
|
315
|
+
sprite.cullable = true;
|
|
316
|
+
sprite.width = width;
|
|
317
|
+
sprite.height = height;
|
|
318
|
+
this.target = sprite;
|
|
319
|
+
this.intrinsicWidth = width;
|
|
320
|
+
this.intrinsicHeight = height;
|
|
321
|
+
this.buildFilters();
|
|
322
|
+
}
|
|
323
|
+
/** Reuse (core/reuse.ts): the key this layer is matched by, while it can still lend its state. */
|
|
324
|
+
reuseKey() {
|
|
325
|
+
return this._renderer && !this._donated && !this._closing ? this._key : null;
|
|
326
|
+
}
|
|
327
|
+
_lendable() {
|
|
328
|
+
return this.reuseKey() !== null && !!this._scene && !!this._ctx && !!this._texture;
|
|
329
|
+
}
|
|
330
|
+
/** Take over a layer of the tree being replaced: its scene, renderer, texture and mirrors. Nothing is drawn until the new tree is on stage; the old layer goes on drawing meanwhile. */
|
|
331
|
+
_borrow(d, width, height, name) {
|
|
332
|
+
this.renderer = d.renderer;
|
|
333
|
+
this.backend = d.backend;
|
|
334
|
+
this._gpu = d._gpu;
|
|
335
|
+
this.sharedGpu = d.sharedGpu;
|
|
336
|
+
this._renderer = d._renderer;
|
|
337
|
+
this._scene = d._scene;
|
|
338
|
+
this._camera = d._camera;
|
|
339
|
+
this._ctx = d._ctx;
|
|
340
|
+
this._objects = d._objects;
|
|
341
|
+
this._rt = d._rt;
|
|
342
|
+
this._sharedTexture = d._sharedTexture;
|
|
343
|
+
this._texture = d._texture;
|
|
344
|
+
this._lightMirror = d._lightMirror;
|
|
345
|
+
this._fogMirror = d._fogMirror;
|
|
346
|
+
this._tracked = d._tracked;
|
|
347
|
+
this._borrowed = d;
|
|
348
|
+
if (this.spec && this._threeSpec.followCamera) this._checkFollowShape(width, height, name);
|
|
349
|
+
this._makeSprite(this._texture, width, height, name);
|
|
350
|
+
}
|
|
351
|
+
/** The new tree is on stage: the layer this one borrowed from has given its state away for good. */
|
|
352
|
+
commitReuse() {
|
|
353
|
+
const d = this._borrowed;
|
|
354
|
+
if (!d) return;
|
|
355
|
+
d._donated = true;
|
|
356
|
+
d._tracked = false;
|
|
357
|
+
this._borrowed = null;
|
|
358
|
+
}
|
|
289
359
|
/**
|
|
290
360
|
* Per-frame sync hook. Movie._awaitVideoFrames duck-types on this method
|
|
291
361
|
* (same contract as VideoSequence) and awaits it inside gotoFrame — the
|
|
@@ -308,7 +378,7 @@ var ThreeSequence = class extends Sequence {
|
|
|
308
378
|
}
|
|
309
379
|
}
|
|
310
380
|
this._draw(t);
|
|
311
|
-
this.target?.texture.source.update();
|
|
381
|
+
if (!this.sharedGpu) this.target?.texture.source.update();
|
|
312
382
|
}
|
|
313
383
|
/**
|
|
314
384
|
* `movie.pick`: a ray through the point (u, v) of the layer's picture (0..1, v down) from the layer's camera, and what it meets first: the object's name (its own, or its nearest
|
|
@@ -398,7 +468,7 @@ var ThreeSequence = class extends Sequence {
|
|
|
398
468
|
try {
|
|
399
469
|
this._followSpace(t);
|
|
400
470
|
this._threeSpec.update?.(t, ctx);
|
|
401
|
-
this._draw(t);
|
|
471
|
+
this._draw(t, true);
|
|
402
472
|
g.clearRect(0, 0, w, h);
|
|
403
473
|
g.drawImage(source, 0, 0);
|
|
404
474
|
} catch {
|
|
@@ -501,10 +571,45 @@ var ThreeSequence = class extends Sequence {
|
|
|
501
571
|
* follow each other in one task (a seek, an export) would all show the lights of the last animation frame: a lamp keyframed with `three.lamp.intensity` would not move.
|
|
502
572
|
* So before each render the layer advances the node frame itself, and gives `time` the layer's own time (not three's wall clock).
|
|
503
573
|
*/
|
|
504
|
-
_draw(t) {
|
|
574
|
+
_draw(t, toCanvas = false) {
|
|
505
575
|
if (!this._renderer || !this._scene || !this._camera) return;
|
|
506
576
|
if (this._gpu) this._advanceNodeFrame(t);
|
|
507
|
-
|
|
577
|
+
if (!this._rt || toCanvas) {
|
|
578
|
+
this._renderer.render(this._scene, this._camera);
|
|
579
|
+
return;
|
|
580
|
+
}
|
|
581
|
+
const r = this._renderer;
|
|
582
|
+
r.setOutputRenderTarget(this._rt);
|
|
583
|
+
try {
|
|
584
|
+
this._renderer.render(this._scene, this._camera);
|
|
585
|
+
} finally {
|
|
586
|
+
r.setOutputRenderTarget(null);
|
|
587
|
+
r.setRenderTarget(null);
|
|
588
|
+
}
|
|
589
|
+
}
|
|
590
|
+
/**
|
|
591
|
+
* A shared layer's texture: a render target of the layer's size, drawn into once (the GPU texture exists only after a draw) and adopted by a PixiJS texture source. Throws when something
|
|
592
|
+
* is not as this expects (the build then makes the layer again on a canvas of its own). Done before `setup`, so nothing the author made yet depends on the renderer.
|
|
593
|
+
*/
|
|
594
|
+
_prepareShared(renderer, shared, width, height, resolution, antialias) {
|
|
595
|
+
const w = Math.round(width * resolution), h = Math.round(height * resolution);
|
|
596
|
+
const rt = new RenderTarget(w, h, { depthBuffer: true, samples: antialias ? 4 : 0 });
|
|
597
|
+
this._rt = rt;
|
|
598
|
+
const r = renderer;
|
|
599
|
+
if (typeof r.setOutputRenderTarget !== "function") throw new Error("this three has no setOutputRenderTarget");
|
|
600
|
+
r.setOutputRenderTarget(rt);
|
|
601
|
+
try {
|
|
602
|
+
renderer.render(new Scene(), new PerspectiveCamera());
|
|
603
|
+
} finally {
|
|
604
|
+
r.setOutputRenderTarget(null);
|
|
605
|
+
r.setRenderTarget(null);
|
|
606
|
+
}
|
|
607
|
+
const gpuTexture = r.backend?.get?.(rt.texture)?.texture;
|
|
608
|
+
if (!gpuTexture || typeof gpuTexture.createView !== "function") throw new Error("three keeps no GPU texture for a render target");
|
|
609
|
+
const source = new TextureSource({ width: w, height: h, format: gpuTexture.format, label: "three layer (shared GPU)" });
|
|
610
|
+
shared.adopt(source, gpuTexture);
|
|
611
|
+
this._sharedTexture = new Texture({ source });
|
|
612
|
+
this.sharedGpu = true;
|
|
508
613
|
}
|
|
509
614
|
/**
|
|
510
615
|
* The author chose renderer: 'webgpu'. Three's WebGPU renderer turns materials into node materials: a ShaderMaterial / RawShaderMaterial cannot run there (three logs an error on
|
|
@@ -599,28 +704,40 @@ var ThreeSequence = class extends Sequence {
|
|
|
599
704
|
console.warn("pixi-effects: three renderer dispose threw \u2014", err);
|
|
600
705
|
}
|
|
601
706
|
this._renderer = null;
|
|
707
|
+
try {
|
|
708
|
+
this._rt?.dispose();
|
|
709
|
+
} catch {
|
|
710
|
+
}
|
|
711
|
+
this._rt = null;
|
|
602
712
|
}
|
|
603
713
|
destroy() {
|
|
604
714
|
const spec = this._threeSpec;
|
|
605
|
-
|
|
715
|
+
const kept = this._donated || this._borrowed !== null;
|
|
716
|
+
if (!kept && this._ctx && spec.dispose) {
|
|
606
717
|
try {
|
|
607
718
|
spec.dispose(this._ctx);
|
|
608
719
|
} catch (err) {
|
|
609
720
|
console.warn("pixi-effects: three dispose() threw \u2014", err);
|
|
610
721
|
}
|
|
611
722
|
}
|
|
612
|
-
const texture = this.
|
|
613
|
-
|
|
723
|
+
const texture = this._texture;
|
|
724
|
+
if (!kept) {
|
|
725
|
+
this._lightMirror?.dispose();
|
|
726
|
+
this._fogMirror?.dispose();
|
|
727
|
+
this._disposeRenderer();
|
|
728
|
+
}
|
|
614
729
|
this._lightMirror = null;
|
|
615
|
-
this._fogMirror?.dispose();
|
|
616
730
|
this._fogMirror = null;
|
|
617
|
-
this.
|
|
731
|
+
this._renderer = null;
|
|
732
|
+
this._rt = null;
|
|
618
733
|
this._scene = null;
|
|
619
734
|
this._camera = null;
|
|
620
735
|
this._ctx = null;
|
|
621
736
|
this._objects = {};
|
|
622
737
|
super.destroy();
|
|
623
|
-
texture?.destroy(true);
|
|
738
|
+
if (!kept) texture?.destroy(true);
|
|
739
|
+
this._texture = null;
|
|
740
|
+
this._sharedTexture = null;
|
|
624
741
|
}
|
|
625
742
|
};
|
|
626
743
|
function resolveDim(v, scope) {
|
|
@@ -628,6 +745,17 @@ function resolveDim(v, scope) {
|
|
|
628
745
|
if (typeof v === "number") return v;
|
|
629
746
|
return evaluateExpr(v, scope);
|
|
630
747
|
}
|
|
748
|
+
var ids = /* @__PURE__ */ new WeakMap();
|
|
749
|
+
var lastId = 0;
|
|
750
|
+
function idOf(fn) {
|
|
751
|
+
if (typeof fn !== "function") return 0;
|
|
752
|
+
let id = ids.get(fn);
|
|
753
|
+
if (id === void 0) {
|
|
754
|
+
id = ++lastId;
|
|
755
|
+
ids.set(fn, id);
|
|
756
|
+
}
|
|
757
|
+
return id;
|
|
758
|
+
}
|
|
631
759
|
async function threeGltf(url, options = {}) {
|
|
632
760
|
const label = "pixi-effects: threeGltf";
|
|
633
761
|
if (typeof url !== "string" || !url) throw new Error(`${label}: the first argument is the URL of a .glb or .gltf file`);
|