Files
crtr/Assets/Cryville/Crtr/Skin/EffectGroup.cs

75 lines
1.9 KiB
C#

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<EffectInstance> {
readonly List<EffectInstance> _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<float, EffectInstance> _instances
= new();
readonly List<EffectInstance> _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();
}
}
}