physics_body_2d.cpp 75 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900
  1. /*************************************************************************/
  2. /* physics_body_2d.cpp */
  3. /*************************************************************************/
  4. /* This file is part of: */
  5. /* GODOT ENGINE */
  6. /* https://godotengine.org */
  7. /*************************************************************************/
  8. /* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
  9. /* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
  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. #include "physics_body_2d.h"
  31. #include "core/core_string_names.h"
  32. #include "scene/scene_string_names.h"
  33. void PhysicsBody2D::_bind_methods() {
  34. ClassDB::bind_method(D_METHOD("move_and_collide", "distance", "test_only", "safe_margin"), &PhysicsBody2D::_move, DEFVAL(false), DEFVAL(0.08));
  35. ClassDB::bind_method(D_METHOD("test_move", "from", "distance", "collision", "safe_margin"), &PhysicsBody2D::test_move, DEFVAL(Variant()), DEFVAL(0.08));
  36. ClassDB::bind_method(D_METHOD("get_collision_exceptions"), &PhysicsBody2D::get_collision_exceptions);
  37. ClassDB::bind_method(D_METHOD("add_collision_exception_with", "body"), &PhysicsBody2D::add_collision_exception_with);
  38. ClassDB::bind_method(D_METHOD("remove_collision_exception_with", "body"), &PhysicsBody2D::remove_collision_exception_with);
  39. }
  40. PhysicsBody2D::PhysicsBody2D(PhysicsServer2D::BodyMode p_mode) :
  41. CollisionObject2D(PhysicsServer2D::get_singleton()->body_create(), false) {
  42. set_body_mode(p_mode);
  43. set_pickable(false);
  44. }
  45. PhysicsBody2D::~PhysicsBody2D() {
  46. if (motion_cache.is_valid()) {
  47. motion_cache->owner = nullptr;
  48. }
  49. }
  50. Ref<KinematicCollision2D> PhysicsBody2D::_move(const Vector2 &p_distance, bool p_test_only, real_t p_margin) {
  51. PhysicsServer2D::MotionParameters parameters(get_global_transform(), p_distance, p_margin);
  52. parameters.recovery_as_collision = false; // Don't report collisions generated only from recovery.
  53. PhysicsServer2D::MotionResult result;
  54. if (move_and_collide(parameters, result, p_test_only)) {
  55. // Create a new instance when the cached reference is invalid or still in use in script.
  56. if (motion_cache.is_null() || motion_cache->reference_get_count() > 1) {
  57. motion_cache.instantiate();
  58. motion_cache->owner = this;
  59. }
  60. motion_cache->result = result;
  61. return motion_cache;
  62. }
  63. return Ref<KinematicCollision2D>();
  64. }
  65. bool PhysicsBody2D::move_and_collide(const PhysicsServer2D::MotionParameters &p_parameters, PhysicsServer2D::MotionResult &r_result, bool p_test_only, bool p_cancel_sliding) {
  66. if (is_only_update_transform_changes_enabled()) {
  67. ERR_PRINT("Move functions do not work together with 'sync to physics' option. Please read the documentation.");
  68. }
  69. bool colliding = PhysicsServer2D::get_singleton()->body_test_motion(get_rid(), p_parameters, &r_result);
  70. // Restore direction of motion to be along original motion,
  71. // in order to avoid sliding due to recovery,
  72. // but only if collision depth is low enough to avoid tunneling.
  73. if (p_cancel_sliding) {
  74. real_t motion_length = p_parameters.motion.length();
  75. real_t precision = 0.001;
  76. if (colliding) {
  77. // Can't just use margin as a threshold because collision depth is calculated on unsafe motion,
  78. // so even in normal resting cases the depth can be a bit more than the margin.
  79. precision += motion_length * (r_result.collision_unsafe_fraction - r_result.collision_safe_fraction);
  80. if (r_result.collision_depth > p_parameters.margin + precision) {
  81. p_cancel_sliding = false;
  82. }
  83. }
  84. if (p_cancel_sliding) {
  85. // When motion is null, recovery is the resulting motion.
  86. Vector2 motion_normal;
  87. if (motion_length > CMP_EPSILON) {
  88. motion_normal = p_parameters.motion / motion_length;
  89. }
  90. // Check depth of recovery.
  91. real_t projected_length = r_result.travel.dot(motion_normal);
  92. Vector2 recovery = r_result.travel - motion_normal * projected_length;
  93. real_t recovery_length = recovery.length();
  94. // Fixes cases where canceling slide causes the motion to go too deep into the ground,
  95. // because we're only taking rest information into account and not general recovery.
  96. if (recovery_length < p_parameters.margin + precision) {
  97. // Apply adjustment to motion.
  98. r_result.travel = motion_normal * projected_length;
  99. r_result.remainder = p_parameters.motion - r_result.travel;
  100. }
  101. }
  102. }
  103. if (!p_test_only) {
  104. Transform2D gt = p_parameters.from;
  105. gt.columns[2] += r_result.travel;
  106. set_global_transform(gt);
  107. }
  108. return colliding;
  109. }
  110. bool PhysicsBody2D::test_move(const Transform2D &p_from, const Vector2 &p_distance, const Ref<KinematicCollision2D> &r_collision, real_t p_margin) {
  111. ERR_FAIL_COND_V(!is_inside_tree(), false);
  112. PhysicsServer2D::MotionResult *r = nullptr;
  113. PhysicsServer2D::MotionResult temp_result;
  114. if (r_collision.is_valid()) {
  115. // Needs const_cast because method bindings don't support non-const Ref.
  116. r = const_cast<PhysicsServer2D::MotionResult *>(&r_collision->result);
  117. } else {
  118. r = &temp_result;
  119. }
  120. PhysicsServer2D::MotionParameters parameters(p_from, p_distance, p_margin);
  121. parameters.recovery_as_collision = false; // Don't report collisions generated only from recovery.
  122. return PhysicsServer2D::get_singleton()->body_test_motion(get_rid(), parameters, r);
  123. }
  124. TypedArray<PhysicsBody2D> PhysicsBody2D::get_collision_exceptions() {
  125. List<RID> exceptions;
  126. PhysicsServer2D::get_singleton()->body_get_collision_exceptions(get_rid(), &exceptions);
  127. Array ret;
  128. for (const RID &body : exceptions) {
  129. ObjectID instance_id = PhysicsServer2D::get_singleton()->body_get_object_instance_id(body);
  130. Object *obj = ObjectDB::get_instance(instance_id);
  131. PhysicsBody2D *physics_body = Object::cast_to<PhysicsBody2D>(obj);
  132. ret.append(physics_body);
  133. }
  134. return ret;
  135. }
  136. void PhysicsBody2D::add_collision_exception_with(Node *p_node) {
  137. ERR_FAIL_NULL(p_node);
  138. PhysicsBody2D *physics_body = Object::cast_to<PhysicsBody2D>(p_node);
  139. ERR_FAIL_COND_MSG(!physics_body, "Collision exception only works between two objects of PhysicsBody2D type.");
  140. PhysicsServer2D::get_singleton()->body_add_collision_exception(get_rid(), physics_body->get_rid());
  141. }
  142. void PhysicsBody2D::remove_collision_exception_with(Node *p_node) {
  143. ERR_FAIL_NULL(p_node);
  144. PhysicsBody2D *physics_body = Object::cast_to<PhysicsBody2D>(p_node);
  145. ERR_FAIL_COND_MSG(!physics_body, "Collision exception only works between two objects of PhysicsBody2D type.");
  146. PhysicsServer2D::get_singleton()->body_remove_collision_exception(get_rid(), physics_body->get_rid());
  147. }
  148. void StaticBody2D::set_constant_linear_velocity(const Vector2 &p_vel) {
  149. constant_linear_velocity = p_vel;
  150. PhysicsServer2D::get_singleton()->body_set_state(get_rid(), PhysicsServer2D::BODY_STATE_LINEAR_VELOCITY, constant_linear_velocity);
  151. }
  152. void StaticBody2D::set_constant_angular_velocity(real_t p_vel) {
  153. constant_angular_velocity = p_vel;
  154. PhysicsServer2D::get_singleton()->body_set_state(get_rid(), PhysicsServer2D::BODY_STATE_ANGULAR_VELOCITY, constant_angular_velocity);
  155. }
  156. Vector2 StaticBody2D::get_constant_linear_velocity() const {
  157. return constant_linear_velocity;
  158. }
  159. real_t StaticBody2D::get_constant_angular_velocity() const {
  160. return constant_angular_velocity;
  161. }
  162. void StaticBody2D::set_physics_material_override(const Ref<PhysicsMaterial> &p_physics_material_override) {
  163. if (physics_material_override.is_valid()) {
  164. if (physics_material_override->is_connected(CoreStringNames::get_singleton()->changed, callable_mp(this, &StaticBody2D::_reload_physics_characteristics))) {
  165. physics_material_override->disconnect(CoreStringNames::get_singleton()->changed, callable_mp(this, &StaticBody2D::_reload_physics_characteristics));
  166. }
  167. }
  168. physics_material_override = p_physics_material_override;
  169. if (physics_material_override.is_valid()) {
  170. physics_material_override->connect(CoreStringNames::get_singleton()->changed, callable_mp(this, &StaticBody2D::_reload_physics_characteristics));
  171. }
  172. _reload_physics_characteristics();
  173. }
  174. Ref<PhysicsMaterial> StaticBody2D::get_physics_material_override() const {
  175. return physics_material_override;
  176. }
  177. void StaticBody2D::_bind_methods() {
  178. ClassDB::bind_method(D_METHOD("set_constant_linear_velocity", "vel"), &StaticBody2D::set_constant_linear_velocity);
  179. ClassDB::bind_method(D_METHOD("set_constant_angular_velocity", "vel"), &StaticBody2D::set_constant_angular_velocity);
  180. ClassDB::bind_method(D_METHOD("get_constant_linear_velocity"), &StaticBody2D::get_constant_linear_velocity);
  181. ClassDB::bind_method(D_METHOD("get_constant_angular_velocity"), &StaticBody2D::get_constant_angular_velocity);
  182. ClassDB::bind_method(D_METHOD("set_physics_material_override", "physics_material_override"), &StaticBody2D::set_physics_material_override);
  183. ClassDB::bind_method(D_METHOD("get_physics_material_override"), &StaticBody2D::get_physics_material_override);
  184. ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "physics_material_override", PROPERTY_HINT_RESOURCE_TYPE, "PhysicsMaterial"), "set_physics_material_override", "get_physics_material_override");
  185. ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "constant_linear_velocity", PROPERTY_HINT_NONE, "suffix:px/s"), "set_constant_linear_velocity", "get_constant_linear_velocity");
  186. ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "constant_angular_velocity", PROPERTY_HINT_NONE, U"radians,suffix:\u00B0/s"), "set_constant_angular_velocity", "get_constant_angular_velocity");
  187. }
  188. StaticBody2D::StaticBody2D(PhysicsServer2D::BodyMode p_mode) :
  189. PhysicsBody2D(p_mode) {
  190. }
  191. void StaticBody2D::_reload_physics_characteristics() {
  192. if (physics_material_override.is_null()) {
  193. PhysicsServer2D::get_singleton()->body_set_param(get_rid(), PhysicsServer2D::BODY_PARAM_BOUNCE, 0);
  194. PhysicsServer2D::get_singleton()->body_set_param(get_rid(), PhysicsServer2D::BODY_PARAM_FRICTION, 1);
  195. } else {
  196. PhysicsServer2D::get_singleton()->body_set_param(get_rid(), PhysicsServer2D::BODY_PARAM_BOUNCE, physics_material_override->computed_bounce());
  197. PhysicsServer2D::get_singleton()->body_set_param(get_rid(), PhysicsServer2D::BODY_PARAM_FRICTION, physics_material_override->computed_friction());
  198. }
  199. }
  200. void AnimatableBody2D::set_sync_to_physics(bool p_enable) {
  201. if (sync_to_physics == p_enable) {
  202. return;
  203. }
  204. sync_to_physics = p_enable;
  205. _update_kinematic_motion();
  206. }
  207. bool AnimatableBody2D::is_sync_to_physics_enabled() const {
  208. return sync_to_physics;
  209. }
  210. void AnimatableBody2D::_update_kinematic_motion() {
  211. #ifdef TOOLS_ENABLED
  212. if (Engine::get_singleton()->is_editor_hint()) {
  213. return;
  214. }
  215. #endif
  216. if (sync_to_physics) {
  217. PhysicsServer2D::get_singleton()->body_set_state_sync_callback(get_rid(), this, _body_state_changed_callback);
  218. set_only_update_transform_changes(true);
  219. set_notify_local_transform(true);
  220. } else {
  221. PhysicsServer2D::get_singleton()->body_set_state_sync_callback(get_rid(), nullptr, nullptr);
  222. set_only_update_transform_changes(false);
  223. set_notify_local_transform(false);
  224. }
  225. }
  226. void AnimatableBody2D::_body_state_changed_callback(void *p_instance, PhysicsDirectBodyState2D *p_state) {
  227. AnimatableBody2D *body = static_cast<AnimatableBody2D *>(p_instance);
  228. body->_body_state_changed(p_state);
  229. }
  230. void AnimatableBody2D::_body_state_changed(PhysicsDirectBodyState2D *p_state) {
  231. if (!sync_to_physics) {
  232. return;
  233. }
  234. last_valid_transform = p_state->get_transform();
  235. set_notify_local_transform(false);
  236. set_global_transform(last_valid_transform);
  237. set_notify_local_transform(true);
  238. }
  239. void AnimatableBody2D::_notification(int p_what) {
  240. switch (p_what) {
  241. case NOTIFICATION_ENTER_TREE: {
  242. last_valid_transform = get_global_transform();
  243. _update_kinematic_motion();
  244. } break;
  245. case NOTIFICATION_EXIT_TREE: {
  246. set_only_update_transform_changes(false);
  247. set_notify_local_transform(false);
  248. } break;
  249. case NOTIFICATION_LOCAL_TRANSFORM_CHANGED: {
  250. // Used by sync to physics, send the new transform to the physics...
  251. Transform2D new_transform = get_global_transform();
  252. PhysicsServer2D::get_singleton()->body_set_state(get_rid(), PhysicsServer2D::BODY_STATE_TRANSFORM, new_transform);
  253. // ... but then revert changes.
  254. set_notify_local_transform(false);
  255. set_global_transform(last_valid_transform);
  256. set_notify_local_transform(true);
  257. } break;
  258. }
  259. }
  260. void AnimatableBody2D::_bind_methods() {
  261. ClassDB::bind_method(D_METHOD("set_sync_to_physics", "enable"), &AnimatableBody2D::set_sync_to_physics);
  262. ClassDB::bind_method(D_METHOD("is_sync_to_physics_enabled"), &AnimatableBody2D::is_sync_to_physics_enabled);
  263. ADD_PROPERTY(PropertyInfo(Variant::BOOL, "sync_to_physics"), "set_sync_to_physics", "is_sync_to_physics_enabled");
  264. }
  265. AnimatableBody2D::AnimatableBody2D() :
  266. StaticBody2D(PhysicsServer2D::BODY_MODE_KINEMATIC) {
  267. }
  268. void RigidBody2D::_body_enter_tree(ObjectID p_id) {
  269. Object *obj = ObjectDB::get_instance(p_id);
  270. Node *node = Object::cast_to<Node>(obj);
  271. ERR_FAIL_COND(!node);
  272. ERR_FAIL_COND(!contact_monitor);
  273. HashMap<ObjectID, BodyState>::Iterator E = contact_monitor->body_map.find(p_id);
  274. ERR_FAIL_COND(!E);
  275. ERR_FAIL_COND(E->value.in_scene);
  276. contact_monitor->locked = true;
  277. E->value.in_scene = true;
  278. emit_signal(SceneStringNames::get_singleton()->body_entered, node);
  279. for (int i = 0; i < E->value.shapes.size(); i++) {
  280. emit_signal(SceneStringNames::get_singleton()->body_shape_entered, E->value.rid, node, E->value.shapes[i].body_shape, E->value.shapes[i].local_shape);
  281. }
  282. contact_monitor->locked = false;
  283. }
  284. void RigidBody2D::_body_exit_tree(ObjectID p_id) {
  285. Object *obj = ObjectDB::get_instance(p_id);
  286. Node *node = Object::cast_to<Node>(obj);
  287. ERR_FAIL_COND(!node);
  288. ERR_FAIL_COND(!contact_monitor);
  289. HashMap<ObjectID, BodyState>::Iterator E = contact_monitor->body_map.find(p_id);
  290. ERR_FAIL_COND(!E);
  291. ERR_FAIL_COND(!E->value.in_scene);
  292. E->value.in_scene = false;
  293. contact_monitor->locked = true;
  294. emit_signal(SceneStringNames::get_singleton()->body_exited, node);
  295. for (int i = 0; i < E->value.shapes.size(); i++) {
  296. emit_signal(SceneStringNames::get_singleton()->body_shape_exited, E->value.rid, node, E->value.shapes[i].body_shape, E->value.shapes[i].local_shape);
  297. }
  298. contact_monitor->locked = false;
  299. }
  300. void RigidBody2D::_body_inout(int p_status, const RID &p_body, ObjectID p_instance, int p_body_shape, int p_local_shape) {
  301. bool body_in = p_status == 1;
  302. ObjectID objid = p_instance;
  303. Object *obj = ObjectDB::get_instance(objid);
  304. Node *node = Object::cast_to<Node>(obj);
  305. ERR_FAIL_COND(!contact_monitor);
  306. HashMap<ObjectID, BodyState>::Iterator E = contact_monitor->body_map.find(objid);
  307. ERR_FAIL_COND(!body_in && !E);
  308. if (body_in) {
  309. if (!E) {
  310. E = contact_monitor->body_map.insert(objid, BodyState());
  311. E->value.rid = p_body;
  312. //E->value.rc=0;
  313. E->value.in_scene = node && node->is_inside_tree();
  314. if (node) {
  315. node->connect(SceneStringNames::get_singleton()->tree_entered, callable_mp(this, &RigidBody2D::_body_enter_tree).bind(objid));
  316. node->connect(SceneStringNames::get_singleton()->tree_exiting, callable_mp(this, &RigidBody2D::_body_exit_tree).bind(objid));
  317. if (E->value.in_scene) {
  318. emit_signal(SceneStringNames::get_singleton()->body_entered, node);
  319. }
  320. }
  321. //E->value.rc++;
  322. }
  323. if (node) {
  324. E->value.shapes.insert(ShapePair(p_body_shape, p_local_shape));
  325. }
  326. if (E->value.in_scene) {
  327. emit_signal(SceneStringNames::get_singleton()->body_shape_entered, p_body, node, p_body_shape, p_local_shape);
  328. }
  329. } else {
  330. //E->value.rc--;
  331. if (node) {
  332. E->value.shapes.erase(ShapePair(p_body_shape, p_local_shape));
  333. }
  334. bool in_scene = E->value.in_scene;
  335. if (E->value.shapes.is_empty()) {
  336. if (node) {
  337. node->disconnect(SceneStringNames::get_singleton()->tree_entered, callable_mp(this, &RigidBody2D::_body_enter_tree));
  338. node->disconnect(SceneStringNames::get_singleton()->tree_exiting, callable_mp(this, &RigidBody2D::_body_exit_tree));
  339. if (in_scene) {
  340. emit_signal(SceneStringNames::get_singleton()->body_exited, node);
  341. }
  342. }
  343. contact_monitor->body_map.remove(E);
  344. }
  345. if (node && in_scene) {
  346. emit_signal(SceneStringNames::get_singleton()->body_shape_exited, p_body, node, p_body_shape, p_local_shape);
  347. }
  348. }
  349. }
  350. struct _RigidBody2DInOut {
  351. RID rid;
  352. ObjectID id;
  353. int shape = 0;
  354. int local_shape = 0;
  355. };
  356. void RigidBody2D::_body_state_changed_callback(void *p_instance, PhysicsDirectBodyState2D *p_state) {
  357. RigidBody2D *body = static_cast<RigidBody2D *>(p_instance);
  358. body->_body_state_changed(p_state);
  359. }
  360. void RigidBody2D::_body_state_changed(PhysicsDirectBodyState2D *p_state) {
  361. set_block_transform_notify(true); // don't want notify (would feedback loop)
  362. if (!freeze || freeze_mode != FREEZE_MODE_KINEMATIC) {
  363. set_global_transform(p_state->get_transform());
  364. }
  365. linear_velocity = p_state->get_linear_velocity();
  366. angular_velocity = p_state->get_angular_velocity();
  367. if (sleeping != p_state->is_sleeping()) {
  368. sleeping = p_state->is_sleeping();
  369. emit_signal(SceneStringNames::get_singleton()->sleeping_state_changed);
  370. }
  371. GDVIRTUAL_CALL(_integrate_forces, p_state);
  372. set_block_transform_notify(false); // want it back
  373. if (contact_monitor) {
  374. contact_monitor->locked = true;
  375. //untag all
  376. int rc = 0;
  377. for (KeyValue<ObjectID, BodyState> &E : contact_monitor->body_map) {
  378. for (int i = 0; i < E.value.shapes.size(); i++) {
  379. E.value.shapes[i].tagged = false;
  380. rc++;
  381. }
  382. }
  383. _RigidBody2DInOut *toadd = (_RigidBody2DInOut *)alloca(p_state->get_contact_count() * sizeof(_RigidBody2DInOut));
  384. int toadd_count = 0; //state->get_contact_count();
  385. RigidBody2D_RemoveAction *toremove = (RigidBody2D_RemoveAction *)alloca(rc * sizeof(RigidBody2D_RemoveAction));
  386. int toremove_count = 0;
  387. //put the ones to add
  388. for (int i = 0; i < p_state->get_contact_count(); i++) {
  389. RID rid = p_state->get_contact_collider(i);
  390. ObjectID obj = p_state->get_contact_collider_id(i);
  391. int local_shape = p_state->get_contact_local_shape(i);
  392. int shape = p_state->get_contact_collider_shape(i);
  393. HashMap<ObjectID, BodyState>::Iterator E = contact_monitor->body_map.find(obj);
  394. if (!E) {
  395. toadd[toadd_count].rid = rid;
  396. toadd[toadd_count].local_shape = local_shape;
  397. toadd[toadd_count].id = obj;
  398. toadd[toadd_count].shape = shape;
  399. toadd_count++;
  400. continue;
  401. }
  402. ShapePair sp(shape, local_shape);
  403. int idx = E->value.shapes.find(sp);
  404. if (idx == -1) {
  405. toadd[toadd_count].rid = rid;
  406. toadd[toadd_count].local_shape = local_shape;
  407. toadd[toadd_count].id = obj;
  408. toadd[toadd_count].shape = shape;
  409. toadd_count++;
  410. continue;
  411. }
  412. E->value.shapes[idx].tagged = true;
  413. }
  414. //put the ones to remove
  415. for (const KeyValue<ObjectID, BodyState> &E : contact_monitor->body_map) {
  416. for (int i = 0; i < E.value.shapes.size(); i++) {
  417. if (!E.value.shapes[i].tagged) {
  418. toremove[toremove_count].rid = E.value.rid;
  419. toremove[toremove_count].body_id = E.key;
  420. toremove[toremove_count].pair = E.value.shapes[i];
  421. toremove_count++;
  422. }
  423. }
  424. }
  425. //process removals
  426. for (int i = 0; i < toremove_count; i++) {
  427. _body_inout(0, toremove[i].rid, toremove[i].body_id, toremove[i].pair.body_shape, toremove[i].pair.local_shape);
  428. }
  429. //process additions
  430. for (int i = 0; i < toadd_count; i++) {
  431. _body_inout(1, toadd[i].rid, toadd[i].id, toadd[i].shape, toadd[i].local_shape);
  432. }
  433. contact_monitor->locked = false;
  434. }
  435. }
  436. void RigidBody2D::_apply_body_mode() {
  437. if (freeze) {
  438. switch (freeze_mode) {
  439. case FREEZE_MODE_STATIC: {
  440. set_body_mode(PhysicsServer2D::BODY_MODE_STATIC);
  441. } break;
  442. case FREEZE_MODE_KINEMATIC: {
  443. set_body_mode(PhysicsServer2D::BODY_MODE_KINEMATIC);
  444. } break;
  445. }
  446. } else if (lock_rotation) {
  447. set_body_mode(PhysicsServer2D::BODY_MODE_RIGID_LINEAR);
  448. } else {
  449. set_body_mode(PhysicsServer2D::BODY_MODE_RIGID);
  450. }
  451. }
  452. void RigidBody2D::set_lock_rotation_enabled(bool p_lock_rotation) {
  453. if (p_lock_rotation == lock_rotation) {
  454. return;
  455. }
  456. lock_rotation = p_lock_rotation;
  457. _apply_body_mode();
  458. }
  459. bool RigidBody2D::is_lock_rotation_enabled() const {
  460. return lock_rotation;
  461. }
  462. void RigidBody2D::set_freeze_enabled(bool p_freeze) {
  463. if (p_freeze == freeze) {
  464. return;
  465. }
  466. freeze = p_freeze;
  467. _apply_body_mode();
  468. }
  469. bool RigidBody2D::is_freeze_enabled() const {
  470. return freeze;
  471. }
  472. void RigidBody2D::set_freeze_mode(FreezeMode p_freeze_mode) {
  473. if (p_freeze_mode == freeze_mode) {
  474. return;
  475. }
  476. freeze_mode = p_freeze_mode;
  477. _apply_body_mode();
  478. }
  479. RigidBody2D::FreezeMode RigidBody2D::get_freeze_mode() const {
  480. return freeze_mode;
  481. }
  482. void RigidBody2D::set_mass(real_t p_mass) {
  483. ERR_FAIL_COND(p_mass <= 0);
  484. mass = p_mass;
  485. PhysicsServer2D::get_singleton()->body_set_param(get_rid(), PhysicsServer2D::BODY_PARAM_MASS, mass);
  486. }
  487. real_t RigidBody2D::get_mass() const {
  488. return mass;
  489. }
  490. void RigidBody2D::set_inertia(real_t p_inertia) {
  491. ERR_FAIL_COND(p_inertia < 0);
  492. inertia = p_inertia;
  493. PhysicsServer2D::get_singleton()->body_set_param(get_rid(), PhysicsServer2D::BODY_PARAM_INERTIA, inertia);
  494. }
  495. real_t RigidBody2D::get_inertia() const {
  496. return inertia;
  497. }
  498. void RigidBody2D::set_center_of_mass_mode(CenterOfMassMode p_mode) {
  499. if (center_of_mass_mode == p_mode) {
  500. return;
  501. }
  502. center_of_mass_mode = p_mode;
  503. switch (center_of_mass_mode) {
  504. case CENTER_OF_MASS_MODE_AUTO: {
  505. center_of_mass = Vector2();
  506. PhysicsServer2D::get_singleton()->body_reset_mass_properties(get_rid());
  507. if (inertia != 0.0) {
  508. PhysicsServer2D::get_singleton()->body_set_param(get_rid(), PhysicsServer2D::BODY_PARAM_INERTIA, inertia);
  509. }
  510. } break;
  511. case CENTER_OF_MASS_MODE_CUSTOM: {
  512. PhysicsServer2D::get_singleton()->body_set_param(get_rid(), PhysicsServer2D::BODY_PARAM_CENTER_OF_MASS, center_of_mass);
  513. } break;
  514. }
  515. }
  516. RigidBody2D::CenterOfMassMode RigidBody2D::get_center_of_mass_mode() const {
  517. return center_of_mass_mode;
  518. }
  519. void RigidBody2D::set_center_of_mass(const Vector2 &p_center_of_mass) {
  520. if (center_of_mass == p_center_of_mass) {
  521. return;
  522. }
  523. ERR_FAIL_COND(center_of_mass_mode != CENTER_OF_MASS_MODE_CUSTOM);
  524. center_of_mass = p_center_of_mass;
  525. PhysicsServer2D::get_singleton()->body_set_param(get_rid(), PhysicsServer2D::BODY_PARAM_CENTER_OF_MASS, center_of_mass);
  526. }
  527. const Vector2 &RigidBody2D::get_center_of_mass() const {
  528. return center_of_mass;
  529. }
  530. void RigidBody2D::set_physics_material_override(const Ref<PhysicsMaterial> &p_physics_material_override) {
  531. if (physics_material_override.is_valid()) {
  532. if (physics_material_override->is_connected(CoreStringNames::get_singleton()->changed, callable_mp(this, &RigidBody2D::_reload_physics_characteristics))) {
  533. physics_material_override->disconnect(CoreStringNames::get_singleton()->changed, callable_mp(this, &RigidBody2D::_reload_physics_characteristics));
  534. }
  535. }
  536. physics_material_override = p_physics_material_override;
  537. if (physics_material_override.is_valid()) {
  538. physics_material_override->connect(CoreStringNames::get_singleton()->changed, callable_mp(this, &RigidBody2D::_reload_physics_characteristics));
  539. }
  540. _reload_physics_characteristics();
  541. }
  542. Ref<PhysicsMaterial> RigidBody2D::get_physics_material_override() const {
  543. return physics_material_override;
  544. }
  545. void RigidBody2D::set_gravity_scale(real_t p_gravity_scale) {
  546. gravity_scale = p_gravity_scale;
  547. PhysicsServer2D::get_singleton()->body_set_param(get_rid(), PhysicsServer2D::BODY_PARAM_GRAVITY_SCALE, gravity_scale);
  548. }
  549. real_t RigidBody2D::get_gravity_scale() const {
  550. return gravity_scale;
  551. }
  552. void RigidBody2D::set_linear_damp_mode(DampMode p_mode) {
  553. linear_damp_mode = p_mode;
  554. PhysicsServer2D::get_singleton()->body_set_param(get_rid(), PhysicsServer2D::BODY_PARAM_LINEAR_DAMP_MODE, linear_damp_mode);
  555. }
  556. RigidBody2D::DampMode RigidBody2D::get_linear_damp_mode() const {
  557. return linear_damp_mode;
  558. }
  559. void RigidBody2D::set_angular_damp_mode(DampMode p_mode) {
  560. angular_damp_mode = p_mode;
  561. PhysicsServer2D::get_singleton()->body_set_param(get_rid(), PhysicsServer2D::BODY_PARAM_ANGULAR_DAMP_MODE, angular_damp_mode);
  562. }
  563. RigidBody2D::DampMode RigidBody2D::get_angular_damp_mode() const {
  564. return angular_damp_mode;
  565. }
  566. void RigidBody2D::set_linear_damp(real_t p_linear_damp) {
  567. ERR_FAIL_COND(p_linear_damp < -1);
  568. linear_damp = p_linear_damp;
  569. PhysicsServer2D::get_singleton()->body_set_param(get_rid(), PhysicsServer2D::BODY_PARAM_LINEAR_DAMP, linear_damp);
  570. }
  571. real_t RigidBody2D::get_linear_damp() const {
  572. return linear_damp;
  573. }
  574. void RigidBody2D::set_angular_damp(real_t p_angular_damp) {
  575. ERR_FAIL_COND(p_angular_damp < -1);
  576. angular_damp = p_angular_damp;
  577. PhysicsServer2D::get_singleton()->body_set_param(get_rid(), PhysicsServer2D::BODY_PARAM_ANGULAR_DAMP, angular_damp);
  578. }
  579. real_t RigidBody2D::get_angular_damp() const {
  580. return angular_damp;
  581. }
  582. void RigidBody2D::set_axis_velocity(const Vector2 &p_axis) {
  583. Vector2 axis = p_axis.normalized();
  584. linear_velocity -= axis * axis.dot(linear_velocity);
  585. linear_velocity += p_axis;
  586. PhysicsServer2D::get_singleton()->body_set_state(get_rid(), PhysicsServer2D::BODY_STATE_LINEAR_VELOCITY, linear_velocity);
  587. }
  588. void RigidBody2D::set_linear_velocity(const Vector2 &p_velocity) {
  589. linear_velocity = p_velocity;
  590. PhysicsServer2D::get_singleton()->body_set_state(get_rid(), PhysicsServer2D::BODY_STATE_LINEAR_VELOCITY, linear_velocity);
  591. }
  592. Vector2 RigidBody2D::get_linear_velocity() const {
  593. return linear_velocity;
  594. }
  595. void RigidBody2D::set_angular_velocity(real_t p_velocity) {
  596. angular_velocity = p_velocity;
  597. PhysicsServer2D::get_singleton()->body_set_state(get_rid(), PhysicsServer2D::BODY_STATE_ANGULAR_VELOCITY, angular_velocity);
  598. }
  599. real_t RigidBody2D::get_angular_velocity() const {
  600. return angular_velocity;
  601. }
  602. void RigidBody2D::set_use_custom_integrator(bool p_enable) {
  603. if (custom_integrator == p_enable) {
  604. return;
  605. }
  606. custom_integrator = p_enable;
  607. PhysicsServer2D::get_singleton()->body_set_omit_force_integration(get_rid(), p_enable);
  608. }
  609. bool RigidBody2D::is_using_custom_integrator() {
  610. return custom_integrator;
  611. }
  612. void RigidBody2D::set_sleeping(bool p_sleeping) {
  613. sleeping = p_sleeping;
  614. PhysicsServer2D::get_singleton()->body_set_state(get_rid(), PhysicsServer2D::BODY_STATE_SLEEPING, sleeping);
  615. }
  616. void RigidBody2D::set_can_sleep(bool p_active) {
  617. can_sleep = p_active;
  618. PhysicsServer2D::get_singleton()->body_set_state(get_rid(), PhysicsServer2D::BODY_STATE_CAN_SLEEP, p_active);
  619. }
  620. bool RigidBody2D::is_able_to_sleep() const {
  621. return can_sleep;
  622. }
  623. bool RigidBody2D::is_sleeping() const {
  624. return sleeping;
  625. }
  626. void RigidBody2D::set_max_contacts_reported(int p_amount) {
  627. max_contacts_reported = p_amount;
  628. PhysicsServer2D::get_singleton()->body_set_max_contacts_reported(get_rid(), p_amount);
  629. }
  630. int RigidBody2D::get_max_contacts_reported() const {
  631. return max_contacts_reported;
  632. }
  633. int RigidBody2D::get_contact_count() const {
  634. PhysicsDirectBodyState2D *bs = PhysicsServer2D::get_singleton()->body_get_direct_state(get_rid());
  635. ERR_FAIL_NULL_V(bs, 0);
  636. return bs->get_contact_count();
  637. }
  638. void RigidBody2D::apply_central_impulse(const Vector2 &p_impulse) {
  639. PhysicsServer2D::get_singleton()->body_apply_central_impulse(get_rid(), p_impulse);
  640. }
  641. void RigidBody2D::apply_impulse(const Vector2 &p_impulse, const Vector2 &p_position) {
  642. PhysicsServer2D::get_singleton()->body_apply_impulse(get_rid(), p_impulse, p_position);
  643. }
  644. void RigidBody2D::apply_torque_impulse(real_t p_torque) {
  645. PhysicsServer2D::get_singleton()->body_apply_torque_impulse(get_rid(), p_torque);
  646. }
  647. void RigidBody2D::apply_central_force(const Vector2 &p_force) {
  648. PhysicsServer2D::get_singleton()->body_apply_central_force(get_rid(), p_force);
  649. }
  650. void RigidBody2D::apply_force(const Vector2 &p_force, const Vector2 &p_position) {
  651. PhysicsServer2D::get_singleton()->body_apply_force(get_rid(), p_force, p_position);
  652. }
  653. void RigidBody2D::apply_torque(real_t p_torque) {
  654. PhysicsServer2D::get_singleton()->body_apply_torque(get_rid(), p_torque);
  655. }
  656. void RigidBody2D::add_constant_central_force(const Vector2 &p_force) {
  657. PhysicsServer2D::get_singleton()->body_add_constant_central_force(get_rid(), p_force);
  658. }
  659. void RigidBody2D::add_constant_force(const Vector2 &p_force, const Vector2 &p_position) {
  660. PhysicsServer2D::get_singleton()->body_add_constant_force(get_rid(), p_force, p_position);
  661. }
  662. void RigidBody2D::add_constant_torque(const real_t p_torque) {
  663. PhysicsServer2D::get_singleton()->body_add_constant_torque(get_rid(), p_torque);
  664. }
  665. void RigidBody2D::set_constant_force(const Vector2 &p_force) {
  666. PhysicsServer2D::get_singleton()->body_set_constant_force(get_rid(), p_force);
  667. }
  668. Vector2 RigidBody2D::get_constant_force() const {
  669. return PhysicsServer2D::get_singleton()->body_get_constant_force(get_rid());
  670. }
  671. void RigidBody2D::set_constant_torque(real_t p_torque) {
  672. PhysicsServer2D::get_singleton()->body_set_constant_torque(get_rid(), p_torque);
  673. }
  674. real_t RigidBody2D::get_constant_torque() const {
  675. return PhysicsServer2D::get_singleton()->body_get_constant_torque(get_rid());
  676. }
  677. void RigidBody2D::set_continuous_collision_detection_mode(CCDMode p_mode) {
  678. ccd_mode = p_mode;
  679. PhysicsServer2D::get_singleton()->body_set_continuous_collision_detection_mode(get_rid(), PhysicsServer2D::CCDMode(p_mode));
  680. }
  681. RigidBody2D::CCDMode RigidBody2D::get_continuous_collision_detection_mode() const {
  682. return ccd_mode;
  683. }
  684. TypedArray<Node2D> RigidBody2D::get_colliding_bodies() const {
  685. ERR_FAIL_COND_V(!contact_monitor, TypedArray<Node2D>());
  686. TypedArray<Node2D> ret;
  687. ret.resize(contact_monitor->body_map.size());
  688. int idx = 0;
  689. for (const KeyValue<ObjectID, BodyState> &E : contact_monitor->body_map) {
  690. Object *obj = ObjectDB::get_instance(E.key);
  691. if (!obj) {
  692. ret.resize(ret.size() - 1); //ops
  693. } else {
  694. ret[idx++] = obj;
  695. }
  696. }
  697. return ret;
  698. }
  699. void RigidBody2D::set_contact_monitor(bool p_enabled) {
  700. if (p_enabled == is_contact_monitor_enabled()) {
  701. return;
  702. }
  703. if (!p_enabled) {
  704. ERR_FAIL_COND_MSG(contact_monitor->locked, "Can't disable contact monitoring during in/out callback. Use call_deferred(\"set_contact_monitor\", false) instead.");
  705. for (const KeyValue<ObjectID, BodyState> &E : contact_monitor->body_map) {
  706. //clean up mess
  707. Object *obj = ObjectDB::get_instance(E.key);
  708. Node *node = Object::cast_to<Node>(obj);
  709. if (node) {
  710. node->disconnect(SceneStringNames::get_singleton()->tree_entered, callable_mp(this, &RigidBody2D::_body_enter_tree));
  711. node->disconnect(SceneStringNames::get_singleton()->tree_exiting, callable_mp(this, &RigidBody2D::_body_exit_tree));
  712. }
  713. }
  714. memdelete(contact_monitor);
  715. contact_monitor = nullptr;
  716. } else {
  717. contact_monitor = memnew(ContactMonitor);
  718. contact_monitor->locked = false;
  719. }
  720. }
  721. bool RigidBody2D::is_contact_monitor_enabled() const {
  722. return contact_monitor != nullptr;
  723. }
  724. void RigidBody2D::_notification(int p_what) {
  725. #ifdef TOOLS_ENABLED
  726. switch (p_what) {
  727. case NOTIFICATION_ENTER_TREE: {
  728. if (Engine::get_singleton()->is_editor_hint()) {
  729. set_notify_local_transform(true); // Used for warnings and only in editor.
  730. }
  731. } break;
  732. case NOTIFICATION_LOCAL_TRANSFORM_CHANGED: {
  733. if (Engine::get_singleton()->is_editor_hint()) {
  734. update_configuration_warnings();
  735. }
  736. } break;
  737. }
  738. #endif
  739. }
  740. TypedArray<String> RigidBody2D::get_configuration_warnings() const {
  741. Transform2D t = get_transform();
  742. TypedArray<String> warnings = CollisionObject2D::get_configuration_warnings();
  743. if (ABS(t.columns[0].length() - 1.0) > 0.05 || ABS(t.columns[1].length() - 1.0) > 0.05) {
  744. 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."));
  745. }
  746. return warnings;
  747. }
  748. void RigidBody2D::_bind_methods() {
  749. ClassDB::bind_method(D_METHOD("set_mass", "mass"), &RigidBody2D::set_mass);
  750. ClassDB::bind_method(D_METHOD("get_mass"), &RigidBody2D::get_mass);
  751. ClassDB::bind_method(D_METHOD("get_inertia"), &RigidBody2D::get_inertia);
  752. ClassDB::bind_method(D_METHOD("set_inertia", "inertia"), &RigidBody2D::set_inertia);
  753. ClassDB::bind_method(D_METHOD("set_center_of_mass_mode", "mode"), &RigidBody2D::set_center_of_mass_mode);
  754. ClassDB::bind_method(D_METHOD("get_center_of_mass_mode"), &RigidBody2D::get_center_of_mass_mode);
  755. ClassDB::bind_method(D_METHOD("set_center_of_mass", "center_of_mass"), &RigidBody2D::set_center_of_mass);
  756. ClassDB::bind_method(D_METHOD("get_center_of_mass"), &RigidBody2D::get_center_of_mass);
  757. ClassDB::bind_method(D_METHOD("set_physics_material_override", "physics_material_override"), &RigidBody2D::set_physics_material_override);
  758. ClassDB::bind_method(D_METHOD("get_physics_material_override"), &RigidBody2D::get_physics_material_override);
  759. ClassDB::bind_method(D_METHOD("set_gravity_scale", "gravity_scale"), &RigidBody2D::set_gravity_scale);
  760. ClassDB::bind_method(D_METHOD("get_gravity_scale"), &RigidBody2D::get_gravity_scale);
  761. ClassDB::bind_method(D_METHOD("set_linear_damp_mode", "linear_damp_mode"), &RigidBody2D::set_linear_damp_mode);
  762. ClassDB::bind_method(D_METHOD("get_linear_damp_mode"), &RigidBody2D::get_linear_damp_mode);
  763. ClassDB::bind_method(D_METHOD("set_angular_damp_mode", "angular_damp_mode"), &RigidBody2D::set_angular_damp_mode);
  764. ClassDB::bind_method(D_METHOD("get_angular_damp_mode"), &RigidBody2D::get_angular_damp_mode);
  765. ClassDB::bind_method(D_METHOD("set_linear_damp", "linear_damp"), &RigidBody2D::set_linear_damp);
  766. ClassDB::bind_method(D_METHOD("get_linear_damp"), &RigidBody2D::get_linear_damp);
  767. ClassDB::bind_method(D_METHOD("set_angular_damp", "angular_damp"), &RigidBody2D::set_angular_damp);
  768. ClassDB::bind_method(D_METHOD("get_angular_damp"), &RigidBody2D::get_angular_damp);
  769. ClassDB::bind_method(D_METHOD("set_linear_velocity", "linear_velocity"), &RigidBody2D::set_linear_velocity);
  770. ClassDB::bind_method(D_METHOD("get_linear_velocity"), &RigidBody2D::get_linear_velocity);
  771. ClassDB::bind_method(D_METHOD("set_angular_velocity", "angular_velocity"), &RigidBody2D::set_angular_velocity);
  772. ClassDB::bind_method(D_METHOD("get_angular_velocity"), &RigidBody2D::get_angular_velocity);
  773. ClassDB::bind_method(D_METHOD("set_max_contacts_reported", "amount"), &RigidBody2D::set_max_contacts_reported);
  774. ClassDB::bind_method(D_METHOD("get_max_contacts_reported"), &RigidBody2D::get_max_contacts_reported);
  775. ClassDB::bind_method(D_METHOD("get_contact_count"), &RigidBody2D::get_contact_count);
  776. ClassDB::bind_method(D_METHOD("set_use_custom_integrator", "enable"), &RigidBody2D::set_use_custom_integrator);
  777. ClassDB::bind_method(D_METHOD("is_using_custom_integrator"), &RigidBody2D::is_using_custom_integrator);
  778. ClassDB::bind_method(D_METHOD("set_contact_monitor", "enabled"), &RigidBody2D::set_contact_monitor);
  779. ClassDB::bind_method(D_METHOD("is_contact_monitor_enabled"), &RigidBody2D::is_contact_monitor_enabled);
  780. ClassDB::bind_method(D_METHOD("set_continuous_collision_detection_mode", "mode"), &RigidBody2D::set_continuous_collision_detection_mode);
  781. ClassDB::bind_method(D_METHOD("get_continuous_collision_detection_mode"), &RigidBody2D::get_continuous_collision_detection_mode);
  782. ClassDB::bind_method(D_METHOD("set_axis_velocity", "axis_velocity"), &RigidBody2D::set_axis_velocity);
  783. ClassDB::bind_method(D_METHOD("apply_central_impulse", "impulse"), &RigidBody2D::apply_central_impulse, Vector2());
  784. ClassDB::bind_method(D_METHOD("apply_impulse", "impulse", "position"), &RigidBody2D::apply_impulse, Vector2());
  785. ClassDB::bind_method(D_METHOD("apply_torque_impulse", "torque"), &RigidBody2D::apply_torque_impulse);
  786. ClassDB::bind_method(D_METHOD("apply_central_force", "force"), &RigidBody2D::apply_central_force);
  787. ClassDB::bind_method(D_METHOD("apply_force", "force", "position"), &RigidBody2D::apply_force, Vector2());
  788. ClassDB::bind_method(D_METHOD("apply_torque", "torque"), &RigidBody2D::apply_torque);
  789. ClassDB::bind_method(D_METHOD("add_constant_central_force", "force"), &RigidBody2D::add_constant_central_force);
  790. ClassDB::bind_method(D_METHOD("add_constant_force", "force", "position"), &RigidBody2D::add_constant_force, Vector2());
  791. ClassDB::bind_method(D_METHOD("add_constant_torque", "torque"), &RigidBody2D::add_constant_torque);
  792. ClassDB::bind_method(D_METHOD("set_constant_force", "force"), &RigidBody2D::set_constant_force);
  793. ClassDB::bind_method(D_METHOD("get_constant_force"), &RigidBody2D::get_constant_force);
  794. ClassDB::bind_method(D_METHOD("set_constant_torque", "torque"), &RigidBody2D::set_constant_torque);
  795. ClassDB::bind_method(D_METHOD("get_constant_torque"), &RigidBody2D::get_constant_torque);
  796. ClassDB::bind_method(D_METHOD("set_sleeping", "sleeping"), &RigidBody2D::set_sleeping);
  797. ClassDB::bind_method(D_METHOD("is_sleeping"), &RigidBody2D::is_sleeping);
  798. ClassDB::bind_method(D_METHOD("set_can_sleep", "able_to_sleep"), &RigidBody2D::set_can_sleep);
  799. ClassDB::bind_method(D_METHOD("is_able_to_sleep"), &RigidBody2D::is_able_to_sleep);
  800. ClassDB::bind_method(D_METHOD("set_lock_rotation_enabled", "lock_rotation"), &RigidBody2D::set_lock_rotation_enabled);
  801. ClassDB::bind_method(D_METHOD("is_lock_rotation_enabled"), &RigidBody2D::is_lock_rotation_enabled);
  802. ClassDB::bind_method(D_METHOD("set_freeze_enabled", "freeze_mode"), &RigidBody2D::set_freeze_enabled);
  803. ClassDB::bind_method(D_METHOD("is_freeze_enabled"), &RigidBody2D::is_freeze_enabled);
  804. ClassDB::bind_method(D_METHOD("set_freeze_mode", "freeze_mode"), &RigidBody2D::set_freeze_mode);
  805. ClassDB::bind_method(D_METHOD("get_freeze_mode"), &RigidBody2D::get_freeze_mode);
  806. ClassDB::bind_method(D_METHOD("get_colliding_bodies"), &RigidBody2D::get_colliding_bodies);
  807. GDVIRTUAL_BIND(_integrate_forces, "state");
  808. ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "mass", PROPERTY_HINT_RANGE, "0.01,1000,0.01,or_greater,exp,suffix:kg"), "set_mass", "get_mass");
  809. 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");
  810. ADD_PROPERTY(PropertyInfo(Variant::INT, "center_of_mass_mode", PROPERTY_HINT_ENUM, "Auto,Custom", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), "set_center_of_mass_mode", "get_center_of_mass_mode");
  811. ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "center_of_mass", PROPERTY_HINT_RANGE, "-10,10,0.01,or_lesser,or_greater,suffix:px"), "set_center_of_mass", "get_center_of_mass");
  812. ADD_LINKED_PROPERTY("center_of_mass_mode", "center_of_mass");
  813. ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "physics_material_override", PROPERTY_HINT_RESOURCE_TYPE, "PhysicsMaterial"), "set_physics_material_override", "get_physics_material_override");
  814. ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "gravity_scale", PROPERTY_HINT_RANGE, "-128,128,0.01"), "set_gravity_scale", "get_gravity_scale");
  815. ADD_PROPERTY(PropertyInfo(Variant::BOOL, "custom_integrator"), "set_use_custom_integrator", "is_using_custom_integrator");
  816. 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");
  817. ADD_PROPERTY(PropertyInfo(Variant::INT, "max_contacts_reported", PROPERTY_HINT_RANGE, "0,64,1,or_greater"), "set_max_contacts_reported", "get_max_contacts_reported");
  818. ADD_PROPERTY(PropertyInfo(Variant::BOOL, "contact_monitor"), "set_contact_monitor", "is_contact_monitor_enabled");
  819. ADD_PROPERTY(PropertyInfo(Variant::BOOL, "sleeping"), "set_sleeping", "is_sleeping");
  820. ADD_PROPERTY(PropertyInfo(Variant::BOOL, "can_sleep"), "set_can_sleep", "is_able_to_sleep");
  821. ADD_PROPERTY(PropertyInfo(Variant::BOOL, "lock_rotation"), "set_lock_rotation_enabled", "is_lock_rotation_enabled");
  822. ADD_PROPERTY(PropertyInfo(Variant::BOOL, "freeze"), "set_freeze_enabled", "is_freeze_enabled");
  823. ADD_PROPERTY(PropertyInfo(Variant::INT, "freeze_mode", PROPERTY_HINT_ENUM, "Static,Kinematic"), "set_freeze_mode", "get_freeze_mode");
  824. ADD_GROUP("Linear", "linear_");
  825. ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "linear_velocity", PROPERTY_HINT_NONE, "suffix:px/s"), "set_linear_velocity", "get_linear_velocity");
  826. ADD_PROPERTY(PropertyInfo(Variant::INT, "linear_damp_mode", PROPERTY_HINT_ENUM, "Combine,Replace"), "set_linear_damp_mode", "get_linear_damp_mode");
  827. ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "linear_damp", PROPERTY_HINT_RANGE, "-1,100,0.001,or_greater"), "set_linear_damp", "get_linear_damp");
  828. ADD_GROUP("Angular", "angular_");
  829. ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "angular_velocity", PROPERTY_HINT_NONE, "suffix:rad/s"), "set_angular_velocity", "get_angular_velocity");
  830. ADD_PROPERTY(PropertyInfo(Variant::INT, "angular_damp_mode", PROPERTY_HINT_ENUM, "Combine,Replace"), "set_angular_damp_mode", "get_angular_damp_mode");
  831. ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "angular_damp", PROPERTY_HINT_RANGE, "-1,100,0.001,or_greater"), "set_angular_damp", "get_angular_damp");
  832. ADD_GROUP("Constant Forces", "constant_");
  833. ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "constant_force", PROPERTY_HINT_NONE, U"suffix:kg\u22C5px/s\u00B2"), "set_constant_force", "get_constant_force");
  834. ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "constant_torque", PROPERTY_HINT_NONE, U"suffix:kg\u22C5px\u00B2/s\u00B2/rad"), "set_constant_torque", "get_constant_torque");
  835. 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")));
  836. 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")));
  837. ADD_SIGNAL(MethodInfo("body_entered", PropertyInfo(Variant::OBJECT, "body", PROPERTY_HINT_RESOURCE_TYPE, "Node")));
  838. ADD_SIGNAL(MethodInfo("body_exited", PropertyInfo(Variant::OBJECT, "body", PROPERTY_HINT_RESOURCE_TYPE, "Node")));
  839. ADD_SIGNAL(MethodInfo("sleeping_state_changed"));
  840. BIND_ENUM_CONSTANT(FREEZE_MODE_STATIC);
  841. BIND_ENUM_CONSTANT(FREEZE_MODE_KINEMATIC);
  842. BIND_ENUM_CONSTANT(CENTER_OF_MASS_MODE_AUTO);
  843. BIND_ENUM_CONSTANT(CENTER_OF_MASS_MODE_CUSTOM);
  844. BIND_ENUM_CONSTANT(DAMP_MODE_COMBINE);
  845. BIND_ENUM_CONSTANT(DAMP_MODE_REPLACE);
  846. BIND_ENUM_CONSTANT(CCD_MODE_DISABLED);
  847. BIND_ENUM_CONSTANT(CCD_MODE_CAST_RAY);
  848. BIND_ENUM_CONSTANT(CCD_MODE_CAST_SHAPE);
  849. }
  850. void RigidBody2D::_validate_property(PropertyInfo &p_property) const {
  851. if (center_of_mass_mode != CENTER_OF_MASS_MODE_CUSTOM) {
  852. if (p_property.name == "center_of_mass") {
  853. p_property.usage = PROPERTY_USAGE_NO_EDITOR;
  854. }
  855. }
  856. }
  857. RigidBody2D::RigidBody2D() :
  858. PhysicsBody2D(PhysicsServer2D::BODY_MODE_RIGID) {
  859. PhysicsServer2D::get_singleton()->body_set_state_sync_callback(get_rid(), this, _body_state_changed_callback);
  860. }
  861. RigidBody2D::~RigidBody2D() {
  862. if (contact_monitor) {
  863. memdelete(contact_monitor);
  864. }
  865. }
  866. void RigidBody2D::_reload_physics_characteristics() {
  867. if (physics_material_override.is_null()) {
  868. PhysicsServer2D::get_singleton()->body_set_param(get_rid(), PhysicsServer2D::BODY_PARAM_BOUNCE, 0);
  869. PhysicsServer2D::get_singleton()->body_set_param(get_rid(), PhysicsServer2D::BODY_PARAM_FRICTION, 1);
  870. } else {
  871. PhysicsServer2D::get_singleton()->body_set_param(get_rid(), PhysicsServer2D::BODY_PARAM_BOUNCE, physics_material_override->computed_bounce());
  872. PhysicsServer2D::get_singleton()->body_set_param(get_rid(), PhysicsServer2D::BODY_PARAM_FRICTION, physics_material_override->computed_friction());
  873. }
  874. }
  875. //////////////////////////
  876. // So, if you pass 45 as limit, avoid numerical precision errors when angle is 45.
  877. #define FLOOR_ANGLE_THRESHOLD 0.01
  878. bool CharacterBody2D::move_and_slide() {
  879. // Hack in order to work with calling from _process as well as from _physics_process; calling from thread is risky.
  880. double delta = Engine::get_singleton()->is_in_physics_frame() ? get_physics_process_delta_time() : get_process_delta_time();
  881. Vector2 current_platform_velocity = platform_velocity;
  882. Transform2D gt = get_global_transform();
  883. previous_position = gt.columns[2];
  884. if ((on_floor || on_wall) && platform_rid.is_valid()) {
  885. bool excluded = false;
  886. if (on_floor) {
  887. excluded = (platform_floor_layers & platform_layer) == 0;
  888. } else if (on_wall) {
  889. excluded = (platform_wall_layers & platform_layer) == 0;
  890. }
  891. if (!excluded) {
  892. //this approach makes sure there is less delay between the actual body velocity and the one we saved
  893. PhysicsDirectBodyState2D *bs = PhysicsServer2D::get_singleton()->body_get_direct_state(platform_rid);
  894. if (bs) {
  895. Vector2 local_position = gt.columns[2] - bs->get_transform().columns[2];
  896. current_platform_velocity = bs->get_velocity_at_local_position(local_position);
  897. } else {
  898. // Body is removed or destroyed, invalidate floor.
  899. current_platform_velocity = Vector2();
  900. platform_rid = RID();
  901. }
  902. } else {
  903. current_platform_velocity = Vector2();
  904. }
  905. }
  906. motion_results.clear();
  907. last_motion = Vector2();
  908. bool was_on_floor = on_floor;
  909. on_floor = false;
  910. on_ceiling = false;
  911. on_wall = false;
  912. if (!current_platform_velocity.is_equal_approx(Vector2())) {
  913. PhysicsServer2D::MotionParameters parameters(get_global_transform(), current_platform_velocity * delta, margin);
  914. parameters.recovery_as_collision = true; // Also report collisions generated only from recovery.
  915. parameters.exclude_bodies.insert(platform_rid);
  916. if (platform_object_id.is_valid()) {
  917. parameters.exclude_objects.insert(platform_object_id);
  918. }
  919. PhysicsServer2D::MotionResult floor_result;
  920. if (move_and_collide(parameters, floor_result, false, false)) {
  921. motion_results.push_back(floor_result);
  922. _set_collision_direction(floor_result);
  923. }
  924. }
  925. if (motion_mode == MOTION_MODE_GROUNDED) {
  926. _move_and_slide_grounded(delta, was_on_floor);
  927. } else {
  928. _move_and_slide_floating(delta);
  929. }
  930. // Compute real velocity.
  931. real_velocity = get_position_delta() / delta;
  932. if (platform_on_leave != PLATFORM_ON_LEAVE_DO_NOTHING) {
  933. // Add last platform velocity when just left a moving platform.
  934. if (!on_floor && !on_wall) {
  935. if (platform_on_leave == PLATFORM_ON_LEAVE_ADD_UPWARD_VELOCITY && current_platform_velocity.dot(up_direction) < 0) {
  936. current_platform_velocity = current_platform_velocity.slide(up_direction);
  937. }
  938. velocity += current_platform_velocity;
  939. }
  940. }
  941. return motion_results.size() > 0;
  942. }
  943. void CharacterBody2D::_move_and_slide_grounded(double p_delta, bool p_was_on_floor) {
  944. Vector2 motion = velocity * p_delta;
  945. Vector2 motion_slide_up = motion.slide(up_direction);
  946. Vector2 prev_floor_normal = floor_normal;
  947. platform_rid = RID();
  948. platform_object_id = ObjectID();
  949. floor_normal = Vector2();
  950. platform_velocity = Vector2();
  951. // No sliding on first attempt to keep floor motion stable when possible,
  952. // When stop on slope is enabled or when there is no up direction.
  953. bool sliding_enabled = !floor_stop_on_slope;
  954. // Constant speed can be applied only the first time sliding is enabled.
  955. bool can_apply_constant_speed = sliding_enabled;
  956. // If the platform's ceiling push down the body.
  957. bool apply_ceiling_velocity = false;
  958. bool first_slide = true;
  959. bool vel_dir_facing_up = velocity.dot(up_direction) > 0;
  960. Vector2 last_travel;
  961. for (int iteration = 0; iteration < max_slides; ++iteration) {
  962. PhysicsServer2D::MotionParameters parameters(get_global_transform(), motion, margin);
  963. parameters.recovery_as_collision = true; // Also report collisions generated only from recovery.
  964. Vector2 prev_position = parameters.from.columns[2];
  965. PhysicsServer2D::MotionResult result;
  966. bool collided = move_and_collide(parameters, result, false, !sliding_enabled);
  967. last_motion = result.travel;
  968. if (collided) {
  969. motion_results.push_back(result);
  970. _set_collision_direction(result);
  971. // If we hit a ceiling platform, we set the vertical velocity to at least the platform one.
  972. if (on_ceiling && result.collider_velocity != Vector2() && result.collider_velocity.dot(up_direction) < 0) {
  973. // If ceiling sliding is on, only apply when the ceiling is flat or when the motion is upward.
  974. if (!slide_on_ceiling || motion.dot(up_direction) < 0 || (result.collision_normal + up_direction).length() < 0.01) {
  975. apply_ceiling_velocity = true;
  976. Vector2 ceiling_vertical_velocity = up_direction * up_direction.dot(result.collider_velocity);
  977. Vector2 motion_vertical_velocity = up_direction * up_direction.dot(velocity);
  978. if (motion_vertical_velocity.dot(up_direction) > 0 || ceiling_vertical_velocity.length_squared() > motion_vertical_velocity.length_squared()) {
  979. velocity = ceiling_vertical_velocity + velocity.slide(up_direction);
  980. }
  981. }
  982. }
  983. if (on_floor && floor_stop_on_slope && (velocity.normalized() + up_direction).length() < 0.01) {
  984. Transform2D gt = get_global_transform();
  985. if (result.travel.length() <= margin + CMP_EPSILON) {
  986. gt.columns[2] -= result.travel;
  987. }
  988. set_global_transform(gt);
  989. velocity = Vector2();
  990. last_motion = Vector2();
  991. motion = Vector2();
  992. break;
  993. }
  994. if (result.remainder.is_equal_approx(Vector2())) {
  995. motion = Vector2();
  996. break;
  997. }
  998. // Move on floor only checks.
  999. if (floor_block_on_wall && on_wall && motion_slide_up.dot(result.collision_normal) <= 0) {
  1000. // Avoid to move forward on a wall if floor_block_on_wall is true.
  1001. if (p_was_on_floor && !on_floor && !vel_dir_facing_up) {
  1002. // If the movement is large the body can be prevented from reaching the walls.
  1003. if (result.travel.length() <= margin + CMP_EPSILON) {
  1004. // Cancels the motion.
  1005. Transform2D gt = get_global_transform();
  1006. gt.columns[2] -= result.travel;
  1007. set_global_transform(gt);
  1008. }
  1009. // Determines if you are on the ground.
  1010. _snap_on_floor(true, false, true);
  1011. velocity = Vector2();
  1012. last_motion = Vector2();
  1013. motion = Vector2();
  1014. break;
  1015. }
  1016. // Prevents the body from being able to climb a slope when it moves forward against the wall.
  1017. else if (!on_floor) {
  1018. motion = up_direction * up_direction.dot(result.remainder);
  1019. motion = motion.slide(result.collision_normal);
  1020. } else {
  1021. motion = result.remainder;
  1022. }
  1023. }
  1024. // Constant Speed when the slope is upward.
  1025. else if (floor_constant_speed && is_on_floor_only() && can_apply_constant_speed && p_was_on_floor && motion.dot(result.collision_normal) < 0) {
  1026. can_apply_constant_speed = false;
  1027. Vector2 motion_slide_norm = result.remainder.slide(result.collision_normal).normalized();
  1028. motion = motion_slide_norm * (motion_slide_up.length() - result.travel.slide(up_direction).length() - last_travel.slide(up_direction).length());
  1029. }
  1030. // Regular sliding, the last part of the test handle the case when you don't want to slide on the ceiling.
  1031. else if ((sliding_enabled || !on_floor) && (!on_ceiling || slide_on_ceiling || !vel_dir_facing_up) && !apply_ceiling_velocity) {
  1032. Vector2 slide_motion = result.remainder.slide(result.collision_normal);
  1033. if (slide_motion.dot(velocity) > 0.0) {
  1034. motion = slide_motion;
  1035. } else {
  1036. motion = Vector2();
  1037. }
  1038. if (slide_on_ceiling && on_ceiling) {
  1039. // Apply slide only in the direction of the input motion, otherwise just stop to avoid jittering when moving against a wall.
  1040. if (vel_dir_facing_up) {
  1041. velocity = velocity.slide(result.collision_normal);
  1042. } else {
  1043. // Avoid acceleration in slope when falling.
  1044. velocity = up_direction * up_direction.dot(velocity);
  1045. }
  1046. }
  1047. }
  1048. // No sliding on first attempt to keep floor motion stable when possible.
  1049. else {
  1050. motion = result.remainder;
  1051. if (on_ceiling && !slide_on_ceiling && vel_dir_facing_up) {
  1052. velocity = velocity.slide(up_direction);
  1053. motion = motion.slide(up_direction);
  1054. }
  1055. }
  1056. last_travel = result.travel;
  1057. }
  1058. // When you move forward in a downward slope you don’t collide because you will be in the air.
  1059. // This test ensures that constant speed is applied, only if the player is still on the ground after the snap is applied.
  1060. else if (floor_constant_speed && first_slide && _on_floor_if_snapped(p_was_on_floor, vel_dir_facing_up)) {
  1061. can_apply_constant_speed = false;
  1062. sliding_enabled = true;
  1063. Transform2D gt = get_global_transform();
  1064. gt.columns[2] = prev_position;
  1065. set_global_transform(gt);
  1066. Vector2 motion_slide_norm = motion.slide(prev_floor_normal).normalized();
  1067. motion = motion_slide_norm * (motion_slide_up.length());
  1068. collided = true;
  1069. }
  1070. can_apply_constant_speed = !can_apply_constant_speed && !sliding_enabled;
  1071. sliding_enabled = true;
  1072. first_slide = false;
  1073. if (!collided || motion.is_equal_approx(Vector2())) {
  1074. break;
  1075. }
  1076. }
  1077. _snap_on_floor(p_was_on_floor, vel_dir_facing_up);
  1078. // Scales the horizontal velocity according to the wall slope.
  1079. if (is_on_wall_only() && motion_slide_up.dot(motion_results.get(0).collision_normal) < 0) {
  1080. Vector2 slide_motion = velocity.slide(motion_results.get(0).collision_normal);
  1081. if (motion_slide_up.dot(slide_motion) < 0) {
  1082. velocity = up_direction * up_direction.dot(velocity);
  1083. } else {
  1084. // Keeps the vertical motion from velocity and add the horizontal motion of the projection.
  1085. velocity = up_direction * up_direction.dot(velocity) + slide_motion.slide(up_direction);
  1086. }
  1087. }
  1088. // Reset the gravity accumulation when touching the ground.
  1089. if (on_floor && !vel_dir_facing_up) {
  1090. velocity = velocity.slide(up_direction);
  1091. }
  1092. }
  1093. void CharacterBody2D::_move_and_slide_floating(double p_delta) {
  1094. Vector2 motion = velocity * p_delta;
  1095. platform_rid = RID();
  1096. platform_object_id = ObjectID();
  1097. floor_normal = Vector2();
  1098. platform_velocity = Vector2();
  1099. bool first_slide = true;
  1100. for (int iteration = 0; iteration < max_slides; ++iteration) {
  1101. PhysicsServer2D::MotionParameters parameters(get_global_transform(), motion, margin);
  1102. parameters.recovery_as_collision = true; // Also report collisions generated only from recovery.
  1103. PhysicsServer2D::MotionResult result;
  1104. bool collided = move_and_collide(parameters, result, false, false);
  1105. last_motion = result.travel;
  1106. if (collided) {
  1107. motion_results.push_back(result);
  1108. _set_collision_direction(result);
  1109. if (result.remainder.is_equal_approx(Vector2())) {
  1110. motion = Vector2();
  1111. break;
  1112. }
  1113. if (wall_min_slide_angle != 0 && result.get_angle(-velocity.normalized()) < wall_min_slide_angle + FLOOR_ANGLE_THRESHOLD) {
  1114. motion = Vector2();
  1115. } else if (first_slide) {
  1116. Vector2 motion_slide_norm = result.remainder.slide(result.collision_normal).normalized();
  1117. motion = motion_slide_norm * (motion.length() - result.travel.length());
  1118. } else {
  1119. motion = result.remainder.slide(result.collision_normal);
  1120. }
  1121. if (motion.dot(velocity) <= 0.0) {
  1122. motion = Vector2();
  1123. }
  1124. }
  1125. if (!collided || motion.is_equal_approx(Vector2())) {
  1126. break;
  1127. }
  1128. first_slide = false;
  1129. }
  1130. }
  1131. void CharacterBody2D::_snap_on_floor(bool p_was_on_floor, bool p_vel_dir_facing_up, bool p_wall_as_floor) {
  1132. if (on_floor || !p_was_on_floor || p_vel_dir_facing_up) {
  1133. return;
  1134. }
  1135. // Snap by at least collision margin to keep floor state consistent.
  1136. real_t length = MAX(floor_snap_length, margin);
  1137. PhysicsServer2D::MotionParameters parameters(get_global_transform(), -up_direction * length, margin);
  1138. parameters.recovery_as_collision = true; // Also report collisions generated only from recovery.
  1139. parameters.collide_separation_ray = true;
  1140. PhysicsServer2D::MotionResult result;
  1141. if (move_and_collide(parameters, result, true, false)) {
  1142. if ((result.get_angle(up_direction) <= floor_max_angle + FLOOR_ANGLE_THRESHOLD) ||
  1143. (p_wall_as_floor && result.get_angle(-up_direction) > floor_max_angle + FLOOR_ANGLE_THRESHOLD)) {
  1144. on_floor = true;
  1145. floor_normal = result.collision_normal;
  1146. _set_platform_data(result);
  1147. if (floor_stop_on_slope) {
  1148. // move and collide may stray the object a bit because of pre un-stucking,
  1149. // so only ensure that motion happens on floor direction in this case.
  1150. if (result.travel.length() > margin) {
  1151. result.travel = up_direction * up_direction.dot(result.travel);
  1152. } else {
  1153. result.travel = Vector2();
  1154. }
  1155. }
  1156. parameters.from.columns[2] += result.travel;
  1157. set_global_transform(parameters.from);
  1158. }
  1159. }
  1160. }
  1161. bool CharacterBody2D::_on_floor_if_snapped(bool p_was_on_floor, bool p_vel_dir_facing_up) {
  1162. if (up_direction == Vector2() || on_floor || !p_was_on_floor || p_vel_dir_facing_up) {
  1163. return false;
  1164. }
  1165. // Snap by at least collision margin to keep floor state consistent.
  1166. real_t length = MAX(floor_snap_length, margin);
  1167. PhysicsServer2D::MotionParameters parameters(get_global_transform(), -up_direction * length, margin);
  1168. parameters.recovery_as_collision = true; // Also report collisions generated only from recovery.
  1169. parameters.collide_separation_ray = true;
  1170. PhysicsServer2D::MotionResult result;
  1171. if (move_and_collide(parameters, result, true, false)) {
  1172. if (result.get_angle(up_direction) <= floor_max_angle + FLOOR_ANGLE_THRESHOLD) {
  1173. return true;
  1174. }
  1175. }
  1176. return false;
  1177. }
  1178. void CharacterBody2D::_set_collision_direction(const PhysicsServer2D::MotionResult &p_result) {
  1179. if (motion_mode == MOTION_MODE_GROUNDED && p_result.get_angle(up_direction) <= floor_max_angle + FLOOR_ANGLE_THRESHOLD) { //floor
  1180. on_floor = true;
  1181. floor_normal = p_result.collision_normal;
  1182. _set_platform_data(p_result);
  1183. } else if (motion_mode == MOTION_MODE_GROUNDED && p_result.get_angle(-up_direction) <= floor_max_angle + FLOOR_ANGLE_THRESHOLD) { //ceiling
  1184. on_ceiling = true;
  1185. } else {
  1186. on_wall = true;
  1187. wall_normal = p_result.collision_normal;
  1188. // Don't apply wall velocity when the collider is a CharacterBody2D.
  1189. if (Object::cast_to<CharacterBody2D>(ObjectDB::get_instance(p_result.collider_id)) == nullptr) {
  1190. _set_platform_data(p_result);
  1191. }
  1192. }
  1193. }
  1194. void CharacterBody2D::_set_platform_data(const PhysicsServer2D::MotionResult &p_result) {
  1195. platform_rid = p_result.collider;
  1196. platform_object_id = p_result.collider_id;
  1197. platform_velocity = p_result.collider_velocity;
  1198. platform_layer = PhysicsServer2D::get_singleton()->body_get_collision_layer(platform_rid);
  1199. }
  1200. const Vector2 &CharacterBody2D::get_velocity() const {
  1201. return velocity;
  1202. }
  1203. void CharacterBody2D::set_velocity(const Vector2 &p_velocity) {
  1204. velocity = p_velocity;
  1205. }
  1206. bool CharacterBody2D::is_on_floor() const {
  1207. return on_floor;
  1208. }
  1209. bool CharacterBody2D::is_on_floor_only() const {
  1210. return on_floor && !on_wall && !on_ceiling;
  1211. }
  1212. bool CharacterBody2D::is_on_wall() const {
  1213. return on_wall;
  1214. }
  1215. bool CharacterBody2D::is_on_wall_only() const {
  1216. return on_wall && !on_floor && !on_ceiling;
  1217. }
  1218. bool CharacterBody2D::is_on_ceiling() const {
  1219. return on_ceiling;
  1220. }
  1221. bool CharacterBody2D::is_on_ceiling_only() const {
  1222. return on_ceiling && !on_floor && !on_wall;
  1223. }
  1224. const Vector2 &CharacterBody2D::get_floor_normal() const {
  1225. return floor_normal;
  1226. }
  1227. const Vector2 &CharacterBody2D::get_wall_normal() const {
  1228. return wall_normal;
  1229. }
  1230. const Vector2 &CharacterBody2D::get_last_motion() const {
  1231. return last_motion;
  1232. }
  1233. Vector2 CharacterBody2D::get_position_delta() const {
  1234. return get_global_transform().columns[2] - previous_position;
  1235. }
  1236. const Vector2 &CharacterBody2D::get_real_velocity() const {
  1237. return real_velocity;
  1238. }
  1239. real_t CharacterBody2D::get_floor_angle(const Vector2 &p_up_direction) const {
  1240. ERR_FAIL_COND_V(p_up_direction == Vector2(), 0);
  1241. return Math::acos(floor_normal.dot(p_up_direction));
  1242. }
  1243. const Vector2 &CharacterBody2D::get_platform_velocity() const {
  1244. return platform_velocity;
  1245. }
  1246. int CharacterBody2D::get_slide_collision_count() const {
  1247. return motion_results.size();
  1248. }
  1249. PhysicsServer2D::MotionResult CharacterBody2D::get_slide_collision(int p_bounce) const {
  1250. ERR_FAIL_INDEX_V(p_bounce, motion_results.size(), PhysicsServer2D::MotionResult());
  1251. return motion_results[p_bounce];
  1252. }
  1253. Ref<KinematicCollision2D> CharacterBody2D::_get_slide_collision(int p_bounce) {
  1254. ERR_FAIL_INDEX_V(p_bounce, motion_results.size(), Ref<KinematicCollision2D>());
  1255. if (p_bounce >= slide_colliders.size()) {
  1256. slide_colliders.resize(p_bounce + 1);
  1257. }
  1258. // Create a new instance when the cached reference is invalid or still in use in script.
  1259. if (slide_colliders[p_bounce].is_null() || slide_colliders[p_bounce]->reference_get_count() > 1) {
  1260. slide_colliders.write[p_bounce].instantiate();
  1261. slide_colliders.write[p_bounce]->owner = this;
  1262. }
  1263. slide_colliders.write[p_bounce]->result = motion_results[p_bounce];
  1264. return slide_colliders[p_bounce];
  1265. }
  1266. Ref<KinematicCollision2D> CharacterBody2D::_get_last_slide_collision() {
  1267. if (motion_results.size() == 0) {
  1268. return Ref<KinematicCollision2D>();
  1269. }
  1270. return _get_slide_collision(motion_results.size() - 1);
  1271. }
  1272. void CharacterBody2D::set_safe_margin(real_t p_margin) {
  1273. margin = p_margin;
  1274. }
  1275. real_t CharacterBody2D::get_safe_margin() const {
  1276. return margin;
  1277. }
  1278. bool CharacterBody2D::is_floor_stop_on_slope_enabled() const {
  1279. return floor_stop_on_slope;
  1280. }
  1281. void CharacterBody2D::set_floor_stop_on_slope_enabled(bool p_enabled) {
  1282. floor_stop_on_slope = p_enabled;
  1283. }
  1284. bool CharacterBody2D::is_floor_constant_speed_enabled() const {
  1285. return floor_constant_speed;
  1286. }
  1287. void CharacterBody2D::set_floor_constant_speed_enabled(bool p_enabled) {
  1288. floor_constant_speed = p_enabled;
  1289. }
  1290. bool CharacterBody2D::is_floor_block_on_wall_enabled() const {
  1291. return floor_block_on_wall;
  1292. }
  1293. void CharacterBody2D::set_floor_block_on_wall_enabled(bool p_enabled) {
  1294. floor_block_on_wall = p_enabled;
  1295. }
  1296. bool CharacterBody2D::is_slide_on_ceiling_enabled() const {
  1297. return slide_on_ceiling;
  1298. }
  1299. void CharacterBody2D::set_slide_on_ceiling_enabled(bool p_enabled) {
  1300. slide_on_ceiling = p_enabled;
  1301. }
  1302. uint32_t CharacterBody2D::get_platform_floor_layers() const {
  1303. return platform_floor_layers;
  1304. }
  1305. void CharacterBody2D::set_platform_floor_layers(uint32_t p_exclude_layers) {
  1306. platform_floor_layers = p_exclude_layers;
  1307. }
  1308. uint32_t CharacterBody2D::get_platform_wall_layers() const {
  1309. return platform_wall_layers;
  1310. }
  1311. void CharacterBody2D::set_platform_wall_layers(uint32_t p_exclude_layers) {
  1312. platform_wall_layers = p_exclude_layers;
  1313. }
  1314. void CharacterBody2D::set_motion_mode(MotionMode p_mode) {
  1315. motion_mode = p_mode;
  1316. }
  1317. CharacterBody2D::MotionMode CharacterBody2D::get_motion_mode() const {
  1318. return motion_mode;
  1319. }
  1320. void CharacterBody2D::set_platform_on_leave(PlatformOnLeave p_on_leave_apply_velocity) {
  1321. platform_on_leave = p_on_leave_apply_velocity;
  1322. }
  1323. CharacterBody2D::PlatformOnLeave CharacterBody2D::get_platform_on_leave() const {
  1324. return platform_on_leave;
  1325. }
  1326. int CharacterBody2D::get_max_slides() const {
  1327. return max_slides;
  1328. }
  1329. void CharacterBody2D::set_max_slides(int p_max_slides) {
  1330. ERR_FAIL_COND(p_max_slides < 1);
  1331. max_slides = p_max_slides;
  1332. }
  1333. real_t CharacterBody2D::get_floor_max_angle() const {
  1334. return floor_max_angle;
  1335. }
  1336. void CharacterBody2D::set_floor_max_angle(real_t p_radians) {
  1337. floor_max_angle = p_radians;
  1338. }
  1339. real_t CharacterBody2D::get_floor_snap_length() {
  1340. return floor_snap_length;
  1341. }
  1342. void CharacterBody2D::set_floor_snap_length(real_t p_floor_snap_length) {
  1343. ERR_FAIL_COND(p_floor_snap_length < 0);
  1344. floor_snap_length = p_floor_snap_length;
  1345. }
  1346. real_t CharacterBody2D::get_wall_min_slide_angle() const {
  1347. return wall_min_slide_angle;
  1348. }
  1349. void CharacterBody2D::set_wall_min_slide_angle(real_t p_radians) {
  1350. wall_min_slide_angle = p_radians;
  1351. }
  1352. const Vector2 &CharacterBody2D::get_up_direction() const {
  1353. return up_direction;
  1354. }
  1355. void CharacterBody2D::set_up_direction(const Vector2 &p_up_direction) {
  1356. ERR_FAIL_COND_MSG(p_up_direction == Vector2(), "up_direction can't be equal to Vector2.ZERO, consider using Floating motion mode instead.");
  1357. up_direction = p_up_direction.normalized();
  1358. }
  1359. void CharacterBody2D::_notification(int p_what) {
  1360. switch (p_what) {
  1361. case NOTIFICATION_ENTER_TREE: {
  1362. // Reset move_and_slide() data.
  1363. on_floor = false;
  1364. platform_rid = RID();
  1365. platform_object_id = ObjectID();
  1366. on_ceiling = false;
  1367. on_wall = false;
  1368. motion_results.clear();
  1369. platform_velocity = Vector2();
  1370. } break;
  1371. }
  1372. }
  1373. void CharacterBody2D::_bind_methods() {
  1374. ClassDB::bind_method(D_METHOD("move_and_slide"), &CharacterBody2D::move_and_slide);
  1375. ClassDB::bind_method(D_METHOD("set_velocity", "velocity"), &CharacterBody2D::set_velocity);
  1376. ClassDB::bind_method(D_METHOD("get_velocity"), &CharacterBody2D::get_velocity);
  1377. ClassDB::bind_method(D_METHOD("set_safe_margin", "margin"), &CharacterBody2D::set_safe_margin);
  1378. ClassDB::bind_method(D_METHOD("get_safe_margin"), &CharacterBody2D::get_safe_margin);
  1379. ClassDB::bind_method(D_METHOD("is_floor_stop_on_slope_enabled"), &CharacterBody2D::is_floor_stop_on_slope_enabled);
  1380. ClassDB::bind_method(D_METHOD("set_floor_stop_on_slope_enabled", "enabled"), &CharacterBody2D::set_floor_stop_on_slope_enabled);
  1381. ClassDB::bind_method(D_METHOD("set_floor_constant_speed_enabled", "enabled"), &CharacterBody2D::set_floor_constant_speed_enabled);
  1382. ClassDB::bind_method(D_METHOD("is_floor_constant_speed_enabled"), &CharacterBody2D::is_floor_constant_speed_enabled);
  1383. ClassDB::bind_method(D_METHOD("set_floor_block_on_wall_enabled", "enabled"), &CharacterBody2D::set_floor_block_on_wall_enabled);
  1384. ClassDB::bind_method(D_METHOD("is_floor_block_on_wall_enabled"), &CharacterBody2D::is_floor_block_on_wall_enabled);
  1385. ClassDB::bind_method(D_METHOD("set_slide_on_ceiling_enabled", "enabled"), &CharacterBody2D::set_slide_on_ceiling_enabled);
  1386. ClassDB::bind_method(D_METHOD("is_slide_on_ceiling_enabled"), &CharacterBody2D::is_slide_on_ceiling_enabled);
  1387. ClassDB::bind_method(D_METHOD("set_platform_floor_layers", "exclude_layer"), &CharacterBody2D::set_platform_floor_layers);
  1388. ClassDB::bind_method(D_METHOD("get_platform_floor_layers"), &CharacterBody2D::get_platform_floor_layers);
  1389. ClassDB::bind_method(D_METHOD("set_platform_wall_layers", "exclude_layer"), &CharacterBody2D::set_platform_wall_layers);
  1390. ClassDB::bind_method(D_METHOD("get_platform_wall_layers"), &CharacterBody2D::get_platform_wall_layers);
  1391. ClassDB::bind_method(D_METHOD("get_max_slides"), &CharacterBody2D::get_max_slides);
  1392. ClassDB::bind_method(D_METHOD("set_max_slides", "max_slides"), &CharacterBody2D::set_max_slides);
  1393. ClassDB::bind_method(D_METHOD("get_floor_max_angle"), &CharacterBody2D::get_floor_max_angle);
  1394. ClassDB::bind_method(D_METHOD("set_floor_max_angle", "radians"), &CharacterBody2D::set_floor_max_angle);
  1395. ClassDB::bind_method(D_METHOD("get_floor_snap_length"), &CharacterBody2D::get_floor_snap_length);
  1396. ClassDB::bind_method(D_METHOD("set_floor_snap_length", "floor_snap_length"), &CharacterBody2D::set_floor_snap_length);
  1397. ClassDB::bind_method(D_METHOD("get_wall_min_slide_angle"), &CharacterBody2D::get_wall_min_slide_angle);
  1398. ClassDB::bind_method(D_METHOD("set_wall_min_slide_angle", "radians"), &CharacterBody2D::set_wall_min_slide_angle);
  1399. ClassDB::bind_method(D_METHOD("get_up_direction"), &CharacterBody2D::get_up_direction);
  1400. ClassDB::bind_method(D_METHOD("set_up_direction", "up_direction"), &CharacterBody2D::set_up_direction);
  1401. ClassDB::bind_method(D_METHOD("set_motion_mode", "mode"), &CharacterBody2D::set_motion_mode);
  1402. ClassDB::bind_method(D_METHOD("get_motion_mode"), &CharacterBody2D::get_motion_mode);
  1403. ClassDB::bind_method(D_METHOD("set_platform_on_leave", "on_leave_apply_velocity"), &CharacterBody2D::set_platform_on_leave);
  1404. ClassDB::bind_method(D_METHOD("get_platform_on_leave"), &CharacterBody2D::get_platform_on_leave);
  1405. ClassDB::bind_method(D_METHOD("is_on_floor"), &CharacterBody2D::is_on_floor);
  1406. ClassDB::bind_method(D_METHOD("is_on_floor_only"), &CharacterBody2D::is_on_floor_only);
  1407. ClassDB::bind_method(D_METHOD("is_on_ceiling"), &CharacterBody2D::is_on_ceiling);
  1408. ClassDB::bind_method(D_METHOD("is_on_ceiling_only"), &CharacterBody2D::is_on_ceiling_only);
  1409. ClassDB::bind_method(D_METHOD("is_on_wall"), &CharacterBody2D::is_on_wall);
  1410. ClassDB::bind_method(D_METHOD("is_on_wall_only"), &CharacterBody2D::is_on_wall_only);
  1411. ClassDB::bind_method(D_METHOD("get_floor_normal"), &CharacterBody2D::get_floor_normal);
  1412. ClassDB::bind_method(D_METHOD("get_wall_normal"), &CharacterBody2D::get_wall_normal);
  1413. ClassDB::bind_method(D_METHOD("get_last_motion"), &CharacterBody2D::get_last_motion);
  1414. ClassDB::bind_method(D_METHOD("get_position_delta"), &CharacterBody2D::get_position_delta);
  1415. ClassDB::bind_method(D_METHOD("get_real_velocity"), &CharacterBody2D::get_real_velocity);
  1416. ClassDB::bind_method(D_METHOD("get_floor_angle", "up_direction"), &CharacterBody2D::get_floor_angle, DEFVAL(Vector2(0.0, -1.0)));
  1417. ClassDB::bind_method(D_METHOD("get_platform_velocity"), &CharacterBody2D::get_platform_velocity);
  1418. ClassDB::bind_method(D_METHOD("get_slide_collision_count"), &CharacterBody2D::get_slide_collision_count);
  1419. ClassDB::bind_method(D_METHOD("get_slide_collision", "slide_idx"), &CharacterBody2D::_get_slide_collision);
  1420. ClassDB::bind_method(D_METHOD("get_last_slide_collision"), &CharacterBody2D::_get_last_slide_collision);
  1421. ADD_PROPERTY(PropertyInfo(Variant::INT, "motion_mode", PROPERTY_HINT_ENUM, "Grounded,Floating", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), "set_motion_mode", "get_motion_mode");
  1422. ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "up_direction"), "set_up_direction", "get_up_direction");
  1423. ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "velocity", PROPERTY_HINT_NONE, "suffix:px/s", PROPERTY_USAGE_NO_EDITOR), "set_velocity", "get_velocity");
  1424. ADD_PROPERTY(PropertyInfo(Variant::BOOL, "slide_on_ceiling"), "set_slide_on_ceiling_enabled", "is_slide_on_ceiling_enabled");
  1425. ADD_PROPERTY(PropertyInfo(Variant::INT, "max_slides", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR), "set_max_slides", "get_max_slides");
  1426. ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "wall_min_slide_angle", PROPERTY_HINT_RANGE, "0,180,0.1,radians", PROPERTY_USAGE_DEFAULT), "set_wall_min_slide_angle", "get_wall_min_slide_angle");
  1427. ADD_GROUP("Floor", "floor_");
  1428. ADD_PROPERTY(PropertyInfo(Variant::BOOL, "floor_stop_on_slope"), "set_floor_stop_on_slope_enabled", "is_floor_stop_on_slope_enabled");
  1429. ADD_PROPERTY(PropertyInfo(Variant::BOOL, "floor_constant_speed"), "set_floor_constant_speed_enabled", "is_floor_constant_speed_enabled");
  1430. ADD_PROPERTY(PropertyInfo(Variant::BOOL, "floor_block_on_wall"), "set_floor_block_on_wall_enabled", "is_floor_block_on_wall_enabled");
  1431. ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "floor_max_angle", PROPERTY_HINT_RANGE, "0,180,0.1,radians"), "set_floor_max_angle", "get_floor_max_angle");
  1432. ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "floor_snap_length", PROPERTY_HINT_RANGE, "0,32,0.1,or_greater,suffix:px"), "set_floor_snap_length", "get_floor_snap_length");
  1433. ADD_GROUP("Moving Platform", "platform");
  1434. ADD_PROPERTY(PropertyInfo(Variant::INT, "platform_on_leave", PROPERTY_HINT_ENUM, "Add Velocity,Add Upward Velocity,Do Nothing", PROPERTY_USAGE_DEFAULT), "set_platform_on_leave", "get_platform_on_leave");
  1435. ADD_PROPERTY(PropertyInfo(Variant::INT, "platform_floor_layers", PROPERTY_HINT_LAYERS_2D_PHYSICS), "set_platform_floor_layers", "get_platform_floor_layers");
  1436. ADD_PROPERTY(PropertyInfo(Variant::INT, "platform_wall_layers", PROPERTY_HINT_LAYERS_2D_PHYSICS), "set_platform_wall_layers", "get_platform_wall_layers");
  1437. ADD_GROUP("Collision", "");
  1438. ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "safe_margin", PROPERTY_HINT_RANGE, "0.001,256,0.001,suffix:px"), "set_safe_margin", "get_safe_margin");
  1439. BIND_ENUM_CONSTANT(MOTION_MODE_GROUNDED);
  1440. BIND_ENUM_CONSTANT(MOTION_MODE_FLOATING);
  1441. BIND_ENUM_CONSTANT(PLATFORM_ON_LEAVE_ADD_VELOCITY);
  1442. BIND_ENUM_CONSTANT(PLATFORM_ON_LEAVE_ADD_UPWARD_VELOCITY);
  1443. BIND_ENUM_CONSTANT(PLATFORM_ON_LEAVE_DO_NOTHING);
  1444. }
  1445. void CharacterBody2D::_validate_property(PropertyInfo &p_property) const {
  1446. if (motion_mode == MOTION_MODE_FLOATING) {
  1447. if (p_property.name.begins_with("floor_") || p_property.name == "up_direction" || p_property.name == "slide_on_ceiling") {
  1448. p_property.usage = PROPERTY_USAGE_NO_EDITOR;
  1449. }
  1450. } else {
  1451. if (p_property.name == "wall_min_slide_angle") {
  1452. p_property.usage = PROPERTY_USAGE_NO_EDITOR;
  1453. }
  1454. }
  1455. }
  1456. CharacterBody2D::CharacterBody2D() :
  1457. PhysicsBody2D(PhysicsServer2D::BODY_MODE_KINEMATIC) {
  1458. }
  1459. CharacterBody2D::~CharacterBody2D() {
  1460. for (int i = 0; i < slide_colliders.size(); i++) {
  1461. if (slide_colliders[i].is_valid()) {
  1462. slide_colliders.write[i]->owner = nullptr;
  1463. }
  1464. }
  1465. }
  1466. ////////////////////////
  1467. Vector2 KinematicCollision2D::get_position() const {
  1468. return result.collision_point;
  1469. }
  1470. Vector2 KinematicCollision2D::get_normal() const {
  1471. return result.collision_normal;
  1472. }
  1473. Vector2 KinematicCollision2D::get_travel() const {
  1474. return result.travel;
  1475. }
  1476. Vector2 KinematicCollision2D::get_remainder() const {
  1477. return result.remainder;
  1478. }
  1479. real_t KinematicCollision2D::get_angle(const Vector2 &p_up_direction) const {
  1480. ERR_FAIL_COND_V(p_up_direction == Vector2(), 0);
  1481. return result.get_angle(p_up_direction);
  1482. }
  1483. real_t KinematicCollision2D::get_depth() const {
  1484. return result.collision_depth;
  1485. }
  1486. Object *KinematicCollision2D::get_local_shape() const {
  1487. if (!owner) {
  1488. return nullptr;
  1489. }
  1490. uint32_t ownerid = owner->shape_find_owner(result.collision_local_shape);
  1491. return owner->shape_owner_get_owner(ownerid);
  1492. }
  1493. Object *KinematicCollision2D::get_collider() const {
  1494. if (result.collider_id.is_valid()) {
  1495. return ObjectDB::get_instance(result.collider_id);
  1496. }
  1497. return nullptr;
  1498. }
  1499. ObjectID KinematicCollision2D::get_collider_id() const {
  1500. return result.collider_id;
  1501. }
  1502. RID KinematicCollision2D::get_collider_rid() const {
  1503. return result.collider;
  1504. }
  1505. Object *KinematicCollision2D::get_collider_shape() const {
  1506. Object *collider = get_collider();
  1507. if (collider) {
  1508. CollisionObject2D *obj2d = Object::cast_to<CollisionObject2D>(collider);
  1509. if (obj2d) {
  1510. uint32_t ownerid = obj2d->shape_find_owner(result.collider_shape);
  1511. return obj2d->shape_owner_get_owner(ownerid);
  1512. }
  1513. }
  1514. return nullptr;
  1515. }
  1516. int KinematicCollision2D::get_collider_shape_index() const {
  1517. return result.collider_shape;
  1518. }
  1519. Vector2 KinematicCollision2D::get_collider_velocity() const {
  1520. return result.collider_velocity;
  1521. }
  1522. void KinematicCollision2D::_bind_methods() {
  1523. ClassDB::bind_method(D_METHOD("get_position"), &KinematicCollision2D::get_position);
  1524. ClassDB::bind_method(D_METHOD("get_normal"), &KinematicCollision2D::get_normal);
  1525. ClassDB::bind_method(D_METHOD("get_travel"), &KinematicCollision2D::get_travel);
  1526. ClassDB::bind_method(D_METHOD("get_remainder"), &KinematicCollision2D::get_remainder);
  1527. ClassDB::bind_method(D_METHOD("get_angle", "up_direction"), &KinematicCollision2D::get_angle, DEFVAL(Vector2(0.0, -1.0)));
  1528. ClassDB::bind_method(D_METHOD("get_depth"), &KinematicCollision2D::get_depth);
  1529. ClassDB::bind_method(D_METHOD("get_local_shape"), &KinematicCollision2D::get_local_shape);
  1530. ClassDB::bind_method(D_METHOD("get_collider"), &KinematicCollision2D::get_collider);
  1531. ClassDB::bind_method(D_METHOD("get_collider_id"), &KinematicCollision2D::get_collider_id);
  1532. ClassDB::bind_method(D_METHOD("get_collider_rid"), &KinematicCollision2D::get_collider_rid);
  1533. ClassDB::bind_method(D_METHOD("get_collider_shape"), &KinematicCollision2D::get_collider_shape);
  1534. ClassDB::bind_method(D_METHOD("get_collider_shape_index"), &KinematicCollision2D::get_collider_shape_index);
  1535. ClassDB::bind_method(D_METHOD("get_collider_velocity"), &KinematicCollision2D::get_collider_velocity);
  1536. }