batframework 1.0.8a7__py3-none-any.whl → 1.0.8a8__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 (70) hide show
  1. batFramework/__init__.py +51 -68
  2. batFramework/action.py +99 -126
  3. batFramework/actionContainer.py +9 -53
  4. batFramework/animatedSprite.py +82 -141
  5. batFramework/audioManager.py +26 -69
  6. batFramework/camera.py +69 -259
  7. batFramework/constants.py +54 -16
  8. batFramework/cutscene.py +29 -39
  9. batFramework/cutsceneBlocks.py +43 -36
  10. batFramework/debugger.py +48 -0
  11. batFramework/dynamicEntity.py +9 -18
  12. batFramework/easing.py +71 -0
  13. batFramework/entity.py +97 -48
  14. batFramework/gui/__init__.py +2 -10
  15. batFramework/gui/button.py +78 -9
  16. batFramework/gui/constraints.py +204 -0
  17. batFramework/gui/container.py +32 -174
  18. batFramework/gui/debugger.py +43 -131
  19. batFramework/gui/frame.py +19 -0
  20. batFramework/gui/image.py +20 -56
  21. batFramework/gui/indicator.py +21 -38
  22. batFramework/gui/interactiveWidget.py +13 -192
  23. batFramework/gui/label.py +74 -309
  24. batFramework/gui/layout.py +63 -231
  25. batFramework/gui/root.py +38 -134
  26. batFramework/gui/shape.py +57 -237
  27. batFramework/gui/toggle.py +51 -101
  28. batFramework/gui/widget.py +250 -358
  29. batFramework/manager.py +19 -52
  30. batFramework/particles.py +77 -0
  31. batFramework/scene.py +123 -281
  32. batFramework/sceneManager.py +116 -178
  33. batFramework/stateMachine.py +8 -11
  34. batFramework/time.py +58 -145
  35. batFramework/transition.py +124 -195
  36. batFramework/transitionManager.py +0 -0
  37. batFramework/triggerZone.py +1 -1
  38. batFramework/utils.py +147 -112
  39. batframework-1.0.8a8.dist-info/METADATA +53 -0
  40. batframework-1.0.8a8.dist-info/RECORD +42 -0
  41. {batframework-1.0.8a7.dist-info → batframework-1.0.8a8.dist-info}/WHEEL +1 -1
  42. batFramework/character.py +0 -27
  43. batFramework/easingController.py +0 -58
  44. batFramework/enums.py +0 -113
  45. batFramework/fontManager.py +0 -65
  46. batFramework/gui/clickableWidget.py +0 -220
  47. batFramework/gui/constraints/__init__.py +0 -1
  48. batFramework/gui/constraints/constraints.py +0 -815
  49. batFramework/gui/dialogueBox.py +0 -99
  50. batFramework/gui/draggableWidget.py +0 -40
  51. batFramework/gui/meter.py +0 -74
  52. batFramework/gui/radioButton.py +0 -84
  53. batFramework/gui/slider.py +0 -240
  54. batFramework/gui/style.py +0 -10
  55. batFramework/gui/styleManager.py +0 -48
  56. batFramework/gui/textInput.py +0 -247
  57. batFramework/object.py +0 -123
  58. batFramework/particle.py +0 -115
  59. batFramework/renderGroup.py +0 -67
  60. batFramework/resourceManager.py +0 -100
  61. batFramework/scrollingSprite.py +0 -114
  62. batFramework/sprite.py +0 -51
  63. batFramework/templates/__init__.py +0 -2
  64. batFramework/templates/character.py +0 -44
  65. batFramework/templates/states.py +0 -166
  66. batFramework/tileset.py +0 -46
  67. batframework-1.0.8a7.dist-info/LICENCE +0 -21
  68. batframework-1.0.8a7.dist-info/METADATA +0 -43
  69. batframework-1.0.8a7.dist-info/RECORD +0 -62
  70. {batframework-1.0.8a7.dist-info → batframework-1.0.8a8.dist-info}/top_level.txt +0 -0
@@ -1,99 +0,0 @@
1
- from .label import Label
2
- import batFramework as bf
3
- from typing import Self
4
-
5
-
6
- class DialogueBox(Label):
7
- def __init__(self) -> None:
8
- self.cursor_position: float = 0.0
9
- self.text_speed: float = 20.0
10
- self.message_queue: list[str] = []
11
- self.is_over: bool = True
12
- self.is_paused: bool = False
13
- self.set_autoresize(False)
14
- self.set_alignment(bf.alignment.LEFT)
15
- super().__init__("")
16
-
17
- def __str__(self) -> str:
18
- return "DialogueBox"
19
-
20
- def pause(self) -> Self:
21
- self.is_paused = True
22
- return self
23
-
24
- def resume(self) -> Self:
25
- self.is_paused = False
26
- return self
27
-
28
- def set_text_speed(self, speed: float) -> Self:
29
- self.text_speed = speed
30
- return self
31
-
32
- def cut_text_to_width(self, text: str) -> list[str]:
33
- w = self.get_padded_width()
34
- if text == "" or not self.font_object or w < self.font_object.point_size:
35
- return [text]
36
- left = 0
37
- for index in range(len(text)):
38
- width = self.font_object.size(text[left:index])[0]
39
-
40
- if width > w:
41
- cut_point_start = index - 1
42
- cut_point_end = index - 1
43
- last_space = text.rfind(" ", 0, cut_point_start)
44
- last_nline = text.rfind("\n", 0, cut_point_start)
45
-
46
- if last_space != -1 or last_nline != -1: # space was found !:
47
- cut_point_start = max(last_space, last_nline)
48
- cut_point_end = cut_point_start + 1
49
- res = [text[:cut_point_start].strip()]
50
- res.extend(self.cut_text_to_width(text[cut_point_end:].strip()))
51
- return res
52
- elif text[index] == "\n":
53
- left = index
54
- return [text]
55
-
56
- def paint(self) -> None:
57
- if self.font_object and self.message_queue:
58
- message = self.message_queue.pop(0)
59
- message = "\n".join(self.cut_text_to_width(message))
60
- self.message_queue.insert(0, message)
61
- super().paint()
62
-
63
- def say(self, message: str) -> Self:
64
- self.message_queue.append(message)
65
- self.is_over = False
66
- return self
67
-
68
- def is_queue_empty(self) -> bool:
69
- return not self.message_queue
70
-
71
- def is_current_message_over(self) -> bool:
72
- return self.is_over
73
-
74
- def clear_queue(self) -> Self:
75
- self.message_queue.clear()
76
- self.next_message()
77
- return self
78
-
79
- def next_message(self) -> Self:
80
- if self.message_queue:
81
- self.message_queue.pop(0)
82
- self.cursor_position = 0
83
- self.set_text("")
84
- return self
85
-
86
- def skip_current_message(self) -> Self:
87
- self.cursor_position = len(self.message_queue[0])
88
- self.dirty_shape = True
89
-
90
- def do_update(self, dt):
91
- if not self.message_queue or self.is_paused:
92
- return
93
- if not self.is_over and self.cursor_position == len(self.message_queue[0]):
94
- self.is_over = True
95
- return
96
- self.cursor_position = min(
97
- self.cursor_position + self.text_speed * dt, len(self.message_queue[0])
98
- )
99
- self.set_text(self.message_queue[0][: int(self.cursor_position)])
@@ -1,40 +0,0 @@
1
- from .interactiveWidget import InteractiveWidget
2
- import batFramework as bf
3
- import pygame
4
-
5
-
6
- class DraggableWidget(InteractiveWidget):
7
- def __init__(self, *args, **kwargs) -> None:
8
- self.drag_action = bf.Action("dragging").add_mouse_control(1).set_holding()
9
-
10
- self.drag_start = None
11
- self.offset = None
12
- super().__init__(*args, **kwargs)
13
-
14
- def do_process_actions(self, event: pygame.Event) -> None:
15
- self.drag_action.process_event(event)
16
-
17
- def do_reset_actions(self) -> None:
18
- self.drag_action.reset()
19
-
20
- def do_on_drag(
21
- self, drag_start: tuple[float, float], drag_end: tuple[float, float]
22
- ) -> None:
23
- self.set_position(drag_end[0] - self.offset[0], drag_end[1] - self.offset[1])
24
-
25
- def update(self, dt: float):
26
- if self.drag_action.active and self.is_clicked_down:
27
- r = self.get_root()
28
- x, y = r.drawing_camera.screen_to_world(pygame.mouse.get_pos())
29
- if self.drag_start == None and self.drag_action.active:
30
- self.offset = x - self.rect.x, y - self.rect.y
31
- self.drag_start = x, y
32
- return
33
- else:
34
- self.do_on_drag(self.drag_start, (x, y))
35
- return
36
- else:
37
- self.drag_start = None
38
- self.offset = None
39
- self.is_clicked_down = False
40
- super().update(dt)
batFramework/gui/meter.py DELETED
@@ -1,74 +0,0 @@
1
- import batFramework as bf
2
- from .shape import Shape
3
- from typing import Self
4
-
5
-
6
- def custom_top_at(self, x, y):
7
- if Shape.top_at(self, x, y) == self:
8
- return self.parent
9
- return None
10
-
11
-
12
- class Meter(Shape):
13
- def __init__(self, min_value: float = 0, max_value: float = 1, step: float = 0.1):
14
- super().__init__()
15
- self.min_value, self.max_value = min_value, max_value
16
- self.step = step
17
- self.snap: bool = False
18
- self.value = self.max_value
19
- self.content = Shape((0, 0)).set_color(bf.color.BLUE)
20
- self.content.set_debug_color("cyan")
21
- self.content.top_at = lambda x, y: custom_top_at(self.content, x, y)
22
- self.add(self.content)
23
- self.set_padding(4)
24
- self.set_color("gray20")
25
- self.set_outline_width(1)
26
- self.set_outline_color(bf.color.BLACK)
27
- self.set_debug_color("pink")
28
-
29
- def __str__(self) -> str:
30
- return "Meter"
31
-
32
- def set_step(self, step: float) -> Self:
33
- self.step = step
34
- self.set_value(self.value)
35
- return self
36
-
37
- def set_range(self, range_min: float, range_max: float) -> Self:
38
- if range_min >= range_max:
39
- print(
40
- f"[Warning] : minimum value {range_min} is greater than or equal to maximum value {range_max}"
41
- )
42
- return self
43
- self.min_value = range_min
44
- self.max_value = range_max
45
- self.dirty_shape = True
46
-
47
- def get_debug_outlines(self):
48
- yield from super().get_debug_outlines()
49
- # yield from self.content.get_debug_outlines()
50
-
51
- def set_value(self, value: float) -> Self:
52
- value = max(self.min_value, min(self.max_value, value))
53
- value = round(value / self.step) * self.step
54
- self.value = round(value,10)
55
- self.dirty_shape = True
56
- return self
57
-
58
- def get_value(self) -> float:
59
- return self.value
60
-
61
- def get_range(self) -> float:
62
- return self.max_value - self.min_value
63
-
64
- def get_ratio(self) -> float:
65
- return (self.value-self.min_value) / (self.max_value - self.min_value)
66
-
67
- def _build_content(self) -> None:
68
- width = self.get_padded_width() * self.get_ratio()
69
- self.content.set_size((width, self.get_padded_height()))
70
- self.content.rect.topleft = self.get_padded_rect().topleft
71
-
72
- def build(self) -> None:
73
- super().build()
74
- self._build_content()
@@ -1,84 +0,0 @@
1
- import batFramework as bf
2
- from typing import Self, Any, Callable
3
- from .toggle import Toggle
4
-
5
-
6
- class RadioVariable: ...
7
-
8
-
9
- class RadioButton(Toggle):
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
- )
21
-
22
- def set_radio_value(self, value: Any) -> Self:
23
- self.radio_value = value
24
-
25
- if self.radio_variable:
26
- self.radio_variable.update_buttons()
27
- return self
28
-
29
- def set_text(self, text: str) -> Self:
30
- flag = False
31
- if self.value == self.text or self.value is None:
32
- flag = True
33
- super().set_text(text)
34
- if flag:
35
- self.set_radio_value(self.text)
36
- return self
37
-
38
- def click(self) -> None:
39
- if self.radio_variable is None:
40
- return
41
- self.radio_variable.set_value(self.radio_value)
42
-
43
-
44
- class RadioVariable:
45
- def __init__(self) -> None:
46
- self.buttons: list[RadioButton] = []
47
- self.value = 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
53
-
54
- def link(self, *buttons: RadioButton) -> Self:
55
- if not buttons:
56
- return self
57
- for b in buttons:
58
- b.radio_variable = self
59
- self.buttons.extend(buttons)
60
-
61
- if self.value is None:
62
- self.set_value(buttons[0].radio_value)
63
- else:
64
- self.update_buttons()
65
- return self
66
-
67
- def unlink(self, *buttons) -> Self:
68
- for b in self.buttons:
69
- if b in buttons:
70
- b.radio_variable = None
71
- self.buttons = [b for b in self.buttons if b not in buttons]
72
- return self
73
-
74
- def set_value(self, value: Any) -> Self:
75
- if value == self.value:
76
- return
77
- self.value = value
78
- if self.modify_callback:
79
- self.modify_callback(value)
80
- self.update_buttons()
81
- return self
82
-
83
- def update_buttons(self):
84
- _ = [b.set_value(b.radio_value == self.value, False) for b in self.buttons]
@@ -1,240 +0,0 @@
1
- import batFramework as bf
2
- from .meter import Meter
3
- from .button import Button
4
- from .indicator import *
5
- from .meter import Meter
6
- from .shape import Shape
7
- from .interactiveWidget import InteractiveWidget
8
-
9
-
10
- class SliderHandle(Indicator, DraggableWidget):
11
- def __init__(self):
12
- super().__init__()
13
- self.set_color(bf.color.CLOUD_SHADE)
14
- self.old_key_repeat: tuple = (0, 0)
15
- self.parent : bf.ClickableWidget = self.parent
16
- def __str__(self) -> str:
17
- return "SliderHandle"
18
-
19
- def on_click_down(self, button: int) -> None:
20
- if not self.parent.is_enabled():
21
- return
22
- super().on_click_down(button)
23
- if button == 1:
24
- self.parent.get_focus()
25
-
26
- def on_exit(self) -> None:
27
- self.is_hovered = False
28
- self.do_on_exit()
29
-
30
- def do_on_drag(
31
- self, drag_start: tuple[float, float], drag_end: tuple[float, float]
32
- ) -> None:
33
- if not self.parent.is_enabled():
34
- return
35
- super().do_on_drag(drag_start, drag_end)
36
- m: Meter = self.parent.meter
37
- r = m.get_padded_rect()
38
- position = self.rect.centerx
39
- self.rect.clamp_ip(r)
40
- # Adjust handle position to value
41
- new_value = self.parent.position_to_value(position)
42
- self.parent.set_value(new_value)
43
- self.rect.centerx = self.parent.value_to_position(new_value)
44
-
45
- def top_at(self, x, y):
46
- return Widget.top_at(self, x, y)
47
-
48
-
49
- class SliderMeter(Meter, InteractiveWidget):
50
- def __str__(self) -> str:
51
- return "SliderMeter"
52
-
53
- def on_click_down(self, button: int) -> None:
54
- if not self.parent.is_enabled():
55
- return
56
- if button == 1:
57
- self.parent.get_focus()
58
- r = self.get_root()
59
- if r:
60
- pos = r.drawing_camera.screen_to_world(pygame.mouse.get_pos())[0]
61
- self.parent.set_value(self.parent.position_to_value(pos))
62
- self.do_on_click_down(button)
63
-
64
- class Slider(Button):
65
- def __init__(self, text: str, default_value: float = 1.0) -> None:
66
- super().__init__(text, None)
67
- self.gap: float | int = 0
68
- self.spacing: bf.spacing = bf.spacing.MANUAL
69
- self.modified_callback = None
70
- self.meter: SliderMeter = SliderMeter()
71
- self.handle = SliderHandle()
72
- self.add(self.meter, self.handle)
73
- self.meter.set_debug_color(bf.color.RED)
74
- self.set_value(default_value, True)
75
-
76
- def set_visible(self, value: bool) -> Self:
77
- self.handle.set_visible(value)
78
- self.meter.set_visible(value)
79
- return super().set_visible(value)
80
-
81
- def __str__(self) -> str:
82
- return "Slider"
83
-
84
- def set_gap(self, value: int | float) -> Self:
85
- value = max(0, value)
86
- self.gap = value
87
- return self
88
-
89
- def do_on_get_focus(self) -> None:
90
- super().do_on_get_focus()
91
- self.old_key_repeat = pygame.key.get_repeat()
92
- pygame.key.set_repeat(200, 50)
93
-
94
- def do_on_lose_focus(self) -> None:
95
- super().do_on_lose_focus()
96
- pygame.key.set_repeat(*self.old_key_repeat)
97
-
98
- def set_spacing(self, spacing: bf.spacing) -> Self:
99
- if spacing == self.spacing:
100
- return self
101
- self.spacing = spacing
102
- self.dirty_shape = True
103
- return self
104
-
105
- def set_modify_callback(self, callback) -> Self:
106
- self.modified_callback = callback
107
- return self
108
-
109
- def set_range(self, range_min: float, range_max: float) -> Self:
110
- self.meter.set_range(range_min, range_max)
111
- self.dirty_shape = True
112
- return self
113
-
114
- def set_step(self, step: float) -> Self:
115
- self.meter.set_step(step)
116
- self.dirty_shape = True
117
- return self
118
-
119
- def set_value(self, value, no_callback: bool = False) -> Self:
120
- if self.meter.value != value:
121
- self.meter.set_value(value)
122
- self.dirty_shape = True
123
- if self.modified_callback and (not no_callback):
124
- self.modified_callback(self.meter.value)
125
- return self
126
-
127
- def get_value(self) -> float:
128
- return self.meter.get_value()
129
-
130
- def do_on_key_down(self, key):
131
- if not self.is_enabled():
132
- return
133
- if key == pygame.K_RIGHT:
134
- self.set_value(self.meter.get_value() + self.meter.step)
135
- elif key == pygame.K_LEFT:
136
- self.set_value(self.meter.get_value() - self.meter.step)
137
-
138
- def do_on_click_down(self, button) -> None:
139
- if not self.is_enabled():
140
- return
141
- if button == 1:
142
- self.get_focus()
143
-
144
- def value_to_position(self, value: float) -> float:
145
- """
146
- Converts a value to a position on the meter, considering the step size.
147
- """
148
- rect = self.meter.get_padded_rect()
149
- value_range = self.meter.get_range()
150
- value = round(value / self.meter.step) * self.meter.step
151
- position_ratio = (value - self.meter.min_value) / value_range
152
- return (
153
- rect.left
154
- + (self.handle.rect.w / 2)
155
- + position_ratio * (rect.width - self.handle.rect.w)
156
- )
157
-
158
- def position_to_value(self, position: float) -> float:
159
- """
160
- Converts a position on the meter to a value, considering the step size.
161
- """
162
- handle_half = self.handle.rect.w / 2
163
- rect = self.meter.get_padded_rect()
164
- position = max(rect.left + handle_half, min(position, rect.right - handle_half))
165
-
166
- position_ratio = (position - rect.left - handle_half) / (
167
- rect.width - self.handle.rect.w
168
- )
169
- value_range = self.meter.get_range()
170
- value = self.meter.min_value + position_ratio * value_range
171
- return round(value / self.meter.step) * self.meter.step
172
-
173
- def get_min_required_size(self) -> tuple[float, float]:
174
- gap = self.gap if self.text else 0
175
- if not self.text_rect:
176
- self.text_rect.size = self._get_text_rect_required_size()
177
- w, h = self.text_rect.size
178
- return self.inflate_rect_by_padding((0, 0, w + gap + self.meter.get_min_required_size()[1], h)).size
179
-
180
- def _build_layout(self) -> None:
181
-
182
- gap = self.gap if self.text else 0
183
- self.text_rect.size = self._get_text_rect_required_size()
184
-
185
- #right part size
186
- meter_width = self.text_rect.h * 10
187
- if not self.autoresize_w:
188
- meter_width = self.get_padded_width() - self.text_rect.w - gap
189
- right_part_height = min(self.text_rect.h, self.font_object.point_size)
190
- self.meter.set_size_if_autoresize((meter_width,right_part_height))
191
- self.handle.set_size_if_autoresize((None,right_part_height))
192
-
193
-
194
- #join left and right
195
- joined_rect = pygame.FRect(
196
- 0, 0, self.text_rect.w + gap + meter_width, self.text_rect.h
197
- )
198
-
199
- if self.autoresize_h or self.autoresize_w:
200
- target_rect = self.inflate_rect_by_padding(joined_rect)
201
- if not self.autoresize_w:
202
- target_rect.w = self.rect.w
203
- if not self.autoresize_h:
204
- target_rect.h = self.rect.h
205
- if self.rect.size != target_rect.size:
206
- self.set_size(target_rect.size)
207
- self.build()
208
- return
209
-
210
- # ------------------------------------ size is ok
211
-
212
-
213
- offset = self._get_outline_offset() if self.show_text_outline else (0,0)
214
- padded_rect = self.get_padded_rect()
215
- padded_relative = padded_rect.move(-self.rect.x, -self.rect.y)
216
-
217
- self.align_text(joined_rect, padded_relative.move( offset), self.alignment)
218
- self.text_rect.midleft = joined_rect.midleft
219
-
220
- if self.text:
221
- match self.spacing:
222
- case bf.spacing.MAX:
223
- gap = padded_relative.right - self.text_rect.right - self.meter.rect.w
224
- case bf.spacing.MIN:
225
- gap = 0
226
-
227
- # place meter
228
-
229
- pos = self.text_rect.move(
230
- self.rect.x + gap -offset[0],
231
- self.rect.y + (self.text_rect.h / 2) - (right_part_height / 2) -offset[1],
232
- ).topright
233
- self.meter.rect.topleft = pos
234
- # place handle
235
-
236
- x = self.value_to_position(self.meter.value)
237
- r = self.meter.get_padded_rect()
238
- self.handle.set_center(x, r.centery)
239
-
240
- # self.handle.set_center(x,self.rect.top)
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,48 +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] = True
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(self):
43
- for widget in self.widgets:
44
- if self.lookup[widget]:
45
- continue
46
- for style in self.styles:
47
- style.apply(widget)
48
- self.lookup[widget] = True