using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace RR.Common.Controls
{
///
/// Строитель последовательности световых эффектов.
/// Создаётся через .
///
/// SetLight(LightMode.VerticalWave, 3).Then(LightMode.DiagonalWave, 3).Loop();
/// SetLight(LightMode.VerticalWave, 3).Then(LightMode.Off);
/// SetLight(LightMode.Rainbow, 5);
///
///
public class LightSequence
{
private readonly struct Step
{
public readonly LightMode Mode;
public readonly int DurationSeconds;
public Step(LightMode mode, int durationSeconds) { Mode = mode; DurationSeconds = durationSeconds; }
}
private readonly List _steps = new();
private readonly LightController _controller;
private bool _looping;
private Coroutine _coroutine;
internal LightSequence(LightController controller, LightMode firstMode, int firstDuration)
{
_controller = controller;
_steps.Add(new Step(firstMode, firstDuration));
}
/// Добавляет следующий эффект с временем по умолчанию.
public LightSequence Then(LightMode mode) => Then(mode, _controller.DefaultDuration);
/// Добавляет следующий эффект с указанным временем.
public LightSequence Then(LightMode mode, int durationSeconds)
{
_steps.Add(new Step(mode, durationSeconds));
return this;
}
///
/// Зацикливает последовательность. Для остановки — .
///
public LightSequence Loop()
{
_looping = true;
Play();
return this;
}
/// Запускает последовательность один раз.
public LightSequence Play()
{
Stop();
_coroutine = _controller.StartCoroutine(RunSequence());
return this;
}
/// Останавливает выполнение последовательности.
public void Stop()
{
if (_coroutine == null) return;
_controller.StopCoroutine(_coroutine);
_coroutine = null;
}
/// Возвращает true, если последовательность сейчас выполняется.
public bool IsPlaying => _coroutine != null;
// ReSharper disable once IteratorNeverReturns — цикл намеренно бесконечный при _looping=true
private IEnumerator RunSequence()
{
do
{
foreach (Step step in _steps)
{
_controller.SendCommand(step.Mode, step.DurationSeconds);
if (step.Mode != LightMode.Off && step.DurationSeconds > 0)
yield return new WaitForSecondsRealtime(step.DurationSeconds);
}
}
while (_looping);
_coroutine = null;
}
}
}