private bool handleMouseMove(InputState state) { return(positionalInputQueue.Any(target => target.TriggerOnMouseMove(state))); }
protected virtual void TransformState(InputState inputState) { }
private void updateMouseEvents(InputState state) { MouseState mouse = (MouseState)state.Mouse; var last = state.Last?.Mouse as MouseState; if (last == null) { return; } if (mouse.Position != last.Position) { handleMouseMove(state); if (isDragging) { handleMouseDrag(state); } } for (MouseButton b = 0; b < MouseButton.LastButton; b++) { var lastPressed = last.IsPressed(b); if (lastPressed != mouse.IsPressed(b)) { if (lastPressed) { handleMouseUp(state, b); } else { handleMouseDown(state, b); } } } if (mouse.WheelDelta != 0) { handleWheel(state); } if (mouse.HasAnyButtonPressed) { if (!last.HasAnyButtonPressed) { //stuff which only happens once after the mousedown state mouse.PositionMouseDown = state.Mouse.Position; LastActionTime = Time.Current; if (mouse.IsPressed(MouseButton.Left)) { isValidClick = true; if (Time.Current - lastClickTime < double_click_time) { if (handleMouseDoubleClick(state)) { //when we handle a double-click we want to block a normal click from firing. isValidClick = false; } lastClickTime = 0; } lastClickTime = Time.Current; } } if (!isDragging && Vector2Extensions.Distance(mouse.PositionMouseDown ?? mouse.Position, mouse.Position) > drag_start_distance) { isDragging = true; handleMouseDragStart(state); } } else if (last.HasAnyButtonPressed) { if (isValidClick && (DraggedDrawable == null || Vector2Extensions.Distance(mouse.PositionMouseDown ?? mouse.Position, mouse.Position) < click_drag_distance)) { handleMouseClick(state); } mouseDownInputQueue = null; mouse.PositionMouseDown = null; isValidClick = false; if (isDragging) { isDragging = false; handleMouseDragEnd(state); } } }
private bool handleMouseMove(InputState state) { return(mouseInputQueue.Any(target => target.TriggerMouseMove(state))); }
/// <summary> /// In order to provide a reliable event system to drawables, we want to ensure that we reprocess input queues (via the /// main loop in<see cref="updateInputQueues(InputState)"/> after each and every button or key change. This allows /// correct behaviour in a case where the input queues change based on triggered by a button or key. /// </summary> /// <param name="states">A list of <see cref="InputState"/>s</param> /// <returns>Processed states such that at most one button change occurs between any two consecutive states.</returns> private IEnumerable <InputState> createDistinctInputStates(List <InputState> states) { InputState last = CurrentState; foreach (var i in states) { //first we want to create a copy of ourselves without any button changes //we do this by updating our buttons to the state of the last frame. var iWithoutButtons = i.Clone(); var iHasMouse = iWithoutButtons.Mouse != null; var iHasKeyboard = iWithoutButtons.Keyboard != null; if (iHasMouse) { for (MouseButton b = 0; b < MouseButton.LastButton; b++) { iWithoutButtons.Mouse.SetPressed(b, last.Mouse?.IsPressed(b) ?? false); } } if (iHasKeyboard) { iWithoutButtons.Keyboard.Keys = last.Keyboard?.Keys ?? new Key[] { } } ; //we start by adding this state to the processed list... yield return(iWithoutButtons); last = iWithoutButtons; //and then iterate over each button/key change, adding intermediate states along the way. if (iHasMouse) { for (MouseButton b = 0; b < MouseButton.LastButton; b++) { if (i.Mouse.IsPressed(b) != (last.Mouse?.IsPressed(b) ?? false)) { var intermediateState = last.Clone(); if (intermediateState.Mouse == null) { intermediateState.Mouse = new MouseState(); } //add our single local change intermediateState.Mouse.SetPressed(b, i.Mouse.IsPressed(b)); last = intermediateState; yield return(intermediateState); } } } if (iHasKeyboard) { foreach (var releasedKey in last.Keyboard?.Keys.Except(i.Keyboard.Keys) ?? new Key[] { }) { var intermediateState = last.Clone(); if (intermediateState.Keyboard == null) { intermediateState.Keyboard = new KeyboardState(); } intermediateState.Keyboard.Keys = intermediateState.Keyboard.Keys.Where(d => d != releasedKey); last = intermediateState; yield return(intermediateState); } foreach (var pressedKey in i.Keyboard.Keys.Except(last.Keyboard?.Keys ?? new Key[] { })) { var intermediateState = last.Clone(); if (intermediateState.Keyboard == null) { intermediateState.Keyboard = new KeyboardState(); } intermediateState.Keyboard.Keys = intermediateState.Keyboard.Keys.Union(new[] { pressedKey }); last = intermediateState; yield return(intermediateState); } } } }
private bool handleWheel(InputState state) { return(PropagateWheel(positionalInputQueue, state)); }
/// <summary> /// Handles the button being released. /// </summary> /// <param name="state">The current <see cref="InputState"/>.</param> /// <param name="targets">The list of targets that must handle the event. This will contain targets up to the target that handled the button down event.</param> protected abstract void HandleButtonUp(InputState state, List <Drawable> targets);
private bool handleMouseMove(InputState state, Vector2 lastPosition) { return(PropagateBlockableEvent(PositionalInputQueue, new MouseMoveEvent(state, lastPosition))); }
private bool handleScroll(InputState state, Vector2 lastScroll, bool isPrecise) { return(PropagateBlockableEvent(PositionalInputQueue, new ScrollEvent(state, state.Mouse.Scroll - lastScroll, isPrecise))); }
private void focusTopMostRequestingDrawable(InputState state) => keyboardInputQueue.FirstOrDefault(target => target.RequestingFocus)?.TriggerFocus(state, true);
// set PositionMouseDown right before the event is invoked so it can be used as the mouse down position for each button private void setPositionMouseDown(InputState state) { state.Mouse.PositionMouseDown = MouseDownPosition; }
private bool handleWheel(InputState state) { return(mouseInputQueue.Any(target => target.TriggerWheel(state))); }
private bool handleMouseDragStart(InputState state) { draggingDrawable = mouseDownInputQueue?.FirstOrDefault(target => target.IsAlive && target.TriggerDragStart(state)); return(draggingDrawable != null); }
private bool handleMouseDoubleClick(InputState state) { return(mouseInputQueue.Any(target => target.TriggerDoubleClick(state))); }
private bool handleMouseDoubleClick(InputState state) { return(positionalInputQueue.Any(target => target.TriggerOnDoubleClick(state))); }
private bool handleKeyDown(InputState state, Key key, bool repeat) { return(PropagateBlockableEvent(NonPositionalInputQueue, new KeyDownEvent(state, key, repeat))); }
private bool handleMouseDrag(InputState state) { //Once a drawable is dragged, it remains in a dragged state until the drag is finished. return(DraggedDrawable?.TriggerOnDrag(state) ?? false); }
private bool handleKeyUp(InputState state, Key key) { return(PropagateBlockableEvent(NonPositionalInputQueue, new KeyUpEvent(state, key))); }
/// <summary> /// Handles the button being released. /// </summary> /// <param name="state">The current <see cref="InputState"/>.</param> private void handleButtonUp(InputState state) { HandleButtonUp(state, ButtonDownInputQueue); ButtonDownInputQueue = null; }
private bool handleJoystickRelease(InputState state, JoystickButton button) { return(PropagateBlockableEvent(NonPositionalInputQueue, new JoystickReleaseEvent(state, button))); }
/// <summary> /// Handles the button being pressed. /// </summary> /// <param name="state">The current <see cref="InputState"/>.</param> /// <param name="targets">The list of possible targets that can handle the event.</param> /// <returns>The <see cref="Drawable"/> that handled the event.</returns> protected abstract Drawable HandleButtonDown(InputState state, List <Drawable> targets);
protected override void Update() { var pendingStates = createDistinctInputStates(GetPendingStates()).ToArray(); unfocusIfNoLongerValid(CurrentState); //we need to make sure the code in the foreach below is run at least once even if we have no new pending states. if (pendingStates.Length == 0) { pendingStates = new[] { CurrentState } } ; foreach (InputState s in pendingStates) { bool hasKeyboard = s.Keyboard != null; bool hasMouse = s.Mouse != null; if (!hasKeyboard && !hasMouse) { continue; } var last = CurrentState; //avoid lingering references that would stay forever. last.Last = null; CurrentState = s; CurrentState.Last = last; if (CurrentState.Keyboard == null) { CurrentState.Keyboard = last.Keyboard ?? new KeyboardState(); } if (CurrentState.Mouse == null) { CurrentState.Mouse = last.Mouse ?? new MouseState(); } TransformState(CurrentState); //move above? updateInputQueues(CurrentState); if (hasMouse) { (s.Mouse as MouseState)?.SetLast(last.Mouse); //necessary for now as last state is used internally for stuff updateHoverEvents(CurrentState); updateMouseEvents(CurrentState); } if (hasKeyboard) { updateKeyboardEvents(CurrentState); } } if (CurrentState.Mouse != null) { foreach (var d in mouseInputQueue) { if (d is IRequireHighFrequencyMousePosition) { if (d.TriggerMouseMove(CurrentState)) { break; } } } } keyboardRepeatTime -= Time.Elapsed; if (FocusedDrawable == null) { focusTopMostRequestingDrawable(CurrentState); } base.Update(); }