-
Notifications
You must be signed in to change notification settings - Fork 6
/
basictypes.py
137 lines (106 loc) · 3.67 KB
/
basictypes.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
"""
Basic types definitions used all over Ice Emblem's code base
"""
import pygame
class Point(tuple):
"""
A tuple with more convenient operators to use for points
"""
def __new__(cls, *args):
if len(args) == 0:
return tuple.__new__(cls, (0, 0))
try:
return tuple.__new__(cls, *args)
except TypeError:
return tuple.__new__(cls, args)
def __add__(self, other) -> 'Point':
if isinstance(other, int):
return Point(int(x + other) for x in self)
return Point(int(x + y) for x, y in zip(self, other))
def __sub__(self, other) -> 'Point':
return self.__add__(int(-i) for i in other)
def __neg__(self) -> 'Point':
return Point(int(-x) for x in self)
def __abs__(self) -> 'Point':
return Point(abs(int(x)) for x in self)
def __mul__(self, other) -> 'Point':
return Point(int(x * other) for x in self)
def __truediv__(self, other) -> 'Point':
return Point(int(x / other) for x in self)
def __floordiv__(self, other) -> 'Point':
return Point(int(x // other) for x in self)
def __repr__(self) -> str:
return f'({"; ".join(str(x) for x in self)})'
def norm(self) -> 'Point':
return sum(abs(x) for x in self)
def normalized(self) -> 'Point':
return self / self.norm() if self.norm() > 0 else self
def __getattr__(self, attr):
try:
return self[['x', 'y', 'z', 'w'].index(attr)]
except (IndexError, ValueError):
raise AttributeError('%s is not an attribute of Point %s' % (attr, self))
def __setattr__(self, key, value):
raise AttributeError('Point is immutable!')
class NESW(object):
"""
North East South West. Used to specify padding, border and margin like HTML.
"""
def __init__(self, *args):
if len(args) == 1:
args = args[0]
if isinstance(args, int):
self.n = self.e = self.s = self.w = args
elif len(args) == 2:
self.n = self.s = args[0]
self.e = self.w = args[1]
elif len(args) == 4:
self.n: int = args[0]
self.e: int = args[1]
self.s: int = args[2]
self.w: int = args[3]
else:
raise ValueError("'padding' should be either 1, 2 or 4 ints")
def __repr__(self):
return "(%d, %d, %d, %d)" % (self.n, self.e, self.s, self.w)
@property
def ns(self) -> int:
return self.n + self.s
@property
def ew(self) -> int:
return self.e + self.w
@property
def we(self) -> int:
return self.ew
@property
def sn(self) -> int:
return self.ns
def __getitem__(self, index) -> int:
return getattr(self, ['n', 'e', 's', 'w'][index])
def __add__(self, other) -> Point:
return Point(self.w + other[0], self.n + other[1])
def __radd__(self, other) -> Point:
return Point(self.w + other[0], self.n + other[1])
def grow(self, rect) -> pygame.Rect:
rect = rect.move(-self.w, -self.n)
rect.w += self.w + self.e
rect.h += self.n + self.s
return rect
def shrink(self, rect) -> pygame.Rect:
rect = rect.move(self.w, self.n)
rect.w -= self.w + self.e
rect.h += self.n + self.s
return rect
if __name__ == '__main__':
p = Point((10, 0)).normalized()
q = Point((1, 0, 2, 3))
def test_getattr(point):
for attr in ['x', 'y', 'z', 'w', 'a']:
try:
print(getattr(point, attr))
except AttributeError as e:
print(e)
test_getattr(p)
test_getattr(q)
print(p, q)
print("END")