batframework 1.0.9a10__py3-none-any.whl → 1.1.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 (76) hide show
  1. batFramework/__init__.py +52 -76
  2. batFramework/action.py +99 -126
  3. batFramework/actionContainer.py +9 -53
  4. batFramework/animatedSprite.py +114 -56
  5. batFramework/audioManager.py +36 -82
  6. batFramework/camera.py +69 -263
  7. batFramework/constants.py +53 -29
  8. batFramework/cutscene.py +109 -243
  9. batFramework/cutsceneBlocks.py +176 -0
  10. batFramework/debugger.py +48 -0
  11. batFramework/dynamicEntity.py +9 -16
  12. batFramework/easing.py +71 -0
  13. batFramework/entity.py +85 -92
  14. batFramework/gui/__init__.py +3 -14
  15. batFramework/gui/button.py +78 -12
  16. batFramework/gui/constraints.py +204 -0
  17. batFramework/gui/container.py +31 -183
  18. batFramework/gui/debugger.py +43 -126
  19. batFramework/gui/frame.py +19 -0
  20. batFramework/gui/image.py +20 -55
  21. batFramework/gui/indicator.py +22 -95
  22. batFramework/gui/interactiveWidget.py +12 -229
  23. batFramework/gui/label.py +77 -311
  24. batFramework/gui/layout.py +66 -411
  25. batFramework/gui/root.py +35 -203
  26. batFramework/gui/shape.py +57 -247
  27. batFramework/gui/toggle.py +48 -114
  28. batFramework/gui/widget.py +243 -457
  29. batFramework/manager.py +29 -113
  30. batFramework/particles.py +77 -0
  31. batFramework/scene.py +217 -22
  32. batFramework/sceneManager.py +129 -161
  33. batFramework/stateMachine.py +8 -11
  34. batFramework/time.py +75 -0
  35. batFramework/transition.py +124 -129
  36. batFramework/transitionManager.py +0 -0
  37. batFramework/triggerZone.py +4 -4
  38. batFramework/utils.py +144 -266
  39. {batframework-1.0.9a10.dist-info → batframework-1.1.0.dist-info}/METADATA +24 -22
  40. batframework-1.1.0.dist-info/RECORD +43 -0
  41. batFramework/animation.py +0 -77
  42. batFramework/baseScene.py +0 -240
  43. batFramework/cutsceneManager.py +0 -34
  44. batFramework/drawable.py +0 -77
  45. batFramework/easingController.py +0 -58
  46. batFramework/enums.py +0 -135
  47. batFramework/fontManager.py +0 -65
  48. batFramework/gui/animatedLabel.py +0 -89
  49. batFramework/gui/clickableWidget.py +0 -245
  50. batFramework/gui/constraints/__init__.py +0 -1
  51. batFramework/gui/constraints/constraints.py +0 -980
  52. batFramework/gui/draggableWidget.py +0 -44
  53. batFramework/gui/meter.py +0 -96
  54. batFramework/gui/radioButton.py +0 -35
  55. batFramework/gui/selector.py +0 -250
  56. batFramework/gui/slider.py +0 -397
  57. batFramework/gui/style.py +0 -10
  58. batFramework/gui/styleManager.py +0 -54
  59. batFramework/gui/syncedVar.py +0 -49
  60. batFramework/gui/textInput.py +0 -306
  61. batFramework/gui/tooltip.py +0 -30
  62. batFramework/particle.py +0 -118
  63. batFramework/propertyEaser.py +0 -79
  64. batFramework/renderGroup.py +0 -34
  65. batFramework/resourceManager.py +0 -130
  66. batFramework/sceneLayer.py +0 -138
  67. batFramework/scrollingSprite.py +0 -115
  68. batFramework/sprite.py +0 -51
  69. batFramework/templates/__init__.py +0 -1
  70. batFramework/templates/controller.py +0 -97
  71. batFramework/tileset.py +0 -46
  72. batFramework/timeManager.py +0 -213
  73. batframework-1.0.9a10.dist-info/RECORD +0 -67
  74. {batframework-1.0.9a10.dist-info → batframework-1.1.0.dist-info}/LICENSE +0 -0
  75. {batframework-1.0.9a10.dist-info → batframework-1.1.0.dist-info}/WHEEL +0 -0
  76. {batframework-1.0.9a10.dist-info → batframework-1.1.0.dist-info}/top_level.txt +0 -0
@@ -1,426 +1,81 @@
1
1
  import batFramework as bf
2
2
  from .widget import Widget
3
- from .constraints.constraints import *
4
- from typing import Self, TYPE_CHECKING
5
- from abc import ABC,abstractmethod
6
- import pygame
7
- from .interactiveWidget import InteractiveWidget
3
+ from .constraints import *
4
+ from typing import Self
8
5
 
9
- if TYPE_CHECKING:
10
- from .container import Container
11
-
12
-
13
- class Layout(ABC):
14
- def __init__(self, parent: "Container" = None):
6
+ class Layout:
7
+ def __init__(self, parent: Widget=None):
15
8
  self.parent = parent
16
- self.child_constraints: list[Constraint] = []
17
- self.children_rect = pygame.FRect(0, 0, 0, 0)
18
-
19
- def get_free_space(self)->tuple[float,float]:
20
- """
21
- return the space available for Growing widgets to use
22
- """
23
- return self.parent.get_inner_rect()
24
-
25
- def set_child_constraints(self, *constraints) -> Self:
26
- self.child_constraints = list(constraints)
27
- self.update_child_constraints()
28
- self.notify_parent()
9
+ self.child_constraints : list[Constraint] = []
10
+
11
+ def set_child_constraints(self,*constraints)->Self:
12
+ self.child_constraints = constraints
13
+ self.arrange()
29
14
  return self
30
-
31
- def set_parent(self, parent: Widget):
32
- self.parent = parent
33
- self.notify_parent()
34
-
35
- def notify_parent(self) -> None:
36
- if self.parent:
37
- self.parent.dirty_layout = True
38
-
39
- def update_children_rect(self):
40
- if self.parent.get_layout_children():
41
- self.children_rect = pygame.FRect(*self.parent.get_inner_rect().topleft,*self.parent.get_layout_children()[0].get_min_required_size())
42
-
43
- self.children_rect.unionall(
44
- [pygame.FRect(0,0,*c.get_min_required_size()) for c in self.parent.get_layout_children()[1:]]
45
- )
46
- else:
47
- self.children_rect = pygame.FRect(*self.parent.get_inner_rect().topleft, 0, 0)
48
- self.children_rect.move_ip(-self.parent.scroll.x,-self.parent.scroll.y)
49
-
50
- def update_child_constraints(self):
51
- if self.parent:
52
- for child in self.parent.get_layout_children():
53
- child.add_constraints(*self.child_constraints)
54
-
55
- def arrange(self) -> None:
56
- """
57
- updates the position of children in the parent
58
- """
59
- return
60
-
61
- def get_raw_size(self):
62
- """
63
- Returns the size the container should have to encapsulate perfectly all of its widgets
64
- """
65
- # print(self,self.parent,len(self.parent.get_layout_children()))
66
- self.update_children_rect()
67
- return self.children_rect.size
68
-
69
- def get_auto_size(self) -> tuple[float, float]:
70
- """
71
- Returns the final size the container should have (while keeping the width and height if they are non-resizable)
72
- """
73
- target_size = list(self.get_raw_size())
74
- if not self.parent.autoresize_w:
75
- target_size[0] = self.parent.get_inner_width()
76
- if not self.parent.autoresize_h:
77
- target_size[1] = self.parent.get_inner_height()
78
15
 
79
- return self.parent.expand_rect_with_padding((0,0,*target_size)).size
80
- # return target_size
81
-
82
- def scroll_to_widget(self, widget: "Widget"):
83
- """
84
- Scrolls parent containers so that the widget becomes visible.
85
- Handles deeply nested widgets and large widgets gracefully.
86
- """
87
- target = widget
88
- container = self.parent
89
-
90
- while container and not container.is_root:
91
- target_rect = target.rect # global
92
- padded_rect = container.get_inner_rect() # global
93
-
94
- dx = dy = 0
95
-
96
- # --- Horizontal ---
97
- if target_rect.width <= padded_rect.width:
98
- if target_rect.left < padded_rect.left:
99
- dx = target_rect.left - padded_rect.left
100
- elif target_rect.right > padded_rect.right:
101
- dx = target_rect.right - padded_rect.right
102
- else:
103
- # Widget is wider than viewport: align left side
104
- if target_rect.left < padded_rect.left:
105
- dx = target_rect.left - padded_rect.left
106
- elif target_rect.right > padded_rect.right:
107
- dx = target_rect.right - padded_rect.right
108
-
109
- # --- Vertical ---
110
- if target_rect.height <= padded_rect.height:
111
- if target_rect.top < padded_rect.top:
112
- dy = target_rect.top - padded_rect.top
113
- elif target_rect.bottom > padded_rect.bottom:
114
- dy = target_rect.bottom - padded_rect.bottom
115
- else:
116
- # Widget is taller than viewport: align top side
117
- if target_rect.top < padded_rect.top:
118
- dy = target_rect.top - padded_rect.top
119
- elif target_rect.bottom > padded_rect.bottom:
120
- dy = target_rect.bottom - padded_rect.bottom
121
-
122
- # Convert global delta into local scroll delta for container
123
- container.scroll_by((dx, dy))
124
-
125
- # Now the target for the next iteration is the container itself
126
- target = container
127
- container = container.parent
128
-
129
-
130
- def handle_event(self, event):
131
- pass
132
-
133
- class FreeLayout(Layout):...
134
-
135
- class SingleAxisLayout(Layout):
136
-
137
- def __init__(self, parent = None):
138
- super().__init__(parent)
139
-
140
- def focus_next_child(self) -> None:
141
- l = self.parent.get_interactive_children()
142
- self.parent.focused_index = min(self.parent.focused_index + 1, len(l) - 1)
143
- focused = l[self.parent.focused_index]
144
- focused.get_focus()
145
-
146
- def focus_prev_child(self) -> None:
147
- l = self.parent.get_interactive_children()
148
- self.parent.focused_index = max(self.parent.focused_index - 1, 0)
149
- focused = l[self.parent.focused_index]
150
- focused.get_focus()
151
-
152
-
153
- class DoubleAxisLayout(Layout):
154
- """Abstract layout class for layouts that arrange widgets in two dimensions."""
155
-
156
- def focus_up_child(self) -> None:...
157
- def focus_down_child(self) -> None:...
158
- def focus_right_child(self) -> None:...
159
- def focus_left_child(self) -> None:...
160
-
161
-
162
- class Column(SingleAxisLayout):
163
- def __init__(self, gap: int = 0):
164
- super().__init__()
165
- self.gap = gap
166
-
167
- def update_children_rect(self):
168
- if self.parent.get_layout_children():
169
- width = max(child.get_min_required_size()[0] for child in self.parent.get_layout_children() )
170
- height = sum(child.get_min_required_size()[1] for child in self.parent.get_layout_children()) + self.gap * (len(self.parent.get_layout_children()) - 1)
171
-
172
- # width = max(child.rect.w for child in self.parent.get_layout_children() )
173
- # height = sum(child.rect.h for child in self.parent.get_layout_children()) + self.gap * (len(self.parent.get_layout_children()) - 1)
174
-
175
-
176
- self.children_rect = pygame.FRect(*self.parent.get_inner_rect().topleft, width, height)
177
- else:
178
- self.children_rect = pygame.FRect(*self.parent.get_inner_rect().topleft, 10, 10)
179
- self.children_rect.move_ip(-self.parent.scroll.x,-self.parent.scroll.y)
180
-
181
- def handle_event(self, event):
182
- if not self.parent.get_layout_children() or not self.parent.children_has_focus():
183
- return
184
-
185
- if event.type == pygame.KEYDOWN:
186
- if event.key in (pygame.K_DOWN, pygame.K_UP):
187
- self.focus_next_child() if event.key == pygame.K_DOWN else self.focus_prev_child()
188
- event.consumed = True
189
- event.consumed = True
190
-
16
+ def set_parent(self,parent:Widget):
17
+ self.parent = parent
18
+ self.arrange()
191
19
 
192
- def arrange(self) -> None:
193
- self.update_children_rect()
194
- y = self.children_rect.y
195
- for child in self.parent.get_layout_children():
196
- child.set_position(self.children_rect.x, y)
197
- y += child.rect.height + self.gap
20
+ def arrange(self)->None:
21
+ raise NotImplementedError("Subclasses must implement arrange method")
198
22
 
199
- class Row(SingleAxisLayout):
200
- def __init__(self, gap: int = 0):
23
+ class Column(Layout):
24
+ def __init__(self,gap:int=0,shrink:bool=False):
201
25
  super().__init__()
202
26
  self.gap = gap
203
-
204
- def update_children_rect(self):
205
- if self.parent.get_layout_children():
206
- height = max(child.get_min_required_size()[1] for child in self.parent.get_layout_children())
207
- width = sum(child.get_min_required_size()[0] for child in self.parent.get_layout_children()) + self.gap * (len(self.parent.get_layout_children()) - 1)
208
- self.children_rect = pygame.FRect(*self.parent.get_inner_rect().topleft, width, height)
209
- else:
210
- self.children_rect = pygame.FRect(*self.parent.get_inner_rect().topleft, 10,10)
211
- self.children_rect.move_ip(-self.parent.scroll.x,-self.parent.scroll.y)
212
-
213
- def handle_event(self, event):
214
- if not self.parent.get_layout_children() or not self.parent.children_has_focus():
215
- return
216
-
217
- if event.type == pygame.KEYDOWN:
218
- if event.key in (pygame.K_RIGHT, pygame.K_LEFT):
219
- self.focus_next_child() if event.key == pygame.K_RIGHT else self.focus_prev_child()
220
- event.consumed = True
221
-
222
-
223
- def arrange(self) -> None:
224
- self.update_children_rect()
225
- x = self.children_rect.x
226
- for child in self.parent.get_layout_children():
227
- child.set_position(x,self.children_rect.y)
228
- x += child.rect.width + self.gap
229
-
230
-
231
-
232
- class RowFill(Row):
233
-
234
- def update_children_rect(self):
235
- parent_width = self.parent.get_inner_width()
236
- if self.parent.get_layout_children():
237
- height = max(child.get_min_required_size()[1] for child in self.parent.get_layout_children())
238
- width = parent_width
239
- self.children_rect = pygame.FRect(*self.parent.get_inner_rect().topleft, width, height)
240
- else:
241
- self.children_rect = pygame.FRect(*self.parent.get_inner_rect().topleft, parent_width,10)
242
- self.children_rect.move_ip(-self.parent.scroll.x,-self.parent.scroll.y)
243
-
244
-
245
- def arrange(self) -> None:
246
- """
247
- Arranges children in a row and resizes them to fill the parent's height,
248
- accounting for the gap between children.
249
- """
250
- self.update_children_rect()
251
- for child in self.parent.get_layout_children():
252
- child.set_autoresize_w(False)
253
- x = self.children_rect.x
254
- # available_height = self.children_rect.height
255
-
256
- # Calculate the width available for each child
257
- total_gap = self.gap * (len(self.parent.get_layout_children()) - 1)
258
- available_width = max(0, self.children_rect.width - total_gap)
259
- child_width = available_width / len(self.parent.get_layout_children()) if self.parent.get_layout_children() else 0
260
-
261
- for child in self.parent.get_layout_children():
262
- child.set_size((child_width, None)) # Resize child to fill height
263
- child.set_position(x, self.children_rect.y) # Position child
264
- x += child_width + self.gap
265
-
266
-
267
- class ColumnFill(Column):
268
-
269
- def update_children_rect(self):
270
- parent_height = self.parent.get_inner_height()
271
- if self.parent.get_layout_children():
272
- width = max(child.get_min_required_size()[0] for child in self.parent.get_layout_children())
273
- height = parent_height
274
- self.children_rect = pygame.FRect(*self.parent.get_inner_rect().topleft, width, height)
275
- else:
276
- self.children_rect = pygame.FRect(*self.parent.get_inner_rect().topleft, 10, parent_height)
277
- self.children_rect.move_ip(-self.parent.scroll.x, -self.parent.scroll.y)
278
-
279
- def arrange(self) -> None:
280
- """
281
- Arranges children in a column and resizes them to fill the parent's width,
282
- accounting for the gap between children.
283
- """
284
- self.update_children_rect()
285
- for child in self.parent.get_layout_children():
286
- child.set_autoresize_h(False)
287
- y = self.children_rect.y
288
-
289
- # Calculate the height available for each child
290
- total_gap = self.gap * (len(self.parent.get_layout_children()) - 1)
291
- available_height = max(0, self.children_rect.height - total_gap)
292
- child_height = available_height / len(self.parent.get_layout_children()) if self.parent.get_layout_children() else 0
293
-
294
- for child in self.parent.get_layout_children():
295
- child.set_size((None, child_height)) # Resize child to fill width
296
- child.set_position(self.children_rect.x, y) # Position child
297
- y += child_height + self.gap
298
-
299
-
300
- class Grid(DoubleAxisLayout):
301
- def __init__(self, rows: int, cols: int, gap: int = 0):
27
+ self.shrink :bool = shrink
28
+
29
+ def arrange(self)->None:
30
+ if not self.parent or not self.parent.children : return
31
+ if self.shrink:
32
+ len_children = len(self.parent.children)
33
+ parent_height = sum(c.rect.h for c in self.parent.children)
34
+ parent_width = max(c.rect.w for c in self.parent.children)
35
+ if self.gap : parent_height += (len_children-1) * self.gap
36
+ # print(self.parent.to_string(),len_children,parent_height)
37
+ c = self.parent.get_constraint("height")
38
+ if not c or c.height != parent_height :
39
+ self.parent.add_constraint(ConstraintHeight(parent_height))
40
+ c = self.parent.get_constraint("width")
41
+ if not c or c.width != parent_width :
42
+ self.parent.add_constraint(ConstraintWidth(parent_width))
43
+ current_y = self.parent.rect.top
44
+
45
+ for child in self.parent.children:
46
+ child.set_position(self.parent.rect.x,current_y)
47
+ current_y += child.rect.h + self.gap
48
+ for c in self.child_constraints:
49
+ if not child.has_constraint(c.name):
50
+ child.add_constraint(c)
51
+
52
+ class Row(Layout):
53
+ def __init__(self, gap: int = 0, shrink: bool = False):
302
54
  super().__init__()
303
- self.rows = rows
304
- self.cols = cols
305
55
  self.gap = gap
56
+ self.shrink = shrink
306
57
 
307
- def focus_up_child(self) -> None:
308
- l = self.parent.get_interactive_children()
309
- if not l:
310
- return
311
- current_index = self.parent.focused_index
312
- if current_index == -1:
313
- return
314
- current_row = current_index // self.cols
315
- target_index = max(0, current_index - self.cols)
316
- if target_index // self.cols < current_row:
317
- self.parent.focused_index = target_index
318
- l[target_index].get_focus()
319
-
320
- def focus_down_child(self) -> None:
321
- l = self.parent.get_interactive_children()
322
- if not l:
323
- return
324
- current_index = self.parent.focused_index
325
- if current_index == -1:
326
- return
327
- current_row = current_index // self.cols
328
- target_index = min(len(l) - 1, current_index + self.cols)
329
- if target_index // self.cols > current_row:
330
- self.parent.focused_index = target_index
331
- l[target_index].get_focus()
332
-
333
- def focus_left_child(self) -> None:
334
- l = self.parent.get_interactive_children()
335
- if not l:
336
- return
337
- current_index = self.parent.focused_index
338
- if current_index == -1:
339
- return
340
- target_index = max(0, current_index - 1)
341
- if target_index // self.cols == current_index // self.cols:
342
- self.parent.focused_index = target_index
343
- l[target_index].get_focus()
344
-
345
- def focus_right_child(self) -> None:
346
- l = self.parent.get_interactive_children()
347
- if not l:
348
- return
349
- current_index = self.parent.focused_index
350
- if current_index == -1:
351
- return
352
- target_index = min(len(l) - 1, current_index + 1)
353
- if target_index // self.cols == current_index // self.cols:
354
- self.parent.focused_index = target_index
355
- l[target_index].get_focus()
356
-
357
- def handle_event(self, event):
358
- if not self.parent.get_layout_children() or not self.parent.children_has_focus():
359
- return
360
-
361
- if event.type == pygame.KEYDOWN:
362
- if event.key in (pygame.K_RIGHT, pygame.K_LEFT, pygame.K_UP, pygame.K_DOWN):
363
- if event.key == pygame.K_RIGHT:
364
- self.focus_right_child()
365
- elif event.key == pygame.K_LEFT:
366
- self.focus_left_child()
367
- elif event.key == pygame.K_UP:
368
- self.focus_up_child()
369
- elif event.key == pygame.K_DOWN:
370
- self.focus_down_child()
371
-
372
- event.consumed = True
373
-
374
- def update_children_rect(self):
375
- if self.parent.get_layout_children():
376
- cell_width = max(child.get_min_required_size()[0] for child in self.parent.get_layout_children())
377
- cell_height = max(child.get_min_required_size()[1] for child in self.parent.get_layout_children())
378
- width = self.cols * cell_width + self.gap * (self.cols - 1)
379
- height = self.rows * cell_height + self.gap * (self.rows - 1)
380
- self.children_rect = pygame.FRect(*self.parent.get_inner_rect().topleft, width, height)
381
- else:
382
- self.children_rect = pygame.FRect(*self.parent.get_inner_rect().topleft, 10, 10)
383
- self.children_rect.move_ip(-self.parent.scroll.x, -self.parent.scroll.y)
384
-
385
- def arrange(self) -> None:
386
- self.update_children_rect()
387
- if not self.parent.get_layout_children():
388
- return
389
-
390
- cell_width = (self.children_rect.width - self.gap * (self.cols - 1)) / self.cols
391
- cell_height = (self.children_rect.height - self.gap * (self.rows - 1)) / self.rows
392
-
393
- for i, child in enumerate(self.parent.get_layout_children()):
394
- row = i // self.cols
395
- col = i % self.cols
396
- x = self.children_rect.x + col * (cell_width + self.gap)
397
- y = self.children_rect.y + row * (cell_height + self.gap)
398
- child.set_size((cell_width, cell_height))
399
- child.set_position(x, y)
400
-
401
-
402
- class GridFill(Grid):
403
- def update_children_rect(self):
404
- self.children_rect = self.parent.get_inner_rect()
405
58
  def arrange(self) -> None:
406
- """
407
- Arranges children in a grid and resizes them to fill the parent's available space,
408
- accounting for the gap between children.
409
- """
410
- self.update_children_rect()
411
-
412
- if not self.parent.get_layout_children():
59
+ if not self.parent:
413
60
  return
414
- for child in self.parent.get_layout_children():
415
- child.set_autoresize(False)
416
-
417
- cell_width = (self.children_rect.width - self.gap * (self.cols - 1)) / self.cols
418
- cell_height = (self.children_rect.height - self.gap * (self.rows - 1)) / self.rows
419
-
420
- for i, child in enumerate(self.parent.get_layout_children()):
421
- row = i // self.cols
422
- col = i % self.cols
423
- x = self.children_rect.x + col * (cell_width + self.gap)
424
- y = self.children_rect.y + row * (cell_height + self.gap)
425
- child.set_size((cell_width, cell_height))
426
- child.set_position(x, y)
61
+ if self.shrink and self.parent.children:
62
+ len_children = len(self.parent.children)
63
+ parent_width = sum(c.rect.w for c in self.parent.children)
64
+ parent_height = max(c.rect.h for c in self.parent.children)
65
+ if self.gap:
66
+ parent_width += (len_children - 1) * self.gap
67
+
68
+ c = self.parent.get_constraint("width")
69
+ if not c or c.width != parent_width:
70
+ self.parent.add_constraint(ConstraintWidth(parent_width))
71
+ c = self.parent.get_constraint("height")
72
+ if not c or c.height != parent_height:
73
+ self.parent.add_constraint(ConstraintHeight(parent_height))
74
+
75
+ current_x = self.parent.rect.left
76
+ for child in self.parent.children:
77
+ child.set_position(current_x,self.parent.rect.y)
78
+ current_x += child.rect.w + self.gap
79
+ for c in self.child_constraints:
80
+ if not child.has_constraint(c.name):
81
+ child.add_constraint(c)