pixelkiln 0.67.0 → 0.68.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/PROVIDERS.md +30 -15
- package/README.md +18 -18
- package/dist/cli.js +81 -2
- package/dist/cli.js.map +1 -1
- package/dist/index.cjs +86 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +434 -34
- package/dist/index.d.ts +434 -34
- package/dist/index.js +84 -2
- package/dist/index.js.map +1 -1
- package/docs/AGENTS.md +1 -1
- package/docs/CHARACTERS.md +4 -1
- package/docs/CLI.md +32 -25
- package/docs/GENERATORS.md +41 -1
- package/docs/MANIFEST.md +5 -2
- package/docs/PIXELLAB.md +18 -4
- package/docs/README.md +2 -2
- package/package.json +1 -1
- package/schema/manifest.schema.json +61 -0
- package/skills/pixelkiln/SKILL.md +10 -4
- package/skills/pixelkiln/references/pixellab-roadmap.md +57 -82
- package/skills/pixelkiln/references/pixellab.md +29 -12
- package/skills/pixelkiln/references/revisions.md +18 -4
package/PROVIDERS.md
CHANGED
|
@@ -57,19 +57,20 @@ the providers offer directly.
|
|
|
57
57
|
| Decision | PixelLab | Retro Diffusion |
|
|
58
58
|
|---|---|---|
|
|
59
59
|
| Best fit today | Existing PixelKiln projects, account reconciliation, and live-tested generation | Native pixel-art styles, USD budgets, animation, and alternate tileset workflows |
|
|
60
|
-
| PixelKiln generators | `map`, `pixflux`, `1dir`, `tiles`, `character` | `map` and `pixflux` stills, `tiles`, `animation` |
|
|
61
|
-
| Output | PNG stills, candidates,
|
|
60
|
+
| PixelKiln generators | `map`, `pixflux`, `1dir`, `imagePro`, `imageProFlash`, `tiles`, `terrain`, `isometricTile`, `character`, `objectPro`, `uiAsset`, `uiElement` | `map` and `pixflux` stills, `tiles`, `animation` |
|
|
61
|
+
| Output | PNG stills, candidates, structural tile members, and ordered frame sets | PNG stills/tiles/spritesheets or animated GIF |
|
|
62
62
|
| Candidate review | Yes; count varies by generator and size | Yes for 1–16 still candidates; animations and tilesets currently use one result |
|
|
63
|
-
| References | `1dir` and tile style modes | Up to nine for supported RD Pro/user still styles; constrained inputs for animation and tiles |
|
|
63
|
+
| References | `1dir` and tile style modes; a character or `objectPro` reference sprite; a `pro` character concept image; one `imageProFlash` style image; one `uiElement` concept image | Up to nine for supported RD Pro/user still styles; constrained inputs for animation and tiles |
|
|
64
64
|
| Cost model | Subscription generations | Prepaid USD balance |
|
|
65
65
|
| Cost safety | Offline estimate plus hard generation budget | Offline estimate, hard USD budget, then a free authoritative quote before submission |
|
|
66
66
|
| Account lifecycle | Balance, list, adopt, salvage, tag, and confirmed purge | Balance only in the current adapter |
|
|
67
67
|
| Live confidence | Full paid generation workflows exercised | RD Fast and RD Plus single-candidate stills exercised end to end; multi-candidate, tileset, GIF, and spritesheet runs pending |
|
|
68
68
|
|
|
69
69
|
Choose PixelLab when mature account-object recovery and reconciliation matter,
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
70
|
+
when the measured one-generation `map`/`pixflux` routes fit the work, or when an
|
|
71
|
+
animation belongs to a character, an object, or an existing image. Choose
|
|
72
|
+
Retro Diffusion when a GIF or spritesheet from one prompt fits, an RD style is
|
|
73
|
+
the desired look, or a USD quote is easier to budget. For a production batch,
|
|
73
74
|
run one representative asset through the selected provider before expanding the
|
|
74
75
|
scope.
|
|
75
76
|
|
|
@@ -96,9 +97,12 @@ the same graph and still differ because their checkpoint bytes, custom nodes,
|
|
|
96
97
|
or sampler settings differ. Commit the workflow and record the model stack used
|
|
97
98
|
to test it.
|
|
98
99
|
|
|
99
|
-
The revision manifest and dependency gate are provider-neutral
|
|
100
|
-
|
|
101
|
-
|
|
100
|
+
The revision manifest and dependency gate are provider-neutral. ComfyUI and
|
|
101
|
+
PixelLab opt in; Retro Diffusion and Scenario reject revision assets offline.
|
|
102
|
+
PixelLab covers `image-to-image`, `inpaint`, `reduce-colors`,
|
|
103
|
+
`correct-pixelart`, `animate`, `animate-pixminimax`, `animate-skeleton`,
|
|
104
|
+
`interpolate`, and `edit-animation`, but not `outpaint`. ComfyUI covers the
|
|
105
|
+
single-image modes through its workflow bindings. See
|
|
102
106
|
[Controlled asset revisions](./docs/REVISIONS.md) before using the bundled
|
|
103
107
|
square image-to-image graph.
|
|
104
108
|
|
|
@@ -131,7 +135,7 @@ background. That distinction matters more than raw canvas size.
|
|
|
131
135
|
| Asset type | PixelLab | Retro Diffusion | ComfyUI | Scenario |
|
|
132
136
|
|---|---|---|---|---|
|
|
133
137
|
| Isolated house, building, mountain, or landmark | Start with `map`: arbitrary dimensions up to 400×400 and a measured one-generation cost. Live benchmark outputs had opaque backgrounds, so plan for cleanup. Use `1dir` only when references or candidate variety justify 20–40 generations and a square canvas. | Start with `rd_plus__topdown_asset`, `rd_plus__isometric_asset`, or `rd_tile__scene_object`, depending on perspective. `rd_tile__scene_object` is intended for 64–384px objects placed on tile maps. | Choose a checkpoint or LoRA trained for the intended perspective, then keep background removal or segmentation in the workflow. For the tested Pixel Art XL stack, target 48–128px native components even though the adapter accepts larger working canvases. | The live BFL smoke produced a readable 512px keep, but it was opaque and used 19,619 colors. Use that profile for concepts or refinement input, not a finished limited-palette asset. A project-specific model may improve consistency but needs its own smoke. |
|
|
134
|
-
| Full scenic background | Use `pixflux` with `noBackground: false` when an exact palette matters, or `map` for a simple scene
|
|
138
|
+
| Full scenic background | Use `pixflux` with `noBackground: false` when an exact palette matters, or `map` for a simple scene; both top out at 400×400. `imagePro` reaches 792 wide or 688 tall for a flat 40 generations. | `rd_plus__environment` targets one-point-perspective scenes; `rd_plus__topdown_map` targets 3/4 top-down maps. These styles support up to 384×384. | Use composition controls only to establish the scene. Recover and review native components, then compose them at 1× with one grid and palette. A large model canvas is not a large native pixel-art canvas. | The BFL profile accepts canvases up to 2048px, but no Scenario scenic brief has passed the shared benchmark. Treat that as model-canvas capacity, not native pixel resolution. Start with one 512px concept before raising size or steps. |
|
|
135
139
|
| Style consistency across a set | `1dir` accepts a style reference and returns size-dependent candidates, but it is more expensive and capped at the square-object range. | RD Pro accepts up to nine references and has stronger prompt following, but its common styles top out at 256×256 and cost $0.18 per image. Environment-specific RD Plus styles trade references for a larger 384px canvas. | LoRAs, reference adapters, ControlNet, and shared latent settings can live in the committed workflow. Reproducibility also depends on external model and custom-node versions. | Scenario's project models and LoRAs are the main reason to use it for a set. PixelKiln can pin the model ID and parameters, but its first live run covers only the public BFL profile. |
|
|
136
140
|
| Very large final scene | Generate reusable objects, terrain, and background layers separately; assemble them deterministically and integer-upscale the result. | Use the same layered approach. The API has a 512px overall ceiling, but the useful environment and scene-object styles currently cap at 384px. | The graph can tile, upscale, or composite beyond hosted-provider limits, but memory and seam quality become workflow concerns. Prefer reusable layers unless the scene truly needs one render. | Scenario can request a larger raster from a compatible model, but the same rule applies: generate reusable layers at their useful native detail, compose at 1×, and integer-upscale only the final scene. |
|
|
137
141
|
|
|
@@ -194,18 +198,29 @@ not share one runtime.
|
|
|
194
198
|
The services use different billing units, so PixelKiln never adds their costs
|
|
195
199
|
together.
|
|
196
200
|
|
|
197
|
-
PixelLab figures below
|
|
198
|
-
|
|
201
|
+
PixelLab figures below come from the endpoints PixelKiln currently uses. Rows
|
|
202
|
+
marked unmeasured or quoted are `plan` estimates, not bills. None is a
|
|
203
|
+
conversion to dollars:
|
|
199
204
|
|
|
200
|
-
| PixelLab route |
|
|
205
|
+
| PixelLab route | Cost |
|
|
201
206
|
|---|---:|
|
|
202
207
|
| `map` | 1 generation |
|
|
203
208
|
| `pixflux` | 1 generation |
|
|
204
209
|
| `1dir` | 20–40 generations |
|
|
210
|
+
| `imagePro` | 40 generations |
|
|
211
|
+
| `imageProFlash` | 5–9 generations (provisional quote) |
|
|
205
212
|
| `tiles` | 20–40 generations |
|
|
206
|
-
| `
|
|
207
|
-
| `
|
|
213
|
+
| `terrain` | 20–40 generations (unmeasured) |
|
|
214
|
+
| `isometricTile` | 1 generation (measured once) |
|
|
215
|
+
| `character` base | 1 (standard), 2–9 (v3), 20–40 (pro), 6–17 (pro-flash; rotations only from a reference) |
|
|
216
|
+
| `character` state or portrait | 20–40 generations |
|
|
208
217
|
| `character` animation | 1 (template), 1 at 64px from text, 20–40 (pro) |
|
|
218
|
+
| `character` outfit | 20 generations (one 2-frame, 92×92 job) |
|
|
219
|
+
| `objectPro` base | 6 at 64px (unmeasured) |
|
|
220
|
+
| `uiAsset` | 20 generations (measured once, at 256×192) |
|
|
221
|
+
| `uiElement` | 20–40 generations (unmeasured) |
|
|
222
|
+
| `image-to-image` / `inpaint` revision | 20–40 generations; 5–9 with `engine: "pro-flash"` (provisional quote) |
|
|
223
|
+
| `reduce-colors` / `correct-pixelart` revision | 0.1 generations (measured at 32×32) |
|
|
209
224
|
|
|
210
225
|
Retro Diffusion publishes USD formulas and fixed prices. Examples relevant to
|
|
211
226
|
PixelKiln include RD Fast from about $0.015 per image, RD Plus from about $0.025,
|
package/README.md
CHANGED
|
@@ -53,8 +53,9 @@ provenance and no long-lived npm token.
|
|
|
53
53
|
| Plan and budget | Offline manifest/lock/disk diff, provider-grouped estimates, keyed mixed-provider budget ceilings, JSON/CI gate. |
|
|
54
54
|
| Generate and review | Resumable submit/poll/pick/fetch pipeline, exact next-step hints, candidate or atomic frame-set review, and a provenance gallery that can edit intent, generate under a budget, and compare records. |
|
|
55
55
|
| Hand edits | Touch-ups in your own editor or a pinned in-browser Pixelorama, kept beside the generated art with the generation still the record; frame and tile sets member by member. |
|
|
56
|
-
| Controlled inputs | Hashed image-to-image
|
|
57
|
-
| Characters | A base in 4 or 8 directions from a prompt or your own sprite (four PixelLab engines), poses and
|
|
56
|
+
| Controlled inputs | Hashed revision lineage (image-to-image and inpaint; on PixelLab also palette reduction, pixel cleanup, animation, skeleton posing, interpolation, and animation edits), fail-closed parent approval, source-versus-candidate review, and content-addressed per-asset ComfyUI bindings. |
|
|
57
|
+
| Characters | A base in 4 or 8 directions from a prompt or your own sprite (four PixelLab engines), poses, loops, portraits, and outfit transfers as dependent assets generated in waves, free mirrored directions (one `directions` list declares a loop and mirrors the rest), account adoption and salvage, and SpriteFrames export. |
|
|
58
|
+
| PixelLab utilities | `unzoom` returns upscaled reference art to its native grid, `font` generates a `.ttf` and glyph atlas, and `estimate-skeleton` starts a keypoints file for skeleton animation. |
|
|
58
59
|
| Existing-art onboarding | Manifest scaffolding, exact-hash account adoption, and prompt recovery. |
|
|
59
60
|
| Recovery | Safe stale-output replacement, validated caches, durable references, resumable paid jobs, and per-asset generation history with free restores. |
|
|
60
61
|
| Shared-account safety | Cross-project claim files or a registered workspace catalog, sibling-style exclusion, reviewed salvage, keep/discard tags, separate confirmed purge. |
|
|
@@ -258,18 +259,17 @@ Measured PixelLab economics vary by 40×:
|
|
|
258
259
|
| Independent or connectable ground tiles | `tiles` | 20–40 generations |
|
|
259
260
|
| A character in 4 or 8 directions, its poses, its loops | `character` | 1 per base, 20–40 per pose, 1 per template loop per direction; a `mirror` of a loop is free |
|
|
260
261
|
|
|
261
|
-
Start with the required capability, not the most expensive endpoint. Forty
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
[measured endpoint reference](./docs/ENDPOINTS.md).
|
|
262
|
+
Start with the required capability, not the most expensive endpoint. Forty `map`
|
|
263
|
+
re-rolls cost the same as one 64×64 `1dir` call; conversely, `map` cannot replace a
|
|
264
|
+
hard palette or reference-image constraint. PixelLab has seven more generators
|
|
265
|
+
(`imagePro`, `imageProFlash`, `terrain`, `isometricTile`, `objectPro`, `uiAsset`,
|
|
266
|
+
`uiElement`); see [Generator selection](./docs/GENERATORS.md) and the [measured endpoint reference](./docs/ENDPOINTS.md).
|
|
266
267
|
|
|
267
|
-
Generator names describe PixelKiln workflows; their exact capabilities and
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
Compare the adapters in the [provider comparison](./PROVIDERS.md).
|
|
268
|
+
Generator names describe PixelKiln workflows; their exact capabilities and prices
|
|
269
|
+
depend on the selected provider. Retro Diffusion also supports the provider-specific
|
|
270
|
+
`animation` generator. ComfyUI supports `map` plus atomic still-image `frames` through
|
|
271
|
+
an operator-supplied workflow. Scenario supports `map` with a required offline CU
|
|
272
|
+
ceiling and a live quote before each paid call. Compare the adapters in the [provider comparison](./PROVIDERS.md).
|
|
273
273
|
|
|
274
274
|
## Derived artifacts
|
|
275
275
|
|
|
@@ -368,12 +368,13 @@ verification. See [Library API](./docs/LIBRARY.md).
|
|
|
368
368
|
| [Set up ComfyUI](./docs/COMFYUI.md) | Self-hosted stills, revisions, ordered frame sets, per-asset inputs, and quality limits. |
|
|
369
369
|
| [Set up Scenario](./docs/SCENARIO.md) | Experimental hosted models, two-part credentials, CU preflight, review, and durable downloads. |
|
|
370
370
|
| [Versioned recipes](./docs/RECIPES.md) | Pinned workflow packs, model hashes, manifest templates, and quality contracts. |
|
|
371
|
-
| [Controlled revisions](./docs/REVISIONS.md) | Image-to-image
|
|
371
|
+
| [Controlled revisions](./docs/REVISIONS.md) | Image-to-image, inpaint, palette cleanup, animation, and interpolation from a parent; masks, fail-closed readiness, provenance, and ComfyUI bindings. |
|
|
372
372
|
| [CLI reference](./docs/CLI.md) | Every command, flag, JSON mode, and exit contract. |
|
|
373
373
|
| [Manifest reference](./docs/MANIFEST.md) | Style/asset fields, quality profiles, and generator constraints. |
|
|
374
374
|
| [Mixed-provider projects](./docs/MIXED_PROVIDERS.md) | Per-style routing, provider-keyed budgets, recovery, and account commands. |
|
|
375
375
|
| [Agent workflows](./docs/AGENTS.md) | Official skill install, operating model, and provider-aware safety. |
|
|
376
376
|
| [Generators](./docs/GENERATORS.md) | Capability choice, measured costs, palettes, style references, and tiles. |
|
|
377
|
+
| [Characters](./docs/CHARACTERS.md) | Bases, states, loops, mirrors, portraits, outfits, the `directions` shorthand, and per-engine costs. |
|
|
377
378
|
| [Environment provider benchmark](./docs/PROVIDER_BENCHMARK.md) | Thirty provider outputs plus native-grid and final-palette results comparing large scenes, transparency, palette size, and file readiness. |
|
|
378
379
|
| [Derived artifacts](./docs/ARTIFACTS.md) | Refine, pack, mount, export, provenance, ownership, transactions, and recovery. |
|
|
379
380
|
| [Recovery](./docs/RECOVERY.md) | Restore, caches, adopt, salvage, claims, and purge safety. |
|
|
@@ -384,10 +385,9 @@ verification. See [Library API](./docs/LIBRARY.md).
|
|
|
384
385
|
| [Endpoint research](./docs/ENDPOINTS.md) | Measured PixelLab API behavior and recipes. |
|
|
385
386
|
| [Provider comparison](./PROVIDERS.md) | Provider selection, costs, supported workflows, confidence, and limitations. |
|
|
386
387
|
|
|
387
|
-
The [public documentation site](https://pixelkiln.griffen.codes/docs) is built from
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
[Security](./SECURITY.md), [provider comparison](./PROVIDERS.md).
|
|
388
|
+
The [public documentation site](https://pixelkiln.griffen.codes/docs) is built from these Markdown
|
|
389
|
+
files by [`website/`](./website/README.md), so the site and the package share one source.
|
|
390
|
+
Policies: [Contributing](./CONTRIBUTING.md), [Security](./SECURITY.md).
|
|
391
391
|
|
|
392
392
|
## Scope
|
|
393
393
|
|
package/dist/cli.js
CHANGED
|
@@ -689,6 +689,11 @@ function specHash(spec, styleImageHashes, providerOptionIdentity = spec.provider
|
|
|
689
689
|
uiPieces: spec.uiPieces,
|
|
690
690
|
uiElements: spec.uiElements,
|
|
691
691
|
uiColorPalette: spec.uiColorPalette,
|
|
692
|
+
// Scene and mask enter as their bytes' hashes, never their paths.
|
|
693
|
+
scene: spec.scene ? {
|
|
694
|
+
image: spec.scene.sha256,
|
|
695
|
+
placement: spec.scene.placement.type === "mask" ? { type: "mask", mask: spec.scene.placement.sha256 } : spec.scene.placement
|
|
696
|
+
} : void 0,
|
|
692
697
|
styleTraits: spec.styleTraits,
|
|
693
698
|
styleImages: styleImageHashes,
|
|
694
699
|
// A character family: the engine and rotations of a base, the parent's
|
|
@@ -987,6 +992,16 @@ var CharacterPortraitSchema = z.object({
|
|
|
987
992
|
of: z.string().min(1),
|
|
988
993
|
size: CharacterPortraitSizeSchema.default(64)
|
|
989
994
|
}).strict();
|
|
995
|
+
var MapScenePlacementSchema = z.union([
|
|
996
|
+
z.object({ oval: z.number().min(0.05).max(0.95) }).strict(),
|
|
997
|
+
z.object({ rectangle: z.number().min(0.05).max(0.95) }).strict(),
|
|
998
|
+
z.object({ mask: z.string().min(1) }).strict()
|
|
999
|
+
]);
|
|
1000
|
+
var MapSceneSchema = z.object({
|
|
1001
|
+
/** Manifest-relative PNG of the scene. Any earlier asset's output file works. */
|
|
1002
|
+
image: z.string().min(1),
|
|
1003
|
+
placement: MapScenePlacementSchema.default({ oval: 0.3 })
|
|
1004
|
+
}).strict();
|
|
990
1005
|
var CharacterOutfitSchema = z.object({
|
|
991
1006
|
/** The loop (a character animation asset) to re-clothe, in the same style. */
|
|
992
1007
|
of: z.string().min(1),
|
|
@@ -1681,6 +1696,8 @@ var AssetSchema = z.object({
|
|
|
1681
1696
|
portrait: CharacterPortraitSchema.optional(),
|
|
1682
1697
|
/** `character` styles: this asset re-clothes an existing loop's frames with a reference outfit. */
|
|
1683
1698
|
outfit: CharacterOutfitSchema.optional(),
|
|
1699
|
+
/** `map` styles only: draw this object in the style of a scene image. See `MapSceneSchema`. */
|
|
1700
|
+
scene: MapSceneSchema.optional(),
|
|
1684
1701
|
/** `character` styles, `standard` humanoid bases: this character's proportions, over the style's. */
|
|
1685
1702
|
proportions: CharacterProportionsSchema.optional(),
|
|
1686
1703
|
/**
|
|
@@ -1757,7 +1774,7 @@ var AssetSchema = z.object({
|
|
|
1757
1774
|
path: ["revision"]
|
|
1758
1775
|
});
|
|
1759
1776
|
}
|
|
1760
|
-
const shapes = [asset.revision && "revision", asset.state && "state", asset.animation && "animation", asset.mirror && "mirror", asset.batch && "batch", asset.portrait && "portrait", asset.outfit && "outfit"].filter(Boolean);
|
|
1777
|
+
const shapes = [asset.revision && "revision", asset.state && "state", asset.animation && "animation", asset.mirror && "mirror", asset.batch && "batch", asset.portrait && "portrait", asset.outfit && "outfit", asset.scene && "scene"].filter(Boolean);
|
|
1761
1778
|
if (shapes.length > 1) {
|
|
1762
1779
|
context.addIssue({
|
|
1763
1780
|
code: z.ZodIssueCode.custom,
|
|
@@ -4212,6 +4229,7 @@ async function inspectRevisionReadiness(spec, lock) {
|
|
|
4212
4229
|
if (spec.character?.parentSpec) return inspectCharacterParent(spec, lock, /* @__PURE__ */ new Set());
|
|
4213
4230
|
if (spec.character?.styleAnchor) return inspectStyleAnchor(spec, lock, /* @__PURE__ */ new Set());
|
|
4214
4231
|
if (spec.objectPro?.parentSpec) return inspectObjectProParent(spec, lock, /* @__PURE__ */ new Set());
|
|
4232
|
+
if (spec.scene) return inspectScene(spec);
|
|
4215
4233
|
if (!spec.revision) return null;
|
|
4216
4234
|
return inspectRevision(spec, lock, /* @__PURE__ */ new Set());
|
|
4217
4235
|
}
|
|
@@ -4229,6 +4247,16 @@ async function inspectStyleAnchor(spec, lock, seen) {
|
|
|
4229
4247
|
}
|
|
4230
4248
|
return { ready: true, reason: `${label} is current` };
|
|
4231
4249
|
}
|
|
4250
|
+
async function inspectScene(spec) {
|
|
4251
|
+
const scene = spec.scene;
|
|
4252
|
+
const files = [{ label: "scene image", file: scene.file, sha256: scene.sha256 }];
|
|
4253
|
+
if (scene.placement.type === "mask") files.push({ label: "scene mask", file: scene.placement.file, sha256: scene.placement.sha256 });
|
|
4254
|
+
for (const { label, file, sha256: sha2562 } of files) {
|
|
4255
|
+
if (!sha2562 || !existsSync4(file)) return { ready: false, reason: `${label} does not exist yet: ${file}` };
|
|
4256
|
+
if (await sha256File(file) !== sha2562) return { ready: false, reason: `${label} changed after the manifest was resolved` };
|
|
4257
|
+
}
|
|
4258
|
+
return { ready: true, reason: "scene is current" };
|
|
4259
|
+
}
|
|
4232
4260
|
async function inspectMirror(spec, lock, seen) {
|
|
4233
4261
|
const source = spec.mirror.sourceSpec;
|
|
4234
4262
|
const label = `mirror source ${spec.styleId}/${spec.mirror.sourceAssetId}`;
|
|
@@ -6136,6 +6164,12 @@ var PixelLabClient = class {
|
|
|
6136
6164
|
if (args.shading) body.shading = args.shading;
|
|
6137
6165
|
if (args.detail) body.detail = args.detail;
|
|
6138
6166
|
if (args.seed != null) body.seed = args.seed;
|
|
6167
|
+
if (args.scene) {
|
|
6168
|
+
const encode = (image) => ({ type: "base64", base64: image.base64, format: image.format });
|
|
6169
|
+
const placement = args.scene.placement;
|
|
6170
|
+
body.background_image = encode(args.scene.image);
|
|
6171
|
+
body.inpainting = placement.type === "mask" ? { type: "mask", mask_image: encode(placement.mask) } : { type: placement.type, fraction: placement.fraction };
|
|
6172
|
+
}
|
|
6139
6173
|
return validateResponse(
|
|
6140
6174
|
MapSubmitSchema,
|
|
6141
6175
|
await this.request("/map-objects", { method: "POST", body: JSON.stringify(body) }),
|
|
@@ -7297,6 +7331,8 @@ var PixelLabProvider = class _PixelLabProvider {
|
|
|
7297
7331
|
supports(generator) {
|
|
7298
7332
|
return generator === "1dir" || generator === "map" || generator === "pixflux" || generator === "tiles" || generator === "terrain" || generator === "imagePro" || generator === "character" || generator === "isometricTile" || generator === "objectPro" || generator === "uiAsset" || generator === "uiElement" || generator === "imageProFlash";
|
|
7299
7333
|
}
|
|
7334
|
+
/** `/map-objects` style matching: `background_image` plus `inpainting`. */
|
|
7335
|
+
supportsMapScene = true;
|
|
7300
7336
|
/**
|
|
7301
7337
|
* `inpaint` (`/inpaint-v3`, a mask) and `image-to-image` (`/edit-images-v2`,
|
|
7302
7338
|
* no mask) both exist on PixelLab, and so do `reduce-colors`
|
|
@@ -8442,7 +8478,8 @@ var PixelLabProvider = class _PixelLabProvider {
|
|
|
8442
8478
|
outline: spec.outline,
|
|
8443
8479
|
shading: spec.shading,
|
|
8444
8480
|
detail: spec.detail,
|
|
8445
|
-
seed: spec.seed
|
|
8481
|
+
seed: spec.seed,
|
|
8482
|
+
scene: spec.scene ? mapScenePayload(spec) : void 0
|
|
8446
8483
|
});
|
|
8447
8484
|
return { jobId: res.object_id, metadata: { backgroundJobId: res.background_job_id } };
|
|
8448
8485
|
}
|
|
@@ -9319,6 +9356,21 @@ function findObjectAnimation(object, name, direction, animationId) {
|
|
|
9319
9356
|
}
|
|
9320
9357
|
return null;
|
|
9321
9358
|
}
|
|
9359
|
+
function mapScenePayload(spec) {
|
|
9360
|
+
const scene = spec.scene;
|
|
9361
|
+
const read = (file, hash, label) => {
|
|
9362
|
+
const bytes = readFileSync2(file);
|
|
9363
|
+
if (!hash || sha256(bytes) !== hash) {
|
|
9364
|
+
throw new Error(`${spec.styleId}/${spec.assetId}: ${label} changed after the manifest was resolved`);
|
|
9365
|
+
}
|
|
9366
|
+
return { base64: bytes.toString("base64"), format: "png" };
|
|
9367
|
+
};
|
|
9368
|
+
const placement = scene.placement;
|
|
9369
|
+
return {
|
|
9370
|
+
image: read(scene.file, scene.sha256, "scene image"),
|
|
9371
|
+
placement: placement.type === "mask" ? { type: "mask", mask: read(placement.file, placement.sha256, "scene mask") } : placement
|
|
9372
|
+
};
|
|
9373
|
+
}
|
|
9322
9374
|
|
|
9323
9375
|
// src/providers/retrodiffusion.ts
|
|
9324
9376
|
var DEFAULT_BASE_URL2 = "https://api.retrodiffusion.ai/v1";
|
|
@@ -11021,6 +11073,7 @@ async function resolveSpecs(loaded, filter) {
|
|
|
11021
11073
|
};
|
|
11022
11074
|
}
|
|
11023
11075
|
}
|
|
11076
|
+
if (asset.scene) resolved.scene = await resolveMapScene(root, styleId, assetId, resolved.generator, asset.scene, activeProvider);
|
|
11024
11077
|
resolved.specHash = specHash(
|
|
11025
11078
|
resolved,
|
|
11026
11079
|
styleImageHashes,
|
|
@@ -11079,6 +11132,32 @@ function pngPath(file) {
|
|
|
11079
11132
|
const extension = path13.extname(file);
|
|
11080
11133
|
return extension ? `${file.slice(0, -extension.length)}.png` : `${file}.png`;
|
|
11081
11134
|
}
|
|
11135
|
+
async function resolveMapScene(root, styleId, assetId, generator, scene, provider) {
|
|
11136
|
+
if (generator !== "map") {
|
|
11137
|
+
throw new Error(`assets.${assetId}.scene: only a map object can be drawn into a scene; style "${styleId}" uses "${generator}"`);
|
|
11138
|
+
}
|
|
11139
|
+
if (!provider.supportsMapScene) {
|
|
11140
|
+
throw new Error(`assets.${assetId}.scene: provider "${provider.id}" cannot draw into a scene; PixelLab's /map-objects can`);
|
|
11141
|
+
}
|
|
11142
|
+
const file = path13.resolve(root, scene.image);
|
|
11143
|
+
const image = await optionalRevisionImage(file, "scene image", "png");
|
|
11144
|
+
const base = { file, sha256: image?.hash ?? null, width: image?.width ?? null, height: image?.height ?? null };
|
|
11145
|
+
const placement = scene.placement;
|
|
11146
|
+
if ("mask" in placement) {
|
|
11147
|
+
const maskFile = path13.resolve(root, placement.mask);
|
|
11148
|
+
const mask = await optionalRevisionImage(maskFile, "scene mask", "png");
|
|
11149
|
+
if (image && mask && (image.width !== mask.width || image.height !== mask.height)) {
|
|
11150
|
+
throw new Error(
|
|
11151
|
+
`assets.${assetId}.scene: the mask is ${mask.width}x${mask.height}; the scene ${scene.image} is ${image.width}x${image.height}`
|
|
11152
|
+
);
|
|
11153
|
+
}
|
|
11154
|
+
return {
|
|
11155
|
+
...base,
|
|
11156
|
+
placement: { type: "mask", file: maskFile, sha256: mask?.hash ?? null, width: mask?.width ?? null, height: mask?.height ?? null }
|
|
11157
|
+
};
|
|
11158
|
+
}
|
|
11159
|
+
return "oval" in placement ? { ...base, placement: { type: "oval", fraction: placement.oval } } : { ...base, placement: { type: "rectangle", fraction: placement.rectangle } };
|
|
11160
|
+
}
|
|
11082
11161
|
async function optionalRevisionImage(file, label, requiredFormat) {
|
|
11083
11162
|
if (!existsSync8(file)) return null;
|
|
11084
11163
|
const bytes = await readFile6(file);
|