physical_bone_2d.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300
  1. /**************************************************************************/
  2. /* physical_bone_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 "physical_bone_2d.h"
  31. #include "scene/2d/physics/joints/joint_2d.h"
  32. void PhysicalBone2D::_notification(int p_what) {
  33. switch (p_what) {
  34. case NOTIFICATION_INTERNAL_PHYSICS_PROCESS: {
  35. // Position the RigidBody in the correct position.
  36. if (follow_bone_when_simulating) {
  37. _position_at_bone2d();
  38. }
  39. // Keep the child joint in the correct position.
  40. if (child_joint && auto_configure_joint) {
  41. child_joint->set_global_position(get_global_position());
  42. }
  43. } break;
  44. case NOTIFICATION_READY: {
  45. _find_skeleton_parent();
  46. _find_joint_child();
  47. // Configure joint.
  48. if (child_joint && auto_configure_joint) {
  49. _auto_configure_joint();
  50. }
  51. // Simulate physics if set.
  52. if (simulate_physics) {
  53. _start_physics_simulation();
  54. } else {
  55. _stop_physics_simulation();
  56. }
  57. set_physics_process_internal(true);
  58. } break;
  59. }
  60. }
  61. void PhysicalBone2D::_position_at_bone2d() {
  62. // Reset to Bone2D position
  63. if (parent_skeleton) {
  64. Bone2D *bone_to_use = parent_skeleton->get_bone(bone2d_index);
  65. ERR_FAIL_NULL_MSG(bone_to_use, "It's not possible to position the bone with ID: " + itos(bone2d_index) + ".");
  66. set_global_transform(bone_to_use->get_global_transform());
  67. }
  68. }
  69. void PhysicalBone2D::_find_skeleton_parent() {
  70. Node *current_parent = get_parent();
  71. while (current_parent != nullptr) {
  72. Skeleton2D *potential_skeleton = Object::cast_to<Skeleton2D>(current_parent);
  73. if (potential_skeleton) {
  74. parent_skeleton = potential_skeleton;
  75. break;
  76. } else {
  77. PhysicalBone2D *potential_parent_bone = Object::cast_to<PhysicalBone2D>(current_parent);
  78. if (potential_parent_bone) {
  79. current_parent = potential_parent_bone->get_parent();
  80. } else {
  81. current_parent = nullptr;
  82. }
  83. }
  84. }
  85. }
  86. void PhysicalBone2D::_find_joint_child() {
  87. for (int i = 0; i < get_child_count(); i++) {
  88. Node *child_node = get_child(i);
  89. Joint2D *potential_joint = Object::cast_to<Joint2D>(child_node);
  90. if (potential_joint) {
  91. child_joint = potential_joint;
  92. break;
  93. }
  94. }
  95. }
  96. PackedStringArray PhysicalBone2D::get_configuration_warnings() const {
  97. PackedStringArray warnings = RigidBody2D::get_configuration_warnings();
  98. if (!parent_skeleton) {
  99. warnings.push_back(RTR("A PhysicalBone2D only works with a Skeleton2D or another PhysicalBone2D as a parent node!"));
  100. }
  101. if (parent_skeleton && bone2d_index <= -1) {
  102. warnings.push_back(RTR("A PhysicalBone2D needs to be assigned to a Bone2D node in order to function! Please set a Bone2D node in the inspector."));
  103. }
  104. if (!child_joint) {
  105. PhysicalBone2D *parent_bone = Object::cast_to<PhysicalBone2D>(get_parent());
  106. if (parent_bone) {
  107. warnings.push_back(RTR("A PhysicalBone2D node should have a Joint2D-based child node to keep bones connected! Please add a Joint2D-based node as a child to this node!"));
  108. }
  109. }
  110. return warnings;
  111. }
  112. void PhysicalBone2D::_auto_configure_joint() {
  113. if (!auto_configure_joint) {
  114. return;
  115. }
  116. if (child_joint) {
  117. // Node A = parent | Node B = this node
  118. Node *parent_node = get_parent();
  119. PhysicalBone2D *potential_parent_bone = Object::cast_to<PhysicalBone2D>(parent_node);
  120. if (potential_parent_bone) {
  121. child_joint->set_node_a(child_joint->get_path_to(potential_parent_bone));
  122. child_joint->set_node_b(child_joint->get_path_to(this));
  123. } else {
  124. WARN_PRINT("Cannot setup joint without a parent PhysicalBone2D node.");
  125. }
  126. // Place the child joint at this node's position.
  127. child_joint->set_global_position(get_global_position());
  128. }
  129. }
  130. void PhysicalBone2D::_start_physics_simulation() {
  131. if (_internal_simulate_physics) {
  132. return;
  133. }
  134. // Reset to Bone2D position.
  135. _position_at_bone2d();
  136. // Apply the layers and masks.
  137. PhysicsServer2D::get_singleton()->body_set_collision_layer(get_rid(), get_collision_layer());
  138. PhysicsServer2D::get_singleton()->body_set_collision_mask(get_rid(), get_collision_mask());
  139. PhysicsServer2D::get_singleton()->body_set_collision_priority(get_rid(), get_collision_priority());
  140. // Apply the correct mode.
  141. _apply_body_mode();
  142. _internal_simulate_physics = true;
  143. set_physics_process_internal(true);
  144. }
  145. void PhysicalBone2D::_stop_physics_simulation() {
  146. if (_internal_simulate_physics) {
  147. _internal_simulate_physics = false;
  148. // Reset to Bone2D position
  149. _position_at_bone2d();
  150. set_physics_process_internal(false);
  151. PhysicsServer2D::get_singleton()->body_set_collision_layer(get_rid(), 0);
  152. PhysicsServer2D::get_singleton()->body_set_collision_mask(get_rid(), 0);
  153. PhysicsServer2D::get_singleton()->body_set_collision_priority(get_rid(), 1.0);
  154. PhysicsServer2D::get_singleton()->body_set_mode(get_rid(), PhysicsServer2D::BodyMode::BODY_MODE_STATIC);
  155. }
  156. }
  157. Joint2D *PhysicalBone2D::get_joint() const {
  158. return child_joint;
  159. }
  160. bool PhysicalBone2D::get_auto_configure_joint() const {
  161. return auto_configure_joint;
  162. }
  163. void PhysicalBone2D::set_auto_configure_joint(bool p_auto_configure) {
  164. auto_configure_joint = p_auto_configure;
  165. _auto_configure_joint();
  166. }
  167. void PhysicalBone2D::set_simulate_physics(bool p_simulate) {
  168. if (p_simulate == simulate_physics) {
  169. return;
  170. }
  171. simulate_physics = p_simulate;
  172. if (simulate_physics) {
  173. _start_physics_simulation();
  174. } else {
  175. _stop_physics_simulation();
  176. }
  177. }
  178. bool PhysicalBone2D::get_simulate_physics() const {
  179. return simulate_physics;
  180. }
  181. bool PhysicalBone2D::is_simulating_physics() const {
  182. return _internal_simulate_physics;
  183. }
  184. void PhysicalBone2D::set_bone2d_nodepath(const NodePath &p_nodepath) {
  185. bone2d_nodepath = p_nodepath;
  186. notify_property_list_changed();
  187. }
  188. NodePath PhysicalBone2D::get_bone2d_nodepath() const {
  189. return bone2d_nodepath;
  190. }
  191. void PhysicalBone2D::set_bone2d_index(int p_bone_idx) {
  192. ERR_FAIL_COND_MSG(p_bone_idx < 0, "Bone index is out of range: The index is too low!");
  193. if (!is_inside_tree()) {
  194. bone2d_index = p_bone_idx;
  195. return;
  196. }
  197. if (parent_skeleton) {
  198. ERR_FAIL_INDEX_MSG(p_bone_idx, parent_skeleton->get_bone_count(), "Passed-in Bone index is out of range!");
  199. bone2d_index = p_bone_idx;
  200. bone2d_nodepath = get_path_to(parent_skeleton->get_bone(bone2d_index));
  201. } else {
  202. WARN_PRINT("Cannot verify bone index...");
  203. bone2d_index = p_bone_idx;
  204. }
  205. notify_property_list_changed();
  206. }
  207. int PhysicalBone2D::get_bone2d_index() const {
  208. return bone2d_index;
  209. }
  210. void PhysicalBone2D::set_follow_bone_when_simulating(bool p_follow_bone) {
  211. follow_bone_when_simulating = p_follow_bone;
  212. if (_internal_simulate_physics) {
  213. _stop_physics_simulation();
  214. _start_physics_simulation();
  215. }
  216. }
  217. bool PhysicalBone2D::get_follow_bone_when_simulating() const {
  218. return follow_bone_when_simulating;
  219. }
  220. void PhysicalBone2D::_bind_methods() {
  221. ClassDB::bind_method(D_METHOD("get_joint"), &PhysicalBone2D::get_joint);
  222. ClassDB::bind_method(D_METHOD("get_auto_configure_joint"), &PhysicalBone2D::get_auto_configure_joint);
  223. ClassDB::bind_method(D_METHOD("set_auto_configure_joint", "auto_configure_joint"), &PhysicalBone2D::set_auto_configure_joint);
  224. ClassDB::bind_method(D_METHOD("set_simulate_physics", "simulate_physics"), &PhysicalBone2D::set_simulate_physics);
  225. ClassDB::bind_method(D_METHOD("get_simulate_physics"), &PhysicalBone2D::get_simulate_physics);
  226. ClassDB::bind_method(D_METHOD("is_simulating_physics"), &PhysicalBone2D::is_simulating_physics);
  227. ClassDB::bind_method(D_METHOD("set_bone2d_nodepath", "nodepath"), &PhysicalBone2D::set_bone2d_nodepath);
  228. ClassDB::bind_method(D_METHOD("get_bone2d_nodepath"), &PhysicalBone2D::get_bone2d_nodepath);
  229. ClassDB::bind_method(D_METHOD("set_bone2d_index", "bone_index"), &PhysicalBone2D::set_bone2d_index);
  230. ClassDB::bind_method(D_METHOD("get_bone2d_index"), &PhysicalBone2D::get_bone2d_index);
  231. ClassDB::bind_method(D_METHOD("set_follow_bone_when_simulating", "follow_bone"), &PhysicalBone2D::set_follow_bone_when_simulating);
  232. ClassDB::bind_method(D_METHOD("get_follow_bone_when_simulating"), &PhysicalBone2D::get_follow_bone_when_simulating);
  233. ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "bone2d_nodepath", PROPERTY_HINT_NODE_PATH_VALID_TYPES, "Bone2D"), "set_bone2d_nodepath", "get_bone2d_nodepath");
  234. ADD_PROPERTY(PropertyInfo(Variant::INT, "bone2d_index", PROPERTY_HINT_RANGE, "-1, 1000, 1"), "set_bone2d_index", "get_bone2d_index");
  235. ADD_PROPERTY(PropertyInfo(Variant::BOOL, "auto_configure_joint"), "set_auto_configure_joint", "get_auto_configure_joint");
  236. ADD_PROPERTY(PropertyInfo(Variant::BOOL, "simulate_physics"), "set_simulate_physics", "get_simulate_physics");
  237. ADD_PROPERTY(PropertyInfo(Variant::BOOL, "follow_bone_when_simulating"), "set_follow_bone_when_simulating", "get_follow_bone_when_simulating");
  238. }
  239. PhysicalBone2D::PhysicalBone2D() {
  240. // Stop the RigidBody from executing its force integration.
  241. PhysicsServer2D::get_singleton()->body_set_collision_layer(get_rid(), 0);
  242. PhysicsServer2D::get_singleton()->body_set_collision_mask(get_rid(), 0);
  243. PhysicsServer2D::get_singleton()->body_set_mode(get_rid(), PhysicsServer2D::BodyMode::BODY_MODE_STATIC);
  244. child_joint = nullptr;
  245. }
  246. PhysicalBone2D::~PhysicalBone2D() {
  247. }