void Selector(SerializedProperty property)
    {
        SpineBone    attrib = (SpineBone)attribute;
        SkeletonData data   = skeletonDataAsset.GetSkeletonData(true);

        if (data == null)
        {
            return;
        }

        GenericMenu menu = new GenericMenu();

        menu.AddDisabledItem(new GUIContent(skeletonDataAsset.name));
        menu.AddSeparator("");

        for (int i = 0; i < data.Bones.Count; i++)
        {
            string name = data.Bones[i].Name;
            if (name.StartsWith(attrib.startsWith))
            {
                menu.AddItem(new GUIContent(name), name == property.stringValue, HandleSelect, new SpineDrawerValuePair(name, property));
            }
        }

        menu.ShowAsContext();
    }
Ejemplo n.º 2
0
        /// <summary>
        /// Pushing spine segment from detected collider
        /// </summary>
        public void PushIfSegmentInsideCollider(SpineBone bone, ref Vector3 targetPoint)
        {
            // We must translate phantom/reference skeleton positions to true position in world space for collisions
            Vector3 offset;

            if (UseTruePosition)
            {
                Vector3 theTarget    = targetPoint;
                Vector3 truePosition = bone.FinalPosition;
                offset = truePosition - theTarget + bone.transform.TransformVector(bone.ColliderOffset + OffsetAllColliders);
            }
            else
            {
                offset = bone.transform.TransformVector(bone.ColliderOffset + OffsetAllColliders);
            }

            if (!DetailedCollision)
            {
                for (int i = 0; i < CollidersDataToCheck.Count; i++)
                {
                    if (CollidersDataToCheck[i].PushIfInside(ref targetPoint, bone.GetCollisionRadiusScaled(), offset))
                    {
                        return;
                    }
                }
            }
            else
            {
                for (int i = 0; i < CollidersDataToCheck.Count; i++)
                {
                    CollidersDataToCheck[i].PushIfInside(ref targetPoint, bone.GetCollisionRadiusScaled(), offset);
                }
            }
        }
    public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
    {
        if (property.propertyType != SerializedPropertyType.String)
        {
            EditorGUI.LabelField(position, "ERROR:", "May only apply to type string");
            return;
        }

        SpineBone attrib = (SpineBone)attribute;

        var dataProperty = property.serializedObject.FindProperty(attrib.dataField);

        if (dataProperty != null)
        {
            if (dataProperty.objectReferenceValue is SkeletonDataAsset)
            {
                skeletonDataAsset = (SkeletonDataAsset)dataProperty.objectReferenceValue;
            }
            else if (dataProperty.objectReferenceValue is SkeletonRenderer)
            {
                var renderer = (SkeletonRenderer)dataProperty.objectReferenceValue;
                if (renderer != null)
                {
                    skeletonDataAsset = renderer.skeletonDataAsset;
                }
            }
            else
            {
                EditorGUI.LabelField(position, "ERROR:", "Invalid reference type");
                return;
            }
        }
        else if (property.serializedObject.targetObject is Component)
        {
            var component = (Component)property.serializedObject.targetObject;
            if (component.GetComponentInChildren <SkeletonRenderer>() != null)
            {
                var skeletonRenderer = component.GetComponentInChildren <SkeletonRenderer>();
                skeletonDataAsset = skeletonRenderer.skeletonDataAsset;
            }
        }

        if (skeletonDataAsset == null)
        {
            EditorGUI.LabelField(position, "ERROR:", "Must have reference to a SkeletonDataAsset");
            return;
        }

        position = EditorGUI.PrefixLabel(position, label);

        if (GUI.Button(position, property.stringValue, EditorStyles.popup))
        {
            Selector(property);
        }
    }
Ejemplo n.º 4
0
    void Start()
    {
        if (speedReference == null)
        {
            speedReference = transform;
        }

        skeletonAnimation = GetComponent <SkeletonAnimation>();
        bone = SpineBone.GetBone(boneName, skeletonAnimation);
        skeletonAnimation.UpdateLocal += UpdateLocal;
        lastPosition = speedReference.position;
    }
Ejemplo n.º 5
0
        /// <summary>
        /// Should be called by inspector window, but you can also do it during playmode for procedural creations
        /// </summary>
        public void CreateSpineChain(Transform start, Transform end)
        {
            if (start == null || end == null)
            {
                Debug.Log("[SPINE ANIMATOR] Can't create spine chain if one of the bones is null!");
                return;
            }

            List <Transform> fullChain = new List <Transform>();

            Transform p = end;

            while (p != null)
            {
                if (p == start)
                {
                    break;
                }
                fullChain.Add(p); p = p.parent;
            }


            if (p == null)
            {
                Debug.Log("[SPINE ANIMATOR] '" + start.name + "' is not child of '" + end.name + "' !");
                return;
            }

            fullChain.Add(start);
            fullChain.Reverse();

            SpineBones = new List <SpineBone>();

            for (int i = 0; i < fullChain.Count; i++)
            {
                SpineBone bone = new SpineBone(fullChain[i]);
                SpineBones.Add(bone);
            }

            // After creating chain we checking if some auto corrections can be done
        }
Ejemplo n.º 6
0
        /// <summary>
        /// Calculation target animation position for bone
        /// </summary>
        void CalculateTargetBonePosition(int index)
        {
            SpineBone otherBone   = SpineBones[index - chainIndexDirection];
            SpineBone currentBone = SpineBones[index];

            // Target position calculation
            Vector3 targetPosition = otherBone.ProceduralPosition - (currentBone.ProceduralRotation * ModelForwardAxisScaled) * (currentBone.BoneLength * DistancesMultiplier);

            if (currentBone.Collide)
            {
                targetPosition += gravityScale;
            }


            #region Springiness Stuff

            if (Springiness > 0f)
            {
                if (!LastBoneLeading)
                {
                    Vector3 backPosDiff = currentBone.ProceduralPosition - currentBone.PreviousPosition;
                    Vector3 newPos      = currentBone.ProceduralPosition;
                    currentBone.PreviousPosition = currentBone.ProceduralPosition;
                    newPos += backPosDiff * (1 - Mathf.Lerp(.05f, .25f, Springiness));

                    float restDistance = (otherBone.ProceduralPosition - newPos).magnitude;

                    Matrix4x4 otherLocalToWorld = otherBone.transform.localToWorldMatrix;
                    otherLocalToWorld.SetColumn(3, otherBone.ProceduralPosition);
                    Vector3 restPos = otherLocalToWorld.MultiplyPoint3x4(currentBone.transform.localPosition);

                    Vector3 diffPosVector = restPos - newPos;
                    newPos += diffPosVector * Mathf.Lerp(0.05f, 0.2f, Springiness);

                    diffPosVector = restPos - newPos;
                    float distance    = diffPosVector.magnitude;
                    float maxDistance = restDistance * (1 - Mathf.Lerp(0.0f, 0.2f, Springiness)) * 2;
                    if (distance > maxDistance)
                    {
                        newPos += diffPosVector * ((distance - maxDistance) / distance);
                    }

                    if (MaxStretching < 1f)
                    {
                        float dist = Vector3.Distance(currentBone.ProceduralPosition, newPos);
                        if (dist > 0f)
                        {
                            float maxDist = currentBone.BoneLength * 4 * MaxStretching;
                            if (dist > maxDist)
                            {
                                newPos = Vector3.Lerp(newPos, targetPosition, Mathf.InverseLerp(dist, 0f, maxDist));
                            }
                        }
                    }

                    targetPosition = Vector3.Lerp(targetPosition, newPos, Mathf.Lerp(0.3f, 0.9f, Springiness));
                }
            }

            #endregion


            // Target Position Stretching Prevention
            if (PosSmoother > 0f)
            {
                if (MaxStretching < 1f)
                {
                    float dist = Vector3.Distance(currentBone.ProceduralPosition, targetPosition);
                    if (dist > 0f)
                    {
                        float maxDist = currentBone.BoneLength * 4 * MaxStretching;
                        if (dist > maxDist)
                        {
                            currentBone.ProceduralPosition = Vector3.Lerp(currentBone.ProceduralPosition, targetPosition, Mathf.InverseLerp(dist, 0f, maxDist));
                        }
                    }
                }
            }


            if (UseCollisions)
            {
                if (currentBone.Collide)
                {
                    PushIfSegmentInsideCollider(currentBone, ref targetPosition);
                }
            }

            // Smoothing Position
            if (PosSmoother == 0f)
            {
                currentBone.ProceduralPosition = targetPosition;
            }
            else
            {
                currentBone.ProceduralPosition = Vector3.LerpUnclamped(currentBone.ProceduralPosition, targetPosition, Mathf.LerpUnclamped(1f, unifiedDelta, PosSmoother));
            }
        }
Ejemplo n.º 7
0
        /// <summary>
        /// Calculating rotation with limitations and stuff for single segment
        /// </summary>
        void CalculateTargetBoneRotation(int index)
        {
            // Preparation for calculations
            SpineBone otherBone   = SpineBones[index - chainIndexDirection];
            SpineBone currentBone = SpineBones[index];

            Quaternion targetLookRotation, backRotationRef;


            // Slithery calculation
            if (Slithery >= 1f)
            {
                backRotationRef = otherBone.ProceduralRotation;
            }
            else
            if (Slithery > 0f)
            {
                backRotationRef = Quaternion.LerpUnclamped(currentBone.ReferenceRotation, otherBone.ProceduralRotation, Slithery);
            }
            else
            {
                backRotationRef = currentBone.ReferenceRotation;
            }


            // Initial target rotation calculation
            targetLookRotation = Quaternion.LookRotation(otherBone.ProceduralPosition - currentBone.ProceduralPosition, otherBone.ProceduralRotation * ModelUpAxis);


            #region Calculations to limit rotations in order to adjust animation behaviour for project needs

            if (AngleLimit < 91)
            {
                float lookDiff = Quaternion.Angle(targetLookRotation, backRotationRef);

                // Limiting rotation to correct state with elastic range
                if (lookDiff > AngleLimit)
                {
                    float limiting = 0f;
                    limiting = Mathf.InverseLerp(0f, lookDiff, lookDiff - AngleLimit);

                    Quaternion limitRange = Quaternion.LerpUnclamped(targetLookRotation, backRotationRef, limiting);

                    float elasticPush = Mathf.Min(1f, lookDiff / (AngleLimit / 0.75f));
                    elasticPush = Mathf.Sqrt(Mathf.Pow(elasticPush, 4)) * elasticPush; // sqrt and power will make this value increase slower but reaching 1f at the end

                    if (LimitSmoother == 0f)
                    {
                        targetLookRotation = Quaternion.LerpUnclamped(targetLookRotation, limitRange, elasticPush);
                    }
                    else
                    {
                        //targetLookRotation = Quaternion.LerpUnclamped(targetLookRotation, limitRange, Mathf.LerpUnclamped(1f, unifiedDelta * elasticPush, LimitSmoother));
                        targetLookRotation = Quaternion.LerpUnclamped(targetLookRotation, limitRange, unifiedDelta * (1f - LimitSmoother) * 50f * elasticPush);
                    }
                }
            }

            if (GoBackSpeed <= 0f)
            {
                // When position in previous frame was different, we straigtening a little rotation of spine
                if (StraightenSpeed > 0f)
                {
                    if (previousPos != RoundPosDiff(SpineBones[leadingBoneIndex].ProceduralPosition))
                    {
                        currentBone.TargetStraightenFactor = 1f;
                    }
                    else
                    if (currentBone.TargetStraightenFactor > 0f)
                    {
                        currentBone.TargetStraightenFactor -= delta * (5f + StraightenSpeed);
                    }

                    currentBone.StraightenFactor = Mathf.Lerp(currentBone.StraightenFactor, currentBone.TargetStraightenFactor, unifiedDelta * (1f + StraightenSpeed));

                    if (currentBone.StraightenFactor > 0.025f)
                    {
                        targetLookRotation = Quaternion.Lerp(targetLookRotation, backRotationRef, unifiedDelta * currentBone.StraightenFactor * StraightenSpeed * (TurboStraighten ? 6f : 1f));
                    }
                }
            }
            else // When we set GoBackSpeed variable spine is going back to straight pose continously so diff would be detected all the time and we don't want this
            {
                // If we use straigtening at the same time when using GoBack variable
                float straightenVal = 0f;

                // When position in previous frame was different, we straigtening a little rotation of spine
                if (StraightenSpeed > 0f)
                {
                    if (previousPos != RoundPosDiff(SpineBones[leadingBoneIndex].ProceduralPosition))
                    {
                        currentBone.TargetStraightenFactor = 1f;
                    }
                    else
                    if (currentBone.TargetStraightenFactor > 0f)
                    {
                        currentBone.TargetStraightenFactor -= delta * (5f + StraightenSpeed);
                    }

                    //currentBone.StraightenFactor = Mathf.Lerp(currentBone.StraightenFactor, currentBone.TargetStraightenFactor, Mathf.LerpUnclamped(unifiedDelta, 1f, StraightenSpeed / 15f));
                    currentBone.StraightenFactor = Mathf.Lerp(currentBone.StraightenFactor, currentBone.TargetStraightenFactor, unifiedDelta * (1f + StraightenSpeed));

                    if (currentBone.StraightenFactor > 0.025f)
                    {
                        straightenVal = currentBone.StraightenFactor * StraightenSpeed * (TurboStraighten ? 6f : 1f);
                    }
                }

                //targetLookRotation = Quaternion.Lerp(targetLookRotation, backRotationRef, Mathf.LerpUnclamped(unifiedDelta + straightenVal, 1f, GoBackSpeed));
                targetLookRotation = Quaternion.Lerp(targetLookRotation, backRotationRef, unifiedDelta * (Mathf.Lerp(0f, 55f, GoBackSpeed) + straightenVal));
            }

            #endregion


            // If we want some smooth motion for follower
            if (RotSmoother == 0f)
            {
                currentBone.ProceduralRotation = targetLookRotation;
            }
            else
            {
                currentBone.ProceduralRotation = Quaternion.LerpUnclamped(currentBone.ProceduralRotation, targetLookRotation, Mathf.LerpUnclamped(0f, Mathf.LerpUnclamped(1f, unifiedDelta, RotSmoother), MotionInfluence));
            }
        }
        private void ViewBodyMenu(HumanMuscle script)
        {
            GUILayout.BeginHorizontal();
            EditorGUILayout.Space();
            BoneNameButton(HeadBone.GetInstance(), 100);
            EditorGUILayout.Space();
            GUILayout.EndHorizontal();


            GUILayout.BeginHorizontal();
            EditorGUILayout.Space();
            BoneNameButton(ShoulderLeftBone.GetInstance());
            BoneNameButton(NeckBone.GetInstance(), 80);
            BoneNameButton(ShoulderRightBone.GetInstance());
            EditorGUILayout.Space();
            GUILayout.EndHorizontal();

            GUILayout.BeginHorizontal();
            BoneNameButton(UpperArmLeftBone.GetInstance());
            EditorGUILayout.Space();
            BoneNameButton(UpperChestBone.GetInstance(), 100);
            EditorGUILayout.Space();
            BoneNameButton(UpperArmRightBone.GetInstance());
            GUILayout.EndHorizontal();

            GUILayout.BeginHorizontal();
            BoneNameButton(LowerArmLeftBone.GetInstance());
            EditorGUILayout.Space();
            BoneNameButton(ChestBone.GetInstance(), 100);
            EditorGUILayout.Space();
            BoneNameButton(LowerArmRightBone.GetInstance());
            GUILayout.EndHorizontal();

            GUILayout.BeginHorizontal();
            BoneNameButton(HandLeftBone.GetInstance(), 100);
            EditorGUILayout.Space();
            BoneNameButton(SpineBone.GetInstance(), 100);
            EditorGUILayout.Space();
            BoneNameButton(HandRightBone.GetInstance(), 100);
            GUILayout.EndHorizontal();

            GUILayout.BeginHorizontal();
            EditorGUILayout.Space();
            BoneNameButton(RootBone.GetInstance(), 100);
            EditorGUILayout.Space();
            GUILayout.EndHorizontal();

            GUILayout.BeginHorizontal();
            EditorGUILayout.Space();
            BoneNameButton(UpperLegLeftBone.GetInstance(), 150);
            BoneNameButton(UpperLegRightBone.GetInstance(), 150);
            EditorGUILayout.Space();
            GUILayout.EndHorizontal();

            GUILayout.BeginHorizontal();
            EditorGUILayout.Space();
            BoneNameButton(LowerLegLeftBone.GetInstance(), 150);
            EditorGUILayout.Space();
            BoneNameButton(LowerLegRightBone.GetInstance(), 150);
            EditorGUILayout.Space();
            GUILayout.EndHorizontal();

            GUILayout.BeginHorizontal();
            BoneNameButton(FootLeftBone.GetInstance(), 150);
            EditorGUILayout.Space();
            BoneNameButton(FootRightBone.GetInstance(), 150);
            GUILayout.EndHorizontal();

            GUILayout.BeginHorizontal();
            BoneNameButton(ToesLeftBone.GetInstance(), 150);
            EditorGUILayout.Space();
            BoneNameButton(ToesRightBone.GetInstance(), 150);
            GUILayout.EndHorizontal();
        }