/// <summary> /// Handle used to twist the bone /// /// Note: We return "Unity Forward" values, not "Bone Forward" ones /// </summary> /// <returns></returns> public static bool JointTwistHandle(BoneControllerBone rBone, IKBoneModifier rModifier) { bool lIsDirty = false; #if UNITY_EDITOR if (rBone != null) { Vector3 lWorldPosition = rBone._Transform.position; Quaternion lWorldSwing = rBone.WorldBindRotation * rModifier.Swing; Color lHandleColor = Handles.color; float lHandleSnapSettingsRotation = 1f; float lHandleScale = 0.1f; if (rBone.Skeleton.EditorAutoScaleHandles) { lHandleScale = HandleUtility.GetHandleSize(lWorldPosition) * HandlesHelper.HandleScale; } // Track the rotation when we start using the handle. Event lEvent = Event.current; switch (lEvent.type) { case EventType.MouseDown: StartRotation = rModifier.Twist; break; } // ROLL Handles.color = InactiveColor; Handles.DrawWireArc(lWorldPosition, lWorldSwing * Vector3.forward, lWorldSwing * Vector3.right, 360f, lHandleScale); Handles.color = Handles.zAxisColor; Quaternion lRotation = Quaternion.identity; Quaternion lNewRotation = Handles.Disc(lRotation, lWorldPosition, lWorldSwing * Vector3.forward, lHandleScale, true, lHandleSnapSettingsRotation); if (lNewRotation != lRotation) { float lTwistAngle = 0f; Vector3 lTwistAxis = Vector3.zero; lNewRotation.ToAngleAxis(out lTwistAngle, out lTwistAxis); // When the rotation exceeds 360 degress, our angle starts to // reverse its trending. We can fix that here. float lTwistInvertTest = Vector3.Angle(lWorldSwing * Vector3.forward, lTwistAxis); float lAngle = (Mathf.Abs(lTwistInvertTest) < 1f ? 1 : -1) * lTwistAngle; // We return Unity Forward values rModifier.Twist = StartRotation * Quaternion.AngleAxis(lAngle, Vector3.forward); // Flag the skeleton as dirty lIsDirty = true; } // Reset Handles.color = lHandleColor; } #endif return lIsDirty; }
/// <summary> /// Handle used to swing the bone using GUI handles /// </summary> /// <param name="rBone">Bone that is being rotated</param> /// <param name="rSwing">Local space swing</param> /// <returns></returns> public static bool JointSwingHandle(BoneControllerBone rBone, IKBoneModifier rModifier) { bool lIsDirty = false; #if UNITY_EDITOR Vector3 lWorldPosition = rBone._Transform.position; Quaternion lWorldSwing = rBone.WorldBindRotation * rModifier.Swing; Color lHandleColor = Handles.color; float lHandleSnapSettingsRotation = 1f; float lHandleScale = 0.1f; if (rBone.Skeleton.EditorAutoScaleHandles) { lHandleScale = HandleUtility.GetHandleSize(lWorldPosition) * HandlesHelper.HandleScale; } // Track the rotation when we start using the handle. Event lEvent = Event.current; switch (lEvent.type) { case EventType.MouseDown: StartRotation = lWorldSwing; break; } Quaternion lOldValue = StartRotation; Quaternion lNewValue = Quaternion.identity; // PITCH Handles.color = InactiveColor; Handles.DrawWireArc(lWorldPosition, lWorldSwing * Vector3.right, lWorldSwing * Vector3.up, 360f, lHandleScale); Handles.color = Handles.xAxisColor; lNewValue = Handles.Disc(lOldValue, lWorldPosition, lWorldSwing * Vector3.right, lHandleScale, true, lHandleSnapSettingsRotation); if (lNewValue != lOldValue) { rModifier.Swing = Quaternion.Inverse(rBone.WorldBindRotation) * lNewValue; lIsDirty = true; lOldValue = lNewValue; } // YAW Handles.color = InactiveColor; Handles.DrawWireArc(lWorldPosition, lWorldSwing * Vector3.up, lWorldSwing * Vector3.forward, 360f, lHandleScale); Handles.color = Handles.yAxisColor; lNewValue = Handles.Disc(lOldValue, lWorldPosition, lWorldSwing * Vector3.up, lHandleScale, true, lHandleSnapSettingsRotation); if (lNewValue != lOldValue) { rModifier.Swing = Quaternion.Inverse(rBone.WorldBindRotation) * lNewValue; lIsDirty = true; lOldValue = lNewValue; } // Reset Handles.color = lHandleColor; #endif return lIsDirty; }
/// <summary> /// Handle used to twist the bone /// </summary> /// <returns></returns> public static bool JointSwingAxisHandle(BoneControllerBone rBone, Vector3 rAxis, IKBoneModifier rModifier) { bool lIsDirty = false; #if UNITY_EDITOR Vector3 lWorldPosition = rBone._Transform.position; Quaternion lWorldSwing = rBone.WorldBindRotation * rModifier.Swing; Vector3 lWorldAxis = rBone.WorldBindRotation * rAxis; Color lHandleColor = Handles.color; float lHandleSnapSettingsRotation = 1f; float lHandleScale = 0.1f; if (rBone.Skeleton.EditorAutoScaleHandles) { lHandleScale = HandleUtility.GetHandleSize(lWorldPosition) * HandlesHelper.HandleScale; } // Track the rotation when we start using the handle. Event lEvent = Event.current; switch (lEvent.type) { case EventType.MouseDown: StartRotation = lWorldSwing; break; } Quaternion lOldValue = StartRotation; Quaternion lNewValue = Quaternion.identity; // AXIS Handles.color = new Color(0.94118f, 0.39608f, 0.13333f, 1f); lNewValue = Handles.Disc(lOldValue, lWorldPosition, lWorldAxis, lHandleScale, false, lHandleSnapSettingsRotation); if (lNewValue != lOldValue) { rModifier.Swing = Quaternion.Inverse(rBone.WorldBindRotation) * lNewValue; lIsDirty = true; lOldValue = lNewValue; } // Reset Handles.color = lHandleColor; #endif return lIsDirty; }