This commit is contained in:
2024-10-16 00:03:41 +08:00
commit 897058435c
5033 changed files with 1009728 additions and 0 deletions

View File

@@ -0,0 +1,71 @@
using System;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.UI;
using Object = UnityEngine.Object;
namespace IcecreamView
{
[AttributeUsage(AttributeTargets.Method)]
public class BindUIButton : Attribute
{
private string[] _eventPaths;
private Button[] _buttons;
[Obsolete("不推荐使用地址绑定方式该操作会使用Transform.Find, 推荐使用直接引用按钮字段的方式进行事件绑定")]
public BindUIButton(params string[] buttonPaths)
{
this._eventPaths = buttonPaths;
}
public BindUIButton(params Button[] buttons)
{
this._buttons = buttons;
}
internal void AddListener(Transform obj, UnityAction action)
{
if (_eventPaths == null || _eventPaths.Length == 0)
return;
foreach (var path in this._eventPaths)
{
GetButtonComponent(obj , path)?.onClick.AddListener(action);
}
}
internal void AddListenerButton(UnityAction action)
{
if (_buttons == null || _buttons.Length == 0)
return;
foreach (var button in _buttons)
{
// ReSharper disable once Unity.PerformanceCriticalCodeNullComparison
if (button != null)
{
button.onClick.AddListener(action);
}
}
}
private Button GetButtonComponent(Transform obj, string path)
{
Transform mT;
if (!string.IsNullOrEmpty(path))
mT = obj.Find(path);
else
mT = obj;
var btn = mT?.GetComponent<Button>();
if (mT == null)
{
Debug.LogError("[IceCreamView] 指定路径无效 : " + path, obj);
}
else if (btn == null)
{
Debug.LogError("[IceCreamView] 指定路径下没有Button组件: " + path, obj);
}
return btn;
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 29442ad1c57d48e588235e592beb0dbf
timeCreated: 1573710190

View File

@@ -0,0 +1,15 @@
using System;
namespace IcecreamView
{
[AttributeUsage(AttributeTargets.Method)]
public class BindUIEvent : Attribute
{
public int EventCode;
public BindUIEvent (int eventCode)
{
this.EventCode = eventCode;
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 6c85dfe9d5b049e3b48c9e1c1871330e
timeCreated: 1565230421

View File

@@ -0,0 +1,53 @@
using System;
namespace IcecreamView
{
[AttributeUsage(AttributeTargets.Field)]
public class BindUIPath : Attribute
{
public string Path;
private string ItemPath;
private int StartIndex;
public bool IsArray;
/// <summary>
/// 绑定一个UI控件
/// </summary>
/// <param name="path">控件相对该组件对应的相对地址</param>
public BindUIPath(string path)
{
this.IsArray = false;
this.Path = path;
}
/// <summary>
/// 绑定一个List类型的UI控件
/// </summary>
/// <param name="path">该list的根节点路径</param>
/// <param name="itemPath">每个item的路径如果有递增类型的值请使用{n}关键字代替递增数字, *代表根节点下的所有对象</param>
/// <param name="startIndex">递增值的初始值,默认为0</param>
public BindUIPath(string path, string itemPath , int startIndex = 0 )
{
this.IsArray = true;
if (itemPath == null)
{
itemPath = "*";
}
this.Path = path;
this.ItemPath = itemPath;
this.StartIndex = startIndex;
}
public string GetElementPath(int Index)
{
if (this.IsArray)
{
return this.ItemPath.Replace("{n}", Index + this.StartIndex + "");
}
return null;
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: bd696ef850584690806c98a3a90263e1
timeCreated: 1564544711

View File

@@ -0,0 +1,11 @@
using UnityEngine;
namespace IcecreamView
{
public class CanvasNode : MonoBehaviour
{
public bool IsBaseCanvas;
public int OrderRange;
public Canvas Canvas;
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 02852c69c24a4a55b5dc70f2e1314404
timeCreated: 1627547169

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 20c0b47623c190e4983df1984a7417dd
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,51 @@
using System;
using System.Collections.Generic;
using Sirenix.OdinInspector;
using UnityEditor;
using UnityEngine;
namespace IcecreamView
{
[CreateAssetMenu(fileName = "IC_GlobalSetting", menuName = "IceCreamView/GlobalSetting")]
public class IC_GlobalSetting : ScriptableObject
{
[Header("命名空间")] public string NameSpacePath = "View";
[Header("代码生成路径")] public string FilePath = "Scripts/View";
[Header("预制体保存路径")] public string PrefabsPath = "Resources/View";
[Header("继承类")] public string AbstractClass = "IcecreamView.IC_AbstractModule";
public string AssemblyName = "Assembly-CSharp";
#if UNITY_EDITOR
[Header("UI场景")]public SceneAsset UiSceneAsset;
#endif
[Header("自定义UI控件配置表")] public List<CustomUIConfig> CustomUIConfigs;
[Header("自定义UI页面配置表")] public List<CustomUIPanelConfig> CustomPanelConfigs;
}
[Serializable]
public class CustomUIConfig
{
// [HorizontalGroup("Box")]
[HorizontalGroup("Prefab", 55), PropertyOrder(-1)]
[PreviewField(50, Sirenix.OdinInspector.ObjectFieldAlignment.Left), HideLabel]
public CustomUIConnector Prefab;
[BoxGroup("Prefab/info"), LabelText("UI控件名称")]
public string Name;
[BoxGroup("Prefab/info"), LabelText("UI控件描述")]
public string Desc;
}
[Serializable]
public class CustomUIPanelConfig
{
// [HorizontalGroup("Box")]
[HorizontalGroup("Prefab", 55), PropertyOrder(-1)]
[PreviewField(50, Sirenix.OdinInspector.ObjectFieldAlignment.Left), HideLabel]
public IcecreamView.IC_ModuleConnector Prefab;
[BoxGroup("Prefab/info"), LabelText("页面名称")]
public string Name;
[BoxGroup("Prefab/info"), LabelText("页面描述")]
public string Desc;
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 1badf54a3ca64034bdd3fdf4100c8202
timeCreated: 1588251654

View File

@@ -0,0 +1,21 @@
using System.Collections.Generic;
namespace IcecreamView {
public interface IC_IViewConfig
{
void OnInit();
string GetDefaultViewTable();
bool ContainsKey(string viewTable);
List<string> GetCacheTables();
IC_IViewInfo OnAddView(string viewTable);
void OnRemoveView(IC_AbstractView view);
void OnDispose();
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: a3b4639ae73b9f740a4fb233227a3b4d
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,11 @@

namespace IcecreamView {
public interface IC_IViewInfo
{
string GetTable();
bool IsOnce();
bool IsCache();
IC_AbstractView GetView();
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 8eee9fefcf41d154c9ca69c2c1a66ccf
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,69 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace IcecreamView {
[CreateAssetMenu(fileName = "IC_Resource_ViewConfig", menuName = "IceCreamView/IceView ConfigResource link", order = 89)]
public class IC_Resource_ViewConfig : ScriptableObject, IC_IViewConfig
{
[Header("UI预制体相对Resources下的根目录")]
public string ResourceViewPath;
[Header("默认打开页面")]
public string DefaultView;
[Header("需要复用View白名单关闭View后不会销毁类似对象池存储")]
public List<string> persistenceList = new List<string>();
private Dictionary<string, IC_IViewInfo> mViewDic;
public bool ContainsKey(string viewTable)
{
if (mViewDic.ContainsKey(viewTable))
return true;
var view = Resources.Load<IC_AbstractView>(ResourceViewPath + viewTable);
if (view != null)
{
var viewInfo = new IC_ViewInfo() { autoLoad = this.persistenceList.Contains(viewTable) , isOnce = !persistenceList.Contains(viewTable) , Table = viewTable , View = view};
mViewDic.Add(viewTable , viewInfo);
return true;
}
return false;
}
public List<string> GetCacheTables()
{
return this.persistenceList;
}
public string GetDefaultViewTable()
{
if(string.IsNullOrEmpty(DefaultView))
return null;
return DefaultView;
}
public IC_IViewInfo OnAddView(string viewTable)
{
return mViewDic[viewTable];
}
public void OnRemoveView(IC_AbstractView view)
{
GameObject.Destroy(view.gameObject);
}
public void OnDispose()
{
mViewDic.Clear();
Resources.UnloadUnusedAssets();
System.GC.Collect();
}
public void OnInit()
{
mViewDic = new Dictionary<string, IC_IViewInfo>();
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 628ff49fd857e0b4cb7f99680f51b40b
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,123 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace IcecreamView {
[System.Serializable]
public class IC_ViewInfo : IC_IViewInfo{
public IC_AbstractView View;
[Header("可选填默认为View预制体名称")]
public string Table;
[Header("是否提前缓存(用于大型View)")]
public bool autoLoad;
[Header("是否作为一次性使用,当页面被关闭时直接销毁")]
public bool isOnce;
public string GetTable()
{
return Table;
}
public bool IsCache()
{
return autoLoad;
}
public IC_AbstractView GetView()
{
return View;
}
public bool IsOnce()
{
return isOnce;
}
}
/// <summary>
/// 游戏View配置表
/// </summary>
[CreateAssetMenu(fileName = "IC_ViewConfig" , menuName = "IceCreamView/IceView ConfigPrefabs link" , order = 88)]
public class IC_ViewConfig : ScriptableObject , IC_IViewConfig
{
public string ConfigName;
public string DefaultViewTable;
public List<IC_ViewInfo> GameViewList;
private Dictionary<string, IC_IViewInfo> mViewDic;
public void OnInit()
{
Debug.Log("Init ViewConfig : " + ConfigName);
mViewDic = new Dictionary<string, IC_IViewInfo>();
mViewDic = GetViewModleDic();
}
public Dictionary<string, IC_IViewInfo> GetViewModleDic()
{
Dictionary<string, IC_IViewInfo> viewDic = new Dictionary<string, IC_IViewInfo>();
if (GameViewList != null && GameViewList.Count > 0)
{
GameViewList.ForEach(view =>
{
if (string.IsNullOrEmpty(view.Table))
{
view.Table = view.View.name;
}
if (!viewDic.ContainsKey(view.Table))
{
viewDic.Add(view.Table, view);
}
else {
Debug.LogError("[IceCreamView] View数据出现重名数据" + view.Table);
}
});
}
return viewDic;
}
public string GetDefaultViewTable()
{
return DefaultViewTable;
}
public bool ContainsKey(string viewTable)
{
return mViewDic.ContainsKey(viewTable);
}
public List<string> GetCacheTables()
{
List<string> tableList = new List<string>();
foreach (IC_ViewInfo IcViewInfo in GameViewList)
{
if (IcViewInfo.autoLoad)
{
tableList.Add(IcViewInfo.Table);
}
}
return tableList;
}
public IC_IViewInfo OnAddView(string viewTable)
{
return mViewDic[viewTable];
}
public void OnRemoveView(IC_AbstractView view)
{
GameObject.Destroy(view.gameObject);
}
public void OnDispose()
{
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 9dd6fc253e125ee4e8c3efae89432f15
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,109 @@
using System.Collections.Generic;
namespace IcecreamView
{
public class IC_ViewConfigGroup : IC_IViewConfig
{
private List<IC_IViewConfig> _configs;
public IC_ViewConfigGroup ()
{
OnInit ();
}
public void OnInit ()
{
this._configs = new List<IC_IViewConfig> ();
}
public bool AddConfig (IC_IViewConfig config)
{
if (_configs.Contains (config) == false)
{
this._configs.Add (config);
return true;
}
return false;
}
public void RemoveConfig (IC_IViewConfig config)
{
this._configs.Remove (config);
config.OnDispose ();
}
public string GetDefaultViewTable ()
{
if (this._configs.Count > 0)
{
return this._configs[^1].GetDefaultViewTable ();
}
return null;
}
public bool ContainsKey (string viewTable)
{
foreach (var config in this._configs)
{
if (config.ContainsKey (viewTable))
{
return true;
}
}
return false;
}
public bool TryContainsKeyConfig (string viewTable, out IC_IViewConfig config)
{
foreach (var c in this._configs)
{
if (c.ContainsKey (viewTable))
{
config = c;
return true;
}
}
config = null;
return false;
}
public List<string> GetCacheTables ()
{
List<string> tables = new List<string> ();
foreach (var config in this._configs)
{
tables.AddRange (config.GetCacheTables ());
}
return tables;
}
public IC_IViewInfo OnAddView (string viewTable)
{
throw new System.NotImplementedException ();
}
public void OnRemoveView (IC_AbstractView view)
{
foreach (var config in this._configs)
{
if (config.GetHashCode () == view._configID)
{
config.OnRemoveView (view);
return;
}
}
}
public void OnDispose ()
{
foreach (var config in this._configs)
{
config.OnDispose ();
}
this._configs.Clear ();
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 37c69d0bb73d4652b6f6f61207031437
timeCreated: 1716797150

View File

@@ -0,0 +1,9 @@
using UnityEngine;
namespace IcecreamView
{
public class CustomUIConnector : MonoBehaviour
{
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: b167aacff6384b958a1f7f0f0709527c
timeCreated: 1685946428

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 14f45208cccd4044a4100502d532a204
timeCreated: 1565244232

View File

@@ -0,0 +1,32 @@
using System.Collections.Generic;
namespace IcecreamView
{
public class EventArg
{
private List<object> values;
public EventArg(params object[] values)
{
if (values == null)
{
this.values = null;
return;
}
this.values = new List<object>(values);
}
public T GetValue<T>(int index = 0)
{
if (this.values == null || index >= this.values.Count)
{
return default;
}
return (T)this.values[index];
}
public bool IsNotNull(int index = 0) { return this.values.Count > index && this.values[index] != null; }
public int Count => values.Count;
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 3730f8fe0134456fb3385744fd4da4d4
timeCreated: 1565254674

View File

@@ -0,0 +1,49 @@
using System;
using System.Collections.Generic;
namespace IcecreamView
{
public class IC_UIEventManager
{
private Dictionary<int, List<Action<EventArg>>> eventDict = new Dictionary<int, List<Action<EventArg>>>();
public void BindEvent(int code , Action<EventArg> eventCallback)
{
if (this.eventDict.ContainsKey(code))
{
if (!this.eventDict[code].Contains(eventCallback))
this.eventDict[code].Add(eventCallback);
}
else
{
this.eventDict[code] = new List<Action<EventArg>>();
this.eventDict[code].Add(eventCallback);
}
}
public void UnBindEvent(int code , Action<EventArg> eventCallback)
{
if (this.eventDict.ContainsKey(code))
{
this.eventDict[code].Remove(eventCallback);
}
}
public void SendEvent(int code , params object[] values)
{
this.SendEvent(code, new EventArg(values));
}
public void SendEvent(int code , EventArg eventArg)
{
if (this.eventDict.ContainsKey(code))
{
for (int i = 0; i < this.eventDict[code].Count; i++)
{
this.eventDict[code][i].Invoke(eventArg);
}
}
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 8449cc0e1f354e27a86a1168c100e3c7
timeCreated: 1565241933

View File

@@ -0,0 +1,38 @@
using System;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;
namespace IcecreamView {
/// <summary>
/// gameView模板类
/// </summary>
[RequireComponent(typeof(IC_ModuleConnector))]
public abstract class IC_AbstractModule : MonoBehaviour
{
[Tooltip("执行优先级(越小越优先)")]
public int prioritylevel = 1;
[Tooltip("UIBinder可以更加方便的绑定场景中的对象但在同一View下启用该功能的组件数量越多越会影响效率")]
public bool IsActiveUIBinder = true;
[HideInInspector]
public IC_ModuleConnector ViewConnector;
public RectTransform ViewRectTransform => ViewConnector.ViewRectTransform;
public virtual void OnOpenView (IC_ViewData msgData) { }
public virtual void OnCloseView() { }
public virtual void OnInitView () { }
public virtual void OnDestroyView() { }
public virtual void OnFocusActive() { }
public virtual void OnFocusInactive() { }
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 34cf465e4c13b4041bbfadfbb26f925d
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,191 @@
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace IcecreamView
{
[DisallowMultipleComponent, System.Serializable]
public abstract class IC_AbstractView : MonoBehaviour
{
#if UNITY_EDITOR
public bool HasAutoCreate = true;
#endif
/// <summary>
/// ViewTable标识 不能修改
/// </summary>
[HideInInspector]
public string VIEWTABLE;
internal string _group;
internal int _configID;
internal int openCount;
internal int CurSortOrder;
[SerializeField ,Tooltip("是否可被聚焦")]
internal bool hasFocusView = true;
internal int _focusID;
internal bool CurFocusState;
internal Action onOpened;
internal Action onClosed;
/// <summary>
/// 用于判断页面是否开启
/// </summary>
[HideInInspector]
public bool isOpen = false;
[HideInInspector]
public bool isOnce = false;
[SerializeField] internal int DefaultStory;
public int PanelLayer => DefaultStory;
public bool HasFocusView => hasFocusView;
public string Group => this._group;
public RectTransform ViewRectTransform { get; protected set; }
/// <summary>
/// 对应View管理器
/// </summary>
[System.NonSerialized] protected IC_Controller viewManager;
internal void SetViewManager(IC_Controller viewManager)
{
if (this.viewManager == null)
{
this.viewManager = viewManager;
}
}
public void SendEvent(int code , params object[] value)
{
this.viewManager.EventManager.SendEvent(code , value);
}
/// <summary>
/// 页面被创建初始化时触发该方法
/// </summary>
internal virtual void OnInitView ()
{
this.ViewRectTransform = (RectTransform)this.transform;
}
/// <summary>
/// 页面打开时触发该方法
/// </summary>
internal virtual void OnOpenView(params IC_ViewData[] values) { }
/// <summary>
/// 页面被关闭前触发该方法
/// </summary>
internal virtual void OnCloseView() { }
/// <summary>
/// 强制关闭页面时触发该方法
/// </summary>
internal virtual void OnHardCloseView() { }
/// <summary>
/// 页面被彻底销毁时触发
/// </summary>
internal virtual void OnDestroyView() { }
internal virtual void OnFocus(bool isFocus) { }
/// <summary>
/// 关闭当前页面
/// </summary>
public void CloseView()
{
viewManager.CloseViewFromView(this);
}
/// <summary>
/// 用于截断页面关闭的钩子方法,默认返回true如果返回false转为手动模式需要自行close页面适用于各种骚操作请谨慎使用可能会引起未知错误
/// </summary>
/// <returns></returns>
internal virtual bool _closeHook()
{
return true;
}
/// <summary>
/// 直接关闭页面通常情况下请使用CloseView方法直接使用该方法可能导致不稳定出现位置问题
/// </summary>
internal void _directClose()
{
OnClosed ();
if (isOnce)
{
viewManager.DestroyViewAtHash(gameObject.GetHashCode());
}
else
{
gameObject.SetActive(false);
transform.SetAsFirstSibling();
}
this.viewManager.UpdateFocusView ();
this.viewManager.OnViewClosed?.Invoke(this);
}
/// <summary>
/// 打开指定页面
/// </summary>
/// <param name="ViewTable">页面table</param>
/// <param name="isCloseThis">是否同时关闭自己</param>
public IC_AbstractView OpenView(string ViewTable, bool isCloseThis = false, bool isSinge = true , params IC_ViewData[] values)
{
if (viewManager != null)
{
if (isCloseThis)
{
CloseView();
}
return viewManager.OpenView(ViewTable, isSinge, values);
}
return null;
}
public IC_AbstractView OpenView(string ViewTable, bool isCloseThis = false, params IC_ViewData[] values)
{
return OpenView(ViewTable , isCloseThis , true , values);
}
public IC_AbstractView OpenView(string ViewTable, params IC_ViewData[] values)
{
return OpenView(ViewTable , false , true , values);
}
private void OnDestroy()
{
this.OnDestroyView();
}
// ReSharper disable Unity.PerformanceAnalysis
protected void OnOpened ()
{
var opened = this.onOpened;
this.onOpened = null;
opened?.Invoke ();
}
protected void OnClosed ()
{
var closed = this.onClosed;
this.onClosed = null;
closed?.Invoke ();
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 5c4639cd5f06ba043b6257e65593c461
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,651 @@
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;
}
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 0a3650d50655537449f350dc11b7c347
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,30 @@
namespace IcecreamView {
/// <summary>
/// icecream页面接口
/// </summary>
public interface IC_IView
{
/// <summary>
/// 页面被初始化时触发
/// </summary>
void OnInitView();
/// <summary>
/// 页面被打开时触发
/// </summary>
void OnOpenView(params IC_ViewData[] values);
/// <summary>
/// 页面被关闭时触发
/// </summary>
void OnCloseView();
/// <summary>
/// 页面被销毁时触发
/// </summary>
void OnDestoryView();
/// <summary>
/// 关闭当前页面
/// </summary>
void CloseView();
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: ec93ef680cfc0fe4288072143abc577b
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,450 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Reflection;
using UnityEngine;
using UnityEngine.Events;
namespace IcecreamView
{
/// <summary>
/// 使用模板组合View模式的必要组件
/// </summary>
[DisallowMultipleComponent, AddComponentMenu("IceCreamView/Connector")]
public class IC_ModuleConnector : IC_AbstractView
{
private List<IC_AbstractModule> gameViewAbstractModules = null;
private Dictionary<int, List<Action<EventArg>>> eventDict;
private RunType awaitType;
private int awaitCount = 0;
private bool isAwait = false;
private Dictionary<string, IC_ViewData> values;
private IC_ViewData defaultMsg;
public IC_ViewData GetMsg(String code)
{
if (values.TryGetValue(code, out var msg))
{
return msg;
}
return null;
}
/// <summary>
/// 获取指定类型的组件列表
/// </summary>
/// <typeparam name="T"></typeparam>
/// <returns></returns>
public List<T> GetViewModuleList<T>() where T : IC_AbstractModule
{
List<T> modules = new List<T>();
string cname = typeof(T).ToString();
foreach (IC_AbstractModule key in gameViewAbstractModules)
{
if (key.GetType().Name.Equals(cname))
{
modules.Add((T) key);
}
}
return modules;
}
/// <summary>
/// 获取该页面上第一个指定类型的组件
/// </summary>
/// <typeparam name="T"></typeparam>
/// <returns></returns>
public T GetViewModule<T>() where T : IC_AbstractModule
{
for (int i = 0; i < gameViewAbstractModules.Count; i++)
{
IC_AbstractModule key = gameViewAbstractModules[i];
if (key is T)
{
return (T) key;
}
}
return null;
}
// [Header("是否启用UIPath功能(Bate)")]
// [Tooltip("UIPath可以更加方便的绑定场景中的对象但是在同一View下启用该功能的组件数量越多越会影响效率")]
// public bool IsActiveUIPath = true;
private void OnOpenModel()
{
isAwait = false;
if (awaitType != RunType.OnOpen)
{
awaitCount = 0;
awaitType = RunType.OnOpen;
}
while (awaitCount < gameViewAbstractModules.Count)
{
awaitCount++;
gameViewAbstractModules[awaitCount - 1].OnOpenView(this.defaultMsg);
if (isAwait)
{
return;
}
}
awaitCount = 0;
this.OnOpened ();
}
internal override void OnOpenView(params IC_ViewData[] args)
{
this.values.Clear();
this.defaultMsg = null;
foreach (IC_ViewData viewData in args)
{
if (viewData.code.Equals(IC_ViewData.DefaultCode, StringComparison.Ordinal))
{
this.defaultMsg = viewData;
}
else
{
this.values[viewData.code] = viewData;
}
}
OnOpenModel();
}
internal override void OnCloseView()
{
isAwait = false;
if (awaitType != RunType.OnClose)
{
awaitCount = 0;
awaitType = RunType.OnClose;
}
while (awaitCount < gameViewAbstractModules.Count)
{
awaitCount++;
gameViewAbstractModules[awaitCount - 1].OnCloseView();
if (isAwait)
{
return;
}
}
awaitCount = 0;
_directClose();
}
internal override void OnFocus(bool isFocus)
{
for (int i = 0; i < gameViewAbstractModules.Count; i++)
{
if (isFocus)
{
gameViewAbstractModules[i].OnFocusActive();
}
else
{
gameViewAbstractModules[i].OnFocusInactive();
}
}
}
/// <summary>
/// 强制关闭时禁用await功能
/// </summary>
internal override void OnHardCloseView()
{
isAwait = false;
awaitCount = 0;
awaitType = RunType.OnClose;
while (awaitCount < gameViewAbstractModules.Count)
{
awaitCount++;
gameViewAbstractModules[awaitCount - 1].OnCloseView();
isAwait = false;
}
awaitCount = 0;
// _directClose();
}
internal override void OnInitView()
{
base.OnInitView ();
awaitType = RunType.OnInit;
this.values = new Dictionary<string, IC_ViewData>();
this.eventDict = new Dictionary<int, List<Action<EventArg>>>();
if (gameViewAbstractModules == null)
{
gameViewAbstractModules = new List<IC_AbstractModule>();
//获取当前对象上的所有View模块
GetComponents(gameViewAbstractModules);
//重新根据优先级排序
gameViewAbstractModules.Sort((IC_AbstractModule a, IC_AbstractModule b) =>
{
if (a.prioritylevel < b.prioritylevel)
{
return -1;
}
else if (a.prioritylevel > b.prioritylevel)
{
return 1;
}
return 0;
});
//初始化所有模块
gameViewAbstractModules.ForEach(m => { m.ViewConnector = this; });
}
foreach (var item in gameViewAbstractModules)
{
if (item.IsActiveUIBinder)
{
this._initUIPath(item);
}
var bindingFlag = BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Public;
var mMethods = item.GetType().GetMethods(bindingFlag);
//绑定事件
this._initUIEvent(item, mMethods);
//绑定按钮事件
this._initUIButton(item, mMethods);
item.OnInitView();
}
}
internal override void OnDestroyView()
{
isAwait = false;
awaitCount = 0;
this.removeEvent();
while (awaitCount < gameViewAbstractModules.Count)
{
gameViewAbstractModules[awaitCount].OnDestroyView();
awaitCount++;
}
}
internal override bool _closeHook()
{
return false;
}
/// <summary>
/// 停止该页面正在执行的生命周期 ,停止的范围仅限(OnOpen、OnClose)
/// 不支持多线程操作
/// </summary>
public void Await()
{
this.isAwait = true;
// return Continue;
}
public void Continue()
{
if (!isAwait) return;
isAwait = false;
switch (awaitType)
{
case RunType.OnClose:
OnCloseView();
break;
case RunType.OnOpen:
OnOpenModel();
break;
default:
break;
}
}
private void _initUIPath(object uiModule)
{
var bindingFlag = BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Public;
var mFields = uiModule.GetType().GetFields(bindingFlag);
foreach (var mFieldInfo in mFields)
{
var mAttrObjs = mFieldInfo.GetCustomAttributes(typeof(BindUIPath), false);
if (mAttrObjs.Length > 0)
{
var mUiPath = mAttrObjs[0] as BindUIPath;
if (mUiPath != null)
{
Transform mTransform;
if (string.IsNullOrEmpty(mUiPath.Path))
mTransform = this.transform;
else
mTransform = this.transform.Find(mUiPath.Path);
if (mTransform)
{
if (mUiPath.IsArray)
{
if (typeof(IList).IsAssignableFrom(mFieldInfo.FieldType) &&
mFieldInfo.FieldType.IsGenericType)
{
Type UIType = mFieldInfo.FieldType.GenericTypeArguments[0];
IList ListValue = (IList) Activator.CreateInstance(mFieldInfo.FieldType);
int count = 0;
while (count < mTransform.childCount)
{
Transform itemTran = null;
if (mUiPath.GetElementPath(count) == "*")
itemTran = mTransform.GetChild(count);
else
itemTran = mTransform.Find(mUiPath.GetElementPath(count));
if (itemTran != null)
{
object mValue = _getComponent(itemTran, UIType);
if (mValue != null)
{
ListValue.Add(mValue);
}
else if (mUiPath.GetElementPath(count) != "*")
{
Debug.LogError("[IceCreamView] 指定路径的对象未包含组件: " + UIType, itemTran);
break;
}
}
else
{
break;
}
count++;
}
mFieldInfo.SetValue(uiModule, ListValue);
}
else
{
Debug.LogError("[IceCreamView] 字段不满足ListUI控件绑定规范请使用List<T>或者其派生类: " +
mFieldInfo.Name);
}
}
else
{
object mValue = this._getComponent(mTransform, mFieldInfo.FieldType);
if (mValue != null)
{
mFieldInfo.SetValue(uiModule, mValue);
}
else
{
Debug.LogError("[IceCreamView] 指定路径的对象未包含组件: " + mFieldInfo.FieldType.ToString() +
" 字段名称:" + mFieldInfo.Name);
}
}
}
else
{
Debug.LogError("[IceCreamView] 无效的UI地址: " + mUiPath.Path);
}
}
}
}
}
private object _getComponent(Transform targetObj, Type ComponentType)
{
if (ComponentType == typeof(GameObject))
return targetObj.gameObject;
if (typeof(Component).IsAssignableFrom(ComponentType) || ComponentType.IsInterface)
{
return targetObj.GetComponent(ComponentType);
}
Debug.LogError("[IceCreamView] 不支持获取该类型仅支持GameObject、Component派生类、接口: " + ComponentType.Name);
return null;
}
private void _initUIEvent(object uiModule, MethodInfo[] mMethods)
{
foreach (var mMethodInfo in mMethods)
{
var mAttrObjs = mMethodInfo.GetCustomAttributes(typeof(BindUIEvent), false);
if (mAttrObjs.Length > 0)
{
var mAttrObj = mAttrObjs[0] as BindUIEvent;
var methodParameters = mMethodInfo.GetParameters();
if (methodParameters.Length == 1 & methodParameters[0].ParameterType == typeof(EventArg))
{
Action<EventArg> action = (EventArg rArg) => { mMethodInfo.Invoke(uiModule, new object[] {rArg}); };
viewManager.EventManager.BindEvent(mAttrObj.EventCode, action);
addEvent(mAttrObj.EventCode, action);
}
else
{
Debug.LogError("[IceCreamView] 指定方法不符合规定方法必须声明传参EventArg : " + mMethodInfo.Name, this);
}
}
}
}
private void _initUIButton(object uiModule, MethodInfo[] mMethods)
{
foreach (var mMethodInfo in mMethods)
{
var mAttrObjs = mMethodInfo.GetCustomAttributes(typeof(BindUIButton), false);
if (mAttrObjs.Length > 0)
{
var mAttrObj = mAttrObjs[0] as BindUIButton;
var methodParameters = mMethodInfo.GetParameters();
if (methodParameters.Length == 0)
{
void Callback()
{
mMethodInfo.Invoke(uiModule, null);
}
if (mAttrObj != null)
{
mAttrObj.AddListener(this.transform, Callback);
mAttrObj.AddListenerButton(Callback);
}
}
else
{
Debug.LogError("[IceCreamView] 指定方法不符合规定,点击事件方法不能携带任何参数 : " + mMethodInfo.Name, this);
}
}
}
}
private void addEvent(int code, Action<EventArg> action)
{
if (!this.eventDict.ContainsKey(code))
this.eventDict[code] = new List<Action<EventArg>>();
this.eventDict[code].Add(action);
}
private void removeEvent()
{
foreach (var mEventListKey in this.eventDict.Keys)
{
foreach (Action<EventArg> mAction in this.eventDict[mEventListKey])
{
this.viewManager.EventManager.UnBindEvent(mEventListKey, mAction);
}
}
}
private enum RunType
{
OnInit,
OnOpen,
OnClose
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 7783ab86db5640e4485e3aff12200852
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,40 @@
using System.Collections.Generic;
namespace IcecreamView
{
public class IC_ViewData
{
internal const string DefaultCode = "DEFAULT_MSG";
public string code;
public List<object> values;
public int MsgCount => values?.Count ?? 0;
public IC_ViewData(params object[] values)
{
this.code = DefaultCode;
this.values = new List<object>();
this.values.AddRange(values);
}
public static IC_ViewData CreateData(string code, params object[] values)
{
var data = new IC_ViewData(values);
data.code = code;
return data;
}
public T GetValue<T>(int index = 0)
{
if (this.values[index] == null)
return default;
return (T) this.values[index];
}
public object GetValue(int index = 0)
{
if (this.values[index] == null)
return default;
return this.values[index];
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: e926a14e48a48b64ca208e80c01016da
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,16 @@
{
"name": "IcecreamView",
"references": [
"GUID:9e24947de15b9834991c9d8411ea37cf",
"GUID:84651a3751eca9349aac36a66bba901b"
],
"includePlatforms": [],
"excludePlatforms": [],
"allowUnsafeCode": false,
"overrideReferences": false,
"precompiledReferences": [],
"autoReferenced": true,
"defineConstraints": [],
"versionDefines": [],
"noEngineReferences": false
}

View File

@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 9d61d29b329d622458c8165d250bc2d9
AssemblyDefinitionImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,34 @@
using UnityEngine;
namespace IcecreamView
{
/// <summary>
/// 单例模板类
/// </summary>
/// <typeparam name="T">必须为继承MonoBehaviour对象</typeparam>
public class SingletonTemplate<T> : MonoBehaviour where T : MonoBehaviour
{
private static volatile T instance;
private static object syncRoot = new Object();
public static T Instance
{
get
{
lock (syncRoot)
{
if (instance == null)
{
instance = FindObjectOfType<T>();
if (instance == null)
{
GameObject go = new GameObject();
go.name = typeof(T).Name;
instance = go.AddComponent<T>();
}
}
}
return instance;
}
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 1ad56bc16870bda4b83347400dee3137
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant: