1
0
mirror of https://github.com/vcmi/vcmi.git synced 2024-12-14 10:12:59 +02:00
vcmi/client/eventsSDL/InputSourceTouch.h
2024-11-02 19:15:49 +01:00

131 lines
3.9 KiB
C++

/*
* InputSourceTouch.h, part of VCMI engine
*
* Authors: listed in file AUTHORS in main folder
*
* License: GNU General Public License v2.0 or later
* Full text of license available in license.txt file, in main folder
*
*/
#pragma once
#include "../../lib/Point.h"
// Debug option. If defined, mouse events will instead generate touch events, allowing testing of touch input on desktop
// #define VCMI_EMULATE_TOUCHSCREEN_WITH_MOUSE
enum class MouseButton;
struct SDL_TouchFingerEvent;
/// Enumeration that describes current state of gesture recognition
enum class TouchState
{
// special state that allows no transitions
// used when player selects "relative mode" in Launcher
// in this mode touchscreen acts like touchpad, moving cursor at certains speed
// and generates events for positions below cursor instead of positions below touch events
RELATIVE_MODE,
// no active touch events
// DOWN -> transition to TAP_DOWN_SHORT
// MOTION / UP -> not expected
IDLE,
// single finger is touching the screen for a short time
// DOWN -> transition to TAP_DOWN_DOUBLE
// MOTION -> transition to TAP_DOWN_PANNING
// UP -> transition to IDLE, emit onLeftClickDown and onLeftClickUp
// on timer -> transition to TAP_DOWN_LONG, emit showPopup() event
TAP_DOWN_SHORT,
// single finger is moving across screen
// DOWN -> transition to TAP_DOWN_DOUBLE
// MOTION -> emit panning event
// UP -> transition to IDLE
TAP_DOWN_PANNING,
// single finger is moving across screen
// DOWN -> ignored
// MOTION -> emit panning event
// UP -> transition to TAP_DOWN_LONG_AWAIT
TAP_DOWN_PANNING_POPUP,
// two fingers are touching the screen
// DOWN -> ??? how to handle 3rd finger? Ignore?
// MOTION -> emit pinch event
// UP -> transition to TAP_DOWN
TAP_DOWN_DOUBLE,
// single finger is down for long period of time
// DOWN -> ignored
// MOTION -> ignored
// UP -> transition to TAP_DOWN_LONG_AWAIT
TAP_DOWN_LONG,
// right-click popup is active, waiting for new tap to hide popup
// DOWN -> ignored
// MOTION -> transition to TAP_DOWN_PANNING_POPUP
// UP -> transition to IDLE, generate closePopup() event
TAP_DOWN_LONG_AWAIT,
};
struct TouchInputParameters
{
/// Speed factor of mouse pointer when relative mode is used
double relativeModeSpeedFactor = 1.0;
/// tap for period longer than specified here will be qualified as "long tap", triggering corresponding gesture
uint32_t longTouchTimeMilliseconds = 750;
/// time span in where the second tap has to happen for qualifing as "double click"
uint32_t doubleTouchTimeMilliseconds = 500;
/// max distance in where the second tap has to happen for qualifing as "double click"
uint32_t doubleTouchToleranceDistance = 50;
/// moving finger for distance larger than specified will be qualified as panning gesture instead of long press
uint32_t panningSensitivityThreshold = 15;
/// gesture will be qualified as pinch if distance between fingers is at least specified here
uint32_t pinchSensitivityThreshold = 10;
/// touch event will trigger clicking of elements up to X pixels away from actual touch position
uint32_t touchToleranceDistance = 20;
bool useRelativeMode = false;
bool hapticFeedbackEnabled = false;
};
/// Class that handles touchscreen input from SDL events
class InputSourceTouch
{
TouchInputParameters params;
TouchState state;
uint32_t lastTapTimeTicks;
Point lastTapPosition;
uint32_t lastLeftClickTimeTicks;
Point lastLeftClickPosition;
Point convertTouchToMouse(const SDL_TouchFingerEvent & current);
Point convertTouchToMouse(float x, float y);
void emitPanningEvent(const SDL_TouchFingerEvent & tfinger);
void emitPinchEvent(const SDL_TouchFingerEvent & tfinger);
public:
InputSourceTouch();
void handleEventFingerMotion(const SDL_TouchFingerEvent & current);
void handleEventFingerDown(const SDL_TouchFingerEvent & current);
void handleEventFingerUp(const SDL_TouchFingerEvent & current);
void hapticFeedback();
void handleUpdate();
bool hasTouchInputDevice() const;
};