using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Text; using TyphoonGUIStyle; using UnityEditor; using UnityEngine; using Object = UnityEngine.Object; namespace TyphoonUI { public class ExportNodesWindow : EditorWindow { private static GUIStyle _label = null; private GUIStyle Label { get { if (_label == null) { _label = new GUIStyle(Styles.BoldLabel); _label.fontStyle = FontStyle.Normal; } return _label; } } /*节点状态*/ public class NodeStatus { public Object Node; public bool Exported; public NodeStatus(Object node, bool exported) { Node = node; Exported = exported; } } /*导出条目*/ public class ExportItemInfo { public UIObject UIObject; public List Status = new List(); public ExportItemInfo(UIObject view, GameObject select) { UIObject = view; var hash = view.GetValidateNodesHashList(); var nodes = new List(); nodes.Add(select); var coms = select.GetComponents(); foreach (var com in coms) { nodes.Add(com); } foreach (var node in nodes) { var exported = hash.Contains(node); Status.Add(new NodeStatus(node, exported)); } } public ExportItemInfo(UIObject view, UIObject select) { UIObject = view; Status.Add(new NodeStatus(select, view.Contains(select))); } public void ExportAll() { foreach (var element in Status) { element.Exported = true; } } public void Clear() { foreach (var element in Status) { element.Exported = false; } } } public static void Open(GameObject obj) { _data = CalculateExportInfo(obj); var win = GetWindow(); win.titleContent = new GUIContent("导出"); win.minSize = new Vector2(300, 600); var mousePos = Vector2.zero; try { mousePos = Event.current.mousePosition; } catch (Exception e) { } var guiPoint = GUIUtility.GUIToScreenPoint(mousePos); var sh = Screen.height; var sw = Screen.width; win.Show(); var rect = win.position; rect.position = guiPoint; rect.x += 20; rect.y += 20; win.position = rect; win.Focus(); } private static List _data; private Dictionary _icons = new Dictionary(); private bool _lostFocus = false; private Vector2 _scroll; public void OnGUI() { var rect = position; rect.x = 0; rect.y = 0; var rectContent = rect; rectContent.width -= 8; rectContent.height -= 8; rectContent.center = rect.center; GUILayout.BeginArea(rectContent); _scroll = GUILayout.BeginScrollView(_scroll); if (_data != null) { foreach (var data in _data) { GUILayout.BeginHorizontal(); var titleRect = GUIDrawer.DrawTitleLabel($"导出到:{data.UIObject.gameObject.name}", GUILayout.Height(28)); var btnExportAll = titleRect; btnExportAll.height -= 4; btnExportAll.width = 60; btnExportAll.center = titleRect.center; btnExportAll.x = titleRect.xMax - btnExportAll.width; btnExportAll.x -= 2; if (GUI.Button(btnExportAll, "导出全部", Styles.Btn)) { data.ExportAll(); } var btnClear = btnExportAll; btnClear.x = btnExportAll.xMin - btnClear.width - 2; if (GUI.Button(btnClear, "清空导出", Styles.Btn)) { data.Clear(); } var pingBtn = titleRect; pingBtn.width = titleRect.xMax - btnClear.x; if (GUI.Button(pingBtn, "", GUIStyle.none)) { EditorGUIUtility.PingObject(data.UIObject.gameObject); } GUILayout.EndHorizontal(); var status = data.Status; foreach (var element in status) { var click = DrawExportNodeButton(element); if (click) { element.Exported = !element.Exported; } } GUILayout.Space(10); } if (_data.Count <= 0) { GUILayout.Label(new GUIContent("找不到UIObject组件,无有效导出节点\n请添加UIObject组件", Styles.IconInfo), Styles.HelpBox); } } else { GUILayout.Label(new GUIContent("意外错误,请重试", Styles.IconWarning), Styles.HelpBox); } GUILayout.EndScrollView(); GUILayout.EndArea(); if (_lostFocus) { //应用导出 ApplyInfos(_data); Close(); } Repaint(); } private void OnLostFocus() { _lostFocus = true; } private Texture GetIcon(Object obj) { if (!_icons.ContainsKey(obj)) { _icons.Add(obj, EditorGUIUtility.ObjectContent(obj, obj.GetType()).image); } return _icons[obj]; } private bool DrawExportNodeButton(NodeStatus element) { var result = GUILayout.Button("", GUILayout.Height(32)); var last = GUILayoutUtility.GetLastRect(); if (element.Exported) { EditorGUI.DrawRect(last, new Color(0.41f, 0.65f, 0.29f, 0.5f)); } var iconRect = last; iconRect.width = 22; iconRect.height = 22; iconRect.center = last.center; iconRect.x = last.x + 4; GUI.Label(iconRect, GetIcon(element.Node)); var toggleRect = last; toggleRect.height -= 4; toggleRect.width = toggleRect.height; toggleRect.center = last.center; toggleRect.x = last.xMax - toggleRect.width; toggleRect.x -= 2; if (element.Exported) { GUI.Label(toggleRect, EditorIcons.check_mark); } var labRect = last; labRect.width = toggleRect.xMin - iconRect.xMax; labRect.width -= 8; labRect.height = 22; labRect.center = last.center; labRect.x = iconRect.xMax; labRect.x += 4; var style = element.Exported ? Styles.BoldLabel : Label; GUI.Label(labRect, $"{element.Node.name} ({element.Node.GetType().Name})", style); return result; } private static List CalculateExportInfo(GameObject obj) { var result = new List(); var parentUIObject = GetParentUIObjects(obj); foreach (var element in parentUIObject) { result.Add(new ExportItemInfo(element, obj)); } return result; } //应用变化 private static void ApplyInfos(List infos) { if (infos != null) { foreach (var info in infos) { info.UIObject.Modify(info.Status); } } } /*获取父节点*/ private static List GetParentUIObjects(GameObject check) { var hash = new HashSet(); var node = check.transform; while (node != null) { var obj = node.GetComponent(); if (obj != null) { hash.Add(obj); } node = node.parent; } return hash.ToList(); } } }