PixelWeaver v0.5.0 /server.src.pixelweaver.layer_tree
On this page

Recursive, schema-neutral traversal helpers for the authoritative layer tree of pixel and role leaves and nested groups, mirroring the client's layer-tree model.

#server.src.pixelweaver.layer_tree

#server.src.pixelweaver.layer_tree

Recursive traversal helpers for the authoritative layer tree.

The server layer model mirrors the client (src/lib/layers/layer-tree.svelte.ts): canvas.layers is an ordered list (bottom-to-top) whose entries are either pixel/role LEAF layers or GROUP dicts. A group carries type == "group", a children list, and an expanded flag; leaves carry type == "pixel" (absent type is treated as a leaf for forward-compatibility with pre-tree saves).

A FLAT list is simply a tree with every leaf at the root -- which is why projects saved before groups existed load untouched (the load-time migration is a no-op transform: a flat list already IS a valid root-level tree).

Every function here is schema-neutral: it takes the raw list[dict] layer list (or a CanvasState's .layers) and never mutates unless documented.

#is_group

python
def is_group(layer: dict[str, Any]) -> bool

Whether layer is a group node (has children).

#iter_layers

python
def iter_layers(layers: list[dict[str, Any]]) -> Iterator[dict[str, Any]]

Yield every node depth-first (a group is yielded before its children).

#iter_leaves

python
def iter_leaves(layers: list[dict[str, Any]]) -> Iterator[dict[str, Any]]

Yield only non-group LEAF layers, depth-first (bottom-to-top order).

#leaf_ids

python
def leaf_ids(layers: list[dict[str, Any]]) -> list[str]

Every leaf layer id in depth-first order.

#all_ids

python
def all_ids(layers: list[dict[str, Any]]) -> list[str]

Every node id (groups + leaves) in depth-first order.

#find_layer

python
def find_layer(layers: list[dict[str, Any]], layer_id: str) -> dict[str, Any] | None

Find a layer dict by id anywhere in the tree (groups included).

#LayerContext

Where a layer sits: the node, its live sibling list, its index, and the id of the enclosing group (None for a root-level layer).

#find_context

python
def find_context(layers: list[dict[str, Any]], layer_id: str, parent_id: str | None=None) -> LayerContext | None

Find a layer and its parent array by id, searching the whole tree.

Mirrors the client findLayerContext: siblings is the LIVE list the layer lives in (mutating it mutates the tree), parent_id is the enclosing group's id or None at the root.

#resolve_children

python
def resolve_children(layers: list[dict[str, Any]], parent_id: str | None) -> list[dict[str, Any]]

Return the live child list for parent_id (None => root list).

Hard error if parent_id names a missing layer or a non-group. A group with a missing children key is initialized to [] so callers can splice into the live list.

#any_role_leaf

python
def any_role_leaf(layers: list[dict[str, Any]]) -> bool

Whether any LEAF layer in the tree is role-kind.

#validate_tree

python
def validate_tree(layers: Any) -> None

Hard error on structurally corrupt layer-tree data (load-time guard).

A flat list is valid (all leaves at root). Corruption = a non-dict node, a node missing a string id, a group whose children is not a list, a leaf carrying a children list, or a duplicate id anywhere in the tree.

Search