batframework 1.0.8a1__py3-none-any.whl → 1.0.8a2__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 (63) hide show
  1. batFramework/__init__.py +50 -53
  2. batFramework/action.py +105 -116
  3. batFramework/actionContainer.py +11 -53
  4. batFramework/animatedSprite.py +65 -115
  5. batFramework/audioManager.py +26 -70
  6. batFramework/camera.py +68 -253
  7. batFramework/constants.py +54 -16
  8. batFramework/cutscene.py +25 -34
  9. batFramework/cutsceneBlocks.py +42 -37
  10. batFramework/debugger.py +48 -0
  11. batFramework/dynamicEntity.py +7 -9
  12. batFramework/easing.py +71 -0
  13. batFramework/entity.py +98 -42
  14. batFramework/gui/__init__.py +2 -8
  15. batFramework/gui/button.py +79 -7
  16. batFramework/gui/constraints.py +204 -0
  17. batFramework/gui/container.py +31 -155
  18. batFramework/gui/debugger.py +43 -124
  19. batFramework/gui/frame.py +19 -0
  20. batFramework/gui/image.py +17 -41
  21. batFramework/gui/indicator.py +21 -41
  22. batFramework/gui/interactiveWidget.py +13 -116
  23. batFramework/gui/label.py +73 -278
  24. batFramework/gui/layout.py +61 -148
  25. batFramework/gui/root.py +37 -102
  26. batFramework/gui/shape.py +57 -258
  27. batFramework/gui/toggle.py +46 -97
  28. batFramework/gui/widget.py +254 -268
  29. batFramework/manager.py +19 -40
  30. batFramework/particles.py +77 -0
  31. batFramework/scene.py +107 -214
  32. batFramework/sceneManager.py +107 -150
  33. batFramework/stateMachine.py +0 -1
  34. batFramework/time.py +57 -117
  35. batFramework/transition.py +126 -184
  36. batFramework/transitionManager.py +0 -0
  37. batFramework/utils.py +161 -34
  38. batframework-1.0.8a2.dist-info/METADATA +58 -0
  39. batframework-1.0.8a2.dist-info/RECORD +42 -0
  40. {batframework-1.0.8a1.dist-info → batframework-1.0.8a2.dist-info}/WHEEL +1 -1
  41. batFramework/easingController.py +0 -58
  42. batFramework/enums.py +0 -104
  43. batFramework/fontManager.py +0 -65
  44. batFramework/gui/clickableWidget.py +0 -206
  45. batFramework/gui/constraints/__init__.py +0 -1
  46. batFramework/gui/constraints/constraints.py +0 -378
  47. batFramework/gui/dialogueBox.py +0 -96
  48. batFramework/gui/draggableWidget.py +0 -38
  49. batFramework/gui/meter.py +0 -76
  50. batFramework/gui/radioButton.py +0 -62
  51. batFramework/gui/slider.py +0 -220
  52. batFramework/gui/textInput.py +0 -134
  53. batFramework/object.py +0 -115
  54. batFramework/particle.py +0 -101
  55. batFramework/renderGroup.py +0 -62
  56. batFramework/resourceManager.py +0 -84
  57. batFramework/scrollingSprite.py +0 -113
  58. batFramework/sprite.py +0 -45
  59. batFramework/tileset.py +0 -46
  60. batframework-1.0.8a1.dist-info/LICENCE +0 -21
  61. batframework-1.0.8a1.dist-info/METADATA +0 -55
  62. batframework-1.0.8a1.dist-info/RECORD +0 -56
  63. {batframework-1.0.8a1.dist-info → batframework-1.0.8a2.dist-info}/top_level.txt +0 -0
@@ -1,321 +1,307 @@
1
- from typing import TYPE_CHECKING,Self,Callable
2
- from collections.abc import Iterable
1
+ from __future__ import annotations
2
+ from typing import TYPE_CHECKING
3
+ if TYPE_CHECKING:
4
+ from .constraints import Constraint
5
+ from .root import Root
6
+ from typing import Self
7
+
3
8
  import batFramework as bf
4
9
  import pygame
5
- if TYPE_CHECKING :
6
- from .constraints.constraints import Constraint
7
- from .root import Root
8
- MAX_CONSTRAINTS = 10
10
+ from math import ceil
11
+
12
+
13
+
9
14
  class Widget(bf.Entity):
10
- def __init__(self,*args,**kwargs) -> None:
11
- super().__init__(*args,**kwargs)
12
- self.children: list["Widget"] = []
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
13
22
  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
29
-
30
- def __str__(self)->str:
31
- return "Widget"
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
32
42
 
33
- def set_autoresize(self,value:bool)->Self:
34
- self.autoresize_w = self.autoresize_h = value
35
- self.dirty_shape = True
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
+ )
36
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]
37
58
 
38
- def set_autoresize_w(self,value:bool)->Self:
39
- self.autoresize_w = value
40
- self.dirty_shape = True
41
- return self
59
+ def get_content_top(self)->float:
60
+ return self.rect.top + self.padding[1]
42
61
 
43
- def set_autoresize_h(self,value:bool)->Self:
44
- self.autoresize_h = value
45
- self.dirty_shape = True
46
- return self
62
+ def get_content_right(self)->float:
63
+ return self.rect.right - self.padding[2]
47
64
 
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
65
+ def get_content_bottom(self)->float:
66
+ return self.rect.bottom - self.padding[3]
67
+
68
+ def get_content_width(self)->float:
69
+ return self.rect.w - self.padding[0] - self.padding[2]
52
70
 
71
+ def get_content_height(self)->float:
72
+ return self.rect.h - self.padding[1] - self.padding[3]
53
73
 
54
- def inflate_rect_by_padding(self,rect: pygame.Rect|pygame.FRect)->pygame.Rect|pygame.FRect:
74
+ def get_content_rect(self)->pygame.FRect:
55
75
  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]
76
+ self.rect.left + self.padding[0],
77
+ self.rect.top + self.padding[1],
78
+ self.get_content_width(),
79
+ self.get_content_height()
60
80
  )
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
81
 
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
82
+ def get_content_rect_rel(self)->pygame.FRect:
83
+ return self.get_content_rect().move(-self.rect.left,-self.rect.top)
79
84
 
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
85
+ def get_content_center(self)->tuple[float,float]:
86
+ return self.get_content_rect().center
89
87
 
90
- def set_padding(self, value: float | int | tuple | list) -> Self:
91
- if isinstance(value, Iterable):
92
- if len(value) > 4:
93
- pass
94
- elif any(v < 0 for v in value):
95
- pass
96
- elif len(value) == 2:
97
- self.padding = (value[0], value[1], value[0], value[1])
98
- else:
99
- self.padding = (*value, *self.padding[len(value) :])
88
+ def get_depth(self)->int:
89
+ if self.is_root or self.parent is None :
90
+ self.gui_depth = 0
100
91
  else:
101
- self.padding = (value,) * 4
92
+ self.gui_depth = self.parent.get_depth() + 1
93
+ return self.gui_depth
102
94
 
103
- self.dirty_shape = True
104
- return self
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:
102
+ return self
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)
105
107
 
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
108
+ def add_constraints(self,*constraints:Constraint)->Self:
109
+ for c in constraints:
110
+ self.add_constraint(c,False)
111
+ self.apply_constraints()
112
+ return self
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()
120
+ return self
110
121
 
111
- def get_min_required_size(self)->tuple[float,float]:
112
- return self.rect.size
122
+ def has_constraint(self,name:str)->bool:
123
+ return any(c.name == name for c in self.constraints)
113
124
 
114
- def get_padded_width(self)->float:
115
- return self.rect.w - self.padding[0] - self.padding[2]
116
-
117
- def get_padded_height(self)->float:
118
- return self.rect.h - self.padding[1] - self.padding[3]
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()
119
129
 
120
- def get_padded_left(self)->float:
121
- return self.rect.left + self.padding[0]
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)
122
138
 
123
- def get_padded_right(self)->float:
124
- return self.rect.right + self.padding[2]
139
+ for iteration in range(max_iterations):
140
+ unsatisfied = [] # Initialize a flag
125
141
 
126
- def get_padded_center(self)->tuple[float,float]:
127
- return self.get_padded_rect().center
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])}")
153
+
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()
159
+
160
+ def get_size_int(self)->tuple[int,int]:
161
+ return (ceil(self.rect.width),ceil(self.rect.height))
162
+
163
+
164
+ def get_center(self)->tuple[float,float]:
165
+ return self.rect.center
166
+
167
+
168
+ def get_bounding_box(self):
169
+ yield (self.rect,self._debug_color)
170
+ yield (self.get_content_rect(),"yellow")
171
+ for child in self.children:
172
+ yield from child.get_bounding_box()
128
173
 
129
- def get_padded_top(self)->float:
130
- return self.rect.y + self.padding[1]
174
+ def set_autoresize(self,value:bool)-> Self:
175
+ self.autoresize = value
176
+ self.build()
177
+ return self
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
131
189
 
132
- def get_padded_bottom(self)->float:
133
- return self.rect.bottom - self.padding[3]
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)
134
194
 
135
- def get_debug_outlines(self):
136
- yield (self.rect, self.debug_color)
137
- if any(self.padding) : yield (self.get_padded_rect(),"gray")
195
+ def set_x(self,x:float)->Self:
196
+ delta = x - self.rect.x
197
+ self.rect.x = x
138
198
  for child in self.children:
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
199
+ child.set_x(child.rect.x + delta)
200
+ self.apply_constraints()
152
201
  return self
153
202
 
154
- def resolve_constraints(self)->None:
155
- if self.parent is None or not self.constraints:
156
- self.dirty_constraints = False
157
- return
158
- all_good = False
159
- constraint_iteration = 0
160
- while not all_good:
161
- for constraint in self.constraints:
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
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()
179
209
 
180
- def has_constraint(self,name:str)->bool:
181
- return any(c.name == name for c in self.constraints )
210
+ return self
182
211
 
183
- def visit(self,func:Callable,top_down:bool = True)->None:
184
- if top_down : func(self)
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
185
216
  for child in self.children:
186
- child.visit(func,top_down)
187
- if not top_down: func(self)
217
+ child.set_position(child.rect.x + delta_x,child.rect.y+delta_y)
218
+ self.apply_constraints()
219
+ return self
220
+
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
188
229
 
189
- def get_root(self)->"Root":
190
- if self.is_root:
191
- return self
192
- return self.parent.get_root()
193
230
 
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
209
- if self.parent:
210
- self.parent.do_sort_children = True
231
+ def set_size(self, width : float, height: float) -> Self:
232
+ self.rect.size = (width,height)
233
+ self.build()
211
234
  return self
235
+
212
236
 
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
237
+ # Other Methods
220
238
 
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
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)
225
243
 
226
- self.set_size(size)
244
+ def to_string(self)->str:
245
+
246
+ return f"{self.to_string_id()}@{*self.rect.topleft,* self.rect.size}"
227
247
 
228
- return self
229
248
 
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
237
- return self
238
-
249
+ def to_string_id(self)->str:
250
+ return "Widget"
239
251
 
240
- def process_event(self, event: pygame.Event) -> bool:
241
- # First propagate to children
242
- for child in self.children:
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)
246
252
 
253
+ def do_when_removed(self)->None:
254
+ if self.parent_scene and self.parent == self.parent_scene.root:
255
+ self.set_parent(None)
247
256
 
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)
257
+ # Methods on children
254
258
 
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()
255
266
 
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()
262
-
263
- def paint(self)->None:
264
- self.surface.fill((0,0,0,0))
265
- return self
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()
266
272
 
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())
304
273
 
305
- if self.dirty_surface :
306
- self.paint()
307
- self.dirty_surface = False
308
274
 
309
275
 
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)
310
284
 
311
- super().draw(camera)
312
- if self.clip_children:
313
285
 
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)
286
+ def update(self,dt:float):
287
+ for child in self.children:
288
+ child.update(dt)
318
289
 
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)
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()
batFramework/manager.py CHANGED
@@ -2,70 +2,49 @@ import batFramework as bf
2
2
  import pygame
3
3
  import random
4
4
 
5
-
6
5
  class Manager(bf.SceneManager):
7
6
  def __init__(self, *initial_scene_list) -> None:
8
- # random.seed("random")
9
- super().__init__()
10
- self._screen: pygame.Surface | None = bf.const.SCREEN
11
- self._timeManager = bf.TimeManager()
12
- self._cutsceneManager = bf.CutsceneManager()
13
- self._cutsceneManager.set_manager(self)
7
+ random.seed("random")
8
+ self._screen: pygame.Surface = bf.const.SCREEN
9
+ self._timeManager = bf.Time()
10
+ self._cutsceneManager = bf.CutsceneManager(self)
14
11
  self._clock: pygame.Clock = pygame.Clock()
15
- pygame.mouse.set_cursor(bf.const.DEFAULT_CURSOR)
16
- self.do_pre_init()
17
- self.init_scenes(*initial_scene_list)
12
+ super().__init__(*initial_scene_list)
18
13
  self.set_sharedVar("clock", self._clock)
19
14
  self.do_init()
20
15
 
21
16
  @staticmethod
22
- def set_icon(path: str) -> None:
23
- surf = pygame.image.load(bf.ResourceManager().get_path(path)).convert_alpha()
17
+ def set_icon(path: str):
18
+ surf = pygame.image.load(bf.utils.get_path(path)).convert_alpha()
24
19
  pygame.display.set_icon(surf)
25
20
 
26
- def print_status(self):
27
- super().print_status()
28
- print("TIMERS : ")
29
- for r in self._timeManager.get_active_registers():
30
- # print(r["timers"])
31
- print("\n".join(str(t) for t in r))
32
- print("-" * 40)
33
-
34
- def get_fps(self) -> float:
21
+ def get_fps(self):
35
22
  return self._clock.get_fps()
36
23
 
37
- def do_init(self) -> None:
38
- pass
39
-
40
- def do_pre_init(self) -> None:
24
+ def do_init(self):
41
25
  pass
42
26
 
43
- def stop(self) -> None:
27
+ def stop(self)->None:
44
28
  self._running = False
45
29
 
46
- def run(self) -> None:
30
+ def run(self):
47
31
  self._running = True
48
32
  dt: float = 0
49
33
  while self._running:
50
34
  for event in pygame.event.get():
51
- event.consumed = False
35
+ if event.type == pygame.QUIT:
36
+ self._running = False
37
+ break
38
+ if event.type == pygame.VIDEORESIZE:
39
+ bf.const.set_resolution((event.w,event.h))
52
40
  self.process_event(event)
53
- if not event.consumed:
54
- if event.type == pygame.QUIT:
55
- self._running = False
56
- break
57
- if event.type == pygame.VIDEORESIZE and not (
58
- bf.const.FLAGS & pygame.SCALED
59
- ):
60
- bf.const.set_resolution((event.w, event.h))
61
41
  # update
62
- dt = self._clock.tick(bf.const.FPS) / 1000
63
- # dt = min(dt, 0.02) dirty fix for dt being too high when window not focused for a long time
64
- self._timeManager.update(dt)
42
+ dt = self._clock.tick(bf.const.FPS if not bf.const.VSYNC else 0) / 1000
43
+ dt = min(dt, 0.02)
65
44
  self._cutsceneManager.update(dt)
45
+ self._timeManager.update()
66
46
  self.update(dt)
67
47
  # render
68
- self._screen.fill((0, 0, 0))
69
48
  self.draw(self._screen)
70
49
  pygame.display.flip()
71
50
  pygame.quit()