"""Render-2D item-pipeline: the build-once 2D renderer (design §2).
This subpackage holds the data structures + the live render path for the
build-once 2D render Item pipeline described in
``design/render_2d_architecture.md`` §2. It is the engine's only 2D renderer.
The pieces:
- :class:`ItemList` -- the flat struct-of-arrays (SoA) render-Item store
(§2.1, §2.4 design D-A): parallel typed numpy columns, add/remove/iterate,
and a vectorised stable-sort into draw order on ``(layer, z, seq)`` (§2.2).
- :class:`ClipScopeTable` -- the nested clip+transform scope table (§2.5) that
reproduces push/pop nesting once items live in one flat sorted list.
- :data:`PipelineKind`, :data:`BlendMode`, :data:`ItemFlags` -- the column
enums, kept compatible with ``draw2d_ops.OpKind``/``BLEND_MODES``.
- :class:`ItemBuilder` / :func:`build_item_list` -- the collection seam (§2.2):
walk a Node tree and *produce* an :class:`ItemList` (camera-free per-item
transforms, nested clip scopes, geometry handles), via the op-adapter bridge
that captures each node's ``on_draw``.
- :class:`RenderItemCache` / :class:`ViewState` -- the unified retention cache
(§2.7). **Frame level**: skips the walk + re-sort on a clean frame (dirty clean
+ view + theme unchanged + not ``dynamic``). **Item level (P2)**: a render-dirty
drawable re-captures only its ``on_draw`` and overwrites its geometry + item
columns in place (one item re-uploaded). **Transform-only level (P2)**: a moved
drawable rewrites its LOCAL transform row in place (the scroll/move fast path).
Invalidation is AUTOMATIC -- the cache reads the render-retention bits the core
``Drawable2D`` mixin carries on every 2D drawable, which the existing blanket
descriptor hook + observed-vec + on_change + theme-bridge + ``dynamic`` opt-out
set (the can't-forget-a-property contract).
- :class:`ItemPublisher` / :class:`PublishedItemView` -- the render-thread
publish/freeze + double-buffer (§4, P1.5): freeze the mutable game-thread store
into an immutable, GPU-uploadable snapshot the render thread reads, reusing the
SAME view object (zero-copy) on a clean frame.
"""
from .cache import RenderItemCache, ViewState
from .clip_scope import ROOT_CLIP_SCOPE, ClipScope, ClipScopeTable
from .item_builder import (
CollectResult,
Geometry,
GeometryStore,
ItemBuilder,
NodeEntry,
affine_row,
build_item_list,
)
from .item_list import (
BlendMode,
ItemFlags,
ItemList,
PipelineKind,
pack_sort_key,
unpack_sort_key,
)
from .publish import ItemPublisher, PublishedItemView, freeze_collect_result
from .submit import (
BindlessItemSubmitter,
CameraAffine,
ItemSubmitter,
build_bindless_geometry,
build_item_ops,
camera_affine_from_tree,
)
__all__ = [
"BindlessItemSubmitter",
"CameraAffine",
"ItemSubmitter",
"build_bindless_geometry",
"build_item_ops",
"camera_affine_from_tree",
"ROOT_CLIP_SCOPE",
"BlendMode",
"ClipScope",
"ClipScopeTable",
"CollectResult",
"Geometry",
"GeometryStore",
"ItemBuilder",
"ItemFlags",
"ItemList",
"ItemPublisher",
"NodeEntry",
"PipelineKind",
"PublishedItemView",
"RenderItemCache",
"ViewState",
"affine_row",
"build_item_list",
"freeze_collect_result",
"pack_sort_key",
"unpack_sort_key",
]