2011-12-17 21:59:59 +03:00
# include "StdInc.h"
# include "CGuiHandler.h"
2015-06-22 20:53:47 +02:00
# include "../lib/CondSh.h"
2011-12-17 21:59:59 +03:00
2014-07-15 10:14:49 +03:00
# include <SDL.h>
2011-12-17 21:59:59 +03:00
# include "CIntObject.h"
2011-12-22 16:05:19 +03:00
# include "CCursorHandler.h"
2014-07-13 20:53:37 +03:00
# include "../CGameInfo.h"
2011-12-17 21:59:59 +03:00
# include "../../lib/CThreadHelper.h"
2012-09-29 13:59:43 +03:00
# include "../../lib/CConfigHandler.h"
2013-04-04 17:58:54 +03:00
# include "../CMT.h"
2014-05-23 22:39:10 +03:00
# include "../CPlayerInterface.h"
2011-12-17 21:59:59 +03:00
2012-09-11 17:25:19 +03:00
extern std : : queue < SDL_Event > events ;
2011-12-17 21:59:59 +03:00
extern boost : : mutex eventsM ;
2015-06-22 20:53:47 +02:00
CondSh < bool > CGuiHandler : : terminate_cond ;
2012-04-08 04:15:18 +03:00
boost : : thread_specific_ptr < bool > inGuiThread ;
2016-10-22 16:22:00 +02:00
SObjectConstruction : : SObjectConstruction ( CIntObject * obj )
2011-12-17 21:59:59 +03:00
: 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 ;
}
2014-03-07 16:21:09 +03:00
static inline void
2012-10-06 23:35:04 +03:00
processList ( const ui16 mask , const ui16 flag , std : : list < CIntObject * > * lst , std : : function < void ( std : : list < CIntObject * > * ) > cb )
{
if ( mask & flag )
2014-03-07 16:21:09 +03:00
cb ( lst ) ;
2012-10-06 23:35:04 +03:00
}
2014-03-07 16:21:09 +03:00
void CGuiHandler : : processLists ( const ui16 activityFlag , std : : function < void ( std : : list < CIntObject * > * ) > cb )
2012-10-06 23:35:04 +03:00
{
processList ( CIntObject : : LCLICK , activityFlag , & lclickable , cb ) ;
processList ( CIntObject : : RCLICK , activityFlag , & rclickable , cb ) ;
processList ( CIntObject : : HOVER , activityFlag , & hoverable , cb ) ;
processList ( CIntObject : : MOVE , activityFlag , & motioninterested , cb ) ;
processList ( CIntObject : : KEYBOARD , activityFlag , & keyinterested , cb ) ;
processList ( CIntObject : : TIME , activityFlag , & timeinterested , cb ) ;
2014-03-07 16:21:09 +03:00
processList ( CIntObject : : WHEEL , activityFlag , & wheelInterested , cb ) ;
processList ( CIntObject : : DOUBLECLICK , activityFlag , & doubleClickInterested , cb ) ;
2014-05-23 19:46:54 +03:00
processList ( CIntObject : : TEXTINPUT , activityFlag , & textInterested , cb ) ;
2012-10-06 23:35:04 +03:00
}
void CGuiHandler : : handleElementActivate ( CIntObject * elem , ui16 activityFlag )
{
2012-10-07 13:38:35 +03:00
processLists ( activityFlag , [ & ] ( std : : list < CIntObject * > * lst ) {
2014-03-07 16:21:09 +03:00
lst - > push_front ( elem ) ;
2012-10-06 23:35:04 +03:00
} ) ;
elem - > active_m | = activityFlag ;
}
void CGuiHandler : : handleElementDeActivate ( CIntObject * elem , ui16 activityFlag )
{
2012-10-07 13:38:35 +03:00
processLists ( activityFlag , [ & ] ( std : : list < CIntObject * > * lst ) {
2013-06-29 16:05:48 +03:00
auto hlp = std : : find ( lst - > begin ( ) , lst - > end ( ) , elem ) ;
2012-10-06 23:35:04 +03:00
assert ( hlp ! = lst - > end ( ) ) ;
2014-03-07 16:21:09 +03:00
lst - > erase ( hlp ) ;
2012-10-06 23:35:04 +03:00
} ) ;
elem - > active_m & = ~ activityFlag ;
}
2016-10-22 16:22:00 +02:00
void CGuiHandler : : popInt ( IShowActivatable * top )
2011-12-17 21:59:59 +03:00
{
assert ( listInt . front ( ) = = top ) ;
top - > deactivate ( ) ;
listInt . pop_front ( ) ;
objsToBlit - = top ;
2013-11-03 15:51:25 +03:00
if ( ! listInt . empty ( ) )
2011-12-17 21:59:59 +03:00
listInt . front ( ) - > activate ( ) ;
totalRedraw ( ) ;
}
2016-10-22 16:22:00 +02:00
void CGuiHandler : : popIntTotally ( IShowActivatable * top )
2011-12-17 21:59:59 +03:00
{
assert ( listInt . front ( ) = = top ) ;
popInt ( top ) ;
delete top ;
fakeMouseMove ( ) ;
}
2016-10-22 16:22:00 +02:00
void CGuiHandler : : pushInt ( IShowActivatable * newInt )
2011-12-17 21:59:59 +03:00
{
2013-07-22 19:23:23 +03:00
assert ( newInt ) ;
assert ( boost : : range : : find ( listInt , newInt ) = = listInt . end ( ) ) ; // do not add same object twice
2011-12-17 21:59:59 +03:00
//a new interface will be present, we'll need to use buffer surface (unless it's advmapint that will alter screenBuf on activate anyway)
2014-03-07 16:21:09 +03:00
screenBuf = screen2 ;
2011-12-17 21:59:59 +03:00
2013-11-03 15:51:25 +03:00
if ( ! listInt . empty ( ) )
2011-12-17 21:59:59 +03:00
listInt . front ( ) - > deactivate ( ) ;
listInt . push_front ( newInt ) ;
newInt - > activate ( ) ;
objsToBlit . push_back ( newInt ) ;
totalRedraw ( ) ;
}
2016-10-22 16:22:00 +02:00
void CGuiHandler : : popInts ( int howMany )
2011-12-17 21:59:59 +03:00
{
if ( ! howMany ) return ; //senseless but who knows...
assert ( listInt . size ( ) > = howMany ) ;
listInt . front ( ) - > deactivate ( ) ;
for ( int i = 0 ; i < howMany ; i + + )
{
objsToBlit - = listInt . front ( ) ;
delete listInt . front ( ) ;
listInt . pop_front ( ) ;
}
2013-11-03 15:51:25 +03:00
if ( ! listInt . empty ( ) )
2011-12-17 21:59:59 +03:00
{
listInt . front ( ) - > activate ( ) ;
totalRedraw ( ) ;
}
fakeMouseMove ( ) ;
}
IShowActivatable * CGuiHandler : : topInt ( )
{
2013-11-03 15:51:25 +03:00
if ( listInt . empty ( ) )
2013-06-26 14:18:27 +03:00
return nullptr ;
2014-03-07 16:21:09 +03:00
else
2011-12-17 21:59:59 +03:00
return listInt . front ( ) ;
}
void CGuiHandler : : totalRedraw ( )
{
2013-06-29 16:05:48 +03:00
for ( auto & elem : objsToBlit )
elem - > showAll ( screen2 ) ;
2011-12-17 21:59:59 +03:00
blitAt ( screen2 , 0 , 0 , screen ) ;
}
void CGuiHandler : : updateTime ( )
{
2012-06-13 16:04:06 +03:00
int ms = mainFPSmng - > getElapsedMilliseconds ( ) ;
2011-12-17 21:59:59 +03:00
std : : list < CIntObject * > hlp = timeinterested ;
2013-06-29 16:05:48 +03:00
for ( auto & elem : hlp )
2011-12-17 21:59:59 +03:00
{
2013-06-29 16:05:48 +03:00
if ( ! vstd : : contains ( timeinterested , elem ) ) continue ;
( elem ) - > onTimer ( ms ) ;
2011-12-17 21:59:59 +03:00
}
}
void CGuiHandler : : handleEvents ( )
{
2014-06-21 11:13:19 +03:00
//player interface may want special event handling
2014-06-18 13:31:11 +03:00
if ( nullptr ! = LOCPLINT & & LOCPLINT - > capturedAllEvents ( ) )
return ;
boost : : unique_lock < boost : : mutex > lock ( eventsM ) ;
2014-06-18 07:30:23 +03:00
while ( ! events . empty ( ) )
2011-12-17 21:59:59 +03:00
{
2014-06-18 07:30:23 +03:00
SDL_Event ev = events . front ( ) ;
events . pop ( ) ;
2014-06-16 13:32:37 +03:00
this - > handleEvent ( & ev ) ;
2011-12-17 21:59:59 +03:00
}
}
void CGuiHandler : : handleEvent ( SDL_Event * sEvent )
{
current = sEvent ;
bool prev ;
if ( sEvent - > type = = SDL_KEYDOWN | | sEvent - > type = = SDL_KEYUP )
{
SDL_KeyboardEvent key = sEvent - > key ;
//translate numpad keys
if ( key . keysym . sym = = SDLK_KP_ENTER )
{
2015-06-21 00:38:05 +02:00
key . keysym . sym = SDLK_RETURN ;
2014-05-23 20:29:43 +03:00
key . keysym . scancode = SDL_SCANCODE_RETURN ;
2011-12-17 21:59:59 +03:00
}
bool keysCaptured = false ;
2013-06-29 16:05:48 +03:00
for ( auto i = keyinterested . begin ( ) ; i ! = keyinterested . end ( ) & & current ; i + + )
2011-12-17 21:59:59 +03:00
{
2012-03-11 19:29:01 +03:00
if ( ( * i ) - > captureThisEvent ( key ) )
2011-12-17 21:59:59 +03:00
{
keysCaptured = true ;
break ;
}
}
std : : list < CIntObject * > miCopy = keyinterested ;
2013-06-29 16:05:48 +03:00
for ( auto i = miCopy . begin ( ) ; i ! = miCopy . end ( ) & & current ; i + + )
2012-03-11 19:29:01 +03:00
if ( vstd : : contains ( keyinterested , * i ) & & ( ! keysCaptured | | ( * i ) - > captureThisEvent ( key ) ) )
2011-12-17 21:59:59 +03:00
( * * i ) . keyPressed ( key ) ;
}
else if ( sEvent - > type = = SDL_MOUSEMOTION )
{
CCS - > curh - > cursorMove ( sEvent - > motion . x , sEvent - > motion . y ) ;
handleMouseMotion ( sEvent ) ;
}
else if ( sEvent - > type = = SDL_MOUSEBUTTONDOWN )
{
if ( sEvent - > button . button = = SDL_BUTTON_LEFT )
{
if ( lastClick = = sEvent - > motion & & ( SDL_GetTicks ( ) - lastClickTime ) < 300 )
{
std : : list < CIntObject * > hlp = doubleClickInterested ;
2013-06-29 16:05:48 +03:00
for ( auto i = hlp . begin ( ) ; i ! = hlp . end ( ) & & current ; i + + )
2011-12-17 21:59:59 +03:00
{
if ( ! vstd : : contains ( doubleClickInterested , * i ) ) continue ;
if ( isItIn ( & ( * i ) - > pos , sEvent - > motion . x , sEvent - > motion . y ) )
{
( * i ) - > onDoubleClick ( ) ;
}
}
}
lastClick = sEvent - > motion ;
lastClickTime = SDL_GetTicks ( ) ;
std : : list < CIntObject * > hlp = lclickable ;
2013-06-29 16:05:48 +03:00
for ( auto i = hlp . begin ( ) ; i ! = hlp . end ( ) & & current ; i + + )
2011-12-17 21:59:59 +03:00
{
if ( ! vstd : : contains ( lclickable , * i ) ) continue ;
if ( isItIn ( & ( * i ) - > pos , sEvent - > motion . x , sEvent - > motion . y ) )
{
prev = ( * i ) - > pressedL ;
( * i ) - > pressedL = true ;
( * i ) - > clickLeft ( true , prev ) ;
}
}
}
else if ( sEvent - > button . button = = SDL_BUTTON_RIGHT )
{
std : : list < CIntObject * > hlp = rclickable ;
2013-06-29 16:05:48 +03:00
for ( auto i = hlp . begin ( ) ; i ! = hlp . end ( ) & & current ; i + + )
2011-12-17 21:59:59 +03:00
{
if ( ! vstd : : contains ( rclickable , * i ) ) continue ;
if ( isItIn ( & ( * i ) - > pos , sEvent - > motion . x , sEvent - > motion . y ) )
{
prev = ( * i ) - > pressedR ;
( * i ) - > pressedR = true ;
( * i ) - > clickRight ( true , prev ) ;
}
}
}
2014-05-21 19:04:34 +03:00
}
2014-05-24 16:52:43 +03:00
else if ( sEvent - > type = = SDL_MOUSEWHEEL )
2014-05-21 19:04:34 +03:00
{
std : : list < CIntObject * > hlp = wheelInterested ;
for ( auto i = hlp . begin ( ) ; i ! = hlp . end ( ) & & current ; i + + )
{
if ( ! vstd : : contains ( wheelInterested , * i ) ) continue ;
2015-08-22 04:47:54 +02:00
// SDL doesn't have the proper values for mouse positions on SDL_MOUSEWHEEL, refetch them
int x = 0 , y = 0 ;
SDL_GetMouseState ( & x , & y ) ;
( * i ) - > wheelScrolled ( sEvent - > wheel . y < 0 , isItIn ( & ( * i ) - > pos , x , y ) ) ;
}
2011-12-17 21:59:59 +03:00
}
2014-05-23 19:46:54 +03:00
else if ( sEvent - > type = = SDL_TEXTINPUT )
{
for ( auto it : textInterested )
{
it - > textInputed ( sEvent - > text ) ;
}
}
else if ( sEvent - > type = = SDL_TEXTEDITING )
{
for ( auto it : textInterested )
{
it - > textEdited ( sEvent - > edit ) ;
}
}
2014-07-03 11:26:15 +03:00
//todo: muiltitouch
2011-12-17 21:59:59 +03:00
else if ( ( sEvent - > type = = SDL_MOUSEBUTTONUP ) & & ( sEvent - > button . button = = SDL_BUTTON_LEFT ) )
{
std : : list < CIntObject * > hlp = lclickable ;
2013-06-29 16:05:48 +03:00
for ( auto i = hlp . begin ( ) ; i ! = hlp . end ( ) & & current ; i + + )
2011-12-17 21:59:59 +03:00
{
if ( ! vstd : : contains ( lclickable , * i ) ) continue ;
prev = ( * i ) - > pressedL ;
( * i ) - > pressedL = false ;
if ( isItIn ( & ( * i ) - > pos , sEvent - > motion . x , sEvent - > motion . y ) )
{
( * i ) - > clickLeft ( false , prev ) ;
}
else
( * i ) - > clickLeft ( boost : : logic : : indeterminate , prev ) ;
}
}
else if ( ( sEvent - > type = = SDL_MOUSEBUTTONUP ) & & ( sEvent - > button . button = = SDL_BUTTON_RIGHT ) )
{
std : : list < CIntObject * > hlp = rclickable ;
2013-06-29 16:05:48 +03:00
for ( auto i = hlp . begin ( ) ; i ! = hlp . end ( ) & & current ; i + + )
2011-12-17 21:59:59 +03:00
{
if ( ! vstd : : contains ( rclickable , * i ) ) continue ;
prev = ( * i ) - > pressedR ;
( * i ) - > pressedR = false ;
if ( isItIn ( & ( * i ) - > pos , sEvent - > motion . x , sEvent - > motion . y ) )
{
( * i ) - > clickRight ( false , prev ) ;
}
else
( * i ) - > clickRight ( boost : : logic : : indeterminate , prev ) ;
}
}
2013-06-26 14:18:27 +03:00
current = nullptr ;
2011-12-17 21:59:59 +03:00
} //event end
void CGuiHandler : : handleMouseMotion ( SDL_Event * sEvent )
{
//sending active, hovered hoverable objects hover() call
std : : vector < CIntObject * > hlp ;
2013-06-29 16:05:48 +03:00
for ( auto & elem : hoverable )
2011-12-17 21:59:59 +03:00
{
2013-06-29 16:05:48 +03:00
if ( isItIn ( & ( elem ) - > pos , sEvent - > motion . x , sEvent - > motion . y ) )
2011-12-17 21:59:59 +03:00
{
2013-06-29 16:05:48 +03:00
if ( ! ( elem ) - > hovered )
hlp . push_back ( ( elem ) ) ;
2011-12-17 21:59:59 +03:00
}
2013-06-29 16:05:48 +03:00
else if ( ( elem ) - > hovered )
2011-12-17 21:59:59 +03:00
{
2013-06-29 16:05:48 +03:00
( elem ) - > hover ( false ) ;
( elem ) - > hovered = false ;
2011-12-17 21:59:59 +03:00
}
}
2013-06-29 16:05:48 +03:00
for ( auto & elem : hlp )
2011-12-17 21:59:59 +03:00
{
2013-06-29 16:05:48 +03:00
elem - > hover ( true ) ;
elem - > hovered = true ;
2011-12-17 21:59:59 +03:00
}
handleMoveInterested ( sEvent - > motion ) ;
}
void CGuiHandler : : simpleRedraw ( )
{
//update only top interface and draw background
if ( objsToBlit . size ( ) > 1 )
blitAt ( screen2 , 0 , 0 , screen ) ; //blit background
objsToBlit . back ( ) - > show ( screen ) ; //blit active interface/window
}
2016-10-22 16:22:00 +02:00
void CGuiHandler : : handleMoveInterested ( const SDL_MouseMotionEvent & motion )
2014-03-07 16:21:09 +03:00
{
2011-12-17 21:59:59 +03:00
//sending active, MotionInterested objects mouseMoved() call
std : : list < CIntObject * > miCopy = motioninterested ;
2013-06-29 16:05:48 +03:00
for ( auto & elem : miCopy )
2011-12-17 21:59:59 +03:00
{
2013-06-29 16:05:48 +03:00
if ( ( elem ) - > strongInterest | | isItIn ( & ( elem ) - > pos , motion . x , motion . y ) )
2011-12-17 21:59:59 +03:00
{
2013-06-29 16:05:48 +03:00
( elem ) - > mouseMoved ( motion ) ;
2011-12-17 21:59:59 +03:00
}
}
}
void CGuiHandler : : fakeMouseMove ( )
{
SDL_Event evnt ;
2014-05-23 20:29:43 +03:00
SDL_MouseMotionEvent sme = { SDL_MOUSEMOTION , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 } ;
2011-12-17 21:59:59 +03:00
int x , y ;
2015-06-21 00:13:45 +02:00
2011-12-17 21:59:59 +03:00
sme . state = SDL_GetMouseState ( & x , & y ) ;
sme . x = x ;
sme . y = y ;
evnt . motion = sme ;
current = & evnt ;
handleMouseMotion ( & evnt ) ;
}
2014-06-01 18:31:37 +03:00
void CGuiHandler : : renderFrame ( )
2011-12-17 21:59:59 +03:00
{
2015-08-22 15:47:40 +02:00
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,
// 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 ( 15 ) ) ;
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 ( ) ;
2015-06-22 22:57:34 +02:00
if ( settings [ " general " ] [ " showfps " ] . Bool ( ) )
drawFPSCounter ( ) ;
2015-06-22 20:53:47 +02:00
2014-07-03 21:05:59 +03:00
// draw the mouse cursor and update the screen
CCS - > curh - > render ( ) ;
if ( 0 ! = SDL_RenderCopy ( mainRenderer , screenTexture , nullptr , nullptr ) )
logGlobal - > errorStream ( ) < < __FUNCTION__ < < " SDL_RenderCopy " < < SDL_GetError ( ) ;
2015-08-22 15:47:40 +02:00
SDL_RenderPresent ( mainRenderer ) ;
}
2015-06-22 20:53:47 +02:00
2014-07-03 21:05:59 +03:00
mainFPSmng - > framerateDelay ( ) ; // holds a constant FPS
2011-12-17 21:59:59 +03:00
}
2014-06-01 18:31:37 +03:00
2011-12-17 21:59:59 +03:00
CGuiHandler : : CGuiHandler ( )
: lastClick ( - 500 , - 500 )
{
2013-06-26 14:18:27 +03:00
curInt = nullptr ;
current = nullptr ;
statusbar = nullptr ;
2011-12-17 21:59:59 +03:00
// Creates the FPS manager and sets the framerate to 48 which is doubled the value of the original Heroes 3 FPS rate
2011-12-22 16:05:19 +03:00
mainFPSmng = new CFramerateManager ( 48 ) ;
2014-03-07 16:21:09 +03:00
//do not init CFramerateManager here --AVS
2015-06-22 20:53:47 +02:00
terminate_cond . set ( false ) ;
2011-12-17 21:59:59 +03:00
}
CGuiHandler : : ~ CGuiHandler ( )
{
delete mainFPSmng ;
}
void CGuiHandler : : breakEventHandling ( )
{
2013-06-26 14:18:27 +03:00
current = nullptr ;
2011-12-17 21:59:59 +03:00
}
void CGuiHandler : : drawFPSCounter ( )
{
const static SDL_Color yellow = { 255 , 255 , 0 , 0 } ;
static SDL_Rect overlay = { 0 , 0 , 64 , 32 } ;
Uint32 black = SDL_MapRGB ( screen - > format , 10 , 10 , 10 ) ;
SDL_FillRect ( screen , & overlay , black ) ;
std : : string fps = boost : : lexical_cast < std : : string > ( mainFPSmng - > fps ) ;
2012-12-19 20:24:53 +03:00
graphics - > fonts [ FONT_BIG ] - > renderTextLeft ( screen , fps , yellow , Point ( 10 , 10 ) ) ;
2011-12-17 21:59:59 +03:00
}
2016-10-22 16:22:00 +02:00
SDL_Keycode CGuiHandler : : arrowToNum ( SDL_Keycode key )
2011-12-17 21:59:59 +03:00
{
2014-05-21 19:04:34 +03:00
switch ( key )
{
case SDLK_DOWN :
return SDLK_KP_2 ;
case SDLK_UP :
return SDLK_KP_8 ;
case SDLK_LEFT :
return SDLK_KP_4 ;
case SDLK_RIGHT :
return SDLK_KP_6 ;
default :
2014-07-03 11:26:15 +03:00
throw std : : runtime_error ( " Wrong key! " ) ;
2014-05-21 19:04:34 +03:00
}
2011-12-17 21:59:59 +03:00
}
2015-06-21 00:38:05 +02:00
SDL_Keycode CGuiHandler : : numToDigit ( SDL_Keycode key )
2011-12-17 21:59:59 +03:00
{
# define REMOVE_KP(keyName) case SDLK_KP_ ## keyName : return SDLK_ ## keyName;
switch ( key )
{
2014-05-23 20:29:43 +03:00
REMOVE_KP ( 0 )
REMOVE_KP ( 1 )
REMOVE_KP ( 2 )
REMOVE_KP ( 3 )
REMOVE_KP ( 4 )
REMOVE_KP ( 5 )
REMOVE_KP ( 6 )
REMOVE_KP ( 7 )
REMOVE_KP ( 8 )
REMOVE_KP ( 9 )
2011-12-17 21:59:59 +03:00
REMOVE_KP ( PERIOD )
2014-05-23 20:29:43 +03:00
REMOVE_KP ( MINUS )
REMOVE_KP ( PLUS )
REMOVE_KP ( EQUALS )
2011-12-17 21:59:59 +03:00
case SDLK_KP_MULTIPLY :
return SDLK_ASTERISK ;
case SDLK_KP_DIVIDE :
return SDLK_SLASH ;
case SDLK_KP_ENTER :
return SDLK_RETURN ;
default :
return SDLK_UNKNOWN ;
}
# undef REMOVE_KP
}
2015-06-21 00:38:05 +02:00
bool CGuiHandler : : isNumKey ( SDL_Keycode key , bool number )
2011-12-17 21:59:59 +03:00
{
2014-05-21 19:04:34 +03:00
if ( number )
2014-05-23 20:29:43 +03:00
return key > = SDLK_KP_1 & & key < = SDLK_KP_0 ;
2014-05-21 19:04:34 +03:00
else
2014-05-23 20:29:43 +03:00
return ( key > = SDLK_KP_1 & & key < = SDLK_KP_0 ) | | key = = SDLK_KP_MINUS | | key = = SDLK_KP_PLUS | | key = = SDLK_KP_EQUALS ;
2011-12-17 21:59:59 +03:00
}
2015-06-21 00:38:05 +02:00
bool CGuiHandler : : isArrowKey ( SDL_Keycode key )
2011-12-17 21:59:59 +03:00
{
2014-05-23 20:29:43 +03:00
return key = = SDLK_UP | | key = = SDLK_DOWN | | key = = SDLK_LEFT | | key = = SDLK_RIGHT ;
2011-12-22 16:05:19 +03:00
}
2012-04-08 04:15:18 +03:00
bool CGuiHandler : : amIGuiThread ( )
{
return inGuiThread . get ( ) & & * inGuiThread ;
}
2011-12-22 16:05:19 +03:00
2012-09-11 17:25:19 +03:00
void CGuiHandler : : pushSDLEvent ( int type , int usercode )
{
SDL_Event event ;
event . type = type ;
event . user . code = usercode ; // not necessarily used
SDL_PushEvent ( & event ) ;
}
2011-12-22 16:05:19 +03:00
CFramerateManager : : CFramerateManager ( int rate )
{
this - > rate = rate ;
this - > rateticks = ( 1000.0 / rate ) ;
this - > fps = 0 ;
2015-06-23 00:08:25 +02:00
this - > accumulatedFrames = 0 ;
this - > accumulatedTime = 0 ;
2011-12-22 16:05:19 +03:00
}
void CFramerateManager : : init ( )
{
this - > lastticks = SDL_GetTicks ( ) ;
}
void CFramerateManager : : framerateDelay ( )
{
ui32 currentTicks = SDL_GetTicks ( ) ;
2012-06-13 16:04:06 +03:00
timeElapsed = currentTicks - lastticks ;
2015-06-23 00:08:25 +02:00
2011-12-22 16:05:19 +03:00
// FPS is higher than it should be, then wait some time
2012-06-13 16:04:06 +03:00
if ( timeElapsed < rateticks )
2011-12-22 16:05:19 +03:00
{
2012-06-13 16:04:06 +03:00
SDL_Delay ( ceil ( this - > rateticks ) - timeElapsed ) ;
2011-12-22 16:05:19 +03:00
}
2015-06-23 00:08:25 +02:00
accumulatedTime + = timeElapsed ;
accumulatedFrames + + ;
2011-12-22 16:05:19 +03:00
2015-06-23 00:08:25 +02:00
if ( accumulatedFrames > = 100 )
{
//about 2 second should be passed
fps = ceil ( 1000.0 / ( accumulatedTime / accumulatedFrames ) ) ;
accumulatedTime = 0 ;
accumulatedFrames = 0 ;
} ;
2012-06-13 16:04:06 +03:00
2015-06-23 00:08:25 +02:00
currentTicks = SDL_GetTicks ( ) ;
2013-08-09 20:37:41 +03:00
// 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)
timeElapsed = std : : min < ui32 > ( currentTicks - lastticks , 1000 ) ;
2015-06-23 00:08:25 +02:00
2012-06-13 16:04:06 +03:00
lastticks = SDL_GetTicks ( ) ;
2012-11-20 20:53:45 +03:00
}