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.
Files changed (65) hide show
  1. batFramework/__init__.py +53 -50
  2. batFramework/action.py +126 -99
  3. batFramework/actionContainer.py +53 -9
  4. batFramework/animatedSprite.py +115 -65
  5. batFramework/audioManager.py +69 -26
  6. batFramework/camera.py +259 -69
  7. batFramework/constants.py +16 -54
  8. batFramework/cutscene.py +36 -29
  9. batFramework/cutsceneBlocks.py +37 -42
  10. batFramework/dynamicEntity.py +9 -7
  11. batFramework/easingController.py +58 -0
  12. batFramework/entity.py +48 -97
  13. batFramework/enums.py +113 -0
  14. batFramework/fontManager.py +65 -0
  15. batFramework/gui/__init__.py +10 -2
  16. batFramework/gui/button.py +9 -78
  17. batFramework/gui/clickableWidget.py +219 -0
  18. batFramework/gui/constraints/__init__.py +1 -0
  19. batFramework/gui/constraints/constraints.py +590 -0
  20. batFramework/gui/container.py +174 -32
  21. batFramework/gui/debugger.py +131 -43
  22. batFramework/gui/dialogueBox.py +99 -0
  23. batFramework/gui/draggableWidget.py +40 -0
  24. batFramework/gui/image.py +54 -18
  25. batFramework/gui/indicator.py +38 -21
  26. batFramework/gui/interactiveWidget.py +177 -13
  27. batFramework/gui/label.py +288 -74
  28. batFramework/gui/layout.py +219 -60
  29. batFramework/gui/meter.py +71 -0
  30. batFramework/gui/radioButton.py +84 -0
  31. batFramework/gui/root.py +128 -38
  32. batFramework/gui/shape.py +253 -57
  33. batFramework/gui/slider.py +246 -0
  34. batFramework/gui/style.py +10 -0
  35. batFramework/gui/styleManager.py +48 -0
  36. batFramework/gui/textInput.py +137 -0
  37. batFramework/gui/toggle.py +115 -51
  38. batFramework/gui/widget.py +329 -254
  39. batFramework/manager.py +40 -19
  40. batFramework/object.py +114 -0
  41. batFramework/particle.py +101 -0
  42. batFramework/renderGroup.py +67 -0
  43. batFramework/resourceManager.py +84 -0
  44. batFramework/scene.py +242 -114
  45. batFramework/sceneManager.py +145 -107
  46. batFramework/scrollingSprite.py +115 -0
  47. batFramework/sprite.py +51 -0
  48. batFramework/stateMachine.py +2 -2
  49. batFramework/tileset.py +46 -0
  50. batFramework/time.py +117 -57
  51. batFramework/transition.py +184 -126
  52. batFramework/utils.py +31 -156
  53. batframework-1.0.8a3.dist-info/LICENCE +21 -0
  54. batframework-1.0.8a3.dist-info/METADATA +55 -0
  55. batframework-1.0.8a3.dist-info/RECORD +58 -0
  56. batFramework/debugger.py +0 -48
  57. batFramework/easing.py +0 -71
  58. batFramework/gui/constraints.py +0 -204
  59. batFramework/gui/frame.py +0 -19
  60. batFramework/particles.py +0 -77
  61. batFramework/transitionManager.py +0 -0
  62. batframework-1.0.8a2.dist-info/METADATA +0 -58
  63. batframework-1.0.8a2.dist-info/RECORD +0 -42
  64. {batframework-1.0.8a2.dist-info → batframework-1.0.8a3.dist-info}/WHEEL +0 -0
  65. {batframework-1.0.8a2.dist-info → batframework-1.0.8a3.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,137 @@
1
+ import batFramework as bf
2
+ from typing import Self, Callable
3
+ from .label import Label
4
+ from .interactiveWidget import InteractiveWidget
5
+ import pygame
6
+
7
+
8
+ class TextInput(Label, InteractiveWidget):
9
+ def __init__(self) -> None:
10
+ self.cursor_position = 0
11
+ self.old_key_repeat: tuple = (0, 0)
12
+ self.cursor_timer = bf.Timer(0.3, self._cursor_toggle, loop=True).start()
13
+ self.cursor_timer.pause()
14
+ self.show_cursor: bool = False
15
+ self.on_modify: Callable[[str], str] = None
16
+ self.set_focusable(True)
17
+ self.set_outline_color("black")
18
+ super().__init__("")
19
+
20
+ def set_modify_callback(self, callback: Callable[[str], str]) -> Self:
21
+ self.on_modify = callback
22
+ return self
23
+
24
+ def __str__(self) -> str:
25
+ return f"TextInput({self.text})"
26
+
27
+ def _cursor_toggle(self, value: bool = None):
28
+ if value is None:
29
+ value = not self.show_cursor
30
+ self.show_cursor = value
31
+ self.dirty_surface = True
32
+
33
+ def do_on_click_down(self, button):
34
+ if button != 1:
35
+ return
36
+ self.get_focus()
37
+
38
+ def do_on_enter(self):
39
+ pygame.mouse.set_cursor(pygame.SYSTEM_CURSOR_IBEAM)
40
+
41
+ def do_on_exit(self):
42
+ pygame.mouse.set_cursor(bf.const.DEFAULT_CURSOR)
43
+
44
+ def do_on_get_focus(self):
45
+ self.old_key_repeat = pygame.key.get_repeat()
46
+ self.cursor_timer.resume()
47
+ self._cursor_toggle(True)
48
+ self.set_cursor_position(len(self.get_text()))
49
+ pygame.key.set_repeat(200, 50)
50
+
51
+ def do_on_lose_focus(self):
52
+ self.cursor_timer.pause()
53
+ self._cursor_toggle(False)
54
+ pygame.key.set_repeat(*self.old_key_repeat)
55
+
56
+ def set_cursor_position(self, position: int) -> Self:
57
+ if position < 0:
58
+ position = 0
59
+ elif position > len(self.get_text()):
60
+ position = len(self.get_text())
61
+ self.cursor_position = position
62
+ self.show_cursor = True
63
+ self.dirty_surface = True
64
+ if self.text_rect.w > self.get_padded_width():
65
+ self.dirty_shape = True
66
+ return self
67
+
68
+ def do_handle_event(self, event):
69
+ if not self.is_focused:
70
+ return
71
+ text = self.get_text()
72
+ cursor_position = self.cursor_position
73
+
74
+ if event.type == pygame.TEXTINPUT:
75
+ self.set_text(text[:cursor_position] + event.text + text[cursor_position:])
76
+ self.set_cursor_position(cursor_position + 1)
77
+ elif event.type == pygame.KEYDOWN:
78
+ if event.key == pygame.K_ESCAPE:
79
+ self.lose_focus()
80
+
81
+ elif event.key == pygame.K_BACKSPACE:
82
+ if cursor_position > 0:
83
+ self.set_text(text[: cursor_position - 1] + text[cursor_position:])
84
+ self.set_cursor_position(cursor_position - 1)
85
+
86
+ elif event.key == pygame.K_RIGHT:
87
+ self.set_cursor_position(cursor_position + 1)
88
+
89
+ elif event.key == pygame.K_LEFT:
90
+ self.set_cursor_position(cursor_position - 1)
91
+
92
+ else:
93
+ return
94
+ else:
95
+ return
96
+
97
+ event.consumed = True
98
+
99
+ def set_text(self, text: str) -> Self:
100
+ if self.on_modify:
101
+ text = self.on_modify(text)
102
+ return super().set_text(text)
103
+
104
+ def _paint_cursor(self) -> None:
105
+ if not self.font_object or not self.show_cursor:
106
+ return
107
+ partial_text_size = self.font_object.size(
108
+ self.get_text()[: self.cursor_position]
109
+ )
110
+
111
+ cursor_rect = pygame.Rect(0, 0, 1, self.font_object.point_size)
112
+ if self.cursor_position != 0: # align left properly
113
+ cursor_rect.midleft = self.text_rect.move(partial_text_size[0], 0).midleft
114
+ else:
115
+ cursor_rect.midright = self.text_rect.midleft
116
+
117
+ pygame.draw.rect(self.surface, self.text_color, cursor_rect)
118
+
119
+ def paint(self) -> None:
120
+ super().paint()
121
+ self._paint_cursor()
122
+
123
+ def align_text(
124
+ self, text_rect: pygame.FRect, area: pygame.FRect, alignment: bf.alignment
125
+ ):
126
+ if alignment == bf.alignment.LEFT:
127
+ alignment = bf.alignment.MIDLEFT
128
+ elif alignment == bf.alignment.MIDRIGHT:
129
+ alignment = bf.alignment.MIDRIGHT
130
+
131
+ pos = area.__getattribute__(alignment.value)
132
+ text_rect.__setattr__(alignment.value, pos)
133
+ w = self.font_object.size(self.get_text()[: self.cursor_position])[0]
134
+ if self.text_rect.x + w > area.right:
135
+ self.text_rect.right = area.right
136
+ elif self.text_rect.x + w < area.left:
137
+ self.text_rect.left = area.left - w
@@ -1,62 +1,126 @@
1
1
  from .button import Button
2
- from .indicator import Indicator,ToggleIndicator
3
- import pygame
2
+ from .indicator import Indicator, ToggleIndicator
4
3
  import batFramework as bf
5
4
  from typing import Self
5
+ import pygame
6
+
6
7
 
7
8
  class Toggle(Button):
8
- def __init__(self,text:str,default_value : bool = False)->None:
9
- self.value :bool= default_value
10
- self.on_toggle = None
11
- self.indicator : Indicator=ToggleIndicator(default_value)
12
- self.gap :float|int = 0
13
- super().__init__(text,self.toggle)
14
- self.add_child(self.indicator)
15
- self.set_gap(int(max(4,self.get_content_width()/3)))
16
- # self.set_gap()
17
- # self.set_gap(20)
18
-
19
- def set_gap(self,value:int|float)->Self:
20
- if value < 0 : return self
9
+ def __init__(self, text: str, callback=None, default_value: bool = False) -> None:
10
+ self.value: bool = default_value
11
+ self.indicator: ToggleIndicator = ToggleIndicator(default_value)
12
+ self.gap: float | int = 0
13
+ self.spacing: bf.spacing = bf.spacing.MANUAL
14
+ super().__init__(text, callback)
15
+ self.add(self.indicator)
16
+ # self.set_gap(int(max(4, self.get_padded_width() / 3)))
17
+
18
+ def set_visible(self, value: bool) -> Self:
19
+ self.indicator.set_visible(value)
20
+ return super().set_visible(value)
21
+
22
+ def set_value(self, value: bool, do_callback=False) -> Self:
23
+ self.value = value
24
+ self.indicator.set_value(value)
25
+ self.dirty_surface = True
26
+ if do_callback and self.callback:
27
+ self.callback(self.value)
28
+ return self
29
+
30
+ def set_spacing(self, spacing: bf.spacing) -> Self:
31
+ if spacing == self.spacing:
32
+ return self
33
+ self.spacing = spacing
34
+ self.dirty_shape = True
35
+ return self
36
+
37
+ def click(self) -> None:
38
+ self.set_value(not self.value, True)
39
+
40
+ def set_gap(self, value: int | float) -> Self:
41
+ value = max(0, value)
42
+ if value == self.gap:
43
+ return self
21
44
  self.gap = value
22
- self.build()
23
- if self.parent : self.parent.children_modified()
45
+ self.dirty_shape = True
24
46
  return self
25
- def to_string_id(self)->str:
47
+
48
+ def __str__(self) -> str:
26
49
  return f"Toggle({self.value})"
27
-
28
- def toggle(self)->None:
29
- self.value = not self.value
30
- self.build()
31
- if self.on_toggle : self.on_toggle(self.value)
32
-
33
- def set_toggle_callback(self,callback)->Self:
34
- self.on_toggle = callback
35
- return self
36
50
 
37
- def _build_layout(self)->None:
38
- self.indicator.set_value(self.value)
39
-
51
+ def toggle(self) -> None:
52
+ self.set_value(not self.value, do_callback=True)
53
+
54
+ def get_min_required_size(self) -> tuple[float, float]:
55
+ if not self.text_rect:
56
+ params = {
57
+ "font_name": self.font_object.name,
58
+ "text": self.text,
59
+ "antialias": False,
60
+ "color": "white",
61
+ "bgcolor": "black", # if (self.has_alpha_color() or self.draw_mode == bf.drawMode.TEXTURED) else self.color,
62
+ "wraplength": (
63
+ int(self.get_padded_width()) if self.auto_wraplength else 0
64
+ ),
65
+ }
66
+ self.text_rect.size = self._render_font(params).get_size()
67
+ w, h = self.text_rect.size
40
68
  size = (
41
- 0,
42
- 0,
43
- self._text_rect.w + self.indicator.rect.w + self.gap,
44
- max(self._text_rect.h, self.indicator.rect.h)
69
+ max(
70
+ self.indicator.rect.w,
71
+ w + self.font_object.point_size + (self.gap if self.text else 0),
72
+ ),
73
+ self.text_rect.h,
74
+ )
75
+ return self.inflate_rect_by_padding((0, 0, *size)).size
76
+
77
+ def _build_layout(self) -> None:
78
+
79
+ gap = self.gap if self.text else 0
80
+
81
+ params = {
82
+ "font_name": self.font_object.name,
83
+ "text": self.text,
84
+ "antialias": False,
85
+ "color": "white",
86
+ "bgcolor": "black", # if (self.has_alpha_color() or self.draw_mode == bf.drawMode.TEXTURED) else self.color,
87
+ "wraplength": int(self.get_padded_width()) if self.auto_wraplength else 0,
88
+ }
89
+ self.text_rect.size = self._render_font(params).get_size()
90
+
91
+ indicator_height = self.font_object.point_size
92
+
93
+ self.indicator.set_size((indicator_height, indicator_height))
94
+
95
+ tmp_rect = pygame.FRect(
96
+ 0, 0, self.text_rect.w + gap + indicator_height, self.text_rect.h
97
+ )
98
+
99
+ if self.autoresize_h or self.autoresize_w:
100
+ target_rect = self.inflate_rect_by_padding(tmp_rect)
101
+ if not self.autoresize_w:
102
+ target_rect.w = self.rect.w
103
+ if not self.autoresize_h:
104
+ target_rect.h = self.rect.h
105
+ if self.rect.size != target_rect.size:
106
+ self.set_size(target_rect.size)
107
+ self.build()
108
+ return
109
+
110
+ padded = self.get_padded_rect().move(-self.rect.x, -self.rect.y)
111
+
112
+ self.align_text(tmp_rect, padded, self.alignment)
113
+ self.text_rect.midleft = tmp_rect.midleft
114
+ if self.text:
115
+ match self.spacing:
116
+ case bf.spacing.MAX:
117
+ gap = padded.w - self.text_rect.w - self.indicator.rect.w
118
+ case bf.spacing.MIN:
119
+ gap = 0
120
+
121
+ self.indicator.set_position(
122
+ *self.text_rect.move(
123
+ self.rect.x + gap,
124
+ self.rect.y + (self.text_rect.h / 2) - self.indicator.rect.h / 2,
125
+ ).topright
45
126
  )
46
-
47
- required_rect = self.inflate_rect_by_padding(size)
48
-
49
- if self.autoresize and (self.rect.size != required_rect.size) :
50
- self.set_size(*required_rect.size)
51
- return
52
-
53
- required_rect = self.get_content_rect()
54
- required_rect_rel = self.get_content_rect_rel()
55
-
56
- self._text_rect.midleft = required_rect_rel.midleft
57
- r = self.indicator.rect.copy()
58
- r.midleft = required_rect.move(self._text_rect.w+self.gap,0).midleft
59
- self.indicator.set_position(*r.topleft)
60
-
61
- self.surface.blit(self._text_surface,self._text_rect)
62
-