Team Fortress 2 Source Code as on 22/4/2020
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.

411 lines
12 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. // $NoKeywords: $
  6. //===========================================================================//
  7. #include "LoadCommentaryDialog.h"
  8. #include "EngineInterface.h"
  9. #include "IGameUIFuncs.h"
  10. #include "vgui/ISystem.h"
  11. #include "vgui/IVGui.h"
  12. #include "tier1/KeyValues.h"
  13. #include "tier1/convar.h"
  14. #include "filesystem.h"
  15. #include "vgui_controls/PanelListPanel.h"
  16. #include "vgui_controls/Label.h"
  17. #include "vgui_controls/ImagePanel.h"
  18. #include "vgui_controls/Button.h"
  19. #include "vgui_controls/Button.h"
  20. #include "vgui_controls/PanelListPanel.h"
  21. #include "vgui_controls/QueryBox.h"
  22. #include <stdio.h>
  23. #include <stdlib.h>
  24. #include "BasePanel.h"
  25. #include "GameUI_Interface.h"
  26. #include "MouseMessageForwardingPanel.h"
  27. #include "TGAImagePanel.h"
  28. // memdbgon must be the last include file in a .cpp file!!!
  29. #include "tier0/memdbgon.h"
  30. using namespace vgui;
  31. void OpenLoadCommentaryDialog( void )
  32. {
  33. DHANDLE<CLoadCommentaryDialog> hCommentaryDialog;
  34. if ( !hCommentaryDialog.Get() )
  35. {
  36. hCommentaryDialog = new CLoadCommentaryDialog( BasePanel() );
  37. }
  38. GameUI().ActivateGameUI();
  39. hCommentaryDialog->Activate();
  40. }
  41. //-----------------------------------------------------------------------------
  42. // Purpose:
  43. //-----------------------------------------------------------------------------
  44. void CC_LoadCommentary_Test( void )
  45. {
  46. OpenLoadCommentaryDialog();
  47. }
  48. static ConCommand commentary_testfirstrun("loadcommentary", CC_LoadCommentary_Test, 0 );
  49. //-----------------------------------------------------------------------------
  50. // Purpose: Describes the layout of a commentary map list item
  51. //-----------------------------------------------------------------------------
  52. class CCommentaryItemPanel : public vgui::EditablePanel
  53. {
  54. DECLARE_CLASS_SIMPLE( CCommentaryItemPanel, vgui::EditablePanel );
  55. public:
  56. CCommentaryItemPanel( PanelListPanel *parent, const char *name, int iListItemID ) : BaseClass( parent, name )
  57. {
  58. m_iListItemID = iListItemID;
  59. m_pParent = parent;
  60. m_pCommentaryScreenshot = new CTGAImagePanel( this, "CommentaryMapScreenshot" );
  61. m_pCommentaryScreenshotBackground = new ImagePanel( this, "CommentaryScreenshotBackground" );
  62. // map name
  63. m_pMapNameLabel = new Label( this, "MapName", "" );
  64. // description
  65. m_pDescriptionLabel = new Label( this, "Description", "" );
  66. CMouseMessageForwardingPanel *panel = new CMouseMessageForwardingPanel(this, NULL);
  67. panel->SetZPos(2);
  68. SetSize( 200, 140 );
  69. LoadControlSettings( "resource/CommentaryItem.res" );
  70. m_FillColor = m_pCommentaryScreenshotBackground->GetFillColor();
  71. }
  72. void SetCommentaryInfo( CommentaryItem_t &item )
  73. {
  74. // set the bitmap to display
  75. char tga[_MAX_PATH];
  76. Q_strncpy( tga, item.szMapFileName, sizeof(tga) );
  77. char *ext = strstr( tga, ".txt" );
  78. if ( ext )
  79. {
  80. strcpy( ext, ".tga" );
  81. }
  82. m_pCommentaryScreenshot->SetTGA( tga );
  83. // set the title text
  84. m_pMapNameLabel->SetText( item.szPrintName );
  85. m_pDescriptionLabel->SetText( item.szDescription );
  86. }
  87. MESSAGE_FUNC_INT( OnPanelSelected, "PanelSelected", state )
  88. {
  89. if ( state )
  90. {
  91. // set the text color to be orange, and the pic border to be orange
  92. m_pCommentaryScreenshotBackground->SetFillColor( m_SelectedColor );
  93. m_pMapNameLabel->SetFgColor( m_SelectedColor );
  94. m_pDescriptionLabel->SetFgColor( m_SelectedColor );
  95. }
  96. else
  97. {
  98. m_pCommentaryScreenshotBackground->SetFillColor( m_FillColor );
  99. m_pMapNameLabel->SetFgColor( m_TextColor );
  100. m_pDescriptionLabel->SetFgColor( m_TextColor );
  101. }
  102. PostMessage( m_pParent->GetVParent(), new KeyValues("PanelSelected") );
  103. }
  104. virtual void OnMousePressed( vgui::MouseCode code )
  105. {
  106. m_pParent->SetSelectedPanel( this );
  107. }
  108. virtual void ApplySchemeSettings( IScheme *pScheme )
  109. {
  110. m_TextColor = pScheme->GetColor( "NewGame.TextColor", Color(255, 255, 255, 255) );
  111. m_SelectedColor = pScheme->GetColor( "NewGame.SelectionColor", Color(255, 255, 255, 255) );
  112. BaseClass::ApplySchemeSettings( pScheme );
  113. }
  114. virtual void OnMouseDoublePressed( vgui::MouseCode code )
  115. {
  116. // call the panel
  117. OnMousePressed( code );
  118. PostMessage( m_pParent->GetParent(), new KeyValues("Command", "command", "loadcommentary") );
  119. }
  120. int GetListItemID()
  121. {
  122. return m_iListItemID;
  123. }
  124. private:
  125. vgui::PanelListPanel *m_pParent;
  126. vgui::Label *m_pMapNameLabel;
  127. vgui::Label *m_pDescriptionLabel;
  128. CTGAImagePanel *m_pCommentaryScreenshot;
  129. ImagePanel *m_pCommentaryScreenshotBackground;
  130. Color m_TextColor, m_FillColor, m_SelectedColor;
  131. int m_iListItemID;
  132. };
  133. //-----------------------------------------------------------------------------
  134. // Purpose:Constructor
  135. //-----------------------------------------------------------------------------
  136. CLoadCommentaryDialog::CLoadCommentaryDialog(vgui::Panel *parent) : BaseClass(parent, "LoadCommentaryDialog")
  137. {
  138. SetDeleteSelfOnClose(true);
  139. SetBounds(0, 0, 512, 384);
  140. SetMinimumSize( 256, 300 );
  141. SetSizeable( true );
  142. SetTitle("#GameUI_LoadCommentary", true);
  143. vgui::Button *cancel = new vgui::Button( this, "Cancel", "#GameUI_Cancel" );
  144. cancel->SetCommand( "Close" );
  145. CreateCommentaryItemList();
  146. new vgui::Button( this, "loadcommentary", "" );
  147. SetControlEnabled( "loadcommentary", false );
  148. LoadControlSettings("resource/LoadCommentaryDialog.res");
  149. // Look for commentary .txt files in the map directory
  150. ScanCommentaryFiles();
  151. }
  152. //-----------------------------------------------------------------------------
  153. // Purpose:
  154. //-----------------------------------------------------------------------------
  155. void CLoadCommentaryDialog::OnCommand( const char *command )
  156. {
  157. if ( !Q_stricmp( command, "loadcommentary" ) )
  158. {
  159. int itemIndex = GetSelectedItemIndex();
  160. if ( m_CommentaryItems.IsValidIndex(itemIndex) )
  161. {
  162. const char *mapName = m_CommentaryItems[itemIndex].szMapName;
  163. if ( mapName && mapName[ 0 ] )
  164. {
  165. // Load the game, return to top and switch to engine
  166. char sz[ 256 ];
  167. Q_snprintf(sz, sizeof( sz ), "progress_enable\ncommentary 1\nmap %s\n", mapName );
  168. // Close this dialog
  169. OnClose();
  170. engine->ClientCmd_Unrestricted( sz );
  171. }
  172. }
  173. }
  174. else
  175. {
  176. BaseClass::OnCommand( command );
  177. }
  178. }
  179. void CLoadCommentaryDialog::OnKeyCodePressed( vgui::KeyCode code )
  180. {
  181. if ( code == KEY_XBUTTON_A || code == STEAMCONTROLLER_A )
  182. {
  183. OnCommand( "loadcommentary" );
  184. return;
  185. }
  186. else if ( code == KEY_XBUTTON_B )
  187. {
  188. OnCommand( "Close" );
  189. return;
  190. }
  191. BaseClass::OnKeyCodePressed(code);
  192. }
  193. //-----------------------------------------------------------------------------
  194. // Purpose: Creates the load game display list
  195. //-----------------------------------------------------------------------------
  196. void CLoadCommentaryDialog::CreateCommentaryItemList()
  197. {
  198. m_pGameList = new vgui::PanelListPanel( this, "listpanel_commentary" );
  199. m_pGameList->SetFirstColumnWidth( 0 );
  200. }
  201. //-----------------------------------------------------------------------------
  202. // Purpose: returns the save file name of the selected item
  203. //-----------------------------------------------------------------------------
  204. int CLoadCommentaryDialog::GetSelectedItemIndex()
  205. {
  206. CCommentaryItemPanel *panel = dynamic_cast<CCommentaryItemPanel *>(m_pGameList->GetSelectedPanel());
  207. if ( panel )
  208. {
  209. // find the panel in the list
  210. for ( int i = 0; i < m_CommentaryItems.Count(); i++ )
  211. {
  212. if ( i == panel->GetListItemID() )
  213. {
  214. return i;
  215. }
  216. }
  217. }
  218. return m_CommentaryItems.InvalidIndex();
  219. }
  220. //-----------------------------------------------------------------------------
  221. // Purpose: builds save game list from directory
  222. //-----------------------------------------------------------------------------
  223. void CLoadCommentaryDialog::ScanCommentaryFiles()
  224. {
  225. // populate list box with all saved games on record:
  226. char szDirectory[_MAX_PATH];
  227. Q_snprintf( szDirectory, sizeof( szDirectory ), "maps/*commentary.txt" );
  228. // clear the current list
  229. m_pGameList->DeleteAllItems();
  230. m_CommentaryItems.RemoveAll();
  231. // iterate the files
  232. FileFindHandle_t handle;
  233. const char *pFileName = g_pFullFileSystem->FindFirst( szDirectory, &handle );
  234. while (pFileName)
  235. {
  236. char szFileName[_MAX_PATH];
  237. Q_snprintf(szFileName, sizeof( szFileName ), "maps/%s", pFileName);
  238. // Only load save games from the current mod's save dir
  239. if( !g_pFullFileSystem->FileExists( szFileName, "MOD" ) )
  240. {
  241. pFileName = g_pFullFileSystem->FindNext( handle );
  242. continue;
  243. }
  244. ParseCommentaryFile( szFileName, pFileName );
  245. pFileName = g_pFullFileSystem->FindNext( handle );
  246. }
  247. g_pFullFileSystem->FindClose( handle );
  248. // sort the save list
  249. qsort( m_CommentaryItems.Base(), m_CommentaryItems.Count(), sizeof(CommentaryItem_t), &SaveGameSortFunc );
  250. // add to the list
  251. for ( int saveIndex = 0; saveIndex < m_CommentaryItems.Count() && saveIndex < MAX_LISTED_COMMENTARY_ITEMS; saveIndex++ )
  252. {
  253. // add the item to the panel
  254. AddCommentaryItemToList( saveIndex );
  255. }
  256. // display a message if there are no save games
  257. if ( !m_CommentaryItems.Count() )
  258. {
  259. vgui::Label *pNoCommentaryItemsLabel = SETUP_PANEL(new Label(m_pGameList, "NoCommentaryItemsLabel", "#GameUI_NoCommentaryItemsToDisplay"));
  260. pNoCommentaryItemsLabel->SetTextColorState(vgui::Label::CS_DULL);
  261. m_pGameList->AddItem( NULL, pNoCommentaryItemsLabel );
  262. }
  263. SetControlEnabled( "loadcommentary", false );
  264. }
  265. //-----------------------------------------------------------------------------
  266. // Purpose: Adds an item to the list
  267. //-----------------------------------------------------------------------------
  268. void CLoadCommentaryDialog::AddCommentaryItemToList( int itemIndex )
  269. {
  270. // create the new panel and add to the list
  271. CCommentaryItemPanel *commentaryItemPanel = new CCommentaryItemPanel( m_pGameList, "CommentaryItemPanel", itemIndex );
  272. commentaryItemPanel->SetCommentaryInfo( m_CommentaryItems[itemIndex] );
  273. m_pGameList->AddItem( NULL, commentaryItemPanel );
  274. }
  275. //-----------------------------------------------------------------------------
  276. // Purpose: Parses the save game info out of the .sav file header
  277. //-----------------------------------------------------------------------------
  278. void CLoadCommentaryDialog::ParseCommentaryFile( char const *pszFileName, char const *pszShortName )
  279. {
  280. if ( !pszFileName || !pszShortName )
  281. return;
  282. // load the file as keyvalues
  283. KeyValues *pData = new KeyValues( "commentary_data" );
  284. if ( false == pData->LoadFromFile( g_pFullFileSystem, pszFileName, "MOD" ) )
  285. {
  286. pData->deleteThis();
  287. return;
  288. }
  289. // walk the platform menu loading all the interfaces
  290. KeyValues *menuKeys = pData->FindKey("trackinfo", false);
  291. if ( menuKeys )
  292. {
  293. for (KeyValues *track = menuKeys->GetFirstSubKey(); track != NULL; track = track->GetNextKey())
  294. {
  295. //Msg( "track found: %s %s\n", track->GetString("map", "?"), track->GetString( "description", "asdf" ) );
  296. CommentaryItem_t item;
  297. Q_strncpy( item.szMapFileName, pszFileName, sizeof(item.szMapFileName) );
  298. Q_strncpy( item.szMapName, track->GetString( "map", "" ), sizeof(item.szMapName) );
  299. Q_strncpy( item.szPrintName, track->GetString( "printname", "" ), sizeof(item.szPrintName) );
  300. Q_strncpy( item.szDescription, track->GetString( "description", "" ), sizeof(item.szDescription) );
  301. //item.iChannel = track->GetInt( "channel" );
  302. m_CommentaryItems.AddToTail( item );
  303. }
  304. }
  305. else
  306. {
  307. CommentaryItem_t item;
  308. Q_strncpy( item.szMapFileName, pszFileName, sizeof(item.szMapFileName) );
  309. char mapname[_MAX_PATH];
  310. Q_strncpy( mapname, pszFileName, sizeof(item.szMapName) );
  311. char *ext = strstr( mapname, "_commentary" );
  312. if ( !ext )
  313. return;
  314. *ext = '\0';
  315. Q_FileBase( mapname, item.szMapName, sizeof(item.szMapName) );
  316. Q_strncpy( item.szPrintName, "No trackinfo found.", sizeof(item.szPrintName) );
  317. Q_strncpy( item.szDescription, "No trackinfo found.", sizeof(item.szDescription) );
  318. m_CommentaryItems.AddToTail( item );
  319. }
  320. return;
  321. }
  322. //-----------------------------------------------------------------------------
  323. // Purpose: timestamp sort function for savegames
  324. //-----------------------------------------------------------------------------
  325. int CLoadCommentaryDialog::SaveGameSortFunc( const void *lhs, const void *rhs )
  326. {
  327. // Sort by map name
  328. const CommentaryItem_t *s1 = (const CommentaryItem_t *)lhs;
  329. const CommentaryItem_t *s2 = (const CommentaryItem_t *)rhs;
  330. return Q_stricmp( s1->szPrintName, s2->szPrintName );
  331. }
  332. //-----------------------------------------------------------------------------
  333. // Purpose: One item has been selected
  334. //-----------------------------------------------------------------------------
  335. void CLoadCommentaryDialog::OnPanelSelected()
  336. {
  337. SetControlEnabled( "loadcommentary", true );
  338. }