2025-09-05 19:46:30 +08:00
|
|
|
|
using System;
|
|
|
|
|
|
using AlicizaX;
|
2026-04-24 20:50:13 +08:00
|
|
|
|
using AlicizaX.Timer.Runtime;
|
2026-04-28 18:25:04 +08:00
|
|
|
|
using Cysharp.Text;
|
2025-09-05 19:46:30 +08:00
|
|
|
|
|
|
|
|
|
|
namespace AlicizaX.UI.Runtime
|
|
|
|
|
|
{
|
2026-03-26 16:14:05 +08:00
|
|
|
|
internal sealed partial class UIService
|
2025-09-05 19:46:30 +08:00
|
|
|
|
{
|
2026-03-09 20:13:40 +08:00
|
|
|
|
private readonly struct CacheEntry
|
|
|
|
|
|
{
|
|
|
|
|
|
public readonly UIMetadata Metadata;
|
2026-04-27 12:06:09 +08:00
|
|
|
|
public readonly ulong TimerHandle;
|
2026-03-09 20:13:40 +08:00
|
|
|
|
|
2026-04-27 12:06:09 +08:00
|
|
|
|
public CacheEntry(UIMetadata metadata, ulong timerHandle)
|
2026-03-09 20:13:40 +08:00
|
|
|
|
{
|
|
|
|
|
|
Metadata = metadata;
|
2026-04-27 12:06:09 +08:00
|
|
|
|
TimerHandle = timerHandle;
|
2026-03-09 20:13:40 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-04-28 18:25:04 +08:00
|
|
|
|
private CacheEntry[] m_CacheWindow = new CacheEntry[8];
|
|
|
|
|
|
private int[] m_CacheTypeIdToIndex = CreateCacheIndexArray(8);
|
|
|
|
|
|
private int m_CacheWindowCount;
|
2025-09-05 19:46:30 +08:00
|
|
|
|
|
|
|
|
|
|
private void CacheWindow(UIMetadata uiMetadata, bool force)
|
|
|
|
|
|
{
|
2025-12-24 20:44:36 +08:00
|
|
|
|
if (uiMetadata?.View?.Holder == null)
|
2025-09-05 19:46:30 +08:00
|
|
|
|
{
|
2025-12-24 20:44:36 +08:00
|
|
|
|
Log.Error("Cannot cache null UI metadata or holder");
|
2025-09-05 19:46:30 +08:00
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (force || uiMetadata.MetaInfo.CacheTime == 0)
|
|
|
|
|
|
{
|
2026-04-24 09:21:37 +08:00
|
|
|
|
uiMetadata.DisposeImmediate();
|
2025-09-05 19:46:30 +08:00
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-04-28 18:25:04 +08:00
|
|
|
|
RemoveFromCache(uiMetadata.MetaInfo.TypeId);
|
2026-04-27 12:06:09 +08:00
|
|
|
|
ulong timerHandle = 0UL;
|
2025-09-05 19:46:30 +08:00
|
|
|
|
|
|
|
|
|
|
uiMetadata.View.Holder.transform.SetParent(UICacheLayer);
|
|
|
|
|
|
if (uiMetadata.MetaInfo.CacheTime > 0)
|
|
|
|
|
|
{
|
2026-04-23 20:19:46 +08:00
|
|
|
|
ITimerService timerService = GetTimerService();
|
2026-04-27 12:06:09 +08:00
|
|
|
|
timerHandle = timerService.AddTimer(
|
2025-12-24 20:44:36 +08:00
|
|
|
|
OnTimerDisposeWindow,
|
2026-03-24 17:45:15 +08:00
|
|
|
|
uiMetadata,
|
2025-12-24 20:44:36 +08:00
|
|
|
|
uiMetadata.MetaInfo.CacheTime,
|
|
|
|
|
|
isLoop: false,
|
2026-04-24 20:50:13 +08:00
|
|
|
|
isUnscaled: true);
|
2025-12-24 20:44:36 +08:00
|
|
|
|
|
2026-04-27 12:06:09 +08:00
|
|
|
|
if (timerHandle == 0UL)
|
2025-12-24 20:44:36 +08:00
|
|
|
|
{
|
2026-04-28 18:25:04 +08:00
|
|
|
|
Log.Warning(ZString.Format("Failed to create cache timer for {0}", uiMetadata.UILogicType.Name));
|
2025-12-24 20:44:36 +08:00
|
|
|
|
}
|
2025-09-05 19:46:30 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
uiMetadata.InCache = true;
|
2026-04-28 18:25:04 +08:00
|
|
|
|
AddToCache(uiMetadata, timerHandle);
|
2025-09-05 19:46:30 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2026-03-24 17:45:15 +08:00
|
|
|
|
private void OnTimerDisposeWindow(UIMetadata meta)
|
2025-09-05 19:46:30 +08:00
|
|
|
|
{
|
2025-12-24 20:44:36 +08:00
|
|
|
|
if (meta != null)
|
|
|
|
|
|
{
|
2026-04-28 18:25:04 +08:00
|
|
|
|
RemoveFromCache(meta.MetaInfo.TypeId);
|
2026-04-23 20:39:58 +08:00
|
|
|
|
meta.DisposeImmediate();
|
2025-12-24 20:44:36 +08:00
|
|
|
|
}
|
2025-09-05 19:46:30 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2026-04-15 09:45:52 +08:00
|
|
|
|
private void RemoveFromCache(RuntimeTypeHandle typeHandle)
|
2025-09-05 19:46:30 +08:00
|
|
|
|
{
|
2026-04-28 18:25:04 +08:00
|
|
|
|
if (UIMetaRegistry.TryGet(typeHandle, out UIMetaRegistry.UIMetaInfo metaInfo))
|
2025-09-05 19:46:30 +08:00
|
|
|
|
{
|
2026-04-28 18:25:04 +08:00
|
|
|
|
RemoveFromCache(metaInfo.TypeId);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private void RemoveFromCache(int typeId)
|
|
|
|
|
|
{
|
|
|
|
|
|
if ((uint)typeId >= (uint)m_CacheTypeIdToIndex.Length)
|
|
|
|
|
|
{
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int index = m_CacheTypeIdToIndex[typeId];
|
|
|
|
|
|
if (index < 0 || index >= m_CacheWindowCount)
|
|
|
|
|
|
{
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
CacheEntry entry = m_CacheWindow[index];
|
|
|
|
|
|
int lastIndex = m_CacheWindowCount - 1;
|
|
|
|
|
|
CacheEntry last = m_CacheWindow[lastIndex];
|
|
|
|
|
|
m_CacheWindow[index] = last;
|
|
|
|
|
|
m_CacheWindow[lastIndex] = default;
|
|
|
|
|
|
m_CacheWindowCount = lastIndex;
|
|
|
|
|
|
m_CacheTypeIdToIndex[typeId] = -1;
|
|
|
|
|
|
if (index != lastIndex && last.Metadata != null)
|
|
|
|
|
|
{
|
|
|
|
|
|
m_CacheTypeIdToIndex[last.Metadata.MetaInfo.TypeId] = index;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
entry.Metadata.InCache = false;
|
|
|
|
|
|
if (entry.TimerHandle != 0UL && _timerService != null)
|
|
|
|
|
|
{
|
|
|
|
|
|
_timerService.RemoveTimer(entry.TimerHandle);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private void AddToCache(UIMetadata metadata, ulong timerHandle)
|
|
|
|
|
|
{
|
|
|
|
|
|
int typeId = metadata.MetaInfo.TypeId;
|
|
|
|
|
|
EnsureCacheIndexCapacity(typeId);
|
|
|
|
|
|
EnsureCacheCapacity();
|
|
|
|
|
|
int index = m_CacheWindowCount++;
|
|
|
|
|
|
m_CacheWindow[index] = new CacheEntry(metadata, timerHandle);
|
|
|
|
|
|
m_CacheTypeIdToIndex[typeId] = index;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private void EnsureCacheCapacity()
|
|
|
|
|
|
{
|
|
|
|
|
|
if (m_CacheWindowCount < m_CacheWindow.Length)
|
|
|
|
|
|
{
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Array.Resize(ref m_CacheWindow, m_CacheWindow.Length << 1);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private void EnsureCacheIndexCapacity(int typeId)
|
|
|
|
|
|
{
|
|
|
|
|
|
if ((uint)typeId < (uint)m_CacheTypeIdToIndex.Length)
|
|
|
|
|
|
{
|
|
|
|
|
|
return;
|
2025-09-05 19:46:30 +08:00
|
|
|
|
}
|
2026-04-28 18:25:04 +08:00
|
|
|
|
|
|
|
|
|
|
int oldLength = m_CacheTypeIdToIndex.Length;
|
|
|
|
|
|
int newLength = oldLength;
|
|
|
|
|
|
while (newLength <= typeId)
|
|
|
|
|
|
{
|
|
|
|
|
|
newLength <<= 1;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Array.Resize(ref m_CacheTypeIdToIndex, newLength);
|
|
|
|
|
|
for (int i = oldLength; i < newLength; i++)
|
|
|
|
|
|
{
|
|
|
|
|
|
m_CacheTypeIdToIndex[i] = -1;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private static int[] CreateCacheIndexArray(int capacity)
|
|
|
|
|
|
{
|
|
|
|
|
|
int[] values = new int[capacity];
|
|
|
|
|
|
for (int i = 0; i < values.Length; i++)
|
|
|
|
|
|
{
|
|
|
|
|
|
values[i] = -1;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return values;
|
2025-09-05 19:46:30 +08:00
|
|
|
|
}
|
2026-04-23 20:19:46 +08:00
|
|
|
|
|
|
|
|
|
|
private ITimerService GetTimerService()
|
|
|
|
|
|
{
|
|
|
|
|
|
if (_timerService != null)
|
|
|
|
|
|
{
|
|
|
|
|
|
return _timerService;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
_timerService = AppServices.Require<ITimerService>();
|
|
|
|
|
|
return _timerService;
|
|
|
|
|
|
}
|
2025-09-05 19:46:30 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|