batframework 1.0.9a11__py3-none-any.whl → 1.0.9a12__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 (73) hide show
  1. batFramework/__init__.py +2 -0
  2. batFramework/action.py +280 -279
  3. batFramework/actionContainer.py +105 -82
  4. batFramework/animatedSprite.py +80 -58
  5. batFramework/animation.py +91 -77
  6. batFramework/audioManager.py +156 -131
  7. batFramework/baseScene.py +249 -240
  8. batFramework/camera.py +245 -317
  9. batFramework/constants.py +57 -51
  10. batFramework/cutscene.py +239 -253
  11. batFramework/cutsceneManager.py +34 -34
  12. batFramework/drawable.py +107 -77
  13. batFramework/dynamicEntity.py +30 -30
  14. batFramework/easingController.py +58 -58
  15. batFramework/entity.py +130 -130
  16. batFramework/enums.py +171 -135
  17. batFramework/fontManager.py +65 -65
  18. batFramework/gui/__init__.py +28 -25
  19. batFramework/gui/animatedLabel.py +90 -89
  20. batFramework/gui/button.py +17 -17
  21. batFramework/gui/clickableWidget.py +244 -244
  22. batFramework/gui/collapseContainer.py +98 -0
  23. batFramework/gui/constraints/__init__.py +1 -1
  24. batFramework/gui/constraints/constraints.py +1066 -980
  25. batFramework/gui/container.py +220 -206
  26. batFramework/gui/debugger.py +140 -130
  27. batFramework/gui/draggableWidget.py +63 -44
  28. batFramework/gui/image.py +61 -58
  29. batFramework/gui/indicator.py +116 -113
  30. batFramework/gui/interactiveWidget.py +243 -239
  31. batFramework/gui/label.py +147 -344
  32. batFramework/gui/layout.py +442 -429
  33. batFramework/gui/meter.py +155 -96
  34. batFramework/gui/radioButton.py +43 -35
  35. batFramework/gui/root.py +228 -228
  36. batFramework/gui/scrollingContainer.py +282 -0
  37. batFramework/gui/selector.py +232 -250
  38. batFramework/gui/shape.py +286 -276
  39. batFramework/gui/slider.py +353 -397
  40. batFramework/gui/style.py +10 -10
  41. batFramework/gui/styleManager.py +49 -54
  42. batFramework/gui/syncedVar.py +43 -49
  43. batFramework/gui/textInput.py +331 -306
  44. batFramework/gui/textWidget.py +308 -0
  45. batFramework/gui/toggle.py +140 -128
  46. batFramework/gui/tooltip.py +35 -30
  47. batFramework/gui/widget.py +546 -521
  48. batFramework/manager.py +131 -134
  49. batFramework/particle.py +118 -118
  50. batFramework/propertyEaser.py +79 -79
  51. batFramework/renderGroup.py +34 -34
  52. batFramework/resourceManager.py +130 -130
  53. batFramework/scene.py +31 -31
  54. batFramework/sceneLayer.py +134 -138
  55. batFramework/sceneManager.py +200 -197
  56. batFramework/scrollingSprite.py +115 -115
  57. batFramework/sprite.py +46 -51
  58. batFramework/stateMachine.py +49 -54
  59. batFramework/templates/__init__.py +2 -1
  60. batFramework/templates/character.py +15 -0
  61. batFramework/templates/controller.py +158 -97
  62. batFramework/templates/stateMachine.py +39 -0
  63. batFramework/tileset.py +46 -46
  64. batFramework/timeManager.py +213 -213
  65. batFramework/transition.py +162 -162
  66. batFramework/triggerZone.py +22 -22
  67. batFramework/utils.py +306 -306
  68. {batframework-1.0.9a11.dist-info → batframework-1.0.9a12.dist-info}/LICENSE +20 -20
  69. {batframework-1.0.9a11.dist-info → batframework-1.0.9a12.dist-info}/METADATA +24 -17
  70. batframework-1.0.9a12.dist-info/RECORD +72 -0
  71. batframework-1.0.9a11.dist-info/RECORD +0 -67
  72. {batframework-1.0.9a11.dist-info → batframework-1.0.9a12.dist-info}/WHEEL +0 -0
  73. {batframework-1.0.9a11.dist-info → batframework-1.0.9a12.dist-info}/top_level.txt +0 -0
@@ -1,131 +1,156 @@
1
- import batFramework as bf
2
- import pygame
3
-
4
-
5
-
6
-
7
- class AudioManager(metaclass=bf.Singleton):
8
- def __init__(self) -> None:
9
- self.sounds: dict = {}
10
- self.musics: dict = {}
11
- self.current_music: str | None = None
12
- self.music_volume: float = 1
13
- self.sound_volume: float = 1
14
- pygame.mixer.music.set_endevent(bf.const.MUSIC_END_EVENT)
15
-
16
- def free_sounds(self, force: bool = False):
17
- if force:
18
- self.sounds = {}
19
- return
20
- self.sounds: dict = {
21
- key: value for key, value in self.sounds.items() if value["persistent"]
22
- }
23
-
24
- def free_music(self):
25
- if self.current_music:
26
- pygame.mixer.music.unload(self.current_music)
27
-
28
- def set_sound_volume(self, volume: float):
29
- self.sound_volume = volume
30
-
31
- def set_music_volume(self, volume: float):
32
- self.music_volume = volume
33
- pygame.mixer.music.set_volume(volume)
34
-
35
- def get_music_volume(self) -> float:
36
- return self.music_volume
37
-
38
- def get_sound_volume(self) -> float:
39
- return self.sound_volume
40
-
41
- def has_sound(self, name: str):
42
- return name in self.sounds
43
-
44
- def load_sound(self, name, path, persistent=False) -> pygame.mixer.Sound:
45
- """
46
- if persistent==True the sound won't be unloaded when sounds are freed (unless force is used)
47
- """
48
- if name in self.sounds:
49
- return self.sounds[name]["sound"]
50
- path = bf.ResourceManager().get_path(path)
51
- self.sounds[name] = {
52
- "path": path,
53
- "sound": pygame.mixer.Sound(path),
54
- "persistent": persistent,
55
- }
56
- return self.sounds[name]["sound"]
57
-
58
- def load_sounds(self, sound_data: tuple[str, str, bool]) -> None:
59
- for data in sound_data:
60
- self.load_sound(*data)
61
- return
62
-
63
- def play_sound(self, name, volume=1) -> bool:
64
- """
65
- Play the sound file with the given name.
66
- returns True if the sound was played
67
-
68
- """
69
- try:
70
- self.sounds[name]["sound"].set_volume(volume * self.sound_volume)
71
- self.sounds[name]["sound"].play()
72
- return True
73
- except KeyError:
74
- print(f"Sound '{name}' not loaded in AudioManager.")
75
- return False
76
-
77
- def stop_sound(self, name) -> bool:
78
- try:
79
- self.sounds[name]["sound"].stop()
80
- return True
81
- except KeyError:
82
- return False
83
- print(f"Sound '{name}' not loaded in AudioManager.")
84
-
85
- def load_music(self, name, path):
86
- self.musics[name] = bf.ResourceManager().get_path(path)
87
- return
88
-
89
- def load_musics(self, *music_data:tuple[str, str]):
90
- for data in music_data:
91
- self.load_music(*data)
92
- return
93
-
94
- def play_music(self, name, loop=0, fade=500) -> bool:
95
- """
96
- Play the sound file with the given 'name'.
97
- Fades with the given 'fade' time in ms.
98
- Music will loop 'loop' times (indefinitely if -1).
99
- returns True if the sound was played
100
- """
101
- try:
102
- pygame.mixer.music.load(self.musics[name])
103
- pygame.mixer.music.play(loop, fade_ms=fade)
104
- self.current_music = name
105
- return True
106
- except KeyError:
107
- print(f"Music '{name}' not loaded in AudioManager.")
108
- return False
109
-
110
- def stop_music(self):
111
- if not self.current_music:
112
- return
113
- pygame.mixer.music.stop()
114
-
115
- def fadeout_music(self, fade_ms: int):
116
- if not self.current_music:
117
- return
118
- pygame.mixer.music.fadeout(fade_ms)
119
-
120
- def pause_music(self):
121
- if not self.current_music:
122
- return
123
- pygame.mixer.music.pause()
124
-
125
- def resume_music(self):
126
- if not self.current_music:
127
- return
128
- pygame.mixer.music.unpause()
129
-
130
- def get_current_music(self) -> str | None:
131
- return self.current_music
1
+ import pygame
2
+ import batFramework as bf
3
+
4
+ class AudioManager(metaclass=bf.Singleton):
5
+ def __init__(self) -> None:
6
+ self._sounds: dict[str, dict] = {}
7
+ self._musics: dict[str, str] = {}
8
+ self._current_music: str | None = None
9
+ self._music_volume: float = 1.0
10
+ self._sound_volume: float = 1.0
11
+
12
+ self._channels: dict[str, pygame.mixer.Channel] = {}
13
+ self._channel_volumes: dict[str, float] = {}
14
+ self._use_custom_channels: bool = False
15
+
16
+ pygame.mixer.music.set_endevent(bf.const.MUSIC_END_EVENT)
17
+
18
+ # --- Channel management ---
19
+ def setup_channels(self, channels: dict[str, int]) -> None:
20
+ """
21
+ Setup channels by providing a dict of {channel_name: channel_index}.
22
+ Enables custom channel management.
23
+ """
24
+ pygame.mixer.set_num_channels(max(channels.values()) + 1)
25
+ self._channels = {
26
+ name: pygame.mixer.Channel(idx) for name, idx in channels.items()
27
+ }
28
+ self._channel_volumes = {name: 1.0 for name in channels.keys()}
29
+ self._use_custom_channels = True
30
+
31
+ def set_channel_volume(self, channel_name: str, volume: float) -> None:
32
+ if channel_name in self._channels:
33
+ clamped = max(0.0, min(volume, 1.0))
34
+ self._channel_volumes[channel_name] = clamped
35
+ self._channels[channel_name].set_volume(clamped)
36
+
37
+ def get_channel_volume(self, channel_name: str) -> float:
38
+ return self._channel_volumes.get(channel_name, 1.0)
39
+
40
+ # --- Sound management ---
41
+ def load_sound(self, name: str, path: str, persistent: bool = False) -> pygame.mixer.Sound:
42
+ if name in self._sounds:
43
+ return self._sounds[name]["sound"]
44
+ path = bf.ResourceManager().get_path(path)
45
+ sound = pygame.mixer.Sound(path)
46
+ self._sounds[name] = {
47
+ "sound": sound,
48
+ "path": path,
49
+ "persistent": persistent,
50
+ }
51
+ return sound
52
+
53
+ def load_sounds(self, sounds_data: list[tuple[str, str, bool]]) -> None:
54
+ for name, path, persistent in sounds_data:
55
+ self.load_sound(name, path, persistent)
56
+
57
+ def play_sound(self, name: str, volume: float = 1.0, channel_name: str | None = None) -> bool:
58
+ sound_data = self._sounds.get(name)
59
+ if not sound_data:
60
+ print(f"[AudioManager] Sound '{name}' not loaded.")
61
+ return False
62
+ sound = sound_data["sound"]
63
+ volume = max(0.0, min(volume, 1.0)) * self._sound_volume
64
+
65
+ if self._use_custom_channels and channel_name:
66
+ channel = self._channels.get(channel_name)
67
+ if not channel:
68
+ print(f"[AudioManager] Channel '{channel_name}' not found. Using default channel.")
69
+ sound.set_volume(volume)
70
+ sound.play()
71
+ return True
72
+ channel.set_volume(volume * self._channel_volumes.get(channel_name, 1.0))
73
+ channel.play(sound)
74
+ else:
75
+ # Default pygame behavior: auto assign a free channel
76
+ sound.set_volume(volume)
77
+ sound.play()
78
+ return True
79
+
80
+ def stop_sound(self, name: str) -> bool:
81
+ sound_data = self._sounds.get(name)
82
+ if not sound_data:
83
+ print(f"[AudioManager] Sound '{name}' not loaded.")
84
+ return False
85
+ sound_data["sound"].stop()
86
+ return True
87
+
88
+ def free_sounds(self, force: bool = False) -> None:
89
+ if force:
90
+ self._sounds.clear()
91
+ else:
92
+ self._sounds = {
93
+ name: data for name, data in self._sounds.items() if data["persistent"]
94
+ }
95
+
96
+ def set_sound_volume(self, volume: float) -> None:
97
+ self._sound_volume = max(0.0, min(volume, 1.0))
98
+
99
+ def get_sound_volume(self) -> float:
100
+ return self._sound_volume
101
+
102
+ # --- Music management ---
103
+ def load_music(self, name: str, path: str) -> None:
104
+ self._musics[name] = bf.ResourceManager().get_path(path)
105
+
106
+ def load_musics(self, musics_data: list[tuple[str, str]]) -> None:
107
+ for name, path in musics_data:
108
+ self.load_music(name, path)
109
+
110
+ def play_music(self, name: str, loops: int = 0, fade_ms: int = 500) -> bool:
111
+ path = self._musics.get(name)
112
+ if not path:
113
+ print(f"[AudioManager] Music '{name}' not loaded.")
114
+ return False
115
+ try:
116
+ pygame.mixer.music.load(path)
117
+ pygame.mixer.music.set_volume(self._music_volume)
118
+ pygame.mixer.music.play(loops=loops, fade_ms=fade_ms)
119
+ self._current_music = name
120
+ return True
121
+ except pygame.error as e:
122
+ print(f"[AudioManager] Failed to play music '{name}': {e}")
123
+ return False
124
+
125
+ def stop_music(self) -> None:
126
+ if self._current_music:
127
+ pygame.mixer.music.stop()
128
+ self._current_music = None
129
+
130
+ def fadeout_music(self, fade_ms: int) -> None:
131
+ if self._current_music:
132
+ pygame.mixer.music.fadeout(fade_ms)
133
+ self._current_music = None
134
+
135
+ def pause_music(self) -> None:
136
+ if self._current_music:
137
+ pygame.mixer.music.pause()
138
+
139
+ def resume_music(self) -> None:
140
+ if self._current_music:
141
+ pygame.mixer.music.unpause()
142
+
143
+ def free_music(self) -> None:
144
+ if self._current_music:
145
+ pygame.mixer.music.unload()
146
+ self._current_music = None
147
+
148
+ def set_music_volume(self, volume: float) -> None:
149
+ self._music_volume = max(0.0, min(volume, 1.0))
150
+ pygame.mixer.music.set_volume(self._music_volume)
151
+
152
+ def get_music_volume(self) -> float:
153
+ return self._music_volume
154
+
155
+ def get_current_music(self) -> str | None:
156
+ return self._current_music