/// <summary>
    /// Selects the new bone and deselects the old one
    /// </summary>
    /// <param name="rBone"></param>
    private void SelectBone(BoneControllerBone rBone)
    {
        // Flag the old bone as deselected
        if (mSelectedBone != null)
        {
            mSelectedBone.OnDisable();
        }

        // Flag the new bone as selected
        if (rBone == null)
        {
            mSelectedBones.Clear();
        }
        else if (mSelectedBones.Count > 0)
        {
            mSelectedBones[0] = rBone;
        }
        else
        {
            mSelectedBones.Add(rBone);
        }

        mSelectedBone = rBone;
        if (mSelectedBone != null)
        {
            mSelectedBone.OnEnable();
        }
    }
        /// <summary>
        /// When the skeleton is reloaded, we'll have different references for
        /// the same bone. So, we need to update our references to point to the skeleton
        /// </summary>
        public virtual void RefreshBones()
        {
            for (int i = mBones.Count - 1; i >= 0; i--)
            {
                bool   lFound          = false;
                string lBoneName       = mBones[i].Name;
                string lBoneParentName = (mBones[i].Parent != null ? mBones[i].Parent.Name : "");

                BoneControllerBone lNewBone = mSkeleton.GetBone(lBoneName) as BoneControllerBone;
                if (lNewBone != null)
                {
                    string lNewBoneParentName = (lNewBone.Parent != null ? lNewBone.Parent.Name : "");
                    if (lNewBoneParentName == lBoneParentName)
                    {
                        lFound    = true;
                        mBones[i] = lNewBone;
                    }
                }

                // If we didn't find a matching bone, we need to remove the
                // old one. Otherwise, the user may think everything is ok
                if (!lFound)
                {
                    RemoveBone(i, false);
                    Debug.LogWarning("BoneControllerMotor.RefreshBones() - Matching bone for " + lBoneName + " was not found. " + (Name.Length > 0 ? Name : this.GetType().Name) + " removing old bone.");
                }
            }
        }
Пример #3
0
        /// <summary>
        /// Renders out bone details specific to the motor
        /// </summary>
        /// <param name="rIndex"></param>
        /// <param name="rBone"></param>
        /// <returns></returns>
        protected override bool RenderBone(int rIndex, BoneControllerBone rBone)
        {
            bool lIsDirty = false;

#if UNITY_EDITOR
            while (rIndex >= _BoneInfo.Count)
            {
                PoseMotorBone lBoneInfo = new PoseMotorBone();
                _BoneInfo.Insert(mBones.IndexOf(rBone), lBoneInfo);
            }

            // Set the bone enable
            bool lNewIsEnabled = EditorGUILayout.Toggle(new GUIContent("Is Enabled", "Determines if this bone pose is enabled."), _BoneInfo[rIndex].IsEnabled);
            if (lNewIsEnabled != _BoneInfo[rIndex].IsEnabled)
            {
                lIsDirty = true;
                _BoneInfo[rIndex].IsEnabled = lNewIsEnabled;
            }

            // Set the bone weight
            float lNewWeight = EditorGUILayout.FloatField(new GUIContent("Weight", "Determines how much the motor effects vs. currently animated rotation."), _BoneInfo[rIndex].Weight);
            if (lNewWeight != _BoneInfo[rIndex].Weight)
            {
                lIsDirty = true;
                _BoneInfo[rIndex].Weight = lNewWeight;
            }

            // Set the bone lerp
            float lNewRotationLerp = EditorGUILayout.FloatField(new GUIContent("Rotation Lerp", "Determines how quickly we rotate to the target."), _BoneInfo[rIndex].RotationLerp);
            if (lNewRotationLerp != _BoneInfo[rIndex].RotationLerp)
            {
                lIsDirty = true;
                _BoneInfo[rIndex].RotationLerp = lNewRotationLerp;
            }

            // Render inspector controls based on the joint type
            if (rBone != null)
            {
                PoseMotorBone lBoneInfo = _BoneInfo[rIndex];
                lBoneInfo.IsDirty = false;

                if (rBone.Joint == null)
                {
                    rBone.OnInspectorManipulatorGUI(lBoneInfo);
                }
                else
                {
                    rBone.Joint.OnInspectorManipulatorGUI(lBoneInfo);
                }

                // Update the actual dirty flag
                if (_BoneInfo[rIndex].IsDirty)
                {
                    lIsDirty = true;
                }
            }
#endif

            return(lIsDirty);
        }
Пример #4
0
        /// <summary>
        /// Spreads the impact through to the children
        /// </summary>
        /// <param name="rParent">Parent whose children will be impacted</param>
        /// <param name="rChange">Change being applied</param>
        /// <param name="rDepthRemaining">Determines how deep we go</param>
        /// <param name="rDamping">Determines how much we dull the change on each iteration</param>
        private void ApplyImpactToChildren(BoneControllerBone rParent, Vector3 rChange, int rDepthRemaining, float rDamping)
        {
            rDepthRemaining--;
            rChange = rChange * rDamping;

            for (int i = 0; i < rParent.Children.Count; i++)
            {
                BoneControllerBone lChild = rParent.Children[i];
                if (AddTemporaryBone(lChild))
                {
                    // We're going to temper the child response based on the
                    // length compared to the original.
                    float lCompare = Mathf.Min(lChild.Length / rParent.Length, 1f);
                    rChange = rChange * lCompare;

                    mActiveBoneInfo[lChild].State  = 1;
                    mActiveBoneInfo[lChild].Time   = _ImpactTime;
                    mActiveBoneInfo[lChild].Change = rChange;

                    if (rDepthRemaining > 0)
                    {
                        ApplyImpactToChildren(lChild, rChange, rDepthRemaining, rDamping);
                    }
                }
            }
        }
Пример #5
0
        /// <summary>
        /// Adds a rotation to the specified bone
        /// </summary>
        /// <param name="rBone"></param>
        /// <param name="rSwing"></param>
        /// <param name="rTwist"></param>
        public void AddRotation(BoneControllerBone rBone, Quaternion rSwing, Quaternion rTwist)
        {
            Rotations.Add(rBone, rSwing * rTwist);

            Swings.Add(rBone, rSwing);
            Twists.Add(rBone, rTwist);
        }
        /// <summary>
        /// Add information specific to the bone. This helps us manage the bone
        /// </summary>
        /// <param name="rBone"></param>
        private void AddBoneInfo(int rIndex, BoneControllerBone rBone)
        {
            // Remember we want one more bone info than
            // we have bones.
            while (_BoneInfo.Count <= rIndex)
            {
                _BoneInfo.Add(new BoneChainDragBone());
            }

            if (rBone != null)
            {
                BoneChainDragBone lBoneInfo = _BoneInfo[rIndex];

                // Reset the values
                lBoneInfo.Position       = rBone._Transform.position;
                lBoneInfo.PrevPosition   = rBone._Transform.position;
                lBoneInfo.RotationTarget = rBone.Transform.rotation * rBone.ToBoneForward;
                lBoneInfo.Rotation       = lBoneInfo.RotationTarget;

                lBoneInfo.Length = rBone.Length;
                CapsuleCollider lCollider = rBone._Transform.GetComponent <CapsuleCollider>();
                if (lCollider != null)
                {
                    lBoneInfo.Length = lCollider.height * rBone._Transform.lossyScale.y;
                }

                // Record the transforms for collision testing
                if (!mBoneTransforms.Contains(rBone._Transform))
                {
                    mBoneTransforms.Add(rBone._Transform);
                }
            }
        }
Пример #7
0
        /// <summary>
        /// Renders out bone details specific to the motor
        /// </summary>
        /// <param name="rIndex"></param>
        /// <param name="rBone"></param>
        /// <returns></returns>
        protected override bool RenderBone(int rIndex, BoneControllerBone rBone)
        {
            bool lIsDirty = false;

#if UNITY_EDITOR
            while (rIndex >= _BoneInfo.Count)
            {
                ImpactMotorBone lBoneInfo = new ImpactMotorBone();

                if (rBone != null && rBone._Transform != null)
                {
                    lBoneInfo.EndPosition = rBone._Transform.position + (rBone._Transform.rotation * (rBone.BoneForward * rBone.Length));
                }

                _BoneInfo.Insert(mBones.IndexOf(rBone), lBoneInfo);
            }

            // Set the bone weight
            float lOldBoneWeight = (rBone == null ? 0 : _BoneInfo[rIndex].Weight);
            float lNewBoneWeight = EditorGUILayout.FloatField(new GUIContent("Rotation Weight", "Normalized weight this bone will be responsible for."), lOldBoneWeight);
            if (lNewBoneWeight != lOldBoneWeight)
            {
                if (rBone != null)
                {
                    lIsDirty = true;
                    _BoneInfo[rIndex].Weight = lNewBoneWeight;
                }
            }
#endif

            return(lIsDirty);
        }
        /// <summary>
        /// Renders out bone details specific to the motor
        /// </summary>
        /// <param name="rIndex"></param>
        /// <param name="rBone"></param>
        /// <returns></returns>
        protected override bool RenderBone(int rIndex, BoneControllerBone rBone)
        {
            bool lIsDirty = false;

#if UNITY_EDITOR
            // Set the collision flag
            bool lNewUseBindPosition = EditorGUILayout.Toggle(new GUIContent("Use Bind Position", "Determines if the movement is based on the current position or bind position."), _BoneInfo[rIndex].UseBindPosition);
            if (lNewUseBindPosition != _BoneInfo[rIndex].UseBindPosition)
            {
                lIsDirty = true;
                _BoneInfo[rIndex].UseBindPosition = lNewUseBindPosition;
            }

            // Set the bone yaw
            float lNewRotationLerp = EditorGUILayout.FloatField(new GUIContent("Drag Lerp", "Determines how quickly we rotate to the target."), _BoneInfo[rIndex].RotationLerp);
            if (lNewRotationLerp != _BoneInfo[rIndex].RotationLerp)
            {
                lIsDirty = true;
                _BoneInfo[rIndex].RotationLerp = lNewRotationLerp;
            }

            // Set the bone yaw
            float lNewUntwistLerp = EditorGUILayout.FloatField(new GUIContent("Untwist Lerp", "Determines how quickly we return to the bind twist. Setting to 0 disables untwisting."), _BoneInfo[rIndex].UntwistLerp);
            if (lNewUntwistLerp != _BoneInfo[rIndex].UntwistLerp)
            {
                lIsDirty = true;
                _BoneInfo[rIndex].UntwistLerp = lNewUntwistLerp;
            }
#endif

            return(lIsDirty);
        }
Пример #9
0
        /// <summary>
        /// Allows the motor to process bones temporarily and removes them once done
        /// </summary>
        /// <param name="rBone"></param>
        protected virtual bool AddTemporaryBone(BoneControllerBone rBone)
        {
            if (rBone == null || rBone._Transform == null)
            {
                return(false);
            }
            if (rBone.Length < _MinBoneLength)
            {
                return(false);
            }
            if (rBone == mSkeleton.Root)
            {
                return(false);
            }

            if (mActiveBoneInfo.ContainsKey(rBone))
            {
                return(true);
            }

            ImpactMotorBone lBoneInfo = ImpactMotorBone.Allocate();

            lBoneInfo.IsTemporary = true;
            lBoneInfo.EndPosition = rBone._Transform.position + (rBone._Transform.rotation * (rBone.BoneForward * rBone.Length));

            mActiveBoneInfo.Add(rBone, lBoneInfo);

            return(true);
        }
        /// <summary>
        /// Handle used to twist the bone
        /// </summary>
        /// <returns></returns>
        public static bool JointTwistHandle(BoneControllerBone rBone, ref Quaternion rTwist)
        {
            bool lIsDirty = false;

#if UNITY_EDITOR

            if (rBone != null)
            {
                Vector3 lWorldPosition = rBone._Transform.position;
                Quaternion lWorldSwing = rBone.WorldBindRotation * rBone.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 = rTwist;
                        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
                    rTwist = StartRotation * Quaternion.AngleAxis(lAngle, Vector3.forward);

                    // Flag the skeleton as dirty
                    lIsDirty = true;
                }

                // Reset
                Handles.color = lHandleColor;
            }

#endif

            return lIsDirty;
        }
Пример #11
0
        /// <summary>
        /// Allows the motor to process any specific bone logic after
        /// a bone has been added
        /// </summary>
        /// <param name="rIndex">Index position of the new bone</param>
        /// <param name="rBone">New bone that was added</param>
        public override void AddBone(BoneControllerBone rBone, bool rIncludeChildren)
        {
            base.AddBone(rBone, rIncludeChildren);

            PoseMotorBone lBoneInfo = new PoseMotorBone();

            _BoneInfo.Insert(mBones.IndexOf(rBone), lBoneInfo);
        }
        /// <summary>
        /// Renders a bone using the handle draw functions
        /// </summary>
        /// <param name="rBone"></param>
        /// <param name="rColor"></param>
        public static void DrawBoneCollider(BoneControllerBone rBone, Color rColor)
        {
#if UNITY_EDITOR

            if (rBone == null) { return; }
            if (rBone._Transform == null) { return; }
            if (rBone._ColliderSize.x == 0f && rBone._ColliderSize.y == 0f && rBone._ColliderSize.z == 0f) { return; }

            Color lHandleColor = Handles.color;
            Handles.color = rColor;

            // Sphere type
            if (rBone._ColliderType == 1)
            {
                Handles.DrawWireDisc(rBone._Transform.position, rBone._Transform.rotation * rBone._BoneForward, rBone._ColliderSize.x);
                Handles.DrawWireDisc(rBone._Transform.position, rBone._Transform.rotation * rBone._BoneUp, rBone._ColliderSize.x);
                Handles.DrawWireDisc(rBone._Transform.position, rBone._Transform.rotation * rBone._BoneRight, rBone._ColliderSize.x);
            }
            // Box type
            else
            {
                float lHalfX = rBone._ColliderSize.x / 2f;
                float lHalfY = rBone._ColliderSize.y / 2f;
                float lZ = rBone.ColliderSize.z;

                Vector3 lPosition = rBone._Transform.position;
                Quaternion lRotation = rBone._Transform.rotation * rBone._ToBoneForward;

                Vector3 lPoint0 = lRotation * new Vector3(-lHalfX, lHalfY, 0f);
                Vector3 lPoint1 = lRotation * new Vector3(-lHalfX, -lHalfY, 0f);
                Vector3 lPoint2 = lRotation * new Vector3(lHalfX, lHalfY, 0f);
                Vector3 lPoint3 = lRotation * new Vector3(lHalfX, -lHalfY, 0f);
                Vector3 lPoint4 = lRotation * new Vector3(-lHalfX, lHalfY, lZ);
                Vector3 lPoint5 = lRotation * new Vector3(-lHalfX, -lHalfY, lZ);
                Vector3 lPoint6 = lRotation * new Vector3(lHalfX, lHalfY, lZ);
                Vector3 lPoint7 = lRotation * new Vector3(lHalfX, -lHalfY, lZ);

                Handles.DrawLine(lPosition + lPoint0, lPosition + lPoint1);
                Handles.DrawLine(lPosition + lPoint0, lPosition + lPoint2);
                Handles.DrawLine(lPosition + lPoint2, lPosition + lPoint3);
                Handles.DrawLine(lPosition + lPoint1, lPosition + lPoint3);

                Handles.DrawLine(lPosition + lPoint4, lPosition + lPoint5);
                Handles.DrawLine(lPosition + lPoint4, lPosition + lPoint6);
                Handles.DrawLine(lPosition + lPoint6, lPosition + lPoint7);
                Handles.DrawLine(lPosition + lPoint5, lPosition + lPoint7);

                Handles.DrawLine(lPosition + lPoint0, lPosition + lPoint4);
                Handles.DrawLine(lPosition + lPoint1, lPosition + lPoint5);
                Handles.DrawLine(lPosition + lPoint2, lPosition + lPoint6);
                Handles.DrawLine(lPosition + lPoint3, lPosition + lPoint7);
            }

            Handles.color = lHandleColor;
#endif
        }
        /// <summary>
        /// Allows the motor to process any specific bone logic after
        /// a bone has been added
        /// </summary>
        /// <param name="rIndex">Index position of the new bone</param>
        /// <param name="rBone">New bone that was added</param>
        public override void AddBone(BoneControllerBone rBone, bool rIncludeChildren)
        {
            base.AddBone(rBone, rIncludeChildren);

            while (_BoneInfo.Count < mBones.Count)
            {
                FootPlacementMotorBone lBoneInfo = new FootPlacementMotorBone();
                _BoneInfo.Insert(mBones.IndexOf(rBone), lBoneInfo);
            }
        }
Пример #14
0
        /// <summary>
        /// Allows the motor to process any specific bone logic after
        /// a bone has been deleted
        /// </summary>
        /// <param name="rIndex">Index position the bone was at</param>
        /// <param name="rBone">Bone that was deleted</param>
        protected override void RemoveBone(BoneControllerBone rBone, bool rIncludeChildren)
        {
            int lIndex = mBones.IndexOf(rBone);

            if (lIndex >= 0)
            {
                _BoneInfo.RemoveAt(lIndex);
                base.RemoveBone(rBone, rIncludeChildren);
            }
        }
        /// <summary>
        /// Allows the motor to process any specific bone logic after
        /// a bone has been added
        /// </summary>
        /// <param name="rIndex">Index position of the new bone</param>
        /// <param name="rBone">New bone that was added</param>
        public override void AddBone(BoneControllerBone rBone, bool rIncludeChildren)
        {
            if (rBone == null || rBone._Transform == null)
            {
                return;
            }

            base.AddBone(rBone, rIncludeChildren);

            AddBoneInfo(mBones.IndexOf(rBone), rBone);
        }
        /// <summary>
        /// Allows the motor to process any specific bone logic after
        /// a bone has been deleted
        /// </summary>
        /// <param name="rIndex">Index position the bone was at</param>
        /// <param name="rBone">Bone that was deleted</param>
        protected virtual void RemoveBone(int rBoneIndex, bool rIncludeChildren)
        {
            if (rBoneIndex < 0 || rBoneIndex >= mBones.Count)
            {
                return;
            }

            BoneControllerBone rBone = mBones[rBoneIndex];

            RemoveBone(rBone, rIncludeChildren);
        }
Пример #17
0
        /// <summary>
        /// Allows the motor to process any specific bone logic after
        /// a bone has been added
        /// </summary>
        /// <param name="rIndex">Index position of the new bone</param>
        /// <param name="rBone">New bone that was added</param>
        public override void AddBone(BoneControllerBone rBone, bool rIncludeChildren)
        {
            base.AddBone(rBone, rIncludeChildren);

            RotationBone lBoneInfo = new RotationBone();

            if (rBone != null)
            {
                lBoneInfo.Euler = (rBone._Transform.rotation * rBone._ToBoneForwardInv).eulerAngles;
            }

            _BoneInfo.Insert(mBones.IndexOf(rBone), lBoneInfo);
        }
        /// <summary>
        /// Handle used to twist the bone
        /// </summary>
        /// <returns></returns>
        public static bool JointSwingAxisHandle(BoneControllerBone rBone, Vector3 rAxis, ref Quaternion rSwing)
        {
            bool lIsDirty = false;

#if UNITY_EDITOR

            Quaternion lWorldBind = rBone.WorldBindRotation;

            Vector3 lWorldPosition = rBone._Transform.position;
            Quaternion lWorldSwing = rBone.WorldBindRotation * rSwing;

            Vector3 lWorldAxis = lWorldBind * rAxis;

            Color lHandleColor = Handles.color;
            float lHandleSnapSettingsRotation = 1f;

            float lHandleScale = 0.1f;
            if (rBone.Skeleton.EditorAutoScaleHandles) { lHandleScale = HandleUtility.GetHandleSize(rBone.Transform.position) * HandlesHelper.HandleScale; }

            // Render the backs
            Handles.color = InactiveColor;
            //Handles.DrawWireArc(lWorldPosition, lWorldSwing * Vector3.forward, lWorldSwing * -Vector3.up, 360f, lHandleSize);
            //Handles.DrawWireArc(lWorldPosition, lWorldSwing * Vector3.right, lWorldSwing * -Vector3.up, 360f, lHandleSize);

            // Track the rotation when we start using the handle.
            Event lEvent = Event.current;
            switch (lEvent.type)
            {
                case EventType.MouseDown:
                    StartRotation = lWorldSwing;
                    break;
            }

            // Render the rotation handle for the z axis
            Handles.color = new Color(0.94118f, 0.39608f, 0.13333f, 1f);
            Quaternion lNewRotationZ = Handles.Disc(StartRotation, lWorldPosition, lWorldAxis, lHandleScale, false, lHandleSnapSettingsRotation);
            if (lNewRotationZ != StartRotation)
            {
                rSwing = rBone.TransformWorldRotationToLocalRotation(lNewRotationZ);
                lIsDirty = true;
            }

            // Reset
            Handles.color = lHandleColor;

#endif

            return lIsDirty;
        }
Пример #19
0
        /// <summary>
        /// Allows the motor to process any specific bone logic after
        /// a bone has been added
        /// </summary>
        /// <param name="rIndex">Index position of the new bone</param>
        /// <param name="rBone">New bone that was added</param>
        public override void AddBone(BoneControllerBone rBone, bool rIncludeChildren)
        {
            base.AddBone(rBone, rIncludeChildren);

            ImpactMotorBone lBoneInfo = new ImpactMotorBone();

            lBoneInfo.IsTemporary = false;

            if (rBone != null && rBone._Transform != null)
            {
                lBoneInfo.EndPosition = rBone._Transform.position + (rBone._Transform.rotation * (rBone.BoneForward * rBone.Length));
            }

            _BoneInfo.Insert(mBones.IndexOf(rBone), lBoneInfo);
        }
        /// <summary>
        /// Allows the motor to process any specific bone logic after
        /// a bone has been added
        /// </summary>
        /// <param name="rIndex">Index position of the new bone</param>
        /// <param name="rBone">New bone that was added</param>
        public virtual void AddBone(BoneControllerBone rBone, bool rIncludeChildren)
        {
            if (rBone == null || !mBones.Contains(rBone))
            {
                mBones.Add(rBone);
            }

            if (rBone != null && rIncludeChildren)
            {
                for (int i = 0; i < rBone.Children.Count; i++)
                {
                    AddBone(rBone.Children[i], rIncludeChildren);
                }
            }
        }
    /// <summary>
    /// Renders out a list of bones that belong to the skeleton
    /// </summary>
    private bool RenderBoneList(string rNameFilter, bool rSelectedFilter)
    {
        // Cycle through the motions
        BoneControllerBone lBone = mSkeleton.Root;

        if (lBone == null)
        {
            EditorGUILayout.HelpBox("Select a root transform above that will represent the root of your skeleton. Typically this is the 'hips'.", MessageType.Info);
            return(false);
        }
        else
        {
            return(RenderBone(lBone, 0, rNameFilter, rSelectedFilter));
        }
    }
        /// <summary>
        /// Allows the motor to process any specific bone logic after
        /// a bone has been deleted
        /// </summary>
        /// <param name="rIndex">Index position the bone was at</param>
        /// <param name="rBone">Bone that was deleted</param>
        protected virtual void RemoveBone(BoneControllerBone rBone, bool rIncludeChildren)
        {
            if (mBones.Contains(rBone))
            {
                mBones.Remove(rBone);
            }

            if (rBone != null && rIncludeChildren)
            {
                for (int i = 0; i < rBone.Children.Count; i++)
                {
                    RemoveBone(rBone.Children[i], rIncludeChildren);
                }
            }
        }
        /// <summary>
        /// Retrieves the bone index if it exists or -1 if it doesn't.
        /// </summary>
        /// <param name="rBoneID"></param>
        /// <returns></returns>
        public int GetBoneIndex(HumanBodyBones rBoneID)
        {
            if (mBones == null || mBones.Count == 0)
            {
                return(-1);
            }

            BoneControllerBone lBone = mSkeleton.GetBone(rBoneID) as BoneControllerBone;

            if (lBone != null)
            {
                return(mBones.IndexOf(lBone));
            }

            return(-1);
        }
        /// <summary>
        /// This function renders out the handles that allow us to edit the twist limits. It
        /// isn't actually meant to change the twist itself
        /// </summary>
        /// <param name="rBone"></param>
        /// <param name="rMinAngle"></param>
        /// <param name="rMaxAngle"></param>
        /// <returns></returns>
        public static bool JointSwingAxisLimitsHandle(BoneControllerBone rBone, Vector3 rAxis, float rMinAngle, float rMaxAngle)
        {
            bool lIsDirty = false;

#if UNITY_EDITOR

            Vector3 lWorldPosition = rBone._Transform.position;
            Quaternion lWorldSwing = rBone.WorldBindRotation * rBone.Swing;

            Color lGUIColor = GUI.color;
            Color lHandleColor = Handles.color;

            float lHandleScale = 0.2f;
            if (rBone.Skeleton.EditorAutoScaleHandles) { lHandleScale = HandleUtility.GetHandleSize(rBone.Transform.position) * HandlesHelper.HandleScale; }

            // Render the border of the angles
            Quaternion lMinRotation = Quaternion.AngleAxis(rMinAngle, rAxis);
            Quaternion lMaxRotation = Quaternion.AngleAxis(rMaxAngle, rAxis);

            // We don't use the world swing since we want the rotation based on the bind position
            Vector3 lMinOffset = rBone.WorldBindRotation * lMinRotation * Vector3.forward * lHandleScale;
            Vector3 lMaxOffset = rBone.WorldBindRotation * lMaxRotation * Vector3.forward * lHandleScale;

            Handles.color = new Color(0.94118f, 0.39608f, 0.13333f, 1f);
            Handles.DrawLine(lWorldPosition, lWorldPosition + lMinOffset);
            Handles.DrawLine(lWorldPosition, lWorldPosition + lMaxOffset);

            // Render the solid of the angles
            Handles.color = new Color(0.94118f, 0.39608f, 0.13333f, 0.1f);
            Handles.DrawSolidArc(lWorldPosition, rBone.WorldBindRotation * rAxis, (rBone.WorldBindRotation * lMinRotation * Vector3.forward), Mathf.Abs(rMinAngle) + rMaxAngle, lHandleScale);

            // Draw text
            GUI.color = new Color(0.72549f, 0.30588f, 0.10588f, 1f);
            Handles.Label(lWorldPosition + lMinOffset, "min:\r\n" + rMinAngle.ToString("0.00"));
            Handles.Label(lWorldPosition + lMaxOffset, "max:\r\n" + rMaxAngle.ToString("0.00"));

            Vector3 lDirectionAxis = Vector3.Cross(rAxis, rBone._BindRotation * rBone._BoneForward);
            float lSwingAngle = Vector3Ext.SignedAngle(lDirectionAxis, rBone.Swing * lDirectionAxis, rAxis);
            Handles.Label(lWorldPosition + (lWorldSwing * (Vector3.forward * (lHandleScale * 1.3f))), "  " + lSwingAngle.ToString("0.00"));

            // Reset
            GUI.color = lGUIColor;
            Handles.color = lHandleColor;
#endif

            return lIsDirty;
        }
        /// <summary>
        /// This function renders out the handles that allow us to edit the twist limits. It
        /// isn't actually meant to change the twist itself
        /// </summary>
        /// <param name="rBone"></param>
        /// <param name="rMinAngle"></param>
        /// <param name="rMaxAngle"></param>
        /// <returns></returns>
        public static bool JointTwistLimitsHandle(BoneControllerBone rBone, ref float rMinAngle, ref float rMaxAngle)
        {
            bool lIsDirty = false;

#if UNITY_EDITOR

            Vector3 lWorldPosition = rBone._Transform.position;
            Quaternion lWorldSwingRotation = rBone.WorldBindRotation * rBone._Swing;

            Color lGUIColor = GUI.color;
            Color lHandleColor = Handles.color;

            float lHandleScale = 0.2f;
            if (rBone.Skeleton.EditorAutoScaleHandles) { lHandleScale = HandleUtility.GetHandleSize(rBone.Transform.position) * HandlesHelper.HandleScale; }

            // Render the border of the angles
            float lTwistAngle = Vector3Ext.SignedAngle(Vector3.up, rBone._Twist * Vector3.up, Vector3.forward);

            Quaternion lActualRotation = Quaternion.AngleAxis(lTwistAngle, Vector3.forward);
            Quaternion lMinRotation = Quaternion.AngleAxis(rMinAngle, Vector3.forward);
            Quaternion lMaxRotation = Quaternion.AngleAxis(rMaxAngle, Vector3.forward);

            Vector3 lMinOffset = lWorldSwingRotation * lMinRotation * Vector3.up * lHandleScale;
            Vector3 lMaxOffset = lWorldSwingRotation * lMaxRotation * Vector3.up * lHandleScale;

            Handles.color = new Color(0.1f, 0.1f, 0.6f, 1f);
            Handles.DrawLine(lWorldPosition, lWorldPosition + lMinOffset);
            Handles.DrawLine(lWorldPosition, lWorldPosition + lMaxOffset);
            //Handles.DrawLine(lWorldPosition, lWorldPosition + (lWorldSwingRotation * rBone.Twist * Vector3.up * (lHandleScale * 1.1f)));

            // Render the solid of the angles
            Handles.color = new Color(0.25f, 0.60f, 0.95f, 0.1f);
            Handles.DrawSolidArc(lWorldPosition, rBone.Transform.rotation * rBone._BoneForward, lWorldSwingRotation * lMinRotation * Vector3.up, Mathf.Abs(rMinAngle) + rMaxAngle, lHandleScale);

            // Render text
            GUI.color = new Color(0.05f, 0.05f, 0.5f, 1f);
            Handles.Label(lWorldPosition + lMinOffset, "min:\r\n" + rMinAngle.ToString("0.00"));
            Handles.Label(lWorldPosition + lMaxOffset, "max:\r\n" + rMaxAngle.ToString("0.00"));
            Handles.Label(lWorldPosition + (lWorldSwingRotation * lActualRotation * Vector3.up * (lHandleScale * 1.3f)), " " + lTwistAngle.ToString("0.00"));

            // Reset
            GUI.color = lGUIColor;
            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;
        }
        /// <summary>
        /// Renders out bone details specific to the motor
        /// </summary>
        /// <param name="rIndex"></param>
        /// <param name="rBone"></param>
        /// <returns></returns>
        protected override bool RenderBone(int rIndex, BoneControllerBone rBone)
        {
            bool lIsDirty = false;

#if UNITY_EDITOR
            while (rIndex >= _BoneInfo.Count)
            {
                FootPlacementMotorBone lBoneInfo = new FootPlacementMotorBone();
                _BoneInfo.Insert(mBones.IndexOf(rBone), lBoneInfo);
            }

            // Set the bone weight
            float lNewWeight = EditorGUILayout.FloatField(new GUIContent("Weight", "Determines how much the motor effects vs. currently animated rotation."), _BoneInfo[rIndex].Weight);
            if (lNewWeight != _BoneInfo[rIndex].Weight)
            {
                lIsDirty = true;
                _BoneInfo[rIndex].Weight = lNewWeight;
            }

            // Set the bone yaw
            float lNewRotationLerp = EditorGUILayout.FloatField(new GUIContent("Rotation Lerp", "Determines how quickly we rotate to the target."), _BoneInfo[rIndex].RotationLerp);
            if (lNewRotationLerp != _BoneInfo[rIndex].RotationLerp)
            {
                lIsDirty = true;
                _BoneInfo[rIndex].RotationLerp = lNewRotationLerp;
            }

            // Axis to rotate around
            Vector3 lNewBendAxis = EditorGUILayout.Vector3Field(new GUIContent("Support Axis", "Axis used for rotating the bone."), _BoneInfo[rIndex].BendAxis);
            if (lNewBendAxis != _BoneInfo[rIndex].BendAxis)
            {
                lIsDirty = true;
                _BoneInfo[rIndex].BendAxis = lNewBendAxis;
            }

            // Final twist to apply to the bone after it's rotated
            float lNewTwist = EditorGUILayout.FloatField(new GUIContent("Final Twist Adjust", "Twist applied to the bone after movement."), _BoneInfo[rIndex].Twist);
            if (lNewTwist != _BoneInfo[rIndex].Twist)
            {
                lIsDirty = true;
                _BoneInfo[rIndex].Twist = lNewTwist;
            }
#endif

            return(lIsDirty);
        }
        /// <summary>
        /// Associates the bone and allows for any setup
        /// </summary>
        /// <param name="rBone">Bone the joint is tied to</param>
        public override void Initialize(BoneControllerBone rBone)
        {
            base.Initialize(rBone);

            //Log.ConsoleWrite("SwingPointAndTwistJoint.Initialize");

            // Use the default boundary points if we need to
            if (BoundaryPoints == null || BoundaryPoints.Count == 0)
            {
                ClearBoundaryPoints();
            }
            // Create the reach points with the existig boundary points
            else
            {
                BuildReachCones();
            }
        }
Пример #29
0
        /// <summary>
        /// Allows the motor to process any specific bone logic after
        /// a bone has been added
        /// </summary>
        /// <param name="rBone">New bone that was added</param>
        public override void AddBone(BoneControllerBone rBone, bool rIncludeChildren)
        {
            base.AddBone(rBone, rIncludeChildren);

            LookAtMotorBone lBoneInfo = new LookAtMotorBone();

            lBoneInfo.Weight = 1 / Mathf.Pow(2, _BoneInfo.Count);

            if (rBone == null)
            {
                _BoneInfo.Add(lBoneInfo);
            }
            else
            {
                int lIndex = mBones.IndexOf(rBone);
                _BoneInfo.Insert(lIndex, lBoneInfo);
            }
        }
Пример #30
0
        /// <summary>
        /// Allow the motor to control the scene GUI
        /// </summary>
        /// <returns></returns>
        public override bool OnSceneGUI(List <BoneControllerBone> rSelectedBones)
        {
            bool lIsDirty = false;

#if UNITY_EDITOR
            // Force the selected bone based on the input list
            BoneControllerBone lSelectedBone = null;
            int lSelectedBoneIndex           = -1;
            if (rSelectedBones.Count > 0)
            {
                lSelectedBone      = rSelectedBones[0];
                lSelectedBoneIndex = mBones.IndexOf(lSelectedBone);
            }

            // If we have a bone index, we can process the motor
            if (lSelectedBoneIndex >= 0 && lSelectedBoneIndex < mBones.Count)
            {
                PoseMotorBone lBoneInfo = _BoneInfo[lSelectedBoneIndex];
                lBoneInfo.IsDirty = false;

                if (lSelectedBone != null)
                {
                    // Local space rotators
                    if (lSelectedBone.Joint == null)
                    {
                        lSelectedBone.OnSceneManipulatorGUI(lBoneInfo);
                    }
                    else
                    {
                        lSelectedBone.Joint.OnSceneManipulatorGUI(lBoneInfo);
                    }

                    // Update the actual dirty flag
                    if (lBoneInfo.IsDirty)
                    {
                        lIsDirty = true;
                    }
                }
            }
#endif

            return(lIsDirty);
        }