batframework 1.0.9a11__py3-none-any.whl → 1.0.9a12__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.
- batFramework/__init__.py +2 -0
- batFramework/action.py +280 -279
- batFramework/actionContainer.py +105 -82
- batFramework/animatedSprite.py +80 -58
- batFramework/animation.py +91 -77
- batFramework/audioManager.py +156 -131
- batFramework/baseScene.py +249 -240
- batFramework/camera.py +245 -317
- batFramework/constants.py +57 -51
- batFramework/cutscene.py +239 -253
- batFramework/cutsceneManager.py +34 -34
- batFramework/drawable.py +107 -77
- batFramework/dynamicEntity.py +30 -30
- batFramework/easingController.py +58 -58
- batFramework/entity.py +130 -130
- batFramework/enums.py +171 -135
- batFramework/fontManager.py +65 -65
- batFramework/gui/__init__.py +28 -25
- batFramework/gui/animatedLabel.py +90 -89
- batFramework/gui/button.py +17 -17
- batFramework/gui/clickableWidget.py +244 -244
- batFramework/gui/collapseContainer.py +98 -0
- batFramework/gui/constraints/__init__.py +1 -1
- batFramework/gui/constraints/constraints.py +1066 -980
- batFramework/gui/container.py +220 -206
- batFramework/gui/debugger.py +140 -130
- batFramework/gui/draggableWidget.py +63 -44
- batFramework/gui/image.py +61 -58
- batFramework/gui/indicator.py +116 -113
- batFramework/gui/interactiveWidget.py +243 -239
- batFramework/gui/label.py +147 -344
- batFramework/gui/layout.py +442 -429
- batFramework/gui/meter.py +155 -96
- batFramework/gui/radioButton.py +43 -35
- batFramework/gui/root.py +228 -228
- batFramework/gui/scrollingContainer.py +282 -0
- batFramework/gui/selector.py +232 -250
- batFramework/gui/shape.py +286 -276
- batFramework/gui/slider.py +353 -397
- batFramework/gui/style.py +10 -10
- batFramework/gui/styleManager.py +49 -54
- batFramework/gui/syncedVar.py +43 -49
- batFramework/gui/textInput.py +331 -306
- batFramework/gui/textWidget.py +308 -0
- batFramework/gui/toggle.py +140 -128
- batFramework/gui/tooltip.py +35 -30
- batFramework/gui/widget.py +546 -521
- batFramework/manager.py +131 -134
- batFramework/particle.py +118 -118
- batFramework/propertyEaser.py +79 -79
- batFramework/renderGroup.py +34 -34
- batFramework/resourceManager.py +130 -130
- batFramework/scene.py +31 -31
- batFramework/sceneLayer.py +134 -138
- batFramework/sceneManager.py +200 -197
- batFramework/scrollingSprite.py +115 -115
- batFramework/sprite.py +46 -51
- batFramework/stateMachine.py +49 -54
- batFramework/templates/__init__.py +2 -1
- batFramework/templates/character.py +15 -0
- batFramework/templates/controller.py +158 -97
- batFramework/templates/stateMachine.py +39 -0
- batFramework/tileset.py +46 -46
- batFramework/timeManager.py +213 -213
- batFramework/transition.py +162 -162
- batFramework/triggerZone.py +22 -22
- batFramework/utils.py +306 -306
- {batframework-1.0.9a11.dist-info → batframework-1.0.9a12.dist-info}/LICENSE +20 -20
- {batframework-1.0.9a11.dist-info → batframework-1.0.9a12.dist-info}/METADATA +24 -17
- batframework-1.0.9a12.dist-info/RECORD +72 -0
- batframework-1.0.9a11.dist-info/RECORD +0 -67
- {batframework-1.0.9a11.dist-info → batframework-1.0.9a12.dist-info}/WHEEL +0 -0
- {batframework-1.0.9a11.dist-info → batframework-1.0.9a12.dist-info}/top_level.txt +0 -0
@@ -1,239 +1,243 @@
|
|
1
|
-
from .widget import Widget
|
2
|
-
from typing import Self
|
3
|
-
|
4
|
-
import
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
self.
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
if
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
self
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
return
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
"""
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
self.
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
return
|
183
|
-
|
184
|
-
def
|
185
|
-
return
|
186
|
-
|
187
|
-
def
|
188
|
-
return
|
189
|
-
|
190
|
-
def
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
self.
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
def
|
203
|
-
pass
|
204
|
-
|
205
|
-
def
|
206
|
-
|
207
|
-
|
208
|
-
def
|
209
|
-
|
210
|
-
|
211
|
-
def
|
212
|
-
pass
|
213
|
-
|
214
|
-
def
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
1
|
+
from .widget import Widget
|
2
|
+
from typing import Self
|
3
|
+
import pygame
|
4
|
+
from math import cos
|
5
|
+
import batFramework as bf
|
6
|
+
|
7
|
+
def children_has_focus(widget)->bool:
|
8
|
+
if isinstance(widget,InteractiveWidget) and widget.is_focused:
|
9
|
+
return True
|
10
|
+
for child in widget.children:
|
11
|
+
if children_has_focus(child):
|
12
|
+
return True
|
13
|
+
return False
|
14
|
+
|
15
|
+
|
16
|
+
class InteractiveWidget(Widget):
|
17
|
+
__focus_effect_cache = {}
|
18
|
+
def __init__(self, *args, **kwargs) -> None:
|
19
|
+
self.is_focused: bool = False
|
20
|
+
self.is_hovered: bool = False
|
21
|
+
self.is_clicked_down: list[bool] = [False]*5
|
22
|
+
self.focused_index = 0
|
23
|
+
self.click_pass_through : bool = False
|
24
|
+
super().__init__(*args, **kwargs)
|
25
|
+
|
26
|
+
|
27
|
+
def handle_event(self, event):
|
28
|
+
if self.is_hovered:
|
29
|
+
if event.type == pygame.MOUSEBUTTONDOWN:
|
30
|
+
self.is_clicked_down[event.button-1] = True
|
31
|
+
self.on_click_down(event.button,event)
|
32
|
+
elif event.type == pygame.MOUSEBUTTONUP:
|
33
|
+
self.is_clicked_down[event.button-1] = False
|
34
|
+
self.on_click_up(event.button,event)
|
35
|
+
|
36
|
+
if self.is_focused:
|
37
|
+
if event.type == pygame.KEYDOWN:
|
38
|
+
self.on_key_down(event.key,event)
|
39
|
+
elif event.type == pygame.KEYUP:
|
40
|
+
self.on_key_up(event.key,event)
|
41
|
+
|
42
|
+
def set_click_pass_through(self,pass_through:bool)->Self:
|
43
|
+
"""
|
44
|
+
# Allows mouse click events to pass through this widget to underlying widgets if True.
|
45
|
+
"""
|
46
|
+
self.click_pass_through = pass_through
|
47
|
+
return self
|
48
|
+
|
49
|
+
|
50
|
+
def allow_focus_to_self(self) -> bool:
|
51
|
+
return self.visible
|
52
|
+
|
53
|
+
def get_focus(self) -> bool:
|
54
|
+
if self.allow_focus_to_self() and ((r := self.get_root()) is not None):
|
55
|
+
r.focus_on(self)
|
56
|
+
return True
|
57
|
+
return False
|
58
|
+
|
59
|
+
def lose_focus(self) -> bool:
|
60
|
+
if self.is_focused and ((r := self.get_root()) is not None):
|
61
|
+
r.focus_on(None)
|
62
|
+
return True
|
63
|
+
return False
|
64
|
+
|
65
|
+
def set_parent(self, parent: Widget) -> Self:
|
66
|
+
if parent is None and children_has_focus(self):
|
67
|
+
self.get_root().clear_focused()
|
68
|
+
# pass focus on
|
69
|
+
|
70
|
+
return super().set_parent(parent)
|
71
|
+
|
72
|
+
def get_interactive_widgets(self):
|
73
|
+
"""Retrieve all interactive widgets in the tree, in depth-first order."""
|
74
|
+
widgets = []
|
75
|
+
stack = [self]
|
76
|
+
while stack:
|
77
|
+
widget = stack.pop()
|
78
|
+
if isinstance(widget, InteractiveWidget) and widget.allow_focus_to_self():
|
79
|
+
widgets.append(widget)
|
80
|
+
stack.extend(reversed(widget.children)) # Add children in reverse for left-to-right traversal
|
81
|
+
return widgets
|
82
|
+
|
83
|
+
def find_next_widget(self, current):
|
84
|
+
"""Find the next interactive widget, considering parent and sibling relationships."""
|
85
|
+
if current.is_root:
|
86
|
+
return None # Root has no parent
|
87
|
+
|
88
|
+
if hasattr(current.parent, "layout"):
|
89
|
+
siblings = current.parent.get_interactive_children()
|
90
|
+
else:
|
91
|
+
siblings = current.parent.children
|
92
|
+
|
93
|
+
start_index = siblings.index(current)
|
94
|
+
good_index = -1
|
95
|
+
for i in range(start_index + 1, len(siblings)):
|
96
|
+
sibling = siblings[i]
|
97
|
+
if isinstance(sibling,InteractiveWidget) and not(sibling is current) :
|
98
|
+
if sibling.allow_focus_to_self():
|
99
|
+
good_index = i
|
100
|
+
break
|
101
|
+
if good_index >= 0:
|
102
|
+
# Not the last child, return the next sibling
|
103
|
+
return siblings[good_index]
|
104
|
+
else:
|
105
|
+
# Current is the last child, move to parent's next sibling
|
106
|
+
return self.find_next_widget(current.parent)
|
107
|
+
|
108
|
+
def find_prev_widget(self, current : "Widget"):
|
109
|
+
"""Find the previous interactive widget, considering parent and sibling relationships."""
|
110
|
+
if current.is_root:
|
111
|
+
return None # Root has no parent
|
112
|
+
|
113
|
+
# siblings = [c for c in current.parent.children if isinstance(c,InteractiveWidget) and c.allow_focus_to_self()]
|
114
|
+
if hasattr(current.parent, "layout"):
|
115
|
+
siblings = current.parent.get_interactive_children()
|
116
|
+
else:
|
117
|
+
siblings = current.parent.children
|
118
|
+
start_index = siblings.index(current)
|
119
|
+
good_index = -1
|
120
|
+
for i in range(start_index-1,-1,-1):
|
121
|
+
sibling = siblings[i]
|
122
|
+
if isinstance(sibling,InteractiveWidget) and not(sibling is current) :
|
123
|
+
if sibling.allow_focus_to_self():
|
124
|
+
good_index = i
|
125
|
+
break
|
126
|
+
if good_index >= 0:
|
127
|
+
# Not the first child, return the previous sibling
|
128
|
+
return siblings[good_index]
|
129
|
+
else:
|
130
|
+
# Current is the first child, move to parent's previous sibling
|
131
|
+
return self.find_prev_widget(current.parent)
|
132
|
+
|
133
|
+
def focus_next_tab(self, previous_widget):
|
134
|
+
"""Focus the next interactive widget."""
|
135
|
+
if previous_widget:
|
136
|
+
next_widget = self.find_next_widget(previous_widget)
|
137
|
+
if next_widget:
|
138
|
+
next_widget.get_focus()
|
139
|
+
|
140
|
+
def focus_prev_tab(self, previous_widget):
|
141
|
+
"""Focus the previous interactive widget."""
|
142
|
+
if previous_widget:
|
143
|
+
prev_widget = self.find_prev_widget(previous_widget)
|
144
|
+
if prev_widget:
|
145
|
+
prev_widget.get_focus()
|
146
|
+
|
147
|
+
|
148
|
+
|
149
|
+
def on_key_down(self, key,event) -> None:
|
150
|
+
self.do_on_key_down(key,event)
|
151
|
+
|
152
|
+
def on_key_up(self, key,event) -> None:
|
153
|
+
self.do_on_key_up(key,event)
|
154
|
+
|
155
|
+
def on_click_down(self, button: int,event=None) -> None:
|
156
|
+
if not self.click_pass_through:
|
157
|
+
event.consumed = True
|
158
|
+
self.do_on_click_down(button,event)
|
159
|
+
|
160
|
+
def on_click_up(self, button: int,event=None) -> None:
|
161
|
+
if not self.click_pass_through:
|
162
|
+
event.consumed = True
|
163
|
+
self.do_on_click_up(button,event)
|
164
|
+
|
165
|
+
def on_get_focus(self) -> None:
|
166
|
+
self.is_focused = True
|
167
|
+
if isinstance(self.parent,bf.gui.InteractiveWidget):
|
168
|
+
self.parent.set_focused_child(self)
|
169
|
+
self.do_on_get_focus()
|
170
|
+
|
171
|
+
def on_lose_focus(self) -> None:
|
172
|
+
self.is_focused = False
|
173
|
+
self.do_on_lose_focus()
|
174
|
+
|
175
|
+
def do_on_get_focus(self) -> None:
|
176
|
+
pass
|
177
|
+
|
178
|
+
def do_on_lose_focus(self) -> None:
|
179
|
+
pass
|
180
|
+
|
181
|
+
def do_on_key_down(self, key,event) -> None:
|
182
|
+
return
|
183
|
+
|
184
|
+
def do_on_key_up(self, key,event) -> None:
|
185
|
+
return
|
186
|
+
|
187
|
+
def do_on_click_down(self, button: int,event=None) -> None:
|
188
|
+
return
|
189
|
+
|
190
|
+
def do_on_click_up(self, button: int,event=None) -> None:
|
191
|
+
return
|
192
|
+
|
193
|
+
def on_enter(self) -> None:
|
194
|
+
self.is_hovered = True
|
195
|
+
self.do_on_enter()
|
196
|
+
|
197
|
+
def on_exit(self) -> None:
|
198
|
+
self.is_hovered = False
|
199
|
+
self.is_clicked_down = [False]*5
|
200
|
+
self.do_on_exit()
|
201
|
+
|
202
|
+
def do_on_enter(self) -> None:
|
203
|
+
pass
|
204
|
+
|
205
|
+
def do_on_exit(self) -> None:
|
206
|
+
pass
|
207
|
+
|
208
|
+
def on_mouse_motion(self, x, y) -> None:
|
209
|
+
self.do_on_mouse_motion(x, y)
|
210
|
+
|
211
|
+
def do_on_mouse_motion(self, x, y) -> None:
|
212
|
+
pass
|
213
|
+
|
214
|
+
def set_focused_child(self, child: "InteractiveWidget"):
|
215
|
+
pass
|
216
|
+
|
217
|
+
def draw_focused(self, camera: bf.Camera) -> None:
|
218
|
+
if isinstance(self,bf.gui.Shape):
|
219
|
+
prop = 8
|
220
|
+
pulse = int(prop * 0.75 - (prop * cos(pygame.time.get_ticks() / 100) / 4))
|
221
|
+
delta = (pulse // 2) * 2 # ensure even
|
222
|
+
|
223
|
+
# Get rect in screen space, inflated for visual effect
|
224
|
+
screen_rect = camera.world_to_screen(self.rect.inflate(prop+self.outline_width, prop+self.outline_width))
|
225
|
+
|
226
|
+
# Shrink for inner pulsing border
|
227
|
+
inner = screen_rect.inflate(-delta, -delta)
|
228
|
+
inner.topleft = 0,0
|
229
|
+
inner.w = round(inner.w)
|
230
|
+
inner.h = round(inner.h)
|
231
|
+
|
232
|
+
surface = InteractiveWidget.__focus_effect_cache.get(inner.size)
|
233
|
+
if surface is None:
|
234
|
+
surface = pygame.Surface(inner.size)
|
235
|
+
InteractiveWidget.__focus_effect_cache[inner.size] = surface
|
236
|
+
|
237
|
+
surface.set_colorkey((0,0,0))
|
238
|
+
pygame.draw.rect(surface, "white", inner, 2, *self.border_radius)
|
239
|
+
pygame.draw.rect(surface, "black", inner.inflate(-1 * min(16,inner.w*0.75),0), 2)
|
240
|
+
pygame.draw.rect(surface, "black", inner.inflate(0,-1 * min(16,inner.h*0.75)), 2)
|
241
|
+
inner.center = screen_rect.center
|
242
|
+
camera.surface.blit(surface,inner)
|
243
|
+
|