Files
ScienceLab.TimeAndSpace/Assets/Scripts/RewindManager.cs
2026-03-17 18:10:00 +02:00

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;
}
}