-
Notifications
You must be signed in to change notification settings - Fork 2.5k
Renderer refactor #532
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
eulertour
merged 27 commits into
ManimCommunity:master
from
eulertour:renderer-refactor
Oct 15, 2020
Merged
Renderer refactor #532
Changes from all commits
Commits
Show all changes
27 commits
Select commit
Hold shift + click to select a range
6a96e2a
Remove Scene decorators and consolidate play() and wait()
eulertour e42c48f
Add CairoRenderer, move Scene.get_frame()
eulertour aef7eec
Move Scene.update_frame()
eulertour b1f8f6b
Move Scene.freeze_background() and Camera.extract_mobject_family_memb…
eulertour 2555bc7
Move Scene.update_skipping_status()
eulertour 0fd9074
Remove Scene.get_mobjects_from_last_animation()
eulertour a7fb0ee
Remove Scene.force_skipping()
eulertour 304fd4d
Move Scene.add_frame()
eulertour 7af7998
Move Scene.show_frame()
eulertour c74256c
Move more stuff out of Scene
eulertour d9eee53
Move Scene.file_writer
eulertour eddbb06
Remove some Scene references from SceneFileWriter
eulertour f8a55aa
Update ThreeDScene, move Scene.camera
eulertour 97f0715
Update Camera test
eulertour cfcdca0
Merge remote-tracking branch 'origin/master' into renderer-refactor
eulertour cab3396
Use wait-specific caching function
eulertour 067f0c1
Add renderer/__init__.py
eulertour a74313f
Update Camera variants
eulertour 57a2ead
Move caching functions
eulertour 4051ee1
Pass Scene to play() and wait()
eulertour ca618a6
Remove scene references from CairoRenderer
eulertour 200d83c
Initialize CairoRenderer without a Scene
eulertour e7a38a9
Decouple CairoRenderer from Scene
eulertour 7286453
Pass scene argument to play and wait
eulertour e00f7b3
Restore --save_last_frame functionality
eulertour d06faaf
Merge remote-tracking branch 'origin/master' into renderer-refactor
eulertour 44a0dee
Address review comments
eulertour File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Empty file.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,215 @@ | ||
| import numpy as np | ||
| from .. import config, camera_config, file_writer_config | ||
| from ..utils.iterables import list_update | ||
| from ..utils.exceptions import EndSceneEarlyException | ||
| from ..constants import DEFAULT_WAIT_TIME | ||
| from ..scene.scene_file_writer import SceneFileWriter | ||
| from ..utils.caching import handle_caching_play, handle_caching_wait | ||
| from ..camera.camera import Camera | ||
|
|
||
|
|
||
| def pass_scene_reference(func): | ||
| def wrapper(self, scene, *args, **kwargs): | ||
| func(self, scene, *args, **kwargs) | ||
|
|
||
| return wrapper | ||
|
|
||
|
|
||
| def handle_play_like_call(func): | ||
| """ | ||
| This method is used internally to wrap the | ||
| passed function, into a function that | ||
| actually writes to the video stream. | ||
| Simultaneously, it also adds to the number | ||
| of animations played. | ||
|
|
||
| Parameters | ||
| ---------- | ||
| func : function | ||
| The play() like function that has to be | ||
| written to the video file stream. | ||
|
|
||
| Returns | ||
| ------- | ||
| function | ||
| The play() like function that can now write | ||
| to the video file stream. | ||
| """ | ||
|
|
||
| def wrapper(self, scene, *args, **kwargs): | ||
| allow_write = not file_writer_config["skip_animations"] | ||
| self.file_writer.begin_animation(allow_write) | ||
| func(self, scene, *args, **kwargs) | ||
| self.file_writer.end_animation(allow_write) | ||
| self.num_plays += 1 | ||
|
|
||
| return wrapper | ||
|
|
||
|
|
||
| class CairoRenderer: | ||
| """A renderer using Cairo. | ||
|
|
||
| num_plays : Number of play() functions in the scene. | ||
| time: time elapsed since initialisation of scene. | ||
| """ | ||
|
|
||
| def __init__(self, camera_class=None, **kwargs): | ||
| # All of the following are set to EITHER the value passed via kwargs, | ||
| # OR the value stored in the global config dict at the time of | ||
| # _instance construction_. Before, they were in the CONFIG dict, which | ||
| # is a class attribute and is defined at the time of _class | ||
| # definition_. This did not allow for creating two Cameras with | ||
| # different configurations in the same session. | ||
| self.file_writer = None | ||
| self.video_quality_config = {} | ||
| for attr in [ | ||
| "pixel_height", | ||
| "pixel_width", | ||
| "frame_height", | ||
| "frame_width", | ||
| "frame_rate", | ||
| ]: | ||
| self.video_quality_config[attr] = kwargs.get(attr, config[attr]) | ||
| camera_cls = camera_class if camera_class is not None else Camera | ||
| self.camera = camera_cls(self.video_quality_config, **camera_config) | ||
| self.original_skipping_status = file_writer_config["skip_animations"] | ||
| self.animations_hashes = [] | ||
| self.num_plays = 0 | ||
| self.time = 0 | ||
|
|
||
| def init(self, scene): | ||
| self.file_writer = SceneFileWriter( | ||
| self, | ||
| self.video_quality_config, | ||
| scene.__class__.__name__, | ||
| **file_writer_config, | ||
| ) | ||
|
|
||
| @pass_scene_reference | ||
| @handle_caching_play | ||
| @handle_play_like_call | ||
| def play(self, scene, *args, **kwargs): | ||
| scene.play_internal(*args, **kwargs) | ||
|
|
||
| @pass_scene_reference | ||
| @handle_caching_wait | ||
| @handle_play_like_call | ||
| def wait(self, scene, duration=DEFAULT_WAIT_TIME, stop_condition=None): | ||
| scene.wait_internal(duration=duration, stop_condition=stop_condition) | ||
|
|
||
| def update_frame( # TODO Description in Docstring | ||
| self, | ||
| scene, | ||
| mobjects=None, | ||
| background=None, | ||
| include_submobjects=True, | ||
| ignore_skipping=True, | ||
| **kwargs, | ||
| ): | ||
| """Update the frame. | ||
|
|
||
| Parameters | ||
| ---------- | ||
| mobjects: list, optional | ||
| list of mobjects | ||
|
|
||
| background: np.ndarray, optional | ||
| Pixel Array for Background. | ||
|
|
||
| include_submobjects: bool, optional | ||
|
|
||
| ignore_skipping : bool, optional | ||
|
|
||
| **kwargs | ||
|
|
||
| """ | ||
| if file_writer_config["skip_animations"] and not ignore_skipping: | ||
| return | ||
| if mobjects is None: | ||
| mobjects = list_update( | ||
| scene.mobjects, | ||
| scene.foreground_mobjects, | ||
| ) | ||
| if background is not None: | ||
| self.camera.set_frame_to_background(background) | ||
| else: | ||
| self.camera.reset() | ||
|
|
||
| kwargs["include_submobjects"] = include_submobjects | ||
| self.camera.capture_mobjects(mobjects, **kwargs) | ||
|
|
||
| def get_frame(self): | ||
| """ | ||
| Gets the current frame as NumPy array. | ||
|
|
||
| Returns | ||
| ------- | ||
| np.array | ||
| NumPy array of pixel values of each pixel in screen. | ||
| The shape of the array is height x width x 3 | ||
| """ | ||
| return np.array(self.camera.pixel_array) | ||
|
|
||
| def add_frame(self, frame, num_frames=1): | ||
| """ | ||
| Adds a frame to the video_file_stream | ||
|
|
||
| Parameters | ||
| ---------- | ||
| frame : numpy.ndarray | ||
| The frame to add, as a pixel array. | ||
| num_frames: int | ||
| The number of times to add frame. | ||
| """ | ||
| dt = 1 / self.camera.frame_rate | ||
| self.time += num_frames * dt | ||
| if file_writer_config["skip_animations"]: | ||
| return | ||
| for _ in range(num_frames): | ||
| self.file_writer.write_frame(frame) | ||
|
|
||
| def show_frame(self): | ||
| """ | ||
| Opens the current frame in the Default Image Viewer | ||
| of your system. | ||
| """ | ||
| self.update_frame(ignore_skipping=True) | ||
| self.camera.get_image().show() | ||
|
|
||
| def update_skipping_status(self): | ||
| """ | ||
| This method is used internally to check if the current | ||
| animation needs to be skipped or not. It also checks if | ||
| the number of animations that were played correspond to | ||
| the number of animations that need to be played, and | ||
| raises an EndSceneEarlyException if they don't correspond. | ||
| """ | ||
| if file_writer_config["from_animation_number"]: | ||
| if self.num_plays < file_writer_config["from_animation_number"]: | ||
| file_writer_config["skip_animations"] = True | ||
| if file_writer_config["upto_animation_number"]: | ||
| if self.num_plays > file_writer_config["upto_animation_number"]: | ||
| file_writer_config["skip_animations"] = True | ||
| raise EndSceneEarlyException() | ||
|
|
||
| def revert_to_original_skipping_status(self): | ||
| """ | ||
| Forces the scene to go back to its original skipping status, | ||
| by setting skip_animations to whatever it reads | ||
| from original_skipping_status. | ||
|
|
||
| Returns | ||
| ------- | ||
| Scene | ||
| The Scene, with the original skipping status. | ||
| """ | ||
| if hasattr(self, "original_skipping_status"): | ||
| file_writer_config["skip_animations"] = self.original_skipping_status | ||
| return self | ||
|
|
||
| def finish(self, scene): | ||
| file_writer_config["skip_animations"] = False | ||
| self.file_writer.finish() | ||
| if file_writer_config["save_last_frame"]: | ||
| self.update_frame(scene, ignore_skipping=True) | ||
| self.file_writer.save_final_image(self.camera.get_image()) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.