44
55from arcade .camera .orthographic import OrthographicProjector
66from arcade .camera .data_types import CameraData , OrthographicProjectionData , Projector
7+ from arcade .gl import Framebuffer
78
89from arcade .window_commands import get_window
910if TYPE_CHECKING :
@@ -43,71 +44,88 @@ class Camera2D:
4344
4445 :param window: The Arcade Window to bind the camera to.
4546 Defaults to the currently active window.
46- :param viewport: A 4-int tuple which defines the pixel bounds which the camera with project to.
47- :param position: The 2D position of the camera in the XY plane.
48- :param up: The 2D unit vector which defines the +Y-axis of the camera space.
49- :param zoom: A scalar value which is inversely proportional to the size of the camera projection.
50- i.e. a zoom of 2.0 halves the size of the projection, doubling the perceived size of objects.
51- :param projection: A 4-float tuple which defines the world space
52- bounds which the camera projects to the viewport.
53- :param near: The near clipping plane of the camera.
54- :param far: The far clipping plane of the camera.
5547 :param camera_data: A :py:class:`~arcade.camera.data.CameraData`
5648 describing the viewport, position, up, and zoom.
5749 :param projection_data: A :py:class:`~arcade.camera.data.OrthographicProjectionData`
5850 which describes the left, right, top, bottom, far, near planes for an orthographic projection.
51+ :param render_target: The FrameBuffer that the camera uses. Defaults to the screen.
52+ If the framebuffer is not the default screen nothing drawn after this camera is used will
53+ show up. The FrameBuffer's internal viewport is ignored.
5954 """
6055 def __init__ (self , * ,
61- window : Optional ["Window" ] = None ,
62- viewport : Optional [Tuple [int , int , int , int ]] = None ,
63- position : Optional [Tuple [float , float ]] = None ,
64- up : Optional [Tuple [float , float ]] = None ,
65- zoom : Optional [float ] = None ,
66- projection : Optional [Tuple [float , float , float , float ]] = None ,
67- near : Optional [float ] = None ,
68- far : Optional [float ] = None ,
69- camera_data : Optional [CameraData ] = None ,
70- projection_data : Optional [OrthographicProjectionData ] = None
71- ):
72- window = window or get_window ()
73- self ._window : "Window" = window
56+ camera_data : CameraData ,
57+ projection_data : OrthographicProjectionData ,
58+ render_target : Optional [Framebuffer ] = None ,
59+ window : Optional ["Window" ] = None ):
60+ self ._window : "Window" = window or get_window ()
61+ self .render_target : Framebuffer = render_target or self ._window .ctx .screen
7462
75- assert (
76- not any ((viewport , position , up , zoom )) or not camera_data
77- ), (
78- "Camera2D Warning: Provided both a CameraData object and raw values. Defaulting to CameraData."
79- )
63+ self ._data = camera_data
64+ self ._projection : OrthographicProjectionData = projection_data
8065
81- assert (
82- not any ((projection , near , far )) or not projection_data
83- ), (
84- "Camera2D Warning: Provided both an OrthographicProjectionData object and raw values."
85- "Defaulting to OrthographicProjectionData."
66+ self ._ortho_projector : OrthographicProjector = OrthographicProjector (
67+ window = self ._window ,
68+ view = self ._data ,
69+ projection = self ._projection
8670 )
8771
88- half_width = window .width / 2
89- half_height = window .height / 2
72+ @staticmethod
73+ def from_raw_data (
74+ viewport : Optional [Tuple [int , int , int , int ]] = None ,
75+ position : Optional [Tuple [float , float ]] = None ,
76+ up : Tuple [float , float ] = (0.0 , 1.0 ),
77+ zoom : float = 1.0 ,
78+ projection : Optional [Tuple [float , float , float , float ]] = None ,
79+ near : float = - 100 ,
80+ far : float = 100 ,
81+ * ,
82+ render_target : Optional [Framebuffer ] = None ,
83+ window : Optional ["Window" ] = None
84+ ):
85+ """
86+ Create a Camera2D without first defining CameraData or an OrthographicProjectionData object.
87+
88+ :param viewport: A 4-int tuple which defines the pixel bounds which the camera with project to.
89+ :param position: The 2D position of the camera in the XY plane.
90+ :param up: The 2D unit vector which defines the +Y-axis of the camera space.
91+ :param zoom: A scalar value which is inversely proportional to the size of the camera projection.
92+ i.e. a zoom of 2.0 halves the size of the projection, doubling the perceived size of objects.
93+ :param projection: A 4-float tuple which defines the world space
94+ bounds which the camera projects to the viewport.
95+ :param near: The near clipping plane of the camera.
96+ :param far: The far clipping plane of the camera.
97+ :param render_target: The FrameBuffer that the camera uses. Defaults to the screen.
98+ If the framebuffer is not the default screen nothing drawn after this camera is used will
99+ show up. The FrameBuffer's internal viewport is ignored.
100+ :param window: The Arcade Window to bind the camera to.
101+ Defaults to the currently active window.
102+ """
103+ window = window or get_window ()
104+
105+ half_width = window .width / 2
106+ half_height = window .height / 2
90107
91108 _pos = position or (half_width , half_height )
92- _up = up or (0.0 , 1.0 )
93- self ._data = camera_data or CameraData (
94- (_pos [0 ], _pos [1 ], 0.0 ),
95- (_up [0 ], _up [1 ], 0.0 ),
96- (0.0 , 0.0 , - 1.0 ),
97- zoom or 1.0
109+ _data : CameraData = CameraData (
110+ (_pos [0 ], _pos [1 ], 0.0 ), # position
111+ (up [0 ], up [1 ], 0.0 ), # up vector
112+ (0.0 , 0.0 , - 1.0 ), # forward vector
113+ zoom # zoom
98114 )
99115
100- self ._projection : OrthographicProjectionData = projection_data or OrthographicProjectionData (
101- - half_width , half_width , # Left and Right.
102- - half_height , half_height , # Bottom and Top.
116+ left , right , bottom , top = projection or (- half_width , half_width , - half_height , half_height )
117+ _projection : OrthographicProjectionData = OrthographicProjectionData (
118+ left , right , # Left and Right.
119+ top , bottom , # Bottom and Top.
103120 near or 0.0 , far or 100.0 , # Near and Far.
104121 viewport or (0 , 0 , window .width , window .height ) # Viewport
105122 )
106123
107- self ._ortho_projector : OrthographicProjector = OrthographicProjector (
108- window = self ._window ,
109- view = self ._data ,
110- projection = self ._projection
124+ return Camera2D (
125+ camera_data = _data ,
126+ projection_data = _projection ,
127+ window = window ,
128+ render_target = (render_target or window .ctx .screen )
111129 )
112130
113131 @property
@@ -662,6 +680,7 @@ def use(self) -> None:
662680
663681 If you want to use a 'with' block use activate() instead.
664682 """
683+ self .render_target .use ()
665684 self ._ortho_projector .use ()
666685
667686 @contextmanager
@@ -675,10 +694,13 @@ def activate(self) -> Iterator[Projector]:
675694 the projector to the one previously in use.
676695 """
677696 previous_projection = self ._window .current_camera
697+ previous_framebuffer = self ._window .ctx .active_framebuffer
678698 try :
699+ self .render_target .use ()
679700 self .use ()
680701 yield self
681702 finally :
703+ previous_framebuffer .use ()
682704 previous_projection .use ()
683705
684706 def map_coordinate (self , screen_coordinate : Tuple [float , float ], depth : float = 0.0 ) -> Tuple [float , float ]:
0 commit comments