2025-09-24 11:24:38 +05:00

246 lines
5.0 KiB
C#

using System;
using UnityEngine;
using DG.Tweening;
namespace TPSBR
{
public class SimpleAnimation : CoreBehaviour
{
// PUBLIC MEMBERS
public float StartDelay;
public Animation Translation;
public Animation Rotation;
public Animation Scale;
[Space]
public bool PlayAutomatically = true;
public bool ResetOnStop = true;
public bool IsPlaying => Translation.HasStarted == true || Rotation.HasStarted == true || Scale.HasStarted;
// PRIVATE MEMBERS
private bool _hasStarted;
private float _delay;
private bool _playReversed;
// PUBLIC METHODS
public void Play(float delay, bool forceRestart = false)
{
if (IsPlaying == true && forceRestart == false)
return;
Stop();
_playReversed = false;
Translation.TryStart(transform.localPosition);
Rotation.TryStart(transform.localRotation.eulerAngles);
Scale.TryStart(transform.localScale);
_delay = delay;
}
public void PlayReversed(float delay)
{
Stop();
_playReversed = true;
Translation.TryStart(transform.localPosition);
Rotation.TryStart(transform.localRotation.eulerAngles);
Scale.TryStart(transform.localScale);
_delay = delay;
}
public void Stop()
{
if (ResetOnStop == true)
{
if (Translation.HasStarted == true)
{
transform.localPosition = Translation.RestartValue;
}
if (Rotation.HasStarted == true)
{
transform.localRotation = Quaternion.Euler(Rotation.RestartValue);
}
if (Scale.HasStarted == true)
{
transform.localScale = Scale.RestartValue;
}
_playReversed = false;
}
Translation.Stop();
Rotation.Stop();
Scale.Stop();
}
// MONOBEHAVIOR
protected void OnEnable()
{
if (PlayAutomatically == true)
{
_delay = StartDelay;
}
}
protected void Update()
{
_delay -= Time.deltaTime;
if (_delay > 0)
return;
if (_hasStarted == false && PlayAutomatically == true)
{
_hasStarted = true;
Play(0f);
}
if (Translation.CanUpdate == true)
{
transform.localPosition = Translation.Update(_playReversed);
}
if (Rotation.CanUpdate == true)
{
transform.localRotation = Quaternion.Euler(Rotation.Update(_playReversed));
}
if (Scale.CanUpdate == true)
{
transform.localScale = Scale.Update(_playReversed);
}
}
protected void OnDisable()
{
Stop();
_hasStarted = false;
_delay = 0f;
}
// HELPERS
[Serializable]
public class Animation
{
// PUBLIC MEMBERS
public Vector3 Value;
public Ease Ease = Ease.Linear;
public float Duration;
public float Delay;
public EPlayBehavior Behavior = EPlayBehavior.Once;
public bool ValueIsAbsolute;
public EDirection Direction = EDirection.FromTransformValues;
public bool HasStarted => _hasStarted;
public bool CanUpdate => _hasStarted == true && _isFinished == false;
public Vector3 RestartValue => _restartValue;
// PRIVATE MEMBERS
private bool _hasStarted;
private bool _isFinished;
private Vector3 _restartValue;
private float _currentTime;
private Vector3 _start;
private Vector3 _target;
// PUBLIC METHODS
public void TryStart(Vector3 initialValue)
{
_hasStarted = Behavior != EPlayBehavior.None && Value != Vector3.zero && Duration > 0;
if (_hasStarted == false)
return;
if (Direction == EDirection.FromTransformValues)
{
_restartValue = _start = initialValue;
_target = ValueIsAbsolute == true ? Value : _start + Value;
}
else
{
_restartValue = initialValue;
_start = ValueIsAbsolute == true ? Value : initialValue - Value;
_target = initialValue;
}
_currentTime = -Delay;
_isFinished = false;
}
public void Stop()
{
_hasStarted = false;
_isFinished = false;
}
public Vector3 Update(bool reversed)
{
_currentTime += Time.deltaTime;
if (_currentTime >= Duration)
{
if (Behavior == EPlayBehavior.Once)
{
_isFinished = true;
return reversed == true ? _start : _target;
}
else if (Behavior == EPlayBehavior.Restart)
{
_currentTime = _currentTime - Duration - Delay;
}
else if (Behavior == EPlayBehavior.PingPong)
{
var previousStart = _start;
_start = _target;
_target = previousStart;
_currentTime = _currentTime - Duration - Delay;
}
else if (Behavior == EPlayBehavior.Continue)
{
var delta = _target - _start;
_start = _target;
_target = _target + delta;
_currentTime = _currentTime - Duration - Delay;
}
}
float linearProgress = reversed == true ? 1f - _currentTime / Duration : _currentTime / Duration;
float progress = DOVirtual.EasedValue(0f, 1f, linearProgress, Ease);
return Vector3.Lerp(_start, _target, progress);
}
}
public enum EPlayBehavior
{
None,
Once,
Restart,
PingPong,
Continue,
}
public enum EDirection
{
FromTransformValues,
ToTransformValues,
}
}
}