public Rect Draw(Rect position) { #if UNITY_EDITOR if (Platform.EditorMode) { bool headerHeightDetermined = true; var actualDrawnPosition = EditorGUIDrawer.AssetHeader(position, editor, ref headerHeightDetermined); #if UNITY_2018_3_OR_NEWER if (isPrefab) { const float padding = 3f; const float doublePadding = padding + padding; position.y += position.height - OpenInPrefabModeButtonHeight + padding; position.height = OpenInPrefabModeButtonHeight - doublePadding; DrawGUI.Active.ColorRect(position, InspectorUtility.Preferences.theme.AssetHeaderBackground); position.x += padding; position.width -= doublePadding; // UPDATE: even if prefab is being drawn in grayed out color // due to being inactive, draw the open prefab button without // being grayed out, to make it clear that it remains usable. var guiColorWas = GUI.color; var setColor = guiColorWas; setColor.a = 1f; GUI.color = setColor; if (GUI.Button(position, OpenPrefabButtonLabel)) { DrawGUI.UseEvent(); GameObjectDrawer.OpenPrefab(targets[0]); } GUI.color = guiColorWas; actualDrawnPosition.height += OpenInPrefabModeButtonHeight; } #endif return(actualDrawnPosition); } #endif DrawGUI.Runtime.GameObjectHeader(position, targets[0]); return(position); }
/// <summary> Handles the resizing. </summary> /// <param name="target"> Target whose prefix label resizing should be handled. </param> /// <param name="prefixResizerMouseovered"> [out] True if prefix resizer is currently mouseovered. </param> /// <param name="maxHeight"> (Optional) The maximum height. </param> /// <param name="minPrefixLabelWidth"> (Optional) Minimum width for the prefix label when resizing. Some Editors like RectTransform might require a larger min width than the default. </param> /// <param name="fillBackground"> (Optional) True to fill area behind the resizer with background color, preventing clipping with any elements drawn behidn the resizer. </param> /// <returns> New prefix size. </returns> public static float HandleResizing(IUnityObjectDrawer target, out bool prefixResizerMouseovered, float maxHeight, float minPrefixLabelWidth, float maxPrefixLabelWidth) { bool drawVerticalSplitter = target.PrefixResizer == PrefixResizer.Vertical; bool nowResizingThis = nowResizing == target; #if DEV_MODE // make it easier to accurately find optimal prefix width for CustomEditorBaseDrawer // by drawing the vertical splitter if (nowResizingThis) { drawVerticalSplitter = true; } #endif var targetBounds = target.Bounds; var prefixWidth = target.PrefixLabelWidth; var verticalRect = targetBounds; { verticalRect.x = prefixWidth - 1f; var headerHeight = target.HeaderHeight; verticalRect.y += headerHeight + 5f; verticalRect.width = 2f; verticalRect.height = targetBounds.height - headerHeight - 10f; if (maxHeight > 0f && verticalRect.height > maxHeight) { verticalRect.height = maxHeight; } } var manager = InspectorUtility.ActiveManager; var inspector = manager.ActiveInspector; var preferences = inspector.Preferences; var backgroundColor = preferences.theme.Background; bool drawTopSplitter; Rect topResizerPos; if (drawVerticalSplitter) { drawTopSplitter = false; topResizerPos = default(Rect); var bgRect = verticalRect; //some clipping over the controls would occur without this fix on CustomEditors. //even now there's very slight clipping over sliders and text fields, //so it's not a perfect approach float clippingFix = 1.5f; bgRect.width = DrawGUI.MiddlePadding + DrawGUI.MiddlePadding - clippingFix - clippingFix; bgRect.x = prefixWidth - DrawGUI.MiddlePadding + clippingFix; DrawGUI.Active.ColorRect(bgRect, backgroundColor); GUI.DrawTexture(verticalRect, preferences.graphics.splitterBg, ScaleMode.StretchToFill); verticalRect.width += 2f; verticalRect.x -= 1f; prefixResizerMouseovered = verticalRect.MouseIsOver(); } else if (target.PrefixResizer == PrefixResizer.TopOnly) { drawTopSplitter = true; topResizerPos = GetTopResizerRect(target); prefixResizerMouseovered = topResizerPos.MouseIsOver(); } else { drawTopSplitter = false; topResizerPos = default(Rect); prefixResizerMouseovered = false; } // Resising should not be allowed over certain controls that extend over // the full width of the inspector (like the UnityEvent drawer). if (nowResizing != null || manager.MouseoveredSelectable == null || (manager.MouseoveredInspector == target.Inspector && manager.MouseoveredSelectable.PrefixResizingEnabledOverControl)) { var e = Event.current; var eventType = manager.MouseDownInfo.GetEventTypeForMouseUpDetection(e); if (nowResizingThis) { DrawGUI.Active.SetCursor(MouseCursor.ResizeHorizontal); prefixResizerMouseovered = true; } else if (prefixResizerMouseovered) { if (drawVerticalSplitter) { DrawGUI.Active.AddCursorRect(verticalRect, MouseCursor.ResizeHorizontal); } else if (drawTopSplitter) { DrawGUI.Active.AddCursorRect(topResizerPos, MouseCursor.ResizeHorizontal); } if (eventType == EventType.MouseDown) { target.Select(ReasonSelectionChanged.ControlClicked); KeyboardControlUtility.JustClickedControl = 0; KeyboardControlUtility.KeyboardControl = 0; if (e.clickCount == 2) { prefixWidth = target.GetOptimalPrefixLabelWidth(0); #if DEV_MODE Debug.Log(target.ToString() + ".HandleResizing() was double clicked, prefixWidth was set to: " + prefixWidth); #endif } NowResizing = target; resizeMouseDownPos = e.mousePosition; resizeMouseDownWidth = prefixWidth; DrawGUI.UseEvent(); } } if (nowResizingThis) { if (eventType == EventType.MouseUp) { NowResizing = null; DrawGUI.UseEvent(); } else if (eventType == EventType.MouseDrag) { DrawGUI.UseEvent(); prefixWidth = resizeMouseDownWidth + (e.mousePosition.x - resizeMouseDownPos.x); GUI.changed = true; //trigger a repaint for a more responsive drag handle } #if UNITY_EDITOR && DEV_MODE && DEBUG_DISPLAY_PREFIX_WIDTH_WHEN_RESIZING if (nowResizing != null) { var debugRect = target.ClickToSelectArea; debugRect.x = prefixWidth + 10f; debugRect.y += debugRect.height; debugRect.width = 30f; debugRect.height = DrawGUI.SingleLineHeight; if (drawVerticalSplitter) { InspectorUtility.SetActiveTooltip(target.Inspector, debugRect, StringUtils.ToString(Mathf.RoundToInt(prefixWidth))); } else { GUI.Label(debugRect, StringUtils.ToString(Mathf.RoundToInt(prefixWidth)), "MiniLabel"); } } #endif } else if (nowResizing != null) { if (nowResizing.Inactive || !manager.MouseDownInfo.MouseButtonIsDown) { #if DEV_MODE Debug.LogWarning("PrefixResizeUtility force stopping resizing prefix of " + nowResizing + " with nowResizing.Inactive=" + nowResizing.Inactive + ", manager.MouseDownInfo.MouseButtonIsDown=" + manager.MouseDownInfo.MouseButtonIsDown); #endif NowResizing = null; } } } prefixWidth = Mathf.Clamp(prefixWidth, minPrefixLabelWidth, maxPrefixLabelWidth); DrawGUI.PrefixLabelWidth = prefixWidth; if (drawTopSplitter) { if (target.Unfoldedness >= 0.5f) { //middle DrawGUI.Active.ColorRect(topResizerPos, backgroundColor); GUI.DrawTexture(topResizerPos, InspectorUtility.Preferences.graphics.prefixColumnResizeHandle); //left topResizerPos.x = DrawGUI.LeftPadding; topResizerPos.height = 2f; topResizerPos.width = prefixWidth - DrawGUI.LeftPadding - 5f; if (topResizerPos.width > 0f) { GUI.DrawTexture(topResizerPos, InspectorUtility.Preferences.graphics.prefixColumnResizeTrackLeft); } //right topResizerPos.x += topResizerPos.width + TopOnlyPrefixResizerWidth; topResizerPos.width = target.Bounds.width - prefixWidth + 4f - DrawGUI.RightPadding; GUI.DrawTexture(topResizerPos, InspectorUtility.Preferences.graphics.prefixColumnResizeTrackRight); } // the top resizer middle part starts looking a ugly when it's scaled to be only a few pixels in height, so don't draw it at those scales. else { //left topResizerPos.x = DrawGUI.LeftPadding; topResizerPos.height = 2f; topResizerPos.width = prefixWidth - DrawGUI.LeftPadding; if (topResizerPos.width > 0f) { GUI.DrawTexture(topResizerPos, InspectorUtility.Preferences.graphics.prefixColumnResizeTrackLeft); } //right topResizerPos.x += topResizerPos.width; topResizerPos.width = target.Bounds.width - prefixWidth - DrawGUI.RightPadding; GUI.DrawTexture(topResizerPos, InspectorUtility.Preferences.graphics.prefixColumnResizeTrackRight); } } return(prefixWidth); }
/// <inheritdoc/> public override bool DrawPrefix(Rect position) { if (Event.current.type == EventType.Repaint) { //hide prefix resizer line behind the field DrawGUI.Active.ColorRect(lastDrawPosition, DrawGUI.Active.InspectorBackgroundColor); if (backgroundRect.width > 0f) { GUI.Label(backgroundRect, "", InspectorPreferences.Styles.MethodBackground); } } bool drawBackgroundBehindFoldoutsWas = DrawGUI.drawBackgroundBehindFoldouts; DrawGUI.drawBackgroundBehindFoldouts = false; var prefixDrawRect = PrefixLabelPosition; var clipLabelInsideRect = prefixDrawRect; clipLabelInsideRect.width += clipLabelInsideRect.x; clipLabelInsideRect.x = 0f; prefixDrawRect.y = 0f; //use BeginArea to prevent foldout text clipping past the Button GUILayout.BeginArea(clipLabelInsideRect); bool dirty = base.DrawPrefix(prefixDrawRect); GUILayout.EndArea(); DrawGUI.drawBackgroundBehindFoldouts = drawBackgroundBehindFoldoutsWas; bool selected = Selected; var guiColorWas = GUI.color; bool isInvoking; if (isCoroutine && Application.isPlaying) { if (monoBehaviour != null) { isInvoking = monoBehaviour.IsInvoking(memberInfo.MethodInfo.Name); } else { isInvoking = StaticCoroutine.IsInvoking(memberInfo.MethodInfo.Name); } } else { isInvoking = false; } if (isInvoking) { GUI.color = Color.green; } else if (selected) { var col = preferences.theme.ButtonSelected; GUI.color = col; } if (GUI.Button(buttonRect, buttonLabel, Style)) { DrawGUI.UseEvent(); if (Event.current.button == 0) { dirty = true; Invoke(); Select(ReasonSelectionChanged.ControlClicked); } else if (Event.current.button == 1) { var menu = Menu.Create(); menu.Add(Menu.Item("Invoke", () => Invoke(false, false, false, false))); if (hasReturnValue) { #if !POWER_INSPECTOR_LITE menu.AddSeparator(); menu.Add(Menu.Item("Copy Return Value", () => Invoke(false, false, true, false))); #endif if (UnityObjectExtensions.IsUnityObjectOrUnityObjectCollectionType(Type)) { menu.Add(Menu.Item("Ping Return Value", () => Invoke(true, false, false, false))); menu.Add(Menu.Item("Select Return Value", () => Invoke(false, false, false, true))); } } if (isCoroutine) { menu.AddSeparator(); var monoBehaviour = UnityObject as MonoBehaviour; string methodName = MethodInfo.Name; if (monoBehaviour != null && Application.isPlaying) { menu.Add("Invoke Repeating/Every Second", () => monoBehaviour.InvokeRepeating(MethodInfo.Name, 1f, 1f)); menu.Add("Invoke Repeating/Every 5 Seconds", () => monoBehaviour.InvokeRepeating(MethodInfo.Name, 5f, 5f)); menu.Add("Invoke Repeating/Every 10 Seconds", () => monoBehaviour.InvokeRepeating(MethodInfo.Name, 10f, 10f)); if (monoBehaviour.IsInvoking(methodName)) { menu.Add("Stop Coroutine", () => monoBehaviour.StopCoroutine(MethodInfo.Name)); menu.Add("Cancel Invoke", () => monoBehaviour.CancelInvoke(MethodInfo.Name)); } } } ContextMenuUtility.Open(menu, this); } else if (Event.current.button == 2) { Invoke(true, false, true, false); } } GUI.color = guiColorWas; return(dirty); }
/// <inheritdoc /> public override bool OnKeyboardInputGiven(Event inputEvent, KeyConfigs keys) { InspectorUtility.ActiveInspector.OnNextLayout(TruncateAndSelectAllTextIfEditing); switch (inputEvent.keyCode) { case KeyCode.Escape: { if (DrawGUI.EditingTextField) { GUI.changed = true; KeyboardControlUtility.KeyboardControl = 0; DrawGUI.EditingTextField = false; DrawGUI.Use(inputEvent); return(true); } return(false); } case KeyCode.Return: case KeyCode.KeypadEnter: if (inputEvent.modifiers == EventModifiers.None && !ReadOnly) { GUI.changed = true; DrawGUI.Use(inputEvent); if (!DrawGUI.EditingTextField) { StartEditingField(); } else { KeyboardControlUtility.KeyboardControl = 0; DrawGUI.EditingTextField = false; } return(true); } return(false); case KeyCode.F2: if (!ReadOnly) { GUI.changed = true; DrawGUI.Use(inputEvent); StartEditingField(); return(true); } return(false); #if DEV_MODE case KeyCode.U: if (Event.current.modifiers == EventModifiers.Control && !ReadOnly) { GUI.changed = true; DrawGUI.Use(inputEvent); Value = char.ToUpper(Value); return(true); } return(false); case KeyCode.L: if (Event.current.modifiers == EventModifiers.Control && !ReadOnly) { GUI.changed = true; DrawGUI.UseEvent(); Value = char.ToLower(Value); ApplyValueToField(); return(true); } return(false); case KeyCode.UpArrow: if (inputEvent.modifiers == EventModifiers.FunctionKey) { DrawGUI.Use(inputEvent); SelectNextFieldUp(GetSelectedRowIndex()); return(true); } return(false); case KeyCode.DownArrow: if (inputEvent.modifiers == EventModifiers.FunctionKey) { DrawGUI.Use(inputEvent); SelectNextFieldDown(GetSelectedRowIndex()); return(true); } return(false); case KeyCode.LeftArrow: if (inputEvent.modifiers == EventModifiers.FunctionKey) { DrawGUI.Use(inputEvent); SelectNextFieldLeft(false, false); return(true); } return(false); case KeyCode.RightArrow: #if DEV_MODE Debug.Log(StringUtils.ToColorizedString(ToString(), " RightArrow with modifiers=", StringUtils.ToString(inputEvent.modifiers))); #endif if (inputEvent.modifiers == EventModifiers.FunctionKey) { DrawGUI.Use(inputEvent); SelectNextFieldRight(false, false); return(true); } return(false); #endif default: if (inputEvent.character != 0 && inputEvent.modifiers == EventModifiers.None && !ReadOnly) { switch (inputEvent.character) { //TO DO: Don't insert tab, return etc. case '\t': case '\n': case '\r': //break; //UPDATE: with only a break here, //it was causing the field to get selected again //immediately after being deselected //via the return or enter keys return(false); default: Value = inputEvent.character; break; } GUI.changed = true; DrawGUI.Use(inputEvent); StartEditingField(); return(true); } break; } if (DrawGUI.EditingTextField && keys.DetectTextFieldReservedInput(inputEvent, TextFieldType.TextRow)) { #if DEV_MODE Debug.Log(GetType().Name + ".OnKeyboardInputGiven aborting because detected text field reserved input\nInput=" + StringUtils.ToString(inputEvent)); #endif return(false); } if (base.OnKeyboardInputGiven(inputEvent, keys)) { return(true); } // Prevent keyboard events from bleeding elsewhere. E.g. when F was pressed, would cause Scene view to focus to selected Object. DrawGUI.Use(inputEvent); return(true); }
/// <inheritdoc /> public override bool DrawPrefix(Rect position) { //hide prefix resizer line behind the field DrawGUI.Active.ColorRect(lastDrawPosition, DrawGUI.Active.InspectorBackgroundColor); GUI.Label(backgroundRect, "", InspectorPreferences.Styles.MethodBackground); bool drawBackgroundBehindFoldoutsWas = DrawGUI.drawBackgroundBehindFoldouts; DrawGUI.drawBackgroundBehindFoldouts = false; var labelPos = PrefixLabelPosition; //use BeginArea to prevent foldout text clipping past the Button GUILayout.BeginArea(labelPos); labelPos.x = 0f; labelPos.y = 0f; bool dirty = base.DrawPrefix(labelPos); GUILayout.EndArea(); DrawGUI.drawBackgroundBehindFoldouts = drawBackgroundBehindFoldoutsWas; bool highlightButton = Selected && (showGetButton || showSetButton); var guiColorWas = GUI.color; if (showGetButton) { if (highlightButton && firstButtonSelected) { var col = InspectorUtility.Preferences.theme.ButtonSelected; GUI.color = col; } if (GUI.Button(getButtonRect, GetButtonLabel, InspectorPreferences.Styles.MiniButton)) { dirty = true; InvokeGet(); Select(ReasonSelectionChanged.ControlClicked); DrawGUI.UseEvent(); } } if (showSetButton) { if (highlightButton) { if (!firstButtonSelected || !showGetButton) { var col = InspectorUtility.Preferences.theme.ButtonSelected; GUI.color = col; } else { GUI.color = guiColorWas; } } if (GUI.Button(setButtonRect, SetButtonLabel, InspectorPreferences.Styles.MiniButton)) { dirty = true; InvokeSet(); Select(ReasonSelectionChanged.ControlClicked); DrawGUI.UseEvent(); } } if (highlightButton) { GUI.color = guiColorWas; } return(dirty); }