/******************************************************************************/ /* UI<=>GAME MESSAGES *********************************************************/ /******************************************************************************/ #ifndef _H_LW_LIB_MESSAGES #define _H_LW_LIB_MESSAGES #include #include namespace lw { /*= VIEWS ====================================================================*/ /* Empty abstract class that serves as a base for game views */ class A_GameView { public: virtual ~A_GameView( ) = 0; }; M_ABSTRACT_POINTERS( GameView ); /* Abstract class for a view builder * * User interfaces need to access the game's data in order to display it. View * builders provide a way to do that; they are passed to the game's main loop * by the UI. Once set, they will be used to create and update view data. */ class A_ViewBuilder { public: virtual ~A_ViewBuilder( ) = 0; /* This method creates a view instance. It is called twice when the * builder is installed, in order to create a "double buffer" - one * view can be sent to the UI while the other is being updated. */ virtual OP_GameView createView( ) = 0; /* This method is responsible for updating a view instance. */ virtual void updateView( OP_GameView view ) = 0; }; M_ABSTRACT_POINTERS( ViewBuilder ); /*= GAME STATE ===============================================================*/ /* State of the main loop */ enum class E_GameState { NO_GAME , // No game loaded GAME_PAUSED , // Game is loaded but not running GAME_SLOW , // Game is running at slow speed GAME_NORMAL , // Game is running at normal speed GAME_FAST // Game is running at high speed }; M_LSHIFT_OP( T_StringBuilder , E_GameState ); /*= PROGRESS INFORMATION =====================================================*/ /* Progress information for long operations - part (main or sub) */ class T_ProgressInfoPart { private: T_String text_; uint32_t progress_; uint32_t total_; public: T_ProgressInfoPart( ) = delete; T_ProgressInfoPart( T_String text , uint32_t progress , uint32_t total ) noexcept; T_ProgressInfoPart( T_ProgressInfoPart&& other ) noexcept; T_ProgressInfoPart( T_ProgressInfoPart const& other ); T_String const& text( ) const noexcept; uint32_t progress( ) const noexcept; uint32_t total( ) const noexcept; }; /* Progress information for long operations - main */ class T_ProgressInfo { private: T_ProgressInfoPart main_; T_Optional< T_ProgressInfoPart > sub_; public: T_ProgressInfo( ) = delete; T_ProgressInfo( T_String text , uint32_t progress , uint32_t total ) noexcept; explicit T_ProgressInfo( T_ProgressInfoPart main ) noexcept; T_ProgressInfo( T_ProgressInfoPart main , T_ProgressInfoPart sub ) noexcept; T_ProgressInfo( T_ProgressInfoPart main , T_String sText , uint32_t sProgress , uint32_t sTotal ) noexcept; T_ProgressInfo( T_String text , uint32_t progress , uint32_t total , T_String sText , uint32_t sProgress , uint32_t sTotal ) noexcept; T_ProgressInfo( T_ProgressInfo&& other ) noexcept; T_ProgressInfo( T_ProgressInfo const& other ) = delete; T_ProgressInfoPart const& main( ) const noexcept; bool hasSub( ) const noexcept; T_ProgressInfoPart const& sub( ) const; }; M_CLASS_POINTERS( ProgressInfo ); /*= MESSAGES =================================================================*/ /* Types of messages sent by the UI to the game */ enum class E_GameUIMessage { /* Create a new game * Data: XXX */ NEW , /* Load an existing game * Data: uint32_t - game identifier */ LOAD , /* Save the current game * Data: none */ SAVE , /* Quit the current game * Data: none */ STOP , /* Quit current game (if any) the exit the main loop * Data: none */ QUIT , /* Abort the current operation * Data: none */ ABORT , /* Delete a saved game * Data: uint32_t - game identifier */ DELETE , /* Copy or rename a saved game * Data: XXX */ COPY_OR_RENAME , /* Set the current game's speed * Data: E_GameState (but NO_GAME will be ignored) */ SET_SPEED , /* Execute computation steps * Data: XXX */ STEPS , /* Set a view builder * Data: XXX */ SET_VIEW , /* Indicate that a view has been displayed * Data: T_String - identifier of the view */ VIEW_DISPLAYED , /* Send a query to the game * Data: XXX */ QUERY , /* Send a command to the game * Data: XXX */ COMMAND }; M_LSHIFT_OP( T_StringBuilder , E_GameUIMessage ); /*----------------------------------------------------------------------------*/ /* Types of messages sent by the main loop to the UI */ enum class E_GameLoopMessage { /* Main loop exiting * Data: none */ TERMINATED , /* Progress information * Data: T_ProgressInfo */ PROGRESS , /* Operation completed * Data: none */ DONE , /* State changed * Data: E_GameState */ STATE_CHANGED , /* Indicate that a view is available * Data: XXX */ VIEW_AVAILABLE , /* Query response * Data: XXX */ QUERY_RESPONSE , /* Command execution - success * Data: none */ COMMAND_OK , /* Command execution - syntax error * Data: XXX */ COMMAND_SYNTAX , /* Command execution - error * Data: XXX */ COMMAND_ERROR , }; M_LSHIFT_OP( T_StringBuilder , E_GameLoopMessage ); /*----------------------------------------------------------------------------*/ /* Types for message data */ using T_GameUIMessageData = T_Union< uint32_t , T_String , E_GameState >; using T_GameLoopMessageData = T_Union< T_ProgressInfo , E_GameState >; /*----------------------------------------------------------------------------*/ /* Message direction */ enum class E_MessageDirection { FROM_UI_TO_GAME , FROM_GAME_TO_UI }; /* Message class template, can be used for both directions */ template< E_MessageDirection Direction , typename EType = std::conditional_t< Direction == E_MessageDirection::FROM_UI_TO_GAME , E_GameUIMessage , E_GameLoopMessage > , typename DType = std::conditional_t< Direction == E_MessageDirection::FROM_UI_TO_GAME , T_GameUIMessageData , T_GameLoopMessageData > > class T_GameMessage { public: using T_Type = EType; using T_Data = DType; private: using T_Self_ = T_GameMessage< Direction >; T_Optional< T_Type > type_; T_Optional< T_Data > data_; public: constexpr T_GameMessage( ) noexcept; constexpr T_GameMessage( T_Type type ) noexcept; T_GameMessage( T_Type type , T_Data data ) noexcept; T_GameMessage( T_Self_ const& ) = delete; T_GameMessage( T_Self_&& other ) noexcept; T_Self_& operator =( T_Self_ const& ) = delete; T_Self_& operator =( T_Self_&& other ) noexcept; constexpr bool hasMessage( ) const noexcept; constexpr T_Type type( ) const noexcept; template< typename T > constexpr T const& data( ) const; }; /*----------------------------------------------------------------------------*/ using T_UIMessage = T_GameMessage< E_MessageDirection::FROM_UI_TO_GAME >; using T_LoopMessage = T_GameMessage< E_MessageDirection::FROM_GAME_TO_UI >; } // namespace lw #endif // _H_LW_LIB_MESSAGES #include