157 lines
4.7 KiB
C#
157 lines
4.7 KiB
C#
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;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Queues skill/combined-action GFX for delayed stop (fade-out window), aligned with A3DGFXExMan::UpdateFadeOutGfxLst.
|
|
/// </summary>
|
|
public class A3DGfxMan : IAutoInitialize, ITickable
|
|
{
|
|
public const int DefaultFadeOutMs = 1000;
|
|
|
|
private static A3DGfxMan _instance;
|
|
|
|
readonly Dictionary<int, List<GFX_BINDING>> _releaseByModel = new Dictionary<int, List<GFX_BINDING>>();
|
|
readonly List<FadeOutGfx> _fadeOutList = new List<FadeOutGfx>();
|
|
readonly List<GFX_BINDING> _flushBuffer = new List<GFX_BINDING>();
|
|
|
|
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<GFX_BINDING> list))
|
|
{
|
|
list = new List<GFX_BINDING>(4);
|
|
_releaseByModel[modelId] = list;
|
|
}
|
|
|
|
list.Add(gfx);
|
|
}
|
|
|
|
public int GetPendingReleaseCount(int modelId)
|
|
{
|
|
return _releaseByModel.TryGetValue(modelId, out List<GFX_BINDING> list) ? list.Count : 0;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Fade out the oldest <paramref name="maxCount"/> pending GFX for a model (cast/chant phase snapshot).
|
|
/// 淡出该模型最早注册的 maxCount 个待释放特效(吟唱阶段快照)。
|
|
/// </summary>
|
|
public void FadeOutReleaseUpTo(int modelId, int maxCount, int fadeMs = DefaultFadeOutMs)
|
|
{
|
|
if (maxCount <= 0
|
|
|| !_releaseByModel.TryGetValue(modelId, out List<GFX_BINDING> releaseList)
|
|
|| releaseList.Count == 0)
|
|
return;
|
|
|
|
int count = maxCount < releaseList.Count ? maxCount : releaseList.Count;
|
|
QueueFadeOutFromReleaseList(releaseList, count, fadeMs);
|
|
|
|
if (releaseList.Count == 0)
|
|
_releaseByModel.Remove(modelId);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Fade out every pending combined-action GFX registered for a model.
|
|
/// 淡出该模型所有待释放的组合动作特效。
|
|
/// </summary>
|
|
public void FadeOutGfx(int modelId, int fadeMs = DefaultFadeOutMs)
|
|
{
|
|
if (!_releaseByModel.TryGetValue(modelId, out List<GFX_BINDING> releaseList)
|
|
|| releaseList.Count == 0)
|
|
return;
|
|
|
|
QueueFadeOutFromReleaseList(releaseList, releaseList.Count, fadeMs);
|
|
_releaseByModel.Remove(modelId);
|
|
}
|
|
|
|
void QueueFadeOutFromReleaseList(List<GFX_BINDING> 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();
|
|
}
|
|
}
|
|
}
|