batframework 1.0.8a1__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/action.py +30 -14
- batFramework/actionContainer.py +5 -3
- batFramework/audioManager.py +0 -1
- batFramework/camera.py +29 -24
- batFramework/cutscene.py +2 -4
- batFramework/entity.py +9 -2
- batFramework/enums.py +11 -2
- batFramework/fontManager.py +1 -1
- batFramework/gui/__init__.py +3 -1
- batFramework/gui/button.py +5 -2
- batFramework/gui/clickableWidget.py +42 -29
- batFramework/gui/constraints/constraints.py +269 -57
- batFramework/gui/container.py +39 -21
- batFramework/gui/debugger.py +18 -11
- batFramework/gui/dialogueBox.py +20 -17
- batFramework/gui/draggableWidget.py +7 -5
- batFramework/gui/image.py +27 -15
- batFramework/gui/indicator.py +1 -4
- batFramework/gui/interactiveWidget.py +91 -30
- batFramework/gui/label.py +44 -35
- batFramework/gui/layout.py +115 -43
- batFramework/gui/meter.py +3 -8
- batFramework/gui/radioButton.py +47 -25
- batFramework/gui/root.py +50 -25
- batFramework/gui/shape.py +14 -19
- batFramework/gui/slider.py +70 -44
- batFramework/gui/style.py +10 -0
- batFramework/gui/styleManager.py +48 -0
- batFramework/gui/textInput.py +25 -22
- batFramework/gui/toggle.py +42 -29
- batFramework/gui/widget.py +176 -115
- batFramework/object.py +9 -10
- batFramework/renderGroup.py +7 -2
- batFramework/scene.py +70 -49
- batFramework/sceneManager.py +15 -20
- batFramework/scrollingSprite.py +5 -3
- batFramework/sprite.py +20 -14
- batFramework/stateMachine.py +1 -2
- batFramework/tileset.py +5 -5
- batFramework/utils.py +12 -10
- {batframework-1.0.8a1.dist-info → batframework-1.0.8a3.dist-info}/METADATA +1 -1
- batframework-1.0.8a3.dist-info/RECORD +58 -0
- {batframework-1.0.8a1.dist-info → batframework-1.0.8a3.dist-info}/WHEEL +1 -1
- batframework-1.0.8a1.dist-info/RECORD +0 -56
- {batframework-1.0.8a1.dist-info → batframework-1.0.8a3.dist-info}/LICENCE +0 -0
- {batframework-1.0.8a1.dist-info → batframework-1.0.8a3.dist-info}/top_level.txt +0 -0
@@ -37,7 +37,7 @@ class MinWidth(Constraint):
|
|
37
37
|
return child_widget.rect.width >= self.min_width
|
38
38
|
|
39
39
|
def apply_constraint(self, parent_widget, child_widget):
|
40
|
-
child_widget.set_size((self.min_width,None))
|
40
|
+
child_widget.set_size((self.min_width, None))
|
41
41
|
|
42
42
|
|
43
43
|
class MinHeight(Constraint):
|
@@ -57,12 +57,14 @@ class CenterX(Constraint):
|
|
57
57
|
super().__init__(name="centerx")
|
58
58
|
|
59
59
|
def evaluate(self, parent_widget, child_widget):
|
60
|
-
return
|
60
|
+
return (
|
61
|
+
int(child_widget.rect.centerx - parent_widget.get_padded_center()[0]) == 0
|
62
|
+
)
|
61
63
|
|
62
64
|
def apply_constraint(self, parent_widget, child_widget):
|
63
65
|
child_widget.set_center(
|
64
|
-
|
65
|
-
|
66
|
+
parent_widget.get_padded_center()[0], child_widget.rect.centery
|
67
|
+
)
|
66
68
|
|
67
69
|
|
68
70
|
class CenterY(Constraint):
|
@@ -70,12 +72,14 @@ class CenterY(Constraint):
|
|
70
72
|
super().__init__(name="centery")
|
71
73
|
|
72
74
|
def evaluate(self, parent_widget, child_widget):
|
73
|
-
return
|
75
|
+
return (
|
76
|
+
int(child_widget.rect.centery - parent_widget.get_padded_center()[1]) == 0
|
77
|
+
)
|
74
78
|
|
75
79
|
def apply_constraint(self, parent_widget, child_widget):
|
76
80
|
child_widget.set_center(
|
77
|
-
|
78
|
-
|
81
|
+
child_widget.rect.centerx, parent_widget.get_padded_center()[1]
|
82
|
+
)
|
79
83
|
|
80
84
|
|
81
85
|
class Center(Constraint):
|
@@ -83,8 +87,11 @@ class Center(Constraint):
|
|
83
87
|
super().__init__(name="center")
|
84
88
|
|
85
89
|
def evaluate(self, parent_widget, child_widget):
|
86
|
-
return
|
87
|
-
|
90
|
+
return (
|
91
|
+
int(child_widget.rect.centerx - parent_widget.get_padded_center()[0]) == 0
|
92
|
+
and int(child_widget.rect.centery - parent_widget.get_padded_center()[1])
|
93
|
+
== 0
|
94
|
+
)
|
88
95
|
|
89
96
|
def apply_constraint(self, parent_widget, child_widget):
|
90
97
|
child_widget.set_center(*parent_widget.get_padded_center())
|
@@ -114,10 +121,10 @@ class PercentageWidth(Constraint):
|
|
114
121
|
child_widget.set_autoresize_w(False)
|
115
122
|
|
116
123
|
child_widget.set_size(
|
117
|
-
(
|
118
|
-
round(parent_widget.get_padded_width() * self.percentage),None)
|
124
|
+
(round(parent_widget.get_padded_width() * self.percentage), None)
|
119
125
|
)
|
120
126
|
|
127
|
+
|
121
128
|
class PercentageHeight(Constraint):
|
122
129
|
def __init__(self, percentage: float, keep_autoresize: bool = False):
|
123
130
|
super().__init__(name="percentage_height")
|
@@ -125,7 +132,9 @@ class PercentageHeight(Constraint):
|
|
125
132
|
self.keep_autoresize: bool = keep_autoresize
|
126
133
|
|
127
134
|
def evaluate(self, parent_widget, child_widget):
|
128
|
-
return child_widget.rect.height == round(
|
135
|
+
return child_widget.rect.height == round(
|
136
|
+
parent_widget.get_padded_height() * self.percentage
|
137
|
+
)
|
129
138
|
|
130
139
|
def __str__(self) -> str:
|
131
140
|
return f"{super().__str__()}.[{self.percentage*100}%,keep_autoresize={self.keep_autoresize}]"
|
@@ -133,68 +142,90 @@ class PercentageHeight(Constraint):
|
|
133
142
|
def apply_constraint(self, parent_widget, child_widget):
|
134
143
|
if child_widget.autoresize_h:
|
135
144
|
if self.keep_autoresize:
|
136
|
-
print(
|
145
|
+
print(
|
146
|
+
f"WARNING: Constraint on {child_widget} can't resize, autoresize set to True"
|
147
|
+
)
|
137
148
|
return
|
138
149
|
child_widget.set_autoresize_h(False)
|
139
|
-
child_widget.set_size(
|
150
|
+
child_widget.set_size(
|
151
|
+
(None, round(parent_widget.get_padded_height() * self.percentage))
|
152
|
+
)
|
153
|
+
|
140
154
|
|
141
155
|
class FillX(PercentageWidth):
|
142
156
|
def __init__(self, keep_autoresize: bool = False):
|
143
|
-
super().__init__(1,keep_autoresize)
|
157
|
+
super().__init__(1, keep_autoresize)
|
144
158
|
self.name = "fill_x"
|
145
159
|
|
160
|
+
|
146
161
|
class FillY(PercentageHeight):
|
147
162
|
def __init__(self, keep_autoresize: bool = False):
|
148
|
-
super().__init__(1,keep_autoresize)
|
163
|
+
super().__init__(1, keep_autoresize)
|
149
164
|
self.name = "fill_y"
|
150
165
|
|
151
166
|
|
152
|
-
class
|
153
|
-
def __init__(self,
|
154
|
-
|
155
|
-
|
156
|
-
super().__init__(name="height")
|
157
|
-
self.height = height
|
167
|
+
class PercentageRectHeight(Constraint):
|
168
|
+
def __init__(self, percentage: float, keep_autoresize: bool = False):
|
169
|
+
super().__init__(name="percentage_rect_height")
|
170
|
+
self.percentage: float = percentage
|
158
171
|
self.keep_autoresize: bool = keep_autoresize
|
159
172
|
|
160
|
-
def __str__(self) -> str:
|
161
|
-
return f"{super().__str__()}.(height={self.height})"
|
162
|
-
|
163
173
|
def evaluate(self, parent_widget, child_widget):
|
164
|
-
return child_widget.rect.height ==
|
174
|
+
return child_widget.rect.height == round(
|
175
|
+
parent_widget.rect.height * self.percentage
|
176
|
+
)
|
177
|
+
|
178
|
+
def __str__(self) -> str:
|
179
|
+
return f"{super().__str__()}.[{self.percentage*100}%, keep_autoresize={self.keep_autoresize}]"
|
165
180
|
|
166
181
|
def apply_constraint(self, parent_widget, child_widget):
|
167
182
|
if child_widget.autoresize_h:
|
168
183
|
if self.keep_autoresize:
|
169
|
-
print(
|
184
|
+
print(
|
185
|
+
f"WARNING: Constraint on {child_widget} can't resize, autoresize set to True"
|
186
|
+
)
|
170
187
|
return
|
171
188
|
child_widget.set_autoresize_h(False)
|
172
|
-
child_widget.set_size(
|
189
|
+
child_widget.set_size(
|
190
|
+
(None, round(parent_widget.rect.height * self.percentage))
|
191
|
+
)
|
173
192
|
|
174
193
|
|
175
|
-
class
|
176
|
-
def __init__(self,
|
177
|
-
|
178
|
-
|
179
|
-
super().__init__(name="width")
|
180
|
-
self.width = width
|
194
|
+
class PercentageRectWidth(Constraint):
|
195
|
+
def __init__(self, percentage: float, keep_autoresize: bool = False):
|
196
|
+
super().__init__(name="percentage_rect_width")
|
197
|
+
self.percentage: float = percentage
|
181
198
|
self.keep_autoresize: bool = keep_autoresize
|
182
199
|
|
183
|
-
def __str__(self) -> str:
|
184
|
-
return f"{super().__str__()}.(width={self.width})"
|
185
|
-
|
186
200
|
def evaluate(self, parent_widget, child_widget):
|
187
|
-
return child_widget.rect.width ==
|
201
|
+
return child_widget.rect.width == round(
|
202
|
+
parent_widget.rect.width * self.percentage
|
203
|
+
)
|
204
|
+
|
205
|
+
def __str__(self) -> str:
|
206
|
+
return f"{super().__str__()}.[{self.percentage*100}%, keep_autoresize={self.keep_autoresize}]"
|
188
207
|
|
189
208
|
def apply_constraint(self, parent_widget, child_widget):
|
190
209
|
if child_widget.autoresize_w:
|
191
210
|
if self.keep_autoresize:
|
192
211
|
print(
|
193
|
-
f"WARNING: Constraint on {child_widget
|
212
|
+
f"WARNING: Constraint on {child_widget} can't resize, autoresize set to True"
|
194
213
|
)
|
195
214
|
return
|
196
215
|
child_widget.set_autoresize_w(False)
|
197
|
-
child_widget.set_size((self.
|
216
|
+
child_widget.set_size((round(parent_widget.rect.width * self.percentage), None))
|
217
|
+
|
218
|
+
|
219
|
+
class FillRectX(PercentageRectWidth):
|
220
|
+
def __init__(self, keep_autoresize: bool = False):
|
221
|
+
super().__init__(1, keep_autoresize)
|
222
|
+
self.name = "fill_rect_x"
|
223
|
+
|
224
|
+
|
225
|
+
class FillRectY(PercentageRectHeight):
|
226
|
+
def __init__(self, keep_autoresize: bool = False):
|
227
|
+
super().__init__(1, keep_autoresize)
|
228
|
+
self.name = "fill_rect_y"
|
198
229
|
|
199
230
|
|
200
231
|
class AspectRatio(Constraint):
|
@@ -205,13 +236,17 @@ class AspectRatio(Constraint):
|
|
205
236
|
keep_autoresize=False,
|
206
237
|
):
|
207
238
|
super().__init__(name="aspect_ratio")
|
208
|
-
self.ref_axis
|
239
|
+
self.ref_axis: bf.axis = reference_axis
|
209
240
|
self.keep_autoresize: bool = keep_autoresize
|
210
241
|
|
211
242
|
if isinstance(ratio, float | int):
|
212
243
|
self.ratio = ratio
|
213
244
|
elif isinstance(ratio, pygame.rect.FRect):
|
214
|
-
self.ratio = (
|
245
|
+
self.ratio = (
|
246
|
+
(ratio.w / ratio.h)
|
247
|
+
if reference_axis == bf.axis.HORIZONTAL
|
248
|
+
else (ratio.h / ratio.w)
|
249
|
+
)
|
215
250
|
else:
|
216
251
|
raise TypeError(f"Ratio must be float or FRect")
|
217
252
|
|
@@ -224,17 +259,17 @@ class AspectRatio(Constraint):
|
|
224
259
|
def apply_constraint(self, parent_widget, child_widget):
|
225
260
|
|
226
261
|
if self.ref_axis == bf.axis.VERTICAL:
|
227
|
-
if child_widget.autoresize_w
|
262
|
+
if child_widget.autoresize_w:
|
228
263
|
if self.keep_autoresize:
|
229
264
|
print(
|
230
265
|
f"WARNING: Constraint on {child_widget.__str__()} can't resize, autoresize set to True"
|
231
266
|
)
|
232
267
|
return
|
233
268
|
child_widget.set_autoresize_w(False)
|
234
|
-
child_widget.set_size((child_widget.rect.h * self.ratio,None))
|
235
|
-
|
269
|
+
child_widget.set_size((child_widget.rect.h * self.ratio, None))
|
270
|
+
|
236
271
|
if self.ref_axis == bf.axis.HORIZONTAL:
|
237
|
-
if child_widget.autoresize_h
|
272
|
+
if child_widget.autoresize_h:
|
238
273
|
if self.keep_autoresize:
|
239
274
|
print(
|
240
275
|
f"WARNING: Constraint on {child_widget.__str__()} can't resize, autoresize set to True"
|
@@ -242,28 +277,39 @@ class AspectRatio(Constraint):
|
|
242
277
|
return
|
243
278
|
child_widget.set_autoresize_h(False)
|
244
279
|
print("HERE")
|
245
|
-
child_widget.set_size((None,child_widget.rect.w * self.ratio))
|
280
|
+
child_widget.set_size((None, child_widget.rect.w * self.ratio))
|
281
|
+
|
246
282
|
|
247
283
|
class AnchorBottom(Constraint):
|
248
284
|
def __init__(self):
|
249
285
|
super().__init__(name="anchor_bottom")
|
250
286
|
|
251
287
|
def evaluate(self, parent_widget, child_widget):
|
252
|
-
return
|
288
|
+
return (
|
289
|
+
child_widget.rect.top
|
290
|
+
== parent_widget.get_padded_bottom() - child_widget.rect.h
|
291
|
+
)
|
253
292
|
|
254
293
|
def apply_constraint(self, parent_widget, child_widget):
|
255
|
-
child_widget.set_position(
|
294
|
+
child_widget.set_position(
|
295
|
+
child_widget.rect.x, parent_widget.get_padded_bottom() - child_widget.rect.h
|
296
|
+
)
|
297
|
+
|
256
298
|
|
257
299
|
class AnchorBottom(Constraint):
|
258
300
|
def __init__(self):
|
259
301
|
super().__init__(name="anchor_bottom")
|
260
302
|
|
261
303
|
def evaluate(self, parent_widget, child_widget):
|
262
|
-
return
|
304
|
+
return (
|
305
|
+
child_widget.rect.top
|
306
|
+
== parent_widget.get_padded_bottom() - child_widget.rect.h
|
307
|
+
)
|
263
308
|
|
264
309
|
def apply_constraint(self, parent_widget, child_widget):
|
265
|
-
child_widget.set_position(
|
266
|
-
|
310
|
+
child_widget.set_position(
|
311
|
+
child_widget.rect.x, parent_widget.get_padded_bottom() - child_widget.rect.h
|
312
|
+
)
|
267
313
|
|
268
314
|
|
269
315
|
class AnchorTopRight(Constraint):
|
@@ -334,10 +380,12 @@ class MarginBottom(Constraint):
|
|
334
380
|
)
|
335
381
|
|
336
382
|
def apply_constraint(self, parent_widget, child_widget):
|
337
|
-
child_widget.set_position(
|
338
|
-
|
383
|
+
child_widget.set_position(
|
384
|
+
child_widget.rect.x,
|
385
|
+
parent_widget.get_padded_bottom() - child_widget.rect.h - self.margin,
|
339
386
|
)
|
340
387
|
|
388
|
+
|
341
389
|
class MarginTop(Constraint):
|
342
390
|
def __init__(self, margin: float):
|
343
391
|
super().__init__(name="margin_top")
|
@@ -347,7 +395,9 @@ class MarginTop(Constraint):
|
|
347
395
|
return child_widget.rect.top == parent_widget.get_padded_top() + self.margin
|
348
396
|
|
349
397
|
def apply_constraint(self, parent_widget, child_widget):
|
350
|
-
child_widget.set_position(
|
398
|
+
child_widget.set_position(
|
399
|
+
child_widget.rect.x, parent_widget.get_padded_top() + self.margin
|
400
|
+
)
|
351
401
|
|
352
402
|
|
353
403
|
class MarginLeft(Constraint):
|
@@ -360,7 +410,9 @@ class MarginLeft(Constraint):
|
|
360
410
|
|
361
411
|
def apply_constraint(self, parent_widget, child_widget):
|
362
412
|
if not self.evaluate(parent_widget, child_widget):
|
363
|
-
child_widget.set_position(
|
413
|
+
child_widget.set_position(
|
414
|
+
parent_widget.get_padded_left() + self.margin, child_widget.rect.y
|
415
|
+
)
|
364
416
|
|
365
417
|
|
366
418
|
class MarginRight(Constraint):
|
@@ -374,5 +426,165 @@ class MarginRight(Constraint):
|
|
374
426
|
def apply_constraint(self, parent_widget, child_widget):
|
375
427
|
child_widget.set_position(
|
376
428
|
parent_widget.get_padded_right() - child_widget.rect.w - self.margin,
|
377
|
-
child_widget.rect.y
|
429
|
+
child_widget.rect.y,
|
430
|
+
)
|
431
|
+
|
432
|
+
|
433
|
+
class PercentageMarginBottom(Constraint):
|
434
|
+
def __init__(self, margin: float):
|
435
|
+
super().__init__(name="percentage_margin_bottom")
|
436
|
+
self.margin = margin
|
437
|
+
|
438
|
+
def evaluate(self, parent_widget, child_widget):
|
439
|
+
return (
|
440
|
+
child_widget.rect.bottom
|
441
|
+
== parent_widget.get_padded_top()
|
442
|
+
+ parent_widget.get_padded_height() * self.margin
|
443
|
+
)
|
444
|
+
|
445
|
+
def apply_constraint(self, parent_widget, child_widget):
|
446
|
+
child_widget.set_position(
|
447
|
+
child_widget.rect.x,
|
448
|
+
parent_widget.get_padded_bottom()
|
449
|
+
- child_widget.rect.h
|
450
|
+
- parent_widget.get_padded_height() * self.margin,
|
451
|
+
)
|
452
|
+
|
453
|
+
|
454
|
+
class PercentageMarginTop(Constraint):
|
455
|
+
def __init__(self, margin: float):
|
456
|
+
super().__init__(name="percentage_margin_top")
|
457
|
+
self.margin = margin
|
458
|
+
|
459
|
+
def evaluate(self, parent_widget, child_widget):
|
460
|
+
return (
|
461
|
+
child_widget.rect.top
|
462
|
+
== parent_widget.get_padded_top()
|
463
|
+
+ parent_widget.get_padded_height() * self.margin
|
464
|
+
)
|
465
|
+
|
466
|
+
def apply_constraint(self, parent_widget, child_widget):
|
467
|
+
child_widget.set_position(
|
468
|
+
child_widget.rect.x,
|
469
|
+
parent_widget.get_padded_top()
|
470
|
+
+ parent_widget.get_padded_height() * self.margin,
|
471
|
+
)
|
472
|
+
|
473
|
+
|
474
|
+
class PercentageMarginLeft(Constraint):
|
475
|
+
def __init__(self, margin: float):
|
476
|
+
super().__init__(name="percentage_margin_left")
|
477
|
+
self.margin = margin
|
478
|
+
|
479
|
+
def evaluate(self, parent_widget, child_widget):
|
480
|
+
return (
|
481
|
+
child_widget.rect.left
|
482
|
+
== parent_widget.get_padded_left()
|
483
|
+
+ parent_widget.get_padded_width() * self.margin
|
484
|
+
)
|
485
|
+
|
486
|
+
def apply_constraint(self, parent_widget, child_widget):
|
487
|
+
if not self.evaluate(parent_widget, child_widget):
|
488
|
+
child_widget.set_position(
|
489
|
+
parent_widget.get_padded_left()
|
490
|
+
+ parent_widget.get_padded_width() * self.margin,
|
491
|
+
child_widget.rect.y,
|
492
|
+
)
|
493
|
+
|
494
|
+
|
495
|
+
class PercentageMarginRight(Constraint):
|
496
|
+
def __init__(self, margin: float):
|
497
|
+
super().__init__(name="percentage_margin_right")
|
498
|
+
self.margin = margin
|
499
|
+
|
500
|
+
def evaluate(self, parent_widget, child_widget):
|
501
|
+
return (
|
502
|
+
child_widget.rect.right
|
503
|
+
== parent_widget.get_padded_right()
|
504
|
+
- parent_widget.get_padded_width() * self.margin
|
505
|
+
)
|
506
|
+
|
507
|
+
def apply_constraint(self, parent_widget, child_widget):
|
508
|
+
child_widget.set_position(
|
509
|
+
parent_widget.get_padded_right()
|
510
|
+
- child_widget.rect.w
|
511
|
+
- parent_widget.get_padded_width() * self.margin,
|
512
|
+
child_widget.rect.y,
|
513
|
+
)
|
514
|
+
|
515
|
+
|
516
|
+
class PercentageRectMarginBottom(Constraint):
|
517
|
+
def __init__(self, margin: float):
|
518
|
+
super().__init__(name="percentage_rect_margin_bottom")
|
519
|
+
self.margin = margin
|
520
|
+
|
521
|
+
def evaluate(self, parent_widget, child_widget):
|
522
|
+
return (
|
523
|
+
child_widget.rect.bottom
|
524
|
+
== parent_widget.rect.top + parent_widget.rect.height * self.margin
|
525
|
+
)
|
526
|
+
|
527
|
+
def apply_constraint(self, parent_widget, child_widget):
|
528
|
+
child_widget.set_position(
|
529
|
+
child_widget.rect.x,
|
530
|
+
parent_widget.rect.bottom
|
531
|
+
- child_widget.rect.height
|
532
|
+
- parent_widget.rect.height * self.margin,
|
533
|
+
)
|
534
|
+
|
535
|
+
|
536
|
+
class PercentageRectMarginTop(Constraint):
|
537
|
+
def __init__(self, margin: float):
|
538
|
+
super().__init__(name="percentage_rect_margin_top")
|
539
|
+
self.margin = margin
|
540
|
+
|
541
|
+
def evaluate(self, parent_widget, child_widget):
|
542
|
+
return (
|
543
|
+
child_widget.rect.top
|
544
|
+
== parent_widget.rect.top + parent_widget.rect.height * self.margin
|
545
|
+
)
|
546
|
+
|
547
|
+
def apply_constraint(self, parent_widget, child_widget):
|
548
|
+
child_widget.set_position(
|
549
|
+
child_widget.rect.x,
|
550
|
+
parent_widget.rect.top + parent_widget.rect.height * self.margin,
|
551
|
+
)
|
552
|
+
|
553
|
+
|
554
|
+
class PercentageRectMarginLeft(Constraint):
|
555
|
+
def __init__(self, margin: float):
|
556
|
+
super().__init__(name="percentage_rect_margin_left")
|
557
|
+
self.margin = margin
|
558
|
+
|
559
|
+
def evaluate(self, parent_widget, child_widget):
|
560
|
+
return (
|
561
|
+
child_widget.rect.left
|
562
|
+
== parent_widget.rect.left + parent_widget.rect.width * self.margin
|
563
|
+
)
|
564
|
+
|
565
|
+
def apply_constraint(self, parent_widget, child_widget):
|
566
|
+
if not self.evaluate(parent_widget, child_widget):
|
567
|
+
child_widget.set_position(
|
568
|
+
parent_widget.rect.left + parent_widget.rect.width * self.margin,
|
569
|
+
child_widget.rect.y,
|
570
|
+
)
|
571
|
+
|
572
|
+
|
573
|
+
class PercentageRectMarginRight(Constraint):
|
574
|
+
def __init__(self, margin: float):
|
575
|
+
super().__init__(name="percentage_rect_margin_right")
|
576
|
+
self.margin = margin
|
577
|
+
|
578
|
+
def evaluate(self, parent_widget, child_widget):
|
579
|
+
return (
|
580
|
+
child_widget.rect.right
|
581
|
+
== parent_widget.rect.right - parent_widget.rect.width * self.margin
|
582
|
+
)
|
583
|
+
|
584
|
+
def apply_constraint(self, parent_widget, child_widget):
|
585
|
+
child_widget.set_position(
|
586
|
+
parent_widget.rect.right
|
587
|
+
- child_widget.rect.width
|
588
|
+
- parent_widget.rect.width * self.margin,
|
589
|
+
child_widget.rect.y,
|
378
590
|
)
|
batFramework/gui/container.py
CHANGED
@@ -20,6 +20,9 @@ class Container(Shape, InteractiveWidget):
|
|
20
20
|
self.layout.set_parent(self)
|
21
21
|
self.add(*children)
|
22
22
|
|
23
|
+
def __str__(self) -> str:
|
24
|
+
return f"Container({self.uid},{len(self.children)})"
|
25
|
+
|
23
26
|
def get_min_required_size(self):
|
24
27
|
if self.layout:
|
25
28
|
return self.layout.get_auto_size()
|
@@ -50,6 +53,23 @@ class Container(Shape, InteractiveWidget):
|
|
50
53
|
self.dirty_children = True
|
51
54
|
return self
|
52
55
|
|
56
|
+
def clamp_scroll(self) -> Self:
|
57
|
+
if not self.children:
|
58
|
+
return Self
|
59
|
+
r = self.get_padded_rect()
|
60
|
+
size = self.children[0].rect.unionall(self.children[1:]).size
|
61
|
+
|
62
|
+
# Calculate the maximum scroll values
|
63
|
+
max_scroll_x = max(0, size[0] - r.width)
|
64
|
+
max_scroll_y = max(0, size[1] - r.height)
|
65
|
+
|
66
|
+
# Clamp the scroll values
|
67
|
+
self.scroll.x = max(0, min(self.scroll.x, max_scroll_x))
|
68
|
+
self.scroll.y = max(0, min(self.scroll.y, max_scroll_y))
|
69
|
+
|
70
|
+
self.dirty_children = True
|
71
|
+
return self
|
72
|
+
|
53
73
|
def set_layout(self, layout: Layout) -> Self:
|
54
74
|
tmp = self.layout
|
55
75
|
self.layout = layout
|
@@ -57,23 +77,16 @@ class Container(Shape, InteractiveWidget):
|
|
57
77
|
self.dirty_children = True
|
58
78
|
return self
|
59
79
|
|
60
|
-
|
61
|
-
def get_debug_outlines(self):
|
62
|
-
yield (self.rect, self.debug_color)
|
63
|
-
yield (self.get_padded_rect(), self.debug_color)
|
64
|
-
|
65
|
-
for child in self.children:
|
66
|
-
yield from child.get_debug_outlines()
|
67
|
-
# for data in child.get_debug_outlines():
|
68
|
-
|
69
80
|
def get_interactive_children(self) -> list[InteractiveWidget]:
|
70
81
|
return [
|
71
|
-
child
|
82
|
+
child
|
83
|
+
for child in self.children
|
84
|
+
if isinstance(child, InteractiveWidget) and child.allow_focus_to_self()
|
72
85
|
]
|
73
86
|
|
74
87
|
def focus_next_child(self) -> None:
|
75
88
|
self.layout.focus_next_child()
|
76
|
-
|
89
|
+
|
77
90
|
def focus_prev_child(self) -> None:
|
78
91
|
self.layout.focus_prev_child()
|
79
92
|
|
@@ -94,14 +107,11 @@ class Container(Shape, InteractiveWidget):
|
|
94
107
|
def resolve_constraints(self) -> None:
|
95
108
|
super().resolve_constraints()
|
96
109
|
|
97
|
-
def __str__(self) -> str:
|
98
|
-
return f"Container({self.uid},{len(self.children)})"
|
99
|
-
|
100
110
|
def top_at(self, x: float | int, y: float | int) -> "None|Widget":
|
101
111
|
if self.visible and self.rect.collidepoint(x, y):
|
102
112
|
if self.children:
|
103
113
|
for child in reversed(self.children):
|
104
|
-
r = child.top_at(x,y)
|
114
|
+
r = child.top_at(x, y)
|
105
115
|
if r is not None:
|
106
116
|
return r
|
107
117
|
return self
|
@@ -117,16 +127,22 @@ class Container(Shape, InteractiveWidget):
|
|
117
127
|
self.focused_index = min(self.focused_index, len(l))
|
118
128
|
return l[self.focused_index].get_focus()
|
119
129
|
|
130
|
+
def do_handle_event(self, event):
|
131
|
+
self.layout.handle_event(event)
|
132
|
+
|
120
133
|
def set_focused_child(self, child: InteractiveWidget) -> bool:
|
121
134
|
l = self.get_interactive_children()
|
122
|
-
|
135
|
+
try:
|
136
|
+
i = l.index(child)
|
137
|
+
except ValueError:
|
138
|
+
return False
|
123
139
|
if i >= 0:
|
124
140
|
self.focused_index = i
|
125
141
|
return True
|
126
142
|
return False
|
127
143
|
|
128
144
|
def allow_focus_to_self(self) -> bool:
|
129
|
-
return len(self.get_interactive_children()) != 0
|
145
|
+
return len(self.get_interactive_children()) != 0 and self.visible
|
130
146
|
|
131
147
|
def draw(self, camera: bf.Camera) -> None:
|
132
148
|
constraints_down = False
|
@@ -144,7 +160,8 @@ class Container(Shape, InteractiveWidget):
|
|
144
160
|
self.parent.visit_up(self.selective_up)
|
145
161
|
else:
|
146
162
|
constraints_down = True
|
147
|
-
|
163
|
+
if not self.dirty_children:
|
164
|
+
self.dirty_children = any(c.dirty_shape for c in self.children)
|
148
165
|
if self.dirty_children:
|
149
166
|
if self.layout:
|
150
167
|
self.layout.arrange()
|
@@ -157,7 +174,6 @@ class Container(Shape, InteractiveWidget):
|
|
157
174
|
self.paint()
|
158
175
|
self.dirty_surface = False
|
159
176
|
|
160
|
-
|
161
177
|
bf.Entity.draw(self, camera)
|
162
178
|
|
163
179
|
if self.clip_children:
|
@@ -166,8 +182,10 @@ class Container(Shape, InteractiveWidget):
|
|
166
182
|
new_clip = new_clip.clip(old_clip)
|
167
183
|
camera.surface.set_clip(new_clip)
|
168
184
|
# Draw children with adjusted positions
|
169
|
-
_ = [
|
185
|
+
_ = [
|
186
|
+
child.draw(camera)
|
187
|
+
for child in sorted(self.children, key=lambda c: c.render_order)
|
188
|
+
]
|
170
189
|
|
171
190
|
if self.clip_children:
|
172
191
|
camera.surface.set_clip(old_clip)
|
173
|
-
|
batFramework/gui/debugger.py
CHANGED
@@ -7,6 +7,7 @@ import pygame
|
|
7
7
|
def convert_to_int(*args):
|
8
8
|
return [int(arg) for arg in args]
|
9
9
|
|
10
|
+
|
10
11
|
class Debugger(Label):
|
11
12
|
def __init__(self) -> None:
|
12
13
|
super().__init__("")
|
@@ -17,12 +18,6 @@ class Debugger(Label):
|
|
17
18
|
self.add_tags("debugger")
|
18
19
|
self.set_visible(False)
|
19
20
|
|
20
|
-
# def get_debug_outlines(self):
|
21
|
-
# yield None
|
22
|
-
|
23
|
-
def to_string_id(self) -> str:
|
24
|
-
return "Debugger"
|
25
|
-
|
26
21
|
def set_refresh_rate(self, value: int) -> Self:
|
27
22
|
self.refresh_rate = value
|
28
23
|
return self
|
@@ -61,14 +56,17 @@ class Debugger(Label):
|
|
61
56
|
def update_text(self) -> None:
|
62
57
|
if not self.parent_scene:
|
63
58
|
return
|
59
|
+
|
64
60
|
d = "\n".join(
|
65
61
|
key + ":" + data if key != "" else data
|
66
62
|
for key, data in self.static_data.items()
|
67
63
|
)
|
64
|
+
|
68
65
|
d2 = "\n".join(
|
69
66
|
key + ":" + str(data()) if key != "" else str(data())
|
70
67
|
for key, data in self.dynamic_data.items()
|
71
68
|
)
|
69
|
+
|
72
70
|
self.set_text("\n".join((d, d2)).strip())
|
73
71
|
|
74
72
|
def update(self, dt: float) -> None:
|
@@ -83,13 +81,17 @@ class Debugger(Label):
|
|
83
81
|
self.refresh_counter = 0
|
84
82
|
self.update_text()
|
85
83
|
|
86
|
-
|
87
|
-
def __str__(self)->str:
|
84
|
+
def __str__(self) -> str:
|
88
85
|
return "Debugger"
|
89
|
-
|
90
|
-
|
86
|
+
|
87
|
+
def top_at(self, x, y):
|
88
|
+
return None
|
89
|
+
|
91
90
|
|
92
91
|
class FPSDebugger(Debugger):
|
92
|
+
def __init__(self):
|
93
|
+
super().__init__()
|
94
|
+
|
93
95
|
def do_when_added(self):
|
94
96
|
if not self.parent_scene or not self.parent_scene.manager:
|
95
97
|
print("Debugger could not link to the manager")
|
@@ -125,4 +127,9 @@ class BasicDebugger(FPSDebugger):
|
|
125
127
|
self.add_dynamic("W. Ent.", lambda: parent_scene.get_world_entity_count())
|
126
128
|
self.add_dynamic("H. Ent.", lambda: parent_scene.get_hud_entity_count())
|
127
129
|
|
128
|
-
self.add_dynamic(
|
130
|
+
self.add_dynamic(
|
131
|
+
"Hover",
|
132
|
+
lambda: (
|
133
|
+
str(parent_scene.root.hovered) if parent_scene.root.hovered else None
|
134
|
+
),
|
135
|
+
)
|