batframework 1.0.9a10__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.
- batFramework/__init__.py +52 -76
- batFramework/action.py +99 -126
- batFramework/actionContainer.py +9 -53
- batFramework/animatedSprite.py +114 -56
- batFramework/audioManager.py +36 -82
- batFramework/camera.py +69 -263
- batFramework/constants.py +53 -29
- batFramework/cutscene.py +109 -243
- batFramework/cutsceneBlocks.py +176 -0
- batFramework/debugger.py +48 -0
- batFramework/dynamicEntity.py +9 -16
- batFramework/easing.py +71 -0
- batFramework/entity.py +85 -92
- batFramework/gui/__init__.py +3 -14
- batFramework/gui/button.py +78 -12
- batFramework/gui/constraints.py +204 -0
- batFramework/gui/container.py +31 -183
- batFramework/gui/debugger.py +43 -126
- batFramework/gui/frame.py +19 -0
- batFramework/gui/image.py +20 -55
- batFramework/gui/indicator.py +22 -95
- batFramework/gui/interactiveWidget.py +12 -229
- batFramework/gui/label.py +77 -311
- batFramework/gui/layout.py +66 -411
- batFramework/gui/root.py +35 -203
- batFramework/gui/shape.py +57 -247
- batFramework/gui/toggle.py +48 -114
- batFramework/gui/widget.py +243 -457
- batFramework/manager.py +29 -113
- batFramework/particles.py +77 -0
- batFramework/scene.py +217 -22
- batFramework/sceneManager.py +129 -161
- batFramework/stateMachine.py +8 -11
- batFramework/time.py +75 -0
- batFramework/transition.py +124 -129
- batFramework/transitionManager.py +0 -0
- batFramework/triggerZone.py +4 -4
- batFramework/utils.py +144 -266
- {batframework-1.0.9a10.dist-info → batframework-1.1.0.dist-info}/METADATA +24 -22
- batframework-1.1.0.dist-info/RECORD +43 -0
- batFramework/animation.py +0 -77
- batFramework/baseScene.py +0 -240
- batFramework/cutsceneManager.py +0 -34
- batFramework/drawable.py +0 -77
- batFramework/easingController.py +0 -58
- batFramework/enums.py +0 -135
- batFramework/fontManager.py +0 -65
- batFramework/gui/animatedLabel.py +0 -89
- batFramework/gui/clickableWidget.py +0 -245
- batFramework/gui/constraints/__init__.py +0 -1
- batFramework/gui/constraints/constraints.py +0 -980
- batFramework/gui/draggableWidget.py +0 -44
- batFramework/gui/meter.py +0 -96
- batFramework/gui/radioButton.py +0 -35
- batFramework/gui/selector.py +0 -250
- batFramework/gui/slider.py +0 -397
- batFramework/gui/style.py +0 -10
- batFramework/gui/styleManager.py +0 -54
- batFramework/gui/syncedVar.py +0 -49
- batFramework/gui/textInput.py +0 -306
- batFramework/gui/tooltip.py +0 -30
- batFramework/particle.py +0 -118
- batFramework/propertyEaser.py +0 -79
- batFramework/renderGroup.py +0 -34
- batFramework/resourceManager.py +0 -130
- batFramework/sceneLayer.py +0 -138
- batFramework/scrollingSprite.py +0 -115
- batFramework/sprite.py +0 -51
- batFramework/templates/__init__.py +0 -1
- batFramework/templates/controller.py +0 -97
- batFramework/tileset.py +0 -46
- batFramework/timeManager.py +0 -213
- batframework-1.0.9a10.dist-info/RECORD +0 -67
- {batframework-1.0.9a10.dist-info → batframework-1.1.0.dist-info}/LICENSE +0 -0
- {batframework-1.0.9a10.dist-info → batframework-1.1.0.dist-info}/WHEEL +0 -0
- {batframework-1.0.9a10.dist-info → batframework-1.1.0.dist-info}/top_level.txt +0 -0
@@ -1,239 +1,22 @@
|
|
1
1
|
from .widget import Widget
|
2
|
-
from typing import Self
|
3
|
-
from typing import TYPE_CHECKING
|
4
|
-
import pygame
|
5
|
-
from math import cos,floor,ceil
|
6
|
-
|
7
|
-
if TYPE_CHECKING:
|
8
|
-
from .container import Container
|
9
|
-
import batFramework as bf
|
10
|
-
|
11
|
-
def children_has_focus(widget)->bool:
|
12
|
-
if isinstance(widget,InteractiveWidget) and widget.is_focused:
|
13
|
-
return True
|
14
|
-
for child in widget.children:
|
15
|
-
if children_has_focus(child):
|
16
|
-
return True
|
17
|
-
return False
|
18
|
-
|
19
2
|
|
20
3
|
class InteractiveWidget(Widget):
|
21
|
-
|
22
|
-
|
23
|
-
self.is_focused: bool = False
|
24
|
-
self.is_hovered: bool = False
|
25
|
-
self.is_clicked_down: list[bool] = [False]*5
|
26
|
-
self.focused_index = 0
|
4
|
+
def __init__(self,*args,**kwargs):
|
5
|
+
super().__init__(convert_alpha = True)
|
27
6
|
self.focusable = True
|
28
|
-
|
29
|
-
|
30
|
-
def set_focusable(self, value: bool) -> Self:
|
31
|
-
self.focusable = value
|
32
|
-
return self
|
33
|
-
|
34
|
-
def allow_focus_to_self(self) -> bool:
|
35
|
-
return self.visible
|
7
|
+
self.is_focused : bool = False
|
36
8
|
|
37
|
-
def get_focus(self)
|
38
|
-
if self.
|
39
|
-
|
40
|
-
if self.parent and isinstance(self.parent, InteractiveWidget):
|
41
|
-
self.parent.set_focused_child(self)
|
42
|
-
return True
|
43
|
-
return False
|
9
|
+
def get_focus(self)->bool:
|
10
|
+
if self.parent is None or not self.focusable: return False
|
11
|
+
self.get_root().focus_on(self)
|
44
12
|
|
45
|
-
def
|
46
|
-
if self.is_focused and ((r := self.get_root()) is not None):
|
47
|
-
r.focus_on(None)
|
48
|
-
return True
|
49
|
-
return False
|
50
|
-
|
51
|
-
def set_parent(self, parent: Widget) -> Self:
|
52
|
-
if parent is None and children_has_focus(self):
|
53
|
-
self.get_root().clear_focused()
|
54
|
-
# pass focus on
|
55
|
-
|
56
|
-
return super().set_parent(parent)
|
57
|
-
|
58
|
-
def on_get_focus(self) -> None:
|
13
|
+
def on_get_focus(self)->None:
|
59
14
|
self.is_focused = True
|
60
|
-
if isinstance(self.parent,bf.gui.Container):
|
61
|
-
self.parent.layout.scroll_to_widget(self)
|
62
|
-
self.do_on_get_focus()
|
63
15
|
|
64
|
-
def on_lose_focus(self)
|
16
|
+
def on_lose_focus(self)->None:
|
65
17
|
self.is_focused = False
|
66
|
-
self.do_on_lose_focus()
|
67
|
-
|
68
18
|
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
stack = [self]
|
74
|
-
while stack:
|
75
|
-
widget = stack.pop()
|
76
|
-
if isinstance(widget, InteractiveWidget) and widget.allow_focus_to_self():
|
77
|
-
widgets.append(widget)
|
78
|
-
stack.extend(reversed(widget.children)) # Add children in reverse for left-to-right traversal
|
79
|
-
return widgets
|
80
|
-
|
81
|
-
def find_next_widget(self, current):
|
82
|
-
"""Find the next interactive widget, considering parent and sibling relationships."""
|
83
|
-
if current.is_root:
|
84
|
-
return None # Root has no parent
|
85
|
-
|
86
|
-
siblings = current.parent.children
|
87
|
-
start_index = siblings.index(current)
|
88
|
-
good_index = -1
|
89
|
-
for i in range(start_index + 1, len(siblings)):
|
90
|
-
if isinstance(siblings[i], InteractiveWidget) and siblings[i].allow_focus_to_self():
|
91
|
-
good_index = i
|
92
|
-
break
|
93
|
-
if good_index >= 0:
|
94
|
-
# Not the last child, return the next sibling
|
95
|
-
return siblings[good_index]
|
96
|
-
else:
|
97
|
-
# Current is the last child, move to parent's next sibling
|
98
|
-
return self.find_next_widget(current.parent)
|
99
|
-
|
100
|
-
def find_prev_widget(self, current : "Widget"):
|
101
|
-
"""Find the previous interactive widget, considering parent and sibling relationships."""
|
102
|
-
if current.is_root:
|
103
|
-
return None # Root has no parent
|
104
|
-
|
105
|
-
# siblings = [c for c in current.parent.children if isinstance(c,InteractiveWidget) and c.allow_focus_to_self()]
|
106
|
-
siblings = current.parent.children
|
107
|
-
start_index = siblings.index(current)
|
108
|
-
good_index = -1
|
109
|
-
for i in range(start_index-1,-1,-1):
|
110
|
-
sibling = siblings[i]
|
111
|
-
if isinstance(sibling,InteractiveWidget):
|
112
|
-
if sibling.allow_focus_to_self():
|
113
|
-
good_index = i
|
114
|
-
break
|
115
|
-
if good_index >= 0:
|
116
|
-
# Not the first child, return the previous sibling
|
117
|
-
return siblings[good_index]
|
118
|
-
else:
|
119
|
-
# Current is the first child, move to parent's previous sibling
|
120
|
-
return self.find_prev_widget(current.parent)
|
121
|
-
|
122
|
-
def focus_next_tab(self, previous_widget):
|
123
|
-
"""Focus the next interactive widget."""
|
124
|
-
if previous_widget:
|
125
|
-
next_widget = self.find_next_widget(previous_widget)
|
126
|
-
if next_widget:
|
127
|
-
next_widget.get_focus()
|
128
|
-
|
129
|
-
def focus_prev_tab(self, previous_widget):
|
130
|
-
"""Focus the previous interactive widget."""
|
131
|
-
if previous_widget:
|
132
|
-
prev_widget = self.find_prev_widget(previous_widget)
|
133
|
-
if prev_widget:
|
134
|
-
prev_widget.get_focus()
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
def on_key_down(self, key) -> bool:
|
139
|
-
"""
|
140
|
-
return True to stop event propagation
|
141
|
-
"""
|
142
|
-
return self.do_on_key_down(key)
|
143
|
-
|
144
|
-
def on_key_up(self, key) -> bool:
|
145
|
-
"""
|
146
|
-
return True to stop event propagation
|
147
|
-
"""
|
148
|
-
return self.do_on_key_up(key)
|
149
|
-
|
150
|
-
def do_on_get_focus(self) -> None:
|
151
|
-
pass
|
152
|
-
|
153
|
-
def do_on_lose_focus(self) -> None:
|
154
|
-
pass
|
155
|
-
|
156
|
-
def do_on_key_down(self, key) -> bool:
|
157
|
-
"""
|
158
|
-
return True to stop event propagation
|
159
|
-
"""
|
160
|
-
return False
|
161
|
-
|
162
|
-
def do_on_key_up(self, key) -> bool:
|
163
|
-
"""
|
164
|
-
return True to stop event propagation
|
165
|
-
"""
|
166
|
-
return False
|
167
|
-
|
168
|
-
def on_click_down(self, button: int) -> bool:
|
169
|
-
"""
|
170
|
-
return True to stop event propagation
|
171
|
-
"""
|
172
|
-
if button < 1 or button > 5 : return False
|
173
|
-
self.is_clicked_down[button-1] = True
|
174
|
-
return self.do_on_click_down(button)
|
175
|
-
|
176
|
-
def on_click_up(self, button: int) -> bool:
|
177
|
-
"""
|
178
|
-
return True to stop event propagation
|
179
|
-
"""
|
180
|
-
if button < 1 or button > 5 : return False
|
181
|
-
self.is_clicked_down[button-1] = False
|
182
|
-
return self.do_on_click_up(button)
|
183
|
-
|
184
|
-
def do_on_click_down(self, button: int) -> None:
|
185
|
-
return
|
186
|
-
|
187
|
-
def do_on_click_up(self, button: int) -> None:
|
188
|
-
return
|
189
|
-
|
190
|
-
def on_enter(self) -> None:
|
191
|
-
self.is_hovered = True
|
192
|
-
self.do_on_enter()
|
193
|
-
|
194
|
-
def on_exit(self) -> None:
|
195
|
-
self.is_hovered = False
|
196
|
-
self.is_clicked_down = [False]*5
|
197
|
-
self.do_on_exit()
|
198
|
-
|
199
|
-
def do_on_enter(self) -> None:
|
200
|
-
pass
|
201
|
-
|
202
|
-
def do_on_exit(self) -> None:
|
203
|
-
pass
|
204
|
-
|
205
|
-
def on_mouse_motion(self, x, y) -> None:
|
206
|
-
self.do_on_mouse_motion(x, y)
|
207
|
-
|
208
|
-
def do_on_mouse_motion(self, x, y) -> None:
|
209
|
-
pass
|
210
|
-
|
211
|
-
def set_focused_child(self, child: "InteractiveWidget"):
|
212
|
-
pass
|
213
|
-
|
214
|
-
def draw_focused(self, camera: bf.Camera) -> None:
|
215
|
-
prop = 16
|
216
|
-
pulse = int(prop * 0.75 - (prop * cos(pygame.time.get_ticks() / 100) / 4))
|
217
|
-
delta = (pulse // 2) * 2 # ensure even
|
218
|
-
|
219
|
-
# Get rect in screen space, inflated for visual effect
|
220
|
-
screen_rect = camera.world_to_screen(self.rect.inflate(prop, prop))
|
221
|
-
|
222
|
-
# Shrink for inner pulsing border
|
223
|
-
inner = screen_rect.inflate(-delta, -delta)
|
224
|
-
inner.topleft = 0,0
|
225
|
-
inner.w = round(inner.w)
|
226
|
-
inner.h = round(inner.h)
|
227
|
-
|
228
|
-
surface = InteractiveWidget.__focus_effect_cache.get(inner.size)
|
229
|
-
if surface is None:
|
230
|
-
surface = pygame.Surface(inner.size)
|
231
|
-
InteractiveWidget.__focus_effect_cache[inner.size] = surface
|
232
|
-
|
233
|
-
surface.set_colorkey((0,0,0))
|
234
|
-
pygame.draw.rect(surface, "white", inner, 2, *self.border_radius)
|
235
|
-
pygame.draw.rect(surface, "black", inner.inflate(-1 * min(16,inner.w*0.75),0), 2)
|
236
|
-
pygame.draw.rect(surface, "black", inner.inflate(0,-1 * min(16,inner.h*0.75)), 2)
|
237
|
-
inner.center = screen_rect.center
|
238
|
-
camera.surface.blit(surface,inner)
|
239
|
-
|
19
|
+
def lose_focus(self)->bool:
|
20
|
+
if self.is_focused and self.parent is not None:
|
21
|
+
self.get_root().focus_on(None)
|
22
|
+
|
batFramework/gui/label.py
CHANGED
@@ -1,344 +1,110 @@
|
|
1
1
|
import batFramework as bf
|
2
2
|
import pygame
|
3
3
|
from .shape import Shape
|
4
|
-
from typing import
|
5
|
-
from math import ceil
|
4
|
+
from typing import Self
|
6
5
|
|
7
6
|
class Label(Shape):
|
8
|
-
|
9
|
-
|
10
|
-
def __init__(self, text: str = "") -> None:
|
11
|
-
self.text = text
|
12
|
-
|
13
|
-
# Allows scrolling the text
|
14
|
-
self.allow_scroll : bool = True
|
15
|
-
|
16
|
-
# Scroll variable
|
17
|
-
self.scroll :pygame.Vector2 = pygame.Vector2(0,0)
|
18
|
-
|
19
|
-
self.resized_flag: bool = False
|
20
|
-
|
7
|
+
def __init__(self,text:str) -> None:
|
8
|
+
self._text = ""
|
21
9
|
# Enable/Disable antialiasing
|
22
|
-
self.
|
23
|
-
|
24
|
-
self.
|
25
|
-
|
26
|
-
self.
|
27
|
-
|
28
|
-
self.alignment: bf.alignment = bf.alignment.CENTER
|
29
|
-
|
30
|
-
self.text_color: tuple[int, int, int] | str = "black"
|
31
|
-
|
32
|
-
self.text_outline_color: tuple[int, int, int] | str = "gray50"
|
33
|
-
|
34
|
-
self.text_outline_surface: pygame.Surface = None
|
35
|
-
|
36
|
-
self._text_outline_mask = pygame.Mask((3, 3), fill=True)
|
37
|
-
|
38
|
-
self.line_alignment = pygame.FONT_LEFT
|
10
|
+
self._antialias : bool = True
|
11
|
+
|
12
|
+
self._text_size = bf.const.DEFAULT_TEXT_SIZE
|
13
|
+
|
14
|
+
self._text_color : tuple[int,int,int]|str = "black"
|
39
15
|
# font name (given when loaded by utils) to use for the text
|
40
|
-
self.
|
16
|
+
self._font_name = None
|
41
17
|
# reference to the font object
|
42
|
-
self.
|
18
|
+
self._font_object = None
|
43
19
|
# Rect containing the text of the label
|
44
|
-
self.
|
20
|
+
self._text_rect = None
|
45
21
|
# text surface (result of font.render)
|
46
|
-
self.
|
47
|
-
|
48
|
-
self.
|
49
|
-
|
50
|
-
self.is_italic: bool = False
|
51
|
-
|
52
|
-
self.is_bold: bool = False
|
53
|
-
|
54
|
-
self.is_underlined: bool = False
|
55
|
-
|
56
|
-
super().__init__((0, 0))
|
57
|
-
self.set_padding((10, 4))
|
22
|
+
self._text_surface : pygame.Surface | None= None
|
23
|
+
super().__init__(width=0,height=0)
|
24
|
+
self.set_padding((10,4))
|
58
25
|
self.set_debug_color("blue")
|
59
|
-
self.set_color("
|
26
|
+
self.set_color("white")
|
60
27
|
self.set_autoresize(True)
|
61
28
|
self.set_font(force=True)
|
29
|
+
self.set_text(text)
|
62
30
|
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
def set_allow_scroll(self, value:bool)->Self:
|
69
|
-
if self.allow_scroll == value: return self
|
70
|
-
self.allow_scroll = value
|
71
|
-
self.dirty_shape = True
|
31
|
+
def set_text_color(self,color)->Self:
|
32
|
+
self._text_color = color
|
33
|
+
self.build()
|
72
34
|
return self
|
73
35
|
|
74
|
-
def
|
75
|
-
self.
|
76
|
-
self.dirty_surface = True
|
77
|
-
return self
|
36
|
+
def to_string_id(self)->str:
|
37
|
+
return f"Label({self._text})"
|
78
38
|
|
79
|
-
def set_line_alignment(self, alignment: Union[Literal["left"], Literal["right"], Literal["center"]]) -> Self:
|
80
|
-
self.line_alignment = alignment
|
81
|
-
self.dirty_surface = True
|
82
|
-
return self
|
83
39
|
|
84
|
-
def
|
85
|
-
|
86
|
-
|
87
|
-
self.is_italic = value
|
88
|
-
if self.autoresize_h or self.autoresize_w:
|
89
|
-
self.dirty_shape = True
|
90
|
-
else:
|
91
|
-
self.dirty_surface = True
|
92
|
-
return self
|
40
|
+
def get_bounding_box(self):
|
41
|
+
yield from super().get_bounding_box()
|
42
|
+
if self._text_rect : yield self._text_rect.move(*self.rect.topleft)
|
93
43
|
|
94
|
-
def
|
95
|
-
if
|
96
|
-
|
97
|
-
self.
|
98
|
-
|
99
|
-
self.dirty_shape = True
|
100
|
-
else:
|
101
|
-
self.dirty_surface = True
|
44
|
+
def set_font(self,font_name:str=None,force:bool = False)-> "Label":
|
45
|
+
if font_name == self._font_name and not force: return self
|
46
|
+
self._font_name = font_name
|
47
|
+
self._font_object = bf.utils.get_font(self._font_name,self._text_size)
|
48
|
+
self.build()
|
102
49
|
return self
|
103
50
|
|
104
|
-
def
|
105
|
-
|
106
|
-
|
107
|
-
self.
|
108
|
-
self.
|
51
|
+
def set_text_size(self,text_size:int) -> "Label":
|
52
|
+
text_size = round(text_size/2) * 2
|
53
|
+
if text_size == self._text_size : return self
|
54
|
+
self._text_size = text_size
|
55
|
+
self._font_object = bf.utils.get_font(self._font_name,self._text_size)
|
56
|
+
self.build()
|
109
57
|
return self
|
110
58
|
|
111
|
-
def
|
112
|
-
|
113
|
-
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]))]
|
114
|
-
self._text_outline_mask = pygame.Mask(size, fill=True)
|
115
|
-
self.set_text_outline_matrix(m)
|
116
|
-
return self
|
117
|
-
|
118
|
-
def set_text_outline_matrix(self, matrix: list[list[0 | 1]]) -> Self:
|
119
|
-
if matrix is None:
|
120
|
-
matrix = [[0 for _ in range(3)] for _ in range(3)]
|
121
|
-
for y in range(3):
|
122
|
-
for x in range(3):
|
123
|
-
self._text_outline_mask.set_at((x, y), matrix[2 - y][2 - x])
|
124
|
-
self.dirty_shape = True
|
125
|
-
return self
|
126
|
-
|
127
|
-
def set_text_outline_color(self, color) -> Self:
|
128
|
-
self.text_outline_color = color
|
129
|
-
self.dirty_surface = True
|
130
|
-
return self
|
131
|
-
|
132
|
-
def enable_text_outline(self) -> Self:
|
133
|
-
self.show_text_outline = True
|
134
|
-
self.dirty_shape = True
|
135
|
-
return self
|
59
|
+
def get_text_size(self)-> int:
|
60
|
+
return self._text_size
|
136
61
|
|
137
|
-
def
|
138
|
-
self.
|
139
|
-
self.dirty_shape = True
|
140
|
-
return self
|
62
|
+
def is_antialias(self)->bool:
|
63
|
+
return self._antialias
|
141
64
|
|
142
|
-
def
|
143
|
-
self.
|
144
|
-
self.
|
65
|
+
def set_antialias(self,value:bool)->"Label":
|
66
|
+
self._antialias = value
|
67
|
+
self.build()
|
145
68
|
return self
|
146
69
|
|
147
|
-
def
|
148
|
-
self.
|
149
|
-
|
150
|
-
|
151
|
-
else:
|
152
|
-
self.dirty_surface = True
|
70
|
+
def set_text(self,text:str) -> "Label":
|
71
|
+
if text == self._text : return self
|
72
|
+
self._text = text
|
73
|
+
self.build()
|
153
74
|
return self
|
154
|
-
|
155
|
-
def get_debug_outlines(self):
|
156
|
-
yield from super().get_debug_outlines()
|
157
|
-
if self.visible:
|
158
|
-
yield (self.text_rect.move(self.rect.x - self.scroll.x,self.rect.y - self.scroll.y), "purple")
|
159
|
-
|
160
|
-
# offset = self._get_outline_offset() if self.show_text_outline else (0,0)
|
161
|
-
# yield (self.text_rect.move(self.rect.x - offset[0] - self.scroll.x,self.rect.y - offset[1] - self.scroll.y), "purple")
|
162
|
-
|
163
|
-
def set_font(self, font_name: str = None, force: bool = False) -> Self:
|
164
|
-
if font_name == self.font_name and not force:
|
165
|
-
return self
|
166
|
-
self.font_name = font_name
|
167
|
-
self.font_object = bf.FontManager().get_font(self.font_name, self.text_size)
|
168
|
-
if self.autoresize_h or self.autoresize_w:
|
169
|
-
self.dirty_shape = True
|
170
|
-
else:
|
171
|
-
self.dirty_surface = True
|
172
|
-
return self
|
173
|
-
|
174
|
-
def set_text_size(self, text_size: int) -> Self:
|
175
|
-
text_size = (text_size // 2) * 2
|
176
|
-
if text_size == self.text_size:
|
177
|
-
return self
|
178
|
-
self.text_size = text_size
|
179
|
-
self.font_object = bf.FontManager().get_font(self.font_name, self.text_size)
|
180
|
-
self.dirty_shape = True
|
181
|
-
return self
|
182
|
-
|
183
|
-
def get_text_size(self) -> int:
|
184
|
-
return self.text_size
|
185
|
-
|
186
|
-
def is_antialias(self) -> bool:
|
187
|
-
return self.antialias
|
188
|
-
|
189
|
-
def set_antialias(self, value: bool) -> Self:
|
190
|
-
self.antialias = value
|
191
|
-
self.dirty_surface = True
|
192
|
-
return self
|
193
|
-
|
194
|
-
def set_text(self, text: str) -> Self:
|
195
|
-
if text == self.text:
|
196
|
-
return self
|
197
|
-
self.text = text
|
198
|
-
self.dirty_shape = True
|
199
|
-
return self
|
200
|
-
|
201
|
-
def get_min_required_size(self) -> tuple[float, float]:
|
202
|
-
return self.expand_rect_with_padding(
|
203
|
-
(0, 0, *self._get_text_rect_required_size())
|
204
|
-
).size
|
205
|
-
|
206
|
-
def get_text(self) -> str:
|
207
|
-
return self.text
|
208
|
-
|
209
|
-
def _render_font(self, params: dict) -> pygame.Surface:
|
210
|
-
|
211
|
-
if self.draw_mode == bf.drawMode.SOLID:
|
212
|
-
params.pop("font_name")
|
213
|
-
|
214
|
-
# save old settings
|
215
|
-
old_italic = self.font_object.get_italic()
|
216
|
-
old_bold = self.font_object.get_bold()
|
217
|
-
old_underline = self.font_object.get_underline()
|
218
|
-
old_align = self.font_object.align
|
219
|
-
# setup font
|
220
|
-
self.font_object.set_italic(self.is_italic)
|
221
|
-
self.font_object.set_bold(self.is_bold)
|
222
|
-
self.font_object.set_underline(self.is_underlined)
|
223
|
-
self.font_object.align = self.line_alignment
|
224
|
-
surf = self.font_object.render(**params)
|
225
|
-
|
226
|
-
# reset font
|
227
|
-
self.font_object.set_italic(old_italic)
|
228
|
-
self.font_object.set_bold(old_bold)
|
229
|
-
self.font_object.set_underline(old_underline)
|
230
|
-
self.font_object.align = old_align
|
231
|
-
else:
|
232
|
-
params.pop("font_name")
|
233
|
-
surf = self.font_object.render(**params)
|
234
|
-
|
235
|
-
return surf
|
236
|
-
|
237
|
-
def _get_outline_offset(self)->tuple[int,int]:
|
238
|
-
mask_size = self._text_outline_mask.get_size()
|
239
|
-
return mask_size[0]//2,mask_size[1]//2
|
240
75
|
|
241
|
-
def
|
242
|
-
|
243
|
-
if not self.text:
|
244
|
-
size = (0,font_height)
|
245
|
-
else:
|
246
|
-
tmp_text = self.text
|
247
|
-
if self.text.endswith('\n'):
|
248
|
-
tmp_text+=" "
|
249
|
-
params = {
|
250
|
-
"font_name": self.font_object.name,
|
251
|
-
"text": tmp_text,
|
252
|
-
"antialias": self.antialias,
|
253
|
-
"color": self.text_color,
|
254
|
-
"bgcolor": None, # if (self.has_alpha_color() or self.draw_mode == bf.drawMode.TEXTURED) else self.color,
|
255
|
-
"wraplength": int(self.get_inner_width()) if self.auto_wraplength and not self.autoresize_w else 0,
|
256
|
-
}
|
257
|
-
|
258
|
-
size = self._render_font(params).get_size()
|
259
|
-
size = size[0],max(font_height,size[1])
|
260
|
-
|
261
|
-
# print(self.text,size)
|
262
|
-
s = self._get_outline_offset() if self.show_text_outline else (0,0)
|
263
|
-
return size[0] + s[0]*2, size[1] + s[1]*2
|
264
|
-
|
265
|
-
def _build_layout(self) -> bool:
|
266
|
-
ret = False
|
267
|
-
target_size = self.resolve_size(self.get_min_required_size())
|
76
|
+
def get_text(self)->str:
|
77
|
+
return self._text
|
268
78
|
|
269
|
-
if self.rect.size != target_size :
|
270
|
-
self.set_size(target_size)
|
271
|
-
ret = True
|
272
|
-
# self.apply_post_updates(skip_draw=True)
|
273
|
-
# return True
|
274
79
|
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
return ret
|
279
|
-
|
280
|
-
def _paint_text(self) -> None:
|
281
|
-
if self.font_object is None:
|
282
|
-
print(f"No font for widget with text : '{self}' :(")
|
80
|
+
def _build_text(self)-> None:
|
81
|
+
if self._font_object is None:
|
82
|
+
print("No font :(")
|
283
83
|
return
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
if self.
|
296
|
-
self.
|
297
|
-
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
(self.text_outline_surface,(self.text_rect.x - self.scroll.x,self.text_rect.y - self.scroll.y)),
|
307
|
-
(self.text_surface, self.text_rect.move(*outline_offset))
|
308
|
-
]
|
309
|
-
else:
|
310
|
-
l = [(self.text_surface, self.text_rect.move(-self.scroll))]
|
311
|
-
|
312
|
-
# clip surface
|
313
|
-
|
314
|
-
old = self.surface.get_clip()
|
315
|
-
self.surface.set_clip(self.get_local_inner_rect())
|
316
|
-
self.surface.fblits(l)
|
317
|
-
self.surface.set_clip(old)
|
318
|
-
|
319
|
-
def align_text(
|
320
|
-
self, text_rect: pygame.FRect, area: pygame.FRect, alignment: bf.alignment
|
321
|
-
):
|
322
|
-
if alignment == bf.alignment.LEFT:
|
323
|
-
alignment = bf.alignment.MIDLEFT
|
324
|
-
elif alignment == bf.alignment.MIDRIGHT:
|
325
|
-
alignment = bf.alignment.MIDRIGHT
|
326
|
-
|
327
|
-
pos = area.__getattribute__(alignment.value)
|
328
|
-
text_rect.__setattr__(alignment.value, pos)
|
329
|
-
text_rect.y = ceil(text_rect.y)
|
330
|
-
|
331
|
-
def build(self) -> bool:
|
332
|
-
"""
|
333
|
-
return True if size changed
|
334
|
-
"""
|
335
|
-
|
336
|
-
size_changed = self._build_layout()
|
84
|
+
# render(text, antialias, color, bgcolor=None, wraplength=0) -> Surface
|
85
|
+
self._text_surface = self._font_object.render(
|
86
|
+
text = self._text,
|
87
|
+
antialias = self._antialias,
|
88
|
+
color = self._text_color,
|
89
|
+
bgcolor = self._color,
|
90
|
+
wraplength = 0
|
91
|
+
)
|
92
|
+
self._text_rect = self._text_surface.get_frect()
|
93
|
+
|
94
|
+
def _build_layout(self)->None:
|
95
|
+
if self.autoresize:
|
96
|
+
if self.rect.size != self.inflate_rect_by_padding(self._text_rect).size :
|
97
|
+
self.set_size(
|
98
|
+
self._text_rect.w + self.padding[0]+self.padding[2],
|
99
|
+
self._text_rect.h + self.padding[1]+self.padding[3]
|
100
|
+
)
|
101
|
+
return
|
102
|
+
self._text_rect.center = self.get_content_rect_rel().center
|
103
|
+
self.surface.blit(self._text_surface,self._text_rect)
|
104
|
+
|
105
|
+
def build(self)->None:
|
337
106
|
super().build()
|
338
|
-
return
|
339
|
-
|
340
|
-
|
341
|
-
|
342
|
-
super().paint()
|
343
|
-
if self.font_object:
|
344
|
-
self._paint_text()
|
107
|
+
if not self._font_object:return
|
108
|
+
self._build_text()
|
109
|
+
self._build_layout()
|
110
|
+
|