Source code for mini_arcade_core.engine.render.passes.world
"""
World render pass implementation.
"""
from __future__ import annotations
from dataclasses import dataclass
from mini_arcade_core.backend import Backend
from mini_arcade_core.engine.render.camera import viewport_transform_for_packet
from mini_arcade_core.engine.render.context import RenderContext
from mini_arcade_core.engine.render.frame_packet import FramePacket
from mini_arcade_core.engine.render.packet import DrawOp, RenderPacket
[docs]
@dataclass
class WorldPass:
"""
World Render Pass.
This pass handles rendering of world-space objects.
"""
name: str = "WorldPass"
[docs]
def run(
self, backend: Backend, ctx: RenderContext, packets: list[FramePacket]
):
"""Run the world render pass."""
for fp in packets:
if fp.is_overlay:
continue
layer_ops = self._layer_ops(fp.packet, "world")
if layer_ops is not None:
self._draw_ops(backend, ctx, fp.packet, layer_ops)
continue
self._draw_packet(backend, ctx, fp.packet)
@staticmethod
def _layer_ops(
packet: RenderPacket, key: str
) -> tuple[DrawOp, ...] | None:
raw = packet.meta.get("pass_ops")
if not isinstance(raw, dict):
return None
ops = raw.get(key)
if ops is None:
return tuple()
return tuple(ops)
def _draw_packet(
self, backend: Backend, ctx: RenderContext, packet: RenderPacket
):
if not packet or not packet.ops:
return
self._draw_ops(backend, ctx, packet, packet.ops)
def _draw_ops(
self,
backend: Backend,
ctx: RenderContext,
packet: RenderPacket,
ops: tuple[DrawOp, ...],
):
if not ops:
return
ctx.stats.packets += 1
ctx.stats.renderables += len(ops)
ctx.stats.draw_groups += 1 # approx: 1 group per packet
world_transform = viewport_transform_for_packet(ctx.viewport, packet)
backend.set_viewport_transform(
ctx.viewport.offset_x,
ctx.viewport.offset_y,
ctx.viewport.scale,
)
backend.render.set_clip_rect(
0,
0,
ctx.viewport.virtual_w,
ctx.viewport.virtual_h,
)
try:
backend.set_viewport_transform(
world_transform.ox,
world_transform.oy,
world_transform.s,
)
for op in ops:
op(backend)
finally:
backend.render.clear_clip_rect()
backend.clear_viewport_transform()