public override void OnGUI(Rect position) { if (!_initialised) { _originalPosition = editorWindow.position.position; _initialised = true; } Event e = Event.current; bool additive = e.control || e.command || e.shift; GUIUtility.hotControl = 0; int highlightedIndex = -1; // Scrolling behaviour. if (e.type == EventType.ScrollWheel) { _scrollDelta = Math.Sign(e.delta.y); } if (_scrollDelta != 0) { ScrollPosition += _scrollDelta; ScrollPosition = Mathf.Clamp(ScrollPosition, 0, TotalSelection.Count - 1); Rect tempRect = editorWindow.position; tempRect.position = new Vector2(_originalPosition.x, _originalPosition.y - ScrollPosition * Height); editorWindow.position = tempRect; _scrollDelta = 0; } //Top and bottom borders (to fix a weird issue where the top 5 pixels of the window do not receive mouse events) EditorGUI.DrawRect(new Rect(0, 0, Width, 5), GUI.color); EditorGUI.DrawRect(new Rect(0, 6 + Height * TotalSelection.Count, Width, 5), GUI.color); Rect separatorTopRect = new Rect(0, 5, Width, 1); EditorGUI.DrawRect(separatorTopRect, BoxBorderColor); for (var i = 0; i < TotalSelection.Count; i++) { SelectionItem selectionItem = TotalSelection[i]; GameObject gameObject = selectionItem.GameObject; GUIContent[] icons = selectionItem.Icons; Rect boxRect = new Rect(0, 5 + 1 + i * Height, Width, Height); GUIStyle labelStyle; bool isInSelection = _currentSelection.Contains(gameObject); bool containsMouse = boxRect.Contains(e.mousePosition); if (containsMouse) { highlightedIndex = i; } EditorGUI.DrawRect(boxRect, BoxBorderColor); if (isInSelection) { if (containsMouse) { // If we're not holding it will solely select this object, otherwise it will be a deselection. GUI.color = !additive ? new Color(0f, 0.5f, 1f) : new Color(0.58f, 0.62f, 0.75f); } else { // If we're not holding control and we're not hovering it will deselect these, so show that preview. // Otherwise, we will be selecting additionally. GUI.color = !additive ? new Color(0.58f, 0.62f, 0.75f) : new Color(0f, 0.5f, 1f); } labelStyle = MiniLabelWhite; } else { if (containsMouse) // Going to select. { GUI.color = new Color(0f, 0.5f, 1f); labelStyle = MiniLabelWhite; } else // Not in selection. { GUI.color = Color.white; labelStyle = MiniLabelBlack; } } Rect innerBoxRect = new Rect(boxRect.x + 1, boxRect.y, boxRect.width - 2, boxRect.height - 1); EditorGUI.DrawRect(innerBoxRect, GUI.color); GUI.color = Color.white; GUI.Label(new Rect(boxRect.x + 20, boxRect.y, Width - 20, boxRect.height), gameObject.name, labelStyle); int maxLength = Mathf.Min(icons.Length, MaxIcons); float width = Height * maxLength; if (icons.Length > 0) { Rect iconsRect = new Rect(boxRect.x + boxRect.width - width, boxRect.y, width, Height); // Behaviour for scrolling icons when the cursor is over the selection (only if the icon count is greater than MaxIcons) if (containsMouse && maxLength < icons.Length) { if (_currentlyHoveringIndex != i) { _currentlyHoveringIndex = i; _iconOffset = 0; } float max = icons.Length - maxLength; _iconOffset = Mathf.MoveTowards(_iconOffset, _iconOffsetTarget, (float)(EditorApplication.timeSinceStartup - lastTime)); if (_iconOffset <= 0) { _iconOffset = 0; _iconOffsetTarget = max; } else if (_iconOffset >= max) { _iconOffset = max; _iconOffsetTarget = 0; } } using (new GUI.GroupScope(iconsRect)) { for (var j = 0; j < icons.Length; j++) { GUIContent icon = icons[j]; GUI.Label( new Rect(width - (maxLength - j) * Height - _iconOffset * Height, 0, Height, Height), icon); } } } // If the selection is being hovered we may need to modify the currently previewing selection // or if the control key has changes states. if (containsMouse && (i != _lastHighlightedIndex || _additionWasLastHeldForPreview != additive)) { _lastHighlightedIndex = i; if (!additive) { _additionWasLastHeldForPreview = false; ResetHierarchyToExpandedStateExcept(gameObject); // If we're not selecting more (ie. have control held) we should just set the selection to be the hovered item. Selection.objects = Array.Empty <Object>(); Selection.activeGameObject = gameObject; } else { _additionWasLastHeldForPreview = true; // Otherwise we need to alter the current selection to add or remove the currently hovered selection. if (isInSelection) { ResetHierarchyToExpandedState(); // Remove the GameObject. Object[] newSelection = new Object[_currentSelection.Count - 1]; int n = 0; foreach (GameObject o in _currentSelection) { if (o == gameObject) { continue; } newSelection[n++] = o; } Selection.objects = newSelection; } else { ResetHierarchyToExpandedStateExcept(gameObject); // Add the GameObject. Object[] newSelection = new Object[_currentSelection.Count + 1]; int n = 0; foreach (GameObject o in _currentSelection) { newSelection[n++] = o; } newSelection[n] = gameObject; Selection.objects = newSelection; } } } // Clicked in the box! if (containsMouse && e.isMouse && e.type == EventType.MouseUp) { MakeSelection(i, additive); e.Use(); if (!additive) { break; } } } if (highlightedIndex == -1 && _lastHighlightedIndex != -1) { RevertPreviewSelection(); } if (e.isKey && e.type == EventType.KeyUp) { switch (e.keyCode) { case KeyCode.Escape: RevertPreviewSelection(); EndSelection(); break; case KeyCode.Return: if (highlightedIndex >= 0) { MakeSelection(highlightedIndex, additive); } break; } } else if (e.isMouse && e.type == EventType.MouseUp) { if (highlightedIndex == -1) { RevertPreviewSelection(); } EndSelection(); } if (e.type != EventType.Repaint && e.type != EventType.Layout) { e.Use(); } lastTime = EditorApplication.timeSinceStartup; }
void OnGUI() { Event e = Event.current; GUIUtility.hotControl = 0; int indexCurrentlyHighlighted = -1; //Scrolling behaviour if (e.type == EventType.ScrollWheel) { scrollDelta = Math.Sign(e.delta.y); } if (scrollDelta != 0) { scrollPosition += scrollDelta; scrollPosition = Mathf.Clamp(scrollPosition, 0, totalSelection.Count - 1); Rect tempRect = position; tempRect.position = new Vector2(originalPosition.x, originalPosition.y - scrollPosition * NSelection.height); ShowAsDropDown(new Rect(tempRect.position, Vector2.zero), tempRect.size); scrollDelta = 0; } //Top and bottom borders (to fix a weird issue where the top 5 pixels of the window do not receive mouse events) EditorGUI.DrawRect(new Rect(0, 0, NSelection.width, 5), GUI.color); EditorGUI.DrawRect(new Rect(0, 6 + NSelection.height * totalSelection.Count, NSelection.width, 5), GUI.color); Rect separatorTopRect = new Rect(0, 5, NSelection.width, 1); EditorGUI.DrawRect(separatorTopRect, boxBorderColor); for (var i = 0; i < totalSelection.Count; i++) { SelectionItem selectionItem = totalSelection[i]; GameObject gameObject = selectionItem.GameObject; GUIContent[] icons = selectionItem.Icons; Rect boxRect = new Rect(0, 5 + 1 + i * NSelection.height, NSelection.width, NSelection.height); GUIStyle labelStyle; bool isInSelection = currentSelection.Contains(gameObject); bool contains = boxRect.Contains(e.mousePosition); if (contains) { indexCurrentlyHighlighted = i; } EditorGUI.DrawRect(boxRect, boxBorderColor); if (isInSelection) { if (contains) { //If we're not holding shift it will solely select this object if (!e.shift) { GUI.color = new Color(0f, 0.5f, 1f); } else //Otherwise it will be a deselection { GUI.color = new Color(0.58f, 0.62f, 0.75f); } } else { //If we're not holding shift and we're not hovering it will deselect these, so show that preview. if (!e.shift) { GUI.color = new Color(0.58f, 0.62f, 0.75f); } else // Otherwise, we will be selecting additionally { GUI.color = new Color(0f, 0.5f, 1f); } } labelStyle = miniLabelWhite; } else { if (contains) //Going To Select { GUI.color = new Color(0f, 0.5f, 1f); labelStyle = miniLabelWhite; } else //Not In Selection { GUI.color = Color.white; labelStyle = miniLabelBlack; } } Rect innerBoxRect = new Rect(boxRect.x + 1, boxRect.y, boxRect.width - 2, boxRect.height - 1); EditorGUI.DrawRect(innerBoxRect, GUI.color); GUI.color = Color.white; GUI.Label(new Rect(boxRect.x + 20, boxRect.y, NSelection.width - 20, boxRect.height), gameObject.name, labelStyle); if (icons.Length > 0) { int maxLength = Mathf.Min(icons.Length, maxIcons); float width = NSelection.height * maxLength; Rect iconsRect = new Rect(boxRect.x + boxRect.width - maxLength * NSelection.height, boxRect.y, width, NSelection.height); //Behaviour for scrolling icons when the cursor is over the selection (only if the icon count is greater than maxIcons) if (contains && maxLength < icons.Length) { if (currentlyHoveringIndex != i) { currentlyHoveringIndex = i; iconOffset = 0; } float max = icons.Length - maxLength; iconOffset = Mathf.MoveTowards(iconOffset, iconOffsetTarget, (float)(EditorApplication.timeSinceStartup - lastTime)); if (iconOffset <= 0) { iconOffset = 0; iconOffsetTarget = max; } else if (iconOffset >= max) { iconOffset = max; iconOffsetTarget = 0; } } using (new GUI.GroupScope(iconsRect)) { for (var j = 0; j < icons.Length; j++) { GUIContent icon = icons[j]; GUI.Label(new Rect(width - (maxLength - j) * NSelection.height - iconOffset * NSelection.height, 0, NSelection.height, NSelection.height), icon); } } } //If the selection is being hovered we may need to modify the currently previewing selection //or if the shift key has changes states. if (contains && (i != lastIndexHighlighted || shiftWasHeldForPreview != e.shift)) { ResetHierarchyToExpandedState(); lastIndexHighlighted = i; if (!e.shift) { shiftWasHeldForPreview = false; //If we're not selecting more (ie. have shift held) we should just set the selection to be the hovered item Selection.objects = new Object[0]; Selection.activeGameObject = gameObject; } else { shiftWasHeldForPreview = true; //Otherwise we need to alter the current selection to add or remove the currently hovered selection if (isInSelection) { //Remove the GameObject Object[] newSelection = new Object[currentSelection.Count - 1]; int n = 0; foreach (GameObject o in currentSelection) { if (o == gameObject) { continue; } newSelection[n++] = o; } Selection.objects = newSelection; } else { //Add the GameObject Object[] newSelection = new Object[currentSelection.Count + 1]; int n = 0; foreach (GameObject o in currentSelection) { newSelection[n++] = o; } newSelection[n] = gameObject; Selection.objects = newSelection; } } } //Clicked in the box! if (contains && e.isMouse && e.type == EventType.MouseUp) { MakeSelection(i, e.shift); e.Use(); if (!e.shift) { break; } } } if (indexCurrentlyHighlighted == -1 && lastIndexHighlighted != -1) { RevertPreviewSelection(); } if (e.isKey && e.type == EventType.KeyUp) { switch (e.keyCode) { case KeyCode.Escape: RevertPreviewSelection(); EndSelection(); break; case KeyCode.Return: if (indexCurrentlyHighlighted >= 0) { MakeSelection(indexCurrentlyHighlighted, e.shift); } break; } } else if (e.isMouse && e.type == EventType.MouseUp) { if (indexCurrentlyHighlighted == -1) { RevertPreviewSelection(); } EndSelection(); } if (e.type != EventType.Repaint && e.type != EventType.Layout) { e.Use(); } Focus(); Repaint(); lastTime = EditorApplication.timeSinceStartup; }