Skip to content

Commit 072101f

Browse files
authored
updated ViewportProjector to use Rect, and created unit tests (#2343)
* updated ViewportProjector to use Rect and created unit tests * linting ✨ * ⬛ * Correcting references to the viewport Thanks for pointing out the issue, @eruvanos!
1 parent 83cb72d commit 072101f

File tree

2 files changed

+39
-13
lines changed

2 files changed

+39
-13
lines changed

arcade/camera/default.py

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
from pyglet.math import Mat4, Vec2, Vec3
77
from typing_extensions import Self
88

9-
from arcade.types import Point
9+
from arcade.types import LBWH, Point, Rect
1010
from arcade.window_commands import get_window
1111

1212
if TYPE_CHECKING:
@@ -29,28 +29,28 @@ class ViewportProjector:
2929

3030
def __init__(
3131
self,
32-
viewport: tuple[int, int, int, int] | None = None,
32+
viewport: Rect | None = None,
3333
*,
3434
context: ArcadeContext | None = None,
3535
):
36-
self._ctx = context or get_window().ctx
37-
self._viewport = viewport or self._ctx.viewport
36+
self._ctx: ArcadeContext = context or get_window().ctx
37+
self._viewport: Rect = viewport or LBWH(*self._ctx.viewport)
3838
self._projection_matrix: Mat4 = Mat4.orthogonal_projection(
39-
0.0, self._viewport[2], 0.0, self._viewport[3], -100, 100
39+
0.0, self._viewport.width, 0.0, self._viewport.height, -100, 100
4040
)
4141

4242
@property
43-
def viewport(self) -> tuple[int, int, int, int]:
43+
def viewport(self) -> Rect:
4444
"""
4545
The viewport use to derive projection and view matrix.
4646
"""
4747
return self._viewport
4848

4949
@viewport.setter
50-
def viewport(self, viewport: tuple[int, int, int, int]) -> None:
50+
def viewport(self, viewport: Rect) -> None:
5151
self._viewport = viewport
5252
self._projection_matrix = Mat4.orthogonal_projection(
53-
0, viewport[2], 0, viewport[3], -100, 100
53+
0, viewport.width, 0, viewport.height, -100, 100
5454
)
5555

5656
def use(self) -> None:
@@ -60,7 +60,7 @@ def use(self) -> None:
6060
"""
6161
self._ctx.current_camera = self
6262

63-
self._ctx.viewport = self._viewport
63+
self._ctx.viewport = self.viewport.viewport # get the integer 4-tuple LBWH
6464

6565
self._ctx.view_matrix = Mat4()
6666
self._ctx.projection_matrix = self._projection_matrix
@@ -121,18 +121,19 @@ def use(self) -> None:
121121
cache's the window viewport to determine the projection matrix.
122122
"""
123123

124+
viewport = self.viewport.viewport
124125
# If the viewport is correct and the default camera is in use,
125126
# then don't waste time resetting the view and projection matrices
126-
if self._ctx.viewport == self.viewport and self._ctx.current_camera == self:
127+
if self._ctx.viewport == viewport and self._ctx.current_camera == self:
127128
return
128129

129130
# If the viewport has changed while the default camera is active then the
130131
# default needs to update itself.
131132
# If it was another camera's viewport being used the default camera should not update.
132-
if self._ctx.viewport != self.viewport and self._ctx.current_camera == self:
133-
self.viewport = self._ctx.viewport
133+
if self._ctx.viewport != viewport and self._ctx.current_camera == self:
134+
self.viewport = LBWH(*self._ctx.viewport)
134135
else:
135-
self._ctx.viewport = self.viewport
136+
self._ctx.viewport = viewport
136137

137138
self._ctx.current_camera = self
138139

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import pytest as pytest
2+
3+
from pyglet.math import Vec3, Vec2
4+
5+
from arcade import camera, Window
6+
from arcade.types import Point, LBWH, Rect
7+
8+
@pytest.mark.parametrize("wrld_pos", [Vec2(100, 150), Vec2(1280, 720), Vec3(500, 500, -10)])
9+
def test_viewport_projector_project(window: Window, wrld_pos: Point):
10+
cam = camera.default.ViewportProjector()
11+
assert cam.project(wrld_pos) == wrld_pos.xy
12+
13+
@pytest.mark.parametrize("wrld_pos", [Vec2(100, 150), Vec2(1280, 720), Vec3(500, 500, -10)])
14+
def test_viewport_projector_unproject(window: Window, wrld_pos: Point):
15+
cam = camera.default.ViewportProjector()
16+
x, y, *z = wrld_pos
17+
18+
assert cam.unproject(wrld_pos) == Vec3(x, y, 0.0 if not z else z[0])
19+
20+
@pytest.mark.parametrize("viewport", [LBWH(0.0, 0.0, 100, 200), LBWH(100, 100, 20, 40), LBWH(300, 20, 20, 700)])
21+
def test_viewport_projector_viewport(window: Window, viewport: Rect):
22+
cam = camera.default.ViewportProjector()
23+
assert cam.viewport.viewport == window.ctx.viewport
24+
cam.viewport = viewport
25+
assert cam.viewport == viewport

0 commit comments

Comments
 (0)