Skip to content

Commit f8a5490

Browse files
committed
move viewport projector to it's own file to hopefully improve it's visibility
1 parent 9102087 commit f8a5490

File tree

2 files changed

+105
-0
lines changed

2 files changed

+105
-0
lines changed

arcade/camera/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323

2424
from arcade.camera.orthographic import OrthographicProjector
2525
from arcade.camera.perspective import PerspectiveProjector
26+
from arcade.camera.viewport import ViewportProjector
2627

2728
from arcade.camera.camera_2d import Camera2D
2829

@@ -33,6 +34,7 @@
3334
"Projection",
3435
"Projector",
3536
"CameraData",
37+
"ViewportProjector",
3638
"generate_view_matrix",
3739
"OrthographicProjectionData",
3840
"generate_orthographic_matrix",

arcade/camera/viewport.py

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
from __future__ import annotations
2+
3+
from collections.abc import Generator
4+
from contextlib import contextmanager
5+
from typing import TYPE_CHECKING
6+
7+
from pyglet.math import Mat4, Vec2, Vec3
8+
from typing_extensions import Self
9+
10+
from arcade.types import LBWH, Point, Rect
11+
from arcade.window_commands import get_window
12+
from arcade.camera.data_types import DEFAULT_NEAR_ORTHO, DEFAULT_FAR
13+
14+
if TYPE_CHECKING:
15+
from arcade.context import ArcadeContext
16+
17+
__all__ = ["ViewportProjector"]
18+
19+
20+
class ViewportProjector:
21+
"""
22+
A simple Projector which does not rely on any camera PoDs.
23+
24+
Does not have a way of moving, rotating, or zooming the camera.
25+
perfect for something like UI or for mapping to an offscreen framebuffer.
26+
27+
Args:
28+
viewport: The viewport to project to.
29+
context: The window context to bind the camera to. Defaults to the currently active window.
30+
"""
31+
32+
def __init__(
33+
self,
34+
viewport: Rect | None = None,
35+
*,
36+
context: ArcadeContext | None = None,
37+
):
38+
self._ctx: ArcadeContext = context or get_window().ctx
39+
self._viewport: Rect = viewport or LBWH(*self._ctx.viewport)
40+
self._projection_matrix: Mat4 = Mat4.orthogonal_projection(
41+
0.0, self.viewport.width, 0.0, self.viewport.height, DEFAULT_NEAR_ORTHO, DEFAULT_FAR
42+
)
43+
44+
@property
45+
def viewport(self) -> Rect | None:
46+
"""
47+
The viewport use to derive projection and view matrix.
48+
"""
49+
return self._viewport
50+
51+
@viewport.setter
52+
def viewport(self, viewport: Rect) -> None:
53+
self._viewport = viewport
54+
self._projection_matrix = Mat4.orthogonal_projection(
55+
0, viewport.width, 0, viewport.height, DEFAULT_NEAR_ORTHO, DEFAULT_FAR
56+
)
57+
58+
def use(self) -> None:
59+
"""
60+
Set the window's projection and view matrix.
61+
Also sets the projector as the windows current camera.
62+
"""
63+
self._ctx.current_camera = self
64+
65+
if self.viewport:
66+
self._ctx.viewport = self.viewport.lbwh_int
67+
68+
self._ctx.view_matrix = Mat4()
69+
self._ctx.projection_matrix = self._projection_matrix
70+
71+
@contextmanager
72+
def activate(self) -> Generator[Self, None, None]:
73+
"""
74+
The context manager version of the use method.
75+
76+
usable with the 'with' block. e.g. 'with ViewportProjector.activate() as cam: ...'
77+
"""
78+
previous = self._ctx.current_camera
79+
previous_viewport = self._ctx.viewport
80+
try:
81+
self.use()
82+
yield self
83+
finally:
84+
self._ctx.viewport = previous_viewport
85+
previous.use()
86+
87+
def project(self, world_coordinate: Point) -> Vec2:
88+
"""
89+
Take a Vec2 or Vec3 of coordinates and return the related screen coordinate
90+
"""
91+
x, y, *z = world_coordinate
92+
return Vec2(x, y)
93+
94+
def unproject(self, screen_coordinate: Point) -> Vec3:
95+
"""
96+
Map the screen pos to screen_coordinates.
97+
98+
Due to the nature of viewport projector this does not do anything.
99+
"""
100+
x, y, *_z = screen_coordinate
101+
z = 0.0 if not _z else _z[0]
102+
103+
return Vec3(x, y, z)

0 commit comments

Comments
 (0)