private void UpdateMouseOver(Viewport viewport, RenderUIElement state)
        {
            if (input == null || !input.HasMouse)
            {
                return;
            }

            var intersectionPoint    = Vector3.Zero;
            var mousePosition        = input.MousePosition;
            var rootElement          = state.UIComponent.RootElement;
            var lastMouseOverElement = state.LastMouseOverElement;
            var mouseOverElement     = lastMouseOverElement;

            // determine currently overred element.
            if (mousePosition != state.LastMousePosition)
            {
                Ray uiRay;
                if (!GetTouchPosition(state.UIComponent, ref viewport, mousePosition, out uiRay))
                {
                    return;
                }

                mouseOverElement = GetElementAtScreenPosition(rootElement, uiRay, ref intersectionPoint);
            }

            // find the common parent between current and last overred elements
            var commonElement = FindCommonParent(mouseOverElement, lastMouseOverElement);

            // disable mouse over state to previously overred hierarchy
            var parent = lastMouseOverElement;

            while (parent != commonElement && parent != null)
            {
                parent.MouseOverState = MouseOverState.MouseOverNone;
                parent = parent.VisualParent;
            }

            // enable mouse over state to currently overred hierarchy
            if (mouseOverElement != null)
            {
                // the element itself
                mouseOverElement.MouseOverState = MouseOverState.MouseOverElement;

                // its hierarchy
                parent = mouseOverElement.VisualParent;
                while (parent != null)
                {
                    if (parent.IsHierarchyEnabled)
                    {
                        parent.MouseOverState = MouseOverState.MouseOverChild;
                    }

                    parent = parent.VisualParent;
                }
            }

            // update cached values
            state.LastMouseOverElement = mouseOverElement;
            state.LastMousePosition    = mousePosition;
        }
        partial void PickingUpdate(RenderUIElement renderUIElement, Viewport viewport, ref Matrix worldViewProj, GameTime drawTime)
        {
            if (renderUIElement.UIComponent.Page?.RootElement == null)
                return;

             UpdateMouseOver(ref viewport, ref worldViewProj, renderUIElement);
             UpdateTouchEvents(ref viewport, ref worldViewProj, renderUIElement, drawTime);
        }
        partial void PickingUpdate(RenderUIElement renderUIElement, Viewport viewport, GameTime drawTime)
        {
            if (renderUIElement.UIComponent.RootElement == null)
            {
                return;
            }

            UpdateMouseOver(viewport, renderUIElement);
            UpdateTouchEvents(viewport, renderUIElement, drawTime);
        }
        partial void PickingUpdate(RenderUIElement renderUIElement, Viewport viewport, ref Matrix worldViewProj, GameTime drawTime)
        {
            if (renderUIElement.UIComponent.Page?.RootElement == null)
            {
                return;
            }

            UpdateMouseOver(ref viewport, ref worldViewProj, renderUIElement);
            UpdateTouchEvents(ref viewport, ref worldViewProj, renderUIElement, drawTime);
        }
Example #5
0
        private void UpdateTouchEvents(ref Viewport viewport, ref Matrix worldViewProj, RenderUIElement state, GameTime gameTime)
        {
            var rootElement       = state.UIComponent.Page.RootElement;
            var intersectionPoint = Vector3.Zero;
            var lastTouchPosition = new Vector2(float.NegativeInfinity);

            // analyze pointer event input and trigger UI touch events depending on hit Tests
            foreach (var pointerEvent in compactedPointerEvents)
            {
                // performance optimization: skip all the events that started outside of the UI
                var lastTouchedElement = state.LastTouchedElement;
                if (lastTouchedElement == null && pointerEvent.EventType != PointerEventType.Pressed)
                {
                    continue;
                }

                var time = gameTime.Total;

                var currentTouchPosition  = pointerEvent.Position;
                var currentTouchedElement = lastTouchedElement;

                // re-calculate the element under cursor if click position changed.
                if (lastTouchPosition != currentTouchPosition)
                {
                    Ray uiRay;
                    if (!GetTouchPosition(state.UIComponent, ref viewport, ref worldViewProj, currentTouchPosition, out uiRay))
                    {
                        continue;
                    }

                    currentTouchedElement = GetElementAtScreenPosition(rootElement, ref uiRay, ref worldViewProj, ref intersectionPoint);
                }

                if (pointerEvent.EventType == PointerEventType.Pressed || pointerEvent.EventType == PointerEventType.Released)
                {
                    state.LastIntersectionPoint = intersectionPoint;
                }

                // TODO: add the pointer type to the event args?
                var touchEvent = new TouchEventArgs
                {
                    Action            = TouchAction.Down,
                    Timestamp         = time,
                    ScreenPosition    = currentTouchPosition,
                    ScreenTranslation = pointerEvent.DeltaPosition,
                    WorldPosition     = intersectionPoint,
                    WorldTranslation  = intersectionPoint - state.LastIntersectionPoint
                };

                switch (pointerEvent.EventType)
                {
                case PointerEventType.Pressed:
                    touchEvent.Action = TouchAction.Down;
                    currentTouchedElement?.RaiseTouchDownEvent(touchEvent);
                    break;

                case PointerEventType.Released:
                    touchEvent.Action = TouchAction.Up;

                    // generate enter/leave events if we passed from an element to another without move events
                    if (currentTouchedElement != lastTouchedElement)
                    {
                        ThrowEnterAndLeaveTouchEvents(currentTouchedElement, lastTouchedElement, touchEvent);
                    }

                    // trigger the up event
                    currentTouchedElement?.RaiseTouchUpEvent(touchEvent);
                    break;

                case PointerEventType.Moved:
                    touchEvent.Action = TouchAction.Move;

                    // first notify the move event (even if the touched element changed in between it is still coherent in one of its parents)
                    currentTouchedElement?.RaiseTouchMoveEvent(touchEvent);

                    // then generate enter/leave events if we passed from an element to another
                    if (currentTouchedElement != lastTouchedElement)
                    {
                        ThrowEnterAndLeaveTouchEvents(currentTouchedElement, lastTouchedElement, touchEvent);
                    }
                    break;

                case PointerEventType.Canceled:
                    touchEvent.Action = TouchAction.Move;

                    // generate enter/leave events if we passed from an element to another without move events
                    if (currentTouchedElement != lastTouchedElement)
                    {
                        ThrowEnterAndLeaveTouchEvents(currentTouchedElement, lastTouchedElement, touchEvent);
                    }

                    // then raise leave event to all the hierarchy of the previously selected element.
                    var element = currentTouchedElement;
                    while (element != null)
                    {
                        if (element.IsTouched)
                        {
                            element.RaiseTouchLeaveEvent(touchEvent);
                        }
                        element = element.VisualParent;
                    }
                    break;

                default:
                    throw new ArgumentOutOfRangeException();
                }

                lastTouchPosition           = currentTouchPosition;
                state.LastTouchedElement    = currentTouchedElement;
                state.LastIntersectionPoint = intersectionPoint;
            }
        }
        private void UpdateMouseOver(ref Viewport viewport, ref Matrix worldViewProj, RenderUIElement state)
        {
            if (input == null || !input.HasMouse)
                return;

            var intersectionPoint = Vector3.Zero;
            var mousePosition = input.MousePosition;
            var rootElement = state.UIComponent.Page.RootElement;
            var lastMouseOverElement = state.LastMouseOverElement;
            var mouseOverElement = lastMouseOverElement;

            // determine currently overred element.
            if (mousePosition != state.LastMousePosition)
            {
                Ray uiRay;
                if (!GetTouchPosition(state.UIComponent, ref viewport, ref worldViewProj, mousePosition, out uiRay))
                    return;

                mouseOverElement = GetElementAtScreenPosition(rootElement, ref uiRay, ref worldViewProj, ref intersectionPoint);
            }

            // find the common parent between current and last overred elements
            var commonElement = FindCommonParent(mouseOverElement, lastMouseOverElement);

            // disable mouse over state to previously overred hierarchy
            var parent = lastMouseOverElement;
            while (parent != commonElement && parent != null)
            {
                parent.MouseOverState = MouseOverState.MouseOverNone;
                parent = parent.VisualParent;
            }

            // enable mouse over state to currently overred hierarchy
            if (mouseOverElement != null)
            {
                // the element itself
                mouseOverElement.MouseOverState = MouseOverState.MouseOverElement;

                // its hierarchy
                parent = mouseOverElement.VisualParent;
                while (parent != null)
                {
                    if (parent.IsHierarchyEnabled)
                        parent.MouseOverState = MouseOverState.MouseOverChild;

                    parent = parent.VisualParent;
                }
            }

            // update cached values
            state.LastMouseOverElement = mouseOverElement;
            state.LastMousePosition = mousePosition;
        }
        private void UpdateTouchEvents(ref Viewport viewport, ref Matrix worldViewProj, RenderUIElement state, GameTime gameTime)
        {
            var rootElement = state.UIComponent.Page.RootElement;
            var intersectionPoint = Vector3.Zero;
            var lastTouchPosition = new Vector2(float.NegativeInfinity);

            // analyze pointer event input and trigger UI touch events depending on hit Tests
            foreach (var pointerEvent in compactedPointerEvents)
            {
                // performance optimization: skip all the events that started outside of the UI
                var lastTouchedElement = state.LastTouchedElement;
                if (lastTouchedElement == null && pointerEvent.State != PointerState.Down)
                    continue;

                var time = gameTime.Total;

                var currentTouchPosition = pointerEvent.Position;
                var currentTouchedElement = lastTouchedElement;

                // re-calculate the element under cursor if click position changed.
                if (lastTouchPosition != currentTouchPosition)
                {
                    Ray uiRay;
                    if (!GetTouchPosition(state.UIComponent, ref viewport, ref worldViewProj, currentTouchPosition, out uiRay))
                        continue;

                    currentTouchedElement = GetElementAtScreenPosition(rootElement, ref uiRay, ref worldViewProj, ref intersectionPoint);
                }

                if (pointerEvent.State == PointerState.Down || pointerEvent.State == PointerState.Up)
                    state.LastIntersectionPoint = intersectionPoint;

                // TODO: add the pointer type to the event args?
                var touchEvent = new TouchEventArgs
                {
                    Action = TouchAction.Down,
                    Timestamp = time,
                    ScreenPosition = currentTouchPosition,
                    ScreenTranslation = pointerEvent.DeltaPosition,
                    WorldPosition = intersectionPoint,
                    WorldTranslation = intersectionPoint - state.LastIntersectionPoint
                };

                switch (pointerEvent.State)
                {
                    case PointerState.Down:
                        touchEvent.Action = TouchAction.Down;
                        currentTouchedElement?.RaiseTouchDownEvent(touchEvent);
                        break;

                    case PointerState.Up:
                        touchEvent.Action = TouchAction.Up;

                        // generate enter/leave events if we passed from an element to another without move events
                        if (currentTouchedElement != lastTouchedElement)
                            ThrowEnterAndLeaveTouchEvents(currentTouchedElement, lastTouchedElement, touchEvent);

                        // trigger the up event
                        currentTouchedElement?.RaiseTouchUpEvent(touchEvent);
                        break;

                    case PointerState.Move:
                        touchEvent.Action = TouchAction.Move;

                        // first notify the move event (even if the touched element changed in between it is still coherent in one of its parents)
                        currentTouchedElement?.RaiseTouchMoveEvent(touchEvent);

                        // then generate enter/leave events if we passed from an element to another
                        if (currentTouchedElement != lastTouchedElement)
                            ThrowEnterAndLeaveTouchEvents(currentTouchedElement, lastTouchedElement, touchEvent);
                        break;

                    case PointerState.Out:
                    case PointerState.Cancel:
                        touchEvent.Action = TouchAction.Move;

                        // generate enter/leave events if we passed from an element to another without move events
                        if (currentTouchedElement != lastTouchedElement)
                            ThrowEnterAndLeaveTouchEvents(currentTouchedElement, lastTouchedElement, touchEvent);

                        // then raise leave event to all the hierarchy of the previously selected element.
                        var element = currentTouchedElement;
                        while (element != null)
                        {
                            if (element.IsTouched)
                                element.RaiseTouchLeaveEvent(touchEvent);
                            element = element.VisualParent;
                        }
                        break;
                    default:
                        throw new ArgumentOutOfRangeException();
                }

                lastTouchPosition = currentTouchPosition;
                state.LastTouchedElement = currentTouchedElement;
                state.LastIntersectionPoint = intersectionPoint;
            }
        }
Example #8
0
 partial void PickingUpdate(RenderUIElement renderUIElement, Viewport viewport, ref Matrix worldViewProj, GameTime drawTime);
Example #9
0
 public UIElementState(RenderUIElement renderObject)
 {
     RenderObject = renderObject;
     WorldViewProjectionMatrix = Matrix.Identity;
 }
Example #10
0
 partial void PickingUpdate(RenderUIElement renderUIElement, Viewport viewport, GameTime drawTime);
 partial void PickingUpdate(RenderUIElement renderUIElement, Viewport viewport, ref Matrix worldViewProj, GameTime drawTime);
 public UIElementState(RenderUIElement renderObject)
 {
     RenderObject = renderObject;
     WorldViewProjectionMatrix = Matrix.Identity;
 }