1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-01-12 02:28:11 +02:00

Allow input configuration via config file

This commit is contained in:
Ivan Savenko 2024-04-30 20:11:09 +03:00
parent 3749439702
commit 89d6ddd916
8 changed files with 155 additions and 38 deletions

View File

@ -38,6 +38,9 @@ InputHandler::InputHandler()
, fingerHandler(std::make_unique<InputSourceTouch>())
, textHandler(std::make_unique<InputSourceText>())
, gameControllerHandler(std::make_unique<InputSourceGameController>())
, enableMouse(settings["input"]["enableMouse"].Bool())
, enableTouch(settings["input"]["enableTouch"].Bool())
, enableController(settings["input"]["enableController"].Bool())
{
}
@ -48,35 +51,59 @@ void InputHandler::handleCurrentEvent(const SDL_Event & current)
switch (current.type)
{
case SDL_KEYDOWN:
return keyboardHandler->handleEventKeyDown(current.key);
keyboardHandler->handleEventKeyDown(current.key);
return;
case SDL_KEYUP:
return keyboardHandler->handleEventKeyUp(current.key);
keyboardHandler->handleEventKeyUp(current.key);
return;
#ifndef VCMI_EMULATE_TOUCHSCREEN_WITH_MOUSE
case SDL_MOUSEMOTION:
return mouseHandler->handleEventMouseMotion(current.motion);
if (enableMouse)
mouseHandler->handleEventMouseMotion(current.motion);
return;
case SDL_MOUSEBUTTONDOWN:
return mouseHandler->handleEventMouseButtonDown(current.button);
if (enableMouse)
mouseHandler->handleEventMouseButtonDown(current.button);
return;
case SDL_MOUSEBUTTONUP:
return mouseHandler->handleEventMouseButtonUp(current.button);
if (enableMouse)
mouseHandler->handleEventMouseButtonUp(current.button);
return;
case SDL_MOUSEWHEEL:
return mouseHandler->handleEventMouseWheel(current.wheel);
if (enableMouse)
mouseHandler->handleEventMouseWheel(current.wheel);
return;
#endif
case SDL_TEXTINPUT:
return textHandler->handleEventTextInput(current.text);
textHandler->handleEventTextInput(current.text);
return;
case SDL_TEXTEDITING:
return textHandler->handleEventTextEditing(current.edit);
textHandler->handleEventTextEditing(current.edit);
return;
case SDL_FINGERMOTION:
return fingerHandler->handleEventFingerMotion(current.tfinger);
if (enableTouch)
fingerHandler->handleEventFingerMotion(current.tfinger);
return;
case SDL_FINGERDOWN:
return fingerHandler->handleEventFingerDown(current.tfinger);
if (enableTouch)
fingerHandler->handleEventFingerDown(current.tfinger);
return;
case SDL_FINGERUP:
return fingerHandler->handleEventFingerUp(current.tfinger);
if (enableTouch)
fingerHandler->handleEventFingerUp(current.tfinger);
return;
case SDL_CONTROLLERAXISMOTION:
return gameControllerHandler->handleEventAxisMotion(current.caxis);
if (enableController)
gameControllerHandler->handleEventAxisMotion(current.caxis);
return;
case SDL_CONTROLLERBUTTONDOWN:
return gameControllerHandler->handleEventButtonDown(current.cbutton);
if (enableController)
gameControllerHandler->handleEventButtonDown(current.cbutton);
return;
case SDL_CONTROLLERBUTTONUP:
return gameControllerHandler->handleEventButtonUp(current.cbutton);
if (enableController)
gameControllerHandler->handleEventButtonUp(current.cbutton);
return;
}
}

View File

@ -30,6 +30,10 @@ class InputHandler
Point cursorPosition;
const bool enableMouse;
const bool enableTouch;
const bool enableController;
std::vector<SDL_Event> acquireEvents();
void preprocessEvent(const SDL_Event & event);

View File

@ -19,6 +19,8 @@
#include "../gui/EventDispatcher.h"
#include "../gui/ShortcutHandler.h"
#include "../../lib/CConfigHandler.h"
void InputSourceGameController::gameControllerDeleter(SDL_GameController * gameController)
{
if(gameController)
@ -26,6 +28,13 @@ void InputSourceGameController::gameControllerDeleter(SDL_GameController * gameC
}
InputSourceGameController::InputSourceGameController():
configTriggerTreshold(settings["input"]["controllerTriggerTreshold"].Float()),
configAxisDeadZone(settings["input"]["controllerAxisDeadZone"].Float()),
configAxisFullZone(settings["input"]["controllerAxisFullZone"].Float()),
configPointerSpeed(settings["input"]["controllerPointerSpeed"].Float()),
configPointerScale(settings["input"]["controllerPointerScale"].Float()),
configPanningSpeed(settings["input"]["controllerPanningSpeed"].Float()),
configPanningScale(settings["input"]["controllerPanningScale"].Float()),
cursorAxisValueX(0),
cursorAxisValueY(0),
cursorPlanDisX(0.0),
@ -120,21 +129,22 @@ void InputSourceGameController::handleEventDeviceRemapped(const SDL_ControllerDe
openGameController(device.which);
}
int InputSourceGameController::getRealAxisValue(int value)
double InputSourceGameController::getRealAxisValue(int value)
{
if(value < AXIS_DEAD_ZOOM && value > -AXIS_DEAD_ZOOM)
double ratio = static_cast<double>(value) / SDL_JOYSTICK_AXIS_MAX;
double greenZone = configAxisFullZone - configAxisDeadZone;
if (std::abs(ratio) < configAxisDeadZone)
return 0;
if(value > AXIS_MAX_ZOOM)
return AXIS_MAX_ZOOM;
if(value < -AXIS_MAX_ZOOM)
return -AXIS_MAX_ZOOM;
int base = value > 0 ? AXIS_DEAD_ZOOM : -AXIS_DEAD_ZOOM;
return (value - base) * AXIS_MAX_ZOOM / (AXIS_MAX_ZOOM - AXIS_DEAD_ZOOM);
double scaledValue = (ratio - configAxisDeadZone) / greenZone;
double clampedValue = std::clamp(scaledValue, -1.0, +1.0);
return clampedValue;
}
void InputSourceGameController::dispatchAxisShortcuts(const std::vector<EShortcut> & shortcutsVector, SDL_GameControllerAxis axisID, int axisValue)
{
if(axisValue >= TRIGGER_PRESS_THRESHOLD)
if(getRealAxisValue(axisValue) > configTriggerTreshold)
{
if(!pressedAxes.count(axisID))
{
@ -256,12 +266,12 @@ void InputSourceGameController::handleCursorUpdate(int32_t deltaTimeMs)
if(cursorAxisValueX == 0)
cursorPlanDisX = 0;
else
cursorPlanDisX += deltaTimeSeconds * AXIS_MOVE_SPEED * cursorAxisValueX / AXIS_MAX_ZOOM;
cursorPlanDisX += deltaTimeSeconds * configPointerSpeed * std::pow(cursorAxisValueX, configPointerScale);
if(cursorAxisValueY == 0)
cursorPlanDisY = 0;
else
cursorPlanDisY += deltaTimeSeconds * AXIS_MOVE_SPEED * cursorAxisValueY / AXIS_MAX_ZOOM;
cursorPlanDisY += deltaTimeSeconds * configPointerSpeed * std::pow(cursorAxisValueY, configPointerScale);
int moveDisX = getMoveDis(cursorPlanDisX);
int moveDisY = getMoveDis(cursorPlanDisY);
@ -290,8 +300,8 @@ void InputSourceGameController::handleScrollUpdate(int32_t deltaTimeMs)
return;
}
float deltaTimeSeconds = static_cast<float>(deltaTimeMs) / 1000;
scrollPlanDisX += deltaTimeSeconds * AXIS_MOVE_SPEED * scrollAxisValueX / AXIS_MAX_ZOOM;
scrollPlanDisY += deltaTimeSeconds * AXIS_MOVE_SPEED * scrollAxisValueY / AXIS_MAX_ZOOM;
scrollPlanDisX += deltaTimeSeconds * configPanningSpeed * std::pow(scrollAxisValueX, configPanningScale);
scrollPlanDisY += deltaTimeSeconds * configPanningSpeed * std::pow(scrollAxisValueY, configPanningScale);
int moveDisX = getMoveDis(scrollPlanDisX);
int moveDisY = getMoveDis(scrollPlanDisY);
if(moveDisX != 0 || moveDisY != 0)

View File

@ -44,9 +44,17 @@ class InputSourceGameController
float scrollPlanDisX;
float scrollPlanDisY;
const double configTriggerTreshold;
const double configAxisDeadZone;
const double configAxisFullZone;
const double configPointerSpeed;
const double configPointerScale;
const double configPanningSpeed;
const double configPanningScale;
void openGameController(int index);
int getJoystickIndex(SDL_GameController * controller);
int getRealAxisValue(int value);
double getRealAxisValue(int value);
void dispatchAxisShortcuts(const std::vector<EShortcut> & shortcutsVector, SDL_GameControllerAxis axisID, int axisValue);
void tryToConvertCursor();
void doCursorMove(int deltaX, int deltaY);

View File

@ -12,15 +12,18 @@
#include "InputSourceMouse.h"
#include "InputHandler.h"
#include "../../lib/Point.h"
#include "../gui/CGuiHandler.h"
#include "../gui/EventDispatcher.h"
#include "../gui/MouseButton.h"
#include "../../lib/Point.h"
#include "../../lib/CConfigHandler.h"
#include <SDL_events.h>
#include <SDL_hints.h>
InputSourceMouse::InputSourceMouse()
:mouseToleranceDistance(settings["input"]["mouseToleranceDistance"].Integer())
{
SDL_SetHint(SDL_HINT_MOUSE_FOCUS_CLICKTHROUGH, "1");
}
@ -48,12 +51,12 @@ void InputSourceMouse::handleEventMouseButtonDown(const SDL_MouseButtonEvent & b
{
case SDL_BUTTON_LEFT:
if(button.clicks > 1)
GH.events().dispatchMouseDoubleClick(position, 0);
GH.events().dispatchMouseDoubleClick(position, mouseToleranceDistance);
else
GH.events().dispatchMouseLeftButtonPressed(position, 0);
GH.events().dispatchMouseLeftButtonPressed(position, mouseToleranceDistance);
break;
case SDL_BUTTON_RIGHT:
GH.events().dispatchShowPopup(position, 0);
GH.events().dispatchShowPopup(position, mouseToleranceDistance);
break;
case SDL_BUTTON_MIDDLE:
middleClickPosition = position;
@ -74,7 +77,7 @@ void InputSourceMouse::handleEventMouseButtonUp(const SDL_MouseButtonEvent & but
switch(button.button)
{
case SDL_BUTTON_LEFT:
GH.events().dispatchMouseLeftButtonReleased(position, 0);
GH.events().dispatchMouseLeftButtonReleased(position, mouseToleranceDistance);
break;
case SDL_BUTTON_RIGHT:
GH.events().dispatchClosePopup(position);

View File

@ -23,6 +23,7 @@ class InputSourceMouse
{
Point middleClickPosition;
int mouseButtonsMask = 0;
const int mouseToleranceDistance;
public:
InputSourceMouse();

View File

@ -17,6 +17,7 @@
#include "WindowHandler.h"
#include "gui/Shortcut.h"
#include "../../lib/CConfigHandler.h"
#include "../../lib/Rect.h"
template<typename Functor>
@ -76,10 +77,10 @@ void EventDispatcher::dispatchShortcutPressed(const std::vector<EShortcut> & sho
bool keysCaptured = false;
if (vstd::contains(shortcutsVector, EShortcut::MOUSE_LEFT))
dispatchMouseLeftButtonPressed(GH.getCursorPosition(), 0);
dispatchMouseLeftButtonPressed(GH.getCursorPosition(), settings["input"]["shortcutToleranceDistance"].Integer());
if (vstd::contains(shortcutsVector, EShortcut::MOUSE_RIGHT))
dispatchShowPopup(GH.getCursorPosition(), 0);
dispatchShowPopup(GH.getCursorPosition(), settings["input"]["shortcutToleranceDistance"].Integer());
for(auto & i : keyinterested)
for(EShortcut shortcut : shortcutsVector)
@ -105,7 +106,7 @@ void EventDispatcher::dispatchShortcutReleased(const std::vector<EShortcut> & sh
bool keysCaptured = false;
if (vstd::contains(shortcutsVector, EShortcut::MOUSE_LEFT))
dispatchMouseLeftButtonReleased(GH.getCursorPosition(), 0);
dispatchMouseLeftButtonReleased(GH.getCursorPosition(), settings["input"]["shortcutToleranceDistance"].Integer());
if (vstd::contains(shortcutsVector, EShortcut::MOUSE_RIGHT))
dispatchClosePopup(GH.getCursorPosition());
@ -164,7 +165,7 @@ AEventsReceiver * EventDispatcher::findElementInToleranceRange(const EventReceiv
if (distance.lengthSquared() == 0)
continue;
Point moveDelta = distance * tolerance / distance.length();
Point moveDelta = distance * std::min(1.0, static_cast<double>(tolerance) / distance.length());
Point testPosition = position + moveDelta;
if( !i->receiveEvent(testPosition, eventToTest))

View File

@ -236,7 +236,22 @@
"type" : "object",
"additionalProperties" : false,
"default" : {},
"required" : [ "radialWheelGarrisonSwipe", "touchToleranceDistance" ],
"required" : [
"radialWheelGarrisonSwipe",
"touchToleranceDistance",
"mouseToleranceDistance",
"shortcutToleranceDistance",
"enableMouse",
"enableTouch",
"enableController",
"controllerTriggerTreshold",
"controllerAxisDeadZone",
"controllerAxisFullZone",
"controllerPointerSpeed",
"controllerPointerScale",
"controllerPanningSpeed",
"controllerPanningScale",
],
"properties" : {
"radialWheelGarrisonSwipe" : {
"type" : "boolean",
@ -245,7 +260,55 @@
"touchToleranceDistance" : {
"type" : "number",
"default" : 20
},
"mouseToleranceDistance" : {
"type" : "number",
"default" : 0
},
"shortcutToleranceDistance" : {
"type" : "number",
"default" : 0
},
"enableMouse" : {
"type" : "boolean",
"default" : true
},
"enableTouch" : {
"type" : "boolean",
"default" : true
},
"enableController" : {
"type" : "boolean",
"default" : true
},
"controllerTriggerTreshold" : {
"type" : "number",
"default" : 0.3
}
"controllerAxisDeadZone" : {
"type" : "number",
"default" : 0.2
},
"controllerAxisFullZone" : {
"type" : "number",
"default" : 0.9
},
"controllerPointerSpeed" : {
"type" : "number",
"default" : 1
},
"controllerPointerScale" : {
"type" : "number",
"default" : 1
},
"controllerPanningSpeed" : {
"type" : "number",
"default" : 1
},
"controllerPanningScale" : {
"type" : "number",
"default" : 1
},
}
},
"adventure" : {