batframework 1.0.7__py3-none-any.whl → 1.0.8a1__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 +24 -15
- batFramework/action.py +95 -106
- batFramework/actionContainer.py +11 -8
- batFramework/animatedSprite.py +60 -43
- batFramework/audioManager.py +52 -22
- batFramework/camera.py +87 -72
- batFramework/constants.py +19 -41
- batFramework/cutscene.py +12 -11
- batFramework/cutsceneBlocks.py +12 -14
- batFramework/dynamicEntity.py +5 -4
- batFramework/easingController.py +58 -0
- batFramework/entity.py +37 -130
- batFramework/enums.py +93 -3
- batFramework/fontManager.py +15 -7
- batFramework/gui/__init__.py +5 -1
- batFramework/gui/button.py +6 -144
- batFramework/gui/clickableWidget.py +206 -0
- batFramework/gui/constraints/__init__.py +1 -0
- batFramework/gui/constraints/constraints.py +378 -0
- batFramework/gui/container.py +147 -34
- batFramework/gui/debugger.py +39 -22
- batFramework/gui/dialogueBox.py +69 -43
- batFramework/gui/draggableWidget.py +38 -0
- batFramework/gui/image.py +33 -28
- batFramework/gui/indicator.py +30 -16
- batFramework/gui/interactiveWidget.py +72 -20
- batFramework/gui/label.py +240 -98
- batFramework/gui/layout.py +125 -53
- batFramework/gui/meter.py +76 -0
- batFramework/gui/radioButton.py +62 -0
- batFramework/gui/root.py +72 -48
- batFramework/gui/shape.py +257 -49
- batFramework/gui/slider.py +217 -2
- batFramework/gui/textInput.py +106 -60
- batFramework/gui/toggle.py +85 -42
- batFramework/gui/widget.py +259 -288
- batFramework/manager.py +30 -16
- batFramework/object.py +115 -0
- batFramework/{particles.py → particle.py} +37 -34
- batFramework/renderGroup.py +62 -0
- batFramework/resourceManager.py +36 -24
- batFramework/scene.py +94 -88
- batFramework/sceneManager.py +140 -57
- batFramework/scrollingSprite.py +113 -0
- batFramework/sprite.py +35 -23
- batFramework/tileset.py +34 -52
- batFramework/time.py +105 -56
- batFramework/transition.py +213 -1
- batFramework/utils.py +38 -18
- {batframework-1.0.7.dist-info → batframework-1.0.8a1.dist-info}/METADATA +1 -1
- batframework-1.0.8a1.dist-info/RECORD +56 -0
- {batframework-1.0.7.dist-info → batframework-1.0.8a1.dist-info}/WHEEL +1 -1
- batFramework/easing.py +0 -76
- batFramework/gui/constraints.py +0 -277
- batFramework/gui/frame.py +0 -25
- batFramework/transitionManager.py +0 -0
- batframework-1.0.7.dist-info/RECORD +0 -50
- {batframework-1.0.7.dist-info → batframework-1.0.8a1.dist-info}/LICENCE +0 -0
- {batframework-1.0.7.dist-info → batframework-1.0.8a1.dist-info}/top_level.txt +0 -0
batFramework/gui/widget.py
CHANGED
@@ -1,39 +1,94 @@
|
|
1
|
-
from
|
2
|
-
from
|
3
|
-
|
4
|
-
if TYPE_CHECKING:
|
5
|
-
from .constraints import Constraint
|
6
|
-
from .root import Root
|
7
|
-
from .interactiveWidget import InteractiveWidget
|
8
|
-
from typing import Self
|
9
|
-
|
1
|
+
from typing import TYPE_CHECKING,Self,Callable
|
2
|
+
from collections.abc import Iterable
|
10
3
|
import batFramework as bf
|
11
4
|
import pygame
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
5
|
+
if TYPE_CHECKING :
|
6
|
+
from .constraints.constraints import Constraint
|
7
|
+
from .root import Root
|
8
|
+
MAX_CONSTRAINTS = 10
|
16
9
|
class Widget(bf.Entity):
|
17
|
-
def __init__(self
|
18
|
-
super().__init__(
|
19
|
-
self.autoresize = False
|
20
|
-
self.parent: None | Self = None
|
21
|
-
self.is_root: bool = False
|
10
|
+
def __init__(self,*args,**kwargs) -> None:
|
11
|
+
super().__init__(*args,**kwargs)
|
22
12
|
self.children: list["Widget"] = []
|
23
|
-
self.
|
24
|
-
self.
|
25
|
-
self.
|
26
|
-
|
27
|
-
|
28
|
-
self.
|
29
|
-
self.
|
13
|
+
self.constraints : list[Constraint] = []
|
14
|
+
self.parent : "Widget" = None
|
15
|
+
self.do_sort_children =False
|
16
|
+
self.clip_children : bool = True
|
17
|
+
self.padding = (0, 0, 0, 0)
|
18
|
+
self.dirty_surface : bool = True # if true will call paint before drawing
|
19
|
+
self.dirty_shape : bool = True # if true will call (build+paint) before drawing
|
20
|
+
self.dirty_constraints : bool = False
|
21
|
+
self.is_root : bool = False
|
22
|
+
self.autoresize_w,self.autoresize_h = True,True
|
23
|
+
self.__constraint_iteration = 0
|
24
|
+
|
25
|
+
def set_clip_children(self,value:bool)->Self:
|
26
|
+
self.clip_children = value
|
27
|
+
self.dirty_surface = True
|
28
|
+
return self
|
30
29
|
|
31
|
-
def
|
32
|
-
|
33
|
-
|
34
|
-
|
30
|
+
def __str__(self)->str:
|
31
|
+
return "Widget"
|
32
|
+
|
33
|
+
def set_autoresize(self,value:bool)->Self:
|
34
|
+
self.autoresize_w = self.autoresize_h = value
|
35
|
+
self.dirty_shape = True
|
36
|
+
return self
|
37
|
+
|
38
|
+
def set_autoresize_w(self,value:bool)->Self:
|
39
|
+
self.autoresize_w = value
|
40
|
+
self.dirty_shape = True
|
41
|
+
return self
|
42
|
+
|
43
|
+
def set_autoresize_h(self,value:bool)->Self:
|
44
|
+
self.autoresize_h = value
|
45
|
+
self.dirty_shape = True
|
46
|
+
return self
|
47
|
+
|
48
|
+
def set_render_order(self,render_order:int)->Self:
|
49
|
+
super().set_render_order(render_order)
|
50
|
+
if self.parent:self.parent.do_sort_children = True
|
51
|
+
return self
|
52
|
+
|
53
|
+
|
54
|
+
def inflate_rect_by_padding(self,rect: pygame.Rect|pygame.FRect)->pygame.Rect|pygame.FRect:
|
55
|
+
return pygame.FRect(
|
56
|
+
rect[0] - self.padding[0],
|
57
|
+
rect[1] - self.padding[1],
|
58
|
+
rect[2] + self.padding[0] + self.padding[2],
|
59
|
+
rect[3] + self.padding[1] + self.padding[3]
|
35
60
|
)
|
36
|
-
|
61
|
+
|
62
|
+
def set_position(self, x, y) -> Self:
|
63
|
+
if x is None: x = self.rect.x
|
64
|
+
if y is None: y = self.rect.y
|
65
|
+
if (x,y) == self.rect.topleft : return self
|
66
|
+
dx,dy = x-self.rect.x,y-self.rect.y
|
67
|
+
self.rect.topleft = x,y
|
68
|
+
_ = [c.set_position(c.rect.x+dx,c.rect.y+dy) for c in self.children]
|
69
|
+
return self
|
70
|
+
|
71
|
+
def set_center(self,x,y)->Self:
|
72
|
+
if x is None : x = self.rect.centerx
|
73
|
+
if y is None : y = self.rect.centery
|
74
|
+
if (x,y) == self.rect.center : return self
|
75
|
+
dx,dy = x-self.rect.centerx,y-self.rect.centery
|
76
|
+
self.rect.center = x,y
|
77
|
+
_ = [c.set_center(c.rect.centerx+dx,c.rect.centery+dy) for c in self.children]
|
78
|
+
return self
|
79
|
+
|
80
|
+
def set_parent_scene(self,parent_scene:bf.Scene)->Self:
|
81
|
+
super().set_parent_scene(parent_scene)
|
82
|
+
for c in self.children :
|
83
|
+
c.set_parent_scene(parent_scene)
|
84
|
+
return self
|
85
|
+
|
86
|
+
def set_parent(self,parent:"Widget")->Self:
|
87
|
+
self.parent = parent
|
88
|
+
return self
|
89
|
+
|
90
|
+
def set_padding(self, value: float | int | tuple | list) -> Self:
|
91
|
+
if isinstance(value, Iterable):
|
37
92
|
if len(value) > 4:
|
38
93
|
pass
|
39
94
|
elif any(v < 0 for v in value):
|
@@ -45,306 +100,222 @@ class Widget(bf.Entity):
|
|
45
100
|
else:
|
46
101
|
self.padding = (value,) * 4
|
47
102
|
|
48
|
-
self.
|
49
|
-
old_raw_size[0] + self.padding[0] + self.padding[2],
|
50
|
-
old_raw_size[1] + self.padding[1] + self.padding[3],
|
51
|
-
)
|
103
|
+
self.dirty_shape = True
|
52
104
|
return self
|
53
105
|
|
106
|
+
def get_padded_rect(self)->pygame.FRect:
|
107
|
+
r = self.rect.inflate(-self.padding[0]-self.padding[2],-self.padding[1]-self.padding[3])
|
108
|
+
# r.normalize()
|
109
|
+
return r
|
54
110
|
|
55
|
-
def inflate_rect_by_padding(self, rect: pygame.FRect) -> pygame.FRect:
|
56
|
-
return pygame.FRect(
|
57
|
-
rect[0] - self.padding[0],
|
58
|
-
rect[1] - self.padding[1],
|
59
|
-
rect[2] + self.padding[0] + self.padding[2],
|
60
|
-
rect[3] + self.padding[1] + self.padding[3],
|
61
|
-
)
|
62
111
|
def get_min_required_size(self)->tuple[float,float]:
|
63
112
|
return self.rect.size
|
64
113
|
|
65
|
-
def
|
66
|
-
return self.rect.left + self.padding[0]
|
67
|
-
|
68
|
-
def get_content_top(self) -> float:
|
69
|
-
return self.rect.top + self.padding[1]
|
70
|
-
|
71
|
-
def get_content_right(self) -> float:
|
72
|
-
return self.rect.right - self.padding[2]
|
73
|
-
|
74
|
-
def get_content_bottom(self) -> float:
|
75
|
-
return self.rect.bottom - self.padding[3]
|
76
|
-
|
77
|
-
def get_content_width(self) -> float:
|
114
|
+
def get_padded_width(self)->float:
|
78
115
|
return self.rect.w - self.padding[0] - self.padding[2]
|
79
|
-
|
80
|
-
def
|
116
|
+
|
117
|
+
def get_padded_height(self)->float:
|
81
118
|
return self.rect.h - self.padding[1] - self.padding[3]
|
119
|
+
|
120
|
+
def get_padded_left(self)->float:
|
121
|
+
return self.rect.left + self.padding[0]
|
82
122
|
|
83
|
-
def
|
84
|
-
return
|
85
|
-
self.rect.left + self.padding[0],
|
86
|
-
self.rect.top + self.padding[1],
|
87
|
-
self.get_content_width(),
|
88
|
-
self.get_content_height(),
|
89
|
-
)
|
90
|
-
|
91
|
-
def get_content_rect_rel(self) -> pygame.FRect:
|
92
|
-
return self.get_content_rect().move(-self.rect.left, -self.rect.top)
|
93
|
-
|
94
|
-
def get_content_center(self) -> tuple[float, float]:
|
95
|
-
return self.get_content_rect().center
|
96
|
-
|
97
|
-
def get_depth(self) -> int:
|
98
|
-
if self.is_root or self.parent is None:
|
99
|
-
self.gui_depth = 0
|
100
|
-
else:
|
101
|
-
self.gui_depth = self.parent.get_depth() + 1
|
102
|
-
return self.gui_depth
|
103
|
-
|
104
|
-
def top_at(self, x: float|int, y: float|int) -> "None|Widget":
|
105
|
-
if self.visible and self.rect.collidepoint(x, y):
|
106
|
-
if self.children:
|
107
|
-
for child in reversed(self.children):
|
108
|
-
r = child.top_at(x, y)
|
109
|
-
if r is not None:
|
110
|
-
return r
|
111
|
-
return self
|
112
|
-
|
113
|
-
return None
|
123
|
+
def get_padded_right(self)->float:
|
124
|
+
return self.rect.right + self.padding[2]
|
114
125
|
|
115
|
-
def
|
116
|
-
return
|
126
|
+
def get_padded_center(self)->tuple[float,float]:
|
127
|
+
return self.get_padded_rect().center
|
117
128
|
|
118
|
-
def
|
119
|
-
|
120
|
-
c = self.get_constraint(constraint.name)
|
121
|
-
if c is not None:
|
122
|
-
self.constraints.remove(c)
|
123
|
-
self.constraints.append(constraint)
|
124
|
-
self.apply_constraints()
|
125
|
-
return self
|
129
|
+
def get_padded_top(self)->float:
|
130
|
+
return self.rect.y + self.padding[1]
|
126
131
|
|
127
|
-
def
|
128
|
-
return
|
132
|
+
def get_padded_bottom(self)->float:
|
133
|
+
return self.rect.bottom - self.padding[3]
|
129
134
|
|
130
|
-
def
|
135
|
+
def get_debug_outlines(self):
|
136
|
+
yield (self.rect, self.debug_color)
|
137
|
+
if any(self.padding) : yield (self.get_padded_rect(),"gray")
|
131
138
|
for child in self.children:
|
132
|
-
child.
|
133
|
-
|
139
|
+
yield from child.get_debug_outlines()
|
140
|
+
|
141
|
+
def add_constraints(self,*constraints:"Constraint")->Self:
|
142
|
+
self.constraints.extend(constraints)
|
143
|
+
seen = set()
|
144
|
+
result = []
|
145
|
+
for c in self.constraints:
|
146
|
+
if c.name not in seen:
|
147
|
+
result.append(c)
|
148
|
+
seen.add(c.name)
|
149
|
+
self.constraints = result
|
150
|
+
self.constraints.sort(key=lambda c : c.priority)
|
151
|
+
self.dirty_constraints = True
|
152
|
+
return self
|
134
153
|
|
135
|
-
def
|
136
|
-
if not self.
|
137
|
-
|
138
|
-
return
|
139
|
-
if not self.constraints:
|
154
|
+
def resolve_constraints(self)->None:
|
155
|
+
if self.parent is None or not self.constraints:
|
156
|
+
self.dirty_constraints = False
|
140
157
|
return
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
for iteration in range(MAX_CONSTRAINT_ITERATION):
|
145
|
-
unsatisfied = [] # Initialize a flag
|
146
|
-
|
158
|
+
all_good = False
|
159
|
+
constraint_iteration = 0
|
160
|
+
while not all_good:
|
147
161
|
for constraint in self.constraints:
|
148
|
-
if not constraint.evaluate(self.parent,
|
149
|
-
|
150
|
-
constraint.
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
yield from c.get_by_tags(*tags)
|
166
|
-
if any(self.has_tags(t) for t in tags):
|
167
|
-
yield self
|
168
|
-
|
169
|
-
def count_children_recursive(self):
|
170
|
-
return 1 + sum(child.count_children_recursive() for child in self.children)
|
171
|
-
|
172
|
-
|
173
|
-
def propagate_function(self,function):
|
174
|
-
function(self)
|
175
|
-
for child in self.children:
|
176
|
-
child.propagate_function(function)
|
177
|
-
|
178
|
-
def get_root(self) -> Root | None:
|
179
|
-
if self.parent_scene is not None:
|
180
|
-
return self.parent_scene.root
|
181
|
-
return None if self.parent is None else self.parent.get_root()
|
182
|
-
|
183
|
-
def get_size_int(self) -> tuple[int, int]:
|
184
|
-
return (ceil(self.rect.width), ceil(self.rect.height))
|
162
|
+
if not constraint.evaluate(self.parent,self):
|
163
|
+
constraint.apply(self.parent,self)
|
164
|
+
# print(constraint.name,"Applied")
|
165
|
+
constraint_iteration += 1
|
166
|
+
if all(c.evaluate(self.parent,self) for c in self.constraints):
|
167
|
+
all_good = True
|
168
|
+
break
|
169
|
+
elif self.__constraint_iteration > MAX_CONSTRAINTS:
|
170
|
+
print(self,"CONSTRAINTS ERROR",list(c.name for c in self.constraints if not c.evaluate(self.parent,self)))
|
171
|
+
self.dirty_constraints = False
|
172
|
+
return
|
173
|
+
# print("DONE")
|
174
|
+
self.dirty_constraints = False
|
175
|
+
|
176
|
+
def remove_constraints(self,*names:str)->Self:
|
177
|
+
self.constraints = [c for c in self.constraints if c.name not in names]
|
178
|
+
return self
|
185
179
|
|
186
|
-
def
|
187
|
-
return self.
|
180
|
+
def has_constraint(self,name:str)->bool:
|
181
|
+
return any(c.name == name for c in self.constraints )
|
188
182
|
|
189
|
-
def
|
190
|
-
|
191
|
-
yield (self.get_content_rect(), "yellow")
|
183
|
+
def visit(self,func:Callable,top_down:bool = True)->None:
|
184
|
+
if top_down : func(self)
|
192
185
|
for child in self.children:
|
193
|
-
|
186
|
+
child.visit(func,top_down)
|
187
|
+
if not top_down: func(self)
|
194
188
|
|
195
|
-
def
|
196
|
-
self.
|
197
|
-
|
198
|
-
return self
|
189
|
+
def get_root(self)->"Root":
|
190
|
+
if self.is_root:
|
191
|
+
return self
|
192
|
+
return self.parent.get_root()
|
199
193
|
|
200
|
-
def
|
194
|
+
def top_at(self, x: float | int, y: float | int) -> "None|Widget":
|
195
|
+
if self.children:
|
196
|
+
for child in reversed(self.children):
|
197
|
+
if child.visible:
|
198
|
+
r = child.top_at(x, y)
|
199
|
+
if r is not None:
|
200
|
+
return r
|
201
|
+
return self if self.visible and self.rect.collidepoint(x, y) else None
|
202
|
+
|
203
|
+
def add(self,*children:"Widget")->Self:
|
204
|
+
self.children.extend(children)
|
205
|
+
i = len(self.children)
|
206
|
+
for child in children:
|
207
|
+
child.set_render_order(i).set_parent(self).set_parent_scene(self.parent_scene)
|
208
|
+
i += 1
|
201
209
|
if self.parent:
|
202
|
-
self.parent.
|
203
|
-
self.parent = parent
|
204
|
-
self.apply_all_constraints()
|
210
|
+
self.parent.do_sort_children = True
|
205
211
|
return self
|
206
212
|
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
super().set_parent_scene(scene)
|
215
|
-
for child in self.children:
|
216
|
-
child.set_parent_scene(scene)
|
217
|
-
return self
|
218
|
-
def set_x(self, x: float) -> Self:
|
219
|
-
if x == self.rect.x : return self
|
220
|
-
delta = x - self.rect.x
|
221
|
-
self.rect.x = x
|
222
|
-
for child in self.children:
|
223
|
-
child.set_x(child.rect.x + delta)
|
224
|
-
self.apply_constraints()
|
225
|
-
return self
|
213
|
+
def remove(self,*children:"Widget")->Self:
|
214
|
+
for child in self.children[:]:
|
215
|
+
if child in children:
|
216
|
+
child.set_parent(None).set_parent_scene(None)
|
217
|
+
self.children.remove(child)
|
218
|
+
if self.parent:
|
219
|
+
self.parent.do_sort_children = True
|
226
220
|
|
227
|
-
def
|
228
|
-
|
229
|
-
|
230
|
-
self.
|
231
|
-
for child in self.children:
|
232
|
-
child.set_y(child.rect.y + delta)
|
233
|
-
self.apply_constraints()
|
234
|
-
return self
|
221
|
+
def set_size_if_autoresize(self,size:tuple[float,float])->Self:
|
222
|
+
size = list(size)
|
223
|
+
size[0] = size[0] if self.autoresize_w else None
|
224
|
+
size[1] = size[1] if self.autoresize_h else None
|
235
225
|
|
236
|
-
|
237
|
-
if self.rect.topleft == (x,y) : return self
|
238
|
-
delta_x = x - self.rect.x
|
239
|
-
delta_y = y - self.rect.y
|
240
|
-
self.rect.topleft = x, y
|
241
|
-
for child in self.children:
|
242
|
-
child.set_position(child.rect.x + delta_x, child.rect.y + delta_y)
|
243
|
-
self.apply_constraints()
|
244
|
-
return self
|
226
|
+
self.set_size(size)
|
245
227
|
|
246
|
-
def set_center(self, x: float, y: float) -> Self:
|
247
|
-
if self.rect.center == (x,y) : return self
|
248
|
-
delta_x = x - self.rect.centerx
|
249
|
-
delta_y = y - self.rect.centery
|
250
|
-
self.rect.center = x, y
|
251
|
-
for child in self.children:
|
252
|
-
child.set_position(child.rect.x + delta_x, child.rect.y + delta_y)
|
253
|
-
self.apply_constraints()
|
254
228
|
return self
|
255
229
|
|
256
|
-
def set_size(self,
|
257
|
-
|
258
|
-
if
|
259
|
-
if
|
260
|
-
self.rect.size
|
261
|
-
self.
|
262
|
-
self.
|
263
|
-
self.children_modified()
|
230
|
+
def set_size(self,size:tuple)->Self:
|
231
|
+
size = list(size)
|
232
|
+
if size[0] is None : size[0] = self.rect.w
|
233
|
+
if size[1] is None : size[1] = self.rect.h
|
234
|
+
if size == self.rect.size : return self
|
235
|
+
self.rect.size = size
|
236
|
+
self.dirty_shape = True
|
264
237
|
return self
|
238
|
+
|
265
239
|
|
266
|
-
|
267
|
-
|
268
|
-
def print_tree(self, ident: int = 0) -> None:
|
269
|
-
print("\t" * ident + self.to_string() + (":" if self.children else ""))
|
240
|
+
def process_event(self, event: pygame.Event) -> bool:
|
241
|
+
# First propagate to children
|
270
242
|
for child in self.children:
|
271
|
-
child.
|
272
|
-
|
273
|
-
|
274
|
-
return f"{self.to_string_id()}@{*self.rect.topleft,* self.rect.size}"
|
275
|
-
|
276
|
-
def to_string_id(self) -> str:
|
277
|
-
return "Widget"
|
243
|
+
child.process_event(event)
|
244
|
+
# return True if the method is blocking (no propagation to next children of the scene)
|
245
|
+
super().process_event(event)
|
278
246
|
|
279
|
-
def do_when_removed(self) -> None:
|
280
|
-
if self.parent_scene and self.parent == self.parent_scene.root:
|
281
|
-
self.set_parent(None)
|
282
|
-
|
283
|
-
# Methods on children
|
284
|
-
|
285
|
-
def add_child(self, *child: "Widget") -> None:
|
286
|
-
for c in child:
|
287
|
-
self.children.append(c)
|
288
|
-
c.set_parent(self)
|
289
|
-
c.set_parent_scene(self.parent_scene)
|
290
|
-
c.do_when_added()
|
291
|
-
self._sort_children()
|
292
|
-
self.apply_all_constraints()
|
293
|
-
self.children_modified()
|
294
|
-
|
295
|
-
def remove_child(self, child: "Widget") -> None:
|
296
|
-
try :
|
297
|
-
self.children.remove(child)
|
298
|
-
except ValueError:
|
299
|
-
return
|
300
|
-
child.set_parent(None)
|
301
|
-
child.do_when_removed()
|
302
|
-
child.set_parent_scene(None)
|
303
|
-
self._sort_children()
|
304
|
-
self.apply_all_constraints()
|
305
|
-
self.children_modified()
|
306
247
|
|
307
|
-
def
|
308
|
-
self.
|
248
|
+
def update(self,dt)->None:
|
249
|
+
if self.do_sort_children:
|
250
|
+
self.children.sort(key = lambda c : c.render_order)
|
251
|
+
self.do_sort_children = False
|
252
|
+
_ = [c.update(dt) for c in self.children]
|
253
|
+
super().update(dt)
|
309
254
|
|
310
255
|
|
311
|
-
|
312
|
-
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
-
# return True if the method is blocking (no propagation to next children of the scene)
|
318
|
-
return super().process_event(event)
|
256
|
+
def build(self)->None:
|
257
|
+
new_size =tuple(map(int,self.rect.size))
|
258
|
+
if self.surface.get_size() != new_size:
|
259
|
+
new_size = [max(0,i) for i in new_size]
|
260
|
+
self.surface = pygame.Surface(new_size,self.surface_flags)
|
261
|
+
if self.convert_alpha : self.surface = self.surface.convert_alpha()
|
319
262
|
|
320
|
-
def
|
321
|
-
|
322
|
-
|
323
|
-
self.do_update(dt)
|
263
|
+
def paint(self)->None:
|
264
|
+
self.surface.fill((0,0,0,0))
|
265
|
+
return self
|
324
266
|
|
325
|
-
def
|
326
|
-
|
327
|
-
|
328
|
-
|
267
|
+
def visit_up(self,func)->None:
|
268
|
+
if func(self) : return
|
269
|
+
if self.parent:
|
270
|
+
self.parent.visit_up(func)
|
271
|
+
|
272
|
+
def selective_up(self,widget:"Widget"):
|
273
|
+
# if returns True then stop climbing widget tree
|
274
|
+
if widget.parent and widget.parent.dirty_constraints:
|
275
|
+
return False
|
276
|
+
widget.visit(self.selective_down)
|
277
|
+
return True
|
278
|
+
|
279
|
+
def selective_down(self,widget: "Widget"):
|
280
|
+
if widget.constraints :
|
281
|
+
widget.resolve_constraints()
|
282
|
+
else:
|
283
|
+
widget.dirty_constraints = False
|
284
|
+
if widget.dirty_shape:
|
285
|
+
widget.build()
|
286
|
+
widget.dirty_shape = False
|
287
|
+
self.dirty_surface = True
|
288
|
+
|
289
|
+
|
290
|
+
def draw(self, camera: bf.Camera) -> None:
|
291
|
+
if self.dirty_shape:
|
292
|
+
self.dirty_constraints = True
|
293
|
+
self.dirty_surface = True
|
294
|
+
self.build()
|
295
|
+
self.dirty_shape = False
|
296
|
+
for child in self.children :
|
297
|
+
child.dirty_constraints = True
|
298
|
+
|
299
|
+
if self.dirty_constraints:
|
300
|
+
if self.parent and self.parent.dirty_constraints:
|
301
|
+
self.parent.visit_up(self.selective_up)
|
302
|
+
else:
|
303
|
+
self.visit(lambda c : c.resolve_constraints())
|
329
304
|
|
330
|
-
|
331
|
-
|
332
|
-
|
333
|
-
It usually has to be overriden if inherited to suit the needs of the new class
|
334
|
-
"""
|
335
|
-
if not self.surface:
|
336
|
-
return
|
337
|
-
if self.surface.get_size() != self.get_size_int():
|
338
|
-
self.surface = pygame.Surface(self.get_size_int())
|
305
|
+
if self.dirty_surface :
|
306
|
+
self.paint()
|
307
|
+
self.dirty_surface = False
|
339
308
|
|
340
309
|
|
341
|
-
def build_all(self) -> None:
|
342
|
-
self.build()
|
343
|
-
for child in self.children:
|
344
|
-
child.build_all()
|
345
310
|
|
346
|
-
|
347
|
-
if self.
|
348
|
-
self.parent.children_modified()
|
311
|
+
super().draw(camera)
|
312
|
+
if self.clip_children:
|
349
313
|
|
314
|
+
new_clip = camera.world_to_screen(self.get_padded_rect())
|
315
|
+
old_clip = camera.surface.get_clip()
|
316
|
+
new_clip = new_clip.clip(old_clip)
|
317
|
+
camera.surface.set_clip(new_clip)
|
350
318
|
|
319
|
+
_ = [child.draw(camera) for child in sorted(self.children, key=lambda c: c.render_order)]
|
320
|
+
if self.clip_children:
|
321
|
+
camera.surface.set_clip(old_clip)
|