batframework 1.0.8a9__py3-none-any.whl → 1.0.8a10__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 +68 -51
- batFramework/action.py +126 -99
- batFramework/actionContainer.py +53 -9
- batFramework/animatedSprite.py +141 -82
- batFramework/audioManager.py +69 -26
- batFramework/camera.py +259 -69
- batFramework/character.py +27 -0
- batFramework/constants.py +16 -54
- batFramework/cutscene.py +39 -29
- batFramework/cutsceneBlocks.py +36 -43
- batFramework/dynamicEntity.py +18 -9
- batFramework/easingController.py +58 -0
- batFramework/entity.py +48 -97
- batFramework/enums.py +113 -0
- batFramework/fontManager.py +65 -0
- batFramework/gui/__init__.py +10 -2
- batFramework/gui/button.py +9 -78
- batFramework/gui/clickableWidget.py +220 -0
- batFramework/gui/constraints/__init__.py +1 -0
- batFramework/gui/constraints/constraints.py +815 -0
- batFramework/gui/container.py +174 -32
- batFramework/gui/debugger.py +131 -43
- batFramework/gui/dialogueBox.py +99 -0
- batFramework/gui/draggableWidget.py +40 -0
- batFramework/gui/image.py +56 -20
- batFramework/gui/indicator.py +38 -21
- batFramework/gui/interactiveWidget.py +192 -13
- batFramework/gui/label.py +309 -74
- batFramework/gui/layout.py +231 -63
- batFramework/gui/meter.py +74 -0
- batFramework/gui/radioButton.py +84 -0
- batFramework/gui/root.py +134 -38
- batFramework/gui/shape.py +237 -57
- batFramework/gui/slider.py +240 -0
- batFramework/gui/style.py +10 -0
- batFramework/gui/styleManager.py +48 -0
- batFramework/gui/textInput.py +247 -0
- batFramework/gui/toggle.py +101 -51
- batFramework/gui/widget.py +358 -250
- batFramework/manager.py +52 -19
- batFramework/object.py +123 -0
- batFramework/particle.py +115 -0
- batFramework/renderGroup.py +67 -0
- batFramework/resourceManager.py +100 -0
- batFramework/scene.py +281 -123
- batFramework/sceneManager.py +178 -116
- batFramework/scrollingSprite.py +114 -0
- batFramework/sprite.py +51 -0
- batFramework/stateMachine.py +11 -8
- batFramework/templates/__init__.py +2 -0
- batFramework/templates/character.py +44 -0
- batFramework/templates/states.py +166 -0
- batFramework/tileset.py +46 -0
- batFramework/time.py +145 -58
- batFramework/transition.py +195 -124
- batFramework/triggerZone.py +1 -1
- batFramework/utils.py +112 -147
- batframework-1.0.8a10.dist-info/LICENCE +21 -0
- batframework-1.0.8a10.dist-info/METADATA +43 -0
- batframework-1.0.8a10.dist-info/RECORD +62 -0
- batFramework/debugger.py +0 -48
- batFramework/easing.py +0 -71
- batFramework/gui/constraints.py +0 -204
- batFramework/gui/frame.py +0 -19
- batFramework/particles.py +0 -77
- batFramework/transitionManager.py +0 -0
- batframework-1.0.8a9.dist-info/METADATA +0 -53
- batframework-1.0.8a9.dist-info/RECORD +0 -42
- {batframework-1.0.8a9.dist-info → batframework-1.0.8a10.dist-info}/WHEEL +0 -0
- {batframework-1.0.8a9.dist-info → batframework-1.0.8a10.dist-info}/top_level.txt +0 -0
batFramework/gui/label.py
CHANGED
@@ -2,109 +2,344 @@ import batFramework as bf
|
|
2
2
|
import pygame
|
3
3
|
from .shape import Shape
|
4
4
|
from typing import Self
|
5
|
+
from math import ceil
|
5
6
|
|
6
7
|
class Label(Shape):
|
7
|
-
|
8
|
-
|
8
|
+
_text_cache = {}
|
9
|
+
|
10
|
+
def __init__(self, text: str = "") -> None:
|
11
|
+
self.text = text
|
12
|
+
|
13
|
+
self.resized_flag: bool = False
|
14
|
+
|
9
15
|
# Enable/Disable antialiasing
|
10
|
-
self.
|
11
|
-
|
12
|
-
self.
|
13
|
-
|
14
|
-
self.
|
16
|
+
self.antialias: bool = bf.FontManager().DEFAULT_ANTIALIAS
|
17
|
+
|
18
|
+
self.text_size = bf.FontManager().DEFAULT_TEXT_SIZE
|
19
|
+
|
20
|
+
self.auto_wraplength: bool = False
|
21
|
+
|
22
|
+
self.alignment: bf.alignment = bf.alignment.CENTER
|
23
|
+
|
24
|
+
self.text_color: tuple[int, int, int] | str = "black"
|
25
|
+
|
26
|
+
self.text_outline_color: tuple[int, int, int] | str = "gray50"
|
27
|
+
|
28
|
+
self.text_outline_surface: pygame.Surface = None
|
29
|
+
|
30
|
+
self._text_outline_mask = pygame.Mask((3, 3), fill=True)
|
31
|
+
|
15
32
|
# font name (given when loaded by utils) to use for the text
|
16
|
-
self.
|
33
|
+
self.font_name = None
|
17
34
|
# reference to the font object
|
18
|
-
self.
|
35
|
+
self.font_object = None
|
19
36
|
# Rect containing the text of the label
|
20
|
-
self.
|
37
|
+
self.text_rect = pygame.FRect(0, 0, 0, 0)
|
21
38
|
# text surface (result of font.render)
|
22
|
-
self.
|
23
|
-
|
24
|
-
|
39
|
+
self.text_surface: pygame.Surface = pygame.Surface((0, 0))
|
40
|
+
self.do_caching: bool = False
|
41
|
+
|
42
|
+
self.show_text_outline: bool = False
|
43
|
+
|
44
|
+
self.is_italic: bool = False
|
45
|
+
|
46
|
+
self.is_bold: bool = False
|
47
|
+
|
48
|
+
self.is_underlined: bool = False
|
49
|
+
|
50
|
+
super().__init__((0, 0))
|
51
|
+
self.set_padding((10, 4))
|
25
52
|
self.set_debug_color("blue")
|
26
|
-
self.set_color("
|
53
|
+
self.set_color("gray50")
|
27
54
|
self.set_autoresize(True)
|
28
55
|
self.set_font(force=True)
|
29
|
-
self.set_text(text)
|
30
56
|
|
31
|
-
|
32
|
-
|
33
|
-
|
57
|
+
@staticmethod
|
58
|
+
def clear_cache():
|
59
|
+
Label._text_cache = {}
|
60
|
+
|
61
|
+
def __str__(self) -> str:
|
62
|
+
return f"Label({repr(self.text)})"
|
63
|
+
|
64
|
+
def enable_caching(self) -> Self:
|
65
|
+
self.do_caching = True
|
34
66
|
return self
|
35
67
|
|
36
|
-
def
|
37
|
-
|
68
|
+
def disable_caching(self) -> Self:
|
69
|
+
self.do_caching = False
|
70
|
+
return self
|
38
71
|
|
72
|
+
def set_text_color(self, color) -> Self:
|
73
|
+
self.text_color = color
|
74
|
+
self.dirty_surface = True
|
75
|
+
return self
|
39
76
|
|
40
|
-
def
|
41
|
-
|
42
|
-
|
77
|
+
def set_italic(self, value: bool) -> Self:
|
78
|
+
if value == self.is_italic:
|
79
|
+
return self
|
80
|
+
self.is_italic = value
|
81
|
+
if self.autoresize_h or self.autoresize_w:
|
82
|
+
self.dirty_shape = True
|
83
|
+
else:
|
84
|
+
self.dirty_surface = True
|
85
|
+
return self
|
43
86
|
|
44
|
-
def
|
45
|
-
if
|
46
|
-
|
47
|
-
self.
|
48
|
-
self.
|
87
|
+
def set_bold(self, value: bool) -> Self:
|
88
|
+
if value == self.is_bold:
|
89
|
+
return self
|
90
|
+
self.is_bold = value
|
91
|
+
if self.autoresize_h or self.autoresize_w:
|
92
|
+
self.dirty_shape = True
|
93
|
+
else:
|
94
|
+
self.dirty_surface = True
|
49
95
|
return self
|
50
96
|
|
51
|
-
def
|
52
|
-
|
53
|
-
|
54
|
-
self.
|
55
|
-
self.
|
56
|
-
self.build()
|
97
|
+
def set_underlined(self, value: bool) -> Self:
|
98
|
+
if value == self.is_underlined:
|
99
|
+
return self
|
100
|
+
self.is_underlined = value
|
101
|
+
self.dirty_surface = True
|
57
102
|
return self
|
58
103
|
|
59
|
-
def
|
60
|
-
|
104
|
+
def set_text_outline_mask_size(self,size:tuple[int,int])->Self:
|
105
|
+
old_size = self._text_outline_mask.get_size()
|
106
|
+
m = [[self._text_outline_mask.get_at((x,y)) for x in range(min(old_size[0],size[0]))] for y in range(min(old_size[1],size[1]))]
|
107
|
+
self._text_outline_mask = pygame.Mask(size, fill=True)
|
108
|
+
self.set_text_outline_matrix(m)
|
109
|
+
return self
|
61
110
|
|
62
|
-
def
|
63
|
-
|
111
|
+
def set_text_outline_matrix(self, matrix: list[list[0 | 1]]) -> Self:
|
112
|
+
if matrix is None:
|
113
|
+
matrix = [[0 for _ in range(3)] for _ in range(3)]
|
114
|
+
for y in range(3):
|
115
|
+
for x in range(3):
|
116
|
+
self._text_outline_mask.set_at((x, y), matrix[2 - y][2 - x])
|
117
|
+
self.dirty_shape = True
|
118
|
+
return self
|
64
119
|
|
65
|
-
def
|
66
|
-
self.
|
67
|
-
self.
|
120
|
+
def set_text_outline_color(self, color) -> Self:
|
121
|
+
self.text_outline_color = color
|
122
|
+
self.dirty_surface = True
|
68
123
|
return self
|
69
124
|
|
70
|
-
def
|
71
|
-
|
72
|
-
self.
|
73
|
-
self.build()
|
125
|
+
def enable_text_outline(self) -> Self:
|
126
|
+
self.show_text_outline = True
|
127
|
+
self.dirty_shape = True
|
74
128
|
return self
|
75
|
-
|
76
|
-
def get_text(self)->str:
|
77
|
-
return self._text
|
78
129
|
|
130
|
+
def disable_text_outline(self) -> Self:
|
131
|
+
self.show_text_outline = False
|
132
|
+
self.dirty_shape = True
|
133
|
+
return self
|
79
134
|
|
80
|
-
def
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
135
|
+
def set_alignment(self, alignment: bf.alignment) -> Self:
|
136
|
+
self.alignment = alignment
|
137
|
+
self.dirty_surface = True
|
138
|
+
return self
|
139
|
+
|
140
|
+
def set_auto_wraplength(self, val: bool) -> Self:
|
141
|
+
self.auto_wraplength = val
|
142
|
+
if self.autoresize_h or self.autoresize_w:
|
143
|
+
self.dirty_shape = True
|
144
|
+
else:
|
145
|
+
self.dirty_surface = True
|
146
|
+
return self
|
147
|
+
|
148
|
+
def get_debug_outlines(self):
|
149
|
+
if self.visible:
|
150
|
+
offset = self._get_outline_offset() if self.show_text_outline else (0,0)
|
151
|
+
yield (self.text_rect.move(self.rect.x - offset[0],self.rect.y - offset[1]), "purple")
|
152
|
+
yield from super().get_debug_outlines()
|
153
|
+
|
154
|
+
def set_font(self, font_name: str = None, force: bool = False) -> Self:
|
155
|
+
if font_name == self.font_name and not force:
|
156
|
+
return self
|
157
|
+
self.font_name = font_name
|
158
|
+
self.font_object = bf.FontManager().get_font(self.font_name, self.text_size)
|
159
|
+
if self.autoresize_h or self.autoresize_w:
|
160
|
+
self.dirty_shape = True
|
161
|
+
else:
|
162
|
+
self.dirty_surface = True
|
163
|
+
return self
|
164
|
+
|
165
|
+
def set_text_size(self, text_size: int) -> Self:
|
166
|
+
text_size = round(text_size / 2) * 2
|
167
|
+
if text_size == self.text_size:
|
168
|
+
return self
|
169
|
+
self.text_size = text_size
|
170
|
+
self.font_object = bf.FontManager().get_font(self.font_name, self.text_size)
|
171
|
+
if self.autoresize_h or self.autoresize_w:
|
172
|
+
self.dirty_shape = True
|
173
|
+
return self
|
174
|
+
|
175
|
+
def get_text_size(self) -> int:
|
176
|
+
return self.text_size
|
177
|
+
|
178
|
+
def is_antialias(self) -> bool:
|
179
|
+
return self.antialias
|
180
|
+
|
181
|
+
def set_antialias(self, value: bool) -> Self:
|
182
|
+
self.antialias = value
|
183
|
+
self.dirty_surface = True
|
184
|
+
return self
|
185
|
+
|
186
|
+
def set_text(self, text: str) -> Self:
|
187
|
+
if text == self.text:
|
188
|
+
return self
|
189
|
+
self.text = text
|
190
|
+
self.dirty_shape = True
|
191
|
+
return self
|
192
|
+
|
193
|
+
def get_min_required_size(self) -> tuple[float, float]:
|
194
|
+
if not (self.autoresize_w or self.autoresize_h):
|
195
|
+
return self.rect.size
|
196
|
+
if not self.text_rect:
|
197
|
+
self.text_rect.size = self._get_text_rect_required_size()
|
198
|
+
res = self.inflate_rect_by_padding((0, 0, *self.text_rect.size)).size
|
199
|
+
|
200
|
+
return res
|
201
|
+
return res[0] if self.autoresize_w else self.rect.w, (
|
202
|
+
res[1] if self.autoresize_h else self.rect.h
|
91
203
|
)
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
204
|
+
|
205
|
+
def get_text(self) -> str:
|
206
|
+
return self.text
|
207
|
+
|
208
|
+
def _render_font(self, params: dict) -> pygame.Surface:
|
209
|
+
key = tuple(params.values())
|
210
|
+
|
211
|
+
cached_value = Label._text_cache.get(key, None)
|
212
|
+
|
213
|
+
if self.draw_mode == bf.drawMode.SOLID:
|
214
|
+
if cached_value is None:
|
215
|
+
params.pop("font_name")
|
216
|
+
|
217
|
+
# save old settings
|
218
|
+
old_italic = self.font_object.get_italic()
|
219
|
+
old_bold = self.font_object.get_bold()
|
220
|
+
old_underline = self.font_object.get_underline()
|
221
|
+
|
222
|
+
# setup font
|
223
|
+
self.font_object.set_italic(self.is_italic)
|
224
|
+
self.font_object.set_bold(self.is_bold)
|
225
|
+
self.font_object.set_underline(self.is_underlined)
|
226
|
+
|
227
|
+
surf = self.font_object.render(**params)
|
228
|
+
|
229
|
+
# reset font
|
230
|
+
self.font_object.set_italic(old_italic)
|
231
|
+
self.font_object.set_bold(old_bold)
|
232
|
+
self.font_object.set_underline(old_underline)
|
233
|
+
|
234
|
+
if self.do_caching:
|
235
|
+
Label._text_cache[key] = surf
|
236
|
+
else:
|
237
|
+
surf = cached_value
|
238
|
+
else:
|
239
|
+
params.pop("font_name")
|
240
|
+
surf = self.font_object.render(**params)
|
241
|
+
|
242
|
+
return surf
|
243
|
+
def _get_text_rect_required_size(self):
|
244
|
+
font_height = self.font_object.get_linesize()
|
245
|
+
if not self.text:
|
246
|
+
# font_height = self.font_object.get_ascent() - self.font_object.get_ascent()
|
247
|
+
size = (0,font_height)
|
248
|
+
else:
|
249
|
+
tmp_text = self.text
|
250
|
+
if self.text.endswith('\n'):
|
251
|
+
tmp_text+=" "
|
252
|
+
params = {
|
253
|
+
"font_name": self.font_object.name,
|
254
|
+
"text": tmp_text,
|
255
|
+
"antialias": self.antialias,
|
256
|
+
"color": self.text_color,
|
257
|
+
"bgcolor": None, # if (self.has_alpha_color() or self.draw_mode == bf.drawMode.TEXTURED) else self.color,
|
258
|
+
"wraplength": int(self.get_padded_width()) if self.auto_wraplength and not self.autoresize_w else 0,
|
259
|
+
}
|
260
|
+
|
261
|
+
size = self._render_font(params).get_size()
|
262
|
+
size = size[0],max(font_height,size[1])
|
263
|
+
s = self._get_outline_offset() if self.show_text_outline else (0,0)
|
264
|
+
return size[0] + s[0]*2, size[1] + s[1]*2
|
265
|
+
|
266
|
+
def _build_layout(self) -> None:
|
267
|
+
|
268
|
+
self.text_rect.size = self._get_text_rect_required_size()
|
269
|
+
# self.text_rect.w = ceil(self.text_rect.w)
|
270
|
+
# self.text_rect.h = ceil(self.text_rect.h)
|
271
|
+
|
272
|
+
if self.autoresize_h or self.autoresize_w:
|
273
|
+
target_rect = self.inflate_rect_by_padding((0, 0, *self.text_rect.size))
|
274
|
+
if not self.autoresize_w:
|
275
|
+
target_rect.w = self.rect.w
|
276
|
+
if not self.autoresize_h:
|
277
|
+
target_rect.h = self.rect.h
|
278
|
+
if self.rect.size != target_rect.size:
|
279
|
+
self.set_size(target_rect.size)
|
280
|
+
self.build()
|
101
281
|
return
|
102
|
-
self.
|
103
|
-
self.
|
104
|
-
|
105
|
-
|
282
|
+
offset = self._get_outline_offset() if self.show_text_outline else (0,0)
|
283
|
+
padded = self.get_padded_rect().move(-self.rect.x + offset[0], -self.rect.y + offset[1])
|
284
|
+
self.align_text(self.text_rect, padded, self.alignment)
|
285
|
+
|
286
|
+
def _get_outline_offset(self)->tuple[int,int]:
|
287
|
+
mask_size = self._text_outline_mask.get_size()
|
288
|
+
return mask_size[0]//2,mask_size[1]//2
|
289
|
+
|
290
|
+
def _paint_text(self) -> None:
|
291
|
+
if self.font_object is None:
|
292
|
+
print(f"No font for widget with text : '{self}' :(")
|
293
|
+
return
|
294
|
+
|
295
|
+
params = {
|
296
|
+
"font_name": self.font_object.name,
|
297
|
+
"text": self.text,
|
298
|
+
"antialias": self.antialias,
|
299
|
+
"color": self.text_color,
|
300
|
+
"bgcolor": None, # if (self.has_alpha_color() or self.draw_mode == bf.drawMode.TEXTURED) else self.color,
|
301
|
+
"wraplength": int(self.get_padded_width()) if self.auto_wraplength and not self.autoresize_w else 0,
|
302
|
+
}
|
303
|
+
|
304
|
+
self.text_surface = self._render_font(params)
|
305
|
+
|
306
|
+
if self.show_text_outline:
|
307
|
+
self.text_outline_surface = (
|
308
|
+
pygame.mask.from_surface(self.text_surface)
|
309
|
+
.convolve(self._text_outline_mask)
|
310
|
+
.to_surface(setcolor=self.text_outline_color, unsetcolor=(0, 0, 0, 0))
|
311
|
+
)
|
312
|
+
|
313
|
+
l = []
|
314
|
+
outline_offset = self._get_outline_offset() if self.show_text_outline else (0,0)
|
315
|
+
|
316
|
+
if self.show_text_outline:
|
317
|
+
l.append(
|
318
|
+
(self.text_outline_surface,
|
319
|
+
(self.text_rect.x - outline_offset[0],self.text_rect.y - outline_offset[1]))
|
320
|
+
)
|
321
|
+
l.append(
|
322
|
+
(self.text_surface, self.text_rect)
|
323
|
+
)
|
324
|
+
self.surface.fblits(l)
|
325
|
+
|
326
|
+
def align_text(
|
327
|
+
self, text_rect: pygame.FRect, area: pygame.FRect, alignment: bf.alignment
|
328
|
+
):
|
329
|
+
if alignment == bf.alignment.LEFT:
|
330
|
+
alignment = bf.alignment.MIDLEFT
|
331
|
+
elif alignment == bf.alignment.MIDRIGHT:
|
332
|
+
alignment = bf.alignment.MIDRIGHT
|
333
|
+
|
334
|
+
pos = area.__getattribute__(alignment.value)
|
335
|
+
text_rect.__setattr__(alignment.value, pos)
|
336
|
+
text_rect.y = ceil(text_rect.y)
|
337
|
+
|
338
|
+
def build(self) -> None:
|
106
339
|
super().build()
|
107
|
-
if not self._font_object:return
|
108
|
-
self._build_text()
|
109
340
|
self._build_layout()
|
110
341
|
|
342
|
+
def paint(self) -> None:
|
343
|
+
super().paint()
|
344
|
+
if self.font_object:
|
345
|
+
self._paint_text()
|