/// <summary> /// Draws the Odin Editor Window. /// </summary> protected virtual void OnGUI() { EditorTimeHelper prevTimeHelper = EditorTimeHelper.Time; EditorTimeHelper.Time = this.timeHelper; EditorTimeHelper.Time.Update(); try { bool messureArea = this.preventContentFromExpanding; if (messureArea) { GUILayout.BeginArea(new Rect(0, 0, this.position.width, this.wrappedAreaMaxHeight)); } if (this.OnBeginGUI != null) { this.OnBeginGUI(); } // Editor windows, can be created before Odin assigns OdinEditors to all relevent types via reflection. // This ensures that that happens before we render anything. if (!hasUpdatedOdinEditors) { InspectorConfig.Instance.EnsureEditorsHaveBeenUpdated(); hasUpdatedOdinEditors = true; } this.InitializeIfNeeded(); this.marginStyle = this.marginStyle ?? new GUIStyle() { padding = new RectOffset() }; if (Event.current.type == EventType.Layout) { this.marginStyle.padding.left = (int)this.WindowPadding.x; this.marginStyle.padding.right = (int)this.WindowPadding.y; this.marginStyle.padding.top = (int)this.WindowPadding.z; this.marginStyle.padding.bottom = (int)this.WindowPadding.w; // Creates the editors. UpdateEditors(); } // Removes focus from text-fields when clicking on an empty area. var prevType = Event.current.type; if (Event.current.type == EventType.MouseDown) { this.mouseDownId = GUIUtility.hotControl; this.mouseDownKeyboardControl = GUIUtility.keyboardControl; this.mouseDownWindow = focusedWindow; } // Draws the editors. bool useScrollWheel = this.UseScrollView; if (useScrollWheel) { this.scrollPos = EditorGUILayout.BeginScrollView(this.scrollPos); } // Draw the GUI //var r = EditorGUILayout.BeginVertical(); //{ // Update the content rect Vector2 size; if (this.preventContentFromExpanding) { size = EditorGUILayout.BeginVertical(GUILayoutOptions.ExpandHeight(false)).size; } else { size = EditorGUILayout.BeginVertical().size; } if (this.contenSize == Vector2.zero || Event.current.type == EventType.Repaint) { this.contenSize = size; } GUIHelper.PushHierarchyMode(false); float labelWidth; if (this.DefaultLabelWidth < 1) { labelWidth = this.contenSize.x * this.DefaultLabelWidth; } else { labelWidth = this.DefaultLabelWidth; } GUIHelper.PushLabelWidth(labelWidth); this.OnBeginDrawEditors(); GUILayout.BeginVertical(this.marginStyle); DrawEditors(); GUILayout.EndVertical(); this.OnEndDrawEditors(); GUIHelper.PopLabelWidth(); GUIHelper.PopHierarchyMode(); EditorGUILayout.EndVertical(); if (useScrollWheel) { EditorGUILayout.EndScrollView(); } if (this.OnEndGUI != null) { this.OnEndGUI(); } // This removes focus from text-fields when clicking on an empty area. if (Event.current.type != prevType) { this.mouseDownId = -2; } if (Event.current.type == EventType.MouseUp && GUIUtility.hotControl == this.mouseDownId && focusedWindow == this.mouseDownWindow && GUIUtility.keyboardControl == this.mouseDownKeyboardControl) { GUIHelper.RemoveFocusControl(); GUI.FocusControl(null); } if (this.drawCountWarmup < 10) { this.Repaint(); if (Event.current.type == EventType.Repaint) { this.drawCountWarmup++; } } // TODO: Find out why the window doesn't repaint properly when this is 0. And then remove this if statement. // Try navigating a menu tree with the keyboard filled menu items with nothing to inspect. // It only updates when you start moving the mouse. if (Event.current.isMouse || Event.current.type == EventType.Used || this.currentTargets == null || this.currentTargets.Length == 0 || GUIHelper.CurrentWindowHasFocus) { this.Repaint(); } this.RepaintIfRequested(); if (messureArea) { GUILayout.EndArea(); } } finally { EditorTimeHelper.Time = prevTimeHelper; } }
/// <summary> /// Draws the menu tree recursively. /// </summary> public void DrawMenuTree() { EditorTimeHelper prevTimeHelper = EditorTimeHelper.Time; EditorTimeHelper.Time = this.timeHelper; EditorTimeHelper.Time.Update(); try { timeHelper.Update(); this.frameCounter.Update(); var config = this.Config; if (this.requestRepaint) { GUIHelper.RequestRepaint(); this.requestRepaint = false; } if (config.DrawSearchToolbar) { this.DrawSearchToolbar(); } var outerRect = EditorGUILayout.BeginVertical(); this.HandleActiveMenuTreeState(outerRect); if (config.DrawScrollView) { if (Event.current.type == EventType.Repaint) { this.outerScrollViewRect = outerRect; } if (this.hideScrollbarsWhileContentIsExpanding > 0) { config.ScrollPos = EditorGUILayout.BeginScrollView(config.ScrollPos, GUIStyle.none, GUIStyle.none, GUILayoutOptions.ExpandHeight(false)); } else { config.ScrollPos = EditorGUILayout.BeginScrollView(config.ScrollPos, GUILayoutOptions.ExpandHeight(false)); } var size = EditorGUILayout.BeginVertical(); // hideScrollbarsWhileContentIsExpanding: // When drawn in confined areas, the scrollbars on the scrollview will flicker in and out while expanding. // The code below ensures we hide the scorllbars remain invisible while the inner and outer scrollview heights are somewhat close to each other. if (this.innerScrollViewRect.height == 0 || Event.current.type == EventType.Repaint) { var chancedSizeDiff = Mathf.Abs(this.innerScrollViewRect.height - size.height); var boxDiff = Mathf.Abs(this.innerScrollViewRect.height - this.outerScrollViewRect.height); var shouldHaveScrollViewRegardless = this.innerScrollViewRect.height - 40 > this.outerScrollViewRect.height; if (!shouldHaveScrollViewRegardless && chancedSizeDiff > 0) { this.hideScrollbarsWhileContentIsExpanding = 5; GUIHelper.RequestRepaint(); } else if (Mathf.Abs(boxDiff) < 1) { this.hideScrollbarsWhileContentIsExpanding = 5; } else { this.hideScrollbarsWhileContentIsExpanding--; if (this.hideScrollbarsWhileContentIsExpanding < 0) { this.hideScrollbarsWhileContentIsExpanding = 0; } else { GUIHelper.RequestRepaint(); } } this.innerScrollViewRect = size; } GUILayout.Space(-1); } if (this.isDirty && Event.current.type == EventType.Layout) { this.UpdateMenuTree(); this.isDirty = false; } VisibleRect = GUIClipInfo.VisibleRect.Expand(300); CurrentEvent = Event.current; CurrentEventType = CurrentEvent.type; CurrentEditorTimeHelper = EditorTimeHelper.Time; CurrentEditorTimeHelperDeltaTime = CurrentEditorTimeHelper.DeltaTime; var tree = this.DrawInSearchMode ? this.FlatMenuTree : this.MenuItems; var count = tree.Count; if (config.EXPERIMENTAL_INTERNAL_DrawFlatTreeFastNoLayout) { var itemHeight = this.DefaultMenuStyle.Height; var height = count * itemHeight; var rect = GUILayoutUtility.GetRect(0, height); rect.height = itemHeight; for (int i = 0; i < count; i++) { var item = tree[i]; item.EXPERIMENTAL_DontAllocateNewRect = true; item.rect = rect; item.DrawMenuItem(0); rect.y += itemHeight; } } else { for (int i = 0; i < count; i++) { tree[i].DrawMenuItems(0); } } if (config.DrawScrollView) { EditorGUILayout.EndVertical(); EditorGUILayout.EndScrollView(); } EditorGUILayout.EndVertical(); if (config.AutoHandleKeyboardNavigation) { this.HandleKeybaordMenuNavigation(); } if (this.scrollToWhenReady != null) { this.ScrollToMenuItem(this.scrollToWhenReady, this.scollToCenter); } if (Event.current.type == EventType.Repaint) { this.isFirstFrame = false; } } finally { EditorTimeHelper.Time = prevTimeHelper; } }
/// <summary> /// Draws the Odin Editor Window. /// </summary> protected override void OnGUI() { EditorTimeHelper prevTimeHelper = EditorTimeHelper.Time; EditorTimeHelper.Time = this.timeHelper; EditorTimeHelper.Time.Update(); try { if (Event.current.type == EventType.Layout) { bool setActive = this.menuTree == null; if (this.menuTree == null || this.isDirty) { this.ForceMenuTreeRebuild(); if (setActive) { OdinMenuTree.ActiveMenuTree = this.menuTree; } if (UnityEditorEventUtility.HasOnProjectChanged) { UnityEditorEventUtility.OnProjectChanged -= ProjectWindowChanged; UnityEditorEventUtility.OnProjectChanged += ProjectWindowChanged; } else { #pragma warning disable 0618 EditorApplication.projectWindowChanged -= ProjectWindowChanged; EditorApplication.projectWindowChanged += ProjectWindowChanged; #pragma warning restore 0618 } this.isDirty = false; } // Try select object. if (this.trySelectObject != null && this.menuTree != null) { var menuItem = this.menuTree.EnumerateTree() .FirstOrDefault(x => x.Value == this.trySelectObject); if (menuItem != null) { this.menuTree.Selection.Clear(); menuItem.Select(); this.trySelectObject = null; } } } Rect menuBorderRect; GUILayout.BeginHorizontal(); GUILayout.BeginVertical(GUILayoutOptions.Width(this.MenuWidth).ExpandHeight()); { var rect = GUIHelper.GetCurrentLayoutRect(); if (this.menuTree != null) { this.menuTree.MenuTreeActivationZone(rect); } EditorGUI.DrawRect(rect, SirenixGUIStyles.MenuBackgroundColor); menuBorderRect = rect; menuBorderRect.xMin = rect.xMax - 4; menuBorderRect.xMax += 4; if (this.ResizableMenuWidth) { EditorGUIUtility.AddCursorRect(menuBorderRect, MouseCursor.ResizeHorizontal); this.MenuWidth += SirenixEditorGUI.SlideRect(menuBorderRect).x; } this.DrawMenu(); } GUILayout.EndVertical(); GUILayout.BeginVertical(); { var rect = GUIHelper.GetCurrentLayoutRect(); EditorGUI.DrawRect(rect, SirenixGUIStyles.DarkEditorBackground); base.OnGUI(); } GUILayout.EndVertical(); GUILayout.EndHorizontal(); EditorGUI.DrawRect(menuBorderRect.AlignCenter(1), SirenixGUIStyles.BorderColor); if (this.menuTree != null) { this.menuTree.HandleKeybaordMenuNavigation(); // TODO: Handle scroll to selected menu items... // this.menuTree.Selection.Last() is the latest selected item. } this.RepaintIfRequested(); } finally { EditorTimeHelper.Time = prevTimeHelper; } }