This commit is contained in:
Weekend
2023-10-30 23:04:05 +08:00
46 changed files with 1769 additions and 418 deletions

View File

@@ -277,7 +277,7 @@ namespace GameLogic
item.SetSelected(false); item.SetSelected(false);
} }
item = GetItem(m_selectIndex) as IListSelectItem; item = GetItem(selectIndex) as IListSelectItem;
if (item != null) if (item != null)
{ {
item.SetSelected(true); item.SetSelected(true);

View File

@@ -1,5 +1,6 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using TEngine;
using UnityEngine; using UnityEngine;
namespace GameLogic namespace GameLogic
@@ -17,7 +18,7 @@ namespace GameLogic
/// <summary> /// <summary>
/// Item字典 /// Item字典
/// </summary> /// </summary>
private Dictionary<int, TItem> m_itemCache = new Dictionary<int, TItem>(); private GameFrameworkDictionary<int, TItem> m_itemCache = new GameFrameworkDictionary<int, TItem>();
/// <summary> /// <summary>
/// 计算偏差后的ItemList /// 计算偏差后的ItemList
@@ -163,9 +164,19 @@ namespace GameLogic
m_items.Clear(); m_items.Clear();
for (int i = 0; i < m_itemCache.Count; i++) for (int i = 0; i < m_itemCache.Count; i++)
{ {
m_items.Add(m_itemCache[i]); m_items.Add(m_itemCache.GetValueByIndex(i));
} }
return m_items; return m_items;
} }
/// <summary>
/// 获取Item。
/// </summary>
/// <param name="index">索引。</param>
/// <returns>TItem。</returns>
public TItem GetItemByIndex(int index)
{
return m_itemCache.GetValueByIndex(index);
}
} }
} }

View File

@@ -8,7 +8,7 @@ namespace GameLogic
{ {
public LoopListView LoopRectView { private set; get; } public LoopListView LoopRectView { private set; get; }
private Dictionary<int, T> m_itemCache = new Dictionary<int, T>(); private GameFrameworkDictionary<int, T> m_itemCache = new GameFrameworkDictionary<int, T>();
public override void BindMemberProperty() public override void BindMemberProperty()
{ {
@@ -71,9 +71,8 @@ namespace GameLogic
List<T> list = new List<T>(); List<T> list = new List<T>();
for (int i = 0; i < m_itemCache.Count; i++) for (int i = 0; i < m_itemCache.Count; i++)
{ {
list.Add(m_itemCache[i]); list.Add(m_itemCache.GetValueByIndex(i));
} }
return list; return list;
} }
@@ -85,11 +84,11 @@ namespace GameLogic
/// <summary> /// <summary>
/// 获取Item。 /// 获取Item。
/// </summary> /// </summary>
/// <param name="index"></param> /// <param name="index">索引。</param>
/// <returns></returns> /// <returns>TItem。</returns>
public T GetItemByIndex(int index) public T GetItemByIndex(int index)
{ {
return m_itemCache[index]; return m_itemCache.GetValueByIndex(index);
} }
} }
} }

View File

@@ -1,5 +1,6 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using TEngine;
using UnityEngine; using UnityEngine;
namespace GameLogic namespace GameLogic
@@ -16,8 +17,9 @@ namespace GameLogic
/// <summary> /// <summary>
/// Item字典 /// Item字典
/// <remarks>Key => GameObjectHashCode | Value => TItem.</remarks>
/// </summary> /// </summary>
private Dictionary<int, TItem> m_itemCache = new Dictionary<int, TItem>(); private GameFrameworkDictionary<int, TItem> m_itemCache = new GameFrameworkDictionary<int, TItem>();
/// <summary> /// <summary>
/// 计算偏差后的ItemList /// 计算偏差后的ItemList
@@ -159,7 +161,10 @@ namespace GameLogic
public List<TItem> GetItemList() public List<TItem> GetItemList()
{ {
m_items.Clear(); m_items.Clear();
m_items.AddRange(m_itemCache.Values); for (int i = 0; i < m_itemCache.Count; i++)
{
m_items.Add(m_itemCache.GetValueByIndex(i));
}
return m_items; return m_items;
} }
@@ -171,5 +176,15 @@ namespace GameLogic
{ {
return LoopRectView.GetItemStartIndex(); return LoopRectView.GetItemStartIndex();
} }
/// <summary>
/// 获取Item。
/// </summary>
/// <param name="index">索引。</param>
/// <returns>TItem。</returns>
public TItem GetItemByIndex(int index)
{
return m_itemCache.GetValueByIndex(index);
}
} }
} }

View File

@@ -812,7 +812,6 @@ GameObject:
- component: {fileID: 4070374929253206932} - component: {fileID: 4070374929253206932}
- component: {fileID: 4872533144352319846} - component: {fileID: 4872533144352319846}
- component: {fileID: 3352775805385032060} - component: {fileID: 3352775805385032060}
- component: {fileID: 3859027068210555860}
m_Layer: 5 m_Layer: 5
m_Name: UILoadTip m_Name: UILoadTip
m_TagString: Untagged m_TagString: Untagged
@@ -880,31 +879,6 @@ MonoBehaviour:
m_BlockingMask: m_BlockingMask:
serializedVersion: 2 serializedVersion: 2
m_Bits: 55 m_Bits: 55
--- !u!114 &3859027068210555860
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 7666412045263395013}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: bcd11033283847ee8f7c71eedd9a4771, type: 3}
m_Name:
m_EditorClassIdentifier:
elements:
m_keys:
- m_btnUpdate
- m_btnIgnore
- m_textInfo
- m_textTittle
- m_btnPackage
m_values:
- {fileID: 2745714441875214452}
- {fileID: 467775921333773033}
- {fileID: 3862717357071106210}
- {fileID: 9127528276671758327}
- {fileID: 1387175525974173601}
--- !u!1 &8012535748721374403 --- !u!1 &8012535748721374403
GameObject: GameObject:
m_ObjectHideFlags: 0 m_ObjectHideFlags: 0

View File

@@ -773,7 +773,6 @@ GameObject:
- component: {fileID: 1633508802563447727} - component: {fileID: 1633508802563447727}
- component: {fileID: 5827342734203288403} - component: {fileID: 5827342734203288403}
- component: {fileID: 4835021223508371640} - component: {fileID: 4835021223508371640}
- component: {fileID: 903919243524269039}
m_Layer: 5 m_Layer: 5
m_Name: UILoadUpdate m_Name: UILoadUpdate
m_TagString: Untagged m_TagString: Untagged
@@ -843,33 +842,6 @@ MonoBehaviour:
m_BlockingMask: m_BlockingMask:
serializedVersion: 2 serializedVersion: 2
m_Bits: 55 m_Bits: 55
--- !u!114 &903919243524269039
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 9130266365217219149}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: bcd11033283847ee8f7c71eedd9a4771, type: 3}
m_Name:
m_EditorClassIdentifier:
elements:
m_keys:
- m_imgBackGround
- m_scrollbarProgress
- m_textDesc
- m_btnClear
- m_textAppid
- m_textResid
m_values:
- {fileID: 4652061626151979521}
- {fileID: 2347891492826839465}
- {fileID: 8666815445422661327}
- {fileID: 4232232858152633415}
- {fileID: 3038352660368000718}
- {fileID: 8143980099109665604}
--- !u!1 &9157096376857424144 --- !u!1 &9157096376857424144
GameObject: GameObject:
m_ObjectHideFlags: 0 m_ObjectHideFlags: 0

View File

@@ -20,26 +20,22 @@ namespace GameMain
public MessageShowType ShowType = MessageShowType.None; public MessageShowType ShowType = MessageShowType.None;
#region #region
private Button m_btnPackage; private Button m_btnPackage;
private Text m_textTittle; private Text m_textTittle;
private Text m_textInfo; private Text m_textInfo;
private Button m_btnIgnore; private Button m_btnIgnore;
private Button m_btnUpdate; private Button m_btnUpdate;
public override void ScriptGenerator() public override void ScriptGenerator()
{ {
CheckUIElement(); m_btnPackage = FindChildComponent<Button>("BgImage/m_btnPackage");
m_btnPackage = FChild<Button>("m_btnPackage"); m_textTittle = FindChildComponent<Text>("BgImage/m_textTittle");
m_textTittle = FChild<Text>("m_textTittle"); m_textInfo = FindChildComponent<Text>("BgImage/m_textInfo");
m_textInfo = FChild<Text>("m_textInfo"); m_btnIgnore = FindChildComponent<Button>("BgImage/Group/m_btnIgnore");
m_btnIgnore = FChild<Button>("m_btnIgnore"); m_btnUpdate = FindChildComponent<Button>("BgImage/Group/m_btnUpdate");
m_btnUpdate = FChild<Button>("m_btnUpdate");
m_btnPackage.onClick.AddListener(OnClickPackageBtn); m_btnPackage.onClick.AddListener(OnClickPackageBtn);
m_btnIgnore.onClick.AddListener(OnClickIgnoreBtn); m_btnIgnore.onClick.AddListener(OnClickIgnoreBtn);
m_btnUpdate.onClick.AddListener(OnClickUpdateBtn); m_btnUpdate.onClick.AddListener(OnClickUpdateBtn);
} }
#endregion #endregion
#region #region

View File

@@ -8,22 +8,22 @@ namespace GameMain
[Window(UILayer.UI, fromResources: true, location: "AssetLoad/UILoadUpdate",fullScreen:true)] [Window(UILayer.UI, fromResources: true, location: "AssetLoad/UILoadUpdate",fullScreen:true)]
public class UILoadUpdate : UIWindow public class UILoadUpdate : UIWindow
{ {
private Scrollbar m_scrollbarProgress;
#region #region
private Image m_imgBackGround; private Image m_imgBackGround;
private Scrollbar m_scrollbarProgress;
private Text m_textDesc; private Text m_textDesc;
private Button m_btnClear; private Button m_btnClear;
private Text m_textAppid; private Text m_textAppid;
private Text m_textResid; private Text m_textResid;
public override void ScriptGenerator() public override void ScriptGenerator()
{ {
CheckUIElement(); m_imgBackGround = FindChildComponent<Image>("m_imgBackGround");
m_imgBackGround = FChild<Image>("m_imgBackGround"); m_textDesc = FindChildComponent<Text>("m_textDesc");
m_scrollbarProgress = FChild<Scrollbar>("m_scrollbarProgress"); m_btnClear = FindChildComponent<Button>("TopNode/m_btnClear");
m_textDesc = FChild<Text>("m_textDesc"); m_textAppid = FindChildComponent<Text>("TopNode/m_textAppid");
m_btnClear = FChild<Button>("m_btnClear"); m_textResid = FindChildComponent<Text>("TopNode/m_textResid");
m_textAppid = FChild<Text>("m_textAppid"); m_scrollbarProgress = FindChildComponent<Scrollbar>("m_scrollbarProgress");
m_textResid = FChild<Text>("m_textResid");
m_btnClear.onClick.AddListener(OnClickClearBtn); m_btnClear.onClick.AddListener(OnClickClearBtn);
} }
#endregion #endregion
@@ -118,12 +118,12 @@ namespace GameMain
m_scrollbarProgress.size = progress; m_scrollbarProgress.size = progress;
} }
protected override void Close() public override void OnDestroy()
{ {
base.OnDestroy();
OnStop(null); OnStop(null);
LoadUpdateLogic.Instance.DownloadCompleteAction -= DownLoad_Complete_Action; LoadUpdateLogic.Instance.DownloadCompleteAction -= DownLoad_Complete_Action;
LoadUpdateLogic.Instance.DownProgressAction -= DownLoad_Progress_Action; LoadUpdateLogic.Instance.DownProgressAction -= DownLoad_Progress_Action;
base.Close();
} }
} }
} }

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: bf1e53a3963b4dbf8c5f139ee8d80c3d
timeCreated: 1698301726

View File

@@ -0,0 +1,45 @@
using Sirenix.OdinInspector;
using UnityEngine;
using UnityEditor;
/// <summary>
/// 自动绑定全局设置
/// </summary>
public class AutoBindGlobalSetting : ScriptableObject
{
[FolderPath]
[LabelText("默认组件代码保存路径")]
[SerializeField]
private string m_CodePath;
[LabelText("绑定代码命名空间")]
[SerializeField]
private string m_Namespace;
[LabelText("子组件名称(不会往下继续遍历)")]
[SerializeField]
private string m_WidgetName = "m_item";
public string CodePath => m_CodePath;
public string Namespace => m_Namespace;
public string WidgetName => m_WidgetName;
[MenuItem("TEngine/CreateAutoBindGlobalSetting")]
private static void CreateAutoBindGlobalSetting()
{
string[] paths = AssetDatabase.FindAssets("t:AutoBindGlobalSetting");
if (paths.Length >= 1)
{
string path = AssetDatabase.GUIDToAssetPath(paths[0]);
EditorUtility.DisplayDialog("警告", $"已存在AutoBindGlobalSetting路径:{path}", "确认");
return;
}
AutoBindGlobalSetting setting = CreateInstance<AutoBindGlobalSetting>();
AssetDatabase.CreateAsset(setting, "Assets/TEngine/ResRaw/AutoBindGlobalSetting.asset");
AssetDatabase.SaveAssets();
AssetDatabase.Refresh();
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 3dac541dae7b4c4d8b5497057739cfb0
timeCreated: 1698304721

View File

@@ -0,0 +1,12 @@
using Sirenix.OdinInspector.Editor;
using UnityEditor;
[CustomEditor(typeof(AutoBindGlobalSetting))]
public class AutoBindGlobalSettingInspector : OdinEditor
{
public override void OnInspectorGUI()
{
base.OnInspectorGUI();
serializedObject.ApplyModifiedProperties();
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 020e5781e8c44c90bfbdf2cb12441e79
timeCreated: 1698304745

View File

@@ -0,0 +1,534 @@
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
using System;
using BindData = ComponentAutoBindTool.BindData;
using System.Reflection;
using System.IO;
[CustomEditor(typeof(ComponentAutoBindTool))]
public class ComponentAutoBindToolInspector : Editor
{
private ComponentAutoBindTool m_Target;
private SerializedProperty m_BindDatas;
private SerializedProperty m_BindComs;
private List<BindData> m_TempList = new List<BindData>();
private List<string> m_TempFiledNames = new List<string>();
private List<string> m_TempComponentTypeNames = new List<string>();
private string[] s_AssemblyNames = { "Assembly-CSharp", "TEngine.Runtime" };
private string[] m_HelperTypeNames;
private string m_HelperTypeName;
private int m_HelperTypeNameIndex;
private AutoBindGlobalSetting m_Setting;
private SerializedProperty m_Namespace;
private SerializedProperty m_ClassName;
private SerializedProperty m_CodePath;
private SerializedProperty m_IsWidget;
private void OnEnable()
{
m_Target = (ComponentAutoBindTool)target;
m_BindDatas = serializedObject.FindProperty("BindDatas");
m_BindComs = serializedObject.FindProperty("bindComponents");
m_HelperTypeNames = GetTypeNames(typeof(IAutoBindRuleHelper), s_AssemblyNames);
string[] paths = AssetDatabase.FindAssets("t:AutoBindGlobalSetting");
if (paths.Length == 0)
{
Debug.LogError("不存在AutoBindGlobalSetting");
return;
}
if (paths.Length > 1)
{
Debug.LogError("AutoBindGlobalSetting数量大于1");
return;
}
string path = AssetDatabase.GUIDToAssetPath(paths[0]);
m_Setting = AssetDatabase.LoadAssetAtPath<AutoBindGlobalSetting>(path);
m_Namespace = serializedObject.FindProperty("m_Namespace");
m_ClassName = serializedObject.FindProperty("m_ClassName");
m_CodePath = serializedObject.FindProperty("m_CodePath");
m_IsWidget = serializedObject.FindProperty("m_IsWidget");
m_Namespace.stringValue = string.IsNullOrEmpty(m_Namespace.stringValue) ? m_Setting.Namespace : m_Namespace.stringValue;
m_ClassName.stringValue = string.IsNullOrEmpty(m_ClassName.stringValue) ? m_Target.gameObject.name : m_ClassName.stringValue;
m_CodePath.stringValue = string.IsNullOrEmpty(m_CodePath.stringValue) ? m_Setting.CodePath : m_CodePath.stringValue;
serializedObject.ApplyModifiedProperties();
}
public override void OnInspectorGUI()
{
serializedObject.Update();
DrawTopButton();
DrawHelperSelect();
DrawSetting();
DrawKvData();
serializedObject.ApplyModifiedProperties();
}
/// <summary>
/// 绘制顶部按钮
/// </summary>
private void DrawTopButton()
{
EditorGUILayout.BeginHorizontal();
if (GUILayout.Button("排序"))
{
Sort();
}
if (GUILayout.Button("全部删除"))
{
RemoveAll();
}
if (GUILayout.Button("删除空引用"))
{
RemoveNull();
}
if (GUILayout.Button("自动绑定组件"))
{
AutoBindComponent();
}
if (GUILayout.Button("生成绑定代码"))
{
GenAutoBindCode();
}
EditorGUILayout.EndHorizontal();
}
/// <summary>
/// 排序
/// </summary>
private void Sort()
{
m_TempList.Clear();
foreach (BindData data in m_Target.BindDatas)
{
m_TempList.Add(new BindData(data.Name, data.BindCom, data.IsGameObject));
}
m_TempList.Sort((x, y) => string.Compare(x.Name, y.Name, StringComparison.Ordinal));
m_BindDatas.ClearArray();
foreach (BindData data in m_TempList)
{
AddBindData(data.Name, data.BindCom, data.IsGameObject);
}
SyncBindComs();
}
/// <summary>
/// 全部删除
/// </summary>
private void RemoveAll()
{
m_BindDatas.ClearArray();
SyncBindComs();
}
/// <summary>
/// 删除空引用
/// </summary>
private void RemoveNull()
{
for (int i = m_BindDatas.arraySize - 1; i >= 0; i--)
{
SerializedProperty element = m_BindDatas.GetArrayElementAtIndex(i).FindPropertyRelative("BindCom");
if (element.objectReferenceValue == null)
{
m_BindDatas.DeleteArrayElementAtIndex(i);
}
}
SyncBindComs();
}
/// <summary>
/// 自动绑定组件
/// </summary>
private void AutoBindComponent()
{
m_BindDatas.ClearArray();
var transform = m_Target.transform;
Ergodic(transform, transform);
SyncBindComs();
}
private void Ergodic(Transform rootTransform, Transform currentTransform)
{
for (int i = 0; i < currentTransform.childCount; ++i)
{
Transform child = currentTransform.GetChild(i);
m_TempFiledNames.Clear();
m_TempComponentTypeNames.Clear();
if (m_Target.RuleHelper.IsValidBind(child, m_TempFiledNames, m_TempComponentTypeNames))
{
for (int index = 0; index < m_TempFiledNames.Count; index++)
{
string componentName = m_TempComponentTypeNames[index];
bool isGameObject = componentName.Equals("GameObject");
componentName = isGameObject ? "Transform" : componentName;
Component com = child.GetComponent(componentName);
if (com == null)
{
Debug.LogError($"{child.name}上不存在{componentName}的组件");
}
else
{
AddBindData(m_TempFiledNames[index], child.GetComponent(componentName), isGameObject);
}
}
}
if (!child.name.StartsWith(m_Setting.WidgetName))
{
Ergodic(rootTransform, child);
}
}
}
/// <summary>
/// 绘制辅助器选择框
/// </summary>
private void DrawHelperSelect()
{
m_HelperTypeName = m_HelperTypeNames[0];
if (m_Target.RuleHelper != null)
{
m_HelperTypeName = m_Target.RuleHelper.GetType().Name;
for (int i = 0; i < m_HelperTypeNames.Length; i++)
{
if (m_HelperTypeName == m_HelperTypeNames[i])
{
m_HelperTypeNameIndex = i;
}
}
}
else
{
IAutoBindRuleHelper helper = (IAutoBindRuleHelper)CreateHelperInstance(m_HelperTypeName, s_AssemblyNames);
m_Target.RuleHelper = helper;
}
foreach (GameObject go in Selection.gameObjects)
{
ComponentAutoBindTool autoBindTool = go.GetComponent<ComponentAutoBindTool>();
if (autoBindTool.RuleHelper == null)
{
IAutoBindRuleHelper helper = (IAutoBindRuleHelper)CreateHelperInstance(m_HelperTypeName, s_AssemblyNames);
autoBindTool.RuleHelper = helper;
}
}
int selectedIndex = EditorGUILayout.Popup("AutoBindRuleHelper", m_HelperTypeNameIndex, m_HelperTypeNames);
if (selectedIndex != m_HelperTypeNameIndex)
{
m_HelperTypeNameIndex = selectedIndex;
m_HelperTypeName = m_HelperTypeNames[selectedIndex];
IAutoBindRuleHelper helper = (IAutoBindRuleHelper)CreateHelperInstance(m_HelperTypeName, s_AssemblyNames);
m_Target.RuleHelper = helper;
}
}
/// <summary>
/// 绘制设置项
/// </summary>
private void DrawSetting()
{
EditorGUILayout.BeginHorizontal();
m_Namespace.stringValue = EditorGUILayout.TextField(new GUIContent("命名空间:"), m_Namespace.stringValue);
if (GUILayout.Button("默认设置"))
{
m_Namespace.stringValue = m_Setting.Namespace;
}
EditorGUILayout.EndHorizontal();
EditorGUILayout.BeginHorizontal();
m_ClassName.stringValue = EditorGUILayout.TextField(new GUIContent("类名:"), m_ClassName.stringValue);
if (GUILayout.Button("物体名"))
{
m_ClassName.stringValue = m_Target.gameObject.name;
}
EditorGUILayout.EndHorizontal();
bool isWidget = EditorGUILayout.Toggle("是否是组件", m_IsWidget.boolValue);
if (isWidget != m_IsWidget.boolValue)
{
m_IsWidget.boolValue = isWidget;
}
EditorGUILayout.LabelField("代码保存路径:");
EditorGUILayout.LabelField(m_CodePath.stringValue);
EditorGUILayout.BeginHorizontal();
if (GUILayout.Button("选择路径"))
{
string temp = m_CodePath.stringValue;
m_CodePath.stringValue = EditorUtility.OpenFolderPanel("选择代码保存路径", Application.dataPath, "");
if (string.IsNullOrEmpty(m_CodePath.stringValue))
{
m_CodePath.stringValue = temp;
}
}
if (GUILayout.Button("默认设置"))
{
m_CodePath.stringValue = m_Setting.CodePath;
}
EditorGUILayout.EndHorizontal();
}
/// <summary>
/// 绘制键值对数据
/// </summary>
private void DrawKvData()
{
//绘制key value数据
int needDeleteIndex = -1;
EditorGUILayout.BeginVertical();
SerializedProperty property;
for (int i = 0; i < m_BindDatas.arraySize; i++)
{
EditorGUILayout.BeginHorizontal();
EditorGUILayout.LabelField($"[{i}]", GUILayout.Width(25));
property = m_BindDatas.GetArrayElementAtIndex(i).FindPropertyRelative("Name");
property.stringValue = EditorGUILayout.TextField(property.stringValue, GUILayout.Width(150));
property = m_BindDatas.GetArrayElementAtIndex(i).FindPropertyRelative("BindCom");
property.objectReferenceValue = EditorGUILayout.ObjectField(property.objectReferenceValue, typeof(Component), true);
if (GUILayout.Button("X"))
{
//将元素下标添加进删除list
needDeleteIndex = i;
}
EditorGUILayout.EndHorizontal();
}
//删除data
if (needDeleteIndex != -1)
{
m_BindDatas.DeleteArrayElementAtIndex(needDeleteIndex);
SyncBindComs();
}
EditorGUILayout.EndVertical();
}
/// <summary>
/// 添加绑定数据
/// </summary>
private void AddBindData(string name, Component bindCom, bool isGameObject = false)
{
int index = m_BindDatas.arraySize;
m_BindDatas.InsertArrayElementAtIndex(index);
SerializedProperty element = m_BindDatas.GetArrayElementAtIndex(index);
element.FindPropertyRelative("Name").stringValue = name;
element.FindPropertyRelative("BindCom").objectReferenceValue = bindCom;
element.FindPropertyRelative("IsGameObject").boolValue = isGameObject;
}
/// <summary>
/// 同步绑定数据
/// </summary>
private void SyncBindComs()
{
m_BindComs.ClearArray();
for (int i = 0; i < m_BindDatas.arraySize; i++)
{
SerializedProperty property = m_BindDatas.GetArrayElementAtIndex(i).FindPropertyRelative("BindCom");
m_BindComs.InsertArrayElementAtIndex(i);
m_BindComs.GetArrayElementAtIndex(i).objectReferenceValue = property.objectReferenceValue;
}
}
/// <summary>
/// 获取指定基类在指定程序集中的所有子类名称
/// </summary>
private string[] GetTypeNames(Type typeBase, string[] assemblyNames)
{
List<string> typeNames = new List<string>();
foreach (string assemblyName in assemblyNames)
{
Assembly assembly = null;
try
{
assembly = Assembly.Load(assemblyName);
}
catch
{
continue;
}
if (assembly == null)
{
continue;
}
Type[] types = assembly.GetTypes();
foreach (Type type in types)
{
if (type.IsClass && !type.IsAbstract && typeBase.IsAssignableFrom(type))
{
typeNames.Add(type.FullName);
}
}
}
typeNames.Sort();
return typeNames.ToArray();
}
/// <summary>
/// 创建辅助器实例
/// </summary>
private object CreateHelperInstance(string helperTypeName, string[] assemblyNames)
{
foreach (string assemblyName in assemblyNames)
{
Assembly assembly = Assembly.Load(assemblyName);
object instance = assembly.CreateInstance(helperTypeName);
if (instance != null)
{
return instance;
}
}
return null;
}
/// <summary>
/// 生成自动绑定代码
/// </summary>
private void GenAutoBindCode()
{
GameObject go = m_Target.gameObject;
string className = !string.IsNullOrEmpty(m_Target.ClassName) ? m_Target.ClassName : go.name;
string codePath = !string.IsNullOrEmpty(m_Target.CodePath) ? m_Target.CodePath : m_Setting.CodePath;
if (!Directory.Exists(codePath))
{
Debug.LogError($"{go.name}的代码保存路径{codePath}无效");
}
using (StreamWriter sw = new StreamWriter($"{codePath}/{className}.BindComponents.cs"))
{
sw.WriteLine(
"//------------------------------------------------------------------------------\n//\t<auto-generated>\n//\t\tTime:[" + DateTime.Now +
"].\n//\t\tThis code was generated by autoBindTool.\n//\t\tChanges to this file may cause incorrect behavior and will be lost if\n//\t\tthe code is regenerated.\n//\t</auto-generated>\n//------------------------------------------------------------------------------");
sw.WriteLine("using UnityEngine;");
sw.WriteLine("using UnityEngine.UI;");
sw.WriteLine("using TEngine;");
sw.WriteLine("");
if (!string.IsNullOrEmpty(m_Target.Namespace))
{
//命名空间
sw.WriteLine("namespace " + m_Target.Namespace);
sw.WriteLine("{");
}
//类名
// if (!m_Target.IsWidget)
// {
// sw.WriteLine($"\tpublic partial class {className} : UIWindow");
// }
// else
// {
// sw.WriteLine($"\tpublic partial class {className} : UIWidget");
// }
sw.WriteLine($"\tpublic partial class {className}");
sw.WriteLine("\t{");
//组件字段
foreach (BindData data in m_Target.BindDatas)
{
if (data.IsGameObject)
{
sw.WriteLine($"\t\tprivate GameObject m_{data.Name};");
}
else
{
sw.WriteLine($"\t\tprivate {data.BindCom.GetType().Name} m_{data.Name};");
}
}
sw.WriteLine("");
// sw.WriteLine(
// "\t\tpublic override void ScriptGenerator()\n\t\t{\n\t\t\tbase.ScriptGenerator();\n\t\t\tGetBindComponents(transform.gameObject);\n\t\t}");
sw.WriteLine("\t\tprivate void GetBindComponents(GameObject go)");
sw.WriteLine("\t\t{");
//获取autoBindTool上的Component
sw.WriteLine($"\t\t\tComponentAutoBindTool autoBindTool = go.GetComponent<ComponentAutoBindTool>();");
sw.WriteLine("");
//根据索引获取
for (int i = 0; i < m_Target.BindDatas.Count; i++)
{
BindData data = m_Target.BindDatas[i];
string filedName = $"m_{data.Name}";
if (data.IsGameObject)
{
sw.WriteLine($"\t\t\t{filedName} = autoBindTool.GetBindComponent<{data.BindCom.GetType().Name}>({i}).gameObject;");
}
else
{
sw.WriteLine($"\t\t\t{filedName} = autoBindTool.GetBindComponent<{data.BindCom.GetType().Name}>({i});");
}
}
sw.WriteLine("\t\t}");
sw.WriteLine("\t}");
if (!string.IsNullOrEmpty(m_Target.Namespace))
{
sw.WriteLine("}");
}
}
AssetDatabase.Refresh();
EditorUtility.DisplayDialog("提示", "代码生成完毕", "OK");
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 77f2df681a094ff5a14e92e380ba90e7
timeCreated: 1698304775

View File

@@ -1,179 +0,0 @@
using System.Collections.Generic;
using System.Text;
using Sirenix.OdinInspector.Editor;
using TEngine.Editor.UI;
using UnityEditor;
using UnityEngine;
#if UNITY_EDITOR
namespace TEngine
{
[CanEditMultipleObjects]
[CustomEditor(typeof(UIElement), true)]
public class UIElementEditor : OdinEditor
{
protected UIElement Element;
protected override void OnEnable()
{
base.OnEnable();
Element = target as UIElement;
}
public override void OnInspectorGUI()
{
serializedObject.Update();
EditorGUI.BeginChangeCheck();
if (GUILayout.Button("Generate", GUILayout.Width(130)))
{
CheckUiItems();
}
serializedObject.ApplyModifiedProperties();
if (EditorGUI.EndChangeCheck())
{
EditorUtility.SetDirty(Element);
}
base.OnInspectorGUI();
}
protected void CheckUiItems()
{
if (Element == null) return;
ClearUnusedItems();
var root = Element.transform;
StringBuilder strVar = new StringBuilder();
StringBuilder strBind = new StringBuilder();
StringBuilder strOnCreate = new StringBuilder();
StringBuilder strOnCreateRedNote = new StringBuilder();
StringBuilder strCallback = new StringBuilder();
Ergodic(root, root, ref strVar, ref strBind, ref strOnCreate, ref strOnCreateRedNote, ref strCallback);
StringBuilder strFile = new StringBuilder();
// 脚本工具生成的代码
strFile.Append("\t\t#region 脚本工具生成的代码\n");
strFile.Append(strVar);
strFile.Append("\t\tpublic override void ScriptGenerator()\n");
strFile.Append("\t\t{\n");
strFile.Append("\t\t\tCheckUIElement();\n");
strFile.Append(strBind);
strFile.Append(strOnCreate);
strFile.Append(strOnCreateRedNote);
strFile.Append("\t\t}\n");
strFile.Append("\t\t#endregion");
TextEditor te = new TextEditor();
te.text = strFile.ToString();
te.SelectAll();
te.Copy();
}
private void ClearUnusedItems()
{
if (Element == null || Element.Elements == null) return;
List<string> ids = new List<string>();
foreach (var kv in Element.Elements)
{
if (kv.Value == null || !string.IsNullOrEmpty(GetVerType(kv.Key)))
{
ids.Add(kv.Key);
}
}
foreach (var id in ids)
{
Element.Elements.Remove(id);
}
}
private void Ergodic(Transform root, Transform transform, ref StringBuilder strVar, ref StringBuilder strBind, ref StringBuilder strOnCreate,
ref StringBuilder strOnCreateRedNote, ref StringBuilder strCallback)
{
for (int i = 0; i < transform.childCount; ++i)
{
Transform child = transform.GetChild(i);
WriteScript(root, child, ref strVar, ref strBind, ref strOnCreate, ref strOnCreateRedNote, ref strCallback);
if (child.name.StartsWith("m_item"))
{
continue;
}
Ergodic(root, child, ref strVar, ref strBind, ref strOnCreate, ref strOnCreateRedNote, ref strCallback);
}
}
private void WriteScript(Transform root, Transform child, ref StringBuilder strVar, ref StringBuilder strBind, ref StringBuilder strOnCreate,
ref StringBuilder strOnCreateRedNote, ref StringBuilder strCallback)
{
var varName = child.name;
var varType = GetVerType(varName);
if (varType == string.Empty) return;
if (Element.Elements.Contains(varName))
{
Debug.LogError("有重复的key:" + varName);
return;
}
Element.Elements[varName] = child;
if (!string.IsNullOrEmpty(varName))
{
strVar.Append("\t\tprivate " + varType + " " + varName + ";\n");
switch (varType)
{
case "Transform":
strBind.Append($"\t\t\t{varName} = FChild(\"{varName}\");\n");
break;
case "GameObject":
strBind.Append($"\t\t\t{varName} = FChild(\"{varName}\").gameObject;\n");
break;
case "RichItemIcon":
strBind.Append($"\t\t\t{varName} = CreateWidgetByType<{varType}>(FChild(\"{varName}\"));\n");
break;
case "RedNoteWidget":
break;
case "TextButtonItem":
case "SwitchTabItem":
case "UIActorWidget":
case "UIEffectWidget":
case "UISpineWidget":
case "UIMainPlayerWidget":
strBind.Append($"\t\t\t{varName} = CreateWidget<{varType}>(FChild(\"{varName}\").gameObject);\n");
break;
default:
strBind.Append($"\t\t\t{varName} = FChild<{varType}>(\"{varName}\");\n");
break;
}
if (varType == "Button")
{
string varFuncName = ScriptGenerator.GetBtnFuncName(varName);
strOnCreate.Append($"\t\t\t{varName}.onClick.AddListener({varFuncName});\n");
strCallback.Append($"\t\tprivate void {varFuncName}()\n");
strCallback.Append("\t\t{\n\t\t}\n");
}
else if (varType == "Toggle")
{
string varFuncName = ScriptGenerator.GetToggleFuncName(varName);
strOnCreate.Append($"\t\t\t{varName}.onValueChanged.AddListener({varFuncName});\n");
strCallback.Append($"\t\tprivate void {varFuncName}(bool isOn)\n");
strCallback.Append("\t\t{\n\t\t}\n");
}
}
}
protected string GetVerType(string uiName)
{
foreach (var pair in SettingsUtils.GetScriptGenerateRule())
{
if (uiName.StartsWith(pair.uiElementRegex))
{
return pair.componentName;
}
}
return string.Empty;
}
}
}
#endif

View File

@@ -1,3 +0,0 @@
fileFormatVersion: 2
guid: 02ba9976b78c4a079e16aa9302c1b43e
timeCreated: 1696659319

View File

@@ -0,0 +1,17 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!114 &11400000
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 0}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 3dac541dae7b4c4d8b5497057739cfb0, type: 3}
m_Name: AutoBindGlobalSetting
m_EditorClassIdentifier:
m_CodePath: Assets/GameScripts
m_Namespace: GameLogic
m_WidgetName: m_item

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: eb33bb9d9cdf9484997cc91b0517ba4d
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 11400000
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,120 @@
using System.Collections.Generic;
namespace TEngine
{
/// <summary>
/// 游戏框架字典类。
/// </summary>
/// <typeparam name="TKey">指定字典Key的元素类型。</typeparam>
/// <typeparam name="TValue">指定字典Value的元素类型。</typeparam>
public class GameFrameworkDictionary<TKey, TValue>
{
protected readonly List<TKey> KeyList = new List<TKey>();
protected readonly Dictionary<TKey, TValue> Dictionary = new Dictionary<TKey, TValue>();
/// <summary>
/// 存储键的列表。
/// </summary>
public List<TKey> Keys => KeyList;
/// <summary>
/// 存储字典实例。
/// </summary>
public int Count => KeyList.Count;
/// <summary>
/// 通过KEY的数组下标获取元素。
/// </summary>
/// <param name="index">下标。</param>
/// <returns>TValue。</returns>
public TValue GetValueByIndex(int index)
{
return Dictionary[KeyList[index]];
}
/// <summary>
/// 通过KEY的数组下标设置元素。
/// </summary>
/// <param name="index">下标。</param>
/// <param name="item">TValue。</param>
public void SetValue(int index, TValue item)
{
Dictionary[KeyList[index]] = item;
}
/// <summary>
/// 字典索引器。
/// </summary>
/// <param name="key">TKey。</param>
public TValue this[TKey key]
{
get => Dictionary[key];
set
{
if (!ContainsKey(key))
{
Add(key, value);
}
else
{
Dictionary[key] = value;
}
}
}
/// <summary>Removes all keys and values from the <see cref="T:TEngine.GameFrameworkDictionary`2" />.</summary>
public void Clear()
{
KeyList.Clear();
Dictionary.Clear();
}
/// <summary>Adds the specified key and value to the dictionary.</summary>
/// <param name="key">The key of the element to add.</param>
/// <param name="item">The value of the element to add. The value can be <see langword="null" /> for reference types.</param>
public virtual void Add(TKey key, TValue item)
{
KeyList.Add(key);
Dictionary.Add(key, item);
}
/// <summary>Gets the value associated with the specified key.</summary>
/// <param name="key">The key of the value to get.</param>
/// <param name="value">When this method returns, contains the value associated with the specified key, if the key is found; otherwise, the default value for the type of the <paramref name="value" /> parameter. This parameter is passed uninitialized.</param>
public bool TryGetValue(TKey key, out TValue value)
{
return Dictionary.TryGetValue(key, out value);
}
/// <summary>Determines whether the <see cref="T:System.Collections.Generic.Dictionary`2" /> contains the specified key.</summary>
/// <param name="key">The key to locate in the </param>
public bool ContainsKey(TKey key)
{
return Dictionary.ContainsKey(key);
}
public TKey GetKey(int index)
{
return KeyList[index];
}
public bool Remove(TKey key)
{
return KeyList.Remove(key) && Dictionary.Remove(key);
}
}
/// <summary>
/// 游戏框架顺序字典类。
/// </summary>
/// <typeparam name="TKey">指定字典Key的元素类型。</typeparam>
/// <typeparam name="TValue">指定字典Value的元素类型。</typeparam>
public class GameFrameworkSortedDictionary<TKey, TValue> : GameFrameworkDictionary<TKey, TValue>
{
public override void Add(TKey key, TValue item)
{
base.Add(key, item);
KeyList.Sort();
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 3df785fede30420dbfa6acb2ff48c166
timeCreated: 1698296076

View File

@@ -0,0 +1,614 @@
using System;
using System.Collections.Generic;
#region Class Documentation
/************************************************************************************************************
Class Name: ActorEventDispatcher.cs 局部单位事件分发器。
Type: Actor, Event
Example:
private ActorEventDispatcher _event;
/// <summary>
/// 局部事件管理器。
/// <remark>只分发和监听这个Event内部的事件</remark>
/// </summary>
public ActorEventDispatcher Event => _event ??= MemoryPool.Acquire<ActorEventDispatcher>();
// owner局部发送事件。
owner.Event.Send(eventId,xxx);
// owner监听自身事件并绑定持有对象为owner。 比如是组件的情况下。移除时调用RemoveAllListenerByOwner(owner)会根据持有对象(组件)移除。
owner.Event.AddEventListener(eventId,xxx,owner);
************************************************************************************************************/
#endregion
namespace TEngine
{
/// <summary>
/// 局部单位事件分发器。
/// </summary>
public class ActorEventDispatcher : IMemory
{
/// <summary>
/// 所有事件。
/// </summary>
private readonly Dictionary<int, List<EventRegInfo>> _allEventListenerMap;
/// <summary>
/// 用于标记一个事件是不是正在处理。
/// </summary>
private readonly List<int> _processEventList;
/// <summary>
/// 用于标记一个事件是不是被移除。
/// </summary>
private readonly List<int> _delayDeleteEventList;
public ActorEventDispatcher()
{
_processEventList = new List<int>();
_delayDeleteEventList = new List<int>();
_allEventListenerMap = new Dictionary<int, List<EventRegInfo>>();
}
/// <summary>
/// 移除所有事件监听。
/// </summary>
public void DestroyAllEventListener()
{
var itr = _allEventListenerMap.GetEnumerator();
while (itr.MoveNext())
{
var kv = itr.Current;
kv.Value.Clear();
}
_processEventList.Clear();
_delayDeleteEventList.Clear();
itr.Dispose();
}
/// <summary>
/// 延迟移除事件。
/// </summary>
/// <param name="eventId"></param>
private void AddDelayDelete(int eventId)
{
if (!_delayDeleteEventList.Contains(eventId))
{
_delayDeleteEventList.Add(eventId);
Log.Info("delay delete eventId[{0}]", eventId);
}
}
/// <summary>
/// 如果找到eventId对应的监听删除所有标记为delete的监听。
/// </summary>
/// <param name="eventId">事件Id。</param>
private void CheckDelayDelete(int eventId)
{
if (_delayDeleteEventList.Contains(eventId))
{
if (_allEventListenerMap.TryGetValue(eventId, out var listListener))
{
for (int i = 0; i < listListener.Count; i++)
{
if (listListener[i].IsDeleted)
{
Log.Info("remove delay delete eventId[{0}]", eventId);
listListener[i] = listListener[^1];
listListener.RemoveAt(listListener.Count - 1);
i--;
}
}
}
_delayDeleteEventList.Remove(eventId);
}
}
/// <summary>
/// 发送事件。
/// </summary>
/// <param name="eventId">事件Id。</param>
public void SendEvent(int eventId)
{
if (_allEventListenerMap.TryGetValue(eventId, out var listListener))
{
_processEventList.Add(eventId);
#if UNITY_EDITOR
int iEventCnt = _processEventList.Count;
#endif
var count = listListener.Count;
for (int i = 0; i < count; i++)
{
var node = listListener[i];
if (node.IsDeleted)
{
continue;
}
if (listListener[i].Callback is Action callBack)
{
callBack();
}
else
{
Log.Fatal("Invalid event data type: {0}", eventId);
}
}
#if UNITY_EDITOR
Log.Assert(iEventCnt == _processEventList.Count);
Log.Assert(eventId == _processEventList[^1]);
#endif
_processEventList.RemoveAt(_processEventList.Count - 1);
CheckDelayDelete(eventId);
}
}
/// <summary>
/// 发送事件。
/// </summary>
/// <param name="eventId">事件Id。</param>
/// <param name="arg1">事件参数。</param>
/// <typeparam name="TArg1">事件参数类型1。</typeparam>
public void SendEvent<TArg1>(int eventId, TArg1 arg1)
{
if (_allEventListenerMap.TryGetValue(eventId, out var listListener))
{
_processEventList.Add(eventId);
#if UNITY_EDITOR
int iEventCnt = _processEventList.Count;
#endif
var count = listListener.Count;
for (int i = 0; i < count; i++)
{
var node = listListener[i];
if (node.IsDeleted)
{
continue;
}
if (listListener[i].Callback is Action<TArg1> callBack)
{
callBack(arg1);
}
else
{
Log.Fatal("Invalid event data type: {0}", eventId);
}
}
#if UNITY_EDITOR
Log.Assert(iEventCnt == _processEventList.Count);
Log.Assert(eventId == _processEventList[^1]);
#endif
_processEventList.RemoveAt(_processEventList.Count - 1);
CheckDelayDelete(eventId);
}
}
/// <summary>
/// 发送事件。
/// </summary>
/// <param name="eventId">事件Id。</param>
/// <param name="arg1">事件参数1。</param>
/// <param name="arg2">事件参数2。</param>
/// <typeparam name="TArg1">事件参数类型1。</typeparam>
/// <typeparam name="TArg2">事件参数类型2。</typeparam>
public void SendEvent<TArg1, TArg2>(int eventId, TArg1 arg1, TArg2 arg2)
{
if (_allEventListenerMap.TryGetValue(eventId, out var listListener))
{
_processEventList.Add(eventId);
#if UNITY_EDITOR
int iEventCnt = _processEventList.Count;
#endif
var count = listListener.Count;
for (int i = 0; i < count; i++)
{
var node = listListener[i];
if (node.IsDeleted)
{
continue;
}
if (listListener[i].Callback is Action<TArg1, TArg2> callBack)
{
callBack(arg1, arg2);
}
else
{
Log.Fatal("Invalid event data type: {0}", eventId);
}
}
#if UNITY_EDITOR
Log.Assert(iEventCnt == _processEventList.Count);
Log.Assert(eventId == _processEventList[^1]);
#endif
_processEventList.RemoveAt(_processEventList.Count - 1);
CheckDelayDelete(eventId);
}
}
/// <summary>
/// 发送事件。
/// </summary>
/// <param name="eventId">事件Id。</param>
/// <param name="arg1">事件参数1。</param>
/// <param name="arg2">事件参数2。</param>
/// <param name="arg3">事件参数3。</param>
/// <typeparam name="TArg1">事件参数类型1。</typeparam>
/// <typeparam name="TArg2">事件参数类型2。</typeparam>
/// <typeparam name="TArg3">事件参数类型3。</typeparam>
public void SendEvent<TArg1, TArg2, TArg3>(int eventId, TArg1 arg1, TArg2 arg2, TArg3 arg3)
{
if (_allEventListenerMap.TryGetValue(eventId, out var listListener))
{
_processEventList.Add(eventId);
#if UNITY_EDITOR
int iEventCnt = _processEventList.Count;
#endif
var count = listListener.Count;
for (int i = 0; i < count; i++)
{
var node = listListener[i];
if (node.IsDeleted)
{
continue;
}
if (node.Callback is Action<TArg1, TArg2, TArg3> callBack)
{
callBack(arg1, arg2, arg3);
}
else
{
Log.Fatal("Invalid event data type: {0}", eventId);
}
}
#if UNITY_EDITOR
Log.Assert(iEventCnt == _processEventList.Count);
Log.Assert(eventId == _processEventList[^1]);
#endif
_processEventList.RemoveAt(_processEventList.Count - 1);
CheckDelayDelete(eventId);
}
}
/// <summary>
/// 发送事件。
/// </summary>
/// <param name="eventId">事件Id。</param>
/// <param name="arg1">事件参数1。</param>
/// <param name="arg2">事件参数2。</param>
/// <param name="arg3">事件参数3。</param>
/// <param name="arg4">事件参数4。</param>
/// <typeparam name="TArg1">事件参数类型1。</typeparam>
/// <typeparam name="TArg2">事件参数类型2。</typeparam>
/// <typeparam name="TArg3">事件参数类型3。</typeparam>
/// <typeparam name="TArg4">事件参数类型4。</typeparam>
public void SendEvent<TArg1, TArg2, TArg3, TArg4>(int eventId, TArg1 arg1, TArg2 arg2, TArg3 arg3, TArg4 arg4)
{
if (_allEventListenerMap.TryGetValue(eventId, out var listListener))
{
_processEventList.Add(eventId);
#if UNITY_EDITOR
int iEventCnt = _processEventList.Count;
#endif
var count = listListener.Count;
for (int i = 0; i < count; i++)
{
var node = listListener[i];
if (node.IsDeleted)
{
continue;
}
if (listListener[i].Callback is Action<TArg1, TArg2, TArg3, TArg4> callBack)
{
callBack(arg1, arg2, arg3, arg4);
}
else
{
Log.Fatal("Invalid event data type: {0}", eventId);
}
}
#if UNITY_EDITOR
Log.Assert(iEventCnt == _processEventList.Count);
Log.Assert(eventId == _processEventList[^1]);
#endif
_processEventList.RemoveAt(_processEventList.Count - 1);
CheckDelayDelete(eventId);
}
}
/// <summary>
/// 增加事件监听。
/// </summary>
/// <param name="eventId">事件Id。</param>
/// <param name="eventCallback">事件回调。</param>
/// <param name="owner">持有者Tag。</param>
public void AddEventListener(int eventId, Action eventCallback, object owner)
{
AddEventListenerImp(eventId, eventCallback, owner);
}
/// <summary>
/// 增加事件监听。
/// </summary>
/// <param name="eventId">事件Id。</param>
/// <param name="eventCallback">事件回调。</param>
/// <param name="owner">持有者Tag。</param>
/// <typeparam name="TArg1">事件参数类型1。</typeparam>
public void AddEventListener<TArg1>(int eventId, Action<TArg1> eventCallback, object owner)
{
AddEventListenerImp(eventId, eventCallback, owner);
}
/// <summary>
/// 增加事件监听。
/// </summary>
/// <param name="eventId">事件Id。</param>
/// <param name="eventCallback">事件回调。</param>
/// <param name="owner">持有者Tag。</param>
/// <typeparam name="TArg1">事件参数类型1。</typeparam>
/// <typeparam name="TArg2">事件参数类型2。</typeparam>
public void AddEventListener<TArg1, TArg2>(int eventId, Action<TArg1, TArg2> eventCallback, object owner)
{
AddEventListenerImp(eventId, eventCallback, owner);
}
/// <summary>
/// 增加事件监听。
/// </summary>
/// <param name="eventId">事件Id。</param>
/// <param name="eventCallback">事件回调。</param>
/// <param name="owner">持有者Tag。</param>
/// <typeparam name="TArg1">事件参数类型1。</typeparam>
/// <typeparam name="TArg2">事件参数类型2。</typeparam>
/// <typeparam name="TArg3">事件参数类型3。</typeparam>
public void AddEventListener<TArg1, TArg2, TArg3>(int eventId, Action<TArg1, TArg2, TArg3> eventCallback, object owner)
{
AddEventListenerImp(eventId, eventCallback, owner);
}
/// <summary>
/// 增加事件监听。
/// </summary>
/// <param name="eventId">事件Id。</param>
/// <param name="eventCallback">事件回调。</param>
/// <param name="owner">持有者Tag。</param>
/// <typeparam name="TArg1">事件参数类型1。</typeparam>
/// <typeparam name="TArg2">事件参数类型2。</typeparam>
/// <typeparam name="TArg3">事件参数类型3。</typeparam>
/// <typeparam name="TArg4">事件参数类型4。</typeparam>
public void AddEventListener<TArg1, TArg2, TArg3, TArg4>(int eventId, Action<TArg1, TArg2, TArg3, TArg4> eventCallback, object owner)
{
AddEventListenerImp(eventId, eventCallback, owner);
}
/// <summary>
/// 增加事件监听具体实现。
/// </summary>
/// <param name="eventId">事件Id。</param>
/// <param name="listener">事件回调。</param>
/// <param name="owner">持有者Tag。</param>
private void AddEventListenerImp(int eventId, Delegate listener, object owner)
{
if (!_allEventListenerMap.TryGetValue(eventId, out var listListener))
{
listListener = new List<EventRegInfo>();
_allEventListenerMap.Add(eventId, listListener);
}
var existNode = listListener.Find((node) => node.Callback == listener);
if (existNode != null)
{
if (existNode.IsDeleted)
{
existNode.IsDeleted = false;
Log.Warning("AddEvent hashId deleted, repeat add: {0}", eventId);
return;
}
Log.Fatal("AddEvent hashId repeated: {0}", eventId);
return;
}
listListener.Add(new EventRegInfo(listener, owner));
}
/// <summary>
/// 通过持有者Tag移除监听。
/// </summary>
/// <param name="owner">持有者Tag。</param>
public void RemoveAllListenerByOwner(object owner)
{
var itr = _allEventListenerMap.GetEnumerator();
while (itr.MoveNext())
{
var kv = itr.Current;
var list = kv.Value;
int eventId = kv.Key;
bool isProcessing = _processEventList.Contains(eventId);
bool delayDeleted = false;
for (int i = 0; i < list.Count; i++)
{
var regInfo = list[i];
if (regInfo.Owner == owner)
{
if (isProcessing)
{
regInfo.IsDeleted = true;
delayDeleted = true;
}
else
{
list[i] = list[^1];
list.RemoveAt(list.Count - 1);
i--;
}
}
}
if (delayDeleted)
{
AddDelayDelete(eventId);
}
}
itr.Dispose();
}
/// <summary>
/// 移除事件监听。
/// </summary>
/// <param name="eventId">事件Id。</param>
/// <param name="eventCallback">消息回调。</param>
public void RemoveEventListener(int eventId, Action eventCallback)
{
RemoveEventListenerImp(eventId, eventCallback);
}
/// <summary>
/// 移除事件监听。
/// </summary>
/// <param name="eventId">事件Id。</param>
/// <param name="eventCallback">消息回调。</param>
/// <typeparam name="TArg1">参数类型1。</typeparam>
public void RemoveEventListener<TArg1>(int eventId, Action<TArg1> eventCallback)
{
RemoveEventListenerImp(eventId, eventCallback);
}
/// <summary>
/// 移除事件监听。
/// </summary>
/// <param name="eventId">事件Id。</param>
/// <param name="eventCallback">消息回调。</param>
/// <typeparam name="TArg1">参数类型1。</typeparam>
/// <typeparam name="TArg2">参数类型2。</typeparam>
public void RemoveEventListener<TArg1, TArg2>(int eventId, Action<TArg1, TArg2> eventCallback)
{
RemoveEventListenerImp(eventId, eventCallback);
}
/// <summary>
/// 移除事件监听。
/// </summary>
/// <param name="eventId">事件Id。</param>
/// <param name="eventCallback">消息回调。</param>
/// <typeparam name="TArg1">参数类型1。</typeparam>
/// <typeparam name="TArg2">参数类型2。</typeparam>
/// <typeparam name="TArg3">参数类型3。</typeparam>
public void RemoveEventListener<TArg1, TArg2, TArg3>(int eventId, Action<TArg1, TArg2, TArg3> eventCallback)
{
RemoveEventListenerImp(eventId, eventCallback);
}
/// <summary>
/// 移除事件监听。
/// </summary>
/// <param name="eventId">事件Id。</param>
/// <param name="eventCallback">消息回调。</param>
/// <typeparam name="TArg1">参数类型1。</typeparam>
/// <typeparam name="TArg2">参数类型2。</typeparam>
/// <typeparam name="TArg3">参数类型3。</typeparam>
/// <typeparam name="TArg4">参数类型4。</typeparam>
public void RemoveEventListener<TArg1, TArg2, TArg3, TArg4>(int eventId, Action<TArg1, TArg2, TArg3, TArg4> eventCallback)
{
RemoveEventListenerImp(eventId, eventCallback);
}
/// <summary>
/// 删除监听,如果是正在处理的监听则标记为删除
/// </summary>
/// <param name="eventId">事件Id。</param>
/// <param name="listener">事件监听。</param>
protected void RemoveEventListenerImp(int eventId, Delegate listener)
{
if (_allEventListenerMap.TryGetValue(eventId, out var listListener))
{
bool isProcessing = _processEventList.Contains(eventId);
if (!isProcessing)
{
listListener.RemoveAll(node => node.Callback == listener);
}
else
{
int listenCnt = listListener.Count;
for (int i = 0; i < listenCnt; i++)
{
var node = listListener[i];
if (node.Callback == listener)
{
node.IsDeleted = true;
AddDelayDelete(eventId);
break;
}
}
}
}
}
/// <summary>
/// 清除回收接口。
/// </summary>
public void Clear()
{
DestroyAllEventListener();
}
}
/// <summary>
/// 事件注册信息。
/// </summary>
public class EventRegInfo
{
/// <summary>
/// 事件回调。
/// </summary>
public readonly Delegate Callback;
/// <summary>
/// 事件持有者。
/// </summary>
public readonly object Owner;
/// <summary>
/// 事件是否删除。
/// </summary>
public bool IsDeleted;
public EventRegInfo(Delegate callback, object owner)
{
this.Callback = callback;
Owner = owner;
IsDeleted = false;
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 222c2a26f3b14d42950d0e9a10b61b38
timeCreated: 1673511406

View File

@@ -25,7 +25,7 @@ namespace TEngine
var cts = new CancellationTokenSource(); var cts = new CancellationTokenSource();
cts.CancelAfterSlim(TimeSpan.FromSeconds(timeout)); cts.CancelAfterSlim(TimeSpan.FromSeconds(timeout));
UnityWebRequest unityWebRequest = UnityWebRequest.Get(url); using UnityWebRequest unityWebRequest = UnityWebRequest.Get(url);
return await SendWebRequest(unityWebRequest, cts); return await SendWebRequest(unityWebRequest, cts);
} }
@@ -41,7 +41,7 @@ namespace TEngine
var cts = new CancellationTokenSource(); var cts = new CancellationTokenSource();
cts.CancelAfterSlim(TimeSpan.FromSeconds(timeout)); cts.CancelAfterSlim(TimeSpan.FromSeconds(timeout));
UnityWebRequest unityWebRequest = UnityWebRequest.Post(url, postData); using UnityWebRequest unityWebRequest = UnityWebRequest.Post(url, postData);
return await SendWebRequest(unityWebRequest, cts); return await SendWebRequest(unityWebRequest, cts);
} }
@@ -57,7 +57,7 @@ namespace TEngine
var cts = new CancellationTokenSource(); var cts = new CancellationTokenSource();
cts.CancelAfterSlim(TimeSpan.FromSeconds(timeout)); cts.CancelAfterSlim(TimeSpan.FromSeconds(timeout));
UnityWebRequest unityWebRequest = UnityWebRequest.Post(url, formFields); using UnityWebRequest unityWebRequest = UnityWebRequest.Post(url, formFields);
return await SendWebRequest(unityWebRequest, cts); return await SendWebRequest(unityWebRequest, cts);
} }
@@ -73,7 +73,7 @@ namespace TEngine
var cts = new CancellationTokenSource(); var cts = new CancellationTokenSource();
cts.CancelAfterSlim(TimeSpan.FromSeconds(timeout)); cts.CancelAfterSlim(TimeSpan.FromSeconds(timeout));
UnityWebRequest unityWebRequest = UnityWebRequest.Post(url, formData); using UnityWebRequest unityWebRequest = UnityWebRequest.Post(url, formData);
return await SendWebRequest(unityWebRequest, cts); return await SendWebRequest(unityWebRequest, cts);
} }
@@ -91,6 +91,9 @@ namespace TEngine
if (isCanceled) if (isCanceled)
{ {
Log.Warning($"HttpPost {unityWebRequest.url} be canceled!"); Log.Warning($"HttpPost {unityWebRequest.url} be canceled!");
unityWebRequest.Dispose();
cts.Dispose();
return string.Empty;
} }
} }
catch (OperationCanceledException ex) catch (OperationCanceledException ex)
@@ -98,11 +101,16 @@ namespace TEngine
if (ex.CancellationToken == cts.Token) if (ex.CancellationToken == cts.Token)
{ {
Log.Warning("HttpPost Timeout"); Log.Warning("HttpPost Timeout");
unityWebRequest.Dispose();
cts.Dispose();
return string.Empty; return string.Empty;
} }
} }
return unityWebRequest.downloadHandler.text; string ret = unityWebRequest.downloadHandler.text;
unityWebRequest.Dispose();
cts.Dispose();
return ret;
} }
} }
} }

View File

@@ -175,10 +175,7 @@ namespace TEngine
/// <returns>音频代理辅助器。</returns> /// <returns>音频代理辅助器。</returns>
public static AudioAgent Create(string path, bool bAsync, AudioCategory audioCategory, bool bInPool = false) public static AudioAgent Create(string path, bool bAsync, AudioCategory audioCategory, bool bInPool = false)
{ {
AudioAgent audioAgent = new AudioAgent AudioAgent audioAgent = new AudioAgent();
{
_audioModuleImp = ModuleImpSystem.GetModule<AudioModuleImp>()
};
audioAgent.Init(audioCategory); audioAgent.Init(audioCategory);
audioAgent.Load(path, bAsync, bInPool); audioAgent.Load(path, bAsync, bInPool);
return audioAgent; return audioAgent;
@@ -191,6 +188,7 @@ namespace TEngine
/// <param name="index">音频代理辅助器编号。</param> /// <param name="index">音频代理辅助器编号。</param>
public void Init(AudioCategory audioCategory, int index = 0) public void Init(AudioCategory audioCategory, int index = 0)
{ {
_audioModuleImp = ModuleImpSystem.GetModule<AudioModuleImp>();
GameObject host = new GameObject(Utility.Text.Format("Audio Agent Helper - {0} - {1}", audioCategory.AudioMixerGroup.name, index)); GameObject host = new GameObject(Utility.Text.Format("Audio Agent Helper - {0} - {1}", audioCategory.AudioMixerGroup.name, index));
host.transform.SetParent(audioCategory.InstanceRoot); host.transform.SetParent(audioCategory.InstanceRoot);
host.transform.localPosition = Vector3.zero; host.transform.localPosition = Vector3.zero;

View File

@@ -38,6 +38,8 @@ namespace TEngine
[SerializeField] [SerializeField]
private DebuggerActiveWindowType m_ActiveWindow = DebuggerActiveWindowType.AlwaysOpen; private DebuggerActiveWindowType m_ActiveWindow = DebuggerActiveWindowType.AlwaysOpen;
public DebuggerActiveWindowType ActiveWindowType => m_ActiveWindow;
[SerializeField] [SerializeField]
private bool m_ShowFullWindow = false; private bool m_ShowFullWindow = false;
@@ -393,7 +395,7 @@ namespace TEngine
DrawDebuggerWindowGroup(subDebuggerWindowGroup); DrawDebuggerWindowGroup(subDebuggerWindowGroup);
} }
debuggerWindowGroup.SelectedWindow.OnDraw(); debuggerWindowGroup?.SelectedWindow?.OnDraw();
} }
private void DrawDebuggerWindowIcon(int windowId) private void DrawDebuggerWindowIcon(int windowId)

View File

@@ -11,18 +11,29 @@ namespace TEngine
{ {
private static readonly Dictionary<Type, Module> _moduleMaps = new Dictionary<Type, Module>(ModuleImpSystem.DesignModuleCount); private static readonly Dictionary<Type, Module> _moduleMaps = new Dictionary<Type, Module>(ModuleImpSystem.DesignModuleCount);
private static GameObject _gameModuleRoot;
#region #region
/// <summary> /// <summary>
/// 获取游戏基础模块。 /// 获取游戏基础模块。
/// </summary> /// </summary>
public static RootModule Base => _base ??= Get<RootModule>(); public static RootModule Base
{
get => _base ??= Get<RootModule>();
private set => _base = value;
}
private static RootModule _base; private static RootModule _base;
/// <summary> /// <summary>
/// 获取调试模块。 /// 获取调试模块。
/// </summary> /// </summary>
public static DebuggerModule Debugger => _debugger ??= Get<DebuggerModule>(); public static DebuggerModule Debugger
{
get => _debugger ??= Get<DebuggerModule>();
private set => _debugger = value;
}
private static DebuggerModule _debugger; private static DebuggerModule _debugger;
@@ -117,7 +128,31 @@ namespace TEngine
{ {
Log.Info("GameModule Active"); Log.Info("GameModule Active");
gameObject.name = $"[{nameof(GameModule)}]"; gameObject.name = $"[{nameof(GameModule)}]";
_gameModuleRoot = gameObject;
DontDestroyOnLoad(gameObject); DontDestroyOnLoad(gameObject);
} }
public static void Shutdown(ShutdownType shutdownType)
{
Log.Info("GameModule Shutdown");
if (_gameModuleRoot != null)
{
Destroy(_gameModuleRoot);
_gameModuleRoot = null;
}
_moduleMaps.Clear();
_base = null;
_debugger = null;
_fsm = null;
_procedure = null;
_objectPool = null;
_resource = null;
_audio = null;
_setting = null;
_ui = null;
_localization = null;
_scene = null;
}
} }
} }

View File

@@ -84,9 +84,10 @@ namespace TEngine
rootModule.Shutdown(); rootModule.Shutdown();
rootModule = null; rootModule = null;
} }
_modules.Clear(); _modules.Clear();
GameModule.Shutdown(shutdownType);
if (shutdownType == ShutdownType.None) if (shutdownType == ShutdownType.None)
{ {
return; return;

View File

@@ -62,7 +62,7 @@ namespace TEngine
private void OnDestroy() private void OnDestroy()
{ {
if (_operationHandle != null) if (_operationHandle is { IsValid: true })
{ {
_operationHandle.Release(); _operationHandle.Release();
_operationHandle = null; _operationHandle = null;

View File

@@ -0,0 +1,28 @@
namespace TEngine
{
/// <summary>
/// 资源管理日志实现器。
/// </summary>
internal class AssetsLogger : YooAsset.ILogger
{
public void Log(string message)
{
TEngine.Log.Info(message);
}
public void Warning(string message)
{
TEngine.Log.Warning(message);
}
public void Error(string message)
{
TEngine.Log.Error(message);
}
public void Exception(System.Exception exception)
{
TEngine.Log.Fatal(exception.Message);
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: fb010b07ce0e492dae9f04e18a1af2e2
timeCreated: 1698250627

View File

@@ -2,7 +2,6 @@
using System.Threading; using System.Threading;
using Cysharp.Threading.Tasks; using Cysharp.Threading.Tasks;
using UnityEngine; using UnityEngine;
using UnityEngine.SceneManagement;
using YooAsset; using YooAsset;
namespace TEngine namespace TEngine
@@ -102,7 +101,6 @@ namespace TEngine
internal override void Shutdown() internal override void Shutdown()
{ {
ReleaseAllHandle();
#if !UNITY_WEBGL #if !UNITY_WEBGL
YooAssets.Destroy(); YooAssets.Destroy();
#endif #endif
@@ -115,13 +113,12 @@ namespace TEngine
while (iter.MoveNext()) while (iter.MoveNext())
{ {
AssetOperationHandle handle = iter.Current; AssetOperationHandle handle = iter.Current;
if (handle != null) if (handle is { IsValid: true })
{ {
handle.Dispose(); handle.Dispose();
handle = null; handle = null;
} }
} }
iter.Dispose(); iter.Dispose();
_releaseMaps.Clear(); _releaseMaps.Clear();
@@ -129,15 +126,15 @@ namespace TEngine
while (iter.MoveNext()) while (iter.MoveNext())
{ {
AssetOperationHandle handle = iter.Current; AssetOperationHandle handle = iter.Current;
if (handle != null) if (handle is { IsValid: true })
{ {
handle.Dispose(); handle.Dispose();
handle = null; handle = null;
} }
} }
iter.Dispose(); iter.Dispose();
_operationHandlesMaps.Clear(); _operationHandlesMaps.Clear();
_arcCacheTable = new ArcCacheTable<string, AssetOperationHandle>(ARCTableCapacity, OnAddAsset, OnRemoveAsset); _arcCacheTable = new ArcCacheTable<string, AssetOperationHandle>(ARCTableCapacity, OnAddAsset, OnRemoveAsset);
} }
@@ -369,7 +366,7 @@ namespace TEngine
while (iter.MoveNext()) while (iter.MoveNext())
{ {
AssetOperationHandle handle = iter.Current; AssetOperationHandle handle = iter.Current;
if (handle != null) if (handle is { IsValid: true })
{ {
handle.Dispose(); handle.Dispose();
handle = null; handle = null;
@@ -882,30 +879,4 @@ namespace TEngine
return cancelOrFailed ? null : handle.GetSubAssetObjects<T>(); return cancelOrFailed ? null : handle.GetSubAssetObjects<T>();
} }
} }
/// <summary>
/// 资源管理日志实现器。
/// </summary>
internal class AssetsLogger : YooAsset.ILogger
{
public void Log(string message)
{
TEngine.Log.Info(message);
}
public void Warning(string message)
{
TEngine.Log.Warning(message);
}
public void Error(string message)
{
TEngine.Log.Error(message);
}
public void Exception(System.Exception exception)
{
TEngine.Log.Fatal(exception.Message);
}
}
} }

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 5fefbf9d90fc46eaaa7d12e5cd8cd219
timeCreated: 1698301646

View File

@@ -0,0 +1,81 @@
using System;
using System.Collections.Generic;
using UnityEngine;
/// <summary>
/// 组件自动绑定工具
/// </summary>
public class ComponentAutoBindTool : MonoBehaviour
{
#if UNITY_EDITOR
[Serializable]
public class BindData
{
public BindData()
{
}
public BindData(string name, Component bindCom, bool isGameObject = false)
{
Name = name;
BindCom = bindCom;
IsGameObject = isGameObject;
}
public string Name;
public Component BindCom;
public bool IsGameObject;
}
public List<BindData> BindDatas = new List<BindData>();
[SerializeField]
private string m_ClassName;
[SerializeField]
private string m_Namespace;
[SerializeField]
private string m_CodePath;
[SerializeField]
private bool m_IsWidget;
public string ClassName => m_ClassName;
public string Namespace => m_Namespace;
public string CodePath => m_CodePath;
public bool IsWidget => m_IsWidget;
public IAutoBindRuleHelper RuleHelper
{
get;
set;
}
#endif
[SerializeField]
public List<Component> bindComponents = new List<Component>();
public T GetBindComponent<T>(int index) where T : Component
{
if (index >= bindComponents.Count)
{
Debug.LogError("索引无效");
return null;
}
T bindCom = bindComponents[index] as T;
if (bindCom == null)
{
Debug.LogError("类型无效");
return null;
}
return bindCom;
}
}

View File

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

View File

@@ -0,0 +1,77 @@
#if false
using System.Collections.Generic;
using UnityEngine;
/// <summary>
/// 默认自动绑定规则辅助器
/// </summary>
public class DefaultAutoBindRuleHelper : IAutoBindRuleHelper
{
/// <summary>
/// 命名前缀与类型的映射
/// </summary>
private Dictionary<string, string> m_PrefixesDict = new Dictionary<string, string>()
{
{"Trans","Transform" },
{"OldAnim","Animation"},
{"NewAnim","Animator"},
{"Rect","RectTransform"},
{"Canvas","Canvas"},
{"Group","CanvasGroup"},
{"VGroup","VerticalLayoutGroup"},
{"HGroup","HorizontalLayoutGroup"},
{"GGroup","GridLayoutGroup"},
{"TGroup","ToggleGroup"},
{"Btn","UIButtonSuper"},
{"Img","Image"},
{"RImg","RawImage"},
{"Txt","Text"},
{"TxtM","TextMeshProUGUI"},
{"Input","TMP_InputField"},
{"Slider","Slider"},
{"Mask","Mask"},
{"Mask2D","RectMask2D"},
{"Tog","Toggle"},
{"Sbar","Scrollbar"},
{"SRect","ScrollRect"},
{"Drop","Dropdown"},
{"USpriteAni","UGUISpriteAnimation"},
{"VGridV","LoopGridView"},
{"HGridV","LoopGridView"},
{"VListV","LoopListView2"},
{"HListV","LoopListView2"},
};
public bool IsValidBind( Transform target, List<string> filedNames, List<string> componentTypeNames)
{
string[] strArray = target.name.Split('_');
if (strArray.Length == 1)
{
return false;
}
string filedName = strArray[^1];
for (int i = 0; i < strArray.Length - 1; i++)
{
string str = strArray[i];
if (m_PrefixesDict.TryGetValue(str,out var componentName))
{
filedNames.Add($"{str}_{filedName}");
componentTypeNames.Add(componentName);
}
else
{
Debug.LogError($"{target.name}的命名中{str}不存在对应的组件类型,绑定失败");
return false;
}
}
return true;
}
}
#endif

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 48a5faab9d684f14a38c5a001326eb03
timeCreated: 1698301686

View File

@@ -0,0 +1,13 @@
using System.Collections.Generic;
using UnityEngine;
/// <summary>
/// 自动绑定规则辅助器接口
/// </summary>
public interface IAutoBindRuleHelper
{
/// <summary>
/// 是否为有效绑定
/// </summary>
bool IsValidBind(Transform target,List<string> filedNames,List<string> componentTypeNames);
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 5654ec3474b94b7fa84dfdc684fe2fa9
timeCreated: 1698301670

View File

@@ -0,0 +1,31 @@
using System.Collections.Generic;
using UnityEngine;
/// <summary>
/// UI自动绑定规则辅助器
/// </summary>
public class UIAutoBindRuleHelper: IAutoBindRuleHelper
{
public bool IsValidBind( Transform targetTransform, List<string> filedNames, List<string> componentTypeNames)
{
string uiElementName = targetTransform.name;
string[] strArray = targetTransform.name.Split('_');
if (strArray.Length == 1)
{
return false;
}
string filedName = strArray[^1];
var rule = SettingsUtils.GetScriptGenerateRule().Find(t => uiElementName.StartsWith(t.uiElementRegex));
if (rule != null)
{
filedNames.Add($"{filedName}");
componentTypeNames.Add(rule.componentName);
return true;
}
Debug.LogWarning($"{targetTransform.name}的命名中{uiElementName}不存在对应的组件类型,绑定失败");
return false;
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: a4256bde2e254a7f91fc70ea1f7420d8
timeCreated: 1698306650

View File

@@ -1,15 +1,16 @@
using UnityEngine; using System;
using UnityEngine;
namespace TEngine namespace TEngine
{ {
public class ErrorLogger public class ErrorLogger:IDisposable
{ {
public ErrorLogger() public ErrorLogger()
{ {
Application.logMessageReceived += LogHandler; Application.logMessageReceived += LogHandler;
} }
~ErrorLogger() public void Dispose()
{ {
Application.logMessageReceived -= LogHandler; Application.logMessageReceived -= LogHandler;
} }

View File

@@ -513,54 +513,5 @@ namespace TEngine
} }
#endregion #endregion
#region UIElement
/// <summary>
/// UI元素节点。
/// </summary>
protected UIElement UIElement;
/// <summary>
/// 检测UI元素节点。
/// </summary>
protected virtual void CheckUIElement()
{
if (rectTransform != null)
{
UIElement = rectTransform.GetComponent<UIElement>();
}
}
/// <summary>
/// 获取子节点。
/// </summary>
/// <param name="childName">子节点名称。</param>
/// <returns>子节点位置实例。</returns>
protected Transform FChild(string childName)
{
if (UIElement != null)
{
var child = UIElement.Get(childName);
if (child != null)
{
return child;
}
}
return FindChild(childName);
}
/// <summary>
/// 获取子节点脚本。
/// </summary>
/// <typeparam name="T">子节点类型。</typeparam>
/// <param name="childName">子节点名称。</param>
/// <returns>子节点脚本实例。</returns>
protected T FChild<T>(string childName) where T : Component
{
var child = FChild(childName);
return child == null ? null : child.GetComponent<T>();
}
#endregion
} }
} }

View File

@@ -1,50 +0,0 @@
using UnityEngine;
namespace TEngine
{
/// <summary>
/// UI元素节点。
/// <remarks>通过mono序列化来绑定ui节点的元素换取查找与ui的稳定性。</remarks>
/// </summary>
public class UIElement : MonoBehaviour
{
/// <summary>
/// UI元素。
/// </summary>
[SerializeField] protected SerializableDictionary<string, Transform> elements = new SerializableDictionary<string, Transform>();
/// <summary>
/// UI元素。
/// </summary>
public SerializableDictionary<string, Transform> Elements => elements;
/// <summary>
/// 获取UI元素。
/// </summary>
/// <param name="uiID">ui元素标识。</param>
/// <returns>UI元素。</returns>
public Transform Get(string uiID)
{
elements.TryGetValue(uiID, out var uiTransform);
return uiTransform;
}
/// <summary>
/// 获取UI元素。
/// </summary>
/// <typeparam name="T">ui元素类型。</typeparam>
/// <param name="uiID">ui元素标识。</param>
/// <returns>ui元素标识。</returns>
public T Get<T>(string uiID) where T : Component
{
var uiTransform = Get(uiID);
return uiTransform == null ? null : uiTransform.GetComponent<T>();
}
public void OnDestroy()
{
elements.Clear();
elements = null;
}
}
}

View File

@@ -1,3 +0,0 @@
fileFormatVersion: 2
guid: bcd11033283847ee8f7c71eedd9a4771
timeCreated: 1696656961

View File

@@ -68,6 +68,25 @@ namespace TEngine
m_InstanceRoot.gameObject.layer = LayerMask.NameToLayer("UI"); m_InstanceRoot.gameObject.layer = LayerMask.NameToLayer("UI");
UIRootStatic = m_InstanceRoot; UIRootStatic = m_InstanceRoot;
switch (GameModule.Debugger.ActiveWindowType)
{
case DebuggerActiveWindowType.AlwaysOpen:
m_enableErrorLog = true;
break;
case DebuggerActiveWindowType.OnlyOpenWhenDevelopment:
m_enableErrorLog = Debug.isDebugBuild;
break;
case DebuggerActiveWindowType.OnlyOpenInEditor:
m_enableErrorLog = Application.isEditor;
break;
default:
m_enableErrorLog = false;
break;
}
if (m_enableErrorLog) if (m_enableErrorLog)
{ {
_errorLogger = new ErrorLogger(); _errorLogger = new ErrorLogger();
@@ -76,7 +95,16 @@ namespace TEngine
private void OnDestroy() private void OnDestroy()
{ {
if (_errorLogger != null)
{
_errorLogger.Dispose();
_errorLogger = null;
}
CloseAll(); CloseAll();
if (m_InstanceRoot != null && m_InstanceRoot.parent != null)
{
Destroy(m_InstanceRoot.parent.gameObject);
}
} }
#region #region