1
0
mirror of https://github.com/vcmi/vcmi.git synced 2024-12-16 10:19:47 +02:00
vcmi/client/gui/CGuiHandler.cpp

257 lines
6.2 KiB
C++
Raw Normal View History

/*
* CGuiHandler.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 "CGuiHandler.h"
2015-06-22 20:53:47 +02:00
#include "../lib/CondSh.h"
#include "CIntObject.h"
#include "CursorHandler.h"
#include "ShortcutHandler.h"
#include "FramerateManager.h"
#include "WindowHandler.h"
2023-05-18 12:31:26 +02:00
#include "EventDispatcher.h"
#include "../eventsSDL/InputHandler.h"
#include "../CGameInfo.h"
#include "../render/Colors.h"
#include "../renderSDL/ScreenHandler.h"
#include "../CMT.h"
2014-05-23 22:39:10 +03:00
#include "../CPlayerInterface.h"
#include "../battle/BattleInterface.h"
#include "../../lib/CThreadHelper.h"
#include "../../lib/CConfigHandler.h"
2023-01-30 00:12:43 +02:00
#include <SDL_render.h>
2023-02-02 19:10:29 +02:00
CGuiHandler GH;
boost::thread_specific_ptr<bool> inGuiThread;
SObjectConstruction::SObjectConstruction(CIntObject *obj)
:myObj(obj)
{
GH.createdObj.push_front(obj);
GH.captureChildren = true;
}
SObjectConstruction::~SObjectConstruction()
{
assert(GH.createdObj.size());
assert(GH.createdObj.front() == myObj);
GH.createdObj.pop_front();
GH.captureChildren = GH.createdObj.size();
}
SSetCaptureState::SSetCaptureState(bool allow, ui8 actions)
{
previousCapture = GH.captureChildren;
GH.captureChildren = false;
prevActions = GH.defActionsDef;
GH.defActionsDef = actions;
}
SSetCaptureState::~SSetCaptureState()
{
GH.captureChildren = previousCapture;
GH.defActionsDef = prevActions;
}
2023-01-16 12:26:43 +02:00
void CGuiHandler::init()
{
inputHandlerInstance = std::make_unique<InputHandler>();
2023-05-18 12:31:26 +02:00
eventDispatcherInstance = std::make_unique<EventDispatcher>();
windowHandlerInstance = std::make_unique<WindowHandler>();
screenHandlerInstance = std::make_unique<ScreenHandler>();
2023-04-28 13:22:03 +02:00
shortcutsHandlerInstance = std::make_unique<ShortcutHandler>();
framerateManagerInstance = std::make_unique<FramerateManager>(settings["video"]["targetfps"].Integer());
2023-01-16 12:26:43 +02:00
}
void CGuiHandler::handleEvents()
{
events().dispatchTimer(framerate().getElapsedMilliseconds());
2023-05-18 01:09:42 +02:00
2016-11-27 16:48:18 +02:00
//player interface may want special event handling
if(nullptr != LOCPLINT && LOCPLINT->capturedAllEvents())
return;
2016-11-27 16:48:18 +02:00
input().processEvents();
2023-01-16 12:26:43 +02:00
}
void CGuiHandler::fakeMouseMove()
{
pushUserEvent(EUserEvent::FAKE_MOUSE_MOVE);
2023-01-16 12:26:43 +02:00
}
void CGuiHandler::startTextInput(const Rect & whereInput)
{
input().startTextInput(whereInput);
}
void CGuiHandler::stopTextInput()
{
input().stopTextInput();
}
void CGuiHandler::renderFrame()
{
2015-06-22 20:53:47 +02:00
// Updating GUI requires locking pim mutex (that protects screen and GUI state).
// During game:
// When ending the game, the pim mutex might be hold by other thread,
2016-11-27 16:48:18 +02:00
// that will notify us about the ending game by setting terminate_cond flag.
//in PreGame terminate_cond stay false
2015-08-22 15:47:40 +02:00
bool acquiredTheLockOnPim = false; //for tracking whether pim mutex locking succeeded
while(!terminate_cond->get() && !(acquiredTheLockOnPim = CPlayerInterface::pim->try_lock())) //try acquiring long until it succeeds or we are told to terminate
boost::this_thread::sleep(boost::posix_time::milliseconds(1));
2015-06-22 20:53:47 +02:00
2015-08-22 15:47:40 +02:00
if(acquiredTheLockOnPim)
{
2015-06-22 20:53:47 +02:00
// If we are here, pim mutex has been successfully locked - let's store it in a safe RAII lock.
boost::unique_lock<boost::recursive_mutex> un(*CPlayerInterface::pim, boost::adopt_lock);
if(nullptr != curInt)
curInt->update();
2016-11-27 16:48:18 +02:00
if(settings["video"]["showfps"].Bool())
2016-11-27 16:48:18 +02:00
drawFPSCounter();
SDL_UpdateTexture(screenTexture, nullptr, screen->pixels, screen->pitch);
2022-06-13 15:11:53 +02:00
SDL_RenderClear(mainRenderer);
SDL_RenderCopy(mainRenderer, screenTexture, nullptr, nullptr);
CCS->curh->render();
2016-11-27 16:48:18 +02:00
SDL_RenderPresent(mainRenderer);
windows().onFrameRendered();
2016-11-27 16:48:18 +02:00
}
2022-06-05 15:20:01 +02:00
framerate().framerateDelay(); // holds a constant FPS
}
CGuiHandler::CGuiHandler()
2023-05-18 01:09:42 +02:00
: defActionsDef(0)
, captureChildren(false)
, curInt(nullptr)
2023-05-16 17:34:23 +02:00
, fakeStatusBar(std::make_shared<EmptyStatusBar>())
, terminate_cond (new CondSh<bool>(false))
{
}
CGuiHandler::~CGuiHandler()
{
delete terminate_cond;
}
ShortcutHandler & CGuiHandler::shortcuts()
{
assert(shortcutsHandlerInstance);
2023-04-28 13:22:03 +02:00
return *shortcutsHandlerInstance;
}
FramerateManager & CGuiHandler::framerate()
{
assert(framerateManagerInstance);
return *framerateManagerInstance;
}
bool CGuiHandler::isKeyboardCtrlDown() const
{
return inputHandlerInstance->isKeyboardCtrlDown();
}
bool CGuiHandler::isKeyboardAltDown() const
{
return inputHandlerInstance->isKeyboardAltDown();
}
bool CGuiHandler::isKeyboardShiftDown() const
{
return inputHandlerInstance->isKeyboardShiftDown();
}
const Point & CGuiHandler::getCursorPosition() const
{
return inputHandlerInstance->getCursorPosition();
}
Point CGuiHandler::screenDimensions() const
{
return Point(screen->w, screen->h);
}
void CGuiHandler::drawFPSCounter()
{
static SDL_Rect overlay = { 0, 0, 64, 32};
uint32_t black = SDL_MapRGB(screen->format, 10, 10, 10);
SDL_FillRect(screen, &overlay, black);
std::string fps = std::to_string(framerate().getFramerate());
2023-01-30 00:12:43 +02:00
graphics->fonts[FONT_BIG]->renderTextLeft(screen, fps, Colors::YELLOW, Point(10, 10));
}
bool CGuiHandler::amIGuiThread()
{
return inGuiThread.get() && *inGuiThread;
}
void CGuiHandler::pushUserEvent(EUserEvent usercode)
{
inputHandlerInstance->pushUserEvent(usercode, nullptr);
}
void CGuiHandler::pushUserEvent(EUserEvent usercode, void * userdata)
{
inputHandlerInstance->pushUserEvent(usercode, userdata);
}
IScreenHandler & CGuiHandler::screenHandler()
{
return *screenHandlerInstance;
}
EventDispatcher & CGuiHandler::events()
{
return *eventDispatcherInstance;
}
InputHandler & CGuiHandler::input()
{
return *inputHandlerInstance;
}
WindowHandler & CGuiHandler::windows()
{
assert(windowHandlerInstance);
return *windowHandlerInstance;
}
2023-05-16 17:34:23 +02:00
std::shared_ptr<IStatusBar> CGuiHandler::statusbar()
{
auto locked = currentStatusBar.lock();
if (!locked)
return fakeStatusBar;
return locked;
}
void CGuiHandler::setStatusbar(std::shared_ptr<IStatusBar> newStatusBar)
{
currentStatusBar = newStatusBar;
}
void CGuiHandler::onScreenResize()
{
screenHandler().onScreenResize();
windows().onScreenResize();
}