mirror of
https://github.com/3b1b/manim.git
synced 2025-08-05 16:49:03 +00:00
Merge branch 'lighthouse-grant' into lighthouse2
This commit is contained in:
commit
3944c8a2d8
11 changed files with 4711 additions and 100 deletions
|
@ -426,7 +426,6 @@ class IntroScene(PiCreatureScene):
|
||||||
|
|
||||||
self.ellipsis = TexMobject("\cdots")
|
self.ellipsis = TexMobject("\cdots")
|
||||||
self.ellipsis.scale(0.4)
|
self.ellipsis.scale(0.4)
|
||||||
|
|
||||||
for i in range(5, max_n1):
|
for i in range(5, max_n1):
|
||||||
|
|
||||||
if i == 5:
|
if i == 5:
|
||||||
|
@ -441,7 +440,6 @@ class IntroScene(PiCreatureScene):
|
||||||
GrowFromPoint(self.rects[i], self.euler_sum[10].get_center(),
|
GrowFromPoint(self.rects[i], self.euler_sum[10].get_center(),
|
||||||
run_time = 0.5)
|
run_time = 0.5)
|
||||||
)
|
)
|
||||||
|
|
||||||
for i in range(max_n1, max_n2):
|
for i in range(max_n1, max_n2):
|
||||||
self.play(
|
self.play(
|
||||||
GrowFromPoint(self.rects[i], self.euler_sum[10].get_center(),
|
GrowFromPoint(self.rects[i], self.euler_sum[10].get_center(),
|
||||||
|
@ -929,15 +927,11 @@ class SingleLighthouseScene(PiCreatureScene):
|
||||||
|
|
||||||
|
|
||||||
class MorphIntoSunScene(PiCreatureScene):
|
class MorphIntoSunScene(PiCreatureScene):
|
||||||
|
|
||||||
def construct(self):
|
def construct(self):
|
||||||
|
|
||||||
self.setup_elements()
|
self.setup_elements()
|
||||||
self.morph_lighthouse_into_sun()
|
self.morph_lighthouse_into_sun()
|
||||||
|
|
||||||
|
|
||||||
def setup_elements(self):
|
def setup_elements(self):
|
||||||
|
|
||||||
self.remove(self.get_primary_pi_creature())
|
self.remove(self.get_primary_pi_creature())
|
||||||
|
|
||||||
SCREEN_SIZE = 3.0
|
SCREEN_SIZE = 3.0
|
||||||
|
@ -988,10 +982,8 @@ class MorphIntoSunScene(PiCreatureScene):
|
||||||
|
|
||||||
self.add_foreground_mobject(self.light_source.shadow)
|
self.add_foreground_mobject(self.light_source.shadow)
|
||||||
self.add_foreground_mobject(morty)
|
self.add_foreground_mobject(morty)
|
||||||
|
|
||||||
self.light_source.dim_ambient
|
self.light_source.dim_ambient
|
||||||
self.add(self.light_source.spotlight)
|
self.add(self.light_source.spotlight)
|
||||||
|
|
||||||
self.screen_tracker = ScreenTracker(self.light_source)
|
self.screen_tracker = ScreenTracker(self.light_source)
|
||||||
self.add(self.screen_tracker)
|
self.add(self.screen_tracker)
|
||||||
|
|
||||||
|
@ -4351,10 +4343,6 @@ class ArcHighlightOverlayScene(Scene):
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
flash_arcs(3)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class ThumbnailScene(Scene):
|
class ThumbnailScene(Scene):
|
||||||
|
|
||||||
|
@ -4545,14 +4533,4 @@ class RightAnglesOverlay(Scene):
|
||||||
|
|
||||||
self.play(FadeOut(lines))
|
self.play(FadeOut(lines))
|
||||||
|
|
||||||
|
flash_arcs(3)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
4651
active_projects/basel2.py
Normal file
4651
active_projects/basel2.py
Normal file
File diff suppressed because it is too large
Load diff
|
@ -101,9 +101,15 @@ class Swap(CyclicReplace):
|
||||||
pass #Renaming, more understandable for two entries
|
pass #Renaming, more understandable for two entries
|
||||||
|
|
||||||
class GrowFromPoint(Transform):
|
class GrowFromPoint(Transform):
|
||||||
|
CONFIG = {
|
||||||
|
"point_color" : None,
|
||||||
|
}
|
||||||
def __init__(self, mobject, point, **kwargs):
|
def __init__(self, mobject, point, **kwargs):
|
||||||
|
digest_config(self, kwargs)
|
||||||
target = mobject.copy()
|
target = mobject.copy()
|
||||||
point_mob = Point(point)
|
point_mob = Point(point)
|
||||||
|
if self.point_color:
|
||||||
|
point_mob.highlight(self.point_color)
|
||||||
mobject.replace(point_mob)
|
mobject.replace(point_mob)
|
||||||
mobject.highlight(point_mob.get_color())
|
mobject.highlight(point_mob.get_color())
|
||||||
Transform.__init__(self, mobject, target, **kwargs)
|
Transform.__init__(self, mobject, target, **kwargs)
|
||||||
|
|
|
@ -18,7 +18,6 @@ from camera import Camera
|
||||||
HELP_MESSAGE = """
|
HELP_MESSAGE = """
|
||||||
Usage:
|
Usage:
|
||||||
python extract_scene.py <module> [<scene name>]
|
python extract_scene.py <module> [<scene name>]
|
||||||
|
|
||||||
-p preview in low quality
|
-p preview in low quality
|
||||||
-s show and save picture of last frame
|
-s show and save picture of last frame
|
||||||
-w write result to file [this is default if nothing else is stated]
|
-w write result to file [this is default if nothing else is stated]
|
||||||
|
@ -35,7 +34,6 @@ SCENE_NOT_FOUND_MESSAGE = """
|
||||||
CHOOSE_NUMBER_MESSAGE = """
|
CHOOSE_NUMBER_MESSAGE = """
|
||||||
Choose number corresponding to desired scene/arguments.
|
Choose number corresponding to desired scene/arguments.
|
||||||
(Use comma separated list for multiple entries)
|
(Use comma separated list for multiple entries)
|
||||||
|
|
||||||
Choice(s): """
|
Choice(s): """
|
||||||
INVALID_NUMBER_MESSAGE = "Fine then, if you don't want to give a valid number I'll just quit"
|
INVALID_NUMBER_MESSAGE = "Fine then, if you don't want to give a valid number I'll just quit"
|
||||||
|
|
||||||
|
@ -95,6 +93,7 @@ def get_configuration():
|
||||||
"save_pngs" : args.save_pngs,
|
"save_pngs" : args.save_pngs,
|
||||||
#If -t is passed in (for transparent), this will be RGBA
|
#If -t is passed in (for transparent), this will be RGBA
|
||||||
"saved_image_mode": "RGBA" if args.transparent else "RGB",
|
"saved_image_mode": "RGBA" if args.transparent else "RGB",
|
||||||
|
"movie_file_extension" : ".mov" if args.transparent else ".mp4",
|
||||||
"quiet" : args.quiet or args.write_all,
|
"quiet" : args.quiet or args.write_all,
|
||||||
"ignore_waits" : args.preview,
|
"ignore_waits" : args.preview,
|
||||||
"write_all" : args.write_all,
|
"write_all" : args.write_all,
|
||||||
|
@ -237,6 +236,7 @@ def main():
|
||||||
"write_to_movie",
|
"write_to_movie",
|
||||||
"output_directory",
|
"output_directory",
|
||||||
"save_pngs",
|
"save_pngs",
|
||||||
|
"movie_file_extension",
|
||||||
"start_at_animation_number",
|
"start_at_animation_number",
|
||||||
"end_at_animation_number",
|
"end_at_animation_number",
|
||||||
]
|
]
|
||||||
|
@ -260,4 +260,4 @@ def main():
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
main()
|
main()
|
|
@ -693,6 +693,7 @@ class DictAsObject(object):
|
||||||
def __init__(self, dict):
|
def __init__(self, dict):
|
||||||
self.__dict__ = dict
|
self.__dict__ = dict
|
||||||
|
|
||||||
|
# Just to have a less heavyweight name for this extremely common operation
|
||||||
#
|
#
|
||||||
# We may wish to have more fine-grained control over division by zero behavior
|
# We may wish to have more fine-grained control over division by zero behavior
|
||||||
# in the future (separate specifiable values for 0/0 and x/0 with x != 0),
|
# in the future (separate specifiable values for 0/0 and x/0 with x != 0),
|
||||||
|
@ -707,7 +708,6 @@ def fdiv(a, b, zero_over_zero_value = None):
|
||||||
|
|
||||||
return np.true_divide(a, b, out = out, where = where)
|
return np.true_divide(a, b, out = out, where = where)
|
||||||
|
|
||||||
|
|
||||||
def add_extension_if_not_present(file_name, extension):
|
def add_extension_if_not_present(file_name, extension):
|
||||||
# This could conceivably be smarter about handling existing differing extensions
|
# This could conceivably be smarter about handling existing differing extensions
|
||||||
if(file_name[-len(extension):] != extension):
|
if(file_name[-len(extension):] != extension):
|
||||||
|
|
|
@ -389,6 +389,9 @@ class Mobject(Container):
|
||||||
def stretch_to_fit_height(self, height, **kwargs):
|
def stretch_to_fit_height(self, height, **kwargs):
|
||||||
return self.rescale_to_fit(height, 1, stretch = True, **kwargs)
|
return self.rescale_to_fit(height, 1, stretch = True, **kwargs)
|
||||||
|
|
||||||
|
def stretch_to_fit_depth(self, depth, **kwargs):
|
||||||
|
return self.rescale_to_fit(depth, 1, stretch = True, **kwargs)
|
||||||
|
|
||||||
def scale_to_fit_width(self, width, **kwargs):
|
def scale_to_fit_width(self, width, **kwargs):
|
||||||
return self.rescale_to_fit(width, 0, stretch = False, **kwargs)
|
return self.rescale_to_fit(width, 0, stretch = False, **kwargs)
|
||||||
|
|
||||||
|
|
|
@ -37,9 +37,9 @@ class SVGMobject(VMobject):
|
||||||
if self.file_name is None:
|
if self.file_name is None:
|
||||||
raise Exception("Must specify file for SVGMobject")
|
raise Exception("Must specify file for SVGMobject")
|
||||||
possible_paths = [
|
possible_paths = [
|
||||||
self.file_name,
|
|
||||||
os.path.join(SVG_IMAGE_DIR, self.file_name),
|
os.path.join(SVG_IMAGE_DIR, self.file_name),
|
||||||
os.path.join(SVG_IMAGE_DIR, self.file_name + ".svg"),
|
os.path.join(SVG_IMAGE_DIR, self.file_name + ".svg"),
|
||||||
|
self.file_name,
|
||||||
]
|
]
|
||||||
for path in possible_paths:
|
for path in possible_paths:
|
||||||
if os.path.exists(path):
|
if os.path.exists(path):
|
||||||
|
|
|
@ -82,7 +82,7 @@ class Scene(Container):
|
||||||
def setup(self):
|
def setup(self):
|
||||||
"""
|
"""
|
||||||
This is meant to be implement by any scenes which
|
This is meant to be implement by any scenes which
|
||||||
are commonly subclassed, and have some common setup
|
are comonly subclassed, and have some common setup
|
||||||
involved before the construct method is called.
|
involved before the construct method is called.
|
||||||
"""
|
"""
|
||||||
pass
|
pass
|
||||||
|
@ -366,7 +366,6 @@ class Scene(Container):
|
||||||
Each arg can either be an animation, or a mobject method
|
Each arg can either be an animation, or a mobject method
|
||||||
followed by that methods arguments (and potentially follow
|
followed by that methods arguments (and potentially follow
|
||||||
by a dict of kwargs for that method).
|
by a dict of kwargs for that method).
|
||||||
|
|
||||||
This animation list is built by going through the args list,
|
This animation list is built by going through the args list,
|
||||||
and each animation is simply added, but when a mobject method
|
and each animation is simply added, but when a mobject method
|
||||||
s hit, a MoveToTarget animation is built using the args that
|
s hit, a MoveToTarget animation is built using the args that
|
||||||
|
@ -387,7 +386,7 @@ class Scene(Container):
|
||||||
animations.pop()
|
animations.pop()
|
||||||
#method should already have target then.
|
#method should already have target then.
|
||||||
else:
|
else:
|
||||||
mobject.target = mobject.deepcopy()
|
mobject.generate_target()
|
||||||
#
|
#
|
||||||
if len(state["method_args"]) > 0 and isinstance(state["method_args"][-1], dict):
|
if len(state["method_args"]) > 0 and isinstance(state["method_args"][-1], dict):
|
||||||
method_kwargs = state["method_args"].pop()
|
method_kwargs = state["method_args"].pop()
|
||||||
|
@ -578,17 +577,12 @@ class Scene(Container):
|
||||||
FFMPEG_BIN,
|
FFMPEG_BIN,
|
||||||
'-y', # overwrite output file if it exists
|
'-y', # overwrite output file if it exists
|
||||||
'-f', 'rawvideo',
|
'-f', 'rawvideo',
|
||||||
'-vcodec','rawvideo',
|
|
||||||
'-s', '%dx%d'%(width, height), # size of one frame
|
'-s', '%dx%d'%(width, height), # size of one frame
|
||||||
'-pix_fmt', 'rgba',
|
'-pix_fmt', 'rgba',
|
||||||
'-r', str(fps), # frames per second
|
'-r', str(fps), # frames per second
|
||||||
'-i', '-', # The imput comes from a pipe
|
'-i', '-', # The imput comes from a pipe
|
||||||
'-an', # Tells FFMPEG not to expect any audio
|
'-an', # Tells FFMPEG not to expect any audio
|
||||||
'-vcodec', 'mpeg',
|
|
||||||
'-c:v', 'libx264',
|
|
||||||
'-pix_fmt', 'yuv420p',
|
|
||||||
'-loglevel', 'error',
|
'-loglevel', 'error',
|
||||||
temp_file_path,
|
|
||||||
]
|
]
|
||||||
if self.movie_file_extension == ".mov":
|
if self.movie_file_extension == ".mov":
|
||||||
# This is if the background of the exported video
|
# This is if the background of the exported video
|
||||||
|
@ -624,4 +618,3 @@ class EndSceneEarlyException(Exception):
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -123,8 +123,11 @@ class PatreonEndScreen(PatreonThanks):
|
||||||
"n_patron_columns" : 3,
|
"n_patron_columns" : 3,
|
||||||
"max_patron_width" : 3,
|
"max_patron_width" : 3,
|
||||||
"run_time" : 20,
|
"run_time" : 20,
|
||||||
|
"randomize_order" : True,
|
||||||
}
|
}
|
||||||
def construct(self):
|
def construct(self):
|
||||||
|
if self.randomize_order:
|
||||||
|
random.shuffle(self.specific_patrons)
|
||||||
self.add_title()
|
self.add_title()
|
||||||
self.scroll_through_patrons()
|
self.scroll_through_patrons()
|
||||||
|
|
||||||
|
@ -141,7 +144,6 @@ class PatreonEndScreen(PatreonThanks):
|
||||||
pi.next_to(title, vect, buff = MED_LARGE_BUFF)
|
pi.next_to(title, vect, buff = MED_LARGE_BUFF)
|
||||||
self.add_foreground_mobjects(title, randy, morty)
|
self.add_foreground_mobjects(title, randy, morty)
|
||||||
|
|
||||||
|
|
||||||
def scroll_through_patrons(self):
|
def scroll_through_patrons(self):
|
||||||
logo_box = Square(side_length = 2.5)
|
logo_box = Square(side_length = 2.5)
|
||||||
logo_box.to_corner(DOWN+LEFT, buff = MED_LARGE_BUFF)
|
logo_box.to_corner(DOWN+LEFT, buff = MED_LARGE_BUFF)
|
||||||
|
@ -176,7 +178,7 @@ class PatreonEndScreen(PatreonThanks):
|
||||||
aligned_edge = UP,
|
aligned_edge = UP,
|
||||||
)
|
)
|
||||||
columns.scale_to_fit_width(total_width - 1)
|
columns.scale_to_fit_width(total_width - 1)
|
||||||
columns.next_to(black_rect, DOWN, LARGE_BUFF)
|
columns.next_to(black_rect, DOWN, 3*LARGE_BUFF)
|
||||||
columns.to_edge(RIGHT)
|
columns.to_edge(RIGHT)
|
||||||
|
|
||||||
self.play(
|
self.play(
|
||||||
|
|
|
@ -128,7 +128,6 @@ class LightSource(VMobject):
|
||||||
self.camera_mob = new_cam_mob
|
self.camera_mob = new_cam_mob
|
||||||
self.spotlight.camera_mob = new_cam_mob
|
self.spotlight.camera_mob = new_cam_mob
|
||||||
|
|
||||||
|
|
||||||
def set_screen(self, new_screen):
|
def set_screen(self, new_screen):
|
||||||
if self.has_screen():
|
if self.has_screen():
|
||||||
self.spotlight.screen = new_screen
|
self.spotlight.screen = new_screen
|
||||||
|
@ -160,9 +159,6 @@ class LightSource(VMobject):
|
||||||
# in any case
|
# in any case
|
||||||
self.screen = new_screen
|
self.screen = new_screen
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def move_source_to(self,point):
|
def move_source_to(self,point):
|
||||||
apoint = np.array(point)
|
apoint = np.array(point)
|
||||||
v = apoint - self.get_source_point()
|
v = apoint - self.get_source_point()
|
||||||
|
@ -195,14 +191,13 @@ class LightSource(VMobject):
|
||||||
self.spotlight.update_sectors()
|
self.spotlight.update_sectors()
|
||||||
self.update_shadow()
|
self.update_shadow()
|
||||||
|
|
||||||
|
|
||||||
def update_lighthouse(self):
|
def update_lighthouse(self):
|
||||||
new_lh = Lighthouse()
|
self.lighthouse.move_to(self.get_source_point())
|
||||||
new_lh.move_to(ORIGIN)
|
# new_lh = Lighthouse()
|
||||||
new_lh.apply_matrix(self.rotation_matrix())
|
# new_lh.move_to(ORIGIN)
|
||||||
new_lh.shift(self.get_source_point())
|
# new_lh.apply_matrix(self.rotation_matrix())
|
||||||
self.lighthouse.submobjects = new_lh.submobjects
|
# new_lh.shift(self.get_source_point())
|
||||||
|
# self.lighthouse.submobjects = new_lh.submobjects
|
||||||
|
|
||||||
def update_ambient(self):
|
def update_ambient(self):
|
||||||
new_ambient_light = AmbientLight(
|
new_ambient_light = AmbientLight(
|
||||||
|
@ -217,12 +212,9 @@ class LightSource(VMobject):
|
||||||
new_ambient_light.move_source_to(self.get_source_point())
|
new_ambient_light.move_source_to(self.get_source_point())
|
||||||
self.ambient_light.submobjects = new_ambient_light.submobjects
|
self.ambient_light.submobjects = new_ambient_light.submobjects
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def get_source_point(self):
|
def get_source_point(self):
|
||||||
return self.source_point.get_location()
|
return self.source_point.get_location()
|
||||||
|
|
||||||
|
|
||||||
def rotation_matrix(self):
|
def rotation_matrix(self):
|
||||||
|
|
||||||
if self.camera_mob == None:
|
if self.camera_mob == None:
|
||||||
|
@ -247,9 +239,7 @@ class LightSource(VMobject):
|
||||||
R = np.dot(R2, R1)
|
R = np.dot(R2, R1)
|
||||||
return R
|
return R
|
||||||
|
|
||||||
|
|
||||||
def update_shadow(self):
|
def update_shadow(self):
|
||||||
|
|
||||||
point = self.get_source_point()
|
point = self.get_source_point()
|
||||||
projected_screen_points = []
|
projected_screen_points = []
|
||||||
if not self.has_screen():
|
if not self.has_screen():
|
||||||
|
@ -319,7 +309,6 @@ class LightSource(VMobject):
|
||||||
self.shadow.mark_paths_closed = True
|
self.shadow.mark_paths_closed = True
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class SwitchOn(LaggedStart):
|
class SwitchOn(LaggedStart):
|
||||||
CONFIG = {
|
CONFIG = {
|
||||||
"lag_ratio": 0.2,
|
"lag_ratio": 0.2,
|
||||||
|
@ -329,9 +318,9 @@ class SwitchOn(LaggedStart):
|
||||||
def __init__(self, light, **kwargs):
|
def __init__(self, light, **kwargs):
|
||||||
if (not isinstance(light,AmbientLight) and not isinstance(light,Spotlight)):
|
if (not isinstance(light,AmbientLight) and not isinstance(light,Spotlight)):
|
||||||
raise Exception("Only AmbientLights and Spotlights can be switched on")
|
raise Exception("Only AmbientLights and Spotlights can be switched on")
|
||||||
LaggedStart.__init__(self,
|
LaggedStart.__init__(
|
||||||
FadeIn, light, **kwargs)
|
self, FadeIn, light, **kwargs
|
||||||
|
)
|
||||||
|
|
||||||
class SwitchOff(LaggedStart):
|
class SwitchOff(LaggedStart):
|
||||||
CONFIG = {
|
CONFIG = {
|
||||||
|
@ -347,9 +336,6 @@ class SwitchOff(LaggedStart):
|
||||||
FadeOut, light, **kwargs)
|
FadeOut, light, **kwargs)
|
||||||
light.submobjects = light.submobjects[::-1]
|
light.submobjects = light.submobjects[::-1]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class Lighthouse(SVGMobject):
|
class Lighthouse(SVGMobject):
|
||||||
CONFIG = {
|
CONFIG = {
|
||||||
"file_name" : "lighthouse",
|
"file_name" : "lighthouse",
|
||||||
|
@ -361,7 +347,6 @@ class Lighthouse(SVGMobject):
|
||||||
def move_to(self,point):
|
def move_to(self,point):
|
||||||
self.next_to(point, DOWN, buff = 0)
|
self.next_to(point, DOWN, buff = 0)
|
||||||
|
|
||||||
|
|
||||||
class AmbientLight(VMobject):
|
class AmbientLight(VMobject):
|
||||||
|
|
||||||
# Parameters are:
|
# Parameters are:
|
||||||
|
@ -377,8 +362,8 @@ class AmbientLight(VMobject):
|
||||||
"opacity_function" : lambda r : 1.0/(r+1.0)**2,
|
"opacity_function" : lambda r : 1.0/(r+1.0)**2,
|
||||||
"color" : LIGHT_COLOR,
|
"color" : LIGHT_COLOR,
|
||||||
"max_opacity" : 1.0,
|
"max_opacity" : 1.0,
|
||||||
"num_levels" : 10,
|
"num_levels" : NUM_LEVELS,
|
||||||
"radius" : 10.0
|
"radius" : 5.0
|
||||||
}
|
}
|
||||||
|
|
||||||
def generate_points(self):
|
def generate_points(self):
|
||||||
|
@ -438,21 +423,7 @@ class AmbientLight(VMobject):
|
||||||
submob.set_fill(opacity = new_submob_alpha)
|
submob.set_fill(opacity = new_submob_alpha)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class Spotlight(VMobject):
|
class Spotlight(VMobject):
|
||||||
|
|
||||||
CONFIG = {
|
CONFIG = {
|
||||||
"source_point": VectorizedPoint(location = ORIGIN, stroke_width = 0, fill_opacity = 0),
|
"source_point": VectorizedPoint(location = ORIGIN, stroke_width = 0, fill_opacity = 0),
|
||||||
"opacity_function" : lambda r : 1.0/(r/2+1.0)**2,
|
"opacity_function" : lambda r : 1.0/(r/2+1.0)**2,
|
||||||
|
@ -481,13 +452,10 @@ class Spotlight(VMobject):
|
||||||
w = project_along_vector(point,v)
|
w = project_along_vector(point,v)
|
||||||
return w
|
return w
|
||||||
|
|
||||||
|
|
||||||
def get_source_point(self):
|
def get_source_point(self):
|
||||||
return self.source_point.get_location()
|
return self.source_point.get_location()
|
||||||
|
|
||||||
|
|
||||||
def generate_points(self):
|
def generate_points(self):
|
||||||
|
|
||||||
self.submobjects = []
|
self.submobjects = []
|
||||||
|
|
||||||
self.add(self.source_point)
|
self.add(self.source_point)
|
||||||
|
@ -503,13 +471,7 @@ class Spotlight(VMobject):
|
||||||
new_sector = self.new_sector(r,dr,lower_angle,upper_angle)
|
new_sector = self.new_sector(r,dr,lower_angle,upper_angle)
|
||||||
self.add(new_sector)
|
self.add(new_sector)
|
||||||
|
|
||||||
|
|
||||||
def new_sector(self,r,dr,lower_angle,upper_angle):
|
def new_sector(self,r,dr,lower_angle,upper_angle):
|
||||||
# Note: I'm not looking _too_ closely at the implementation
|
|
||||||
# of these updates based on viewing angles and such. It seems to
|
|
||||||
# behave as intended, but let me know if you'd like more thorough
|
|
||||||
# scrutiny
|
|
||||||
|
|
||||||
alpha = self.max_opacity * self.opacity_function(r)
|
alpha = self.max_opacity * self.opacity_function(r)
|
||||||
annular_sector = AnnularSector(
|
annular_sector = AnnularSector(
|
||||||
inner_radius = r,
|
inner_radius = r,
|
||||||
|
@ -545,7 +507,6 @@ class Spotlight(VMobject):
|
||||||
else:
|
else:
|
||||||
return -absolute_angle
|
return -absolute_angle
|
||||||
|
|
||||||
|
|
||||||
def viewing_angles(self,screen):
|
def viewing_angles(self,screen):
|
||||||
|
|
||||||
screen_points = screen.get_anchors()
|
screen_points = screen.get_anchors()
|
||||||
|
@ -572,7 +533,6 @@ class Spotlight(VMobject):
|
||||||
|
|
||||||
return lower_ray, upper_ray
|
return lower_ray, upper_ray
|
||||||
|
|
||||||
|
|
||||||
def opening_angle(self):
|
def opening_angle(self):
|
||||||
l,u = self.viewing_angles(self.screen)
|
l,u = self.viewing_angles(self.screen)
|
||||||
return u - l
|
return u - l
|
||||||
|
@ -592,21 +552,20 @@ class Spotlight(VMobject):
|
||||||
self.update_sectors()
|
self.update_sectors()
|
||||||
return self
|
return self
|
||||||
|
|
||||||
|
|
||||||
def update_sectors(self):
|
def update_sectors(self):
|
||||||
if self.screen == None:
|
if self.screen == None:
|
||||||
return
|
return
|
||||||
for submob in self.submobject_family():
|
for submob in self.submobjects:
|
||||||
if type(submob) == AnnularSector:
|
if type(submob) == AnnularSector:
|
||||||
lower_angle, upper_angle = self.viewing_angles(self.screen)
|
lower_angle, upper_angle = self.viewing_angles(self.screen)
|
||||||
#dr = submob.outer_radius - submob.inner_radius
|
#dr = submob.outer_radius - submob.inner_radius
|
||||||
dr = self.radius / self.num_levels
|
dr = self.radius / self.num_levels
|
||||||
new_submob = self.new_sector(submob.inner_radius,dr,lower_angle,upper_angle)
|
new_submob = self.new_sector(
|
||||||
submob.points = new_submob.points
|
submob.inner_radius, dr, lower_angle, upper_angle
|
||||||
submob.set_fill(opacity = 10 * self.opacity_function(submob.outer_radius))
|
)
|
||||||
|
# submob.points = new_submob.points
|
||||||
|
# submob.set_fill(opacity = 10 * self.opacity_function(submob.outer_radius))
|
||||||
|
Transform(submob, new_submob).update(1)
|
||||||
|
|
||||||
def dimming(self,new_alpha):
|
def dimming(self,new_alpha):
|
||||||
old_alpha = self.max_opacity
|
old_alpha = self.max_opacity
|
||||||
|
@ -640,7 +599,27 @@ class Spotlight(VMobject):
|
||||||
|
|
||||||
|
|
||||||
class ScreenTracker(ContinualAnimation):
|
class ScreenTracker(ContinualAnimation):
|
||||||
|
def __init__(self, light_source, **kwargs):
|
||||||
|
self.light_source = light_source
|
||||||
|
dummy_mob = Mobject()
|
||||||
|
ContinualAnimation.__init__(self, dummy_mob, **kwargs)
|
||||||
|
|
||||||
def update_mobject(self, dt):
|
def update_mobject(self, dt):
|
||||||
self.mobject.update()
|
self.light_source.update()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -144,7 +144,6 @@ class ContinualChangingDecimal(ContinualAnimation):
|
||||||
|
|
||||||
def update_mobject(self, dt):
|
def update_mobject(self, dt):
|
||||||
self.anim.update(self.internal_time)
|
self.anim.update(self.internal_time)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue