batframework 1.0.9a11__py3-none-any.whl → 1.0.10__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 +53 -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.0.10.dist-info}/METADATA +24 -17
  40. batframework-1.0.10.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.0.10.dist-info}/LICENSE +0 -0
  75. {batframework-1.0.9a11.dist-info → batframework-1.0.10.dist-info}/WHEEL +0 -0
  76. {batframework-1.0.9a11.dist-info → batframework-1.0.10.dist-info}/top_level.txt +0 -0
@@ -1,397 +0,0 @@
1
- import batFramework as bf
2
- from .meter import BarMeter
3
- from .button import Button
4
- from .indicator import *
5
- from .meter import BarMeter
6
- from .shape import Shape
7
- from .interactiveWidget import InteractiveWidget
8
-
9
- class SliderHandle(Indicator, DraggableWidget):
10
- def __init__(self):
11
- super().__init__()
12
- self.set_color(bf.color.CLOUD_SHADE)
13
- self.old_key_repeat: tuple = (0, 0)
14
- self.parent : bf.ClickableWidget = self.parent
15
- self.set_click_mask(1)
16
- def __str__(self) -> str:
17
- return "SliderHandle"
18
-
19
- def on_click_down(self, button: int) -> bool:
20
- if not self.parent.is_enabled:
21
- return True
22
- res = super().on_click_down(button)
23
- if res :
24
- self.parent.get_focus()
25
- return res
26
-
27
- def on_exit(self):
28
- before = self.is_clicked_down
29
- super().on_exit()
30
- self.is_clicked_down = before
31
-
32
- def do_on_drag(
33
- self, drag_start: tuple[float, float], drag_end: tuple[float, float]
34
- ) -> None:
35
- if not self.parent.is_enabled:
36
- return
37
- super().do_on_drag(drag_start, drag_end)
38
- m: BarMeter = self.parent.meter
39
- r = m.get_inner_rect()
40
-
41
- position = self.rect.centerx if self.parent.axis == bf.axis.HORIZONTAL else self.rect.centery
42
- self.rect.clamp_ip(r)
43
- # Adjust handle position to value
44
- new_value = self.parent.position_to_value(position)
45
- self.parent.set_value(new_value)
46
- if self.parent.axis == bf.axis.HORIZONTAL:
47
- self.rect.centerx = self.parent.value_to_position(new_value)
48
- else:
49
- self.rect.centery = self.parent.value_to_position(new_value)
50
-
51
- def top_at(self, x, y):
52
- return Widget.top_at(self, x, y)
53
-
54
- class SliderMeter(BarMeter, InteractiveWidget):
55
- def __str__(self) -> str:
56
- return "SliderMeter"
57
-
58
- def __init__(self, min_value = 0, max_value = 1, step = 0.1):
59
- super().__init__(min_value, max_value, step)
60
- self.set_padding(0)
61
-
62
- def get_min_required_size(self):
63
- size = list(super().get_min_required_size())
64
- if self.parent.axis == bf.axis.HORIZONTAL:
65
- size[0] = size[1]*3
66
- else:
67
- size[1] = size[0]*3
68
- return self.resolve_size(size)
69
-
70
- def on_click_down(self, button: int) -> bool:
71
- if not self.parent.is_enabled:
72
- return False
73
- if button != 1:
74
- return False
75
-
76
- self.parent.get_focus()
77
- pos = self.parent_layer.camera.screen_to_world(pygame.mouse.get_pos())
78
- if self.parent.axis == bf.axis.HORIZONTAL:
79
- pos = pos[0]
80
- else:
81
- pos = pos[1]
82
- new_value = self.parent.position_to_value(pos)
83
- self.parent.set_value(new_value)
84
- self.do_on_click_down(button)
85
- return True
86
-
87
- class Slider(Button):
88
-
89
- def __init__(self, text: str, default_value: float = 1.0) -> None:
90
- super().__init__(text, None)
91
- self.axis : bf.axis = bf.axis.HORIZONTAL
92
- self.gap: float | int = 0
93
- self.spacing: bf.spacing = bf.spacing.MANUAL
94
- self.modified_callback : Callable[[float],Any] = None
95
- self.meter: SliderMeter = SliderMeter()
96
- self.handle = SliderHandle()
97
- self.add(self.meter, self.handle)
98
- self.meter.set_debug_color(bf.color.RED)
99
- self.set_value(default_value, True)
100
-
101
- def set_tooltip_text(self, text):
102
- return super().set_tooltip_text(text)
103
-
104
- def set_fill_color(self,color)->Self:
105
- self.meter.content.set_color(color)
106
- return self
107
-
108
- def set_axis(self,axis:bf.axis)->Self:
109
- self.axis = axis
110
- self.meter.set_axis(axis)
111
- self.dirty_shape = True
112
- return self
113
-
114
- def set_visible(self, value: bool) -> Self:
115
- self.handle.set_visible(value)
116
- self.meter.set_visible(value)
117
- return super().set_visible(value)
118
-
119
- def __str__(self) -> str:
120
- return "Slider"
121
-
122
- def set_gap(self, value: int | float) -> Self:
123
- value = max(0, value)
124
- self.gap = value
125
- return self
126
-
127
- def do_on_get_focus(self) -> None:
128
- super().do_on_get_focus()
129
- self.old_key_repeat = pygame.key.get_repeat()
130
- pygame.key.set_repeat(200, 50)
131
-
132
- def do_on_lose_focus(self) -> None:
133
- super().do_on_lose_focus()
134
- pygame.key.set_repeat(*self.old_key_repeat)
135
-
136
- def set_spacing(self, spacing: bf.spacing) -> Self:
137
- if spacing == self.spacing:
138
- return self
139
- self.spacing = spacing
140
- self.dirty_shape = True
141
- return self
142
-
143
- def set_modify_callback(self, callback : Callable[[float],Any]) -> Self:
144
- self.modified_callback = callback
145
- return self
146
-
147
- def set_range(self, range_min: float, range_max: float) -> Self:
148
- self.meter.set_range(range_min, range_max)
149
- self.dirty_shape = True
150
- return self
151
-
152
- def set_step(self, step: float) -> Self:
153
- self.meter.set_step(step)
154
- self.dirty_shape = True
155
- return self
156
-
157
- def set_value(self, value, no_callback: bool = False) -> Self:
158
- if self.meter.value != value:
159
- self.meter.set_value(value)
160
- self.dirty_shape = True
161
- if self.modified_callback and (not no_callback):
162
- self.modified_callback(self.meter.value)
163
- self.handle.set_tooltip_text(str(self.get_value()))
164
- self.meter.set_tooltip_text(str(self.get_value()))
165
-
166
- return self
167
-
168
- def get_value(self) -> float:
169
- return self.meter.get_value()
170
-
171
- def on_key_down(self, key):
172
- if super().on_key_down(key):
173
- return True
174
- if not self.is_enabled:
175
- return False
176
- if self.axis == bf.axis.HORIZONTAL:
177
- if key == pygame.K_RIGHT:
178
- self.set_value(self.meter.get_value() + self.meter.step)
179
- elif key == pygame.K_LEFT:
180
- self.set_value(self.meter.get_value() - self.meter.step)
181
- else:
182
- return False
183
- return True
184
- else:
185
- if key == pygame.K_UP:
186
- self.set_value(self.meter.get_value() + self.meter.step)
187
- elif key == pygame.K_DOWN:
188
- self.set_value(self.meter.get_value() - self.meter.step)
189
- else:
190
- return False
191
-
192
- return True
193
-
194
- def do_on_click_down(self, button) -> None:
195
- if not self.is_enabled:
196
- return
197
- if button == 1:
198
- self.get_focus()
199
-
200
- def value_to_position(self, value: float) -> float:
201
- """
202
- Converts a value to a position on the meter, considering the step size.
203
- """
204
- rect = self.meter.get_inner_rect()
205
- value_range = self.meter.get_range()
206
- value = round(value / self.meter.step) * self.meter.step
207
- position_ratio = (value - self.meter.min_value) / value_range
208
- if self.axis == bf.axis.HORIZONTAL:
209
- return (
210
- rect.left
211
- + (self.handle.rect.w / 2)
212
- + position_ratio * (rect.width - self.handle.rect.w)
213
- )
214
- else:
215
- return (
216
- rect.bottom
217
- - (self.handle.rect.h / 2)
218
- - position_ratio * (rect.height - self.handle.rect.h)
219
- )
220
-
221
- def position_to_value(self, position: float) -> float:
222
- """
223
- Converts a position on the meter to a value, considering the step size.
224
- """
225
- rect = self.meter.get_inner_rect()
226
- if self.axis == bf.axis.HORIZONTAL:
227
- if self.rect.w == self.handle.rect.w:
228
- position_ratio = 0
229
- else:
230
- handle_half = self.handle.rect.w // 2
231
- position = max(rect.left + handle_half, min(position, rect.right - handle_half))
232
- position_ratio = (position - rect.left - handle_half) / (
233
- rect.width - self.handle.rect.w
234
- )
235
- else:
236
- if self.rect.h == self.handle.rect.h:
237
- position_ratio = 0
238
- else:
239
- handle_half = self.handle.rect.h // 2
240
- position = max(rect.top + handle_half, min(position, rect.bottom - handle_half))
241
- # Flip ratio vertically: bottom is min, top is max
242
- position_ratio = (rect.bottom - position - handle_half) / (
243
- rect.height - self.handle.rect.h
244
- )
245
-
246
- value_range = self.meter.get_range()
247
- value = self.meter.min_value + position_ratio * value_range
248
- return round(value / self.meter.step) * self.meter.step
249
-
250
- def get_min_required_size(self) -> tuple[float, float]:
251
- """
252
- Calculates the minimum required size for the slider, considering the text, meter, and axis.
253
-
254
- Returns:
255
- tuple[float, float]: The width and height of the minimum required size.
256
- """
257
- gap = self.gap if self.text else 0
258
- text_width, text_height = self._get_text_rect_required_size() if self.text else (0, 0)
259
- meter_width, meter_height = self.meter.resolve_size(self.meter.get_min_required_size())
260
-
261
- if self.axis == bf.axis.HORIZONTAL:
262
- width = text_width + gap + meter_width
263
- height = max(text_height, meter_height)
264
- else:
265
- width = max(text_width, meter_width)
266
- height = text_height + gap + meter_height
267
-
268
- height += self.unpressed_relief
269
- return self.expand_rect_with_padding((0, 0, width, height)).size
270
-
271
- def _build_composed_layout(self) -> None:
272
- """
273
- Builds the composed layout for the slider, including the meter and handle.
274
- This method adjusts the sizes and positions of the meter and handle based on the slider's axis,
275
- autoresize conditions, and spacing settings. It ensures the slider's components are properly aligned
276
- and sized within the slider's padded rectangle.
277
- """
278
- self.text_rect.size = self._get_text_rect_required_size()
279
-
280
- size_changed = False
281
- gap = self.gap if self.text else 0
282
-
283
- full_rect = self.text_rect.copy()
284
-
285
-
286
- # Resolve the meter's size based on the axis and autoresize conditions
287
- if self.axis == bf.axis.HORIZONTAL:
288
- meter_width,meter_height = self.meter.get_min_required_size()
289
- if not self.autoresize_w:
290
- meter_width = self.get_inner_width() - gap - self.text_rect.w
291
- meter_width,meter_height = self.meter.resolve_size((meter_width,meter_height))
292
-
293
- full_rect.w = max(self.get_inner_width(), meter_width + (gap + self.text_rect.w if self.text else 0))
294
- self.meter.set_size((meter_width, meter_height))
295
- full_rect.h = max(meter_height, self.text_rect.h if self.text else meter_height)
296
-
297
- else: # VERTICAL
298
- meter_width, meter_height = self.meter.get_min_required_size()
299
- if not self.autoresize_h:
300
- meter_height = self.get_inner_height() - gap - self.text_rect.h
301
- meter_width, meter_height = self.meter.resolve_size((meter_width, meter_height))
302
-
303
- full_rect.h = meter_height + (gap + self.text_rect.h if self.text else 0)
304
- self.meter.set_size((meter_width, meter_height))
305
- full_rect.w = max(meter_width, self.text_rect.w if self.text else meter_width)
306
-
307
-
308
- # Inflate the rect by padding and resolve the target size
309
- full_rect.h += self.unpressed_relief
310
- inflated = self.expand_rect_with_padding((0, 0, *full_rect.size)).size
311
-
312
- target_size = self.resolve_size(inflated)
313
-
314
-
315
- # Update the slider's size if it doesn't match the target size
316
- if self.rect.size != target_size:
317
- self.set_size(target_size)
318
- size_changed = True
319
-
320
- # Adjust the handle size based on the meter's size
321
- if self.axis == bf.axis.HORIZONTAL:
322
- handle_size = self.meter.get_inner_height()
323
- self.handle.set_size(self.handle.resolve_size((handle_size, handle_size)))
324
- else:
325
- handle_size = self.meter.get_inner_width()
326
- self.handle.set_size(self.handle.resolve_size((handle_size, handle_size)))
327
-
328
- self._align_composed()
329
- return size_changed
330
-
331
- def _align_composed(self):
332
-
333
- if not self.text:
334
- self.text_rect.size = (0,0)
335
- full_rect = self.get_local_inner_rect()
336
- left_rect = self.text_rect
337
- right_rect = self.meter.rect.copy()
338
-
339
-
340
-
341
- if self.axis == bf.axis.HORIZONTAL:
342
- gap = {
343
- bf.spacing.MIN: 0,
344
- bf.spacing.HALF: (full_rect.width - left_rect.width - right_rect.width) // 2,
345
- bf.spacing.MAX: full_rect.width - left_rect.width - right_rect.width,
346
- bf.spacing.MANUAL: self.gap
347
- }.get(self.spacing, 0)
348
-
349
- gap = max(0, gap)
350
- combined_width = left_rect.width + right_rect.width + gap
351
-
352
- group_x = {
353
- bf.alignment.LEFT: full_rect.left,
354
- bf.alignment.MIDLEFT: full_rect.left,
355
- bf.alignment.RIGHT: full_rect.right - combined_width,
356
- bf.alignment.MIDRIGHT: full_rect.right - combined_width,
357
- bf.alignment.CENTER: full_rect.centerx - combined_width // 2
358
- }.get(self.alignment, full_rect.left)
359
-
360
- left_rect.x, right_rect.x = group_x, group_x + left_rect.width + gap
361
- left_rect.centery = right_rect.centery = full_rect.centery
362
-
363
- else: # VERTICAL
364
- gap = {
365
- bf.spacing.MIN: 0,
366
- bf.spacing.HALF: (full_rect.height - left_rect.height - right_rect.height) // 2,
367
- bf.spacing.MAX: full_rect.height - left_rect.height - right_rect.height,
368
- bf.spacing.MANUAL: self.gap
369
- }.get(self.spacing, 0)
370
-
371
- gap = max(0, gap)
372
- combined_height = left_rect.height + right_rect.height + gap
373
-
374
- group_y = {
375
- bf.alignment.TOP: full_rect.top,
376
- bf.alignment.MIDTOP: full_rect.top,
377
- bf.alignment.BOTTOM: full_rect.bottom - combined_height,
378
- bf.alignment.MIDBOTTOM: full_rect.bottom - combined_height,
379
- bf.alignment.CENTER: full_rect.centery - combined_height // 2
380
- }.get(self.alignment, full_rect.top)
381
-
382
- left_rect.y, right_rect.y = group_y, group_y + left_rect.height + gap
383
- left_rect.centerx = right_rect.centerx = full_rect.centerx
384
-
385
- # Push text to local, push shape to world
386
- self.text_rect = left_rect
387
- right_rect.move_ip(*self.rect.topleft)
388
- self.meter.set_position(*right_rect.topleft)
389
-
390
- # Position the handle based on the current value
391
- if self.axis == bf.axis.HORIZONTAL:
392
- self.handle.set_center(self.value_to_position(self.meter.value), self.meter.rect.centery)
393
- else:
394
- self.handle.set_center(self.meter.rect.centerx, self.value_to_position(self.meter.value))
395
-
396
- def _build_layout(self) -> None:
397
- return self._build_composed_layout()
batFramework/gui/style.py DELETED
@@ -1,10 +0,0 @@
1
- from .widget import Widget
2
-
3
-
4
- class Style:
5
-
6
- def __init__(self):
7
- pass
8
-
9
- def apply(self, widget: Widget):
10
- pass
@@ -1,54 +0,0 @@
1
- from ..utils import Singleton
2
- from .widget import Widget
3
-
4
-
5
- class Style:
6
- def __init__(self):
7
- pass
8
-
9
- def apply(self, widget: Widget):
10
- pass
11
-
12
-
13
- class StyleManager(metaclass=Singleton):
14
- def __init__(self):
15
- self.styles: list[Style] = []
16
- self.widgets: set[Widget] = set()
17
- self.lookup: dict[Widget, bool] = {}
18
-
19
- def register_widget(self, widget: Widget):
20
- if widget in self.widgets:
21
- return
22
- self.widgets.add(widget)
23
- self.lookup[widget] = False
24
- self.update()
25
-
26
- def refresh_widget(self, widget: Widget):
27
- if widget in self.widgets:
28
- self.lookup[widget] = False
29
- self.update()
30
-
31
- def remove_widget(self, widget: Widget):
32
- if widget not in self.widgets:
33
- return
34
- self.widgets.remove(widget)
35
- self.lookup.pop(widget)
36
-
37
- def add(self, style: Style):
38
- self.styles.append(style)
39
- self.lookup = {key: False for key in self.lookup}
40
- self.update()
41
-
42
- def update_forced(self):
43
- for widget in self.widgets:
44
- for style in self.styles:
45
- style.apply(widget)
46
- self.lookup[widget] = True
47
-
48
- def update(self):
49
- for widget in self.widgets:
50
- if self.lookup[widget]:
51
- continue
52
- for style in self.styles:
53
- style.apply(widget)
54
- self.lookup[widget] = True
@@ -1,49 +0,0 @@
1
- from .widget import Widget
2
- from typing import Callable, Any, Self
3
-
4
- class SyncedVar:
5
- def __init__(self, value=None):
6
- self._value: Any = value
7
- self.modify_callback: Callable[[Any], Any] | None = None
8
- self._bound_widgets: set[tuple[Widget, Callable[[Any], Any]]] = set()
9
-
10
- def set_modify_callback(self, callback : Callable[[Any], Any]) -> Self:
11
- self.modify_callback = callback
12
- return self
13
-
14
- def bind_widget(self, widget: Widget, update_callback: Callable[[Any], Any]) -> Self:
15
- """
16
- Binds a widget to the SyncedVar. The widget must provide an update_callback
17
- function that will be called whenever the value changes.
18
- """
19
- self._bound_widgets.add((widget, update_callback))
20
- self._update_widgets()
21
- return self
22
-
23
- def unbind_widget(self, widget: Widget)->Self:
24
- """
25
- Unbinds a widget from the SyncedVar.
26
- """
27
- self._bound_widgets = {
28
- (w, cb) for w, cb in self._bound_widgets if w != widget
29
- }
30
- return self
31
-
32
- @property
33
- def value(self):
34
- return self._value
35
-
36
- @value.setter
37
- def value(self, new_value):
38
- if self._value != new_value:
39
- self._value = new_value
40
- self._update_widgets()
41
- if self.modify_callback is not None:
42
- self.modify_callback(new_value)
43
-
44
- def _update_widgets(self):
45
- """
46
- Calls the update callback for all bound widgets.
47
- """
48
- for _, update_callback in self._bound_widgets:
49
- update_callback(self._value)