1 | /**************************************************************************/ |
2 | /* godot_physics_server_3d.cpp */ |
3 | /**************************************************************************/ |
4 | /* This file is part of: */ |
5 | /* GODOT ENGINE */ |
6 | /* https://godotengine.org */ |
7 | /**************************************************************************/ |
8 | /* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ |
9 | /* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ |
10 | /* */ |
11 | /* Permission is hereby granted, free of charge, to any person obtaining */ |
12 | /* a copy of this software and associated documentation files (the */ |
13 | /* "Software"), to deal in the Software without restriction, including */ |
14 | /* without limitation the rights to use, copy, modify, merge, publish, */ |
15 | /* distribute, sublicense, and/or sell copies of the Software, and to */ |
16 | /* permit persons to whom the Software is furnished to do so, subject to */ |
17 | /* the following conditions: */ |
18 | /* */ |
19 | /* The above copyright notice and this permission notice shall be */ |
20 | /* included in all copies or substantial portions of the Software. */ |
21 | /* */ |
22 | /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ |
23 | /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ |
24 | /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ |
25 | /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ |
26 | /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ |
27 | /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ |
28 | /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ |
29 | /**************************************************************************/ |
30 | |
31 | #include "godot_physics_server_3d.h" |
32 | |
33 | #include "godot_body_direct_state_3d.h" |
34 | #include "godot_broad_phase_3d_bvh.h" |
35 | #include "joints/godot_cone_twist_joint_3d.h" |
36 | #include "joints/godot_generic_6dof_joint_3d.h" |
37 | #include "joints/godot_hinge_joint_3d.h" |
38 | #include "joints/godot_pin_joint_3d.h" |
39 | #include "joints/godot_slider_joint_3d.h" |
40 | |
41 | #include "core/debugger/engine_debugger.h" |
42 | #include "core/os/os.h" |
43 | |
44 | #define FLUSH_QUERY_CHECK(m_object) \ |
45 | ERR_FAIL_COND_MSG(m_object->get_space() && flushing_queries, "Can't change this state while flushing queries. Use call_deferred() or set_deferred() to change monitoring state instead."); |
46 | |
47 | RID GodotPhysicsServer3D::world_boundary_shape_create() { |
48 | GodotShape3D *shape = memnew(GodotWorldBoundaryShape3D); |
49 | RID rid = shape_owner.make_rid(shape); |
50 | shape->set_self(rid); |
51 | return rid; |
52 | } |
53 | RID GodotPhysicsServer3D::separation_ray_shape_create() { |
54 | GodotShape3D *shape = memnew(GodotSeparationRayShape3D); |
55 | RID rid = shape_owner.make_rid(shape); |
56 | shape->set_self(rid); |
57 | return rid; |
58 | } |
59 | RID GodotPhysicsServer3D::sphere_shape_create() { |
60 | GodotShape3D *shape = memnew(GodotSphereShape3D); |
61 | RID rid = shape_owner.make_rid(shape); |
62 | shape->set_self(rid); |
63 | return rid; |
64 | } |
65 | RID GodotPhysicsServer3D::box_shape_create() { |
66 | GodotShape3D *shape = memnew(GodotBoxShape3D); |
67 | RID rid = shape_owner.make_rid(shape); |
68 | shape->set_self(rid); |
69 | return rid; |
70 | } |
71 | RID GodotPhysicsServer3D::capsule_shape_create() { |
72 | GodotShape3D *shape = memnew(GodotCapsuleShape3D); |
73 | RID rid = shape_owner.make_rid(shape); |
74 | shape->set_self(rid); |
75 | return rid; |
76 | } |
77 | RID GodotPhysicsServer3D::cylinder_shape_create() { |
78 | GodotShape3D *shape = memnew(GodotCylinderShape3D); |
79 | RID rid = shape_owner.make_rid(shape); |
80 | shape->set_self(rid); |
81 | return rid; |
82 | } |
83 | RID GodotPhysicsServer3D::convex_polygon_shape_create() { |
84 | GodotShape3D *shape = memnew(GodotConvexPolygonShape3D); |
85 | RID rid = shape_owner.make_rid(shape); |
86 | shape->set_self(rid); |
87 | return rid; |
88 | } |
89 | RID GodotPhysicsServer3D::concave_polygon_shape_create() { |
90 | GodotShape3D *shape = memnew(GodotConcavePolygonShape3D); |
91 | RID rid = shape_owner.make_rid(shape); |
92 | shape->set_self(rid); |
93 | return rid; |
94 | } |
95 | RID GodotPhysicsServer3D::heightmap_shape_create() { |
96 | GodotShape3D *shape = memnew(GodotHeightMapShape3D); |
97 | RID rid = shape_owner.make_rid(shape); |
98 | shape->set_self(rid); |
99 | return rid; |
100 | } |
101 | RID GodotPhysicsServer3D::custom_shape_create() { |
102 | ERR_FAIL_V(RID()); |
103 | } |
104 | |
105 | void GodotPhysicsServer3D::shape_set_data(RID p_shape, const Variant &p_data) { |
106 | GodotShape3D *shape = shape_owner.get_or_null(p_shape); |
107 | ERR_FAIL_COND(!shape); |
108 | shape->set_data(p_data); |
109 | }; |
110 | |
111 | void GodotPhysicsServer3D::shape_set_custom_solver_bias(RID p_shape, real_t p_bias) { |
112 | GodotShape3D *shape = shape_owner.get_or_null(p_shape); |
113 | ERR_FAIL_COND(!shape); |
114 | shape->set_custom_bias(p_bias); |
115 | } |
116 | |
117 | PhysicsServer3D::ShapeType GodotPhysicsServer3D::shape_get_type(RID p_shape) const { |
118 | const GodotShape3D *shape = shape_owner.get_or_null(p_shape); |
119 | ERR_FAIL_COND_V(!shape, SHAPE_CUSTOM); |
120 | return shape->get_type(); |
121 | }; |
122 | |
123 | Variant GodotPhysicsServer3D::shape_get_data(RID p_shape) const { |
124 | const GodotShape3D *shape = shape_owner.get_or_null(p_shape); |
125 | ERR_FAIL_COND_V(!shape, Variant()); |
126 | ERR_FAIL_COND_V(!shape->is_configured(), Variant()); |
127 | return shape->get_data(); |
128 | }; |
129 | |
130 | void GodotPhysicsServer3D::shape_set_margin(RID p_shape, real_t p_margin) { |
131 | } |
132 | |
133 | real_t GodotPhysicsServer3D::shape_get_margin(RID p_shape) const { |
134 | return 0.0; |
135 | } |
136 | |
137 | real_t GodotPhysicsServer3D::shape_get_custom_solver_bias(RID p_shape) const { |
138 | const GodotShape3D *shape = shape_owner.get_or_null(p_shape); |
139 | ERR_FAIL_COND_V(!shape, 0); |
140 | return shape->get_custom_bias(); |
141 | } |
142 | |
143 | RID GodotPhysicsServer3D::space_create() { |
144 | GodotSpace3D *space = memnew(GodotSpace3D); |
145 | RID id = space_owner.make_rid(space); |
146 | space->set_self(id); |
147 | RID area_id = area_create(); |
148 | GodotArea3D *area = area_owner.get_or_null(area_id); |
149 | ERR_FAIL_COND_V(!area, RID()); |
150 | space->set_default_area(area); |
151 | area->set_space(space); |
152 | area->set_priority(-1); |
153 | RID sgb = body_create(); |
154 | body_set_space(sgb, id); |
155 | body_set_mode(sgb, BODY_MODE_STATIC); |
156 | space->set_static_global_body(sgb); |
157 | |
158 | return id; |
159 | }; |
160 | |
161 | void GodotPhysicsServer3D::space_set_active(RID p_space, bool p_active) { |
162 | GodotSpace3D *space = space_owner.get_or_null(p_space); |
163 | ERR_FAIL_COND(!space); |
164 | if (p_active) { |
165 | active_spaces.insert(space); |
166 | } else { |
167 | active_spaces.erase(space); |
168 | } |
169 | } |
170 | |
171 | bool GodotPhysicsServer3D::space_is_active(RID p_space) const { |
172 | const GodotSpace3D *space = space_owner.get_or_null(p_space); |
173 | ERR_FAIL_COND_V(!space, false); |
174 | |
175 | return active_spaces.has(space); |
176 | } |
177 | |
178 | void GodotPhysicsServer3D::space_set_param(RID p_space, SpaceParameter p_param, real_t p_value) { |
179 | GodotSpace3D *space = space_owner.get_or_null(p_space); |
180 | ERR_FAIL_COND(!space); |
181 | |
182 | space->set_param(p_param, p_value); |
183 | } |
184 | |
185 | real_t GodotPhysicsServer3D::space_get_param(RID p_space, SpaceParameter p_param) const { |
186 | const GodotSpace3D *space = space_owner.get_or_null(p_space); |
187 | ERR_FAIL_COND_V(!space, 0); |
188 | return space->get_param(p_param); |
189 | } |
190 | |
191 | PhysicsDirectSpaceState3D *GodotPhysicsServer3D::space_get_direct_state(RID p_space) { |
192 | GodotSpace3D *space = space_owner.get_or_null(p_space); |
193 | ERR_FAIL_COND_V(!space, nullptr); |
194 | ERR_FAIL_COND_V_MSG((using_threads && !doing_sync) || space->is_locked(), nullptr, "Space state is inaccessible right now, wait for iteration or physics process notification." ); |
195 | |
196 | return space->get_direct_state(); |
197 | } |
198 | |
199 | void GodotPhysicsServer3D::space_set_debug_contacts(RID p_space, int p_max_contacts) { |
200 | GodotSpace3D *space = space_owner.get_or_null(p_space); |
201 | ERR_FAIL_COND(!space); |
202 | space->set_debug_contacts(p_max_contacts); |
203 | } |
204 | |
205 | Vector<Vector3> GodotPhysicsServer3D::space_get_contacts(RID p_space) const { |
206 | GodotSpace3D *space = space_owner.get_or_null(p_space); |
207 | ERR_FAIL_COND_V(!space, Vector<Vector3>()); |
208 | return space->get_debug_contacts(); |
209 | } |
210 | |
211 | int GodotPhysicsServer3D::space_get_contact_count(RID p_space) const { |
212 | GodotSpace3D *space = space_owner.get_or_null(p_space); |
213 | ERR_FAIL_COND_V(!space, 0); |
214 | return space->get_debug_contact_count(); |
215 | } |
216 | |
217 | RID GodotPhysicsServer3D::area_create() { |
218 | GodotArea3D *area = memnew(GodotArea3D); |
219 | RID rid = area_owner.make_rid(area); |
220 | area->set_self(rid); |
221 | return rid; |
222 | } |
223 | |
224 | void GodotPhysicsServer3D::area_set_space(RID p_area, RID p_space) { |
225 | GodotArea3D *area = area_owner.get_or_null(p_area); |
226 | ERR_FAIL_COND(!area); |
227 | |
228 | GodotSpace3D *space = nullptr; |
229 | if (p_space.is_valid()) { |
230 | space = space_owner.get_or_null(p_space); |
231 | ERR_FAIL_COND(!space); |
232 | } |
233 | |
234 | if (area->get_space() == space) { |
235 | return; //pointless |
236 | } |
237 | |
238 | area->clear_constraints(); |
239 | area->set_space(space); |
240 | } |
241 | |
242 | RID GodotPhysicsServer3D::area_get_space(RID p_area) const { |
243 | GodotArea3D *area = area_owner.get_or_null(p_area); |
244 | ERR_FAIL_COND_V(!area, RID()); |
245 | |
246 | GodotSpace3D *space = area->get_space(); |
247 | if (!space) { |
248 | return RID(); |
249 | } |
250 | return space->get_self(); |
251 | } |
252 | |
253 | void GodotPhysicsServer3D::area_add_shape(RID p_area, RID p_shape, const Transform3D &p_transform, bool p_disabled) { |
254 | GodotArea3D *area = area_owner.get_or_null(p_area); |
255 | ERR_FAIL_COND(!area); |
256 | |
257 | GodotShape3D *shape = shape_owner.get_or_null(p_shape); |
258 | ERR_FAIL_COND(!shape); |
259 | |
260 | area->add_shape(shape, p_transform, p_disabled); |
261 | } |
262 | |
263 | void GodotPhysicsServer3D::area_set_shape(RID p_area, int p_shape_idx, RID p_shape) { |
264 | GodotArea3D *area = area_owner.get_or_null(p_area); |
265 | ERR_FAIL_COND(!area); |
266 | |
267 | GodotShape3D *shape = shape_owner.get_or_null(p_shape); |
268 | ERR_FAIL_COND(!shape); |
269 | ERR_FAIL_COND(!shape->is_configured()); |
270 | |
271 | area->set_shape(p_shape_idx, shape); |
272 | } |
273 | |
274 | void GodotPhysicsServer3D::area_set_shape_transform(RID p_area, int p_shape_idx, const Transform3D &p_transform) { |
275 | GodotArea3D *area = area_owner.get_or_null(p_area); |
276 | ERR_FAIL_COND(!area); |
277 | |
278 | area->set_shape_transform(p_shape_idx, p_transform); |
279 | } |
280 | |
281 | int GodotPhysicsServer3D::area_get_shape_count(RID p_area) const { |
282 | GodotArea3D *area = area_owner.get_or_null(p_area); |
283 | ERR_FAIL_COND_V(!area, -1); |
284 | |
285 | return area->get_shape_count(); |
286 | } |
287 | |
288 | RID GodotPhysicsServer3D::area_get_shape(RID p_area, int p_shape_idx) const { |
289 | GodotArea3D *area = area_owner.get_or_null(p_area); |
290 | ERR_FAIL_COND_V(!area, RID()); |
291 | |
292 | GodotShape3D *shape = area->get_shape(p_shape_idx); |
293 | ERR_FAIL_COND_V(!shape, RID()); |
294 | |
295 | return shape->get_self(); |
296 | } |
297 | |
298 | Transform3D GodotPhysicsServer3D::area_get_shape_transform(RID p_area, int p_shape_idx) const { |
299 | GodotArea3D *area = area_owner.get_or_null(p_area); |
300 | ERR_FAIL_COND_V(!area, Transform3D()); |
301 | |
302 | return area->get_shape_transform(p_shape_idx); |
303 | } |
304 | |
305 | void GodotPhysicsServer3D::area_remove_shape(RID p_area, int p_shape_idx) { |
306 | GodotArea3D *area = area_owner.get_or_null(p_area); |
307 | ERR_FAIL_COND(!area); |
308 | |
309 | area->remove_shape(p_shape_idx); |
310 | } |
311 | |
312 | void GodotPhysicsServer3D::area_clear_shapes(RID p_area) { |
313 | GodotArea3D *area = area_owner.get_or_null(p_area); |
314 | ERR_FAIL_COND(!area); |
315 | |
316 | while (area->get_shape_count()) { |
317 | area->remove_shape(0); |
318 | } |
319 | } |
320 | |
321 | void GodotPhysicsServer3D::area_set_shape_disabled(RID p_area, int p_shape_idx, bool p_disabled) { |
322 | GodotArea3D *area = area_owner.get_or_null(p_area); |
323 | ERR_FAIL_COND(!area); |
324 | ERR_FAIL_INDEX(p_shape_idx, area->get_shape_count()); |
325 | FLUSH_QUERY_CHECK(area); |
326 | area->set_shape_disabled(p_shape_idx, p_disabled); |
327 | } |
328 | |
329 | void GodotPhysicsServer3D::area_attach_object_instance_id(RID p_area, ObjectID p_id) { |
330 | if (space_owner.owns(p_area)) { |
331 | GodotSpace3D *space = space_owner.get_or_null(p_area); |
332 | p_area = space->get_default_area()->get_self(); |
333 | } |
334 | GodotArea3D *area = area_owner.get_or_null(p_area); |
335 | ERR_FAIL_COND(!area); |
336 | area->set_instance_id(p_id); |
337 | } |
338 | |
339 | ObjectID GodotPhysicsServer3D::area_get_object_instance_id(RID p_area) const { |
340 | if (space_owner.owns(p_area)) { |
341 | GodotSpace3D *space = space_owner.get_or_null(p_area); |
342 | p_area = space->get_default_area()->get_self(); |
343 | } |
344 | GodotArea3D *area = area_owner.get_or_null(p_area); |
345 | ERR_FAIL_COND_V(!area, ObjectID()); |
346 | return area->get_instance_id(); |
347 | } |
348 | |
349 | void GodotPhysicsServer3D::area_set_param(RID p_area, AreaParameter p_param, const Variant &p_value) { |
350 | if (space_owner.owns(p_area)) { |
351 | GodotSpace3D *space = space_owner.get_or_null(p_area); |
352 | p_area = space->get_default_area()->get_self(); |
353 | } |
354 | GodotArea3D *area = area_owner.get_or_null(p_area); |
355 | ERR_FAIL_COND(!area); |
356 | area->set_param(p_param, p_value); |
357 | }; |
358 | |
359 | void GodotPhysicsServer3D::area_set_transform(RID p_area, const Transform3D &p_transform) { |
360 | GodotArea3D *area = area_owner.get_or_null(p_area); |
361 | ERR_FAIL_COND(!area); |
362 | area->set_transform(p_transform); |
363 | }; |
364 | |
365 | Variant GodotPhysicsServer3D::area_get_param(RID p_area, AreaParameter p_param) const { |
366 | if (space_owner.owns(p_area)) { |
367 | GodotSpace3D *space = space_owner.get_or_null(p_area); |
368 | p_area = space->get_default_area()->get_self(); |
369 | } |
370 | GodotArea3D *area = area_owner.get_or_null(p_area); |
371 | ERR_FAIL_COND_V(!area, Variant()); |
372 | |
373 | return area->get_param(p_param); |
374 | }; |
375 | |
376 | Transform3D GodotPhysicsServer3D::area_get_transform(RID p_area) const { |
377 | GodotArea3D *area = area_owner.get_or_null(p_area); |
378 | ERR_FAIL_COND_V(!area, Transform3D()); |
379 | |
380 | return area->get_transform(); |
381 | }; |
382 | |
383 | void GodotPhysicsServer3D::area_set_collision_layer(RID p_area, uint32_t p_layer) { |
384 | GodotArea3D *area = area_owner.get_or_null(p_area); |
385 | ERR_FAIL_COND(!area); |
386 | |
387 | area->set_collision_layer(p_layer); |
388 | } |
389 | |
390 | uint32_t GodotPhysicsServer3D::area_get_collision_layer(RID p_area) const { |
391 | GodotArea3D *area = area_owner.get_or_null(p_area); |
392 | ERR_FAIL_COND_V(!area, 0); |
393 | |
394 | return area->get_collision_layer(); |
395 | } |
396 | |
397 | void GodotPhysicsServer3D::area_set_collision_mask(RID p_area, uint32_t p_mask) { |
398 | GodotArea3D *area = area_owner.get_or_null(p_area); |
399 | ERR_FAIL_COND(!area); |
400 | |
401 | area->set_collision_mask(p_mask); |
402 | } |
403 | |
404 | uint32_t GodotPhysicsServer3D::area_get_collision_mask(RID p_area) const { |
405 | GodotArea3D *area = area_owner.get_or_null(p_area); |
406 | ERR_FAIL_COND_V(!area, 0); |
407 | |
408 | return area->get_collision_mask(); |
409 | } |
410 | |
411 | void GodotPhysicsServer3D::area_set_monitorable(RID p_area, bool p_monitorable) { |
412 | GodotArea3D *area = area_owner.get_or_null(p_area); |
413 | ERR_FAIL_COND(!area); |
414 | FLUSH_QUERY_CHECK(area); |
415 | |
416 | area->set_monitorable(p_monitorable); |
417 | } |
418 | |
419 | void GodotPhysicsServer3D::area_set_monitor_callback(RID p_area, const Callable &p_callback) { |
420 | GodotArea3D *area = area_owner.get_or_null(p_area); |
421 | ERR_FAIL_COND(!area); |
422 | |
423 | area->set_monitor_callback(p_callback.is_valid() ? p_callback : Callable()); |
424 | } |
425 | |
426 | void GodotPhysicsServer3D::area_set_ray_pickable(RID p_area, bool p_enable) { |
427 | GodotArea3D *area = area_owner.get_or_null(p_area); |
428 | ERR_FAIL_COND(!area); |
429 | |
430 | area->set_ray_pickable(p_enable); |
431 | } |
432 | |
433 | void GodotPhysicsServer3D::area_set_area_monitor_callback(RID p_area, const Callable &p_callback) { |
434 | GodotArea3D *area = area_owner.get_or_null(p_area); |
435 | ERR_FAIL_COND(!area); |
436 | |
437 | area->set_area_monitor_callback(p_callback.is_valid() ? p_callback : Callable()); |
438 | } |
439 | |
440 | /* BODY API */ |
441 | |
442 | RID GodotPhysicsServer3D::body_create() { |
443 | GodotBody3D *body = memnew(GodotBody3D); |
444 | RID rid = body_owner.make_rid(body); |
445 | body->set_self(rid); |
446 | return rid; |
447 | }; |
448 | |
449 | void GodotPhysicsServer3D::body_set_space(RID p_body, RID p_space) { |
450 | GodotBody3D *body = body_owner.get_or_null(p_body); |
451 | ERR_FAIL_COND(!body); |
452 | |
453 | GodotSpace3D *space = nullptr; |
454 | if (p_space.is_valid()) { |
455 | space = space_owner.get_or_null(p_space); |
456 | ERR_FAIL_COND(!space); |
457 | } |
458 | |
459 | if (body->get_space() == space) { |
460 | return; //pointless |
461 | } |
462 | |
463 | body->clear_constraint_map(); |
464 | body->set_space(space); |
465 | }; |
466 | |
467 | RID GodotPhysicsServer3D::body_get_space(RID p_body) const { |
468 | GodotBody3D *body = body_owner.get_or_null(p_body); |
469 | ERR_FAIL_COND_V(!body, RID()); |
470 | |
471 | GodotSpace3D *space = body->get_space(); |
472 | if (!space) { |
473 | return RID(); |
474 | } |
475 | return space->get_self(); |
476 | }; |
477 | |
478 | void GodotPhysicsServer3D::body_set_mode(RID p_body, BodyMode p_mode) { |
479 | GodotBody3D *body = body_owner.get_or_null(p_body); |
480 | ERR_FAIL_COND(!body); |
481 | |
482 | body->set_mode(p_mode); |
483 | }; |
484 | |
485 | PhysicsServer3D::BodyMode GodotPhysicsServer3D::body_get_mode(RID p_body) const { |
486 | GodotBody3D *body = body_owner.get_or_null(p_body); |
487 | ERR_FAIL_COND_V(!body, BODY_MODE_STATIC); |
488 | |
489 | return body->get_mode(); |
490 | }; |
491 | |
492 | void GodotPhysicsServer3D::body_add_shape(RID p_body, RID p_shape, const Transform3D &p_transform, bool p_disabled) { |
493 | GodotBody3D *body = body_owner.get_or_null(p_body); |
494 | ERR_FAIL_COND(!body); |
495 | |
496 | GodotShape3D *shape = shape_owner.get_or_null(p_shape); |
497 | ERR_FAIL_COND(!shape); |
498 | |
499 | body->add_shape(shape, p_transform, p_disabled); |
500 | } |
501 | |
502 | void GodotPhysicsServer3D::body_set_shape(RID p_body, int p_shape_idx, RID p_shape) { |
503 | GodotBody3D *body = body_owner.get_or_null(p_body); |
504 | ERR_FAIL_COND(!body); |
505 | |
506 | GodotShape3D *shape = shape_owner.get_or_null(p_shape); |
507 | ERR_FAIL_COND(!shape); |
508 | ERR_FAIL_COND(!shape->is_configured()); |
509 | |
510 | body->set_shape(p_shape_idx, shape); |
511 | } |
512 | void GodotPhysicsServer3D::body_set_shape_transform(RID p_body, int p_shape_idx, const Transform3D &p_transform) { |
513 | GodotBody3D *body = body_owner.get_or_null(p_body); |
514 | ERR_FAIL_COND(!body); |
515 | |
516 | body->set_shape_transform(p_shape_idx, p_transform); |
517 | } |
518 | |
519 | int GodotPhysicsServer3D::body_get_shape_count(RID p_body) const { |
520 | GodotBody3D *body = body_owner.get_or_null(p_body); |
521 | ERR_FAIL_COND_V(!body, -1); |
522 | |
523 | return body->get_shape_count(); |
524 | } |
525 | |
526 | RID GodotPhysicsServer3D::body_get_shape(RID p_body, int p_shape_idx) const { |
527 | GodotBody3D *body = body_owner.get_or_null(p_body); |
528 | ERR_FAIL_COND_V(!body, RID()); |
529 | |
530 | GodotShape3D *shape = body->get_shape(p_shape_idx); |
531 | ERR_FAIL_COND_V(!shape, RID()); |
532 | |
533 | return shape->get_self(); |
534 | } |
535 | |
536 | void GodotPhysicsServer3D::body_set_shape_disabled(RID p_body, int p_shape_idx, bool p_disabled) { |
537 | GodotBody3D *body = body_owner.get_or_null(p_body); |
538 | ERR_FAIL_COND(!body); |
539 | ERR_FAIL_INDEX(p_shape_idx, body->get_shape_count()); |
540 | FLUSH_QUERY_CHECK(body); |
541 | |
542 | body->set_shape_disabled(p_shape_idx, p_disabled); |
543 | } |
544 | |
545 | Transform3D GodotPhysicsServer3D::body_get_shape_transform(RID p_body, int p_shape_idx) const { |
546 | GodotBody3D *body = body_owner.get_or_null(p_body); |
547 | ERR_FAIL_COND_V(!body, Transform3D()); |
548 | |
549 | return body->get_shape_transform(p_shape_idx); |
550 | } |
551 | |
552 | void GodotPhysicsServer3D::body_remove_shape(RID p_body, int p_shape_idx) { |
553 | GodotBody3D *body = body_owner.get_or_null(p_body); |
554 | ERR_FAIL_COND(!body); |
555 | |
556 | body->remove_shape(p_shape_idx); |
557 | } |
558 | |
559 | void GodotPhysicsServer3D::body_clear_shapes(RID p_body) { |
560 | GodotBody3D *body = body_owner.get_or_null(p_body); |
561 | ERR_FAIL_COND(!body); |
562 | |
563 | while (body->get_shape_count()) { |
564 | body->remove_shape(0); |
565 | } |
566 | } |
567 | |
568 | void GodotPhysicsServer3D::body_set_enable_continuous_collision_detection(RID p_body, bool p_enable) { |
569 | GodotBody3D *body = body_owner.get_or_null(p_body); |
570 | ERR_FAIL_COND(!body); |
571 | |
572 | body->set_continuous_collision_detection(p_enable); |
573 | } |
574 | |
575 | bool GodotPhysicsServer3D::body_is_continuous_collision_detection_enabled(RID p_body) const { |
576 | GodotBody3D *body = body_owner.get_or_null(p_body); |
577 | ERR_FAIL_COND_V(!body, false); |
578 | |
579 | return body->is_continuous_collision_detection_enabled(); |
580 | } |
581 | |
582 | void GodotPhysicsServer3D::body_set_collision_layer(RID p_body, uint32_t p_layer) { |
583 | GodotBody3D *body = body_owner.get_or_null(p_body); |
584 | ERR_FAIL_COND(!body); |
585 | |
586 | body->set_collision_layer(p_layer); |
587 | } |
588 | |
589 | uint32_t GodotPhysicsServer3D::body_get_collision_layer(RID p_body) const { |
590 | const GodotBody3D *body = body_owner.get_or_null(p_body); |
591 | ERR_FAIL_COND_V(!body, 0); |
592 | |
593 | return body->get_collision_layer(); |
594 | } |
595 | |
596 | void GodotPhysicsServer3D::body_set_collision_mask(RID p_body, uint32_t p_mask) { |
597 | GodotBody3D *body = body_owner.get_or_null(p_body); |
598 | ERR_FAIL_COND(!body); |
599 | |
600 | body->set_collision_mask(p_mask); |
601 | } |
602 | |
603 | uint32_t GodotPhysicsServer3D::body_get_collision_mask(RID p_body) const { |
604 | const GodotBody3D *body = body_owner.get_or_null(p_body); |
605 | ERR_FAIL_COND_V(!body, 0); |
606 | |
607 | return body->get_collision_mask(); |
608 | } |
609 | |
610 | void GodotPhysicsServer3D::body_set_collision_priority(RID p_body, real_t p_priority) { |
611 | GodotBody3D *body = body_owner.get_or_null(p_body); |
612 | ERR_FAIL_COND(!body); |
613 | |
614 | body->set_collision_priority(p_priority); |
615 | } |
616 | |
617 | real_t GodotPhysicsServer3D::body_get_collision_priority(RID p_body) const { |
618 | const GodotBody3D *body = body_owner.get_or_null(p_body); |
619 | ERR_FAIL_COND_V(!body, 0); |
620 | |
621 | return body->get_collision_priority(); |
622 | } |
623 | |
624 | void GodotPhysicsServer3D::body_attach_object_instance_id(RID p_body, ObjectID p_id) { |
625 | GodotBody3D *body = body_owner.get_or_null(p_body); |
626 | if (body) { |
627 | body->set_instance_id(p_id); |
628 | return; |
629 | } |
630 | |
631 | GodotSoftBody3D *soft_body = soft_body_owner.get_or_null(p_body); |
632 | if (soft_body) { |
633 | soft_body->set_instance_id(p_id); |
634 | return; |
635 | } |
636 | |
637 | ERR_FAIL_MSG("Invalid ID." ); |
638 | } |
639 | |
640 | ObjectID GodotPhysicsServer3D::body_get_object_instance_id(RID p_body) const { |
641 | GodotBody3D *body = body_owner.get_or_null(p_body); |
642 | ERR_FAIL_COND_V(!body, ObjectID()); |
643 | |
644 | return body->get_instance_id(); |
645 | } |
646 | |
647 | void GodotPhysicsServer3D::body_set_user_flags(RID p_body, uint32_t p_flags) { |
648 | GodotBody3D *body = body_owner.get_or_null(p_body); |
649 | ERR_FAIL_COND(!body); |
650 | } |
651 | |
652 | uint32_t GodotPhysicsServer3D::body_get_user_flags(RID p_body) const { |
653 | GodotBody3D *body = body_owner.get_or_null(p_body); |
654 | ERR_FAIL_COND_V(!body, 0); |
655 | |
656 | return 0; |
657 | } |
658 | |
659 | void GodotPhysicsServer3D::body_set_param(RID p_body, BodyParameter p_param, const Variant &p_value) { |
660 | GodotBody3D *body = body_owner.get_or_null(p_body); |
661 | ERR_FAIL_COND(!body); |
662 | |
663 | body->set_param(p_param, p_value); |
664 | } |
665 | |
666 | Variant GodotPhysicsServer3D::body_get_param(RID p_body, BodyParameter p_param) const { |
667 | GodotBody3D *body = body_owner.get_or_null(p_body); |
668 | ERR_FAIL_COND_V(!body, 0); |
669 | |
670 | return body->get_param(p_param); |
671 | } |
672 | |
673 | void GodotPhysicsServer3D::body_reset_mass_properties(RID p_body) { |
674 | GodotBody3D *body = body_owner.get_or_null(p_body); |
675 | ERR_FAIL_COND(!body); |
676 | |
677 | return body->reset_mass_properties(); |
678 | } |
679 | |
680 | void GodotPhysicsServer3D::body_set_state(RID p_body, BodyState p_state, const Variant &p_variant) { |
681 | GodotBody3D *body = body_owner.get_or_null(p_body); |
682 | ERR_FAIL_COND(!body); |
683 | |
684 | body->set_state(p_state, p_variant); |
685 | } |
686 | |
687 | Variant GodotPhysicsServer3D::body_get_state(RID p_body, BodyState p_state) const { |
688 | GodotBody3D *body = body_owner.get_or_null(p_body); |
689 | ERR_FAIL_COND_V(!body, Variant()); |
690 | |
691 | return body->get_state(p_state); |
692 | } |
693 | |
694 | void GodotPhysicsServer3D::body_apply_central_impulse(RID p_body, const Vector3 &p_impulse) { |
695 | GodotBody3D *body = body_owner.get_or_null(p_body); |
696 | ERR_FAIL_COND(!body); |
697 | |
698 | _update_shapes(); |
699 | |
700 | body->apply_central_impulse(p_impulse); |
701 | body->wakeup(); |
702 | } |
703 | |
704 | void GodotPhysicsServer3D::body_apply_impulse(RID p_body, const Vector3 &p_impulse, const Vector3 &p_position) { |
705 | GodotBody3D *body = body_owner.get_or_null(p_body); |
706 | ERR_FAIL_COND(!body); |
707 | |
708 | _update_shapes(); |
709 | |
710 | body->apply_impulse(p_impulse, p_position); |
711 | body->wakeup(); |
712 | } |
713 | |
714 | void GodotPhysicsServer3D::body_apply_torque_impulse(RID p_body, const Vector3 &p_impulse) { |
715 | GodotBody3D *body = body_owner.get_or_null(p_body); |
716 | ERR_FAIL_COND(!body); |
717 | |
718 | _update_shapes(); |
719 | |
720 | body->apply_torque_impulse(p_impulse); |
721 | body->wakeup(); |
722 | } |
723 | |
724 | void GodotPhysicsServer3D::body_apply_central_force(RID p_body, const Vector3 &p_force) { |
725 | GodotBody3D *body = body_owner.get_or_null(p_body); |
726 | ERR_FAIL_COND(!body); |
727 | |
728 | body->apply_central_force(p_force); |
729 | body->wakeup(); |
730 | } |
731 | |
732 | void GodotPhysicsServer3D::body_apply_force(RID p_body, const Vector3 &p_force, const Vector3 &p_position) { |
733 | GodotBody3D *body = body_owner.get_or_null(p_body); |
734 | ERR_FAIL_COND(!body); |
735 | |
736 | body->apply_force(p_force, p_position); |
737 | body->wakeup(); |
738 | } |
739 | |
740 | void GodotPhysicsServer3D::body_apply_torque(RID p_body, const Vector3 &p_torque) { |
741 | GodotBody3D *body = body_owner.get_or_null(p_body); |
742 | ERR_FAIL_COND(!body); |
743 | |
744 | body->apply_torque(p_torque); |
745 | body->wakeup(); |
746 | } |
747 | |
748 | void GodotPhysicsServer3D::body_add_constant_central_force(RID p_body, const Vector3 &p_force) { |
749 | GodotBody3D *body = body_owner.get_or_null(p_body); |
750 | ERR_FAIL_COND(!body); |
751 | |
752 | body->add_constant_central_force(p_force); |
753 | body->wakeup(); |
754 | } |
755 | |
756 | void GodotPhysicsServer3D::body_add_constant_force(RID p_body, const Vector3 &p_force, const Vector3 &p_position) { |
757 | GodotBody3D *body = body_owner.get_or_null(p_body); |
758 | ERR_FAIL_COND(!body); |
759 | |
760 | body->add_constant_force(p_force, p_position); |
761 | body->wakeup(); |
762 | } |
763 | |
764 | void GodotPhysicsServer3D::body_add_constant_torque(RID p_body, const Vector3 &p_torque) { |
765 | GodotBody3D *body = body_owner.get_or_null(p_body); |
766 | ERR_FAIL_COND(!body); |
767 | |
768 | body->add_constant_torque(p_torque); |
769 | body->wakeup(); |
770 | } |
771 | |
772 | void GodotPhysicsServer3D::body_set_constant_force(RID p_body, const Vector3 &p_force) { |
773 | GodotBody3D *body = body_owner.get_or_null(p_body); |
774 | ERR_FAIL_COND(!body); |
775 | |
776 | body->set_constant_force(p_force); |
777 | if (!p_force.is_zero_approx()) { |
778 | body->wakeup(); |
779 | } |
780 | } |
781 | |
782 | Vector3 GodotPhysicsServer3D::body_get_constant_force(RID p_body) const { |
783 | GodotBody3D *body = body_owner.get_or_null(p_body); |
784 | ERR_FAIL_COND_V(!body, Vector3()); |
785 | return body->get_constant_force(); |
786 | } |
787 | |
788 | void GodotPhysicsServer3D::body_set_constant_torque(RID p_body, const Vector3 &p_torque) { |
789 | GodotBody3D *body = body_owner.get_or_null(p_body); |
790 | ERR_FAIL_COND(!body); |
791 | |
792 | body->set_constant_torque(p_torque); |
793 | if (!p_torque.is_zero_approx()) { |
794 | body->wakeup(); |
795 | } |
796 | } |
797 | |
798 | Vector3 GodotPhysicsServer3D::body_get_constant_torque(RID p_body) const { |
799 | GodotBody3D *body = body_owner.get_or_null(p_body); |
800 | ERR_FAIL_COND_V(!body, Vector3()); |
801 | |
802 | return body->get_constant_torque(); |
803 | } |
804 | |
805 | void GodotPhysicsServer3D::body_set_axis_velocity(RID p_body, const Vector3 &p_axis_velocity) { |
806 | GodotBody3D *body = body_owner.get_or_null(p_body); |
807 | ERR_FAIL_COND(!body); |
808 | |
809 | _update_shapes(); |
810 | |
811 | Vector3 v = body->get_linear_velocity(); |
812 | Vector3 axis = p_axis_velocity.normalized(); |
813 | v -= axis * axis.dot(v); |
814 | v += p_axis_velocity; |
815 | body->set_linear_velocity(v); |
816 | body->wakeup(); |
817 | } |
818 | |
819 | void GodotPhysicsServer3D::body_set_axis_lock(RID p_body, BodyAxis p_axis, bool p_lock) { |
820 | GodotBody3D *body = body_owner.get_or_null(p_body); |
821 | ERR_FAIL_COND(!body); |
822 | |
823 | body->set_axis_lock(p_axis, p_lock); |
824 | body->wakeup(); |
825 | } |
826 | |
827 | bool GodotPhysicsServer3D::body_is_axis_locked(RID p_body, BodyAxis p_axis) const { |
828 | const GodotBody3D *body = body_owner.get_or_null(p_body); |
829 | ERR_FAIL_COND_V(!body, 0); |
830 | return body->is_axis_locked(p_axis); |
831 | } |
832 | |
833 | void GodotPhysicsServer3D::body_add_collision_exception(RID p_body, RID p_body_b) { |
834 | GodotBody3D *body = body_owner.get_or_null(p_body); |
835 | ERR_FAIL_COND(!body); |
836 | |
837 | body->add_exception(p_body_b); |
838 | body->wakeup(); |
839 | }; |
840 | |
841 | void GodotPhysicsServer3D::body_remove_collision_exception(RID p_body, RID p_body_b) { |
842 | GodotBody3D *body = body_owner.get_or_null(p_body); |
843 | ERR_FAIL_COND(!body); |
844 | |
845 | body->remove_exception(p_body_b); |
846 | body->wakeup(); |
847 | }; |
848 | |
849 | void GodotPhysicsServer3D::body_get_collision_exceptions(RID p_body, List<RID> *p_exceptions) { |
850 | GodotBody3D *body = body_owner.get_or_null(p_body); |
851 | ERR_FAIL_COND(!body); |
852 | |
853 | for (int i = 0; i < body->get_exceptions().size(); i++) { |
854 | p_exceptions->push_back(body->get_exceptions()[i]); |
855 | } |
856 | }; |
857 | |
858 | void GodotPhysicsServer3D::body_set_contacts_reported_depth_threshold(RID p_body, real_t p_threshold) { |
859 | GodotBody3D *body = body_owner.get_or_null(p_body); |
860 | ERR_FAIL_COND(!body); |
861 | }; |
862 | |
863 | real_t GodotPhysicsServer3D::body_get_contacts_reported_depth_threshold(RID p_body) const { |
864 | GodotBody3D *body = body_owner.get_or_null(p_body); |
865 | ERR_FAIL_COND_V(!body, 0); |
866 | return 0; |
867 | }; |
868 | |
869 | void GodotPhysicsServer3D::body_set_omit_force_integration(RID p_body, bool p_omit) { |
870 | GodotBody3D *body = body_owner.get_or_null(p_body); |
871 | ERR_FAIL_COND(!body); |
872 | |
873 | body->set_omit_force_integration(p_omit); |
874 | }; |
875 | |
876 | bool GodotPhysicsServer3D::body_is_omitting_force_integration(RID p_body) const { |
877 | GodotBody3D *body = body_owner.get_or_null(p_body); |
878 | ERR_FAIL_COND_V(!body, false); |
879 | return body->get_omit_force_integration(); |
880 | }; |
881 | |
882 | void GodotPhysicsServer3D::body_set_max_contacts_reported(RID p_body, int p_contacts) { |
883 | GodotBody3D *body = body_owner.get_or_null(p_body); |
884 | ERR_FAIL_COND(!body); |
885 | body->set_max_contacts_reported(p_contacts); |
886 | } |
887 | |
888 | int GodotPhysicsServer3D::body_get_max_contacts_reported(RID p_body) const { |
889 | GodotBody3D *body = body_owner.get_or_null(p_body); |
890 | ERR_FAIL_COND_V(!body, -1); |
891 | return body->get_max_contacts_reported(); |
892 | } |
893 | |
894 | void GodotPhysicsServer3D::body_set_state_sync_callback(RID p_body, const Callable &p_callable) { |
895 | GodotBody3D *body = body_owner.get_or_null(p_body); |
896 | ERR_FAIL_COND(!body); |
897 | body->set_state_sync_callback(p_callable); |
898 | } |
899 | |
900 | void GodotPhysicsServer3D::body_set_force_integration_callback(RID p_body, const Callable &p_callable, const Variant &p_udata) { |
901 | GodotBody3D *body = body_owner.get_or_null(p_body); |
902 | ERR_FAIL_COND(!body); |
903 | body->set_force_integration_callback(p_callable, p_udata); |
904 | } |
905 | |
906 | void GodotPhysicsServer3D::body_set_ray_pickable(RID p_body, bool p_enable) { |
907 | GodotBody3D *body = body_owner.get_or_null(p_body); |
908 | ERR_FAIL_COND(!body); |
909 | body->set_ray_pickable(p_enable); |
910 | } |
911 | |
912 | bool GodotPhysicsServer3D::body_test_motion(RID p_body, const MotionParameters &p_parameters, MotionResult *r_result) { |
913 | GodotBody3D *body = body_owner.get_or_null(p_body); |
914 | ERR_FAIL_COND_V(!body, false); |
915 | ERR_FAIL_COND_V(!body->get_space(), false); |
916 | ERR_FAIL_COND_V(body->get_space()->is_locked(), false); |
917 | |
918 | _update_shapes(); |
919 | |
920 | return body->get_space()->test_body_motion(body, p_parameters, r_result); |
921 | } |
922 | |
923 | PhysicsDirectBodyState3D *GodotPhysicsServer3D::body_get_direct_state(RID p_body) { |
924 | ERR_FAIL_COND_V_MSG((using_threads && !doing_sync), nullptr, "Body state is inaccessible right now, wait for iteration or physics process notification." ); |
925 | |
926 | if (!body_owner.owns(p_body)) { |
927 | return nullptr; |
928 | } |
929 | |
930 | GodotBody3D *body = body_owner.get_or_null(p_body); |
931 | ERR_FAIL_NULL_V(body, nullptr); |
932 | |
933 | if (!body->get_space()) { |
934 | return nullptr; |
935 | } |
936 | |
937 | ERR_FAIL_COND_V_MSG(body->get_space()->is_locked(), nullptr, "Body state is inaccessible right now, wait for iteration or physics process notification." ); |
938 | |
939 | return body->get_direct_state(); |
940 | } |
941 | |
942 | /* SOFT BODY */ |
943 | |
944 | RID GodotPhysicsServer3D::soft_body_create() { |
945 | GodotSoftBody3D *soft_body = memnew(GodotSoftBody3D); |
946 | RID rid = soft_body_owner.make_rid(soft_body); |
947 | soft_body->set_self(rid); |
948 | return rid; |
949 | } |
950 | |
951 | void GodotPhysicsServer3D::soft_body_update_rendering_server(RID p_body, PhysicsServer3DRenderingServerHandler *p_rendering_server_handler) { |
952 | GodotSoftBody3D *soft_body = soft_body_owner.get_or_null(p_body); |
953 | ERR_FAIL_COND(!soft_body); |
954 | |
955 | soft_body->update_rendering_server(p_rendering_server_handler); |
956 | } |
957 | |
958 | void GodotPhysicsServer3D::soft_body_set_space(RID p_body, RID p_space) { |
959 | GodotSoftBody3D *soft_body = soft_body_owner.get_or_null(p_body); |
960 | ERR_FAIL_COND(!soft_body); |
961 | |
962 | GodotSpace3D *space = nullptr; |
963 | if (p_space.is_valid()) { |
964 | space = space_owner.get_or_null(p_space); |
965 | ERR_FAIL_COND(!space); |
966 | } |
967 | |
968 | if (soft_body->get_space() == space) { |
969 | return; |
970 | } |
971 | |
972 | soft_body->set_space(space); |
973 | } |
974 | |
975 | RID GodotPhysicsServer3D::soft_body_get_space(RID p_body) const { |
976 | GodotSoftBody3D *soft_body = soft_body_owner.get_or_null(p_body); |
977 | ERR_FAIL_COND_V(!soft_body, RID()); |
978 | |
979 | GodotSpace3D *space = soft_body->get_space(); |
980 | if (!space) { |
981 | return RID(); |
982 | } |
983 | return space->get_self(); |
984 | } |
985 | |
986 | void GodotPhysicsServer3D::soft_body_set_collision_layer(RID p_body, uint32_t p_layer) { |
987 | GodotSoftBody3D *soft_body = soft_body_owner.get_or_null(p_body); |
988 | ERR_FAIL_COND(!soft_body); |
989 | |
990 | soft_body->set_collision_layer(p_layer); |
991 | } |
992 | |
993 | uint32_t GodotPhysicsServer3D::soft_body_get_collision_layer(RID p_body) const { |
994 | GodotSoftBody3D *soft_body = soft_body_owner.get_or_null(p_body); |
995 | ERR_FAIL_COND_V(!soft_body, 0); |
996 | |
997 | return soft_body->get_collision_layer(); |
998 | } |
999 | |
1000 | void GodotPhysicsServer3D::soft_body_set_collision_mask(RID p_body, uint32_t p_mask) { |
1001 | GodotSoftBody3D *soft_body = soft_body_owner.get_or_null(p_body); |
1002 | ERR_FAIL_COND(!soft_body); |
1003 | |
1004 | soft_body->set_collision_mask(p_mask); |
1005 | } |
1006 | |
1007 | uint32_t GodotPhysicsServer3D::soft_body_get_collision_mask(RID p_body) const { |
1008 | GodotSoftBody3D *soft_body = soft_body_owner.get_or_null(p_body); |
1009 | ERR_FAIL_COND_V(!soft_body, 0); |
1010 | |
1011 | return soft_body->get_collision_mask(); |
1012 | } |
1013 | |
1014 | void GodotPhysicsServer3D::soft_body_add_collision_exception(RID p_body, RID p_body_b) { |
1015 | GodotSoftBody3D *soft_body = soft_body_owner.get_or_null(p_body); |
1016 | ERR_FAIL_COND(!soft_body); |
1017 | |
1018 | soft_body->add_exception(p_body_b); |
1019 | } |
1020 | |
1021 | void GodotPhysicsServer3D::soft_body_remove_collision_exception(RID p_body, RID p_body_b) { |
1022 | GodotSoftBody3D *soft_body = soft_body_owner.get_or_null(p_body); |
1023 | ERR_FAIL_COND(!soft_body); |
1024 | |
1025 | soft_body->remove_exception(p_body_b); |
1026 | } |
1027 | |
1028 | void GodotPhysicsServer3D::soft_body_get_collision_exceptions(RID p_body, List<RID> *p_exceptions) { |
1029 | GodotSoftBody3D *soft_body = soft_body_owner.get_or_null(p_body); |
1030 | ERR_FAIL_COND(!soft_body); |
1031 | |
1032 | for (int i = 0; i < soft_body->get_exceptions().size(); i++) { |
1033 | p_exceptions->push_back(soft_body->get_exceptions()[i]); |
1034 | } |
1035 | } |
1036 | |
1037 | void GodotPhysicsServer3D::soft_body_set_state(RID p_body, BodyState p_state, const Variant &p_variant) { |
1038 | GodotSoftBody3D *soft_body = soft_body_owner.get_or_null(p_body); |
1039 | ERR_FAIL_COND(!soft_body); |
1040 | |
1041 | soft_body->set_state(p_state, p_variant); |
1042 | } |
1043 | |
1044 | Variant GodotPhysicsServer3D::soft_body_get_state(RID p_body, BodyState p_state) const { |
1045 | GodotSoftBody3D *soft_body = soft_body_owner.get_or_null(p_body); |
1046 | ERR_FAIL_COND_V(!soft_body, Variant()); |
1047 | |
1048 | return soft_body->get_state(p_state); |
1049 | } |
1050 | |
1051 | void GodotPhysicsServer3D::soft_body_set_transform(RID p_body, const Transform3D &p_transform) { |
1052 | GodotSoftBody3D *soft_body = soft_body_owner.get_or_null(p_body); |
1053 | ERR_FAIL_COND(!soft_body); |
1054 | |
1055 | soft_body->set_state(BODY_STATE_TRANSFORM, p_transform); |
1056 | } |
1057 | |
1058 | void GodotPhysicsServer3D::soft_body_set_ray_pickable(RID p_body, bool p_enable) { |
1059 | GodotSoftBody3D *soft_body = soft_body_owner.get_or_null(p_body); |
1060 | ERR_FAIL_COND(!soft_body); |
1061 | |
1062 | soft_body->set_ray_pickable(p_enable); |
1063 | } |
1064 | |
1065 | void GodotPhysicsServer3D::soft_body_set_simulation_precision(RID p_body, int p_simulation_precision) { |
1066 | GodotSoftBody3D *soft_body = soft_body_owner.get_or_null(p_body); |
1067 | ERR_FAIL_COND(!soft_body); |
1068 | |
1069 | soft_body->set_iteration_count(p_simulation_precision); |
1070 | } |
1071 | |
1072 | int GodotPhysicsServer3D::soft_body_get_simulation_precision(RID p_body) const { |
1073 | GodotSoftBody3D *soft_body = soft_body_owner.get_or_null(p_body); |
1074 | ERR_FAIL_COND_V(!soft_body, 0.f); |
1075 | |
1076 | return soft_body->get_iteration_count(); |
1077 | } |
1078 | |
1079 | void GodotPhysicsServer3D::soft_body_set_total_mass(RID p_body, real_t p_total_mass) { |
1080 | GodotSoftBody3D *soft_body = soft_body_owner.get_or_null(p_body); |
1081 | ERR_FAIL_COND(!soft_body); |
1082 | |
1083 | soft_body->set_total_mass(p_total_mass); |
1084 | } |
1085 | |
1086 | real_t GodotPhysicsServer3D::soft_body_get_total_mass(RID p_body) const { |
1087 | GodotSoftBody3D *soft_body = soft_body_owner.get_or_null(p_body); |
1088 | ERR_FAIL_COND_V(!soft_body, 0.f); |
1089 | |
1090 | return soft_body->get_total_mass(); |
1091 | } |
1092 | |
1093 | void GodotPhysicsServer3D::soft_body_set_linear_stiffness(RID p_body, real_t p_stiffness) { |
1094 | GodotSoftBody3D *soft_body = soft_body_owner.get_or_null(p_body); |
1095 | ERR_FAIL_COND(!soft_body); |
1096 | |
1097 | soft_body->set_linear_stiffness(p_stiffness); |
1098 | } |
1099 | |
1100 | real_t GodotPhysicsServer3D::soft_body_get_linear_stiffness(RID p_body) const { |
1101 | GodotSoftBody3D *soft_body = soft_body_owner.get_or_null(p_body); |
1102 | ERR_FAIL_COND_V(!soft_body, 0.f); |
1103 | |
1104 | return soft_body->get_linear_stiffness(); |
1105 | } |
1106 | |
1107 | void GodotPhysicsServer3D::soft_body_set_pressure_coefficient(RID p_body, real_t p_pressure_coefficient) { |
1108 | GodotSoftBody3D *soft_body = soft_body_owner.get_or_null(p_body); |
1109 | ERR_FAIL_COND(!soft_body); |
1110 | |
1111 | soft_body->set_pressure_coefficient(p_pressure_coefficient); |
1112 | } |
1113 | |
1114 | real_t GodotPhysicsServer3D::soft_body_get_pressure_coefficient(RID p_body) const { |
1115 | GodotSoftBody3D *soft_body = soft_body_owner.get_or_null(p_body); |
1116 | ERR_FAIL_COND_V(!soft_body, 0.f); |
1117 | |
1118 | return soft_body->get_pressure_coefficient(); |
1119 | } |
1120 | |
1121 | void GodotPhysicsServer3D::soft_body_set_damping_coefficient(RID p_body, real_t p_damping_coefficient) { |
1122 | GodotSoftBody3D *soft_body = soft_body_owner.get_or_null(p_body); |
1123 | ERR_FAIL_COND(!soft_body); |
1124 | |
1125 | soft_body->set_damping_coefficient(p_damping_coefficient); |
1126 | } |
1127 | |
1128 | real_t GodotPhysicsServer3D::soft_body_get_damping_coefficient(RID p_body) const { |
1129 | GodotSoftBody3D *soft_body = soft_body_owner.get_or_null(p_body); |
1130 | ERR_FAIL_COND_V(!soft_body, 0.f); |
1131 | |
1132 | return soft_body->get_damping_coefficient(); |
1133 | } |
1134 | |
1135 | void GodotPhysicsServer3D::soft_body_set_drag_coefficient(RID p_body, real_t p_drag_coefficient) { |
1136 | GodotSoftBody3D *soft_body = soft_body_owner.get_or_null(p_body); |
1137 | ERR_FAIL_COND(!soft_body); |
1138 | |
1139 | soft_body->set_drag_coefficient(p_drag_coefficient); |
1140 | } |
1141 | |
1142 | real_t GodotPhysicsServer3D::soft_body_get_drag_coefficient(RID p_body) const { |
1143 | GodotSoftBody3D *soft_body = soft_body_owner.get_or_null(p_body); |
1144 | ERR_FAIL_COND_V(!soft_body, 0.f); |
1145 | |
1146 | return soft_body->get_drag_coefficient(); |
1147 | } |
1148 | |
1149 | void GodotPhysicsServer3D::soft_body_set_mesh(RID p_body, RID p_mesh) { |
1150 | GodotSoftBody3D *soft_body = soft_body_owner.get_or_null(p_body); |
1151 | ERR_FAIL_COND(!soft_body); |
1152 | |
1153 | soft_body->set_mesh(p_mesh); |
1154 | } |
1155 | |
1156 | AABB GodotPhysicsServer3D::soft_body_get_bounds(RID p_body) const { |
1157 | GodotSoftBody3D *soft_body = soft_body_owner.get_or_null(p_body); |
1158 | ERR_FAIL_COND_V(!soft_body, AABB()); |
1159 | |
1160 | return soft_body->get_bounds(); |
1161 | } |
1162 | |
1163 | void GodotPhysicsServer3D::soft_body_move_point(RID p_body, int p_point_index, const Vector3 &p_global_position) { |
1164 | GodotSoftBody3D *soft_body = soft_body_owner.get_or_null(p_body); |
1165 | ERR_FAIL_COND(!soft_body); |
1166 | |
1167 | soft_body->set_vertex_position(p_point_index, p_global_position); |
1168 | } |
1169 | |
1170 | Vector3 GodotPhysicsServer3D::soft_body_get_point_global_position(RID p_body, int p_point_index) const { |
1171 | GodotSoftBody3D *soft_body = soft_body_owner.get_or_null(p_body); |
1172 | ERR_FAIL_COND_V(!soft_body, Vector3()); |
1173 | |
1174 | return soft_body->get_vertex_position(p_point_index); |
1175 | } |
1176 | |
1177 | void GodotPhysicsServer3D::soft_body_remove_all_pinned_points(RID p_body) { |
1178 | GodotSoftBody3D *soft_body = soft_body_owner.get_or_null(p_body); |
1179 | ERR_FAIL_COND(!soft_body); |
1180 | |
1181 | soft_body->unpin_all_vertices(); |
1182 | } |
1183 | |
1184 | void GodotPhysicsServer3D::soft_body_pin_point(RID p_body, int p_point_index, bool p_pin) { |
1185 | GodotSoftBody3D *soft_body = soft_body_owner.get_or_null(p_body); |
1186 | ERR_FAIL_COND(!soft_body); |
1187 | |
1188 | if (p_pin) { |
1189 | soft_body->pin_vertex(p_point_index); |
1190 | } else { |
1191 | soft_body->unpin_vertex(p_point_index); |
1192 | } |
1193 | } |
1194 | |
1195 | bool GodotPhysicsServer3D::soft_body_is_point_pinned(RID p_body, int p_point_index) const { |
1196 | GodotSoftBody3D *soft_body = soft_body_owner.get_or_null(p_body); |
1197 | ERR_FAIL_COND_V(!soft_body, false); |
1198 | |
1199 | return soft_body->is_vertex_pinned(p_point_index); |
1200 | } |
1201 | |
1202 | /* JOINT API */ |
1203 | |
1204 | RID GodotPhysicsServer3D::joint_create() { |
1205 | GodotJoint3D *joint = memnew(GodotJoint3D); |
1206 | RID rid = joint_owner.make_rid(joint); |
1207 | joint->set_self(rid); |
1208 | return rid; |
1209 | } |
1210 | |
1211 | void GodotPhysicsServer3D::joint_clear(RID p_joint) { |
1212 | GodotJoint3D *joint = joint_owner.get_or_null(p_joint); |
1213 | ERR_FAIL_NULL(joint); |
1214 | if (joint->get_type() != JOINT_TYPE_MAX) { |
1215 | GodotJoint3D *empty_joint = memnew(GodotJoint3D); |
1216 | empty_joint->copy_settings_from(joint); |
1217 | |
1218 | joint_owner.replace(p_joint, empty_joint); |
1219 | memdelete(joint); |
1220 | } |
1221 | } |
1222 | |
1223 | void GodotPhysicsServer3D::joint_make_pin(RID p_joint, RID p_body_A, const Vector3 &p_local_A, RID p_body_B, const Vector3 &p_local_B) { |
1224 | GodotBody3D *body_A = body_owner.get_or_null(p_body_A); |
1225 | ERR_FAIL_COND(!body_A); |
1226 | |
1227 | if (!p_body_B.is_valid()) { |
1228 | ERR_FAIL_COND(!body_A->get_space()); |
1229 | p_body_B = body_A->get_space()->get_static_global_body(); |
1230 | } |
1231 | |
1232 | GodotBody3D *body_B = body_owner.get_or_null(p_body_B); |
1233 | ERR_FAIL_COND(!body_B); |
1234 | |
1235 | ERR_FAIL_COND(body_A == body_B); |
1236 | |
1237 | GodotJoint3D *prev_joint = joint_owner.get_or_null(p_joint); |
1238 | ERR_FAIL_COND(prev_joint == nullptr); |
1239 | |
1240 | GodotJoint3D *joint = memnew(GodotPinJoint3D(body_A, p_local_A, body_B, p_local_B)); |
1241 | |
1242 | joint->copy_settings_from(prev_joint); |
1243 | joint_owner.replace(p_joint, joint); |
1244 | memdelete(prev_joint); |
1245 | } |
1246 | |
1247 | void GodotPhysicsServer3D::pin_joint_set_param(RID p_joint, PinJointParam p_param, real_t p_value) { |
1248 | GodotJoint3D *joint = joint_owner.get_or_null(p_joint); |
1249 | ERR_FAIL_COND(!joint); |
1250 | ERR_FAIL_COND(joint->get_type() != JOINT_TYPE_PIN); |
1251 | GodotPinJoint3D *pin_joint = static_cast<GodotPinJoint3D *>(joint); |
1252 | pin_joint->set_param(p_param, p_value); |
1253 | } |
1254 | |
1255 | real_t GodotPhysicsServer3D::pin_joint_get_param(RID p_joint, PinJointParam p_param) const { |
1256 | GodotJoint3D *joint = joint_owner.get_or_null(p_joint); |
1257 | ERR_FAIL_COND_V(!joint, 0); |
1258 | ERR_FAIL_COND_V(joint->get_type() != JOINT_TYPE_PIN, 0); |
1259 | GodotPinJoint3D *pin_joint = static_cast<GodotPinJoint3D *>(joint); |
1260 | return pin_joint->get_param(p_param); |
1261 | } |
1262 | |
1263 | void GodotPhysicsServer3D::pin_joint_set_local_a(RID p_joint, const Vector3 &p_A) { |
1264 | GodotJoint3D *joint = joint_owner.get_or_null(p_joint); |
1265 | ERR_FAIL_COND(!joint); |
1266 | ERR_FAIL_COND(joint->get_type() != JOINT_TYPE_PIN); |
1267 | GodotPinJoint3D *pin_joint = static_cast<GodotPinJoint3D *>(joint); |
1268 | pin_joint->set_pos_a(p_A); |
1269 | } |
1270 | |
1271 | Vector3 GodotPhysicsServer3D::pin_joint_get_local_a(RID p_joint) const { |
1272 | GodotJoint3D *joint = joint_owner.get_or_null(p_joint); |
1273 | ERR_FAIL_COND_V(!joint, Vector3()); |
1274 | ERR_FAIL_COND_V(joint->get_type() != JOINT_TYPE_PIN, Vector3()); |
1275 | GodotPinJoint3D *pin_joint = static_cast<GodotPinJoint3D *>(joint); |
1276 | return pin_joint->get_position_a(); |
1277 | } |
1278 | |
1279 | void GodotPhysicsServer3D::pin_joint_set_local_b(RID p_joint, const Vector3 &p_B) { |
1280 | GodotJoint3D *joint = joint_owner.get_or_null(p_joint); |
1281 | ERR_FAIL_COND(!joint); |
1282 | ERR_FAIL_COND(joint->get_type() != JOINT_TYPE_PIN); |
1283 | GodotPinJoint3D *pin_joint = static_cast<GodotPinJoint3D *>(joint); |
1284 | pin_joint->set_pos_b(p_B); |
1285 | } |
1286 | |
1287 | Vector3 GodotPhysicsServer3D::pin_joint_get_local_b(RID p_joint) const { |
1288 | GodotJoint3D *joint = joint_owner.get_or_null(p_joint); |
1289 | ERR_FAIL_COND_V(!joint, Vector3()); |
1290 | ERR_FAIL_COND_V(joint->get_type() != JOINT_TYPE_PIN, Vector3()); |
1291 | GodotPinJoint3D *pin_joint = static_cast<GodotPinJoint3D *>(joint); |
1292 | return pin_joint->get_position_b(); |
1293 | } |
1294 | |
1295 | void GodotPhysicsServer3D::joint_make_hinge(RID p_joint, RID p_body_A, const Transform3D &p_frame_A, RID p_body_B, const Transform3D &p_frame_B) { |
1296 | GodotBody3D *body_A = body_owner.get_or_null(p_body_A); |
1297 | ERR_FAIL_COND(!body_A); |
1298 | |
1299 | if (!p_body_B.is_valid()) { |
1300 | ERR_FAIL_COND(!body_A->get_space()); |
1301 | p_body_B = body_A->get_space()->get_static_global_body(); |
1302 | } |
1303 | |
1304 | GodotBody3D *body_B = body_owner.get_or_null(p_body_B); |
1305 | ERR_FAIL_COND(!body_B); |
1306 | |
1307 | ERR_FAIL_COND(body_A == body_B); |
1308 | |
1309 | GodotJoint3D *prev_joint = joint_owner.get_or_null(p_joint); |
1310 | ERR_FAIL_COND(prev_joint == nullptr); |
1311 | |
1312 | GodotJoint3D *joint = memnew(GodotHingeJoint3D(body_A, body_B, p_frame_A, p_frame_B)); |
1313 | |
1314 | joint->copy_settings_from(prev_joint); |
1315 | joint_owner.replace(p_joint, joint); |
1316 | memdelete(prev_joint); |
1317 | } |
1318 | |
1319 | void GodotPhysicsServer3D::joint_make_hinge_simple(RID p_joint, RID p_body_A, const Vector3 &p_pivot_A, const Vector3 &p_axis_A, RID p_body_B, const Vector3 &p_pivot_B, const Vector3 &p_axis_B) { |
1320 | GodotBody3D *body_A = body_owner.get_or_null(p_body_A); |
1321 | ERR_FAIL_COND(!body_A); |
1322 | |
1323 | if (!p_body_B.is_valid()) { |
1324 | ERR_FAIL_COND(!body_A->get_space()); |
1325 | p_body_B = body_A->get_space()->get_static_global_body(); |
1326 | } |
1327 | |
1328 | GodotBody3D *body_B = body_owner.get_or_null(p_body_B); |
1329 | ERR_FAIL_COND(!body_B); |
1330 | |
1331 | ERR_FAIL_COND(body_A == body_B); |
1332 | |
1333 | GodotJoint3D *prev_joint = joint_owner.get_or_null(p_joint); |
1334 | ERR_FAIL_COND(prev_joint == nullptr); |
1335 | |
1336 | GodotJoint3D *joint = memnew(GodotHingeJoint3D(body_A, body_B, p_pivot_A, p_pivot_B, p_axis_A, p_axis_B)); |
1337 | |
1338 | joint->copy_settings_from(prev_joint); |
1339 | joint_owner.replace(p_joint, joint); |
1340 | memdelete(prev_joint); |
1341 | } |
1342 | |
1343 | void GodotPhysicsServer3D::hinge_joint_set_param(RID p_joint, HingeJointParam p_param, real_t p_value) { |
1344 | GodotJoint3D *joint = joint_owner.get_or_null(p_joint); |
1345 | ERR_FAIL_COND(!joint); |
1346 | ERR_FAIL_COND(joint->get_type() != JOINT_TYPE_HINGE); |
1347 | GodotHingeJoint3D *hinge_joint = static_cast<GodotHingeJoint3D *>(joint); |
1348 | hinge_joint->set_param(p_param, p_value); |
1349 | } |
1350 | |
1351 | real_t GodotPhysicsServer3D::hinge_joint_get_param(RID p_joint, HingeJointParam p_param) const { |
1352 | GodotJoint3D *joint = joint_owner.get_or_null(p_joint); |
1353 | ERR_FAIL_COND_V(!joint, 0); |
1354 | ERR_FAIL_COND_V(joint->get_type() != JOINT_TYPE_HINGE, 0); |
1355 | GodotHingeJoint3D *hinge_joint = static_cast<GodotHingeJoint3D *>(joint); |
1356 | return hinge_joint->get_param(p_param); |
1357 | } |
1358 | |
1359 | void GodotPhysicsServer3D::hinge_joint_set_flag(RID p_joint, HingeJointFlag p_flag, bool p_value) { |
1360 | GodotJoint3D *joint = joint_owner.get_or_null(p_joint); |
1361 | ERR_FAIL_COND(!joint); |
1362 | ERR_FAIL_COND(joint->get_type() != JOINT_TYPE_HINGE); |
1363 | GodotHingeJoint3D *hinge_joint = static_cast<GodotHingeJoint3D *>(joint); |
1364 | hinge_joint->set_flag(p_flag, p_value); |
1365 | } |
1366 | |
1367 | bool GodotPhysicsServer3D::hinge_joint_get_flag(RID p_joint, HingeJointFlag p_flag) const { |
1368 | GodotJoint3D *joint = joint_owner.get_or_null(p_joint); |
1369 | ERR_FAIL_COND_V(!joint, false); |
1370 | ERR_FAIL_COND_V(joint->get_type() != JOINT_TYPE_HINGE, false); |
1371 | GodotHingeJoint3D *hinge_joint = static_cast<GodotHingeJoint3D *>(joint); |
1372 | return hinge_joint->get_flag(p_flag); |
1373 | } |
1374 | |
1375 | void GodotPhysicsServer3D::joint_set_solver_priority(RID p_joint, int p_priority) { |
1376 | GodotJoint3D *joint = joint_owner.get_or_null(p_joint); |
1377 | ERR_FAIL_COND(!joint); |
1378 | joint->set_priority(p_priority); |
1379 | } |
1380 | |
1381 | int GodotPhysicsServer3D::joint_get_solver_priority(RID p_joint) const { |
1382 | GodotJoint3D *joint = joint_owner.get_or_null(p_joint); |
1383 | ERR_FAIL_COND_V(!joint, 0); |
1384 | return joint->get_priority(); |
1385 | } |
1386 | |
1387 | void GodotPhysicsServer3D::joint_disable_collisions_between_bodies(RID p_joint, bool p_disable) { |
1388 | GodotJoint3D *joint = joint_owner.get_or_null(p_joint); |
1389 | ERR_FAIL_COND(!joint); |
1390 | |
1391 | joint->disable_collisions_between_bodies(p_disable); |
1392 | |
1393 | if (2 == joint->get_body_count()) { |
1394 | GodotBody3D *body_a = *joint->get_body_ptr(); |
1395 | GodotBody3D *body_b = *(joint->get_body_ptr() + 1); |
1396 | |
1397 | if (p_disable) { |
1398 | body_add_collision_exception(body_a->get_self(), body_b->get_self()); |
1399 | body_add_collision_exception(body_b->get_self(), body_a->get_self()); |
1400 | } else { |
1401 | body_remove_collision_exception(body_a->get_self(), body_b->get_self()); |
1402 | body_remove_collision_exception(body_b->get_self(), body_a->get_self()); |
1403 | } |
1404 | } |
1405 | } |
1406 | |
1407 | bool GodotPhysicsServer3D::joint_is_disabled_collisions_between_bodies(RID p_joint) const { |
1408 | GodotJoint3D *joint = joint_owner.get_or_null(p_joint); |
1409 | ERR_FAIL_COND_V(!joint, true); |
1410 | |
1411 | return joint->is_disabled_collisions_between_bodies(); |
1412 | } |
1413 | |
1414 | GodotPhysicsServer3D::JointType GodotPhysicsServer3D::joint_get_type(RID p_joint) const { |
1415 | GodotJoint3D *joint = joint_owner.get_or_null(p_joint); |
1416 | ERR_FAIL_COND_V(!joint, JOINT_TYPE_PIN); |
1417 | return joint->get_type(); |
1418 | } |
1419 | |
1420 | void GodotPhysicsServer3D::joint_make_slider(RID p_joint, RID p_body_A, const Transform3D &p_local_frame_A, RID p_body_B, const Transform3D &p_local_frame_B) { |
1421 | GodotBody3D *body_A = body_owner.get_or_null(p_body_A); |
1422 | ERR_FAIL_COND(!body_A); |
1423 | |
1424 | if (!p_body_B.is_valid()) { |
1425 | ERR_FAIL_COND(!body_A->get_space()); |
1426 | p_body_B = body_A->get_space()->get_static_global_body(); |
1427 | } |
1428 | |
1429 | GodotBody3D *body_B = body_owner.get_or_null(p_body_B); |
1430 | ERR_FAIL_COND(!body_B); |
1431 | |
1432 | ERR_FAIL_COND(body_A == body_B); |
1433 | |
1434 | GodotJoint3D *prev_joint = joint_owner.get_or_null(p_joint); |
1435 | ERR_FAIL_COND(prev_joint == nullptr); |
1436 | |
1437 | GodotJoint3D *joint = memnew(GodotSliderJoint3D(body_A, body_B, p_local_frame_A, p_local_frame_B)); |
1438 | |
1439 | joint->copy_settings_from(prev_joint); |
1440 | joint_owner.replace(p_joint, joint); |
1441 | memdelete(prev_joint); |
1442 | } |
1443 | |
1444 | void GodotPhysicsServer3D::slider_joint_set_param(RID p_joint, SliderJointParam p_param, real_t p_value) { |
1445 | GodotJoint3D *joint = joint_owner.get_or_null(p_joint); |
1446 | ERR_FAIL_COND(!joint); |
1447 | ERR_FAIL_COND(joint->get_type() != JOINT_TYPE_SLIDER); |
1448 | GodotSliderJoint3D *slider_joint = static_cast<GodotSliderJoint3D *>(joint); |
1449 | slider_joint->set_param(p_param, p_value); |
1450 | } |
1451 | |
1452 | real_t GodotPhysicsServer3D::slider_joint_get_param(RID p_joint, SliderJointParam p_param) const { |
1453 | GodotJoint3D *joint = joint_owner.get_or_null(p_joint); |
1454 | ERR_FAIL_COND_V(!joint, 0); |
1455 | ERR_FAIL_COND_V(joint->get_type() != JOINT_TYPE_CONE_TWIST, 0); |
1456 | GodotSliderJoint3D *slider_joint = static_cast<GodotSliderJoint3D *>(joint); |
1457 | return slider_joint->get_param(p_param); |
1458 | } |
1459 | |
1460 | void GodotPhysicsServer3D::joint_make_cone_twist(RID p_joint, RID p_body_A, const Transform3D &p_local_frame_A, RID p_body_B, const Transform3D &p_local_frame_B) { |
1461 | GodotBody3D *body_A = body_owner.get_or_null(p_body_A); |
1462 | ERR_FAIL_COND(!body_A); |
1463 | |
1464 | if (!p_body_B.is_valid()) { |
1465 | ERR_FAIL_COND(!body_A->get_space()); |
1466 | p_body_B = body_A->get_space()->get_static_global_body(); |
1467 | } |
1468 | |
1469 | GodotBody3D *body_B = body_owner.get_or_null(p_body_B); |
1470 | ERR_FAIL_COND(!body_B); |
1471 | |
1472 | ERR_FAIL_COND(body_A == body_B); |
1473 | |
1474 | GodotJoint3D *prev_joint = joint_owner.get_or_null(p_joint); |
1475 | ERR_FAIL_COND(prev_joint == nullptr); |
1476 | |
1477 | GodotJoint3D *joint = memnew(GodotConeTwistJoint3D(body_A, body_B, p_local_frame_A, p_local_frame_B)); |
1478 | |
1479 | joint->copy_settings_from(prev_joint); |
1480 | joint_owner.replace(p_joint, joint); |
1481 | memdelete(prev_joint); |
1482 | } |
1483 | |
1484 | void GodotPhysicsServer3D::cone_twist_joint_set_param(RID p_joint, ConeTwistJointParam p_param, real_t p_value) { |
1485 | GodotJoint3D *joint = joint_owner.get_or_null(p_joint); |
1486 | ERR_FAIL_COND(!joint); |
1487 | ERR_FAIL_COND(joint->get_type() != JOINT_TYPE_CONE_TWIST); |
1488 | GodotConeTwistJoint3D *cone_twist_joint = static_cast<GodotConeTwistJoint3D *>(joint); |
1489 | cone_twist_joint->set_param(p_param, p_value); |
1490 | } |
1491 | |
1492 | real_t GodotPhysicsServer3D::cone_twist_joint_get_param(RID p_joint, ConeTwistJointParam p_param) const { |
1493 | GodotJoint3D *joint = joint_owner.get_or_null(p_joint); |
1494 | ERR_FAIL_COND_V(!joint, 0); |
1495 | ERR_FAIL_COND_V(joint->get_type() != JOINT_TYPE_CONE_TWIST, 0); |
1496 | GodotConeTwistJoint3D *cone_twist_joint = static_cast<GodotConeTwistJoint3D *>(joint); |
1497 | return cone_twist_joint->get_param(p_param); |
1498 | } |
1499 | |
1500 | void GodotPhysicsServer3D::joint_make_generic_6dof(RID p_joint, RID p_body_A, const Transform3D &p_local_frame_A, RID p_body_B, const Transform3D &p_local_frame_B) { |
1501 | GodotBody3D *body_A = body_owner.get_or_null(p_body_A); |
1502 | ERR_FAIL_COND(!body_A); |
1503 | |
1504 | if (!p_body_B.is_valid()) { |
1505 | ERR_FAIL_COND(!body_A->get_space()); |
1506 | p_body_B = body_A->get_space()->get_static_global_body(); |
1507 | } |
1508 | |
1509 | GodotBody3D *body_B = body_owner.get_or_null(p_body_B); |
1510 | ERR_FAIL_COND(!body_B); |
1511 | |
1512 | ERR_FAIL_COND(body_A == body_B); |
1513 | |
1514 | GodotJoint3D *prev_joint = joint_owner.get_or_null(p_joint); |
1515 | ERR_FAIL_COND(prev_joint == nullptr); |
1516 | |
1517 | GodotJoint3D *joint = memnew(GodotGeneric6DOFJoint3D(body_A, body_B, p_local_frame_A, p_local_frame_B, true)); |
1518 | |
1519 | joint->copy_settings_from(prev_joint); |
1520 | joint_owner.replace(p_joint, joint); |
1521 | memdelete(prev_joint); |
1522 | } |
1523 | |
1524 | void GodotPhysicsServer3D::generic_6dof_joint_set_param(RID p_joint, Vector3::Axis p_axis, G6DOFJointAxisParam p_param, real_t p_value) { |
1525 | GodotJoint3D *joint = joint_owner.get_or_null(p_joint); |
1526 | ERR_FAIL_COND(!joint); |
1527 | ERR_FAIL_COND(joint->get_type() != JOINT_TYPE_6DOF); |
1528 | GodotGeneric6DOFJoint3D *generic_6dof_joint = static_cast<GodotGeneric6DOFJoint3D *>(joint); |
1529 | generic_6dof_joint->set_param(p_axis, p_param, p_value); |
1530 | } |
1531 | |
1532 | real_t GodotPhysicsServer3D::generic_6dof_joint_get_param(RID p_joint, Vector3::Axis p_axis, G6DOFJointAxisParam p_param) const { |
1533 | GodotJoint3D *joint = joint_owner.get_or_null(p_joint); |
1534 | ERR_FAIL_COND_V(!joint, 0); |
1535 | ERR_FAIL_COND_V(joint->get_type() != JOINT_TYPE_6DOF, 0); |
1536 | GodotGeneric6DOFJoint3D *generic_6dof_joint = static_cast<GodotGeneric6DOFJoint3D *>(joint); |
1537 | return generic_6dof_joint->get_param(p_axis, p_param); |
1538 | } |
1539 | |
1540 | void GodotPhysicsServer3D::generic_6dof_joint_set_flag(RID p_joint, Vector3::Axis p_axis, G6DOFJointAxisFlag p_flag, bool p_enable) { |
1541 | GodotJoint3D *joint = joint_owner.get_or_null(p_joint); |
1542 | ERR_FAIL_COND(!joint); |
1543 | ERR_FAIL_COND(joint->get_type() != JOINT_TYPE_6DOF); |
1544 | GodotGeneric6DOFJoint3D *generic_6dof_joint = static_cast<GodotGeneric6DOFJoint3D *>(joint); |
1545 | generic_6dof_joint->set_flag(p_axis, p_flag, p_enable); |
1546 | } |
1547 | |
1548 | bool GodotPhysicsServer3D::generic_6dof_joint_get_flag(RID p_joint, Vector3::Axis p_axis, G6DOFJointAxisFlag p_flag) const { |
1549 | GodotJoint3D *joint = joint_owner.get_or_null(p_joint); |
1550 | ERR_FAIL_COND_V(!joint, false); |
1551 | ERR_FAIL_COND_V(joint->get_type() != JOINT_TYPE_6DOF, false); |
1552 | GodotGeneric6DOFJoint3D *generic_6dof_joint = static_cast<GodotGeneric6DOFJoint3D *>(joint); |
1553 | return generic_6dof_joint->get_flag(p_axis, p_flag); |
1554 | } |
1555 | |
1556 | void GodotPhysicsServer3D::free(RID p_rid) { |
1557 | _update_shapes(); //just in case |
1558 | |
1559 | if (shape_owner.owns(p_rid)) { |
1560 | GodotShape3D *shape = shape_owner.get_or_null(p_rid); |
1561 | |
1562 | while (shape->get_owners().size()) { |
1563 | GodotShapeOwner3D *so = shape->get_owners().begin()->key; |
1564 | so->remove_shape(shape); |
1565 | } |
1566 | |
1567 | shape_owner.free(p_rid); |
1568 | memdelete(shape); |
1569 | } else if (body_owner.owns(p_rid)) { |
1570 | GodotBody3D *body = body_owner.get_or_null(p_rid); |
1571 | |
1572 | body->set_space(nullptr); |
1573 | |
1574 | while (body->get_shape_count()) { |
1575 | body->remove_shape(0); |
1576 | } |
1577 | |
1578 | body_owner.free(p_rid); |
1579 | memdelete(body); |
1580 | } else if (soft_body_owner.owns(p_rid)) { |
1581 | GodotSoftBody3D *soft_body = soft_body_owner.get_or_null(p_rid); |
1582 | |
1583 | soft_body->set_space(nullptr); |
1584 | |
1585 | soft_body_owner.free(p_rid); |
1586 | memdelete(soft_body); |
1587 | } else if (area_owner.owns(p_rid)) { |
1588 | GodotArea3D *area = area_owner.get_or_null(p_rid); |
1589 | |
1590 | area->set_space(nullptr); |
1591 | |
1592 | while (area->get_shape_count()) { |
1593 | area->remove_shape(0); |
1594 | } |
1595 | |
1596 | area_owner.free(p_rid); |
1597 | memdelete(area); |
1598 | } else if (space_owner.owns(p_rid)) { |
1599 | GodotSpace3D *space = space_owner.get_or_null(p_rid); |
1600 | |
1601 | while (space->get_objects().size()) { |
1602 | GodotCollisionObject3D *co = static_cast<GodotCollisionObject3D *>(*space->get_objects().begin()); |
1603 | co->set_space(nullptr); |
1604 | } |
1605 | |
1606 | active_spaces.erase(space); |
1607 | free(space->get_default_area()->get_self()); |
1608 | free(space->get_static_global_body()); |
1609 | |
1610 | space_owner.free(p_rid); |
1611 | memdelete(space); |
1612 | } else if (joint_owner.owns(p_rid)) { |
1613 | GodotJoint3D *joint = joint_owner.get_or_null(p_rid); |
1614 | |
1615 | joint_owner.free(p_rid); |
1616 | memdelete(joint); |
1617 | |
1618 | } else { |
1619 | ERR_FAIL_MSG("Invalid ID." ); |
1620 | } |
1621 | } |
1622 | |
1623 | void GodotPhysicsServer3D::set_active(bool p_active) { |
1624 | active = p_active; |
1625 | } |
1626 | |
1627 | void GodotPhysicsServer3D::init() { |
1628 | stepper = memnew(GodotStep3D); |
1629 | } |
1630 | |
1631 | void GodotPhysicsServer3D::step(real_t p_step) { |
1632 | #ifndef _3D_DISABLED |
1633 | |
1634 | if (!active) { |
1635 | return; |
1636 | } |
1637 | |
1638 | _update_shapes(); |
1639 | |
1640 | island_count = 0; |
1641 | active_objects = 0; |
1642 | collision_pairs = 0; |
1643 | for (const GodotSpace3D *E : active_spaces) { |
1644 | stepper->step(const_cast<GodotSpace3D *>(E), p_step); |
1645 | island_count += E->get_island_count(); |
1646 | active_objects += E->get_active_objects(); |
1647 | collision_pairs += E->get_collision_pairs(); |
1648 | } |
1649 | #endif |
1650 | } |
1651 | |
1652 | void GodotPhysicsServer3D::sync() { |
1653 | doing_sync = true; |
1654 | } |
1655 | |
1656 | void GodotPhysicsServer3D::flush_queries() { |
1657 | #ifndef _3D_DISABLED |
1658 | |
1659 | if (!active) { |
1660 | return; |
1661 | } |
1662 | |
1663 | flushing_queries = true; |
1664 | |
1665 | uint64_t time_beg = OS::get_singleton()->get_ticks_usec(); |
1666 | |
1667 | for (const GodotSpace3D *E : active_spaces) { |
1668 | GodotSpace3D *space = const_cast<GodotSpace3D *>(E); |
1669 | space->call_queries(); |
1670 | } |
1671 | |
1672 | flushing_queries = false; |
1673 | |
1674 | if (EngineDebugger::is_profiling("servers" )) { |
1675 | uint64_t total_time[GodotSpace3D::ELAPSED_TIME_MAX]; |
1676 | static const char *time_name[GodotSpace3D::ELAPSED_TIME_MAX] = { |
1677 | "integrate_forces" , |
1678 | "generate_islands" , |
1679 | "setup_constraints" , |
1680 | "solve_constraints" , |
1681 | "integrate_velocities" |
1682 | }; |
1683 | |
1684 | for (int i = 0; i < GodotSpace3D::ELAPSED_TIME_MAX; i++) { |
1685 | total_time[i] = 0; |
1686 | } |
1687 | |
1688 | for (const GodotSpace3D *E : active_spaces) { |
1689 | for (int i = 0; i < GodotSpace3D::ELAPSED_TIME_MAX; i++) { |
1690 | total_time[i] += E->get_elapsed_time(GodotSpace3D::ElapsedTime(i)); |
1691 | } |
1692 | } |
1693 | |
1694 | Array values; |
1695 | values.resize(GodotSpace3D::ELAPSED_TIME_MAX * 2); |
1696 | for (int i = 0; i < GodotSpace3D::ELAPSED_TIME_MAX; i++) { |
1697 | values[i * 2 + 0] = time_name[i]; |
1698 | values[i * 2 + 1] = USEC_TO_SEC(total_time[i]); |
1699 | } |
1700 | values.push_back("flush_queries" ); |
1701 | values.push_back(USEC_TO_SEC(OS::get_singleton()->get_ticks_usec() - time_beg)); |
1702 | |
1703 | values.push_front("physics_3d" ); |
1704 | EngineDebugger::profiler_add_frame_data("servers" , values); |
1705 | } |
1706 | #endif |
1707 | } |
1708 | |
1709 | void GodotPhysicsServer3D::end_sync() { |
1710 | doing_sync = false; |
1711 | } |
1712 | |
1713 | void GodotPhysicsServer3D::finish() { |
1714 | memdelete(stepper); |
1715 | } |
1716 | |
1717 | int GodotPhysicsServer3D::get_process_info(ProcessInfo p_info) { |
1718 | switch (p_info) { |
1719 | case INFO_ACTIVE_OBJECTS: { |
1720 | return active_objects; |
1721 | } break; |
1722 | case INFO_COLLISION_PAIRS: { |
1723 | return collision_pairs; |
1724 | } break; |
1725 | case INFO_ISLAND_COUNT: { |
1726 | return island_count; |
1727 | } break; |
1728 | } |
1729 | |
1730 | return 0; |
1731 | } |
1732 | |
1733 | void GodotPhysicsServer3D::_update_shapes() { |
1734 | while (pending_shape_update_list.first()) { |
1735 | pending_shape_update_list.first()->self()->_shape_changed(); |
1736 | pending_shape_update_list.remove(pending_shape_update_list.first()); |
1737 | } |
1738 | } |
1739 | |
1740 | void GodotPhysicsServer3D::_shape_col_cbk(const Vector3 &p_point_A, int p_index_A, const Vector3 &p_point_B, int p_index_B, const Vector3 &normal, void *p_userdata) { |
1741 | CollCbkData *cbk = static_cast<CollCbkData *>(p_userdata); |
1742 | |
1743 | if (cbk->max == 0) { |
1744 | return; |
1745 | } |
1746 | |
1747 | if (cbk->amount == cbk->max) { |
1748 | //find least deep |
1749 | real_t min_depth = 1e20; |
1750 | int min_depth_idx = 0; |
1751 | for (int i = 0; i < cbk->amount; i++) { |
1752 | real_t d = cbk->ptr[i * 2 + 0].distance_squared_to(cbk->ptr[i * 2 + 1]); |
1753 | if (d < min_depth) { |
1754 | min_depth = d; |
1755 | min_depth_idx = i; |
1756 | } |
1757 | } |
1758 | |
1759 | real_t d = p_point_A.distance_squared_to(p_point_B); |
1760 | if (d < min_depth) { |
1761 | return; |
1762 | } |
1763 | cbk->ptr[min_depth_idx * 2 + 0] = p_point_A; |
1764 | cbk->ptr[min_depth_idx * 2 + 1] = p_point_B; |
1765 | |
1766 | } else { |
1767 | cbk->ptr[cbk->amount * 2 + 0] = p_point_A; |
1768 | cbk->ptr[cbk->amount * 2 + 1] = p_point_B; |
1769 | cbk->amount++; |
1770 | } |
1771 | } |
1772 | |
1773 | GodotPhysicsServer3D *GodotPhysicsServer3D::godot_singleton = nullptr; |
1774 | GodotPhysicsServer3D::GodotPhysicsServer3D(bool p_using_threads) { |
1775 | godot_singleton = this; |
1776 | GodotBroadPhase3D::create_func = GodotBroadPhase3DBVH::_create; |
1777 | |
1778 | using_threads = p_using_threads; |
1779 | }; |
1780 | |