mirror of
https://github.com/jeertmans/manim-slides.git
synced 2025-05-22 13:06:45 +08:00
feat(present): fix presentation size and add screen option (#232)
* feat(present): fix presentation size and add screen option This kinda fixes the issue of weird resizes between two presentations * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * fix(ci): typing --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
This commit is contained in:
@ -25,6 +25,7 @@ HIGHLIGHTED_KEYWORDS = [ # these keywords are highlighted specially
|
|||||||
"File",
|
"File",
|
||||||
"Rendering",
|
"Rendering",
|
||||||
"Rendered",
|
"Rendered",
|
||||||
|
"Pressed key",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
@ -14,7 +14,15 @@ from click import Context, Parameter
|
|||||||
from pydantic import ValidationError
|
from pydantic import ValidationError
|
||||||
from pydantic_extra_types.color import Color
|
from pydantic_extra_types.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,
|
||||||
|
QScreen,
|
||||||
|
)
|
||||||
from PySide6.QtWidgets import QApplication, QGridLayout, QLabel, QWidget
|
from PySide6.QtWidgets import QApplication, QGridLayout, QLabel, QWidget
|
||||||
from tqdm import tqdm
|
from tqdm import tqdm
|
||||||
|
|
||||||
@ -351,7 +359,7 @@ class Display(QThread): # type: ignore
|
|||||||
|
|
||||||
change_video_signal = Signal(np.ndarray)
|
change_video_signal = Signal(np.ndarray)
|
||||||
change_info_signal = Signal(dict)
|
change_info_signal = Signal(dict)
|
||||||
change_presentation_sigal = Signal()
|
change_presentation_signal = Signal()
|
||||||
finished = Signal()
|
finished = Signal()
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
@ -402,7 +410,7 @@ class Display(QThread): # type: ignore
|
|||||||
if -len(self) <= value < len(self):
|
if -len(self) <= value < len(self):
|
||||||
self.__current_presentation_index = value
|
self.__current_presentation_index = value
|
||||||
self.current_presentation.release_cap()
|
self.current_presentation.release_cap()
|
||||||
self.change_presentation_sigal.emit()
|
self.change_presentation_signal.emit()
|
||||||
else:
|
else:
|
||||||
logger.error(
|
logger.error(
|
||||||
f"Could not load scene number {value}, playing first scene instead."
|
f"Could not load scene number {value}, playing first scene instead."
|
||||||
@ -423,6 +431,10 @@ class Display(QThread): # type: ignore
|
|||||||
"""Returns the background color of the current presentation."""
|
"""Returns the background color of the current presentation."""
|
||||||
return self.current_presentation.background_color
|
return self.current_presentation.background_color
|
||||||
|
|
||||||
|
def start(self) -> None:
|
||||||
|
super().start()
|
||||||
|
self.change_presentation_signal.emit()
|
||||||
|
|
||||||
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:
|
||||||
@ -651,10 +663,15 @@ class App(QWidget): # type: ignore
|
|||||||
aspect_ratio: AspectRatio = AspectRatio.auto,
|
aspect_ratio: AspectRatio = AspectRatio.auto,
|
||||||
resize_mode: Qt.TransformationMode = Qt.SmoothTransformation,
|
resize_mode: Qt.TransformationMode = Qt.SmoothTransformation,
|
||||||
background_color: str = "black",
|
background_color: str = "black",
|
||||||
|
screen: Optional[QScreen] = None,
|
||||||
**kwargs: Any,
|
**kwargs: Any,
|
||||||
):
|
):
|
||||||
super().__init__()
|
super().__init__()
|
||||||
|
|
||||||
|
if screen:
|
||||||
|
self.setScreen(screen)
|
||||||
|
self.move(screen.geometry().topLeft())
|
||||||
|
|
||||||
self.setWindowTitle(WINDOW_NAME)
|
self.setWindowTitle(WINDOW_NAME)
|
||||||
self.icon = QIcon(":/icon.png")
|
self.icon = QIcon(":/icon.png")
|
||||||
self.setWindowIcon(self.icon)
|
self.setWindowIcon(self.icon)
|
||||||
@ -676,10 +693,6 @@ class App(QWidget): # type: ignore
|
|||||||
if self.aspect_ratio == AspectRatio.auto:
|
if self.aspect_ratio == AspectRatio.auto:
|
||||||
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.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)
|
||||||
@ -694,11 +707,13 @@ class App(QWidget): # type: ignore
|
|||||||
|
|
||||||
if fullscreen:
|
if fullscreen:
|
||||||
self.showFullScreen()
|
self.showFullScreen()
|
||||||
|
else:
|
||||||
|
self.resize(self.display_width, self.display_height)
|
||||||
|
|
||||||
# connect signals
|
# connect signals
|
||||||
self.thread.change_video_signal.connect(self.update_image)
|
self.thread.change_video_signal.connect(self.update_image)
|
||||||
self.thread.change_info_signal.connect(self.info.update_info)
|
self.thread.change_info_signal.connect(self.info.update_info)
|
||||||
self.thread.change_presentation_sigal.connect(self.update_canvas)
|
self.thread.change_presentation_signal.connect(self.update_canvas)
|
||||||
self.thread.finished.connect(self.closeAll)
|
self.thread.finished.connect(self.closeAll)
|
||||||
self.send_key_signal.connect(self.thread.set_key)
|
self.send_key_signal.connect(self.thread.set_key)
|
||||||
|
|
||||||
@ -756,8 +771,12 @@ class App(QWidget): # type: ignore
|
|||||||
def update_canvas(self) -> None:
|
def update_canvas(self) -> None:
|
||||||
"""Update the canvas when a presentation has changed."""
|
"""Update the canvas when a presentation has changed."""
|
||||||
logger.debug("Updating canvas")
|
logger.debug("Updating canvas")
|
||||||
self.display_width, self.display_height = self.thread.current_resolution
|
w, h = self.thread.current_resolution
|
||||||
if not self.isFullScreen():
|
|
||||||
|
if not self.isFullScreen() and (
|
||||||
|
self.display_width != w or self.display_height != h
|
||||||
|
):
|
||||||
|
self.display_width, self.display_height = w, h
|
||||||
self.resize(self.display_width, self.display_height)
|
self.resize(self.display_width, self.display_height)
|
||||||
self.label.setStyleSheet(
|
self.label.setStyleSheet(
|
||||||
f"background-color: {self.thread.current_background_color}"
|
f"background-color: {self.thread.current_background_color}"
|
||||||
@ -998,6 +1017,14 @@ def start_at_callback(
|
|||||||
default=0,
|
default=0,
|
||||||
help="Start presenting at a given animation number (0 is first, -1 is last). This conflicts with slide number since animation number is absolute to the presentation.",
|
help="Start presenting at a given animation number (0 is first, -1 is last). This conflicts with slide number since animation number is absolute to the presentation.",
|
||||||
)
|
)
|
||||||
|
@click.option(
|
||||||
|
"--screen",
|
||||||
|
"screen_number",
|
||||||
|
metavar="NUMBER",
|
||||||
|
type=int,
|
||||||
|
default=None,
|
||||||
|
help="Presents content on the given screen (a.k.a. display).",
|
||||||
|
)
|
||||||
@click.help_option("-h", "--help")
|
@click.help_option("-h", "--help")
|
||||||
@verbosity_option
|
@verbosity_option
|
||||||
def present(
|
def present(
|
||||||
@ -1018,6 +1045,7 @@ def present(
|
|||||||
start_at_scene_number: Optional[int],
|
start_at_scene_number: Optional[int],
|
||||||
start_at_slide_number: Optional[int],
|
start_at_slide_number: Optional[int],
|
||||||
start_at_animation_number: Optional[int],
|
start_at_animation_number: Optional[int],
|
||||||
|
screen_number: Optional[int] = None,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""
|
"""
|
||||||
Present SCENE(s), one at a time, in order.
|
Present SCENE(s), one at a time, in order.
|
||||||
@ -1069,7 +1097,9 @@ def present(
|
|||||||
ext = record_to.suffix
|
ext = record_to.suffix
|
||||||
if ext.lower() != ".avi":
|
if ext.lower() != ".avi":
|
||||||
raise click.UsageError(
|
raise click.UsageError(
|
||||||
"Recording only support '.avi' extension. For other video formats, please convert the resulting '.avi' file afterwards."
|
"Recording only support '.avi' extension. "
|
||||||
|
"For other video formats, "
|
||||||
|
"please convert the resulting '.avi' file afterwards."
|
||||||
)
|
)
|
||||||
|
|
||||||
if start_at[0]:
|
if start_at[0]:
|
||||||
@ -1087,6 +1117,19 @@ def present(
|
|||||||
app = QApplication.instance()
|
app = QApplication.instance()
|
||||||
|
|
||||||
app.setApplicationName("Manim Slides")
|
app.setApplicationName("Manim Slides")
|
||||||
|
|
||||||
|
if screen_number is not None:
|
||||||
|
try:
|
||||||
|
screen = app.screens()[screen_number]
|
||||||
|
except IndexError:
|
||||||
|
logger.error(
|
||||||
|
f"Invalid screen number {screen_number}, "
|
||||||
|
f"allowed values are from 0 to {len(app.screens())-1} (incl.)"
|
||||||
|
)
|
||||||
|
screen = None
|
||||||
|
else:
|
||||||
|
screen = None
|
||||||
|
|
||||||
a = App(
|
a = App(
|
||||||
presentations,
|
presentations,
|
||||||
config=config,
|
config=config,
|
||||||
@ -1101,7 +1144,9 @@ def present(
|
|||||||
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,
|
||||||
|
screen=screen,
|
||||||
)
|
)
|
||||||
|
|
||||||
a.show()
|
a.show()
|
||||||
|
|
||||||
# inform about CTRL+C
|
# inform about CTRL+C
|
||||||
|
Reference in New Issue
Block a user