mini-arcade-native-backend 0.4.6__cp310-cp310-win_amd64.whl → 0.5.3__cp310-cp310-win_amd64.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.
- mini_arcade_native_backend/__init__.py +162 -23
- mini_arcade_native_backend/_native.cp310-win_amd64.pyd +0 -0
- {mini_arcade_native_backend-0.4.6.dist-info → mini_arcade_native_backend-0.5.3.dist-info}/METADATA +2 -2
- mini_arcade_native_backend-0.5.3.dist-info/RECORD +6 -0
- mini_arcade_native_backend-0.4.6.dist-info/RECORD +0 -6
- {mini_arcade_native_backend-0.4.6.dist-info → mini_arcade_native_backend-0.5.3.dist-info}/WHEEL +0 -0
- {mini_arcade_native_backend-0.4.6.dist-info → mini_arcade_native_backend-0.5.3.dist-info}/licenses/LICENSE +0 -0
|
@@ -6,8 +6,9 @@ from __future__ import annotations
|
|
|
6
6
|
|
|
7
7
|
import os
|
|
8
8
|
import sys
|
|
9
|
+
from dataclasses import dataclass
|
|
9
10
|
from pathlib import Path
|
|
10
|
-
from typing import Union
|
|
11
|
+
from typing import Optional, Union
|
|
11
12
|
|
|
12
13
|
# --- 1) Make sure Windows can find SDL2.dll when using vcpkg ------------------
|
|
13
14
|
|
|
@@ -37,13 +38,28 @@ if sys.platform == "win32":
|
|
|
37
38
|
|
|
38
39
|
# Justification: Need to import core after setting DLL path on Windows
|
|
39
40
|
# pylint: disable=wrong-import-position
|
|
40
|
-
|
|
41
|
-
|
|
41
|
+
# Justification: When mini-arcade-core is installed in editable mode, import-error
|
|
42
|
+
# false positive can occur.
|
|
43
|
+
# pylint: disable=import-error
|
|
44
|
+
from mini_arcade_core.backend import ( # pyright: ignore[reportMissingImports]
|
|
45
|
+
Backend,
|
|
46
|
+
WindowSettings,
|
|
47
|
+
)
|
|
48
|
+
from mini_arcade_core.backend.events import ( # pyright: ignore[reportMissingImports]
|
|
49
|
+
Event,
|
|
50
|
+
EventType,
|
|
51
|
+
)
|
|
52
|
+
from mini_arcade_core.backend.sdl_map import ( # pyright: ignore[reportMissingImports]
|
|
53
|
+
SDL_KEYCODE_TO_KEY,
|
|
54
|
+
)
|
|
42
55
|
|
|
43
56
|
# Justification: Importing the native extension module
|
|
44
57
|
# pylint: disable=import-self,no-name-in-module
|
|
45
58
|
from . import _native as native
|
|
46
59
|
|
|
60
|
+
# pylint: enable=import-error
|
|
61
|
+
|
|
62
|
+
|
|
47
63
|
# --- 2) Now import core + define NativeBackend as before ---
|
|
48
64
|
|
|
49
65
|
|
|
@@ -65,23 +81,49 @@ _NATIVE_TO_CORE = {
|
|
|
65
81
|
}
|
|
66
82
|
|
|
67
83
|
|
|
84
|
+
@dataclass
|
|
85
|
+
class BackendSettings:
|
|
86
|
+
"""
|
|
87
|
+
Settings for the NativeBackend.
|
|
88
|
+
|
|
89
|
+
:ivar font_path (Optional[str]): Optional path to a TTF font file to load.
|
|
90
|
+
:ivar font_size (int): Font size in points to use when loading the font.
|
|
91
|
+
:ivar sounds (Optional[dict[str, str]]): Optional dictionary mapping sound IDs to file paths.
|
|
92
|
+
"""
|
|
93
|
+
|
|
94
|
+
font_path: Optional[str] = None
|
|
95
|
+
font_size: int = 24
|
|
96
|
+
sounds: Optional[dict[str, str]] = None # sound_id -> path
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
# TODO: Refactor backend interface into smaller protocols?
|
|
100
|
+
# Justification: Many public methods needed for backend interface
|
|
101
|
+
# pylint: disable=too-many-public-methods,too-many-instance-attributes
|
|
68
102
|
class NativeBackend(Backend):
|
|
69
103
|
"""Adapter that makes the C++ Engine usable as a mini-arcade backend."""
|
|
70
104
|
|
|
71
|
-
def __init__(self,
|
|
105
|
+
def __init__(self, backend_settings: BackendSettings | None = None):
|
|
72
106
|
"""
|
|
73
|
-
:param
|
|
74
|
-
:type
|
|
75
|
-
|
|
76
|
-
:param font_size: Font size in points to use when loading the font.
|
|
77
|
-
:type font_size: int
|
|
107
|
+
:param backend_settings: Optional settings for the backend.
|
|
108
|
+
:type backend_settings: BackendSettings | None
|
|
78
109
|
"""
|
|
79
110
|
self._engine = native.Engine()
|
|
80
|
-
|
|
81
|
-
self.
|
|
111
|
+
|
|
112
|
+
self._font_path = (
|
|
113
|
+
backend_settings.font_path if backend_settings else None
|
|
114
|
+
)
|
|
115
|
+
self._font_size = (
|
|
116
|
+
backend_settings.font_size if backend_settings else 24
|
|
117
|
+
)
|
|
82
118
|
self._default_font_id: int | None = None
|
|
83
119
|
self._fonts_by_size: dict[int, int] = {}
|
|
84
120
|
|
|
121
|
+
self._sounds = backend_settings.sounds if backend_settings else None
|
|
122
|
+
|
|
123
|
+
self._vp_offset_x = 0
|
|
124
|
+
self._vp_offset_y = 0
|
|
125
|
+
self._vp_scale = 1.0
|
|
126
|
+
|
|
85
127
|
def _get_font_id(self, font_size: int | None) -> int:
|
|
86
128
|
# No font loaded -> keep current “no-op” behavior
|
|
87
129
|
if self._font_path is None:
|
|
@@ -108,20 +150,15 @@ class NativeBackend(Backend):
|
|
|
108
150
|
self._fonts_by_size[font_size] = font_id
|
|
109
151
|
return font_id
|
|
110
152
|
|
|
111
|
-
def init(self,
|
|
153
|
+
def init(self, window_settings: WindowSettings):
|
|
112
154
|
"""
|
|
113
155
|
Initialize the backend with a window of given width, height, and title.
|
|
114
156
|
|
|
115
|
-
:param
|
|
116
|
-
:type
|
|
117
|
-
|
|
118
|
-
:param height: Height of the window in pixels.
|
|
119
|
-
:type height: int
|
|
120
|
-
|
|
121
|
-
:param title: Title of the window.
|
|
122
|
-
:type title: str
|
|
157
|
+
:param window_settings: Settings for the backend window.
|
|
158
|
+
:type window_settings: WindowSettings
|
|
123
159
|
"""
|
|
124
|
-
|
|
160
|
+
title = ""
|
|
161
|
+
self._engine.init(window_settings.width, window_settings.height, title)
|
|
125
162
|
|
|
126
163
|
# Load font if provided
|
|
127
164
|
if self._font_path is not None:
|
|
@@ -130,6 +167,20 @@ class NativeBackend(Backend):
|
|
|
130
167
|
)
|
|
131
168
|
self._fonts_by_size[self._font_size] = self._default_font_id
|
|
132
169
|
|
|
170
|
+
# Load sounds if provided
|
|
171
|
+
if self._sounds is not None:
|
|
172
|
+
for sound_id, path in self._sounds.items():
|
|
173
|
+
self.load_sound(sound_id, path)
|
|
174
|
+
|
|
175
|
+
def set_window_title(self, title: str):
|
|
176
|
+
"""
|
|
177
|
+
Set the window title.
|
|
178
|
+
|
|
179
|
+
:param title: Title of the window.
|
|
180
|
+
:type title: str
|
|
181
|
+
"""
|
|
182
|
+
self._engine.set_window_title(title)
|
|
183
|
+
|
|
133
184
|
def set_clear_color(self, r: int, g: int, b: int):
|
|
134
185
|
"""
|
|
135
186
|
Set the background/clear color used by begin_frame.
|
|
@@ -303,7 +354,12 @@ class NativeBackend(Backend):
|
|
|
303
354
|
:type color: tuple[int, ...]
|
|
304
355
|
"""
|
|
305
356
|
r, g, b, a = self._get_color_values(color)
|
|
306
|
-
self.
|
|
357
|
+
sx = int(round(self._vp_offset_x + x * self._vp_scale)) # top-left x
|
|
358
|
+
sy = int(round(self._vp_offset_y + y * self._vp_scale)) # top-left y
|
|
359
|
+
sw = int(round(w * self._vp_scale)) # width
|
|
360
|
+
sh = int(round(h * self._vp_scale)) # height
|
|
361
|
+
self._engine.draw_rect(sx, sy, sw, sh, r, g, b, a)
|
|
362
|
+
# self._engine.draw_rect(x, y, w, h, r, g, b, a)
|
|
307
363
|
|
|
308
364
|
def draw_text(
|
|
309
365
|
self,
|
|
@@ -331,9 +387,22 @@ class NativeBackend(Backend):
|
|
|
331
387
|
"""
|
|
332
388
|
r, g, b, a = self._get_color_values(color)
|
|
333
389
|
font_id = self._get_font_id(font_size)
|
|
390
|
+
sx = int(round(self._vp_offset_x + x * self._vp_scale))
|
|
391
|
+
sy = int(round(self._vp_offset_y + y * self._vp_scale))
|
|
392
|
+
|
|
393
|
+
# optional but recommended: scale font size too
|
|
394
|
+
if font_size is not None:
|
|
395
|
+
scaled = max(8, int(round(font_size * self._vp_scale)))
|
|
396
|
+
else:
|
|
397
|
+
scaled = None
|
|
398
|
+
|
|
399
|
+
font_id = self._get_font_id(scaled)
|
|
334
400
|
self._engine.draw_text(
|
|
335
|
-
text,
|
|
401
|
+
text, sx, sy, int(r), int(g), int(b), int(a), font_id
|
|
336
402
|
)
|
|
403
|
+
# self._engine.draw_text(
|
|
404
|
+
# text, x, y, int(r), int(g), int(b), int(a), font_id
|
|
405
|
+
# )
|
|
337
406
|
|
|
338
407
|
# pylint: enable=too-many-arguments,too-many-positional-arguments
|
|
339
408
|
|
|
@@ -363,3 +432,73 @@ class NativeBackend(Backend):
|
|
|
363
432
|
font_id = self._get_font_id(font_size)
|
|
364
433
|
w, h = self._engine.measure_text(text, font_id)
|
|
365
434
|
return int(w), int(h)
|
|
435
|
+
|
|
436
|
+
def init_audio(
|
|
437
|
+
self, frequency: int = 44100, channels: int = 2, chunk_size: int = 2048
|
|
438
|
+
):
|
|
439
|
+
"""Initialize SDL_mixer audio."""
|
|
440
|
+
self._engine.init_audio(int(frequency), int(channels), int(chunk_size))
|
|
441
|
+
|
|
442
|
+
def shutdown_audio(self):
|
|
443
|
+
"""Shutdown SDL_mixer audio and free loaded sounds."""
|
|
444
|
+
self._engine.shutdown_audio()
|
|
445
|
+
|
|
446
|
+
def load_sound(self, sound_id: str, path: str):
|
|
447
|
+
"""
|
|
448
|
+
Load a WAV sound and store it by ID.
|
|
449
|
+
Example: backend.load_sound("hit", "assets/sfx/hit.wav")
|
|
450
|
+
"""
|
|
451
|
+
if not sound_id:
|
|
452
|
+
raise ValueError("sound_id cannot be empty")
|
|
453
|
+
|
|
454
|
+
p = Path(path)
|
|
455
|
+
if not p.exists():
|
|
456
|
+
raise FileNotFoundError(f"Sound file not found: {p}")
|
|
457
|
+
|
|
458
|
+
self._engine.load_sound(sound_id, str(p))
|
|
459
|
+
|
|
460
|
+
def play_sound(self, sound_id: str, loops: int = 0):
|
|
461
|
+
"""
|
|
462
|
+
Play a loaded sound.
|
|
463
|
+
loops=0 => play once
|
|
464
|
+
loops=-1 => infinite loop
|
|
465
|
+
loops=1 => play twice (SDL convention)
|
|
466
|
+
"""
|
|
467
|
+
self._engine.play_sound(sound_id, int(loops))
|
|
468
|
+
|
|
469
|
+
def set_master_volume(self, volume: int):
|
|
470
|
+
"""
|
|
471
|
+
Master volume: 0..128
|
|
472
|
+
"""
|
|
473
|
+
self._engine.set_master_volume(int(volume))
|
|
474
|
+
|
|
475
|
+
def set_sound_volume(self, sound_id: str, volume: int):
|
|
476
|
+
"""
|
|
477
|
+
Per-sound volume: 0..128
|
|
478
|
+
"""
|
|
479
|
+
self._engine.set_sound_volume(sound_id, int(volume))
|
|
480
|
+
|
|
481
|
+
def stop_all_sounds(self):
|
|
482
|
+
"""Stop all channels."""
|
|
483
|
+
self._engine.stop_all_sounds()
|
|
484
|
+
|
|
485
|
+
def set_viewport_transform(
|
|
486
|
+
self, offset_x: int, offset_y: int, scale: float
|
|
487
|
+
) -> None:
|
|
488
|
+
self._vp_offset_x = int(offset_x)
|
|
489
|
+
self._vp_offset_y = int(offset_y)
|
|
490
|
+
self._vp_scale = float(scale)
|
|
491
|
+
|
|
492
|
+
def clear_viewport_transform(self) -> None:
|
|
493
|
+
self._vp_offset_x = 0
|
|
494
|
+
self._vp_offset_y = 0
|
|
495
|
+
self._vp_scale = 1.0
|
|
496
|
+
|
|
497
|
+
def resize_window(self, width: int, height: int) -> None:
|
|
498
|
+
self._engine.resize_window(int(width), int(height))
|
|
499
|
+
|
|
500
|
+
def set_clip_rect(self, x: int, y: int, w: int, h: int) -> None:
|
|
501
|
+
self._engine.set_clip_rect(int(x), int(y), int(w), int(h))
|
|
502
|
+
|
|
503
|
+
def clear_clip_rect(self) -> None:
|
|
504
|
+
self._engine.clear_clip_rect()
|
|
Binary file
|
{mini_arcade_native_backend-0.4.6.dist-info → mini_arcade_native_backend-0.5.3.dist-info}/METADATA
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.2
|
|
2
2
|
Name: mini-arcade-native-backend
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.5.3
|
|
4
4
|
Summary: Native SDL2 backend for mini-arcade-core using SDL2 + pybind11.
|
|
5
5
|
Author-Email: Santiago Rincon <rincores@gmail.com>
|
|
6
6
|
License: Copyright (c) 2025 Santiago Rincón
|
|
@@ -24,7 +24,7 @@ License: Copyright (c) 2025 Santiago Rincón
|
|
|
24
24
|
SOFTWARE.
|
|
25
25
|
|
|
26
26
|
Requires-Python: <3.12,>=3.9
|
|
27
|
-
Requires-Dist: mini-arcade-core~=0
|
|
27
|
+
Requires-Dist: mini-arcade-core~=1.0
|
|
28
28
|
Provides-Extra: dev
|
|
29
29
|
Requires-Dist: pytest~=8.3; extra == "dev"
|
|
30
30
|
Requires-Dist: pytest-cov~=6.0; extra == "dev"
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
mini_arcade_native_backend/__init__.py,sha256=eguv2ESm07S1h8beSRfKKhMFBywfpsUlo-3forhhCoc,16809
|
|
2
|
+
mini_arcade_native_backend/_native.cp310-win_amd64.pyd,sha256=RdVjaGR589_NHqKLYkwZvhO0FU7iME3OB7dH1o_Uckk,227328
|
|
3
|
+
mini_arcade_native_backend-0.5.3.dist-info/METADATA,sha256=Br3ckI1QZuE2tgZ7eKIgkQf_g8z-b69kdcQIe8k4SSs,10517
|
|
4
|
+
mini_arcade_native_backend-0.5.3.dist-info/WHEEL,sha256=hrGeChGtn46HBGmzasO9QQDSLelRN-tUarBSv4gFcsI,106
|
|
5
|
+
mini_arcade_native_backend-0.5.3.dist-info/licenses/LICENSE,sha256=cZRgTdRJ3YASekMxkGAvylB2nROh4ov228DxAogK3yY,1115
|
|
6
|
+
mini_arcade_native_backend-0.5.3.dist-info/RECORD,,
|
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
mini_arcade_native_backend/__init__.py,sha256=dUcIJJBR6TLFvhjQdNoA-CoT3l6nntrxzhwYvGOkg40,12005
|
|
2
|
-
mini_arcade_native_backend/_native.cp310-win_amd64.pyd,sha256=wGkC8dY6iEGXZOgFdSesFiRAPnZOQ1LX7oW18cZXbPA,212992
|
|
3
|
-
mini_arcade_native_backend-0.4.6.dist-info/METADATA,sha256=rBo0xnG-rqR-gnANDoASoZq5rsZzaWv6SDoBYACXB9Q,10518
|
|
4
|
-
mini_arcade_native_backend-0.4.6.dist-info/WHEEL,sha256=hrGeChGtn46HBGmzasO9QQDSLelRN-tUarBSv4gFcsI,106
|
|
5
|
-
mini_arcade_native_backend-0.4.6.dist-info/licenses/LICENSE,sha256=cZRgTdRJ3YASekMxkGAvylB2nROh4ov228DxAogK3yY,1115
|
|
6
|
-
mini_arcade_native_backend-0.4.6.dist-info/RECORD,,
|
{mini_arcade_native_backend-0.4.6.dist-info → mini_arcade_native_backend-0.5.3.dist-info}/WHEEL
RENAMED
|
File without changes
|
|
File without changes
|