batframework 1.0.8a13__tar.gz → 1.0.9a1__tar.gz

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 (73) hide show
  1. {batframework-1.0.8a13/src/batframework.egg-info → batframework-1.0.9a1}/PKG-INFO +1 -1
  2. {batframework-1.0.8a13 → batframework-1.0.9a1}/pyproject.toml +1 -1
  3. {batframework-1.0.8a13 → batframework-1.0.9a1}/src/batFramework/__init__.py +11 -15
  4. {batframework-1.0.8a13 → batframework-1.0.9a1}/src/batFramework/animatedSprite.py +1 -1
  5. {batframework-1.0.8a13 → batframework-1.0.9a1}/src/batFramework/camera.py +1 -1
  6. {batframework-1.0.8a13 → batframework-1.0.9a1}/src/batFramework/character.py +1 -1
  7. {batframework-1.0.8a13 → batframework-1.0.9a1}/src/batFramework/constants.py +10 -0
  8. {batframework-1.0.8a13 → batframework-1.0.9a1}/src/batFramework/cutscene.py +10 -10
  9. batframework-1.0.8a13/src/batFramework/entity.py → batframework-1.0.9a1/src/batFramework/drawable.py +4 -3
  10. {batframework-1.0.8a13 → batframework-1.0.9a1}/src/batFramework/dynamicEntity.py +2 -4
  11. batframework-1.0.8a13/src/batFramework/object.py → batframework-1.0.9a1/src/batFramework/entity.py +17 -29
  12. {batframework-1.0.8a13 → batframework-1.0.9a1}/src/batFramework/enums.py +1 -0
  13. {batframework-1.0.8a13 → batframework-1.0.9a1}/src/batFramework/fontManager.py +3 -3
  14. {batframework-1.0.8a13 → batframework-1.0.9a1}/src/batFramework/gui/__init__.py +2 -2
  15. batframework-1.0.8a13/src/batFramework/gui/dialogueBox.py → batframework-1.0.9a1/src/batFramework/gui/animatedLabel.py +18 -36
  16. batframework-1.0.9a1/src/batFramework/gui/button.py +45 -0
  17. {batframework-1.0.8a13 → batframework-1.0.9a1}/src/batFramework/gui/clickableWidget.py +6 -1
  18. {batframework-1.0.8a13 → batframework-1.0.9a1}/src/batFramework/gui/constraints/constraints.py +90 -1
  19. batframework-1.0.9a1/src/batFramework/gui/container.py +182 -0
  20. {batframework-1.0.8a13 → batframework-1.0.9a1}/src/batFramework/gui/debugger.py +1 -1
  21. {batframework-1.0.8a13 → batframework-1.0.9a1}/src/batFramework/gui/indicator.py +3 -2
  22. {batframework-1.0.8a13 → batframework-1.0.9a1}/src/batFramework/gui/interactiveWidget.py +43 -24
  23. {batframework-1.0.8a13 → batframework-1.0.9a1}/src/batFramework/gui/label.py +43 -49
  24. batframework-1.0.9a1/src/batFramework/gui/layout.py +585 -0
  25. {batframework-1.0.8a13 → batframework-1.0.9a1}/src/batFramework/gui/root.py +2 -9
  26. {batframework-1.0.8a13 → batframework-1.0.9a1}/src/batFramework/gui/shape.py +2 -0
  27. {batframework-1.0.8a13 → batframework-1.0.9a1}/src/batFramework/gui/textInput.py +115 -78
  28. {batframework-1.0.8a13 → batframework-1.0.9a1}/src/batFramework/gui/toggle.py +1 -4
  29. {batframework-1.0.8a13 → batframework-1.0.9a1}/src/batFramework/gui/widget.py +50 -38
  30. batframework-1.0.9a1/src/batFramework/manager.py +133 -0
  31. {batframework-1.0.8a13 → batframework-1.0.9a1}/src/batFramework/particle.py +1 -1
  32. {batframework-1.0.8a13 → batframework-1.0.9a1}/src/batFramework/scene.py +1 -34
  33. {batframework-1.0.8a13 → batframework-1.0.9a1}/src/batFramework/sceneManager.py +6 -34
  34. {batframework-1.0.8a13 → batframework-1.0.9a1}/src/batFramework/scrollingSprite.py +1 -1
  35. {batframework-1.0.8a13 → batframework-1.0.9a1}/src/batFramework/sprite.py +2 -2
  36. batframework-1.0.8a13/src/batFramework/time.py → batframework-1.0.9a1/src/batFramework/timeManager.py +0 -2
  37. batframework-1.0.9a1/src/batFramework/utils.py +248 -0
  38. {batframework-1.0.8a13 → batframework-1.0.9a1/src/batframework.egg-info}/PKG-INFO +1 -1
  39. {batframework-1.0.8a13 → batframework-1.0.9a1}/src/batframework.egg-info/SOURCES.txt +3 -3
  40. batframework-1.0.8a13/src/batFramework/gui/button.py +0 -15
  41. batframework-1.0.8a13/src/batFramework/gui/container.py +0 -191
  42. batframework-1.0.8a13/src/batFramework/gui/layout.py +0 -249
  43. batframework-1.0.8a13/src/batFramework/manager.py +0 -121
  44. batframework-1.0.8a13/src/batFramework/utils.py +0 -149
  45. {batframework-1.0.8a13 → batframework-1.0.9a1}/LICENCE +0 -0
  46. {batframework-1.0.8a13 → batframework-1.0.9a1}/README.md +0 -0
  47. {batframework-1.0.8a13 → batframework-1.0.9a1}/setup.cfg +0 -0
  48. {batframework-1.0.8a13 → batframework-1.0.9a1}/src/batFramework/action.py +0 -0
  49. {batframework-1.0.8a13 → batframework-1.0.9a1}/src/batFramework/actionContainer.py +0 -0
  50. {batframework-1.0.8a13 → batframework-1.0.9a1}/src/batFramework/animation.py +0 -0
  51. {batframework-1.0.8a13 → batframework-1.0.9a1}/src/batFramework/audioManager.py +0 -0
  52. {batframework-1.0.8a13 → batframework-1.0.9a1}/src/batFramework/cutsceneBlocks.py +0 -0
  53. {batframework-1.0.8a13 → batframework-1.0.9a1}/src/batFramework/easingController.py +0 -0
  54. {batframework-1.0.8a13 → batframework-1.0.9a1}/src/batFramework/gui/constraints/__init__.py +0 -0
  55. {batframework-1.0.8a13 → batframework-1.0.9a1}/src/batFramework/gui/draggableWidget.py +0 -0
  56. {batframework-1.0.8a13 → batframework-1.0.9a1}/src/batFramework/gui/image.py +0 -0
  57. {batframework-1.0.8a13 → batframework-1.0.9a1}/src/batFramework/gui/meter.py +0 -0
  58. {batframework-1.0.8a13 → batframework-1.0.9a1}/src/batFramework/gui/radioButton.py +0 -0
  59. {batframework-1.0.8a13 → batframework-1.0.9a1}/src/batFramework/gui/slider.py +0 -0
  60. {batframework-1.0.8a13 → batframework-1.0.9a1}/src/batFramework/gui/style.py +0 -0
  61. {batframework-1.0.8a13 → batframework-1.0.9a1}/src/batFramework/gui/styleManager.py +0 -0
  62. {batframework-1.0.8a13 → batframework-1.0.9a1}/src/batFramework/renderGroup.py +0 -0
  63. {batframework-1.0.8a13 → batframework-1.0.9a1}/src/batFramework/resourceManager.py +0 -0
  64. {batframework-1.0.8a13 → batframework-1.0.9a1}/src/batFramework/stateMachine.py +0 -0
  65. {batframework-1.0.8a13 → batframework-1.0.9a1}/src/batFramework/templates/__init__.py +0 -0
  66. {batframework-1.0.8a13 → batframework-1.0.9a1}/src/batFramework/templates/character.py +0 -0
  67. {batframework-1.0.8a13 → batframework-1.0.9a1}/src/batFramework/templates/states.py +0 -0
  68. {batframework-1.0.8a13 → batframework-1.0.9a1}/src/batFramework/tileset.py +0 -0
  69. {batframework-1.0.8a13 → batframework-1.0.9a1}/src/batFramework/transition.py +0 -0
  70. {batframework-1.0.8a13 → batframework-1.0.9a1}/src/batFramework/triggerZone.py +0 -0
  71. {batframework-1.0.8a13 → batframework-1.0.9a1}/src/batframework.egg-info/dependency_links.txt +0 -0
  72. {batframework-1.0.8a13 → batframework-1.0.9a1}/src/batframework.egg-info/requires.txt +0 -0
  73. {batframework-1.0.8a13 → batframework-1.0.9a1}/src/batframework.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: batframework
3
- Version: 1.0.8a13
3
+ Version: 1.0.9a1
4
4
  Summary: Pygame framework for making games easier.
5
5
  Author-email: Turan Baturay <baturayturan@gmail.com>
6
6
  Project-URL: Homepage, https://github.com/TuranBaturay/batFramework
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "batframework"
7
- version = "1.0.8a13"
7
+ version = "1.0.9a1"
8
8
  description = "Pygame framework for making games easier."
9
9
  readme = "README.md"
10
10
  classifiers = [ "Programming Language :: Python :: 3", "License :: OSI Approved :: MIT License", "Operating System :: OS Independent",]
@@ -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 *
@@ -8,17 +7,17 @@ from .resourceManager import ResourceManager
8
7
  from .fontManager import FontManager
9
8
  from .utils import Utils as utils
10
9
  from .tileset import Tileset
11
- from .time import *
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
18
17
  from .actionContainer import *
19
18
  from .camera import Camera
20
- from .object import Object
21
19
  from .entity import Entity
20
+ from .drawable import Drawable
22
21
  from .renderGroup import RenderGroup
23
22
  from .dynamicEntity import DynamicEntity
24
23
  from .sprite import Sprite
@@ -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)
@@ -3,7 +3,7 @@ import pygame
3
3
  from typing import List, Dict, Tuple, Union, Optional, Self
4
4
  from .animation import Animation
5
5
 
6
- class AnimatedSprite(bf.Entity):
6
+ class AnimatedSprite(bf.Drawable):
7
7
  def __init__(self, size: Optional[Tuple[int, int]] = None,*args,**kwargs) -> None:
8
8
  super().__init__(size, no_surface=True,*args,**kwargs)
9
9
  self.float_counter: float = 0
@@ -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
@@ -3,7 +3,7 @@ from .stateMachine import State
3
3
  from .animatedSprite import AnimatedSprite
4
4
  from .dynamicEntity import DynamicEntity
5
5
 
6
- class Character(AnimatedSprite,DynamicEntity):
6
+ class Character(DynamicEntity,AnimatedSprite):
7
7
  def __init__(self,*args,**kwargs) -> None:
8
8
  super().__init__(*args,**kwargs)
9
9
  self.state_machine = bf.StateMachine(self)
@@ -4,6 +4,8 @@ import pygame
4
4
  class Constants:
5
5
  SCREEN: pygame.Surface = None
6
6
  RESOLUTION: tuple[int, int] = (1280, 720)
7
+ WIDTH = 1280
8
+ HEIGHT = 720
7
9
  VSYNC = 0
8
10
  FLAGS: int = pygame.SCALED | pygame.RESIZABLE
9
11
  FPS: int = 60
@@ -14,10 +16,18 @@ class Constants:
14
16
  DEFAULT_CLICK_CURSOR = pygame.cursors.Cursor(pygame.SYSTEM_CURSOR_ARROW)
15
17
 
16
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
+
17
25
 
18
26
  @staticmethod
19
27
  def set_resolution(resolution: tuple[int, int]):
20
28
  Constants.RESOLUTION = resolution
29
+ Constants.WIDTH = resolution[0]
30
+ Constants.HEIGHT = resolution[1]
21
31
 
22
32
  @staticmethod
23
33
  def set_default_cursor(cursor: pygame.Cursor):
@@ -1,5 +1,5 @@
1
1
  import batFramework as bf
2
- from typing import TYPE_CHECKING
2
+ from typing import TYPE_CHECKING,Self
3
3
 
4
4
  class CutsceneBlock: ...
5
5
 
@@ -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:
@@ -75,13 +73,15 @@ class Cutscene:
75
73
  def init_blocks(self):
76
74
  pass
77
75
 
78
- def add_blocks(self, *blocks: CutsceneBlock):
76
+ def add_blocks(self, *blocks: CutsceneBlock)->Self:
79
77
  self.cutscene_blocks.extend(blocks)
80
-
81
- def add_end_blocks(self, *blocks: CutsceneBlock):
78
+ return self
79
+
80
+ def add_end_blocks(self, *blocks: CutsceneBlock)->Self:
82
81
  _ = [block.set_parent_cutscene(self) for block in blocks]
83
82
  self.end_blocks.extend(blocks)
84
-
83
+ return self
84
+
85
85
  def get_scene_at(self, index):
86
86
  return bf.CutsceneManager().manager.scenes[index]
87
87
 
@@ -1,10 +1,10 @@
1
1
  from typing import Any, Self
2
2
  import pygame
3
3
  import batFramework as bf
4
- from .object import Object
4
+ from .entity import Entity
5
5
 
6
6
 
7
- class Entity(Object):
7
+ class Drawable(Entity):
8
8
  """
9
9
  Basic entity class
10
10
  """
@@ -19,6 +19,7 @@ class Entity(Object):
19
19
  ) -> None:
20
20
  super().__init__()
21
21
  self.visible: bool = True
22
+ self.render_order: int = 0
22
23
  self.rect.size = (10, 10) if size is None else size
23
24
  self.convert_alpha: bool = convert_alpha
24
25
  self.surface_flags: int = surface_flags
@@ -65,7 +66,7 @@ class Entity(Object):
65
66
  """
66
67
  Draw the entity onto the camera surface
67
68
  """
68
- 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:
69
70
  return
70
71
  camera.surface.blit(
71
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
 
@@ -7,29 +7,28 @@ if TYPE_CHECKING:
7
7
  from .camera import Camera
8
8
 
9
9
 
10
- class Object:
11
- __count = 0
12
- __available_uid = set()
13
- __used_uid = set()
10
+ class Entity:
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.render_order: int = 0
21
- self.uid: int = Object.__count
22
- Object.__used_uid.add(self.uid)
23
-
24
- if Object.__available_uid:
25
- self.name = Object.__available_uid.pop()
26
- else:
27
- self.name = Object.__count
28
- Object.__count += 1
29
26
 
30
27
  def __del__(self):
31
- Object.__available_uid.add(self.uid)
32
-
28
+ try:
29
+ Entity._available_uids.add(self.uid)
30
+ except AttributeError:
31
+ pass
33
32
  def set_position(self, x, y) -> Self:
34
33
  self.rect.topleft = x, y
35
34
  return self
@@ -61,14 +60,6 @@ class Object:
61
60
  def do_when_removed(self):
62
61
  pass
63
62
 
64
- def set_uid(self, uid: int) -> Self:
65
- if uid in Object.__used_uid:
66
- print(f"set_uid error : UID '{uid}' is already in use")
67
- return self
68
- self.uid = uid
69
- Object.__used_uid.add(uid)
70
- return self
71
-
72
63
  def add_tags(self, *tags) -> Self:
73
64
  for tag in tags:
74
65
  if tag not in self.tags:
@@ -85,10 +76,7 @@ class Object:
85
76
  def get_tags(self) -> list[str]:
86
77
  return self.tags
87
78
 
88
- def process_event(self, event: pygame.Event) -> bool:
89
- """
90
- Returns bool : True if the method is blocking (no propagation to next object of the scene)
91
- """
79
+ def process_event(self, event: pygame.Event) -> None:
92
80
  if event.consumed:
93
81
  return
94
82
  self.do_process_actions(event)
@@ -112,7 +100,7 @@ class Object:
112
100
 
113
101
  def update(self, dt: float) -> None:
114
102
  """
115
- Update method to be overriden by subclasses of object (must call do_update and do_reset_actions)
103
+ Update method to be overriden by subclasses of Entity (must call do_update and do_reset_actions)
116
104
  """
117
105
  self.do_update(dt)
118
106
  self.do_reset_actions()
@@ -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)])))
@@ -0,0 +1,45 @@
1
+ from .label import Label
2
+ import batFramework as bf
3
+ from typing import Self, Callable
4
+ from .clickableWidget import ClickableWidget
5
+ import pygame
6
+ from math import ceil
7
+
8
+
9
+ class Button(Label, ClickableWidget):
10
+ def __init__(self, text: str = "", callback: None | Callable = None) -> None:
11
+ super().__init__(text=text)
12
+ self.set_callback(callback)
13
+
14
+ def __str__(self) -> str:
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
+ )