batframework 1.0.8a14__py3-none-any.whl → 1.0.9a2__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 +9 -13
- batFramework/camera.py +1 -1
- batFramework/constants.py +6 -0
- batFramework/cutscene.py +3 -5
- batFramework/drawable.py +1 -1
- batFramework/dynamicEntity.py +2 -4
- batFramework/entity.py +15 -28
- batFramework/enums.py +1 -0
- batFramework/fontManager.py +3 -3
- batFramework/gui/__init__.py +2 -2
- batFramework/gui/{dialogueBox.py → animatedLabel.py} +18 -36
- batFramework/gui/button.py +30 -0
- batFramework/gui/clickableWidget.py +6 -1
- batFramework/gui/constraints/constraints.py +90 -1
- batFramework/gui/container.py +84 -93
- batFramework/gui/indicator.py +3 -2
- batFramework/gui/interactiveWidget.py +43 -24
- batFramework/gui/label.py +25 -9
- batFramework/gui/layout.py +378 -42
- batFramework/gui/root.py +2 -3
- batFramework/gui/shape.py +2 -0
- batFramework/gui/slider.py +1 -0
- batFramework/gui/textInput.py +115 -78
- batFramework/gui/toggle.py +2 -4
- batFramework/gui/widget.py +49 -37
- batFramework/manager.py +42 -31
- batFramework/sceneManager.py +2 -12
- batFramework/scrollingSprite.py +1 -1
- batFramework/utils.py +0 -1
- {batframework-1.0.8a14.dist-info → batframework-1.0.9a2.dist-info}/METADATA +1 -1
- batframework-1.0.9a2.dist-info/RECORD +63 -0
- {batframework-1.0.8a14.dist-info → batframework-1.0.9a2.dist-info}/WHEEL +1 -1
- batframework-1.0.8a14.dist-info/RECORD +0 -63
- {batframework-1.0.8a14.dist-info → batframework-1.0.9a2.dist-info}/LICENCE +0 -0
- {batframework-1.0.8a14.dist-info → batframework-1.0.9a2.dist-info}/top_level.txt +0 -0
batFramework/gui/container.py
CHANGED
@@ -11,181 +11,172 @@ from pygame.math import Vector2
|
|
11
11
|
class Container(Shape, InteractiveWidget):
|
12
12
|
def __init__(self, layout: Layout = None, *children: Widget) -> None:
|
13
13
|
super().__init__()
|
14
|
-
self.
|
14
|
+
self.dirty_layout: bool = False
|
15
15
|
self.set_debug_color("green")
|
16
|
-
self.layout
|
17
|
-
self.scroll = Vector2(0, 0)
|
18
|
-
if not self.layout:
|
19
|
-
self.layout = Column()
|
16
|
+
self.layout = layout if layout else Column()
|
20
17
|
self.layout.set_parent(self)
|
18
|
+
self.scroll = Vector2(0, 0)
|
21
19
|
self.add(*children)
|
22
20
|
|
23
21
|
def __str__(self) -> str:
|
24
22
|
return f"Container({self.uid},{len(self.children)})"
|
25
23
|
|
26
24
|
def get_min_required_size(self):
|
27
|
-
if self.layout
|
28
|
-
return self.layout.get_auto_size()
|
29
|
-
return self.rect.size
|
25
|
+
return self.layout.get_auto_size() if self.layout else self.rect.size
|
30
26
|
|
31
27
|
def reset_scroll(self) -> Self:
|
28
|
+
if self.scroll == (0,0):
|
29
|
+
return self
|
32
30
|
self.scroll.update(0, 0)
|
33
|
-
self.
|
31
|
+
self.dirty_layout = True
|
34
32
|
return self
|
35
33
|
|
36
34
|
def set_scroll(self, value: tuple) -> Self:
|
35
|
+
if (self.scroll.x,self.scroll.y) == value:
|
36
|
+
return self
|
37
37
|
self.scroll.update(value)
|
38
|
-
self.
|
38
|
+
self.clamp_scroll()
|
39
|
+
self.dirty_layout = True
|
39
40
|
return self
|
40
41
|
|
41
42
|
def scrollX_by(self, x: float | int) -> Self:
|
43
|
+
if x == 0:
|
44
|
+
return self
|
42
45
|
self.scroll.x += x
|
43
|
-
self.
|
46
|
+
self.clamp_scroll()
|
47
|
+
self.dirty_layout = True
|
44
48
|
return self
|
45
49
|
|
46
50
|
def scrollY_by(self, y: float | int) -> Self:
|
51
|
+
if y == 0:
|
52
|
+
return self
|
47
53
|
self.scroll.y += y
|
48
|
-
self.
|
54
|
+
self.clamp_scroll()
|
55
|
+
self.dirty_layout = True
|
49
56
|
return self
|
50
57
|
|
51
58
|
def scroll_by(self, value: tuple[float | int, float | int]) -> Self:
|
59
|
+
if value[0] == 0 and value[1] == 0:
|
60
|
+
return self
|
52
61
|
self.scroll += value
|
53
|
-
self.
|
62
|
+
self.clamp_scroll()
|
63
|
+
self.dirty_layout = True
|
54
64
|
return self
|
55
65
|
|
56
66
|
def clamp_scroll(self) -> Self:
|
57
67
|
if not self.children:
|
58
|
-
return
|
68
|
+
return self
|
59
69
|
r = self.get_padded_rect()
|
60
|
-
size = self.children[0].rect.unionall(self.children[1:]).size
|
70
|
+
size = self.children[0].rect.unionall([child.rect for child in self.children[1:]]).size
|
61
71
|
|
62
|
-
# Calculate the maximum scroll values
|
63
72
|
max_scroll_x = max(0, size[0] - r.width)
|
64
73
|
max_scroll_y = max(0, size[1] - r.height)
|
65
74
|
|
66
|
-
# Clamp the scroll values
|
67
75
|
self.scroll.x = max(0, min(self.scroll.x, max_scroll_x))
|
68
76
|
self.scroll.y = max(0, min(self.scroll.y, max_scroll_y))
|
69
|
-
|
70
|
-
self.dirty_children = True
|
77
|
+
self.dirty_layout = True
|
71
78
|
return self
|
72
79
|
|
73
80
|
def set_layout(self, layout: Layout) -> Self:
|
74
81
|
tmp = self.layout
|
75
82
|
self.layout = layout
|
76
83
|
if self.layout != tmp:
|
77
|
-
|
84
|
+
tmp.set_parent(None)
|
85
|
+
self.layout.set_parent(self)
|
86
|
+
self.dirty_layout = True
|
78
87
|
return self
|
79
88
|
|
80
89
|
def get_interactive_children(self) -> list[InteractiveWidget]:
|
81
|
-
return [
|
82
|
-
child
|
83
|
-
for child in self.children
|
84
|
-
if isinstance(child, InteractiveWidget) and child.allow_focus_to_self()
|
85
|
-
]
|
86
|
-
|
87
|
-
def focus_next_child(self) -> None:
|
88
|
-
self.layout.focus_next_child()
|
89
|
-
|
90
|
-
def focus_prev_child(self) -> None:
|
91
|
-
self.layout.focus_prev_child()
|
90
|
+
return [child for child in self.children if isinstance(child, InteractiveWidget) and not isinstance(child,Container) and child.allow_focus_to_self()]
|
92
91
|
|
93
92
|
def clear_children(self) -> None:
|
94
93
|
self.children.clear()
|
95
|
-
self.
|
94
|
+
self.dirty_layout = True
|
96
95
|
|
97
96
|
def add(self, *child: Widget) -> Self:
|
98
97
|
super().add(*child)
|
99
|
-
self.
|
98
|
+
self.dirty_shape = True
|
99
|
+
self.clamp_scroll()
|
100
100
|
return self
|
101
101
|
|
102
102
|
def remove(self, *child: Widget) -> Self:
|
103
103
|
super().remove(*child)
|
104
|
-
self.
|
104
|
+
self.dirty_shape = True
|
105
|
+
self.clamp_scroll()
|
105
106
|
return self
|
106
107
|
|
107
|
-
def resolve_constraints(self) -> None:
|
108
|
-
super().resolve_constraints()
|
109
|
-
|
110
108
|
def top_at(self, x: float | int, y: float | int) -> "None|Widget":
|
111
109
|
if self.visible and self.rect.collidepoint(x, y):
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
return r
|
110
|
+
for child in reversed(self.children):
|
111
|
+
result = child.top_at(x, y)
|
112
|
+
if result is not None:
|
113
|
+
return result
|
117
114
|
return self
|
118
115
|
return None
|
119
116
|
|
120
117
|
def get_focus(self) -> bool:
|
121
|
-
|
122
|
-
if not res:
|
118
|
+
if not super().get_focus():
|
123
119
|
return False
|
124
|
-
|
125
|
-
if not
|
120
|
+
interactive_children = self.get_interactive_children()
|
121
|
+
if not interactive_children:
|
126
122
|
return True
|
127
|
-
self.focused_index = min(self.focused_index, len(
|
128
|
-
return
|
123
|
+
self.focused_index = min(self.focused_index, len(interactive_children) - 1)
|
124
|
+
return interactive_children[self.focused_index].get_focus()
|
129
125
|
|
130
|
-
def do_handle_event(self, event):
|
131
|
-
self.
|
126
|
+
def do_handle_event(self, event) -> None:
|
127
|
+
if any(child.is_focused for child in self.get_interactive_children()):
|
128
|
+
self.layout.handle_event(event)
|
132
129
|
|
133
130
|
def set_focused_child(self, child: InteractiveWidget) -> bool:
|
134
|
-
|
131
|
+
interactive_children = self.get_interactive_children()
|
135
132
|
try:
|
136
|
-
|
133
|
+
index = interactive_children.index(child)
|
134
|
+
self.focused_index = index
|
135
|
+
return True
|
137
136
|
except ValueError:
|
138
137
|
return False
|
139
|
-
if i >= 0:
|
140
|
-
self.focused_index = i
|
141
|
-
return True
|
142
|
-
return False
|
143
138
|
|
144
139
|
def allow_focus_to_self(self) -> bool:
|
145
|
-
return
|
140
|
+
return bool(self.get_interactive_children()) and self.visible
|
146
141
|
|
147
|
-
|
148
|
-
|
142
|
+
|
143
|
+
def apply_updates(self):
|
144
|
+
if any(child.dirty_shape for child in self.children):
|
145
|
+
self.dirty_layout = True # Mark layout as dirty if any child changed size
|
146
|
+
|
147
|
+
if self.dirty_constraints:
|
148
|
+
self.resolve_constraints() # Finalize positioning based on size
|
149
|
+
|
150
|
+
# Step 1: Build shape if needed
|
149
151
|
if self.dirty_shape:
|
150
|
-
self.
|
151
|
-
self.
|
152
|
-
self.dirty_surface = True
|
153
|
-
self.
|
152
|
+
self.build() # Finalize size of the container
|
153
|
+
self.dirty_shape = False
|
154
|
+
self.dirty_surface = True # Mark surface for repaint
|
155
|
+
self.dirty_layout = True # Mark layout for arrangement
|
156
|
+
# Flag all children to update constraints after size is finalized
|
154
157
|
for child in self.children:
|
155
158
|
child.dirty_constraints = True
|
156
|
-
self.dirty_shape = False
|
157
159
|
|
160
|
+
for child in self.children:
|
161
|
+
child.apply_updates()
|
162
|
+
|
163
|
+
# Step 2: Arrange layout if marked as dirty
|
164
|
+
if self.dirty_layout:
|
165
|
+
self.layout.arrange()
|
166
|
+
self.dirty_surface = True
|
167
|
+
self.dirty_layout = False
|
168
|
+
# Constraints may need to adjust based on the layout change
|
169
|
+
self.dirty_constraints = True
|
170
|
+
|
171
|
+
# Step 3: Resolve constraints now that size and layout are finalized
|
158
172
|
if self.dirty_constraints:
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
if not self.dirty_children:
|
164
|
-
self.dirty_children = any(c.dirty_shape for c in self.children)
|
165
|
-
if self.dirty_children:
|
166
|
-
if self.layout:
|
167
|
-
self.layout.arrange()
|
168
|
-
self.dirty_children = False
|
169
|
-
|
170
|
-
if constraints_down:
|
171
|
-
self.visit(lambda c: c.resolve_constraints())
|
173
|
+
self.resolve_constraints() # Finalize positioning based on size
|
174
|
+
for child in self.children:
|
175
|
+
child.dirty_constraints = True # Children inherit updated positioning
|
176
|
+
self.dirty_constraints = False
|
172
177
|
|
178
|
+
# Step 4: Paint the surface if marked as dirty
|
173
179
|
if self.dirty_surface:
|
180
|
+
# print("PAINT !!")
|
174
181
|
self.paint()
|
175
182
|
self.dirty_surface = False
|
176
|
-
|
177
|
-
bf.Drawable.draw(self, camera)
|
178
|
-
|
179
|
-
if self.clip_children:
|
180
|
-
new_clip = camera.world_to_screen(self.get_padded_rect())
|
181
|
-
old_clip = camera.surface.get_clip()
|
182
|
-
new_clip = new_clip.clip(old_clip)
|
183
|
-
camera.surface.set_clip(new_clip)
|
184
|
-
# Draw children with adjusted positions
|
185
|
-
_ = [
|
186
|
-
child.draw(camera)
|
187
|
-
for child in sorted(self.children, key=lambda c: c.render_order)
|
188
|
-
]
|
189
|
-
|
190
|
-
if self.clip_children:
|
191
|
-
camera.surface.set_clip(old_clip)
|
batFramework/gui/indicator.py
CHANGED
@@ -29,11 +29,11 @@ class Indicator(Shape):
|
|
29
29
|
|
30
30
|
class ToggleIndicator(Indicator):
|
31
31
|
def __init__(self, default_value: bool) -> None:
|
32
|
+
super().__init__((20, 20))
|
32
33
|
self.value: bool = default_value
|
33
34
|
self.callback = lambda val: self.set_color("green" if val else "red")
|
34
|
-
super().__init__((20, 20))
|
35
35
|
self.set_value(default_value)
|
36
|
-
|
36
|
+
self.callback(default_value)
|
37
37
|
# TODO aspect ratio would be good right about here
|
38
38
|
# self.add_constraint(ConstraintAspectRatio(1))
|
39
39
|
|
@@ -55,3 +55,4 @@ class ToggleIndicator(Indicator):
|
|
55
55
|
if r is self:
|
56
56
|
return None
|
57
57
|
return r
|
58
|
+
|
@@ -2,13 +2,13 @@ from .widget import Widget
|
|
2
2
|
from typing import Self
|
3
3
|
from typing import TYPE_CHECKING
|
4
4
|
import pygame
|
5
|
-
from math import cos
|
5
|
+
from math import cos,floor,ceil
|
6
6
|
|
7
7
|
if TYPE_CHECKING:
|
8
8
|
from .container import Container
|
9
9
|
import batFramework as bf
|
10
10
|
|
11
|
-
def children_has_focus(widget):
|
11
|
+
def children_has_focus(widget)->bool:
|
12
12
|
if isinstance(widget,InteractiveWidget) and widget.is_focused:
|
13
13
|
return True
|
14
14
|
for child in widget.children:
|
@@ -56,6 +56,8 @@ class InteractiveWidget(Widget):
|
|
56
56
|
|
57
57
|
def on_get_focus(self) -> None:
|
58
58
|
self.is_focused = True
|
59
|
+
if isinstance(self.parent,bf.Container):
|
60
|
+
self.parent.layout.scroll_to_widget(self)
|
59
61
|
self.do_on_get_focus()
|
60
62
|
|
61
63
|
def on_lose_focus(self) -> None:
|
@@ -84,7 +86,7 @@ class InteractiveWidget(Widget):
|
|
84
86
|
i_children[index + 1].get_focus()
|
85
87
|
return
|
86
88
|
|
87
|
-
if self.parent:
|
89
|
+
if self.parent and isinstance(self.parent,InteractiveWidget):
|
88
90
|
self.parent.focus_next_tab(self)
|
89
91
|
|
90
92
|
def focus_prev_tab(self, previous_widget):
|
@@ -108,30 +110,18 @@ class InteractiveWidget(Widget):
|
|
108
110
|
i_children[index - 1].get_focus()
|
109
111
|
return
|
110
112
|
|
111
|
-
if self.parent:
|
113
|
+
if self.parent and isinstance(self.parent,InteractiveWidget):
|
112
114
|
self.parent.focus_prev_tab(self)
|
113
115
|
|
114
|
-
def focus_next_sibling(self) -> None:
|
115
|
-
if isinstance(self.parent, bf.Container):
|
116
|
-
self.parent.focus_next_child()
|
117
|
-
|
118
|
-
def focus_prev_sibling(self) -> None:
|
119
|
-
if isinstance(self.parent, bf.Container):
|
120
|
-
self.parent.focus_prev_child()
|
121
|
-
|
122
116
|
def on_key_down(self, key) -> bool:
|
123
|
-
if key == pygame.
|
124
|
-
self.focus_next_sibling()
|
125
|
-
elif key == pygame.K_UP:
|
126
|
-
self.focus_prev_sibling()
|
127
|
-
elif key == pygame.K_TAB and self.parent:
|
117
|
+
if key == pygame.K_TAB and self.parent:
|
128
118
|
keys = pygame.key.get_pressed()
|
129
119
|
if keys[pygame.K_LSHIFT] or keys[pygame.K_RSHIFT]:
|
130
120
|
|
131
121
|
self.focus_prev_tab(self)
|
132
122
|
else:
|
133
123
|
self.focus_next_tab(self)
|
134
|
-
|
124
|
+
return True
|
135
125
|
else:
|
136
126
|
|
137
127
|
return self.do_on_key_down(key)
|
@@ -192,10 +182,39 @@ class InteractiveWidget(Widget):
|
|
192
182
|
pass
|
193
183
|
|
194
184
|
def draw_focused(self, camera: bf.Camera) -> None:
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
185
|
+
|
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),
|
201
220
|
)
|
batFramework/gui/label.py
CHANGED
@@ -10,12 +10,14 @@ class Label(Shape):
|
|
10
10
|
def __init__(self, text: str = "") -> None:
|
11
11
|
self.text = text
|
12
12
|
|
13
|
+
self.scroll :pygame.Vector2 = pygame.Vector2(0,0)
|
14
|
+
|
13
15
|
self.resized_flag: bool = False
|
14
16
|
|
15
17
|
# Enable/Disable antialiasing
|
16
18
|
self.antialias: bool = bf.FontManager().DEFAULT_ANTIALIAS
|
17
19
|
|
18
|
-
self.text_size = bf.FontManager().
|
20
|
+
self.text_size = bf.FontManager().DEFAULT_FONT_SIZE
|
19
21
|
|
20
22
|
self.auto_wraplength: bool = False
|
21
23
|
|
@@ -53,6 +55,7 @@ class Label(Shape):
|
|
53
55
|
self.set_autoresize(True)
|
54
56
|
self.set_font(force=True)
|
55
57
|
|
58
|
+
|
56
59
|
def __str__(self) -> str:
|
57
60
|
return f"Label({repr(self.text)})"
|
58
61
|
|
@@ -135,7 +138,7 @@ class Label(Shape):
|
|
135
138
|
def get_debug_outlines(self):
|
136
139
|
if self.visible:
|
137
140
|
offset = self._get_outline_offset() if self.show_text_outline else (0,0)
|
138
|
-
yield (self.text_rect.move(self.rect.x - offset[0],self.rect.y - offset[1]), "purple")
|
141
|
+
yield (self.text_rect.move(self.rect.x - offset[0] - self.scroll.x,self.rect.y - offset[1] - self.scroll.y), "purple")
|
139
142
|
yield from super().get_debug_outlines()
|
140
143
|
|
141
144
|
def set_font(self, font_name: str = None, force: bool = False) -> Self:
|
@@ -183,7 +186,7 @@ class Label(Shape):
|
|
183
186
|
if not self.text_rect:
|
184
187
|
self.text_rect.size = self._get_text_rect_required_size()
|
185
188
|
res = self.inflate_rect_by_padding((0, 0, *self.text_rect.size)).size
|
186
|
-
|
189
|
+
|
187
190
|
return res[0] if self.autoresize_w else self.rect.w, (
|
188
191
|
res[1] if self.autoresize_h else self.rect.h
|
189
192
|
)
|
@@ -217,6 +220,7 @@ class Label(Shape):
|
|
217
220
|
surf = self.font_object.render(**params)
|
218
221
|
|
219
222
|
return surf
|
223
|
+
|
220
224
|
def _get_text_rect_required_size(self):
|
221
225
|
font_height = self.font_object.get_linesize()
|
222
226
|
if not self.text:
|
@@ -245,7 +249,6 @@ class Label(Shape):
|
|
245
249
|
self.text_rect.size = self._get_text_rect_required_size()
|
246
250
|
# self.text_rect.w = ceil(self.text_rect.w)
|
247
251
|
# self.text_rect.h = ceil(self.text_rect.h)
|
248
|
-
|
249
252
|
if self.autoresize_h or self.autoresize_w:
|
250
253
|
target_rect = self.inflate_rect_by_padding((0, 0, *self.text_rect.size))
|
251
254
|
if not self.autoresize_w:
|
@@ -254,7 +257,7 @@ class Label(Shape):
|
|
254
257
|
target_rect.h = self.rect.h
|
255
258
|
if self.rect.size != target_rect.size:
|
256
259
|
self.set_size(target_rect.size)
|
257
|
-
self.
|
260
|
+
self.apply_updates()
|
258
261
|
return
|
259
262
|
offset = self._get_outline_offset() if self.show_text_outline else (0,0)
|
260
263
|
padded = self.get_padded_rect().move(-self.rect.x + offset[0], -self.rect.y + offset[1])
|
@@ -279,7 +282,6 @@ class Label(Shape):
|
|
279
282
|
}
|
280
283
|
|
281
284
|
self.text_surface = self._render_font(params)
|
282
|
-
|
283
285
|
if self.show_text_outline:
|
284
286
|
self.text_outline_surface = (
|
285
287
|
pygame.mask.from_surface(self.text_surface)
|
@@ -287,19 +289,28 @@ class Label(Shape):
|
|
287
289
|
.to_surface(setcolor=self.text_outline_color, unsetcolor=(0, 0, 0, 0))
|
288
290
|
)
|
289
291
|
|
290
|
-
l = []
|
291
292
|
outline_offset = self._get_outline_offset() if self.show_text_outline else (0,0)
|
292
293
|
|
294
|
+
|
295
|
+
# prepare fblit list
|
296
|
+
l = []
|
293
297
|
if self.show_text_outline:
|
294
298
|
l.append(
|
295
299
|
(self.text_outline_surface,
|
296
|
-
(self.text_rect.x - outline_offset[0],self.text_rect.y - outline_offset[1]))
|
300
|
+
(self.text_rect.x - outline_offset[0] - self.scroll.x,self.text_rect.y - outline_offset[1] - self.scroll.y))
|
297
301
|
)
|
298
302
|
l.append(
|
299
|
-
(self.text_surface, self.text_rect)
|
303
|
+
(self.text_surface, self.text_rect.move(-self.scroll))
|
300
304
|
)
|
305
|
+
|
306
|
+
# clip surface
|
307
|
+
|
308
|
+
old = self.surface.get_clip()
|
309
|
+
self.surface.set_clip(self.get_padded_rect().move(-self.rect.x,-self.rect.y))
|
301
310
|
self.surface.fblits(l)
|
311
|
+
self.surface.set_clip(old)
|
302
312
|
|
313
|
+
|
303
314
|
def align_text(
|
304
315
|
self, text_rect: pygame.FRect, area: pygame.FRect, alignment: bf.alignment
|
305
316
|
):
|
@@ -312,6 +323,8 @@ class Label(Shape):
|
|
312
323
|
text_rect.__setattr__(alignment.value, pos)
|
313
324
|
text_rect.y = ceil(text_rect.y)
|
314
325
|
|
326
|
+
|
327
|
+
|
315
328
|
def build(self) -> None:
|
316
329
|
super().build()
|
317
330
|
self._build_layout()
|
@@ -320,3 +333,6 @@ class Label(Shape):
|
|
320
333
|
super().paint()
|
321
334
|
if self.font_object:
|
322
335
|
self._paint_text()
|
336
|
+
|
337
|
+
# def set_alignment(self, alignment: bf.alignment) -> Self:
|
338
|
+
# return self
|