mirror of
https://github.com/vcmi/vcmi.git
synced 2025-11-25 22:42:04 +02:00
Moved input handling from GuiHandler to set of classes in eventsSDL dir
This commit is contained in:
155
client/CMT.cpp
155
client/CMT.cpp
@@ -14,36 +14,27 @@
|
|||||||
|
|
||||||
#include "CGameInfo.h"
|
#include "CGameInfo.h"
|
||||||
#include "mainmenu/CMainMenu.h"
|
#include "mainmenu/CMainMenu.h"
|
||||||
#include "mainmenu/CPrologEpilogVideo.h"
|
|
||||||
#include "gui/CursorHandler.h"
|
#include "gui/CursorHandler.h"
|
||||||
|
#include "eventsSDL/InputHandler.h"
|
||||||
#include "CPlayerInterface.h"
|
#include "CPlayerInterface.h"
|
||||||
#include "CVideoHandler.h"
|
#include "CVideoHandler.h"
|
||||||
#include "CMusicHandler.h"
|
#include "CMusicHandler.h"
|
||||||
#include "gui/CGuiHandler.h"
|
#include "gui/CGuiHandler.h"
|
||||||
#include "gui/WindowHandler.h"
|
#include "gui/WindowHandler.h"
|
||||||
#include "CServerHandler.h"
|
#include "CServerHandler.h"
|
||||||
#include "gui/NotificationHandler.h"
|
|
||||||
#include "ClientCommandManager.h"
|
#include "ClientCommandManager.h"
|
||||||
#include "windows/CMessage.h"
|
#include "windows/CMessage.h"
|
||||||
#include "render/IScreenHandler.h"
|
#include "render/IScreenHandler.h"
|
||||||
|
|
||||||
#include "../lib/filesystem/Filesystem.h"
|
#include "../lib/filesystem/Filesystem.h"
|
||||||
#include "../lib/CConsoleHandler.h"
|
|
||||||
#include "../lib/CGeneralTextHandler.h"
|
#include "../lib/CGeneralTextHandler.h"
|
||||||
#include "../lib/VCMIDirs.h"
|
#include "../lib/VCMIDirs.h"
|
||||||
#include "../lib/mapping/CCampaignHandler.h"
|
#include "../lib/CConfigHandler.h"
|
||||||
|
|
||||||
#include "../lib/logging/CBasicLogConfigurator.h"
|
#include "../lib/logging/CBasicLogConfigurator.h"
|
||||||
|
|
||||||
#include <boost/program_options.hpp>
|
#include <boost/program_options.hpp>
|
||||||
#include <vstd/StringUtils.h>
|
#include <vstd/StringUtils.h>
|
||||||
#include <SDL_events.h>
|
|
||||||
#include <SDL_hints.h>
|
|
||||||
#include <SDL_main.h>
|
|
||||||
|
|
||||||
#ifdef VCMI_WINDOWS
|
|
||||||
#include <SDL_syswm.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef VCMI_ANDROID
|
#ifdef VCMI_ANDROID
|
||||||
#include "../lib/CAndroidVMHelper.h"
|
#include "../lib/CAndroidVMHelper.h"
|
||||||
@@ -54,15 +45,14 @@
|
|||||||
#undef main
|
#undef main
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
extern boost::mutex eventsM;
|
||||||
|
|
||||||
namespace po = boost::program_options;
|
namespace po = boost::program_options;
|
||||||
namespace po_style = boost::program_options::command_line_style;
|
namespace po_style = boost::program_options::command_line_style;
|
||||||
namespace bfs = boost::filesystem;
|
namespace bfs = boost::filesystem;
|
||||||
|
|
||||||
extern boost::thread_specific_ptr<bool> inGuiThread;
|
extern boost::thread_specific_ptr<bool> inGuiThread;
|
||||||
|
|
||||||
std::queue<SDL_Event> SDLEventsQueue;
|
|
||||||
boost::mutex eventsM;
|
|
||||||
|
|
||||||
static po::variables_map vm;
|
static po::variables_map vm;
|
||||||
|
|
||||||
#ifndef VCMI_IOS
|
#ifndef VCMI_IOS
|
||||||
@@ -331,7 +321,7 @@ int main(int argc, char * argv[])
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef SDL_HINT_MOUSE_TOUCH_EVENTS
|
#ifdef SDL_HINT_MOUSE_TOUCH_EVENTS
|
||||||
if(GH.isPointerRelativeMode)
|
if(settings["general"]["userRelativePointer"].Bool())
|
||||||
{
|
{
|
||||||
SDL_SetHint(SDL_HINT_MOUSE_TOUCH_EVENTS, "0");
|
SDL_SetHint(SDL_HINT_MOUSE_TOUCH_EVENTS, "0");
|
||||||
SDL_SetHint(SDL_HINT_TOUCH_MOUSE_EVENTS, "0");
|
SDL_SetHint(SDL_HINT_TOUCH_MOUSE_EVENTS, "0");
|
||||||
@@ -469,147 +459,18 @@ void playIntro()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void handleEvent(SDL_Event & ev)
|
|
||||||
{
|
|
||||||
if((ev.type==SDL_QUIT) ||(ev.type == SDL_KEYDOWN && ev.key.keysym.sym==SDLK_F4 && (ev.key.keysym.mod & KMOD_ALT)))
|
|
||||||
{
|
|
||||||
#ifdef VCMI_ANDROID
|
|
||||||
handleQuit(false);
|
|
||||||
#else
|
|
||||||
handleQuit();
|
|
||||||
#endif
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
#ifdef VCMI_ANDROID
|
|
||||||
else if (ev.type == SDL_KEYDOWN && ev.key.keysym.scancode == SDL_SCANCODE_AC_BACK)
|
|
||||||
{
|
|
||||||
handleQuit(true);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
else if(ev.type == SDL_KEYDOWN && ev.key.keysym.sym==SDLK_F4)
|
|
||||||
{
|
|
||||||
Settings full = settings.write["video"]["fullscreen"];
|
|
||||||
full->Bool() = !full->Bool();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
else if(ev.type == SDL_USEREVENT)
|
|
||||||
{
|
|
||||||
switch(static_cast<EUserEvent>(ev.user.code))
|
|
||||||
{
|
|
||||||
case EUserEvent::FORCE_QUIT:
|
|
||||||
{
|
|
||||||
handleQuit(false);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case EUserEvent::RETURN_TO_MAIN_MENU:
|
|
||||||
{
|
|
||||||
CSH->endGameplay();
|
|
||||||
GH.defActionsDef = 63;
|
|
||||||
CMM->menu->switchToTab("main");
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case EUserEvent::RESTART_GAME:
|
|
||||||
{
|
|
||||||
CSH->sendRestartGame();
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case EUserEvent::CAMPAIGN_START_SCENARIO:
|
|
||||||
{
|
|
||||||
CSH->campaignServerRestartLock.set(true);
|
|
||||||
CSH->endGameplay();
|
|
||||||
auto ourCampaign = std::shared_ptr<CCampaignState>(reinterpret_cast<CCampaignState *>(ev.user.data1));
|
|
||||||
auto & epilogue = ourCampaign->camp->scenarios[ourCampaign->mapsConquered.back()].epilog;
|
|
||||||
auto finisher = [=]()
|
|
||||||
{
|
|
||||||
if(ourCampaign->mapsRemaining.size())
|
|
||||||
{
|
|
||||||
GH.windows().pushWindow(CMM);
|
|
||||||
GH.windows().pushWindow(CMM->menu);
|
|
||||||
CMM->openCampaignLobby(ourCampaign);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
if(epilogue.hasPrologEpilog)
|
|
||||||
{
|
|
||||||
GH.windows().createAndPushWindow<CPrologEpilogVideo>(epilogue, finisher);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
CSH->campaignServerRestartLock.waitUntil(false);
|
|
||||||
finisher();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case EUserEvent::RETURN_TO_MENU_LOAD:
|
|
||||||
CSH->endGameplay();
|
|
||||||
GH.defActionsDef = 63;
|
|
||||||
CMM->menu->switchToTab("load");
|
|
||||||
break;
|
|
||||||
case EUserEvent::FULLSCREEN_TOGGLED:
|
|
||||||
{
|
|
||||||
boost::unique_lock<boost::recursive_mutex> lock(*CPlayerInterface::pim);
|
|
||||||
GH.onScreenResize();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
logGlobal->error("Unknown user event. Code %d", ev.user.code);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
else if(ev.type == SDL_WINDOWEVENT)
|
|
||||||
{
|
|
||||||
switch (ev.window.event) {
|
|
||||||
case SDL_WINDOWEVENT_RESTORED:
|
|
||||||
#ifndef VCMI_IOS
|
|
||||||
{
|
|
||||||
boost::unique_lock<boost::recursive_mutex> lock(*CPlayerInterface::pim);
|
|
||||||
GH.onScreenResize();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
else if(ev.type == SDL_SYSWMEVENT)
|
|
||||||
{
|
|
||||||
if(!settings["session"]["headless"].Bool() && settings["general"]["notifications"].Bool())
|
|
||||||
{
|
|
||||||
NotificationHandler::handleSdlEvent(ev);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//preprocessing
|
|
||||||
if(ev.type == SDL_MOUSEMOTION)
|
|
||||||
{
|
|
||||||
CCS->curh->cursorMove(ev.motion.x, ev.motion.y);
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
boost::unique_lock<boost::mutex> lock(eventsM);
|
|
||||||
SDLEventsQueue.push(ev);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void mainLoop()
|
static void mainLoop()
|
||||||
{
|
{
|
||||||
SettingsListener resChanged = settings.listen["video"]["resolution"];
|
SettingsListener resChanged = settings.listen["video"]["resolution"];
|
||||||
SettingsListener fsChanged = settings.listen["video"]["fullscreen"];
|
SettingsListener fsChanged = settings.listen["video"]["fullscreen"];
|
||||||
resChanged([](const JsonNode &newState){ CGuiHandler::pushUserEvent(EUserEvent::FULLSCREEN_TOGGLED); });
|
resChanged([](const JsonNode &newState){ GH.pushUserEvent(EUserEvent::FULLSCREEN_TOGGLED); });
|
||||||
fsChanged([](const JsonNode &newState){ CGuiHandler::pushUserEvent(EUserEvent::FULLSCREEN_TOGGLED); });
|
fsChanged([](const JsonNode &newState){ GH.pushUserEvent(EUserEvent::FULLSCREEN_TOGGLED); });
|
||||||
|
|
||||||
inGuiThread.reset(new bool(true));
|
inGuiThread.reset(new bool(true));
|
||||||
|
|
||||||
while(1) //main SDL events loop
|
while(1) //main SDL events loop
|
||||||
{
|
{
|
||||||
SDL_Event ev;
|
GH.input().fetchEvents();
|
||||||
|
|
||||||
while(1 == SDL_PollEvent(&ev))
|
|
||||||
{
|
|
||||||
handleEvent(ev);
|
|
||||||
}
|
|
||||||
|
|
||||||
CSH->applyPacksOnLobbyScreen();
|
CSH->applyPacksOnLobbyScreen();
|
||||||
GH.renderFrame();
|
GH.renderFrame();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,6 +27,14 @@ set(client_SRCS
|
|||||||
battle/BattleWindow.cpp
|
battle/BattleWindow.cpp
|
||||||
battle/CreatureAnimation.cpp
|
battle/CreatureAnimation.cpp
|
||||||
|
|
||||||
|
eventsSDL/NotificationHandler.cpp
|
||||||
|
eventsSDL/InputHandler.cpp
|
||||||
|
eventsSDL/UserEventHandler.cpp
|
||||||
|
eventsSDL/InputSourceKeyboard.cpp
|
||||||
|
eventsSDL/InputSourceMouse.cpp
|
||||||
|
eventsSDL/InputSourceText.cpp
|
||||||
|
eventsSDL/InputSourceTouch.cpp
|
||||||
|
|
||||||
gui/CGuiHandler.cpp
|
gui/CGuiHandler.cpp
|
||||||
gui/CIntObject.cpp
|
gui/CIntObject.cpp
|
||||||
gui/CursorHandler.cpp
|
gui/CursorHandler.cpp
|
||||||
@@ -34,7 +42,6 @@ set(client_SRCS
|
|||||||
gui/EventsReceiver.cpp
|
gui/EventsReceiver.cpp
|
||||||
gui/InterfaceObjectConfigurable.cpp
|
gui/InterfaceObjectConfigurable.cpp
|
||||||
gui/FramerateManager.cpp
|
gui/FramerateManager.cpp
|
||||||
gui/NotificationHandler.cpp
|
|
||||||
gui/ShortcutHandler.cpp
|
gui/ShortcutHandler.cpp
|
||||||
gui/WindowHandler.cpp
|
gui/WindowHandler.cpp
|
||||||
|
|
||||||
@@ -162,6 +169,14 @@ set(client_HEADERS
|
|||||||
battle/BattleWindow.h
|
battle/BattleWindow.h
|
||||||
battle/CreatureAnimation.h
|
battle/CreatureAnimation.h
|
||||||
|
|
||||||
|
eventsSDL/NotificationHandler.h
|
||||||
|
eventsSDL/InputHandler.h
|
||||||
|
eventsSDL/UserEventHandler.h
|
||||||
|
eventsSDL/InputSourceKeyboard.h
|
||||||
|
eventsSDL/InputSourceMouse.h
|
||||||
|
eventsSDL/InputSourceText.h
|
||||||
|
eventsSDL/InputSourceTouch.h
|
||||||
|
|
||||||
gui/CGuiHandler.h
|
gui/CGuiHandler.h
|
||||||
gui/CIntObject.h
|
gui/CIntObject.h
|
||||||
gui/CursorHandler.h
|
gui/CursorHandler.h
|
||||||
@@ -170,7 +185,6 @@ set(client_HEADERS
|
|||||||
gui/InterfaceObjectConfigurable.h
|
gui/InterfaceObjectConfigurable.h
|
||||||
gui/FramerateManager.h
|
gui/FramerateManager.h
|
||||||
gui/MouseButton.h
|
gui/MouseButton.h
|
||||||
gui/NotificationHandler.h
|
|
||||||
gui/Shortcut.h
|
gui/Shortcut.h
|
||||||
gui/ShortcutHandler.h
|
gui/ShortcutHandler.h
|
||||||
gui/TextAlignment.h
|
gui/TextAlignment.h
|
||||||
@@ -337,7 +351,7 @@ if(WIN32)
|
|||||||
endif()
|
endif()
|
||||||
target_compile_definitions(vcmiclient PRIVATE WINDOWS_IGNORE_PACKING_MISMATCH)
|
target_compile_definitions(vcmiclient PRIVATE WINDOWS_IGNORE_PACKING_MISMATCH)
|
||||||
|
|
||||||
# TODO: very hacky, find proper solution to copy AI dlls into bin dir
|
# TODO: very hacky, find proper solution to copy AI dlls into bin dir
|
||||||
if(MSVC)
|
if(MSVC)
|
||||||
add_custom_command(TARGET vcmiclient POST_BUILD
|
add_custom_command(TARGET vcmiclient POST_BUILD
|
||||||
WORKING_DIRECTORY "$<TARGET_FILE_DIR:vcmiclient>"
|
WORKING_DIRECTORY "$<TARGET_FILE_DIR:vcmiclient>"
|
||||||
|
|||||||
@@ -74,7 +74,7 @@
|
|||||||
#include "CServerHandler.h"
|
#include "CServerHandler.h"
|
||||||
// FIXME: only needed for CGameState::mutex
|
// FIXME: only needed for CGameState::mutex
|
||||||
#include "../lib/CGameState.h"
|
#include "../lib/CGameState.h"
|
||||||
#include "gui/NotificationHandler.h"
|
#include "eventsSDL/NotificationHandler.h"
|
||||||
#include "adventureMap/CInGameConsole.h"
|
#include "adventureMap/CInGameConsole.h"
|
||||||
|
|
||||||
#include <SDL_events.h>
|
#include <SDL_events.h>
|
||||||
|
|||||||
@@ -843,7 +843,7 @@ void CServerHandler::threadHandleConnection()
|
|||||||
if(client)
|
if(client)
|
||||||
{
|
{
|
||||||
state = EClientState::DISCONNECTING;
|
state = EClientState::DISCONNECTING;
|
||||||
CGuiHandler::pushUserEvent(EUserEvent::RETURN_TO_MAIN_MENU);
|
GH.pushUserEvent(EUserEvent::RETURN_TO_MAIN_MENU);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -371,7 +371,7 @@ void CVideoPlayer::update( int x, int y, SDL_Surface *dst, bool forceRedraw, boo
|
|||||||
auto packet_duration = frame->duration;
|
auto packet_duration = frame->duration;
|
||||||
#endif
|
#endif
|
||||||
double frameEndTime = (frame->pts + packet_duration) * av_q2d(format->streams[stream]->time_base);
|
double frameEndTime = (frame->pts + packet_duration) * av_q2d(format->streams[stream]->time_base);
|
||||||
frameTime += GH.framerateManager().getElapsedMilliseconds() / 1000.0;
|
frameTime += GH.framerate().getElapsedMilliseconds() / 1000.0;
|
||||||
|
|
||||||
if (frameTime >= frameEndTime )
|
if (frameTime >= frameEndTime )
|
||||||
{
|
{
|
||||||
|
|||||||
250
client/eventsSDL/InputHandler.cpp
Normal file
250
client/eventsSDL/InputHandler.cpp
Normal file
@@ -0,0 +1,250 @@
|
|||||||
|
/*
|
||||||
|
* InputHandler.cpp, 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
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "StdInc.h"
|
||||||
|
#include "InputHandler.h"
|
||||||
|
|
||||||
|
#include "NotificationHandler.h"
|
||||||
|
#include "InputSourceMouse.h"
|
||||||
|
#include "InputSourceKeyboard.h"
|
||||||
|
#include "InputSourceTouch.h"
|
||||||
|
#include "InputSourceText.h"
|
||||||
|
#include "UserEventHandler.h"
|
||||||
|
|
||||||
|
#include "../gui/CGuiHandler.h"
|
||||||
|
#include "../gui/CursorHandler.h"
|
||||||
|
#include "../gui/EventDispatcher.h"
|
||||||
|
#include "../CMT.h"
|
||||||
|
#include "../CPlayerInterface.h"
|
||||||
|
#include "../CGameInfo.h"
|
||||||
|
|
||||||
|
#include "../../lib/CConfigHandler.h"
|
||||||
|
|
||||||
|
#include <SDL_events.h>
|
||||||
|
|
||||||
|
std::queue<SDL_Event> SDLEventsQueue;
|
||||||
|
boost::mutex eventsM;
|
||||||
|
|
||||||
|
InputHandler::InputHandler()
|
||||||
|
: mouseHandler(std::make_unique<InputSourceMouse>())
|
||||||
|
, keyboardHandler(std::make_unique<InputSourceKeyboard>())
|
||||||
|
, fingerHandler(std::make_unique<InputSourceTouch>())
|
||||||
|
, textHandler(std::make_unique<InputSourceText>())
|
||||||
|
, userHandler(std::make_unique<UserEventHandler>())
|
||||||
|
, mouseButtonsMask(0)
|
||||||
|
, pointerSpeedMultiplier(settings["general"]["relativePointerSpeedMultiplier"].Float())
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
InputHandler::~InputHandler() = default;
|
||||||
|
|
||||||
|
void InputHandler::handleCurrentEvent(const SDL_Event & current)
|
||||||
|
{
|
||||||
|
switch (current.type)
|
||||||
|
{
|
||||||
|
case SDL_KEYDOWN:
|
||||||
|
return keyboardHandler->handleEventKeyDown(current.key);
|
||||||
|
case SDL_KEYUP:
|
||||||
|
return keyboardHandler->handleEventKeyUp(current.key);
|
||||||
|
case SDL_MOUSEMOTION:
|
||||||
|
return mouseHandler->handleEventMouseMotion(current.motion);
|
||||||
|
case SDL_MOUSEBUTTONDOWN:
|
||||||
|
return mouseHandler->handleEventMouseButtonDown(current.button);
|
||||||
|
case SDL_MOUSEWHEEL:
|
||||||
|
return mouseHandler->handleEventMouseWheel(current.wheel);
|
||||||
|
case SDL_TEXTINPUT:
|
||||||
|
return textHandler->handleEventTextInput(current.text);
|
||||||
|
case SDL_TEXTEDITING:
|
||||||
|
return textHandler->handleEventTextEditing(current.edit);
|
||||||
|
case SDL_MOUSEBUTTONUP:
|
||||||
|
return mouseHandler->handleEventMouseButtonUp(current.button);
|
||||||
|
case SDL_FINGERMOTION:
|
||||||
|
return fingerHandler->handleEventFingerMotion(current.tfinger);
|
||||||
|
case SDL_FINGERDOWN:
|
||||||
|
return fingerHandler->handleEventFingerDown(current.tfinger);
|
||||||
|
case SDL_FINGERUP:
|
||||||
|
return fingerHandler->handleEventFingerUp(current.tfinger);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void InputHandler::processEvents()
|
||||||
|
{
|
||||||
|
boost::unique_lock<boost::mutex> lock(eventsM);
|
||||||
|
while(!SDLEventsQueue.empty())
|
||||||
|
{
|
||||||
|
GH.events().allowEventHandling(true);
|
||||||
|
SDL_Event currentEvent = SDLEventsQueue.front();
|
||||||
|
|
||||||
|
if (currentEvent.type == SDL_MOUSEMOTION)
|
||||||
|
{
|
||||||
|
cursorPosition = Point(currentEvent.motion.x, currentEvent.motion.y);
|
||||||
|
mouseButtonsMask = currentEvent.motion.state;
|
||||||
|
}
|
||||||
|
SDLEventsQueue.pop();
|
||||||
|
|
||||||
|
// In a sequence of mouse motion events, skip all but the last one.
|
||||||
|
// This prevents freezes when every motion event takes longer to handle than interval at which
|
||||||
|
// the events arrive (like dragging on the minimap in world view, with redraw at every event)
|
||||||
|
// so that the events would start piling up faster than they can be processed.
|
||||||
|
if ((currentEvent.type == SDL_MOUSEMOTION) && !SDLEventsQueue.empty() && (SDLEventsQueue.front().type == SDL_MOUSEMOTION))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
handleCurrentEvent(currentEvent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void InputHandler::preprocessEvent(const SDL_Event & ev)
|
||||||
|
{
|
||||||
|
if((ev.type==SDL_QUIT) ||(ev.type == SDL_KEYDOWN && ev.key.keysym.sym==SDLK_F4 && (ev.key.keysym.mod & KMOD_ALT)))
|
||||||
|
{
|
||||||
|
#ifdef VCMI_ANDROID
|
||||||
|
handleQuit(false);
|
||||||
|
#else
|
||||||
|
handleQuit();
|
||||||
|
#endif
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#ifdef VCMI_ANDROID
|
||||||
|
else if (ev.type == SDL_KEYDOWN && ev.key.keysym.scancode == SDL_SCANCODE_AC_BACK)
|
||||||
|
{
|
||||||
|
handleQuit(true);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
else if(ev.type == SDL_KEYDOWN && ev.key.keysym.sym==SDLK_F4)
|
||||||
|
{
|
||||||
|
Settings full = settings.write["video"]["fullscreen"];
|
||||||
|
full->Bool() = !full->Bool();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else if(ev.type == SDL_USEREVENT)
|
||||||
|
{
|
||||||
|
userHandler->handleUserEvent(ev.user);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else if(ev.type == SDL_WINDOWEVENT)
|
||||||
|
{
|
||||||
|
switch (ev.window.event) {
|
||||||
|
case SDL_WINDOWEVENT_RESTORED:
|
||||||
|
#ifndef VCMI_IOS
|
||||||
|
{
|
||||||
|
boost::unique_lock<boost::recursive_mutex> lock(*CPlayerInterface::pim);
|
||||||
|
GH.onScreenResize();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else if(ev.type == SDL_SYSWMEVENT)
|
||||||
|
{
|
||||||
|
if(!settings["session"]["headless"].Bool() && settings["general"]["notifications"].Bool())
|
||||||
|
{
|
||||||
|
NotificationHandler::handleSdlEvent(ev);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//preprocessing
|
||||||
|
if(ev.type == SDL_MOUSEMOTION)
|
||||||
|
{
|
||||||
|
CCS->curh->cursorMove(ev.motion.x, ev.motion.y);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
boost::unique_lock<boost::mutex> lock(eventsM);
|
||||||
|
SDLEventsQueue.push(ev);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void InputHandler::fetchEvents()
|
||||||
|
{
|
||||||
|
SDL_Event ev;
|
||||||
|
|
||||||
|
while(1 == SDL_PollEvent(&ev))
|
||||||
|
{
|
||||||
|
preprocessEvent(ev);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool InputHandler::isKeyboardCtrlDown() const
|
||||||
|
{
|
||||||
|
#ifdef VCMI_MAC
|
||||||
|
return SDL_GetKeyboardState(nullptr)[SDL_SCANCODE_LGUI] || SDL_GetKeyboardState(nullptr)[SDL_SCANCODE_RGUI];
|
||||||
|
#else
|
||||||
|
return SDL_GetKeyboardState(nullptr)[SDL_SCANCODE_LCTRL] || SDL_GetKeyboardState(nullptr)[SDL_SCANCODE_RCTRL];
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
bool InputHandler::isKeyboardAltDown() const
|
||||||
|
{
|
||||||
|
return SDL_GetKeyboardState(nullptr)[SDL_SCANCODE_LALT] || SDL_GetKeyboardState(nullptr)[SDL_SCANCODE_RALT];
|
||||||
|
}
|
||||||
|
|
||||||
|
bool InputHandler::isKeyboardShiftDown() const
|
||||||
|
{
|
||||||
|
return SDL_GetKeyboardState(nullptr)[SDL_SCANCODE_LSHIFT] || SDL_GetKeyboardState(nullptr)[SDL_SCANCODE_RSHIFT];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void InputHandler::fakeMoveCursor(float dx, float dy)
|
||||||
|
{
|
||||||
|
int x, y, w, h;
|
||||||
|
|
||||||
|
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::startTextInput(const Rect & where)
|
||||||
|
{
|
||||||
|
textHandler->startTextInput(where);
|
||||||
|
}
|
||||||
|
|
||||||
|
void InputHandler::stopTextInput()
|
||||||
|
{
|
||||||
|
textHandler->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);
|
||||||
|
}
|
||||||
|
|
||||||
|
void InputHandler::pushUserEvent(EUserEvent usercode, void * userdata)
|
||||||
|
{
|
||||||
|
SDL_Event event;
|
||||||
|
event.type = SDL_USEREVENT;
|
||||||
|
event.user.code = static_cast<int32_t>(usercode);
|
||||||
|
event.user.data1 = userdata;
|
||||||
|
SDL_PushEvent(&event);
|
||||||
|
}
|
||||||
|
|
||||||
|
const Point & InputHandler::getCursorPosition() const
|
||||||
|
{
|
||||||
|
return cursorPosition;
|
||||||
|
}
|
||||||
59
client/eventsSDL/InputHandler.h
Normal file
59
client/eventsSDL/InputHandler.h
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
/*
|
||||||
|
* InputHandler.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/Rect.h"
|
||||||
|
|
||||||
|
enum class EUserEvent;
|
||||||
|
enum class MouseButton;
|
||||||
|
union SDL_Event;
|
||||||
|
|
||||||
|
class InputSourceMouse;
|
||||||
|
class InputSourceKeyboard;
|
||||||
|
class InputSourceTouch;
|
||||||
|
class InputSourceText;
|
||||||
|
class UserEventHandler;
|
||||||
|
|
||||||
|
class InputHandler
|
||||||
|
{
|
||||||
|
Point cursorPosition;
|
||||||
|
float pointerSpeedMultiplier;
|
||||||
|
int mouseButtonsMask;
|
||||||
|
|
||||||
|
void preprocessEvent(const SDL_Event & event);
|
||||||
|
void handleCurrentEvent(const SDL_Event & current);
|
||||||
|
|
||||||
|
std::unique_ptr<InputSourceMouse> mouseHandler;
|
||||||
|
std::unique_ptr<InputSourceKeyboard> keyboardHandler;
|
||||||
|
std::unique_ptr<InputSourceTouch> fingerHandler;
|
||||||
|
std::unique_ptr<InputSourceText> textHandler;
|
||||||
|
std::unique_ptr<UserEventHandler> userHandler;
|
||||||
|
|
||||||
|
public:
|
||||||
|
InputHandler();
|
||||||
|
~InputHandler();
|
||||||
|
|
||||||
|
void fetchEvents();
|
||||||
|
void processEvents();
|
||||||
|
|
||||||
|
void fakeMoveCursor(float dx, float dy);
|
||||||
|
void startTextInput(const Rect & where);
|
||||||
|
void stopTextInput();
|
||||||
|
bool isMouseButtonPressed(MouseButton button) const;
|
||||||
|
void pushUserEvent(EUserEvent usercode, void * userdata);
|
||||||
|
|
||||||
|
const Point & getCursorPosition() const;
|
||||||
|
|
||||||
|
/// returns true if chosen keyboard key is currently pressed down
|
||||||
|
bool isKeyboardAltDown() const;
|
||||||
|
bool isKeyboardCtrlDown() const;
|
||||||
|
bool isKeyboardShiftDown() const;
|
||||||
|
};
|
||||||
76
client/eventsSDL/InputSourceKeyboard.cpp
Normal file
76
client/eventsSDL/InputSourceKeyboard.cpp
Normal file
@@ -0,0 +1,76 @@
|
|||||||
|
/*
|
||||||
|
* InputSourceKeyboard.cpp, 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
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "StdInc.h"
|
||||||
|
#include "InputSourceKeyboard.h"
|
||||||
|
|
||||||
|
#include "../../lib/CConfigHandler.h"
|
||||||
|
#include "../CPlayerInterface.h"
|
||||||
|
#include "../gui/CGuiHandler.h"
|
||||||
|
#include "../gui/EventDispatcher.h"
|
||||||
|
#include "../gui/ShortcutHandler.h"
|
||||||
|
|
||||||
|
#include <SDL_events.h>
|
||||||
|
|
||||||
|
void InputSourceKeyboard::handleEventKeyDown(const SDL_KeyboardEvent & key)
|
||||||
|
{
|
||||||
|
if(key.repeat != 0)
|
||||||
|
return; // ignore periodic event resends
|
||||||
|
|
||||||
|
assert(key.state == SDL_PRESSED);
|
||||||
|
|
||||||
|
if(key.keysym.sym >= SDLK_F1 && key.keysym.sym <= SDLK_F15 && settings["session"]["spectate"].Bool())
|
||||||
|
{
|
||||||
|
//TODO: we need some central place for all interface-independent hotkeys
|
||||||
|
Settings s = settings.write["session"];
|
||||||
|
switch(key.keysym.sym)
|
||||||
|
{
|
||||||
|
case SDLK_F5:
|
||||||
|
if(settings["session"]["spectate-locked-pim"].Bool())
|
||||||
|
CPlayerInterface::pim->unlock();
|
||||||
|
else
|
||||||
|
CPlayerInterface::pim->lock();
|
||||||
|
s["spectate-locked-pim"].Bool() = !settings["session"]["spectate-locked-pim"].Bool();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SDLK_F6:
|
||||||
|
s["spectate-ignore-hero"].Bool() = !settings["session"]["spectate-ignore-hero"].Bool();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SDLK_F7:
|
||||||
|
s["spectate-skip-battle"].Bool() = !settings["session"]["spectate-skip-battle"].Bool();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SDLK_F8:
|
||||||
|
s["spectate-skip-battle-result"].Bool() = !settings["session"]["spectate-skip-battle-result"].Bool();
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto shortcutsVector = GH.shortcuts().translateKeycode(key.keysym.sym);
|
||||||
|
|
||||||
|
GH.events().dispatchShortcutPressed(shortcutsVector);
|
||||||
|
}
|
||||||
|
|
||||||
|
void InputSourceKeyboard::handleEventKeyUp(const SDL_KeyboardEvent & key)
|
||||||
|
{
|
||||||
|
if(key.repeat != 0)
|
||||||
|
return; // ignore periodic event resends
|
||||||
|
|
||||||
|
assert(key.state == SDL_RELEASED);
|
||||||
|
|
||||||
|
auto shortcutsVector = GH.shortcuts().translateKeycode(key.keysym.sym);
|
||||||
|
|
||||||
|
GH.events().dispatchShortcutReleased(shortcutsVector);
|
||||||
|
}
|
||||||
20
client/eventsSDL/InputSourceKeyboard.h
Normal file
20
client/eventsSDL/InputSourceKeyboard.h
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
/*
|
||||||
|
* InputSourceKeyboard.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
|
||||||
|
|
||||||
|
struct SDL_KeyboardEvent;
|
||||||
|
|
||||||
|
class InputSourceKeyboard
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
void handleEventKeyDown(const SDL_KeyboardEvent & current);
|
||||||
|
void handleEventKeyUp(const SDL_KeyboardEvent & current);
|
||||||
|
};
|
||||||
72
client/eventsSDL/InputSourceMouse.cpp
Normal file
72
client/eventsSDL/InputSourceMouse.cpp
Normal file
@@ -0,0 +1,72 @@
|
|||||||
|
/*
|
||||||
|
* InputSourceMouse.cpp, 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
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "StdInc.h"
|
||||||
|
#include "InputSourceMouse.h"
|
||||||
|
|
||||||
|
#include "../../lib/Point.h"
|
||||||
|
#include "../gui/CGuiHandler.h"
|
||||||
|
#include "../gui/EventDispatcher.h"
|
||||||
|
#include "../gui/MouseButton.h"
|
||||||
|
|
||||||
|
#include <SDL_events.h>
|
||||||
|
|
||||||
|
void InputSourceMouse::handleEventMouseMotion(const SDL_MouseMotionEvent & motion)
|
||||||
|
{
|
||||||
|
GH.events().dispatchMouseMoved(Point(motion.x, motion.y));
|
||||||
|
}
|
||||||
|
|
||||||
|
void InputSourceMouse::handleEventMouseButtonDown(const SDL_MouseButtonEvent & button)
|
||||||
|
{
|
||||||
|
Point position(button.x, button.y);
|
||||||
|
|
||||||
|
switch(button.button)
|
||||||
|
{
|
||||||
|
case SDL_BUTTON_LEFT:
|
||||||
|
if(button.clicks > 1)
|
||||||
|
GH.events().dispatchMouseDoubleClick(position);
|
||||||
|
else
|
||||||
|
GH.events().dispatchMouseButtonPressed(MouseButton::LEFT, position);
|
||||||
|
break;
|
||||||
|
case SDL_BUTTON_RIGHT:
|
||||||
|
GH.events().dispatchMouseButtonPressed(MouseButton::RIGHT, position);
|
||||||
|
break;
|
||||||
|
case SDL_BUTTON_MIDDLE:
|
||||||
|
GH.events().dispatchMouseButtonPressed(MouseButton::MIDDLE, position);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void InputSourceMouse::handleEventMouseWheel(const SDL_MouseWheelEvent & wheel)
|
||||||
|
{
|
||||||
|
// SDL doesn't have the proper values for mouse positions on SDL_MOUSEWHEEL, refetch them
|
||||||
|
int x = 0, y = 0;
|
||||||
|
SDL_GetMouseState(&x, &y);
|
||||||
|
|
||||||
|
GH.events().dispatchMouseScrolled(Point(wheel.x, wheel.y), Point(x, y));
|
||||||
|
}
|
||||||
|
|
||||||
|
void InputSourceMouse::handleEventMouseButtonUp(const SDL_MouseButtonEvent & button)
|
||||||
|
{
|
||||||
|
Point position(button.x, button.y);
|
||||||
|
|
||||||
|
switch(button.button)
|
||||||
|
{
|
||||||
|
case SDL_BUTTON_LEFT:
|
||||||
|
GH.events().dispatchMouseButtonReleased(MouseButton::LEFT, position);
|
||||||
|
break;
|
||||||
|
case SDL_BUTTON_RIGHT:
|
||||||
|
GH.events().dispatchMouseButtonReleased(MouseButton::RIGHT, position);
|
||||||
|
break;
|
||||||
|
case SDL_BUTTON_MIDDLE:
|
||||||
|
GH.events().dispatchMouseButtonReleased(MouseButton::MIDDLE, position);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
24
client/eventsSDL/InputSourceMouse.h
Normal file
24
client/eventsSDL/InputSourceMouse.h
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
/*
|
||||||
|
* InputSourceMouse.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
|
||||||
|
|
||||||
|
struct SDL_MouseWheelEvent;
|
||||||
|
struct SDL_MouseMotionEvent;
|
||||||
|
struct SDL_MouseButtonEvent;
|
||||||
|
|
||||||
|
class InputSourceMouse
|
||||||
|
{
|
||||||
|
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);
|
||||||
|
};
|
||||||
92
client/eventsSDL/InputSourceText.cpp
Normal file
92
client/eventsSDL/InputSourceText.cpp
Normal file
@@ -0,0 +1,92 @@
|
|||||||
|
/*
|
||||||
|
* InputSourceText.cpp, 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
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "StdInc.h"
|
||||||
|
#include "InputSourceText.h"
|
||||||
|
|
||||||
|
#include "../CMT.h"
|
||||||
|
#include "../gui/CGuiHandler.h"
|
||||||
|
#include "../gui/EventDispatcher.h"
|
||||||
|
|
||||||
|
#include "../../lib/Rect.h"
|
||||||
|
|
||||||
|
#include <SDL_events.h>
|
||||||
|
#include <SDL_render.h>
|
||||||
|
|
||||||
|
#ifdef VCMI_APPLE
|
||||||
|
# include <dispatch/dispatch.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef VCMI_IOS
|
||||||
|
# include "ios/utils.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void InputSourceText::handleEventTextInput(const SDL_TextInputEvent & text)
|
||||||
|
{
|
||||||
|
GH.events().dispatchTextInput(text.text);
|
||||||
|
}
|
||||||
|
|
||||||
|
void InputSourceText::handleEventTextEditing(const SDL_TextEditingEvent & text)
|
||||||
|
{
|
||||||
|
GH.events().dispatchTextEditing(text.text);
|
||||||
|
}
|
||||||
|
|
||||||
|
void InputSourceText::startTextInput(const Rect & whereInput)
|
||||||
|
{
|
||||||
|
#ifdef VCMI_APPLE
|
||||||
|
dispatch_async(dispatch_get_main_queue(), ^{
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// TODO ios: looks like SDL bug actually, try fixing there
|
||||||
|
auto renderer = SDL_GetRenderer(mainWindow);
|
||||||
|
float scaleX, scaleY;
|
||||||
|
SDL_Rect viewport;
|
||||||
|
SDL_RenderGetScale(renderer, &scaleX, &scaleY);
|
||||||
|
SDL_RenderGetViewport(renderer, &viewport);
|
||||||
|
|
||||||
|
#ifdef VCMI_IOS
|
||||||
|
const auto nativeScale = iOS_utils::screenScale();
|
||||||
|
scaleX /= nativeScale;
|
||||||
|
scaleY /= nativeScale;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
SDL_Rect rectInScreenCoordinates;
|
||||||
|
rectInScreenCoordinates.x = (viewport.x + whereInput.x) * scaleX;
|
||||||
|
rectInScreenCoordinates.y = (viewport.y + whereInput.y) * scaleY;
|
||||||
|
rectInScreenCoordinates.w = whereInput.w * scaleX;
|
||||||
|
rectInScreenCoordinates.h = whereInput.h * scaleY;
|
||||||
|
|
||||||
|
SDL_SetTextInputRect(&rectInScreenCoordinates);
|
||||||
|
|
||||||
|
if (SDL_IsTextInputActive() == SDL_FALSE)
|
||||||
|
{
|
||||||
|
SDL_StartTextInput();
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef VCMI_APPLE
|
||||||
|
});
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void InputSourceText::stopTextInput()
|
||||||
|
{
|
||||||
|
#ifdef VCMI_APPLE
|
||||||
|
dispatch_async(dispatch_get_main_queue(), ^{
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (SDL_IsTextInputActive() == SDL_TRUE)
|
||||||
|
{
|
||||||
|
SDL_StopTextInput();
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef VCMI_APPLE
|
||||||
|
});
|
||||||
|
#endif
|
||||||
|
}
|
||||||
28
client/eventsSDL/InputSourceText.h
Normal file
28
client/eventsSDL/InputSourceText.h
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
/*
|
||||||
|
* InputSourceText.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
|
||||||
|
|
||||||
|
VCMI_LIB_NAMESPACE_BEGIN
|
||||||
|
class Rect;
|
||||||
|
VCMI_LIB_NAMESPACE_END
|
||||||
|
|
||||||
|
struct SDL_TextEditingEvent;
|
||||||
|
struct SDL_TextInputEvent;
|
||||||
|
|
||||||
|
class InputSourceText
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
void handleEventTextInput(const SDL_TextInputEvent & current);
|
||||||
|
void handleEventTextEditing(const SDL_TextEditingEvent & current);
|
||||||
|
|
||||||
|
void startTextInput(const Rect & where);
|
||||||
|
void stopTextInput();
|
||||||
|
};
|
||||||
128
client/eventsSDL/InputSourceTouch.cpp
Normal file
128
client/eventsSDL/InputSourceTouch.cpp
Normal file
@@ -0,0 +1,128 @@
|
|||||||
|
/*
|
||||||
|
* InputSourceTouch.cpp, 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
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "StdInc.h"
|
||||||
|
#include "InputSourceTouch.h"
|
||||||
|
|
||||||
|
#include "InputHandler.h"
|
||||||
|
|
||||||
|
#include "../../lib/CConfigHandler.h"
|
||||||
|
#include "../CMT.h"
|
||||||
|
#include "../gui/CGuiHandler.h"
|
||||||
|
#include "../gui/EventDispatcher.h"
|
||||||
|
|
||||||
|
#include <SDL_events.h>
|
||||||
|
#include <SDL_render.h>
|
||||||
|
|
||||||
|
InputSourceTouch::InputSourceTouch()
|
||||||
|
: multifinger(false)
|
||||||
|
, isPointerRelativeMode(settings["general"]["userRelativePointer"].Bool())
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void InputSourceTouch::handleEventFingerMotion(const SDL_TouchFingerEvent & tfinger)
|
||||||
|
{
|
||||||
|
if(isPointerRelativeMode)
|
||||||
|
{
|
||||||
|
GH.input().fakeMoveCursor(tfinger.dx, tfinger.dy);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#ifndef VCMI_IOS
|
||||||
|
else if(fingerCount == 2)
|
||||||
|
{
|
||||||
|
Point position = convertTouchToMouse(tfinger);
|
||||||
|
|
||||||
|
GH.events().dispatchMouseMoved(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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#ifndef VCMI_IOS
|
||||||
|
else if(multifinger)
|
||||||
|
{
|
||||||
|
Point position = convertTouchToMouse(tfinger);
|
||||||
|
GH.events().dispatchMouseMoved(position);
|
||||||
|
GH.events().dispatchMouseButtonReleased(MouseButton::RIGHT, position);
|
||||||
|
multifinger = fingerCount != 0;
|
||||||
|
}
|
||||||
|
#endif //VCMI_IOS
|
||||||
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
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);
|
||||||
|
}
|
||||||
36
client/eventsSDL/InputSourceTouch.h
Normal file
36
client/eventsSDL/InputSourceTouch.h
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
/*
|
||||||
|
* 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
|
||||||
|
|
||||||
|
VCMI_LIB_NAMESPACE_BEGIN
|
||||||
|
class Point;
|
||||||
|
VCMI_LIB_NAMESPACE_END
|
||||||
|
|
||||||
|
struct SDL_TouchFingerEvent;
|
||||||
|
|
||||||
|
class InputSourceTouch
|
||||||
|
{
|
||||||
|
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);
|
||||||
|
|
||||||
|
public:
|
||||||
|
InputSourceTouch();
|
||||||
|
|
||||||
|
void handleEventFingerMotion(const SDL_TouchFingerEvent & current);
|
||||||
|
void handleEventFingerDown(const SDL_TouchFingerEvent & current);
|
||||||
|
void handleEventFingerUp(const SDL_TouchFingerEvent & current);
|
||||||
|
};
|
||||||
@@ -10,11 +10,11 @@
|
|||||||
|
|
||||||
#include "StdInc.h"
|
#include "StdInc.h"
|
||||||
#include "NotificationHandler.h"
|
#include "NotificationHandler.h"
|
||||||
#include <SDL_video.h>
|
|
||||||
#include <SDL_events.h>
|
|
||||||
|
|
||||||
#if defined(VCMI_WINDOWS)
|
#if defined(VCMI_WINDOWS)
|
||||||
#include <SDL_syswm.h>
|
#include <SDL_syswm.h>
|
||||||
|
#include <SDL_video.h>
|
||||||
|
#include <SDL_events.h>
|
||||||
|
|
||||||
#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
|
#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
|
||||||
// Windows Header Files:
|
// Windows Header Files:
|
||||||
87
client/eventsSDL/UserEventHandler.cpp
Normal file
87
client/eventsSDL/UserEventHandler.cpp
Normal file
@@ -0,0 +1,87 @@
|
|||||||
|
/*
|
||||||
|
* EventHandlerSDLUser.cpp, 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
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "StdInc.h"
|
||||||
|
#include "UserEventHandler.h"
|
||||||
|
|
||||||
|
#include "../CMT.h"
|
||||||
|
#include "../CPlayerInterface.h"
|
||||||
|
#include "../CServerHandler.h"
|
||||||
|
#include "../gui/CGuiHandler.h"
|
||||||
|
#include "../gui/WindowHandler.h"
|
||||||
|
#include "../mainmenu/CMainMenu.h"
|
||||||
|
#include "../mainmenu/CPrologEpilogVideo.h"
|
||||||
|
|
||||||
|
#include <SDL_events.h>
|
||||||
|
|
||||||
|
void UserEventHandler::handleUserEvent(const SDL_UserEvent & user)
|
||||||
|
{
|
||||||
|
switch(static_cast<EUserEvent>(user.code))
|
||||||
|
{
|
||||||
|
case EUserEvent::FORCE_QUIT:
|
||||||
|
{
|
||||||
|
handleQuit(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case EUserEvent::RETURN_TO_MAIN_MENU:
|
||||||
|
{
|
||||||
|
CSH->endGameplay();
|
||||||
|
GH.defActionsDef = 63;
|
||||||
|
CMM->menu->switchToTab("main");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case EUserEvent::RESTART_GAME:
|
||||||
|
{
|
||||||
|
CSH->sendRestartGame();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case EUserEvent::CAMPAIGN_START_SCENARIO:
|
||||||
|
{
|
||||||
|
CSH->campaignServerRestartLock.set(true);
|
||||||
|
CSH->endGameplay();
|
||||||
|
auto ourCampaign = std::shared_ptr<CCampaignState>(reinterpret_cast<CCampaignState *>(user.data1));
|
||||||
|
auto & epilogue = ourCampaign->camp->scenarios[ourCampaign->mapsConquered.back()].epilog;
|
||||||
|
auto finisher = [=]()
|
||||||
|
{
|
||||||
|
if(!ourCampaign->mapsRemaining.empty())
|
||||||
|
{
|
||||||
|
GH.windows().pushWindow(CMM);
|
||||||
|
GH.windows().pushWindow(CMM->menu);
|
||||||
|
CMM->openCampaignLobby(ourCampaign);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
if(epilogue.hasPrologEpilog)
|
||||||
|
{
|
||||||
|
GH.windows().createAndPushWindow<CPrologEpilogVideo>(epilogue, finisher);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
CSH->campaignServerRestartLock.waitUntil(false);
|
||||||
|
finisher();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case EUserEvent::RETURN_TO_MENU_LOAD:
|
||||||
|
CSH->endGameplay();
|
||||||
|
GH.defActionsDef = 63;
|
||||||
|
CMM->menu->switchToTab("load");
|
||||||
|
break;
|
||||||
|
case EUserEvent::FULLSCREEN_TOGGLED:
|
||||||
|
{
|
||||||
|
boost::unique_lock<boost::recursive_mutex> lock(*CPlayerInterface::pim);
|
||||||
|
GH.onScreenResize();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
logGlobal->error("Unknown user event. Code %d", user.code);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
19
client/eventsSDL/UserEventHandler.h
Normal file
19
client/eventsSDL/UserEventHandler.h
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
/*
|
||||||
|
* EventHandlerSDLUser.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
|
||||||
|
|
||||||
|
struct SDL_UserEvent;
|
||||||
|
|
||||||
|
class UserEventHandler
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
void handleUserEvent(const SDL_UserEvent & current);
|
||||||
|
};
|
||||||
@@ -17,6 +17,7 @@
|
|||||||
#include "FramerateManager.h"
|
#include "FramerateManager.h"
|
||||||
#include "WindowHandler.h"
|
#include "WindowHandler.h"
|
||||||
#include "EventDispatcher.h"
|
#include "EventDispatcher.h"
|
||||||
|
#include "../eventsSDL/InputHandler.h"
|
||||||
|
|
||||||
#include "../CGameInfo.h"
|
#include "../CGameInfo.h"
|
||||||
#include "../render/Colors.h"
|
#include "../render/Colors.h"
|
||||||
@@ -30,17 +31,6 @@
|
|||||||
#include "../../lib/CConfigHandler.h"
|
#include "../../lib/CConfigHandler.h"
|
||||||
|
|
||||||
#include <SDL_render.h>
|
#include <SDL_render.h>
|
||||||
#include <SDL_timer.h>
|
|
||||||
#include <SDL_events.h>
|
|
||||||
#include <SDL_keycode.h>
|
|
||||||
|
|
||||||
#ifdef VCMI_APPLE
|
|
||||||
#include <dispatch/dispatch.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef VCMI_IOS
|
|
||||||
#include "ios/utils.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
CGuiHandler GH;
|
CGuiHandler GH;
|
||||||
|
|
||||||
@@ -80,382 +70,38 @@ SSetCaptureState::~SSetCaptureState()
|
|||||||
|
|
||||||
void CGuiHandler::init()
|
void CGuiHandler::init()
|
||||||
{
|
{
|
||||||
|
inputHandlerInstance = std::make_unique<InputHandler>();
|
||||||
eventDispatcherInstance = std::make_unique<EventDispatcher>();
|
eventDispatcherInstance = std::make_unique<EventDispatcher>();
|
||||||
windowHandlerInstance = std::make_unique<WindowHandler>();
|
windowHandlerInstance = std::make_unique<WindowHandler>();
|
||||||
screenHandlerInstance = std::make_unique<ScreenHandler>();
|
screenHandlerInstance = std::make_unique<ScreenHandler>();
|
||||||
shortcutsHandlerInstance = std::make_unique<ShortcutHandler>();
|
shortcutsHandlerInstance = std::make_unique<ShortcutHandler>();
|
||||||
framerateManagerInstance = std::make_unique<FramerateManager>(settings["video"]["targetfps"].Integer());
|
framerateManagerInstance = std::make_unique<FramerateManager>(settings["video"]["targetfps"].Integer());
|
||||||
|
|
||||||
isPointerRelativeMode = settings["general"]["userRelativePointer"].Bool();
|
|
||||||
pointerSpeedMultiplier = settings["general"]["relativePointerSpeedMultiplier"].Float();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CGuiHandler::handleEvents()
|
void CGuiHandler::handleEvents()
|
||||||
{
|
{
|
||||||
eventDispatcher().dispatchTimer(framerateManager().getElapsedMilliseconds());
|
events().dispatchTimer(framerate().getElapsedMilliseconds());
|
||||||
|
|
||||||
//player interface may want special event handling
|
//player interface may want special event handling
|
||||||
if(nullptr != LOCPLINT && LOCPLINT->capturedAllEvents())
|
if(nullptr != LOCPLINT && LOCPLINT->capturedAllEvents())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
boost::unique_lock<boost::mutex> lock(eventsM);
|
input().processEvents();
|
||||||
while(!SDLEventsQueue.empty())
|
|
||||||
{
|
|
||||||
eventDispatcher().allowEventHandling(true);
|
|
||||||
SDL_Event currentEvent = SDLEventsQueue.front();
|
|
||||||
|
|
||||||
if (currentEvent.type == SDL_MOUSEMOTION)
|
|
||||||
{
|
|
||||||
cursorPosition = Point(currentEvent.motion.x, currentEvent.motion.y);
|
|
||||||
mouseButtonsMask = currentEvent.motion.state;
|
|
||||||
}
|
|
||||||
SDLEventsQueue.pop();
|
|
||||||
|
|
||||||
// In a sequence of mouse motion events, skip all but the last one.
|
|
||||||
// This prevents freezes when every motion event takes longer to handle than interval at which
|
|
||||||
// the events arrive (like dragging on the minimap in world view, with redraw at every event)
|
|
||||||
// so that the events would start piling up faster than they can be processed.
|
|
||||||
if ((currentEvent.type == SDL_MOUSEMOTION) && !SDLEventsQueue.empty() && (SDLEventsQueue.front().type == SDL_MOUSEMOTION))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
handleCurrentEvent(currentEvent);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void CGuiHandler::convertTouchToMouse(SDL_Event * current)
|
|
||||||
{
|
|
||||||
int rLogicalWidth, rLogicalHeight;
|
|
||||||
|
|
||||||
SDL_RenderGetLogicalSize(mainRenderer, &rLogicalWidth, &rLogicalHeight);
|
|
||||||
|
|
||||||
int adjustedMouseY = (int)(current->tfinger.y * rLogicalHeight);
|
|
||||||
int adjustedMouseX = (int)(current->tfinger.x * rLogicalWidth);
|
|
||||||
|
|
||||||
current->button.x = adjustedMouseX;
|
|
||||||
current->motion.x = adjustedMouseX;
|
|
||||||
current->button.y = adjustedMouseY;
|
|
||||||
current->motion.y = adjustedMouseY;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CGuiHandler::fakeMoveCursor(float dx, float dy)
|
|
||||||
{
|
|
||||||
int x, y, w, h;
|
|
||||||
|
|
||||||
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 = CCS->curh->position().x + (int)(GH.pointerSpeedMultiplier * w * dx);
|
|
||||||
sme.y = CCS->curh->position().y + (int)(GH.pointerSpeedMultiplier * h * dy);
|
|
||||||
|
|
||||||
vstd::abetween(sme.x, 0, w);
|
|
||||||
vstd::abetween(sme.y, 0, h);
|
|
||||||
|
|
||||||
event.motion = sme;
|
|
||||||
SDL_PushEvent(&event);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CGuiHandler::fakeMouseMove()
|
void CGuiHandler::fakeMouseMove()
|
||||||
{
|
{
|
||||||
fakeMoveCursor(0, 0);
|
input().fakeMoveCursor(0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CGuiHandler::startTextInput(const Rect & whereInput)
|
void CGuiHandler::startTextInput(const Rect & whereInput)
|
||||||
{
|
{
|
||||||
#ifdef VCMI_APPLE
|
input().startTextInput(whereInput);
|
||||||
dispatch_async(dispatch_get_main_queue(), ^{
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// TODO ios: looks like SDL bug actually, try fixing there
|
|
||||||
auto renderer = SDL_GetRenderer(mainWindow);
|
|
||||||
float scaleX, scaleY;
|
|
||||||
SDL_Rect viewport;
|
|
||||||
SDL_RenderGetScale(renderer, &scaleX, &scaleY);
|
|
||||||
SDL_RenderGetViewport(renderer, &viewport);
|
|
||||||
|
|
||||||
#ifdef VCMI_IOS
|
|
||||||
const auto nativeScale = iOS_utils::screenScale();
|
|
||||||
scaleX /= nativeScale;
|
|
||||||
scaleY /= nativeScale;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
SDL_Rect rectInScreenCoordinates;
|
|
||||||
rectInScreenCoordinates.x = (viewport.x + whereInput.x) * scaleX;
|
|
||||||
rectInScreenCoordinates.y = (viewport.y + whereInput.y) * scaleY;
|
|
||||||
rectInScreenCoordinates.w = whereInput.w * scaleX;
|
|
||||||
rectInScreenCoordinates.h = whereInput.h * scaleY;
|
|
||||||
|
|
||||||
SDL_SetTextInputRect(&rectInScreenCoordinates);
|
|
||||||
|
|
||||||
if (SDL_IsTextInputActive() == SDL_FALSE)
|
|
||||||
{
|
|
||||||
SDL_StartTextInput();
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef VCMI_APPLE
|
|
||||||
});
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CGuiHandler::stopTextInput()
|
void CGuiHandler::stopTextInput()
|
||||||
{
|
{
|
||||||
#ifdef VCMI_APPLE
|
input().stopTextInput();
|
||||||
dispatch_async(dispatch_get_main_queue(), ^{
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (SDL_IsTextInputActive() == SDL_TRUE)
|
|
||||||
{
|
|
||||||
SDL_StopTextInput();
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef VCMI_APPLE
|
|
||||||
});
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
void CGuiHandler::fakeMouseButtonEventRelativeMode(bool down, bool right)
|
|
||||||
{
|
|
||||||
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 = CCS->curh->position().x;
|
|
||||||
sme.y = CCS->curh->position().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 CGuiHandler::handleCurrentEvent( SDL_Event & current )
|
|
||||||
{
|
|
||||||
switch (current.type)
|
|
||||||
{
|
|
||||||
case SDL_KEYDOWN:
|
|
||||||
return handleEventKeyDown(current);
|
|
||||||
case SDL_KEYUP:
|
|
||||||
return handleEventKeyUp(current);
|
|
||||||
case SDL_MOUSEMOTION:
|
|
||||||
return handleEventMouseMotion(current);
|
|
||||||
case SDL_MOUSEBUTTONDOWN:
|
|
||||||
return handleEventMouseButtonDown(current);
|
|
||||||
case SDL_MOUSEWHEEL:
|
|
||||||
return handleEventMouseWheel(current);
|
|
||||||
case SDL_TEXTINPUT:
|
|
||||||
return handleEventTextInput(current);
|
|
||||||
case SDL_TEXTEDITING:
|
|
||||||
return handleEventTextEditing(current);
|
|
||||||
case SDL_MOUSEBUTTONUP:
|
|
||||||
return handleEventMouseButtonUp(current);
|
|
||||||
case SDL_FINGERMOTION:
|
|
||||||
return handleEventFingerMotion(current);
|
|
||||||
case SDL_FINGERDOWN:
|
|
||||||
return handleEventFingerDown(current);
|
|
||||||
case SDL_FINGERUP:
|
|
||||||
return handleEventFingerUp(current);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void CGuiHandler::handleEventKeyDown(SDL_Event & current)
|
|
||||||
{
|
|
||||||
SDL_KeyboardEvent key = current.key;
|
|
||||||
|
|
||||||
if(key.repeat != 0)
|
|
||||||
return; // ignore periodic event resends
|
|
||||||
|
|
||||||
assert(key.state == SDL_PRESSED);
|
|
||||||
|
|
||||||
if(current.type == SDL_KEYDOWN && key.keysym.sym >= SDLK_F1 && key.keysym.sym <= SDLK_F15 && settings["session"]["spectate"].Bool())
|
|
||||||
{
|
|
||||||
//TODO: we need some central place for all interface-independent hotkeys
|
|
||||||
Settings s = settings.write["session"];
|
|
||||||
switch(key.keysym.sym)
|
|
||||||
{
|
|
||||||
case SDLK_F5:
|
|
||||||
if(settings["session"]["spectate-locked-pim"].Bool())
|
|
||||||
LOCPLINT->pim->unlock();
|
|
||||||
else
|
|
||||||
LOCPLINT->pim->lock();
|
|
||||||
s["spectate-locked-pim"].Bool() = !settings["session"]["spectate-locked-pim"].Bool();
|
|
||||||
break;
|
|
||||||
|
|
||||||
case SDLK_F6:
|
|
||||||
s["spectate-ignore-hero"].Bool() = !settings["session"]["spectate-ignore-hero"].Bool();
|
|
||||||
break;
|
|
||||||
|
|
||||||
case SDLK_F7:
|
|
||||||
s["spectate-skip-battle"].Bool() = !settings["session"]["spectate-skip-battle"].Bool();
|
|
||||||
break;
|
|
||||||
|
|
||||||
case SDLK_F8:
|
|
||||||
s["spectate-skip-battle-result"].Bool() = !settings["session"]["spectate-skip-battle-result"].Bool();
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto shortcutsVector = shortcutsHandler().translateKeycode(key.keysym.sym);
|
|
||||||
|
|
||||||
eventDispatcher().dispatchShortcutPressed(shortcutsVector);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CGuiHandler::handleEventKeyUp(SDL_Event & current)
|
|
||||||
{
|
|
||||||
SDL_KeyboardEvent key = current.key;
|
|
||||||
|
|
||||||
if(key.repeat != 0)
|
|
||||||
return; // ignore periodic event resends
|
|
||||||
|
|
||||||
assert(key.state == SDL_RELEASED);
|
|
||||||
|
|
||||||
auto shortcutsVector = shortcutsHandler().translateKeycode(key.keysym.sym);
|
|
||||||
|
|
||||||
eventDispatcher().dispatchShortcutReleased(shortcutsVector);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CGuiHandler::handleEventMouseMotion(SDL_Event & current)
|
|
||||||
{
|
|
||||||
eventDispatcher().dispatchMouseMoved(Point(current.motion.x, current.motion.y));
|
|
||||||
}
|
|
||||||
|
|
||||||
void CGuiHandler::handleEventMouseButtonDown(SDL_Event & current)
|
|
||||||
{
|
|
||||||
switch(current.button.button)
|
|
||||||
{
|
|
||||||
case SDL_BUTTON_LEFT:
|
|
||||||
if (current.button.clicks > 1)
|
|
||||||
eventDispatcher().dispatchMouseDoubleClick(Point(current.button.x, current.button.y));
|
|
||||||
else
|
|
||||||
eventDispatcher().dispatchMouseButtonPressed(MouseButton::LEFT, Point(current.button.x, current.button.y));
|
|
||||||
break;
|
|
||||||
case SDL_BUTTON_RIGHT:
|
|
||||||
eventDispatcher().dispatchMouseButtonPressed(MouseButton::RIGHT, Point(current.button.x, current.button.y));
|
|
||||||
break;
|
|
||||||
case SDL_BUTTON_MIDDLE:
|
|
||||||
eventDispatcher().dispatchMouseButtonPressed(MouseButton::MIDDLE, Point(current.button.x, current.button.y));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void CGuiHandler::handleEventMouseWheel(SDL_Event & current)
|
|
||||||
{
|
|
||||||
// SDL doesn't have the proper values for mouse positions on SDL_MOUSEWHEEL, refetch them
|
|
||||||
int x = 0, y = 0;
|
|
||||||
SDL_GetMouseState(&x, &y);
|
|
||||||
|
|
||||||
eventDispatcher().dispatchMouseScrolled(Point(current.wheel.x, current.wheel.y), Point(x, y));
|
|
||||||
}
|
|
||||||
|
|
||||||
void CGuiHandler::handleEventTextInput(SDL_Event & current)
|
|
||||||
{
|
|
||||||
eventDispatcher().dispatchTextInput(current.text.text);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CGuiHandler::handleEventTextEditing(SDL_Event & current)
|
|
||||||
{
|
|
||||||
eventDispatcher().dispatchTextEditing(current.text.text);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CGuiHandler::handleEventMouseButtonUp(SDL_Event & current)
|
|
||||||
{
|
|
||||||
if(!multifinger)
|
|
||||||
{
|
|
||||||
switch(current.button.button)
|
|
||||||
{
|
|
||||||
case SDL_BUTTON_LEFT:
|
|
||||||
eventDispatcher().dispatchMouseButtonReleased(MouseButton::LEFT, Point(current.button.x, current.button.y));
|
|
||||||
break;
|
|
||||||
case SDL_BUTTON_RIGHT:
|
|
||||||
eventDispatcher().dispatchMouseButtonReleased(MouseButton::RIGHT, Point(current.button.x, current.button.y));
|
|
||||||
break;
|
|
||||||
case SDL_BUTTON_MIDDLE:
|
|
||||||
eventDispatcher().dispatchMouseButtonReleased(MouseButton::MIDDLE, Point(current.button.x, current.button.y));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void CGuiHandler::handleEventFingerMotion(SDL_Event & current)
|
|
||||||
{
|
|
||||||
if(isPointerRelativeMode)
|
|
||||||
{
|
|
||||||
fakeMoveCursor(current.tfinger.dx, current.tfinger.dy);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void CGuiHandler::handleEventFingerDown(SDL_Event & current)
|
|
||||||
{
|
|
||||||
auto fingerCount = SDL_GetNumTouchFingers(current.tfinger.touchId);
|
|
||||||
|
|
||||||
multifinger = fingerCount > 1;
|
|
||||||
|
|
||||||
if(isPointerRelativeMode)
|
|
||||||
{
|
|
||||||
if(current.tfinger.x > 0.5)
|
|
||||||
{
|
|
||||||
bool isRightClick = current.tfinger.y < 0.5;
|
|
||||||
|
|
||||||
fakeMouseButtonEventRelativeMode(true, isRightClick);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#ifndef VCMI_IOS
|
|
||||||
else if(fingerCount == 2)
|
|
||||||
{
|
|
||||||
convertTouchToMouse(¤t);
|
|
||||||
|
|
||||||
eventDispatcher().dispatchMouseMoved(Point(current.button.x, current.button.y));
|
|
||||||
eventDispatcher().dispatchMouseButtonPressed(MouseButton::RIGHT, Point(current.button.x, current.button.y));
|
|
||||||
}
|
|
||||||
#endif //VCMI_IOS
|
|
||||||
}
|
|
||||||
|
|
||||||
void CGuiHandler::handleEventFingerUp(SDL_Event & current)
|
|
||||||
{
|
|
||||||
#ifndef VCMI_IOS
|
|
||||||
auto fingerCount = SDL_GetNumTouchFingers(current.tfinger.touchId);
|
|
||||||
#endif //VCMI_IOS
|
|
||||||
|
|
||||||
if(isPointerRelativeMode)
|
|
||||||
{
|
|
||||||
if(current.tfinger.x > 0.5)
|
|
||||||
{
|
|
||||||
bool isRightClick = current.tfinger.y < 0.5;
|
|
||||||
|
|
||||||
fakeMouseButtonEventRelativeMode(false, isRightClick);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#ifndef VCMI_IOS
|
|
||||||
else if(multifinger)
|
|
||||||
{
|
|
||||||
convertTouchToMouse(¤t);
|
|
||||||
eventDispatcher().dispatchMouseMoved(Point(current.button.x, current.button.y));
|
|
||||||
eventDispatcher().dispatchMouseButtonReleased(MouseButton::RIGHT, Point(current.button.x, current.button.y));
|
|
||||||
multifinger = fingerCount != 0;
|
|
||||||
}
|
|
||||||
#endif //VCMI_IOS
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CGuiHandler::renderFrame()
|
void CGuiHandler::renderFrame()
|
||||||
@@ -493,14 +139,12 @@ void CGuiHandler::renderFrame()
|
|||||||
windows().onFrameRendered();
|
windows().onFrameRendered();
|
||||||
}
|
}
|
||||||
|
|
||||||
framerateManager().framerateDelay(); // holds a constant FPS
|
framerate().framerateDelay(); // holds a constant FPS
|
||||||
}
|
}
|
||||||
|
|
||||||
CGuiHandler::CGuiHandler()
|
CGuiHandler::CGuiHandler()
|
||||||
: defActionsDef(0)
|
: defActionsDef(0)
|
||||||
, captureChildren(false)
|
, captureChildren(false)
|
||||||
, multifinger(false)
|
|
||||||
, mouseButtonsMask(0)
|
|
||||||
, curInt(nullptr)
|
, curInt(nullptr)
|
||||||
, fakeStatusBar(std::make_shared<EmptyStatusBar>())
|
, fakeStatusBar(std::make_shared<EmptyStatusBar>())
|
||||||
, terminate_cond (new CondSh<bool>(false))
|
, terminate_cond (new CondSh<bool>(false))
|
||||||
@@ -512,50 +156,41 @@ CGuiHandler::~CGuiHandler()
|
|||||||
delete terminate_cond;
|
delete terminate_cond;
|
||||||
}
|
}
|
||||||
|
|
||||||
ShortcutHandler & CGuiHandler::shortcutsHandler()
|
ShortcutHandler & CGuiHandler::shortcuts()
|
||||||
{
|
{
|
||||||
assert(shortcutsHandlerInstance);
|
assert(shortcutsHandlerInstance);
|
||||||
return *shortcutsHandlerInstance;
|
return *shortcutsHandlerInstance;
|
||||||
}
|
}
|
||||||
|
|
||||||
FramerateManager & CGuiHandler::framerateManager()
|
FramerateManager & CGuiHandler::framerate()
|
||||||
{
|
{
|
||||||
assert(framerateManagerInstance);
|
assert(framerateManagerInstance);
|
||||||
return *framerateManagerInstance;
|
return *framerateManagerInstance;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CGuiHandler::moveCursorToPosition(const Point & position)
|
|
||||||
{
|
|
||||||
SDL_WarpMouseInWindow(mainWindow, position.x, position.y);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CGuiHandler::isKeyboardCtrlDown() const
|
bool CGuiHandler::isKeyboardCtrlDown() const
|
||||||
{
|
{
|
||||||
#ifdef VCMI_MAC
|
return inputHandlerInstance->isKeyboardCtrlDown();
|
||||||
return SDL_GetKeyboardState(nullptr)[SDL_SCANCODE_LGUI] || SDL_GetKeyboardState(nullptr)[SDL_SCANCODE_RGUI];
|
|
||||||
#else
|
|
||||||
return SDL_GetKeyboardState(nullptr)[SDL_SCANCODE_LCTRL] || SDL_GetKeyboardState(nullptr)[SDL_SCANCODE_RCTRL];
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CGuiHandler::isKeyboardAltDown() const
|
bool CGuiHandler::isKeyboardAltDown() const
|
||||||
{
|
{
|
||||||
return SDL_GetKeyboardState(nullptr)[SDL_SCANCODE_LALT] || SDL_GetKeyboardState(nullptr)[SDL_SCANCODE_RALT];
|
return inputHandlerInstance->isKeyboardAltDown();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CGuiHandler::isKeyboardShiftDown() const
|
bool CGuiHandler::isKeyboardShiftDown() const
|
||||||
{
|
{
|
||||||
return SDL_GetKeyboardState(nullptr)[SDL_SCANCODE_LSHIFT] || SDL_GetKeyboardState(nullptr)[SDL_SCANCODE_RSHIFT];
|
return inputHandlerInstance->isKeyboardShiftDown();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CGuiHandler::breakEventHandling()
|
void CGuiHandler::breakEventHandling()
|
||||||
{
|
{
|
||||||
eventDispatcher().allowEventHandling(false);
|
events().allowEventHandling(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
const Point & CGuiHandler::getCursorPosition() const
|
const Point & CGuiHandler::getCursorPosition() const
|
||||||
{
|
{
|
||||||
return cursorPosition;
|
return inputHandlerInstance->getCursorPosition();
|
||||||
}
|
}
|
||||||
|
|
||||||
Point CGuiHandler::screenDimensions() const
|
Point CGuiHandler::screenDimensions() const
|
||||||
@@ -565,19 +200,12 @@ Point CGuiHandler::screenDimensions() const
|
|||||||
|
|
||||||
bool CGuiHandler::isMouseButtonPressed() const
|
bool CGuiHandler::isMouseButtonPressed() const
|
||||||
{
|
{
|
||||||
return mouseButtonsMask > 0;
|
return isMouseButtonPressed(MouseButton::LEFT) || isMouseButtonPressed(MouseButton::MIDDLE) || isMouseButtonPressed(MouseButton::RIGHT);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CGuiHandler::isMouseButtonPressed(MouseButton button) const
|
bool CGuiHandler::isMouseButtonPressed(MouseButton button) const
|
||||||
{
|
{
|
||||||
static_assert(static_cast<uint32_t>(MouseButton::LEFT) == SDL_BUTTON_LEFT, "mismatch between VCMI and SDL enum!");
|
return inputHandlerInstance->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 CGuiHandler::drawFPSCounter()
|
void CGuiHandler::drawFPSCounter()
|
||||||
@@ -585,7 +213,7 @@ void CGuiHandler::drawFPSCounter()
|
|||||||
static SDL_Rect overlay = { 0, 0, 64, 32};
|
static SDL_Rect overlay = { 0, 0, 64, 32};
|
||||||
uint32_t black = SDL_MapRGB(screen->format, 10, 10, 10);
|
uint32_t black = SDL_MapRGB(screen->format, 10, 10, 10);
|
||||||
SDL_FillRect(screen, &overlay, black);
|
SDL_FillRect(screen, &overlay, black);
|
||||||
std::string fps = std::to_string(framerateManager().getFramerate());
|
std::string fps = std::to_string(framerate().getFramerate());
|
||||||
graphics->fonts[FONT_BIG]->renderTextLeft(screen, fps, Colors::YELLOW, Point(10, 10));
|
graphics->fonts[FONT_BIG]->renderTextLeft(screen, fps, Colors::YELLOW, Point(10, 10));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -596,16 +224,12 @@ bool CGuiHandler::amIGuiThread()
|
|||||||
|
|
||||||
void CGuiHandler::pushUserEvent(EUserEvent usercode)
|
void CGuiHandler::pushUserEvent(EUserEvent usercode)
|
||||||
{
|
{
|
||||||
pushUserEvent(usercode, nullptr);
|
inputHandlerInstance->pushUserEvent(usercode, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CGuiHandler::pushUserEvent(EUserEvent usercode, void * userdata)
|
void CGuiHandler::pushUserEvent(EUserEvent usercode, void * userdata)
|
||||||
{
|
{
|
||||||
SDL_Event event;
|
inputHandlerInstance->pushUserEvent(usercode, userdata);
|
||||||
event.type = SDL_USEREVENT;
|
|
||||||
event.user.code = static_cast<int32_t>(usercode);
|
|
||||||
event.user.data1 = userdata;
|
|
||||||
SDL_PushEvent(&event);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
IScreenHandler & CGuiHandler::screenHandler()
|
IScreenHandler & CGuiHandler::screenHandler()
|
||||||
@@ -613,11 +237,16 @@ IScreenHandler & CGuiHandler::screenHandler()
|
|||||||
return *screenHandlerInstance;
|
return *screenHandlerInstance;
|
||||||
}
|
}
|
||||||
|
|
||||||
EventDispatcher & CGuiHandler::eventDispatcher()
|
EventDispatcher & CGuiHandler::events()
|
||||||
{
|
{
|
||||||
return *eventDispatcherInstance;
|
return *eventDispatcherInstance;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
InputHandler & CGuiHandler::input()
|
||||||
|
{
|
||||||
|
return *inputHandlerInstance;
|
||||||
|
}
|
||||||
|
|
||||||
WindowHandler & CGuiHandler::windows()
|
WindowHandler & CGuiHandler::windows()
|
||||||
{
|
{
|
||||||
assert(windowHandlerInstance);
|
assert(windowHandlerInstance);
|
||||||
|
|||||||
@@ -31,18 +31,17 @@ class IShowActivatable;
|
|||||||
class IScreenHandler;
|
class IScreenHandler;
|
||||||
class WindowHandler;
|
class WindowHandler;
|
||||||
class EventDispatcher;
|
class EventDispatcher;
|
||||||
|
class InputHandler;
|
||||||
|
|
||||||
// TODO: event handling need refactoring
|
// TODO: event handling need refactoring. Perhaps convert into delayed function call?
|
||||||
enum class EUserEvent
|
enum class EUserEvent
|
||||||
{
|
{
|
||||||
/*CHANGE_SCREEN_RESOLUTION = 1,*/
|
RETURN_TO_MAIN_MENU,
|
||||||
RETURN_TO_MAIN_MENU = 2,
|
RESTART_GAME,
|
||||||
//STOP_CLIENT = 3,
|
|
||||||
RESTART_GAME = 4,
|
|
||||||
RETURN_TO_MENU_LOAD,
|
RETURN_TO_MENU_LOAD,
|
||||||
FULLSCREEN_TOGGLED,
|
FULLSCREEN_TOGGLED,
|
||||||
CAMPAIGN_START_SCENARIO,
|
CAMPAIGN_START_SCENARIO,
|
||||||
FORCE_QUIT, //quit client without question
|
FORCE_QUIT,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Handles GUI logic and drawing
|
// Handles GUI logic and drawing
|
||||||
@@ -55,41 +54,22 @@ private:
|
|||||||
/// Status bar of current window, if any. Uses weak_ptr to allow potential hanging reference after owned window has been deleted
|
/// Status bar of current window, if any. Uses weak_ptr to allow potential hanging reference after owned window has been deleted
|
||||||
std::weak_ptr<IStatusBar> currentStatusBar;
|
std::weak_ptr<IStatusBar> currentStatusBar;
|
||||||
|
|
||||||
Point cursorPosition;
|
|
||||||
uint32_t mouseButtonsMask;
|
|
||||||
|
|
||||||
std::unique_ptr<ShortcutHandler> shortcutsHandlerInstance;
|
std::unique_ptr<ShortcutHandler> shortcutsHandlerInstance;
|
||||||
std::unique_ptr<WindowHandler> windowHandlerInstance;
|
std::unique_ptr<WindowHandler> windowHandlerInstance;
|
||||||
|
|
||||||
std::unique_ptr<IScreenHandler> screenHandlerInstance;
|
std::unique_ptr<IScreenHandler> screenHandlerInstance;
|
||||||
std::unique_ptr<FramerateManager> framerateManagerInstance;
|
std::unique_ptr<FramerateManager> framerateManagerInstance;
|
||||||
std::unique_ptr<EventDispatcher> eventDispatcherInstance;
|
std::unique_ptr<EventDispatcher> eventDispatcherInstance;
|
||||||
|
std::unique_ptr<InputHandler> inputHandlerInstance;
|
||||||
void handleCurrentEvent(SDL_Event ¤t);
|
|
||||||
void convertTouchToMouse(SDL_Event * current);
|
|
||||||
void fakeMoveCursor(float dx, float dy);
|
|
||||||
void fakeMouseButtonEventRelativeMode(bool down, bool right);
|
|
||||||
|
|
||||||
void handleEventKeyDown(SDL_Event & current);
|
|
||||||
void handleEventKeyUp(SDL_Event & current);
|
|
||||||
void handleEventMouseMotion(SDL_Event & current);
|
|
||||||
void handleEventMouseButtonDown(SDL_Event & current);
|
|
||||||
void handleEventMouseWheel(SDL_Event & current);
|
|
||||||
void handleEventTextInput(SDL_Event & current);
|
|
||||||
void handleEventTextEditing(SDL_Event & current);
|
|
||||||
void handleEventMouseButtonUp(SDL_Event & current);
|
|
||||||
void handleEventFingerMotion(SDL_Event & current);
|
|
||||||
void handleEventFingerDown(SDL_Event & current);
|
|
||||||
void handleEventFingerUp(SDL_Event & current);
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
/// returns current position of mouse cursor, relative to vcmi window
|
/// returns current position of mouse cursor, relative to vcmi window
|
||||||
const Point & getCursorPosition() const;
|
const Point & getCursorPosition() const;
|
||||||
|
|
||||||
ShortcutHandler & shortcutsHandler();
|
ShortcutHandler & shortcuts();
|
||||||
FramerateManager & framerateManager();
|
FramerateManager & framerate();
|
||||||
EventDispatcher & eventDispatcher();
|
EventDispatcher & events();
|
||||||
|
InputHandler & input();
|
||||||
|
|
||||||
/// Returns current logical screen dimensions
|
/// Returns current logical screen dimensions
|
||||||
/// May not match size of window if user has UI scaling different from 100%
|
/// May not match size of window if user has UI scaling different from 100%
|
||||||
@@ -109,9 +89,6 @@ public:
|
|||||||
void startTextInput(const Rect & where);
|
void startTextInput(const Rect & where);
|
||||||
void stopTextInput();
|
void stopTextInput();
|
||||||
|
|
||||||
/// moves mouse pointer into specified position inside vcmi window
|
|
||||||
void moveCursorToPosition(const Point & position);
|
|
||||||
|
|
||||||
IScreenHandler & screenHandler();
|
IScreenHandler & screenHandler();
|
||||||
|
|
||||||
WindowHandler & windows();
|
WindowHandler & windows();
|
||||||
@@ -124,10 +101,6 @@ public:
|
|||||||
|
|
||||||
IUpdateable *curInt;
|
IUpdateable *curInt;
|
||||||
|
|
||||||
bool multifinger;
|
|
||||||
bool isPointerRelativeMode;
|
|
||||||
float pointerSpeedMultiplier;
|
|
||||||
|
|
||||||
ui8 defActionsDef; //default auto actions
|
ui8 defActionsDef; //default auto actions
|
||||||
bool captureChildren; //all newly created objects will get their parents from stack and will be added to parents children list
|
bool captureChildren; //all newly created objects will get their parents from stack and will be added to parents children list
|
||||||
std::list<CIntObject *> createdObj; //stack of objs being created
|
std::list<CIntObject *> createdObj; //stack of objs being created
|
||||||
@@ -146,9 +119,9 @@ public:
|
|||||||
void breakEventHandling(); //current event won't be propagated anymore
|
void breakEventHandling(); //current event won't be propagated anymore
|
||||||
void drawFPSCounter(); // draws the FPS to the upper left corner of the screen
|
void drawFPSCounter(); // draws the FPS to the upper left corner of the screen
|
||||||
|
|
||||||
static bool amIGuiThread();
|
bool amIGuiThread();
|
||||||
static void pushUserEvent(EUserEvent usercode);
|
void pushUserEvent(EUserEvent usercode);
|
||||||
static void pushUserEvent(EUserEvent usercode, void * userdata);
|
void pushUserEvent(EUserEvent usercode, void * userdata);
|
||||||
|
|
||||||
CondSh<bool> * terminate_cond; // confirm termination
|
CondSh<bool> * terminate_cond; // confirm termination
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -251,7 +251,7 @@ void CursorHandler::updateSpellcastCursor()
|
|||||||
{
|
{
|
||||||
static const float frameDisplayDuration = 0.1f; // H3 uses 100 ms per frame
|
static const float frameDisplayDuration = 0.1f; // H3 uses 100 ms per frame
|
||||||
|
|
||||||
frameTime += GH.framerateManager().getElapsedMilliseconds() / 1000.f;
|
frameTime += GH.framerate().getElapsedMilliseconds() / 1000.f;
|
||||||
size_t newFrame = frame;
|
size_t newFrame = frame;
|
||||||
|
|
||||||
while (frameTime >= frameDisplayDuration)
|
while (frameTime >= frameDisplayDuration)
|
||||||
|
|||||||
@@ -51,14 +51,14 @@ void AEventsReceiver::activateEvents(ui16 what)
|
|||||||
assert((what & GENERAL) || (activeState & GENERAL));
|
assert((what & GENERAL) || (activeState & GENERAL));
|
||||||
|
|
||||||
activeState |= GENERAL;
|
activeState |= GENERAL;
|
||||||
GH.eventDispatcher().handleElementActivate(this, what);
|
GH.events().handleElementActivate(this, what);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AEventsReceiver::deactivateEvents(ui16 what)
|
void AEventsReceiver::deactivateEvents(ui16 what)
|
||||||
{
|
{
|
||||||
if (what & GENERAL)
|
if (what & GENERAL)
|
||||||
activeState &= ~GENERAL;
|
activeState &= ~GENERAL;
|
||||||
GH.eventDispatcher().handleElementDeActivate(this, what & activeState);
|
GH.events().handleElementDeActivate(this, what & activeState);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AEventsReceiver::click(MouseButton btn, tribool down, bool previousState)
|
void AEventsReceiver::click(MouseButton btn, tribool down, bool previousState)
|
||||||
|
|||||||
@@ -224,7 +224,7 @@ EShortcut InterfaceObjectConfigurable::readHotkey(const JsonNode & config) const
|
|||||||
return EShortcut::NONE;
|
return EShortcut::NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
EShortcut result = GH.shortcutsHandler().findShortcut(config.String());
|
EShortcut result = GH.shortcuts().findShortcut(config.String());
|
||||||
if (result == EShortcut::NONE)
|
if (result == EShortcut::NONE)
|
||||||
logGlobal->error("Invalid hotkey '%s' in interface configuration!", config.String());
|
logGlobal->error("Invalid hotkey '%s' in interface configuration!", config.String());
|
||||||
return result;;
|
return result;;
|
||||||
|
|||||||
@@ -233,7 +233,7 @@ std::shared_ptr<CButton> CMenuEntry::createButton(CMenuScreen * parent, const Js
|
|||||||
if(posy < 0)
|
if(posy < 0)
|
||||||
posy = pos.h + posy;
|
posy = pos.h + posy;
|
||||||
|
|
||||||
EShortcut shortcut = GH.shortcutsHandler().findShortcut(button["shortcut"].String());
|
EShortcut shortcut = GH.shortcuts().findShortcut(button["shortcut"].String());
|
||||||
|
|
||||||
auto result = std::make_shared<CButton>(Point(posx, posy), button["name"].String(), help, command, shortcut);
|
auto result = std::make_shared<CButton>(Point(posx, posy), button["name"].String(), help, command, shortcut);
|
||||||
|
|
||||||
|
|||||||
@@ -98,8 +98,8 @@ void MapViewActions::handleSwipeMove(const Point & cursorPosition)
|
|||||||
if(!swipeEnabled() && !GH.isMouseButtonPressed(MouseButton::MIDDLE))
|
if(!swipeEnabled() && !GH.isMouseButtonPressed(MouseButton::MIDDLE))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// on mobile platforms with enabled swipe any button is enough
|
// on mobile platforms with enabled swipe we use left button
|
||||||
if(swipeEnabled() && (!GH.isMouseButtonPressed() || GH.multifinger))
|
if(swipeEnabled() && !GH.isMouseButtonPressed(MouseButton::LEFT))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if(!isSwiping)
|
if(!isSwiping)
|
||||||
|
|||||||
@@ -13,7 +13,7 @@
|
|||||||
|
|
||||||
#include "../../lib/CConfigHandler.h"
|
#include "../../lib/CConfigHandler.h"
|
||||||
#include "../gui/CGuiHandler.h"
|
#include "../gui/CGuiHandler.h"
|
||||||
#include "../gui/NotificationHandler.h"
|
#include "../eventsSDL/NotificationHandler.h"
|
||||||
#include "../gui/WindowHandler.h"
|
#include "../gui/WindowHandler.h"
|
||||||
#include "CMT.h"
|
#include "CMT.h"
|
||||||
#include "SDL_Extensions.h"
|
#include "SDL_Extensions.h"
|
||||||
|
|||||||
Reference in New Issue
Block a user