using System.Collections.Generic;
using BrewMonster.Scripts;
namespace BrewMonster
{
public sealed class FadeOutGfx
{
public int m_dwTotalTTL;
public int m_dwTTL;
public GFX_BINDING m_pGfx;
public float m_fAlpha;
}
///
/// Queues skill/combined-action GFX for delayed stop (fade-out window), aligned with A3DGFXExMan::UpdateFadeOutGfxLst.
///
public class A3DGfxMan : IAutoInitialize, ITickable
{
public const int DefaultFadeOutMs = 1000;
private static A3DGfxMan _instance;
readonly Dictionary> _releaseByModel = new Dictionary>();
readonly List _fadeOutList = new List();
readonly List _flushBuffer = new List();
public static A3DGfxMan Instance => _instance ??= new A3DGfxMan();
public void Initialize()
{
_instance = this;
TickInvoker.Instance.RegisterTickable(this);
}
public bool Tick(uint dwDeltaTime)
{
if (_fadeOutList.Count == 0)
return true;
int deltaTime = (int)dwDeltaTime;
for (int i = _fadeOutList.Count - 1; i >= 0; i--)
{
FadeOutGfx entry = _fadeOutList[i];
GFX_BINDING gfx = entry.m_pGfx;
if (gfx == null)
{
_fadeOutList.RemoveAt(i);
continue;
}
entry.m_dwTTL -= deltaTime;
if (entry.m_dwTTL > 0)
{
_fadeOutList[i] = entry;
continue;
}
gfx.Stop();
_fadeOutList.RemoveAt(i);
}
return true;
}
public void Dispose()
{
_fadeOutList.Clear();
_releaseByModel.Clear();
_flushBuffer.Clear();
}
public void AddReleaseGfx(int modelId, GFX_BINDING gfx)
{
if (gfx == null)
return;
if (!_releaseByModel.TryGetValue(modelId, out List list))
{
list = new List(4);
_releaseByModel[modelId] = list;
}
list.Add(gfx);
}
public int GetPendingReleaseCount(int modelId)
{
return _releaseByModel.TryGetValue(modelId, out List list) ? list.Count : 0;
}
///
/// Fade out the oldest pending GFX for a model (cast/chant phase snapshot).
/// 淡出该模型最早注册的 maxCount 个待释放特效(吟唱阶段快照)。
///
public void FadeOutReleaseUpTo(int modelId, int maxCount, int fadeMs = DefaultFadeOutMs)
{
if (maxCount <= 0
|| !_releaseByModel.TryGetValue(modelId, out List releaseList)
|| releaseList.Count == 0)
return;
int count = maxCount < releaseList.Count ? maxCount : releaseList.Count;
QueueFadeOutFromReleaseList(releaseList, count, fadeMs);
if (releaseList.Count == 0)
_releaseByModel.Remove(modelId);
}
///
/// Fade out every pending combined-action GFX registered for a model.
/// 淡出该模型所有待释放的组合动作特效。
///
public void FadeOutGfx(int modelId, int fadeMs = DefaultFadeOutMs)
{
if (!_releaseByModel.TryGetValue(modelId, out List releaseList)
|| releaseList.Count == 0)
return;
QueueFadeOutFromReleaseList(releaseList, releaseList.Count, fadeMs);
_releaseByModel.Remove(modelId);
}
void QueueFadeOutFromReleaseList(List releaseList, int count, int fadeMs)
{
_flushBuffer.Clear();
for (int i = 0; i < count; i++)
{
GFX_BINDING gfx = releaseList[i];
if (gfx != null)
_flushBuffer.Add(gfx);
}
releaseList.RemoveRange(0, count);
for (int i = 0; i < _flushBuffer.Count; i++)
{
GFX_BINDING gfx = _flushBuffer[i];
if (gfx == null)
continue;
_fadeOutList.Add(new FadeOutGfx
{
m_dwTotalTTL = fadeMs,
m_dwTTL = fadeMs,
m_pGfx = gfx,
m_fAlpha = 1f,
});
}
_flushBuffer.Clear();
}
}
}