LayerDepth¶
Namespace Nfty.Core.Editing in assembly Nfty.Core.
Depth, as a projection of RecipeManifest.LayerOrder: 1-based, dense, and bottom-first — depth 1 is the layer that paints first, and everything above paints over it.
There is no stored depth field, deliberately. An integer z on the manifest would make two layers at the same depth expressible, which is the very collision depth was asked for to prevent; it would then need a Validator rule, a tie-break for every archive already on disk, and an absent-default on every read path — the same cost every optional field pays for the floor schema it was added after. A list makes the illegal state unrepresentable rather than merely invalid. So layerOrder stays authoritative — it is already what Generator walks and what Compositor draws — and depth is that same field read a second way. Nothing here can drift out of agreement with paint order, because there is no second structure to drift.
Consequences worth stating: no manifest changes and Schema.Current does not move; and inserting or moving a layer renumbers the ones it passes, because the numbering is positional.
Pure: every operation takes a manifest and returns a new one via with. It never mutates, never touches an image, and never looks at the recipe's ingredient collection — which is what lets both front-ends share it. Reordering preserves the exact set of ids, so the strict bijection between layerOrder and the ingredients that Validator enforces survives every move: a move can neither drop an id nor duplicate one.
Methods¶
At(RecipeManifest, int)¶
The layer sitting at a given depth.
Parameters
recipe(RecipeManifest) - The recipe to read.depth(int) - A 1-based depth, from 1 (bottom) toLayerDepth.Count()(top).
Returns. That layer's ingredient id.
Exceptions
ArgumentOutOfRangeException- The depth falls outside 1..LayerDepth.Count(). Reading throws where moving clamps: a caller asking "what is at depth 7?" of a five-layer stack has a bug, whereas a caller nudging the top layer upwards has a no-op.
Count(RecipeManifest)¶
How many layers the recipe stacks — the largest legal depth.
Parameters
recipe(RecipeManifest) - The recipe to measure.
Returns. The number of entries in the layer order; zero for a recipe with no layers.
DepthOf(RecipeManifest, string)¶
The 1-based depth of one layer, counting from the bottom of the stack.
Parameters
recipe(RecipeManifest) - The recipe that owns the layer.ingredientId(string) - The layer to locate.
Returns. 1 for the bottom layer, LayerDepth.Count() for the top one.
Exceptions
KeyNotFoundException- The recipe's layer order does not name that ingredient.
MoveBy(RecipeManifest, string, int)¶
Moves one layer by a relative number of steps: positive is up (towards the top of the stack), negative is down.
Parameters
recipe(RecipeManifest) - The recipe to reorder.ingredientId(string) - The layer to move.delta(int) - Steps to move; +1 is one layer up, -1 one layer down. The resulting depth is clamped to 1..LayerDepth.Count(), so a nudge off either end is a no-op.
Returns. A NEW manifest whose layer order holds exactly the same ids, reordered.
Exceptions
KeyNotFoundException- The recipe's layer order does not name that ingredient.
MoveTo(RecipeManifest, string, int)¶
Moves one layer to a depth, shifting every layer it passes by one to make room.
Parameters
recipe(RecipeManifest) - The recipe to reorder.ingredientId(string) - The layer to move.depth(int) - The 1-based depth to move it to. Clamped to 1..LayerDepth.Count()rather than rejected, so "move the top layer up" is a no-op the UI does not have to guard.
Returns. A NEW manifest whose layer order holds exactly the same ids, reordered.
Exceptions
KeyNotFoundException- The recipe's layer order does not name that ingredient.
Ordered(RecipeManifest)¶
The whole stack, bottom-to-top, each layer paired with its depth — the shape a UI binds a layer table to.
Parameters
recipe(RecipeManifest) - The recipe to read.
Returns. One entry per layer, in paint order, numbered densely from 1.