mirror of
https://github.com/3b1b/manim.git
synced 2025-08-30 15:48:29 +00:00
Merge pull request #1941 from 3b1b/video-work
Small bug fixes and refactors
This commit is contained in:
commit
67912e26d3
8 changed files with 60 additions and 56 deletions
|
@ -184,7 +184,7 @@ def get_manim_dir():
|
|||
return os.path.abspath(os.path.join(manimlib_dir, ".."))
|
||||
|
||||
|
||||
def get_module(file_name):
|
||||
def get_module(file_name: str | None):
|
||||
if file_name is None:
|
||||
return None
|
||||
module_name = file_name.replace(os.sep, ".").replace(".py", "")
|
||||
|
@ -198,8 +198,9 @@ def get_indent(line: str):
|
|||
return len(line) - len(line.lstrip())
|
||||
|
||||
|
||||
@contextmanager
|
||||
def insert_embed_line(file_name: str, scene_name: str, line_marker: str):
|
||||
def get_module_with_inserted_embed_line(
|
||||
file_name: str, scene_name: str, line_marker: str
|
||||
):
|
||||
"""
|
||||
This is hacky, but convenient. When user includes the argument "-e", it will try
|
||||
to recreate a file that inserts the line `self.embed()` into the end of the scene's
|
||||
|
@ -255,14 +256,19 @@ def insert_embed_line(file_name: str, scene_name: str, line_marker: str):
|
|||
inserted_line = " " * n_spaces + "self.embed()\n"
|
||||
new_lines = list(lines)
|
||||
new_lines.insert(prev_line_num + 1, inserted_line)
|
||||
new_file = file_name.replace(".py", "_insert_embed.py")
|
||||
|
||||
with open(file_name, 'w') as fp:
|
||||
with open(new_file, 'w') as fp:
|
||||
fp.writelines(new_lines)
|
||||
try:
|
||||
yield file_name
|
||||
finally:
|
||||
with open(file_name, 'w') as fp:
|
||||
fp.writelines(lines)
|
||||
|
||||
module = get_module(new_file)
|
||||
# This is to pretend the module imported from the edited lines
|
||||
# of code actually comes from the original file.
|
||||
module.__file__ = file_name
|
||||
|
||||
os.remove(new_file)
|
||||
|
||||
return module
|
||||
|
||||
|
||||
def get_custom_config():
|
||||
|
@ -326,7 +332,7 @@ def get_configuration(args):
|
|||
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(
|
||||
"If you want to create a local configuration file, you can create a file named"
|
||||
"If you want to create a local configuration file, you can create a file named" + \
|
||||
f" `{__config_file__}`, or run `manimgl --config`"
|
||||
)
|
||||
|
||||
|
@ -367,11 +373,12 @@ def get_configuration(args):
|
|||
"quiet": args.quiet,
|
||||
}
|
||||
|
||||
module = get_module(args.file)
|
||||
|
||||
if args.embed is not None:
|
||||
with insert_embed_line(args.file, args.scene_names[0], args.embed) as alt_file:
|
||||
module = get_module(alt_file)
|
||||
module = get_module_with_inserted_embed_line(
|
||||
args.file, args.scene_names[0], args.embed
|
||||
)
|
||||
else:
|
||||
module = get_module(args.file)
|
||||
|
||||
config = {
|
||||
"module": module,
|
||||
|
|
|
@ -410,13 +410,15 @@ class Axes(VGroup, CoordinateSystem):
|
|||
axis_config: dict = dict(),
|
||||
x_axis_config: dict = dict(),
|
||||
y_axis_config: dict = dict(),
|
||||
height: float = FRAME_HEIGHT - 2,
|
||||
width: float = FRAME_WIDTH - 2,
|
||||
height: float | None = None,
|
||||
width: float | None = None,
|
||||
unit_size: float = 1.0,
|
||||
**kwargs
|
||||
):
|
||||
CoordinateSystem.__init__(self, x_range, y_range, **kwargs)
|
||||
VGroup.__init__(self, **kwargs)
|
||||
|
||||
axis_config = dict(**axis_config, unit_size=unit_size)
|
||||
self.x_axis = self.create_axis(
|
||||
self.x_range,
|
||||
axis_config=merge_dicts_recursively(
|
||||
|
@ -435,7 +437,7 @@ class Axes(VGroup, CoordinateSystem):
|
|||
axis_config,
|
||||
y_axis_config
|
||||
),
|
||||
length=height
|
||||
length=height,
|
||||
)
|
||||
self.y_axis.rotate(90 * DEGREES, about_point=ORIGIN)
|
||||
# Add as a separate group in case various other
|
||||
|
@ -449,7 +451,7 @@ class Axes(VGroup, CoordinateSystem):
|
|||
self,
|
||||
range_terms: RangeSpecifier,
|
||||
axis_config: dict,
|
||||
length: float
|
||||
length: float | None
|
||||
) -> NumberLine:
|
||||
axis = NumberLine(range_terms, width=length, **axis_config)
|
||||
axis.shift(-axis.n2p(0))
|
||||
|
@ -576,8 +578,6 @@ class NumberPlane(Axes):
|
|||
self,
|
||||
x_range: RangeSpecifier = (-8.0, 8.0, 1.0),
|
||||
y_range: RangeSpecifier = (-4.0, 4.0, 1.0),
|
||||
height: float = 8.0,
|
||||
width: float = 16.0,
|
||||
background_line_style: dict = dict(
|
||||
stroke_color=BLUE_D,
|
||||
stroke_width=2,
|
||||
|
@ -589,12 +589,7 @@ class NumberPlane(Axes):
|
|||
make_smooth_after_applying_functions: bool = True,
|
||||
**kwargs
|
||||
):
|
||||
super().__init__(
|
||||
x_range, y_range,
|
||||
height=height,
|
||||
width=width,
|
||||
**kwargs
|
||||
)
|
||||
super().__init__(x_range, y_range, **kwargs)
|
||||
self.background_line_style = dict(background_line_style)
|
||||
self.faded_line_style = dict(faded_line_style)
|
||||
self.faded_line_ratio = faded_line_ratio
|
||||
|
|
|
@ -3,6 +3,8 @@ from __future__ import annotations
|
|||
import re
|
||||
|
||||
from manimlib.mobject.svg.string_mobject import StringMobject
|
||||
from manimlib.utils.color import color_to_hex
|
||||
from manimlib.utils.color import hex_to_int
|
||||
from manimlib.utils.tex_file_writing import tex_content_to_svg_file
|
||||
|
||||
from typing import TYPE_CHECKING
|
||||
|
@ -159,7 +161,7 @@ class MTex(StringMobject):
|
|||
|
||||
@staticmethod
|
||||
def get_color_command(rgb_hex: str) -> str:
|
||||
rgb = MTex.hex_to_int(rgb_hex)
|
||||
rgb = hex_to_int(rgb_hex)
|
||||
rg, b = divmod(rgb, 256)
|
||||
r, g = divmod(rg, 256)
|
||||
return f"\\color[RGB]{{{r}, {g}, {b}}}"
|
||||
|
@ -181,7 +183,7 @@ class MTex(StringMobject):
|
|||
suffix_lines = []
|
||||
if not is_labelled:
|
||||
prefix_lines.append(self.get_color_command(
|
||||
self.color_to_hex(self.base_color)
|
||||
color_to_hex(self.base_color)
|
||||
))
|
||||
if self.alignment:
|
||||
prefix_lines.append(self.alignment)
|
||||
|
|
|
@ -10,8 +10,9 @@ from manimlib.constants import WHITE
|
|||
from manimlib.logger import log
|
||||
from manimlib.mobject.svg.svg_mobject import SVGMobject
|
||||
from manimlib.mobject.types.vectorized_mobject import VGroup
|
||||
from manimlib.utils.color import color_to_rgb
|
||||
from manimlib.utils.color import rgb_to_hex
|
||||
from manimlib.utils.color import color_to_hex
|
||||
from manimlib.utils.color import hex_to_int
|
||||
from manimlib.utils.color import int_to_hex
|
||||
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
|
@ -117,7 +118,7 @@ class StringMobject(SVGMobject, ABC):
|
|||
for submob, labelled_svg_submob in zip(
|
||||
self.submobjects, labelled_svg.submobjects
|
||||
):
|
||||
label = self.hex_to_int(self.color_to_hex(
|
||||
label = hex_to_int(color_to_hex(
|
||||
labelled_svg_submob.get_fill_color()
|
||||
))
|
||||
if label >= labels_count:
|
||||
|
@ -129,7 +130,7 @@ class StringMobject(SVGMobject, ABC):
|
|||
"Unrecognizable color labels detected (%s). " + \
|
||||
"The result could be unexpected.",
|
||||
", ".join(
|
||||
self.int_to_hex(color)
|
||||
int_to_hex(color)
|
||||
for color in unrecognizable_colors
|
||||
)
|
||||
)
|
||||
|
@ -196,18 +197,6 @@ class StringMobject(SVGMobject, ABC):
|
|||
def span_contains(span_0: Span, span_1: Span) -> bool:
|
||||
return span_0[0] <= span_1[0] and span_0[1] >= span_1[1]
|
||||
|
||||
@staticmethod
|
||||
def color_to_hex(color: ManimColor) -> str:
|
||||
return rgb_to_hex(color_to_rgb(color))
|
||||
|
||||
@staticmethod
|
||||
def hex_to_int(rgb_hex: str) -> int:
|
||||
return int(rgb_hex[1:], 16)
|
||||
|
||||
@staticmethod
|
||||
def int_to_hex(rgb_int: int) -> str:
|
||||
return f"#{rgb_int:06x}".upper()
|
||||
|
||||
# Parsing
|
||||
|
||||
def parse(self) -> None:
|
||||
|
@ -380,7 +369,7 @@ class StringMobject(SVGMobject, ABC):
|
|||
lambda label, flag, attr_dict: self.get_command_string(
|
||||
attr_dict,
|
||||
is_end=flag < 0,
|
||||
label_hex=self.int_to_hex(label) if is_labelled else None
|
||||
label_hex=int_to_hex(label) if is_labelled else None
|
||||
)
|
||||
)
|
||||
prefix, suffix = self.get_content_prefix_and_suffix(
|
||||
|
|
|
@ -15,6 +15,8 @@ from manimlib.constants import NORMAL
|
|||
from manimlib.logger import log
|
||||
from manimlib.mobject.svg.string_mobject import StringMobject
|
||||
from manimlib.utils.customization import get_customization
|
||||
from manimlib.utils.color import color_to_hex
|
||||
from manimlib.utils.color import int_to_hex
|
||||
from manimlib.utils.directories import get_downloads_dir
|
||||
from manimlib.utils.directories import get_text_dir
|
||||
from manimlib.utils.simple_functions import hash_string
|
||||
|
@ -366,7 +368,7 @@ class MarkupText(StringMobject):
|
|||
self, is_labelled: bool
|
||||
) -> tuple[str, str]:
|
||||
global_attr_dict = {
|
||||
"foreground": self.color_to_hex(self.base_color),
|
||||
"foreground": color_to_hex(self.base_color),
|
||||
"font_family": self.font,
|
||||
"font_style": self.slant,
|
||||
"font_weight": self.weight,
|
||||
|
@ -394,7 +396,7 @@ class MarkupText(StringMobject):
|
|||
self.get_command_string(
|
||||
global_attr_dict,
|
||||
is_end=is_end,
|
||||
label_hex=self.int_to_hex(0) if is_labelled else None
|
||||
label_hex=int_to_hex(0) if is_labelled else None
|
||||
)
|
||||
for is_end in (False, True)
|
||||
)
|
||||
|
|
|
@ -100,7 +100,6 @@ class VMobject(Mobject):
|
|||
self.flat_stroke = flat_stroke
|
||||
|
||||
self.needs_new_triangulation = True
|
||||
self.needs_new_unit_normal = True
|
||||
self.triangulation = np.zeros(0, dtype='i4')
|
||||
|
||||
super().__init__(**kwargs)
|
||||
|
@ -759,10 +758,9 @@ class VMobject(Mobject):
|
|||
if not self.has_points():
|
||||
return np.zeros(3)
|
||||
|
||||
nppc = self.n_points_per_curve
|
||||
points = self.get_points()
|
||||
p0 = points[0::nppc]
|
||||
p1 = points[nppc - 1::nppc]
|
||||
p0 = points[:-1]
|
||||
p1 = points[1:]
|
||||
|
||||
# Each term goes through all edges [(x1, y1, z1), (x2, y2, z2)]
|
||||
return 0.5 * np.array([
|
||||
|
@ -772,7 +770,7 @@ class VMobject(Mobject):
|
|||
])
|
||||
|
||||
def get_unit_normal(self, recompute: bool = False) -> Vect3:
|
||||
if not self.needs_new_unit_normal and not recompute:
|
||||
if not recompute:
|
||||
return self.data["unit_normal"][0]
|
||||
|
||||
if self.get_num_points() < 3:
|
||||
|
@ -789,12 +787,11 @@ class VMobject(Mobject):
|
|||
points[2] - points[1],
|
||||
)
|
||||
self.data["unit_normal"][:] = normal
|
||||
self.needs_new_unit_normal = False
|
||||
return normal
|
||||
|
||||
def refresh_unit_normal(self):
|
||||
for mob in self.get_family():
|
||||
mob.needs_new_unit_normal = True
|
||||
mob.get_unit_normal(recompute=True)
|
||||
return self
|
||||
|
||||
# Alignment
|
||||
|
@ -1026,9 +1023,10 @@ class VMobject(Mobject):
|
|||
super().set_points(points)
|
||||
return self
|
||||
|
||||
@triggers_refreshed_triangulation
|
||||
def append_points(self, points: Vect3Array):
|
||||
super().append_points(points)
|
||||
self.refresh_unit_normal()
|
||||
self.refresh_triangulation()
|
||||
return self
|
||||
|
||||
@triggers_refreshed_triangulation
|
||||
|
|
|
@ -624,7 +624,6 @@ class Scene(object):
|
|||
break
|
||||
self.refresh_static_mobjects()
|
||||
self.post_play()
|
||||
return self
|
||||
|
||||
def hold_loop(self):
|
||||
while self.hold_on_wait:
|
||||
|
|
|
@ -62,6 +62,18 @@ def color_to_int_rgba(color: ManimColor, opacity: float = 1.0) -> np.ndarray[int
|
|||
return np.array([*color_to_int_rgb(color), alpha], dtype=np.uint8)
|
||||
|
||||
|
||||
def color_to_hex(color: ManimColor) -> str:
|
||||
return Color(color).hex.upper()
|
||||
|
||||
|
||||
def hex_to_int(rgb_hex: str) -> int:
|
||||
return int(rgb_hex[1:], 16)
|
||||
|
||||
|
||||
def int_to_hex(rgb_int: int) -> str:
|
||||
return f"#{rgb_int:06x}".upper()
|
||||
|
||||
|
||||
def color_gradient(
|
||||
reference_colors: Iterable[ManimColor],
|
||||
length_of_output: int
|
||||
|
|
Loading…
Add table
Reference in a new issue