using Cryville.Common.Buffers; using System.Collections.Generic; using UnityEngine; namespace Cryville.Crtr.Skin { public class EffectGroup { public EffectDefinition Definition { get; private set; } readonly EffectPool _pool; class EffectPool : ObjectPool { readonly List _instances = new(); readonly EffectGroup _group; public EffectPool(EffectGroup group) : base(256) { _group = group; } protected override EffectInstance Construct() { var result = new EffectInstance(_group.Definition); _instances.Add(result); return result; } public void DisposeAll() { foreach (var i in _instances) i.Dispose(); } } readonly Dictionary _instances = new(); readonly List _endQueue = new(); public EffectGroup(EffectDefinition def) { Definition = def; _pool = new EffectPool(this); } double _time; public void Tick(double time) { _time = time; while (_endQueue.Count > 0) { var item = _endQueue[0]; if (item.EndTime > _time) break; _endQueue.RemoveAt(0); if (item.OnStateDone()) { QueueInstance(item); } else { item.Tick(time); _instances.Remove(item.Index); _pool.Return(item); } } foreach (var instance in _instances) { instance.Value.Tick(time); } } public void Emit(float index, Transform target = null) { bool flag = _instances.TryGetValue(index, out EffectInstance instance); if (!flag) _instances.Add(index, instance = _pool.Rent()); instance.Index = index; if (instance.CanEmit()) { if (flag) { var i = _endQueue.BinarySearch(instance); _endQueue.RemoveAt(i); } instance.OnEmit(_time, target); QueueInstance(instance); } } void QueueInstance(EffectInstance i) { var index = ~_endQueue.BinarySearch(i); _endQueue.Insert(index, i); } public void Dispose() { _pool.DisposeAll(); } } }