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.

448 lines
14 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. //=============================================================================//
  6. #include "cbase.h"
  7. #if defined( REPLAY_ENABLED )
  8. #include "replaybrowsermainpanel.h"
  9. #include "replaybrowserbasepage.h"
  10. #include "confirm_delete_dialog.h"
  11. #include "vgui_controls/PropertySheet.h"
  12. #include "vgui_controls/TextImage.h"
  13. #include "vgui/IInput.h"
  14. #include "vgui/ISurface.h"
  15. #include "ienginevgui.h"
  16. #include "replay/ireplaymanager.h"
  17. #include "replay/ireplaymoviemanager.h"
  18. #include "econ/econ_controls.h"
  19. // memdbgon must be the last include file in a .cpp file!!!
  20. #include <tier0/memdbgon.h>
  21. //-----------------------------------------------------------------------------
  22. // Purpose: Replay deletion confirmation dialog
  23. //-----------------------------------------------------------------------------
  24. class CConfirmDeleteReplayDialog : public CConfirmDeleteDialog
  25. {
  26. DECLARE_CLASS_SIMPLE( CConfirmDeleteReplayDialog, CConfirmDeleteDialog );
  27. public:
  28. CConfirmDeleteReplayDialog( Panel *pParent, IReplayItemManager *pItemManager, int iPerformance )
  29. : BaseClass( pParent )
  30. {
  31. m_pTextId = iPerformance >= 0 ? "#Replay_DeleteEditConfirm" : pItemManager->AreItemsMovies() ? "#Replay_DeleteMovieConfirm" : "#Replay_DeleteReplayConfirm";
  32. }
  33. const wchar_t *GetText()
  34. {
  35. return g_pVGuiLocalize->Find( m_pTextId );
  36. }
  37. const char *m_pTextId;
  38. };
  39. //-----------------------------------------------------------------------------
  40. // Purpose:
  41. //-----------------------------------------------------------------------------
  42. CReplayBrowserPanel::CReplayBrowserPanel( Panel *parent )
  43. : PropertyDialog(parent, "ReplayBrowser"),
  44. m_pConfirmDeleteDialog( NULL )
  45. {
  46. // Clear out delete info
  47. V_memset( &m_DeleteInfo, 0, sizeof( m_DeleteInfo ) );
  48. // Replay browser is parented to the game UI panel
  49. vgui::VPANEL gameuiPanel = enginevgui->GetPanel( PANEL_GAMEUIDLL );
  50. SetParent( gameuiPanel );
  51. SetMoveable( false );
  52. SetSizeable( false );
  53. vgui::HScheme scheme = vgui::scheme()->LoadSchemeFromFileEx( enginevgui->GetPanel( PANEL_CLIENTDLL ), "resource/ClientScheme.res", "ClientScheme");
  54. SetScheme(scheme);
  55. SetProportional( true );
  56. // Setup page
  57. m_pReplaysPage = new CReplayBrowserBasePage( this );
  58. m_pReplaysPage->AddActionSignalTarget( this );
  59. AddPage( m_pReplaysPage, "#Replay_MyReplays" );
  60. m_pReplaysPage->SetVisible( true );
  61. ListenForGameEvent( "gameui_hidden" );
  62. // Create this now, so that it can be the default button (if created in .res file, it fights with PropertyDialog's OkButton & generates asserts)
  63. CExButton *pCloseButton = new CExButton( this, "BackButton", "" );
  64. GetFocusNavGroup().SetDefaultButton(pCloseButton);
  65. m_flTimeOpened = 0.0f;
  66. }
  67. //-----------------------------------------------------------------------------
  68. // Purpose:
  69. //-----------------------------------------------------------------------------
  70. CReplayBrowserPanel::~CReplayBrowserPanel()
  71. {
  72. if ( m_pConfirmDeleteDialog )
  73. {
  74. m_pConfirmDeleteDialog->MarkForDeletion();
  75. }
  76. }
  77. //-----------------------------------------------------------------------------
  78. // Purpose:
  79. //-----------------------------------------------------------------------------
  80. void CReplayBrowserPanel::ApplySchemeSettings( vgui::IScheme *pScheme )
  81. {
  82. BaseClass::ApplySchemeSettings( pScheme );
  83. LoadControlSettings( "resource/ui/replaybrowser/mainpanel.res", "GAME" );
  84. SetOKButtonVisible(false);
  85. SetCancelButtonVisible(false);
  86. }
  87. //-----------------------------------------------------------------------------
  88. // Purpose:
  89. //-----------------------------------------------------------------------------
  90. void CReplayBrowserPanel::PerformLayout( void )
  91. {
  92. if ( GetVParent() )
  93. {
  94. int w,h;
  95. vgui::ipanel()->GetSize( GetVParent(), w, h );
  96. SetBounds(0,0,w,h);
  97. }
  98. BaseClass::PerformLayout();
  99. }
  100. //-----------------------------------------------------------------------------
  101. // Purpose:
  102. //-----------------------------------------------------------------------------
  103. void CReplayBrowserPanel::ShowPanel(bool bShow, ReplayHandle_t hReplayDetails/*=REPLAY_HANDLE_INVALID*/,
  104. int iPerformance/*=-1*/ )
  105. {
  106. if ( bShow )
  107. {
  108. GetPropertySheet()->SetActivePage( m_pReplaysPage );
  109. InvalidateLayout( false, true );
  110. Activate();
  111. m_flTimeOpened = gpGlobals->realtime;
  112. }
  113. else
  114. {
  115. PostMessage( m_pReplaysPage, new KeyValues("CancelSelection") );
  116. }
  117. SetVisible( bShow );
  118. m_pReplaysPage->SetVisible( bShow );
  119. if ( hReplayDetails != REPLAY_HANDLE_INVALID )
  120. {
  121. char szDetails[32];
  122. V_snprintf( szDetails, sizeof( szDetails ), "details%i_%i", (int)hReplayDetails, iPerformance );
  123. m_pReplaysPage->OnCommand( szDetails );
  124. }
  125. }
  126. //-----------------------------------------------------------------------------
  127. // Purpose:
  128. //-----------------------------------------------------------------------------
  129. void CReplayBrowserPanel::FireGameEvent( IGameEvent *event )
  130. {
  131. const char * type = event->GetName();
  132. if ( Q_strcmp(type, "gameui_hidden") == 0 )
  133. {
  134. ShowPanel( false );
  135. }
  136. }
  137. //-----------------------------------------------------------------------------
  138. // Purpose:
  139. //-----------------------------------------------------------------------------
  140. void CReplayBrowserPanel::OnCommand( const char *command )
  141. {
  142. if ( !Q_stricmp( command, "back" ) )
  143. {
  144. if ( m_pReplaysPage->IsDetailsViewOpen() )
  145. {
  146. m_pReplaysPage->DeleteDetailsPanelAndShowReplayList();
  147. }
  148. else
  149. {
  150. // Close the main panel
  151. ShowPanel( false );
  152. // TODO: Properly manage the browser so that we don't have to recreate it ever time its opened
  153. MarkForDeletion();
  154. // If we're connected to a game server, we also close the game UI.
  155. if ( engine->IsInGame() )
  156. {
  157. engine->ClientCmd_Unrestricted( "gameui_hide" );
  158. }
  159. }
  160. }
  161. BaseClass::OnCommand( command );
  162. }
  163. void CReplayBrowserPanel::OnKeyCodeTyped(vgui::KeyCode code)
  164. {
  165. if ( code == KEY_ESCAPE )
  166. {
  167. ShowPanel( false );
  168. }
  169. else
  170. {
  171. BaseClass::OnKeyCodeTyped( code );
  172. }
  173. }
  174. //-----------------------------------------------------------------------------
  175. // Purpose:
  176. //-----------------------------------------------------------------------------
  177. void CReplayBrowserPanel::OnKeyCodePressed(vgui::KeyCode code)
  178. {
  179. if ( GetBaseButtonCode( code ) == KEY_XBUTTON_B )
  180. {
  181. ShowPanel( false );
  182. }
  183. else if ( code == KEY_ENTER )
  184. {
  185. // do nothing, the default is to close the panel!
  186. }
  187. else
  188. {
  189. BaseClass::OnKeyCodePressed( code );
  190. }
  191. }
  192. //-----------------------------------------------------------------------------
  193. // Purpose:
  194. //-----------------------------------------------------------------------------
  195. void CReplayBrowserPanel::ShowDeleteReplayDenialDlg()
  196. {
  197. ShowMessageBox( "#Replay_DeleteDenialTitle", "#Replay_DeleteDenialText", "#GameUI_OK" );
  198. }
  199. //-----------------------------------------------------------------------------
  200. // Purpose:
  201. //-----------------------------------------------------------------------------
  202. void CReplayBrowserPanel::AttemptToDeleteReplayItem( Panel *pHandler, ReplayItemHandle_t hReplayItem,
  203. IReplayItemManager *pItemManager, int iPerformance )
  204. {
  205. IQueryableReplayItem *pItem = pItemManager->GetItem( hReplayItem );
  206. CGenericClassBasedReplay *pReplay = ToGenericClassBasedReplay( pItem->GetItemReplay() );
  207. // If this is an actual replay the user is trying to delete, only allow it
  208. // if the replay says it's OK. Don't execute this code for performances.
  209. if ( !pItemManager->AreItemsMovies() && iPerformance < 0 && !pReplay->ShouldAllowDelete() )
  210. {
  211. ShowDeleteReplayDenialDlg();
  212. return;
  213. }
  214. // Otherwise, show the confirm delete dlg
  215. vgui::surface()->PlaySound( "replay\\replaydialog_warn.wav" );
  216. ConfirmReplayItemDelete( pHandler, hReplayItem, pItemManager, iPerformance );
  217. }
  218. //-----------------------------------------------------------------------------
  219. // Purpose:
  220. //-----------------------------------------------------------------------------
  221. void CReplayBrowserPanel::ConfirmReplayItemDelete( Panel *pHandler, ReplayItemHandle_t hReplayItem,
  222. IReplayItemManager *pItemManager, int iPerformance )
  223. {
  224. CConfirmDeleteReplayDialog *pConfirm = vgui::SETUP_PANEL( new CConfirmDeleteReplayDialog( this, pItemManager, iPerformance ) );
  225. if ( pConfirm )
  226. {
  227. // Cache replay and handler for later
  228. m_DeleteInfo.m_hReplayItem = hReplayItem;
  229. m_DeleteInfo.m_pItemManager = pItemManager;
  230. m_DeleteInfo.m_hHandler = pHandler->GetVPanel();
  231. m_DeleteInfo.m_iPerformance = iPerformance;
  232. // Display the panel!
  233. pConfirm->Show();
  234. // Cache confirm dialog ptr
  235. m_pConfirmDeleteDialog = pConfirm;
  236. }
  237. }
  238. //-----------------------------------------------------------------------------
  239. // Purpose:
  240. //-----------------------------------------------------------------------------
  241. void CReplayBrowserPanel::OnConfirmDelete( KeyValues *data )
  242. {
  243. // Clear confirm ptr
  244. m_pConfirmDeleteDialog = NULL;
  245. // User confirmed delete?
  246. int nConfirmed = data->GetInt( "confirmed", 0 );
  247. if ( !nConfirmed )
  248. return;
  249. // Get the replay from the dialog
  250. ReplayItemHandle_t hReplayItem = m_DeleteInfo.m_hReplayItem;
  251. // Post actions signal to the handler
  252. KeyValues *pMsg = new KeyValues( "ReplayItemDeleted" );
  253. pMsg->SetInt( "replayitem", (int)hReplayItem );
  254. pMsg->SetInt( "perf", m_DeleteInfo.m_iPerformance );
  255. PostMessage( m_DeleteInfo.m_hHandler, pMsg );
  256. // Delete actual replay item
  257. if ( m_DeleteInfo.m_iPerformance < 0 )
  258. {
  259. // Cleanup UI related to the replay/movie
  260. CleanupUIForReplayItem( hReplayItem );
  261. // Delete the replay/movie
  262. m_DeleteInfo.m_pItemManager->DeleteItem( GetActivePage(), hReplayItem, false );
  263. }
  264. vgui::surface()->PlaySound( "replay\\deleted_take.wav" );
  265. // Clear delete info
  266. V_memset( &m_DeleteInfo, 0, sizeof( m_DeleteInfo ) );
  267. }
  268. //-----------------------------------------------------------------------------
  269. // Purpose:
  270. //-----------------------------------------------------------------------------
  271. void CReplayBrowserPanel::OnSaveReplay( ReplayHandle_t hNewReplay )
  272. {
  273. // Verify that the handle is valid
  274. Assert( g_pReplayManager->GetReplay( hNewReplay ) );
  275. m_pReplaysPage->AddReplay( hNewReplay );
  276. m_pReplaysPage->Repaint();
  277. }
  278. //-----------------------------------------------------------------------------
  279. // Purpose:
  280. //-----------------------------------------------------------------------------
  281. void CReplayBrowserPanel::OnDeleteReplay( ReplayHandle_t hDeletedReplay )
  282. {
  283. // Verify that the handle is valid
  284. Assert( g_pReplayManager->GetReplay( hDeletedReplay ) );
  285. DeleteReplay( hDeletedReplay );
  286. }
  287. //-----------------------------------------------------------------------------
  288. // Purpose:
  289. //-----------------------------------------------------------------------------
  290. void CReplayBrowserPanel::DeleteReplay( ReplayHandle_t hReplay )
  291. {
  292. m_pReplaysPage->DeleteReplay( hReplay );
  293. }
  294. //-----------------------------------------------------------------------------
  295. // Purpose:
  296. //-----------------------------------------------------------------------------
  297. void CReplayBrowserPanel::CleanupUIForReplayItem( ReplayItemHandle_t hReplayItem )
  298. {
  299. if ( GetActivePage() == m_pReplaysPage )
  300. {
  301. m_pReplaysPage->CleanupUIForReplayItem( hReplayItem );
  302. }
  303. }
  304. static vgui::DHANDLE<CReplayBrowserPanel> g_ReplayBrowserPanel;
  305. //-----------------------------------------------------------------------------
  306. // Purpose:
  307. //-----------------------------------------------------------------------------
  308. CReplayBrowserPanel *ReplayUI_OpenReplayBrowserPanel( ReplayHandle_t hReplayDetails,
  309. int iPerformance )
  310. {
  311. if ( !g_ReplayBrowserPanel.Get() )
  312. {
  313. g_ReplayBrowserPanel = vgui::SETUP_PANEL( new CReplayBrowserPanel( NULL ) );
  314. g_ReplayBrowserPanel->InvalidateLayout( false, true );
  315. }
  316. engine->ClientCmd_Unrestricted( "gameui_activate" );
  317. g_ReplayBrowserPanel->ShowPanel( true, hReplayDetails, iPerformance );
  318. extern IReplayMovieManager *g_pReplayMovieManager;
  319. if ( g_pReplayMovieManager->GetMovieCount() > 0 )
  320. {
  321. // Fire a message the game DLL can intercept (for achievements, etc).
  322. IGameEvent *event = gameeventmanager->CreateEvent( "browse_replays" );
  323. if ( event )
  324. {
  325. gameeventmanager->FireEventClientSide( event );
  326. }
  327. }
  328. return g_ReplayBrowserPanel;
  329. }
  330. //-----------------------------------------------------------------------------
  331. // Purpose:
  332. //-----------------------------------------------------------------------------
  333. CReplayBrowserPanel *ReplayUI_GetBrowserPanel( void )
  334. {
  335. return g_ReplayBrowserPanel.Get();
  336. }
  337. //-----------------------------------------------------------------------------
  338. // Purpose:
  339. //-----------------------------------------------------------------------------
  340. void ReplayUI_CloseReplayBrowser()
  341. {
  342. if ( g_ReplayBrowserPanel )
  343. {
  344. g_ReplayBrowserPanel->MarkForDeletion();
  345. g_ReplayBrowserPanel = NULL;
  346. }
  347. }
  348. //-----------------------------------------------------------------------------
  349. // Purpose:
  350. //-----------------------------------------------------------------------------
  351. void ReplayUI_ReloadBrowser( ReplayHandle_t hReplay/*=REPLAY_HANDLE_INVALID*/,
  352. int iPerformance/*=-1*/ )
  353. {
  354. delete g_ReplayBrowserPanel.Get();
  355. g_ReplayBrowserPanel = NULL;
  356. ReplayUI_OpenReplayBrowserPanel( hReplay, iPerformance );
  357. }
  358. //-----------------------------------------------------------------------------
  359. // Purpose:
  360. //-----------------------------------------------------------------------------
  361. CON_COMMAND_F( open_replaybrowser, "Open the replay browser.", FCVAR_CLIENTDLL )
  362. {
  363. ReplayUI_OpenReplayBrowserPanel( REPLAY_HANDLE_INVALID, -1 );
  364. g_ReplayBrowserPanel->InvalidateLayout( false, true );
  365. }
  366. //-----------------------------------------------------------------------------
  367. // Purpose:
  368. //-----------------------------------------------------------------------------
  369. CON_COMMAND_F( replay_reloadbrowser, "Reloads replay data and display replay browser", FCVAR_CLIENTDLL | FCVAR_CLIENTCMD_CAN_EXECUTE )
  370. {
  371. ReplayUI_ReloadBrowser();
  372. }
  373. //-----------------------------------------------------------------------------
  374. // Purpose:
  375. //-----------------------------------------------------------------------------
  376. CON_COMMAND_F( replay_hidebrowser, "Hides replay browser", FCVAR_CLIENTDLL )
  377. {
  378. ReplayUI_CloseReplayBrowser();
  379. }
  380. #endif