physics_body_2d.cpp 75 KB

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