batframework 1.0.9a11__py3-none-any.whl → 1.1.0__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 (76) hide show
  1. batFramework/__init__.py +52 -76
  2. batFramework/action.py +99 -126
  3. batFramework/actionContainer.py +9 -53
  4. batFramework/animatedSprite.py +114 -56
  5. batFramework/audioManager.py +36 -82
  6. batFramework/camera.py +69 -263
  7. batFramework/constants.py +53 -29
  8. batFramework/cutscene.py +109 -243
  9. batFramework/cutsceneBlocks.py +176 -0
  10. batFramework/debugger.py +48 -0
  11. batFramework/dynamicEntity.py +9 -16
  12. batFramework/easing.py +71 -0
  13. batFramework/entity.py +85 -92
  14. batFramework/gui/__init__.py +3 -14
  15. batFramework/gui/button.py +78 -12
  16. batFramework/gui/constraints.py +204 -0
  17. batFramework/gui/container.py +31 -188
  18. batFramework/gui/debugger.py +43 -126
  19. batFramework/gui/frame.py +19 -0
  20. batFramework/gui/image.py +20 -55
  21. batFramework/gui/indicator.py +22 -95
  22. batFramework/gui/interactiveWidget.py +12 -229
  23. batFramework/gui/label.py +77 -311
  24. batFramework/gui/layout.py +66 -414
  25. batFramework/gui/root.py +35 -203
  26. batFramework/gui/shape.py +57 -247
  27. batFramework/gui/toggle.py +48 -114
  28. batFramework/gui/widget.py +243 -457
  29. batFramework/manager.py +29 -113
  30. batFramework/particles.py +77 -0
  31. batFramework/scene.py +217 -22
  32. batFramework/sceneManager.py +129 -161
  33. batFramework/stateMachine.py +8 -11
  34. batFramework/time.py +75 -0
  35. batFramework/transition.py +124 -129
  36. batFramework/transitionManager.py +0 -0
  37. batFramework/triggerZone.py +4 -4
  38. batFramework/utils.py +144 -266
  39. {batframework-1.0.9a11.dist-info → batframework-1.1.0.dist-info}/METADATA +24 -22
  40. batframework-1.1.0.dist-info/RECORD +43 -0
  41. batFramework/animation.py +0 -77
  42. batFramework/baseScene.py +0 -240
  43. batFramework/cutsceneManager.py +0 -34
  44. batFramework/drawable.py +0 -77
  45. batFramework/easingController.py +0 -58
  46. batFramework/enums.py +0 -135
  47. batFramework/fontManager.py +0 -65
  48. batFramework/gui/animatedLabel.py +0 -89
  49. batFramework/gui/clickableWidget.py +0 -244
  50. batFramework/gui/constraints/__init__.py +0 -1
  51. batFramework/gui/constraints/constraints.py +0 -980
  52. batFramework/gui/draggableWidget.py +0 -44
  53. batFramework/gui/meter.py +0 -96
  54. batFramework/gui/radioButton.py +0 -35
  55. batFramework/gui/selector.py +0 -250
  56. batFramework/gui/slider.py +0 -397
  57. batFramework/gui/style.py +0 -10
  58. batFramework/gui/styleManager.py +0 -54
  59. batFramework/gui/syncedVar.py +0 -49
  60. batFramework/gui/textInput.py +0 -306
  61. batFramework/gui/tooltip.py +0 -30
  62. batFramework/particle.py +0 -118
  63. batFramework/propertyEaser.py +0 -79
  64. batFramework/renderGroup.py +0 -34
  65. batFramework/resourceManager.py +0 -130
  66. batFramework/sceneLayer.py +0 -138
  67. batFramework/scrollingSprite.py +0 -115
  68. batFramework/sprite.py +0 -51
  69. batFramework/templates/__init__.py +0 -1
  70. batFramework/templates/controller.py +0 -97
  71. batFramework/tileset.py +0 -46
  72. batFramework/timeManager.py +0 -213
  73. batframework-1.0.9a11.dist-info/RECORD +0 -67
  74. {batframework-1.0.9a11.dist-info → batframework-1.1.0.dist-info}/LICENSE +0 -0
  75. {batframework-1.0.9a11.dist-info → batframework-1.1.0.dist-info}/WHEEL +0 -0
  76. {batframework-1.0.9a11.dist-info → batframework-1.1.0.dist-info}/top_level.txt +0 -0
batFramework/baseScene.py DELETED
@@ -1,240 +0,0 @@
1
- from __future__ import annotations
2
- from typing import TYPE_CHECKING, Any
3
- if TYPE_CHECKING:
4
- from .manager import Manager
5
- from .sceneManager import SceneManager
6
-
7
- import pygame
8
- import itertools
9
- import batFramework as bf
10
- from .sceneLayer import SceneLayer
11
-
12
- class BaseScene:
13
- def __init__(self,name: str) -> None:
14
- """
15
- Base Scene object.
16
- Empty scene with no layers or gui setup
17
- Args:
18
- name: Name of the scene.
19
- """
20
- bf.TimeManager().add_register(name,False)
21
- self.scene_index = 0
22
- self.name = name
23
- self.manager: Manager | None = None
24
- self.active = False
25
- self.visible = False
26
- self.clear_color = bf.color.BLACK
27
- self.actions: bf.ActionContainer = bf.ActionContainer()
28
- self.early_actions: bf.ActionContainer = bf.ActionContainer()
29
- self.scene_layers : list[SceneLayer] = []
30
-
31
- def set_clear_color(self,color):
32
- """
33
- Sets the clear color of the entire scene.
34
- This color will fill the scene before all layers are drawn.
35
- Results will not show if a layer has an opaque fill color on top.
36
- Set to None to skip.
37
- """
38
- self.clear_color = color
39
-
40
- def add_layer(self,layer:SceneLayer,index:int=0):
41
- layer.set_scene(self)
42
- self.scene_layers.insert(index,layer)
43
-
44
- def remove_layer(self,index=0):
45
- self.scene_layers.pop(index)
46
-
47
- def set_layer(self,layername,layer):
48
- for i,l in enumerate(self.scene_layers[::]):
49
- if l.name == layername:
50
- self.scene_layers[i] = layer
51
- layer.set_scene(self)
52
-
53
- def get_layer(self,name:str)->bf.SceneLayer:
54
- for s in self.scene_layers:
55
- if s.name == name:
56
- return s
57
- return None
58
-
59
- def add(self,layer:str,*entities):
60
- l = self.get_layer(layer)
61
- if l is None : return
62
- l.add(*entities)
63
-
64
- def remove(self,layer:str,*entities):
65
- l = self.get_layer(layer)
66
- if l is None : return
67
- l.remove(*entities)
68
-
69
- def __str__(self)->str:
70
- return f"Scene({self.name})"
71
-
72
- def set_scene_index(self, index: int):
73
- """Set the scene index."""
74
- self.scene_index = index
75
-
76
- def get_scene_index(self) -> int:
77
- """Get the scene index."""
78
- return self.scene_index
79
-
80
- def when_added(self):
81
- for s in self.scene_layers:
82
- s.flush_entity_changes()
83
- self.do_when_added()
84
-
85
- def do_when_added(self):
86
- pass
87
-
88
- def set_manager(self, manager_link: Manager):
89
- """Set the manager link for the scene."""
90
- self.manager = manager_link
91
- self.manager.update_scene_states()
92
-
93
- def set_visible(self, value: bool):
94
- """Set the visibility of the scene."""
95
- self.visible = value
96
- if self.manager:
97
- self.manager.update_scene_states()
98
-
99
- def set_active(self, value):
100
- """Set the activity of the scene."""
101
- self.active = value
102
- if self.manager:
103
- self.manager.update_scene_states()
104
-
105
- def is_active(self) -> bool:
106
- """Check if the scene is active."""
107
- return self.active
108
-
109
- def is_visible(self) -> bool:
110
- """Check if the scene is visible."""
111
- return self.visible
112
-
113
- def get_name(self) -> str:
114
- """Get the name of the scene."""
115
- return self.name
116
-
117
- def get_by_tags(self, *tags):
118
- """Get entities by their tags."""
119
- return itertools.chain.from_iterable(l.get_by_tags(*tags) for l in self.scene_layers)
120
-
121
- def get_by_uid(self, uid) -> bf.Entity | None:
122
- """Get an entity by its unique identifier."""
123
- for l in self.scene_layers:
124
- r = l.get_by_uid(uid)
125
- if r is not None:
126
- return r
127
- return None
128
-
129
- def add_actions(self, *action):
130
- """Add actions to the scene."""
131
- self.actions.add_actions(*action)
132
-
133
- def add_early_actions(self, *action):
134
- """Add actions to the scene."""
135
- self.early_actions.add_actions(*action)
136
-
137
- def process_event(self, event: pygame.Event):
138
- """
139
- Propagates event while it is not consumed.
140
- In order : do_early_handle_event
141
- -> scene early_actions
142
- -> propagate to all layers
143
- -> do_handle_event
144
- -> scene actions.
145
- at each step, if the event is consumed the propagation stops
146
- """
147
- self.do_early_handle_event(event)
148
- if event.consumed: return
149
- self.early_actions.process_event(event)
150
- if event.consumed: return
151
-
152
- if self.manager.current_transition and event.type in bf.enums.playerInput:
153
- return
154
-
155
- for l in self.scene_layers:
156
- l.process_event(event)
157
- if event.consumed : return
158
-
159
- self.do_handle_event(event)
160
-
161
- if event.consumed:return
162
- self.actions.process_event(event)
163
-
164
- # called before process event
165
- def do_early_handle_event(self, event: pygame.Event):
166
- """Called early in event propagation"""
167
- pass
168
-
169
- def do_handle_event(self, event: pygame.Event):
170
- """called inside process_event but before resetting the scene's action container and propagating event to scene layers"""
171
- pass
172
-
173
- def update(self, dt):
174
- """Update the scene. Do NOT override"""
175
-
176
- #update all scene layers
177
- for l in self.scene_layers:
178
- l.update(dt)
179
- self.do_update(dt)
180
- self.actions.reset()
181
- self.early_actions.reset()
182
-
183
-
184
- def do_update(self, dt):
185
- """Specific update within the scene."""
186
- pass
187
-
188
-
189
- def draw(self, surface: pygame.Surface):
190
- if self.clear_color is not None:
191
- surface.fill(self.clear_color)
192
-
193
- self.do_early_draw(surface)
194
-
195
- # Draw all layers back to front
196
- for i,l in enumerate(reversed(self.scene_layers)):
197
- #blit all layers onto surface
198
- l.draw(surface)
199
- if i < len(self.scene_layers)-1:
200
- self.do_between_layer_draw(surface,l)
201
- self.do_final_draw(surface)
202
-
203
-
204
- def do_early_draw(self, surface: pygame.Surface):
205
- """Called before any layer draw"""
206
- pass
207
-
208
- def do_between_layer_draw(self, surface: pygame.Surface,layer:SceneLayer):
209
- """Called after drawing the argument layer (except the last layer)"""
210
- pass
211
-
212
- def do_final_draw(self, surface: pygame.Surface):
213
- "Called after all layers"
214
- pass
215
-
216
- def on_enter(self):
217
- self.set_active(True)
218
- self.set_visible(True)
219
- bf.TimeManager().activate_register(self.name)
220
- self.do_on_enter()
221
-
222
- def on_exit(self):
223
- self.set_active(False)
224
- self.set_visible(False)
225
- self.actions.hard_reset()
226
- self.early_actions.hard_reset()
227
- bf.TimeManager().deactivate_register(self.name)
228
- self.do_on_exit()
229
-
230
- def do_on_enter(self) -> None:
231
- pass
232
-
233
- def do_on_exit(self) -> None:
234
- pass
235
-
236
- def do_on_enter_early(self) -> None:
237
- pass
238
-
239
- def do_on_exit_early(self) -> None:
240
- pass
@@ -1,34 +0,0 @@
1
- import batFramework as bf
2
- from typing import TYPE_CHECKING,Self
3
- import pygame
4
- # if TYPE_CHECKING:
5
- from .cutscene import Cutscene
6
-
7
-
8
- class CutsceneManager(metaclass=bf.Singleton):
9
- def __init__(self) -> None:
10
- self.current_cutscene: Cutscene = None
11
- self.manager: bf.Manager = None
12
- self.is_playing : bool = False
13
- def set_manager(self, manager):
14
- self.manager = manager
15
-
16
- def process_event(self, event):
17
- if self.current_cutscene is not None:
18
- self.current_cutscene.process_event(event)
19
- if event.type in bf.enums.playerInput:
20
- event.consumed = True
21
-
22
- def play(self,cutscene:Cutscene):
23
- if self.current_cutscene is not None:return
24
-
25
- self.current_cutscene = cutscene
26
- cutscene.start()
27
- self.is_playing = True
28
-
29
- def update(self,dt):
30
- if self.current_cutscene:
31
- self.current_cutscene.update(dt)
32
- if self.current_cutscene.is_over:
33
- self.current_cutscene = None
34
- self.is_playing = False
batFramework/drawable.py DELETED
@@ -1,77 +0,0 @@
1
- from typing import Any, Self
2
- import pygame
3
- import batFramework as bf
4
- from .entity import Entity
5
-
6
-
7
- class Drawable(Entity):
8
- """
9
- Basic entity class
10
- """
11
-
12
- def __init__(
13
- self,
14
- size: None | tuple[int|float] = None,
15
- surface_flags: int = 0,
16
- convert_alpha: bool = False,
17
- *args,
18
- **kwargs,
19
- ) -> None:
20
- super().__init__()
21
- self.visible: bool = True
22
- self.render_order: int = 0
23
- if size is not None:
24
- self.rect.size = size
25
- self.convert_alpha: bool = convert_alpha
26
- self.surface_flags: int = surface_flags
27
- self.blit_flags: int = 0
28
- self.drawn_by_group : bool = False # flag for render group
29
- self.surface: pygame.Surface = pygame.Surface(self.rect.size, surface_flags)
30
- if convert_alpha:
31
- self.surface = self.surface.convert_alpha()
32
- self.surface.fill((0, 0, 0, 0))
33
-
34
- def set_alpha(self, alpha: int) -> Self:
35
- self.surface.set_alpha(min(max(0, alpha), 255))
36
- return self
37
-
38
- def get_alpha(self) -> int:
39
- return self.surface.get_alpha()
40
-
41
- def set_surface_flags(self, surface_flags: int) -> Self:
42
- self.surface_flags = surface_flags
43
- return self
44
-
45
- def set_convert_alpha(self, value: bool) -> Self:
46
- self.convert_alpha = value
47
- return self
48
-
49
- def set_blit_flags(self, blit_flags: int) -> Self:
50
- self.blit_flags = blit_flags
51
- return self
52
-
53
- def get_debug_outlines(self):
54
- if self.visible:
55
- yield (self.rect, self.debug_color)
56
-
57
- def set_render_order(self, render_order: int) -> Self:
58
- self.render_order = render_order
59
- if self.parent_layer:
60
- self.parent_layer.update_draw_order()
61
- return self
62
-
63
- def set_visible(self, value: bool) -> Self:
64
- self.visible = value
65
- return self
66
-
67
- def draw(self, camera: bf.Camera) -> None:
68
- """
69
- Draw the entity onto the camera surface
70
- """
71
- if not self.visible or self.drawn_by_group or not camera.rect.colliderect(self.rect) or self.surface.get_alpha() == 0:
72
- return
73
- camera.surface.blit(
74
- self.surface,
75
- camera.world_to_screen(self.rect),
76
- special_flags=self.blit_flags,
77
- )
@@ -1,58 +0,0 @@
1
- import pygame
2
- import batFramework as bf
3
- from functools import lru_cache
4
- from typing import Callable,Any
5
-
6
-
7
- @lru_cache(maxsize=None)
8
- def process_value(progress: float, p0: float, p1: float, p2: float, p3: float) -> float:
9
- if p0 == 0 and p1 == 0 and p2 == 1 and p3 == 1: # Linear easing control points
10
- return progress
11
- t = progress
12
- t_inv = 1.0 - t
13
- t2 = t * t
14
- t3 = t * t2
15
- t_inv2 = t_inv * t_inv
16
- return 3 * t_inv2 * t * p1 + 3 * t_inv * t2 * p3 + t3
17
-
18
-
19
- class EasingController(bf.Timer):
20
- def __init__(
21
- self,
22
- duration: float = 1,
23
- easing: bf.easing = bf.easing.LINEAR,
24
- update_callback=None,
25
- end_callback: Callable[[], Any] = None,
26
- loop: int = 0,
27
- register:str="global"
28
- ) -> None:
29
- self.easing_function = easing
30
- self.update_callback: Callable[[float], Any] = update_callback
31
- self.value: float = 0.0
32
- super().__init__(duration, end_callback, loop, register)
33
-
34
- def get_value(self) -> float:
35
- return self.value
36
-
37
- def start(self, force: bool = False):
38
- super().start(force)
39
- self.value = 0
40
-
41
- def update(self, dt: float) -> None:
42
- if self.get_progression() == 1:
43
- return
44
- super().update(dt)
45
- if self.get_progression() == 0:
46
- return
47
- if self.easing_function == bf.easing.LINEAR: # avoid calculating if linear (just use progression as is)
48
- self.value = self.get_progression()
49
- else:
50
- self.value = process_value(self.get_progression(), *self.easing_function.control_points)
51
-
52
- if self.update_callback:
53
- self.update_callback(self.value)
54
-
55
- def end(self):
56
- if self.update_callback:
57
- self.update_callback(1)
58
- super().end()
batFramework/enums.py DELETED
@@ -1,135 +0,0 @@
1
- from enum import Enum
2
- import pygame
3
-
4
- playerInput = [pygame.KEYDOWN,pygame.MOUSEBUTTONDOWN,pygame.KEYUP,pygame.MOUSEBUTTONUP]
5
-
6
- class color:
7
- WHITE = pygame.Color(255, 255, 255)
8
- LIGHTER_GRAY = pygame.Color(236, 240, 241)
9
- LIGHT_GRAY = pygame.Color(189, 195, 199)
10
- DARK_GRAY = pygame.Color(66, 66, 66)
11
- DARKER_GRAY = pygame.Color(23, 23, 23)
12
- BLACK = pygame.Color(0, 0, 0)
13
-
14
- TURQUOISE = pygame.Color(26, 188, 156)
15
- TURQUOISE_SHADE = pygame.Color(22, 160, 133)
16
-
17
- GREEN = pygame.Color(46, 204, 113)
18
- GREEN_SHADE = pygame.Color(39, 174, 96)
19
-
20
- BLUE = pygame.Color(52, 152, 219)
21
- BLUE_SHADE = pygame.Color(41, 128, 185)
22
-
23
- PURPLE = pygame.Color(155, 89, 182)
24
- PURPLE_SHADE = pygame.Color(142, 68, 173)
25
-
26
- CHARCOAL = pygame.Color(52, 73, 94)
27
- CHARCOAL_SHADE = pygame.Color(44, 62, 80)
28
-
29
- GOLD = pygame.Color(241, 196, 15)
30
- GOLD_SHADE = pygame.Color(243, 156, 18)
31
-
32
- ORANGE = pygame.Color(230, 126, 34)
33
- ORANGE_SHADE = pygame.Color(211, 84, 0)
34
-
35
- RED = pygame.Color(231, 76, 60)
36
- RED_SHADE = pygame.Color(192, 57, 43)
37
-
38
- CLOUD = pygame.Color(236, 240, 241)
39
- CLOUD_SHADE = pygame.Color(189, 195, 199)
40
-
41
- CONCRETE = pygame.Color(149, 165, 166)
42
- CONCRETE_SHADE = pygame.Color(127, 140, 141)
43
-
44
- # GB
45
- DARKER_GB = pygame.Color(27, 42, 9)
46
- DARK_GB = pygame.Color(14, 69, 11)
47
- LIGHT_GB = pygame.Color(73, 107, 34)
48
- LIGHTER_GB = pygame.Color(154, 158, 63)
49
-
50
- @staticmethod
51
- def mult(color: pygame.Color, factor: float):
52
- return pygame.Color(
53
- min(max(0, int(color.r * factor)), 255),
54
- min(max(0, int(color.g * factor)), 255),
55
- min(max(0, int(color.b * factor)), 255),
56
- color.a
57
- )
58
-
59
- class easing(Enum):
60
- LINEAR = (0, 0, 1, 1)
61
- EASE_IN = (0.95, 0, 1, 0.55)
62
- EASE_OUT = (0.5, 1, 0.5, 1)
63
- EASE_IN_OUT = (0.55, 0, 0.45, 1)
64
- EASE_IN_OUT_ELASTIC = (0.76,-0.36,0.41,1.34)
65
-
66
- def __init__(self, *control_points):
67
- self.control_points = control_points
68
-
69
- @classmethod
70
- def create(cls, *control_points):
71
- """Create a custom easing instance."""
72
- instance = object.__new__(cls)
73
- instance._value_ = control_points
74
- instance.control_points = control_points
75
- return instance
76
-
77
- class axis(Enum):
78
- HORIZONTAL = "horizontal"
79
- VERTICAL = "vertical"
80
-
81
-
82
- class spacing(Enum):
83
- MIN = "min"
84
- HALF = "half"
85
- MAX = "max"
86
- MANUAL = "manual"
87
-
88
-
89
- class alignment(Enum):
90
- LEFT = "left"
91
- RIGHT = "right"
92
- CENTER = "center"
93
- TOP = "top"
94
- BOTTOM = "bottom"
95
- TOPLEFT = "topleft"
96
- TOPRIGHT = "topright"
97
- MIDLEFT = "midleft"
98
- MIDRIGHT = "midright"
99
- MIDTOP = "midtop"
100
- MIDBOTTOM = "midbottom"
101
- BOTTOMLEFT = "bottomleft"
102
- BOTTOMRIGHT = "bottomright"
103
-
104
-
105
- class direction(Enum):
106
- LEFT = 0
107
- UP = 1
108
- RIGHT = 2
109
- DOWN = 3
110
-
111
-
112
- class drawMode(Enum):
113
- SOLID = 0
114
- TEXTURED = 1
115
-
116
-
117
- class debugMode(Enum):
118
- HIDDEN = 0
119
- DEBUGGER = 1
120
- OUTLINES = 2
121
-
122
-
123
- class actionType(Enum):
124
- INSTANTANEOUS = 0
125
- CONTINUOUS = 1
126
- HOLDING = 2
127
-
128
-
129
- class textMode(Enum):
130
- ALPHABETICAL = 0
131
- NUMERICAL = 1
132
- ALPHANUMERICAL = 3
133
-
134
-
135
-
@@ -1,65 +0,0 @@
1
- from .utils import Singleton
2
-
3
- # put font stuff here later
4
- import pygame
5
- import os
6
- import batFramework as bf
7
-
8
-
9
- class FontManager(metaclass=Singleton):
10
- def __init__(self):
11
- pygame.font.init()
12
- self.DEFAULT_FONT_SIZE = 16
13
- self.MIN_FONT_SIZE = 8
14
- self.MAX_FONT_SIZE = 64
15
- self.DEFAULT_ANTIALIAS = False
16
- self.FONTS = {}
17
-
18
- def set_default_antialias(self, value: bool):
19
- self.DEFAULT_ANTIALIAS = value
20
-
21
- def set_default_text_size(self, size: int):
22
- self.DEFAULT_FONT_SIZE = size
23
-
24
- def init_font(self, raw_path: str | None):
25
- try:
26
- if raw_path is not None:
27
- self.load_font(raw_path if raw_path else None, None)
28
- self.load_font(raw_path)
29
- except FileNotFoundError:
30
- self.load_sysfont(raw_path)
31
- self.load_sysfont(raw_path, None)
32
-
33
- def load_font(self, path: str | None, name: str | None = ""):
34
- if path is not None:
35
- path = bf.ResourceManager().get_path(path) # convert path if given
36
- filename = None
37
- if path is not None:
38
- filename = os.path.basename(path).split(".")[0]
39
-
40
- # get filename if path is given, else None
41
- if name != "":
42
- filename = name # if name is not given, name is the filename
43
- self.FONTS[filename] = {}
44
- # fill the dict
45
- for size in range(self.MIN_FONT_SIZE, self.MAX_FONT_SIZE+1, 2):
46
- self.FONTS[filename][size] = pygame.font.Font(path, size=size)
47
-
48
- def load_sysfont(self, font_name: str | None, key: str | None = ""):
49
- if key == "":
50
- key = font_name
51
- if font_name is None or pygame.font.match_font(font_name) is None:
52
- raise FileNotFoundError(f"Requested font '{font_name}' was not found")
53
- self.FONTS[font_name] = {}
54
-
55
- for size in range(self.MIN_FONT_SIZE, self.MAX_FONT_SIZE+1, 2):
56
- self.FONTS[key][size] = pygame.font.SysFont(font_name, size=size)
57
-
58
- def get_font(
59
- self, name: str | None = None, text_size: int = 12
60
- ) -> pygame.Font | None:
61
- if not name in self.FONTS:
62
- return None
63
- if not text_size in self.FONTS[name]:
64
- return None
65
- return self.FONTS[name][text_size]
@@ -1,89 +0,0 @@
1
- from .label import Label
2
- import batFramework as bf
3
- from typing import Self,Callable,Any
4
-
5
-
6
- class AnimatedLabel(Label):
7
- def __init__(self,text="") -> None:
8
- self.cursor_position: float = 0.0
9
- self.text_speed: float = 20.0
10
- self.is_over: bool = True
11
- self.is_paused: bool = False
12
- self.original_text = ""
13
- self.end_callback : Callable[[],Any]= None
14
- self.set_autoresize(False)
15
- self.set_alignment(bf.alignment.LEFT)
16
- super().__init__("")
17
- self.set_text(text)
18
-
19
- def __str__(self) -> str:
20
- return "AnimatedLabel"
21
-
22
- def set_end_callback(self,callback:Callable[[],Any]):
23
- self.end_callback = callback
24
-
25
- def pause(self) -> Self:
26
- self.is_paused = True
27
- return self
28
-
29
- def resume(self) -> Self:
30
- self.is_paused = False
31
- return self
32
-
33
- def set_text_speed(self, speed: float) -> Self:
34
- self.text_speed = speed
35
- return self
36
-
37
- def cut_text_to_width(self, text: str) -> list[str]:
38
- w = self.get_inner_width()
39
- if text == "" or not self.font_object or w < self.font_object.point_size:
40
- return [text]
41
- left = 0
42
- for index in range(len(text)):
43
- width = self.font_object.size(text[left:index])[0]
44
-
45
- if width > w:
46
- cut_point_start = index - 1
47
- cut_point_end = index - 1
48
- last_space = text.rfind(" ", 0, cut_point_start)
49
- last_nline = text.rfind("\n", 0, cut_point_start)
50
-
51
- if last_space != -1 or last_nline != -1: # space was found !:
52
- cut_point_start = max(last_space, last_nline)
53
- cut_point_end = cut_point_start + 1
54
- res = [text[:cut_point_start].strip()]
55
- res.extend(self.cut_text_to_width(text[cut_point_end:].strip()))
56
- return res
57
- elif text[index] == "\n":
58
- left = index
59
- return [text]
60
-
61
-
62
- def _set_text_internal(self,text:str)->Self:
63
- super().set_text(text)
64
- return self
65
-
66
- def set_text(self,text:str)->Self:
67
- self.original_text = text
68
- self.is_over = False
69
- self.cursor_position = 0
70
-
71
- def set_size(self, size):
72
- super().set_size(size)
73
- self._set_text_internal('\n'.join(self.cut_text_to_width(self.original_text[: int(self.cursor_position)])))
74
-
75
- def do_update(self, dt):
76
- if self.is_over:
77
- return
78
- if not self.is_over and self.cursor_position == len(self.original_text):
79
- if len(self.original_text) == 0:
80
- self._set_text_internal("")
81
- self.is_over = True
82
- if self.end_callback is not None:
83
- self.end_callback()
84
- return
85
- self.cursor_position = min(
86
- self.cursor_position + self.text_speed * dt, len(self.original_text)
87
- )
88
- # self.set_text(self.original_text[: int(self.cursor_position)])
89
- self._set_text_internal('\n'.join(self.cut_text_to_width(self.original_text[: int(self.cursor_position)])))