You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

259 lines
7.3 KiB
C#

2 months ago
namespace Example
{
using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using UnityEngine;
using UnityEngine.UIElements;
using UnityEditor;
using UnityEditor.SceneManagement;
[InitializeOnLoad]
public static partial class ToolbarUtility
{
// PRIVATE MEMBERS
private static ScriptableObject _mainToolbar;
private static int _mainToolbarInstanceID;
private static VisualElement _leftToolbar;
private static VisualElement _rightToolbar;
private static string _currentScene;
private static string[] _scenePaths;
private static string[] _sceneNames;
// CONSTRUCTORS
static ToolbarUtility()
{
EditorApplication.update -= Update;
EditorApplication.update += Update;
}
// PUBLIC METHODS
public static void InvalidateToolbar()
{
_mainToolbarInstanceID += 1;
}
// PARTIAL METHODS
static partial void OnUpdate();
static partial void OnLeftToolbarAttached(VisualElement toolbar);
static partial void OnRightToolbarAttached(VisualElement toolbar);
// PRIVATE METHODS
private static void Update()
{
if (_scenePaths == null || _scenePaths.Length != EditorBuildSettings.scenes.Length)
{
List<string> scenePaths = new List<string>();
List<string> sceneNames = new List<string>();
foreach (EditorBuildSettingsScene scene in EditorBuildSettings.scenes)
{
if (scene.path == null || scene.path.StartsWith("Assets") == false)
continue;
string scenePath = Application.dataPath + scene.path.Substring(6);
scenePaths.Add(scenePath);
sceneNames.Add(Path.GetFileNameWithoutExtension(scenePath));
}
_scenePaths = scenePaths.ToArray();
_sceneNames = sceneNames.ToArray();
InvalidateToolbar();
}
string currentScene = EditorSceneManager.GetActiveScene().name;
if (_currentScene != currentScene)
{
_currentScene = currentScene;
InvalidateToolbar();
}
if (_mainToolbar == null)
{
UnityEngine.Object[] toolbars = Resources.FindObjectsOfTypeAll(typeof(Editor).Assembly.GetType("UnityEditor.Toolbar"));
_mainToolbar = toolbars.Length > 0 ? (ScriptableObject)toolbars[0] : null;
}
if (_mainToolbar != null)
{
int mainToolbarInstanceID = _mainToolbar.GetInstanceID();
if (mainToolbarInstanceID != _mainToolbarInstanceID)
{
_mainToolbarInstanceID = mainToolbarInstanceID;
RefreshToolbar(ref _leftToolbar, "ToolbarZoneLeftAlign", FlexDirection.Row, LeftToolbarAttached);
RefreshToolbar(ref _rightToolbar, "ToolbarZoneRightAlign", FlexDirection.RowReverse, RightToolbarAttached);
}
}
OnUpdate();
}
private static void RefreshToolbar(ref VisualElement toolbar, string toolbarID, FlexDirection direction, Action<VisualElement> onAttachToMainToolbar)
{
if (toolbar != null)
{
toolbar.RemoveFromHierarchy();
toolbar = null;
}
FieldInfo root = _mainToolbar.GetType().GetField("m_Root", BindingFlags.NonPublic | BindingFlags.Instance);
if (root != null)
{
object rawRoot = root.GetValue(_mainToolbar);
if (rawRoot != null)
{
VisualElement toolbarRoot = rawRoot as VisualElement;
VisualElement toolbarZone = toolbarRoot.Q(toolbarID);
toolbar = new VisualElement()
{
style =
{
flexGrow = 1,
flexDirection = direction,
}
};
toolbar.Add(new VisualElement()
{
style =
{
flexGrow = 1,
}
});
toolbarZone.Add(toolbar);
onAttachToMainToolbar(toolbar);
}
}
}
private static void LeftToolbarAttached(VisualElement toolbar)
{
OnLeftToolbarAttached(toolbar);
}
private static void RightToolbarAttached(VisualElement toolbar)
{
OnRightToolbarAttached(toolbar);
toolbar.Add(CreateToolbarButton(ShowPackageManager, "Package Manager", "Packages"));
toolbar.Add(CreateToolbarButton(ShowSettings, "Settings", "Settings"));
// toolbar.Add(CreateToolbarButton(ShowRunnerControls, "d_SceneViewCamera@2x", "Fusion Controls"));
toolbar.Add(CreateToolbarButton(ShowFusionConfig, "ScriptableObject Icon", "Fusion Config"));
toolbar.Add(CreateToolbarButton(ShowScenes, "BuildSettings.Editor", string.IsNullOrEmpty(_currentScene) == false ? _currentScene : "Scene"));
}
private static void ShowScenes()
{
GenericMenu menu = new GenericMenu();
string currentPrefix = default;
for (int i = 0; i < _sceneNames.Length; ++i)
{
string scenePath = _scenePaths[i];
if (scenePath != null)
{
int prefixIndex = scenePath.IndexOf("/Assets/Example/");
if (prefixIndex >= 0)
{
string prefix = scenePath.Substring(prefixIndex, 18);
if (currentPrefix != default && currentPrefix != prefix)
{
menu.AddSeparator("");
}
currentPrefix = prefix;
}
}
string sceenName = _sceneNames[i];
menu.AddItem(new GUIContent(sceenName), sceenName == _currentScene, (sceneIndex) =>
{
if (EditorSceneManager.SaveCurrentModifiedScenesIfUserWantsTo() == true)
{
EditorSceneManager.OpenScene(_scenePaths[(int)sceneIndex], OpenSceneMode.Single);
InvalidateToolbar();
}
}, i);
}
menu.ShowAsContext();
}
private static void ShowFusionConfig()
{
EditorApplication.ExecuteMenuItem("Tools/Fusion/Network Project Config");
}
private static void ShowRunnerControls()
{
EditorApplication.ExecuteMenuItem("Tools/Fusion/Windows/Network Runner Controls");
}
private static void ShowSettings()
{
GenericMenu menu = new GenericMenu();
menu.AddItem(new GUIContent("Project"), false, () => EditorApplication.ExecuteMenuItem("Edit/Project Settings..."));
menu.AddItem(new GUIContent("Preferences"), false, () => EditorApplication.ExecuteMenuItem("Edit/Preferences..."));
menu.AddSeparator("");
menu.AddItem(new GUIContent("Realtime Settings"), false, () => EditorApplication.ExecuteMenuItem("Tools/Fusion/Realtime Settings"));
menu.AddItem(new GUIContent("Network Project Config"), false, () => EditorApplication.ExecuteMenuItem("Tools/Fusion/Network Project Config"));
menu.ShowAsContext();
}
private static void ShowPackageManager()
{
UnityEditor.PackageManager.UI.Window.Open("");
}
private static VisualElement CreateToolbarButton(Action onClick, string icon = null, string text = null, Color color = default)
{
Button buttonElement = new Button(onClick);
buttonElement.AddToClassList("unity-toolbar-button");
buttonElement.AddToClassList("unity-editor-toolbar-element");
buttonElement.RemoveFromClassList("unity-button");
buttonElement.style.marginRight = 2;
buttonElement.style.marginLeft = 2;
if (color != default)
{
buttonElement.style.color = color;
}
if (string.IsNullOrEmpty(icon) == false)
{
VisualElement iconElement = new VisualElement();
iconElement.AddToClassList("unity-editor-toolbar-element__icon");
iconElement.style.backgroundImage = Background.FromTexture2D(EditorGUIUtility.IconContent(icon).image as Texture2D);
buttonElement.Add(iconElement);
}
if (string.IsNullOrEmpty(text) == false)
{
TextElement textElement = new TextElement();
textElement.text = text;
textElement.style.marginLeft = 4;
textElement.style.marginRight = 4;
textElement.style.unityTextAlign = TextAnchor.MiddleCenter;
buttonElement.Add(textElement);
}
return buttonElement;
}
}
}