using System;
using System.Collections.Generic;
using UnityEngine;
using XGame.Framework.Asset;
using XGame.Framework.Asyncs;
using XGame.Framework.Interfaces;
namespace XGame.Framework.Map
{
public class MapModule : IMapModule, IUpdate, ILateUpdate, IMapContextSetter, IDisposable
{
private MapContext _context;
private Transform _mapRoot;
private IAssetModule _assetModule;
///
/// 加载中的
///
private Dictionary _loadingMap;
///
/// 已打开的
///
private Dictionary _openedMap;
///
/// 已关闭的
///
private Dictionary _closedMap;
///
/// pdate 和 LateUpdate用
///
private List _updates;
public MapModule(IAssetModule assetModule, Transform root)
{
_assetModule = assetModule;
_mapRoot = root;
_loadingMap = new Dictionary();
_openedMap = new Dictionary();
_closedMap = new Dictionary();
_updates = new List();
}
#region 接口实现
public MapContext Context { get => _context; set => _context = value; }
IAsync IMapModule.RunAsync(MapKey mapKey, object intent)
{
string key = mapKey;
if (_loadingMap.ContainsKey(key))
{
return _loadingMap[key];
}
var asyncGroup = new AsyncGroup();
if (_openedMap.ContainsKey(key))
{
Log.Warn($"重复打开地图:{key}");
}
else if (_closedMap.TryGetValue(key, out var closedView))
{ //已关闭的地图
asyncGroup.On(_ =>
{
_closedMap.Remove(key);
closedView.Behaviour.transform.SetAsLastSibling();
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 behaviour = loadAsync.Result;
if (behaviour == null)
{
Log.Error($"地图加载结果为空. MapKey:{key}");
return;
}
var view = Activator.CreateInstance(mapKey.MapViewType) as IMapView;
(view as IMapContextSetter).Context = _context.Clone();
view.Behaviour = behaviour;
behaviour.transform.SetParent(_mapRoot, false);
view.Enable(intent);
_openedMap.Add(key, view);
});
}
asyncGroup.End();
return asyncGroup;
}
void IMapModule.Close(MapKey mapKey, bool isDestroy)
{
if (mapKey == null)
return;
var key = mapKey.Key;
if (_loadingMap.TryGetValue(key, out var async))
{
_loadingMap.Remove(key);
async.RemoveAll();
return;
}
if (_openedMap.TryGetValue(key, out var mapView))
{
_openedMap.Remove(key);
mapView.Disable();
if (isDestroy)
{
DestroyView(mapView);
}
else
{
_closedMap.Add(key, mapView);
}
return;
}
if (isDestroy && _closedMap.TryGetValue(key, out mapView))
{
_closedMap.Remove(key);
DestroyView(mapView);
}
}
IAsync IMapModule.Preload(MapKey mapKey)
{
var loadAsync = _assetModule.PreloadAsync(mapKey);
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)
{
DestroyView(uiview);
}
_closedMap.Clear();
foreach (var uiview in _openedMap.Values)
{
DestroyView(uiview);
}
_openedMap.Clear();
GameObject.Destroy(_mapRoot.gameObject);
(_assetModule as IDisposable)?.Dispose();
_assetModule = null;
_context = null;
}
#endregion
private void DestroyView(IMapView view)
{
var behaviour = view.Behaviour;
(view as IDisposable).Dispose();
_assetModule.Recycle(behaviour.gameObject, true);
}
}
}