batframework 1.0.8a3__py3-none-any.whl → 1.0.8a6__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 +16 -2
- batFramework/animatedSprite.py +94 -85
- batFramework/audioManager.py +2 -2
- batFramework/character.py +27 -0
- batFramework/cutscene.py +5 -2
- batFramework/cutsceneBlocks.py +3 -5
- batFramework/dynamicEntity.py +11 -4
- batFramework/enums.py +2 -2
- batFramework/fontManager.py +2 -2
- batFramework/gui/clickableWidget.py +10 -9
- batFramework/gui/constraints/constraints.py +282 -57
- batFramework/gui/image.py +14 -14
- batFramework/gui/interactiveWidget.py +16 -1
- batFramework/gui/label.py +58 -37
- batFramework/gui/layout.py +23 -14
- batFramework/gui/meter.py +10 -7
- batFramework/gui/radioButton.py +1 -1
- batFramework/gui/root.py +7 -1
- batFramework/gui/shape.py +21 -37
- batFramework/gui/slider.py +52 -58
- batFramework/gui/textInput.py +161 -51
- batFramework/gui/toggle.py +27 -41
- batFramework/gui/widget.py +68 -35
- batFramework/manager.py +17 -5
- batFramework/object.py +17 -8
- batFramework/particle.py +22 -8
- batFramework/resourceManager.py +18 -2
- batFramework/scene.py +50 -20
- batFramework/sceneManager.py +52 -28
- batFramework/scrollingSprite.py +7 -8
- batFramework/stateMachine.py +9 -6
- batFramework/templates/__init__.py +2 -0
- batFramework/templates/character.py +44 -0
- batFramework/templates/states.py +166 -0
- batFramework/time.py +54 -28
- batFramework/transition.py +25 -12
- batFramework/triggerZone.py +1 -1
- batFramework/utils.py +92 -2
- {batframework-1.0.8a3.dist-info → batframework-1.0.8a6.dist-info}/METADATA +3 -15
- batframework-1.0.8a6.dist-info/RECORD +62 -0
- {batframework-1.0.8a3.dist-info → batframework-1.0.8a6.dist-info}/WHEEL +1 -1
- batframework-1.0.8a3.dist-info/RECORD +0 -58
- {batframework-1.0.8a3.dist-info → batframework-1.0.8a6.dist-info}/LICENCE +0 -0
- {batframework-1.0.8a3.dist-info → batframework-1.0.8a6.dist-info}/top_level.txt +0 -0
batFramework/gui/widget.py
CHANGED
@@ -35,6 +35,8 @@ class Widget(bf.Entity, metaclass=WidgetMeta):
|
|
35
35
|
self.is_root: bool = False
|
36
36
|
self.autoresize_w, self.autoresize_h = True, True
|
37
37
|
self.__constraint_iteration = 0
|
38
|
+
self.__constraints_to_ignore = []
|
39
|
+
self.__constraints_capture = None
|
38
40
|
|
39
41
|
def show(self) -> Self:
|
40
42
|
self.visit(lambda w: w.set_visible(True))
|
@@ -110,7 +112,7 @@ class Widget(bf.Entity, metaclass=WidgetMeta):
|
|
110
112
|
]
|
111
113
|
return self
|
112
114
|
|
113
|
-
def set_parent_scene(self, parent_scene: bf.Scene) -> Self:
|
115
|
+
def set_parent_scene(self, parent_scene: bf.Scene | None) -> Self:
|
114
116
|
super().set_parent_scene(parent_scene)
|
115
117
|
if parent_scene is None:
|
116
118
|
bf.StyleManager().remove_widget(self)
|
@@ -122,8 +124,8 @@ class Widget(bf.Entity, metaclass=WidgetMeta):
|
|
122
124
|
def set_parent(self, parent: "Widget") -> Self:
|
123
125
|
if parent == self.parent:
|
124
126
|
return self
|
125
|
-
if self.parent is not None:
|
126
|
-
|
127
|
+
# if self.parent is not None and self.parent != parent:
|
128
|
+
# self.parent.remove(self)
|
127
129
|
self.parent = parent
|
128
130
|
return self
|
129
131
|
|
@@ -188,47 +190,75 @@ class Widget(bf.Entity, metaclass=WidgetMeta):
|
|
188
190
|
seen = set()
|
189
191
|
result = []
|
190
192
|
for c in self.constraints:
|
191
|
-
if c
|
193
|
+
if not any(c == o for o in seen):
|
192
194
|
result.append(c)
|
193
195
|
seen.add(c.name)
|
194
196
|
self.constraints = result
|
195
197
|
self.constraints.sort(key=lambda c: c.priority)
|
196
198
|
self.dirty_constraints = True
|
199
|
+
self.__constraint_to_ignore = []
|
200
|
+
|
201
|
+
return self
|
202
|
+
|
203
|
+
|
204
|
+
def remove_constraints(self, *names: str) -> Self:
|
205
|
+
for c in self.constraints:
|
206
|
+
if c.name in names:
|
207
|
+
c.on_removal(self)
|
208
|
+
self.constraints = [c for c in self.constraints if c.name not in names]
|
209
|
+
self.__constraint_to_ignore = []
|
197
210
|
return self
|
198
211
|
|
199
212
|
def resolve_constraints(self) -> None:
|
200
213
|
if self.parent is None or not self.constraints:
|
201
214
|
self.dirty_constraints = False
|
202
215
|
return
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
216
|
+
|
217
|
+
if not self.__constraint_iteration:
|
218
|
+
self.__constraints_capture = None
|
219
|
+
else:
|
220
|
+
capture = tuple([c.priority for c in self.constraints])
|
221
|
+
if capture != self.__constraints_capture:
|
222
|
+
self.__constraints_capture = capture
|
223
|
+
self.__constraint_to_ignore = []
|
224
|
+
|
225
|
+
constraints = self.constraints.copy()
|
226
|
+
# If all are resolved early exit
|
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
|
230
|
+
|
231
|
+
# # Here there might be a conflict between 2 or more constraints
|
232
|
+
# we have to determine which ones causes conflict and ignore the one with least priority
|
233
|
+
|
234
|
+
stop = False
|
235
|
+
|
236
|
+
while True:
|
237
|
+
stop = True
|
238
|
+
# first pass with 2 iterations to sort out the transformative constraints
|
239
|
+
for _ in range(2):
|
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:
|
213
255
|
break
|
214
|
-
elif self.__constraint_iteration > MAX_CONSTRAINTS:
|
215
|
-
print(
|
216
|
-
self,
|
217
|
-
"CONSTRAINTS ERROR",
|
218
|
-
list(
|
219
|
-
c.name
|
220
|
-
for c in self.constraints
|
221
|
-
if not c.evaluate(self.parent, self)
|
222
|
-
),
|
223
|
-
)
|
224
|
-
self.dirty_constraints = False
|
225
|
-
return
|
226
|
-
# print("DONE")
|
227
|
-
self.dirty_constraints = False
|
228
256
|
|
229
|
-
|
230
|
-
|
231
|
-
|
257
|
+
if self.__constraints_to_ignore:
|
258
|
+
print("Constraints ignored : ",[str(c) for c in self.__constraints_to_ignore])
|
259
|
+
|
260
|
+
|
261
|
+
self.dirty_constraints = False
|
232
262
|
|
233
263
|
def has_constraint(self, name: str) -> bool:
|
234
264
|
return any(c.name == name for c in self.constraints)
|
@@ -236,7 +266,9 @@ class Widget(bf.Entity, metaclass=WidgetMeta):
|
|
236
266
|
def get_root(self) -> "Root":
|
237
267
|
if self.is_root:
|
238
268
|
return self
|
239
|
-
|
269
|
+
if self.parent:
|
270
|
+
return self.parent.get_root()
|
271
|
+
return None
|
240
272
|
|
241
273
|
def top_at(self, x: float | int, y: float | int) -> "None|Widget":
|
242
274
|
if self.children:
|
@@ -251,6 +283,7 @@ class Widget(bf.Entity, metaclass=WidgetMeta):
|
|
251
283
|
self.children.extend(children)
|
252
284
|
i = len(self.children)
|
253
285
|
for child in children:
|
286
|
+
|
254
287
|
child.set_render_order(i).set_parent(self).set_parent_scene(
|
255
288
|
self.parent_scene
|
256
289
|
)
|
@@ -262,8 +295,8 @@ class Widget(bf.Entity, metaclass=WidgetMeta):
|
|
262
295
|
def remove(self, *children: "Widget") -> Self:
|
263
296
|
for child in self.children:
|
264
297
|
if child in children:
|
265
|
-
self.children.remove(child)
|
266
298
|
child.set_parent(None).set_parent_scene(None)
|
299
|
+
self.children.remove(child)
|
267
300
|
if self.parent:
|
268
301
|
self.parent.do_sort_children = True
|
269
302
|
|
@@ -271,9 +304,7 @@ class Widget(bf.Entity, metaclass=WidgetMeta):
|
|
271
304
|
size = list(size)
|
272
305
|
size[0] = size[0] if self.autoresize_w else None
|
273
306
|
size[1] = size[1] if self.autoresize_h else None
|
274
|
-
|
275
307
|
self.set_size(size)
|
276
|
-
|
277
308
|
return self
|
278
309
|
|
279
310
|
def set_size(self, size: tuple) -> Self:
|
@@ -305,10 +336,12 @@ class Widget(bf.Entity, metaclass=WidgetMeta):
|
|
305
336
|
def build(self) -> None:
|
306
337
|
new_size = tuple(map(int, self.rect.size))
|
307
338
|
if self.surface.get_size() != new_size:
|
339
|
+
old_alpha = self.surface.get_alpha()
|
308
340
|
new_size = [max(0, i) for i in new_size]
|
309
341
|
self.surface = pygame.Surface(new_size, self.surface_flags)
|
310
342
|
if self.convert_alpha:
|
311
343
|
self.surface = self.surface.convert_alpha()
|
344
|
+
self.surface.set_alpha(old_alpha)
|
312
345
|
|
313
346
|
def paint(self) -> None:
|
314
347
|
self.surface.fill((0, 0, 0, 0))
|
batFramework/manager.py
CHANGED
@@ -24,12 +24,24 @@ class Manager(bf.SceneManager):
|
|
24
24
|
pygame.display.set_icon(surf)
|
25
25
|
|
26
26
|
def print_status(self):
|
27
|
+
"""
|
28
|
+
Print detailed information about the current state of the scenes, shared variables,
|
29
|
+
and additional timers managed by the subclass.
|
30
|
+
"""
|
31
|
+
# Call the parent class's print_status method to include its information
|
27
32
|
super().print_status()
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
print("
|
33
|
+
|
34
|
+
# Add the timers information in a cohesive manner
|
35
|
+
print("\n" + "=" * 50)
|
36
|
+
print(" TIMERS".center(50))
|
37
|
+
print("=" * 50)
|
38
|
+
|
39
|
+
# Print the timers information
|
40
|
+
print(self._timeManager)
|
41
|
+
|
42
|
+
# End with a visual separator
|
43
|
+
print("=" * 50 + "\n")
|
44
|
+
|
33
45
|
|
34
46
|
def get_fps(self) -> float:
|
35
47
|
return self._clock.get_fps()
|
batFramework/object.py
CHANGED
@@ -8,7 +8,9 @@ if TYPE_CHECKING:
|
|
8
8
|
|
9
9
|
|
10
10
|
class Object:
|
11
|
-
|
11
|
+
__count = 0
|
12
|
+
__available_uid = set()
|
13
|
+
__used_uid = set()
|
12
14
|
|
13
15
|
def __init__(self) -> None:
|
14
16
|
self.rect = pygame.FRect(0, 0, 0, 0)
|
@@ -16,14 +18,17 @@ class Object:
|
|
16
18
|
self.parent_scene: bf.Scene | None = None
|
17
19
|
self.debug_color: tuple | str = "red"
|
18
20
|
self.render_order: int = 0
|
19
|
-
self.uid: int = Object.
|
20
|
-
Object.
|
21
|
+
self.uid: int = Object.__count
|
22
|
+
Object.__used_uid.add(self.uid)
|
21
23
|
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
24
|
+
if Object.__available_uid:
|
25
|
+
self.name = Object.__available_uid.pop()
|
26
|
+
else:
|
27
|
+
self.name = Object.__count
|
28
|
+
Object.__count += 1
|
29
|
+
|
30
|
+
def __del__(self):
|
31
|
+
Object.__available_uid.add(self.uid)
|
27
32
|
|
28
33
|
def set_position(self, x, y) -> Self:
|
29
34
|
self.rect.topleft = x, y
|
@@ -57,7 +62,11 @@ class Object:
|
|
57
62
|
pass
|
58
63
|
|
59
64
|
def set_uid(self, uid: int) -> Self:
|
65
|
+
if uid in Object.__used_uid:
|
66
|
+
print(f"set_uid error : UID '{uid}' is already in use")
|
67
|
+
return self
|
60
68
|
self.uid = uid
|
69
|
+
Object.__used_uid.add(uid)
|
61
70
|
return self
|
62
71
|
|
63
72
|
def add_tags(self, *tags) -> Self:
|
batFramework/particle.py
CHANGED
@@ -7,6 +7,10 @@ class Particle:
|
|
7
7
|
def __init__(self, *args, **kwargs):
|
8
8
|
self.dead = False
|
9
9
|
self.surface = None
|
10
|
+
self.generator = None
|
11
|
+
|
12
|
+
def do_when_added(self):
|
13
|
+
pass
|
10
14
|
|
11
15
|
def update(self, dt):
|
12
16
|
pass
|
@@ -21,7 +25,15 @@ class Particle:
|
|
21
25
|
class TimedParticle(Particle):
|
22
26
|
def __init__(self, duration):
|
23
27
|
super().__init__()
|
24
|
-
self.
|
28
|
+
self.duration = duration
|
29
|
+
|
30
|
+
def do_when_added(self):
|
31
|
+
if self.generator and self.generator.parent_scene:
|
32
|
+
self.timer = bf.SceneTimer(
|
33
|
+
self.duration, end_callback=self.kill,
|
34
|
+
scene_name=self.generator.parent_scene.name).start()
|
35
|
+
else:
|
36
|
+
self.timer = bf.Timer(self.duration, end_callback=self.kill).start()
|
25
37
|
|
26
38
|
|
27
39
|
class BasicParticle(TimedParticle):
|
@@ -36,8 +48,9 @@ class BasicParticle(TimedParticle):
|
|
36
48
|
**kwargs,
|
37
49
|
):
|
38
50
|
super().__init__(duration)
|
39
|
-
self.rect = pygame.FRect(
|
40
|
-
self.
|
51
|
+
self.rect = pygame.FRect(0,0, *size)
|
52
|
+
self.rect.center = start_pos
|
53
|
+
self.surface = pygame.Surface(size)
|
41
54
|
self.velocity = Vector2(start_vel)
|
42
55
|
if color:
|
43
56
|
self.surface.fill(color)
|
@@ -57,7 +70,6 @@ class BasicParticle(TimedParticle):
|
|
57
70
|
|
58
71
|
class DirectionalParticle(BasicParticle):
|
59
72
|
def start(self):
|
60
|
-
self.surface = self.surface.convert_alpha()
|
61
73
|
self.original_surface = self.surface.copy()
|
62
74
|
|
63
75
|
def update_surface(self):
|
@@ -72,6 +84,7 @@ class ParticleGenerator(bf.Entity):
|
|
72
84
|
self.particles: list[Particle] = []
|
73
85
|
|
74
86
|
def get_debug_outlines(self):
|
87
|
+
return
|
75
88
|
for particle in self.particles:
|
76
89
|
yield (
|
77
90
|
particle.rect.move(particle.rect.w // 2, particle.rect.h // 2),
|
@@ -79,7 +92,9 @@ class ParticleGenerator(bf.Entity):
|
|
79
92
|
)
|
80
93
|
yield (self.rect, "cyan")
|
81
94
|
|
82
|
-
def add_particle(self, particle):
|
95
|
+
def add_particle(self, particle:Particle):
|
96
|
+
particle.generator = self
|
97
|
+
particle.do_when_added()
|
83
98
|
self.particles.append(particle)
|
84
99
|
|
85
100
|
def clear(self):
|
@@ -94,8 +109,7 @@ class ParticleGenerator(bf.Entity):
|
|
94
109
|
for p in particles_to_remove:
|
95
110
|
self.particles.remove(p)
|
96
111
|
|
97
|
-
def draw(self, camera) ->
|
112
|
+
def draw(self, camera) -> None:
|
98
113
|
camera.surface.fblits(
|
99
|
-
[(p.surface, camera.world_to_screen(p.rect)
|
114
|
+
[(p.surface, camera.world_to_screen(p.rect)) for p in self.particles]
|
100
115
|
)
|
101
|
-
return len(self.particles)
|
batFramework/resourceManager.py
CHANGED
@@ -3,6 +3,7 @@ import os
|
|
3
3
|
import pygame
|
4
4
|
import sys
|
5
5
|
import json
|
6
|
+
from typing import Any
|
6
7
|
from .utils import Singleton
|
7
8
|
|
8
9
|
if getattr(sys, "frozen", False):
|
@@ -16,6 +17,7 @@ else:
|
|
16
17
|
|
17
18
|
class ResourceManager(metaclass=Singleton):
|
18
19
|
def __init__(self):
|
20
|
+
self.shared_variables: dict[str,Any] = {}
|
19
21
|
self.convert_image_cache = {}
|
20
22
|
self.convert_alpha_image_cache = {}
|
21
23
|
self.sound_cache = {}
|
@@ -33,11 +35,11 @@ class ResourceManager(metaclass=Singleton):
|
|
33
35
|
# print(f"Loaded image : '{file_path}'")
|
34
36
|
|
35
37
|
elif file.lower().endswith((".mp3", ".wav")):
|
36
|
-
bf.AudioManager().load_sound(file.
|
38
|
+
bf.AudioManager().load_sound(file.split(".")[0], file_path)
|
37
39
|
# print(f"Loaded sound : '{file_path}'")
|
38
40
|
|
39
41
|
elif file.lower().endswith((".ttf", ".otf")):
|
40
|
-
bf.FontManager().load_font(file_path, file.
|
42
|
+
bf.FontManager().load_font(file_path, file.split(".")[0])
|
41
43
|
# print(f"Loaded font : '{file_path}'")
|
42
44
|
|
43
45
|
print(f"Loaded resources in directory : '{path}'")
|
@@ -82,3 +84,17 @@ class ResourceManager(metaclass=Singleton):
|
|
82
84
|
return True
|
83
85
|
except FileNotFoundError:
|
84
86
|
return False
|
87
|
+
|
88
|
+
|
89
|
+
def set_sharedVar(self, name, value) -> bool:
|
90
|
+
"""
|
91
|
+
Set a shared variable of any type. This will be accessible (read/write) from any scene
|
92
|
+
"""
|
93
|
+
self.shared_variables[name] = value
|
94
|
+
return True
|
95
|
+
|
96
|
+
def get_sharedVar(self, name, error_value=None):
|
97
|
+
"""
|
98
|
+
Get a shared variable
|
99
|
+
"""
|
100
|
+
return self.shared_variables.get(name, error_value)
|
batFramework/scene.py
CHANGED
@@ -1,9 +1,9 @@
|
|
1
1
|
from __future__ import annotations
|
2
2
|
import re
|
3
|
-
from typing import TYPE_CHECKING, Any
|
4
3
|
from collections import OrderedDict
|
5
4
|
import itertools
|
6
5
|
|
6
|
+
from typing import TYPE_CHECKING, Any
|
7
7
|
if TYPE_CHECKING:
|
8
8
|
from .manager import Manager
|
9
9
|
from .sceneManager import SceneManager
|
@@ -27,6 +27,7 @@ class Scene:
|
|
27
27
|
"""
|
28
28
|
self.scene_index = 0
|
29
29
|
self.name = name
|
30
|
+
bf.TimeManager().add_register(self.name,False)
|
30
31
|
self.manager: Manager | None = None
|
31
32
|
self.active = False
|
32
33
|
self.visible = False
|
@@ -36,10 +37,16 @@ class Scene:
|
|
36
37
|
self.early_actions: bf.ActionContainer = bf.ActionContainer()
|
37
38
|
self.camera: bf.Camera = bf.Camera(convert_alpha=world_convert_alpha)
|
38
39
|
self.hud_camera: bf.Camera = bf.Camera(convert_alpha=hud_convert_alpha)
|
39
|
-
|
40
|
+
self.should_sort :bool = True
|
40
41
|
self.root: bf.Root = bf.Root(self.hud_camera)
|
41
42
|
self.root.rect.center = self.hud_camera.get_center()
|
42
43
|
self.add_hud_entity(self.root)
|
44
|
+
self.entities_to_remove = []
|
45
|
+
self.entities_to_add = []
|
46
|
+
|
47
|
+
|
48
|
+
def __str__(self)->str:
|
49
|
+
return f"Scene({self.name})"
|
43
50
|
|
44
51
|
def get_world_entity_count(self) -> int:
|
45
52
|
return len(self.world_entities)
|
@@ -130,31 +137,33 @@ class Scene:
|
|
130
137
|
|
131
138
|
def add_world_entity(self, *entities: bf.Entity):
|
132
139
|
"""Add world entities to the scene."""
|
140
|
+
change = False
|
133
141
|
for e in entities:
|
134
|
-
if e not in self.world_entities:
|
135
|
-
|
136
|
-
e
|
137
|
-
|
138
|
-
|
139
|
-
|
142
|
+
if e not in self.world_entities and e not in self.entities_to_add:
|
143
|
+
change = True
|
144
|
+
# self.world_entities[e] = None
|
145
|
+
self.entities_to_add.append(e)
|
146
|
+
e.set_parent_scene(self)
|
147
|
+
# self.sort_entities()
|
148
|
+
return change
|
149
|
+
|
150
|
+
# Updated remove_world_entity method to add entities to the removal list
|
140
151
|
def remove_world_entity(self, *entities: bf.Entity):
|
141
|
-
"""
|
142
|
-
|
152
|
+
"""Mark world entities for removal from the scene."""
|
153
|
+
change = False
|
143
154
|
for e in entities:
|
144
155
|
if e in self.world_entities:
|
145
|
-
|
146
|
-
e
|
147
|
-
|
148
|
-
|
149
|
-
return removed
|
156
|
+
change = True
|
157
|
+
self.entities_to_remove.append(e)
|
158
|
+
e.set_parent_scene(None)
|
159
|
+
return change
|
150
160
|
|
151
161
|
def add_hud_entity(self, *entities: bf.Entity):
|
152
162
|
"""Add HUD entities to the scene."""
|
153
163
|
for e in entities:
|
154
164
|
if e not in self.hud_entities:
|
155
165
|
self.hud_entities[e] = None
|
156
|
-
e.
|
157
|
-
e.do_when_added()
|
166
|
+
e.set_parent_scene(self)
|
158
167
|
self.sort_entities()
|
159
168
|
return True
|
160
169
|
|
@@ -162,9 +171,8 @@ class Scene:
|
|
162
171
|
"""Remove HUD entities from the scene."""
|
163
172
|
for e in entities:
|
164
173
|
if e in self.hud_entities:
|
165
|
-
e.
|
166
|
-
e
|
167
|
-
del self.hud_entities[e]
|
174
|
+
e.set_parent_scene(None)
|
175
|
+
self.hud_entities.pop(e)
|
168
176
|
|
169
177
|
def add_actions(self, *action):
|
170
178
|
"""Add actions to the scene."""
|
@@ -255,16 +263,32 @@ class Scene:
|
|
255
263
|
|
256
264
|
def update(self, dt):
|
257
265
|
"""Update the scene. Do NOT override"""
|
266
|
+
if self.should_sort:
|
267
|
+
self._sort_entities_internal()
|
268
|
+
|
258
269
|
for entity in itertools.chain(
|
259
270
|
self.hud_entities.keys(), self.world_entities.keys()
|
260
271
|
):
|
261
272
|
entity.update(dt)
|
273
|
+
|
262
274
|
self.do_update(dt)
|
263
275
|
self.camera.update(dt)
|
264
276
|
self.hud_camera.update(dt)
|
265
277
|
self.actions.reset()
|
266
278
|
self.early_actions.reset()
|
267
279
|
|
280
|
+
|
281
|
+
if self.entities_to_add:
|
282
|
+
for e in self.entities_to_add:
|
283
|
+
self.world_entities[e] = None
|
284
|
+
self.entities_to_add.clear()
|
285
|
+
|
286
|
+
# Remove marked entities after updating
|
287
|
+
if self.entities_to_remove:
|
288
|
+
for e in self.entities_to_remove:
|
289
|
+
self.world_entities.pop(e, None)
|
290
|
+
self.entities_to_remove.clear()
|
291
|
+
|
268
292
|
def do_update(self, dt):
|
269
293
|
"""Specific update within the scene."""
|
270
294
|
pass
|
@@ -284,6 +308,9 @@ class Scene:
|
|
284
308
|
[draw_rect(data) for data in entity.get_debug_outlines()]
|
285
309
|
|
286
310
|
def sort_entities(self) -> None:
|
311
|
+
self.should_sort = True
|
312
|
+
|
313
|
+
def _sort_entities_internal(self):
|
287
314
|
"""Sort entities within the scene based on their rendering order."""
|
288
315
|
self.world_entities = OrderedDict(
|
289
316
|
sorted(self.world_entities.items(), key=lambda e: e[0].render_order)
|
@@ -291,6 +318,7 @@ class Scene:
|
|
291
318
|
self.hud_entities = OrderedDict(
|
292
319
|
sorted(self.hud_entities.items(), key=lambda e: e[0].render_order)
|
293
320
|
)
|
321
|
+
self.should_sort = False
|
294
322
|
|
295
323
|
def draw(self, surface: pygame.Surface):
|
296
324
|
self.camera.clear()
|
@@ -329,6 +357,7 @@ class Scene:
|
|
329
357
|
self.root.clear_hovered()
|
330
358
|
# self.root.clear_focused()
|
331
359
|
self.root.build()
|
360
|
+
bf.TimeManager().activate_register(self.name)
|
332
361
|
self.do_on_enter()
|
333
362
|
# self.root.visit(lambda e : e.resolve_constraints())
|
334
363
|
|
@@ -339,6 +368,7 @@ class Scene:
|
|
339
368
|
self.set_visible(False)
|
340
369
|
self.actions.hard_reset()
|
341
370
|
self.early_actions.hard_reset()
|
371
|
+
bf.TimeManager().deactivate_register(self.name)
|
342
372
|
self.do_on_exit()
|
343
373
|
|
344
374
|
def do_on_enter(self) -> None:
|
batFramework/sceneManager.py
CHANGED
@@ -10,16 +10,15 @@ def swap(lst, index1, index2):
|
|
10
10
|
class SceneManager:
|
11
11
|
def __init__(self) -> None:
|
12
12
|
self.scenes: list[bf.Scene] = []
|
13
|
-
self.shared_variables: dict = {}
|
14
13
|
self.shared_events = {pygame.WINDOWRESIZED}
|
15
14
|
|
16
15
|
self.set_sharedVar("in_cutscene", False)
|
17
16
|
self.set_sharedVar("player_has_control", True)
|
18
|
-
|
17
|
+
self.old_player_control = True
|
19
18
|
self.debug_mode: bf.enums.debugMode = bf.debugMode.HIDDEN
|
20
19
|
self.current_transitions: dict[str, bf.transition.Transition] = {}
|
21
20
|
|
22
|
-
def init_scenes(self, *initial_scenes):
|
21
|
+
def init_scenes(self, *initial_scenes:bf.Scene):
|
23
22
|
for index, s in enumerate(initial_scenes):
|
24
23
|
s.set_scene_index(index)
|
25
24
|
for s in reversed(initial_scenes):
|
@@ -36,33 +35,55 @@ class SceneManager:
|
|
36
35
|
|
37
36
|
def print_status(self):
|
38
37
|
"""
|
39
|
-
Print
|
40
|
-
"""
|
41
|
-
print("-" * 40)
|
42
|
-
print(
|
43
|
-
"\n".join(
|
44
|
-
f" {s.name:<30}\t{'Active' if s.active else 'Inactive'}\t{'Visible' if s.visible else 'Invisible'}\tindex= {s.scene_index}"
|
45
|
-
for s in self.scenes
|
46
|
-
)
|
47
|
-
)
|
48
|
-
print(f"[Debugging] = {self.debug_mode}")
|
49
|
-
print("---SHARED VARIABLES---")
|
50
|
-
for name, value in self.shared_variables.items():
|
51
|
-
print(f"[{str(name)} = {str(value)}]")
|
52
|
-
print("-" * 40)
|
53
|
-
|
54
|
-
def set_sharedVar(self, name, value) -> bool:
|
55
|
-
"""
|
56
|
-
Set a shared variable of any type. This will be accessible (read/write) from any scene
|
38
|
+
Print detailed information about the current state of the scenes and shared variables.
|
57
39
|
"""
|
58
|
-
|
59
|
-
|
40
|
+
|
41
|
+
def format_scene_info(scene):
|
42
|
+
status = 'Active' if scene.active else 'Inactive'
|
43
|
+
visibility = 'Visible' if scene.visible else 'Invisible'
|
44
|
+
return f"{scene.name:<30} | {status:<8} | {visibility:<10} | Index={scene.scene_index}"
|
45
|
+
|
46
|
+
def format_shared_variable(name, value):
|
47
|
+
return f"[{name}] = {value}"
|
48
|
+
|
49
|
+
print("\n" + "=" * 50)
|
50
|
+
print(" SCENE STATUS".center(50))
|
51
|
+
print("=" * 50)
|
52
|
+
|
53
|
+
# Print scene information
|
54
|
+
if self.scenes:
|
55
|
+
header = f"{'Scene Name':<30} | {'Status':<8} | {'Visibility':<10} | {'Index':<7}"
|
56
|
+
print(header)
|
57
|
+
print("-" * 50)
|
58
|
+
print("\n".join(format_scene_info(s) for s in self.scenes))
|
59
|
+
else:
|
60
|
+
print("No scenes available.")
|
61
|
+
|
62
|
+
# Print debugging mode status
|
63
|
+
print("\n" + "=" * 50)
|
64
|
+
print(" DEBUGGING STATUS".center(50))
|
65
|
+
print("=" * 50)
|
66
|
+
print(f"[Debugging Mode] = {self.debug_mode}")
|
67
|
+
|
68
|
+
# Print shared variables
|
69
|
+
print("\n" + "=" * 50)
|
70
|
+
print(" SHARED VARIABLES".center(50))
|
71
|
+
print("=" * 50)
|
72
|
+
|
73
|
+
if bf.ResourceManager().shared_variables:
|
74
|
+
for name, value in bf.ResourceManager().shared_variables.items():
|
75
|
+
print(format_shared_variable(name, value))
|
76
|
+
else:
|
77
|
+
print("No shared variables available.")
|
78
|
+
|
79
|
+
print("=" * 50 + "\n")
|
80
|
+
|
81
|
+
|
82
|
+
def set_sharedVar(self, name, value) -> None:
|
83
|
+
bf.ResourceManager().set_sharedVar(name,value)
|
60
84
|
|
61
85
|
def get_sharedVar(self, name, error_value=None):
|
62
|
-
|
63
|
-
Get a shared variable
|
64
|
-
"""
|
65
|
-
return self.shared_variables.get(name, error_value)
|
86
|
+
return bf.ResourceManager().get_sharedVar(name, error_value)
|
66
87
|
|
67
88
|
def get_current_scene_name(self) -> str:
|
68
89
|
"""get the name of the current scene"""
|
@@ -129,11 +150,11 @@ class SceneManager:
|
|
129
150
|
def _start_transition(self, target_scene: bf.Scene):
|
130
151
|
target_scene.set_active(True)
|
131
152
|
target_scene.set_visible(True)
|
153
|
+
self.old_player_control = bool(self.get_sharedVar("player_has_control"))
|
132
154
|
self.set_sharedVar("player_has_control", False)
|
133
155
|
|
134
156
|
def _end_transition(self, scene_name, index):
|
135
157
|
self.set_scene(scene_name, index, True)
|
136
|
-
self.set_sharedVar("player_has_control", True)
|
137
158
|
self.current_transitions.clear()
|
138
159
|
|
139
160
|
def set_scene(self, scene_name, index=0, ignore_early: bool = False):
|
@@ -156,6 +177,9 @@ class SceneManager:
|
|
156
177
|
self.scenes[index].do_on_enter_early()
|
157
178
|
target_scene.on_enter()
|
158
179
|
|
180
|
+
self.set_sharedVar("player_has_control", self.old_player_control)
|
181
|
+
|
182
|
+
|
159
183
|
def cycle_debug_mode(self):
|
160
184
|
current_index = self.debug_mode.value
|
161
185
|
next_index = (current_index + 1) % len(bf.debugMode)
|