//========= Copyright Valve Corporation, All rights reserved. ============// // // Purpose: // //=============================================================================// #include "cbase.h" #if defined( REPLAY_ENABLED ) #include "replaybrowsermainpanel.h" #include "replaybrowserbasepage.h" #include "confirm_delete_dialog.h" #include "vgui_controls/PropertySheet.h" #include "vgui_controls/TextImage.h" #include "vgui/IInput.h" #include "vgui/ISurface.h" #include "ienginevgui.h" #include "replay/ireplaymanager.h" #include "replay/ireplaymoviemanager.h" #include "econ/econ_controls.h" // memdbgon must be the last include file in a .cpp file!!! #include //----------------------------------------------------------------------------- // Purpose: Replay deletion confirmation dialog //----------------------------------------------------------------------------- class CConfirmDeleteReplayDialog : public CConfirmDeleteDialog { DECLARE_CLASS_SIMPLE( CConfirmDeleteReplayDialog, CConfirmDeleteDialog ); public: CConfirmDeleteReplayDialog( Panel *pParent, IReplayItemManager *pItemManager, int iPerformance ) : BaseClass( pParent ) { m_pTextId = iPerformance >= 0 ? "#Replay_DeleteEditConfirm" : pItemManager->AreItemsMovies() ? "#Replay_DeleteMovieConfirm" : "#Replay_DeleteReplayConfirm"; } const wchar_t *GetText() { return g_pVGuiLocalize->Find( m_pTextId ); } const char *m_pTextId; }; //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- CReplayBrowserPanel::CReplayBrowserPanel( Panel *parent ) : PropertyDialog(parent, "ReplayBrowser"), m_pConfirmDeleteDialog( NULL ) { // Clear out delete info V_memset( &m_DeleteInfo, 0, sizeof( m_DeleteInfo ) ); // Replay browser is parented to the game UI panel vgui::VPANEL gameuiPanel = enginevgui->GetPanel( PANEL_GAMEUIDLL ); SetParent( gameuiPanel ); SetMoveable( false ); SetSizeable( false ); vgui::HScheme scheme = vgui::scheme()->LoadSchemeFromFileEx( enginevgui->GetPanel( PANEL_CLIENTDLL ), "resource/ClientScheme.res", "ClientScheme"); SetScheme(scheme); SetProportional( true ); // Setup page m_pReplaysPage = new CReplayBrowserBasePage( this ); m_pReplaysPage->AddActionSignalTarget( this ); AddPage( m_pReplaysPage, "#Replay_MyReplays" ); m_pReplaysPage->SetVisible( true ); ListenForGameEvent( "gameui_hidden" ); // Create this now, so that it can be the default button (if created in .res file, it fights with PropertyDialog's OkButton & generates asserts) CExButton *pCloseButton = new CExButton( this, "BackButton", "" ); GetFocusNavGroup().SetDefaultButton(pCloseButton); m_flTimeOpened = 0.0f; } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- CReplayBrowserPanel::~CReplayBrowserPanel() { if ( m_pConfirmDeleteDialog ) { m_pConfirmDeleteDialog->MarkForDeletion(); } } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CReplayBrowserPanel::ApplySchemeSettings( vgui::IScheme *pScheme ) { BaseClass::ApplySchemeSettings( pScheme ); LoadControlSettings( "resource/ui/replaybrowser/mainpanel.res", "GAME" ); SetOKButtonVisible(false); SetCancelButtonVisible(false); } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CReplayBrowserPanel::PerformLayout( void ) { if ( GetVParent() ) { int w,h; vgui::ipanel()->GetSize( GetVParent(), w, h ); SetBounds(0,0,w,h); } BaseClass::PerformLayout(); } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CReplayBrowserPanel::ShowPanel(bool bShow, ReplayHandle_t hReplayDetails/*=REPLAY_HANDLE_INVALID*/, int iPerformance/*=-1*/ ) { if ( bShow ) { GetPropertySheet()->SetActivePage( m_pReplaysPage ); InvalidateLayout( false, true ); Activate(); m_flTimeOpened = gpGlobals->realtime; } else { PostMessage( m_pReplaysPage, new KeyValues("CancelSelection") ); } SetVisible( bShow ); m_pReplaysPage->SetVisible( bShow ); if ( hReplayDetails != REPLAY_HANDLE_INVALID ) { char szDetails[32]; V_snprintf( szDetails, sizeof( szDetails ), "details%i_%i", (int)hReplayDetails, iPerformance ); m_pReplaysPage->OnCommand( szDetails ); } } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CReplayBrowserPanel::FireGameEvent( IGameEvent *event ) { const char * type = event->GetName(); if ( Q_strcmp(type, "gameui_hidden") == 0 ) { ShowPanel( false ); } } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CReplayBrowserPanel::OnCommand( const char *command ) { if ( !Q_stricmp( command, "back" ) ) { if ( m_pReplaysPage->IsDetailsViewOpen() ) { m_pReplaysPage->DeleteDetailsPanelAndShowReplayList(); } else { // Close the main panel ShowPanel( false ); // TODO: Properly manage the browser so that we don't have to recreate it ever time its opened MarkForDeletion(); // If we're connected to a game server, we also close the game UI. if ( engine->IsInGame() ) { engine->ClientCmd_Unrestricted( "gameui_hide" ); } } } BaseClass::OnCommand( command ); } void CReplayBrowserPanel::OnKeyCodeTyped(vgui::KeyCode code) { if ( code == KEY_ESCAPE ) { ShowPanel( false ); } else { BaseClass::OnKeyCodeTyped( code ); } } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CReplayBrowserPanel::OnKeyCodePressed(vgui::KeyCode code) { if ( GetBaseButtonCode( code ) == KEY_XBUTTON_B ) { ShowPanel( false ); } else if ( code == KEY_ENTER ) { // do nothing, the default is to close the panel! } else { BaseClass::OnKeyCodePressed( code ); } } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CReplayBrowserPanel::ShowDeleteReplayDenialDlg() { ShowMessageBox( "#Replay_DeleteDenialTitle", "#Replay_DeleteDenialText", "#GameUI_OK" ); } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CReplayBrowserPanel::AttemptToDeleteReplayItem( Panel *pHandler, ReplayItemHandle_t hReplayItem, IReplayItemManager *pItemManager, int iPerformance ) { IQueryableReplayItem *pItem = pItemManager->GetItem( hReplayItem ); CGenericClassBasedReplay *pReplay = ToGenericClassBasedReplay( pItem->GetItemReplay() ); // If this is an actual replay the user is trying to delete, only allow it // if the replay says it's OK. Don't execute this code for performances. if ( !pItemManager->AreItemsMovies() && iPerformance < 0 && !pReplay->ShouldAllowDelete() ) { ShowDeleteReplayDenialDlg(); return; } // Otherwise, show the confirm delete dlg vgui::surface()->PlaySound( "replay\\replaydialog_warn.wav" ); ConfirmReplayItemDelete( pHandler, hReplayItem, pItemManager, iPerformance ); } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CReplayBrowserPanel::ConfirmReplayItemDelete( Panel *pHandler, ReplayItemHandle_t hReplayItem, IReplayItemManager *pItemManager, int iPerformance ) { CConfirmDeleteReplayDialog *pConfirm = vgui::SETUP_PANEL( new CConfirmDeleteReplayDialog( this, pItemManager, iPerformance ) ); if ( pConfirm ) { // Cache replay and handler for later m_DeleteInfo.m_hReplayItem = hReplayItem; m_DeleteInfo.m_pItemManager = pItemManager; m_DeleteInfo.m_hHandler = pHandler->GetVPanel(); m_DeleteInfo.m_iPerformance = iPerformance; // Display the panel! pConfirm->Show(); // Cache confirm dialog ptr m_pConfirmDeleteDialog = pConfirm; } } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CReplayBrowserPanel::OnConfirmDelete( KeyValues *data ) { // Clear confirm ptr m_pConfirmDeleteDialog = NULL; // User confirmed delete? int nConfirmed = data->GetInt( "confirmed", 0 ); if ( !nConfirmed ) return; // Get the replay from the dialog ReplayItemHandle_t hReplayItem = m_DeleteInfo.m_hReplayItem; // Post actions signal to the handler KeyValues *pMsg = new KeyValues( "ReplayItemDeleted" ); pMsg->SetInt( "replayitem", (int)hReplayItem ); pMsg->SetInt( "perf", m_DeleteInfo.m_iPerformance ); PostMessage( m_DeleteInfo.m_hHandler, pMsg ); // Delete actual replay item if ( m_DeleteInfo.m_iPerformance < 0 ) { // Cleanup UI related to the replay/movie CleanupUIForReplayItem( hReplayItem ); // Delete the replay/movie m_DeleteInfo.m_pItemManager->DeleteItem( GetActivePage(), hReplayItem, false ); } vgui::surface()->PlaySound( "replay\\deleted_take.wav" ); // Clear delete info V_memset( &m_DeleteInfo, 0, sizeof( m_DeleteInfo ) ); } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CReplayBrowserPanel::OnSaveReplay( ReplayHandle_t hNewReplay ) { // Verify that the handle is valid Assert( g_pReplayManager->GetReplay( hNewReplay ) ); m_pReplaysPage->AddReplay( hNewReplay ); m_pReplaysPage->Repaint(); } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CReplayBrowserPanel::OnDeleteReplay( ReplayHandle_t hDeletedReplay ) { // Verify that the handle is valid Assert( g_pReplayManager->GetReplay( hDeletedReplay ) ); DeleteReplay( hDeletedReplay ); } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CReplayBrowserPanel::DeleteReplay( ReplayHandle_t hReplay ) { m_pReplaysPage->DeleteReplay( hReplay ); } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CReplayBrowserPanel::CleanupUIForReplayItem( ReplayItemHandle_t hReplayItem ) { if ( GetActivePage() == m_pReplaysPage ) { m_pReplaysPage->CleanupUIForReplayItem( hReplayItem ); } } static vgui::DHANDLE g_ReplayBrowserPanel; //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- CReplayBrowserPanel *ReplayUI_OpenReplayBrowserPanel( ReplayHandle_t hReplayDetails, int iPerformance ) { if ( !g_ReplayBrowserPanel.Get() ) { g_ReplayBrowserPanel = vgui::SETUP_PANEL( new CReplayBrowserPanel( NULL ) ); g_ReplayBrowserPanel->InvalidateLayout( false, true ); } engine->ClientCmd_Unrestricted( "gameui_activate" ); g_ReplayBrowserPanel->ShowPanel( true, hReplayDetails, iPerformance ); extern IReplayMovieManager *g_pReplayMovieManager; if ( g_pReplayMovieManager->GetMovieCount() > 0 ) { // Fire a message the game DLL can intercept (for achievements, etc). IGameEvent *event = gameeventmanager->CreateEvent( "browse_replays" ); if ( event ) { gameeventmanager->FireEventClientSide( event ); } } return g_ReplayBrowserPanel; } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- CReplayBrowserPanel *ReplayUI_GetBrowserPanel( void ) { return g_ReplayBrowserPanel.Get(); } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void ReplayUI_CloseReplayBrowser() { if ( g_ReplayBrowserPanel ) { g_ReplayBrowserPanel->MarkForDeletion(); g_ReplayBrowserPanel = NULL; } } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void ReplayUI_ReloadBrowser( ReplayHandle_t hReplay/*=REPLAY_HANDLE_INVALID*/, int iPerformance/*=-1*/ ) { delete g_ReplayBrowserPanel.Get(); g_ReplayBrowserPanel = NULL; ReplayUI_OpenReplayBrowserPanel( hReplay, iPerformance ); } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- CON_COMMAND_F( open_replaybrowser, "Open the replay browser.", FCVAR_CLIENTDLL ) { ReplayUI_OpenReplayBrowserPanel( REPLAY_HANDLE_INVALID, -1 ); g_ReplayBrowserPanel->InvalidateLayout( false, true ); } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- CON_COMMAND_F( replay_reloadbrowser, "Reloads replay data and display replay browser", FCVAR_CLIENTDLL | FCVAR_CLIENTCMD_CAN_EXECUTE ) { ReplayUI_ReloadBrowser(); } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- CON_COMMAND_F( replay_hidebrowser, "Hides replay browser", FCVAR_CLIENTDLL ) { ReplayUI_CloseReplayBrowser(); } #endif