basilisk-engine 0.1.35__py3-none-any.whl → 0.1.36__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.

Potentially problematic release.


This version of basilisk-engine might be problematic. Click here for more details.

Files changed (98) hide show
  1. basilisk/__init__.py +26 -26
  2. basilisk/audio/sound.py +27 -27
  3. basilisk/bsk_assets/cube.obj +48 -48
  4. basilisk/collisions/broad/broad_aabb.py +102 -102
  5. basilisk/collisions/broad/broad_bvh.py +137 -137
  6. basilisk/collisions/collider.py +95 -95
  7. basilisk/collisions/collider_handler.py +225 -225
  8. basilisk/collisions/narrow/contact_manifold.py +95 -95
  9. basilisk/collisions/narrow/dataclasses.py +34 -34
  10. basilisk/collisions/narrow/deprecated.py +46 -46
  11. basilisk/collisions/narrow/epa.py +91 -91
  12. basilisk/collisions/narrow/gjk.py +66 -66
  13. basilisk/collisions/narrow/graham_scan.py +24 -24
  14. basilisk/collisions/narrow/helper.py +29 -29
  15. basilisk/collisions/narrow/line_intersections.py +106 -106
  16. basilisk/collisions/narrow/sutherland_hodgman.py +75 -75
  17. basilisk/config.py +54 -4
  18. basilisk/draw/draw.py +100 -100
  19. basilisk/draw/draw_handler.py +175 -175
  20. basilisk/draw/font_renderer.py +28 -28
  21. basilisk/engine.py +165 -165
  22. basilisk/generic/abstract_bvh.py +15 -15
  23. basilisk/generic/abstract_custom.py +133 -133
  24. basilisk/generic/collisions.py +70 -70
  25. basilisk/generic/input_validation.py +82 -74
  26. basilisk/generic/math.py +6 -6
  27. basilisk/generic/matrices.py +35 -35
  28. basilisk/generic/meshes.py +72 -72
  29. basilisk/generic/quat.py +142 -142
  30. basilisk/generic/quat_methods.py +7 -7
  31. basilisk/generic/raycast_result.py +26 -26
  32. basilisk/generic/vec3.py +143 -143
  33. basilisk/input_output/IO_handler.py +91 -91
  34. basilisk/input_output/clock.py +49 -49
  35. basilisk/input_output/keys.py +43 -43
  36. basilisk/input_output/mouse.py +90 -89
  37. basilisk/input_output/path.py +14 -14
  38. basilisk/mesh/cube.py +33 -33
  39. basilisk/mesh/mesh.py +233 -233
  40. basilisk/mesh/mesh_from_data.py +150 -150
  41. basilisk/mesh/model.py +271 -271
  42. basilisk/mesh/narrow_aabb.py +89 -89
  43. basilisk/mesh/narrow_bvh.py +91 -91
  44. basilisk/mesh/narrow_primative.py +23 -23
  45. basilisk/nodes/helper.py +28 -28
  46. basilisk/nodes/node.py +704 -695
  47. basilisk/nodes/node_handler.py +97 -97
  48. basilisk/particles/particle_handler.py +64 -64
  49. basilisk/particles/particle_renderer.py +92 -92
  50. basilisk/physics/impulse.py +112 -112
  51. basilisk/physics/physics_body.py +43 -43
  52. basilisk/physics/physics_engine.py +35 -35
  53. basilisk/render/batch.py +103 -103
  54. basilisk/render/bloom.py +108 -0
  55. basilisk/render/camera.py +260 -260
  56. basilisk/render/chunk.py +108 -106
  57. basilisk/render/chunk_handler.py +167 -165
  58. basilisk/render/frame.py +107 -95
  59. basilisk/render/framebuffer.py +203 -192
  60. basilisk/render/image.py +120 -120
  61. basilisk/render/image_handler.py +120 -120
  62. basilisk/render/light.py +96 -96
  63. basilisk/render/light_handler.py +58 -58
  64. basilisk/render/material.py +232 -221
  65. basilisk/render/material_handler.py +133 -133
  66. basilisk/render/post_process.py +139 -139
  67. basilisk/render/shader.py +134 -134
  68. basilisk/render/shader_handler.py +85 -83
  69. basilisk/render/sky.py +120 -120
  70. basilisk/scene.py +289 -289
  71. basilisk/shaders/batch.frag +289 -276
  72. basilisk/shaders/batch.vert +117 -115
  73. basilisk/shaders/bloom_downsample.frag +43 -0
  74. basilisk/shaders/bloom_frame.frag +25 -0
  75. basilisk/shaders/bloom_upsample.frag +34 -0
  76. basilisk/shaders/crt.frag +31 -31
  77. basilisk/shaders/draw.frag +25 -22
  78. basilisk/shaders/draw.vert +25 -25
  79. basilisk/shaders/filter.frag +22 -22
  80. basilisk/shaders/frame.frag +12 -12
  81. basilisk/shaders/frame.vert +13 -13
  82. basilisk/shaders/geometry.frag +8 -8
  83. basilisk/shaders/geometry.vert +41 -41
  84. basilisk/shaders/normal.frag +59 -59
  85. basilisk/shaders/normal.vert +96 -96
  86. basilisk/shaders/particle.frag +71 -71
  87. basilisk/shaders/particle.vert +84 -84
  88. basilisk/shaders/sky.frag +23 -9
  89. basilisk/shaders/sky.vert +13 -13
  90. basilisk_engine-0.1.36.dist-info/METADATA +89 -0
  91. basilisk_engine-0.1.36.dist-info/RECORD +110 -0
  92. {basilisk_engine-0.1.35.dist-info → basilisk_engine-0.1.36.dist-info}/WHEEL +1 -1
  93. basilisk/input/__init__.py +0 -0
  94. basilisk/input/mouse.py +0 -62
  95. basilisk/input/path.py +0 -14
  96. basilisk_engine-0.1.35.dist-info/METADATA +0 -45
  97. basilisk_engine-0.1.35.dist-info/RECORD +0 -109
  98. {basilisk_engine-0.1.35.dist-info → basilisk_engine-0.1.36.dist-info}/top_level.txt +0 -0
basilisk/generic/quat.py CHANGED
@@ -1,143 +1,143 @@
1
- import glm
2
- import numpy as np
3
- from .abstract_custom import Custom
4
-
5
-
6
- class Quat(Custom):
7
- def __init__(self, *args, callback=None):
8
- self.callback = callback
9
- self.prev_data = glm.quat(1, 0, 0, 0)
10
-
11
- if len(args) == 1:
12
-
13
- if isinstance(args[0], Quat):
14
- self.data = glm.quat(args[0].data)
15
- self.prev_data = glm.quat(args[0].prev_data)
16
- self.callback = args[0].callback
17
-
18
- elif isinstance(args[0], glm.quat):
19
- self.data = args[0]
20
-
21
- elif isinstance(args[0], tuple) or isinstance(args[0], list) or isinstance(args[0], np.ndarray):
22
- assert 2 < len(args[0]) < 5, f'Quat: Expected 3 or 4 values from incoming vector, got {len(args[0])}'
23
- self.data = glm.quat(args[0])
24
-
25
- else:
26
- try: self.data = glm.quat(args[0])
27
- except: raise ValueError(f'Quat: Unexpected incoming quaternion type {args[0]}')
28
-
29
- elif 2 < len(args) < 5: self.data = glm.quat(*args)
30
- else: raise ValueError(f'Quat: Expected either a vector, quaternion, or 3 or 4 numbers, got {len(args)} values')
31
-
32
- def apply_function(self, other, func, func_name):
33
- quat = glm.quat(self.data)
34
-
35
- if isinstance(other, (glm.vec3, glm.quat)):
36
- quat = func(quat, other)
37
-
38
- elif isinstance(other, (tuple, list, np.ndarray)):
39
- assert 2 < len(other) < 5, f'Quat: Expected 3 or 4 values from incoming vector, got {len(other)}'
40
- quat = func(quat, other)
41
-
42
- elif isinstance(other, Custom):
43
- quat = func(quat, other.data)
44
-
45
- else:
46
- try: quat = func(quat, other)
47
- except: raise ValueError(f'Quat: Not an accepted type for {func_name}, got {type(other)}')
48
- return Quat(quat)
49
-
50
- # unary operators
51
- def __neg__(self):
52
- return Quat(-self.data, callback=self.callback)
53
-
54
- def __abs__(self):
55
- return Quat(abs(self.data), callback=self.callback)
56
-
57
- # accessor functions
58
- def __getitem__(self, index):
59
- assert int(index) == index, f'Quat: index must be an int, got {type(index)}' # check if index is a float
60
- assert 0 <= index <= 3, f'Quat: index out of bounds, got {index}'
61
- return self.data[index]
62
-
63
- def __setitem__(self, index, value):
64
- assert int(index) == index, f'Quat: index must be an int, got {type(index)}' # check if index is a float
65
- assert 0 <= index <= 3, f'Quat: index out of bounds, got {index}'
66
- try: self.data[index] = value
67
- except: raise ValueError(f'Quat: Invalid element type, got {type(value)}')
68
-
69
- def __delitem__(self, index): # cannot delete an index from a quaternion, so we set the value to zero instead
70
- assert int(index) == index, f'Quat: index must be an int, got {type(index)}' # check if index is a float
71
- assert 0 <= index <= 3, f'Quat: index out of bounds, got {index}'
72
- self.data[index] = 0
73
-
74
- def __len__(self):
75
- return 4
76
-
77
- def __iter__(self):
78
- return iter(self.data)
79
-
80
- def __contains__(self, item):
81
- return item in self.data
82
-
83
- # override str operators
84
- def __repr__(self):
85
- return 'bsk' + str(self.data)
86
-
87
- def __str__(self):
88
- return 'bsk ' + str(self.data)
89
-
90
- @property
91
- def data(self): return self._data
92
- @property
93
- def w(self): return self.data.w
94
- @property
95
- def x(self): return self.data.x
96
- @property
97
- def y(self): return self.data.y
98
- @property
99
- def z(self): return self.data.z
100
-
101
- @data.setter
102
- def data(self, value: glm.vec3 | glm.quat):
103
- self._data = glm.quat(value)
104
- cur = self._data
105
- prev = self.prev_data
106
- thresh = 1e-6
107
-
108
- if self.callback and (abs(cur.w - prev.w) > thresh or abs(cur.x - prev.x) > thresh or abs(cur.y - prev.y) > thresh or abs(cur.z - prev.z) > thresh):
109
- self.prev_data = glm.quat(self._data)
110
- self.callback()
111
- self.normalize()
112
-
113
- @w.setter
114
- def w(self, value):
115
- self.data.w = value
116
- if self.callback and abs(value - self.prev_data.w) > 1e-6:
117
- self.prev_data.w = value
118
- self.callback()
119
- self.normalize()
120
-
121
- @x.setter
122
- def x(self, value):
123
- self._data.x = value
124
- if self.callback and abs(value - self.prev_data.x) > 1e-6:
125
- self.prev_data.x = value
126
- self.callback()
127
- self.normalize()
128
-
129
- @y.setter
130
- def y(self, value):
131
- self._data.y = value
132
- if self.callback and abs(value - self.prev_data.y) > 1e-6:
133
- self.prev_data.y = value
134
- self.callback()
135
- self.normalize()
136
-
137
- @z.setter
138
- def z(self, value):
139
- self._data.z = value
140
- if self.callback and abs(value - self.prev_data.z) > 1e-6:
141
- self.prev_data.z = value
142
- self.callback()
1
+ import glm
2
+ import numpy as np
3
+ from .abstract_custom import Custom
4
+
5
+
6
+ class Quat(Custom):
7
+ def __init__(self, *args, callback=None):
8
+ self.callback = callback
9
+ self.prev_data = glm.quat(1, 0, 0, 0)
10
+
11
+ if len(args) == 1:
12
+
13
+ if isinstance(args[0], Quat):
14
+ self.data = glm.quat(args[0].data)
15
+ self.prev_data = glm.quat(args[0].prev_data)
16
+ self.callback = args[0].callback
17
+
18
+ elif isinstance(args[0], glm.quat):
19
+ self.data = args[0]
20
+
21
+ elif isinstance(args[0], tuple) or isinstance(args[0], list) or isinstance(args[0], np.ndarray):
22
+ assert 2 < len(args[0]) < 5, f'Quat: Expected 3 or 4 values from incoming vector, got {len(args[0])}'
23
+ self.data = glm.quat(args[0])
24
+
25
+ else:
26
+ try: self.data = glm.quat(args[0])
27
+ except: raise ValueError(f'Quat: Unexpected incoming quaternion type {args[0]}')
28
+
29
+ elif 2 < len(args) < 5: self.data = glm.quat(*args)
30
+ else: raise ValueError(f'Quat: Expected either a vector, quaternion, or 3 or 4 numbers, got {len(args)} values')
31
+
32
+ def apply_function(self, other, func, func_name):
33
+ quat = glm.quat(self.data)
34
+
35
+ if isinstance(other, (glm.vec3, glm.quat)):
36
+ quat = func(quat, other)
37
+
38
+ elif isinstance(other, (tuple, list, np.ndarray)):
39
+ assert 2 < len(other) < 5, f'Quat: Expected 3 or 4 values from incoming vector, got {len(other)}'
40
+ quat = func(quat, other)
41
+
42
+ elif isinstance(other, Custom):
43
+ quat = func(quat, other.data)
44
+
45
+ else:
46
+ try: quat = func(quat, other)
47
+ except: raise ValueError(f'Quat: Not an accepted type for {func_name}, got {type(other)}')
48
+ return Quat(quat)
49
+
50
+ # unary operators
51
+ def __neg__(self):
52
+ return Quat(-self.data, callback=self.callback)
53
+
54
+ def __abs__(self):
55
+ return Quat(abs(self.data), callback=self.callback)
56
+
57
+ # accessor functions
58
+ def __getitem__(self, index):
59
+ assert int(index) == index, f'Quat: index must be an int, got {type(index)}' # check if index is a float
60
+ assert 0 <= index <= 3, f'Quat: index out of bounds, got {index}'
61
+ return self.data[index]
62
+
63
+ def __setitem__(self, index, value):
64
+ assert int(index) == index, f'Quat: index must be an int, got {type(index)}' # check if index is a float
65
+ assert 0 <= index <= 3, f'Quat: index out of bounds, got {index}'
66
+ try: self.data[index] = value
67
+ except: raise ValueError(f'Quat: Invalid element type, got {type(value)}')
68
+
69
+ def __delitem__(self, index): # cannot delete an index from a quaternion, so we set the value to zero instead
70
+ assert int(index) == index, f'Quat: index must be an int, got {type(index)}' # check if index is a float
71
+ assert 0 <= index <= 3, f'Quat: index out of bounds, got {index}'
72
+ self.data[index] = 0
73
+
74
+ def __len__(self):
75
+ return 4
76
+
77
+ def __iter__(self):
78
+ return iter(self.data)
79
+
80
+ def __contains__(self, item):
81
+ return item in self.data
82
+
83
+ # override str operators
84
+ def __repr__(self):
85
+ return 'bsk' + str(self.data)
86
+
87
+ def __str__(self):
88
+ return 'bsk ' + str(self.data)
89
+
90
+ @property
91
+ def data(self): return self._data
92
+ @property
93
+ def w(self): return self.data.w
94
+ @property
95
+ def x(self): return self.data.x
96
+ @property
97
+ def y(self): return self.data.y
98
+ @property
99
+ def z(self): return self.data.z
100
+
101
+ @data.setter
102
+ def data(self, value: glm.vec3 | glm.quat):
103
+ self._data = glm.quat(value)
104
+ cur = self._data
105
+ prev = self.prev_data
106
+ thresh = 1e-6
107
+
108
+ if self.callback and (abs(cur.w - prev.w) > thresh or abs(cur.x - prev.x) > thresh or abs(cur.y - prev.y) > thresh or abs(cur.z - prev.z) > thresh):
109
+ self.prev_data = glm.quat(self._data)
110
+ self.callback()
111
+ self.normalize()
112
+
113
+ @w.setter
114
+ def w(self, value):
115
+ self.data.w = value
116
+ if self.callback and abs(value - self.prev_data.w) > 1e-6:
117
+ self.prev_data.w = value
118
+ self.callback()
119
+ self.normalize()
120
+
121
+ @x.setter
122
+ def x(self, value):
123
+ self._data.x = value
124
+ if self.callback and abs(value - self.prev_data.x) > 1e-6:
125
+ self.prev_data.x = value
126
+ self.callback()
127
+ self.normalize()
128
+
129
+ @y.setter
130
+ def y(self, value):
131
+ self._data.y = value
132
+ if self.callback and abs(value - self.prev_data.y) > 1e-6:
133
+ self.prev_data.y = value
134
+ self.callback()
135
+ self.normalize()
136
+
137
+ @z.setter
138
+ def z(self, value):
139
+ self._data.z = value
140
+ if self.callback and abs(value - self.prev_data.z) > 1e-6:
141
+ self.prev_data.z = value
142
+ self.callback()
143
143
  self.normalize()
@@ -1,8 +1,8 @@
1
- import glm
2
-
3
-
4
- def rotate_vec_by_quat(vec: glm.vec3, quat: glm.quat) -> glm.vec3:
5
- """
6
- Rotates a vector by a quaternion. Probably just dont use this, just a reminder of how glm works with quaternions
7
- """
1
+ import glm
2
+
3
+
4
+ def rotate_vec_by_quat(vec: glm.vec3, quat: glm.quat) -> glm.vec3:
5
+ """
6
+ Rotates a vector by a quaternion. Probably just dont use this, just a reminder of how glm works with quaternions
7
+ """
8
8
  return vec * quat
@@ -1,27 +1,27 @@
1
- import glm
2
- from ..nodes.node import Node
3
-
4
-
5
- class RaycastResult:
6
- node: Node | None
7
- """The node that the raycast hit. Is None if no object was hit"""
8
- position: glm.vec3
9
- """The node that the raycast hit"""
10
- normal: glm.vec3
11
- """The normal of the raycast hit"""
12
-
13
- def __init__(self, node: Node | None, position: glm.vec3, normal: glm.vec3):
14
- """
15
- Container for returning raycast results.
16
- Contains the node hit and the global position the raycast hit at.
17
- """
18
-
19
- self.node = node
20
- self.position = position
21
- self.normal = normal
22
-
23
- def __bool__(self):
24
- return bool(self.node)
25
-
26
- def __repr__(self):
1
+ import glm
2
+ from ..nodes.node import Node
3
+
4
+
5
+ class RaycastResult:
6
+ node: Node | None
7
+ """The node that the raycast hit. Is None if no object was hit"""
8
+ position: glm.vec3
9
+ """The node that the raycast hit"""
10
+ normal: glm.vec3
11
+ """The normal of the raycast hit"""
12
+
13
+ def __init__(self, node: Node | None, position: glm.vec3, normal: glm.vec3):
14
+ """
15
+ Container for returning raycast results.
16
+ Contains the node hit and the global position the raycast hit at.
17
+ """
18
+
19
+ self.node = node
20
+ self.position = position
21
+ self.normal = normal
22
+
23
+ def __bool__(self):
24
+ return bool(self.node)
25
+
26
+ def __repr__(self):
27
27
  return f'<Raycast | Node: {self.node}, Position: {self.position}, Normal: {self.normal}>'
basilisk/generic/vec3.py CHANGED
@@ -1,144 +1,144 @@
1
- import glm
2
- import numpy as np
3
- from .abstract_custom import Custom
4
-
5
- class Vec3(Custom):
6
- def __init__(self, *args, callback=None):
7
- self.callback = callback
8
- self.prev_data = glm.vec3(0.0)
9
-
10
- if len(args) == 1:
11
-
12
- if isinstance(args[0], Vec3):
13
- self.data = glm.vec3(args[0].data)
14
- self.prev_data = glm.vec3(args[0].prev_data)
15
- self.callback = args[0].callback
16
-
17
- elif isinstance(args[0], glm.vec3):
18
- self.data = args[0]
19
-
20
- elif isinstance(args[0], tuple) or isinstance(args[0], list) or isinstance(args[0], np.ndarray):
21
- assert len(args[0]) == 3, f'Vec3: Expected 3 values from incoming vector, got {len(args[0])}'
22
- self.data = glm.vec3(args[0])
23
-
24
- else:
25
- try: self.data = glm.vec3(args[0])
26
- except: raise ValueError(f'Vec3: Unexpected incoming vector type {args[0]}')
27
-
28
- elif len(args) == 3: self.data = glm.vec3(*args)
29
- else: raise ValueError(f'Vec3: Expected either 1 vector or 3 numbers, got {len(args)} values')
30
-
31
- def apply_function(self, other, func, func_name):
32
- vec = glm.vec3(self.data)
33
-
34
- if isinstance(other, (glm.vec3, glm.quat)):
35
- vec = func(vec, other)
36
-
37
- elif isinstance(other, tuple) or isinstance(other, list) or isinstance(other, np.ndarray):
38
- assert len(other) == 3, f'Vec3: Number of added values must be 3, got {len(other)}'
39
- vec = func(vec, other)
40
-
41
- elif isinstance(other, Custom): # perserve self.callback over other.callback. this should never be done by the user
42
- vec = func(vec, other.data)
43
-
44
- else:
45
- try: vec = func(vec, other)
46
- except: raise ValueError(f'Vec3: Not an accepted type for {func_name}, got {type(other)}')
47
- return Vec3(vec)
48
-
49
- # unary operators
50
- def __neg__(self):
51
- return Vec3(-self.data, callback=self.callback)
52
-
53
- def __abs__(self):
54
- return Vec3(abs(self.data), callback=self.callback)
55
-
56
- # accessor functions
57
- def __getitem__(self, index):
58
- assert int(index) == index, f'Vec3: index must be an int, got {type(index)}' # check if index is a float
59
- assert 0 <= index <= 2, f'Vec3: index out of bounds, got {index}'
60
- return self.data[index]
61
-
62
- def __setitem__(self, index, value):
63
- assert int(index) == index, f'Vec3: index must be an int, got {type(index)}' # check if index is a float
64
- assert 0 <= index <= 2, f'Vec3: index out of bounds, got {index}'
65
- try: self.data[index] = value
66
- except: raise ValueError(f'Vec3: Invalid element type, got {type(value)}')
67
-
68
- def __delitem__(self, index): # index in a vec cannot be deleted, so we default to zero
69
- assert int(index) == index, f'Vec3: index must be an int, got {type(index)}' # check if index is a float
70
- assert 0 <= index <= 2, f'Vec3: index out of bounds, got {index}'
71
- self.data[index] = 0
72
-
73
- def __len__(self):
74
- return 3
75
-
76
- def __iter__(self):
77
- return iter(self.data)
78
-
79
- def __contains__(self, item):
80
- return item in self.data
81
-
82
- # override str operators
83
- def __repr__(self):
84
- return 'bsk ' + str(self.data)
85
-
86
- def __str__(self):
87
- return 'bsk ' + str(self.data)
88
-
89
- @property
90
- def data(self): return self._data
91
- @property
92
- def x(self): return self.data.x
93
- @property
94
- def y(self): return self.data.y
95
- @property
96
- def z(self): return self.data.z
97
-
98
- @data.setter
99
- def data(self, value: glm.vec3):
100
- self._data = glm.vec3(value)
101
- cur = self._data
102
- prev = self.prev_data
103
- thresh = 1e-6
104
-
105
- if self.callback and (abs(cur.x - prev.x) > thresh or abs(cur.y - prev.y) > thresh or abs(cur.z - prev.z) > thresh):
106
- self.prev_data = glm.vec3(self._data)
107
- self.callback()
108
-
109
- @x.setter
110
- def x(self, value):
111
- self._data.x = value
112
- if self.callback and abs(value - self.prev_data.x) > 1e-6:
113
- self.prev_data.x = value
114
- self.callback()
115
-
116
- @y.setter
117
- def y(self, value):
118
- self._data.y = value
119
- if self.callback and abs(value - self.prev_data.y) > 1e-6:
120
- self.prev_data.y = value
121
- self.callback()
122
-
123
- @z.setter
124
- def z(self, value):
125
- self._data.z = value
126
- if self.callback and abs(value - self.prev_data.z) > 1e-6:
127
- self.prev_data.z = value
128
- self.callback()
129
-
130
- class Node():
131
-
132
- def __init__(self, pos):
133
-
134
- def callback(): print('calling back')
135
- self.pos_callback = callback
136
- self._pos = Vec3(pos, callback=self.pos_callback)
137
-
138
- @property
139
- def pos(self): return self._pos
140
-
141
- @pos.setter
142
- def pos(self, value):
143
- if isinstance(value, Vec3): self._pos.data = value.data
1
+ import glm
2
+ import numpy as np
3
+ from .abstract_custom import Custom
4
+
5
+ class Vec3(Custom):
6
+ def __init__(self, *args, callback=None):
7
+ self.callback = callback
8
+ self.prev_data = glm.vec3(0.0)
9
+
10
+ if len(args) == 1:
11
+
12
+ if isinstance(args[0], Vec3):
13
+ self.data = glm.vec3(args[0].data)
14
+ self.prev_data = glm.vec3(args[0].prev_data)
15
+ self.callback = args[0].callback
16
+
17
+ elif isinstance(args[0], glm.vec3):
18
+ self.data = args[0]
19
+
20
+ elif isinstance(args[0], tuple) or isinstance(args[0], list) or isinstance(args[0], np.ndarray):
21
+ assert len(args[0]) == 3, f'Vec3: Expected 3 values from incoming vector, got {len(args[0])}'
22
+ self.data = glm.vec3(args[0])
23
+
24
+ else:
25
+ try: self.data = glm.vec3(args[0])
26
+ except: raise ValueError(f'Vec3: Unexpected incoming vector type {args[0]}')
27
+
28
+ elif len(args) == 3: self.data = glm.vec3(*args)
29
+ else: raise ValueError(f'Vec3: Expected either 1 vector or 3 numbers, got {len(args)} values')
30
+
31
+ def apply_function(self, other, func, func_name):
32
+ vec = glm.vec3(self.data)
33
+
34
+ if isinstance(other, (glm.vec3, glm.quat)):
35
+ vec = func(vec, other)
36
+
37
+ elif isinstance(other, tuple) or isinstance(other, list) or isinstance(other, np.ndarray):
38
+ assert len(other) == 3, f'Vec3: Number of added values must be 3, got {len(other)}'
39
+ vec = func(vec, other)
40
+
41
+ elif isinstance(other, Custom): # perserve self.callback over other.callback. this should never be done by the user
42
+ vec = func(vec, other.data)
43
+
44
+ else:
45
+ try: vec = func(vec, other)
46
+ except: raise ValueError(f'Vec3: Not an accepted type for {func_name}, got {type(other)}')
47
+ return Vec3(vec)
48
+
49
+ # unary operators
50
+ def __neg__(self):
51
+ return Vec3(-self.data, callback=self.callback)
52
+
53
+ def __abs__(self):
54
+ return Vec3(abs(self.data), callback=self.callback)
55
+
56
+ # accessor functions
57
+ def __getitem__(self, index):
58
+ assert int(index) == index, f'Vec3: index must be an int, got {type(index)}' # check if index is a float
59
+ assert 0 <= index <= 2, f'Vec3: index out of bounds, got {index}'
60
+ return self.data[index]
61
+
62
+ def __setitem__(self, index, value):
63
+ assert int(index) == index, f'Vec3: index must be an int, got {type(index)}' # check if index is a float
64
+ assert 0 <= index <= 2, f'Vec3: index out of bounds, got {index}'
65
+ try: self.data[index] = value
66
+ except: raise ValueError(f'Vec3: Invalid element type, got {type(value)}')
67
+
68
+ def __delitem__(self, index): # index in a vec cannot be deleted, so we default to zero
69
+ assert int(index) == index, f'Vec3: index must be an int, got {type(index)}' # check if index is a float
70
+ assert 0 <= index <= 2, f'Vec3: index out of bounds, got {index}'
71
+ self.data[index] = 0
72
+
73
+ def __len__(self):
74
+ return 3
75
+
76
+ def __iter__(self):
77
+ return iter(self.data)
78
+
79
+ def __contains__(self, item):
80
+ return item in self.data
81
+
82
+ # override str operators
83
+ def __repr__(self):
84
+ return 'bsk ' + str(self.data)
85
+
86
+ def __str__(self):
87
+ return 'bsk ' + str(self.data)
88
+
89
+ @property
90
+ def data(self): return self._data
91
+ @property
92
+ def x(self): return self.data.x
93
+ @property
94
+ def y(self): return self.data.y
95
+ @property
96
+ def z(self): return self.data.z
97
+
98
+ @data.setter
99
+ def data(self, value: glm.vec3):
100
+ self._data = glm.vec3(value)
101
+ cur = self._data
102
+ prev = self.prev_data
103
+ thresh = 1e-6
104
+
105
+ if self.callback and (abs(cur.x - prev.x) > thresh or abs(cur.y - prev.y) > thresh or abs(cur.z - prev.z) > thresh):
106
+ self.prev_data = glm.vec3(self._data)
107
+ self.callback()
108
+
109
+ @x.setter
110
+ def x(self, value):
111
+ self._data.x = value
112
+ if self.callback and abs(value - self.prev_data.x) > 1e-6:
113
+ self.prev_data.x = value
114
+ self.callback()
115
+
116
+ @y.setter
117
+ def y(self, value):
118
+ self._data.y = value
119
+ if self.callback and abs(value - self.prev_data.y) > 1e-6:
120
+ self.prev_data.y = value
121
+ self.callback()
122
+
123
+ @z.setter
124
+ def z(self, value):
125
+ self._data.z = value
126
+ if self.callback and abs(value - self.prev_data.z) > 1e-6:
127
+ self.prev_data.z = value
128
+ self.callback()
129
+
130
+ class Node():
131
+
132
+ def __init__(self, pos):
133
+
134
+ def callback(): print('calling back')
135
+ self.pos_callback = callback
136
+ self._pos = Vec3(pos, callback=self.pos_callback)
137
+
138
+ @property
139
+ def pos(self): return self._pos
140
+
141
+ @pos.setter
142
+ def pos(self, value):
143
+ if isinstance(value, Vec3): self._pos.data = value.data
144
144
  else: self._pos.data = value