diff --git a/scene/resources/2d/skeleton/skeleton_modification_2d_lookat.cpp b/scene/resources/2d/skeleton/skeleton_modification_2d_lookat.cpp index e5ce028dcc0..78335454a3f 100644 --- a/scene/resources/2d/skeleton/skeleton_modification_2d_lookat.cpp +++ b/scene/resources/2d/skeleton/skeleton_modification_2d_lookat.cpp @@ -141,37 +141,32 @@ void SkeletonModification2DLookAt::_execute(float p_delta) { return; } - Transform2D operation_transform = operation_bone->get_global_transform(); - Transform2D target_trans = target_node_reference->get_global_transform(); + real_t angle_to_target = operation_bone->get_angle_to(target_node_reference->get_global_position()); - // Look at the target! - operation_transform = operation_transform.looking_at(target_trans.get_origin()); - // Apply whatever scale it had prior to looking_at - operation_transform.set_scale(operation_bone->get_global_scale()); - - // Account for the direction the bone faces in: - operation_transform.set_rotation(operation_transform.get_rotation() - operation_bone->get_bone_angle()); + // Account for the direction the bone faces in + angle_to_target -= operation_bone->get_bone_angle(); // Apply additional rotation - operation_transform.set_rotation(operation_transform.get_rotation() + additional_rotation); + angle_to_target += additional_rotation; - // Apply constraints in globalspace: - if (enable_constraint && !constraint_in_localspace) { - operation_transform.set_rotation(clamp_angle(operation_transform.get_rotation(), constraint_angle_min, constraint_angle_max, constraint_angle_invert)); - } + if (enable_constraint) { + real_t new_angle = angle_to_target; - // Convert from a global transform to a local transform via the Bone2D node - operation_bone->set_global_transform(operation_transform); - operation_transform = operation_bone->get_transform(); - - // Apply constraints in localspace: - if (enable_constraint && constraint_in_localspace) { - operation_transform.set_rotation(clamp_angle(operation_transform.get_rotation(), constraint_angle_min, constraint_angle_max, constraint_angle_invert)); + if (constraint_in_localspace) { + new_angle += operation_bone->get_rotation(); + new_angle = clamp_angle(new_angle, constraint_angle_min, constraint_angle_max, constraint_angle_invert); + operation_bone->set_rotation(new_angle); + } else { + new_angle += operation_bone->get_global_rotation(); + new_angle = clamp_angle(new_angle, constraint_angle_min, constraint_angle_max, constraint_angle_invert); + operation_bone->set_global_rotation(new_angle); + } + } else { + operation_bone->rotate(angle_to_target); } // Set the local pose override, and to make sure child bones are also updated, set the transform of the bone. - stack->skeleton->set_bone_local_pose_override(bone_idx, operation_transform, stack->strength, true); - operation_bone->set_transform(operation_transform); + stack->skeleton->set_bone_local_pose_override(bone_idx, operation_bone->get_transform(), stack->strength, true); } void SkeletonModification2DLookAt::_setup_modification(SkeletonModificationStack2D *p_stack) { diff --git a/scene/resources/2d/skeleton/skeleton_modification_2d_twoboneik.cpp b/scene/resources/2d/skeleton/skeleton_modification_2d_twoboneik.cpp index 8b4a6fcd095..2c60f620be8 100644 --- a/scene/resources/2d/skeleton/skeleton_modification_2d_twoboneik.cpp +++ b/scene/resources/2d/skeleton/skeleton_modification_2d_twoboneik.cpp @@ -142,7 +142,7 @@ void SkeletonModification2DTwoBoneIK::_execute(float p_delta) { return; } - // Adopted from the links below: + // Adapted from the links below: // http://theorangeduck.com/page/simple-two-joint // https://www.alanzucconi.com/2018/05/02/ik-2d-2/ // With modifications by TwistedTwigleg @@ -150,9 +150,10 @@ void SkeletonModification2DTwoBoneIK::_execute(float p_delta) { float joint_one_to_target = target_difference.length(); float angle_atan = target_difference.angle(); - float bone_one_length = joint_one_bone->get_length() * MIN(joint_one_bone->get_global_scale().x, joint_one_bone->get_global_scale().y); - float bone_two_length = joint_two_bone->get_length() * MIN(joint_two_bone->get_global_scale().x, joint_two_bone->get_global_scale().y); + float bone_one_length = joint_one_bone->get_length() * MIN(joint_one_bone->get_global_scale().abs().x, joint_one_bone->get_global_scale().abs().y); + float bone_two_length = joint_two_bone->get_length() * MIN(joint_two_bone->get_global_scale().abs().x, joint_two_bone->get_global_scale().abs().y); bool override_angles_due_to_out_of_range = false; + bool same_scale_sign = true; if (joint_one_to_target < target_minimum_distance) { joint_one_to_target = target_minimum_distance; @@ -165,6 +166,10 @@ void SkeletonModification2DTwoBoneIK::_execute(float p_delta) { override_angles_due_to_out_of_range = true; } + if (joint_one_bone->get_global_scale().sign().x != joint_one_bone->get_global_scale().sign().y) { + same_scale_sign = false; + } + if (!override_angles_due_to_out_of_range) { float angle_0 = Math::acos(((joint_one_to_target * joint_one_to_target) + (bone_one_length * bone_one_length) - (bone_two_length * bone_two_length)) / (2.0 * joint_one_to_target * bone_one_length)); float angle_1 = Math::acos(((bone_two_length * bone_two_length) + (bone_one_length * bone_one_length) - (joint_one_to_target * joint_one_to_target)) / (2.0 * bone_two_length * bone_one_length)); @@ -177,12 +182,23 @@ void SkeletonModification2DTwoBoneIK::_execute(float p_delta) { if (std::isnan(angle_0) || std::isnan(angle_1)) { // We cannot solve for this angle! Do nothing to avoid setting the rotation (and scale) to NaN. } else { - joint_one_bone->set_global_rotation(angle_atan - angle_0 - joint_one_bone->get_bone_angle()); + if (same_scale_sign) { + joint_one_bone->set_global_rotation(angle_atan - angle_0 - joint_one_bone->get_bone_angle()); + } else { + joint_one_bone->set_global_rotation(angle_atan + angle_0 + joint_one_bone->get_bone_angle()); + } + joint_two_bone->set_rotation(-Math::PI - angle_1 - joint_two_bone->get_bone_angle() + joint_one_bone->get_bone_angle()); } + } else { - joint_one_bone->set_global_rotation(angle_atan - joint_one_bone->get_bone_angle()); - joint_two_bone->set_global_rotation(angle_atan - joint_two_bone->get_bone_angle()); + if (same_scale_sign) { + joint_one_bone->set_global_rotation(angle_atan - joint_one_bone->get_bone_angle()); + joint_two_bone->set_global_rotation(angle_atan - joint_two_bone->get_bone_angle()); + } else { + joint_one_bone->set_global_rotation(angle_atan + joint_one_bone->get_bone_angle()); + joint_two_bone->set_global_rotation(angle_atan + joint_two_bone->get_bone_angle()); + } } stack->skeleton->set_bone_local_pose_override(joint_one_bone_idx, joint_one_bone->get_transform(), stack->strength, true); @@ -211,7 +227,8 @@ void SkeletonModification2DTwoBoneIK::_draw_editor_gizmo() { } stack->skeleton->draw_set_transform( stack->skeleton->to_local(operation_bone_one->get_global_position()), - operation_bone_one->get_global_rotation() - stack->skeleton->get_global_rotation()); + operation_bone_one->get_global_rotation() - stack->skeleton->get_global_rotation(), + operation_bone_one->get_global_scale()); Color bone_ik_color = Color(1.0, 0.65, 0.0, 0.4); #ifdef TOOLS_ENABLED