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.
- batFramework/__init__.py +51 -68
- batFramework/action.py +99 -126
- batFramework/actionContainer.py +9 -53
- batFramework/animatedSprite.py +82 -141
- batFramework/audioManager.py +26 -69
- batFramework/camera.py +69 -259
- batFramework/constants.py +54 -16
- batFramework/cutscene.py +29 -39
- batFramework/cutsceneBlocks.py +43 -36
- batFramework/debugger.py +48 -0
- batFramework/dynamicEntity.py +9 -18
- batFramework/easing.py +71 -0
- batFramework/entity.py +97 -48
- batFramework/gui/__init__.py +2 -10
- batFramework/gui/button.py +78 -9
- batFramework/gui/constraints.py +204 -0
- batFramework/gui/container.py +32 -174
- batFramework/gui/debugger.py +43 -131
- batFramework/gui/frame.py +19 -0
- batFramework/gui/image.py +20 -56
- batFramework/gui/indicator.py +21 -38
- batFramework/gui/interactiveWidget.py +13 -192
- batFramework/gui/label.py +74 -309
- batFramework/gui/layout.py +63 -231
- batFramework/gui/root.py +38 -134
- batFramework/gui/shape.py +57 -237
- batFramework/gui/toggle.py +51 -101
- batFramework/gui/widget.py +250 -358
- batFramework/manager.py +19 -52
- batFramework/particles.py +77 -0
- batFramework/scene.py +123 -281
- batFramework/sceneManager.py +116 -178
- batFramework/stateMachine.py +8 -11
- batFramework/time.py +58 -145
- batFramework/transition.py +124 -195
- batFramework/transitionManager.py +0 -0
- batFramework/triggerZone.py +1 -1
- batFramework/utils.py +147 -112
- batframework-1.0.8a8.dist-info/METADATA +53 -0
- batframework-1.0.8a8.dist-info/RECORD +42 -0
- {batframework-1.0.8a7.dist-info → batframework-1.0.8a8.dist-info}/WHEEL +1 -1
- batFramework/character.py +0 -27
- batFramework/easingController.py +0 -58
- batFramework/enums.py +0 -113
- batFramework/fontManager.py +0 -65
- batFramework/gui/clickableWidget.py +0 -220
- batFramework/gui/constraints/__init__.py +0 -1
- batFramework/gui/constraints/constraints.py +0 -815
- batFramework/gui/dialogueBox.py +0 -99
- batFramework/gui/draggableWidget.py +0 -40
- batFramework/gui/meter.py +0 -74
- batFramework/gui/radioButton.py +0 -84
- batFramework/gui/slider.py +0 -240
- batFramework/gui/style.py +0 -10
- batFramework/gui/styleManager.py +0 -48
- batFramework/gui/textInput.py +0 -247
- batFramework/object.py +0 -123
- batFramework/particle.py +0 -115
- batFramework/renderGroup.py +0 -67
- batFramework/resourceManager.py +0 -100
- batFramework/scrollingSprite.py +0 -114
- batFramework/sprite.py +0 -51
- batFramework/templates/__init__.py +0 -2
- batFramework/templates/character.py +0 -44
- batFramework/templates/states.py +0 -166
- batFramework/tileset.py +0 -46
- batframework-1.0.8a7.dist-info/LICENCE +0 -21
- batframework-1.0.8a7.dist-info/METADATA +0 -43
- batframework-1.0.8a7.dist-info/RECORD +0 -62
- {batframework-1.0.8a7.dist-info → batframework-1.0.8a8.dist-info}/top_level.txt +0 -0
batFramework/gui/widget.py
CHANGED
@@ -1,415 +1,307 @@
|
|
1
|
-
from
|
2
|
-
from
|
3
|
-
import batFramework as bf
|
4
|
-
import pygame
|
5
|
-
|
1
|
+
from __future__ import annotations
|
2
|
+
from typing import TYPE_CHECKING
|
6
3
|
if TYPE_CHECKING:
|
7
|
-
from .constraints
|
4
|
+
from .constraints import Constraint
|
8
5
|
from .root import Root
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
class WidgetMeta(type):
|
13
|
-
def __call__(cls, *args, **kwargs):
|
14
|
-
"""Called when you call MyNewClass()"""
|
15
|
-
obj = type.__call__(cls, *args, **kwargs)
|
16
|
-
# obj.new_init()
|
17
|
-
bf.StyleManager().register_widget(obj)
|
18
|
-
return obj
|
19
|
-
|
20
|
-
|
21
|
-
class Widget(bf.Entity, metaclass=WidgetMeta):
|
22
|
-
def __init__(self, *args, **kwargs) -> None:
|
23
|
-
super().__init__(*args, **kwargs)
|
24
|
-
self.children: list["Widget"] = []
|
25
|
-
self.constraints: list[Constraint] = []
|
26
|
-
self.parent: "Widget" = None
|
27
|
-
self.do_sort_children = False
|
28
|
-
self.clip_children: bool = True
|
29
|
-
self.padding = (0, 0, 0, 0)
|
30
|
-
self.dirty_surface: bool = True # if true will call paint before drawing
|
31
|
-
self.dirty_shape: bool = (
|
32
|
-
True # if true will call (build+paint) before drawing
|
33
|
-
)
|
34
|
-
self.dirty_constraints: bool = False
|
35
|
-
self.is_root: bool = False
|
36
|
-
self.autoresize_w, self.autoresize_h = True, True
|
37
|
-
self.__constraint_iteration = 0
|
38
|
-
self.__constraints_to_ignore = []
|
39
|
-
self.__constraints_capture = None
|
40
|
-
|
41
|
-
def show(self) -> Self:
|
42
|
-
self.visit(lambda w: w.set_visible(True))
|
43
|
-
return self
|
6
|
+
from typing import Self
|
44
7
|
|
45
|
-
|
46
|
-
|
47
|
-
|
8
|
+
import batFramework as bf
|
9
|
+
import pygame
|
10
|
+
from math import ceil
|
11
|
+
|
12
|
+
|
13
|
+
|
14
|
+
class Widget(bf.Entity):
|
15
|
+
def __init__(self,convert_alpha=True)->None:
|
16
|
+
super().__init__(convert_alpha=convert_alpha)
|
17
|
+
self.autoresize = False
|
18
|
+
self.parent : None|Self = None
|
19
|
+
self.is_root :bool = False
|
20
|
+
self.children : list["Widget"] = []
|
21
|
+
self.focusable :bool= False
|
22
|
+
self.constraints : list[Constraint] = []
|
23
|
+
self.gui_depth : int = 0
|
24
|
+
if self.surface : self.surface.fill("white")
|
25
|
+
self.set_debug_color("red")
|
26
|
+
self.padding :tuple[float|int,...]= (0,0,0,0)
|
27
|
+
|
28
|
+
def set_padding(self,value : float|int|tuple|list)->Self:
|
29
|
+
old_raw_size = (
|
30
|
+
self.rect.w - self.padding[0] - self.padding[2],
|
31
|
+
self.rect.h - self.padding[1] - self.padding[3]
|
32
|
+
)
|
33
|
+
if isinstance(value,list) or isinstance(value,tuple):
|
34
|
+
if len(value) > 4 : return self
|
35
|
+
if any(v<0 for v in value) : return self
|
36
|
+
if len(value) == 2:
|
37
|
+
self.padding = (value[0],value[1],value[0],value[1])
|
38
|
+
else:
|
39
|
+
self.padding = (*value, *self.padding[len(value):])
|
40
|
+
else:
|
41
|
+
self.padding = (value,)*4
|
48
42
|
|
49
|
-
|
50
|
-
|
51
|
-
|
43
|
+
self.set_size(
|
44
|
+
old_raw_size[0] + self.padding[0] + self.padding[2],
|
45
|
+
old_raw_size[1] + self.padding[1] + self.padding[3],
|
46
|
+
)
|
52
47
|
return self
|
48
|
+
|
49
|
+
def inflate_rect_by_padding(self,rect:pygame.FRect)->pygame.FRect:
|
50
|
+
return pygame.FRect(
|
51
|
+
rect[0] - self.padding[0],
|
52
|
+
rect[1] - self.padding[1],
|
53
|
+
rect[2] + self.padding[0]+self.padding[2],
|
54
|
+
rect[3] + self.padding[1]+self.padding[3]
|
55
|
+
)
|
56
|
+
def get_content_left(self)->float:
|
57
|
+
return self.rect.left + self.padding[0]
|
53
58
|
|
54
|
-
def
|
55
|
-
return
|
59
|
+
def get_content_top(self)->float:
|
60
|
+
return self.rect.top + self.padding[1]
|
56
61
|
|
57
|
-
def
|
58
|
-
self.
|
59
|
-
self.dirty_shape = True
|
60
|
-
return self
|
62
|
+
def get_content_right(self)->float:
|
63
|
+
return self.rect.right - self.padding[2]
|
61
64
|
|
62
|
-
def
|
63
|
-
self.
|
64
|
-
self.dirty_shape = True
|
65
|
-
return self
|
65
|
+
def get_content_bottom(self)->float:
|
66
|
+
return self.rect.bottom - self.padding[3]
|
66
67
|
|
67
|
-
def
|
68
|
-
self.
|
69
|
-
self.dirty_shape = True
|
70
|
-
return self
|
68
|
+
def get_content_width(self)->float:
|
69
|
+
return self.rect.w - self.padding[0] - self.padding[2]
|
71
70
|
|
72
|
-
def
|
73
|
-
|
74
|
-
if self.parent:
|
75
|
-
self.parent.do_sort_children = True
|
76
|
-
return self
|
71
|
+
def get_content_height(self)->float:
|
72
|
+
return self.rect.h - self.padding[1] - self.padding[3]
|
77
73
|
|
78
|
-
def
|
79
|
-
self, rect: pygame.Rect | pygame.FRect
|
80
|
-
) -> pygame.Rect | pygame.FRect:
|
74
|
+
def get_content_rect(self)->pygame.FRect:
|
81
75
|
return pygame.FRect(
|
82
|
-
rect
|
83
|
-
rect
|
84
|
-
|
85
|
-
|
76
|
+
self.rect.left + self.padding[0],
|
77
|
+
self.rect.top + self.padding[1],
|
78
|
+
self.get_content_width(),
|
79
|
+
self.get_content_height()
|
86
80
|
)
|
87
81
|
|
88
|
-
def
|
89
|
-
|
90
|
-
x = self.rect.x
|
91
|
-
if y is None:
|
92
|
-
y = self.rect.y
|
93
|
-
if (x, y) == self.rect.topleft:
|
94
|
-
return self
|
95
|
-
dx, dy = x - self.rect.x, y - self.rect.y
|
96
|
-
self.rect.topleft = x, y
|
97
|
-
_ = [c.set_position(c.rect.x + dx, c.rect.y + dy) for c in self.children]
|
98
|
-
return self
|
99
|
-
|
100
|
-
def set_center(self, x, y) -> Self:
|
101
|
-
if x is None:
|
102
|
-
x = self.rect.centerx
|
103
|
-
if y is None:
|
104
|
-
y = self.rect.centery
|
105
|
-
if (x, y) == self.rect.center:
|
106
|
-
return self
|
107
|
-
dx, dy = x - self.rect.centerx, y - self.rect.centery
|
108
|
-
self.rect.center = x, y
|
109
|
-
_ = [
|
110
|
-
c.set_center(c.rect.centerx + dx, c.rect.centery + dy)
|
111
|
-
for c in self.children
|
112
|
-
]
|
113
|
-
return self
|
82
|
+
def get_content_rect_rel(self)->pygame.FRect:
|
83
|
+
return self.get_content_rect().move(-self.rect.left,-self.rect.top)
|
114
84
|
|
115
|
-
def
|
116
|
-
|
117
|
-
if parent_scene is None:
|
118
|
-
bf.StyleManager().remove_widget(self)
|
85
|
+
def get_content_center(self)->tuple[float,float]:
|
86
|
+
return self.get_content_rect().center
|
119
87
|
|
120
|
-
|
121
|
-
|
122
|
-
|
88
|
+
def get_depth(self)->int:
|
89
|
+
if self.is_root or self.parent is None :
|
90
|
+
self.gui_depth = 0
|
91
|
+
else:
|
92
|
+
self.gui_depth = self.parent.get_depth() + 1
|
93
|
+
return self.gui_depth
|
123
94
|
|
124
|
-
def
|
125
|
-
if
|
95
|
+
def top_at(self, x: float, y: float) -> "None|Widget":
|
96
|
+
if self.children:
|
97
|
+
for child in reversed(self.children):
|
98
|
+
r = child.top_at(x,y)
|
99
|
+
if r is not None:
|
100
|
+
return r
|
101
|
+
if self.rect.collidepoint(x,y) and self.visible:
|
126
102
|
return self
|
127
|
-
|
128
|
-
|
129
|
-
|
103
|
+
return None
|
104
|
+
|
105
|
+
def get_constraint(self,name:str)->Constraint|None:
|
106
|
+
return next((c for c in self.constraints if c.name == name), None)
|
107
|
+
|
108
|
+
def add_constraints(self,*constraints:Constraint)->Self:
|
109
|
+
for c in constraints:
|
110
|
+
self.add_constraint(c,False)
|
111
|
+
self.apply_constraints()
|
130
112
|
return self
|
131
|
-
|
132
|
-
def
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
elif len(value) == 2:
|
139
|
-
self.padding = (value[0], value[1], value[0], value[1])
|
140
|
-
else:
|
141
|
-
self.padding = (*value, *self.padding[len(value) :])
|
142
|
-
else:
|
143
|
-
self.padding = (value,) * 4
|
144
|
-
|
145
|
-
self.dirty_shape = True
|
113
|
+
|
114
|
+
def add_constraint(self,constraint:Constraint,apply:bool=True)->Self:
|
115
|
+
c = self.get_constraint(constraint.name)
|
116
|
+
if c is not None:
|
117
|
+
self.constraints.remove(c)
|
118
|
+
self.constraints.append(constraint)
|
119
|
+
self.apply_constraints()
|
146
120
|
return self
|
147
121
|
|
148
|
-
def
|
149
|
-
|
150
|
-
-self.padding[0] - self.padding[2], -self.padding[1] - self.padding[3]
|
151
|
-
)
|
152
|
-
# r.normalize()
|
153
|
-
return r
|
122
|
+
def has_constraint(self,name:str)->bool:
|
123
|
+
return any(c.name == name for c in self.constraints)
|
154
124
|
|
155
|
-
def
|
156
|
-
|
125
|
+
def apply_all_constraints(self)->None:
|
126
|
+
# print("APPLY ALL CONSTRAINTS IN ",self.to_string())
|
127
|
+
self.apply_constraints()
|
128
|
+
for child in self.children : child.apply_all_constraints()
|
129
|
+
|
130
|
+
def apply_constraints(self, max_iterations: int = 10) -> None:
|
131
|
+
if not self.parent:
|
132
|
+
# print(f"Warning : can't apply constraints on {self.to_string()} without parent widget")
|
133
|
+
return
|
134
|
+
if not self.constraints:
|
135
|
+
return
|
136
|
+
# Sort constraints based on priority
|
137
|
+
self.constraints.sort(key=lambda c: c.priority)
|
157
138
|
|
158
|
-
|
159
|
-
|
139
|
+
for iteration in range(max_iterations):
|
140
|
+
unsatisfied = [] # Initialize a flag
|
160
141
|
|
161
|
-
|
162
|
-
|
142
|
+
for constraint in self.constraints:
|
143
|
+
if not constraint.evaluate(self.parent, self):
|
144
|
+
unsatisfied.append(constraint)
|
145
|
+
constraint.apply(self.parent, self)
|
146
|
+
if not unsatisfied:
|
147
|
+
# data = ''.join(f"\n\t->{c.to_string()}" for c in self.constraints)
|
148
|
+
# print(self.get_depth()*'\t'+f"Following constraints of {self.to_string()} were all satisfied :{data}")
|
149
|
+
break
|
150
|
+
# print(f"pass {iteration}/{max_iterations} : unsatisfied = {';'.join(c.to_string() for c in unsatisfied)}")
|
151
|
+
if iteration == max_iterations - 1:
|
152
|
+
raise ValueError(f"[WARNING] Following constraints for {self.to_string()} were not satisfied : \n\t{';'.join([c.to_string() for c in unsatisfied])}")
|
163
153
|
|
164
|
-
|
165
|
-
|
154
|
+
# GETTERS
|
155
|
+
def get_root(self)-> Self|Root|None:
|
156
|
+
if self.is_root: return self
|
157
|
+
if self.parent_scene is not None : return self.parent_scene.root
|
158
|
+
return None if self.parent is None else self.parent.get_root()
|
166
159
|
|
167
|
-
def
|
168
|
-
return self.rect.
|
160
|
+
def get_size_int(self)->tuple[int,int]:
|
161
|
+
return (ceil(self.rect.width),ceil(self.rect.height))
|
169
162
|
|
170
|
-
def get_padded_center(self) -> tuple[float, float]:
|
171
|
-
return self.get_padded_rect().center
|
172
163
|
|
173
|
-
def
|
174
|
-
return self.rect.
|
164
|
+
def get_center(self)->tuple[float,float]:
|
165
|
+
return self.rect.center
|
175
166
|
|
176
|
-
def get_padded_bottom(self) -> float:
|
177
|
-
return self.rect.bottom - self.padding[3]
|
178
167
|
|
179
|
-
def
|
180
|
-
|
181
|
-
|
182
|
-
yield (self.rect, self.debug_color)
|
183
|
-
if any(self.padding):
|
184
|
-
yield (self.get_padded_rect(), self.debug_color)
|
168
|
+
def get_bounding_box(self):
|
169
|
+
yield (self.rect,self._debug_color)
|
170
|
+
yield (self.get_content_rect(),"yellow")
|
185
171
|
for child in self.children:
|
186
|
-
yield from child.
|
187
|
-
|
188
|
-
def add_constraints(self, *constraints: "Constraint") -> Self:
|
189
|
-
self.constraints.extend(constraints)
|
190
|
-
seen = set()
|
191
|
-
result = []
|
192
|
-
for c in self.constraints:
|
193
|
-
if not any(c == o for o in seen):
|
194
|
-
result.append(c)
|
195
|
-
seen.add(c.name)
|
196
|
-
self.constraints = result
|
197
|
-
self.constraints.sort(key=lambda c: c.priority)
|
198
|
-
self.dirty_constraints = True
|
199
|
-
self.__constraint_to_ignore = []
|
172
|
+
yield from child.get_bounding_box()
|
200
173
|
|
174
|
+
def set_autoresize(self,value:bool)-> Self:
|
175
|
+
self.autoresize = value
|
176
|
+
self.build()
|
201
177
|
return self
|
202
178
|
|
179
|
+
def set_parent(self,parent:Self|None)->None:
|
180
|
+
if self.parent:
|
181
|
+
self.parent.remove_child(self)
|
182
|
+
self.parent = parent
|
183
|
+
self.apply_all_constraints()
|
184
|
+
# SETTERS
|
185
|
+
|
186
|
+
def set_root(self) -> Self:
|
187
|
+
self.is_root = True
|
188
|
+
return self
|
189
|
+
|
190
|
+
def set_parent_scene(self,scene)->None:
|
191
|
+
super().set_parent_scene(scene)
|
192
|
+
for child in self.children :
|
193
|
+
child.set_parent_scene(scene)
|
203
194
|
|
204
|
-
def
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
self.
|
195
|
+
def set_x(self,x:float)->Self:
|
196
|
+
delta = x - self.rect.x
|
197
|
+
self.rect.x = x
|
198
|
+
for child in self.children:
|
199
|
+
child.set_x(child.rect.x + delta)
|
200
|
+
self.apply_constraints()
|
210
201
|
return self
|
211
202
|
|
212
|
-
def
|
213
|
-
|
214
|
-
|
215
|
-
|
203
|
+
def set_y(self,y:float)->Self:
|
204
|
+
delta = y - self.rect.y
|
205
|
+
self.rect.y = y
|
206
|
+
for child in self.children:
|
207
|
+
child.set_y(child.rect.y + delta)
|
208
|
+
self.apply_constraints()
|
216
209
|
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
if all(c.evaluate(self.parent,self) for c in constraints if c not in self.__constraint_to_ignore):
|
228
|
-
self.dirty_constraints = False
|
229
|
-
return
|
210
|
+
return self
|
211
|
+
|
212
|
+
def set_position(self,x:float,y:float)->Self:
|
213
|
+
delta_x = x - self.rect.x
|
214
|
+
delta_y = y - self.rect.y
|
215
|
+
self.rect.topleft = x,y
|
216
|
+
for child in self.children:
|
217
|
+
child.set_position(child.rect.x + delta_x,child.rect.y+delta_y)
|
218
|
+
self.apply_constraints()
|
219
|
+
return self
|
230
220
|
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
for c in constraints:
|
241
|
-
if c in self.__constraints_to_ignore:continue
|
242
|
-
if not c.evaluate(self.parent,self) :
|
243
|
-
c.apply(self.parent,self)
|
244
|
-
# second pass where we check conflicts
|
245
|
-
for c in constraints:
|
246
|
-
if c in self.__constraints_to_ignore:
|
247
|
-
continue
|
248
|
-
if not c.evaluate(self.parent,self):
|
249
|
-
# first pass invalidated this constraint
|
250
|
-
self.__constraints_to_ignore.append(c)
|
251
|
-
stop = False
|
252
|
-
break
|
253
|
-
|
254
|
-
if stop:
|
255
|
-
break
|
221
|
+
def set_center(self,x:float,y:float)->Self:
|
222
|
+
delta_x = x - self.rect.centerx
|
223
|
+
delta_y = y - self.rect.centery
|
224
|
+
self.rect.center = x,y
|
225
|
+
for child in self.children:
|
226
|
+
child.set_position(child.rect.x + delta_x,child.rect.y+delta_y)
|
227
|
+
self.apply_constraints()
|
228
|
+
return self
|
229
|
+
|
256
230
|
|
257
|
-
|
258
|
-
|
231
|
+
def set_size(self, width : float, height: float) -> Self:
|
232
|
+
self.rect.size = (width,height)
|
233
|
+
self.build()
|
234
|
+
return self
|
259
235
|
|
260
236
|
|
261
|
-
|
237
|
+
# Other Methods
|
262
238
|
|
263
|
-
def
|
264
|
-
|
239
|
+
def print_tree(self,ident:int=0)->None:
|
240
|
+
print('\t'*ident+self.to_string()+(':' if self.children else ''))
|
241
|
+
for child in self.children :
|
242
|
+
child.print_tree(ident+1)
|
265
243
|
|
266
|
-
def
|
267
|
-
|
268
|
-
|
269
|
-
if self.parent:
|
270
|
-
return self.parent.get_root()
|
271
|
-
return None
|
244
|
+
def to_string(self)->str:
|
245
|
+
|
246
|
+
return f"{self.to_string_id()}@{*self.rect.topleft,* self.rect.size}"
|
272
247
|
|
273
|
-
def top_at(self, x: float | int, y: float | int) -> "None|Widget":
|
274
|
-
if self.children:
|
275
|
-
for child in reversed(self.children):
|
276
|
-
if child.visible:
|
277
|
-
r = child.top_at(x, y)
|
278
|
-
if r is not None:
|
279
|
-
return r
|
280
|
-
return self if self.visible and self.rect.collidepoint(x, y) else None
|
281
|
-
|
282
|
-
def add(self, *children: "Widget") -> Self:
|
283
|
-
self.children.extend(children)
|
284
|
-
i = len(self.children)
|
285
|
-
for child in children:
|
286
|
-
|
287
|
-
child.set_render_order(i).set_parent(self).set_parent_scene(
|
288
|
-
self.parent_scene
|
289
|
-
)
|
290
|
-
i += 1
|
291
|
-
if self.parent:
|
292
|
-
self.parent.do_sort_children = True
|
293
|
-
return self
|
294
248
|
|
295
|
-
def
|
296
|
-
|
297
|
-
if child in children:
|
298
|
-
child.set_parent(None).set_parent_scene(None)
|
299
|
-
self.children.remove(child)
|
300
|
-
if self.parent:
|
301
|
-
self.parent.do_sort_children = True
|
249
|
+
def to_string_id(self)->str:
|
250
|
+
return "Widget"
|
302
251
|
|
303
|
-
def set_size_if_autoresize(self, size: tuple[float, float]) -> Self:
|
304
|
-
size = list(size)
|
305
|
-
size[0] = size[0] if self.autoresize_w else None
|
306
|
-
size[1] = size[1] if self.autoresize_h else None
|
307
|
-
self.set_size(size)
|
308
|
-
return self
|
309
252
|
|
310
|
-
def
|
311
|
-
|
312
|
-
|
313
|
-
size[0] = self.rect.w
|
314
|
-
if size[1] is None:
|
315
|
-
size[1] = self.rect.h
|
316
|
-
if size == self.rect.size:
|
317
|
-
return self
|
318
|
-
self.rect.size = size
|
319
|
-
self.dirty_shape = True
|
320
|
-
return self
|
253
|
+
def do_when_removed(self)->None:
|
254
|
+
if self.parent_scene and self.parent == self.parent_scene.root:
|
255
|
+
self.set_parent(None)
|
321
256
|
|
322
|
-
|
323
|
-
# First propagate to children
|
324
|
-
for child in self.children:
|
325
|
-
child.process_event(event)
|
326
|
-
# return True if the method is blocking (no propagation to next children of the scene)
|
327
|
-
super().process_event(event)
|
328
|
-
|
329
|
-
def update(self, dt) -> None:
|
330
|
-
if self.do_sort_children:
|
331
|
-
self.children.sort(key=lambda c: c.render_order)
|
332
|
-
self.do_sort_children = False
|
333
|
-
_ = [c.update(dt) for c in self.children]
|
334
|
-
super().update(dt)
|
335
|
-
|
336
|
-
def build(self) -> None:
|
337
|
-
new_size = tuple(map(int, self.rect.size))
|
338
|
-
if self.surface.get_size() != new_size:
|
339
|
-
old_alpha = self.surface.get_alpha()
|
340
|
-
new_size = [max(0, i) for i in new_size]
|
341
|
-
self.surface = pygame.Surface(new_size, self.surface_flags)
|
342
|
-
if self.convert_alpha:
|
343
|
-
self.surface = self.surface.convert_alpha()
|
344
|
-
self.surface.set_alpha(old_alpha)
|
345
|
-
|
346
|
-
def paint(self) -> None:
|
347
|
-
self.surface.fill((0, 0, 0, 0))
|
348
|
-
return self
|
257
|
+
# Methods on children
|
349
258
|
|
350
|
-
def
|
351
|
-
|
352
|
-
|
353
|
-
|
354
|
-
|
355
|
-
|
356
|
-
|
259
|
+
def add_child(self,*child:"Widget")->None:
|
260
|
+
for c in child :
|
261
|
+
self.children.append(c)
|
262
|
+
c.set_parent(self)
|
263
|
+
c.set_parent_scene(self.parent_scene)
|
264
|
+
c.apply_constraints()
|
265
|
+
self.children_modified()
|
357
266
|
|
358
|
-
def
|
359
|
-
|
360
|
-
|
361
|
-
|
362
|
-
|
363
|
-
|
364
|
-
def selective_up(self, widget: "Widget"):
|
365
|
-
# if returns True then stop climbing widget tree
|
366
|
-
if widget.parent and widget.parent.dirty_constraints:
|
367
|
-
return False
|
368
|
-
widget.visit(self.selective_down)
|
369
|
-
return True
|
370
|
-
|
371
|
-
def selective_down(self, widget: "Widget"):
|
372
|
-
if widget.constraints:
|
373
|
-
widget.resolve_constraints()
|
374
|
-
else:
|
375
|
-
widget.dirty_constraints = False
|
376
|
-
if widget.dirty_shape:
|
377
|
-
widget.build()
|
378
|
-
widget.dirty_shape = False
|
379
|
-
self.dirty_surface = True
|
380
|
-
|
381
|
-
def draw(self, camera: bf.Camera) -> None:
|
382
|
-
if self.dirty_shape:
|
383
|
-
self.dirty_constraints = True
|
384
|
-
self.dirty_surface = True
|
385
|
-
self.build()
|
386
|
-
self.dirty_shape = False
|
387
|
-
for child in self.children:
|
388
|
-
child.dirty_constraints = True
|
389
|
-
|
390
|
-
if self.dirty_constraints:
|
391
|
-
if self.parent and self.parent.dirty_constraints:
|
392
|
-
self.parent.visit_up(self.selective_up)
|
393
|
-
else:
|
394
|
-
self.visit(lambda c: c.resolve_constraints())
|
267
|
+
def remove_child(self,child:Self)->None:
|
268
|
+
self.children.remove(child)
|
269
|
+
child.set_parent(None)
|
270
|
+
child.set_parent_scene(None)
|
271
|
+
self.children_modified()
|
395
272
|
|
396
|
-
if self.dirty_surface:
|
397
|
-
self.paint()
|
398
|
-
self.dirty_surface = False
|
399
273
|
|
400
|
-
super().draw(camera)
|
401
274
|
|
402
|
-
if self.clip_children:
|
403
275
|
|
404
|
-
|
405
|
-
|
406
|
-
|
407
|
-
|
276
|
+
# if return True -> don't propagate to siblings or parents
|
277
|
+
def process_event(self, event: pygame.Event)->bool:
|
278
|
+
# First propagate to children
|
279
|
+
for child in self.children:
|
280
|
+
if child.process_event(event):
|
281
|
+
return True
|
282
|
+
#return True if the method is blocking (no propagation to next children of the scene)
|
283
|
+
return super().process_event(event)
|
408
284
|
|
409
|
-
_ = [
|
410
|
-
child.draw(camera)
|
411
|
-
for child in sorted(self.children, key=lambda c: c.render_order)
|
412
|
-
]
|
413
285
|
|
414
|
-
|
415
|
-
|
286
|
+
def update(self,dt:float):
|
287
|
+
for child in self.children:
|
288
|
+
child.update(dt)
|
289
|
+
|
290
|
+
def draw(self, camera: bf.Camera) -> int:
|
291
|
+
self.children.sort(key=lambda e: (e.z_depth,e.render_order))
|
292
|
+
return super().draw(camera) + sum([child.draw(camera) for child in self.children])
|
293
|
+
|
294
|
+
def build(self)->None:
|
295
|
+
"""
|
296
|
+
This function is called each time the widget's surface has to be updated
|
297
|
+
It usually has to be overriden if inherited to suit the needs of the new class
|
298
|
+
"""
|
299
|
+
if not self.surface: return
|
300
|
+
if self.surface.get_size() != self.get_size_int():
|
301
|
+
self.surface = pygame.Surface(self.get_size_int())
|
302
|
+
if self.parent : self.parent.children_modified()
|
303
|
+
|
304
|
+
def children_modified(self)->None:
|
305
|
+
self.apply_constraints()
|
306
|
+
if self.parent and not self.is_root:
|
307
|
+
self.parent.children_modified()
|