batframework 1.0.9a7__py3-none-any.whl → 1.0.9a8__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 -1
- 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 +3 -1
- batFramework/gui/animatedLabel.py +10 -2
- batFramework/gui/button.py +4 -31
- batFramework/gui/clickableWidget.py +42 -30
- batFramework/gui/constraints/constraints.py +212 -136
- batFramework/gui/container.py +72 -48
- batFramework/gui/debugger.py +12 -17
- batFramework/gui/draggableWidget.py +8 -11
- batFramework/gui/image.py +3 -10
- batFramework/gui/indicator.py +73 -1
- batFramework/gui/interactiveWidget.py +117 -100
- batFramework/gui/label.py +73 -63
- batFramework/gui/layout.py +221 -452
- batFramework/gui/meter.py +21 -7
- batFramework/gui/radioButton.py +0 -1
- batFramework/gui/root.py +99 -29
- batFramework/gui/selector.py +257 -0
- batFramework/gui/shape.py +13 -5
- batFramework/gui/slider.py +260 -93
- batFramework/gui/textInput.py +45 -21
- batFramework/gui/toggle.py +70 -52
- batFramework/gui/tooltip.py +30 -0
- batFramework/gui/widget.py +203 -125
- 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 +121 -3
- {batframework-1.0.9a7.dist-info → batframework-1.0.9a8.dist-info}/METADATA +24 -3
- batframework-1.0.9a8.dist-info/RECORD +66 -0
- {batframework-1.0.9a7.dist-info → batframework-1.0.9a8.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.9a8.dist-info/LICENSE +0 -0
- {batframework-1.0.9a7.dist-info → batframework-1.0.9a8.dist-info}/top_level.txt +0 -0
batFramework/gui/meter.py
CHANGED
@@ -12,6 +12,7 @@ def custom_top_at(self, x, y):
|
|
12
12
|
class Meter(Shape):
|
13
13
|
def __init__(self, min_value: float = 0, max_value: float = 1, step: float = 0.1):
|
14
14
|
super().__init__()
|
15
|
+
self.axis: bf.axis = bf.axis.HORIZONTAL
|
15
16
|
self.min_value, self.max_value = min_value, max_value
|
16
17
|
self.step = step
|
17
18
|
self.snap: bool = False
|
@@ -29,6 +30,11 @@ class Meter(Shape):
|
|
29
30
|
def __str__(self) -> str:
|
30
31
|
return "Meter"
|
31
32
|
|
33
|
+
def set_axis(self,axis:bf.axis)->Self:
|
34
|
+
self.axis = axis
|
35
|
+
self.dirty_shape = True
|
36
|
+
return self
|
37
|
+
|
32
38
|
def set_step(self, step: float) -> Self:
|
33
39
|
self.step = step
|
34
40
|
self.set_value(self.value)
|
@@ -36,9 +42,6 @@ class Meter(Shape):
|
|
36
42
|
|
37
43
|
def set_range(self, range_min: float, range_max: float) -> Self:
|
38
44
|
if range_min >= range_max:
|
39
|
-
print(
|
40
|
-
f"[Warning] : minimum value {range_min} is greater than or equal to maximum value {range_max}"
|
41
|
-
)
|
42
45
|
return self
|
43
46
|
self.min_value = range_min
|
44
47
|
self.max_value = range_max
|
@@ -65,10 +68,21 @@ class Meter(Shape):
|
|
65
68
|
return (self.value-self.min_value) / (self.max_value - self.min_value)
|
66
69
|
|
67
70
|
def _build_content(self) -> None:
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
+
padded = self.get_inner_rect()
|
72
|
+
ratio = self.get_ratio()
|
73
|
+
|
74
|
+
if self.axis == bf.axis.HORIZONTAL:
|
75
|
+
width = padded.width * ratio
|
76
|
+
self.content.set_size((width, padded.height))
|
77
|
+
self.content.rect.topleft = padded.topleft
|
78
|
+
|
79
|
+
else: # VERTICAL
|
80
|
+
height = padded.height * ratio
|
81
|
+
self.content.set_size((padded.width, height))
|
82
|
+
# Content grows from bottom up
|
83
|
+
self.content.rect.bottomleft = padded.bottomleft
|
84
|
+
|
71
85
|
|
72
86
|
def build(self) -> None:
|
73
|
-
super().build()
|
74
87
|
self._build_content()
|
88
|
+
super().build()
|
batFramework/gui/radioButton.py
CHANGED
batFramework/gui/root.py
CHANGED
@@ -15,15 +15,28 @@ class Root(InteractiveWidget):
|
|
15
15
|
self.rect.size = pygame.display.get_surface().get_size()
|
16
16
|
self.focused: InteractiveWidget | None = self
|
17
17
|
self.hovered: Widget | None = self
|
18
|
-
self.set_debug_color("yellow")
|
19
|
-
self.set_render_order(sys.maxsize)
|
20
18
|
self.clip_children = False
|
19
|
+
self.set_debug_color("yellow")
|
20
|
+
|
21
|
+
self.show_tooltip : bool = True
|
22
|
+
self.tooltip = bf.gui.ToolTip("").set_visible(False)
|
23
|
+
self.add(self.tooltip)
|
21
24
|
|
25
|
+
def toggle_tooltip(self,value:bool)->Self:
|
26
|
+
self.show_tooltip = value
|
27
|
+
return self
|
28
|
+
|
22
29
|
def __str__(self) -> str:
|
23
30
|
return "Root"
|
31
|
+
|
32
|
+
def to_ascii_tree(self) -> str:
|
33
|
+
def f(w, depth):
|
34
|
+
prefix = " " * (depth * 4) + ("└── " if depth > 0 else "")
|
35
|
+
children = "\n".join(f(c, depth + 1) for c in w.children) if w.children else ""
|
36
|
+
return f"{prefix}{str(w)}\n{children}"
|
37
|
+
return f(self, 0)
|
24
38
|
|
25
39
|
def set_parent_scene(self, parent_scene: bf.Scene) -> Self:
|
26
|
-
bf.StyleManager().register_widget(self)
|
27
40
|
return super().set_parent_scene(parent_scene)
|
28
41
|
|
29
42
|
def get_focused(self) -> Widget | None:
|
@@ -91,28 +104,36 @@ class Root(InteractiveWidget):
|
|
91
104
|
if not force:
|
92
105
|
return self
|
93
106
|
self.rect.size = size
|
107
|
+
self.dirty_shape = True
|
108
|
+
self.dirty_size_constraints = True
|
94
109
|
return self
|
95
110
|
|
96
|
-
def
|
111
|
+
def process_event(self,event):
|
112
|
+
if event.consumed : return
|
113
|
+
self.do_handle_event_early(event)
|
114
|
+
if event.consumed : return
|
115
|
+
super().process_event(event)
|
116
|
+
|
117
|
+
def do_handle_event_early(self, event):
|
118
|
+
if event.type == pygame.VIDEORESIZE:
|
119
|
+
self.set_size((event.w,event.h),force=True)
|
97
120
|
if self.focused:
|
98
121
|
if event.type == pygame.KEYDOWN:
|
99
|
-
|
100
|
-
|
122
|
+
event.consumed = self.focused.on_key_down(event.key)
|
123
|
+
if not event.consumed :
|
124
|
+
event.consumed = self._handle_alt_tab(event.key)
|
101
125
|
elif event.type == pygame.KEYUP:
|
102
|
-
|
103
|
-
event.consumed = True
|
126
|
+
event.consumed = self.focused.on_key_up(event.key)
|
104
127
|
|
105
128
|
if not self.hovered or (not isinstance(self.hovered, InteractiveWidget)):
|
106
129
|
return
|
107
130
|
|
108
131
|
if event.type == pygame.MOUSEBUTTONDOWN:
|
109
|
-
|
110
|
-
event.consumed = True
|
132
|
+
event.consumed = self.hovered.on_click_down(event.button)
|
111
133
|
|
112
134
|
elif event.type == pygame.MOUSEBUTTONUP:
|
113
|
-
|
114
|
-
|
115
|
-
|
135
|
+
event.consumed = self.hovered.on_click_up(event.button)
|
136
|
+
|
116
137
|
def do_on_click_down(self, button: int) -> None:
|
117
138
|
if button == 1:
|
118
139
|
self.clear_focused()
|
@@ -127,25 +148,68 @@ class Root(InteractiveWidget):
|
|
127
148
|
|
128
149
|
def update(self, dt: float) -> None:
|
129
150
|
super().update(dt)
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
151
|
+
self.update_tree()
|
152
|
+
|
153
|
+
mouse_screen = pygame.mouse.get_pos()
|
154
|
+
mouse_world = self.drawing_camera.screen_to_world(mouse_screen)
|
155
|
+
prev_hovered = self.hovered
|
156
|
+
self.hovered = self.top_at(*mouse_world) or None
|
157
|
+
|
158
|
+
# Tooltip logic
|
159
|
+
if self.hovered and self.hovered.tooltip_text:
|
160
|
+
self.tooltip.set_text(self.hovered.tooltip_text)
|
161
|
+
|
162
|
+
tooltip_size = self.tooltip.get_min_required_size()
|
163
|
+
screen_w, screen_h = self.drawing_camera.rect.size
|
164
|
+
tooltip_x, tooltip_y = self.drawing_camera.world_to_screen_point(mouse_world)
|
165
|
+
|
166
|
+
tooltip_x = min(tooltip_x, screen_w - tooltip_size[0])
|
167
|
+
tooltip_y = min(tooltip_y, screen_h - tooltip_size[1])
|
168
|
+
tooltip_x = max(0, tooltip_x)
|
169
|
+
tooltip_y = max(0, tooltip_y)
|
170
|
+
|
171
|
+
self.tooltip.set_position(tooltip_x, tooltip_y)
|
172
|
+
self.tooltip.fade_in()
|
173
|
+
else:
|
174
|
+
self.tooltip.fade_out()
|
175
|
+
|
176
|
+
if self.hovered == prev_hovered:
|
177
|
+
if isinstance(self.hovered, InteractiveWidget):
|
178
|
+
self.hovered.on_mouse_motion(*mouse_world)
|
135
179
|
return
|
136
|
-
|
137
|
-
|
138
|
-
|
180
|
+
|
181
|
+
if isinstance(prev_hovered, InteractiveWidget):
|
182
|
+
prev_hovered.on_exit()
|
183
|
+
if isinstance(self.hovered, InteractiveWidget):
|
139
184
|
self.hovered.on_enter()
|
140
185
|
|
141
|
-
def apply_updates(self):
|
142
|
-
if any(child.dirty_shape for child in self.children):
|
143
|
-
self.dirty_shape = True # Mark layout as dirty if any child changed size
|
144
186
|
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
187
|
+
def _handle_alt_tab(self,key):
|
188
|
+
if self.focused is None:
|
189
|
+
return False
|
190
|
+
if key != pygame.K_TAB:
|
191
|
+
return False
|
192
|
+
keys = pygame.key.get_pressed()
|
193
|
+
if keys[pygame.K_LSHIFT] or keys[pygame.K_RSHIFT]:
|
194
|
+
self.focused.focus_prev_tab(self.focused)
|
195
|
+
else:
|
196
|
+
self.focused.focus_next_tab(self.focused)
|
197
|
+
return True
|
198
|
+
|
199
|
+
def update_tree(self):
|
200
|
+
# print("START updating tree")
|
201
|
+
self.apply_updates("pre")
|
202
|
+
self.apply_updates("post")
|
203
|
+
self.apply_updates("pre")
|
204
|
+
self.apply_updates("post")
|
205
|
+
|
206
|
+
# print("END updating tree")
|
207
|
+
|
208
|
+
def apply_pre_updates(self):
|
209
|
+
return
|
210
|
+
|
211
|
+
def apply_post_updates(self, skip_draw = False):
|
212
|
+
return
|
149
213
|
|
150
214
|
def draw(self, camera: bf.Camera) -> None:
|
151
215
|
super().draw(camera)
|
@@ -155,4 +219,10 @@ class Root(InteractiveWidget):
|
|
155
219
|
and self.focused
|
156
220
|
and self.focused != self
|
157
221
|
):
|
158
|
-
self.focused.
|
222
|
+
clip:bool =self.focused.parent and self.focused.parent.clip_children
|
223
|
+
if clip:
|
224
|
+
old_clip = camera.surface.get_clip()
|
225
|
+
camera.surface.set_clip(camera.world_to_screen(self.focused.parent.rect))
|
226
|
+
if clip:
|
227
|
+
camera.surface.set_clip(old_clip)
|
228
|
+
self.focused.draw_focused(camera)
|
@@ -0,0 +1,257 @@
|
|
1
|
+
import batFramework as bf
|
2
|
+
import pygame
|
3
|
+
from typing import Self,Callable,Any
|
4
|
+
from .button import Button
|
5
|
+
from .indicator import ArrowIndicator
|
6
|
+
from .clickableWidget import ClickableWidget
|
7
|
+
from .widget import Widget
|
8
|
+
|
9
|
+
class MyArrow(ArrowIndicator,ClickableWidget):
|
10
|
+
def top_at(self,x,y):
|
11
|
+
return Widget.top_at(self,x,y)
|
12
|
+
|
13
|
+
def get_focus(self):
|
14
|
+
return self.parent.get_focus()
|
15
|
+
|
16
|
+
class Selector(Button):
|
17
|
+
def __init__(self,options:list[str]=None,default_value:str=None,allow_cycle:bool=False):
|
18
|
+
super().__init__('')
|
19
|
+
self.allow_cycle = allow_cycle
|
20
|
+
self.current_index = 0
|
21
|
+
self.on_modify_callback : Callable[[str,int],Any] = None
|
22
|
+
self.options = options if options else []
|
23
|
+
self.gap : int = 2
|
24
|
+
self.indicator_height = 0
|
25
|
+
text_value = ""
|
26
|
+
|
27
|
+
|
28
|
+
if not (default_value is not None and default_value in self.options):
|
29
|
+
default_value = options[0]
|
30
|
+
|
31
|
+
text_value = default_value
|
32
|
+
self.current_index = self.options.index(default_value)
|
33
|
+
|
34
|
+
self.left_indicator : MyArrow = (MyArrow(bf.direction.LEFT)
|
35
|
+
.set_draw_stem(False)
|
36
|
+
.set_color((0,0,0,0)).set_arrow_color(self.text_color)
|
37
|
+
.set_callback(lambda : self.set_by_index(self.get_current_index()-1))
|
38
|
+
)
|
39
|
+
|
40
|
+
self.right_indicator:MyArrow =(MyArrow(bf.direction.RIGHT)
|
41
|
+
.set_draw_stem(False)
|
42
|
+
.set_color((0,0,0,0)).set_arrow_color(self.text_color)
|
43
|
+
.set_callback(lambda : self.set_by_index(self.get_current_index()+1))
|
44
|
+
)
|
45
|
+
|
46
|
+
self.add(self.left_indicator,self.right_indicator)
|
47
|
+
self.set_clip_children(False)
|
48
|
+
self.set_text(text_value)
|
49
|
+
|
50
|
+
def __str__(self):
|
51
|
+
return f"Selector[{self.options[self.current_index]}]"
|
52
|
+
|
53
|
+
def set_gap(self,value:int)->Self:
|
54
|
+
self.gap = value
|
55
|
+
self.dirty_shape = True
|
56
|
+
return self
|
57
|
+
|
58
|
+
def disable(self):
|
59
|
+
super().disable()
|
60
|
+
self.left_indicator.disable()
|
61
|
+
self.right_indicator.disable()
|
62
|
+
return self
|
63
|
+
|
64
|
+
def enable(self):
|
65
|
+
super().enable()
|
66
|
+
self.right_indicator.enable()
|
67
|
+
self.left_indicator.enable()
|
68
|
+
index = self.current_index
|
69
|
+
if not self.allow_cycle:
|
70
|
+
if index == 0:
|
71
|
+
self.left_indicator.disable()
|
72
|
+
else:
|
73
|
+
self.left_indicator.enable()
|
74
|
+
if index == len(self.options)-1:
|
75
|
+
self.right_indicator.disable()
|
76
|
+
else:
|
77
|
+
self.right_indicator.enable()
|
78
|
+
|
79
|
+
|
80
|
+
return self
|
81
|
+
|
82
|
+
def set_tooltip_text(self, text):
|
83
|
+
self.left_indicator.set_tooltip_text(text)
|
84
|
+
self.right_indicator.set_tooltip_text(text)
|
85
|
+
return super().set_tooltip_text(text)
|
86
|
+
|
87
|
+
def get_min_required_size(self) -> tuple[float, float]:
|
88
|
+
"""
|
89
|
+
Calculates the minimum size required for the selector, including text and indicators.
|
90
|
+
"""
|
91
|
+
|
92
|
+
# Calculate the maximum size needed for the text
|
93
|
+
old_text = self.text
|
94
|
+
max_text_size = (0, 0)
|
95
|
+
for option in self.options:
|
96
|
+
self.text = option
|
97
|
+
text_size = self._get_text_rect_required_size()
|
98
|
+
max_text_size = max(max_text_size[0], text_size[0]), max(max_text_size[1], text_size[1])
|
99
|
+
self.text = old_text
|
100
|
+
|
101
|
+
# Ensure total_height is always an odd integer
|
102
|
+
total_height = max(8, max_text_size[1] * 1.5)
|
103
|
+
total_height += self.unpressed_relief
|
104
|
+
total_height += max(self.right_indicator.outline_width,self.left_indicator.outline_width)
|
105
|
+
self.indicator_height = total_height
|
106
|
+
|
107
|
+
# Calculate total width and height
|
108
|
+
total_width = (
|
109
|
+
self.indicator_height*2+
|
110
|
+
max_text_size[0] + # Text width
|
111
|
+
self.gap * 2 # Gaps between text and indicators
|
112
|
+
)
|
113
|
+
# Inflate by padding at the very end
|
114
|
+
final_size = self.expand_rect_with_padding((0, 0, total_width, total_height)).size
|
115
|
+
|
116
|
+
return final_size
|
117
|
+
|
118
|
+
|
119
|
+
|
120
|
+
def _align_content(self):
|
121
|
+
"""
|
122
|
+
Builds the selector layout (places and resizes the indicators)
|
123
|
+
"""
|
124
|
+
|
125
|
+
# return
|
126
|
+
# Step 1: Calculate the padded area for positioning
|
127
|
+
padded = self.get_inner_rect()
|
128
|
+
|
129
|
+
|
130
|
+
# left_size = self.left_indicator.rect.size
|
131
|
+
right_size = self.right_indicator.rect.size
|
132
|
+
|
133
|
+
indicator_height = self.indicator_height
|
134
|
+
|
135
|
+
self.left_indicator.set_size((indicator_height,indicator_height))
|
136
|
+
self.right_indicator.set_size((indicator_height,indicator_height))
|
137
|
+
|
138
|
+
|
139
|
+
# Step 3: Position indicators
|
140
|
+
self.left_indicator.set_position(padded.left, None)
|
141
|
+
self.left_indicator.set_center(None, padded.centery)
|
142
|
+
|
143
|
+
self.right_indicator.set_position(padded.right - right_size[0], None)
|
144
|
+
self.right_indicator.set_center(None, padded.centery)
|
145
|
+
|
146
|
+
|
147
|
+
|
148
|
+
def build(self):
|
149
|
+
|
150
|
+
super().build()
|
151
|
+
self._align_content()
|
152
|
+
|
153
|
+
def get_current_index(self)->int:
|
154
|
+
return self.current_index
|
155
|
+
|
156
|
+
def set_allow_cycle(self,value:bool)->Self:
|
157
|
+
if value == self.allow_cycle: return self
|
158
|
+
self.allow_cycle = value
|
159
|
+
self.dirty_surface = True
|
160
|
+
return self
|
161
|
+
|
162
|
+
def set_text_color(self,color)->Self:
|
163
|
+
super().set_text_color(color)
|
164
|
+
self.left_indicator.set_arrow_color(color)
|
165
|
+
self.right_indicator.set_arrow_color(color)
|
166
|
+
return self
|
167
|
+
|
168
|
+
def set_modify_callback(self,function:Callable[[str,int],Any]):
|
169
|
+
"""
|
170
|
+
the function will receive the value and the index
|
171
|
+
"""
|
172
|
+
self.on_modify_callback = function
|
173
|
+
return self
|
174
|
+
|
175
|
+
|
176
|
+
|
177
|
+
def set_by_index(self,index:int)->Self:
|
178
|
+
if self.allow_cycle:
|
179
|
+
index = index%len(self.options)
|
180
|
+
else:
|
181
|
+
index = max(min(len(self.options)-1,index),0)
|
182
|
+
|
183
|
+
if index == self.current_index:
|
184
|
+
return self
|
185
|
+
|
186
|
+
|
187
|
+
self.current_index = index
|
188
|
+
self.set_text(self.options[self.current_index])
|
189
|
+
if self.on_modify_callback:
|
190
|
+
self.on_modify_callback(self.options[self.current_index],self.current_index)
|
191
|
+
if not self.allow_cycle:
|
192
|
+
if index == 0:
|
193
|
+
self.left_indicator.disable()
|
194
|
+
else:
|
195
|
+
self.left_indicator.enable()
|
196
|
+
if index == len(self.options)-1:
|
197
|
+
self.right_indicator.disable()
|
198
|
+
else:
|
199
|
+
self.right_indicator.enable()
|
200
|
+
return self
|
201
|
+
|
202
|
+
def paint(self):
|
203
|
+
super().paint()
|
204
|
+
self.left_indicator.show()
|
205
|
+
self.right_indicator.show()
|
206
|
+
if not self.allow_cycle and self.current_index == 0:
|
207
|
+
self.left_indicator.hide()
|
208
|
+
elif not self.allow_cycle and self.current_index== len(self.options)-1:
|
209
|
+
self.right_indicator.hide()
|
210
|
+
|
211
|
+
def set_by_value(self,value:str)->Self:
|
212
|
+
if not self.enabled : return
|
213
|
+
if value not in self.options : return self
|
214
|
+
index = self.options.index(value)
|
215
|
+
self.set_by_index(index)
|
216
|
+
return self
|
217
|
+
|
218
|
+
def on_key_down(self, key: int) -> bool:
|
219
|
+
if not self.enabled:
|
220
|
+
return False
|
221
|
+
|
222
|
+
key_actions = {
|
223
|
+
pygame.K_RIGHT: self.right_indicator,
|
224
|
+
pygame.K_SPACE: self.right_indicator,
|
225
|
+
pygame.K_LEFT: self.left_indicator
|
226
|
+
}
|
227
|
+
|
228
|
+
indicator = key_actions.get(key)
|
229
|
+
if indicator and indicator.visible and indicator.enabled:
|
230
|
+
indicator.on_click_down(1)
|
231
|
+
return True
|
232
|
+
|
233
|
+
return False
|
234
|
+
|
235
|
+
def on_key_up(self, key: int) -> bool:
|
236
|
+
if not self.enabled:
|
237
|
+
return False
|
238
|
+
|
239
|
+
key_actions = {
|
240
|
+
pygame.K_RIGHT: self.right_indicator,
|
241
|
+
pygame.K_SPACE: self.right_indicator,
|
242
|
+
pygame.K_LEFT: self.left_indicator
|
243
|
+
}
|
244
|
+
|
245
|
+
indicator = key_actions.get(key)
|
246
|
+
if indicator and indicator.visible and indicator.enabled:
|
247
|
+
indicator.on_click_up(1)
|
248
|
+
return True
|
249
|
+
|
250
|
+
return False
|
251
|
+
|
252
|
+
def do_on_click_down(self, button) -> None:
|
253
|
+
if self.enabled and button == 1:
|
254
|
+
if not self.get_focus():
|
255
|
+
return True
|
256
|
+
return False
|
257
|
+
|
batFramework/gui/shape.py
CHANGED
@@ -18,16 +18,24 @@ class Shape(Widget):
|
|
18
18
|
self.shadow_color: tuple[int, int, int] | str = (0, 0, 0, 255)
|
19
19
|
self.draw_mode = bf.drawMode.SOLID
|
20
20
|
|
21
|
-
def
|
21
|
+
def get_inner_bottom(self) -> float:
|
22
22
|
return self.rect.bottom - self.padding[3] - self.relief
|
23
23
|
|
24
|
-
def
|
24
|
+
def get_inner_height(self) -> float:
|
25
25
|
return self.rect.h - self.padding[1] - self.padding[3] - self.relief
|
26
26
|
|
27
|
-
def
|
28
|
-
return self.rect.y + self.
|
27
|
+
def get_inner_top(self) -> float:
|
28
|
+
return self.rect.y + self.padding[1]
|
29
29
|
|
30
|
-
def
|
30
|
+
def get_local_padded_rect(self)->pygame.FRect:
|
31
|
+
return pygame.FRect(
|
32
|
+
self.padding[0],
|
33
|
+
self.padding[1],
|
34
|
+
self.rect.w - self.padding[2] - self.padding[0],
|
35
|
+
self.rect.h - self.padding[1] - self.padding[3] - self.relief,
|
36
|
+
)
|
37
|
+
|
38
|
+
def get_inner_rect(self) -> pygame.FRect:
|
31
39
|
return pygame.FRect(
|
32
40
|
self.rect.x + self.padding[0],
|
33
41
|
self.rect.y + self.padding[1],
|