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>())
|
||||
, textHandler(std::make_unique<InputSourceText>())
|
||||
, 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);
|
||||
for (auto const & currentEvent : eventsQueue)
|
||||
{
|
||||
if (currentEvent.type == SDL_MOUSEMOTION)
|
||||
{
|
||||
cursorPosition = Point(currentEvent.motion.x, currentEvent.motion.y);
|
||||
mouseButtonsMask = currentEvent.motion.state;
|
||||
}
|
||||
handleCurrentEvent(currentEvent);
|
||||
}
|
||||
|
||||
eventsQueue.clear();
|
||||
}
|
||||
|
||||
@ -211,25 +203,15 @@ bool InputHandler::isKeyboardShiftDown() const
|
||||
return SDL_GetKeyboardState(nullptr)[SDL_SCANCODE_LSHIFT] || SDL_GetKeyboardState(nullptr)[SDL_SCANCODE_RSHIFT];
|
||||
}
|
||||
|
||||
|
||||
void InputHandler::fakeMoveCursor(float dx, float dy)
|
||||
void InputHandler::moveCursorPosition(const Point & distance)
|
||||
{
|
||||
int x, y, w, h;
|
||||
setCursorPosition(getCursorPosition() + distance);
|
||||
}
|
||||
|
||||
SDL_Event event;
|
||||
SDL_MouseMotionEvent sme = {SDL_MOUSEMOTION, 0, 0, 0, 0, 0, 0, 0, 0};
|
||||
|
||||
sme.state = SDL_GetMouseState(&x, &y);
|
||||
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::setCursorPosition(const Point & position)
|
||||
{
|
||||
cursorPosition = position;
|
||||
GH.events().dispatchMouseMoved(position);
|
||||
}
|
||||
|
||||
void InputHandler::startTextInput(const Rect & where)
|
||||
@ -244,14 +226,7 @@ void InputHandler::stopTextInput()
|
||||
|
||||
bool InputHandler::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);
|
||||
return mouseHandler->isMouseButtonPressed(button) || fingerHandler->isMouseButtonPressed(button);
|
||||
}
|
||||
|
||||
void InputHandler::pushUserEvent(EUserEvent usercode, void * userdata)
|
||||
|
@ -28,8 +28,6 @@ class InputHandler
|
||||
boost::mutex eventsMutex;
|
||||
|
||||
Point cursorPosition;
|
||||
float pointerSpeedMultiplier;
|
||||
int mouseButtonsMask;
|
||||
|
||||
void preprocessEvent(const SDL_Event & event);
|
||||
void handleCurrentEvent(const SDL_Event & current);
|
||||
@ -53,7 +51,11 @@ public:
|
||||
/// returns true if input event has been found
|
||||
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)
|
||||
void startTextInput(const Rect & where);
|
||||
|
@ -10,6 +10,7 @@
|
||||
|
||||
#include "StdInc.h"
|
||||
#include "InputSourceMouse.h"
|
||||
#include "InputHandler.h"
|
||||
|
||||
#include "../../lib/Point.h"
|
||||
#include "../gui/CGuiHandler.h"
|
||||
@ -20,7 +21,12 @@
|
||||
|
||||
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)
|
||||
@ -70,3 +76,15 @@ void InputSourceMouse::handleEventMouseButtonUp(const SDL_MouseButtonEvent & but
|
||||
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_MouseButtonEvent;
|
||||
|
||||
enum class MouseButton;
|
||||
|
||||
/// Class that handles mouse input from SDL events
|
||||
class InputSourceMouse
|
||||
{
|
||||
int mouseButtonsMask = 0;
|
||||
public:
|
||||
void handleEventMouseMotion(const SDL_MouseMotionEvent & current);
|
||||
void handleEventMouseButtonDown(const SDL_MouseButtonEvent & current);
|
||||
void handleEventMouseWheel(const SDL_MouseWheelEvent & current);
|
||||
void handleEventMouseButtonUp(const SDL_MouseButtonEvent & current);
|
||||
|
||||
bool isMouseButtonPressed(MouseButton button) const;
|
||||
};
|
||||
|
@ -26,6 +26,7 @@
|
||||
InputSourceTouch::InputSourceTouch()
|
||||
: multifinger(false)
|
||||
, isPointerRelativeMode(settings["general"]["userRelativePointer"].Bool())
|
||||
, pointerSpeedMultiplier(settings["general"]["relativePointerSpeedMultiplier"].Float())
|
||||
{
|
||||
if(isPointerRelativeMode)
|
||||
{
|
||||
@ -38,58 +39,73 @@ void InputSourceTouch::handleEventFingerMotion(const SDL_TouchFingerEvent & tfin
|
||||
{
|
||||
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)
|
||||
{
|
||||
auto fingerCount = SDL_GetNumTouchFingers(tfinger.touchId);
|
||||
|
||||
multifinger = fingerCount > 1;
|
||||
|
||||
if(isPointerRelativeMode)
|
||||
{
|
||||
if(tfinger.x > 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
|
||||
else if(fingerCount == 2)
|
||||
else
|
||||
{
|
||||
Point position = convertTouchToMouse(tfinger);
|
||||
auto fingerCount = SDL_GetNumTouchFingers(tfinger.touchId);
|
||||
multifinger = fingerCount > 1;
|
||||
|
||||
GH.events().dispatchMouseMoved(position);
|
||||
GH.events().dispatchMouseButtonPressed(MouseButton::RIGHT, position);
|
||||
if(fingerCount == 2)
|
||||
{
|
||||
Point position = convertTouchToMouse(tfinger);
|
||||
|
||||
GH.input().setCursorPosition(position);
|
||||
GH.events().dispatchMouseButtonPressed(MouseButton::RIGHT, position);
|
||||
}
|
||||
}
|
||||
#endif //VCMI_IOS
|
||||
}
|
||||
|
||||
void InputSourceTouch::handleEventFingerUp(const SDL_TouchFingerEvent & tfinger)
|
||||
{
|
||||
#ifndef VCMI_IOS
|
||||
auto fingerCount = SDL_GetNumTouchFingers(tfinger.touchId);
|
||||
#endif //VCMI_IOS
|
||||
|
||||
if(isPointerRelativeMode)
|
||||
{
|
||||
if(tfinger.x > 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
|
||||
else if(multifinger)
|
||||
else
|
||||
{
|
||||
Point position = convertTouchToMouse(tfinger);
|
||||
GH.events().dispatchMouseMoved(position);
|
||||
GH.events().dispatchMouseButtonReleased(MouseButton::RIGHT, position);
|
||||
multifinger = fingerCount != 0;
|
||||
if(multifinger)
|
||||
{
|
||||
auto fingerCount = SDL_GetNumTouchFingers(tfinger.touchId);
|
||||
Point position = convertTouchToMouse(tfinger);
|
||||
GH.input().setCursorPosition(position);
|
||||
GH.events().dispatchMouseButtonReleased(MouseButton::RIGHT, position);
|
||||
multifinger = fingerCount != 0;
|
||||
}
|
||||
}
|
||||
#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);
|
||||
}
|
||||
|
||||
void InputSourceTouch::fakeMouseButtonEventRelativeMode(bool down, bool right)
|
||||
bool InputSourceTouch::isMouseButtonPressed(MouseButton button) const
|
||||
{
|
||||
SDL_Event event;
|
||||
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);
|
||||
return false;
|
||||
}
|
||||
|
@ -14,16 +14,16 @@ VCMI_LIB_NAMESPACE_BEGIN
|
||||
class Point;
|
||||
VCMI_LIB_NAMESPACE_END
|
||||
|
||||
enum class MouseButton;
|
||||
struct SDL_TouchFingerEvent;
|
||||
|
||||
/// Class that handles touchscreen input from SDL events
|
||||
class InputSourceTouch
|
||||
{
|
||||
double pointerSpeedMultiplier;
|
||||
bool multifinger;
|
||||
bool isPointerRelativeMode;
|
||||
|
||||
/// moves mouse pointer into specified position inside vcmi window
|
||||
void moveCursorToPosition(const Point & position);
|
||||
Point convertTouchToMouse(const SDL_TouchFingerEvent & current);
|
||||
|
||||
void fakeMouseButtonEventRelativeMode(bool down, bool right);
|
||||
@ -34,4 +34,6 @@ public:
|
||||
void handleEventFingerMotion(const SDL_TouchFingerEvent & current);
|
||||
void handleEventFingerDown(const SDL_TouchFingerEvent & current);
|
||||
void handleEventFingerUp(const SDL_TouchFingerEvent & current);
|
||||
|
||||
bool isMouseButtonPressed(MouseButton button) const;
|
||||
};
|
||||
|
@ -18,6 +18,7 @@
|
||||
#include "../gui/WindowHandler.h"
|
||||
#include "../mainmenu/CMainMenu.h"
|
||||
#include "../mainmenu/CPrologEpilogVideo.h"
|
||||
#include "../gui/EventDispatcher.h"
|
||||
|
||||
#include <SDL_events.h>
|
||||
|
||||
@ -80,6 +81,9 @@ void UserEventHandler::handleUserEvent(const SDL_UserEvent & user)
|
||||
GH.onScreenResize();
|
||||
break;
|
||||
}
|
||||
case EUserEvent::FAKE_MOUSE_MOVE:
|
||||
GH.events().dispatchMouseMoved(GH.getCursorPosition());
|
||||
break;
|
||||
default:
|
||||
logGlobal->error("Unknown user event. Code %d", user.code);
|
||||
break;
|
||||
|
@ -87,7 +87,7 @@ void CGuiHandler::handleEvents()
|
||||
|
||||
void CGuiHandler::fakeMouseMove()
|
||||
{
|
||||
input().fakeMoveCursor(0, 0);
|
||||
pushUserEvent(EUserEvent::FAKE_MOUSE_MOVE);
|
||||
}
|
||||
|
||||
void CGuiHandler::startTextInput(const Rect & whereInput)
|
||||
|
@ -36,6 +36,7 @@ enum class EUserEvent
|
||||
FULLSCREEN_TOGGLED,
|
||||
CAMPAIGN_START_SCENARIO,
|
||||
FORCE_QUIT,
|
||||
FAKE_MOUSE_MOVE,
|
||||
};
|
||||
|
||||
// Handles GUI logic and drawing
|
||||
|
Loading…
x
Reference in New Issue
Block a user