pixelkiln 0.87.0 → 0.89.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.
@@ -47,7 +47,8 @@
47
47
  "objectPro",
48
48
  "uiAsset",
49
49
  "uiElement",
50
- "imageProFlash"
50
+ "imageProFlash",
51
+ "vfx"
51
52
  ],
52
53
  "default": "map"
53
54
  },
@@ -233,6 +234,28 @@
233
234
  "minimum": 0,
234
235
  "maximum": 1
235
236
  },
237
+ "terrainRoundness": {
238
+ "type": "number",
239
+ "minimum": 0,
240
+ "maximum": 2
241
+ },
242
+ "terrainBoundaryAmplitude": {
243
+ "type": "number",
244
+ "minimum": 0,
245
+ "maximum": 0.3
246
+ },
247
+ "terrainBoundarySeed": {
248
+ "type": "integer",
249
+ "minimum": 0
250
+ },
251
+ "terrainStepSlope": {
252
+ "type": "number",
253
+ "minimum": 0,
254
+ "maximum": 2
255
+ },
256
+ "terrainConnectDiagonals": {
257
+ "type": "boolean"
258
+ },
236
259
  "terrainTransitionSize": {
237
260
  "type": "number",
238
261
  "minimum": 0,
@@ -245,6 +268,13 @@
245
268
  "high top-down"
246
269
  ]
247
270
  },
271
+ "terrainOrientation": {
272
+ "type": "string",
273
+ "enum": [
274
+ "top-down",
275
+ "sidescroller"
276
+ ]
277
+ },
248
278
  "isometricTileSize": {
249
279
  "type": "number",
250
280
  "enum": [
@@ -382,6 +412,16 @@
382
412
  },
383
413
  "default": []
384
414
  },
415
+ "paletteName": {
416
+ "type": "string",
417
+ "minLength": 1,
418
+ "maxLength": 100
419
+ },
420
+ "maxColors": {
421
+ "type": "integer",
422
+ "minimum": 2,
423
+ "maximum": 64
424
+ },
385
425
  "enforcePalette": {
386
426
  "type": "boolean",
387
427
  "default": false
@@ -505,7 +545,8 @@
505
545
  "objectPro",
506
546
  "uiAsset",
507
547
  "uiElement",
508
- "imageProFlash"
548
+ "imageProFlash",
549
+ "vfx"
509
550
  ],
510
551
  "default": "map"
511
552
  },
@@ -691,6 +732,28 @@
691
732
  "minimum": 0,
692
733
  "maximum": 1
693
734
  },
735
+ "terrainRoundness": {
736
+ "type": "number",
737
+ "minimum": 0,
738
+ "maximum": 2
739
+ },
740
+ "terrainBoundaryAmplitude": {
741
+ "type": "number",
742
+ "minimum": 0,
743
+ "maximum": 0.3
744
+ },
745
+ "terrainBoundarySeed": {
746
+ "type": "integer",
747
+ "minimum": 0
748
+ },
749
+ "terrainStepSlope": {
750
+ "type": "number",
751
+ "minimum": 0,
752
+ "maximum": 2
753
+ },
754
+ "terrainConnectDiagonals": {
755
+ "type": "boolean"
756
+ },
694
757
  "terrainTransitionSize": {
695
758
  "type": "number",
696
759
  "minimum": 0,
@@ -703,6 +766,13 @@
703
766
  "high top-down"
704
767
  ]
705
768
  },
769
+ "terrainOrientation": {
770
+ "type": "string",
771
+ "enum": [
772
+ "top-down",
773
+ "sidescroller"
774
+ ]
775
+ },
706
776
  "isometricTileSize": {
707
777
  "type": "number",
708
778
  "enum": [
@@ -840,6 +910,16 @@
840
910
  },
841
911
  "default": []
842
912
  },
913
+ "paletteName": {
914
+ "type": "string",
915
+ "minLength": 1,
916
+ "maxLength": 100
917
+ },
918
+ "maxColors": {
919
+ "type": "integer",
920
+ "minimum": 2,
921
+ "maximum": 64
922
+ },
843
923
  "enforcePalette": {
844
924
  "type": "boolean",
845
925
  "default": false
@@ -1015,7 +1095,8 @@
1015
1095
  "animate-pixminimax",
1016
1096
  "animate-skeleton",
1017
1097
  "interpolate",
1018
- "edit-animation"
1098
+ "edit-animation",
1099
+ "normal-map"
1019
1100
  ]
1020
1101
  },
1021
1102
  "from": {
@@ -1117,6 +1198,13 @@
1117
1198
  "complex"
1118
1199
  ]
1119
1200
  },
1201
+ "convention": {
1202
+ "type": "string",
1203
+ "enum": [
1204
+ "opengl",
1205
+ "directx"
1206
+ ]
1207
+ },
1120
1208
  "description": {
1121
1209
  "type": "string",
1122
1210
  "minLength": 1
@@ -1544,6 +1632,109 @@
1544
1632
  ],
1545
1633
  "additionalProperties": false
1546
1634
  },
1635
+ "vfx": {
1636
+ "type": "object",
1637
+ "properties": {
1638
+ "preset": {
1639
+ "type": "string",
1640
+ "minLength": 1
1641
+ },
1642
+ "recipe": {
1643
+ "type": "string",
1644
+ "minLength": 1
1645
+ },
1646
+ "parts": {
1647
+ "type": "array",
1648
+ "items": {
1649
+ "type": "object",
1650
+ "properties": {
1651
+ "name": {
1652
+ "type": "string",
1653
+ "minLength": 1
1654
+ }
1655
+ },
1656
+ "required": [
1657
+ "name"
1658
+ ],
1659
+ "additionalProperties": {}
1660
+ }
1661
+ },
1662
+ "sprite": {
1663
+ "type": "string",
1664
+ "minLength": 1
1665
+ },
1666
+ "fps": {
1667
+ "type": "integer",
1668
+ "minimum": 1,
1669
+ "maximum": 60
1670
+ },
1671
+ "name": {
1672
+ "type": "string",
1673
+ "minLength": 1
1674
+ },
1675
+ "description": {
1676
+ "type": "string",
1677
+ "minLength": 1,
1678
+ "maxLength": 8000
1679
+ },
1680
+ "artist": {
1681
+ "type": "string",
1682
+ "enum": [
1683
+ "lite",
1684
+ "pro"
1685
+ ]
1686
+ }
1687
+ },
1688
+ "additionalProperties": false
1689
+ },
1690
+ "connect": {
1691
+ "type": "object",
1692
+ "properties": {
1693
+ "lower": {
1694
+ "type": "object",
1695
+ "properties": {
1696
+ "of": {
1697
+ "type": "string",
1698
+ "minLength": 1
1699
+ },
1700
+ "terrain": {
1701
+ "type": "string",
1702
+ "enum": [
1703
+ "lower",
1704
+ "upper"
1705
+ ]
1706
+ }
1707
+ },
1708
+ "required": [
1709
+ "of",
1710
+ "terrain"
1711
+ ],
1712
+ "additionalProperties": false
1713
+ },
1714
+ "upper": {
1715
+ "type": "object",
1716
+ "properties": {
1717
+ "of": {
1718
+ "type": "string",
1719
+ "minLength": 1
1720
+ },
1721
+ "terrain": {
1722
+ "type": "string",
1723
+ "enum": [
1724
+ "lower",
1725
+ "upper"
1726
+ ]
1727
+ }
1728
+ },
1729
+ "required": [
1730
+ "of",
1731
+ "terrain"
1732
+ ],
1733
+ "additionalProperties": false
1734
+ }
1735
+ },
1736
+ "additionalProperties": false
1737
+ },
1547
1738
  "proportions": {
1548
1739
  "anyOf": [
1549
1740
  {
@@ -122,7 +122,8 @@
122
122
  "objectPro",
123
123
  "uiAsset",
124
124
  "uiElement",
125
- "imageProFlash"
125
+ "imageProFlash",
126
+ "vfx"
126
127
  ],
127
128
  "default": "map"
128
129
  },
@@ -308,6 +309,28 @@
308
309
  "minimum": 0,
309
310
  "maximum": 1
310
311
  },
312
+ "terrainRoundness": {
313
+ "type": "number",
314
+ "minimum": 0,
315
+ "maximum": 2
316
+ },
317
+ "terrainBoundaryAmplitude": {
318
+ "type": "number",
319
+ "minimum": 0,
320
+ "maximum": 0.3
321
+ },
322
+ "terrainBoundarySeed": {
323
+ "type": "integer",
324
+ "minimum": 0
325
+ },
326
+ "terrainStepSlope": {
327
+ "type": "number",
328
+ "minimum": 0,
329
+ "maximum": 2
330
+ },
331
+ "terrainConnectDiagonals": {
332
+ "type": "boolean"
333
+ },
311
334
  "terrainTransitionSize": {
312
335
  "type": "number",
313
336
  "minimum": 0,
@@ -320,6 +343,13 @@
320
343
  "high top-down"
321
344
  ]
322
345
  },
346
+ "terrainOrientation": {
347
+ "type": "string",
348
+ "enum": [
349
+ "top-down",
350
+ "sidescroller"
351
+ ]
352
+ },
323
353
  "isometricTileSize": {
324
354
  "type": "number",
325
355
  "enum": [
@@ -457,6 +487,16 @@
457
487
  },
458
488
  "default": []
459
489
  },
490
+ "paletteName": {
491
+ "type": "string",
492
+ "minLength": 1,
493
+ "maxLength": 100
494
+ },
495
+ "maxColors": {
496
+ "type": "integer",
497
+ "minimum": 2,
498
+ "maximum": 64
499
+ },
460
500
  "enforcePalette": {
461
501
  "type": "boolean",
462
502
  "default": false
@@ -59,7 +59,12 @@ hashes.
59
59
  takes a reference, and the unzoomed result is opaque. For outside art that
60
60
  was never pixel art (a photo, painting, or render), `pixelkiln pixelate
61
61
  --from <file> --out <file>` converts it with PixelLab's Image to Pixel Art
62
- Pro Flash for 6 generations and asks first.
62
+ Pro Flash for 6 generations and asks first. The result is opaque on
63
+ near-white, so remove its background before using it as a cut-out.
64
+ - For a spell, hit, explosion, aura, or other effect, use `pixelkiln vfx`
65
+ (PixelLab's VFX workbench, free): start from a `--preset`, add `--part`s,
66
+ build around a `--sprite`, and keep the `.vfx.json` it writes, since its
67
+ recipe re-renders the same effect with `--recipe`.
63
68
  - Treat every ComfyUI output as source material until it passes the native-grid,
64
69
  final-palette, prompt-coverage, and human 1× checks in the ComfyUI reference.
65
70
  A successful PNG or high-confidence grid result is not quality approval.
@@ -113,8 +118,8 @@ composition review and, for an isolated asset, background removal.
113
118
  Read only the reference needed for the current decision:
114
119
 
115
120
  - For PixelLab configuration, generators (including `uiElement` for single UI
116
- pieces and `imageProFlash` for styled stills), costs, alpha behavior,
117
- account operations, or the `unzoom`, `pixelate`, `font`, `estimate-skeleton`, and
121
+ pieces, `imageProFlash` for styled stills, and `vfx` for animated effects), costs, alpha behavior,
122
+ account operations, or the `unzoom`, `pixelate`, `normal-map`, `vfx`, `font`, `estimate-skeleton`, and
118
123
  `skeleton-preview` utilities, read [references/pixellab.md](references/pixellab.md). For a
119
124
  PixelLab style aimed at a specific resolution or fidelity tier (retro,
120
125
  high-detail, or matching an existing set's look), read
@@ -1,17 +1,26 @@
1
1
  # PixelLab coverage and remaining gaps
2
2
 
3
3
  A catalog of PixelLab capabilities checked against PixelKiln: what this
4
- adapter now covers, and what is still absent. It was built by reading all 29
4
+ adapter now covers, and what is still absent. It was built by reading all 31
5
5
  tutorials on PixelLab's official YouTube channel (the original
6
6
  26 — the 12 featured on pixellab.ai plus 14 more from the channel's "PixelLab
7
- Tutorial" playlist, filtered to ~12 months back from that pass — plus 3 more
7
+ Tutorial" playlist, filtered to ~12 months back from that pass — plus 5 more
8
8
  published since: "Level Up Your Game: Custom Sprite Animation Tutorial,"
9
9
  "Pixel Art Animation Tutorial: Images Pro Flash, Skeleton V3 & PixMiniMax,"
10
- and "How to Reduce Colors Like a Pro!") against this adapter's actual source
11
- — and, for the newest pass, against PixelLab's own MCP tool schemas
12
- (`create_image_pro_flash`, `edit_image_pro_flash`, `inpaint_image_pro_flash`,
13
- `get_pro_flash_capabilities`) where a tutorial's framing needed checking
14
- against the live surface, the same standard the original pass held itself to.
10
+ "How to Reduce Colors Like a Pro!", "How to Make Animated Pixel Art VFX in
11
+ PixelLab" (https://www.youtube.com/watch?v=t8FIMv-8QpI), and "PixelLab Pro
12
+ Tilesets: Full Guide" (https://www.youtube.com/watch?v=MbkqpDUFkEg)) against
13
+ this adapter's actual source — and, for the newer passes, against PixelLab's
14
+ own MCP tool schemas (`create_image_pro_flash`, `edit_image_pro_flash`,
15
+ `inpaint_image_pro_flash`, `get_pro_flash_capabilities`, and for the last two
16
+ `create_topdown_tileset`, `create_sidescroller_tileset`, `create_tiles_pro`,
17
+ `create_map`, `animate_image_pixminimax`, `create_image_pro`, `vfx_workbench`,
18
+ and `search_knowledge`) plus the REST OpenAPI document's `/create-tileset`
19
+ and `/create-tileset-sidescroller` request schemas, where a tutorial's
20
+ framing needed checking against the live surface, the same standard the
21
+ original pass held itself to. The PixelLab 0.4.130 release notes (October 2026: Tileset
22
+ Pro, a target palette for Create Image Pro, VFX in the API, normal maps)
23
+ were checked the same way against the REST OpenAPI document.
15
24
  Read this when scoping new PixelLab work, so effort goes toward a
16
25
  confirmed gap with real demand rather than a guess. Nothing here is a
17
26
  commitment to build it — it is what is missing, with the evidence for why it
@@ -55,10 +64,26 @@ and which tutorial(s) demonstrated real (not hypothetical) demand for it.
55
64
  — a real gap, not a docs fix: `tiles`'s own `tileFeature: "tileset"` draws
56
65
  one terrain's edges, not two named, connected terrain levels with their own
57
66
  transition prompt. Closed by the `terrain` generator; see
58
- `pixellab.md`. Cost is unmeasured (borrows the same 10/15/25 canvas tiers
59
- already confirmed for `tiles` and `1dir`); `/create-tileset-sidescroller`,
60
- reference images, `color_image`, and the `pro` pipeline's own tunables
61
- beyond `spreadX`/`slopeSize`/`raggedness` remain unmodeled.
67
+ `pixellab.md`. Reference images and `color_image` remain unmodeled.
68
+ - **Tileset Pro shape controls, connected sets, and sidescrollers**
69
+ (PixelLab 0.4.130, October 2026). `terrain` styles take
70
+ `terrainRoundness`, `terrainBoundaryAmplitude`/`terrainBoundarySeed`,
71
+ `terrainStepSlope`, and `terrainConnectDiagonals`, each refused outside
72
+ the mode that reads it. `terrainSpreadX`/`terrainSlopeSize` are
73
+ deprecated, since PixelLab now documents both as "No effect". A Pro set at
74
+ `terrainTransitionSize` 0.5 counts as 25 tiles. An asset's `connect` shares
75
+ a terrain with another set in the same style: pixelkiln records each set's
76
+ `metadata.terrain_ids`, sends the other set's id as `lower_base_tile_id` or
77
+ `upper_base_tile_id`, blocks until that set is downloaded, and marks the
78
+ connected set stale when the other is regenerated.
79
+ `terrainOrientation: "sidescroller"` calls `/create-tileset-sidescroller`
80
+ (platform body plus top layer). Its response is the top-down shape with
81
+ `terrain_types` `["central","background"]` but `lower`/`upper` corners,
82
+ lower being the platform. **Measured once**: a 16px set at transition 0.25
83
+ billed exactly 3 generations. Estimates now follow PixelLab's quotes: Pro
84
+ 15 up to 32px and 25 at 64px, standard 4 (the top of its quoted 1 to 4),
85
+ sidescroller 3. What is still open is in
86
+ [Pro tilesets](#pro-tilesets-what-is-left-after-04130) below.
62
87
  - **Pro-tier full-bleed background generation** (`generate-image-v2`, PixelLab's
63
88
  Pro image tier) at arbitrary custom aspect ratios (not just square) —
64
89
  already measured at 40 generations in `docs/ENDPOINTS.md`, but `pixflux`
@@ -302,9 +327,49 @@ and which tutorial(s) demonstrated real (not hypothetical) demand for it.
302
327
  PixelLab 0.4.128, October 2026) — converts a photo, painting, or render
303
328
  into pixel art, choosing the output size itself. Closed by `pixelkiln
304
329
  pixelate`, a standalone command on a loose file like `unzoom`, since its
305
- input comes from outside the manifest. Billed a flat 6 generations live,
306
- and unlike `image-to-pixelart` it keeps transparency
307
- (docs/ENDPOINTS.md, "Image to Pixel Art Pro Flash, measured").
330
+ input comes from outside the manifest. Billed a flat 6 generations live;
331
+ the result is opaque on a near-white background (docs/ENDPOINTS.md,
332
+ "Image to Pixel Art Pro Flash, measured").
333
+ - **Create VFX** (PixelLab 0.4.128, October 2026) — animated pixel-art
334
+ effects (spells, hits, explosions, auras, weather). Offered only as the
335
+ `vfx_workbench` MCP tool, with no REST endpoint as of October 2026, and free on a
336
+ subscription because it renders a recipe rather than generating. Closed by
337
+ `pixelkiln vfx`, which calls PixelLab's MCP server directly with the same
338
+ API key. It starts from a preset, a saved effect, or a recipe file, adds
339
+ parts, downloads the sheet, GIF, atlas, and optional game pack, and saves
340
+ the recipe so the effect re-renders byte for byte (docs/ENDPOINTS.md, "VFX
341
+ workbench (MCP only), measured"). Effects are also a manifest generator,
342
+ `vfx`, planned, locked, and packed like every other asset (see
343
+ docs/GENERATORS.md). Still open there: a sprite named by asset rather than
344
+ by file, the game pack's per-piece clips, and the effect's anchor in the
345
+ sheet formats. PixelLab 0.4.130 then put a second effects path in the
346
+ REST API: `POST /vfx`, the website's VFX *artist*, which builds an effect
347
+ from a plain-language description and saves it to My effects. It is paid:
348
+ 1 generation for a lite effect with no sprite or one up to 128px, up to 28
349
+ for a pro effect around a 512px sprite, charged on delivery and never more
350
+ than twice the quote. Closed as a `vfx` block's `description` (with
351
+ `artist: "lite" | "pro"`) and `pixelkiln vfx --description`. Plans count
352
+ twice the quote. **Measured once**: a lite effect with no sprite billed
353
+ exactly its 1-generation quote, and its sheet (a 3×3 grid with an
354
+ Aseprite-style atlas) cut into 8 correct frames (docs/ENDPOINTS.md). A
355
+ sprite, the pro artist, and changes are unmeasured. Animated sprites (GIF
356
+ or strips) are not sent yet.
357
+ - **Normal maps** (`POST /normal-map`, PixelLab 0.4.130) — a sprite's normal
358
+ map for engine lighting, 8 to 512px, up to 32 frames as one strip so the
359
+ light stays steady, `opengl` or `directx` convention, 0.5 generations.
360
+ Closed by the `revision` asset shape's `normal-map` mode (a loop goes as
361
+ one strip and comes back cut into frames; a character's directions are
362
+ refused, since a strip would shape every direction from the first) and the
363
+ standalone `pixelkiln normal-map` command. Styles with `enforcePalette` or
364
+ `quality` refuse it so nothing palette-snaps a normal map. **Measured
365
+ once**: an 8-frame 1304×26 strip billed exactly 0.5 and came back the same
366
+ size with matching alpha.
367
+ - **Target palette for Create Image Pro** (`target_palette` on
368
+ `/generate-image-v2`, PixelLab 0.4.130) — an `imagePro` style's `palette`
369
+ is now sent as the colors every pixel must use, with `maxColors` (2 to 64
370
+ per image) and `paletteName`. The beta `smart` mapping is left out because
371
+ PixelLab documents it as single-image only and `imagePro` returns a grid of
372
+ candidates below 171px. Cost unchanged and unmeasured with a palette.
308
373
  - **October 2026 Pro price cut** — PixelLab 0.4.128 moved every Pro tool from
309
374
  20/25/40 to 10/15/25 generations. Cost estimates now use the new prices,
310
375
  and `imagePro` (`generate-image-v2`) is tiered instead of a flat 40: a
@@ -363,17 +428,79 @@ and which tutorial(s) demonstrated real (not hypothetical) demand for it.
363
428
  from an existing 8-direction object's sprites), is not worth a second,
364
429
  pricier engine on its own.
365
430
 
366
- ## Create VFX (experimental, no API yet)
431
+ ## Pro tilesets: what is left after 0.4.130
367
432
 
368
- PixelLab 0.4.128 (October 2026) added Create VFX, an experimental web tool
369
- for pixel-art visual effects (`pixellab.ai/create-vfx`). As of that release it
370
- has no endpoint in `/v2/openapi.json` and no MCP tool; PixelLab's release
371
- notes say it "will be added for MCP". Effects are a real gap for game work
372
- (hit sparks, spell bursts, dust puffs), and pixelkiln's closest substitutes
373
- are an `animate` revision or an `objectPro` animation, neither built for it.
374
- Revisit once an endpoint appears: check its request shape, whether the
375
- result is a frame set or a sheet, and its cost, then decide between a
376
- generator (frames into a `pack`able set) and a loose-file command.
433
+ "PixelLab Pro Tilesets: Full Guide" and the 0.4.130 release ("Tileset Pro
434
+ Update... Both top down and sidescroller has been updated! It also supports
435
+ connecting different tilesets") are now mostly covered; see the closed
436
+ `terrain` entries above. Checked against `/create-tileset` and
437
+ `/create-tileset-sidescroller`'s REST schemas, what remains:
438
+
439
+ - **Pro sidescrollers are web-app only.** The video's sidescroller is the
440
+ Pro form at 16, 32, and 64px with top-layer height up to 100%.
441
+ `/create-tileset-sidescroller` has no `mode` field, and its tile size is
442
+ 16 or 32. pixelkiln's sidescroller sets use whatever model that endpoint
443
+ runs.
444
+ - **Older terrain fields are not identity.** `terrainMode`,
445
+ `terrainTransitionSize`, `terrainRaggedness`, `terrainShapeStyle`, and
446
+ `terrainView` never entered `specHash`, so changing one does not mark a set stale. The 0.4.130 fields
447
+ are hashed (when set). Hashing the older ones would make every existing
448
+ terrain lock entry stale at once, so it needs a deliberate migration.
449
+ - **Wall-continuation twins export as duplicates.** The 25-tile layout has
450
+ 21 distinct corner combinations. Four tiles share corners with a twin and
451
+ differ only in `pattern_4x4`, which pixelkiln records but cannot express in
452
+ a four-bit Tiled/Godot corner mask.
453
+ - **Unexercised live:** `lower_base_tile_id`/`upper_base_tile_id`, every
454
+ new shape control, and the top-down prices (Pro 15 or 25, standard planned
455
+ at 4 from PixelLab's quoted 1 to 4). Sidescroller tile counts at transition
456
+ sizes other than 0.25 are assumed to be 16. The one sidescroller call
457
+ returned `metadata.transition_size: 0.0` although 0.25 was sent.
458
+ - **Prompting advice** lives in the skill reference: end each terrain on
459
+ the word "texture", keep prompts short, and lead with color, season, and
460
+ outline words.
461
+
462
+ ## Generated effects with PixMiniMax
463
+
464
+ "How to Make Animated Pixel Art VFX in PixelLab" builds effects with
465
+ generation rather than the VFX workbench (`vfx`). It draws a sheet of
466
+ different effects in one Create Image Pro call, then animates each one with
467
+ PixMiniMax. Most of the steps already exist in pixelkiln. An `imagePro`
468
+ asset at 64×64 returns 16 candidates, and a prompt that lists one effect
469
+ per frame ("an orange fireball facing right, a white and cyan crescent
470
+ slash, ...") fills them. `animate-pixminimax` takes the pick as its parent,
471
+ `lastFrame` pins an ending (a full ice crystal grown from a few blue pixels,
472
+ a splash after a water hammer), and a `"engine": "pro-flash"` revision makes
473
+ that ending from the start frame (the video's plain sword, then a "lightning
474
+ enhanced version"). `driftThreshold` and a `reduce-colors` revision across
475
+ the frame set cover its frame-to-frame color flicker, and `correct-pixelart`
476
+ or `pixelkiln edit` covers its stray pixels. The video's frame counts (12,
477
+ 16, 20, 24) are all multiples of 4, which PixMiniMax requires. What is
478
+ missing:
479
+
480
+ - **Several assets from one candidate sheet.** The video animates eight or
481
+ more effects from two sheets. `pick` gives one `imagePro` asset one
482
+ candidate, so each effect is either its own paid call or a hand-copied
483
+ `source` file. `1dir`'s `batch` is the closest shape, but it fans one call
484
+ out to declared descriptions, not to picks.
485
+ - **Padding the canvas before animating.** The video reframes most effects
486
+ onto a larger canvas (64 to 80px) so a flame or splash has room to grow.
487
+ A revision sends its parent at the parent's own size. The workaround is a
488
+ hand-padded `source` file.
489
+ - **Trimming a loop's repeated frame.** The video deletes the last frame of
490
+ a fireball loop because it repeats the first. `animate_image_pixminimax`
491
+ says `get_image` returns `frame_count + 1` images with index 0 the input
492
+ unchanged. pixelkiln's frame extraction for this mode is unexercised live,
493
+ so whether the input frame lands in the set is unknown. There is no
494
+ manifest way to drop a frame either way.
495
+ - **The cost estimate under-reads long clips.** The MCP tool now prices
496
+ PixMiniMax by generation time: 64×64 at 4, 8, 16, and 40 frames costs 1, 1,
497
+ 2, and 6 generations. pixelkiln's placeholder,
498
+ `ceil(width × height × frames / 65536)`, gives 1, 1, 1, and 3 for the same
499
+ clips. Unlike every other unmeasured estimate here, this one under-reads,
500
+ so `--budget` can be too low.
501
+ - **Joining two clips.** The video joins two orb animations end to end in
502
+ Aseprite. pixelkiln has no frame-set concatenation; `lastFrame` can pin a
503
+ clip's ending to another clip's frame file, but the two sets stay separate.
377
504
 
378
505
  ## Map Workshop (scene composition)
379
506