ToolbarCallback.cs 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110
  1. using System;
  2. using UnityEngine;
  3. using UnityEditor;
  4. using System.Reflection;
  5. #if UNITY_2019_1_OR_NEWER
  6. using UnityEngine.UIElements;
  7. #else
  8. using UnityEngine.Experimental.UIElements;
  9. #endif
  10. namespace UnityToolbarExtender
  11. {
  12. public static class ToolbarCallback
  13. {
  14. static Type m_toolbarType = typeof(Editor).Assembly.GetType("UnityEditor.Toolbar");
  15. static Type m_guiViewType = typeof(Editor).Assembly.GetType("UnityEditor.GUIView");
  16. #if UNITY_2020_1_OR_NEWER
  17. static Type m_iWindowBackendType = typeof(Editor).Assembly.GetType("UnityEditor.IWindowBackend");
  18. static PropertyInfo m_windowBackend = m_guiViewType.GetProperty("windowBackend",
  19. BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
  20. static PropertyInfo m_viewVisualTree = m_iWindowBackendType.GetProperty("visualTree",
  21. BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
  22. #else
  23. static PropertyInfo m_viewVisualTree = m_guiViewType.GetProperty("visualTree",
  24. BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
  25. #endif
  26. static FieldInfo m_imguiContainerOnGui = typeof(IMGUIContainer).GetField("m_OnGUIHandler",
  27. BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
  28. static ScriptableObject m_currentToolbar;
  29. /// <summary>
  30. /// Callback for toolbar OnGUI method.
  31. /// </summary>
  32. public static Action OnToolbarGUI;
  33. public static Action OnToolbarGUILeft;
  34. public static Action OnToolbarGUIRight;
  35. static ToolbarCallback()
  36. {
  37. EditorApplication.update -= OnUpdate;
  38. EditorApplication.update += OnUpdate;
  39. }
  40. static void OnUpdate()
  41. {
  42. // Relying on the fact that toolbar is ScriptableObject and gets deleted when layout changes
  43. if (m_currentToolbar == null)
  44. {
  45. // Find toolbar
  46. var toolbars = Resources.FindObjectsOfTypeAll(m_toolbarType);
  47. m_currentToolbar = toolbars.Length > 0 ? (ScriptableObject) toolbars[0] : null;
  48. if (m_currentToolbar != null)
  49. {
  50. #if UNITY_2021_1_OR_NEWER
  51. var root = m_currentToolbar.GetType().GetField("m_Root", BindingFlags.NonPublic | BindingFlags.Instance);
  52. var rawRoot = root.GetValue(m_currentToolbar);
  53. var mRoot = rawRoot as VisualElement;
  54. RegisterCallback("ToolbarZoneLeftAlign", OnToolbarGUILeft);
  55. RegisterCallback("ToolbarZoneRightAlign", OnToolbarGUIRight);
  56. void RegisterCallback(string root, Action cb) {
  57. var toolbarZone = mRoot.Q(root);
  58. var parent = new VisualElement()
  59. {
  60. style = {
  61. flexGrow = 1,
  62. flexDirection = FlexDirection.Row,
  63. }
  64. };
  65. var container = new IMGUIContainer();
  66. container.onGUIHandler += () => {
  67. cb?.Invoke();
  68. };
  69. parent.Add(container);
  70. toolbarZone.Add(parent);
  71. }
  72. #else
  73. #if UNITY_2020_1_OR_NEWER
  74. var windowBackend = m_windowBackend.GetValue(m_currentToolbar);
  75. // Get it's visual tree
  76. var visualTree = (VisualElement) m_viewVisualTree.GetValue(windowBackend, null);
  77. #else
  78. // Get it's visual tree
  79. var visualTree = (VisualElement) m_viewVisualTree.GetValue(m_currentToolbar, null);
  80. #endif
  81. // Get first child which 'happens' to be toolbar IMGUIContainer
  82. var container = (IMGUIContainer) visualTree[0];
  83. // (Re)attach handler
  84. var handler = (Action) m_imguiContainerOnGui.GetValue(container);
  85. handler -= OnGUI;
  86. handler += OnGUI;
  87. m_imguiContainerOnGui.SetValue(container, handler);
  88. #endif
  89. }
  90. }
  91. }
  92. static void OnGUI()
  93. {
  94. var handler = OnToolbarGUI;
  95. if (handler != null) handler();
  96. }
  97. }
  98. }