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); }
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; } }
partial void PickingUpdate(RenderUIElement renderUIElement, Viewport viewport, ref Matrix worldViewProj, GameTime drawTime);
public UIElementState(RenderUIElement renderObject) { RenderObject = renderObject; WorldViewProjectionMatrix = Matrix.Identity; }
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; }