/// <summary> /// This should be called at the beginning of OnGUI of every instance of classes that implement IInspector. /// /// Handles things like setting the ActiveInspector, updating mouseovered inspector part, and broadcasting various events. /// /// SEE ALSO: DrawGUI.BeginOnGUI and InspectorUtility.BeginInspectorDrawer. /// </summary> public static void BeginInspector([NotNull] IInspector inspector, ref bool anyInspectorPartMouseovered) { inspectorBeginScreenPoint = GUIUtility.GUIToScreenPoint(Vector2.zero); GUISpace.Current = Space.Window; activeInspectorDrawer = inspector.InspectorDrawer; ActiveManager = activeInspectorDrawer.Manager; #if DEV_MODE Debug.Assert(activeManager.ActiveInstances.Contains(inspector)); #endif var e = Event.current; var setMouseoveredPart = inspector.GetMouseoveredPartUpdated(ref anyInspectorPartMouseovered); if (setMouseoveredPart != InspectorPart.None) { inspector.InspectorDrawer.Manager.SetMouseoveredInspector(inspector, setMouseoveredPart); } else if (activeManager.MouseoveredInspector == inspector) { #if DEV_MODE && DEBUG_SET_MOUSEOVERED_INSPECTOR Debug.Log(StringUtils.ToColorizedString("SetMouseoveredInspector(", StringUtils.Null, ") with anyInspectorPartMouseovered=", anyInspectorPartMouseovered, ", IgnoreAllMouseInputs=", activeManager.IgnoreAllMouseInputs, ", Cursor.CanRequestLocalPosition=", Cursor.CanRequestLocalPosition, ", Cursor.LocalPosition=", Cursor.LocalPosition, ", windowRect=", inspector.State.WindowRect)); #endif activeManager.SetMouseoveredInspector(null, InspectorPart.None); } activeManager.ActiveInspector = inspector; var state = inspector.State; inspector.NowDrawingPart = InspectorPart.Other; if (OnInspectorGUIBegin != null) { OnInspectorGUIBegin(inspector); } 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); switch (type) { case EventType.MouseUp: case EventType.DragPerform: case EventType.DragExited: #if DEV_MODE && DEBUG_DRAG_N_DROP Debug.Log(StringUtils.ToColorizedString("BeginInspector: " + e.type + " with ObjectReferences=", DrawGUI.Active.DragAndDropObjectReferences, ", MouseDownEventWasUsed=", mouseDownInfo.MouseDownEventWasUsed, ", IgnoreAllMouseInputs=", activeManager.IgnoreAllMouseInputs, ", mouseoveredPart=", setMouseoveredPart, ", button=", Event.current.button + ", mouseDownInfo.Inspector=", mouseDownInfo.Inspector, ", MouseDownOverControl=", mouseDownInfo.MouseDownOverDrawer)); #endif if (e.type == EventType.DragExited && mouseDownInfo.IsDragExitedReallyMouseLeaveWindowEvent()) { #if DEV_MODE Debug.LogWarning("Ignoring DragExited call because IsDragExitedReallyMouseLeaveWindowEvent=" + StringUtils.True + " - cursor probably just left EditorWindow bounds."); #endif break; } var mouseoveredInspector = activeManager.MouseoveredInspector; if (!activeManager.IgnoreAllMouseInputs && mouseoveredInspector != null) { if (e.type == EventType.DragPerform || (e.type == EventType.MouseUp && Event.current.button == 0)) { mouseoveredInspector.LastInputTime = Platform.Time; var reordering = mouseDownInfo.Reordering; var reorderingTo = reordering.MouseoveredDropTarget.Parent; if (reorderingTo != null && !mouseDownInfo.IsClick) { reorderingTo.OnMemberDragNDrop(mouseDownInfo, DrawGUI.Active.DragAndDropObjectReferences); } #if DEV_MODE && DEBUG_DRAG_N_DROP else { Debug.Log(StringUtils.ToColorizedString("Won't call OnMemberDragNDrop. reorderingTo=", reorderingTo, ", mouseDownInfo.IsClick=", mouseDownInfo.IsClick)); } #endif } #if DEV_MODE && DEBUG_DRAG_N_DROP else { Debug.Log(StringUtils.ToColorizedString("Won't call OnMemberDragNDrop. currentEvent.type=", e.type, ", Event.current.button=", Event.current.button)); } #endif } #if DEV_MODE && DEBUG_DRAG_N_DROP else { Debug.Log(StringUtils.ToColorizedString("Won't call OnMemberDragNDrop. IgnoreAllMouseInputs=", activeManager.IgnoreAllMouseInputs, ", setMouseoveredPart=", setMouseoveredPart)); } #endif if (mouseDownInfo.Inspector == inspector) { if (e.type != EventType.MouseUp || Event.current.button == 0) { if (mouseDownInfo.MouseDownOverDrawer != null) { #if DEV_MODE if (!mouseDownInfo.IsClick && !mouseDownInfo.CursorMovedAfterMouseDown) { Debug.LogWarning("Calling OnMouseUpAfterDownOverControl with IsClick=" + StringUtils.False + ", but CursorMovedAfterMouseDown was also false. Bug?"); } #endif mouseDownInfo.MouseDownOverDrawer.OnMouseUpAfterDownOverControl(e, mouseDownInfo.IsClick); } mouseDownInfo.Clear(true); } } break; case EventType.MouseDown: #if DEV_MODE && DEBUG_ON_MOUSE_DOWN Debug.Log(StringUtils.ToColorizedString("BeginInspector(" + inspector + ") - MouseDown with IgnoreAllMouseInputs=", activeManager.IgnoreAllMouseInputs, ", setMouseoveredPart=", setMouseoveredPart)); #endif if (!activeManager.IgnoreAllMouseInputs && setMouseoveredPart != InspectorPart.None) { inspector.LastInputTime = Platform.Time; inspector.OnMouseDown(e); //give controls time to react to selection changes, editing text field changes etc. //before cached values are updated } break; case EventType.KeyDown: inspector.LastInputTime = Platform.Time; break; case EventType.ContextClick: if (!activeManager.IgnoreAllMouseInputs && setMouseoveredPart != InspectorPart.None) { inspector.OnContextClick(e); } break; } if (state.keyboardControlLastFrame != KeyboardControlUtility.KeyboardControl) { state.previousKeyboardControl = state.keyboardControlLastFrame; state.keyboardControlLastFrame = KeyboardControlUtility.KeyboardControl; #if UNITY_EDITOR state.previousKeyboardControlRect = state.keyboardRectLastFrame; state.keyboardRectLastFrame = KeyboardControlUtility.Info.KeyboardRect; #endif } }