batframework 0.1.13__py3-none-any.whl → 1.0.1__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 +41 -46
- batFramework/action.py +42 -20
- batFramework/actionContainer.py +43 -4
- batFramework/animatedSprite.py +26 -20
- batFramework/camera.py +177 -47
- batFramework/constants.py +26 -51
- batFramework/cutscene.py +15 -15
- batFramework/cutsceneBlocks.py +11 -9
- batFramework/dynamicEntity.py +7 -6
- batFramework/easing.py +28 -23
- batFramework/entity.py +87 -49
- batFramework/enums.py +14 -0
- batFramework/fontManager.py +57 -0
- batFramework/gui/__init__.py +2 -2
- batFramework/gui/button.py +82 -31
- batFramework/gui/constraints.py +137 -104
- batFramework/gui/container.py +27 -28
- batFramework/gui/debugger.py +92 -42
- batFramework/gui/frame.py +15 -15
- batFramework/gui/image.py +37 -17
- batFramework/gui/indicator.py +18 -14
- batFramework/gui/interactiveWidget.py +11 -10
- batFramework/gui/label.py +60 -56
- batFramework/gui/layout.py +50 -47
- batFramework/gui/root.py +43 -30
- batFramework/gui/shape.py +34 -41
- batFramework/gui/slider.py +5 -0
- batFramework/gui/toggle.py +31 -27
- batFramework/gui/widget.py +148 -128
- batFramework/manager.py +18 -13
- batFramework/particles.py +16 -13
- batFramework/resourceManager.py +55 -0
- batFramework/scene.py +141 -83
- batFramework/sceneManager.py +21 -16
- batFramework/sprite.py +31 -0
- batFramework/stateMachine.py +1 -0
- batFramework/tileset.py +7 -9
- batFramework/time.py +61 -50
- batFramework/transition.py +20 -12
- batFramework/utils.py +2 -65
- batframework-1.0.1.dist-info/LICENCE +21 -0
- {batframework-0.1.13.dist-info → batframework-1.0.1.dist-info}/METADATA +3 -2
- batframework-1.0.1.dist-info/RECORD +48 -0
- {batframework-0.1.13.dist-info → batframework-1.0.1.dist-info}/WHEEL +1 -1
- batFramework/debugger.py +0 -48
- batframework-0.1.13.dist-info/RECORD +0 -43
- {batframework-0.1.13.dist-info → batframework-1.0.1.dist-info}/top_level.txt +0 -0
batFramework/entity.py
CHANGED
@@ -1,51 +1,59 @@
|
|
1
|
+
from typing import Any, Self
|
1
2
|
import pygame
|
2
3
|
import batFramework as bf
|
3
|
-
from typing import Any
|
4
4
|
|
5
5
|
class Entity:
|
6
|
-
|
6
|
+
"""
|
7
|
+
Basic entity class
|
8
|
+
"""
|
9
|
+
__instance_count = 0
|
10
|
+
|
7
11
|
def __init__(
|
8
12
|
self,
|
9
|
-
size
|
10
|
-
no_surface
|
11
|
-
surface_flags
|
12
|
-
convert_alpha
|
13
|
+
size: None | tuple[int, int] = None,
|
14
|
+
no_surface: bool = False,
|
15
|
+
surface_flags: int = 0,
|
16
|
+
convert_alpha: bool = False,
|
13
17
|
) -> None:
|
14
18
|
self.convert_alpha = convert_alpha
|
15
19
|
if size is None:
|
16
|
-
size= (
|
17
|
-
|
20
|
+
size = (10, 10)
|
18
21
|
if no_surface:
|
19
22
|
self.surface = None
|
20
23
|
else:
|
21
|
-
self.surface =
|
22
|
-
|
24
|
+
self.surface = pygame.Surface(size, surface_flags)
|
25
|
+
|
23
26
|
if convert_alpha and self.surface is not None:
|
24
27
|
self.surface = self.surface.convert_alpha()
|
25
|
-
self.surface.fill((0,0,0,0))
|
28
|
+
self.surface.fill((0, 0, 0, 0))
|
26
29
|
|
27
|
-
self.
|
30
|
+
self.rect = pygame.FRect(0, 0, *size)
|
28
31
|
self.tags: list[str] = []
|
29
32
|
self.parent_scene: bf.Scene | None = None
|
30
|
-
self.
|
31
|
-
|
32
|
-
self.
|
33
|
-
self.
|
34
|
-
|
35
|
-
|
36
|
-
|
33
|
+
self.visible: bool = True
|
34
|
+
self.debug_color: tuple = bf.color.DARK_RED
|
35
|
+
self.render_order: int = 0
|
36
|
+
self.uid: Any = Entity.__instance_count
|
37
|
+
Entity.__instance_count += 1
|
38
|
+
|
39
|
+
def set_render_order(self, render_order: int) -> Self:
|
40
|
+
self.render_order = render_order
|
41
|
+
return self
|
37
42
|
|
38
43
|
def get_bounding_box(self):
|
39
|
-
yield (self.rect,self.
|
44
|
+
yield (self.rect, self.debug_color)
|
40
45
|
|
41
|
-
def set_debug_color(self, color):
|
42
|
-
self.
|
46
|
+
def set_debug_color(self, color) -> Self:
|
47
|
+
self.debug_color = color
|
48
|
+
return self
|
43
49
|
|
44
|
-
def set_visible(self, value: bool):
|
50
|
+
def set_visible(self, value: bool) -> Self:
|
45
51
|
self.visible = value
|
52
|
+
return self
|
46
53
|
|
47
|
-
def set_parent_scene(self, scene):
|
54
|
+
def set_parent_scene(self, scene) -> Self:
|
48
55
|
self.parent_scene = scene
|
56
|
+
return self
|
49
57
|
|
50
58
|
def do_when_added(self):
|
51
59
|
pass
|
@@ -53,70 +61,100 @@ class Entity:
|
|
53
61
|
def do_when_removed(self):
|
54
62
|
pass
|
55
63
|
|
56
|
-
def set_position(self, x, y):
|
64
|
+
def set_position(self, x, y) -> Self:
|
57
65
|
self.rect.topleft = (x, y)
|
58
66
|
return self
|
59
67
|
|
60
|
-
def
|
68
|
+
def get_position(self) -> tuple:
|
69
|
+
return self.rect.topleft
|
70
|
+
|
71
|
+
def get_center(self) -> tuple:
|
72
|
+
return self.rect.center
|
73
|
+
|
74
|
+
def set_x(self, x) -> Self:
|
61
75
|
self.rect.x = x
|
62
76
|
return self
|
63
77
|
|
64
|
-
def set_y(self,y):
|
78
|
+
def set_y(self, y) -> Self:
|
65
79
|
self.rect.y = y
|
66
80
|
return self
|
67
81
|
|
68
|
-
def set_center(self, x, y):
|
82
|
+
def set_center(self, x, y) -> Self:
|
69
83
|
self.rect.center = (x, y)
|
70
84
|
return self
|
71
85
|
|
72
|
-
def set_uid(self, uid):
|
86
|
+
def set_uid(self, uid) -> Self:
|
73
87
|
self.uid = uid
|
74
88
|
return self
|
75
89
|
|
76
|
-
def
|
90
|
+
def add_tags(self, *tags) -> Self:
|
77
91
|
for tag in tags:
|
78
92
|
if tag not in self.tags:
|
79
93
|
self.tags.append(tag)
|
80
94
|
self.tags.sort()
|
81
95
|
return self
|
82
96
|
|
83
|
-
def
|
97
|
+
def remove_tags(self, *tags):
|
84
98
|
self.tags = [tag for tag in self.tags if tag not in tags]
|
85
99
|
|
86
|
-
def
|
87
|
-
return tag in self.tags
|
100
|
+
def has_tags(self, *tags) -> bool:
|
101
|
+
return all(tag in self.tags for tag in tags)
|
102
|
+
|
103
|
+
def get_tags(self) -> list[str]:
|
104
|
+
return self.tags
|
88
105
|
|
89
|
-
def process_event(self, event: pygame.Event)->bool:
|
106
|
+
def process_event(self, event: pygame.Event) -> bool:
|
90
107
|
"""
|
91
108
|
Returns bool : True if the method is blocking (no propagation to next children of the scene)
|
92
109
|
"""
|
93
110
|
self.do_process_actions(event)
|
94
|
-
res = self.
|
111
|
+
res = self.do_handle_actions()
|
112
|
+
res = res or self.do_handle_event(event)
|
95
113
|
self.do_reset_actions()
|
96
114
|
return res
|
97
115
|
|
98
|
-
def do_process_actions(self,event : pygame.Event)->None:
|
99
|
-
pass
|
100
116
|
|
101
|
-
|
102
|
-
|
103
|
-
|
117
|
+
|
118
|
+
def do_process_actions(self, event: pygame.Event) -> None:
|
119
|
+
"""
|
120
|
+
Process entity actions you may have set
|
121
|
+
"""
|
122
|
+
|
123
|
+
def do_reset_actions(self) -> None:
|
124
|
+
"""
|
125
|
+
Reset entity actions you may have set
|
126
|
+
"""
|
127
|
+
|
128
|
+
def do_handle_actions(self) ->None:
|
129
|
+
"""
|
130
|
+
Handle entity actions
|
131
|
+
"""
|
132
|
+
|
104
133
|
def do_handle_event(self, event: pygame.Event) -> bool:
|
134
|
+
"""
|
135
|
+
Handle specific
|
136
|
+
"""
|
137
|
+
|
105
138
|
return False
|
106
139
|
|
107
140
|
def update(self, dt: float):
|
141
|
+
"""
|
142
|
+
Update method to be overriden by subclasses of widget
|
143
|
+
"""
|
108
144
|
self.do_update(dt)
|
109
145
|
|
110
|
-
def do_update(self,dt:float):
|
111
|
-
|
146
|
+
def do_update(self, dt: float):
|
147
|
+
"""
|
148
|
+
Update method to be overriden for specific behavior by the end user
|
149
|
+
"""
|
112
150
|
|
113
151
|
def draw(self, camera: bf.Camera) -> int:
|
114
|
-
|
115
|
-
|
116
|
-
|
152
|
+
"""
|
153
|
+
Draw the entity onto the camera with coordinate transposing
|
154
|
+
"""
|
155
|
+
should_not_draw = not self.visible or not self.surface or not camera.intersects(self.rect)
|
156
|
+
if should_not_draw:
|
117
157
|
return 0
|
118
|
-
camera.surface.blit(
|
119
|
-
|
120
|
-
tuple(round(i * self.z_depth) for i in camera.transpose(self.rect).topleft),
|
121
|
-
)
|
158
|
+
camera.surface.blit(self.surface, camera.transpose(self.rect))
|
159
|
+
|
122
160
|
return 1
|
batFramework/enums.py
ADDED
@@ -0,0 +1,57 @@
|
|
1
|
+
from .utils import Singleton
|
2
|
+
# put font stuff here later
|
3
|
+
import pygame
|
4
|
+
import os
|
5
|
+
import batFramework as bf
|
6
|
+
class FontManager(metaclass=Singleton):
|
7
|
+
def __init__(self):
|
8
|
+
pygame.font.init()
|
9
|
+
self.DEFAULT_TEXT_SIZE = 16
|
10
|
+
self.MIN_FONT_SIZE = 8
|
11
|
+
self.MAX_FONT_SIZE = 64
|
12
|
+
self.DEFAULT_ANTIALIAS = False
|
13
|
+
self.FONTS = {}
|
14
|
+
|
15
|
+
def set_default_text_size(self,size: int):
|
16
|
+
self.DEFAULT_TEXT_SIZE = size
|
17
|
+
|
18
|
+
def init_font(self,raw_path: str|None):
|
19
|
+
try:
|
20
|
+
if raw_path is not None:
|
21
|
+
self.load_font(raw_path if raw_path else None, None)
|
22
|
+
self.load_font(raw_path)
|
23
|
+
except FileNotFoundError:
|
24
|
+
self.load_sysfont(raw_path)
|
25
|
+
self.load_sysfont(raw_path, None)
|
26
|
+
|
27
|
+
def load_font(self,path: str|None, name: str|None = ""):
|
28
|
+
if path is not None:
|
29
|
+
path = bf.ResourceManager().get_path(path) # convert path if given
|
30
|
+
filename = None
|
31
|
+
if path is not None:
|
32
|
+
filename = os.path.basename(path).split(".")[0]
|
33
|
+
|
34
|
+
# get filename if path is given, else None
|
35
|
+
if name != "":
|
36
|
+
filename = name # if name is not given, name is the filename
|
37
|
+
self.FONTS[filename] = {}
|
38
|
+
# fill the dict
|
39
|
+
for size in range(self.MIN_FONT_SIZE, self.MAX_FONT_SIZE, 2):
|
40
|
+
self.FONTS[filename][size] = pygame.font.Font(path, size=size)
|
41
|
+
|
42
|
+
def load_sysfont(self,font_name: str|None, key: str |None= ""):
|
43
|
+
if key == "":
|
44
|
+
key = font_name
|
45
|
+
if font_name is None or pygame.font.match_font(font_name) is None:
|
46
|
+
raise FileNotFoundError(f"Requested font '{font_name}' was not found")
|
47
|
+
self.FONTS[font_name] = {}
|
48
|
+
|
49
|
+
for size in range(self.MIN_FONT_SIZE, self.MAX_FONT_SIZE, 2):
|
50
|
+
self.FONTS[key][size] = pygame.font.SysFont(font_name, size=size)
|
51
|
+
|
52
|
+
def get_font(self,name: str | None = None, text_size: int = 12) -> pygame.Font|None:
|
53
|
+
if not name in self.FONTS:
|
54
|
+
return None
|
55
|
+
if not text_size in self.FONTS[name]:
|
56
|
+
return None
|
57
|
+
return self.FONTS[name][text_size]
|
batFramework/gui/__init__.py
CHANGED
@@ -5,9 +5,9 @@ from .interactiveWidget import InteractiveWidget
|
|
5
5
|
from .root import Root
|
6
6
|
from .shape import Shape
|
7
7
|
from .frame import Frame
|
8
|
-
from .label import Label,Align
|
8
|
+
from .label import Label, Align
|
9
9
|
from .button import Button
|
10
|
-
from .debugger import
|
10
|
+
from .debugger import *
|
11
11
|
from .layout import *
|
12
12
|
from .container import Container
|
13
13
|
from .indicator import *
|
batFramework/gui/button.py
CHANGED
@@ -1,25 +1,50 @@
|
|
1
1
|
from .label import Label
|
2
2
|
import batFramework as bf
|
3
|
-
from
|
4
|
-
from typing import Self
|
3
|
+
from typing import Self,Callable
|
5
4
|
from .interactiveWidget import InteractiveWidget
|
6
5
|
import pygame
|
7
6
|
|
8
|
-
|
7
|
+
|
8
|
+
class Button(Label, InteractiveWidget):
|
9
9
|
_cache = {}
|
10
|
-
|
11
|
-
def __init__(self, text: str, callback
|
12
|
-
# Label.__init__(self,text)
|
13
|
-
self.callback = callback
|
10
|
+
|
11
|
+
def __init__(self, text: str, callback: None| Callable = None) -> None:
|
12
|
+
# Label.__init__(self,text)
|
13
|
+
self.callback = callback
|
14
14
|
self.click_action = bf.Action("click").add_mouse_control(1)
|
15
15
|
self.hover_action = bf.Action("hover").add_mouse_control(pygame.MOUSEMOTION)
|
16
|
-
self.is_hovered
|
17
|
-
self.is_clicking
|
16
|
+
self.is_hovered: bool = False
|
17
|
+
self.is_clicking: bool = False
|
18
|
+
self.effect_max :float= 20
|
19
|
+
self.effect_speed :float= 1.2
|
20
|
+
self.effect :float = 0
|
21
|
+
self.enabled :bool = True
|
18
22
|
super().__init__(text=text)
|
19
23
|
self.set_debug_color("cyan")
|
20
24
|
|
25
|
+
def get_surface_filter(self)->pygame.Surface|None:
|
26
|
+
if not self.surface : return None
|
27
|
+
size = self.surface.get_size()
|
28
|
+
surface_filter = Button._cache.get(size, None)
|
29
|
+
if surface_filter is None:
|
30
|
+
surface_filter = pygame.Surface(size).convert_alpha()
|
31
|
+
surface_filter.fill((30, 30, 30, 0))
|
32
|
+
Button._cache[size] = surface_filter
|
33
|
+
return surface_filter
|
34
|
+
def enable(self)->Self:
|
35
|
+
self.enabled = True
|
36
|
+
self.build()
|
37
|
+
return self
|
21
38
|
|
22
|
-
def
|
39
|
+
def disable(self)->Self:
|
40
|
+
self.enabled = False
|
41
|
+
self.build()
|
42
|
+
return self
|
43
|
+
|
44
|
+
def is_enabled(self)->bool:
|
45
|
+
return self.enabled
|
46
|
+
|
47
|
+
def set_callback(self, callback: Callable) -> Self:
|
23
48
|
self.callback = callback
|
24
49
|
return self
|
25
50
|
|
@@ -31,17 +56,19 @@ class Button(Label,InteractiveWidget):
|
|
31
56
|
super().on_lose_focus()
|
32
57
|
self.build()
|
33
58
|
|
34
|
-
def to_string_id(self)->str:
|
35
|
-
return f"Button({self._text})"
|
59
|
+
def to_string_id(self) -> str:
|
60
|
+
return f"Button({self._text}){'' if self.enabled else '[disabled]'}"
|
36
61
|
|
37
|
-
def click(self)->None:
|
38
|
-
if self.callback and not self.is_clicking:
|
62
|
+
def click(self) -> None:
|
63
|
+
if self.callback is not None and not self.is_clicking:
|
39
64
|
self.is_clicking = True
|
40
65
|
self.callback()
|
41
66
|
self.is_clicking = False
|
42
|
-
|
43
|
-
|
44
|
-
|
67
|
+
|
68
|
+
def start_effect(self):
|
69
|
+
if self.effect <= 0 : self.effect = self.effect_max
|
70
|
+
|
71
|
+
def do_process_actions(self, event):
|
45
72
|
self.click_action.process_event(event)
|
46
73
|
self.hover_action.process_event(event)
|
47
74
|
|
@@ -49,13 +76,16 @@ class Button(Label,InteractiveWidget):
|
|
49
76
|
self.click_action.reset()
|
50
77
|
self.hover_action.reset()
|
51
78
|
|
52
|
-
def do_handle_event(self,event)->
|
79
|
+
def do_handle_event(self, event) -> bool:
|
53
80
|
res = False
|
54
81
|
if self.click_action.is_active():
|
55
82
|
root = self.get_root()
|
56
|
-
if root
|
57
|
-
|
58
|
-
self.
|
83
|
+
if root is None : return res
|
84
|
+
if root.get_hovered() == self and self.enabled:
|
85
|
+
if not self.is_focused:
|
86
|
+
self.get_focus()
|
87
|
+
# self.click()
|
88
|
+
self.start_effect()
|
59
89
|
res = True
|
60
90
|
elif self.hover_action.is_active():
|
61
91
|
root = self.get_root()
|
@@ -70,18 +100,39 @@ class Button(Label,InteractiveWidget):
|
|
70
100
|
res = True
|
71
101
|
return res
|
72
102
|
|
103
|
+
def update(self,dt):
|
104
|
+
super().update(dt)
|
105
|
+
if self.effect > 0:
|
106
|
+
self.effect -= dt*60*self.effect_speed
|
107
|
+
self.build()
|
108
|
+
if self.effect <= 0:
|
109
|
+
self.is_hovered = False
|
110
|
+
self.effect = 0
|
111
|
+
self.click()
|
112
|
+
self.build()
|
73
113
|
|
74
|
-
|
75
|
-
|
114
|
+
def _build_effect(self)->None:
|
115
|
+
pygame.draw.rect(
|
116
|
+
self.surface,
|
117
|
+
bf.color.CLOUD_WHITE,
|
118
|
+
(0,0,*self.surface.get_size()),
|
119
|
+
int(self.effect),
|
120
|
+
*self._border_radius
|
121
|
+
)
|
122
|
+
|
123
|
+
def build(self) -> None:
|
76
124
|
super().build()
|
125
|
+
size = self.surface.get_size()
|
126
|
+
if not self.enabled:
|
127
|
+
self.surface.blit(self.get_surface_filter(), (0, 0), special_flags=pygame.BLEND_SUB)
|
128
|
+
return
|
129
|
+
if self.effect:
|
130
|
+
if self.effect >= 1 :
|
131
|
+
self._build_effect()
|
132
|
+
return
|
77
133
|
if self.is_hovered:
|
78
|
-
|
79
|
-
if hover_surf is None:
|
80
|
-
hover_surf = pygame.Surface(self.surface.get_size()).convert_alpha()
|
81
|
-
hover_surf.fill((30,30,30,0))
|
82
|
-
Button._cache[self.surface.get_size()] = hover_surf
|
83
|
-
self.surface.blit(hover_surf,(0,0),special_flags = pygame.BLEND_ADD)
|
134
|
+
self.surface.blit(self.get_surface_filter(), (0, 0), special_flags=pygame.BLEND_ADD)
|
84
135
|
|
136
|
+
def apply_contraints(self) -> None:
|
137
|
+
super().apply_constraints()
|
85
138
|
|
86
|
-
def apply_contraints(self)->None:
|
87
|
-
super().apply_contraints()
|