Source code for manim.camera.multi_camera
"""A camera supporting multiple perspectives."""
from __future__ import annotations
__all__ = ["MultiCamera"]
from manim.mobject.types.image_mobject import ImageMobject
from ..camera.moving_camera import MovingCamera
from ..utils.iterables import list_difference_update
[docs]class MultiCamera(MovingCamera):
"""Camera Object that allows for multiple perspectives."""
def __init__(
self,
image_mobjects_from_cameras: ImageMobject | None = None,
allow_cameras_to_capture_their_own_display=False,
**kwargs,
):
"""Initialises the MultiCamera
Parameters
----------
image_mobjects_from_cameras
kwargs
Any valid keyword arguments of MovingCamera.
"""
self.image_mobjects_from_cameras = []
if image_mobjects_from_cameras is not None:
for imfc in image_mobjects_from_cameras:
self.add_image_mobject_from_camera(imfc)
self.allow_cameras_to_capture_their_own_display = (
allow_cameras_to_capture_their_own_display
)
super().__init__(**kwargs)
[docs] def add_image_mobject_from_camera(self, image_mobject_from_camera: ImageMobject):
"""Adds an ImageMobject that's been obtained from the camera
into the list ``self.image_mobject_from_cameras``
Parameters
----------
image_mobject_from_camera
The ImageMobject to add to self.image_mobject_from_cameras
"""
# A silly method to have right now, but maybe there are things
# we want to guarantee about any imfc's added later.
imfc = image_mobject_from_camera
assert isinstance(imfc.camera, MovingCamera)
self.image_mobjects_from_cameras.append(imfc)
[docs] def update_sub_cameras(self):
"""Reshape sub_camera pixel_arrays"""
for imfc in self.image_mobjects_from_cameras:
pixel_height, pixel_width = self.pixel_array.shape[:2]
imfc.camera.frame_shape = (
imfc.camera.frame.height,
imfc.camera.frame.width,
)
imfc.camera.reset_pixel_shape(
int(pixel_height * imfc.height / self.frame_height),
int(pixel_width * imfc.width / self.frame_width),
)
[docs] def reset(self):
"""Resets the MultiCamera.
Returns
-------
MultiCamera
The reset MultiCamera
"""
for imfc in self.image_mobjects_from_cameras:
imfc.camera.reset()
super().reset()
return self
[docs] def capture_mobjects(self, mobjects, **kwargs):
self.update_sub_cameras()
for imfc in self.image_mobjects_from_cameras:
to_add = list(mobjects)
if not self.allow_cameras_to_capture_their_own_display:
to_add = list_difference_update(to_add, imfc.get_family())
imfc.camera.capture_mobjects(to_add, **kwargs)
super().capture_mobjects(mobjects, **kwargs)
[docs] def get_mobjects_indicating_movement(self):
"""Returns all mobjects whose movement implies that the camera
should think of all other mobjects on the screen as moving
Returns
-------
list
"""
return [self.frame] + [
imfc.camera.frame for imfc in self.image_mobjects_from_cameras
]