using Cysharp.Threading.Tasks; using System.Threading; using TMPro; using UnityEngine; using UnityEngine.UI; namespace Learn { public class TipView : MonoBehaviour { [SerializeField] private CanvasGroup group; [SerializeField] private CanvasGroup tlButton, trButton, blButton, brButton; [SerializeField] TextMeshProUGUI tipLabel; [SerializeField] private Image tipImage; private CancellationTokenSource animationCts; public void Configure(Tip tip) { group.alpha = 0; tlButton.alpha = 0; trButton.alpha = 0; blButton.alpha = 0; brButton.alpha = 0; tipLabel.text = tip.text; CanvasGroup btn = tip.signal switch { InSignal.UpLeft => tlButton, InSignal.UpRight => trButton, InSignal.DownLeft => blButton, InSignal.DownRight => brButton, _ => null }; btn.alpha = 1; if (tip.voiceClip != null) { SoundManager.PlayReplica(tip.voiceClip); } } private async UniTask AnimateImage() { animationCts?.Cancel(); animationCts = new CancellationTokenSource(); float time = 0; while (!animationCts.Token.IsCancellationRequested) { time += Time.deltaTime * 2f; float scale = 1f + Mathf.Sin(time) * 0.05f; tipImage.transform.localScale = Vector3.one * scale; await UniTask.Yield(animationCts.Token); } } public async UniTask Show(CancellationToken ct) { StopAnimation(); float t = Mathf.InverseLerp(0, 1, group.alpha); await LerpAlpha(0, 1, 1.5f, group, ct, t); } public async UniTask Hide(CancellationToken ct) { StopAnimation(); float t = Mathf.InverseLerp(1, 0, group.alpha); await LerpAlpha(1, 0, 1.5f, group, ct, t); } public void Hide() { group.alpha = 0; } private void StopAnimation() { animationCts?.Cancel(); animationCts?.Dispose(); animationCts = null; } private async UniTask LerpAlpha(float from, float to, float speed, CanvasGroup cg, CancellationToken ct, float initialT = 0) { float t = initialT; while (t < 1 && !ct.IsCancellationRequested) { t += Time.deltaTime * speed; t = Mathf.Min(t, 1); cg.alpha = Mathf.Lerp(from, to, t); await UniTask.Yield(ct); } cg.alpha = to; } private void OnDestroy() { StopAnimation(); } } }