AlicizaX/Client/Packages/com.alicizax.uxtool/Editor/UXGUI/SceneView/PrefabTab/PrefabTabs.cs

251 lines
8.9 KiB
C#
Raw Normal View History

2025-12-01 16:46:28 +08:00
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);
}
}
}