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/__init__.py
CHANGED
@@ -8,7 +8,7 @@ from .resourceManager import ResourceManager
|
|
8
8
|
from .fontManager import FontManager
|
9
9
|
from .utils import Utils as utils
|
10
10
|
from .tileset import Tileset
|
11
|
-
from .time import
|
11
|
+
from .time import *
|
12
12
|
from .easingController import EasingController
|
13
13
|
from .cutscene import Cutscene, CutsceneManager
|
14
14
|
from .cutsceneBlocks import *
|
@@ -24,12 +24,15 @@ from .dynamicEntity import DynamicEntity
|
|
24
24
|
from .sprite import Sprite
|
25
25
|
from .scrollingSprite import ScrollingSprite
|
26
26
|
from .particle import *
|
27
|
-
from .animatedSprite import AnimatedSprite,
|
27
|
+
from .animatedSprite import AnimatedSprite, Animation
|
28
|
+
from .character import Character
|
28
29
|
from .stateMachine import State, StateMachine
|
29
30
|
from .scene import Scene
|
30
31
|
from .gui import *
|
31
32
|
from .sceneManager import SceneManager
|
32
33
|
from .manager import Manager
|
34
|
+
from .templates import *
|
35
|
+
import importlib.metadata
|
33
36
|
|
34
37
|
|
35
38
|
def init_screen(resolution: tuple[int, int], flags: int = 0, vsync: int = 0):
|
@@ -44,6 +47,16 @@ def init_screen(resolution: tuple[int, int], flags: int = 0, vsync: int = 0):
|
|
44
47
|
)
|
45
48
|
|
46
49
|
|
50
|
+
|
51
|
+
def print_version():
|
52
|
+
package_name = "batFramework"
|
53
|
+
try:
|
54
|
+
version = importlib.metadata.version(package_name)
|
55
|
+
print(f"{package_name} version: {version}")
|
56
|
+
except importlib.metadata.PackageNotFoundError:
|
57
|
+
print(f"{package_name} is not installed")
|
58
|
+
|
59
|
+
|
47
60
|
def init(
|
48
61
|
resolution: tuple[int, int],
|
49
62
|
flags: int = 0,
|
@@ -54,6 +67,7 @@ def init(
|
|
54
67
|
window_title: str = "BatFramework Project",
|
55
68
|
fps_limit: int = 0,
|
56
69
|
):
|
70
|
+
print_version()
|
57
71
|
pygame.display.set_caption(window_title)
|
58
72
|
init_screen(resolution, flags, vsync)
|
59
73
|
|
batFramework/animatedSprite.py
CHANGED
@@ -1,8 +1,9 @@
|
|
1
1
|
import batFramework as bf
|
2
2
|
import pygame
|
3
|
+
from typing import List, Dict, Tuple, Union, Optional, Self
|
3
4
|
|
4
5
|
|
5
|
-
def search_index(target, lst):
|
6
|
+
def search_index(target: int, lst: List[int]) -> int:
|
6
7
|
cumulative_sum = 0
|
7
8
|
for index, value in enumerate(lst):
|
8
9
|
cumulative_sum += value
|
@@ -11,65 +12,68 @@ def search_index(target, lst):
|
|
11
12
|
return -1
|
12
13
|
|
13
14
|
|
14
|
-
class
|
15
|
+
class Animation:
|
15
16
|
def __init__(
|
16
17
|
self,
|
17
|
-
name: str
|
18
|
-
surface: pygame.Surface,
|
19
|
-
width,
|
20
|
-
height,
|
21
|
-
duration_list: list | int,
|
18
|
+
name: str
|
22
19
|
) -> None:
|
23
|
-
self.frames: list[pygame.Surface] = list(
|
24
|
-
bf.utils.split_surface(
|
25
|
-
surface, width, height, False, convert_alpha
|
26
|
-
).values()
|
27
|
-
)
|
28
|
-
self.frames_flipX: list[pygame.Surface] = list(
|
29
|
-
bf.utils.split_surface(surface, width, height, True, convert_alpha).values()
|
30
|
-
)
|
31
|
-
|
32
20
|
self.name = name
|
33
|
-
self.
|
34
|
-
self.
|
35
|
-
self.
|
21
|
+
self.frames: list[pygame.Surface] = []
|
22
|
+
self.frames_flipX : list[pygame.Surface] = []
|
23
|
+
self.duration_list = []
|
24
|
+
self.duration_list_length = 1
|
25
|
+
|
26
|
+
def from_surface(self,surface:pygame.Surface,size : Tuple[int,int])->Self:
|
27
|
+
self.frames : List[pygame.Surface] = list(bf.utils.split_surface(surface, size).values())
|
28
|
+
self.frames_flipX : List[pygame.Surface] = list(bf.utils.split_surface(surface, size,func=lambda s : pygame.transform.flip(s,True,False)).values())
|
29
|
+
return self
|
36
30
|
|
37
31
|
def __repr__(self):
|
38
|
-
return f"
|
32
|
+
return f"Animation({self.name})"
|
39
33
|
|
40
|
-
def counter_to_frame(self, counter: float
|
34
|
+
def counter_to_frame(self, counter: Union[float, int]) -> int:
|
35
|
+
if not self.frames :
|
36
|
+
raise ValueError("Animation has no frames")
|
41
37
|
return search_index(
|
42
38
|
int(counter % self.duration_list_length), self.duration_list
|
43
39
|
)
|
44
40
|
|
45
|
-
def get_frame(self, counter, flip):
|
41
|
+
def get_frame(self, counter: Union[float, int], flip: bool) -> pygame.Surface:
|
46
42
|
i = self.counter_to_frame(counter)
|
47
43
|
return self.frames_flipX[i] if flip else self.frames[i]
|
48
44
|
|
49
|
-
def set_duration_list(self, duration_list:
|
45
|
+
def set_duration_list(self, duration_list: Union[List[int], int]) -> Self:
|
50
46
|
if isinstance(duration_list, int):
|
51
47
|
duration_list = [duration_list] * len(self.frames)
|
52
48
|
if len(duration_list) != len(self.frames):
|
53
49
|
raise ValueError("duration_list should have values for all frames")
|
54
50
|
self.duration_list = duration_list
|
55
51
|
self.duration_list_length = sum(self.duration_list)
|
52
|
+
return self
|
56
53
|
|
57
|
-
|
58
|
-
|
59
|
-
def __init__(self, size=None) -> None:
|
54
|
+
class AnimatedSprite(bf.Entity):
|
55
|
+
def __init__(self, size: Optional[Tuple[int, int]] = None) -> None:
|
60
56
|
super().__init__(size, no_surface=True)
|
61
57
|
self.float_counter: float = 0
|
62
|
-
self.
|
63
|
-
self.current_state:
|
64
|
-
self.flipX = False
|
65
|
-
self._locked = False
|
66
|
-
self.
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
self
|
58
|
+
self.animations: Dict[str, Animation] = {}
|
59
|
+
self.current_state: Optional[Animation] = None
|
60
|
+
self.flipX: bool = False
|
61
|
+
self._locked: bool = False
|
62
|
+
self._paused: bool = False
|
63
|
+
self.animation_end_callback = None
|
64
|
+
self.transition_end_animation = None
|
65
|
+
|
66
|
+
def set_animation_end_callback(self,callback)->Self:
|
67
|
+
self.animation_end_callback = callback
|
68
|
+
return self
|
69
|
+
|
70
|
+
@property
|
71
|
+
def paused(self) -> bool:
|
72
|
+
return self._paused
|
73
|
+
|
74
|
+
@paused.setter
|
75
|
+
def paused(self, value: bool) -> None:
|
76
|
+
self._paused = value
|
73
77
|
|
74
78
|
def toggle_pause(self) -> None:
|
75
79
|
self.paused = not self.paused
|
@@ -80,16 +84,7 @@ class AnimatedSprite(bf.DynamicEntity):
|
|
80
84
|
def set_frame(self, frame_index: int) -> None:
|
81
85
|
if not self.current_state:
|
82
86
|
return
|
83
|
-
|
84
|
-
frame_index = max(0, min(total, frame_index))
|
85
|
-
new_counter = 0
|
86
|
-
i = 0
|
87
|
-
while frame_index < total:
|
88
|
-
if self.current_state.counter_to_frame(new_counter) >= frame_index:
|
89
|
-
break
|
90
|
-
new_counter += self.current_state.duration_list[i]
|
91
|
-
i += 1
|
92
|
-
self.set_counter(new_counter)
|
87
|
+
self.set_counter(sum(self.current_state.duration_list[:frame_index]))
|
93
88
|
|
94
89
|
def lock(self) -> None:
|
95
90
|
self._locked = True
|
@@ -97,71 +92,85 @@ class AnimatedSprite(bf.DynamicEntity):
|
|
97
92
|
def unlock(self) -> None:
|
98
93
|
self._locked = False
|
99
94
|
|
100
|
-
def set_flipX(self, value) -> None:
|
95
|
+
def set_flipX(self, value: bool) -> None:
|
101
96
|
self.flipX = value
|
102
97
|
|
103
|
-
def
|
104
|
-
if not
|
98
|
+
def remove_animation(self, name: str) -> bool:
|
99
|
+
if name not in self.animations:
|
105
100
|
return False
|
106
|
-
self.
|
101
|
+
self.animations.pop(name)
|
107
102
|
if self.current_state and self.current_state.name == name:
|
108
|
-
self.
|
109
|
-
list(self.
|
103
|
+
self.current_state = (
|
104
|
+
list(self.animations.values())[0] if self.animations else None
|
110
105
|
)
|
111
106
|
return True
|
112
107
|
|
113
|
-
def
|
108
|
+
def add_animation(
|
114
109
|
self,
|
115
|
-
|
116
|
-
surface: pygame.Surface,
|
117
|
-
size: tuple[int, int],
|
118
|
-
duration_list: list[int],
|
119
|
-
convert_alpha: bool = True,
|
110
|
+
animation:Animation
|
120
111
|
) -> bool:
|
121
|
-
if name in self.
|
112
|
+
if animation.name in self.animations:
|
122
113
|
return False
|
123
|
-
self.
|
124
|
-
if len(self.animStates) == 1:
|
125
|
-
self.set_animState(name)
|
114
|
+
self.animations[animation.name] = animation
|
126
115
|
return True
|
127
116
|
|
128
|
-
def
|
129
|
-
|
117
|
+
def set_animation(
|
118
|
+
self, state: str, reset_counter: bool = True, lock: bool = False
|
119
|
+
) -> bool:
|
120
|
+
if state not in self.animations or self._locked:
|
130
121
|
return False
|
122
|
+
|
123
|
+
animation = self.animations[state]
|
124
|
+
self.current_state = animation
|
131
125
|
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
self.rect = self.current_state.frames[0].get_frect(center=self.rect.center)
|
126
|
+
if self.current_state.frames:
|
127
|
+
self.rect = self.current_state.frames[0].get_frect(center=self.rect.center)
|
136
128
|
|
137
|
-
if reset_counter or self.float_counter >
|
129
|
+
if reset_counter or (self.float_counter > animation.duration_list_length):
|
138
130
|
self.float_counter = 0
|
131
|
+
|
139
132
|
if lock:
|
140
133
|
self.lock()
|
134
|
+
|
135
|
+
if self.transition_end_animation is not None:
|
136
|
+
self.transition_end_animation = None
|
141
137
|
return True
|
142
|
-
|
143
|
-
def
|
138
|
+
|
139
|
+
def transition_to_animation(self,transition:str,animation:str)->Self:
|
140
|
+
self.set_animation(transition)
|
141
|
+
self.transition_end_animation = animation
|
142
|
+
return self
|
143
|
+
|
144
|
+
def get_current_animation(self) -> Optional[Animation]:
|
144
145
|
return self.current_state
|
145
146
|
|
146
147
|
def update(self, dt: float) -> None:
|
147
|
-
s = self.
|
148
|
-
if
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
148
|
+
s = self.get_current_animation()
|
149
|
+
if self.animations and s is not None:
|
150
|
+
if not self.paused:
|
151
|
+
self.float_counter += 60 * dt
|
152
|
+
if self.float_counter > s.duration_list_length:
|
153
|
+
if self.transition_end_animation is not None:
|
154
|
+
# print(f"{self.transition_end_animation=}, {self.get_current_animation()=}")
|
155
|
+
self.set_animation(self.transition_end_animation)
|
156
|
+
if self.animation_end_callback is not None:
|
157
|
+
self.animation_end_callback()
|
158
|
+
self.float_counter = 0
|
159
|
+
super().update(dt)
|
160
|
+
|
161
|
+
|
162
|
+
def get_current_frame(self)->pygame.Surface:
|
163
|
+
return self.current_state.get_frame(self.float_counter, self.flipX)
|
164
|
+
|
165
|
+
def draw(self, camera: bf.Camera) -> None:
|
157
166
|
if (
|
158
167
|
not self.visible
|
159
168
|
or not camera.rect.colliderect(self.rect)
|
160
169
|
or not self.current_state
|
161
170
|
):
|
162
|
-
return
|
171
|
+
return
|
163
172
|
camera.surface.blit(
|
164
|
-
self.
|
173
|
+
self.get_current_frame(),
|
165
174
|
camera.world_to_screen(self.rect),
|
166
175
|
)
|
167
|
-
return
|
176
|
+
return
|
batFramework/audioManager.py
CHANGED
@@ -68,7 +68,7 @@ class AudioManager(metaclass=bf.Singleton):
|
|
68
68
|
self.sounds[name]["sound"].play()
|
69
69
|
return True
|
70
70
|
except KeyError:
|
71
|
-
|
71
|
+
print(f"Sound '{name}' not loaded in AudioManager.")
|
72
72
|
return False
|
73
73
|
|
74
74
|
def stop_sound(self, name) -> bool:
|
@@ -77,7 +77,7 @@ class AudioManager(metaclass=bf.Singleton):
|
|
77
77
|
return True
|
78
78
|
except KeyError:
|
79
79
|
return False
|
80
|
-
|
80
|
+
print(f"Sound '{name}' not loaded in AudioManager.")
|
81
81
|
|
82
82
|
def load_music(self, name, path):
|
83
83
|
self.musics[name] = bf.ResourceManager().get_path(path)
|
@@ -0,0 +1,27 @@
|
|
1
|
+
import batFramework as bf
|
2
|
+
from .stateMachine import State
|
3
|
+
from .animatedSprite import AnimatedSprite
|
4
|
+
from .dynamicEntity import DynamicEntity
|
5
|
+
|
6
|
+
class Character(AnimatedSprite,DynamicEntity):
|
7
|
+
def __init__(self) -> None:
|
8
|
+
super().__init__()
|
9
|
+
self.state_machine = bf.StateMachine(self)
|
10
|
+
self.do_setup_animations()
|
11
|
+
self.do_setup_states()
|
12
|
+
|
13
|
+
def set_state(self,state_name:str):
|
14
|
+
self.state_machine.set_state(state_name)
|
15
|
+
|
16
|
+
def get_current_state(self)->State:
|
17
|
+
return self.state_machine.get_current_state()
|
18
|
+
|
19
|
+
def update(self, dt: float) -> None:
|
20
|
+
self.state_machine.update(dt)
|
21
|
+
super().update(dt)
|
22
|
+
|
23
|
+
def do_setup_states(self):
|
24
|
+
pass
|
25
|
+
|
26
|
+
def do_setup_animations(self):
|
27
|
+
pass
|
batFramework/cutscene.py
CHANGED
@@ -1,8 +1,11 @@
|
|
1
1
|
import batFramework as bf
|
2
|
-
|
2
|
+
from typing import TYPE_CHECKING
|
3
3
|
|
4
4
|
class CutsceneBlock: ...
|
5
5
|
|
6
|
+
if TYPE_CHECKING:
|
7
|
+
from .cutsceneBlocks import CutsceneBlock
|
8
|
+
|
6
9
|
|
7
10
|
class Cutscene: ...
|
8
11
|
|
@@ -58,7 +61,7 @@ class CutsceneManager(metaclass=bf.Singleton):
|
|
58
61
|
|
59
62
|
class Cutscene:
|
60
63
|
def __init__(self) -> None:
|
61
|
-
self.cutscene_blocks = []
|
64
|
+
self.cutscene_blocks : list[CutsceneBlock] = []
|
62
65
|
self.block_index = 0
|
63
66
|
self.end_blocks: list[CutsceneBlock] = []
|
64
67
|
self.ended = False
|
batFramework/cutsceneBlocks.py
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
import batFramework as bf
|
2
2
|
from .cutscene import Cutscene, CutsceneManager
|
3
3
|
from .transition import *
|
4
|
-
|
4
|
+
from typing import Optional,Callable
|
5
5
|
|
6
6
|
# Define the base CutsceneBlock class
|
7
7
|
class CutsceneBlock:
|
@@ -150,7 +150,6 @@ class SceneTransitionBlock(CutsceneBlock):
|
|
150
150
|
# Start the timer to handle the end of the transition
|
151
151
|
self.timer.start()
|
152
152
|
|
153
|
-
|
154
153
|
class DelayBlock(CutsceneBlock):
|
155
154
|
def __init__(self, duration) -> None:
|
156
155
|
super().__init__()
|
@@ -160,12 +159,11 @@ class DelayBlock(CutsceneBlock):
|
|
160
159
|
super().start()
|
161
160
|
self.timer.start()
|
162
161
|
|
163
|
-
|
164
162
|
class FunctionBlock(CutsceneBlock):
|
165
|
-
def __init__(self, func) -> None:
|
163
|
+
def __init__(self, func : Optional[Callable]) -> None:
|
166
164
|
self.function = func
|
167
165
|
|
168
166
|
def start(self):
|
169
167
|
super().start()
|
170
|
-
self.function()
|
168
|
+
if self.function : self.function()
|
171
169
|
self.end()
|
batFramework/dynamicEntity.py
CHANGED
@@ -8,15 +8,22 @@ class DynamicEntity(bf.Entity):
|
|
8
8
|
self,
|
9
9
|
size: None | tuple[int, int] = None,
|
10
10
|
surface_flags: int = 0,
|
11
|
-
convert_alpha: bool = False
|
11
|
+
convert_alpha: bool = False,*args,**kwargs
|
12
12
|
) -> None:
|
13
|
-
super().__init__(size, surface_flags, convert_alpha)
|
13
|
+
super().__init__(size, surface_flags, convert_alpha,*args,**kwargs)
|
14
14
|
self.velocity = pygame.math.Vector2(0, 0)
|
15
|
+
self.ignore_collisions : bool = False
|
15
16
|
|
16
|
-
def on_collideX(self, collider:
|
17
|
+
def on_collideX(self, collider: "DynamicEntity"):
|
18
|
+
"""
|
19
|
+
Return true if collision
|
20
|
+
"""
|
17
21
|
return False
|
18
22
|
|
19
|
-
def on_collideY(self, collider:
|
23
|
+
def on_collideY(self, collider: "DynamicEntity"):
|
24
|
+
"""
|
25
|
+
Return true if collision
|
26
|
+
"""
|
20
27
|
return False
|
21
28
|
|
22
29
|
def move_by_velocity(self, dt) -> None:
|
batFramework/enums.py
CHANGED
@@ -51,7 +51,7 @@ class easing(Enum):
|
|
51
51
|
EASE_IN = (0.95, 0, 1, 0.55)
|
52
52
|
EASE_OUT = (0.5, 1, 0.5, 1)
|
53
53
|
EASE_IN_OUT = (0.55, 0, 0.45, 1)
|
54
|
-
EASE_IN_OUT_ELASTIC = (0.
|
54
|
+
EASE_IN_OUT_ELASTIC = (0.76,-0.36,0.41,1.34)
|
55
55
|
|
56
56
|
def __init__(self, *control_points):
|
57
57
|
self.control_points = control_points
|
@@ -110,4 +110,4 @@ class actionType(Enum):
|
|
110
110
|
class textMode(Enum):
|
111
111
|
ALPHABETICAL = 0
|
112
112
|
NUMERICAL = 1
|
113
|
-
|
113
|
+
ALPHANUMERICAL = 3
|
batFramework/fontManager.py
CHANGED
@@ -42,7 +42,7 @@ class FontManager(metaclass=Singleton):
|
|
42
42
|
filename = name # if name is not given, name is the filename
|
43
43
|
self.FONTS[filename] = {}
|
44
44
|
# fill the dict
|
45
|
-
for size in range(self.MIN_FONT_SIZE, self.MAX_FONT_SIZE, 2):
|
45
|
+
for size in range(self.MIN_FONT_SIZE, self.MAX_FONT_SIZE+1, 2):
|
46
46
|
self.FONTS[filename][size] = pygame.font.Font(path, size=size)
|
47
47
|
|
48
48
|
def load_sysfont(self, font_name: str | None, key: str | None = ""):
|
@@ -52,7 +52,7 @@ class FontManager(metaclass=Singleton):
|
|
52
52
|
raise FileNotFoundError(f"Requested font '{font_name}' was not found")
|
53
53
|
self.FONTS[font_name] = {}
|
54
54
|
|
55
|
-
for size in range(self.MIN_FONT_SIZE, self.MAX_FONT_SIZE, 2):
|
55
|
+
for size in range(self.MIN_FONT_SIZE, self.MAX_FONT_SIZE+1, 2):
|
56
56
|
self.FONTS[key][size] = pygame.font.SysFont(font_name, size=size)
|
57
57
|
|
58
58
|
def get_font(
|
@@ -27,7 +27,7 @@ class ClickableWidget(Shape, InteractiveWidget):
|
|
27
27
|
self.set_debug_color("cyan")
|
28
28
|
self.set_relief(self.unpressed_relief)
|
29
29
|
|
30
|
-
def set_unpressed_relief(self, relief: int
|
30
|
+
def set_unpressed_relief(self, relief: int) -> Self:
|
31
31
|
if relief == self.unpressed_relief:
|
32
32
|
return self
|
33
33
|
self.unpressed_relief = relief
|
@@ -36,18 +36,17 @@ class ClickableWidget(Shape, InteractiveWidget):
|
|
36
36
|
self.set_relief(relief)
|
37
37
|
return self
|
38
38
|
|
39
|
-
def
|
40
|
-
self.silent_focus = value
|
41
|
-
return self
|
42
|
-
|
43
|
-
def set_pressed_relief(self, relief: int = 0) -> Self:
|
39
|
+
def set_pressed_relief(self, relief: int) -> Self:
|
44
40
|
if relief == self.pressed_relief:
|
45
41
|
return self
|
46
42
|
self.pressed_relief = relief
|
47
43
|
self.dirty_shape = True
|
48
44
|
if self.is_pressed:
|
49
45
|
self.set_relief(relief)
|
46
|
+
return self
|
50
47
|
|
48
|
+
def set_silent_focus(self, value: bool) -> Self:
|
49
|
+
self.silent_focus = value
|
51
50
|
return self
|
52
51
|
|
53
52
|
def set_click_down_sound(self, sound_name: str) -> Self:
|
@@ -141,15 +140,16 @@ class ClickableWidget(Shape, InteractiveWidget):
|
|
141
140
|
if not self.get_focus():
|
142
141
|
return
|
143
142
|
self.is_pressed = True
|
144
|
-
|
145
|
-
|
143
|
+
if self.click_down_sound:
|
144
|
+
bf.AudioManager().play_sound(self.click_down_sound)
|
146
145
|
pygame.mouse.set_cursor(self.click_cursor)
|
147
146
|
self.set_relief(self.pressed_relief)
|
148
147
|
|
149
148
|
def do_on_click_up(self, button) -> None:
|
150
149
|
if self.enabled and button == 1 and self.is_pressed:
|
151
150
|
self.is_pressed = False
|
152
|
-
|
151
|
+
if self.click_up_sound:
|
152
|
+
bf.AudioManager().play_sound(self.click_up_sound)
|
153
153
|
self.set_relief(self.unpressed_relief)
|
154
154
|
self.click()
|
155
155
|
|
@@ -217,3 +217,4 @@ class ClickableWidget(Shape, InteractiveWidget):
|
|
217
217
|
self._paint_disabled()
|
218
218
|
elif self.is_hovered:
|
219
219
|
self._paint_hovered()
|
220
|
+
|