Files
taptap2024_GJ_chidouren/Packages/CC-Framework/com.foldcc.icecreamview/Runtime/IC_Controller.cs
2024-10-16 00:03:41 +08:00

651 lines
21 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using System;
using System.Collections.Generic;
using UnityEngine;
using Object = UnityEngine.Object;
namespace IcecreamView
{
/// <summary>
/// icecream页面管理器驱动页面的核心控制器用于控制页面生成、展示、隐藏、跳转等操作
/// </summary>
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<IC_AbstractView> _viewPool;
public Transform BaseRoot;
public Dictionary<int, Canvas> Canvases;
private int _curFocusID = 0;
public IC_AbstractView CurFocusView { get; private set; }
public IC_UIEventManager EventManager { get; private set; }
public Action<IC_AbstractView> OnViewOpened;
public Action<IC_AbstractView> OnViewClosed;
public Action<IC_AbstractView> 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<IC_AbstractView> ();
this.Canvases = new Dictionary<int, Canvas> ();
this._curFocusID = 0;
this.AddConfig (gameViewConfig);
}
public void Init (IC_IViewConfig gameViewConfig, IList<CanvasNode> nodes)
{
this._config = new IC_ViewConfigGroup ();
EventManager = new IC_UIEventManager ();
this._viewPool = new List<IC_AbstractView> ();
this.Canvases = new Dictionary<int, Canvas> ();
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;
}
/// <summary>
/// 构建一个View对象
/// </summary>
/// <param name="config"></param>
/// <param name="Table">ViewTable</param>
/// <returns></returns>
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;
}
/// <summary>
/// 获取指定页面
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="table"></param>
/// <returns></returns>
public T GetView<T> (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);
}
/// <summary>
/// 获取指定table页面的指定Module
/// </summary>
/// <param name="table"></param>
/// <typeparam name="T"></typeparam>
/// <returns></returns>
public T GetViewModule<T> (string table) where T : IC_AbstractModule
{
var View = GetView<IC_ModuleConnector> (table);
if (View != null)
{
return View.GetViewModule<T> ();
}
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 ("<color=yellow>{0}</color>", "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<IC_AbstractView> ();
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);
}
/// <summary>
/// 关闭所有页面 并打开指定页面
/// </summary>
/// <param name="table"></param>
/// <returns></returns>
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;
}
/// <summary>
/// 提前缓存指定Table数组
/// </summary>
/// <param name="Tables"></param>
internal void CacheView (List<string> 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);
}
}
}
/// <summary>
/// 缓存指定页面
/// </summary>
/// <param name="Table"></param>
/// <returns></returns>
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);
}
}
/// <summary>
/// 判断指定table是否存在
/// </summary>
/// <param name="table"></param>
/// <returns></returns>
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;
}
/// <summary>
/// 判断指定table页面是否已存在
/// </summary>
/// <param name="table"></param>
/// <returns></returns>
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;
}
/// <summary>
/// 返回一个指定table的View对应下标
/// </summary>
/// <param name="table"></param>
/// <returns></returns>
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;
}
/// <summary>
/// 更新当前焦点页面
/// </summary>
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;
}
/// <summary>
/// 关闭指定Table的页面
/// </summary>
/// <param name="table"></param>
/// <param name="onClosed"></param>
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 ();
}
}
/// <summary>
/// 关闭指定类型的所有页面
/// </summary>
/// <param name="table"></param>
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 ();
}
/// <summary>
/// 关闭指定Group的所有页面
/// </summary>
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 ();
}
/// <summary>
/// 关闭所有页面
/// </summary>
public void CloseAllView ()
{
for (int i = this._viewPool.Count - 1; i >= 0; i--)
{
var view = this._viewPool[i];
if (view.isOpen)
{
_closeView (view);
}
}
UpdateFocusView ();
}
/// <summary>
/// 直接销毁所有View不会触发任何生命周期
/// </summary>
internal void ClearAll ()
{
_curFocusID = 0;
CurFocusView = null;
this._viewPool.ForEach (view => UnityEngine.Object.Destroy (view.gameObject));
this._viewPool.Clear ();
}
/// <summary>
/// 销毁指定的view
/// </summary>
/// <param name="hash"></param>
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
// /// <summary>
// /// 重置view配置表
// /// </summary>
// /// <param name="viewConfig"></param>
// /// <param name="config"></param>
// 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 ();
}
/// <summary>
/// 真正被销毁之前
/// </summary>
/// <param name="view"></param>
internal void _closeViewBefore (IC_AbstractView view)
{
if (view.CurFocusState)
{
view.CurFocusState = false;
// view.OnFocus (false);
}
_curFocusID -= view.openCount;
if (_curFocusID < 0)
{
_curFocusID = 0;
}
}
}
}