Skip to content

LayerDepth

Namespace Nfty.Core.Editing in assembly Nfty.Core.

public static class LayerDepth

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)

public static string At(RecipeManifest recipe, int depth);

The layer sitting at a given depth.

Parameters

  • recipe (RecipeManifest) - The recipe to read.
  • depth (int) - A 1-based depth, from 1 (bottom) to LayerDepth.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)

public static int Count(RecipeManifest recipe);

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)

public static int DepthOf(RecipeManifest recipe, string ingredientId);

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)

public static RecipeManifest MoveBy(RecipeManifest recipe, string ingredientId, int delta);

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)

public static RecipeManifest MoveTo(RecipeManifest recipe, string ingredientId, int depth);

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)

public static IReadOnlyList<(int, string)> Ordered(RecipeManifest recipe);

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.