diff --git a/docs/source/development/changelog.rst b/docs/source/development/changelog.rst index 597fb44a..1ac48974 100644 --- a/docs/source/development/changelog.rst +++ b/docs/source/development/changelog.rst @@ -4,11 +4,35 @@ Changelog Unreleased ---------- +Fixed bugs +^^^^^^^^^^ + +- `#1653 `__: Fixed ``Mobject.stretch_to_fit_depth`` + +New Features +^^^^^^^^^^^^ + +- `e10f850 `__: Added CLI flag ``--log-level`` to specify log level + + +v1.2.0 +------ + Fixed bugs ^^^^^^^^^^ - `#1592 `__: Fixed ``put_start_and_end_on`` in 3D - `#1601 `__: Fixed ``DecimalNumber``'s scaling issue +- `56df154 `__: Fixed bug with common range array used for all coordinate systems +- `8645894 `__: Fixed ``CoordinateSystem`` init bug +- `0dc096b `__: Fixed bug for single-valued ``ValueTracker`` +- `54ad355 `__: Fixed bug with SVG rectangles +- `d45ea28 `__: Fixed ``DotCloud.set_radii`` +- `b543cc0 `__: Temporarily fixed bug for ``PMobject`` array resizing +- `5f878a2 `__: Fixed ``match_style`` +- `719c81d `__: Fixed negative ``path_arc`` case +- `c726eb7 `__: Fixed bug with ``CoordinateSystem.get_lines_parallel_to_axis`` +- `7732d2f `__: Fixed ``ComplexPlane`` -i display bug New Features ^^^^^^^^^^^^ @@ -17,15 +41,38 @@ New Features - `#1607 `__: Added ``FlashyFadeIn`` - `#1607 `__: Save triangulation - `#1625 `__: Added new ``Code`` mobject +- `#1637 `__: Add warnings and use rich to display log - `bd356da `__: Added ``VCube`` - `6d72893 `__: Supported ``ValueTracker`` to track vectors +- `3bb8f3f `__: Added ``set_max_width``, ``set_max_height``, ``set_max_depth`` to ``Mobject`` +- `a35dd5a `__: Added ``TracgTail`` +- `acba13f `__: Added ``Scene.point_to_mobject`` +- `f84b8a6 `__: Added poly_fractal shader +- `b24ba19 `__: Added kwargs to ``TipableVMobject.set_length`` +- `17c2772 `__: Added ``Mobject.replicate`` +- `33fa76d `__: Added mandelbrot_fractal shader +- `f22a341 `__: Saved state before each embed +- `e10a752 `__: Allowed releasing of Textures +- `14fbed7 `__: Consolidated and renamed newton_fractal shader +- `6cdbe0d `__: Hade ``ImageMoject`` remember the filepath to the Image Refactor ^^^^^^^^ -- `#1601 `__: Change back to simpler ``Mobject.scale`` implementation -- `b667db2 `__: Simplify ``Square`` +- `#1601 `__: Changed back to simpler ``Mobject.scale`` implementation +- `b667db2 `__: Simplified ``Square`` - `40290ad `__: Removed unused parameter ``triangulation_locked`` +- `8647a64 `__: Reimplemented ``Arrow`` +- `d8378d8 `__: Used ``make_approximately_smooth`` for ``set_points_smoothly`` by default +- `7b4199c `__: Refactored to call ``_handle_scale_side_effects`` after scaling takes place +- `7356a36 `__: Refactored to only call ``throw_error_if_no_points`` once for ``get_start_and_end`` +- `0787c4f `__: Made sure framerate is 30 for previewed scenes +- `c635f19 `__: Pushed ``pixel_coords_to_space_coords`` to ``Window`` +- `d5a88d0 `__: Refactored to pass tuples and not arrays to uniforms +- `9483f26 `__: Refactored to copy uniform arrays in ``Mobject.copy`` +- `ed1fc4d `__: Added ``bounding_box`` as exceptional key to point_cloud mobject +- `329d2c6 `__: Made sure stroke width is always a float + v1.1.0 ------- diff --git a/manimlib/__main__.py b/manimlib/__main__.py index 82e9b38f..c8faafae 100644 --- a/manimlib/__main__.py +++ b/manimlib/__main__.py @@ -1,16 +1,19 @@ #!/usr/bin/env python import manimlib.config +import manimlib.logger import manimlib.extract_scene import manimlib.utils.init_config from manimlib import __version__ def main(): - args = manimlib.config.parse_cli() - print(f"ManimGL \033[32mv{__version__}\033[0m") + + args = manimlib.config.parse_cli() if args.version and args.file == None: return + if args.log_level: + manimlib.logger.log.setLevel(args.log_level) if args.config: manimlib.utils.init_config.init_customization() @@ -21,5 +24,5 @@ def main(): for scene in scenes: scene.run() -if __name__ == '__main__': +if __name__ == "__main__": main() diff --git a/manimlib/camera/camera.py b/manimlib/camera/camera.py index aca7646c..8144dd48 100644 --- a/manimlib/camera/camera.py +++ b/manimlib/camera/camera.py @@ -67,7 +67,7 @@ class CameraFrame(Mobject): added_rot_T = rotation_matrix_transpose(angle, axis) new_rot_T = np.dot(curr_rot_T, added_rot_T) Fz = new_rot_T[2] - phi = np.arccos(Fz[2]) + phi = np.arccos(clip(Fz[2], -1, 1)) theta = angle_of_vector(Fz[:2]) + PI / 2 partial_rot_T = np.dot( rotation_matrix_transpose(phi, RIGHT), diff --git a/manimlib/config.py b/manimlib/config.py index 636adb71..8992ce5b 100644 --- a/manimlib/config.py +++ b/manimlib/config.py @@ -142,6 +142,10 @@ def parse_cli(): action="store_true", help="Display the version of manimgl" ) + parser.add_argument( + "--log-level", + help="Level of messages to Display, can be DEBUG / INFO / WARNING / ERROR / CRITICAL" + ) args = parser.parse_args() return args except argparse.ArgumentError as err: @@ -193,9 +197,9 @@ def get_custom_config(): def check_temporary_storage(config): if config["directories"]["temporary_storage"] == "" and sys.platform == "win32": - log.warning("You may be using Windows platform and have not specified the `temporary\ -_storage` path, which may cause OSError. So it is recommended that you specify the `temporary\ -_storage` in the config file (.yml)") + log.warning("You may be using Windows platform and have not specified the path of" + " `temporary_storage`, which may cause OSError. So it is recommended" + " to specify the `temporary_storage` in the config file (.yml)") def get_configuration(args): @@ -220,13 +224,13 @@ def get_configuration(args): 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(__config_file__)): - log.info("There is no configuration file detected. Initial configuration:\n") + log.info("There is no configuration file detected. Switch to the config file initializer:") init_customization() elif not os.path.exists(__config_file__): log.info(f"Using the default configuration file, which you can modify in `{global_defaults_file}`") - log.info(f"If you want to create a local configuration file, you can create a file named \ -`{__config_file__}`, or run `manimgl --config`") + log.info("If you want to create a local configuration file, you can create a file named" + f" `{__config_file__}`, or run `manimgl --config`") custom_config = get_custom_config() check_temporary_storage(custom_config) diff --git a/manimlib/logger.py b/manimlib/logger.py index b8f9fa36..b04ae7ae 100644 --- a/manimlib/logger.py +++ b/manimlib/logger.py @@ -1,9 +1,13 @@ import logging from rich.logging import RichHandler +__all__ = ["log"] + + FORMAT = "%(message)s" logging.basicConfig( - level="NOTSET", format=FORMAT, datefmt="[%X]", handlers=[RichHandler()] + level=logging.WARNING, format=FORMAT, datefmt="[%X]", handlers=[RichHandler()] ) -log = logging.getLogger("rich") \ No newline at end of file +log = logging.getLogger("manimgl") +log.setLevel("DEBUG") diff --git a/manimlib/mobject/mobject.py b/manimlib/mobject/mobject.py index 056db669..d93fd180 100644 --- a/manimlib/mobject/mobject.py +++ b/manimlib/mobject/mobject.py @@ -767,7 +767,7 @@ class Mobject(object): return self.rescale_to_fit(height, 1, stretch=True, **kwargs) def stretch_to_fit_depth(self, depth, **kwargs): - return self.rescale_to_fit(depth, 1, stretch=True, **kwargs) + return self.rescale_to_fit(depth, 2, stretch=True, **kwargs) def set_width(self, width, stretch=False, **kwargs): return self.rescale_to_fit(width, 0, stretch=stretch, **kwargs) diff --git a/manimlib/scene/scene.py b/manimlib/scene/scene.py index 21f05241..118404be 100644 --- a/manimlib/scene/scene.py +++ b/manimlib/scene/scene.py @@ -10,10 +10,10 @@ import time from manimlib.animation.animation import prepare_animation from manimlib.animation.transform import MoveToTarget -from manimlib.mobject.mobject import Point from manimlib.camera.camera import Camera from manimlib.constants import DEFAULT_WAIT_TIME from manimlib.mobject.mobject import Mobject +from manimlib.mobject.mobject import Point from manimlib.scene.scene_file_writer import SceneFileWriter from manimlib.utils.config_ops import digest_config from manimlib.utils.family_ops import extract_mobject_family_members @@ -101,8 +101,8 @@ class Scene(object): # If there is a window, enter a loop # which updates the frame while under # the hood calling the pyglet event loop - log.info("Tips: You are now in the interactive mode. Now you can use the keyboard\ -and the mouse to interact with the scene. Just press `q` if you want to quit.") + log.info("Tips: You are now in the interactive mode. Now you can use the keyboard" + " and the mouse to interact with the scene. Just press `q` if you want to quit.") self.quit_interaction = False self.lock_static_mobject_data() while not (self.window.is_closing or self.quit_interaction): @@ -134,8 +134,8 @@ and the mouse to interact with the scene. Just press `q` if you want to quit.") local_ns["touch"] = self.interact for term in ("play", "wait", "add", "remove", "clear", "save_state", "restore"): local_ns[term] = getattr(self, term) - log.info("Tips: Now the embed iPython terminal is open. But you can't interact with \ -the window directly. To do so, you need to type `touch()` or `self.interact()`") + log.info("Tips: Now the embed iPython terminal is open. But you can't interact with" + " the window directly. To do so, you need to type `touch()` or `self.interact()`") shell(local_ns=local_ns, stack_depth=2) # End scene when exiting an embed. raise EndSceneEarlyException() @@ -463,9 +463,7 @@ the window directly. To do so, you need to type `touch()` or `self.interact()`") @handle_play_like_call def play(self, *args, **kwargs): if len(args) == 0: - log.warning( - "Called Scene.play with no animations" - ) + log.warning("Called Scene.play with no animations") return animations = self.anims_from_play_args(*args, **kwargs) self.lock_static_mobject_data(*animations) diff --git a/manimlib/scene/scene_file_writer.py b/manimlib/scene/scene_file_writer.py index 8d74765e..3269b416 100644 --- a/manimlib/scene/scene_file_writer.py +++ b/manimlib/scene/scene_file_writer.py @@ -301,7 +301,7 @@ class SceneFileWriter(object): self.print_file_ready_message(file_path) def print_file_ready_message(self, file_path): - log.info(f"\nFile ready at {file_path}\n") + log.info(f"File ready at {file_path}") def should_open_file(self): return any([ diff --git a/manimlib/utils/bezier.py b/manimlib/utils/bezier.py index f5317584..c6b750e1 100644 --- a/manimlib/utils/bezier.py +++ b/manimlib/utils/bezier.py @@ -69,9 +69,9 @@ def interpolate(start, end, alpha): try: return (1 - alpha) * start + alpha * end except TypeError: - log.debug(type(start), start.dtype) - log.debug(type(end), start.dtype) - log.debug(alpha) + log.debug(f"`start` parameter with type `{type(start)}` and dtype `{start.dtype}`") + log.debug(f"`end` parameter with type `{type(end)}` and dtype `{end.dtype}`") + log.debug(f"`alpha` parameter with value `{alpha}`") import sys sys.exit(2) diff --git a/manimlib/utils/init_config.py b/manimlib/utils/init_config.py index 10a0b8ba..db33cd70 100644 --- a/manimlib/utils/init_config.py +++ b/manimlib/utils/init_config.py @@ -46,6 +46,7 @@ def init_customization(): } } + print("Initialize configuration") scope = input(" Please select the scope of the configuration [global/local]: ") if scope == "global": from manimlib.config import get_manim_dir diff --git a/requirements.txt b/requirements.txt index 1b85903b..e10b4521 100644 --- a/requirements.txt +++ b/requirements.txt @@ -12,6 +12,7 @@ moderngl_window pydub pygments pyyaml +rich screeninfo pyreadline; sys_platform == 'win32' validators diff --git a/setup.cfg b/setup.cfg index 3b3ed5fd..4b90f1d2 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,6 +1,6 @@ [metadata] name = manimgl -version = 1.1.1 +version = 1.2.0 author = Grant Sanderson author_email= grant@3blue1brown.com description = Animation engine for explanatory math videos @@ -29,7 +29,9 @@ install_requires = moderngl moderngl_window pydub + pygments pyyaml + rich screeninfo pyreadline; sys_platform == 'win32' validators