using UnityEditor; using UnityEngine; #if UNITY_2021_1_OR_NEWER using System.Collections.Generic; using UnityEngine.UIElements; #endif namespace Module.NavigationTool.Editor.Toolbar { [InitializeOnLoad] internal static class ToolbarDrawer { private static bool IS_INITIALIZED; private static AbstractToolbarDrawer[] DRAWERS; #if UNITY_2021_1_OR_NEWER private static readonly Dictionary DICT_MAPPING = new Dictionary(); #endif static ToolbarDrawer() { EditorApplication.update -= OnEditorUpdate; EditorApplication.update += OnEditorUpdate; } private static void OnEditorUpdate() { if (!IS_INITIALIZED) { DRAWERS = ToolbarUtility.GetAllDrawers(); #if !UNITY_2021_1_OR_NEWER ToolbarUtility.AddGuiListener(OnGUI); #endif IS_INITIALIZED = true; } #if UNITY_2021_1_OR_NEWER ToolbarUtility.OnUpdate(OnUpdateElements); #endif for (var i = 0; i < DRAWERS.Length; i++) { if (DRAWERS[i].Visible) DRAWERS[i].Update(); } } #if UNITY_2021_1_OR_NEWER private static void OnUpdateElements(VisualElement leftAlign, VisualElement rightAlign) { const float HEIGHT = 22.0f; var added = false; for (int i = DRAWERS.Length - 1; i >= 0; i--) { AbstractToolbarDrawer drawer = DRAWERS[i]; bool valid = CheckValidityOfContainer(drawer, leftAlign, rightAlign); if (drawer.Visible && !valid) { var rect = new Rect(0.0f, 0.0f, drawer.CalculateWidth(), HEIGHT); drawer.Setup(rect); var container = new ToolbarIMGUIContainer(drawer.OnGUI, drawer.Priority); container.style.width = rect.width; DICT_MAPPING.Add(drawer, container); added = true; if (drawer.Placement == EToolbarPlacement.Left) leftAlign.Add(container); else rightAlign.Add(container); } else if (!drawer.Visible && valid) { IMGUIContainer container = DICT_MAPPING[drawer]; DICT_MAPPING.Remove(drawer); container.RemoveFromHierarchy(); } } if (added) { leftAlign.Sort(SortVisualElements); rightAlign.Sort(SortVisualElements); } } private static bool CheckValidityOfContainer(AbstractToolbarDrawer drawer, VisualElement leftAlign, VisualElement rightAlign) { if (!DICT_MAPPING.TryGetValue(drawer, out IMGUIContainer container)) return false; bool valid = drawer.Placement == EToolbarPlacement.Left ? leftAlign.Contains(container) : rightAlign.Contains(container); if (!valid) DICT_MAPPING.Remove(drawer); return valid; } private static int SortVisualElements(VisualElement ve0, VisualElement ve1) { var c0 = ve0 as ToolbarIMGUIContainer; var c1 = ve1 as ToolbarIMGUIContainer; if (c0 == null && c1 == null) return 0; if (c0 == null) return -1; if (c1 == null) return 1; return c0.Priority.CompareTo(c1.Priority); } #else private static void OnGUI() { const float Y = 5.0f; const float SPACING = 4.0f; const float HEIGHT = 22.0f; const float PLAY_BUTTON_EXTENT = 75.0f; const float PLAY_BUTTON_OFFSET = -23.0f; if (DRAWERS == null) return; 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++) { AbstractToolbarDrawer drawer = DRAWERS[i]; if (!drawer.Visible) continue; GUI.enabled = drawer.Enabled; float width = drawer.CalculateWidth(); Rect rect; if (drawer.Placement == EToolbarPlacement.Left) { rect = new Rect(xLeft - width, Y, width, HEIGHT); xLeft -= width + SPACING; // Note: Magic number for closest right-most item left of play button (2020.3) if (rect.xMin < 414.0f) continue; } else { rect = new Rect(xRight, Y, width, HEIGHT); xRight += width + SPACING; // Note: Magic number for closest left-most item right of play button (2020.3) // If you don't have collab, which no sane person has if (rect.xMax < 642.0f) continue; } drawer.Setup(rect); drawer.OnGUI(); } GUI.enabled = true; } #endif } }