2017-03-08 15:18:09 -08:00
|
|
|
|
|
|
|
from helpers import *
|
|
|
|
|
|
|
|
from scene.scene import Scene
|
2017-12-08 17:57:32 -08:00
|
|
|
from animation import Animation
|
2018-03-14 14:52:33 -07:00
|
|
|
from animation.simple_animations import Write, DrawBorderThenFill
|
|
|
|
from animation.compositions import LaggedStart
|
2017-04-14 23:30:29 -07:00
|
|
|
from animation.transform import FadeIn, FadeOut, ApplyMethod
|
2017-03-08 15:18:09 -08:00
|
|
|
from mobject.vectorized_mobject import VGroup
|
|
|
|
from mobject.tex_mobject import TexMobject, TextMobject
|
2017-12-08 17:57:32 -08:00
|
|
|
from topics.characters import Mortimer, Randolph, Blink
|
2017-03-08 15:18:09 -08:00
|
|
|
from topics.objects import PatreonLogo
|
2017-12-08 17:57:32 -08:00
|
|
|
from topics.geometry import Square, Rectangle, DashedLine
|
2017-03-08 15:18:09 -08:00
|
|
|
|
|
|
|
|
|
|
|
class OpeningQuote(Scene):
|
|
|
|
CONFIG = {
|
2017-03-29 16:06:10 -07:00
|
|
|
"quote" : [],
|
2017-03-22 15:06:17 -07:00
|
|
|
"quote_arg_separator" : " ",
|
2017-03-29 16:06:10 -07:00
|
|
|
"highlighted_quote_terms" : {},
|
|
|
|
"author" : "",
|
2017-03-08 15:18:09 -08:00
|
|
|
"fade_in_kwargs" : {
|
|
|
|
"submobject_mode" : "lagged_start",
|
|
|
|
"rate_func" : None,
|
2017-03-22 15:06:17 -07:00
|
|
|
"lag_factor" : 4,
|
2017-03-08 15:18:09 -08:00
|
|
|
"run_time" : 5,
|
|
|
|
},
|
|
|
|
}
|
|
|
|
def construct(self):
|
2017-04-12 09:06:04 -07:00
|
|
|
self.quote = self.get_quote()
|
|
|
|
self.author = self.get_author(self.quote)
|
2017-03-08 15:18:09 -08:00
|
|
|
|
2017-04-12 09:06:04 -07:00
|
|
|
self.play(FadeIn(self.quote, **self.fade_in_kwargs))
|
2018-01-15 19:15:05 -08:00
|
|
|
self.wait(2)
|
2017-04-12 09:06:04 -07:00
|
|
|
self.play(Write(self.author, run_time = 3))
|
2018-01-15 19:15:05 -08:00
|
|
|
self.wait()
|
2017-03-08 15:18:09 -08:00
|
|
|
|
|
|
|
def get_quote(self, max_width = 2*SPACE_WIDTH-1):
|
2017-03-22 15:06:17 -07:00
|
|
|
text_mobject_kwargs = {
|
|
|
|
"alignment" : "",
|
|
|
|
"arg_separator" : self.quote_arg_separator,
|
|
|
|
}
|
2017-03-08 15:18:09 -08:00
|
|
|
if isinstance(self.quote, str):
|
2017-03-22 15:06:17 -07:00
|
|
|
quote = TextMobject("``%s''"%self.quote.strip(), **text_mobject_kwargs)
|
2017-03-08 15:18:09 -08:00
|
|
|
else:
|
2017-07-20 13:37:12 -07:00
|
|
|
words = ["\\Large ``"] + list(self.quote) + ["''"]
|
2017-03-22 15:06:17 -07:00
|
|
|
quote = TextMobject(*words, **text_mobject_kwargs)
|
2017-03-08 15:18:09 -08:00
|
|
|
##TODO, make less hacky
|
2017-04-25 22:14:16 -07:00
|
|
|
if self.quote_arg_separator == " ":
|
|
|
|
quote[0].shift(0.2*RIGHT)
|
|
|
|
quote[-1].shift(0.2*LEFT)
|
2017-03-08 15:18:09 -08:00
|
|
|
for term, color in self.highlighted_quote_terms.items():
|
|
|
|
quote.highlight_by_tex(term, color)
|
|
|
|
quote.to_edge(UP)
|
|
|
|
if quote.get_width() > max_width:
|
|
|
|
quote.scale_to_fit_width(max_width)
|
|
|
|
return quote
|
|
|
|
|
|
|
|
def get_author(self, quote):
|
2017-07-20 13:37:12 -07:00
|
|
|
author = TextMobject("\\Large -" + self.author)
|
2017-03-08 15:18:09 -08:00
|
|
|
author.next_to(quote, DOWN)
|
|
|
|
author.highlight(YELLOW)
|
|
|
|
return author
|
|
|
|
|
|
|
|
class PatreonThanks(Scene):
|
|
|
|
CONFIG = {
|
2017-11-02 22:58:54 -07:00
|
|
|
"specific_patrons" : [],
|
2017-06-14 21:54:21 -07:00
|
|
|
"max_patron_group_size" : 20,
|
2017-07-05 19:21:24 -07:00
|
|
|
"patron_scale_val" : 0.8,
|
2017-03-08 15:18:09 -08:00
|
|
|
}
|
|
|
|
def construct(self):
|
|
|
|
morty = Mortimer()
|
|
|
|
morty.next_to(ORIGIN, DOWN)
|
|
|
|
|
|
|
|
patreon_logo = PatreonLogo()
|
2017-06-14 21:54:21 -07:00
|
|
|
patreon_logo.to_edge(UP)
|
2017-03-08 15:18:09 -08:00
|
|
|
|
2017-06-14 21:54:21 -07:00
|
|
|
n_patrons = len(self.specific_patrons)
|
2017-04-14 23:30:29 -07:00
|
|
|
patrons = map(TextMobject, self.specific_patrons)
|
2017-06-14 21:54:21 -07:00
|
|
|
num_groups = float(len(patrons)) / self.max_patron_group_size
|
2017-04-20 13:30:51 -07:00
|
|
|
proportion_range = np.linspace(0, 1, num_groups + 1)
|
|
|
|
indices = (len(patrons)*proportion_range).astype('int')
|
|
|
|
patron_groups = [
|
|
|
|
VGroup(*patrons[i:j])
|
|
|
|
for i, j in zip(indices, indices[1:])
|
|
|
|
]
|
|
|
|
|
|
|
|
for i, group in enumerate(patron_groups):
|
2017-06-14 21:54:21 -07:00
|
|
|
left_group = VGroup(*group[:len(group)/2])
|
|
|
|
right_group = VGroup(*group[len(group)/2:])
|
|
|
|
for subgroup, vect in (left_group, LEFT), (right_group, RIGHT):
|
|
|
|
subgroup.arrange_submobjects(DOWN, aligned_edge = LEFT)
|
|
|
|
subgroup.scale(self.patron_scale_val)
|
|
|
|
subgroup.to_edge(vect)
|
|
|
|
|
|
|
|
last_group = None
|
2017-04-14 23:30:29 -07:00
|
|
|
for i, group in enumerate(patron_groups):
|
2017-06-14 21:54:21 -07:00
|
|
|
anims = []
|
|
|
|
if last_group is not None:
|
|
|
|
self.play(
|
|
|
|
FadeOut(last_group),
|
|
|
|
morty.look, UP+LEFT
|
|
|
|
)
|
|
|
|
else:
|
|
|
|
anims += [
|
|
|
|
DrawBorderThenFill(patreon_logo),
|
|
|
|
]
|
|
|
|
self.play(
|
|
|
|
LaggedStart(
|
|
|
|
FadeIn, group,
|
|
|
|
run_time = 2,
|
2017-04-14 23:30:29 -07:00
|
|
|
),
|
2017-06-14 21:54:21 -07:00
|
|
|
morty.change, "gracious", group.get_corner(UP+LEFT),
|
|
|
|
*anims
|
|
|
|
)
|
|
|
|
self.play(morty.look_at, group.get_corner(DOWN+LEFT))
|
|
|
|
self.play(morty.look_at, group.get_corner(UP+RIGHT))
|
|
|
|
self.play(morty.look_at, group.get_corner(DOWN+RIGHT))
|
2017-04-14 23:30:29 -07:00
|
|
|
self.play(Blink(morty))
|
2017-06-14 21:54:21 -07:00
|
|
|
last_group = group
|
2017-03-08 15:18:09 -08:00
|
|
|
|
2017-12-08 17:57:32 -08:00
|
|
|
class PatreonEndScreen(PatreonThanks):
|
|
|
|
CONFIG = {
|
|
|
|
"n_patron_columns" : 3,
|
|
|
|
"max_patron_width" : 3,
|
|
|
|
"run_time" : 20,
|
2018-03-04 10:43:35 -08:00
|
|
|
"randomize_order" : True,
|
2017-12-08 17:57:32 -08:00
|
|
|
}
|
|
|
|
def construct(self):
|
2018-03-04 10:43:35 -08:00
|
|
|
if self.randomize_order:
|
|
|
|
random.shuffle(self.specific_patrons)
|
2017-12-08 17:57:32 -08:00
|
|
|
self.add_title()
|
|
|
|
self.scroll_through_patrons()
|
|
|
|
|
|
|
|
def add_title(self):
|
2018-03-14 14:52:33 -07:00
|
|
|
title = self.title = TextMobject("Clicky Stuffs")
|
2017-12-08 17:57:32 -08:00
|
|
|
title.scale(1.5)
|
|
|
|
title.to_edge(UP, buff = MED_SMALL_BUFF)
|
|
|
|
|
|
|
|
randy, morty = Randolph(), Mortimer()
|
|
|
|
for pi, vect in (randy, LEFT), (morty, RIGHT):
|
|
|
|
pi.scale_to_fit_height(title.get_height())
|
|
|
|
pi.change_mode("thinking")
|
|
|
|
pi.look(DOWN)
|
|
|
|
pi.next_to(title, vect, buff = MED_LARGE_BUFF)
|
|
|
|
self.add_foreground_mobjects(title, randy, morty)
|
|
|
|
|
|
|
|
def scroll_through_patrons(self):
|
|
|
|
logo_box = Square(side_length = 2.5)
|
|
|
|
logo_box.to_corner(DOWN+LEFT, buff = MED_LARGE_BUFF)
|
|
|
|
total_width = SPACE_WIDTH - logo_box.get_right()[0]
|
|
|
|
|
|
|
|
black_rect = Rectangle(
|
|
|
|
fill_color = BLACK,
|
|
|
|
fill_opacity = 1,
|
|
|
|
stroke_width = 0,
|
|
|
|
width = 2*SPACE_WIDTH,
|
|
|
|
height = 1.1*SPACE_HEIGHT
|
|
|
|
)
|
|
|
|
black_rect.to_edge(UP, buff = 0)
|
|
|
|
line = DashedLine(SPACE_WIDTH*LEFT, SPACE_WIDTH*RIGHT)
|
|
|
|
line.move_to(black_rect, DOWN)
|
|
|
|
line.shift(SMALL_BUFF*SMALL_BUFF*DOWN)
|
|
|
|
self.add(line)
|
|
|
|
|
|
|
|
patrons = VGroup(*map(TextMobject, self.specific_patrons))
|
|
|
|
patrons.scale(self.patron_scale_val)
|
|
|
|
for patron in patrons:
|
|
|
|
if patron.get_width() > self.max_patron_width:
|
|
|
|
patron.scale_to_fit_width(self.max_patron_width)
|
|
|
|
columns = VGroup(*[
|
|
|
|
VGroup(
|
|
|
|
*patrons[i::self.n_patron_columns]
|
|
|
|
).arrange_submobjects(DOWN, buff = MED_SMALL_BUFF)
|
|
|
|
for i in range(self.n_patron_columns)
|
|
|
|
])
|
|
|
|
columns.arrange_submobjects(
|
|
|
|
RIGHT, buff = LARGE_BUFF,
|
|
|
|
aligned_edge = UP,
|
|
|
|
)
|
|
|
|
columns.scale_to_fit_width(total_width - 1)
|
2018-02-28 21:39:25 -08:00
|
|
|
columns.next_to(black_rect, DOWN, 3*LARGE_BUFF)
|
2017-12-08 17:57:32 -08:00
|
|
|
columns.to_edge(RIGHT)
|
|
|
|
|
|
|
|
self.play(
|
|
|
|
columns.next_to, SPACE_HEIGHT*DOWN, UP, LARGE_BUFF,
|
|
|
|
columns.to_edge, RIGHT,
|
|
|
|
Animation(black_rect),
|
|
|
|
rate_func = None,
|
|
|
|
run_time = self.run_time,
|
|
|
|
)
|
|
|
|
|
2017-06-20 14:05:48 -07:00
|
|
|
class ExternallyAnimatedScene(Scene):
|
|
|
|
def construct(self):
|
|
|
|
raise Exception("Don't actually run this class.")
|
2017-03-08 15:18:09 -08:00
|
|
|
|
2017-08-05 20:47:06 -07:00
|
|
|
class TODOStub(Scene):
|
|
|
|
CONFIG = {
|
|
|
|
"message" : ""
|
|
|
|
}
|
|
|
|
def construct(self):
|
|
|
|
self.add(TextMobject("TODO: %s"%self.message))
|
2018-01-15 19:15:05 -08:00
|
|
|
self.wait()
|
2017-03-08 15:18:09 -08:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|