Skip to content

Commit 48d5a36

Browse files
fmuenkelchopan050behackl
authored
Typing opengl_renderer_window.py (#4363)
Co-authored-by: Francisco Manríquez Novoa <[email protected]> Co-authored-by: Francisco Manríquez <[email protected]> Co-authored-by: Benjamin Hackl <[email protected]>
1 parent 05cc414 commit 48d5a36

File tree

6 files changed

+77
-54
lines changed

6 files changed

+77
-54
lines changed

manim/_config/utils.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1418,7 +1418,7 @@ def window_position(self, value: str) -> None:
14181418

14191419
@property
14201420
def window_size(self) -> str:
1421-
"""The size of the opengl window. 'default' to automatically scale the window based on the display monitor."""
1421+
"""The size of the opengl window as 'width,height' or 'default' to automatically scale the window based on the display monitor."""
14221422
return self._d["window_size"]
14231423

14241424
@window_size.setter

manim/renderer/opengl_renderer.py

Lines changed: 31 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@
4545
from manim.animation.animation import Animation
4646
from manim.mobject.mobject import Mobject
4747
from manim.scene.scene import Scene
48+
from manim.typing import Point3D
4849

4950

5051
__all__ = ["OpenGLCamera", "OpenGLRenderer"]
@@ -248,45 +249,46 @@ def __init__(
248249
self.camera = OpenGLCamera()
249250
self.pressed_keys = set()
250251

252+
self.window = None
253+
251254
# Initialize texture map.
252255
self.path_to_texture_id = {}
253256

254257
self.background_color = config["background_color"]
255258

256-
def init_scene(self, scene):
259+
def init_scene(self, scene: Scene) -> None:
257260
self.partial_movie_files = []
258261
self.file_writer: Any = self._file_writer_class(
259262
self,
260263
scene.__class__.__name__,
261264
)
262265
self.scene = scene
263266
self.background_color = config["background_color"]
264-
if not hasattr(self, "window"):
265-
if self.should_create_window():
266-
from .opengl_renderer_window import Window
267+
if self.should_create_window():
268+
from .opengl_renderer_window import Window
267269

268-
self.window = Window(self)
269-
self.context = self.window.ctx
270-
self.frame_buffer_object = self.context.detect_framebuffer()
271-
else:
272-
self.window = None
273-
try:
274-
self.context = moderngl.create_context(standalone=True)
275-
except Exception:
276-
self.context = moderngl.create_context(
277-
standalone=True,
278-
backend="egl",
279-
)
280-
self.frame_buffer_object = self.get_frame_buffer_object(self.context, 0)
281-
self.frame_buffer_object.use()
282-
self.context.enable(moderngl.BLEND)
283-
self.context.wireframe = config["enable_wireframe"]
284-
self.context.blend_func = (
285-
moderngl.SRC_ALPHA,
286-
moderngl.ONE_MINUS_SRC_ALPHA,
287-
moderngl.ONE,
288-
moderngl.ONE,
289-
)
270+
self.window = Window(self)
271+
self.context = self.window.ctx
272+
self.frame_buffer_object = self.context.detect_framebuffer()
273+
else:
274+
# self.window = None
275+
try:
276+
self.context = moderngl.create_context(standalone=True)
277+
except Exception:
278+
self.context = moderngl.create_context(
279+
standalone=True,
280+
backend="egl",
281+
)
282+
self.frame_buffer_object = self.get_frame_buffer_object(self.context, 0)
283+
self.frame_buffer_object.use()
284+
self.context.enable(moderngl.BLEND)
285+
self.context.wireframe = config["enable_wireframe"]
286+
self.context.blend_func = (
287+
moderngl.SRC_ALPHA,
288+
moderngl.ONE_MINUS_SRC_ALPHA,
289+
moderngl.ONE,
290+
moderngl.ONE,
291+
)
290292

291293
def should_create_window(self):
292294
if config["force_window"]:
@@ -585,7 +587,9 @@ def get_frame(self):
585587
# Returns offset from the bottom left corner in pixels.
586588
# top_left flag should be set to True when using a GUI framework
587589
# where the (0,0) is at the top left: e.g. PySide6
588-
def pixel_coords_to_space_coords(self, px, py, relative=False, top_left=False):
590+
def pixel_coords_to_space_coords(
591+
self, px: float, py: float, relative: bool = False, top_left: bool = False
592+
) -> Point3D:
589593
pixel_shape = self.get_pixel_shape()
590594
if pixel_shape is None:
591595
return np.array([0, 0, 0])

manim/renderer/opengl_renderer_window.py

Lines changed: 37 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,17 @@
11
from __future__ import annotations
22

3+
from typing import TYPE_CHECKING, Any
4+
35
import moderngl_window as mglw
46
from moderngl_window.context.pyglet.window import Window as PygletWindow
57
from moderngl_window.timers.clock import Timer
6-
from screeninfo import get_monitors
8+
from screeninfo import Monitor, get_monitors
79

810
from .. import __version__, config
911

12+
if TYPE_CHECKING:
13+
from .opengl_renderer import OpenGLRenderer
14+
1015
__all__ = ["Window"]
1116

1217

@@ -17,15 +22,19 @@ class Window(PygletWindow):
1722
vsync = True
1823
cursor = True
1924

20-
def __init__(self, renderer, size=config.window_size, **kwargs):
25+
def __init__(
26+
self,
27+
renderer: OpenGLRenderer,
28+
window_size: str = config.window_size,
29+
**kwargs: Any,
30+
) -> None:
2131
monitors = get_monitors()
2232
mon_index = config.window_monitor
2333
monitor = monitors[min(mon_index, len(monitors) - 1)]
2434

25-
if size == "default":
35+
if window_size == "default":
2636
# make window_width half the width of the monitor
2737
# but make it full screen if --fullscreen
28-
2938
window_width = monitor.width
3039
if not config.fullscreen:
3140
window_width //= 2
@@ -35,8 +44,13 @@ def __init__(self, renderer, size=config.window_size, **kwargs):
3544
window_width * config.frame_height // config.frame_width,
3645
)
3746
size = (window_width, window_height)
47+
elif len(window_size.split(",")) == 2:
48+
(window_width, window_height) = tuple(map(int, window_size.split(",")))
49+
size = (window_width, window_height)
3850
else:
39-
size = tuple(size)
51+
raise ValueError(
52+
"Window_size must be specified as 'width,height' or 'default'.",
53+
)
4054

4155
super().__init__(size=size)
4256

@@ -55,13 +69,13 @@ def __init__(self, renderer, size=config.window_size, **kwargs):
5569
self.position = initial_position
5670

5771
# Delegate event handling to scene.
58-
def on_mouse_motion(self, x, y, dx, dy):
72+
def on_mouse_motion(self, x: int, y: int, dx: int, dy: int) -> None:
5973
super().on_mouse_motion(x, y, dx, dy)
6074
point = self.renderer.pixel_coords_to_space_coords(x, y)
6175
d_point = self.renderer.pixel_coords_to_space_coords(dx, dy, relative=True)
6276
self.renderer.scene.on_mouse_motion(point, d_point)
6377

64-
def on_mouse_scroll(self, x, y, x_offset: float, y_offset: float):
78+
def on_mouse_scroll(self, x: int, y: int, x_offset: float, y_offset: float) -> None:
6579
super().on_mouse_scroll(x, y, x_offset, y_offset)
6680
point = self.renderer.pixel_coords_to_space_coords(x, y)
6781
offset = self.renderer.pixel_coords_to_space_coords(
@@ -71,28 +85,32 @@ def on_mouse_scroll(self, x, y, x_offset: float, y_offset: float):
7185
)
7286
self.renderer.scene.on_mouse_scroll(point, offset)
7387

74-
def on_key_press(self, symbol, modifiers):
88+
def on_key_press(self, symbol: int, modifiers: int) -> bool:
7589
self.renderer.pressed_keys.add(symbol)
76-
super().on_key_press(symbol, modifiers)
90+
event_handled: bool = super().on_key_press(symbol, modifiers)
7791
self.renderer.scene.on_key_press(symbol, modifiers)
92+
return event_handled
7893

79-
def on_key_release(self, symbol, modifiers):
94+
def on_key_release(self, symbol: int, modifiers: int) -> None:
8095
if symbol in self.renderer.pressed_keys:
8196
self.renderer.pressed_keys.remove(symbol)
8297
super().on_key_release(symbol, modifiers)
8398
self.renderer.scene.on_key_release(symbol, modifiers)
8499

85-
def on_mouse_drag(self, x, y, dx, dy, buttons, modifiers):
100+
def on_mouse_drag(
101+
self, x: int, y: int, dx: int, dy: int, buttons: int, modifiers: int
102+
) -> None:
86103
super().on_mouse_drag(x, y, dx, dy, buttons, modifiers)
87104
point = self.renderer.pixel_coords_to_space_coords(x, y)
88105
d_point = self.renderer.pixel_coords_to_space_coords(dx, dy, relative=True)
89106
self.renderer.scene.on_mouse_drag(point, d_point, buttons, modifiers)
90107

91-
def find_initial_position(self, size, monitor):
108+
def find_initial_position(
109+
self, size: tuple[int, int], monitor: Monitor
110+
) -> tuple[int, int]:
92111
custom_position = config.window_position
93112
window_width, window_height = size
94-
# Position might be specified with a string of the form
95-
# x,y for integers x and y
113+
# Position might be specified with a string of the form x,y for integers x and y
96114
if len(custom_position) == 1:
97115
raise ValueError(
98116
"window_position must specify both Y and X positions (Y/X -> UR). Also accepts LEFT/RIGHT/ORIGIN/UP/DOWN.",
@@ -105,20 +123,21 @@ def find_initial_position(self, size, monitor):
105123
elif custom_position == "ORIGIN":
106124
custom_position = "O" * 2
107125
elif "," in custom_position:
108-
return tuple(map(int, custom_position.split(",")))
126+
pos_y, pos_x = tuple(map(int, custom_position.split(",")))
127+
return (pos_x, pos_y)
109128

110129
# Alternatively, it might be specified with a string like
111130
# UR, OO, DL, etc. specifying what corner it should go to
112131
char_to_n = {"L": 0, "U": 0, "O": 1, "R": 2, "D": 2}
113-
width_diff = monitor.width - window_width
114-
height_diff = monitor.height - window_height
132+
width_diff: int = monitor.width - window_width
133+
height_diff: int = monitor.height - window_height
115134

116135
return (
117136
monitor.x + char_to_n[custom_position[1]] * width_diff // 2,
118137
-monitor.y + char_to_n[custom_position[0]] * height_diff // 2,
119138
)
120139

121-
def on_mouse_press(self, x, y, button, modifiers):
140+
def on_mouse_press(self, x: int, y: int, button: int, modifiers: int) -> None:
122141
super().on_mouse_press(x, y, button, modifiers)
123142
point = self.renderer.pixel_coords_to_space_coords(x, y)
124143
mouse_button_map = {

manim/renderer/vectorized_mobject_rendering.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ def render_mobject_fills_with_matrix(
101101
)
102102
fill_shader.set_uniform(
103103
"u_projection_matrix",
104-
renderer.scene.camera.projection_matrix,
104+
renderer.camera.projection_matrix,
105105
)
106106

107107
vbo = renderer.context.buffer(attributes.tobytes())
@@ -302,7 +302,7 @@ def render_mobject_strokes_with_matrix(
302302
renderer.camera.unformatted_view_matrix @ model_matrix,
303303
),
304304
)
305-
shader.set_uniform("u_projection_matrix", renderer.scene.camera.projection_matrix)
305+
shader.set_uniform("u_projection_matrix", renderer.camera.projection_matrix)
306306
shader.set_uniform("manim_unit_normal", tuple(-mobjects[0].unit_normal[0]))
307307

308308
vbo = renderer.context.buffer(stroke_data.tobytes())

manim/scene/scene.py

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1489,7 +1489,10 @@ def interact(self, shell: Any, keyboard_thread: threading.Thread) -> None:
14891489
assert self.queue.qsize() == 0
14901490

14911491
last_time = time.time()
1492-
while not (self.renderer.window.is_closing or self.quit_interaction):
1492+
while not (
1493+
(self.renderer.window is not None and self.renderer.window.is_closing)
1494+
or self.quit_interaction
1495+
):
14931496
if not self.queue.empty():
14941497
action = self.queue.get_nowait()
14951498
if isinstance(action, SceneInteractRerun):
@@ -1550,7 +1553,7 @@ def interact(self, shell: Any, keyboard_thread: threading.Thread) -> None:
15501553
if self.dearpygui_imported and config["enable_gui"]:
15511554
dpg.stop_dearpygui()
15521555

1553-
if self.renderer.window.is_closing:
1556+
if self.renderer.window is not None and self.renderer.window.is_closing:
15541557
self.renderer.window.destroy()
15551558

15561559
def embed(self) -> None:
@@ -1924,6 +1927,6 @@ def mouse_drag_orbit_controls(
19241927
def set_key_function(self, char: str, func: Callable[[], Any]) -> None:
19251928
self.key_to_function_map[char] = func
19261929

1927-
def on_mouse_press(self, point: Point3D, button: int, modifiers: int) -> None:
1930+
def on_mouse_press(self, point: Point3D, button: str, modifiers: int) -> None:
19281931
for func in self.mouse_press_callbacks:
19291932
func()

mypy.ini

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -138,9 +138,6 @@ ignore_errors = True
138138
[mypy-manim.renderer.opengl_renderer]
139139
ignore_errors = True
140140

141-
[mypy-manim.renderer.opengl_renderer_window]
142-
ignore_errors = True
143-
144141
[mypy-manim.renderer.shader_wrapper]
145142
ignore_errors = True
146143

0 commit comments

Comments
 (0)