Skip to content

[ZH] Implement the system time and simulation timer within InGameUI #1170

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions GeneralsMD/Code/GameEngine/Include/Common/GlobalData.h
Original file line number Diff line number Diff line change
Expand Up @@ -409,6 +409,10 @@ class GlobalData : public SubsystemInterface
Bool m_saveCameraInReplay;
Bool m_useCameraInReplay;

// TheSuperHackers @feature Mauller 21/06/2025 allow the system time and game time font size to be set, a size of zero disables them
Int m_systemTimeFontSize;
Int m_gameTimeFontSize;

Real m_shakeSubtleIntensity; ///< Intensity for shaking a camera with SHAKE_SUBTLE
Real m_shakeNormalIntensity; ///< Intensity for shaking a camera with SHAKE_NORMAL
Real m_shakeStrongIntensity; ///< Intensity for shaking a camera with SHAKE_STRONG
Expand Down
3 changes: 3 additions & 0 deletions GeneralsMD/Code/GameEngine/Include/Common/UserPreferences.h
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,9 @@ class OptionPreferences : public UserPreferences

Int getCampaignDifficulty(void);
void setCampaignDifficulty( Int diff );

Int getSystemTimeFontSize(void);
Int getGameTimeFontSize(void);
};

//-----------------------------------------------------------------------------
Expand Down
24 changes: 24 additions & 0 deletions GeneralsMD/Code/GameEngine/Include/GameClient/InGameUI.h
Original file line number Diff line number Diff line change
Expand Up @@ -382,6 +382,7 @@ friend class Drawable; // for selection/deselection transactions
virtual void toggleMessages( void ) { m_messagesOn = 1 - m_messagesOn; } ///< toggle messages on/off
virtual Bool isMessagesOn( void ) { return m_messagesOn; } ///< are the display messages on
void freeMessageResources( void ); ///< free resources for the ui messages
void freeCustomUiResources( void ); ///< free resources for custom ui elements
Color getMessageColor(Bool altColor) { return (altColor)?m_messageColor2:m_messageColor1; }

// interface for military style messages
Expand Down Expand Up @@ -466,6 +467,7 @@ friend class Drawable; // for selection/deselection transactions
virtual void preDraw( void ); ///< Logic which needs to occur before the UI renders
virtual void draw( void ) = 0; ///< Render the in-game user interface
virtual void postDraw( void ); ///< Logic which needs to occur after the UI renders
virtual void postWindowDraw( void ); ///< Logic which needs to occur after the WindowManager has repainted the menus

/// Ingame video playback
virtual void playMovie( const AsciiString& movieName );
Expand Down Expand Up @@ -578,6 +580,9 @@ friend class Drawable; // for selection/deselection transactions
virtual void updateIdleWorker( void );
virtual void resetIdleWorker( void );

void drawSystemTime();
void drawGameTime();

public:
void registerWindowLayout(WindowLayout *layout); // register a layout for updates
void unregisterWindowLayout(WindowLayout *layout); // stop updates for this layout
Expand Down Expand Up @@ -741,6 +746,25 @@ friend class Drawable; // for selection/deselection transactions
VideoBuffer* m_cameoVideoBuffer;///< video playback buffer
VideoStreamInterface* m_cameoVideoStream;///< Video stream;

// System Time
DisplayString * m_systemTimeString;
AsciiString m_systemTimeFont;
Int m_systemTimePointSize;
Bool m_systemTimeBold;
Coord2D m_systemTimePosition;
Color m_systemTimeColor;
Color m_systemTimeDropColor;

// Game Time
DisplayString * m_gameTimeString;
DisplayString * m_gameTimeFrameString;
AsciiString m_gameTimeFont;
Int m_gameTimePointSize;
Bool m_gameTimeBold;
Coord2D m_gameTimePosition;
Color m_gameTimeColor;
Color m_gameTimeDropColor;

// message data
UIMessage m_uiMessages[ MAX_UI_MESSAGES ];/**< messages to display to the user, the
array is organized with newer messages at
Expand Down
5 changes: 5 additions & 0 deletions GeneralsMD/Code/GameEngine/Source/Common/GlobalData.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -928,6 +928,8 @@ GlobalData::GlobalData()
m_saveCameraInReplay = FALSE;
m_useCameraInReplay = FALSE;

m_systemTimeFontSize = 8;
m_gameTimeFontSize = 8;

m_debugShowGraphicalFramerate = FALSE;

Expand Down Expand Up @@ -1196,6 +1198,9 @@ void GlobalData::parseGameDataDefinition( INI* ini )

TheWritableGlobalData->m_saveCameraInReplay = optionPref.saveCameraInReplays();
TheWritableGlobalData->m_useCameraInReplay = optionPref.useCameraInReplays();

TheWritableGlobalData->m_systemTimeFontSize = optionPref.getSystemTimeFontSize();
TheWritableGlobalData->m_gameTimeFontSize = optionPref.getGameTimeFontSize();

Int val=optionPref.getGammaValue();
//generate a value between 0.6 and 2.0.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -772,6 +772,34 @@ Real OptionPreferences::getMusicVolume(void)
return volume;
}

Int OptionPreferences::getSystemTimeFontSize(void)
{
OptionPreferences::const_iterator it = find("SystemTimeFontSize");
if (it == end())
return 8;

Int fontSize = atoi(it->second.str());
if (fontSize < 0)
{
fontSize = 0;
}
return fontSize;
}

Int OptionPreferences::getGameTimeFontSize(void)
{
OptionPreferences::const_iterator it = find("GameTimeFontSize");
if (it == end())
return 8;

Int fontSize = atoi(it->second.str());
if (fontSize < 0)
{
fontSize = 0;
}
return fontSize;
}

static OptionPreferences *pref = NULL;

static void setDefaults( void )
Expand Down Expand Up @@ -1262,6 +1290,26 @@ static void saveOptions( void )
}
}

//-------------------------------------------------------------------------------------------------
// Set System Time Font Size
val = TheWritableGlobalData->m_systemTimeFontSize; // TheSuperHackers @todo replace with options input when applicable
if (val)
{
AsciiString prefString;
prefString.format("%d", val);
(*pref)["SystemTimeFontSize"] = prefString;
}

//-------------------------------------------------------------------------------------------------
// Set Game Time Font Size
val = TheWritableGlobalData->m_gameTimeFontSize; // TheSuperHackers @todo replace with options input when applicable
if (val)
{
AsciiString prefString;
prefString.format("%d", val);
(*pref)["GameTimeFontSize"] = prefString;
}

//-------------------------------------------------------------------------------------------------
// Resolution
//
Expand Down
119 changes: 119 additions & 0 deletions GeneralsMD/Code/GameEngine/Source/GameClient/InGameUI.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -876,6 +876,19 @@ const FieldParse InGameUI::s_fieldParseTable[] =
{ "ClearMinesRadiusCursor", RadiusDecalTemplate::parseRadiusDecalTemplate, NULL, offsetof( InGameUI, m_radiusCursors[ RADIUSCURSOR_CLEARMINES] ) },
{ "AmbulanceRadiusCursor", RadiusDecalTemplate::parseRadiusDecalTemplate, NULL, offsetof( InGameUI, m_radiusCursors[ RADIUSCURSOR_AMBULANCE] ) },

// TheSuperHackers @info ui enhancement configuration
{ "SystemTimeFont", INI::parseAsciiString, NULL, offsetof( InGameUI, m_systemTimeFont ) },
{ "SystemTimeBold", INI::parseBool, NULL, offsetof( InGameUI, m_systemTimeBold ) },
{ "SystemTimePosition", INI::parseCoord2D, NULL, offsetof( InGameUI, m_systemTimePosition ) },
{ "SystemTimeColor", INI::parseColorInt, NULL, offsetof( InGameUI, m_systemTimeColor ) },
{ "SystemTimeDropColor", INI::parseColorInt, NULL, offsetof( InGameUI, m_systemTimeDropColor ) },

{ "GameTimeFont", INI::parseAsciiString, NULL, offsetof( InGameUI, m_gameTimeFont ) },
{ "GameTimeBold", INI::parseBool, NULL, offsetof( InGameUI, m_gameTimeBold ) },
{ "GameTimePosition", INI::parseCoord2D, NULL, offsetof( InGameUI, m_gameTimePosition ) },
{ "GameTimeColor", INI::parseColorInt, NULL, offsetof( InGameUI, m_gameTimeColor ) },
{ "GameTimeDropColor", INI::parseColorInt, NULL, offsetof( InGameUI, m_gameTimeDropColor ) },

{ NULL, NULL, NULL, 0 } // keep this last
};

Expand Down Expand Up @@ -1001,6 +1014,25 @@ InGameUI::InGameUI()
m_replayWindow = NULL;
m_messagesOn = TRUE;

m_systemTimeString = NULL;
m_systemTimeFont = "Tahoma";
m_systemTimePointSize = TheGlobalData->m_systemTimeFontSize;
m_systemTimeBold = TRUE;
m_systemTimePosition.x = 3; // TheSuperHackers @info relative to the left of the screen
m_systemTimePosition.y = -1;
m_systemTimeColor = GameMakeColor( 255, 255, 255, 255 );
m_systemTimeDropColor = GameMakeColor( 0, 0, 0, 255 );

m_gameTimeString = NULL;
m_gameTimeFrameString = NULL;
m_gameTimeFont = "Tahoma";
m_gameTimePointSize = TheGlobalData->m_gameTimeFontSize;
m_gameTimeBold = TRUE;
m_gameTimePosition.x = 3; // TheSuperHackers @info relative to the right of the screen
m_gameTimePosition.y = -1;
m_gameTimeColor = GameMakeColor( 255, 255, 255, 255 );
m_gameTimeDropColor = GameMakeColor( 0, 0, 0, 255 );

m_superweaponPosition.x = 0.7f;
m_superweaponPosition.y = 0.7f;
m_superweaponFlashDuration = 1.0f;
Expand Down Expand Up @@ -1082,6 +1114,9 @@ InGameUI::~InGameUI()
// delete the message resources
freeMessageResources();

// free custom ui strings
freeCustomUiResources();

// delete the array for the drawbles
delete [] m_placeIcon;
m_placeIcon = NULL;
Expand Down Expand Up @@ -1924,6 +1959,9 @@ void InGameUI::reset( void )
// free any message resources allocated
freeMessageResources();

// free custom ui strings
freeCustomUiResources();

Int i;
for (i=0; i<MAX_PLAYER_COUNT; ++i)
{
Expand Down Expand Up @@ -2009,6 +2047,16 @@ void InGameUI::freeMessageResources( void )

} // end freeMessageResources

void InGameUI::freeCustomUiResources( void )
{
TheDisplayStringManager->freeDisplayString(m_systemTimeString);
m_systemTimeString = NULL;
TheDisplayStringManager->freeDisplayString(m_gameTimeString);
m_gameTimeString = NULL;
TheDisplayStringManager->freeDisplayString(m_gameTimeFrameString);
m_gameTimeFrameString = NULL;
}

//-------------------------------------------------------------------------------------------------
/** Same as the unicode message method, but this takes an ascii string which is assumed
* to me a string manager label */
Expand Down Expand Up @@ -3459,6 +3507,22 @@ void InGameUI::disregardDrawable( Drawable *draw )

}

//-------------------------------------------------------------------------------------------------
/** This is called after the WindowManager has drawn the menus. */
//-------------------------------------------------------------------------------------------------
void InGameUI::postWindowDraw( void )
{
if (m_systemTimePointSize > 0)
{
drawSystemTime();
}

if ( (m_gameTimePointSize > 0) && !TheGameLogic->isInShellGame() && TheGameLogic->isInGame() )
{
drawGameTime();
}
}

//-------------------------------------------------------------------------------------------------
/** This is called after the UI has been drawn. */
//-------------------------------------------------------------------------------------------------
Expand Down Expand Up @@ -5718,4 +5782,59 @@ WindowMsgHandledType IdleWorkerSystem( GameWindow *window, UnsignedInt msg,

}

void InGameUI::drawSystemTime()
{
if (!m_systemTimeString) {
m_systemTimeString = TheDisplayStringManager->newDisplayString();
}

// current system time
SYSTEMTIME systemTime;
GetLocalTime( &systemTime );

UnicodeString TimeString;
TimeString.format(L"%2.2d:%2.2d:%2.2d", systemTime.wHour, systemTime.wMinute, systemTime.wSecond);
Int adjustedSystemTimeFontSize = TheGlobalLanguageData->adjustFontSize(m_systemTimePointSize);
GameFont* systemTimeFont = TheWindowManager->winFindFont(m_systemTimeFont, adjustedSystemTimeFontSize, m_systemTimeBold);
m_systemTimeString->setFont(systemTimeFont);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This setup is done every frame. This can be optimized by moving display string creation and setup to the constructor or init function. Can create a pair to freeCustomUiResources.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we want people to be able to change the font size dynamically from the options menu then it will need to be setup every frame.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The settings in the Options Menu are applied when pressing ACCEPT, which calls a function. In this function we will then be able to call

freeCustomUiResources();
createCustomUiResources();

or

refreshCustomUiResources();

to rescale the texts.

This would then also need to be done after the Display Resolution has changed.

m_systemTimeString->setText(TimeString);

m_systemTimeString->draw(m_systemTimePosition.x, m_systemTimePosition.y, m_systemTimeColor, m_systemTimeDropColor);
}

void InGameUI::drawGameTime()
{
if (!m_gameTimeString) {
m_gameTimeString = TheDisplayStringManager->newDisplayString();
}

if (!m_gameTimeFrameString) {
m_gameTimeFrameString = TheDisplayStringManager->newDisplayString();
}

Int currentFrame = TheGameLogic->getFrame();
Int gameSeconds = (Int) (SECONDS_PER_LOGICFRAME_REAL * currentFrame );
Int hours = gameSeconds / 60 / 60;
Int minutes = (gameSeconds / 60) % 60;
Int seconds = gameSeconds % 60;
Int frame = currentFrame % 30;

UnicodeString gameTimeString;
gameTimeString.format(L"%2.2d:%2.2d:%2.2d", hours, minutes, seconds);
Int adjustedGameTimeFontSize = TheGlobalLanguageData->adjustFontSize(m_gameTimePointSize);
GameFont* gameTimeFont = TheWindowManager->winFindFont(m_gameTimeFont, adjustedGameTimeFontSize, m_gameTimeBold);
m_gameTimeString->setFont(gameTimeFont);
m_gameTimeString->setText(gameTimeString);

UnicodeString gameTimeFrameString;
gameTimeFrameString.format(L".%2.2d", frame);
m_gameTimeFrameString->setFont(gameTimeFont);
m_gameTimeFrameString->setText(gameTimeFrameString);

// TheSuperHackers @info this implicitly offsets the game timer from the right instead of left of the screen
int horizontalTimerOffset = TheDisplay->getWidth() - (Int)m_gameTimePosition.x - m_gameTimeString->getWidth() - m_gameTimeFrameString->getWidth();
int horizontalFrameOffset = TheDisplay->getWidth() - (Int)m_gameTimePosition.x - m_gameTimeFrameString->getWidth();

m_gameTimeString->draw(horizontalTimerOffset, m_gameTimePosition.y, m_gameTimeColor, m_gameTimeDropColor);
m_gameTimeFrameString->draw(horizontalFrameOffset, m_gameTimePosition.y, GameMakeColor(180,180,180,255), m_gameTimeDropColor);
}
Original file line number Diff line number Diff line change
Expand Up @@ -437,6 +437,8 @@ void W3DInGameUI::draw( void )
postDraw();

TheWindowManager->winRepaint();

postWindowDraw();

#ifdef EXTENDED_STATS
}
Expand Down
Loading