batframework 1.0.9a7__py3-none-any.whl → 1.0.9a9__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 +20 -11
- batFramework/action.py +1 -1
- batFramework/animatedSprite.py +47 -116
- batFramework/animation.py +30 -5
- batFramework/audioManager.py +8 -5
- batFramework/baseScene.py +240 -0
- batFramework/camera.py +4 -0
- batFramework/constants.py +6 -2
- batFramework/cutscene.py +221 -21
- batFramework/cutsceneManager.py +5 -2
- batFramework/drawable.py +7 -5
- batFramework/easingController.py +10 -11
- batFramework/entity.py +21 -2
- batFramework/enums.py +48 -33
- batFramework/gui/__init__.py +6 -3
- batFramework/gui/animatedLabel.py +10 -2
- batFramework/gui/button.py +4 -31
- batFramework/gui/clickableWidget.py +63 -50
- batFramework/gui/constraints/constraints.py +212 -136
- batFramework/gui/container.py +77 -58
- batFramework/gui/debugger.py +12 -17
- batFramework/gui/draggableWidget.py +21 -17
- batFramework/gui/image.py +3 -10
- batFramework/gui/indicator.py +56 -1
- batFramework/gui/interactiveWidget.py +127 -108
- batFramework/gui/label.py +73 -64
- batFramework/gui/layout.py +286 -445
- batFramework/gui/meter.py +42 -20
- batFramework/gui/radioButton.py +20 -69
- batFramework/gui/root.py +99 -29
- batFramework/gui/selector.py +250 -0
- batFramework/gui/shape.py +13 -5
- batFramework/gui/slider.py +262 -107
- batFramework/gui/syncedVar.py +49 -0
- batFramework/gui/textInput.py +46 -22
- batFramework/gui/toggle.py +70 -52
- batFramework/gui/tooltip.py +30 -0
- batFramework/gui/widget.py +222 -135
- batFramework/manager.py +7 -8
- batFramework/particle.py +4 -1
- batFramework/propertyEaser.py +79 -0
- batFramework/renderGroup.py +17 -50
- batFramework/resourceManager.py +43 -13
- batFramework/scene.py +15 -335
- batFramework/sceneLayer.py +138 -0
- batFramework/sceneManager.py +31 -36
- batFramework/scrollingSprite.py +8 -3
- batFramework/sprite.py +1 -1
- batFramework/templates/__init__.py +1 -2
- batFramework/templates/controller.py +97 -0
- batFramework/timeManager.py +76 -22
- batFramework/transition.py +37 -103
- batFramework/utils.py +125 -66
- {batframework-1.0.9a7.dist-info → batframework-1.0.9a9.dist-info}/METADATA +24 -3
- batframework-1.0.9a9.dist-info/RECORD +67 -0
- {batframework-1.0.9a7.dist-info → batframework-1.0.9a9.dist-info}/WHEEL +1 -1
- batFramework/character.py +0 -27
- batFramework/templates/character.py +0 -43
- batFramework/templates/states.py +0 -166
- batframework-1.0.9a7.dist-info/RECORD +0 -63
- /batframework-1.0.9a7.dist-info/LICENCE → /batframework-1.0.9a9.dist-info/LICENSE +0 -0
- {batframework-1.0.9a7.dist-info → batframework-1.0.9a9.dist-info}/top_level.txt +0 -0
@@ -18,10 +18,11 @@ def children_has_focus(widget)->bool:
|
|
18
18
|
|
19
19
|
|
20
20
|
class InteractiveWidget(Widget):
|
21
|
+
__focus_effect_cache = {}
|
21
22
|
def __init__(self, *args, **kwargs) -> None:
|
22
23
|
self.is_focused: bool = False
|
23
24
|
self.is_hovered: bool = False
|
24
|
-
self.is_clicked_down: bool = False
|
25
|
+
self.is_clicked_down: list[bool] = [False]*5
|
25
26
|
self.focused_index = 0
|
26
27
|
self.focusable = True
|
27
28
|
super().__init__(*args, **kwargs)
|
@@ -56,7 +57,7 @@ class InteractiveWidget(Widget):
|
|
56
57
|
|
57
58
|
def on_get_focus(self) -> None:
|
58
59
|
self.is_focused = True
|
59
|
-
if isinstance(self.parent,bf.Container):
|
60
|
+
if isinstance(self.parent,bf.gui.Container):
|
60
61
|
self.parent.layout.scroll_to_widget(self)
|
61
62
|
self.do_on_get_focus()
|
62
63
|
|
@@ -64,98 +65,127 @@ class InteractiveWidget(Widget):
|
|
64
65
|
self.is_focused = False
|
65
66
|
self.do_on_lose_focus()
|
66
67
|
|
67
|
-
|
68
|
-
|
69
|
-
if previous_widget != self and self.visible:
|
70
|
-
if (
|
71
|
-
isinstance(self, InteractiveWidget)
|
72
|
-
and not isinstance(self, bf.Container)
|
73
|
-
and self.allow_focus_to_self()
|
74
|
-
):
|
75
|
-
self.focus_next_sibling()
|
76
|
-
return
|
77
|
-
i_children = [
|
78
|
-
c
|
79
|
-
for c in self.children
|
80
|
-
if isinstance(c, InteractiveWidget) and c.visible
|
81
|
-
]
|
82
|
-
if i_children:
|
83
|
-
index = i_children.index(previous_widget)
|
84
|
-
if index < len(i_children) - 1:
|
85
|
-
|
86
|
-
i_children[index + 1].get_focus()
|
87
|
-
return
|
88
|
-
|
89
|
-
if self.parent and isinstance(self.parent,InteractiveWidget):
|
90
|
-
self.parent.focus_next_tab(self)
|
68
|
+
|
91
69
|
|
92
|
-
def
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
):
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
70
|
+
def get_interactive_widgets(self):
|
71
|
+
"""Retrieve all interactive widgets in the tree, in depth-first order."""
|
72
|
+
widgets = []
|
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)
|
115
121
|
|
116
|
-
def
|
117
|
-
|
118
|
-
|
119
|
-
|
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()
|
120
128
|
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
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()
|
126
135
|
|
127
|
-
return self.do_on_key_down(key)
|
128
136
|
|
129
|
-
|
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)
|
130
143
|
|
131
144
|
def on_key_up(self, key) -> bool:
|
145
|
+
"""
|
146
|
+
return True to stop event propagation
|
147
|
+
"""
|
132
148
|
return self.do_on_key_up(key)
|
133
149
|
|
134
|
-
def do_on_key_down(self, key) -> bool:
|
135
|
-
return False
|
136
|
-
|
137
|
-
def do_on_key_up(self, key) -> bool:
|
138
|
-
return False
|
139
|
-
|
140
150
|
def do_on_get_focus(self) -> None:
|
141
151
|
pass
|
142
152
|
|
143
153
|
def do_on_lose_focus(self) -> None:
|
144
154
|
pass
|
145
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
|
+
|
146
168
|
def on_click_down(self, button: int) -> bool:
|
147
|
-
|
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
|
148
174
|
return self.do_on_click_down(button)
|
149
175
|
|
150
176
|
def on_click_up(self, button: int) -> bool:
|
151
|
-
|
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
|
152
182
|
return self.do_on_click_up(button)
|
153
183
|
|
154
|
-
def do_on_click_down(self, button: int) ->
|
155
|
-
return
|
184
|
+
def do_on_click_down(self, button: int) -> None:
|
185
|
+
return
|
156
186
|
|
157
|
-
def do_on_click_up(self, button: int) ->
|
158
|
-
return
|
187
|
+
def do_on_click_up(self, button: int) -> None:
|
188
|
+
return
|
159
189
|
|
160
190
|
def on_enter(self) -> None:
|
161
191
|
self.is_hovered = True
|
@@ -163,7 +193,7 @@ class InteractiveWidget(Widget):
|
|
163
193
|
|
164
194
|
def on_exit(self) -> None:
|
165
195
|
self.is_hovered = False
|
166
|
-
self.is_clicked_down = False
|
196
|
+
self.is_clicked_down = [False]*5
|
167
197
|
self.do_on_exit()
|
168
198
|
|
169
199
|
def do_on_enter(self) -> None:
|
@@ -182,39 +212,28 @@ class InteractiveWidget(Widget):
|
|
182
212
|
pass
|
183
213
|
|
184
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)
|
185
239
|
|
186
|
-
proportion = 16
|
187
|
-
surface = pygame.Surface(self.rect.inflate(proportion,proportion).size)
|
188
|
-
surface.fill("black")
|
189
|
-
|
190
|
-
delta = proportion*0.75 - int(proportion * cos(pygame.time.get_ticks() / 100) /4)
|
191
|
-
delta = delta//2 * 2
|
192
|
-
# Base rect centered in tmp surface
|
193
|
-
base_rect = surface.get_frect()
|
194
|
-
|
195
|
-
# Expanded white rectangle for border effect
|
196
|
-
white_rect = base_rect.inflate(-delta,-delta)
|
197
|
-
white_rect.center = base_rect.center
|
198
|
-
pygame.draw.rect(surface, "white", white_rect, 2, *self.border_radius)
|
199
|
-
|
200
|
-
# Black cutout rectangles to create the effect around the edges
|
201
|
-
black_rect_1 = white_rect.copy()
|
202
|
-
black_rect_1.w -= proportion
|
203
|
-
black_rect_1.centerx = white_rect.centerx
|
204
|
-
|
205
|
-
black_rect_2 = white_rect.copy()
|
206
|
-
black_rect_2.h -= proportion
|
207
|
-
black_rect_2.centery = white_rect.centery
|
208
|
-
|
209
|
-
surface.fill("black", black_rect_1)
|
210
|
-
surface.fill("black", black_rect_2)
|
211
|
-
|
212
|
-
base_rect.center = self.rect.center
|
213
|
-
|
214
|
-
surface.set_colorkey("black")
|
215
|
-
|
216
|
-
# Blit the tmp surface onto the camera surface with adjusted position
|
217
|
-
camera.surface.blit(
|
218
|
-
surface,
|
219
|
-
base_rect.move(-camera.rect.x, -camera.rect.y),
|
220
|
-
)
|
batFramework/gui/label.py
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
import batFramework as bf
|
2
2
|
import pygame
|
3
3
|
from .shape import Shape
|
4
|
-
from typing import Self
|
4
|
+
from typing import Literal, Self,Union
|
5
5
|
from math import ceil
|
6
6
|
|
7
7
|
class Label(Shape):
|
@@ -10,6 +10,10 @@ class Label(Shape):
|
|
10
10
|
def __init__(self, text: str = "") -> None:
|
11
11
|
self.text = text
|
12
12
|
|
13
|
+
# Allows scrolling the text
|
14
|
+
self.allow_scroll : bool = True
|
15
|
+
|
16
|
+
# Scroll variable
|
13
17
|
self.scroll :pygame.Vector2 = pygame.Vector2(0,0)
|
14
18
|
|
15
19
|
self.resized_flag: bool = False
|
@@ -31,6 +35,7 @@ class Label(Shape):
|
|
31
35
|
|
32
36
|
self._text_outline_mask = pygame.Mask((3, 3), fill=True)
|
33
37
|
|
38
|
+
self.line_alignment = pygame.FONT_LEFT
|
34
39
|
# font name (given when loaded by utils) to use for the text
|
35
40
|
self.font_name = None
|
36
41
|
# reference to the font object
|
@@ -59,11 +64,23 @@ class Label(Shape):
|
|
59
64
|
def __str__(self) -> str:
|
60
65
|
return f"Label({repr(self.text)})"
|
61
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
|
72
|
+
return self
|
73
|
+
|
62
74
|
def set_text_color(self, color) -> Self:
|
63
75
|
self.text_color = color
|
64
76
|
self.dirty_surface = True
|
65
77
|
return self
|
66
78
|
|
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
|
+
|
67
84
|
def set_italic(self, value: bool) -> Self:
|
68
85
|
if value == self.is_italic:
|
69
86
|
return self
|
@@ -136,10 +153,12 @@ class Label(Shape):
|
|
136
153
|
return self
|
137
154
|
|
138
155
|
def get_debug_outlines(self):
|
139
|
-
if self.visible:
|
140
|
-
offset = self._get_outline_offset() if self.show_text_outline else (0,0)
|
141
|
-
yield (self.text_rect.move(self.rect.x - offset[0] - self.scroll.x,self.rect.y - offset[1] - self.scroll.y), "purple")
|
142
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")
|
143
162
|
|
144
163
|
def set_font(self, font_name: str = None, force: bool = False) -> Self:
|
145
164
|
if font_name == self.font_name and not force:
|
@@ -153,13 +172,12 @@ class Label(Shape):
|
|
153
172
|
return self
|
154
173
|
|
155
174
|
def set_text_size(self, text_size: int) -> Self:
|
156
|
-
text_size =
|
175
|
+
text_size = (text_size // 2) * 2
|
157
176
|
if text_size == self.text_size:
|
158
177
|
return self
|
159
178
|
self.text_size = text_size
|
160
179
|
self.font_object = bf.FontManager().get_font(self.font_name, self.text_size)
|
161
|
-
|
162
|
-
self.dirty_shape = True
|
180
|
+
self.dirty_shape = True
|
163
181
|
return self
|
164
182
|
|
165
183
|
def get_text_size(self) -> int:
|
@@ -181,15 +199,9 @@ class Label(Shape):
|
|
181
199
|
return self
|
182
200
|
|
183
201
|
def get_min_required_size(self) -> tuple[float, float]:
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
self.text_rect.size = self._get_text_rect_required_size()
|
188
|
-
res = self.inflate_rect_by_padding((0, 0, *self.text_rect.size)).size
|
189
|
-
|
190
|
-
return res[0] if self.autoresize_w else self.rect.w, (
|
191
|
-
res[1] if self.autoresize_h else self.rect.h
|
192
|
-
)
|
202
|
+
return self.expand_rect_with_padding(
|
203
|
+
(0, 0, *self._get_text_rect_required_size())
|
204
|
+
).size
|
193
205
|
|
194
206
|
def get_text(self) -> str:
|
195
207
|
return self.text
|
@@ -203,28 +215,32 @@ class Label(Shape):
|
|
203
215
|
old_italic = self.font_object.get_italic()
|
204
216
|
old_bold = self.font_object.get_bold()
|
205
217
|
old_underline = self.font_object.get_underline()
|
206
|
-
|
218
|
+
old_align = self.font_object.align
|
207
219
|
# setup font
|
208
220
|
self.font_object.set_italic(self.is_italic)
|
209
221
|
self.font_object.set_bold(self.is_bold)
|
210
222
|
self.font_object.set_underline(self.is_underlined)
|
211
|
-
|
223
|
+
self.font_object.align = self.line_alignment
|
212
224
|
surf = self.font_object.render(**params)
|
213
225
|
|
214
226
|
# reset font
|
215
227
|
self.font_object.set_italic(old_italic)
|
216
228
|
self.font_object.set_bold(old_bold)
|
217
229
|
self.font_object.set_underline(old_underline)
|
230
|
+
self.font_object.align = old_align
|
218
231
|
else:
|
219
232
|
params.pop("font_name")
|
220
233
|
surf = self.font_object.render(**params)
|
221
234
|
|
222
235
|
return surf
|
223
|
-
|
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
|
+
|
224
241
|
def _get_text_rect_required_size(self):
|
225
|
-
font_height = self.font_object.
|
242
|
+
font_height = self.font_object.get_ascent() - self.font_object.get_descent()
|
226
243
|
if not self.text:
|
227
|
-
# font_height = self.font_object.get_ascent() - self.font_object.get_ascent()
|
228
244
|
size = (0,font_height)
|
229
245
|
else:
|
230
246
|
tmp_text = self.text
|
@@ -236,49 +252,43 @@ class Label(Shape):
|
|
236
252
|
"antialias": self.antialias,
|
237
253
|
"color": self.text_color,
|
238
254
|
"bgcolor": None, # if (self.has_alpha_color() or self.draw_mode == bf.drawMode.TEXTURED) else self.color,
|
239
|
-
"wraplength": int(self.
|
255
|
+
"wraplength": int(self.get_inner_width()) if self.auto_wraplength and not self.autoresize_w else 0,
|
240
256
|
}
|
241
257
|
|
242
258
|
size = self._render_font(params).get_size()
|
243
259
|
size = size[0],max(font_height,size[1])
|
260
|
+
|
261
|
+
# print(self.text,size)
|
244
262
|
s = self._get_outline_offset() if self.show_text_outline else (0,0)
|
245
263
|
return size[0] + s[0]*2, size[1] + s[1]*2
|
246
264
|
|
247
|
-
def _build_layout(self) ->
|
265
|
+
def _build_layout(self) -> bool:
|
266
|
+
ret = False
|
267
|
+
target_size = self.resolve_size(self.get_min_required_size())
|
248
268
|
|
249
|
-
|
250
|
-
|
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
|
251
274
|
|
252
|
-
|
253
|
-
|
254
|
-
if not self.autoresize_w:
|
255
|
-
target_rect.w = self.rect.w
|
256
|
-
if not self.autoresize_h:
|
257
|
-
target_rect.h = self.rect.h
|
258
|
-
if self.rect.size != target_rect.size:
|
259
|
-
# print("Size not good ! ",self.rect.size,target_rect.size,repr(self.text))
|
260
|
-
self.set_size(target_rect.size)
|
261
|
-
self.apply_updates()
|
262
|
-
|
263
|
-
offset = self._get_outline_offset() if self.show_text_outline else (0,0)
|
264
|
-
padded = self.get_padded_rect().move(-self.rect.x + offset[0], -self.rect.y + offset[1])
|
275
|
+
self.text_rect.size = self._get_text_rect_required_size()
|
276
|
+
padded = self.get_local_inner_rect()
|
265
277
|
self.align_text(self.text_rect, padded, self.alignment)
|
266
|
-
|
267
|
-
def _get_outline_offset(self)->tuple[int,int]:
|
268
|
-
mask_size = self._text_outline_mask.get_size()
|
269
|
-
return mask_size[0]//2,mask_size[1]//2
|
278
|
+
return ret
|
270
279
|
|
271
280
|
def _paint_text(self) -> None:
|
272
281
|
if self.font_object is None:
|
273
282
|
print(f"No font for widget with text : '{self}' :(")
|
274
283
|
return
|
284
|
+
wrap = int(self.get_inner_width()) if self.auto_wraplength and not self.autoresize_w else 0
|
275
285
|
params = {
|
276
286
|
"font_name": self.font_object.name,
|
277
287
|
"text": self.text,
|
278
288
|
"antialias": self.antialias,
|
279
289
|
"color": self.text_color,
|
280
|
-
"bgcolor": None,
|
281
|
-
"wraplength":
|
290
|
+
"bgcolor": None,
|
291
|
+
"wraplength": wrap,
|
282
292
|
}
|
283
293
|
|
284
294
|
self.text_surface = self._render_font(params)
|
@@ -289,27 +299,22 @@ class Label(Shape):
|
|
289
299
|
.to_surface(setcolor=self.text_outline_color, unsetcolor=(0, 0, 0, 0))
|
290
300
|
)
|
291
301
|
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
)
|
302
|
-
l.append(
|
303
|
-
(self.text_surface, self.text_rect.move(-self.scroll))
|
304
|
-
)
|
302
|
+
outline_offset = list(self._get_outline_offset())
|
303
|
+
outline_offset[0]-=self.scroll.x
|
304
|
+
outline_offset[1]-=self.scroll.y
|
305
|
+
l = [
|
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))]
|
305
311
|
|
306
312
|
# clip surface
|
307
313
|
|
308
314
|
old = self.surface.get_clip()
|
309
|
-
self.surface.set_clip(self.
|
315
|
+
self.surface.set_clip(self.get_local_inner_rect())
|
310
316
|
self.surface.fblits(l)
|
311
317
|
self.surface.set_clip(old)
|
312
|
-
|
313
318
|
|
314
319
|
def align_text(
|
315
320
|
self, text_rect: pygame.FRect, area: pygame.FRect, alignment: bf.alignment
|
@@ -323,12 +328,16 @@ class Label(Shape):
|
|
323
328
|
text_rect.__setattr__(alignment.value, pos)
|
324
329
|
text_rect.y = ceil(text_rect.y)
|
325
330
|
|
326
|
-
|
327
|
-
|
328
|
-
|
331
|
+
def build(self) -> bool:
|
332
|
+
"""
|
333
|
+
return True if size changed
|
334
|
+
"""
|
335
|
+
|
336
|
+
size_changed = self._build_layout()
|
329
337
|
super().build()
|
330
|
-
|
331
|
-
|
338
|
+
return size_changed
|
339
|
+
|
340
|
+
|
332
341
|
def paint(self) -> None:
|
333
342
|
super().paint()
|
334
343
|
if self.font_object:
|