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