batframework 1.0.8a14__py3-none-any.whl → 1.0.9a1__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 CHANGED
@@ -1,6 +1,5 @@
1
1
  import pygame
2
2
  import batFramework as bf
3
- import sys
4
3
  from .constants import Constants as const
5
4
  from .utils import Singleton
6
5
  from .enums import *
@@ -11,7 +10,7 @@ from .tileset import Tileset
11
10
  from .timeManager import TimeManager,Timer,SceneTimer
12
11
  from .easingController import EasingController
13
12
  from .cutscene import Cutscene, CutsceneManager
14
- from .cutsceneBlocks import *
13
+ import batFramework.cutsceneBlocks
15
14
  from .audioManager import AudioManager
16
15
  import batFramework.transition as transition
17
16
  from .action import Action
@@ -29,7 +28,7 @@ from .animatedSprite import AnimatedSprite
29
28
  from .character import Character
30
29
  from .stateMachine import State, StateMachine
31
30
  from .scene import Scene
32
- from .gui import *
31
+ from .gui import *
33
32
  from .sceneManager import SceneManager
34
33
  from .manager import Manager
35
34
  from .templates import *
@@ -47,8 +46,6 @@ def init_screen(resolution: tuple[int, int], flags: int = 0, vsync: int = 0):
47
46
  f"Window : {resolution[0]}x{resolution[1]}"
48
47
  )
49
48
 
50
-
51
-
52
49
  def print_version():
53
50
  package_name = "batFramework"
54
51
  try:
@@ -57,19 +54,18 @@ def print_version():
57
54
  except importlib.metadata.PackageNotFoundError:
58
55
  print(f"{package_name} is not installed")
59
56
 
60
-
61
57
  def init(
62
58
  resolution: tuple[int, int],
63
59
  flags: int = 0,
64
- vsync: int = 0,
65
- default_text_size=None,
66
- default_font=None,
60
+ window_caption: str = "BatFramework Project",
67
61
  resource_path: str | None = None,
68
- window_title: str = "BatFramework Project",
62
+ default_font_size=None,
63
+ default_font=None,
69
64
  fps_limit: int = 0,
65
+ vsync: int = 0,
70
66
  ):
71
67
  print_version()
72
- pygame.display.set_caption(window_title)
68
+ pygame.display.set_caption(window_caption)
73
69
  init_screen(resolution, flags, vsync)
74
70
 
75
71
  ResourceManager().set_resource_path(
@@ -77,8 +73,8 @@ def init(
77
73
  )
78
74
  if resource_path is not None:
79
75
  ResourceManager().load_dir(ResourceManager().RESOURCE_PATH)
80
- if default_text_size is not None:
81
- FontManager().set_default_text_size(default_text_size)
76
+ if default_font_size is not None:
77
+ FontManager().set_default_text_size(default_font_size)
82
78
  FontManager().init_font(default_font)
83
79
  const.BF_INITIALIZED = True
84
80
  const.set_fps_limit(fps_limit)
batFramework/camera.py CHANGED
@@ -213,7 +213,7 @@ class Camera:
213
213
 
214
214
  return surface
215
215
 
216
- def resize(self, size: tuple[int, int] | None = None) -> Self:
216
+ def set_size(self, size: tuple[int, int] | None = None) -> Self:
217
217
  if size is None:
218
218
  size = bf.const.RESOLUTION
219
219
  self.target_size = size
batFramework/constants.py CHANGED
@@ -16,6 +16,12 @@ class Constants:
16
16
  DEFAULT_CLICK_CURSOR = pygame.cursors.Cursor(pygame.SYSTEM_CURSOR_ARROW)
17
17
 
18
18
  BF_INITIALIZED: bool = False
19
+ ALLOW_DEBUG : bool = True
20
+
21
+ @staticmethod
22
+ def set_allow_debug(allow_debug:bool):
23
+ Constants.ALLOW_DEBUG = allow_debug
24
+
19
25
 
20
26
  @staticmethod
21
27
  def set_resolution(resolution: tuple[int, int]):
batFramework/cutscene.py CHANGED
@@ -37,14 +37,13 @@ class CutsceneManager(metaclass=bf.Singleton):
37
37
  self.current_cutscene.on_enter()
38
38
  self.current_cutscene.init_blocks()
39
39
  self.current_cutscene.play()
40
- self.manager.set_sharedVar("in_cutscene", True)
41
40
 
42
41
  def enable_player_control(self) -> None:
43
- self.manager.set_sharedVar("player_has_control", True)
42
+ pass
44
43
 
45
44
  def disable_player_control(self) -> None:
46
- self.manager.set_sharedVar("player_has_control", False)
47
-
45
+ pass
46
+
48
47
  def update(self, dt):
49
48
  if not self.current_cutscene is None:
50
49
  self.current_cutscene.update(dt)
@@ -56,7 +55,6 @@ class CutsceneManager(metaclass=bf.Singleton):
56
55
  self.play(self.cutscenes.pop(0))
57
56
  else:
58
57
  self.current_cutscene = None
59
- self.manager.set_sharedVar("in_cutscene", False)
60
58
 
61
59
 
62
60
  class Cutscene:
batFramework/drawable.py CHANGED
@@ -66,7 +66,7 @@ class Drawable(Entity):
66
66
  """
67
67
  Draw the entity onto the camera surface
68
68
  """
69
- if not self.visible or not camera.rect.colliderect(self.rect):
69
+ if not self.visible or not camera.rect.colliderect(self.rect) or self.surface.get_alpha() == 0:
70
70
  return
71
71
  camera.surface.blit(
72
72
  self.surface,
@@ -6,11 +6,9 @@ from typing import Self
6
6
  class DynamicEntity(bf.Entity):
7
7
  def __init__(
8
8
  self,
9
- size: None | tuple[int, int] = None,
10
- surface_flags: int = 0,
11
- convert_alpha: bool = False,*args,**kwargs
9
+ *args,**kwargs
12
10
  ) -> None:
13
- super().__init__(size, surface_flags, convert_alpha,*args,**kwargs)
11
+ super().__init__(*args,**kwargs)
14
12
  self.velocity = pygame.math.Vector2(0, 0)
15
13
  self.ignore_collisions : bool = False
16
14
 
batFramework/entity.py CHANGED
@@ -8,27 +8,27 @@ if TYPE_CHECKING:
8
8
 
9
9
 
10
10
  class Entity:
11
- __count = 0
12
- __available_uid = set()
13
- __used_uid = set()
11
+ _count: int = 0
12
+ _available_uids: set[int] = set()
13
+
14
+
15
+ def __init__(self,*args,**kwargs) -> None:
16
+ if Entity._available_uids:
17
+ self.uid = Entity._available_uids.pop()
18
+ else:
19
+ self.uid = Entity._count
20
+ Entity._count += 1
14
21
 
15
- def __init__(self) -> None:
16
22
  self.rect = pygame.FRect(0, 0, 0, 0)
17
23
  self.tags: list[str] = []
18
24
  self.parent_scene: bf.Scene | None = None
19
25
  self.debug_color: tuple | str = "red"
20
- self.uid: int = Entity.__count
21
- Entity.__used_uid.add(self.uid)
22
-
23
- if Entity.__available_uid:
24
- self.name = Entity.__available_uid.pop()
25
- else:
26
- self.name = Entity.__count
27
- Entity.__count += 1
28
26
 
29
27
  def __del__(self):
30
- Entity.__available_uid.add(self.uid)
31
-
28
+ try:
29
+ Entity._available_uids.add(self.uid)
30
+ except AttributeError:
31
+ pass
32
32
  def set_position(self, x, y) -> Self:
33
33
  self.rect.topleft = x, y
34
34
  return self
@@ -60,16 +60,6 @@ class Entity:
60
60
  def do_when_removed(self):
61
61
  pass
62
62
 
63
- def set_uid(self, uid: int) -> Self:
64
- if uid in Entity.__used_uid:
65
- print(f"set_uid error : UID '{uid}' is already in use")
66
- return self
67
- self.uid = uid
68
- if uid in Entity.__used_uid:
69
- Entity.__used_uid.remove(uid)
70
- Entity.__used_uid.add(uid)
71
- return self
72
-
73
63
  def add_tags(self, *tags) -> Self:
74
64
  for tag in tags:
75
65
  if tag not in self.tags:
@@ -86,10 +76,7 @@ class Entity:
86
76
  def get_tags(self) -> list[str]:
87
77
  return self.tags
88
78
 
89
- def process_event(self, event: pygame.Event) -> bool:
90
- """
91
- Returns bool : True if the method is blocking (no propagation to next Entity of the scene)
92
- """
79
+ def process_event(self, event: pygame.Event) -> None:
93
80
  if event.consumed:
94
81
  return
95
82
  self.do_process_actions(event)
batFramework/enums.py CHANGED
@@ -111,3 +111,4 @@ class textMode(Enum):
111
111
  ALPHABETICAL = 0
112
112
  NUMERICAL = 1
113
113
  ALPHANUMERICAL = 3
114
+
@@ -9,17 +9,17 @@ import batFramework as bf
9
9
  class FontManager(metaclass=Singleton):
10
10
  def __init__(self):
11
11
  pygame.font.init()
12
- self.DEFAULT_TEXT_SIZE = 16
12
+ self.DEFAULT_FONT_SIZE = 16
13
13
  self.MIN_FONT_SIZE = 8
14
14
  self.MAX_FONT_SIZE = 64
15
15
  self.DEFAULT_ANTIALIAS = False
16
16
  self.FONTS = {}
17
17
 
18
- def set_antialias(self, value: bool):
18
+ def set_default_antialias(self, value: bool):
19
19
  self.DEFAULT_ANTIALIAS = value
20
20
 
21
21
  def set_default_text_size(self, size: int):
22
- self.DEFAULT_TEXT_SIZE = size
22
+ self.DEFAULT_FONT_SIZE = size
23
23
 
24
24
  def init_font(self, raw_path: str | None):
25
25
  try:
@@ -1,4 +1,3 @@
1
- from .constraints import *
2
1
  from .widget import Widget
3
2
  from .styleManager import StyleManager
4
3
  from .style import Style
@@ -10,7 +9,7 @@ from .root import Root
10
9
  from .shape import Shape
11
10
  from .meter import Meter
12
11
  from .label import Label
13
- from .dialogueBox import DialogueBox
12
+ from .animatedLabel import AnimatedLabel
14
13
  from .textInput import TextInput
15
14
  from .button import Button
16
15
  from .debugger import *
@@ -20,3 +19,4 @@ from .indicator import *
20
19
  from .toggle import Toggle
21
20
  from .radioButton import RadioButton, RadioVariable
22
21
  from .slider import Slider
22
+ from .constraints import *
@@ -3,19 +3,20 @@ import batFramework as bf
3
3
  from typing import Self
4
4
 
5
5
 
6
- class DialogueBox(Label):
7
- def __init__(self) -> None:
6
+ class AnimatedLabel(Label):
7
+ def __init__(self,text="") -> None:
8
8
  self.cursor_position: float = 0.0
9
9
  self.text_speed: float = 20.0
10
- self.message_queue: list[str] = []
11
10
  self.is_over: bool = True
12
11
  self.is_paused: bool = False
12
+ self.original_text = ""
13
13
  self.set_autoresize(False)
14
14
  self.set_alignment(bf.alignment.LEFT)
15
15
  super().__init__("")
16
+ self.set_text(text)
16
17
 
17
18
  def __str__(self) -> str:
18
- return "DialogueBox"
19
+ return "AnimatedLabel"
19
20
 
20
21
  def pause(self) -> Self:
21
22
  self.is_paused = True
@@ -53,47 +54,28 @@ class DialogueBox(Label):
53
54
  left = index
54
55
  return [text]
55
56
 
56
- def paint(self) -> None:
57
- if self.font_object and self.message_queue:
58
- message = self.message_queue.pop(0)
59
- message = "\n".join(self.cut_text_to_width(message))
60
- self.message_queue.insert(0, message)
61
- super().paint()
62
57
 
63
- def say(self, message: str) -> Self:
64
- self.message_queue.append(message)
65
- self.is_over = False
58
+ def _set_text_internal(self,text:str)->Self:
59
+ super().set_text(text)
66
60
  return self
67
61
 
68
- def is_queue_empty(self) -> bool:
69
- return not self.message_queue
70
-
71
- def is_current_message_over(self) -> bool:
72
- return self.is_over
73
-
74
- def clear_queue(self) -> Self:
75
- self.message_queue.clear()
76
- self.next_message()
77
- return self
78
-
79
- def next_message(self) -> Self:
80
- if self.message_queue:
81
- self.message_queue.pop(0)
62
+ def set_text(self,text:str)->Self:
63
+ self.original_text = text
64
+ self.is_over = False
82
65
  self.cursor_position = 0
83
- self.set_text("")
84
- return self
85
66
 
86
- def skip_current_message(self) -> Self:
87
- self.cursor_position = len(self.message_queue[0])
88
- self.dirty_shape = True
67
+ def set_size(self, size):
68
+ super().set_size(size)
69
+ self._set_text_internal('\n'.join(self.cut_text_to_width(self.original_text[: int(self.cursor_position)])))
89
70
 
90
71
  def do_update(self, dt):
91
- if not self.message_queue or self.is_paused:
72
+ if self.is_over:
92
73
  return
93
- if not self.is_over and self.cursor_position == len(self.message_queue[0]):
74
+ if not self.is_over and self.cursor_position == len(self.original_text):
94
75
  self.is_over = True
95
76
  return
96
77
  self.cursor_position = min(
97
- self.cursor_position + self.text_speed * dt, len(self.message_queue[0])
78
+ self.cursor_position + self.text_speed * dt, len(self.original_text)
98
79
  )
99
- self.set_text(self.message_queue[0][: int(self.cursor_position)])
80
+ # self.set_text(self.original_text[: int(self.cursor_position)])
81
+ self._set_text_internal('\n'.join(self.cut_text_to_width(self.original_text[: int(self.cursor_position)])))
@@ -13,3 +13,33 @@ class Button(Label, ClickableWidget):
13
13
 
14
14
  def __str__(self) -> str:
15
15
  return f"Button({self.text})"
16
+
17
+ def get_min_required_size(self) -> tuple[float, float]:
18
+ if not (self.autoresize_w or self.autoresize_h):
19
+ return self.rect.size
20
+ if not self.text_rect:
21
+ self.text_rect.size = self._get_text_rect_required_size()
22
+ res = self.inflate_rect_by_padding((0, 0, *self.text_rect.size)).size
23
+ res = res[0],res[1]+self.unpressed_relief
24
+ return res[0] if self.autoresize_w else self.rect.w, (
25
+ res[1] if self.autoresize_h else self.rect.h
26
+ )
27
+
28
+
29
+ def _build_layout(self) -> None:
30
+
31
+ self.text_rect.size = self._get_text_rect_required_size()
32
+ if self.autoresize_h or self.autoresize_w:
33
+ target_rect = self.inflate_rect_by_padding((0, 0, *self.text_rect.size))
34
+ target_rect.h += self.unpressed_relief
35
+ if not self.autoresize_w:
36
+ target_rect.w = self.rect.w
37
+ if not self.autoresize_h:
38
+ target_rect.h = self.rect.h
39
+ if self.rect.size != target_rect.size:
40
+ self.set_size(target_rect.size)
41
+ self.apply_updates()
42
+ return
43
+ offset = self._get_outline_offset() if self.show_text_outline else (0,0)
44
+ padded = self.get_padded_rect().move(-self.rect.x + offset[0], -self.rect.y + offset[1])
45
+ self.align_text(self.text_rect, padded, self.alignment)
@@ -27,6 +27,11 @@ class ClickableWidget(Shape, InteractiveWidget):
27
27
  self.set_debug_color("cyan")
28
28
  self.set_relief(self.unpressed_relief)
29
29
 
30
+ def get_min_required_size(self) -> tuple[float, float]:
31
+ return self.rect.size.inflate(0,self.unpressed_relief)
32
+
33
+
34
+
30
35
  def set_unpressed_relief(self, relief: int) -> Self:
31
36
  if relief == self.unpressed_relief:
32
37
  return self
@@ -217,4 +222,4 @@ class ClickableWidget(Shape, InteractiveWidget):
217
222
  self._paint_disabled()
218
223
  elif self.is_hovered:
219
224
  self._paint_hovered()
220
-
225
+
@@ -598,6 +598,95 @@ class MarginRight(Constraint):
598
598
  other.margin == self.margin
599
599
  )
600
600
 
601
+ class RectMarginBottom(Constraint):
602
+ def __init__(self, margin: float):
603
+ super().__init__()
604
+ self.margin = margin
605
+
606
+ def evaluate(self, parent_widget, child_widget):
607
+ return (
608
+ child_widget.rect.bottom == parent_widget.rect.bottom - self.margin
609
+ )
610
+
611
+ def apply_constraint(self, parent_widget, child_widget):
612
+ child_widget.set_position(
613
+ child_widget.rect.x,
614
+ parent_widget.rect.bottom- child_widget.rect.h - self.margin,
615
+ )
616
+
617
+ def __eq__(self,other:"Constraint")->bool:
618
+ if not isinstance(other,self.__class__):
619
+ return False
620
+ return (
621
+ other.name == self.name and
622
+ other.margin == self.margin
623
+ )
624
+
625
+ class RectMarginTop(Constraint):
626
+ def __init__(self, margin: float):
627
+ super().__init__()
628
+ self.margin = margin
629
+
630
+ def evaluate(self, parent_widget, child_widget):
631
+ return child_widget.rect.top == parent_widget.rect.top + self.margin
632
+
633
+ def apply_constraint(self, parent_widget, child_widget):
634
+ child_widget.set_position(
635
+ child_widget.rect.x, parent_widget.rect.top + self.margin
636
+ )
637
+
638
+ def __eq__(self,other:"Constraint")->bool:
639
+ if not isinstance(other,self.__class__):
640
+ return False
641
+ return (
642
+ other.name == self.name and
643
+ other.margin == self.margin
644
+ )
645
+
646
+ class RectMarginLeft(Constraint):
647
+ def __init__(self, margin: float):
648
+ super().__init__()
649
+ self.margin = margin
650
+
651
+ def evaluate(self, parent_widget, child_widget):
652
+ return child_widget.rect.left == parent_widget.rect.left + self.margin
653
+
654
+ def apply_constraint(self, parent_widget, child_widget):
655
+ if not self.evaluate(parent_widget, child_widget):
656
+ child_widget.set_position(
657
+ parent_widget.rect.left + self.margin, child_widget.rect.y
658
+ )
659
+
660
+ def __eq__(self,other:"Constraint")->bool:
661
+ if not isinstance(other,self.__class__):
662
+ return False
663
+ return (
664
+ other.name == self.name and
665
+ other.margin == self.margin
666
+ )
667
+
668
+ class RectMarginRight(Constraint):
669
+ def __init__(self, margin: float):
670
+ super().__init__()
671
+ self.margin = margin
672
+
673
+ def evaluate(self, parent_widget, child_widget):
674
+ return child_widget.rect.right == parent_widget.rect.right - self.margin
675
+
676
+ def apply_constraint(self, parent_widget, child_widget):
677
+ child_widget.set_position(
678
+ parent_widget.rect.right - child_widget.rect.w - self.margin,
679
+ child_widget.rect.y,
680
+ )
681
+
682
+ def __eq__(self,other:"Constraint")->bool:
683
+ if not isinstance(other,self.__class__):
684
+ return False
685
+ return (
686
+ other.name == self.name and
687
+ other.margin == self.margin
688
+ )
689
+
601
690
  class PercentageMarginBottom(Constraint):
602
691
  def __init__(self, margin: float):
603
692
  super().__init__()
@@ -812,4 +901,4 @@ class PercentageRectMarginRight(Constraint):
812
901
  return (
813
902
  other.name == self.name and
814
903
  other.margin == self.margin
815
- )
904
+ )