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())
}
}