Counter Strike : Global Offensive Source Code
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

863 lines
27 KiB

  1. //========= Copyright � 1996-2005, Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. // $NoKeywords: $
  6. //=============================================================================//
  7. #include "bonusmapsdialog.h"
  8. #include "engineinterface.h"
  9. #include "vgui/ISystem.h"
  10. #include "vgui/ISurface.h"
  11. #include "vgui/IVGui.h"
  12. #include <vgui/ILocalize.h>
  13. #include "filesystem.h"
  14. #include "vgui_controls/Button.h"
  15. #include "vgui_controls/ComboBox.h"
  16. #include "vgui_controls/PanelListPanel.h"
  17. #include "vgui_controls/QueryBox.h"
  18. #include "vgui_controls/ImagePanel.h"
  19. #include "vgui_controls/BitmapImagePanel.h"
  20. #include "vgui_controls/FileOpenDialog.h"
  21. #include "vgui_controls/tgaimagepanel.h"
  22. #include "mousemessageforwardingpanel.h"
  23. #include "basepanel.h"
  24. // memdbgon must be the last include file in a .cpp file!!!
  25. #include "tier0/memdbgon.h"
  26. using namespace vgui;
  27. #define MAX_LISTED_BONUS_MAPS 128
  28. extern const char *COM_GetModDirectory( void );
  29. bool ConstructFullImagePath( const char *pCurrentPath, const char *pchImageName, char *pchImageFileName )
  30. {
  31. char *ext = Q_strstr( pchImageName , ".tga" );
  32. if ( ext )
  33. {
  34. // Use the specified image
  35. if ( pchImageName[ 0 ] != '.' )
  36. Q_snprintf( pchImageFileName, _MAX_PATH, "%s", pchImageName );
  37. else
  38. Q_snprintf( pchImageFileName, _MAX_PATH, "%s/%s", pCurrentPath, pchImageName );
  39. return true;
  40. }
  41. Q_strcpy( pchImageFileName, pchImageName );
  42. return false;
  43. }
  44. //-----------------------------------------------------------------------------
  45. // Purpose: Describes the layout of a same game pic
  46. //-----------------------------------------------------------------------------
  47. class CBonusMapPanel : public vgui::EditablePanel
  48. {
  49. DECLARE_CLASS_SIMPLE( CBonusMapPanel, vgui::EditablePanel );
  50. public:
  51. CBonusMapPanel( PanelListPanel *parent, const char *name, int bonusMapListItemID ) : BaseClass( parent, name )
  52. {
  53. m_iBonusMapListItemID = bonusMapListItemID;
  54. m_pParent = parent;
  55. m_pBonusMapTGAImage = new CTGAImagePanel( this, "BonusMapTGAImage" );
  56. m_pBonusMapImage = SETUP_PANEL( new ImagePanel( this, "BonusMapImage" ) );
  57. m_pBonusMapScreenshotBackground = SETUP_PANEL( new ImagePanel( this, "BonusMapScreenshotBackground" ) );
  58. m_pMapNameLabel = new Label( this, "MapNameLabel", "" );
  59. m_pLockIcon = new ImagePanel( this, "LockIcon" );
  60. m_pCompleteIcon = new ImagePanel( this, "CompleteIcon" );
  61. CMouseMessageForwardingPanel *panel = new CMouseMessageForwardingPanel(this, NULL);
  62. panel->SetZPos(2);
  63. SetSize( 200, 140 );
  64. LoadControlSettings( "resource/BonusMapPanel.res" );
  65. m_FillColor = m_pBonusMapScreenshotBackground->GetFillColor();
  66. }
  67. void SetBonusMapInfo( const char *pCurrentPath, BonusMapDescription_t &map )
  68. {
  69. // set the image to display
  70. char szImageFileName[_MAX_PATH];
  71. bool bIsTGA = false;
  72. if ( map.bIsFolder )
  73. {
  74. if ( map.szImageName[ 0 ] == '\0' )
  75. {
  76. // use associate bonus folder icon
  77. Q_snprintf( szImageFileName, sizeof(szImageFileName), "%s/foldericon.tga", map.szFileName );
  78. bIsTGA = true;
  79. // use default folder icon
  80. if( !g_pFullFileSystem->FileExists( szImageFileName, "MOD" ) )
  81. {
  82. Q_strcpy( szImageFileName, "bonusmaps/icon_bonus_map_folder" );
  83. bIsTGA = false;
  84. }
  85. }
  86. else
  87. {
  88. // Use the specified image
  89. bIsTGA = ConstructFullImagePath( pCurrentPath, map.szImageName, szImageFileName );
  90. }
  91. }
  92. else
  93. {
  94. if ( map.szImageName[ 0 ] == '\0' )
  95. {
  96. // Didn't specify an image name, so pair it with the name of this file
  97. char szImpliedTgaName[_MAX_PATH];
  98. Q_snprintf( szImpliedTgaName, sizeof( szImpliedTgaName ), "%s.tga", map.szMapFileName );
  99. bIsTGA = ConstructFullImagePath( pCurrentPath, szImpliedTgaName, szImageFileName );
  100. // if it doesn't exist use default bonus map icon
  101. if( !g_pFullFileSystem->FileExists( szImageFileName, "MOD" ) )
  102. {
  103. Q_strcpy( szImageFileName, "bonusmaps/icon_bonus_map_default" );
  104. bIsTGA = false;
  105. }
  106. }
  107. else
  108. {
  109. // Use the specified image
  110. bIsTGA = ConstructFullImagePath( pCurrentPath, map.szImageName, szImageFileName );
  111. }
  112. }
  113. if ( bIsTGA )
  114. {
  115. m_pBonusMapTGAImage->SetTGAFilenameNonMod( szImageFileName );
  116. m_pBonusMapTGAImage->SetSize( 180, 100 );
  117. m_pBonusMapTGAImage->SetVisible( true );
  118. m_pBonusMapImage->SetVisible( false );
  119. }
  120. else
  121. {
  122. m_pBonusMapImage->SetImage( szImageFileName );
  123. m_pBonusMapImage->SetSize( 180, 100 );
  124. m_pBonusMapImage->SetVisible( true );
  125. m_pBonusMapTGAImage->SetVisible( false );
  126. }
  127. m_pLockIcon->SetVisible( map.bLocked );
  128. m_pCompleteIcon->SetVisible( map.bComplete );
  129. // set the title text
  130. m_pMapNameLabel->SetText( map.szMapName );
  131. }
  132. MESSAGE_FUNC_INT( OnPanelSelected, "PanelSelected", state )
  133. {
  134. if ( state )
  135. {
  136. // set the text color to be orange, and the pic border to be orange
  137. m_pBonusMapScreenshotBackground->SetFillColor( m_SelectedColor );
  138. m_pMapNameLabel->SetFgColor( Color( 0, 0, 0, 255 ) );
  139. }
  140. else
  141. {
  142. m_pBonusMapScreenshotBackground->SetFillColor( m_FillColor );
  143. m_pMapNameLabel->SetFgColor( m_TextColor );
  144. }
  145. PostMessage( m_pParent->GetVParent(), new KeyValues("PanelSelected") );
  146. }
  147. virtual void OnMousePressed( vgui::MouseCode code )
  148. {
  149. m_pParent->SetSelectedPanel( this );
  150. }
  151. virtual void ApplySchemeSettings( IScheme *pScheme )
  152. {
  153. m_TextColor = pScheme->GetColor( "NewGame.TextColor", Color(255, 255, 255, 255) );
  154. m_SelectedColor = pScheme->GetColor( "NewGame.SelectionColor", Color(255, 255, 255, 255) );
  155. BaseClass::ApplySchemeSettings( pScheme );
  156. }
  157. virtual void OnMouseDoublePressed( vgui::MouseCode code )
  158. {
  159. // call the panel
  160. OnMousePressed( code );
  161. PostMessage( m_pParent->GetParent(), new KeyValues("Command", "command", "loadbonusmap") );
  162. }
  163. int GetBonusMapListItemID()
  164. {
  165. return m_iBonusMapListItemID;
  166. }
  167. private:
  168. vgui::PanelListPanel *m_pParent;
  169. vgui::Label *m_pMapNameLabel;
  170. ImagePanel *m_pBonusMapImage;
  171. CTGAImagePanel *m_pBonusMapTGAImage;
  172. ImagePanel *m_pLockIcon;
  173. ImagePanel *m_pCompleteIcon;
  174. // things to change color when the selection changes
  175. ImagePanel *m_pBonusMapScreenshotBackground;
  176. Color m_TextColor, m_FillColor, m_SelectedColor;
  177. int m_iBonusMapListItemID;
  178. };
  179. CBonusMapsDialog *g_pBonusMapsDialog = NULL;
  180. //-----------------------------------------------------------------------------
  181. // Purpose:Constructor
  182. //-----------------------------------------------------------------------------
  183. CBonusMapsDialog::CBonusMapsDialog(vgui::Panel *parent) : BaseClass(parent, "BonusMapsDialog")
  184. {
  185. g_pBonusMapsDialog = this;
  186. m_hImportBonusMapsDialog = NULL;
  187. BonusMapsDatabase()->RootPath();
  188. CreateBonusMapsList();
  189. BuildMapsList();
  190. new vgui::Button( this, "loadbonusmap", "" );
  191. SetControlEnabled( "loadbonusmap", false );
  192. SetDeleteSelfOnClose(true);
  193. //SetBounds(0, 0, 512, 384);
  194. //SetMinimumSize( 256, 300 );
  195. SetSizeable( false );
  196. SetTitle("#GameUI_BonusMaps", true);
  197. vgui::Button *cancel = new vgui::Button( this, "Cancel", "#GameUI_Cancel" );
  198. cancel->SetCommand( "Close" );
  199. m_pPercentageBarBackground = SETUP_PANEL( new ImagePanel( this, "PercentageBarBackground" ) );
  200. m_pPercentageBar = SETUP_PANEL( new ImagePanel( this, "PercentageBar" ) );
  201. LoadControlSettings("resource/BonusMapsDialog.res");
  202. // Stop blinking the bonus maps menu item
  203. CBaseModPanel *pBasePanel = BasePanel();
  204. if ( pBasePanel )
  205. pBasePanel->SetMenuItemBlinkingState( "OpenBonusMapsDialog", false );
  206. BonusMapsDatabase()->SetBlink( false );
  207. }
  208. //-----------------------------------------------------------------------------
  209. // Purpose: Destructor
  210. //-----------------------------------------------------------------------------
  211. CBonusMapsDialog::~CBonusMapsDialog()
  212. {
  213. BonusMapsDatabase()->WriteSaveData(); // Closing this dialog is a good time to save
  214. g_pBonusMapsDialog = NULL;
  215. }
  216. bool CBonusMapsDialog::ImportZippedBonusMaps( const char *pchZippedFileName )
  217. {
  218. // Get the zip file's name with dir info
  219. char *pchShortFileName = Q_strrchr( pchZippedFileName, '\\' );
  220. if ( !pchShortFileName )
  221. return false;
  222. // It's going to go in the maps folder
  223. char szOutFilename[ 512 ];
  224. Q_snprintf( szOutFilename, sizeof( szOutFilename ), "maps%s", pchShortFileName );
  225. Q_StripExtension( szOutFilename, szOutFilename, sizeof( szOutFilename ) );
  226. // If there's already a folder by the same name we're going to tack a number onto the end
  227. int iOutFilenameLength = Q_strlen( szOutFilename );
  228. int iSameFolderCount = 1;
  229. while ( g_pFullFileSystem->FileExists( szOutFilename, "MOD" ) )
  230. {
  231. ++iSameFolderCount;
  232. if ( iSameFolderCount > 99 )
  233. {
  234. return false;
  235. }
  236. szOutFilename[ iOutFilenameLength ] = '\0';
  237. Q_snprintf( szOutFilename, sizeof( szOutFilename ), "%s%02i", szOutFilename, iSameFolderCount );
  238. }
  239. // Pull the files out of the zip
  240. if ( g_pFullFileSystem->UnzipFile( pchZippedFileName, "MOD", szOutFilename ) )
  241. {
  242. // New maps have been imported, so refresh the list
  243. BuildMapsList();
  244. }
  245. return false;
  246. }
  247. //-----------------------------------------------------------------------------
  248. // Purpose: builds bonus map list from directory
  249. //-----------------------------------------------------------------------------
  250. void CBonusMapsDialog::BuildMapsList( void )
  251. {
  252. // clear the current list
  253. m_pGameList->DeleteAllItems();
  254. BonusMapsDatabase()->ClearBonusMapsList();
  255. BonusMapsDatabase()->ScanBonusMaps();
  256. // Enable back button if we're in a sub folder
  257. bool bIsRoot = ( Q_strcmp( BonusMapsDatabase()->GetPath(), "." ) == 0 );
  258. SetControlEnabled( "Back", !bIsRoot );
  259. SetControlVisible( "Back", !bIsRoot );
  260. SetControlEnabled( "ImportBonusMaps", bIsRoot );
  261. SetControlVisible( "ImportBonusMaps", bIsRoot );
  262. char szDisplayPath[_MAX_PATH];
  263. Q_snprintf( szDisplayPath, _MAX_PATH, "%s/", BonusMapsDatabase()->GetPath() );
  264. SetControlString( "FileName", szDisplayPath );
  265. SetControlString( "CommentLabel", "" );
  266. int iMapCount = BonusMapsDatabase()->BonusCount();
  267. // add to the list
  268. for ( int iMapIndex = 0; iMapIndex < iMapCount && iMapIndex < MAX_LISTED_BONUS_MAPS; ++iMapIndex )
  269. {
  270. CBonusMapPanel *bonusMapPanel = new CBonusMapPanel( m_pGameList, "BonusMapPanel", iMapIndex );
  271. bonusMapPanel->SetBonusMapInfo( BonusMapsDatabase()->GetPath(), *(BonusMapsDatabase()->GetBonusData( iMapIndex )) );
  272. m_pGameList->AddItem( NULL, bonusMapPanel );
  273. }
  274. // display a message if there are no save games
  275. if ( iMapCount <= 0 )
  276. {
  277. vgui::Label *pNoSavesLabel = SETUP_PANEL(new Label(m_pGameList, "NoBonusMapsLabel", "#GameUI_NoBonusMapsToDisplay"));
  278. pNoSavesLabel->SetTextColorState(vgui::Label::CS_DULL);
  279. m_pGameList->AddItem( NULL, pNoSavesLabel );
  280. m_pGameList->SetNumColumns( 1 );
  281. }
  282. else
  283. {
  284. m_pGameList->SetNumColumns( 3 );
  285. }
  286. RefreshCompletionPercentage();
  287. // Disable load button
  288. SetControlEnabled( "loadbonusmap", false );
  289. // Make challenge selection invisible
  290. m_pChallengeSelection->SetEnabled( false );
  291. m_pChallengeSelection->SetVisible( false );
  292. }
  293. //-----------------------------------------------------------------------------
  294. // Purpose: Creates the load game display list
  295. //-----------------------------------------------------------------------------
  296. void CBonusMapsDialog::CreateBonusMapsList()
  297. {
  298. m_pGameList = new vgui::PanelListPanel( this, "listpanel_bonusmaps" );
  299. m_pGameList->SetFirstColumnWidth( 0 );
  300. new Label( this, "FileName", "./" );
  301. new Label( this, "CommentLabel", "" );
  302. m_pChallengeSelection = new vgui::ComboBox( this, "ChallengeSelection", 0, false );
  303. }
  304. //-----------------------------------------------------------------------------
  305. // Purpose: returns the save file name of the selected item
  306. //-----------------------------------------------------------------------------
  307. int CBonusMapsDialog::GetSelectedItemBonusMapIndex()
  308. {
  309. CBonusMapPanel *panel = dynamic_cast<CBonusMapPanel *>(m_pGameList->GetSelectedPanel());
  310. if ( panel && panel->GetBonusMapListItemID() < BonusMapsDatabase()->BonusCount() )
  311. return panel->GetBonusMapListItemID();
  312. return BonusMapsDatabase()->InvalidIndex();
  313. }
  314. void CBonusMapsDialog::SetSelectedBooleanStatus( const char *pchName, bool bValue )
  315. {
  316. CBonusMapPanel *pSelectedBonusMapPanel = (CBonusMapPanel *)m_pGameList->GetSelectedPanel();
  317. if ( !pSelectedBonusMapPanel )
  318. return;
  319. BonusMapsDatabase()->SetBooleanStatus( pchName, pSelectedBonusMapPanel->GetBonusMapListItemID(), bValue );
  320. // Change the status in the dialog
  321. BonusMapDescription_t *pMap = BonusMapsDatabase()->GetBonusData( pSelectedBonusMapPanel->GetBonusMapListItemID() );
  322. pSelectedBonusMapPanel->SetBonusMapInfo( BonusMapsDatabase()->GetPath(), *pMap );
  323. RefreshCompletionPercentage();
  324. RefreshDialog( pMap );
  325. }
  326. void CBonusMapsDialog::RefreshData( void )
  327. {
  328. for ( int iMap = 0; iMap < m_pGameList->GetItemCount(); ++iMap )
  329. {
  330. CBonusMapPanel *pBonusMapPanel = (CBonusMapPanel *)m_pGameList->GetItemPanel( iMap );
  331. if ( pBonusMapPanel )
  332. pBonusMapPanel->SetBonusMapInfo( BonusMapsDatabase()->GetPath(), *(BonusMapsDatabase()->GetBonusData( pBonusMapPanel->GetBonusMapListItemID() ) ) );
  333. }
  334. CBonusMapPanel *pSelectedBonusMapPanel = (CBonusMapPanel *)m_pGameList->GetSelectedPanel();
  335. if ( !pSelectedBonusMapPanel )
  336. return;
  337. BonusMapDescription_t *pMap = BonusMapsDatabase()->GetBonusData( pSelectedBonusMapPanel->GetBonusMapListItemID() );
  338. RefreshCompletionPercentage();
  339. RefreshDialog( pMap );
  340. }
  341. int CBonusMapsDialog::GetSelectedChallenge( void )
  342. {
  343. if ( !m_pChallengeSelection->IsEnabled() )
  344. return -1;
  345. KeyValues *pUserDataKey = m_pChallengeSelection->GetActiveItemUserData();
  346. return pUserDataKey->GetInt( "challenge" );
  347. }
  348. void CBonusMapsDialog::RefreshDialog( BonusMapDescription_t *pMap )
  349. {
  350. if ( !pMap || pMap->bLocked || ( m_pChallengeSelection->IsEnabled() && GetSelectedChallenge() == -1 ) )
  351. {
  352. // It's locked or no challenge is selected, so disable the load button
  353. SetControlEnabled( "loadbonusmap", false );
  354. }
  355. else
  356. {
  357. // Enable the load button
  358. SetControlEnabled( "loadbonusmap", true );
  359. }
  360. RefreshMedalDisplay( pMap );
  361. if ( pMap )
  362. SetControlString( "CommentLabel", pMap->szComment );
  363. else
  364. SetControlString( "CommentLabel", "" );
  365. }
  366. void CBonusMapsDialog::RefreshMedalDisplay( BonusMapDescription_t *pMap )
  367. {
  368. int iFirstChildIndex = FindChildIndexByName( "ChallengeMedalOverview00" );
  369. for ( int iMedal = 0; iMedal < 5; ++iMedal )
  370. {
  371. Panel *pMedalImage = GetChild( iFirstChildIndex + iMedal );
  372. pMedalImage->SetVisible( false );
  373. }
  374. if ( !pMap || !pMap->m_pChallenges )
  375. {
  376. SetControlVisible( "ChallengeCommentLabel", false );
  377. SetControlVisible( "ChallengeEarnedMedal", false );
  378. SetControlVisible( "ChallengeBestLabel", false );
  379. SetControlVisible( "ChallengeNextMedal", false );
  380. SetControlVisible( "ChallengeNextLabel", false );
  381. return;
  382. }
  383. char szBuff[ 512 ];
  384. int iChallenge = GetSelectedChallenge();
  385. if ( iChallenge < 0 )
  386. {
  387. SetControlVisible( "ChallengeCommentLabel", false );
  388. SetControlVisible( "ChallengeEarnedMedal", false );
  389. SetControlVisible( "ChallengeBestLabel", false );
  390. SetControlVisible( "ChallengeNextMedal", false );
  391. SetControlVisible( "ChallengeNextLabel", false );
  392. int iFirstChildIndex = FindChildIndexByName( "ChallengeMedalOverview00" );
  393. for ( int iChallengeIndex = 0; iChallengeIndex < m_pChallengeSelection->GetItemCount(); ++iChallengeIndex )
  394. {
  395. KeyValues *pUserDataKey = m_pChallengeSelection->GetItemUserData( iChallengeIndex );
  396. int iChallengeNum = pUserDataKey->GetInt( "challenge" );
  397. if ( iChallengeNum >= 0 )
  398. {
  399. ChallengeDescription_t *pChallengeDescription = NULL;
  400. for ( int i = 0 ; i < pMap->m_pChallenges->Count(); ++i )
  401. {
  402. int iType = ((*pMap->m_pChallenges)[ i ]).iType;
  403. if ( iType == -1 )
  404. {
  405. iType = i;
  406. }
  407. if ( iType == iChallengeNum )
  408. pChallengeDescription = &((*pMap->m_pChallenges)[ i ]);
  409. }
  410. if ( pChallengeDescription )
  411. {
  412. int iBest, iEarnedMedal, iNext, iNextMedal;
  413. GetChallengeMedals( pChallengeDescription, iBest, iEarnedMedal, iNext, iNextMedal );
  414. if ( iChallengeNum < 10 )
  415. Q_snprintf( szBuff, 256, "medals/medal_0%i_%s", iChallengeNum, g_pszMedalNames[ iEarnedMedal ] );
  416. else
  417. Q_snprintf( szBuff, 256, "medals/medal_%i_%s", iChallengeNum, g_pszMedalNames[ iEarnedMedal ] );
  418. }
  419. CBitmapImagePanel *pBitmap = dynamic_cast<CBitmapImagePanel*>( GetChild( iFirstChildIndex + iChallengeNum ) );
  420. pBitmap->SetVisible( true );
  421. pBitmap->setTexture( szBuff );
  422. }
  423. }
  424. return;
  425. }
  426. ChallengeDescription_t *pChallengeDescription = NULL;
  427. for ( int i = 0 ; i < pMap->m_pChallenges->Count(); ++i )
  428. {
  429. int iType = ((*pMap->m_pChallenges)[ i ]).iType;
  430. if ( iType == -1 )
  431. {
  432. iType = i;
  433. }
  434. if ( iType == iChallenge )
  435. pChallengeDescription = &((*pMap->m_pChallenges)[ i ]);
  436. }
  437. if ( !pChallengeDescription )
  438. return;
  439. const char *pchChallengeComment = pChallengeDescription->szComment;
  440. int iBest, iEarnedMedal, iNext, iNextMedal;
  441. GetChallengeMedals( pChallengeDescription, iBest, iEarnedMedal, iNext, iNextMedal );
  442. // Set comment label
  443. SetControlString( "ChallengeCommentLabel", pchChallengeComment );
  444. SetControlVisible( "ChallengeCommentLabel", true );
  445. // Set earned medal
  446. if ( iEarnedMedal > -1 )
  447. {
  448. if ( iChallenge < 10 )
  449. Q_snprintf( szBuff, sizeof( szBuff ), "medals/medal_0%i_%s", iChallenge, g_pszMedalNames[ iEarnedMedal ] );
  450. else
  451. Q_snprintf( szBuff, sizeof( szBuff ), "medals/medal_%i_%s", iChallenge, g_pszMedalNames[ iEarnedMedal ] );
  452. CBitmapImagePanel *pBitmap = dynamic_cast<CBitmapImagePanel*>( FindChildByName( "ChallengeEarnedMedal" ) );
  453. pBitmap->SetVisible( true );
  454. pBitmap->setTexture( szBuff );
  455. }
  456. // Set next medal
  457. if ( iNextMedal > 0 )
  458. {
  459. if ( iChallenge < 10 )
  460. Q_snprintf( szBuff, sizeof( szBuff ), "medals/medal_0%i_%s", iChallenge, g_pszMedalNames[ iNextMedal ] );
  461. else
  462. Q_snprintf( szBuff, sizeof( szBuff ), "medals/medal_%i_%s", iChallenge, g_pszMedalNames[ iNextMedal ] );
  463. CBitmapImagePanel *pBitmap = dynamic_cast<CBitmapImagePanel*>( FindChildByName( "ChallengeNextMedal" ) );
  464. pBitmap->SetVisible( true );
  465. pBitmap->setTexture( szBuff );
  466. }
  467. else
  468. {
  469. SetControlVisible( "ChallengeNextMedal", false );
  470. }
  471. wchar_t szWideBuff[ 64 ];
  472. wchar_t szWideBuff2[ 64 ];
  473. // Best label
  474. if ( iBest != -1 )
  475. {
  476. Q_snprintf( szBuff, sizeof( szBuff ), "%i", iBest );
  477. g_pVGuiLocalize->ConvertANSIToUnicode( szBuff, szWideBuff2, sizeof( szWideBuff2 ) );
  478. g_pVGuiLocalize->ConstructString( szWideBuff, sizeof( szWideBuff ), g_pVGuiLocalize->Find( "#GameUI_BonusMapsBest" ), 1, szWideBuff2 );
  479. g_pVGuiLocalize->ConvertUnicodeToANSI( szWideBuff, szBuff, sizeof( szBuff ) );
  480. SetControlString( "ChallengeBestLabel", szBuff );
  481. SetControlVisible( "ChallengeBestLabel", true );
  482. }
  483. else
  484. SetControlVisible( "ChallengeBestLabel", false );
  485. // Next label
  486. if ( iNext != -1 )
  487. {
  488. Q_snprintf( szBuff, sizeof( szBuff ), "%i", iNext );
  489. g_pVGuiLocalize->ConvertANSIToUnicode( szBuff, szWideBuff2, sizeof( szWideBuff2 ) );
  490. g_pVGuiLocalize->ConstructString( szWideBuff, sizeof( szWideBuff ), g_pVGuiLocalize->Find( "#GameUI_BonusMapsGoal" ), 1, szWideBuff2 );
  491. g_pVGuiLocalize->ConvertUnicodeToANSI( szWideBuff, szBuff, sizeof( szBuff ) );
  492. SetControlString( "ChallengeNextLabel", szBuff );
  493. SetControlVisible( "ChallengeNextLabel", true );
  494. }
  495. else
  496. SetControlVisible( "ChallengeNextLabel", false );
  497. }
  498. void CBonusMapsDialog::RefreshCompletionPercentage( void )
  499. {
  500. float fPercentage = BonusMapsDatabase()->GetCompletionPercentage();
  501. if ( fPercentage > 0.0f )
  502. {
  503. char szBuff[ 256 ];
  504. if ( fPercentage * 100.0f < 1.0f )
  505. Q_snprintf( szBuff, 256, "%.2f%%", fPercentage * 100.0f ); // Show decimal places if less than 1%
  506. else
  507. Q_snprintf( szBuff, 256, "%.0f%%", fPercentage * 100.0f );
  508. SetControlString( "PercentageText", szBuff );
  509. SetControlVisible( "PercentageText", true );
  510. SetControlVisible( "CompletionText", true );
  511. // Blend the color from backround color 0% to selected color 100%
  512. Color cProgressBar = Color( static_cast<float>( m_PercentageBarBackgroundColor.r() ) * ( 1.0f - fPercentage ) + static_cast<float>( m_PercentageBarColor.r() ) * fPercentage,
  513. static_cast<float>( m_PercentageBarBackgroundColor.g() ) * ( 1.0f - fPercentage ) + static_cast<float>( m_PercentageBarColor.g() ) * fPercentage,
  514. static_cast<float>( m_PercentageBarBackgroundColor.b() ) * ( 1.0f - fPercentage ) + static_cast<float>( m_PercentageBarColor.b() ) * fPercentage,
  515. static_cast<float>( m_PercentageBarBackgroundColor.a() ) * ( 1.0f - fPercentage ) + static_cast<float>( m_PercentageBarColor.a() ) * fPercentage );
  516. m_pPercentageBar->SetFillColor( cProgressBar );
  517. m_pPercentageBar->SetWide( m_pPercentageBarBackground->GetWide() * fPercentage );
  518. SetControlVisible( "PercentageBarBackground", true );
  519. SetControlVisible( "PercentageBar", true );
  520. }
  521. else
  522. {
  523. // 0% complete so don't display
  524. SetControlVisible( "PercentageText", false );
  525. SetControlVisible( "CompletionText", false );
  526. SetControlVisible( "PercentageBarBackground", false );
  527. SetControlVisible( "PercentageBar", false );
  528. }
  529. }
  530. void CBonusMapsDialog::ApplySchemeSettings( IScheme *pScheme )
  531. {
  532. m_PercentageBarBackgroundColor = Color( 0, 0, 0, 64 );
  533. m_PercentageBarColor = pScheme->GetColor( "NewGame.SelectionColor", Color(255, 255, 255, 255) );
  534. BaseClass::ApplySchemeSettings( pScheme );
  535. }
  536. //-----------------------------------------------------------------------------
  537. // Purpose:
  538. //-----------------------------------------------------------------------------
  539. void CBonusMapsDialog::OnCommand( const char *command )
  540. {
  541. if ( !stricmp( command, "loadbonusmap" ) )
  542. {
  543. int mapIndex = GetSelectedItemBonusMapIndex();
  544. if ( BonusMapsDatabase()->IsValidIndex( mapIndex ) )
  545. {
  546. BonusMapDescription_t *pBonusMap = BonusMapsDatabase()->GetBonusData( mapIndex );
  547. // Don't do anything with locked items
  548. if ( pBonusMap->bLocked || ( m_pChallengeSelection->IsEnabled() && GetSelectedChallenge() == -1 ) )
  549. return;
  550. const char *shortName = pBonusMap->szShortName;
  551. if ( shortName && shortName[ 0 ] )
  552. {
  553. if ( pBonusMap->bIsFolder )
  554. {
  555. BonusMapsDatabase()->AppendPath( shortName );
  556. // repopulate list with current directory
  557. BuildMapsList();
  558. m_pGameList->MoveScrollBarToTop();
  559. }
  560. else
  561. {
  562. // Load the game, return to top and switch to engine
  563. char sz[ 256 ];
  564. // Set the challenge mode if one is selected
  565. int iChallenge = GetSelectedChallenge() + 1;
  566. if ( iChallenge > 0 )
  567. {
  568. Q_snprintf( sz, sizeof( sz ), "sv_bonus_challenge %i\n", iChallenge );
  569. engine->ClientCmd_Unrestricted( sz );
  570. ChallengeDescription_t *pChallengeDescription = &((*pBonusMap->m_pChallenges)[ iChallenge - 1 ]);
  571. // Set up medal goals
  572. BonusMapsDatabase()->SetCurrentChallengeObjectives( pChallengeDescription->iBronze, pChallengeDescription->iSilver, pChallengeDescription->iGold );
  573. BonusMapsDatabase()->SetCurrentChallengeNames( pBonusMap->szFileName, pBonusMap->szMapName, pChallengeDescription->szName );
  574. }
  575. if ( pBonusMap->szMapFileName[ 0 ] != '.' )
  576. {
  577. Q_snprintf( sz, sizeof( sz ), "map %s\n", pBonusMap->szMapFileName );
  578. }
  579. else
  580. {
  581. const char *pchSubDir = Q_strnchr( BonusMapsDatabase()->GetPath(), '/', Q_strlen( BonusMapsDatabase()->GetPath() ) );
  582. if ( pchSubDir )
  583. {
  584. pchSubDir = Q_strnchr( pchSubDir + 1, '/', Q_strlen( pchSubDir ) );
  585. if ( pchSubDir )
  586. {
  587. ++pchSubDir;
  588. const char *pchMapFileName = pBonusMap->szMapFileName + 2;
  589. Q_snprintf( sz, sizeof( sz ), "map %s/%s\n", pchSubDir, pchMapFileName );
  590. }
  591. }
  592. }
  593. engine->ClientCmd_Unrestricted( sz );
  594. // Close this dialog
  595. //OnClose();
  596. }
  597. }
  598. }
  599. }
  600. else if ( !stricmp( command, "back" ) )
  601. {
  602. BonusMapsDatabase()->BackPath();
  603. // repopulate list with current directory
  604. BuildMapsList();
  605. m_pChallengeSelection->RemoveAll();
  606. m_pChallengeSelection->AddItem( "<Select A Challenge>", new KeyValues( "ChallengeSelection", "challenge", -1 ) );
  607. RefreshDialog( NULL );
  608. m_pGameList->MoveScrollBarToTop();
  609. }
  610. else if ( !stricmp( command, "ImportBonusMaps" ) )
  611. {
  612. if ( m_hImportBonusMapsDialog == NULL )
  613. {
  614. m_hImportBonusMapsDialog = new FileOpenDialog( NULL, "#GameUI_ImportBonusMaps", true );
  615. m_hImportBonusMapsDialog->AddFilter( "*.bmz", "#GameUI_BMZ_Files", true );
  616. m_hImportBonusMapsDialog->AddActionSignalTarget( this );
  617. }
  618. m_hImportBonusMapsDialog->DoModal(false);
  619. m_hImportBonusMapsDialog->Activate();
  620. }
  621. else
  622. {
  623. BaseClass::OnCommand( command );
  624. }
  625. }
  626. //-----------------------------------------------------------------------------
  627. // Purpose: One item has been selected
  628. //-----------------------------------------------------------------------------
  629. void CBonusMapsDialog::OnPanelSelected()
  630. {
  631. CBonusMapPanel *pSelectedBonusMapPanel = (CBonusMapPanel *)m_pGameList->GetSelectedPanel();
  632. BonusMapDescription_t *pMap = BonusMapsDatabase()->GetBonusData( pSelectedBonusMapPanel->GetBonusMapListItemID() );
  633. SetControlString( "CommentLabel", pMap->szComment );
  634. // Handle challenge selection box
  635. int iNumChallenges = 0;
  636. if ( pMap->m_pChallenges )
  637. {
  638. // Get the name of the previously selected challenge so that we can select a matching challenge (if one exists)
  639. int iSelectedChallenge = GetSelectedChallenge();
  640. m_pChallengeSelection->RemoveAll();
  641. m_pChallengeSelection->AddItem( "<Select A Challenge>", new KeyValues( "ChallengeSelection", "challenge", -1 ) );
  642. int iFoundSimilar = 0;
  643. for ( iNumChallenges; iNumChallenges < pMap->m_pChallenges->Count(); ++iNumChallenges )
  644. {
  645. ChallengeDescription_t *pChallenge = &(*pMap->m_pChallenges)[ iNumChallenges ];
  646. int iType = iNumChallenges;
  647. // If the challenge type was specified then use that instead of (legacy) the order the challenges were listed
  648. if ( pChallenge->iType != -1 )
  649. iType = pChallenge->iType;
  650. m_pChallengeSelection->AddItem( pChallenge->szName, new KeyValues( "ChallengeSelection", "challenge", iType ) );
  651. if ( iSelectedChallenge == iNumChallenges )
  652. iFoundSimilar = iNumChallenges + 1;
  653. }
  654. m_pChallengeSelection->ActivateItemByRow( iFoundSimilar );
  655. }
  656. if ( iNumChallenges > 0 )
  657. {
  658. m_pChallengeSelection->SetEnabled( true );
  659. m_pChallengeSelection->SetVisible( true );
  660. m_pChallengeSelection->SetNumberOfEditLines( iNumChallenges + 1 );
  661. }
  662. else
  663. {
  664. m_pChallengeSelection->SetEnabled( false );
  665. m_pChallengeSelection->SetVisible( false );
  666. }
  667. RefreshDialog( pMap );
  668. }
  669. void CBonusMapsDialog::OnControlModified()
  670. {
  671. CBonusMapPanel *pSelectedBonusMapPanel = (CBonusMapPanel *)m_pGameList->GetSelectedPanel();
  672. BonusMapDescription_t *pMap = BonusMapsDatabase()->GetBonusData( pSelectedBonusMapPanel->GetBonusMapListItemID() );
  673. RefreshDialog( pMap );
  674. }
  675. // file selected. This can only happen when someone selects an image to be imported as a spray logo.
  676. void CBonusMapsDialog::OnFileSelected( const char *fullpath )
  677. {
  678. if ( fullpath == NULL || fullpath[ 0 ] == '\0' )
  679. return;
  680. // this can take a while, put up a waiting cursor
  681. surface()->SetCursor(dc_hourglass);
  682. ImportZippedBonusMaps( fullpath );
  683. // change the cursor back to normal
  684. surface()->SetCursor(dc_user);
  685. }