batframework 1.0.10__py3-none-any.whl → 2.0.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 (81) hide show
  1. batFramework/__init__.py +84 -52
  2. batFramework/action.py +280 -252
  3. batFramework/actionContainer.py +105 -38
  4. batFramework/animatedSprite.py +81 -117
  5. batFramework/animation.py +91 -0
  6. batFramework/audioManager.py +156 -85
  7. batFramework/baseScene.py +249 -0
  8. batFramework/camera.py +245 -123
  9. batFramework/constants.py +57 -75
  10. batFramework/cutscene.py +239 -119
  11. batFramework/cutsceneManager.py +34 -0
  12. batFramework/drawable.py +107 -0
  13. batFramework/dynamicEntity.py +30 -23
  14. batFramework/easingController.py +58 -0
  15. batFramework/entity.py +130 -123
  16. batFramework/enums.py +171 -0
  17. batFramework/fontManager.py +65 -0
  18. batFramework/gui/__init__.py +28 -14
  19. batFramework/gui/animatedLabel.py +90 -0
  20. batFramework/gui/button.py +18 -84
  21. batFramework/gui/clickableWidget.py +244 -0
  22. batFramework/gui/collapseContainer.py +98 -0
  23. batFramework/gui/constraints/__init__.py +1 -0
  24. batFramework/gui/constraints/constraints.py +1066 -0
  25. batFramework/gui/container.py +220 -49
  26. batFramework/gui/debugger.py +140 -47
  27. batFramework/gui/draggableWidget.py +63 -0
  28. batFramework/gui/image.py +61 -23
  29. batFramework/gui/indicator.py +116 -40
  30. batFramework/gui/interactiveWidget.py +243 -22
  31. batFramework/gui/label.py +147 -110
  32. batFramework/gui/layout.py +442 -81
  33. batFramework/gui/meter.py +155 -0
  34. batFramework/gui/radioButton.py +43 -0
  35. batFramework/gui/root.py +228 -60
  36. batFramework/gui/scrollingContainer.py +282 -0
  37. batFramework/gui/selector.py +232 -0
  38. batFramework/gui/shape.py +286 -86
  39. batFramework/gui/slider.py +353 -0
  40. batFramework/gui/style.py +10 -0
  41. batFramework/gui/styleManager.py +49 -0
  42. batFramework/gui/syncedVar.py +43 -0
  43. batFramework/gui/textInput.py +331 -0
  44. batFramework/gui/textWidget.py +308 -0
  45. batFramework/gui/toggle.py +140 -62
  46. batFramework/gui/tooltip.py +35 -0
  47. batFramework/gui/widget.py +546 -307
  48. batFramework/manager.py +131 -50
  49. batFramework/particle.py +118 -0
  50. batFramework/propertyEaser.py +79 -0
  51. batFramework/renderGroup.py +34 -0
  52. batFramework/resourceManager.py +130 -0
  53. batFramework/scene.py +31 -226
  54. batFramework/sceneLayer.py +134 -0
  55. batFramework/sceneManager.py +200 -165
  56. batFramework/scrollingSprite.py +115 -0
  57. batFramework/sprite.py +46 -0
  58. batFramework/stateMachine.py +49 -51
  59. batFramework/templates/__init__.py +2 -0
  60. batFramework/templates/character.py +15 -0
  61. batFramework/templates/controller.py +158 -0
  62. batFramework/templates/stateMachine.py +39 -0
  63. batFramework/tileset.py +46 -0
  64. batFramework/timeManager.py +213 -0
  65. batFramework/transition.py +162 -157
  66. batFramework/triggerZone.py +22 -22
  67. batFramework/utils.py +306 -184
  68. {batframework-1.0.10.dist-info → batframework-2.0.0.dist-info}/LICENSE +1 -1
  69. {batframework-1.0.10.dist-info → batframework-2.0.0.dist-info}/METADATA +3 -4
  70. batframework-2.0.0.dist-info/RECORD +72 -0
  71. batFramework/cutsceneBlocks.py +0 -176
  72. batFramework/debugger.py +0 -48
  73. batFramework/easing.py +0 -71
  74. batFramework/gui/constraints.py +0 -204
  75. batFramework/gui/frame.py +0 -19
  76. batFramework/particles.py +0 -77
  77. batFramework/time.py +0 -75
  78. batFramework/transitionManager.py +0 -0
  79. batframework-1.0.10.dist-info/RECORD +0 -43
  80. {batframework-1.0.10.dist-info → batframework-2.0.0.dist-info}/WHEEL +0 -0
  81. {batframework-1.0.10.dist-info → batframework-2.0.0.dist-info}/top_level.txt +0 -0
@@ -1,84 +1,18 @@
1
- from .label import Label
2
- import batFramework as bf
3
- from types import FunctionType
4
- from typing import Self
5
- from .interactiveWidget import InteractiveWidget
6
- import pygame
7
-
8
- class Button(Label,InteractiveWidget):
9
- _cache = {}
10
-
11
- def __init__(self, text: str, callback : FunctionType =None) -> None:
12
- # Label.__init__(self,text)
13
- self.callback = callback
14
- self.click_action = bf.Action("click").add_mouse_control(1)
15
- self.hover_action = bf.Action("hover").add_mouse_control(pygame.MOUSEMOTION)
16
- self.is_hovered : bool = False
17
- self.is_clicking : bool = False
18
- super().__init__(text=text)
19
- self.set_debug_color("cyan")
20
-
21
-
22
- def set_callback(self,callback : FunctionType = None)->Self:
23
- self.callback = callback
24
- return self
25
-
26
- def on_get_focus(self):
27
- super().on_get_focus()
28
- self.build()
29
-
30
- def on_lose_focus(self):
31
- super().on_lose_focus()
32
- self.build()
33
-
34
- def to_string_id(self)->str:
35
- return f"Button({self._text})"
36
-
37
- def click(self)->None:
38
- if self.callback and not self.is_clicking:
39
- self.is_clicking = True
40
- self.callback()
41
- self.is_clicking = False
42
-
43
-
44
- def do_process_actions(self,event):
45
- self.click_action.process_event(event)
46
- self.hover_action.process_event(event)
47
-
48
- def do_reset_actions(self):
49
- self.click_action.reset()
50
- self.hover_action.reset()
51
-
52
- def do_handle_event(self,event)->None:
53
- res = False
54
- if self.click_action.is_active():
55
- root = self.get_root()
56
- if root.hovered == self:
57
- if not self.is_focused : self.get_focus()
58
- self.click()
59
- elif self.hover_action.is_active():
60
- root = self.get_root()
61
- if root:
62
- if self.is_hovered and root.hovered != self:
63
- self.is_hovered = False
64
- self.build()
65
- if not self.is_hovered and root.hovered == self:
66
- self.is_hovered = True
67
- self.build()
68
- return res
69
-
70
-
71
-
72
- def build(self)->None:
73
- super().build()
74
- if self.is_hovered:
75
- hover_surf = Button._cache.get(self.surface.get_size(),None)
76
- if hover_surf is None:
77
- hover_surf = pygame.Surface(self.surface.get_size()).convert_alpha()
78
- hover_surf.fill((30,30,30,0))
79
- Button._cache[self.surface.get_size()] = hover_surf
80
- self.surface.blit(hover_surf,(0,0),special_flags = pygame.BLEND_ADD)
81
-
82
-
83
- def apply_contraints(self)->None:
84
- super().apply_contraints()
1
+ from .label import Label
2
+ import batFramework as bf
3
+ from typing import Self, Callable,Any
4
+ from .clickableWidget import ClickableWidget
5
+
6
+
7
+ class Button(Label, ClickableWidget):
8
+ def __init__(self, text: str = "", callback: Callable[[],Any] = None) -> None:
9
+ super().__init__(text=text)
10
+ self.set_callback(callback)
11
+
12
+ def __str__(self) -> str:
13
+ return f"Button('{self.text_widget.text}')"
14
+
15
+ def get_min_required_size(self):
16
+ res = super().get_min_required_size()
17
+ res = res[0],res[1]+self.unpressed_relief
18
+ return res
@@ -0,0 +1,244 @@
1
+ import batFramework as bf
2
+ from typing import Self, Callable, Any
3
+ from .interactiveWidget import InteractiveWidget
4
+ from .shape import Shape
5
+ import pygame
6
+
7
+
8
+ class ClickableWidget(Shape, InteractiveWidget):
9
+ _cache: dict = {}
10
+
11
+ def __init__(self, callback: Callable[[],Any] = None, *args, **kwargs) -> None:
12
+ super().__init__(*args, **kwargs)
13
+ self.callback = callback
14
+ self.is_pressed: bool = False # the state where the button is being held down (releasing will trigger callback)
15
+ self.is_enabled: bool = True #
16
+ self.hover_cursor = bf.const.DEFAULT_HOVER_CURSOR
17
+ self.click_cursor = bf.const.DEFAULT_CLICK_CURSOR
18
+
19
+ self.click_down_sound = None
20
+ self.click_up_sound = None
21
+ self.get_focus_sound = None
22
+ self.lose_focus_sound = None
23
+
24
+ self.pressed_relief: int = 1 # Depth effect height when pressed
25
+ self.unpressed_relief: int = 2 # Depth effect height when released (default)
26
+ self.silent_focus: bool = False
27
+ self.set_debug_color("cyan")
28
+ self.set_relief(self.unpressed_relief)
29
+ self.set_click_pass_through(False)
30
+
31
+ def get_min_required_size(self) -> tuple[float, float]:
32
+ res = super().get_min_required_size()
33
+ res = res[0],res[1]+self.unpressed_relief
34
+ return res
35
+
36
+ def set_unpressed_relief(self, relief: int) -> Self:
37
+ if relief == self.unpressed_relief:
38
+ return self
39
+ self.unpressed_relief = relief
40
+ self.dirty_shape = True
41
+ if not self.is_pressed:
42
+ self.set_relief(relief)
43
+ return self
44
+
45
+ def set_pressed_relief(self, relief: int) -> Self:
46
+ if relief == self.pressed_relief:
47
+ return self
48
+ self.pressed_relief = relief
49
+ self.dirty_shape = True
50
+ if self.is_pressed:
51
+ self.set_relief(relief)
52
+ return self
53
+
54
+ def set_silent_focus(self, value: bool) -> Self:
55
+ self.silent_focus = value
56
+ return self
57
+
58
+ def set_click_down_sound(self, sound_name: str) -> Self:
59
+ self.click_down_sound = sound_name
60
+ return self
61
+
62
+ def set_click_up_sound(self, sound_name: str) -> Self:
63
+ self.click_up_sound = sound_name
64
+ return self
65
+
66
+ def set_get_focus_sound(self, sound_name: str) -> Self:
67
+ self.get_focus_sound = sound_name
68
+ return self
69
+
70
+ def set_lose_focus_sound(self, sound_name: str) -> Self:
71
+ self.lose_focus_sound = sound_name
72
+ return self
73
+
74
+ def set_hover_cursor(self, cursor: pygame.Cursor) -> Self:
75
+ self.hover_cursor = cursor
76
+ return self
77
+
78
+ def set_click_cursor(self, cursor: pygame.Cursor) -> Self:
79
+ self.click_cursor = cursor
80
+ return self
81
+
82
+ def get_surface_filter(self) -> pygame.Surface | None:
83
+ size = int(self.rect.w), int(self.rect.h)
84
+ surface_filter = ClickableWidget._cache.get((size, *self.border_radius), None)
85
+ if surface_filter is None:
86
+ # Create a mask from the original surface
87
+ mask = pygame.mask.from_surface(self.surface, threshold=0)
88
+
89
+ silhouette_surface = mask.to_surface(
90
+ setcolor=(30, 30, 30), unsetcolor=(0, 0, 0)
91
+ )
92
+
93
+ ClickableWidget._cache[(size, *self.border_radius)] = silhouette_surface
94
+
95
+ surface_filter = silhouette_surface
96
+
97
+ return surface_filter
98
+
99
+ def allow_focus_to_self(self) -> bool:
100
+ return True
101
+
102
+ def enable(self) -> Self:
103
+ self.is_enabled = True
104
+ self.dirty_surface = True
105
+ return self
106
+
107
+ def disable(self) -> Self:
108
+ self.is_enabled = False
109
+ self.dirty_surface = True
110
+ return self
111
+
112
+ def set_callback(self, callback: Callable[[],Any]) -> Self:
113
+ self.callback = callback
114
+ return self
115
+
116
+ def on_get_focus(self):
117
+ super().on_get_focus()
118
+ if self.get_focus_sound and not self.silent_focus:
119
+ if self.parent_scene and self.parent_scene.visible:
120
+ bf.AudioManager().play_sound(self.get_focus_sound)
121
+ if self.silent_focus:
122
+ self.silent_focus = False
123
+
124
+ def on_lose_focus(self):
125
+ super().on_lose_focus()
126
+ if self.lose_focus_sound and not self.silent_focus:
127
+ if self.parent_scene and self.parent_scene.visible:
128
+ bf.AudioManager().play_sound(self.lose_focus_sound)
129
+ if self.silent_focus:
130
+ self.silent_focus = False
131
+
132
+ def __str__(self) -> str:
133
+ return f"ClickableWidget"
134
+
135
+ def click(self, force=False) -> None:
136
+ if not self.is_enabled and not force:
137
+ return False
138
+ if self.callback is not None:
139
+ self.callback()
140
+ return True
141
+ return False
142
+
143
+ def on_key_down(self, key,event):
144
+ if key == pygame.K_SPACE:
145
+ self.on_click_down(1,event)
146
+ self.do_on_key_down(key,event)
147
+
148
+ def on_key_up(self, key,event):
149
+ if key == pygame.K_SPACE:
150
+ self.on_click_up(1,event)
151
+ self.do_on_key_down(key,event)
152
+
153
+ def on_click_down(self, button,event) -> None :
154
+ if button < 1 or button > 5 :
155
+ return
156
+ self.is_clicked_down[button-1] = True
157
+ if button != 1:
158
+ return
159
+ event.consumed = not self.click_pass_through
160
+ if self.is_enabled and self.get_focus():
161
+ self.is_pressed = True
162
+ if self.click_down_sound:
163
+ bf.AudioManager().play_sound(self.click_down_sound)
164
+ pygame.mouse.set_cursor(self.click_cursor)
165
+ self.set_relief(self.pressed_relief)
166
+ self.do_on_click_down(button,event)
167
+
168
+ def on_click_up(self, button,event):
169
+ if button < 1 or button > 5 :
170
+ return
171
+ self.is_clicked_down[button-1] = False
172
+ if button != 1 :
173
+ return
174
+ event.consumed = not self.click_pass_through
175
+ if self.is_enabled and self.is_pressed:
176
+ self.is_pressed = False
177
+ if self.click_up_sound:
178
+ bf.AudioManager().play_sound(self.click_up_sound)
179
+ self.set_relief(self.unpressed_relief)
180
+ self.click()
181
+ self.do_on_click_up(button,event)
182
+
183
+ def on_enter(self) -> None:
184
+ self.is_hovered = True
185
+ if not self.is_enabled:
186
+ return
187
+ super().on_enter()
188
+ self.dirty_surface = True
189
+ pygame.mouse.set_cursor(self.hover_cursor)
190
+
191
+ def on_exit(self) -> None:
192
+ super().on_exit()
193
+ if self.is_pressed:
194
+ self.set_relief(self.unpressed_relief)
195
+ self.is_pressed = False
196
+ self.dirty_surface = True
197
+ pygame.mouse.set_cursor(bf.const.DEFAULT_CURSOR)
198
+
199
+ def on_lose_focus(self):
200
+ super().on_lose_focus()
201
+ self.on_exit()
202
+
203
+ def _paint_disabled(self) -> None:
204
+ self.surface.blit(
205
+ self.get_surface_filter(), (0, 0), special_flags=pygame.BLEND_RGB_SUB
206
+ )
207
+
208
+ def _paint_hovered(self) -> None:
209
+ self.surface.blit(
210
+ self.get_surface_filter(), (0, 0), special_flags=pygame.BLEND_RGB_ADD
211
+ )
212
+
213
+ def get_inner_rect(self) -> pygame.FRect:
214
+ return pygame.FRect(
215
+ self.rect.x + self.padding[0],
216
+ self.rect.y + self.padding[1] + (self.unpressed_relief - self.pressed_relief if self.is_pressed else 0),
217
+ self.rect.w - self.padding[2] - self.padding[0],
218
+ self.rect.h - self.unpressed_relief - self.padding[1] - self.padding[3],
219
+ )
220
+
221
+ def get_local_inner_rect(self) -> pygame.FRect:
222
+ return pygame.FRect(
223
+ self.padding[0],
224
+ self.padding[1] + (self.unpressed_relief - self.pressed_relief if self.is_pressed else 0),
225
+ self.rect.w - self.padding[2] - self.padding[0],
226
+ self.rect.h - self.unpressed_relief - self.padding[1] - self.padding[3],
227
+ )
228
+
229
+
230
+ def _get_elevated_rect(self) -> pygame.FRect:
231
+ return pygame.FRect(
232
+ 0,
233
+ self.unpressed_relief - self.pressed_relief if self.is_pressed else 0,
234
+ self.rect.w,
235
+ self.rect.h - self.unpressed_relief,
236
+ )
237
+
238
+ def paint(self) -> None:
239
+ super().paint()
240
+ if not self.is_enabled:
241
+ self._paint_disabled()
242
+ elif self.is_hovered:
243
+ self._paint_hovered()
244
+
@@ -0,0 +1,98 @@
1
+ from .container import Container
2
+ from .scrollingContainer import ScrollingContainer
3
+ from .interactiveWidget import InteractiveWidget
4
+ from .toggle import Toggle
5
+ from .shape import Shape
6
+ from .indicator import ArrowIndicator
7
+ from .syncedVar import SyncedVar
8
+ from .layout import Column
9
+ import batFramework as bf
10
+ from .syncedVar import SyncedVar
11
+ from .widget import Widget
12
+ from .layout import Layout
13
+
14
+
15
+ class CollapseIndicator(ArrowIndicator):
16
+ def __init__(self,synced_var:SyncedVar[bool]):
17
+ super().__init__(bf.direction.RIGHT)
18
+ synced_var.bind(self,self.on_state_change)
19
+
20
+ def on_state_change(self,state:bool):
21
+ self.set_arrow_direction(bf.direction.DOWN if state else bf.direction.RIGHT)
22
+
23
+ def top_at(self, x: float, y: float) -> "None|Widget":
24
+ r = super().top_at(x, y)
25
+ if r is self:
26
+ return None
27
+ return r
28
+
29
+
30
+ class CollapseContainer(Shape,InteractiveWidget):
31
+ def __init__(self, text:str, layout:Layout=None, *children:Widget, **kwargs):
32
+ super().__init__(**kwargs)
33
+ self.state = SyncedVar[bool](False)
34
+ self.state.bind(self,self._on_state_change)
35
+ self.toggle = Toggle(text,synced_var=self.state)
36
+ self.toggle.set_autoresize_w(False)
37
+ self.container = Container(layout,*children)
38
+ self.container.set_autoresize_w(False)
39
+ self.add(self.toggle,self.container)
40
+ self.state.value = False
41
+ self.toggle.set_indicator(CollapseIndicator(self.state))
42
+ self.toggle.indicator.add_constraints(bf.gui.AspectRatio(1,reference_axis=bf.axis.VERTICAL))
43
+
44
+ def __str__(self):
45
+ return "CollapseContainer"
46
+
47
+ def _on_state_change(self,value):
48
+ print("state is ",value)
49
+ self.container.show() if value else self.container.hide()
50
+ self.dirty_shape = True
51
+
52
+ def allow_focus_to_self(self):
53
+ return super().allow_focus_to_self() and self.toggle.allow_focus_to_self()
54
+
55
+ def get_focus(self):
56
+ if self.allow_focus_to_self() and ((r := self.get_root()) is not None):
57
+ r.focus_on(self.toggle)
58
+ return True
59
+ return False
60
+
61
+ def build(self):
62
+ res = False
63
+ min_size = self.get_min_required_size()
64
+ target_size = self.resolve_size(min_size)
65
+ if self.rect.size != target_size :
66
+ self.set_size(target_size)
67
+ res = True
68
+
69
+ inner = self.get_inner_rect()
70
+ self.toggle.set_size((inner.w,None))
71
+ self.toggle.set_position(*inner.topleft)
72
+ if self.state.value:
73
+ self.container.set_size((inner.w,None))
74
+ self.container.set_position(*self.toggle.rect.bottomleft)
75
+ return res
76
+
77
+ def apply_updates(self, pass_type):
78
+
79
+ if pass_type == "pre":
80
+ self.apply_pre_updates()
81
+ if self.state.value : self.container.apply_updates("pre")
82
+ self.toggle.apply_updates("pre")
83
+ elif pass_type == "post":
84
+ if self.state.value : self.container.apply_updates("post")
85
+ self.toggle.apply_updates("post")
86
+ self.apply_post_updates(skip_draw=not self.visible)
87
+
88
+
89
+ def get_min_required_size(self):
90
+ t_min = self.toggle.get_min_required_size()
91
+ if self.container.layout:
92
+ c_min = self.container.expand_rect_with_padding((0,0,*self.container.layout.get_raw_size())).size
93
+ else:
94
+ c_min = self.container.get_min_required_size()
95
+ if not self.state.value:
96
+ c_min = (c_min[0],0)
97
+
98
+ return self.expand_rect_with_padding((0,0,max(t_min[0],c_min[0]),t_min[1]+c_min[1])).size
@@ -0,0 +1 @@
1
+ from . import constraints