LanMapSelectMenu.cpp 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460
  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: LanMapSelectMenu.cpp ////////////////////////////////////////////////////////////////////////
  24. // Author: Colin Day, October 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/GameEngine.h"
  30. #include "Common/NameKeyGenerator.h"
  31. #include "Common/MessageStream.h"
  32. #include "Common/UserPreferences.h"
  33. #include "GameClient/WindowLayout.h"
  34. #include "GameClient/Gadget.h"
  35. #include "GameClient/Shell.h"
  36. #include "GameClient/GameWindowManager.h"
  37. #include "GameClient/GadgetListBox.h"
  38. #include "GameClient/GadgetRadioButton.h"
  39. #include "GameNetwork/LANAPICallbacks.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 NameKeyType winMapPreviewID = NAMEKEY_INVALID;
  52. static GameWindow *parent = NULL;
  53. static GameWindow *mapList = NULL;
  54. static GameWindow *winMapPreview = NULL;
  55. static NameKeyType radioButtonSystemMapsID = NAMEKEY_INVALID;
  56. static NameKeyType radioButtonUserMapsID = NAMEKEY_INVALID;
  57. static GameWindow *buttonMapStartPosition[MAX_SLOTS] = {NULL,NULL,NULL,NULL,
  58. NULL,NULL,NULL,NULL };
  59. static NameKeyType buttonMapStartPositionID[MAX_SLOTS] = { NAMEKEY_INVALID,NAMEKEY_INVALID,
  60. NAMEKEY_INVALID,NAMEKEY_INVALID,
  61. NAMEKEY_INVALID,NAMEKEY_INVALID,
  62. NAMEKEY_INVALID,NAMEKEY_INVALID };
  63. // PUBLIC FUNCTIONS ///////////////////////////////////////////////////////////////////////////////
  64. void positionStartSpots( AsciiString mapName, GameWindow *buttonMapStartPositions[], GameWindow *mapWindow);
  65. static const char *layoutFilename = "LanGameOptionsMenu.wnd";
  66. static const char *parentName = "LanGameOptionsMenuParent";
  67. static const char *gadgetsToHide[] =
  68. {
  69. "MapWindow",
  70. //"StaticTextTitle",
  71. "StaticTextTeam",
  72. "StaticTextFaction",
  73. "StaticTextColor",
  74. "TextEntryMapDisplay",
  75. "ButtonSelectMap",
  76. "ButtonStart",
  77. "StaticTextMapPreview",
  78. NULL // keep this last
  79. };
  80. static const char *perPlayerGadgetsToHide[] =
  81. {
  82. "ComboBoxTeam",
  83. "ComboBoxColor",
  84. "ComboBoxPlayerTemplate",
  85. NULL // keep this last
  86. };
  87. static void showLANGameOptionsUnderlyingGUIElements( Bool show )
  88. {
  89. ShowUnderlyingGUIElements( show, layoutFilename, parentName, gadgetsToHide, perPlayerGadgetsToHide );
  90. GameWindow *win = TheWindowManager->winGetWindowFromId( NULL, TheNameKeyGenerator->nameToKey("LanGameOptionsMenu.wnd:ButtonBack") );
  91. if(win)
  92. win->winEnable( show );
  93. }
  94. static void NullifyControls()
  95. {
  96. mapList = NULL;
  97. winMapPreview = NULL;
  98. parent = NULL;
  99. for (Int i=0; i<MAX_SLOTS; ++i)
  100. {
  101. buttonMapStartPosition[i] = NULL;
  102. }
  103. }
  104. //-------------------------------------------------------------------------------------------------
  105. /** Initialize the MapSelect menu */
  106. //-------------------------------------------------------------------------------------------------
  107. void LanMapSelectMenuInit( WindowLayout *layout, void *userData )
  108. {
  109. showLANGameOptionsUnderlyingGUIElements(FALSE);
  110. // set keyboard focus to main parent
  111. AsciiString parentName( "LanMapSelectMenu.wnd:LanMapSelectMenuParent" );
  112. NameKeyType parentID = TheNameKeyGenerator->nameToKey( parentName );
  113. parent = TheWindowManager->winGetWindowFromId( NULL, parentID );
  114. TheWindowManager->winSetFocus( parent );
  115. LANPreferences pref;
  116. Bool usesSystemMapDir = pref.usesSystemMapDir();
  117. const MapMetaData *mmd = TheMapCache->findMap(TheLAN->GetMyGame()->getMap());
  118. if (mmd)
  119. {
  120. usesSystemMapDir = mmd->m_isOfficial;
  121. }
  122. buttonBack = TheNameKeyGenerator->nameToKey( AsciiString("LanMapSelectMenu.wnd:ButtonBack") );
  123. buttonOK = TheNameKeyGenerator->nameToKey( AsciiString("LanMapSelectMenu.wnd:ButtonOK") );
  124. listboxMap = TheNameKeyGenerator->nameToKey( AsciiString("LanMapSelectMenu.wnd:ListboxMap") );
  125. winMapPreviewID = TheNameKeyGenerator->nameToKey( AsciiString("LanMapSelectMenu.wnd:WinMapPreview") );
  126. radioButtonSystemMapsID = TheNameKeyGenerator->nameToKey( "LanMapSelectMenu.wnd:RadioButtonSystemMaps" );
  127. radioButtonUserMapsID = TheNameKeyGenerator->nameToKey( "LanMapSelectMenu.wnd:RadioButtonUserMaps" );
  128. GameWindow *radioButtonSystemMaps = TheWindowManager->winGetWindowFromId( parent, radioButtonSystemMapsID );
  129. GameWindow *radioButtonUserMaps = TheWindowManager->winGetWindowFromId( parent, radioButtonUserMapsID );
  130. winMapPreview = TheWindowManager->winGetWindowFromId(parent, winMapPreviewID);
  131. if (usesSystemMapDir)
  132. GadgetRadioSetSelection( radioButtonSystemMaps, FALSE );
  133. else
  134. GadgetRadioSetSelection( radioButtonUserMaps, FALSE );
  135. AsciiString tmpString;
  136. for (Int i = 0; i < MAX_SLOTS; i++)
  137. {
  138. tmpString.format("LanMapSelectMenu.wnd:ButtonMapStartPosition%d", i);
  139. buttonMapStartPositionID[i] = TheNameKeyGenerator->nameToKey( tmpString );
  140. buttonMapStartPosition[i] = TheWindowManager->winGetWindowFromId( winMapPreview, buttonMapStartPositionID[i] );
  141. DEBUG_ASSERTCRASH(buttonMapStartPosition[i], ("Could not find the ButtonMapStartPosition[%d]",i ));
  142. buttonMapStartPosition[i]->winHide(TRUE);
  143. buttonMapStartPosition[i]->winEnable(FALSE);
  144. }
  145. // get the listbox window
  146. AsciiString listString( "LanMapSelectMenu.wnd:ListboxMap" );
  147. NameKeyType mapListID = TheNameKeyGenerator->nameToKey( listString );
  148. mapList = TheWindowManager->winGetWindowFromId( parent, mapListID );
  149. if( mapList )
  150. {
  151. if (TheMapCache)
  152. TheMapCache->updateCache();
  153. populateMapListbox( mapList, usesSystemMapDir, TRUE, TheLAN->GetMyGame()->getMap() );
  154. }
  155. } // end LanMapSelectMenuInit
  156. //-------------------------------------------------------------------------------------------------
  157. /** MapSelect menu shutdown method */
  158. //-------------------------------------------------------------------------------------------------
  159. void LanMapSelectMenuShutdown( WindowLayout *layout, void *userData )
  160. {
  161. // hide menu
  162. layout->hide( TRUE );
  163. NullifyControls();
  164. // our shutdown is complete
  165. TheShell->shutdownComplete( layout );
  166. } // end LanMapSelectMenuShutdown
  167. //-------------------------------------------------------------------------------------------------
  168. /** MapSelect menu update method */
  169. //-------------------------------------------------------------------------------------------------
  170. void LanMapSelectMenuUpdate( WindowLayout *layout, void *userData )
  171. {
  172. } // end LanMapSelectMenuUpdate
  173. //-------------------------------------------------------------------------------------------------
  174. /** Map select menu input callback */
  175. //-------------------------------------------------------------------------------------------------
  176. WindowMsgHandledType LanMapSelectMenuInput( GameWindow *window, UnsignedInt msg,
  177. WindowMsgData mData1, WindowMsgData mData2 )
  178. {
  179. switch( msg )
  180. {
  181. // --------------------------------------------------------------------------------------------
  182. case GWM_CHAR:
  183. {
  184. UnsignedByte key = mData1;
  185. UnsignedByte state = mData2;
  186. switch( key )
  187. {
  188. // ----------------------------------------------------------------------------------------
  189. case KEY_ESC:
  190. {
  191. //
  192. // send a simulated selected event to the parent window of the
  193. // back/exit button
  194. //
  195. if( BitTest( state, KEY_STATE_UP ) )
  196. {
  197. AsciiString buttonName( "LanMapSelectMenu.wnd:ButtonBack" );
  198. NameKeyType buttonID = TheNameKeyGenerator->nameToKey( buttonName );
  199. GameWindow *button = TheWindowManager->winGetWindowFromId( window, buttonID );
  200. TheWindowManager->winSendSystemMsg( window, GBM_SELECTED,
  201. (WindowMsgData)button, buttonID );
  202. } // end if
  203. // don't let key fall through anywhere else
  204. return MSG_HANDLED;
  205. } // end escape
  206. } // end switch( key )
  207. } // end char
  208. } // end switch( msg )
  209. return MSG_IGNORED;
  210. } // end LanMapSelectMenuInput
  211. //-------------------------------------------------------------------------------------------------
  212. /** MapSelect menu window system callback */
  213. //-------------------------------------------------------------------------------------------------
  214. WindowMsgHandledType LanMapSelectMenuSystem( GameWindow *window, UnsignedInt msg,
  215. WindowMsgData mData1, WindowMsgData mData2 )
  216. {
  217. GameWindow *mapWindow = NULL;
  218. if (listboxMap != NULL)
  219. {
  220. mapWindow = TheWindowManager->winGetWindowFromId( parent, listboxMap );
  221. }
  222. switch( msg )
  223. {
  224. // --------------------------------------------------------------------------------------------
  225. case GWM_CREATE:
  226. {
  227. break;
  228. } // end create
  229. //---------------------------------------------------------------------------------------------
  230. case GWM_DESTROY:
  231. {
  232. NullifyControls();
  233. break;
  234. } // end case
  235. // --------------------------------------------------------------------------------------------
  236. case GWM_INPUT_FOCUS:
  237. {
  238. // if we're givin the opportunity to take the keyboard focus we must say we want it
  239. if( mData1 == TRUE )
  240. *(Bool *)mData2 = TRUE;
  241. return MSG_HANDLED;
  242. } // end input
  243. //---------------------------------------------------------------------------------------------
  244. case GLM_DOUBLE_CLICKED:
  245. {
  246. GameWindow *control = (GameWindow *)mData1;
  247. Int controlID = control->winGetWindowId();
  248. if( controlID == listboxMap )
  249. {
  250. int rowSelected = mData2;
  251. if (rowSelected >= 0)
  252. {
  253. GadgetListBoxSetSelected( control, rowSelected );
  254. GameWindow *button = TheWindowManager->winGetWindowFromId( window, buttonOK );
  255. TheWindowManager->winSendSystemMsg( window, GBM_SELECTED,
  256. (WindowMsgData)button, buttonOK );
  257. }
  258. }
  259. break;
  260. }
  261. //---------------------------------------------------------------------------------------------
  262. case GBM_SELECTED:
  263. {
  264. GameWindow *control = (GameWindow *)mData1;
  265. Int controlID = control->winGetWindowId();
  266. if ( controlID == radioButtonSystemMapsID )
  267. {
  268. if (TheMapCache)
  269. TheMapCache->updateCache();
  270. populateMapListbox( mapList, TRUE, TRUE, TheLAN->GetMyGame()->getMap() );
  271. LANPreferences pref;
  272. pref["UseSystemMapDir"] = "yes";
  273. pref.write();
  274. }
  275. else if ( controlID == radioButtonUserMapsID )
  276. {
  277. if (TheMapCache)
  278. TheMapCache->updateCache();
  279. populateMapListbox( mapList, FALSE, TRUE, TheLAN->GetMyGame()->getMap() );
  280. LANPreferences pref;
  281. pref["UseSystemMapDir"] = "no";
  282. pref.write();
  283. }
  284. else if ( controlID == buttonBack )
  285. {
  286. mapSelectLayout->destroyWindows();
  287. mapSelectLayout->deleteInstance();
  288. mapSelectLayout = NULL;
  289. // set the controls to NULL since they've been destroyed.
  290. NullifyControls();
  291. showLANGameOptionsUnderlyingGUIElements(TRUE);
  292. PostToLanGameOptions( MAP_BACK );
  293. } // end if
  294. else if ( controlID == buttonOK )
  295. {
  296. Int selected = -1;
  297. UnicodeString map;
  298. // get the selected index
  299. if (mapWindow != NULL)
  300. {
  301. GadgetListBoxGetSelected( mapWindow, &selected );
  302. }
  303. if( selected != -1 )
  304. {
  305. // get text of the map to load
  306. map = GadgetListBoxGetText( mapWindow, selected, 0 );
  307. // set the map name in the global data map name
  308. AsciiString asciiMap;
  309. const char *mapFname = (const char *)GadgetListBoxGetItemData( mapWindow, selected );
  310. DEBUG_ASSERTCRASH(mapFname, ("No map item data"));
  311. if (mapFname)
  312. asciiMap = mapFname;
  313. else
  314. asciiMap.translate( map );
  315. TheLAN->GetMyGame()->setMap( asciiMap );
  316. asciiMap.toLower();
  317. std::map<AsciiString, MapMetaData>::iterator it = TheMapCache->find(asciiMap);
  318. if (it != TheMapCache->end())
  319. {
  320. TheLAN->GetMyGame()->getSlot(0)->setMapAvailability(true);
  321. TheLAN->GetMyGame()->setMapCRC( it->second.m_CRC );
  322. TheLAN->GetMyGame()->setMapSize( it->second.m_filesize );
  323. TheLAN->GetMyGame()->resetStartSpots();
  324. TheLAN->GetMyGame()->adjustSlotsForMap(); // BGC- adjust the slots for the new map.
  325. }
  326. mapSelectLayout->destroyWindows();
  327. mapSelectLayout->deleteInstance();
  328. mapSelectLayout = NULL;
  329. // set the controls to NULL since they've been destroyed.
  330. NullifyControls();
  331. showLANGameOptionsUnderlyingGUIElements(TRUE);
  332. PostToLanGameOptions(SEND_GAME_OPTS);
  333. } // end if
  334. } // end else if
  335. break;
  336. } // end selected
  337. case GLM_SELECTED:
  338. {
  339. GameWindow *control = (GameWindow *)mData1;
  340. Int controlID = control->winGetWindowId();
  341. if( controlID == listboxMap )
  342. {
  343. int rowSelected = mData2;
  344. if( rowSelected < 0 )
  345. {
  346. positionStartSpots( AsciiString::TheEmptyString, buttonMapStartPosition, winMapPreview);
  347. // winMapPreview->winClearStatus(WIN_STATUS_IMAGE);
  348. break;
  349. }
  350. winMapPreview->winSetStatus(WIN_STATUS_IMAGE);
  351. UnicodeString map;
  352. // get text of the map to load
  353. map = GadgetListBoxGetText( mapWindow, rowSelected, 0 );
  354. // set the map name in the global data map name
  355. AsciiString asciiMap;
  356. const char *mapFname = (const char *)GadgetListBoxGetItemData( mapWindow, rowSelected );
  357. DEBUG_ASSERTCRASH(mapFname, ("No map item data"));
  358. if (mapFname)
  359. asciiMap = mapFname;
  360. else
  361. asciiMap.translate( map );
  362. asciiMap.toLower();
  363. Image *image = getMapPreviewImage(asciiMap);
  364. winMapPreview->winSetUserData((void *)TheMapCache->findMap(asciiMap));
  365. if(image)
  366. {
  367. winMapPreview->winSetEnabledImage(0, image);
  368. }
  369. else
  370. {
  371. winMapPreview->winClearStatus(WIN_STATUS_IMAGE);
  372. }
  373. positionStartSpots( asciiMap, buttonMapStartPosition, winMapPreview);
  374. }
  375. break;
  376. }
  377. default:
  378. return MSG_IGNORED;
  379. } // end switch
  380. return MSG_HANDLED;
  381. } // end LanMapSelectMenuSystem