e2D 1.4.20__tar.gz → 1.4.22__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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: e2D
3
- Version: 1.4.20
3
+ Version: 1.4.22
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
@@ -35,6 +35,22 @@ class Vector2D:
35
35
  @angle.setter
36
36
  def angle(self, new_angle) -> None:
37
37
  self.rotate(new_angle - self.angle)
38
+
39
+ @property
40
+ def aspect_x(self) -> float:
41
+ return self.x / self.y if self.y != 0 else 0
42
+
43
+ @aspect_x.setter
44
+ def aspect_x(self, new_aspect) -> None:
45
+ self.x = self.y * new_aspect
46
+
47
+ @property
48
+ def aspect_y(self) -> float:
49
+ return self.y / self.x if self.x != 0 else 0
50
+
51
+ @aspect_y.setter
52
+ def aspect_y(self, new_aspect) -> None:
53
+ self.y = self.x * new_aspect
38
54
 
39
55
  @property
40
56
  def copy(self) -> "Vector2D":
@@ -52,7 +68,7 @@ class Vector2D:
52
68
  self.y = clamp(self.y, min_val.y, max_val.y)
53
69
 
54
70
  @property
55
- def normalize(self) -> "Vector2D":
71
+ def normalized(self) -> "Vector2D":
56
72
  if (mag:=self.length) == 0:
57
73
  return self.copy
58
74
  return Vector2D(self.x / mag, self.y / mag)
@@ -60,11 +76,31 @@ class Vector2D:
60
76
  @property
61
77
  def length(self) -> float:
62
78
  return (self.x ** 2 + self.y ** 2) ** .5
63
-
79
+
80
+ @length.setter
81
+ def length(self, new_length: float) -> None:
82
+ current_length = self.length
83
+ if current_length == 0:
84
+ self.x = new_length
85
+ self.y = 0
86
+ else:
87
+ self.x *= new_length / current_length
88
+ self.y *= new_length / current_length
89
+
64
90
  @property
65
91
  def length_sqrd(self) -> float:
66
92
  return self.x ** 2 + self.y ** 2
67
-
93
+
94
+ @length_sqrd.setter
95
+ def length_sqrd(self, new_length_sqrd: float) -> None:
96
+ current_length = self.length
97
+ if current_length == 0:
98
+ self.x = _mt.sqrt(new_length_sqrd)
99
+ self.y = 0
100
+ else:
101
+ self.x *= _mt.sqrt(new_length_sqrd) / current_length
102
+ self.y *= _mt.sqrt(new_length_sqrd) / current_length
103
+
68
104
  @property
69
105
  def inverse(self) -> "Vector2D":
70
106
  return self.mult(-1)
@@ -119,6 +155,13 @@ class Vector2D:
119
155
  def complex_to_cartesian(cls, complex_n) -> "Vector2D":
120
156
  return cls(complex_n.real, complex_n.imag)
121
157
 
158
+ def cartesian_to_linear(self, size) -> int:
159
+ return int(self.x + self.y * size)
160
+
161
+ @classmethod
162
+ def linear_to_cartesian(cls, linear, size) -> "Vector2D":
163
+ return cls(linear % size, linear // size)
164
+
122
165
  def lerp(self, other, t=.1) -> "Vector2D":
123
166
  return Vector2D(self.x + (other.x - self.x) * t, self.y + (other.y - self.y) * t)
124
167
 
@@ -495,10 +538,10 @@ V2down_right = Vector2D(1, -1)
495
538
  V2up_left = Vector2D(-1, 1)
496
539
  V2down_left = Vector2D(-1, -1)
497
540
 
498
- V2up_right_norm = V2up_right.normalize
499
- V2down_right_norm = V2down_right.normalize
500
- V2up_left_norm = V2up_left.normalize
501
- V2down_left_norm = V2down_left.normalize
541
+ V2up_right_norm = V2up_right.normalized
542
+ V2down_right_norm = V2down_right.normalized
543
+ V2up_left_norm = V2up_left.normalized
544
+ V2down_left_norm = V2down_left.normalized
502
545
 
503
546
  VECTORS_4_DIRECTIONS = (V2right, V2down, V2left, V2up)
504
547
  VECTORS_4_SEMIDIRECTIONS = (V2down_right, V2down_left, V2up_left, V2up_right)
@@ -141,10 +141,59 @@ class Vector2D:
141
141
  ...
142
142
 
143
143
  @property
144
- def angle(self:"Vector2D") -> int|float: ...
144
+ def angle(self:"Vector2D") -> int|float:
145
+ """
146
+ # Vector Angle
147
+ ## Returns:
148
+ float: The angle (in radians) of the vector from the positive x-axis.
149
+ ## Example:
150
+ v = Vector2D(1, 1)
151
+ angle = v.angle
152
+ print(angle) # Output: 0.7853981633974483
153
+ ## Explanation:
154
+ This property calculates the angle of the vector from the positive x-axis using the `atan2` function.
155
+ """
156
+ ...
145
157
 
146
158
  @angle.setter
147
- def angle(self:"Vector2D", argv) -> None: ...
159
+ def angle(self:"Vector2D", argv) -> None:
160
+ ...
161
+
162
+ @property
163
+ def aspect_x(self: "Vector2D") -> float:
164
+ """
165
+ # Aspect Ratio (X over Y)
166
+ ## Returns:
167
+ float: The aspect ratio of the vector, calculated as the x component divided by the y component. Returns 0 if the y component is zero.
168
+ ## Example:
169
+ v = Vector2D(4, 2)
170
+ aspect = v.aspect_x
171
+ print(aspect) # Output: 2.0
172
+ ## Explanation:
173
+ This property computes the ratio of the x component to the y component of the vector. If the y component is zero, it returns 0 to avoid division by zero.
174
+ """
175
+ ...
176
+
177
+ @aspect_x.setter
178
+ def aspect_x(self: "Vector2D", new_aspect) -> None: ...
179
+
180
+ @property
181
+ def aspect_y(self: "Vector2D") -> float:
182
+ """
183
+ # Aspect Ratio (Y over X)
184
+ ## Returns:
185
+ float: The aspect ratio of the vector, calculated as the y component divided by the x component. Returns 0 if the x component is zero.
186
+ ## Example:
187
+ v = Vector2D(2, 4)
188
+ aspect = v.aspect_y
189
+ print(aspect) # Output: 2.0
190
+ ## Explanation:
191
+ This property computes the ratio of the y component to the x component of the vector. If the x component is zero, it returns 0 to avoid division by zero.
192
+ """
193
+ ...
194
+
195
+ @aspect_y.setter
196
+ def aspect_y(self: "Vector2D", new_aspect) -> None: ...
148
197
 
149
198
  @property
150
199
  def copy(self:"Vector2D") -> "Vector2D":
@@ -261,7 +310,7 @@ class Vector2D:
261
310
  ...
262
311
 
263
312
  @property
264
- def normalize(self:"Vector2D") -> "Vector2D":
313
+ def normalized(self:"Vector2D") -> "Vector2D":
265
314
  """
266
315
  # Vector Normalization
267
316
 
@@ -273,7 +322,7 @@ class Vector2D:
273
322
 
274
323
  ## Example:
275
324
  v = Vector2D(3, 4)
276
- normalized_v = v.normalize() # Normalize the vector (3, 4)
325
+ normalized_v = v.normalized() # Normalize the vector (3, 4)
277
326
  print(normalized_v) # Output: (0.6, 0.8)
278
327
 
279
328
  ## Explanation:
@@ -293,23 +342,123 @@ class Vector2D:
293
342
 
294
343
  @property
295
344
  def length(self:"Vector2D") -> float:
345
+ """
346
+ # Vector Length
347
+
348
+ ## Returns:
349
+ float: The length (magnitude) of the vector.
350
+
351
+ ## Example:
352
+ v = Vector2D(3, 4)
353
+ length = v.length
354
+ print(length) # Output: 5.0
355
+
356
+ ## Explanation:
357
+ This property calculates the length (magnitude) of the vector using the Pythagorean theorem.
358
+ """
296
359
  ...
297
360
 
298
361
  @property
299
362
  def length_sqrd(self:"Vector2D") -> float:
363
+ """
364
+ # Vector Length Squared
365
+
366
+ ## Returns:
367
+ float: The squared length (magnitude) of the vector.
368
+
369
+ ## Example:
370
+ v = Vector2D(3, 4)
371
+ length_sqrd = v.length_sqrd
372
+ print(length_sqrd) # Output: 25
373
+
374
+ ## Explanation:
375
+ This property calculates the squared length (magnitude) of the vector.
376
+ It is more efficient than calculating the actual length, as it avoids the
377
+ square root calculation.
378
+ """
300
379
  ...
301
380
 
302
381
  @property
303
382
  def inverse(self:"Vector2D") -> "Vector2D":
383
+ """
384
+ # Vector Inversion
385
+
386
+ ## Returns:
387
+ Vector2D: A new vector with inverted components.
388
+
389
+ ## Example:
390
+ v = Vector2D(3, 4)
391
+ inverted_v = v.inverse()
392
+ print(inverted_v) # Output: (-3, -4)
393
+
394
+ ## Explanation:
395
+ This method calculates the inverted version of the current vector, which means a new vector with the same magnitude
396
+ but opposite direction.
397
+
398
+ The inverted vector is obtained by negating each component of the current vector.
399
+
400
+ The resulting inverted vector is returned.
401
+ """
304
402
  ...
305
403
 
306
404
  def floor(self:"Vector2D", n:"int|float|Vector2D"=1) -> "Vector2D":
405
+ """
406
+ # Round the Vector2D components down to the nearest integer or specified decimal place.
407
+
408
+ ## Parameters:
409
+ n (int|float|Vector2D, optional): The decimal place to round down to. Default is 1.
410
+
411
+ ## Returns:
412
+ Vector2D: A new vector with rounded-down components.
413
+
414
+ ## Example:
415
+ v = Vector2D(3.14159, 2.71828)
416
+ rounded_v = v.floor(2)
417
+ print(rounded_v) # Output: (3.14, 2.71)
418
+
419
+ ## Explanation:
420
+ This method rounds each component of the vector down to the nearest integer or specified decimal place.
421
+ """
307
422
  ...
308
423
 
309
424
  def ceil(self:"Vector2D", n:"int|float|Vector2D"=1) -> "Vector2D":
425
+ """
426
+ # Round the Vector2D components up to the nearest integer or specified decimal place.
427
+
428
+ ## Parameters:
429
+ n (int|float|Vector2D, optional): The decimal place to round up to. Default is 1.
430
+
431
+ ## Returns:
432
+ Vector2D: A new vector with rounded-up components.
433
+
434
+ ## Example:
435
+ v = Vector2D(3.14159, 2.71828)
436
+ rounded_v = v.ceil(2)
437
+ print(rounded_v) # Output: (3.15, 2.72)
438
+
439
+ ## Explanation:
440
+ This method rounds each component of the vector up to the nearest integer or specified decimal place.
441
+ """
310
442
  ...
311
443
 
312
444
  def round(self:"Vector2D", n:"int|float|Vector2D"=1) -> "Vector2D":
445
+ """
446
+ # Round the Vector2D components to the nearest integer or specified decimal place.
447
+
448
+ ## Parameters:
449
+ n (int|float|Vector2D, optional): The decimal place to round to. Default is 1.
450
+
451
+ ## Returns:
452
+ Vector2D: A new vector with rounded components.
453
+
454
+ ## Example:
455
+ v = Vector2D(3.14159, 2.71828)
456
+ rounded_v = v.round(2)
457
+ print(rounded_v) # Output: (3.14, 2.72)
458
+
459
+ ## Explanation:
460
+ This method rounds each component of the vector to the nearest integer or specified decimal place.
461
+ """
313
462
  ...
314
463
 
315
464
  @classmethod
@@ -500,7 +649,65 @@ class Vector2D:
500
649
  def cartesian_to_complex(self:"Vector2D") -> complex: ...
501
650
 
502
651
  @classmethod
503
- def complex_to_cartesian(cls, complex_n: complex) -> "Vector2D": ...
652
+ def complex_to_cartesian(cls, complex_n: complex) -> "Vector2D":
653
+ """
654
+ # Convert a Complex Number to Cartesian Coordinates
655
+
656
+ ## Parameters:
657
+ complex_n (complex): The complex number to convert.
658
+
659
+ ## Returns:
660
+ Vector2D: The corresponding (x, y) coordinates as a Vector2D.
661
+
662
+ ## Example:
663
+ v = Vector2D.complex_to_cartesian(3 + 4j) # v = Vector2D(3, 4)
664
+
665
+ ## Explanation:
666
+ This class method converts a complex number (a + bi) to Cartesian coordinates (x, y).
667
+ The real part 'a' becomes the x-coordinate, and the imaginary part 'b' becomes the y-coordinate.
668
+ """
669
+ ...
670
+
671
+ def cartesian_to_linear(self:"Vector2D", size:int|float) -> int:
672
+ """
673
+ # Convert 2D Cartesian coordinates to a linear index.
674
+
675
+ ## Parameters:
676
+ size (int|float): The width of the grid (number of columns).
677
+
678
+ ## Returns:
679
+ int: The linear index corresponding to the (x, y) coordinates.
680
+
681
+ ## Example:
682
+ v = Vector2D(3, 2)
683
+ idx = v.cartesian_to_linear(5) # idx = 3 + 2*5 = 13
684
+
685
+ ## Explanation:
686
+ This method converts the (x, y) coordinates of the vector to a single linear index,
687
+ assuming row-major order in a 2D grid of the given width.
688
+ """
689
+ ...
690
+
691
+ @classmethod
692
+ def linear_to_cartesian(cls, linear:int, size:int|float) -> "Vector2D":
693
+ """
694
+ # Convert a linear index to 2D Cartesian coordinates.
695
+
696
+ ## Parameters:
697
+ linear (int): The linear index.
698
+ size (int|float): The width of the grid (number of columns).
699
+
700
+ ## Returns:
701
+ Vector2D: The corresponding (x, y) coordinates as a Vector2D.
702
+
703
+ ## Example:
704
+ v = Vector2D.linear_to_cartesian(13, 5) # v = Vector2D(3, 2)
705
+
706
+ ## Explanation:
707
+ This class method converts a linear index to (x, y) coordinates,
708
+ assuming row-major order in a 2D grid of the given width.
709
+ """
710
+ ...
504
711
 
505
712
  def lerp(self:"Vector2D", other:"int|float|Vector2D|list|tuple", t:float=.1) -> "Vector2D":
506
713
  """
@@ -1095,4 +1302,37 @@ def distance_line_point(line_point_a:Vector2D, line_point_b:Vector2D, point_c:Ve
1095
1302
  ...
1096
1303
 
1097
1304
  def optimize_value_string(value: int|float, precision: int) -> str:
1305
+ """
1306
+ # Optimize the string representation of a numeric value based on its magnitude and the specified precision.
1307
+
1308
+ ## Parameters:
1309
+ value (int | float): The numeric value to be formatted.
1310
+ precision (int): The number of decimal places or significant digits to use in the formatted string.
1311
+
1312
+ ## Returns:
1313
+ str: The optimized string representation of the value.
1314
+
1315
+ ## Example:
1316
+ value = 0.000012345
1317
+ precision = 3
1318
+ result = optimize_value_string(value, precision)
1319
+ print(result)
1320
+ # Output: '1.235e-05'
1321
+
1322
+ value = 123.456789
1323
+ precision = 2
1324
+ result = optimize_value_string(value, precision)
1325
+ print(result)
1326
+ # Output: '123.46'
1327
+
1328
+ ## Explanation:
1329
+ The function formats the input value as a string, choosing between fixed-point and scientific notation
1330
+ based on the magnitude of the value relative to the specified precision:
1331
+ - If the absolute value is very small (less than 1 divided by 10 to the power of precision, but not zero),
1332
+ scientific notation is used.
1333
+ - If the absolute value is less than 10 to the power of precision, fixed-point notation is used,
1334
+ with trailing zeros and decimal points removed for brevity.
1335
+ - Otherwise, scientific notation is used.
1336
+ This ensures that the string representation is concise and readable, while maintaining the requested precision.
1337
+ """
1098
1338
  ...
@@ -1,7 +1,8 @@
1
+ from __future__ import annotations
1
2
  from colorsys import hsv_to_rgb as __hsv_to_rgb_def__, hls_to_rgb as __hls_to_rgb_def__, rgb_to_hls as __rgb_to_hls__, rgb_to_hsv as __rgb_to_hsv__
2
3
  from typing import Any, Callable, Generator, Literal
3
4
  from pygame.color import Color as __color_pygame__
4
- from random import randint as __randint__
5
+ from random import random as __rand__
5
6
 
6
7
  RGB_COLOR_MODE = "rgb"
7
8
  RGBA_COLOR_MODE = "rgba"
@@ -15,11 +16,11 @@ HLS_COLOR_MODE = "hls"
15
16
 
16
17
  __LITERAL_COLOR_MODES__ = Literal["rgb","rgba","bgr","bgra","g","hsv","hls"] #,"cmyk","lab"]
17
18
 
18
- def __hsv_to_rgb__(h:int|float, s:int|float, v:int|float) -> tuple[int|float, int|float, int|float]:
19
+ def __hsv_to_rgb__(h:"int|float", s:"int|float", v:"int|float") -> tuple["int|float", "int|float", "int|float"]:
19
20
  r,g,b = __hsv_to_rgb_def__(h, s, v)
20
21
  return r*255, g*255, b*255
21
22
 
22
- def __hls_to_rgb__(h:int|float, s:int|float, v:int|float) -> tuple[int|float, int|float, int|float]:
23
+ def __hls_to_rgb__(h:"int|float", s:"int|float", v:"int|float") -> tuple["int|float", "int|float", "int|float"]:
23
24
  r,g,b = __hls_to_rgb_def__(h, s, v)
24
25
  return r*255, g*255, b*255
25
26
 
@@ -110,35 +111,35 @@ class Color:
110
111
  return (d ** .5) if rooted else d
111
112
 
112
113
  @classmethod
113
- def new_rgb(cls, r:int|float, g:int|float, b:int|float) -> "Color":
114
+ def new_rgb(cls, r:"int|float", g:"int|float", b:"int|float") -> "Color":
114
115
  return Color(r,g,b, mode=RGB_COLOR_MODE)
115
116
  @classmethod
116
- def new_rgba(cls, r:int|float, g:int|float, b:int|float, a:int|float) -> "Color":
117
+ def new_rgba(cls, r:"int|float", g:"int|float", b:"int|float", a:"int|float") -> "Color":
117
118
  return Color(r,g,b,a, mode=RGBA_COLOR_MODE)
118
119
  @classmethod
119
- def new_bgr(cls, b:int|float, g:int|float, r:int|float) -> "Color":
120
+ def new_bgr(cls, b:"int|float", g:"int|float", r:"int|float") -> "Color":
120
121
  return Color(b,g,r, mode=BGR_COLOR_MODE)
121
122
  @classmethod
122
- def new_bgra(cls, b:int|float, g:int|float, r:int|float, a:int|float) -> "Color":
123
+ def new_bgra(cls, b:"int|float", g:"int|float", r:"int|float", a:"int|float") -> "Color":
123
124
  return Color(b,g,r,a, mode=BGRA_COLOR_MODE)
124
125
  @classmethod
125
126
  def new_g(cls, g) -> "Color":
126
127
  return Color(g, mode=GRAY_COLOR_MODE)
127
128
  @classmethod
128
- def new_hsv(cls, h:int|float, s:int|float, v:int|float) -> "Color":
129
+ def new_hsv(cls, h:"int|float", s:"int|float", v:"int|float") -> "Color":
129
130
  return Color(h,s,v, mode=HSV_COLOR_MODE)
130
131
  @classmethod
131
- def new_hls(cls, h:int|float, l:int|float, s:int|float) -> "Color":
132
+ def new_hls(cls, h:"int|float", l:"int|float", s:"int|float") -> "Color":
132
133
  return Color(h,l,s, mode=HLS_COLOR_MODE)
133
134
  # @classmethod
134
- # def new_cmyk(cls, c:int|float, m:int|float, y:int|float, k:int|float) -> Color:
135
+ # def new_cmyk(cls, c:"int|float", m:"int|float", y:"int|float", k:"int|float") -> Color:
135
136
  # return Color(c,m,y,k, mode=CMYK_COLOR_MODE)
136
137
  # @classmethod
137
- # def new_lab(cls, l:int|float, a:int|float, b:int|float) -> Color:
138
+ # def new_lab(cls, l:"int|float", a:"int|float", b:"int|float") -> Color:
138
139
  # return Color(l,a,b, mode=LAB_COLOR_MODE)
139
140
 
140
141
  @property
141
- def values(self) -> tuple[int|float, ...]:
142
+ def values(self) -> tuple["int|float", ...]:
142
143
  return tuple(self.__dict__.values())[:-1]
143
144
 
144
145
  @property
@@ -146,7 +147,7 @@ class Color:
146
147
  return tuple(self.__dict__.keys())[:-1]
147
148
 
148
149
  @property
149
- def items(self) -> tuple[tuple[str, int|float], ...]:
150
+ def items(self) -> tuple[tuple[str, "int|float"], ...]:
150
151
  return tuple(self.__dict__.items())[:-1]
151
152
 
152
153
  def copy(self) -> "Color":
@@ -392,7 +393,7 @@ class Color:
392
393
  def __float__(self) -> "Color":
393
394
  return Color(float(self.r), float(self.g), float(self.b))
394
395
 
395
- def __getitem__(self, n) -> int|float:
396
+ def __getitem__(self, n) -> "int|float":
396
397
  return self.values[n] if isinstance(n, int) else self.values[self.keys.index(n)]
397
398
 
398
399
  def __iter__(self) -> Generator[float, Any, None]:
@@ -412,7 +413,7 @@ class Color:
412
413
  try:
413
414
  return cls(*other.values, mode=other.mode)
414
415
  except:
415
- raise TypeError(f"The value {other} of type {type(other)} is not a num type: [{int|float}] nor an array type: [{list|tuple}]")
416
+ raise TypeError(f"The value {other} of type {type(other)} is not a num type: [int|float] nor an array type: [list|tuple]")
416
417
 
417
418
  @classmethod
418
419
  def transparent(cls) -> "Color": return Color(0,0,0,0, mode=RGBA_COLOR_MODE)
@@ -426,13 +427,26 @@ class Color:
426
427
  def green(cls) -> "Color": return Color(0,255,0)
427
428
  @classmethod
428
429
  def blue(cls) -> "Color": return Color(0,0,255)
429
-
430
- # @classmethod
431
- # def (cls) -> "Color": return Color(0,0,255)
430
+ @classmethod
431
+ def cyan(cls) -> "Color": return Color(0,255,255)
432
+ @classmethod
433
+ def magenta(cls) -> "Color": return Color(255,0,255)
434
+ @classmethod
435
+ def yellow(cls) -> "Color": return Color(255,255,0)
432
436
 
433
437
  @classmethod
434
- def randomize(cls) -> "Color":
435
- return Color(__randint__(0,255), __randint__(0,255), __randint__(0,255))
438
+ def randomize(cls, start=0, end=255, func=lambda val:val) -> "Color":
439
+ if not isinstance(start, Color):
440
+ if isinstance(start, (int, float)):
441
+ start = Color(start, start, start)
442
+ else:
443
+ raise Exception(f"\nArg start must be in [Color, int, float, tuple, list] not a [{type(start)}]\n")
444
+ if not isinstance(end, Color):
445
+ if isinstance(end, (int, float)):
446
+ end = Color(end, end, end)
447
+ else:
448
+ raise Exception(f"\nArg end must be in [Color, int, float, tuple, list] not a [{type(end)}]\n")
449
+ return start + Color(func(__rand__()), func(__rand__()), func(__rand__())) * (end - start)
436
450
 
437
451
 
438
452
  TRANSPARENT_COLOR = Color.transparent()
@@ -441,6 +455,9 @@ BLACK_COLOR = Color.black()
441
455
  RED_COLOR = Color.red()
442
456
  GREEN_COLOR = Color.green()
443
457
  BLUE_COLOR = Color.blue()
458
+ CYAN_COLOR = Color.cyan()
459
+ MAGENTA_COLOR = Color.magenta()
460
+ YELLOW_COLOR = Color.yellow()
444
461
 
445
462
  TRANSPARENT_COLOR_PYG = TRANSPARENT_COLOR()
446
463
  WHITE_COLOR_PYG = WHITE_COLOR()
@@ -448,3 +465,6 @@ BLACK_COLOR_PYG = BLACK_COLOR()
448
465
  RED_COLOR_PYG = RED_COLOR()
449
466
  GREEN_COLOR_PYG = GREEN_COLOR()
450
467
  BLUE_COLOR_PYG = BLUE_COLOR()
468
+ CYAN_COLOR_PYG = CYAN_COLOR()
469
+ MAGENTA_COLOR_PYG = MAGENTA_COLOR()
470
+ YELLOW_COLOR_PYG = YELLOW_COLOR()
@@ -42,13 +42,15 @@ class RootEnv:
42
42
  quit_on_key_pressed : None|int = pg.K_x,
43
43
  vsync : bool = True,
44
44
  window_flags : int = pg.DOUBLEBUF,
45
+ display_index : int = 0,
45
46
  clear_screen_each_frame : bool = True) -> None:
46
47
  self.quit = False
47
48
  self.__screen_size__ :Vector2D= screen_size
48
49
 
49
50
  self.__vsync__ = vsync
50
51
  self.__flags__ = window_flags
51
- self.screen = pg.display.set_mode(self.__screen_size__(), vsync=self.__vsync__, flags=self.__flags__)
52
+ self.__display_index__ = display_index
53
+ self.screen = pg.display.set_mode(self.__screen_size__(), vsync=self.__vsync__, flags=self.__flags__, display=self.__display_index__)
52
54
 
53
55
  self.clock = pg.time.Clock()
54
56
  self.keyboard = Keyboard()
@@ -56,6 +58,7 @@ class RootEnv:
56
58
 
57
59
  self.target_fps = target_fps
58
60
  self.current_fps = self.target_fps if self.target_fps != 0 else 1
61
+ self.__dt__ = 1 / self.current_fps
59
62
  self.current_frame = 0
60
63
  self.show_fps = show_fps
61
64
  self.events :list[pg.event.Event]= []
@@ -67,6 +70,13 @@ class RootEnv:
67
70
  self.selected_util :Util|None = None
68
71
  self.__quit_on_key_pressed__ = quit_on_key_pressed
69
72
 
73
+ self.fps_label = Label(str(round(self.current_fps,2)), self.screen_size * .01, V2(250, 50), BLACK_COLOR_PYG, TRANSPARENT_COLOR_PYG, WHITE_COLOR_PYG, border_width=0, starting_hidden=(not self.show_fps), pivot_position="top_left", font=FONT_ARIAL_32)
74
+ self.add_utils(self.fps_label)
75
+
76
+ def init_rec(self, fps:int=30, path:str='output.mp4') -> None:
77
+ from .winrec import WinRec
78
+ self.__winrecorder__ = WinRec(self, fps=fps, path=path)
79
+
70
80
  @property
71
81
  def background_color(self) -> Color:
72
82
  return unpygamize_color(self.__background_color__)
@@ -81,19 +91,24 @@ class RootEnv:
81
91
  @screen_size.setter
82
92
  def screen_size(self, new_size:Vector2D) -> None:
83
93
  self.__screen_size__ = new_size
84
- self.screen = pg.display.set_mode(self.__screen_size__(), vsync=self.__vsync__, flags=self.__flags__)
94
+ self.screen = pg.display.set_mode(self.__screen_size__(), vsync=self.__vsync__, flags=self.__flags__, display=self.__display_index__)
95
+
96
+ def update_screen_to_new_size(self) -> None:
97
+ self.screen = pg.display.set_mode(self.__screen_size__(), vsync=self.__vsync__, flags=self.__flags__, display=self.__display_index__)
85
98
 
86
99
  @property
87
100
  def delta(self) -> int:
88
- return self.clock.get_time() / 1000
101
+ return self.__dt__
89
102
 
90
103
  def get_teoric_max_fps(self) -> float:
91
104
  rawdelta = self.clock.get_rawtime()
92
105
  return (1000 / rawdelta) if rawdelta != 0 else 1
93
106
 
94
- def update_screen_mode(self, vsync:None|bool=None, flags=None) -> None:
107
+ def update_screen_mode(self, vsync:None|bool=None, flags=None, display_index=None) -> None:
95
108
  self.__vsync__ = vsync
96
109
  self.__flags__ = flags
110
+ self.__display_index__ = display_index
111
+ self.screen = pg.display.set_mode(self.__screen_size__(), vsync=self.__vsync__, flags=self.__flags__, display=self.__display_index__)
97
112
 
98
113
  def sleep(self, seconds:int|float, precise_delay=False) -> None:
99
114
  if precise_delay:
@@ -106,7 +121,7 @@ class RootEnv:
106
121
  if util.surface == None: util.surface = self.screen
107
122
  util.rootEnv = self
108
123
  util.id = self.__new_util_id__()
109
- util.render()
124
+ util.__render__()
110
125
  self.utils[util.id] = util
111
126
 
112
127
  def remove_utils(self, *utils:int|str|Util) -> None:
@@ -169,24 +184,32 @@ class RootEnv:
169
184
  surface.blit(text_box, pivotted_position())
170
185
 
171
186
  def __draw__(self) -> None:
172
- self.clock.tick(self.target_fps)
187
+ self.__dt__ = self.clock.tick(self.target_fps) / 1000.0
173
188
  self.current_fps = self.clock.get_fps()
189
+ self.fps_label.text = str(round(self.current_fps, 2))
190
+
174
191
  if self.clear_screen_each_frame: self.clear()
175
192
 
176
193
  self.env.draw()
177
- for util in self.utils.values(): util.draw()
194
+ for util in self.utils.values(): util.__draw__()
178
195
 
179
- if self.show_fps: self.print(str(round(self.current_fps,2)), self.screen_size * .01, bg_color=BLACK_COLOR_PYG)
180
196
  pg.display.flip()
181
197
 
182
198
  def __update__(self) -> None:
183
199
  self.mouse.update()
184
200
  self.keyboard.update()
185
201
  self.env.update()
186
- for util in self.utils.values(): util.update()
202
+ for util in self.utils.values(): util.__update__()
203
+
204
+ if hasattr(self, "__winrecorder__"):
205
+ self.__winrecorder__.update()
206
+ self.__winrecorder__.draw()
187
207
 
188
208
  def frame(self) -> None:
189
- self.events = pg.event.get()
209
+ try:
210
+ self.events = pg.event.get()
211
+ except SystemError:
212
+ raise Warning(f"Pygame error with event drivers. Try restarting the program. If the error persists, try restarting your computer.")
190
213
  self.current_frame += 1
191
214
  self.__update__()
192
215
  self.__draw__()
@@ -194,4 +217,5 @@ class RootEnv:
194
217
  for event in self.events:
195
218
  if event.type == pg.QUIT or ((event.type == pg.KEYDOWN and event.key == self.__quit_on_key_pressed__ and self.selected_util == None) if self.__quit_on_key_pressed__ != None else False):
196
219
  pg.quit()
220
+ if hasattr(self, "__winrecorder__"): self.__winrecorder__.quit()
197
221
  self.quit = True
@@ -33,32 +33,51 @@ __PIVOT_POSITIONS_MULTIPLIER__ = dict(zip(("top_left", "top_center", "top_right"
33
33
  class Mouse:
34
34
  def __init__(self, parent) -> None:
35
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
-
36
+ self.__last_frame_position_number__ :int= 0
37
+ self.__last_frame_position__ :Vector2D= Vector2D.new_zero()
38
+ self.__last_frame_movement_number__ :int= 0
39
+ self.__last_frame_movement__ :Vector2D= Vector2D.new_zero()
40
+ self.__last_frame_wheel_number__ :int= 0
41
+ self.__last_frame_wheel_delta__ :int= 0
42
+
41
43
  self.__pressed__ : tuple[bool, bool, bool] = (False, False, False)
42
- self.update()
44
+ self.update()
45
+
46
+ @property
47
+ def wheel_delta(self) -> int:
48
+ for event in self.parent.events:
49
+ if event.type == pg.MOUSEWHEEL:
50
+ if self.__last_frame_wheel_number__ != self.parent.current_frame:
51
+ self.__last_frame_wheel_delta__ = event.y
52
+ self.__last_frame_wheel_number__ = self.parent.current_frame
53
+ return self.__last_frame_wheel_delta__
54
+
55
+ self.__last_frame_wheel_delta__ = 0
56
+ self.__last_frame_wheel_number__ = self.parent.current_frame
57
+ return self.__last_frame_wheel_delta__
43
58
 
44
59
  @property
45
60
  def position(self) -> Vector2D:
46
- if self.__last_frame_position_count__ != self.parent.current_frame:
61
+ if self.__last_frame_position_number__ != self.parent.current_frame:
47
62
  self.__last_frame_position__ = Vector2D(*pg.mouse.get_pos())
48
- self.__last_frame_position_count__ = self.parent.current_frame
63
+ self.__last_frame_position_number__ = self.parent.current_frame
49
64
  return self.__last_frame_position__
50
65
  @position.setter
51
66
  def position(self, new_position:Vector2D) -> None:
52
- self.__last_frame_position_count__ = self.parent.current_frame
67
+ self.__last_frame_position_number__ = self.parent.current_frame
53
68
  self.__last_frame_position__ = new_position
54
69
  pg.mouse.set_pos(self.__last_frame_position__())
55
70
 
56
71
  @property
57
72
  def last_frame_movement(self) -> Vector2D:
58
- if self.__last_frame_movement_count__ != self.parent.current_frame:
73
+ if self.__last_frame_movement_number__ != self.parent.current_frame:
59
74
  self.__last_frame_movement__ = Vector2D(*pg.mouse.get_rel())
60
- self.__last_frame_movement_count__ = self.parent.current_frame
75
+ self.__last_frame_movement_number__ = self.parent.current_frame
61
76
  return self.__last_frame_movement__
77
+ @last_frame_movement.setter
78
+ def last_frame_movement(self, new_movement:Vector2D) -> None:
79
+ self.__last_frame_movement_number__ = self.parent.current_frame
80
+ self.__last_frame_movement__ = new_movement
62
81
 
63
82
  def update(self) -> None:
64
83
  self.__last_pressed__ = self.__pressed__
@@ -95,8 +114,8 @@ class Keyboard:
95
114
 
96
115
  class Util:
97
116
  def __init__(self) -> None:
98
- self.rootEnv = None
99
- self.surface : pg.Surface = pg.SurfaceType
117
+ self.rootEnv : Any
118
+ self.surface : pg.Surface= None # type: ignore
100
119
  self.id : int|str
101
120
  self.is_hovered :bool= False
102
121
  self.hidden :bool= False
@@ -104,9 +123,9 @@ class Util:
104
123
  self.hidden = True
105
124
  def show(self) -> None:
106
125
  self.hidden = False
107
- def render(self) -> None: pass
108
- def draw(self) -> None: pass
109
- def update(self) -> None: pass
126
+ def __render__(self) -> None: pass
127
+ def __draw__(self) -> None: pass
128
+ def __update__(self) -> None: pass
110
129
 
111
130
  class InputCell(Util):
112
131
  def __init__(self,
@@ -176,7 +195,7 @@ class InputCell(Util):
176
195
  def border_color(self, new_color:Color|pg.Color) -> None:
177
196
  self.__border_color__ = pygamize_color(new_color)
178
197
 
179
- def draw(self) -> None:
198
+ def __draw__(self) -> None:
180
199
  if self.hidden: return
181
200
  self.text_surface.fill(TRANSPARENT_COLOR_PYG)
182
201
 
@@ -194,7 +213,7 @@ class InputCell(Util):
194
213
 
195
214
  self.surface.blit(self.text_surface, self.position())
196
215
 
197
- def update(self) -> None:
216
+ def __update__(self) -> None:
198
217
  if self.hidden: return
199
218
  self.is_hovered = self.position.x < self.rootEnv.mouse.position.x < self.position.x + self.size.x and\
200
219
  self.position.y < self.rootEnv.mouse.position.y < self.position.y + self.size.y
@@ -261,7 +280,7 @@ class Slider(Util):
261
280
  self.text_pivot = text_pivot
262
281
 
263
282
  self.handleRadius = handleRadius
264
- self.surface = personalized_surface
283
+ self.surface = personalized_surface # type: ignore
265
284
 
266
285
  self.hidden = False
267
286
 
@@ -281,21 +300,21 @@ class Slider(Util):
281
300
  def handleColour(self, new_color:Color|pg.Color) -> None:
282
301
  self.__handleColour__ = pygamize_color(new_color)
283
302
 
284
- def draw(self) -> None:
303
+ def __draw__(self) -> None:
285
304
  if self.hidden: return
286
- pg.draw.rect(self.rootEnv.screen, self.__color__, self.position() + self.size())
305
+ pg.draw.rect(self.surface, self.__color__, self.position() + self.size())
287
306
 
288
307
  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)
308
+ pg.draw.circle(self.surface, self.__color__, (self.position.x, self.position.y + self.size.y // 2), self.radius)
309
+ pg.draw.circle(self.surface, self.__color__, (self.position.x + self.size.x, self.position.y + self.size.y // 2), self.radius)
291
310
 
292
311
  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
312
 
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)
313
+ pg.draw.circle(self.surface, self.__color__, circle(), self.handleRadius * 1.25)
314
+ pg.draw.circle(self.surface, self.__handleColour__, circle(), self.handleRadius)
296
315
  self.rootEnv.print(self.text.format(round(self.value, 2)), self.position + self.size * self.text_offset, pivot_position=self.text_pivot)
297
316
 
298
- def update(self) -> None:
317
+ def __update__(self) -> None:
299
318
  if self.hidden: return
300
319
  x,y = self.rootEnv.mouse.position
301
320
 
@@ -324,22 +343,22 @@ class Button(Util):
324
343
  text : str,
325
344
  position : V2|Vector2D,
326
345
  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,
346
+ callback : Callable[[], None]|Callable[[], None] = lambda: None,
347
+ default_bg_color : Color|pg.Color = BLUE_COLOR_PYG,
348
+ hovered_bg_color : Color|pg.Color = CYAN_COLOR_PYG,
349
+ border_color : Color|pg.Color = WHITE_COLOR_PYG,
331
350
  text_color : Color|pg.Color = WHITE_COLOR_PYG,
332
351
  font : pg.font.Font = FONT_ARIAL_32,
333
352
  border_radius : float = 10,
334
353
  border_width : float = 10,
335
- starting_hiddden : bool = False,
354
+ starting_hidden : bool = False,
336
355
  args : list = [],
337
356
  activation_mode : __LITERAL_KEY_MODE_TYPES__ = "just_pressed",
338
357
  pivot_position : __LITERAL_PIVOT_POSITIONS__ = "top_left",
339
358
  personalized_surface : pg.Surface|None = None,
340
359
  ) -> None:
341
360
  super().__init__()
342
-
361
+
343
362
  self.text = text
344
363
  self.font = font
345
364
 
@@ -348,10 +367,11 @@ class Button(Util):
348
367
  self.border_radius = border_radius
349
368
  self.__size__ = size
350
369
  self.__border_width__ = border_width
351
-
352
- self.update_position(position, pivot_position)
353
370
 
354
- self.hidden = starting_hiddden
371
+ self.pivot_position :__LITERAL_PIVOT_POSITIONS__= pivot_position
372
+ self.update_position(position)
373
+
374
+ self.hidden = starting_hidden
355
375
  self.args = args
356
376
 
357
377
  self.activation_mode = activation_mode
@@ -359,19 +379,23 @@ class Button(Util):
359
379
  self.hovered = False
360
380
 
361
381
  self.text_color = text_color
362
- self.default_color = default_color
382
+ self.default_bg_color = default_bg_color
363
383
  self.border_color = border_color
364
- self.hovered_color = hovered_color
384
+ self.hovered_bg_color = hovered_bg_color
365
385
 
366
- self.surface = personalized_surface
386
+ self.surface = personalized_surface #type: ignore
367
387
  self.update_surface()
368
388
 
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]
389
+ def update_position(self, new_position:V2) -> None:
390
+ self.position = new_position - self.__size__ * __PIVOT_POSITIONS_MULTIPLIER__[self.pivot_position]
391
+
392
+ def update_pivoting(self, new_pivot_position:__LITERAL_PIVOT_POSITIONS__) -> None:
393
+ self.pivot_position = new_pivot_position
394
+ self.update_position(self.position)
371
395
 
372
396
  def update_surface(self, render=False) -> None:
373
397
  self.buffer_surface = pg.Surface((self.__size__ + self.__border_width__ * 2)(), pg.SRCALPHA, 32).convert_alpha()
374
- if render: self.render()
398
+ if render: self.__render__()
375
399
 
376
400
  @property
377
401
  def size(self) -> V2:
@@ -386,6 +410,7 @@ class Button(Util):
386
410
  return self.__border_width__
387
411
  @border_width.setter
388
412
  def border_width(self, new_width:float) -> None:
413
+ # self.position -= (self.__border_width__ - new_width) * .5
389
414
  self.__border_width__ = new_width
390
415
  self.update_surface(render=True)
391
416
 
@@ -396,11 +421,11 @@ class Button(Util):
396
421
  def text_color(self, new_color:Color|pg.Color) -> None:
397
422
  self.__text_color__ = pygamize_color(new_color)
398
423
  @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)
424
+ def default_bg_color(self) -> Color:
425
+ return unpygamize_color(self.__default_bg_color__)
426
+ @default_bg_color.setter
427
+ def default_bg_color(self, new_color:Color|pg.Color) -> None:
428
+ self.__default_bg_color__ = pygamize_color(new_color)
404
429
  @property
405
430
  def border_color(self) -> Color:
406
431
  return unpygamize_color(self.__border_color__)
@@ -408,27 +433,28 @@ class Button(Util):
408
433
  def border_color(self, new_color:Color|pg.Color) -> None:
409
434
  self.__border_color__ = pygamize_color(new_color)
410
435
  @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")
436
+ def hovered_bg_color(self) -> Color:
437
+ return unpygamize_color(self.__hovered_bg_color__)
438
+ @hovered_bg_color.setter
439
+ def hovered_bg_color(self, new_color:Color|pg.Color) -> None:
440
+ self.__hovered_bg_color__ = pygamize_color(new_color)
441
+
442
+ def __render__(self) -> None:
419
443
  self.buffer_surface.fill(TRANSPARENT_COLOR_PYG)
420
444
 
421
- color = self.__hovered_color__ if self.hovered else self.__default_color__
445
+ color = self.__hovered_bg_color__ if self.hovered else self.__default_bg_color__
422
446
  pg.draw.rect(self.buffer_surface, self.__border_color__, V2.zero()() + (self.size + self.border_width * 2)(), border_radius=self.border_radius)
423
447
  pg.draw.rect(self.buffer_surface, color, (V2.zero() + self.border_width)() + self.size(), border_radius=self.border_radius)
424
448
 
449
+ # TODO:
450
+ # not only size * .5 but also internal pivoting on the corners and sides
425
451
  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
452
 
427
- def draw(self) -> None:
453
+ def __draw__(self) -> None:
428
454
  if self.hidden: return
429
455
  self.surface.blit(self.buffer_surface, (self.position)())
430
456
 
431
- def update(self) -> None:
457
+ def __update__(self) -> None:
432
458
  if self.hidden: return
433
459
 
434
460
  old_overed = self.hovered
@@ -436,15 +462,15 @@ class Button(Util):
436
462
  self.position.x < self.rootEnv.mouse.position.x < self.position.x + self.size.x and \
437
463
  self.position.y < self.rootEnv.mouse.position.y < self.position.y + self.size.y
438
464
  if self.hovered != old_overed:
439
- self.render()
465
+ self.__render__()
440
466
 
441
467
  if self.hovered and self.rootEnv.mouse.get_key(0, self.activation_mode):
442
468
  self.callback(*self.args)
443
469
  self.rootEnv.selected_util = self
444
- self.render()
470
+ self.__render__()
445
471
  elif self.rootEnv.selected_util == self:
446
472
  self.rootEnv.selected_util = None
447
- self.render()
473
+ self.__render__()
448
474
 
449
475
  class Label(Util):
450
476
  def __init__(self,
@@ -457,7 +483,7 @@ class Label(Util):
457
483
  font : pg.font.Font = FONT_ARIAL_32,
458
484
  border_radius : float = 10,
459
485
  border_width : float = 10,
460
- starting_hiddden : bool = False,
486
+ starting_hidden : bool = False,
461
487
  personalized_surface : pg.Surface|None = None,
462
488
  pivot_position : __LITERAL_PIVOT_POSITIONS__ = "top_left",
463
489
  ) -> None:
@@ -470,23 +496,28 @@ class Label(Util):
470
496
  self.__size__ = size
471
497
  self.__border_width__ = border_width
472
498
 
473
- self.position = self.update_position(position, pivot_position)
499
+ self.pivot_position :__LITERAL_PIVOT_POSITIONS__= pivot_position
500
+ self.update_position(position)
474
501
 
475
- self.hidden = starting_hiddden
502
+ self.hidden = starting_hidden
476
503
 
477
504
  self.text_color = text_color
478
505
  self.default_color = default_color
479
506
  self.border_color = border_color
480
507
 
481
- self.surface = personalized_surface
508
+ self.surface = personalized_surface # type: ignore
482
509
  self.update_surface()
483
510
 
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
-
511
+ def update_position(self, new_position:V2) -> None:
512
+ self.position = new_position - (self.__size__ + self.border_width * 2) * __PIVOT_POSITIONS_MULTIPLIER__[self.pivot_position]
513
+
514
+ def update_pivoting(self, new_pivot_position:__LITERAL_PIVOT_POSITIONS__="top_left") -> None:
515
+ self.pivot_position = new_pivot_position
516
+ self.update_position(self.position)
517
+
487
518
  def update_surface(self, render=False) -> None:
488
519
  self.buffer_surface = pg.Surface((self.__size__ + self.__border_width__ * 2)(), pg.SRCALPHA, 32).convert_alpha()
489
- if render: self.render()
520
+ if render: self.__render__()
490
521
 
491
522
  @property
492
523
  def text(self) -> str:
@@ -494,7 +525,7 @@ class Label(Util):
494
525
  @text.setter
495
526
  def text(self, new_text:str) -> None:
496
527
  self.__text__ = new_text
497
- self.render()
528
+ self.__render__()
498
529
 
499
530
  @property
500
531
  def size(self) -> V2:
@@ -531,15 +562,16 @@ class Label(Util):
531
562
  def border_color(self, new_color:Color|pg.Color) -> None:
532
563
  self.__border_color__ = pygamize_color(new_color)
533
564
 
534
- def render(self) -> None:
535
- print("rendering label")
565
+ def __render__(self) -> None:
536
566
  self.buffer_surface.fill(TRANSPARENT_COLOR_PYG)
537
567
 
538
568
  pg.draw.rect(self.buffer_surface, self.__border_color__, V2.zero()() + (self.size + self.border_width * 2)(), border_radius=self.border_radius)
539
569
  pg.draw.rect(self.buffer_surface, self.__default_color__, (V2.zero() + self.border_width)() + self.size(), border_radius=self.border_radius)
540
570
 
571
+ # TODO:
572
+ # not only size * .5 but also internal pivoting on the corners and sides
541
573
  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
574
 
543
- def draw(self) -> None:
575
+ def __draw__(self) -> None:
544
576
  if self.hidden: return
545
577
  self.surface.blit(self.buffer_surface, (self.position)())
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: e2D
3
- Version: 1.4.20
3
+ Version: 1.4.22
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
@@ -1,6 +1,6 @@
1
1
  [metadata]
2
2
  name = e2D
3
- version = 1.4.20
3
+ version = 1.4.22
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!
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