[+] EditorToolbar

[+] EditorToolbar
This commit is contained in:
ALEXTANG
2023-05-11 23:52:42 +08:00
parent 35f7c9309c
commit a827e501f2
15 changed files with 520 additions and 0 deletions

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 9847b59583cecaa408b648da16cf2d00
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 075130c21aee41b49b3977adc2bfa288
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 20dbf6614352aaf488de29690deeab68
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: fb0502859d7561142a3408d0ce2a19d8
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,84 @@
using UnityEditor;
using UnityEditor.SceneManagement;
using UnityEngine;
namespace UnityToolbarExtender
{
[InitializeOnLoad]
public class SceneSwitchLeftButton
{
private static readonly string SceneName1 = "main";
private static readonly string SceneName2 = "main2";
static SceneSwitchLeftButton()
{
ToolbarExtender.LeftToolbarGUI.Add(OnToolbarGUI);
}
static readonly string ButtonStyleName = "Tab middle";
static GUIStyle _buttonGuiStyle;
static void OnToolbarGUI()
{
_buttonGuiStyle ??= new GUIStyle(ButtonStyleName)
{
padding = new RectOffset(2, 8, 2, 2),
alignment = TextAnchor.MiddleCenter,
fontStyle = FontStyle.Bold
};
GUILayout.FlexibleSpace();
if (GUILayout.Button(
new GUIContent("Launcher", EditorGUIUtility.FindTexture("PlayButton"), $"Start Scene Launcher"),
_buttonGuiStyle))
{
SceneHelper.StartScene(SceneName1);
}
}
}
static class SceneHelper
{
static string _sceneToOpen;
public static void StartScene(string sceneName)
{
if (EditorApplication.isPlaying)
{
EditorApplication.isPlaying = false;
}
_sceneToOpen = sceneName;
EditorApplication.update += OnUpdate;
}
static void OnUpdate()
{
if (_sceneToOpen == null ||
EditorApplication.isPlaying || EditorApplication.isPaused ||
EditorApplication.isCompiling || EditorApplication.isPlayingOrWillChangePlaymode)
{
return;
}
EditorApplication.update -= OnUpdate;
if (EditorSceneManager.SaveCurrentModifiedScenesIfUserWantsTo())
{
string[] guids = AssetDatabase.FindAssets("t:scene " + _sceneToOpen, null);
if (guids.Length == 0)
{
Debug.LogWarning("Couldn't find scene file");
}
else
{
string scenePath = AssetDatabase.GUIDToAssetPath(guids[0]);
EditorSceneManager.OpenScene(scenePath);
EditorApplication.isPlaying = true;
}
}
_sceneToOpen = null;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 45017e4df12424c4fb16db4708d239f0
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: acd9403857c068f4792b1a536a7b89f6
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 252cc3ce82f9548b99943bfdadc9d4c0
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,58 @@
using UnityEditor;
using UnityEngine;
namespace UnityToolbarExtender.Examples
{
[InitializeOnLoad]
public static class SceneViewFocuser
{
static bool m_enabled;
static bool Enabled
{
get { return m_enabled; }
set
{
m_enabled = value;
EditorPrefs.SetBool("SceneViewFocuser", value);
}
}
static SceneViewFocuser()
{
m_enabled = EditorPrefs.GetBool("SceneViewFocuser", false);
EditorApplication.playModeStateChanged += OnPlayModeChanged;
EditorApplication.pauseStateChanged += OnPauseChanged;
ToolbarExtender.RightToolbarGUI.Add(OnToolbarGUI);
}
static void OnPauseChanged(PauseState obj)
{
if (Enabled && obj == PauseState.Unpaused)
{
// Not sure why, but this must be delayed
EditorApplication.delayCall += EditorWindow.FocusWindowIfItsOpen<SceneView>;
}
}
static void OnPlayModeChanged(PlayModeStateChange obj)
{
if (Enabled && obj == PlayModeStateChange.EnteredPlayMode)
{
EditorWindow.FocusWindowIfItsOpen<SceneView>();
}
}
static void OnToolbarGUI()
{
var tex = EditorGUIUtility.IconContent(@"UnityEditor.SceneView").image;
GUI.changed = false;
GUILayout.Toggle(m_enabled, new GUIContent(null, tex, "Focus SceneView when entering play mode"), "Command");
if (GUI.changed)
{
Enabled = !Enabled;
}
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: c8ddf5f9fafe5734dbae1d30d51bb2a6
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,111 @@
using System;
using UnityEngine;
using UnityEditor;
using System.Reflection;
#if UNITY_2019_1_OR_NEWER
using UnityEngine.UIElements;
#else
using UnityEngine.Experimental.UIElements;
#endif
namespace UnityToolbarExtender
{
public static class ToolbarCallback
{
static Type m_toolbarType = typeof(Editor).Assembly.GetType("UnityEditor.Toolbar");
static Type m_guiViewType = typeof(Editor).Assembly.GetType("UnityEditor.GUIView");
#if UNITY_2020_1_OR_NEWER
static Type m_iWindowBackendType = typeof(Editor).Assembly.GetType("UnityEditor.IWindowBackend");
static PropertyInfo m_windowBackend = m_guiViewType.GetProperty("windowBackend",
BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
static PropertyInfo m_viewVisualTree = m_iWindowBackendType.GetProperty("visualTree",
BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
#else
static PropertyInfo m_viewVisualTree = m_guiViewType.GetProperty("visualTree",
BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
#endif
static FieldInfo m_imguiContainerOnGui = typeof(IMGUIContainer).GetField("m_OnGUIHandler",
BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
static ScriptableObject m_currentToolbar;
/// <summary>
/// Callback for toolbar OnGUI method.
/// </summary>
public static Action OnToolbarGUI;
public static Action OnToolbarGUILeft;
public static Action OnToolbarGUIRight;
static ToolbarCallback()
{
EditorApplication.update -= OnUpdate;
EditorApplication.update += OnUpdate;
}
static void OnUpdate()
{
// Relying on the fact that toolbar is ScriptableObject and gets deleted when layout changes
if (m_currentToolbar == null)
{
// Find toolbar
var toolbars = Resources.FindObjectsOfTypeAll(m_toolbarType);
m_currentToolbar = toolbars.Length > 0 ? (ScriptableObject) toolbars[0] : null;
if (m_currentToolbar != null)
{
#if UNITY_2021_1_OR_NEWER
var root = m_currentToolbar.GetType().GetField("m_Root", BindingFlags.NonPublic | BindingFlags.Instance);
var rawRoot = root.GetValue(m_currentToolbar);
var mRoot = rawRoot as VisualElement;
RegisterCallback("ToolbarZoneLeftAlign", OnToolbarGUILeft);
RegisterCallback("ToolbarZoneRightAlign", OnToolbarGUIRight);
void RegisterCallback(string root, Action cb) {
var toolbarZone = mRoot.Q(root);
var parent = new VisualElement()
{
style = {
flexGrow = 1,
flexDirection = FlexDirection.Row,
}
};
var container = new IMGUIContainer();
container.style.flexGrow = 1;
container.onGUIHandler += () => {
cb?.Invoke();
};
parent.Add(container);
toolbarZone.Add(parent);
}
#else
#if UNITY_2020_1_OR_NEWER
var windowBackend = m_windowBackend.GetValue(m_currentToolbar);
// Get it's visual tree
var visualTree = (VisualElement) m_viewVisualTree.GetValue(windowBackend, null);
#else
// Get it's visual tree
var visualTree = (VisualElement) m_viewVisualTree.GetValue(m_currentToolbar, null);
#endif
// Get first child which 'happens' to be toolbar IMGUIContainer
var container = (IMGUIContainer) visualTree[0];
// (Re)attach handler
var handler = (Action) m_imguiContainerOnGui.GetValue(container);
handler -= OnGUI;
handler += OnGUI;
m_imguiContainerOnGui.SetValue(container, handler);
#endif
}
}
}
static void OnGUI()
{
var handler = OnToolbarGUI;
if (handler != null) handler();
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 4314ecffdfd1d90488e39e9ae35d14a1
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,169 @@
using System;
using System.Collections.Generic;
using System.Reflection;
using UnityEditor;
using UnityEngine;
namespace UnityToolbarExtender
{
[InitializeOnLoad]
public static class ToolbarExtender
{
static int m_toolCount;
static GUIStyle m_commandStyle = null;
public static readonly List<Action> LeftToolbarGUI = new List<Action>();
public static readonly List<Action> RightToolbarGUI = new List<Action>();
static ToolbarExtender()
{
Type toolbarType = typeof(Editor).Assembly.GetType("UnityEditor.Toolbar");
#if UNITY_2019_1_OR_NEWER
string fieldName = "k_ToolCount";
#else
string fieldName = "s_ShownToolIcons";
#endif
FieldInfo toolIcons = toolbarType.GetField(fieldName,
BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static);
#if UNITY_2019_3_OR_NEWER
m_toolCount = toolIcons != null ? ((int) toolIcons.GetValue(null)) : 8;
#elif UNITY_2019_1_OR_NEWER
m_toolCount = toolIcons != null ? ((int) toolIcons.GetValue(null)) : 7;
#elif UNITY_2018_1_OR_NEWER
m_toolCount = toolIcons != null ? ((Array) toolIcons.GetValue(null)).Length : 6;
#else
m_toolCount = toolIcons != null ? ((Array) toolIcons.GetValue(null)).Length : 5;
#endif
ToolbarCallback.OnToolbarGUI = OnGUI;
ToolbarCallback.OnToolbarGUILeft = GUILeft;
ToolbarCallback.OnToolbarGUIRight = GUIRight;
}
#if UNITY_2019_3_OR_NEWER
public const float space = 8;
#else
public const float space = 10;
#endif
public const float largeSpace = 20;
public const float buttonWidth = 32;
public const float dropdownWidth = 80;
#if UNITY_2019_1_OR_NEWER
public const float playPauseStopWidth = 140;
#else
public const float playPauseStopWidth = 100;
#endif
static void OnGUI()
{
// Create two containers, left and right
// Screen is whole toolbar
if (m_commandStyle == null)
{
m_commandStyle = new GUIStyle("CommandLeft");
}
var screenWidth = EditorGUIUtility.currentViewWidth;
// Following calculations match code reflected from Toolbar.OldOnGUI()
float playButtonsPosition = Mathf.RoundToInt ((screenWidth - playPauseStopWidth) / 2);
Rect leftRect = new Rect(0, 0, screenWidth, Screen.height);
leftRect.xMin += space; // Spacing left
leftRect.xMin += buttonWidth * m_toolCount; // Tool buttons
#if UNITY_2019_3_OR_NEWER
leftRect.xMin += space; // Spacing between tools and pivot
#else
leftRect.xMin += largeSpace; // Spacing between tools and pivot
#endif
leftRect.xMin += 64 * 2; // Pivot buttons
leftRect.xMax = playButtonsPosition;
Rect rightRect = new Rect(0, 0, screenWidth, Screen.height);
rightRect.xMin = playButtonsPosition;
rightRect.xMin += m_commandStyle.fixedWidth * 3; // Play buttons
rightRect.xMax = screenWidth;
rightRect.xMax -= space; // Spacing right
rightRect.xMax -= dropdownWidth; // Layout
rightRect.xMax -= space; // Spacing between layout and layers
rightRect.xMax -= dropdownWidth; // Layers
#if UNITY_2019_3_OR_NEWER
rightRect.xMax -= space; // Spacing between layers and account
#else
rightRect.xMax -= largeSpace; // Spacing between layers and account
#endif
rightRect.xMax -= dropdownWidth; // Account
rightRect.xMax -= space; // Spacing between account and cloud
rightRect.xMax -= buttonWidth; // Cloud
rightRect.xMax -= space; // Spacing between cloud and collab
rightRect.xMax -= 78; // Colab
// Add spacing around existing controls
leftRect.xMin += space;
leftRect.xMax -= space;
rightRect.xMin += space;
rightRect.xMax -= space;
// Add top and bottom margins
#if UNITY_2019_3_OR_NEWER
leftRect.y = 4;
leftRect.height = 22;
rightRect.y = 4;
rightRect.height = 22;
#else
leftRect.y = 5;
leftRect.height = 24;
rightRect.y = 5;
rightRect.height = 24;
#endif
if (leftRect.width > 0)
{
GUILayout.BeginArea(leftRect);
GUILayout.BeginHorizontal();
foreach (var handler in LeftToolbarGUI)
{
handler();
}
GUILayout.EndHorizontal();
GUILayout.EndArea();
}
if (rightRect.width > 0)
{
GUILayout.BeginArea(rightRect);
GUILayout.BeginHorizontal();
foreach (var handler in RightToolbarGUI)
{
handler();
}
GUILayout.EndHorizontal();
GUILayout.EndArea();
}
}
public static void GUILeft() {
GUILayout.BeginHorizontal();
foreach (var handler in LeftToolbarGUI)
{
handler();
}
GUILayout.EndHorizontal();
}
public static void GUIRight() {
GUILayout.BeginHorizontal();
foreach (var handler in RightToolbarGUI)
{
handler();
}
GUILayout.EndHorizontal();
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 7b71421f0295dfa4f9c32f3ace45690d
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -18,6 +18,12 @@ EditorUserSettings:
value: 5a040704065659090f575b2442270f44464f4b2f7c797e697c2c4e65e4b73269
flags: 0
RecentlyUsedSceneGuid-4:
value: 500906055d045d0c54570f7a47770e15444e4d79287c27657d2c1b6ae4b4666d
flags: 0
RecentlyUsedSceneGuid-5:
value: 055056510407580e5857547415770e44474f402e7f7c7336747f4f60bae3316a
flags: 0
RecentlyUsedSceneGuid-6:
value: 0557570353005959590f5f7b48700744174f417c7e717165797b1835b2b96d6a
flags: 0
RecentlyUsedScenePath-0: