using System;
using System.Collections.Generic;
using UnityEngine;
using Object = UnityEngine.Object;
namespace IcecreamView
{
///
/// icecream页面管理器,驱动页面的核心控制器,用于控制页面生成、展示、隐藏、跳转等操作
///
public sealed class IC_Controller : IDisposable
{
public static IC_Controller InstantiateViewManager (IC_IViewConfig gameViewConfig, Transform parent)
{
var IC = new IC_Controller ();
IC.Init (gameViewConfig, parent);
return IC;
}
private IC_ViewConfigGroup _config;
private List _viewPool;
public Transform BaseRoot;
public Dictionary Canvases;
private int _curFocusID = 0;
public IC_AbstractView CurFocusView { get; private set; }
public IC_UIEventManager EventManager { get; private set; }
public Action OnViewOpened;
public Action OnViewClosed;
public Action OnViewFocusChanged;
public void Init (IC_IViewConfig gameViewConfig, Transform baseRoot)
{
this._config = new IC_ViewConfigGroup ();
this.BaseRoot = baseRoot;
EventManager = new IC_UIEventManager ();
this._viewPool = new List ();
this.Canvases = new Dictionary ();
this._curFocusID = 0;
this.AddConfig (gameViewConfig);
}
public void Init (IC_IViewConfig gameViewConfig, IList nodes)
{
this._config = new IC_ViewConfigGroup ();
EventManager = new IC_UIEventManager ();
this._viewPool = new List ();
this.Canvases = new Dictionary ();
foreach (var canvasNode in nodes)
{
this.BindCanvas (canvasNode);
if (canvasNode.IsBaseCanvas)
this.BaseRoot = canvasNode.Canvas.transform;
}
this.AddConfig (gameViewConfig);
}
#region UI Method
public void BindCanvas (CanvasNode canvasNode)
{
this.Canvases[canvasNode.OrderRange] = canvasNode.Canvas;
}
///
/// 构建一个View对象
///
///
/// ViewTable
///
private IC_AbstractView CreateView (IC_IViewConfig config, string Table, string group = null)
{
var viewModle = config.OnAddView (Table);
IC_AbstractView gameViewAbstract = UnityEngine.Object.Instantiate (viewModle.GetView (), this.BaseRoot);
gameViewAbstract.VIEWTABLE = Table;
gameViewAbstract._configID = config.GetHashCode ();
gameViewAbstract._group = group;
// gameViewAbstract.transform.localRotation = Quaternion.Euler(Vector3.zero);
if (viewModle.IsOnce ())
{
gameViewAbstract.isOnce = viewModle.IsOnce ();
}
else
{
gameViewAbstract.isOnce = ContainsKeyView (Table);
}
gameViewAbstract.openCount = 0;
gameViewAbstract.SetViewManager (this);
gameViewAbstract.isOpen = false;
gameViewAbstract.OnInitView ();
return gameViewAbstract;
}
///
/// 获取指定页面
///
///
///
///
public T GetView (string table) where T : IC_AbstractView
{
if (ContainsKeyView (table))
{
for (int i = 0; i < this._viewPool.Count; i++)
{
if (table.Equals (this._viewPool[i].VIEWTABLE))
{
return (T) this._viewPool[i];
}
}
}
return default(T);
}
///
/// 获取指定table页面的指定Module
///
///
///
///
public T GetViewModule (string table) where T : IC_AbstractModule
{
var View = GetView (table);
if (View != null)
{
return View.GetViewModule ();
}
return null;
}
public IC_AbstractView OpenView (string table, string group, int sortingLayer, bool isSinge = true,
params IC_ViewData[] values)
{
return OpenView (table, group, sortingLayer, isSinge, null, values);
}
public IC_AbstractView OpenView (string table, string group, int sortingLayer, bool isSinge = true, Action onOpened = null ,
params IC_ViewData[] values)
{
int viewCount = getViewIndex (table, isSinge);
//如果已经存在相同页面
if (viewCount != -1)
{
var view = this._viewPool[viewCount];
if (view.isOpen)
{
view.OnHardCloseView ();
}
_curFocusID += 1;
view.openCount += 1;
view._group = group;
view.isOpen = true;
view.gameObject.SetActive (true);
this.SetSortOrder (view, sortingLayer);
view._focusID = _curFocusID;
view.onOpened = onOpened;
view.OnOpenView (values);
UpdateFocusView ();
this.OnViewOpened?.Invoke (view);
return view;
}
if (this._config.TryContainsKeyConfig (table , out var config))
{
IC_AbstractView gameViewAbstract = CreateView (config , table, group);
gameViewAbstract.isOpen = true;
gameViewAbstract.gameObject.SetActive (true);
this.SetSortOrder (gameViewAbstract, sortingLayer);
this._viewPool.Add (gameViewAbstract);
this._curFocusID += 1;
gameViewAbstract.openCount += 1;
gameViewAbstract._focusID = this._curFocusID;
gameViewAbstract.onOpened = onOpened;
gameViewAbstract.OnOpenView (values);
UpdateFocusView ();
this.OnViewOpened?.Invoke (gameViewAbstract);
return gameViewAbstract;
}
Debug.LogFormat ("{0}", "IC_Controller : 打开view失败,未找到指定table --- " + table);
return null;
}
public void SetSortOrder (IC_AbstractView view, int sortingLayer)
{
if (sortingLayer == -1)
sortingLayer = view.DefaultStory;
view.CurSortOrder = sortingLayer;
Transform viewTransform;
(viewTransform = view.transform).SetParent (GetCanvasParent (sortingLayer));
viewTransform.localScale = Vector3.one;
viewTransform.localPosition = Vector3.zero;
viewTransform.localRotation = Quaternion.identity;
Transform transform;
(transform = view.transform).SetAsLastSibling ();
var parent = transform.parent;
for (int i = parent.childCount - 2; i >= 0; i--)
{
var tView = parent.GetChild (i).GetComponent ();
if (tView is { gameObject: { activeSelf: true } })
{
if (view.CurSortOrder >= tView.CurSortOrder)
break;
else
view.transform.SetSiblingIndex (tView.transform.GetSiblingIndex ());
}
}
}
private Transform GetCanvasParent (int order)
{
foreach (var canvasesKey in this.Canvases.Keys)
{
if (order <= canvasesKey)
{
return this.Canvases[canvasesKey].transform;
}
}
return this.BaseRoot;
}
public IC_AbstractView OpenView (string table, int sortingLayer, bool isSinge = true,
params IC_ViewData[] values)
{
return OpenView (table, null, sortingLayer, isSinge, values);
}
public IC_AbstractView OpenView (string table, bool isSinge = true, params IC_ViewData[] values)
{
return OpenView (table, null, -1, isSinge, values);
}
public IC_AbstractView OpenView (string table, bool isSinge = true, Action onOpened = null, params IC_ViewData[] values)
{
return OpenView (table, null, -1, isSinge, values);
}
public IC_AbstractView OpenView (string table, params IC_ViewData[] values)
{
return OpenView (table, null, -1, true, values);
}
public IC_AbstractView OpenView (string table, Action onOpened, params IC_ViewData[] values)
{
return OpenView (table, null, -1, true, onOpened, values);
}
public IC_AbstractView OpenView (string table, string group, params IC_ViewData[] values)
{
return OpenView (table, group, -1, true, values);
}
///
/// 关闭所有页面 并打开指定页面
///
///
///
public IC_AbstractView OpenViewAndCloseOther (string table, bool isSinge, params IC_ViewData[] values)
{
if (table == null)
{
return null;
}
this.CloseAllView ();
IC_AbstractView view = OpenView (table, isSinge, values);
return view;
}
///
/// 提前缓存指定Table数组
///
///
internal void CacheView (List Tables)
{
foreach (var Table in Tables)
{
if (this._config.TryContainsKeyConfig (Table, out var config))
{
var view = CreateView (config, Table);
view.gameObject.SetActive (false);
this._viewPool.Add (view);
}
}
}
///
/// 缓存指定页面
///
///
///
internal void CacheView (string Table)
{
if (this._config.TryContainsKeyConfig (Table, out var config))
{
var view = CreateView (config, Table);
view.gameObject.SetActive (false);
this._viewPool.Add (view);
}
}
///
/// 判断指定table是否存在
///
///
///
public bool ContainsKeyView (string table)
{
for (int i = 0; i < this._viewPool.Count; i++)
{
if (table.Equals (this._viewPool[i].VIEWTABLE))
{
return true;
}
}
return false;
}
///
/// 判断指定table页面是否已存在
///
///
///
public bool IsOpenedView (string table)
{
for (int i = 0; i < this._viewPool.Count; i++)
{
var abstractView = this._viewPool[i];
if (table.Equals (abstractView.VIEWTABLE) && abstractView.isOpen)
{
return true;
}
}
return false;
}
///
/// 返回一个指定table的View对应下标
///
///
///
private int getViewIndex (string table, bool isSinge = false, bool objectType = false)
{
for (int i = 0; i < this._viewPool.Count; i++)
{
if (table.Equals (this._viewPool[i].VIEWTABLE, StringComparison.Ordinal))
{
if (isSinge)
{
return i;
}
else if (this._viewPool[i].gameObject.activeSelf == objectType)
{
return i;
}
}
}
return -1;
}
///
/// 更新当前焦点页面
///
internal void UpdateFocusView ()
{
//先计算出当前焦点页面
var focusView = _getFocusView ();
//在比较是否与当前的焦点页面相同
//如果相同则不做处理
//如果不同则更新当前焦点页面
if (ReferenceEquals (focusView, null) || focusView == CurFocusView)
{
return;
}
var lastFocusView = CurFocusView;
if (lastFocusView is { CurFocusState: true, isOpen: true })
{
lastFocusView.CurFocusState = false;
}
//此处改为先通知新页面获得焦点,再通知旧页面失去焦点
CurFocusView = focusView;
CurFocusView.CurFocusState = true;
CurFocusView.OnFocus (true);
if (lastFocusView is { CurFocusState: false })
{
lastFocusView.OnFocus (false);
}
this.OnViewFocusChanged?.Invoke (CurFocusView);
}
IC_AbstractView _getFocusView ()
{
//对所有符合规则的页面焦点ID与当前焦点ID进行比较,获得差值最小的页面
//如果差值相同则取最后打开的页面
IC_AbstractView view = null;
int min = int.MaxValue;
for (int i = 0; i < _viewPool.Count; i++)
{
var tempView = _viewPool[i];
if (tempView.isOpen && tempView.hasFocusView)
{
var temp = Mathf.Abs (tempView._focusID - _curFocusID);
if (temp <= min)
{
min = temp;
view = tempView;
}
}
}
return view;
}
///
/// 关闭指定Table的页面
///
///
///
public void CloseView (string table , Action onClosed = null)
{
var count = getViewIndex (table, false, true);
if (count == -1) return;
_closeView (this._viewPool[count] , onClosed);
UpdateFocusView ();
}
internal void CloseViewFromView (IC_AbstractView view)
{
_closeView (view);
UpdateFocusView ();
}
private void _closeView (IC_AbstractView view , Action onClosed = null)
{
if (ReferenceEquals (view, default)) return;
if (!view.isOpen)
{
#if UNITY_EDITOR || DEBUG
Debug.Log (view.VIEWTABLE + " view is Closed");
#endif
return;
}
_closeViewBefore (view);
view.openCount = 0;
view.isOpen = false;
view.onClosed = onClosed;
view.OnCloseView ();
if (view._closeHook ())
{
view._directClose ();
}
}
///
/// 关闭指定类型的所有页面
///
///
public void CloseTableViews (string table)
{
if (table == null) return;
for (int i = 0; i < this._viewPool.Count; i++)
{
if (table.Equals (this._viewPool[i].VIEWTABLE, StringComparison.Ordinal))
{
_closeView (_viewPool[i]);
}
}
UpdateFocusView ();
}
///
/// 关闭指定Group的所有页面
///
public void CloseViewWithGroup (string group)
{
if (group == null) return;
for (int i = this._viewPool.Count - 1; i >= 0; i--)
{
var view = this._viewPool[i];
if (group.Equals (view.Group, StringComparison.Ordinal))
{
_closeView (view);
}
}
UpdateFocusView ();
}
internal void CloseViewWithConfigId (IC_IViewConfig config)
{
var hashCode = config.GetHashCode ();
for (int i = this._viewPool.Count - 1; i >= 0; i--)
{
var view = this._viewPool[i];
if (view._configID == hashCode)
{
_closeView (view);
}
}
UpdateFocusView ();
}
///
/// 关闭所有页面
///
public void CloseAllView ()
{
for (int i = this._viewPool.Count - 1; i >= 0; i--)
{
var view = this._viewPool[i];
if (view.isOpen)
{
_closeView (view);
}
}
UpdateFocusView ();
}
///
/// 直接销毁所有View,不会触发任何生命周期
///
internal void ClearAll ()
{
_curFocusID = 0;
CurFocusView = null;
this._viewPool.ForEach (view => UnityEngine.Object.Destroy (view.gameObject));
this._viewPool.Clear ();
}
///
/// 销毁指定的view
///
///
internal void DestroyViewAtHash (int hash)
{
for (int i = 0; i < this._viewPool.Count; i++)
{
if (this._viewPool[i].gameObject.GetHashCode () == hash)
{
// GameObject.Destroy(ViewPool[i].gameObject);
this._config.OnRemoveView (this._viewPool[i]);
this._viewPool.Remove (this._viewPool[i]);
return;
}
}
}
#endregion
// ///
// /// 重置view配置表
// ///
// ///
// ///
// public void ResetConfig (IC_IViewConfig viewConfig)
// {
// if (viewConfig == null)
// {
// return;
// }
//
// this.ClearAll ();
// this._config?.OnDispose ();
// this._config = viewConfig;
// this._config.OnInit ();
// //缓存页面
// this.CacheView (this._config.GetCacheTables ());
// if (!string.IsNullOrEmpty (this._config.GetDefaultViewTable ()))
// {
// OpenView (this._config.GetDefaultViewTable ());
// }
// }
public void AddConfig (IC_IViewConfig config)
{
if (config == null)
{
return;
}
if (this._config.AddConfig (config))
{
config.OnInit ();
//缓存页面
this.CacheView (this._config.GetCacheTables ());
}
}
public void RemoveConfig (IC_IViewConfig config)
{
if (config == null)
{
return;
}
this.CloseViewWithConfigId (config);
this._config.RemoveConfig (config);
}
public void Dispose ()
{
foreach (var value in Canvases.Values)
{
Object.Destroy (value.gameObject);
}
this.Canvases.Clear ();
this.ClearAll ();
this._config?.OnDispose ();
System.GC.Collect ();
}
///
/// 真正被销毁之前
///
///
internal void _closeViewBefore (IC_AbstractView view)
{
if (view.CurFocusState)
{
view.CurFocusState = false;
// view.OnFocus (false);
}
_curFocusID -= view.openCount;
if (_curFocusID < 0)
{
_curFocusID = 0;
}
}
}
}