mini-arcade-core 0.9.3__tar.gz → 0.9.4__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 (21) hide show
  1. {mini_arcade_core-0.9.3 → mini_arcade_core-0.9.4}/PKG-INFO +1 -1
  2. {mini_arcade_core-0.9.3 → mini_arcade_core-0.9.4}/pyproject.toml +1 -1
  3. {mini_arcade_core-0.9.3 → mini_arcade_core-0.9.4}/src/mini_arcade_core/__init__.py +2 -0
  4. mini_arcade_core-0.9.4/src/mini_arcade_core/autoreg.py +39 -0
  5. {mini_arcade_core-0.9.3 → mini_arcade_core-0.9.4}/src/mini_arcade_core/registry.py +51 -1
  6. {mini_arcade_core-0.9.3 → mini_arcade_core-0.9.4}/src/mini_arcade_core/ui/menu.py +3 -7
  7. {mini_arcade_core-0.9.3 → mini_arcade_core-0.9.4}/LICENSE +0 -0
  8. {mini_arcade_core-0.9.3 → mini_arcade_core-0.9.4}/README.md +0 -0
  9. {mini_arcade_core-0.9.3 → mini_arcade_core-0.9.4}/src/mini_arcade_core/backend.py +0 -0
  10. {mini_arcade_core-0.9.3 → mini_arcade_core-0.9.4}/src/mini_arcade_core/boundaries2d.py +0 -0
  11. {mini_arcade_core-0.9.3 → mini_arcade_core-0.9.4}/src/mini_arcade_core/collision2d.py +0 -0
  12. {mini_arcade_core-0.9.3 → mini_arcade_core-0.9.4}/src/mini_arcade_core/entity.py +0 -0
  13. {mini_arcade_core-0.9.3 → mini_arcade_core-0.9.4}/src/mini_arcade_core/game.py +0 -0
  14. {mini_arcade_core-0.9.3 → mini_arcade_core-0.9.4}/src/mini_arcade_core/geometry2d.py +0 -0
  15. {mini_arcade_core-0.9.3 → mini_arcade_core-0.9.4}/src/mini_arcade_core/keymaps/__init__.py +0 -0
  16. {mini_arcade_core-0.9.3 → mini_arcade_core-0.9.4}/src/mini_arcade_core/keymaps/sdl.py +0 -0
  17. {mini_arcade_core-0.9.3 → mini_arcade_core-0.9.4}/src/mini_arcade_core/keys.py +0 -0
  18. {mini_arcade_core-0.9.3 → mini_arcade_core-0.9.4}/src/mini_arcade_core/kinematics2d.py +0 -0
  19. {mini_arcade_core-0.9.3 → mini_arcade_core-0.9.4}/src/mini_arcade_core/physics2d.py +0 -0
  20. {mini_arcade_core-0.9.3 → mini_arcade_core-0.9.4}/src/mini_arcade_core/scene.py +0 -0
  21. {mini_arcade_core-0.9.3 → mini_arcade_core-0.9.4}/src/mini_arcade_core/ui/__init__.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: mini-arcade-core
3
- Version: 0.9.3
3
+ Version: 0.9.4
4
4
  Summary: Tiny scene-based game loop core for small arcade games.
5
5
  License: Copyright (c) 2025 Santiago Rincón
6
6
 
@@ -4,7 +4,7 @@ build-backend = "poetry.core.masonry.api"
4
4
 
5
5
  [project]
6
6
  name = "mini-arcade-core"
7
- version = "0.9.3"
7
+ version = "0.9.4"
8
8
  description = "Tiny scene-based game loop core for small arcade games."
9
9
  authors = [
10
10
  { name = "Santiago Rincon", email = "rincores@gmail.com" },
@@ -8,6 +8,7 @@ from __future__ import annotations
8
8
  import logging
9
9
  from importlib.metadata import PackageNotFoundError, version
10
10
 
11
+ from .autoreg import register_scene
11
12
  from .backend import Backend, Event, EventType
12
13
  from .boundaries2d import (
13
14
  RectKinematic,
@@ -78,6 +79,7 @@ __all__ = [
78
79
  "Key",
79
80
  "keymap",
80
81
  "SceneRegistry",
82
+ "register_scene",
81
83
  ]
82
84
 
83
85
  PACKAGE_NAME = "mini-arcade-core" # or whatever is in your pyproject.toml
@@ -0,0 +1,39 @@
1
+ """
2
+ Autoregistration utilities for mini arcade core.
3
+ Allows automatic registration of Scene classes via decorators.
4
+ """
5
+
6
+ from __future__ import annotations
7
+
8
+ from typing import TYPE_CHECKING, Dict, Type
9
+
10
+ if TYPE_CHECKING:
11
+ from .scene import Scene
12
+
13
+ _AUTO: Dict[str, Type["Scene"]] = {}
14
+
15
+
16
+ def register_scene(scene_id: str):
17
+ """Decorator to mark and register a Scene class under an id."""
18
+
19
+ def deco(cls: Type["Scene"]):
20
+ _AUTO[scene_id] = cls
21
+ setattr(cls, "__scene_id__", scene_id)
22
+ return cls
23
+
24
+ return deco
25
+
26
+
27
+ def snapshot() -> Dict[str, Type["Scene"]]:
28
+ """
29
+ Copy of current catalog (useful for tests).
30
+
31
+ :return: A copy of the current scene catalog.
32
+ :rtype: Dict[str, Type["Scene"]]
33
+ """
34
+ return dict(_AUTO)
35
+
36
+
37
+ def clear():
38
+ """Clear the current catalog (useful for tests)."""
39
+ _AUTO.clear()
@@ -5,9 +5,13 @@ Allows registering and creating scenes by string IDs.
5
5
 
6
6
  from __future__ import annotations
7
7
 
8
+ import importlib
9
+ import pkgutil
8
10
  from dataclasses import dataclass
9
11
  from typing import TYPE_CHECKING, Dict, Protocol
10
12
 
13
+ from .autoreg import snapshot
14
+
11
15
  if TYPE_CHECKING:
12
16
  from mini_arcade_core.game import Game
13
17
  from mini_arcade_core.scene import Scene
@@ -29,7 +33,7 @@ class SceneRegistry:
29
33
 
30
34
  _factories: Dict[str, SceneFactory]
31
35
 
32
- def register(self, scene_id: str, factory: SceneFactory) -> None:
36
+ def register(self, scene_id: str, factory: SceneFactory):
33
37
  """
34
38
  Register a scene factory under a given scene ID.
35
39
 
@@ -41,6 +45,22 @@ class SceneRegistry:
41
45
  """
42
46
  self._factories[scene_id] = factory
43
47
 
48
+ def register_cls(self, scene_id: str, scene_cls: type["Scene"]):
49
+ """
50
+ Register a Scene class under a given scene ID.
51
+
52
+ :param scene_id: The string ID for the scene.
53
+ :type scene_id: str
54
+
55
+ :param scene_cls: The Scene class to register.
56
+ :type scene_cls: type["Scene"]
57
+ """
58
+
59
+ def return_factory(game: "Game") -> "Scene":
60
+ return scene_cls(game)
61
+
62
+ self.register(scene_id, return_factory)
63
+
44
64
  def create(self, scene_id: str, game: "Game") -> "Scene":
45
65
  """
46
66
  Create a scene instance using the registered factory for the given scene ID.
@@ -60,3 +80,33 @@ class SceneRegistry:
60
80
  return self._factories[scene_id](game)
61
81
  except KeyError as e:
62
82
  raise KeyError(f"Unknown scene_id={scene_id!r}") from e
83
+
84
+ def load_catalog(self, catalog: Dict[str, type["Scene"]]):
85
+ """
86
+ Load a catalog of Scene classes into the registry.
87
+
88
+ :param catalog: A dictionary mapping scene IDs to Scene classes.
89
+ :type catalog: Dict[str, type["Scene"]]
90
+ """
91
+ for scene_id, cls in catalog.items():
92
+ self.register_cls(scene_id, cls)
93
+
94
+ def discover(self, package: str) -> "SceneRegistry":
95
+ """
96
+ Import all modules in a package so @scene decorators run.
97
+
98
+ :param package: The package name to scan for scene modules.
99
+ :type package: str
100
+
101
+ :return: The SceneRegistry instance (for chaining).
102
+ :rtype: SceneRegistry
103
+ """
104
+ pkg = importlib.import_module(package)
105
+ if not hasattr(pkg, "__path__"):
106
+ return self # not a package
107
+
108
+ for mod in pkgutil.walk_packages(pkg.__path__, pkg.__name__ + "."):
109
+ importlib.import_module(mod.name)
110
+
111
+ self.load_catalog(snapshot())
112
+ return self
@@ -253,9 +253,7 @@ class Menu:
253
253
  color=self.style.hint_color,
254
254
  )
255
255
 
256
- def _draw_text_items(
257
- self, surface: Backend, x_center: int, cursor_y: int
258
- ) -> None:
256
+ def _draw_text_items(self, surface: Backend, x_center: int, cursor_y: int):
259
257
  for i, item in enumerate(self.items):
260
258
  color = (
261
259
  self.style.selected
@@ -272,9 +270,7 @@ class Menu:
272
270
 
273
271
  # Justification: Local variables for layout calculations
274
272
  # pylint: disable=too-many-locals
275
- def _draw_buttons(
276
- self, surface: Backend, x_center: int, cursor_y: int
277
- ) -> None:
273
+ def _draw_buttons(self, surface: Backend, x_center: int, cursor_y: int):
278
274
  # Determine button width: fixed or auto-fit
279
275
  if self.style.button_width is not None:
280
276
  bw = self.style.button_width
@@ -366,6 +362,6 @@ class Menu:
366
362
  text: str,
367
363
  *,
368
364
  color: Color,
369
- ) -> None:
365
+ ):
370
366
  w, _ = surface.measure_text(text)
371
367
  surface.draw_text(x_center - (w // 2), y, text, color=color)