From 620bb30960f7d28c6153ffd3fd30fd90702e0dc4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9rome=20Eertmans?= Date: Fri, 16 Sep 2022 15:28:18 +0200 Subject: [PATCH] feat(ui): much cleaner UI (#17) --- manim_slides/__version__.py | 2 +- manim_slides/defaults.py | 4 ++++ manim_slides/present.py | 33 +++++++++++++++++++++++++++++---- manim_slides/wizard.py | 34 +++++++++++++++++++++++++++------- 4 files changed, 61 insertions(+), 12 deletions(-) diff --git a/manim_slides/__version__.py b/manim_slides/__version__.py index 0d337e8..ce1305b 100644 --- a/manim_slides/__version__.py +++ b/manim_slides/__version__.py @@ -1 +1 @@ -__version__ = "4.0.0rc1" +__version__ = "4.0.0" diff --git a/manim_slides/defaults.py b/manim_slides/defaults.py index f63a375..23689fc 100644 --- a/manim_slides/defaults.py +++ b/manim_slides/defaults.py @@ -1,5 +1,9 @@ import platform +import cv2 + +FONT_ARGS = (cv2.FONT_HERSHEY_SIMPLEX, 1, 255, 1, cv2.LINE_AA) +PIXELS_PER_CHARACTER = 20 FOLDER_PATH: str = "./slides" CONFIG_PATH: str = ".manim-slides.json" diff --git a/manim_slides/present.py b/manim_slides/present.py index 0197eb2..24a4053 100644 --- a/manim_slides/present.py +++ b/manim_slides/present.py @@ -17,9 +17,10 @@ from pydantic import ValidationError from .commons import config_path_option 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_INFO_NAME = f"{WINDOW_NAME}: Info" @unique @@ -251,6 +252,7 @@ class Display: start_paused=False, fullscreen=False, skip_all=False, + resolution=(1280, 720), ): self.presentations = presentations self.start_paused = start_paused @@ -267,6 +269,11 @@ class Display: self.lag = 0 self.last_time = now() + cv2.namedWindow( + WINDOW_INFO_NAME, + cv2.WINDOW_GUI_NORMAL | cv2.WINDOW_FREERATIO | cv2.WINDOW_AUTOSIZE, + ) + if self.is_windows: user32 = ctypes.windll.user32 self.screen_width, self.screen_height = user32.GetSystemMetrics( @@ -278,6 +285,12 @@ class Display: cv2.setWindowProperty( 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): """ @@ -318,6 +331,8 @@ class Display: self.current_presentation_index += 1 self.state = State.PLAYING self.handle_key() + if self.exit: + continue self.show_video() self.show_info() @@ -336,7 +351,7 @@ class Display: def show_info(self): """Shows updated information about presentations.""" 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_y = [30, 70, 110] @@ -368,7 +383,7 @@ class Display: *font_args, ) - cv2.imshow(f"{WINDOW_NAME}: Info", info) + cv2.imshow(WINDOW_INFO_NAME, info) def handle_key(self): """Handles key strokes.""" @@ -461,8 +476,17 @@ def _list_scenes(folder) -> List[str]: is_flag=True, 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") -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.""" if len(scenes) == 0: @@ -527,5 +551,6 @@ def present(scenes, config_path, folder, start_paused, fullscreen, skip_all): start_paused=start_paused, fullscreen=fullscreen, skip_all=skip_all, + resolution=resolution, ) display.run() diff --git a/manim_slides/wizard.py b/manim_slides/wizard.py index 962d6b1..f41f7b9 100644 --- a/manim_slides/wizard.py +++ b/manim_slides/wizard.py @@ -7,17 +7,32 @@ import numpy as np from .commons import config_options 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: - font_args = (cv2.FONT_HERSHEY_SIMPLEX, 0.7, 255) - display = np.zeros((130, 420), np.uint8) + """Diplays some question in current window and waits for key press.""" + display = np.zeros(WINDOW_SIZE, np.uint8) - cv2.putText(display, "* Manim Slides Wizard *", (70, 33), *font_args) - cv2.putText(display, question, (30, 85), *font_args) + text = "* Manim Slides Wizard *" + 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) @@ -61,6 +76,11 @@ def _init(config_path, force, merge, skip_interactive=False): if not skip_interactive: + cv2.namedWindow( + WINDOW_NAME, + cv2.WINDOW_GUI_NORMAL | cv2.WINDOW_FREERATIO | cv2.WINDOW_AUTOSIZE, + ) + prompt("Press any key to continue") 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) 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}`")