PlayPy 0.2.1__py3-none-any.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.
playpy/state.py ADDED
@@ -0,0 +1,565 @@
1
+ from __future__ import annotations
2
+
3
+ from enum import IntEnum
4
+ from typing import Self, overload, Union
5
+ from . import resources
6
+
7
+ import pygame as pg
8
+
9
+ ColorValue = tuple[int, int, int] | tuple[int, int, int, int]
10
+
11
+ RectValue = Union[tuple[int, int, int, int], tuple[tuple[int, int], tuple[int, int]], pg.Rect, "Rect"]
12
+ FRectValue = Union[tuple[float, float, float, float], tuple[tuple[float, float], tuple[float, float]], "FRect"]
13
+ CoordinateValue = tuple[int, int]
14
+ FCoordinateValue = tuple[float, float]
15
+
16
+ def arg_to_rect(arg: RectValue) -> tuple[int, int, int, int]:
17
+ if isinstance(arg, pg.Rect):
18
+ return (arg.x, arg.y, arg.w, arg.h)
19
+ elif isinstance(arg, Rect):
20
+ return (arg.x, arg.y, arg.w, arg.h)
21
+ elif len(arg) == 2 and isinstance(arg[0], tuple):
22
+ topleft, size = arg
23
+ return (topleft[0], topleft[1], size[0], size[1])
24
+ else:
25
+ return arg # type: ignore
26
+
27
+ def arg_to_frect(arg: FRectValue) -> tuple[float, float, float, float]:
28
+ if isinstance(arg, FRect):
29
+ return (arg.x, arg.y, arg.w, arg.h)
30
+ elif len(arg) == 2 and isinstance(arg[0], tuple):
31
+ topleft, size = arg
32
+ return (topleft[0], topleft[1], size[0], size[1])
33
+ else:
34
+ return arg # type: ignore
35
+
36
+
37
+ class _KeyBase(IntEnum):
38
+ def __str__(self) -> str:
39
+ return f"{type(self).__name__}.{self.name}"
40
+
41
+ @classmethod
42
+ def from_pygame(cls, value: int | Self) -> Self | int:
43
+ if isinstance(value, cls):
44
+ return value
45
+ try:
46
+ return cls(value)
47
+ except ValueError:
48
+ return value
49
+
50
+
51
+ class Key(_KeyBase):
52
+ # These values are defined explicitly so PlayPy's key API stays stable
53
+ # and easy to inspect without depending on runtime enum generation.
54
+ DIGIT_0 = pg.K_0
55
+ DIGIT_1 = pg.K_1
56
+ DIGIT_2 = pg.K_2
57
+ DIGIT_3 = pg.K_3
58
+ DIGIT_4 = pg.K_4
59
+ DIGIT_5 = pg.K_5
60
+ DIGIT_6 = pg.K_6
61
+ DIGIT_7 = pg.K_7
62
+ DIGIT_8 = pg.K_8
63
+ DIGIT_9 = pg.K_9
64
+ AC_BACK = pg.K_AC_BACK
65
+ AMPERSAND = pg.K_AMPERSAND
66
+ ASTERISK = pg.K_ASTERISK
67
+ AT = pg.K_AT
68
+ BACKQUOTE = pg.K_BACKQUOTE
69
+ BACKSLASH = pg.K_BACKSLASH
70
+ BACKSPACE = pg.K_BACKSPACE
71
+ BREAK = pg.K_BREAK
72
+ CAPSLOCK = pg.K_CAPSLOCK
73
+ CARET = pg.K_CARET
74
+ CLEAR = pg.K_CLEAR
75
+ COLON = pg.K_COLON
76
+ COMMA = pg.K_COMMA
77
+ CURRENCYSUBUNIT = pg.K_CURRENCYSUBUNIT
78
+ CURRENCYUNIT = pg.K_CURRENCYUNIT
79
+ DELETE = pg.K_DELETE
80
+ DOLLAR = pg.K_DOLLAR
81
+ DOWN = pg.K_DOWN
82
+ END = pg.K_END
83
+ EQUALS = pg.K_EQUALS
84
+ ESCAPE = pg.K_ESCAPE
85
+ EURO = pg.K_EURO
86
+ EXCLAIM = pg.K_EXCLAIM
87
+ F1 = pg.K_F1
88
+ F10 = pg.K_F10
89
+ F11 = pg.K_F11
90
+ F12 = pg.K_F12
91
+ F13 = pg.K_F13
92
+ F14 = pg.K_F14
93
+ F15 = pg.K_F15
94
+ F2 = pg.K_F2
95
+ F3 = pg.K_F3
96
+ F4 = pg.K_F4
97
+ F5 = pg.K_F5
98
+ F6 = pg.K_F6
99
+ F7 = pg.K_F7
100
+ F8 = pg.K_F8
101
+ F9 = pg.K_F9
102
+ GREATER = pg.K_GREATER
103
+ HASH = pg.K_HASH
104
+ HELP = pg.K_HELP
105
+ HOME = pg.K_HOME
106
+ INSERT = pg.K_INSERT
107
+ KP_0 = pg.K_KP0
108
+ KP_1 = pg.K_KP1
109
+ KP_2 = pg.K_KP2
110
+ KP_3 = pg.K_KP3
111
+ KP_4 = pg.K_KP4
112
+ KP_5 = pg.K_KP5
113
+ KP_6 = pg.K_KP6
114
+ KP_7 = pg.K_KP7
115
+ KP_8 = pg.K_KP8
116
+ KP_9 = pg.K_KP9
117
+ KP_DIVIDE = pg.K_KP_DIVIDE
118
+ KP_ENTER = pg.K_KP_ENTER
119
+ KP_EQUALS = pg.K_KP_EQUALS
120
+ KP_MINUS = pg.K_KP_MINUS
121
+ KP_MULTIPLY = pg.K_KP_MULTIPLY
122
+ KP_PERIOD = pg.K_KP_PERIOD
123
+ KP_PLUS = pg.K_KP_PLUS
124
+ LALT = pg.K_LALT
125
+ LCTRL = pg.K_LCTRL
126
+ LEFT = pg.K_LEFT
127
+ LEFTBRACKET = pg.K_LEFTBRACKET
128
+ LEFTPAREN = pg.K_LEFTPAREN
129
+ LESS = pg.K_LESS
130
+ LGUI = pg.K_LGUI
131
+ LMETA = pg.K_LMETA
132
+ LSHIFT = pg.K_LSHIFT
133
+ LSUPER = pg.K_LSUPER
134
+ MENU = pg.K_MENU
135
+ MINUS = pg.K_MINUS
136
+ MODE = pg.K_MODE
137
+ NUMLOCK = pg.K_NUMLOCK
138
+ NUMLOCKCLEAR = pg.K_NUMLOCKCLEAR
139
+ PAGEDOWN = pg.K_PAGEDOWN
140
+ PAGEUP = pg.K_PAGEUP
141
+ PAUSE = pg.K_PAUSE
142
+ PERCENT = pg.K_PERCENT
143
+ PERIOD = pg.K_PERIOD
144
+ PLUS = pg.K_PLUS
145
+ POWER = pg.K_POWER
146
+ PRINT = pg.K_PRINT
147
+ PRINTSCREEN = pg.K_PRINTSCREEN
148
+ QUESTION = pg.K_QUESTION
149
+ QUOTE = pg.K_QUOTE
150
+ QUOTEDBL = pg.K_QUOTEDBL
151
+ RALT = pg.K_RALT
152
+ RCTRL = pg.K_RCTRL
153
+ RETURN = pg.K_RETURN
154
+ RGUI = pg.K_RGUI
155
+ RIGHT = pg.K_RIGHT
156
+ RIGHTBRACKET = pg.K_RIGHTBRACKET
157
+ RIGHTPAREN = pg.K_RIGHTPAREN
158
+ RMETA = pg.K_RMETA
159
+ RSHIFT = pg.K_RSHIFT
160
+ RSUPER = pg.K_RSUPER
161
+ SCROLLLOCK = pg.K_SCROLLLOCK
162
+ SEMICOLON = pg.K_SEMICOLON
163
+ SLASH = pg.K_SLASH
164
+ SPACE = pg.K_SPACE
165
+ SYSREQ = pg.K_SYSREQ
166
+ TAB = pg.K_TAB
167
+ UNDERSCORE = pg.K_UNDERSCORE
168
+ UNKNOWN = pg.K_UNKNOWN
169
+ UP = pg.K_UP
170
+ A = pg.K_a
171
+ B = pg.K_b
172
+ C = pg.K_c
173
+ D = pg.K_d
174
+ E = pg.K_e
175
+ F = pg.K_f
176
+ G = pg.K_g
177
+ H = pg.K_h
178
+ I = pg.K_i
179
+ J = pg.K_j
180
+ K = pg.K_k
181
+ L = pg.K_l
182
+ M = pg.K_m
183
+ N = pg.K_n
184
+ O = pg.K_o
185
+ P = pg.K_p
186
+ Q = pg.K_q
187
+ R = pg.K_r
188
+ S = pg.K_s
189
+ T = pg.K_t
190
+ U = pg.K_u
191
+ V = pg.K_v
192
+ W = pg.K_w
193
+ X = pg.K_x
194
+ Y = pg.K_y
195
+ Z = pg.K_z
196
+
197
+
198
+ class MouseButton(_KeyBase):
199
+ LEFT = pg.BUTTON_LEFT
200
+ MIDDLE = pg.BUTTON_MIDDLE
201
+ RIGHT = pg.BUTTON_RIGHT
202
+ WHEELUP = pg.BUTTON_WHEELUP
203
+ WHEELDOWN = pg.BUTTON_WHEELDOWN
204
+ X1 = pg.BUTTON_X1
205
+ X2 = pg.BUTTON_X2
206
+
207
+
208
+ KeyValue = Key | int
209
+ MouseButtonValue = MouseButton | int
210
+
211
+
212
+ class InputState:
213
+ def __init__(self):
214
+ self.keys_pressed: set[KeyValue] = set()
215
+ self.keys_pressed_last_frame: set[KeyValue] = set()
216
+ self.mouse_buttons_pressed: set[MouseButtonValue] = set()
217
+ self.mouse_buttons_pressed_last_frame: set[MouseButtonValue] = set()
218
+ self.mouse_pos: tuple[int, int] = (0, 0)
219
+ self.mouse_pos_last_frame: tuple[int, int] = (0, 0)
220
+ self.text_input: list[str] = []
221
+ self.mouse_wheel: int = 0
222
+ self.runtime: float = 0.0
223
+ self.dt: float = 0.0
224
+ self.quit = False
225
+
226
+ def next_frame(self, dt: float):
227
+ self.keys_pressed_last_frame = self.keys_pressed.copy()
228
+ self.mouse_buttons_pressed_last_frame = self.mouse_buttons_pressed.copy()
229
+ self.mouse_pos_last_frame = self.mouse_pos
230
+ self.dt = dt
231
+ self.runtime += dt
232
+
233
+ @property
234
+ def key_downs(self) -> set[KeyValue]:
235
+ return self.keys_pressed - self.keys_pressed_last_frame
236
+
237
+ @property
238
+ def key_ups(self) -> set[KeyValue]:
239
+ return self.keys_pressed_last_frame - self.keys_pressed
240
+
241
+ @property
242
+ def mouse_downs(self) -> set[int]:
243
+ return self.mouse_buttons_pressed - self.mouse_buttons_pressed_last_frame
244
+
245
+ @property
246
+ def mouse_ups(self) -> set[int]:
247
+ return self.mouse_buttons_pressed_last_frame - self.mouse_buttons_pressed
248
+
249
+ @property
250
+ def mouse_delta(self) -> tuple[int, int]:
251
+ return (self.mouse_pos[0] - self.mouse_pos_last_frame[0], self.mouse_pos[1] - self.mouse_pos_last_frame[1])
252
+
253
+ def key_held(self, key: KeyValue) -> bool: return key in self.keys_pressed
254
+ def key_up(self, key: KeyValue) -> bool: return key in self.key_ups
255
+ def key_down(self, key: KeyValue) -> bool: return key in self.key_downs
256
+
257
+ def mousebutton_held(self, mousebutton: MouseButtonValue) -> bool: return mousebutton in self.mouse_buttons_pressed
258
+ def mousebutton_up(self, mousebutton: MouseButtonValue) -> bool: return mousebutton in self.mouse_ups
259
+ def mousebutton_down(self, mousebutton: MouseButtonValue) -> bool: return mousebutton in self.mouse_downs
260
+
261
+ class FRect:
262
+ @overload
263
+ def __init__(self, x: float, y: float, w: float, h: float, /) -> None: ...
264
+
265
+ @overload
266
+ def __init__(self, topleft: FCoordinateValue, size: FCoordinateValue, /) -> None: ...
267
+
268
+ @overload
269
+ def __init__(self, rect: FRectValue, /) -> None: ...
270
+
271
+ def __init__(self, *args):
272
+ if not (1 <= len(args) <= 4):
273
+ resources.log(resources.Severity.ERROR, resources.InvalidValue, "FRect constructor takes 1 to 4 arguments")
274
+ arg1 = args[0]
275
+ arg2 = args[1] if len(args) > 1 else None
276
+ arg3 = args[2] if len(args) > 2 else None
277
+ arg4 = args[3] if len(args) > 3 else None
278
+ if isinstance(arg1, (int, float)) and isinstance(arg2, (int, float)) and isinstance(arg3, (int, float)) and isinstance(arg4, (int, float)):
279
+ x, y, w, h = float(arg1), float(arg2), float(arg3), float(arg4)
280
+ elif isinstance(arg1, tuple) and len(arg1) == 2:
281
+ val1, val2 = arg1
282
+ if isinstance(val1, (int, float)) and isinstance(val2, (int, float)) and isinstance(arg2, tuple):
283
+ x, y = float(val1), float(val2)
284
+ w, h = float(arg2[0]), float(arg2[1])
285
+ elif isinstance(val1, tuple) and isinstance(val2, tuple) and len(val1) == 2 and len(val2) == 2 and arg2 is None:
286
+ topleft, size = val1, val2
287
+ x, y = float(topleft[0]), float(topleft[1])
288
+ w, h = float(size[0]), float(size[1])
289
+ else:
290
+ resources.log(resources.Severity.ERROR, resources.InvalidValue, "Invalid arguments for FRect constructor")
291
+ elif isinstance(arg1, pg.Rect) and arg2 is None and arg3 is None and arg4 is None:
292
+ x, y, w, h = float(arg1.x), float(arg1.y), float(arg1.w), float(arg1.h)
293
+ else:
294
+ resources.log(resources.Severity.ERROR, resources.InvalidValue, "Invalid arguments for FRect constructor")
295
+ self._x = x
296
+ self._y = y
297
+ self._w = w
298
+ self._h = h
299
+
300
+ def tuple(self) -> tuple[float, float, float, float]:
301
+ return (self._x, self._y, self._w, self._h)
302
+
303
+ @property
304
+ def x(self):
305
+ return self._x
306
+
307
+ @x.setter
308
+ def x(self, new: float):
309
+ self._x = new
310
+
311
+ @property
312
+ def y(self):
313
+ return self._y
314
+
315
+ @y.setter
316
+ def y(self, new: float):
317
+ self._y = new
318
+
319
+ @property
320
+ def w(self):
321
+ return self._w
322
+
323
+ @w.setter
324
+ def w(self, new: float):
325
+ self._w = new
326
+
327
+ @property
328
+ def h(self):
329
+ return self._h
330
+
331
+ @h.setter
332
+ def h(self, new: float):
333
+ self._h = new
334
+
335
+ left = x
336
+ top = y
337
+
338
+ @property
339
+ def right(self) -> float:
340
+ return self._x + self._w
341
+
342
+ @right.setter
343
+ def right(self, new: float):
344
+ self._x = new - self._w
345
+
346
+ @property
347
+ def bottom(self) -> float:
348
+ return self._y + self._h
349
+
350
+ @bottom.setter
351
+ def bottom(self, new: float):
352
+ self._y = new - self._h
353
+
354
+ @property
355
+ def topleft(self):
356
+ return (self.x, self.y)
357
+
358
+ @topleft.setter
359
+ def topleft(self, new: tuple[float, float]):
360
+ self.x, self.y = new
361
+
362
+ @property
363
+ def bottomleft(self):
364
+ return (self.x, self.bottom)
365
+
366
+ @bottomleft.setter
367
+ def bottomleft(self, new: tuple[float, float]):
368
+ self.x, self.bottom = new
369
+
370
+ @property
371
+ def topright(self):
372
+ return (self.right, self.y)
373
+
374
+ @topright.setter
375
+ def topright(self, new: tuple[float, float]):
376
+ self.right, self.y = new
377
+
378
+ @property
379
+ def bottomright(self):
380
+ return (self.right, self.bottom)
381
+
382
+ @bottomright.setter
383
+ def bottomright(self, new: tuple[float, float]):
384
+ self.right, self.bottom = new
385
+
386
+ @property
387
+ def center(self):
388
+ return (self.x + self.w / 2, self.y + self.h / 2)
389
+
390
+ @center.setter
391
+ def center(self, new: tuple[float, float]):
392
+ cx, cy = new
393
+ self.x = cx - self.w / 2
394
+ self.y = cy - self.h / 2
395
+
396
+ def copy(self):
397
+ return FRect(self.x, self.y, self.w, self.h)
398
+
399
+
400
+ class Rect:
401
+ @overload
402
+ def __init__(self, x: int, y: int, w: int, h: int, /) -> None: ...
403
+
404
+ @overload
405
+ def __init__(self, topleft: CoordinateValue, size: CoordinateValue, /) -> None: ...
406
+
407
+ @overload
408
+ def __init__(self, rect: RectValue, /) -> None: ...
409
+
410
+ def __init__(self, *args):
411
+ if not (1 <= len(args) <= 4):
412
+ resources.log(resources.Severity.ERROR, resources.InvalidValue, "Rect constructor takes 1 to 4 arguments")
413
+ arg1 = args[0]
414
+ arg2 = args[1] if len(args) > 1 else None
415
+ arg3 = args[2] if len(args) > 2 else None
416
+ arg4 = args[3] if len(args) > 3 else None
417
+ if isinstance(arg1, int) and isinstance(arg2, int) and isinstance(arg3, int) and isinstance(arg4, int):
418
+ x, y, w, h = arg1, arg2, arg3, arg4
419
+ elif isinstance(arg1, tuple) and len(arg1) == 2:
420
+ val1, val2 = arg1
421
+ if isinstance(val1, int) and isinstance(val2, int) and isinstance(arg2, tuple):
422
+ x, y = val1, val2
423
+ w, h = arg2
424
+ elif isinstance(val1, tuple) and isinstance(val2, tuple) and len(val1) == 2 and len(val2) == 2 and arg2 is None:
425
+ topleft, size = val1, val2
426
+ x, y = topleft
427
+ w, h = size
428
+ else:
429
+ resources.log(resources.Severity.ERROR, resources.InvalidValue, "Invalid arguments for Rect constructor")
430
+ elif isinstance(arg1, pg.Rect) and arg2 is None and arg3 is None and arg4 is None:
431
+ x, y, w, h = arg1.x, arg1.y, arg1.w, arg1.h
432
+ else:
433
+ resources.log(resources.Severity.ERROR, resources.InvalidValue, "Invalid arguments for Rect constructor")
434
+ self._x = x
435
+ self._y = y
436
+ self._w = w
437
+ self._h = h
438
+ self._rect = pg.Rect(x, y, w, h)
439
+
440
+ def tuple(self) -> tuple[int, int, int, int]:
441
+ return (self._x, self._y, self._w, self._h)
442
+
443
+ @property
444
+ def x(self):
445
+ return self._x
446
+
447
+ @x.setter
448
+ def x(self, new: int):
449
+ self._x = new
450
+ self._rect.x = new
451
+
452
+ @property
453
+ def y(self):
454
+ return self._y
455
+
456
+ @y.setter
457
+ def y(self, new: int):
458
+ self._y = new
459
+ self._rect.y = new
460
+
461
+ @property
462
+ def w(self):
463
+ return self._w
464
+
465
+ @w.setter
466
+ def w(self, new: int):
467
+ self._w = new
468
+ self._rect.w = new
469
+
470
+ @property
471
+ def h(self):
472
+ return self._h
473
+
474
+ @h.setter
475
+ def h(self, new: int):
476
+ self._h = new
477
+ self._rect.h = new
478
+
479
+ left = x
480
+ top = y
481
+
482
+ @property
483
+ def right(self) -> int:
484
+ return self._x + self._w
485
+
486
+ @right.setter
487
+ def right(self, new: int):
488
+ self._x = new - self._w
489
+ self._rect.right = new
490
+
491
+ @property
492
+ def bottom(self) -> int:
493
+ return self._y + self._h
494
+
495
+ @bottom.setter
496
+ def bottom(self, new: int):
497
+ self._y = new - self._h
498
+ self._rect.bottom = new
499
+
500
+ @property
501
+ def topleft(self):
502
+ return (self.x, self.y)
503
+
504
+ @topleft.setter
505
+ def topleft(self, new: tuple[int, int]):
506
+ self.x, self.y = new
507
+
508
+ @property
509
+ def bottomleft(self):
510
+ return (self.x, self.bottom)
511
+
512
+ @bottomleft.setter
513
+ def bottomleft(self, new: tuple[int, int]):
514
+ self.x, self.bottom = new
515
+
516
+ @property
517
+ def topright(self):
518
+ return (self.right, self.y)
519
+
520
+ @topright.setter
521
+ def topright(self, new: tuple[int, int]):
522
+ self.right, self.y = new
523
+
524
+ @property
525
+ def bottomright(self):
526
+ return (self.right, self.bottom)
527
+
528
+ @bottomright.setter
529
+ def bottomright(self, new: tuple[int, int]):
530
+ self.right, self.bottom = new
531
+
532
+ @property
533
+ def center(self):
534
+ return (self.x + self.w // 2, self.y + self.h // 2)
535
+
536
+ @center.setter
537
+ def center(self, new: tuple[int, int]):
538
+ cx, cy = new
539
+ self.x = cx - self.w // 2
540
+ self.y = cy - self.h // 2
541
+
542
+ def copy(self):
543
+ return Rect(self.x, self.y, self.w, self.h)
544
+
545
+ def empty_rect():
546
+ return Rect(0, 0, 0, 0)
547
+
548
+ def empty_frect():
549
+ return FRect(0, 0, 0, 0)
550
+
551
+
552
+ __all__ = [
553
+ "ColorValue",
554
+ "RectValue",
555
+ "FRectValue",
556
+ "CoordinateValue",
557
+ "FCoordinateValue",
558
+ "Key",
559
+ "MouseButton",
560
+ "InputState",
561
+ "FRect",
562
+ "Rect",
563
+ "empty_rect",
564
+ "empty_frect"
565
+ ]