Source code for simvx.graphics.engine_surface

"""Structural contract for the engine object ``SceneAdapter`` drives.

``SceneAdapter`` runs unchanged against both the Vulkan :class:`~simvx.graphics.engine.Engine`
and the browser ``EngineStub`` (``simvx.web``). The two are mirrored by hand with no
shared base, so a member added to one and consumed by the adapter but missing on the
other surfaces only as a runtime ``AttributeError`` -- in the browser, where it is
hardest to catch (this is exactly how ``create_text_texture`` shipped broken on web).

This ``Protocol`` declares the subset of the engine that ``SceneAdapter`` and the
example surface actually consume. Annotating ``SceneAdapter.__init__(engine: EngineSurface)``
turns any divergence into a mypy error at the construction site, not a browser crash.
Keep it to the *consumed* surface; do not grow it into a mirror of the whole Engine.
"""

from __future__ import annotations

from typing import Any, Protocol, runtime_checkable


[docs] @runtime_checkable class EngineSurface(Protocol): """The engine members ``SceneAdapter`` (and text-on-3D examples) depend on. Members are declared read-only (``@property``) so the contract is covariant and satisfied by either a property (the Vulkan ``Engine``) or a plain attribute (the web ``EngineStub``) -- ``SceneAdapter`` only ever reads them. """
[docs] @property def content_scale(self) -> tuple[float, float]: """HiDPI content scale; ``(1.0, 1.0)`` when unscaled. Unpacked as ``sx, sy``.""" ...
[docs] @property def extent(self) -> tuple[int, int] | None: """Swapchain/render-target extent, or ``None`` before init.""" ...
[docs] @property def mesh_registry(self) -> Any: """Mesh registrar (``.register(vertices, indices) -> handle``).""" ...
[docs] @property def texture_manager(self) -> Any: """Texture manager (``.resolve(...)`` / pixel cache).""" ...
[docs] def upload_texture_pixels(self, pixels: Any, width: int, height: int) -> int: """Upload raw RGBA pixels, returning a bindless texture index.""" ...
[docs] def create_text_texture(self, font: str | None = None, size: int = 32, width: int = 256, height: int = 64) -> Any: """Create a text-on-3D texture object (``.text`` / ``.colour`` / ``.texture_index``).""" ...