batframework 1.0.10__py3-none-any.whl → 2.0.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (81) hide show
  1. batFramework/__init__.py +84 -52
  2. batFramework/action.py +280 -252
  3. batFramework/actionContainer.py +105 -38
  4. batFramework/animatedSprite.py +81 -117
  5. batFramework/animation.py +91 -0
  6. batFramework/audioManager.py +156 -85
  7. batFramework/baseScene.py +249 -0
  8. batFramework/camera.py +245 -123
  9. batFramework/constants.py +57 -75
  10. batFramework/cutscene.py +239 -119
  11. batFramework/cutsceneManager.py +34 -0
  12. batFramework/drawable.py +107 -0
  13. batFramework/dynamicEntity.py +30 -23
  14. batFramework/easingController.py +58 -0
  15. batFramework/entity.py +130 -123
  16. batFramework/enums.py +171 -0
  17. batFramework/fontManager.py +65 -0
  18. batFramework/gui/__init__.py +28 -14
  19. batFramework/gui/animatedLabel.py +90 -0
  20. batFramework/gui/button.py +18 -84
  21. batFramework/gui/clickableWidget.py +244 -0
  22. batFramework/gui/collapseContainer.py +98 -0
  23. batFramework/gui/constraints/__init__.py +1 -0
  24. batFramework/gui/constraints/constraints.py +1066 -0
  25. batFramework/gui/container.py +220 -49
  26. batFramework/gui/debugger.py +140 -47
  27. batFramework/gui/draggableWidget.py +63 -0
  28. batFramework/gui/image.py +61 -23
  29. batFramework/gui/indicator.py +116 -40
  30. batFramework/gui/interactiveWidget.py +243 -22
  31. batFramework/gui/label.py +147 -110
  32. batFramework/gui/layout.py +442 -81
  33. batFramework/gui/meter.py +155 -0
  34. batFramework/gui/radioButton.py +43 -0
  35. batFramework/gui/root.py +228 -60
  36. batFramework/gui/scrollingContainer.py +282 -0
  37. batFramework/gui/selector.py +232 -0
  38. batFramework/gui/shape.py +286 -86
  39. batFramework/gui/slider.py +353 -0
  40. batFramework/gui/style.py +10 -0
  41. batFramework/gui/styleManager.py +49 -0
  42. batFramework/gui/syncedVar.py +43 -0
  43. batFramework/gui/textInput.py +331 -0
  44. batFramework/gui/textWidget.py +308 -0
  45. batFramework/gui/toggle.py +140 -62
  46. batFramework/gui/tooltip.py +35 -0
  47. batFramework/gui/widget.py +546 -307
  48. batFramework/manager.py +131 -50
  49. batFramework/particle.py +118 -0
  50. batFramework/propertyEaser.py +79 -0
  51. batFramework/renderGroup.py +34 -0
  52. batFramework/resourceManager.py +130 -0
  53. batFramework/scene.py +31 -226
  54. batFramework/sceneLayer.py +134 -0
  55. batFramework/sceneManager.py +200 -165
  56. batFramework/scrollingSprite.py +115 -0
  57. batFramework/sprite.py +46 -0
  58. batFramework/stateMachine.py +49 -51
  59. batFramework/templates/__init__.py +2 -0
  60. batFramework/templates/character.py +15 -0
  61. batFramework/templates/controller.py +158 -0
  62. batFramework/templates/stateMachine.py +39 -0
  63. batFramework/tileset.py +46 -0
  64. batFramework/timeManager.py +213 -0
  65. batFramework/transition.py +162 -157
  66. batFramework/triggerZone.py +22 -22
  67. batFramework/utils.py +306 -184
  68. {batframework-1.0.10.dist-info → batframework-2.0.0.dist-info}/LICENSE +1 -1
  69. {batframework-1.0.10.dist-info → batframework-2.0.0.dist-info}/METADATA +3 -4
  70. batframework-2.0.0.dist-info/RECORD +72 -0
  71. batFramework/cutsceneBlocks.py +0 -176
  72. batFramework/debugger.py +0 -48
  73. batFramework/easing.py +0 -71
  74. batFramework/gui/constraints.py +0 -204
  75. batFramework/gui/frame.py +0 -19
  76. batFramework/particles.py +0 -77
  77. batFramework/time.py +0 -75
  78. batFramework/transitionManager.py +0 -0
  79. batframework-1.0.10.dist-info/RECORD +0 -43
  80. {batframework-1.0.10.dist-info → batframework-2.0.0.dist-info}/WHEEL +0 -0
  81. {batframework-1.0.10.dist-info → batframework-2.0.0.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,232 @@
1
+ import batFramework as bf
2
+ import pygame
3
+ from typing import Self, Callable, Any
4
+ from .button import Button
5
+ from .indicator import ArrowIndicator
6
+ from .clickableWidget import ClickableWidget
7
+ from .widget import Widget
8
+ from .syncedVar import SyncedVar
9
+
10
+ class MyArrow(ArrowIndicator, ClickableWidget):
11
+ def top_at(self, x, y):
12
+ return Widget.top_at(self, x, y)
13
+
14
+ def get_focus(self):
15
+ return self.parent.get_focus()
16
+
17
+ def __str__(self):
18
+ return "SelectorArrow"
19
+
20
+ class Selector(Button):
21
+ def __init__(self, options: list[Any] = None, default_value_index: int = None, display_func: Callable[[Any], str] = None,synced_var: SyncedVar = None):
22
+ self.allow_cycle = False
23
+ self.current_index = default_value_index
24
+ self.on_modify_callback: Callable[[Any, int], Any] = None
25
+ self.options = options if options else []
26
+ self.display_func = display_func or str
27
+ self.gap: int = 2
28
+ self.synced_var = synced_var if synced_var is not None else SyncedVar(None)
29
+ display_text = ""
30
+
31
+ super().__init__("")
32
+
33
+ self.left_indicator: MyArrow = (MyArrow(bf.direction.LEFT)
34
+ .set_color((0, 0, 0, 0)).set_arrow_color(self.text_widget.text_color)
35
+ .set_callback(lambda: self.set_by_index(self.get_current_index() - 1))
36
+ )
37
+
38
+ self.right_indicator: MyArrow = (MyArrow(bf.direction.RIGHT)
39
+ .set_color((0, 0, 0, 0)).set_arrow_color(self.text_widget.text_color)
40
+ .set_callback(lambda: self.set_by_index(self.get_current_index() + 1))
41
+ )
42
+
43
+ self.add(self.left_indicator, self.right_indicator)
44
+ self.set_clip_children(False)
45
+
46
+ if self.options and default_value_index is None and synced_var is not None:
47
+ display_text = display_func(synced_var.value)
48
+ default_value_index = self.options.index(synced_var.value)
49
+ elif self.options:
50
+ if default_value_index is None:
51
+ default_value_index= 0
52
+ display_text = self.display_func(self.options[default_value_index])
53
+ self.current_index = default_value_index
54
+ self.set_text(display_text)
55
+
56
+ def __str__(self):
57
+ return f"Selector[{self.options[self.current_index] if self.options else ''}]"
58
+
59
+ def _update_text_widget(self):
60
+ if self.options:
61
+ display_text = self.display_func(self.options[self.current_index])
62
+ self.text_widget.set_text(display_text)
63
+ else:
64
+ self.text_widget.set_text("")
65
+
66
+ def _on_synced_var_update(self, value: Any):
67
+ if value in self.options:
68
+ self.current_index = self.options.index(value)
69
+ self._update_text_widget()
70
+ self._update_arrow_states()
71
+ if self.on_modify_callback:
72
+ self.on_modify_callback(value, self.current_index)
73
+
74
+ def _update_arrow_states(self):
75
+ if not self.allow_cycle:
76
+ if self.current_index <= 0:
77
+ self.left_indicator.disable()
78
+ else:
79
+ self.left_indicator.enable()
80
+
81
+ if self.current_index >= len(self.options) - 1:
82
+ self.right_indicator.disable()
83
+ else:
84
+ self.right_indicator.enable()
85
+
86
+ def set_gap(self, value: int) -> Self:
87
+ self.gap = value
88
+ self.dirty_shape = True
89
+ return self
90
+
91
+ def set_arrow_color(self, color) -> Self:
92
+ self.left_indicator.set_arrow_color(color)
93
+ self.right_indicator.set_arrow_color(color)
94
+ return self
95
+
96
+ def disable(self):
97
+ super().disable()
98
+ self.left_indicator.disable()
99
+ self.right_indicator.disable()
100
+ return self
101
+
102
+ def enable(self):
103
+ super().enable()
104
+ self.left_indicator.enable()
105
+ self.right_indicator.enable()
106
+ self._update_arrow_states()
107
+ return self
108
+
109
+ def set_tooltip_text(self, text) -> Self:
110
+ self.left_indicator.set_tooltip_text(text)
111
+ self.right_indicator.set_tooltip_text(text)
112
+ return super().set_tooltip_text(text)
113
+
114
+ def get_min_required_size(self) -> tuple[float, float]:
115
+ old_text = self.text_widget.get_text()
116
+ max_size = (0, 0)
117
+ for option in self.options:
118
+ self.text_widget.set_text(self.display_func(option))
119
+ size = self.text_widget.get_min_required_size()
120
+ max_size = (max(max_size[0], size[0]), max(max_size[1], size[1]))
121
+ self.text_widget.set_text(old_text)
122
+
123
+ # total_height = max(self.font_object.get_height() + 1, max_size[1] * 1.5)
124
+ total_height = max_size[1] if max_size[1] > 16 else max_size[1]*1.5
125
+ total_height += self.unpressed_relief
126
+ total_height += max(self.right_indicator.outline_width, self.left_indicator.outline_width)
127
+
128
+ total_width = total_height * 2 + max_size[0] + self.gap * 2
129
+
130
+ return self.expand_rect_with_padding((0, 0, total_width, total_height)).size
131
+
132
+ def _align_content(self):
133
+ padded = self.get_inner_rect()
134
+ indicator_height = padded.h
135
+ self.left_indicator.set_size((indicator_height, indicator_height))
136
+ self.right_indicator.set_size((indicator_height, indicator_height))
137
+
138
+ self.left_indicator.set_position(padded.left, None)
139
+ self.left_indicator.set_center(None, padded.centery)
140
+
141
+ right_size = self.right_indicator.rect.size
142
+ self.right_indicator.set_position(padded.right - right_size[0], None)
143
+ self.right_indicator.set_center(None, padded.centery)
144
+
145
+ def apply_post_updates(self, skip_draw=False):
146
+ super().apply_post_updates(skip_draw)
147
+ self._align_content()
148
+
149
+ def get_current_index(self) -> int:
150
+ return self.current_index
151
+
152
+ def set_allow_cycle(self, value: bool) -> Self:
153
+ if value != self.allow_cycle:
154
+ self.allow_cycle = value
155
+ self.dirty_surface = True
156
+ self._update_arrow_states()
157
+ return self
158
+
159
+ def set_text_color(self, color) -> Self:
160
+ super().set_text_color(color)
161
+ return self
162
+
163
+ def set_modify_callback(self, func: Callable[[Any, int], Any]) -> Self:
164
+ self.on_modify_callback = func
165
+ return self
166
+
167
+ def set_by_index(self, index: int) -> Self:
168
+ if self.allow_cycle:
169
+ index = index % len(self.options)
170
+ else:
171
+ index = max(min(len(self.options) - 1, index), 0)
172
+
173
+ if index == self.current_index:
174
+ return self
175
+
176
+ self.current_index = index
177
+ value = self.options[self.current_index]
178
+ display_text = self.display_func(value)
179
+ self.set_text(display_text)
180
+
181
+ self.synced_var.value = value
182
+
183
+ if self.on_modify_callback:
184
+ self.on_modify_callback(value, self.current_index)
185
+
186
+ if not self.allow_cycle:
187
+ if index == 0:
188
+ self.left_indicator.disable()
189
+ else:
190
+ self.left_indicator.enable()
191
+ if index == len(self.options) - 1:
192
+ self.right_indicator.disable()
193
+ else:
194
+ self.right_indicator.enable()
195
+
196
+ return self
197
+
198
+
199
+ def set_by_value(self, value: str) -> Self:
200
+ if not self.is_enabled:
201
+ return self
202
+ if value not in self.options:
203
+ return self
204
+ index = self.options.index(value)
205
+ self.set_by_index(index)
206
+ return self
207
+
208
+ def on_key_down(self, key: int,event) -> None:
209
+ if not self.is_enabled:
210
+ return
211
+ key_actions = {
212
+ pygame.K_RIGHT: self.right_indicator,
213
+ pygame.K_SPACE: self.right_indicator,
214
+ pygame.K_LEFT: self.left_indicator,
215
+ }
216
+ indicator = key_actions.get(key)
217
+ if indicator and indicator.visible and indicator.is_enabled:
218
+ indicator.on_click_down(1,event)
219
+ event.consumed = True
220
+
221
+ def on_key_up(self, key: int,event) -> None:
222
+ if not self.is_enabled:
223
+ return
224
+ key_actions = {
225
+ pygame.K_RIGHT: self.right_indicator,
226
+ pygame.K_SPACE: self.right_indicator,
227
+ pygame.K_LEFT: self.left_indicator,
228
+ }
229
+ indicator = key_actions.get(key)
230
+ if indicator and indicator.visible and indicator.is_enabled:
231
+ indicator.on_click_up(1,event)
232
+ event.consumed = True
batFramework/gui/shape.py CHANGED
@@ -1,86 +1,286 @@
1
- import batFramework as bf
2
- from .widget import Widget
3
- import pygame
4
-
5
-
6
- class Shape(Widget):
7
- def __init__(self,width:float,height:float):
8
- self._color = (0,0,0,0)
9
- self._border_radius:list[int] = [0]
10
- self._outline : int = 0
11
- self._outline_color : tuple[int,int,int] | str = (0,0,0,0)
12
- super().__init__(convert_alpha = True)
13
- self.set_size(width,height)
14
-
15
-
16
- def to_string_id(self)->str:
17
- return "Shape"
18
-
19
- def set_color(self,color:tuple[int,int,int]|str) -> "Frame":
20
- self._color = color
21
- self.build()
22
- return self
23
-
24
- def set_outline_color(self,color:tuple[int,int,int]|str) -> "Frame":
25
- self._outline_color = color
26
- self.build()
27
- return self
28
-
29
- def set_border_radius(self,value:int|list[int]) -> "Frame":
30
- if isinstance(value,int):
31
- self._border_radius = [value]
32
- else:
33
- self._border_radius = value
34
- self.build()
35
- return self
36
-
37
- def set_outline_width(self,value:int) -> "Frame":
38
- self._outline = value
39
- self.build()
40
- return self
41
-
42
- def build(self)->None:
43
- if self.surface.get_size() != self.get_size_int():
44
- self.surface = pygame.Surface(self.get_size_int())
45
- if self.convert_alpha :
46
- self.surface = self.surface.convert_alpha()
47
- self.surface.fill((0,0,0,0))
48
- if self.parent :
49
- self.parent.children_modified()
50
- if self._border_radius == [0]:
51
- self._build_shape()
52
- if self._outline : self._build_outline()
53
- else:
54
- self._build_rounded_shape()
55
- if self._outline : self._build_rounded_outline()
56
-
57
-
58
- def _build_shape(self)->None:
59
- self.surface.fill(self._color)
60
-
61
- def _build_rounded_shape(self)->None:
62
- self.surface.fill((0,0,0,0))
63
- pygame.draw.rect(
64
- self.surface,
65
- self._color,
66
- (0,0,*self.rect.size),
67
- 0,
68
- *self._border_radius
69
- )
70
-
71
- def _build_outline(self)->None:
72
- pygame.draw.rect(
73
- self.surface,
74
- self._outline_color,
75
- (0,0,*self.rect.size),
76
- self._outline
77
- )
78
-
79
- def _build_rounded_outline(self)->None:
80
- pygame.draw.rect(
81
- self.surface,
82
- self._outline_color,
83
- (0,0,*self.rect.size),
84
- self._outline,
85
- *self._border_radius
86
- )
1
+ import batFramework as bf
2
+ from .widget import Widget
3
+ import pygame
4
+ from typing import Self, Iterable
5
+ from math import ceil
6
+
7
+
8
+ class Shape(Widget):
9
+ def __init__(self, size: tuple[float, float]|None = None, *args, **kwargs):
10
+ super().__init__(size=size, convert_alpha=True)
11
+ self.color = (0, 0, 0, 0)
12
+ self.border_radius: list[int] = [0]
13
+ self.outline_width: int = 0
14
+ self.outline_color: pygame.typing.ColorLike = (0, 0, 0, 255)
15
+ self.texture_surface = None
16
+ self.texture_subsize = (0, 0)
17
+ self.relief = 0
18
+ self.shadow_color: pygame.typing.ColorLike = (0, 0, 0, 255)
19
+ self.draw_mode = bf.drawMode.SOLID
20
+
21
+ def get_inner_bottom(self) -> float:
22
+ return self.rect.bottom - self.padding[3] - self.relief
23
+
24
+ def get_inner_height(self) -> float:
25
+ return self.rect.h - self.padding[1] - self.padding[3] - self.relief
26
+
27
+ def get_inner_top(self) -> float:
28
+ return self.rect.y + self.padding[1]
29
+
30
+ def get_local_inner_rect(self)->pygame.FRect:
31
+ return pygame.FRect(
32
+ self.padding[0],
33
+ self.padding[1],
34
+ self.rect.w - self.padding[2] - self.padding[0],
35
+ self.rect.h - self.padding[1] - self.padding[3] - self.relief,
36
+ )
37
+
38
+ def get_inner_rect(self) -> pygame.FRect:
39
+ return pygame.FRect(
40
+ self.rect.x + self.padding[0],
41
+ self.rect.y + self.padding[1],
42
+ self.rect.w - self.padding[2] - self.padding[0],
43
+ self.rect.h - self.padding[1] - self.padding[3] - self.relief,
44
+ )
45
+
46
+ def set_shadow_color(self, color: pygame.typing.ColorLike) -> Self:
47
+ self.shadow_color = color
48
+ self.dirty_surface = True
49
+ return self
50
+
51
+ def set_relief(self, relief: int) -> Self:
52
+ if relief < 0:
53
+ return self
54
+ self.dirty_shape = self.relief != relief
55
+ self.relief = relief
56
+ return self
57
+
58
+
59
+
60
+ def set_texture(
61
+ self, surface: pygame.SurfaceType, subsize: tuple[int, int] | None = None
62
+ ) -> Self:
63
+ self.texture_surface = surface
64
+ if subsize is None:
65
+ subsize = (ceil(surface.get_width() / 3), ceil(surface.get_height() / 3))
66
+ self.texture_subsize = subsize
67
+ self.dirty_surface = True
68
+ return self
69
+
70
+ def set_draw_mode(self, mode: bf.drawMode) -> Self:
71
+ self.draw_mode = mode
72
+ self.dirty_surface = True
73
+ return self
74
+
75
+ def get_draw_mode(self) -> bf.drawMode:
76
+ return self.draw_mode
77
+
78
+ def has_alpha_color(self) -> bool:
79
+ return (pygame.Color(self.color).a != 255) or (
80
+ pygame.Color(self.outline_color).a != 255
81
+ )
82
+
83
+ def __str__(self) -> str:
84
+ return "Shape"
85
+
86
+ def set_color(self, color: pygame.typing.ColorLike) -> Self:
87
+ self.color = color
88
+ self.dirty_surface = True
89
+ return self
90
+
91
+ def set_outline_color(self, color: pygame.typing.ColorLike) -> Self:
92
+ self.outline_color = color
93
+ self.dirty_surface = True
94
+ return self
95
+
96
+ def set_border_radius(self, value: int | list[int]) -> Self:
97
+ if isinstance(value, int):
98
+ self.border_radius = [value]
99
+ else:
100
+ self.border_radius = value
101
+ self.dirty_surface = True
102
+ return self
103
+
104
+ def set_outline_width(self, value: int) -> Self:
105
+ self.outline_width = value
106
+ self.dirty_surface = True
107
+ return self
108
+
109
+ def paint(self) -> None:
110
+ self._resize_surface()
111
+ if self.draw_mode == bf.drawMode.TEXTURED:
112
+ self._paint_textured()
113
+ return
114
+ if self.border_radius == [0]:
115
+ self._paint_shape()
116
+ if self.outline_width:
117
+ self._paint_outline()
118
+ else:
119
+ self._paint_rounded_shape()
120
+ if self.outline_width:
121
+ self._paint_rounded_outline()
122
+
123
+ def _paint_textured(self) -> None:
124
+ self.surface.fill((0, 0, 0, 0))
125
+ if self.texture_surface is None:
126
+ return
127
+ w, h = self.surface.get_size()
128
+ sw, sh = self.texture_surface.get_size()
129
+ sub = self.texture_subsize
130
+
131
+ # center
132
+ center_surface = self.texture_surface.subsurface((sub[0], sub[1], *sub))
133
+ top_surface = self.texture_surface.subsurface((sub[0], 0, *sub))
134
+ bottom_surface = self.texture_surface.subsurface((sub[0], sh - sub[1], *sub))
135
+ left_surface = self.texture_surface.subsurface((0, sub[1], *sub))
136
+ right_surface = self.texture_surface.subsurface((sw - sub[0], sub[1], *sub))
137
+
138
+ lst = []
139
+ for y in range(sub[1], h + 1 - sub[1] * 2, sub[1]):
140
+ for x in range(sub[0], w + 1 - sub[0] * 2, sub[0]):
141
+ lst.append((center_surface, (x, y)))
142
+
143
+ w_remainder = w % sub[0]
144
+ h_remainder = h % sub[1]
145
+ fix_x = ((w // sub[0]) - 1) * sub[0]
146
+ fix_y = ((h // sub[1]) - 1) * sub[1]
147
+
148
+ if (w > sub[0]) and (w_remainder > 0):
149
+ # Center : Fix gaps on the x axis
150
+ h_portion = center_surface.subsurface(0, 0, w_remainder, sub[1])
151
+ for y in range(sub[1], h - sub[1] * 2, sub[1]):
152
+ lst.append((h_portion, (fix_x, y)))
153
+
154
+ # Fix partial gaps on the top
155
+
156
+ t_portion = top_surface.subsurface(0, 0, w_remainder, sub[1])
157
+ lst.append((t_portion, (fix_x, 0)))
158
+
159
+ # Fix partial gaps on the bottom
160
+ b_portion = bottom_surface.subsurface(0, 0, w_remainder, sub[1])
161
+ lst.append((b_portion, (fix_x, h - sub[1] - 1)))
162
+
163
+ if (h > sub[1]) and (h_remainder > 0):
164
+ # Center : Fix gaps on the y axis
165
+ v_portion = center_surface.subsurface(0, 0, sub[0], h_remainder)
166
+ for x in range(sub[0], w - sub[0] * 2, sub[0]):
167
+ lst.append((v_portion, (x, fix_y)))
168
+
169
+ # Fix partial gaps on the left
170
+ l_portion = left_surface.subsurface(0, 0, sub[0], h_remainder)
171
+ lst.append((l_portion, (0, fix_y)))
172
+
173
+ # Fix partial gaps on the right
174
+ r_portion = right_surface.subsurface(0, 0, sub[0], h_remainder)
175
+ lst.append((r_portion, (w - sub[0] - 1, fix_y)))
176
+
177
+ # fix corner gap
178
+ if h > sub[1] or w > sub[0]:
179
+ corner_portion = center_surface.subsurface(
180
+ 0,
181
+ 0,
182
+ w_remainder if w_remainder else sub[0],
183
+ h_remainder if h_remainder else sub[1],
184
+ )
185
+ if w_remainder == 0:
186
+ fix_x -= sub[0]
187
+ if h_remainder == 0:
188
+ fix_y -= sub[1]
189
+ lst.append((corner_portion, (fix_x - 1, fix_y - 1)))
190
+
191
+ # borders
192
+ lst.extend(
193
+ [(top_surface, (x, 0)) for x in range(sub[0], w + 1 - sub[0] * 2, sub[0])]
194
+ + [
195
+ (bottom_surface, (x, h - sub[1] - 1))
196
+ for x in range(sub[0], w + 1 - sub[0] * 2, sub[0])
197
+ ]
198
+ + [
199
+ (left_surface, (0, y))
200
+ for y in range(sub[1], h + 1 - sub[1] * 2, sub[1])
201
+ ]
202
+ + [
203
+ (right_surface, (w - sub[0] - 1, y))
204
+ for y in range(sub[1], h + 1 - sub[1] * 2, sub[1])
205
+ ]
206
+ + [
207
+ (self.texture_surface.subsurface((0, 0, *sub)), (0, 0)),
208
+ (
209
+ self.texture_surface.subsurface((sw - sub[0], 0, *sub)),
210
+ (w - sub[0] - 1, 0),
211
+ ),
212
+ (
213
+ self.texture_surface.subsurface((0, sh - sub[1], *sub)),
214
+ (0, h - sub[1] - 1),
215
+ ),
216
+ (
217
+ self.texture_surface.subsurface((sw - sub[0], sh - sub[1], *sub)),
218
+ (w - sub[0] - 1, h - sub[1] - 1),
219
+ ),
220
+ ]
221
+ )
222
+
223
+ self.surface.fblits(lst)
224
+
225
+ def _get_elevated_rect(self) -> pygame.FRect:
226
+ return pygame.FRect(0, 0, self.rect.w, self.rect.h - self.relief)
227
+
228
+ def _get_base_rect(self) -> pygame.FRect:
229
+ return pygame.FRect(0, self.rect.h - self.relief, self.rect.w, self.relief)
230
+
231
+ def _paint_shape(self) -> None:
232
+ self.surface.fill((0, 0, 0, 0))
233
+ if self.relief!=0:
234
+ if self.shadow_color is not None:
235
+ self.surface.fill(self.shadow_color, self._get_base_rect())
236
+ if self.color is not None:
237
+ self.surface.fill(self.color, self._get_elevated_rect())
238
+
239
+ elif self.color is not None:
240
+ self.surface.fill(self.color, self._get_elevated_rect())
241
+
242
+ def _paint_rounded_shape(self) -> None:
243
+ self.surface.fill((0, 0, 0, 0))
244
+ e = self._get_elevated_rect()
245
+ if self.relief != 0:
246
+ b = e.copy()
247
+ b.bottom = self.rect.h
248
+ if self.shadow_color is not None:
249
+ pygame.draw.rect(self.surface, self.shadow_color, b, 0, *self.border_radius)
250
+ if self.color is not None:
251
+ pygame.draw.rect(self.surface, self.color, e, 0, *self.border_radius)
252
+ elif self.color is not None:
253
+ pygame.draw.rect(self.surface, self.color, e, 0, *self.border_radius)
254
+
255
+ def _paint_outline(self) -> None:
256
+ if self.outline_color is None:
257
+ return
258
+ pygame.draw.rect(
259
+ self.surface,
260
+ self.outline_color,
261
+ self._get_elevated_rect(),
262
+ self.outline_width,
263
+ )
264
+
265
+ def _paint_rounded_outline(self) -> None:
266
+ if self.outline_color is None:
267
+ return
268
+ e = self._get_elevated_rect()
269
+ b = e.copy()
270
+ b.h += e.bottom - b.bottom
271
+
272
+ pygame.draw.rect(
273
+ self.surface,
274
+ self.outline_color,
275
+ e,
276
+ self.outline_width,
277
+ *self.border_radius,
278
+ )
279
+ if self.relief:
280
+ pygame.draw.rect(
281
+ self.surface,
282
+ self.outline_color,
283
+ b,
284
+ self.outline_width,
285
+ *self.border_radius,
286
+ )