GUIUtil.cpp 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466
  1. /*
  2. ** Command & Conquer Generals(tm)
  3. ** Copyright 2025 Electronic Arts Inc.
  4. **
  5. ** This program is free software: you can redistribute it and/or modify
  6. ** it under the terms of the GNU General Public License as published by
  7. ** the Free Software Foundation, either version 3 of the License, or
  8. ** (at your option) any later version.
  9. **
  10. ** This program is distributed in the hope that it will be useful,
  11. ** but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. ** GNU General Public License for more details.
  14. **
  15. ** You should have received a copy of the GNU General Public License
  16. ** along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. */
  18. ////////////////////////////////////////////////////////////////////////////////
  19. // //
  20. // (c) 2001-2003 Electronic Arts Inc. //
  21. // //
  22. ////////////////////////////////////////////////////////////////////////////////
  23. // FILE: GUIUtil.cpp //////////////////////////////////////////////////////
  24. // Author: Matthew D. Campbell, Sept 2002
  25. #include "PreRTS.h" // This must go first in EVERY cpp file int the GameEngine
  26. #include "GameNetwork/GUIUtil.h"
  27. #include "GameNetwork/NetworkDefs.h"
  28. #include "GameClient/GameWindowManager.h"
  29. #include "GameClient/MapUtil.h"
  30. #include "Common/NameKeyGenerator.h"
  31. #include "Common/MultiplayerSettings.h"
  32. #include "GameClient/GadgetListBox.h"
  33. #include "GameClient/GadgetComboBox.h"
  34. #include "GameClient/GadgetTextEntry.h"
  35. #include "GameClient/GadgetStaticText.h"
  36. #include "GameClient/GadgetPushButton.h"
  37. #include "GameClient/GameText.h"
  38. #include "GameNetwork/GameInfo.h"
  39. #include "Common/PlayerTemplate.h"
  40. #include "GameNetwork/LANAPICallbacks.h" // for acceptTrueColor, etc
  41. #ifdef _INTERNAL
  42. // for occasional debugging...
  43. //#pragma optimize("", off)
  44. //#pragma MESSAGE("************************************** WARNING, optimization disabled for debugging purposes")
  45. #endif
  46. // -----------------------------------------------------------------------------
  47. static Bool winInitialized = FALSE;
  48. void EnableSlotListUpdates( Bool val )
  49. {
  50. winInitialized = val;
  51. }
  52. Bool AreSlotListUpdatesEnabled( void )
  53. {
  54. return winInitialized;
  55. }
  56. // -----------------------------------------------------------------------------
  57. void EnableAcceptControls(Bool Enabled, GameInfo *myGame, GameWindow *comboPlayer[],
  58. GameWindow *comboColor[], GameWindow *comboPlayerTemplate[],
  59. GameWindow *comboTeam[], GameWindow *buttonAccept[], GameWindow *buttonStart,
  60. GameWindow *buttonMapStartPosition[], Int slotNum)
  61. {
  62. if(slotNum == -1 || slotNum >= MAX_SLOTS )
  63. slotNum = myGame->getLocalSlotNum();
  64. Bool isObserver = myGame->getConstSlot(slotNum)->getPlayerTemplate() == PLAYERTEMPLATE_OBSERVER;
  65. if( !myGame->amIHost() && (buttonStart != NULL) )
  66. buttonStart->winEnable(Enabled);
  67. if(comboColor[slotNum])
  68. {
  69. if (isObserver)
  70. {
  71. GadgetComboBoxHideList(comboColor[slotNum]);
  72. }
  73. comboColor[slotNum]->winEnable(Enabled && !isObserver);
  74. }
  75. if(comboPlayerTemplate[slotNum])
  76. comboPlayerTemplate[slotNum]->winEnable(Enabled);
  77. if(comboTeam[slotNum])
  78. {
  79. if (isObserver)
  80. {
  81. GadgetComboBoxHideList(comboTeam[slotNum]);
  82. }
  83. comboTeam[slotNum]->winEnable(Enabled && !isObserver);
  84. }
  85. Bool canChooseStartSpot = FALSE;
  86. if (!isObserver)
  87. canChooseStartSpot = TRUE;
  88. for (Int i=0; i<MAX_SLOTS && !canChooseStartSpot && myGame->amIHost(); ++i)
  89. {
  90. if (myGame->getConstSlot(i) && myGame->getConstSlot(i)->isAI())
  91. canChooseStartSpot = TRUE;
  92. }
  93. if (slotNum == myGame->getLocalSlotNum())
  94. {
  95. if (myGame->getConstSlot(myGame->getLocalSlotNum())->hasMap())
  96. {
  97. for (Int i=0; i<MAX_SLOTS; ++i)
  98. {
  99. if (buttonMapStartPosition[i])
  100. {
  101. buttonMapStartPosition[i]->winEnable(Enabled && canChooseStartSpot);
  102. }
  103. }
  104. }
  105. else
  106. {
  107. for (Int i=0; i<MAX_SLOTS; ++i)
  108. {
  109. if (buttonMapStartPosition[i])
  110. buttonMapStartPosition[i]->winEnable(FALSE);
  111. }
  112. }
  113. }
  114. }
  115. // -----------------------------------------------------------------------------
  116. void ShowUnderlyingGUIElements( Bool show, const char *layoutFilename, const char *parentName,
  117. const char **gadgetsToHide, const char **perPlayerGadgetsToHide )
  118. {
  119. AsciiString parentNameStr;
  120. parentNameStr.format("%s:%s", layoutFilename, parentName);
  121. NameKeyType parentID = NAMEKEY(parentNameStr);
  122. GameWindow *parent = TheWindowManager->winGetWindowFromId( NULL, parentID );
  123. if (!parent)
  124. {
  125. DEBUG_CRASH(("Window %s not found\n", parentNameStr.str()));
  126. return;
  127. }
  128. // hide some GUI elements of the screen underneath
  129. GameWindow *win;
  130. Int player;
  131. const char **text;
  132. text = gadgetsToHide;
  133. while (*text)
  134. {
  135. AsciiString gadgetName;
  136. gadgetName.format("%s:%s", layoutFilename, *text);
  137. win = TheWindowManager->winGetWindowFromId( parent, NAMEKEY(gadgetName) );
  138. //DEBUG_ASSERTCRASH(win, ("Cannot find %s to show/hide it", gadgetName.str()));
  139. if (win)
  140. {
  141. win->winHide( !show );
  142. }
  143. ++text;
  144. }
  145. text = perPlayerGadgetsToHide;
  146. while (*text)
  147. {
  148. for (player = 0; player < MAX_SLOTS; ++player)
  149. {
  150. AsciiString gadgetName;
  151. gadgetName.format("%s:%s%d", layoutFilename, *text, player);
  152. win = TheWindowManager->winGetWindowFromId( parent, NAMEKEY(gadgetName) );
  153. //DEBUG_ASSERTCRASH(win, ("Cannot find %s to show/hide it", gadgetName.str()));
  154. if (win)
  155. {
  156. win->winHide( !show );
  157. }
  158. }
  159. ++text;
  160. }
  161. }
  162. // -----------------------------------------------------------------------------
  163. void PopulateColorComboBox(Int comboBox, GameWindow *comboArray[], GameInfo *myGame, Bool isObserver)
  164. {
  165. Int numColors = TheMultiplayerSettings->getNumColors();
  166. UnicodeString colorName;
  167. std::vector<bool> availableColors;
  168. for (Int i = 0; i < numColors; i++)
  169. availableColors.push_back(true);
  170. for (i = 0; i < MAX_SLOTS; i++)
  171. {
  172. GameSlot *slot = myGame->getSlot(i);
  173. if( slot && (i != comboBox) && (slot->getColor() >= 0 )&& (slot->getColor() < numColors))
  174. {
  175. DEBUG_ASSERTCRASH(slot->getColor() >= 0,("We've tried to access array %d and that ain't good",slot->getColor()));
  176. availableColors[slot->getColor()] = false;
  177. }
  178. }
  179. Bool wasObserver = (GadgetComboBoxGetLength(comboArray[comboBox]) == 1);
  180. GadgetComboBoxReset(comboArray[comboBox]);
  181. MultiplayerColorDefinition *def = TheMultiplayerSettings->getColor(PLAYERTEMPLATE_RANDOM);
  182. Int newIndex = GadgetComboBoxAddEntry(comboArray[comboBox],
  183. (isObserver)?TheGameText->fetch("GUI:None"):TheGameText->fetch("GUI:???"), def->getColor());
  184. GadgetComboBoxSetItemData(comboArray[comboBox], newIndex, (void *)-1);
  185. if (isObserver)
  186. {
  187. GadgetComboBoxSetSelectedPos(comboArray[comboBox], 0);
  188. return;
  189. }
  190. for (Int c=0; c<numColors; ++c)
  191. {
  192. def = TheMultiplayerSettings->getColor(c);
  193. if (!def || availableColors[c] == false)
  194. continue;
  195. colorName = TheGameText->fetch(def->getTooltipName().str());
  196. newIndex = GadgetComboBoxAddEntry(comboArray[comboBox], colorName, def->getColor());
  197. GadgetComboBoxSetItemData(comboArray[comboBox], newIndex, (void *)c);
  198. }
  199. if (wasObserver)
  200. GadgetComboBoxSetSelectedPos(comboArray[comboBox], 0);
  201. }
  202. // -----------------------------------------------------------------------------
  203. void PopulatePlayerTemplateComboBox(Int comboBox, GameWindow *comboArray[], GameInfo *myGame, Bool allowObservers)
  204. {
  205. Int numPlayerTemplates = ThePlayerTemplateStore->getPlayerTemplateCount();
  206. UnicodeString playerTemplateName;
  207. GadgetComboBoxReset(comboArray[comboBox]);
  208. MultiplayerColorDefinition *def = TheMultiplayerSettings->getColor(PLAYERTEMPLATE_RANDOM);
  209. Int newIndex = GadgetComboBoxAddEntry(comboArray[comboBox], TheGameText->fetch("GUI:Random"), def->getColor());
  210. GadgetComboBoxSetItemData(comboArray[comboBox], newIndex, (void *)PLAYERTEMPLATE_RANDOM);
  211. std::set<AsciiString> seenSides;
  212. for (Int c=0; c<numPlayerTemplates; ++c)
  213. {
  214. const PlayerTemplate *fac = ThePlayerTemplateStore->getNthPlayerTemplate(c);
  215. if (!fac)
  216. continue;
  217. if (fac->getStartingBuilding().isEmpty())
  218. continue;
  219. AsciiString side;
  220. side.format("SIDE:%s", fac->getSide().str());
  221. if (seenSides.find(side) != seenSides.end())
  222. continue;
  223. seenSides.insert(side);
  224. newIndex = GadgetComboBoxAddEntry(comboArray[comboBox], TheGameText->fetch(side), def->getColor());
  225. GadgetComboBoxSetItemData(comboArray[comboBox], newIndex, (void *)c);
  226. }
  227. seenSides.clear();
  228. // disabling observers for Multiplayer test
  229. #ifndef _PLAYTEST
  230. if (allowObservers)
  231. {
  232. def = TheMultiplayerSettings->getColor(PLAYERTEMPLATE_OBSERVER);
  233. newIndex = GadgetComboBoxAddEntry(comboArray[comboBox], TheGameText->fetch("GUI:Observer"), def->getColor());
  234. GadgetComboBoxSetItemData(comboArray[comboBox], newIndex, (void *)PLAYERTEMPLATE_OBSERVER);
  235. }
  236. #endif
  237. GadgetComboBoxSetSelectedPos(comboArray[comboBox], 0);
  238. }
  239. // -----------------------------------------------------------------------------
  240. void PopulateTeamComboBox(Int comboBox, GameWindow *comboArray[], GameInfo *myGame, Bool isObserver)
  241. {
  242. Int numTeams = MAX_SLOTS/2;
  243. UnicodeString teamName;
  244. GadgetComboBoxReset(comboArray[comboBox]);
  245. MultiplayerColorDefinition *def = TheMultiplayerSettings->getColor(PLAYERTEMPLATE_RANDOM);
  246. Int newIndex = GadgetComboBoxAddEntry(comboArray[comboBox], TheGameText->fetch("Team:0"), def->getColor());
  247. GadgetComboBoxSetItemData(comboArray[comboBox], newIndex, (void *)-1);
  248. if (isObserver)
  249. {
  250. GadgetComboBoxSetSelectedPos(comboArray[comboBox], 0);
  251. return;
  252. }
  253. for (Int c=0; c<numTeams; ++c)
  254. {
  255. AsciiString teamStr;
  256. teamStr.format("Team:%d", c + 1);
  257. teamName = TheGameText->fetch(teamStr.str());
  258. newIndex = GadgetComboBoxAddEntry(comboArray[comboBox], teamName, def->getColor());
  259. GadgetComboBoxSetItemData(comboArray[comboBox], newIndex, (void *)c);
  260. }
  261. GadgetComboBoxSetSelectedPos(comboArray[comboBox], 0);
  262. }
  263. // -----------------------------------------------------------------------------
  264. // -----------------------------------------------------------------------------------------
  265. // The slot list displaying function
  266. //-------------------------------------------------------------------------------------------------
  267. void UpdateSlotList( GameInfo *myGame, GameWindow *comboPlayer[],
  268. GameWindow *comboColor[], GameWindow *comboPlayerTemplate[],
  269. GameWindow *comboTeam[], GameWindow *buttonAccept[],
  270. GameWindow *buttonStart, GameWindow *buttonMapStartPosition[] )
  271. {
  272. if(!AreSlotListUpdatesEnabled())
  273. return;
  274. //LANGameInfo *myGame = TheLAN->GetMyGame();
  275. const MapMetaData *mapData = TheMapCache->findMap( myGame->getMap() );
  276. Bool willTransfer = TRUE;
  277. if (mapData)
  278. {
  279. willTransfer = !mapData->m_isOfficial;
  280. }
  281. else
  282. {
  283. willTransfer = WouldMapTransfer(myGame->getMap());
  284. }
  285. if (myGame)
  286. {
  287. for( int i =0; i < MAX_SLOTS; i++ )
  288. {
  289. GameSlot * slot = myGame->getSlot(i);
  290. // if i'm host, enable the controls for AI
  291. if(myGame->amIHost() && slot && slot->isAI())
  292. {
  293. EnableAcceptControls(TRUE, myGame, comboPlayer, comboColor, comboPlayerTemplate,
  294. comboTeam, buttonAccept, buttonStart, buttonMapStartPosition, i);
  295. }
  296. else if (slot && myGame->getLocalSlotNum() == i)
  297. {
  298. if(slot->isAccepted() && !myGame->amIHost())
  299. {
  300. EnableAcceptControls(FALSE, myGame, comboPlayer, comboColor, comboPlayerTemplate,
  301. comboTeam, buttonAccept, buttonStart, buttonMapStartPosition);
  302. }
  303. else
  304. {
  305. if (slot->hasMap()) {
  306. EnableAcceptControls(TRUE, myGame, comboPlayer, comboColor, comboPlayerTemplate,
  307. comboTeam, buttonAccept, buttonStart, buttonMapStartPosition);
  308. }
  309. else
  310. {
  311. EnableAcceptControls(willTransfer, myGame, comboPlayer, comboColor, comboPlayerTemplate,
  312. comboTeam, buttonAccept, buttonStart, buttonMapStartPosition);
  313. }
  314. }
  315. }
  316. else if(myGame->amIHost())
  317. {
  318. EnableAcceptControls(FALSE, myGame, comboPlayer, comboColor, comboPlayerTemplate,
  319. comboTeam, buttonAccept, buttonStart, buttonMapStartPosition, i);
  320. }
  321. if(slot && slot->isHuman())
  322. {
  323. UnicodeString newName = slot->getName();
  324. UnicodeString oldName = GadgetComboBoxGetText(comboPlayer[i]);
  325. if (comboPlayer[i] && newName.compare(oldName))
  326. {
  327. GadgetComboBoxSetText(comboPlayer[i], newName);
  328. }
  329. if(i!= 0 && buttonAccept && buttonAccept[i])
  330. {
  331. buttonAccept[i]->winHide(FALSE);
  332. //Color In the little accepted boxes
  333. if(slot->isAccepted())
  334. {
  335. if(BitTest(buttonAccept[i]->winGetStatus(), WIN_STATUS_IMAGE ))
  336. buttonAccept[i]->winEnable(TRUE);
  337. else
  338. GadgetButtonSetEnabledColor(buttonAccept[i], acceptTrueColor );
  339. }
  340. else
  341. {
  342. if(BitTest(buttonAccept[i]->winGetStatus(), WIN_STATUS_IMAGE ))
  343. buttonAccept[i]->winEnable(FALSE);
  344. else
  345. GadgetButtonSetEnabledColor(buttonAccept[i], acceptFalseColor );
  346. }
  347. }
  348. }
  349. else
  350. {
  351. GadgetComboBoxSetSelectedPos(comboPlayer[i], slot->getState(), TRUE);
  352. if( buttonAccept && buttonAccept[i] )
  353. buttonAccept[i]->winHide(TRUE);
  354. }
  355. /*
  356. if (myGame->getLocalSlotNum() == i && i!=0)
  357. {
  358. if (comboPlayer[i])
  359. comboPlayer[i]->winEnable( TRUE );
  360. }
  361. else*/ if (!myGame->amIHost())
  362. {
  363. if (comboPlayer[i])
  364. comboPlayer[i]->winEnable( FALSE );
  365. }
  366. //if( i == myGame->getLocalSlotNum())
  367. if((comboColor[i] != NULL) && BitTest(comboColor[i]->winGetStatus(), WIN_STATUS_ENABLED))
  368. PopulateColorComboBox(i, comboColor, myGame, myGame->getConstSlot(i)->getPlayerTemplate() == PLAYERTEMPLATE_OBSERVER);
  369. Int max, idx;
  370. if (comboColor[i] != NULL) {
  371. max = GadgetComboBoxGetLength(comboColor[i]);
  372. for (idx=0; idx<max; ++idx)
  373. {
  374. Int color = (Int)GadgetComboBoxGetItemData(comboColor[i], idx);
  375. if (color == slot->getColor())
  376. {
  377. GadgetComboBoxSetSelectedPos(comboColor[i], idx, TRUE);
  378. break;
  379. }
  380. }
  381. }
  382. if (comboTeam[i] != NULL) {
  383. max = GadgetComboBoxGetLength(comboTeam[i]);
  384. for (idx=0; idx<max; ++idx)
  385. {
  386. Int team = (Int)GadgetComboBoxGetItemData(comboTeam[i], idx);
  387. if (team == slot->getTeamNumber())
  388. {
  389. GadgetComboBoxSetSelectedPos(comboTeam[i], idx, TRUE);
  390. break;
  391. }
  392. }
  393. }
  394. if (comboPlayerTemplate[i] != NULL) {
  395. max = GadgetComboBoxGetLength(comboPlayerTemplate[i]);
  396. for (idx=0; idx<max; ++idx)
  397. {
  398. Int playerTemplate = (Int)GadgetComboBoxGetItemData(comboPlayerTemplate[i], idx);
  399. if (playerTemplate == slot->getPlayerTemplate())
  400. {
  401. GadgetComboBoxSetSelectedPos(comboPlayerTemplate[i], idx, TRUE);
  402. break;
  403. }
  404. }
  405. }
  406. }
  407. }
  408. }
  409. // -----------------------------------------------------------------------------