batframework 1.0.8a1__py3-none-any.whl → 1.0.8a3__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 (46) hide show
  1. batFramework/action.py +30 -14
  2. batFramework/actionContainer.py +5 -3
  3. batFramework/audioManager.py +0 -1
  4. batFramework/camera.py +29 -24
  5. batFramework/cutscene.py +2 -4
  6. batFramework/entity.py +9 -2
  7. batFramework/enums.py +11 -2
  8. batFramework/fontManager.py +1 -1
  9. batFramework/gui/__init__.py +3 -1
  10. batFramework/gui/button.py +5 -2
  11. batFramework/gui/clickableWidget.py +42 -29
  12. batFramework/gui/constraints/constraints.py +269 -57
  13. batFramework/gui/container.py +39 -21
  14. batFramework/gui/debugger.py +18 -11
  15. batFramework/gui/dialogueBox.py +20 -17
  16. batFramework/gui/draggableWidget.py +7 -5
  17. batFramework/gui/image.py +27 -15
  18. batFramework/gui/indicator.py +1 -4
  19. batFramework/gui/interactiveWidget.py +91 -30
  20. batFramework/gui/label.py +44 -35
  21. batFramework/gui/layout.py +115 -43
  22. batFramework/gui/meter.py +3 -8
  23. batFramework/gui/radioButton.py +47 -25
  24. batFramework/gui/root.py +50 -25
  25. batFramework/gui/shape.py +14 -19
  26. batFramework/gui/slider.py +70 -44
  27. batFramework/gui/style.py +10 -0
  28. batFramework/gui/styleManager.py +48 -0
  29. batFramework/gui/textInput.py +25 -22
  30. batFramework/gui/toggle.py +42 -29
  31. batFramework/gui/widget.py +176 -115
  32. batFramework/object.py +9 -10
  33. batFramework/renderGroup.py +7 -2
  34. batFramework/scene.py +70 -49
  35. batFramework/sceneManager.py +15 -20
  36. batFramework/scrollingSprite.py +5 -3
  37. batFramework/sprite.py +20 -14
  38. batFramework/stateMachine.py +1 -2
  39. batFramework/tileset.py +5 -5
  40. batFramework/utils.py +12 -10
  41. {batframework-1.0.8a1.dist-info → batframework-1.0.8a3.dist-info}/METADATA +1 -1
  42. batframework-1.0.8a3.dist-info/RECORD +58 -0
  43. {batframework-1.0.8a1.dist-info → batframework-1.0.8a3.dist-info}/WHEEL +1 -1
  44. batframework-1.0.8a1.dist-info/RECORD +0 -56
  45. {batframework-1.0.8a1.dist-info → batframework-1.0.8a3.dist-info}/LICENCE +0 -0
  46. {batframework-1.0.8a1.dist-info → batframework-1.0.8a3.dist-info}/top_level.txt +0 -0
@@ -1,12 +1,13 @@
1
1
  import batFramework as bf
2
2
  from .widget import Widget
3
3
  from .constraints.constraints import *
4
- from typing import Self,TYPE_CHECKING
4
+ from typing import Self, TYPE_CHECKING
5
5
  import pygame
6
6
 
7
7
  if TYPE_CHECKING:
8
8
  from .container import Container
9
9
 
10
+
10
11
  class Layout:
11
12
  def __init__(self, parent: "Container" = None):
12
13
  self.parent = parent
@@ -23,46 +24,58 @@ class Layout:
23
24
  self.notify_parent()
24
25
 
25
26
  def notify_parent(self) -> None:
26
- if self.parent:self.parent.dirty_children = True
27
+ if self.parent:
28
+ self.parent.dirty_children = True
27
29
 
28
30
  def arrange(self) -> None:
29
31
  return
30
32
 
31
- def clamp_scroll(self)->None:
32
- return
33
-
34
- def get_raw_size(self)->tuple[float,float]:
35
- return self.parent.rect.size if self.parent else 0,0
33
+ def get_raw_size(self) -> tuple[float, float]:
34
+ """
35
+ Returns the supposed size the container should have to encapsulate perfectly all of its widgets
36
+ """
37
+ return self.parent.rect.size if self.parent else (0, 0)
36
38
 
37
- def get_auto_size(self)->tuple[float,float]:
38
- return self.parent.rect.size if self.parent else 0,0
39
+ def get_auto_size(self) -> tuple[float, float]:
40
+ """
41
+ Returns the final size the container should have (while keeping the the width and height if they are non-resizable)
42
+ """
43
+ target_size = list(self.get_raw_size())
44
+ if not self.parent.autoresize_w:
45
+ target_size[0] = self.parent.rect.w
46
+ if not self.parent.autoresize_h:
47
+ target_size[1] = self.parent.rect.h
48
+ return target_size
39
49
 
40
- def focus_next_child(self)->None:
50
+ def focus_next_child(self) -> None:
41
51
  l = self.parent.get_interactive_children()
42
52
  self.parent.focused_index = min(self.parent.focused_index + 1, len(l) - 1)
43
53
  focused = l[self.parent.focused_index]
44
54
  focused.get_focus()
45
55
  self.scroll_to_widget(focused)
46
56
 
47
- def focus_prev_child(self)->None:
57
+ def focus_prev_child(self) -> None:
48
58
  l = self.parent.get_interactive_children()
49
59
  self.parent.focused_index = max(self.parent.focused_index - 1, 0)
50
60
  focused = l[self.parent.focused_index]
51
61
  focused.get_focus()
52
62
  self.scroll_to_widget(focused)
53
63
 
54
- def scroll_to_widget(self,widget:Widget)->None:
64
+ def scroll_to_widget(self, widget: Widget) -> None:
55
65
  padded = self.parent.get_padded_rect()
56
66
  r = widget.rect
57
- if padded.contains(r):return
67
+ if padded.contains(r):
68
+ return
58
69
  clamped = r.clamp(padded)
59
- dx,dy = clamped.move(-r.x,-r.y).topleft
60
- self.parent.scroll_by((-dx,-dy))
70
+ dx, dy = clamped.move(-r.x, -r.y).topleft
71
+ self.parent.scroll_by((-dx, -dy))
61
72
 
73
+ def handle_event(self, event):
74
+ pass
62
75
 
63
76
 
64
77
  class Column(Layout):
65
- def __init__(self, gap: int = 0,spacing:bf.spacing = bf.spacing.MANUAL):
78
+ def __init__(self, gap: int = 0, spacing: bf.spacing = bf.spacing.MANUAL):
66
79
  super().__init__()
67
80
  self.gap = gap
68
81
  self.spacing = spacing
@@ -71,50 +84,81 @@ class Column(Layout):
71
84
  self.gap = value
72
85
  self.notify_parent()
73
86
  return self
74
-
75
- def set_spacing(self,spacing: bf.spacing)->Self:
87
+
88
+ def set_spacing(self, spacing: bf.spacing) -> Self:
76
89
  self.spacing = spacing
77
90
  self.notify_parent()
78
91
  return self
79
92
 
80
- def get_raw_size(self)-> tuple[float,float]:
93
+ def get_raw_size(self) -> tuple[float, float]:
81
94
  len_children = len(self.parent.children)
82
- if not len_children : return self.parent.rect.size
95
+ if not len_children:
96
+ return self.parent.rect.size
83
97
  parent_height = sum(c.get_min_required_size()[1] for c in self.parent.children)
84
98
  parent_width = max(c.get_min_required_size()[0] for c in self.parent.children)
85
99
  if self.gap:
86
100
  parent_height += (len_children - 1) * self.gap
87
- target_rect = self.parent.inflate_rect_by_padding((0,0,parent_width,parent_height))
101
+ target_rect = self.parent.inflate_rect_by_padding(
102
+ (0, 0, parent_width, parent_height)
103
+ )
88
104
  return target_rect.size
89
-
90
- def get_auto_size(self)-> tuple[float,float]:
105
+
106
+ def get_auto_size(self) -> tuple[float, float]:
91
107
  target_size = list(self.get_raw_size())
92
- if not self.parent.autoresize_w : target_size[0] = self.parent.rect.w
93
- if not self.parent.autoresize_h : target_size[1] = self.parent.rect.h
108
+ if not self.parent.autoresize_w:
109
+ target_size[0] = self.parent.rect.w
110
+ if not self.parent.autoresize_h:
111
+ target_size[1] = self.parent.rect.h
94
112
  return target_size
95
113
 
96
114
  def arrange(self) -> None:
97
115
  if not self.parent or not self.parent.children:
98
116
  return
99
- if self.child_constraints :
100
- for child in self.parent.children : child.add_constraints(*self.child_constraints)
117
+ if self.child_constraints:
118
+ for child in self.parent.children:
119
+ child.add_constraints(*self.child_constraints)
101
120
  self.child_rect = self.parent.get_padded_rect()
102
121
 
103
122
  if self.parent.autoresize_w or self.parent.autoresize_h:
104
- width,height = self.get_auto_size()
105
- if self.parent.rect.size != (width,height):
106
- self.parent.set_size((width,height))
123
+ width, height = self.get_auto_size()
124
+ if self.parent.rect.size != (width, height):
125
+ self.parent.set_size((width, height))
107
126
  self.parent.build()
108
127
  self.arrange()
109
128
  return
110
- self.child_rect.move_ip(-self.parent.scroll.x,-self.parent.scroll.y)
129
+ self.child_rect.move_ip(-self.parent.scroll.x, -self.parent.scroll.y)
111
130
  y = self.child_rect.top
112
- for child in self.parent.children :
113
- child.set_position(self.child_rect.x,y)
114
- y+= child.get_min_required_size()[1] + self.gap
131
+ for child in self.parent.children:
132
+ child.set_position(self.child_rect.x, y)
133
+ y += child.get_min_required_size()[1] + self.gap
134
+
135
+ def handle_event(self, event):
136
+ if self.parent.autoresize_h or not self.parent.visible:
137
+ return
138
+
139
+ if not self.parent.children:
140
+ return
141
+
142
+ if event.type == pygame.MOUSEBUTTONDOWN:
143
+ r = self.parent.get_root()
144
+ if not r:
145
+ return
146
+
147
+ if self.parent.rect.collidepoint(
148
+ r.drawing_camera.screen_to_world(pygame.mouse.get_pos())
149
+ ):
150
+ if event.button == 4:
151
+ self.parent.scroll_by((0, -10))
152
+ elif event.button == 5:
153
+ self.parent.scroll_by((0, 10))
154
+ else:
155
+ return
156
+ event.consumed = True
157
+ self.parent.clamp_scroll()
158
+
115
159
 
116
160
  class Row(Layout):
117
- def __init__(self, gap: int = 0,spacing: bf.spacing=bf.spacing.MANUAL):
161
+ def __init__(self, gap: int = 0, spacing: bf.spacing = bf.spacing.MANUAL):
118
162
  super().__init__()
119
163
  self.gap = gap
120
164
  self.spacing = spacing
@@ -123,35 +167,40 @@ class Row(Layout):
123
167
  self.gap = value
124
168
  self.notify_parent()
125
169
  return self
126
-
127
- def set_spacing(self,spacing: bf.spacing)->Self:
170
+
171
+ def set_spacing(self, spacing: bf.spacing) -> Self:
128
172
  self.spacing = spacing
129
173
  self.notify_parent()
130
174
  return self
131
175
 
132
-
133
176
  def get_raw_size(self) -> tuple[float, float]:
134
177
  len_children = len(self.parent.children)
135
- if not len_children: return self.parent.rect.size
178
+ if not len_children:
179
+ return self.parent.rect.size
136
180
  parent_width = sum(c.get_min_required_size()[0] for c in self.parent.children)
137
181
  parent_height = max(c.get_min_required_size()[1] for c in self.parent.children)
138
182
  if self.gap:
139
183
  parent_width += (len_children - 1) * self.gap
140
- target_rect = self.parent.inflate_rect_by_padding((0, 0, parent_width, parent_height))
184
+ target_rect = self.parent.inflate_rect_by_padding(
185
+ (0, 0, parent_width, parent_height)
186
+ )
141
187
 
142
188
  return target_rect.size
143
189
 
144
190
  def get_auto_size(self) -> tuple[float, float]:
145
191
  target_size = list(self.get_raw_size())
146
- if not self.parent.autoresize_w: target_size[0] = self.parent.rect.w
147
- if not self.parent.autoresize_h: target_size[1] = self.parent.rect.h
192
+ if not self.parent.autoresize_w:
193
+ target_size[0] = self.parent.rect.w
194
+ if not self.parent.autoresize_h:
195
+ target_size[1] = self.parent.rect.h
148
196
  return target_size
149
197
 
150
198
  def arrange(self) -> None:
151
199
  if not self.parent or not self.parent.children:
152
200
  return
153
201
  if self.child_constraints:
154
- for child in self.parent.children: child.add_constraints(*self.child_constraints)
202
+ for child in self.parent.children:
203
+ child.add_constraints(*self.child_constraints)
155
204
  self.child_rect = self.parent.get_padded_rect()
156
205
 
157
206
  if self.parent.autoresize_w or self.parent.autoresize_h:
@@ -166,3 +215,26 @@ class Row(Layout):
166
215
  for child in self.parent.children:
167
216
  child.set_position(x, self.child_rect.y)
168
217
  x += child.get_min_required_size()[0] + self.gap
218
+
219
+ def handle_event(self, event):
220
+ if self.parent.autoresize_w or not self.parent.visible:
221
+ return
222
+
223
+ if not self.parent.children:
224
+ return
225
+
226
+ if event.type == pygame.MOUSEBUTTONDOWN:
227
+ r = self.parent.get_root()
228
+ if not r:
229
+ return
230
+ if self.parent.rect.collidepoint(
231
+ r.drawing_camera.screen_to_world(pygame.mouse.get_pos())
232
+ ):
233
+ if event.button == 4:
234
+ self.parent.scroll_by((-10, 0))
235
+ elif event.button == 5:
236
+ self.parent.scroll_by((10, 0))
237
+ else:
238
+ return
239
+ event.consumed = True
240
+ self.parent.clamp_scroll()
batFramework/gui/meter.py CHANGED
@@ -10,14 +10,9 @@ def custom_top_at(self, x, y):
10
10
 
11
11
 
12
12
  class Meter(Shape):
13
- def __init__(
14
- self,
15
- min_value: float = 0,
16
- max_value: float = 1,
17
- step: float = 0.1
18
- ):
13
+ def __init__(self, min_value: float = 0, max_value: float = 1, step: float = 0.1):
19
14
  super().__init__()
20
- self.min_value, self.max_value = min_value,max_value
15
+ self.min_value, self.max_value = min_value, max_value
21
16
  self.step = step
22
17
  self.snap: bool = False
23
18
  self.value = self.max_value
@@ -67,7 +62,7 @@ class Meter(Shape):
67
62
  return self.value / (self.max_value - self.min_value)
68
63
 
69
64
  def _build_content(self) -> None:
70
- width = (self.get_padded_width() * self.get_ratio())
65
+ width = self.get_padded_width() * self.get_ratio()
71
66
  self.content.set_size((width, self.get_padded_height()))
72
67
  self.content.set_position(*self.get_padded_rect().topleft)
73
68
 
@@ -1,62 +1,84 @@
1
1
  import batFramework as bf
2
- from typing import Self,Any,Callable
2
+ from typing import Self, Any, Callable
3
3
  from .toggle import Toggle
4
4
 
5
- class RadioVariable:...
5
+
6
+ class RadioVariable: ...
7
+
6
8
 
7
9
  class RadioButton(Toggle):
8
- def __init__(self, text: str, radio_value:Any = None) -> None:
9
- super().__init__(text,None, False)
10
- self.radio_value : Any = radio_value if radio_value is not None else text if text else None
11
- self.radio_variable : RadioVariable = None
10
+ def __init__(self, text: str, radio_value: Any = None) -> None:
11
+ super().__init__(text, None, False)
12
+ self.radio_value: Any = (
13
+ radio_value if radio_value is not None else text if text else None
14
+ )
15
+ self.radio_variable: RadioVariable = None
16
+
17
+ def __str__(self) -> str:
18
+ return (
19
+ f"RadioButton({self.radio_value}|{'Active' if self.value else 'Inactive'})"
20
+ )
12
21
 
13
- def set_radio_value(self,value:Any)->Self:
22
+ def set_radio_value(self, value: Any) -> Self:
14
23
  self.radio_value = value
15
- self.update_radio()
24
+
25
+ if self.radio_variable:
26
+ self.radio_variable.update_buttons()
16
27
  return self
17
-
28
+
18
29
  def set_text(self, text: str) -> Self:
19
30
  flag = False
20
- if self.value == self.text or self.value is None: flag = True
31
+ if self.value == self.text or self.value is None:
32
+ flag = True
21
33
  super().set_text(text)
22
34
  if flag:
23
35
  self.set_radio_value(self.text)
24
36
  return self
25
37
 
26
38
  def click(self) -> None:
27
- if self.radio_variable is None: return
39
+ if self.radio_variable is None:
40
+ return
28
41
  self.radio_variable.set_value(self.radio_value)
29
42
 
43
+
30
44
  class RadioVariable:
31
- def __init__(self)->None:
32
- self.buttons : list[RadioButton] = []
45
+ def __init__(self) -> None:
46
+ self.buttons: list[RadioButton] = []
33
47
  self.value = None
34
- self.modify_callback : Callable[[Any],] = None
48
+ self.modify_callback: Callable[[Any],] = None
49
+
50
+ def set_modify_callback(self, callback) -> Self:
51
+ self.modify_callback = callback
52
+ return self
35
53
 
36
- def link(self,*buttons:RadioButton)->Self:
37
- if not buttons : return self
38
- for b in buttons :
54
+ def link(self, *buttons: RadioButton) -> Self:
55
+ if not buttons:
56
+ return self
57
+ for b in buttons:
39
58
  b.radio_variable = self
40
59
  self.buttons.extend(buttons)
41
-
60
+
42
61
  if self.value is None:
43
62
  self.set_value(buttons[0].radio_value)
44
63
  else:
45
- self.update_buttons()
64
+ self.update_buttons()
46
65
  return self
47
66
 
48
- def unlink(self,*buttons)->Self:
67
+ def unlink(self, *buttons) -> Self:
49
68
  for b in self.buttons:
50
69
  if b in buttons:
51
70
  b.radio_variable = None
52
71
  self.buttons = [b for b in self.buttons if b not in buttons]
53
72
  return self
54
73
 
55
- def set_value(self,value:Any):
56
- if value == self.value: return
74
+ def set_value(self, value: Any) -> Self:
75
+ if value == self.value:
76
+ return
57
77
  self.value = value
58
- if self.modify_callback :self.modify_callback(value)
59
- self.update_buttons()
78
+ if self.modify_callback:
79
+ self.modify_callback(value)
80
+ self.update_buttons()
81
+ return self
60
82
 
61
83
  def update_buttons(self):
62
- _ = [b.set_value(b.radio_value == self.value,False) for b in self.buttons]
84
+ _ = [b.set_value(b.radio_value == self.value, False) for b in self.buttons]
batFramework/gui/root.py CHANGED
@@ -2,6 +2,8 @@ import batFramework as bf
2
2
  from .interactiveWidget import InteractiveWidget
3
3
  from .widget import Widget
4
4
  import pygame
5
+ from typing import Self
6
+ import sys
5
7
 
6
8
 
7
9
  class Root(InteractiveWidget):
@@ -14,12 +16,16 @@ class Root(InteractiveWidget):
14
16
  self.focused: InteractiveWidget | None = self
15
17
  self.hovered: Widget | None = self
16
18
  self.set_debug_color("yellow")
17
- self.set_render_order(999)
19
+ self.set_render_order(sys.maxsize)
18
20
  self.clip_children = False
19
21
 
20
22
  def __str__(self) -> str:
21
23
  return "Root"
22
24
 
25
+ def set_parent_scene(self, parent_scene: bf.Scene) -> Self:
26
+ bf.StyleManager().register_widget(self)
27
+ return super().set_parent_scene(parent_scene)
28
+
23
29
  def get_focused(self) -> Widget | None:
24
30
  return self.focused
25
31
 
@@ -34,8 +40,14 @@ class Root(InteractiveWidget):
34
40
  self.hovered.on_exit()
35
41
  self.hovered = None
36
42
 
43
+ def get_debug_outlines(self):
44
+ yield (self.rect, self.debug_color)
45
+ for child in self.children:
46
+ yield from child.get_debug_outlines()
47
+
37
48
  def focus_on(self, widget: InteractiveWidget | None) -> None:
38
- if widget == self.focused : return
49
+ if widget == self.focused:
50
+ return
39
51
  if widget and not widget.allow_focus_to_self():
40
52
  return
41
53
  if self.focused is not None:
@@ -46,26 +58,34 @@ class Root(InteractiveWidget):
46
58
  self.focused = widget
47
59
  self.focused.on_get_focus()
48
60
 
49
- def get_by_tags(self,*tags)->list[Widget]:
61
+ def get_by_tags(self, *tags) -> list[Widget]:
50
62
  res = []
51
- def getter(w:Widget):
63
+
64
+ def getter(w: Widget):
52
65
  nonlocal res
53
66
  if any(t in w.tags for t in tags):
54
67
  res.append(w)
68
+
55
69
  self.visit(getter)
56
70
  return res
57
71
 
58
- def get_by_uid(self,uid:int)->Widget:
59
- def helper(w: Widget,uid):
72
+ def focus_next_tab(self, widget):
73
+ return True
74
+
75
+ def focus_prev_tab(self, widget):
76
+ return True
77
+
78
+ def get_by_uid(self, uid: int) -> "Widget":
79
+ def helper(w: "Widget", uid: int) -> "Widget":
60
80
  if w.uid == uid:
61
81
  return w
62
82
  for child in w.children:
63
- res = helper(child,uid)
64
- if res :
65
- return child
66
-
83
+ res = helper(child, uid)
84
+ if res is not None:
85
+ return res
67
86
  return None
68
- return helper(self,uid)
87
+
88
+ return helper(self, uid)
69
89
 
70
90
  def set_size(self, size: tuple[float, float], force: bool = False) -> "Root":
71
91
  if not force:
@@ -74,23 +94,25 @@ class Root(InteractiveWidget):
74
94
  # self.build(resolve_constraints=True)
75
95
  return self
76
96
 
77
-
78
97
  def do_handle_event(self, event):
79
- # if event.type == pygame.VIDEORESIZE:
80
- # self.set_size(event.w, event.h, force=True)
81
- # return True
82
98
  if self.focused:
83
99
  if event.type == pygame.KEYDOWN:
84
- self.focused.on_key_down(event.key)
85
- if event.type == pygame.KEYUP:
86
- self.focused.on_key_up(event.key)
87
- elif not self.hovered or not isinstance(self.hovered, InteractiveWidget):
100
+ if self.focused.on_key_down(event.key):
101
+ event.consumed = True
102
+ elif event.type == pygame.KEYUP:
103
+ if self.focused.on_key_up(event.key):
104
+ event.consumed = True
105
+
106
+ if not self.hovered or (not isinstance(self.hovered, InteractiveWidget)):
88
107
  return
108
+
89
109
  if event.type == pygame.MOUSEBUTTONDOWN:
90
- self.hovered.on_click_down(event.button)
91
- elif event.type == pygame.MOUSEBUTTONUP:
92
- self.hovered.on_click_up(event.button)
110
+ if self.hovered.on_click_down(event.button):
111
+ event.consumed = True
93
112
 
113
+ elif event.type == pygame.MOUSEBUTTONUP:
114
+ if self.hovered.on_click_up(event.button):
115
+ event.consumed = True
94
116
 
95
117
  def do_on_click_down(self, button: int) -> None:
96
118
  if button == 1:
@@ -119,7 +141,10 @@ class Root(InteractiveWidget):
119
141
 
120
142
  def draw(self, camera: bf.Camera) -> int:
121
143
  super().draw(camera)
122
- if self.focused and self.focused!=self:
144
+ if (
145
+ self.parent_scene
146
+ and self.parent_scene.active
147
+ and self.focused
148
+ and self.focused != self
149
+ ):
123
150
  self.focused.draw_focused(camera)
124
-
125
-
batFramework/gui/shape.py CHANGED
@@ -1,13 +1,13 @@
1
1
  import batFramework as bf
2
2
  from .widget import Widget
3
3
  import pygame
4
- from typing import Self,Iterable
4
+ from typing import Self, Iterable
5
5
  from math import ceil
6
6
 
7
7
 
8
8
  class Shape(Widget):
9
- def __init__(self, size: tuple[float, float] = None,*args,**kwargs):
10
- super().__init__(size=size,convert_alpha=True)
9
+ def __init__(self, size: tuple[float, float] = None, *args, **kwargs):
10
+ super().__init__(size=size, convert_alpha=True)
11
11
  self.color = (0, 0, 0, 0)
12
12
  self.border_radius: list[int] = [0]
13
13
  self.outline: int = 0
@@ -24,15 +24,15 @@ class Shape(Widget):
24
24
  def get_padded_height(self) -> float:
25
25
  return self.rect.h - self.padding[1] - self.padding[3] - self.relief
26
26
 
27
- def get_padded_top(self)->float:
27
+ def get_padded_top(self) -> float:
28
28
  return self.rect.y + self.relief
29
29
 
30
- def get_padded_rect(self)->pygame.FRect:
30
+ def get_padded_rect(self) -> pygame.FRect:
31
31
  return pygame.FRect(
32
32
  self.rect.x + self.padding[0],
33
33
  self.rect.y + self.padding[1],
34
34
  self.rect.w - self.padding[2] - self.padding[0],
35
- self.rect.h - self.padding[1] - self.padding[3] - self.relief
35
+ self.rect.h - self.padding[1] - self.padding[3] - self.relief,
36
36
  )
37
37
 
38
38
  def set_shadow_color(self, color: tuple[int, int, int] | str) -> Self:
@@ -43,7 +43,8 @@ class Shape(Widget):
43
43
  def set_relief(self, relief: int) -> Self:
44
44
  if relief < 0:
45
45
  return self
46
- if self.relief == relief : return self
46
+ if self.relief == relief:
47
+ return self
47
48
  self.relief = relief
48
49
  self.dirty_shape = True
49
50
  return self
@@ -100,7 +101,7 @@ class Shape(Widget):
100
101
  self.dirty_surface = True
101
102
  return self
102
103
 
103
- def paint(self)->None:
104
+ def paint(self) -> None:
104
105
  if self.draw_mode == bf.drawMode.TEXTURED:
105
106
  self._paint_textured()
106
107
  return
@@ -113,8 +114,6 @@ class Shape(Widget):
113
114
  if self.outline:
114
115
  self._paint_rounded_outline()
115
116
 
116
-
117
-
118
117
  def _paint_textured(self) -> None:
119
118
  self.surface.fill((0, 0, 0, 0))
120
119
  if self.texture_surface is None:
@@ -218,14 +217,10 @@ class Shape(Widget):
218
217
  self.surface.fblits(lst)
219
218
 
220
219
  def _get_elevated_rect(self) -> pygame.FRect:
221
- return pygame.FRect(
222
- 0,0 , self.rect.w, self.rect.h - self.relief
223
- )
220
+ return pygame.FRect(0, 0, self.rect.w, self.rect.h - self.relief)
224
221
 
225
222
  def _get_base_rect(self) -> pygame.FRect:
226
- return pygame.FRect(
227
- 0, self.rect.h - self.relief , self.rect.w, self.relief
228
- )
223
+ return pygame.FRect(0, self.rect.h - self.relief, self.rect.w, self.relief)
229
224
 
230
225
  def _paint_shape(self) -> None:
231
226
  self.surface.fill((0, 0, 0, 0))
@@ -237,8 +232,8 @@ class Shape(Widget):
237
232
  e = self._get_elevated_rect()
238
233
  b = e.copy()
239
234
  b.bottom = self.rect.h
240
- pygame.draw.rect(self.surface, self.shadow_color, b, 0, *self.border_radius)
241
- pygame.draw.rect(self.surface, self.color, e, 0, *self.border_radius)
235
+ pygame.draw.rect(self.surface, self.shadow_color, b, 0, *self.border_radius)
236
+ pygame.draw.rect(self.surface, self.color, e, 0, *self.border_radius)
242
237
 
243
238
  def _paint_outline(self) -> None:
244
239
  if self.relief:
@@ -269,7 +264,7 @@ class Shape(Widget):
269
264
  e = self._get_elevated_rect()
270
265
  b = e.copy()
271
266
  b.h += e.bottom - b.bottom
272
-
267
+
273
268
  pygame.draw.rect(
274
269
  self.surface,
275
270
  self.outline_color,