diff --git a/camera/camera.py b/camera/camera.py index f4a1f6c6..cd3127cd 100644 --- a/camera/camera.py +++ b/camera/camera.py @@ -34,12 +34,12 @@ class Camera(object): "frame_shape": (FRAME_HEIGHT, FRAME_WIDTH), "space_center": ORIGIN, "background_color": BLACK, + "background_alpha": 0, # Out of rgb_max_val # Points in vectorized mobjects with norm greater # than this value will be rescaled. "max_allowable_norm": FRAME_WIDTH, "image_mode": "RGBA", "n_rgb_coords": 4, - "background_alpha": 0, # Out of rgb_max_val "pixel_array_dtype": 'uint8', "use_z_coordinate_for_display_order": False, # z_buff_func is only used if the flag above is set to True. diff --git a/camera/moving_camera.py b/camera/moving_camera.py index 4072227a..2b1085a0 100644 --- a/camera/moving_camera.py +++ b/camera/moving_camera.py @@ -10,9 +10,9 @@ from utils.config_ops import digest_config class MovingCamera(Camera): """ - Stays in line with the height, width and position - of a given mobject + Stays in line with the height, width and position of it's 'frame', which is a Rectangle """ + CONFIG = { "fixed_dimension": 0, # width "default_frame_stroke_color": WHITE, @@ -21,8 +21,8 @@ class MovingCamera(Camera): def __init__(self, frame=None, **kwargs): """ - frame is a Mobject, (should be a rectangle) determining - which region of space the camera displys + frame is a Mobject, (should almost certainly be a rectangle) + determining which region of space the camera displys """ digest_config(self, kwargs) if frame is None: diff --git a/camera/multi_camera.py b/camera/multi_camera.py index 5d7b7a3e..102e8d97 100644 --- a/camera/multi_camera.py +++ b/camera/multi_camera.py @@ -3,17 +3,9 @@ from __future__ import absolute_import from camera.moving_camera import MovingCamera from utils.iterables import list_difference_update -# Distinct notions of view frame vs. display frame - -# For now, let's say it is the responsibility of the scene holding -# this camera to add all of the relevant image_mobjects_from_cameras, -# as well as their display_frames - class MultiCamera(MovingCamera): CONFIG = { - # "lock_display_frame_dimensions_to_view_frame": True, - # "display_frame_fixed_dimension": 1, # Height "allow_cameras_to_capture_their_own_display": False, } @@ -31,11 +23,7 @@ class MultiCamera(MovingCamera): self.image_mobjects_from_cameras.append(imfc) def update_sub_cameras(self): - # if self.lock_display_frame_dimensions_to_view_frame: - # for imfc in self.image_mobjects_from_cameras: - # aspect_ratio = imfc.view_frame.get_width() / imfc.view_frame.get_height() - - # Reshape sub_camera pixel_arrays + """ Reshape sub_camera pixel_arrays """ for imfc in self.image_mobjects_from_cameras: frame_height, frame_width = self.frame_shape pixel_height, pixel_width = self.get_pixel_array().shape[:2] @@ -55,7 +43,6 @@ class MultiCamera(MovingCamera): return self def capture_mobjects(self, mobjects, **kwargs): - # Make sure all frames are in mobjects? Or not? self.update_sub_cameras() for imfc in self.image_mobjects_from_cameras: to_add = list(mobjects) diff --git a/mobject/types/image_mobject.py b/mobject/types/image_mobject.py index ab73a048..9d6878b4 100644 --- a/mobject/types/image_mobject.py +++ b/mobject/types/image_mobject.py @@ -19,11 +19,7 @@ class AbstractImageMobject(Mobject): Automatically filters out black pixels """ CONFIG = { - "filter_color": "black", - "invert": False, - # "use_cache" : True, "height": 2.0, - "image_mode": "RGBA", "pixel_array_dtype": "uint8", } @@ -31,12 +27,11 @@ class AbstractImageMobject(Mobject): raise Exception("Not implemented") def set_color(self): - # Likely to be implemented in subclasses + # Likely to be implemented in subclasses, but no obgligation pass def init_points(self): - # Corresponding corners of image are fixed to these - # Three points + # Corresponding corners of image are fixed to these 3 points self.points = np.array([ UP + LEFT, UP + RIGHT, @@ -52,16 +47,9 @@ class AbstractImageMobject(Mobject): class ImageMobject(AbstractImageMobject): - """ - Automatically filters out black pixels - """ CONFIG = { - "filter_color": "black", "invert": False, - # "use_cache" : True, - "height": 2.0, "image_mode": "RGBA", - "pixel_array_dtype": "uint8", } def __init__(self, filename_or_array, **kwargs): @@ -118,6 +106,10 @@ class ImageMobject(AbstractImageMobject): mobject1.pixel_array, mobject2.pixel_array, alpha ).astype(self.pixel_array_dtype) +# TODO, add the ability to have the dimensions/orientation of this +# mobject more strongly tied to the frame of the camera it contains, +# in the case where that's a MovingCamera + class ImageMobjectFromCamera(AbstractImageMobject): CONFIG = { diff --git a/scene/zoomed_scene.py b/scene/zoomed_scene.py index 1fff1e74..bf628894 100644 --- a/scene/zoomed_scene.py +++ b/scene/zoomed_scene.py @@ -1,17 +1,16 @@ from __future__ import absolute_import -import numpy as np - from scene.scene import Scene -from animation.creation import FadeIn from camera.moving_camera import MovingCamera from camera.multi_camera import MultiCamera -from mobject.geometry import Rectangle from mobject.types.image_mobject import ImageMobjectFromCamera from constants import * +# Note, any scenes from old videos using ZoomedScene will almost certainly +# break, as it was restructured. + class ZoomedScene(Scene): CONFIG = { "camera_class": MultiCamera, @@ -56,9 +55,10 @@ class ZoomedScene(Scene): self.zoomed_display = zoomed_display def activate_zooming(self, animate=False, run_times=[2, 1]): - self.zoom_activated = True zoomed_camera = self.zoomed_camera zoomed_display = self.zoomed_display + + self.zoom_activated = True self.camera.add_image_mobject_from_camera(zoomed_display) to_add = [zoomed_camera.frame, zoomed_display] @@ -84,132 +84,7 @@ class ZoomedScene(Scene): zoomed_mobjects = [self.zoomed_camera.frame, self.zoomed_display] moving_zoomed_mobjects = set(moving_mobjects).intersection(zoomed_mobjects) if self.zoom_activated and moving_zoomed_mobjects: + # If either of the zoomed_mobjects are moving, then so is + # everything return self.mobjects - else: - return moving_mobjects - - - -class OldZoomedScene(Scene): - """ - Move around self.little_rectangle to determine - which part of the screen is zoomed in on. - """ - CONFIG = { - "zoomed_canvas_frame_shape": (3, 3), - "zoomed_canvas_center": None, - "zoomed_canvas_corner": UP + RIGHT, - "zoomed_canvas_corner_buff": DEFAULT_MOBJECT_TO_EDGE_BUFFER, - "zoomed_camera_background": None, - "little_rectangle_start_position": ORIGIN, - "zoom_factor": 6, - "square_color": WHITE, - "zoom_activated": False, - } - - def activate_zooming(self): - self.generate_big_rectangle() - self.setup_zoomed_canvas() - self.setup_zoomed_camera() - self.zoom_activated = True - - def animate_activate_zooming(self): - self.activate_zooming() - self.play(*map(FadeIn, [ - self.little_rectangle, self.big_rectangle - ])) - - def disactivate_zooming(self): - self.remove(self.big_rectangle, self.little_rectangle) - self.zoom_activated = False - - def get_zoomed_camera_mobject(self): - return self.little_rectangle - - def get_zoomed_screen(self): - return self.big_rectangle - - def generate_big_rectangle(self): - height, width = self.zoomed_canvas_frame_shape - self.big_rectangle = Rectangle( - height=height, - width=width, - color=self.square_color - ) - if self.zoomed_canvas_center is not None: - self.big_rectangle.shift(self.zoomed_canvas_center) - elif self.zoomed_canvas_corner is not None: - self.big_rectangle.to_corner( - self.zoomed_canvas_corner, - buff=self.zoomed_canvas_corner_buff - ) - self.add(self.big_rectangle) - - def setup_zoomed_canvas(self): - upper_left = self.big_rectangle.get_corner(UP + LEFT) - lower_right = self.big_rectangle.get_corner(DOWN + RIGHT) - pixel_coords = self.camera.points_to_pixel_coords( - np.array([upper_left, lower_right]) - ) - self.zoomed_canvas_pixel_indices = pixel_coords - (up, left), (down, right) = pixel_coords - self.zoomed_canvas_pixel_shape = ( - right - left, - down - up, - ) - - def setup_zoomed_camera(self): - self.little_rectangle = self.big_rectangle.copy() - self.little_rectangle.scale(1. / self.zoom_factor) - self.little_rectangle.move_to( - self.little_rectangle_start_position - ) - self.zoomed_camera = MovingCamera( - self.little_rectangle, - pixel_shape=self.zoomed_canvas_pixel_shape, - background=self.zoomed_camera_background - ) - self.add(self.little_rectangle) - # TODO, is there a better way to hanld this? - self.zoomed_camera.adjusted_thickness = lambda x: x - - def get_frame(self): - frame = Scene.get_frame(self) - if self.zoom_activated: - (up, left), (down, right) = self.zoomed_canvas_pixel_indices - frame[left:right, up:down, :] = self.zoomed_camera.get_image() - return frame - - def set_camera_pixel_array(self, pixel_array): - self.camera.set_pixel_array(pixel_array) - if self.zoom_activated: - (up, left), (down, right) = self.zoomed_canvas_pixel_indices - self.zoomed_camera.set_pixel_array( - pixel_array[left:right, up:down]) - - def set_camera_background(self, background): - self.set_camera_pixel_array(self, background) - # TODO, check this... - - def reset_camera(self): - self.camera.reset() - if self.zoom_activated: - self.zoomed_camera.reset() - - def capture_mobjects_in_camera(self, mobjects, **kwargs): - self.camera.capture_mobjects(mobjects, **kwargs) - if self.zoom_activated: - if self.big_rectangle in mobjects: - mobjects = list(mobjects) - mobjects.remove(self.big_rectangle) - self.zoomed_camera.capture_mobjects( - mobjects, **kwargs - ) - - def get_moving_mobjects(self, *animations): - moving_mobjects = Scene.get_moving_mobjects(self, *animations) - if self.zoom_activated and self.little_rectangle in moving_mobjects: - # When the camera is moving, so is everything, - return self.mobjects - else: - return moving_mobjects + return moving_mobjects