using System.Collections; using UnityEngine; namespace FIMSpace.FProceduralAnimation { [AddComponentMenu("FImpossible Creations/Legs Animator")] [DefaultExecutionOrder(-7)] public partial class LegsAnimator : MonoBehaviour { // All Legs Animator code is placed inside the partial classes \\ /// Once per frame calculated component's blend value for the algorithms public float _MainBlend { get; protected set; } float _lastMainBlend = 1f; /// For extra update calls liek IK refresh protected bool _lastMainBlendChanged { get; private set; } public float _MainBlendPlusGrounded { get; protected set; } [Tooltip("Total blend of the plugin effects. When zero it disables most of the calculations (but not all)")] [FPD_Suffix(0f, 1f)] public float LegsAnimatorBlend = 1f; /// Used for fading off legs animator on culling camera distance protected float cullingBlend = 1f; public float GetCurrentCullingBlend() { return cullingBlend; } /// Can be used by inheriting for custom blending amount protected float protectedBlend = 1f; /// If not initialized, it's false, it can be used for optimization protected bool AllowUpdate = false; protected bool _started = false; private void Start() { _started = true; AllowUpdate = false; if (DelayedInitialization == false) Initialize(); StartCoroutine(IEStart()); } #region Start Coroutine private IEnumerator IEStart() { yield return null; yield return null; if (Rigidbody == null) { Rigidbody = BaseTransform.GetComponent(); if (!Rigidbody) Rigidbody = BaseTransform.GetComponentInChildren(); if (!Rigidbody) Rigidbody = BaseTransform.GetComponentInParent(); } Initialize(); } private void OnEnable() { // Prevent start-disable not activated component error if (_started) { if (!LegsInitialized) { Initialize(); } else _wasInstantTriggered = false; } } #endregion Start Coroutine private void CheckActivation() { // Distance Culling Fading if (FadeOffAtDistance < 0.01f) cullingBlend = 1f; else { bool inRange = true; if (FadeOff_DistanceToCamera == null) if (Camera.main != null) FadeOff_DistanceToCamera = Camera.main.transform; if (FadeOff_DistanceToCamera != null) { FadeOff_lastCameraDistance = Vector3.Distance(BaseTransform.position, FadeOff_DistanceToCamera.position); if (FadeOff_lastCameraDistance > FadeOffAtDistance) inRange = false; } if (inRange) { if (cullingBlend < 1f) { cullingBlend = Mathf.Min(1f, Mathf.Lerp(cullingBlend, 1.05f, Time.unscaledDeltaTime * 6f)); cullingBlend = Mathf.MoveTowards(cullingBlend, 1f, Time.unscaledDeltaTime); } } else cullingBlend = Mathf.MoveTowards(cullingBlend, 0f, Time.unscaledDeltaTime * 1.5f); } // Camera Visibility culling if (DisableIfInvisible != null) { if (DisableIfInvisible.isVisible == false) { legsWasDisabled = true; return; } } #region Backquote input debug disable plugin #if UNITY_EDITOR #if ENABLE_LEGACY_INPUT_MANAGER // Just for editor debug help if (Input.GetKey(KeyCode.BackQuote)) { legsWasDisabled = true; return; } #endif #endif #endregion Backquote input debug disable plugin // Reactivating procedures if (legsWasDisabled) { if (_MainBlend > 0f) if (LegsInitialized) { OnLegsReactivate(); legsWasDisabled = false; } } } private void Update() { if (LegsInitialized == false) return; CheckActivation(); float dt = UnscaledDeltaTime ? Time.unscaledDeltaTime : Time.deltaTime; PrepareValues(dt); if (!AllowUpdate) return; if (AnimatePhysics) return; if (legsWasDisabled) return; UpdateStack(dt); } private bool _fixedUpdated = false; private void FixedUpdate() { if (!AllowUpdate) return; if (legsWasDisabled) return; float dt = UnscaledDeltaTime ? Time.fixedUnscaledDeltaTime : Time.fixedDeltaTime; PrepareValues(dt); ExtraFixedUpdate(); if (AnimatePhysics == false) return; UpdateStack(dt); _fixedUpdated = true; } /// Called even when animate physics is disabled protected virtual void ExtraFixedUpdate() { if (!UseRigidbodyVelocityForIsMoving) return; if (!Rigidbody) return; Vector3 localVelo = ToRootLocalSpaceVec(Rigidbody.linearVelocity); localVelo.y = 0f; bool moving = (localVelo.magnitude) > ScaleReferenceNoScale * 0.02f; User_SetIsMoving(moving); } private void LateUpdate() { if (!AllowUpdate) return; if (legsWasDisabled) return; #region Animate Physics support if (AnimatePhysics) { if (!_fixedUpdated) return; else { _fixedUpdated = false; } } #endregion Animate Physics support PreLateUpdateStack(); LateUpdateStack(); } /// Prepare target blend value for the component's algorithms protected virtual void PrepareValues(float delta) { _MainBlend = LegsAnimatorBlend * cullingBlend * protectedBlend * RagdolledDisablerBlend; _MainBlendPlusGrounded = _MainBlend * IsGroundedBlend; if (Mecanim != null) AnimatePhysics = Mecanim.updateMode == AnimatorUpdateMode.Fixed; if (_lastMainBlend != _MainBlend) { _lastMainBlendChanged = true; for (int l = 0; l < Legs.Count; l++) Legs[l].IK_UpdateParamsBase(); } else { _lastMainBlendChanged = false; } _lastMainBlend = _MainBlend; } protected virtual void UpdateStack(float delta) { #region Editor Debug Performance Measure Start MeasurePerformanceUpdate(true); #endregion Editor Debug Performance Measure Start DeltaTime = delta; Scale = baseTransform.lossyScale.y; if (_MainBlend > 0f) { if (_wasInstantTriggered == false) IK_TriggerGlueInstantTransition(); RefreshTargetMovementDirectionHelper(); RefreshMatrices(); Controll_Update(); UpdateGroundedBlend(); UpdateMovingBlend(); UpdateSlidingBlend(); Hips_PreCalibrate(); Legs_PreCalibrate(); ExtraControls_Update(); Modules_Update(); } else { Legs_PreCalibrate(); legsWasDisabled = true; } #region Editor Debug Performance Measure End MeasurePerformanceUpdate(false); #endregion Editor Debug Performance Measure End } protected virtual void PreLateUpdateStack() { #region Editor Debug Performance Measure Start MeasurePerformancePreLateUpdate(true); #endregion Editor Debug Performance Measure Start Legs_CheckAnimatorPose(); Modules_AfterAnimatorCaptureUpdate(); BaseObject_MotionUpdate(); Hips_PreLateUpdate(); Hips_LateUpdate(); Legs_BeginLateUpdate(); //StepHeatmap_Update(); #region Editor Debug Performance Measure End MeasurePerformancePreLateUpdate(false); #endregion Editor Debug Performance Measure End } protected virtual void LateUpdateStack() { #region Editor Debug Performance Measure Start MeasurePerformanceMain(true); #endregion Editor Debug Performance Measure Start if (_MainBlend > 0.001f) Legs_MidLateUpdateAndRaycasting(); Modules_PreLateUpdate(); // Legs_LateUpdate(); Hips_PostLateUpdate(); Modules_LateUpdatePreApply(); // Legs_LateUpdate_Apply(); Modules_PostLateUpdate(); // #region Editor Debug Performance Measure End MeasurePerformanceMain(false); #endregion Editor Debug Performance Measure End } public virtual void User_UpdateParametersAfterManualChange() { #region Editor ifdef #if UNITY_EDITOR if (Application.isPlaying == false) return; #endif #endregion Editor ifdef if (AllowUpdate == false) return; #region IK Rotate Support Part I //_ExecutionIKOffsetsRotate = IKOffsetsRotate; //if (IKOffsetsRotate != 0f) //{ // if (usingIKRotate == false) usingIKRotate = true; //} #endregion IK Rotate Support Part I Modules_UpdateAfterManualChanges(); #region IK Rotate Support Part II //if (usingIKRotate) //{ // //if (useCustomIKRotatorVector == false) // IK_UseIKRotatorQuat = Quaternion.Euler(0f, _ExecutionIKOffsetsRotate, 0f); //} #endregion IK Rotate Support Part II for (int l = 0; l < Legs.Count; l++) { var leg = Legs[l]; leg.Leg_UpdateParams(); } if (Event_OnStep.GetPersistentEventCount() > 0 || StepInfoReceiver) { UseEvents = true; } else { UseEvents = false; } } #region Editor Code (void Reset()) #if UNITY_EDITOR [HideInInspector] public LegsAnimatorControlModuleBase _Editor_DefaultModuleOnStart; [HideInInspector] public LegsAnimatorControlModuleBase _Editor_LegHelperModule; protected virtual void Reset() { MotionInfluence = new MotionInfluenceProcessor(); MotionInfluence.AxisMotionInfluence.x = 0f; BaseLegAnimating = new LegStepAnimatingParameters(); LegAnimatingSettings.RefreshDefaultCurves(); CustomModules = new System.Collections.Generic.List(); var helper = new LegsAnimatorCustomModuleHelper(this); helper.ModuleReference = _Editor_DefaultModuleOnStart; if (helper.ModuleReference == null) return; CustomModules.Add(helper); } #endif #endregion Editor Code (void Reset()) } }