Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
godotengine
GitHub Repository: godotengine/godot
Path: blob/master/modules/godot_physics_2d/godot_physics_server_2d.cpp
10277 views
1
/**************************************************************************/
2
/* godot_physics_server_2d.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_2d.h"
32
33
#include "godot_body_direct_state_2d.h"
34
#include "godot_broad_phase_2d_bvh.h"
35
#include "godot_collision_solver_2d.h"
36
37
#include "core/config/project_settings.h"
38
#include "core/debugger/engine_debugger.h"
39
#include "core/os/os.h"
40
41
#define FLUSH_QUERY_CHECK(m_object) \
42
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.");
43
44
RID GodotPhysicsServer2D::_shape_create(ShapeType p_shape) {
45
GodotShape2D *shape = nullptr;
46
switch (p_shape) {
47
case SHAPE_WORLD_BOUNDARY: {
48
shape = memnew(GodotWorldBoundaryShape2D);
49
} break;
50
case SHAPE_SEPARATION_RAY: {
51
shape = memnew(GodotSeparationRayShape2D);
52
} break;
53
case SHAPE_SEGMENT: {
54
shape = memnew(GodotSegmentShape2D);
55
} break;
56
case SHAPE_CIRCLE: {
57
shape = memnew(GodotCircleShape2D);
58
} break;
59
case SHAPE_RECTANGLE: {
60
shape = memnew(GodotRectangleShape2D);
61
} break;
62
case SHAPE_CAPSULE: {
63
shape = memnew(GodotCapsuleShape2D);
64
} break;
65
case SHAPE_CONVEX_POLYGON: {
66
shape = memnew(GodotConvexPolygonShape2D);
67
} break;
68
case SHAPE_CONCAVE_POLYGON: {
69
shape = memnew(GodotConcavePolygonShape2D);
70
} break;
71
case SHAPE_CUSTOM: {
72
ERR_FAIL_V(RID());
73
74
} break;
75
}
76
77
RID id = shape_owner.make_rid(shape);
78
shape->set_self(id);
79
80
return id;
81
}
82
83
RID GodotPhysicsServer2D::world_boundary_shape_create() {
84
return _shape_create(SHAPE_WORLD_BOUNDARY);
85
}
86
87
RID GodotPhysicsServer2D::separation_ray_shape_create() {
88
return _shape_create(SHAPE_SEPARATION_RAY);
89
}
90
91
RID GodotPhysicsServer2D::segment_shape_create() {
92
return _shape_create(SHAPE_SEGMENT);
93
}
94
95
RID GodotPhysicsServer2D::circle_shape_create() {
96
return _shape_create(SHAPE_CIRCLE);
97
}
98
99
RID GodotPhysicsServer2D::rectangle_shape_create() {
100
return _shape_create(SHAPE_RECTANGLE);
101
}
102
103
RID GodotPhysicsServer2D::capsule_shape_create() {
104
return _shape_create(SHAPE_CAPSULE);
105
}
106
107
RID GodotPhysicsServer2D::convex_polygon_shape_create() {
108
return _shape_create(SHAPE_CONVEX_POLYGON);
109
}
110
111
RID GodotPhysicsServer2D::concave_polygon_shape_create() {
112
return _shape_create(SHAPE_CONCAVE_POLYGON);
113
}
114
115
void GodotPhysicsServer2D::shape_set_data(RID p_shape, const Variant &p_data) {
116
GodotShape2D *shape = shape_owner.get_or_null(p_shape);
117
ERR_FAIL_NULL(shape);
118
shape->set_data(p_data);
119
}
120
121
void GodotPhysicsServer2D::shape_set_custom_solver_bias(RID p_shape, real_t p_bias) {
122
GodotShape2D *shape = shape_owner.get_or_null(p_shape);
123
ERR_FAIL_NULL(shape);
124
shape->set_custom_bias(p_bias);
125
}
126
127
PhysicsServer2D::ShapeType GodotPhysicsServer2D::shape_get_type(RID p_shape) const {
128
const GodotShape2D *shape = shape_owner.get_or_null(p_shape);
129
ERR_FAIL_NULL_V(shape, SHAPE_CUSTOM);
130
return shape->get_type();
131
}
132
133
Variant GodotPhysicsServer2D::shape_get_data(RID p_shape) const {
134
const GodotShape2D *shape = shape_owner.get_or_null(p_shape);
135
ERR_FAIL_NULL_V(shape, Variant());
136
ERR_FAIL_COND_V(!shape->is_configured(), Variant());
137
return shape->get_data();
138
}
139
140
real_t GodotPhysicsServer2D::shape_get_custom_solver_bias(RID p_shape) const {
141
const GodotShape2D *shape = shape_owner.get_or_null(p_shape);
142
ERR_FAIL_NULL_V(shape, 0);
143
return shape->get_custom_bias();
144
}
145
146
void GodotPhysicsServer2D::_shape_col_cbk(const Vector2 &p_point_A, const Vector2 &p_point_B, void *p_userdata) {
147
CollCbkData *cbk = static_cast<CollCbkData *>(p_userdata);
148
149
if (cbk->max == 0) {
150
return;
151
}
152
153
Vector2 rel_dir = (p_point_A - p_point_B);
154
real_t rel_length2 = rel_dir.length_squared();
155
if (cbk->valid_dir != Vector2()) {
156
if (cbk->valid_depth < 10e20) {
157
if (rel_length2 > cbk->valid_depth * cbk->valid_depth ||
158
(rel_length2 > CMP_EPSILON && cbk->valid_dir.dot(rel_dir.normalized()) < CMP_EPSILON)) {
159
cbk->invalid_by_dir++;
160
return;
161
}
162
} else {
163
if (rel_length2 > 0 && cbk->valid_dir.dot(rel_dir.normalized()) < CMP_EPSILON) {
164
return;
165
}
166
}
167
}
168
169
if (cbk->amount == cbk->max) {
170
//find least deep
171
real_t min_depth = 1e20;
172
int min_depth_idx = 0;
173
for (int i = 0; i < cbk->amount; i++) {
174
real_t d = cbk->ptr[i * 2 + 0].distance_squared_to(cbk->ptr[i * 2 + 1]);
175
if (d < min_depth) {
176
min_depth = d;
177
min_depth_idx = i;
178
}
179
}
180
181
if (rel_length2 < min_depth) {
182
return;
183
}
184
cbk->ptr[min_depth_idx * 2 + 0] = p_point_A;
185
cbk->ptr[min_depth_idx * 2 + 1] = p_point_B;
186
cbk->passed++;
187
188
} else {
189
cbk->ptr[cbk->amount * 2 + 0] = p_point_A;
190
cbk->ptr[cbk->amount * 2 + 1] = p_point_B;
191
cbk->amount++;
192
cbk->passed++;
193
}
194
}
195
196
bool GodotPhysicsServer2D::shape_collide(RID p_shape_A, const Transform2D &p_xform_A, const Vector2 &p_motion_A, RID p_shape_B, const Transform2D &p_xform_B, const Vector2 &p_motion_B, Vector2 *r_results, int p_result_max, int &r_result_count) {
197
GodotShape2D *shape_A = shape_owner.get_or_null(p_shape_A);
198
ERR_FAIL_NULL_V(shape_A, false);
199
GodotShape2D *shape_B = shape_owner.get_or_null(p_shape_B);
200
ERR_FAIL_NULL_V(shape_B, false);
201
202
if (p_result_max == 0) {
203
return GodotCollisionSolver2D::solve(shape_A, p_xform_A, p_motion_A, shape_B, p_xform_B, p_motion_B, nullptr, nullptr);
204
}
205
206
CollCbkData cbk;
207
cbk.max = p_result_max;
208
cbk.amount = 0;
209
cbk.passed = 0;
210
cbk.ptr = r_results;
211
212
bool res = GodotCollisionSolver2D::solve(shape_A, p_xform_A, p_motion_A, shape_B, p_xform_B, p_motion_B, _shape_col_cbk, &cbk);
213
r_result_count = cbk.amount;
214
return res;
215
}
216
217
RID GodotPhysicsServer2D::space_create() {
218
GodotSpace2D *space = memnew(GodotSpace2D);
219
RID id = space_owner.make_rid(space);
220
space->set_self(id);
221
RID area_id = area_create();
222
GodotArea2D *area = area_owner.get_or_null(area_id);
223
ERR_FAIL_NULL_V(area, RID());
224
space->set_default_area(area);
225
area->set_space(space);
226
area->set_priority(-1);
227
228
return id;
229
}
230
231
void GodotPhysicsServer2D::space_set_active(RID p_space, bool p_active) {
232
GodotSpace2D *space = space_owner.get_or_null(p_space);
233
ERR_FAIL_NULL(space);
234
if (p_active) {
235
active_spaces.insert(space);
236
} else {
237
active_spaces.erase(space);
238
}
239
}
240
241
bool GodotPhysicsServer2D::space_is_active(RID p_space) const {
242
GodotSpace2D *space = space_owner.get_or_null(p_space);
243
ERR_FAIL_NULL_V(space, false);
244
245
return active_spaces.has(space);
246
}
247
248
void GodotPhysicsServer2D::space_set_param(RID p_space, SpaceParameter p_param, real_t p_value) {
249
GodotSpace2D *space = space_owner.get_or_null(p_space);
250
ERR_FAIL_NULL(space);
251
252
space->set_param(p_param, p_value);
253
}
254
255
real_t GodotPhysicsServer2D::space_get_param(RID p_space, SpaceParameter p_param) const {
256
const GodotSpace2D *space = space_owner.get_or_null(p_space);
257
ERR_FAIL_NULL_V(space, 0);
258
return space->get_param(p_param);
259
}
260
261
void GodotPhysicsServer2D::space_set_debug_contacts(RID p_space, int p_max_contacts) {
262
GodotSpace2D *space = space_owner.get_or_null(p_space);
263
ERR_FAIL_NULL(space);
264
space->set_debug_contacts(p_max_contacts);
265
}
266
267
Vector<Vector2> GodotPhysicsServer2D::space_get_contacts(RID p_space) const {
268
GodotSpace2D *space = space_owner.get_or_null(p_space);
269
ERR_FAIL_NULL_V(space, Vector<Vector2>());
270
return space->get_debug_contacts();
271
}
272
273
int GodotPhysicsServer2D::space_get_contact_count(RID p_space) const {
274
GodotSpace2D *space = space_owner.get_or_null(p_space);
275
ERR_FAIL_NULL_V(space, 0);
276
return space->get_debug_contact_count();
277
}
278
279
PhysicsDirectSpaceState2D *GodotPhysicsServer2D::space_get_direct_state(RID p_space) {
280
GodotSpace2D *space = space_owner.get_or_null(p_space);
281
ERR_FAIL_NULL_V(space, nullptr);
282
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.");
283
284
return space->get_direct_state();
285
}
286
287
RID GodotPhysicsServer2D::area_create() {
288
GodotArea2D *area = memnew(GodotArea2D);
289
RID rid = area_owner.make_rid(area);
290
area->set_self(rid);
291
return rid;
292
}
293
294
void GodotPhysicsServer2D::area_set_space(RID p_area, RID p_space) {
295
GodotArea2D *area = area_owner.get_or_null(p_area);
296
ERR_FAIL_NULL(area);
297
298
GodotSpace2D *space = nullptr;
299
if (p_space.is_valid()) {
300
space = space_owner.get_or_null(p_space);
301
ERR_FAIL_NULL(space);
302
}
303
304
if (area->get_space() == space) {
305
return; //pointless
306
}
307
308
area->clear_constraints();
309
area->set_space(space);
310
}
311
312
RID GodotPhysicsServer2D::area_get_space(RID p_area) const {
313
GodotArea2D *area = area_owner.get_or_null(p_area);
314
ERR_FAIL_NULL_V(area, RID());
315
316
GodotSpace2D *space = area->get_space();
317
if (!space) {
318
return RID();
319
}
320
return space->get_self();
321
}
322
323
void GodotPhysicsServer2D::area_add_shape(RID p_area, RID p_shape, const Transform2D &p_transform, bool p_disabled) {
324
GodotArea2D *area = area_owner.get_or_null(p_area);
325
ERR_FAIL_NULL(area);
326
327
GodotShape2D *shape = shape_owner.get_or_null(p_shape);
328
ERR_FAIL_NULL(shape);
329
330
area->add_shape(shape, p_transform, p_disabled);
331
}
332
333
void GodotPhysicsServer2D::area_set_shape(RID p_area, int p_shape_idx, RID p_shape) {
334
GodotArea2D *area = area_owner.get_or_null(p_area);
335
ERR_FAIL_NULL(area);
336
337
GodotShape2D *shape = shape_owner.get_or_null(p_shape);
338
ERR_FAIL_NULL(shape);
339
ERR_FAIL_COND(!shape->is_configured());
340
341
area->set_shape(p_shape_idx, shape);
342
}
343
344
void GodotPhysicsServer2D::area_set_shape_transform(RID p_area, int p_shape_idx, const Transform2D &p_transform) {
345
GodotArea2D *area = area_owner.get_or_null(p_area);
346
ERR_FAIL_NULL(area);
347
348
area->set_shape_transform(p_shape_idx, p_transform);
349
}
350
351
void GodotPhysicsServer2D::area_set_shape_disabled(RID p_area, int p_shape, bool p_disabled) {
352
GodotArea2D *area = area_owner.get_or_null(p_area);
353
ERR_FAIL_NULL(area);
354
ERR_FAIL_INDEX(p_shape, area->get_shape_count());
355
FLUSH_QUERY_CHECK(area);
356
357
area->set_shape_disabled(p_shape, p_disabled);
358
}
359
360
int GodotPhysicsServer2D::area_get_shape_count(RID p_area) const {
361
GodotArea2D *area = area_owner.get_or_null(p_area);
362
ERR_FAIL_NULL_V(area, -1);
363
364
return area->get_shape_count();
365
}
366
367
RID GodotPhysicsServer2D::area_get_shape(RID p_area, int p_shape_idx) const {
368
GodotArea2D *area = area_owner.get_or_null(p_area);
369
ERR_FAIL_NULL_V(area, RID());
370
371
GodotShape2D *shape = area->get_shape(p_shape_idx);
372
ERR_FAIL_NULL_V(shape, RID());
373
374
return shape->get_self();
375
}
376
377
Transform2D GodotPhysicsServer2D::area_get_shape_transform(RID p_area, int p_shape_idx) const {
378
GodotArea2D *area = area_owner.get_or_null(p_area);
379
ERR_FAIL_NULL_V(area, Transform2D());
380
381
return area->get_shape_transform(p_shape_idx);
382
}
383
384
void GodotPhysicsServer2D::area_remove_shape(RID p_area, int p_shape_idx) {
385
GodotArea2D *area = area_owner.get_or_null(p_area);
386
ERR_FAIL_NULL(area);
387
388
area->remove_shape(p_shape_idx);
389
}
390
391
void GodotPhysicsServer2D::area_clear_shapes(RID p_area) {
392
GodotArea2D *area = area_owner.get_or_null(p_area);
393
ERR_FAIL_NULL(area);
394
395
while (area->get_shape_count()) {
396
area->remove_shape(0);
397
}
398
}
399
400
void GodotPhysicsServer2D::area_attach_object_instance_id(RID p_area, ObjectID p_id) {
401
if (space_owner.owns(p_area)) {
402
GodotSpace2D *space = space_owner.get_or_null(p_area);
403
p_area = space->get_default_area()->get_self();
404
}
405
GodotArea2D *area = area_owner.get_or_null(p_area);
406
ERR_FAIL_NULL(area);
407
area->set_instance_id(p_id);
408
}
409
410
ObjectID GodotPhysicsServer2D::area_get_object_instance_id(RID p_area) const {
411
if (space_owner.owns(p_area)) {
412
GodotSpace2D *space = space_owner.get_or_null(p_area);
413
p_area = space->get_default_area()->get_self();
414
}
415
GodotArea2D *area = area_owner.get_or_null(p_area);
416
ERR_FAIL_NULL_V(area, ObjectID());
417
return area->get_instance_id();
418
}
419
420
void GodotPhysicsServer2D::area_attach_canvas_instance_id(RID p_area, ObjectID p_id) {
421
if (space_owner.owns(p_area)) {
422
GodotSpace2D *space = space_owner.get_or_null(p_area);
423
p_area = space->get_default_area()->get_self();
424
}
425
GodotArea2D *area = area_owner.get_or_null(p_area);
426
ERR_FAIL_NULL(area);
427
area->set_canvas_instance_id(p_id);
428
}
429
430
ObjectID GodotPhysicsServer2D::area_get_canvas_instance_id(RID p_area) const {
431
if (space_owner.owns(p_area)) {
432
GodotSpace2D *space = space_owner.get_or_null(p_area);
433
p_area = space->get_default_area()->get_self();
434
}
435
GodotArea2D *area = area_owner.get_or_null(p_area);
436
ERR_FAIL_NULL_V(area, ObjectID());
437
return area->get_canvas_instance_id();
438
}
439
440
void GodotPhysicsServer2D::area_set_param(RID p_area, AreaParameter p_param, const Variant &p_value) {
441
if (space_owner.owns(p_area)) {
442
GodotSpace2D *space = space_owner.get_or_null(p_area);
443
p_area = space->get_default_area()->get_self();
444
}
445
GodotArea2D *area = area_owner.get_or_null(p_area);
446
ERR_FAIL_NULL(area);
447
area->set_param(p_param, p_value);
448
}
449
450
void GodotPhysicsServer2D::area_set_transform(RID p_area, const Transform2D &p_transform) {
451
GodotArea2D *area = area_owner.get_or_null(p_area);
452
ERR_FAIL_NULL(area);
453
area->set_transform(p_transform);
454
}
455
456
Variant GodotPhysicsServer2D::area_get_param(RID p_area, AreaParameter p_param) const {
457
if (space_owner.owns(p_area)) {
458
GodotSpace2D *space = space_owner.get_or_null(p_area);
459
p_area = space->get_default_area()->get_self();
460
}
461
GodotArea2D *area = area_owner.get_or_null(p_area);
462
ERR_FAIL_NULL_V(area, Variant());
463
464
return area->get_param(p_param);
465
}
466
467
Transform2D GodotPhysicsServer2D::area_get_transform(RID p_area) const {
468
GodotArea2D *area = area_owner.get_or_null(p_area);
469
ERR_FAIL_NULL_V(area, Transform2D());
470
471
return area->get_transform();
472
}
473
474
void GodotPhysicsServer2D::area_set_pickable(RID p_area, bool p_pickable) {
475
GodotArea2D *area = area_owner.get_or_null(p_area);
476
ERR_FAIL_NULL(area);
477
area->set_pickable(p_pickable);
478
}
479
480
void GodotPhysicsServer2D::area_set_monitorable(RID p_area, bool p_monitorable) {
481
GodotArea2D *area = area_owner.get_or_null(p_area);
482
ERR_FAIL_NULL(area);
483
FLUSH_QUERY_CHECK(area);
484
485
area->set_monitorable(p_monitorable);
486
}
487
488
void GodotPhysicsServer2D::area_set_collision_layer(RID p_area, uint32_t p_layer) {
489
GodotArea2D *area = area_owner.get_or_null(p_area);
490
ERR_FAIL_NULL(area);
491
492
area->set_collision_layer(p_layer);
493
}
494
495
uint32_t GodotPhysicsServer2D::area_get_collision_layer(RID p_area) const {
496
GodotArea2D *area = area_owner.get_or_null(p_area);
497
ERR_FAIL_NULL_V(area, 0);
498
499
return area->get_collision_layer();
500
}
501
502
void GodotPhysicsServer2D::area_set_collision_mask(RID p_area, uint32_t p_mask) {
503
GodotArea2D *area = area_owner.get_or_null(p_area);
504
ERR_FAIL_NULL(area);
505
506
area->set_collision_mask(p_mask);
507
}
508
509
uint32_t GodotPhysicsServer2D::area_get_collision_mask(RID p_area) const {
510
GodotArea2D *area = area_owner.get_or_null(p_area);
511
ERR_FAIL_NULL_V(area, 0);
512
513
return area->get_collision_mask();
514
}
515
516
void GodotPhysicsServer2D::area_set_monitor_callback(RID p_area, const Callable &p_callback) {
517
GodotArea2D *area = area_owner.get_or_null(p_area);
518
ERR_FAIL_NULL(area);
519
520
area->set_monitor_callback(p_callback.is_valid() ? p_callback : Callable());
521
}
522
523
void GodotPhysicsServer2D::area_set_area_monitor_callback(RID p_area, const Callable &p_callback) {
524
GodotArea2D *area = area_owner.get_or_null(p_area);
525
ERR_FAIL_NULL(area);
526
527
area->set_area_monitor_callback(p_callback.is_valid() ? p_callback : Callable());
528
}
529
530
/* BODY API */
531
532
RID GodotPhysicsServer2D::body_create() {
533
GodotBody2D *body = memnew(GodotBody2D);
534
RID rid = body_owner.make_rid(body);
535
body->set_self(rid);
536
return rid;
537
}
538
539
void GodotPhysicsServer2D::body_set_space(RID p_body, RID p_space) {
540
GodotBody2D *body = body_owner.get_or_null(p_body);
541
ERR_FAIL_NULL(body);
542
GodotSpace2D *space = nullptr;
543
if (p_space.is_valid()) {
544
space = space_owner.get_or_null(p_space);
545
ERR_FAIL_NULL(space);
546
}
547
548
if (body->get_space() == space) {
549
return; //pointless
550
}
551
552
body->clear_constraint_list();
553
body->set_space(space);
554
}
555
556
RID GodotPhysicsServer2D::body_get_space(RID p_body) const {
557
GodotBody2D *body = body_owner.get_or_null(p_body);
558
ERR_FAIL_NULL_V(body, RID());
559
560
GodotSpace2D *space = body->get_space();
561
if (!space) {
562
return RID();
563
}
564
return space->get_self();
565
}
566
567
void GodotPhysicsServer2D::body_set_mode(RID p_body, BodyMode p_mode) {
568
GodotBody2D *body = body_owner.get_or_null(p_body);
569
ERR_FAIL_NULL(body);
570
FLUSH_QUERY_CHECK(body);
571
572
body->set_mode(p_mode);
573
}
574
575
PhysicsServer2D::BodyMode GodotPhysicsServer2D::body_get_mode(RID p_body) const {
576
GodotBody2D *body = body_owner.get_or_null(p_body);
577
ERR_FAIL_NULL_V(body, BODY_MODE_STATIC);
578
579
return body->get_mode();
580
}
581
582
void GodotPhysicsServer2D::body_add_shape(RID p_body, RID p_shape, const Transform2D &p_transform, bool p_disabled) {
583
GodotBody2D *body = body_owner.get_or_null(p_body);
584
ERR_FAIL_NULL(body);
585
586
GodotShape2D *shape = shape_owner.get_or_null(p_shape);
587
ERR_FAIL_NULL(shape);
588
589
body->add_shape(shape, p_transform, p_disabled);
590
}
591
592
void GodotPhysicsServer2D::body_set_shape(RID p_body, int p_shape_idx, RID p_shape) {
593
GodotBody2D *body = body_owner.get_or_null(p_body);
594
ERR_FAIL_NULL(body);
595
596
GodotShape2D *shape = shape_owner.get_or_null(p_shape);
597
ERR_FAIL_NULL(shape);
598
ERR_FAIL_COND(!shape->is_configured());
599
600
body->set_shape(p_shape_idx, shape);
601
}
602
603
void GodotPhysicsServer2D::body_set_shape_transform(RID p_body, int p_shape_idx, const Transform2D &p_transform) {
604
GodotBody2D *body = body_owner.get_or_null(p_body);
605
ERR_FAIL_NULL(body);
606
607
body->set_shape_transform(p_shape_idx, p_transform);
608
}
609
610
int GodotPhysicsServer2D::body_get_shape_count(RID p_body) const {
611
GodotBody2D *body = body_owner.get_or_null(p_body);
612
ERR_FAIL_NULL_V(body, -1);
613
614
return body->get_shape_count();
615
}
616
617
RID GodotPhysicsServer2D::body_get_shape(RID p_body, int p_shape_idx) const {
618
GodotBody2D *body = body_owner.get_or_null(p_body);
619
ERR_FAIL_NULL_V(body, RID());
620
621
GodotShape2D *shape = body->get_shape(p_shape_idx);
622
ERR_FAIL_NULL_V(shape, RID());
623
624
return shape->get_self();
625
}
626
627
Transform2D GodotPhysicsServer2D::body_get_shape_transform(RID p_body, int p_shape_idx) const {
628
GodotBody2D *body = body_owner.get_or_null(p_body);
629
ERR_FAIL_NULL_V(body, Transform2D());
630
631
return body->get_shape_transform(p_shape_idx);
632
}
633
634
void GodotPhysicsServer2D::body_remove_shape(RID p_body, int p_shape_idx) {
635
GodotBody2D *body = body_owner.get_or_null(p_body);
636
ERR_FAIL_NULL(body);
637
638
body->remove_shape(p_shape_idx);
639
}
640
641
void GodotPhysicsServer2D::body_clear_shapes(RID p_body) {
642
GodotBody2D *body = body_owner.get_or_null(p_body);
643
ERR_FAIL_NULL(body);
644
645
while (body->get_shape_count()) {
646
body->remove_shape(0);
647
}
648
}
649
650
void GodotPhysicsServer2D::body_set_shape_disabled(RID p_body, int p_shape_idx, bool p_disabled) {
651
GodotBody2D *body = body_owner.get_or_null(p_body);
652
ERR_FAIL_NULL(body);
653
ERR_FAIL_INDEX(p_shape_idx, body->get_shape_count());
654
FLUSH_QUERY_CHECK(body);
655
656
body->set_shape_disabled(p_shape_idx, p_disabled);
657
}
658
659
void GodotPhysicsServer2D::body_set_shape_as_one_way_collision(RID p_body, int p_shape_idx, bool p_enable, real_t p_margin) {
660
GodotBody2D *body = body_owner.get_or_null(p_body);
661
ERR_FAIL_NULL(body);
662
ERR_FAIL_INDEX(p_shape_idx, body->get_shape_count());
663
FLUSH_QUERY_CHECK(body);
664
665
body->set_shape_as_one_way_collision(p_shape_idx, p_enable, p_margin);
666
}
667
668
void GodotPhysicsServer2D::body_set_continuous_collision_detection_mode(RID p_body, CCDMode p_mode) {
669
GodotBody2D *body = body_owner.get_or_null(p_body);
670
ERR_FAIL_NULL(body);
671
body->set_continuous_collision_detection_mode(p_mode);
672
}
673
674
GodotPhysicsServer2D::CCDMode GodotPhysicsServer2D::body_get_continuous_collision_detection_mode(RID p_body) const {
675
const GodotBody2D *body = body_owner.get_or_null(p_body);
676
ERR_FAIL_NULL_V(body, CCD_MODE_DISABLED);
677
678
return body->get_continuous_collision_detection_mode();
679
}
680
681
void GodotPhysicsServer2D::body_attach_object_instance_id(RID p_body, ObjectID p_id) {
682
GodotBody2D *body = body_owner.get_or_null(p_body);
683
ERR_FAIL_NULL(body);
684
685
body->set_instance_id(p_id);
686
}
687
688
ObjectID GodotPhysicsServer2D::body_get_object_instance_id(RID p_body) const {
689
GodotBody2D *body = body_owner.get_or_null(p_body);
690
ERR_FAIL_NULL_V(body, ObjectID());
691
692
return body->get_instance_id();
693
}
694
695
void GodotPhysicsServer2D::body_attach_canvas_instance_id(RID p_body, ObjectID p_id) {
696
GodotBody2D *body = body_owner.get_or_null(p_body);
697
ERR_FAIL_NULL(body);
698
699
body->set_canvas_instance_id(p_id);
700
}
701
702
ObjectID GodotPhysicsServer2D::body_get_canvas_instance_id(RID p_body) const {
703
GodotBody2D *body = body_owner.get_or_null(p_body);
704
ERR_FAIL_NULL_V(body, ObjectID());
705
706
return body->get_canvas_instance_id();
707
}
708
709
void GodotPhysicsServer2D::body_set_collision_layer(RID p_body, uint32_t p_layer) {
710
GodotBody2D *body = body_owner.get_or_null(p_body);
711
ERR_FAIL_NULL(body);
712
body->set_collision_layer(p_layer);
713
}
714
715
uint32_t GodotPhysicsServer2D::body_get_collision_layer(RID p_body) const {
716
GodotBody2D *body = body_owner.get_or_null(p_body);
717
ERR_FAIL_NULL_V(body, 0);
718
719
return body->get_collision_layer();
720
}
721
722
void GodotPhysicsServer2D::body_set_collision_mask(RID p_body, uint32_t p_mask) {
723
GodotBody2D *body = body_owner.get_or_null(p_body);
724
ERR_FAIL_NULL(body);
725
body->set_collision_mask(p_mask);
726
}
727
728
uint32_t GodotPhysicsServer2D::body_get_collision_mask(RID p_body) const {
729
GodotBody2D *body = body_owner.get_or_null(p_body);
730
ERR_FAIL_NULL_V(body, 0);
731
732
return body->get_collision_mask();
733
}
734
735
void GodotPhysicsServer2D::body_set_collision_priority(RID p_body, real_t p_priority) {
736
GodotBody2D *body = body_owner.get_or_null(p_body);
737
ERR_FAIL_NULL(body);
738
739
body->set_collision_priority(p_priority);
740
}
741
742
real_t GodotPhysicsServer2D::body_get_collision_priority(RID p_body) const {
743
const GodotBody2D *body = body_owner.get_or_null(p_body);
744
ERR_FAIL_NULL_V(body, 0);
745
746
return body->get_collision_priority();
747
}
748
749
void GodotPhysicsServer2D::body_set_param(RID p_body, BodyParameter p_param, const Variant &p_value) {
750
GodotBody2D *body = body_owner.get_or_null(p_body);
751
ERR_FAIL_NULL(body);
752
753
body->set_param(p_param, p_value);
754
}
755
756
Variant GodotPhysicsServer2D::body_get_param(RID p_body, BodyParameter p_param) const {
757
GodotBody2D *body = body_owner.get_or_null(p_body);
758
ERR_FAIL_NULL_V(body, 0);
759
760
return body->get_param(p_param);
761
}
762
763
void GodotPhysicsServer2D::body_reset_mass_properties(RID p_body) {
764
GodotBody2D *body = body_owner.get_or_null(p_body);
765
ERR_FAIL_NULL(body);
766
767
return body->reset_mass_properties();
768
}
769
770
void GodotPhysicsServer2D::body_set_state(RID p_body, BodyState p_state, const Variant &p_variant) {
771
GodotBody2D *body = body_owner.get_or_null(p_body);
772
ERR_FAIL_NULL(body);
773
774
body->set_state(p_state, p_variant);
775
}
776
777
Variant GodotPhysicsServer2D::body_get_state(RID p_body, BodyState p_state) const {
778
GodotBody2D *body = body_owner.get_or_null(p_body);
779
ERR_FAIL_NULL_V(body, Variant());
780
781
return body->get_state(p_state);
782
}
783
784
void GodotPhysicsServer2D::body_apply_central_impulse(RID p_body, const Vector2 &p_impulse) {
785
GodotBody2D *body = body_owner.get_or_null(p_body);
786
ERR_FAIL_NULL(body);
787
788
body->apply_central_impulse(p_impulse);
789
body->wakeup();
790
}
791
792
void GodotPhysicsServer2D::body_apply_torque_impulse(RID p_body, real_t p_torque) {
793
GodotBody2D *body = body_owner.get_or_null(p_body);
794
ERR_FAIL_NULL(body);
795
796
_update_shapes();
797
798
body->apply_torque_impulse(p_torque);
799
body->wakeup();
800
}
801
802
void GodotPhysicsServer2D::body_apply_impulse(RID p_body, const Vector2 &p_impulse, const Vector2 &p_position) {
803
GodotBody2D *body = body_owner.get_or_null(p_body);
804
ERR_FAIL_NULL(body);
805
806
_update_shapes();
807
808
body->apply_impulse(p_impulse, p_position);
809
body->wakeup();
810
}
811
812
void GodotPhysicsServer2D::body_apply_central_force(RID p_body, const Vector2 &p_force) {
813
GodotBody2D *body = body_owner.get_or_null(p_body);
814
ERR_FAIL_NULL(body);
815
816
body->apply_central_force(p_force);
817
body->wakeup();
818
}
819
820
void GodotPhysicsServer2D::body_apply_force(RID p_body, const Vector2 &p_force, const Vector2 &p_position) {
821
GodotBody2D *body = body_owner.get_or_null(p_body);
822
ERR_FAIL_NULL(body);
823
824
body->apply_force(p_force, p_position);
825
body->wakeup();
826
}
827
828
void GodotPhysicsServer2D::body_apply_torque(RID p_body, real_t p_torque) {
829
GodotBody2D *body = body_owner.get_or_null(p_body);
830
ERR_FAIL_NULL(body);
831
832
body->apply_torque(p_torque);
833
body->wakeup();
834
}
835
836
void GodotPhysicsServer2D::body_add_constant_central_force(RID p_body, const Vector2 &p_force) {
837
GodotBody2D *body = body_owner.get_or_null(p_body);
838
ERR_FAIL_NULL(body);
839
840
body->add_constant_central_force(p_force);
841
body->wakeup();
842
}
843
844
void GodotPhysicsServer2D::body_add_constant_force(RID p_body, const Vector2 &p_force, const Vector2 &p_position) {
845
GodotBody2D *body = body_owner.get_or_null(p_body);
846
ERR_FAIL_NULL(body);
847
848
body->add_constant_force(p_force, p_position);
849
body->wakeup();
850
}
851
852
void GodotPhysicsServer2D::body_add_constant_torque(RID p_body, real_t p_torque) {
853
GodotBody2D *body = body_owner.get_or_null(p_body);
854
ERR_FAIL_NULL(body);
855
856
body->add_constant_torque(p_torque);
857
body->wakeup();
858
}
859
860
void GodotPhysicsServer2D::body_set_constant_force(RID p_body, const Vector2 &p_force) {
861
GodotBody2D *body = body_owner.get_or_null(p_body);
862
ERR_FAIL_NULL(body);
863
864
body->set_constant_force(p_force);
865
if (!p_force.is_zero_approx()) {
866
body->wakeup();
867
}
868
}
869
870
Vector2 GodotPhysicsServer2D::body_get_constant_force(RID p_body) const {
871
GodotBody2D *body = body_owner.get_or_null(p_body);
872
ERR_FAIL_NULL_V(body, Vector2());
873
return body->get_constant_force();
874
}
875
876
void GodotPhysicsServer2D::body_set_constant_torque(RID p_body, real_t p_torque) {
877
GodotBody2D *body = body_owner.get_or_null(p_body);
878
ERR_FAIL_NULL(body);
879
880
body->set_constant_torque(p_torque);
881
if (!Math::is_zero_approx(p_torque)) {
882
body->wakeup();
883
}
884
}
885
886
real_t GodotPhysicsServer2D::body_get_constant_torque(RID p_body) const {
887
GodotBody2D *body = body_owner.get_or_null(p_body);
888
ERR_FAIL_NULL_V(body, 0);
889
890
return body->get_constant_torque();
891
}
892
893
void GodotPhysicsServer2D::body_set_axis_velocity(RID p_body, const Vector2 &p_axis_velocity) {
894
GodotBody2D *body = body_owner.get_or_null(p_body);
895
ERR_FAIL_NULL(body);
896
897
_update_shapes();
898
899
Vector2 v = body->get_linear_velocity();
900
Vector2 axis = p_axis_velocity.normalized();
901
v -= axis * axis.dot(v);
902
v += p_axis_velocity;
903
body->set_linear_velocity(v);
904
body->wakeup();
905
}
906
907
void GodotPhysicsServer2D::body_add_collision_exception(RID p_body, RID p_body_b) {
908
GodotBody2D *body = body_owner.get_or_null(p_body);
909
ERR_FAIL_NULL(body);
910
911
body->add_exception(p_body_b);
912
body->wakeup();
913
}
914
915
void GodotPhysicsServer2D::body_remove_collision_exception(RID p_body, RID p_body_b) {
916
GodotBody2D *body = body_owner.get_or_null(p_body);
917
ERR_FAIL_NULL(body);
918
919
body->remove_exception(p_body_b);
920
body->wakeup();
921
}
922
923
void GodotPhysicsServer2D::body_get_collision_exceptions(RID p_body, List<RID> *p_exceptions) {
924
GodotBody2D *body = body_owner.get_or_null(p_body);
925
ERR_FAIL_NULL(body);
926
927
for (int i = 0; i < body->get_exceptions().size(); i++) {
928
p_exceptions->push_back(body->get_exceptions()[i]);
929
}
930
}
931
932
void GodotPhysicsServer2D::body_set_contacts_reported_depth_threshold(RID p_body, real_t p_threshold) {
933
GodotBody2D *body = body_owner.get_or_null(p_body);
934
ERR_FAIL_NULL(body);
935
}
936
937
real_t GodotPhysicsServer2D::body_get_contacts_reported_depth_threshold(RID p_body) const {
938
GodotBody2D *body = body_owner.get_or_null(p_body);
939
ERR_FAIL_NULL_V(body, 0);
940
return 0;
941
}
942
943
void GodotPhysicsServer2D::body_set_omit_force_integration(RID p_body, bool p_omit) {
944
GodotBody2D *body = body_owner.get_or_null(p_body);
945
ERR_FAIL_NULL(body);
946
947
body->set_omit_force_integration(p_omit);
948
}
949
950
bool GodotPhysicsServer2D::body_is_omitting_force_integration(RID p_body) const {
951
GodotBody2D *body = body_owner.get_or_null(p_body);
952
ERR_FAIL_NULL_V(body, false);
953
return body->get_omit_force_integration();
954
}
955
956
void GodotPhysicsServer2D::body_set_max_contacts_reported(RID p_body, int p_contacts) {
957
GodotBody2D *body = body_owner.get_or_null(p_body);
958
ERR_FAIL_NULL(body);
959
body->set_max_contacts_reported(p_contacts);
960
}
961
962
int GodotPhysicsServer2D::body_get_max_contacts_reported(RID p_body) const {
963
GodotBody2D *body = body_owner.get_or_null(p_body);
964
ERR_FAIL_NULL_V(body, -1);
965
return body->get_max_contacts_reported();
966
}
967
968
void GodotPhysicsServer2D::body_set_state_sync_callback(RID p_body, const Callable &p_callable) {
969
GodotBody2D *body = body_owner.get_or_null(p_body);
970
ERR_FAIL_NULL(body);
971
body->set_state_sync_callback(p_callable);
972
}
973
974
void GodotPhysicsServer2D::body_set_force_integration_callback(RID p_body, const Callable &p_callable, const Variant &p_udata) {
975
GodotBody2D *body = body_owner.get_or_null(p_body);
976
ERR_FAIL_NULL(body);
977
body->set_force_integration_callback(p_callable, p_udata);
978
}
979
980
bool GodotPhysicsServer2D::body_collide_shape(RID p_body, int p_body_shape, RID p_shape, const Transform2D &p_shape_xform, const Vector2 &p_motion, Vector2 *r_results, int p_result_max, int &r_result_count) {
981
GodotBody2D *body = body_owner.get_or_null(p_body);
982
ERR_FAIL_NULL_V(body, false);
983
ERR_FAIL_INDEX_V(p_body_shape, body->get_shape_count(), false);
984
985
return shape_collide(body->get_shape(p_body_shape)->get_self(), body->get_transform() * body->get_shape_transform(p_body_shape), Vector2(), p_shape, p_shape_xform, p_motion, r_results, p_result_max, r_result_count);
986
}
987
988
void GodotPhysicsServer2D::body_set_pickable(RID p_body, bool p_pickable) {
989
GodotBody2D *body = body_owner.get_or_null(p_body);
990
ERR_FAIL_NULL(body);
991
body->set_pickable(p_pickable);
992
}
993
994
bool GodotPhysicsServer2D::body_test_motion(RID p_body, const MotionParameters &p_parameters, MotionResult *r_result) {
995
GodotBody2D *body = body_owner.get_or_null(p_body);
996
ERR_FAIL_NULL_V(body, false);
997
ERR_FAIL_NULL_V(body->get_space(), false);
998
ERR_FAIL_COND_V(body->get_space()->is_locked(), false);
999
1000
_update_shapes();
1001
1002
return body->get_space()->test_body_motion(body, p_parameters, r_result);
1003
}
1004
1005
PhysicsDirectBodyState2D *GodotPhysicsServer2D::body_get_direct_state(RID p_body) {
1006
ERR_FAIL_COND_V_MSG((using_threads && !doing_sync), nullptr, "Body state is inaccessible right now, wait for iteration or physics process notification.");
1007
1008
if (!body_owner.owns(p_body)) {
1009
return nullptr;
1010
}
1011
1012
GodotBody2D *body = body_owner.get_or_null(p_body);
1013
ERR_FAIL_NULL_V(body, nullptr);
1014
1015
if (!body->get_space()) {
1016
return nullptr;
1017
}
1018
1019
ERR_FAIL_COND_V_MSG(body->get_space()->is_locked(), nullptr, "Body state is inaccessible right now, wait for iteration or physics process notification.");
1020
1021
return body->get_direct_state();
1022
}
1023
1024
/* JOINT API */
1025
1026
RID GodotPhysicsServer2D::joint_create() {
1027
GodotJoint2D *joint = memnew(GodotJoint2D);
1028
RID joint_rid = joint_owner.make_rid(joint);
1029
joint->set_self(joint_rid);
1030
return joint_rid;
1031
}
1032
1033
void GodotPhysicsServer2D::joint_clear(RID p_joint) {
1034
GodotJoint2D *joint = joint_owner.get_or_null(p_joint);
1035
ERR_FAIL_NULL(joint);
1036
if (joint->get_type() != JOINT_TYPE_MAX) {
1037
GodotJoint2D *empty_joint = memnew(GodotJoint2D);
1038
empty_joint->copy_settings_from(joint);
1039
1040
joint_owner.replace(p_joint, empty_joint);
1041
memdelete(joint);
1042
}
1043
}
1044
1045
void GodotPhysicsServer2D::joint_set_param(RID p_joint, JointParam p_param, real_t p_value) {
1046
GodotJoint2D *joint = joint_owner.get_or_null(p_joint);
1047
ERR_FAIL_NULL(joint);
1048
1049
switch (p_param) {
1050
case JOINT_PARAM_BIAS:
1051
joint->set_bias(p_value);
1052
break;
1053
case JOINT_PARAM_MAX_BIAS:
1054
joint->set_max_bias(p_value);
1055
break;
1056
case JOINT_PARAM_MAX_FORCE:
1057
joint->set_max_force(p_value);
1058
break;
1059
}
1060
}
1061
1062
real_t GodotPhysicsServer2D::joint_get_param(RID p_joint, JointParam p_param) const {
1063
const GodotJoint2D *joint = joint_owner.get_or_null(p_joint);
1064
ERR_FAIL_NULL_V(joint, -1);
1065
1066
switch (p_param) {
1067
case JOINT_PARAM_BIAS:
1068
return joint->get_bias();
1069
break;
1070
case JOINT_PARAM_MAX_BIAS:
1071
return joint->get_max_bias();
1072
break;
1073
case JOINT_PARAM_MAX_FORCE:
1074
return joint->get_max_force();
1075
break;
1076
}
1077
1078
return 0;
1079
}
1080
1081
void GodotPhysicsServer2D::joint_disable_collisions_between_bodies(RID p_joint, const bool p_disable) {
1082
GodotJoint2D *joint = joint_owner.get_or_null(p_joint);
1083
ERR_FAIL_NULL(joint);
1084
1085
joint->disable_collisions_between_bodies(p_disable);
1086
1087
if (2 == joint->get_body_count()) {
1088
GodotBody2D *body_a = *joint->get_body_ptr();
1089
GodotBody2D *body_b = *(joint->get_body_ptr() + 1);
1090
1091
if (p_disable) {
1092
body_add_collision_exception(body_a->get_self(), body_b->get_self());
1093
body_add_collision_exception(body_b->get_self(), body_a->get_self());
1094
} else {
1095
body_remove_collision_exception(body_a->get_self(), body_b->get_self());
1096
body_remove_collision_exception(body_b->get_self(), body_a->get_self());
1097
}
1098
}
1099
}
1100
1101
bool GodotPhysicsServer2D::joint_is_disabled_collisions_between_bodies(RID p_joint) const {
1102
const GodotJoint2D *joint = joint_owner.get_or_null(p_joint);
1103
ERR_FAIL_NULL_V(joint, true);
1104
1105
return joint->is_disabled_collisions_between_bodies();
1106
}
1107
1108
void GodotPhysicsServer2D::joint_make_pin(RID p_joint, const Vector2 &p_pos, RID p_body_a, RID p_body_b) {
1109
GodotBody2D *A = body_owner.get_or_null(p_body_a);
1110
ERR_FAIL_NULL(A);
1111
GodotBody2D *B = nullptr;
1112
if (body_owner.owns(p_body_b)) {
1113
B = body_owner.get_or_null(p_body_b);
1114
ERR_FAIL_NULL(B);
1115
}
1116
1117
GodotJoint2D *prev_joint = joint_owner.get_or_null(p_joint);
1118
ERR_FAIL_NULL(prev_joint);
1119
1120
GodotJoint2D *joint = memnew(GodotPinJoint2D(p_pos, A, B));
1121
1122
joint_owner.replace(p_joint, joint);
1123
joint->copy_settings_from(prev_joint);
1124
memdelete(prev_joint);
1125
}
1126
1127
void GodotPhysicsServer2D::joint_make_groove(RID p_joint, const Vector2 &p_a_groove1, const Vector2 &p_a_groove2, const Vector2 &p_b_anchor, RID p_body_a, RID p_body_b) {
1128
GodotBody2D *A = body_owner.get_or_null(p_body_a);
1129
ERR_FAIL_NULL(A);
1130
1131
GodotBody2D *B = body_owner.get_or_null(p_body_b);
1132
ERR_FAIL_NULL(B);
1133
1134
GodotJoint2D *prev_joint = joint_owner.get_or_null(p_joint);
1135
ERR_FAIL_NULL(prev_joint);
1136
1137
GodotJoint2D *joint = memnew(GodotGrooveJoint2D(p_a_groove1, p_a_groove2, p_b_anchor, A, B));
1138
1139
joint_owner.replace(p_joint, joint);
1140
joint->copy_settings_from(prev_joint);
1141
memdelete(prev_joint);
1142
}
1143
1144
void GodotPhysicsServer2D::joint_make_damped_spring(RID p_joint, const Vector2 &p_anchor_a, const Vector2 &p_anchor_b, RID p_body_a, RID p_body_b) {
1145
GodotBody2D *A = body_owner.get_or_null(p_body_a);
1146
ERR_FAIL_NULL(A);
1147
1148
GodotBody2D *B = body_owner.get_or_null(p_body_b);
1149
ERR_FAIL_NULL(B);
1150
1151
GodotJoint2D *prev_joint = joint_owner.get_or_null(p_joint);
1152
ERR_FAIL_NULL(prev_joint);
1153
1154
GodotJoint2D *joint = memnew(GodotDampedSpringJoint2D(p_anchor_a, p_anchor_b, A, B));
1155
1156
joint_owner.replace(p_joint, joint);
1157
joint->copy_settings_from(prev_joint);
1158
memdelete(prev_joint);
1159
}
1160
1161
void GodotPhysicsServer2D::pin_joint_set_flag(RID p_joint, PinJointFlag p_flag, bool p_enabled) {
1162
GodotJoint2D *joint = joint_owner.get_or_null(p_joint);
1163
ERR_FAIL_NULL(joint);
1164
ERR_FAIL_COND(joint->get_type() != JOINT_TYPE_PIN);
1165
1166
GodotPinJoint2D *pin_joint = static_cast<GodotPinJoint2D *>(joint);
1167
pin_joint->set_flag(p_flag, p_enabled);
1168
}
1169
1170
bool GodotPhysicsServer2D::pin_joint_get_flag(RID p_joint, PinJointFlag p_flag) const {
1171
GodotJoint2D *joint = joint_owner.get_or_null(p_joint);
1172
ERR_FAIL_NULL_V(joint, false);
1173
ERR_FAIL_COND_V(joint->get_type() != JOINT_TYPE_PIN, false);
1174
1175
GodotPinJoint2D *pin_joint = static_cast<GodotPinJoint2D *>(joint);
1176
return pin_joint->get_flag(p_flag);
1177
}
1178
1179
void GodotPhysicsServer2D::pin_joint_set_param(RID p_joint, PinJointParam p_param, real_t p_value) {
1180
GodotJoint2D *joint = joint_owner.get_or_null(p_joint);
1181
ERR_FAIL_NULL(joint);
1182
ERR_FAIL_COND(joint->get_type() != JOINT_TYPE_PIN);
1183
1184
GodotPinJoint2D *pin_joint = static_cast<GodotPinJoint2D *>(joint);
1185
pin_joint->set_param(p_param, p_value);
1186
}
1187
1188
real_t GodotPhysicsServer2D::pin_joint_get_param(RID p_joint, PinJointParam p_param) const {
1189
GodotJoint2D *joint = joint_owner.get_or_null(p_joint);
1190
ERR_FAIL_NULL_V(joint, 0);
1191
ERR_FAIL_COND_V(joint->get_type() != JOINT_TYPE_PIN, 0);
1192
1193
GodotPinJoint2D *pin_joint = static_cast<GodotPinJoint2D *>(joint);
1194
return pin_joint->get_param(p_param);
1195
}
1196
1197
void GodotPhysicsServer2D::damped_spring_joint_set_param(RID p_joint, DampedSpringParam p_param, real_t p_value) {
1198
GodotJoint2D *joint = joint_owner.get_or_null(p_joint);
1199
ERR_FAIL_NULL(joint);
1200
ERR_FAIL_COND(joint->get_type() != JOINT_TYPE_DAMPED_SPRING);
1201
1202
GodotDampedSpringJoint2D *dsj = static_cast<GodotDampedSpringJoint2D *>(joint);
1203
dsj->set_param(p_param, p_value);
1204
}
1205
1206
real_t GodotPhysicsServer2D::damped_spring_joint_get_param(RID p_joint, DampedSpringParam p_param) const {
1207
GodotJoint2D *joint = joint_owner.get_or_null(p_joint);
1208
ERR_FAIL_NULL_V(joint, 0);
1209
ERR_FAIL_COND_V(joint->get_type() != JOINT_TYPE_DAMPED_SPRING, 0);
1210
1211
GodotDampedSpringJoint2D *dsj = static_cast<GodotDampedSpringJoint2D *>(joint);
1212
return dsj->get_param(p_param);
1213
}
1214
1215
PhysicsServer2D::JointType GodotPhysicsServer2D::joint_get_type(RID p_joint) const {
1216
GodotJoint2D *joint = joint_owner.get_or_null(p_joint);
1217
ERR_FAIL_NULL_V(joint, JOINT_TYPE_PIN);
1218
1219
return joint->get_type();
1220
}
1221
1222
void GodotPhysicsServer2D::free(RID p_rid) {
1223
_update_shapes(); // just in case
1224
1225
if (shape_owner.owns(p_rid)) {
1226
GodotShape2D *shape = shape_owner.get_or_null(p_rid);
1227
1228
while (shape->get_owners().size()) {
1229
GodotShapeOwner2D *so = shape->get_owners().begin()->key;
1230
so->remove_shape(shape);
1231
}
1232
1233
shape_owner.free(p_rid);
1234
memdelete(shape);
1235
} else if (body_owner.owns(p_rid)) {
1236
GodotBody2D *body = body_owner.get_or_null(p_rid);
1237
1238
body_set_space(p_rid, RID());
1239
1240
while (body->get_shape_count()) {
1241
body->remove_shape(0);
1242
}
1243
1244
body_owner.free(p_rid);
1245
memdelete(body);
1246
1247
} else if (area_owner.owns(p_rid)) {
1248
GodotArea2D *area = area_owner.get_or_null(p_rid);
1249
1250
area->set_space(nullptr);
1251
1252
while (area->get_shape_count()) {
1253
area->remove_shape(0);
1254
}
1255
1256
area_owner.free(p_rid);
1257
memdelete(area);
1258
} else if (space_owner.owns(p_rid)) {
1259
GodotSpace2D *space = space_owner.get_or_null(p_rid);
1260
1261
while (space->get_objects().size()) {
1262
GodotCollisionObject2D *co = static_cast<GodotCollisionObject2D *>(*space->get_objects().begin());
1263
co->set_space(nullptr);
1264
}
1265
1266
active_spaces.erase(space);
1267
free(space->get_default_area()->get_self());
1268
space_owner.free(p_rid);
1269
memdelete(space);
1270
} else if (joint_owner.owns(p_rid)) {
1271
GodotJoint2D *joint = joint_owner.get_or_null(p_rid);
1272
1273
joint_owner.free(p_rid);
1274
memdelete(joint);
1275
1276
} else {
1277
ERR_FAIL_MSG("Invalid ID.");
1278
}
1279
}
1280
1281
void GodotPhysicsServer2D::set_active(bool p_active) {
1282
active = p_active;
1283
}
1284
1285
void GodotPhysicsServer2D::init() {
1286
doing_sync = false;
1287
stepper = memnew(GodotStep2D);
1288
}
1289
1290
void GodotPhysicsServer2D::step(real_t p_step) {
1291
if (!active) {
1292
return;
1293
}
1294
1295
_update_shapes();
1296
1297
island_count = 0;
1298
active_objects = 0;
1299
collision_pairs = 0;
1300
for (GodotSpace2D *E : active_spaces) {
1301
stepper->step(E, p_step);
1302
island_count += E->get_island_count();
1303
active_objects += E->get_active_objects();
1304
collision_pairs += E->get_collision_pairs();
1305
}
1306
}
1307
1308
void GodotPhysicsServer2D::sync() {
1309
doing_sync = true;
1310
}
1311
1312
void GodotPhysicsServer2D::flush_queries() {
1313
if (!active) {
1314
return;
1315
}
1316
1317
flushing_queries = true;
1318
1319
uint64_t time_beg = OS::get_singleton()->get_ticks_usec();
1320
1321
for (GodotSpace2D *E : active_spaces) {
1322
E->call_queries();
1323
}
1324
1325
flushing_queries = false;
1326
1327
if (EngineDebugger::is_profiling("servers")) {
1328
uint64_t total_time[GodotSpace2D::ELAPSED_TIME_MAX];
1329
static const char *time_name[GodotSpace2D::ELAPSED_TIME_MAX] = {
1330
"integrate_forces",
1331
"generate_islands",
1332
"setup_constraints",
1333
"solve_constraints",
1334
"integrate_velocities"
1335
};
1336
1337
for (int i = 0; i < GodotSpace2D::ELAPSED_TIME_MAX; i++) {
1338
total_time[i] = 0;
1339
}
1340
1341
for (const GodotSpace2D *E : active_spaces) {
1342
for (int i = 0; i < GodotSpace2D::ELAPSED_TIME_MAX; i++) {
1343
total_time[i] += E->get_elapsed_time(GodotSpace2D::ElapsedTime(i));
1344
}
1345
}
1346
1347
Array values;
1348
values.resize(GodotSpace2D::ELAPSED_TIME_MAX * 2);
1349
for (int i = 0; i < GodotSpace2D::ELAPSED_TIME_MAX; i++) {
1350
values[i * 2 + 0] = time_name[i];
1351
values[i * 2 + 1] = USEC_TO_SEC(total_time[i]);
1352
}
1353
values.push_back("flush_queries");
1354
values.push_back(USEC_TO_SEC(OS::get_singleton()->get_ticks_usec() - time_beg));
1355
1356
values.push_front("physics_2d");
1357
EngineDebugger::profiler_add_frame_data("servers", values);
1358
}
1359
}
1360
1361
void GodotPhysicsServer2D::end_sync() {
1362
doing_sync = false;
1363
}
1364
1365
void GodotPhysicsServer2D::finish() {
1366
memdelete(stepper);
1367
}
1368
1369
void GodotPhysicsServer2D::_update_shapes() {
1370
while (pending_shape_update_list.first()) {
1371
pending_shape_update_list.first()->self()->_shape_changed();
1372
pending_shape_update_list.remove(pending_shape_update_list.first());
1373
}
1374
}
1375
1376
int GodotPhysicsServer2D::get_process_info(ProcessInfo p_info) {
1377
switch (p_info) {
1378
case INFO_ACTIVE_OBJECTS: {
1379
return active_objects;
1380
} break;
1381
case INFO_COLLISION_PAIRS: {
1382
return collision_pairs;
1383
} break;
1384
case INFO_ISLAND_COUNT: {
1385
return island_count;
1386
} break;
1387
}
1388
1389
return 0;
1390
}
1391
1392
GodotPhysicsServer2D *GodotPhysicsServer2D::godot_singleton = nullptr;
1393
1394
GodotPhysicsServer2D::GodotPhysicsServer2D(bool p_using_threads) {
1395
godot_singleton = this;
1396
GodotBroadPhase2D::create_func = GodotBroadPhase2DBVH::_create;
1397
1398
using_threads = p_using_threads;
1399
}
1400
1401