From 99c83ea6d35337c801b7129fb7bf6eccc978386d Mon Sep 17 00:00:00 2001 From: Anders Ejlersen Date: Mon, 21 Jun 2021 10:01:49 +0200 Subject: [PATCH] 0.6.3: Fixed issue, where toolbar items didn't accept mouse input in 2021 or newer versions --- Editor/Toolbar/AbstractToolbarDrawer.cs | 39 ++++++++ ....cs.meta => AbstractToolbarDrawer.cs.meta} | 0 Editor/Toolbar/IToolbarDrawer.cs | 16 --- Editor/Toolbar/ToolbarDrawer.cs | 45 +++++++-- Editor/Toolbar/Tools/ToolScenePicker.cs | 20 ++-- Editor/Toolbar/Tools/ToolUICanvasPicker.cs | 22 ++--- Editor/Toolbar/Tools/ToolUILayerToggle.cs | 18 ++-- Editor/Toolbar/Utilities/ToolbarUtility.cs | 97 ++++++++++++++++--- package.json | 2 +- 9 files changed, 186 insertions(+), 73 deletions(-) create mode 100644 Editor/Toolbar/AbstractToolbarDrawer.cs rename Editor/Toolbar/{IToolbarDrawer.cs.meta => AbstractToolbarDrawer.cs.meta} (100%) delete mode 100644 Editor/Toolbar/IToolbarDrawer.cs diff --git a/Editor/Toolbar/AbstractToolbarDrawer.cs b/Editor/Toolbar/AbstractToolbarDrawer.cs new file mode 100644 index 0000000..e7e3e93 --- /dev/null +++ b/Editor/Toolbar/AbstractToolbarDrawer.cs @@ -0,0 +1,39 @@ +using Game.NavigationTool.Editor.Toolbar; +using UnityEngine; + +namespace Game.NavigationTool.Editor +{ + public abstract class AbstractToolbarDrawer + { + public abstract bool Enabled { get; } + public abstract EToolbarPlacement Placement { get; } + + private Rect rect; + protected Styles styles; + + public void Setup(Rect rect) + { + this.rect = rect; + } + + public virtual void Update() + { + + } + + public void OnGUI() + { + if (styles == null) + styles = new Styles(); + + styles.Initialize(GUI.skin); + + GUI.enabled = Enabled; + Draw(rect); + GUI.enabled = true; + } + + protected abstract void Draw(Rect rect); + public abstract float CalculateWidth(); + } +} \ No newline at end of file diff --git a/Editor/Toolbar/IToolbarDrawer.cs.meta b/Editor/Toolbar/AbstractToolbarDrawer.cs.meta similarity index 100% rename from Editor/Toolbar/IToolbarDrawer.cs.meta rename to Editor/Toolbar/AbstractToolbarDrawer.cs.meta diff --git a/Editor/Toolbar/IToolbarDrawer.cs b/Editor/Toolbar/IToolbarDrawer.cs deleted file mode 100644 index 2d6f5a5..0000000 --- a/Editor/Toolbar/IToolbarDrawer.cs +++ /dev/null @@ -1,16 +0,0 @@ -using Game.NavigationTool.Editor.Toolbar; -using UnityEngine; - -namespace Game.NavigationTool.Editor -{ - public interface IToolbarDrawer - { - bool Visible { get; } - bool Enabled { get; } - EToolbarPlacement Placement { get; } - - void Update(); - void Draw(Rect rect, Styles styles); - float CalculateWidth(); - } -} \ No newline at end of file diff --git a/Editor/Toolbar/ToolbarDrawer.cs b/Editor/Toolbar/ToolbarDrawer.cs index 38cb9ba..025a375 100644 --- a/Editor/Toolbar/ToolbarDrawer.cs +++ b/Editor/Toolbar/ToolbarDrawer.cs @@ -1,6 +1,7 @@ using Game.NavigationTool.Editor.Toolbar; using UnityEditor; using UnityEngine; +using UnityEngine.UIElements; namespace Game.NavigationTool.Editor { @@ -8,9 +9,8 @@ namespace Game.NavigationTool.Editor internal static class ToolbarDrawer { private static bool IS_INITIALIZED; - private static IToolbarDrawer[] DRAWERS; - private static Styles styles; - + private static AbstractToolbarDrawer[] DRAWERS; + static ToolbarDrawer() { EditorApplication.update -= OnEditorUpdate; @@ -21,9 +21,14 @@ namespace Game.NavigationTool.Editor { if (!IS_INITIALIZED) { - styles = new Styles(); DRAWERS = ToolbarUtility.GetAllDrawers(); + + #if UNITY_2021_1_OR_NEWER + ToolbarUtility.OnUpdate(OnCreateElements); + #else ToolbarUtility.AddGuiListener(OnGUI); + #endif + IS_INITIALIZED = true; } @@ -33,6 +38,27 @@ namespace Game.NavigationTool.Editor } } + #if UNITY_2021_1_OR_NEWER + private static void OnCreateElements(VisualElement leftAlign, VisualElement rightAlign) + { + const float HEIGHT = 22.0f; + + for (var i = 0; i < DRAWERS.Length; i++) + { + AbstractToolbarDrawer drawer = DRAWERS[i]; + var rect = new Rect(0.0f, 0.0f, drawer.CalculateWidth(), HEIGHT); + drawer.Setup(rect); + + var container = new IMGUIContainer(drawer.OnGUI); + container.style.width = rect.width; + + if (drawer.Placement == EToolbarPlacement.Left) + leftAlign.Add(container); + else + rightAlign.Add(container); + } + } + #else private static void OnGUI() { const float Y = 5.0f; @@ -44,19 +70,16 @@ namespace Game.NavigationTool.Editor if (DRAWERS == null) return; - styles.Initialize(GUI.skin); float xLeft = EditorGUIUtility.currentViewWidth * 0.5f + PLAY_BUTTON_OFFSET - PLAY_BUTTON_EXTENT; float xRight = EditorGUIUtility.currentViewWidth * 0.5f + PLAY_BUTTON_OFFSET + PLAY_BUTTON_EXTENT; for (var i = 0; i < DRAWERS.Length; i++) { - IToolbarDrawer drawer = DRAWERS[i]; - - if (!drawer.Visible) - continue; + AbstractToolbarDrawer drawer = DRAWERS[i]; GUI.enabled = drawer.Enabled; float width = drawer.CalculateWidth(); + Rect rect; if (drawer.Placement == EToolbarPlacement.Left) @@ -70,10 +93,12 @@ namespace Game.NavigationTool.Editor xRight += width + SPACING; } - drawer.Draw(rect, styles); + drawer.Setup(rect); + drawer.OnGUI(); } GUI.enabled = true; } + #endif } } \ No newline at end of file diff --git a/Editor/Toolbar/Tools/ToolScenePicker.cs b/Editor/Toolbar/Tools/ToolScenePicker.cs index eeb6258..349874e 100644 --- a/Editor/Toolbar/Tools/ToolScenePicker.cs +++ b/Editor/Toolbar/Tools/ToolScenePicker.cs @@ -1,6 +1,5 @@ using System.Collections.Generic; using System.IO; -using Game.NavigationTool.Editor.Toolbar; using JetBrains.Annotations; using UnityEditor; using UnityEditor.SceneManagement; @@ -10,18 +9,17 @@ using UnityEngine.SceneManagement; namespace Game.NavigationTool.Editor.Tools { [UsedImplicitly] - internal sealed class ToolScenePicker : IToolbarDrawer + internal sealed class ToolScenePicker : AbstractToolbarDrawer { - public bool Visible => true; - public bool Enabled => !EditorApplication.isPlaying && !EditorApplication.isPlayingOrWillChangePlaymode; - public EToolbarPlacement Placement => EToolbarPlacement.Right; + public override bool Enabled => !EditorApplication.isPlaying && !EditorApplication.isPlayingOrWillChangePlaymode; + public override EToolbarPlacement Placement => EToolbarPlacement.Right; private static bool IS_DIRTY = true; private static int SELECTED_INDEX = -1; private static string[] OPTIONS = new string[0]; private static string[] PATHS = new string[0]; - - private void Initialize() + + private static void Initialize() { if (!IS_DIRTY) return; @@ -67,13 +65,13 @@ namespace Game.NavigationTool.Editor.Tools SELECTED_INDEX = listPaths.IndexOf(activeScene.path); IS_DIRTY = false; } - - public void Update() + + public override void Update() { Initialize(); } - public void Draw(Rect rect, Styles styles) + protected override void Draw(Rect rect) { Initialize(); int temp = EditorGUI.Popup(rect, SELECTED_INDEX, OPTIONS, styles.popup); @@ -90,7 +88,7 @@ namespace Game.NavigationTool.Editor.Tools } } - public float CalculateWidth() + public override float CalculateWidth() { return 100.0f; } diff --git a/Editor/Toolbar/Tools/ToolUICanvasPicker.cs b/Editor/Toolbar/Tools/ToolUICanvasPicker.cs index bb3cd1a..df7888f 100644 --- a/Editor/Toolbar/Tools/ToolUICanvasPicker.cs +++ b/Editor/Toolbar/Tools/ToolUICanvasPicker.cs @@ -1,5 +1,4 @@ using System.Collections.Generic; -using Game.NavigationTool.Editor.Toolbar; using JetBrains.Annotations; using UnityEditor; using UnityEditorInternal; @@ -9,17 +8,16 @@ using UTools = UnityEditor.Tools; namespace Game.NavigationTool.Editor.Tools { [UsedImplicitly] - internal sealed class ToolUICanvasPicker : IToolbarDrawer + internal sealed class ToolUICanvasPicker : AbstractToolbarDrawer { - public bool Visible => true; - public bool Enabled => (UTools.visibleLayers & (1 << LayerMask.NameToLayer("UI"))) != 0; - public EToolbarPlacement Placement => EToolbarPlacement.Left; + public override bool Enabled => (UTools.visibleLayers & (1 << LayerMask.NameToLayer("UI"))) != 0; + public override EToolbarPlacement Placement => EToolbarPlacement.Left; private static bool IS_DIRTY = true; private static string[] OPTIONS = new string[0]; private static int[] INSTANCE_IDS = new int[0]; - - private void Initialize() + + private static void Initialize() { if (!IS_DIRTY) return; @@ -48,13 +46,13 @@ namespace Game.NavigationTool.Editor.Tools INSTANCE_IDS = listIds.ToArray(); IS_DIRTY = false; } - - public void Update() + + public override void Update() { Initialize(); } - public void Draw(Rect rect, Styles styles) + protected override void Draw(Rect rect) { Initialize(); int temp = EditorGUI.Popup(rect, 0, OPTIONS, styles.popup); @@ -62,8 +60,8 @@ namespace Game.NavigationTool.Editor.Tools if (temp != 0 && OPTIONS.Length != 1) Focus(INSTANCE_IDS[temp]); } - - public float CalculateWidth() + + public override float CalculateWidth() { return 100.0f; } diff --git a/Editor/Toolbar/Tools/ToolUILayerToggle.cs b/Editor/Toolbar/Tools/ToolUILayerToggle.cs index fab5b35..0afdb61 100644 --- a/Editor/Toolbar/Tools/ToolUILayerToggle.cs +++ b/Editor/Toolbar/Tools/ToolUILayerToggle.cs @@ -1,5 +1,4 @@ -using Game.NavigationTool.Editor.Toolbar; -using JetBrains.Annotations; +using JetBrains.Annotations; using UnityEditor; using UnityEngine; using UTools = UnityEditor.Tools; @@ -7,17 +6,12 @@ using UTools = UnityEditor.Tools; namespace Game.NavigationTool.Editor.Tools { [UsedImplicitly] - internal sealed class ToolUILayerToggle : IToolbarDrawer + internal sealed class ToolUILayerToggle : AbstractToolbarDrawer { - public bool Visible => true; - public bool Enabled => true; - public EToolbarPlacement Placement => EToolbarPlacement.Left; - - public void Update() - { - } + public override bool Enabled => true; + public override EToolbarPlacement Placement => EToolbarPlacement.Left; - public void Draw(Rect rect, Styles styles) + protected override void Draw(Rect rect) { int layer = 1 << LayerMask.NameToLayer("UI"); bool value = (UTools.visibleLayers & layer) != 0; @@ -39,7 +33,7 @@ namespace Game.NavigationTool.Editor.Tools } } - public float CalculateWidth() + public override float CalculateWidth() { return 30.0f; } diff --git a/Editor/Toolbar/Utilities/ToolbarUtility.cs b/Editor/Toolbar/Utilities/ToolbarUtility.cs index abea4f0..34acd2a 100644 --- a/Editor/Toolbar/Utilities/ToolbarUtility.cs +++ b/Editor/Toolbar/Utilities/ToolbarUtility.cs @@ -15,22 +15,89 @@ namespace Game.NavigationTool.Editor.Toolbar { internal static class ToolbarUtility { + private static readonly Assembly ASSEMBLY = typeof(UnityEditor.Editor).Assembly; + + #if UNITY_2021_1_OR_NEWER + private static ScriptableObject CURRENT_TOOLBAR; + private static VisualElement CURRENT_PARENT_LEFT; + private static VisualElement CURRENT_PARENT_RIGHT; + private static int CURRENT_INSTANCE_ID = -1; + #endif + + #if UNITY_2021_1_OR_NEWER + public static void OnUpdate(Action callback) + { + if (CURRENT_TOOLBAR == null) + CURRENT_TOOLBAR = GetToolbarObject(); + + if (CURRENT_TOOLBAR != null && CURRENT_PARENT_LEFT != null && CURRENT_TOOLBAR.GetInstanceID() != CURRENT_INSTANCE_ID) + { + CURRENT_PARENT_LEFT.RemoveFromHierarchy(); + CURRENT_PARENT_LEFT = null; + + CURRENT_PARENT_RIGHT.RemoveFromHierarchy(); + CURRENT_PARENT_RIGHT = null; + + CURRENT_INSTANCE_ID = CURRENT_TOOLBAR.GetInstanceID(); + } + + if (CURRENT_TOOLBAR == null || CURRENT_PARENT_LEFT != null) + return; + + CURRENT_PARENT_LEFT?.RemoveFromHierarchy(); + CURRENT_PARENT_RIGHT?.RemoveFromHierarchy(); + + FieldInfo root = CURRENT_TOOLBAR.GetType().GetField("m_Root", BindingFlags.NonPublic | BindingFlags.Instance); + object rawRoot = root?.GetValue(CURRENT_TOOLBAR); + var mRoot = rawRoot as VisualElement; + + CURRENT_PARENT_LEFT = CreateParent(mRoot, "ToolbarZoneLeftAlign", true); + CURRENT_PARENT_RIGHT = CreateParent(mRoot, "ToolbarZoneRightAlign", false); + callback?.Invoke(CURRENT_PARENT_LEFT, CURRENT_PARENT_RIGHT); + } + + private static VisualElement CreateParent(VisualElement root, string query, bool isLeft) + { + VisualElement parent = root.Q(query); + + var result = new VisualElement + { + style = { + flexGrow = 1, + flexDirection = FlexDirection.Row + } + }; + + if (isLeft) + { + result.Add(new VisualElement + { + style = { + flexGrow = 1 + } + }); + } + + parent.Add(result); + return result; + } + #else public static void AddGuiListener(Action action) { - Assembly assembly = typeof(UnityEditor.Editor).Assembly; - Type typeToolbar = assembly.GetType("UnityEditor.Toolbar"); - Object[] toolbars = Resources.FindObjectsOfTypeAll(typeToolbar); - ScriptableObject so = toolbars.Length > 0 ? (ScriptableObject)toolbars[0] : null; + ScriptableObject so = GetToolbarObject(); if (so == null) return; - Type typeGuiView = assembly.GetType("UnityEditor.GUIView"); + Type typeGuiView = ASSEMBLY.GetType("UnityEditor.GUIView"); #if UNITY_2020_1_OR_NEWER - Type typeWindowBackend = assembly.GetType("UnityEditor.IWindowBackend"); + Type typeWindowBackend = ASSEMBLY.GetType("UnityEditor.IWindowBackend"); PropertyInfo piWindowBackend = typeGuiView.GetProperty("windowBackend", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance); PropertyInfo piVisualTree = typeWindowBackend.GetProperty("visualTree", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance); + + if (piWindowBackend == null) + return; #else PropertyInfo piVisualTree = typeGuiView.GetProperty("visualTree", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance); #endif @@ -44,7 +111,7 @@ namespace Game.NavigationTool.Editor.Toolbar return; #if UNITY_2020_1_OR_NEWER - var windowBackend = piWindowBackend.GetValue(so); + object windowBackend = piWindowBackend.GetValue(so); var visualTree = (VisualElement)piVisualTree.GetValue(windowBackend, null); #else var visualTree = (VisualElement)piVisualTree.GetValue(so, null); @@ -56,13 +123,21 @@ namespace Game.NavigationTool.Editor.Toolbar handler += action; fiImguiContainer.SetValue(container, handler); } + #endif - public static IToolbarDrawer[] GetAllDrawers() + private static ScriptableObject GetToolbarObject() + { + Type typeToolbar = ASSEMBLY.GetType("UnityEditor.Toolbar"); + Object[] toolbars = Resources.FindObjectsOfTypeAll(typeToolbar); + return toolbars.Length > 0 ? (ScriptableObject)toolbars[0] : null; + } + + public static AbstractToolbarDrawer[] GetAllDrawers() { Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); - Type iType = typeof(IToolbarDrawer); + Type iType = typeof(AbstractToolbarDrawer); - var list = new List(8); + var list = new List(8); for (var i = 0; i < assemblies.Length; i++) { @@ -74,7 +149,7 @@ namespace Game.NavigationTool.Editor.Toolbar Type type = types[j]; if (!type.IsAbstract && iType.IsAssignableFrom(type)) - list.Add((IToolbarDrawer)FormatterServices.GetUninitializedObject(type)); + list.Add((AbstractToolbarDrawer)FormatterServices.GetUninitializedObject(type)); } } diff --git a/package.json b/package.json index b157187..cdcf8f3 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "com.module.navigationtool", - "version": "0.6.2", + "version": "0.6.3", "displayName": "Module.NavigationTool", "description": "Support for navigation tools, like favorites, history and toolbars", "unity": "2019.2",