859 lines
31 KiB
C#
859 lines
31 KiB
C#
|
#if !BUILDING
|
|||
|
using Cysharp.Threading.Tasks;
|
|||
|
using System;
|
|||
|
using System.Collections.Generic;
|
|||
|
using System.IO;
|
|||
|
using System.Linq;
|
|||
|
using System.Text;
|
|||
|
using UnityEditor;
|
|||
|
using UnityEditor.SceneManagement;
|
|||
|
using UnityEngine;
|
|||
|
using UnityEngine.UI;
|
|||
|
|
|||
|
namespace EditorCreateUI
|
|||
|
{
|
|||
|
public partial class Editor_CreateUIPanel : EditorWindowBase
|
|||
|
{
|
|||
|
private GenerateAttData[] generateAttDatas = new GenerateAttData[]
|
|||
|
{
|
|||
|
new GenerateAttData("Ga_", "对象", "GameObject"),
|
|||
|
|
|||
|
new GenerateAttData("Tr_", "对象", "Transform"),
|
|||
|
|
|||
|
new GenerateAttData("Rect_", "RectTransform", "RectTransform"),
|
|||
|
|
|||
|
new GenerateAttData("Content_", "容器", "Transform"),
|
|||
|
|
|||
|
new GenerateAttData("Btn_", "按钮", "Button"),
|
|||
|
|
|||
|
new GenerateAttData("Tcg_", "复选框组", "TgCheckGroup"),
|
|||
|
|
|||
|
new GenerateAttData("Av_", "视频ui", "DisplayUGUI", "using RenderHeads.Media.AVProVideo;"),
|
|||
|
|
|||
|
new GenerateAttData("Tx_", "文本", "TextMeshProUGUI", "using TMPro;"),
|
|||
|
|
|||
|
new GenerateAttData("Img_", "图片", "Image或RawImage"),
|
|||
|
|
|||
|
new GenerateAttData("Sr_", "滑动列表", "ScrollRect"),
|
|||
|
|
|||
|
new GenerateAttData("Rv_", "无限列表", "RecycleView"),
|
|||
|
|
|||
|
new GenerateAttData("Ev_", "无限列表(带标签)", "ExpandableView"),
|
|||
|
|
|||
|
new GenerateAttData("Evs_", "无限列表(带标签,单二级)", "ExpandableViewSingle"),
|
|||
|
|
|||
|
new GenerateAttData("Input_", "输入框", "TMP_InputField", "using TMPro;"),
|
|||
|
|
|||
|
new GenerateAttData("Slider_", "滑动条", "Slider"),
|
|||
|
|
|||
|
new GenerateAttData("Toggle_", "复选框", "Toggle"),
|
|||
|
|
|||
|
new GenerateAttData("TG_", "复选组", "TgGroup"),
|
|||
|
|
|||
|
new GenerateAttData("Lt_", "多语言文本", "LanguageText"),
|
|||
|
|
|||
|
new GenerateAttData("Li_", "多语言图片", "LanguageImage"),
|
|||
|
|
|||
|
new GenerateAttData("Ldt_", "倒计时", "LanguageDownTime"),
|
|||
|
|
|||
|
new GenerateAttData("Tm_", "TMP文本", "TextMeshProUGUI", "using TMPro;"),
|
|||
|
|
|||
|
new GenerateAttData("Cam_", "摄像机", "Camera"),
|
|||
|
|
|||
|
new GenerateAttData("Class_{T}", "自定义类型", "{T}"),
|
|||
|
};
|
|||
|
|
|||
|
private static string[] notClose_raycast = new string[]
|
|||
|
{
|
|||
|
"Scroll View",
|
|||
|
"btn_",
|
|||
|
"ray",
|
|||
|
"sv_",
|
|||
|
"close",
|
|||
|
};
|
|||
|
|
|||
|
private static string[] notFindChild = new string[]
|
|||
|
{
|
|||
|
"UI_"
|
|||
|
};
|
|||
|
|
|||
|
private string panelName = "";
|
|||
|
|
|||
|
private int selectedOptionIndex = 0;
|
|||
|
|
|||
|
private Vector2 scrollPosition = Vector2.zero;
|
|||
|
|
|||
|
string systemName;
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// child, panelName, prefabDir
|
|||
|
/// </summary>
|
|||
|
List<Tuple<bool, string, string>> lastPanelName = new List<Tuple<bool, string, string>>();
|
|||
|
int lastPanelIndex = 0;
|
|||
|
[MenuItem("Window/Create UI Panel")]
|
|||
|
public static void ShowWindow()
|
|||
|
{
|
|||
|
var window = EditorWindow.GetWindow(typeof(Editor_CreateUIPanel));
|
|||
|
window.titleContent = new GUIContent("UI管理工具");
|
|||
|
}
|
|||
|
private void ShowTips()
|
|||
|
{
|
|||
|
try
|
|||
|
{
|
|||
|
if (position.width <= 350) return;
|
|||
|
//GUILayout.Label("首字母大写,前缀_名称。会自动创建变量。\n不是以下类型前缀的,都自动生成为Transform。\n名称中带ray不会关闭RayCast");
|
|||
|
|
|||
|
scrollPosition = GUILayout.BeginScrollView(scrollPosition, false, true, GUILayout.ExpandHeight(true));
|
|||
|
|
|||
|
// 开始绘制表格布局
|
|||
|
GUILayout.BeginVertical(GUI.skin.box);
|
|||
|
|
|||
|
// 表头
|
|||
|
GUILayout.BeginHorizontal();
|
|||
|
DrawTableCell("", 20, 20, Color.gray);
|
|||
|
DrawTableCell("前缀", 150, 20, Color.gray);
|
|||
|
DrawTableCell("类型", 150, 20, Color.gray);
|
|||
|
DrawTableCell("描述", 150, 20, Color.gray);
|
|||
|
GUILayout.EndHorizontal();
|
|||
|
|
|||
|
// 分隔线
|
|||
|
DrawHorizontalLine(500);
|
|||
|
|
|||
|
|
|||
|
// 数据行
|
|||
|
for (int i = 0; i < generateAttDatas.Length; i++)
|
|||
|
{
|
|||
|
var data = generateAttDatas[i];
|
|||
|
GUILayout.BeginHorizontal();
|
|||
|
DrawTableCell((i + 1).ToString(), 20, 15, Color.gray);
|
|||
|
DrawTableCell(data.prefix, 150);
|
|||
|
DrawTableCell(data.type, 150);
|
|||
|
DrawTableCell(data.description, 150);
|
|||
|
GUILayout.EndHorizontal();
|
|||
|
|
|||
|
// 添加淡淡的分割线
|
|||
|
DrawHorizontalLine(500, Color.gray);
|
|||
|
}
|
|||
|
// 结束绘制表格布局
|
|||
|
GUILayout.EndVertical();
|
|||
|
|
|||
|
// 结束绘制滚动视图
|
|||
|
GUILayout.EndScrollView();
|
|||
|
}
|
|||
|
catch (Exception)
|
|||
|
{
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
bool CheckIsThis()
|
|||
|
{
|
|||
|
var sta = PrefabStageUtility.GetCurrentPrefabStage();
|
|||
|
if (sta && sta.prefabContentsRoot)
|
|||
|
{
|
|||
|
if (sta.prefabContentsRoot.name == panelName)
|
|||
|
{
|
|||
|
return true;
|
|||
|
}
|
|||
|
}
|
|||
|
return false;
|
|||
|
}
|
|||
|
|
|||
|
bool GetIsSingle()
|
|||
|
{
|
|||
|
var sta = PrefabStageUtility.GetCurrentPrefabStage();
|
|||
|
|
|||
|
Debug.Log(sta.prefabContentsRoot);
|
|||
|
return true;
|
|||
|
}
|
|||
|
|
|||
|
string[] GetCompletion()
|
|||
|
{
|
|||
|
List<string> str = new List<string>();
|
|||
|
// 指定目录
|
|||
|
string directoryPath = "Assets/Scripts/HotUpdate/Game/UI";
|
|||
|
|
|||
|
DirectoryInfo directoryInfo = new DirectoryInfo(directoryPath);
|
|||
|
|
|||
|
DirectoryInfo[] di = directoryInfo.GetDirectories();
|
|||
|
|
|||
|
for (int i = 0; i < di.Length; i++)
|
|||
|
{
|
|||
|
DirectoryInfo[] di2 = di[i].GetDirectories();
|
|||
|
for (int j = 0; j < di2.Length; j++)
|
|||
|
{
|
|||
|
str.Add(di2[j].Name);
|
|||
|
GetCompletion(ref str, di2[j]);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
return str.ToArray();
|
|||
|
}
|
|||
|
|
|||
|
void GetCompletion(ref List<string> str, DirectoryInfo dir)
|
|||
|
{
|
|||
|
DirectoryInfo[] dirs = dir.GetDirectories();
|
|||
|
for (int i = 0; i < dirs.Length; i++)
|
|||
|
{
|
|||
|
var item = dirs[i];
|
|||
|
if (item.Name.ToLower().StartsWith("ui_"))
|
|||
|
{
|
|||
|
str.Add(item.Name);
|
|||
|
GetCompletion(ref str, item);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
private void OnGUI()
|
|||
|
{
|
|||
|
//try
|
|||
|
//{
|
|||
|
//// 页签名称数组
|
|||
|
//string[] tabNames = { "Main", "Child" };
|
|||
|
//// 创建一个横向页签栏
|
|||
|
//selectedTabIndex = GUILayout.Toolbar(selectedTabIndex, tabNames);
|
|||
|
|
|||
|
if (IsCreateChild == false)
|
|||
|
OnMainGUI();
|
|||
|
else
|
|||
|
OnCreateChildGUI();
|
|||
|
|
|||
|
|
|||
|
//if (GUI_Button("测试"))
|
|||
|
// GetCompletion();
|
|||
|
|
|||
|
GUILayout.Space(20);
|
|||
|
// 开始绘制滚动视图
|
|||
|
|
|||
|
ShowTool();
|
|||
|
|
|||
|
ShowTips();
|
|||
|
//}
|
|||
|
//catch (Exception)
|
|||
|
//{
|
|||
|
|
|||
|
//}
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
private void CreatePanel(string systemName)
|
|||
|
{
|
|||
|
string panelName = this.panelName;
|
|||
|
if (!this.panelName.StartsWith("UI_"))
|
|||
|
panelName = "UI_" + this.panelName;
|
|||
|
|
|||
|
// 复制 UI_Example 目录
|
|||
|
string sourceDir = "Assets/Art/UI/Panels/UI_Example";
|
|||
|
string targetDir = "Assets/Art/UI/Panels/" + panelName;
|
|||
|
|
|||
|
if (!AssetDatabase.IsValidFolder(targetDir))
|
|||
|
{
|
|||
|
AssetDatabase.CopyAsset(sourceDir, targetDir);
|
|||
|
AssetDatabase.Refresh();
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
Debug.LogWarning("已存在同名的面板。");
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
// 将 UI_Example 文件复制到新目录
|
|||
|
string sourceFile = Path.Combine(sourceDir, "UI_Example.prefab");
|
|||
|
string destFile = Path.Combine(targetDir, panelName + ".prefab");
|
|||
|
string deleteFile = Path.Combine(targetDir, "UI_Example.prefab");
|
|||
|
File.Copy(sourceFile, destFile);
|
|||
|
File.Delete(deleteFile);
|
|||
|
|
|||
|
string ToSourceFolder = $"Assets/Scripts/HotUpdate/Game/UI/{systemName}/{panelName}";
|
|||
|
if (!Directory.Exists(ToSourceFolder))
|
|||
|
Directory.CreateDirectory(ToSourceFolder);
|
|||
|
AssetDatabase.Refresh();
|
|||
|
|
|||
|
//复制 UI_Example.cs 脚本并创建新脚本
|
|||
|
string scriptSource = $"Assets/Scripts/HotUpdate/Game/UI/Normal/UI_Example/UI_Example.cs";
|
|||
|
string scriptTarget = $"Assets/Scripts/HotUpdate/Game/UI/{systemName}/{panelName}/{panelName}.cs";
|
|||
|
|
|||
|
AssetDatabase.CopyAsset(scriptSource, scriptTarget);
|
|||
|
|
|||
|
|
|||
|
// 复制 UI_Example_Generate.cs 脚本并创建新脚本
|
|||
|
string scriptSource2 = $"Assets/Scripts/HotUpdate/Game/UI/Normal/UI_Example/UI_Example_Generate.cs";
|
|||
|
string scriptTarget2 = $"Assets/Scripts/HotUpdate/Game/UI/{systemName}/{panelName}/{panelName}_Generate.cs";
|
|||
|
|
|||
|
AssetDatabase.CopyAsset(scriptSource2, scriptTarget2);
|
|||
|
|
|||
|
// 读取并替换脚本内容
|
|||
|
string scriptPath = Path.Combine(Application.dataPath, $"Scripts/HotUpdate/Game/UI/{systemName}/{panelName}/{panelName}.cs");
|
|||
|
string scriptContent = File.ReadAllText(scriptPath);
|
|||
|
scriptContent = scriptContent.Replace("UI_Example", panelName);
|
|||
|
|
|||
|
// 将修改后的内容写回脚本文件
|
|||
|
File.WriteAllText(scriptPath, scriptContent);
|
|||
|
|
|||
|
|
|||
|
// 读取并替换脚本内容
|
|||
|
string scriptPath2 = Path.Combine(Application.dataPath, $"Scripts/HotUpdate/Game/UI/{systemName}/{panelName}/{panelName}_Generate.cs");
|
|||
|
string scriptContent2 = File.ReadAllText(scriptPath2);
|
|||
|
scriptContent2 = scriptContent2.Replace("UI_Example", panelName);
|
|||
|
|
|||
|
// 将修改后的内容写回脚本文件
|
|||
|
File.WriteAllText(scriptPath2, scriptContent2);
|
|||
|
|
|||
|
AssetDatabase.Refresh();
|
|||
|
GameObject prefab = AssetDatabase.LoadAssetAtPath<GameObject>(destFile);
|
|||
|
|
|||
|
if (prefab != null)
|
|||
|
{
|
|||
|
// 修改 tx_name 的文本属性
|
|||
|
|
|||
|
//Text textComponent = prefab.GetComponentInChildren<Text>();
|
|||
|
//if (textComponent != null)
|
|||
|
// textComponent.text = panelName.Substring(3);
|
|||
|
//else
|
|||
|
// Debug.LogError("在预制体中未找到 Text 组件。");
|
|||
|
|
|||
|
|
|||
|
// 保存预制体的更改
|
|||
|
PrefabUtility.SaveAsPrefabAsset(prefab, destFile);
|
|||
|
|
|||
|
var sceneView = SceneView.sceneViews[0] as SceneView;
|
|||
|
|
|||
|
// 激活主场景视图
|
|||
|
if (sceneView != null)
|
|||
|
sceneView.Focus();
|
|||
|
|
|||
|
Selection.activeObject = prefab;
|
|||
|
AssetDatabase.OpenAsset(prefab);
|
|||
|
|
|||
|
if (!SceneView.lastActiveSceneView.in2DMode)
|
|||
|
// 切换到 2D 模式
|
|||
|
SceneView.lastActiveSceneView.in2DMode = true;
|
|||
|
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
//Debug.LogError("在路径 " + destFile + " 中未找到预制体。");
|
|||
|
}
|
|||
|
|
|||
|
AssetDatabase.Refresh();
|
|||
|
}
|
|||
|
|
|||
|
bool IsSpecialName(string name)
|
|||
|
{
|
|||
|
return char.IsUpper(name[0]) && name.Contains("_") && !name.Contains(" ")
|
|||
|
&& !name.Contains("(")
|
|||
|
&& !name.Contains(")");
|
|||
|
}
|
|||
|
|
|||
|
void AutoSetRaycast(Transform tr)
|
|||
|
{
|
|||
|
bool isNot = false;
|
|||
|
for (int i = 0; i < notClose_raycast.Length; i++)
|
|||
|
{
|
|||
|
if (tr.name.ToLower().Contains(notClose_raycast[i].ToLower()))
|
|||
|
{
|
|||
|
isNot = true;
|
|||
|
break;
|
|||
|
}
|
|||
|
}
|
|||
|
if (!isNot)
|
|||
|
{
|
|||
|
//如果不是特殊命名
|
|||
|
if (!IsSpecialName(tr.name))
|
|||
|
{
|
|||
|
var gra = tr.GetComponent<MaskableGraphic>();
|
|||
|
if (gra != null)
|
|||
|
gra.raycastTarget = false;
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
//Text都关掉 Raycast
|
|||
|
var te = tr.GetComponent<Text>();
|
|||
|
if (te != null)
|
|||
|
te.raycastTarget = false;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
for (int k = 0; k < tr.childCount; k++)
|
|||
|
AutoSetRaycast(tr.GetChild(k));
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
void GenerateAttribute(string systemName)
|
|||
|
{
|
|||
|
string panelName = this.panelName;
|
|||
|
if (!this.panelName.StartsWith("UI_"))
|
|||
|
panelName = "UI_" + this.panelName;
|
|||
|
|
|||
|
string targetDir = "Assets/Art/UI/Panels/" + panelName;
|
|||
|
string destFile = Path.Combine(targetDir, panelName + ".prefab");
|
|||
|
|
|||
|
string str =
|
|||
|
@"using UnityEngine;
|
|||
|
using UnityEngine.UI;
|
|||
|
[USING]
|
|||
|
|
|||
|
//子类[NAME]
|
|||
|
[UIClassName(typeof([NAME]))]
|
|||
|
public abstract class [NAME]_Generate : UIRootPanelBase
|
|||
|
{
|
|||
|
[ATTRIBUTE]
|
|||
|
|
|||
|
protected abstract void Init();
|
|||
|
|
|||
|
internal override void InitAttribute()
|
|||
|
{
|
|||
|
[FIND]
|
|||
|
|
|||
|
Init();
|
|||
|
}
|
|||
|
}";
|
|||
|
str = str.Replace("[NAME]", panelName);
|
|||
|
|
|||
|
GameObject prefab = AssetDatabase.LoadAssetAtPath<GameObject>(destFile);
|
|||
|
List<Tuple<string, string>> tuples = new List<Tuple<string, string>>();
|
|||
|
|
|||
|
string str_using = "";
|
|||
|
|
|||
|
Action<Transform> action = null;
|
|||
|
action = (tr) =>
|
|||
|
{
|
|||
|
// 检查节点名字首字母是否为大写,并且带_
|
|||
|
if (IsSpecialName(tr.name))
|
|||
|
{
|
|||
|
Transform target = tr.parent;
|
|||
|
string namePath = tr.name;
|
|||
|
while (target != prefab.transform)
|
|||
|
{
|
|||
|
namePath = target.name + "/" + namePath;
|
|||
|
target = target.parent;
|
|||
|
}
|
|||
|
|
|||
|
//Debug.Log("生成:" + tr.name);
|
|||
|
string attStr;
|
|||
|
string findStr;
|
|||
|
if (tr.name.StartsWith("Img_"))
|
|||
|
{
|
|||
|
if (tr.GetComponent<RawImage>() != null)
|
|||
|
{
|
|||
|
attStr = "internal RawImage " + tr.name + ";";
|
|||
|
findStr = $"{tr.name} = transform.Find(\"{namePath}\").GetComponent<RawImage>();";
|
|||
|
}
|
|||
|
else if (tr.GetComponent<Image>() != null)
|
|||
|
{
|
|||
|
attStr = "internal Image " + tr.name + ";";
|
|||
|
findStr = $"{tr.name} = transform.Find(\"{namePath}\").GetComponent<Image>();";
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
attStr = "internal Transform " + tr.name + ";";
|
|||
|
findStr = $"{tr.name} = transform.Find(\"{namePath}\");";
|
|||
|
}
|
|||
|
}
|
|||
|
else if (tr.name.StartsWith("Btn_"))
|
|||
|
{
|
|||
|
if (tr.GetComponent<Button>() != null)
|
|||
|
{
|
|||
|
attStr = "internal Button " + tr.name + ";";
|
|||
|
findStr = $"{tr.name} = transform.Find(\"{namePath}\").GetComponent<Button>();";
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
attStr = "internal GameObject " + tr.name + ";";
|
|||
|
findStr = $"{tr.name} = transform.Find(\"{namePath}\").gameObject;";
|
|||
|
}
|
|||
|
}
|
|||
|
else if (tr.name.StartsWith("Content_"))
|
|||
|
{
|
|||
|
attStr = "internal Transform " + tr.name + ";";
|
|||
|
findStr = $"{tr.name} = transform.Find(\"{namePath}\");";
|
|||
|
}
|
|||
|
else if (tr.name.StartsWith("Ga_"))
|
|||
|
{
|
|||
|
attStr = "internal GameObject " + tr.name + ";";
|
|||
|
findStr = $"{tr.name} = transform.Find(\"{namePath}\").gameObject;";
|
|||
|
}
|
|||
|
else if (tr.name.StartsWith("Class_"))
|
|||
|
{
|
|||
|
string componName = tr.name.Replace("Class_", "");
|
|||
|
attStr = $"internal {componName} {tr.name};";
|
|||
|
findStr = $"{tr.name} = transform.Find(\"{namePath}\").GetComponent<{componName}>();";
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
GenerateAttData gen = null;
|
|||
|
foreach (var item in generateAttDatas)
|
|||
|
if (tr.name.StartsWith(item.prefix))
|
|||
|
{
|
|||
|
gen = item;
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
if (gen == null)
|
|||
|
{
|
|||
|
attStr = $"internal Transform {tr.name};";
|
|||
|
findStr = $"{tr.name} = transform.Find(\"{namePath}\");";
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
attStr = $"internal {gen.type} {tr.name};";
|
|||
|
findStr = $"{tr.name} = transform.Find(\"{namePath}\").GetComponent<{gen.type}>();";
|
|||
|
|
|||
|
foreach (var item_u in gen.usin)
|
|||
|
{
|
|||
|
if (!str_using.Contains(item_u))
|
|||
|
str_using += $"{item_u}\n";
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
tuples.Add(Tuple.Create(attStr, findStr));
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
bool isFind = true;
|
|||
|
foreach (var startW in notFindChild)
|
|||
|
if (tr.name.StartsWith(startW))
|
|||
|
{
|
|||
|
isFind = false;
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
if (isFind)
|
|||
|
for (int k = 0; k < tr.childCount; k++)
|
|||
|
action.Invoke(tr.GetChild(k));
|
|||
|
};
|
|||
|
|
|||
|
for (int i = 0; i < prefab.transform.childCount; i++)
|
|||
|
action(prefab.transform.GetChild(i));
|
|||
|
|
|||
|
StringBuilder atts = new StringBuilder();
|
|||
|
StringBuilder finds = new StringBuilder();
|
|||
|
|
|||
|
for (int j = 0; j < tuples.Count; j++)
|
|||
|
{
|
|||
|
var tuple = tuples[j];
|
|||
|
if (j == 0)
|
|||
|
{
|
|||
|
atts.Append(tuple.Item1);
|
|||
|
finds.Append(tuple.Item2);
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
atts.Append("\n " + tuple.Item1);
|
|||
|
finds.Append("\n " + tuple.Item2);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
str = str.Replace("[ATTRIBUTE]", atts.ToString());
|
|||
|
str = str.Replace("[FIND]", finds.ToString());
|
|||
|
str = str.Replace("[USING]", str_using);
|
|||
|
string scriptTarget2 = $"Assets/Scripts/HotUpdate/Game/UI/{systemName}/{panelName}/{panelName}_Generate.cs";
|
|||
|
|
|||
|
File.WriteAllText(scriptTarget2, str);
|
|||
|
|
|||
|
AssetDatabase.Refresh();
|
|||
|
}
|
|||
|
|
|||
|
DirectoryInfo GetDir(string uiName)
|
|||
|
{
|
|||
|
string sysFolder = Path.Combine(Application.dataPath, "Scripts/HotUpdate/Game/UI");
|
|||
|
var sysF = new DirectoryInfo(sysFolder);
|
|||
|
//sys
|
|||
|
foreach (var item in sysF.GetDirectories())
|
|||
|
{
|
|||
|
//主ui
|
|||
|
foreach (var item2 in item.GetDirectories())
|
|||
|
{
|
|||
|
if (item2.Name == uiName)
|
|||
|
{
|
|||
|
return item2;
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
//子ui
|
|||
|
DirectoryInfo[] allDirectories = item2.GetDirectories("*", SearchOption.AllDirectories);
|
|||
|
|
|||
|
foreach (var dir in allDirectories)
|
|||
|
if (uiName == dir.Name)
|
|||
|
return dir;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
return null;
|
|||
|
}
|
|||
|
|
|||
|
static string ConvertPath(string path)
|
|||
|
{
|
|||
|
string fixedPart = @"Assets\Scripts\HotUpdate\Game\UI";
|
|||
|
var parts = path.Split('\\');
|
|||
|
int startIndex = Array.IndexOf(parts, fixedPart.Split('\\').Last()) + 1;
|
|||
|
return startIndex > 0 && startIndex < parts.Length
|
|||
|
? string.Join(" → ", parts.Skip(startIndex))
|
|||
|
: "Path does not contain the specified structure.";
|
|||
|
}
|
|||
|
|
|||
|
void OpenPanel(bool isChild, string prefabDir)
|
|||
|
{
|
|||
|
if (!isChild) this.currentPanelScriptDir = null;
|
|||
|
string prefabPath = $"{prefabDir}/{panelName}.prefab";
|
|||
|
GameObject prefab = AssetDatabase.LoadAssetAtPath<GameObject>(prefabPath);
|
|||
|
Selection.activeObject = prefab;
|
|||
|
AssetDatabase.OpenAsset(prefab);
|
|||
|
|
|||
|
var sceneView = SceneView.sceneViews[0] as SceneView;
|
|||
|
// 激活主场景视图
|
|||
|
if (sceneView != null)
|
|||
|
sceneView.Focus();
|
|||
|
|
|||
|
if (!SceneView.lastActiveSceneView.in2DMode)
|
|||
|
// 切换到 2D 模式
|
|||
|
SceneView.lastActiveSceneView.in2DMode = true;
|
|||
|
|
|||
|
|
|||
|
//临时处理,解决描边不正常的bug
|
|||
|
var sta = PrefabStageUtility.GetCurrentPrefabStage();
|
|||
|
}
|
|||
|
|
|||
|
private void OnMainGUI()
|
|||
|
{
|
|||
|
if (currentPanelScriptDir != null)
|
|||
|
{
|
|||
|
GUILayout.Label(ConvertPath(currentPanelScriptDir.FullName));
|
|||
|
}
|
|||
|
|
|||
|
GUILayout.Label("输入面板名称", EditorStyles.boldLabel);
|
|||
|
this.panelName = PlayerPrefs.GetString("editor_panelName");
|
|||
|
//this.panelName = EditorGUILayout.TextField("面板名称: UI_", this.panelName);
|
|||
|
// 绘制自动补全输入框
|
|||
|
|
|||
|
string[] suggestions = GetCompletion();
|
|||
|
|
|||
|
bool isClick = false;
|
|||
|
bool isReturn = false;
|
|||
|
|
|||
|
bool isShowReturn = lastPanelName.Count > 1;
|
|||
|
|
|||
|
this.panelName = AutoCompleteTextField(this.panelName, suggestions, ref isClick, isShowReturn, ref isReturn);
|
|||
|
PlayerPrefs.SetString("editor_panelName", this.panelName);
|
|||
|
|
|||
|
if (string.IsNullOrEmpty(this.panelName))
|
|||
|
{
|
|||
|
EditorGUILayout.HelpBox("输入名称后创建/打开面板", MessageType.Info);
|
|||
|
//ShowTips();
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
string panelName = this.panelName;
|
|||
|
if (!this.panelName.StartsWith("UI_"))
|
|||
|
panelName = "UI_" + this.panelName;
|
|||
|
|
|||
|
bool isExa = false;
|
|||
|
if (panelName == "UI_Example")
|
|||
|
{
|
|||
|
GUILayout.Label("示例ui");
|
|||
|
isExa = true;
|
|||
|
}
|
|||
|
|
|||
|
string prefabDir = $"Assets/Art/UI/Panels/{panelName}";
|
|||
|
if (AssetDatabase.IsValidFolder(prefabDir))
|
|||
|
{
|
|||
|
bool isChild = false;
|
|||
|
|
|||
|
string sysFolder = Path.Combine(Application.dataPath, "Scripts/HotUpdate/Game/UI");
|
|||
|
var sysF = new DirectoryInfo(sysFolder);
|
|||
|
var dirs = sysF.GetDirectories();
|
|||
|
string[] dirNames = new string[dirs.Length];
|
|||
|
for (int i = 0; i < dirs.Length; i++)
|
|||
|
dirNames[i] = dirs[i].Name;
|
|||
|
|
|||
|
int index = -1;
|
|||
|
|
|||
|
for (int i = 0; i < dirs.Length; i++)
|
|||
|
{
|
|||
|
var dirs2 = dirs[i].GetDirectories();
|
|||
|
for (int j = 0; j < dirs2.Length; j++)
|
|||
|
if (dirs2[j].Name == panelName)
|
|||
|
{
|
|||
|
index = i;
|
|||
|
break;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
if (index == -1)
|
|||
|
isChild = true;
|
|||
|
|
|||
|
this.currentPanelScriptDir = GetDir(panelName);
|
|||
|
int newIndex;
|
|||
|
|
|||
|
if (!isChild)
|
|||
|
{
|
|||
|
newIndex = EditorGUILayout.Popup("系统目录:", index, dirNames);
|
|||
|
systemName = dirNames[index];
|
|||
|
|
|||
|
if (newIndex != index)
|
|||
|
{
|
|||
|
Debug.Log("修改目录为" + dirNames[newIndex]);
|
|||
|
string oldFolder = $"{Application.dataPath}/Scripts/HotUpdate/Game/UI/{systemName}/{panelName}";
|
|||
|
string newFolder = $"{Application.dataPath}/Scripts/HotUpdate/Game/UI/{dirNames[newIndex]}";
|
|||
|
MoveDirectory(oldFolder, newFolder);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
if (isReturn)
|
|||
|
{
|
|||
|
//打开上一个面板
|
|||
|
lastPanelName.RemoveAt(lastPanelName.Count - 1);
|
|||
|
var last = lastPanelName[lastPanelName.Count - 1];
|
|||
|
this.panelName = last.Item2;
|
|||
|
OpenPanel(last.Item1, last.Item3);
|
|||
|
PlayerPrefs.SetString("editor_panelName", this.panelName);
|
|||
|
}
|
|||
|
|
|||
|
if (CheckIsThis())
|
|||
|
{
|
|||
|
if (GUI_Button("生成属性"))
|
|||
|
{
|
|||
|
if (isChild)
|
|||
|
{
|
|||
|
GenerateAttribute_Child(currentPanelScriptDir);
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
GenerateAttribute(systemName);
|
|||
|
}
|
|||
|
|
|||
|
var sta = PrefabStageUtility.GetCurrentPrefabStage();
|
|||
|
AutoSetRaycast(sta.prefabContentsRoot.transform);
|
|||
|
}
|
|||
|
|
|||
|
//if (GUI_Button("关闭多余 Raycast Target"))
|
|||
|
//{
|
|||
|
// var sta = PrefabStageUtility.GetCurrentPrefabStage();
|
|||
|
// AutoSetRaycast(sta.prefabContentsRoot.transform);
|
|||
|
//}
|
|||
|
|
|||
|
if (isClick)
|
|||
|
{
|
|||
|
var sceneView = SceneView.sceneViews[0] as SceneView;
|
|||
|
// 激活主场景视图
|
|||
|
if (sceneView != null)
|
|||
|
sceneView.Focus();
|
|||
|
|
|||
|
if (!SceneView.lastActiveSceneView.in2DMode)
|
|||
|
// 切换到 2D 模式
|
|||
|
SceneView.lastActiveSceneView.in2DMode = true;
|
|||
|
}
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
if (GUI_Button("打开面板") || isClick)
|
|||
|
{
|
|||
|
if (panelName != "")
|
|||
|
if (lastPanelName.Count == 0 || lastPanelName[lastPanelName.Count - 1].Item2 != panelName)
|
|||
|
lastPanelName.Add(Tuple.Create(isChild, this.panelName, prefabDir));
|
|||
|
OpenPanel(isChild, prefabDir);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
if (GUI_Button("打开脚本"))
|
|||
|
{
|
|||
|
if (isChild)
|
|||
|
{
|
|||
|
string scriptTarget = Path.Combine(currentPanelScriptDir.FullName, $"{panelName}.cs");
|
|||
|
Application.OpenURL(scriptTarget);
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
var openPath = $"Scripts/HotUpdate/Game/UI/{systemName}/{panelName}/{panelName}.cs";
|
|||
|
string scriptTarget = Path.Combine(Application.dataPath, openPath).Replace('\\', '/');
|
|||
|
Application.OpenURL(scriptTarget);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
if (GUI_Button("创建子面板"))
|
|||
|
{
|
|||
|
int controlID = GUIUtility.GetControlID(FocusType.Keyboard);
|
|||
|
GUIUtility.keyboardControl = controlID; // 退出输入状态
|
|||
|
|
|||
|
//this.currentPanelScriptDir = new DirectoryInfo(currentPanelScriptDir.FullName);
|
|||
|
|
|||
|
IsCreateChild = true;
|
|||
|
}
|
|||
|
|
|||
|
if (isExa == false)
|
|||
|
if (GUI_Button("删除界面"))
|
|||
|
{
|
|||
|
bool confirm = EditorUtility.DisplayDialog("是否删除?", "是否删除" + panelName, "确定", "取消");
|
|||
|
if (confirm)
|
|||
|
{
|
|||
|
|
|||
|
Directory.Delete(prefabDir, true);
|
|||
|
File.Delete(prefabDir + ".meta");
|
|||
|
if (isChild)
|
|||
|
{
|
|||
|
if (currentPanelScriptDir != null)
|
|||
|
{
|
|||
|
File.Delete(currentPanelScriptDir.FullName + ".meta");
|
|||
|
currentPanelScriptDir.Delete(true);
|
|||
|
}
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
string scriptFolder = $"{Application.dataPath}/Scripts/HotUpdate/Game/UI/{systemName}/{panelName}";
|
|||
|
Directory.Delete(scriptFolder, true);
|
|||
|
File.Delete(scriptFolder + ".meta");
|
|||
|
}
|
|||
|
|
|||
|
AssetDatabase.Refresh();
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
GUILayout.Space(10);
|
|||
|
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
string sysFolder = Path.Combine(Application.dataPath, "Scripts/HotUpdate/Game/UI");
|
|||
|
var sysF = new DirectoryInfo(sysFolder);
|
|||
|
var dirs = sysF.GetDirectories();
|
|||
|
string[] dirNames = new string[dirs.Length];
|
|||
|
for (int i = 0; i < dirs.Length; i++)
|
|||
|
dirNames[i] = dirs[i].Name;
|
|||
|
|
|||
|
// 绘制下拉框控件,并将选定的选项索引保存到selectedOptionIndex变量中
|
|||
|
this.selectedOptionIndex = PlayerPrefs.GetInt("editor_system");
|
|||
|
selectedOptionIndex = EditorGUILayout.Popup("创建到目录:", selectedOptionIndex, dirNames);
|
|||
|
|
|||
|
PlayerPrefs.SetInt("editor_system", this.selectedOptionIndex);
|
|||
|
|
|||
|
if (GUI_Button("创建面板"))
|
|||
|
CreatePanel(dirNames[selectedOptionIndex]);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
public class GenerateAttData
|
|||
|
{
|
|||
|
public string prefix;
|
|||
|
public string description;
|
|||
|
public string type;
|
|||
|
public string[] usin;
|
|||
|
|
|||
|
public GenerateAttData(string prefix, string description, string type, params string[] usin)
|
|||
|
{
|
|||
|
this.prefix = prefix;
|
|||
|
this.description = description;
|
|||
|
this.type = type;
|
|||
|
this.usin = usin;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
#endif
|