physical_bone_simulator_3d.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392
  1. /**************************************************************************/
  2. /* physical_bone_simulator_3d.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_simulator_3d.h"
  31. #include "scene/3d/physics/physical_bone_3d.h"
  32. void PhysicalBoneSimulator3D::_skeleton_changed(Skeleton3D *p_old, Skeleton3D *p_new) {
  33. if (p_old) {
  34. if (p_old->is_connected(SNAME("bone_list_changed"), callable_mp(this, &PhysicalBoneSimulator3D::_bone_list_changed))) {
  35. p_old->disconnect(SNAME("bone_list_changed"), callable_mp(this, &PhysicalBoneSimulator3D::_bone_list_changed));
  36. }
  37. if (p_old->is_connected(SceneStringName(pose_updated), callable_mp(this, &PhysicalBoneSimulator3D::_pose_updated))) {
  38. p_old->disconnect(SceneStringName(pose_updated), callable_mp(this, &PhysicalBoneSimulator3D::_pose_updated));
  39. }
  40. }
  41. if (p_new) {
  42. if (!p_new->is_connected(SNAME("bone_list_changed"), callable_mp(this, &PhysicalBoneSimulator3D::_bone_list_changed))) {
  43. p_new->connect(SNAME("bone_list_changed"), callable_mp(this, &PhysicalBoneSimulator3D::_bone_list_changed));
  44. }
  45. if (!p_new->is_connected(SceneStringName(pose_updated), callable_mp(this, &PhysicalBoneSimulator3D::_pose_updated))) {
  46. p_new->connect(SceneStringName(pose_updated), callable_mp(this, &PhysicalBoneSimulator3D::_pose_updated));
  47. }
  48. }
  49. _bone_list_changed();
  50. }
  51. void PhysicalBoneSimulator3D::_bone_list_changed() {
  52. bones.clear();
  53. Skeleton3D *skeleton = get_skeleton();
  54. if (!skeleton) {
  55. return;
  56. }
  57. for (int i = 0; i < skeleton->get_bone_count(); i++) {
  58. SimulatedBone sb;
  59. sb.parent = skeleton->get_bone_parent(i);
  60. sb.child_bones = skeleton->get_bone_children(i);
  61. bones.push_back(sb);
  62. }
  63. _rebuild_physical_bones_cache();
  64. _pose_updated();
  65. }
  66. void PhysicalBoneSimulator3D::_pose_updated() {
  67. Skeleton3D *skeleton = get_skeleton();
  68. if (!skeleton || simulating) {
  69. return;
  70. }
  71. ERR_FAIL_COND(skeleton->get_bone_count() != bones.size());
  72. for (int i = 0; i < skeleton->get_bone_count(); i++) {
  73. _bone_pose_updated(skeleton, i);
  74. }
  75. }
  76. void PhysicalBoneSimulator3D::_bone_pose_updated(Skeleton3D *p_skeleton, int p_bone_id) {
  77. ERR_FAIL_INDEX(p_bone_id, bones.size());
  78. bones.write[p_bone_id].global_pose = p_skeleton->get_bone_global_pose(p_bone_id);
  79. }
  80. void PhysicalBoneSimulator3D::_set_active(bool p_active) {
  81. if (!Engine::get_singleton()->is_editor_hint()) {
  82. _reset_physical_bones_state();
  83. }
  84. }
  85. void PhysicalBoneSimulator3D::_reset_physical_bones_state() {
  86. for (int i = 0; i < bones.size(); i += 1) {
  87. if (bones[i].physical_bone) {
  88. bones[i].physical_bone->reset_physics_simulation_state();
  89. }
  90. }
  91. }
  92. bool PhysicalBoneSimulator3D::is_simulating_physics() const {
  93. return simulating;
  94. }
  95. int PhysicalBoneSimulator3D::find_bone(const String &p_name) const {
  96. Skeleton3D *skeleton = get_skeleton();
  97. if (!skeleton) {
  98. return -1;
  99. }
  100. return skeleton->find_bone(p_name);
  101. }
  102. String PhysicalBoneSimulator3D::get_bone_name(int p_bone) const {
  103. Skeleton3D *skeleton = get_skeleton();
  104. if (!skeleton) {
  105. return String();
  106. }
  107. return skeleton->get_bone_name(p_bone);
  108. }
  109. int PhysicalBoneSimulator3D::get_bone_count() const {
  110. return bones.size();
  111. }
  112. bool PhysicalBoneSimulator3D::is_bone_parent_of(int p_bone, int p_parent_bone_id) const {
  113. Skeleton3D *skeleton = get_skeleton();
  114. if (!skeleton) {
  115. return false;
  116. }
  117. return skeleton->is_bone_parent_of(p_bone, p_parent_bone_id);
  118. }
  119. void PhysicalBoneSimulator3D::bind_physical_bone_to_bone(int p_bone, PhysicalBone3D *p_physical_bone) {
  120. const int bone_size = bones.size();
  121. ERR_FAIL_INDEX(p_bone, bone_size);
  122. ERR_FAIL_COND(bones[p_bone].physical_bone);
  123. ERR_FAIL_NULL(p_physical_bone);
  124. bones.write[p_bone].physical_bone = p_physical_bone;
  125. _rebuild_physical_bones_cache();
  126. }
  127. void PhysicalBoneSimulator3D::unbind_physical_bone_from_bone(int p_bone) {
  128. const int bone_size = bones.size();
  129. ERR_FAIL_INDEX(p_bone, bone_size);
  130. bones.write[p_bone].physical_bone = nullptr;
  131. _rebuild_physical_bones_cache();
  132. }
  133. PhysicalBone3D *PhysicalBoneSimulator3D::get_physical_bone(int p_bone) {
  134. const int bone_size = bones.size();
  135. ERR_FAIL_INDEX_V(p_bone, bone_size, nullptr);
  136. return bones[p_bone].physical_bone;
  137. }
  138. PhysicalBone3D *PhysicalBoneSimulator3D::get_physical_bone_parent(int p_bone) {
  139. const int bone_size = bones.size();
  140. ERR_FAIL_INDEX_V(p_bone, bone_size, nullptr);
  141. if (bones[p_bone].cache_parent_physical_bone) {
  142. return bones[p_bone].cache_parent_physical_bone;
  143. }
  144. return _get_physical_bone_parent(p_bone);
  145. }
  146. PhysicalBone3D *PhysicalBoneSimulator3D::_get_physical_bone_parent(int p_bone) {
  147. const int bone_size = bones.size();
  148. ERR_FAIL_INDEX_V(p_bone, bone_size, nullptr);
  149. const int parent_bone = bones[p_bone].parent;
  150. if (parent_bone < 0) {
  151. return nullptr;
  152. }
  153. PhysicalBone3D *pb = bones[parent_bone].physical_bone;
  154. if (pb) {
  155. return pb;
  156. } else {
  157. return get_physical_bone_parent(parent_bone);
  158. }
  159. }
  160. void PhysicalBoneSimulator3D::_rebuild_physical_bones_cache() {
  161. const int b_size = bones.size();
  162. for (int i = 0; i < b_size; ++i) {
  163. PhysicalBone3D *parent_pb = _get_physical_bone_parent(i);
  164. if (parent_pb != bones[i].cache_parent_physical_bone) {
  165. bones.write[i].cache_parent_physical_bone = parent_pb;
  166. if (bones[i].physical_bone) {
  167. bones[i].physical_bone->_on_bone_parent_changed();
  168. }
  169. }
  170. }
  171. }
  172. #ifndef DISABLE_DEPRECATED
  173. void _pb_stop_simulation_compat(Node *p_node) {
  174. PhysicalBoneSimulator3D *ps = Object::cast_to<PhysicalBoneSimulator3D>(p_node);
  175. if (ps) {
  176. return; // Prevent conflict.
  177. }
  178. for (int i = p_node->get_child_count() - 1; i >= 0; --i) {
  179. _pb_stop_simulation_compat(p_node->get_child(i));
  180. }
  181. PhysicalBone3D *pb = Object::cast_to<PhysicalBone3D>(p_node);
  182. if (pb) {
  183. pb->set_simulate_physics(false);
  184. }
  185. }
  186. #endif // _DISABLE_DEPRECATED
  187. void _pb_stop_simulation(Node *p_node) {
  188. for (int i = p_node->get_child_count() - 1; i >= 0; --i) {
  189. PhysicalBone3D *pb = Object::cast_to<PhysicalBone3D>(p_node->get_child(i));
  190. if (!pb) {
  191. continue;
  192. }
  193. _pb_stop_simulation(pb);
  194. }
  195. PhysicalBone3D *pb = Object::cast_to<PhysicalBone3D>(p_node);
  196. if (pb) {
  197. pb->set_simulate_physics(false);
  198. }
  199. }
  200. void PhysicalBoneSimulator3D::physical_bones_stop_simulation() {
  201. simulating = false;
  202. _reset_physical_bones_state();
  203. #ifndef DISABLE_DEPRECATED
  204. if (is_compat) {
  205. Skeleton3D *sk = get_skeleton();
  206. if (sk) {
  207. _pb_stop_simulation_compat(sk);
  208. }
  209. } else {
  210. _pb_stop_simulation(this);
  211. }
  212. #else
  213. _pb_stop_simulation(this);
  214. #endif // _DISABLE_DEPRECATED
  215. }
  216. #ifndef DISABLE_DEPRECATED
  217. void _pb_start_simulation_compat(const PhysicalBoneSimulator3D *p_simulator, Node *p_node, const Vector<int> &p_sim_bones) {
  218. PhysicalBoneSimulator3D *ps = Object::cast_to<PhysicalBoneSimulator3D>(p_node);
  219. if (ps) {
  220. return; // Prevent conflict.
  221. }
  222. for (int i = p_node->get_child_count() - 1; i >= 0; --i) {
  223. _pb_start_simulation_compat(p_simulator, p_node->get_child(i), p_sim_bones);
  224. }
  225. PhysicalBone3D *pb = Object::cast_to<PhysicalBone3D>(p_node);
  226. if (pb) {
  227. if (p_sim_bones.is_empty()) { // If no bones are specified, activate ragdoll on full body.
  228. pb->set_simulate_physics(true);
  229. } else {
  230. for (int i = p_sim_bones.size() - 1; i >= 0; --i) {
  231. if (p_sim_bones[i] == pb->get_bone_id() || p_simulator->is_bone_parent_of(pb->get_bone_id(), p_sim_bones[i])) {
  232. pb->set_simulate_physics(true);
  233. break;
  234. }
  235. }
  236. }
  237. }
  238. }
  239. #endif // _DISABLE_DEPRECATED
  240. void _pb_start_simulation(const PhysicalBoneSimulator3D *p_simulator, Node *p_node, const Vector<int> &p_sim_bones) {
  241. for (int i = p_node->get_child_count() - 1; i >= 0; --i) {
  242. PhysicalBone3D *pb = Object::cast_to<PhysicalBone3D>(p_node->get_child(i));
  243. if (!pb) {
  244. continue;
  245. }
  246. _pb_start_simulation(p_simulator, pb, p_sim_bones);
  247. }
  248. PhysicalBone3D *pb = Object::cast_to<PhysicalBone3D>(p_node);
  249. if (pb) {
  250. if (p_sim_bones.is_empty()) { // If no bones are specified, activate ragdoll on full body.
  251. pb->set_simulate_physics(true);
  252. } else {
  253. for (int i = p_sim_bones.size() - 1; i >= 0; --i) {
  254. if (p_sim_bones[i] == pb->get_bone_id() || p_simulator->is_bone_parent_of(pb->get_bone_id(), p_sim_bones[i])) {
  255. pb->set_simulate_physics(true);
  256. break;
  257. }
  258. }
  259. }
  260. }
  261. }
  262. void PhysicalBoneSimulator3D::physical_bones_start_simulation_on(const TypedArray<StringName> &p_bones) {
  263. _pose_updated();
  264. simulating = true;
  265. _reset_physical_bones_state();
  266. Vector<int> sim_bones;
  267. if (p_bones.size() > 0) {
  268. sim_bones.resize(p_bones.size());
  269. int c = 0;
  270. for (int i = sim_bones.size() - 1; i >= 0; --i) {
  271. int bone_id = find_bone(p_bones[i]);
  272. if (bone_id != -1) {
  273. sim_bones.write[c++] = bone_id;
  274. }
  275. }
  276. sim_bones.resize(c);
  277. }
  278. #ifndef DISABLE_DEPRECATED
  279. if (is_compat) {
  280. Skeleton3D *sk = get_skeleton();
  281. if (sk) {
  282. _pb_start_simulation_compat(this, sk, sim_bones);
  283. }
  284. } else {
  285. _pb_start_simulation(this, this, sim_bones);
  286. }
  287. #else
  288. _pb_start_simulation(this, this, sim_bones);
  289. #endif // _DISABLE_DEPRECATED
  290. }
  291. void _physical_bones_add_remove_collision_exception(bool p_add, Node *p_node, RID p_exception) {
  292. for (int i = p_node->get_child_count() - 1; i >= 0; --i) {
  293. _physical_bones_add_remove_collision_exception(p_add, p_node->get_child(i), p_exception);
  294. }
  295. CollisionObject3D *co = Object::cast_to<CollisionObject3D>(p_node);
  296. if (co) {
  297. if (p_add) {
  298. PhysicsServer3D::get_singleton()->body_add_collision_exception(co->get_rid(), p_exception);
  299. } else {
  300. PhysicsServer3D::get_singleton()->body_remove_collision_exception(co->get_rid(), p_exception);
  301. }
  302. }
  303. }
  304. void PhysicalBoneSimulator3D::physical_bones_add_collision_exception(RID p_exception) {
  305. _physical_bones_add_remove_collision_exception(true, this, p_exception);
  306. }
  307. void PhysicalBoneSimulator3D::physical_bones_remove_collision_exception(RID p_exception) {
  308. _physical_bones_add_remove_collision_exception(false, this, p_exception);
  309. }
  310. Transform3D PhysicalBoneSimulator3D::get_bone_global_pose(int p_bone) const {
  311. const int bone_size = bones.size();
  312. ERR_FAIL_INDEX_V(p_bone, bone_size, Transform3D());
  313. return bones[p_bone].global_pose;
  314. }
  315. void PhysicalBoneSimulator3D::set_bone_global_pose(int p_bone, const Transform3D &p_pose) {
  316. const int bone_size = bones.size();
  317. ERR_FAIL_INDEX(p_bone, bone_size);
  318. bones.write[p_bone].global_pose = p_pose;
  319. }
  320. void PhysicalBoneSimulator3D::_process_modification() {
  321. Skeleton3D *skeleton = get_skeleton();
  322. if (!skeleton) {
  323. return;
  324. }
  325. ERR_FAIL_COND(skeleton->get_bone_count() != bones.size());
  326. for (int i = 0; i < skeleton->get_bone_count(); i++) {
  327. if (!bones[i].physical_bone) {
  328. continue;
  329. }
  330. if (bones[i].physical_bone->is_simulating_physics() == false) {
  331. _bone_pose_updated(skeleton, i);
  332. bones[i].physical_bone->reset_to_rest_position();
  333. } else if (simulating) {
  334. skeleton->set_bone_global_pose(i, bones[i].global_pose);
  335. }
  336. }
  337. }
  338. void PhysicalBoneSimulator3D::_bind_methods() {
  339. ClassDB::bind_method(D_METHOD("is_simulating_physics"), &PhysicalBoneSimulator3D::is_simulating_physics);
  340. ClassDB::bind_method(D_METHOD("physical_bones_stop_simulation"), &PhysicalBoneSimulator3D::physical_bones_stop_simulation);
  341. ClassDB::bind_method(D_METHOD("physical_bones_start_simulation", "bones"), &PhysicalBoneSimulator3D::physical_bones_start_simulation_on, DEFVAL(Array()));
  342. ClassDB::bind_method(D_METHOD("physical_bones_add_collision_exception", "exception"), &PhysicalBoneSimulator3D::physical_bones_add_collision_exception);
  343. ClassDB::bind_method(D_METHOD("physical_bones_remove_collision_exception", "exception"), &PhysicalBoneSimulator3D::physical_bones_remove_collision_exception);
  344. }
  345. PhysicalBoneSimulator3D::PhysicalBoneSimulator3D() {
  346. }