skeleton_modification_3d_twoboneik.cpp 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617
  1. /*************************************************************************/
  2. /* skeleton_modification_3d_twoboneik.cpp */
  3. /*************************************************************************/
  4. /* This file is part of: */
  5. /* GODOT ENGINE */
  6. /* https://godotengine.org */
  7. /*************************************************************************/
  8. /* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
  9. /* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
  10. /* */
  11. /* Permission is hereby granted, free of charge, to any person obtaining */
  12. /* a copy of this software and associated documentation files (the */
  13. /* "Software"), to deal in the Software without restriction, including */
  14. /* without limitation the rights to use, copy, modify, merge, publish, */
  15. /* distribute, sublicense, and/or sell copies of the Software, and to */
  16. /* permit persons to whom the Software is furnished to do so, subject to */
  17. /* the following conditions: */
  18. /* */
  19. /* The above copyright notice and this permission notice shall be */
  20. /* included in all copies or substantial portions of the Software. */
  21. /* */
  22. /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
  23. /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
  24. /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
  25. /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
  26. /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
  27. /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
  28. /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
  29. /*************************************************************************/
  30. #include "scene/resources/skeleton_modification_3d_twoboneik.h"
  31. #include "scene/3d/skeleton_3d.h"
  32. #include "scene/resources/skeleton_modification_3d.h"
  33. bool SkeletonModification3DTwoBoneIK::_set(const StringName &p_path, const Variant &p_value) {
  34. String path = p_path;
  35. if (path == "use_tip_node") {
  36. set_use_tip_node(p_value);
  37. } else if (path == "tip_node") {
  38. set_tip_node(p_value);
  39. } else if (path == "auto_calculate_joint_length") {
  40. set_auto_calculate_joint_length(p_value);
  41. } else if (path == "use_pole_node") {
  42. set_use_pole_node(p_value);
  43. } else if (path == "pole_node") {
  44. set_pole_node(p_value);
  45. } else if (path == "joint_one_length") {
  46. set_joint_one_length(p_value);
  47. } else if (path == "joint_two_length") {
  48. set_joint_two_length(p_value);
  49. } else if (path == "joint_one/bone_name") {
  50. set_joint_one_bone_name(p_value);
  51. } else if (path == "joint_one/bone_idx") {
  52. set_joint_one_bone_idx(p_value);
  53. } else if (path == "joint_one/roll") {
  54. set_joint_one_roll(Math::deg_to_rad(real_t(p_value)));
  55. } else if (path == "joint_two/bone_name") {
  56. set_joint_two_bone_name(p_value);
  57. } else if (path == "joint_two/bone_idx") {
  58. set_joint_two_bone_idx(p_value);
  59. } else if (path == "joint_two/roll") {
  60. set_joint_two_roll(Math::deg_to_rad(real_t(p_value)));
  61. }
  62. return true;
  63. }
  64. bool SkeletonModification3DTwoBoneIK::_get(const StringName &p_path, Variant &r_ret) const {
  65. String path = p_path;
  66. if (path == "use_tip_node") {
  67. r_ret = get_use_tip_node();
  68. } else if (path == "tip_node") {
  69. r_ret = get_tip_node();
  70. } else if (path == "auto_calculate_joint_length") {
  71. r_ret = get_auto_calculate_joint_length();
  72. } else if (path == "use_pole_node") {
  73. r_ret = get_use_pole_node();
  74. } else if (path == "pole_node") {
  75. r_ret = get_pole_node();
  76. } else if (path == "joint_one_length") {
  77. r_ret = get_joint_one_length();
  78. } else if (path == "joint_two_length") {
  79. r_ret = get_joint_two_length();
  80. } else if (path == "joint_one/bone_name") {
  81. r_ret = get_joint_one_bone_name();
  82. } else if (path == "joint_one/bone_idx") {
  83. r_ret = get_joint_one_bone_idx();
  84. } else if (path == "joint_one/roll") {
  85. r_ret = Math::rad_to_deg(get_joint_one_roll());
  86. } else if (path == "joint_two/bone_name") {
  87. r_ret = get_joint_two_bone_name();
  88. } else if (path == "joint_two/bone_idx") {
  89. r_ret = get_joint_two_bone_idx();
  90. } else if (path == "joint_two/roll") {
  91. r_ret = Math::rad_to_deg(get_joint_two_roll());
  92. }
  93. return true;
  94. }
  95. void SkeletonModification3DTwoBoneIK::_get_property_list(List<PropertyInfo> *p_list) const {
  96. p_list->push_back(PropertyInfo(Variant::BOOL, "use_tip_node", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT));
  97. if (use_tip_node) {
  98. p_list->push_back(PropertyInfo(Variant::NODE_PATH, "tip_node", PROPERTY_HINT_NODE_PATH_VALID_TYPES, "Node3D", PROPERTY_USAGE_DEFAULT));
  99. }
  100. p_list->push_back(PropertyInfo(Variant::BOOL, "auto_calculate_joint_length", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT));
  101. if (!auto_calculate_joint_length) {
  102. p_list->push_back(PropertyInfo(Variant::FLOAT, "joint_one_length", PROPERTY_HINT_RANGE, "-1, 10000, 0.001", PROPERTY_USAGE_DEFAULT));
  103. p_list->push_back(PropertyInfo(Variant::FLOAT, "joint_two_length", PROPERTY_HINT_RANGE, "-1, 10000, 0.001", PROPERTY_USAGE_DEFAULT));
  104. }
  105. p_list->push_back(PropertyInfo(Variant::BOOL, "use_pole_node", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT));
  106. if (use_pole_node) {
  107. p_list->push_back(PropertyInfo(Variant::NODE_PATH, "pole_node", PROPERTY_HINT_NODE_PATH_VALID_TYPES, "Node3D", PROPERTY_USAGE_DEFAULT));
  108. }
  109. p_list->push_back(PropertyInfo(Variant::STRING_NAME, "joint_one/bone_name", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT));
  110. p_list->push_back(PropertyInfo(Variant::INT, "joint_one/bone_idx", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT));
  111. p_list->push_back(PropertyInfo(Variant::FLOAT, "joint_one/roll", PROPERTY_HINT_RANGE, "-360, 360, 0.01", PROPERTY_USAGE_DEFAULT));
  112. p_list->push_back(PropertyInfo(Variant::STRING_NAME, "joint_two/bone_name", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT));
  113. p_list->push_back(PropertyInfo(Variant::INT, "joint_two/bone_idx", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT));
  114. p_list->push_back(PropertyInfo(Variant::FLOAT, "joint_two/roll", PROPERTY_HINT_RANGE, "-360, 360, 0.01", PROPERTY_USAGE_DEFAULT));
  115. }
  116. void SkeletonModification3DTwoBoneIK::_execute(real_t p_delta) {
  117. ERR_FAIL_COND_MSG(!stack || !is_setup || stack->skeleton == nullptr,
  118. "Modification is not setup and therefore cannot execute!");
  119. if (!enabled) {
  120. return;
  121. }
  122. if (_print_execution_error(joint_one_bone_idx < 0 || joint_two_bone_idx < 0,
  123. "One (or more) of the bones in the modification have invalid bone indexes. Cannot execute modification!")) {
  124. return;
  125. }
  126. if (target_node_cache.is_null()) {
  127. _print_execution_error(true, "Target cache is out of date. Attempting to update...");
  128. update_cache_target();
  129. return;
  130. }
  131. // Update joint lengths (if needed)
  132. if (auto_calculate_joint_length && (joint_one_length < 0 || joint_two_length < 0)) {
  133. calculate_joint_lengths();
  134. }
  135. // Adopted from the links below:
  136. // http://theorangeduck.com/page/simple-two-joint
  137. // https://www.alanzucconi.com/2018/05/02/ik-2d-2/
  138. // With modifications by TwistedTwigleg
  139. Node3D *target = Object::cast_to<Node3D>(ObjectDB::get_instance(target_node_cache));
  140. if (_print_execution_error(!target || !target->is_inside_tree(), "Target node is not in the scene tree. Cannot execute modification!")) {
  141. return;
  142. }
  143. Transform3D target_trans = stack->skeleton->world_transform_to_global_pose(target->get_global_transform());
  144. Transform3D bone_one_trans;
  145. Transform3D bone_two_trans;
  146. // Make the first joint look at the pole, and the second look at the target. That way, the
  147. // TwoBoneIK solver has to really only handle extension/contraction, which should make it align with the pole.
  148. if (use_pole_node) {
  149. if (pole_node_cache.is_null()) {
  150. _print_execution_error(true, "Pole cache is out of date. Attempting to update...");
  151. update_cache_pole();
  152. return;
  153. }
  154. Node3D *pole = Object::cast_to<Node3D>(ObjectDB::get_instance(pole_node_cache));
  155. if (_print_execution_error(!pole || !pole->is_inside_tree(), "Pole node is not in the scene tree. Cannot execute modification!")) {
  156. return;
  157. }
  158. Transform3D pole_trans = stack->skeleton->world_transform_to_global_pose(pole->get_global_transform());
  159. Transform3D bone_one_local_pos = stack->skeleton->get_bone_local_pose_override(joint_one_bone_idx);
  160. if (bone_one_local_pos == Transform3D()) {
  161. bone_one_local_pos = stack->skeleton->get_bone_pose(joint_one_bone_idx);
  162. }
  163. Transform3D bone_two_local_pos = stack->skeleton->get_bone_local_pose_override(joint_two_bone_idx);
  164. if (bone_two_local_pos == Transform3D()) {
  165. bone_two_local_pos = stack->skeleton->get_bone_pose(joint_two_bone_idx);
  166. }
  167. bone_one_trans = stack->skeleton->local_pose_to_global_pose(joint_one_bone_idx, bone_one_local_pos);
  168. bone_one_trans = bone_one_trans.looking_at(pole_trans.origin, Vector3(0, 1, 0));
  169. bone_one_trans.basis = stack->skeleton->global_pose_z_forward_to_bone_forward(joint_one_bone_idx, bone_one_trans.basis);
  170. stack->skeleton->update_bone_rest_forward_vector(joint_one_bone_idx);
  171. bone_one_trans.basis.rotate_local(stack->skeleton->get_bone_axis_forward_vector(joint_one_bone_idx), joint_one_roll);
  172. stack->skeleton->set_bone_local_pose_override(joint_one_bone_idx, stack->skeleton->global_pose_to_local_pose(joint_one_bone_idx, bone_one_trans), stack->strength, true);
  173. stack->skeleton->force_update_bone_children_transforms(joint_one_bone_idx);
  174. bone_two_trans = stack->skeleton->local_pose_to_global_pose(joint_two_bone_idx, bone_two_local_pos);
  175. bone_two_trans = bone_two_trans.looking_at(target_trans.origin, Vector3(0, 1, 0));
  176. bone_two_trans.basis = stack->skeleton->global_pose_z_forward_to_bone_forward(joint_two_bone_idx, bone_two_trans.basis);
  177. stack->skeleton->update_bone_rest_forward_vector(joint_two_bone_idx);
  178. bone_two_trans.basis.rotate_local(stack->skeleton->get_bone_axis_forward_vector(joint_two_bone_idx), joint_two_roll);
  179. stack->skeleton->set_bone_local_pose_override(joint_two_bone_idx, stack->skeleton->global_pose_to_local_pose(joint_two_bone_idx, bone_two_trans), stack->strength, true);
  180. stack->skeleton->force_update_bone_children_transforms(joint_two_bone_idx);
  181. } else {
  182. Transform3D bone_one_local_pos = stack->skeleton->get_bone_local_pose_override(joint_one_bone_idx);
  183. if (bone_one_local_pos == Transform3D()) {
  184. bone_one_local_pos = stack->skeleton->get_bone_pose(joint_one_bone_idx);
  185. }
  186. Transform3D bone_two_local_pos = stack->skeleton->get_bone_local_pose_override(joint_two_bone_idx);
  187. if (bone_two_local_pos == Transform3D()) {
  188. bone_two_local_pos = stack->skeleton->get_bone_pose(joint_two_bone_idx);
  189. }
  190. bone_one_trans = stack->skeleton->local_pose_to_global_pose(joint_one_bone_idx, bone_one_local_pos);
  191. bone_two_trans = stack->skeleton->local_pose_to_global_pose(joint_two_bone_idx, bone_two_local_pos);
  192. }
  193. Transform3D bone_two_tip_trans;
  194. if (use_tip_node) {
  195. if (tip_node_cache.is_null()) {
  196. _print_execution_error(true, "Tip cache is out of date. Attempting to update...");
  197. update_cache_tip();
  198. return;
  199. }
  200. Node3D *tip = Object::cast_to<Node3D>(ObjectDB::get_instance(tip_node_cache));
  201. if (_print_execution_error(!tip || !tip->is_inside_tree(), "Tip node is not in the scene tree. Cannot execute modification!")) {
  202. return;
  203. }
  204. bone_two_tip_trans = stack->skeleton->world_transform_to_global_pose(tip->get_global_transform());
  205. } else {
  206. stack->skeleton->update_bone_rest_forward_vector(joint_two_bone_idx);
  207. bone_two_tip_trans = bone_two_trans;
  208. bone_two_tip_trans.origin += bone_two_trans.basis.xform(stack->skeleton->get_bone_axis_forward_vector(joint_two_bone_idx)).normalized() * joint_two_length;
  209. }
  210. real_t joint_one_to_target_length = bone_one_trans.origin.distance_to(target_trans.origin);
  211. if (joint_one_length + joint_two_length < joint_one_to_target_length) {
  212. // Set the target *just* out of reach to straighten the bones
  213. joint_one_to_target_length = joint_one_length + joint_two_length + 0.01;
  214. } else if (joint_one_to_target_length < joint_one_length) {
  215. // Place the target in reach so the solver doesn't do crazy things
  216. joint_one_to_target_length = joint_one_length;
  217. }
  218. // Get the square lengths for all three sides of the triangle we'll use to calculate the angles
  219. real_t sqr_one_length = joint_one_length * joint_one_length;
  220. real_t sqr_two_length = joint_two_length * joint_two_length;
  221. real_t sqr_three_length = joint_one_to_target_length * joint_one_to_target_length;
  222. // Calculate the angles for the first joint using the law of cosigns
  223. real_t ac_ab_0 = Math::acos(CLAMP(bone_two_tip_trans.origin.direction_to(bone_one_trans.origin).dot(bone_two_trans.origin.direction_to(bone_one_trans.origin)), -1, 1));
  224. real_t ac_at_0 = Math::acos(CLAMP(bone_one_trans.origin.direction_to(bone_two_tip_trans.origin).dot(bone_one_trans.origin.direction_to(target_trans.origin)), -1, 1));
  225. real_t ac_ab_1 = Math::acos(CLAMP((sqr_two_length - sqr_one_length - sqr_three_length) / (-2.0 * joint_one_length * joint_one_to_target_length), -1, 1));
  226. // Calculate the angles of rotation. Angle 0 is the extension/contraction axis, while angle 1 is the rotation axis to align the triangle to the target
  227. Vector3 axis_0 = bone_one_trans.origin.direction_to(bone_two_tip_trans.origin).cross(bone_one_trans.origin.direction_to(bone_two_trans.origin));
  228. Vector3 axis_1 = bone_one_trans.origin.direction_to(bone_two_tip_trans.origin).cross(bone_one_trans.origin.direction_to(target_trans.origin));
  229. // Make a quaternion with the delta rotation needed to rotate the first joint into alignment and apply it to the transform.
  230. Quaternion bone_one_quat = bone_one_trans.basis.get_rotation_quaternion();
  231. Quaternion rot_0 = Quaternion(bone_one_quat.inverse().xform(axis_0).normalized(), (ac_ab_1 - ac_ab_0));
  232. Quaternion rot_2 = Quaternion(bone_one_quat.inverse().xform(axis_1).normalized(), ac_at_0);
  233. bone_one_trans.basis.set_quaternion(bone_one_quat * (rot_0 * rot_2));
  234. stack->skeleton->update_bone_rest_forward_vector(joint_one_bone_idx);
  235. bone_one_trans.basis.rotate_local(stack->skeleton->get_bone_axis_forward_vector(joint_one_bone_idx), joint_one_roll);
  236. // Apply the rotation to the first joint
  237. bone_one_trans = stack->skeleton->global_pose_to_local_pose(joint_one_bone_idx, bone_one_trans);
  238. bone_one_trans.origin = Vector3(0, 0, 0);
  239. stack->skeleton->set_bone_local_pose_override(joint_one_bone_idx, bone_one_trans, stack->strength, true);
  240. stack->skeleton->force_update_bone_children_transforms(joint_one_bone_idx);
  241. if (use_pole_node) {
  242. // Update bone_two_trans so its at the latest position, with the rotation of bone_one_trans taken into account, then look at the target.
  243. bone_two_trans = stack->skeleton->local_pose_to_global_pose(joint_two_bone_idx, stack->skeleton->get_bone_local_pose_override(joint_two_bone_idx));
  244. stack->skeleton->update_bone_rest_forward_vector(joint_two_bone_idx);
  245. Vector3 forward_vector = stack->skeleton->get_bone_axis_forward_vector(joint_two_bone_idx);
  246. bone_two_trans.basis.rotate_to_align(forward_vector, bone_two_trans.origin.direction_to(target_trans.origin));
  247. stack->skeleton->update_bone_rest_forward_vector(joint_two_bone_idx);
  248. bone_two_trans.basis.rotate_local(stack->skeleton->get_bone_axis_forward_vector(joint_two_bone_idx), joint_two_roll);
  249. bone_two_trans = stack->skeleton->global_pose_to_local_pose(joint_two_bone_idx, bone_two_trans);
  250. stack->skeleton->set_bone_local_pose_override(joint_two_bone_idx, bone_two_trans, stack->strength, true);
  251. stack->skeleton->force_update_bone_children_transforms(joint_two_bone_idx);
  252. } else {
  253. // Calculate the angles for the second joint using the law of cosigns, make a quaternion with the delta rotation needed to rotate the joint into
  254. // alignment, and then apply it to the second joint.
  255. real_t ba_bc_0 = Math::acos(CLAMP(bone_two_trans.origin.direction_to(bone_one_trans.origin).dot(bone_two_trans.origin.direction_to(bone_two_tip_trans.origin)), -1, 1));
  256. real_t ba_bc_1 = Math::acos(CLAMP((sqr_three_length - sqr_one_length - sqr_two_length) / (-2.0 * joint_one_length * joint_two_length), -1, 1));
  257. Quaternion bone_two_quat = bone_two_trans.basis.get_rotation_quaternion();
  258. Quaternion rot_1 = Quaternion(bone_two_quat.inverse().xform(axis_0).normalized(), (ba_bc_1 - ba_bc_0));
  259. bone_two_trans.basis.set_quaternion(bone_two_quat * rot_1);
  260. stack->skeleton->update_bone_rest_forward_vector(joint_two_bone_idx);
  261. bone_two_trans.basis.rotate_local(stack->skeleton->get_bone_axis_forward_vector(joint_two_bone_idx), joint_two_roll);
  262. bone_two_trans = stack->skeleton->global_pose_to_local_pose(joint_two_bone_idx, bone_two_trans);
  263. bone_two_trans.origin = Vector3(0, 0, 0);
  264. stack->skeleton->set_bone_local_pose_override(joint_two_bone_idx, bone_two_trans, stack->strength, true);
  265. stack->skeleton->force_update_bone_children_transforms(joint_two_bone_idx);
  266. }
  267. }
  268. void SkeletonModification3DTwoBoneIK::_setup_modification(SkeletonModificationStack3D *p_stack) {
  269. stack = p_stack;
  270. if (stack != nullptr) {
  271. is_setup = true;
  272. execution_error_found = false;
  273. update_cache_target();
  274. update_cache_tip();
  275. }
  276. }
  277. void SkeletonModification3DTwoBoneIK::update_cache_target() {
  278. if (!is_setup || !stack) {
  279. _print_execution_error(true, "Cannot update target cache: modification is not properly setup!");
  280. return;
  281. }
  282. target_node_cache = ObjectID();
  283. if (stack->skeleton) {
  284. if (stack->skeleton->is_inside_tree() && target_node.is_empty() == false) {
  285. if (stack->skeleton->has_node(target_node)) {
  286. Node *node = stack->skeleton->get_node(target_node);
  287. ERR_FAIL_COND_MSG(!node || stack->skeleton == node,
  288. "Cannot update target cache: Target node is this modification's skeleton or cannot be found. Cannot execute modification");
  289. ERR_FAIL_COND_MSG(!node->is_inside_tree(),
  290. "Cannot update target cache: Target node is not in the scene tree. Cannot execute modification!");
  291. target_node_cache = node->get_instance_id();
  292. execution_error_found = false;
  293. }
  294. }
  295. }
  296. }
  297. void SkeletonModification3DTwoBoneIK::update_cache_tip() {
  298. if (!is_setup || !stack) {
  299. _print_execution_error(true, "Cannot update tip cache: modification is not properly setup!");
  300. return;
  301. }
  302. tip_node_cache = ObjectID();
  303. if (stack->skeleton) {
  304. if (stack->skeleton->is_inside_tree()) {
  305. if (stack->skeleton->has_node(tip_node)) {
  306. Node *node = stack->skeleton->get_node(tip_node);
  307. ERR_FAIL_COND_MSG(!node || stack->skeleton == node,
  308. "Cannot update tip cache: Tip node is this modification's skeleton or cannot be found!");
  309. ERR_FAIL_COND_MSG(!node->is_inside_tree(),
  310. "Cannot update tip cache: Tip node is not in the scene tree. Cannot execute modification!");
  311. tip_node_cache = node->get_instance_id();
  312. execution_error_found = false;
  313. }
  314. }
  315. }
  316. }
  317. void SkeletonModification3DTwoBoneIK::update_cache_pole() {
  318. if (!is_setup || !stack) {
  319. _print_execution_error(true, "Cannot update pole cache: modification is not properly setup!");
  320. return;
  321. }
  322. pole_node_cache = ObjectID();
  323. if (stack->skeleton) {
  324. if (stack->skeleton->is_inside_tree()) {
  325. if (stack->skeleton->has_node(pole_node)) {
  326. Node *node = stack->skeleton->get_node(pole_node);
  327. ERR_FAIL_COND_MSG(!node || stack->skeleton == node,
  328. "Cannot update pole cache: Pole node is this modification's skeleton or cannot be found!");
  329. ERR_FAIL_COND_MSG(!node->is_inside_tree(),
  330. "Cannot update pole cache: Pole node is not in the scene tree. Cannot execute modification!");
  331. pole_node_cache = node->get_instance_id();
  332. execution_error_found = false;
  333. }
  334. }
  335. }
  336. }
  337. void SkeletonModification3DTwoBoneIK::set_target_node(const NodePath &p_target_node) {
  338. target_node = p_target_node;
  339. update_cache_target();
  340. }
  341. NodePath SkeletonModification3DTwoBoneIK::get_target_node() const {
  342. return target_node;
  343. }
  344. void SkeletonModification3DTwoBoneIK::set_use_tip_node(const bool p_use_tip_node) {
  345. use_tip_node = p_use_tip_node;
  346. notify_property_list_changed();
  347. }
  348. bool SkeletonModification3DTwoBoneIK::get_use_tip_node() const {
  349. return use_tip_node;
  350. }
  351. void SkeletonModification3DTwoBoneIK::set_tip_node(const NodePath &p_tip_node) {
  352. tip_node = p_tip_node;
  353. update_cache_tip();
  354. }
  355. NodePath SkeletonModification3DTwoBoneIK::get_tip_node() const {
  356. return tip_node;
  357. }
  358. void SkeletonModification3DTwoBoneIK::set_use_pole_node(const bool p_use_pole_node) {
  359. use_pole_node = p_use_pole_node;
  360. notify_property_list_changed();
  361. }
  362. bool SkeletonModification3DTwoBoneIK::get_use_pole_node() const {
  363. return use_pole_node;
  364. }
  365. void SkeletonModification3DTwoBoneIK::set_pole_node(const NodePath &p_pole_node) {
  366. pole_node = p_pole_node;
  367. update_cache_pole();
  368. }
  369. NodePath SkeletonModification3DTwoBoneIK::get_pole_node() const {
  370. return pole_node;
  371. }
  372. void SkeletonModification3DTwoBoneIK::set_auto_calculate_joint_length(bool p_calculate) {
  373. auto_calculate_joint_length = p_calculate;
  374. if (p_calculate) {
  375. calculate_joint_lengths();
  376. }
  377. notify_property_list_changed();
  378. }
  379. bool SkeletonModification3DTwoBoneIK::get_auto_calculate_joint_length() const {
  380. return auto_calculate_joint_length;
  381. }
  382. void SkeletonModification3DTwoBoneIK::calculate_joint_lengths() {
  383. if (!is_setup) {
  384. return; // fail silently, as we likely just loaded the scene.
  385. }
  386. ERR_FAIL_COND_MSG(!stack || stack->skeleton == nullptr,
  387. "Modification is not setup and therefore cannot calculate joint lengths!");
  388. ERR_FAIL_COND_MSG(joint_one_bone_idx <= -1 || joint_two_bone_idx <= -1,
  389. "One of the bones in the TwoBoneIK modification are not set! Cannot calculate joint lengths!");
  390. Transform3D bone_one_rest_trans = stack->skeleton->get_bone_global_pose(joint_one_bone_idx);
  391. Transform3D bone_two_rest_trans = stack->skeleton->get_bone_global_pose(joint_two_bone_idx);
  392. joint_one_length = bone_one_rest_trans.origin.distance_to(bone_two_rest_trans.origin);
  393. if (use_tip_node) {
  394. if (tip_node_cache.is_null()) {
  395. update_cache_tip();
  396. WARN_PRINT("Tip cache is out of date. Updating...");
  397. }
  398. Node3D *tip = Object::cast_to<Node3D>(ObjectDB::get_instance(tip_node_cache));
  399. if (tip) {
  400. Transform3D bone_tip_trans = stack->skeleton->world_transform_to_global_pose(tip->get_global_transform());
  401. joint_two_length = bone_two_rest_trans.origin.distance_to(bone_tip_trans.origin);
  402. }
  403. } else {
  404. // Attempt to use children bones to get the length
  405. Vector<int> bone_two_children = stack->skeleton->get_bone_children(joint_two_bone_idx);
  406. if (bone_two_children.size() > 0) {
  407. joint_two_length = 0;
  408. for (int i = 0; i < bone_two_children.size(); i++) {
  409. joint_two_length += bone_two_rest_trans.origin.distance_to(
  410. stack->skeleton->get_bone_global_pose(bone_two_children[i]).origin);
  411. }
  412. joint_two_length = joint_two_length / bone_two_children.size();
  413. } else {
  414. WARN_PRINT("TwoBoneIK modification: Cannot auto calculate length for joint 2! Auto setting the length to 1...");
  415. joint_two_length = 1.0;
  416. }
  417. }
  418. execution_error_found = false;
  419. }
  420. void SkeletonModification3DTwoBoneIK::set_joint_one_bone_name(String p_bone_name) {
  421. joint_one_bone_name = p_bone_name;
  422. if (stack && stack->skeleton) {
  423. joint_one_bone_idx = stack->skeleton->find_bone(p_bone_name);
  424. }
  425. execution_error_found = false;
  426. notify_property_list_changed();
  427. }
  428. String SkeletonModification3DTwoBoneIK::get_joint_one_bone_name() const {
  429. return joint_one_bone_name;
  430. }
  431. void SkeletonModification3DTwoBoneIK::set_joint_one_bone_idx(int p_bone_idx) {
  432. joint_one_bone_idx = p_bone_idx;
  433. if (stack && stack->skeleton) {
  434. joint_one_bone_name = stack->skeleton->get_bone_name(p_bone_idx);
  435. }
  436. execution_error_found = false;
  437. notify_property_list_changed();
  438. }
  439. int SkeletonModification3DTwoBoneIK::get_joint_one_bone_idx() const {
  440. return joint_one_bone_idx;
  441. }
  442. void SkeletonModification3DTwoBoneIK::set_joint_one_length(real_t p_length) {
  443. joint_one_length = p_length;
  444. }
  445. real_t SkeletonModification3DTwoBoneIK::get_joint_one_length() const {
  446. return joint_one_length;
  447. }
  448. void SkeletonModification3DTwoBoneIK::set_joint_two_bone_name(String p_bone_name) {
  449. joint_two_bone_name = p_bone_name;
  450. if (stack && stack->skeleton) {
  451. joint_two_bone_idx = stack->skeleton->find_bone(p_bone_name);
  452. }
  453. execution_error_found = false;
  454. notify_property_list_changed();
  455. }
  456. String SkeletonModification3DTwoBoneIK::get_joint_two_bone_name() const {
  457. return joint_two_bone_name;
  458. }
  459. void SkeletonModification3DTwoBoneIK::set_joint_two_bone_idx(int p_bone_idx) {
  460. joint_two_bone_idx = p_bone_idx;
  461. if (stack && stack->skeleton) {
  462. joint_two_bone_name = stack->skeleton->get_bone_name(p_bone_idx);
  463. }
  464. execution_error_found = false;
  465. notify_property_list_changed();
  466. }
  467. int SkeletonModification3DTwoBoneIK::get_joint_two_bone_idx() const {
  468. return joint_two_bone_idx;
  469. }
  470. void SkeletonModification3DTwoBoneIK::set_joint_two_length(real_t p_length) {
  471. joint_two_length = p_length;
  472. }
  473. real_t SkeletonModification3DTwoBoneIK::get_joint_two_length() const {
  474. return joint_two_length;
  475. }
  476. void SkeletonModification3DTwoBoneIK::set_joint_one_roll(real_t p_roll) {
  477. joint_one_roll = p_roll;
  478. }
  479. real_t SkeletonModification3DTwoBoneIK::get_joint_one_roll() const {
  480. return joint_one_roll;
  481. }
  482. void SkeletonModification3DTwoBoneIK::set_joint_two_roll(real_t p_roll) {
  483. joint_two_roll = p_roll;
  484. }
  485. real_t SkeletonModification3DTwoBoneIK::get_joint_two_roll() const {
  486. return joint_two_roll;
  487. }
  488. void SkeletonModification3DTwoBoneIK::_bind_methods() {
  489. ClassDB::bind_method(D_METHOD("set_target_node", "target_nodepath"), &SkeletonModification3DTwoBoneIK::set_target_node);
  490. ClassDB::bind_method(D_METHOD("get_target_node"), &SkeletonModification3DTwoBoneIK::get_target_node);
  491. ClassDB::bind_method(D_METHOD("set_use_pole_node", "use_pole_node"), &SkeletonModification3DTwoBoneIK::set_use_pole_node);
  492. ClassDB::bind_method(D_METHOD("get_use_pole_node"), &SkeletonModification3DTwoBoneIK::get_use_pole_node);
  493. ClassDB::bind_method(D_METHOD("set_pole_node", "pole_nodepath"), &SkeletonModification3DTwoBoneIK::set_pole_node);
  494. ClassDB::bind_method(D_METHOD("get_pole_node"), &SkeletonModification3DTwoBoneIK::get_pole_node);
  495. ClassDB::bind_method(D_METHOD("set_use_tip_node", "use_tip_node"), &SkeletonModification3DTwoBoneIK::set_use_tip_node);
  496. ClassDB::bind_method(D_METHOD("get_use_tip_node"), &SkeletonModification3DTwoBoneIK::get_use_tip_node);
  497. ClassDB::bind_method(D_METHOD("set_tip_node", "tip_nodepath"), &SkeletonModification3DTwoBoneIK::set_tip_node);
  498. ClassDB::bind_method(D_METHOD("get_tip_node"), &SkeletonModification3DTwoBoneIK::get_tip_node);
  499. ClassDB::bind_method(D_METHOD("set_auto_calculate_joint_length", "auto_calculate_joint_length"), &SkeletonModification3DTwoBoneIK::set_auto_calculate_joint_length);
  500. ClassDB::bind_method(D_METHOD("get_auto_calculate_joint_length"), &SkeletonModification3DTwoBoneIK::get_auto_calculate_joint_length);
  501. ClassDB::bind_method(D_METHOD("set_joint_one_bone_name", "bone_name"), &SkeletonModification3DTwoBoneIK::set_joint_one_bone_name);
  502. ClassDB::bind_method(D_METHOD("get_joint_one_bone_name"), &SkeletonModification3DTwoBoneIK::get_joint_one_bone_name);
  503. ClassDB::bind_method(D_METHOD("set_joint_one_bone_idx", "bone_idx"), &SkeletonModification3DTwoBoneIK::set_joint_one_bone_idx);
  504. ClassDB::bind_method(D_METHOD("get_joint_one_bone_idx"), &SkeletonModification3DTwoBoneIK::get_joint_one_bone_idx);
  505. ClassDB::bind_method(D_METHOD("set_joint_one_length", "bone_length"), &SkeletonModification3DTwoBoneIK::set_joint_one_length);
  506. ClassDB::bind_method(D_METHOD("get_joint_one_length"), &SkeletonModification3DTwoBoneIK::get_joint_one_length);
  507. ClassDB::bind_method(D_METHOD("set_joint_two_bone_name", "bone_name"), &SkeletonModification3DTwoBoneIK::set_joint_two_bone_name);
  508. ClassDB::bind_method(D_METHOD("get_joint_two_bone_name"), &SkeletonModification3DTwoBoneIK::get_joint_two_bone_name);
  509. ClassDB::bind_method(D_METHOD("set_joint_two_bone_idx", "bone_idx"), &SkeletonModification3DTwoBoneIK::set_joint_two_bone_idx);
  510. ClassDB::bind_method(D_METHOD("get_joint_two_bone_idx"), &SkeletonModification3DTwoBoneIK::get_joint_two_bone_idx);
  511. ClassDB::bind_method(D_METHOD("set_joint_two_length", "bone_length"), &SkeletonModification3DTwoBoneIK::set_joint_two_length);
  512. ClassDB::bind_method(D_METHOD("get_joint_two_length"), &SkeletonModification3DTwoBoneIK::get_joint_two_length);
  513. ClassDB::bind_method(D_METHOD("set_joint_one_roll", "roll"), &SkeletonModification3DTwoBoneIK::set_joint_one_roll);
  514. ClassDB::bind_method(D_METHOD("get_joint_one_roll"), &SkeletonModification3DTwoBoneIK::get_joint_one_roll);
  515. ClassDB::bind_method(D_METHOD("set_joint_two_roll", "roll"), &SkeletonModification3DTwoBoneIK::set_joint_two_roll);
  516. ClassDB::bind_method(D_METHOD("get_joint_two_roll"), &SkeletonModification3DTwoBoneIK::get_joint_two_roll);
  517. ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "target_nodepath", PROPERTY_HINT_NODE_PATH_VALID_TYPES, "Node3D"), "set_target_node", "get_target_node");
  518. ADD_GROUP("", "");
  519. }
  520. SkeletonModification3DTwoBoneIK::SkeletonModification3DTwoBoneIK() {
  521. stack = nullptr;
  522. is_setup = false;
  523. }
  524. SkeletonModification3DTwoBoneIK::~SkeletonModification3DTwoBoneIK() {
  525. }