You've already forked taptap2024_GJ_chidouren
init
This commit is contained in:
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a0508e272c3d9404eb32c8cca69ee2fb
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,175 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
|
||||
namespace IcecreamView.Editor
|
||||
{
|
||||
[CustomEditor(typeof(IcecreamView.IC_AbstractView), true), CanEditMultipleObjects]
|
||||
public class GameViewAbstractEditor : UnityEditor.Editor
|
||||
{
|
||||
public static Texture2D GetTexture2D(Color32 color32)
|
||||
{
|
||||
Texture2D texturesss = new Texture2D(4, 4);
|
||||
Color32[] colors = texturesss.GetPixels32();
|
||||
for (int i = 0; i < colors.Length; i++)
|
||||
{
|
||||
colors[i] = color32;
|
||||
}
|
||||
|
||||
texturesss.SetPixels32(colors);
|
||||
texturesss.Apply();
|
||||
return texturesss;
|
||||
}
|
||||
|
||||
public override void OnInspectorGUI()
|
||||
{
|
||||
GUIStyle gUIStyle = new GUIStyle();
|
||||
|
||||
gUIStyle.fontSize = 20;
|
||||
gUIStyle.normal.textColor = Color.black;
|
||||
gUIStyle.normal.background = GameViewAbstractEditor.GetTexture2D(new Color32(0, 205, 255, 100));
|
||||
gUIStyle.alignment = TextAnchor.MiddleCenter;
|
||||
gUIStyle.margin = new RectOffset(0, 0, 10, 0);
|
||||
|
||||
GUILayout.Space(10);
|
||||
GUILayout.Box(" Game View ", gUIStyle);
|
||||
|
||||
gUIStyle = new GUIStyle();
|
||||
gUIStyle.fontSize = 16;
|
||||
gUIStyle.normal.textColor = Color.white;
|
||||
gUIStyle.normal.background = GameViewAbstractEditor.GetTexture2D(new Color32(77, 77, 77, 255));
|
||||
gUIStyle.alignment = TextAnchor.MiddleCenter;
|
||||
GUILayout.Box(this.target.GetType().Name, gUIStyle);
|
||||
|
||||
EditorGUILayout.HelpBox("游戏界面基础组件", MessageType.None);
|
||||
GUILayout.Space(10);
|
||||
gUIStyle = null;
|
||||
base.DrawDefaultInspector();
|
||||
this.serializedObject.ApplyModifiedProperties();
|
||||
}
|
||||
}
|
||||
|
||||
[CustomEditor(typeof(IcecreamView.IC_ModuleConnector), true), CanEditMultipleObjects]
|
||||
public class GameViewModuleConnectorEditor : UnityEditor.Editor
|
||||
{
|
||||
private bool _isCreate;
|
||||
private SerializedProperty defaultStory;
|
||||
private SerializedProperty hasFocus;
|
||||
private SerializedProperty hasAutoCreate;
|
||||
|
||||
private void OnEnable()
|
||||
{
|
||||
this.RefreshCreateType();
|
||||
}
|
||||
|
||||
private void RefreshCreateType()
|
||||
{
|
||||
if (!EditorApplication.isPlaying)
|
||||
{
|
||||
var path = $"Assets/{IceCreamCodeUtils.GlobalInstance.FilePath ?? "Scripts/View"}";
|
||||
var fileName = $"{serializedObject.targetObject.name.Replace(" ", "")}.cs";
|
||||
this._isCreate = !File.Exists(path + "/" + fileName);
|
||||
}
|
||||
|
||||
this.defaultStory = this.serializedObject.FindProperty("DefaultStory");
|
||||
this.hasFocus = this.serializedObject.FindProperty("hasFocusView");
|
||||
this.hasAutoCreate = this.serializedObject.FindProperty("HasAutoCreate");
|
||||
}
|
||||
|
||||
public override void OnInspectorGUI()
|
||||
{
|
||||
GUIStyle gUIStyle = new GUIStyle();
|
||||
|
||||
gUIStyle.fontSize = 20;
|
||||
gUIStyle.normal.textColor = Color.black;
|
||||
gUIStyle.normal.background = GameViewAbstractEditor.GetTexture2D(new Color32(255, 0, 99, 100));
|
||||
gUIStyle.alignment = TextAnchor.MiddleCenter;
|
||||
gUIStyle.margin = new RectOffset(0, 0, 10, 0);
|
||||
|
||||
|
||||
GUILayout.Space(10);
|
||||
GUILayout.Box(" Game View Connect ", gUIStyle);
|
||||
EditorGUILayout.HelpBox("模块管理器,用于关联并激活该对象上的所有< Game View Module >", MessageType.None);
|
||||
GUILayout.Space(10);
|
||||
if (this._isCreate && hasAutoCreate != null)
|
||||
{
|
||||
hasAutoCreate.boolValue = GUILayout.Toggle(hasAutoCreate.boolValue, "自动构建检查", "Button");
|
||||
|
||||
if (hasAutoCreate.boolValue)
|
||||
{
|
||||
if (GUILayout.Button("自动构建"))
|
||||
{
|
||||
IceCreamCodeUtils.CreateCode(this.serializedObject);
|
||||
this._isCreate = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
GUILayout.Space(10);
|
||||
|
||||
EditorGUILayout.BeginHorizontal();
|
||||
EditorGUILayout.PropertyField(defaultStory, new GUIContent("UI默认层级"));
|
||||
EditorGUILayout.PropertyField(hasFocus, new GUIContent("是否拥有焦点"));
|
||||
EditorGUILayout.EndHorizontal();
|
||||
|
||||
gUIStyle = null;
|
||||
this.serializedObject.ApplyModifiedProperties();
|
||||
}
|
||||
}
|
||||
|
||||
[CustomEditor(typeof(IcecreamView.IC_AbstractModule), true), CanEditMultipleObjects]
|
||||
public class GameViewAbstractModuleEditor : UnityEditor.Editor
|
||||
{
|
||||
public override void OnInspectorGUI()
|
||||
{
|
||||
GUIStyle gUIStyle = new GUIStyle();
|
||||
|
||||
gUIStyle.fontSize = 20;
|
||||
gUIStyle.normal.textColor = Color.black;
|
||||
gUIStyle.normal.background = GameViewAbstractEditor.GetTexture2D(new Color32(147, 255, 0, 100));
|
||||
gUIStyle.alignment = TextAnchor.MiddleCenter;
|
||||
gUIStyle.margin = new RectOffset(0, 0, 10, 0);
|
||||
|
||||
|
||||
GUILayout.Space(10);
|
||||
GUILayout.Box(" Game View Module ", gUIStyle);
|
||||
|
||||
gUIStyle = new GUIStyle();
|
||||
gUIStyle.fontSize = 16;
|
||||
gUIStyle.normal.textColor = Color.white;
|
||||
gUIStyle.normal.background = GameViewAbstractEditor.GetTexture2D(new Color32(77, 77, 77, 255));
|
||||
gUIStyle.alignment = TextAnchor.MiddleCenter;
|
||||
GUILayout.Box(this.target.GetType().Name, gUIStyle);
|
||||
|
||||
EditorGUILayout.HelpBox("界面功能模块组件,允许多模块自由组合", MessageType.None);
|
||||
GUILayout.Space(10);
|
||||
gUIStyle = null;
|
||||
base.DrawDefaultInspector();
|
||||
this.serializedObject.ApplyModifiedProperties();
|
||||
}
|
||||
}
|
||||
|
||||
// public static class IceViewConfigTool{
|
||||
// [MenuItem("Assets/Create/IceCreamView/AutoView Config", false, 88)]
|
||||
// public static void CreatConfig() {
|
||||
// Object[] arr = Selection.GetFiltered(typeof(IC_AbstractView), SelectionMode.TopLevel);
|
||||
// var GameConfig = ScriptableObject.CreateInstance<IC_ViewConfig>();
|
||||
// List<IC_ViewInfo> gameInfos = new List<IC_ViewInfo>();
|
||||
// foreach (var item in arr)
|
||||
// {
|
||||
// var a = new IC_ViewInfo();
|
||||
// a.View = (IC_AbstractView)item;
|
||||
// a.Table = item.name;
|
||||
// gameInfos.Add(a);
|
||||
// }
|
||||
// GameConfig.GameViewList = gameInfos;
|
||||
// GameConfig.ConfigName = "defaultConfig";
|
||||
// if (arr.Length > 0) {
|
||||
// var filePath = AssetDatabase.GetAssetPath(arr[0]).Replace(arr[0].name + ".prefab", "viewConfig.asset");
|
||||
// AssetDatabase.CreateAsset(GameConfig, filePath);
|
||||
// Debug.LogFormat("Create Config : {0}" , filePath);
|
||||
// }
|
||||
// AssetDatabase.Refresh();
|
||||
// }
|
||||
// }
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9c4773dc9ceb0a4499a573fdb0b3cdcd
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,94 @@
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
using System.Text;
|
||||
using System.IO;
|
||||
|
||||
namespace IcecreamView.Editor
|
||||
{
|
||||
public static class IceCreamCodeTemplateEditor
|
||||
{
|
||||
private static Texture2D scriptIcon = (EditorGUIUtility.IconContent("cs Script Icon").image as Texture2D);
|
||||
|
||||
[MenuItem("Assets/Create/IceCreamView/IceCream ViewModule C# Script", false, 89)]
|
||||
private static void CreateViewModuleCode()
|
||||
{
|
||||
string[] guids = AssetDatabase.FindAssets("ViewAbstractModuleTemplate.cs");
|
||||
if (guids.Length == 0)
|
||||
{
|
||||
Debug.LogError("ViewAbstractModuleTemplate.cs.txt not found in asset database");
|
||||
return;
|
||||
}
|
||||
|
||||
string path = AssetDatabase.GUIDToAssetPath(guids[0]);
|
||||
CreateFromTemplate("NewViewModule.cs", path);
|
||||
}
|
||||
|
||||
[MenuItem("Assets/Create/IceCreamView/IceCream View C# Script", false, 89)]
|
||||
private static void CreateViewCode()
|
||||
{
|
||||
string[] guids = AssetDatabase.FindAssets("ViewAbstractTemplate.cs");
|
||||
if (guids.Length == 0)
|
||||
{
|
||||
Debug.LogError("ViewAbstractTemplate.cs.txt not found in asset database");
|
||||
return;
|
||||
}
|
||||
|
||||
string path = AssetDatabase.GUIDToAssetPath(guids[0]);
|
||||
CreateFromTemplate("NewView.cs", path);
|
||||
}
|
||||
|
||||
public static void CreateFromTemplate(string initialName, string templatePath)
|
||||
{
|
||||
ProjectWindowUtil.StartNameEditingIfProjectWindowExists(
|
||||
0,
|
||||
ScriptableObject.CreateInstance<DoCreateCodeFile>(),
|
||||
initialName,
|
||||
scriptIcon,
|
||||
templatePath
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
|
||||
public class DoCreateCodeFile : UnityEditor.ProjectWindowCallback.EndNameEditAction
|
||||
{
|
||||
public override void Action(int instanceId, string pathName, string resourceFile)
|
||||
{
|
||||
Object o = CreateScript(pathName, resourceFile);
|
||||
ProjectWindowUtil.ShowCreatedAsset(o);
|
||||
}
|
||||
}
|
||||
|
||||
public static UnityEngine.Object CreateScript(string pathName, string templatePath)
|
||||
{
|
||||
string className = Path.GetFileNameWithoutExtension(pathName).Replace(" ", string.Empty);
|
||||
string templateText = string.Empty;
|
||||
|
||||
UTF8Encoding encoding = new UTF8Encoding(true, false);
|
||||
|
||||
if (File.Exists(templatePath))
|
||||
{
|
||||
StreamReader reader = new StreamReader(templatePath);
|
||||
templateText = reader.ReadToEnd();
|
||||
reader.Close();
|
||||
|
||||
templateText = templateText.Replace("#SCRIPTNAME#", className);
|
||||
templateText = templateText.Replace("#NOTRIM#", string.Empty);
|
||||
|
||||
StreamWriter writer = new StreamWriter(Path.GetFullPath(pathName), false, encoding);
|
||||
writer.Write(templateText);
|
||||
writer.Close();
|
||||
|
||||
AssetDatabase.ImportAsset(pathName);
|
||||
return AssetDatabase.LoadAssetAtPath(pathName, typeof(Object));
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogError(string.Format("The template file was not found: {0}", templatePath));
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b40b12afaefaa874c8ddfe4e223822f2
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,309 @@
|
||||
using System;
|
||||
using System.CodeDom;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
namespace IcecreamView.Editor
|
||||
{
|
||||
public static class IceCreamCodeUtils
|
||||
{
|
||||
|
||||
public const string Templete = @"using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using IcecreamView;
|
||||
|
||||
#NamespaceStart
|
||||
|
||||
public class #ScriptName : #Abstract
|
||||
{
|
||||
public override void OnOpenView(IC_ViewData parameters)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public override void OnCloseView()
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
#NamespaceEnd
|
||||
";
|
||||
|
||||
public const string UIPanelTemplete = @"
|
||||
using IcecreamView;
|
||||
|
||||
#NamespaceStart
|
||||
public class UIPanel
|
||||
{
|
||||
//Code start
|
||||
//Code end
|
||||
}
|
||||
#NamespaceEnd
|
||||
";
|
||||
|
||||
public static void CreateCode(SerializedObject target)
|
||||
{
|
||||
if (target.targetObject == null || string.IsNullOrEmpty(target.targetObject.name))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// CodeCompileUnit unit = new CodeCompileUnit();
|
||||
// //设置命名空间(这个是指要生成的类的空间)
|
||||
// CodeNamespace myNamespace = new CodeNamespace("Joh.Test");
|
||||
// //导入必要的命名空间引用
|
||||
// myNamespace.Imports.Add(new CodeNamespaceImport("System"));
|
||||
// myNamespace.Imports.Add(new CodeNamespaceImport("UnityEngine"));
|
||||
// //Code:代码体
|
||||
// CodeTypeDeclaration myClass = new CodeTypeDeclaration(className);
|
||||
|
||||
string className = string.IsNullOrEmpty(GlobalInstance.NameSpacePath) ? target.targetObject.name : GlobalInstance.NameSpacePath + "." + target.targetObject.name;
|
||||
string objPath = GetGameObjectPath(((IC_ModuleConnector) target.targetObject).transform);
|
||||
WriteFile("Temp", "ICE_ACTION.tmp", StringToArrayByteUtf8(className + "#" + objPath));
|
||||
|
||||
string path = $"Assets/{GlobalInstance.FilePath ?? "Scripts/View"}";
|
||||
string fileName = $"{target.targetObject.name.Replace(" ", "")}.cs";
|
||||
if (!File.Exists(path + "/" + fileName))
|
||||
{
|
||||
//创建代码
|
||||
string fileContent = Templete;
|
||||
if (string.IsNullOrEmpty(GlobalInstance.NameSpacePath) == false)
|
||||
{
|
||||
fileContent = fileContent.Replace("#NamespaceStart", $"namespace {GlobalInstance.NameSpacePath}" + "{");
|
||||
fileContent = fileContent.Replace("#NamespaceEnd", "}");
|
||||
}
|
||||
else
|
||||
{
|
||||
fileContent = fileContent.Replace("#NamespaceStart", "");
|
||||
fileContent = fileContent.Replace("#NamespaceEnd", "");
|
||||
}
|
||||
|
||||
fileContent = fileContent.Replace("#Abstract", GlobalInstance.AbstractClass ?? "IC_AbstractModule");
|
||||
fileContent = fileContent.Replace("#ScriptName", target.targetObject.name);
|
||||
WriteFile(path, fileName, StringToArrayByteUtf8(fileContent));
|
||||
Debug.Log("构建UI代码完成:" + path + "/" + fileName);
|
||||
UpdateUIPanel(target.targetObject.name.Replace(" ", ""));
|
||||
AssetDatabase.Refresh();
|
||||
}
|
||||
else
|
||||
{
|
||||
// Debug.Log("已存在相同文件名:" + path + "/" + fileName);
|
||||
BindComponent();
|
||||
}
|
||||
}
|
||||
//
|
||||
// [MenuItem("Icecream/UpdatePanel")]
|
||||
// public static void MainTest()
|
||||
// {
|
||||
// UpdateUIPanel("Test");
|
||||
// }
|
||||
|
||||
/// <summary>
|
||||
/// 更新UIPanel
|
||||
/// </summary>
|
||||
public static void UpdateUIPanel(String name)
|
||||
{
|
||||
var path = GlobalInstance.FilePath;
|
||||
var fileName = "UIPanel.cs";
|
||||
if (!File.Exists("Assets/" + path + "/" + fileName))
|
||||
{
|
||||
CreateUIPanel();
|
||||
}
|
||||
var fileContent = ReadFile("Assets/" + path, fileName);
|
||||
// Debug.Log(fileContent);
|
||||
var startIndex = fileContent.IndexOf("//Code start", StringComparison.Ordinal) + 13;
|
||||
var endIndex = fileContent.IndexOf("//Code end", StringComparison.Ordinal) - 10;
|
||||
var panelContent = fileContent.Substring(startIndex , endIndex - startIndex);
|
||||
// Debug.Log(panelContent);
|
||||
var panelList = panelContent.Split(';');
|
||||
List<String> panelNames = new List<string>();
|
||||
var temp = "public const string ";
|
||||
bool isCreate = true;
|
||||
foreach (var panel in panelList)
|
||||
{
|
||||
var start = panel.IndexOf(temp, StringComparison.Ordinal);
|
||||
if (start > 0)
|
||||
{
|
||||
var p2 = panel.Substring(start + temp.Length);
|
||||
var panelName = p2.Substring(0, p2.IndexOf(" ", StringComparison.Ordinal));
|
||||
panelNames.Add(panelName);
|
||||
if (panelName.Equals(name , StringComparison.Ordinal))
|
||||
{
|
||||
isCreate = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (isCreate)
|
||||
{
|
||||
//添加新Panel
|
||||
fileContent = fileContent.Insert(endIndex, $"\r\n {temp}{name} \t\t\t=\"{name}\";");
|
||||
Debug.Log("构建UIPanel完成: " + name);
|
||||
}
|
||||
// Debug.Log(fileContent);
|
||||
WriteFile("Assets/"+path, fileName, StringToArrayByteUtf8(fileContent));
|
||||
}
|
||||
|
||||
public static void CreateUIPanel()
|
||||
{
|
||||
var path = "Assets/" + GlobalInstance.FilePath;
|
||||
var fileName = "UIPanel.cs";
|
||||
// if (File.Exists(path + "/" + fileName))
|
||||
// {
|
||||
// File.Delete(path + "/" + fileName);
|
||||
// }
|
||||
var fileContent = UIPanelTemplete;
|
||||
if (string.IsNullOrEmpty(GlobalInstance.NameSpacePath) == false)
|
||||
{
|
||||
fileContent = fileContent.Replace("#NamespaceStart", $"namespace {GlobalInstance.NameSpacePath}" + "{");
|
||||
fileContent = fileContent.Replace("#NamespaceEnd", "}");
|
||||
}
|
||||
else
|
||||
{
|
||||
fileContent = fileContent.Replace("#NamespaceStart", "");
|
||||
fileContent = fileContent.Replace("#NamespaceEnd", "");
|
||||
}
|
||||
WriteFile(path, fileName, StringToArrayByteUtf8(fileContent));
|
||||
}
|
||||
|
||||
[UnityEditor.Callbacks.DidReloadScripts]
|
||||
public static void BindComponent()
|
||||
{
|
||||
if (File.Exists("Temp/ICE_ACTION.tmp") == false)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
string fileContent = ReadFile("Temp", "ICE_ACTION.tmp");
|
||||
File.Delete("Temp/ICE_ACTION.tmp");
|
||||
string className = fileContent.Substring(0, fileContent.IndexOf("#", StringComparison.Ordinal));
|
||||
string objPath = fileContent.Substring(fileContent.IndexOf("#", StringComparison.Ordinal) + 1);
|
||||
var assembly = Assembly.Load(GlobalInstance.AssemblyName);
|
||||
if (assembly == null)
|
||||
{
|
||||
Debug.LogError("加载失败:" + GlobalInstance.AssemblyName);
|
||||
return;
|
||||
}
|
||||
|
||||
Type t = assembly.GetType(className);
|
||||
var obj = GameObject.Find(objPath);
|
||||
if (t != null)
|
||||
{
|
||||
if (!obj.GetComponent(t))
|
||||
{
|
||||
obj.gameObject.AddComponent(t);
|
||||
}
|
||||
|
||||
var prefabPath = "Assets/" + GlobalInstance.PrefabsPath + "/" + obj.name + ".prefab";
|
||||
if (Directory.Exists("Assets/" + GlobalInstance.PrefabsPath) == false)
|
||||
{
|
||||
Directory.CreateDirectory("Assets/" + GlobalInstance.PrefabsPath);
|
||||
}
|
||||
|
||||
if (File.Exists(prefabPath))
|
||||
{
|
||||
//保存修改到预制体
|
||||
PrefabUtility.ApplyPrefabInstance(obj, InteractionMode.AutomatedAction);
|
||||
}
|
||||
else
|
||||
{
|
||||
//创建预制体
|
||||
PrefabUtility.SaveAsPrefabAssetAndConnect(obj, prefabPath, InteractionMode.AutomatedAction);
|
||||
}
|
||||
|
||||
Debug.Log("构建UI预制体完成:" + prefabPath);
|
||||
AssetDatabase.Refresh();
|
||||
}
|
||||
}
|
||||
|
||||
private static string GetGameObjectPath(Transform obj)
|
||||
{
|
||||
Transform selectChild = obj;
|
||||
string result = selectChild.name;
|
||||
if (selectChild != null)
|
||||
{
|
||||
while (selectChild.parent != null)
|
||||
{
|
||||
selectChild = selectChild.parent;
|
||||
result = string.Format("{0}/{1}", selectChild.name, result);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
// Debug.Log(string.Format("The gameobject:{0}'s path has been copied to the clipboard!", obj.name));
|
||||
}
|
||||
|
||||
|
||||
private static IC_GlobalSetting _globalInstance;
|
||||
|
||||
public static IC_GlobalSetting GlobalInstance
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_globalInstance == null)
|
||||
{
|
||||
#if UNITY_EDITOR
|
||||
_globalInstance = AssetDatabase.LoadAssetAtPath<IC_GlobalSetting>("Assets/IceCreamGlobalSettings.asset");
|
||||
if (_globalInstance == null)
|
||||
{
|
||||
_globalInstance = ScriptableObject.CreateInstance<IC_GlobalSetting>();
|
||||
// 自定义资源保存路径
|
||||
string path = "Assets/";
|
||||
//如果项目总不包含该路径,创建一个
|
||||
if (!Directory.Exists(path))
|
||||
{
|
||||
Directory.CreateDirectory(path);
|
||||
}
|
||||
|
||||
AssetDatabase.CreateAsset(_globalInstance, path + "/IceCreamGlobalSettings.asset");
|
||||
AssetDatabase.Refresh();
|
||||
_globalInstance = AssetDatabase.LoadAssetAtPath<IC_GlobalSetting>("Assets/IceCreamGlobalSettings.asset");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
return _globalInstance;
|
||||
}
|
||||
}
|
||||
|
||||
public static void WriteFile(string path, string fileName, byte[] content)
|
||||
{
|
||||
CreateDirectory(path);
|
||||
var fullName = path + "/" + fileName;
|
||||
FileStream fs = new FileStream(fullName, FileMode.Create, FileAccess.Write, FileShare.None, 4096, FileOptions.None);
|
||||
fs.Write(content, 0, content.Length);
|
||||
fs.Close();
|
||||
}
|
||||
|
||||
public static void CreateDirectory(string path)
|
||||
{
|
||||
if (!(Directory.Exists(path) || File.Exists(path)))
|
||||
{
|
||||
Directory.CreateDirectory(path);
|
||||
}
|
||||
}
|
||||
|
||||
public static string ReadFile(string path, string fileName)
|
||||
{
|
||||
var fullName = path + "/" + fileName;
|
||||
if (Directory.Exists(path) || File.Exists(path))
|
||||
{
|
||||
FileStream fs = new FileStream(fullName, FileMode.Open, FileAccess.Read, FileShare.None, 4096, FileOptions.None);
|
||||
byte[] bytes = new byte[fs.Length];
|
||||
fs.Read(bytes, 0, bytes.Length);
|
||||
fs.Close();
|
||||
return ArrayByteUtf8ToString(bytes);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public static byte[] StringToArrayByteUtf8(string value) { return Encoding.UTF8.GetBytes(value); }
|
||||
public static string ArrayByteUtf8ToString(byte[] bytes) { return Encoding.UTF8.GetString(bytes); }
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2f0314c9fd814f96be2fccf7d0394189
|
||||
timeCreated: 1588241337
|
||||
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"name": "IcecreamView.Editor",
|
||||
"references": [
|
||||
"IcecreamView"
|
||||
],
|
||||
"optionalUnityReferences": [],
|
||||
"includePlatforms": [
|
||||
"Editor"
|
||||
],
|
||||
"excludePlatforms": [],
|
||||
"allowUnsafeCode": false,
|
||||
"overrideReferences": false,
|
||||
"precompiledReferences": [],
|
||||
"autoReferenced": true,
|
||||
"defineConstraints": []
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4eee1f27bc1848f41ac762647e3912f6
|
||||
AssemblyDefinitionImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 052ea4d2fafb5aa4c823e3d039f49584
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,23 @@
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using IcecreamView;
|
||||
|
||||
public class #SCRIPTNAME# : IC_AbstractModule
|
||||
{
|
||||
public override void OnInitView()
|
||||
{
|
||||
}
|
||||
|
||||
public override void OnOpenView(Dictionary<string,IC_ViewData> parameters)
|
||||
{
|
||||
}
|
||||
|
||||
public override void OnCloseView()
|
||||
{
|
||||
}
|
||||
|
||||
public override void OnDestroyView()
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 240f6fdcb40695640889bf682044b199
|
||||
TextScriptImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,23 @@
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using IcecreamView;
|
||||
|
||||
public class #SCRIPTNAME# : IC_AbstractView
|
||||
{
|
||||
public override void OnInitView()
|
||||
{
|
||||
}
|
||||
|
||||
public override void OnOpenView(Dictionary<string,IC_ViewData> parameters)
|
||||
{
|
||||
}
|
||||
|
||||
public override void OnCloseView()
|
||||
{
|
||||
}
|
||||
|
||||
public override void OnDestroyView()
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9395976db8255cb41880384900ea4460
|
||||
TextScriptImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f06a3c4cf0626b44d92e09b68c9cc508
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,400 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using IcecreamView;
|
||||
using IcecreamView.Editor;
|
||||
using UnityEditor;
|
||||
using UnityEditor.SceneManagement;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UIElements;
|
||||
using Object = System.Object;
|
||||
|
||||
namespace IcecreamView
|
||||
{
|
||||
public class IceCreamUIBox : EditorWindow
|
||||
{
|
||||
private Label _viewTitle;
|
||||
private Label _viewDesc;
|
||||
|
||||
private VisualElement _customUIInfo;
|
||||
private VisualElement _customUIWork;
|
||||
private VisualElement _createInfo;
|
||||
private VisualElement _createWork;
|
||||
|
||||
private Label _customUITitle;
|
||||
private Label _customUIDesc;
|
||||
private Button _createBtn;
|
||||
|
||||
private IC_ModuleConnector connector;
|
||||
|
||||
private CanvasNode _baseCanvasNode;
|
||||
|
||||
//---------------------------create work------------------------------------
|
||||
private Button _loadUISceneBtn;
|
||||
private Label _createSceneInfoLabel;
|
||||
private Label _createSceneInfoDesc;
|
||||
private ListView _createPanelListView;
|
||||
private TextField _createPanelName;
|
||||
private SliderInt _createPanelLayer;
|
||||
private Toggle _createPanelToggle;
|
||||
private Button _createPanelCreateBtn;
|
||||
|
||||
// private Label
|
||||
|
||||
//---------------------------create work------------------------------------
|
||||
|
||||
private Transform _onSelectionTransform;
|
||||
|
||||
[MenuItem("IceCream/IceCream UI Box")]
|
||||
public static void ShowBoxTool()
|
||||
{
|
||||
IceCreamUIBox wnd = GetWindow<IceCreamUIBox>();
|
||||
wnd.titleContent = new GUIContent("IceCream UI Box");
|
||||
}
|
||||
|
||||
|
||||
public void CreateGUI()
|
||||
{
|
||||
// Debug.Log("创建 IceCream UI Box");
|
||||
// return;
|
||||
UnityEditor.Selection.selectionChanged += OnSelectionChangeScene;
|
||||
VisualElement root = rootVisualElement;
|
||||
|
||||
var fromScriptableObject = MonoScript.FromScriptableObject(this);
|
||||
var path = AssetDatabase.GetAssetPath(fromScriptableObject);
|
||||
|
||||
//将指定的path改为同路径下后缀为.uxml的路径
|
||||
path = path.Replace(".cs", ".uxml");
|
||||
var window = AssetDatabase.LoadAssetAtPath<VisualTreeAsset>(path);
|
||||
if (window == null)
|
||||
{
|
||||
Debug.LogError("无法加载uxml文件 : " + path + " 请检查插件是否损坏!");
|
||||
return;
|
||||
}
|
||||
|
||||
VisualElement container = window.Instantiate();
|
||||
|
||||
|
||||
_customUIInfo = container.Q<VisualElement>("BoxViewInfo");
|
||||
_customUIWork = container.Q<VisualElement>("BoxViewCustom");
|
||||
_createInfo = container.Q<VisualElement>("BoxPanelInfo");
|
||||
_createWork = container.Q<VisualElement>("BoxPanelCreate");
|
||||
|
||||
_viewTitle = _customUIInfo.Q<Label>("ViewTitle");
|
||||
_viewDesc = _customUIInfo.Q<Label>("Desc");
|
||||
_createBtn = _customUIWork.Q<Button>("CreateBtn");
|
||||
_customUITitle = _customUIWork.Q<Label>("CustomUITitle");
|
||||
_customUIDesc = _customUIWork.Q<Label>("CustomUIDesc");
|
||||
var uxmlButton = _customUIInfo.Q<Button>("UpdateViewBtn");
|
||||
|
||||
|
||||
_loadUISceneBtn = _createInfo.Q<Button>("LoadSceneBtn");
|
||||
_createSceneInfoLabel = _createInfo.Q<Label>("ViewTitle");
|
||||
_createSceneInfoDesc = _createInfo.Q<Label>("Desc");
|
||||
_createPanelName = _createWork.Q<TextField>("PanelName");
|
||||
_createPanelLayer = _createWork.Q<SliderInt>("PanelLayer");
|
||||
_createPanelToggle = _createWork.Q<Toggle>("FocusToggle");
|
||||
_createPanelCreateBtn = _createWork.Q<Button>("CreateBtn");
|
||||
_createPanelListView = _createWork.Q<ListView>("CustomUiListView");
|
||||
|
||||
uxmlButton.RegisterCallback<MouseUpEvent>(OnClick_UpdateViewInfo);
|
||||
_createBtn.RegisterCallback<MouseUpEvent>(OnClick_Create);
|
||||
_loadUISceneBtn.RegisterCallback<MouseUpEvent>(OnClick_LoadUIScene);
|
||||
_createPanelCreateBtn.RegisterCallback<MouseUpEvent>(OnClick_CreatePanel);
|
||||
_createPanelListView.onSelectionChange += OnPanelItemSelected;
|
||||
|
||||
_customUIInfo.SetEnabled(false);
|
||||
root.Add(container);
|
||||
UpdateCustomUiView();
|
||||
}
|
||||
|
||||
private CustomUIPanelConfig curSelectPanelPrefab;
|
||||
|
||||
private void OnPanelItemSelected(IEnumerable<object> obj)
|
||||
{
|
||||
var enumerable = obj as object[] ?? obj.ToArray();
|
||||
if (enumerable.Length == 0)
|
||||
{
|
||||
_createWork.SetEnabled(false);
|
||||
return;
|
||||
}
|
||||
|
||||
curSelectPanelPrefab = enumerable[0] as CustomUIPanelConfig;
|
||||
_createWork.SetEnabled(true);
|
||||
_createPanelCreateBtn.SetEnabled(true);
|
||||
_createPanelName.SetEnabled(true);
|
||||
_createPanelLayer.SetEnabled(true);
|
||||
_createPanelToggle.SetEnabled(true);
|
||||
// ReSharper disable once UsePatternMatching
|
||||
var config = curSelectPanelPrefab;
|
||||
if (config != null)
|
||||
{
|
||||
_createPanelName.SetValueWithoutNotify(config.Name);
|
||||
_createPanelLayer.value = config.Prefab.PanelLayer;
|
||||
_createPanelToggle.value = config.Prefab.HasFocusView;
|
||||
}
|
||||
}
|
||||
|
||||
private void OnClick_CreatePanel(MouseUpEvent evt)
|
||||
{
|
||||
if (curSelectPanelPrefab == null || curSelectPanelPrefab.Prefab == null)
|
||||
{
|
||||
Debug.LogError("待创建对象为空,无法创建!");
|
||||
return;
|
||||
}
|
||||
|
||||
var curCanvasNode = Selection.activeTransform.GetComponent<CanvasNode>() ?? _baseCanvasNode;
|
||||
//构建到场景
|
||||
var obj = (MonoBehaviour)PrefabUtility.InstantiatePrefab(curSelectPanelPrefab.Prefab,
|
||||
curCanvasNode.transform);
|
||||
var instantiatePrefab = obj.GetComponent<RectTransform>();
|
||||
instantiatePrefab.anchoredPosition = Vector2.zero;
|
||||
PrefabUtility.UnpackPrefabInstance(obj.gameObject, PrefabUnpackMode.Completely,
|
||||
InteractionMode.AutomatedAction);
|
||||
var icModuleConnector = instantiatePrefab.GetComponent<IC_ModuleConnector>();
|
||||
// var serializedObject = new SerializedObject(icModuleConnector.gameObject);
|
||||
// var sortOrder = serializedObject.FindProperty("SortOrder");
|
||||
// sortOrder.intValue = _createPanelLayer.value;
|
||||
// var hasFocusView = serializedObject.FindProperty("hasFocusView");
|
||||
// hasFocusView.boolValue = _createPanelToggle.value;
|
||||
|
||||
var pl = icModuleConnector.GetType();
|
||||
BindingFlags bindingFlags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance;
|
||||
var sortOrder = pl.GetField("DefaultStory" , bindingFlags);
|
||||
var hasFocusView = pl.GetField("hasFocusView" , bindingFlags);
|
||||
sortOrder?.SetValue(icModuleConnector , _createPanelLayer.value);
|
||||
hasFocusView?.SetValue(icModuleConnector , _createPanelToggle.value);
|
||||
icModuleConnector.name = _createPanelName.value;
|
||||
Selection.activeTransform = obj.transform;
|
||||
// EditorUtility.SetDirty(icModuleConnector);
|
||||
// EditorSceneManager.SaveOpenScenes();
|
||||
}
|
||||
|
||||
private void OnClick_LoadUIScene(MouseUpEvent evt)
|
||||
{
|
||||
var globalInstanceUiSceneAsset = IceCreamCodeUtils.GlobalInstance.UiSceneAsset;
|
||||
if (globalInstanceUiSceneAsset != null)
|
||||
{
|
||||
EditorSceneManager.SaveOpenScenes();
|
||||
EditorSceneManager.OpenScene(AssetDatabase.GetAssetPath(globalInstanceUiSceneAsset));
|
||||
UpdateCustomUiView();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void ShowWork(int state)
|
||||
{
|
||||
_createInfo.style.display = new StyleEnum<DisplayStyle>(state == 0 ? DisplayStyle.Flex : DisplayStyle.None);
|
||||
_createWork.style.display = new StyleEnum<DisplayStyle>(state == 0 ? DisplayStyle.Flex : DisplayStyle.None);
|
||||
_customUIInfo.style.display =
|
||||
new StyleEnum<DisplayStyle>(state == 1 ? DisplayStyle.Flex : DisplayStyle.None);
|
||||
_customUIWork.style.display =
|
||||
new StyleEnum<DisplayStyle>(state == 1 ? DisplayStyle.Flex : DisplayStyle.None);
|
||||
}
|
||||
|
||||
private void OnSelectionChangeScene()
|
||||
{
|
||||
UpdateCustomUiView();
|
||||
}
|
||||
|
||||
private void UpdateCustomUiView()
|
||||
{
|
||||
var activeTransform = UnityEditor.Selection.activeTransform;
|
||||
if (activeTransform == null)
|
||||
{
|
||||
ShowWork(-1);
|
||||
rootVisualElement.SetEnabled(false);
|
||||
return;
|
||||
}
|
||||
|
||||
rootVisualElement.SetEnabled(true);
|
||||
// Debug.Log("当前选中" + activeTransform.name);
|
||||
//根据当前选中的物体,获取对应的View,通过方向遍历父节点查找挂载了IC_ModuleConnector的物体,如果找到则显示对应的信息
|
||||
connector = null;
|
||||
var target = activeTransform;
|
||||
while (target != null && target != target.root)
|
||||
{
|
||||
if (target.TryGetComponent(out connector))
|
||||
{
|
||||
_onSelectionTransform = activeTransform;
|
||||
break;
|
||||
}
|
||||
|
||||
target = target.parent;
|
||||
}
|
||||
|
||||
if (connector != null)
|
||||
{
|
||||
ShowWork(1);
|
||||
UpdateCustomWork();
|
||||
}
|
||||
else
|
||||
{
|
||||
ShowWork(0);
|
||||
UpdateCreateWork();
|
||||
// _baseCanvasNode
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateCustomWork()
|
||||
{
|
||||
//更新ViewTitle
|
||||
_viewTitle.text = $"当前根页面:" + (connector != null ? connector.name : "无");
|
||||
_viewDesc.text = $"页面层级:{(connector != null ? connector.PanelLayer : 0)}";
|
||||
if (_currentSelected == null)
|
||||
{
|
||||
_customUITitle.text = "";
|
||||
_customUIDesc.text = "";
|
||||
_createBtn.SetEnabled(false);
|
||||
}
|
||||
|
||||
ShowList();
|
||||
}
|
||||
|
||||
private void UpdateCreateWork()
|
||||
{
|
||||
var canvasNodes = Transform.FindObjectsOfType<CanvasNode>();
|
||||
if (canvasNodes != null && canvasNodes.Length > 0)
|
||||
{
|
||||
_baseCanvasNode = canvasNodes[0];
|
||||
}
|
||||
|
||||
var isShowLoadBtn = _baseCanvasNode == null && IceCreamCodeUtils.GlobalInstance.UiSceneAsset != null;
|
||||
_loadUISceneBtn.style.display =
|
||||
new StyleEnum<DisplayStyle>((isShowLoadBtn ? DisplayStyle.Flex : DisplayStyle.None));
|
||||
// ReSharper disable once Unity.NoNullPropagation
|
||||
|
||||
var curCanvasNode = Selection.activeTransform.GetComponent<CanvasNode>() ?? _baseCanvasNode;
|
||||
|
||||
if (curCanvasNode != null)
|
||||
{
|
||||
_createSceneInfoLabel.text = $"当前是否可以进行UI创建 <color=green>{curCanvasNode != null}</color>";
|
||||
_createSceneInfoDesc.text = $"当前创建节点Canvas:{curCanvasNode.name}";
|
||||
_createWork.SetEnabled(true);
|
||||
}
|
||||
else
|
||||
{
|
||||
_createSceneInfoLabel.text = $"当前是否可以进行UI创建 <color=red>{curCanvasNode != null}</color>";
|
||||
_createSceneInfoDesc.text = "";
|
||||
_createWork.SetEnabled(false);
|
||||
}
|
||||
|
||||
ShowPanelList();
|
||||
}
|
||||
|
||||
private void ShowPanelList()
|
||||
{
|
||||
var items = IceCreamCodeUtils.GlobalInstance.CustomPanelConfigs;
|
||||
|
||||
if (items == null)
|
||||
{
|
||||
items = new List<CustomUIPanelConfig>();
|
||||
}
|
||||
|
||||
Func<VisualElement> makeItem = () => new Label();
|
||||
|
||||
Action<VisualElement, int> bindItem = (e, i) => ((Label)e).text = items[i].Name;
|
||||
|
||||
_createPanelListView.makeItem = makeItem;
|
||||
_createPanelListView.bindItem = bindItem;
|
||||
_createPanelListView.itemsSource = items;
|
||||
_createPanelListView.selectionType = SelectionType.Single;
|
||||
|
||||
_createPanelCreateBtn.SetEnabled(false);
|
||||
_createPanelName.SetEnabled(false);
|
||||
_createPanelLayer.SetEnabled(false);
|
||||
_createPanelToggle.SetEnabled(false);
|
||||
}
|
||||
|
||||
private void ShowList()
|
||||
{
|
||||
var items = IceCreamCodeUtils.GlobalInstance.CustomUIConfigs;
|
||||
|
||||
if (items == null)
|
||||
{
|
||||
items = new List<CustomUIConfig>();
|
||||
}
|
||||
|
||||
Func<VisualElement> makeItem = () => new Label();
|
||||
|
||||
Action<VisualElement, int> bindItem = (e, i) => ((Label)e).text = items[i].Name;
|
||||
|
||||
var listView = _customUIWork.Q<ListView>("CustomUiListView");
|
||||
listView.makeItem = makeItem;
|
||||
listView.bindItem = bindItem;
|
||||
listView.itemsSource = items;
|
||||
listView.selectionType = SelectionType.Single;
|
||||
|
||||
listView.onSelectionChange += OnItemSelected;
|
||||
}
|
||||
|
||||
private void OnClick_Create(MouseUpEvent evt)
|
||||
{
|
||||
if (connector == null)
|
||||
{
|
||||
Debug.LogError("当前选中物体没有挂载IC_ModuleConnector组件,无法创建!");
|
||||
return;
|
||||
}
|
||||
|
||||
if (_currentSelected == null)
|
||||
{
|
||||
Debug.LogError("当前没有选中任何自定义UI,无法创建!");
|
||||
return;
|
||||
}
|
||||
|
||||
var config = _currentSelected as CustomUIConfig;
|
||||
if (config == null || config.Prefab == null)
|
||||
{
|
||||
Debug.LogError("当前选中的自定义UI配置有误,无法创建!");
|
||||
return;
|
||||
}
|
||||
|
||||
//构建到场景
|
||||
var obj = (MonoBehaviour)PrefabUtility.InstantiatePrefab(config.Prefab, _onSelectionTransform);
|
||||
var instantiatePrefab = obj.GetComponent<RectTransform>();
|
||||
//设置位置,如果父节点是RectTransform,则设置为居中
|
||||
if (_onSelectionTransform is RectTransform)
|
||||
{
|
||||
instantiatePrefab.anchoredPosition = Vector2.zero;
|
||||
}
|
||||
else
|
||||
{
|
||||
instantiatePrefab.localPosition = Vector3.zero;
|
||||
}
|
||||
|
||||
PrefabUtility.UnpackPrefabInstance(obj.gameObject, PrefabUnpackMode.Completely,
|
||||
InteractionMode.AutomatedAction);
|
||||
Selection.activeTransform = obj.transform;
|
||||
Debug.Log("创建成功!");
|
||||
}
|
||||
|
||||
private void OnClick_UpdateViewInfo(MouseUpEvent evt)
|
||||
{
|
||||
UpdateCustomUiView();
|
||||
}
|
||||
|
||||
private Object _currentSelected;
|
||||
|
||||
private void OnItemSelected(IEnumerable<object> obj)
|
||||
{
|
||||
var enumerable = obj as object[] ?? obj.ToArray();
|
||||
if (enumerable.Length == 0)
|
||||
{
|
||||
_customUIInfo.SetEnabled(false);
|
||||
return;
|
||||
}
|
||||
|
||||
_currentSelected = enumerable[0];
|
||||
_createBtn.SetEnabled(true);
|
||||
_customUIInfo.SetEnabled(true);
|
||||
// ReSharper disable once UsePatternMatching
|
||||
var config = _currentSelected as CustomUIConfig;
|
||||
if (config != null)
|
||||
{
|
||||
_customUITitle.text = config.Name;
|
||||
_customUIDesc.text = config.Desc;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1bbc1495191064b45b319b93211dd6e8
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,33 @@
|
||||
<ui:UXML xmlns:ui="UnityEngine.UIElements" xmlns:uie="UnityEditor.UIElements" editor-extension-mode="False">
|
||||
<ui:VisualElement name="BoxPanelInfo" style="height: 108px; background-color: rgba(82, 80, 80, 0.45); border-left-width: 1px; border-right-width: 1px; border-top-width: 1px; border-bottom-width: 1px; border-top-left-radius: 10px; border-bottom-left-radius: 10px; border-top-right-radius: 10px; border-bottom-right-radius: 10px; margin-left: 5px; margin-right: 5px; margin-top: 5px; margin-bottom: 5px; padding-left: 5px; padding-right: 5px; padding-top: 5px; padding-bottom: 5px; position: relative; left: 0; right: 0; border-left-color: rgb(120, 120, 120); border-right-color: rgb(120, 120, 120); border-top-color: rgb(120, 120, 120); border-bottom-color: rgb(120, 120, 120);">
|
||||
<ui:Label text="当前是否为UI场景" display-tooltip-when-elided="true" name="ViewTitle" tooltip="当前根页面信息" usage-hints="None" style="height: 23px; -unity-font-style: bold; -unity-text-align: middle-left; font-size: 20px; color: rgb(248, 248, 248);" />
|
||||
<ui:Label text="Label" display-tooltip-when-elided="true" name="Desc" style="height: 43px; padding-left: 5px; padding-right: 5px; padding-top: 5px; padding-bottom: 5px; color: rgb(171, 171, 171);" />
|
||||
<ui:Button text="跳转到UI制作场景" display-tooltip-when-elided="true" name="LoadSceneBtn" style="align-items: center; justify-content: flex-end; -unity-text-align: upper-center; white-space: nowrap; position: relative; top: auto; left: 0; height: 23px; width: auto; -unity-font-style: normal; border-top-left-radius: 10px; border-bottom-left-radius: 10px; border-top-right-radius: 10px; border-bottom-right-radius: 10px; right: 0; bottom: auto; overflow: visible; visibility: visible; display: flex; opacity: 1;" />
|
||||
</ui:VisualElement>
|
||||
<ui:VisualElement name="BoxPanelCreate" style="height: 257px; background-color: rgba(82, 80, 80, 0.45); border-left-width: 1px; border-right-width: 1px; border-top-width: 1px; border-bottom-width: 1px; border-top-left-radius: 10px; border-bottom-left-radius: 10px; border-top-right-radius: 10px; border-bottom-right-radius: 10px; margin-left: 5px; margin-right: 5px; margin-top: 5px; margin-bottom: 5px; padding-left: 5px; padding-right: 5px; padding-top: 5px; padding-bottom: 5px; position: relative; left: 0; right: 0; border-left-color: rgb(120, 120, 120); border-right-color: rgb(120, 120, 120); border-top-color: rgb(120, 120, 120); border-bottom-color: rgb(120, 120, 120);">
|
||||
<ui:Label text="页面构建" display-tooltip-when-elided="true" name="PanelCreateTitle" usage-hints="None" style="height: 23px; -unity-font-style: normal; -unity-text-align: middle-left; font-size: 18px; color: rgb(248, 248, 248);" />
|
||||
<ui:VisualElement style="height: 2px; background-color: rgb(46, 46, 46); margin-top: 5px; margin-bottom: 5px;" />
|
||||
<ui:ListView focusable="true" reorderable="false" reorder-mode="Simple" name="CustomUiListView" style="padding-left: 5px; padding-right: 5px; padding-top: 5px; padding-bottom: 5px; margin-left: 5px; margin-right: 5px; margin-top: 5px; margin-bottom: 5px; background-color: rgb(63, 63, 63); border-left-color: rgb(120, 120, 120); border-right-color: rgb(120, 120, 120); border-top-color: rgb(120, 120, 120); border-bottom-color: rgb(120, 120, 120); border-left-width: 1px; border-right-width: 1px; border-top-width: 1px; border-bottom-width: 1px; border-top-left-radius: 5px; border-bottom-left-radius: 5px; border-top-right-radius: 5px; border-bottom-right-radius: 5px; height: 108px; max-height: 108px;" />
|
||||
<ui:VisualElement name="CustomUIInfo" style="border-top-left-radius: 10px; border-bottom-left-radius: 10px; border-top-right-radius: 10px; border-bottom-right-radius: 10px; height: auto; border-left-color: rgb(120, 120, 120); border-right-color: rgb(120, 120, 120); border-top-color: rgb(120, 120, 120); border-bottom-color: rgb(120, 120, 120); border-left-width: 1px; border-right-width: 1px; border-top-width: 1px; border-bottom-width: 1px; justify-content: flex-start; bottom: 0; position: relative; width: auto; left: 0; right: 0; align-items: stretch; padding-left: 5px; padding-right: 5px; padding-top: 5px; padding-bottom: 5px;">
|
||||
<ui:TextField picking-mode="Ignore" label="页面名称" text="New Panel" name="PanelName" />
|
||||
<ui:SliderInt picking-mode="Ignore" label="页面层级" value="0" high-value="100" show-input-field="true" name="PanelLayer" low-value="-50" />
|
||||
<ui:Toggle label="是否聚焦" name="FocusToggle" value="true" />
|
||||
<ui:Button text="构建到场景" display-tooltip-when-elided="true" name="CreateBtn" style="white-space: nowrap; align-items: stretch; left: auto; right: auto; justify-content: flex-start; flex-direction: column; flex-wrap: nowrap; transform-origin: center;" />
|
||||
</ui:VisualElement>
|
||||
</ui:VisualElement>
|
||||
<ui:VisualElement name="BoxViewInfo" style="height: 108px; background-color: rgba(82, 80, 80, 0.45); border-left-width: 1px; border-right-width: 1px; border-top-width: 1px; border-bottom-width: 1px; border-top-left-radius: 10px; border-bottom-left-radius: 10px; border-top-right-radius: 10px; border-bottom-right-radius: 10px; margin-left: 5px; margin-right: 5px; margin-top: 5px; margin-bottom: 5px; padding-left: 5px; padding-right: 5px; padding-top: 5px; padding-bottom: 5px; position: relative; left: 0; right: 0; border-left-color: rgb(120, 120, 120); border-right-color: rgb(120, 120, 120); border-top-color: rgb(120, 120, 120); border-bottom-color: rgb(120, 120, 120); display: none;">
|
||||
<ui:Label text="当前根页面:xxxxx" display-tooltip-when-elided="true" name="ViewTitle" tooltip="当前根页面信息" usage-hints="None" style="height: 23px; -unity-font-style: bold; -unity-text-align: middle-left; font-size: 20px; color: rgb(248, 248, 248);" />
|
||||
<ui:Label text="Label" display-tooltip-when-elided="true" name="Desc" style="height: 43px; padding-left: 5px; padding-right: 5px; padding-top: 5px; padding-bottom: 5px; color: rgb(171, 171, 171);" />
|
||||
<ui:Button text="刷新" display-tooltip-when-elided="true" name="UpdateViewBtn" style="align-items: center; justify-content: flex-end; -unity-text-align: upper-center; white-space: nowrap; position: relative; top: auto; left: 0; height: 23px; width: auto; -unity-font-style: normal; border-top-left-radius: 10px; border-bottom-left-radius: 10px; border-top-right-radius: 10px; border-bottom-right-radius: 10px; right: 0; bottom: auto; overflow: visible; visibility: visible; display: none; opacity: 1;" />
|
||||
</ui:VisualElement>
|
||||
<ui:VisualElement name="BoxViewCustom" style="height: 257px; background-color: rgba(82, 80, 80, 0.45); border-left-width: 1px; border-right-width: 1px; border-top-width: 1px; border-bottom-width: 1px; border-top-left-radius: 10px; border-bottom-left-radius: 10px; border-top-right-radius: 10px; border-bottom-right-radius: 10px; margin-left: 5px; margin-right: 5px; margin-top: 5px; margin-bottom: 5px; padding-left: 5px; padding-right: 5px; padding-top: 5px; padding-bottom: 5px; position: relative; left: 0; right: 0; border-left-color: rgb(120, 120, 120); border-right-color: rgb(120, 120, 120); border-top-color: rgb(120, 120, 120); border-bottom-color: rgb(120, 120, 120); display: none;">
|
||||
<ui:Label text="自定义组件库" display-tooltip-when-elided="true" name="ViewTitle" tooltip="当前根页面信息" usage-hints="None" style="height: 23px; -unity-font-style: normal; -unity-text-align: middle-left; font-size: 18px; color: rgb(248, 248, 248);" />
|
||||
<ui:VisualElement style="height: 2px; background-color: rgb(46, 46, 46); margin-top: 5px; margin-bottom: 5px;" />
|
||||
<ui:ListView focusable="true" reorderable="false" reorder-mode="Simple" name="CustomUiListView" style="padding-left: 5px; padding-right: 5px; padding-top: 5px; padding-bottom: 5px; margin-left: 5px; margin-right: 5px; margin-top: 5px; margin-bottom: 5px; background-color: rgb(63, 63, 63); border-left-color: rgb(120, 120, 120); border-right-color: rgb(120, 120, 120); border-top-color: rgb(120, 120, 120); border-bottom-color: rgb(120, 120, 120); border-left-width: 1px; border-right-width: 1px; border-top-width: 1px; border-bottom-width: 1px; border-top-left-radius: 5px; border-bottom-left-radius: 5px; border-top-right-radius: 5px; border-bottom-right-radius: 5px; height: 108px; max-height: 108px;" />
|
||||
<ui:VisualElement name="CustomUIInfo" style="border-top-left-radius: 10px; border-bottom-left-radius: 10px; border-top-right-radius: 10px; border-bottom-right-radius: 10px; height: auto; border-left-color: rgb(120, 120, 120); border-right-color: rgb(120, 120, 120); border-top-color: rgb(120, 120, 120); border-bottom-color: rgb(120, 120, 120); border-left-width: 1px; border-right-width: 1px; border-top-width: 1px; border-bottom-width: 1px; justify-content: flex-start; bottom: 0; position: relative; width: auto; left: 0; right: 0; align-items: stretch; padding-left: 5px; padding-right: 5px; padding-top: 5px; padding-bottom: 5px;">
|
||||
<ui:Label text="Label" display-tooltip-when-elided="true" name="CustomUITitle" style="margin-left: 5px; margin-right: 5px; margin-top: 5px; margin-bottom: 5px; -unity-font-style: bold;" />
|
||||
<ui:Label text="Label" display-tooltip-when-elided="true" name="CustomUIDesc" style="margin-left: 5px; margin-right: 5px; margin-top: 5px; margin-bottom: 5px; -unity-font-style: normal; color: rgb(168, 168, 168);" />
|
||||
<ui:Button text="构建到场景" display-tooltip-when-elided="true" name="CreateBtn" style="white-space: nowrap; align-items: stretch; left: auto; right: auto; justify-content: flex-start; flex-direction: column; flex-wrap: nowrap; transform-origin: center;" />
|
||||
</ui:VisualElement>
|
||||
</ui:VisualElement>
|
||||
</ui:UXML>
|
||||
@@ -0,0 +1,10 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4ec32f900ab7abb4ab911e12724e2dad
|
||||
ScriptedImporter:
|
||||
internalIDToNameTable: []
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
script: {fileID: 13804, guid: 0000000000000000e000000000000000, type: 0}
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 842bd4eee4f5d2249a33a92b7a02e7a7
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 29442ad1c57d48e588235e592beb0dbf
|
||||
timeCreated: 1573710190
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6c85dfe9d5b049e3b48c9e1c1871330e
|
||||
timeCreated: 1565230421
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: bd696ef850584690806c98a3a90263e1
|
||||
timeCreated: 1564544711
|
||||
@@ -0,0 +1,11 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace IcecreamView
|
||||
{
|
||||
public class CanvasNode : MonoBehaviour
|
||||
{
|
||||
public bool IsBaseCanvas;
|
||||
public int OrderRange;
|
||||
public Canvas Canvas;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 02852c69c24a4a55b5dc70f2e1314404
|
||||
timeCreated: 1627547169
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 20c0b47623c190e4983df1984a7417dd
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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;
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1badf54a3ca64034bdd3fdf4100c8202
|
||||
timeCreated: 1588251654
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a3b4639ae73b9f740a4fb233227a3b4d
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,11 @@
|
||||
|
||||
namespace IcecreamView {
|
||||
public interface IC_IViewInfo
|
||||
{
|
||||
string GetTable();
|
||||
bool IsOnce();
|
||||
bool IsCache();
|
||||
IC_AbstractView GetView();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8eee9fefcf41d154c9ca69c2c1a66ccf
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,69 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
namespace IcecreamView {
|
||||
|
||||
[CreateAssetMenu(fileName = "IC_Resource_ViewConfig", menuName = "IceCreamView/IceView Config(Resource 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>();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 628ff49fd857e0b4cb7f99680f51b40b
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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 Config(Prefabs 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()
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9dd6fc253e125ee4e8c3efae89432f15
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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 ();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 37c69d0bb73d4652b6f6f61207031437
|
||||
timeCreated: 1716797150
|
||||
@@ -0,0 +1,9 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace IcecreamView
|
||||
{
|
||||
public class CustomUIConnector : MonoBehaviour
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b167aacff6384b958a1f7f0f0709527c
|
||||
timeCreated: 1685946428
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 14f45208cccd4044a4100502d532a204
|
||||
timeCreated: 1565244232
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3730f8fe0134456fb3385744fd4da4d4
|
||||
timeCreated: 1565254674
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8449cc0e1f354e27a86a1168c100e3c7
|
||||
timeCreated: 1565241933
|
||||
@@ -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() { }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 34cf465e4c13b4041bbfadfbb26f925d
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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 ();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5c4639cd5f06ba043b6257e65593c461
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0a3650d50655537449f350dc11b7c347
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ec93ef680cfc0fe4288072143abc577b
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7783ab86db5640e4485e3aff12200852
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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];
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e926a14e48a48b64ca208e80c01016da
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"name": "IcecreamView",
|
||||
"references": [
|
||||
"GUID:9e24947de15b9834991c9d8411ea37cf",
|
||||
"GUID:84651a3751eca9349aac36a66bba901b"
|
||||
],
|
||||
"includePlatforms": [],
|
||||
"excludePlatforms": [],
|
||||
"allowUnsafeCode": false,
|
||||
"overrideReferences": false,
|
||||
"precompiledReferences": [],
|
||||
"autoReferenced": true,
|
||||
"defineConstraints": [],
|
||||
"versionDefines": [],
|
||||
"noEngineReferences": false
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9d61d29b329d622458c8165d250bc2d9
|
||||
AssemblyDefinitionImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1ad56bc16870bda4b83347400dee3137
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
13
Packages/CC-Framework/com.foldcc.icecreamview/package.json
Normal file
13
Packages/CC-Framework/com.foldcc.icecreamview/package.json
Normal file
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"name": "com.foldcc.icecreamview",
|
||||
"version": "0.1.5",
|
||||
"displayName": "IceCream View",
|
||||
"description": "冰淇淋UI框架,一套灵活高可用高扩展的UI框架控制器,可高度自定义",
|
||||
"unity": "2018.1",
|
||||
"dependencies": {
|
||||
},
|
||||
"author": {
|
||||
"name": "Foldcc",
|
||||
"email": "lhyuau@qq.com"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 932d7c7252686e14697d1ef0a6db1c98
|
||||
TextScriptImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Reference in New Issue
Block a user