2024-11-03 16:42:23 +08:00
|
|
|
|
using System;
|
2025-02-24 23:03:39 +08:00
|
|
|
|
using System.Collections.Concurrent;
|
2024-11-03 16:42:23 +08:00
|
|
|
|
using System.Collections.Generic;
|
2024-11-13 17:47:45 +08:00
|
|
|
|
using Cysharp.Threading.Tasks;
|
2024-11-03 16:42:23 +08:00
|
|
|
|
|
|
|
|
|
namespace BITKit
|
|
|
|
|
{
|
|
|
|
|
public interface IValidHandle
|
|
|
|
|
{
|
|
|
|
|
bool Allow { get; }
|
|
|
|
|
void AddElement(object obj);
|
|
|
|
|
void RemoveElement(object obj);
|
|
|
|
|
void AddDisableElements(object obj);
|
|
|
|
|
void RemoveDisableElements(object obj);
|
|
|
|
|
void SetElements(object obj, bool add = true);
|
|
|
|
|
void SetDisableElements(object obj, bool add = true);
|
|
|
|
|
void Invoke();
|
|
|
|
|
void Invoke(bool value);
|
|
|
|
|
void AddListener(Action<bool> action);
|
|
|
|
|
void RemoveListener(Action<bool> action);
|
|
|
|
|
void Clear();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[CustomType(typeof(IValidHandle))]
|
2024-12-28 23:19:55 +08:00
|
|
|
|
public sealed class ValidHandle: IValidHandle,IDisposable
|
2024-11-03 16:42:23 +08:00
|
|
|
|
{
|
2024-11-13 17:47:45 +08:00
|
|
|
|
public class MyHandle:IDisposable
|
|
|
|
|
{
|
|
|
|
|
private readonly ValidHandle _validHandle;
|
2025-03-04 16:34:27 +08:00
|
|
|
|
private readonly bool _isDisable;
|
2024-11-13 17:47:45 +08:00
|
|
|
|
public MyHandle(ValidHandle validHandle,bool isDisable = false)
|
|
|
|
|
{
|
|
|
|
|
_validHandle = validHandle;
|
|
|
|
|
|
|
|
|
|
_isDisable = isDisable;
|
|
|
|
|
if (isDisable)
|
|
|
|
|
{
|
|
|
|
|
_validHandle.AddDisableElements(this);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
_validHandle.AddElement(this);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
public void Dispose()
|
|
|
|
|
{
|
|
|
|
|
if (_isDisable)
|
|
|
|
|
{
|
|
|
|
|
_validHandle.RemoveDisableElements(this);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
_validHandle.RemoveElement(this);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public MyHandle GetHandle() => new MyHandle(this);
|
|
|
|
|
public MyHandle GetDisableHandle()=> new MyHandle(this,true);
|
|
|
|
|
|
2024-11-03 16:42:23 +08:00
|
|
|
|
public override string ToString()
|
|
|
|
|
{
|
2025-03-04 16:34:27 +08:00
|
|
|
|
return $"Allow:{_enableHandle}\nElements:{string.Join("\n",_objs)}\nDisableElements:{string.Join("\n",_disableObjs)}";
|
2024-11-03 16:42:23 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public ValidHandle() {}
|
|
|
|
|
public ValidHandle(Action<bool> boolDelegate)
|
|
|
|
|
{
|
|
|
|
|
AddListener(boolDelegate);
|
2025-03-04 16:34:27 +08:00
|
|
|
|
_eventOnEnableChanged?.Invoke(_enableHandle);
|
2024-11-03 16:42:23 +08:00
|
|
|
|
}
|
|
|
|
|
public static implicit operator bool(ValidHandle validHandle)
|
|
|
|
|
{
|
2025-03-04 16:34:27 +08:00
|
|
|
|
return !validHandle._isDisposed && validHandle._enableHandle;
|
2024-11-03 16:42:23 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public bool Allow => this;
|
|
|
|
|
|
2025-03-04 16:34:27 +08:00
|
|
|
|
private bool _enableHandle;
|
2024-11-03 16:42:23 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
/// ⚠️Dont operate this field directly
|
|
|
|
|
/// </summary>
|
2025-03-04 16:34:27 +08:00
|
|
|
|
private readonly HashSet<object> _objs = new();
|
|
|
|
|
|
2024-11-03 16:42:23 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
/// ⚠️Dont operate this field directly
|
|
|
|
|
/// </summary>
|
2025-03-04 16:34:27 +08:00
|
|
|
|
private readonly HashSet<object> _disableObjs = new();
|
|
|
|
|
private bool _tempEnable;
|
|
|
|
|
private Action<bool> _eventOnEnableChanged;
|
2025-02-24 23:03:39 +08:00
|
|
|
|
private readonly ConcurrentQueue<UniTaskCompletionSource> _completionSources = new();
|
2024-12-28 23:19:55 +08:00
|
|
|
|
private bool _isDisposed;
|
2024-11-03 16:42:23 +08:00
|
|
|
|
|
|
|
|
|
public void AddElement(object obj)
|
|
|
|
|
{
|
2025-03-04 16:34:27 +08:00
|
|
|
|
_objs.Add(obj);
|
2024-11-03 16:42:23 +08:00
|
|
|
|
CheckEnable();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void CheckEnable()
|
|
|
|
|
{
|
2025-03-04 16:34:27 +08:00
|
|
|
|
_tempEnable = _objs.Count > 0 && _disableObjs.Count == 0;
|
|
|
|
|
if (_tempEnable == _enableHandle) return;
|
|
|
|
|
_enableHandle = _tempEnable;
|
|
|
|
|
_eventOnEnableChanged?.Invoke(_enableHandle);
|
|
|
|
|
if (_tempEnable) return;
|
|
|
|
|
if (_completionSources.TryDequeue(out var cs))
|
2024-11-03 16:42:23 +08:00
|
|
|
|
{
|
2025-03-04 16:34:27 +08:00
|
|
|
|
cs.TrySetResult();
|
2024-11-03 16:42:23 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
public void RemoveElement(object obj)
|
|
|
|
|
{
|
2025-03-04 16:34:27 +08:00
|
|
|
|
if (_objs.Contains(obj))
|
2024-11-03 16:42:23 +08:00
|
|
|
|
{
|
2025-03-04 16:34:27 +08:00
|
|
|
|
_objs.Remove(obj);
|
2024-11-03 16:42:23 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
CheckEnable();
|
|
|
|
|
}
|
2025-03-04 16:34:27 +08:00
|
|
|
|
public int Lenght => _objs.Count;
|
|
|
|
|
public bool Contains(object obj) => _objs.Contains(obj);
|
2024-11-03 16:42:23 +08:00
|
|
|
|
public void AddDisableElements(object obj)
|
|
|
|
|
{
|
2025-03-04 16:34:27 +08:00
|
|
|
|
_disableObjs.Add(obj);
|
2024-11-03 16:42:23 +08:00
|
|
|
|
CheckEnable();
|
|
|
|
|
}
|
|
|
|
|
public void RemoveDisableElements(object obj)
|
|
|
|
|
{
|
2025-03-04 16:34:27 +08:00
|
|
|
|
if (_disableObjs.Contains(obj))
|
2024-11-03 16:42:23 +08:00
|
|
|
|
{
|
2025-03-04 16:34:27 +08:00
|
|
|
|
_disableObjs.Remove(obj);
|
2024-11-03 16:42:23 +08:00
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
CheckEnable();
|
|
|
|
|
}
|
|
|
|
|
public void SetElements(object obj, bool add = true)
|
|
|
|
|
{
|
|
|
|
|
if (add)
|
|
|
|
|
{
|
|
|
|
|
AddElement(obj);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
RemoveElement(obj);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
public void SetDisableElements(object obj, bool add = true)
|
|
|
|
|
{
|
|
|
|
|
if (add)
|
|
|
|
|
{
|
|
|
|
|
AddDisableElements(obj);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
RemoveDisableElements(obj);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
public void Invoke()
|
|
|
|
|
{
|
2025-03-04 16:34:27 +08:00
|
|
|
|
var enable = _disableObjs.Count == 0 && _objs.Count > 0;
|
|
|
|
|
_eventOnEnableChanged?.Invoke(enable);
|
2024-11-03 16:42:23 +08:00
|
|
|
|
}
|
|
|
|
|
public void Invoke(bool value)
|
|
|
|
|
{
|
2025-03-04 16:34:27 +08:00
|
|
|
|
_eventOnEnableChanged?.Invoke(value);
|
2024-11-03 16:42:23 +08:00
|
|
|
|
}
|
|
|
|
|
public void AddListener(Action<bool> action)
|
|
|
|
|
{
|
2025-03-04 16:34:27 +08:00
|
|
|
|
_eventOnEnableChanged+= action;
|
2024-11-03 16:42:23 +08:00
|
|
|
|
}
|
|
|
|
|
public void RemoveListener(Action<bool> action)
|
|
|
|
|
{
|
2025-03-04 16:34:27 +08:00
|
|
|
|
if(_eventOnEnableChanged is not null && action is not null)
|
2024-11-03 16:42:23 +08:00
|
|
|
|
{
|
2025-03-04 16:34:27 +08:00
|
|
|
|
_eventOnEnableChanged -= action;
|
2024-11-03 16:42:23 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
2024-11-13 17:47:45 +08:00
|
|
|
|
public UniTask.Awaiter GetAwaiter()
|
|
|
|
|
{
|
|
|
|
|
if (Allow is false)
|
|
|
|
|
{
|
|
|
|
|
return UniTask.CompletedTask.GetAwaiter();
|
|
|
|
|
}
|
|
|
|
|
var cs = new UniTaskCompletionSource();
|
|
|
|
|
_completionSources.Enqueue(cs);
|
|
|
|
|
return cs.Task.GetAwaiter();
|
|
|
|
|
}
|
2024-11-03 16:42:23 +08:00
|
|
|
|
public void Clear()
|
|
|
|
|
{
|
2025-03-04 16:34:27 +08:00
|
|
|
|
_objs.Clear();
|
|
|
|
|
_disableObjs.Clear();
|
2024-11-03 16:42:23 +08:00
|
|
|
|
Invoke();
|
|
|
|
|
}
|
2024-12-28 23:19:55 +08:00
|
|
|
|
|
|
|
|
|
public void Dispose()
|
|
|
|
|
{
|
|
|
|
|
_isDisposed = true;
|
2025-03-04 16:34:27 +08:00
|
|
|
|
_objs.Clear();
|
|
|
|
|
_disableObjs.Clear();
|
|
|
|
|
_eventOnEnableChanged = null;
|
2024-12-28 23:19:55 +08:00
|
|
|
|
}
|
2024-11-03 16:42:23 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|