batframework 1.0.8a2__py3-none-any.whl → 1.0.8a3__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 +53 -50
- batFramework/action.py +126 -99
- batFramework/actionContainer.py +53 -9
- batFramework/animatedSprite.py +115 -65
- batFramework/audioManager.py +69 -26
- batFramework/camera.py +259 -69
- batFramework/constants.py +16 -54
- batFramework/cutscene.py +36 -29
- batFramework/cutsceneBlocks.py +37 -42
- batFramework/dynamicEntity.py +9 -7
- 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 +219 -0
- batFramework/gui/constraints/__init__.py +1 -0
- batFramework/gui/constraints/constraints.py +590 -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 +54 -18
- batFramework/gui/indicator.py +38 -21
- batFramework/gui/interactiveWidget.py +177 -13
- batFramework/gui/label.py +288 -74
- batFramework/gui/layout.py +219 -60
- batFramework/gui/meter.py +71 -0
- batFramework/gui/radioButton.py +84 -0
- batFramework/gui/root.py +128 -38
- batFramework/gui/shape.py +253 -57
- batFramework/gui/slider.py +246 -0
- batFramework/gui/style.py +10 -0
- batFramework/gui/styleManager.py +48 -0
- batFramework/gui/textInput.py +137 -0
- batFramework/gui/toggle.py +115 -51
- batFramework/gui/widget.py +329 -254
- batFramework/manager.py +40 -19
- batFramework/object.py +114 -0
- batFramework/particle.py +101 -0
- batFramework/renderGroup.py +67 -0
- batFramework/resourceManager.py +84 -0
- batFramework/scene.py +242 -114
- batFramework/sceneManager.py +145 -107
- batFramework/scrollingSprite.py +115 -0
- batFramework/sprite.py +51 -0
- batFramework/stateMachine.py +2 -2
- batFramework/tileset.py +46 -0
- batFramework/time.py +117 -57
- batFramework/transition.py +184 -126
- batFramework/utils.py +31 -156
- batframework-1.0.8a3.dist-info/LICENCE +21 -0
- batframework-1.0.8a3.dist-info/METADATA +55 -0
- batframework-1.0.8a3.dist-info/RECORD +58 -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.8a2.dist-info/METADATA +0 -58
- batframework-1.0.8a2.dist-info/RECORD +0 -42
- {batframework-1.0.8a2.dist-info → batframework-1.0.8a3.dist-info}/WHEEL +0 -0
- {batframework-1.0.8a2.dist-info → batframework-1.0.8a3.dist-info}/top_level.txt +0 -0
batFramework/gui/indicator.py
CHANGED
@@ -1,40 +1,57 @@
|
|
1
1
|
from .shape import Shape
|
2
|
-
from typing import Any
|
2
|
+
from typing import Any, Self
|
3
3
|
import pygame
|
4
|
-
|
4
|
+
from .widget import Widget
|
5
|
+
from .interactiveWidget import InteractiveWidget
|
6
|
+
from .draggableWidget import DraggableWidget
|
7
|
+
import batFramework as bf
|
8
|
+
|
5
9
|
|
6
10
|
class Indicator(Shape):
|
7
|
-
def __init__(self,
|
8
|
-
super().__init__(
|
11
|
+
def __init__(self, size: tuple[int | float] = (10, 10)) -> None:
|
12
|
+
super().__init__(size)
|
13
|
+
self.debug_color = "magenta"
|
14
|
+
self.set_outline_width(1)
|
15
|
+
self.set_outline_color("black")
|
9
16
|
|
10
|
-
def to_string_id(self)->str:
|
17
|
+
def to_string_id(self) -> str:
|
11
18
|
return "Indicator"
|
12
19
|
|
13
|
-
def set_value(self,value:Any)->None:
|
20
|
+
def set_value(self, value: Any) -> None:
|
14
21
|
pass
|
15
22
|
|
16
|
-
def get_value(self)->Any:
|
23
|
+
def get_value(self) -> Any:
|
17
24
|
pass
|
18
25
|
|
19
|
-
def
|
20
|
-
|
21
|
-
|
22
|
-
def build(self)->None:
|
23
|
-
super().build()
|
24
|
-
self._build_indicator()
|
26
|
+
def top_at(self, x, y):
|
27
|
+
return None
|
25
28
|
|
26
29
|
|
27
30
|
class ToggleIndicator(Indicator):
|
28
|
-
def __init__(self,default_value:bool)->None:
|
29
|
-
self.value:bool = default_value
|
30
|
-
|
31
|
+
def __init__(self, default_value: bool) -> None:
|
32
|
+
self.value: bool = default_value
|
33
|
+
self.callback = lambda val: self.set_color("green" if val else "red")
|
34
|
+
super().__init__((20, 20))
|
35
|
+
self.set_value(default_value)
|
36
|
+
|
37
|
+
# TODO aspect ratio would be good right about here
|
31
38
|
# self.add_constraint(ConstraintAspectRatio(1))
|
32
39
|
|
33
|
-
def
|
40
|
+
def set_callback(self, callback) -> Self:
|
41
|
+
self.callback = callback
|
42
|
+
return self
|
43
|
+
|
44
|
+
def set_value(self, value: bool) -> None:
|
34
45
|
self.value = value
|
35
|
-
self.
|
36
|
-
|
46
|
+
if self.callback:
|
47
|
+
self.callback(value)
|
48
|
+
self.dirty_surface = True
|
37
49
|
|
38
|
-
def get_value(self)->bool:
|
50
|
+
def get_value(self) -> bool:
|
39
51
|
return self.value
|
40
|
-
|
52
|
+
|
53
|
+
def top_at(self, x: float, y: float) -> "None|Widget":
|
54
|
+
r = super().top_at(x, y)
|
55
|
+
if r is self:
|
56
|
+
return None
|
57
|
+
return r
|
@@ -1,22 +1,186 @@
|
|
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
|
6
|
+
|
7
|
+
if TYPE_CHECKING:
|
8
|
+
from .container import Container
|
9
|
+
import batFramework as bf
|
10
|
+
|
2
11
|
|
3
12
|
class InteractiveWidget(Widget):
|
4
|
-
def __init__(self
|
5
|
-
|
13
|
+
def __init__(self, *args, **kwargs) -> None:
|
14
|
+
self.is_focused: bool = False
|
15
|
+
self.is_hovered: bool = False
|
16
|
+
self.is_clicked_down: bool = False
|
17
|
+
self.focused_index = 0
|
6
18
|
self.focusable = True
|
7
|
-
|
19
|
+
super().__init__(*args, **kwargs)
|
20
|
+
|
21
|
+
def set_focusable(self, value: bool) -> Self:
|
22
|
+
self.focusable = value
|
23
|
+
return self
|
24
|
+
|
25
|
+
def allow_focus_to_self(self) -> bool:
|
26
|
+
return self.visible
|
27
|
+
|
28
|
+
def get_focus(self) -> bool:
|
29
|
+
if self.focusable and ((r := self.get_root()) is not None):
|
30
|
+
r.focus_on(self)
|
31
|
+
if self.parent and isinstance(self.parent, InteractiveWidget):
|
32
|
+
self.parent.set_focused_child(self)
|
33
|
+
return True
|
34
|
+
return False
|
8
35
|
|
9
|
-
def
|
10
|
-
if self.
|
11
|
-
|
36
|
+
def lose_focus(self) -> bool:
|
37
|
+
if self.is_focused and ((r := self.get_root()) is not None):
|
38
|
+
r.focus_on(None)
|
39
|
+
return True
|
40
|
+
return False
|
12
41
|
|
13
|
-
def on_get_focus(self)->None:
|
42
|
+
def on_get_focus(self) -> None:
|
14
43
|
self.is_focused = True
|
44
|
+
self.do_on_get_focus()
|
15
45
|
|
16
|
-
def on_lose_focus(self)->None:
|
46
|
+
def on_lose_focus(self) -> None:
|
17
47
|
self.is_focused = False
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
48
|
+
self.do_on_lose_focus()
|
49
|
+
|
50
|
+
def focus_next_tab(self, previous_widget):
|
51
|
+
|
52
|
+
if previous_widget != self and self.visible:
|
53
|
+
if (
|
54
|
+
isinstance(self, InteractiveWidget)
|
55
|
+
and not isinstance(self, bf.Container)
|
56
|
+
and self.allow_focus_to_self()
|
57
|
+
):
|
58
|
+
self.focus_next_sibling()
|
59
|
+
return
|
60
|
+
i_children = [
|
61
|
+
c
|
62
|
+
for c in self.children
|
63
|
+
if isinstance(c, InteractiveWidget) and c.visible
|
64
|
+
]
|
65
|
+
if i_children:
|
66
|
+
index = i_children.index(previous_widget)
|
67
|
+
if index < len(i_children) - 1:
|
68
|
+
|
69
|
+
i_children[index + 1].get_focus()
|
70
|
+
return
|
71
|
+
|
72
|
+
if self.parent:
|
73
|
+
self.parent.focus_next_tab(self)
|
74
|
+
|
75
|
+
def focus_prev_tab(self, previous_widget):
|
76
|
+
if previous_widget != self and self.visible:
|
77
|
+
if (
|
78
|
+
isinstance(self, InteractiveWidget)
|
79
|
+
and not isinstance(self, bf.Container)
|
80
|
+
and self.allow_focus_to_self()
|
81
|
+
):
|
82
|
+
self.get_focus()
|
83
|
+
return
|
84
|
+
i_children = [
|
85
|
+
c
|
86
|
+
for c in self.children
|
87
|
+
if isinstance(c, InteractiveWidget) and c.visible
|
88
|
+
]
|
89
|
+
|
90
|
+
if i_children:
|
91
|
+
index = i_children.index(previous_widget)
|
92
|
+
if index > 0:
|
93
|
+
i_children[index - 1].get_focus()
|
94
|
+
return
|
95
|
+
|
96
|
+
if self.parent:
|
97
|
+
self.parent.focus_prev_tab(self)
|
98
|
+
|
99
|
+
def focus_next_sibling(self) -> None:
|
100
|
+
if isinstance(self.parent, bf.Container):
|
101
|
+
self.parent.focus_next_child()
|
102
|
+
|
103
|
+
def focus_prev_sibling(self) -> None:
|
104
|
+
if isinstance(self.parent, bf.Container):
|
105
|
+
self.parent.focus_prev_child()
|
106
|
+
|
107
|
+
def on_key_down(self, key) -> bool:
|
108
|
+
if key == pygame.K_DOWN:
|
109
|
+
self.focus_next_sibling()
|
110
|
+
elif key == pygame.K_UP:
|
111
|
+
self.focus_prev_sibling()
|
112
|
+
elif key == pygame.K_TAB and self.parent:
|
113
|
+
keys = pygame.key.get_pressed()
|
114
|
+
if keys[pygame.K_LSHIFT] or keys[pygame.K_RSHIFT]:
|
115
|
+
|
116
|
+
self.focus_prev_tab(self)
|
117
|
+
else:
|
118
|
+
self.focus_next_tab(self)
|
119
|
+
|
120
|
+
else:
|
121
|
+
|
122
|
+
return self.do_on_key_down(key)
|
123
|
+
|
124
|
+
return False
|
125
|
+
|
126
|
+
def on_key_up(self, key) -> bool:
|
127
|
+
return self.do_on_key_up(key)
|
128
|
+
|
129
|
+
def do_on_key_down(self, key) -> bool:
|
130
|
+
return False
|
131
|
+
|
132
|
+
def do_on_key_up(self, key) -> bool:
|
133
|
+
return False
|
134
|
+
|
135
|
+
def do_on_get_focus(self) -> None:
|
136
|
+
pass
|
137
|
+
|
138
|
+
def do_on_lose_focus(self) -> None:
|
139
|
+
pass
|
140
|
+
|
141
|
+
def on_click_down(self, button: int) -> bool:
|
142
|
+
self.is_clicked_down = True
|
143
|
+
return self.do_on_click_down(button)
|
144
|
+
|
145
|
+
def on_click_up(self, button: int) -> bool:
|
146
|
+
self.is_clicked_down = False
|
147
|
+
return self.do_on_click_up(button)
|
148
|
+
|
149
|
+
def do_on_click_down(self, button: int) -> bool:
|
150
|
+
return False
|
151
|
+
|
152
|
+
def do_on_click_up(self, button: int) -> bool:
|
153
|
+
return False
|
154
|
+
|
155
|
+
def on_enter(self) -> None:
|
156
|
+
self.is_hovered = True
|
157
|
+
self.do_on_enter()
|
158
|
+
|
159
|
+
def on_exit(self) -> None:
|
160
|
+
self.is_hovered = False
|
161
|
+
self.is_clicked_down = False
|
162
|
+
self.do_on_exit()
|
163
|
+
|
164
|
+
def do_on_enter(self) -> None:
|
165
|
+
pass
|
166
|
+
|
167
|
+
def do_on_exit(self) -> None:
|
168
|
+
pass
|
169
|
+
|
170
|
+
def on_mouse_motion(self, x, y) -> None:
|
171
|
+
self.do_on_mouse_motion(x, y)
|
172
|
+
|
173
|
+
def do_on_mouse_motion(self, x, y) -> None:
|
174
|
+
pass
|
175
|
+
|
176
|
+
def set_focused_child(self, child: "InteractiveWidget"):
|
177
|
+
pass
|
178
|
+
|
179
|
+
def draw_focused(self, camera: bf.Camera) -> None:
|
180
|
+
delta = 4 + ((2 * cos(pygame.time.get_ticks() / 100)) // 2) * 2
|
181
|
+
pygame.draw.rect(
|
182
|
+
camera.surface,
|
183
|
+
"white",
|
184
|
+
self.rect.move(-camera.rect.x, -camera.rect.y).inflate(delta, delta),
|
185
|
+
1,
|
186
|
+
)
|
batFramework/gui/label.py
CHANGED
@@ -3,108 +3,322 @@ import pygame
|
|
3
3
|
from .shape import Shape
|
4
4
|
from typing import Self
|
5
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({self.text})"
|
63
|
+
|
64
|
+
def enable_caching(self) -> Self:
|
65
|
+
self.do_caching = True
|
66
|
+
return self
|
67
|
+
|
68
|
+
def disable_caching(self) -> Self:
|
69
|
+
self.do_caching = False
|
70
|
+
return self
|
71
|
+
|
72
|
+
def set_text_color(self, color) -> Self:
|
73
|
+
self.text_color = color
|
74
|
+
self.dirty_surface = True
|
34
75
|
return self
|
35
76
|
|
36
|
-
def
|
37
|
-
|
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
|
38
86
|
|
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
|
95
|
+
return self
|
39
96
|
|
40
|
-
def
|
41
|
-
|
42
|
-
|
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
|
102
|
+
return self
|
43
103
|
|
44
|
-
def
|
45
|
-
if
|
46
|
-
|
47
|
-
|
48
|
-
|
104
|
+
def set_text_outline_matrix(self, matrix: list[list[0 | 1]]) -> Self:
|
105
|
+
if matrix is None:
|
106
|
+
matrix = [[0 for _ in range(3)] for _ in range(3)]
|
107
|
+
for y in range(3):
|
108
|
+
for x in range(3):
|
109
|
+
self._text_outline_mask.set_at((x, y), matrix[2 - y][2 - x])
|
110
|
+
self.dirty_surface = True
|
49
111
|
return self
|
50
112
|
|
51
|
-
def
|
52
|
-
|
53
|
-
|
54
|
-
self._text_size = text_size
|
55
|
-
self._font_object = bf.utils.get_font(self._font_name,self._text_size)
|
56
|
-
self.build()
|
113
|
+
def set_text_outline_color(self, color) -> Self:
|
114
|
+
self.text_outline_color = color
|
115
|
+
self.dirty_surface = True
|
57
116
|
return self
|
58
117
|
|
59
|
-
def
|
60
|
-
|
118
|
+
def enable_text_outline(self) -> Self:
|
119
|
+
self.show_text_outline = True
|
120
|
+
self.dirty_surface = True
|
121
|
+
return self
|
61
122
|
|
62
|
-
def
|
63
|
-
|
123
|
+
def disable_text_outline(self) -> Self:
|
124
|
+
self.show_text_outline = False
|
125
|
+
self.dirty_surface = True
|
126
|
+
return self
|
64
127
|
|
65
|
-
def
|
66
|
-
self.
|
67
|
-
self.
|
128
|
+
def set_alignment(self, alignment: bf.alignment) -> "Label":
|
129
|
+
self.alignment = alignment
|
130
|
+
self.dirty_surface = True
|
68
131
|
return self
|
69
132
|
|
70
|
-
def
|
71
|
-
|
72
|
-
self.
|
73
|
-
|
133
|
+
def set_auto_wraplength(self, val: bool) -> "Label":
|
134
|
+
self.auto_wraplength = val
|
135
|
+
if self.autoresize_h or self.autoresize_w:
|
136
|
+
self.dirty_shape = True
|
137
|
+
else:
|
138
|
+
self.dirty_surface = True
|
74
139
|
return self
|
75
|
-
|
76
|
-
def get_text(self)->str:
|
77
|
-
return self._text
|
78
140
|
|
141
|
+
def get_debug_outlines(self):
|
142
|
+
if self.visible:
|
143
|
+
yield (self.text_rect.move(*self.rect.topleft), "purple")
|
144
|
+
yield from super().get_debug_outlines()
|
79
145
|
|
80
|
-
def
|
81
|
-
if self.
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
self.
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
146
|
+
def set_font(self, font_name: str = None, force: bool = False) -> Self:
|
147
|
+
if font_name == self.font_name and not force:
|
148
|
+
return self
|
149
|
+
self.font_name = font_name
|
150
|
+
self.font_object = bf.FontManager().get_font(self.font_name, self.text_size)
|
151
|
+
if self.autoresize_h or self.autoresize_w:
|
152
|
+
self.dirty_shape = True
|
153
|
+
else:
|
154
|
+
self.dirty_surface = True
|
155
|
+
return self
|
156
|
+
|
157
|
+
def set_text_size(self, text_size: int) -> Self:
|
158
|
+
text_size = round(text_size / 2) * 2
|
159
|
+
if text_size == self.text_size:
|
160
|
+
return self
|
161
|
+
self.text_size = text_size
|
162
|
+
self.font_object = bf.FontManager().get_font(self.font_name, self.text_size)
|
163
|
+
if self.autoresize_h or self.autoresize_w:
|
164
|
+
self.dirty_shape = True
|
165
|
+
return self
|
166
|
+
|
167
|
+
def get_text_size(self) -> int:
|
168
|
+
return self.text_size
|
169
|
+
|
170
|
+
def is_antialias(self) -> bool:
|
171
|
+
return self.antialias
|
172
|
+
|
173
|
+
def set_antialias(self, value: bool) -> Self:
|
174
|
+
self.antialias = value
|
175
|
+
self.dirty_surface = True
|
176
|
+
return self
|
177
|
+
|
178
|
+
def set_text(self, text: str) -> Self:
|
179
|
+
if text == self.text:
|
180
|
+
return self
|
181
|
+
self.text = text
|
182
|
+
self.dirty_shape = True
|
183
|
+
return self
|
184
|
+
|
185
|
+
def get_min_required_size(self) -> tuple[float, float]:
|
186
|
+
if not (self.autoresize_w or self.autoresize_h):
|
187
|
+
return self.rect.size
|
188
|
+
if not self.text_rect:
|
189
|
+
params = {
|
190
|
+
"font_name": self.font_object.name,
|
191
|
+
"text": self.text,
|
192
|
+
"antialias": False,
|
193
|
+
"color": "white",
|
194
|
+
"bgcolor": "black", # if (self.has_alpha_color() or self.draw_mode == bf.drawMode.TEXTURED) else self.color,
|
195
|
+
"wraplength": (
|
196
|
+
int(self.get_padded_width()) if self.auto_wraplength else 0
|
197
|
+
),
|
198
|
+
}
|
199
|
+
|
200
|
+
self.text_rect.size = self._render_font(params).get_size()
|
201
|
+
res = self.inflate_rect_by_padding((0, 0, *self.text_rect.size)).size
|
202
|
+
# return res
|
203
|
+
return res[0] if self.autoresize_w else self.rect.w, (
|
204
|
+
res[1] if self.autoresize_h else self.rect.h
|
91
205
|
)
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
206
|
+
|
207
|
+
def get_text(self) -> str:
|
208
|
+
return self.text
|
209
|
+
|
210
|
+
def _render_font(self, params: dict) -> pygame.Surface:
|
211
|
+
key = tuple(params.values())
|
212
|
+
|
213
|
+
cached_value = Label._text_cache.get(key, None)
|
214
|
+
|
215
|
+
if self.draw_mode == bf.drawMode.SOLID:
|
216
|
+
if cached_value is None:
|
217
|
+
params.pop("font_name")
|
218
|
+
|
219
|
+
# save old settings
|
220
|
+
old_italic = self.font_object.get_italic()
|
221
|
+
old_bold = self.font_object.get_bold()
|
222
|
+
old_underline = self.font_object.get_underline()
|
223
|
+
|
224
|
+
# setup font
|
225
|
+
self.font_object.set_italic(self.is_italic)
|
226
|
+
self.font_object.set_bold(self.is_bold)
|
227
|
+
self.font_object.set_underline(self.is_underlined)
|
228
|
+
|
229
|
+
surf = self.font_object.render(**params)
|
230
|
+
|
231
|
+
# reset font
|
232
|
+
self.font_object.set_italic(old_italic)
|
233
|
+
self.font_object.set_bold(old_bold)
|
234
|
+
self.font_object.set_underline(old_underline)
|
235
|
+
|
236
|
+
if self.do_caching:
|
237
|
+
Label._text_cache[key] = surf
|
238
|
+
else:
|
239
|
+
surf = cached_value
|
240
|
+
else:
|
241
|
+
params.pop("font_name")
|
242
|
+
surf = self.font_object.render(**params)
|
243
|
+
|
244
|
+
return surf
|
245
|
+
|
246
|
+
def _build_layout(self) -> None:
|
247
|
+
|
248
|
+
params = {
|
249
|
+
"font_name": self.font_object.name,
|
250
|
+
"text": self.text,
|
251
|
+
"antialias": False,
|
252
|
+
"color": "white",
|
253
|
+
"bgcolor": "black", # if (self.has_alpha_color() or self.draw_mode == bf.drawMode.TEXTURED) else self.color,
|
254
|
+
"wraplength": int(self.get_padded_width()) if self.auto_wraplength else 0,
|
255
|
+
}
|
256
|
+
|
257
|
+
self.text_rect.size = self._render_font(params).get_size()
|
258
|
+
if self.autoresize_h or self.autoresize_w:
|
259
|
+
target_rect = self.inflate_rect_by_padding((0, 0, *self.text_rect.size))
|
260
|
+
if not self.autoresize_w:
|
261
|
+
target_rect.w = self.rect.w
|
262
|
+
if not self.autoresize_h:
|
263
|
+
target_rect.h = self.rect.h
|
264
|
+
if self.rect.size != target_rect.size:
|
265
|
+
self.set_size(target_rect.size)
|
266
|
+
self.build()
|
101
267
|
return
|
102
|
-
|
103
|
-
self.
|
104
|
-
|
105
|
-
def
|
268
|
+
padded = self.get_padded_rect().move(-self.rect.x, -self.rect.y)
|
269
|
+
self.align_text(self.text_rect, padded, self.alignment)
|
270
|
+
|
271
|
+
def _paint_text(self) -> None:
|
272
|
+
if self.font_object is None:
|
273
|
+
print(f"No font for widget with text : '{self}' :(")
|
274
|
+
return
|
275
|
+
|
276
|
+
params = {
|
277
|
+
"font_name": self.font_object.name,
|
278
|
+
"text": self.text,
|
279
|
+
"antialias": self.antialias,
|
280
|
+
"color": self.text_color,
|
281
|
+
"bgcolor": None, # if (self.has_alpha_color() or self.draw_mode == bf.drawMode.TEXTURED) else self.color,
|
282
|
+
"wraplength": int(self.get_padded_width()) if self.auto_wraplength else 0,
|
283
|
+
}
|
284
|
+
self.text_surface = self._render_font(params)
|
285
|
+
|
286
|
+
if self.show_text_outline:
|
287
|
+
self.text_outline_surface = (
|
288
|
+
pygame.mask.from_surface(self.text_surface)
|
289
|
+
.convolve(self._text_outline_mask)
|
290
|
+
.to_surface(setcolor=self.text_outline_color, unsetcolor=(0, 0, 0, 0))
|
291
|
+
)
|
292
|
+
|
293
|
+
l = []
|
294
|
+
if self.show_text_outline:
|
295
|
+
l.append(
|
296
|
+
(
|
297
|
+
self.text_outline_surface,
|
298
|
+
self.text_rect.move(-1, self.relief - self.get_relief() - 1),
|
299
|
+
)
|
300
|
+
)
|
301
|
+
l.append(
|
302
|
+
(self.text_surface, self.text_rect.move(0, self.relief - self.get_relief()))
|
303
|
+
)
|
304
|
+
self.surface.fblits(l)
|
305
|
+
|
306
|
+
def align_text(
|
307
|
+
self, text_rect: pygame.FRect, area: pygame.FRect, alignment: bf.alignment
|
308
|
+
):
|
309
|
+
if alignment == bf.alignment.LEFT:
|
310
|
+
alignment = bf.alignment.MIDLEFT
|
311
|
+
elif alignment == bf.alignment.MIDRIGHT:
|
312
|
+
alignment = bf.alignment.MIDRIGHT
|
313
|
+
|
314
|
+
pos = area.__getattribute__(alignment.value)
|
315
|
+
text_rect.__setattr__(alignment.value, pos)
|
316
|
+
|
317
|
+
def build(self) -> None:
|
106
318
|
super().build()
|
107
|
-
if not self._font_object:return
|
108
|
-
self._build_text()
|
109
319
|
self._build_layout()
|
110
320
|
|
321
|
+
def paint(self) -> None:
|
322
|
+
super().paint()
|
323
|
+
if self.font_object:
|
324
|
+
self._paint_text()
|