pygkit 1.0.8__tar.gz → 2.1.0__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.
- {pygkit-1.0.8 → pygkit-2.1.0}/PKG-INFO +21 -4
- {pygkit-1.0.8 → pygkit-2.1.0}/README.md +11 -3
- {pygkit-1.0.8 → pygkit-2.1.0}/pyproject.toml +17 -1
- pygkit-2.1.0/src/pygkit/__init__.py +231 -0
- {pygkit-1.0.8 → pygkit-2.1.0}/src/pygkit/animation/player.py +29 -24
- pygkit-2.1.0/src/pygkit/audio/__init__.py +7 -0
- pygkit-2.1.0/src/pygkit/audio/soundmanager.py +262 -0
- {pygkit-1.0.8 → pygkit-2.1.0}/src/pygkit/inventory/__init__.py +1 -16
- {pygkit-1.0.8 → pygkit-2.1.0}/src/pygkit/inventory/assets.py +1 -4
- {pygkit-1.0.8 → pygkit-2.1.0}/src/pygkit/inventory/core.py +17 -8
- {pygkit-1.0.8 → pygkit-2.1.0}/src/pygkit/inventory/data.py +1 -2
- {pygkit-1.0.8 → pygkit-2.1.0}/src/pygkit/inventory/ui.py +27 -14
- {pygkit-1.0.8 → pygkit-2.1.0}/src/pygkit/lighting/__init__.py +4 -4
- {pygkit-1.0.8 → pygkit-2.1.0}/src/pygkit/lighting/lightmap.py +9 -3
- {pygkit-1.0.8 → pygkit-2.1.0}/src/pygkit/lighting/lights.py +269 -56
- {pygkit-1.0.8 → pygkit-2.1.0}/src/pygkit/lighting/sprites.py +11 -1
- pygkit-2.1.0/src/pygkit/parallax/__init__.py +8 -0
- pygkit-2.1.0/src/pygkit/parallax/background.py +139 -0
- pygkit-2.1.0/src/pygkit/parallax/camera.py +182 -0
- pygkit-2.1.0/src/pygkit/protocols.py +49 -0
- {pygkit-1.0.8 → pygkit-2.1.0}/src/pygkit/signals/core.py +34 -8
- {pygkit-1.0.8 → pygkit-2.1.0}/src/pygkit/transitions/base.py +38 -2
- {pygkit-1.0.8 → pygkit-2.1.0}/src/pygkit/transitions/effects.py +59 -25
- {pygkit-1.0.8 → pygkit-2.1.0}/src/pygkit/transitions/fades.py +44 -28
- {pygkit-1.0.8 → pygkit-2.1.0}/src/pygkit/transitions/wipes.py +46 -25
- {pygkit-1.0.8 → pygkit-2.1.0}/src/pygkit/ui/__init__.py +12 -0
- pygkit-2.1.0/src/pygkit/ui/anchors.py +80 -0
- {pygkit-1.0.8 → pygkit-2.1.0}/src/pygkit/ui/base.py +5 -5
- pygkit-2.1.0/src/pygkit/ui/button.py +140 -0
- pygkit-2.1.0/src/pygkit/ui/container.py +54 -0
- {pygkit-1.0.8 → pygkit-2.1.0}/src/pygkit/ui/cooldown.py +11 -6
- {pygkit-1.0.8 → pygkit-2.1.0}/src/pygkit/ui/dialog.py +47 -71
- pygkit-2.1.0/src/pygkit/ui/menubar.py +118 -0
- {pygkit-1.0.8 → pygkit-2.1.0}/src/pygkit/ui/progressbar.py +3 -3
- {pygkit-1.0.8 → pygkit-2.1.0}/src/pygkit/utils/interpolation.py +3 -3
- {pygkit-1.0.8 → pygkit-2.1.0}/src/pygkit/utils/text.py +8 -11
- pygkit-2.1.0/src/pygkit/utils/timer.py +70 -0
- {pygkit-1.0.8 → pygkit-2.1.0}/src/pygkit.egg-info/PKG-INFO +21 -4
- {pygkit-1.0.8 → pygkit-2.1.0}/src/pygkit.egg-info/SOURCES.txt +14 -0
- pygkit-2.1.0/src/pygkit.egg-info/requires.txt +18 -0
- pygkit-2.1.0/tests/test_anchors.py +39 -0
- {pygkit-1.0.8 → pygkit-2.1.0}/tests/test_animation.py +25 -16
- pygkit-2.1.0/tests/test_audio.py +200 -0
- pygkit-2.1.0/tests/test_button.py +104 -0
- pygkit-2.1.0/tests/test_container.py +69 -0
- pygkit-2.1.0/tests/test_cooldown.py +42 -0
- {pygkit-1.0.8 → pygkit-2.1.0}/tests/test_dialog.py +24 -1
- {pygkit-1.0.8 → pygkit-2.1.0}/tests/test_interpolation.py +17 -8
- {pygkit-1.0.8 → pygkit-2.1.0}/tests/test_inventory.py +176 -0
- {pygkit-1.0.8 → pygkit-2.1.0}/tests/test_lighting.py +66 -0
- pygkit-2.1.0/tests/test_menubar.py +132 -0
- pygkit-2.1.0/tests/test_packaging.py +106 -0
- pygkit-2.1.0/tests/test_parallax.py +280 -0
- {pygkit-1.0.8 → pygkit-2.1.0}/tests/test_signals.py +21 -5
- {pygkit-1.0.8 → pygkit-2.1.0}/tests/test_text.py +1 -1
- pygkit-2.1.0/tests/test_timer.py +112 -0
- {pygkit-1.0.8 → pygkit-2.1.0}/tests/test_transitions.py +37 -1
- pygkit-1.0.8/src/pygkit/__init__.py +0 -95
- pygkit-1.0.8/src/pygkit/audio/__init__.py +0 -6
- pygkit-1.0.8/src/pygkit/audio/soundmanager.py +0 -89
- pygkit-1.0.8/src/pygkit/protocols.py +0 -29
- pygkit-1.0.8/src/pygkit/ui/container.py +0 -21
- pygkit-1.0.8/src/pygkit/utils/timer.py +0 -35
- pygkit-1.0.8/src/pygkit.egg-info/requires.txt +0 -1
- pygkit-1.0.8/tests/test_timer.py +0 -42
- {pygkit-1.0.8 → pygkit-2.1.0}/LICENSE +0 -0
- {pygkit-1.0.8 → pygkit-2.1.0}/setup.cfg +0 -0
- {pygkit-1.0.8 → pygkit-2.1.0}/src/pygkit/animation/__init__.py +0 -0
- {pygkit-1.0.8 → pygkit-2.1.0}/src/pygkit/animation/sheet.py +0 -0
- {pygkit-1.0.8 → pygkit-2.1.0}/src/pygkit/lighting/blend.py +0 -0
- {pygkit-1.0.8 → pygkit-2.1.0}/src/pygkit/signals/__init__.py +0 -0
- {pygkit-1.0.8 → pygkit-2.1.0}/src/pygkit/transitions/__init__.py +0 -0
- {pygkit-1.0.8 → pygkit-2.1.0}/src/pygkit/utils/__init__.py +0 -0
- {pygkit-1.0.8 → pygkit-2.1.0}/src/pygkit.egg-info/dependency_links.txt +0 -0
- {pygkit-1.0.8 → pygkit-2.1.0}/src/pygkit.egg-info/top_level.txt +0 -0
- {pygkit-1.0.8 → pygkit-2.1.0}/tests/test_box_model.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: pygkit
|
|
3
|
-
Version: 1.0
|
|
3
|
+
Version: 2.1.0
|
|
4
4
|
Summary: General-purpose Pygame CE runtime kit: UI widgets, audio, timers, interpolation, and more.
|
|
5
5
|
Author: pygkit contributors
|
|
6
6
|
License: GNU GENERAL PUBLIC LICENSE
|
|
@@ -694,6 +694,15 @@ Requires-Python: >=3.10
|
|
|
694
694
|
Description-Content-Type: text/markdown
|
|
695
695
|
License-File: LICENSE
|
|
696
696
|
Requires-Dist: pygame-ce>=2.5
|
|
697
|
+
Provides-Extra: ui
|
|
698
|
+
Provides-Extra: audio
|
|
699
|
+
Provides-Extra: animation
|
|
700
|
+
Provides-Extra: lighting
|
|
701
|
+
Provides-Extra: transitions
|
|
702
|
+
Provides-Extra: inventory
|
|
703
|
+
Provides-Extra: parallax
|
|
704
|
+
Provides-Extra: all
|
|
705
|
+
Requires-Dist: pygkit[animation,audio,inventory,lighting,parallax,transitions,ui]; extra == "all"
|
|
697
706
|
Dynamic: license-file
|
|
698
707
|
|
|
699
708
|
# pygkit
|
|
@@ -708,11 +717,11 @@ import pygkit
|
|
|
708
717
|
|
|
709
718
|
## Features
|
|
710
719
|
|
|
711
|
-
- **UI**: Box-model widgets with plugin compositing — progress bars, cooldown overlays, containers, dialog system
|
|
720
|
+
- **UI**: Box-model widgets with plugin compositing — progress bars, cooldown overlays, containers, dialog system, buttons, menubar container, anchor/row/grid placement helpers
|
|
712
721
|
- **Animation**: Multi-state `AnimationPlayer` where every state owns its own spritesheet — mixed image sizes and grids (e.g. `idle_spritesheet.png` vs `run_spritesheet.png`) in one player; pure image API, no JSON
|
|
713
722
|
- **Dialog**: Typewriter effect with customizable speeds, speaker names, and progress indicators
|
|
714
723
|
- **Inventory**: Grid-based item management with stacking, weight tracking, events, and serialization
|
|
715
|
-
- **Audio**: SoundManager with channel pools
|
|
724
|
+
- **Audio**: SoundManager with channel pools, kind/key addressing, volume buses, fades
|
|
716
725
|
- **Lighting**: low-resolution light map pipeline (`LightMap`), point lights
|
|
717
726
|
with flicker, wind-reactive `DynamicLight` flames, and cone `Spotlight` —
|
|
718
727
|
full RGB/RGBA blend modes, allocation-free per frame
|
|
@@ -722,5 +731,13 @@ import pygkit
|
|
|
722
731
|
## Installation
|
|
723
732
|
|
|
724
733
|
```bash
|
|
725
|
-
pip install pygkit
|
|
734
|
+
pip install pygkit # core: signals, utils, protocols
|
|
735
|
+
pip install "pygkit[ui]" # widgets, dialog, cooldowns
|
|
736
|
+
pip install "pygkit[all]" # everything
|
|
726
737
|
```
|
|
738
|
+
|
|
739
|
+
Available extras: `ui`, `audio`, `animation`, `lighting`,
|
|
740
|
+
`transitions`, `inventory`, `parallax`, `all`. `import pygkit` alone loads
|
|
741
|
+
core only; subsystems load lazily on first use.
|
|
742
|
+
|
|
743
|
+
> Extra: lightning idea was extended version of [https://www.youtube.com/watch?v=LN7u20H7zK4](https://www.youtube.com/watch?v=LN7u20H7zK4) which was my first attempt of making lightning after learning blend modes.
|
|
@@ -10,11 +10,11 @@ import pygkit
|
|
|
10
10
|
|
|
11
11
|
## Features
|
|
12
12
|
|
|
13
|
-
- **UI**: Box-model widgets with plugin compositing — progress bars, cooldown overlays, containers, dialog system
|
|
13
|
+
- **UI**: Box-model widgets with plugin compositing — progress bars, cooldown overlays, containers, dialog system, buttons, menubar container, anchor/row/grid placement helpers
|
|
14
14
|
- **Animation**: Multi-state `AnimationPlayer` where every state owns its own spritesheet — mixed image sizes and grids (e.g. `idle_spritesheet.png` vs `run_spritesheet.png`) in one player; pure image API, no JSON
|
|
15
15
|
- **Dialog**: Typewriter effect with customizable speeds, speaker names, and progress indicators
|
|
16
16
|
- **Inventory**: Grid-based item management with stacking, weight tracking, events, and serialization
|
|
17
|
-
- **Audio**: SoundManager with channel pools
|
|
17
|
+
- **Audio**: SoundManager with channel pools, kind/key addressing, volume buses, fades
|
|
18
18
|
- **Lighting**: low-resolution light map pipeline (`LightMap`), point lights
|
|
19
19
|
with flicker, wind-reactive `DynamicLight` flames, and cone `Spotlight` —
|
|
20
20
|
full RGB/RGBA blend modes, allocation-free per frame
|
|
@@ -24,5 +24,13 @@ import pygkit
|
|
|
24
24
|
## Installation
|
|
25
25
|
|
|
26
26
|
```bash
|
|
27
|
-
pip install pygkit
|
|
27
|
+
pip install pygkit # core: signals, utils, protocols
|
|
28
|
+
pip install "pygkit[ui]" # widgets, dialog, cooldowns
|
|
29
|
+
pip install "pygkit[all]" # everything
|
|
28
30
|
```
|
|
31
|
+
|
|
32
|
+
Available extras: `ui`, `audio`, `animation`, `lighting`,
|
|
33
|
+
`transitions`, `inventory`, `parallax`, `all`. `import pygkit` alone loads
|
|
34
|
+
core only; subsystems load lazily on first use.
|
|
35
|
+
|
|
36
|
+
> Extra: lightning idea was extended version of [https://www.youtube.com/watch?v=LN7u20H7zK4](https://www.youtube.com/watch?v=LN7u20H7zK4) which was my first attempt of making lightning after learning blend modes.
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "pygkit"
|
|
7
|
-
version = "1.0
|
|
7
|
+
version = "2.1.0"
|
|
8
8
|
description = "General-purpose Pygame CE runtime kit: UI widgets, audio, timers, interpolation, and more."
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.10"
|
|
@@ -26,6 +26,22 @@ classifiers = [
|
|
|
26
26
|
"Topic :: Software Development :: Libraries",
|
|
27
27
|
]
|
|
28
28
|
|
|
29
|
+
[project.optional-dependencies]
|
|
30
|
+
# One extra per subsystem. Empty for now: every subsystem is pure
|
|
31
|
+
# pygame-ce + stdlib. Slots are reserved for future speedups
|
|
32
|
+
# (lighting color math -> numpy, sprite pack -> pillow) without
|
|
33
|
+
# taxing core installs.
|
|
34
|
+
ui = []
|
|
35
|
+
audio = []
|
|
36
|
+
animation = []
|
|
37
|
+
lighting = []
|
|
38
|
+
transitions = []
|
|
39
|
+
inventory = []
|
|
40
|
+
parallax = []
|
|
41
|
+
all = [
|
|
42
|
+
"pygkit[ui, audio, animation, lighting, transitions, inventory, parallax]",
|
|
43
|
+
]
|
|
44
|
+
|
|
29
45
|
[project.urls]
|
|
30
46
|
Homepage = "https://github.com/FluffyBrudy/pygkit"
|
|
31
47
|
Repository = "https://github.com/FluffyBrudy/pygkit"
|
|
@@ -0,0 +1,231 @@
|
|
|
1
|
+
"""pygkit - Pygame CE runtime kit.
|
|
2
|
+
|
|
3
|
+
Core (signals, utils, protocols) imports eagerly. Subsystems load
|
|
4
|
+
lazily on first attribute use, so ``import pygkit`` stays cheap::
|
|
5
|
+
|
|
6
|
+
pip install pygkit # core only
|
|
7
|
+
pip install "pygkit[ui]" # + widgets, dialog, cooldowns
|
|
8
|
+
pip install "pygkit[all]" # everything
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
from __future__ import annotations
|
|
12
|
+
|
|
13
|
+
import importlib
|
|
14
|
+
from typing import Any
|
|
15
|
+
|
|
16
|
+
from .protocols import Clickable, Drawable, Renderable, UIElement, Updateable, Widget
|
|
17
|
+
from .signals import Signal, SignalBus, signal
|
|
18
|
+
from .utils import (
|
|
19
|
+
SimpleInterpolation,
|
|
20
|
+
Timer,
|
|
21
|
+
ease_in,
|
|
22
|
+
ease_in_out,
|
|
23
|
+
ease_out,
|
|
24
|
+
fit,
|
|
25
|
+
lerp,
|
|
26
|
+
load_font,
|
|
27
|
+
outline,
|
|
28
|
+
render_multiline,
|
|
29
|
+
shadow,
|
|
30
|
+
smoothstep,
|
|
31
|
+
wrap,
|
|
32
|
+
)
|
|
33
|
+
|
|
34
|
+
_LAZY_ATTRS: dict[str, str] = {
|
|
35
|
+
"SoundManager": "audio",
|
|
36
|
+
"SFX_CHANNELS": "audio",
|
|
37
|
+
"DEFAULT_SFX_CHANNELS": "audio",
|
|
38
|
+
"ParallaxBackground": "parallax",
|
|
39
|
+
"ParallaxLayer": "parallax",
|
|
40
|
+
"Camera2D": "parallax",
|
|
41
|
+
"AnimationPlayer": "animation",
|
|
42
|
+
"AnimationSheet": "animation",
|
|
43
|
+
"PackOptions": "animation",
|
|
44
|
+
"pack_spritesheet": "animation",
|
|
45
|
+
"LightMap": "lighting",
|
|
46
|
+
"PointLight": "lighting",
|
|
47
|
+
"Spotlight": "lighting",
|
|
48
|
+
"DynamicLight": "lighting",
|
|
49
|
+
"glow_sprite": "lighting",
|
|
50
|
+
"spotlight_sprite": "lighting",
|
|
51
|
+
"dynamic_glow_sprite": "lighting",
|
|
52
|
+
"clear_sprite_cache": "lighting",
|
|
53
|
+
"RGB_ADD": "lighting",
|
|
54
|
+
"RGB_SUB": "lighting",
|
|
55
|
+
"RGB_MULT": "lighting",
|
|
56
|
+
"RGB_MIN": "lighting",
|
|
57
|
+
"RGB_MAX": "lighting",
|
|
58
|
+
"RGBA_ADD": "lighting",
|
|
59
|
+
"RGBA_SUB": "lighting",
|
|
60
|
+
"RGBA_MULT": "lighting",
|
|
61
|
+
"RGBA_MIN": "lighting",
|
|
62
|
+
"RGBA_MAX": "lighting",
|
|
63
|
+
"LIGHT_ADD": "lighting",
|
|
64
|
+
"SCENE_MULT": "lighting",
|
|
65
|
+
"TransitionRunner": "transitions",
|
|
66
|
+
"TransitionState": "transitions",
|
|
67
|
+
"FadeToBlack": "transitions",
|
|
68
|
+
"FadeFromBlack": "transitions",
|
|
69
|
+
"Crossfade": "transitions",
|
|
70
|
+
"Flash": "transitions",
|
|
71
|
+
"IrisIn": "transitions",
|
|
72
|
+
"IrisOut": "transitions",
|
|
73
|
+
"Slide": "transitions",
|
|
74
|
+
"PixelDissolve": "transitions",
|
|
75
|
+
"Shake": "transitions",
|
|
76
|
+
"Container": "ui",
|
|
77
|
+
"CooldownOverlay": "ui",
|
|
78
|
+
"ProgressBarUI": "ui",
|
|
79
|
+
"UIBase": "ui",
|
|
80
|
+
"UIOptions": "ui",
|
|
81
|
+
"BoxModel": "ui",
|
|
82
|
+
"BoxModelResult": "ui",
|
|
83
|
+
"generate_box_model": "ui",
|
|
84
|
+
"DialogBox": "ui",
|
|
85
|
+
"DialogConfig": "ui",
|
|
86
|
+
"DialogColors": "ui",
|
|
87
|
+
"DialogLine": "ui",
|
|
88
|
+
"TypewriterSpeed": "ui",
|
|
89
|
+
"Button": "ui",
|
|
90
|
+
"ButtonStyle": "ui",
|
|
91
|
+
"Menubar": "ui",
|
|
92
|
+
"ANCHORS": "ui",
|
|
93
|
+
"anchor_point": "ui",
|
|
94
|
+
"place": "ui",
|
|
95
|
+
"row": "ui",
|
|
96
|
+
"column": "ui",
|
|
97
|
+
"grid": "ui",
|
|
98
|
+
"ItemData": "inventory",
|
|
99
|
+
"InventoryConfig": "inventory",
|
|
100
|
+
"ItemStack": "inventory",
|
|
101
|
+
"InventoryEvent": "inventory",
|
|
102
|
+
"RARITY_COLORS": "inventory",
|
|
103
|
+
"DEFAULT_INVENTORY_CONFIG": "inventory",
|
|
104
|
+
"Inventory": "inventory",
|
|
105
|
+
"AssetCache": "inventory",
|
|
106
|
+
"get_cache": "inventory",
|
|
107
|
+
"generate_procedural_icon": "inventory",
|
|
108
|
+
"render_quantity_text": "inventory",
|
|
109
|
+
"Tooltip": "inventory",
|
|
110
|
+
"DragDropState": "inventory",
|
|
111
|
+
"InventoryWidget": "inventory",
|
|
112
|
+
"InventoryManager": "inventory",
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
__all__ = [
|
|
116
|
+
"SoundManager",
|
|
117
|
+
"SFX_CHANNELS",
|
|
118
|
+
"DEFAULT_SFX_CHANNELS",
|
|
119
|
+
"ParallaxBackground",
|
|
120
|
+
"ParallaxLayer",
|
|
121
|
+
"Camera2D",
|
|
122
|
+
"AnimationPlayer",
|
|
123
|
+
"AnimationSheet",
|
|
124
|
+
"PackOptions",
|
|
125
|
+
"pack_spritesheet",
|
|
126
|
+
"LightMap",
|
|
127
|
+
"PointLight",
|
|
128
|
+
"Spotlight",
|
|
129
|
+
"DynamicLight",
|
|
130
|
+
"glow_sprite",
|
|
131
|
+
"spotlight_sprite",
|
|
132
|
+
"dynamic_glow_sprite",
|
|
133
|
+
"clear_sprite_cache",
|
|
134
|
+
"RGB_ADD",
|
|
135
|
+
"RGB_SUB",
|
|
136
|
+
"RGB_MULT",
|
|
137
|
+
"RGB_MIN",
|
|
138
|
+
"RGB_MAX",
|
|
139
|
+
"RGBA_ADD",
|
|
140
|
+
"RGBA_SUB",
|
|
141
|
+
"RGBA_MULT",
|
|
142
|
+
"RGBA_MIN",
|
|
143
|
+
"RGBA_MAX",
|
|
144
|
+
"LIGHT_ADD",
|
|
145
|
+
"SCENE_MULT",
|
|
146
|
+
"TransitionRunner",
|
|
147
|
+
"TransitionState",
|
|
148
|
+
"FadeToBlack",
|
|
149
|
+
"FadeFromBlack",
|
|
150
|
+
"Crossfade",
|
|
151
|
+
"Flash",
|
|
152
|
+
"IrisIn",
|
|
153
|
+
"IrisOut",
|
|
154
|
+
"Slide",
|
|
155
|
+
"PixelDissolve",
|
|
156
|
+
"Shake",
|
|
157
|
+
"Container",
|
|
158
|
+
"CooldownOverlay",
|
|
159
|
+
"ProgressBarUI",
|
|
160
|
+
"UIBase",
|
|
161
|
+
"UIOptions",
|
|
162
|
+
"BoxModel",
|
|
163
|
+
"BoxModelResult",
|
|
164
|
+
"generate_box_model",
|
|
165
|
+
"DialogBox",
|
|
166
|
+
"DialogConfig",
|
|
167
|
+
"DialogColors",
|
|
168
|
+
"DialogLine",
|
|
169
|
+
"TypewriterSpeed",
|
|
170
|
+
"Button",
|
|
171
|
+
"ButtonStyle",
|
|
172
|
+
"Menubar",
|
|
173
|
+
"ANCHORS",
|
|
174
|
+
"anchor_point",
|
|
175
|
+
"place",
|
|
176
|
+
"row",
|
|
177
|
+
"column",
|
|
178
|
+
"grid",
|
|
179
|
+
"ItemData",
|
|
180
|
+
"InventoryConfig",
|
|
181
|
+
"ItemStack",
|
|
182
|
+
"InventoryEvent",
|
|
183
|
+
"RARITY_COLORS",
|
|
184
|
+
"DEFAULT_INVENTORY_CONFIG",
|
|
185
|
+
"Inventory",
|
|
186
|
+
"AssetCache",
|
|
187
|
+
"get_cache",
|
|
188
|
+
"generate_procedural_icon",
|
|
189
|
+
"render_quantity_text",
|
|
190
|
+
"Tooltip",
|
|
191
|
+
"DragDropState",
|
|
192
|
+
"InventoryWidget",
|
|
193
|
+
"InventoryManager",
|
|
194
|
+
"SimpleInterpolation",
|
|
195
|
+
"Timer",
|
|
196
|
+
"lerp",
|
|
197
|
+
"smoothstep",
|
|
198
|
+
"ease_in_out",
|
|
199
|
+
"ease_out",
|
|
200
|
+
"ease_in",
|
|
201
|
+
"load_font",
|
|
202
|
+
"outline",
|
|
203
|
+
"shadow",
|
|
204
|
+
"wrap",
|
|
205
|
+
"render_multiline",
|
|
206
|
+
"fit",
|
|
207
|
+
"Signal",
|
|
208
|
+
"SignalBus",
|
|
209
|
+
"signal",
|
|
210
|
+
"Renderable",
|
|
211
|
+
"UIElement",
|
|
212
|
+
"Drawable",
|
|
213
|
+
"Updateable",
|
|
214
|
+
"Clickable",
|
|
215
|
+
"Widget",
|
|
216
|
+
]
|
|
217
|
+
|
|
218
|
+
|
|
219
|
+
def __getattr__(name: str) -> Any:
|
|
220
|
+
try:
|
|
221
|
+
sub = _LAZY_ATTRS[name]
|
|
222
|
+
except KeyError:
|
|
223
|
+
raise AttributeError(f"module {__name__!r} has no attribute {name!r}") from None
|
|
224
|
+
module = importlib.import_module(f"{__name__}.{sub}")
|
|
225
|
+
value = getattr(module, name)
|
|
226
|
+
globals()[name] = value
|
|
227
|
+
return value
|
|
228
|
+
|
|
229
|
+
|
|
230
|
+
def __dir__() -> list[str]:
|
|
231
|
+
return sorted(__all__)
|
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
+
import math
|
|
3
4
|
from dataclasses import dataclass
|
|
4
5
|
from typing import Callable
|
|
5
6
|
|
|
6
7
|
from .sheet import AnimationSheet
|
|
7
8
|
|
|
9
|
+
_UNSET: object = object()
|
|
10
|
+
|
|
8
11
|
|
|
9
12
|
@dataclass
|
|
10
13
|
class _State:
|
|
@@ -19,7 +22,7 @@ class AnimationPlayer:
|
|
|
19
22
|
|
|
20
23
|
States are registered lazily via :meth:`play`; sheets may differ freely in
|
|
21
24
|
pixel size and grid layout between states. Playback is time-based: feed
|
|
22
|
-
``update(
|
|
25
|
+
``update(dt)`` each frame with delta time in seconds and blit ``image``.
|
|
23
26
|
"""
|
|
24
27
|
|
|
25
28
|
__slots__ = (
|
|
@@ -89,13 +92,15 @@ class AnimationPlayer:
|
|
|
89
92
|
*,
|
|
90
93
|
fps: float | None = None,
|
|
91
94
|
loop: bool | None = None,
|
|
92
|
-
on_finish: Callable[[], None] | None =
|
|
95
|
+
on_finish: Callable[[], None] | None | object = _UNSET,
|
|
96
|
+
restart: bool = False,
|
|
93
97
|
) -> None:
|
|
94
98
|
"""Switch to *name*, registering the state on first use.
|
|
95
99
|
|
|
96
100
|
Registration requires *sheet*; omitted options fall back to the
|
|
97
101
|
player defaults given at construction. Calling ``play`` for the state
|
|
98
|
-
already playing does not restart it
|
|
102
|
+
already playing does not restart it unless ``restart`` is true.
|
|
103
|
+
Pass ``on_finish=None`` explicitly to clear a default callback.
|
|
99
104
|
"""
|
|
100
105
|
if name not in self._states:
|
|
101
106
|
if sheet is None:
|
|
@@ -106,37 +111,37 @@ class AnimationPlayer:
|
|
|
106
111
|
sheet=sheet,
|
|
107
112
|
fps=float(resolved_fps),
|
|
108
113
|
loop=self._default_loop if loop is None else bool(loop),
|
|
109
|
-
on_finish=self._default_on_finish if on_finish is
|
|
114
|
+
on_finish=self._default_on_finish if on_finish is _UNSET else on_finish,
|
|
110
115
|
)
|
|
111
116
|
|
|
112
|
-
if name == self._state_name:
|
|
117
|
+
if name == self._state_name and not restart:
|
|
113
118
|
return
|
|
114
119
|
self._state_name = name
|
|
115
120
|
self.reset()
|
|
116
121
|
|
|
117
|
-
def update(self,
|
|
118
|
-
"""Advance playback by *
|
|
122
|
+
def update(self, dt: float) -> None:
|
|
123
|
+
"""Advance playback by *dt* seconds."""
|
|
119
124
|
if self._paused or self._state_name is None or self._finished:
|
|
120
125
|
return
|
|
126
|
+
if not math.isfinite(dt) or dt < 0:
|
|
127
|
+
dt = 0.0
|
|
121
128
|
state = self._states[self._state_name]
|
|
122
129
|
frame_count = state.sheet.frame_count
|
|
123
|
-
frame_duration =
|
|
124
|
-
self._elapsed_in_frame
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
state.on_finish()
|
|
139
|
-
break
|
|
130
|
+
frame_duration = 1.0 / state.fps
|
|
131
|
+
steps, self._elapsed_in_frame = divmod(self._elapsed_in_frame + dt, frame_duration)
|
|
132
|
+
steps = int(steps)
|
|
133
|
+
if steps <= 0:
|
|
134
|
+
return
|
|
135
|
+
if state.loop:
|
|
136
|
+
self._frame_index = (self._frame_index + steps) % frame_count
|
|
137
|
+
elif self._frame_index + steps >= frame_count:
|
|
138
|
+
self._frame_index = frame_count - 1
|
|
139
|
+
self._elapsed_in_frame = 0.0
|
|
140
|
+
self._finished = True
|
|
141
|
+
if state.on_finish is not None:
|
|
142
|
+
state.on_finish()
|
|
143
|
+
else:
|
|
144
|
+
self._frame_index += steps
|
|
140
145
|
|
|
141
146
|
def pause(self) -> None:
|
|
142
147
|
self._paused = True
|