Source code for simvx.graphics.render2d

"""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",
]