mirror of
https://github.com/jeertmans/manim-slides.git
synced 2025-05-22 04:56:24 +08:00
feat(cli/lib): use scene background color as default (#160)
* Use scene background color as default * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Minor changes to feature: Read scene background * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Small fix for feature "Read bg color" * chore(ci): add typing ignore * fix(ci): typo --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Jérome Eertmans <jeertmans@icloud.com>
This commit is contained in:
@ -8,6 +8,7 @@ from pathlib import Path
|
|||||||
from typing import Dict, List, Optional, Set, Tuple, Union
|
from typing import Dict, List, Optional, Set, Tuple, Union
|
||||||
|
|
||||||
from pydantic import BaseModel, FilePath, PositiveInt, root_validator, validator
|
from pydantic import BaseModel, FilePath, PositiveInt, root_validator, validator
|
||||||
|
from pydantic.color import Color
|
||||||
from PySide6.QtCore import Qt
|
from PySide6.QtCore import Qt
|
||||||
|
|
||||||
from .defaults import FFMPEG_BIN
|
from .defaults import FFMPEG_BIN
|
||||||
@ -150,6 +151,7 @@ class PresentationConfig(BaseModel): # type: ignore
|
|||||||
slides: List[SlideConfig]
|
slides: List[SlideConfig]
|
||||||
files: List[FilePath]
|
files: List[FilePath]
|
||||||
resolution: Tuple[PositiveInt, PositiveInt] = (1920, 1080)
|
resolution: Tuple[PositiveInt, PositiveInt] = (1920, 1080)
|
||||||
|
background_color: Color = "black"
|
||||||
|
|
||||||
@root_validator
|
@root_validator
|
||||||
def animation_indices_match_files(
|
def animation_indices_match_files(
|
||||||
|
@ -321,9 +321,9 @@ class RevealJS(Converter):
|
|||||||
# Read more about this:
|
# Read more about this:
|
||||||
# https://developer.mozilla.org/en-US/docs/Web/Media/Autoplay_guide#autoplay_and_autoplay_blocking
|
# https://developer.mozilla.org/en-US/docs/Web/Media/Autoplay_guide#autoplay_and_autoplay_blocking
|
||||||
if slide_config.is_loop():
|
if slide_config.is_loop():
|
||||||
yield f'<section data-background-size={self.background_size.value} data-background-video="{file}" data-background-video-muted data-background-video-loop></section>'
|
yield f'<section data-background-size={self.background_size.value} data-background-color="{presentation_config.background_color}" data-background-video="{file}" data-background-video-muted data-background-video-loop></section>'
|
||||||
else:
|
else:
|
||||||
yield f'<section data-background-size={self.background_size.value} data-background-video="{file}" data-background-video-muted></section>'
|
yield f'<section data-background-size={self.background_size.value} data-background-color="{presentation_config.background_color}" data-background-video="{file}" data-background-video-muted></section>'
|
||||||
|
|
||||||
def load_template(self) -> str:
|
def load_template(self) -> str:
|
||||||
"""Returns the RevealJS HTML template as a string."""
|
"""Returns the RevealJS HTML template as a string."""
|
||||||
|
@ -11,6 +11,7 @@ import cv2
|
|||||||
import numpy as np
|
import numpy as np
|
||||||
from click import Context, Parameter
|
from click import Context, Parameter
|
||||||
from pydantic import ValidationError
|
from pydantic import ValidationError
|
||||||
|
from pydantic.color import Color
|
||||||
from PySide6.QtCore import Qt, QThread, Signal, Slot
|
from PySide6.QtCore import Qt, QThread, Signal, Slot
|
||||||
from PySide6.QtGui import QCloseEvent, QIcon, QImage, QKeyEvent, QPixmap, QResizeEvent
|
from PySide6.QtGui import QCloseEvent, QIcon, QImage, QKeyEvent, QPixmap, QResizeEvent
|
||||||
from PySide6.QtWidgets import QApplication, QGridLayout, QLabel, QWidget
|
from PySide6.QtWidgets import QApplication, QGridLayout, QLabel, QWidget
|
||||||
@ -105,6 +106,11 @@ class Presentation:
|
|||||||
"""Returns the resolution."""
|
"""Returns the resolution."""
|
||||||
return self.config.resolution
|
return self.config.resolution
|
||||||
|
|
||||||
|
@property
|
||||||
|
def background_color(self) -> Color:
|
||||||
|
"""Returns the background color."""
|
||||||
|
return self.config.background_color
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def current_slide_index(self) -> int:
|
def current_slide_index(self) -> int:
|
||||||
return self.__current_slide_index
|
return self.__current_slide_index
|
||||||
@ -411,6 +417,11 @@ class Display(QThread): # type: ignore
|
|||||||
"""Returns the resolution of the current presentation."""
|
"""Returns the resolution of the current presentation."""
|
||||||
return self.current_presentation.resolution
|
return self.current_presentation.resolution
|
||||||
|
|
||||||
|
@property
|
||||||
|
def current_background_color(self) -> Color:
|
||||||
|
"""Returns the background color of the current presentation."""
|
||||||
|
return self.current_presentation.background_color
|
||||||
|
|
||||||
def run(self) -> None:
|
def run(self) -> None:
|
||||||
"""Runs a series of presentations until end or exit."""
|
"""Runs a series of presentations until end or exit."""
|
||||||
while self.run_flag:
|
while self.run_flag:
|
||||||
@ -649,7 +660,9 @@ class App(QWidget): # type: ignore
|
|||||||
self.label.setScaledContents(True)
|
self.label.setScaledContents(True)
|
||||||
self.label.setAlignment(Qt.AlignCenter)
|
self.label.setAlignment(Qt.AlignCenter)
|
||||||
self.label.resize(self.display_width, self.display_height)
|
self.label.resize(self.display_width, self.display_height)
|
||||||
self.label.setStyleSheet(f"background-color: {background_color}")
|
self.label.setStyleSheet(
|
||||||
|
f"background-color: {self.thread.current_background_color}"
|
||||||
|
)
|
||||||
|
|
||||||
self.pixmap = QPixmap(self.width(), self.height())
|
self.pixmap = QPixmap(self.width(), self.height())
|
||||||
self.label.setPixmap(self.pixmap)
|
self.label.setPixmap(self.pixmap)
|
||||||
@ -729,6 +742,9 @@ class App(QWidget): # type: ignore
|
|||||||
self.display_width, self.display_height = self.thread.current_resolution
|
self.display_width, self.display_height = self.thread.current_resolution
|
||||||
if not self.isFullScreen():
|
if not self.isFullScreen():
|
||||||
self.resize(self.display_width, self.display_height)
|
self.resize(self.display_width, self.display_height)
|
||||||
|
self.label.setStyleSheet(
|
||||||
|
f"background-color: {self.thread.current_background_color}"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
@click.command()
|
@click.command()
|
||||||
@ -924,8 +940,8 @@ def start_at_callback(
|
|||||||
"background_color",
|
"background_color",
|
||||||
metavar="COLOR",
|
metavar="COLOR",
|
||||||
type=str,
|
type=str,
|
||||||
default="black",
|
default=None,
|
||||||
help='Set the background color for borders when using "keep" resize mode. Can be any valid CSS color, e.g., "green", "#FF6500" or "rgba(255, 255, 0, .5)".',
|
help='Set the background color for borders when using "keep" resize mode. Can be any valid CSS color, e.g., "green", "#FF6500" or "rgba(255, 255, 0, .5)". If not set, it defaults to the background color configured in the Manim scene.',
|
||||||
show_default=True,
|
show_default=True,
|
||||||
)
|
)
|
||||||
@click.option(
|
@click.option(
|
||||||
@ -980,7 +996,7 @@ def present(
|
|||||||
hide_mouse: bool,
|
hide_mouse: bool,
|
||||||
aspect_ratio: str,
|
aspect_ratio: str,
|
||||||
resize_mode: str,
|
resize_mode: str,
|
||||||
background_color: str,
|
background_color: Optional[str],
|
||||||
start_at: Tuple[Optional[int], Optional[int], Optional[int]],
|
start_at: Tuple[Optional[int], Optional[int], Optional[int]],
|
||||||
start_at_scene_number: Optional[int],
|
start_at_scene_number: Optional[int],
|
||||||
start_at_slide_number: Optional[int],
|
start_at_slide_number: Optional[int],
|
||||||
@ -1005,6 +1021,10 @@ def present(
|
|||||||
for presentation_config in presentation_configs:
|
for presentation_config in presentation_configs:
|
||||||
presentation_config.resolution = resolution
|
presentation_config.resolution = resolution
|
||||||
|
|
||||||
|
if background_color is not None:
|
||||||
|
for presentation_config in presentation_configs:
|
||||||
|
presentation_config.background_color = background_color
|
||||||
|
|
||||||
presentations = [
|
presentations = [
|
||||||
Presentation(presentation_config)
|
Presentation(presentation_config)
|
||||||
for presentation_config in presentation_configs
|
for presentation_config in presentation_configs
|
||||||
@ -1048,7 +1068,6 @@ def present(
|
|||||||
hide_mouse=hide_mouse,
|
hide_mouse=hide_mouse,
|
||||||
aspect_ratio=ASPECT_RATIO_MODES[aspect_ratio],
|
aspect_ratio=ASPECT_RATIO_MODES[aspect_ratio],
|
||||||
resize_mode=RESIZE_MODES[resize_mode],
|
resize_mode=RESIZE_MODES[resize_mode],
|
||||||
background_color=background_color,
|
|
||||||
start_at_scene_number=start_at_scene_number,
|
start_at_scene_number=start_at_scene_number,
|
||||||
start_at_slide_number=start_at_slide_number,
|
start_at_slide_number=start_at_slide_number,
|
||||||
start_at_animation_number=start_at_animation_number,
|
start_at_animation_number=start_at_animation_number,
|
||||||
|
@ -54,6 +54,14 @@ class Slide(Scene): # type:ignore
|
|||||||
self.__loop_start_animation: Optional[int] = None
|
self.__loop_start_animation: Optional[int] = None
|
||||||
self.__pause_start_animation = 0
|
self.__pause_start_animation = 0
|
||||||
|
|
||||||
|
@property
|
||||||
|
def __background_color(self) -> str:
|
||||||
|
"""Returns the scene's background color."""
|
||||||
|
if MANIMGL:
|
||||||
|
return self.camera_config["background_color"].hex # type: ignore
|
||||||
|
else:
|
||||||
|
return config["background_color"].hex # type: ignore
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def __resolution(self) -> Tuple[int, int]:
|
def __resolution(self) -> Tuple[int, int]:
|
||||||
"""Returns the scene's resolution used during rendering."""
|
"""Returns the scene's resolution used during rendering."""
|
||||||
@ -321,7 +329,10 @@ class Slide(Scene): # type:ignore
|
|||||||
with open(slide_path, "w") as f:
|
with open(slide_path, "w") as f:
|
||||||
f.write(
|
f.write(
|
||||||
PresentationConfig(
|
PresentationConfig(
|
||||||
slides=self.__slides, files=files, resolution=self.__resolution
|
slides=self.__slides,
|
||||||
|
files=files,
|
||||||
|
resolution=self.__resolution,
|
||||||
|
background_color=self.__background_color,
|
||||||
).json(indent=2)
|
).json(indent=2)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user