From f4737828f65999252c0cab9824d9d34cfabf4341 Mon Sep 17 00:00:00 2001 From: Grant Sanderson Date: Thu, 20 Mar 2025 14:00:35 -0500 Subject: [PATCH] Video work (#2326) * Only use -no-pdf for xelatex rendering * Instead of tracking du and dv points on surface, track points off the surface in the normal direction This means that surface shading will not necessarily work well for arbitrary transformations of the surface. But the existing solution was flimsy anyway, and caused annoying issues with singularity points. * Have density of anchor points on arcs depend on arc length * Allow for specifying true normals and orientation of Sphere * Change miter threshold on stroke shader * Add get_start_and_end to DashedLine * Add min_total_width option to DecimalNumber * Have BackgroundRectangle.set_style absorb (and ignore) added configuration Note, this feels suboptimal * Add LineBrace * Update font_size adjustment in Tex * Add scale_factor parameter to BulletedList.fade_all_but * Minor import tweaks * Add play_sound --- manimlib/mobject/svg/special_tex.py | 7 +++++-- manimlib/scene/scene.py | 4 ++-- manimlib/utils/sounds.py | 28 ++++++++++++++++++++++++++++ 3 files changed, 35 insertions(+), 4 deletions(-) diff --git a/manimlib/mobject/svg/special_tex.py b/manimlib/mobject/svg/special_tex.py index a2ed9964..f933a11e 100644 --- a/manimlib/mobject/svg/special_tex.py +++ b/manimlib/mobject/svg/special_tex.py @@ -22,7 +22,7 @@ class BulletedList(VGroup): buff: float = MED_LARGE_BUFF, aligned_edge: Vect3 = LEFT, **kwargs - ): + ): labelled_content = [R"\item " + item for item in items] tex_string = "\n".join([ R"\begin{itemize}", @@ -36,9 +36,12 @@ class BulletedList(VGroup): self.arrange(DOWN, buff=buff, aligned_edge=aligned_edge) - def fade_all_but(self, index: int, opacity: float = 0.25) -> None: + def fade_all_but(self, index: int, opacity: float = 0.25, scale_factor=0.7) -> None: + max_dot_height = max([item[0].get_height() for item in self.submobjects]) for i, part in enumerate(self.submobjects): + trg_dot_height = (1.0 if i == index else scale_factor) * max_dot_height part.set_fill(opacity=(1.0 if i == index else opacity)) + part.scale(trg_dot_height / part[0].get_height(), about_edge=LEFT) class TexTextFromPresetString(TexText): diff --git a/manimlib/scene/scene.py b/manimlib/scene/scene.py index f334eeac..c43be957 100644 --- a/manimlib/scene/scene.py +++ b/manimlib/scene/scene.py @@ -8,10 +8,9 @@ from functools import wraps from contextlib import contextmanager from contextlib import ExitStack -from pyglet.window import key as PygletWindowKeys - import numpy as np from tqdm.auto import tqdm as ProgressDisplay +from pyglet.window import key as PygletWindowKeys from manimlib.animation.animation import prepare_animation from manimlib.camera.camera import Camera @@ -33,6 +32,7 @@ from manimlib.utils.dict_ops import merge_dicts_recursively from manimlib.utils.family_ops import extract_mobject_family_members from manimlib.utils.family_ops import recursive_mobject_remove from manimlib.utils.iterables import batch_by_property +from manimlib.utils.sounds import play_sound from manimlib.window import Window from typing import TYPE_CHECKING diff --git a/manimlib/utils/sounds.py b/manimlib/utils/sounds.py index f34ba435..c0ddc8f3 100644 --- a/manimlib/utils/sounds.py +++ b/manimlib/utils/sounds.py @@ -1,5 +1,9 @@ from __future__ import annotations +import subprocess +import threading +import platform + from manimlib.utils.directories import get_sound_dir from manimlib.utils.file_ops import find_file @@ -10,3 +14,27 @@ def get_full_sound_file_path(sound_file_name: str) -> str: directories=[get_sound_dir()], extensions=[".wav", ".mp3", ""] ) + + +def play_sound(sound_file): + """Play a sound file using the system's audio player""" + full_path = get_full_sound_file_path(sound_file) + system = platform.system() + + if system == "Windows": + # Windows + subprocess.Popen( + ["powershell", "-c", f"(New-Object Media.SoundPlayer '{full_path}').PlaySync()"], + shell=True, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL + ) + elif system == "Darwin": + # macOS + subprocess.Popen( + ["afplay", full_path], + stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL + ) + else: + subprocess.Popen( + ["aplay", full_path], + stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL + )