batframework 1.0.9a10__py3-none-any.whl → 1.0.10__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 (76) hide show
  1. batFramework/__init__.py +53 -76
  2. batFramework/action.py +99 -126
  3. batFramework/actionContainer.py +9 -53
  4. batFramework/animatedSprite.py +114 -56
  5. batFramework/audioManager.py +36 -82
  6. batFramework/camera.py +69 -263
  7. batFramework/constants.py +53 -29
  8. batFramework/cutscene.py +109 -243
  9. batFramework/cutsceneBlocks.py +176 -0
  10. batFramework/debugger.py +48 -0
  11. batFramework/dynamicEntity.py +9 -16
  12. batFramework/easing.py +71 -0
  13. batFramework/entity.py +85 -92
  14. batFramework/gui/__init__.py +3 -14
  15. batFramework/gui/button.py +78 -12
  16. batFramework/gui/constraints.py +204 -0
  17. batFramework/gui/container.py +31 -183
  18. batFramework/gui/debugger.py +43 -126
  19. batFramework/gui/frame.py +19 -0
  20. batFramework/gui/image.py +20 -55
  21. batFramework/gui/indicator.py +22 -95
  22. batFramework/gui/interactiveWidget.py +12 -229
  23. batFramework/gui/label.py +77 -311
  24. batFramework/gui/layout.py +66 -411
  25. batFramework/gui/root.py +35 -203
  26. batFramework/gui/shape.py +57 -247
  27. batFramework/gui/toggle.py +48 -114
  28. batFramework/gui/widget.py +243 -457
  29. batFramework/manager.py +29 -113
  30. batFramework/particles.py +77 -0
  31. batFramework/scene.py +217 -22
  32. batFramework/sceneManager.py +129 -161
  33. batFramework/stateMachine.py +8 -11
  34. batFramework/time.py +75 -0
  35. batFramework/transition.py +124 -129
  36. batFramework/transitionManager.py +0 -0
  37. batFramework/triggerZone.py +4 -4
  38. batFramework/utils.py +144 -266
  39. {batframework-1.0.9a10.dist-info → batframework-1.0.10.dist-info}/METADATA +24 -17
  40. batframework-1.0.10.dist-info/RECORD +43 -0
  41. batFramework/animation.py +0 -77
  42. batFramework/baseScene.py +0 -240
  43. batFramework/cutsceneManager.py +0 -34
  44. batFramework/drawable.py +0 -77
  45. batFramework/easingController.py +0 -58
  46. batFramework/enums.py +0 -135
  47. batFramework/fontManager.py +0 -65
  48. batFramework/gui/animatedLabel.py +0 -89
  49. batFramework/gui/clickableWidget.py +0 -245
  50. batFramework/gui/constraints/__init__.py +0 -1
  51. batFramework/gui/constraints/constraints.py +0 -980
  52. batFramework/gui/draggableWidget.py +0 -44
  53. batFramework/gui/meter.py +0 -96
  54. batFramework/gui/radioButton.py +0 -35
  55. batFramework/gui/selector.py +0 -250
  56. batFramework/gui/slider.py +0 -397
  57. batFramework/gui/style.py +0 -10
  58. batFramework/gui/styleManager.py +0 -54
  59. batFramework/gui/syncedVar.py +0 -49
  60. batFramework/gui/textInput.py +0 -306
  61. batFramework/gui/tooltip.py +0 -30
  62. batFramework/particle.py +0 -118
  63. batFramework/propertyEaser.py +0 -79
  64. batFramework/renderGroup.py +0 -34
  65. batFramework/resourceManager.py +0 -130
  66. batFramework/sceneLayer.py +0 -138
  67. batFramework/scrollingSprite.py +0 -115
  68. batFramework/sprite.py +0 -51
  69. batFramework/templates/__init__.py +0 -1
  70. batFramework/templates/controller.py +0 -97
  71. batFramework/tileset.py +0 -46
  72. batFramework/timeManager.py +0 -213
  73. batframework-1.0.9a10.dist-info/RECORD +0 -67
  74. {batframework-1.0.9a10.dist-info → batframework-1.0.10.dist-info}/LICENSE +0 -0
  75. {batframework-1.0.9a10.dist-info → batframework-1.0.10.dist-info}/WHEEL +0 -0
  76. {batframework-1.0.9a10.dist-info → batframework-1.0.10.dist-info}/top_level.txt +0 -0
batFramework/entity.py CHANGED
@@ -1,68 +1,51 @@
1
- from typing import Any, Self
2
1
  import pygame
3
2
  import batFramework as bf
4
- from typing import TYPE_CHECKING
5
-
6
- if TYPE_CHECKING:
7
- from .camera import Camera
8
-
3
+ from typing import Any
9
4
 
10
5
  class Entity:
11
- _count: int = 0
12
- _available_uids: set[int] = set()
13
-
14
- def __init__(self,*args,**kwargs) -> None:
15
- if Entity._available_uids:
16
- self.uid = Entity._available_uids.pop()
6
+ instance_num = 0
7
+ def __init__(
8
+ self,
9
+ size : None|tuple[int,int]=None,
10
+ no_surface : bool =False,
11
+ surface_flags : int =0,
12
+ convert_alpha : bool=False
13
+ ) -> None:
14
+ self.convert_alpha = convert_alpha
15
+ if size is None:
16
+ size= (100,100)
17
+
18
+ if no_surface:
19
+ self.surface = None
17
20
  else:
18
- self.uid = Entity._count
19
- Entity._count += 1
21
+ self.surface = (pygame.Surface(size, surface_flags))
20
22
 
21
- self.rect = pygame.FRect(0, 0, 10, 10)
23
+ if convert_alpha and self.surface is not None:
24
+ self.surface = self.surface.convert_alpha()
25
+ self.surface.fill((0,0,0,0))
26
+
27
+ self.uid: Any = Entity.instance_num
22
28
  self.tags: list[str] = []
23
29
  self.parent_scene: bf.Scene | None = None
24
- self.parent_layer: bf.SceneLayer | None = None
25
- self.debug_color: tuple | str = "red"
26
-
27
- def __del__(self):
28
- try:
29
- Entity._available_uids.add(self.uid)
30
- except AttributeError:
31
- pass
32
- def set_position(self, x, y) -> Self:
33
- self.rect.topleft = x, y
34
- return self
30
+ self.rect = pygame.FRect(0, 0, *size)
31
+
32
+ self.visible = True
33
+ self._debug_color : tuple = bf.color.DARK_RED
34
+ self.render_order = 0
35
+ self.z_depth = 1
36
+ Entity.instance_num += 1
35
37
 
36
- def set_center(self, x, y) -> Self:
37
- self.rect.center = x, y
38
- return self
38
+ def get_bounding_box(self):
39
+ yield (self.rect,self._debug_color)
39
40
 
40
- def get_debug_outlines(self):
41
- yield (self.rect, self.debug_color)
42
-
43
- def set_debug_color(self, color) -> Self:
44
- self.debug_color = color
45
- return self
46
-
47
- def kill(self):
48
- """
49
- Removes the entity from a scene layer
50
- """
51
- if self.parent_layer:
52
- self.parent_layer.remove(self)
41
+ def set_debug_color(self, color):
42
+ self._debug_color = color
53
43
 
54
- def set_parent_layer(self, layer):
55
- self.parent_layer = layer
44
+ def set_visible(self, value: bool):
45
+ self.visible = value
56
46
 
57
- def set_parent_scene(self, scene) -> Self:
58
- if scene == self.parent_scene:
59
- return self
60
- if self.parent_scene is not None:
61
- self.do_when_removed()
47
+ def set_parent_scene(self, scene):
62
48
  self.parent_scene = scene
63
- if scene is not None:
64
- self.do_when_added()
65
- return self
66
49
 
67
50
  def do_when_added(self):
68
51
  pass
@@ -70,61 +53,71 @@ class Entity:
70
53
  def do_when_removed(self):
71
54
  pass
72
55
 
73
- def add_tags(self, *tags) -> Self:
56
+ def set_position(self, x, y):
57
+ self.rect.topleft = (x, y)
58
+ return self
59
+
60
+ def set_x(self,x):
61
+ self.rect.x = x
62
+ return self
63
+
64
+ def set_y(self,y):
65
+ self.rect.y = y
66
+ return self
67
+
68
+ def set_center(self, x, y):
69
+ self.rect.center = (x, y)
70
+ return self
71
+
72
+ def set_uid(self, uid):
73
+ self.uid = uid
74
+ return self
75
+
76
+ def add_tag(self, *tags):
74
77
  for tag in tags:
75
78
  if tag not in self.tags:
76
79
  self.tags.append(tag)
77
80
  self.tags.sort()
78
81
  return self
79
82
 
80
- def remove_tags(self, *tags):
83
+ def remove_tag(self, *tags):
81
84
  self.tags = [tag for tag in self.tags if tag not in tags]
85
+ self.tags.sort()
82
86
 
83
- def has_tags(self, *tags) -> bool:
84
- """
85
- return True if entity contains all given tags
86
- """
87
- return all(tag in self.tags for tag in tags)
87
+ def has_tag(self, tag) -> bool:
88
+ return tag in self.tags
88
89
 
89
- def has_any_tags(self, *tags) -> bool:
90
+ def process_event(self, event: pygame.Event)->bool:
90
91
  """
91
- return True if entity contains any of given tags
92
+ Returns bool : True if the method is blocking (no propagation to next children of the scene)
92
93
  """
93
- return any(tag in self.tags for tag in tags)
94
-
95
- def get_tags(self) -> list[str]:
96
- return self.tags
97
-
98
- def process_event(self, event: pygame.Event) -> None:
99
- if event.consumed:
100
- return
101
94
  self.do_process_actions(event)
102
- self.do_handle_event(event)
103
-
104
- def do_process_actions(self, event: pygame.Event) -> None:
105
- """
106
- Process entity actions you may have set
107
- """
95
+ res = self.do_handle_event(event)
96
+ self.do_reset_actions()
97
+ return res
108
98
 
109
- def do_reset_actions(self) -> None:
110
- """
111
- Reset entity actions you may have set
112
- """
99
+ def do_process_actions(self,event : pygame.Event)->None:
100
+ pass
113
101
 
114
- def do_handle_event(self, event: pygame.Event):
115
- """
116
- Handle specific events with no action support
117
- """
102
+ def do_reset_actions(self)->None:
103
+ pass
104
+
105
+ def do_handle_event(self, event: pygame.Event) -> bool:
118
106
  return False
119
107
 
120
- def update(self, dt: float) -> None:
121
- """
122
- Update method to be overriden by subclasses of Entity (must call do_update and do_reset_actions)
123
- """
108
+ def update(self, dt: float):
124
109
  self.do_update(dt)
125
- self.do_reset_actions()
126
110
 
127
- def do_update(self, dt: float) -> None:
128
- """
129
- Update method to be overriden for specific behavior by the end user
130
- """
111
+ def do_update(self,dt:float):
112
+ pass
113
+
114
+ def draw(self, camera: bf.Camera) -> int:
115
+ if not self.visible:
116
+ return False
117
+ if not self.surface or not camera.intersects(self.rect):
118
+ return False
119
+ camera.surface.blit(
120
+ self.surface,
121
+ tuple(round(i * self.z_depth) for i in camera.transpose(self.rect).topleft),
122
+ )
123
+ return True
@@ -1,25 +1,14 @@
1
+ from .constraints import *
1
2
  from .widget import Widget
2
- from .styleManager import StyleManager
3
- from .style import Style
4
3
  from .image import Image
5
4
  from .interactiveWidget import InteractiveWidget
6
- from .draggableWidget import DraggableWidget
7
- from .clickableWidget import ClickableWidget
8
5
  from .root import Root
9
6
  from .shape import Shape
10
- from .meter import BarMeter
7
+ from .frame import Frame
11
8
  from .label import Label
12
- from .tooltip import ToolTip
13
- from .animatedLabel import AnimatedLabel
14
- from .textInput import TextInput
15
9
  from .button import Button
16
- from .debugger import *
10
+ from .debugger import Debugger
17
11
  from .layout import *
18
12
  from .container import Container
19
13
  from .indicator import *
20
14
  from .toggle import Toggle
21
- from .syncedVar import SyncedVar
22
- from .radioButton import RadioButton
23
- from .slider import Slider
24
- from .selector import Selector
25
- import batFramework.gui.constraints as constraints
@@ -1,18 +1,84 @@
1
1
  from .label import Label
2
2
  import batFramework as bf
3
- from typing import Self, Callable,Any
4
- from .clickableWidget import ClickableWidget
3
+ from types import FunctionType
4
+ from typing import Self
5
+ from .interactiveWidget import InteractiveWidget
6
+ import pygame
5
7
 
6
-
7
- class Button(Label, ClickableWidget):
8
- def __init__(self, text: str = "", callback: Callable[[],Any] = None) -> None:
8
+ class Button(Label,InteractiveWidget):
9
+ _cache = {}
10
+
11
+ def __init__(self, text: str, callback : FunctionType =None) -> None:
12
+ # Label.__init__(self,text)
13
+ self.callback = callback
14
+ self.click_action = bf.Action("click").add_mouse_control(1)
15
+ self.hover_action = bf.Action("hover").add_mouse_control(pygame.MOUSEMOTION)
16
+ self.is_hovered : bool = False
17
+ self.is_clicking : bool = False
9
18
  super().__init__(text=text)
10
- self.set_callback(callback)
19
+ self.set_debug_color("cyan")
20
+
21
+
22
+ def set_callback(self,callback : FunctionType = None)->Self:
23
+ self.callback = callback
24
+ return self
25
+
26
+ def on_get_focus(self):
27
+ super().on_get_focus()
28
+ self.build()
29
+
30
+ def on_lose_focus(self):
31
+ super().on_lose_focus()
32
+ self.build()
33
+
34
+ def to_string_id(self)->str:
35
+ return f"Button({self._text})"
36
+
37
+ def click(self)->None:
38
+ if self.callback and not self.is_clicking:
39
+ self.is_clicking = True
40
+ self.callback()
41
+ self.is_clicking = False
42
+
43
+
44
+ def do_process_actions(self,event):
45
+ self.click_action.process_event(event)
46
+ self.hover_action.process_event(event)
47
+
48
+ def do_reset_actions(self):
49
+ self.click_action.reset()
50
+ self.hover_action.reset()
51
+
52
+ def do_handle_event(self,event)->None:
53
+ res = False
54
+ if self.click_action.is_active():
55
+ root = self.get_root()
56
+ if root.hovered == self:
57
+ if not self.is_focused : self.get_focus()
58
+ self.click()
59
+ elif self.hover_action.is_active():
60
+ root = self.get_root()
61
+ if root:
62
+ if self.is_hovered and root.hovered != self:
63
+ self.is_hovered = False
64
+ self.build()
65
+ if not self.is_hovered and root.hovered == self:
66
+ self.is_hovered = True
67
+ self.build()
68
+ return res
69
+
70
+
71
+
72
+ def build(self)->None:
73
+ super().build()
74
+ if self.is_hovered:
75
+ hover_surf = Button._cache.get(self.surface.get_size(),None)
76
+ if hover_surf is None:
77
+ hover_surf = pygame.Surface(self.surface.get_size()).convert_alpha()
78
+ hover_surf.fill((30,30,30,0))
79
+ Button._cache[self.surface.get_size()] = hover_surf
80
+ self.surface.blit(hover_surf,(0,0),special_flags = pygame.BLEND_ADD)
11
81
 
12
- def __str__(self) -> str:
13
- return f"Button('{self.text}')"
14
82
 
15
- def get_min_required_size(self):
16
- res = super().get_min_required_size()
17
- res = res[0],res[1]+self.unpressed_relief
18
- return res
83
+ def apply_contraints(self)->None:
84
+ super().apply_contraints()
@@ -0,0 +1,204 @@
1
+ from .widget import Widget
2
+ import batFramework as bf
3
+
4
+
5
+ class Constraint:
6
+ def __init__(self,name="Constraint", priority=0):
7
+ self.priority = priority
8
+ self.name = name
9
+ def set_priority(self, priority)->"Constraint":
10
+ self.priority = priority
11
+ return self
12
+ def to_string(self)->str:
13
+ return f"{self.name.upper()}"
14
+
15
+ def evaluate(self, parent_widget:Widget, child_widget:Widget) -> bool:
16
+ raise NotImplementedError("Subclasses must implement evaluate method")
17
+
18
+ def apply(self, parent_widget:Widget, child_widget:Widget=None) -> bool:
19
+ if not self.evaluate(parent_widget, child_widget):
20
+ self.apply_constraint(parent_widget, child_widget)
21
+ return False
22
+ return True
23
+
24
+ def apply_constraint(self, parent_widget:Widget, child_widget:Widget):
25
+ raise NotImplementedError("Subclasses must implement apply_constraint method")
26
+
27
+
28
+
29
+
30
+
31
+
32
+
33
+
34
+
35
+
36
+
37
+
38
+
39
+
40
+
41
+
42
+ class ConstraintMinWidth(Constraint):
43
+ def __init__(self, width):
44
+ super().__init__(name="min_width")
45
+ self.min_width = width
46
+
47
+ def evaluate(self, parent_widget, child_widget):
48
+ return child_widget.rect.width >= self.min_width
49
+
50
+ def apply_constraint(self, parent_widget, child_widget):
51
+ if not self.evaluate(parent_widget, child_widget):
52
+ child_widget.set_size(self.min_width,child_widget.rect.h)
53
+
54
+
55
+
56
+
57
+ class ConstraintCenterX(Constraint):
58
+ def __init__(self):
59
+ super().__init__(name="centerx")
60
+
61
+ def evaluate(self, parent_widget, child_widget):
62
+ return child_widget.rect.centerx == parent_widget.get_content_center()[0]
63
+
64
+ def apply_constraint(self,parent_widget,child_widget):
65
+ if not self.evaluate(parent_widget,child_widget):
66
+ child_widget.set_center(parent_widget.get_content_center()[0],child_widget.rect.centery)
67
+
68
+ class ConstraintCenterY(Constraint):
69
+ def __init__(self):
70
+ super().__init__(name="centery")
71
+
72
+ def evaluate(self, parent_widget, child_widget):
73
+ return child_widget.rect.centery == parent_widget.get_content_center()[1]
74
+
75
+ def apply_constraint(self,parent_widget,child_widget):
76
+ if not self.evaluate(parent_widget,child_widget):
77
+ child_widget.set_center(child_widget.rect.centerx,parent_widget.get_content_center()[1])
78
+
79
+ class ConstraintCenter(Constraint):
80
+ def __init__(self):
81
+ super().__init__(name="center")
82
+
83
+ def evaluate(self, parent_widget, child_widget):
84
+ return child_widget.rect.center == parent_widget.get_content_center()
85
+
86
+ def apply_constraint(self,parent_widget,child_widget):
87
+ if not self.evaluate(parent_widget,child_widget):
88
+ child_widget.set_center(*parent_widget.get_content_center())
89
+
90
+ class ConstraintPercentageWidth(Constraint):
91
+ def __init__(self,percentage:float,keep_autoresize:bool=True):
92
+ super().__init__(name="percentage_width")
93
+ self.percentage:float = percentage
94
+ self.keep_autoresize: bool = keep_autoresize
95
+ def to_string(self)->str:
96
+ return f"{super().to_string()}.[{self.percentage},{self.keep_autoresize}]"
97
+ def evaluate(self, parent_widget, child_widget):
98
+ return child_widget.rect.width == round(parent_widget.get_content_width() * self.percentage)
99
+
100
+ def apply_constraint(self,parent_widget,child_widget):
101
+ if not self.evaluate(parent_widget,child_widget):
102
+ if child_widget.autoresize:
103
+ if self.keep_autoresize:
104
+ print(f"Warning: Constraint on {child_widget.to_string()} can't resize, autoresize set to True")
105
+ return
106
+ child_widget.set_autoresize(False)
107
+ child_widget.set_size(round(parent_widget.get_content_width() * self.percentage) ,child_widget.rect.h)
108
+
109
+
110
+ class ConstraintPercentageHeight(Constraint):
111
+ def __init__(self,percentage:float,keep_autoresize:bool=True):
112
+ super().__init__(name="percentage_height")
113
+ self.percentage:float = percentage
114
+ self.keep_autoresize: bool = keep_autoresize
115
+
116
+ def evaluate(self, parent_widget, child_widget):
117
+ return child_widget.rect.height == round(parent_widget.get_content_height() * self.percentage)
118
+
119
+ def apply_constraint(self,parent_widget,child_widget):
120
+ if not self.evaluate(parent_widget,child_widget):
121
+ if child_widget.autoresize:
122
+ if self.keep_autoresize:
123
+ print(f"Warning: Constraint on {child_widget.to_string()} can't resize, autoresize set to True")
124
+ return
125
+ child_widget.set_autoresize(False)
126
+ child_widget.set_size(child_widget.rect.w,round(parent_widget.get_content_height() * self.percentage))
127
+
128
+ class ConstraintHeight(Constraint):
129
+ def __init__(self,height:float):
130
+ if height < 0 :
131
+ raise ValueError("height can't be negative")
132
+ super().__init__(name="height")
133
+ self.height = height
134
+
135
+ def to_string(self)->str:
136
+ return f"{super().to_string()}.({self.height})"
137
+
138
+ def evaluate(self, parent_widget, child_widget):
139
+ return child_widget.rect.height == self.height
140
+
141
+ def apply_constraint(self,parent_widget,child_widget):
142
+ if not self.evaluate(parent_widget,child_widget):
143
+ child_widget.set_size(child_widget.rect.w,self.height)
144
+
145
+ class ConstraintWidth(Constraint):
146
+ def __init__(self,width:float):
147
+ if width < 0 :
148
+ raise ValueError("width can't be negative")
149
+ super().__init__(name="width")
150
+ self.width = width
151
+
152
+ def to_string(self)->str:
153
+ return f"{super().to_string()}.({self.width})"
154
+
155
+ def evaluate(self, parent_widget, child_widget):
156
+ return child_widget.rect.width == self.width
157
+
158
+ def apply_constraint(self,parent_widget,child_widget):
159
+ if not self.evaluate(parent_widget,child_widget):
160
+ child_widget.set_size(self.width,child_widget.rect.h)
161
+
162
+
163
+ class ConstraintAspectRatio(Constraint):
164
+ def __init__(self,ratio:int|float=1):
165
+ super().__init__(name="aspect_ratio")
166
+ if isinstance(ratio, float|int):
167
+ self.ratio = ratio
168
+ elif isinstance(ratio,Widget):
169
+ self.ratio = ratio.rect.w / ratio.rect.h
170
+ else:
171
+ raise TypeError(f"Ratio must be float or Widget")
172
+ def evaluate(self, parent_widget,child_widget):
173
+ return self.ratio == child_widget.rect.w / child_widget.rect.h
174
+
175
+ def apply_constraint(self,parent_widget,child_widget):
176
+ if not self.evaluate(parent_widget,child_widget):
177
+ return # TODO
178
+
179
+ class ConstraintAnchorBottom(Constraint):
180
+ def __init__(self):
181
+ super().__init__(name="anchor_bottom")
182
+
183
+ def evaluate(self, parent_widget,child_widget):
184
+ return child_widget.rect.bottom == parent_widget.rect.bottom
185
+
186
+ def apply_constraint(self,parent_widget,child_widget):
187
+ if not self.evaluate(parent_widget,child_widget):
188
+ child_widget.set_y(parent_widget.get_content_bottom() - child_widget.rect.h)
189
+
190
+
191
+ class ConstraintAnchorTopRight(Constraint):
192
+ def __init__(self):
193
+ super().__init__(name="anchor_topright")
194
+
195
+ def evaluate(self, parent_widget,child_widget):
196
+ return child_widget.rect.topright == parent_widget.rect.topright
197
+
198
+ def apply_constraint(self,parent_widget,child_widget):
199
+ if not self.evaluate(parent_widget,child_widget):
200
+ child_widget.set_position(parent_widget.get_content_right()-child_widget.rect.w, parent_widget.get_content_top())
201
+
202
+
203
+
204
+