158 lines
4.1 KiB
C#

using Cysharp.Threading.Tasks;
using System;
using System.Collections.Generic;
using System.Threading;
using TMPro;
using UnityEngine;
using UnityEngine.UI;
public class Instruction : MonoBehaviour
{
[Header("Exit progress")]
[SerializeField] private CanvasGroup progressGroup;
[SerializeField] private Image bar;
private bool groupVisible = false;
private float progress;
private CancellationTokenSource exitBarCts;
[Header("Instruction")]
[SerializeField] TextMeshProUGUI instructionLabel;
[SerializeField] CanvasGroup UpLeft, UpRight, DownLeft, DownRight, LabelCG;
[SerializeField] List<InstructionBlock> instructions;
private CancellationTokenSource instructionCts;
private Dictionary<InSignal, CanvasGroup> buttons;
public void SetProgress(float percent) => progress = percent;
public void Init()
{
buttons = new()
{
[InSignal.UpLeft] = UpLeft,
[InSignal.UpRight] = UpRight,
[InSignal.DownLeft] = DownLeft,
[InSignal.DownRight] = DownRight
};
instructionCts = new();
StartInstructionsSequence(instructionCts.Token).Forget();
SetProgress(0);
}
private void Update()
{
ProgressBarProcess();
}
private void OnDestroy()
{
instructionCts?.Cancel();
instructionCts?.Dispose();
exitBarCts?.Cancel();
exitBarCts?.Dispose();
}
private void ProgressBarProcess()
{
if (!groupVisible && progress > 0)
{
exitBarCts?.Cancel();
exitBarCts?.Dispose();
exitBarCts = new();
SetVisibility(true, exitBarCts.Token).Forget();
}
if (groupVisible && progress == 0)
{
exitBarCts?.Cancel();
exitBarCts?.Dispose();
exitBarCts = new();
SetVisibility(false, exitBarCts.Token).Forget();
}
bar.fillAmount = progress;
}
private async UniTask SetVisibility(bool visible, CancellationToken token)
{
float targetAlpha = visible ? 1 : 0;
groupVisible = visible;
while (progressGroup.alpha != targetAlpha && !token.IsCancellationRequested)
{
progressGroup.alpha = Mathf.MoveTowards(progressGroup.alpha, targetAlpha, Time.deltaTime);
await UniTask.Yield(PlayerLoopTiming.Update, token);
}
}
private async UniTask StartInstructionsSequence(CancellationToken token)
{
if (instructions == null) return;
if (instructions.Count == 0) return;
int instructionIndex = 0;
while (!token.IsCancellationRequested)
{
await ShowInstruction(instructions[instructionIndex], token);
instructionIndex = (instructionIndex + 1) % instructions.Count;
}
}
private async UniTask ShowInstruction(InstructionBlock instruction, CancellationToken token)
{
HideInstruction();
instructionLabel.text = instruction.text;
float t = 0;
//Зажигаем
while (!token.IsCancellationRequested && t < 1)
{
t += Time.deltaTime;
t = Mathf.Min(t, 1);
foreach (var signal in instruction.signals)
buttons[signal].alpha = t;
LabelCG.alpha = t;
await UniTask.Yield(token);
}
await UniTask.Delay(1000, cancellationToken: token);
t = 0;
//Тушим
while (!token.IsCancellationRequested && t < 1)
{
t += Time.deltaTime;
t = Mathf.Min(t, 1);
float oneMinus = 1 - t;
foreach (var signal in instruction.signals)
buttons[signal].alpha = oneMinus;
LabelCG.alpha = oneMinus;
await UniTask.Yield(token);
}
}
private void HideInstruction()
{
UpLeft.alpha = 0;
UpRight.alpha = 0;
DownLeft.alpha = 0;
DownRight.alpha = 0;
LabelCG.alpha = 0;
}
[Serializable]
private class InstructionBlock
{
public List<InSignal> signals;
[TextArea] public string text;
}
}