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