WOLMapSelectMenu.cpp 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483
  1. /*
  2. ** Command & Conquer Generals Zero Hour(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: WOLMapSelectMenu.cpp ////////////////////////////////////////////////////////////////////////
  24. // Author: Matt Campbell, December 2001
  25. // Description: MapSelect menu window callbacks
  26. ///////////////////////////////////////////////////////////////////////////////////////////////////
  27. // INCLUDES ///////////////////////////////////////////////////////////////////////////////////////
  28. #include "PreRTS.h" // This must go first in EVERY cpp file int the GameEngine
  29. #include "Common/CustomMatchPreferences.h"
  30. #include "Common/GameEngine.h"
  31. #include "Common/MessageStream.h"
  32. #include "GameClient/WindowLayout.h"
  33. #include "GameClient/Gadget.h"
  34. #include "GameClient/GadgetRadioButton.h"
  35. #include "GameClient/Shell.h"
  36. #include "GameClient/GameWindowManager.h"
  37. #include "GameClient/GadgetListBox.h"
  38. #include "GameNetwork/GameSpy/PeerDefs.h"
  39. #include "GameNetwork/GameSpyOverlay.h"
  40. #include "GameClient/MapUtil.h"
  41. #include "GameNetwork/GUIUtil.h"
  42. #ifdef _INTERNAL
  43. // for occasional debugging...
  44. //#pragma optimize("", off)
  45. //#pragma MESSAGE("************************************** WARNING, optimization disabled for debugging purposes")
  46. #endif
  47. // PRIVATE DATA ///////////////////////////////////////////////////////////////////////////////////
  48. static NameKeyType buttonBack = NAMEKEY_INVALID;
  49. static NameKeyType buttonOK = NAMEKEY_INVALID;
  50. static NameKeyType listboxMap = NAMEKEY_INVALID;
  51. static GameWindow *parent = NULL;
  52. static Bool raiseMessageBoxes = FALSE;
  53. static GameWindow *winMapPreview = NULL;
  54. static NameKeyType winMapPreviewID = NAMEKEY_INVALID;
  55. static NameKeyType radioButtonSystemMapsID = NAMEKEY_INVALID;
  56. static NameKeyType radioButtonUserMapsID = NAMEKEY_INVALID;
  57. extern WindowLayout *WOLMapSelectLayout; ///< Map selection overlay
  58. static GameWindow *mapList = NULL;
  59. static GameWindow *buttonMapStartPosition[MAX_SLOTS] = {NULL,NULL,NULL,NULL,
  60. NULL,NULL,NULL,NULL };
  61. static NameKeyType buttonMapStartPositionID[MAX_SLOTS] = { NAMEKEY_INVALID,NAMEKEY_INVALID,
  62. NAMEKEY_INVALID,NAMEKEY_INVALID,
  63. NAMEKEY_INVALID,NAMEKEY_INVALID,
  64. NAMEKEY_INVALID,NAMEKEY_INVALID };
  65. static GameWindow *winMapWindow = NULL;
  66. static void NullifyControls(void)
  67. {
  68. parent = NULL;
  69. winMapPreview = NULL;
  70. mapList = NULL;
  71. for (Int i=0; i<MAX_SLOTS; ++i)
  72. {
  73. buttonMapStartPosition[i] = NULL;
  74. }
  75. }
  76. static const char *layoutFilename = "GameSpyGameOptionsMenu.wnd";
  77. static const char *parentName = "GameSpyGameOptionsMenuParent";
  78. static const char *gadgetsToHide[] =
  79. {
  80. "MapWindow",
  81. //"StaticTextGameName",
  82. "StaticTextTeam",
  83. "StaticTextFaction",
  84. "StaticTextColor",
  85. "TextEntryMapDisplay",
  86. "ButtonSelectMap",
  87. "ButtonStart",
  88. "StaticTextMapPreview",
  89. NULL // keep this last
  90. };
  91. static const char *perPlayerGadgetsToHide[] =
  92. {
  93. "ComboBoxTeam",
  94. "ComboBoxColor",
  95. "ComboBoxPlayerTemplate",
  96. //"ButtonStartPosition",
  97. NULL // keep this last
  98. };
  99. void positionStartSpots( AsciiString mapName, GameWindow *buttonMapStartPositions[], GameWindow *mapWindow);
  100. static void showGameSpyGameOptionsUnderlyingGUIElements( Bool show )
  101. {
  102. ShowUnderlyingGUIElements( show, layoutFilename, parentName, gadgetsToHide, perPlayerGadgetsToHide );
  103. GameWindow *win = TheWindowManager->winGetWindowFromId( NULL, TheNameKeyGenerator->nameToKey("GameSpyGameOptionsMenu.wnd:ButtonBack") );
  104. if(win)
  105. win->winEnable( show );
  106. }
  107. // PUBLIC FUNCTIONS ///////////////////////////////////////////////////////////////////////////////
  108. //-------------------------------------------------------------------------------------------------
  109. /** Initialize the MapSelect menu */
  110. //-------------------------------------------------------------------------------------------------
  111. void WOLMapSelectMenuInit( WindowLayout *layout, void *userData )
  112. {
  113. // set keyboard focus to main parent
  114. AsciiString parentName( "WOLMapSelectMenu.wnd:WOLMapSelectMenuParent" );
  115. NameKeyType parentID = TheNameKeyGenerator->nameToKey( parentName );
  116. parent = TheWindowManager->winGetWindowFromId( NULL, parentID );
  117. TheWindowManager->winSetFocus( parent );
  118. CustomMatchPreferences pref;
  119. Bool usesSystemMapDir = pref.usesSystemMapDir();
  120. winMapPreviewID = TheNameKeyGenerator->nameToKey( AsciiString("WOLMapSelectMenu.wnd:WinMapPreview") );
  121. winMapPreview = TheWindowManager->winGetWindowFromId(parent, winMapPreviewID);
  122. const MapMetaData *mmd = TheMapCache->findMap(TheGameSpyGame->getMap());
  123. if (mmd)
  124. {
  125. usesSystemMapDir = mmd->m_isOfficial;
  126. }
  127. //if stats are enabled, only official maps can be used
  128. if( TheGameSpyInfo->getCurrentStagingRoom()->getUseStats() )
  129. usesSystemMapDir = true;
  130. buttonBack = TheNameKeyGenerator->nameToKey( AsciiString("WOLMapSelectMenu.wnd:ButtonBack") );
  131. buttonOK = TheNameKeyGenerator->nameToKey( AsciiString("WOLMapSelectMenu.wnd:ButtonOK") );
  132. listboxMap = TheNameKeyGenerator->nameToKey( AsciiString("WOLMapSelectMenu.wnd:ListboxMap") );
  133. radioButtonSystemMapsID = TheNameKeyGenerator->nameToKey( "WOLMapSelectMenu.wnd:RadioButtonSystemMaps" );
  134. radioButtonUserMapsID = TheNameKeyGenerator->nameToKey( "WOLMapSelectMenu.wnd:RadioButtonUserMaps" );
  135. winMapWindow = TheWindowManager->winGetWindowFromId( parent, listboxMap );
  136. GameWindow *radioButtonSystemMaps = TheWindowManager->winGetWindowFromId( parent, radioButtonSystemMapsID );
  137. GameWindow *radioButtonUserMaps = TheWindowManager->winGetWindowFromId( parent, radioButtonUserMapsID );
  138. if( TheGameSpyInfo->getCurrentStagingRoom()->getUseStats() )
  139. { //disable unofficial maps if stats are being recorded
  140. GadgetRadioSetSelection( radioButtonSystemMaps, FALSE );
  141. radioButtonUserMaps->winEnable( FALSE );
  142. }
  143. else if (usesSystemMapDir)
  144. GadgetRadioSetSelection( radioButtonSystemMaps, FALSE );
  145. else
  146. GadgetRadioSetSelection( radioButtonUserMaps, FALSE );
  147. AsciiString tmpString;
  148. for (Int i = 0; i < MAX_SLOTS; i++)
  149. {
  150. tmpString.format("WOLMapSelectMenu.wnd:ButtonMapStartPosition%d", i);
  151. buttonMapStartPositionID[i] = TheNameKeyGenerator->nameToKey( tmpString );
  152. buttonMapStartPosition[i] = TheWindowManager->winGetWindowFromId( winMapPreview, buttonMapStartPositionID[i] );
  153. DEBUG_ASSERTCRASH(buttonMapStartPosition[i], ("Could not find the ButtonMapStartPosition[%d]",i ));
  154. buttonMapStartPosition[i]->winHide(TRUE);
  155. buttonMapStartPosition[i]->winEnable(FALSE);
  156. }
  157. raiseMessageBoxes = TRUE;
  158. showGameSpyGameOptionsUnderlyingGUIElements( FALSE );
  159. // get the listbox window
  160. AsciiString listString( "WOLMapSelectMenu.wnd:ListboxMap" );
  161. NameKeyType mapListID = TheNameKeyGenerator->nameToKey( listString );
  162. mapList = TheWindowManager->winGetWindowFromId( parent, mapListID );
  163. if( mapList )
  164. {
  165. if (TheMapCache)
  166. TheMapCache->updateCache();
  167. populateMapListbox( mapList, usesSystemMapDir, TRUE, TheGameSpyGame->getMap() );
  168. }
  169. } // end WOLMapSelectMenuInit
  170. //-------------------------------------------------------------------------------------------------
  171. /** MapSelect menu shutdown method */
  172. //-------------------------------------------------------------------------------------------------
  173. void WOLMapSelectMenuShutdown( WindowLayout *layout, void *userData )
  174. {
  175. NullifyControls();
  176. // hide menu
  177. layout->hide( TRUE );
  178. // our shutdown is complete
  179. TheShell->shutdownComplete( layout );
  180. } // end WOLMapSelectMenuShutdown
  181. //-------------------------------------------------------------------------------------------------
  182. /** MapSelect menu update method */
  183. //-------------------------------------------------------------------------------------------------
  184. void WOLMapSelectMenuUpdate( WindowLayout *layout, void *userData )
  185. {
  186. if (raiseMessageBoxes)
  187. {
  188. RaiseGSMessageBox();
  189. raiseMessageBoxes = false;
  190. }
  191. // No update because the game setup screen is up at the same
  192. // time and it does the update for us...
  193. } // end WOLMapSelectMenuUpdate
  194. //-------------------------------------------------------------------------------------------------
  195. /** Map select menu input callback */
  196. //-------------------------------------------------------------------------------------------------
  197. WindowMsgHandledType WOLMapSelectMenuInput( GameWindow *window, UnsignedInt msg,
  198. WindowMsgData mData1, WindowMsgData mData2 )
  199. {
  200. switch( msg )
  201. {
  202. // --------------------------------------------------------------------------------------------
  203. case GWM_CHAR:
  204. {
  205. UnsignedByte key = mData1;
  206. UnsignedByte state = mData2;
  207. switch( key )
  208. {
  209. // ----------------------------------------------------------------------------------------
  210. case KEY_ESC:
  211. {
  212. //
  213. // send a simulated selected event to the parent window of the
  214. // back/exit button
  215. //
  216. if( BitTest( state, KEY_STATE_UP ) )
  217. {
  218. AsciiString buttonName( "WOLMapSelectMenu.wnd:ButtonBack" );
  219. NameKeyType buttonID = TheNameKeyGenerator->nameToKey( buttonName );
  220. GameWindow *button = TheWindowManager->winGetWindowFromId( window, buttonID );
  221. TheWindowManager->winSendSystemMsg( window, GBM_SELECTED,
  222. (WindowMsgData)button, buttonID );
  223. } // end if
  224. // don't let key fall through anywhere else
  225. return MSG_HANDLED;
  226. } // end escape
  227. } // end switch( key )
  228. } // end char
  229. } // end switch( msg )
  230. return MSG_IGNORED;
  231. } // end WOLMapSelectMenuInput
  232. void WOLPositionStartSpots( void );
  233. //-------------------------------------------------------------------------------------------------
  234. /** MapSelect menu window system callback */
  235. //-------------------------------------------------------------------------------------------------
  236. WindowMsgHandledType WOLMapSelectMenuSystem( GameWindow *window, UnsignedInt msg,
  237. WindowMsgData mData1, WindowMsgData mData2 )
  238. {
  239. switch( msg )
  240. {
  241. // --------------------------------------------------------------------------------------------
  242. case GWM_CREATE:
  243. {
  244. break;
  245. } // end create
  246. //---------------------------------------------------------------------------------------------
  247. case GWM_DESTROY:
  248. {
  249. NullifyControls();
  250. break;
  251. } // end case
  252. // --------------------------------------------------------------------------------------------
  253. case GWM_INPUT_FOCUS:
  254. {
  255. // if we're givin the opportunity to take the keyboard focus we must say we want it
  256. if( mData1 == TRUE )
  257. *(Bool *)mData2 = TRUE;
  258. return MSG_HANDLED;
  259. } // end input
  260. //---------------------------------------------------------------------------------------------
  261. case GLM_DOUBLE_CLICKED:
  262. {
  263. GameWindow *control = (GameWindow *)mData1;
  264. Int controlID = control->winGetWindowId();
  265. if( controlID == listboxMap )
  266. {
  267. int rowSelected = mData2;
  268. if (rowSelected >= 0)
  269. {
  270. GadgetListBoxSetSelected( control, rowSelected );
  271. GameWindow *button = TheWindowManager->winGetWindowFromId( window, buttonOK );
  272. TheWindowManager->winSendSystemMsg( window, GBM_SELECTED,
  273. (WindowMsgData)button, buttonOK );
  274. }
  275. }
  276. break;
  277. }
  278. //---------------------------------------------------------------------------------------------
  279. case GLM_SELECTED:
  280. {
  281. GameWindow *control = (GameWindow *)mData1;
  282. Int controlID = control->winGetWindowId();
  283. if( controlID == listboxMap )
  284. {
  285. int rowSelected = mData2;
  286. if( rowSelected < 0 )
  287. {
  288. positionStartSpots( AsciiString::TheEmptyString, buttonMapStartPosition, winMapPreview);
  289. // winMapPreview->winClearStatus(WIN_STATUS_IMAGE);
  290. break;
  291. }
  292. winMapPreview->winSetStatus(WIN_STATUS_IMAGE);
  293. UnicodeString map;
  294. // get text of the map to load
  295. map = GadgetListBoxGetText( winMapWindow, rowSelected, 0 );
  296. // set the map name in the global data map name
  297. AsciiString asciiMap;
  298. const char *mapFname = (const char *)GadgetListBoxGetItemData( winMapWindow, rowSelected );
  299. DEBUG_ASSERTCRASH(mapFname, ("No map item data"));
  300. if (mapFname)
  301. asciiMap = mapFname;
  302. else
  303. asciiMap.translate( map );
  304. asciiMap.toLower();
  305. Image *image = getMapPreviewImage(asciiMap);
  306. winMapPreview->winSetUserData((void *)TheMapCache->findMap(asciiMap));
  307. if(image)
  308. {
  309. winMapPreview->winSetEnabledImage(0, image);
  310. }
  311. else
  312. {
  313. winMapPreview->winClearStatus(WIN_STATUS_IMAGE);
  314. }
  315. positionStartSpots( asciiMap, buttonMapStartPosition, winMapPreview);
  316. }
  317. break;
  318. }
  319. //---------------------------------------------------------------------------------------------
  320. case GBM_SELECTED:
  321. {
  322. GameWindow *control = (GameWindow *)mData1;
  323. Int controlID = control->winGetWindowId();
  324. if( controlID == buttonBack )
  325. {
  326. showGameSpyGameOptionsUnderlyingGUIElements( TRUE );
  327. WOLMapSelectLayout->destroyWindows();
  328. WOLMapSelectLayout->deleteInstance();
  329. WOLMapSelectLayout = NULL;
  330. WOLPositionStartSpots();
  331. } // end if
  332. else if ( controlID == radioButtonSystemMapsID )
  333. {
  334. if (TheMapCache)
  335. TheMapCache->updateCache();
  336. populateMapListbox( mapList, TRUE, TRUE, TheGameSpyGame->getMap() );
  337. CustomMatchPreferences pref;
  338. pref.setUsesSystemMapDir(TRUE);
  339. pref.write();
  340. }
  341. else if ( controlID == radioButtonUserMapsID )
  342. {
  343. if (TheMapCache)
  344. TheMapCache->updateCache();
  345. populateMapListbox( mapList, FALSE, TRUE, TheGameSpyGame->getMap() );
  346. CustomMatchPreferences pref;
  347. pref.setUsesSystemMapDir(FALSE);
  348. pref.write();
  349. }
  350. else if( controlID == buttonOK )
  351. {
  352. Int selected;
  353. UnicodeString map;
  354. // get the selected index
  355. GadgetListBoxGetSelected( winMapWindow, &selected );
  356. if( selected != -1 )
  357. {
  358. // get text of the map to load
  359. map = GadgetListBoxGetText( winMapWindow, selected, 0 );
  360. // set the map name in the global data map name
  361. AsciiString asciiMap;
  362. const char *mapFname = (const char *)GadgetListBoxGetItemData( winMapWindow, selected );
  363. DEBUG_ASSERTCRASH(mapFname, ("No map item data"));
  364. if (mapFname)
  365. asciiMap = mapFname;
  366. else
  367. asciiMap.translate( map );
  368. TheGameSpyGame->setMap(asciiMap);
  369. asciiMap.toLower();
  370. std::map<AsciiString, MapMetaData>::iterator it = TheMapCache->find(asciiMap);
  371. if (it != TheMapCache->end())
  372. {
  373. TheGameSpyGame->getGameSpySlot(0)->setMapAvailability(TRUE);
  374. TheGameSpyGame->setMapCRC( it->second.m_CRC );
  375. TheGameSpyGame->setMapSize( it->second.m_filesize );
  376. }
  377. TheGameSpyGame->adjustSlotsForMap(); // BGC- adjust the slots for the new map.
  378. TheGameSpyGame->resetAccepted();
  379. TheGameSpyGame->resetStartSpots();
  380. TheGameSpyInfo->setGameOptions();
  381. WOLDisplaySlotList();
  382. WOLDisplayGameOptions();
  383. WOLMapSelectLayout->destroyWindows();
  384. WOLMapSelectLayout->deleteInstance();
  385. WOLMapSelectLayout = NULL;
  386. showGameSpyGameOptionsUnderlyingGUIElements( TRUE );
  387. WOLPositionStartSpots();
  388. } // end if
  389. } // end else if
  390. break;
  391. } // end selected
  392. default:
  393. return MSG_IGNORED;
  394. } // end switch
  395. return MSG_HANDLED;
  396. } // end WOLMapSelectMenuSystem