/// <summary> /// This should be called at the beginning of OnGUI of every instance of classes that implement IInspectorDrawer. /// /// SEE ALSO: DrawGUI.BeginOnGUI and InspectorUtility.BeginInspector. /// </summary> /// <param name="inspectorDrawer"> The inspector drawer instance. </param> /// <param name="splittable"> The inspector drawer if it implements ISplittableInspectorDrawer, otherwise null. </param> public static void BeginInspectorDrawer([NotNull] IInspectorDrawer inspectorDrawer, [CanBeNull] ISplittableInspectorDrawer splittable) { #if DEV_MODE && PI_ASSERTATIONS Debug.Assert(inspectorDrawer != null); #endif var manager = inspectorDrawer.Manager; activeInspectorDrawer = inspectorDrawer; ActiveManager = manager; activeManager.ActiveInspector = inspectorDrawer.MainView; var e = Event.current; #if DEV_MODE && PI_ASSERTATIONS Debug.Assert(e != null); #endif var mouseDownInfo = activeManager.MouseDownInfo; // Events like MouseUp, DragUpdated and DragPerformed are normally ignored when the cursor is outside EditorWindow bounds // but when a field is being dragged we still need those events (especially important for the MouseUp event!) var type = mouseDownInfo.GetEventTypeForMouseUpDetection(e); if (mouseDownInfo.NowReordering) { var reordering = mouseDownInfo.Reordering; var dropTarget = reordering.MouseoveredDropTarget; // When reordering and cursor is not above a valid drop target, set DragAndDropVisualMode to rejected, // unless dragging Object references outside window bounds, where want to allow dragging into other // EditorWindows. // UPDATE: This broke drag n drop e.g. from Component header to object reference field inside a custom editor. //if(dropTarget.Parent == null && ((DrawGUI.Active.DragAndDropObjectReferences.Length == 0 || activeManager.MouseoveredInspector != null))) if (dropTarget.Parent == null && DrawGUI.Active.DragAndDropObjectReferences.Length == 0) { #if DEV_MODE Debug.LogWarning("Reordering Rejected because dropTarget.Parent=null && DrawGUI.Active.DragAndDropObjectReferences=" + StringUtils.ToString(DrawGUI.Active.DragAndDropObjectReferences) + ", activeManager.MouseoveredInspector=" + StringUtils.ToString(activeManager.MouseoveredInspector)); #endif // Update: only do this once cursor has moved, otherwise it can look strange during simple click events if (mouseDownInfo.CursorMovedAfterMouseDown) { DrawGUI.Active.DragAndDropVisualMode = DragAndDropVisualMode.Rejected; } } DrawGUI.Active.AddCursorRect(new Rect(0f, 0f, 100000f, 100000f), MouseCursor.MoveArrow); } else if (mouseDownInfo.NowDraggingPrefix) { DrawGUI.Active.SetCursor(MouseCursor.SlideArrow); } switch (type) { case EventType.Repaint: if (inspectorDrawer.MainView.RequiresConstantRepaint() || (splittable != null && splittable.ViewIsSplit && splittable.SplitView.RequiresConstantRepaint())) { inspectorDrawer.Repaint(); } break; case EventType.Layout: activeManager.OnLayout(); UpdateDimensions(inspectorDrawer, splittable); break; case EventType.ValidateCommand: inspectorDrawer.OnValidateCommand(e); break; case EventType.ExecuteCommand: if (OnExecuteCommand != null) { if (inspectorDrawer == manager.FirstInspectorDrawer) { #if DEV_MODE && DEBUG_EXECUTE_COMMAND Debug.Log("ExecuteCommand(" + e.commandName + ")"); #endif OnExecuteCommand(ActiveManager.LastSelectedActiveOrDefaultInspector(), e.commandName); } #if DEV_MODE && DEBUG_EXECUTE_COMMAND else { Debug.Log("ExecuteCommand(" + e.commandName + ") not sent with e=" + StringUtils.ToString(e) + ", OnExecuteCommand=" + StringUtils.ToString(OnExecuteCommand)); } #endif } inspectorDrawer.OnExecuteCommand(e); break; case EventType.MouseUp: case EventType.DragPerform: #if DEV_MODE && (DEBUG_MOUSE_UP || DEBUG_DRAG_N_DROP) Debug.Log(type + " with IsUnityObjectDrag=" + StringUtils.True + ", MouseDownInfo.Inspector=" + activeManager.MouseDownInfo.Inspector + ", activeInspectorDrawer.MouseIsOver=" + (inspectorDrawer == null ? StringUtils.Null : StringUtils.ToColorizedString(inspectorDrawer.MouseIsOver))); #endif inspectorDrawer.Repaint(); mouseDownInfo.OnMouseUp(activeManager); break; case EventType.DragExited: //IMPORTANT NOTE: DragExited gets called when during DragNDrop cursor leaves EditorWindow bounds! #if DEV_MODE && UNITY_EDITOR Debug.Log(type + " with LastInputEvent().type=" + DrawGUI.LastInputEvent().type + ", IsUnityObjectDrag=" + StringUtils.ToColorizedString(DrawGUI.IsUnityObjectDrag) + ", EditorWindow.focusedWindow=" + UnityEditor.EditorWindow.focusedWindow + ", activeManager.MouseoveredInspector=" + activeManager.MouseoveredInspector + ", mouseoveredDrawer.position=" + (activeManager.MouseoveredInspector == null || activeManager.MouseoveredInspector.InspectorDrawer == null ? StringUtils.Null : activeManager.MouseoveredInspector.InspectorDrawer.position.ToString()) + ", MouseDownInfo.Inspector=" + activeManager.MouseDownInfo.Inspector + ", Drawer.MouseIsOver=" + (activeInspectorDrawer == null ? StringUtils.Null : StringUtils.ToColorizedString(activeInspectorDrawer.MouseIsOver))); #endif if (mouseDownInfo.IsDragExitedReallyMouseLeaveWindowEvent()) { #if DEV_MODE Debug.LogWarning("Ignoring DragExited call because IsDragExitedReallyMouseLeaveWindowEvent=" + StringUtils.True + " - cursor probably just left EditorWindow bounds."); #endif break; } inspectorDrawer.Repaint(); mouseDownInfo.OnMouseUp(activeManager); break; case EventType.MouseDown: ActiveManager.MouseDownInfo.OnMouseDown(); #if DEV_MODE && DEBUG_ON_MOUSE_DOWN Debug.Log("MouseDown with button=" + e.button + ", keyCode=" + e.keyCode + ", MouseoveredSelectable=" + StringUtils.ToString(ActiveManager.MouseoveredSelectable)); #endif break; case EventType.KeyDown: inspectorDrawer.OnKeyDown(e); break; case EventType.KeyUp: inspectorDrawer.Manager.OnKeyUp(e); break; } }
public static void OnKeyDown(this IInspectorDrawer inspectorDrawer, Event e) { #if DEV_MODE && DEBUG_KEYBOARD_INPUT Debug.Log(StringUtils.ToColorizedString(inspectorDrawer.ToString(), ".OnKeyDown(", e.keyCode, ") with HasFocus=", inspectorDrawer.HasFocus, ", selectedControl=", StringUtils.ToString(inspectorDrawer.SelectedOrDefaultView().FocusedDrawer), ", SelectedPart=", inspectorDrawer.Manager.SelectedInspectorPart)); #endif if (!inspectorDrawer.HasFocus) { return; } var view = inspectorDrawer.SelectedOrDefaultView(); var keys = view.Preferences.keyConfigs; #if !POWER_INSPECTOR_LITE if (keys.stepBackInSelectionHistory.DetectAndUseInput(e)) { view.StepBackInSelectionHistory(); return; } if (keys.stepForwardInSelectionHistory.DetectAndUseInput(e)) { view.StepForwardInSelectionHistory(); return; } #endif inspectorDrawer.Repaint(); DrawGUI.RegisterInputEvent(e); var activeView = inspectorDrawer.SelectedOrDefaultView(); // give controls time to react to selection changes, editing text field changes etc. // before cached values are updated. (e.g. unapplied changes in delayed fields are // not discarded before they have time to get applied activeView.ResetNextUpdateCachedValues(); #if DEV_MODE && PI_ASSERTATIONS Debug.Assert(!inspectorDrawer.HasFocus || activeView.Selected); #endif #if DEV_MODE && DEBUG_KEYBOARD_INPUT Debug.Log(StringUtils.ToColorizedString("OnKeyDown activeView.Selected=", activeView.Selected, ", activeView.FocusedDrawer=", activeView.FocusedDrawer + ", Manager.SelectedInspector=", inspectorDrawer.Manager.SelectedInspector, ", inspectorDrawer.HasFocus=", inspectorDrawer.HasFocus)); #endif if (activeView.Toolbar.OnKeyboardInputGivenWhenNotSelected(e, activeView.Preferences.keyConfigs)) { if (e.type != EventType.Used) { DrawGUI.Use(e); ExitGUIUtility.ExitGUI(); } } IDrawer selectedControl = null; if (activeView.Selected) { selectedControl = activeView.FocusedDrawer; if (selectedControl != null) { var onKeyboardInputBeingGiven = selectedControl.OnKeyboardInputBeingGiven; if (onKeyboardInputBeingGiven != null) { #if DEV_MODE && DEBUG_KEYBOARD_INPUT Debug.Log("onKeyboardInputBeingGiven(" + StringUtils.ToString(e) + "): " + StringUtils.ToString(onKeyboardInputBeingGiven)); #endif if (onKeyboardInputBeingGiven(selectedControl, e, selectedControl.Inspector.Preferences.keyConfigs)) { return; } } if (selectedControl.OnKeyboardInputGiven(e, selectedControl.Inspector.Preferences.keyConfigs)) { return; } } else if (inspectorDrawer.Manager.SelectedInspectorPart == InspectorPart.Toolbar) { activeView.Toolbar.OnKeyboardInputGiven(e, activeView.Preferences.keyConfigs); } else if (inspectorDrawer.Manager.SelectedInspectorPart == InspectorPart.Viewport || inspectorDrawer.Manager.SelectedInspectorPart == InspectorPart.None) { bool fieldChangeInputGiven; if (keys.DetectNextField(e, true) || keys.DetectPreviousField(e, true) || keys.nextFieldLeft.DetectAndUseInput(e) || keys.nextFieldRight.DetectAndUseInput(e) || keys.nextFieldDown.DetectAndUseInput(e) || keys.nextFieldUp.DetectAndUseInput(e)) { fieldChangeInputGiven = true; } else if (e.modifiers == EventModifiers.FunctionKey) { switch (e.keyCode) { case KeyCode.DownArrow: case KeyCode.UpArrow: case KeyCode.LeftArrow: case KeyCode.RightArrow: fieldChangeInputGiven = true; break; default: fieldChangeInputGiven = false; break; } } else { fieldChangeInputGiven = false; } if (fieldChangeInputGiven) { var drawers = activeView.State.drawers; if (drawers.Length == 0) { if (activeView.Toolbar != null) { activeView.Toolbar.OnFindCommandGiven(); } else { KeyboardControlUtility.SetKeyboardControl(0, 3); } } else { var first = drawers[0]; var select = first.GetNextSelectableDrawerRight(true, null); #if DEV_MODE && DEBUG_NEXT_FIELD Debug.Log(first + ".GetNextSelectableDrawerRight: " + StringUtils.ToString(select)); #endif if (select != null) { activeView.Select(select, ReasonSelectionChanged.SelectNextControl); } } } } } if (DrawGUI.EditingTextField && keys.DetectTextFieldReservedInput(e, TextFieldType.TextRow)) { #if DEV_MODE && DEBUG_KEYBOARD_INPUT Debug.Log(StringUtils.ToColorizedString("OnKeyboardInputGiven( ", StringUtils.ToString(e), ") DetectTextFieldReservedInput: ", true, " with selectedControl=", selectedControl)); #endif return; } if (keys.addComponent.DetectInput(e)) { #if DEV_MODE Debug.Log("AddComponent shortcut detected"); #endif if (AddComponentButtonDrawer.OpenSelectedOrFirstFoundInstance(activeView)) { DrawGUI.Use(e); } } if (keys.toggleSplitView.DetectInput(e)) { var splittable = inspectorDrawer as ISplittableInspectorDrawer; if (splittable != null && splittable.CanSplitView) { DrawGUI.Use(e); bool setSplitView = !splittable.ViewIsSplit; splittable.MainView.OnNextLayout(() => splittable.SetSplitView(setSplitView)); } } if (keys.refresh.DetectAndUseInput(e)) { var selectedInspector = inspectorDrawer.Manager.SelectedInspector; if (selectedInspector != null && selectedInspector.InspectorDrawer == inspectorDrawer) { selectedInspector.ForceRebuildDrawers(); } else { var mainView = inspectorDrawer.MainView; mainView.ForceRebuildDrawers(); var splittable = inspectorDrawer as ISplittableInspectorDrawer; if (splittable != null && splittable.ViewIsSplit) { splittable.SplitView.ForceRebuildDrawers(); } } } var keyCode = e.keyCode; switch (keyCode) { case KeyCode.Menu: if (selectedControl != null) { selectedControl.OpenContextMenu(e, selectedControl.RightClickArea, false, selectedControl.SelectedPart); } break; case KeyCode.Space: inspectorDrawer.Manager.RegisterKeyHeldDown(keyCode, "space"); break; case KeyCode.F2: inspectorDrawer.Repaint(); if (!DrawGUI.EditingTextField) { DrawGUI.Use(e); DrawGUI.EditingTextField = true; } break; case KeyCode.Escape: #if DEV_MODE Debug.Log("!!! ESCAPE !!!"); #endif //when dragging a control, allow aborting using the escape key if (inspectorDrawer.Manager.MouseDownInfo.MouseDownOverDrawer != null) { inspectorDrawer.Manager.MouseDownInfo.Clear(); } if (DrawGUI.EditingTextField) { DrawGUI.Use(e); DrawGUI.EditingTextField = false; } break; case KeyCode.AltGr: case KeyCode.RightAlt: KeyConfig.OnAltGrDown(); break; #if DEV_MODE case KeyCode.I: if (e.control && e.alt) { Debug.Log("INFO: FocusedDrawer=" + StringUtils.ToString(inspectorDrawer.SelectedOrDefaultView().FocusedDrawer) + ", EditingTextField=" + DrawGUI.EditingTextField); } break; #endif } }