Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
godotengine
GitHub Repository: godotengine/godot
Path: blob/master/scene/2d/physics/rigid_body_2d.cpp
9906 views
1
/**************************************************************************/
2
/* rigid_body_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 "rigid_body_2d.h"
32
33
void RigidBody2D::_body_enter_tree(ObjectID p_id) {
34
Object *obj = ObjectDB::get_instance(p_id);
35
Node *node = Object::cast_to<Node>(obj);
36
ERR_FAIL_NULL(node);
37
ERR_FAIL_NULL(contact_monitor);
38
HashMap<ObjectID, BodyState>::Iterator E = contact_monitor->body_map.find(p_id);
39
ERR_FAIL_COND(!E);
40
ERR_FAIL_COND(E->value.in_scene);
41
42
contact_monitor->locked = true;
43
44
E->value.in_scene = true;
45
emit_signal(SceneStringName(body_entered), node);
46
47
for (int i = 0; i < E->value.shapes.size(); i++) {
48
emit_signal(SceneStringName(body_shape_entered), E->value.rid, node, E->value.shapes[i].body_shape, E->value.shapes[i].local_shape);
49
}
50
51
contact_monitor->locked = false;
52
}
53
54
void RigidBody2D::_body_exit_tree(ObjectID p_id) {
55
Object *obj = ObjectDB::get_instance(p_id);
56
Node *node = Object::cast_to<Node>(obj);
57
ERR_FAIL_NULL(node);
58
ERR_FAIL_NULL(contact_monitor);
59
HashMap<ObjectID, BodyState>::Iterator E = contact_monitor->body_map.find(p_id);
60
ERR_FAIL_COND(!E);
61
ERR_FAIL_COND(!E->value.in_scene);
62
E->value.in_scene = false;
63
64
contact_monitor->locked = true;
65
66
emit_signal(SceneStringName(body_exited), node);
67
68
for (int i = 0; i < E->value.shapes.size(); i++) {
69
emit_signal(SceneStringName(body_shape_exited), E->value.rid, node, E->value.shapes[i].body_shape, E->value.shapes[i].local_shape);
70
}
71
72
contact_monitor->locked = false;
73
}
74
75
void RigidBody2D::_body_inout(int p_status, const RID &p_body, ObjectID p_instance, int p_body_shape, int p_local_shape) {
76
bool body_in = p_status == 1;
77
ObjectID objid = p_instance;
78
79
Object *obj = ObjectDB::get_instance(objid);
80
Node *node = Object::cast_to<Node>(obj);
81
82
ERR_FAIL_NULL(contact_monitor);
83
HashMap<ObjectID, BodyState>::Iterator E = contact_monitor->body_map.find(objid);
84
85
ERR_FAIL_COND(!body_in && !E);
86
87
if (body_in) {
88
if (!E) {
89
E = contact_monitor->body_map.insert(objid, BodyState());
90
E->value.rid = p_body;
91
//E->value.rc=0;
92
E->value.in_scene = node && node->is_inside_tree();
93
if (node) {
94
node->connect(SceneStringName(tree_entered), callable_mp(this, &RigidBody2D::_body_enter_tree).bind(objid));
95
node->connect(SceneStringName(tree_exiting), callable_mp(this, &RigidBody2D::_body_exit_tree).bind(objid));
96
if (E->value.in_scene) {
97
emit_signal(SceneStringName(body_entered), node);
98
}
99
}
100
101
//E->value.rc++;
102
}
103
104
if (node) {
105
E->value.shapes.insert(ShapePair(p_body_shape, p_local_shape));
106
}
107
108
if (E->value.in_scene) {
109
emit_signal(SceneStringName(body_shape_entered), p_body, node, p_body_shape, p_local_shape);
110
}
111
112
} else {
113
//E->value.rc--;
114
115
if (node) {
116
E->value.shapes.erase(ShapePair(p_body_shape, p_local_shape));
117
}
118
119
bool in_scene = E->value.in_scene;
120
121
if (E->value.shapes.is_empty()) {
122
if (node) {
123
node->disconnect(SceneStringName(tree_entered), callable_mp(this, &RigidBody2D::_body_enter_tree));
124
node->disconnect(SceneStringName(tree_exiting), callable_mp(this, &RigidBody2D::_body_exit_tree));
125
if (in_scene) {
126
emit_signal(SceneStringName(body_exited), node);
127
}
128
}
129
130
contact_monitor->body_map.remove(E);
131
}
132
if (node && in_scene) {
133
emit_signal(SceneStringName(body_shape_exited), p_body, node, p_body_shape, p_local_shape);
134
}
135
}
136
}
137
138
struct _RigidBody2DInOut {
139
RID rid;
140
ObjectID id;
141
int shape = 0;
142
int local_shape = 0;
143
};
144
145
void RigidBody2D::_sync_body_state(PhysicsDirectBodyState2D *p_state) {
146
if (!freeze || freeze_mode != FREEZE_MODE_KINEMATIC) {
147
set_block_transform_notify(true);
148
set_global_transform(p_state->get_transform());
149
set_block_transform_notify(false);
150
}
151
152
linear_velocity = p_state->get_linear_velocity();
153
angular_velocity = p_state->get_angular_velocity();
154
155
contact_count = p_state->get_contact_count();
156
157
if (sleeping != p_state->is_sleeping()) {
158
sleeping = p_state->is_sleeping();
159
emit_signal(SceneStringName(sleeping_state_changed));
160
}
161
}
162
163
void RigidBody2D::_body_state_changed(PhysicsDirectBodyState2D *p_state) {
164
lock_callback();
165
166
if (GDVIRTUAL_IS_OVERRIDDEN(_integrate_forces)) {
167
_sync_body_state(p_state);
168
169
Transform2D old_transform = get_global_transform();
170
GDVIRTUAL_CALL(_integrate_forces, p_state);
171
Transform2D new_transform = get_global_transform();
172
173
if (new_transform != old_transform) {
174
// Update the physics server with the new transform, to prevent it from being overwritten at the sync below.
175
PhysicsServer2D::get_singleton()->body_set_state(get_rid(), PhysicsServer2D::BODY_STATE_TRANSFORM, new_transform);
176
}
177
}
178
179
_sync_body_state(p_state);
180
181
if (contact_monitor) {
182
contact_monitor->locked = true;
183
184
//untag all
185
int rc = 0;
186
for (KeyValue<ObjectID, BodyState> &E : contact_monitor->body_map) {
187
for (int i = 0; i < E.value.shapes.size(); i++) {
188
E.value.shapes[i].tagged = false;
189
rc++;
190
}
191
}
192
193
_RigidBody2DInOut *toadd = (_RigidBody2DInOut *)alloca(p_state->get_contact_count() * sizeof(_RigidBody2DInOut));
194
int toadd_count = 0; //state->get_contact_count();
195
RigidBody2D_RemoveAction *toremove = (RigidBody2D_RemoveAction *)alloca(rc * sizeof(RigidBody2D_RemoveAction));
196
int toremove_count = 0;
197
198
//put the ones to add
199
200
for (int i = 0; i < p_state->get_contact_count(); i++) {
201
RID col_rid = p_state->get_contact_collider(i);
202
ObjectID col_obj = p_state->get_contact_collider_id(i);
203
int local_shape = p_state->get_contact_local_shape(i);
204
int col_shape = p_state->get_contact_collider_shape(i);
205
206
HashMap<ObjectID, BodyState>::Iterator E = contact_monitor->body_map.find(col_obj);
207
if (!E) {
208
toadd[toadd_count].rid = col_rid;
209
toadd[toadd_count].local_shape = local_shape;
210
toadd[toadd_count].id = col_obj;
211
toadd[toadd_count].shape = col_shape;
212
toadd_count++;
213
continue;
214
}
215
216
ShapePair sp(col_shape, local_shape);
217
int idx = E->value.shapes.find(sp);
218
if (idx == -1) {
219
toadd[toadd_count].rid = col_rid;
220
toadd[toadd_count].local_shape = local_shape;
221
toadd[toadd_count].id = col_obj;
222
toadd[toadd_count].shape = col_shape;
223
toadd_count++;
224
continue;
225
}
226
227
E->value.shapes[idx].tagged = true;
228
}
229
230
//put the ones to remove
231
232
for (const KeyValue<ObjectID, BodyState> &E : contact_monitor->body_map) {
233
for (int i = 0; i < E.value.shapes.size(); i++) {
234
if (!E.value.shapes[i].tagged) {
235
toremove[toremove_count].rid = E.value.rid;
236
toremove[toremove_count].body_id = E.key;
237
toremove[toremove_count].pair = E.value.shapes[i];
238
toremove_count++;
239
}
240
}
241
}
242
243
//process removals
244
245
for (int i = 0; i < toremove_count; i++) {
246
_body_inout(0, toremove[i].rid, toremove[i].body_id, toremove[i].pair.body_shape, toremove[i].pair.local_shape);
247
}
248
249
//process additions
250
251
for (int i = 0; i < toadd_count; i++) {
252
_body_inout(1, toadd[i].rid, toadd[i].id, toadd[i].shape, toadd[i].local_shape);
253
}
254
255
contact_monitor->locked = false;
256
}
257
258
unlock_callback();
259
}
260
261
void RigidBody2D::_apply_body_mode() {
262
if (freeze) {
263
switch (freeze_mode) {
264
case FREEZE_MODE_STATIC: {
265
set_body_mode(PhysicsServer2D::BODY_MODE_STATIC);
266
} break;
267
case FREEZE_MODE_KINEMATIC: {
268
set_body_mode(PhysicsServer2D::BODY_MODE_KINEMATIC);
269
} break;
270
}
271
} else if (lock_rotation) {
272
set_body_mode(PhysicsServer2D::BODY_MODE_RIGID_LINEAR);
273
} else {
274
set_body_mode(PhysicsServer2D::BODY_MODE_RIGID);
275
}
276
}
277
278
void RigidBody2D::set_lock_rotation_enabled(bool p_lock_rotation) {
279
if (p_lock_rotation == lock_rotation) {
280
return;
281
}
282
283
lock_rotation = p_lock_rotation;
284
_apply_body_mode();
285
}
286
287
bool RigidBody2D::is_lock_rotation_enabled() const {
288
return lock_rotation;
289
}
290
291
void RigidBody2D::set_freeze_enabled(bool p_freeze) {
292
if (p_freeze == freeze) {
293
return;
294
}
295
296
freeze = p_freeze;
297
_apply_body_mode();
298
}
299
300
bool RigidBody2D::is_freeze_enabled() const {
301
return freeze;
302
}
303
304
void RigidBody2D::set_freeze_mode(FreezeMode p_freeze_mode) {
305
if (p_freeze_mode == freeze_mode) {
306
return;
307
}
308
309
freeze_mode = p_freeze_mode;
310
_apply_body_mode();
311
}
312
313
RigidBody2D::FreezeMode RigidBody2D::get_freeze_mode() const {
314
return freeze_mode;
315
}
316
317
void RigidBody2D::set_mass(real_t p_mass) {
318
ERR_FAIL_COND(p_mass <= 0);
319
mass = p_mass;
320
PhysicsServer2D::get_singleton()->body_set_param(get_rid(), PhysicsServer2D::BODY_PARAM_MASS, mass);
321
}
322
323
real_t RigidBody2D::get_mass() const {
324
return mass;
325
}
326
327
void RigidBody2D::set_inertia(real_t p_inertia) {
328
ERR_FAIL_COND(p_inertia < 0);
329
inertia = p_inertia;
330
PhysicsServer2D::get_singleton()->body_set_param(get_rid(), PhysicsServer2D::BODY_PARAM_INERTIA, inertia);
331
}
332
333
real_t RigidBody2D::get_inertia() const {
334
return inertia;
335
}
336
337
void RigidBody2D::set_center_of_mass_mode(CenterOfMassMode p_mode) {
338
if (center_of_mass_mode == p_mode) {
339
return;
340
}
341
342
center_of_mass_mode = p_mode;
343
344
switch (center_of_mass_mode) {
345
case CENTER_OF_MASS_MODE_AUTO: {
346
center_of_mass = Vector2();
347
PhysicsServer2D::get_singleton()->body_reset_mass_properties(get_rid());
348
if (inertia != 0.0) {
349
PhysicsServer2D::get_singleton()->body_set_param(get_rid(), PhysicsServer2D::BODY_PARAM_INERTIA, inertia);
350
}
351
} break;
352
353
case CENTER_OF_MASS_MODE_CUSTOM: {
354
PhysicsServer2D::get_singleton()->body_set_param(get_rid(), PhysicsServer2D::BODY_PARAM_CENTER_OF_MASS, center_of_mass);
355
} break;
356
}
357
358
notify_property_list_changed();
359
}
360
361
RigidBody2D::CenterOfMassMode RigidBody2D::get_center_of_mass_mode() const {
362
return center_of_mass_mode;
363
}
364
365
void RigidBody2D::set_center_of_mass(const Vector2 &p_center_of_mass) {
366
if (center_of_mass == p_center_of_mass) {
367
return;
368
}
369
370
ERR_FAIL_COND(center_of_mass_mode != CENTER_OF_MASS_MODE_CUSTOM);
371
center_of_mass = p_center_of_mass;
372
373
PhysicsServer2D::get_singleton()->body_set_param(get_rid(), PhysicsServer2D::BODY_PARAM_CENTER_OF_MASS, center_of_mass);
374
}
375
376
const Vector2 &RigidBody2D::get_center_of_mass() const {
377
return center_of_mass;
378
}
379
380
void RigidBody2D::set_physics_material_override(const Ref<PhysicsMaterial> &p_physics_material_override) {
381
if (physics_material_override.is_valid()) {
382
physics_material_override->disconnect_changed(callable_mp(this, &RigidBody2D::_reload_physics_characteristics));
383
}
384
385
physics_material_override = p_physics_material_override;
386
387
if (physics_material_override.is_valid()) {
388
physics_material_override->connect_changed(callable_mp(this, &RigidBody2D::_reload_physics_characteristics));
389
}
390
_reload_physics_characteristics();
391
}
392
393
Ref<PhysicsMaterial> RigidBody2D::get_physics_material_override() const {
394
return physics_material_override;
395
}
396
397
void RigidBody2D::set_gravity_scale(real_t p_gravity_scale) {
398
gravity_scale = p_gravity_scale;
399
PhysicsServer2D::get_singleton()->body_set_param(get_rid(), PhysicsServer2D::BODY_PARAM_GRAVITY_SCALE, gravity_scale);
400
}
401
402
real_t RigidBody2D::get_gravity_scale() const {
403
return gravity_scale;
404
}
405
406
void RigidBody2D::set_linear_damp_mode(DampMode p_mode) {
407
linear_damp_mode = p_mode;
408
PhysicsServer2D::get_singleton()->body_set_param(get_rid(), PhysicsServer2D::BODY_PARAM_LINEAR_DAMP_MODE, linear_damp_mode);
409
}
410
411
RigidBody2D::DampMode RigidBody2D::get_linear_damp_mode() const {
412
return linear_damp_mode;
413
}
414
415
void RigidBody2D::set_angular_damp_mode(DampMode p_mode) {
416
angular_damp_mode = p_mode;
417
PhysicsServer2D::get_singleton()->body_set_param(get_rid(), PhysicsServer2D::BODY_PARAM_ANGULAR_DAMP_MODE, angular_damp_mode);
418
}
419
420
RigidBody2D::DampMode RigidBody2D::get_angular_damp_mode() const {
421
return angular_damp_mode;
422
}
423
424
void RigidBody2D::set_linear_damp(real_t p_linear_damp) {
425
ERR_FAIL_COND(p_linear_damp < -1);
426
linear_damp = p_linear_damp;
427
PhysicsServer2D::get_singleton()->body_set_param(get_rid(), PhysicsServer2D::BODY_PARAM_LINEAR_DAMP, linear_damp);
428
}
429
430
real_t RigidBody2D::get_linear_damp() const {
431
return linear_damp;
432
}
433
434
void RigidBody2D::set_angular_damp(real_t p_angular_damp) {
435
ERR_FAIL_COND(p_angular_damp < -1);
436
angular_damp = p_angular_damp;
437
PhysicsServer2D::get_singleton()->body_set_param(get_rid(), PhysicsServer2D::BODY_PARAM_ANGULAR_DAMP, angular_damp);
438
}
439
440
real_t RigidBody2D::get_angular_damp() const {
441
return angular_damp;
442
}
443
444
void RigidBody2D::set_axis_velocity(const Vector2 &p_axis) {
445
Vector2 axis = p_axis.normalized();
446
linear_velocity -= axis * axis.dot(linear_velocity);
447
linear_velocity += p_axis;
448
PhysicsServer2D::get_singleton()->body_set_state(get_rid(), PhysicsServer2D::BODY_STATE_LINEAR_VELOCITY, linear_velocity);
449
}
450
451
void RigidBody2D::set_linear_velocity(const Vector2 &p_velocity) {
452
linear_velocity = p_velocity;
453
PhysicsServer2D::get_singleton()->body_set_state(get_rid(), PhysicsServer2D::BODY_STATE_LINEAR_VELOCITY, linear_velocity);
454
}
455
456
Vector2 RigidBody2D::get_linear_velocity() const {
457
return linear_velocity;
458
}
459
460
void RigidBody2D::set_angular_velocity(real_t p_velocity) {
461
angular_velocity = p_velocity;
462
PhysicsServer2D::get_singleton()->body_set_state(get_rid(), PhysicsServer2D::BODY_STATE_ANGULAR_VELOCITY, angular_velocity);
463
}
464
465
real_t RigidBody2D::get_angular_velocity() const {
466
return angular_velocity;
467
}
468
469
void RigidBody2D::set_use_custom_integrator(bool p_enable) {
470
if (custom_integrator == p_enable) {
471
return;
472
}
473
474
custom_integrator = p_enable;
475
PhysicsServer2D::get_singleton()->body_set_omit_force_integration(get_rid(), p_enable);
476
}
477
478
bool RigidBody2D::is_using_custom_integrator() {
479
return custom_integrator;
480
}
481
482
void RigidBody2D::set_sleeping(bool p_sleeping) {
483
sleeping = p_sleeping;
484
PhysicsServer2D::get_singleton()->body_set_state(get_rid(), PhysicsServer2D::BODY_STATE_SLEEPING, sleeping);
485
}
486
487
void RigidBody2D::set_can_sleep(bool p_active) {
488
can_sleep = p_active;
489
PhysicsServer2D::get_singleton()->body_set_state(get_rid(), PhysicsServer2D::BODY_STATE_CAN_SLEEP, p_active);
490
}
491
492
bool RigidBody2D::is_able_to_sleep() const {
493
return can_sleep;
494
}
495
496
bool RigidBody2D::is_sleeping() const {
497
return sleeping;
498
}
499
500
void RigidBody2D::set_max_contacts_reported(int p_amount) {
501
ERR_FAIL_INDEX_MSG(p_amount, MAX_CONTACTS_REPORTED_2D_MAX, "Max contacts reported allocates memory (about 100 bytes each), and therefore must not be set too high.");
502
max_contacts_reported = p_amount;
503
PhysicsServer2D::get_singleton()->body_set_max_contacts_reported(get_rid(), p_amount);
504
}
505
506
int RigidBody2D::get_max_contacts_reported() const {
507
return max_contacts_reported;
508
}
509
510
int RigidBody2D::get_contact_count() const {
511
return contact_count;
512
}
513
514
void RigidBody2D::apply_central_impulse(const Vector2 &p_impulse) {
515
PhysicsServer2D::get_singleton()->body_apply_central_impulse(get_rid(), p_impulse);
516
}
517
518
void RigidBody2D::apply_impulse(const Vector2 &p_impulse, const Vector2 &p_position) {
519
PhysicsServer2D::get_singleton()->body_apply_impulse(get_rid(), p_impulse, p_position);
520
}
521
522
void RigidBody2D::apply_torque_impulse(real_t p_torque) {
523
PhysicsServer2D::get_singleton()->body_apply_torque_impulse(get_rid(), p_torque);
524
}
525
526
void RigidBody2D::apply_central_force(const Vector2 &p_force) {
527
PhysicsServer2D::get_singleton()->body_apply_central_force(get_rid(), p_force);
528
}
529
530
void RigidBody2D::apply_force(const Vector2 &p_force, const Vector2 &p_position) {
531
PhysicsServer2D::get_singleton()->body_apply_force(get_rid(), p_force, p_position);
532
}
533
534
void RigidBody2D::apply_torque(real_t p_torque) {
535
PhysicsServer2D::get_singleton()->body_apply_torque(get_rid(), p_torque);
536
}
537
538
void RigidBody2D::add_constant_central_force(const Vector2 &p_force) {
539
PhysicsServer2D::get_singleton()->body_add_constant_central_force(get_rid(), p_force);
540
}
541
542
void RigidBody2D::add_constant_force(const Vector2 &p_force, const Vector2 &p_position) {
543
PhysicsServer2D::get_singleton()->body_add_constant_force(get_rid(), p_force, p_position);
544
}
545
546
void RigidBody2D::add_constant_torque(const real_t p_torque) {
547
PhysicsServer2D::get_singleton()->body_add_constant_torque(get_rid(), p_torque);
548
}
549
550
void RigidBody2D::set_constant_force(const Vector2 &p_force) {
551
PhysicsServer2D::get_singleton()->body_set_constant_force(get_rid(), p_force);
552
}
553
554
Vector2 RigidBody2D::get_constant_force() const {
555
return PhysicsServer2D::get_singleton()->body_get_constant_force(get_rid());
556
}
557
558
void RigidBody2D::set_constant_torque(real_t p_torque) {
559
PhysicsServer2D::get_singleton()->body_set_constant_torque(get_rid(), p_torque);
560
}
561
562
real_t RigidBody2D::get_constant_torque() const {
563
return PhysicsServer2D::get_singleton()->body_get_constant_torque(get_rid());
564
}
565
566
void RigidBody2D::set_continuous_collision_detection_mode(CCDMode p_mode) {
567
ccd_mode = p_mode;
568
PhysicsServer2D::get_singleton()->body_set_continuous_collision_detection_mode(get_rid(), PhysicsServer2D::CCDMode(p_mode));
569
}
570
571
RigidBody2D::CCDMode RigidBody2D::get_continuous_collision_detection_mode() const {
572
return ccd_mode;
573
}
574
575
TypedArray<Node2D> RigidBody2D::get_colliding_bodies() const {
576
ERR_FAIL_NULL_V(contact_monitor, TypedArray<Node2D>());
577
578
TypedArray<Node2D> ret;
579
ret.resize(contact_monitor->body_map.size());
580
int idx = 0;
581
for (const KeyValue<ObjectID, BodyState> &E : contact_monitor->body_map) {
582
Object *obj = ObjectDB::get_instance(E.key);
583
if (!obj) {
584
ret.resize(ret.size() - 1); //ops
585
} else {
586
ret[idx++] = obj;
587
}
588
}
589
590
return ret;
591
}
592
593
void RigidBody2D::set_contact_monitor(bool p_enabled) {
594
if (p_enabled == is_contact_monitor_enabled()) {
595
return;
596
}
597
598
if (!p_enabled) {
599
ERR_FAIL_COND_MSG(contact_monitor->locked, "Can't disable contact monitoring during in/out callback. Use call_deferred(\"set_contact_monitor\", false) instead.");
600
601
for (const KeyValue<ObjectID, BodyState> &E : contact_monitor->body_map) {
602
//clean up mess
603
Object *obj = ObjectDB::get_instance(E.key);
604
Node *node = Object::cast_to<Node>(obj);
605
606
if (node) {
607
node->disconnect(SceneStringName(tree_entered), callable_mp(this, &RigidBody2D::_body_enter_tree));
608
node->disconnect(SceneStringName(tree_exiting), callable_mp(this, &RigidBody2D::_body_exit_tree));
609
}
610
}
611
612
memdelete(contact_monitor);
613
contact_monitor = nullptr;
614
} else {
615
contact_monitor = memnew(ContactMonitor);
616
contact_monitor->locked = false;
617
}
618
619
notify_property_list_changed();
620
}
621
622
bool RigidBody2D::is_contact_monitor_enabled() const {
623
return contact_monitor != nullptr;
624
}
625
626
void RigidBody2D::_notification(int p_what) {
627
#ifdef TOOLS_ENABLED
628
switch (p_what) {
629
case NOTIFICATION_ENTER_TREE: {
630
if (Engine::get_singleton()->is_editor_hint()) {
631
set_notify_local_transform(true); // Used for warnings and only in editor.
632
}
633
} break;
634
635
case NOTIFICATION_LOCAL_TRANSFORM_CHANGED: {
636
update_configuration_warnings();
637
} break;
638
}
639
#endif
640
}
641
642
PackedStringArray RigidBody2D::get_configuration_warnings() const {
643
Transform2D t = get_transform();
644
645
PackedStringArray warnings = PhysicsBody2D::get_configuration_warnings();
646
647
if (Math::abs(t.columns[0].length() - 1.0) > 0.05 || Math::abs(t.columns[1].length() - 1.0) > 0.05) {
648
warnings.push_back(RTR("Size changes to RigidBody2D will be overridden by the physics engine when running.\nChange the size in children collision shapes instead."));
649
}
650
651
return warnings;
652
}
653
654
void RigidBody2D::_bind_methods() {
655
ClassDB::bind_method(D_METHOD("set_mass", "mass"), &RigidBody2D::set_mass);
656
ClassDB::bind_method(D_METHOD("get_mass"), &RigidBody2D::get_mass);
657
658
ClassDB::bind_method(D_METHOD("get_inertia"), &RigidBody2D::get_inertia);
659
ClassDB::bind_method(D_METHOD("set_inertia", "inertia"), &RigidBody2D::set_inertia);
660
661
ClassDB::bind_method(D_METHOD("set_center_of_mass_mode", "mode"), &RigidBody2D::set_center_of_mass_mode);
662
ClassDB::bind_method(D_METHOD("get_center_of_mass_mode"), &RigidBody2D::get_center_of_mass_mode);
663
664
ClassDB::bind_method(D_METHOD("set_center_of_mass", "center_of_mass"), &RigidBody2D::set_center_of_mass);
665
ClassDB::bind_method(D_METHOD("get_center_of_mass"), &RigidBody2D::get_center_of_mass);
666
667
ClassDB::bind_method(D_METHOD("set_physics_material_override", "physics_material_override"), &RigidBody2D::set_physics_material_override);
668
ClassDB::bind_method(D_METHOD("get_physics_material_override"), &RigidBody2D::get_physics_material_override);
669
670
ClassDB::bind_method(D_METHOD("set_gravity_scale", "gravity_scale"), &RigidBody2D::set_gravity_scale);
671
ClassDB::bind_method(D_METHOD("get_gravity_scale"), &RigidBody2D::get_gravity_scale);
672
673
ClassDB::bind_method(D_METHOD("set_linear_damp_mode", "linear_damp_mode"), &RigidBody2D::set_linear_damp_mode);
674
ClassDB::bind_method(D_METHOD("get_linear_damp_mode"), &RigidBody2D::get_linear_damp_mode);
675
676
ClassDB::bind_method(D_METHOD("set_angular_damp_mode", "angular_damp_mode"), &RigidBody2D::set_angular_damp_mode);
677
ClassDB::bind_method(D_METHOD("get_angular_damp_mode"), &RigidBody2D::get_angular_damp_mode);
678
679
ClassDB::bind_method(D_METHOD("set_linear_damp", "linear_damp"), &RigidBody2D::set_linear_damp);
680
ClassDB::bind_method(D_METHOD("get_linear_damp"), &RigidBody2D::get_linear_damp);
681
682
ClassDB::bind_method(D_METHOD("set_angular_damp", "angular_damp"), &RigidBody2D::set_angular_damp);
683
ClassDB::bind_method(D_METHOD("get_angular_damp"), &RigidBody2D::get_angular_damp);
684
685
ClassDB::bind_method(D_METHOD("set_linear_velocity", "linear_velocity"), &RigidBody2D::set_linear_velocity);
686
ClassDB::bind_method(D_METHOD("get_linear_velocity"), &RigidBody2D::get_linear_velocity);
687
688
ClassDB::bind_method(D_METHOD("set_angular_velocity", "angular_velocity"), &RigidBody2D::set_angular_velocity);
689
ClassDB::bind_method(D_METHOD("get_angular_velocity"), &RigidBody2D::get_angular_velocity);
690
691
ClassDB::bind_method(D_METHOD("set_max_contacts_reported", "amount"), &RigidBody2D::set_max_contacts_reported);
692
ClassDB::bind_method(D_METHOD("get_max_contacts_reported"), &RigidBody2D::get_max_contacts_reported);
693
ClassDB::bind_method(D_METHOD("get_contact_count"), &RigidBody2D::get_contact_count);
694
695
ClassDB::bind_method(D_METHOD("set_use_custom_integrator", "enable"), &RigidBody2D::set_use_custom_integrator);
696
ClassDB::bind_method(D_METHOD("is_using_custom_integrator"), &RigidBody2D::is_using_custom_integrator);
697
698
ClassDB::bind_method(D_METHOD("set_contact_monitor", "enabled"), &RigidBody2D::set_contact_monitor);
699
ClassDB::bind_method(D_METHOD("is_contact_monitor_enabled"), &RigidBody2D::is_contact_monitor_enabled);
700
701
ClassDB::bind_method(D_METHOD("set_continuous_collision_detection_mode", "mode"), &RigidBody2D::set_continuous_collision_detection_mode);
702
ClassDB::bind_method(D_METHOD("get_continuous_collision_detection_mode"), &RigidBody2D::get_continuous_collision_detection_mode);
703
704
ClassDB::bind_method(D_METHOD("set_axis_velocity", "axis_velocity"), &RigidBody2D::set_axis_velocity);
705
ClassDB::bind_method(D_METHOD("apply_central_impulse", "impulse"), &RigidBody2D::apply_central_impulse, Vector2());
706
ClassDB::bind_method(D_METHOD("apply_impulse", "impulse", "position"), &RigidBody2D::apply_impulse, Vector2());
707
ClassDB::bind_method(D_METHOD("apply_torque_impulse", "torque"), &RigidBody2D::apply_torque_impulse);
708
709
ClassDB::bind_method(D_METHOD("apply_central_force", "force"), &RigidBody2D::apply_central_force);
710
ClassDB::bind_method(D_METHOD("apply_force", "force", "position"), &RigidBody2D::apply_force, Vector2());
711
ClassDB::bind_method(D_METHOD("apply_torque", "torque"), &RigidBody2D::apply_torque);
712
713
ClassDB::bind_method(D_METHOD("add_constant_central_force", "force"), &RigidBody2D::add_constant_central_force);
714
ClassDB::bind_method(D_METHOD("add_constant_force", "force", "position"), &RigidBody2D::add_constant_force, Vector2());
715
ClassDB::bind_method(D_METHOD("add_constant_torque", "torque"), &RigidBody2D::add_constant_torque);
716
717
ClassDB::bind_method(D_METHOD("set_constant_force", "force"), &RigidBody2D::set_constant_force);
718
ClassDB::bind_method(D_METHOD("get_constant_force"), &RigidBody2D::get_constant_force);
719
720
ClassDB::bind_method(D_METHOD("set_constant_torque", "torque"), &RigidBody2D::set_constant_torque);
721
ClassDB::bind_method(D_METHOD("get_constant_torque"), &RigidBody2D::get_constant_torque);
722
723
ClassDB::bind_method(D_METHOD("set_sleeping", "sleeping"), &RigidBody2D::set_sleeping);
724
ClassDB::bind_method(D_METHOD("is_sleeping"), &RigidBody2D::is_sleeping);
725
726
ClassDB::bind_method(D_METHOD("set_can_sleep", "able_to_sleep"), &RigidBody2D::set_can_sleep);
727
ClassDB::bind_method(D_METHOD("is_able_to_sleep"), &RigidBody2D::is_able_to_sleep);
728
729
ClassDB::bind_method(D_METHOD("set_lock_rotation_enabled", "lock_rotation"), &RigidBody2D::set_lock_rotation_enabled);
730
ClassDB::bind_method(D_METHOD("is_lock_rotation_enabled"), &RigidBody2D::is_lock_rotation_enabled);
731
732
ClassDB::bind_method(D_METHOD("set_freeze_enabled", "freeze_mode"), &RigidBody2D::set_freeze_enabled);
733
ClassDB::bind_method(D_METHOD("is_freeze_enabled"), &RigidBody2D::is_freeze_enabled);
734
735
ClassDB::bind_method(D_METHOD("set_freeze_mode", "freeze_mode"), &RigidBody2D::set_freeze_mode);
736
ClassDB::bind_method(D_METHOD("get_freeze_mode"), &RigidBody2D::get_freeze_mode);
737
738
ClassDB::bind_method(D_METHOD("get_colliding_bodies"), &RigidBody2D::get_colliding_bodies);
739
740
GDVIRTUAL_BIND(_integrate_forces, "state");
741
742
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "mass", PROPERTY_HINT_RANGE, "0.001,1000,0.001,or_greater,exp,suffix:kg"), "set_mass", "get_mass");
743
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "physics_material_override", PROPERTY_HINT_RESOURCE_TYPE, "PhysicsMaterial"), "set_physics_material_override", "get_physics_material_override");
744
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "gravity_scale", PROPERTY_HINT_RANGE, "-8,8,0.001,or_less,or_greater"), "set_gravity_scale", "get_gravity_scale");
745
ADD_GROUP("Mass Distribution", "");
746
ADD_PROPERTY(PropertyInfo(Variant::INT, "center_of_mass_mode", PROPERTY_HINT_ENUM, "Auto,Custom"), "set_center_of_mass_mode", "get_center_of_mass_mode");
747
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "center_of_mass", PROPERTY_HINT_RANGE, "-1000,1000,0.01,or_less,or_greater,suffix:px"), "set_center_of_mass", "get_center_of_mass");
748
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "inertia", PROPERTY_HINT_RANGE, U"0,1000,0.01,or_greater,exp,suffix:kg\u22C5px\u00B2"), "set_inertia", "get_inertia");
749
ADD_GROUP("Deactivation", "");
750
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "sleeping"), "set_sleeping", "is_sleeping");
751
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "can_sleep"), "set_can_sleep", "is_able_to_sleep");
752
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "lock_rotation"), "set_lock_rotation_enabled", "is_lock_rotation_enabled");
753
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "freeze"), "set_freeze_enabled", "is_freeze_enabled");
754
ADD_PROPERTY(PropertyInfo(Variant::INT, "freeze_mode", PROPERTY_HINT_ENUM, "Static,Kinematic"), "set_freeze_mode", "get_freeze_mode");
755
ADD_GROUP("Solver", "");
756
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "custom_integrator"), "set_use_custom_integrator", "is_using_custom_integrator");
757
ADD_PROPERTY(PropertyInfo(Variant::INT, "continuous_cd", PROPERTY_HINT_ENUM, "Disabled,Cast Ray,Cast Shape"), "set_continuous_collision_detection_mode", "get_continuous_collision_detection_mode");
758
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "contact_monitor"), "set_contact_monitor", "is_contact_monitor_enabled");
759
ADD_PROPERTY(PropertyInfo(Variant::INT, "max_contacts_reported", PROPERTY_HINT_RANGE, "0,64,1,or_greater"), "set_max_contacts_reported", "get_max_contacts_reported");
760
ADD_GROUP("Linear", "linear_");
761
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "linear_velocity", PROPERTY_HINT_NONE, "suffix:px/s"), "set_linear_velocity", "get_linear_velocity");
762
ADD_PROPERTY(PropertyInfo(Variant::INT, "linear_damp_mode", PROPERTY_HINT_ENUM, "Combine,Replace"), "set_linear_damp_mode", "get_linear_damp_mode");
763
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "linear_damp", PROPERTY_HINT_RANGE, "-1,100,0.001,or_greater"), "set_linear_damp", "get_linear_damp");
764
ADD_GROUP("Angular", "angular_");
765
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "angular_velocity", PROPERTY_HINT_NONE, U"radians_as_degrees,suffix:\u00B0/s"), "set_angular_velocity", "get_angular_velocity");
766
ADD_PROPERTY(PropertyInfo(Variant::INT, "angular_damp_mode", PROPERTY_HINT_ENUM, "Combine,Replace"), "set_angular_damp_mode", "get_angular_damp_mode");
767
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "angular_damp", PROPERTY_HINT_RANGE, "-1,100,0.001,or_greater"), "set_angular_damp", "get_angular_damp");
768
ADD_GROUP("Constant Forces", "constant_");
769
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "constant_force", PROPERTY_HINT_NONE, U"suffix:kg\u22C5px/s\u00B2"), "set_constant_force", "get_constant_force");
770
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "constant_torque", PROPERTY_HINT_NONE, U"suffix:kg\u22C5px\u00B2/s\u00B2/rad"), "set_constant_torque", "get_constant_torque");
771
772
ADD_SIGNAL(MethodInfo("body_shape_entered", PropertyInfo(Variant::RID, "body_rid"), PropertyInfo(Variant::OBJECT, "body", PROPERTY_HINT_RESOURCE_TYPE, "Node"), PropertyInfo(Variant::INT, "body_shape_index"), PropertyInfo(Variant::INT, "local_shape_index")));
773
ADD_SIGNAL(MethodInfo("body_shape_exited", PropertyInfo(Variant::RID, "body_rid"), PropertyInfo(Variant::OBJECT, "body", PROPERTY_HINT_RESOURCE_TYPE, "Node"), PropertyInfo(Variant::INT, "body_shape_index"), PropertyInfo(Variant::INT, "local_shape_index")));
774
ADD_SIGNAL(MethodInfo("body_entered", PropertyInfo(Variant::OBJECT, "body", PROPERTY_HINT_RESOURCE_TYPE, "Node")));
775
ADD_SIGNAL(MethodInfo("body_exited", PropertyInfo(Variant::OBJECT, "body", PROPERTY_HINT_RESOURCE_TYPE, "Node")));
776
ADD_SIGNAL(MethodInfo("sleeping_state_changed"));
777
778
BIND_ENUM_CONSTANT(FREEZE_MODE_STATIC);
779
BIND_ENUM_CONSTANT(FREEZE_MODE_KINEMATIC);
780
781
BIND_ENUM_CONSTANT(CENTER_OF_MASS_MODE_AUTO);
782
BIND_ENUM_CONSTANT(CENTER_OF_MASS_MODE_CUSTOM);
783
784
BIND_ENUM_CONSTANT(DAMP_MODE_COMBINE);
785
BIND_ENUM_CONSTANT(DAMP_MODE_REPLACE);
786
787
BIND_ENUM_CONSTANT(CCD_MODE_DISABLED);
788
BIND_ENUM_CONSTANT(CCD_MODE_CAST_RAY);
789
BIND_ENUM_CONSTANT(CCD_MODE_CAST_SHAPE);
790
}
791
792
void RigidBody2D::_validate_property(PropertyInfo &p_property) const {
793
if (!Engine::get_singleton()->is_editor_hint()) {
794
return;
795
}
796
if (center_of_mass_mode != CENTER_OF_MASS_MODE_CUSTOM && p_property.name == "center_of_mass") {
797
p_property.usage = PROPERTY_USAGE_NO_EDITOR;
798
}
799
800
if (!contact_monitor && p_property.name == "max_contacts_reported") {
801
p_property.usage = PROPERTY_USAGE_NO_EDITOR;
802
}
803
}
804
805
RigidBody2D::RigidBody2D() :
806
PhysicsBody2D(PhysicsServer2D::BODY_MODE_RIGID) {
807
PhysicsServer2D::get_singleton()->body_set_state_sync_callback(get_rid(), callable_mp(this, &RigidBody2D::_body_state_changed));
808
}
809
810
RigidBody2D::~RigidBody2D() {
811
if (contact_monitor) {
812
memdelete(contact_monitor);
813
}
814
}
815
816
void RigidBody2D::_reload_physics_characteristics() {
817
if (physics_material_override.is_null()) {
818
PhysicsServer2D::get_singleton()->body_set_param(get_rid(), PhysicsServer2D::BODY_PARAM_BOUNCE, 0);
819
PhysicsServer2D::get_singleton()->body_set_param(get_rid(), PhysicsServer2D::BODY_PARAM_FRICTION, 1);
820
} else {
821
PhysicsServer2D::get_singleton()->body_set_param(get_rid(), PhysicsServer2D::BODY_PARAM_BOUNCE, physics_material_override->computed_bounce());
822
PhysicsServer2D::get_singleton()->body_set_param(get_rid(), PhysicsServer2D::BODY_PARAM_FRICTION, physics_material_override->computed_friction());
823
}
824
}
825
826