コード例 #1
0
            public void AngleLimiting()
            {
                Quaternion localRotation   = Quaternion.Inverse(LastKeyLocalRotation) * transform.localRotation;
                Quaternion limitedRotation = localRotation;

                if (FEngineering.VIsZero(HingeLimits))
                {
                    if (AngleLimit < 180)
                    {
                        limitedRotation = LimitSpherical(limitedRotation);
                    }
                    if (TwistAngleLimit < 180)
                    {
                        limitedRotation = LimitZ(limitedRotation);
                    }
                }
                else
                {
                    limitedRotation = LimitHinge(limitedRotation);
                }

                if (FEngineering.QIsSame(limitedRotation, localRotation))
                {
                    return;
                }

                transform.localRotation = LastKeyLocalRotation * limitedRotation;
            }
コード例 #2
0
        void Gizmos_DrawEndBoneJoint()
        {
            // Drawing auto end joint offset
            if (FEngineering.VIsZero(EndBoneJointOffset))
            {
                Transform t = _TransformsGhostChain[_TransformsGhostChain.Count - 1];
                Transform p = _TransformsGhostChain[_TransformsGhostChain.Count - 1].parent;

                if (p) // Reference from parent
                {
                    Vector3 worldOffset = t.position - p.position;

                    Handles.color = new Color(0.3f, .3f, 1f, 0.8f);
                    FGUI_Handles.DrawBoneHandle(t.position, t.position + worldOffset, BaseTransform.forward, 1f);
                }
                else // Reference to child
                {
                    if (t.childCount > 0)
                    {
                        Transform ch          = _TransformsGhostChain[0].GetChild(0);
                        Vector3   worldOffset = ch.position - t.position;
                        FGUI_Handles.DrawBoneHandle(t.position, t.position + worldOffset, BaseTransform.forward, 1f);
                    }
                }
            }
            // Drawing custom joint offset
            else
            {
                Transform t = _TransformsGhostChain[_TransformsGhostChain.Count - 1];
                Handles.color = new Color(0.3f, .3f, 1f, 0.8f);
                FGUI_Handles.DrawBoneHandle(t.position, t.position + t.TransformVector(EndBoneJointOffset), BaseTransform.forward, 1f);
            }
        }
コード例 #3
0
        /// <summary>
        /// Processing calculated simple segment position with special effects like limiting / collision / smoothing etc.
        /// Calling methods using bone's parent variables
        /// </summary>
        void TailCalculations_SegmentPreProcessingStack(TailSegment child)
        {
            if (!UseCollision) // Basic motion without collision
            // Different update order with enable/disable collisions to avoid jittering on angle limiting
            {
                // Limit segments angles
                if (AngleLimit < 181)
                {
                    child.ProceduralPosition = AngleLimiting(child, child.ProceduralPosition);
                }

                // Smoothing motion
                if (child.PositionSpeed < 1f)
                {
                    child.ProceduralPosition = TailCalculations_SmoothPosition(child.PreviousPosition /*+ _limiting_influenceOffset*/, child.ProceduralPosition, child);
                }
            }
            else
            {
                // Smoothing motion
                if (child.PositionSpeed < 1f)
                {
                    child.ProceduralPosition = TailCalculations_SmoothPosition(child.PreviousPosition /*+ _limiting_influenceOffset*/, child.ProceduralPosition, child);
                }

                // Computing collision offset as first thing
                TailCalculations_ComputeSegmentCollisions(child, ref child.ProceduralPosition);

                // Limit segments angles
                if (AngleLimit < 181)
                {
                    child.ProceduralPosition = AngleLimiting(child, child.ProceduralPosition);
                }
            }


            // Control stretching
            if (MaxStretching < 1f)
            {
                StretchingLimiting(child);
            }

            // Apply gravity
            if (!FEngineering.VIsZero(child.Gravity) || UseWind)
            {
                CalculateGravityPositionOffsetForSegment(child);
            }

            if (Axis2D > 0)
            {
                Axis2DLimit(child);
            }
        }
コード例 #4
0
        protected virtual void OnSceneGUI()
        {
            if (Application.isPlaying)
            {
                return;
            }
            if (!Get.DrawGizmos)
            {
                return;
            }

            if (Get._Editor_Category == TailAnimator2.ETailCategory.Setup)
            {
                if (Get.BaseTransform)
                {
                    if (!FEngineering.VIsZero(Get.EndBoneJointOffset))
                    {
                        Get.RefreshTransformsList();

                        if (Get._TransformsGhostChain.Count > 0)
                        {
                            Undo.RecordObject(Get, "Changing position of tail joint offset");
                            Transform root = Get._TransformsGhostChain[Get._TransformsGhostChain.Count - 1];

                            Vector3 off         = root.TransformVector(Get.EndBoneJointOffset);
                            Vector3 pos         = root.position + off;
                            Vector3 transformed = FEditor_TransformHandles.PositionHandle(pos, Get.BaseTransform.rotation, .3f, true, false);

                            if (Vector3.Distance(transformed, pos) > 0.00001f)
                            {
                                Vector3 diff = transformed - pos;
                                Get.EndBoneJointOffset = root.InverseTransformVector(off + diff);
                                SerializedObject obj = new SerializedObject(Get);
                                if (obj != null)
                                {
                                    obj.ApplyModifiedProperties(); obj.Update();
                                }
                            }
                        }
                    }
                }
            }
        }
コード例 #5
0
        /// <summary>
        /// Begin update operations for additionaly genrated child bone of chain
        /// </summary>
        public void TailCalculations_UpdateArtificialChildBone(TailSegment child)
        {
            // Pre processing with limiting, gravity etc.
            //TailCalculations_SegmentPreProcessingStack(lastChild);

            //// Blending animation weight
            //TailSegment_PreRotationPositionBlend(lastChild);

            TailSegment_BaseSwingProcessing(child);

            if (child.PositionSpeed < 1f)
            {
                child.ProceduralPosition = TailCalculations_SmoothPosition(child.PreviousPosition /*+ _limiting_influenceOffset*/, child.ProceduralPosition, child);
            }

            if (MaxStretching < 1f)
            {
                StretchingLimiting(child);
            }

            if (!FEngineering.VIsZero(child.Gravity) || UseWind)
            {
                CalculateGravityPositionOffsetForSegment(child);
            }

            if (Axis2D > 0)
            {
                Axis2DLimit(child);
            }

            child.CollisionContactRelevancy = -1f;

            // Blending or just setting target position
            if (child.BlendValue * conditionalWeight < 1f)
            {
                child.ProceduralPositionWeightBlended = Vector3.LerpUnclamped(
                    child.ParentBone.transform.TransformPoint(child.LastKeyframeLocalPosition), child.ProceduralPosition, child.BlendValue * conditionalWeight);
            }
            else
            {
                child.ProceduralPositionWeightBlended = child.ProceduralPosition;
            }
        }
コード例 #6
0
 void Shaping_UpdateGravity()
 {
     if (!FEngineering.VIsZero(Gravity))
     {
         if (UseGravityCurve) // Operations with curve
         {
             if (!FEngineering.VIsSame(Gravity, lastGravity) || KeysChanged(GravityCurve.keys, lastGravityKeys))
             {
                 for (int i = 0; i < TailSegments.Count; i++)
                 {
                     TailSegments[i].Gravity  = Gravity * GetValueFromCurve(i, GravityCurve) / 40f;
                     TailSegments[i].Gravity *= (1 + ((TailSegments[i].Index / 2f) * (1f - TailSegments[i].Slithery)));
                 }
             }
         }
         else // Operations without curve
         {
             if (!FEngineering.VIsSame(Gravity, lastGravity))
             {
                 for (int i = 0; i < TailSegments.Count; i++)
                 {
                     TailSegments[i].Gravity  = Gravity / 40f;
                     TailSegments[i].Gravity *= (1 + ((TailSegments[i].Index / 2f) * (1f - TailSegments[i].Slithery)));
                 }
             }
         }
     }
     else // Gravity reset
     {
         if (!FEngineering.VIsSame(Gravity, lastGravity))
         {
             for (int i = 0; i < TailSegments.Count; i++)
             {
                 TailSegments[i].Gravity           = Vector3.zero;
                 TailSegments[i].GravityLookOffset = Vector3.zero;
             }
         }
     }
 }
コード例 #7
0
        /// <summary>
        /// Method to initialize component, to have more controll than waiting for Start() method, init can be executed before or after start, as programmer need it.
        /// </summary>
        protected virtual void Init()
        {
            if (initialized)
            {
                return;
            }


            // Checking if we have transform to create tail chain from
            if (_TransformsGhostChain == null || _TransformsGhostChain.Count == 0)
            {
                _TransformsGhostChain = new List <Transform>();
                GetGhostChain();
            }


            // Generating tail instances for procedural animation
            TailSegments = new List <TailSegment>();

            for (int i = 0; i < _TransformsGhostChain.Count; i++)
            {
                if (_TransformsGhostChain[i] == null)
                {
                    Debug.Log("[Tail Animator] Null bones in " + name + " !");
                    continue;
                }

                TailSegment b = new TailSegment(_TransformsGhostChain[i]);
                b.SetIndex(i, _TransformsGhostChain.Count);
                TailSegments.Add(b);
            }


            // Checking correctness
            if (TailSegments.Count == 0)
            {
                Debug.Log("[Tail Animator] Could not create tail bones chain in " + name + " !");
                return;
            }


            _TC_TailLength = 0f;
            _baseTransform = _TransformsGhostChain[0];

            //if (_baseTransform.parent)
            //    _baseTransform = _baseTransform.parent;
            //else
            //    IncludeParent = false;


            // Setting parent-child relation for tail logics
            for (int i = 0; i < TailSegments.Count; i++)
            {
                TailSegment current = TailSegments[i];
                TailSegment parent;

                #region Defining Parent Bones

                if (i == 0)
                {
                    if (current.transform.parent)
                    {
                        // Creating parent and setting safety parent
                        parent = new TailSegment(current.transform.parent);
                        parent.SetParentRef(new TailSegment(parent.transform.parent));
                    }
                    else
                    #region If first bone is parentless
                    {
                        parent = new TailSegment(current.transform);

                        Vector3 toStartDir;

                        if (_TransformsGhostChain.Count > 1)
                        {
                            toStartDir = _TransformsGhostChain[0].position - _TransformsGhostChain[1].position;
                            if (toStartDir.magnitude == 0)
                            {
                                toStartDir = transform.position - _TransformsGhostChain[1].position;
                            }
                        }
                        else
                        {
                            toStartDir = current.transform.position - _TransformsGhostChain[0].position;
                        }

                        if (toStartDir.magnitude == 0)
                        {
                            toStartDir = transform.position - _TransformsGhostChain[0].position;
                        }
                        if (toStartDir.magnitude == 0)
                        {
                            toStartDir = transform.forward;
                        }

                        parent.LocalOffset = parent.transform.InverseTransformPoint(parent.transform.position + toStartDir);
                        parent.SetParentRef(new TailSegment(current.transform));
                    }
                    #endregion

                    //current.InitialLocalRotation = Quaternion.Inverse(current.transform.localRotation);
                    GhostParent = parent;
                    GhostParent.Validate();
                    current.SetParentRef(GhostParent);
                }
                else // i != 0
                {
                    parent = TailSegments[i - 1];
                    // If bones are removed manually from chain we support custom length of bone undependent from transform parenting chain structure
                    current.ReInitializeLocalPosRot(parent.transform.InverseTransformPoint(current.transform.position), current.transform.localRotation);
                }


                #endregion


                #region Defining Last Child Bone

                if (i == TailSegments.Count - 1)
                {
                    Transform childT = null;
                    if (current.transform.childCount > 0)
                    {
                        childT = current.transform.GetChild(0);
                    }

                    GhostChild = new TailSegment(childT);

                    // Scale ref for ghosting object position offset
                    Vector3 scaleDir;

                    if (FEngineering.VIsZero(EndBoneJointOffset))
                    {
                        if (current.transform.parent)
                        {
                            scaleDir = current.transform.position - current.transform.parent.position;
                        }
                        else
                        if (current.transform.childCount > 0)
                        {
                            scaleDir = current.transform.GetChild(0).position - current.transform.position;
                        }
                        else
                        {
                            scaleDir = current.transform.TransformDirection(Vector3.forward) * 0.05f;
                        }
                    }
                    else
                    {
                        scaleDir = current.transform.TransformVector(EndBoneJointOffset);
                    }


                    GhostChild.ProceduralPosition = current.transform.position + scaleDir;
                    GhostChild.ProceduralPositionWeightBlended = GhostChild.ProceduralPosition;
                    GhostChild.PreviousPosition             = GhostChild.ProceduralPosition;
                    GhostChild.PosRefRotation               = Quaternion.identity;
                    GhostChild.PreviousPosReferenceRotation = Quaternion.identity;
                    GhostChild.ReInitializeLocalPosRot(current.transform.InverseTransformPoint(GhostChild.ProceduralPosition), Quaternion.identity);
                    GhostChild.RefreshFinalPos(GhostChild.ProceduralPosition);
                    GhostChild.RefreshFinalRot(GhostChild.PosRefRotation);
                    GhostChild.TrueTargetRotation = GhostChild.PosRefRotation;
                    current.TrueTargetRotation    = current.transform.rotation;

                    current.SetChildRef(GhostChild);
                    GhostChild.SetParentRef(current);
                }
                else
                {
                    current.SetChildRef(TailSegments[i + 1]);
                }

                #endregion


                current.SetParentRef(parent);

                _TC_TailLength += Vector3.Distance(current.ProceduralPosition, parent.ProceduralPosition);
            }


            // List with ghosts for curves etc.
            GhostParent.SetIndex(-1, TailSegments.Count);
            GhostChild.SetIndex(TailSegments.Count, TailSegments.Count);
            GhostParent.SetChildRef(TailSegments[0]);

            previousWorldPosition = BaseTransform.position;
            WavingRotationOffset  = Quaternion.identity;

            if (CollidersDataToCheck == null)
            {
                CollidersDataToCheck = new List <FImp_ColliderData_Base>();
            }

            DynamicAlwaysInclude = new List <Component>();
            if (UseCollision)
            {
                SetupSphereColliders();
            }

            // List instance for deflection feature
            if (_defl_source == null)
            {
                _defl_source = new List <TailSegment>();
            }

            Waving_Initialize();

            if (DetachChildren)
            {
                DetachChildrenTransforms();
            }

            initialized = true;

            if (TailSegments.Count == 1)
            {
                if (TailSegments[0].transform.parent == null)
                {
                    Debug.Log("[Tail Animator] Can't initialize one-bone length chain on bone which don't have any parent!");
                    Debug.LogError("[Tail Animator] Can't initialize one-bone length chain on bone which don't have any parent!");
                    TailAnimatorAmount = 0f;
                    initialized        = false;
                    return;
                }
            }

            if (UseWind)
            {
                TailAnimatorWind.Refresh(this);
            }

            if (PostProcessingNeeded())
            {
                if (!_pp_initialized)
                {
                    InitializePostProcessing();
                }
            }

            #region Prewarming tail to target state

            if (Prewarm)
            {
                ShapingParamsUpdate();
                ExpertParamsUpdate();

                Update();
                LateUpdate();

                justDelta      = rateDelta;
                secPeriodDelta = 1f;
                deltaForLerps  = secPeriodDelta;
                rateDelta      = 1f / 60f;

                CheckIfTailAnimatorShouldBeUpdated();

                if (updateTailAnimator)
                {
                    int loopCount = 60 + TailSegments.Count / 2;

                    for (int d = 0; d < loopCount; d++)
                    {
                        PreCalibrateBones();
                        LateUpdate();
                    }
                }
            }

            #endregion
        }