/// <summary> /// Called to capture input and manage events. All layers will get events, they must determine if they want /// to work based on the EventProcessingAllowed property of their event layer. /// </summary> /// <param name="time">The clock with info about this frame.</param> public void updateEvents(Clock clock) { //Process the whole update with the same focus layer EventLayer currentFocusLayer = focusLayer; pad1Hardware.Update(); pad2Hardware.Update(); pad3Hardware.Update(); pad4Hardware.Update(); mouse.capture(); bool allowEventProcessing = true; //The first layer always gets all events //If there is a focus layer, process it first if (currentFocusLayer != null) { allowEventProcessing = processLayer(clock, allowEventProcessing, currentFocusLayer); } //Process all other layers skipping the focus layer foreach (var layer in eventLayers) { if (layer != currentFocusLayer) { allowEventProcessing = processLayer(clock, allowEventProcessing, layer); } } mouse.postUpdate(); touches.tick(); }
/// <summary> /// Clear the focus layer if the passed layer is currently the focus layer, otherwise does nothing. /// </summary> internal void clearFocusLayer(EventLayer layer) { if (focusLayer == layer) { focusLayer = null; } }
private void computeZoom(EventLayer eventLayer, ref bool didGesture, Finger finger1, Finger finger2, ref Vector2 finger1Vec, ref Vector2 finger2Vec) { Vector2 finger1Pos = new Vector2(finger1.NrmlX, finger1.NrmlY); Vector2 finger2Pos = new Vector2(finger2.NrmlX, finger2.NrmlY); float currentPinchDistance = (finger1Pos - finger2Pos).length2(); Vector2 vectorSum = finger1Vec - finger2Vec; momentumDirection = 1.0f; zoomDelta = vectorSum.length(); momentum = zoomDelta; deceleration = momentum / decelerationTime; if (currentPinchDistance > lastPinchDistance) { zoomDelta = -zoomDelta; momentumDirection = -1.0f; } didGesture = true; lastPinchDistance = currentPinchDistance; if (!gestureStarted) { gestureStarted = true; if (GestureStarted != null) { GestureStarted.Invoke(eventLayer, this); } } if (Zoom != null) { Zoom.Invoke(eventLayer, this); } }
/// <summary> /// Process a layer. /// </summary> private static bool processLayer(Clock clock, bool allowEventProcessing, EventLayer layer) { //First try to update the layer with the current allowEventProcessing layer.update(allowEventProcessing, clock); //Modify allowEventProcessing as needed, if we have already set allowEventProcessing to false it should stay false allowEventProcessing = allowEventProcessing && !layer.SkipNextLayer; //Reset the layer's HandledEvents for this frame, this is done last to reset without iterating again. //Doing this last also ensures that if we stopped early on one of the fire events below that that layer //keeps its HandledEvents property set where it should be. layer.HandledEvents = false; return(allowEventProcessing); }
/// <summary> /// Internal method to make sure all the buttons for the event are pressed. /// </summary> /// <param name="eventManager">The event manager with the keyboard and mouse being used.</param> /// <returns>True if all the required buttons are pressed.</returns> private ButtonScanResult scanButtons(EventLayer eventLayer) { Mouse mouse = eventLayer.Mouse; Keyboard keyboard = eventLayer.Keyboard; Gamepad pad = eventLayer.getGamepad(this.pad); bool allActivated = keyboardButtons.Count + mouseButtons.Count + gamepadButtons.Count > 0 || MouseWheelDirection > 0; bool anyDownUpThisFrame = false; bool currentDownUpThisFrame; if (allActivated) { foreach (KeyboardButtonCode keyCode in keyboardButtons) { allActivated &= keyboard.isKeyDown(keyCode); if (!allActivated) { break; } } if (allActivated) { foreach (var keyCode in gamepadButtons) { allActivated &= pad.isButtonDown(keyCode); if (!allActivated) { break; } } } if (allActivated) { foreach (MouseButtonCode mouseCode in mouseButtons) { currentDownUpThisFrame = mouse.buttonDownAndUpThisFrame(mouseCode); allActivated &= (mouse.buttonDown(mouseCode) || currentDownUpThisFrame); if (!allActivated) { break; } anyDownUpThisFrame |= currentDownUpThisFrame; } } if (allActivated) { switch (MouseWheelDirection) { case MouseWheelDirection.Up: allActivated &= mouse.RelativePosition.z > 0; break; case MouseWheelDirection.Down: allActivated &= mouse.RelativePosition.z < 0; break; } } } if (allActivated) { if (anyDownUpThisFrame) { return(ButtonScanResult.DownAndUpThisFrame); } return(ButtonScanResult.Down); } else { return(ButtonScanResult.Up); } }
/// <summary> /// Called internally to manage status of the event. /// </summary> protected internal override void update(EventLayer eventLayer, bool allowProcessing, Clock clock) { switch (scanButtons(eventLayer)) { case ButtonScanResult.Down: if (FirstFrameDown) { HeldDown = true; FirstFrameDown = false; } if (HeldDown) { if (OnHeldDown != null) { OnHeldDown.Invoke(eventLayer); } if (OnDown != null) { OnDown.Invoke(eventLayer); } } else { FirstFrameDown = true; if (FirstFrameDownEvent != null) { FirstFrameDownEvent.Invoke(eventLayer); } if (OnDown != null) { OnDown.Invoke(eventLayer); } } FirstFrameUp = false; ReleasedUp = false; break; case ButtonScanResult.Up: if (FirstFrameUp) { ReleasedUp = true; FirstFrameUp = false; } else if (!ReleasedUp) { FirstFrameUp = true; if (FirstFrameUpEvent != null) { FirstFrameUpEvent.Invoke(eventLayer); } } FirstFrameDown = false; HeldDown = false; break; case ButtonScanResult.DownAndUpThisFrame: DownAndUpThisFrame = true; FirstFrameDown = true; if (FirstFrameDownEvent != null) { FirstFrameDownEvent.Invoke(eventLayer); } FirstFrameUp = true; FirstFrameDown = false; if (FirstFrameUpEvent != null) { FirstFrameUpEvent.Invoke(eventLayer); } ReleasedUp = false; HeldDown = false; DownAndUpThisFrame = false; break; } }
/// <summary> /// Set the focus layer overriding any existing focus layer. /// </summary> internal void setFocusLayer(EventLayer layer) { focusLayer = layer; }
/// <summary> /// The update function, do not call this outside EventManager. /// </summary> /// <param name="eventLayer"></param> /// <param name="allowProcessing"></param> protected internal abstract void update(EventLayer eventLayer, bool allowProcessing, Clock clock);
protected internal override void update(EventLayer eventLayer, bool allowProcessing, Clock clock) { var touches = eventLayer.EventManager.Touches; var fingers = touches.Fingers; if (fingers.Count == fingerCount) { Vector2 primaryFingerVec = new Vector2(fingers[0].PixelDeltaX, fingers[0].PixelDeltaY); float primaryFingerLen = primaryFingerVec.length(); Vector2 longestLengthVec = primaryFingerVec; float longestLength = primaryFingerLen; if (primaryFingerLen > 0) { bool allVectorsSameDirection = true; for (int i = 1; i < fingerCount && allVectorsSameDirection; ++i) { Vector2 testFingerVec = new Vector2(fingers[i].PixelDeltaX, fingers[i].PixelDeltaY); float testFingerLen = testFingerVec.length(); if (testFingerLen > 0) { float cosTheta = primaryFingerVec.dot(ref testFingerVec) / (primaryFingerLen * testFingerLen); if (cosTheta > 0.5f) { if (testFingerLen > longestLength) { longestLengthVec = testFingerVec; longestLength = testFingerLen; } } else { allVectorsSameDirection = false; } } } if (allVectorsSameDirection) { DeltaX = longestLengthVec.x; DeltaY = longestLengthVec.y; AbsoluteX = fingers[0].PixelX; AbsoluteY = fingers[0].PixelY; if (!gestureStarted) { cancelMomentum(); gestureStarted = true; if (GestureStarted != null) { GestureStarted.Invoke(eventLayer, this); } } didGesture = true; averageSpeed[averageSpeedCursor] = longestLengthVec; averageSpeedCursor++; averageSpeedCursor %= averageSpeed.Length; //Make sure to fire event last so momentum can be canceled if needed if (Dragged != null) { Dragged.Invoke(eventLayer, this); } } } else if (gestureStarted) { //If we have done the gesture once and the correct number of fingers are down, keep reporting that we did the gesture didGesture = true; } } if (!didGesture) { if (gestureStarted) { momentumStarted = true; momentum = new IntVector2(0, 0); for (int i = 0; i < averageSpeed.Length; ++i) { momentum += averageSpeed[i]; } momentum /= averageSpeed.Length; momentumDirection = new Vector2(1.0f, 1.0f); if (momentum.x < 0.0f) { momentum.x = -momentum.x; momentumDirection.x = -1.0f; } if (momentum.y < 0.0f) { momentum.y = -momentum.y; momentumDirection.y = -1.0f; } if (momentum.x < minimumMomentum) { momentum.x = 0.0f; } if (momentum.y < minimumMomentum) { momentum.y = 0.0f; } deceleration = momentum / decelerationTime; //Important to fire event last so momentum can be canceled if needed if (MomentumStarted != null) { MomentumStarted(eventLayer, this); } } gestureStarted = false; if (momentum.length2() != 0.0f) { momentum -= deceleration * clock.DeltaSeconds; if (momentum.x < 0.0f) { momentum.x = 0.0f; } if (momentum.y <= 0.0f) { momentum.y = 0.0f; } Vector2 finalMomentum = momentum * momentumDirection; DeltaX = finalMomentum.x; DeltaY = finalMomentum.y; if (Dragged != null) { Dragged.Invoke(eventLayer, this); } } else if (momentumStarted) { momentumStarted = false; if (MomentumEnded != null) { MomentumEnded.Invoke(eventLayer, this); } } } didGesture = false; }
protected internal override void update(EventLayer eventLayer, bool allowProcessing, Clock clock) { var touches = eventLayer.EventManager.Touches; var fingers = touches.Fingers; if (fingers.Count == 2) { Finger finger1 = fingers[0]; Finger finger2 = fingers[1]; Vector2 finger1Vec = new Vector2(finger1.NrmlDeltaX, finger1.NrmlDeltaY); Vector2 finger2Vec = new Vector2(finger2.NrmlDeltaX, finger2.NrmlDeltaY); float finger1Len = finger1Vec.length2(); float finger2Len = finger2Vec.length2(); if (finger1Len > 0 || finger2Len > 0) { if (finger1Len > 0 && finger2Len > 0) { float cosTheta = finger1Vec.dot(ref finger2Vec) / (finger1Vec.length() * finger2Vec.length()); if (cosTheta < -0.5f && Zoom != null) { computeZoom(eventLayer, ref didGesture, finger1, finger2, ref finger1Vec, ref finger2Vec); } } else if (finger1Len == 0 && finger2Len > 0) { computeZoom(eventLayer, ref didGesture, finger1, finger2, ref finger1Vec, ref finger2Vec); } else if (finger2Len == 0 && finger1Len > 0) { computeZoom(eventLayer, ref didGesture, finger1, finger2, ref finger1Vec, ref finger2Vec); } } } //Momentum if (!didGesture) { if (momentum > 0.0f) { zoomDelta = momentum * momentumDirection; if (!momentumStarted) { momentumStarted = true; if (MomentumStarted != null) { MomentumStarted.Invoke(eventLayer, this); } } momentum -= deceleration * clock.DeltaSeconds; if (momentum < 0.0f) { momentum = 0.0f; } if (Zoom != null) { Zoom.Invoke(eventLayer, this); } } else if (momentumStarted) { zoomDelta = 0.0f; momentumStarted = false; gestureStarted = false; if (MomentumEnded != null) { MomentumEnded.Invoke(eventLayer, this); } } } didGesture = false; }