2017-07-13 10:26:03 +02:00
/*
* CGuiHandler . 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
*
*/
2011-12-17 21:59:59 +03:00
# pragma once
2023-02-02 16:22:19 +02:00
# include "MouseButton.h"
2023-01-18 15:50:52 +02:00
# include "../../lib/Point.h"
2023-02-02 16:22:19 +02:00
# include <SDL_keycode.h>
2011-12-17 21:59:59 +03:00
2022-07-26 15:07:42 +02:00
VCMI_LIB_NAMESPACE_BEGIN
template < typename T > struct CondSh ;
2023-02-02 16:15:39 +02:00
class Rect ;
2022-07-26 15:07:42 +02:00
VCMI_LIB_NAMESPACE_END
2023-01-17 22:01:35 +02:00
union SDL_Event ;
2023-01-30 19:55:32 +02:00
struct SDL_MouseMotionEvent ;
2023-01-17 22:01:35 +02:00
2011-12-22 16:05:19 +03:00
class CFramerateManager ;
2022-11-18 17:54:10 +02:00
class IStatusBar ;
2011-12-17 21:59:59 +03:00
class CIntObject ;
class IUpdateable ;
class IShowActivatable ;
class IShowable ;
2018-01-05 19:21:07 +02:00
// TODO: event handling need refactoring
2023-02-02 18:15:05 +02:00
enum class EUserEvent
2018-01-05 19:21:07 +02:00
{
/*CHANGE_SCREEN_RESOLUTION = 1,*/
RETURN_TO_MAIN_MENU = 2 ,
//STOP_CLIENT = 3,
RESTART_GAME = 4 ,
RETURN_TO_MENU_LOAD ,
FULLSCREEN_TOGGLED ,
CAMPAIGN_START_SCENARIO ,
FORCE_QUIT , //quit client without question
INTERFACE_CHANGED
} ;
2011-12-22 16:05:19 +03:00
// A fps manager which holds game updates at a constant rate
class CFramerateManager
{
private :
double rateticks ;
ui32 lastticks , timeElapsed ;
int rate ;
2015-06-23 00:08:25 +02:00
ui32 accumulatedTime , accumulatedFrames ;
2011-12-22 16:05:19 +03:00
public :
int fps ; // the actual fps value
CFramerateManager ( int rate ) ; // initializes the manager with a given fps rate
void init ( ) ; // needs to be called directly before the main game loop to reset the internal timer
void framerateDelay ( ) ; // needs to be called every game update cycle
2012-06-13 16:04:06 +03:00
ui32 getElapsedMilliseconds ( ) const { return this - > timeElapsed ; }
2022-06-05 15:20:01 +02:00
ui32 getFrameNumber ( ) const { return accumulatedFrames ; }
2011-12-22 16:05:19 +03:00
} ;
2011-12-17 21:59:59 +03:00
// Handles GUI logic and drawing
class CGuiHandler
{
public :
2011-12-22 16:05:19 +03:00
CFramerateManager * mainFPSmng ; //to keep const framerate
2018-07-25 00:36:48 +02:00
std : : list < std : : shared_ptr < IShowActivatable > > listInt ; //list of interfaces - front=foreground; back = background (includes adventure map, window interfaces, all kind of active dialogs, and so on)
2022-11-18 17:54:10 +02:00
std : : shared_ptr < IStatusBar > statusbar ;
2011-12-17 21:59:59 +03:00
2012-10-06 23:35:04 +03:00
private :
2023-01-27 00:27:06 +02:00
Point cursorPosition ;
2023-02-02 15:49:23 +02:00
uint32_t mouseButtonsMask ;
2023-01-27 00:27:06 +02:00
2018-07-25 00:36:48 +02:00
std : : vector < std : : shared_ptr < IShowActivatable > > disposed ;
2017-09-10 23:00:46 +02:00
std : : atomic < bool > continueEventHandling ;
2012-10-06 23:35:04 +03:00
typedef std : : list < CIntObject * > CIntObjectList ;
2016-11-27 16:48:18 +02:00
2011-12-17 21:59:59 +03:00
//active GUI elements (listening for events
2023-01-27 00:27:06 +02:00
CIntObjectList lclickable ;
CIntObjectList rclickable ;
CIntObjectList mclickable ;
CIntObjectList hoverable ;
CIntObjectList keyinterested ;
CIntObjectList motioninterested ;
CIntObjectList timeinterested ;
CIntObjectList wheelInterested ;
CIntObjectList doubleClickInterested ;
CIntObjectList textInterested ;
2015-06-21 00:17:44 +02:00
2016-11-27 16:48:18 +02:00
2023-02-02 16:22:19 +02:00
void handleMouseButtonClick ( CIntObjectList & interestedObjs , MouseButton btn , bool isPressed ) ;
2016-11-27 16:48:18 +02:00
void processLists ( const ui16 activityFlag , std : : function < void ( std : : list < CIntObject * > * ) > cb ) ;
2023-01-29 18:21:55 +02:00
void handleCurrentEvent ( SDL_Event & current ) ;
2023-01-27 00:27:06 +02:00
void handleMouseMotion ( const SDL_Event & current ) ;
void handleMoveInterested ( const SDL_MouseMotionEvent & motion ) ;
2023-01-16 12:26:43 +02:00
void convertTouchToMouse ( SDL_Event * current ) ;
void fakeMoveCursor ( float dx , float dy ) ;
void fakeMouseButtonEventRelativeMode ( bool down , bool right ) ;
2023-01-27 00:27:06 +02:00
2012-10-06 23:35:04 +03:00
public :
void handleElementActivate ( CIntObject * elem , ui16 activityFlag ) ;
void handleElementDeActivate ( CIntObject * elem , ui16 activityFlag ) ;
2016-11-27 16:48:18 +02:00
2012-10-06 23:35:04 +03:00
public :
2011-12-17 21:59:59 +03:00
//objs to blit
2018-07-25 00:36:48 +02:00
std : : vector < std : : shared_ptr < IShowActivatable > > objsToBlit ;
2011-12-17 21:59:59 +03:00
2023-02-02 15:49:23 +02:00
/// returns current position of mouse cursor, relative to vcmi window
2023-01-27 00:27:06 +02:00
const Point & getCursorPosition ( ) const ;
2023-02-02 15:49:23 +02:00
/// returns true if at least one mouse button is pressed
bool isMouseButtonPressed ( ) const ;
/// returns true if specified mouse button is pressed
bool isMouseButtonPressed ( MouseButton button ) const ;
2023-02-02 16:15:39 +02:00
/// returns true if chosen keyboard key is currently pressed down
bool isKeyboardAltDown ( ) const ;
bool isKeyboardCtrlDown ( ) const ;
bool isKeyboardShiftDown ( ) const ;
void startTextInput ( const Rect & where ) ;
void stopTextInput ( ) ;
/// moves mouse pointer into specified position inside vcmi window
void moveCursorToPosition ( const Point & position ) ;
2015-06-22 20:53:47 +02:00
IUpdateable * curInt ;
2011-12-17 21:59:59 +03:00
2011-12-22 16:05:19 +03:00
Point lastClick ;
2011-12-17 21:59:59 +03:00
unsigned lastClickTime ;
2023-01-17 12:04:57 +02:00
bool multifinger ;
2023-01-16 12:26:43 +02:00
bool isPointerRelativeMode ;
float pointerSpeedMultiplier ;
2011-12-17 21:59:59 +03:00
2016-11-27 16:48:18 +02:00
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
std : : list < CIntObject * > createdObj ; //stack of objs being created
2011-12-17 21:59:59 +03:00
CGuiHandler ( ) ;
~ CGuiHandler ( ) ;
2016-11-27 16:48:18 +02:00
2023-01-16 12:26:43 +02:00
void init ( ) ;
2014-06-01 18:31:37 +03:00
void renderFrame ( ) ;
2011-12-17 21:59:59 +03:00
void totalRedraw ( ) ; //forces total redraw (using showAll), sets a flag, method gets called at the end of the rendering
void simpleRedraw ( ) ; //update only top interface and draw background from buffer, sets a flag, method gets called at the end of the rendering
2018-07-25 00:36:48 +02:00
void pushInt ( std : : shared_ptr < IShowActivatable > newInt ) ; //deactivate old top interface, activates this one and pushes to the top
template < typename T , typename . . . Args >
void pushIntT ( Args & & . . . args )
{
auto newInt = std : : make_shared < T > ( std : : forward < Args > ( args ) . . . ) ;
pushInt ( newInt ) ;
}
2011-12-17 21:59:59 +03:00
void popInts ( int howMany ) ; //pops one or more interfaces - deactivates top, deletes and removes given number of interfaces, activates new front
2018-07-25 00:36:48 +02:00
void popInt ( std : : shared_ptr < IShowActivatable > top ) ; //removes given interface from the top and activates next
std : : shared_ptr < IShowActivatable > topInt ( ) ; //returns top interface
2011-12-17 21:59:59 +03:00
void updateTime ( ) ; //handles timeInterested
void handleEvents ( ) ; //takes events from queue and calls interested objects
void fakeMouseMove ( ) ;
void breakEventHandling ( ) ; //current event won't be propagated anymore
void drawFPSCounter ( ) ; // draws the FPS to the upper left corner of the screen
2012-09-15 22:16:16 +03:00
2015-06-21 00:38:05 +02:00
static SDL_Keycode arrowToNum ( SDL_Keycode key ) ; //converts arrow key to according numpad key
static SDL_Keycode numToDigit ( SDL_Keycode key ) ; //converts numpad digit key to normal digit key
static bool isNumKey ( SDL_Keycode key , bool number = true ) ; //checks if key is on numpad (numbers - check only for numpad digits)
static bool isArrowKey ( SDL_Keycode key ) ;
2012-04-08 04:15:18 +03:00
static bool amIGuiThread ( ) ;
2023-02-02 18:15:05 +02:00
static void pushUserEvent ( EUserEvent usercode ) ;
2023-02-02 18:35:01 +02:00
static void pushUserEvent ( EUserEvent usercode , void * userdata ) ;
2016-11-27 16:48:18 +02:00
2017-08-13 16:44:41 +02:00
CondSh < bool > * terminate_cond ; // confirm termination
2011-12-17 21:59:59 +03:00
} ;
extern CGuiHandler GH ; //global gui handler
struct SObjectConstruction
{
CIntObject * myObj ;
SObjectConstruction ( CIntObject * obj ) ;
~ SObjectConstruction ( ) ;
} ;
struct SSetCaptureState
{
bool previousCapture ;
ui8 prevActions ;
SSetCaptureState ( bool allow , ui8 actions ) ;
~ SSetCaptureState ( ) ;
} ;
# define OBJ_CONSTRUCTION SObjectConstruction obj__i(this)
2022-12-21 22:54:06 +02:00
# define OBJ_CONSTRUCTION_TARGETED(obj) SObjectConstruction obj__i(obj)
2017-11-14 09:50:04 +02:00
# define OBJECT_CONSTRUCTION_CAPTURING(actions) defActions = actions; SSetCaptureState obj__i1(true, actions); SObjectConstruction obj__i(this)
2018-04-07 13:34:11 +02:00
# define OBJECT_CONSTRUCTION_CUSTOM_CAPTURING(actions) SSetCaptureState obj__i1(true, actions); SObjectConstruction obj__i(this)
2018-01-05 19:21:07 +02:00
# define OBJ_CONSTRUCTION_CAPTURING_ALL_NO_DISPOSE defActions = 255 - DISPOSE; SSetCaptureState obj__i1(true, 255 - DISPOSE); SObjectConstruction obj__i(this)