mirror of
https://github.com/jeertmans/manim-slides.git
synced 2025-07-03 23:13:51 +08:00
feat(ui): much cleaner UI (#17)
This commit is contained in:
@ -1 +1 @@
|
|||||||
__version__ = "4.0.0rc1"
|
__version__ = "4.0.0"
|
||||||
|
@ -1,5 +1,9 @@
|
|||||||
import platform
|
import platform
|
||||||
|
|
||||||
|
import cv2
|
||||||
|
|
||||||
|
FONT_ARGS = (cv2.FONT_HERSHEY_SIMPLEX, 1, 255, 1, cv2.LINE_AA)
|
||||||
|
PIXELS_PER_CHARACTER = 20
|
||||||
FOLDER_PATH: str = "./slides"
|
FOLDER_PATH: str = "./slides"
|
||||||
CONFIG_PATH: str = ".manim-slides.json"
|
CONFIG_PATH: str = ".manim-slides.json"
|
||||||
|
|
||||||
|
@ -17,9 +17,10 @@ from pydantic import ValidationError
|
|||||||
|
|
||||||
from .commons import config_path_option
|
from .commons import config_path_option
|
||||||
from .config import Config, PresentationConfig, SlideConfig, SlideType
|
from .config import Config, PresentationConfig, SlideConfig, SlideType
|
||||||
from .defaults import CONFIG_PATH, FOLDER_PATH
|
from .defaults import CONFIG_PATH, FOLDER_PATH, FONT_ARGS
|
||||||
|
|
||||||
WINDOW_NAME = "Manim Slides"
|
WINDOW_NAME = "Manim Slides"
|
||||||
|
WINDOW_INFO_NAME = f"{WINDOW_NAME}: Info"
|
||||||
|
|
||||||
|
|
||||||
@unique
|
@unique
|
||||||
@ -251,6 +252,7 @@ class Display:
|
|||||||
start_paused=False,
|
start_paused=False,
|
||||||
fullscreen=False,
|
fullscreen=False,
|
||||||
skip_all=False,
|
skip_all=False,
|
||||||
|
resolution=(1280, 720),
|
||||||
):
|
):
|
||||||
self.presentations = presentations
|
self.presentations = presentations
|
||||||
self.start_paused = start_paused
|
self.start_paused = start_paused
|
||||||
@ -267,6 +269,11 @@ class Display:
|
|||||||
self.lag = 0
|
self.lag = 0
|
||||||
self.last_time = now()
|
self.last_time = now()
|
||||||
|
|
||||||
|
cv2.namedWindow(
|
||||||
|
WINDOW_INFO_NAME,
|
||||||
|
cv2.WINDOW_GUI_NORMAL | cv2.WINDOW_FREERATIO | cv2.WINDOW_AUTOSIZE,
|
||||||
|
)
|
||||||
|
|
||||||
if self.is_windows:
|
if self.is_windows:
|
||||||
user32 = ctypes.windll.user32
|
user32 = ctypes.windll.user32
|
||||||
self.screen_width, self.screen_height = user32.GetSystemMetrics(
|
self.screen_width, self.screen_height = user32.GetSystemMetrics(
|
||||||
@ -278,6 +285,12 @@ class Display:
|
|||||||
cv2.setWindowProperty(
|
cv2.setWindowProperty(
|
||||||
WINDOW_NAME, cv2.WND_PROP_FULLSCREEN, cv2.WINDOW_FULLSCREEN
|
WINDOW_NAME, cv2.WND_PROP_FULLSCREEN, cv2.WINDOW_FULLSCREEN
|
||||||
)
|
)
|
||||||
|
else:
|
||||||
|
cv2.namedWindow(
|
||||||
|
WINDOW_NAME,
|
||||||
|
cv2.WINDOW_GUI_NORMAL | cv2.WINDOW_FREERATIO | cv2.WINDOW_NORMAL,
|
||||||
|
)
|
||||||
|
cv2.resizeWindow(WINDOW_NAME, *resolution)
|
||||||
|
|
||||||
def resize_frame_to_screen(self, frame: np.ndarray):
|
def resize_frame_to_screen(self, frame: np.ndarray):
|
||||||
"""
|
"""
|
||||||
@ -318,6 +331,8 @@ class Display:
|
|||||||
self.current_presentation_index += 1
|
self.current_presentation_index += 1
|
||||||
self.state = State.PLAYING
|
self.state = State.PLAYING
|
||||||
self.handle_key()
|
self.handle_key()
|
||||||
|
if self.exit:
|
||||||
|
continue
|
||||||
self.show_video()
|
self.show_video()
|
||||||
self.show_info()
|
self.show_info()
|
||||||
|
|
||||||
@ -336,7 +351,7 @@ class Display:
|
|||||||
def show_info(self):
|
def show_info(self):
|
||||||
"""Shows updated information about presentations."""
|
"""Shows updated information about presentations."""
|
||||||
info = np.zeros((130, 420), np.uint8)
|
info = np.zeros((130, 420), np.uint8)
|
||||||
font_args = (cv2.FONT_HERSHEY_SIMPLEX, 0.7, 255)
|
font_args = (FONT_ARGS[0], 0.7, *FONT_ARGS[2:])
|
||||||
grid_x = [30, 230]
|
grid_x = [30, 230]
|
||||||
grid_y = [30, 70, 110]
|
grid_y = [30, 70, 110]
|
||||||
|
|
||||||
@ -368,7 +383,7 @@ class Display:
|
|||||||
*font_args,
|
*font_args,
|
||||||
)
|
)
|
||||||
|
|
||||||
cv2.imshow(f"{WINDOW_NAME}: Info", info)
|
cv2.imshow(WINDOW_INFO_NAME, info)
|
||||||
|
|
||||||
def handle_key(self):
|
def handle_key(self):
|
||||||
"""Handles key strokes."""
|
"""Handles key strokes."""
|
||||||
@ -461,8 +476,17 @@ def _list_scenes(folder) -> List[str]:
|
|||||||
is_flag=True,
|
is_flag=True,
|
||||||
help="Skip all slides, useful the test if slides are working.",
|
help="Skip all slides, useful the test if slides are working.",
|
||||||
)
|
)
|
||||||
|
@click.option(
|
||||||
|
"--resolution",
|
||||||
|
type=(int, int),
|
||||||
|
default=(1280, 720),
|
||||||
|
help="Window resolution used if fullscreen is not set. You may manually resize the window afterward.",
|
||||||
|
show_default=True,
|
||||||
|
)
|
||||||
@click.help_option("-h", "--help")
|
@click.help_option("-h", "--help")
|
||||||
def present(scenes, config_path, folder, start_paused, fullscreen, skip_all):
|
def present(
|
||||||
|
scenes, config_path, folder, start_paused, fullscreen, skip_all, resolution
|
||||||
|
):
|
||||||
"""Present the different scenes."""
|
"""Present the different scenes."""
|
||||||
|
|
||||||
if len(scenes) == 0:
|
if len(scenes) == 0:
|
||||||
@ -527,5 +551,6 @@ def present(scenes, config_path, folder, start_paused, fullscreen, skip_all):
|
|||||||
start_paused=start_paused,
|
start_paused=start_paused,
|
||||||
fullscreen=fullscreen,
|
fullscreen=fullscreen,
|
||||||
skip_all=skip_all,
|
skip_all=skip_all,
|
||||||
|
resolution=resolution,
|
||||||
)
|
)
|
||||||
display.run()
|
display.run()
|
||||||
|
@ -7,17 +7,32 @@ import numpy as np
|
|||||||
|
|
||||||
from .commons import config_options
|
from .commons import config_options
|
||||||
from .config import Config
|
from .config import Config
|
||||||
from .defaults import CONFIG_PATH
|
from .defaults import CONFIG_PATH, FONT_ARGS, PIXELS_PER_CHARACTER
|
||||||
|
|
||||||
|
WINDOW_NAME = "Manim Slides Configuration Wizard"
|
||||||
|
WINDOW_SIZE = (120, 620)
|
||||||
|
|
||||||
|
|
||||||
|
def center_text_horizontally(text, window_size, font_args) -> int:
|
||||||
|
"""Returns centered position for text to be displayed in current window."""
|
||||||
|
_, width = window_size
|
||||||
|
font, scale, _, thickness, _ = font_args
|
||||||
|
(size_in_pixels, _), _ = cv2.getTextSize(text, font, scale, thickness)
|
||||||
|
return (width - size_in_pixels) // 2
|
||||||
|
|
||||||
|
|
||||||
def prompt(question: str) -> int:
|
def prompt(question: str) -> int:
|
||||||
font_args = (cv2.FONT_HERSHEY_SIMPLEX, 0.7, 255)
|
"""Diplays some question in current window and waits for key press."""
|
||||||
display = np.zeros((130, 420), np.uint8)
|
display = np.zeros(WINDOW_SIZE, np.uint8)
|
||||||
|
|
||||||
cv2.putText(display, "* Manim Slides Wizard *", (70, 33), *font_args)
|
text = "* Manim Slides Wizard *"
|
||||||
cv2.putText(display, question, (30, 85), *font_args)
|
text_org = center_text_horizontally(text, WINDOW_SIZE, FONT_ARGS), 33
|
||||||
|
question_org = center_text_horizontally(question, WINDOW_SIZE, FONT_ARGS), 85
|
||||||
|
|
||||||
cv2.imshow("Manim Slides Configuration Wizard", display)
|
cv2.putText(display, "* Manim Slides Wizard *", text_org, *FONT_ARGS)
|
||||||
|
cv2.putText(display, question, question_org, *FONT_ARGS)
|
||||||
|
|
||||||
|
cv2.imshow(WINDOW_NAME, display)
|
||||||
return cv2.waitKeyEx(-1)
|
return cv2.waitKeyEx(-1)
|
||||||
|
|
||||||
|
|
||||||
@ -61,6 +76,11 @@ def _init(config_path, force, merge, skip_interactive=False):
|
|||||||
|
|
||||||
if not skip_interactive:
|
if not skip_interactive:
|
||||||
|
|
||||||
|
cv2.namedWindow(
|
||||||
|
WINDOW_NAME,
|
||||||
|
cv2.WINDOW_GUI_NORMAL | cv2.WINDOW_FREERATIO | cv2.WINDOW_AUTOSIZE,
|
||||||
|
)
|
||||||
|
|
||||||
prompt("Press any key to continue")
|
prompt("Press any key to continue")
|
||||||
|
|
||||||
for _, key in config:
|
for _, key in config:
|
||||||
@ -70,6 +90,6 @@ def _init(config_path, force, merge, skip_interactive=False):
|
|||||||
config = Config.parse_file(config_path).merge_with(config)
|
config = Config.parse_file(config_path).merge_with(config)
|
||||||
|
|
||||||
with open(config_path, "w") as config_file:
|
with open(config_path, "w") as config_file:
|
||||||
config_file.write(config.json(indent=4))
|
config_file.write(config.json(indent=2))
|
||||||
|
|
||||||
click.echo(f"Configuration file successfully save to `{config_path}`")
|
click.echo(f"Configuration file successfully save to `{config_path}`")
|
||||||
|
Reference in New Issue
Block a user