|
@@ -1,5 +1,6 @@
|
|
|
#include "StdInc.h"
|
|
#include "StdInc.h"
|
|
|
#include "CGuiHandler.h"
|
|
#include "CGuiHandler.h"
|
|
|
|
|
+#include "../lib/CondSh.h"
|
|
|
|
|
|
|
|
#include <SDL.h>
|
|
#include <SDL.h>
|
|
|
|
|
|
|
@@ -15,6 +16,7 @@
|
|
|
extern std::queue<SDL_Event> events;
|
|
extern std::queue<SDL_Event> events;
|
|
|
extern boost::mutex eventsM;
|
|
extern boost::mutex eventsM;
|
|
|
|
|
|
|
|
|
|
+CondSh<bool> CGuiHandler::terminate_cond;
|
|
|
boost::thread_specific_ptr<bool> inGuiThread;
|
|
boost::thread_specific_ptr<bool> inGuiThread;
|
|
|
|
|
|
|
|
SObjectConstruction::SObjectConstruction( CIntObject *obj )
|
|
SObjectConstruction::SObjectConstruction( CIntObject *obj )
|
|
@@ -63,10 +65,7 @@ void CGuiHandler::processLists(const ui16 activityFlag, std::function<void (std:
|
|
|
processList(CIntObject::TIME,activityFlag,&timeinterested,cb);
|
|
processList(CIntObject::TIME,activityFlag,&timeinterested,cb);
|
|
|
processList(CIntObject::WHEEL,activityFlag,&wheelInterested,cb);
|
|
processList(CIntObject::WHEEL,activityFlag,&wheelInterested,cb);
|
|
|
processList(CIntObject::DOUBLECLICK,activityFlag,&doubleClickInterested,cb);
|
|
processList(CIntObject::DOUBLECLICK,activityFlag,&doubleClickInterested,cb);
|
|
|
-
|
|
|
|
|
- #ifndef VCMI_SDL1
|
|
|
|
|
processList(CIntObject::TEXTINPUT,activityFlag,&textInterested,cb);
|
|
processList(CIntObject::TEXTINPUT,activityFlag,&textInterested,cb);
|
|
|
- #endif // VCMI_SDL1
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
void CGuiHandler::handleElementActivate(CIntObject * elem, ui16 activityFlag)
|
|
void CGuiHandler::handleElementActivate(CIntObject * elem, ui16 activityFlag)
|
|
@@ -196,10 +195,8 @@ void CGuiHandler::handleEvent(SDL_Event *sEvent)
|
|
|
//translate numpad keys
|
|
//translate numpad keys
|
|
|
if(key.keysym.sym == SDLK_KP_ENTER)
|
|
if(key.keysym.sym == SDLK_KP_ENTER)
|
|
|
{
|
|
{
|
|
|
- key.keysym.sym = (SDLKey)SDLK_RETURN;
|
|
|
|
|
- #ifndef VCMI_SDL1
|
|
|
|
|
|
|
+ key.keysym.sym = SDLK_RETURN;
|
|
|
key.keysym.scancode = SDL_SCANCODE_RETURN;
|
|
key.keysym.scancode = SDL_SCANCODE_RETURN;
|
|
|
- #endif // VCMI_SDL1
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
bool keysCaptured = false;
|
|
bool keysCaptured = false;
|
|
@@ -270,19 +267,7 @@ void CGuiHandler::handleEvent(SDL_Event *sEvent)
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
- #ifdef VCMI_SDL1 //SDL1x only events
|
|
|
|
|
- else if(sEvent->button.button == SDL_BUTTON_WHEELDOWN || sEvent->button.button == SDL_BUTTON_WHEELUP)
|
|
|
|
|
- {
|
|
|
|
|
- std::list<CIntObject*> hlp = wheelInterested;
|
|
|
|
|
- for(auto i=hlp.begin(); i != hlp.end() && current; i++)
|
|
|
|
|
- {
|
|
|
|
|
- if(!vstd::contains(wheelInterested,*i)) continue;
|
|
|
|
|
- (*i)->wheelScrolled(sEvent->button.button == SDL_BUTTON_WHEELDOWN, isItIn(&(*i)->pos,sEvent->motion.x,sEvent->motion.y));
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- #endif
|
|
|
|
|
}
|
|
}
|
|
|
- #ifndef VCMI_SDL1 //SDL2x only events
|
|
|
|
|
else if (sEvent->type == SDL_MOUSEWHEEL)
|
|
else if (sEvent->type == SDL_MOUSEWHEEL)
|
|
|
{
|
|
{
|
|
|
std::list<CIntObject*> hlp = wheelInterested;
|
|
std::list<CIntObject*> hlp = wheelInterested;
|
|
@@ -307,7 +292,6 @@ void CGuiHandler::handleEvent(SDL_Event *sEvent)
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
//todo: muiltitouch
|
|
//todo: muiltitouch
|
|
|
- #endif // VCMI_SDL1
|
|
|
|
|
else if ((sEvent->type==SDL_MOUSEBUTTONUP) && (sEvent->button.button == SDL_BUTTON_LEFT))
|
|
else if ((sEvent->type==SDL_MOUSEBUTTONUP) && (sEvent->button.button == SDL_BUTTON_LEFT))
|
|
|
{
|
|
{
|
|
|
std::list<CIntObject*> hlp = lclickable;
|
|
std::list<CIntObject*> hlp = lclickable;
|
|
@@ -341,7 +325,6 @@ void CGuiHandler::handleEvent(SDL_Event *sEvent)
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
current = nullptr;
|
|
current = nullptr;
|
|
|
-
|
|
|
|
|
} //event end
|
|
} //event end
|
|
|
|
|
|
|
|
void CGuiHandler::handleMouseMotion(SDL_Event *sEvent)
|
|
void CGuiHandler::handleMouseMotion(SDL_Event *sEvent)
|
|
@@ -394,12 +377,9 @@ void CGuiHandler::handleMoveInterested( const SDL_MouseMotionEvent & motion )
|
|
|
void CGuiHandler::fakeMouseMove()
|
|
void CGuiHandler::fakeMouseMove()
|
|
|
{
|
|
{
|
|
|
SDL_Event evnt;
|
|
SDL_Event evnt;
|
|
|
-#ifdef VCMI_SDL1
|
|
|
|
|
- SDL_MouseMotionEvent sme = {SDL_MOUSEMOTION, 0, 0, 0, 0, 0, 0};
|
|
|
|
|
-#else
|
|
|
|
|
SDL_MouseMotionEvent sme = {SDL_MOUSEMOTION, 0, 0, 0, 0, 0, 0, 0, 0};
|
|
SDL_MouseMotionEvent sme = {SDL_MOUSEMOTION, 0, 0, 0, 0, 0, 0, 0, 0};
|
|
|
-#endif
|
|
|
|
|
int x, y;
|
|
int x, y;
|
|
|
|
|
+
|
|
|
sme.state = SDL_GetMouseState(&x, &y);
|
|
sme.state = SDL_GetMouseState(&x, &y);
|
|
|
sme.x = x;
|
|
sme.x = x;
|
|
|
sme.y = y;
|
|
sme.y = y;
|
|
@@ -411,28 +391,42 @@ void CGuiHandler::fakeMouseMove()
|
|
|
|
|
|
|
|
void CGuiHandler::renderFrame()
|
|
void CGuiHandler::renderFrame()
|
|
|
{
|
|
{
|
|
|
- auto doUpdate = [this]()
|
|
|
|
|
{
|
|
{
|
|
|
- if(nullptr != curInt)
|
|
|
|
|
|
|
+ // 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,
|
|
|
|
|
+ // that will notify us about the ending game by setting terminate_cond flag.
|
|
|
|
|
+ //in PreGame terminate_cond stay false
|
|
|
|
|
+
|
|
|
|
|
+ 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(15));
|
|
|
|
|
+
|
|
|
|
|
+ if(!acquiredTheLockOnPim)
|
|
|
{
|
|
{
|
|
|
- curInt -> update();
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ // We broke the while loop above and not because of mutex, so we must be terminating.
|
|
|
|
|
+ assert(terminate_cond.get());
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 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();
|
|
|
|
|
+
|
|
|
|
|
+ if (settings["general"]["showfps"].Bool())
|
|
|
|
|
+ drawFPSCounter();
|
|
|
|
|
+
|
|
|
// draw the mouse cursor and update the screen
|
|
// draw the mouse cursor and update the screen
|
|
|
CCS->curh->render();
|
|
CCS->curh->render();
|
|
|
|
|
|
|
|
- #ifndef VCMI_SDL1
|
|
|
|
|
if(0 != SDL_RenderCopy(mainRenderer, screenTexture, nullptr, nullptr))
|
|
if(0 != SDL_RenderCopy(mainRenderer, screenTexture, nullptr, nullptr))
|
|
|
logGlobal->errorStream() << __FUNCTION__ << " SDL_RenderCopy " << SDL_GetError();
|
|
logGlobal->errorStream() << __FUNCTION__ << " SDL_RenderCopy " << SDL_GetError();
|
|
|
|
|
|
|
|
- SDL_RenderPresent(mainRenderer);
|
|
|
|
|
- #endif
|
|
|
|
|
-
|
|
|
|
|
- };
|
|
|
|
|
-
|
|
|
|
|
- if(curInt)
|
|
|
|
|
- curInt->runLocked(doUpdate);
|
|
|
|
|
- else
|
|
|
|
|
- doUpdate();
|
|
|
|
|
|
|
+ SDL_RenderPresent(mainRenderer);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
|
|
|
mainFPSmng->framerateDelay(); // holds a constant FPS
|
|
mainFPSmng->framerateDelay(); // holds a constant FPS
|
|
|
}
|
|
}
|
|
@@ -448,6 +442,8 @@ CGuiHandler::CGuiHandler()
|
|
|
// Creates the FPS manager and sets the framerate to 48 which is doubled the value of the original Heroes 3 FPS rate
|
|
// Creates the FPS manager and sets the framerate to 48 which is doubled the value of the original Heroes 3 FPS rate
|
|
|
mainFPSmng = new CFramerateManager(48);
|
|
mainFPSmng = new CFramerateManager(48);
|
|
|
//do not init CFramerateManager here --AVS
|
|
//do not init CFramerateManager here --AVS
|
|
|
|
|
+
|
|
|
|
|
+ terminate_cond.set(false);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
CGuiHandler::~CGuiHandler()
|
|
CGuiHandler::~CGuiHandler()
|
|
@@ -470,23 +466,8 @@ void CGuiHandler::drawFPSCounter()
|
|
|
graphics->fonts[FONT_BIG]->renderTextLeft(screen, fps, yellow, Point(10, 10));
|
|
graphics->fonts[FONT_BIG]->renderTextLeft(screen, fps, yellow, Point(10, 10));
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-SDLKey CGuiHandler::arrowToNum( SDLKey key )
|
|
|
|
|
|
|
+SDL_Keycode CGuiHandler::arrowToNum(SDL_Keycode key )
|
|
|
{
|
|
{
|
|
|
- #ifdef VCMI_SDL1
|
|
|
|
|
- switch(key)
|
|
|
|
|
- {
|
|
|
|
|
- case SDLK_DOWN:
|
|
|
|
|
- return SDLK_KP2;
|
|
|
|
|
- case SDLK_UP:
|
|
|
|
|
- return SDLK_KP8;
|
|
|
|
|
- case SDLK_LEFT:
|
|
|
|
|
- return SDLK_KP4;
|
|
|
|
|
- case SDLK_RIGHT:
|
|
|
|
|
- return SDLK_KP6;
|
|
|
|
|
- default:
|
|
|
|
|
- throw std::runtime_error("Wrong key!");assert(0);
|
|
|
|
|
- }
|
|
|
|
|
- #else
|
|
|
|
|
switch(key)
|
|
switch(key)
|
|
|
{
|
|
{
|
|
|
case SDLK_DOWN:
|
|
case SDLK_DOWN:
|
|
@@ -500,20 +481,14 @@ SDLKey CGuiHandler::arrowToNum( SDLKey key )
|
|
|
default:
|
|
default:
|
|
|
throw std::runtime_error("Wrong key!");
|
|
throw std::runtime_error("Wrong key!");
|
|
|
}
|
|
}
|
|
|
- #endif // 0
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-SDLKey CGuiHandler::numToDigit( SDLKey key )
|
|
|
|
|
|
|
+SDL_Keycode CGuiHandler::numToDigit(SDL_Keycode key)
|
|
|
{
|
|
{
|
|
|
-#ifdef VCMI_SDL1
|
|
|
|
|
- if(key >= SDLK_KP0 && key <= SDLK_KP9)
|
|
|
|
|
- return SDLKey(key - SDLK_KP0 + SDLK_0);
|
|
|
|
|
-#endif // 0
|
|
|
|
|
|
|
|
|
|
#define REMOVE_KP(keyName) case SDLK_KP_ ## keyName : return SDLK_ ## keyName;
|
|
#define REMOVE_KP(keyName) case SDLK_KP_ ## keyName : return SDLK_ ## keyName;
|
|
|
switch(key)
|
|
switch(key)
|
|
|
{
|
|
{
|
|
|
-#ifndef VCMI_SDL1
|
|
|
|
|
REMOVE_KP(0)
|
|
REMOVE_KP(0)
|
|
|
REMOVE_KP(1)
|
|
REMOVE_KP(1)
|
|
|
REMOVE_KP(2)
|
|
REMOVE_KP(2)
|
|
@@ -524,7 +499,6 @@ SDLKey CGuiHandler::numToDigit( SDLKey key )
|
|
|
REMOVE_KP(7)
|
|
REMOVE_KP(7)
|
|
|
REMOVE_KP(8)
|
|
REMOVE_KP(8)
|
|
|
REMOVE_KP(9)
|
|
REMOVE_KP(9)
|
|
|
-#endif // VCMI_SDL1
|
|
|
|
|
REMOVE_KP(PERIOD)
|
|
REMOVE_KP(PERIOD)
|
|
|
REMOVE_KP(MINUS)
|
|
REMOVE_KP(MINUS)
|
|
|
REMOVE_KP(PLUS)
|
|
REMOVE_KP(PLUS)
|
|
@@ -542,22 +516,15 @@ SDLKey CGuiHandler::numToDigit( SDLKey key )
|
|
|
#undef REMOVE_KP
|
|
#undef REMOVE_KP
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-bool CGuiHandler::isNumKey( SDLKey key, bool number )
|
|
|
|
|
|
|
+bool CGuiHandler::isNumKey(SDL_Keycode key, bool number)
|
|
|
{
|
|
{
|
|
|
- #ifdef VCMI_SDL1
|
|
|
|
|
- if(number)
|
|
|
|
|
- return key >= SDLK_KP0 && key <= SDLK_KP9;
|
|
|
|
|
- else
|
|
|
|
|
- return key >= SDLK_KP0 && key <= SDLK_KP_EQUALS;
|
|
|
|
|
- #else
|
|
|
|
|
if(number)
|
|
if(number)
|
|
|
return key >= SDLK_KP_1 && key <= SDLK_KP_0;
|
|
return key >= SDLK_KP_1 && key <= SDLK_KP_0;
|
|
|
else
|
|
else
|
|
|
return (key >= SDLK_KP_1 && key <= SDLK_KP_0) || key == SDLK_KP_MINUS || key == SDLK_KP_PLUS || key == SDLK_KP_EQUALS;
|
|
return (key >= SDLK_KP_1 && key <= SDLK_KP_0) || key == SDLK_KP_MINUS || key == SDLK_KP_PLUS || key == SDLK_KP_EQUALS;
|
|
|
- #endif // 0
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-bool CGuiHandler::isArrowKey( SDLKey key )
|
|
|
|
|
|
|
+bool CGuiHandler::isArrowKey(SDL_Keycode key)
|
|
|
{
|
|
{
|
|
|
return key == SDLK_UP || key == SDLK_DOWN || key == SDLK_LEFT || key == SDLK_RIGHT;
|
|
return key == SDLK_UP || key == SDLK_DOWN || key == SDLK_LEFT || key == SDLK_RIGHT;
|
|
|
}
|
|
}
|
|
@@ -580,6 +547,8 @@ CFramerateManager::CFramerateManager(int rate)
|
|
|
this->rate = rate;
|
|
this->rate = rate;
|
|
|
this->rateticks = (1000.0 / rate);
|
|
this->rateticks = (1000.0 / rate);
|
|
|
this->fps = 0;
|
|
this->fps = 0;
|
|
|
|
|
+ this->accumulatedFrames = 0;
|
|
|
|
|
+ this->accumulatedTime = 0;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
void CFramerateManager::init()
|
|
void CFramerateManager::init()
|
|
@@ -591,18 +560,28 @@ void CFramerateManager::framerateDelay()
|
|
|
{
|
|
{
|
|
|
ui32 currentTicks = SDL_GetTicks();
|
|
ui32 currentTicks = SDL_GetTicks();
|
|
|
timeElapsed = currentTicks - lastticks;
|
|
timeElapsed = currentTicks - lastticks;
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
// FPS is higher than it should be, then wait some time
|
|
// FPS is higher than it should be, then wait some time
|
|
|
if (timeElapsed < rateticks)
|
|
if (timeElapsed < rateticks)
|
|
|
{
|
|
{
|
|
|
SDL_Delay(ceil(this->rateticks) - timeElapsed);
|
|
SDL_Delay(ceil(this->rateticks) - timeElapsed);
|
|
|
}
|
|
}
|
|
|
- currentTicks = SDL_GetTicks();
|
|
|
|
|
|
|
+
|
|
|
|
|
+ accumulatedTime += timeElapsed;
|
|
|
|
|
+ accumulatedFrames++;
|
|
|
|
|
|
|
|
- fps = ceil(1000.0 / timeElapsed);
|
|
|
|
|
|
|
+ if(accumulatedFrames >= 100)
|
|
|
|
|
+ {
|
|
|
|
|
+ //about 2 second should be passed
|
|
|
|
|
+ fps = ceil(1000.0 / (accumulatedTime/accumulatedFrames));
|
|
|
|
|
+ accumulatedTime = 0;
|
|
|
|
|
+ accumulatedFrames = 0;
|
|
|
|
|
+ };
|
|
|
|
|
|
|
|
|
|
+ currentTicks = SDL_GetTicks();
|
|
|
// recalculate timeElapsed for external calls via getElapsed()
|
|
// recalculate timeElapsed for external calls via getElapsed()
|
|
|
// limit it to 1000 ms to avoid breaking animation in case of huge lag (e.g. triggered breakpoint)
|
|
// limit it to 1000 ms to avoid breaking animation in case of huge lag (e.g. triggered breakpoint)
|
|
|
timeElapsed = std::min<ui32>(currentTicks - lastticks, 1000);
|
|
timeElapsed = std::min<ui32>(currentTicks - lastticks, 1000);
|
|
|
|
|
+
|
|
|
lastticks = SDL_GetTicks();
|
|
lastticks = SDL_GetTicks();
|
|
|
}
|
|
}
|