DragonECS-Unity/src/Tools/DragonDocs/Editors/DragonDocsWindow.cs
2025-05-10 11:45:24 +08:00

502 lines
19 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#if UNITY_EDITOR
using DCFApixels.DragonECS.Unity.Editors;
using DCFApixels.DragonECS.Unity.Internal;
using System;
using UnityEditor;
using UnityEngine;
namespace DCFApixels.DragonECS.Unity.Docs.Editors
{
internal class DragonDocsWindow : EditorWindow
{
public const string TITLE = "Documentation";
[MenuItem("Tools/" + EcsConsts.FRAMEWORK_NAME + "/" + TITLE)]
static void Open()
{
var wnd = GetWindow<DragonDocsWindow>();
wnd.titleContent = new GUIContent(TITLE);
wnd.minSize = new Vector2(100f, 120f);
wnd.Show();
}
private int _selectedIndex = 0;
private Vector2 ButtonsScrolPosition;
private Vector2 DataScrolPosition;
private Vector2 _buttonsWidthDragStartPos = Vector2.zero;
private float _buttonsWidthDragStartValue = 200f;
private float _buttonsWidth = 200f;
private DragState _dragState;
private enum DragState
{
None,
Init,
Update,
}
private DragonDocsPrefs Prefs { get { return DragonDocsPrefs.instance; } }
private static bool IsShowHidden
{
get { return UserSettingsPrefs.instance.IsShowHidden; }
set { UserSettingsPrefs.instance.IsShowHidden = value; }
}
private static bool IsUseCustomNames
{
get { return UserSettingsPrefs.instance.IsUseCustomNames; }
set { UserSettingsPrefs.instance.IsUseCustomNames = value; }
}
private bool _searchingSampleChanged = false;
private string _searchingSampleEnter = string.Empty;
private string _searchingSample = string.Empty;
private bool[] _searchingHideMetaMap = System.Array.Empty<bool>();
private bool[] _searchingHideGroupMap = System.Array.Empty<bool>();
private void OnGUI()
{
Event current = Event.current;
DragonDocs docs = DragonDocsPrefs.instance.Docs;
if (docs == null || docs.Metas.IsEmpty)
{
docs = DragonDocs.Generate();
DragonDocsPrefs.instance.Save(docs);
}
var metas = docs.Metas;
var infos = DragonDocsPrefs.instance.Infos;
if (_searchingHideMetaMap.Length < metas.Length)
{
System.Array.Resize(ref _searchingHideMetaMap, metas.Length);
}
if (_searchingHideGroupMap.Length < infos.Length)
{
System.Array.Resize(ref _searchingHideGroupMap, DragonDocsPrefs.instance.Infos.Length);
}
if (_selectedIndex < 0 || _selectedIndex >= infos.Length)
{
_selectedIndex = 0;
}
DrawToolbar();
GUILayout.BeginHorizontal(GUILayout.ExpandHeight(true));
MetaGroupInfo selectedGroupInfo;
using (EcsGUI.Layout.BeginScrollView(ref ButtonsScrolPosition, UnityEditorUtility.GetClearBackgrounStyle(), GUILayout.Width(_buttonsWidth)))
{
selectedGroupInfo = DrawGroups();
}
DrawDragger();
GUILayout.Space(EditorGUIUtility.standardVerticalSpacing * -2f);
using (EcsGUI.Layout.BeginScrollView(ref DataScrolPosition, UnityEditorUtility.GetTransperentBlackBackgrounStyle(), GUILayout.ExpandWidth(true)))
{
DrawSelectedGroupMeta(selectedGroupInfo);
}
//GUILayout.Space(EditorGUIUtility.standardVerticalSpacing * -2f);
GUILayout.EndHorizontal();
Rect r = GUILayoutUtility.GetLastRect();
float h = r.height;
r.height = EditorGUIUtility.standardVerticalSpacing;
//EditorGUI.DrawRect(r, new Color(0, 0, 0, 0.3f));
r.y += h;
EditorGUI.DrawRect(r, new Color(0, 0, 0, 0.3f));
GUI.enabled = true;
if (_selectedIndex >= 0 && _selectedIndex < infos.Length)
{
GUILayout.Label(infos[_selectedIndex].Path);
}
}
private void DrawToolbar()
{
using (EcsGUI.SetColor(GUI.color * 0.8f))
GUILayout.BeginHorizontal(EditorStyles.toolbar);
GUILayout.Space(EditorGUIUtility.standardVerticalSpacing * 2f);
if (GUILayout.Button("Update", EditorStyles.toolbarButton, GUILayout.Width(80f)))
{
DragonDocs docs = DragonDocs.Generate();
DragonDocsPrefs.instance.Save(docs);
}
if (EcsGUI.Layout.IconButton(IsShowHidden ? Icons.Instance.VisibilityIconOn : Icons.Instance.VisibilityIconOff, 0f, IsShowHidden ? "Show Hidden" : "Don't Show Hidden", EditorStyles.toolbarButton, GUILayout.Width(EditorGUIUtility.singleLineHeight * 1.6f)))
{
IsShowHidden = !IsShowHidden;
}
if (EcsGUI.Layout.IconButton(IsUseCustomNames ? Icons.Instance.LabelIconMeta : Icons.Instance.LabelIconType, 1f, IsUseCustomNames ? "Use Meta Name" : "Use Type Name", EditorStyles.toolbarButton, GUILayout.Width(EditorGUIUtility.singleLineHeight * 1.6f)))
{
IsUseCustomNames = !IsUseCustomNames;
}
GUILayout.Label("");
EditorGUI.BeginChangeCheck();
_searchingSampleEnter = EditorGUILayout.TextField(_searchingSampleEnter, EditorStyles.toolbarSearchField, GUILayout.ExpandHeight(true), GUILayout.MaxWidth(200f));
if (EditorGUI.EndChangeCheck())
{
_searchingSampleChanged = true;
}
if ((_searchingSampleChanged && Event.current.keyCode == KeyCode.Return) ||
EcsGUI.Layout.IconButton(Icons.Instance.SearchIcon, 1f, null, EditorStyles.toolbarButton, GUILayout.ExpandHeight(true), GUILayout.Width(EditorGUIUtility.singleLineHeight * 1.6f)))
{
Searh();
}
GUILayout.Space(EditorGUIUtility.standardVerticalSpacing * 2f);
GUILayout.EndHorizontal();
GUILayout.Space(EditorGUIUtility.standardVerticalSpacing * -2f);
}
private void Searh()
{
_searchingSample = _searchingSampleEnter;
_searchingSampleChanged = false;
DragonDocs docs = DragonDocsPrefs.instance.Docs;
var metas = docs.Metas;
if (_searchingSample.Length <= 0)
{
var infos = DragonDocsPrefs.instance.Infos;
var isExpands = DragonDocsPrefs.instance.IsExpands;
for (int i = 0; i < _searchingHideMetaMap.Length; i++)
{
_searchingHideMetaMap[i] = false;
}
for (int i = 0; i < _searchingHideGroupMap.Length; i++)
{
_searchingHideGroupMap[i] = false;
}
{
int i = _selectedIndex;
var info = infos[i];
int depth = info.Depth;
while (depth > 0)
{
i--;
info = infos[i];
if (info.Depth >= depth)
{
continue;
}
depth = info.Depth;
isExpands[i] = true;
}
}
}
else
{
var infos = DragonDocsPrefs.instance.Infos;
for (int i = 0; i < infos.Length; i++)
{
var info = infos[i];
int visibleCount = 0;
bool isUseCustomNames = IsUseCustomNames;
for (int j = info.StartIndex, jMax = j + info.Length; j < jMax; j++)
{
var b = (isUseCustomNames ? metas[j].Name : metas[j].TypeName).Contains(_searchingSample, System.StringComparison.InvariantCultureIgnoreCase);
_searchingHideMetaMap[j] = !b;
if (b)
{
visibleCount++;
}
}
_searchingHideGroupMap[i] = visibleCount == 0;
}
}
}
private void DrawSelectedGroupMeta(MetaGroupInfo info)
{
bool hide = IsShowHidden == false;
var metas = Prefs.Docs.Metas;
int iMax = info.Length;
for (int i = 0, j = info.StartIndex; i < iMax; j++)
{
if (_searchingHideMetaMap[j] || (metas[j]._isHidden && hide))
{
iMax--;
}
else
{
DrawMeta(metas[j], i, 12);
i++;
}
}
if (iMax <= 0)
{
GUILayout.Label(info.Length <= 0 ? "empty group" : "there are hidden items", EditorStyles.centeredGreyMiniLabel, GUILayout.ExpandHeight(true), GUILayout.ExpandWidth(true));
}
}
private void DrawMeta(DragonDocsMeta meta, int index, int total)
{
using (EcsGUI.SetIndentLevel(0))
{
Color panelColor = EcsGUI.SelectPanelColor(meta.Color.ToMetaColor(), meta.IsCustomColor, index, total).Desaturate(EscEditorConsts.COMPONENT_DRAWER_DESATURATE);
Color alphaPanelColor = panelColor;
alphaPanelColor.a = EscEditorConsts.COMPONENT_DRAWER_ALPHA;
using (EcsGUI.Layout.BeginVertical(alphaPanelColor))
{
GUILayout.Space(1f);
//draw title block
using (EcsGUI.Layout.BeginHorizontal())
{
GUILayout.TextArea(IsUseCustomNames ? meta.Name : meta.TypeName, EditorStyles.boldLabel, GUILayout.ExpandWidth(false));
if (meta.TryGetSourceType(out System.Type targetType) && ScriptsCache.TryGetScriptAsset(targetType.ToMeta(), out MonoScript script))
{
EcsGUI.Layout.ScriptAssetButton(script, GUILayout.Width(18f));
}
if (meta.IsCustomName)
{
using (EcsGUI.SetAlpha(0.64f)) using (EcsGUI.SetAlignment(GUI.skin.label, TextAnchor.MiddleRight))
{
GUILayout.TextArea(IsUseCustomNames ? meta.TypeName : meta.Name, GUI.skin.label);
}
}
else
{
GUILayout.Label("");
}
if (string.IsNullOrEmpty(meta.MetaID) == false)
{
GUILayout.Space(-EditorGUIUtility.standardVerticalSpacing);
EcsGUI.Layout.CopyMetaIDButton(meta.MetaID, GUILayout.Width(18f));
}
}
void DrawLine()
{
Rect lineRect = GUILayoutUtility.GetLastRect(); ;
lineRect.yMin = lineRect.yMax;
lineRect.yMax += 1f;
lineRect.y += 5f;
EditorGUI.DrawRect(lineRect, new Color(1, 1, 1, 0.12f));
}
bool isWithMetaID = string.IsNullOrEmpty(meta.MetaID) == false;
//draw description block
if (string.IsNullOrEmpty(meta.Description) == false)
{
DrawLine();
GUILayout.Space(7f);
GUILayout.TextArea(meta.Description, EditorStyles.wordWrappedLabel);
}
//draw tags block
if (meta._tags.Length > 0)
{
DrawLine();
GUILayout.Space(3f);
var tagsstring = string.Join(',', meta._tags);
using (EcsGUI.SetAlpha(0.5f))
{
GUILayout.TextArea(tagsstring, EditorStyles.wordWrappedMiniLabel);
}
}
GUILayout.Space(1f);
}
}
}
private MetaGroupInfo DrawGroups()
{
Event current = Event.current;
MetaGroupInfo result = new MetaGroupInfo("NO_NAME", "NO_NAME", 0, 0, 0);
var infos = Prefs.Infos;
var isExpands = Prefs.IsExpands;
using (EcsGUI.SetIndentLevel(0))
{
int clippingDepth = int.MaxValue;
for (int i = 0; i < infos.Length; i++)
{
if (infos.Length > _searchingHideGroupMap.Length)
{
Array.Resize(ref _searchingHideGroupMap, infos.Length);
}
if (_searchingHideGroupMap[i]) { continue; }
var groupInfo = infos[i];
if (i == _selectedIndex)
{
result = groupInfo;
}
if (_searchingSample.Length == 0 && groupInfo.Depth > clippingDepth)
{
continue;
}
else
{
clippingDepth = int.MaxValue;
}
if (_searchingSample.Length == 0)
{
EcsGUI.IndentLevel = groupInfo.Depth;
}
GUIContent label = UnityEditorUtility.GetLabel(_searchingSample.Length == 0 ? groupInfo.Name : groupInfo.Path);
Rect r = GUILayoutUtility.GetRect(label, EditorStyles.foldout);
if (i == _selectedIndex)
{
EditorGUI.DrawRect(r, new Color(0.12f, 0.5f, 1f, 0.40f));
}
using (EcsGUI.SetColor(0, 0, 0, 0)) using (EcsGUI.Disable) { GUI.Button(r, ""); }
bool isClick = false;
if (EcsGUI.HitTest(r))
{
EditorGUI.DrawRect(r, new Color(1f, 1f, 1f, 0.12f));
if (current.type == EventType.MouseUp)
{
isClick = true;
//_selectedIndex = i;
//current.Use();
}
}
if (_searchingSample.Length != 0 || (i + 1 == infos.Length || infos[i + 1].Depth <= groupInfo.Depth))
{
using (EcsGUI.SetBackgroundColor(0, 0, 0, 0))
{
EditorGUI.Foldout(r, false, label, EditorStyles.foldout);
}
}
else
{
EditorGUI.BeginChangeCheck();
isExpands[i] = EditorGUI.Foldout(r, isExpands[i], label, EditorStyles.foldout);
if (EditorGUI.EndChangeCheck())
{
isClick = false;
}
}
if (isClick)
{
_selectedIndex = i;
current.Use();
}
if (isExpands[i] == false)
{
clippingDepth = groupInfo.Depth;
}
if (groupInfo.Length > 0)
{
r.xMax = r.xMin;
r.xMin -= 2f;
r.yMin += 1;
r.yMax -= 1;
EditorGUI.DrawRect(r, new Color(0.2f, 0.6f, 1f));
}
}
}
return result;
}
private void DrawDragger()
{
const float DRAG_RESIZE_WIDTH = 4f;
Rect rect = GUILayoutUtility.GetLastRect();
float m = DRAG_RESIZE_WIDTH;
if (_dragState != DragState.None)
{
m *= 2f;
}
rect.xMin = rect.xMax;
rect.x -= m / 2f;
rect.width = m;
EditorGUI.DrawRect(rect.AddPadding(1f, 0), new Color(0, 0, 0, 0.3f));
Event current = Event.current;
switch (current.type)
{
case EventType.MouseDown:
if (EcsGUI.HitTest(rect))
{
_buttonsWidthDragStartPos = current.mousePosition;
_buttonsWidthDragStartValue = _buttonsWidth;
_dragState = DragState.Init;
current.Use();
}
break;
case EventType.MouseUp:
if (_dragState != DragState.None)
{
_dragState = DragState.None;
current.Use();
}
break;
case EventType.MouseDrag:
{
switch (_dragState)
{
case DragState.Init:
{
if ((Event.current.mousePosition - _buttonsWidthDragStartPos).sqrMagnitude > 16f)
{
_dragState = DragState.Update;
}
}
break;
case DragState.Update:
{
_buttonsWidth = _buttonsWidthDragStartValue + (Event.current.mousePosition.x - _buttonsWidthDragStartPos.x);
_buttonsWidth = Mathf.Max(6f, _buttonsWidth);
current.Use();//TODO кажется это можно использовать вместо лайфахака с кнопкой для моментальной реакции пир наведении курсора для кнопок с иконками
}
break;
}
}
break;
case EventType.Repaint:
{
EditorGUIUtility.AddCursorRect(rect, MouseCursor.SlideArrow);
}
break;
}
}
}
}
#endif