def get_face_card_design(self, value, symbol): from for_3b1b_videos.pi_creature import PiCreature sub_rect = Rectangle( stroke_color=BLACK, fill_opacity=0, height=0.9 * self.get_height(), width=0.6 * self.get_width(), ) sub_rect.move_to(self) # pi_color = average_color(symbol.get_color(), GREY) pi_color = symbol.get_color() pi_mode = { "J": "plain", "Q": "thinking", "K": "hooray" }[value] pi_creature = PiCreature( mode=pi_mode, color=pi_color, ) pi_creature.set_width(0.8 * sub_rect.get_width()) if value in ["Q", "K"]: prefix = "king" if value == "K" else "queen" crown = SVGMobject(file_name=prefix + "_crown") crown.set_stroke(width=0) crown.set_fill(YELLOW, 1) crown.stretch_to_fit_width(0.5 * sub_rect.get_width()) crown.stretch_to_fit_height(0.17 * sub_rect.get_height()) crown.move_to(pi_creature.eyes.get_center(), DOWN) pi_creature.add_to_back(crown) to_top_buff = 0 else: to_top_buff = SMALL_BUFF * sub_rect.get_height() pi_creature.next_to(sub_rect.get_top(), DOWN, to_top_buff) # pi_creature.shift(0.05*sub_rect.get_width()*RIGHT) pi_copy = pi_creature.copy() pi_copy.rotate(np.pi, about_point=sub_rect.get_center()) return VGroup(sub_rect, pi_creature, pi_copy)
def get_face_card_design(self, value, symbol): from for_3b1b_videos.pi_creature import PiCreature sub_rect = Rectangle( stroke_color=BLACK, fill_opacity=0, height=0.9 * self.get_height(), width=0.6 * self.get_width(), ) sub_rect.move_to(self) # pi_color = average_color(symbol.get_color(), GREY) pi_color = symbol.get_color() pi_mode = {"J": "plain", "Q": "thinking", "K": "hooray"}[value] pi_creature = PiCreature( mode=pi_mode, color=pi_color, ) pi_creature.set_width(0.8 * sub_rect.get_width()) if value in ["Q", "K"]: prefix = "king" if value == "K" else "queen" crown = SVGMobject(file_name=prefix + "_crown") crown.set_stroke(width=0) crown.set_fill(YELLOW, 1) crown.stretch_to_fit_width(0.5 * sub_rect.get_width()) crown.stretch_to_fit_height(0.17 * sub_rect.get_height()) crown.move_to(pi_creature.eyes.get_center(), DOWN) pi_creature.add_to_back(crown) to_top_buff = 0 else: to_top_buff = SMALL_BUFF * sub_rect.get_height() pi_creature.next_to(sub_rect.get_top(), DOWN, to_top_buff) # pi_creature.shift(0.05*sub_rect.get_width()*RIGHT) pi_copy = pi_creature.copy() pi_copy.rotate(np.pi, about_point=sub_rect.get_center()) return VGroup(sub_rect, pi_creature, pi_copy)
def __init__(self, texmob, **kwargs): VMobject.__init__(self, **kwargs) rect = Rectangle(width=texmob.get_width() + self.margin, height=texmob.get_height() + self.margin) rect.move_to(texmob) w = rect.get_width() h = rect.get_height() alpha = w / h hp = np.ceil(self.partitions / (2 * (alpha + 1))) wp = np.ceil(alpha * hp) sides = VGroup(*[ Line(rect.get_corner(c1), rect.get_corner(c2)) for c1, c2 in zip([UL, UR, DR, DL], [UR, DR, DL, UL]) ]) total_points = [] for side, p in zip(sides, [wp, hp, wp, hp]): path = FreehandDraw(side, p).points for point in path: total_points.append(point) total_points.append(total_points[0]) self.set_points_smoothly(total_points)
class ControlPanel(Group): CONFIG = { "panel_kwargs": { "width": FRAME_WIDTH / 4, "height": MED_SMALL_BUFF + FRAME_HEIGHT, "fill_color": GREY_C, "fill_opacity": 1.0, "stroke_width": 0.0 }, "opener_kwargs": { "width": FRAME_WIDTH / 8, "height": 0.5, "fill_color": GREY_C, "fill_opacity": 1.0 }, "opener_text_kwargs": { "text": "Control Panel", "font_size": 20 } } def __init__(self, *controls, **kwargs): digest_config(self, kwargs) self.panel = Rectangle(**self.panel_kwargs) self.panel.to_corner(UP + LEFT, buff=0) self.panel.shift(self.panel.get_height() * UP) self.panel.add_mouse_scroll_listner(self.panel_on_mouse_scroll) self.panel_opener_rect = Rectangle(**self.opener_kwargs) self.panel_info_text = Text(**self.opener_text_kwargs) self.panel_info_text.move_to(self.panel_opener_rect) self.panel_opener = Group(self.panel_opener_rect, self.panel_info_text) self.panel_opener.next_to(self.panel, DOWN, aligned_edge=DOWN) self.panel_opener.add_mouse_drag_listner( self.panel_opener_on_mouse_drag) self.controls = Group(*controls) self.controls.arrange(DOWN, center=False, aligned_edge=ORIGIN) self.controls.move_to(self.panel) super().__init__(self.panel, self.panel_opener, self.controls, **kwargs) self.move_panel_and_controls_to_panel_opener() self.fix_in_frame() def move_panel_and_controls_to_panel_opener(self): self.panel.next_to(self.panel_opener_rect, direction=UP, buff=0) controls_old_x = self.controls.get_x() self.controls.next_to(self.panel_opener_rect, direction=UP, buff=MED_SMALL_BUFF) self.controls.set_x(controls_old_x) def add_controls(self, *new_controls): self.controls.add(*new_controls) self.move_panel_and_controls_to_panel_opener() def remove_controls(self, *controls_to_remove): self.controls.remove(*controls_to_remove) self.move_panel_and_controls_to_panel_opener() def open_panel(self): panel_opener_x = self.panel_opener.get_x() self.panel_opener.to_corner(DOWN + LEFT, buff=0.0) self.panel_opener.set_x(panel_opener_x) self.move_panel_and_controls_to_panel_opener() return self def close_panel(self): panel_opener_x = self.panel_opener.get_x() self.panel_opener.to_corner(UP + LEFT, buff=0.0) self.panel_opener.set_x(panel_opener_x) self.move_panel_and_controls_to_panel_opener() return self def panel_opener_on_mouse_drag(self, mob, event_data): point = event_data["point"] self.panel_opener.match_y(Dot(point)) self.move_panel_and_controls_to_panel_opener() return False def panel_on_mouse_scroll(self, mob, event_data): offset = event_data["offset"] factor = 10 * offset[1] self.controls.set_y(self.controls.get_y() + factor) return False
class Checkbox(ControlMobject): CONFIG = { "value_type": np.dtype(bool), "rect_kwargs": { "width": 0.5, "height": 0.5, "fill_opacity": 0.0 }, "checkmark_kwargs": { "stroke_color": GREEN, "stroke_width": 6, }, "cross_kwargs": { "stroke_color": RED, "stroke_width": 6, }, "box_content_buff": SMALL_BUFF } def __init__(self, value=True, **kwargs): digest_config(self, kwargs) self.box = Rectangle(**self.rect_kwargs) self.box_content = self.get_checkmark() if value else self.get_cross() super().__init__(value, self.box, self.box_content, **kwargs) self.add_mouse_press_listner(self.on_mouse_press) def assert_value(self, value): assert (isinstance(value, bool)) def toggle_value(self): super().set_value(not self.get_value()) def set_value_anim(self, value): if value: self.box_content.become(self.get_checkmark()) else: self.box_content.become(self.get_cross()) def on_mouse_press(self, mob, event_data): mob.toggle_value() return False # Helper methods def get_checkmark(self): checkmark = VGroup( Line(UP / 2 + 2 * LEFT, DOWN + LEFT, **self.checkmark_kwargs), Line(DOWN + LEFT, UP + RIGHT, **self.checkmark_kwargs)) checkmark.stretch_to_fit_width(self.box.get_width()) checkmark.stretch_to_fit_height(self.box.get_height()) checkmark.scale(0.5) checkmark.move_to(self.box) return checkmark def get_cross(self): cross = VGroup(Line(UP + LEFT, DOWN + RIGHT, **self.cross_kwargs), Line(UP + RIGHT, DOWN + LEFT, **self.cross_kwargs)) cross.stretch_to_fit_width(self.box.get_width()) cross.stretch_to_fit_height(self.box.get_height()) cross.scale(0.5) cross.move_to(self.box) return cross