251 lines
8.9 KiB
C#
251 lines
8.9 KiB
C#
|
|
using UnityEditor;
|
||
|
|
using UnityEngine;
|
||
|
|
using UnityEngine.UIElements;
|
||
|
|
using System.Linq;
|
||
|
|
using System;
|
||
|
|
using System.IO;
|
||
|
|
using System.Collections.Generic;
|
||
|
|
using UnityEditor.SceneManagement;
|
||
|
|
using UXScroller = UnityEngine.UIElements.Scroller;
|
||
|
|
|
||
|
|
namespace Aliciza.UXTool
|
||
|
|
{
|
||
|
|
public static class PrefabTabs
|
||
|
|
{
|
||
|
|
public static readonly int m_maxCharacters = 20;
|
||
|
|
public static readonly int m_minCharacters = 13;
|
||
|
|
public static readonly int m_maxWidth = 150;
|
||
|
|
public static readonly int m_minWidth = 100;
|
||
|
|
|
||
|
|
public static VisualElement prefabTabsPanel;
|
||
|
|
private static ScrollView TabsList;
|
||
|
|
private static List<string> m_tabs;
|
||
|
|
private static string m_selectedTab;
|
||
|
|
private static SceneView sceneView = SceneView.lastActiveSceneView;
|
||
|
|
private static int width;
|
||
|
|
|
||
|
|
public static string SelectedGuid
|
||
|
|
{
|
||
|
|
get { return m_selectedTab; }
|
||
|
|
set
|
||
|
|
{
|
||
|
|
m_selectedTab = value;
|
||
|
|
EditorPrefs.SetString("AlicizaUXTool_SelectedTab", value); // 记录当前选中的Tab
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
[InitializeOnLoadMethod]
|
||
|
|
public static void Initialize()
|
||
|
|
{
|
||
|
|
UXDesinUtil.OnEnterDesignMode += RegisterEvents;
|
||
|
|
UXDesinUtil.OnExitDesignMode += UnRegisterEvents;
|
||
|
|
|
||
|
|
if (UXDesinUtil.InDesign)
|
||
|
|
{
|
||
|
|
RegisterEvents();
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
UnRegisterEvents();
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
private static void RegisterEvents()
|
||
|
|
{
|
||
|
|
PrefabStageUtils.OnEditRootReplaced += OnEditRootReplaced;
|
||
|
|
EditorApplication.delayCall += OnEditorLoaded;
|
||
|
|
UXPrefabTabsConfig.Instance.SyncTabs();
|
||
|
|
}
|
||
|
|
|
||
|
|
private static void UnRegisterEvents()
|
||
|
|
{
|
||
|
|
PrefabStageUtils.OnEditRootReplaced -= OnEditRootReplaced;
|
||
|
|
EditorApplication.delayCall -= OnEditorLoaded;
|
||
|
|
}
|
||
|
|
|
||
|
|
private static void OnEditorLoaded()
|
||
|
|
{
|
||
|
|
if (UXDesinUtil.InDesign)
|
||
|
|
{
|
||
|
|
CreateGUI();
|
||
|
|
RefreshTabs(false, 0);
|
||
|
|
OpenOrFallbackToLastValidTab();
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
private static void OnEditRootReplaced(string assetPath)
|
||
|
|
{
|
||
|
|
string guid = AssetDatabase.AssetPathToGUID(assetPath);
|
||
|
|
SelectedGuid = guid;
|
||
|
|
RefreshTabs(false, 0);
|
||
|
|
}
|
||
|
|
|
||
|
|
private static void CreateGUI()
|
||
|
|
{
|
||
|
|
sceneView = SceneView.lastActiveSceneView;
|
||
|
|
|
||
|
|
if (sceneView == null) return;
|
||
|
|
|
||
|
|
prefabTabsPanel = new VisualElement();
|
||
|
|
prefabTabsPanel.name = "Tabs";
|
||
|
|
prefabTabsPanel.style.height = new StyleLength(new Length(100, LengthUnit.Percent));
|
||
|
|
prefabTabsPanel.style.position = Position.Relative;
|
||
|
|
prefabTabsPanel.style.top = 0;
|
||
|
|
prefabTabsPanel.style.right = 0;
|
||
|
|
prefabTabsPanel.style.left = 0;
|
||
|
|
prefabTabsPanel.style.backgroundColor = new Color(48f / 255f, 48f / 255f, 48f / 255f); // rgb(48, 48, 48)
|
||
|
|
prefabTabsPanel.style.flexGrow = 0;
|
||
|
|
prefabTabsPanel.style.paddingRight = 0;
|
||
|
|
prefabTabsPanel.style.marginRight = 160;
|
||
|
|
|
||
|
|
TabsList = new ScrollView(ScrollViewMode.Horizontal);
|
||
|
|
TabsList.name = "TabsList";
|
||
|
|
TabsList.horizontalScrollerVisibility = ScrollerVisibility.AlwaysVisible;
|
||
|
|
TabsList.verticalScrollerVisibility = ScrollerVisibility.Hidden;
|
||
|
|
|
||
|
|
|
||
|
|
prefabTabsPanel.Add(TabsList);
|
||
|
|
|
||
|
|
prefabTabsPanel.style.flexGrow = 1;
|
||
|
|
prefabTabsPanel.style.height = Length.Percent(50);
|
||
|
|
prefabTabsPanel.contentContainer.RegisterCallback<MouseLeaveEvent>((e) =>
|
||
|
|
{
|
||
|
|
Vector2 old = TabsList.scrollOffset;
|
||
|
|
TabsList.scrollOffset = old;
|
||
|
|
width = m_tabs.Count == 0 ? m_minWidth : Math.Min(Math.Max(m_minWidth, (int)sceneView.position.width / m_tabs.Count), m_maxWidth);
|
||
|
|
RefreshTabs(false, 0);
|
||
|
|
});
|
||
|
|
UXScroller scroller = TabsList.horizontalScroller;
|
||
|
|
scroller.Remove(scroller.lowButton);
|
||
|
|
scroller.Remove(scroller.highButton);
|
||
|
|
scroller.slider.style.height = 4;
|
||
|
|
scroller.slider.style.marginBottom = 0;
|
||
|
|
scroller.slider.style.paddingBottom = 0;
|
||
|
|
scroller.slider.style.marginLeft = scroller.slider.style.marginRight = 0;
|
||
|
|
scroller.style.height = 5;
|
||
|
|
scroller.style.bottom = 0;
|
||
|
|
scroller.style.marginBottom = 0;
|
||
|
|
|
||
|
|
var parent = sceneView.rootVisualElement.parent.parent.parent.parent.parent.Q<IMGUIContainer>();
|
||
|
|
if (parent != null) parent.Add(prefabTabsPanel);
|
||
|
|
parent.style.flexShrink = 1;
|
||
|
|
parent.style.width = Length.Percent(100);
|
||
|
|
parent.style.flexGrow = 0.08f;
|
||
|
|
parent.style.height = Length.Percent(5);
|
||
|
|
|
||
|
|
m_tabs = UXPrefabTabsConfig.Instance.tabs;
|
||
|
|
m_selectedTab = EditorPrefs.GetString("AlicizaUXTool_SelectedTab", string.Empty);
|
||
|
|
if (m_tabs.Find(p => p == m_selectedTab) == null) m_selectedTab = string.Empty;
|
||
|
|
RefreshTabs(false, 0); // 初始化时刷新 Tabs
|
||
|
|
}
|
||
|
|
|
||
|
|
public static void RefreshTabs(bool isclose, int width)
|
||
|
|
{
|
||
|
|
if (prefabTabsPanel == null) return;
|
||
|
|
#if UNITY_2021_3_OR_NEWER
|
||
|
|
prefabTabsPanel.style.top = 0;
|
||
|
|
#else
|
||
|
|
prefabTabsPanel.style.top = string.IsNullOrEmpty(m_selectedTab) ? 21 : 46;
|
||
|
|
#endif
|
||
|
|
bool flag = TabsList.contentContainer.childCount == m_tabs.Count;
|
||
|
|
TabsList.Clear();
|
||
|
|
Button selectButton = null;
|
||
|
|
foreach (var item in m_tabs)
|
||
|
|
{
|
||
|
|
string path = AssetDatabase.GUIDToAssetPath(item);
|
||
|
|
if (path != "" && File.Exists(path))
|
||
|
|
{
|
||
|
|
var tab = new PrefabSingleTab(new FileInfo(path), item, m_tabs.Count, isclose, width);
|
||
|
|
if (item == m_selectedTab)
|
||
|
|
{
|
||
|
|
tab.visual.style.backgroundColor = new Color(95f / 255, 95f / 255, 95f / 255, 1);
|
||
|
|
selectButton = tab.visual;
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
tab.visual.style.backgroundColor = new Color(60f / 255, 60f / 255, 60f / 255, 1);
|
||
|
|
}
|
||
|
|
|
||
|
|
TabsList.Add(tab.visual);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
if (selectButton != null)
|
||
|
|
{
|
||
|
|
if (flag)
|
||
|
|
{
|
||
|
|
selectButton.RegisterCallback<GeometryChangedEvent, VisualElement>(FirstLayoutCallback, selectButton);
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
TabsList.contentContainer.RegisterCallback<GeometryChangedEvent, VisualElement>(FirstLayoutCallback, selectButton);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
UXPrefabTabsConfig.Instance.tabs = m_tabs; // 保存当前 Tabs 状态
|
||
|
|
UXPrefabTabsConfig.Save(); // 保存到磁盘
|
||
|
|
}
|
||
|
|
|
||
|
|
private static void OpenOrFallbackToLastValidTab()
|
||
|
|
{
|
||
|
|
// 尝试打开当前选中的GUID
|
||
|
|
if (!string.IsNullOrEmpty(m_selectedTab) && m_tabs.Contains(m_selectedTab))
|
||
|
|
{
|
||
|
|
PrefabStageUtils.SwitchStage(AssetDatabase.GUIDToAssetPath(m_selectedTab));
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
// 移除不存在的GUID并选中最后一个有效的
|
||
|
|
m_tabs.RemoveAll(guid =>
|
||
|
|
{
|
||
|
|
string path = AssetDatabase.GUIDToAssetPath(guid);
|
||
|
|
return string.IsNullOrEmpty(path) || !File.Exists(path);
|
||
|
|
});
|
||
|
|
|
||
|
|
if (m_tabs.Count > 0)
|
||
|
|
{
|
||
|
|
m_selectedTab = m_tabs.Last();
|
||
|
|
PrefabStageUtils.SwitchStage(AssetDatabase.GUIDToAssetPath(m_selectedTab));
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
m_selectedTab = string.Empty;
|
||
|
|
PrefabStageUtils.OpenDefaultStage();
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
RefreshTabs(false, 0);
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
public static void OpenTab(string guid, bool replaceRoot)
|
||
|
|
{
|
||
|
|
SelectedGuid = guid;
|
||
|
|
if (replaceRoot)
|
||
|
|
{
|
||
|
|
PrefabStageUtils.SwitchStage(AssetDatabase.GUIDToAssetPath(guid));
|
||
|
|
}
|
||
|
|
|
||
|
|
if (!m_tabs.Contains(guid))
|
||
|
|
{
|
||
|
|
m_tabs.Add(guid);
|
||
|
|
width = Math.Min(Math.Max(m_minWidth, (int)sceneView.position.width / m_tabs.Count), m_maxWidth);
|
||
|
|
}
|
||
|
|
|
||
|
|
RefreshTabs(false, 0);
|
||
|
|
}
|
||
|
|
|
||
|
|
public static void CloseTab(string guid)
|
||
|
|
{
|
||
|
|
m_tabs.Remove(guid);
|
||
|
|
OpenOrFallbackToLastValidTab();
|
||
|
|
}
|
||
|
|
|
||
|
|
private static void FirstLayoutCallback(GeometryChangedEvent evt, VisualElement v)
|
||
|
|
{
|
||
|
|
if (!TabsList.Contains(v)) return;
|
||
|
|
TabsList.ScrollTo(v);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|