From 9db2a8185a10afc4c7f1f1ec19a9810d01f82db5 Mon Sep 17 00:00:00 2001 From: Dan Lawrence Date: Sun, 29 Dec 2024 11:11:30 +0000 Subject: [PATCH] Add test 'border_overlap' theming to somewhat control overlapping of curved shapes and their borders. --- .../core/drawable_shapes/ellipse_drawable_shape.py | 11 +++++++---- .../drawable_shapes/rounded_rect_drawable_shape.py | 10 +++++++--- pygame_gui/core/ui_element.py | 5 +++++ pygame_gui/elements/ui_2d_slider.py | 4 +++- pygame_gui/elements/ui_button.py | 4 +++- pygame_gui/elements/ui_drop_down_menu.py | 7 +++++-- pygame_gui/elements/ui_form.py | 8 ++++++-- pygame_gui/elements/ui_horizontal_scroll_bar.py | 4 +++- pygame_gui/elements/ui_horizontal_slider.py | 4 +++- pygame_gui/elements/ui_label.py | 3 ++- pygame_gui/elements/ui_panel.py | 4 +++- pygame_gui/elements/ui_selection_list.py | 4 +++- pygame_gui/elements/ui_status_bar.py | 4 +++- pygame_gui/elements/ui_text_box.py | 4 +++- pygame_gui/elements/ui_text_entry_line.py | 4 +++- pygame_gui/elements/ui_vertical_scroll_bar.py | 4 +++- pygame_gui/elements/ui_window.py | 4 +++- 17 files changed, 65 insertions(+), 23 deletions(-) diff --git a/pygame_gui/core/drawable_shapes/ellipse_drawable_shape.py b/pygame_gui/core/drawable_shapes/ellipse_drawable_shape.py index 3b808a43..ae46bb0a 100644 --- a/pygame_gui/core/drawable_shapes/ellipse_drawable_shape.py +++ b/pygame_gui/core/drawable_shapes/ellipse_drawable_shape.py @@ -172,6 +172,9 @@ def redraw_state(self, state_str: str, add_text: bool = True): text_colour_state_str = state_str + '_text' text_shadow_colour_state_str = state_str + '_text_shadow' image_state_str = state_str + '_image' + border_overlap = 0 + if 'border_overlap' in self.theming: + border_overlap = self.theming['border_overlap'] found_shape = None shape_id = None @@ -214,25 +217,25 @@ def redraw_state(self, state_str: str, add_text: bool = True): if isinstance(self.theming[border_colour_state_str], ColourGradient): shape_surface = self.clear_and_create_shape_surface(bab_surface, self.border_rect, - 0, aa_amount=aa_amount, + border_overlap, aa_amount=aa_amount, clear=False) self.theming[border_colour_state_str].apply_gradient_to_surface(shape_surface) else: shape_surface = self.clear_and_create_shape_surface(bab_surface, self.border_rect, - 0, aa_amount=aa_amount, + border_overlap, aa_amount=aa_amount, clear=False) apply_colour_to_surface(self.theming[border_colour_state_str], shape_surface) basic_blit(bab_surface, shape_surface, self.border_rect) if isinstance(self.theming[bg_colour_state_str], ColourGradient): shape_surface = self.clear_and_create_shape_surface(bab_surface, - self.background_rect, 1, + self.background_rect, border_overlap, aa_amount=aa_amount) self.theming[bg_colour_state_str].apply_gradient_to_surface(shape_surface) else: shape_surface = self.clear_and_create_shape_surface(bab_surface, - self.background_rect, 1, + self.background_rect, border_overlap, aa_amount=aa_amount) apply_colour_to_surface(self.theming[bg_colour_state_str], shape_surface) diff --git a/pygame_gui/core/drawable_shapes/rounded_rect_drawable_shape.py b/pygame_gui/core/drawable_shapes/rounded_rect_drawable_shape.py index a8e5a259..622a23db 100644 --- a/pygame_gui/core/drawable_shapes/rounded_rect_drawable_shape.py +++ b/pygame_gui/core/drawable_shapes/rounded_rect_drawable_shape.py @@ -330,6 +330,9 @@ def redraw_state(self, state_str: str, add_text: bool = True): text_shadow_colour_state_str = state_str + '_text_shadow' bg_col = self.theming[state_str + '_bg'] border_col = self.theming[state_str + '_border'] + border_overlap = 0 + if 'border_overlap' in self.theming: + border_overlap = self.theming['border_overlap'] found_shape = None shape_id = None @@ -378,7 +381,7 @@ def redraw_state(self, state_str: str, add_text: bool = True): if self.border_width > 0: shape_surface = self.clear_and_create_shape_surface(bab_surface, self.border_rect, - 0, + border_overlap, self.shape_corner_radius, aa_amount=aa_amount, clear=False) @@ -391,7 +394,7 @@ def redraw_state(self, state_str: str, add_text: bool = True): shape_surface = self.clear_and_create_shape_surface(bab_surface, self.background_rect, - 0, + border_overlap, bg_corner_radii, aa_amount=aa_amount) @@ -545,7 +548,8 @@ def create_subtract_surface(self, self.temp_subtractive_shape = pygame.surface.Surface(subtract_size, flags=pygame.SRCALPHA, depth=32) - self.temp_subtractive_shape.fill(pygame.Color('#00000000')) + clear_colour = '#00000000' + self.temp_subtractive_shape.fill(pygame.Color(clear_colour)) RoundedRectangleShape.draw_colourless_rounded_rectangle(corner_radii, self.temp_subtractive_shape, int(aa_amount / 2)) diff --git a/pygame_gui/core/ui_element.py b/pygame_gui/core/ui_element.py index 1a2b0fb5..fbde28d4 100644 --- a/pygame_gui/core/ui_element.py +++ b/pygame_gui/core/ui_element.py @@ -79,6 +79,7 @@ def __init__(self, relative_rect: RectLike, # Themed parameters self.shadow_width = None # type: Union[None, int] self.border_width = None # type: Union[None, int] + self.border_overlap = None # type: Union[None, int] self.shape_corner_radius: Optional[List[int]] = None self.tool_tip_text = None @@ -113,6 +114,7 @@ def __init__(self, relative_rect: RectLike, # need to expand our rect by the shadow size and adjust position by it as well. self._check_shape_theming_changed(defaults={'border_width': 1, 'shadow_width': 2, + 'border_overlap': 1, 'shape_corner_radius': [2, 2, 2, 2]}) self.relative_rect.width += self.shadow_width * 2 self.relative_rect.height += self.shadow_width * 2 @@ -1308,6 +1310,9 @@ def _check_shape_theming_changed(self, defaults: Dict[str, Any]) -> bool: if self._check_misc_theme_data_changed('shadow_width', defaults['shadow_width'], int): has_any_changed = True + if self._check_misc_theme_data_changed('border_overlap', defaults['border_overlap'], int): + has_any_changed = True + # corner radius temp_corner_radius = [0, 0, 0, 0] try: diff --git a/pygame_gui/elements/ui_2d_slider.py b/pygame_gui/elements/ui_2d_slider.py index 56a3c3fd..b287e7f3 100644 --- a/pygame_gui/elements/ui_2d_slider.py +++ b/pygame_gui/elements/ui_2d_slider.py @@ -156,7 +156,8 @@ def rebuild(self): "disabled_border": self.disabled_border_colour, "border_width": self.border_width, "shadow_width": self.shadow_width, - "shape_corner_radius": self.shape_corner_radius} + "shape_corner_radius": self.shape_corner_radius, + 'border_overlap': self.border_overlap} if self.shape == "rectangle": self.drawable_shape = RectDrawableShape(self.rect, theming_parameters, @@ -355,6 +356,7 @@ def rebuild_from_changed_theme_data(self) -> None: if self._check_shape_theming_changed(defaults={"border_width": 1, "shadow_width": 2, + "border_overlap": 1, "shape_corner_radius": [2, 2, 2, 2]}): has_any_changed = True diff --git a/pygame_gui/elements/ui_button.py b/pygame_gui/elements/ui_button.py index 12f2045b..a8d96c42 100644 --- a/pygame_gui/elements/ui_button.py +++ b/pygame_gui/elements/ui_button.py @@ -623,6 +623,7 @@ def rebuild_from_changed_theme_data(self): if self._check_shape_theming_changed(defaults={'border_width': 1, 'shadow_width': 2, + 'border_overlap': 1, 'shape_corner_radius': [2, 2, 2, 2]}): has_any_changed = True @@ -747,7 +748,8 @@ def rebuild(self): 'text_horiz_alignment_method': self.text_horiz_alignment_method, 'text_vert_alignment_padding': self.text_vert_alignment_padding, 'shape_corner_radius': self.shape_corner_radius, - 'transitions': self.state_transitions} + 'transitions': self.state_transitions, + 'border_overlap': self.border_overlap} drawable_shape_rect = self.rect.copy() if self.dynamic_width: diff --git a/pygame_gui/elements/ui_drop_down_menu.py b/pygame_gui/elements/ui_drop_down_menu.py index d78490d2..6a89d68c 100644 --- a/pygame_gui/elements/ui_drop_down_menu.py +++ b/pygame_gui/elements/ui_drop_down_menu.py @@ -84,7 +84,8 @@ def rebuild(self): 'normal_border': self.drop_down_menu_ui.border_colour, 'border_width': self.drop_down_menu_ui.border_width, 'shadow_width': self.drop_down_menu_ui.shadow_width, - 'shape_corner_radius': self.drop_down_menu_ui.shape_corner_radius} + 'shape_corner_radius': self.drop_down_menu_ui.shape_corner_radius, + 'border_overlap': self.drop_down_menu_ui.border_overlap} shape_rect = self.drop_down_menu_ui.relative_rect if self.drop_down_menu_ui.shape == 'rectangle': @@ -457,7 +458,8 @@ def rebuild(self): 'disabled_border': self.drop_down_menu_ui.disabled_border_colour, 'border_width': self.drop_down_menu_ui.border_width, 'shadow_width': self.drop_down_menu_ui.shadow_width, - 'shape_corner_radius': self.drop_down_menu_ui.shape_corner_radius} + 'shape_corner_radius': self.drop_down_menu_ui.shape_corner_radius, + 'border_overlap': self.drop_down_menu_ui.border_overlap} if self.drop_down_menu_ui.shape == 'rectangle': self.drop_down_menu_ui.drawable_shape = RectDrawableShape(self.drop_down_menu_ui.rect, @@ -888,6 +890,7 @@ def rebuild_from_changed_theme_data(self): if self._check_shape_theming_changed(defaults={'border_width': 1, 'shadow_width': 2, + 'border_overlap': 1, 'shape_corner_radius': [2, 2, 2, 2]}): has_any_changed = True diff --git a/pygame_gui/elements/ui_form.py b/pygame_gui/elements/ui_form.py index e5468cd3..08875553 100644 --- a/pygame_gui/elements/ui_form.py +++ b/pygame_gui/elements/ui_form.py @@ -213,6 +213,7 @@ def rebuild_from_changed_theme_data(self) -> None: if self._check_shape_theming_changed(defaults={"border_width": 1, "shadow_width": 2, + 'border_overlap': 1, "shape_corner_radius": 2}): has_any_changed = True @@ -301,7 +302,8 @@ def rebuild(self) -> None: "normal_image": self.background_image, "border_width": self.border_width, "shadow_width": self.shadow_width, - "shape_corner_radius": self.shape_corner_radius} + "shape_corner_radius": self.shape_corner_radius, + 'border_overlap': self.border_overlap} if self.shape == "rectangle": self.drawable_shape = RectDrawableShape(self.rect, theming_parameters, @@ -784,6 +786,7 @@ def rebuild_from_changed_theme_data(self) -> None: if self._check_shape_theming_changed(defaults={"border_width": 1, "shadow_width": 2, + 'border_overlap': 1, "shape_corner_radius": 2}): has_any_changed = True @@ -1025,7 +1028,8 @@ def rebuild(self) -> None: "normal_image": self.background_image, "border_width": self.border_width, "shadow_width": self.shadow_width, - "shape_corner_radius": self.shape_corner_radius} + "shape_corner_radius": self.shape_corner_radius, + 'border_overlap': self.border_overlap} if self.shape == "rectangle": self.drawable_shape = RectDrawableShape(self.rect, theming_parameters, diff --git a/pygame_gui/elements/ui_horizontal_scroll_bar.py b/pygame_gui/elements/ui_horizontal_scroll_bar.py index 35ef557c..65effdbd 100644 --- a/pygame_gui/elements/ui_horizontal_scroll_bar.py +++ b/pygame_gui/elements/ui_horizontal_scroll_bar.py @@ -151,7 +151,8 @@ def rebuild(self): 'disabled_border': self.disabled_border_colour, 'border_width': self.border_width, 'shadow_width': self.shadow_width, - 'shape_corner_radius': self.shape_corner_radius} + 'shape_corner_radius': self.shape_corner_radius, + 'border_overlap': self.border_overlap} if self.shape == 'rectangle': self.drawable_shape = RectDrawableShape(self.rect, theming_parameters, @@ -472,6 +473,7 @@ def rebuild_from_changed_theme_data(self): if self._check_shape_theming_changed(defaults={'border_width': 1, 'shadow_width': 2, + 'border_overlap': 1, 'shape_corner_radius': [2, 2, 2, 2]}): has_any_changed = True diff --git a/pygame_gui/elements/ui_horizontal_slider.py b/pygame_gui/elements/ui_horizontal_slider.py index 9487741c..aa40a712 100644 --- a/pygame_gui/elements/ui_horizontal_slider.py +++ b/pygame_gui/elements/ui_horizontal_slider.py @@ -154,7 +154,8 @@ def rebuild(self): 'disabled_border': self.disabled_border_colour, 'border_width': self.border_width, 'shadow_width': self.shadow_width, - 'shape_corner_radius': self.shape_corner_radius} + 'shape_corner_radius': self.shape_corner_radius, + 'border_overlap': self.border_overlap} if self.shape == 'rectangle': self.drawable_shape = RectDrawableShape(self.rect, theming_parameters, @@ -414,6 +415,7 @@ def rebuild_from_changed_theme_data(self): if self._check_shape_theming_changed(defaults={'border_width': 1, 'shadow_width': 2, + 'border_overlap': 1, 'shape_corner_radius': [2, 2, 2, 2]}): has_any_changed = True diff --git a/pygame_gui/elements/ui_label.py b/pygame_gui/elements/ui_label.py index 245646b3..24fc11b9 100644 --- a/pygame_gui/elements/ui_label.py +++ b/pygame_gui/elements/ui_label.py @@ -154,7 +154,8 @@ def rebuild(self): 'text_horiz_alignment': self.text_horiz_alignment, 'text_vert_alignment': self.text_vert_alignment, 'text_horiz_alignment_padding': self.text_horiz_alignment_padding, - 'text_vert_alignment_padding': self.text_vert_alignment_padding} + 'text_vert_alignment_padding': self.text_vert_alignment_padding, + 'border_overlap': self.border_overlap} drawable_shape_rect = self.rect.copy() if self.dynamic_width: diff --git a/pygame_gui/elements/ui_panel.py b/pygame_gui/elements/ui_panel.py index 4f98b5c0..5d5a8618 100644 --- a/pygame_gui/elements/ui_panel.py +++ b/pygame_gui/elements/ui_panel.py @@ -242,6 +242,7 @@ def rebuild_from_changed_theme_data(self): if self._check_shape_theming_changed(defaults={'border_width': 1, 'shadow_width': 2, + 'border_overlap': 1, 'shape_corner_radius': [2, 2, 2, 2]}): has_any_changed = True @@ -258,7 +259,8 @@ def rebuild(self): 'normal_image': self.background_image, 'border_width': self.border_width, 'shadow_width': self.shadow_width, - 'shape_corner_radius': self.shape_corner_radius} + 'shape_corner_radius': self.shape_corner_radius, + 'border_overlap': self.border_overlap} if self.shape == 'rectangle': self.drawable_shape = RectDrawableShape(self.rect, theming_parameters, diff --git a/pygame_gui/elements/ui_selection_list.py b/pygame_gui/elements/ui_selection_list.py index 350aadd9..f89c7183 100644 --- a/pygame_gui/elements/ui_selection_list.py +++ b/pygame_gui/elements/ui_selection_list.py @@ -615,6 +615,7 @@ def rebuild_from_changed_theme_data(self): if self._check_shape_theming_changed(defaults={'border_width': 1, 'shadow_width': 2, + 'border_overlap': 1, 'shape_corner_radius': [2, 2, 2, 2]}): has_any_changed = True @@ -641,7 +642,8 @@ def rebuild(self): 'normal_image': self.background_image, 'border_width': self.border_width, 'shadow_width': self.shadow_width, - 'shape_corner_radius': self.shape_corner_radius} + 'shape_corner_radius': self.shape_corner_radius, + 'border_overlap': self.border_overlap} if self.shape == 'rectangle': self.drawable_shape = RectDrawableShape(self.rect, theming_parameters, diff --git a/pygame_gui/elements/ui_status_bar.py b/pygame_gui/elements/ui_status_bar.py index 2dac14f2..904c33c3 100644 --- a/pygame_gui/elements/ui_status_bar.py +++ b/pygame_gui/elements/ui_status_bar.py @@ -181,7 +181,8 @@ def redraw(self): 'shape_corner_radius': self.shape_corner_radius, 'filled_bar': self.bar_filled_colour, 'filled_bar_width_percentage': self.percent_full, - 'follow_sprite_offset': self.follow_sprite_offset} + 'follow_sprite_offset': self.follow_sprite_offset, + 'border_overlap': self.border_overlap} text = self.status_text() if text: @@ -232,6 +233,7 @@ def rebuild_from_changed_theme_data(self): if self._check_shape_theming_changed(defaults={'border_width': 1, 'shadow_width': 2, + 'border_overlap': 1, 'shape_corner_radius': [2, 2, 2, 2]}): has_any_changed = True diff --git a/pygame_gui/elements/ui_text_box.py b/pygame_gui/elements/ui_text_box.py index 421056c6..9b07b2e7 100644 --- a/pygame_gui/elements/ui_text_box.py +++ b/pygame_gui/elements/ui_text_box.py @@ -360,7 +360,8 @@ def rebuild(self): 'border_width': self.border_width, 'shadow_width': self.shadow_width, 'shape_corner_radius': self.shape_corner_radius, - 'text_cursor_colour': self.text_cursor_colour} + 'text_cursor_colour': self.text_cursor_colour, + 'border_overlap': self.border_overlap} if self.shape == 'rectangle': self.drawable_shape = RectDrawableShape(self.rect, theming_parameters, @@ -1055,6 +1056,7 @@ def rebuild_from_changed_theme_data(self): if self._check_shape_theming_changed(defaults={'border_width': 1, 'shadow_width': 2, + 'border_overlap': 1, 'shape_corner_radius': [2, 2, 2, 2]}): has_any_changed = True diff --git a/pygame_gui/elements/ui_text_entry_line.py b/pygame_gui/elements/ui_text_entry_line.py index 5817de84..6004e306 100644 --- a/pygame_gui/elements/ui_text_entry_line.py +++ b/pygame_gui/elements/ui_text_entry_line.py @@ -237,7 +237,8 @@ def rebuild(self): 'text_vert_alignment': 'centre', 'text_horiz_alignment_padding': self.padding[0], 'text_vert_alignment_padding': self.padding[1], - 'shape_corner_radius': self.shape_corner_radius} + 'shape_corner_radius': self.shape_corner_radius, + 'border_overlap': self.border_overlap} if self.shape == 'rectangle': self.drawable_shape = RectDrawableShape(self.rect, theming_parameters, @@ -1111,6 +1112,7 @@ def rebuild_from_changed_theme_data(self): if self._check_shape_theming_changed(defaults={'border_width': 1, 'shadow_width': 2, + 'border_overlap': 1, 'shape_corner_radius': [2, 2, 2, 2]}): has_any_changed = True diff --git a/pygame_gui/elements/ui_vertical_scroll_bar.py b/pygame_gui/elements/ui_vertical_scroll_bar.py index 8289fef8..9de3a521 100644 --- a/pygame_gui/elements/ui_vertical_scroll_bar.py +++ b/pygame_gui/elements/ui_vertical_scroll_bar.py @@ -147,7 +147,8 @@ def rebuild(self): 'disabled_border': self.disabled_border_colour, 'border_width': self.border_width, 'shadow_width': self.shadow_width, - 'shape_corner_radius': self.shape_corner_radius} + 'shape_corner_radius': self.shape_corner_radius, + 'border_overlap': self.border_overlap} if self.shape == 'rectangle': self.drawable_shape = RectDrawableShape(self.rect, theming_parameters, @@ -468,6 +469,7 @@ def rebuild_from_changed_theme_data(self): if self._check_shape_theming_changed(defaults={'border_width': 1, 'shadow_width': 2, + 'border_overlap': 1, 'shape_corner_radius': [2, 2, 2, 2]}): has_any_changed = True diff --git a/pygame_gui/elements/ui_window.py b/pygame_gui/elements/ui_window.py index e0a8e905..a3ce64f6 100644 --- a/pygame_gui/elements/ui_window.py +++ b/pygame_gui/elements/ui_window.py @@ -516,7 +516,8 @@ def rebuild(self): 'normal_border': self.border_colour, 'border_width': self.border_width, 'shadow_width': self.shadow_width, - 'shape_corner_radius': self.shape_corner_radius} + 'shape_corner_radius': self.shape_corner_radius, + 'border_overlap': self.border_overlap} if self.shape == 'rectangle': self.drawable_shape = RectDrawableShape(self.rect, theming_parameters, @@ -616,6 +617,7 @@ def rebuild_from_changed_theme_data(self): if self._check_shape_theming_changed(defaults={'border_width': 1, 'shadow_width': 15, + 'border_overlap': 1, 'shape_corner_radius': [2, 2, 2, 2]}): has_any_changed = True