batframework 1.0.8a1__py3-none-any.whl → 1.0.8a3__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/action.py +30 -14
- batFramework/actionContainer.py +5 -3
- batFramework/audioManager.py +0 -1
- batFramework/camera.py +29 -24
- batFramework/cutscene.py +2 -4
- batFramework/entity.py +9 -2
- batFramework/enums.py +11 -2
- batFramework/fontManager.py +1 -1
- batFramework/gui/__init__.py +3 -1
- batFramework/gui/button.py +5 -2
- batFramework/gui/clickableWidget.py +42 -29
- batFramework/gui/constraints/constraints.py +269 -57
- batFramework/gui/container.py +39 -21
- batFramework/gui/debugger.py +18 -11
- batFramework/gui/dialogueBox.py +20 -17
- batFramework/gui/draggableWidget.py +7 -5
- batFramework/gui/image.py +27 -15
- batFramework/gui/indicator.py +1 -4
- batFramework/gui/interactiveWidget.py +91 -30
- batFramework/gui/label.py +44 -35
- batFramework/gui/layout.py +115 -43
- batFramework/gui/meter.py +3 -8
- batFramework/gui/radioButton.py +47 -25
- batFramework/gui/root.py +50 -25
- batFramework/gui/shape.py +14 -19
- batFramework/gui/slider.py +70 -44
- batFramework/gui/style.py +10 -0
- batFramework/gui/styleManager.py +48 -0
- batFramework/gui/textInput.py +25 -22
- batFramework/gui/toggle.py +42 -29
- batFramework/gui/widget.py +176 -115
- batFramework/object.py +9 -10
- batFramework/renderGroup.py +7 -2
- batFramework/scene.py +70 -49
- batFramework/sceneManager.py +15 -20
- batFramework/scrollingSprite.py +5 -3
- batFramework/sprite.py +20 -14
- batFramework/stateMachine.py +1 -2
- batFramework/tileset.py +5 -5
- batFramework/utils.py +12 -10
- {batframework-1.0.8a1.dist-info → batframework-1.0.8a3.dist-info}/METADATA +1 -1
- batframework-1.0.8a3.dist-info/RECORD +58 -0
- {batframework-1.0.8a1.dist-info → batframework-1.0.8a3.dist-info}/WHEEL +1 -1
- batframework-1.0.8a1.dist-info/RECORD +0 -56
- {batframework-1.0.8a1.dist-info → batframework-1.0.8a3.dist-info}/LICENCE +0 -0
- {batframework-1.0.8a1.dist-info → batframework-1.0.8a3.dist-info}/top_level.txt +0 -0
batFramework/gui/layout.py
CHANGED
@@ -1,12 +1,13 @@
|
|
1
1
|
import batFramework as bf
|
2
2
|
from .widget import Widget
|
3
3
|
from .constraints.constraints import *
|
4
|
-
from typing import Self,TYPE_CHECKING
|
4
|
+
from typing import Self, TYPE_CHECKING
|
5
5
|
import pygame
|
6
6
|
|
7
7
|
if TYPE_CHECKING:
|
8
8
|
from .container import Container
|
9
9
|
|
10
|
+
|
10
11
|
class Layout:
|
11
12
|
def __init__(self, parent: "Container" = None):
|
12
13
|
self.parent = parent
|
@@ -23,46 +24,58 @@ class Layout:
|
|
23
24
|
self.notify_parent()
|
24
25
|
|
25
26
|
def notify_parent(self) -> None:
|
26
|
-
if self.parent:
|
27
|
+
if self.parent:
|
28
|
+
self.parent.dirty_children = True
|
27
29
|
|
28
30
|
def arrange(self) -> None:
|
29
31
|
return
|
30
32
|
|
31
|
-
def
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
return self.parent.rect.size if self.parent else 0,0
|
33
|
+
def get_raw_size(self) -> tuple[float, float]:
|
34
|
+
"""
|
35
|
+
Returns the supposed size the container should have to encapsulate perfectly all of its widgets
|
36
|
+
"""
|
37
|
+
return self.parent.rect.size if self.parent else (0, 0)
|
36
38
|
|
37
|
-
def get_auto_size(self)->tuple[float,float]:
|
38
|
-
|
39
|
+
def get_auto_size(self) -> tuple[float, float]:
|
40
|
+
"""
|
41
|
+
Returns the final size the container should have (while keeping the the width and height if they are non-resizable)
|
42
|
+
"""
|
43
|
+
target_size = list(self.get_raw_size())
|
44
|
+
if not self.parent.autoresize_w:
|
45
|
+
target_size[0] = self.parent.rect.w
|
46
|
+
if not self.parent.autoresize_h:
|
47
|
+
target_size[1] = self.parent.rect.h
|
48
|
+
return target_size
|
39
49
|
|
40
|
-
def focus_next_child(self)->None:
|
50
|
+
def focus_next_child(self) -> None:
|
41
51
|
l = self.parent.get_interactive_children()
|
42
52
|
self.parent.focused_index = min(self.parent.focused_index + 1, len(l) - 1)
|
43
53
|
focused = l[self.parent.focused_index]
|
44
54
|
focused.get_focus()
|
45
55
|
self.scroll_to_widget(focused)
|
46
56
|
|
47
|
-
def focus_prev_child(self)->None:
|
57
|
+
def focus_prev_child(self) -> None:
|
48
58
|
l = self.parent.get_interactive_children()
|
49
59
|
self.parent.focused_index = max(self.parent.focused_index - 1, 0)
|
50
60
|
focused = l[self.parent.focused_index]
|
51
61
|
focused.get_focus()
|
52
62
|
self.scroll_to_widget(focused)
|
53
63
|
|
54
|
-
def scroll_to_widget(self,widget:Widget)->None:
|
64
|
+
def scroll_to_widget(self, widget: Widget) -> None:
|
55
65
|
padded = self.parent.get_padded_rect()
|
56
66
|
r = widget.rect
|
57
|
-
if padded.contains(r):
|
67
|
+
if padded.contains(r):
|
68
|
+
return
|
58
69
|
clamped = r.clamp(padded)
|
59
|
-
dx,dy = clamped.move(-r.x
|
60
|
-
self.parent.scroll_by((-dx
|
70
|
+
dx, dy = clamped.move(-r.x, -r.y).topleft
|
71
|
+
self.parent.scroll_by((-dx, -dy))
|
61
72
|
|
73
|
+
def handle_event(self, event):
|
74
|
+
pass
|
62
75
|
|
63
76
|
|
64
77
|
class Column(Layout):
|
65
|
-
def __init__(self, gap: int = 0,spacing:bf.spacing = bf.spacing.MANUAL):
|
78
|
+
def __init__(self, gap: int = 0, spacing: bf.spacing = bf.spacing.MANUAL):
|
66
79
|
super().__init__()
|
67
80
|
self.gap = gap
|
68
81
|
self.spacing = spacing
|
@@ -71,50 +84,81 @@ class Column(Layout):
|
|
71
84
|
self.gap = value
|
72
85
|
self.notify_parent()
|
73
86
|
return self
|
74
|
-
|
75
|
-
def set_spacing(self,spacing: bf.spacing)->Self:
|
87
|
+
|
88
|
+
def set_spacing(self, spacing: bf.spacing) -> Self:
|
76
89
|
self.spacing = spacing
|
77
90
|
self.notify_parent()
|
78
91
|
return self
|
79
92
|
|
80
|
-
def get_raw_size(self)-> tuple[float,float]:
|
93
|
+
def get_raw_size(self) -> tuple[float, float]:
|
81
94
|
len_children = len(self.parent.children)
|
82
|
-
if not len_children
|
95
|
+
if not len_children:
|
96
|
+
return self.parent.rect.size
|
83
97
|
parent_height = sum(c.get_min_required_size()[1] for c in self.parent.children)
|
84
98
|
parent_width = max(c.get_min_required_size()[0] for c in self.parent.children)
|
85
99
|
if self.gap:
|
86
100
|
parent_height += (len_children - 1) * self.gap
|
87
|
-
target_rect = self.parent.inflate_rect_by_padding(
|
101
|
+
target_rect = self.parent.inflate_rect_by_padding(
|
102
|
+
(0, 0, parent_width, parent_height)
|
103
|
+
)
|
88
104
|
return target_rect.size
|
89
|
-
|
90
|
-
def get_auto_size(self)-> tuple[float,float]:
|
105
|
+
|
106
|
+
def get_auto_size(self) -> tuple[float, float]:
|
91
107
|
target_size = list(self.get_raw_size())
|
92
|
-
if not self.parent.autoresize_w
|
93
|
-
|
108
|
+
if not self.parent.autoresize_w:
|
109
|
+
target_size[0] = self.parent.rect.w
|
110
|
+
if not self.parent.autoresize_h:
|
111
|
+
target_size[1] = self.parent.rect.h
|
94
112
|
return target_size
|
95
113
|
|
96
114
|
def arrange(self) -> None:
|
97
115
|
if not self.parent or not self.parent.children:
|
98
116
|
return
|
99
|
-
if self.child_constraints
|
100
|
-
for child in self.parent.children
|
117
|
+
if self.child_constraints:
|
118
|
+
for child in self.parent.children:
|
119
|
+
child.add_constraints(*self.child_constraints)
|
101
120
|
self.child_rect = self.parent.get_padded_rect()
|
102
121
|
|
103
122
|
if self.parent.autoresize_w or self.parent.autoresize_h:
|
104
|
-
width,height = self.get_auto_size()
|
105
|
-
if self.parent.rect.size != (width,height):
|
106
|
-
self.parent.set_size((width,height))
|
123
|
+
width, height = self.get_auto_size()
|
124
|
+
if self.parent.rect.size != (width, height):
|
125
|
+
self.parent.set_size((width, height))
|
107
126
|
self.parent.build()
|
108
127
|
self.arrange()
|
109
128
|
return
|
110
|
-
self.child_rect.move_ip(-self.parent.scroll.x
|
129
|
+
self.child_rect.move_ip(-self.parent.scroll.x, -self.parent.scroll.y)
|
111
130
|
y = self.child_rect.top
|
112
|
-
for child in self.parent.children
|
113
|
-
child.set_position(self.child_rect.x,y)
|
114
|
-
y+= child.get_min_required_size()[1] + self.gap
|
131
|
+
for child in self.parent.children:
|
132
|
+
child.set_position(self.child_rect.x, y)
|
133
|
+
y += child.get_min_required_size()[1] + self.gap
|
134
|
+
|
135
|
+
def handle_event(self, event):
|
136
|
+
if self.parent.autoresize_h or not self.parent.visible:
|
137
|
+
return
|
138
|
+
|
139
|
+
if not self.parent.children:
|
140
|
+
return
|
141
|
+
|
142
|
+
if event.type == pygame.MOUSEBUTTONDOWN:
|
143
|
+
r = self.parent.get_root()
|
144
|
+
if not r:
|
145
|
+
return
|
146
|
+
|
147
|
+
if self.parent.rect.collidepoint(
|
148
|
+
r.drawing_camera.screen_to_world(pygame.mouse.get_pos())
|
149
|
+
):
|
150
|
+
if event.button == 4:
|
151
|
+
self.parent.scroll_by((0, -10))
|
152
|
+
elif event.button == 5:
|
153
|
+
self.parent.scroll_by((0, 10))
|
154
|
+
else:
|
155
|
+
return
|
156
|
+
event.consumed = True
|
157
|
+
self.parent.clamp_scroll()
|
158
|
+
|
115
159
|
|
116
160
|
class Row(Layout):
|
117
|
-
def __init__(self, gap: int = 0,spacing: bf.spacing=bf.spacing.MANUAL):
|
161
|
+
def __init__(self, gap: int = 0, spacing: bf.spacing = bf.spacing.MANUAL):
|
118
162
|
super().__init__()
|
119
163
|
self.gap = gap
|
120
164
|
self.spacing = spacing
|
@@ -123,35 +167,40 @@ class Row(Layout):
|
|
123
167
|
self.gap = value
|
124
168
|
self.notify_parent()
|
125
169
|
return self
|
126
|
-
|
127
|
-
def set_spacing(self,spacing: bf.spacing)->Self:
|
170
|
+
|
171
|
+
def set_spacing(self, spacing: bf.spacing) -> Self:
|
128
172
|
self.spacing = spacing
|
129
173
|
self.notify_parent()
|
130
174
|
return self
|
131
175
|
|
132
|
-
|
133
176
|
def get_raw_size(self) -> tuple[float, float]:
|
134
177
|
len_children = len(self.parent.children)
|
135
|
-
if not len_children:
|
178
|
+
if not len_children:
|
179
|
+
return self.parent.rect.size
|
136
180
|
parent_width = sum(c.get_min_required_size()[0] for c in self.parent.children)
|
137
181
|
parent_height = max(c.get_min_required_size()[1] for c in self.parent.children)
|
138
182
|
if self.gap:
|
139
183
|
parent_width += (len_children - 1) * self.gap
|
140
|
-
target_rect = self.parent.inflate_rect_by_padding(
|
184
|
+
target_rect = self.parent.inflate_rect_by_padding(
|
185
|
+
(0, 0, parent_width, parent_height)
|
186
|
+
)
|
141
187
|
|
142
188
|
return target_rect.size
|
143
189
|
|
144
190
|
def get_auto_size(self) -> tuple[float, float]:
|
145
191
|
target_size = list(self.get_raw_size())
|
146
|
-
if not self.parent.autoresize_w:
|
147
|
-
|
192
|
+
if not self.parent.autoresize_w:
|
193
|
+
target_size[0] = self.parent.rect.w
|
194
|
+
if not self.parent.autoresize_h:
|
195
|
+
target_size[1] = self.parent.rect.h
|
148
196
|
return target_size
|
149
197
|
|
150
198
|
def arrange(self) -> None:
|
151
199
|
if not self.parent or not self.parent.children:
|
152
200
|
return
|
153
201
|
if self.child_constraints:
|
154
|
-
for child in self.parent.children:
|
202
|
+
for child in self.parent.children:
|
203
|
+
child.add_constraints(*self.child_constraints)
|
155
204
|
self.child_rect = self.parent.get_padded_rect()
|
156
205
|
|
157
206
|
if self.parent.autoresize_w or self.parent.autoresize_h:
|
@@ -166,3 +215,26 @@ class Row(Layout):
|
|
166
215
|
for child in self.parent.children:
|
167
216
|
child.set_position(x, self.child_rect.y)
|
168
217
|
x += child.get_min_required_size()[0] + self.gap
|
218
|
+
|
219
|
+
def handle_event(self, event):
|
220
|
+
if self.parent.autoresize_w or not self.parent.visible:
|
221
|
+
return
|
222
|
+
|
223
|
+
if not self.parent.children:
|
224
|
+
return
|
225
|
+
|
226
|
+
if event.type == pygame.MOUSEBUTTONDOWN:
|
227
|
+
r = self.parent.get_root()
|
228
|
+
if not r:
|
229
|
+
return
|
230
|
+
if self.parent.rect.collidepoint(
|
231
|
+
r.drawing_camera.screen_to_world(pygame.mouse.get_pos())
|
232
|
+
):
|
233
|
+
if event.button == 4:
|
234
|
+
self.parent.scroll_by((-10, 0))
|
235
|
+
elif event.button == 5:
|
236
|
+
self.parent.scroll_by((10, 0))
|
237
|
+
else:
|
238
|
+
return
|
239
|
+
event.consumed = True
|
240
|
+
self.parent.clamp_scroll()
|
batFramework/gui/meter.py
CHANGED
@@ -10,14 +10,9 @@ def custom_top_at(self, x, y):
|
|
10
10
|
|
11
11
|
|
12
12
|
class Meter(Shape):
|
13
|
-
def __init__(
|
14
|
-
self,
|
15
|
-
min_value: float = 0,
|
16
|
-
max_value: float = 1,
|
17
|
-
step: float = 0.1
|
18
|
-
):
|
13
|
+
def __init__(self, min_value: float = 0, max_value: float = 1, step: float = 0.1):
|
19
14
|
super().__init__()
|
20
|
-
self.min_value, self.max_value = min_value,max_value
|
15
|
+
self.min_value, self.max_value = min_value, max_value
|
21
16
|
self.step = step
|
22
17
|
self.snap: bool = False
|
23
18
|
self.value = self.max_value
|
@@ -67,7 +62,7 @@ class Meter(Shape):
|
|
67
62
|
return self.value / (self.max_value - self.min_value)
|
68
63
|
|
69
64
|
def _build_content(self) -> None:
|
70
|
-
width =
|
65
|
+
width = self.get_padded_width() * self.get_ratio()
|
71
66
|
self.content.set_size((width, self.get_padded_height()))
|
72
67
|
self.content.set_position(*self.get_padded_rect().topleft)
|
73
68
|
|
batFramework/gui/radioButton.py
CHANGED
@@ -1,62 +1,84 @@
|
|
1
1
|
import batFramework as bf
|
2
|
-
from typing import Self,Any,Callable
|
2
|
+
from typing import Self, Any, Callable
|
3
3
|
from .toggle import Toggle
|
4
4
|
|
5
|
-
|
5
|
+
|
6
|
+
class RadioVariable: ...
|
7
|
+
|
6
8
|
|
7
9
|
class RadioButton(Toggle):
|
8
|
-
def __init__(self, text: str, radio_value:Any = None) -> None:
|
9
|
-
super().__init__(text,None, False)
|
10
|
-
self.radio_value
|
11
|
-
|
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
|
+
)
|
12
21
|
|
13
|
-
def set_radio_value(self,value:Any)->Self:
|
22
|
+
def set_radio_value(self, value: Any) -> Self:
|
14
23
|
self.radio_value = value
|
15
|
-
|
24
|
+
|
25
|
+
if self.radio_variable:
|
26
|
+
self.radio_variable.update_buttons()
|
16
27
|
return self
|
17
|
-
|
28
|
+
|
18
29
|
def set_text(self, text: str) -> Self:
|
19
30
|
flag = False
|
20
|
-
if self.value == self.text or self.value is None:
|
31
|
+
if self.value == self.text or self.value is None:
|
32
|
+
flag = True
|
21
33
|
super().set_text(text)
|
22
34
|
if flag:
|
23
35
|
self.set_radio_value(self.text)
|
24
36
|
return self
|
25
37
|
|
26
38
|
def click(self) -> None:
|
27
|
-
if self.radio_variable is None:
|
39
|
+
if self.radio_variable is None:
|
40
|
+
return
|
28
41
|
self.radio_variable.set_value(self.radio_value)
|
29
42
|
|
43
|
+
|
30
44
|
class RadioVariable:
|
31
|
-
def __init__(self)->None:
|
32
|
-
self.buttons
|
45
|
+
def __init__(self) -> None:
|
46
|
+
self.buttons: list[RadioButton] = []
|
33
47
|
self.value = None
|
34
|
-
self.modify_callback
|
48
|
+
self.modify_callback: Callable[[Any],] = None
|
49
|
+
|
50
|
+
def set_modify_callback(self, callback) -> Self:
|
51
|
+
self.modify_callback = callback
|
52
|
+
return self
|
35
53
|
|
36
|
-
def link(self
|
37
|
-
if not buttons
|
38
|
-
|
54
|
+
def link(self, *buttons: RadioButton) -> Self:
|
55
|
+
if not buttons:
|
56
|
+
return self
|
57
|
+
for b in buttons:
|
39
58
|
b.radio_variable = self
|
40
59
|
self.buttons.extend(buttons)
|
41
|
-
|
60
|
+
|
42
61
|
if self.value is None:
|
43
62
|
self.set_value(buttons[0].radio_value)
|
44
63
|
else:
|
45
|
-
self.update_buttons()
|
64
|
+
self.update_buttons()
|
46
65
|
return self
|
47
66
|
|
48
|
-
def unlink(self
|
67
|
+
def unlink(self, *buttons) -> Self:
|
49
68
|
for b in self.buttons:
|
50
69
|
if b in buttons:
|
51
70
|
b.radio_variable = None
|
52
71
|
self.buttons = [b for b in self.buttons if b not in buttons]
|
53
72
|
return self
|
54
73
|
|
55
|
-
def set_value(self,value:Any):
|
56
|
-
if value == self.value:
|
74
|
+
def set_value(self, value: Any) -> Self:
|
75
|
+
if value == self.value:
|
76
|
+
return
|
57
77
|
self.value = value
|
58
|
-
if self.modify_callback
|
59
|
-
|
78
|
+
if self.modify_callback:
|
79
|
+
self.modify_callback(value)
|
80
|
+
self.update_buttons()
|
81
|
+
return self
|
60
82
|
|
61
83
|
def update_buttons(self):
|
62
|
-
_ = [b.set_value(b.radio_value == self.value,False) for b in self.buttons]
|
84
|
+
_ = [b.set_value(b.radio_value == self.value, False) for b in self.buttons]
|
batFramework/gui/root.py
CHANGED
@@ -2,6 +2,8 @@ import batFramework as bf
|
|
2
2
|
from .interactiveWidget import InteractiveWidget
|
3
3
|
from .widget import Widget
|
4
4
|
import pygame
|
5
|
+
from typing import Self
|
6
|
+
import sys
|
5
7
|
|
6
8
|
|
7
9
|
class Root(InteractiveWidget):
|
@@ -14,12 +16,16 @@ class Root(InteractiveWidget):
|
|
14
16
|
self.focused: InteractiveWidget | None = self
|
15
17
|
self.hovered: Widget | None = self
|
16
18
|
self.set_debug_color("yellow")
|
17
|
-
self.set_render_order(
|
19
|
+
self.set_render_order(sys.maxsize)
|
18
20
|
self.clip_children = False
|
19
21
|
|
20
22
|
def __str__(self) -> str:
|
21
23
|
return "Root"
|
22
24
|
|
25
|
+
def set_parent_scene(self, parent_scene: bf.Scene) -> Self:
|
26
|
+
bf.StyleManager().register_widget(self)
|
27
|
+
return super().set_parent_scene(parent_scene)
|
28
|
+
|
23
29
|
def get_focused(self) -> Widget | None:
|
24
30
|
return self.focused
|
25
31
|
|
@@ -34,8 +40,14 @@ class Root(InteractiveWidget):
|
|
34
40
|
self.hovered.on_exit()
|
35
41
|
self.hovered = None
|
36
42
|
|
43
|
+
def get_debug_outlines(self):
|
44
|
+
yield (self.rect, self.debug_color)
|
45
|
+
for child in self.children:
|
46
|
+
yield from child.get_debug_outlines()
|
47
|
+
|
37
48
|
def focus_on(self, widget: InteractiveWidget | None) -> None:
|
38
|
-
if widget == self.focused
|
49
|
+
if widget == self.focused:
|
50
|
+
return
|
39
51
|
if widget and not widget.allow_focus_to_self():
|
40
52
|
return
|
41
53
|
if self.focused is not None:
|
@@ -46,26 +58,34 @@ class Root(InteractiveWidget):
|
|
46
58
|
self.focused = widget
|
47
59
|
self.focused.on_get_focus()
|
48
60
|
|
49
|
-
def get_by_tags(self
|
61
|
+
def get_by_tags(self, *tags) -> list[Widget]:
|
50
62
|
res = []
|
51
|
-
|
63
|
+
|
64
|
+
def getter(w: Widget):
|
52
65
|
nonlocal res
|
53
66
|
if any(t in w.tags for t in tags):
|
54
67
|
res.append(w)
|
68
|
+
|
55
69
|
self.visit(getter)
|
56
70
|
return res
|
57
71
|
|
58
|
-
def
|
59
|
-
|
72
|
+
def focus_next_tab(self, widget):
|
73
|
+
return True
|
74
|
+
|
75
|
+
def focus_prev_tab(self, widget):
|
76
|
+
return True
|
77
|
+
|
78
|
+
def get_by_uid(self, uid: int) -> "Widget":
|
79
|
+
def helper(w: "Widget", uid: int) -> "Widget":
|
60
80
|
if w.uid == uid:
|
61
81
|
return w
|
62
82
|
for child in w.children:
|
63
|
-
res = helper(child,uid)
|
64
|
-
if res :
|
65
|
-
return
|
66
|
-
|
83
|
+
res = helper(child, uid)
|
84
|
+
if res is not None:
|
85
|
+
return res
|
67
86
|
return None
|
68
|
-
|
87
|
+
|
88
|
+
return helper(self, uid)
|
69
89
|
|
70
90
|
def set_size(self, size: tuple[float, float], force: bool = False) -> "Root":
|
71
91
|
if not force:
|
@@ -74,23 +94,25 @@ class Root(InteractiveWidget):
|
|
74
94
|
# self.build(resolve_constraints=True)
|
75
95
|
return self
|
76
96
|
|
77
|
-
|
78
97
|
def do_handle_event(self, event):
|
79
|
-
# if event.type == pygame.VIDEORESIZE:
|
80
|
-
# self.set_size(event.w, event.h, force=True)
|
81
|
-
# return True
|
82
98
|
if self.focused:
|
83
99
|
if event.type == pygame.KEYDOWN:
|
84
|
-
self.focused.on_key_down(event.key)
|
85
|
-
|
86
|
-
|
87
|
-
|
100
|
+
if self.focused.on_key_down(event.key):
|
101
|
+
event.consumed = True
|
102
|
+
elif event.type == pygame.KEYUP:
|
103
|
+
if self.focused.on_key_up(event.key):
|
104
|
+
event.consumed = True
|
105
|
+
|
106
|
+
if not self.hovered or (not isinstance(self.hovered, InteractiveWidget)):
|
88
107
|
return
|
108
|
+
|
89
109
|
if event.type == pygame.MOUSEBUTTONDOWN:
|
90
|
-
self.hovered.on_click_down(event.button)
|
91
|
-
|
92
|
-
self.hovered.on_click_up(event.button)
|
110
|
+
if self.hovered.on_click_down(event.button):
|
111
|
+
event.consumed = True
|
93
112
|
|
113
|
+
elif event.type == pygame.MOUSEBUTTONUP:
|
114
|
+
if self.hovered.on_click_up(event.button):
|
115
|
+
event.consumed = True
|
94
116
|
|
95
117
|
def do_on_click_down(self, button: int) -> None:
|
96
118
|
if button == 1:
|
@@ -119,7 +141,10 @@ class Root(InteractiveWidget):
|
|
119
141
|
|
120
142
|
def draw(self, camera: bf.Camera) -> int:
|
121
143
|
super().draw(camera)
|
122
|
-
if
|
144
|
+
if (
|
145
|
+
self.parent_scene
|
146
|
+
and self.parent_scene.active
|
147
|
+
and self.focused
|
148
|
+
and self.focused != self
|
149
|
+
):
|
123
150
|
self.focused.draw_focused(camera)
|
124
|
-
|
125
|
-
|
batFramework/gui/shape.py
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
import batFramework as bf
|
2
2
|
from .widget import Widget
|
3
3
|
import pygame
|
4
|
-
from typing import Self,Iterable
|
4
|
+
from typing import Self, Iterable
|
5
5
|
from math import ceil
|
6
6
|
|
7
7
|
|
8
8
|
class Shape(Widget):
|
9
|
-
def __init__(self, size: tuple[float, float] = None
|
10
|
-
super().__init__(size=size,convert_alpha=True)
|
9
|
+
def __init__(self, size: tuple[float, float] = None, *args, **kwargs):
|
10
|
+
super().__init__(size=size, convert_alpha=True)
|
11
11
|
self.color = (0, 0, 0, 0)
|
12
12
|
self.border_radius: list[int] = [0]
|
13
13
|
self.outline: int = 0
|
@@ -24,15 +24,15 @@ class Shape(Widget):
|
|
24
24
|
def get_padded_height(self) -> float:
|
25
25
|
return self.rect.h - self.padding[1] - self.padding[3] - self.relief
|
26
26
|
|
27
|
-
def get_padded_top(self)->float:
|
27
|
+
def get_padded_top(self) -> float:
|
28
28
|
return self.rect.y + self.relief
|
29
29
|
|
30
|
-
def get_padded_rect(self)->pygame.FRect:
|
30
|
+
def get_padded_rect(self) -> pygame.FRect:
|
31
31
|
return pygame.FRect(
|
32
32
|
self.rect.x + self.padding[0],
|
33
33
|
self.rect.y + self.padding[1],
|
34
34
|
self.rect.w - self.padding[2] - self.padding[0],
|
35
|
-
self.rect.h - self.padding[1] - self.padding[3] - self.relief
|
35
|
+
self.rect.h - self.padding[1] - self.padding[3] - self.relief,
|
36
36
|
)
|
37
37
|
|
38
38
|
def set_shadow_color(self, color: tuple[int, int, int] | str) -> Self:
|
@@ -43,7 +43,8 @@ class Shape(Widget):
|
|
43
43
|
def set_relief(self, relief: int) -> Self:
|
44
44
|
if relief < 0:
|
45
45
|
return self
|
46
|
-
if self.relief == relief
|
46
|
+
if self.relief == relief:
|
47
|
+
return self
|
47
48
|
self.relief = relief
|
48
49
|
self.dirty_shape = True
|
49
50
|
return self
|
@@ -100,7 +101,7 @@ class Shape(Widget):
|
|
100
101
|
self.dirty_surface = True
|
101
102
|
return self
|
102
103
|
|
103
|
-
def paint(self)->None:
|
104
|
+
def paint(self) -> None:
|
104
105
|
if self.draw_mode == bf.drawMode.TEXTURED:
|
105
106
|
self._paint_textured()
|
106
107
|
return
|
@@ -113,8 +114,6 @@ class Shape(Widget):
|
|
113
114
|
if self.outline:
|
114
115
|
self._paint_rounded_outline()
|
115
116
|
|
116
|
-
|
117
|
-
|
118
117
|
def _paint_textured(self) -> None:
|
119
118
|
self.surface.fill((0, 0, 0, 0))
|
120
119
|
if self.texture_surface is None:
|
@@ -218,14 +217,10 @@ class Shape(Widget):
|
|
218
217
|
self.surface.fblits(lst)
|
219
218
|
|
220
219
|
def _get_elevated_rect(self) -> pygame.FRect:
|
221
|
-
return pygame.FRect(
|
222
|
-
0,0 , self.rect.w, self.rect.h - self.relief
|
223
|
-
)
|
220
|
+
return pygame.FRect(0, 0, self.rect.w, self.rect.h - self.relief)
|
224
221
|
|
225
222
|
def _get_base_rect(self) -> pygame.FRect:
|
226
|
-
return pygame.FRect(
|
227
|
-
0, self.rect.h - self.relief , self.rect.w, self.relief
|
228
|
-
)
|
223
|
+
return pygame.FRect(0, self.rect.h - self.relief, self.rect.w, self.relief)
|
229
224
|
|
230
225
|
def _paint_shape(self) -> None:
|
231
226
|
self.surface.fill((0, 0, 0, 0))
|
@@ -237,8 +232,8 @@ class Shape(Widget):
|
|
237
232
|
e = self._get_elevated_rect()
|
238
233
|
b = e.copy()
|
239
234
|
b.bottom = self.rect.h
|
240
|
-
pygame.draw.rect(self.surface, self.shadow_color,
|
241
|
-
pygame.draw.rect(self.surface, self.color,
|
235
|
+
pygame.draw.rect(self.surface, self.shadow_color, b, 0, *self.border_radius)
|
236
|
+
pygame.draw.rect(self.surface, self.color, e, 0, *self.border_radius)
|
242
237
|
|
243
238
|
def _paint_outline(self) -> None:
|
244
239
|
if self.relief:
|
@@ -269,7 +264,7 @@ class Shape(Widget):
|
|
269
264
|
e = self._get_elevated_rect()
|
270
265
|
b = e.copy()
|
271
266
|
b.h += e.bottom - b.bottom
|
272
|
-
|
267
|
+
|
273
268
|
pygame.draw.rect(
|
274
269
|
self.surface,
|
275
270
|
self.outline_color,
|