batframework 1.0.7__py3-none-any.whl → 1.0.8a1__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 +24 -15
- batFramework/action.py +95 -106
- batFramework/actionContainer.py +11 -8
- batFramework/animatedSprite.py +60 -43
- batFramework/audioManager.py +52 -22
- batFramework/camera.py +87 -72
- batFramework/constants.py +19 -41
- batFramework/cutscene.py +12 -11
- batFramework/cutsceneBlocks.py +12 -14
- batFramework/dynamicEntity.py +5 -4
- batFramework/easingController.py +58 -0
- batFramework/entity.py +37 -130
- batFramework/enums.py +93 -3
- batFramework/fontManager.py +15 -7
- batFramework/gui/__init__.py +5 -1
- batFramework/gui/button.py +6 -144
- batFramework/gui/clickableWidget.py +206 -0
- batFramework/gui/constraints/__init__.py +1 -0
- batFramework/gui/constraints/constraints.py +378 -0
- batFramework/gui/container.py +147 -34
- batFramework/gui/debugger.py +39 -22
- batFramework/gui/dialogueBox.py +69 -43
- batFramework/gui/draggableWidget.py +38 -0
- batFramework/gui/image.py +33 -28
- batFramework/gui/indicator.py +30 -16
- batFramework/gui/interactiveWidget.py +72 -20
- batFramework/gui/label.py +240 -98
- batFramework/gui/layout.py +125 -53
- batFramework/gui/meter.py +76 -0
- batFramework/gui/radioButton.py +62 -0
- batFramework/gui/root.py +72 -48
- batFramework/gui/shape.py +257 -49
- batFramework/gui/slider.py +217 -2
- batFramework/gui/textInput.py +106 -60
- batFramework/gui/toggle.py +85 -42
- batFramework/gui/widget.py +259 -288
- batFramework/manager.py +30 -16
- batFramework/object.py +115 -0
- batFramework/{particles.py → particle.py} +37 -34
- batFramework/renderGroup.py +62 -0
- batFramework/resourceManager.py +36 -24
- batFramework/scene.py +94 -88
- batFramework/sceneManager.py +140 -57
- batFramework/scrollingSprite.py +113 -0
- batFramework/sprite.py +35 -23
- batFramework/tileset.py +34 -52
- batFramework/time.py +105 -56
- batFramework/transition.py +213 -1
- batFramework/utils.py +38 -18
- {batframework-1.0.7.dist-info → batframework-1.0.8a1.dist-info}/METADATA +1 -1
- batframework-1.0.8a1.dist-info/RECORD +56 -0
- {batframework-1.0.7.dist-info → batframework-1.0.8a1.dist-info}/WHEEL +1 -1
- batFramework/easing.py +0 -76
- batFramework/gui/constraints.py +0 -277
- batFramework/gui/frame.py +0 -25
- batFramework/transitionManager.py +0 -0
- batframework-1.0.7.dist-info/RECORD +0 -50
- {batframework-1.0.7.dist-info → batframework-1.0.8a1.dist-info}/LICENCE +0 -0
- {batframework-1.0.7.dist-info → batframework-1.0.8a1.dist-info}/top_level.txt +0 -0
batFramework/gui/layout.py
CHANGED
@@ -1,96 +1,168 @@
|
|
1
1
|
import batFramework as bf
|
2
2
|
from .widget import Widget
|
3
|
-
from .constraints import *
|
4
|
-
from typing import Self
|
3
|
+
from .constraints.constraints import *
|
4
|
+
from typing import Self,TYPE_CHECKING
|
5
5
|
import pygame
|
6
6
|
|
7
|
+
if TYPE_CHECKING:
|
8
|
+
from .container import Container
|
7
9
|
|
8
10
|
class Layout:
|
9
|
-
def __init__(self, parent:
|
11
|
+
def __init__(self, parent: "Container" = None):
|
10
12
|
self.parent = parent
|
11
13
|
self.child_constraints: list[Constraint] = []
|
12
14
|
self.children_rect = pygame.FRect(0, 0, 0, 0)
|
13
15
|
|
14
16
|
def set_child_constraints(self, *constraints) -> Self:
|
15
17
|
self.child_constraints = list(constraints)
|
16
|
-
self.
|
18
|
+
self.notify_parent()
|
17
19
|
return self
|
18
20
|
|
19
21
|
def set_parent(self, parent: Widget):
|
20
22
|
self.parent = parent
|
21
|
-
self.
|
23
|
+
self.notify_parent()
|
24
|
+
|
25
|
+
def notify_parent(self) -> None:
|
26
|
+
if self.parent:self.parent.dirty_children = True
|
22
27
|
|
23
28
|
def arrange(self) -> None:
|
24
|
-
|
29
|
+
return
|
30
|
+
|
31
|
+
def clamp_scroll(self)->None:
|
32
|
+
return
|
33
|
+
|
34
|
+
def get_raw_size(self)->tuple[float,float]:
|
35
|
+
return self.parent.rect.size if self.parent else 0,0
|
36
|
+
|
37
|
+
def get_auto_size(self)->tuple[float,float]:
|
38
|
+
return self.parent.rect.size if self.parent else 0,0
|
39
|
+
|
40
|
+
def focus_next_child(self)->None:
|
41
|
+
l = self.parent.get_interactive_children()
|
42
|
+
self.parent.focused_index = min(self.parent.focused_index + 1, len(l) - 1)
|
43
|
+
focused = l[self.parent.focused_index]
|
44
|
+
focused.get_focus()
|
45
|
+
self.scroll_to_widget(focused)
|
46
|
+
|
47
|
+
def focus_prev_child(self)->None:
|
48
|
+
l = self.parent.get_interactive_children()
|
49
|
+
self.parent.focused_index = max(self.parent.focused_index - 1, 0)
|
50
|
+
focused = l[self.parent.focused_index]
|
51
|
+
focused.get_focus()
|
52
|
+
self.scroll_to_widget(focused)
|
53
|
+
|
54
|
+
def scroll_to_widget(self,widget:Widget)->None:
|
55
|
+
padded = self.parent.get_padded_rect()
|
56
|
+
r = widget.rect
|
57
|
+
if padded.contains(r):return
|
58
|
+
clamped = r.clamp(padded)
|
59
|
+
dx,dy = clamped.move(-r.x,-r.y).topleft
|
60
|
+
self.parent.scroll_by((-dx,-dy))
|
61
|
+
|
25
62
|
|
26
63
|
|
27
64
|
class Column(Layout):
|
28
|
-
def __init__(self, gap: int = 0,
|
65
|
+
def __init__(self, gap: int = 0,spacing:bf.spacing = bf.spacing.MANUAL):
|
29
66
|
super().__init__()
|
30
67
|
self.gap = gap
|
31
|
-
self.
|
32
|
-
self.center = center
|
68
|
+
self.spacing = spacing
|
33
69
|
|
34
|
-
def
|
35
|
-
|
36
|
-
|
70
|
+
def set_gap(self, value: float) -> Self:
|
71
|
+
self.gap = value
|
72
|
+
self.notify_parent()
|
73
|
+
return self
|
74
|
+
|
75
|
+
def set_spacing(self,spacing: bf.spacing)->Self:
|
76
|
+
self.spacing = spacing
|
77
|
+
self.notify_parent()
|
78
|
+
return self
|
79
|
+
|
80
|
+
def get_raw_size(self)-> tuple[float,float]:
|
37
81
|
len_children = len(self.parent.children)
|
82
|
+
if not len_children : return self.parent.rect.size
|
38
83
|
parent_height = sum(c.get_min_required_size()[1] for c in self.parent.children)
|
39
84
|
parent_width = max(c.get_min_required_size()[0] for c in self.parent.children)
|
40
85
|
if self.gap:
|
41
86
|
parent_height += (len_children - 1) * self.gap
|
42
|
-
self.
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
if self.
|
49
|
-
|
50
|
-
if self.center:
|
51
|
-
self.children_rect.center = self.parent.rect.center
|
52
|
-
|
53
|
-
current_y = self.children_rect.top
|
54
|
-
|
55
|
-
for child in self.parent.children:
|
56
|
-
child.set_position(self.parent.rect.x, current_y)
|
57
|
-
current_y += child.rect.h + self.gap
|
58
|
-
for c in self.child_constraints:
|
59
|
-
child.add_constraints(c)
|
87
|
+
target_rect = self.parent.inflate_rect_by_padding((0,0,parent_width,parent_height))
|
88
|
+
return target_rect.size
|
89
|
+
|
90
|
+
def get_auto_size(self)-> tuple[float,float]:
|
91
|
+
target_size = list(self.get_raw_size())
|
92
|
+
if not self.parent.autoresize_w : target_size[0] = self.parent.rect.w
|
93
|
+
if not self.parent.autoresize_h : target_size[1] = self.parent.rect.h
|
94
|
+
return target_size
|
60
95
|
|
96
|
+
def arrange(self) -> None:
|
97
|
+
if not self.parent or not self.parent.children:
|
98
|
+
return
|
99
|
+
if self.child_constraints :
|
100
|
+
for child in self.parent.children : child.add_constraints(*self.child_constraints)
|
101
|
+
self.child_rect = self.parent.get_padded_rect()
|
102
|
+
|
103
|
+
if self.parent.autoresize_w or self.parent.autoresize_h:
|
104
|
+
width,height = self.get_auto_size()
|
105
|
+
if self.parent.rect.size != (width,height):
|
106
|
+
self.parent.set_size((width,height))
|
107
|
+
self.parent.build()
|
108
|
+
self.arrange()
|
109
|
+
return
|
110
|
+
self.child_rect.move_ip(-self.parent.scroll.x,-self.parent.scroll.y)
|
111
|
+
y = self.child_rect.top
|
112
|
+
for child in self.parent.children :
|
113
|
+
child.set_position(self.child_rect.x,y)
|
114
|
+
y+= child.get_min_required_size()[1] + self.gap
|
61
115
|
|
62
116
|
class Row(Layout):
|
63
|
-
def __init__(self, gap: int = 0,
|
117
|
+
def __init__(self, gap: int = 0,spacing: bf.spacing=bf.spacing.MANUAL):
|
64
118
|
super().__init__()
|
65
119
|
self.gap = gap
|
66
|
-
self.
|
67
|
-
self.center = center
|
120
|
+
self.spacing = spacing
|
68
121
|
|
69
|
-
def
|
70
|
-
|
71
|
-
|
122
|
+
def set_gap(self, value: float) -> Self:
|
123
|
+
self.gap = value
|
124
|
+
self.notify_parent()
|
125
|
+
return self
|
126
|
+
|
127
|
+
def set_spacing(self,spacing: bf.spacing)->Self:
|
128
|
+
self.spacing = spacing
|
129
|
+
self.notify_parent()
|
130
|
+
return self
|
72
131
|
|
132
|
+
|
133
|
+
def get_raw_size(self) -> tuple[float, float]:
|
73
134
|
len_children = len(self.parent.children)
|
135
|
+
if not len_children: return self.parent.rect.size
|
74
136
|
parent_width = sum(c.get_min_required_size()[0] for c in self.parent.children)
|
75
137
|
parent_height = max(c.get_min_required_size()[1] for c in self.parent.children)
|
76
|
-
|
77
138
|
if self.gap:
|
78
139
|
parent_width += (len_children - 1) * self.gap
|
79
|
-
self.
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
)
|
85
|
-
if self.
|
86
|
-
|
87
|
-
|
88
|
-
self.parent.set_size(parent_width,parent_height)
|
89
|
-
|
90
|
-
current_x = self.children_rect.left
|
140
|
+
target_rect = self.parent.inflate_rect_by_padding((0, 0, parent_width, parent_height))
|
141
|
+
|
142
|
+
return target_rect.size
|
143
|
+
|
144
|
+
def get_auto_size(self) -> tuple[float, float]:
|
145
|
+
target_size = list(self.get_raw_size())
|
146
|
+
if not self.parent.autoresize_w: target_size[0] = self.parent.rect.w
|
147
|
+
if not self.parent.autoresize_h: target_size[1] = self.parent.rect.h
|
148
|
+
return target_size
|
91
149
|
|
150
|
+
def arrange(self) -> None:
|
151
|
+
if not self.parent or not self.parent.children:
|
152
|
+
return
|
153
|
+
if self.child_constraints:
|
154
|
+
for child in self.parent.children: child.add_constraints(*self.child_constraints)
|
155
|
+
self.child_rect = self.parent.get_padded_rect()
|
156
|
+
|
157
|
+
if self.parent.autoresize_w or self.parent.autoresize_h:
|
158
|
+
width, height = self.get_auto_size()
|
159
|
+
if self.parent.rect.size != (width, height):
|
160
|
+
self.parent.set_size((width, height))
|
161
|
+
self.parent.build()
|
162
|
+
self.arrange()
|
163
|
+
return
|
164
|
+
self.child_rect.move_ip(-self.parent.scroll.x, -self.parent.scroll.y)
|
165
|
+
x = self.child_rect.left
|
92
166
|
for child in self.parent.children:
|
93
|
-
child.set_position(
|
94
|
-
|
95
|
-
for c in self.child_constraints:
|
96
|
-
child.add_constraints(c)
|
167
|
+
child.set_position(x, self.child_rect.y)
|
168
|
+
x += child.get_min_required_size()[0] + self.gap
|
@@ -0,0 +1,76 @@
|
|
1
|
+
import batFramework as bf
|
2
|
+
from .shape import Shape
|
3
|
+
from typing import Self
|
4
|
+
|
5
|
+
|
6
|
+
def custom_top_at(self, x, y):
|
7
|
+
if Shape.top_at(self, x, y) == self:
|
8
|
+
return self.parent
|
9
|
+
return None
|
10
|
+
|
11
|
+
|
12
|
+
class Meter(Shape):
|
13
|
+
def __init__(
|
14
|
+
self,
|
15
|
+
min_value: float = 0,
|
16
|
+
max_value: float = 1,
|
17
|
+
step: float = 0.1
|
18
|
+
):
|
19
|
+
super().__init__()
|
20
|
+
self.min_value, self.max_value = min_value,max_value
|
21
|
+
self.step = step
|
22
|
+
self.snap: bool = False
|
23
|
+
self.value = self.max_value
|
24
|
+
self.content = Shape((0, 0)).set_color(bf.color.BLUE)
|
25
|
+
self.content.top_at = lambda x, y: custom_top_at(self.content, x, y)
|
26
|
+
self.add(self.content)
|
27
|
+
self.set_padding(1)
|
28
|
+
self.set_outline_width(1)
|
29
|
+
self.set_outline_color(bf.color.BLACK)
|
30
|
+
self.set_debug_color("pink")
|
31
|
+
|
32
|
+
def __str__(self) -> str:
|
33
|
+
return "Meter"
|
34
|
+
|
35
|
+
def set_step(self, step: float) -> Self:
|
36
|
+
self.step = step
|
37
|
+
self.set_value(self.value)
|
38
|
+
return self
|
39
|
+
|
40
|
+
def set_range(self, range_min: float, range_max: float) -> Self:
|
41
|
+
if range_min >= range_max:
|
42
|
+
print(
|
43
|
+
f"[Warning] : minimum value {range_min} is greater than or equal to maximum value {range_max}"
|
44
|
+
)
|
45
|
+
return self
|
46
|
+
self.min_value, self.max_value = range_min, range_max
|
47
|
+
self.dirty_shape = True
|
48
|
+
|
49
|
+
def get_debug_outlines(self):
|
50
|
+
yield from super().get_debug_outlines()
|
51
|
+
yield from self.content.get_debug_outlines()
|
52
|
+
|
53
|
+
def set_value(self, value: float) -> Self:
|
54
|
+
value = max(self.min_value, min(self.max_value, value))
|
55
|
+
value = round(value / self.step) * self.step
|
56
|
+
self.value = value
|
57
|
+
self.dirty_surface = True
|
58
|
+
return self
|
59
|
+
|
60
|
+
def get_value(self) -> float:
|
61
|
+
return self.value
|
62
|
+
|
63
|
+
def get_range(self) -> float:
|
64
|
+
return self.max_value - self.min_value
|
65
|
+
|
66
|
+
def get_ratio(self) -> float:
|
67
|
+
return self.value / (self.max_value - self.min_value)
|
68
|
+
|
69
|
+
def _build_content(self) -> None:
|
70
|
+
width = (self.get_padded_width() * self.get_ratio())
|
71
|
+
self.content.set_size((width, self.get_padded_height()))
|
72
|
+
self.content.set_position(*self.get_padded_rect().topleft)
|
73
|
+
|
74
|
+
def build(self) -> None:
|
75
|
+
super().build()
|
76
|
+
self._build_content()
|
@@ -0,0 +1,62 @@
|
|
1
|
+
import batFramework as bf
|
2
|
+
from typing import Self,Any,Callable
|
3
|
+
from .toggle import Toggle
|
4
|
+
|
5
|
+
class RadioVariable:...
|
6
|
+
|
7
|
+
class RadioButton(Toggle):
|
8
|
+
def __init__(self, text: str, radio_value:Any = None) -> None:
|
9
|
+
super().__init__(text,None, False)
|
10
|
+
self.radio_value : Any = radio_value if radio_value is not None else text if text else None
|
11
|
+
self.radio_variable : RadioVariable = None
|
12
|
+
|
13
|
+
def set_radio_value(self,value:Any)->Self:
|
14
|
+
self.radio_value = value
|
15
|
+
self.update_radio()
|
16
|
+
return self
|
17
|
+
|
18
|
+
def set_text(self, text: str) -> Self:
|
19
|
+
flag = False
|
20
|
+
if self.value == self.text or self.value is None: flag = True
|
21
|
+
super().set_text(text)
|
22
|
+
if flag:
|
23
|
+
self.set_radio_value(self.text)
|
24
|
+
return self
|
25
|
+
|
26
|
+
def click(self) -> None:
|
27
|
+
if self.radio_variable is None: return
|
28
|
+
self.radio_variable.set_value(self.radio_value)
|
29
|
+
|
30
|
+
class RadioVariable:
|
31
|
+
def __init__(self)->None:
|
32
|
+
self.buttons : list[RadioButton] = []
|
33
|
+
self.value = None
|
34
|
+
self.modify_callback : Callable[[Any],] = None
|
35
|
+
|
36
|
+
def link(self,*buttons:RadioButton)->Self:
|
37
|
+
if not buttons : return self
|
38
|
+
for b in buttons :
|
39
|
+
b.radio_variable = self
|
40
|
+
self.buttons.extend(buttons)
|
41
|
+
|
42
|
+
if self.value is None:
|
43
|
+
self.set_value(buttons[0].radio_value)
|
44
|
+
else:
|
45
|
+
self.update_buttons()
|
46
|
+
return self
|
47
|
+
|
48
|
+
def unlink(self,*buttons)->Self:
|
49
|
+
for b in self.buttons:
|
50
|
+
if b in buttons:
|
51
|
+
b.radio_variable = None
|
52
|
+
self.buttons = [b for b in self.buttons if b not in buttons]
|
53
|
+
return self
|
54
|
+
|
55
|
+
def set_value(self,value:Any):
|
56
|
+
if value == self.value: return
|
57
|
+
self.value = value
|
58
|
+
if self.modify_callback :self.modify_callback(value)
|
59
|
+
self.update_buttons()
|
60
|
+
|
61
|
+
def update_buttons(self):
|
62
|
+
_ = [b.set_value(b.radio_value == self.value,False) for b in self.buttons]
|
batFramework/gui/root.py
CHANGED
@@ -5,36 +5,39 @@ import pygame
|
|
5
5
|
|
6
6
|
|
7
7
|
class Root(InteractiveWidget):
|
8
|
-
def __init__(self,camera)->None:
|
8
|
+
def __init__(self, camera) -> None:
|
9
9
|
super().__init__()
|
10
|
-
self.
|
11
|
-
self.
|
12
|
-
self.
|
10
|
+
self.is_root = True
|
11
|
+
self.drawing_camera: bf.Camera = camera
|
12
|
+
self.visible = False
|
13
13
|
self.rect.size = pygame.display.get_surface().get_size()
|
14
|
-
self.focused: InteractiveWidget |None= self
|
14
|
+
self.focused: InteractiveWidget | None = self
|
15
15
|
self.hovered: Widget | None = self
|
16
|
-
self.set_debug_color("
|
16
|
+
self.set_debug_color("yellow")
|
17
|
+
self.set_render_order(999)
|
18
|
+
self.clip_children = False
|
17
19
|
|
18
|
-
def
|
19
|
-
return "
|
20
|
+
def __str__(self) -> str:
|
21
|
+
return "Root"
|
20
22
|
|
21
|
-
def to_string_id(self) -> str:
|
22
|
-
return "ROOT"
|
23
|
-
|
24
23
|
def get_focused(self) -> Widget | None:
|
25
24
|
return self.focused
|
26
25
|
|
27
26
|
def get_hovered(self) -> Widget | None:
|
28
27
|
return self.hovered
|
29
28
|
|
30
|
-
def clear_focused(self)->None:
|
29
|
+
def clear_focused(self) -> None:
|
31
30
|
self.focus_on(None)
|
32
31
|
|
33
|
-
def clear_hovered(self)->None:
|
34
|
-
if isinstance(self.hovered,InteractiveWidget):
|
32
|
+
def clear_hovered(self) -> None:
|
33
|
+
if isinstance(self.hovered, InteractiveWidget):
|
34
|
+
self.hovered.on_exit()
|
35
35
|
self.hovered = None
|
36
36
|
|
37
|
-
def focus_on(self, widget: InteractiveWidget|None) -> None:
|
37
|
+
def focus_on(self, widget: InteractiveWidget | None) -> None:
|
38
|
+
if widget == self.focused : return
|
39
|
+
if widget and not widget.allow_focus_to_self():
|
40
|
+
return
|
38
41
|
if self.focused is not None:
|
39
42
|
self.focused.on_lose_focus()
|
40
43
|
if widget is None:
|
@@ -43,59 +46,80 @@ class Root(InteractiveWidget):
|
|
43
46
|
self.focused = widget
|
44
47
|
self.focused.on_get_focus()
|
45
48
|
|
46
|
-
def
|
49
|
+
def get_by_tags(self,*tags)->list[Widget]:
|
50
|
+
res = []
|
51
|
+
def getter(w:Widget):
|
52
|
+
nonlocal res
|
53
|
+
if any(t in w.tags for t in tags):
|
54
|
+
res.append(w)
|
55
|
+
self.visit(getter)
|
56
|
+
return res
|
57
|
+
|
58
|
+
def get_by_uid(self,uid:int)->Widget:
|
59
|
+
def helper(w: Widget,uid):
|
60
|
+
if w.uid == uid:
|
61
|
+
return w
|
62
|
+
for child in w.children:
|
63
|
+
res = helper(child,uid)
|
64
|
+
if res :
|
65
|
+
return child
|
66
|
+
|
67
|
+
return None
|
68
|
+
return helper(self,uid)
|
69
|
+
|
70
|
+
def set_size(self, size: tuple[float, float], force: bool = False) -> "Root":
|
47
71
|
if not force:
|
48
72
|
return self
|
49
|
-
self.rect.size =
|
50
|
-
self.build(
|
73
|
+
self.rect.size = size
|
74
|
+
# self.build(resolve_constraints=True)
|
51
75
|
return self
|
52
76
|
|
53
|
-
def build(self, apply_constraints: bool = False) -> None:
|
54
|
-
if apply_constraints:
|
55
|
-
self.apply_all_constraints()
|
56
|
-
for child in self.children:
|
57
|
-
child.build()
|
58
77
|
|
59
78
|
def do_handle_event(self, event):
|
60
|
-
if event.type == pygame.VIDEORESIZE:
|
61
|
-
|
62
|
-
|
79
|
+
# if event.type == pygame.VIDEORESIZE:
|
80
|
+
# self.set_size(event.w, event.h, force=True)
|
81
|
+
# return True
|
82
|
+
if self.focused:
|
83
|
+
if event.type == pygame.KEYDOWN:
|
84
|
+
self.focused.on_key_down(event.key)
|
85
|
+
if event.type == pygame.KEYUP:
|
86
|
+
self.focused.on_key_up(event.key)
|
87
|
+
elif not self.hovered or not isinstance(self.hovered, InteractiveWidget):
|
88
|
+
return
|
63
89
|
if event.type == pygame.MOUSEBUTTONDOWN:
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
if self.hovered and isinstance(self.hovered,InteractiveWidget) :
|
68
|
-
self.hovered.on_click_up(event.button)
|
69
|
-
|
70
|
-
return False
|
90
|
+
self.hovered.on_click_down(event.button)
|
91
|
+
elif event.type == pygame.MOUSEBUTTONUP:
|
92
|
+
self.hovered.on_click_up(event.button)
|
71
93
|
|
72
|
-
def get_root(self) -> "Root" :
|
73
|
-
return self
|
74
94
|
|
75
|
-
def do_on_click_down(self,button:int)->None:
|
76
|
-
if button == 1
|
95
|
+
def do_on_click_down(self, button: int) -> None:
|
96
|
+
if button == 1:
|
97
|
+
self.clear_focused()
|
77
98
|
|
78
|
-
def top_at(self, x: float|int, y: float|int) -> "None|Widget":
|
99
|
+
def top_at(self, x: float | int, y: float | int) -> "None|Widget":
|
79
100
|
if self.children:
|
80
101
|
for child in reversed(self.children):
|
81
102
|
r = child.top_at(x, y)
|
82
103
|
if r is not None:
|
83
104
|
return r
|
84
|
-
return self if self.rect.collidepoint(x,y) else None
|
105
|
+
return self if self.rect.collidepoint(x, y) else None
|
85
106
|
|
86
107
|
def update(self, dt: float) -> None:
|
87
108
|
super().update(dt)
|
88
109
|
old = self.hovered
|
89
|
-
transposed = self.drawing_camera.
|
90
|
-
self.hovered = (
|
91
|
-
|
92
|
-
|
93
|
-
else None
|
94
|
-
)
|
95
|
-
if old == self.hovered:
|
110
|
+
transposed = self.drawing_camera.screen_to_world(pygame.mouse.get_pos())
|
111
|
+
self.hovered = self.top_at(*transposed) if self.top_at(*transposed) else None
|
112
|
+
if old == self.hovered and isinstance(self.hovered, InteractiveWidget):
|
113
|
+
self.hovered.on_mouse_motion(*transposed)
|
96
114
|
return
|
97
|
-
if old and isinstance(old,InteractiveWidget):
|
115
|
+
if old and isinstance(old, InteractiveWidget):
|
98
116
|
old.on_exit()
|
99
|
-
if self.hovered and isinstance(self.hovered,InteractiveWidget)
|
117
|
+
if self.hovered and isinstance(self.hovered, InteractiveWidget):
|
100
118
|
self.hovered.on_enter()
|
101
119
|
|
120
|
+
def draw(self, camera: bf.Camera) -> int:
|
121
|
+
super().draw(camera)
|
122
|
+
if self.focused and self.focused!=self:
|
123
|
+
self.focused.draw_focused(camera)
|
124
|
+
|
125
|
+
|