38 changes: 33 additions & 5 deletions src/loadsave.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,11 @@
static void displayLoadBanner(WIDGET *psWidget, UDWORD xOffset, UDWORD yOffset);
static void displayLoadSlot(WIDGET *psWidget, UDWORD xOffset, UDWORD yOffset);

struct LoadSaveDisplayLoadSlotCache {
std::string fullText;
WzText wzText;
};

static W_SCREEN *psRequestScreen; // Widget screen for requester
static bool mode;
static UDWORD chosenSlotId;
Expand All @@ -113,6 +118,12 @@ bool saveMidMission()
return bLoadSaveMode == SAVE_INGAME_MISSION;
}

void loadSaveScreenSizeDidChange(unsigned int oldWidth, unsigned int oldHeight, unsigned int newWidth, unsigned int newHeight)
{
if (psRequestScreen == nullptr) return;
psRequestScreen->screenSizeDidChange(oldWidth, oldHeight, newWidth, newHeight);
}

// ////////////////////////////////////////////////////////////////////////////
bool addLoadSave(LOADSAVE_MODE savemode, const char *title)
{
Expand Down Expand Up @@ -193,7 +204,9 @@ bool addLoadSave(LOADSAVE_MODE savemode, const char *title)
// and * the gaps, add the banner, and finally, the fudge factor ;)
IntFormAnimated *loadSaveForm = new IntFormAnimated(parent);
loadSaveForm->id = LOADSAVE_FORM;
loadSaveForm->setGeometry(LOADSAVE_X, LOADSAVE_Y, LOADSAVE_W, slotsInColumn * (LOADENTRY_H + LOADSAVE_HGAP) + LOADSAVE_BANNER_DEPTH + 20);
loadSaveForm->setCalcLayout(LAMBDA_CALCLAYOUT_SIMPLE({
psWidget->setGeometry(LOADSAVE_X, LOADSAVE_Y, LOADSAVE_W, slotsInColumn * (LOADENTRY_H + LOADSAVE_HGAP) + LOADSAVE_BANNER_DEPTH + 20);
}));

// Add Banner
W_FORMINIT sFormInit;
Expand Down Expand Up @@ -242,6 +255,12 @@ bool addLoadSave(LOADSAVE_MODE savemode, const char *title)
sButInit.width = LOADENTRY_W;
sButInit.height = LOADENTRY_H;
sButInit.pDisplay = displayLoadSlot;
sButInit.initPUserDataFunc = []() -> void * { return new LoadSaveDisplayLoadSlotCache(); };
sButInit.onDelete = [](WIDGET *psWidget) {
assert(psWidget->pUserData != nullptr);
delete static_cast<LoadSaveDisplayLoadSlotCache *>(psWidget->pUserData);
psWidget->pUserData = nullptr;
};

for (slotCount = 0; slotCount < totalslots; slotCount++)
{
Expand Down Expand Up @@ -645,6 +664,10 @@ static void displayLoadBanner(WIDGET *psWidget, UDWORD xOffset, UDWORD yOffset)
// ////////////////////////////////////////////////////////////////////////////
static void displayLoadSlot(WIDGET *psWidget, UDWORD xOffset, UDWORD yOffset)
{
// Any widget using displayLoadSlot must have its pUserData initialized to a (LoadSaveDisplayLoadSlotCache*)
assert(psWidget->pUserData != nullptr);
LoadSaveDisplayLoadSlotCache& cache = *static_cast<LoadSaveDisplayLoadSlotCache *>(psWidget->pUserData);

int x = xOffset + psWidget->x();
int y = yOffset + psWidget->y();
char butString[64];
Expand All @@ -655,13 +678,18 @@ static void displayLoadSlot(WIDGET *psWidget, UDWORD xOffset, UDWORD yOffset)
{
sstrcpy(butString, ((W_BUTTON *)psWidget)->pText.toUtf8().constData());

iV_SetTextColour(WZCOL_FORM_TEXT);
while (iV_GetTextWidth(butString, font_regular) > psWidget->width())
if (cache.fullText != butString)
{
butString[strlen(butString) - 1] = '\0';
// Update cache
while (iV_GetTextWidth(butString, font_regular) > psWidget->width())
{
butString[strlen(butString) - 1] = '\0';
}
cache.wzText.setText(butString, font_regular);
cache.fullText = butString;
}

iV_DrawText(butString, x + 4, y + 17, font_regular);
cache.wzText.render(x + 4, y + 17, WZCOL_FORM_TEXT);
}
}

Expand Down
2 changes: 2 additions & 0 deletions src/loadsave.h
Original file line number Diff line number Diff line change
Expand Up @@ -74,4 +74,6 @@ bool saveMidMission();

void deleteSaveGame(char *saveGameName);

void loadSaveScreenSizeDidChange(unsigned int oldWidth, unsigned int oldHeight, unsigned int newWidth, unsigned int newHeight);

#endif // __INCLUDED_SRC_LOADSAVE_H__
28 changes: 25 additions & 3 deletions src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -564,6 +564,15 @@ static void startGameLoop()
wzGrabMouse();
}

// Disable resizable windows if it's a multiplayer game
if (runningMultiplayer())
{
// This is because the main loop gets frozen while the window resizing / edge dragging occurs
// which effectively pauses the game, and pausing is otherwise disabled in multiplayer games.
// FIXME: Figure out a workaround?
wzSetWindowIsResizable(false);
}

// set a flag for the trigger/event system to indicate initialisation is complete
gameInitialised = true;

Expand Down Expand Up @@ -609,6 +618,13 @@ static void stopGameLoop()
wzReleaseMouse();
}

// Re-enable resizable windows
if (!wzIsFullscreen())
{
// FIXME: This is required because of the disabling in startGameLoop()
wzSetWindowIsResizable(true);
}

gameInitialised = false;
}

Expand Down Expand Up @@ -1024,6 +1040,10 @@ int realmain(int argc, char *argv[])
ssprintf(buf, "Video Mode %d x %d (%s)", w, h, war_getFullscreen() ? "fullscreen" : "window");
addDumpInfo(buf);

float horizScaleFactor, vertScaleFactor;
wzGetGameToRendererScaleFactor(&horizScaleFactor, &vertScaleFactor);
debug(LOG_WZ, "Game to Renderer Scale Factor (w x h): %f x %f", horizScaleFactor, vertScaleFactor);

debug(LOG_MAIN, "Final initialization");
if (!frameInitialise())
{
Expand All @@ -1037,8 +1057,10 @@ int realmain(int argc, char *argv[])
{
return EXIT_FAILURE;
}
war_SetWidth(pie_GetVideoBufferWidth());
war_SetHeight(pie_GetVideoBufferHeight());
unsigned int windowWidth = 0, windowHeight = 0;
wzGetWindowResolution(nullptr, &windowWidth, &windowHeight);
war_SetWidth(windowWidth);
war_SetHeight(windowHeight);

pie_SetFogStatus(false);
pie_ScreenFlip(CLEAR_BLACK);
Expand All @@ -1049,7 +1071,7 @@ int realmain(int argc, char *argv[])
pie_SetFogStatus(false);
pie_ScreenFlip(CLEAR_BLACK);

if (!systemInitialise())
if (!systemInitialise(horizScaleFactor, vertScaleFactor))
{
return EXIT_FAILURE;
}
Expand Down
36 changes: 32 additions & 4 deletions src/mission.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2207,7 +2207,11 @@ void intRemoveTransporterTimer()

static void intDisplayMissionBackDrop(WIDGET *psWidget, UDWORD xOffset, UDWORD yOffset)
{
scoreDataToScreen(psWidget);
// Any widget using intDisplayMissionBackDrop must have its pUserData initialized to a (ScoreDataToScreenCache*)
assert(psWidget->pUserData != nullptr);
ScoreDataToScreenCache& cache = *static_cast<ScoreDataToScreenCache *>(psWidget->pUserData);

scoreDataToScreen(psWidget, cache);
}

static void missionResetInGameState()
Expand Down Expand Up @@ -2248,18 +2252,30 @@ static bool _intAddMissionResult(bool result, bool bPlaySuccess, bool showBackDr
sFormInit.id = IDMISSIONRES_BACKFORM;
sFormInit.style = WFORM_PLAIN;
sFormInit.pDisplay = intDisplayMissionBackDrop;
sFormInit.pUserData = new ScoreDataToScreenCache();
sFormInit.onDelete = [](WIDGET *psWidget) {
assert(psWidget->pUserData != nullptr);
delete static_cast<ScoreDataToScreenCache *>(psWidget->pUserData);
psWidget->pUserData = nullptr;
};
W_FORM *missionResBackForm = widgAddForm(psWScreen, &sFormInit);
missionResBackForm->setGeometry(0 + D_W, 0 + D_H, 640, 480);
missionResBackForm->setCalcLayout(LAMBDA_CALCLAYOUT_SIMPLE({
psWidget->setGeometry(0 + D_W, 0 + D_H, 640, 480);
}));

// TITLE
IntFormAnimated *missionResTitle = new IntFormAnimated(missionResBackForm);
missionResTitle->id = IDMISSIONRES_TITLE;
missionResTitle->setGeometry(MISSIONRES_TITLE_X, MISSIONRES_TITLE_Y, MISSIONRES_TITLE_W, MISSIONRES_TITLE_H);
missionResTitle->setCalcLayout(LAMBDA_CALCLAYOUT_SIMPLE({
psWidget->setGeometry(MISSIONRES_TITLE_X, MISSIONRES_TITLE_Y, MISSIONRES_TITLE_W, MISSIONRES_TITLE_H);
}));

// add form
IntFormAnimated *missionResForm = new IntFormAnimated(missionResBackForm);
missionResForm->id = IDMISSIONRES_FORM;
missionResForm->setGeometry(MISSIONRES_X, MISSIONRES_Y, MISSIONRES_W, MISSIONRES_H);
missionResForm->setCalcLayout(LAMBDA_CALCLAYOUT_SIMPLE({
psWidget->setGeometry(MISSIONRES_X, MISSIONRES_Y, MISSIONRES_W, MISSIONRES_H);
}));

// description of success/fail
W_LABINIT sLabInit;
Expand Down Expand Up @@ -2296,6 +2312,12 @@ static bool _intAddMissionResult(bool result, bool bPlaySuccess, bool showBackDr
sButInit.width = MISSION_TEXT_W;
sButInit.height = MISSION_TEXT_H;
sButInit.pDisplay = displayTextOption;
sButInit.pUserData = new DisplayTextOptionCache();
sButInit.onDelete = [](WIDGET *psWidget) {
assert(psWidget->pUserData != nullptr);
delete static_cast<DisplayTextOptionCache *>(psWidget->pUserData);
psWidget->pUserData = nullptr;
};
//if won
if (result || bMultiPlayer)
{
Expand Down Expand Up @@ -2454,6 +2476,12 @@ void intProcessMissionResult(UDWORD id)
sButInit.width = MISSION_TEXT_W;
sButInit.height = MISSION_TEXT_H;
sButInit.pDisplay = displayTextOption;
sButInit.pUserData = new DisplayTextOptionCache();
sButInit.onDelete = [](WIDGET *psWidget) {
assert(psWidget->pUserData != nullptr);
delete static_cast<DisplayTextOptionCache *>(psWidget->pUserData);
psWidget->pUserData = nullptr;
};
sButInit.id = IDMISSIONRES_QUIT;
sButInit.x = MISSION_3_X;
sButInit.y = MISSION_3_Y;
Expand Down
172 changes: 136 additions & 36 deletions src/multiint.cpp

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions src/multiint.h
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,8 @@ void kickPlayer(uint32_t player_id, const char *reason, LOBBY_ERROR_TYPES type);
void addPlayerBox(bool); // players (mid) box
void loadMapPreview(bool hideInterface);

void multiOptionsScreenSizeDidChange(unsigned int oldWidth, unsigned int oldHeight, unsigned int newWidth, unsigned int newHeight);


// ////////////////////////////////////////////////////////////////
// CONNECTION SCREEN
Expand Down
36 changes: 31 additions & 5 deletions src/multijoin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,25 @@

static void resetMultiVisibility(UDWORD player);

// ////////////////////////////////////////////////////////////////////////////
// Local Variables

struct DisplayMultiJoiningStatusCache {
WzText wzMainProgressText;
WzText wzPlayerCountText;
std::vector<WzText> wzPlayerNameAndStatus;
};

DisplayMultiJoiningStatusCache textCache;

// ////////////////////////////////////////////////////////////////////////////
// Clear Local Display Caches

void clearDisplayMultiJoiningStatusCache()
{
textCache = DisplayMultiJoiningStatusCache();
}

// ////////////////////////////////////////////////////////////////////////////
// Wait For Players

Expand All @@ -92,9 +111,10 @@ bool intDisplayMultiJoiningStatus(UBYTE joinCount)
RenderWindowFrame(FRAME_NORMAL, x, y , w, h); // draw a wee blue box.

// display how far done..
iV_DrawText(_("Players Still Joining"),
x + (w / 2) - (iV_GetTextWidth(_("Players Still Joining"), font_regular) / 2),
y + (h / 2) - 8, font_regular);
textCache.wzMainProgressText.setText(_("Players Still Joining"), font_regular);
textCache.wzMainProgressText.render(x + (w / 2) - (textCache.wzMainProgressText.width() / 2),
y + (h / 2) - 8, WZCOL_TEXT_BRIGHT);

unsigned playerCount = 0; // Calculate what NetPlay.playercount should be, which is apparently only non-zero for the host.
for (unsigned player = 0; player < game.maxPlayers; ++player)
{
Expand All @@ -108,7 +128,8 @@ bool intDisplayMultiJoiningStatus(UBYTE joinCount)
return true;
}
sprintf(sTmp, "%d%%", PERCENT(playerCount - joinCount, playerCount));
iV_DrawText(sTmp , x + (w / 2) - 10, y + (h / 2) + 10, font_large);
textCache.wzPlayerCountText.setText(sTmp, font_large);
textCache.wzPlayerCountText.render(x + (w / 2) - 10, y + (h / 2) + 10, WZCOL_TEXT_BRIGHT);

int yStep = iV_GetTextLineSize(font_small);
int yPos = RET_Y - yStep * game.maxPlayers;
Expand All @@ -128,7 +149,12 @@ bool intDisplayMultiJoiningStatus(UBYTE joinCount)
}
if (status >= 0)
{
iV_DrawText((statusStrings[status] + getPlayerName(player)).c_str(), x + 5, yPos + yStep * NetPlay.players[player].position, font_small);
if (player >= textCache.wzPlayerNameAndStatus.size())
{
textCache.wzPlayerNameAndStatus.resize(player + 1);
}
textCache.wzPlayerNameAndStatus[player].setText((statusStrings[status] + getPlayerName(player)).c_str(), font_small);
textCache.wzPlayerNameAndStatus[player].render(x + 5, yPos + yStep * NetPlay.players[player].position, WZCOL_TEXT_BRIGHT);
}
}

Expand Down
1 change: 1 addition & 0 deletions src/multijoin.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@

#include "droiddef.h"

void clearDisplayMultiJoiningStatusCache(); // Call when bDisplayMultiJoiningStatus is set to 0
bool intDisplayMultiJoiningStatus(UBYTE joinCount);
void recvPlayerLeft(NETQUEUE queue);
bool MultiPlayerLeave(UDWORD playerIndex); // A player has left the game.
Expand Down
36 changes: 29 additions & 7 deletions src/multilimit.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,11 @@

static void displayStructureBar(WIDGET *psWidget, UDWORD xOffset, UDWORD yOffset);

struct DisplayStructureBarCache {
WzText wzNameText;
WzText wzLimitText;
};

// ////////////////////////////////////////////////////////////////////////////
static inline void freeLimitSet()
{
Expand Down Expand Up @@ -131,7 +136,9 @@ bool startLimitScreen()

IntFormAnimated *limitsForm = new IntFormAnimated(parent, false);
limitsForm->id = IDLIMITS;
limitsForm->setGeometry(LIMITSX, LIMITSY, LIMITSW, LIMITSH);
limitsForm->setCalcLayout(LAMBDA_CALCLAYOUT_SIMPLE({
psWidget->setGeometry(LIMITSX, LIMITSY, LIMITSW, LIMITSH);
}));

// return button.
addMultiBut(psWScreen, IDLIMITS, IDLIMITS_RETURN,
Expand All @@ -149,9 +156,13 @@ bool startLimitScreen()

// add tab form..
IntListTabWidget *limitsList = new IntListTabWidget(limitsForm);
limitsList->setChildSize(BARWIDTH, BARHEIGHT);
limitsList->setChildSpacing(5, 5);
limitsList->setGeometry(50, 10, BARWIDTH, 370);
limitsList->setCalcLayout(LAMBDA_CALCLAYOUT_SIMPLE({
IntListTabWidget *limitsList = static_cast<IntListTabWidget *>(psWidget);
assert(limitsList != nullptr);
limitsList->setChildSize(BARWIDTH, BARHEIGHT);
limitsList->setChildSpacing(5, 5);
limitsList->setGeometry(50, 10, BARWIDTH, 370);
}));

//Put the buttons on it
int limitsButtonId = IDLIMITS_ENTRIES_START;
Expand All @@ -164,6 +175,12 @@ bool startLimitScreen()
button->id = limitsButtonId;
button->displayFunction = displayStructureBar;
button->UserData = i;
button->pUserData = new DisplayStructureBarCache();
button->setOnDelete([](WIDGET *psWidget) {
assert(psWidget->pUserData != nullptr);
delete static_cast<DisplayStructureBarCache *>(psWidget->pUserData);
psWidget->pUserData = nullptr;
});
limitsList->addWidgetToLayout(button);
++limitsButtonId;

Expand Down Expand Up @@ -324,6 +341,10 @@ void applyLimitSet()

static void displayStructureBar(WIDGET *psWidget, UDWORD xOffset, UDWORD yOffset)
{
// Any widget using displayStructureBar must have its pUserData initialized to a (DisplayStructureBarCache*)
assert(psWidget->pUserData != nullptr);
DisplayStructureBarCache& cache = *static_cast<DisplayStructureBarCache *>(psWidget->pUserData);

int x = xOffset + psWidget->x();
int y = yOffset + psWidget->y();
int w = psWidget->width();
Expand Down Expand Up @@ -365,12 +386,13 @@ static void displayStructureBar(WIDGET *psWidget, UDWORD xOffset, UDWORD yOffset
pie_SetDepthBufferStatus(DEPTH_CMP_ALWAYS_WRT_ON);

// draw name
iV_SetTextColour(WZCOL_TEXT_BRIGHT);
iV_DrawText(_(getName(stat)), x + 80, y + psWidget->height() / 2 + 3, font_regular);
cache.wzNameText.setText(_(getName(stat)), font_regular);
cache.wzNameText.render(x + 80, y + psWidget->height() / 2 + 3, WZCOL_TEXT_BRIGHT);

// draw limit
ssprintf(str, "%d", ((W_SLIDER *)widgGetFromID(psWScreen, psWidget->id + 1))->pos);
iV_DrawText(str, x + 270, y + psWidget->height() / 2 + 3, font_regular);
cache.wzLimitText.setText(str, font_regular);
cache.wzLimitText.render(x + 270, y + psWidget->height() / 2 + 3, WZCOL_TEXT_BRIGHT);

return;
}
253 changes: 203 additions & 50 deletions src/multimenu.cpp

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions src/multimenu.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ bool intCloseMultiMenu();
void intCloseMultiMenuNoAnim();
bool intAddMultiMenu();

void multiMenuScreenSizeDidChange(unsigned int oldWidth, unsigned int oldHeight, unsigned int newWidth, unsigned int newHeight);

extern bool MultiMenuUp;

extern UDWORD current_numplayers;
Expand Down
2 changes: 2 additions & 0 deletions src/multiplay.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,7 @@ bool multiPlayerLoop()
if (keyPressed(KEY_ESC))// check for cancel
{
bDisplayMultiJoiningStatus = 0;
clearDisplayMultiJoiningStatusCache();
setWidgetsStatus(true);
setPlayerHasLost(true);
}
Expand All @@ -244,6 +245,7 @@ bool multiPlayerLoop()
if (bDisplayMultiJoiningStatus)
{
bDisplayMultiJoiningStatus = 0;
clearDisplayMultiJoiningStatusCache();
setWidgetsStatus(true);
}
if (!ingame.TimeEveryoneIsInGame)
Expand Down
33 changes: 22 additions & 11 deletions src/scores.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -271,7 +271,7 @@ void getAsciiTime(char *psText, unsigned time)
}
}

void scoreDataToScreen(WIDGET *psWidget)
void scoreDataToScreen(WIDGET *psWidget, ScoreDataToScreenCache& cache)
{
int index, x, y, width, height;
bool bMoreBars;
Expand All @@ -288,9 +288,12 @@ void scoreDataToScreen(WIDGET *psWidget)
pie_UniTransBoxFill(16 + D_W, MT_Y_POS - 16, pie_GetVideoBufferWidth() - D_W - 16, MT_Y_POS + 256 + 16, WZCOL_SCORE_BOX);
iV_Box(16 + D_W, MT_Y_POS - 16, pie_GetVideoBufferWidth() - D_W - 16, MT_Y_POS + 256 + 16, WZCOL_SCORE_BOX_BORDER);

iV_DrawText(_("Unit Losses"), LC_X + D_W, 80 + 16 + D_H, font_regular);
iV_DrawText(_("Structure Losses"), LC_X + D_W, 140 + 16 + D_H, font_regular);
iV_DrawText(_("Force Information"), LC_X + D_W, 200 + 16 + D_H, font_regular);
cache.wzLabelText_UnitLosses.setText(_("Unit Losses"), font_regular);
cache.wzLabelText_UnitLosses.render(LC_X + D_W, 80 + 16 + D_H, WZCOL_FORM_TEXT);
cache.wzLabelText_StructureLosses.setText(_("Structure Losses"), font_regular);
cache.wzLabelText_StructureLosses.render(LC_X + D_W, 140 + 16 + D_H, WZCOL_FORM_TEXT);
cache.wzLabelText_ForceInformation.setText(_("Force Information"), font_regular);
cache.wzLabelText_ForceInformation.render(LC_X + D_W, 200 + 16 + D_H, WZCOL_FORM_TEXT);

index = 0;
bMoreBars = true;
Expand Down Expand Up @@ -342,7 +345,12 @@ void scoreDataToScreen(WIDGET *psWidget)
}
/* Now render the text by the bar */
sprintf(text, getDescription((MR_STRING)infoBars[index].stringID), infoBars[index].number);
iV_DrawText(text, x + width + 16, y + 12, font_regular);
if (index >= cache.wzInfoBarText.size())
{
cache.wzInfoBarText.resize(index + 1);
}
cache.wzInfoBarText[index].setText(text, font_regular);
cache.wzInfoBarText[index].render(x + width + 16, y + 12, WZCOL_FORM_TEXT);

/* If we're beyond STAT_ROOKIE, then we're on rankings */
if (index >= STAT_GREEN && index <= STAT_ACE)
Expand All @@ -362,24 +370,27 @@ void scoreDataToScreen(WIDGET *psWidget)

/* Firstly, top of the screen, number of artefacts found */
sprintf(text, _("ARTIFACTS RECOVERED: %d"), missionData.artefactsFound);
iV_DrawText(text, (pie_GetVideoBufferWidth() - iV_GetTextWidth(text, font_regular)) / 2, 300 + D_H, font_regular);
cache.wzInfoText_ArtifactsFound.setText(text, font_regular);
cache.wzInfoText_ArtifactsFound.render((pie_GetVideoBufferWidth() - cache.wzInfoText_ArtifactsFound.width()) / 2, 300 + D_H, WZCOL_FORM_TEXT);

/* Get the mission result time in a string - and write it out */
getAsciiTime((char *)&text2, gameTime - missionData.missionStarted);
sprintf(text, _("Mission Time - %s"), text2);
iV_DrawText(text, (pie_GetVideoBufferWidth() - iV_GetTextWidth(text, font_regular)) / 2, 320 + D_H, font_regular);
cache.wzInfoText_MissionTime.setText(text, font_regular);
cache.wzInfoText_MissionTime.render((pie_GetVideoBufferWidth() - cache.wzInfoText_MissionTime.width()) / 2, 320 + D_H, WZCOL_FORM_TEXT);

/* Write out total game time so far */
getAsciiTime((char *)&text2, gameTime);
sprintf(text, _("Total Game Time - %s"), text2);
iV_DrawText(text, (pie_GetVideoBufferWidth() - iV_GetTextWidth(text, font_regular)) / 2, 340 + D_H, font_regular);
cache.wzInfoText_TotalGameTime.setText(text, font_regular);
cache.wzInfoText_TotalGameTime.render((pie_GetVideoBufferWidth() - cache.wzInfoText_TotalGameTime.width()) / 2, 340 + D_H, WZCOL_FORM_TEXT);
if (Cheated)
{
// A quick way to flash the text
((realTime / 250) % 2) ? iV_SetTextColour(WZCOL_RED) : iV_SetTextColour(WZCOL_YELLOW);
PIELIGHT cheatedTextColor = ((realTime / 250) % 2) ? WZCOL_RED : WZCOL_YELLOW;
sprintf(text, _("You cheated!"));
iV_DrawText(text, (pie_GetVideoBufferWidth() - iV_GetTextWidth(text, font_regular)) / 2, 360 + D_H, font_regular);
iV_SetTextColour(WZCOL_TEXT_BRIGHT);
cache.wzInfoText_Cheated.setText(text, font_regular);
cache.wzInfoText_Cheated.render((pie_GetVideoBufferWidth() - cache.wzInfoText_Cheated.width()) / 2, 360 + D_H, cheatedTextColor);
}
}

Expand Down
16 changes: 15 additions & 1 deletion src/scores.h
Original file line number Diff line number Diff line change
Expand Up @@ -89,10 +89,24 @@ enum
STAT_ACE
};

#include "lib/ivis_opengl/textdraw.h"
struct ScoreDataToScreenCache {
WzText wzLabelText_UnitLosses;
WzText wzLabelText_StructureLosses;
WzText wzLabelText_ForceInformation;

std::vector<WzText> wzInfoBarText;

WzText wzInfoText_ArtifactsFound;
WzText wzInfoText_MissionTime;
WzText wzInfoText_TotalGameTime;
WzText wzInfoText_Cheated;
};

bool scoreInitSystem();
void scoreUpdateVar(DATA_INDEX var);
void scoreDataToConsole();
void scoreDataToScreen(WIDGET *psWidget);
void scoreDataToScreen(WIDGET *psWidget, ScoreDataToScreenCache& cache);
void getAsciiTime(char *psText, unsigned time);
bool readScoreData(const char *fileName);
bool writeScoreData(const char *fileName);
Expand Down
22 changes: 15 additions & 7 deletions src/seqdisp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,9 @@ static SEQLIST aSeqList[MAX_SEQ_LIST];
static SDWORD currentSeq = -1;
static SDWORD currentPlaySeq = -1;

// local rendered text cache
static std::vector<WzText> wzCachedSeqText;

/***************************************************************************/
/*
* local ProtoTypes
Expand Down Expand Up @@ -340,17 +343,20 @@ bool seq_UpdateFullScreenVideo(int *pbClear)
if (((realTime >= currentText.startTime) && (realTime <= currentText.endTime)) ||
(aSeqList[currentPlaySeq].bSeqLoop)) //if its a looped video always draw the text
{
if (i >= wzCachedSeqText.size())
{
wzCachedSeqText.resize(i + 1);
}
if (bMoreThanOneSequenceLine)
{
currentText.x = 20 + D_W2;
}
iV_SetTextColour(WZCOL_GREY);
iV_DrawText(&(currentText.pText[0]), currentText.x - 1, currentText.y - 1, font_scaled);
iV_DrawText(&(currentText.pText[0]), currentText.x - 1, currentText.y + 1, font_scaled);
iV_DrawText(&(currentText.pText[0]), currentText.x - 1, currentText.y + 1, font_scaled);
iV_DrawText(&(currentText.pText[0]), currentText.x + 1, currentText.y + 1, font_scaled);
iV_SetTextColour(WZCOL_WHITE);
iV_DrawText(&(currentText.pText[0]), currentText.x, currentText.y, font_scaled);
wzCachedSeqText[i].setText(&(currentText.pText[0]), font_scaled);
wzCachedSeqText[i].render(currentText.x - 1, currentText.y - 1, WZCOL_GREY);
wzCachedSeqText[i].render(currentText.x - 1, currentText.y + 1, WZCOL_GREY);
wzCachedSeqText[i].render(currentText.x + 1, currentText.y - 1, WZCOL_GREY);
wzCachedSeqText[i].render(currentText.x + 1, currentText.y + 1, WZCOL_GREY);
wzCachedSeqText[i].render(currentText.x, currentText.y, WZCOL_WHITE);
}
}
}
Expand Down Expand Up @@ -391,6 +397,8 @@ bool seq_StopFullScreenVideo()

seq_Shutdown();

wzCachedSeqText.clear();

return true;
}

Expand Down
38 changes: 23 additions & 15 deletions src/transporter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,9 @@ bool intAddTransporter(DROID *psSelected, bool offWorld)

IntFormAnimated *transForm = new IntFormAnimated(parent, Animate); // Do not animate the opening, if the window was already open.
transForm->id = IDTRANS_FORM;
transForm->setGeometry(TRANS_X, TRANS_Y, TRANS_WIDTH, TRANS_HEIGHT);
transForm->setCalcLayout(LAMBDA_CALCLAYOUT_SIMPLE({
psWidget->setGeometry(TRANS_X, TRANS_Y, TRANS_WIDTH, TRANS_HEIGHT);
}));

/* Add the close button */
W_BUTINIT sButInit;
Expand Down Expand Up @@ -244,16 +246,17 @@ bool intAddTransporterContents()

IntFormAnimated *transContentForm = new IntFormAnimated(parent, Animate); // Do not animate the opening, if the window was already open.
transContentForm->id = IDTRANS_CONTENTFORM;
transContentForm->setGeometry(TRANSCONT_X, TRANSCONT_Y, TRANSCONT_WIDTH, TRANSCONT_HEIGHT);
transContentForm->setCalcLayout(LAMBDA_CALCLAYOUT_SIMPLE({
psWidget->setGeometry(TRANSCONT_X, TRANSCONT_Y, TRANSCONT_WIDTH, TRANSCONT_HEIGHT);
}));

/* Add the close button */
W_BUTINIT sButInit;
sButInit.formID = IDTRANS_CONTENTFORM;
sButInit.id = IDTRANS_CONTCLOSE;
sButInit.x = STAT_WIDTH - CLOSE_WIDTH;
sButInit.y = 0;
sButInit.width = CLOSE_WIDTH;
sButInit.height = CLOSE_HEIGHT;
sButInit.calcLayout = (LAMBDA_CALCLAYOUT_SIMPLE({
psWidget->setGeometry(STAT_WIDTH - CLOSE_WIDTH, 0, CLOSE_WIDTH, CLOSE_HEIGHT);
}));
sButInit.pTip = _("Close");
sButInit.pDisplay = intDisplayImageHilight;
sButInit.UserData = PACKDWORD_TRI(0, IMAGE_CLOSEHILIGHT , IMAGE_CLOSE);
Expand Down Expand Up @@ -522,16 +525,17 @@ bool intAddDroidsAvailForm()
/* Add the droids available form */
IntFormAnimated *transDroids = new IntFormAnimated(parent, Animate); // Do not animate the opening, if the window was already open.
transDroids->id = IDTRANS_DROIDS;
transDroids->setGeometry(TRANSDROID_X, TRANSDROID_Y, TRANSDROID_WIDTH, TRANSDROID_HEIGHT);
transDroids->setCalcLayout(LAMBDA_CALCLAYOUT_SIMPLE({
psWidget->setGeometry(TRANSDROID_X, TRANSDROID_Y, TRANSDROID_WIDTH, TRANSDROID_HEIGHT);
}));

/* Add the close button */
W_BUTINIT sButInit;
sButInit.formID = IDTRANS_DROIDS;
sButInit.id = IDTRANS_DROIDCLOSE;
sButInit.x = TRANSDROID_WIDTH - CLOSE_WIDTH;
sButInit.y = 0;
sButInit.width = CLOSE_WIDTH;
sButInit.height = CLOSE_HEIGHT;
sButInit.calcLayout = (LAMBDA_CALCLAYOUT_SIMPLE({
psWidget->setGeometry(TRANSDROID_WIDTH - CLOSE_WIDTH, 0, CLOSE_WIDTH, CLOSE_HEIGHT);
}));
sButInit.pTip = _("Close");
sButInit.pDisplay = intDisplayImageHilight;
sButInit.UserData = PACKDWORD_TRI(0, IMAGE_CLOSEHILIGHT , IMAGE_CLOSE);
Expand All @@ -543,10 +547,14 @@ bool intAddDroidsAvailForm()
//now add the tabbed droids available form
IntListTabWidget *droidList = new IntListTabWidget(transDroids);
droidList->id = IDTRANS_DROIDTAB;
droidList->setChildSize(OBJ_BUTWIDTH, OBJ_BUTHEIGHT);
droidList->setChildSpacing(OBJ_GAP, OBJ_GAP);
int droidListWidth = OBJ_BUTWIDTH * 2 + OBJ_GAP;
droidList->setGeometry((TRANSDROID_WIDTH - droidListWidth) / 2, AVAIL_STARTY + 15, droidListWidth, TRANSDROID_HEIGHT - (AVAIL_STARTY + 15));
droidList->setCalcLayout(LAMBDA_CALCLAYOUT_SIMPLE({
IntListTabWidget *droidList = static_cast<IntListTabWidget *>(psWidget);
assert(droidList != nullptr);
droidList->setChildSize(OBJ_BUTWIDTH, OBJ_BUTHEIGHT);
droidList->setChildSpacing(OBJ_GAP, OBJ_GAP);
int droidListWidth = OBJ_BUTWIDTH * 2 + OBJ_GAP;
droidList->setGeometry((TRANSDROID_WIDTH - droidListWidth) / 2, AVAIL_STARTY + 15, droidListWidth, TRANSDROID_HEIGHT - (AVAIL_STARTY + 15));
}));

/* Add the droids available buttons */
int nextButtonId = IDTRANS_DROIDSTART;
Expand Down
11 changes: 11 additions & 0 deletions src/warzoneconfig.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ struct WARZONE_GLOBALS
FMV_MODE FMVmode = FMV_FULLSCREEN;
UDWORD width = 1024;
UDWORD height = 768;
int displayScale = 100;
int screen = 0;
int8_t SPcolor = 0;
int MPcolour = -1;
Expand Down Expand Up @@ -133,6 +134,16 @@ bool war_GetVsync()
return warGlobs.vsync;
}

unsigned int war_GetDisplayScale()
{
return warGlobs.displayScale;
}

void war_SetDisplayScale(unsigned int scale)
{
warGlobs.displayScale = scale;
}

void war_SetWidth(UDWORD width)
{
warGlobs.width = width;
Expand Down
2 changes: 2 additions & 0 deletions src/warzoneconfig.h
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,8 @@ bool war_GetColouredCursor();
void war_SetColouredCursor(bool enabled);
void war_SetVsync(bool b);
bool war_GetVsync();
void war_SetDisplayScale(unsigned int scale);
unsigned int war_GetDisplayScale();
void war_SetWidth(UDWORD width);
UDWORD war_GetWidth();
void war_SetScreen(int screen);
Expand Down