batframework 1.0.8a3__py3-none-any.whl → 1.0.8a6__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 (44) hide show
  1. batFramework/__init__.py +16 -2
  2. batFramework/animatedSprite.py +94 -85
  3. batFramework/audioManager.py +2 -2
  4. batFramework/character.py +27 -0
  5. batFramework/cutscene.py +5 -2
  6. batFramework/cutsceneBlocks.py +3 -5
  7. batFramework/dynamicEntity.py +11 -4
  8. batFramework/enums.py +2 -2
  9. batFramework/fontManager.py +2 -2
  10. batFramework/gui/clickableWidget.py +10 -9
  11. batFramework/gui/constraints/constraints.py +282 -57
  12. batFramework/gui/image.py +14 -14
  13. batFramework/gui/interactiveWidget.py +16 -1
  14. batFramework/gui/label.py +58 -37
  15. batFramework/gui/layout.py +23 -14
  16. batFramework/gui/meter.py +10 -7
  17. batFramework/gui/radioButton.py +1 -1
  18. batFramework/gui/root.py +7 -1
  19. batFramework/gui/shape.py +21 -37
  20. batFramework/gui/slider.py +52 -58
  21. batFramework/gui/textInput.py +161 -51
  22. batFramework/gui/toggle.py +27 -41
  23. batFramework/gui/widget.py +68 -35
  24. batFramework/manager.py +17 -5
  25. batFramework/object.py +17 -8
  26. batFramework/particle.py +22 -8
  27. batFramework/resourceManager.py +18 -2
  28. batFramework/scene.py +50 -20
  29. batFramework/sceneManager.py +52 -28
  30. batFramework/scrollingSprite.py +7 -8
  31. batFramework/stateMachine.py +9 -6
  32. batFramework/templates/__init__.py +2 -0
  33. batFramework/templates/character.py +44 -0
  34. batFramework/templates/states.py +166 -0
  35. batFramework/time.py +54 -28
  36. batFramework/transition.py +25 -12
  37. batFramework/triggerZone.py +1 -1
  38. batFramework/utils.py +92 -2
  39. {batframework-1.0.8a3.dist-info → batframework-1.0.8a6.dist-info}/METADATA +3 -15
  40. batframework-1.0.8a6.dist-info/RECORD +62 -0
  41. {batframework-1.0.8a3.dist-info → batframework-1.0.8a6.dist-info}/WHEEL +1 -1
  42. batframework-1.0.8a3.dist-info/RECORD +0 -58
  43. {batframework-1.0.8a3.dist-info → batframework-1.0.8a6.dist-info}/LICENCE +0 -0
  44. {batframework-1.0.8a3.dist-info → batframework-1.0.8a6.dist-info}/top_level.txt +0 -0
batFramework/gui/image.py CHANGED
@@ -21,15 +21,22 @@ class Image(Shape):
21
21
 
22
22
  def paint(self) -> None:
23
23
  super().paint()
24
- # self.surface.fill((0,0,0,0 if self.convert_alpha else 255))
25
24
  if self.original_surface is None:
26
25
  return
27
- if self.rect.size != self.original_surface.get_size():
28
- self.surface.blit(
29
- pygame.transform.scale(self.original_surface, self.rect.size), (0, 0)
30
- )
26
+ padded = self.get_padded_rect().move(-self.rect.x,-self.rect.y)
27
+ target_size = padded.size
28
+ if self.original_surface.get_size() != target_size:
29
+ self.surface.blit(pygame.transform.scale(self.original_surface, target_size), padded.topleft)
31
30
  else:
32
- self.surface.blit(self.original_surface, (0, 0))
31
+ self.surface.blit(self.original_surface, padded.topleft)
32
+
33
+ def build(self) -> None:
34
+ if self.original_surface is not None:
35
+ self.set_size_if_autoresize(
36
+ self.inflate_rect_by_padding((0,0,*self.original_surface.get_size())).size
37
+ )
38
+ super().build()
39
+
33
40
 
34
41
  def from_path(self, path: str) -> Self:
35
42
  tmp = bf.ResourceManager().get_image(path, self.convert_alpha)
@@ -37,10 +44,6 @@ class Image(Shape):
37
44
  return self
38
45
  self.original_surface = tmp
39
46
  size = self.original_surface.get_size()
40
- if not self.autoresize_h:
41
- size[0] = None
42
- if not self.autoresize_h:
43
- size[1] = None
44
47
  self.set_size(size)
45
48
  self.dirty_surface = True
46
49
  return self
@@ -50,10 +53,7 @@ class Image(Shape):
50
53
  return self
51
54
  self.original_surface = surface
52
55
  size = self.original_surface.get_size()
53
- if not self.autoresize_h:
54
- size[0] = None
55
- if not self.autoresize_h:
56
- size[1] = None
57
56
  self.set_size(size)
57
+
58
58
  self.dirty_surface = True
59
59
  return self
@@ -8,6 +8,14 @@ if TYPE_CHECKING:
8
8
  from .container import Container
9
9
  import batFramework as bf
10
10
 
11
+ def children_has_focus(widget):
12
+ if isinstance(widget,InteractiveWidget) and widget.is_focused:
13
+ return True
14
+ for child in widget.children:
15
+ if children_has_focus(child):
16
+ return True
17
+ return False
18
+
11
19
 
12
20
  class InteractiveWidget(Widget):
13
21
  def __init__(self, *args, **kwargs) -> None:
@@ -39,6 +47,13 @@ class InteractiveWidget(Widget):
39
47
  return True
40
48
  return False
41
49
 
50
+ def set_parent(self, parent: Widget) -> Self:
51
+ if parent is None and children_has_focus(self):
52
+ self.get_root().clear_focused()
53
+ # pass focus on
54
+
55
+ return super().set_parent(parent)
56
+
42
57
  def on_get_focus(self) -> None:
43
58
  self.is_focused = True
44
59
  self.do_on_get_focus()
@@ -181,6 +196,6 @@ class InteractiveWidget(Widget):
181
196
  pygame.draw.rect(
182
197
  camera.surface,
183
198
  "white",
184
- self.rect.move(-camera.rect.x, -camera.rect.y).inflate(delta, delta),
199
+ self.rect.move(-camera.rect.x, -camera.rect.y),#.inflate(delta, delta),
185
200
  1,
186
201
  )
batFramework/gui/label.py CHANGED
@@ -2,7 +2,7 @@ import batFramework as bf
2
2
  import pygame
3
3
  from .shape import Shape
4
4
  from typing import Self
5
-
5
+ from math import ceil
6
6
 
7
7
  class Label(Shape):
8
8
  _text_cache = {}
@@ -59,7 +59,7 @@ class Label(Shape):
59
59
  Label._text_cache = {}
60
60
 
61
61
  def __str__(self) -> str:
62
- return f"Label({self.text})"
62
+ return f"Label({repr(self.text)})"
63
63
 
64
64
  def enable_caching(self) -> Self:
65
65
  self.do_caching = True
@@ -101,13 +101,20 @@ class Label(Shape):
101
101
  self.dirty_surface = True
102
102
  return self
103
103
 
104
+ def set_text_outline_mask_size(self,size:tuple[int,int])->Self:
105
+ old_size = self._text_outline_mask.get_size()
106
+ m = [[self._text_outline_mask.get_at((x,y)) for x in range(min(old_size[0],size[0]))] for y in range(min(old_size[1],size[1]))]
107
+ self._text_outline_mask = pygame.Mask(size, fill=True)
108
+ self.set_text_outline_matrix(m)
109
+ return self
110
+
104
111
  def set_text_outline_matrix(self, matrix: list[list[0 | 1]]) -> Self:
105
112
  if matrix is None:
106
113
  matrix = [[0 for _ in range(3)] for _ in range(3)]
107
114
  for y in range(3):
108
115
  for x in range(3):
109
116
  self._text_outline_mask.set_at((x, y), matrix[2 - y][2 - x])
110
- self.dirty_surface = True
117
+ self.dirty_shape = True
111
118
  return self
112
119
 
113
120
  def set_text_outline_color(self, color) -> Self:
@@ -117,20 +124,20 @@ class Label(Shape):
117
124
 
118
125
  def enable_text_outline(self) -> Self:
119
126
  self.show_text_outline = True
120
- self.dirty_surface = True
127
+ self.dirty_shape = True
121
128
  return self
122
129
 
123
130
  def disable_text_outline(self) -> Self:
124
131
  self.show_text_outline = False
125
- self.dirty_surface = True
132
+ self.dirty_shape = True
126
133
  return self
127
134
 
128
- def set_alignment(self, alignment: bf.alignment) -> "Label":
135
+ def set_alignment(self, alignment: bf.alignment) -> Self:
129
136
  self.alignment = alignment
130
137
  self.dirty_surface = True
131
138
  return self
132
139
 
133
- def set_auto_wraplength(self, val: bool) -> "Label":
140
+ def set_auto_wraplength(self, val: bool) -> Self:
134
141
  self.auto_wraplength = val
135
142
  if self.autoresize_h or self.autoresize_w:
136
143
  self.dirty_shape = True
@@ -140,7 +147,8 @@ class Label(Shape):
140
147
 
141
148
  def get_debug_outlines(self):
142
149
  if self.visible:
143
- yield (self.text_rect.move(*self.rect.topleft), "purple")
150
+ offset = self._get_outline_offset() if self.show_text_outline else (0,0)
151
+ yield (self.text_rect.move(self.rect.x - offset[0],self.rect.y - offset[1]), "purple")
144
152
  yield from super().get_debug_outlines()
145
153
 
146
154
  def set_font(self, font_name: str = None, force: bool = False) -> Self:
@@ -186,20 +194,10 @@ class Label(Shape):
186
194
  if not (self.autoresize_w or self.autoresize_h):
187
195
  return self.rect.size
188
196
  if not self.text_rect:
189
- params = {
190
- "font_name": self.font_object.name,
191
- "text": self.text,
192
- "antialias": False,
193
- "color": "white",
194
- "bgcolor": "black", # if (self.has_alpha_color() or self.draw_mode == bf.drawMode.TEXTURED) else self.color,
195
- "wraplength": (
196
- int(self.get_padded_width()) if self.auto_wraplength else 0
197
- ),
198
- }
199
-
200
- self.text_rect.size = self._render_font(params).get_size()
197
+ self.text_rect.size = self._get_text_rect_required_size()
201
198
  res = self.inflate_rect_by_padding((0, 0, *self.text_rect.size)).size
202
- # return res
199
+
200
+ return res
203
201
  return res[0] if self.autoresize_w else self.rect.w, (
204
202
  res[1] if self.autoresize_h else self.rect.h
205
203
  )
@@ -242,19 +240,35 @@ class Label(Shape):
242
240
  surf = self.font_object.render(**params)
243
241
 
244
242
  return surf
243
+ def _get_text_rect_required_size(self):
244
+ font_height = self.font_object.get_linesize()
245
+ if not self.text:
246
+ # font_height = self.font_object.get_ascent() - self.font_object.get_ascent()
247
+ size = (0,font_height)
248
+ else:
249
+ tmp_text = self.text
250
+ if self.text.endswith('\n'):
251
+ tmp_text+=" "
252
+ params = {
253
+ "font_name": self.font_object.name,
254
+ "text": tmp_text,
255
+ "antialias": self.antialias,
256
+ "color": self.text_color,
257
+ "bgcolor": None, # if (self.has_alpha_color() or self.draw_mode == bf.drawMode.TEXTURED) else self.color,
258
+ "wraplength": int(self.get_padded_width()) if self.auto_wraplength and not self.autoresize_w else 0,
259
+ }
260
+
261
+ size = self._render_font(params).get_size()
262
+ size = size[0],max(font_height,size[1])
263
+ s = self._get_outline_offset() if self.show_text_outline else (0,0)
264
+ return size[0] + s[0]*2, size[1] + s[1]*2
245
265
 
246
266
  def _build_layout(self) -> None:
247
267
 
248
- params = {
249
- "font_name": self.font_object.name,
250
- "text": self.text,
251
- "antialias": False,
252
- "color": "white",
253
- "bgcolor": "black", # if (self.has_alpha_color() or self.draw_mode == bf.drawMode.TEXTURED) else self.color,
254
- "wraplength": int(self.get_padded_width()) if self.auto_wraplength else 0,
255
- }
268
+ self.text_rect.size = self._get_text_rect_required_size()
269
+ # self.text_rect.w = ceil(self.text_rect.w)
270
+ # self.text_rect.h = ceil(self.text_rect.h)
256
271
 
257
- self.text_rect.size = self._render_font(params).get_size()
258
272
  if self.autoresize_h or self.autoresize_w:
259
273
  target_rect = self.inflate_rect_by_padding((0, 0, *self.text_rect.size))
260
274
  if not self.autoresize_w:
@@ -265,9 +279,14 @@ class Label(Shape):
265
279
  self.set_size(target_rect.size)
266
280
  self.build()
267
281
  return
268
- padded = self.get_padded_rect().move(-self.rect.x, -self.rect.y)
282
+ offset = self._get_outline_offset() if self.show_text_outline else (0,0)
283
+ padded = self.get_padded_rect().move(-self.rect.x + offset[0], -self.rect.y + offset[1])
269
284
  self.align_text(self.text_rect, padded, self.alignment)
270
285
 
286
+ def _get_outline_offset(self)->tuple[int,int]:
287
+ mask_size = self._text_outline_mask.get_size()
288
+ return mask_size[0]//2,mask_size[1]//2
289
+
271
290
  def _paint_text(self) -> None:
272
291
  if self.font_object is None:
273
292
  print(f"No font for widget with text : '{self}' :(")
@@ -279,8 +298,9 @@ class Label(Shape):
279
298
  "antialias": self.antialias,
280
299
  "color": self.text_color,
281
300
  "bgcolor": None, # if (self.has_alpha_color() or self.draw_mode == bf.drawMode.TEXTURED) else self.color,
282
- "wraplength": int(self.get_padded_width()) if self.auto_wraplength else 0,
301
+ "wraplength": int(self.get_padded_width()) if self.auto_wraplength and not self.autoresize_w else 0,
283
302
  }
303
+
284
304
  self.text_surface = self._render_font(params)
285
305
 
286
306
  if self.show_text_outline:
@@ -291,15 +311,15 @@ class Label(Shape):
291
311
  )
292
312
 
293
313
  l = []
314
+ outline_offset = self._get_outline_offset() if self.show_text_outline else (0,0)
315
+
294
316
  if self.show_text_outline:
295
317
  l.append(
296
- (
297
- self.text_outline_surface,
298
- self.text_rect.move(-1, self.relief - self.get_relief() - 1),
299
- )
318
+ (self.text_outline_surface,
319
+ (self.text_rect.x - outline_offset[0],self.text_rect.y - outline_offset[1]))
300
320
  )
301
321
  l.append(
302
- (self.text_surface, self.text_rect.move(0, self.relief - self.get_relief()))
322
+ (self.text_surface, self.text_rect)
303
323
  )
304
324
  self.surface.fblits(l)
305
325
 
@@ -313,6 +333,7 @@ class Label(Shape):
313
333
 
314
334
  pos = area.__getattribute__(alignment.value)
315
335
  text_rect.__setattr__(alignment.value, pos)
336
+ text_rect.y = ceil(text_rect.y)
316
337
 
317
338
  def build(self) -> None:
318
339
  super().build()
@@ -1,14 +1,15 @@
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,override
5
+ from abc import ABC,abstractmethod
5
6
  import pygame
6
7
 
7
8
  if TYPE_CHECKING:
8
9
  from .container import Container
9
10
 
10
11
 
11
- class Layout:
12
+ class Layout(ABC):
12
13
  def __init__(self, parent: "Container" = None):
13
14
  self.parent = parent
14
15
  self.child_constraints: list[Constraint] = []
@@ -48,18 +49,10 @@ class Layout:
48
49
  return target_size
49
50
 
50
51
  def focus_next_child(self) -> None:
51
- l = self.parent.get_interactive_children()
52
- self.parent.focused_index = min(self.parent.focused_index + 1, len(l) - 1)
53
- focused = l[self.parent.focused_index]
54
- focused.get_focus()
55
- self.scroll_to_widget(focused)
52
+ pass
56
53
 
57
54
  def focus_prev_child(self) -> None:
58
- l = self.parent.get_interactive_children()
59
- self.parent.focused_index = max(self.parent.focused_index - 1, 0)
60
- focused = l[self.parent.focused_index]
61
- focused.get_focus()
62
- self.scroll_to_widget(focused)
55
+ pass
63
56
 
64
57
  def scroll_to_widget(self, widget: Widget) -> None:
65
58
  padded = self.parent.get_padded_rect()
@@ -74,7 +67,23 @@ class Layout:
74
67
  pass
75
68
 
76
69
 
77
- class Column(Layout):
70
+ class SingleAxisLayout(Layout):
71
+ def focus_next_child(self) -> None:
72
+ l = self.parent.get_interactive_children()
73
+ self.parent.focused_index = min(self.parent.focused_index + 1, len(l) - 1)
74
+ focused = l[self.parent.focused_index]
75
+ focused.get_focus()
76
+ self.scroll_to_widget(focused)
77
+
78
+ def focus_prev_child(self) -> None:
79
+ l = self.parent.get_interactive_children()
80
+ self.parent.focused_index = max(self.parent.focused_index - 1, 0)
81
+ focused = l[self.parent.focused_index]
82
+ focused.get_focus()
83
+ self.scroll_to_widget(focused)
84
+
85
+
86
+ class Column(SingleAxisLayout):
78
87
  def __init__(self, gap: int = 0, spacing: bf.spacing = bf.spacing.MANUAL):
79
88
  super().__init__()
80
89
  self.gap = gap
@@ -157,7 +166,7 @@ class Column(Layout):
157
166
  self.parent.clamp_scroll()
158
167
 
159
168
 
160
- class Row(Layout):
169
+ class Row(SingleAxisLayout):
161
170
  def __init__(self, gap: int = 0, spacing: bf.spacing = bf.spacing.MANUAL):
162
171
  super().__init__()
163
172
  self.gap = gap
batFramework/gui/meter.py CHANGED
@@ -17,9 +17,11 @@ class Meter(Shape):
17
17
  self.snap: bool = False
18
18
  self.value = self.max_value
19
19
  self.content = Shape((0, 0)).set_color(bf.color.BLUE)
20
+ self.content.set_debug_color("cyan")
20
21
  self.content.top_at = lambda x, y: custom_top_at(self.content, x, y)
21
22
  self.add(self.content)
22
- self.set_padding(1)
23
+ self.set_padding(4)
24
+ self.set_color("gray20")
23
25
  self.set_outline_width(1)
24
26
  self.set_outline_color(bf.color.BLACK)
25
27
  self.set_debug_color("pink")
@@ -38,18 +40,19 @@ class Meter(Shape):
38
40
  f"[Warning] : minimum value {range_min} is greater than or equal to maximum value {range_max}"
39
41
  )
40
42
  return self
41
- self.min_value, self.max_value = range_min, range_max
43
+ self.min_value = range_min
44
+ self.max_value = range_max
42
45
  self.dirty_shape = True
43
46
 
44
47
  def get_debug_outlines(self):
45
48
  yield from super().get_debug_outlines()
46
- yield from self.content.get_debug_outlines()
49
+ # yield from self.content.get_debug_outlines()
47
50
 
48
51
  def set_value(self, value: float) -> Self:
49
52
  value = max(self.min_value, min(self.max_value, value))
50
53
  value = round(value / self.step) * self.step
51
- self.value = value
52
- self.dirty_surface = True
54
+ self.value = round(value,10)
55
+ self.dirty_shape = True
53
56
  return self
54
57
 
55
58
  def get_value(self) -> float:
@@ -59,12 +62,12 @@ class Meter(Shape):
59
62
  return self.max_value - self.min_value
60
63
 
61
64
  def get_ratio(self) -> float:
62
- return self.value / (self.max_value - self.min_value)
65
+ return (self.value-self.min_value) / (self.max_value - self.min_value)
63
66
 
64
67
  def _build_content(self) -> None:
65
68
  width = self.get_padded_width() * self.get_ratio()
66
69
  self.content.set_size((width, self.get_padded_height()))
67
- self.content.set_position(*self.get_padded_rect().topleft)
70
+ self.content.rect.topleft = self.get_padded_rect().topleft
68
71
 
69
72
  def build(self) -> None:
70
73
  super().build()
@@ -7,7 +7,7 @@ class RadioVariable: ...
7
7
 
8
8
 
9
9
  class RadioButton(Toggle):
10
- def __init__(self, text: str, radio_value: Any = None) -> None:
10
+ def __init__(self, text: str = "", radio_value: Any = None) -> None:
11
11
  super().__init__(text, None, False)
12
12
  self.radio_value: Any = (
13
13
  radio_value if radio_value is not None else text if text else None
batFramework/gui/root.py CHANGED
@@ -95,6 +95,8 @@ class Root(InteractiveWidget):
95
95
  return self
96
96
 
97
97
  def do_handle_event(self, event):
98
+ if not self.parent_scene.get_sharedVar("player_has_control"):
99
+ return
98
100
  if self.focused:
99
101
  if event.type == pygame.KEYDOWN:
100
102
  if self.focused.on_key_down(event.key):
@@ -128,6 +130,8 @@ class Root(InteractiveWidget):
128
130
 
129
131
  def update(self, dt: float) -> None:
130
132
  super().update(dt)
133
+ if not self.parent_scene.get_sharedVar("player_has_control",True):
134
+ return
131
135
  old = self.hovered
132
136
  transposed = self.drawing_camera.screen_to_world(pygame.mouse.get_pos())
133
137
  self.hovered = self.top_at(*transposed) if self.top_at(*transposed) else None
@@ -139,8 +143,10 @@ class Root(InteractiveWidget):
139
143
  if self.hovered and isinstance(self.hovered, InteractiveWidget):
140
144
  self.hovered.on_enter()
141
145
 
142
- def draw(self, camera: bf.Camera) -> int:
146
+ def draw(self, camera: bf.Camera) -> None:
143
147
  super().draw(camera)
148
+ if not self.parent_scene.get_sharedVar("player_has_control"):
149
+ return
144
150
  if (
145
151
  self.parent_scene
146
152
  and self.parent_scene.active
batFramework/gui/shape.py CHANGED
@@ -10,7 +10,7 @@ class Shape(Widget):
10
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
- self.outline: int = 0
13
+ self.outline_width: int = 0
14
14
  self.outline_color: tuple[int, int, int] | str = (0, 0, 0, 255)
15
15
  self.texture_surface = None
16
16
  self.texture_subsize = (0, 0)
@@ -43,15 +43,10 @@ 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:
47
- return self
46
+ self.dirty_shape = self.relief != relief
48
47
  self.relief = relief
49
- self.dirty_shape = True
50
48
  return self
51
49
 
52
- def get_relief(self) -> int:
53
- return self.relief
54
-
55
50
  def set_texture(
56
51
  self, surface: pygame.SurfaceType, subsize: tuple[int, int] | None = None
57
52
  ) -> Self:
@@ -97,7 +92,7 @@ class Shape(Widget):
97
92
  return self
98
93
 
99
94
  def set_outline_width(self, value: int) -> Self:
100
- self.outline = value
95
+ self.outline_width = value
101
96
  self.dirty_surface = True
102
97
  return self
103
98
 
@@ -107,11 +102,11 @@ class Shape(Widget):
107
102
  return
108
103
  if self.border_radius == [0]:
109
104
  self._paint_shape()
110
- if self.outline:
105
+ if self.outline_width:
111
106
  self._paint_outline()
112
107
  else:
113
108
  self._paint_rounded_shape()
114
- if self.outline:
109
+ if self.outline_width:
115
110
  self._paint_rounded_outline()
116
111
 
117
112
  def _paint_textured(self) -> None:
@@ -224,40 +219,29 @@ class Shape(Widget):
224
219
 
225
220
  def _paint_shape(self) -> None:
226
221
  self.surface.fill((0, 0, 0, 0))
227
- self.surface.fill(self.shadow_color, self._get_base_rect())
228
- self.surface.fill(self.color, self._get_elevated_rect())
222
+ if self.relief!=0:
223
+ self.surface.fill(self.shadow_color, self._get_base_rect())
224
+ self.surface.fill(self.color, self._get_elevated_rect())
225
+ else:
226
+ self.surface.fill(self.color, self._get_elevated_rect())
229
227
 
230
228
  def _paint_rounded_shape(self) -> None:
231
229
  self.surface.fill((0, 0, 0, 0))
232
230
  e = self._get_elevated_rect()
233
- b = e.copy()
234
- b.bottom = self.rect.h
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)
231
+ if self.relief != 0:
232
+ b = e.copy()
233
+ b.bottom = self.rect.h
234
+ pygame.draw.rect(self.surface, self.shadow_color, b, 0, *self.border_radius)
235
+ pygame.draw.rect(self.surface, self.color, e, 0, *self.border_radius)
236
+ else:
237
+ pygame.draw.rect(self.surface, self.color, e, 0, *self.border_radius)
237
238
 
238
239
  def _paint_outline(self) -> None:
239
- if self.relief:
240
- pygame.draw.rect(
241
- self.surface,
242
- self.outline_color,
243
- (
244
- 0,
245
- self.relief - self.get_relief(),
246
- self.rect.w,
247
- self.rect.h - self.relief,
248
- ),
249
- self.outline,
250
- )
251
240
  pygame.draw.rect(
252
241
  self.surface,
253
242
  self.outline_color,
254
- (
255
- 0,
256
- self.relief - self.get_relief(),
257
- self.rect.w,
258
- self.rect.h - (self.relief - self.get_relief()),
259
- ),
260
- self.outline,
243
+ self._get_elevated_rect(),
244
+ self.outline_width,
261
245
  )
262
246
 
263
247
  def _paint_rounded_outline(self) -> None:
@@ -269,7 +253,7 @@ class Shape(Widget):
269
253
  self.surface,
270
254
  self.outline_color,
271
255
  e,
272
- self.outline,
256
+ self.outline_width,
273
257
  *self.border_radius,
274
258
  )
275
259
  if self.relief:
@@ -277,6 +261,6 @@ class Shape(Widget):
277
261
  self.surface,
278
262
  self.outline_color,
279
263
  b,
280
- self.outline,
264
+ self.outline_width,
281
265
  *self.border_radius,
282
266
  )