e2D 1.4.19__tar.gz → 1.4.20__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.
- {e2d-1.4.19 → e2d-1.4.20}/LICENSE +21 -21
- {e2d-1.4.19 → e2d-1.4.20}/PKG-INFO +3 -2
- {e2d-1.4.19 → e2d-1.4.20}/e2D/__init__.py +8 -0
- {e2d-1.4.19 → e2d-1.4.20}/e2D/__init__.pyi +49 -0
- {e2d-1.4.19 → e2d-1.4.20}/e2D/colors.py +11 -1
- {e2d-1.4.19 → e2d-1.4.20}/e2D/envs.py +38 -14
- e2d-1.4.20/e2D/utils.py +545 -0
- {e2d-1.4.19 → e2d-1.4.20}/e2D.egg-info/PKG-INFO +3 -2
- {e2d-1.4.19 → e2d-1.4.20}/setup.cfg +1 -1
- e2d-1.4.19/e2D/utils.py +0 -191
- {e2d-1.4.19 → e2d-1.4.20}/README.md +0 -0
- {e2d-1.4.19 → e2d-1.4.20}/e2D/def_colors.py +0 -0
- {e2d-1.4.19 → e2d-1.4.20}/e2D/plots.py +0 -0
- {e2d-1.4.19 → e2d-1.4.20}/e2D/winrec.py +0 -0
- {e2d-1.4.19 → e2d-1.4.20}/e2D.egg-info/SOURCES.txt +0 -0
- {e2d-1.4.19 → e2d-1.4.20}/e2D.egg-info/dependency_links.txt +0 -0
- {e2d-1.4.19 → e2d-1.4.20}/e2D.egg-info/requires.txt +0 -0
- {e2d-1.4.19 → e2d-1.4.20}/e2D.egg-info/top_level.txt +0 -0
- {e2d-1.4.19 → e2d-1.4.20}/pyproject.toml +0 -0
|
@@ -1,21 +1,21 @@
|
|
|
1
|
-
MIT License
|
|
2
|
-
|
|
3
|
-
Copyright (c) 2025 Riccardo Mariani
|
|
4
|
-
|
|
5
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
-
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
-
in the Software without restriction, including without limitation the rights
|
|
8
|
-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
-
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
-
furnished to do so, subject to the following conditions:
|
|
11
|
-
|
|
12
|
-
The above copyright notice and this permission notice shall be included in all
|
|
13
|
-
copies or substantial portions of the Software.
|
|
14
|
-
|
|
15
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
-
SOFTWARE.
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Riccardo Mariani
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: e2D
|
|
3
|
-
Version: 1.4.
|
|
3
|
+
Version: 1.4.20
|
|
4
4
|
Summary: Python library for 2D games. Streamlines dev with keyboard/mouse input, vector calculations, color manipulation, and collision detection. Simplify game creation and unleash creativity!
|
|
5
5
|
Home-page: https://github.com/marick-py/e2D
|
|
6
6
|
Author: Riccardo Mariani
|
|
@@ -13,6 +13,7 @@ Description-Content-Type: text/markdown
|
|
|
13
13
|
License-File: LICENSE
|
|
14
14
|
Requires-Dist: numpy
|
|
15
15
|
Requires-Dist: pygame
|
|
16
|
+
Dynamic: license-file
|
|
16
17
|
|
|
17
18
|
# e2D
|
|
18
19
|
## A Python Game Development Library
|
|
@@ -10,6 +10,7 @@ PI_QUARTER = PI/4
|
|
|
10
10
|
PI_DOUBLE = PI*2
|
|
11
11
|
|
|
12
12
|
sign = lambda val: -1 if val < 0 else (1 if val > 0 else 0)
|
|
13
|
+
clamp = lambda x, minn, maxx: x if x > minn and x < maxx else (minn if x < minn else maxx)
|
|
13
14
|
|
|
14
15
|
class Vector2D:
|
|
15
16
|
round_values_on_print = 2
|
|
@@ -42,6 +43,13 @@ class Vector2D:
|
|
|
42
43
|
@property
|
|
43
44
|
def sign(self) -> "Vector2D":
|
|
44
45
|
return Vector2D(sign(self.x), sign(self.y))
|
|
46
|
+
|
|
47
|
+
def clamp(self, min_val: Vector2D, max_val: Vector2D) -> "Vector2D":
|
|
48
|
+
return Vector2D(clamp(self.x, min_val.x, max_val.x), clamp(self.y, min_val.y, max_val.y))
|
|
49
|
+
|
|
50
|
+
def iclamp(self, min_val: Vector2D, max_val: Vector2D) -> None:
|
|
51
|
+
self.x = clamp(self.x, min_val.x, max_val.x)
|
|
52
|
+
self.y = clamp(self.y, min_val.y, max_val.y)
|
|
45
53
|
|
|
46
54
|
@property
|
|
47
55
|
def normalize(self) -> "Vector2D":
|
|
@@ -12,6 +12,7 @@ PI_DOUBLE : float
|
|
|
12
12
|
#
|
|
13
13
|
|
|
14
14
|
sign : Callable[[int|float], Literal[-1,0,1]]
|
|
15
|
+
clamp: Callable[[int|float, int|float, int|float], int|float]
|
|
15
16
|
|
|
16
17
|
class Vector2D:
|
|
17
18
|
round_values_on_print : int|float
|
|
@@ -211,6 +212,54 @@ class Vector2D:
|
|
|
211
212
|
"""
|
|
212
213
|
...
|
|
213
214
|
|
|
215
|
+
def clamp(self, min_val: Vector2D, max_val: Vector2D) -> "Vector2D":
|
|
216
|
+
"""
|
|
217
|
+
# Clamp the vector's components between the corresponding components of two other vectors.
|
|
218
|
+
|
|
219
|
+
## Parameters:
|
|
220
|
+
min_val (Vector2D): The minimum vector for clamping.
|
|
221
|
+
max_val (Vector2D): The maximum vector for clamping.
|
|
222
|
+
|
|
223
|
+
## Returns:
|
|
224
|
+
Vector2D: A new vector with its components clamped between the corresponding components of `min_val` and `max_val`.
|
|
225
|
+
|
|
226
|
+
## Example:
|
|
227
|
+
v = Vector2D(5, 10)
|
|
228
|
+
min_val = Vector2D(0, 8)
|
|
229
|
+
max_val = Vector2D(6, 12)
|
|
230
|
+
clamped_v = v.clamp(min_val, max_val)
|
|
231
|
+
print(clamped_v) # Output: (5, 10)
|
|
232
|
+
|
|
233
|
+
## Explanation:
|
|
234
|
+
This method clamps the x and y components of the current vector between the corresponding x and y components
|
|
235
|
+
of the `min_val` and `max_val` vectors. The resulting vector is returned as a new Vector2D instance.
|
|
236
|
+
"""
|
|
237
|
+
...
|
|
238
|
+
|
|
239
|
+
def iclamp(self, min_val: Vector2D, max_val: Vector2D) -> None:
|
|
240
|
+
"""
|
|
241
|
+
# Clamp the vector's components in place between the corresponding components of two other vectors.
|
|
242
|
+
|
|
243
|
+
## Parameters:
|
|
244
|
+
min_val (Vector2D): The minimum vector for clamping.
|
|
245
|
+
max_val (Vector2D): The maximum vector for clamping.
|
|
246
|
+
|
|
247
|
+
## Returns:
|
|
248
|
+
None
|
|
249
|
+
|
|
250
|
+
## Example:
|
|
251
|
+
v = Vector2D(5, 10)
|
|
252
|
+
min_val = Vector2D(0, 8)
|
|
253
|
+
max_val = Vector2D(6, 12)
|
|
254
|
+
v.iclamp(min_val, max_val)
|
|
255
|
+
print(v) # Output: (5, 10)
|
|
256
|
+
|
|
257
|
+
## Explanation:
|
|
258
|
+
This method clamps the x and y components of the current vector in place between the corresponding x and y components
|
|
259
|
+
of the `min_val` and `max_val` vectors. The method modifies the current vector directly.
|
|
260
|
+
"""
|
|
261
|
+
...
|
|
262
|
+
|
|
214
263
|
@property
|
|
215
264
|
def normalize(self:"Vector2D") -> "Vector2D":
|
|
216
265
|
"""
|
|
@@ -82,6 +82,12 @@ __conversion_table__ :dict[__LITERAL_COLOR_MODES__, dict[__LITERAL_COLOR_MODES__
|
|
|
82
82
|
},
|
|
83
83
|
}
|
|
84
84
|
|
|
85
|
+
def pygamize_color(color: "__color_pygame__|Color") -> "__color_pygame__":
|
|
86
|
+
return color() if isinstance(color, Color) else color
|
|
87
|
+
|
|
88
|
+
def unpygamize_color(color: "__color_pygame__|Color") -> "Color":
|
|
89
|
+
return Color(*color[:], mode=RGBA_COLOR_MODE) if isinstance(color, __color_pygame__) else color
|
|
90
|
+
|
|
85
91
|
class Color:
|
|
86
92
|
def __init__(self, *values, mode:__LITERAL_COLOR_MODES__=RGB_COLOR_MODE) -> None:
|
|
87
93
|
self.__dict__ = dict(zip(mode, values))
|
|
@@ -179,7 +185,7 @@ class Color:
|
|
|
179
185
|
return "Color(" + ", ".join(f"{k}:{v}" for k, v in self.items) + ")"
|
|
180
186
|
|
|
181
187
|
def __call__(self) -> __color_pygame__:
|
|
182
|
-
return __color_pygame__(int(self.r), int(self.g), int(self.b))
|
|
188
|
+
return __color_pygame__(int(self.r), int(self.g), int(self.b)) if self.mode == RGB_COLOR_MODE else __color_pygame__(int(self.r), int(self.g), int(self.b), int(self.a))
|
|
183
189
|
|
|
184
190
|
# fast operations Vector2D.operation(both,x,y)
|
|
185
191
|
def add(self, all3=.0, r=.0, g=.0, b=.0) -> "Color":
|
|
@@ -408,6 +414,8 @@ class Color:
|
|
|
408
414
|
except:
|
|
409
415
|
raise TypeError(f"The value {other} of type {type(other)} is not a num type: [{int|float}] nor an array type: [{list|tuple}]")
|
|
410
416
|
|
|
417
|
+
@classmethod
|
|
418
|
+
def transparent(cls) -> "Color": return Color(0,0,0,0, mode=RGBA_COLOR_MODE)
|
|
411
419
|
@classmethod
|
|
412
420
|
def white(cls) -> "Color": return Color(255,255,255)
|
|
413
421
|
@classmethod
|
|
@@ -427,12 +435,14 @@ class Color:
|
|
|
427
435
|
return Color(__randint__(0,255), __randint__(0,255), __randint__(0,255))
|
|
428
436
|
|
|
429
437
|
|
|
438
|
+
TRANSPARENT_COLOR = Color.transparent()
|
|
430
439
|
WHITE_COLOR = Color.white()
|
|
431
440
|
BLACK_COLOR = Color.black()
|
|
432
441
|
RED_COLOR = Color.red()
|
|
433
442
|
GREEN_COLOR = Color.green()
|
|
434
443
|
BLUE_COLOR = Color.blue()
|
|
435
444
|
|
|
445
|
+
TRANSPARENT_COLOR_PYG = TRANSPARENT_COLOR()
|
|
436
446
|
WHITE_COLOR_PYG = WHITE_COLOR()
|
|
437
447
|
BLACK_COLOR_PYG = BLACK_COLOR()
|
|
438
448
|
RED_COLOR_PYG = RED_COLOR()
|
|
@@ -59,12 +59,21 @@ class RootEnv:
|
|
|
59
59
|
self.current_frame = 0
|
|
60
60
|
self.show_fps = show_fps
|
|
61
61
|
self.events :list[pg.event.Event]= []
|
|
62
|
-
|
|
62
|
+
|
|
63
|
+
self.__background_color__ :Color= BLACK_COLOR_PYG
|
|
64
|
+
|
|
63
65
|
self.clear_screen_each_frame = clear_screen_each_frame
|
|
64
66
|
self.utils :dict[int|str, Util]= {}
|
|
65
67
|
self.selected_util :Util|None = None
|
|
66
68
|
self.__quit_on_key_pressed__ = quit_on_key_pressed
|
|
67
69
|
|
|
70
|
+
@property
|
|
71
|
+
def background_color(self) -> Color:
|
|
72
|
+
return unpygamize_color(self.__background_color__)
|
|
73
|
+
@background_color.setter
|
|
74
|
+
def background_color(self, color: Color|pg.Color) -> None:
|
|
75
|
+
self.__background_color__ = pygamize_color(color)
|
|
76
|
+
|
|
68
77
|
@property
|
|
69
78
|
def screen_size(self) -> Vector2D:
|
|
70
79
|
return self.__screen_size__
|
|
@@ -96,6 +105,8 @@ class RootEnv:
|
|
|
96
105
|
for util in utils:
|
|
97
106
|
if util.surface == None: util.surface = self.screen
|
|
98
107
|
util.rootEnv = self
|
|
108
|
+
util.id = self.__new_util_id__()
|
|
109
|
+
util.render()
|
|
99
110
|
self.utils[util.id] = util
|
|
100
111
|
|
|
101
112
|
def remove_utils(self, *utils:int|str|Util) -> None:
|
|
@@ -106,6 +117,18 @@ class RootEnv:
|
|
|
106
117
|
del self.utils[uid.id]
|
|
107
118
|
else:
|
|
108
119
|
raise Exception(f"Unknown util type: {uid}")
|
|
120
|
+
|
|
121
|
+
def __new_util_id__(self) -> int:
|
|
122
|
+
if not self.utils: return 0
|
|
123
|
+
else: return max(self.utils.keys()) + 1
|
|
124
|
+
|
|
125
|
+
def get_util(self, uid:int|str) -> Util|None:
|
|
126
|
+
if isinstance(uid, Util):
|
|
127
|
+
return self.utils.get(uid.id)
|
|
128
|
+
elif isinstance(uid, int) or isinstance(uid, str):
|
|
129
|
+
return self.utils.get(uid)
|
|
130
|
+
else:
|
|
131
|
+
raise Exception(f"Unknown util type: {uid}")
|
|
109
132
|
|
|
110
133
|
@property
|
|
111
134
|
def runtime_seconds(self) -> float:
|
|
@@ -115,24 +138,25 @@ class RootEnv:
|
|
|
115
138
|
self.env = sub_env
|
|
116
139
|
|
|
117
140
|
def clear(self) -> None:
|
|
118
|
-
self.screen.fill(self.
|
|
141
|
+
self.screen.fill(self.__background_color__)
|
|
119
142
|
|
|
120
143
|
def clear_rect(self, position:Vector2D, size:Vector2D) -> None:
|
|
121
|
-
self.screen.fill(self.
|
|
144
|
+
self.screen.fill(self.__background_color__, position() + size())
|
|
122
145
|
|
|
123
146
|
def print(self,
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
147
|
+
text : str,
|
|
148
|
+
position : Vector2D,
|
|
149
|
+
color : pg.color.Color = WHITE_COLOR_PYG,
|
|
150
|
+
pivot_position : __LITERAL_PIVOT_POSITIONS__ = "top_left",
|
|
151
|
+
font : pg.font.Font = FONT_ARIAL_32,
|
|
152
|
+
bg_color : None|pg.color.Color = None,
|
|
153
|
+
border_color : pg.color.Color = WHITE_COLOR_PYG,
|
|
154
|
+
border_width : float = 0.0,
|
|
155
|
+
border_radius : int|list[int]|tuple[int,int,int,int] = -1,
|
|
156
|
+
margin : Vector2D = Vector2D.zero(),
|
|
157
|
+
personalized_surface : pg.Surface|None = None
|
|
135
158
|
) -> None:
|
|
159
|
+
|
|
136
160
|
text_box = font.render(text, True, color)
|
|
137
161
|
size = Vector2D(*text_box.get_size()) + margin * 2
|
|
138
162
|
pivotted_position = position - size * __PIVOT_POSITIONS_MULTIPLIER__[pivot_position] + margin
|
e2d-1.4.20/e2D/utils.py
ADDED
|
@@ -0,0 +1,545 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
from typing import Any, Callable, Literal
|
|
3
|
+
import pygame as pg
|
|
4
|
+
from e2D import *
|
|
5
|
+
from e2D.colors import *
|
|
6
|
+
|
|
7
|
+
import math as _mt
|
|
8
|
+
|
|
9
|
+
pg.font.init()
|
|
10
|
+
|
|
11
|
+
__KEY_MODE_TYPES_DICT__ = dict(zip(["pressed", "just_pressed", "just_released"], range(3)))
|
|
12
|
+
__LITERAL_KEY_MODE_TYPES__ = Literal["pressed", "just_pressed", "just_released"]
|
|
13
|
+
|
|
14
|
+
__LITERAL_FONTS__ = Literal['arial', 'arialblack', 'bahnschrift', 'calibri', 'cambria', 'cambriamath', 'candara', 'comicsansms', 'consolas', 'constantia', 'corbel', 'couriernew', 'ebrima', 'franklingothicmedium', 'gabriola', 'gadugi', 'georgia', 'impact', 'inkfree', 'javanesetext', 'leelawadeeui', 'leelawadeeuisemilight', 'lucidaconsole', 'lucidasans', 'malgungothic', 'malgungothicsemilight', 'microsofthimalaya', 'microsoftjhenghei', 'microsoftjhengheiui', 'microsoftnewtailue', 'microsoftphagspa', 'microsoftsansserif', 'microsofttaile', 'microsoftyahei', 'microsoftyaheiui', 'microsoftyibaiti', 'mingliuextb', 'pmingliuextb', 'mingliuhkscsextb', 'mongolianbaiti', 'msgothic', 'msuigothic', 'mspgothic', 'mvboli', 'myanmartext', 'nirmalaui', 'nirmalauisemilight', 'palatinolinotype', 'segoemdl2assets', 'segoeprint', 'segoescript', 'segoeui', 'segoeuiblack', 'segoeuiemoji', 'segoeuihistoric', 'segoeuisemibold', 'segoeuisemilight', 'segoeuisymbol', 'simsun', 'nsimsun', 'simsunextb', 'sitkasmall', 'sitkatext', 'sitkasubheading', 'sitkaheading', 'sitkadisplay', 'sitkabanner', 'sylfaen', 'symbol', 'tahoma', 'timesnewroman', 'trebuchetms', 'verdana', 'webdings', 'wingdings', 'yugothic', 'yugothicuisemibold', 'yugothicui', 'yugothicmedium', 'yugothicuiregular', 'yugothicregular', 'yugothicuisemilight', 'holomdl2assets', 'bizudgothic', 'bizudpgothictruetype', 'bizudminchomedium', 'bizudpminchomediumtruetype', 'meiryo', 'meiryoui', 'msmincho', 'mspmincho', 'uddigikyokashonb', 'uddigikyokashonpb', 'uddigikyokashonkb', 'uddigikyokashonr', 'uddigikyokashonpr', 'uddigikyokashonkr', 'yumincho', 'lcd', 'glassgauge', 'maiandragd', 'maiandragddemi', 'newsgothic', 'quartz', 'kievitoffcpro', 'agencyfbgrassetto', 'agencyfb', 'algerian', 'bookantiquagrassetto', 'bookantiquagrassettocorsivo', 'bookantiquacorsivo', 'arialcorsivo', 'arialrounded', 'baskervilleoldface', 'bauhaus93', 'bell', 'bellgrassetto', 'bellcorsivo', 'bernardcondensed', 'bookantiqua', 'bodonigrassetto', 'bodonigrassettocorsivo', 'bodoniblackcorsivo', 'bodoniblack', 'bodonicondensedgrassetto', 'bodonicondensedgrassettocorsivo', 'bodonicondensedcorsivo', 'bodonicondensed', 'bodonicorsivo', 'bodonipostercompressed', 'bodoni', 'bookmanoldstyle', 'bookmanoldstylegrassetto', 'bookmanoldstylegrassettocorsivo', 'bookmanoldstylecorsivo', 'bradleyhanditc', 'britannic', 'berlinsansfbgrassetto', 'berlinsansfbdemigrassetto', 'berlinsansfb', 'broadway', 'brushscriptcorsivo', 'bookshelfsymbol7', 'californianfbgrassetto', 'californianfbcorsivo', 'californianfb', 'calisto', 'calistograssetto', 'calistograssettocorsivo', 'calistocorsivo', 'castellar', 'centuryschoolbook', 'centaur', 'century', 'chiller', 'colonna', 'cooperblack', 'copperplategothic', 'curlz', 'dubai', 'dubaimedium', 'dubairegular', 'elephant', 'elephantcorsivo', 'engravers', 'erasitc', 'erasdemiitc', 'erasmediumitc', 'felixtitling', 'forte', 'franklingothicbook', 'franklingothicbookcorsivo', 'franklingothicdemi', 'franklingothicdemicond', 'franklingothicdemicorsivo', 'franklingothicheavy', 'franklingothicheavycorsivo', 'franklingothicmediumcond', 'freestylescript', 'frenchscript', 'footlight', 'garamond', 'garamondgrassetto', 'garamondcorsivo', 'gigi', 'gillsansgrassettocorsivo', 'gillsansgrassetto', 'gillsanscondensed', 'gillsanscorsivo', 'gillsansultracondensed', 'gillsansultra', 'gillsans', 'gloucesterextracondensed', 'gillsansextcondensed', 'centurygothic', 'centurygothicgrassetto', 'centurygothicgrassettocorsivo', 'centurygothiccorsivo', 'goudyoldstyle', 'goudyoldstylegrassetto', 'goudyoldstylecorsivo', 'goudystout', 'harlowsolid', 'harrington', 'haettenschweiler', 'hightowertext', 'hightowertextcorsivo', 'imprintshadow', 'informalroman', 'blackadderitc', 'kristenitc', 'jokerman', 'juiceitc', 'kunstlerscript', 'widelatin', 'lucidabright', 'lucidacalligraphy', 'leelawadee', 'leelawadeegrassetto', 'lucidafax', 'lucidafaxdemigrassetto', 'lucidafaxdemigrassettocorsivo', 'lucidafaxcorsivo', 'lucidahandwritingcorsivo', 'lucidasansdemigrassetto', 'lucidasansdemigrassettocorsivo', 'lucidasanscorsivo', 'lucidasanstypewriter', 'lucidasanstypewritergrassetto', 'lucidasanstypewritergrassettooblique', 'lucidasanstypewriteroblique', 'magnetograssetto', 'maturascriptcapitals', 'mistral', 'modernno20', 'microsoftuighurgrassetto', 'microsoftuighur', 'monotypecorsiva', 'extra', 'niagaraengraved', 'niagarasolid', 'ocraextended', 'oldenglishtext', 'onyx', 'msoutlook', 'palacescript', 'papyrus', 'parchment', 'perpetuagrassettocorsivo', 'perpetuagrassetto', 'perpetuacorsivo', 'perpetuatitlinggrassetto', 'perpetuatitlingchiarissimo', 'perpetua', 'playbill', 'poorrichard', 'pristina', 'rage', 'ravie', 'msreferencesansserif', 'msreferencespecialty', 'rockwellcondensedgrassetto', 'rockwellcondensed', 'rockwell', 'rockwellgrassetto', 'rockwellgrassettocorsivo', 'rockwellextra', 'rockwellcorsivo', 'centuryschoolbookgrassetto', 'centuryschoolbookgrassettocorsivo', 'centuryschoolbookcorsivo', 'script', 'showcardgothic', 'snapitc', 'stencil', 'twcengrassettocorsivo', 'twcengrassetto', 'twcencondensedgrassetto', 'twcencondensedextra', 'twcencondensed', 'twcencorsivo', 'twcen', 'tempussansitc', 'vinerhanditc', 'vivaldicorsivo', 'vladimirscript', 'wingdings2', 'wingdings3', 'cascadiacoderegular', 'cascadiamonoregular', 'edwardianscriptitcnormale', 'stoneharbourregular', 'mregular', 'xirodregular', 'minecraft']
|
|
15
|
+
|
|
16
|
+
def NEW_FONT(size, name:__LITERAL_FONTS__="arial", bold:bool=False, italic:bool=False) -> pg.font.Font:
|
|
17
|
+
return pg.font.SysFont(name, size, bold, italic)
|
|
18
|
+
FONT_ARIAL_16 = NEW_FONT(16)
|
|
19
|
+
FONT_ARIAL_32 = NEW_FONT(32)
|
|
20
|
+
FONT_ARIAL_64 = NEW_FONT(64)
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
__LITERAL_PIVOT_POSITIONS__ = Literal["top_left", "top_center", "top_right", "center_left", "center_center", "center_right", "bottom_left", "bottom_center", "bottom_right"]
|
|
24
|
+
__PIVOT_POSITIONS_MULTIPLIER__ = dict(zip(("top_left", "top_center", "top_right", "center_left", "center_center", "center_right", "bottom_left", "bottom_center", "bottom_right"), (Vector2D(x,y) for y in [0, .5, 1] for x in [0, .5, 1])))
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
# INPUT_CELL_ASCII_TYPE = 0
|
|
28
|
+
# INPUT_CELL_ALPHANUM_TYPE = 1
|
|
29
|
+
# INPUT_CELL_ALPHA_TYPE = 2
|
|
30
|
+
# INPUT_CELL_NUM_TYPE = 3
|
|
31
|
+
# LITERAL_INPUT_CELL_TYPES = Literal[0,1,2,3]
|
|
32
|
+
|
|
33
|
+
class Mouse:
|
|
34
|
+
def __init__(self, parent) -> None:
|
|
35
|
+
self.parent = parent
|
|
36
|
+
self.__last_frame_position_count__ = 0
|
|
37
|
+
self.__last_frame_position__ = Vector2D.new_zero()
|
|
38
|
+
self.__last_frame_movement_count__ = 0
|
|
39
|
+
self.__last_frame_movement__ = Vector2D.new_zero()
|
|
40
|
+
|
|
41
|
+
self.__pressed__ : tuple[bool, bool, bool] = (False, False, False)
|
|
42
|
+
self.update()
|
|
43
|
+
|
|
44
|
+
@property
|
|
45
|
+
def position(self) -> Vector2D:
|
|
46
|
+
if self.__last_frame_position_count__ != self.parent.current_frame:
|
|
47
|
+
self.__last_frame_position__ = Vector2D(*pg.mouse.get_pos())
|
|
48
|
+
self.__last_frame_position_count__ = self.parent.current_frame
|
|
49
|
+
return self.__last_frame_position__
|
|
50
|
+
@position.setter
|
|
51
|
+
def position(self, new_position:Vector2D) -> None:
|
|
52
|
+
self.__last_frame_position_count__ = self.parent.current_frame
|
|
53
|
+
self.__last_frame_position__ = new_position
|
|
54
|
+
pg.mouse.set_pos(self.__last_frame_position__())
|
|
55
|
+
|
|
56
|
+
@property
|
|
57
|
+
def last_frame_movement(self) -> Vector2D:
|
|
58
|
+
if self.__last_frame_movement_count__ != self.parent.current_frame:
|
|
59
|
+
self.__last_frame_movement__ = Vector2D(*pg.mouse.get_rel())
|
|
60
|
+
self.__last_frame_movement_count__ = self.parent.current_frame
|
|
61
|
+
return self.__last_frame_movement__
|
|
62
|
+
|
|
63
|
+
def update(self) -> None:
|
|
64
|
+
self.__last_pressed__ = self.__pressed__
|
|
65
|
+
self.__pressed__ = pg.mouse.get_pressed()
|
|
66
|
+
|
|
67
|
+
def get_key(self, button_id:Literal[0,1,2]=0, mode:__LITERAL_KEY_MODE_TYPES__="pressed") -> bool:
|
|
68
|
+
if mode == "pressed":
|
|
69
|
+
return self.__pressed__[button_id]
|
|
70
|
+
elif mode == "just_pressed":
|
|
71
|
+
return self.__pressed__[button_id] and (not self.__last_pressed__[button_id])
|
|
72
|
+
elif mode == "just_released":
|
|
73
|
+
return (not self.__pressed__[button_id]) and self.__last_pressed__[button_id]
|
|
74
|
+
else:
|
|
75
|
+
raise Exception(f"Unknown mode type: {mode}")
|
|
76
|
+
|
|
77
|
+
class Keyboard:
|
|
78
|
+
def __init__(self) -> None:
|
|
79
|
+
self.__pressed__ :pg.key.ScancodeWrapper= pg.key.get_pressed()
|
|
80
|
+
self.update()
|
|
81
|
+
|
|
82
|
+
def update(self) -> None:
|
|
83
|
+
self.__last_pressed__ = self.__pressed__
|
|
84
|
+
self.__pressed__ = pg.key.get_pressed()
|
|
85
|
+
|
|
86
|
+
def get_key(self, scan_code:int, mode:__LITERAL_KEY_MODE_TYPES__="pressed") -> bool:
|
|
87
|
+
if mode == "pressed":
|
|
88
|
+
return self.__pressed__[scan_code]
|
|
89
|
+
elif mode == "just_pressed":
|
|
90
|
+
return self.__pressed__[scan_code] and (not self.__last_pressed__[scan_code])
|
|
91
|
+
elif mode == "just_released":
|
|
92
|
+
return (not self.__pressed__[scan_code]) and self.__last_pressed__[scan_code]
|
|
93
|
+
else:
|
|
94
|
+
raise Exception(f"Unknown mode type: {mode}")
|
|
95
|
+
|
|
96
|
+
class Util:
|
|
97
|
+
def __init__(self) -> None:
|
|
98
|
+
self.rootEnv = None
|
|
99
|
+
self.surface : pg.Surface = pg.SurfaceType
|
|
100
|
+
self.id : int|str
|
|
101
|
+
self.is_hovered :bool= False
|
|
102
|
+
self.hidden :bool= False
|
|
103
|
+
def hide(self) -> None:
|
|
104
|
+
self.hidden = True
|
|
105
|
+
def show(self) -> None:
|
|
106
|
+
self.hidden = False
|
|
107
|
+
def render(self) -> None: pass
|
|
108
|
+
def draw(self) -> None: pass
|
|
109
|
+
def update(self) -> None: pass
|
|
110
|
+
|
|
111
|
+
class InputCell(Util):
|
|
112
|
+
def __init__(self,
|
|
113
|
+
initial_value : str,
|
|
114
|
+
position : Vector2D,
|
|
115
|
+
size : Vector2D,
|
|
116
|
+
prefix : str|None = None,
|
|
117
|
+
text_color : Color|pg.Color = Color.white(),
|
|
118
|
+
bg_color : None|Color|pg.Color = None,
|
|
119
|
+
border_color : Color|pg.Color = Color.white(),
|
|
120
|
+
border_width : float = 0,
|
|
121
|
+
border_radius : int|list[int]|tuple[int,int,int,int] = -1,
|
|
122
|
+
margin : Vector2D = Vector2D.zero(),
|
|
123
|
+
pivot_position : __LITERAL_PIVOT_POSITIONS__ = "center_center",
|
|
124
|
+
font : pg.font.Font = FONT_ARIAL_32,
|
|
125
|
+
personalized_surface : pg.Surface|None = None,
|
|
126
|
+
on_enter_pressed : Callable[[str], Any] = lambda full_text: ...,
|
|
127
|
+
check_when_adding : Callable[[str], str] = lambda new_text: new_text,
|
|
128
|
+
) -> None:
|
|
129
|
+
super().__init__()
|
|
130
|
+
|
|
131
|
+
self.value = initial_value
|
|
132
|
+
|
|
133
|
+
# size = Vector2D(*self.text_box.get_size()) + self.margin * 2
|
|
134
|
+
self.size = size
|
|
135
|
+
self.position = (position - size * __PIVOT_POSITIONS_MULTIPLIER__[pivot_position] + margin)
|
|
136
|
+
|
|
137
|
+
self.prefix = prefix if prefix != None else ""
|
|
138
|
+
|
|
139
|
+
self.font = font
|
|
140
|
+
|
|
141
|
+
self.bg_rect = [0, 0] + size()
|
|
142
|
+
|
|
143
|
+
self.border_radius = [border_radius]*4 if not any(isinstance(border_radius, cls) for cls in {tuple, list}) else border_radius
|
|
144
|
+
self.border_width = border_width
|
|
145
|
+
|
|
146
|
+
self.margin_rect = (margin * -1)() + size()
|
|
147
|
+
|
|
148
|
+
self.on_enter_pressed = on_enter_pressed
|
|
149
|
+
self.check_when_adding = check_when_adding
|
|
150
|
+
|
|
151
|
+
self.update_text()
|
|
152
|
+
|
|
153
|
+
self.surface = personalized_surface
|
|
154
|
+
self.text_surface = pg.Surface(self.size(), pg.SRCALPHA, 32).convert_alpha()
|
|
155
|
+
|
|
156
|
+
self.text_color = text_color
|
|
157
|
+
self.bg_color = bg_color
|
|
158
|
+
self.border_color = border_color
|
|
159
|
+
|
|
160
|
+
@property
|
|
161
|
+
def text_color(self) -> Color:
|
|
162
|
+
return unpygamize_color(self.__text_color__)
|
|
163
|
+
@text_color.setter
|
|
164
|
+
def text_color(self, new_color:Color|pg.Color) -> None:
|
|
165
|
+
self.__text_color__ = pygamize_color(new_color)
|
|
166
|
+
@property
|
|
167
|
+
def bg_color(self) -> Color|None:
|
|
168
|
+
return unpygamize_color(self.__bg_color__) if self.__bg_color__ else None
|
|
169
|
+
@bg_color.setter
|
|
170
|
+
def bg_color(self, new_color:Color|pg.Color|None) -> None:
|
|
171
|
+
self.__bg_color__ = pygamize_color(new_color) if new_color else None
|
|
172
|
+
@property
|
|
173
|
+
def border_color(self) -> Color:
|
|
174
|
+
return unpygamize_color(self.__border_color__)
|
|
175
|
+
@border_color.setter
|
|
176
|
+
def border_color(self, new_color:Color|pg.Color) -> None:
|
|
177
|
+
self.__border_color__ = pygamize_color(new_color)
|
|
178
|
+
|
|
179
|
+
def draw(self) -> None:
|
|
180
|
+
if self.hidden: return
|
|
181
|
+
self.text_surface.fill(TRANSPARENT_COLOR_PYG)
|
|
182
|
+
|
|
183
|
+
if self.__bg_color__ is not None:
|
|
184
|
+
pg.draw.rect(self.text_surface, self.__bg_color__(), self.bg_rect, 0, -1, *self.border_radius)
|
|
185
|
+
|
|
186
|
+
self.text_surface.blit(self.text_box, self.text_position())
|
|
187
|
+
|
|
188
|
+
if self.rootEnv.selected_util != self:
|
|
189
|
+
if self.border_width:
|
|
190
|
+
pg.draw.rect(self.text_surface, self.__border_color__(), self.margin_rect, self.border_width, -1, *self.border_radius)
|
|
191
|
+
else:
|
|
192
|
+
k = 127.5 + 127.5 * _mt.sin(self.rootEnv.runtime_seconds * 10)
|
|
193
|
+
pg.draw.rect(self.text_surface, pg.Color(k, k, k), self.margin_rect, self.border_width if self.border_width else 10, -1, *self.border_radius)
|
|
194
|
+
|
|
195
|
+
self.surface.blit(self.text_surface, self.position())
|
|
196
|
+
|
|
197
|
+
def update(self) -> None:
|
|
198
|
+
if self.hidden: return
|
|
199
|
+
self.is_hovered = self.position.x < self.rootEnv.mouse.position.x < self.position.x + self.size.x and\
|
|
200
|
+
self.position.y < self.rootEnv.mouse.position.y < self.position.y + self.size.y
|
|
201
|
+
|
|
202
|
+
if self.rootEnv.mouse.get_key(0, "just_pressed"):
|
|
203
|
+
if self.is_hovered:
|
|
204
|
+
self.rootEnv.selected_util = self if self.rootEnv.selected_util != self else None
|
|
205
|
+
self.update_text()
|
|
206
|
+
|
|
207
|
+
if self.rootEnv.selected_util == self:
|
|
208
|
+
for event in self.rootEnv.events:
|
|
209
|
+
if event.type == pg.TEXTINPUT:
|
|
210
|
+
self.value += self.check_when_adding(event.text)
|
|
211
|
+
elif event.type == pg.KEYDOWN and event.key == pg.K_BACKSPACE:
|
|
212
|
+
self.value = self.value[:-1]
|
|
213
|
+
if self.rootEnv.keyboard.get_key(pg.K_DELETE):
|
|
214
|
+
self.value = self.value[:-1]
|
|
215
|
+
if self.rootEnv.keyboard.get_key(pg.K_RETURN, "just_pressed"):
|
|
216
|
+
self.on_enter_pressed(self.value)
|
|
217
|
+
if self.rootEnv.keyboard.get_key(pg.K_ESCAPE, "just_pressed"):
|
|
218
|
+
self.rootEnv.selected_util = self if self.rootEnv.selected_util != self else None
|
|
219
|
+
self.update_text()
|
|
220
|
+
|
|
221
|
+
def update_text(self) -> None:
|
|
222
|
+
self.text_box = self.font.render(self.prefix + self.value, True, self.__text_color__())
|
|
223
|
+
if self.rootEnv != None and self.rootEnv.selected_util == self:
|
|
224
|
+
# self.text_position = self.position + self.size * Vector2D(.85, .5) - Vector2D(*self.text_box.get_size()) * Vector2D(1, .5) - self.position
|
|
225
|
+
self.text_position = self.position + self.size * .5 - Vector2D(*self.text_box.get_size()) * Vector2D(.5, .5) - self.position
|
|
226
|
+
else:
|
|
227
|
+
self.text_position = self.position + self.size * .5 - Vector2D(*self.text_box.get_size()) * Vector2D(.5, .5) - self.position
|
|
228
|
+
|
|
229
|
+
class Slider(Util):
|
|
230
|
+
def __init__(self,
|
|
231
|
+
text : str,
|
|
232
|
+
position : Vector2D,
|
|
233
|
+
size : Vector2D,
|
|
234
|
+
min_value : float = 0,
|
|
235
|
+
max_value : float = 100,
|
|
236
|
+
step : float = 1,
|
|
237
|
+
color : Color|pg.Color = Color(200, 200, 200),
|
|
238
|
+
handleColour : Color|pg.Color = Color.white(),
|
|
239
|
+
initial_value : float = 0,
|
|
240
|
+
rounded : bool = True,
|
|
241
|
+
handleRadius : float = 10,
|
|
242
|
+
text_offset : V2 = V2(1.1, .5),
|
|
243
|
+
text_pivot : __LITERAL_PIVOT_POSITIONS__ = "center_center",
|
|
244
|
+
personalized_surface : pg.Surface|None = None,
|
|
245
|
+
) -> None:
|
|
246
|
+
super().__init__()
|
|
247
|
+
|
|
248
|
+
self.text = text
|
|
249
|
+
self.selected = False
|
|
250
|
+
self.min = min_value
|
|
251
|
+
self.max = max_value
|
|
252
|
+
self.step = step
|
|
253
|
+
|
|
254
|
+
self.position = position
|
|
255
|
+
self.size = size
|
|
256
|
+
|
|
257
|
+
self.value = clamp(initial_value, self.min, self.max)
|
|
258
|
+
|
|
259
|
+
self.radius = self.size.y // 2 if rounded else 0
|
|
260
|
+
self.text_offset = text_offset
|
|
261
|
+
self.text_pivot = text_pivot
|
|
262
|
+
|
|
263
|
+
self.handleRadius = handleRadius
|
|
264
|
+
self.surface = personalized_surface
|
|
265
|
+
|
|
266
|
+
self.hidden = False
|
|
267
|
+
|
|
268
|
+
self.color = color
|
|
269
|
+
self.handleColour = handleColour
|
|
270
|
+
|
|
271
|
+
@property
|
|
272
|
+
def color(self) -> Color:
|
|
273
|
+
return unpygamize_color(self.__color__)
|
|
274
|
+
@color.setter
|
|
275
|
+
def color(self, new_color:Color|pg.Color) -> None:
|
|
276
|
+
self.__color__ = pygamize_color(new_color)
|
|
277
|
+
@property
|
|
278
|
+
def handleColour(self) -> Color:
|
|
279
|
+
return unpygamize_color(self.__handleColour__)
|
|
280
|
+
@handleColour.setter
|
|
281
|
+
def handleColour(self, new_color:Color|pg.Color) -> None:
|
|
282
|
+
self.__handleColour__ = pygamize_color(new_color)
|
|
283
|
+
|
|
284
|
+
def draw(self) -> None:
|
|
285
|
+
if self.hidden: return
|
|
286
|
+
pg.draw.rect(self.rootEnv.screen, self.__color__, self.position() + self.size())
|
|
287
|
+
|
|
288
|
+
if self.radius:
|
|
289
|
+
pg.draw.circle(self.rootEnv.screen, self.__color__, (self.position.x, self.position.y + self.size.y // 2), self.radius)
|
|
290
|
+
pg.draw.circle(self.rootEnv.screen, self.__color__, (self.position.x + self.size.x, self.position.y + self.size.y // 2), self.radius)
|
|
291
|
+
|
|
292
|
+
circle = V2(int(self.position.x + (self.value - self.min) / (self.max - self.min) * self.size.x), self.position.y + self.size.y // 2)
|
|
293
|
+
|
|
294
|
+
pg.draw.circle(self.rootEnv.screen, self.__color__, circle(), self.handleRadius * 1.25)
|
|
295
|
+
pg.draw.circle(self.rootEnv.screen, self.__handleColour__, circle(), self.handleRadius)
|
|
296
|
+
self.rootEnv.print(self.text.format(round(self.value, 2)), self.position + self.size * self.text_offset, pivot_position=self.text_pivot)
|
|
297
|
+
|
|
298
|
+
def update(self) -> None:
|
|
299
|
+
if self.hidden: return
|
|
300
|
+
x,y = self.rootEnv.mouse.position
|
|
301
|
+
|
|
302
|
+
if self.rootEnv.mouse.get_key(0, "just_pressed") and self.__contains__(x, y):
|
|
303
|
+
self.rootEnv.selected_util = self
|
|
304
|
+
elif self.rootEnv.mouse.get_key(0, "just_released"):
|
|
305
|
+
self.rootEnv.selected_util = None
|
|
306
|
+
|
|
307
|
+
if self.rootEnv.selected_util == self:
|
|
308
|
+
new_value = (x - self.position.x) / self.size.x * self.max + self.min
|
|
309
|
+
self.value = clamp(new_value, self.min, self.max)
|
|
310
|
+
|
|
311
|
+
def __contains__(self, x, y) -> bool:
|
|
312
|
+
handleX = self.position.x + (self.value - self.min) / (self.max - self.min) * self.size.x
|
|
313
|
+
handleY = self.position.y + self.size.y // 2
|
|
314
|
+
return (handleX - x) ** 2 + (handleY - y) ** 2 <= self.handleRadius ** 2
|
|
315
|
+
|
|
316
|
+
def setValue(self, value) -> None:
|
|
317
|
+
self.value = clamp(value, self.min, self.max)
|
|
318
|
+
|
|
319
|
+
def getValue(self) -> float:
|
|
320
|
+
return self.value
|
|
321
|
+
|
|
322
|
+
class Button(Util):
|
|
323
|
+
def __init__(self,
|
|
324
|
+
text : str,
|
|
325
|
+
position : V2|Vector2D,
|
|
326
|
+
size : V2|Vector2D,
|
|
327
|
+
callback : Callable[[...], None]|Callable[[], None],
|
|
328
|
+
default_color : Color|pg.Color,
|
|
329
|
+
hovered_color : Color|pg.Color,
|
|
330
|
+
border_color : Color|pg.Color,
|
|
331
|
+
text_color : Color|pg.Color = WHITE_COLOR_PYG,
|
|
332
|
+
font : pg.font.Font = FONT_ARIAL_32,
|
|
333
|
+
border_radius : float = 10,
|
|
334
|
+
border_width : float = 10,
|
|
335
|
+
starting_hiddden : bool = False,
|
|
336
|
+
args : list = [],
|
|
337
|
+
activation_mode : __LITERAL_KEY_MODE_TYPES__ = "just_pressed",
|
|
338
|
+
pivot_position : __LITERAL_PIVOT_POSITIONS__ = "top_left",
|
|
339
|
+
personalized_surface : pg.Surface|None = None,
|
|
340
|
+
) -> None:
|
|
341
|
+
super().__init__()
|
|
342
|
+
|
|
343
|
+
self.text = text
|
|
344
|
+
self.font = font
|
|
345
|
+
|
|
346
|
+
self.callback = callback
|
|
347
|
+
|
|
348
|
+
self.border_radius = border_radius
|
|
349
|
+
self.__size__ = size
|
|
350
|
+
self.__border_width__ = border_width
|
|
351
|
+
|
|
352
|
+
self.update_position(position, pivot_position)
|
|
353
|
+
|
|
354
|
+
self.hidden = starting_hiddden
|
|
355
|
+
self.args = args
|
|
356
|
+
|
|
357
|
+
self.activation_mode = activation_mode
|
|
358
|
+
|
|
359
|
+
self.hovered = False
|
|
360
|
+
|
|
361
|
+
self.text_color = text_color
|
|
362
|
+
self.default_color = default_color
|
|
363
|
+
self.border_color = border_color
|
|
364
|
+
self.hovered_color = hovered_color
|
|
365
|
+
|
|
366
|
+
self.surface = personalized_surface
|
|
367
|
+
self.update_surface()
|
|
368
|
+
|
|
369
|
+
def update_position(self, new_position:V2, pivot_position:__LITERAL_PIVOT_POSITIONS__="top_left") -> None:
|
|
370
|
+
self.position = new_position - (self.__size__ + self.border_width * 2) * __PIVOT_POSITIONS_MULTIPLIER__[pivot_position]
|
|
371
|
+
|
|
372
|
+
def update_surface(self, render=False) -> None:
|
|
373
|
+
self.buffer_surface = pg.Surface((self.__size__ + self.__border_width__ * 2)(), pg.SRCALPHA, 32).convert_alpha()
|
|
374
|
+
if render: self.render()
|
|
375
|
+
|
|
376
|
+
@property
|
|
377
|
+
def size(self) -> V2:
|
|
378
|
+
return self.__size__
|
|
379
|
+
@size.setter
|
|
380
|
+
def size(self, new_size:V2|Vector2D) -> None:
|
|
381
|
+
self.__size__ = new_size
|
|
382
|
+
self.update_surface(render=True)
|
|
383
|
+
|
|
384
|
+
@property
|
|
385
|
+
def border_width(self) -> float:
|
|
386
|
+
return self.__border_width__
|
|
387
|
+
@border_width.setter
|
|
388
|
+
def border_width(self, new_width:float) -> None:
|
|
389
|
+
self.__border_width__ = new_width
|
|
390
|
+
self.update_surface(render=True)
|
|
391
|
+
|
|
392
|
+
@property
|
|
393
|
+
def text_color(self) -> Color:
|
|
394
|
+
return unpygamize_color(self.__text_color__)
|
|
395
|
+
@text_color.setter
|
|
396
|
+
def text_color(self, new_color:Color|pg.Color) -> None:
|
|
397
|
+
self.__text_color__ = pygamize_color(new_color)
|
|
398
|
+
@property
|
|
399
|
+
def default_color(self) -> Color:
|
|
400
|
+
return unpygamize_color(self.__default_color__)
|
|
401
|
+
@default_color.setter
|
|
402
|
+
def default_color(self, new_color:Color|pg.Color) -> None:
|
|
403
|
+
self.__default_color__ = pygamize_color(new_color)
|
|
404
|
+
@property
|
|
405
|
+
def border_color(self) -> Color:
|
|
406
|
+
return unpygamize_color(self.__border_color__)
|
|
407
|
+
@border_color.setter
|
|
408
|
+
def border_color(self, new_color:Color|pg.Color) -> None:
|
|
409
|
+
self.__border_color__ = pygamize_color(new_color)
|
|
410
|
+
@property
|
|
411
|
+
def hovered_color(self) -> Color:
|
|
412
|
+
return unpygamize_color(self.__hovered_color__)
|
|
413
|
+
@hovered_color.setter
|
|
414
|
+
def hovered_color(self, new_color:Color|pg.Color) -> None:
|
|
415
|
+
self.__hovered_color__ = pygamize_color(new_color)
|
|
416
|
+
|
|
417
|
+
def render(self) -> None:
|
|
418
|
+
print("rendering button")
|
|
419
|
+
self.buffer_surface.fill(TRANSPARENT_COLOR_PYG)
|
|
420
|
+
|
|
421
|
+
color = self.__hovered_color__ if self.hovered else self.__default_color__
|
|
422
|
+
pg.draw.rect(self.buffer_surface, self.__border_color__, V2.zero()() + (self.size + self.border_width * 2)(), border_radius=self.border_radius)
|
|
423
|
+
pg.draw.rect(self.buffer_surface, color, (V2.zero() + self.border_width)() + self.size(), border_radius=self.border_radius)
|
|
424
|
+
|
|
425
|
+
self.rootEnv.print(self.text, self.border_width + self.size * .5, color=self.__text_color__, font=self.font, pivot_position="center_center", personalized_surface=self.buffer_surface)
|
|
426
|
+
|
|
427
|
+
def draw(self) -> None:
|
|
428
|
+
if self.hidden: return
|
|
429
|
+
self.surface.blit(self.buffer_surface, (self.position)())
|
|
430
|
+
|
|
431
|
+
def update(self) -> None:
|
|
432
|
+
if self.hidden: return
|
|
433
|
+
|
|
434
|
+
old_overed = self.hovered
|
|
435
|
+
self.hovered = \
|
|
436
|
+
self.position.x < self.rootEnv.mouse.position.x < self.position.x + self.size.x and \
|
|
437
|
+
self.position.y < self.rootEnv.mouse.position.y < self.position.y + self.size.y
|
|
438
|
+
if self.hovered != old_overed:
|
|
439
|
+
self.render()
|
|
440
|
+
|
|
441
|
+
if self.hovered and self.rootEnv.mouse.get_key(0, self.activation_mode):
|
|
442
|
+
self.callback(*self.args)
|
|
443
|
+
self.rootEnv.selected_util = self
|
|
444
|
+
self.render()
|
|
445
|
+
elif self.rootEnv.selected_util == self:
|
|
446
|
+
self.rootEnv.selected_util = None
|
|
447
|
+
self.render()
|
|
448
|
+
|
|
449
|
+
class Label(Util):
|
|
450
|
+
def __init__(self,
|
|
451
|
+
text : str,
|
|
452
|
+
position : V2|Vector2D,
|
|
453
|
+
size : V2|Vector2D,
|
|
454
|
+
default_color : Color|pg.Color = TRANSPARENT_COLOR_PYG,
|
|
455
|
+
border_color : Color|pg.Color = WHITE_COLOR_PYG,
|
|
456
|
+
text_color : Color|pg.Color = WHITE_COLOR_PYG,
|
|
457
|
+
font : pg.font.Font = FONT_ARIAL_32,
|
|
458
|
+
border_radius : float = 10,
|
|
459
|
+
border_width : float = 10,
|
|
460
|
+
starting_hiddden : bool = False,
|
|
461
|
+
personalized_surface : pg.Surface|None = None,
|
|
462
|
+
pivot_position : __LITERAL_PIVOT_POSITIONS__ = "top_left",
|
|
463
|
+
) -> None:
|
|
464
|
+
super().__init__()
|
|
465
|
+
|
|
466
|
+
self.__text__ = text
|
|
467
|
+
self.font = font
|
|
468
|
+
|
|
469
|
+
self.border_radius = border_radius
|
|
470
|
+
self.__size__ = size
|
|
471
|
+
self.__border_width__ = border_width
|
|
472
|
+
|
|
473
|
+
self.position = self.update_position(position, pivot_position)
|
|
474
|
+
|
|
475
|
+
self.hidden = starting_hiddden
|
|
476
|
+
|
|
477
|
+
self.text_color = text_color
|
|
478
|
+
self.default_color = default_color
|
|
479
|
+
self.border_color = border_color
|
|
480
|
+
|
|
481
|
+
self.surface = personalized_surface
|
|
482
|
+
self.update_surface()
|
|
483
|
+
|
|
484
|
+
def update_position(self, new_position:V2, pivot_position:__LITERAL_PIVOT_POSITIONS__="top_left") -> None:
|
|
485
|
+
self.position = new_position - (self.__size__ + self.border_width * 2) * __PIVOT_POSITIONS_MULTIPLIER__[pivot_position]
|
|
486
|
+
|
|
487
|
+
def update_surface(self, render=False) -> None:
|
|
488
|
+
self.buffer_surface = pg.Surface((self.__size__ + self.__border_width__ * 2)(), pg.SRCALPHA, 32).convert_alpha()
|
|
489
|
+
if render: self.render()
|
|
490
|
+
|
|
491
|
+
@property
|
|
492
|
+
def text(self) -> str:
|
|
493
|
+
return self.__text__
|
|
494
|
+
@text.setter
|
|
495
|
+
def text(self, new_text:str) -> None:
|
|
496
|
+
self.__text__ = new_text
|
|
497
|
+
self.render()
|
|
498
|
+
|
|
499
|
+
@property
|
|
500
|
+
def size(self) -> V2:
|
|
501
|
+
return self.__size__
|
|
502
|
+
@size.setter
|
|
503
|
+
def size(self, new_size:V2|Vector2D) -> None:
|
|
504
|
+
self.__size__ = new_size
|
|
505
|
+
self.update_surface(render=True)
|
|
506
|
+
|
|
507
|
+
@property
|
|
508
|
+
def border_width(self) -> float:
|
|
509
|
+
return self.__border_width__
|
|
510
|
+
@border_width.setter
|
|
511
|
+
def border_width(self, new_width:float) -> None:
|
|
512
|
+
self.__border_width__ = new_width
|
|
513
|
+
self.update_surface(render=True)
|
|
514
|
+
|
|
515
|
+
@property
|
|
516
|
+
def text_color(self) -> Color:
|
|
517
|
+
return unpygamize_color(self.__text_color__)
|
|
518
|
+
@text_color.setter
|
|
519
|
+
def text_color(self, new_color:Color|pg.Color) -> None:
|
|
520
|
+
self.__text_color__ = pygamize_color(new_color)
|
|
521
|
+
@property
|
|
522
|
+
def default_color(self) -> Color:
|
|
523
|
+
return unpygamize_color(self.__default_color__)
|
|
524
|
+
@default_color.setter
|
|
525
|
+
def default_color(self, new_color:Color|pg.Color) -> None:
|
|
526
|
+
self.__default_color__ = pygamize_color(new_color)
|
|
527
|
+
@property
|
|
528
|
+
def border_color(self) -> Color:
|
|
529
|
+
return unpygamize_color(self.__border_color__)
|
|
530
|
+
@border_color.setter
|
|
531
|
+
def border_color(self, new_color:Color|pg.Color) -> None:
|
|
532
|
+
self.__border_color__ = pygamize_color(new_color)
|
|
533
|
+
|
|
534
|
+
def render(self) -> None:
|
|
535
|
+
print("rendering label")
|
|
536
|
+
self.buffer_surface.fill(TRANSPARENT_COLOR_PYG)
|
|
537
|
+
|
|
538
|
+
pg.draw.rect(self.buffer_surface, self.__border_color__, V2.zero()() + (self.size + self.border_width * 2)(), border_radius=self.border_radius)
|
|
539
|
+
pg.draw.rect(self.buffer_surface, self.__default_color__, (V2.zero() + self.border_width)() + self.size(), border_radius=self.border_radius)
|
|
540
|
+
|
|
541
|
+
self.rootEnv.print(self.text, self.border_width + self.size * .5, color=self.__text_color__, font=self.font, pivot_position="center_center", personalized_surface=self.buffer_surface)
|
|
542
|
+
|
|
543
|
+
def draw(self) -> None:
|
|
544
|
+
if self.hidden: return
|
|
545
|
+
self.surface.blit(self.buffer_surface, (self.position)())
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: e2D
|
|
3
|
-
Version: 1.4.
|
|
3
|
+
Version: 1.4.20
|
|
4
4
|
Summary: Python library for 2D games. Streamlines dev with keyboard/mouse input, vector calculations, color manipulation, and collision detection. Simplify game creation and unleash creativity!
|
|
5
5
|
Home-page: https://github.com/marick-py/e2D
|
|
6
6
|
Author: Riccardo Mariani
|
|
@@ -13,6 +13,7 @@ Description-Content-Type: text/markdown
|
|
|
13
13
|
License-File: LICENSE
|
|
14
14
|
Requires-Dist: numpy
|
|
15
15
|
Requires-Dist: pygame
|
|
16
|
+
Dynamic: license-file
|
|
16
17
|
|
|
17
18
|
# e2D
|
|
18
19
|
## A Python Game Development Library
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[metadata]
|
|
2
2
|
name = e2D
|
|
3
|
-
version = 1.4.
|
|
3
|
+
version = 1.4.20
|
|
4
4
|
author = Riccardo Mariani
|
|
5
5
|
author_email = ricomari2006@gmail.com
|
|
6
6
|
description = Python library for 2D games. Streamlines dev with keyboard/mouse input, vector calculations, color manipulation, and collision detection. Simplify game creation and unleash creativity!
|
e2d-1.4.19/e2D/utils.py
DELETED
|
@@ -1,191 +0,0 @@
|
|
|
1
|
-
from __future__ import annotations
|
|
2
|
-
from typing import Any, Callable, Literal
|
|
3
|
-
import pygame as pg
|
|
4
|
-
from e2D import *
|
|
5
|
-
from e2D.colors import *
|
|
6
|
-
|
|
7
|
-
import math as _mt
|
|
8
|
-
|
|
9
|
-
pg.font.init()
|
|
10
|
-
|
|
11
|
-
__KEY_MODE_TYPES_DICT__ = dict(zip(["pressed", "just_pressed", "just_released"], range(3)))
|
|
12
|
-
__LITERAL_KEY_MODE_TYPES__ = Literal["pressed", "just_pressed", "just_released"]
|
|
13
|
-
|
|
14
|
-
__LITERAL_FONTS__ = Literal['arial', 'arialblack', 'bahnschrift', 'calibri', 'cambria', 'cambriamath', 'candara', 'comicsansms', 'consolas', 'constantia', 'corbel', 'couriernew', 'ebrima', 'franklingothicmedium', 'gabriola', 'gadugi', 'georgia', 'impact', 'inkfree', 'javanesetext', 'leelawadeeui', 'leelawadeeuisemilight', 'lucidaconsole', 'lucidasans', 'malgungothic', 'malgungothicsemilight', 'microsofthimalaya', 'microsoftjhenghei', 'microsoftjhengheiui', 'microsoftnewtailue', 'microsoftphagspa', 'microsoftsansserif', 'microsofttaile', 'microsoftyahei', 'microsoftyaheiui', 'microsoftyibaiti', 'mingliuextb', 'pmingliuextb', 'mingliuhkscsextb', 'mongolianbaiti', 'msgothic', 'msuigothic', 'mspgothic', 'mvboli', 'myanmartext', 'nirmalaui', 'nirmalauisemilight', 'palatinolinotype', 'segoemdl2assets', 'segoeprint', 'segoescript', 'segoeui', 'segoeuiblack', 'segoeuiemoji', 'segoeuihistoric', 'segoeuisemibold', 'segoeuisemilight', 'segoeuisymbol', 'simsun', 'nsimsun', 'simsunextb', 'sitkasmall', 'sitkatext', 'sitkasubheading', 'sitkaheading', 'sitkadisplay', 'sitkabanner', 'sylfaen', 'symbol', 'tahoma', 'timesnewroman', 'trebuchetms', 'verdana', 'webdings', 'wingdings', 'yugothic', 'yugothicuisemibold', 'yugothicui', 'yugothicmedium', 'yugothicuiregular', 'yugothicregular', 'yugothicuisemilight', 'holomdl2assets', 'bizudgothic', 'bizudpgothictruetype', 'bizudminchomedium', 'bizudpminchomediumtruetype', 'meiryo', 'meiryoui', 'msmincho', 'mspmincho', 'uddigikyokashonb', 'uddigikyokashonpb', 'uddigikyokashonkb', 'uddigikyokashonr', 'uddigikyokashonpr', 'uddigikyokashonkr', 'yumincho', 'lcd', 'glassgauge', 'maiandragd', 'maiandragddemi', 'newsgothic', 'quartz', 'kievitoffcpro', 'agencyfbgrassetto', 'agencyfb', 'algerian', 'bookantiquagrassetto', 'bookantiquagrassettocorsivo', 'bookantiquacorsivo', 'arialcorsivo', 'arialrounded', 'baskervilleoldface', 'bauhaus93', 'bell', 'bellgrassetto', 'bellcorsivo', 'bernardcondensed', 'bookantiqua', 'bodonigrassetto', 'bodonigrassettocorsivo', 'bodoniblackcorsivo', 'bodoniblack', 'bodonicondensedgrassetto', 'bodonicondensedgrassettocorsivo', 'bodonicondensedcorsivo', 'bodonicondensed', 'bodonicorsivo', 'bodonipostercompressed', 'bodoni', 'bookmanoldstyle', 'bookmanoldstylegrassetto', 'bookmanoldstylegrassettocorsivo', 'bookmanoldstylecorsivo', 'bradleyhanditc', 'britannic', 'berlinsansfbgrassetto', 'berlinsansfbdemigrassetto', 'berlinsansfb', 'broadway', 'brushscriptcorsivo', 'bookshelfsymbol7', 'californianfbgrassetto', 'californianfbcorsivo', 'californianfb', 'calisto', 'calistograssetto', 'calistograssettocorsivo', 'calistocorsivo', 'castellar', 'centuryschoolbook', 'centaur', 'century', 'chiller', 'colonna', 'cooperblack', 'copperplategothic', 'curlz', 'dubai', 'dubaimedium', 'dubairegular', 'elephant', 'elephantcorsivo', 'engravers', 'erasitc', 'erasdemiitc', 'erasmediumitc', 'felixtitling', 'forte', 'franklingothicbook', 'franklingothicbookcorsivo', 'franklingothicdemi', 'franklingothicdemicond', 'franklingothicdemicorsivo', 'franklingothicheavy', 'franklingothicheavycorsivo', 'franklingothicmediumcond', 'freestylescript', 'frenchscript', 'footlight', 'garamond', 'garamondgrassetto', 'garamondcorsivo', 'gigi', 'gillsansgrassettocorsivo', 'gillsansgrassetto', 'gillsanscondensed', 'gillsanscorsivo', 'gillsansultracondensed', 'gillsansultra', 'gillsans', 'gloucesterextracondensed', 'gillsansextcondensed', 'centurygothic', 'centurygothicgrassetto', 'centurygothicgrassettocorsivo', 'centurygothiccorsivo', 'goudyoldstyle', 'goudyoldstylegrassetto', 'goudyoldstylecorsivo', 'goudystout', 'harlowsolid', 'harrington', 'haettenschweiler', 'hightowertext', 'hightowertextcorsivo', 'imprintshadow', 'informalroman', 'blackadderitc', 'kristenitc', 'jokerman', 'juiceitc', 'kunstlerscript', 'widelatin', 'lucidabright', 'lucidacalligraphy', 'leelawadee', 'leelawadeegrassetto', 'lucidafax', 'lucidafaxdemigrassetto', 'lucidafaxdemigrassettocorsivo', 'lucidafaxcorsivo', 'lucidahandwritingcorsivo', 'lucidasansdemigrassetto', 'lucidasansdemigrassettocorsivo', 'lucidasanscorsivo', 'lucidasanstypewriter', 'lucidasanstypewritergrassetto', 'lucidasanstypewritergrassettooblique', 'lucidasanstypewriteroblique', 'magnetograssetto', 'maturascriptcapitals', 'mistral', 'modernno20', 'microsoftuighurgrassetto', 'microsoftuighur', 'monotypecorsiva', 'extra', 'niagaraengraved', 'niagarasolid', 'ocraextended', 'oldenglishtext', 'onyx', 'msoutlook', 'palacescript', 'papyrus', 'parchment', 'perpetuagrassettocorsivo', 'perpetuagrassetto', 'perpetuacorsivo', 'perpetuatitlinggrassetto', 'perpetuatitlingchiarissimo', 'perpetua', 'playbill', 'poorrichard', 'pristina', 'rage', 'ravie', 'msreferencesansserif', 'msreferencespecialty', 'rockwellcondensedgrassetto', 'rockwellcondensed', 'rockwell', 'rockwellgrassetto', 'rockwellgrassettocorsivo', 'rockwellextra', 'rockwellcorsivo', 'centuryschoolbookgrassetto', 'centuryschoolbookgrassettocorsivo', 'centuryschoolbookcorsivo', 'script', 'showcardgothic', 'snapitc', 'stencil', 'twcengrassettocorsivo', 'twcengrassetto', 'twcencondensedgrassetto', 'twcencondensedextra', 'twcencondensed', 'twcencorsivo', 'twcen', 'tempussansitc', 'vinerhanditc', 'vivaldicorsivo', 'vladimirscript', 'wingdings2', 'wingdings3', 'cascadiacoderegular', 'cascadiamonoregular', 'edwardianscriptitcnormale', 'stoneharbourregular', 'mregular', 'xirodregular', 'minecraft']
|
|
15
|
-
|
|
16
|
-
def NEW_FONT(size, name:__LITERAL_FONTS__="arial", bold:bool=False, italic:bool=False) -> pg.font.Font:
|
|
17
|
-
return pg.font.SysFont(name, size, bold, italic)
|
|
18
|
-
FONT_ARIAL_16 = NEW_FONT(16)
|
|
19
|
-
FONT_ARIAL_32 = NEW_FONT(32)
|
|
20
|
-
FONT_ARIAL_64 = NEW_FONT(64)
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
__LITERAL_PIVOT_POSITIONS__ = Literal["top_left", "top_center", "top_right", "center_left", "center_center", "center_right", "bottom_left", "bottom_center", "bottom_right"]
|
|
24
|
-
__PIVOT_POSITIONS_MULTIPLIER__ = dict(zip(("top_left", "top_center", "top_right", "center_left", "center_center", "center_right", "bottom_left", "bottom_center", "bottom_right"), (Vector2D(x,y) for y in [0, .5, 1] for x in [0, .5, 1])))
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
# INPUT_CELL_ASCII_TYPE = 0
|
|
28
|
-
# INPUT_CELL_ALPHANUM_TYPE = 1
|
|
29
|
-
# INPUT_CELL_ALPHA_TYPE = 2
|
|
30
|
-
# INPUT_CELL_NUM_TYPE = 3
|
|
31
|
-
# LITERAL_INPUT_CELL_TYPES = Literal[0,1,2,3]
|
|
32
|
-
|
|
33
|
-
class Mouse:
|
|
34
|
-
def __init__(self, parent) -> None:
|
|
35
|
-
self.parent = parent
|
|
36
|
-
self.__last_frame_position_count__ = 0
|
|
37
|
-
self.__last_frame_position__ = Vector2D.new_zero()
|
|
38
|
-
self.__last_frame_movement_count__ = 0
|
|
39
|
-
self.__last_frame_movement__ = Vector2D.new_zero()
|
|
40
|
-
|
|
41
|
-
self.__pressed__ : tuple[bool, bool, bool] = (False, False, False)
|
|
42
|
-
self.update()
|
|
43
|
-
|
|
44
|
-
@property
|
|
45
|
-
def position(self) -> Vector2D:
|
|
46
|
-
if self.__last_frame_position_count__ != self.parent.current_frame:
|
|
47
|
-
self.__last_frame_position__ = Vector2D(*pg.mouse.get_pos())
|
|
48
|
-
self.__last_frame_position_count__ = self.parent.current_frame
|
|
49
|
-
return self.__last_frame_position__
|
|
50
|
-
@position.setter
|
|
51
|
-
def position(self, new_position:Vector2D) -> None:
|
|
52
|
-
self.__last_frame_position_count__ = self.parent.current_frame
|
|
53
|
-
self.__last_frame_position__ = new_position
|
|
54
|
-
pg.mouse.set_pos(self.__last_frame_position__())
|
|
55
|
-
|
|
56
|
-
@property
|
|
57
|
-
def last_frame_movement(self) -> Vector2D:
|
|
58
|
-
if self.__last_frame_movement_count__ != self.parent.current_frame:
|
|
59
|
-
self.__last_frame_movement__ = Vector2D(*pg.mouse.get_rel())
|
|
60
|
-
self.__last_frame_movement_count__ = self.parent.current_frame
|
|
61
|
-
return self.__last_frame_movement__
|
|
62
|
-
|
|
63
|
-
def update(self) -> None:
|
|
64
|
-
self.__last_pressed__ = self.__pressed__
|
|
65
|
-
self.__pressed__ = pg.mouse.get_pressed()
|
|
66
|
-
|
|
67
|
-
def get_key(self, button_id:Literal[0,1,2]=0, mode:__LITERAL_KEY_MODE_TYPES__="pressed") -> bool:
|
|
68
|
-
if mode == "pressed":
|
|
69
|
-
return self.__pressed__[button_id]
|
|
70
|
-
elif mode == "just_pressed":
|
|
71
|
-
return self.__pressed__[button_id] and (not self.__last_pressed__[button_id])
|
|
72
|
-
elif mode == "just_released":
|
|
73
|
-
return (not self.__pressed__[button_id]) and self.__last_pressed__[button_id]
|
|
74
|
-
else:
|
|
75
|
-
raise Exception(f"Unknown mode type: {mode}")
|
|
76
|
-
|
|
77
|
-
class Keyboard:
|
|
78
|
-
def __init__(self) -> None:
|
|
79
|
-
self.__pressed__ :pg.key.ScancodeWrapper= pg.key.get_pressed()
|
|
80
|
-
self.update()
|
|
81
|
-
|
|
82
|
-
def update(self) -> None:
|
|
83
|
-
self.__last_pressed__ = self.__pressed__
|
|
84
|
-
self.__pressed__ = pg.key.get_pressed()
|
|
85
|
-
|
|
86
|
-
def get_key(self, scan_code:int, mode:__LITERAL_KEY_MODE_TYPES__="pressed") -> bool:
|
|
87
|
-
if mode == "pressed":
|
|
88
|
-
return self.__pressed__[scan_code]
|
|
89
|
-
elif mode == "just_pressed":
|
|
90
|
-
return self.__pressed__[scan_code] and (not self.__last_pressed__[scan_code])
|
|
91
|
-
elif mode == "just_released":
|
|
92
|
-
return (not self.__pressed__[scan_code]) and self.__last_pressed__[scan_code]
|
|
93
|
-
else:
|
|
94
|
-
raise Exception(f"Unknown mode type: {mode}")
|
|
95
|
-
|
|
96
|
-
class Util:
|
|
97
|
-
def __init__(self) -> None:
|
|
98
|
-
self.rootEnv = None
|
|
99
|
-
self.surface : pg.Surface
|
|
100
|
-
self.id : int|str
|
|
101
|
-
self.is_hovered :bool= False
|
|
102
|
-
def draw(self) -> None: pass
|
|
103
|
-
def update(self) -> None: pass
|
|
104
|
-
|
|
105
|
-
class InputCell(Util):
|
|
106
|
-
def __init__(self,
|
|
107
|
-
id : int|str,
|
|
108
|
-
initial_value : str,
|
|
109
|
-
position : Vector2D,
|
|
110
|
-
size : Vector2D,
|
|
111
|
-
prefix : str|None = None,
|
|
112
|
-
text_color : Color = Color.white(),
|
|
113
|
-
bg_color : None|Color = None,
|
|
114
|
-
border_color : Color = Color.white(),
|
|
115
|
-
border_width : float = 0,
|
|
116
|
-
border_radius : int|list[int]|tuple[int,int,int,int] = -1,
|
|
117
|
-
margin : Vector2D = Vector2D.zero(),
|
|
118
|
-
pivot_position : __LITERAL_PIVOT_POSITIONS__ = "center_center",
|
|
119
|
-
font : pg.font.Font = FONT_ARIAL_32,
|
|
120
|
-
personalized_surface : pg.Surface|None = None,
|
|
121
|
-
on_enter_pressed : Callable[[str], Any] = lambda full_text: ...,
|
|
122
|
-
check_when_adding : Callable[[str], str] = lambda new_text: new_text
|
|
123
|
-
) -> None:
|
|
124
|
-
super().__init__()
|
|
125
|
-
|
|
126
|
-
self.id = id
|
|
127
|
-
self.on_enter_pressed = on_enter_pressed
|
|
128
|
-
self.check_when_adding = check_when_adding
|
|
129
|
-
self.prefix = prefix if prefix != None else ""
|
|
130
|
-
|
|
131
|
-
self.text_color = text_color
|
|
132
|
-
self.font = font
|
|
133
|
-
self.surface = personalized_surface
|
|
134
|
-
self.bg_color = bg_color
|
|
135
|
-
# size = Vector2D(*self.text_box.get_size()) + self.margin * 2
|
|
136
|
-
self.size = size
|
|
137
|
-
self.position = (position - size * __PIVOT_POSITIONS_MULTIPLIER__[pivot_position] + margin)
|
|
138
|
-
self.bg_rect = [0, 0] + size()
|
|
139
|
-
self.margin_rect = (margin * -1)() + size()
|
|
140
|
-
self.border_color = border_color
|
|
141
|
-
self.border_radius = [border_radius]*4 if not any(isinstance(border_radius, cls) for cls in {tuple, list}) else border_radius
|
|
142
|
-
self.border_width = border_width
|
|
143
|
-
|
|
144
|
-
self.value = initial_value
|
|
145
|
-
self.update_text()
|
|
146
|
-
|
|
147
|
-
self.text_surface = pg.Surface(self.size(), pg.SRCALPHA, 32).convert_alpha()
|
|
148
|
-
|
|
149
|
-
def draw(self) -> None:
|
|
150
|
-
self.text_surface.fill((0,0,0,0))
|
|
151
|
-
if self.bg_color != None:
|
|
152
|
-
pg.draw.rect(self.text_surface, self.bg_color(), self.bg_rect, 0, -1, *self.border_radius)
|
|
153
|
-
|
|
154
|
-
self.text_surface.blit(self.text_box, self.text_position())
|
|
155
|
-
|
|
156
|
-
if self.rootEnv.selected_util != self:
|
|
157
|
-
if self.border_width:
|
|
158
|
-
pg.draw.rect(self.text_surface, self.border_color(), self.margin_rect, self.border_width, -1, *self.border_radius)
|
|
159
|
-
else:
|
|
160
|
-
pg.draw.rect(self.text_surface, [127 + 127 * _mt.sin(self.rootEnv.runtime_seconds * 10)]*3, self.margin_rect, self.border_width if self.border_width else 10, -1, *self.border_radius)
|
|
161
|
-
|
|
162
|
-
self.surface.blit(self.text_surface, self.position())
|
|
163
|
-
|
|
164
|
-
def update(self) -> None:
|
|
165
|
-
self.is_hovered = self.position.x < self.rootEnv.mouse.position.x < self.position.x + self.size.x and\
|
|
166
|
-
self.position.y < self.rootEnv.mouse.position.y < self.position.y + self.size.y
|
|
167
|
-
if self.rootEnv.mouse.get_key(0, "just_pressed"):
|
|
168
|
-
if self.is_hovered:
|
|
169
|
-
self.rootEnv.selected_util = self if self.rootEnv.selected_util != self else None
|
|
170
|
-
self.update_text()
|
|
171
|
-
if self.rootEnv.selected_util == self:
|
|
172
|
-
for event in self.rootEnv.events:
|
|
173
|
-
if event.type == pg.TEXTINPUT:
|
|
174
|
-
self.value += self.check_when_adding(event.text)
|
|
175
|
-
elif event.type == pg.KEYDOWN and event.key == pg.K_BACKSPACE:
|
|
176
|
-
self.value = self.value[:-1]
|
|
177
|
-
if self.rootEnv.keyboard.get_key(pg.K_DELETE):
|
|
178
|
-
self.value = self.value[:-1]
|
|
179
|
-
if self.rootEnv.keyboard.get_key(pg.K_RETURN, "just_pressed"):
|
|
180
|
-
self.on_enter_pressed(self.value)
|
|
181
|
-
if self.rootEnv.keyboard.get_key(pg.K_ESCAPE, "just_pressed"):
|
|
182
|
-
self.rootEnv.selected_util = self if self.rootEnv.selected_util != self else None
|
|
183
|
-
self.update_text()
|
|
184
|
-
|
|
185
|
-
def update_text(self) -> None:
|
|
186
|
-
self.text_box = self.font.render(self.prefix + self.value, True, self.text_color())
|
|
187
|
-
if self.rootEnv != None and self.rootEnv.selected_util == self:
|
|
188
|
-
# self.text_position = self.position + self.size * Vector2D(.85, .5) - Vector2D(*self.text_box.get_size()) * Vector2D(1, .5) - self.position
|
|
189
|
-
self.text_position = self.position + self.size * .5 - Vector2D(*self.text_box.get_size()) * Vector2D(.5, .5) - self.position
|
|
190
|
-
else:
|
|
191
|
-
self.text_position = self.position + self.size * .5 - Vector2D(*self.text_box.get_size()) * Vector2D(.5, .5) - self.position
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|