basilisk-engine 0.1.8__py3-none-any.whl → 0.1.10__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 (87) hide show
  1. basilisk/__init__.py +14 -14
  2. basilisk/audio/sound.py +28 -32
  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 +224 -224
  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 +2 -2
  18. basilisk/draw/draw.py +100 -100
  19. basilisk/draw/draw_handler.py +179 -179
  20. basilisk/draw/font_renderer.py +28 -28
  21. basilisk/engine.py +206 -202
  22. basilisk/generic/abstract_bvh.py +15 -15
  23. basilisk/generic/abstract_custom.py +133 -133
  24. basilisk/generic/collisions.py +72 -72
  25. basilisk/generic/input_validation.py +66 -66
  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 +23 -23
  32. basilisk/generic/vec3.py +143 -143
  33. basilisk/input/mouse.py +61 -61
  34. basilisk/input/path.py +14 -14
  35. basilisk/mesh/cube.py +33 -33
  36. basilisk/mesh/mesh.py +230 -230
  37. basilisk/mesh/mesh_from_data.py +130 -130
  38. basilisk/mesh/model.py +271 -271
  39. basilisk/mesh/narrow_aabb.py +89 -89
  40. basilisk/mesh/narrow_bvh.py +91 -91
  41. basilisk/mesh/narrow_primative.py +23 -23
  42. basilisk/nodes/helper.py +28 -28
  43. basilisk/nodes/node.py +682 -682
  44. basilisk/nodes/node_handler.py +95 -95
  45. basilisk/particles/particle_handler.py +63 -63
  46. basilisk/particles/particle_renderer.py +87 -87
  47. basilisk/physics/impulse.py +112 -112
  48. basilisk/physics/physics_body.py +43 -43
  49. basilisk/physics/physics_engine.py +35 -35
  50. basilisk/render/batch.py +86 -86
  51. basilisk/render/camera.py +206 -206
  52. basilisk/render/chunk.py +99 -99
  53. basilisk/render/chunk_handler.py +154 -154
  54. basilisk/render/frame.py +101 -101
  55. basilisk/render/framebuffer.py +130 -130
  56. basilisk/render/image.py +87 -87
  57. basilisk/render/image_handler.py +122 -122
  58. basilisk/render/light.py +96 -96
  59. basilisk/render/light_handler.py +58 -58
  60. basilisk/render/material.py +219 -219
  61. basilisk/render/material_handler.py +135 -135
  62. basilisk/render/post_process.py +132 -132
  63. basilisk/render/shader.py +109 -109
  64. basilisk/render/shader_handler.py +79 -79
  65. basilisk/render/sky.py +120 -120
  66. basilisk/scene.py +264 -264
  67. basilisk/shaders/batch.frag +276 -276
  68. basilisk/shaders/batch.vert +115 -115
  69. basilisk/shaders/crt.frag +31 -31
  70. basilisk/shaders/draw.frag +21 -21
  71. basilisk/shaders/draw.vert +21 -21
  72. basilisk/shaders/filter.frag +22 -22
  73. basilisk/shaders/frame.frag +12 -12
  74. basilisk/shaders/frame.vert +13 -13
  75. basilisk/shaders/geometry.frag +8 -8
  76. basilisk/shaders/geometry.vert +41 -41
  77. basilisk/shaders/normal.frag +59 -59
  78. basilisk/shaders/normal.vert +96 -96
  79. basilisk/shaders/particle.frag +71 -71
  80. basilisk/shaders/particle.vert +84 -84
  81. basilisk/shaders/sky.frag +9 -9
  82. basilisk/shaders/sky.vert +13 -13
  83. {basilisk_engine-0.1.8.dist-info → basilisk_engine-0.1.10.dist-info}/METADATA +45 -39
  84. basilisk_engine-0.1.10.dist-info/RECORD +103 -0
  85. {basilisk_engine-0.1.8.dist-info → basilisk_engine-0.1.10.dist-info}/WHEEL +1 -1
  86. basilisk_engine-0.1.8.dist-info/RECORD +0 -103
  87. {basilisk_engine-0.1.8.dist-info → basilisk_engine-0.1.10.dist-info}/top_level.txt +0 -0
basilisk/scene.py CHANGED
@@ -1,265 +1,265 @@
1
- import moderngl as mgl
2
- import glm
3
-
4
- from .mesh.mesh import Mesh
5
- from .render.material import Material
6
- from .render.shader_handler import ShaderHandler
7
- from .render.material_handler import MaterialHandler
8
- from .render.light_handler import LightHandler
9
- from .render.camera import Camera, FreeCamera
10
- from .nodes.node_handler import NodeHandler
11
- from .physics.physics_engine import PhysicsEngine
12
- from .collisions.collider_handler import ColliderHandler
13
- from .draw.draw_handler import DrawHandler
14
- from .render.sky import Sky
15
- from .render.frame import Frame
16
- from .particles.particle_handler import ParticleHandler
17
- from .nodes.node import Node
18
- from .generic.collisions import moller_trumbore
19
- from .generic.raycast_result import RaycastResult
20
- from .render.post_process import PostProcess
21
- from .render.framebuffer import Framebuffer
22
-
23
- class Scene():
24
- engine: any
25
- """Parent engine of the scene"""
26
- ctx: mgl.Context
27
- """Reference to the engine context"""
28
-
29
- def __init__(self) -> None:
30
- """
31
- Basilisk scene object. Contains all nodes for the scene
32
- """
33
-
34
- self.engine = None
35
- self.ctx = None
36
-
37
- self.camera = None
38
- self.shader_handler = None
39
- self.node_handler = None
40
- self.material_handler = None
41
- self.light_handler = None
42
- self.draw_handler = None
43
- self.sky = None
44
- self.frame = None
45
-
46
- def update(self) -> None:
47
- """
48
- Updates the physics and in the scene
49
- """
50
- self.particle.update()
51
- self.camera.update()
52
-
53
-
54
- self.node_handler.update()
55
- if self.engine.delta_time < 0.5: # TODO this will cause physics to slow down when on low frame rate, this is probabl;y acceptable
56
- self.collider_handler.resolve_collisions()
57
-
58
- def render(self, render_target: Framebuffer|Frame=None) -> None:
59
- """
60
- Renders all the nodes with meshes in the scene
61
- """
62
-
63
- if render_target:
64
- show = False
65
- else:
66
- render_target = self.frame
67
- show = True
68
-
69
- render_target.use()
70
- render_target.clear()
71
- self.shader_handler.write()
72
- if self.sky: self.sky.render()
73
- self.node_handler.render()
74
- self.particle.render()
75
- self.draw_handler.render()
76
-
77
- if self.engine.headless or not show: return
78
- self.frame.render()
79
-
80
- def add(self, *objects: Node | None) -> None | Node | list:
81
- """
82
- Adds the given object(s) to the scene. Can pass in any scene objects:
83
- Argument overloads:
84
- object: Node - Adds the given node to the scene.
85
- """
86
-
87
- # List of all return values for the added objects
88
- returns = []
89
-
90
- # Loop through all objects passed in
91
- for bsk_object in objects:
92
-
93
- # Considered well defined behavior to add None
94
- if isinstance(bsk_object, type(None)):
95
- continue
96
-
97
- # Add a node to the scene
98
- elif isinstance(bsk_object, Node):
99
- returns.append(self.node_handler.add(bsk_object)); continue
100
-
101
- # Add a node to the scene
102
- elif isinstance(bsk_object, PostProcess):
103
- returns.append(self.frame.add_post_process(bsk_object)); continue
104
-
105
-
106
- # Recived incompatable type
107
- else:
108
- raise ValueError(f'scene.add: Incompatable object add type {type(bsk_object)}')
109
-
110
- # Return based on what the user passed in
111
- if not returns: return None
112
- if len(returns) == 1: return returns[0]
113
- return returns
114
-
115
- def remove(self, *objects: Node | None) -> None | Node | list:
116
- """
117
- Removes the given baskilsk object from the scene
118
- """
119
-
120
- # List of all return values for the added objects
121
- returns = []
122
-
123
- # Loop through all objects passed in
124
- for bsk_object in objects:
125
-
126
- # Considered well defined behavior to remove None
127
- if isinstance(bsk_object, type(None)):
128
- continue
129
-
130
- # Remove a node from the scene
131
- elif isinstance(bsk_object, Node):
132
- returns.append(self.node_handler.remove(bsk_object)); continue
133
-
134
- # Recived incompatable type
135
- else:
136
- raise ValueError(f'scene.remove: Incompatable object remove type {type(bsk_object)}')
137
-
138
- # Return based on what the user passed in
139
- if not returns: return None
140
- if len(returns) == 1: return returns[0]
141
- return returns
142
-
143
- def set_engine(self, engine: any) -> None:
144
- """
145
- Sets the back references to the engine and creates handlers with the context
146
- """
147
-
148
- self.engine = engine
149
- self.ctx = engine.ctx
150
-
151
- self.camera = FreeCamera()
152
- self.shader_handler = ShaderHandler(self)
153
- self.material_handler = MaterialHandler(self)
154
- self.light_handler = LightHandler(self)
155
- self.physics_engine = PhysicsEngine()
156
- self.node_handler = NodeHandler(self)
157
- self.particle = ParticleHandler(self)
158
- self.collider_handler = ColliderHandler(self)
159
- self.draw_handler = DrawHandler(self)
160
- self.frame = Frame(self)
161
- self.sky = Sky(self.engine)
162
-
163
- def raycast(self, position: glm.vec3=None, forward: glm.vec3=None, max_distance: float=1e5, has_collisions: bool=None, has_physics: bool=None, tags: list[str]=[]) -> RaycastResult:
164
- """
165
- Ray cast from any posiiton and forward vector and returns a RaycastResult eith the nearest node.
166
- If no position or forward is given, uses the scene camera's current position and forward
167
- """
168
- if not position: position = self.camera.position
169
- if not forward: forward = self.camera.forward
170
- forward = glm.normalize(forward)
171
-
172
- # if we are filtering for collisions, use the broad BVH to improve performance
173
- if has_collisions:
174
- colliders = self.collider_handler.bvh.get_line_collided(position, forward)
175
- nodes = [collider.node for collider in colliders]
176
-
177
- def is_valid(node: Node) -> bool:
178
- return all([
179
- has_collisions is None or bool(node.collider) == has_collisions,
180
- has_physics is None or bool(node.physics_body) == has_physics,
181
- all(tag in node.tags for tag in tags)
182
- ])
183
-
184
- nodes: list[Node] = list(filter(lambda node: is_valid(node), nodes))
185
-
186
- # if we are not filtering for collisions, filter nodes and
187
- else: nodes = self.node_handler.get_all(collisions=has_collisions, physics=has_physics, tags=tags)
188
-
189
- # determine closest node
190
- best_distance, best_point, best_node = max_distance, None, None
191
- position_two = position + forward
192
- for node in nodes:
193
-
194
- inv_mat = glm.inverse(node.model_matrix)
195
- relative_position = inv_mat * position
196
- relative_forward = glm.normalize(inv_mat * position_two - relative_position)
197
-
198
- triangles = [node.mesh.indices[i] for i in node.mesh.get_line_collided(relative_position, relative_forward)]
199
-
200
- for triangle in triangles:
201
- intersection = moller_trumbore(relative_position, relative_forward, [node.mesh.points[i] for i in triangle])
202
- if not intersection: continue
203
- intersection = node.model_matrix * intersection
204
- distance = glm.length(intersection - position)
205
- if distance < best_distance:
206
- best_distance = distance
207
- best_point = intersection
208
- best_node = node
209
-
210
- return RaycastResult(best_node, best_point)
211
-
212
- def raycast_mouse(self, position: tuple[int, int] | glm.vec2, max_distance: float=1e5, has_collisions: bool=None, has_pshyics: bool=None, tags: list[str]=[]) -> RaycastResult:
213
- """
214
- Ray casts from the mouse position with respect to the camera. Returns the nearest node that was clicked, if none was clicked, returns None.
215
- """
216
- # derive forward vector from mouse click position
217
- position = glm.vec2(position)
218
- inv_proj, inv_view = glm.inverse(self.camera.m_proj), glm.inverse(self.camera.m_view)
219
- ndc = glm.vec4(2 * position[0] / self.engine.win_size[0] - 1, 1 - 2 * position[1] / self.engine.win_size[1], 1, 1)
220
- point = inv_proj * ndc
221
- point /= point.w
222
- forward = glm.normalize(glm.vec3(inv_view * glm.vec4(point.x, point.y, point.z, 0)))
223
-
224
- return self.raycast(
225
- position=self.camera.position,
226
- forward=forward,
227
- max_distance=max_distance,
228
- has_collisions=has_collisions,
229
- has_physics=has_pshyics,
230
- tags=tags
231
- )
232
-
233
- def get(self, position: glm.vec3=None, scale: glm.vec3=None, rotation: glm.quat=None, forward: glm.vec3=None, mesh: Mesh=None, material: Material=None, velocity: glm.vec3=None, rotational_velocity: glm.quat=None, physics: bool=None, mass: float=None, collisions: bool=None, static_friction: float=None, kinetic_friction: float=None, elasticity: float=None, collision_group: float=None, name: str=None, tags: list[str]=None,static: bool=None) -> Node:
234
- """
235
- Returns the first node with the given traits
236
- """
237
- self.node_handler.get(position, scale, rotation, forward, mesh, material, velocity, rotational_velocity, physics, mass, collisions, static_friction, kinetic_friction, elasticity, collision_group, name, tags, static)
238
-
239
- def get_all(self, position: glm.vec3=None, scale: glm.vec3=None, rotation: glm.quat=None, forward: glm.vec3=None, mesh: Mesh=None, material: Material=None, velocity: glm.vec3=None, rotational_velocity: glm.quat=None, physics: bool=None, mass: float=None, collisions: bool=None, static_friction: float=None, kinetic_friction: float=None, elasticity: float=None, collision_group: float=None, name: str=None, tags: list[str]=None,static: bool=None) -> list[Node]:
240
- """
241
- Returns all nodes with the given traits
242
- """
243
- self.node_handler.get_all(position, scale, rotation, forward, mesh, material, velocity, rotational_velocity, physics, mass, collisions, static_friction, kinetic_friction, elasticity, collision_group, name, tags, static)
244
-
245
- @property
246
- def camera(self): return self._camera
247
- @property
248
- def sky(self): return self._sky
249
- @property
250
- def nodes(self): return self.node_handler.nodes
251
-
252
- @camera.setter
253
- def camera(self, value: Camera):
254
- if not value: return
255
- if not isinstance(value, Camera):
256
- raise TypeError(f'Scene: Invalid camera type: {type(value)}. Expected type bsk.Camera')
257
- self._camera = value
258
- self._camera.scene = self
259
-
260
- @sky.setter
261
- def sky(self, value: Sky):
262
- if not isinstance(value, Sky) and not isinstance(value, type(None)):
263
- raise TypeError(f'Scene: Invalid sky type: {type(value)}. Expected type bsk.Sky or None')
264
- self._sky = value
1
+ import moderngl as mgl
2
+ import glm
3
+
4
+ from .mesh.mesh import Mesh
5
+ from .render.material import Material
6
+ from .render.shader_handler import ShaderHandler
7
+ from .render.material_handler import MaterialHandler
8
+ from .render.light_handler import LightHandler
9
+ from .render.camera import Camera, FreeCamera
10
+ from .nodes.node_handler import NodeHandler
11
+ from .physics.physics_engine import PhysicsEngine
12
+ from .collisions.collider_handler import ColliderHandler
13
+ from .draw.draw_handler import DrawHandler
14
+ from .render.sky import Sky
15
+ from .render.frame import Frame
16
+ from .particles.particle_handler import ParticleHandler
17
+ from .nodes.node import Node
18
+ from .generic.collisions import moller_trumbore
19
+ from .generic.raycast_result import RaycastResult
20
+ from .render.post_process import PostProcess
21
+ from .render.framebuffer import Framebuffer
22
+
23
+ class Scene():
24
+ engine: any
25
+ """Parent engine of the scene"""
26
+ ctx: mgl.Context
27
+ """Reference to the engine context"""
28
+
29
+ def __init__(self) -> None:
30
+ """
31
+ Basilisk scene object. Contains all nodes for the scene
32
+ """
33
+
34
+ self.engine = None
35
+ self.ctx = None
36
+
37
+ self.camera = None
38
+ self.shader_handler = None
39
+ self.node_handler = None
40
+ self.material_handler = None
41
+ self.light_handler = None
42
+ self.draw_handler = None
43
+ self.sky = None
44
+ self.frame = None
45
+
46
+ def update(self) -> None:
47
+ """
48
+ Updates the physics and in the scene
49
+ """
50
+ self.particle.update()
51
+ self.camera.update()
52
+
53
+
54
+ self.node_handler.update()
55
+ if self.engine.delta_time < 0.5: # TODO this will cause physics to slow down when on low frame rate, this is probabl;y acceptable
56
+ self.collider_handler.resolve_collisions()
57
+
58
+ def render(self, render_target: Framebuffer|Frame=None) -> None:
59
+ """
60
+ Renders all the nodes with meshes in the scene
61
+ """
62
+
63
+ if render_target:
64
+ show = False
65
+ else:
66
+ render_target = self.frame
67
+ show = True
68
+
69
+ render_target.use()
70
+ render_target.clear()
71
+ self.shader_handler.write()
72
+ if self.sky: self.sky.render()
73
+ self.node_handler.render()
74
+ self.particle.render()
75
+ self.draw_handler.render()
76
+
77
+ if self.engine.headless or not show: return
78
+ self.frame.render()
79
+
80
+ def add(self, *objects: Node | None) -> None | Node | list:
81
+ """
82
+ Adds the given object(s) to the scene. Can pass in any scene objects:
83
+ Argument overloads:
84
+ object: Node - Adds the given node to the scene.
85
+ """
86
+
87
+ # List of all return values for the added objects
88
+ returns = []
89
+
90
+ # Loop through all objects passed in
91
+ for bsk_object in objects:
92
+
93
+ # Considered well defined behavior to add None
94
+ if isinstance(bsk_object, type(None)):
95
+ continue
96
+
97
+ # Add a node to the scene
98
+ elif isinstance(bsk_object, Node):
99
+ returns.append(self.node_handler.add(bsk_object)); continue
100
+
101
+ # Add a node to the scene
102
+ elif isinstance(bsk_object, PostProcess):
103
+ returns.append(self.frame.add_post_process(bsk_object)); continue
104
+
105
+
106
+ # Recived incompatable type
107
+ else:
108
+ raise ValueError(f'scene.add: Incompatable object add type {type(bsk_object)}')
109
+
110
+ # Return based on what the user passed in
111
+ if not returns: return None
112
+ if len(returns) == 1: return returns[0]
113
+ return returns
114
+
115
+ def remove(self, *objects: Node | None) -> None | Node | list:
116
+ """
117
+ Removes the given baskilsk object from the scene
118
+ """
119
+
120
+ # List of all return values for the added objects
121
+ returns = []
122
+
123
+ # Loop through all objects passed in
124
+ for bsk_object in objects:
125
+
126
+ # Considered well defined behavior to remove None
127
+ if isinstance(bsk_object, type(None)):
128
+ continue
129
+
130
+ # Remove a node from the scene
131
+ elif isinstance(bsk_object, Node):
132
+ returns.append(self.node_handler.remove(bsk_object)); continue
133
+
134
+ # Recived incompatable type
135
+ else:
136
+ raise ValueError(f'scene.remove: Incompatable object remove type {type(bsk_object)}')
137
+
138
+ # Return based on what the user passed in
139
+ if not returns: return None
140
+ if len(returns) == 1: return returns[0]
141
+ return returns
142
+
143
+ def set_engine(self, engine: any) -> None:
144
+ """
145
+ Sets the back references to the engine and creates handlers with the context
146
+ """
147
+
148
+ self.engine = engine
149
+ self.ctx = engine.ctx
150
+
151
+ self.camera = FreeCamera()
152
+ self.shader_handler = ShaderHandler(self)
153
+ self.material_handler = MaterialHandler(self)
154
+ self.light_handler = LightHandler(self)
155
+ self.physics_engine = PhysicsEngine()
156
+ self.node_handler = NodeHandler(self)
157
+ self.particle = ParticleHandler(self)
158
+ self.collider_handler = ColliderHandler(self)
159
+ self.draw_handler = DrawHandler(self)
160
+ self.frame = Frame(self)
161
+ self.sky = Sky(self.engine)
162
+
163
+ def raycast(self, position: glm.vec3=None, forward: glm.vec3=None, max_distance: float=1e5, has_collisions: bool=None, has_physics: bool=None, tags: list[str]=[]) -> RaycastResult:
164
+ """
165
+ Ray cast from any posiiton and forward vector and returns a RaycastResult eith the nearest node.
166
+ If no position or forward is given, uses the scene camera's current position and forward
167
+ """
168
+ if not position: position = self.camera.position
169
+ if not forward: forward = self.camera.forward
170
+ forward = glm.normalize(forward)
171
+
172
+ # if we are filtering for collisions, use the broad BVH to improve performance
173
+ if has_collisions:
174
+ colliders = self.collider_handler.bvh.get_line_collided(position, forward)
175
+ nodes = [collider.node for collider in colliders]
176
+
177
+ def is_valid(node: Node) -> bool:
178
+ return all([
179
+ has_collisions is None or bool(node.collider) == has_collisions,
180
+ has_physics is None or bool(node.physics_body) == has_physics,
181
+ all(tag in node.tags for tag in tags)
182
+ ])
183
+
184
+ nodes: list[Node] = list(filter(lambda node: is_valid(node), nodes))
185
+
186
+ # if we are not filtering for collisions, filter nodes and
187
+ else: nodes = self.node_handler.get_all(collisions=has_collisions, physics=has_physics, tags=tags)
188
+
189
+ # determine closest node
190
+ best_distance, best_point, best_node = max_distance, None, None
191
+ position_two = position + forward
192
+ for node in nodes:
193
+
194
+ inv_mat = glm.inverse(node.model_matrix)
195
+ relative_position = inv_mat * position
196
+ relative_forward = glm.normalize(inv_mat * position_two - relative_position)
197
+
198
+ triangles = [node.mesh.indices[i] for i in node.mesh.get_line_collided(relative_position, relative_forward)]
199
+
200
+ for triangle in triangles:
201
+ intersection = moller_trumbore(relative_position, relative_forward, [node.mesh.points[i] for i in triangle])
202
+ if not intersection: continue
203
+ intersection = node.model_matrix * intersection
204
+ distance = glm.length(intersection - position)
205
+ if distance < best_distance:
206
+ best_distance = distance
207
+ best_point = intersection
208
+ best_node = node
209
+
210
+ return RaycastResult(best_node, best_point)
211
+
212
+ def raycast_mouse(self, position: tuple[int, int] | glm.vec2, max_distance: float=1e5, has_collisions: bool=None, has_pshyics: bool=None, tags: list[str]=[]) -> RaycastResult:
213
+ """
214
+ Ray casts from the mouse position with respect to the camera. Returns the nearest node that was clicked, if none was clicked, returns None.
215
+ """
216
+ # derive forward vector from mouse click position
217
+ position = glm.vec2(position)
218
+ inv_proj, inv_view = glm.inverse(self.camera.m_proj), glm.inverse(self.camera.m_view)
219
+ ndc = glm.vec4(2 * position[0] / self.engine.win_size[0] - 1, 1 - 2 * position[1] / self.engine.win_size[1], 1, 1)
220
+ point = inv_proj * ndc
221
+ point /= point.w
222
+ forward = glm.normalize(glm.vec3(inv_view * glm.vec4(point.x, point.y, point.z, 0)))
223
+
224
+ return self.raycast(
225
+ position=self.camera.position,
226
+ forward=forward,
227
+ max_distance=max_distance,
228
+ has_collisions=has_collisions,
229
+ has_physics=has_pshyics,
230
+ tags=tags
231
+ )
232
+
233
+ def get(self, position: glm.vec3=None, scale: glm.vec3=None, rotation: glm.quat=None, forward: glm.vec3=None, mesh: Mesh=None, material: Material=None, velocity: glm.vec3=None, rotational_velocity: glm.quat=None, physics: bool=None, mass: float=None, collisions: bool=None, static_friction: float=None, kinetic_friction: float=None, elasticity: float=None, collision_group: float=None, name: str=None, tags: list[str]=None,static: bool=None) -> Node:
234
+ """
235
+ Returns the first node with the given traits
236
+ """
237
+ self.node_handler.get(position, scale, rotation, forward, mesh, material, velocity, rotational_velocity, physics, mass, collisions, static_friction, kinetic_friction, elasticity, collision_group, name, tags, static)
238
+
239
+ def get_all(self, position: glm.vec3=None, scale: glm.vec3=None, rotation: glm.quat=None, forward: glm.vec3=None, mesh: Mesh=None, material: Material=None, velocity: glm.vec3=None, rotational_velocity: glm.quat=None, physics: bool=None, mass: float=None, collisions: bool=None, static_friction: float=None, kinetic_friction: float=None, elasticity: float=None, collision_group: float=None, name: str=None, tags: list[str]=None,static: bool=None) -> list[Node]:
240
+ """
241
+ Returns all nodes with the given traits
242
+ """
243
+ self.node_handler.get_all(position, scale, rotation, forward, mesh, material, velocity, rotational_velocity, physics, mass, collisions, static_friction, kinetic_friction, elasticity, collision_group, name, tags, static)
244
+
245
+ @property
246
+ def camera(self): return self._camera
247
+ @property
248
+ def sky(self): return self._sky
249
+ @property
250
+ def nodes(self): return self.node_handler.nodes
251
+
252
+ @camera.setter
253
+ def camera(self, value: Camera):
254
+ if not value: return
255
+ if not isinstance(value, Camera):
256
+ raise TypeError(f'Scene: Invalid camera type: {type(value)}. Expected type bsk.Camera')
257
+ self._camera = value
258
+ self._camera.scene = self
259
+
260
+ @sky.setter
261
+ def sky(self, value: Sky):
262
+ if not isinstance(value, Sky) and not isinstance(value, type(None)):
263
+ raise TypeError(f'Scene: Invalid sky type: {type(value)}. Expected type bsk.Sky or None')
264
+ self._sky = value
265
265
  if value: self._sky.write()