batframework 1.0.9a11__py3-none-any.whl → 1.0.9a13__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 +3 -11
- batFramework/action.py +280 -279
- batFramework/actionContainer.py +105 -82
- batFramework/animatedSprite.py +80 -58
- batFramework/animation.py +91 -77
- batFramework/audioManager.py +156 -131
- batFramework/baseScene.py +249 -240
- batFramework/camera.py +245 -317
- batFramework/constants.py +57 -51
- batFramework/cutscene.py +239 -253
- batFramework/cutsceneManager.py +34 -34
- batFramework/drawable.py +107 -77
- batFramework/dynamicEntity.py +30 -30
- batFramework/easingController.py +58 -58
- batFramework/entity.py +130 -130
- batFramework/enums.py +171 -135
- batFramework/fontManager.py +65 -65
- batFramework/gui/__init__.py +28 -25
- batFramework/gui/animatedLabel.py +90 -89
- batFramework/gui/button.py +17 -17
- batFramework/gui/clickableWidget.py +244 -244
- batFramework/gui/collapseContainer.py +98 -0
- batFramework/gui/constraints/__init__.py +1 -1
- batFramework/gui/constraints/constraints.py +1066 -980
- batFramework/gui/container.py +220 -206
- batFramework/gui/debugger.py +140 -130
- batFramework/gui/draggableWidget.py +63 -44
- batFramework/gui/image.py +61 -58
- batFramework/gui/indicator.py +116 -113
- batFramework/gui/interactiveWidget.py +243 -239
- batFramework/gui/label.py +147 -344
- batFramework/gui/layout.py +442 -429
- batFramework/gui/meter.py +155 -96
- batFramework/gui/radioButton.py +43 -35
- batFramework/gui/root.py +228 -228
- batFramework/gui/scrollingContainer.py +282 -0
- batFramework/gui/selector.py +232 -250
- batFramework/gui/shape.py +286 -276
- batFramework/gui/slider.py +353 -397
- batFramework/gui/style.py +10 -10
- batFramework/gui/styleManager.py +49 -54
- batFramework/gui/syncedVar.py +43 -49
- batFramework/gui/textInput.py +331 -306
- batFramework/gui/textWidget.py +308 -0
- batFramework/gui/toggle.py +140 -128
- batFramework/gui/tooltip.py +35 -30
- batFramework/gui/widget.py +546 -521
- batFramework/manager.py +131 -134
- batFramework/particle.py +118 -118
- batFramework/propertyEaser.py +79 -79
- batFramework/renderGroup.py +34 -34
- batFramework/resourceManager.py +130 -130
- batFramework/scene.py +31 -31
- batFramework/sceneLayer.py +134 -138
- batFramework/sceneManager.py +200 -197
- batFramework/scrollingSprite.py +115 -115
- batFramework/sprite.py +46 -51
- batFramework/stateMachine.py +49 -54
- batFramework/templates/__init__.py +2 -1
- batFramework/templates/character.py +15 -0
- batFramework/templates/controller.py +158 -97
- batFramework/templates/stateMachine.py +39 -0
- batFramework/tileset.py +46 -46
- batFramework/timeManager.py +213 -213
- batFramework/transition.py +162 -162
- batFramework/triggerZone.py +22 -22
- batFramework/utils.py +306 -306
- {batframework-1.0.9a11.dist-info → batframework-1.0.9a13.dist-info}/LICENSE +20 -20
- {batframework-1.0.9a11.dist-info → batframework-1.0.9a13.dist-info}/METADATA +24 -17
- batframework-1.0.9a13.dist-info/RECORD +72 -0
- batframework-1.0.9a11.dist-info/RECORD +0 -67
- {batframework-1.0.9a11.dist-info → batframework-1.0.9a13.dist-info}/WHEEL +0 -0
- {batframework-1.0.9a11.dist-info → batframework-1.0.9a13.dist-info}/top_level.txt +0 -0
batFramework/manager.py
CHANGED
@@ -1,134 +1,131 @@
|
|
1
|
-
import batFramework as bf
|
2
|
-
import
|
3
|
-
import
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
self.
|
11
|
-
self.
|
12
|
-
self.
|
13
|
-
self.
|
14
|
-
self.
|
15
|
-
self.
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
print("
|
41
|
-
print("
|
42
|
-
|
43
|
-
# Print the timers information
|
44
|
-
print(self.timeManager)
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
keys[pygame.
|
68
|
-
and
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
self.
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
self.
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
dt =
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
if
|
118
|
-
raise Exception("
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
dt = self.clock.tick(bf.const.FPS) / 1000
|
133
|
-
dt = min(dt, 0.02) # dirty fix for dt being too high when window not focused for a long time
|
134
|
-
pygame.quit()
|
1
|
+
import batFramework as bf
|
2
|
+
from batFramework import const
|
3
|
+
import pygame
|
4
|
+
import asyncio
|
5
|
+
|
6
|
+
|
7
|
+
class Manager(bf.SceneManager):
|
8
|
+
def __init__(self, *initial_scenes) -> None:
|
9
|
+
super().__init__()
|
10
|
+
self.debug_mode: bf.enums.debugMode = bf.debugMode.HIDDEN
|
11
|
+
self.screen: pygame.Surface | None = bf.const.SCREEN
|
12
|
+
self.timeManager = bf.TimeManager()
|
13
|
+
self.cutsceneManager = bf.CutsceneManager()
|
14
|
+
self.cutsceneManager.set_manager(self)
|
15
|
+
self.clock: pygame.Clock = pygame.Clock()
|
16
|
+
self.is_async_running : bool = False
|
17
|
+
self.running = False
|
18
|
+
pygame.mouse.set_cursor(bf.const.DEFAULT_CURSOR)
|
19
|
+
bf.ResourceManager().set_sharedVar("clock", self.clock)
|
20
|
+
bf.ResourceManager().set_sharedVar("debug_mode", self.debug_mode)
|
21
|
+
|
22
|
+
self.do_pre_init()
|
23
|
+
if initial_scenes:
|
24
|
+
self.init_scenes(*initial_scenes)
|
25
|
+
self.do_init()
|
26
|
+
|
27
|
+
@staticmethod
|
28
|
+
def set_icon(path: str) -> None:
|
29
|
+
surf = pygame.image.load(bf.ResourceManager().get_path(path)).convert_alpha()
|
30
|
+
pygame.display.set_icon(surf)
|
31
|
+
|
32
|
+
def print_status(self):
|
33
|
+
"""
|
34
|
+
Print detailed information about the current state of the scenes, shared variables,
|
35
|
+
and additional timers managed by the subclass.
|
36
|
+
"""
|
37
|
+
# Call the parent class's print_status method to include its information
|
38
|
+
super().print_status()
|
39
|
+
# Add the timers information in a cohesive manner
|
40
|
+
print("\n" + "=" * 50)
|
41
|
+
print(" TIMERS".center(50))
|
42
|
+
print("=" * 50)
|
43
|
+
# Print the timers information
|
44
|
+
print(self.timeManager)
|
45
|
+
# End with a visual separator
|
46
|
+
print("=" * 50 + "\n")
|
47
|
+
|
48
|
+
|
49
|
+
def get_fps(self) -> float:
|
50
|
+
return self.clock.get_fps()
|
51
|
+
|
52
|
+
def do_init(self) -> None:
|
53
|
+
pass
|
54
|
+
|
55
|
+
def do_pre_init(self) -> None:
|
56
|
+
pass
|
57
|
+
|
58
|
+
def stop(self) -> None:
|
59
|
+
self.running = False
|
60
|
+
|
61
|
+
def process_event(self, event: pygame.Event):
|
62
|
+
event.consumed = False
|
63
|
+
keys = pygame.key.get_pressed()
|
64
|
+
if (
|
65
|
+
bf.const.ALLOW_DEBUG and
|
66
|
+
keys[pygame.K_LCTRL]
|
67
|
+
and keys[pygame.K_LSHIFT]
|
68
|
+
and event.type == pygame.KEYDOWN
|
69
|
+
):
|
70
|
+
if event.key == pygame.K_d:
|
71
|
+
self.cycle_debug_mode()
|
72
|
+
return
|
73
|
+
if event.key == pygame.K_p:
|
74
|
+
self.print_status()
|
75
|
+
return
|
76
|
+
self.cutsceneManager.process_event(event)
|
77
|
+
if event.type == pygame.VIDEORESIZE and not (bf.const.FLAGS & pygame.SCALED):
|
78
|
+
bf.const.set_resolution((event.w, event.h))
|
79
|
+
|
80
|
+
if event.consumed: return
|
81
|
+
|
82
|
+
super().process_event(event)
|
83
|
+
if not event.consumed:
|
84
|
+
if event.type == pygame.QUIT:
|
85
|
+
self.running = False
|
86
|
+
|
87
|
+
def update(self, dt: float) -> None:
|
88
|
+
self.timeManager.update(dt)
|
89
|
+
self.cutsceneManager.update(dt)
|
90
|
+
super().update(dt)
|
91
|
+
|
92
|
+
|
93
|
+
async def run_async(self):
|
94
|
+
if len(self.scenes) == 0:
|
95
|
+
raise Exception("Manager can't start without scenes")
|
96
|
+
if self.running:
|
97
|
+
raise Exception("Error : Already running")
|
98
|
+
self.is_async_running = True
|
99
|
+
self.running = True
|
100
|
+
dt: float = 0
|
101
|
+
while self.running:
|
102
|
+
for event in pygame.event.get():
|
103
|
+
self.process_event(event)
|
104
|
+
# update
|
105
|
+
self.update(dt)
|
106
|
+
# render
|
107
|
+
self.draw(self.screen)
|
108
|
+
pygame.display.flip()
|
109
|
+
dt = self.clock.tick(bf.const.FPS) / 1000
|
110
|
+
dt = min(dt, 0.02) # dirty fix for dt being too high when window not focused for a long time
|
111
|
+
await asyncio.sleep(0)
|
112
|
+
pygame.quit()
|
113
|
+
|
114
|
+
def run(self) -> None:
|
115
|
+
if len(self.scenes) == 0:
|
116
|
+
raise Exception("Manager can't start without scenes")
|
117
|
+
if self.running:
|
118
|
+
raise Exception("Error : Already running")
|
119
|
+
self.running = True
|
120
|
+
dt: float = 0
|
121
|
+
while self.running:
|
122
|
+
for event in pygame.event.get():
|
123
|
+
self.process_event(event)
|
124
|
+
# update
|
125
|
+
self.update(dt)
|
126
|
+
# render
|
127
|
+
self.draw(self.screen)
|
128
|
+
pygame.display.flip()
|
129
|
+
dt = self.clock.tick(bf.const.FPS) / 1000
|
130
|
+
dt = min(dt, 0.02) # fix for dt being too high when window not focused for a long time
|
131
|
+
pygame.quit()
|
batFramework/particle.py
CHANGED
@@ -1,118 +1,118 @@
|
|
1
|
-
import batFramework as bf
|
2
|
-
import pygame
|
3
|
-
from pygame.math import Vector2
|
4
|
-
|
5
|
-
|
6
|
-
class Particle:
|
7
|
-
def __init__(self, *args, **kwargs):
|
8
|
-
self.dead = False
|
9
|
-
self.surface = None
|
10
|
-
self.generator = None
|
11
|
-
|
12
|
-
def do_when_added(self):
|
13
|
-
pass
|
14
|
-
|
15
|
-
def update(self, dt):
|
16
|
-
pass
|
17
|
-
|
18
|
-
def kill(self):
|
19
|
-
self.dead = True
|
20
|
-
|
21
|
-
def update_surface(self):
|
22
|
-
pass
|
23
|
-
|
24
|
-
|
25
|
-
class TimedParticle(Particle):
|
26
|
-
def __init__(self, duration):
|
27
|
-
super().__init__()
|
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()
|
37
|
-
|
38
|
-
|
39
|
-
class BasicParticle(TimedParticle):
|
40
|
-
def __init__(
|
41
|
-
self,
|
42
|
-
start_pos: tuple[float, float],
|
43
|
-
start_vel: tuple[float, float],
|
44
|
-
duration=1,
|
45
|
-
color=None,
|
46
|
-
size: tuple[int, int] = (4, 4),
|
47
|
-
*args,
|
48
|
-
**kwargs,
|
49
|
-
):
|
50
|
-
super().__init__(duration)
|
51
|
-
self.rect = pygame.FRect(0,0, *size)
|
52
|
-
self.rect.center = start_pos
|
53
|
-
self.surface = pygame.Surface(size)
|
54
|
-
self.velocity = Vector2(start_vel)
|
55
|
-
if color:
|
56
|
-
self.surface.fill(color)
|
57
|
-
self.start()
|
58
|
-
|
59
|
-
def start(self):
|
60
|
-
pass
|
61
|
-
|
62
|
-
def update(self, dt):
|
63
|
-
super().update(dt)
|
64
|
-
self.rect.center += self.velocity * dt
|
65
|
-
self.update_surface()
|
66
|
-
|
67
|
-
def update_surface(self):
|
68
|
-
self.surface.set_alpha(255 - int(self.timer.get_progression() * 255))
|
69
|
-
|
70
|
-
|
71
|
-
class DirectionalParticle(BasicParticle):
|
72
|
-
def start(self):
|
73
|
-
self.original_surface = self.surface.copy()
|
74
|
-
|
75
|
-
def update_surface(self):
|
76
|
-
angle = self.velocity.angle_to(Vector2(1, 0))
|
77
|
-
self.surface = pygame.transform.rotate(self.original_surface, angle)
|
78
|
-
super().update_surface()
|
79
|
-
|
80
|
-
|
81
|
-
class ParticleGenerator(bf.Drawable):
|
82
|
-
def __init__(self) -> None:
|
83
|
-
super().__init__((0, 0))
|
84
|
-
self.particles: list[Particle] = []
|
85
|
-
self.count = 0
|
86
|
-
|
87
|
-
def get_debug_outlines(self):
|
88
|
-
return
|
89
|
-
for particle in self.particles:
|
90
|
-
yield (
|
91
|
-
particle.rect.move(particle.rect.w // 2, particle.rect.h // 2),
|
92
|
-
"blue",
|
93
|
-
)
|
94
|
-
yield (self.rect, "cyan")
|
95
|
-
|
96
|
-
def add_particle(self, particle:Particle):
|
97
|
-
particle.generator = self
|
98
|
-
particle.do_when_added()
|
99
|
-
self.particles.append(particle)
|
100
|
-
self.count += 1
|
101
|
-
|
102
|
-
def clear(self):
|
103
|
-
self.particles = []
|
104
|
-
self.count = 0
|
105
|
-
def update(self, dt: float):
|
106
|
-
particles_to_remove = []
|
107
|
-
for particle in self.particles:
|
108
|
-
particle.update(dt)
|
109
|
-
if particle.dead:
|
110
|
-
particles_to_remove.append(particle)
|
111
|
-
for p in particles_to_remove:
|
112
|
-
self.particles.remove(p)
|
113
|
-
self.count -= 1
|
114
|
-
|
115
|
-
def draw(self, camera) -> None:
|
116
|
-
camera.surface.fblits(
|
117
|
-
[(p.surface, camera.world_to_screen(p.rect)) for p in self.particles]
|
118
|
-
)
|
1
|
+
import batFramework as bf
|
2
|
+
import pygame
|
3
|
+
from pygame.math import Vector2
|
4
|
+
|
5
|
+
|
6
|
+
class Particle:
|
7
|
+
def __init__(self, *args, **kwargs):
|
8
|
+
self.dead = False
|
9
|
+
self.surface = None
|
10
|
+
self.generator = None
|
11
|
+
|
12
|
+
def do_when_added(self):
|
13
|
+
pass
|
14
|
+
|
15
|
+
def update(self, dt):
|
16
|
+
pass
|
17
|
+
|
18
|
+
def kill(self):
|
19
|
+
self.dead = True
|
20
|
+
|
21
|
+
def update_surface(self):
|
22
|
+
pass
|
23
|
+
|
24
|
+
|
25
|
+
class TimedParticle(Particle):
|
26
|
+
def __init__(self, duration):
|
27
|
+
super().__init__()
|
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()
|
37
|
+
|
38
|
+
|
39
|
+
class BasicParticle(TimedParticle):
|
40
|
+
def __init__(
|
41
|
+
self,
|
42
|
+
start_pos: tuple[float, float],
|
43
|
+
start_vel: tuple[float, float],
|
44
|
+
duration=1,
|
45
|
+
color=None,
|
46
|
+
size: tuple[int, int] = (4, 4),
|
47
|
+
*args,
|
48
|
+
**kwargs,
|
49
|
+
):
|
50
|
+
super().__init__(duration)
|
51
|
+
self.rect = pygame.FRect(0,0, *size)
|
52
|
+
self.rect.center = start_pos
|
53
|
+
self.surface = pygame.Surface(size)
|
54
|
+
self.velocity = Vector2(start_vel)
|
55
|
+
if color:
|
56
|
+
self.surface.fill(color)
|
57
|
+
self.start()
|
58
|
+
|
59
|
+
def start(self):
|
60
|
+
pass
|
61
|
+
|
62
|
+
def update(self, dt):
|
63
|
+
super().update(dt)
|
64
|
+
self.rect.center += self.velocity * dt
|
65
|
+
self.update_surface()
|
66
|
+
|
67
|
+
def update_surface(self):
|
68
|
+
self.surface.set_alpha(255 - int(self.timer.get_progression() * 255))
|
69
|
+
|
70
|
+
|
71
|
+
class DirectionalParticle(BasicParticle):
|
72
|
+
def start(self):
|
73
|
+
self.original_surface = self.surface.copy()
|
74
|
+
|
75
|
+
def update_surface(self):
|
76
|
+
angle = self.velocity.angle_to(Vector2(1, 0))
|
77
|
+
self.surface = pygame.transform.rotate(self.original_surface, angle)
|
78
|
+
super().update_surface()
|
79
|
+
|
80
|
+
|
81
|
+
class ParticleGenerator(bf.Drawable):
|
82
|
+
def __init__(self) -> None:
|
83
|
+
super().__init__((0, 0))
|
84
|
+
self.particles: list[Particle] = []
|
85
|
+
self.count = 0
|
86
|
+
|
87
|
+
def get_debug_outlines(self):
|
88
|
+
return
|
89
|
+
for particle in self.particles:
|
90
|
+
yield (
|
91
|
+
particle.rect.move(particle.rect.w // 2, particle.rect.h // 2),
|
92
|
+
"blue",
|
93
|
+
)
|
94
|
+
yield (self.rect, "cyan")
|
95
|
+
|
96
|
+
def add_particle(self, particle:Particle):
|
97
|
+
particle.generator = self
|
98
|
+
particle.do_when_added()
|
99
|
+
self.particles.append(particle)
|
100
|
+
self.count += 1
|
101
|
+
|
102
|
+
def clear(self):
|
103
|
+
self.particles = []
|
104
|
+
self.count = 0
|
105
|
+
def update(self, dt: float):
|
106
|
+
particles_to_remove = []
|
107
|
+
for particle in self.particles:
|
108
|
+
particle.update(dt)
|
109
|
+
if particle.dead:
|
110
|
+
particles_to_remove.append(particle)
|
111
|
+
for p in particles_to_remove:
|
112
|
+
self.particles.remove(p)
|
113
|
+
self.count -= 1
|
114
|
+
|
115
|
+
def draw(self, camera) -> None:
|
116
|
+
camera.surface.fblits(
|
117
|
+
[(p.surface, camera.world_to_screen(p.rect)) for p in self.particles]
|
118
|
+
)
|
batFramework/propertyEaser.py
CHANGED
@@ -1,79 +1,79 @@
|
|
1
|
-
from .easingController import EasingController
|
2
|
-
import pygame
|
3
|
-
from typing import Callable, Any, Self
|
4
|
-
import batFramework as bf
|
5
|
-
|
6
|
-
class PropertyEaser(EasingController):
|
7
|
-
class EasedProperty:
|
8
|
-
def __init__(self, getter: Callable[[], Any], setter: Callable[[Any], None], end_value: Any, start_value: Any = None):
|
9
|
-
self.getter = getter
|
10
|
-
self.setter = setter
|
11
|
-
self.start_value = start_value if start_value is not None else getter()
|
12
|
-
self.end_value = end_value
|
13
|
-
|
14
|
-
def interpolate(self, t: float):
|
15
|
-
a, b = self.start_value, self.end_value
|
16
|
-
if isinstance(a, (int, float)):
|
17
|
-
return a + (b - a) * t
|
18
|
-
elif isinstance(a, pygame.Vector2):
|
19
|
-
return a.lerp(b, t)
|
20
|
-
elif isinstance(a, pygame.Color):
|
21
|
-
return pygame.Color(
|
22
|
-
round(a.r + (b.r - a.r) * t),
|
23
|
-
round(a.g + (b.g - a.g) * t),
|
24
|
-
round(a.b + (b.b - a.b) * t),
|
25
|
-
round(a.a + (b.a - a.a) * t),
|
26
|
-
)
|
27
|
-
else:
|
28
|
-
raise TypeError(f"Unsupported type for interpolation: {type(a)}")
|
29
|
-
|
30
|
-
def apply(self, t: float):
|
31
|
-
self.setter(self.interpolate(t))
|
32
|
-
|
33
|
-
def __init__(
|
34
|
-
self,
|
35
|
-
duration: float = 1,
|
36
|
-
easing: bf.easing = bf.easing.LINEAR,
|
37
|
-
loop: int = 0,
|
38
|
-
register: str = "global",
|
39
|
-
end_callback: Callable[[], Any] = None,
|
40
|
-
):
|
41
|
-
self.properties: list[PropertyEaser.EasedProperty] = []
|
42
|
-
|
43
|
-
def update_all(progress):
|
44
|
-
for prop in self.properties:
|
45
|
-
prop.apply(progress)
|
46
|
-
|
47
|
-
super().__init__(duration, easing, update_all, end_callback, loop, register)
|
48
|
-
|
49
|
-
def __str__(self):
|
50
|
-
return f"(PROP){super().__str__()}"
|
51
|
-
|
52
|
-
def add_attr(
|
53
|
-
self,
|
54
|
-
obj: Any,
|
55
|
-
attr: str,
|
56
|
-
end_value: Any,
|
57
|
-
start_value: Any = None,
|
58
|
-
)->Self:
|
59
|
-
self.properties.append(
|
60
|
-
PropertyEaser.EasedProperty(
|
61
|
-
getter=lambda o=obj, a=attr: getattr(o, a),
|
62
|
-
setter=lambda v, o=obj, a=attr: setattr(o, a, v),
|
63
|
-
end_value=end_value,
|
64
|
-
start_value=start_value,
|
65
|
-
)
|
66
|
-
)
|
67
|
-
return self
|
68
|
-
|
69
|
-
def add_custom(
|
70
|
-
self,
|
71
|
-
getter: Callable[[], Any],
|
72
|
-
setter: Callable[[Any], None],
|
73
|
-
end_value: Any,
|
74
|
-
start_value: Any = None,
|
75
|
-
)->Self:
|
76
|
-
self.properties.append(
|
77
|
-
PropertyEaser.EasedProperty(getter, setter, end_value, start_value)
|
78
|
-
)
|
79
|
-
return self
|
1
|
+
from .easingController import EasingController
|
2
|
+
import pygame
|
3
|
+
from typing import Callable, Any, Self
|
4
|
+
import batFramework as bf
|
5
|
+
|
6
|
+
class PropertyEaser(EasingController):
|
7
|
+
class EasedProperty:
|
8
|
+
def __init__(self, getter: Callable[[], Any], setter: Callable[[Any], None], end_value: Any, start_value: Any = None):
|
9
|
+
self.getter = getter
|
10
|
+
self.setter = setter
|
11
|
+
self.start_value = start_value if start_value is not None else getter()
|
12
|
+
self.end_value = end_value
|
13
|
+
|
14
|
+
def interpolate(self, t: float):
|
15
|
+
a, b = self.start_value, self.end_value
|
16
|
+
if isinstance(a, (int, float)):
|
17
|
+
return a + (b - a) * t
|
18
|
+
elif isinstance(a, pygame.Vector2):
|
19
|
+
return a.lerp(b, t)
|
20
|
+
elif isinstance(a, pygame.Color):
|
21
|
+
return pygame.Color(
|
22
|
+
round(a.r + (b.r - a.r) * t),
|
23
|
+
round(a.g + (b.g - a.g) * t),
|
24
|
+
round(a.b + (b.b - a.b) * t),
|
25
|
+
round(a.a + (b.a - a.a) * t),
|
26
|
+
)
|
27
|
+
else:
|
28
|
+
raise TypeError(f"Unsupported type for interpolation: {type(a)}")
|
29
|
+
|
30
|
+
def apply(self, t: float):
|
31
|
+
self.setter(self.interpolate(t))
|
32
|
+
|
33
|
+
def __init__(
|
34
|
+
self,
|
35
|
+
duration: float = 1,
|
36
|
+
easing: bf.easing = bf.easing.LINEAR,
|
37
|
+
loop: int = 0,
|
38
|
+
register: str = "global",
|
39
|
+
end_callback: Callable[[], Any] = None,
|
40
|
+
):
|
41
|
+
self.properties: list[PropertyEaser.EasedProperty] = []
|
42
|
+
|
43
|
+
def update_all(progress):
|
44
|
+
for prop in self.properties:
|
45
|
+
prop.apply(progress)
|
46
|
+
|
47
|
+
super().__init__(duration, easing, update_all, end_callback, loop, register)
|
48
|
+
|
49
|
+
def __str__(self):
|
50
|
+
return f"(PROP){super().__str__()}"
|
51
|
+
|
52
|
+
def add_attr(
|
53
|
+
self,
|
54
|
+
obj: Any,
|
55
|
+
attr: str,
|
56
|
+
end_value: Any,
|
57
|
+
start_value: Any = None,
|
58
|
+
)->Self:
|
59
|
+
self.properties.append(
|
60
|
+
PropertyEaser.EasedProperty(
|
61
|
+
getter=lambda o=obj, a=attr: getattr(o, a),
|
62
|
+
setter=lambda v, o=obj, a=attr: setattr(o, a, v),
|
63
|
+
end_value=end_value,
|
64
|
+
start_value=start_value,
|
65
|
+
)
|
66
|
+
)
|
67
|
+
return self
|
68
|
+
|
69
|
+
def add_custom(
|
70
|
+
self,
|
71
|
+
getter: Callable[[], Any],
|
72
|
+
setter: Callable[[Any], None],
|
73
|
+
end_value: Any,
|
74
|
+
start_value: Any = None,
|
75
|
+
)->Self:
|
76
|
+
self.properties.append(
|
77
|
+
PropertyEaser.EasedProperty(getter, setter, end_value, start_value)
|
78
|
+
)
|
79
|
+
return self
|