batframework 1.0.9a11__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 -188
  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 -414
  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.9a11.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 -244
  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.9a11.dist-info/RECORD +0 -67
  74. {batframework-1.0.9a11.dist-info → batframework-1.1.0.dist-info}/LICENSE +0 -0
  75. {batframework-1.0.9a11.dist-info → batframework-1.1.0.dist-info}/WHEEL +0 -0
  76. {batframework-1.0.9a11.dist-info → batframework-1.1.0.dist-info}/top_level.txt +0 -0
@@ -1,429 +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
- if not hasattr(container,"scroll"):
92
- container = container.parent
93
- continue
94
- target_rect = target.rect # global
95
- padded_rect = container.get_inner_rect() # global
96
-
97
- dx = dy = 0
98
-
99
- # --- Horizontal ---
100
- if target_rect.width <= padded_rect.width:
101
- if target_rect.left < padded_rect.left:
102
- dx = target_rect.left - padded_rect.left
103
- elif target_rect.right > padded_rect.right:
104
- dx = target_rect.right - padded_rect.right
105
- else:
106
- # Widget is wider than viewport: align left side
107
- if target_rect.left < padded_rect.left:
108
- dx = target_rect.left - padded_rect.left
109
- elif target_rect.right > padded_rect.right:
110
- dx = target_rect.right - padded_rect.right
111
-
112
- # --- Vertical ---
113
- if target_rect.height <= padded_rect.height:
114
- if target_rect.top < padded_rect.top:
115
- dy = target_rect.top - padded_rect.top
116
- elif target_rect.bottom > padded_rect.bottom:
117
- dy = target_rect.bottom - padded_rect.bottom
118
- else:
119
- # Widget is taller than viewport: align top side
120
- if target_rect.top < padded_rect.top:
121
- dy = target_rect.top - padded_rect.top
122
- elif target_rect.bottom > padded_rect.bottom:
123
- dy = target_rect.bottom - padded_rect.bottom
124
-
125
- # Convert global delta into local scroll delta for container
126
- container.scroll_by((dx, dy))
127
-
128
- # Now the target for the next iteration is the container itself
129
- target = container
130
- container = container.parent
131
-
132
-
133
- def handle_event(self, event):
134
- pass
135
-
136
- class FreeLayout(Layout):...
137
-
138
- class SingleAxisLayout(Layout):
139
-
140
- def __init__(self, parent = None):
141
- super().__init__(parent)
142
-
143
- def focus_next_child(self) -> None:
144
- l = self.parent.get_interactive_children()
145
- self.parent.focused_index = min(self.parent.focused_index + 1, len(l) - 1)
146
- focused = l[self.parent.focused_index]
147
- focused.get_focus()
148
-
149
- def focus_prev_child(self) -> None:
150
- l = self.parent.get_interactive_children()
151
- self.parent.focused_index = max(self.parent.focused_index - 1, 0)
152
- focused = l[self.parent.focused_index]
153
- focused.get_focus()
154
-
155
-
156
- class DoubleAxisLayout(Layout):
157
- """Abstract layout class for layouts that arrange widgets in two dimensions."""
158
-
159
- def focus_up_child(self) -> None:...
160
- def focus_down_child(self) -> None:...
161
- def focus_right_child(self) -> None:...
162
- def focus_left_child(self) -> None:...
163
-
164
-
165
- class Column(SingleAxisLayout):
166
- def __init__(self, gap: int = 0):
167
- super().__init__()
168
- self.gap = gap
169
-
170
- def update_children_rect(self):
171
- if self.parent.get_layout_children():
172
- width = max(child.get_min_required_size()[0] for child in self.parent.get_layout_children() )
173
- 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)
174
-
175
- # width = max(child.rect.w for child in self.parent.get_layout_children() )
176
- # height = sum(child.rect.h for child in self.parent.get_layout_children()) + self.gap * (len(self.parent.get_layout_children()) - 1)
177
-
178
-
179
- self.children_rect = pygame.FRect(*self.parent.get_inner_rect().topleft, width, height)
180
- else:
181
- self.children_rect = pygame.FRect(*self.parent.get_inner_rect().topleft, 10, 10)
182
- self.children_rect.move_ip(-self.parent.scroll.x,-self.parent.scroll.y)
183
-
184
- def handle_event(self, event):
185
- if not self.parent.get_layout_children() or not self.parent.children_has_focus():
186
- return
187
-
188
- if event.type == pygame.KEYDOWN:
189
- if event.key in (pygame.K_DOWN, pygame.K_UP):
190
- self.focus_next_child() if event.key == pygame.K_DOWN else self.focus_prev_child()
191
- event.consumed = True
192
- event.consumed = True
193
-
16
+ def set_parent(self,parent:Widget):
17
+ self.parent = parent
18
+ self.arrange()
194
19
 
195
- def arrange(self) -> None:
196
- self.update_children_rect()
197
- y = self.children_rect.y
198
- for child in self.parent.get_layout_children():
199
- child.set_position(self.children_rect.x, y)
200
- y += child.rect.height + self.gap
20
+ def arrange(self)->None:
21
+ raise NotImplementedError("Subclasses must implement arrange method")
201
22
 
202
- class Row(SingleAxisLayout):
203
- def __init__(self, gap: int = 0):
23
+ class Column(Layout):
24
+ def __init__(self,gap:int=0,shrink:bool=False):
204
25
  super().__init__()
205
26
  self.gap = gap
206
-
207
- def update_children_rect(self):
208
- if self.parent.get_layout_children():
209
- height = max(child.get_min_required_size()[1] for child in self.parent.get_layout_children())
210
- 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)
211
- self.children_rect = pygame.FRect(*self.parent.get_inner_rect().topleft, width, height)
212
- else:
213
- self.children_rect = pygame.FRect(*self.parent.get_inner_rect().topleft, 10,10)
214
- self.children_rect.move_ip(-self.parent.scroll.x,-self.parent.scroll.y)
215
-
216
- def handle_event(self, event):
217
- if not self.parent.get_layout_children() or not self.parent.children_has_focus():
218
- return
219
-
220
- if event.type == pygame.KEYDOWN:
221
- if event.key in (pygame.K_RIGHT, pygame.K_LEFT):
222
- self.focus_next_child() if event.key == pygame.K_RIGHT else self.focus_prev_child()
223
- event.consumed = True
224
-
225
-
226
- def arrange(self) -> None:
227
- self.update_children_rect()
228
- x = self.children_rect.x
229
- for child in self.parent.get_layout_children():
230
- child.set_position(x,self.children_rect.y)
231
- x += child.rect.width + self.gap
232
-
233
-
234
-
235
- class RowFill(Row):
236
-
237
- def update_children_rect(self):
238
- parent_width = self.parent.get_inner_width()
239
- if self.parent.get_layout_children():
240
- height = max(child.get_min_required_size()[1] for child in self.parent.get_layout_children())
241
- width = parent_width
242
- self.children_rect = pygame.FRect(*self.parent.get_inner_rect().topleft, width, height)
243
- else:
244
- self.children_rect = pygame.FRect(*self.parent.get_inner_rect().topleft, parent_width,10)
245
- self.children_rect.move_ip(-self.parent.scroll.x,-self.parent.scroll.y)
246
-
247
-
248
- def arrange(self) -> None:
249
- """
250
- Arranges children in a row and resizes them to fill the parent's height,
251
- accounting for the gap between children.
252
- """
253
- self.update_children_rect()
254
- for child in self.parent.get_layout_children():
255
- child.set_autoresize_w(False)
256
- x = self.children_rect.x
257
- # available_height = self.children_rect.height
258
-
259
- # Calculate the width available for each child
260
- total_gap = self.gap * (len(self.parent.get_layout_children()) - 1)
261
- available_width = max(0, self.children_rect.width - total_gap)
262
- child_width = available_width / len(self.parent.get_layout_children()) if self.parent.get_layout_children() else 0
263
-
264
- for child in self.parent.get_layout_children():
265
- child.set_size((child_width, None)) # Resize child to fill height
266
- child.set_position(x, self.children_rect.y) # Position child
267
- x += child_width + self.gap
268
-
269
-
270
- class ColumnFill(Column):
271
-
272
- def update_children_rect(self):
273
- parent_height = self.parent.get_inner_height()
274
- if self.parent.get_layout_children():
275
- width = max(child.get_min_required_size()[0] for child in self.parent.get_layout_children())
276
- height = parent_height
277
- self.children_rect = pygame.FRect(*self.parent.get_inner_rect().topleft, width, height)
278
- else:
279
- self.children_rect = pygame.FRect(*self.parent.get_inner_rect().topleft, 10, parent_height)
280
- self.children_rect.move_ip(-self.parent.scroll.x, -self.parent.scroll.y)
281
-
282
- def arrange(self) -> None:
283
- """
284
- Arranges children in a column and resizes them to fill the parent's width,
285
- accounting for the gap between children.
286
- """
287
- self.update_children_rect()
288
- for child in self.parent.get_layout_children():
289
- child.set_autoresize_h(False)
290
- y = self.children_rect.y
291
-
292
- # Calculate the height available for each child
293
- total_gap = self.gap * (len(self.parent.get_layout_children()) - 1)
294
- available_height = max(0, self.children_rect.height - total_gap)
295
- child_height = available_height / len(self.parent.get_layout_children()) if self.parent.get_layout_children() else 0
296
-
297
- for child in self.parent.get_layout_children():
298
- child.set_size((None, child_height)) # Resize child to fill width
299
- child.set_position(self.children_rect.x, y) # Position child
300
- y += child_height + self.gap
301
-
302
-
303
- class Grid(DoubleAxisLayout):
304
- 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):
305
54
  super().__init__()
306
- self.rows = rows
307
- self.cols = cols
308
55
  self.gap = gap
56
+ self.shrink = shrink
309
57
 
310
- def focus_up_child(self) -> None:
311
- l = self.parent.get_interactive_children()
312
- if not l:
313
- return
314
- current_index = self.parent.focused_index
315
- if current_index == -1:
316
- return
317
- current_row = current_index // self.cols
318
- target_index = max(0, current_index - self.cols)
319
- if target_index // self.cols < current_row:
320
- self.parent.focused_index = target_index
321
- l[target_index].get_focus()
322
-
323
- def focus_down_child(self) -> None:
324
- l = self.parent.get_interactive_children()
325
- if not l:
326
- return
327
- current_index = self.parent.focused_index
328
- if current_index == -1:
329
- return
330
- current_row = current_index // self.cols
331
- target_index = min(len(l) - 1, current_index + self.cols)
332
- if target_index // self.cols > current_row:
333
- self.parent.focused_index = target_index
334
- l[target_index].get_focus()
335
-
336
- def focus_left_child(self) -> None:
337
- l = self.parent.get_interactive_children()
338
- if not l:
339
- return
340
- current_index = self.parent.focused_index
341
- if current_index == -1:
342
- return
343
- target_index = max(0, current_index - 1)
344
- if target_index // self.cols == current_index // self.cols:
345
- self.parent.focused_index = target_index
346
- l[target_index].get_focus()
347
-
348
- def focus_right_child(self) -> None:
349
- l = self.parent.get_interactive_children()
350
- if not l:
351
- return
352
- current_index = self.parent.focused_index
353
- if current_index == -1:
354
- return
355
- target_index = min(len(l) - 1, current_index + 1)
356
- if target_index // self.cols == current_index // self.cols:
357
- self.parent.focused_index = target_index
358
- l[target_index].get_focus()
359
-
360
- def handle_event(self, event):
361
- if not self.parent.get_layout_children() or not self.parent.children_has_focus():
362
- return
363
-
364
- if event.type == pygame.KEYDOWN:
365
- if event.key in (pygame.K_RIGHT, pygame.K_LEFT, pygame.K_UP, pygame.K_DOWN):
366
- if event.key == pygame.K_RIGHT:
367
- self.focus_right_child()
368
- elif event.key == pygame.K_LEFT:
369
- self.focus_left_child()
370
- elif event.key == pygame.K_UP:
371
- self.focus_up_child()
372
- elif event.key == pygame.K_DOWN:
373
- self.focus_down_child()
374
-
375
- event.consumed = True
376
-
377
- def update_children_rect(self):
378
- if self.parent.get_layout_children():
379
- cell_width = max(child.get_min_required_size()[0] for child in self.parent.get_layout_children())
380
- cell_height = max(child.get_min_required_size()[1] for child in self.parent.get_layout_children())
381
- width = self.cols * cell_width + self.gap * (self.cols - 1)
382
- height = self.rows * cell_height + self.gap * (self.rows - 1)
383
- self.children_rect = pygame.FRect(*self.parent.get_inner_rect().topleft, width, height)
384
- else:
385
- self.children_rect = pygame.FRect(*self.parent.get_inner_rect().topleft, 10, 10)
386
- self.children_rect.move_ip(-self.parent.scroll.x, -self.parent.scroll.y)
387
-
388
- def arrange(self) -> None:
389
- self.update_children_rect()
390
- if not self.parent.get_layout_children():
391
- return
392
-
393
- cell_width = (self.children_rect.width - self.gap * (self.cols - 1)) / self.cols
394
- cell_height = (self.children_rect.height - self.gap * (self.rows - 1)) / self.rows
395
-
396
- for i, child in enumerate(self.parent.get_layout_children()):
397
- row = i // self.cols
398
- col = i % self.cols
399
- x = self.children_rect.x + col * (cell_width + self.gap)
400
- y = self.children_rect.y + row * (cell_height + self.gap)
401
- child.set_size((cell_width, cell_height))
402
- child.set_position(x, y)
403
-
404
-
405
- class GridFill(Grid):
406
- def update_children_rect(self):
407
- self.children_rect = self.parent.get_inner_rect()
408
58
  def arrange(self) -> None:
409
- """
410
- Arranges children in a grid and resizes them to fill the parent's available space,
411
- accounting for the gap between children.
412
- """
413
- self.update_children_rect()
414
-
415
- if not self.parent.get_layout_children():
59
+ if not self.parent:
416
60
  return
417
- for child in self.parent.get_layout_children():
418
- child.set_autoresize(False)
419
-
420
- cell_width = (self.children_rect.width - self.gap * (self.cols - 1)) / self.cols
421
- cell_height = (self.children_rect.height - self.gap * (self.rows - 1)) / self.rows
422
-
423
- for i, child in enumerate(self.parent.get_layout_children()):
424
- row = i // self.cols
425
- col = i % self.cols
426
- x = self.children_rect.x + col * (cell_width + self.gap)
427
- y = self.children_rect.y + row * (cell_height + self.gap)
428
- child.set_size((cell_width, cell_height))
429
- 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)