コード例 #1
0
    def test_add_window(self, _init_pygame, default_ui_manager):
        stack = UIWindowStack((800, 600))
        window = UIWindow(pygame.Rect(100, 100, 200, 200),
                          manager=default_ui_manager,
                          element_ids=[])
        stack.add_new_window(window)

        assert len(stack.stack) == 1
コード例 #2
0
ファイル: ui_manager.py プロジェクト: halfninja/pygame_gui
 def clear_and_reset(self):
     """
     Clear all existing windows, including the root window, which should get rid of all created UI elements.
     We then recreate the UIWindowStack and the root window.
     """
     self.ui_window_stack.clear()
     self.ui_window_stack = UIWindowStack(self.window_resolution)
     UIWindow(pygame.Rect((0, 0), self.window_resolution), self, ['root_window'])
コード例 #3
0
    def test_add_window(self, _init_pygame, default_ui_manager,
                        _display_surface_return_none):
        stack = UIWindowStack((800, 600), default_ui_manager.get_root_container())
        window = UIWindow(pygame.Rect(100, 100, 200, 200), window_display_title="Test Window",
                          manager=default_ui_manager, element_id='test_window')
        stack.add_new_window(window)

        assert len(stack.stack) == 1
コード例 #4
0
ファイル: ui_manager.py プロジェクト: halfninja/pygame_gui
    def __init__(self, window_resolution: Tuple[int, int], theme_path: str = None):
        self.window_resolution = window_resolution
        self.ui_theme = UIAppearanceTheme()
        if theme_path is not None:
            self.ui_theme.load_theme(theme_path)
        self.ui_group = pygame.sprite.LayeredUpdates()

        self.select_focused_element = None
        self.last_focused_vertical_scrollbar = None

        self.ui_window_stack = UIWindowStack(self.window_resolution)
        UIWindow(pygame.Rect((0, 0), self.window_resolution), self, ['root_window'])

        self.shadow_generator = ShadowGenerator()
コード例 #5
0
    def test_move_window_to_front(self, _init_pygame, default_ui_manager,
                                  _display_surface_return_none):
        stack = UIWindowStack((800, 600), default_ui_manager.get_root_container())
        window = UIWindow(pygame.Rect(100, 100, 200, 200), window_display_title="Test Window",
                          manager=default_ui_manager, element_id='test_window')
        window_2 = UIWindow(pygame.Rect(50, 50, 200, 200), window_display_title="Test Window",
                            manager=default_ui_manager, element_id='test_window')
        window_3 = UIWindow(pygame.Rect(0, 0, 200, 200), window_display_title="Test Window",
                            manager=default_ui_manager, element_id='test_window')
        stack.add_new_window(window)
        stack.add_new_window(window_2)
        stack.add_new_window(window_3)
        stack.move_window_to_front(window)
        stack.move_window_to_front(window_3)
        stack.move_window_to_front(window_2)

        assert stack.stack[0] == window
コード例 #6
0
    def test_move_window_to_front(self, _init_pygame, default_ui_manager):
        stack = UIWindowStack((800, 600))
        window = UIWindow(pygame.Rect(100, 100, 200, 200),
                          manager=default_ui_manager,
                          element_ids=[])
        window_2 = UIWindow(pygame.Rect(50, 50, 200, 200),
                            manager=default_ui_manager,
                            element_ids=[])
        window_3 = UIWindow(pygame.Rect(0, 0, 200, 200),
                            manager=default_ui_manager,
                            element_ids=[])
        stack.add_new_window(window)
        stack.add_new_window(window_2)
        stack.add_new_window(window_3)
        stack.move_window_to_front(window)
        stack.move_window_to_front(window_3)
        stack.move_window_to_front(window_2)

        assert stack.stack[0] == window
コード例 #7
0
    def test_remove_window(self, _init_pygame, default_ui_manager):
        stack = UIWindowStack((800, 600))
        window = UIWindow(pygame.Rect(100, 100, 200, 200),
                          manager=default_ui_manager,
                          element_ids=[])
        window_2 = UIWindow(pygame.Rect(50, 50, 200, 200),
                            manager=default_ui_manager,
                            element_ids=[])
        window_3 = UIWindow(pygame.Rect(0, 0, 200, 200),
                            manager=default_ui_manager,
                            element_ids=[])
        stack.add_new_window(window)
        stack.add_new_window(window_2)
        stack.add_new_window(window_3)
        stack.remove_window(window)
        stack.remove_window(window_2)
        stack.remove_window(window_3)

        assert len(stack.stack) == 0
コード例 #8
0
    def __init__(self,
                 window_resolution: Tuple[int, int],
                 theme_path: str = None,
                 enable_live_theme_updates=True):
        self.window_resolution = window_resolution
        self.ui_theme = UIAppearanceTheme()
        if theme_path is not None:
            self.ui_theme.load_theme(theme_path)
        self.ui_group = pygame.sprite.LayeredUpdates()

        self.select_focused_element = None
        self.last_focused_vertical_scrollbar = None

        self.ui_window_stack = UIWindowStack(self.window_resolution)
        UIWindow(pygame.Rect((0, 0), self.window_resolution), self,
                 ['root_window'])

        self.live_theme_updates = enable_live_theme_updates
        self.theme_update_acc = 0.0
        self.theme_update_check_interval = 1.0
コード例 #9
0
 def clear_and_reset(self):
     """
     Clear all existing windows and the root container, which should get rid of all created UI
     elements. We then recreate the UIWindowStack and the root container.
     """
     self.root_container.kill()
     # need to reset to None before recreating otherwise the old container will linger around.
     self.root_container = None
     self.root_container = UIContainer(pygame.Rect((0, 0), self.window_resolution),
                                       self, starting_height=1,
                                       container=None, parent_element=None,
                                       object_id='#root_container')
     self.ui_window_stack = UIWindowStack(self.window_resolution, self.root_container)
コード例 #10
0
ファイル: ui_manager.py プロジェクト: pepe1977/pygame_gui
    def __init__(self,
                 window_resolution: Tuple[int, int],
                 theme_path: str = None,
                 enable_live_theme_updates=True):

        self.window_resolution = window_resolution
        self.ui_theme = UIAppearanceTheme()
        if theme_path is not None:
            self.ui_theme.load_theme(theme_path)

        self.universal_empty_surface = pygame.Surface((0, 0),
                                                      flags=pygame.SRCALPHA,
                                                      depth=32)
        self.ui_group = pygame.sprite.LayeredUpdates()

        self.focused_element = None
        self.last_focused_vertical_scrollbar = None
        self.last_focused_horizontal_scrollbar = None
        self.root_container = None
        self.root_container = UIContainer(pygame.Rect((0, 0),
                                                      self.window_resolution),
                                          self,
                                          starting_height=1,
                                          container=None,
                                          parent_element=None,
                                          object_id='#root_container')

        self.ui_window_stack = UIWindowStack(self.window_resolution,
                                             self.root_container)

        self.live_theme_updates = enable_live_theme_updates
        self.theme_update_acc = 0.0
        self.theme_update_check_interval = 1.0

        self.mouse_double_click_time = 0.5
        self.mouse_position = (0, 0)
        self.mouse_pos_scale_factor = [1.0, 1.0]

        self.visual_debug_active = False

        self.resizing_window_cursors = None
        self._load_default_cursors()
        self.active_user_cursor = pygame.cursors.arrow
        self._active_cursor = self.active_user_cursor
コード例 #11
0
ファイル: ui_manager.py プロジェクト: halfninja/pygame_gui
class UIManager:
    """
    The UI Manager class helps keep track of all the moving parts in the pygame_gui system.

    Before doing anything else with pygame_gui create a UIManager and remember to update it every frame.
    """

    def __init__(self, window_resolution: Tuple[int, int], theme_path: str = None):
        self.window_resolution = window_resolution
        self.ui_theme = UIAppearanceTheme()
        if theme_path is not None:
            self.ui_theme.load_theme(theme_path)
        self.ui_group = pygame.sprite.LayeredUpdates()

        self.select_focused_element = None
        self.last_focused_vertical_scrollbar = None

        self.ui_window_stack = UIWindowStack(self.window_resolution)
        UIWindow(pygame.Rect((0, 0), self.window_resolution), self, ['root_window'])

        self.shadow_generator = ShadowGenerator()

    def get_theme(self) -> UIAppearanceTheme:
        """
        Gets the theme so the data in it can be accessed.
        :return: UIAppearanceTheme - the theme data used by this UIManager
        """
        return self.ui_theme

    def get_sprite_group(self) -> pygame.sprite.LayeredUpdates:
        """
        Gets the sprite group used by the entire UI to keep it in the correct order for drawing and processing input.
        :return : pygame.sprite.LayeredUpdates -
        """
        return self.ui_group

    def get_window_stack(self) -> UIWindowStack:
        """
        The UIWindowStack organises any windows in the UI Manager so that they are correctly sorted and move windows
        we interact with to the top of the stack.
        :return: UIWindowStack
        """
        return self.ui_window_stack

    def get_shadow(self, size: Tuple[int, int], shadow_width: int = 2) -> pygame.Surface:
        """
        Returns a 'shadow' surface scaled to the requested size.

        :param size: The size of the object we are shadowing + it's shadow.
        :param shadow_width: The width of the shadowed edge.
        :return: A shadow.
        """
        return self.shadow_generator.find_closest_shadow_scale_to_size(size, shadow_width)

    def set_window_resolution(self, window_resolution):
        self.window_resolution = window_resolution

    def clear_and_reset(self):
        """
        Clear all existing windows, including the root window, which should get rid of all created UI elements.
        We then recreate the UIWindowStack and the root window.
        """
        self.ui_window_stack.clear()
        self.ui_window_stack = UIWindowStack(self.window_resolution)
        UIWindow(pygame.Rect((0, 0), self.window_resolution), self, ['root_window'])

    def process_events(self, event: pygame.event.Event):
        """
        This is the top level method through which all input to UI elements is processed and reacted to.

        One of the key things it controls is the currently 'focused' or 'selected' element of which there
        can be only one at a time.

        :param event:  pygame.event.Event - the event to process.
        """
        event_handled = False
        window_sorting_event_handled = False
        sorted_layers = sorted(self.ui_group.layers(), reverse=True)
        for layer in sorted_layers:
            sprites_in_layer = self.ui_group.get_sprites_from_layer(layer)
            # a little bit of code to pop windows we start messing with to the front
            if not window_sorting_event_handled:
                windows_in_layer = [window for window in sprites_in_layer if (
                        'window' in window.element_ids[-1]) and (self.ui_window_stack.get_root_window() is not window)]
                for window in windows_in_layer:
                    if not window_sorting_event_handled:
                        window_sorting_event_handled = window.check_clicked_inside(event)
            if not event_handled:
                for ui_element in sprites_in_layer:
                    if not event_handled:
                        if event.type == pygame.MOUSEBUTTONDOWN:
                            if event.button == 1:
                                mouse_x, mouse_y = event.pos
                                if ui_element.rect.collidepoint(mouse_x, mouse_y):
                                    if ui_element is not self.select_focused_element:
                                        self.unselect_focus_element()
                                        self.select_focus_element(ui_element)

                        event_handled = ui_element.process_event(event)

    def update(self, time_delta: float):
        """
        From here all our UI elements are updated and it manages which element is currently 'hovered'; which means
        the mouse pointer is overlapping them.

        :param time_delta: The time passed since the last call to update, in seconds.
        """
        hover_handled = False
        sorted_layers = sorted(self.ui_group.layers(), reverse=True)
        for layer in sorted_layers:
            for ui_element in self.ui_group.get_sprites_from_layer(layer):
                element_handled_hover = ui_element.check_hover(time_delta, hover_handled)
                if element_handled_hover:
                    hover_handled = True

        self.ui_group.update(time_delta)

    def draw_ui(self, window_surface: pygame.Surface):
        """
        Draws all the UI elements on the screen. Generally you want this to be after the rest of your game sprites
        have been drawn.

        If you want to do something particularly unusual with drawing you may have to write your own UI manager.

        :param window_surface: The screen or window surface on which we are going to draw all of our UI Elements.

        """
        self.ui_group.draw(window_surface)

    def add_font_paths(self, font_name: str, regular_path: str, bold_path: str = None,
                       italic_path: str = None, bold_italic_path: str = None):
        """
        Add file paths for custom fonts you want to use in the UI. For each font name you add you can specify
        font files for different styles. Fonts with designed styles tend to render a lot better than fonts that are
        forced to make use of pygame's bold and italic styling effects, so if you plan to use bold and italic text
        at small sizes - find fonts with these styles available as separate files.

        The font name you specify here can be used to choose the font in the blocks of HTML-subset formatted text,
        available in some of the UI elements like the UITextBox.

        It is recommended that you also pre-load any fonts you use at an appropriate moment in your project
        rather than letting the library dynamically load them when they are required. That is because dynamic loading
        of large font files can cause UI elements with a lot of font usage to appear rather slowly as they are waiting
        for the fonts they need to load.

        :param font_name: The name of the font that will be used to reference it elsewhere in the GUI.
        :param regular_path: The path of the font file for this font with no styles applied.
        :param bold_path: The path of the font file for this font with just bold style applied.
        :param italic_path: The path of the font file for this font with just italic style applied.
        :param bold_italic_path: The path of the font file for this font with bold & italic style applied.

        """
        self.get_theme().get_font_dictionary().add_font_path(font_name,
                                                             regular_path,
                                                             bold_path,
                                                             italic_path,
                                                             bold_italic_path)

    def preload_fonts(self, font_list: List[Dict[str, Union[str, int, float]]]):
        """
        It's a good idea to pre-load the exact fonts your program uses during the loading phase of your program.
        By default the pygame_gui library will still work, but will spit out reminder warnings when you haven't
        done this. Loading fonts on the fly will slow down the apparent responsiveness when creating UI elements
        that use a lot of different fonts.

        To pre-load custom fonts, or to use custom fonts at all (i.e. ones that aren't the default 'fira_code' font)
        you must first add the paths to the files for those fonts, then load the specific fonts with a list of font
        descriptions in a dictionary form like so:

        code:`{'name': 'fira_code', 'point_size': 12, 'style': 'bold_italic'}`

        You can specify size either in pygame.Font point sizes with 'point_size', or in HTML style sizes with
        'html_size'. Style options are:

        - 'regular'
        - 'italic'
        - 'bold'
        - 'bold_italic'

        The name parameter here must match the one you used when you added the file paths.

        :param font_list: A list of font descriptions in dictionary format as described above.

        """
        for font in font_list:
            name = 'fira_code'
            bold = False
            italic = False
            size = 14
            if 'name' in font:
                name = font['name']
            if 'style' in font:
                if 'bold' in font['style']:
                    bold = True
                if 'italic' in font['style']:
                    italic = True
            if 'html_size' in font:
                size = self.ui_theme.get_font_dictionary().convert_html_size_to_point_size(font['html_size'])
            elif 'point_size' in font:
                size = font['point_size']

            self.ui_theme.get_font_dictionary().preload_font(size, name, bold, italic)

    def print_unused_fonts(self):
        """
        Helps you identify which pre-loaded fonts you are actually still using in your project after you've
        fiddled around with the text a lot by printing out a list of fonts that have not been used yet at the
        time this function is called.

        Of course if you don't run the code path in which a particular font is used before calling this function
        then it won't be of much use, so take it's results under advisement rather than as gospel.

        """
        self.ui_theme.get_font_dictionary().print_unused_loaded_fonts()

    def unselect_focus_element(self):
        """
        Unselect and clear the currently focused element.
        """
        if self.select_focused_element is not None:
            self.select_focused_element.unselect()
            self.select_focused_element = None

    def select_focus_element(self, ui_element: UIElement):
        """
        Set an element as the focused element.

        If the element is a scroll bar we also keep track of that.

        :param ui_element: The element to focus on.
        """
        if self.select_focused_element is None:
            self.select_focused_element = ui_element
            self.select_focused_element.select()

            if 'vertical_scroll_bar' in self.select_focused_element.element_ids:
                self.last_focused_vertical_scrollbar = self.select_focused_element

    def clear_last_focused_from_vert_scrollbar(self, vert_scrollbar):
        """
        Clears the last scrollbar that we used.

        :param vert_scrollbar: A scrollbar UIElement.
        """
        if vert_scrollbar is self.last_focused_vertical_scrollbar:
            self.last_focused_vertical_scrollbar = None

    def get_last_focused_vert_scrollbar(self):
        """
        Gets the last scrollbar that we used.

        :return: A UIElement.
        """
        return self.last_focused_vertical_scrollbar
コード例 #12
0
 def test_creation(self, _init_pygame, default_ui_manager,
                   _display_surface_return_none):
     UIWindowStack((800, 600), default_ui_manager.get_root_container())
コード例 #13
0
ファイル: ui_manager.py プロジェクト: glipR/pygame_gui
    def __init__(self,
                 window_resolution: Tuple[int, int],
                 theme_path: Union[str, PackageResource] = None,
                 enable_live_theme_updates: bool = True,
                 resource_loader: IResourceLoader = None):

        # Pygame compat
        try:
            pygame.MOUSEWHEEL
        except AttributeError:
            pygame.MOUSEWHEEL = -1

        # Threaded loading
        if resource_loader is None:
            auto_load = True
            self.resource_loader = BlockingThreadedResourceLoader()
        else:
            auto_load = False
            self.resource_loader = resource_loader

        self.window_resolution = window_resolution
        self.ui_theme = UIAppearanceTheme(self.resource_loader)
        if theme_path is not None:
            self.ui_theme.load_theme(theme_path)

        self.universal_empty_surface = pygame.surface.Surface(
            (0, 0), flags=pygame.SRCALPHA, depth=32)
        self.ui_group = LayeredGUIGroup()

        self.focused_set = None
        self.root_container = None
        self.root_container = UIContainer(pygame.Rect((0, 0),
                                                      self.window_resolution),
                                          self,
                                          starting_height=1,
                                          container=None,
                                          parent_element=None,
                                          object_id='#root_container')

        self.ui_window_stack = UIWindowStack(self.window_resolution,
                                             self.root_container)

        self.live_theme_updates = enable_live_theme_updates
        self.theme_update_acc = 0.0
        self.theme_update_check_interval = 1.0

        self.mouse_double_click_time = 0.5
        self.mouse_position = (0, 0)
        self.mouse_pos_scale_factor = [1.0, 1.0]

        self.visual_debug_active = False

        self.resizing_window_cursors = None
        self._load_default_cursors()
        self.active_user_cursor = pygame.cursors.arrow
        self._active_cursor = self.active_user_cursor

        if auto_load:
            self.resource_loader.start()
            # If we are using a blocking loader this will only return when loading is complete
            self.resource_loader.update()
コード例 #14
0
    def __init__(self,
                 window_resolution: Tuple[int, int],
                 theme_path: Union[str, PackageResource] = None,
                 enable_live_theme_updates: bool = True,
                 resource_loader: IResourceLoader = None,
                 starting_language: str = 'en',
                 translation_directory_paths: List[str] = None):

        # Translation stuff
        self._locale = starting_language
        root_path = os.path.abspath(os.path.dirname(os.path.dirname(__file__)))
        translations_path = os.path.normpath(
            os.path.join(root_path, 'pygame_gui/data/translations/'))
        i18n.set('file_format', 'json')
        i18n.load_path.append(translations_path)
        if translation_directory_paths is not None:
            for path in translation_directory_paths:
                # check this is a valid path
                i18n.load_path.append(path)

        i18n.set('locale', self._locale)

        # Threaded loading
        if resource_loader is None:
            auto_load = True
            self.resource_loader = BlockingThreadedResourceLoader()
        else:
            auto_load = False
            self.resource_loader = resource_loader

        self.window_resolution = window_resolution
        self.ui_theme = UIAppearanceTheme(self.resource_loader, self._locale)
        if theme_path is not None:
            self.ui_theme.load_theme(theme_path)

        self.universal_empty_surface = pygame.surface.Surface(
            (0, 0), flags=pygame.SRCALPHA, depth=32)
        self.ui_group = LayeredGUIGroup()

        self.focused_set = None
        self.root_container = None
        self.root_container = UIContainer(pygame.Rect((0, 0),
                                                      self.window_resolution),
                                          self,
                                          starting_height=1,
                                          container=None,
                                          parent_element=None,
                                          object_id='#root_container')

        self.ui_window_stack = UIWindowStack(self.window_resolution,
                                             self.root_container)

        self.live_theme_updates = enable_live_theme_updates
        self.theme_update_acc = 0.0
        self.theme_update_check_interval = 1.0

        self.mouse_double_click_time = 0.5
        self.mouse_position = (0, 0)
        self.mouse_pos_scale_factor = [1.0, 1.0]

        self.visual_debug_active = False

        self.resizing_window_cursors = None
        self._load_default_cursors()
        self.active_user_cursor = pygame.SYSTEM_CURSOR_ARROW
        self._active_cursor = self.active_user_cursor
        self.text_input_hovered = False

        if auto_load:
            self.resource_loader.start()
            # If we are using a blocking loader this will only return when loading is complete
            self.resource_loader.update()
コード例 #15
0
 def test_creation(self, _init_pygame):
     UIWindowStack((800, 600))