2017-07-13 10:26:03 +02:00
/*
* 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
*
*/
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
# include "CIntObject.h"
2023-01-05 19:34:37 +02:00
# include "CursorHandler.h"
2023-04-27 19:21:06 +02:00
# include "ShortcutHandler.h"
2023-05-12 23:15:48 +02:00
# include "FramerateManager.h"
2023-05-16 14:10:26 +02:00
# include "WindowHandler.h"
2023-05-18 12:31:26 +02:00
# include "EventDispatcher.h"
2023-05-18 19:32:29 +02:00
# include "../eventsSDL/InputHandler.h"
2014-07-13 20:53:37 +03:00
# include "../CGameInfo.h"
2023-02-02 21:15:13 +02:00
# include "../render/Colors.h"
2023-07-31 18:50:55 +02:00
# include "../render/Graphics.h"
# include "../render/IFont.h"
# include "../render/EFont.h"
2023-05-08 12:22:01 +02:00
# include "../renderSDL/ScreenHandler.h"
2013-04-04 17:58:54 +03:00
# include "../CMT.h"
2014-05-23 22:39:10 +03:00
# include "../CPlayerInterface.h"
2022-12-09 13:38:46 +02:00
# include "../battle/BattleInterface.h"
2011-12-17 21:59:59 +03:00
2023-02-01 20:42:06 +02:00
# 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
2023-04-30 00:38:28 +02:00
CGuiHandler GH ;
2023-08-20 22:45:41 +02:00
static thread_local bool inGuiThread = false ;
2012-04-08 04:15:18 +03:00
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 ;
}
2023-01-16 12:26:43 +02:00
void CGuiHandler : : init ( )
{
2023-08-20 22:45:41 +02:00
inGuiThread = true ;
2023-05-18 19:32:29 +02:00
inputHandlerInstance = std : : make_unique < InputHandler > ( ) ;
2023-05-18 12:31:26 +02:00
eventDispatcherInstance = std : : make_unique < EventDispatcher > ( ) ;
2023-05-16 14:10:26 +02:00
windowHandlerInstance = std : : make_unique < WindowHandler > ( ) ;
2023-05-08 12:22:01 +02:00
screenHandlerInstance = std : : make_unique < ScreenHandler > ( ) ;
2023-04-28 13:22:03 +02:00
shortcutsHandlerInstance = std : : make_unique < ShortcutHandler > ( ) ;
2023-05-12 23:15:48 +02:00
framerateManagerInstance = std : : make_unique < FramerateManager > ( settings [ " video " ] [ " targetfps " ] . Integer ( ) ) ;
2023-01-16 12:26:43 +02:00
}
2011-12-17 21:59:59 +03:00
void CGuiHandler : : handleEvents ( )
{
2023-05-18 19:32:29 +02:00
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
2014-06-18 13:31:11 +03:00
if ( nullptr ! = LOCPLINT & & LOCPLINT - > capturedAllEvents ( ) )
return ;
2016-11-27 16:48:18 +02:00
2023-05-18 19:32:29 +02:00
input ( ) . processEvents ( ) ;
2023-01-16 12:26:43 +02:00
}
void CGuiHandler : : fakeMouseMove ( )
{
2023-06-26 20:51:10 +02:00
dispatchMainThread ( [ ] ( ) {
2023-08-10 20:19:12 +02:00
assert ( CPlayerInterface : : pim ) ;
boost : : unique_lock lock ( * CPlayerInterface : : pim ) ;
2023-06-26 20:51:10 +02:00
GH . events ( ) . dispatchMouseMoved ( Point ( 0 , 0 ) , GH . getCursorPosition ( ) ) ;
} ) ;
2023-01-16 12:26:43 +02:00
}
2023-02-02 16:15:39 +02:00
void CGuiHandler : : startTextInput ( const Rect & whereInput )
{
2023-05-18 19:32:29 +02:00
input ( ) . startTextInput ( whereInput ) ;
2023-02-02 16:15:39 +02:00
}
void CGuiHandler : : stopTextInput ( )
{
2023-05-18 19:32:29 +02:00
input ( ) . stopTextInput ( ) ;
2023-05-17 16:16:09 +02:00
}
2017-06-07 20:16:18 +02:00
2014-06-01 18:31:37 +03:00
void CGuiHandler : : renderFrame ( )
2011-12-17 21:59:59 +03: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,
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
2017-08-13 16:44:41 +02:00
while ( ! terminate_cond - > get ( ) & & ! ( acquiredTheLockOnPim = CPlayerInterface : : pim - > try_lock ( ) ) ) //try acquiring long until it succeeds or we are told to terminate
2023-08-20 22:45:41 +02:00
boost : : this_thread : : sleep_for ( boost : : chrono : : 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
2023-03-05 21:06:52 +02:00
if ( settings [ " video " ] [ " showfps " ] . Bool ( ) )
2016-11-27 16:48:18 +02:00
drawFPSCounter ( ) ;
2018-07-25 00:36:48 +02:00
SDL_UpdateTexture ( screenTexture , nullptr , screen - > pixels , screen - > pitch ) ;
2014-07-03 21:05:59 +03:00
2022-06-13 15:11:53 +02:00
SDL_RenderClear ( mainRenderer ) ;
2016-10-28 12:39:16 +02:00
SDL_RenderCopy ( mainRenderer , screenTexture , nullptr , nullptr ) ;
2014-07-03 21:05:59 +03:00
2018-07-25 00:36:48 +02:00
CCS - > curh - > render ( ) ;
2016-11-27 16:48:18 +02:00
SDL_RenderPresent ( mainRenderer ) ;
2018-07-25 00:36:48 +02:00
2023-05-16 14:10:26 +02:00
windows ( ) . onFrameRendered ( ) ;
2016-11-27 16:48:18 +02:00
}
2022-06-05 15:20:01 +02:00
2023-05-18 19:32:29 +02:00
framerate ( ) . framerateDelay ( ) ; // holds a constant FPS
2011-12-17 21:59:59 +03:00
}
CGuiHandler : : CGuiHandler ( )
2023-05-18 01:09:42 +02:00
: defActionsDef ( 0 )
2023-02-02 15:49:23 +02:00
, captureChildren ( false )
, curInt ( nullptr )
2023-05-16 17:34:23 +02:00
, fakeStatusBar ( std : : make_shared < EmptyStatusBar > ( ) )
2023-05-16 14:10:26 +02:00
, terminate_cond ( new CondSh < bool > ( false ) )
2011-12-17 21:59:59 +03:00
{
}
CGuiHandler : : ~ CGuiHandler ( )
{
2017-08-13 21:15:25 +02:00
delete terminate_cond ;
2011-12-17 21:59:59 +03:00
}
2023-05-18 19:32:29 +02:00
ShortcutHandler & CGuiHandler : : shortcuts ( )
2023-04-27 19:21:06 +02:00
{
2023-05-13 00:12:11 +02:00
assert ( shortcutsHandlerInstance ) ;
2023-04-28 13:22:03 +02:00
return * shortcutsHandlerInstance ;
2023-04-27 19:21:06 +02:00
}
2023-02-02 16:15:39 +02:00
2023-05-18 19:32:29 +02:00
FramerateManager & CGuiHandler : : framerate ( )
2023-05-12 23:15:48 +02:00
{
2023-05-13 00:12:11 +02:00
assert ( framerateManagerInstance ) ;
2023-05-12 23:15:48 +02:00
return * framerateManagerInstance ;
}
2023-02-02 16:15:39 +02:00
bool CGuiHandler : : isKeyboardCtrlDown ( ) const
{
2023-05-18 19:32:29 +02:00
return inputHandlerInstance - > isKeyboardCtrlDown ( ) ;
2023-02-02 16:15:39 +02:00
}
bool CGuiHandler : : isKeyboardAltDown ( ) const
{
2023-05-18 19:32:29 +02:00
return inputHandlerInstance - > isKeyboardAltDown ( ) ;
2023-02-02 16:15:39 +02:00
}
bool CGuiHandler : : isKeyboardShiftDown ( ) const
{
2023-05-18 19:32:29 +02:00
return inputHandlerInstance - > isKeyboardShiftDown ( ) ;
2023-02-02 16:15:39 +02:00
}
2023-01-27 00:27:06 +02:00
const Point & CGuiHandler : : getCursorPosition ( ) const
{
2023-05-18 19:32:29 +02:00
return inputHandlerInstance - > getCursorPosition ( ) ;
2023-01-27 00:27:06 +02:00
}
2023-02-03 18:23:53 +02:00
Point CGuiHandler : : screenDimensions ( ) const
{
2023-02-03 18:55:25 +02:00
return Point ( screen - > w , screen - > h ) ;
2023-02-03 18:23:53 +02:00
}
2011-12-17 21:59:59 +03:00
void CGuiHandler : : drawFPSCounter ( )
{
static SDL_Rect overlay = { 0 , 0 , 64 , 32 } ;
2023-01-30 19:55:32 +02:00
uint32_t black = SDL_MapRGB ( screen - > format , 10 , 10 , 10 ) ;
2011-12-17 21:59:59 +03:00
SDL_FillRect ( screen , & overlay , black ) ;
2023-05-18 19:32:29 +02:00
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 ) ) ;
2011-12-17 21:59:59 +03:00
}
2012-04-08 04:15:18 +03:00
bool CGuiHandler : : amIGuiThread ( )
{
2023-08-20 22:45:41 +02:00
return inGuiThread ;
2012-04-08 04:15:18 +03:00
}
2011-12-22 16:05:19 +03:00
2023-06-26 20:51:10 +02:00
void CGuiHandler : : dispatchMainThread ( const std : : function < void ( ) > & functor )
2023-02-02 18:35:01 +02:00
{
2023-06-26 20:51:10 +02:00
inputHandlerInstance - > dispatchMainThread ( functor ) ;
2012-09-11 17:25:19 +03:00
}
2023-05-08 12:22:01 +02:00
IScreenHandler & CGuiHandler : : screenHandler ( )
2023-04-30 00:03:50 +02:00
{
2023-05-08 12:22:01 +02:00
return * screenHandlerInstance ;
2023-04-30 00:03:50 +02:00
}
2023-05-18 19:32:29 +02:00
EventDispatcher & CGuiHandler : : events ( )
2023-05-17 22:22:45 +02:00
{
return * eventDispatcherInstance ;
}
2023-05-18 19:32:29 +02:00
InputHandler & CGuiHandler : : input ( )
{
return * inputHandlerInstance ;
}
2023-05-16 14:10:26 +02:00
WindowHandler & CGuiHandler : : windows ( )
2023-05-04 21:33:25 +02:00
{
2023-05-16 14:10:26 +02:00
assert ( windowHandlerInstance ) ;
return * windowHandlerInstance ;
}
2023-05-04 21:33:25 +02:00
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 ;
}
2023-05-16 14:10:26 +02:00
void CGuiHandler : : onScreenResize ( )
{
screenHandler ( ) . onScreenResize ( ) ;
windows ( ) . onScreenResize ( ) ;
2023-05-04 21:33:25 +02:00
}