229 lines
7.1 KiB
C#
229 lines
7.1 KiB
C#
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using UnityEngine;
|
|
using UnityEngine.UI;
|
|
|
|
public class RewindManager : MonoBehaviour
|
|
{
|
|
[Header("Îá'ºêòè ñöåíè")]
|
|
public GameObject david;
|
|
public GameObject drone;
|
|
public ParticleSystem wave1PS;
|
|
public ParticleSystem wave2PS;
|
|
|
|
[Header("UI")]
|
|
public Slider rewindSlider;
|
|
|
|
private bool _recording = false;
|
|
private bool _rewinding = false;
|
|
private bool _animating = false;
|
|
|
|
private Vector3 _davidStartPos;
|
|
private Vector3 _droneStartPos;
|
|
private Vector3 _davidFinalPos;
|
|
private Vector3 _droneFinalPos;
|
|
|
|
private HeroMovement _heroMovement;
|
|
private DroneMovement _droneMovement;
|
|
private Animator _davidAnimator;
|
|
|
|
private int _stopFrameIndex = -1;
|
|
|
|
private struct FrameState
|
|
{
|
|
public float wave1Time;
|
|
public float wave2Time;
|
|
public bool wave1Active;
|
|
public bool wave2Active;
|
|
public int animStateHash;
|
|
public float animNormalizedTime;
|
|
}
|
|
|
|
private List<FrameState> _frames = new List<FrameState>();
|
|
|
|
void Awake()
|
|
{
|
|
if (david != null)
|
|
{
|
|
_davidStartPos = david.transform.position;
|
|
_heroMovement = david.GetComponentInChildren<HeroMovement>();
|
|
_davidAnimator = david.GetComponent<Animator>();
|
|
}
|
|
if (drone != null)
|
|
{
|
|
_droneStartPos = drone.transform.position;
|
|
_droneMovement = drone.GetComponentInChildren<DroneMovement>();
|
|
}
|
|
|
|
if (rewindSlider != null)
|
|
{
|
|
rewindSlider.gameObject.SetActive(false);
|
|
rewindSlider.onValueChanged.AddListener(OnSliderChanged);
|
|
}
|
|
|
|
_recording = true;
|
|
}
|
|
|
|
public void ShowSlider()
|
|
{
|
|
_recording = false;
|
|
_stopFrameIndex = _frames.Count - 1;
|
|
|
|
if (david != null) _davidFinalPos = david.transform.position;
|
|
if (drone != null) _droneFinalPos = drone.transform.position;
|
|
|
|
if (rewindSlider != null)
|
|
{
|
|
rewindSlider.maxValue = _frames.Count - 1;
|
|
rewindSlider.onValueChanged.RemoveListener(OnSliderChanged);
|
|
rewindSlider.value = _frames.Count - 1;
|
|
rewindSlider.onValueChanged.AddListener(OnSliderChanged);
|
|
rewindSlider.gameObject.SetActive(true);
|
|
}
|
|
}
|
|
|
|
void Update()
|
|
{
|
|
if (!_recording || _rewinding) return;
|
|
|
|
FrameState frame = new FrameState();
|
|
frame.wave1Active = wave1PS != null && wave1PS.gameObject.activeSelf;
|
|
frame.wave2Active = wave2PS != null && wave2PS.gameObject.activeSelf;
|
|
frame.wave1Time = frame.wave1Active ? wave1PS.time : 0f;
|
|
frame.wave2Time = frame.wave2Active ? wave2PS.time : 0f;
|
|
|
|
if (_davidAnimator != null && david != null && david.activeInHierarchy)
|
|
{
|
|
AnimatorStateInfo info = _davidAnimator.GetCurrentAnimatorStateInfo(0);
|
|
frame.animStateHash = info.fullPathHash;
|
|
frame.animNormalizedTime = info.normalizedTime;
|
|
}
|
|
|
|
_frames.Add(frame);
|
|
}
|
|
|
|
void OnSliderChanged(float value)
|
|
{
|
|
if (_animating) return;
|
|
if (_frames.Count == 0) return;
|
|
|
|
_rewinding = true;
|
|
Time.timeScale = 0f;
|
|
|
|
int index = Mathf.RoundToInt(value);
|
|
index = Mathf.Clamp(index, 0, _frames.Count - 1);
|
|
|
|
float t = _frames.Count > 1 ? (float)index / (_frames.Count - 1) : 1f;
|
|
|
|
if (david != null) david.transform.position = Vector3.Lerp(_davidStartPos, _davidFinalPos, t);
|
|
if (drone != null) drone.transform.position = Vector3.Lerp(_droneStartPos, _droneFinalPos, t);
|
|
|
|
FrameState frame = _frames[index];
|
|
|
|
if (_davidAnimator != null && frame.animStateHash != 0 && david != null && david.activeInHierarchy)
|
|
{
|
|
_davidAnimator.Play(frame.animStateHash, 0, frame.animNormalizedTime);
|
|
_davidAnimator.Update(0f);
|
|
}
|
|
|
|
if (wave1PS != null && frame.wave1Active)
|
|
{
|
|
wave1PS.gameObject.SetActive(true);
|
|
wave1PS.Stop(true, ParticleSystemStopBehavior.StopEmittingAndClear);
|
|
wave1PS.Simulate(frame.wave1Time, true, true);
|
|
}
|
|
|
|
if (wave2PS != null && frame.wave2Active)
|
|
{
|
|
wave2PS.gameObject.SetActive(true);
|
|
wave2PS.Stop(true, ParticleSystemStopBehavior.StopEmittingAndClear);
|
|
wave2PS.Simulate(frame.wave2Time, true, true);
|
|
}
|
|
}
|
|
|
|
public void OnSliderReleased(float savedValue)
|
|
{
|
|
if (_animating) return;
|
|
|
|
_animating = true;
|
|
_rewinding = false;
|
|
Time.timeScale = 1f;
|
|
|
|
int index = Mathf.RoundToInt(savedValue);
|
|
index = Mathf.Clamp(index, 0, _frames.Count - 1);
|
|
|
|
float animateTo = rewindSlider.maxValue;
|
|
|
|
if (_stopFrameIndex >= 0 && index < _stopFrameIndex)
|
|
{
|
|
GameManager.Instance?.GenerateSimV();
|
|
if (_heroMovement != null) _heroMovement.ResumeMoving();
|
|
if (_droneMovement != null) _droneMovement.ResumeMoving();
|
|
FindObjectOfType<DroneTrigger>()?.Reset();
|
|
FindObjectOfType<HeroTrigger>()?.Reset();
|
|
FindObjectOfType<RestartManager>()?.HideRestart();
|
|
_stopFrameIndex = -1;
|
|
|
|
if (_davidAnimator != null && david != null && david.activeInHierarchy)
|
|
{
|
|
_davidAnimator.Rebind();
|
|
_davidAnimator.Play("FastRun", 0, 0f);
|
|
_davidAnimator.Update(0f);
|
|
}
|
|
}
|
|
|
|
if (wave1PS != null && !_frames[index].wave1Active)
|
|
{
|
|
wave1PS.Stop();
|
|
wave1PS.gameObject.SetActive(false);
|
|
wave1PS.GetComponent<LightWave>()?.ResetText();
|
|
}
|
|
if (wave2PS != null && !_frames[index].wave2Active)
|
|
{
|
|
wave2PS.Stop();
|
|
wave2PS.gameObject.SetActive(false);
|
|
wave2PS.GetComponent<LightWave>()?.ResetText();
|
|
}
|
|
|
|
if (wave1PS != null && wave1PS.gameObject.activeSelf) wave1PS.Play();
|
|
if (wave2PS != null && wave2PS.gameObject.activeSelf) wave2PS.Play();
|
|
|
|
StartCoroutine(AnimateSlider(savedValue, animateTo));
|
|
}
|
|
|
|
public void FullReset()
|
|
{
|
|
StopAllCoroutines();
|
|
Time.timeScale = 1f;
|
|
_frames.Clear();
|
|
_stopFrameIndex = -1;
|
|
_rewinding = false;
|
|
_animating = false;
|
|
_recording = true;
|
|
|
|
if (rewindSlider != null)
|
|
{
|
|
rewindSlider.gameObject.SetActive(false);
|
|
rewindSlider.onValueChanged.RemoveListener(OnSliderChanged);
|
|
rewindSlider.value = 0f;
|
|
rewindSlider.onValueChanged.AddListener(OnSliderChanged);
|
|
}
|
|
}
|
|
|
|
private IEnumerator AnimateSlider(float from, float to)
|
|
{
|
|
rewindSlider.onValueChanged.RemoveListener(OnSliderChanged);
|
|
rewindSlider.maxValue = to;
|
|
float current = from;
|
|
while (current < to)
|
|
{
|
|
current += 60f * Time.unscaledDeltaTime;
|
|
current = Mathf.Min(current, to);
|
|
rewindSlider.value = current;
|
|
yield return null;
|
|
}
|
|
rewindSlider.onValueChanged.AddListener(OnSliderChanged);
|
|
_animating = false;
|
|
}
|
|
}
|