pixi-effects 0.49.0 → 0.50.1
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 +20 -0
- package/README.md +9 -8
- package/ai/CHAT.md +1 -1
- package/ai/chat-template.html +11 -5
- package/ai/tools/check.mjs +6 -6
- package/dist/3d.cjs +18 -13
- package/dist/3d.cjs.map +1 -1
- package/dist/3d.d.cts +3 -1
- package/dist/3d.d.ts +3 -1
- package/dist/3d.js +10 -5
- package/dist/3d.js.map +1 -1
- package/dist/Composition-5SBIDTBB.cjs +17 -0
- package/dist/{Composition-464AWDV6.cjs.map → Composition-5SBIDTBB.cjs.map} +1 -1
- package/dist/Composition-7D6ERUVY.js +8 -0
- package/dist/{Composition-5U63LMPX.js.map → Composition-7D6ERUVY.js.map} +1 -1
- package/dist/Controller.d.cts +2 -2
- package/dist/Controller.d.ts +2 -2
- package/dist/{Movie-BxB7bauG.d.cts → Movie-DogzDBuW.d.cts} +20 -5
- package/dist/{Movie-6EWOz6Yw.d.ts → Movie-Y7iHg2V8.d.ts} +20 -5
- package/dist/{Spans-DUR2W5EH.cjs → Spans-OBNYI6LJ.cjs} +12 -11
- package/dist/Spans-OBNYI6LJ.cjs.map +1 -0
- package/dist/{Spans-W5VJRMGC.js → Spans-WRQPIDPO.js} +7 -6
- package/dist/Spans-WRQPIDPO.js.map +1 -0
- package/dist/{blendModes-NC76DNVX.cjs → blendModes-2IDILRN6.cjs} +5 -5
- package/dist/{blendModes-NC76DNVX.cjs.map → blendModes-2IDILRN6.cjs.map} +1 -1
- package/dist/{blendModes-ZOBLPSR3.js → blendModes-4QH44GOL.js} +4 -4
- package/dist/{blendModes-ZOBLPSR3.js.map → blendModes-4QH44GOL.js.map} +1 -1
- package/dist/{chunk-PBMDZT2T.js → chunk-24MVJFW4.js} +40 -74
- package/dist/chunk-24MVJFW4.js.map +1 -0
- package/dist/{chunk-GUDLIAIG.cjs → chunk-2DC6TRJI.cjs} +83 -117
- package/dist/chunk-2DC6TRJI.cjs.map +1 -0
- package/dist/{chunk-BSFWVTSR.cjs → chunk-2VMLNKHT.cjs} +92 -92
- package/dist/{chunk-BSFWVTSR.cjs.map → chunk-2VMLNKHT.cjs.map} +1 -1
- package/dist/{chunk-ABWRISRK.cjs → chunk-3FCDRLW3.cjs} +4 -3
- package/dist/chunk-3FCDRLW3.cjs.map +1 -0
- package/dist/{chunk-MXACRKAN.js → chunk-C2HL5236.js} +4 -4
- package/dist/{chunk-MXACRKAN.js.map → chunk-C2HL5236.js.map} +1 -1
- package/dist/{chunk-5YNME6AH.cjs → chunk-GXGIISFS.cjs} +5 -5
- package/dist/{chunk-5YNME6AH.cjs.map → chunk-GXGIISFS.cjs.map} +1 -1
- package/dist/{chunk-H363KMJR.js → chunk-J4ZP76IL.js} +4 -3
- package/dist/chunk-J4ZP76IL.js.map +1 -0
- package/dist/{chunk-33USHRV5.cjs → chunk-NXMNBFHM.cjs} +567 -39
- package/dist/chunk-NXMNBFHM.cjs.map +1 -0
- package/dist/{chunk-USUUAYTE.js → chunk-OI75LGIB.js} +5 -5
- package/dist/{chunk-USUUAYTE.js.map → chunk-OI75LGIB.js.map} +1 -1
- package/dist/{chunk-DOGY3EAW.js → chunk-SC7EWGHB.js} +543 -17
- package/dist/chunk-SC7EWGHB.js.map +1 -0
- package/dist/index.cjs +39 -39
- package/dist/index.d.cts +3 -3
- package/dist/index.d.ts +3 -3
- 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 +15 -9
- package/dist/three.cjs.map +1 -1
- package/dist/three.d.cts +5 -1
- package/dist/three.d.ts +5 -1
- package/dist/three.js +10 -4
- package/dist/three.js.map +1 -1
- package/dist/{types-kt7DQKfO.d.cts → types-BZngm4nT.d.cts} +48 -5
- package/dist/{types-kt7DQKfO.d.ts → types-BZngm4nT.d.ts} +48 -5
- package/docs/api.md +14 -1
- package/docs/dsl.md +39 -3
- package/llms-full.txt +107 -6
- package/package.json +1 -1
- package/skills/pixi-effects/SKILL.md +4 -2
- package/skills/pixi-effects/reference/cheatsheet.md +2 -0
- package/skills/pixi-effects/reference/pitfalls.md +6 -0
- package/skills/pixi-effects/reference/recipes.md +42 -0
- package/skills/pixi-effects/template.html +15 -8
- package/dist/Composition-464AWDV6.cjs +0 -16
- package/dist/Composition-5U63LMPX.js +0 -7
- package/dist/Spans-DUR2W5EH.cjs.map +0 -1
- package/dist/Spans-W5VJRMGC.js.map +0 -1
- package/dist/chunk-33USHRV5.cjs.map +0 -1
- package/dist/chunk-ABWRISRK.cjs.map +0 -1
- package/dist/chunk-DOGY3EAW.js.map +0 -1
- package/dist/chunk-GUDLIAIG.cjs.map +0 -1
- package/dist/chunk-H363KMJR.js.map +0 -1
- package/dist/chunk-PBMDZT2T.js.map +0 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,25 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.50.1
|
|
4
|
+
|
|
5
|
+
Fixes from a trial of 8 fresh agents (Sonnet, Opus) making videos with `scene2d` / `scene3d` on 0.50.0; nothing breaks.
|
|
6
|
+
|
|
7
|
+
- **Fixed: an `.ogg` sound played nothing, with no warning.** PixiJS's own video loader took `.ogg` as a video, so an audio layer on it was silent and `check` said nothing; `.m4a`, `.flac` and `.opus` had no loader at all and stopped `init` with "Cannot read properties of null". An audio asset may now be `.mp3`, `.wav`, `.ogg`, `.oga`, `.m4a`, `.aac`, `.flac` or `.opus` (a query after the name is fine), and a sound asset that did not load, or a video with no sound track used as one, stops `init` with the layer, the asset, its file and the formats. Test film `audio-formats`.
|
|
8
|
+
- **PixiJS's official skills are named where an agent writes PixiJS code.** `scene2d` and `scene3d` hold plain PixiJS / PixiJS 3D code, and PixiJS publishes official skills for both (`npx skills add pixijs/pixijs-skills`, MIT); SKILL.md, AGENTS.md, the README, the For AI page and the `scene2d` / `scene3d` sections say so, with the copy inside the npm package of the version the template loads (`pixi.js@8.23.0/skills/pixijs`, `@pixi/3d@0.1.0/skills/pixijs-3d`), readable with no install. The `scene3d` section lists the @pixi/3d geometries with their options and the materials (`emissive: { color, strength }`), and says that @pixi/3d ignores an option it does not know (3 of 4 agents grepped the package's types for them; one passed `tubeRadius` to `TorusGeometry` and got a fat ring).
|
|
9
|
+
- **A PixiJS deprecation keeps its message in `check` and the chat's red box.** PixiJS prints it as a collapsed console group titled with the message and only the stack inside, so the collected warning was a bare stack; both templates now put an open group's title before the warnings inside it.
|
|
10
|
+
- **The sound-effect knobs are shown in place.** 4 of 8 agents wrote `pitch` beside `sfx: 'chime'` (the warning caught it); SKILL.md and CHAT.md now show `sfx: { preset: 'chime', pitch: 7 }` with the units.
|
|
11
|
+
- **`three`: `ctx.objects`** in `update`, what setup returned plus `camera`, as the `scene2d` and `scene3d` layers already have.
|
|
12
|
+
- **`random(seed)` and `rand(seed)` have their own section** in the API reference, so `help random` answers with them (it printed the canvas layer).
|
|
13
|
+
|
|
14
|
+
## 0.50.0
|
|
15
|
+
|
|
16
|
+
Nothing breaks: `scene2d`, a layer of PixiJS 2D objects built by your code (core, nothing to import), and two fixes for every engine: a rebuild that keeps a scene starts its keyframes from setup's values, and a routed `tint` keyframe moves by channel.
|
|
17
|
+
|
|
18
|
+
- **PixiJS 2D built by code: the `scene2d` layer** (core, nothing to import). `{ type: 'scene2d', setup({ root, width, height, texture }), update(t, ctx), dispose, width, height, reuse }`: your PixiJS display objects (`Graphics`, `Sprite`, `AnimatedSprite`, `Text`, a thousand pieces) as one layer, shaped like the `scene3d` layer, so a free box of PixiJS 2D no longer needs a `Sequence` subclass. Keyframes reach `scene2d.<object>.<path>` (raw PixiJS values); `anchorX` / `anchorY` place its box; `update` with a clock or `Math.random` warns; an `AnimatedSprite` left playing is posed from the layer's time (anything else with `autoUpdate` is turned off and said, a `<video>` texture is said); `check` draws it in two orders and names a layer whose same frame differs; `movie.pick` names the object under a point (`kind: 'scene2d'`, `hit.scene2d.object` by its label, `grab().move(x, y)`; empty space falls through) and `check --pick` prints it; `ctx.texture(name)` is a movie asset's texture; a named layer keeps its scene across `setVars` (`setup` runs once). Recipe `scene2d-basics`.
|
|
19
|
+
- **Fixed: a rebuild that keeps a scene (`scene2d`, `scene3d`, `three` with `reuse`) started its keyframes from the last frame the old movie showed.** After `setVars` late in a movie, a keyframe into the scene (`scene3d.cube.position.y`, `three.box.position.y`) began where the old movie had left the object, not where `setup` put it, so the picture differed from a fresh page. The values `setup` left are noted and put back at the swap; the old movie is not touched while the new tree is built. A layer used as a matte source that keeps its scene is committed too.
|
|
20
|
+
- **Fixed: a keyframe on a routed `tint`** (`scene2d.box.tint`, any `<router>.<object>.tint`) moves channel by channel and takes any colour form (it was interpolated as one number, or started from a colour it could not read).
|
|
21
|
+
- PixiJS 3D's own pointer events (`mesh.on('pointerdown')`) are tested to work in a scene3d layer; README and every gallery / interactive example load pixi.js 8.23.0.
|
|
22
|
+
|
|
3
23
|
## 0.49.0
|
|
4
24
|
|
|
5
25
|
Nothing breaks: 3D scenes drawn by PixiJS 3D (`@pixi/3d`), the new main 3D engine, as a `scene3d` layer (entry `pixi-effects/3d`); three.js stays as the sub engine. PixiJS 8.23 in the template.
|
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# pixi-effects
|
|
2
2
|
|
|
3
|
-
> **Status**: experimental — current release `0.
|
|
3
|
+
> **Status**: experimental — current release `0.50.1`. The API may still change between minor versions; see the [CHANGELOG](./CHANGELOG.md) for what each release changed.
|
|
4
4
|
|
|
5
5
|
**[Gallery →](https://yjmtmtk.github.io/pixi-effects/examples/gallery/)** · 43 pieces written as plain data by AI models · **[For AI →](https://yjmtmtk.github.io/pixi-effects/for-ai.html)** · what an AI reads and runs · **[Playground →](https://yjmtmtk.github.io/pixi-effects/examples/playground.html)** in the browser.
|
|
6
6
|
|
|
@@ -10,7 +10,7 @@ Give any AI (ChatGPT, Claude, Codex, Cursor, Claude Code …) one sentence:
|
|
|
10
10
|
|
|
11
11
|
> Use https://github.com/yjmtmtk/pixi-effects to make a video: a 10-second title for a bakery, warm colours, a soft chime at the end.
|
|
12
12
|
|
|
13
|
-
That is all it needs. **To register it as a skill** in your agent (Claude Code, Codex, Cursor, Gemini CLI, Copilot, OpenCode, …): `npx skills add yjmtmtk/pixi-effects` (update with `npx skills update`). In Claude Code you can also run `/plugin install pixi-effects --marketplace yjmtmtk/pixi-effects`. **If you are the AI** that was asked to do this, do not read the whole repository: if you can run commands (a shell, Node 22, Chrome), read [`AGENTS.md`](./AGENTS.md) and [`skills/pixi-effects/SKILL.md`](./skills/pixi-effects/SKILL.md); if you can only write text (a browser chat), fetch https://raw.githubusercontent.com/yjmtmtk/pixi-effects/main/ai/CHAT.md and follow it. You will write the video as plain data in one HTML file, check it (the check tool writes a contact sheet to look at), and hand it over; the person opens the file and downloads the MP4 with the button in the player bar.
|
|
13
|
+
That is all it needs. **To register it as a skill** in your agent (Claude Code, Codex, Cursor, Gemini CLI, Copilot, OpenCode, …): `npx skills add yjmtmtk/pixi-effects` (update with `npx skills update`). In Claude Code you can also run `/plugin install pixi-effects --marketplace yjmtmtk/pixi-effects`. For the PixiJS code you may write inside a `scene2d` or `scene3d` layer, PixiJS's own official skills help too: `npx skills add pixijs/pixijs-skills` ([pixijs/pixijs-skills](https://github.com/pixijs/pixijs-skills)). **If you are the AI** that was asked to do this, do not read the whole repository: if you can run commands (a shell, Node 22, Chrome), read [`AGENTS.md`](./AGENTS.md) and [`skills/pixi-effects/SKILL.md`](./skills/pixi-effects/SKILL.md); if you can only write text (a browser chat), fetch https://raw.githubusercontent.com/yjmtmtk/pixi-effects/main/ai/CHAT.md and follow it. You will write the video as plain data in one HTML file, check it (the check tool writes a contact sheet to look at), and hand it over; the person opens the file and downloads the MP4 with the button in the player bar.
|
|
14
14
|
|
|
15
15
|
Declarative composition and video rendering for the web. After Effects-style timelines on top of [PixiJS v8](https://pixijs.com/), with a small timeline of its own and strict TypeScript types. The ease names and the way `to` / `from` / `set` read are [GSAP](https://gsap.com/)'s, with thanks. Render to MP4 / WebM / MOV via [mediabunny](https://mediabunny.dev/).
|
|
16
16
|
|
|
@@ -25,6 +25,7 @@ Declarative composition and video rendering for the web. After Effects-style tim
|
|
|
25
25
|
- **Music written as text** — `{ type: 'audio', music: { bpm: 96, tracks: [{ inst: 'keys', notes: 'Cmaj7:4 Am7:4' }], drums: { kick: 'x...x...' } } }`: a tune with no audio file, played by a small built-in synthesiser (keys, pluck, pad, bass, lead, bell, music box, drums; chords by name, swing, fades, a ritardando). Deterministic, in the exported file at the same moment; an AI writes it as easily as a title.
|
|
26
26
|
- **Audio-reactive visuals** — `audioEnvelope('music.mp3')` analyses loudness, bass / mid / treble and the beats per frame; `react()` turns them into keyframes, so the picture follows the music and still renders identically.
|
|
27
27
|
- **2.5D layers & camera** — add `threeD: true`, `z`, `rotationX/Y` and a `{ type: 'camera' }` layer for parallax, flips and dolly zooms; no three.js needed.
|
|
28
|
+
- **PixiJS 2D by code** — a `scene2d` layer hands you a PixiJS container: build `Graphics`, `Sprite`s, `AnimatedSprite`s or a thousand pieces in `setup`, set them from the time in `update`, and it is a layer like any other (keyframes reach its objects as `scene2d.dot.alpha`, `movie.pick` names them, `check` holds it to "a function of the time").
|
|
28
29
|
- **3D scenes** *(optional)* — a real 3D scene (meshes, glTF models, PBR, lights, shadows) as a layer via `pixi-effects/3d`, drawn by [PixiJS 3D](https://pixijs.com/3d) inside PixiJS's own renderer, so masks, filters, blend modes and opacity work on it like on any layer; keyframes drive its objects (`scene3d.cube.rotation.y`). It can live in the composition's space (`followCamera`, `followLights`, `followFog`), load and pose a glTF from the time (`loadModel`), show a 2D layer on a mesh (`layerTexture`) and be clicked into (`movie.pick`).
|
|
29
30
|
- **three.js layer** *(optional)* — drop a real three.js scene in as a layer via `pixi-effects/three`; keyframes drive its objects (`three.cube.rotation.y`). It can live in the composition's space: the composition's camera, lights, shadows and fog drive the scene, so one `cameraPath()` flies through the flat layers and a glTF model together (`threeGltf`).
|
|
30
31
|
- **Built-in player UI — or your own** — a drop-in HTML5-`<video>`-style overlay controller (play, scrub, mute, volume, fullscreen, export-to-file) whose colours are one option (`theme: { accent: '#ff4d6d' }`); or build a player yourself on the movie's `<video>`-named events (`play pause ended seeking seeked volumechange error`).
|
|
@@ -49,10 +50,10 @@ Drop the imports into an [importmap](https://developer.mozilla.org/docs/Web/HTML
|
|
|
49
50
|
<script type="importmap">
|
|
50
51
|
{
|
|
51
52
|
"imports": {
|
|
52
|
-
"pixi.js": "https://esm.sh/pixi.js@8.
|
|
53
|
+
"pixi.js": "https://esm.sh/pixi.js@8.23.0?bundle-deps",
|
|
53
54
|
"mediabunny": "https://esm.sh/mediabunny",
|
|
54
|
-
"pixi-effects": "https://cdn.jsdelivr.net/npm/pixi-effects@0.
|
|
55
|
-
"pixi-effects/controller": "https://cdn.jsdelivr.net/npm/pixi-effects@0.
|
|
55
|
+
"pixi-effects": "https://cdn.jsdelivr.net/npm/pixi-effects@0.50.1/dist/index.js",
|
|
56
|
+
"pixi-effects/controller": "https://cdn.jsdelivr.net/npm/pixi-effects@0.50.1/dist/Controller.js"
|
|
56
57
|
}
|
|
57
58
|
}
|
|
58
59
|
</script>
|
|
@@ -65,7 +66,7 @@ Drop the imports into an [importmap](https://developer.mozilla.org/docs/Web/HTML
|
|
|
65
66
|
|
|
66
67
|
The `mediabunny` line is needed only to export (the download button, `movie.render()`) or for a `video` layer; a page that only plays can leave it out and never fetches it (or call `useMediabunny(url)` instead, see [the API](docs/api.md#where-the-encoder-comes-from-usemediabunnysource)).
|
|
67
68
|
|
|
68
|
-
Load the `dist/` files **as they are** (jsDelivr's `/npm/…/dist/…`, or unpkg's `https://unpkg.com/pixi-effects@0.
|
|
69
|
+
Load the `dist/` files **as they are** (jsDelivr's `/npm/…/dist/…`, or unpkg's `https://unpkg.com/pixi-effects@0.50.1/dist/index.js`) rather than a CDN-rebundled build such as `esm.sh/pixi-effects` or jsDelivr's `+esm`: the entries (`pixi-effects`, `…/controller`, `…/three`) share internal chunks, which only works when each file is served untouched.
|
|
69
70
|
|
|
70
71
|
> **A 3D scene?** Add three more entries (`pixi-effects/3d`, `@pixi/3d`, `@pixi/3d/extras`) — see [Adding a 3D scene](#adding-a-3d-scene-optional) below. **Using three.js?** Add two more entries (`three` and `pixi-effects/three`) to this importmap — see [Adding three.js](#adding-threejs-optional) below.
|
|
71
72
|
>
|
|
@@ -80,7 +81,7 @@ Add three entries to the importmap above (PixiJS 3D needs `pixi.js` 8.23.0 or la
|
|
|
80
81
|
{
|
|
81
82
|
"imports": {
|
|
82
83
|
"...": "(everything from the importmap above)",
|
|
83
|
-
"pixi-effects/3d": "https://cdn.jsdelivr.net/npm/pixi-effects@0.
|
|
84
|
+
"pixi-effects/3d": "https://cdn.jsdelivr.net/npm/pixi-effects@0.50.1/dist/3d.js",
|
|
84
85
|
"@pixi/3d": "https://cdn.jsdelivr.net/npm/@pixi/3d@0.1.0/dist/pixijs-3d.min.mjs",
|
|
85
86
|
"@pixi/3d/extras": "https://cdn.jsdelivr.net/npm/@pixi/3d@0.1.0/dist/pixijs-3d-extras.min.mjs"
|
|
86
87
|
}
|
|
@@ -124,7 +125,7 @@ Add two more entries to the importmap above: three.js itself, and the `pixi-effe
|
|
|
124
125
|
"...": "(everything from the importmap above)",
|
|
125
126
|
"three": "https://esm.sh/three@0.178.0",
|
|
126
127
|
"three/addons/": "https://cdn.jsdelivr.net/npm/three@0.178.0/examples/jsm/",
|
|
127
|
-
"pixi-effects/three": "https://cdn.jsdelivr.net/npm/pixi-effects@0.
|
|
128
|
+
"pixi-effects/three": "https://cdn.jsdelivr.net/npm/pixi-effects@0.50.1/dist/three.js"
|
|
128
129
|
}
|
|
129
130
|
}
|
|
130
131
|
</script>
|
package/ai/CHAT.md
CHANGED
|
@@ -58,7 +58,7 @@ That is a complete, working video (the block between the two markers). Change th
|
|
|
58
58
|
- **Shapes:** `shape: 'rect' | 'circle' | 'ellipse' | 'arc' | 'line' | 'polygon' | 'path'`. `rect`: `width height cornerRadius`; `circle`: `radius`; `line`: `from: [x, y], to: [x, y]` (canvas coordinates, no `x, y`); `path`: `d` (SVG path data). Style: `fillColor strokeColor strokeWidth fillAlpha`.
|
|
59
59
|
- **Text:** `style` is a PixiJS text style (`fontSize fontFamily fontWeight fill letterSpacing align wordWrap wordWrapWidth lineHeight`). Use fonts that exist everywhere (`Georgia, serif`, `Arial, sans-serif`, `ui-monospace, monospace`); this page loads no web fonts. Estimate a text's width at about 0.6 × `fontSize` per character, keep important text 5 % away from the edges, and keep the bottom 60 px free (the player bar covers it in the preview, not in the file).
|
|
60
60
|
- **Scenes.** Stack layers with `at` / `duration` over an opaque background rect. Do not remove layers.
|
|
61
|
-
- **Sound with no files:** `{ type: 'audio', sfx: 'swoosh', at: 2 }`. Presets: `click pop swoosh swipe hit riser chime beep coin glitch typewriter`;
|
|
61
|
+
- **Sound with no files:** `{ type: 'audio', sfx: 'swoosh', at: 2 }`. Presets: `click pop swoosh swipe hit riser chime beep coin glitch typewriter`; to change one: `sfx: { preset: 'chime', pitch: 7 }` (`pitch` in semitones, `brightness` −1 … 1; inside `sfx`, never beside it). A `riser` is loudest at its **end**: start it `duration` seconds before the hit. This page cannot load music or images from your own files; use shapes, text, sfx and `music` (below).
|
|
62
62
|
- **Repeat with code, never by copying:** `Array.from({ length: 12 }, (_, i) => ({ type: 'shape', shape: 'circle', radius: 20, at: i * 0.15, duration: DURATION - i * 0.15, initial: { x: 120 + i * 90, y: 360, fillColor: '#ffd166' }, keyframes: [{ at: 0, from: { scale: 0 }, to: { scale: 1 }, duration: 0.4, ease: 'back.out(2)' }] }))` returns twelve layers: spread them into `sequences` with `...`.
|
|
63
63
|
- **Helpers already imported** in the template: `kenBurns` (slow zoom for an image layer), `withFade`, `wiggle` (seeded shake as keyframes), `stagger`, `animateText` (per letter / word entrances), `followPath`, `particles` (seeded confetti / snow / sparks as layers), `deck` (slides). Each returns keyframes or layers: `keyframes: wiggle(...)`, `...particles(...)`. The full signatures are in `https://raw.githubusercontent.com/yjmtmtk/pixi-effects/main/skills/pixi-effects/reference/cheatsheet.md` (22 KB; read it only if you need a helper).
|
|
64
64
|
- **Advanced:** `const INIT = { assets: [...], composition: { transitions: [...] } }` in the edit block adds `movie.init` options (the page merges it); most videos need nothing here.
|
package/ai/chat-template.html
CHANGED
|
@@ -39,9 +39,15 @@
|
|
|
39
39
|
document.getElementById('problems-text').textContent = '\n' + window.__logs.join('\n');
|
|
40
40
|
};
|
|
41
41
|
const add = (line) => { window.__logs.push(line); show(); };
|
|
42
|
+
// A console group's title leads the warnings inside it (PixiJS prints a deprecation as a group titled with its message, the stack inside).
|
|
43
|
+
let group = '';
|
|
44
|
+
const text = (a) => { if (typeof a[0] === 'string' && a[0].includes('%')) { let i = 1; a = [a[0].replace(/%([csdifoO])/g, (_, f) => f === 'c' ? (i++, '') : String(a[i++])), ...a.slice(i)]; } return a.map(x => (x && x.message) || String(x)).join(' '); };
|
|
45
|
+
const gc = console.groupCollapsed.bind(console), ge = console.groupEnd.bind(console);
|
|
46
|
+
console.groupCollapsed = (...a) => { group = text(a); gc(...a); };
|
|
47
|
+
console.groupEnd = () => { group = ''; ge(); };
|
|
42
48
|
for (const k of ['warn', 'error']) {
|
|
43
49
|
const orig = console[k].bind(console);
|
|
44
|
-
console[k] = (...a) => { add(k + ': ' +
|
|
50
|
+
console[k] = (...a) => { add(k + ': ' + (group ? group + ' — ' : '') + text(a)); orig(...a); };
|
|
45
51
|
}
|
|
46
52
|
window.addEventListener('error', e => add('uncaught: ' + e.message));
|
|
47
53
|
window.addEventListener('unhandledrejection', e => add('unhandled: ' + (e.reason && e.reason.message || e.reason)));
|
|
@@ -59,10 +65,10 @@
|
|
|
59
65
|
"imports": {
|
|
60
66
|
"pixi.js": "https://cdn.jsdelivr.net/npm/pixi.js@8.23.0/dist/pixi.min.mjs",
|
|
61
67
|
"mediabunny": "https://cdn.jsdelivr.net/npm/mediabunny@1.61.3/+esm",
|
|
62
|
-
"pixi-effects": "https://cdn.jsdelivr.net/npm/pixi-effects@0.
|
|
63
|
-
"pixi-effects/controller": "https://cdn.jsdelivr.net/npm/pixi-effects@0.
|
|
64
|
-
"pixi-effects/present": "https://cdn.jsdelivr.net/npm/pixi-effects@0.
|
|
65
|
-
"pixi-effects/3d": "https://cdn.jsdelivr.net/npm/pixi-effects@0.
|
|
68
|
+
"pixi-effects": "https://cdn.jsdelivr.net/npm/pixi-effects@0.50.1/dist/index.js",
|
|
69
|
+
"pixi-effects/controller": "https://cdn.jsdelivr.net/npm/pixi-effects@0.50.1/dist/Controller.js",
|
|
70
|
+
"pixi-effects/present": "https://cdn.jsdelivr.net/npm/pixi-effects@0.50.1/dist/present.js",
|
|
71
|
+
"pixi-effects/3d": "https://cdn.jsdelivr.net/npm/pixi-effects@0.50.1/dist/3d.js",
|
|
66
72
|
"@pixi/3d": "https://cdn.jsdelivr.net/npm/@pixi/3d@0.1.0/dist/pixijs-3d.min.mjs",
|
|
67
73
|
"@pixi/3d/extras": "https://cdn.jsdelivr.net/npm/@pixi/3d@0.1.0/dist/pixijs-3d-extras.min.mjs"
|
|
68
74
|
}
|
package/ai/tools/check.mjs
CHANGED
|
@@ -520,7 +520,7 @@ export async function runCheck(opts, log = console.log) {
|
|
|
520
520
|
const layoutProblems = rv.problems.filter(g => g.kind !== 'canvas'), canvasProblems = rv.problems.filter(g => g.kind === 'canvas');
|
|
521
521
|
report.inspect = { checkedFrames: rv.frames, issues: layoutProblems, review: rv.review, canvas: canvasProblems.map(g => g.message), canvasLayers: rv.canvas ?? [] };
|
|
522
522
|
if (layoutProblems.length) report.problems.push(`${layoutProblems.length} kind(s) of layout issue from movie.inspect`);
|
|
523
|
-
if (canvasProblems.length) report.problems.push(`${canvasProblems.length} layer(s) (canvas / three / scene3d) that do not draw the same picture for the same time (movie.canvasProblems)`);
|
|
523
|
+
if (canvasProblems.length) report.problems.push(`${canvasProblems.length} layer(s) (canvas / three / scene3d / scene2d) that do not draw the same picture for the same time (movie.canvasProblems)`);
|
|
524
524
|
// fonts: a web font whose file did not load is a problem (the library lists a layer with no available font for review)
|
|
525
525
|
report.fonts = rv.fonts;
|
|
526
526
|
if (rv.fonts.failed.length) report.problems.push(`${rv.fonts.failed.length} web font(s) failed to load: ${rv.fonts.failed.join(', ')} (the layers that use them are drawn in a fallback)`);
|
|
@@ -553,7 +553,7 @@ export async function runCheck(opts, log = console.log) {
|
|
|
553
553
|
if (rows.some(([, px]) => px > 0)) w.depthBlur = Object.fromEntries(rows);
|
|
554
554
|
// pick: what is under each --pick point at this moment (the frame is on screen after the snapshot above)
|
|
555
555
|
if (opts.pick.length) {
|
|
556
|
-
w.pick = await cdp.eval(`(${JSON.stringify(opts.pick)}).map(p => ({ x: p.x, y: p.y, hits: movie.pickAll(p.x, p.y).map(h => ({ name: h.name ?? h.path, path: h.path, kind: h.kind, object: h.three ? h.three.object : h.scene3d ? h.scene3d.object : undefined })) }))`).catch(() => []);
|
|
556
|
+
w.pick = await cdp.eval(`(${JSON.stringify(opts.pick)}).map(p => ({ x: p.x, y: p.y, hits: movie.pickAll(p.x, p.y).map(h => ({ name: h.name ?? h.path, path: h.path, kind: h.kind, object: h.three ? h.three.object : h.scene3d ? h.scene3d.object : h.scene2d ? h.scene2d.object : undefined })) }))`).catch(() => []);
|
|
557
557
|
}
|
|
558
558
|
// light: how lit each threeD layer is at this moment (left out when the composition has no light)
|
|
559
559
|
const lit = await cdp.eval(`movie.inspect(${w.frame}).then(r => r.layers.filter(l => l.light !== undefined).map(l => [l.path, l.light]))`).catch(() => []);
|
|
@@ -895,7 +895,7 @@ export async function runSteps(cdp, steps, outDir, size, consoleLines, seenLogs)
|
|
|
895
895
|
await sleep(300); // the page's handlers and rebuilds settle
|
|
896
896
|
const after = await cdp.eval('JSON.parse(JSON.stringify(movie.vars || {}))').catch(() => ({}));
|
|
897
897
|
res.vars = Object.fromEntries(Object.keys({ ...before, ...after }).filter(k => JSON.stringify(before[k]) !== JSON.stringify(after[k])).map(k => [k, [before[k], after[k]]]));
|
|
898
|
-
if (last) res.hits = await cdp.eval(`movie.pickAll(${last.x}, ${last.y}).map(h => h.kind === 'three' ? h.path + ' (three: ' + (h.three && h.three.object || '?') + ')' : h.kind === 'scene3d' ? h.path + ' (scene3d: ' + (h.scene3d && h.scene3d.object || '?') + ')' : h.path)`).catch(() => []);
|
|
898
|
+
if (last) res.hits = await cdp.eval(`movie.pickAll(${last.x}, ${last.y}).map(h => h.kind === 'three' ? h.path + ' (three: ' + (h.three && h.three.object || '?') + ')' : h.kind === 'scene3d' ? h.path + ' (scene3d: ' + (h.scene3d && h.scene3d.object || '?') + ')' : h.kind === 'scene2d' ? h.path + ' (scene2d: ' + (h.scene2d && h.scene2d.object || '?') + ')' : h.path)`).catch(() => []);
|
|
899
899
|
res.frame = await cdp.eval('movie.currentFrame').catch(() => null);
|
|
900
900
|
res.playing = await cdp.eval('!!movie.isPlaying').catch(() => null);
|
|
901
901
|
const now = await pageLogs();
|
|
@@ -930,8 +930,8 @@ function finish(report, outDir, log) {
|
|
|
930
930
|
if (g.length > 8) L.push(` … ${g.length - 8} more (report.json)`);
|
|
931
931
|
const cv = report.inspect.canvas ?? [];
|
|
932
932
|
const rows = report.inspect.canvasLayers ?? [];
|
|
933
|
-
if (cv.length) { L.push(` canvas ${cv.length} layer(s) (canvas / three / scene3d) that do not draw the same picture for the same time:`); for (const m of cv.slice(0, 4)) L.push(` - ${m}`); }
|
|
934
|
-
for (const kind of ['canvas', 'three', 'scene3d']) { // silence must not be the only sign that the check ran
|
|
933
|
+
if (cv.length) { L.push(` canvas ${cv.length} layer(s) (canvas / three / scene3d / scene2d) that do not draw the same picture for the same time:`); for (const m of cv.slice(0, 4)) L.push(` - ${m}`); }
|
|
934
|
+
for (const kind of ['canvas', 'three', 'scene3d', 'scene2d']) { // silence must not be the only sign that the check ran
|
|
935
935
|
const mine = rows.filter(r => (r.kind ?? 'canvas') === kind);
|
|
936
936
|
if (!mine.length) continue;
|
|
937
937
|
const good = mine.filter(r => r.ok), slow = [...mine].sort((a, b) => b.drawMs - a.drawMs)[0];
|
|
@@ -952,7 +952,7 @@ function finish(report, outDir, log) {
|
|
|
952
952
|
}
|
|
953
953
|
for (const w of (report.at ?? []).filter(x => x.pick)) {
|
|
954
954
|
for (const p of w.pick) {
|
|
955
|
-
const says = p.hits.length ? p.hits.map(h => h.kind === 'three' || h.kind === 'scene3d' ? `${h.name} (${h.kind}: ${h.object || '?'})` : h.name).join(', ') : 'nothing';
|
|
955
|
+
const says = p.hits.length ? p.hits.map(h => h.kind === 'three' || h.kind === 'scene3d' || h.kind === 'scene2d' ? `${h.name} (${h.kind}: ${h.object || '?'})` : h.name).join(', ') : 'nothing';
|
|
956
956
|
L.push(` pick ${w.label} (${p.x}, ${p.y}) — ${says}`);
|
|
957
957
|
}
|
|
958
958
|
}
|
package/dist/3d.cjs
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
4
|
-
|
|
5
|
-
var
|
|
3
|
+
var chunkNXMNBFHM_cjs = require('./chunk-NXMNBFHM.cjs');
|
|
4
|
+
require('./chunk-VQXZ2NOI.cjs');
|
|
5
|
+
var chunkGXGIISFS_cjs = require('./chunk-GXGIISFS.cjs');
|
|
6
|
+
var chunk3FCDRLW3_cjs = require('./chunk-3FCDRLW3.cjs');
|
|
6
7
|
var chunkDOLTCXCL_cjs = require('./chunk-DOLTCXCL.cjs');
|
|
7
8
|
var _3d = require('@pixi/3d');
|
|
8
9
|
var pixi_js = require('pixi.js');
|
|
@@ -247,7 +248,7 @@ async function layerTexture(ctx, name, options = {}) {
|
|
|
247
248
|
var OWN_KEYS = ["width", "height", "view", "resolution", "setup", "update", "dispose", "followCamera", "followLights", "followFog", "reuse"];
|
|
248
249
|
var THREE_ONLY = ["renderer", "shareGpu", "antialias"];
|
|
249
250
|
var LAYER_OWNED = ["width", "height", "autoResize"];
|
|
250
|
-
var Scene3DSequence = class extends
|
|
251
|
+
var Scene3DSequence = class extends chunkNXMNBFHM_cjs.Sequence {
|
|
251
252
|
_view = null;
|
|
252
253
|
_ctx = null;
|
|
253
254
|
_objects = {};
|
|
@@ -271,6 +272,8 @@ var Scene3DSequence = class extends chunk33USHRV5_cjs.Sequence {
|
|
|
271
272
|
_borrowed = null;
|
|
272
273
|
/** True once another layer took this layer's scene: destroying this one must not let it go. */
|
|
273
274
|
_donated = false;
|
|
275
|
+
/** What setup left on the objects the keyframes reach, shared with a layer that takes the scene over (core/setupValues.ts). */
|
|
276
|
+
_setupValues = new chunkNXMNBFHM_cjs.SetupValues();
|
|
274
277
|
_pendingRebinds = [];
|
|
275
278
|
_lightMirror = null;
|
|
276
279
|
_fogMirror = null;
|
|
@@ -301,14 +304,14 @@ var Scene3DSequence = class extends chunk33USHRV5_cjs.Sequence {
|
|
|
301
304
|
if (this.duration === void 0) this.duration = this.parent?.duration ?? this.root.duration;
|
|
302
305
|
this._checkKeys();
|
|
303
306
|
this._checkTint();
|
|
304
|
-
if (typeof spec.update === "function" &&
|
|
307
|
+
if (typeof spec.update === "function" && chunkNXMNBFHM_cjs.NOT_PURE.test(spec.update.toString())) {
|
|
305
308
|
this._say("pure", "update calls Math.random, Date.now, performance.now or new Date, so it is not deterministic: the same frame would draw differently in playback, in a seek and in an export. Derive the value from t");
|
|
306
309
|
}
|
|
307
310
|
const renderer = this.root.pixiRenderer;
|
|
308
311
|
if (renderer && !renderer.renderPipes.view3d) {
|
|
309
312
|
throw new Error(`${this._who()}: PixiJS 3D was loaded after the renderer started; import 'pixi-effects/3d' (and call register3D()) before movie.init`);
|
|
310
313
|
}
|
|
311
|
-
const scope =
|
|
314
|
+
const scope = chunkNXMNBFHM_cjs.buildScope(this, this.parent, this.root);
|
|
312
315
|
const width = resolveDim(spec.width, scope) ?? this.parent?.width ?? this.root.width;
|
|
313
316
|
const height = resolveDim(spec.height, scope) ?? this.parent?.height ?? this.root.height;
|
|
314
317
|
const viewOptions = { ...spec.view ?? {} };
|
|
@@ -324,7 +327,7 @@ var Scene3DSequence = class extends chunk33USHRV5_cjs.Sequence {
|
|
|
324
327
|
this.intrinsicWidth = width;
|
|
325
328
|
this.intrinsicHeight = height;
|
|
326
329
|
this._key = spec.reuse === false || !spec.name ? null : reuseKeyOf(spec, width, height);
|
|
327
|
-
const donor = this._key !== null ? this.root.reuse?.claim(this._key) : null;
|
|
330
|
+
const donor = this._key !== null ? this.root.reuse?.claim(this._key, this) : null;
|
|
328
331
|
if (donor && donor._lendable()) {
|
|
329
332
|
this._borrow(donor, view, renderer ?? null, width, height);
|
|
330
333
|
if (spec.followCamera) this._checkFollowShape(width, height);
|
|
@@ -367,6 +370,7 @@ var Scene3DSequence = class extends chunk33USHRV5_cjs.Sequence {
|
|
|
367
370
|
const objects = { ...d._objects, ...d._objects.view === d._view ? { view } : {} };
|
|
368
371
|
this._objects = objects;
|
|
369
372
|
this._players = d._players;
|
|
373
|
+
this._setupValues = d._setupValues;
|
|
370
374
|
const ctx = { view, root: view.root, camera: d._view.camera, renderer, width, height, objects };
|
|
371
375
|
const host = this._makeHost(renderer);
|
|
372
376
|
Object.defineProperty(ctx, HOST, { value: host, enumerable: false });
|
|
@@ -378,6 +382,7 @@ var Scene3DSequence = class extends chunk33USHRV5_cjs.Sequence {
|
|
|
378
382
|
const d = this._borrowed, view = this._view, ctx = this._ctx;
|
|
379
383
|
if (!d || !view || !ctx) return;
|
|
380
384
|
const from = d._view;
|
|
385
|
+
this._setupValues.restore();
|
|
381
386
|
const own = view.camera;
|
|
382
387
|
for (const child of [...from.root.children]) view.root.addChild(child);
|
|
383
388
|
view.camera = ctx.camera;
|
|
@@ -415,7 +420,7 @@ var Scene3DSequence = class extends chunk33USHRV5_cjs.Sequence {
|
|
|
415
420
|
}
|
|
416
421
|
/** Unknown keys (with the likely one), and the keys only a three layer has. */
|
|
417
422
|
_checkKeys() {
|
|
418
|
-
const valid = [...
|
|
423
|
+
const valid = [...chunk3FCDRLW3_cjs.COMMON, ...OWN_KEYS];
|
|
419
424
|
for (const key of Object.keys(this.spec)) {
|
|
420
425
|
if (valid.includes(key)) continue;
|
|
421
426
|
if (THREE_ONLY.includes(key)) {
|
|
@@ -496,8 +501,8 @@ var Scene3DSequence = class extends chunk33USHRV5_cjs.Sequence {
|
|
|
496
501
|
const current = view.filters ?? [];
|
|
497
502
|
const others = current.filter((f) => f !== this._look && f !== this._blend);
|
|
498
503
|
const authored = String(this.spec.blendMode ?? "normal");
|
|
499
|
-
if (others.length === 0 &&
|
|
500
|
-
this._blend =
|
|
504
|
+
if (others.length === 0 && chunkGXGIISFS_cjs.isAdvancedBlend(authored) && !this._blend) {
|
|
505
|
+
this._blend = chunkGXGIISFS_cjs.blendFilterFor(authored);
|
|
501
506
|
if (this._blend) view.blendMode = "normal";
|
|
502
507
|
}
|
|
503
508
|
const mode = String(view.blendMode ?? "normal");
|
|
@@ -782,7 +787,7 @@ var Scene3DSequence = class extends chunk33USHRV5_cjs.Sequence {
|
|
|
782
787
|
this._warnPath(path, `no property "${prop}"`);
|
|
783
788
|
return null;
|
|
784
789
|
}
|
|
785
|
-
return { target: obj, prop };
|
|
790
|
+
return this._borrowed ? this._setupValues.view(obj, prop, () => this._borrowed !== null) : (this._setupValues.note(obj, prop), { target: obj, prop });
|
|
786
791
|
}
|
|
787
792
|
_warnPath(path, why) {
|
|
788
793
|
this._say(`path:${path}`, `keyframe path scene3d.${path}: ${why}; skipped`);
|
|
@@ -861,7 +866,7 @@ function reuseKeyOf(spec, width, height) {
|
|
|
861
866
|
function resolveDim(v, scope) {
|
|
862
867
|
if (v === void 0) return void 0;
|
|
863
868
|
if (typeof v === "number") return v;
|
|
864
|
-
return
|
|
869
|
+
return chunkNXMNBFHM_cjs.evaluateExpr(v, scope);
|
|
865
870
|
}
|
|
866
871
|
var label2 = "pixi-effects: loadModel";
|
|
867
872
|
async function loadModel(url, options = {}) {
|
|
@@ -947,7 +952,7 @@ function register3D() {
|
|
|
947
952
|
}
|
|
948
953
|
_3d.Model3D.defaultOptions.autoUpdate = false;
|
|
949
954
|
_3d.AnimationPlayer.defaultOptions.autoUpdate = false;
|
|
950
|
-
|
|
955
|
+
chunkNXMNBFHM_cjs.registerSequenceType("scene3d", Scene3DSequence);
|
|
951
956
|
}
|
|
952
957
|
function scene3d(spec) {
|
|
953
958
|
return spec;
|