Build a project from a script¶
Every part of a CookBook can be created and changed without the app: from manifests and PNGs, or by editing an existing archive in place. Use this to generate projects from a pipeline, or to make bulk changes. For a guided first run, see Your first collection from the command line.
How a project is assembled¶
Archives nest, and you build them from the inside out:
PNGs + ingredient manifest ──new ingredient──▶ layer.igt
.igt files + recipe manifest ──new recipe──────▶ type.rcp
.rcp files + book manifest ──new cookbook────▶ book.cbk
Files are found by id: a variant glow is <images>/glow.png, a layer aura in layerOrder is
<ingredients>/aura.igt, a Recipe cat in recipeWeights is <recipes>/cat.rcp.
The manifests¶
Ingredient (new ingredient out.igt --manifest m.json --images <dir>):
{
"id": "bg",
"name": "Background",
"kind": "dynamic",
"colorization": {
"model": "hsv",
"hueQuantize": 30,
"satQuantize": 25,
"entries": [
{ "weight": 60, "range": { "hueMin": 15, "hueMax": 45, "satMin": 35, "satMax": 80 }, "fixed": null },
{ "weight": 40, "range": { "hueMin": 190, "hueMax": 250, "satMin": 5, "satMax": 30 }, "fixed": null }
]
},
"variants": [
{ "id": "plain", "name": "Plain", "weight": 3 },
{ "id": "stripes", "name": "Stripes", "weight": 1 }
],
"schemaVersion": 2
}
| Field | Rules |
|---|---|
kind |
dynamic, static or custom. |
colorization |
null for custom. Otherwise model (hsv or hsl), the two quantize steps, and entries. |
entries |
Each has a weight, and exactly one of range (Dynamic) or fixed (a color spec, Static); the other is null. A Static layer has one entry. |
range |
Hue in degrees 0 to 360, saturation in percent 0 to 100. Half-open: the maximum itself is never rolled. |
variants |
Each id names <id>.png. Weights are relative; 0 shelves a variant. |
Recipe (new recipe out.rcp --manifest m.json --ingredients <dir>):
{
"id": "chest",
"name": "Chest",
"layerOrder": ["glow", "feet", "body", "bands", "trim", "lock"],
"rules": [
{
"type": "exclude",
"when": { "ingredientId": "body", "variantId": "stone" },
"targets": [ { "ingredientId": "lock", "variantId": "keypad" } ]
}
],
"absentPercent": { "trim": 55, "glow": 72 },
"schemaVersion": 2
}
layerOrder is bottom to top. rules is required (use []); type is exclude or require.
absentPercent is optional.
CookBook (new cookbook out.cbk --manifest m.json --recipes <dir>):
{
"id": "chestdemo",
"name": "Chest Demo",
"canvas": { "width": 32, "height": 32 },
"collection": { "name": "Chest Demo", "description": "Layered chests.", "symbol": "CHST" },
"recipeWeights": { "chest": 65, "strongbox": 35 },
"targetSupply": 1200,
"palette": ["hex:8a5a2b", "hex:c9a227"],
"schemaVersion": 2
}
targetSupply and palette are optional. new cookbook validates and refuses a broken book unless
you pass --force (it prints the problems as warnings; generate still refuses the book).
A kitchen needs no manifest: nfty new kitchen Studio.ktn --name Studio.
Change an archive in place¶
Each of these validates the result before writing and replaces the file atomically.
| To | Command | Works on |
|---|---|---|
| Add a variant | add variant x.igt --id spark --weight 30 --image spark.png [--name Spark] |
.igt |
| Add a layer | add ingredient x.rcp --igt aura.igt [--index N] (0-based; default the top) |
.rcp |
| Add a Recipe | add recipe book.cbk --rcp cat.rcp --weight 60 |
.cbk |
| Add a rule | add rule x.rcp --type exclude --when bg:night --then glow:sparks [--then …] |
.rcp |
| Remove a rule | remove rule x.rcp --at 2 (1-based, as inspect lists) |
.rcp |
| Remove a layer | remove ingredient book.cbk --recipe cat --id aura (also drops its absent chance and every rule naming it) |
.cbk or .rcp |
| Remove a variant | remove variant book.cbk --recipe cat --ingredient aura --id spark (not a layer's last) |
.cbk or .igt |
| Remove a Recipe | remove recipe book.cbk --id fox |
.cbk |
| Move a layer | move ingredient x.rcp --id aura --to 2 or --up / --down |
.rcp |
| Move a Recipe in the listing | move recipe book.cbk --id fox --to 1 |
.cbk |
| Change a variant weight | set variant book.cbk --recipe cat --ingredient aura --id spark --weight 5 (above zero) |
.cbk or .igt |
| Change a Recipe weight | set recipe book.cbk --id fox --weight 0 (0 shelves it) |
.cbk |
| Set an absent chance | set chance x.rcp --id hat --absent 90 |
.rcp |
| Change names and supply | set cookbook book.cbk --name … --collection-name … --symbol … --description … --target-supply 1200\|none |
.cbk |
| Set depth | set depth x.igt --variant stone --map stone-depth.png |
.igt |
| Snap soft edges | set voxel-ready book.cbk [--dry-run] |
.cbk |
On a .cbk, commands that reach inside a Recipe or Ingredient need --recipe (and --ingredient);
on the loose part they are refused. Rules, absent chances and layer moves work on loose .rcp files,
so edit those and re-assemble the book, or make those changes in the app.
Import pictures with a color profile¶
new ingredient and add variant convert a picture with a non-sRGB embedded profile (Display P3,
Adobe RGB) to sRGB and print one line saying so. --keep-profile imports the pixels as stored. A
profile nfty cannot convert is named on stderr and the picture imported as is.