Skip to content

Commit b8031a1

Browse files
committed
Add classes MethodWithArgs, SceneInteractRerun and SceneInteractExit
1 parent 9c43ad0 commit b8031a1

File tree

5 files changed

+49
-48
lines changed

5 files changed

+49
-48
lines changed

manim/animation/transform.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333

3434
import numpy as np
3535

36+
from manim.data_structures import MethodWithArgs
3637
from manim.mobject.opengl.opengl_mobject import OpenGLGroup, OpenGLMobject
3738

3839
from .. import config
@@ -438,13 +439,13 @@ def check_validity_of_input(self, mobject: Mobject) -> None:
438439

439440

440441
class _MethodAnimation(MoveToTarget):
441-
def __init__(self, mobject, methods):
442+
def __init__(self, mobject: Mobject, methods: list[MethodWithArgs]) -> None:
442443
self.methods = methods
443444
super().__init__(mobject)
444445

445446
def finish(self) -> None:
446-
for method, method_args, method_kwargs in self.methods:
447-
method.__func__(self.mobject, *method_args, **method_kwargs)
447+
for item in self.methods:
448+
item.method.__func__(self.mobject, *item.args, **item.kwargs)
448449
super().finish()
449450

450451

manim/gui/gui.py

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,13 @@
1313
from collections.abc import Sequence
1414
from typing import TYPE_CHECKING, Any
1515

16-
from .. import __version__, config
17-
from ..utils.module_ops import scene_classes_from_file
16+
from manim import __version__
17+
from manim._config import config
18+
from manim.data_structures import SceneInteractExit, SceneInteractRerun
19+
from manim.utils.module_ops import scene_classes_from_file
1820

1921
if TYPE_CHECKING:
20-
from ..renderer.opengl_renderer import OpenGLRenderer
22+
from manim.renderer.opengl_renderer import OpenGLRenderer
2123

2224

2325
__all__ = ["configure_pygui"]
@@ -44,14 +46,14 @@ def configure_pygui(
4446
dpg.set_viewport_height(540)
4547

4648
def rerun_callback(sender, data):
47-
renderer.scene.queue.put(("rerun_gui", [], {}))
49+
renderer.scene.queue.put(SceneInteractRerun("gui"))
4850

4951
def continue_callback(sender, data):
50-
renderer.scene.queue.put(("exit_gui", [], {}))
52+
renderer.scene.queue.put(SceneInteractExit("gui"))
5153

5254
def scene_selection_callback(sender, data):
5355
config["scene_names"] = (dpg.get_value(sender),)
54-
renderer.scene.queue.put(("rerun_gui", [], {}))
56+
renderer.scene.queue.put(SceneInteractRerun("gui"))
5557

5658
scene_classes = scene_classes_from_file(Path(config["input_file"]), full_list=True)
5759
scene_names = [scene_class.__name__ for scene_class in scene_classes]

manim/mobject/mobject.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121

2222
import numpy as np
2323

24+
from manim.data_structures import MethodWithArgs
2425
from manim.mobject.opengl.opengl_compatibility import ConvertToOpenGL
2526

2627
from .. import config, logger
@@ -3232,7 +3233,7 @@ def __init__(self, mobject) -> None:
32323233

32333234
self.overridden_animation = None
32343235
self.is_chaining = False
3235-
self.methods = []
3236+
self.methods: list[MethodWithArgs] = []
32363237

32373238
# Whether animation args can be passed
32383239
self.cannot_pass_args = False
@@ -3267,7 +3268,7 @@ def update_target(*method_args, **method_kwargs):
32673268
**method_kwargs,
32683269
)
32693270
else:
3270-
self.methods.append([method, method_args, method_kwargs])
3271+
self.methods.append(MethodWithArgs(method, method_args, method_kwargs))
32713272
method(*method_args, **method_kwargs)
32723273
return self
32733274

manim/mobject/opengl/opengl_mobject.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
from manim import config, logger
1818
from manim.constants import *
19+
from manim.data_structures import MethodWithArgs
1920
from manim.renderer.shader_wrapper import get_colormap_code
2021
from manim.utils.bezier import integer_interpolate, interpolate
2122
from manim.utils.color import (
@@ -2938,7 +2939,7 @@ def __init__(self, mobject: OpenGLMobject):
29382939

29392940
self.overridden_animation = None
29402941
self.is_chaining = False
2941-
self.methods = []
2942+
self.methods: list[MethodWithArgs] = []
29422943

29432944
# Whether animation args can be passed
29442945
self.cannot_pass_args = False
@@ -2973,7 +2974,7 @@ def update_target(*method_args, **method_kwargs):
29732974
**method_kwargs,
29742975
)
29752976
else:
2976-
self.methods.append([method, method_args, method_kwargs])
2977+
self.methods.append(MethodWithArgs(method, method_args, method_kwargs))
29772978
method(*method_args, **method_kwargs)
29782979
return self
29792980

manim/scene/scene.py

Lines changed: 31 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
from watchdog.events import DirModifiedEvent, FileModifiedEvent, FileSystemEventHandler
3535
from watchdog.observers import Observer
3636

37+
from manim.data_structures import MethodWithArgs, SceneInteractExit, SceneInteractRerun
3738
from manim.mobject.mobject import Mobject
3839
from manim.mobject.opengl.opengl_mobject import OpenGLPoint
3940

@@ -55,26 +56,26 @@
5556
if TYPE_CHECKING:
5657
from collections.abc import Iterable, Sequence
5758
from types import FrameType
58-
from typing import Any, Callable, TypeAlias
59+
from typing import Any, Callable, TypeAlias, Union
5960

6061
from typing_extensions import Self
6162

6263
from manim.typing import Point3D
6364

64-
SceneInteractAction: TypeAlias = tuple[str, Iterable[Any], dict[str, Any]]
65-
"""
66-
The SceneInteractAction type alias is used for elements in the queue
65+
SceneInteractAction: TypeAlias = Union[
66+
MethodWithArgs, SceneInteractExit, SceneInteractRerun
67+
]
68+
"""The SceneInteractAction type alias is used for elements in the queue
6769
used by Scene.interact().
68-
The elements consist consist of:
6970
70-
- a string, which is either the name of a Scene method or some special keyword
71-
starting with "rerun" or "exit",
72-
- a list of args for the Scene method (only used if the first string actually
73-
corresponds to a method) and
74-
- a dict of kwargs for the Scene method (if the first string corresponds to one.
75-
Otherwise, currently Scene.interact() extracts a possible "from_animation_number" from it if the first string starts with "rerun"),
76-
as seen around the source code where it's common to use self.queue.put((method_name, [], {})) and similar items.
71+
The elements can be one of the following three:
7772
73+
- a :class:`~.MethodWithArgs` object, which represents a :class:`Scene`
74+
method to be called along with its args and kwargs,
75+
- a :class:`~.SceneInteractExit` object, indicating that the scene
76+
interaction is over, or
77+
- a :class:`~.SceneInteractRerun` object, indicating that the scene should
78+
render again.
7879
"""
7980

8081

@@ -86,7 +87,7 @@ def __init__(self, queue: Queue[SceneInteractAction]) -> None:
8687
self.queue = queue
8788

8889
def on_modified(self, event: DirModifiedEvent | FileModifiedEvent) -> None:
89-
self.queue.put(("rerun_file", [], {}))
90+
self.queue.put(SceneInteractRerun("file"))
9091

9192

9293
class Scene:
@@ -1102,20 +1103,15 @@ def play(
11021103
and config.renderer == RendererType.OPENGL
11031104
and threading.current_thread().name != "MainThread"
11041105
):
1106+
# TODO: are these actually being used?
11051107
kwargs.update(
11061108
{
11071109
"subcaption": subcaption,
11081110
"subcaption_duration": subcaption_duration,
11091111
"subcaption_offset": subcaption_offset,
11101112
}
11111113
)
1112-
self.queue.put(
1113-
(
1114-
"play",
1115-
args,
1116-
kwargs,
1117-
)
1118-
)
1114+
self.queue.put(SceneInteractRerun("play", **kwargs))
11191115
return
11201116

11211117
start_time = self.time
@@ -1359,17 +1355,19 @@ def load_module_into_namespace(
13591355
load_module_into_namespace(manim.opengl, namespace)
13601356

13611357
def embedded_rerun(*args: Any, **kwargs: Any) -> None:
1362-
self.queue.put(("rerun_keyboard", args, kwargs))
1358+
self.queue.put(SceneInteractRerun("keyboard"))
13631359
shell.exiter()
13641360

13651361
namespace["rerun"] = embedded_rerun
13661362

13671363
shell(local_ns=namespace)
1368-
self.queue.put(("exit_keyboard", [], {}))
1364+
self.queue.put(SceneInteractExit("keyboard"))
13691365

13701366
def get_embedded_method(method_name: str) -> Callable[..., None]:
1367+
method = getattr(self, method_name)
1368+
13711369
def embedded_method(*args: Any, **kwargs: Any) -> None:
1372-
self.queue.put((method_name, args, kwargs))
1370+
self.queue.put(MethodWithArgs(method, args, kwargs))
13731371

13741372
return embedded_method
13751373

@@ -1434,34 +1432,33 @@ def interact(self, shell: Any, keyboard_thread: threading.Thread) -> None:
14341432
last_time = time.time()
14351433
while not (self.renderer.window.is_closing or self.quit_interaction):
14361434
if not self.queue.empty():
1437-
tup = self.queue.get_nowait()
1438-
if tup[0].startswith("rerun"):
1435+
action = self.queue.get_nowait()
1436+
if isinstance(action, SceneInteractRerun):
14391437
# Intentionally skip calling join() on the file thread to save time.
1440-
if not tup[0].endswith("keyboard"):
1438+
if action.sender != "keyboard":
14411439
if shell.pt_app:
14421440
shell.pt_app.app.exit(exception=EOFError)
14431441
file_observer.unschedule_all()
14441442
raise RerunSceneException
14451443
keyboard_thread.join()
14461444

1447-
kwargs = tup[2]
1448-
if "from_animation_number" in kwargs:
1449-
config["from_animation_number"] = kwargs[
1445+
if "from_animation_number" in action.kwargs:
1446+
config["from_animation_number"] = action.kwargs[
14501447
"from_animation_number"
14511448
]
14521449
# # TODO: This option only makes sense if interactive_embed() is run at the
14531450
# # end of a scene by default.
1454-
# if "upto_animation_number" in kwargs:
1455-
# config["upto_animation_number"] = kwargs[
1451+
# if "upto_animation_number" in action.kwargs:
1452+
# config["upto_animation_number"] = action.kwargs[
14561453
# "upto_animation_number"
14571454
# ]
14581455

14591456
keyboard_thread.join()
14601457
file_observer.unschedule_all()
14611458
raise RerunSceneException
1462-
elif tup[0].startswith("exit"):
1459+
elif isinstance(action, SceneInteractExit):
14631460
# Intentionally skip calling join() on the file thread to save time.
1464-
if not tup[0].endswith("keyboard") and shell.pt_app:
1461+
if action.sender != "keyboard" and shell.pt_app:
14651462
shell.pt_app.app.exit(exception=EOFError)
14661463
keyboard_thread.join()
14671464
# Remove exit_keyboard from the queue if necessary.
@@ -1470,8 +1467,7 @@ def interact(self, shell: Any, keyboard_thread: threading.Thread) -> None:
14701467
keyboard_thread_needs_join = False
14711468
break
14721469
else:
1473-
method, args, kwargs = tup
1474-
getattr(self, method)(*args, **kwargs)
1470+
action.method(*action.args, **action.kwargs)
14751471
else:
14761472
self.renderer.animation_start_time = 0
14771473
dt = time.time() - last_time

0 commit comments

Comments
 (0)