corelib/include/ebcl/Messages.hh

282 lines
7 KiB
C++

/******************************************************************************/
/* UI<=>GAME MESSAGES *********************************************************/
/******************************************************************************/
#ifndef _H_LW_LIB_MESSAGES
#define _H_LW_LIB_MESSAGES
#include <lw/lib/Strings.hh>
#include <lw/lib/Types.hh>
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 <lw/lib/inline/Messages.hh>