using System;
using System.Collections.Generic;
using UnityEngine;
using XGame.Framework.Asset;
using XGame.Framework.Asyncs;
using XGame.Framework.Interfaces;
namespace XGame.Framework.UI
{
public class UIModule : IUIModule, IUpdate, ILateUpdate, IUIContextSetter, IDisposable, IUIAssetModuleCreator
{
private UIContext _context;
private IUITree _uitree;
private IAssetModule _assetModule;
///
/// 加载中的
///
private Dictionary _loadingMap;
///
/// 已打开的UI
///
private Dictionary _openedMap;
///
/// 已关闭的UI
///
private Dictionary _closedMap;
///
/// Update 和 LateUpdate用
///
private List _updates;
public UIModule(IAssetModule assetModule, IUITree uitree)
{
_assetModule = assetModule;
_uitree = uitree;
_loadingMap = new Dictionary();
_openedMap = new Dictionary();
_closedMap = new Dictionary();
_updates = new List();
}
public UIContext Context { get => _context; set => _context = value; }
#region 接口实现
Camera IUIModule.Camera => _uitree.Camera;
Canvas IUIModule.GetCanvas(UILayer layer)
{
return _uitree.GetCanvas(layer);
}
IAsync IUIModule.OpenAsync(UIKey uikey, object intent)
{
string key = uikey;
if (_loadingMap.ContainsKey(key))
{
return _loadingMap[key];
}
var asyncGroup = new AsyncGroup();
if (_openedMap.ContainsKey(key))
{
Log.Warn($"重复开启UI:{key}");
}
else if (_closedMap.TryGetValue(key, out var closedView))
{ // 已关闭的UI
asyncGroup.On(_ =>
{
_closedMap.Remove(key);
_uitree.SetAsLastSibling(closedView.Panel);
closedView.Enable(intent);
_openedMap.Add(key, closedView);
});
}
else
{
_loadingMap.Add(key, asyncGroup);
var loadAsync = _assetModule.LoadAsync(key);
loadAsync.Join(asyncGroup);
loadAsync.On(_ =>
{
_loadingMap.Remove(key);
var panel = loadAsync.Result;
if (panel == null)
{
Log.Error($"UI加载结果为空. UIKey:{key}");
return;
}
var view = Activator.CreateInstance(uikey.UIViewType) as IUIView;
var context = _context.Clone();
(context as IUIViewAdapter).Key = uikey;
(view as UIView).Init(context, panel);
_uitree.AddPanel(panel);
view.Enable(intent);
_openedMap.Add(key, view);
});
}
asyncGroup.End();
return asyncGroup;
}
void IUIModule.Close(UIKey uikey, bool isDestroy)
{
var key = uikey.Key;
if (_loadingMap.TryGetValue(key, out var async))
{
_loadingMap.Remove(key);
async.RemoveAll();
return;
}
if (_openedMap.TryGetValue(key, out var uiView))
{
_openedMap.Remove(key);
uiView.Disable();
if (isDestroy)
{
DestroyUIView(uiView);
}
else
{
_closedMap.Add(key, uiView);
}
return;
}
if (isDestroy && _closedMap.TryGetValue(key, out uiView))
{
_closedMap.Remove(key);
DestroyUIView(uiView);
}
}
IAsync IUIModule.Preload(UIKey uikey)
{
var loadAsync = _assetModule.PreloadAsync(uikey);
return loadAsync;
}
void IUpdate.Update(int millisecond)
{
if (_openedMap.Count == 0)
return;
_updates.Clear();
_updates.AddRange(_openedMap.Values);
for(var i = 0; i < _updates.Count;)
{
var view = _updates[i];
view.Update(millisecond);
if (view.Active)
{
i++;
}
else
{
_updates.RemoveAt(i);
}
}
}
void ILateUpdate.LateUpdate(int millisecond)
{
if (_updates.Count == 0)
return;
foreach (var uiview in _updates)
{
uiview.LateUpdate(millisecond);
}
_updates.Clear();
}
void IDisposable.Dispose()
{
_updates.Clear();
foreach (var async in _loadingMap.Values)
{
async.RemoveAll();
}
_loadingMap.Clear();
foreach (var uiview in _closedMap.Values)
{
DestroyUIView(uiview);
}
_closedMap.Clear();
foreach (var uiview in _openedMap.Values)
{
DestroyUIView(uiview);
}
_openedMap.Clear();
(_uitree as IDisposable)?.Dispose();
(_assetModule as IDisposable)?.Dispose();
_assetModule = null;
_context = null;
}
IUIAssetModule IUIAssetModuleCreator.Create(UIContext context)
{
return new UIAssetModule(context);
}
#endregion
#region 内部函数
private void DestroyUIView(IUIView view)
{
var uiPanel = view.Panel as UIPanel;
(view as IDisposable).Dispose();
_assetModule.Recycle(uiPanel.gameObject, true);
}
#endregion
}
}