diff --git a/.gitignore b/.gitignore index 346a56ca..6bbcdb2e 100644 --- a/.gitignore +++ b/.gitignore @@ -15,6 +15,8 @@ __pycache__/ build/ develop-eggs/ dist/ +manimlib.egg-info/ + downloads/ eggs/ .eggs/ @@ -147,4 +149,4 @@ dmypy.json # For manim /videos -/custom_config.yml \ No newline at end of file +/custom_config.yml diff --git a/docs/source/development/changelog.rst b/docs/source/development/changelog.rst index e12aeea4..573df074 100644 --- a/docs/source/development/changelog.rst +++ b/docs/source/development/changelog.rst @@ -14,6 +14,8 @@ Fixed bugs - Fixed a bug for off-center vector fields - Had ``Mobject.match_points`` return self - Fixed chaining animation in example scenes +- Fixed the default color of tip +- Fixed a typo in ``ShowPassingFlashWithThinningStrokeWidth`` New Features ^^^^^^^^^^^^ @@ -36,4 +38,7 @@ New Features - Added :meth:`~manimlib.camera.camera.CameraFrame.reorient` for quicker changes to frame angle - Added ``units`` to :meth:`~manimlib.camera.camera.CameraFrame.set_euler_angles` - Allowed any ``VMobject`` to be passed into ``TransformMatchingTex`` -- Removed double brace convention in ``Tex`` and ``TexText`` \ No newline at end of file +- Removed double brace convention in ``Tex`` and ``TexText`` +- Added support for debugger launch +- Added CLI flag ``--config_file`` to load configuration file manually +- Added ``tip_style`` to ``tip_config`` \ No newline at end of file diff --git a/docs/source/getting_started/configuration.rst b/docs/source/getting_started/configuration.rst index 88da1bc8..eb981b19 100644 --- a/docs/source/getting_started/configuration.rst +++ b/docs/source/getting_started/configuration.rst @@ -58,6 +58,7 @@ flag abbr function ``--color COLOR`` ``-c`` Background color ``--leave_progress_bars`` Leave progress bars displayed in terminal ``--video_dir VIDEO_DIR`` directory to write video +``--config_file CONFIG_FILE`` Path to the custom configuration file ========================================================== ====== ================================================================================================================================================================================================= custom_config @@ -86,4 +87,10 @@ following the directory structure: When you enter the ``project/`` folder and run ``manimgl code.py ``, it will overwrite ``manim/default_config.yml`` with ``custom_config.yml`` -in the ``project`` folder. \ No newline at end of file +in the ``project`` folder. + +Alternatively, you can use ``--config_file`` flag in CLI to specify configuration file manually. + +.. code-block:: sh + + manimgl project/code.py --config_file /path/to/custom_config.yml \ No newline at end of file diff --git a/manimlib/__main__.py b/manimlib/__main__.py index ebd342fe..37264645 100644 --- a/manimlib/__main__.py +++ b/manimlib/__main__.py @@ -15,3 +15,6 @@ def main(): for scene in scenes: scene.run() + +if __name__ == '__main__': + main() diff --git a/manimlib/config.py b/manimlib/config.py index 5c0e88eb..e307ac6e 100644 --- a/manimlib/config.py +++ b/manimlib/config.py @@ -130,7 +130,11 @@ def parse_cli(): ) parser.add_argument( "--video_dir", - help="directory to write video", + help="Directory to write video", + ) + parser.add_argument( + "--config_file", + help="Path to the custom configuration file", ) args = parser.parse_args() return args @@ -155,17 +159,19 @@ def get_module(file_name): spec.loader.exec_module(module) return module +__config_file__ = "custom_config.yml" def get_custom_config(): - filename = "custom_config.yml" + global __config_file__ + global_defaults_file = os.path.join(get_manim_dir(), "manimlib", "default_config.yml") if os.path.exists(global_defaults_file): with open(global_defaults_file, "r") as file: config = yaml.safe_load(file) - if os.path.exists(filename): - with open(filename, "r") as file: + if os.path.exists(__config_file__): + with open(__config_file__, "r") as file: local_defaults = yaml.safe_load(file) if local_defaults: config = merge_dicts_recursively( @@ -173,22 +179,41 @@ def get_custom_config(): local_defaults, ) else: - with open(filename, "r") as file: + with open(__config_file__, "r") as file: config = yaml.safe_load(file) - + return config def get_configuration(args): - local_config_file = "custom_config.yml" + global __config_file__ + + # ensure __config_file__ always exists + if args.config_file is not None: + if not os.path.exists(args.config_file): + print(f"Can't find {args.config_file}.") + if sys.platform == 'win32': + print(f"Copying default configuration file to {args.config_file}...") + os.system(f"copy default_config.yml {args.config_file}") + elif sys.platform in ["linux2", "darwin"]: + print(f"Copying default configuration file to {args.config_file}...") + os.system(f"cp default_config.yml {args.config_file}") + else: + print("Please create the configuration file manually.") + print("Read configuration from default_config.yml.") + else: + __config_file__ = args.config_file + global_defaults_file = os.path.join(get_manim_dir(), "manimlib", "default_config.yml") - if not (os.path.exists(global_defaults_file) or os.path.exists(local_config_file)): + + if not (os.path.exists(global_defaults_file) or os.path.exists(__config_file__)): print("There is no configuration file detected. Initial configuration:\n") init_customization() - elif not os.path.exists(local_config_file): - print(f"""Warning: Using the default configuration file, which you can modify in {global_defaults_file} - If you want to create a local configuration file, you can create a file named {local_config_file}, or run manimgl --config - """) + + elif not os.path.exists(__config_file__): + print(f"Warning: Using the default configuration file, which you can modify in {global_defaults_file}") + print(f"If you want to create a local configuration file, you can create a file named {__config_file__}, or run manimgl --config") + custom_config = get_custom_config() write_file = any([args.write_file, args.open, args.finder]) diff --git a/manimlib/mobject/geometry.py b/manimlib/mobject/geometry.py index f8f523b8..69511d67 100644 --- a/manimlib/mobject/geometry.py +++ b/manimlib/mobject/geometry.py @@ -49,6 +49,7 @@ class TipableVMobject(VMobject): "tip_config": { "fill_opacity": 1, "stroke_width": 0, + "tip_style": 0, # triangle=0, inner_smooth=1, dot=2 }, "normal_vector": OUT, } @@ -63,6 +64,7 @@ class TipableVMobject(VMobject): tip = self.create_tip(at_start, **kwargs) self.reset_endpoints_based_on_tip(tip, at_start) self.asign_tip_attr(tip, at_start) + tip.set_color(self.get_stroke_color()) self.add(tip) return self @@ -786,12 +788,20 @@ class ArrowTip(Triangle): "width": DEFAULT_ARROW_TIP_WIDTH, "length": DEFAULT_ARROW_TIP_LENGTH, "angle": 0, + "tip_style": 0, # triangle=0, inner_smooth=1, dot=2 } def __init__(self, **kwargs): Triangle.__init__(self, start_angle=0, **kwargs) self.set_height(self.width) self.set_width(self.length, stretch=True) + if self.tip_style == 1: + self.set_height(self.length * 0.9, stretch=True) + self.data["points"][4] += np.array([0.6 * self.length, 0, 0]) + elif self.tip_style == 2: + h = self.length / 2 + self.clear_points() + self.data["points"] = Dot().set_width(h).get_points() self.rotate(self.angle) def get_base(self): diff --git a/manimlib/mobject/vector_field.py b/manimlib/mobject/vector_field.py index 0776a3cc..b7f69096 100644 --- a/manimlib/mobject/vector_field.py +++ b/manimlib/mobject/vector_field.py @@ -283,7 +283,7 @@ class ShowPassingFlashWithThinningStrokeWidth(AnimationGroup): max_stroke_width = vmobject.get_stroke_width() max_time_width = kwargs.pop("time_width", self.time_width) AnimationGroup.__init__(self, *[ - ShowPassingFlash( + VShowPassingFlash( vmobject.deepcopy().set_stroke(width=stroke_width), time_width=time_width, **kwargs