99
1010from arcade .types import LBWH , Point , Rect
1111from arcade .window_commands import get_window
12+ from arcade .camera .data_types import DEFAULT_NEAR_ORTHO , DEFAULT_FAR
1213
1314if TYPE_CHECKING :
1415 from arcade .context import ArcadeContext
1516
16- __all__ = [ "ViewportProjector" , "DefaultProjector" ]
17+ __all__ = ()
1718
1819
19- class ViewportProjector :
20+ class DefaultProjector :
2021 """
21- A simple Projector which does not rely on any camera PoDs.
22+ An extremely limited projector which lacks any kind of control. This is only
23+ here to act as the default camera used internally by Arcade. There should be
24+ no instance where a developer would want to use this class.
25+
26+ The default viewport tries it's best to allow
27+ simple usecases with no need to use a camera.
2228
23- Does not have a way of moving, rotating, or zooming the camera.
24- perfect for something like UI or for mapping to an offscreen framebuffer.
29+ It does this by defaulting to the size of the active
30+ framebuffer. If the user sets the framebuffer's viewport
31+ without a camera then the default camera will match it
32+ until the framebuffer is changed again.
2533
2634 Args:
27- viewport: The viewport to project to.
28- context: The window context to bind the camera to. Defaults to the currently active window.
35+ context: The window context to bind the camera to. Defaults to the currently active context.
2936 """
3037
31- def __init__ (
32- self ,
33- viewport : Rect | None = None ,
34- * ,
35- context : ArcadeContext | None = None ,
36- ):
38+ def __init__ (self , * , context : ArcadeContext | None = None ):
3739 self ._ctx : ArcadeContext = context or get_window ().ctx
38- self ._viewport : Rect = viewport or LBWH (* self ._ctx .viewport )
39- self ._projection_matrix : Mat4 = Mat4 .orthogonal_projection (
40- 0.0 , self ._viewport .width , 0.0 , self ._viewport .height , - 100 , 100
41- )
40+ self ._viewport : Rect | None = None
41+ self ._scissor : Rect | None = None
42+ self ._matrix : Mat4 | None = None
4243
43- @property
44- def viewport (self ) -> Rect :
44+ def update_viewport (self ):
4545 """
46- The viewport use to derive projection and view matrix.
46+ Called when the ArcadeContext's viewport or active
47+ framebuffer has been set. It only actually updates
48+ the viewport if no other camera is active. Also
49+ setting the viewport to match the size of the active
50+ framebuffer sets the viewport to None.
4751 """
52+ if self ._ctx .current_camera != self :
53+ return
54+ if self ._ctx .viewport [2 ] != self .width or self ._ctx .viewport [3 ] != self .height :
55+ self ._viewport = LBWH (* self ._ctx .viewport )
56+ self ._viewport = None
57+
58+ self .use ()
59+
60+ @property
61+ def viewport (self ) -> Rect | None :
4862 return self ._viewport
4963
5064 @viewport .setter
51- def viewport (self , viewport : Rect ) -> None :
65+ def viewport (self , viewport : Rect | None ) -> None :
66+ if viewport == self ._viewport :
67+ return
5268 self ._viewport = viewport
53- self ._projection_matrix = Mat4 .orthogonal_projection (
54- 0 , viewport .width , 0 , viewport .height , - 100 , 100
69+ self ._matrix = Mat4 .orthogonal_projection (
70+ 0 , self .width , 0 , self .height , DEFAULT_NEAR_ORTHO , DEFAULT_FAR
5571 )
5672
73+ @viewport .deleter
74+ def viewport (self ):
75+ self .viewport = None
76+
77+ @property
78+ def scissor (self ) -> Rect | None :
79+ return self ._scissor
80+
81+ @scissor .setter
82+ def scissor (self , scissor : Rect | None ) -> None :
83+ self ._scissor = scissor
84+
85+ @scissor .deleter
86+ def scissor (self ) -> None :
87+ self ._scissor = None
88+
89+ @property
90+ def width (self ) -> int :
91+ if self ._viewport is not None :
92+ return int (self ._viewport .width )
93+ return self ._ctx .active_framebuffer .width
94+
95+ @property
96+ def height (self ) -> int :
97+ if self ._viewport is not None :
98+ return int (self ._viewport .height )
99+ return self ._ctx .active_framebuffer .height
100+
57101 def use (self ) -> None :
58102 """
59- Set the window's projection and view matrix.
60- Also sets the projector as the windows current camera.
103+ Set the window's Projection and View matrices.
61104 """
62- self ._ctx .current_camera = self
63105
64- self ._ctx .viewport = self .viewport .lbwh_int # get the integer 4-tuple LBWH
106+ viewport = (0 , 0 , self .width , self .height )
107+ # If the viewport is correct and the default camera is in use,
108+ # then don't waste time resetting the view and projection matrices
109+ if self ._ctx .viewport == viewport and self ._ctx .current_camera == self :
110+ return
111+
112+ self ._ctx .current_camera = self
113+ self ._ctx .viewport = viewport
65114
66115 self ._ctx .view_matrix = Mat4 ()
67- self ._ctx .projection_matrix = self ._projection_matrix
116+ if self ._matrix is None :
117+ self ._matrix = Mat4 .orthogonal_projection (
118+ 0 , 0 , viewport [2 ], viewport [3 ], DEFAULT_NEAR_ORTHO , DEFAULT_FAR
119+ )
120+ self ._ctx .projection_matrix = self ._matrix
68121
69122 @contextmanager
70123 def activate (self ) -> Generator [Self , None , None ]:
@@ -74,10 +127,12 @@ def activate(self) -> Generator[Self, None, None]:
74127 usable with the 'with' block. e.g. 'with ViewportProjector.activate() as cam: ...'
75128 """
76129 previous = self ._ctx .current_camera
130+ previous_viewport = self ._ctx .viewport
77131 try :
78132 self .use ()
79133 yield self
80134 finally :
135+ self ._ctx .viewport = previous_viewport
81136 previous .use ()
82137
83138 def project (self , world_coordinate : Point ) -> Vec2 :
@@ -97,46 +152,3 @@ def unproject(self, screen_coordinate: Point) -> Vec3:
97152 z = 0.0 if not _z else _z [0 ]
98153
99154 return Vec3 (x , y , z )
100-
101-
102- # As this class is only supposed to be used internally
103- # I wanted to place an _ in front, but the linting complains
104- # about it being a protected class.
105- class DefaultProjector (ViewportProjector ):
106- """
107- An extremely limited projector which lacks any kind of control. This is only
108- here to act as the default camera used internally by Arcade. There should be
109- no instance where a developer would want to use this class.
110-
111- Args:
112- context: The window context to bind the camera to. Defaults to the currently active window.
113- """
114-
115- def __init__ (self , * , context : ArcadeContext | None = None ):
116- super ().__init__ (context = context )
117-
118- def use (self ) -> None :
119- """
120- Set the window's Projection and View matrices.
121-
122- cache's the window viewport to determine the projection matrix.
123- """
124-
125- viewport = self .viewport .lbwh_int
126- # If the viewport is correct and the default camera is in use,
127- # then don't waste time resetting the view and projection matrices
128- if self ._ctx .viewport == viewport and self ._ctx .current_camera == self :
129- return
130-
131- # If the viewport has changed while the default camera is active then the
132- # default needs to update itself.
133- # If it was another camera's viewport being used the default camera should not update.
134- if self ._ctx .viewport != viewport and self ._ctx .current_camera == self :
135- self .viewport = LBWH (* self ._ctx .viewport )
136- else :
137- self ._ctx .viewport = viewport
138-
139- self ._ctx .current_camera = self
140-
141- self ._ctx .view_matrix = Mat4 ()
142- self ._ctx .projection_matrix = self ._projection_matrix
0 commit comments