mirror of
https://github.com/vcmi/vcmi.git
synced 2025-02-03 13:01:33 +02:00
Minor refactoring of mouse input handling
This commit is contained in:
parent
526ce1b546
commit
34123c7f07
@ -37,8 +37,6 @@ InputHandler::InputHandler()
|
|||||||
, fingerHandler(std::make_unique<InputSourceTouch>())
|
, fingerHandler(std::make_unique<InputSourceTouch>())
|
||||||
, textHandler(std::make_unique<InputSourceText>())
|
, textHandler(std::make_unique<InputSourceText>())
|
||||||
, userHandler(std::make_unique<UserEventHandler>())
|
, userHandler(std::make_unique<UserEventHandler>())
|
||||||
, mouseButtonsMask(0)
|
|
||||||
, pointerSpeedMultiplier(settings["general"]["relativePointerSpeedMultiplier"].Float())
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -77,14 +75,8 @@ void InputHandler::processEvents()
|
|||||||
{
|
{
|
||||||
boost::unique_lock<boost::mutex> lock(eventsMutex);
|
boost::unique_lock<boost::mutex> lock(eventsMutex);
|
||||||
for (auto const & currentEvent : eventsQueue)
|
for (auto const & currentEvent : eventsQueue)
|
||||||
{
|
|
||||||
if (currentEvent.type == SDL_MOUSEMOTION)
|
|
||||||
{
|
|
||||||
cursorPosition = Point(currentEvent.motion.x, currentEvent.motion.y);
|
|
||||||
mouseButtonsMask = currentEvent.motion.state;
|
|
||||||
}
|
|
||||||
handleCurrentEvent(currentEvent);
|
handleCurrentEvent(currentEvent);
|
||||||
}
|
|
||||||
eventsQueue.clear();
|
eventsQueue.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -211,25 +203,15 @@ bool InputHandler::isKeyboardShiftDown() const
|
|||||||
return SDL_GetKeyboardState(nullptr)[SDL_SCANCODE_LSHIFT] || SDL_GetKeyboardState(nullptr)[SDL_SCANCODE_RSHIFT];
|
return SDL_GetKeyboardState(nullptr)[SDL_SCANCODE_LSHIFT] || SDL_GetKeyboardState(nullptr)[SDL_SCANCODE_RSHIFT];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void InputHandler::moveCursorPosition(const Point & distance)
|
||||||
void InputHandler::fakeMoveCursor(float dx, float dy)
|
|
||||||
{
|
{
|
||||||
int x, y, w, h;
|
setCursorPosition(getCursorPosition() + distance);
|
||||||
|
}
|
||||||
|
|
||||||
SDL_Event event;
|
void InputHandler::setCursorPosition(const Point & position)
|
||||||
SDL_MouseMotionEvent sme = {SDL_MOUSEMOTION, 0, 0, 0, 0, 0, 0, 0, 0};
|
{
|
||||||
|
cursorPosition = position;
|
||||||
sme.state = SDL_GetMouseState(&x, &y);
|
GH.events().dispatchMouseMoved(position);
|
||||||
SDL_GetWindowSize(mainWindow, &w, &h);
|
|
||||||
|
|
||||||
sme.x = GH.getCursorPosition().x + (int)(pointerSpeedMultiplier * w * dx);
|
|
||||||
sme.y = GH.getCursorPosition().y + (int)(pointerSpeedMultiplier * h * dy);
|
|
||||||
|
|
||||||
vstd::abetween(sme.x, 0, w);
|
|
||||||
vstd::abetween(sme.y, 0, h);
|
|
||||||
|
|
||||||
event.motion = sme;
|
|
||||||
SDL_PushEvent(&event);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void InputHandler::startTextInput(const Rect & where)
|
void InputHandler::startTextInput(const Rect & where)
|
||||||
@ -244,14 +226,7 @@ void InputHandler::stopTextInput()
|
|||||||
|
|
||||||
bool InputHandler::isMouseButtonPressed(MouseButton button) const
|
bool InputHandler::isMouseButtonPressed(MouseButton button) const
|
||||||
{
|
{
|
||||||
static_assert(static_cast<uint32_t>(MouseButton::LEFT) == SDL_BUTTON_LEFT, "mismatch between VCMI and SDL enum!");
|
return mouseHandler->isMouseButtonPressed(button) || fingerHandler->isMouseButtonPressed(button);
|
||||||
static_assert(static_cast<uint32_t>(MouseButton::MIDDLE) == SDL_BUTTON_MIDDLE, "mismatch between VCMI and SDL enum!");
|
|
||||||
static_assert(static_cast<uint32_t>(MouseButton::RIGHT) == SDL_BUTTON_RIGHT, "mismatch between VCMI and SDL enum!");
|
|
||||||
static_assert(static_cast<uint32_t>(MouseButton::EXTRA1) == SDL_BUTTON_X1, "mismatch between VCMI and SDL enum!");
|
|
||||||
static_assert(static_cast<uint32_t>(MouseButton::EXTRA2) == SDL_BUTTON_X2, "mismatch between VCMI and SDL enum!");
|
|
||||||
|
|
||||||
uint32_t index = static_cast<uint32_t>(button);
|
|
||||||
return mouseButtonsMask & SDL_BUTTON(index);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void InputHandler::pushUserEvent(EUserEvent usercode, void * userdata)
|
void InputHandler::pushUserEvent(EUserEvent usercode, void * userdata)
|
||||||
|
@ -28,8 +28,6 @@ class InputHandler
|
|||||||
boost::mutex eventsMutex;
|
boost::mutex eventsMutex;
|
||||||
|
|
||||||
Point cursorPosition;
|
Point cursorPosition;
|
||||||
float pointerSpeedMultiplier;
|
|
||||||
int mouseButtonsMask;
|
|
||||||
|
|
||||||
void preprocessEvent(const SDL_Event & event);
|
void preprocessEvent(const SDL_Event & event);
|
||||||
void handleCurrentEvent(const SDL_Event & current);
|
void handleCurrentEvent(const SDL_Event & current);
|
||||||
@ -53,7 +51,11 @@ public:
|
|||||||
/// returns true if input event has been found
|
/// returns true if input event has been found
|
||||||
bool ignoreEventsUntilInput();
|
bool ignoreEventsUntilInput();
|
||||||
|
|
||||||
void fakeMoveCursor(float dx, float dy);
|
/// Moves cursor by specified distance
|
||||||
|
void moveCursorPosition(const Point & distance);
|
||||||
|
|
||||||
|
/// Moves cursor to a specified position
|
||||||
|
void setCursorPosition(const Point & position);
|
||||||
|
|
||||||
/// Initiates text input in selected area, potentially creating IME popup (mobile systems only at the moment)
|
/// Initiates text input in selected area, potentially creating IME popup (mobile systems only at the moment)
|
||||||
void startTextInput(const Rect & where);
|
void startTextInput(const Rect & where);
|
||||||
|
@ -10,6 +10,7 @@
|
|||||||
|
|
||||||
#include "StdInc.h"
|
#include "StdInc.h"
|
||||||
#include "InputSourceMouse.h"
|
#include "InputSourceMouse.h"
|
||||||
|
#include "InputHandler.h"
|
||||||
|
|
||||||
#include "../../lib/Point.h"
|
#include "../../lib/Point.h"
|
||||||
#include "../gui/CGuiHandler.h"
|
#include "../gui/CGuiHandler.h"
|
||||||
@ -20,7 +21,12 @@
|
|||||||
|
|
||||||
void InputSourceMouse::handleEventMouseMotion(const SDL_MouseMotionEvent & motion)
|
void InputSourceMouse::handleEventMouseMotion(const SDL_MouseMotionEvent & motion)
|
||||||
{
|
{
|
||||||
GH.events().dispatchMouseMoved(Point(motion.x, motion.y));
|
Point newPosition(motion.x, motion.y);
|
||||||
|
|
||||||
|
GH.input().setCursorPosition(newPosition);
|
||||||
|
|
||||||
|
mouseButtonsMask = motion.state;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void InputSourceMouse::handleEventMouseButtonDown(const SDL_MouseButtonEvent & button)
|
void InputSourceMouse::handleEventMouseButtonDown(const SDL_MouseButtonEvent & button)
|
||||||
@ -70,3 +76,15 @@ void InputSourceMouse::handleEventMouseButtonUp(const SDL_MouseButtonEvent & but
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool InputSourceMouse::isMouseButtonPressed(MouseButton button) const
|
||||||
|
{
|
||||||
|
static_assert(static_cast<uint32_t>(MouseButton::LEFT) == SDL_BUTTON_LEFT, "mismatch between VCMI and SDL enum!");
|
||||||
|
static_assert(static_cast<uint32_t>(MouseButton::MIDDLE) == SDL_BUTTON_MIDDLE, "mismatch between VCMI and SDL enum!");
|
||||||
|
static_assert(static_cast<uint32_t>(MouseButton::RIGHT) == SDL_BUTTON_RIGHT, "mismatch between VCMI and SDL enum!");
|
||||||
|
static_assert(static_cast<uint32_t>(MouseButton::EXTRA1) == SDL_BUTTON_X1, "mismatch between VCMI and SDL enum!");
|
||||||
|
static_assert(static_cast<uint32_t>(MouseButton::EXTRA2) == SDL_BUTTON_X2, "mismatch between VCMI and SDL enum!");
|
||||||
|
|
||||||
|
uint32_t index = static_cast<uint32_t>(button);
|
||||||
|
return mouseButtonsMask & SDL_BUTTON(index);
|
||||||
|
}
|
||||||
|
@ -14,12 +14,17 @@ struct SDL_MouseWheelEvent;
|
|||||||
struct SDL_MouseMotionEvent;
|
struct SDL_MouseMotionEvent;
|
||||||
struct SDL_MouseButtonEvent;
|
struct SDL_MouseButtonEvent;
|
||||||
|
|
||||||
|
enum class MouseButton;
|
||||||
|
|
||||||
/// Class that handles mouse input from SDL events
|
/// Class that handles mouse input from SDL events
|
||||||
class InputSourceMouse
|
class InputSourceMouse
|
||||||
{
|
{
|
||||||
|
int mouseButtonsMask = 0;
|
||||||
public:
|
public:
|
||||||
void handleEventMouseMotion(const SDL_MouseMotionEvent & current);
|
void handleEventMouseMotion(const SDL_MouseMotionEvent & current);
|
||||||
void handleEventMouseButtonDown(const SDL_MouseButtonEvent & current);
|
void handleEventMouseButtonDown(const SDL_MouseButtonEvent & current);
|
||||||
void handleEventMouseWheel(const SDL_MouseWheelEvent & current);
|
void handleEventMouseWheel(const SDL_MouseWheelEvent & current);
|
||||||
void handleEventMouseButtonUp(const SDL_MouseButtonEvent & current);
|
void handleEventMouseButtonUp(const SDL_MouseButtonEvent & current);
|
||||||
|
|
||||||
|
bool isMouseButtonPressed(MouseButton button) const;
|
||||||
};
|
};
|
||||||
|
@ -26,6 +26,7 @@
|
|||||||
InputSourceTouch::InputSourceTouch()
|
InputSourceTouch::InputSourceTouch()
|
||||||
: multifinger(false)
|
: multifinger(false)
|
||||||
, isPointerRelativeMode(settings["general"]["userRelativePointer"].Bool())
|
, isPointerRelativeMode(settings["general"]["userRelativePointer"].Bool())
|
||||||
|
, pointerSpeedMultiplier(settings["general"]["relativePointerSpeedMultiplier"].Float())
|
||||||
{
|
{
|
||||||
if(isPointerRelativeMode)
|
if(isPointerRelativeMode)
|
||||||
{
|
{
|
||||||
@ -38,58 +39,73 @@ void InputSourceTouch::handleEventFingerMotion(const SDL_TouchFingerEvent & tfin
|
|||||||
{
|
{
|
||||||
if(isPointerRelativeMode)
|
if(isPointerRelativeMode)
|
||||||
{
|
{
|
||||||
GH.input().fakeMoveCursor(tfinger.dx, tfinger.dy);
|
Point screenSize = GH.screenDimensions();
|
||||||
|
|
||||||
|
Point moveDistance {
|
||||||
|
static_cast<int>(screenSize.x * pointerSpeedMultiplier * tfinger.dx),
|
||||||
|
static_cast<int>(screenSize.y * pointerSpeedMultiplier * tfinger.dy)
|
||||||
|
};
|
||||||
|
|
||||||
|
GH.input().moveCursorPosition(moveDistance);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void InputSourceTouch::handleEventFingerDown(const SDL_TouchFingerEvent & tfinger)
|
void InputSourceTouch::handleEventFingerDown(const SDL_TouchFingerEvent & tfinger)
|
||||||
{
|
{
|
||||||
auto fingerCount = SDL_GetNumTouchFingers(tfinger.touchId);
|
|
||||||
|
|
||||||
multifinger = fingerCount > 1;
|
|
||||||
|
|
||||||
if(isPointerRelativeMode)
|
if(isPointerRelativeMode)
|
||||||
{
|
{
|
||||||
if(tfinger.x > 0.5)
|
if(tfinger.x > 0.5)
|
||||||
{
|
{
|
||||||
bool isRightClick = tfinger.y < 0.5;
|
bool isRightClick = tfinger.y < 0.5;
|
||||||
|
|
||||||
fakeMouseButtonEventRelativeMode(true, isRightClick);
|
if (isRightClick)
|
||||||
|
GH.events().dispatchMouseButtonPressed(MouseButton::RIGHT, GH.getCursorPosition());
|
||||||
|
else
|
||||||
|
GH.events().dispatchMouseButtonPressed(MouseButton::LEFT, GH.getCursorPosition());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#ifndef VCMI_IOS
|
#ifndef VCMI_IOS
|
||||||
else if(fingerCount == 2)
|
else
|
||||||
{
|
{
|
||||||
Point position = convertTouchToMouse(tfinger);
|
auto fingerCount = SDL_GetNumTouchFingers(tfinger.touchId);
|
||||||
|
multifinger = fingerCount > 1;
|
||||||
|
|
||||||
GH.events().dispatchMouseMoved(position);
|
if(fingerCount == 2)
|
||||||
GH.events().dispatchMouseButtonPressed(MouseButton::RIGHT, position);
|
{
|
||||||
|
Point position = convertTouchToMouse(tfinger);
|
||||||
|
|
||||||
|
GH.input().setCursorPosition(position);
|
||||||
|
GH.events().dispatchMouseButtonPressed(MouseButton::RIGHT, position);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif //VCMI_IOS
|
#endif //VCMI_IOS
|
||||||
}
|
}
|
||||||
|
|
||||||
void InputSourceTouch::handleEventFingerUp(const SDL_TouchFingerEvent & tfinger)
|
void InputSourceTouch::handleEventFingerUp(const SDL_TouchFingerEvent & tfinger)
|
||||||
{
|
{
|
||||||
#ifndef VCMI_IOS
|
|
||||||
auto fingerCount = SDL_GetNumTouchFingers(tfinger.touchId);
|
|
||||||
#endif //VCMI_IOS
|
|
||||||
|
|
||||||
if(isPointerRelativeMode)
|
if(isPointerRelativeMode)
|
||||||
{
|
{
|
||||||
if(tfinger.x > 0.5)
|
if(tfinger.x > 0.5)
|
||||||
{
|
{
|
||||||
bool isRightClick = tfinger.y < 0.5;
|
bool isRightClick = tfinger.y < 0.5;
|
||||||
|
|
||||||
fakeMouseButtonEventRelativeMode(false, isRightClick);
|
if (isRightClick)
|
||||||
|
GH.events().dispatchMouseButtonReleased(MouseButton::RIGHT, GH.getCursorPosition());
|
||||||
|
else
|
||||||
|
GH.events().dispatchMouseButtonReleased(MouseButton::LEFT, GH.getCursorPosition());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#ifndef VCMI_IOS
|
#ifndef VCMI_IOS
|
||||||
else if(multifinger)
|
else
|
||||||
{
|
{
|
||||||
Point position = convertTouchToMouse(tfinger);
|
if(multifinger)
|
||||||
GH.events().dispatchMouseMoved(position);
|
{
|
||||||
GH.events().dispatchMouseButtonReleased(MouseButton::RIGHT, position);
|
auto fingerCount = SDL_GetNumTouchFingers(tfinger.touchId);
|
||||||
multifinger = fingerCount != 0;
|
Point position = convertTouchToMouse(tfinger);
|
||||||
|
GH.input().setCursorPosition(position);
|
||||||
|
GH.events().dispatchMouseButtonReleased(MouseButton::RIGHT, position);
|
||||||
|
multifinger = fingerCount != 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif //VCMI_IOS
|
#endif //VCMI_IOS
|
||||||
}
|
}
|
||||||
@ -99,37 +115,7 @@ Point InputSourceTouch::convertTouchToMouse(const SDL_TouchFingerEvent & tfinger
|
|||||||
return Point(tfinger.x * GH.screenDimensions().x, tfinger.y * GH.screenDimensions().y);
|
return Point(tfinger.x * GH.screenDimensions().x, tfinger.y * GH.screenDimensions().y);
|
||||||
}
|
}
|
||||||
|
|
||||||
void InputSourceTouch::fakeMouseButtonEventRelativeMode(bool down, bool right)
|
bool InputSourceTouch::isMouseButtonPressed(MouseButton button) const
|
||||||
{
|
{
|
||||||
SDL_Event event;
|
return false;
|
||||||
SDL_MouseButtonEvent sme = {SDL_MOUSEBUTTONDOWN, 0, 0, 0, 0, 0, 0, 0, 0, 0};
|
|
||||||
|
|
||||||
if(!down)
|
|
||||||
{
|
|
||||||
sme.type = SDL_MOUSEBUTTONUP;
|
|
||||||
}
|
|
||||||
|
|
||||||
sme.button = right ? SDL_BUTTON_RIGHT : SDL_BUTTON_LEFT;
|
|
||||||
|
|
||||||
sme.x = GH.getCursorPosition().x;
|
|
||||||
sme.y = GH.getCursorPosition().y;
|
|
||||||
|
|
||||||
float xScale, yScale;
|
|
||||||
int w, h, rLogicalWidth, rLogicalHeight;
|
|
||||||
|
|
||||||
SDL_GetWindowSize(mainWindow, &w, &h);
|
|
||||||
SDL_RenderGetLogicalSize(mainRenderer, &rLogicalWidth, &rLogicalHeight);
|
|
||||||
SDL_RenderGetScale(mainRenderer, &xScale, &yScale);
|
|
||||||
|
|
||||||
SDL_EventState(SDL_MOUSEMOTION, SDL_IGNORE);
|
|
||||||
moveCursorToPosition(Point((int)(sme.x * xScale) + (w - rLogicalWidth * xScale) / 2, (int)(sme.y * yScale + (h - rLogicalHeight * yScale) / 2)));
|
|
||||||
SDL_EventState(SDL_MOUSEMOTION, SDL_ENABLE);
|
|
||||||
|
|
||||||
event.button = sme;
|
|
||||||
SDL_PushEvent(&event);
|
|
||||||
}
|
|
||||||
|
|
||||||
void InputSourceTouch::moveCursorToPosition(const Point & position)
|
|
||||||
{
|
|
||||||
SDL_WarpMouseInWindow(mainWindow, position.x, position.y);
|
|
||||||
}
|
}
|
||||||
|
@ -14,16 +14,16 @@ VCMI_LIB_NAMESPACE_BEGIN
|
|||||||
class Point;
|
class Point;
|
||||||
VCMI_LIB_NAMESPACE_END
|
VCMI_LIB_NAMESPACE_END
|
||||||
|
|
||||||
|
enum class MouseButton;
|
||||||
struct SDL_TouchFingerEvent;
|
struct SDL_TouchFingerEvent;
|
||||||
|
|
||||||
/// Class that handles touchscreen input from SDL events
|
/// Class that handles touchscreen input from SDL events
|
||||||
class InputSourceTouch
|
class InputSourceTouch
|
||||||
{
|
{
|
||||||
|
double pointerSpeedMultiplier;
|
||||||
bool multifinger;
|
bool multifinger;
|
||||||
bool isPointerRelativeMode;
|
bool isPointerRelativeMode;
|
||||||
|
|
||||||
/// moves mouse pointer into specified position inside vcmi window
|
|
||||||
void moveCursorToPosition(const Point & position);
|
|
||||||
Point convertTouchToMouse(const SDL_TouchFingerEvent & current);
|
Point convertTouchToMouse(const SDL_TouchFingerEvent & current);
|
||||||
|
|
||||||
void fakeMouseButtonEventRelativeMode(bool down, bool right);
|
void fakeMouseButtonEventRelativeMode(bool down, bool right);
|
||||||
@ -34,4 +34,6 @@ public:
|
|||||||
void handleEventFingerMotion(const SDL_TouchFingerEvent & current);
|
void handleEventFingerMotion(const SDL_TouchFingerEvent & current);
|
||||||
void handleEventFingerDown(const SDL_TouchFingerEvent & current);
|
void handleEventFingerDown(const SDL_TouchFingerEvent & current);
|
||||||
void handleEventFingerUp(const SDL_TouchFingerEvent & current);
|
void handleEventFingerUp(const SDL_TouchFingerEvent & current);
|
||||||
|
|
||||||
|
bool isMouseButtonPressed(MouseButton button) const;
|
||||||
};
|
};
|
||||||
|
@ -18,6 +18,7 @@
|
|||||||
#include "../gui/WindowHandler.h"
|
#include "../gui/WindowHandler.h"
|
||||||
#include "../mainmenu/CMainMenu.h"
|
#include "../mainmenu/CMainMenu.h"
|
||||||
#include "../mainmenu/CPrologEpilogVideo.h"
|
#include "../mainmenu/CPrologEpilogVideo.h"
|
||||||
|
#include "../gui/EventDispatcher.h"
|
||||||
|
|
||||||
#include <SDL_events.h>
|
#include <SDL_events.h>
|
||||||
|
|
||||||
@ -80,6 +81,9 @@ void UserEventHandler::handleUserEvent(const SDL_UserEvent & user)
|
|||||||
GH.onScreenResize();
|
GH.onScreenResize();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case EUserEvent::FAKE_MOUSE_MOVE:
|
||||||
|
GH.events().dispatchMouseMoved(GH.getCursorPosition());
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
logGlobal->error("Unknown user event. Code %d", user.code);
|
logGlobal->error("Unknown user event. Code %d", user.code);
|
||||||
break;
|
break;
|
||||||
|
@ -87,7 +87,7 @@ void CGuiHandler::handleEvents()
|
|||||||
|
|
||||||
void CGuiHandler::fakeMouseMove()
|
void CGuiHandler::fakeMouseMove()
|
||||||
{
|
{
|
||||||
input().fakeMoveCursor(0, 0);
|
pushUserEvent(EUserEvent::FAKE_MOUSE_MOVE);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CGuiHandler::startTextInput(const Rect & whereInput)
|
void CGuiHandler::startTextInput(const Rect & whereInput)
|
||||||
|
@ -36,6 +36,7 @@ enum class EUserEvent
|
|||||||
FULLSCREEN_TOGGLED,
|
FULLSCREEN_TOGGLED,
|
||||||
CAMPAIGN_START_SCENARIO,
|
CAMPAIGN_START_SCENARIO,
|
||||||
FORCE_QUIT,
|
FORCE_QUIT,
|
||||||
|
FAKE_MOUSE_MOVE,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Handles GUI logic and drawing
|
// Handles GUI logic and drawing
|
||||||
|
Loading…
x
Reference in New Issue
Block a user