simvx.graphics.web_app

Client-side web app runtime — runs inside Pyodide (browser WASM Python).

Replaces App for fully client-side web export. Drives the SceneTree, Draw2D, and DrawSerializer in the browser without any server or Vulkan dependency.

The JavaScript web_runtime.js bridge calls tick(dt) each frame via requestAnimationFrame and renders the returned binary data with WebGPU.

Module Contents

Classes

WebApp

Browser-side app runtime for Pyodide.

Data

API

simvx.graphics.web_app.__all__

[‘WebApp’]

class simvx.graphics.web_app.WebApp(width: int, height: int, physics_fps: int = 60, *, include_3d: bool = False)[source]

Browser-side app runtime for Pyodide.

Usage from JavaScript::

const app = pyodide.runPython(`
    from simvx.graphics.web_app import WebApp
    app = WebApp(800, 600)
    app
`)
app.set_root(pyodide.runPython('from game import GameScene; GameScene()'))
# In rAF loop:
app.process_input(events_json)
frame_bytes = app.tick(dt)

Initialization

quit() None[source]

Stop the scene from processing. Canvas freezes on the last rendered frame.

Mirrors App.quit for web runtime. Games invoke self.app.quit() to stop their own simulation; the browser tab itself is closed by the user. No navigation, no clear — just pause physics/process/draw.

property title: str
property engine

Engine interface for 3D nodes that access self.app.engine.

Returns None in 2D-only mode — 2D nodes don’t need it.

set_root(root_node) None[source]

Set the scene root node.

load_atlas(atlas_rgba: bytes, atlas_size: int, regions_json: str, font_size: int, ascender: float, descender: float, line_height: float, sdf_range: float, glyph_padding: int) None[source]

Reconstruct the MSDF atlas from pre-baked data (no freetype needed).

Args: atlas_rgba: Raw RGBA pixel bytes (atlas_size * atlas_size * 4). atlas_size: Width/height of the square atlas texture. regions_json: JSON-serialized glyph regions. font_size: Original font pixel size used to generate the atlas. ascender, descender, line_height: Font metrics. sdf_range: SDF range used during generation. glyph_padding: Glyph padding used during generation.

process_input(events_json: str) None[source]

Process batched input events from JavaScript.

Args: events_json: JSON array of input event objects.

resize(width: int, height: int) None[source]

Update engine dimensions on viewport resize (called from JS).

tick(dt: float) bytes[source]

Advance one frame and return serialized draw commands.

Args: dt: Delta time in seconds since last frame.

Returns: In 2D-only mode: binary frame data for the 2D renderer. In 3D mode: combined <u32 len3d> <3d bytes> <2d bytes> consumed by the 2D+3D composited renderer.

drain_resources(*, debug_log: bool = False)[source]

Drain newly-registered resources as a TLV-encoded binary payload.

Wire format::

count(u32)
  [ kind(u8) + id(u32) + length(u32) + payload(length bytes) ] × count

Each (kind, id) pair is emitted exactly once across the app’s lifetime. Returns b"" when nothing is pending so the JS boot loop can skip the per-frame Pyodide crossing in steady state.

When debug_log=True, returns (blob, summary) where summary is a list of (kind, id, payload_len) tuples — cheap to inspect without parsing the TLV bytes.