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(); } } }