internal void UpdateElementUnderMouse(BaseVisualElementPanel panel)
        {
            if (panel != m_LastMousePositionPanel)
            {
                return;
            }

            Vector2       localMousePosition          = panel.visualTree.WorldToLocal(m_LastMousePosition);
            VisualElement currentTopElementUnderMouse = panel.topElementUnderMouse;

            panel.topElementUnderMouse = panel.Pick(localMousePosition);
            DispatchMouseEnterMouseLeave(currentTopElementUnderMouse, panel.topElementUnderMouse, null);
            DispatchMouseOverMouseOut(currentTopElementUnderMouse, panel.topElementUnderMouse, null);
        }
Example #2
0
        public EventPropagation DispatchEvent(Event e, BaseVisualElementPanel panel)
        {
            EventPropagation result;

            if (e.type == EventType.Repaint)
            {
                Debug.Log("Repaint should be handled by Panel before Dispatcher");
                result = EventPropagation.Continue;
            }
            else
            {
                bool flag = false;
                if (panel.panelDebug != null && panel.panelDebug.enabled && panel.panelDebug.interceptEvents != null && panel.panelDebug.interceptEvents(e))
                {
                    result = EventPropagation.Stop;
                }
                else
                {
                    if (this.capture != null && this.capture.panel == null)
                    {
                        Debug.Log(string.Format("Capture has no panel, forcing removal (capture={0} eventType={1})", this.capture, e.type));
                        this.RemoveCapture();
                    }
                    if (this.capture != null)
                    {
                        if (this.capture.panel.contextType != panel.contextType)
                        {
                            result = EventPropagation.Continue;
                            return(result);
                        }
                        VisualElement visualElement = this.capture as VisualElement;
                        if (visualElement != null)
                        {
                            e.mousePosition = visualElement.GlobalToBound(e.mousePosition);
                        }
                        else
                        {
                            IManipulator manipulator = this.capture as IManipulator;
                            if (manipulator != null)
                            {
                                e.mousePosition = manipulator.target.GlobalToBound(e.mousePosition);
                            }
                        }
                        flag = true;
                        if (this.capture.HandleEvent(e, this.capture as VisualElement) == EventPropagation.Stop)
                        {
                            result = EventPropagation.Stop;
                            return(result);
                        }
                    }
                    if (e.isKey)
                    {
                        flag = true;
                        if (panel.focusedElement != null)
                        {
                            if (this.PropagateEvent(panel.focusedElement, e) == EventPropagation.Stop)
                            {
                                result = EventPropagation.Stop;
                                return(result);
                            }
                        }
                        else if (this.SendEventToIMGUIContainers(panel.visualTree, e, panel.focusedElement) == EventPropagation.Stop)
                        {
                            result = EventPropagation.Stop;
                            return(result);
                        }
                    }
                    else if (e.isMouse || e.isScrollWheel || e.type == EventType.DragUpdated || e.type == EventType.DragPerform || e.type == EventType.DragExited)
                    {
                        if (e.type == EventType.MouseLeaveWindow)
                        {
                            this.elementUnderMouse = null;
                        }
                        else
                        {
                            this.elementUnderMouse = panel.Pick(e.mousePosition);
                        }
                        if (e.type == EventType.MouseDown && this.elementUnderMouse != null && this.elementUnderMouse.enabled)
                        {
                            this.SetFocusedElement(panel, this.elementUnderMouse);
                        }
                        if (this.elementUnderMouse != null)
                        {
                            flag = true;
                            if (this.PropagateEvent(this.elementUnderMouse, e) == EventPropagation.Stop)
                            {
                                result = EventPropagation.Stop;
                                return(result);
                            }
                        }
                        if (e.type == EventType.MouseEnterWindow || e.type == EventType.MouseLeaveWindow)
                        {
                            flag = true;
                            if (this.SendEventToIMGUIContainers(panel.visualTree, e, null) == EventPropagation.Stop)
                            {
                                result = EventPropagation.Stop;
                                return(result);
                            }
                        }
                    }
                    if (e.type == EventType.ExecuteCommand || e.type == EventType.ValidateCommand)
                    {
                        flag = true;
                        if (panel.focusedElement != null && this.PropagateEvent(panel.focusedElement, e) == EventPropagation.Stop)
                        {
                            result = EventPropagation.Stop;
                            return(result);
                        }
                        if (this.SendEventToIMGUIContainers(panel.visualTree, e, panel.focusedElement) == EventPropagation.Stop)
                        {
                            result = EventPropagation.Stop;
                            return(result);
                        }
                    }
                    if (e.type == EventType.Used)
                    {
                        flag = true;
                        if (this.SendEventToIMGUIContainers(panel.visualTree, e, null) == EventPropagation.Stop)
                        {
                            result = EventPropagation.Stop;
                            return(result);
                        }
                    }
                    if (!flag)
                    {
                        if (this.SendEventToIMGUIContainers(panel.visualTree, e, null) == EventPropagation.Stop)
                        {
                            result = EventPropagation.Stop;
                            return(result);
                        }
                    }
                    result = EventPropagation.Continue;
                }
            }
            return(result);
        }
        void ProcessEvent(EventBase evt, IPanel panel)
        {
            using (new Gate(this))
            {
                evt.PreDispatch();

                var panelDebug = (panel as BaseVisualElementPanel)?.panelDebug;
                if (panelDebug != null && panelDebug.showOverlay)
                {
                    if (panelDebug.InterceptEvents(evt.imguiEvent))
                    {
                        evt.StopPropagation();
                        evt.PostDispatch();
                        return;
                    }
                }

                IMouseEvent         mouseEvent         = evt as IMouseEvent;
                IMouseEventInternal mouseEventInternal = evt as IMouseEventInternal;
                if (mouseEvent != null && mouseEventInternal != null && mouseEventInternal.hasUnderlyingPhysicalEvent)
                {
                    m_LastMousePositionPanel = panel;
                    m_LastMousePosition      = mouseEvent.mousePosition;
                }

                bool eventHandled = false;

                // Release mouse capture if capture element is not in a panel.
                VisualElement captureVE = MouseCaptureController.mouseCapture as VisualElement;
                if (evt.GetEventTypeId() != MouseCaptureOutEvent.TypeId() && captureVE != null && captureVE.panel == null)
                {
                    Event e = evt.imguiEvent;
                    Debug.Log(String.Format("Capture has no panel, forcing removal (capture={0} eventType={1})", MouseCaptureController.mouseCapture, e != null ? e.type.ToString() : "null"));
                    MouseCaptureController.ReleaseMouse();
                }

                // Send all IMGUI events (for backward compatibility) and MouseEvents with null target (because thats what we want to do in the new system)
                // to the capture, if there is one. Note that events coming from IMGUI have their target set to null.
                bool sendEventToMouseCapture = false;
                bool mouseEventWasCaptured   = false;
                if (MouseCaptureController.mouseCapture != null)
                {
                    if (evt.imguiEvent != null && evt.target == null)
                    {
                        // Non exclusive processing by capturing element.
                        sendEventToMouseCapture = true;
                        mouseEventWasCaptured   = false;
                    }

                    if (mouseEvent != null && (evt.target == null || evt.target == MouseCaptureController.mouseCapture))
                    {
                        // Exclusive processing by capturing element.
                        sendEventToMouseCapture = true;
                        mouseEventWasCaptured   = true;
                    }

                    if (panel != null)
                    {
                        if (captureVE != null && captureVE.panel.contextType != panel.contextType)
                        {
                            // Capturing element is not in the right context. Ignore it.
                            sendEventToMouseCapture = false;
                            mouseEventWasCaptured   = false;
                        }
                    }

                    if (evt.GetEventTypeId() == WheelEvent.TypeId())
                    {
                        sendEventToMouseCapture = false;
                        mouseEventWasCaptured   = false;
                    }
                }

                evt.skipElement = null;

                if (sendEventToMouseCapture)
                {
                    BaseVisualElementPanel basePanel = panel as BaseVisualElementPanel;

                    if (mouseEvent != null && basePanel != null)
                    {
                        VisualElement currentTopElementUnderMouse = basePanel.topElementUnderMouse;

                        if (evt.target == null)
                        {
                            basePanel.topElementUnderMouse = basePanel.Pick(mouseEvent.mousePosition);
                        }

                        DispatchEnterLeaveEvents(currentTopElementUnderMouse, basePanel.topElementUnderMouse, evt);
                    }

                    IEventHandler originalCaptureElement = MouseCaptureController.mouseCapture;

                    eventHandled = true;

                    evt.dispatch         = true;
                    evt.target           = MouseCaptureController.mouseCapture;
                    evt.currentTarget    = MouseCaptureController.mouseCapture;
                    evt.propagationPhase = PropagationPhase.AtTarget;
                    MouseCaptureController.mouseCapture.HandleEvent(evt);

                    // Do further processing with a target computed the usual way.
                    // However, if mouseEventWasCaptured, the only thing remaining to do is ExecuteDefaultAction,
                    // which whould be done with mouseCapture as the target.
                    if (!mouseEventWasCaptured)
                    {
                        evt.target = null;
                    }

                    evt.currentTarget    = null;
                    evt.propagationPhase = PropagationPhase.None;
                    evt.dispatch         = false;

                    // Do not call HandleEvent again for this element.
                    evt.skipElement = originalCaptureElement;
                }

                if (!mouseEventWasCaptured && !evt.isPropagationStopped)
                {
                    if (evt is IKeyboardEvent && panel != null)
                    {
                        eventHandled = true;
                        if (panel.focusController.focusedElement != null)
                        {
                            IMGUIContainer imguiContainer = panel.focusController.focusedElement as IMGUIContainer;

                            if (imguiContainer != null)
                            {
                                // THINK ABOUT THIS PF: shoudln't we allow for the TrickleDown dispatch phase?
                                if (imguiContainer != evt.skipElement && imguiContainer.HandleIMGUIEvent(evt.imguiEvent))
                                {
                                    evt.StopPropagation();
                                    evt.PreventDefault();
                                }
                            }
                            else
                            {
                                evt.target = panel.focusController.focusedElement;
                                PropagateEvent(evt);
                            }
                        }
                        else
                        {
                            evt.target = panel.visualTree;
                            PropagateEvent(evt);

                            if (!evt.isPropagationStopped)
                            {
                                PropagateToIMGUIContainer(panel.visualTree, evt);
                            }
                        }
                    }
                    else if (mouseEvent != null)
                    {
                        // FIXME: we should not change hover state when capture is true.
                        // However, when doing drag and drop, drop target should be highlighted.

                        // TODO when EditorWindow is docked MouseLeaveWindow is not always sent
                        // this is a problem in itself but it could leave some elements as "hover"

                        BaseVisualElementPanel basePanel = panel as BaseVisualElementPanel;

                        if (basePanel != null && evt.GetEventTypeId() == MouseLeaveWindowEvent.TypeId())
                        {
                            VisualElement currentTopElementUnderMouse = basePanel.topElementUnderMouse;
                            basePanel.topElementUnderMouse = null;
                            DispatchMouseEnterMouseLeave(currentTopElementUnderMouse, basePanel.topElementUnderMouse, mouseEvent);
                            DispatchMouseOverMouseOut(currentTopElementUnderMouse, basePanel.topElementUnderMouse, mouseEvent);
                        }
                        else if (basePanel != null && evt.GetEventTypeId() == DragExitedEvent.TypeId())
                        {
                            VisualElement currentTopElementUnderMouse = basePanel.topElementUnderMouse;
                            basePanel.topElementUnderMouse = null;
                            DispatchDragEnterDragLeave(currentTopElementUnderMouse, basePanel.topElementUnderMouse, mouseEvent);
                        }
                        // update element under mouse and fire necessary events
                        else
                        {
                            VisualElement currentTopElementUnderMouse = null;
                            if (evt.target == null && basePanel != null)
                            {
                                currentTopElementUnderMouse    = basePanel.topElementUnderMouse;
                                basePanel.topElementUnderMouse = panel.Pick(mouseEvent.mousePosition);
                                evt.target = basePanel.topElementUnderMouse;
                            }

                            if (evt.target != null)
                            {
                                eventHandled = true;
                                PropagateEvent(evt);
                            }

                            if (basePanel != null)
                            {
                                DispatchEnterLeaveEvents(currentTopElementUnderMouse, basePanel.topElementUnderMouse, evt);
                            }
                        }
                    }
                    else if (panel != null && evt is ICommandEvent)
                    {
                        IMGUIContainer imguiContainer = panel.focusController.focusedElement as IMGUIContainer;

                        eventHandled = true;
                        if (imguiContainer != null)
                        {
                            if (imguiContainer != evt.skipElement && imguiContainer.HandleIMGUIEvent(evt.imguiEvent))
                            {
                                evt.StopPropagation();
                                evt.PreventDefault();
                            }
                        }
                        else if (panel.focusController.focusedElement != null)
                        {
                            evt.target = panel.focusController.focusedElement;
                            PropagateEvent(evt);
                        }
                        else
                        {
                            PropagateToIMGUIContainer(panel.visualTree, evt);
                        }
                    }
                    else if (evt is IPropagatableEvent ||
                             evt is IFocusEvent ||
                             evt is IChangeEvent ||
                             evt.GetEventTypeId() == InputEvent.TypeId() ||
                             evt.GetEventTypeId() == GeometryChangedEvent.TypeId())
                    {
                        Debug.Assert(evt.target != null);
                        eventHandled = true;
                        PropagateEvent(evt);
                    }
                }

                if (!mouseEventWasCaptured && !evt.isPropagationStopped && panel != null)
                {
                    Event e = evt.imguiEvent;
                    if (!eventHandled || (e != null && e.type == EventType.Used) ||
                        evt.GetEventTypeId() == MouseEnterWindowEvent.TypeId() ||
                        evt.GetEventTypeId() == MouseLeaveWindowEvent.TypeId())
                    {
                        PropagateToIMGUIContainer(panel.visualTree, evt);
                    }
                }

                if (evt.target == null && panel != null)
                {
                    evt.target = panel.visualTree;
                }

                ExecuteDefaultAction(evt);

                evt.PostDispatch();
            }
        }