mirror of
https://github.com/3b1b/manim.git
synced 2025-07-31 22:13:30 +08:00
Introduction of cryptocurrency video
This commit is contained in:
11
camera.py
11
camera.py
@ -11,7 +11,7 @@ from mobject import PMobject, VMobject
|
|||||||
|
|
||||||
class Camera(object):
|
class Camera(object):
|
||||||
CONFIG = {
|
CONFIG = {
|
||||||
#background of a different shape will overwrite this
|
"background_image" : None,
|
||||||
"pixel_shape" : (DEFAULT_HEIGHT, DEFAULT_WIDTH),
|
"pixel_shape" : (DEFAULT_HEIGHT, DEFAULT_WIDTH),
|
||||||
#this will be resized to match pixel_shape
|
#this will be resized to match pixel_shape
|
||||||
"space_shape" : (SPACE_HEIGHT, SPACE_WIDTH),
|
"space_shape" : (SPACE_HEIGHT, SPACE_WIDTH),
|
||||||
@ -44,8 +44,13 @@ class Camera(object):
|
|||||||
self.space_shape = (space_height, space_width)
|
self.space_shape = (space_height, space_width)
|
||||||
|
|
||||||
def init_background(self):
|
def init_background(self):
|
||||||
if self.background is not None:
|
if self.background_image is not None:
|
||||||
self.pixel_shape = self.background.shape[:2]
|
path = get_full_image_path(self.background_image)
|
||||||
|
image = Image.open(path).convert('RGB')
|
||||||
|
height, width = self.pixel_shape
|
||||||
|
#TODO, how to gracefully handle backgrounds
|
||||||
|
#with different sizes?
|
||||||
|
self.background = np.array(image)[:height, :width]
|
||||||
else:
|
else:
|
||||||
background_rgb = color_to_int_rgb(self.background_color)
|
background_rgb = color_to_int_rgb(self.background_color)
|
||||||
self.background = np.zeros(
|
self.background = np.zeros(
|
||||||
|
374
crypto.py
374
crypto.py
@ -20,6 +20,7 @@ from topics.three_dimensions import *
|
|||||||
from topics.objects import *
|
from topics.objects import *
|
||||||
from topics.probability import *
|
from topics.probability import *
|
||||||
from topics.complex_numbers import *
|
from topics.complex_numbers import *
|
||||||
|
from topics.common_scenes import *
|
||||||
from scene import Scene
|
from scene import Scene
|
||||||
from scene.reconfigurable_scene import ReconfigurableScene
|
from scene.reconfigurable_scene import ReconfigurableScene
|
||||||
from scene.zoomed_scene import *
|
from scene.zoomed_scene import *
|
||||||
@ -27,6 +28,13 @@ from camera import Camera
|
|||||||
from mobject.svg_mobject import *
|
from mobject.svg_mobject import *
|
||||||
from mobject.tex_mobject import *
|
from mobject.tex_mobject import *
|
||||||
|
|
||||||
|
#force_skipping
|
||||||
|
#revert_to_original_skipping_status
|
||||||
|
|
||||||
|
BITCOIN_COLOR = "#f7931a"
|
||||||
|
|
||||||
|
##################
|
||||||
|
|
||||||
class AskQuestion(Scene):
|
class AskQuestion(Scene):
|
||||||
CONFIG = {
|
CONFIG = {
|
||||||
"time_per_char" : 0.06,
|
"time_per_char" : 0.06,
|
||||||
@ -50,26 +58,352 @@ class AskQuestion(Scene):
|
|||||||
self.dither(self.time_per_char*n_spaces)
|
self.dither(self.time_per_char*n_spaces)
|
||||||
self.dither(2)
|
self.dither(2)
|
||||||
|
|
||||||
|
class BitcoinPaperHighlightTitle(ExternallyAnimatedScene):
|
||||||
|
pass
|
||||||
|
|
||||||
|
class TimeBitcoinCover(ExternallyAnimatedScene):
|
||||||
|
pass
|
||||||
|
|
||||||
|
class ListOfAttributes(Scene):
|
||||||
|
def construct(self):
|
||||||
|
logo = BitcoinLogo()
|
||||||
|
|
||||||
|
digital = TextMobject("Digital")
|
||||||
|
government, bank = buildings = [
|
||||||
|
SVGMobject(
|
||||||
|
file_name = "%s_building"%word,
|
||||||
|
height = 2,
|
||||||
|
fill_color = LIGHT_GREY,
|
||||||
|
fill_opacity = 1,
|
||||||
|
stroke_width = 0,
|
||||||
|
)
|
||||||
|
for word in "government", "bank"
|
||||||
|
]
|
||||||
|
attributes = VGroup(digital, *buildings)
|
||||||
|
attributes.arrange_submobjects(RIGHT, buff = LARGE_BUFF)
|
||||||
|
for building in buildings:
|
||||||
|
building.cross = Cross(building)
|
||||||
|
building.cross.set_stroke(width = 12)
|
||||||
|
|
||||||
|
self.play(DrawBorderThenFill(logo))
|
||||||
|
self.play(
|
||||||
|
logo.to_corner, UP+LEFT,
|
||||||
|
Write(digital, run_time = 2)
|
||||||
|
)
|
||||||
|
for building in buildings:
|
||||||
|
self.play(FadeIn(building))
|
||||||
|
self.play(ShowCreation(building.cross))
|
||||||
|
self.dither()
|
||||||
|
|
||||||
|
class UnknownAuthor(Scene):
|
||||||
|
CONFIG = {
|
||||||
|
"camera_config" : {
|
||||||
|
"background_image" : "bitcoin_paper"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
def construct(self):
|
||||||
|
rect = Rectangle(height = 0.4, width = 2.5)
|
||||||
|
rect.shift(2.45*UP)
|
||||||
|
question = TextMobject("Who is this?")
|
||||||
|
question.next_to(rect, RIGHT, buff = 1.5)
|
||||||
|
arrow = Arrow(question, rect, buff = SMALL_BUFF)
|
||||||
|
VGroup(question, arrow, rect).highlight(RED_D)
|
||||||
|
|
||||||
|
self.play(ShowCreation(rect))
|
||||||
|
self.play(
|
||||||
|
Write(question),
|
||||||
|
ShowCreation(arrow)
|
||||||
|
)
|
||||||
|
self.dither()
|
||||||
|
|
||||||
|
class NameCryptoCurrencies(TeacherStudentsScene):
|
||||||
|
def construct(self):
|
||||||
|
words = TextMobject("It's called a", "``cryptocurrency''")
|
||||||
|
words.highlight_by_tex("cryptocurrency", YELLOW)
|
||||||
|
self.teacher_says(words)
|
||||||
|
self.change_student_modes(*["pondering"]*3)
|
||||||
|
self.dither()
|
||||||
|
|
||||||
|
class CryptocurrencyMarketCaps(ExternallyAnimatedScene):
|
||||||
|
pass
|
||||||
|
|
||||||
|
class Hype(TeacherStudentsScene):
|
||||||
|
def construct(self):
|
||||||
|
self.teacher.change_mode("guilty")
|
||||||
|
phrases = map(TextMobject, [
|
||||||
|
"I want some!",
|
||||||
|
"I'll get rich, right?",
|
||||||
|
"Buy them all!"
|
||||||
|
])
|
||||||
|
modes = ["hooray", "conniving", "surprised"]
|
||||||
|
for student, phrase, mode in zip(self.students, phrases, modes):
|
||||||
|
bubble = SpeechBubble()
|
||||||
|
bubble.set_fill(BLACK, 1)
|
||||||
|
bubble.add_content(phrase)
|
||||||
|
bubble.resize_to_content()
|
||||||
|
bubble.pin_to(student)
|
||||||
|
bubble.add(phrase)
|
||||||
|
self.play(
|
||||||
|
student.change_mode, mode,
|
||||||
|
FadeIn(bubble),
|
||||||
|
)
|
||||||
|
self.dither(3)
|
||||||
|
|
||||||
|
class AskQuestionCopy(AskQuestion):
|
||||||
|
pass
|
||||||
|
|
||||||
|
class LedgerScene(PiCreatureScene):
|
||||||
|
CONFIG = {
|
||||||
|
"ledger_width" : 6,
|
||||||
|
"ledger_height" : 7,
|
||||||
|
"denomination" : "USD",
|
||||||
|
"ledger_line_height" : 0.4,
|
||||||
|
}
|
||||||
|
def setup(self):
|
||||||
|
PiCreatureScene.setup(self)
|
||||||
|
self.remove(self.pi_creatures)
|
||||||
|
|
||||||
|
def get_ledger(self):
|
||||||
|
title = TextMobject("Ledger")
|
||||||
|
rect = Rectangle(
|
||||||
|
width = self.ledger_width,
|
||||||
|
height = self.ledger_height
|
||||||
|
)
|
||||||
|
title.next_to(rect.get_top(), DOWN)
|
||||||
|
h_line = Line(rect.get_left(), rect.get_right())
|
||||||
|
h_line.scale(0.8)
|
||||||
|
h_line.set_stroke(width = 2)
|
||||||
|
h_line.next_to(title, DOWN)
|
||||||
|
content = VGroup(h_line)
|
||||||
|
|
||||||
|
self.ledger = VGroup(rect, title, h_line, content)
|
||||||
|
self.ledger.content = content
|
||||||
|
self.ledger.to_corner(UP+LEFT)
|
||||||
|
return self.ledger
|
||||||
|
|
||||||
|
def add_line_to_ledger(self, string_or_mob):
|
||||||
|
if isinstance(string_or_mob, str):
|
||||||
|
mob = TextMobject(string_or_mob)
|
||||||
|
elif isinstance(string_or_mob, Mobject):
|
||||||
|
mob = string_or_mob
|
||||||
|
else:
|
||||||
|
raise Exception("Invalid input")
|
||||||
|
|
||||||
|
mob.scale_to_fit_height(self.ledger_line_height)
|
||||||
|
mob.next_to(
|
||||||
|
self.ledger.content[-1], DOWN,
|
||||||
|
buff = MED_SMALL_BUFF,
|
||||||
|
aligned_edge = LEFT
|
||||||
|
)
|
||||||
|
self.ledger.content.add(mob)
|
||||||
|
return mob
|
||||||
|
|
||||||
|
def add_payment_line_to_ledger(self, from_name, to_name, amount):
|
||||||
|
amount_str = str(amount)
|
||||||
|
if self.denomination == "USD":
|
||||||
|
amount_str = "\\$" + amount_str
|
||||||
|
else:
|
||||||
|
amount_str += " " + self.denomination
|
||||||
|
line = TextMobject(
|
||||||
|
from_name.capitalize(),
|
||||||
|
"pays" if from_name.lower() is not "you" else "pay",
|
||||||
|
to_name.capitalize(),
|
||||||
|
amount_str
|
||||||
|
)
|
||||||
|
for name in from_name, to_name:
|
||||||
|
if hasattr(self, name.lower()):
|
||||||
|
creature = getattr(self, name.lower())
|
||||||
|
color = creature.get_color()
|
||||||
|
line.highlight_by_tex(name.capitalize(), color)
|
||||||
|
if self.denomination == "USD":
|
||||||
|
line.highlight_by_tex(amount_str, GREEN_D)
|
||||||
|
elif self.denomination == "BTC":
|
||||||
|
line.highlight_by_tex(amount_str, BITCOIN_COLOR)
|
||||||
|
|
||||||
|
return self.add_line_to_ledger(line)
|
||||||
|
|
||||||
|
def animate_payment_addition(self, *args, **kwargs):
|
||||||
|
line = self.add_payment_line_to_ledger(*args, **kwargs)
|
||||||
|
self.play(LaggedStart(
|
||||||
|
FadeIn,
|
||||||
|
VGroup(*line.family_members_with_points()),
|
||||||
|
run_time = 1
|
||||||
|
))
|
||||||
|
|
||||||
|
def get_network(self):
|
||||||
|
creatures = self.pi_creatures
|
||||||
|
lines = VGroup(*[
|
||||||
|
Line(
|
||||||
|
VGroup(pi1, pi1.label), VGroup(pi2, pi2.label),
|
||||||
|
buff = MED_SMALL_BUFF,
|
||||||
|
stroke_width = 2,
|
||||||
|
)
|
||||||
|
for pi1, pi2 in it.combinations(creatures, 2)
|
||||||
|
])
|
||||||
|
labels = VGroup(*[pi.label for pi in creatures])
|
||||||
|
|
||||||
|
return VGroup(creatures, labels, lines)
|
||||||
|
|
||||||
|
def create_pi_creatures(self):
|
||||||
|
creatures = VGroup(*[
|
||||||
|
PiCreature(color = color, height = 1).shift(2*vect)
|
||||||
|
for color, vect in zip(
|
||||||
|
[BLUE_B, MAROON_D, GREY_BROWN, BLUE_E],
|
||||||
|
[UP+LEFT, UP+RIGHT, DOWN+LEFT, DOWN+RIGHT],
|
||||||
|
)
|
||||||
|
])
|
||||||
|
creatures.to_edge(RIGHT)
|
||||||
|
names = ["alice", "bob", "charlie", "you"]
|
||||||
|
for name, creature in zip(names, creatures):
|
||||||
|
setattr(self, name, creature)
|
||||||
|
label = TextMobject(name.capitalize())
|
||||||
|
label.scale(0.5)
|
||||||
|
label.next_to(creature, DOWN)
|
||||||
|
creature.label = label
|
||||||
|
if (creature.get_center() - creatures.get_center())[0] > 0:
|
||||||
|
creature.flip()
|
||||||
|
creature.look_at(creatures.get_center())
|
||||||
|
|
||||||
|
return creatures
|
||||||
|
|
||||||
|
|
||||||
|
class LayOutPlan(LedgerScene):
|
||||||
|
def construct(self):
|
||||||
|
self.ask_question()
|
||||||
|
self.show_ledger()
|
||||||
|
self.become_skeptical()
|
||||||
|
|
||||||
|
def ask_question(self):
|
||||||
|
btc = BitcoinLogo()
|
||||||
|
group = VGroup(btc, TexMobject("= ???"))
|
||||||
|
group.arrange_submobjects(RIGHT)
|
||||||
|
|
||||||
|
self.play(
|
||||||
|
DrawBorderThenFill(btc),
|
||||||
|
Write(group[1], run_time = 2)
|
||||||
|
)
|
||||||
|
self.dither()
|
||||||
|
self.play(
|
||||||
|
group.scale, 0.7,
|
||||||
|
group.next_to, ORIGIN, RIGHT,
|
||||||
|
group.to_edge, UP
|
||||||
|
)
|
||||||
|
|
||||||
|
def show_ledger(self):
|
||||||
|
network = self.get_network()
|
||||||
|
ledger = self.get_ledger()
|
||||||
|
payments = [
|
||||||
|
("Alice", "Bob", 20),
|
||||||
|
("Bob", "Charlie", 40),
|
||||||
|
("Alice", "You", 50),
|
||||||
|
]
|
||||||
|
|
||||||
|
self.play(*map(FadeIn, [network, ledger]))
|
||||||
|
for payment in payments:
|
||||||
|
new_line = self.add_payment_line_to_ledger(*payment)
|
||||||
|
from_name, to_name, amount = payment
|
||||||
|
from_pi = getattr(self, from_name.lower())
|
||||||
|
to_pi = getattr(self, to_name.lower())
|
||||||
|
cash = TexMobject("\\$"*(amount/10))
|
||||||
|
cash.scale(0.5)
|
||||||
|
cash.move_to(from_pi)
|
||||||
|
cash.highlight(GREEN)
|
||||||
|
|
||||||
|
self.play(
|
||||||
|
cash.move_to, to_pi,
|
||||||
|
to_pi.change_mode, "hooray"
|
||||||
|
)
|
||||||
|
self.play(
|
||||||
|
FadeOut(cash),
|
||||||
|
Write(new_line, run_time = 1)
|
||||||
|
)
|
||||||
|
self.dither()
|
||||||
|
|
||||||
|
def become_skeptical(self):
|
||||||
|
creatures = self.pi_creatures
|
||||||
|
|
||||||
|
self.play(*[
|
||||||
|
ApplyMethod(pi.change_mode, "sassy")
|
||||||
|
for pi in creatures
|
||||||
|
])
|
||||||
|
for k in range(3):
|
||||||
|
self.play(*[
|
||||||
|
ApplyMethod(
|
||||||
|
creatures[i].look_at,
|
||||||
|
creatures[k*(i+1)%4]
|
||||||
|
)
|
||||||
|
for i in range(4)
|
||||||
|
])
|
||||||
|
self.dither(2)
|
||||||
|
|
||||||
|
class UnderlyingSystemVsUserFacing(Scene):
|
||||||
|
def construct(self):
|
||||||
|
underlying = TextMobject("Underlying \\\\ system")
|
||||||
|
underlying.shift(DOWN).to_edge(LEFT)
|
||||||
|
user_facing = TextMobject("User-facing")
|
||||||
|
user_facing.next_to(underlying, UP, LARGE_BUFF, LEFT)
|
||||||
|
|
||||||
|
protocol = TextMobject("Bitcoin protocol")
|
||||||
|
protocol.next_to(underlying, RIGHT, MED_LARGE_BUFF)
|
||||||
|
protocol.highlight(BITCOIN_COLOR)
|
||||||
|
banking = TextMobject("Banking system")
|
||||||
|
banking.next_to(protocol, RIGHT, MED_LARGE_BUFF)
|
||||||
|
banking.highlight(GREEN)
|
||||||
|
|
||||||
|
phone = SVGMobject(
|
||||||
|
file_name = "phone",
|
||||||
|
fill_color = WHITE,
|
||||||
|
fill_opacity = 1,
|
||||||
|
height = 1,
|
||||||
|
stroke_width = 0,
|
||||||
|
)
|
||||||
|
phone.next_to(protocol, UP, LARGE_BUFF)
|
||||||
|
card = SVGMobject(
|
||||||
|
file_name = "credit_card",
|
||||||
|
fill_color = LIGHT_GREY,
|
||||||
|
fill_opacity = 1,
|
||||||
|
stroke_width = 0,
|
||||||
|
height = 1
|
||||||
|
)
|
||||||
|
card.next_to(banking, UP, LARGE_BUFF)
|
||||||
|
|
||||||
|
btc = BitcoinLogo()
|
||||||
|
btc.next_to(phone, UP, MED_LARGE_BUFF)
|
||||||
|
dollar = TexMobject("\\$")
|
||||||
|
dollar.scale_to_fit_height(1)
|
||||||
|
dollar.highlight(GREEN)
|
||||||
|
dollar.next_to(card, UP, MED_LARGE_BUFF)
|
||||||
|
card.save_state()
|
||||||
|
card.shift(2*RIGHT)
|
||||||
|
card.set_fill(opacity = 0)
|
||||||
|
|
||||||
|
|
||||||
|
h_line = Line(underlying.get_left(), banking.get_right())
|
||||||
|
h_line.next_to(underlying, DOWN, MED_SMALL_BUFF, LEFT)
|
||||||
|
h_line2 = h_line.copy()
|
||||||
|
h_line2.next_to(user_facing, DOWN, MED_LARGE_BUFF, LEFT)
|
||||||
|
h_line3 = h_line.copy()
|
||||||
|
h_line3.next_to(user_facing, UP, MED_LARGE_BUFF, LEFT)
|
||||||
|
v_line = Line(5*UP, ORIGIN)
|
||||||
|
v_line.next_to(underlying, RIGHT, MED_SMALL_BUFF)
|
||||||
|
v_line.shift(1.7*UP)
|
||||||
|
v_line2 = v_line.copy()
|
||||||
|
v_line2.next_to(protocol, RIGHT, MED_SMALL_BUFF)
|
||||||
|
v_line2.shift(1.7*UP)
|
||||||
|
|
||||||
|
self.add(h_line, h_line2, h_line3, v_line, v_line2)
|
||||||
|
self.add(underlying, user_facing, btc)
|
||||||
|
self.play(Write(protocol))
|
||||||
|
self.dither(2)
|
||||||
|
self.play(
|
||||||
|
card.restore,
|
||||||
|
Write(dollar)
|
||||||
|
)
|
||||||
|
self.play(Write(banking))
|
||||||
|
self.dither(2)
|
||||||
|
self.play(DrawBorderThenFill(phone))
|
||||||
|
self.dither(2)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
14
helpers.py
14
helpers.py
@ -394,6 +394,20 @@ def cammel_case_initials(name):
|
|||||||
|
|
||||||
################################################
|
################################################
|
||||||
|
|
||||||
|
def get_full_image_path(image_file_name):
|
||||||
|
possible_paths = [
|
||||||
|
image_file_name,
|
||||||
|
os.path.join(IMAGE_DIR, image_file_name),
|
||||||
|
os.path.join(IMAGE_DIR, image_file_name + ".jpg"),
|
||||||
|
os.path.join(IMAGE_DIR, image_file_name + ".png"),
|
||||||
|
os.path.join(IMAGE_DIR, image_file_name + ".gif"),
|
||||||
|
]
|
||||||
|
for path in possible_paths:
|
||||||
|
if os.path.exists(path):
|
||||||
|
return path
|
||||||
|
raise IOError("File not Found")
|
||||||
|
|
||||||
|
|
||||||
def drag_pixels(frames):
|
def drag_pixels(frames):
|
||||||
curr = frames[0]
|
curr = frames[0]
|
||||||
new_frames = []
|
new_frames = []
|
||||||
|
@ -26,21 +26,11 @@ class ImageMobject(PMobject):
|
|||||||
self.name = to_camel_case(
|
self.name = to_camel_case(
|
||||||
os.path.split(image_file)[-1].split(".")[0]
|
os.path.split(image_file)[-1].split(".")[0]
|
||||||
)
|
)
|
||||||
possible_paths = [
|
path = get_full_image_path(image_file)
|
||||||
image_file,
|
self.generate_points_from_file(path)
|
||||||
os.path.join(IMAGE_DIR, image_file),
|
self.scale(self.scale_factorue)
|
||||||
os.path.join(IMAGE_DIR, image_file + ".jpg"),
|
if self.should_center:
|
||||||
os.path.join(IMAGE_DIR, image_file + ".png"),
|
self.center()
|
||||||
os.path.join(IMAGE_DIR, image_file + ".gif"),
|
|
||||||
]
|
|
||||||
for path in possible_paths:
|
|
||||||
if os.path.exists(path):
|
|
||||||
self.generate_points_from_file(path)
|
|
||||||
self.scale(self.scale_factorue)
|
|
||||||
if self.should_center:
|
|
||||||
self.center()
|
|
||||||
return
|
|
||||||
raise IOError("File not Found")
|
|
||||||
|
|
||||||
def generate_points_from_file(self, path):
|
def generate_points_from_file(self, path):
|
||||||
if self.use_cache and self.read_in_cached_attrs(path):
|
if self.use_cache and self.read_in_cached_attrs(path):
|
||||||
|
@ -16,8 +16,9 @@ def string_to_numbers(num_string):
|
|||||||
|
|
||||||
class SVGMobject(VMobject):
|
class SVGMobject(VMobject):
|
||||||
CONFIG = {
|
CONFIG = {
|
||||||
"initial_scale_factor" : 1,
|
|
||||||
"should_center" : True,
|
"should_center" : True,
|
||||||
|
"height" : 2,
|
||||||
|
"width" : None,
|
||||||
#Must be filled in in a subclass, or when called
|
#Must be filled in in a subclass, or when called
|
||||||
"file_name" : None,
|
"file_name" : None,
|
||||||
"propogate_style_to_family" : True,
|
"propogate_style_to_family" : True,
|
||||||
@ -175,7 +176,11 @@ class SVGMobject(VMobject):
|
|||||||
def move_into_position(self):
|
def move_into_position(self):
|
||||||
if self.should_center:
|
if self.should_center:
|
||||||
self.center()
|
self.center()
|
||||||
self.scale_in_place(self.initial_scale_factor)
|
if self.height is not None:
|
||||||
|
self.scale_to_fit_height(self.height)
|
||||||
|
if self.width is not None:
|
||||||
|
self.scale_to_fit_width(self.width)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class VMobjectFromSVGPathstring(VMobject):
|
class VMobjectFromSVGPathstring(VMobject):
|
||||||
|
@ -7,9 +7,7 @@ from topics.geometry import BackgroundRectangle
|
|||||||
import collections
|
import collections
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
TEX_MOB_SCALE_FACTOR = 0.05
|
TEX_MOB_SCALE_FACTOR = 0.04
|
||||||
TEXT_MOB_SCALE_FACTOR = 0.05
|
|
||||||
|
|
||||||
|
|
||||||
class TexSymbol(VMobjectFromSVGPathstring):
|
class TexSymbol(VMobjectFromSVGPathstring):
|
||||||
def pointwise_become_partial(self, mobject, a, b):
|
def pointwise_become_partial(self, mobject, a, b):
|
||||||
@ -37,7 +35,7 @@ class TexMobject(SVGMobject):
|
|||||||
"fill_color" : WHITE,
|
"fill_color" : WHITE,
|
||||||
"should_center" : True,
|
"should_center" : True,
|
||||||
"arg_separator" : " ",
|
"arg_separator" : " ",
|
||||||
"initial_scale_factor" : TEX_MOB_SCALE_FACTOR,
|
"height" : None,
|
||||||
"organize_left_to_right" : False,
|
"organize_left_to_right" : False,
|
||||||
"propogate_style_to_family" : True,
|
"propogate_style_to_family" : True,
|
||||||
"alignment" : "",
|
"alignment" : "",
|
||||||
@ -55,6 +53,7 @@ class TexMobject(SVGMobject):
|
|||||||
self.template_tex_file
|
self.template_tex_file
|
||||||
)
|
)
|
||||||
SVGMobject.__init__(self, file_name = file_name, **kwargs)
|
SVGMobject.__init__(self, file_name = file_name, **kwargs)
|
||||||
|
self.scale(TEX_MOB_SCALE_FACTOR)
|
||||||
if self.organize_left_to_right:
|
if self.organize_left_to_right:
|
||||||
self.organize_submobjects_left_to_right()
|
self.organize_submobjects_left_to_right()
|
||||||
|
|
||||||
@ -189,7 +188,6 @@ class TexMobject(SVGMobject):
|
|||||||
class TextMobject(TexMobject):
|
class TextMobject(TexMobject):
|
||||||
CONFIG = {
|
CONFIG = {
|
||||||
"template_tex_file" : TEMPLATE_TEXT_FILE,
|
"template_tex_file" : TEMPLATE_TEXT_FILE,
|
||||||
"initial_scale_factor" : TEXT_MOB_SCALE_FACTOR,
|
|
||||||
"alignment" : "\\centering",
|
"alignment" : "\\centering",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -31,7 +31,7 @@ class PiCreature(SVGMobject):
|
|||||||
"stroke_color" : BLACK,
|
"stroke_color" : BLACK,
|
||||||
"fill_opacity" : 1.0,
|
"fill_opacity" : 1.0,
|
||||||
"propogate_style_to_family" : True,
|
"propogate_style_to_family" : True,
|
||||||
"initial_scale_factor" : 0.01,
|
"height" : 3,
|
||||||
"corner_scale_factor" : 0.75,
|
"corner_scale_factor" : 0.75,
|
||||||
"flip_at_start" : False,
|
"flip_at_start" : False,
|
||||||
"is_looking_direction_purposeful" : False,
|
"is_looking_direction_purposeful" : False,
|
||||||
|
@ -146,7 +146,9 @@ class PatreonThanks(Scene):
|
|||||||
self.play(Blink(morty))
|
self.play(Blink(morty))
|
||||||
last_group = group
|
last_group = group
|
||||||
|
|
||||||
|
class ExternallyAnimatedScene(Scene):
|
||||||
|
def construct(self):
|
||||||
|
raise Exception("Don't actually run this class.")
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -12,6 +12,20 @@ from topics.geometry import Circle, Line, Rectangle, Square, \
|
|||||||
Arc, Polygon, SurroundingRectangle
|
Arc, Polygon, SurroundingRectangle
|
||||||
from topics.three_dimensions import Cube
|
from topics.three_dimensions import Cube
|
||||||
|
|
||||||
|
class BitcoinLogo(SVGMobject):
|
||||||
|
CONFIG = {
|
||||||
|
"file_name" : "Bitcoin_logo",
|
||||||
|
"height" : 1,
|
||||||
|
"fill_color" : "#f7931a",
|
||||||
|
"inner_color" : WHITE,
|
||||||
|
"fill_opacity" : 1,
|
||||||
|
"stroke_width" : 0,
|
||||||
|
}
|
||||||
|
def __init__(self, **kwargs):
|
||||||
|
SVGMobject.__init__(self, **kwargs)
|
||||||
|
self[0].set_fill(self.fill_color, self.fill_opacity)
|
||||||
|
self[1].set_fill(self.inner_color, 1)
|
||||||
|
|
||||||
class Guitar(SVGMobject):
|
class Guitar(SVGMobject):
|
||||||
CONFIG = {
|
CONFIG = {
|
||||||
"file_name" : "guitar",
|
"file_name" : "guitar",
|
||||||
@ -21,9 +35,6 @@ class Guitar(SVGMobject):
|
|||||||
"stroke_color" : WHITE,
|
"stroke_color" : WHITE,
|
||||||
"stroke_width" : 0.5,
|
"stroke_width" : 0.5,
|
||||||
}
|
}
|
||||||
def __init__(self, **kwargs):
|
|
||||||
SVGMobject.__init__(self, **kwargs)
|
|
||||||
self.scale_to_fit_height(self.height)
|
|
||||||
|
|
||||||
class SunGlasses(SVGMobject):
|
class SunGlasses(SVGMobject):
|
||||||
CONFIG = {
|
CONFIG = {
|
||||||
|
Reference in New Issue
Block a user