diff --git a/docs/source/reference.rst b/docs/source/reference.rst index a329230deb..4375b11cb7 100644 --- a/docs/source/reference.rst +++ b/docs/source/reference.rst @@ -66,6 +66,7 @@ List of Modules _config constants + ~utils.color container diff --git a/manim/animation/indication.py b/manim/animation/indication.py index fd6710c1bd..da4aabb70c 100644 --- a/manim/animation/indication.py +++ b/manim/animation/indication.py @@ -16,6 +16,7 @@ from ..mobject.shape_matchers import SurroundingRectangle from ..mobject.types.vectorized_mobject import VGroup from ..mobject.geometry import Line +from ..utils import color as C from ..utils.bezier import interpolate from ..utils.config_ops import digest_config from ..utils.rate_functions import there_and_back @@ -25,7 +26,7 @@ class FocusOn(Transform): CONFIG = { "opacity": 0.2, - "color": GREY, + "color": C.GREY, "run_time": 2, "remover": True, } @@ -55,7 +56,7 @@ class Indicate(Transform): CONFIG = { "rate_func": there_and_back, "scale_factor": 1.2, - "color": YELLOW, + "color": C.YELLOW, } def create_target(self): @@ -74,7 +75,7 @@ class Flash(AnimationGroup): "run_time": 1, } - def __init__(self, point, color=YELLOW, **kwargs): + def __init__(self, point, color=C.YELLOW, **kwargs): self.point = point self.color = color digest_config(self, kwargs) @@ -104,7 +105,7 @@ class CircleIndicate(Indicate): CONFIG = { "rate_func": there_and_back, "remover": True, - "circle_config": {"color": YELLOW,}, + "circle_config": {"color": C.YELLOW,}, } def __init__(self, mobject, **kwargs): diff --git a/manim/animation/specialized.py b/manim/animation/specialized.py index f5fc3fa360..b1c320fe63 100644 --- a/manim/animation/specialized.py +++ b/manim/animation/specialized.py @@ -3,11 +3,10 @@ from ..animation.composition import LaggedStart from ..animation.transform import ApplyMethod from ..animation.transform import Restore -from ..constants import WHITE -from ..constants import BLACK from ..mobject.geometry import Circle from ..mobject.svg.drawings import Car from ..mobject.types.vectorized_mobject import VGroup +from ..utils import color as C from ..utils.config_ops import digest_config from ..utils.space_ops import get_norm @@ -53,7 +52,7 @@ class Broadcast(LaggedStart): "big_radius": 5, "n_circles": 5, "start_stroke_width": 8, - "color": WHITE, + "color": C.WHITE, "remover": True, "lag_ratio": 0.2, "run_time": 3, @@ -64,7 +63,9 @@ def __init__(self, focal_point, **kwargs): digest_config(self, kwargs) circles = VGroup() for x in range(self.n_circles): - circle = Circle(radius=self.big_radius, stroke_color=BLACK, stroke_width=0,) + circle = Circle( + radius=self.big_radius, stroke_color=C.BLACK, stroke_width=0, + ) circle.add_updater(lambda c: c.move_to(focal_point)) circle.save_state() circle.set_width(self.small_radius * 2) diff --git a/manim/camera/camera.py b/manim/camera/camera.py index 7520e31cd7..3dcbe81688 100644 --- a/manim/camera/camera.py +++ b/manim/camera/camera.py @@ -16,6 +16,7 @@ from ..mobject.mobject import Mobject from ..mobject.types.point_cloud_mobject import PMobject from ..mobject.types.vectorized_mobject import VMobject +from ..utils import color as C from ..utils.color import color_to_int_rgba from ..utils.config_ops import digest_config from ..utils.images import get_full_raster_image_path @@ -52,7 +53,7 @@ class Camera(object): "frame_height": config["frame_height"], "frame_width": config["frame_width"], "frame_center": ORIGIN, - "background_color": BLACK, + "background_color": C.BLACK, "background_opacity": 1, # Points in vectorized mobjects with norm greater # than this value will be rescaled. diff --git a/manim/camera/moving_camera.py b/manim/camera/moving_camera.py index 253498c768..41dc599382 100644 --- a/manim/camera/moving_camera.py +++ b/manim/camera/moving_camera.py @@ -1,8 +1,9 @@ from ..camera.camera import Camera from ..config import config -from ..constants import ORIGIN, WHITE +from ..constants import ORIGIN from ..mobject.frame import ScreenRectangle from ..mobject.types.vectorized_mobject import VGroup +from ..utils import color as C from ..utils.config_ops import digest_config @@ -25,7 +26,7 @@ class MovingCamera(Camera): CONFIG = { "fixed_dimension": 0, # width - "default_frame_stroke_color": WHITE, + "default_frame_stroke_color": C.WHITE, "default_frame_stroke_width": 0, } diff --git a/manim/constants.py b/manim/constants.py index 1dc6bb5ab8..c12f49e4de 100644 --- a/manim/constants.py +++ b/manim/constants.py @@ -108,80 +108,6 @@ class MyText(Text): # ffmpeg stuff FFMPEG_BIN = "ffmpeg" - -# gif stuff -GIF_FILE_EXTENSION = ".gif" - -# Colors -COLOR_MAP = { - "DARK_BLUE": "#236B8E", - "DARK_BROWN": "#8B4513", - "LIGHT_BROWN": "#CD853F", - "BLUE_E": "#1C758A", - "BLUE_D": "#29ABCA", - "BLUE_C": "#58C4DD", - "BLUE_B": "#9CDCEB", - "BLUE_A": "#C7E9F1", - "TEAL_E": "#49A88F", - "TEAL_D": "#55C1A7", - "TEAL_C": "#5CD0B3", - "TEAL_B": "#76DDC0", - "TEAL_A": "#ACEAD7", - "GREEN_E": "#699C52", - "GREEN_D": "#77B05D", - "GREEN_C": "#83C167", - "GREEN_B": "#A6CF8C", - "GREEN_A": "#C9E2AE", - "YELLOW_E": "#E8C11C", - "YELLOW_D": "#F4D345", - "YELLOW_C": "#FFFF00", - "YELLOW_B": "#FFEA94", - "YELLOW_A": "#FFF1B6", - "GOLD_E": "#C78D46", - "GOLD_D": "#E1A158", - "GOLD_C": "#F0AC5F", - "GOLD_B": "#F9B775", - "GOLD_A": "#F7C797", - "RED_E": "#CF5044", - "RED_D": "#E65A4C", - "RED_C": "#FC6255", - "RED_B": "#FF8080", - "RED_A": "#F7A1A3", - "MAROON_E": "#94424F", - "MAROON_D": "#A24D61", - "MAROON_C": "#C55F73", - "MAROON_B": "#EC92AB", - "MAROON_A": "#ECABC1", - "PURPLE_E": "#644172", - "PURPLE_D": "#715582", - "PURPLE_C": "#9A72AC", - "PURPLE_B": "#B189C6", - "PURPLE_A": "#CAA3E8", - "WHITE": "#FFFFFF", - "BLACK": "#000000", - "LIGHT_GRAY": "#BBBBBB", - "LIGHT_GREY": "#BBBBBB", - "GRAY": "#888888", - "GREY": "#888888", - "DARK_GREY": "#444444", - "DARK_GRAY": "#444444", - "DARKER_GREY": "#222222", - "DARKER_GRAY": "#222222", - "GREY_BROWN": "#736357", - "PINK": "#D147BD", - "LIGHT_PINK": "#DC75CD", - "GREEN_SCREEN": "#00FF00", - "ORANGE": "#FF862F", -} -COLOR_MAP.update( - { - name.replace("_C", ""): COLOR_MAP[name] - for name in COLOR_MAP - if name.endswith("_C") - } -) -PALETTE = list(COLOR_MAP.values()) -locals().update(COLOR_MAP) FFMPEG_VERBOSITY_MAP = { "DEBUG": "error", "INFO": "error", @@ -190,3 +116,6 @@ class MyText(Text): "CRITICAL": "fatal", } VERBOSITY_CHOICES = FFMPEG_VERBOSITY_MAP.keys() + +# gif stuff +GIF_FILE_EXTENSION = ".gif" diff --git a/manim/mobject/changing.py b/manim/mobject/changing.py index 02475d6293..0c7dedada5 100644 --- a/manim/mobject/changing.py +++ b/manim/mobject/changing.py @@ -1,13 +1,18 @@ -from ..constants import * from ..mobject.types.vectorized_mobject import VMobject from ..mobject.types.vectorized_mobject import VGroup +from ..utils import color as C from ..utils.rate_functions import smooth from ..utils.space_ops import get_norm class AnimatedBoundary(VGroup): CONFIG = { - "colors": [BLUE_D, BLUE_B, BLUE_E, GREY_BROWN], + "colors": [ + C.BLUE_D, + C.BLUE_B, + C.BLUE_E, + C.GREY_BROWN, + ], "max_stroke_width": 3, "cycle_rate": 0.5, "back_and_forth": True, @@ -64,7 +69,7 @@ def full_family_become_partial(self, mob1, mob2, a, b): class TracedPath(VMobject): CONFIG = { "stroke_width": 2, - "stroke_color": WHITE, + "stroke_color": C.WHITE, "min_distance_to_new_point": 0.1, } diff --git a/manim/mobject/coordinate_systems.py b/manim/mobject/coordinate_systems.py index 713659f320..19edb49aee 100644 --- a/manim/mobject/coordinate_systems.py +++ b/manim/mobject/coordinate_systems.py @@ -9,6 +9,7 @@ from ..mobject.number_line import NumberLine from ..mobject.svg.tex_mobject import TexMobject from ..mobject.types.vectorized_mobject import VGroup +from ..utils import color as C from ..utils.config_ops import digest_config from ..utils.config_ops import merge_dicts_recursively from ..utils.simple_functions import binary_search @@ -122,7 +123,7 @@ def input_to_graph_point(self, x, graph): class Axes(VGroup, CoordinateSystem): CONFIG = { "axis_config": { - "color": LIGHT_GREY, + "color": C.LIGHT_GREY, "include_tip": True, "exclude_zero_from_default_numbers": True, }, @@ -234,7 +235,7 @@ def make_func(axis): class NumberPlane(Axes): CONFIG = { "axis_config": { - "stroke_color": WHITE, + "stroke_color": C.WHITE, "stroke_width": 2, "include_ticks": False, "include_tip": False, @@ -244,7 +245,7 @@ class NumberPlane(Axes): }, "y_axis_config": {"label_direction": DR,}, "background_line_style": { - "stroke_color": BLUE_D, + "stroke_color": C.BLUE_D, "stroke_width": 2, "stroke_opacity": 1, }, @@ -280,7 +281,7 @@ def init_background_lines(self): def get_lines(self): """Generate all the lines, faded and not faded. Two sets of lines are generated: one parallel to the X-axis, and parallel to the Y-axis. - + Returns ------- Tuple[:class:`~.VGroup`, :class:`~.VGroup`] @@ -313,9 +314,9 @@ def get_lines_parallel_to_axis( axis_perpendicular_to : :class:`~.Line` The axis with which the lines will be perpendicular. - + ratio_faded_lines : :class:`float` - The number of faded lines between each non-faded line. + The number of faded lines between each non-faded line. freq : :class:`float` Frequency of non-faded lines (number of non-faded lines per graph unit). @@ -323,7 +324,7 @@ def get_lines_parallel_to_axis( Returns ------- Tuple[:class:`~.VGroup`, :class:`~.VGroup`] - The first (i.e the non-faded lines parallel to `axis_parallel_to`) and second (i.e the faded lines parallel to `axis_parallel_to`) sets of lines, respectively. + The first (i.e the non-faded lines parallel to `axis_parallel_to`) and second (i.e the faded lines parallel to `axis_parallel_to`) sets of lines, respectively. """ line = Line(axis_parallel_to.get_start(), axis_parallel_to.get_end()) dense_freq = ratio_faded_lines @@ -373,7 +374,7 @@ def prepare_for_nonlinear_transform(self, num_inserted_curves=50): class ComplexPlane(NumberPlane): CONFIG = { - "color": BLUE, + "color": C.BLUE, "line_frequency": 1, } diff --git a/manim/mobject/frame.py b/manim/mobject/frame.py index 1c4b6e41b0..014c308ec2 100644 --- a/manim/mobject/frame.py +++ b/manim/mobject/frame.py @@ -1,7 +1,7 @@ -from ..constants import * from ..config import config from ..mobject.geometry import Rectangle from ..utils.config_ops import digest_config +from ..utils import color as C class ScreenRectangle(Rectangle): @@ -21,7 +21,7 @@ class FullScreenRectangle(ScreenRectangle): class FullScreenFadeRectangle(FullScreenRectangle): CONFIG = { "stroke_width": 0, - "fill_color": BLACK, + "fill_color": C.BLACK, "fill_opacity": 0.7, } diff --git a/manim/mobject/functions.py b/manim/mobject/functions.py index f12ec37675..90cd2236a4 100644 --- a/manim/mobject/functions.py +++ b/manim/mobject/functions.py @@ -2,6 +2,7 @@ from ..config import config from ..mobject.types.vectorized_mobject import VMobject from ..utils.config_ops import digest_config +from ..utils import color as C import math @@ -76,7 +77,7 @@ def generate_points(self): class FunctionGraph(ParametricFunction): CONFIG = { - "color": YELLOW, + "color": C.YELLOW, "x_min": -config["frame_x_radius"], "x_max": config["frame_x_radius"], } diff --git a/manim/mobject/geometry.py b/manim/mobject/geometry.py index 3ef7ead285..0c3f1e8d8e 100644 --- a/manim/mobject/geometry.py +++ b/manim/mobject/geometry.py @@ -14,6 +14,7 @@ from ..mobject.types.vectorized_mobject import VGroup from ..mobject.types.vectorized_mobject import VMobject from ..mobject.types.vectorized_mobject import DashedVMobject +from ..utils import color as C from ..utils.config_ops import digest_config from ..utils.iterables import adjacent_n_tuples from ..utils.iterables import adjacent_pairs @@ -322,7 +323,11 @@ def __init__(self, start_point, end_point, **kwargs): class Circle(Arc): - CONFIG = {"color": RED, "close_new_points": True, "anchors_span_full_range": False} + CONFIG = { + "color": C.RED, + "close_new_points": True, + "anchors_span_full_range": False, + } def __init__(self, **kwargs): Arc.__init__(self, 0, TAU, **kwargs) @@ -348,7 +353,7 @@ class Dot(Circle): "radius": DEFAULT_DOT_RADIUS, "stroke_width": 0, "fill_opacity": 1.0, - "color": WHITE, + "color": C.WHITE, } def __init__(self, point=ORIGIN, **kwargs): @@ -378,7 +383,7 @@ class AnnularSector(Arc): "start_angle": 0, "fill_opacity": 1, "stroke_width": 0, - "color": WHITE, + "color": C.WHITE, } def generate_points(self): @@ -408,7 +413,7 @@ class Annulus(Circle): "outer_radius": 2, "fill_opacity": 1, "stroke_width": 0, - "color": WHITE, + "color": C.WHITE, "mark_paths_closed": False, } @@ -684,7 +689,7 @@ def __init__(self, points, **kwargs): class Polygon(VMobject): CONFIG = { - "color": BLUE, + "color": C.BLUE, } def __init__(self, *vertices, **kwargs): @@ -782,7 +787,7 @@ def get_length(self): class Rectangle(Polygon): CONFIG = { - "color": WHITE, + "color": C.WHITE, "height": 2.0, "width": 4.0, "mark_paths_closed": True, diff --git a/manim/mobject/matrix.py b/manim/mobject/matrix.py index 4d132e46ea..eb968a3cce 100644 --- a/manim/mobject/matrix.py +++ b/manim/mobject/matrix.py @@ -8,6 +8,7 @@ from ..mobject.svg.tex_mobject import TextMobject from ..mobject.types.vectorized_mobject import VGroup from ..mobject.types.vectorized_mobject import VMobject +from ..utils import color as C VECTOR_LABEL_SCALE_FACTOR = 0.8 @@ -27,7 +28,9 @@ def matrix_to_mobject(matrix): return TexMobject(matrix_to_tex_string(matrix)) -def vector_coordinate_label(vector_mob, integer_labels=True, n_dim=2, color=WHITE): +def vector_coordinate_label( + vector_mob, integer_labels=True, n_dim=2, color=C.WHITE +): vect = np.array(vector_mob.get_end()) if integer_labels: vect = np.round(vect).astype(int) @@ -122,7 +125,7 @@ def set_column_colors(self, *colors): def get_rows(self): """Return rows of the matrix as VGroups - + Returns -------- List[:class:`~.VGroup`] @@ -134,12 +137,12 @@ def get_rows(self): def set_row_colors(self, *colors): """Set individual colors for each row of the matrix - + Parameters ---------- colors : :class:`str` The list of colors; each color specified corresponds to a row. - + Returns ------- :class:`Matrix` diff --git a/manim/mobject/mobject.py b/manim/mobject/mobject.py index 71d446e768..43a26a5b81 100644 --- a/manim/mobject/mobject.py +++ b/manim/mobject/mobject.py @@ -15,6 +15,7 @@ from ..constants import * from ..config import config from ..container import Container +from ..utils import color as C from ..utils.color import color_gradient from ..utils.color import interpolate_color from ..utils.iterables import list_update @@ -35,7 +36,7 @@ class Mobject(Container): """ CONFIG = { - "color": WHITE, + "color": C.WHITE, "name": None, "dim": 3, "target": None, @@ -539,7 +540,9 @@ def put_start_and_end_on(self, start, end): return self # Background rectangle - def add_background_rectangle(self, color=BLACK, opacity=0.75, **kwargs): + def add_background_rectangle( + self, color=C.BLACK, opacity=0.75, **kwargs + ): # TODO, this does not behave well when the mobject has points, # since it gets displayed on top from ..mobject.shape_matchers import BackgroundRectangle @@ -562,7 +565,7 @@ def add_background_rectangle_to_family_members_with_points(self, **kwargs): # Color functions - def set_color(self, color=YELLOW_C, family=True): + def set_color(self, color=C.YELLOW_C, family=True): """ Condition is function which takes in one arguments, (x, y, z). Here it just recurses to submobjects, but in subclasses this @@ -580,7 +583,11 @@ def set_color_by_gradient(self, *colors): return self def set_colors_by_radial_gradient( - self, center=None, radius=1, inner_color=WHITE, outer_color=BLACK + self, + center=None, + radius=1, + inner_color=C.WHITE, + outer_color=C.BLACK, ): self.set_submobject_colors_by_radial_gradient( center, radius, inner_color, outer_color @@ -601,7 +608,11 @@ def set_submobject_colors_by_gradient(self, *colors): return self def set_submobject_colors_by_radial_gradient( - self, center=None, radius=1, inner_color=WHITE, outer_color=BLACK + self, + center=None, + radius=1, + inner_color=C.WHITE, + outer_color=C.BLACK, ): if center is None: center = self.get_center() diff --git a/manim/mobject/number_line.py b/manim/mobject/number_line.py index da8f286ee7..574aceb8a5 100644 --- a/manim/mobject/number_line.py +++ b/manim/mobject/number_line.py @@ -5,6 +5,7 @@ from ..mobject.geometry import Line from ..mobject.numbers import DecimalNumber from ..mobject.types.vectorized_mobject import VGroup +from ..utils import color as C from ..utils.bezier import interpolate from ..utils.config_ops import digest_config from ..utils.config_ops import merge_dicts_recursively @@ -14,7 +15,7 @@ class NumberLine(Line): CONFIG = { - "color": LIGHT_GREY, + "color": C.LIGHT_GREY, "x_min": -config["frame_x_radius"], "x_max": config["frame_x_radius"], "unit_size": 1, diff --git a/manim/mobject/probability.py b/manim/mobject/probability.py index a9fd5658d1..2bc2c1b197 100644 --- a/manim/mobject/probability.py +++ b/manim/mobject/probability.py @@ -6,6 +6,7 @@ from ..mobject.svg.tex_mobject import TexMobject from ..mobject.svg.tex_mobject import TextMobject from ..mobject.types.vectorized_mobject import VGroup +from ..utils import color as C from ..utils.color import color_gradient from ..utils.iterables import tuplify @@ -16,10 +17,10 @@ class SampleSpace(Rectangle): CONFIG = { "height": 3, "width": 3, - "fill_color": DARK_GREY, + "fill_color": C.DARK_GREY, "fill_opacity": 1, "stroke_width": 0.5, - "stroke_color": LIGHT_GREY, + "stroke_color": C.LIGHT_GREY, ## "default_label_scale_val": 1, } @@ -59,10 +60,14 @@ def get_division_along_dimension(self, p_list, dim, colors, vect): parts.add(part) return parts - def get_horizontal_division(self, p_list, colors=[GREEN_E, BLUE_E], vect=DOWN): + def get_horizontal_division( + self, p_list, colors=[C.GREEN_E, C.BLUE_E], vect=DOWN + ): return self.get_division_along_dimension(p_list, 1, colors, vect) - def get_vertical_division(self, p_list, colors=[MAROON_B, YELLOW], vect=RIGHT): + def get_vertical_division( + self, p_list, colors=[C.MAROON_B, C.YELLOW], vect=RIGHT + ): return self.get_division_along_dimension(p_list, 0, colors, vect) def divide_horizontally(self, *args, **kwargs): @@ -141,7 +146,7 @@ class BarChart(VGroup): "label_y_axis": True, "y_axis_label_height": 0.25, "max_value": 1, - "bar_colors": [BLUE, YELLOW], + "bar_colors": [C.BLUE, C.YELLOW], "bar_fill_opacity": 0.8, "bar_stroke_width": 3, "bar_names": [], diff --git a/manim/mobject/shape_matchers.py b/manim/mobject/shape_matchers.py index 00b8c54a48..5c48a27ad3 100644 --- a/manim/mobject/shape_matchers.py +++ b/manim/mobject/shape_matchers.py @@ -3,13 +3,13 @@ from ..mobject.geometry import Rectangle from ..mobject.types.vectorized_mobject import VGroup from ..mobject.types.vectorized_mobject import VMobject -from ..utils.color import Color +from ..utils import color as C from ..utils.config_ops import digest_config class SurroundingRectangle(Rectangle): CONFIG = { - "color": YELLOW, + "color": C.YELLOW, "buff": SMALL_BUFF, } @@ -23,7 +23,7 @@ def __init__(self, mobject, **kwargs): class BackgroundRectangle(SurroundingRectangle): CONFIG = { - "color": BLACK, + "color": C.BLACK, "stroke_width": 0, "stroke_opacity": 0, "fill_opacity": 0.75, @@ -49,9 +49,9 @@ def set_style_data( # Unchangable style, except for fill_opacity VMobject.set_style_data( self, - stroke_color=BLACK, + stroke_color=C.BLACK, stroke_width=0, - fill_color=BLACK, + fill_color=C.BLACK, fill_opacity=fill_opacity, ) return self @@ -62,7 +62,7 @@ def get_fill_color(self): class Cross(VGroup): CONFIG = { - "stroke_color": RED, + "stroke_color": C.RED, "stroke_width": 6, } diff --git a/manim/mobject/svg/drawings.py b/manim/mobject/svg/drawings.py index 67dd69465f..4d439dd769 100644 --- a/manim/mobject/svg/drawings.py +++ b/manim/mobject/svg/drawings.py @@ -20,6 +20,7 @@ from ...mobject.types.vectorized_mobject import VGroup from ...mobject.types.vectorized_mobject import VMobject from ...mobject.types.vectorized_mobject import VectorizedPoint +from ...utils import color as C from ...utils.bezier import interpolate from ...utils.config_ops import digest_config from ...utils.rate_functions import linear @@ -32,9 +33,9 @@ class Lightbulb(SVGMobject): CONFIG = { "file_name": "lightbulb", "height": 1, - "stroke_color": YELLOW, + "stroke_color": C.YELLOW, "stroke_width": 3, - "fill_color": YELLOW, + "fill_color": C.YELLOW, "fill_opacity": 0, } @@ -44,7 +45,7 @@ class BitcoinLogo(SVGMobject): "file_name": "Bitcoin_logo", "height": 1, "fill_color": "#f7931a", - "inner_color": WHITE, + "inner_color": C.WHITE, "fill_opacity": 1, "stroke_width": 0, } @@ -59,9 +60,9 @@ class Guitar(SVGMobject): CONFIG = { "file_name": "guitar", "height": 2.5, - "fill_color": DARK_GREY, + "fill_color": C.DARK_GREY, "fill_opacity": 1, - "stroke_color": WHITE, + "stroke_color": C.WHITE, "stroke_width": 0.5, } @@ -73,7 +74,7 @@ class Speedometer(VMobject): "tick_length": 0.2, "needle_width": 0.1, "needle_height": 0.8, - "needle_color": YELLOW, + "needle_color": C.YELLOW, } def generate_points(self): @@ -138,8 +139,8 @@ class AoPSLogo(SVGMobject): def __init__(self, **kwargs): SVGMobject.__init__(self, **kwargs) - self.set_stroke(WHITE, width=0) - colors = [BLUE_E, "#008445", GREEN_B] + self.set_stroke(C.WHITE, width=0) + colors = [C.BLUE_E, "#008445", C.GREEN_B] index_lists = [ (10, 11, 12, 13, 14, 21, 22, 23, 24, 27, 28, 29, 30), (0, 1, 2, 3, 4, 15, 16, 17, 26), @@ -159,9 +160,9 @@ class PartyHat(SVGMobject): "height": 1.5, "stroke_width": 0, "fill_opacity": 1, - "frills_colors": [MAROON_B, PURPLE], - "cone_color": GREEN, - "dots_colors": [YELLOW], + "frills_colors": [C.MAROON_B, C.PURPLE], + "cone_color": C.GREEN, + "dots_colors": [C.YELLOW], } NUM_FRILLS = 7 NUM_DOTS = 6 @@ -189,13 +190,13 @@ class Laptop(VGroup): "screen_width_to_screen_plate_width": 0.9, "key_color_kwargs": { "stroke_width": 0, - "fill_color": BLACK, + "fill_color": C.BLACK, "fill_opacity": 1, }, "fill_opacity": 1, "stroke_width": 0, - "body_color": LIGHT_GREY, - "shaded_body_color": GREY, + "body_color": C.LIGHT_GREY, + "shaded_body_color": C.GREY, "open_angle": np.pi / 4, } @@ -228,7 +229,9 @@ def __init__(self, **kwargs): body.add(keyboard) screen_plate.stretch(self.screen_thickness / self.body_dimensions[2], dim=2) - screen = Rectangle(stroke_width=0, fill_color=BLACK, fill_opacity=1,) + screen = Rectangle( + stroke_width=0, fill_color=C.BLACK, fill_opacity=1, + ) screen.replace(screen_plate, stretch=True) screen.scale_in_place(self.screen_width_to_screen_plate_width) screen.next_to(screen_plate, OUT, buff=0.1 * SMALL_BUFF) @@ -243,7 +246,7 @@ def __init__(self, **kwargs): axis = Line( body.get_corner(UP + LEFT + OUT), body.get_corner(UP + RIGHT + OUT), - color=BLACK, + color=C.BLACK, stroke_width=2, ) self.axis = axis @@ -257,7 +260,7 @@ class PatreonLogo(SVGMobject): CONFIG = { "file_name": "patreon_logo", "fill_color": "#F96854", - # "fill_color" : WHITE, + # "fill_color" : C.WHITE, "fill_opacity": 1, "stroke_width": 0, "width": 4, @@ -279,14 +282,14 @@ def __init__(self, **kwargs): SVGMobject.__init__(self, **kwargs) self.center() self.set_width(self.width) - self.set_stroke(color=WHITE, width=0) - self.set_fill(color=WHITE, opacity=1) + self.set_stroke(color=C.WHITE, width=0) + self.set_fill(color=C.WHITE, opacity=1) class VideoSeries(VGroup): CONFIG = { "num_videos": 11, - "gradient_colors": [BLUE_B, BLUE_D], + "gradient_colors": [C.BLUE_B, C.BLUE_D], } def __init__(self, **kwargs): @@ -303,7 +306,7 @@ class Headphones(SVGMobject): "file_name": "headphones", "height": 2, "y_stretch_factor": 0.5, - "color": GREY, + "color": C.GREY, } def __init__(self, **kwargs): @@ -319,7 +322,7 @@ class Clock(VGroup): CONFIG = {} def __init__(self, **kwargs): - circle = Circle(color=WHITE) + circle = Circle(color=C.WHITE) ticks = [] for x in range(12): alpha = x / 12.0 @@ -371,9 +374,9 @@ class Bubble(SVGMobject): "width": 8, "bubble_center_adjustment_factor": 1.0 / 8, "file_name": None, - "fill_color": BLACK, + "fill_color": C.BLACK, "fill_opacity": 0.8, - "stroke_color": WHITE, + "stroke_color": C.WHITE, "stroke_width": 3, } @@ -476,7 +479,7 @@ def __init__(self, **kwargs): self.submobjects.sort(key=lambda m: m.get_bottom()[1]) def make_green_screen(self): - self.submobjects[-1].set_fill(GREEN_SCREEN, opacity=1) + self.submobjects[-1].set_fill(C.GREEN_SCREEN, opacity=1) return self @@ -484,8 +487,8 @@ class Car(SVGMobject): CONFIG = { "file_name": "Car", "height": 1, - "color": LIGHT_GREY, - "light_colors": [BLACK, BLACK], + "color": C.LIGHT_GREY, + "light_colors": [C.BLACK, C.BLACK], } def __init__(self, **kwargs): @@ -501,7 +504,7 @@ def __init__(self, **kwargs): path.add(part) self.set_height(self.height) - self.set_stroke(color=WHITE, width=0) + self.set_stroke(color=C.WHITE, width=0) self.set_fill(self.color, opacity=1) orientation_line = Line(self.get_left(), self.get_right()) @@ -533,7 +536,10 @@ def add_treds_to_tires(self): radius = tire.get_width() / 2 center = tire.get_center() tred = Line( - 0.7 * radius * RIGHT, 1.1 * radius * RIGHT, stroke_width=2, color=BLACK + 0.7 * radius * RIGHT, + 1.1 * radius * RIGHT, + stroke_width=2, + color=C.BLACK, ) tred.rotate(PI / 5, about_point=tred.get_end()) for theta in np.arange(0, 2 * np.pi, np.pi / 4): @@ -560,13 +566,16 @@ class VectorizedEarth(SVGMobject): CONFIG = { "file_name": "earth", "height": 1.5, - "fill_color": BLACK, + "fill_color": C.BLACK, } def __init__(self, **kwargs): SVGMobject.__init__(self, **kwargs) circle = Circle( - stroke_width=3, stroke_color=GREEN, fill_opacity=1, fill_color=BLUE_C, + stroke_width=3, + stroke_color=C.GREEN, + fill_opacity=1, + fill_color=C.BLUE_C, ) circle.replace(self) self.add_to_back(circle) @@ -578,8 +587,8 @@ class Logo(VMobject): "outer_radius": 2.0, "iris_background_blue": "#74C0E3", "iris_background_brown": "#8C6239", - "blue_spike_colors": ["#528EA3", "#3E6576", "#224C5B", BLACK,], - "brown_spike_colors": ["#754C24", "#603813", "#42210b", BLACK,], + "blue_spike_colors": ["#528EA3", "#3E6576", "#224C5B", C.BLACK,], + "brown_spike_colors": ["#754C24", "#603813", "#42210b", C.BLACK,], "n_spike_layers": 4, "n_spikes": 28, "spike_angle": TAU / 28, @@ -684,7 +693,7 @@ def add_spikes(self): def add_pupil(self): self.pupil = Circle( radius=self.pupil_radius, - fill_color=BLACK, + fill_color=C.BLACK, fill_opacity=1, stroke_width=0, sheen=0.0, @@ -714,7 +723,7 @@ def get_blue_part_and_brown_part(self): self.cut_pupil() # circle = Circle() # circle.set_stroke(width=0) - # circle.set_fill(BLACK, opacity=1) + # circle.set_fill(C.BLACK, opacity=1) # circle.match_width(self) # circle.move_to(self) blue_part = VGroup( @@ -755,7 +764,7 @@ class PlayingCard(VGroup): "card_height_to_symbol_height": 7, "card_width_to_corner_num_width": 10, "card_height_to_corner_num_height": 10, - "color": LIGHT_GREY, + "color": C.LIGHT_GREY, "turned_over": False, "possible_suits": ["hearts", "diamonds", "spades", "clubs"], "possible_values": list(map(str, list(range(2, 11)))) + ["J", "Q", "K", "A"], @@ -769,15 +778,15 @@ def generate_points(self): Rectangle( height=self.height, width=self.height / self.height_to_width, - stroke_color=WHITE, + stroke_color=C.WHITE, stroke_width=2, fill_color=self.color, fill_opacity=1, ) ) if self.turned_over: - self.set_fill(DARK_GREY) - self.set_stroke(LIGHT_GREY) + self.set_fill(C.DARK_GREY) + self.set_stroke(C.LIGHT_GREY) contents = VectorizedPoint(self.get_center()) else: value = self.get_value() @@ -903,7 +912,7 @@ class SuitSymbol(SVGMobject): "fill_opacity": 1, "stroke_width": 0, "red": "#D02028", - "black": BLACK, + "black": C.BLACK, } def __init__(self, suit_name, **kwargs): diff --git a/manim/mobject/svg/svg_mobject.py b/manim/mobject/svg/svg_mobject.py index 2a0e864e9c..df9f722b4c 100644 --- a/manim/mobject/svg/svg_mobject.py +++ b/manim/mobject/svg/svg_mobject.py @@ -12,7 +12,7 @@ from ...mobject.geometry import RoundedRectangle from ...mobject.types.vectorized_mobject import VGroup from ...mobject.types.vectorized_mobject import VMobject -from ...utils.color import * +from ...utils import color as C from ...utils.config_ops import digest_config from ...utils.config_ops import digest_locals @@ -33,7 +33,7 @@ class SVGMobject(VMobject): "unpack_groups": True, # if False, creates a hierarchy of VGroups "stroke_width": DEFAULT_STROKE_WIDTH, "fill_opacity": 1.0, - # "fill_color" : LIGHT_GREY, + # "fill_color" : C.LIGHT_GREY, } def __init__(self, file_name=None, **kwargs): @@ -163,19 +163,19 @@ def rect_to_mobject(self, rect_element): # input preprocessing if fill_color in ["", "none", "#FFF", "#FFFFFF"] or Color(fill_color) == Color( - WHITE + C.WHITE ): opacity = 0 - fill_color = BLACK # shdn't be necessary but avoids error msgs + fill_color = C.BLACK # shdn't be necessary but avoids error msgs if fill_color in ["#000", "#000000"]: - fill_color = WHITE + fill_color = C.WHITE if stroke_color in ["", "none", "#FFF", "#FFFFFF"] or Color( stroke_color - ) == Color(WHITE): + ) == Color(C.WHITE): stroke_width = 0 - stroke_color = BLACK + stroke_color = C.BLACK if stroke_color in ["#000", "#000000"]: - stroke_color = WHITE + stroke_color = C.WHITE if stroke_width in ["", "none", "0"]: stroke_width = 0 diff --git a/manim/mobject/svg/tex_mobject.py b/manim/mobject/svg/tex_mobject.py index 9b14e8819d..ed23a69dae 100644 --- a/manim/mobject/svg/tex_mobject.py +++ b/manim/mobject/svg/tex_mobject.py @@ -8,6 +8,7 @@ from ...mobject.svg.svg_mobject import VMobjectFromSVGPathstring from ...mobject.types.vectorized_mobject import VGroup from ...mobject.types.vectorized_mobject import VectorizedPoint +from ...utils import color as C from ...utils.config_ops import digest_config from ...utils.strings import split_string_list_to_isolate_substrings from ...utils.tex_file_writing import tex_to_svg_file @@ -26,7 +27,7 @@ class SingleStringTexMobject(SVGMobject): "stroke_width": 0, "fill_opacity": 1.0, "background_stroke_width": 1, - "background_stroke_color": BLACK, + "background_stroke_color": C.BLACK, "should_center": True, "height": None, "organize_left_to_right": False, diff --git a/manim/mobject/svg/text_mobject.py b/manim/mobject/svg/text_mobject.py index 8272a3943c..6045539662 100644 --- a/manim/mobject/svg/text_mobject.py +++ b/manim/mobject/svg/text_mobject.py @@ -11,6 +11,7 @@ from ...mobject.geometry import Dot, Rectangle from ...mobject.svg.svg_mobject import SVGMobject from ...mobject.types.vectorized_mobject import VGroup +from ...utils import color as C from ...utils.config_ops import digest_config @@ -30,7 +31,7 @@ def __init__(self, start, end, font, slant, weight, line_num=-1): class Text(SVGMobject): CONFIG = { # Mobject - "color": WHITE, + "color": C.WHITE, "height": None, "width": None, "fill_opacity": 1, diff --git a/manim/mobject/three_dimensions.py b/manim/mobject/three_dimensions.py index 4f1194dd44..4f55e4ea9b 100644 --- a/manim/mobject/three_dimensions.py +++ b/manim/mobject/three_dimensions.py @@ -2,6 +2,7 @@ from ..mobject.geometry import Square from ..mobject.types.vectorized_mobject import VGroup from ..mobject.types.vectorized_mobject import VMobject +from ..utils import color as C from ..utils.iterables import tuplify from ..utils.space_ops import z_to_vector @@ -22,10 +23,10 @@ class ParametricSurface(VGroup): "v_max": 1, "resolution": 32, "surface_piece_config": {}, - "fill_color": BLUE_D, + "fill_color": C.BLUE_D, "fill_opacity": 1.0, - "checkerboard_colors": [BLUE_D, BLUE_E], - "stroke_color": LIGHT_GREY, + "checkerboard_colors": [C.BLUE_D, C.BLUE_E], + "stroke_color": C.LIGHT_GREY, "stroke_width": 0.5, "should_make_jagged": False, "pre_function_handle_to_anchor_scale_factor": 0.00001, @@ -114,7 +115,7 @@ def func(self, u, v): class Cube(VGroup): CONFIG = { "fill_opacity": 0.75, - "fill_color": BLUE, + "fill_color": C.BLUE, "stroke_width": 0, "side_length": 2, } diff --git a/manim/mobject/types/image_mobject.py b/manim/mobject/types/image_mobject.py index f50f76352f..1759765fc3 100644 --- a/manim/mobject/types/image_mobject.py +++ b/manim/mobject/types/image_mobject.py @@ -6,6 +6,7 @@ from ...mobject.mobject import Mobject from ...mobject.shape_matchers import SurroundingRectangle from ...utils.bezier import interpolate +from ...utils import color as C from ...utils.color import color_to_int_rgb from ...utils.config_ops import digest_config from ...utils.images import get_full_raster_image_path @@ -107,7 +108,7 @@ class ImageMobjectFromCamera(AbstractImageMobject): CONFIG = { "default_display_frame_config": { "stroke_width": 3, - "stroke_color": WHITE, + "stroke_color": C.WHITE, "buff": 0, } } diff --git a/manim/mobject/types/point_cloud_mobject.py b/manim/mobject/types/point_cloud_mobject.py index c0bd8a1994..3b33828e93 100644 --- a/manim/mobject/types/point_cloud_mobject.py +++ b/manim/mobject/types/point_cloud_mobject.py @@ -1,6 +1,7 @@ from ...constants import * from ...mobject.mobject import Mobject from ...utils.bezier import interpolate +from ...utils import color as C from ...utils.color import color_gradient from ...utils.color import color_to_rgba from ...utils.color import rgba_to_color @@ -38,7 +39,7 @@ def add_points(self, points, rgbas=None, color=None, alpha=1): self.rgbas = np.append(self.rgbas, rgbas, axis=0) return self - def set_color(self, color=YELLOW_C, family=True): + def set_color(self, color=C.YELLOW_C, family=True): rgba = color_to_rgba(color) mobs = self.family_members_with_points() if family else [self] for mob in mobs: @@ -74,7 +75,11 @@ def set_color_by_gradient(self, *colors): return self def set_colors_by_radial_gradient( - self, center=None, radius=1, inner_color=WHITE, outer_color=BLACK + self, + center=None, + radius=1, + inner_color=C.WHITE, + outer_color=C.BLACK, ): start_rgba, end_rgba = list(map(color_to_rgba, [start_color, end_color])) if center is None: @@ -217,7 +222,7 @@ class PointCloudDot(Mobject1D): "radius": 0.075, "stroke_width": 2, "density": DEFAULT_POINT_DENSITY_1D, - "color": YELLOW, + "color": C.YELLOW, } def __init__(self, center=ORIGIN, **kwargs): @@ -236,7 +241,7 @@ def generate_points(self): class Point(PMobject): CONFIG = { - "color": BLACK, + "color": C.BLACK, } def __init__(self, location=ORIGIN, **kwargs): diff --git a/manim/mobject/types/vectorized_mobject.py b/manim/mobject/types/vectorized_mobject.py index 0e0cbac07e..dcc7eee7f9 100644 --- a/manim/mobject/types/vectorized_mobject.py +++ b/manim/mobject/types/vectorized_mobject.py @@ -11,6 +11,7 @@ from ...utils.bezier import interpolate from ...utils.bezier import integer_interpolate from ...utils.bezier import partial_bezier_points +from ...utils import color as C from ...utils.color import color_to_rgba from ...utils.iterables import make_even from ...utils.iterables import stretch_array_to_length @@ -38,11 +39,11 @@ class VMobject(Mobject): # The purpose of background stroke is to have # something that won't overlap the fill, e.g. # For text against some textured background - "background_stroke_color": BLACK, + "background_stroke_color": C.BLACK, "background_stroke_opacity": 1.0, "background_stroke_width": 0, # When a color c is set, there will be a second color - # computed based on interpolating c to WHITE by with + # computed based on interpolating c to Colors.white by with # sheen_factor, and the display will gradient to this # secondary color in the direction of sheen_direction. "sheen_factor": 0.0, @@ -107,7 +108,7 @@ def generate_rgbas_array(self, color, opacity): return rgbas def update_rgbas_array(self, array_name, color=None, opacity=None): - passed_color = color if (color is not None) else BLACK + passed_color = color if (color is not None) else C.BLACK passed_opacity = opacity if (opacity is not None) else 0 rgbas = self.generate_rgbas_array(passed_color, passed_opacity) if not hasattr(self, array_name): @@ -353,7 +354,7 @@ def get_gradient_start_and_end_points(self): def color_using_background_image(self, background_image_file): self.background_image_file = background_image_file - self.set_color(WHITE) + self.set_color(C.WHITE) for submob in self.submobjects: submob.color_using_background_image(background_image_file) return self @@ -880,7 +881,7 @@ class VDict(VMobject): mapping_or_iterable : Union[:class:`Mapping`, Iterable[Tuple[Hashable, :class:`~.VMobject`]]], optional The parameter specifying the key-value mapping of keys and mobjects. show_keys : :class:`bool`, optional - Whether to also display the key associated with + Whether to also display the key associated with the mobject. This might be useful when debugging, especially when there are a lot of mobjects in the :class:`VDict`. Defaults to False. @@ -890,7 +891,7 @@ class VDict(VMobject): Attributes ---------- show_keys : :class:`bool` - Whether to also display the key associated with + Whether to also display the key associated with the mobject. This might be useful when debugging, especially when there are a lot of mobjects in the :class:`VDict`. When displayed, the key is towards @@ -936,7 +937,7 @@ def add(self, mapping_or_iterable): def remove(self, key): """Removes the mobject from the :class:`VDict` object having the key `key` - + Also, it internally removes the mobject from the `submobjects` :class:`list` of :class:`~.Mobject`, (which is responsible for removing it from the screen) @@ -963,12 +964,12 @@ def remove(self, key): def __getitem__(self, key): """Overriding the [] operator for getting submobject by key - + Parameters ---------- key : Hashable The key of the submoject to be accessed - + Returns ------- :class:`VMobject` @@ -991,7 +992,7 @@ def __setitem__(self, key, value): The key of the submoject to be assigned value : :class:`VMobject` The submobject to bind the key to - + Returns ------- None @@ -1008,7 +1009,7 @@ def __setitem__(self, key, value): def get_all_submobjects(self): """To get all the submobjects associated with a particular :class:`VDict` object - + Returns ------- :class:`dict_values` @@ -1066,7 +1067,7 @@ def add_key_value_pair(self, key, value): class VectorizedPoint(VMobject): CONFIG = { - "color": BLACK, + "color": C.BLACK, "fill_opacity": 0, "stroke_width": 0, "artificial_width": 0.01, @@ -1102,7 +1103,11 @@ def __init__(self, vmobject, **kwargs): class DashedVMobject(VMobject): - CONFIG = {"num_dashes": 15, "positive_space_ratio": 0.5, "color": WHITE} + CONFIG = { + "num_dashes": 15, + "positive_space_ratio": 0.5, + "color": C.WHITE, + } def __init__(self, vmobject, **kwargs): VMobject.__init__(self, **kwargs) diff --git a/manim/mobject/vector_field.py b/manim/mobject/vector_field.py index ad5310a729..d1aa9c3f81 100644 --- a/manim/mobject/vector_field.py +++ b/manim/mobject/vector_field.py @@ -14,6 +14,7 @@ from ..mobject.types.vectorized_mobject import VMobject from ..utils.bezier import inverse_interpolate from ..utils.bezier import interpolate +from ..utils import color as C from ..utils.color import color_to_rgb from ..utils.color import rgb_to_color from ..utils.config_ops import digest_config @@ -24,7 +25,12 @@ # from ..utils.space_ops import normalize -DEFAULT_SCALAR_FIELD_COLORS = [BLUE_E, GREEN, YELLOW, RED] +DEFAULT_SCALAR_FIELD_COLORS = [ + C.BLUE_E, + C.GREEN, + C.YELLOW, + C.RED, +] def get_colored_background_image( @@ -53,7 +59,10 @@ def get_colored_background_image( def get_rgb_gradient_function( - min_value=0, max_value=1, colors=[BLUE, RED], flip_alphas=True, # Why? + min_value=0, + max_value=1, + colors=[C.BLUE, C.RED], + flip_alphas=True, # Why? ): rgbs = np.array(list(map(color_to_rgb, colors))) @@ -187,7 +196,7 @@ class StreamLines(VGroup): "virtual_time": 3, "n_anchors_per_line": 100, "stroke_width": 1, - "stroke_color": WHITE, + "stroke_color": C.WHITE, "color_by_arc_length": True, # Min and max arc lengths meant to define # the color range, should color_by_arc_length be True diff --git a/manim/scene/graph_scene.py b/manim/scene/graph_scene.py index 2d8a4d0e03..a9b0e98f3c 100644 --- a/manim/scene/graph_scene.py +++ b/manim/scene/graph_scene.py @@ -15,6 +15,7 @@ from ..mobject.types.vectorized_mobject import VGroup from ..mobject.types.vectorized_mobject import VectorizedPoint from ..scene.scene import Scene +from ..utils import color as C from ..utils.bezier import interpolate from ..utils.color import color_gradient from ..utils.color import invert_color @@ -40,14 +41,18 @@ class GraphScene(Scene): "y_bottom_tick": None, # Change if different from y_min "y_labeled_nums": None, "y_axis_label": "$y$", - "axes_color": GREY, + "axes_color": C.GREY, "graph_origin": 2.5 * DOWN + 4 * LEFT, "exclude_zero_label": True, - "default_graph_colors": [BLUE, GREEN, YELLOW], - "default_derivative_color": GREEN, - "default_input_color": YELLOW, - "default_riemann_start_color": BLUE, - "default_riemann_end_color": GREEN, + "default_graph_colors": [ + C.BLUE, + C.GREEN, + C.YELLOW, + ], + "default_derivative_color": C.GREEN, + "default_input_color": C.YELLOW, + "default_riemann_start_color": C.BLUE, + "default_riemann_end_color": C.GREEN, "area_opacity": 0.8, "num_rects": 50, "include_tip": False, # add tip at the end of the axes @@ -436,7 +441,7 @@ def get_riemann_rectangles( input_sample_type="left", bounded_graph=None, stroke_width=1, - stroke_color=BLACK, + stroke_color=C.BLACK, fill_opacity=1, start_color=None, end_color=None, @@ -591,7 +596,13 @@ def get_riemann_rectangles_list( ] def get_area( - self, graph, t_min, t_max, bounded=None, dx_scaling=1, area_color=WHITE + self, + graph, + t_min, + t_max, + bounded=None, + dx_scaling=1, + area_color=C.WHITE, ): """ Returns a VGroup of Riemann rectangles @@ -854,7 +865,13 @@ def get_secant_slope_group( return group def add_T_label( - self, x_val, side=RIGHT, label=None, color=WHITE, animated=False, **kwargs + self, + x_val, + side=RIGHT, + label=None, + color=C.WHITE, + animated=False, + **kwargs, ): """ This method adds to the Scene: @@ -894,7 +911,9 @@ def add_T_label( T_label = TexMobject(label, fill_color=color) T_label.next_to(triangle, DOWN) - v_line = self.get_vertical_line_to_graph(x_val, self.v_graph, color=YELLOW) + v_line = self.get_vertical_line_to_graph( + x_val, self.v_graph, color=C.YELLOW + ) if animated: self.play( diff --git a/manim/scene/vector_space_scene.py b/manim/scene/vector_space_scene.py index b285fcc7c3..e6c1f767b8 100644 --- a/manim/scene/vector_space_scene.py +++ b/manim/scene/vector_space_scene.py @@ -26,14 +26,15 @@ from ..mobject.types.vectorized_mobject import VGroup from ..mobject.types.vectorized_mobject import VMobject from ..scene.scene import Scene +from ..utils import color as C from ..utils.rate_functions import rush_from from ..utils.rate_functions import rush_into from ..utils.space_ops import angle_of_vector from ..utils.space_ops import get_norm -X_COLOR = GREEN_C -Y_COLOR = RED_C -Z_COLOR = BLUE_D +X_COLOR = C.GREEN_C +Y_COLOR = C.RED_C +Z_COLOR = C.BLUE_D # TODO: Much of this scene type seems dependent on the coordinate system chosen. @@ -67,7 +68,7 @@ def add_plane(self, animate=False, **kwargs): self.add(plane) return plane - def add_axes(self, animate=False, color=WHITE, **kwargs): + def add_axes(self, animate=False, color=C.WHITE, **kwargs): """ Adds a pair of Axes to the Scene. @@ -76,7 +77,7 @@ def add_axes(self, animate=False, color=WHITE, **kwargs): animate : bool, optional Whether or not to animate the addition of the axes through ShowCreation. color : bool, optional - The color of the axes. Defaults to WHITE. + The color of the axes. Defaults to C.WHITE. """ axes = Axes(color=color, tick_frequency=1) if animate: @@ -100,7 +101,7 @@ def lock_in_faded_grid(self, dimness=0.7, axes_dimness=0.5): plane = self.add_plane() axes = plane.get_axes() plane.fade(dimness) - axes.set_color(WHITE) + axes.set_color(C.WHITE) axes.fade(axes_dimness) self.add(axes) self.freeze_background() @@ -128,7 +129,7 @@ def get_vector(self, numerical_vector, **kwargs): **kwargs, ) - def add_vector(self, vector, color=YELLOW, animate=True, **kwargs): + def add_vector(self, vector, color=C.YELLOW, animate=True, **kwargs): """ Returns the Vector after adding it to the Plane. @@ -141,7 +142,7 @@ def add_vector(self, vector, color=YELLOW, animate=True, **kwargs): color : str The string of the hex color of the vector. This is only taken into consideration if - 'vector' is not an Arrow. Defaults to YELLOW. + 'vector' is not an Arrow. Defaults to C.YELLOW. animate : bool Whether or not to animate the addition of the vector @@ -180,7 +181,7 @@ def write_vector_coordinates(self, vector, **kwargs): integer_labels (True) : Whether or not to round the coordinates to integers. n_dim (2) : The number of dimensions of the vector. - color (WHITE) : The color of the label. + color (C.WHITE) : The color of the label. Returns ------- @@ -487,8 +488,8 @@ def show_ghost_movement(self, vector): for y in range(-y_max, y_max) ] ) - dots.set_fill(BLACK, opacity=0) - dots_halfway = dots.copy().shift(vector / 2).set_fill(WHITE, 1) + dots.set_fill(C.BLACK, opacity=0) + dots_halfway = dots.copy().shift(vector / 2).set_fill(C.WHITE, 1) dots_end = dots.copy().shift(vector) self.play(Transform(dots, dots_halfway, rate_func=rush_into)) @@ -513,10 +514,13 @@ class LinearTransformationScene(VectorScene): "faded_line_ratio": 0, }, "background_plane_kwargs": { - "color": GREY, - "axis_config": {"stroke_color": LIGHT_GREY,}, - "axis_config": {"color": GREY,}, - "background_line_style": {"stroke_color": GREY, "stroke_width": 1,}, + "color": C.GREY, + "axis_config": {"stroke_color": C.LIGHT_GREY,}, + "axis_config": {"color": C.GREY,}, + "background_line_style": { + "stroke_color": C.GREY, + "stroke_width": 1, + }, }, "show_coordinates": False, "show_basis_vectors": True, @@ -633,7 +637,7 @@ def add_moving_mobject(self, mobject, target_mobject=None): mobject.target = target_mobject self.add_special_mobjects(self.moving_mobjects, mobject) - def get_unit_square(self, color=YELLOW, opacity=0.3, stroke_width=3): + def get_unit_square(self, color=C.YELLOW, opacity=0.3, stroke_width=3): """ Returns a unit square for the current NumberPlane. @@ -693,7 +697,7 @@ def add_unit_square(self, animate=False, **kwargs): self.square = square return self - def add_vector(self, vector, color=YELLOW, **kwargs): + def add_vector(self, vector, color=C.YELLOW, **kwargs): """ Adds a vector to the scene, and puts it in the special list self.moving_vectors. @@ -707,7 +711,7 @@ def add_vector(self, vector, color=YELLOW, **kwargs): color : str The string of the hex color of the vector. This is only taken into consideration if - 'vector' is not an Arrow. Defaults to YELLOW. + 'vector' is not an Arrow. Defaults to C.YELLOW. **kwargs Any valid keyword argument of VectorScene.add_vector. diff --git a/manim/utils/color.py b/manim/utils/color.py index ebae3ddace..1566ee8f36 100644 --- a/manim/utils/color.py +++ b/manim/utils/color.py @@ -1,15 +1,135 @@ +""" +This module provides pre-defined colors, as well as functions to manipulate +colors, mostly used internally. The preferred way of accessing the colors is +via + +.. code-block:: python + + import manim.utils.color as C + C.WHITE # -> '#FFFFFF' + +""" + import random +from enum import Enum from colour import Color import numpy as np -from ..constants import COLOR_MAP -from ..constants import WHITE from ..utils.bezier import interpolate from ..utils.simple_functions import clip_in_place from ..utils.space_ops import normalize +class Colors(Enum): + """A list of pre-defined colors. + + Examples + -------- + + The preferred way of using these colors is + + .. code-block:: python + + import manim.utils.color as C + C.WHITE # -> '#FFFFFF' + + Note this way uses the name of the colors below in UPPERCASE. + + Alternatively, you can also import this Enum directly and use its members + directly, through the use of :code:`color.value`. Note this way uses the + name of the colors in lowercase. + + .. code-block:: python + + from manim.utils.color import Colors + Colors.white.value # -> '#FFFFFF' + + """ + + dark_blue = "#236B8E" + dark_brown = "#8B4513" + light_brown = "#CD853F" + blue_e = "#1C758A" + blue_d = "#29ABCA" + blue_c = "#58C4DD" + blue = "#58C4DD" + blue_b = "#9CDCEB" + blue_a = "#C7E9F1" + teal_e = "#49A88F" + teal_d = "#55C1A7" + teal_c = "#5CD0B3" + teal = "#5CD0B3" + teal_b = "#76DDC0" + teal_a = "#ACEAD7" + green_e = "#699C52" + green_d = "#77B05D" + green_c = "#83C167" + green = "#83C167" + green_b = "#A6CF8C" + green_a = "#C9E2AE" + yellow_e = "#E8C11C" + yellow_d = "#F4D345" + yellow_c = "#FFFF00" + yellow = "#FFFF00" + yellow_b = "#FFEA94" + yellow_a = "#FFF1B6" + gold_e = "#C78D46" + gold_d = "#E1A158" + gold_c = "#F0AC5F" + gold = "#F0AC5F" + gold_b = "#F9B775" + gold_a = "#F7C797" + red_e = "#CF5044" + red_d = "#E65A4C" + red_c = "#FC6255" + red = "#FC6255" + red_b = "#FF8080" + red_a = "#F7A1A3" + maroon_e = "#94424F" + maroon_d = "#A24D61" + maroon_c = "#C55F73" + maroon = "#C55F73" + maroon_b = "#EC92AB" + maroon_a = "#ECABC1" + purple_e = "#644172" + purple_d = "#715582" + purple_c = "#9A72AC" + purple = "#9A72AC" + purple_b = "#B189C6" + purple_a = "#CAA3E8" + white = "#FFFFFF" + black = "#000000" + light_gray = "#BBBBBB" + light_grey = "#BBBBBB" + gray = "#888888" + grey = "#888888" + dark_grey = "#444444" + dark_gray = "#444444" + darker_grey = "#222222" + darker_gray = "#222222" + grey_brown = "#736357" + pink = "#D147BD" + light_pink = "#DC75CD" + green_screen = "#00FF00" + orange = "#FF862F" + + +# Having a list of pre-defined colors is useful for auto-completion in several +# IDEs. However, in order to reach the value of a color using the Colors enum, +# one needs to access Colors.white.value, which is far too long and clunky. +# Therefore, we also add each color as a global constant, in upper case, to the +# locals() of this module +COLOR_MAP = {n.upper(): c.value for n, c in Colors.__members__.items()} +locals().update(COLOR_MAP) + +# This module only exports the pre-defined colors: the Enum and the globals, +# not the COLOR_MAP. +__all__ = ['Colors'] + list(COLOR_MAP.keys()) + + +# The remaining functions are not exported + def color_to_rgb(color): if isinstance(color, str): return hex_to_rgb(color) @@ -27,7 +147,7 @@ def rgb_to_color(rgb): try: return Color(rgb=rgb) except: - return Color(WHITE) + return Color(Colors.white.value) def rgba_to_color(rgba): @@ -93,7 +213,7 @@ def random_bright_color(): def random_color(): - return random.choice(list(COLOR_MAP.values())) + return random.choice([c.value for c in Colors]) def get_shaded_rgb(rgb, point, unit_normal_vect, light_source): diff --git a/manim/utils/debug.py b/manim/utils/debug.py index e6bfec433e..b1224d67c7 100644 --- a/manim/utils/debug.py +++ b/manim/utils/debug.py @@ -1,6 +1,6 @@ -from ..constants import BLACK from ..mobject.numbers import Integer from ..mobject.types.vectorized_mobject import VGroup +from . import color as C def print_family(mobject, n_tabs=0): @@ -16,6 +16,6 @@ def get_submobject_index_labels(mobject, label_height=0.15): label = Integer(n) label.set_height(label_height) label.move_to(submob) - label.set_stroke(BLACK, 5, background=True) + label.set_stroke(C.BLACK, 5, background=True) labels.add(label) return labels diff --git a/tests/test_graph.py b/tests/test_graph.py index 1bfafc4d49..80d7009da0 100644 --- a/tests/test_graph.py +++ b/tests/test_graph.py @@ -9,8 +9,8 @@ class PlotFunctionsTest(GraphScene): "y_min": -1.5, "y_max": 1.5, "graph_origin": ORIGIN, - "function_color": RED, - "axes_color": GREEN, + "function_color": Colors.red.value, + "axes_color": Colors.green.value, "x_labeled_nums": range(-10, 12, 2), } @@ -29,7 +29,7 @@ class NumberLineTest(GraphScene): "y_min": -1.5, "y_max": 1.5, "graph_origin": ORIGIN, - "axes_color": YELLOW, + "axes_color": Colors.yellow.value, "x_labeled_nums": range(-10, 12, 2), "y_labeled_nums": range(-1, 2), "x_axis_config": { @@ -37,7 +37,7 @@ class NumberLineTest(GraphScene): "decimal_number_config": {"num_decimal_places": 1,}, }, "y_axis_config": { - "color": RED, + "color": Colors.red.value, "decimal_number_config": {"num_decimal_places": 2,}, }, } diff --git a/tests/test_transform.py b/tests/test_transform.py index 80f83dfb3e..9682e99c6e 100644 --- a/tests/test_transform.py +++ b/tests/test_transform.py @@ -51,7 +51,7 @@ def func(p): class FadeToColortTest(Scene): def construct(self): square = Square() - self.play(FadeToColor(square, RED)) + self.play(FadeToColor(square, Colors.red.value)) class ScaleInPlaceTest(Scene): @@ -85,7 +85,7 @@ def apply_function(mob): mob.scale(2) mob.to_corner(UR) mob.rotate(PI / 4) - mob.set_color(RED) + mob.set_color(Colors.red.value) return mob self.play(ApplyFunction(apply_function, square)) diff --git a/tests/test_updaters.py b/tests/test_updaters.py index c3bd801771..3b6eaf0a6a 100644 --- a/tests/test_updaters.py +++ b/tests/test_updaters.py @@ -16,8 +16,8 @@ def construct(self): class ValueTrackerTest(Scene): def construct(self): theta = ValueTracker(PI / 2) - line_1 = Line(ORIGIN, RIGHT * 3, color=RED) - line_2 = Line(ORIGIN, RIGHT * 3, color=GREEN) + line_1 = Line(ORIGIN, RIGHT * 3, color=Colors.red.value) + line_2 = Line(ORIGIN, RIGHT * 3, color=Colors.green.value) line_2.rotate(theta.get_value(), about_point=ORIGIN) diff --git a/tests/tests_data/basic_scenes.py b/tests/tests_data/basic_scenes.py index 5d1ffff5bb..dcad35f3ac 100644 --- a/tests/tests_data/basic_scenes.py +++ b/tests/tests_data/basic_scenes.py @@ -9,7 +9,7 @@ def construct(self): square = Square() square.flip(RIGHT) square.rotate(-3 * TAU / 8) - circle.set_fill(PINK, opacity=0.5) + circle.set_fill(Colors.pink.value, opacity=0.5) self.play(ShowCreation(square)) self.play(Transform(square, circle)) @@ -19,7 +19,7 @@ def construct(self): class WriteStuff(Scene): def construct(self): example_text = TextMobject( - "This is a some text", tex_to_color_map={"text": YELLOW} + "This is a some text", tex_to_color_map={"text": Colors.yellow.value} ) example_tex = TexMobject( "\\sum_{k=1}^\\infty {1 \\over k^2} = {\\pi^2 \\over 6}",