Merge pull request #1538 from manim-kindergarten/shaders

Added some features including --config_file CLI flag and tip_style
This commit is contained in:
Grant Sanderson 2021-06-14 09:47:50 -07:00 committed by GitHub
commit 7ecfc041b3
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 68 additions and 16 deletions

4
.gitignore vendored
View file

@ -15,6 +15,8 @@ __pycache__/
build/ build/
develop-eggs/ develop-eggs/
dist/ dist/
manimlib.egg-info/
downloads/ downloads/
eggs/ eggs/
.eggs/ .eggs/
@ -147,4 +149,4 @@ dmypy.json
# For manim # For manim
/videos /videos
/custom_config.yml /custom_config.yml

View file

@ -14,6 +14,8 @@ Fixed bugs
- Fixed a bug for off-center vector fields - Fixed a bug for off-center vector fields
- Had ``Mobject.match_points`` return self - Had ``Mobject.match_points`` return self
- Fixed chaining animation in example scenes - Fixed chaining animation in example scenes
- Fixed the default color of tip
- Fixed a typo in ``ShowPassingFlashWithThinningStrokeWidth``
New Features New Features
^^^^^^^^^^^^ ^^^^^^^^^^^^
@ -36,4 +38,7 @@ New Features
- Added :meth:`~manimlib.camera.camera.CameraFrame.reorient` for quicker changes to frame angle - Added :meth:`~manimlib.camera.camera.CameraFrame.reorient` for quicker changes to frame angle
- Added ``units`` to :meth:`~manimlib.camera.camera.CameraFrame.set_euler_angles` - Added ``units`` to :meth:`~manimlib.camera.camera.CameraFrame.set_euler_angles`
- Allowed any ``VMobject`` to be passed into ``TransformMatchingTex`` - Allowed any ``VMobject`` to be passed into ``TransformMatchingTex``
- Removed double brace convention in ``Tex`` and ``TexText`` - 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``

View file

@ -58,6 +58,7 @@ flag abbr function
``--color COLOR`` ``-c`` Background color ``--color COLOR`` ``-c`` Background color
``--leave_progress_bars`` Leave progress bars displayed in terminal ``--leave_progress_bars`` Leave progress bars displayed in terminal
``--video_dir VIDEO_DIR`` directory to write video ``--video_dir VIDEO_DIR`` directory to write video
``--config_file CONFIG_FILE`` Path to the custom configuration file
========================================================== ====== ================================================================================================================================================================================================= ========================================================== ====== =================================================================================================================================================================================================
custom_config custom_config
@ -86,4 +87,10 @@ following the directory structure:
When you enter the ``project/`` folder and run ``manimgl code.py <Scene>``, When you enter the ``project/`` folder and run ``manimgl code.py <Scene>``,
it will overwrite ``manim/default_config.yml`` with ``custom_config.yml`` it will overwrite ``manim/default_config.yml`` with ``custom_config.yml``
in the ``project`` folder. 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

View file

@ -15,3 +15,6 @@ def main():
for scene in scenes: for scene in scenes:
scene.run() scene.run()
if __name__ == '__main__':
main()

View file

@ -130,7 +130,11 @@ def parse_cli():
) )
parser.add_argument( parser.add_argument(
"--video_dir", "--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() args = parser.parse_args()
return args return args
@ -155,17 +159,19 @@ def get_module(file_name):
spec.loader.exec_module(module) spec.loader.exec_module(module)
return module return module
__config_file__ = "custom_config.yml"
def get_custom_config(): def get_custom_config():
filename = "custom_config.yml" global __config_file__
global_defaults_file = os.path.join(get_manim_dir(), "manimlib", "default_config.yml") global_defaults_file = os.path.join(get_manim_dir(), "manimlib", "default_config.yml")
if os.path.exists(global_defaults_file): if os.path.exists(global_defaults_file):
with open(global_defaults_file, "r") as file: with open(global_defaults_file, "r") as file:
config = yaml.safe_load(file) config = yaml.safe_load(file)
if os.path.exists(filename): if os.path.exists(__config_file__):
with open(filename, "r") as file: with open(__config_file__, "r") as file:
local_defaults = yaml.safe_load(file) local_defaults = yaml.safe_load(file)
if local_defaults: if local_defaults:
config = merge_dicts_recursively( config = merge_dicts_recursively(
@ -173,22 +179,41 @@ def get_custom_config():
local_defaults, local_defaults,
) )
else: else:
with open(filename, "r") as file: with open(__config_file__, "r") as file:
config = yaml.safe_load(file) config = yaml.safe_load(file)
return config return config
def get_configuration(args): 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") 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") print("There is no configuration file detected. Initial configuration:\n")
init_customization() 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} elif not os.path.exists(__config_file__):
If you want to create a local configuration file, you can create a file named {local_config_file}, or run manimgl --config 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() custom_config = get_custom_config()
write_file = any([args.write_file, args.open, args.finder]) write_file = any([args.write_file, args.open, args.finder])

View file

@ -49,6 +49,7 @@ class TipableVMobject(VMobject):
"tip_config": { "tip_config": {
"fill_opacity": 1, "fill_opacity": 1,
"stroke_width": 0, "stroke_width": 0,
"tip_style": 0, # triangle=0, inner_smooth=1, dot=2
}, },
"normal_vector": OUT, "normal_vector": OUT,
} }
@ -63,6 +64,7 @@ class TipableVMobject(VMobject):
tip = self.create_tip(at_start, **kwargs) tip = self.create_tip(at_start, **kwargs)
self.reset_endpoints_based_on_tip(tip, at_start) self.reset_endpoints_based_on_tip(tip, at_start)
self.asign_tip_attr(tip, at_start) self.asign_tip_attr(tip, at_start)
tip.set_color(self.get_stroke_color())
self.add(tip) self.add(tip)
return self return self
@ -786,12 +788,20 @@ class ArrowTip(Triangle):
"width": DEFAULT_ARROW_TIP_WIDTH, "width": DEFAULT_ARROW_TIP_WIDTH,
"length": DEFAULT_ARROW_TIP_LENGTH, "length": DEFAULT_ARROW_TIP_LENGTH,
"angle": 0, "angle": 0,
"tip_style": 0, # triangle=0, inner_smooth=1, dot=2
} }
def __init__(self, **kwargs): def __init__(self, **kwargs):
Triangle.__init__(self, start_angle=0, **kwargs) Triangle.__init__(self, start_angle=0, **kwargs)
self.set_height(self.width) self.set_height(self.width)
self.set_width(self.length, stretch=True) 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) self.rotate(self.angle)
def get_base(self): def get_base(self):

View file

@ -283,7 +283,7 @@ class ShowPassingFlashWithThinningStrokeWidth(AnimationGroup):
max_stroke_width = vmobject.get_stroke_width() max_stroke_width = vmobject.get_stroke_width()
max_time_width = kwargs.pop("time_width", self.time_width) max_time_width = kwargs.pop("time_width", self.time_width)
AnimationGroup.__init__(self, *[ AnimationGroup.__init__(self, *[
ShowPassingFlash( VShowPassingFlash(
vmobject.deepcopy().set_stroke(width=stroke_width), vmobject.deepcopy().set_stroke(width=stroke_width),
time_width=time_width, time_width=time_width,
**kwargs **kwargs