pixelkiln 0.46.0 → 0.47.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/README.md +5 -5
- package/dist/cli.js +14 -1
- package/dist/cli.js.map +1 -1
- package/dist/index.cjs +14 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +14 -1
- package/dist/index.js.map +1 -1
- package/docs/AGENTS.md +1 -1
- package/docs/ARCHITECTURE.md +21 -10
- package/docs/CHARACTERS.md +309 -0
- package/docs/CLI.md +24 -3
- package/docs/COMFYUI.md +68 -0
- package/docs/ENDPOINTS.md +33 -2
- package/docs/GENERATORS.md +6 -6
- package/docs/GETTING_STARTED.md +25 -1
- package/docs/MANIFEST.md +144 -437
- package/docs/PIXELLAB.md +8 -5
- package/docs/README.md +3 -2
- package/docs/RETRO_DIFFUSION.md +96 -2
- package/docs/SCENARIO.md +46 -0
- package/package.json +1 -1
- package/skills/pixelkiln/SKILL.md +7 -0
- package/skills/pixelkiln/references/pixellab.md +1 -1
package/docs/MANIFEST.md
CHANGED
|
@@ -13,8 +13,8 @@ directory. The canonical machine-readable contract is
|
|
|
13
13
|
"styles": {
|
|
14
14
|
"base": {
|
|
15
15
|
"generator": "map",
|
|
16
|
-
"promptPrefix": "
|
|
17
|
-
"promptSuffix": "
|
|
16
|
+
"promptPrefix": "pixel-art game prop",
|
|
17
|
+
"promptSuffix": "isolated, transparent background",
|
|
18
18
|
"outDir": "assets/generated/base"
|
|
19
19
|
}
|
|
20
20
|
},
|
|
@@ -37,6 +37,17 @@ Unknown properties are rejected at every level.
|
|
|
37
37
|
| `styles` | yes | Map of style id to inherited generation/output settings. |
|
|
38
38
|
| `assets` | yes | Map of stable asset id to subject and per-asset overrides. |
|
|
39
39
|
|
|
40
|
+
```jsonc
|
|
41
|
+
{
|
|
42
|
+
"$schema": "./node_modules/pixelkiln/schema/manifest.schema.json",
|
|
43
|
+
"name": "my-game", // tags every provider object pixelkiln:my-game
|
|
44
|
+
"provider": "pixellab", // the default; a style may name another
|
|
45
|
+
"history": 3, // keep three replaced generations per asset
|
|
46
|
+
"styles": { "base": { "generator": "map", "outDir": "assets/generated/base" } },
|
|
47
|
+
"assets": { "anvil": { "prompt": "a compact blacksmith anvil" } }
|
|
48
|
+
}
|
|
49
|
+
```
|
|
50
|
+
|
|
40
51
|
A resolved unit of work is one `styleId/assetId`. Asset ids are stable lookup
|
|
41
52
|
keys, atlas frame ids, and default filenames; changing one is a data migration,
|
|
42
53
|
not merely a label edit.
|
|
@@ -54,16 +65,17 @@ not merely a label edit.
|
|
|
54
65
|
| `sourceByStyle` | object | Per-style `source`, keyed by style id; wins over `source` for that style. Written by `pixelkiln edit` for a hand edit of an asset that is in several styles. |
|
|
55
66
|
| `remoteId` | string | The provider's own id for art that already exists on the account, so `adopt` maps it without matching bytes: an object id, a character id, or `<character id>#<animation group id>`. Not part of the spec's identity. |
|
|
56
67
|
| `revision` | object | Controlled image-to-image or inpaint dependency. See [controlled revisions](REVISIONS.md). |
|
|
57
|
-
| `state` | object | `character` styles: a pose or outfit of another character asset. See [Characters](
|
|
58
|
-
| `animation` | object | `character` styles: a loop of another character asset in one direction. See [Characters](
|
|
59
|
-
| `mirror` | string | Another asset of the same style flipped left to right, made locally at no cost. See [Mirrors](#mirrors). |
|
|
68
|
+
| `state` | object | `character` styles: a pose or outfit of another character asset. See [Characters](./CHARACTERS.md). |
|
|
69
|
+
| `animation` | object | `character` styles: a loop of another character asset in one direction. See [Characters](./CHARACTERS.md). |
|
|
70
|
+
| `mirror` | string | Another asset of the same style flipped left to right, made locally at no cost. See [Mirrors](./CHARACTERS.md#mirrors). |
|
|
60
71
|
| `proportions` | preset or object | `character` styles: this base's proportions, over the style's. |
|
|
61
|
-
| `reference` | string or object | `character` styles, bases: the character's own south-facing sprite (or `{ "south": ..., "east": ... }`), which PixelLab rotates instead of drawing from the prompt. See [Characters](
|
|
72
|
+
| `reference` | string or object | `character` styles, bases: the character's own south-facing sprite (or `{ "south": ..., "east": ... }`), which PixelLab rotates instead of drawing from the prompt. See [Characters](./CHARACTERS.md). |
|
|
62
73
|
| `concept` | string | `character` styles, `pro` bases: a manifest-relative concept image (up to 1024px) the design is seeded from. |
|
|
63
74
|
| `styleCharacter` | string | `character` styles, `pro` bases: this base's style anchor, over the style's. |
|
|
64
75
|
| `providerInputs` | JSON scalar/sequence map, `{}` | Named per-asset inputs consumed by the active provider. ComfyUI accepts scalars and, for `frames`, one ordered 2–64 value sequence. Image bindings upload PNG/JPEG inputs. |
|
|
65
76
|
| `styles` | string array, `[]` | Restrict the asset to named styles; empty means every style. |
|
|
66
77
|
| `promptByStyle` | string map, `{}` | Replace only the asset prompt for a named style. |
|
|
78
|
+
| `cell` | `[column,row]` | The grid cell this asset owns in a mounted sheet; see [stable-cell mounting](#stable-cell-mounting). |
|
|
67
79
|
| `outputRole` | string | Select one structural output when a generator returns a set. |
|
|
68
80
|
| `tags` | string array, `[]` | Asset tags added to provider objects where supported. |
|
|
69
81
|
|
|
@@ -75,6 +87,26 @@ Only a provider that declares a sequence contract may accept an array. ComfyUI
|
|
|
75
87
|
uses the array named by `providerOptions.comfyui.frames.vary`; other inputs stay
|
|
76
88
|
constant across the set.
|
|
77
89
|
|
|
90
|
+
One asset using the fields most projects reach for:
|
|
91
|
+
|
|
92
|
+
```jsonc
|
|
93
|
+
{
|
|
94
|
+
"assets": {
|
|
95
|
+
"anvil": {
|
|
96
|
+
"prompt": "a compact blacksmith anvil",
|
|
97
|
+
"promptByStyle": { "mono": "a compact blacksmith anvil, dark iron" },
|
|
98
|
+
"width": 48,
|
|
99
|
+
"height": 32,
|
|
100
|
+
"category": "tools", // assets/generated/base/tools/anvil.png
|
|
101
|
+
"tags": ["prop", "forge"],
|
|
102
|
+
"styles": ["base", "mono"], // skip every other style
|
|
103
|
+
"cell": [2, 0], // its cell on a mounted sheet
|
|
104
|
+
"source": "edits/anvil.png" // a hand edit stands in for the generated file
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
```
|
|
109
|
+
|
|
78
110
|
## Style fields
|
|
79
111
|
|
|
80
112
|
| Field | Type/default | Meaning |
|
|
@@ -101,7 +133,7 @@ constant across the set.
|
|
|
101
133
|
| `tileView` | enum | `top-down`, `high top-down`, `low top-down`, or `side`. |
|
|
102
134
|
| `tileFeature` | enum | Connectable `roads`, `tileset`, or `building` structural set. |
|
|
103
135
|
| `outlineMode` | enum | `outline` or `segmentation`; segmentation avoids quilted ground seams. |
|
|
104
|
-
| `mode` | `standard` | `character` only. `standard`, `v3`, `pro`, or `pro-flash`; see [Characters](
|
|
136
|
+
| `mode` | `standard` | `character` only. `standard`, `v3`, `pro`, or `pro-flash`; see [Characters](./CHARACTERS.md). |
|
|
105
137
|
| `directions` | `8` | `character` only. `4` or `8`; every engine but `standard` draws 8. |
|
|
106
138
|
| `template` | `mannequin` | `character` only. Body template: `mannequin`, or `bear`, `cat`, `dog`, `horse`, `lion`; `custom` for `pro-flash`. |
|
|
107
139
|
| `proportions` | | `character` only, `standard` humanoid bases. A preset (`default`, `chibi`, `cartoon`, `stylized`, `realistic_male`, `realistic_female`, `heroic`) or multipliers `{ headSize, armsLength, legsLength, shoulderWidth, hipWidth }`, each 0.5 to 2. An asset may override it. |
|
|
@@ -114,6 +146,36 @@ constant across the set.
|
|
|
114
146
|
| `quality` | object | Optional native-grid, final-palette, and human-approval contract; documented below. |
|
|
115
147
|
| `tags` | string array, `[]` | Tags inherited by every generated provider object in the style. |
|
|
116
148
|
|
|
149
|
+
One style using the common fields, and a `pixflux` style with a locked
|
|
150
|
+
palette:
|
|
151
|
+
|
|
152
|
+
```jsonc
|
|
153
|
+
{
|
|
154
|
+
"styles": {
|
|
155
|
+
"base": {
|
|
156
|
+
"generator": "map",
|
|
157
|
+
"outDir": "assets/generated/base",
|
|
158
|
+
"promptPrefix": "pixel-art game prop",
|
|
159
|
+
"promptSuffix": "isolated, transparent background",
|
|
160
|
+
"size": 64,
|
|
161
|
+
"view": "high top-down",
|
|
162
|
+
"outline": "selective outline",
|
|
163
|
+
"shading": "medium shading",
|
|
164
|
+
"detail": "medium detail",
|
|
165
|
+
"seed": 7,
|
|
166
|
+
"tags": ["props"]
|
|
167
|
+
},
|
|
168
|
+
"gb": {
|
|
169
|
+
"generator": "pixflux",
|
|
170
|
+
"outDir": "assets/generated/gb",
|
|
171
|
+
"palette": ["#0f380f", "#306230", "#8bac0f", "#9bbc0f"],
|
|
172
|
+
"enforcePalette": true,
|
|
173
|
+
"noBackground": false
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
```
|
|
178
|
+
|
|
117
179
|
### Style inheritance
|
|
118
180
|
|
|
119
181
|
Use `extends` for a real variant that differs from a base style by a few
|
|
@@ -300,470 +362,82 @@ disagreement rejects the whole set. The schema rejects `tiles` and provider
|
|
|
300
362
|
`animation`, whose output contracts differ. See
|
|
301
363
|
[Quality gates](./QUALITY.md#manifest-quality-profile) for the release workflow.
|
|
302
364
|
|
|
303
|
-
##
|
|
304
|
-
|
|
305
|
-
Retro Diffusion maps `map` and `pixflux` to still generation, `tiles` to its
|
|
306
|
-
tileset family, and `animation` to GIF or PNG-spritesheet generation. Durable
|
|
307
|
-
sources and lock outputs record `image/png` or `image/gif`, so recovery retains
|
|
308
|
-
the correct extension and validates the correct structure.
|
|
309
|
-
|
|
310
|
-
```jsonc
|
|
311
|
-
{
|
|
312
|
-
"name": "my-game",
|
|
313
|
-
"provider": "retrodiffusion",
|
|
314
|
-
"styles": {
|
|
315
|
-
"base": {
|
|
316
|
-
"generator": "map",
|
|
317
|
-
"outDir": "assets/generated/base",
|
|
318
|
-
"providerOptions": {
|
|
319
|
-
"retrodiffusion": {
|
|
320
|
-
"promptStyle": "rd_plus__default",
|
|
321
|
-
"numImages": 4,
|
|
322
|
-
"removeBg": true
|
|
323
|
-
}
|
|
324
|
-
}
|
|
325
|
-
}
|
|
326
|
-
},
|
|
327
|
-
"assets": {
|
|
328
|
-
"anvil": { "prompt": "a compact blacksmith anvil" }
|
|
329
|
-
}
|
|
330
|
-
}
|
|
331
|
-
```
|
|
332
|
-
|
|
333
|
-
`promptStyle` accepts a live Retro Diffusion still-style selector,
|
|
334
|
-
`numImages` accepts 1–16 candidates, and `removeBg` overrides
|
|
335
|
-
`noBackground`. The Retro Diffusion API accepts 16–512px output. Selected
|
|
336
|
-
styles can impose smaller limits. RD Pro and user styles accept up to nine
|
|
337
|
-
reference images. Costs are
|
|
338
|
-
planned in USD and checked again with Retro Diffusion's free authoritative
|
|
339
|
-
quote endpoint before the paid request is sent. Authenticated single-candidate
|
|
340
|
-
RD Fast and RD Plus paths have passed from quote through validated output and
|
|
341
|
-
recovery.
|
|
342
|
-
Multi-candidate, tileset, GIF, and spritesheet paths remain mock-tested, so the
|
|
343
|
-
adapter is still experimental.
|
|
344
|
-
|
|
345
|
-
Additional Retro Diffusion options are:
|
|
346
|
-
|
|
347
|
-
| Option | Meaning |
|
|
348
|
-
|---|---|
|
|
349
|
-
| `framesDuration` | Animation duration: `4`, `6`, `8`, `10`, `12`, or `16`. |
|
|
350
|
-
| `returnSpritesheet` | Return a PNG spritesheet instead of an animated GIF. |
|
|
351
|
-
| `extraPrompt` | Outside texture description for `rd_tile__tileset_advanced`. |
|
|
352
|
-
| `tileX` / `tileY` | Make supported still styles seamless on either axis. |
|
|
353
|
-
|
|
354
|
-
An animation style is declared explicitly:
|
|
355
|
-
|
|
356
|
-
```jsonc
|
|
357
|
-
{
|
|
358
|
-
"generator": "animation",
|
|
359
|
-
"size": 64,
|
|
360
|
-
"outDir": "assets/generated/animations",
|
|
361
|
-
"providerOptions": {
|
|
362
|
-
"retrodiffusion": {
|
|
363
|
-
"promptStyle": "rd_animation__any_animation",
|
|
364
|
-
"numImages": 1,
|
|
365
|
-
"framesDuration": 8,
|
|
366
|
-
"returnSpritesheet": false
|
|
367
|
-
}
|
|
368
|
-
}
|
|
369
|
-
}
|
|
370
|
-
```
|
|
371
|
-
|
|
372
|
-
The default output is `<assetId>.gif`; `returnSpritesheet: true` produces
|
|
373
|
-
`<assetId>.png`. Advanced animation styles require exactly one `styleImages`
|
|
374
|
-
input. PixelKiln currently limits animation batches to one so selection never
|
|
375
|
-
loses the output media type.
|
|
376
|
-
|
|
377
|
-
For a Wang-style tileset sheet:
|
|
378
|
-
|
|
379
|
-
```jsonc
|
|
380
|
-
{
|
|
381
|
-
"generator": "tiles",
|
|
382
|
-
"tileSize": 32,
|
|
383
|
-
"outDir": "assets/generated/tiles",
|
|
384
|
-
"providerOptions": {
|
|
385
|
-
"retrodiffusion": {
|
|
386
|
-
"promptStyle": "rd_tile__tileset",
|
|
387
|
-
"numImages": 1
|
|
388
|
-
}
|
|
389
|
-
}
|
|
390
|
-
}
|
|
391
|
-
```
|
|
392
|
-
|
|
393
|
-
`rd_tile__tileset_advanced` accepts `extraPrompt` and up to two style images;
|
|
394
|
-
`rd_tile__tile_variation` requires one style image. Provider-specific size and
|
|
395
|
-
input constraints are checked during the free planning phase.
|
|
396
|
-
|
|
397
|
-
## Experimental ComfyUI
|
|
365
|
+
## Provider-specific fields
|
|
398
366
|
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
not pixel-art quality. Use provider-neutral `pixelkiln refine` for native-grid,
|
|
403
|
-
final-palette, and recorded audit checks. Prompt coverage and human 1× approval
|
|
404
|
-
still require a person.
|
|
367
|
+
Each experimental provider adds style and asset fields of its own, under
|
|
368
|
+
`providerOptions.<provider>` on the style and `providerInputs` on the asset.
|
|
369
|
+
They are documented with the provider:
|
|
405
370
|
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
"generator": "map",
|
|
413
|
-
"outDir": "assets/generated/local",
|
|
414
|
-
"seed": 31415,
|
|
415
|
-
"providerOptions": {
|
|
416
|
-
"comfyui": {
|
|
417
|
-
"workflowFile": "workflows/pixel-api.json",
|
|
418
|
-
"outputNodeId": "9",
|
|
419
|
-
"numImages": 4,
|
|
420
|
-
"bindings": {
|
|
421
|
-
"prompt": { "nodeId": "6", "input": "text" },
|
|
422
|
-
"width": { "nodeId": "5", "input": "width" },
|
|
423
|
-
"height": { "nodeId": "5", "input": "height" },
|
|
424
|
-
"batchSize": { "nodeId": "5", "input": "batch_size" },
|
|
425
|
-
"seed": { "nodeId": "3", "input": "seed" },
|
|
426
|
-
"composition": { "nodeId": "19", "input": "image" },
|
|
427
|
-
"controlStrength": { "nodeId": "20", "input": "strength" }
|
|
428
|
-
}
|
|
429
|
-
}
|
|
430
|
-
}
|
|
431
|
-
}
|
|
432
|
-
},
|
|
433
|
-
"assets": {
|
|
434
|
-
"mountain": {
|
|
435
|
-
"prompt": "a snowbound mountain pass",
|
|
436
|
-
"width": 768,
|
|
437
|
-
"height": 512,
|
|
438
|
-
"providerInputs": {
|
|
439
|
-
"composition": "controls/mountain-layout.png",
|
|
440
|
-
"controlStrength": 0.7
|
|
441
|
-
}
|
|
442
|
-
}
|
|
443
|
-
}
|
|
444
|
-
}
|
|
445
|
-
```
|
|
371
|
+
- [Retro Diffusion](./RETRO_DIFFUSION.md#manifest-fields): still styles,
|
|
372
|
+
tilesets, and GIF or spritesheet animation.
|
|
373
|
+
- [ComfyUI](./COMFYUI.md#manifest-fields): a committed workflow, its bindings,
|
|
374
|
+
revisions, and atomic frame sets.
|
|
375
|
+
- [Scenario](./SCENARIO.md#manifest-fields): hosted model ids and Compute
|
|
376
|
+
Unit ceilings.
|
|
446
377
|
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
binding aimed at `LoadImage.image` or `LoadImageMask.image` treats its string as
|
|
451
|
-
a manifest-relative PNG/JPEG, hashes it, and uploads it at submission. Other
|
|
452
|
-
custom inputs accept a string, number, or boolean matching the workflow's
|
|
453
|
-
placeholder type. Local paths never enter stable provenance.
|
|
454
|
-
|
|
455
|
-
The current adapter supports `map` and ordered still-image `frames`, PNG output
|
|
456
|
-
from one node, 1–16 `map` candidates, and dimensions from 16–4096px. A frame
|
|
457
|
-
style uses `numImages: 1`; the varying input supplies 2–64 renders. It rejects
|
|
458
|
-
manifest `styleImages` and `palette`;
|
|
459
|
-
use custom image bindings for per-asset ControlNet or reference images, and keep
|
|
460
|
-
shared model/LoRA/palette controls inside the workflow. See
|
|
461
|
-
[Set up ComfyUI](COMFYUI.md) for the complete procedure, safe workflow, and
|
|
462
|
-
quality limits. The 4096px adapter ceiling is not a recommended generation or
|
|
463
|
-
native-art size.
|
|
464
|
-
|
|
465
|
-
## Experimental Scenario
|
|
466
|
-
|
|
467
|
-
Scenario uses hosted model IDs and requires a conservative Compute Unit ceiling
|
|
468
|
-
for every style:
|
|
378
|
+
Only the active provider's object is resolved and hashed, so one style can
|
|
379
|
+
carry settings for more than one provider and switch between them by
|
|
380
|
+
changing `provider` alone:
|
|
469
381
|
|
|
470
382
|
```jsonc
|
|
471
383
|
{
|
|
472
|
-
"provider": "
|
|
384
|
+
"provider": "pixellab",
|
|
473
385
|
"styles": {
|
|
474
386
|
"environment": {
|
|
475
387
|
"generator": "map",
|
|
476
|
-
"size": 512,
|
|
477
388
|
"outDir": "assets/generated/environment",
|
|
478
389
|
"providerOptions": {
|
|
479
|
-
"
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
"numOutputs": 4,
|
|
483
|
-
"maxComputeUnits": 60,
|
|
484
|
-
"parameters": {
|
|
485
|
-
"guidance": 4,
|
|
486
|
-
"numInferenceSteps": 28
|
|
487
|
-
}
|
|
488
|
-
}
|
|
390
|
+
"retrodiffusion": { "promptStyle": "rd_plus__default", "numImages": 4 },
|
|
391
|
+
"comfyui": { "workflowFile": "workflows/still-api.json", "outputNodeId": "9" },
|
|
392
|
+
"scenario": { "modelId": "model_bfl-flux-2-dev", "maxComputeUnits": 60 }
|
|
489
393
|
}
|
|
490
394
|
}
|
|
491
395
|
},
|
|
492
|
-
"assets": {
|
|
493
|
-
"mountain-town": { "prompt": "a fortified mountain town" }
|
|
494
|
-
}
|
|
396
|
+
"assets": { "keep": { "prompt": "a mountain keep at dusk" } }
|
|
495
397
|
}
|
|
496
398
|
```
|
|
497
399
|
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
| `maxComputeUnits` | Required positive per-asset offline ceiling and maximum accepted live quote. |
|
|
502
|
-
| `numOutputs` | One to four PNG candidates; defaults to one. |
|
|
503
|
-
| `projectId` | Optional Scenario ownership/routing project. |
|
|
504
|
-
| `parameters` | Additional model-specific JSON inputs. PixelKiln-owned request fields cannot be overridden. |
|
|
400
|
+
`providerInputs` on an asset is the same idea per asset, for providers that
|
|
401
|
+
declare bindings (ComfyUI); a provider without them rejects a non-empty
|
|
402
|
+
object rather than ignoring it.
|
|
505
403
|
|
|
506
|
-
|
|
507
|
-
16, optional seed, and no style-image uploads. Every paid request is preceded
|
|
508
|
-
by an identical `dryRun=true` request. See [Set up Scenario](SCENARIO.md) for
|
|
509
|
-
credentials, cost semantics, recovery, and the paid live-test boundary.
|
|
510
|
-
|
|
511
|
-
## Asset fields
|
|
404
|
+
## Characters and mirrors
|
|
512
405
|
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
| `height` | integer 16–8192 | Per-asset height override. Each provider applies its own ceiling. |
|
|
519
|
-
| `size` | integer 32–256 | Per-asset square size override. |
|
|
520
|
-
| `file` | string | Filename/path override beneath the style output root. |
|
|
521
|
-
| `styles` | string array, `[]` | If non-empty, generate this asset only in the named styles. |
|
|
522
|
-
| `promptByStyle` | object, `{}` | Replace the asset prompt for specific style ids. |
|
|
523
|
-
| `tags` | string array, `[]` | Asset tags combined with style tags. |
|
|
524
|
-
| `cell` | `[column,row]` | Non-negative stable grid cell used by `mount`. |
|
|
525
|
-
| `source` | string | Manifest-relative post-processed/hand-drawn source placed by `mount`, `pack`, and `export` instead of lock output. For a set of PNG outputs, a path that is not a file is a stem: each member is placed from `<stem>-<role>.png`, the rule generated outputs follow. A file that exists there is one image placed for the whole set, as before. |
|
|
526
|
-
| `sourceByStyle` | object | The same, for one style only. A hand edit belongs to one generation, so an asset shared by styles keeps one edit per style. |
|
|
527
|
-
| `revision` | object | Generate a new asset from another asset's current bytes. `source` and `revision` are mutually exclusive. |
|
|
528
|
-
| `outputRole` | string | Select one member of a structural output set for mounting. |
|
|
529
|
-
| `mirror` | string | Another asset of this style, flipped left to right. No prompt, no provider, no cost. See [Mirrors](#mirrors). |
|
|
530
|
-
| `proportions` | preset or object | This base's body proportions, over the style's. `standard` humanoid bases only. |
|
|
531
|
-
| `reference` | string or object | The character's own sprite(s) for PixelLab to rotate. Bases only. |
|
|
532
|
-
| `concept` | string | A concept image a `pro` base is designed from. Bases only. |
|
|
533
|
-
| `styleCharacter` | string | The character in this style a `pro` base takes its look from, over the style's. |
|
|
534
|
-
|
|
535
|
-
## Characters
|
|
406
|
+
A `character` style holds a base drawn facing 4 or 8 directions, states, and
|
|
407
|
+
loops, with a `mirror` asset for the direction that faces the other way,
|
|
408
|
+
made locally at no cost. The shapes, engines, references, and costs have
|
|
409
|
+
their own page: [Characters](./CHARACTERS.md) and
|
|
410
|
+
[Mirrors](./CHARACTERS.md#mirrors).
|
|
536
411
|
|
|
537
|
-
```
|
|
412
|
+
```jsonc
|
|
538
413
|
{
|
|
539
414
|
"styles": {
|
|
540
415
|
"cast": {
|
|
541
416
|
"generator": "character",
|
|
542
417
|
"outDir": "art/characters",
|
|
543
|
-
"
|
|
544
|
-
"
|
|
545
|
-
"
|
|
546
|
-
"palette": ["#0f380f", "#306230", "#8bac0f", "#9bbc0f"],
|
|
547
|
-
"enforcePalette": true
|
|
418
|
+
"mode": "pro-flash", // standard, v3, pro, or pro-flash
|
|
419
|
+
"template": "custom", // mannequin, a quadruped, or custom (pro-flash)
|
|
420
|
+
"size": 96
|
|
548
421
|
}
|
|
549
422
|
},
|
|
550
423
|
"assets": {
|
|
551
|
-
"
|
|
552
|
-
"prompt": "small
|
|
424
|
+
"bot": {
|
|
425
|
+
"prompt": "small round orange robot with one blue eye",
|
|
426
|
+
"reference": "refs/bot-south.png" // rotate this sprite instead of drawing from text
|
|
553
427
|
},
|
|
554
|
-
"
|
|
555
|
-
"prompt": "
|
|
556
|
-
"state": { "of": "
|
|
428
|
+
"bot.dented": {
|
|
429
|
+
"prompt": "shell dented, one arm hanging loose",
|
|
430
|
+
"state": { "of": "bot", "paletteFromReference": true }
|
|
557
431
|
},
|
|
558
|
-
"
|
|
559
|
-
"prompt": "
|
|
560
|
-
"animation": { "of": "
|
|
432
|
+
"bot.walk.west": {
|
|
433
|
+
"prompt": "walking in place, short legs stepping",
|
|
434
|
+
"animation": { "of": "bot", "direction": "west", "frames": 12, "fps": 12 }
|
|
561
435
|
},
|
|
562
|
-
"
|
|
563
|
-
"prompt": "",
|
|
564
|
-
"animation": { "of": "mira", "template": "walk", "direction": "south" }
|
|
565
|
-
}
|
|
436
|
+
"bot.walk.east": { "mirror": "bot.walk.west" } // flipped locally, 0 generations
|
|
566
437
|
}
|
|
567
438
|
}
|
|
568
439
|
```
|
|
569
440
|
|
|
570
|
-
A `character` style holds three shapes of asset that share one PixelLab
|
|
571
|
-
character.
|
|
572
|
-
|
|
573
|
-
A base is a prompt, wrapped in the style's prefix and suffix like any other
|
|
574
|
-
asset, that PixelLab draws facing 4 or 8 directions. `mode` picks the
|
|
575
|
-
engine: `standard` (1 generation, the skeleton template, `outline`,
|
|
576
|
-
`shading`, and `detail` as soft guidance, and `palette` sent as a colour
|
|
577
|
-
reference), `v3` (2 to 9 by size, the highest quality, up to 256px),
|
|
578
|
-
`pro` (20 to 40 by size), or `pro-flash` (6 to 17 by size: PixelLab's
|
|
579
|
-
newest image model draws the south sprite and v3 rotates it; sizes are
|
|
580
|
-
multiples of 4 up to 256, `template` may be `custom`, and a `reference`
|
|
581
|
-
pays for the rotations only, 1 at 64px). `size` is the character's size;
|
|
582
|
-
`view` is `low top-down` (the default), `high top-down`, or `side`;
|
|
583
|
-
`template` picks the body. Each direction lands as
|
|
584
|
-
`<asset>-<direction>.png`, south first.
|
|
585
|
-
Standard mode draws on a canvas 28px larger than `size`, 14px of room on
|
|
586
|
-
each side for animation (a 64px character comes back as 92px files, a
|
|
587
|
-
104px one as 132px); the lock records the size asked for, and the files
|
|
588
|
-
are what PixelLab drew.
|
|
589
|
-
|
|
590
|
-
Three more knobs shape a `standard` base. `proportions` is a preset
|
|
591
|
-
(`chibi`, `heroic`, and so on) or multipliers on the mannequin's head,
|
|
592
|
-
arms, legs, shoulders, and hips; it lives on the style and any base may
|
|
593
|
-
override it, and only the mannequin template has proportions to set.
|
|
594
|
-
`textGuidanceScale` (1 to 20, PixelLab's default 8) is how closely the text
|
|
595
|
-
is followed, and applies to template loops as well. `isometric` draws the
|
|
596
|
-
base and every loop in isometric view. The v3 and pro engines take none of
|
|
597
|
-
the three for a base; a v3 style may still set the last two for its loops.
|
|
598
|
-
A `v3` base takes `enhancePrompt` instead, which has PixelLab expand the
|
|
599
|
-
prompt into a fuller one before drawing.
|
|
600
|
-
|
|
601
|
-
A base can also start from your own sprite. `reference` names a
|
|
602
|
-
manifest-relative PNG or JPEG of the character facing south, and PixelLab
|
|
603
|
-
draws the other directions from it, with the prompt as guidance:
|
|
604
|
-
|
|
605
|
-
```json
|
|
606
|
-
"mira": { "prompt": "small young woman, oversized hoodie", "reference": "refs/mira-south.png" }
|
|
607
|
-
```
|
|
608
|
-
|
|
609
|
-
`standard` uses each image as it is, centred on its larger canvas, and
|
|
610
|
-
generates the rest, so the image must be the style's `size` exactly; it
|
|
611
|
-
accepts one image per direction
|
|
612
|
-
(`{ "south": ..., "east": ... }`), and a quadruped template needs south and
|
|
613
|
-
east. `v3` rotates one south image of up to 256px (its `template` must
|
|
614
|
-
match the body in the image). `pro` rotates one south image of up to 168px
|
|
615
|
-
through its `rotate_character` method. The reference's bytes are part of
|
|
616
|
-
the base's identity, so a redrawn file makes the base stale, and the file
|
|
617
|
-
is read again at submit time and refused if it changed since `plan`.
|
|
618
|
-
States, animations, and mirrors take their look from their parent and
|
|
619
|
-
cannot carry a reference.
|
|
620
|
-
|
|
621
|
-
The pro engine has two more ways in. `concept` on a base names a concept
|
|
622
|
-
image (a painting, a photo, a sketch, up to 1024px) that seeds the design
|
|
623
|
-
in place of the prompt alone (PixelLab's `create_from_concept`); the
|
|
624
|
-
prompt still guides it. `styleCharacter`, on the style or a base, names a
|
|
625
|
-
generated 8-direction character in the same style whose look the base
|
|
626
|
-
follows (`style_character_id`); its south sprite becomes the style image
|
|
627
|
-
unless a style image is also given. The anchor is a dependency like a
|
|
628
|
-
loop's character: the base is `blocked` until the anchor is downloaded and
|
|
629
|
-
current, `gen` runs it in the wave after the anchor lands, and a
|
|
630
|
-
regenerated anchor makes every base drawn in its style `stale`. The anchor
|
|
631
|
-
itself ignores the setting, so a style can name its own first character.
|
|
632
|
-
PixelLab wants the base at least as large as the anchor's visible sprite
|
|
633
|
-
and fails the job fast otherwise. A base rotating its own `reference`
|
|
634
|
-
takes neither: the rotate method has one image slot and it is the
|
|
635
|
-
character.
|
|
636
|
-
|
|
637
|
-
Style images on a `character` style are a pro input: one image of up to
|
|
638
|
-
168px that anchors the look of a `pro` base drawn from text or a concept
|
|
639
|
-
(`create_with_style` and `create_from_concept` both take it), or one of
|
|
640
|
-
up to 256px that a `pro-flash` base copies its look from, no larger than
|
|
641
|
-
the character's `size` on either side (crop it to its subject), with
|
|
642
|
-
`styleTraits` (`palette`, `outline`, `detail`, `shading`, each on by
|
|
643
|
-
default) choosing which traits it lends. `standard` and `v3` have no such
|
|
644
|
-
slot and refuse them; a base with a `reference` refuses them too, in
|
|
645
|
-
either engine.
|
|
646
|
-
|
|
647
|
-
A state is a text edit of an existing character, `state.of`, applied to
|
|
648
|
-
every direction at once: a pose, an outfit, a held object. The prompt is
|
|
649
|
-
the edit and goes to PixelLab as written, without the style's prefix and
|
|
650
|
-
suffix, since the character already carries the look.
|
|
651
|
-
`paletteFromReference` snaps the result to the parent's colours; `canvas`
|
|
652
|
-
asks for a larger frame when the edit adds something big. A state costs 20
|
|
653
|
-
to 40 by canvas and keeps the parent's directions. A state may be a state
|
|
654
|
-
of another state.
|
|
655
|
-
|
|
656
|
-
An animation is one loop of one character (`animation.of`, a base or a
|
|
657
|
-
state) in one `direction`. With a `template` (PixelLab's `walk`,
|
|
658
|
-
`breathing-idle`, `running-8-frames`, and so on) it costs 1 and the
|
|
659
|
-
template decides the frame count; without one the prompt is the motion and
|
|
660
|
-
PixelLab's v3 engine draws `frames` frames (4 to 16, even, default 8) for
|
|
661
|
-
`ceil(size² × frames / 65536)` generations, one at 64px. `keepFirstFrame`
|
|
662
|
-
(on by default) stores the resting pose as frame 0, so 8 frames land as 9
|
|
663
|
-
files, `<asset>-frame-00.png` onwards. `fps` is recorded with the frames
|
|
664
|
-
for the gallery, `pack`, and the Godot and Aseprite formats; PixelLab does
|
|
665
|
-
not keep one. An animation lands in review as an ordered set: `pick` shows
|
|
666
|
-
the loop and accepts or rejects it whole. One asset per direction; declare
|
|
667
|
-
another asset for another direction, or a [mirror](#mirrors) of this one
|
|
668
|
-
for the direction that faces the other way.
|
|
669
|
-
|
|
670
|
-
A v3 loop can start and end where you say. `startFrame` is a
|
|
671
|
-
manifest-relative image of the pose to begin from instead of the
|
|
672
|
-
character's rotation; `endFrame` is a pose to reach, and with it the loop
|
|
673
|
-
interpolates from the start frame to that image (both up to 256px, and the
|
|
674
|
-
end frame the same size as the start frame or, without one, as the
|
|
675
|
-
character's rotation, which `plan` checks once the parent is on disk; the
|
|
676
|
-
frames can still come back on a taller canvas when the motion needs it, as
|
|
677
|
-
a 92px crouch did at 92×104). `subject` replaces the character's own description for this loop when it
|
|
678
|
-
would mislead the model (a state that took the armour off), and
|
|
679
|
-
`enhancePrompt` lets PixelLab expand the action into a fuller motion
|
|
680
|
-
description first. A template loop takes none of those; it takes
|
|
681
|
-
`outline`, `shading`, and `detail` overrides instead, over the character's
|
|
682
|
-
own. The style's `palette` goes to every loop as a colour reference, as it
|
|
683
|
-
does to a `standard` base, and `enforcePalette` still snaps the frames
|
|
684
|
-
afterwards. Pose images hash into the loop's identity and are read again
|
|
685
|
-
at submit time, like a base's `reference`.
|
|
686
|
-
|
|
687
|
-
```json
|
|
688
|
-
"mira.bow": {
|
|
689
|
-
"prompt": "bowing deeply from the waist",
|
|
690
|
-
"animation": { "of": "mira", "direction": "south", "frames": 6, "endFrame": "poses/mira-bowed.png" }
|
|
691
|
-
}
|
|
692
|
-
```
|
|
693
|
-
|
|
694
|
-
States and animations depend on their parent the way a revision does. The
|
|
695
|
-
parent must be downloaded and current before the child is actionable;
|
|
696
|
-
`plan` reports the child as `blocked` and names the parent until then, and
|
|
697
|
-
one `gen` runs the waves in order: bases, then states, then animations,
|
|
698
|
-
under one budget. The
|
|
699
|
-
child's identity includes the parent's generated south-facing file, so
|
|
700
|
-
regenerating the parent makes every state and animation of it `stale`. A
|
|
701
|
-
hand edit of the parent does not, because PixelLab draws the child from the
|
|
702
|
-
character it holds, not from local bytes.
|
|
703
|
-
|
|
704
|
-
Regenerating an animation clears PixelKiln's own earlier take of that
|
|
705
|
-
direction on the character first, since PixelLab skips a direction that
|
|
706
|
-
already exists. The lock records the animation and group ids PixelLab
|
|
707
|
-
assigned, and the delete goes by those (PixelLab keeps the name PixelKiln
|
|
708
|
-
gives a loop only for text animations, not template ones). Nothing else on
|
|
709
|
-
the character is touched, and a base or state is never deleted by
|
|
710
|
-
PixelKiln.
|
|
711
|
-
|
|
712
|
-
`enforcePalette` snaps every direction and every frame. `pack --style cast
|
|
713
|
-
--format godot` writes a `SpriteFrames` with each direction of a base or
|
|
714
|
-
state as a still and each animation as a looping set at its fps;
|
|
715
|
-
`--format aseprite` does the same with `frameTags`.
|
|
716
|
-
|
|
717
|
-
Characters that already exist on the account come under the manifest with
|
|
718
|
-
`adopt`. Declare the asset with `remoteId` (the character id, or
|
|
719
|
-
`<character id>#<animation group id>` for a loop; `get_character` in
|
|
720
|
-
PixelLab's own tools shows both) and run `pixelkiln adopt`: it records the
|
|
721
|
-
character, writes every direction and frame that is not on disk, and costs
|
|
722
|
-
nothing. A base can also be matched by the bytes of its south-facing file.
|
|
723
|
-
See [`adopt`](CLI.md#adopt).
|
|
724
|
-
|
|
725
|
-
## Mirrors
|
|
726
|
-
|
|
727
|
-
Each direction of a loop is its own generation, and a sprite walking east
|
|
728
|
-
is the sprite walking west flipped. A `mirror` asset is that flip, made
|
|
729
|
-
locally from the source asset's downloaded files:
|
|
730
|
-
|
|
731
|
-
```json
|
|
732
|
-
"hero.walk.west": { "prompt": "", "animation": { "of": "hero", "template": "walk", "direction": "west" } },
|
|
733
|
-
"hero.walk.east": { "mirror": "hero.walk.west" }
|
|
734
|
-
```
|
|
735
|
-
|
|
736
|
-
A full 8-direction set of one loop is then 5 generations (south, north,
|
|
737
|
-
west, south-west, north-west) and 3 mirrors; a 4-direction set is 3 and 1.
|
|
738
|
-
The mirror takes its shape from the source (a loop of the same character,
|
|
739
|
-
facing the other way, at the same fps), needs no prompt, and costs
|
|
740
|
-
nothing: `plan` lists it under the provider with a cost of 0 and `gen`
|
|
741
|
-
flips it in the wave after the source lands. It has its own lock entry and
|
|
742
|
-
files (`hero.walk.east-frame-00.png` onwards), so `pack`, the gallery, and
|
|
743
|
-
an engine see an ordinary loop. Nothing is sent to the provider, and the
|
|
744
|
-
account holds no east animation.
|
|
745
|
-
|
|
746
|
-
The lock records a hash over the source's output hashes when the flip was
|
|
747
|
-
made. A source that is regenerated, restored, or re-snapped makes its
|
|
748
|
-
mirrors `stale`, and the next `gen` flips them again for free. A mirror
|
|
749
|
-
whose files went missing is `stale` too; one that was hand-edited is
|
|
750
|
-
`orphaned`, like generated art. A source that is not downloaded, current,
|
|
751
|
-
and untouched blocks its mirrors.
|
|
752
|
-
|
|
753
|
-
A loop facing south or north cannot be mirrored: the flip would be the same
|
|
754
|
-
direction with its asymmetries swapped, not a new one. A single image or a
|
|
755
|
-
frame set from any generator can be mirrored, and so can a base or state
|
|
756
|
-
(every direction flipped and relabelled, so west becomes east). A tile set
|
|
757
|
-
cannot; its edges carry meaning. Mirroring swaps handedness, so a character
|
|
758
|
-
who holds a sword in the right hand holds it in the left when facing the
|
|
759
|
-
mirrored way. Most games accept that; if yours does not, generate both
|
|
760
|
-
sides. `adopt` skips mirrors, since there is nothing upstream to adopt.
|
|
761
|
-
|
|
762
|
-
Engines that flip sprites at draw time (Godot's `flip_h`, Unity's
|
|
763
|
-
`flipX`) do not need mirrored files at all. Declare only the directions
|
|
764
|
-
you generate and flip in the engine; mirrors are for pipelines that want
|
|
765
|
-
every direction on disk.
|
|
766
|
-
|
|
767
441
|
## Controlled revisions
|
|
768
442
|
|
|
769
443
|
```jsonc
|
|
@@ -808,7 +482,25 @@ reject the revision during offline resolution. See
|
|
|
808
482
|
|
|
809
483
|
## Prompt and override resolution
|
|
810
484
|
|
|
811
|
-
|
|
485
|
+
```jsonc
|
|
486
|
+
{
|
|
487
|
+
"styles": {
|
|
488
|
+
"base": { "generator": "map", "outDir": "art/base", "promptPrefix": "pixel-art prop", "promptSuffix": "transparent background" },
|
|
489
|
+
"mono": { "extends": "base", "outDir": "art/mono", "promptSuffix": "one-bit, transparent background" }
|
|
490
|
+
},
|
|
491
|
+
"assets": {
|
|
492
|
+
"star": {
|
|
493
|
+
"prompt": "a golden star",
|
|
494
|
+
"promptByStyle": { "mono": "a five-pointed star" } // colour words would fight the style
|
|
495
|
+
}
|
|
496
|
+
}
|
|
497
|
+
}
|
|
498
|
+
```
|
|
499
|
+
|
|
500
|
+
Prefix, subject, and suffix are trimmed and joined with ", ": `base/star`
|
|
501
|
+
is sent as "pixel-art prop, a golden star, transparent background" and
|
|
502
|
+
`mono/star` as "pixel-art prop, a five-pointed star, one-bit, transparent
|
|
503
|
+
background". For each participating style/asset pair:
|
|
812
504
|
|
|
813
505
|
1. Resolve the style provider, falling back to the top-level default.
|
|
814
506
|
2. Choose `promptByStyle[styleId]` when present, otherwise `prompt`.
|
|
@@ -865,6 +557,21 @@ expand one asset into `outputs[]` with stable roles such as `tile-00` and
|
|
|
865
557
|
filenames such as `terrain-tile-00.png`. Consumers should use roles rather than
|
|
866
558
|
assuming array position. See [tiles](./TILES.md).
|
|
867
559
|
|
|
560
|
+
```jsonc
|
|
561
|
+
{
|
|
562
|
+
"styles": { "base": { "generator": "map", "outDir": "art/base" } },
|
|
563
|
+
"assets": {
|
|
564
|
+
"anvil": { "prompt": "an anvil" }, // art/base/anvil.png
|
|
565
|
+
"hammer": { "prompt": "a hammer", "category": "tools" }, // art/base/tools/hammer.png
|
|
566
|
+
"sign": { "prompt": "a shop sign", "file": "ui/shop-sign.png" } // art/base/ui/shop-sign.png
|
|
567
|
+
}
|
|
568
|
+
}
|
|
569
|
+
```
|
|
570
|
+
|
|
571
|
+
A set keeps the same stem and adds the role: a character base `bot` in a
|
|
572
|
+
style with `outDir: "art/cast"` lands as `art/cast/bot-south.png`,
|
|
573
|
+
`bot-west.png`, and so on; a loop as `bot.walk-frame-00.png` onwards.
|
|
574
|
+
|
|
868
575
|
## Validation and editor setup
|
|
869
576
|
|
|
870
577
|
Regenerate the checked-in schema after changing the Zod manifest types:
|