using System; using System.Collections.Generic; using System.Linq.Expressions; using Cysharp.Threading.Tasks; // ReSharper disable MethodHasAsyncOverload namespace BITKit { public interface IEntryGroup { } public interface IEntryElement { bool IsEntered { get; set; } void Entry(); UniTask EntryAsync(); void Entered(); void Exit(); UniTask ExitAsync(); void Exited(); } [System.Serializable] public class EntryGroup : IEntryGroup where T : IEntryElement { public int index = -1; public List list = new(); private int m_index = -1; private bool completed=true; public event Action OnEntry; public event Action OnExit; public void Entry(T t) { if (t is not null) { list.TryAdd(t); } index = list.IndexOf(t); EnsureConfiguration(); } public void Entry(int index) { if (index < list.Count) { this.index = index; } } public void Entry(Func entryFactory) { var index = list.FindIndex(x => entryFactory.Invoke(x)); Entry(index); } public void Entry() { index = 0; EnsureConfiguration(); } public void Exit() { index = -1; EnsureConfiguration(); } public bool TryGetEntried(out T value) { EnsureConfiguration(); if (m_index is not -1) { value = list[m_index]; return true; } value = default; return false; } private async void EnsureConfiguration() { try { if(completed is false) return; completed = false; if (index == m_index) { } else { var currentIndex = m_index; if (currentIndex is not -1 && list.TryGetElementAt(currentIndex, out var currentElement)) { currentElement.Exit(); try { await currentElement.ExitAsync(); } catch (OperationCanceledException) { return; } catch (Exception e) { BIT4Log.LogException(e); } currentElement.Exited(); currentElement.IsEntered = false; OnExit?.Invoke(currentElement); } m_index = index; if (index is not -1 && list.TryGetElementAt(index, out var nextElement)) { nextElement.IsEntered = true; OnEntry?.Invoke(nextElement); nextElement.Entry(); try { await nextElement.EntryAsync(); nextElement.Entered(); } catch (OperationCanceledException){} } } completed = true; } catch (Exception e) { #if UNITY_EDITOR UnityEngine.Debug.LogException(e); #else BIT4Log.LogException(e); #endif } } } }