BITKit/Src/Core/Group/ActivableGroup.cs

134 lines
3.7 KiB
C#

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<T> : IEntryGroup where T : IEntryElement
{
public int index = -1;
public List<T> list = new();
private int m_index = -1;
private bool completed=true;
public event Action<T> OnEntry;
public event Action<T> 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<T,bool> 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)
{
BIT4Log.LogException(e);
}
}
}
}