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