From 7a1652717931d49c112e8fe75919129b4906d9f4 Mon Sep 17 00:00:00 2001 From: frank Date: Wed, 14 Dec 2022 23:16:09 -0500 Subject: [PATCH] add rotate display; preserve fullscreen state when setting display surface --- pgfw/Configuration.py | 10 +++------ pgfw/Display.py | 50 ++++++++++++++++++++++++++++++++----------- pgfw/Game.py | 13 +++++++---- pgfw/Interpolator.py | 7 ++++++ 4 files changed, 56 insertions(+), 24 deletions(-) diff --git a/pgfw/Configuration.py b/pgfw/Configuration.py index 5364395..c7210ae 100644 --- a/pgfw/Configuration.py +++ b/pgfw/Configuration.py @@ -14,8 +14,7 @@ class Configuration(RawConfigParser): default_project_file_rel_path = "config" default_resource_paths = [".", "resource"] - def __init__(self, project_file_rel_path=None, resource_path=None, - type_declarations=None): + def __init__(self, project_file_rel_path=None, resource_path=None, type_declarations=None): RawConfigParser.__init__(self) self.project_file_rel_path = project_file_rel_path self.resource_path = resource_path @@ -48,8 +47,7 @@ class Configuration(RawConfigParser): set_option(section, "title", "", False) set_option(section, "classifiers", "", False) set_option(section, "resource-search-path", "./, resource/", False) - set_option(section, "installation-dir", "/usr/local/share/games/", - False) + set_option(section, "installation-dir", "/usr/local/share/games/", False) set_option(section, "changelog", "changelog", False) set_option(section, "description-file", "", False) set_option(section, "init-script", "", False) @@ -472,9 +470,7 @@ class TypeDeclarations(dict): additional_defaults = {} def __init__(self): - dict.__init__(self, {"bool": [], "int": [], "float": [], "path": [], - "list": [], "int-list": [], "float-list": [], - "path-list": []}) + dict.__init__(self, {"bool": [], "int": [], "float": [], "path": [], "list": [], "int-list": [], "float-list": [], "path-list": []}) self.add_chart(self.defaults) self.add_chart(self.additional_defaults) diff --git a/pgfw/Display.py b/pgfw/Display.py index cef09f7..f39218a 100644 --- a/pgfw/Display.py +++ b/pgfw/Display.py @@ -2,7 +2,7 @@ from os import environ from sys import maxsize, platform import pygame -from pygame import display, image, mouse +from pygame import image, mouse from pygame.locals import * from .GameChild import * @@ -49,28 +49,52 @@ class Display(GameChild): def fullscreen_requested(self): return not self.check_command_line(self.windowed_flag) and self.fullscreen_enabled - def set_screen(self, flags=0x0, dimensions=None, fs=False): - self.dimensions_changed = dimensions is not None + def set_screen(self, flags=0x0, dimensions=None, fs=None): + """ + Initialize the pygame display, passing along any flags, and assign the returned display surface to `self.screen`. If no + dimensions are passed, use the dimensions of the current screen surface if it exists, otherwise get dimensions from the + configuration. If `fs` is `None`, leave the fullscreen state as is, otherwise read it as a boolean and set fullscreen + accordingly. + + @param flags Flags from https://www.pygame.org/docs/ref/display.html#pygame.display.set_mode. To pass multiple flags, + join them with the OR operator. + @param dimensions Dimensions of the screen surface as (width, height) + @param fs Set to True or False or omit to keep current fullscreen state + """ + # Try to auto discover dimensions if not provided if dimensions is None: - if display.get_surface(): - dimensions = display.get_surface().get_size() + if pygame.display.get_surface(): + dimensions = pygame.display.get_surface().get_size() else: dimensions = self.get_configuration("display", "dimensions") + + if fs is None: + # Get the current fullscreen state + fs = bool(pygame.display.get_surface().get_flags() & pygame.FULLSCREEN) + + # Get a display surface with specified fullscreen state if fs: - self.screen = display.set_mode(dimensions, flags | -0x80000000) + self.screen = pygame.display.set_mode(dimensions, flags | pygame.FULLSCREEN) else: - self.screen = display.set_mode(dimensions, flags) - if self.dimensions_changed: - interpolator = self.get_game().interpolator - if interpolator.gui_enabled: - interpolator.gui.rearrange() + self.screen = pygame.display.set_mode(dimensions, flags) + + # Redraw the spline interpolator interface if enabled + if self.get_game().interpolator.gui_enabled: + self.get_game().interpolator.gui.rearrange() + + def rotate(self): + """ + Rotate the screen surface 90 degrees by resetting it with swapped W and H dimensions. + """ + current_width, current_height = self.get_display_surface().get_size() + self.set_screen(dimensions=(current_height, current_width)) def set_caption(self): - display.set_caption(self.caption) + pygame.display.set_caption(self.caption) def set_icon(self): if self.icon_path: - display.set_icon(image.load(self.icon_path).convert_alpha()) + pygame.display.set_icon(image.load(self.icon_path).convert_alpha()) def set_mouse_visibility(self, visibility=None): if visibility is None: diff --git a/pgfw/Game.py b/pgfw/Game.py index 4231fb0..7a7dbd5 100644 --- a/pgfw/Game.py +++ b/pgfw/Game.py @@ -41,21 +41,26 @@ class Game(Animation): self.delegate.enable() def set_configuration(self): - self.configuration = Configuration(self.config_rel_path, - self.resource_path, - self.type_declarations) + self.configuration = Configuration(self.config_rel_path, self.resource_path, self.type_declarations) def set_children(self): + """ + Create the child objects that encapsulate other parts of the framework. They're usually used as singletons or managers. Subscribe + to the pygame.QUIT event. + """ self.delegate = Delegate(self) self.subscribe(self.end, QUIT) self.subscribe(self.end) + self.interpolator = Interpolator(self) self.display = Display(self) self.mainloop = Mainloop(self) self.input = Input(self) self.audio = Audio(self) self.screen_grabber = ScreenGrabber(self) self.video_recorder = VideoRecorder(self) - self.interpolator = Interpolator(self) + + # Call this separately because it needs the display to be initialized previously + self.interpolator.init_gui() def frame(self): self.time_filter.update() diff --git a/pgfw/Interpolator.py b/pgfw/Interpolator.py index 0ce39e9..777bd6b 100644 --- a/pgfw/Interpolator.py +++ b/pgfw/Interpolator.py @@ -16,6 +16,13 @@ class Interpolator(list, GameChild): def __init__(self, parent): GameChild.__init__(self, parent) self.set_nodesets() + self.gui_enabled = False + + def init_gui(self): + """ + If the interpolator is requested on the command line, create a GUI object. This runs separately from `pgfw.Interpolator.__init__` because + the display is not available when the main `pgfw.Interpolator` is created by `pgfw.Game`. + """ self.gui_enabled = self.check_command_line("-interpolator") if self.gui_enabled: self.gui = GUI(self)