/* ** Command & Conquer Generals(tm) ** Copyright 2025 Electronic Arts Inc. ** ** This program is free software: you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by ** the Free Software Foundation, either version 3 of the License, or ** (at your option) any later version. ** ** This program is distributed in the hope that it will be useful, ** but WITHOUT ANY WARRANTY; without even the implied warranty of ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ** GNU General Public License for more details. ** ** You should have received a copy of the GNU General Public License ** along with this program. If not, see . */ //////////////////////////////////////////////////////////////////////////////// // // // (c) 2001-2003 Electronic Arts Inc. // // // //////////////////////////////////////////////////////////////////////////////// // FILE: GUIUtil.cpp ////////////////////////////////////////////////////// // Author: Matthew D. Campbell, Sept 2002 #include "PreRTS.h" // This must go first in EVERY cpp file int the GameEngine #include "GameNetwork/GUIUtil.h" #include "GameNetwork/NetworkDefs.h" #include "GameClient/GameWindowManager.h" #include "GameClient/MapUtil.h" #include "Common/NameKeyGenerator.h" #include "Common/MultiplayerSettings.h" #include "GameClient/GadgetListBox.h" #include "GameClient/GadgetComboBox.h" #include "GameClient/GadgetTextEntry.h" #include "GameClient/GadgetStaticText.h" #include "GameClient/GadgetPushButton.h" #include "GameClient/GameText.h" #include "GameNetwork/GameInfo.h" #include "Common/PlayerTemplate.h" #include "GameNetwork/LANAPICallbacks.h" // for acceptTrueColor, etc #ifdef _INTERNAL // for occasional debugging... //#pragma optimize("", off) //#pragma MESSAGE("************************************** WARNING, optimization disabled for debugging purposes") #endif // ----------------------------------------------------------------------------- static Bool winInitialized = FALSE; void EnableSlotListUpdates( Bool val ) { winInitialized = val; } Bool AreSlotListUpdatesEnabled( void ) { return winInitialized; } // ----------------------------------------------------------------------------- void EnableAcceptControls(Bool Enabled, GameInfo *myGame, GameWindow *comboPlayer[], GameWindow *comboColor[], GameWindow *comboPlayerTemplate[], GameWindow *comboTeam[], GameWindow *buttonAccept[], GameWindow *buttonStart, GameWindow *buttonMapStartPosition[], Int slotNum) { if(slotNum == -1 || slotNum >= MAX_SLOTS ) slotNum = myGame->getLocalSlotNum(); Bool isObserver = myGame->getConstSlot(slotNum)->getPlayerTemplate() == PLAYERTEMPLATE_OBSERVER; if( !myGame->amIHost() && (buttonStart != NULL) ) buttonStart->winEnable(Enabled); if(comboColor[slotNum]) { if (isObserver) { GadgetComboBoxHideList(comboColor[slotNum]); } comboColor[slotNum]->winEnable(Enabled && !isObserver); } if(comboPlayerTemplate[slotNum]) comboPlayerTemplate[slotNum]->winEnable(Enabled); if(comboTeam[slotNum]) { if (isObserver) { GadgetComboBoxHideList(comboTeam[slotNum]); } comboTeam[slotNum]->winEnable(Enabled && !isObserver); } Bool canChooseStartSpot = FALSE; if (!isObserver) canChooseStartSpot = TRUE; for (Int i=0; iamIHost(); ++i) { if (myGame->getConstSlot(i) && myGame->getConstSlot(i)->isAI()) canChooseStartSpot = TRUE; } if (slotNum == myGame->getLocalSlotNum()) { if (myGame->getConstSlot(myGame->getLocalSlotNum())->hasMap()) { for (Int i=0; iwinEnable(Enabled && canChooseStartSpot); } } } else { for (Int i=0; iwinEnable(FALSE); } } } } // ----------------------------------------------------------------------------- void ShowUnderlyingGUIElements( Bool show, const char *layoutFilename, const char *parentName, const char **gadgetsToHide, const char **perPlayerGadgetsToHide ) { AsciiString parentNameStr; parentNameStr.format("%s:%s", layoutFilename, parentName); NameKeyType parentID = NAMEKEY(parentNameStr); GameWindow *parent = TheWindowManager->winGetWindowFromId( NULL, parentID ); if (!parent) { DEBUG_CRASH(("Window %s not found\n", parentNameStr.str())); return; } // hide some GUI elements of the screen underneath GameWindow *win; Int player; const char **text; text = gadgetsToHide; while (*text) { AsciiString gadgetName; gadgetName.format("%s:%s", layoutFilename, *text); win = TheWindowManager->winGetWindowFromId( parent, NAMEKEY(gadgetName) ); //DEBUG_ASSERTCRASH(win, ("Cannot find %s to show/hide it", gadgetName.str())); if (win) { win->winHide( !show ); } ++text; } text = perPlayerGadgetsToHide; while (*text) { for (player = 0; player < MAX_SLOTS; ++player) { AsciiString gadgetName; gadgetName.format("%s:%s%d", layoutFilename, *text, player); win = TheWindowManager->winGetWindowFromId( parent, NAMEKEY(gadgetName) ); //DEBUG_ASSERTCRASH(win, ("Cannot find %s to show/hide it", gadgetName.str())); if (win) { win->winHide( !show ); } } ++text; } } // ----------------------------------------------------------------------------- void PopulateColorComboBox(Int comboBox, GameWindow *comboArray[], GameInfo *myGame, Bool isObserver) { Int numColors = TheMultiplayerSettings->getNumColors(); UnicodeString colorName; std::vector availableColors; for (Int i = 0; i < numColors; i++) availableColors.push_back(true); for (i = 0; i < MAX_SLOTS; i++) { GameSlot *slot = myGame->getSlot(i); if( slot && (i != comboBox) && (slot->getColor() >= 0 )&& (slot->getColor() < numColors)) { DEBUG_ASSERTCRASH(slot->getColor() >= 0,("We've tried to access array %d and that ain't good",slot->getColor())); availableColors[slot->getColor()] = false; } } Bool wasObserver = (GadgetComboBoxGetLength(comboArray[comboBox]) == 1); GadgetComboBoxReset(comboArray[comboBox]); MultiplayerColorDefinition *def = TheMultiplayerSettings->getColor(PLAYERTEMPLATE_RANDOM); Int newIndex = GadgetComboBoxAddEntry(comboArray[comboBox], (isObserver)?TheGameText->fetch("GUI:None"):TheGameText->fetch("GUI:???"), def->getColor()); GadgetComboBoxSetItemData(comboArray[comboBox], newIndex, (void *)-1); if (isObserver) { GadgetComboBoxSetSelectedPos(comboArray[comboBox], 0); return; } for (Int c=0; cgetColor(c); if (!def || availableColors[c] == false) continue; colorName = TheGameText->fetch(def->getTooltipName().str()); newIndex = GadgetComboBoxAddEntry(comboArray[comboBox], colorName, def->getColor()); GadgetComboBoxSetItemData(comboArray[comboBox], newIndex, (void *)c); } if (wasObserver) GadgetComboBoxSetSelectedPos(comboArray[comboBox], 0); } // ----------------------------------------------------------------------------- void PopulatePlayerTemplateComboBox(Int comboBox, GameWindow *comboArray[], GameInfo *myGame, Bool allowObservers) { Int numPlayerTemplates = ThePlayerTemplateStore->getPlayerTemplateCount(); UnicodeString playerTemplateName; GadgetComboBoxReset(comboArray[comboBox]); MultiplayerColorDefinition *def = TheMultiplayerSettings->getColor(PLAYERTEMPLATE_RANDOM); Int newIndex = GadgetComboBoxAddEntry(comboArray[comboBox], TheGameText->fetch("GUI:Random"), def->getColor()); GadgetComboBoxSetItemData(comboArray[comboBox], newIndex, (void *)PLAYERTEMPLATE_RANDOM); std::set seenSides; for (Int c=0; cgetNthPlayerTemplate(c); if (!fac) continue; if (fac->getStartingBuilding().isEmpty()) continue; AsciiString side; side.format("SIDE:%s", fac->getSide().str()); if (seenSides.find(side) != seenSides.end()) continue; seenSides.insert(side); newIndex = GadgetComboBoxAddEntry(comboArray[comboBox], TheGameText->fetch(side), def->getColor()); GadgetComboBoxSetItemData(comboArray[comboBox], newIndex, (void *)c); } seenSides.clear(); // disabling observers for Multiplayer test #ifndef _PLAYTEST if (allowObservers) { def = TheMultiplayerSettings->getColor(PLAYERTEMPLATE_OBSERVER); newIndex = GadgetComboBoxAddEntry(comboArray[comboBox], TheGameText->fetch("GUI:Observer"), def->getColor()); GadgetComboBoxSetItemData(comboArray[comboBox], newIndex, (void *)PLAYERTEMPLATE_OBSERVER); } #endif GadgetComboBoxSetSelectedPos(comboArray[comboBox], 0); } // ----------------------------------------------------------------------------- void PopulateTeamComboBox(Int comboBox, GameWindow *comboArray[], GameInfo *myGame, Bool isObserver) { Int numTeams = MAX_SLOTS/2; UnicodeString teamName; GadgetComboBoxReset(comboArray[comboBox]); MultiplayerColorDefinition *def = TheMultiplayerSettings->getColor(PLAYERTEMPLATE_RANDOM); Int newIndex = GadgetComboBoxAddEntry(comboArray[comboBox], TheGameText->fetch("Team:0"), def->getColor()); GadgetComboBoxSetItemData(comboArray[comboBox], newIndex, (void *)-1); if (isObserver) { GadgetComboBoxSetSelectedPos(comboArray[comboBox], 0); return; } for (Int c=0; cfetch(teamStr.str()); newIndex = GadgetComboBoxAddEntry(comboArray[comboBox], teamName, def->getColor()); GadgetComboBoxSetItemData(comboArray[comboBox], newIndex, (void *)c); } GadgetComboBoxSetSelectedPos(comboArray[comboBox], 0); } // ----------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------- // The slot list displaying function //------------------------------------------------------------------------------------------------- void UpdateSlotList( GameInfo *myGame, GameWindow *comboPlayer[], GameWindow *comboColor[], GameWindow *comboPlayerTemplate[], GameWindow *comboTeam[], GameWindow *buttonAccept[], GameWindow *buttonStart, GameWindow *buttonMapStartPosition[] ) { if(!AreSlotListUpdatesEnabled()) return; //LANGameInfo *myGame = TheLAN->GetMyGame(); const MapMetaData *mapData = TheMapCache->findMap( myGame->getMap() ); Bool willTransfer = TRUE; if (mapData) { willTransfer = !mapData->m_isOfficial; } else { willTransfer = WouldMapTransfer(myGame->getMap()); } if (myGame) { for( int i =0; i < MAX_SLOTS; i++ ) { GameSlot * slot = myGame->getSlot(i); // if i'm host, enable the controls for AI if(myGame->amIHost() && slot && slot->isAI()) { EnableAcceptControls(TRUE, myGame, comboPlayer, comboColor, comboPlayerTemplate, comboTeam, buttonAccept, buttonStart, buttonMapStartPosition, i); } else if (slot && myGame->getLocalSlotNum() == i) { if(slot->isAccepted() && !myGame->amIHost()) { EnableAcceptControls(FALSE, myGame, comboPlayer, comboColor, comboPlayerTemplate, comboTeam, buttonAccept, buttonStart, buttonMapStartPosition); } else { if (slot->hasMap()) { EnableAcceptControls(TRUE, myGame, comboPlayer, comboColor, comboPlayerTemplate, comboTeam, buttonAccept, buttonStart, buttonMapStartPosition); } else { EnableAcceptControls(willTransfer, myGame, comboPlayer, comboColor, comboPlayerTemplate, comboTeam, buttonAccept, buttonStart, buttonMapStartPosition); } } } else if(myGame->amIHost()) { EnableAcceptControls(FALSE, myGame, comboPlayer, comboColor, comboPlayerTemplate, comboTeam, buttonAccept, buttonStart, buttonMapStartPosition, i); } if(slot && slot->isHuman()) { UnicodeString newName = slot->getName(); UnicodeString oldName = GadgetComboBoxGetText(comboPlayer[i]); if (comboPlayer[i] && newName.compare(oldName)) { GadgetComboBoxSetText(comboPlayer[i], newName); } if(i!= 0 && buttonAccept && buttonAccept[i]) { buttonAccept[i]->winHide(FALSE); //Color In the little accepted boxes if(slot->isAccepted()) { if(BitTest(buttonAccept[i]->winGetStatus(), WIN_STATUS_IMAGE )) buttonAccept[i]->winEnable(TRUE); else GadgetButtonSetEnabledColor(buttonAccept[i], acceptTrueColor ); } else { if(BitTest(buttonAccept[i]->winGetStatus(), WIN_STATUS_IMAGE )) buttonAccept[i]->winEnable(FALSE); else GadgetButtonSetEnabledColor(buttonAccept[i], acceptFalseColor ); } } } else { GadgetComboBoxSetSelectedPos(comboPlayer[i], slot->getState(), TRUE); if( buttonAccept && buttonAccept[i] ) buttonAccept[i]->winHide(TRUE); } /* if (myGame->getLocalSlotNum() == i && i!=0) { if (comboPlayer[i]) comboPlayer[i]->winEnable( TRUE ); } else*/ if (!myGame->amIHost()) { if (comboPlayer[i]) comboPlayer[i]->winEnable( FALSE ); } //if( i == myGame->getLocalSlotNum()) if((comboColor[i] != NULL) && BitTest(comboColor[i]->winGetStatus(), WIN_STATUS_ENABLED)) PopulateColorComboBox(i, comboColor, myGame, myGame->getConstSlot(i)->getPlayerTemplate() == PLAYERTEMPLATE_OBSERVER); Int max, idx; if (comboColor[i] != NULL) { max = GadgetComboBoxGetLength(comboColor[i]); for (idx=0; idxgetColor()) { GadgetComboBoxSetSelectedPos(comboColor[i], idx, TRUE); break; } } } if (comboTeam[i] != NULL) { max = GadgetComboBoxGetLength(comboTeam[i]); for (idx=0; idxgetTeamNumber()) { GadgetComboBoxSetSelectedPos(comboTeam[i], idx, TRUE); break; } } } if (comboPlayerTemplate[i] != NULL) { max = GadgetComboBoxGetLength(comboPlayerTemplate[i]); for (idx=0; idxgetPlayerTemplate()) { GadgetComboBoxSetSelectedPos(comboPlayerTemplate[i], idx, TRUE); break; } } } } } } // -----------------------------------------------------------------------------