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