using System; using System.Threading; using Cysharp.Threading.Tasks; using UnityEngine; namespace Code.Infrastructure.Loadings { public class Loading { private int _progress; public bool Completed { get; private set; } private Action _completed; private Action _loadProgress; public Loading(int externalMaxProgress, Action completed, Action loadProgress = null) { _progress = externalMaxProgress; MaxProgress = externalMaxProgress; _completed = completed; _loadProgress = loadProgress; } /// /// Получаем текущее значение прогресса /// public int CurrentProgress => _progress; public int MaxProgress { get; private set; } /// /// Сдвигаем прогресс загрузки на 1 /// public void DoProgress() { _progress--; _loadProgress?.Invoke(this); if(_progress == 0) // Зачем инвертировать, если так читается лучше, райдер соси { Completed = true; _completed?.Invoke(); _cts?.Dispose(); } } /// /// Ждём заполнения шкалы прогресса /// public async UniTask FreezeTillDone() { _cts ??= new CancellationTokenSource(); try { await UniTask.WaitUntil(this, _ => Completed) .AttachExternalCancellation(_cts.Token) .SuppressCancellationThrow(); } catch (OperationCanceledException) { throw; } catch (Exception e) { Debug.LogException(e); throw; } } /// /// Привязать асинхронный процесс к выполнению загрузки. Сдвигает MaxProgress на 1 /// public Loading AttachProcess(Func process) { AddLoadProcess(process).Forget(); return this; } private CancellationTokenSource _cts; /// /// Привязать асинхронный процесс к выполнению загрузки. Сдвигает MaxProgress на 1 /// // Originally written by MrTorex https://github.com/MrTorex public async UniTaskVoid AddLoadProcess(Func loader) { _cts ??= new CancellationTokenSource(); MaxProgress++; _progress++; try { await loader().AttachExternalCancellation(_cts.Token); } catch (OperationCanceledException) { throw; } catch (Exception e) { Debug.LogException(e); throw; } finally { DoProgress(); } } } }