/// <summary>
        /// Allow the joint to render it's own GUI. This GUI is used
        /// for displaying and manipulating the joint itself.
        /// </summary>
        /// <returns>Reports if the object's value was changed</returns>
        public override bool OnInspectorManipulatorGUI(IKBoneModifier rModifier)
        {
#if UNITY_EDITOR
            // Determine if the swing is changing
            if (mBone != null)
            {
                Vector3 lSwing    = rModifier.Swing.eulerAngles;
                Vector3 lNewSwing = InspectorHelper.Vector3Fields("Swing", "Euler angles to swing the bone.", lSwing, true, true, false);
                if (lNewSwing != lSwing)
                {
                    // Grab the amount that was just rotated by based on the current rotation.
                    // We do this so the change is relative to the current swing rotation
                    Vector3 lDeltaRotations = lNewSwing - lSwing;
                    rModifier.Swing = rModifier.Swing * Quaternion.Euler(lDeltaRotations);

                    rModifier.IsDirty = true;
                }

                // Determine if the twist is changing
                //float lTwist = mBone.Twist.eulerAngles.y;
                float lTwist    = Vector3Ext.SignedAngle(Vector3.up, rModifier.Twist * Vector3.up, Vector3.forward);
                float lNewTwist = EditorGUILayout.FloatField("Twist", lTwist);
                if (_AllowTwist && lNewTwist != lTwist)
                {
                    rModifier.Twist   = Quaternion.AngleAxis(lNewTwist, Vector3.forward);
                    rModifier.IsDirty = true;
                }

                // Reset the values if needed
                if (GUILayout.Button("reset rotation", EditorStyles.miniButton))
                {
                    rModifier.Swing   = Quaternion.identity;
                    rModifier.Twist   = (_AllowTwist ? Quaternion.identity : mBone._Twist);
                    rModifier.IsDirty = true;

                    mBone._Transform.localRotation = mBone._BindRotation;
                }

                if (rModifier.IsDirty)
                {
                    // Before we go to far, see if we are within the joint limits. If not,
                    // we need to go back to a good position.
                    bool lIsInLimits = ApplyLimits(ref rModifier.Swing, ref rModifier.Twist);
                    if (lIsInLimits || QuaternionExt.IsEqual(rModifier.Swing, Quaternion.identity))
                    {
                        mLastSwing = rModifier.Swing;
                        mLastTwist = rModifier.Twist;
                    }
                    else
                    {
                        rModifier.Swing = mLastSwing;
                        rModifier.Twist = mLastTwist;
                    }
                }
            }
#endif

            return(rModifier.IsDirty);
        }
        // ************************************** EDITOR SUPPORT **************************************

        /// <summary>
        /// Allow the constraint to render it's own GUI
        /// </summary>
        /// <returns>Reports if the object's value was changed</returns>
        public override bool OnInspectorConstraintGUI(bool rIsSelected)
        {
            bool lIsDirty = false;

#if UNITY_EDITOR
            GUILayout.Space(5);

            // Determine if the swing is changing
            if (mBone != null)
            {
                Vector3 lSwing    = _Swing.eulerAngles;
                Vector3 lNewSwing = InspectorHelper.Vector3Fields("Swing", "Euler angles to swing the bone.", lSwing, true, true, false);
                if (lNewSwing != lSwing)
                {
                    lIsDirty = true;

                    // Grab the amount that was just rotated by based on the current rotation.
                    // We do this so the change is relative to the current swing rotation
                    Vector3 lDeltaRotations = lNewSwing - lSwing;
                    _Swing = _Swing * Quaternion.Euler(lDeltaRotations);
                }

                // Determine if the twist is changing
                float lTwist    = Vector3Ext.SignedAngle(Vector3.up, _Twist * Vector3.up, Vector3.forward);
                float lNewTwist = EditorGUILayout.FloatField("Twist", lTwist);
                if (lNewTwist != lTwist)
                {
                    lIsDirty = true;
                    _Twist   = Quaternion.AngleAxis(lNewTwist, Vector3.forward);
                }

                // Reset the values if needed
                if (GUILayout.Button("reset rotation", EditorStyles.miniButton))
                {
                    _Swing   = Quaternion.identity;
                    _Twist   = Quaternion.identity;
                    lIsDirty = true;
                }

                if (lIsDirty)
                {
                    mBone.SetLocalRotation(_Swing, _Twist, 1f);
                }
            }
#endif

            return(lIsDirty);
        }
        /// <summary>
        /// Allow the joint to render it's own GUI. This GUI is used
        /// for displaying and manipulating the joint itself.
        /// </summary>
        /// <returns>Reports if the object's value was changed</returns>
        public override bool OnInspectorManipulatorGUI(IKBoneModifier rModifier)
        {
#if UNITY_EDITOR
            // Determine if the swing is changing
            if (mBone != null)
            {
                // Determine if the swing is changing
                Vector3 lSwing    = rModifier.Swing.eulerAngles;
                Vector3 lNewSwing = InspectorHelper.Vector3Fields("Swing", "Euler angles to swing the bone.", lSwing, true, true, false); //lBoneForward.x == 0f, lBoneForward.y == 0f, lBoneForward.z == 0f);
                if (lNewSwing != lSwing)
                {
                    // Grab the amount that was just rotated by based on the current rotation.
                    // We do this so the change is relative to the current swing rotation
                    Vector3 lDeltaRotations = lNewSwing - lSwing;
                    rModifier.Swing = rModifier.Swing * Quaternion.Euler(lDeltaRotations);

                    rModifier.IsDirty = true;
                }

                float lTwist    = Vector3Ext.SignedAngle(Vector3.up, rModifier.Twist * Vector3.up, Vector3.forward);
                float lNewTwist = EditorGUILayout.FloatField("Twist", lTwist);
                if (lNewTwist != lTwist)
                {
                    rModifier.Twist   = Quaternion.AngleAxis(lNewTwist, Vector3.forward);
                    rModifier.IsDirty = true;
                }

                // Reset the values if needed
                if (GUILayout.Button("reset rotation", EditorStyles.miniButton))
                {
                    rModifier.Swing   = Quaternion.identity;
                    rModifier.Twist   = Quaternion.identity;
                    rModifier.IsDirty = true;

                    mBone._Transform.localRotation = mBone._BindRotation;
                }

                if (rModifier.IsDirty)
                {
                    ApplyLimits(ref rModifier.Swing, ref rModifier.Twist);
                }
            }
#endif

            return(rModifier.IsDirty);
        }