This commit is contained in:
FluorescentCIAAfricanAmerican
2020-04-22 12:56:21 -04:00
commit 3bf9df6b27
15370 changed files with 5489726 additions and 0 deletions
@@ -0,0 +1,216 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================//
#include "cbase.h"
#if defined( REPLAY_ENABLED )
#include "vgui/IInput.h"
#include "vgui/ISurface.h"
#include "vgui_controls/TextEntry.h"
#include "replaybrowserbasepage.h"
#include "replaybrowserdetailspanel.h"
#include "replaybrowsermainpanel.h"
#include "replaybrowserlistpanel.h"
#include "replay/ireplaymoviemanager.h"
#include "replay/ireplaymanager.h"
// memdbgon must be the last include file in a .cpp file!!!
#include <tier0/memdbgon.h>
//-----------------------------------------------------------------------------
extern IReplayMovieManager *g_pReplayMovieManager;
//-----------------------------------------------------------------------------
CReplayBrowserBasePage::CReplayBrowserBasePage( Panel *pParent )
: BaseClass( pParent, "BasePage" )
{
m_pReplayList = new CReplayListPanel( this, "ReplayList" );
m_pReplayList->SetFirstColumnWidth( 0 );
m_pSearchTextEntry = new vgui::TextEntry( this, "SearchTextEntry" );
m_pSearchTextEntry->SelectAllOnFocusAlways( true );
m_pSearchTextEntry->AddActionSignalTarget( this );
m_pSearchTextEntry->SetCatchEnterKey( true );
InvalidateLayout( true, true );
m_pReplayList->AddReplaysToList();
ivgui()->AddTickSignal( GetVPanel(), 100 );
}
CReplayBrowserBasePage::~CReplayBrowserBasePage()
{
ivgui()->RemoveTickSignal( GetVPanel() );
}
void CReplayBrowserBasePage::OnTick()
{
if ( !IsVisible() )
return;
int nCursorX, nCursorY;
input()->GetCursorPos( nCursorX, nCursorY );
if ( input()->IsMouseDown( MOUSE_LEFT ) &&
!m_pSearchTextEntry->IsWithin( nCursorX, nCursorY ) &&
m_pSearchTextEntry->HasFocus() )
{
RequestFocus();
}
}
void CReplayBrowserBasePage::ApplySchemeSettings( vgui::IScheme *pScheme )
{
BaseClass::ApplySchemeSettings( pScheme );
LoadControlSettings( "resource/ui/replaybrowser/basepage.res", "GAME" );
m_pSearchTextEntry->SetText( "#Replay_SearchText" );
}
void CReplayBrowserBasePage::OnPageShow()
{
BaseClass::OnPageShow();
m_pSearchTextEntry->SetText( "#Replay_SearchText" );
}
void CReplayBrowserBasePage::OnSelectionStarted()
{
PostActionSignal( new KeyValues("SelectionUpdate", "open", 1 ) );
}
void CReplayBrowserBasePage::OnSelectionEnded()
{
PostActionSignal( new KeyValues("SelectionUpdate", "open", 0 ) );
}
void CReplayBrowserBasePage::CleanupUIForReplayItem( ReplayItemHandle_t hReplayItem )
{
m_pReplayList->CleanupUIForReplayItem( hReplayItem );
}
void CReplayBrowserBasePage::AddReplay( ReplayHandle_t hReplay )
{
m_pReplayList->AddReplayItem( hReplay );
}
void CReplayBrowserBasePage::DeleteReplay( ReplayHandle_t hReplayItem )
{
IReplayItemManager *pItemManager;
if ( FindReplayItem( hReplayItem, &pItemManager ) )
{
ReplayUI_GetBrowserPanel()->AttemptToDeleteReplayItem( this, hReplayItem, pItemManager, -1 );
}
}
void CReplayBrowserBasePage::OnCancelSelection()
{
}
void CReplayBrowserBasePage::GoBack()
{
DeleteDetailsPanelAndShowReplayList();
}
void CReplayBrowserBasePage::OnReplayItemDeleted( KeyValues *pParams )
{
GoBack();
}
void CReplayBrowserBasePage::OnTextChanged( KeyValues *data )
{
wchar_t wszText[256];
m_pSearchTextEntry->GetText( wszText, ARRAYSIZE( wszText ) );
m_pReplayList->ApplyFilter( wszText );
InvalidateLayout();
}
void CReplayBrowserBasePage::OnCommand( const char *pCommand )
{
// User wants details on a replay?
if ( !V_strnicmp( pCommand, "details", 7 ) )
{
// Get rid of preview panel
m_pReplayList->ClearPreviewPanel();
QueryableReplayItemHandle_t hReplayItem = (QueryableReplayItemHandle_t)atoi( pCommand + 7 );
IReplayItemManager *pItemManager;
IQueryableReplayItem *pReplayItem = FindReplayItem( hReplayItem, &pItemManager ); Assert( pReplayItem );
if ( pReplayItem )
{
// Get performance
int iPerformance = -1;
const char *pPerformanceStr = V_strstr( pCommand + 8, "_" );
if ( pPerformanceStr )
{
iPerformance = atoi( pPerformanceStr + 1 );
}
m_hReplayDetailsPanel = vgui::SETUP_PANEL( new CReplayDetailsPanel( this, hReplayItem, iPerformance, pItemManager ) );
m_hReplayDetailsPanel->SetVisible( true );
m_hReplayDetailsPanel->MoveToFront();
m_pReplayList->SetVisible( false );
surface()->PlaySound( "replay\\showdetails.wav" );
}
}
// "back" button was hit in details panel?
else if ( FStrEq( pCommand, "back" ) )
{
GoBack();
}
BaseClass::OnCommand( pCommand );
}
void CReplayBrowserBasePage::DeleteDetailsPanelAndShowReplayList()
{
// Delete the panel
if ( m_hReplayDetailsPanel )
{
m_hReplayDetailsPanel->MarkForDeletion();
m_hReplayDetailsPanel = NULL;
}
m_pReplayList->SetVisible( true );
}
void CReplayBrowserBasePage::PerformLayout()
{
BaseClass::PerformLayout();
if ( m_pSearchTextEntry )
{
const bool bHasReplays = g_pReplayManager && g_pReplayManager->GetReplayCount();
const bool bHasMovies = g_pReplayMovieManager && g_pReplayMovieManager->GetMovieCount();
int aListPos[2];
m_pReplayList->GetPos( aListPos[0], aListPos[1] );
m_pSearchTextEntry->SetPos( aListPos[0] + m_pReplayList->GetWide() - m_pSearchTextEntry->GetWide(), YRES( 5 ) );
m_pSearchTextEntry->SetVisible( bHasReplays || bHasMovies );
}
// Invalidate the list too, because we might be laying out due to a replay being removed from the list.
m_pReplayList->InvalidateLayout();
}
void CReplayBrowserBasePage::FreeDetailsPanelMovieLock()
{
m_hReplayDetailsPanel->FreeMovieFileLock();
}
bool CReplayBrowserBasePage::IsDetailsViewOpen()
{
return m_hReplayDetailsPanel.Get() != NULL && m_hReplayDetailsPanel->IsVisible();
}
#endif
@@ -0,0 +1,67 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#ifndef REPLAYBROWSER_BASEPAGE_H
#define REPLAYBROWSER_BASEPAGE_H
#ifdef _WIN32
#pragma once
#endif
#include "vgui_controls/PropertyPage.h"
#include "replaybrowseritemmanager.h"
#include "replay/genericclassbased_replay.h"
using namespace vgui;
//-----------------------------------------------------------------------------
// Forward declarations
//-----------------------------------------------------------------------------
class CReplayListPanel;
class CExLabel;
class CReplayDetailsPanel;
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
class CReplayBrowserBasePage : public PropertyPage
{
DECLARE_CLASS_SIMPLE( CReplayBrowserBasePage, PropertyPage );
public:
CReplayBrowserBasePage( Panel *pParent );
virtual ~CReplayBrowserBasePage();
void DeleteDetailsPanelAndShowReplayList();
bool IsDetailsViewOpen();
void GoBack();
// Movie-only stuff
void FreeDetailsPanelMovieLock();
virtual void ApplySchemeSettings( IScheme *pScheme );
virtual void OnCommand( const char *pCommand );
virtual void PerformLayout();
MESSAGE_FUNC( OnPageShow, "PageShow" );
MESSAGE_FUNC( OnSelectionStarted, "SelectionStarted" );
MESSAGE_FUNC( OnSelectionEnded, "SelectionEnded" );
MESSAGE_FUNC( OnCancelSelection, "CancelSelection" );
MESSAGE_FUNC_PARAMS( OnReplayItemDeleted, "ReplayItemDeleted", pParams );
MESSAGE_FUNC_PARAMS( OnTextChanged, "TextChanged", data );
void AddReplay( ReplayHandle_t hReplay );
void DeleteReplay( ReplayHandle_t hReplay );
void OnTick();
virtual void CleanupUIForReplayItem( ReplayItemHandle_t hReplayItem );
vgui::TextEntry *m_pSearchTextEntry;
CReplayListPanel *m_pReplayList;
DHANDLE< CReplayDetailsPanel > m_hReplayDetailsPanel;
};
#endif // REPLAYBROWSER_BASEPAGE_H
@@ -0,0 +1,39 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
//=======================================================================================//
#include "cbase.h"
#if defined( REPLAY_ENABLED )
#include "replaybrowserbasepanel.h"
//-----------------------------------------------------------------------------
using namespace vgui;
//-----------------------------------------------------------------------------
CReplayBasePanel::CReplayBasePanel( Panel *pParent, const char *pName )
: BaseClass( pParent, pName )
{
}
void CReplayBasePanel::GetPosRelativeToAncestor( Panel *pAncestor, int &nXOut, int &nYOut )
{
nXOut = nYOut = 0;
Panel *pCurrent = this;
while ( pCurrent && pCurrent != pAncestor )
{
int x,y;
pCurrent->GetPos( x, y );
nXOut += x;
nYOut += y;
pCurrent = pCurrent->GetParent();
}
Assert( pAncestor == pCurrent );
}
#endif
@@ -0,0 +1,25 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
//=======================================================================================//
#ifndef REPLAYBASEPANEL_H
#define REPLAYBASEPANEL_H
#ifdef _WIN32
#pragma once
#endif
#include "vgui_controls/EditablePanel.h"
//-----------------------------------------------------------------------------
// Purpose: Base panel for replay panels
//-----------------------------------------------------------------------------
class CReplayBasePanel : public vgui::EditablePanel
{
DECLARE_CLASS_SIMPLE( CReplayBasePanel, vgui::EditablePanel );
public:
CReplayBasePanel( Panel *pParent, const char *pName );
void GetPosRelativeToAncestor( Panel *pAncestor, int &nXOut, int &nYOut );
};
#endif // REPLAYBASEPANEL_H
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,462 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#ifndef REPLAYBROWSER_DETAILSPANEL_H
#define REPLAYBROWSER_DETAILSPANEL_H
#ifdef _WIN32
#pragma once
#endif
#include <game/client/iviewport.h>
#include "vgui_controls/EditablePanel.h"
#include "vgui_controls/ScrollableEditablePanel.h"
#include "replay/iqueryablereplayitem.h"
#include "replay/ireplaymovie.h"
#include "replay/replayhandle.h"
#include "replay/gamedefs.h"
#include "econ/econ_controls.h"
using namespace vgui;
//-----------------------------------------------------------------------------
#define NUM_CLASSES_IN_LOADOUT_PANEL (TF_LAST_NORMAL_CLASS-1) // We don't allow unlockables for the civilian
//-----------------------------------------------------------------------------
// Purpose: Forward declarations
//-----------------------------------------------------------------------------
class CExLabel;
class CExButton;
class CTFReplay;
class CReplayPerformance;
class IReplayItemManager;
//-----------------------------------------------------------------------------
// Purpose: A panel containing 2 labels: one key, one value
//-----------------------------------------------------------------------------
class CKeyValueLabelPanel : public EditablePanel
{
DECLARE_CLASS_SIMPLE( CKeyValueLabelPanel, EditablePanel );
public:
CKeyValueLabelPanel( Panel *pParent, const char *pKey, const char *pValue );
CKeyValueLabelPanel( Panel *pParent, const char *pKey, const wchar_t *pValue );
virtual void ApplySchemeSettings( IScheme *pScheme );
virtual void PerformLayout();
int GetHeight() const;
int GetValueHeight() const;
void SetValue( const wchar_t *pValue );
private:
CExLabel *m_pLabels[2];
};
//-----------------------------------------------------------------------------
// Purpose: Base details panel with left/top padding and black border
//-----------------------------------------------------------------------------
class CBaseDetailsPanel : public EditablePanel
{
DECLARE_CLASS_SIMPLE( CBaseDetailsPanel, EditablePanel );
public:
CBaseDetailsPanel( Panel *pParent, const char *pName, ReplayHandle_t hReplay );
virtual void ApplySchemeSettings( IScheme *pScheme );
virtual void PerformLayout();
int GetMarginSize() const { return XRES(6); }
bool ShouldShow() const { return m_bShouldShow; }
protected:
EditablePanel *GetInset() { return m_pInsetPanel; }
ReplayHandle_t m_hReplay;
bool m_bShouldShow;
private:
EditablePanel *m_pInsetPanel; // padding on left/top
};
//-----------------------------------------------------------------------------
// Purpose: Score panel - contains score & any records from the round
//-----------------------------------------------------------------------------
class CRecordsPanel : public CBaseDetailsPanel
{
DECLARE_CLASS_SIMPLE( CRecordsPanel, CBaseDetailsPanel );
public:
CRecordsPanel( Panel *pParent, ReplayHandle_t hReplay );
virtual void ApplySchemeSettings( IScheme *pScheme );
virtual void PerformLayout();
private:
ImagePanel *m_pClassImage;
};
//-----------------------------------------------------------------------------
// Purpose: Stats panel
//-----------------------------------------------------------------------------
class CStatsPanel : public CBaseDetailsPanel
{
DECLARE_CLASS_SIMPLE( CStatsPanel, CBaseDetailsPanel );
public:
CStatsPanel( Panel *pParent, ReplayHandle_t hReplay );
virtual void ApplySchemeSettings( IScheme *pScheme );
virtual void PerformLayout();
private:
CKeyValueLabelPanel *m_paStatLabels[ REPLAY_MAX_DISPLAY_GAMESTATS ];
};
//-----------------------------------------------------------------------------
// Purpose: Dominations panel
//-----------------------------------------------------------------------------
class CDominationsPanel : public CBaseDetailsPanel
{
DECLARE_CLASS_SIMPLE( CDominationsPanel, CBaseDetailsPanel );
public:
CDominationsPanel( Panel *pParent, ReplayHandle_t hReplay );
virtual void ApplySchemeSettings( IScheme *pScheme );
virtual void PerformLayout();
ImagePanel *m_pNumDominationsImage;
CUtlVector< ImagePanel * > m_vecDominationImages;
};
//-----------------------------------------------------------------------------
// Purpose: Kills panel
//-----------------------------------------------------------------------------
class CKillsPanel : public CBaseDetailsPanel
{
DECLARE_CLASS_SIMPLE( CKillsPanel, CBaseDetailsPanel );
public:
CKillsPanel( Panel *pParent, ReplayHandle_t hReplay );
virtual void ApplySchemeSettings( IScheme *pScheme );
virtual void PerformLayout();
CKeyValueLabelPanel *m_pKillLabels;
CUtlVector< ImagePanel * > m_vecKillImages;
};
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
class CBasicLifeInfoPanel : public CBaseDetailsPanel
{
DECLARE_CLASS_SIMPLE( CBasicLifeInfoPanel, CBaseDetailsPanel );
public:
CBasicLifeInfoPanel( Panel *pParent, ReplayHandle_t hReplay );
virtual void ApplySchemeSettings( IScheme *pScheme );
virtual void PerformLayout();
private:
CKeyValueLabelPanel *m_pKilledByLabels;
CKeyValueLabelPanel *m_pMapLabels;
CKeyValueLabelPanel *m_pLifeLabels;
};
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
class CMovieInfoPanel : public CBaseDetailsPanel
{
DECLARE_CLASS_SIMPLE( CMovieInfoPanel, CBaseDetailsPanel );
public:
CMovieInfoPanel( Panel *pParent, ReplayHandle_t hReplay, QueryableReplayItemHandle_t hMovie,
IReplayItemManager *pItemManager );
virtual void ApplySchemeSettings( IScheme *pScheme );
virtual void PerformLayout();
private:
CKeyValueLabelPanel *m_pRenderTimeLabels;
};
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
class CYouTubeInfoPanel : public CBaseDetailsPanel
{
DECLARE_CLASS_SIMPLE( CYouTubeInfoPanel, CBaseDetailsPanel );
public:
CYouTubeInfoPanel( Panel *pParent );
virtual void PerformLayout();
void SetInfo( const wchar_t *pInfo );
private:
CKeyValueLabelPanel *m_pLabels;
};
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
class CTitleEditPanel : public EditablePanel
{
DECLARE_CLASS_SIMPLE( CTitleEditPanel, EditablePanel );
public:
CTitleEditPanel( Panel *pParent, QueryableReplayItemHandle_t hReplayItem, IReplayItemManager *pItemManager );
~CTitleEditPanel();
virtual void ApplySchemeSettings( IScheme *pScheme );
virtual void PerformLayout();
virtual void PaintBackground();
virtual void OnKeyCodeTyped(vgui::KeyCode code);
virtual void OnTick();
bool m_bMouseOver;
TextEntry *m_pTitleEntry;
ImagePanel *m_pHeaderLine;
CExLabel *m_pClickToEditLabel;
CExLabel *m_pCaratLabel;
QueryableReplayItemHandle_t m_hReplayItem;
IReplayItemManager *m_pItemManager;
};
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
class CReplayScreenshotSlideshowPanel;
class CPlaybackPanel : public EditablePanel
{
DECLARE_CLASS_SIMPLE( CPlaybackPanel, EditablePanel );
public:
CPlaybackPanel( Panel *pParent );
~CPlaybackPanel();
virtual void FreeMovieMaterial() {}
protected:
virtual void ApplySchemeSettings( IScheme *pScheme );
virtual void PerformLayout();
inline int GetMarginSize() { return 9; }
inline int GetViewWidth() { return GetWide() - 2 * GetMarginSize(); }
inline int GetViewHeight() { return GetTall() - 2 * GetMarginSize(); }
};
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
class CPlaybackPanelSlideshow : public CPlaybackPanel
{
DECLARE_CLASS_SIMPLE( CPlaybackPanelSlideshow, CPlaybackPanel );
public:
CPlaybackPanelSlideshow( Panel *pParent, ReplayHandle_t hReplay );
virtual void ApplySchemeSettings( IScheme *pScheme );
virtual void PerformLayout();
private:
ReplayHandle_t m_hReplay;
CExLabel *m_pNoScreenshotLabel;
CReplayScreenshotSlideshowPanel *m_pScreenshotImage;
};
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
class CMoviePlayerPanel;
class CPlaybackPanelMovie : public CPlaybackPanel
{
DECLARE_CLASS_SIMPLE( CPlaybackPanelMovie, CPlaybackPanel );
public:
CPlaybackPanelMovie( Panel *pParent, ReplayHandle_t hReplay );
virtual void ApplySchemeSettings( IScheme *pScheme );
virtual void PerformLayout();
virtual void FreeMovieMaterial();
private:
CExLabel *m_pLoadingLabel;
CMoviePlayerPanel *m_pMoviePlayerPanel;
ReplayHandle_t m_hMovie;
};
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
class CCutImagePanel : public CExImageButton
{
DECLARE_CLASS_SIMPLE( CCutImagePanel, CExImageButton );
public:
CCutImagePanel( Panel *pParent, const char *pName );
virtual void ApplySchemeSettings( vgui::IScheme *pScheme );
virtual void SetSelected( bool bState );
private:
virtual IBorder *GetBorder( bool bDepressed, bool bArmed, bool bSelected, bool bKeyFocus );
IBorder *m_pSelectedBorder;
};
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
class CReplayDetailsPanel;
class CCutsPanel : public CBaseDetailsPanel
{
DECLARE_CLASS_SIMPLE( CCutsPanel, CBaseDetailsPanel );
public:
CCutsPanel( Panel *pParent, ReplayHandle_t hReplay, int iPerformance );
~CCutsPanel();
virtual void ApplySchemeSettings( IScheme *pScheme );
virtual void PerformLayout();
virtual void OnCommand( const char *pCommand );
virtual void ApplySettings( KeyValues *pInResourceData );
void OnPerformanceDeleted( int iPerformance );
CPanelAnimationVarAliasType( int, m_nCutButtonWidth, "cut_button_width", "0", "proportional_xpos" );
CPanelAnimationVarAliasType( int, m_nCutButtonHeight, "cut_button_height", "0", "proportional_ypos" );
CPanelAnimationVarAliasType( int, m_nCutButtonBuffer, "cut_button_buffer", "0", "proportional_xpos" );
CPanelAnimationVarAliasType( int, m_nCutButtonSpace, "cut_button_space", "0", "proportional_xpos" );
CPanelAnimationVarAliasType( int, m_nCutButtonSpaceWide, "cut_button_space_wide", "0", "proportional_xpos" );
CPanelAnimationVarAliasType( int, m_nTopMarginHeight, "top_margin_height", "0", "proportional_ypos" );
CPanelAnimationVarAliasType( int, m_nNameLabelTopMargin, "name_label_top_margin", "0", "proportional_ypos" );
CPanelAnimationVarAliasType( int, m_nButtonStartY, "button_start_y", "0", "proportional_ypos" );
void UpdateNameLabel( int iPerformance );
private:
void SelectButtonFromPerformance( int iPerformance );
void SetPage( int iPage, int iButtonToSelect = 0 );
int ButtonToPerformance( int iButton ) const;
int PerformanceToButton( int iPerformance ) const;
const CReplayPerformance *GetPerformance( int iPerformance ) const;
virtual void OnTick();
struct ButtonInfo_t
{
CExImageButton *m_pButton;
CExButton *m_pAddToRenderQueueButton;
int m_iPerformance;
};
enum Consts_t
{
BUTTONS_PER_PAGE = 4
};
ButtonInfo_t m_aButtons[ BUTTONS_PER_PAGE ];
EditablePanel *m_pVerticalLine;
CExLabel *m_pNoCutsLabel;
CExLabel *m_pOriginalLabel;
CExLabel *m_pCutsLabel;
CExLabel *m_pNameLabel;
CExButton *m_pPrevButton;
CExButton *m_pNextButton;
int m_iPage;
int m_nVisibleButtons;
vgui::DHANDLE< CReplayDetailsPanel > m_hDetailsPanel;
};
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
class IReplayItemManager;
class CConfirmDialog;
class CYouTubeGetStatsHandler;
class CReplayDetailsPanel : public EditablePanel
{
DECLARE_CLASS_SIMPLE( CReplayDetailsPanel, EditablePanel );
public:
CReplayDetailsPanel( Panel *pParent, QueryableReplayItemHandle_t hReplayItem, int iPerformance, IReplayItemManager *pItemManager );
~CReplayDetailsPanel();
virtual void ApplySchemeSettings( IScheme *pScheme );
virtual void PerformLayout();
virtual void OnMousePressed( MouseCode code );
virtual void OnKeyCodeTyped( KeyCode code );
virtual void OnCommand( const char *pCommand );
virtual void OnMessage( const KeyValues* pParams, VPANEL hFromPanel );
EditablePanel *GetInset() { return m_pInsetPanel; }
void ShowRenderDialog();
void FreeMovieFileLock();
void ShowExportDialog();
static void OnPlayerWarningDlgConfirm( bool bConfirmed, void *pContext );
enum eYouTubeStatus
{
kYouTubeStatus_Private,
kYouTubeStatus_RetrievingInfo,
kYouTubeStatus_RetrievedInfo,
kYouTubeStatus_CouldNotRetrieveInfo,
kYouTubeStatus_NotUploaded
};
void SetYouTubeStatus( eYouTubeStatus status );
EditablePanel *m_pInsetPanel; // Parent to most child panels listed here - narrower than screen width
EditablePanel *m_pInfoPanel; // Container for info panels
ScrollableEditablePanel *m_pScrollPanel;
CPlaybackPanel *m_pPlaybackPanel; // Contains screenshot, playback button
CRecordsPanel *m_pRecordsPanel; // Contains score, records
CStatsPanel *m_pStatsPanel; // Contains stats
CDominationsPanel *m_pDominationsPanel; // Dominations
CBasicLifeInfoPanel *m_pBasicInfoPanel; // Killed by, map, life
CKillsPanel *m_pKillsPanel; // # kills, kill class icons
CYouTubeInfoPanel *m_pYouTubeInfoPanel; // YouTube Info
CCutsPanel *m_pCutsPanel; // Buttons for performances
CUtlVector< CBaseDetailsPanel* > m_vecInfoPanels; // List of panels on the right
CTitleEditPanel *m_pTitleEditPanel;
CExButton *m_pBackButton;
CExButton *m_pDeleteButton;
CExButton *m_pRenderButton;
CExButton *m_pPlayButton;
CExButton *m_pExportMovie;
CExButton *m_pYouTubeUpload;
CExButton *m_pYouTubeView;
CExButton *m_pYouTubeShareURL;
CExImageButton *m_pShowRenderInfoButton;
QueryableReplayItemHandle_t m_hReplayItem;
ReplayHandle_t m_hReplay;
IReplayItemManager *m_pItemManager;
int m_iSelectedPerformance; // Which performance to play/render/delete
CYouTubeGetStatsHandler *m_pYouTubeResponseHandler;
vgui::FileOpenDialog *m_hExportMovieDialog;
private:
void ShowRenderInfo();
MESSAGE_FUNC_PARAMS( OnConfirmDisconnect, "ConfirmDlgResult", data );
MESSAGE_FUNC_CHARPTR( OnFileSelected, "FileSelected", fullpath );
CPanelAnimationVarAliasType( int, m_nMarginWidth, "margin_width", "0", "proportional_xpos" );
void GoBack();
void ShowPlayConfirmationDialog();
};
#endif // REPLAYBROWSER_DETAILSPANEL_H
@@ -0,0 +1,133 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
//=======================================================================================//
#include "cbase.h"
#if defined( REPLAY_ENABLED )
#include "replaybrowseritemmanager.h"
#include "replaybrowserbasepage.h"
#include "replay/ireplaymoviemanager.h"
#include "replay/ireplaymanager.h"
#include "replay/ireplaymovie.h"
//-----------------------------------------------------------------------------
using namespace vgui;
//-----------------------------------------------------------------------------
extern IClientReplayContext *g_pClientReplayContext;
extern IReplayMovieManager *g_pReplayMovieManager;
//-----------------------------------------------------------------------------
class CReplayItemManager : public IReplayItemManager
{
public:
virtual int GetItemCount()
{
return g_pReplayManager->GetReplayCount();
}
virtual void GetItems( CUtlLinkedList< IQueryableReplayItem *, int > &items )
{
g_pReplayManager->GetReplaysAsQueryableItems( items );
}
virtual IQueryableReplayItem *GetItem( ReplayItemHandle_t hItem )
{
return static_cast< CReplay * >( g_pReplayManager->GetReplay( (ReplayHandle_t)hItem ) );
}
virtual bool AreItemsMovies()
{
return false;
}
virtual void DeleteItem( Panel *pPage, ReplayItemHandle_t hItem, bool bNotifyUI )
{
g_pReplayManager->DeleteReplay( (ReplayHandle_t)hItem, bNotifyUI );
}
};
//-----------------------------------------------------------------------------
class CMovieItemManager : public IReplayItemManager
{
public:
virtual int GetItemCount()
{
return g_pReplayMovieManager->GetMovieCount();
}
virtual void GetItems( CUtlLinkedList< IQueryableReplayItem *, int > &items )
{
g_pReplayMovieManager->GetMoviesAsQueryableItems( items );
}
virtual IQueryableReplayItem *GetItem( ReplayItemHandle_t hItem )
{
return g_pReplayMovieManager->GetMovie( (ReplayHandle_t)hItem );
}
virtual bool AreItemsMovies()
{
return true;
}
virtual void DeleteItem( Panel *pPage, ReplayItemHandle_t hItem, bool bNotifyUI )
{
CReplayBrowserBasePage *pBasePage = static_cast< CReplayBrowserBasePage * >( pPage );
// Free the lock so the file is deletable
pBasePage->FreeDetailsPanelMovieLock();
// Delete the entry & the file
g_pReplayMovieManager->DeleteMovie( hItem );
}
};
//-----------------------------------------------------------------------------
static CReplayItemManager s_ReplayItemManager;
static CMovieItemManager s_MovieItemManager;
//-----------------------------------------------------------------------------
IReplayItemManager *GetReplayItemManager()
{
return &s_ReplayItemManager;
}
IReplayItemManager *GetReplayMovieItemManager()
{
return &s_MovieItemManager;
}
IQueryableReplayItem *FindReplayItem( ReplayItemHandle_t hItem, IReplayItemManager **ppItemManager )
{
static IReplayItemManager *s_pItemManagers[] = { &s_ReplayItemManager, &s_MovieItemManager };
if ( ppItemManager )
{
*ppItemManager = NULL;
}
for ( int i = 0; i < 2; ++i )
{
IQueryableReplayItem *pItem = s_pItemManagers[ i ]->GetItem( hItem );
if ( pItem )
{
if ( ppItemManager )
{
*ppItemManager = s_pItemManagers[ i ];
}
return pItem;
}
}
return NULL;
}
#endif
@@ -0,0 +1,40 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
//=======================================================================================//
#ifndef REPLAYBROWSER_ITEMMANAGER_H
#define REPLAYBROWSER_ITEMMANAGER_H
#ifdef _WIN32
#pragma once
#endif
#include "utllinkedlist.h"
#include <vgui_controls/Panel.h>
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
typedef int ReplayItemHandle_t;
//-----------------------------------------------------------------------------
// Purpose: Layer of abstraction between UI and replay demos or rendered movies
//-----------------------------------------------------------------------------
class IQueryableReplayItem;
abstract_class IReplayItemManager : public IBaseInterface
{
public:
virtual int GetItemCount() = 0;
virtual void GetItems( CUtlLinkedList< IQueryableReplayItem *, int > &items ) = 0;
virtual IQueryableReplayItem *GetItem( ReplayItemHandle_t hItem ) = 0;
virtual bool AreItemsMovies() = 0;
virtual void DeleteItem( vgui::Panel *pPage, ReplayItemHandle_t hItem, bool bNotifyUI ) = 0;
};
IReplayItemManager *GetReplayItemManager();
IReplayItemManager *GetReplayMovieItemManager();
// Find an item and put the item manager in ppItemManager
IQueryableReplayItem *FindReplayItem( ReplayItemHandle_t hItem, IReplayItemManager **ppItemManager );
#endif // REPLAYBROWSER_ITEMMANAGER_H
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,239 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
//=======================================================================================//
#ifndef REPLAYLISTITEMPANEL_H
#define REPLAYLISTITEMPANEL_H
#ifdef _WIN32
#pragma once
#endif
#include "replaybrowserbasepanel.h"
#include "replaybrowseritemmanager.h"
#include "replay/genericclassbased_replay.h"
#include "game_controls/slideshowpanel.h"
using namespace vgui;
//-----------------------------------------------------------------------------
// Purpose: Slideshow panel that adds all screenshots associated
// with a given replay.
//-----------------------------------------------------------------------------
class CReplayScreenshotSlideshowPanel : public CSlideshowPanel
{
DECLARE_CLASS_SIMPLE( CReplayScreenshotSlideshowPanel, CSlideshowPanel );
public:
CReplayScreenshotSlideshowPanel( Panel *pParent, const char *pName, ReplayHandle_t hReplay );
virtual void PerformLayout();
private:
ReplayHandle_t m_hReplay;
};
//-----------------------------------------------------------------------------
// Purpose: An individual Replay thumbnail, with download button, title, etc.
//-----------------------------------------------------------------------------
class CExButton;
class CExLabel;
class IReplayItemManager;
class CMoviePlayerPanel;
class CReplayBrowserThumbnail : public CReplayBasePanel
{
DECLARE_CLASS_SIMPLE( CReplayBrowserThumbnail, CReplayBasePanel );
public:
CReplayBrowserThumbnail( Panel *pParent, const char *pName, QueryableReplayItemHandle_t hReplayItem, IReplayItemManager *pReplayItemManager );
~CReplayBrowserThumbnail();
virtual void ApplySchemeSettings( IScheme *pScheme );
virtual void PerformLayout();
virtual void OnMousePressed( MouseCode code );
virtual void OnTick();
virtual void OnCommand( const char *pCommand );
void UpdateTitleText();
void SetReplayItem( QueryableReplayItemHandle_t hReplayItem );
CGenericClassBasedReplay *GetReplay();
IQueryableReplayItem *GetReplayItem();
MESSAGE_FUNC_PARAMS( OnDownloadClicked, "Download", pParams );
MESSAGE_FUNC_PARAMS( OnDeleteReplay, "delete_replayitem", pParams );
CCrossfadableImagePanel *m_pScreenshotThumb;
QueryableReplayItemHandle_t m_hReplayItem;
private:
void SetupReplayItemUserData( void *pUserData );
void UpdateProgress( bool bDownloadPhase, const CReplay *pReplay );
Label *m_pTitle;
Label *m_pDownloadLabel;
Label *m_pRecordingInProgressLabel;
ProgressBar *m_pDownloadProgress;
CExButton *m_pDownloadButton;
CExButton *m_pDeleteButton;
Label *m_pErrorLabel;
CMoviePlayerPanel *m_pMoviePlayer;
Panel *m_pDownloadOverlay;
EditablePanel *m_pBorderPanel;
Color m_clrHighlight;
Color m_clrDefaultBg;
bool m_bMouseOver;
IReplayItemManager *m_pReplayItemManager;
float m_flLastMovieScrubTime;
float m_flHoverStartTime;
float m_flLastProgressChangeTime;
};
//-----------------------------------------------------------------------------
// Purpose: A row of Replay thumbnails (CReplayBrowserThumbnail's)
//-----------------------------------------------------------------------------
class CReplayBrowserThumbnailRow : public EditablePanel
{
DECLARE_CLASS_SIMPLE( CReplayBrowserThumbnailRow, EditablePanel );
public:
CReplayBrowserThumbnailRow( Panel *pParent, const char *pName, IReplayItemManager *pReplayItemManager );
void AddReplayThumbnail( const IQueryableReplayItem *pReplay );
void AddReplayThumbnail( QueryableReplayItemHandle_t hReplayItem );
void DeleteReplayItemThumbnail( const IQueryableReplayItem *pReplayItem );
int GetNumReplayItems() const { return m_vecThumbnails.Count(); }
int GetNumVisibleReplayItems() const;
virtual void ApplySchemeSettings( IScheme *pScheme );
virtual void PerformLayout();
CReplayBrowserThumbnail *FindThumbnail( const IQueryableReplayItem *pReplay );
CUtlVector< CReplayBrowserThumbnail * > m_vecThumbnails;
IReplayItemManager *m_pReplayItemManager;
};
//-----------------------------------------------------------------------------
// Purpose: A collection of CReplayBrowserThumbnailRows containing replays
// recorded on a given day.
//-----------------------------------------------------------------------------
class CExLabel;
class CExButton;
class CReplayListPanel;
class CBaseThumbnailCollection : public EditablePanel
{
DECLARE_CLASS_SIMPLE( CBaseThumbnailCollection, EditablePanel );
public:
CBaseThumbnailCollection( CReplayListPanel *pParent, const char *pName, IReplayItemManager *pReplayItemManager );
void AddReplay( const IQueryableReplayItem *pItem );
virtual bool IsMovieCollection() const = 0;
void CleanupUIForReplayItem( ReplayItemHandle_t hReplayItem );
virtual void PerformLayout();
virtual void ApplySchemeSettings( IScheme *pScheme );
void RemoveEmptyRows();
void RemoveAll();
void OnUpdated();
void OnCommand( const char *pCommand );
CReplayBrowserThumbnailRow *FindReplayItemThumbnailRow( const IQueryableReplayItem *pReplayItem );
inline int GetNumRows() const { return m_vecRows.Count(); }
typedef CUtlVector< CReplayBrowserThumbnailRow * > RowContainer_t;
RowContainer_t m_vecRows;
protected:
// Called from PerformLayout() - layout any panels that should appear at the top (vertically)-most position
virtual void LayoutUpperPanels( int nStartY, int nBgWidth ) = 0;
virtual void LayoutBackgroundPanel( int nWide, int nTall ) {}
virtual Panel *GetLowestPanel( int &nVerticalBuffer ) = 0;
void UpdateViewingPage( void );
int m_nStartX;
protected:
CExLabel *m_pNoReplayItemsLabel;
IReplayItemManager *m_pReplayItemManager;
CExButton *m_pShowNextButton;
CExButton *m_pShowPrevButton;
CUtlVector<ReplayItemHandle_t> m_vecReplays;
int m_iViewingPage;
int m_nReplayThumbnailsPerRow;
int m_nMaxRows;
CExLabel *m_pCaratLabel;
CExLabel *m_pTitleLabel;
CExButton *m_pRenderAllButton;
private:
int GetRowStartY();
CReplayListPanel *m_pParentListPanel; // Parent gets altered so we keep this cached ptr around
};
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
class CReplayThumbnailCollection : public CBaseThumbnailCollection
{
DECLARE_CLASS_SIMPLE( CReplayThumbnailCollection, CBaseThumbnailCollection );
public:
CReplayThumbnailCollection( CReplayListPanel *pParent, const char *pName, IReplayItemManager *pReplayItemManager );
virtual bool IsMovieCollection() const;
virtual void PerformLayout();
virtual void ApplySchemeSettings( IScheme *pScheme );
virtual void LayoutUpperPanels( int nStartY, int nBgWidth );
virtual void LayoutBackgroundPanel( int nWide, int nTall );
virtual Panel *GetLowestPanel( int &nVerticalBuffer );
Panel *m_pLinePanel;
CExLabel *m_pWarningLabel;
Panel *m_pUnconvertedBg;
};
#define OLDER_MOVIES_COLLECTION -2
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
class CMovieThumbnailCollection : public CBaseThumbnailCollection
{
DECLARE_CLASS_SIMPLE( CMovieThumbnailCollection, CBaseThumbnailCollection );
public:
CMovieThumbnailCollection( CReplayListPanel *pParent, const char *pName, IReplayItemManager *pReplayItemManager,
int nDay, int nMonth, int nYear, bool bShowSavedMoviesLabel );
CMovieThumbnailCollection( CReplayListPanel *pParent, const char *pName, IReplayItemManager *pReplayItemManager,
bool bShowSavedMoviesLabel );
bool DoesDateMatch( int nDay, int nMonth, int nYear );
virtual bool IsMovieCollection() const;
private:
void Init( int nDay, int nMonth, int nYear, bool bShowSavedMoviesLabel );
virtual void PerformLayout();
virtual void ApplySchemeSettings( IScheme *pScheme );
Panel *GetLowestPanel( int &nVerticalBuffer );
void LayoutUpperPanels( int nStartY, int nBgWidth );
int m_nDay, m_nMonth, m_nYear;
CExLabel *m_pDateLabel;
bool m_bShowSavedMoviesLabel;
};
#endif // REPLAYLISTITEMPANEL_H
@@ -0,0 +1,484 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
//=======================================================================================//
#include "cbase.h"
#if defined( REPLAY_ENABLED )
#include "replaybrowserlistpanel.h"
#include "ienginevgui.h"
#include "vgui/ISurface.h"
#include "vgui/IInput.h"
#include "vgui/IVGui.h"
#include "vgui_controls/ScrollBar.h"
#include "vgui_controls/ScrollBarSlider.h"
#include "replaybrowserlistitempanel.h"
#include "replaybrowserpreviewpanel.h"
#include "replaybrowserbasepage.h"
#include "replay/ireplaymoviemanager.h"
#include "replay/ireplaymanager.h"
#include "replaybrowsermainpanel.h"
// memdbgon must be the last include file in a .cpp file!!!
#include <tier0/memdbgon.h>
//-----------------------------------------------------------------------------
extern IClientReplayContext *g_pClientReplayContext;
extern IReplayMovieManager *g_pReplayMovieManager;
extern const char *GetMapDisplayName( const char *mapName );
//-----------------------------------------------------------------------------
DECLARE_BUILD_FACTORY( CReplayListPanel );
//-----------------------------------------------------------------------------
#define MAX_MOVIE_THUMBNAILS 12 // The remaining movies will be put into a single collection
//-----------------------------------------------------------------------------
CReplayListPanel::CReplayListPanel( Panel *pParent, const char *pName )
: BaseClass( pParent, pName ),
m_pPrevHoverPanel( NULL ),
m_pPreviewPanel( NULL )
{
ivgui()->AddTickSignal( GetVPanel(), 10 );
m_pBorderArrowImg = new ImagePanel( this, "ArrowImage" );
// Add replays and movies collections, which will contain all replays & movies.
m_pReplaysCollection = new CReplayThumbnailCollection( this, "ReplayThumbnailCollection", GetReplayItemManager() );
m_pMoviesCollection = new CMovieThumbnailCollection( this, "MovieThumbnailCollection", GetReplayMovieItemManager(), true );
m_vecCollections.AddToTail( m_pReplaysCollection );
m_vecCollections.AddToTail( m_pMoviesCollection );
m_wszFilter[0] = L' ';
m_wszFilter[1] = NULL;
}
CReplayListPanel::~CReplayListPanel()
{
ivgui()->RemoveTickSignal( GetVPanel() );
}
void CReplayListPanel::ApplySchemeSettings( vgui::IScheme *pScheme )
{
BaseClass::ApplySchemeSettings( pScheme );
LoadControlSettings( "resource/ui/replaybrowser/replaylistpanel.res", "GAME" );
#if !defined( TF_CLIENT_DLL )
SetPaintBorderEnabled( false );
#endif
MoveScrollBarToTop();
vgui::ScrollBar *pScrollBar = dynamic_cast< vgui::ScrollBar * >( FindChildByName( "PanelListPanelVScroll" ) );
pScrollBar->SetScrollbarButtonsVisible( false );
Color clrButtonColor = GetSchemeColor( "Yellow", Color( 255, 255, 255, 255 ), pScheme );
Color clrBgColor = GetSchemeColor( "TanDark", Color( 255, 255, 255, 255 ), pScheme );
const int nWidth = XRES( 5 );
pScrollBar->SetSize( nWidth, GetTall() );
pScrollBar->GetSlider()->SetSize( nWidth, GetTall() );
}
void CReplayListPanel::PerformLayout()
{
BaseClass::PerformLayout();
}
void CReplayListPanel::OnMouseWheeled(int delta)
{
if ( !GetScrollbar()->IsVisible() )
return;
BaseClass::OnMouseWheeled( delta );
}
void CReplayListPanel::SetupBorderArrow( bool bLeft )
{
m_pBorderArrowImg->SetVisible( true );
m_pBorderArrowImg->SetImage( bLeft ? "replay/replay_balloon_arrow_left" : "replay/replay_balloon_arrow_right" );
m_pBorderArrowImg->SetZPos( 1000 );
m_pBorderArrowImg->GetImage()->GetContentSize( m_aBorderArrowDims[0], m_aBorderArrowDims[1] );
m_pBorderArrowImg->SetSize( m_aBorderArrowDims[0], m_aBorderArrowDims[1] );
}
void CReplayListPanel::ClearPreviewPanel()
{
if ( m_pPreviewPanel )
{
m_pPreviewPanel->MarkForDeletion();
m_pPreviewPanel = NULL;
}
}
void CReplayListPanel::ApplyFilter( const wchar_t *pFilterText )
{
Q_wcsncpy( m_wszFilter, pFilterText, sizeof( m_wszFilter ) );
V_wcslower( m_wszFilter );
m_pReplaysCollection->RemoveAll();
m_pMoviesCollection->RemoveAll();
m_pPrevHoverPanel = NULL;
ClearPreviewPanel();
RemoveAll();
AddReplaysToList();
FOR_EACH_VEC( m_vecCollections, i )
{
m_vecCollections[i]->OnUpdated();
}
InvalidateLayout();
}
void CReplayListPanel::OnTick()
{
if ( !enginevgui->IsGameUIVisible() )
return;
CReplayBrowserPanel *pReplayBrowser = ReplayUI_GetBrowserPanel();
if ( !pReplayBrowser || !pReplayBrowser->IsVisible() )
return;
int x,y;
vgui::input()->GetCursorPos(x, y);
// If the deletion confirmation dialog is up
if ( vgui::input()->GetAppModalSurface() )
{
ClearPreviewPanel();
// Hide the preview arrow
m_pBorderArrowImg->SetVisible( false );
return;
}
CReplayBrowserThumbnail *pOverPanel = FindThumbnailAtCursor( x, y );
if ( m_pPrevHoverPanel != pOverPanel )
{
if ( m_pPrevHoverPanel )
{
OnItemPanelExited( m_pPrevHoverPanel );
}
m_pPrevHoverPanel = pOverPanel;
if ( m_pPrevHoverPanel )
{
OnItemPanelEntered( m_pPrevHoverPanel );
}
}
}
void CReplayListPanel::OnItemPanelEntered( vgui::Panel *pPanel )
{
CReplayBrowserThumbnail *pThumbnail = dynamic_cast< CReplayBrowserThumbnail * >( pPanel );
if ( IsVisible() && pThumbnail && pThumbnail->IsVisible() )
{
ClearPreviewPanel();
// Determine which type of preview panel to display
IReplayItemManager *pItemManager;
IQueryableReplayItem *pReplayItem = FindReplayItem( pThumbnail->m_hReplayItem, &pItemManager );
AssertMsg( pReplayItem, "Why is this happening?" );
if ( !pReplayItem )
return;
if ( pReplayItem->IsItemAMovie() )
{
m_pPreviewPanel = new CReplayPreviewPanelBase( this, pReplayItem->GetItemHandle(), pItemManager );
}
else
{
m_pPreviewPanel = new CReplayPreviewPanelSlideshow( this, pReplayItem->GetItemHandle(), pItemManager );
}
m_pPreviewPanel->InvalidateLayout( true, true );
int x,y;
pThumbnail->GetPosRelativeToAncestor( this, x, y );
int nXPos, nYPos;
int nOffset = XRES( 1 );
nXPos = ( x > GetWide()/2 ) ? ( x - m_pPreviewPanel->GetWide() - nOffset ) : ( x + pThumbnail->GetWide() + nOffset );
nYPos = y + ( pThumbnail->GetTall() - m_pPreviewPanel->GetTall() ) / 2;
// Make sure the popup stays onscreen.
if ( nXPos < 0 )
{
nXPos = 0;
}
else if ( (nXPos + m_pPreviewPanel->GetWide()) > GetWide() )
{
nXPos = GetWide() - m_pPreviewPanel->GetWide();
}
if ( nYPos < 0 )
{
nYPos = 0;
}
else if ( (nYPos + m_pPreviewPanel->GetTall()) > GetTall() )
{
// Move it up as much as we can without it going below the bottom
nYPos = GetTall() - m_pPreviewPanel->GetTall();
}
// Setup the balloon's arrow
bool bLeftArrow = x < (GetWide() / 2);
SetupBorderArrow( bLeftArrow ); // Sets proper image and caches image dims in m_aBorderArrowDims
int nArrowXPos, nArrowYPos;
const int nPreviewBorderWidth = 2; // Should be just big enough to cover the preview's border width
if ( bLeftArrow )
{
// Setup the arrow along the left-hand side
nArrowXPos = nXPos - m_aBorderArrowDims[0] + nPreviewBorderWidth;
}
else
{
nArrowXPos = nXPos + m_pPreviewPanel->GetWide() - nPreviewBorderWidth;
}
nArrowYPos = MIN( nYPos + m_pPreviewPanel->GetTall() - m_pBorderArrowImg->GetTall() * 2, y + ( pThumbnail->m_pScreenshotThumb->GetTall() - m_aBorderArrowDims[1] ) / 2 );
m_pBorderArrowImg->SetPos( nArrowXPos, nArrowYPos );
m_pPreviewPanel->SetPos( nXPos, nYPos );
m_pPreviewPanel->SetVisible( true );
surface()->PlaySound( "replay\\replaypreviewpopup.wav" );
}
}
void CReplayListPanel::OnItemPanelExited( vgui::Panel *pPanel )
{
CReplayBrowserThumbnail *pThumbnail = dynamic_cast < CReplayBrowserThumbnail * > ( pPanel );
if ( pThumbnail && IsVisible() && m_pPreviewPanel )
{
m_pBorderArrowImg->SetVisible( false );
ClearPreviewPanel();
}
}
CBaseThumbnailCollection *CReplayListPanel::FindOrAddReplayThumbnailCollection( const IQueryableReplayItem *pItem, IReplayItemManager *pItemManager )
{
Assert( pItem );
if ( pItem->IsItemAMovie() )
{
return m_pMoviesCollection;
}
return m_pReplaysCollection;
}
void CReplayListPanel::AddReplaysToList()
{
// Cache off list item pointers into a temp list for processing
CUtlLinkedList< IQueryableReplayItem *, int > lstMovies;
CUtlLinkedList< IQueryableReplayItem *, int > lstReplays;
// Add all replays to a replays list
g_pReplayManager->GetReplaysAsQueryableItems( lstReplays );
// Add all movies to a movies list
g_pReplayMovieManager->GetMoviesAsQueryableItems( lstMovies );
// Go through all movies, and add them to the proper collection, based on date
FOR_EACH_LL( lstMovies, i )
{
if ( PassesFilter( lstMovies[ i ] ) )
{
AddReplayItem( lstMovies[ i ]->GetItemHandle() );
}
}
// Add any replays to the "temporary replays" collection
FOR_EACH_LL( lstReplays, i )
{
if ( PassesFilter( lstReplays[ i ] ) )
{
m_pReplaysCollection->AddReplay( lstReplays[ i ] );
}
}
// Add all collection panels to the list panel
FOR_EACH_VEC( m_vecCollections, i )
{
AddItem( NULL, m_vecCollections[ i ] );
}
}
void CReplayListPanel::RemoveCollection( CBaseThumbnailCollection *pCollection )
{
// Never remove our two base collections. If they have no entries, they display messages instead.
if ( pCollection == m_pMoviesCollection || pCollection == m_pReplaysCollection )
return;
// Find the item and remove it
int i = FirstItem();
while ( i != InvalidItemID() )
{
if ( GetItemPanel( i ) == pCollection )
{
int nNextI = NextItem( i );
RemoveItem( i );
i = nNextI;
}
else
{
i = NextItem( i );
}
}
// Remove our own cached ptr
i = m_vecCollections.Find( pCollection );
if ( i != m_vecCollections.InvalidIndex() )
{
m_vecCollections.Remove( i );
}
}
CReplayBrowserThumbnail *CReplayListPanel::FindThumbnailAtCursor( int x, int y )
{
// Is the cursor hovering over any of the thumbnails?
FOR_EACH_VEC( m_vecCollections, i )
{
CBaseThumbnailCollection *pCollection = m_vecCollections[ i ];
if ( pCollection->IsWithin( x, y ) )
{
FOR_EACH_VEC( pCollection->m_vecRows, j )
{
CReplayBrowserThumbnailRow *pRow = pCollection->m_vecRows[ j ];
if ( pRow->IsWithin( x, y ) )
{
FOR_EACH_VEC( pRow->m_vecThumbnails, k )
{
CReplayBrowserThumbnail *pThumbnail = pRow->m_vecThumbnails[ k ];
if ( pThumbnail->IsWithin( x, y ) )
{
return pThumbnail;
}
}
}
}
}
}
return NULL;
}
#if defined( WIN32 )
#define Q_wcstok( text, delimiters, context ) wcstok( text, delimiters ); context;
#elif defined( OSX ) || defined( LINUX )
#define Q_wcstok( text, delimiters, context ) wcstok( text, delimiters, context )
#endif
bool CReplayListPanel::PassesFilter( IQueryableReplayItem *pItem )
{
CGenericClassBasedReplay *pReplay = ToGenericClassBasedReplay( pItem->GetItemReplay() );
if ( !pReplay )
return false;
wchar_t wszSearchableText[1024] = L"";
wchar_t wszTemp[256];
// title
const wchar_t *pTitle = pItem->GetItemTitle();
V_wcscat_safe( wszSearchableText, pTitle );
V_wcscat_safe( wszSearchableText, L" " );
// map
const char *pMapName = GetMapDisplayName( pReplay->m_szMapName );
g_pVGuiLocalize->ConvertANSIToUnicode( pMapName, wszTemp, sizeof( wszTemp ) );
V_wcscat_safe( wszSearchableText, wszTemp );
V_wcscat_safe( wszSearchableText, L" " );
// player class
g_pVGuiLocalize->ConvertANSIToUnicode( pReplay->GetPlayerClass(), wszTemp, sizeof( wszTemp ) );
V_wcscat_safe( wszSearchableText, wszTemp );
V_wcscat_safe( wszSearchableText, L" " );
// killer name
if ( pReplay->WasKilled() )
{
g_pVGuiLocalize->ConvertANSIToUnicode( pReplay->GetKillerName(), wszTemp, sizeof( wszTemp ) );
V_wcscat_safe( wszSearchableText, wszTemp );
V_wcscat_safe( wszSearchableText, L" " );
}
// lower case
V_wcslower( wszSearchableText );
wchar_t wszFilter[256];
Q_wcsncpy( wszFilter, m_wszFilter, sizeof( wszFilter ) );
bool bPasses = true;
wchar_t seps[] = L" ";
wchar_t *last = NULL;
wchar_t *token = Q_wcstok( wszFilter, seps, &last );
while ( token && bPasses )
{
bPasses &= wcsstr( wszSearchableText, token ) != NULL;
token = Q_wcstok( NULL, seps, &last );
}
return bPasses;
}
void CReplayListPanel::AddReplayItem( ReplayItemHandle_t hItem )
{
IReplayItemManager *pItemManager;
const IQueryableReplayItem *pItem = FindReplayItem( hItem, &pItemManager );
if ( !pItem )
return;
// Find or add the collection
CBaseThumbnailCollection *pCollection = FindOrAddReplayThumbnailCollection( pItem, pItemManager );
// Add the replay
pCollection->AddReplay( pItem );
}
void CReplayListPanel::CleanupUIForReplayItem( ReplayItemHandle_t hReplayItem )
{
IReplayItemManager *pItemManager;
const IQueryableReplayItem *pReplayItem = FindReplayItem( hReplayItem, &pItemManager ); AssertValidReadPtr( pReplayItem );
CBaseThumbnailCollection *pCollection = NULL;
FOR_EACH_VEC( m_vecCollections, i )
{
CBaseThumbnailCollection *pCurCollection = m_vecCollections[ i ];
if ( pCurCollection->FindReplayItemThumbnailRow( pReplayItem ) )
{
pCollection = pCurCollection;
break;
}
}
// Find the collection associated with the given replay - NOTE: we pass false here for the "bAddIfNotFound" param
if ( !pCollection )
{
AssertMsg( 0, "REPLAY: Should have found collection while attempting to delete a replay from the browser." );
return;
}
// Clear the previous hover pointer to avoid a potential crash where we've got a stale ptr
m_pPrevHoverPanel = NULL;
// Clear out the preview panel if it exists and is for the given replay necessary
if ( m_pPreviewPanel && m_pPreviewPanel->GetReplayHandle() == pReplayItem->GetItemReplayHandle() )
{
ClearPreviewPanel();
m_pBorderArrowImg->SetVisible( false );
}
pCollection->CleanupUIForReplayItem( hReplayItem );
}
#endif
@@ -0,0 +1,80 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
//=======================================================================================//
#ifndef REPLAYBROWSER_LISTPANEL_H
#define REPLAYBROWSER_LISTPANEL_H
#ifdef _WIN32
#pragma once
#endif
#include <game/client/iviewport.h>
#include "vgui_controls/PropertyPage.h"
#include "vgui_controls/Button.h"
#include "vgui_controls/PanelListPanel.h"
#include "vgui_controls/EditablePanel.h"
#include "replaybrowseritemmanager.h"
#include "replay/genericclassbased_replay.h"
using namespace vgui;
//-----------------------------------------------------------------------------
// Forward declarations
//-----------------------------------------------------------------------------
class CBaseThumbnailCollection;
class CReplayPreviewPanelBase;
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
class CReplayBrowserThumbnail;
class CExLabel;
class CReplayListPanel : public PanelListPanel
{
DECLARE_CLASS_SIMPLE( CReplayListPanel, PanelListPanel );
public:
CReplayListPanel( Panel *pParent, const char *pName );
~CReplayListPanel();
virtual void ApplySchemeSettings( IScheme *pScheme );
virtual void PerformLayout();
void AddReplayItem( ReplayItemHandle_t hItem );
void CleanupUIForReplayItem( ReplayItemHandle_t hReplayItem );
void AddReplaysToList();
void RemoveCollection( CBaseThumbnailCollection *pCollection );
virtual void OnTick();
void OnItemPanelEntered( Panel *pPanel );
void OnItemPanelExited( Panel *pPanel );
void SetupBorderArrow( bool bLeft );
void ClearPreviewPanel();
void ApplyFilter( const wchar_t *pFilterText );
protected:
virtual void OnMouseWheeled(int delta);
private:
const IQueryableReplayItem *FindItem( ReplayItemHandle_t hItem, int *pItemManagerIndex );
CBaseThumbnailCollection *FindOrAddReplayThumbnailCollection( const IQueryableReplayItem *pItem, IReplayItemManager *pItemManager );
CReplayBrowserThumbnail *FindThumbnailAtCursor( int x, int y );
bool PassesFilter( IQueryableReplayItem *pItem );
CBaseThumbnailCollection *m_pReplaysCollection;
CBaseThumbnailCollection *m_pMoviesCollection;
CUtlVector< CBaseThumbnailCollection * > m_vecCollections;
CReplayPreviewPanelBase *m_pPreviewPanel;
Panel *m_pPrevHoverPanel;
ImagePanel *m_pBorderArrowImg;
int m_aBorderArrowDims[2];
wchar_t m_wszFilter[256];
};
#endif // REPLAYBROWSER_LISTPANEL_H
@@ -0,0 +1,449 @@
//========= 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 <tier0/memdbgon.h>
//-----------------------------------------------------------------------------
// 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<CReplayBrowserPanel> 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
@@ -0,0 +1,89 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#if defined( REPLAY_ENABLED )
#ifndef REPLAYBROWSER_MAIN_PANEL_H
#define REPLAYBROWSER_MAIN_PANEL_H
#ifdef _WIN32
#pragma once
#endif
#include "vgui_controls/PropertyDialog.h"
#include "replay/replayhandle.h"
#include "GameEventListener.h"
#include "replaybrowseritemmanager.h"
//-----------------------------------------------------------------------------
class CReplayBrowserBasePage;
class CConfirmDeleteDialog;
class CExButton;
//-----------------------------------------------------------------------------
class CReplayBrowserPanel : public vgui::PropertyDialog,
public CGameEventListener
{
DECLARE_CLASS_SIMPLE( CReplayBrowserPanel, vgui::PropertyDialog );
public:
CReplayBrowserPanel( Panel *parent );
virtual ~CReplayBrowserPanel();
void OnSaveReplay( ReplayHandle_t hNewReplay );
void OnDeleteReplay( ReplayHandle_t hDeletedReplay );
void DeleteReplay( ReplayHandle_t hReplay );
virtual void CleanupUIForReplayItem( ReplayItemHandle_t hReplay ); // After a replay has been deleted - deletes all UI (thumbnail, but maybe also row and/or collection as well)
virtual void ApplySchemeSettings( vgui::IScheme *pScheme );
virtual void PerformLayout( void );
virtual void OnCommand( const char *command );
virtual void ShowPanel( bool bShow, ReplayHandle_t hReplayDetails = REPLAY_HANDLE_INVALID, int iPerformance = -1 );
virtual void OnKeyCodeTyped(vgui::KeyCode code);
virtual void OnKeyCodePressed(vgui::KeyCode code);
virtual void FireGameEvent( IGameEvent *event );
MESSAGE_FUNC_PARAMS( OnConfirmDelete, "ConfirmDlgResult", data );
void AttemptToDeleteReplayItem( Panel *pHandler, ReplayItemHandle_t hReplayItem, IReplayItemManager *pItemManager, int iPerformance );
CReplayBrowserBasePage *m_pReplaysPage;
CConfirmDeleteDialog *m_pConfirmDeleteDialog;
struct DeleteInfo_t
{
ReplayItemHandle_t m_hReplayItem;
IReplayItemManager *m_pItemManager;
vgui::VPANEL m_hHandler;
int m_iPerformance;
};
DeleteInfo_t m_DeleteInfo;
float GetTimeOpened( void ){ return m_flTimeOpened; }
private:
void ShowDeleteReplayDenialDlg();
void ConfirmReplayItemDelete( Panel *pHandler, ReplayItemHandle_t hReplayItem, IReplayItemManager *pItemManager, int iPerformance );
float m_flTimeOpened;
};
//-----------------------------------------------------------------------------
CReplayBrowserPanel *ReplayUI_GetBrowserPanel();
void ReplayUI_ReloadBrowser( ReplayHandle_t hReplay = REPLAY_HANDLE_INVALID, int iPerformance = -1 );
void ReplayUI_CloseReplayBrowser();
//-----------------------------------------------------------------------------
#endif // REPLAYBROWSER_MAIN_PANEL_H
#endif
@@ -0,0 +1,220 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
//=======================================================================================//
#include "cbase.h"
#if defined( REPLAY_ENABLED )
#include "replaybrowsermovieplayerpanel.h"
#include "vgui/IVGui.h"
#include "vgui/IInput.h"
#include "engine/IEngineSound.h"
#include "iclientmode.h"
//-----------------------------------------------------------------------------
using namespace vgui;
//-----------------------------------------------------------------------------
CMoviePlayerPanel::CMoviePlayerPanel( Panel *pParent, const char *pName, const char *pMovieFilename )
: CReplayBasePanel( pParent, pName ),
m_flCurFrame( 0.0f ),
m_flLastTime( 0.0f ),
m_nLastMouseXPos( 0 ),
m_bPlaying( false ),
m_bLooping( false ),
m_bFullscreen( false ),
m_bMouseOverScrub( false ),
m_pOldParent( NULL ),
m_pVideoMaterial( NULL )
{
if ( g_pVideo )
{
m_pVideoMaterial = g_pVideo->CreateVideoMaterial( pMovieFilename, pMovieFilename, "GAME" );
if ( m_pVideoMaterial )
{
m_pMaterial = m_pVideoMaterial->GetMaterial();
m_pMaterial->AddRef();
m_nNumFrames = m_pVideoMaterial->GetFrameCount();
}
}
ivgui()->AddTickSignal( GetVPanel(), 0 );
}
CMoviePlayerPanel::~CMoviePlayerPanel()
{
FreeMaterial();
ivgui()->RemoveTickSignal( GetVPanel() );
}
void CMoviePlayerPanel::PerformLayout()
{
BaseClass::PerformLayout();
GetPosRelativeToAncestor( NULL, m_nGlobalPos[0], m_nGlobalPos[1] );
if ( m_bFullscreen )
{
// Cache parent
m_pOldParent = GetParent();
GetBounds( m_aOldBounds[0], m_aOldBounds[1], m_aOldBounds[2], m_aOldBounds[3] );
// Adjust parent for fullscreen mode
SetParent( g_pClientMode->GetViewport() );
// Adjust bounds for fullscreen
SetBounds( 0, 0, ScreenWidth(), ScreenHeight() );
}
else if ( m_pOldParent )
{
// Restore old parent/bounds
SetParent( m_pOldParent );
SetBounds( m_aOldBounds[0], m_aOldBounds[1], m_aOldBounds[2], m_aOldBounds[3] );
}
}
void CMoviePlayerPanel::OnMousePressed( MouseCode code )
{
// ToggleFullscreen();
}
void CMoviePlayerPanel::SetScrubOnMouseOverMode( bool bOn )
{
if ( bOn )
{
m_bPlaying = false;
}
m_bMouseOverScrub = bOn;
}
void CMoviePlayerPanel::Play()
{
m_bPlaying = true;
m_flLastTime = gpGlobals->realtime;
enginesound->NotifyBeginMoviePlayback();
}
void CMoviePlayerPanel::FreeMaterial()
{
if ( m_pVideoMaterial )
{
if ( g_pVideo )
{
g_pVideo->DestroyVideoMaterial( m_pVideoMaterial );
}
m_pVideoMaterial = NULL;
}
if ( m_pMaterial )
{
m_pMaterial->Release();
m_pMaterial = NULL;
}
}
void CMoviePlayerPanel::OnTick()
{
if ( !IsEnabled() )
return;
if ( m_bMouseOverScrub )
{
int nMouseX, nMouseY;
input()->GetCursorPos( nMouseX, nMouseY );
if ( IsWithin( nMouseX, nMouseY ) &&
nMouseX != m_nLastMouseXPos )
{
float flPercent = (float)( nMouseX - m_nGlobalPos[0] ) / GetWide();
m_flCurFrame = flPercent * ( m_nNumFrames - 1 );
m_nLastMouseXPos = nMouseX;
}
}
else if ( m_bPlaying )
{
float flElapsed = gpGlobals->realtime - m_flLastTime;
m_flLastTime = gpGlobals->realtime;
m_flCurFrame += flElapsed * m_pVideoMaterial->GetVideoFrameRate().GetFPS();
// Loop if necessary
if ( m_flCurFrame >= m_nNumFrames )
{
if ( m_bLooping )
{
m_flCurFrame = m_flCurFrame - m_nNumFrames;
}
else
{
// Don't go past last frame
m_flCurFrame = m_nNumFrames - 1;
}
}
}
m_pVideoMaterial->SetFrame( m_flCurFrame );
// Msg( "frame: %f / %i\n", m_flCurFrame, m_nNumFrames );
}
void CMoviePlayerPanel::Paint()
{
if ( m_pVideoMaterial == NULL )
return;
// Get panel position/dimensions
int x,y;
int w,h;
GetPosRelativeToAncestor( NULL, x, y );
GetSize( w,h );
CMatRenderContextPtr pRenderContext( materials );
pRenderContext->Bind( m_pMaterial );
IMesh* pMesh = pRenderContext->GetDynamicMesh( true );
float flMinU = 0.0f, flMinV = 0.0f;
float flMaxU, flMaxV;
m_pVideoMaterial->GetVideoTexCoordRange( &flMaxU, &flMaxV );
CMeshBuilder meshBuilder;
meshBuilder.Begin( pMesh, MATERIAL_QUADS, 1 );
meshBuilder.Position3f( x, y, 0.0f );
meshBuilder.TexCoord2f( 0, flMinU, flMinV );
meshBuilder.Color4ub( 255, 255, 255, 255 );
meshBuilder.AdvanceVertex();
meshBuilder.Position3f( x + w, y, 0.0f );
meshBuilder.TexCoord2f( 0, flMaxU, flMinV );
meshBuilder.Color4ub( 255, 255, 255, 255 );
meshBuilder.AdvanceVertex();
meshBuilder.Position3f( x + w, y + h, 0.0f );
meshBuilder.TexCoord2f( 0, flMaxU, flMaxV );
meshBuilder.Color4ub( 255, 255, 255, 255 );
meshBuilder.AdvanceVertex();
meshBuilder.Position3f( x, y + h, 0.0f );
meshBuilder.TexCoord2f( 0, flMinU, flMaxV );
meshBuilder.Color4ub( 255, 255, 255, 255 );
meshBuilder.AdvanceVertex();
meshBuilder.End();
pMesh->Draw();
}
void CMoviePlayerPanel::ToggleFullscreen()
{
m_bFullscreen = !m_bFullscreen;
InvalidateLayout( false, false );
}
#endif
@@ -0,0 +1,57 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
//=======================================================================================//
#ifndef REPLAYBROWSERMOVIEPLAYERPANEL_H
#define REPLAYBROWSERMOVIEPLAYERPANEL_H
#ifdef _WIN32
#pragma once
#endif
#include "replaybrowserbasepanel.h"
#include "video/ivideoservices.h"
using namespace vgui;
//-----------------------------------------------------------------------------
// Purpose: A panel that plays AVI's
//-----------------------------------------------------------------------------
class CMoviePlayerPanel : public CReplayBasePanel
{
DECLARE_CLASS_SIMPLE( CMoviePlayerPanel, CReplayBasePanel );
public:
CMoviePlayerPanel( Panel *pParent, const char *pName, const char *pMovieFilename );
~CMoviePlayerPanel();
virtual void Paint();
void Play();
void SetLooping( bool bLooping ) { m_bLooping = bLooping; }
bool IsPlaying() { return m_bPlaying; }
void SetScrubOnMouseOverMode( bool bOn );
void FreeMaterial();
void ToggleFullscreen();
private:
virtual void PerformLayout();
virtual void OnMousePressed( MouseCode code );
virtual void OnTick();
IVideoMaterial *m_pVideoMaterial;
IMaterial *m_pMaterial;
float m_flCurFrame;
int m_nNumFrames;
bool m_bPlaying;
bool m_bLooping;
float m_flLastTime;
int m_nGlobalPos[2];
int m_nLastMouseXPos;
bool m_bFullscreen;
Panel *m_pOldParent;
int m_aOldBounds[4];
bool m_bMouseOverScrub; // In this mode, we don't playback, only scrub on mouse over
};
#endif // REPLAYBROWSERMOVIEPLAYERPANEL_H
@@ -0,0 +1,301 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================//
#include "cbase.h"
#if defined( REPLAY_ENABLED )
#include "replaybrowserpreviewpanel.h"
#include "replaybrowsermainpanel.h"
#include "replaybrowsermovieplayerpanel.h"
#include "replaybrowserlistitempanel.h"
#include "replay/ireplaymovie.h"
#include "replay/screenshot.h"
#include "vgui/ISurface.h"
#include "econ/econ_controls.h"
// memdbgon must be the last include file in a .cpp file!!!
#include <tier0/memdbgon.h>
//-----------------------------------------------------------------------------
CReplayPreviewPanelBase::CReplayPreviewPanelBase( Panel *pParent, QueryableReplayItemHandle_t hItem, IReplayItemManager *pItemManager )
: EditablePanel( pParent, "PreviewPanel" ),
m_hItem( hItem ),
m_pItemManager( pItemManager )
{
CGenericClassBasedReplay *pReplay = GetReplay();
IQueryableReplayItem *pItem = pItemManager->GetItem( hItem );
// Setup class image
char szImage[MAX_OSPATH];
m_pClassImage = new ImagePanel( this, "ClassImage" );
V_snprintf( szImage, sizeof( szImage ), "class_sel_sm_%s_%s", pReplay->GetMaterialFriendlyPlayerClass(), pReplay->GetPlayerTeam() ); // Cause default image to display
m_pClassImage->SetImage( szImage );
m_pInfoPanel = new vgui::EditablePanel( this, "InfoPanel" );
// Setup map label
const char *pMapName = pReplay->m_szMapName;
const char *pUnderscore = V_strstr( pMapName, "_" );
if ( pUnderscore )
{
pMapName = pUnderscore + 1;
}
m_pMapLabel = new CExLabel( m_pInfoPanel, "MapLabel", pMapName );
// Setup record date/time
const CReplayTime &RecordTime = pItem->GetItemDate();
int nDay, nMonth, nYear;
RecordTime.GetDate( nDay, nMonth, nYear );
int nHour, nMin, nSec;
RecordTime.GetTime( nHour, nMin, nSec );
const wchar_t *pDateAndTime = CReplayTime::GetLocalizedDate( g_pVGuiLocalize, nDay, nMonth, nYear, &nHour, &nMin, &nSec );
// Setup date / time label
m_pDateTimeLabel = new CExLabel( m_pInfoPanel, "DateTimeLabel", pDateAndTime );
// Setup info labels
for ( int i = 0; i < NUM_INFO_LABELS; ++i )
{
for ( int j = 0; j < 2; ++j )
{
m_pReplayInfoLabels[i][j] = new CExLabel( m_pInfoPanel, VarArgs("Label%d_%d", i, j), "" );
}
}
m_pReplayInfoLabels[ LABEL_PLAYED_AS ][1]->SetText( pReplay->GetPlayerClass() );
m_pReplayInfoLabels[ LABEL_KILLED_BY ][1]->SetText( pReplay->WasKilled() ? pReplay->GetKillerName() : "#Replay_NoKiller" );
m_pReplayInfoLabels[ LABEL_LIFE_LENGTH ][1]->SetText( CReplayTime::FormatTimeString( (int)pItem->GetItemLength() ) );
}
CReplayPreviewPanelBase::~CReplayPreviewPanelBase()
{
}
void CReplayPreviewPanelBase::ApplySchemeSettings( IScheme *pScheme )
{
BaseClass::ApplySchemeSettings( pScheme );
LoadControlSettings( "resource/ui/replaybrowser/previewpanel.res", "GAME" );
#if !defined( TF_CLIENT_DLL )
m_pClassImage->SetVisible( false );
#endif
}
void CReplayPreviewPanelBase::PerformLayout()
{
BaseClass::PerformLayout();
CGenericClassBasedReplay *pReplay = GetReplay();
if ( !pReplay )
return;
int nWide = XRES(18);
int nTall = YRES(18);
int nScreenshotH = 0; // Represents the height of the screenshot OR the "no screenshot" label
LayoutView( nWide, nTall, nScreenshotH );
int iInfoHeight = m_pInfoPanel->GetTall();
nTall += iInfoHeight;
if ( m_pClassImage )
{
int w, h;
m_pClassImage->GetImage()->GetContentSize( w, h );
float s = ShoudlUseLargeClassImage() ? 1.25f : 1.0f;
int nClassTall = s*h;
m_pClassImage->SetSize( s*w, nClassTall );
m_pClassImage->SetShouldScaleImage( true );
m_pClassImage->SetScaleAmount( s );
// The panel should be at least as tall as the height of the screenshot
// (or "no screenshot" label) and the class image.
if ( nTall < nClassTall )
{
nTall = nClassTall;
}
m_pClassImage->SetPos( XRES(9), nTall - nClassTall );
}
const int nLabelX = m_pClassImage->GetWide() + XRES( 18 );
int iInfoWidth = nWide - nLabelX;
m_pMapLabel->SetSize( iInfoWidth, m_pMapLabel->GetTall() );
m_pDateTimeLabel->SetSize( iInfoWidth, m_pMapLabel->GetTall() );
m_pInfoPanel->SetBounds( nLabelX, nTall - iInfoHeight, iInfoWidth, iInfoHeight );
nTall += YRES(9);
SetSize( nWide, nTall );
}
void CReplayPreviewPanelBase::LayoutView( int &nWide, int &nTall, int &nCurY )
{
nWide = XRES( 188 );
nTall = YRES(9);
nCurY = nTall;
}
CGenericClassBasedReplay *CReplayPreviewPanelBase::GetReplay()
{
return ToGenericClassBasedReplay( m_pItemManager->GetItem( m_hItem )->GetItemReplay() );
}
ReplayHandle_t CReplayPreviewPanelBase::GetReplayHandle()
{
return GetReplay()->GetHandle();
}
//-----------------------------------------------------------------------------
CReplayPreviewPanelSlideshow::CReplayPreviewPanelSlideshow( Panel *pParent, QueryableReplayItemHandle_t hReplay, IReplayItemManager *pItemManager )
: BaseClass( pParent, hReplay, pItemManager ),
m_pScreenshotPanel( NULL )
{
// Setup screenshot slideshow panel
CGenericClassBasedReplay *pReplay = GetReplay();
const int nScreenshotCount = pReplay->GetScreenshotCount();
if ( nScreenshotCount )
{
m_pScreenshotPanel = new CReplayScreenshotSlideshowPanel( this, "ScreenshotSlideshowPanel", hReplay );
// Set pretty quick transition times based on the screenshot count
m_pScreenshotPanel->SetInterval( ( nScreenshotCount == 2 ) ? 3.0f : 2.0f );
m_pScreenshotPanel->SetTransitionTime( 0.5f );
}
// Setup the no screenshot label
m_pNoScreenshotLabel = new CExLabel( this, "NoScreenshotLabel", "#Replay_NoScreenshot" );
m_pNoScreenshotLabel->SetVisible( false );
}
void CReplayPreviewPanelSlideshow::PerformLayout()
{
BaseClass::PerformLayout();
m_pNoScreenshotLabel->SizeToContents();
m_pNoScreenshotLabel->SetWide( GetWide() );
}
void CReplayPreviewPanelSlideshow::LayoutView( int &nWide, int &nTall, int &nCurY )
{
if ( m_pScreenshotPanel )
{
// Use the dimensions from the first screenshot to figure out the scale, even though the dimensions
// may vary if the user changed resolutions during gameplay
CGenericClassBasedReplay *pReplay = GetReplay();
const CReplayScreenshot *pScreenshot = pReplay->GetScreenshot( 0 );
int nScreenshotW = pScreenshot->m_nWidth;
int nScreenshotH = pScreenshot->m_nHeight;
// Scale the screenshot if it's too big for the current resolution
float flScreenshotScale = 1.0f;
int nMaxScreenshotWidth = ScreenWidth() / 3;
if ( nScreenshotW > nMaxScreenshotWidth )
{
flScreenshotScale = (float)nMaxScreenshotWidth / pScreenshot->m_nWidth;
nScreenshotW = nMaxScreenshotWidth;
}
nCurY = nScreenshotH * flScreenshotScale;
m_pScreenshotPanel->GetImagePanel()->SetShouldScaleImage( true );
m_pScreenshotPanel->GetImagePanel()->SetScaleAmount( flScreenshotScale );
nWide += nScreenshotW;
nTall += nCurY;
m_pScreenshotPanel->SetBounds( (nWide - nScreenshotW) * 0.5, YRES(9), nScreenshotW, nCurY );
}
else
{
int w, h;
m_pNoScreenshotLabel->SetContentAlignment( Label::a_center );
m_pNoScreenshotLabel->GetContentSize( w, h );
nTall += YRES( 20 );
m_pNoScreenshotLabel->SetBounds( 0, nTall, w, h );
nTall += YRES( 20 );
m_pNoScreenshotLabel->SetVisible( true );
nWide += XRES( 213 ); // Default width (maps to 640 on 1920x1200)
nTall += h;
nCurY = nTall;
}
}
//-----------------------------------------------------------------------------
CReplayPreviewPanelMovie::CReplayPreviewPanelMovie( Panel *pParent, QueryableReplayItemHandle_t hItem, IReplayItemManager *pItemManager )
: BaseClass( pParent, hItem, pItemManager ),
m_pMoviePlayerPanel( NULL )
{
m_flCreateTime = gpGlobals->realtime;
ivgui()->AddTickSignal( GetVPanel(), 10 );
}
CReplayPreviewPanelMovie::~CReplayPreviewPanelMovie()
{
ivgui()->RemoveTickSignal( GetVPanel() );
}
void CReplayPreviewPanelMovie::OnTick()
{
if ( gpGlobals->realtime >= m_flCreateTime + 0.5f )
{
if ( !m_pMoviePlayerPanel )
{
m_pMoviePlayerPanel = new CMoviePlayerPanel( this, "MoviePlayer", GetReplayMovie()->GetMovieFilename() );
InvalidateLayout( true, false );
}
if ( !m_pMoviePlayerPanel->IsPlaying() )
{
m_pMoviePlayerPanel->SetLooping( true );
m_pMoviePlayerPanel->Play();
}
}
}
IReplayMovie* CReplayPreviewPanelMovie::GetReplayMovie()
{
return static_cast< IReplayMovie * >( m_pItemManager->GetItem( m_hItem ) );
}
void CReplayPreviewPanelMovie::LayoutView( int &nWide, int &nTall, int &nCurY )
{
// Get frame dimensions
int nFrameWidth, nFrameHeight;
IReplayMovie* pReplayMovie = GetReplayMovie();
pReplayMovie->GetFrameDimensions( nFrameWidth, nFrameHeight );
int nScaledWidth = nFrameWidth;
int nScaledHeight = nFrameHeight;
// Scale the screenshot if it's too big for the current resolution
float flScale = 1.0f;
int nMaxWidth = ScreenWidth() / 3;
if ( nFrameWidth > nMaxWidth )
{
flScale = (float)nMaxWidth / nFrameWidth;
nScaledWidth = nMaxWidth;
nScaledHeight = nFrameHeight * flScale;
}
nWide += nScaledWidth;
nTall += nScaledHeight;
nCurY = nTall;
// Layout movie player panel if it's ready
if ( m_pMoviePlayerPanel )
{
m_pMoviePlayerPanel->SetBounds( 9, 9, nScaledWidth, nScaledHeight );
m_pMoviePlayerPanel->SetEnabled( true );
m_pMoviePlayerPanel->SetVisible( true );
m_pMoviePlayerPanel->SetZPos( 101 );
}
}
#endif
@@ -0,0 +1,120 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#ifndef REPLAYBROWSER_PREVIEWPANEL_H
#define REPLAYBROWSER_PREVIEWPANEL_H
#ifdef _WIN32
#pragma once
#endif
#include <game/client/iviewport.h>
#include "vgui_controls/PropertyPage.h"
#include "vgui_controls/Button.h"
#include "vgui_controls/PanelListPanel.h"
#include "vgui_controls/EditablePanel.h"
#include "replaybrowseritemmanager.h"
#include "replay/genericclassbased_replay.h"
using namespace vgui;
//-----------------------------------------------------------------------------
// Forward declarations
//-----------------------------------------------------------------------------
class CExLabel;
class CBaseThumbnailCollection;
class CReplayDetailsPanel;
class CReplayScreenshotSlideshowPanel;
//-----------------------------------------------------------------------------
// Purpose: Preview balloon
//-----------------------------------------------------------------------------
class CGenericClassBasedReplay;
class CCrossfadableImagePanel;
class CSlideshowPanel;
class CReplayPreviewPanelBase : public EditablePanel
{
DECLARE_CLASS_SIMPLE( CReplayPreviewPanelBase, EditablePanel );
public:
CReplayPreviewPanelBase( Panel *pParent, QueryableReplayItemHandle_t hItem, IReplayItemManager *pItemManager );
~CReplayPreviewPanelBase();
virtual void ApplySchemeSettings( IScheme *pScheme );
virtual void PerformLayout();
ReplayHandle_t GetReplayHandle();
protected:
CGenericClassBasedReplay *GetReplay();
virtual bool ShoudlUseLargeClassImage() { return false; }
virtual void LayoutView( int &nWide, int &nTall, int &nCurY );
protected:
IReplayItemManager *m_pItemManager;
QueryableReplayItemHandle_t m_hItem;
private:
ImagePanel *m_pClassImage;
vgui::EditablePanel *m_pInfoPanel;
CExLabel *m_pMapLabel;
CExLabel *m_pDateTimeLabel;
enum ELabels
{
LABEL_PLAYED_AS,
LABEL_KILLED_BY,
LABEL_LIFE_LENGTH,
NUM_INFO_LABELS
};
CExLabel *m_pReplayInfoLabels[NUM_INFO_LABELS][2];
};
//-----------------------------------------------------------------------------
// Purpose: Preview balloon for slideshows (actual replays)
//-----------------------------------------------------------------------------
class CReplayPreviewPanelSlideshow : public CReplayPreviewPanelBase
{
DECLARE_CLASS_SIMPLE( CReplayPreviewPanelSlideshow, CReplayPreviewPanelBase );
public:
CReplayPreviewPanelSlideshow( Panel *pParent, QueryableReplayItemHandle_t hItem, IReplayItemManager *pItemManager );
private:
virtual void PerformLayout();
virtual void LayoutView( int &nWide, int &nTall, int &nCurY );
CReplayScreenshotSlideshowPanel *m_pScreenshotPanel;
CExLabel *m_pNoScreenshotLabel;
};
//-----------------------------------------------------------------------------
// Purpose: Preview balloon for movies (rendered replays)
//-----------------------------------------------------------------------------
class CMoviePlayerPanel;
class IReplayMovie;
class CReplayPreviewPanelMovie : public CReplayPreviewPanelBase
{
DECLARE_CLASS_SIMPLE( CReplayPreviewPanelMovie, CReplayPreviewPanelBase );
public:
CReplayPreviewPanelMovie( Panel *pParent, QueryableReplayItemHandle_t hItem, IReplayItemManager *pItemManager );
~CReplayPreviewPanelMovie();
private:
virtual void OnTick();
virtual void LayoutView( int &nWide, int &nTall, int &nCurY );
virtual IReplayMovie *GetReplayMovie();
CMoviePlayerPanel *m_pMoviePlayerPanel;
float m_flCreateTime;
};
#endif // REPLAYBROWSER_PREVIEWPANEL_H
@@ -0,0 +1,639 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
//=======================================================================================//
#include "cbase.h"
#if defined( REPLAY_ENABLED )
#include "replaybrowserrenderdialog.h"
#include "vgui_controls/TextImage.h"
#include "vgui_controls/CheckButton.h"
#include "vgui_controls/TextEntry.h"
#include "vgui/IInput.h"
#include "replay/genericclassbased_replay.h"
#include "ienginevgui.h"
#include "replayrenderoverlay.h"
#include "replay/ireplaymanager.h"
#include "replay/ireplaymoviemanager.h"
#include "video/ivideoservices.h"
#include "confirm_dialog.h"
#include "replay/replayrenderer.h"
#include "replay/performance.h"
#include "replay/replayvideo.h"
#include "replay_gamestats_shared.h"
#include "econ/econ_controls.h"
// memdbgon must be the last include file in a .cpp file!!!
#include <tier0/memdbgon.h>
//-----------------------------------------------------------------------------
extern IReplayMovieManager *g_pReplayMovieManager;
//-----------------------------------------------------------------------------
ConVar replay_rendersetting_quitwhendone( "replay_rendersetting_quitwhendone", "0", FCVAR_CLIENTDLL | FCVAR_DONTRECORD, "Quit after rendering is completed.", true, 0.0f, true, 1.0f );
ConVar replay_rendersetting_exportraw( "replay_rendersetting_exportraw", "0", FCVAR_CLIENTDLL | FCVAR_DONTRECORD | FCVAR_ARCHIVE, "Export raw TGA frames and a .wav file, instead of encoding a movie file.", true, 0.0f, true, 1.0f );
ConVar replay_rendersetting_motionblurquality( "replay_rendersetting_motionblurquality", "0", FCVAR_CLIENTDLL | FCVAR_DONTRECORD, "Motion blur quality.", true, 0, true, MAX_MOTION_BLUR_QUALITY );
ConVar replay_rendersetting_motionblurenabled( "replay_rendersetting_motionblurenabled", "1", FCVAR_CLIENTDLL | FCVAR_DONTRECORD, "Motion blur enabled/disabled.", true, 0.0f, true, 1.0f );
ConVar replay_rendersetting_encodingquality( "replay_rendersetting_encodingquality", "100", FCVAR_CLIENTDLL | FCVAR_DONTRECORD, "Render quality: the higher the quality, the larger the resulting movie file size.", true, 0, true, 100 );
ConVar replay_rendersetting_motionblur_can_toggle( "replay_rendersetting_motionblur_can_toggle", "0", FCVAR_CLIENTDLL | FCVAR_DONTRECORD, "" );
ConVar replay_rendersetting_renderglow( "replay_rendersetting_renderglow", "0", FCVAR_CLIENTDLL | FCVAR_DONTRECORD | FCVAR_ARCHIVE, "Glow effect enabled/disabled.", true, 0.0f, true, 1.0f );
//-----------------------------------------------------------------------------
CReplayRenderDialog::CReplayRenderDialog( Panel *pParent, ReplayHandle_t hReplay, bool bSetQuit, int iPerformance )
: BaseClass( pParent, "RenderDialog" ),
m_bShowAdvancedOptions( false ),
m_hReplay( hReplay ),
m_bSetQuit( bSetQuit ),
m_iPerformance( iPerformance ),
m_pVideoModesCombo( NULL ),
m_pCodecCombo( NULL ),
m_pPlayVoiceCheck( NULL ),
m_pShowAdvancedOptionsCheck( NULL ),
m_pQuitWhenDoneCheck( NULL ),
m_pExportRawCheck( NULL ),
m_pTitleText( NULL ),
m_pResolutionNoteLabel( NULL ),
m_pEnterANameLabel( NULL ),
m_pVideoModeLabel( NULL ),
m_pCodecLabel( NULL ),
m_pMotionBlurLabel( NULL ),
m_pMotionBlurSlider( NULL ),
m_pQualityLabel( NULL ),
m_pQualitySlider( NULL ),
m_pTitleLabel( NULL ),
m_pCancelButton( NULL ),
m_pRenderButton( NULL ),
m_pBgPanel( NULL ),
m_pMotionBlurCheck( NULL ),
m_pQualityPresetLabel( NULL ),
m_pQualityPresetCombo( NULL ),
m_pSeparator( NULL ),
m_pGlowEnabledCheck( NULL )
{
m_iQualityPreset = ReplayVideo_GetDefaultQualityPreset();
}
void CReplayRenderDialog::UpdateControlsValues()
{
ConVarRef replay_voice_during_playback( "replay_voice_during_playback" );
m_pQuitWhenDoneCheck->SetSelected( replay_rendersetting_quitwhendone.GetBool() );
m_pExportRawCheck->SetSelected( replay_rendersetting_exportraw.GetBool() );
m_pShowAdvancedOptionsCheck->SetSelected( m_bShowAdvancedOptions );
m_pMotionBlurSlider->SetValue( replay_rendersetting_motionblurquality.GetInt() );
m_pMotionBlurCheck->SetSelected( replay_rendersetting_motionblurenabled.GetBool() );
m_pQualitySlider->SetValue( replay_rendersetting_encodingquality.GetInt() / ReplayVideo_GetQualityInterval() );
if ( m_pGlowEnabledCheck )
{
m_pGlowEnabledCheck->SetSelected( replay_rendersetting_renderglow.GetBool() );
}
if ( replay_voice_during_playback.IsValid() )
{
m_pPlayVoiceCheck->SetSelected( replay_voice_during_playback.GetBool() );
}
else
{
m_pPlayVoiceCheck->SetEnabled( false );
}
}
void CReplayRenderDialog::AddControlToAutoLayout( Panel *pPanel, bool bAdvanced )
{
LayoutInfo_t *pNewLayoutInfo = new LayoutInfo_t;
pNewLayoutInfo->pPanel = pPanel;
// Use the positions from the .res file as relative positions for auto-layout
pPanel->GetPos( pNewLayoutInfo->nOffsetX, pNewLayoutInfo->nOffsetY );
pNewLayoutInfo->bAdvanced = bAdvanced;
// Add to the list
m_lstControls.AddToTail( pNewLayoutInfo );
}
void CReplayRenderDialog::SetValuesFromQualityPreset()
{
const ReplayQualityPreset_t &preset = ReplayVideo_GetQualityPreset( m_iQualityPreset );
replay_rendersetting_motionblurquality.SetValue( preset.m_iMotionBlurQuality );
replay_rendersetting_motionblurenabled.SetValue( (int)preset.m_bMotionBlurEnabled );
replay_rendersetting_encodingquality.SetValue( preset.m_iQuality );
for ( int i = 0; i < ReplayVideo_GetCodecCount(); ++i )
{
const ReplayCodec_t &CurCodec = ReplayVideo_GetCodec( i );
if ( CurCodec.m_nCodecId == preset.m_nCodecId )
{
m_pCodecCombo->ActivateItem( m_pCodecCombo->GetItemIDFromRow( i ) );
break;
}
}
UpdateControlsValues();
InvalidateLayout();
}
void CReplayRenderDialog::ApplySchemeSettings( vgui::IScheme *pScheme )
{
int i;
// Link in TF scheme
extern IEngineVGui *enginevgui;
vgui::HScheme pTFScheme = vgui::scheme()->LoadSchemeFromFileEx( enginevgui->GetPanel( PANEL_CLIENTDLL ), "resource/ClientScheme.res", "ClientScheme" );
SetScheme( pTFScheme );
SetProportional( true );
BaseClass::ApplySchemeSettings( vgui::scheme()->GetIScheme( pTFScheme ) );
LoadControlSettings( "Resource/UI/replaybrowser/renderdialog.res", "GAME" );
// retrieve controls
m_pPlayVoiceCheck = dynamic_cast< CheckButton * >( FindChildByName( "PlayVoice" ) );
m_pShowAdvancedOptionsCheck = dynamic_cast< CheckButton * >( FindChildByName( "ShowAdvancedOptions" ) );
m_pQuitWhenDoneCheck = dynamic_cast< CheckButton * >( FindChildByName( "QuitWhenDone" ) );
m_pExportRawCheck = dynamic_cast< CheckButton * >( FindChildByName( "ExportRaw" ) );
m_pTitleText = dynamic_cast< TextEntry * >( FindChildByName( "TitleInput" ) );
m_pResolutionNoteLabel = dynamic_cast< CExLabel * >( FindChildByName( "ResolutionNoteLabel" ) );
m_pEnterANameLabel = dynamic_cast< CExLabel * >( FindChildByName( "EnterANameLabel" ) );
m_pVideoModeLabel = dynamic_cast< CExLabel * >( FindChildByName( "VideoModeLabel" ) );
m_pCodecLabel = dynamic_cast< CExLabel * >( FindChildByName( "CodecLabel" ) );
m_pMotionBlurLabel = dynamic_cast< CExLabel * >( FindChildByName( "MotionBlurLabel" ) );
m_pMotionBlurSlider = dynamic_cast< Slider * >( FindChildByName( "MotionBlurSlider" ) );
m_pQualityLabel = dynamic_cast< CExLabel * >( FindChildByName( "QualityLabel" ) );
m_pQualitySlider = dynamic_cast< Slider * >( FindChildByName( "QualitySlider" ) );
m_pTitleLabel = dynamic_cast< CExLabel * >( FindChildByName( "TitleLabel" ) );
m_pRenderButton = dynamic_cast< CExButton * >( FindChildByName( "RenderButton" ) );
m_pCancelButton = dynamic_cast< CExButton * >( FindChildByName( "CancelButton" ) );
m_pBgPanel = dynamic_cast< EditablePanel * >( FindChildByName( "BGPanel" ) );
m_pMotionBlurCheck = dynamic_cast< CheckButton * >( FindChildByName( "MotionBlurEnabled" ) );
m_pQualityPresetLabel = dynamic_cast< CExLabel * >( FindChildByName( "QualityPresetLabel" ) );
m_pQualityPresetCombo = dynamic_cast< vgui::ComboBox * >( FindChildByName( "QualityPresetCombo" ) );
m_pCodecCombo = dynamic_cast< vgui::ComboBox * >( FindChildByName( "CodecCombo" ) );
m_pVideoModesCombo = dynamic_cast< vgui::ComboBox * >( FindChildByName( "VideoModeCombo" ) );
m_pEstimateTimeLabel = dynamic_cast< CExLabel * >( FindChildByName( "EstimateTimeLabel" ) );
m_pEstimateFileLabel = dynamic_cast< CExLabel * >( FindChildByName( "EstimateFileLabel" ) );
m_pSeparator = FindChildByName( "SeparatorLine" );
m_pGlowEnabledCheck = dynamic_cast< CheckButton * >( FindChildByName( "GlowEnabled" ) );
m_pLockWarningLabel = dynamic_cast< CExLabel * >( FindChildByName( "LockWarningLabel" ) );
#if defined( TF_CLIENT_DLL )
if ( m_pBgPanel )
{
m_pBgPanel->SetPaintBackgroundType( 2 ); // Rounded.
}
#endif
AddControlToAutoLayout( m_pTitleLabel, false );
// The replay may be REPLAY_HANDLE_INVALID in the case that we are about to render all unrendered replays
if ( m_hReplay != REPLAY_HANDLE_INVALID )
{
CGenericClassBasedReplay *pReplay = GetGenericClassBasedReplay( m_hReplay );
m_pTitleText->SetText( pReplay->m_wszTitle );
m_pTitleText->SetVisible( true );
m_pTitleLabel->SetText( "#Replay_RenderReplay" );
m_pEnterANameLabel->SetVisible( true );
AddControlToAutoLayout( m_pEnterANameLabel, false );
}
else
{
m_pTitleLabel->SetText( "#Replay_RenderReplays" );
}
m_pTitleText->SelectAllOnFocusAlways( true );
AddControlToAutoLayout( m_pTitleText, false );
// Update controls based on preset
SetValuesFromQualityPreset();
// Set quit button if necessary
if ( m_bSetQuit )
{
m_pQuitWhenDoneCheck->SetSelected( true );
}
m_pPlayVoiceCheck->SetProportional( false );
m_pQuitWhenDoneCheck->SetProportional( false );
m_pShowAdvancedOptionsCheck->SetProportional( false );
m_pMotionBlurCheck->SetProportional( false );
m_pMotionBlurSlider->InvalidateLayout( false, true ); // Without this, the range labels show up with "..." because of an invalid font in TextImage::ApplySchemeSettings().
m_pExportRawCheck->SetProportional( false );
m_pQualitySlider->InvalidateLayout( false, true ); // Without this, the range labels show up with "..." because of an invalid font in TextImage::ApplySchemeSettings().
if ( m_pGlowEnabledCheck )
{
m_pGlowEnabledCheck->SetProportional( false );
}
// Fill in combo box with preset quality levels
const int nQualityPresetCount = ReplayVideo_GetQualityPresetCount();
m_pQualityPresetCombo->SetNumberOfEditLines( nQualityPresetCount );
for ( i = 0; i < nQualityPresetCount; ++i )
{
const ReplayQualityPreset_t &CurQualityPreset = ReplayVideo_GetQualityPreset( i );
m_pQualityPresetCombo->AddItem( CurQualityPreset.m_pName, NULL );
m_pQualityPresetCombo->SetItemEnabled( i, true );
}
m_pQualityPresetCombo->ActivateItem( m_pQualityPresetCombo->GetItemIDFromRow( m_iQualityPreset ) );
// Fill in combo box with video modes
int nScreenW = ScreenWidth();
int nScreenH = ScreenHeight();
const int nVidModeCount = ReplayVideo_GetVideoModeCount();
m_pVideoModesCombo->SetNumberOfEditLines( nVidModeCount );
bool bAtLeastOneVideoModeAdded = false;
bool bEnable = false;
bool bSkipped = false;
for ( i = 0; i < nVidModeCount; ++i )
{
// Only offer display modes less than the current window size
const ReplayVideoMode_t &CurVideoMode = ReplayVideo_GetVideoMode( i );
int nMw = CurVideoMode.m_nWidth;
int nMh = CurVideoMode.m_nHeight;
// Only display modes that fit in the current window
bEnable = ( nMw <= nScreenW && nMh <= nScreenH );
if (!bEnable)
bSkipped = true;
m_pVideoModesCombo->AddItem( CurVideoMode.m_pName, NULL );
m_pVideoModesCombo->SetItemEnabled( i, bEnable );
if (bEnable)
bAtLeastOneVideoModeAdded = true;
}
if ( bAtLeastOneVideoModeAdded )
{
m_pVideoModesCombo->ActivateItem( m_pVideoModesCombo->GetItemIDFromRow( 0 ) );
}
// fill in the combo box with codecs
const int nNumCodecs = ReplayVideo_GetCodecCount();
m_pCodecCombo->SetNumberOfEditLines( nNumCodecs );
for ( i = 0; i < nNumCodecs; ++i )
{
const ReplayCodec_t &CurCodec = ReplayVideo_GetCodec( i );
m_pCodecCombo->AddItem( CurCodec.m_pName, NULL );
m_pCodecCombo->SetItemEnabled( i, true );
}
m_pCodecCombo->ActivateItem( m_pCodecCombo->GetItemIDFromRow( 0 ) );
// now layout
// simplified options
AddControlToAutoLayout( m_pVideoModeLabel, false );
AddControlToAutoLayout( m_pVideoModesCombo, false );
// Show the note about "not all resolutions are available?"
if ( bSkipped && m_pResolutionNoteLabel )
{
m_pResolutionNoteLabel->SetVisible( true );
AddControlToAutoLayout( m_pResolutionNoteLabel, false );
}
// other simplified options
AddControlToAutoLayout( m_pQualityPresetLabel, false );
AddControlToAutoLayout( m_pQualityPresetCombo, false );
AddControlToAutoLayout( m_pEstimateTimeLabel, false );
AddControlToAutoLayout( m_pEstimateFileLabel, false );
AddControlToAutoLayout( m_pPlayVoiceCheck, false );
AddControlToAutoLayout( m_pShowAdvancedOptionsCheck, false );
AddControlToAutoLayout( m_pQuitWhenDoneCheck, false );
AddControlToAutoLayout( m_pLockWarningLabel, false );
// now advanced options
AddControlToAutoLayout( m_pSeparator, true );
AddControlToAutoLayout( m_pCodecLabel, true );
AddControlToAutoLayout( m_pCodecCombo, true );
if ( replay_rendersetting_motionblur_can_toggle.GetBool() )
{
AddControlToAutoLayout( m_pMotionBlurCheck, true );
}
else
{
m_pMotionBlurCheck->SetVisible( false );
}
AddControlToAutoLayout( m_pMotionBlurLabel, true );
AddControlToAutoLayout( m_pMotionBlurSlider, true );
AddControlToAutoLayout( m_pQualityLabel, true );
AddControlToAutoLayout( m_pQualitySlider, true );
AddControlToAutoLayout( m_pExportRawCheck, true );
if ( m_pGlowEnabledCheck )
{
AddControlToAutoLayout( m_pGlowEnabledCheck, true );
}
// these buttons always show up
AddControlToAutoLayout( m_pRenderButton, false );
AddControlToAutoLayout( m_pCancelButton, false );
}
void CReplayRenderDialog::PerformLayout()
{
BaseClass::PerformLayout();
m_pResolutionNoteLabel->SizeToContents(); // Get the proper height
int nY = m_nStartY;
Panel *pPrevPanel = NULL;
int nLastCtrlHeight = 0;
FOR_EACH_LL( m_lstControls, i )
{
LayoutInfo_t *pLayoutInfo = m_lstControls[ i ];
Panel *pPanel = pLayoutInfo->pPanel;
// should an advanced option be shown?
if ( pLayoutInfo->bAdvanced )
{
if ( pPanel->IsVisible() != m_bShowAdvancedOptions )
{
pPanel->SetVisible( m_bShowAdvancedOptions );
}
}
if ( !pPanel->IsVisible() )
continue;
if ( pPrevPanel && pLayoutInfo->nOffsetY >= 0 )
{
nY += pPrevPanel->GetTall() + pLayoutInfo->nOffsetY + m_nVerticalBuffer;
}
pPanel->SetPos( pLayoutInfo->nOffsetX ? pLayoutInfo->nOffsetX : m_nDefaultX, nY );
pPrevPanel = pPanel;
nLastCtrlHeight = pPanel->GetTall();
}
m_pBgPanel->SetTall( nY + nLastCtrlHeight + 2 * m_nVerticalBuffer );
}
void CReplayRenderDialog::Close()
{
SetVisible( false );
MarkForDeletion();
TFModalStack()->PopModal( this );
}
void CReplayRenderDialog::OnCommand( const char *pCommand )
{
if ( FStrEq( pCommand, "cancel" ) )
{
Close();
}
else if ( FStrEq( pCommand, "render" ) )
{
Close();
Render();
}
else
{
engine->ClientCmd( const_cast<char *>( pCommand ) );
}
BaseClass::OnCommand( pCommand );
}
void CReplayRenderDialog::Render()
{
// Only complain about QuickTime if we aren't exporting raw TGA's/WAV
if ( !m_pExportRawCheck->IsSelected() )
{
#ifndef USE_WEBM_FOR_REPLAY
if ( !g_pVideo || !g_pVideo->IsVideoSystemAvailable( VideoSystem::QUICKTIME ) )
{
ShowMessageBox( "#Replay_QuicktimeTitle", "#Replay_NeedQuicktime", "#GameUI_OK" );
return;
}
if ( g_pVideo->GetVideoSystemStatus( VideoSystem::QUICKTIME ) != VideoSystemStatus::OK )
{
if ( g_pVideo->GetVideoSystemStatus( VideoSystem::QUICKTIME ) == VideoSystemStatus::NOT_CURRENT_VERSION )
{
ShowMessageBox( "#Replay_QuicktimeTitle", "#Replay_NeedQuicktimeNewer", "#GameUI_OK" );
return;
}
ShowMessageBox( "#Replay_QuicktimeTitle", "#Replay_Err_QT_FailedToLoad", "#GameUI_OK" );
return;
}
#endif
}
// Update convars from settings
const int nMotionBlurQuality = clamp( m_pMotionBlurSlider->GetValue(), 0, MAX_MOTION_BLUR_QUALITY );
replay_rendersetting_quitwhendone.SetValue( (int)m_pQuitWhenDoneCheck->IsSelected() );
replay_rendersetting_exportraw.SetValue( (int)m_pExportRawCheck->IsSelected() );
replay_rendersetting_motionblurquality.SetValue( nMotionBlurQuality );
replay_rendersetting_motionblurenabled.SetValue( replay_rendersetting_motionblur_can_toggle.GetBool() ? (int)m_pMotionBlurCheck->IsSelected() : 1 );
replay_rendersetting_encodingquality.SetValue( clamp( m_pQualitySlider->GetValue() * ReplayVideo_GetQualityInterval(), 0, 100 ) );
if ( m_pGlowEnabledCheck )
{
replay_rendersetting_renderglow.SetValue( m_pGlowEnabledCheck->IsSelected() );
}
ConVarRef replay_voice_during_playback( "replay_voice_during_playback" );
if ( replay_voice_during_playback.IsValid() && m_pPlayVoiceCheck->IsEnabled() )
{
replay_voice_during_playback.SetValue( (int)m_pPlayVoiceCheck->IsSelected() );
}
// Setup parameters for render
RenderMovieParams_t params;
params.m_hReplay = m_hReplay;
params.m_iPerformance = m_iPerformance; // Use performance passed in from details panel
params.m_bQuitWhenFinished = m_pQuitWhenDoneCheck->IsSelected();
params.m_bExportRaw = m_pExportRawCheck->IsSelected();
m_pTitleText->GetText( params.m_wszTitle, sizeof( params.m_wszTitle ) );
#ifdef USE_WEBM_FOR_REPLAY
V_strcpy_safe( params.m_szExtension, ".webm" ); // Use .webm
#else
V_strcpy_safe( params.m_szExtension, ".mov" ); // Use .mov for Quicktime
#endif
const int iRes = m_pVideoModesCombo->GetActiveItem();
const ReplayVideoMode_t &VideoMode = ReplayVideo_GetVideoMode( iRes );
params.m_Settings.m_bMotionBlurEnabled = replay_rendersetting_motionblurenabled.GetBool();
params.m_Settings.m_bAAEnabled = replay_rendersetting_motionblurenabled.GetBool();
params.m_Settings.m_nMotionBlurQuality = nMotionBlurQuality;
params.m_Settings.m_nWidth = VideoMode.m_nWidth;
params.m_Settings.m_nHeight = VideoMode.m_nHeight;
params.m_Settings.m_FPS.SetFPS( VideoMode.m_nBaseFPS, VideoMode.m_bNTSCRate );
params.m_Settings.m_Codec = ReplayVideo_GetCodec( m_pCodecCombo->GetActiveItem() ).m_nCodecId;
params.m_Settings.m_nEncodingQuality = replay_rendersetting_encodingquality.GetInt();
params.m_Settings.m_bRaw = m_pExportRawCheck->IsSelected();
// Calculate the framerate for the engine - for each engine frame, we need the # of motion blur timesteps,
// x 2, since the shutter is open for nNumMotionBlurTimeSteps and closed for nNumMotionBlurTimeSteps,
// with the engine frame centered in the shutter open state (ie when we're half way through the motion blur
// timesteps). Antialiasing does not factor in here because it doesn't require extra frames - the AA jitter
// is interwoven in with the motion sub-frames.
const int nNumMotionBlurTimeSteps = ( params.m_Settings.m_bMotionBlurEnabled ) ? CReplayRenderer::GetNumMotionBlurTimeSteps( params.m_Settings.m_nMotionBlurQuality ) : 1;
if ( params.m_Settings.m_bMotionBlurEnabled )
{
params.m_flEngineFps = 2 * nNumMotionBlurTimeSteps * params.m_Settings.m_FPS.GetFPS();
}
else
{
Assert( nNumMotionBlurTimeSteps == 1 );
params.m_flEngineFps = params.m_Settings.m_FPS.GetFPS();
}
// Close the browser
extern void ReplayUI_CloseReplayBrowser();
ReplayUI_CloseReplayBrowser();
// Hide the console
engine->ExecuteClientCmd( "hideconsole" );
// Stats tracking.
GetReplayGameStatsHelper().SW_ReplayStats_WriteRenderDataStart( params, this );
// Render the movie
g_pReplayMovieManager->RenderMovie( params );
}
void CReplayRenderDialog::OnKeyCodeTyped( vgui::KeyCode code )
{
if( code == KEY_ENTER )
{
OnCommand( "render" );
}
else if ( code == KEY_ESCAPE )
{
MarkForDeletion();
}
else
{
BaseClass::OnKeyCodeTyped( code );
}
}
void CReplayRenderDialog::OnThink()
{
if ( m_pEstimateTimeLabel == NULL || m_pEstimateFileLabel == NULL )
return;
// The replay may be NULL if this dialog is created by 'save all' from the quit confirmation dialog. In this
// case, we don't want to a replay-specific time estimate anyway, so we can just early out here.
CGenericClassBasedReplay *pReplay = ToGenericClassBasedReplay( g_pReplayManager->GetReplay( m_hReplay) );
if ( !pReplay )
return;
const int nMotionBlurQuality = clamp( m_pMotionBlurSlider->GetValue(), 0, MAX_MOTION_BLUR_QUALITY );
const int nCodecQuality = clamp( m_pQualitySlider->GetValue(), 0, ReplayVideo_GetQualityRange() );
VideoEncodeCodec::EVideoEncodeCodec_t eCodec = ReplayVideo_GetCodec( m_pCodecCombo->GetActiveItem() ).m_nCodecId;
// fFrameSize is the scale factor based on the size of the rendered frame.
const int iRes = m_pVideoModesCombo->GetActiveItem();
const ReplayVideoMode_t &VideoMode = ReplayVideo_GetVideoMode( iRes );
float fFrameSize = (float)(VideoMode.m_nWidth * VideoMode.m_nHeight)/(float)(640*480);
float flEstimatedFileSize = 0;
float flEstimatedRenderTime_Min = 0;
static float mjpegToMotionBlurMultiplierTable[] = { 2.0f, 3.0f, 5.5f, 12.0f };
static float h264ToMotionBlurMultiplierTable[] = { 2.8f, 4.2f, 6.4f, 13.0f };
static float webmToMotionBlurMultiplierTable[] = { 2.8f, 4.2f, 6.4f, 13.0f };
static float mjpegToQualityMultiplierTable[] = { 620.0f, 736.0f, 1284.0f, 2115.0f, 3028.0f };
static float h264ToQualityMultiplierTable[] = { 276.0f, 384.0f, 595.0f, 1026.0f, 1873.0f };
static float webmToQualityMultiplierTable[] = { 125.0f, 250.0f, 312.0f, 673.0f, 1048.0f };
switch ( eCodec )
{
case VideoEncodeCodec::WEBM_CODEC:
flEstimatedFileSize = pReplay->m_flLength * webmToQualityMultiplierTable[nCodecQuality]*fFrameSize;
flEstimatedRenderTime_Min = pReplay->m_flLength * webmToMotionBlurMultiplierTable[nMotionBlurQuality];
break;
case VideoEncodeCodec::H264_CODEC:
flEstimatedFileSize = pReplay->m_flLength * h264ToQualityMultiplierTable[nCodecQuality];
flEstimatedRenderTime_Min = pReplay->m_flLength * h264ToMotionBlurMultiplierTable[nMotionBlurQuality];
break;
case VideoEncodeCodec::MJPEG_A_CODEC:
flEstimatedFileSize = pReplay->m_flLength * mjpegToQualityMultiplierTable[nCodecQuality];
flEstimatedRenderTime_Min = pReplay->m_flLength * mjpegToMotionBlurMultiplierTable[nMotionBlurQuality];
break;
}
float flEstimatedRenderTime_Max = flEstimatedRenderTime_Min * 3.0f;
// @todo Tom Bui: if this goes into hours, we are in trouble...
wchar_t wzFileSize[64];
_snwprintf( wzFileSize, ARRAYSIZE( wzFileSize ), L"%d", (int)flEstimatedFileSize );
wchar_t wzTimeMin[64];
wchar_t wzTimeMax[64];
g_pVGuiLocalize->ConvertANSIToUnicode( CReplayTime::FormatTimeString( flEstimatedRenderTime_Min ), wzTimeMin, sizeof( wzTimeMin ) );
g_pVGuiLocalize->ConvertANSIToUnicode( CReplayTime::FormatTimeString( flEstimatedRenderTime_Max ), wzTimeMax, sizeof( wzTimeMax ) );
wchar_t wzText[256] = L"";
g_pVGuiLocalize->ConstructString_safe( wzText, g_pVGuiLocalize->Find( "#Replay_RenderEstimate_File" ), 1,
wzFileSize,
wzTimeMin,
wzTimeMax );
m_pEstimateFileLabel->SetText( wzText );
g_pVGuiLocalize->ConstructString_safe( wzText, g_pVGuiLocalize->Find( "#Replay_RenderEstimate_Time" ), 2,
wzTimeMin,
wzTimeMax );
m_pEstimateTimeLabel->SetText( wzText );
}
void CReplayRenderDialog::OnTextChanged( KeyValues *data )
{
Panel *pPanel = reinterpret_cast<vgui::Panel *>( data->GetPtr("panel") );
vgui::ComboBox *pComboBox = dynamic_cast<vgui::ComboBox *>( pPanel );
if ( pComboBox == m_pQualityPresetCombo )
{
m_iQualityPreset = m_pQualityPresetCombo->GetActiveItem();
SetValuesFromQualityPreset();
}
}
void CReplayRenderDialog::OnCheckButtonChecked( vgui::Panel *panel )
{
if ( panel == m_pShowAdvancedOptionsCheck )
{
m_bShowAdvancedOptions = m_pShowAdvancedOptionsCheck->IsSelected();
InvalidateLayout( true, false );
}
}
void CReplayRenderDialog::OnSetFocus()
{
m_pTitleText->RequestFocus();
}
void ReplayUI_ShowRenderDialog( Panel* pParent, ReplayHandle_t hReplay, bool bSetQuit, int iPerformance )
{
CReplayRenderDialog *pRenderDialog = vgui::SETUP_PANEL( new CReplayRenderDialog( pParent, hReplay, bSetQuit, iPerformance ) );
pRenderDialog->SetVisible( true );
pRenderDialog->MakePopup();
pRenderDialog->MoveToFront();
pRenderDialog->SetKeyBoardInputEnabled( true );
pRenderDialog->SetMouseInputEnabled( true );
TFModalStack()->PushModal( pRenderDialog );
}
#endif
@@ -0,0 +1,109 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#ifndef REPLAYBROWSER_RENDERDIALOG_H
#define REPLAYBROWSER_RENDERDIALOG_H
#ifdef _WIN32
#pragma once
#endif
#include "replaybrowserbasepanel.h"
#include "vgui/IScheme.h"
#include "vgui_controls/CheckButton.h"
#include "vgui_controls/ComboBox.h"
#include "vgui_controls/Slider.h"
#include "replay/replayhandle.h"
using namespace vgui;
class CExLabel;
class CExButton;
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
class CReplayRenderDialog : public CReplayBasePanel
{
DECLARE_CLASS_SIMPLE( CReplayRenderDialog, CReplayBasePanel );
public:
CReplayRenderDialog( Panel *pParent, ReplayHandle_t hReplay, bool bSetQuit, int iPerformance );
virtual void ApplySchemeSettings( IScheme *pScheme );
virtual void PerformLayout();
virtual void OnCommand( const char *pCommand );
virtual void OnKeyCodeTyped( vgui::KeyCode code );
virtual void OnThink();
MESSAGE_FUNC_PARAMS( OnTextChanged, "TextChanged", data );
MESSAGE_FUNC_PTR( OnCheckButtonChecked, "CheckButtonChecked", panel );
private:
MESSAGE_FUNC( OnSetFocus, "SetFocus" );
void Close();
void Render();
void ValidateRenderData();
void UpdateControlsValues();
void AddControlToAutoLayout( Panel *pPanel, bool bAdvanced );
void SetValuesFromQualityPreset();
bool m_bShowAdvancedOptions;
int m_iQualityPreset;
ReplayHandle_t m_hReplay;
bool m_bSetQuit;
int m_iPerformance;
CheckButton *m_pPlayVoiceCheck;
CheckButton *m_pShowAdvancedOptionsCheck;
CheckButton *m_pQuitWhenDoneCheck;
CheckButton *m_pExportRawCheck;
CExButton *m_pCancelButton;
CExButton *m_pRenderButton;
TextEntry *m_pTitleText;
ComboBox *m_pVideoModesCombo;
ComboBox *m_pCodecCombo;
CExLabel *m_pQualityPresetLabel;
ComboBox *m_pQualityPresetCombo;
CExLabel *m_pResolutionNoteLabel;
CExLabel *m_pEnterANameLabel;
CExLabel *m_pVideoModeLabel;
CExLabel *m_pTitleLabel;
CExLabel *m_pLockWarningLabel;
CExLabel *m_pCodecLabel;
CExLabel *m_pEstimateTimeLabel;
CExLabel *m_pEstimateFileLabel;
CheckButton *m_pMotionBlurCheck;
CExLabel *m_pMotionBlurLabel;
Slider *m_pMotionBlurSlider;
CExLabel *m_pQualityLabel;
Slider *m_pQualitySlider;
EditablePanel *m_pBgPanel;
Panel *m_pSeparator;
CheckButton *m_pGlowEnabledCheck;
struct LayoutInfo_t
{
Panel *pPanel;
int nOffsetX;
int nOffsetY;
bool bAdvanced;
};
CUtlLinkedList< LayoutInfo_t * > m_lstControls;
CPanelAnimationVarAliasType( int, m_nStartY, "start_y", "0", "proportional_ypos" );
CPanelAnimationVarAliasType( int, m_nVerticalBuffer, "vertical_buffer", "0", "proportional_ypos" );
CPanelAnimationVarAliasType( int, m_nDefaultX, "default_x", "0", "proportional_xpos" );
friend class CReplayGameStatsHelper;
};
//-----------------------------------------------------------------------------
void ReplayUI_ShowRenderDialog( Panel* pParent, ReplayHandle_t hReplay, bool bSetQuit, int iPerformance );
//-----------------------------------------------------------------------------
#endif // REPLAYBROWSER_RENDERDIALOG_H
@@ -0,0 +1,167 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================//
#include "cbase.h"
#if defined( REPLAY_ENABLED )
#include "replayconfirmquitdlg.h"
#include "vgui_controls/TextImage.h"
#include "vgui_controls/CheckButton.h"
#include "vgui_controls/TextEntry.h"
#include "vgui/IInput.h"
#include "vgui/ISurface.h"
#include "ienginevgui.h"
#include "replay/genericclassbased_replay.h"
#include "replaybrowserrenderdialog.h"
#include "econ/econ_controls.h"
// memdbgon must be the last include file in a .cpp file!!!
#include <tier0/memdbgon.h>
using namespace vgui;
//-----------------------------------------------------------------------------
ConVar replay_quitmsg_dontaskagain( "replay_quitmsg_dontaskagain", "0", FCVAR_CLIENTDLL | FCVAR_DONTRECORD | FCVAR_ARCHIVE, "The replay system will ask you to render your replays on quit, unless this cvar is 1.", true, 0, true, 1 );
//-----------------------------------------------------------------------------
CReplayConfirmQuitDialog::CReplayConfirmQuitDialog( Panel *pParent )
: BaseClass( pParent, "confirmquitdlg" ),
m_pDontShowAgain( NULL ),
m_pQuitButton( NULL )
{
SetScheme( "ClientScheme" );
InvalidateLayout( true, true );
}
void CReplayConfirmQuitDialog::ApplySchemeSettings( vgui::IScheme *pScheme )
{
// Link in TF scheme
extern IEngineVGui *enginevgui;
vgui::HScheme pTFScheme = vgui::scheme()->LoadSchemeFromFileEx( enginevgui->GetPanel( PANEL_CLIENTDLL ), "resource/ClientScheme.res", "ClientScheme" );
SetScheme( pTFScheme );
SetProportional( true );
BaseClass::ApplySchemeSettings( vgui::scheme()->GetIScheme( pTFScheme ) );
LoadControlSettings( "Resource/UI/replaybrowser/confirmquitdlg.res", "GAME" );
m_pDontShowAgain = dynamic_cast< CheckButton * >( FindChildByName( "DontShowThisAgainCheckbox" ) );
m_pQuitButton = dynamic_cast< CExButton * >( FindChildByName( "QuitButton" ) );
if ( m_pQuitButton )
{
m_pQuitButton->GetTextImage()->ClearColorChangeStream();
m_pQuitButton->GetTextImage()->AddColorChange( Color(200,80,60,255), 0 );
}
}
void CReplayConfirmQuitDialog::OnCommand( const char *pCommand )
{
// Store the setting of our "never show this again" checkbox if the user picked anything
// except cancel.
if ( !FStrEq( pCommand, "cancel" ) && m_pDontShowAgain && m_pDontShowAgain->IsSelected() )
{
replay_quitmsg_dontaskagain.SetValue( 1 );
}
if ( FStrEq( pCommand, "rendernow_delay" ) )
{
// Delete this
SetVisible( false );
MarkForDeletion();
// Render all unrendered replays now
ReplayUI_ShowRenderDialog( NULL, REPLAY_HANDLE_INVALID, true, -1 );
}
else if ( FStrEq( pCommand, "rendernow" ) )
{
// Sometimes this message comes in just before input is processed when using a controller
// Refire after a delay
PostMessage( this, new KeyValues( "Command", "command", "rendernow_delay" ), 0.001f );
}
else if ( FStrEq( pCommand, "quit" ) )
{
MarkForDeletion();
engine->ClientCmd_Unrestricted( "quit\n" );
}
else if ( FStrEq( pCommand, "cancel" ) )
{
MarkForDeletion();
}
else if ( FStrEq( pCommand, "gotoreplays"))
{
// "Go to replays"
MarkForDeletion();
engine->ClientCmd( "replay_reloadbrowser" );
}
}
void CReplayConfirmQuitDialog::OnKeyCodeTyped( vgui::KeyCode code )
{
if ( code == KEY_ESCAPE )
{
OnCommand( "cancel" );
}
else
{
BaseClass::OnKeyCodeTyped( code );
}
}
void CReplayConfirmQuitDialog::OnKeyCodePressed( vgui::KeyCode code )
{
if ( GetBaseButtonCode( code ) == KEY_XBUTTON_B || GetBaseButtonCode( code ) == STEAMCONTROLLER_B )
{
OnCommand( "cancel" );
}
else if ( GetBaseButtonCode( code ) == KEY_XBUTTON_A || GetBaseButtonCode( code ) == STEAMCONTROLLER_A )
{
OnCommand( "quit" );
}
else if ( GetBaseButtonCode( code ) == KEY_XBUTTON_X || GetBaseButtonCode( code ) == STEAMCONTROLLER_X )
{
if ( m_pDontShowAgain )
{
m_pDontShowAgain->SetSelected( !m_pDontShowAgain->IsSelected() );
}
}
else if ( GetBaseButtonCode( code ) == KEY_XBUTTON_Y || GetBaseButtonCode( code ) == STEAMCONTROLLER_Y )
{
OnCommand( "gotoreplays" );
}
else
{
BaseClass::OnKeyCodePressed( code );
}
}
bool ReplayUI_ShowConfirmQuitDlg()
{
if ( replay_quitmsg_dontaskagain.GetBool() )
return false;
CReplayConfirmQuitDialog *pConfirmQuitDlg = vgui::SETUP_PANEL( new CReplayConfirmQuitDialog( NULL ) );
if ( pConfirmQuitDlg )
{
vgui::surface()->PlaySound( "replay\\replaydialog_warn.wav" );
// Display the panel!
pConfirmQuitDlg->SetVisible( true );
pConfirmQuitDlg->MakePopup();
pConfirmQuitDlg->MoveToFront();
pConfirmQuitDlg->SetKeyBoardInputEnabled( true );
pConfirmQuitDlg->SetMouseInputEnabled( true );
TFModalStack()->PushModal( pConfirmQuitDlg );
}
return true;
}
#endif
@@ -0,0 +1,45 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#ifndef REPLAYBROWSER_CONFIRMQUITDLG_H
#define REPLAYBROWSER_CONFIRMQUITDLG_H
#ifdef _WIN32
#pragma once
#endif
#include "replaybrowserbasepanel.h"
#include "vgui/IScheme.h"
#include "vgui_controls/CheckButton.h"
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
class CExButton;
class CReplayConfirmQuitDialog : public CReplayBasePanel
{
DECLARE_CLASS_SIMPLE( CReplayConfirmQuitDialog, CReplayBasePanel );
public:
CReplayConfirmQuitDialog( Panel *pParent );
virtual void ApplySchemeSettings( vgui::IScheme *pScheme );
virtual void OnCommand( const char *pCommand );
virtual void OnKeyCodeTyped( vgui::KeyCode code );
virtual void OnKeyCodePressed( vgui::KeyCode code );
private:
vgui::CheckButton *m_pDontShowAgain;
CExButton *m_pQuitButton;
};
//-----------------------------------------------------------------------------
bool ReplayUI_ShowConfirmQuitDlg();
//-----------------------------------------------------------------------------
#endif // REPLAYBROWSER_CONFIRMQUITDLG_H
@@ -0,0 +1,245 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
//=======================================================================================//
#include "cbase.h"
#if defined( REPLAY_ENABLED )
#include "replayinputpanel.h"
#include "replaybrowsermainpanel.h"
#include "replay/replay.h"
#include "vgui_controls/EditablePanel.h"
#include "vgui_controls/TextEntry.h"
#include "vgui/IInput.h"
#include "vgui/ILocalize.h"
#include "ienginevgui.h"
#include "vgui_int.h"
#include "vgui/ISurface.h"
#include "iclientmode.h"
#include "replay/ireplaymanager.h"
#include "econ/econ_controls.h"
#if defined( TF_CLIENT_DLL )
#include "tf_item_inventory.h"
#endif
using namespace vgui;
//-----------------------------------------------------------------------------
static bool s_bPanelVisible = false;
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// Purpose: Player input dialog for a replay
//-----------------------------------------------------------------------------
class CReplayInputPanel : public EditablePanel
{
private:
DECLARE_CLASS_SIMPLE( CReplayInputPanel, EditablePanel );
public:
CReplayInputPanel( Panel *pParent, const char *pName, ReplayHandle_t hReplay );
~CReplayInputPanel();
virtual void ApplySchemeSettings( IScheme *pScheme );
virtual void PerformLayout();
virtual void OnCommand( const char *command );
virtual void OnKeyCodePressed( KeyCode code );
virtual void OnKeyCodeTyped( KeyCode code );
MESSAGE_FUNC( OnSetFocus, "SetFocus" );
private:
Panel *m_pDlg;
TextEntry *m_pTitleEntry;
ReplayHandle_t m_hReplay;
};
//-----------------------------------------------------------------------------
// Purpose: CReplayInputPanel implementation
//-----------------------------------------------------------------------------
CReplayInputPanel::CReplayInputPanel( Panel *pParent, const char *pName, ReplayHandle_t hReplay )
: BaseClass( pParent, pName ),
m_hReplay( hReplay ),
m_pDlg( NULL ),
m_pTitleEntry( NULL )
{
SetScheme( "ClientScheme" );
SetProportional( true );
}
CReplayInputPanel::~CReplayInputPanel()
{
}
void CReplayInputPanel::ApplySchemeSettings( IScheme *pScheme )
{
BaseClass::ApplySchemeSettings( pScheme );
LoadControlSettings( "resource/ui/replayinputpanel.res", "GAME" );
// Cache off the dlg pointer
m_pDlg = FindChildByName( "Dlg" );
// Setup some action sigsies
m_pDlg->FindChildByName( "SaveButton" )->AddActionSignalTarget( this );
m_pDlg->FindChildByName( "CancelButton" )->AddActionSignalTarget( this );
m_pTitleEntry = static_cast< TextEntry * >( m_pDlg->FindChildByName( "TitleInput" ) );
m_pTitleEntry->SelectAllOnFocusAlways( true );
m_pTitleEntry->SetSelectionBgColor( GetSchemeColor( "Yellow", Color( 255, 255, 255, 255), pScheme ) );
m_pTitleEntry->SetSelectionTextColor( Color( 255, 255, 255, 255 ) );
if ( m_hReplay != REPLAY_HANDLE_INVALID )
{
CReplay *pReplay = g_pReplayManager->GetReplay( m_hReplay );
m_pTitleEntry->SetText( pReplay->m_wszTitle );
}
}
void CReplayInputPanel::PerformLayout()
{
BaseClass::PerformLayout();
SetWide( ScreenWidth() );
SetTall( ScreenHeight() );
// Center
m_pDlg->SetPos( ( ScreenWidth() - m_pDlg->GetWide() ) / 2, ( ScreenHeight() - m_pDlg->GetTall() ) / 2 );
}
void CReplayInputPanel::OnKeyCodeTyped( KeyCode code )
{
if ( code == KEY_ESCAPE )
{
OnCommand( "cancel" );
}
BaseClass::OnKeyCodeTyped( code );
}
void CReplayInputPanel::OnKeyCodePressed( KeyCode code )
{
if ( code == KEY_ENTER )
{
OnCommand( "save" );
}
BaseClass::OnKeyCodePressed( code );
}
void CReplayInputPanel::OnSetFocus()
{
m_pTitleEntry->RequestFocus();
}
void CReplayInputPanel::OnCommand( const char *command )
{
bool bCloseWindow = false;
bool bLocalPlayerDead = false;
if ( !Q_strnicmp( command, "save", 4 ) )
{
if ( m_hReplay != REPLAY_HANDLE_INVALID )
{
// Store the title
CReplay *pReplay = g_pReplayManager->GetReplay( m_hReplay );
if ( pReplay )
{
m_pTitleEntry->GetText( pReplay->m_wszTitle, sizeof( pReplay->m_wszTitle ) );
}
// Cache to disk
g_pReplayManager->FlagReplayForFlush( pReplay, false );
// Add the replay to the browser
CReplayBrowserPanel* pReplayBrowser = ReplayUI_GetBrowserPanel();
if ( pReplayBrowser )
{
pReplayBrowser->OnSaveReplay( m_hReplay );
}
// Display a message - if we somehow disconnect, we can crash here if local player isn't checked
C_BasePlayer *pLocalPlayer = C_BasePlayer::GetLocalPlayer();
if ( pLocalPlayer )
{
g_pClientMode->DisplayReplayMessage( pLocalPlayer->IsAlive() ? "#Replay_ReplaySavedAlive" : "#Replay_ReplaySavedDead", -1.0f, false, "replay\\saved.wav", false );
// Check to see if player's dead - used later to determine if we should show items window
bLocalPlayerDead = !pLocalPlayer->IsAlive();
}
}
bCloseWindow = true;
}
else if ( !Q_strnicmp( command, "cancel", 6 ) )
{
bCloseWindow = true;
}
// Close the window?
if ( bCloseWindow )
{
s_bPanelVisible = false;
SetVisible( false );
TFModalStack()->PopModal( this );
MarkForDeletion();
// This logic is perhaps a smidge of a hack. We have to be careful about executing "gameui_hide"
// since it will hide the item pickup panel. If there are no items to be picked up, we can safely
// hide the gameui panel, but we have to call CheckForRoomAndForceDiscard() (as ShowItemsPickedUp()
// does if no items are picked up). Otherwise, skip the "gameui_hide" call and show the item pickup
// panel.
#if defined( TF_CLIENT_DLL )
if ( TFInventoryManager()->GetNumItemPickedUpItems() == 0 )
{
TFInventoryManager()->CheckForRoomAndForceDiscard();
engine->ClientCmd_Unrestricted( "gameui_hide" );
}
else if ( bLocalPlayerDead )
{
// Now show the items pickup screen if player's dead
TFInventoryManager()->ShowItemsPickedUp();
}
#endif
}
BaseClass::OnCommand( command );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
bool IsReplayInputPanelVisible()
{
return s_bPanelVisible;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void ShowReplayInputPanel( ReplayHandle_t hReplay )
{
vgui::DHANDLE< CReplayInputPanel > hReplayInputPanel;
hReplayInputPanel = vgui::SETUP_PANEL( new CReplayInputPanel( NULL, "ReplayInputPanel", hReplay ) );
hReplayInputPanel->SetVisible( true );
hReplayInputPanel->MakePopup();
hReplayInputPanel->MoveToFront();
hReplayInputPanel->SetKeyBoardInputEnabled(true);
hReplayInputPanel->SetMouseInputEnabled(true);
TFModalStack()->PushModal( hReplayInputPanel );
engine->ClientCmd_Unrestricted( "gameui_hide" );
s_bPanelVisible = true;
}
//-----------------------------------------------------------------------------
// Purpose: Test the replay input dialog
//-----------------------------------------------------------------------------
CON_COMMAND_F( open_replayinputpanel, "Open replay input panel test", FCVAR_NONE )
{
ShowReplayInputPanel( NULL );
}
#endif
@@ -0,0 +1,25 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
//=======================================================================================//
#ifndef REPLAY_INPUT_PANEL_H
#define REPLAY_INPUT_PANEL_H
#ifdef _WIN32
#pragma once
#endif
//-----------------------------------------------------------------------------
#include "replay/replayhandle.h"
//-----------------------------------------------------------------------------
// Purpose: Show Replay input panel for entering a title, etc.
//-----------------------------------------------------------------------------
void ShowReplayInputPanel( ReplayHandle_t hReplay );
//-----------------------------------------------------------------------------
// Purpose: Is the panel visible?
//-----------------------------------------------------------------------------
bool IsReplayInputPanelVisible();
#endif // REPLAY_INPUT_PANEL_H
@@ -0,0 +1,375 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
//----------------------------------------------------------------------------------------
#include "cbase.h"
#if defined( REPLAY_ENABLED )
#include "replaymessagepanel.h"
#include "vgui_controls/CheckButton.h"
#include "ienginevgui.h"
#include "vgui_controls/PHandle.h"
#include "econ/econ_controls.h"
#if defined( CSTRIKE_DLL )
# include "cstrike/clientmode_csnormal.h"
#elif defined( TF_CLIENT_DLL )
# include "tf/clientmode_tf.h"
#endif
// memdbgon must be the last include file in a .cpp file!!!
#include <tier0/memdbgon.h>
//-----------------------------------------------------------------------------
#if _DEBUG
CON_COMMAND( testreplaymessagepanel, "" )
{
CReplayMessagePanel *pPanel = new CReplayMessagePanel( "#Replay_StartRecord", replay_msgduration_misc.GetFloat(), rand()%2==0);
pPanel->Show();
}
CON_COMMAND( testreplaymessagedlg, "" )
{
CReplayMessageDlg *pPanel = SETUP_PANEL( new CReplayMessageDlg( "text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text." ) );
pPanel->SetVisible( true );
pPanel->MakePopup();
pPanel->MoveToFront();
pPanel->SetKeyBoardInputEnabled( true );
pPanel->SetMouseInputEnabled( true );
pPanel->RequestFocus();
engine->ClientCmd_Unrestricted( "gameui_hide" );
}
#endif
//-----------------------------------------------------------------------------
using namespace vgui;
//-----------------------------------------------------------------------------
typedef vgui::DHANDLE< CReplayMessagePanel > ReplayMessagePanelHandle_t;
static CUtlVector< ReplayMessagePanelHandle_t > g_vecReplayMessagePanels;
//-----------------------------------------------------------------------------
ConVar replay_msgduration_startrecord( "replay_msgduration_startrecord", "6", FCVAR_DONTRECORD, "Duration for start record message.", true, 0.0f, true, 10.0f );
ConVar replay_msgduration_stoprecord( "replay_msgduration_stoprecord", "6", FCVAR_DONTRECORD, "Duration for stop record message.", true, 0.0f, true, 10.0f );
ConVar replay_msgduration_replaysavailable( "replay_msgduration_replaysavailable", "6", FCVAR_DONTRECORD, "Duration for replays available message.", true, 0.0f, true, 10.0f );
ConVar replay_msgduration_error( "replay_msgduration_error", "6", FCVAR_DONTRECORD, "Duration for replays available message.", true, 0.0f, true, 10.0f );
ConVar replay_msgduration_misc( "replay_msgduration_misc", "5", FCVAR_DONTRECORD, "Duration for misc replays messages (server errors and such).", true, 0.0f, true, 10.0f );
ConVar replay_msgduration_connectrecording( "replay_msgduration_connectrecording", "8", FCVAR_DONTRECORD, "Duration for the message that pops up when you connect to a server already recording replays.", true, 0.0f, true, 15.0f );
//-----------------------------------------------------------------------------
CReplayMessageDlg::CReplayMessageDlg( const char *pText )
: BaseClass( NULL, "ReplayMessageDlg" ),
m_pOKButton( NULL ),
m_pDlg( NULL ),
m_pMsgLabel( NULL )
{
InvalidateLayout( true, true );
m_pMsgLabel->SetText( pText );
}
CReplayMessageDlg::~CReplayMessageDlg()
{
}
void CReplayMessageDlg::ApplySchemeSettings( IScheme *pScheme )
{
// Link in TF scheme
extern IEngineVGui *enginevgui;
vgui::HScheme pTFScheme = vgui::scheme()->LoadSchemeFromFileEx( enginevgui->GetPanel( PANEL_CLIENTDLL ), "resource/ClientScheme.res", "ClientScheme" );
SetScheme( pTFScheme );
SetProportional( true );
BaseClass::ApplySchemeSettings( vgui::scheme()->GetIScheme( pTFScheme ) );
LoadControlSettings( "resource/ui/replaymessagedlg.res", "GAME" );
m_pDlg = FindChildByName( "Dlg" );
m_pOKButton = dynamic_cast< CExButton * >( m_pDlg->FindChildByName( "OKButton" ) );
m_pMsgLabel = dynamic_cast< CExLabel * >( m_pDlg->FindChildByName( "TextLabel") );
m_pOKButton->AddActionSignalTarget( this );
}
void CReplayMessageDlg::PerformLayout()
{
BaseClass::PerformLayout();
SetWide( ScreenWidth() );
SetTall( ScreenHeight() );
// Center dlg on screen
m_pDlg->SetPos( ( ScreenWidth() - m_pDlg->GetWide() ) / 2, ( ScreenHeight() - m_pDlg->GetTall() ) / 2 );
// Position OK below text label, centered horizontally
int nButtonX = XRES(13);
int nButtonY = m_pDlg->GetTall() - m_pOKButton->GetTall() - YRES( 10 );
m_pOKButton->SetPos( nButtonX, nButtonY );
}
void CReplayMessageDlg::Close()
{
// Hide / delete / hide game UI
SetVisible( false );
MarkForDeletion();
engine->ClientCmd_Unrestricted( "gameui_hide" );
}
void CReplayMessageDlg::OnCommand( const char *pCommand )
{
if ( FStrEq( pCommand, "close" ) )
{
Close();
}
BaseClass::OnCommand( pCommand );
}
void CReplayMessageDlg::OnKeyCodeTyped( KeyCode nCode )
{
switch ( nCode )
{
case KEY_ESCAPE:
case KEY_SPACE:
case KEY_ENTER:
Close();
return;
}
BaseClass::OnKeyCodeTyped( nCode );
}
//-----------------------------------------------------------------------------
int CReplayMessagePanel::InstanceCount()
{
return g_vecReplayMessagePanels.Count();
}
void CReplayMessagePanel::RemoveAll()
{
FOR_EACH_VEC( g_vecReplayMessagePanels, i )
{
CReplayMessagePanel *pCurPanel = g_vecReplayMessagePanels[ i ];
pCurPanel->MarkForDeletion();
}
g_vecReplayMessagePanels.RemoveAll();
}
//-----------------------------------------------------------------------------
ReplayMessagePanelHandle_t GetReplayMessagePanelHandle( CReplayMessagePanel *pPanel )
{
ReplayMessagePanelHandle_t hThis;
hThis = pPanel;
return hThis;
}
CReplayMessagePanel::CReplayMessagePanel( const char *pLocalizeName, float flDuration, bool bUrgent )
: EditablePanel( g_pClientMode->GetViewport(), "ReplayMessagePanel" ),
m_bUrgent( bUrgent )
{
m_flShowStartTime = 0;
m_flShowDuration = flDuration;
m_pMessageLabel = new CExLabel( this, "MessageLabel", pLocalizeName );
m_pReplayLabel = new CExLabel( this, "ReplayLabel", "" );
m_pIcon = new ImagePanel( this, "Icon" );
#if defined( TF_CLIENT_DLL )
const char *pBorderName = bUrgent ? "ReplayFatLineBorderRedBGOpaque" : "ReplayFatLineBorderOpaque";
V_strncpy( m_szBorderName, pBorderName, sizeof( m_szBorderName ) );
#endif
g_vecReplayMessagePanels.AddToTail( GetReplayMessagePanelHandle( const_cast< CReplayMessagePanel * >( this ) ) );
InvalidateLayout( true, true );
ivgui()->AddTickSignal( GetVPanel(), 10 );
}
CReplayMessagePanel::~CReplayMessagePanel()
{
// CUtlVector<>::Find() vomits.
int iFind = g_vecReplayMessagePanels.InvalidIndex();
FOR_EACH_VEC( g_vecReplayMessagePanels, i )
{
if ( g_vecReplayMessagePanels[ i ].Get() == this )
{
iFind = i;
}
}
// Remove, if found.
if ( iFind != g_vecReplayMessagePanels.InvalidIndex() )
{
g_vecReplayMessagePanels.FastRemove( iFind );
}
ivgui()->RemoveTickSignal( GetVPanel() );
}
void CReplayMessagePanel::Show()
{
m_pMessageLabel->SetVisible( true );
// Setup start time
m_flShowStartTime = gpGlobals->curtime;
m_pMessageLabel->MoveToFront();
SetAlpha( 0 );
}
inline float LerpScale( float flIn, float flInMin, float flInMax, float flOutMin, float flOutMax )
{
float flDenom = flInMax - flInMin;
if ( flDenom == 0.0f )
return 0.0f;
float t = clamp( ( flIn - flInMin ) / flDenom, 0.0f, 1.0f );
return Lerp( t, flOutMin, flOutMax );
}
inline float SCurve( float t )
{
t = clamp( t, 0.0f, 1.0f );
return t * t * (3 - 2*t);
}
void CReplayMessagePanel::OnTick()
{
// Hide if taking screenshot
extern ConVar hud_freezecamhide;
extern bool IsTakingAFreezecamScreenshot();
if ( hud_freezecamhide.GetBool() && IsTakingAFreezecamScreenshot() )
{
SetVisible( false );
return;
}
// Delete the panel if life exceeded
const float flEndTime = m_flShowStartTime + m_flShowDuration;
if ( gpGlobals->curtime >= flEndTime )
{
SetVisible( false );
MarkForDeletion();
return;
}
SetVisible( true );
const float flFadeDuration = .4f;
float flAlpha;
// Fade out?
if ( gpGlobals->curtime >= flEndTime - flFadeDuration )
{
flAlpha = LerpScale( gpGlobals->curtime, flEndTime - flFadeDuration, flEndTime, 1.0f, 0.0f );
}
// Fade in?
else if ( gpGlobals->curtime <= m_flShowStartTime + flFadeDuration )
{
flAlpha = LerpScale( gpGlobals->curtime, m_flShowStartTime, m_flShowStartTime + flFadeDuration, 0.0f, 1.0f );
}
// Otherwise, we must be in between fade in/fade out
else
{
flAlpha = 1.0f;
}
SetAlpha( 255 * SCurve( flAlpha ) );
}
void CReplayMessagePanel::ApplySchemeSettings( IScheme *pScheme )
{
BaseClass::ApplySchemeSettings( pScheme );
LoadControlSettings( "resource/ui/replaymessage.res", "GAME" );
#if defined( CSTRIKE_DLL )
SetPaintBackgroundEnabled( true );
SetPaintBorderEnabled( false );
SetPaintBackgroundType( 0 );
SetBgColor( pScheme->GetColor( m_bUrgent ? "DarkRed" : "DarkGray", Color( 255, 255, 255, 255 ) ) );
#endif
}
void CReplayMessagePanel::PerformLayout()
{
BaseClass::PerformLayout();
#if defined( TF_CLIENT_DLL )
// Set the border if one was specified
if ( m_szBorderName[0] )
{
SetBorder( scheme()->GetIScheme( GetScheme() )->GetBorder( m_szBorderName ) );
}
#endif
// Adjust overall panel size depending on min-mode
#if defined( TF_CLIENT_DLL )
extern ConVar cl_hud_minmode;
bool bMinMode = cl_hud_minmode.GetBool();
#else
bool bMinMode = false;
#endif
int nVerticalBuffer = bMinMode ? YRES(3) : YRES(5);
int nMessageLabelY = nVerticalBuffer;
int nVerticalOffsetBetweenPanels = YRES(6);
// Only display replay icon and "replay" label if this is the top-most (vertically) panel
// and we're not in min-mode
Assert( InstanceCount() > 0 );
if ( !InstanceCount() || bMinMode || g_vecReplayMessagePanels[ 0 ].Get() != this )
{
m_pIcon->SetTall( 0 );
m_pReplayLabel->SetTall( 0 );
nVerticalOffsetBetweenPanels = YRES(1);
}
else
{
m_pReplayLabel->SizeToContents();
nMessageLabelY += m_pReplayLabel->GetTall();
nVerticalOffsetBetweenPanels = YRES(6);
}
// Resize the message label to fit the text
m_pMessageLabel->SizeToContents();
// Adjust this panel's height to fit the label size
SetTall( nMessageLabelY + m_pMessageLabel->GetTall() + nVerticalBuffer );
// Set the message label's position
m_pMessageLabel->SetPos( XRES(8), nMessageLabelY );
// Get the bottom of the bottom-most message panel
int nMaxY = 0;
FOR_EACH_VEC( g_vecReplayMessagePanels, it )
{
CReplayMessagePanel *pPanel = g_vecReplayMessagePanels[ it ];
if ( pPanel == this )
continue;
int nX, nY;
pPanel->GetPos( nX, nY );
nMaxY = MAX( nMaxY, pPanel->GetTall() + nY );
}
// Adjust this panel's position to be below bottom-most panel
// NOTE: Intentionally using YRES() for xpos, since we want to match offsets in both x & y margins
SetPos( YRES(6), nMaxY + nVerticalOffsetBetweenPanels );
}
//-----------------------------------------------------------------------------
#endif
@@ -0,0 +1,85 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
//----------------------------------------------------------------------------------------
#ifndef REPLAYMESSAGEPANEL_H
#define REPLAYMESSAGEPANEL_H
#ifdef _WIN32
#pragma once
#endif
#include "vgui_controls/EditablePanel.h"
using namespace vgui;
//----------------------------------------------------------------------------------------
// Purpose:
//----------------------------------------------------------------------------------------
extern ConVar replay_msgduration_startrecord;
extern ConVar replay_msgduration_stoprecord;
extern ConVar replay_msgduration_replaysavailable;
extern ConVar replay_msgduration_error;
extern ConVar replay_msgduration_misc;
extern ConVar replay_msgduration_connectrecording;
//----------------------------------------------------------------------------------------
// Purpose: Forward declarations
//----------------------------------------------------------------------------------------
class CExLabel;
class CExButton;
class CReplayMessageDlg : public EditablePanel
{
DECLARE_CLASS_SIMPLE( CReplayMessageDlg, EditablePanel );
public:
CReplayMessageDlg( const char *pText );
~CReplayMessageDlg();
virtual void ApplySchemeSettings( IScheme *pScheme );
virtual void PerformLayout();
virtual void OnKeyCodeTyped( KeyCode nCode );
virtual void OnCommand( const char *pCommand );
private:
void Close();
Panel *m_pDlg;
CExLabel *m_pMsgLabel;
CExButton *m_pOKButton;
};
//----------------------------------------------------------------------------------------
// Purpose: A panel for display messages from the replay system during gameplay
//----------------------------------------------------------------------------------------
class CReplayMessagePanel : public EditablePanel
{
DECLARE_CLASS_SIMPLE( CReplayMessagePanel, EditablePanel );
public:
CReplayMessagePanel( const char *pLocalizeName, float flDuration, bool bUrgent );
virtual ~CReplayMessagePanel();
void Show();
virtual void OnTick();
static int InstanceCount();
static void RemoveAll();
private:
virtual void ApplySchemeSettings( IScheme *pScheme );
virtual void PerformLayout();
CExLabel *m_pMessageLabel;
CExLabel *m_pReplayLabel;
ImagePanel *m_pIcon;
float m_flShowStartTime;
float m_flShowDuration;
bool m_bUrgent;
#if defined( TF_CLIENT_DLL )
char m_szBorderName[ 64 ];
#endif
};
#endif // REPLAYMESSAGEPANEL_H
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,241 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#if defined( REPLAY_ENABLED )
#ifndef REPLAYPERFORMANCEEDITOR_H
#define REPLAYPERFORMANCEEDITOR_H
#ifdef _WIN32
#pragma once
#endif
#include "vgui_controls/EditablePanel.h"
#include "vgui_controls/ImagePanel.h"
#include "vgui_controls/ImageList.h"
#include "tf/vgui/tf_controls.h"
#include "replay/replayhandle.h"
#include "replay/ireplayperformanceeditor.h"
#include "replay/ireplayperformancecontroller.h"
//-----------------------------------------------------------------------------
class CPlayerCell;
class CCameraOptionsPanel;
class CRecLightPanel;
class CReplay;
class CReplayPerformance;
class CReplayTipLabel;
class CSavingDialog;
//-----------------------------------------------------------------------------
// NOTE: Should not change order here - if you do, you need to modify g_pCamNames.
enum CameraMode_t
{
CAM_INVALID = -1,
CAM_FREE,
CAM_THIRD,
CAM_FIRST,
COMPONENT_TIMESCALE,
NCAMS
};
//-----------------------------------------------------------------------------
class CReplayPerformanceEditorPanel : public vgui::EditablePanel,
public IReplayPerformanceEditor
{
DECLARE_CLASS_SIMPLE( CReplayPerformanceEditorPanel, vgui::EditablePanel );
public:
CReplayPerformanceEditorPanel( Panel *parent, ReplayHandle_t hReplay );
virtual ~CReplayPerformanceEditorPanel();
virtual void ShowPanel( bool bShow );
bool OnEndOfReplayReached();
void OnInGameMouseWheelEvent( int nDelta );
void UpdateCameraSelectionPosition( CameraMode_t nCameraMode );
void UpdateFreeCamSettings( const SetViewParams_t &params );
void UpdateTimeScale( float flScale );
void HandleUiToggle();
void Exit();
void Exit_ShowDialogs();
private:
virtual void ApplySchemeSettings( vgui::IScheme *pScheme );
virtual void ApplySettings( KeyValues *pInResourceData );
virtual void PerformLayout();
virtual void OnCommand( const char *command );
virtual void OnMouseWheeled( int nDelta );
virtual void OnTick();
void Achievements_Think( float flElapsed );
void Achievements_OnSpaceBarPressed();
void Achievements_Grant();
friend class CReplayButton;
friend class CSavingDialog;
void SetButtonTip( wchar_t *pTipText, Panel *pContextPanel );
void ShowButtonTip( bool bShow );
void ShowSavingDialog();
//
// IReplayPerformanceEditor:
//
virtual CReplay *GetReplay();
virtual void OnRewindComplete();
// Called when the user attempts to change to a different camera, etc.
// Returns true if request is immediately granted - false means the event
// was queued and the user has been asked if they are OK with nuking any
// changes after the current time.
bool OnStateChangeRequested( const char *pEventStr );
void EnsureRecording( bool bShouldSnip = true ); // Start recording now if not already doing so
bool IsPaused();
void UpdateCameraButtonImages( bool bForceUseUnselected = false );
void LayoutPlayerCells();
void SetupHighlightPanel( EditablePanel *pPanel, CPlayerCell *pPlayerCell );
void UpdateTimeLabels();
void ClearPlayerCellData();
void HandleMouseWheel( int nDelta );
private:
enum ControlButtons_t
{
CTRLBUTTON_IN,
CTRLBUTTON_GOTOBEGINNING,
CTRLBUTTON_REWIND,
CTRLBUTTON_PLAY,
CTRLBUTTON_FF,
CTRLBUTTON_GOTOEND,
CTRLBUTTON_OUT,
NUM_CTRLBUTTONS
};
CReplayPerformance *GetPerformance() const;
CReplayPerformance *GetSavedPerformance() const;
int GetCameraModeFromButtonIndex( CameraMode_t iCamera );
void AddSetViewEvent();
void AddTimeScaleEvent( float flTimeScale );
void AddPanelKeyboardInputDisableList( vgui::Panel *pPanel );
CameraMode_t IsMouseOverActiveCameraOptionsPanel( int nMouseX, int nMouseY );
void SetOrRemoveInTick( int nTick, bool bRemoveIfSet );
void SetOrRemoveOutTick( int nTick, bool bRemoveIfSet );
void SetOrRemoveTick( int nTick, bool bUseInTick, bool bRemoveIfSet );
void ToggleMenu();
void OnMenuCommand_Save( bool bExitEditorWhenDone = false );
void OnMenuCommand_SaveAs( bool bExitEditorWhenDone = false );
void OnMenuCommand_Exit();
void DisplaySavedTip( bool bSucceess );
void OnSaveComplete();
void SaveAs( const wchar_t *pTitle );
void ShowRewindConfirmMessage();
static void OnConfirmSaveAs( bool bShouldSave, wchar_t *pTitle, void *pContext );
static void OnConfirmDestroyChanges( bool bConfirmed, void *pContext );
static void OnConfirmDiscard( bool bConfirmed, void *pContext );
static void OnConfirmExit( bool bConfirmed, void *pContext );
static void OnConfirmRewind( bool bConfirmed, void *pContext );
MESSAGE_FUNC_PARAMS( OnSliderMoved, "SliderMoved", pParams );
ReplayHandle_t m_hReplay;
float m_flLastTime; // Can't use gpGlobals->frametime when playback is paused
float m_flOldFps;
CExLabel *m_pCurTimeLabel;
CExLabel *m_pTotalTimeLabel;
CExLabel *m_pPlayerNameLabel;
KeyValues *m_pPlayerCellData;
CPlayerCell *m_pPlayerCells[2][MAX_PLAYERS+1];
vgui::ImageList *m_pImageList;
EditablePanel *m_pMouseTargetPanel;
EditablePanel *m_pBottom;
CPlayerCell *m_pCurTargetCell;
CExImageButton *m_pCameraButtons[NCAMS];
CExImageButton *m_pCtrlButtons[NUM_CTRLBUTTONS];
float m_flTimeScaleProxy;
EditablePanel *m_pPlayerCellsPanel;
vgui::ImagePanel *m_pCameraSelection;
CameraMode_t m_iCameraSelection; // NOTE: Indexes into some arrays
CReplayTipLabel *m_pButtonTip;
CSavingDialog *m_pSavingDlg;
enum MenuItems_t
{
MENU_SAVE,
MENU_SAVEAS,
MENU_EXIT,
NUM_MENUITEMS
};
CExImageButton *m_pMenuButton;
vgui::Menu *m_pMenu;
int m_aMenuItemIds[ NUM_MENUITEMS ];
CExButton *m_pSlowMoButton;
CCameraOptionsPanel *m_pCameraOptionsPanels[NCAMS];
CUtlLinkedList< vgui::Panel *, int > m_lstDisableKeyboardInputPanels;
int m_nRedBlueLabelRightX;
int m_nBottomPanelStartY;
int m_nBottomPanelHeight;
int m_nRedBlueSigns[2];
int m_iCurPlayerTarget;
float m_flSpaceDownStart; // The time at which user started holding down space bar
bool m_bSpaceDown;
bool m_bSpacePressed;
int m_nLastRoundedTime;
bool m_bMousePressed;
bool m_bMouseDown;
float m_flDefaultFramerate; // host_framerate before perf editor started mucking about with it
CameraMode_t m_nMouseClickedOverCameraSettingsPanel; // Allows user to drag slider outside of camera settings panel w/o the panel disappearing
CRecLightPanel *m_pRecLightPanel;
bool m_bShownAtLeastOnce; // Has the replay editor shown at least once? In other words, has the user hit the space bar at all yet?
char m_szSuspendedEvent[128];
bool m_bAchievementAwarded; // Was an achievement awarded during this editing session?
float m_flLastTimeSpaceBarPressed;
float m_flActiveTimeInEditor; // Will be zero'd out if user is idle (ie if they don't press space bar often enough)
CPanelAnimationVarAliasType( int, m_nRightMarginWidth, "right_margin_width", "0", "proportional_xpos" );
bool m_bCurrentTargetNeedsVisibilityUpdate;
};
//-----------------------------------------------------------------------------
CReplayPerformanceEditorPanel *ReplayUI_InitPerformanceEditor( ReplayHandle_t hReplay );
CReplayPerformanceEditorPanel *ReplayUI_GetPerformanceEditor();
void ReplayUI_ClosePerformanceEditor();
//-----------------------------------------------------------------------------
#endif // REPLAYPERFORMANCEEDITOR_H
#endif
@@ -0,0 +1,261 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
//=======================================================================================//
#include "cbase.h"
#if defined( REPLAY_ENABLED )
#include "replayperformancesavedlg.h"
#include "replay/performance.h"
#include "replay/ireplaymanager.h"
#include "replay/ireplayperformancecontroller.h"
#include "replay/replay.h"
#include "econ/confirm_dialog.h"
#include "vgui_controls/EditablePanel.h"
#include "vgui_controls/TextEntry.h"
#include "vgui_controls/TextImage.h"
#include "vgui/ISurface.h"
#include "replay/replaycamera.h"
#include "replayperformanceeditor.h"
//-----------------------------------------------------------------------------
using namespace vgui;
//-----------------------------------------------------------------------------
// Purpose: Player input dialog for a replay
//-----------------------------------------------------------------------------
class CReplayPerformanceSaveDlg : public EditablePanel
{
private:
DECLARE_CLASS_SIMPLE( CReplayPerformanceSaveDlg, EditablePanel );
public:
CReplayPerformanceSaveDlg( Panel *pParent, const char *pName,
OnConfirmSaveCallback pfnCallback, void *pContext, CReplay *pReplay, bool bExitEditorWhenDone );
~CReplayPerformanceSaveDlg();
static void Show( OnConfirmSaveCallback pfnCallback, void *pContext, CReplay *pReplay,
bool bExitEditorWhenDone );
virtual void ApplySchemeSettings( IScheme *pScheme );
virtual void PerformLayout();
virtual void OnCommand( const char *command );
virtual void OnKeyCodePressed( KeyCode code );
virtual void OnKeyCodeTyped( KeyCode code );
bool ConfirmOverwriteOrSaveNow();
void CloseWindow();
static void OnConfirmOverwrite( bool bConfirm, void *pContext );
MESSAGE_FUNC( OnSetFocus, "SetFocus" );
static vgui::DHANDLE< CReplayPerformanceSaveDlg > ms_hDlg;
private:
OnConfirmSaveCallback m_pfnCallback;
void *m_pContext;
Panel *m_pDlg;
CReplay *m_pReplay;
TextEntry *m_pTitleEntry;
bool m_bExitEditorWhenDone;
wchar_t m_wszTitle[ MAX_TAKE_TITLE_LENGTH ];
};
vgui::DHANDLE< CReplayPerformanceSaveDlg > CReplayPerformanceSaveDlg::ms_hDlg;
//-----------------------------------------------------------------------------
// Purpose: CReplayPerformanceSaveDlg implementation
//-----------------------------------------------------------------------------
CReplayPerformanceSaveDlg::CReplayPerformanceSaveDlg( Panel *pParent, const char *pName,
OnConfirmSaveCallback pfnCallback, void *pContext,
CReplay *pReplay, bool bExitEditorWhenDone )
: BaseClass( pParent, pName ),
m_pfnCallback( pfnCallback ),
m_pContext( pContext ),
m_pReplay( pReplay ),
m_bExitEditorWhenDone( bExitEditorWhenDone ),
m_pDlg( NULL ),
m_pTitleEntry( NULL )
{
Assert( m_pContext );
SetScheme( "ClientScheme" );
SetProportional( true );
}
CReplayPerformanceSaveDlg::~CReplayPerformanceSaveDlg()
{
ms_hDlg = NULL;
}
/*static*/ void CReplayPerformanceSaveDlg::Show( OnConfirmSaveCallback pfnCallback, void *pContext, CReplay *pReplay,
bool bExitEditorWhenDone )
{
Assert( !ms_hDlg.Get() );
ms_hDlg = vgui::SETUP_PANEL( new CReplayPerformanceSaveDlg( NULL, "ReplayInputPanel", pfnCallback, pContext, pReplay, bExitEditorWhenDone ) );
ms_hDlg->SetVisible( true );
ms_hDlg->MakePopup();
ms_hDlg->MoveToFront();
ms_hDlg->SetKeyBoardInputEnabled(true);
ms_hDlg->SetMouseInputEnabled(true);
TFModalStack()->PushModal( ms_hDlg );
engine->ClientCmd_Unrestricted( "gameui_hide" );
ReplayCamera()->EnableInput( false );
}
void CReplayPerformanceSaveDlg::ApplySchemeSettings( IScheme *pScheme )
{
BaseClass::ApplySchemeSettings( pScheme );
LoadControlSettings( "resource/ui/replayperformanceeditor/savedlg.res", "GAME" );
// Cache off the dlg pointer
m_pDlg = FindChildByName( "Dlg" );
CExButton *pDiscardButton;
pDiscardButton = dynamic_cast< CExButton * >( m_pDlg->FindChildByName( "DiscardButton" ) );
SetXToRed( pDiscardButton );
// Setup some action sigs
m_pDlg->FindChildByName( "SaveButton" )->AddActionSignalTarget( this );
m_pDlg->FindChildByName( "CancelButton" )->AddActionSignalTarget( this );
pDiscardButton->AddActionSignalTarget( this );
m_pTitleEntry = static_cast< TextEntry * >( m_pDlg->FindChildByName( "TitleInput" ) );
m_pTitleEntry->SelectAllOnFocusAlways( true );
m_pTitleEntry->SetSelectionBgColor( GetSchemeColor( "Yellow", Color( 255, 255, 255, 255), pScheme ) );
m_pTitleEntry->SetSelectionTextColor( Color( 255, 255, 255, 255 ) );
m_pTitleEntry->SetText( L"" );
}
void CReplayPerformanceSaveDlg::PerformLayout()
{
BaseClass::PerformLayout();
SetWide( ScreenWidth() );
SetTall( ScreenHeight() );
// Center
m_pDlg->SetPos( ( ScreenWidth() - m_pDlg->GetWide() ) / 2, ( ScreenHeight() - m_pDlg->GetTall() ) / 2 );
}
void CReplayPerformanceSaveDlg::OnKeyCodeTyped( KeyCode code )
{
if ( code == KEY_ESCAPE )
{
surface()->PlaySound( "replay\\record_fail.wav" );
return;
}
BaseClass::OnKeyCodeTyped( code );
}
void CReplayPerformanceSaveDlg::OnKeyCodePressed( KeyCode code )
{
if ( code == KEY_ENTER )
{
OnCommand( "save" );
}
BaseClass::OnKeyCodePressed( code );
}
void CReplayPerformanceSaveDlg::OnSetFocus()
{
m_pTitleEntry->RequestFocus();
}
/*static*/ void CReplayPerformanceSaveDlg::OnConfirmOverwrite( bool bConfirm, void *pContext )
{
CReplayPerformanceSaveDlg *pThis = (CReplayPerformanceSaveDlg *)pContext;
pThis->m_pfnCallback( bConfirm, pThis->m_wszTitle, pThis->m_pContext );
pThis->CloseWindow();
}
bool CReplayPerformanceSaveDlg::ConfirmOverwriteOrSaveNow()
{
// Using the same title as an existing performance?
CReplayPerformance *pExistingPerformance = m_pReplay->GetPerformanceWithTitle( m_wszTitle );
if ( pExistingPerformance )
{
ShowConfirmDialog( "#Replay_OverwriteDlgTitle", "#Replay_OverwriteDlgText",
"#Replay_ConfirmOverwrite", "#Replay_Cancel", OnConfirmOverwrite, NULL, this );
return false;
}
m_pfnCallback( true, m_wszTitle, m_pContext );
return true;
}
void CReplayPerformanceSaveDlg::OnCommand( const char *command )
{
bool bCloseWindow = false;
extern IReplayPerformanceController *g_pReplayPerformanceController;
if ( !Q_strnicmp( command, "save", 4 ) )
{
// Get the text and save the replay/performance immediately
m_pTitleEntry->GetText( m_wszTitle, MAX_TAKE_TITLE_LENGTH );
// If we aren't overwriting an existing performance, this func will return true.
bCloseWindow = ConfirmOverwriteOrSaveNow();
}
else if ( !Q_strnicmp( command, "cancel", 6 ) )
{
bCloseWindow = true;
}
// Close the window?
if ( bCloseWindow )
{
CloseWindow();
}
BaseClass::OnCommand( command );
}
void CReplayPerformanceSaveDlg::CloseWindow()
{
SetVisible( false );
MarkForDeletion();
TFModalStack()->PopModal( ms_hDlg.Get() );
ReplayCamera()->EnableInput( true );
CReplayPerformanceEditorPanel *pEditor = ReplayUI_GetPerformanceEditor();
if ( m_bExitEditorWhenDone && pEditor )
{
pEditor->Exit();
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void ReplayUI_ShowPerformanceSaveDlg( OnConfirmSaveCallback pfnCallback,
void *pContext, CReplay *pReplay,
bool bExitEditorWhenDone )
{
CReplayPerformanceSaveDlg::Show( pfnCallback, pContext, pReplay, bExitEditorWhenDone );
}
bool ReplayUI_IsPerformanceSaveDlgOpen()
{
return CReplayPerformanceSaveDlg::ms_hDlg.Get() != NULL;
}
//-----------------------------------------------------------------------------
// Purpose: Test the replay input dialog
//-----------------------------------------------------------------------------
CON_COMMAND_F( replay_test_take_save_dlg, "Open replay save take dlg", FCVAR_NONE )
{
ReplayUI_ShowPerformanceSaveDlg( NULL, NULL, NULL, false );
}
#endif
@@ -0,0 +1,27 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
//=======================================================================================//
#ifndef REPLAYPERFORMANCESAVEDLG_H
#define REPLAYPERFORMANCESAVEDLG_H
#ifdef _WIN32
#pragma once
#endif
//-----------------------------------------------------------------------------
class CReplay;
//-----------------------------------------------------------------------------
typedef void (*OnConfirmSaveCallback)( bool bConfirmed, wchar_t *pTitle, void *pContext );
//-----------------------------------------------------------------------------
void ReplayUI_ShowPerformanceSaveDlg( OnConfirmSaveCallback pfnCallback, void *pContext, CReplay *pReplay,
bool bExitEditorWhenDone );
bool ReplayUI_IsPerformanceSaveDlgOpen();
//-----------------------------------------------------------------------------
#endif // REPLAYPERFORMANCESAVEDLG_H
@@ -0,0 +1,163 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#include "cbase.h"
#if defined( REPLAY_ENABLED )
#include "replayreminderpanel.h"
#include "replay/ireplaysystem.h"
#include "replay/replay.h"
#include "replay/ireplayscreenshotmanager.h"
#include "replay/ireplaymanager.h"
#include "replay/screenshot.h"
#include "iclientmode.h"
#include "vgui_controls/AnimationController.h"
//-----------------------------------------------------------------------------
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
//-----------------------------------------------------------------------------
DECLARE_HUDELEMENT( CReplayReminderPanel );
//-----------------------------------------------------------------------------
CReplayReminderPanel::CReplayReminderPanel( const char *pElementName )
: EditablePanel( g_pClientMode->GetViewport(), "ReplayReminder" ),
CHudElement( pElementName )
{
SetScheme( "ClientScheme" );
m_flShowTime = 0;
m_bShouldDraw = false;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CReplayReminderPanel::SetupText()
{
// Get current key binding, if any.
const char *pBoundKey = engine->Key_LookupBinding( "save_replay" );
if ( !pBoundKey || FStrEq( pBoundKey, "(null)" ) )
{
pBoundKey = " ";
}
char szKey[16];
Q_snprintf( szKey, sizeof(szKey), "%s", pBoundKey );
wchar_t wKey[16];
wchar_t wLabel[256];
g_pVGuiLocalize->ConvertANSIToUnicode( szKey, wKey, sizeof( wKey ) );
g_pVGuiLocalize->ConstructString_safe( wLabel, g_pVGuiLocalize->Find("#Replay_freezecam_replay" ), 1, wKey );
// Set the text
SetDialogVariable( "text", wLabel );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CReplayReminderPanel::ApplySchemeSettings( IScheme *pScheme )
{
LoadControlSettings("Resource/UI/ReplayReminder.res", "GAME");
BaseClass::ApplySchemeSettings( pScheme );
SetupText();
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CReplayReminderPanel::Show()
{
m_flShowTime = gpGlobals->curtime;
SetVisible( true );
g_pClientMode->GetViewportAnimationController()->StartAnimationSequence( GetParent(), "HudReplayReminderIn" );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CReplayReminderPanel::Hide()
{
SetVisible( false );
m_flShowTime = 0;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
int CReplayReminderPanel::HudElementKeyInput( int down, ButtonCode_t keynum, const char *pszCurrentBinding )
{
if ( ShouldDraw() && pszCurrentBinding )
{
if ( FStrEq (pszCurrentBinding, "save_replay" ) )
{
SetVisible( false );
}
}
return 0;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CReplayReminderPanel::OnThink()
{
BaseClass::OnThink();
if ( !IsVisible() )
return;
// If we're displaying the element for some specific duration...
if ( m_flShowTime )
{
// Get maximum duration
ConVarRef replay_postwinreminderduration( "replay_postwinreminderduration" );
float flShowLength = replay_postwinreminderduration.IsValid() ? replay_postwinreminderduration.GetFloat() : 5.0f;
if ( gpGlobals->curtime >= m_flShowTime + flShowLength )
{
m_flShowTime = 0;
SetVisible( false );
}
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CReplayReminderPanel::SetVisible( bool bState )
{
if ( bState )
{
SetupText();
}
// Store this state for ShouldDraw()
m_bShouldDraw = bState;
BaseClass::SetVisible( bState );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
bool CReplayReminderPanel::ShouldDraw()
{
return m_bShouldDraw;
}
#endif // #if defined( REPLAY_ENABLED )
@@ -0,0 +1,50 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================
#ifndef REPLAYREMINDERPANEL_H
#define REPLAYREMINDERPANEL_H
#ifdef _WIN32
#pragma once
#endif
#include <vgui_controls/EditablePanel.h>
#include <game/client/iviewport.h>
#include <vgui/IScheme.h>
#include "hud.h"
#include "hudelement.h"
using namespace vgui;
//-----------------------------------------------------------------------------
// Purpose: Replay reminder panel
//-----------------------------------------------------------------------------
class CReplayReminderPanel : public EditablePanel, public CHudElement
{
DECLARE_CLASS_SIMPLE( CReplayReminderPanel, vgui::EditablePanel );
public:
CReplayReminderPanel( const char *pElementName );
void Hide(); // To be used by HUD only
void Show(); // To be used by HUD only
// CHudElement overrides
virtual bool ShouldDraw();
virtual void OnThink();
virtual int HudElementKeyInput( int down, ButtonCode_t keynum, const char *pszCurrentBinding );
// EditablePanel overrides
virtual void ApplySchemeSettings( IScheme *pScheme );
virtual void SetVisible( bool bState );
private:
void SetupText();
float m_flShowTime; // Used by the HUD only, to display the panel only for a certain period of time
bool m_bShouldDraw; // Store this state for ShouldDraw(), which allows us to use a single panel for
// both the post-win reminder and the freezepanel reminder.
};
#endif // REPLAYREMINDERPANEL_H
@@ -0,0 +1,380 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
//=======================================================================================//
#include "cbase.h"
#if defined( REPLAY_ENABLED )
#include "replayrenderoverlay.h"
#include "vgui_controls/TextImage.h"
#include "replay/genericclassbased_replay.h"
#include "iclientmode.h"
#include "VGuiMatSurface/IMatSystemSurface.h"
#include "ienginevgui.h"
#include "vgui/IVGui.h"
#include "econ/confirm_dialog.h"
#include "replay/ireplaymanager.h"
#include "replay/irecordingsessionmanager.h"
#include "replay/ireplaymoviemanager.h"
#include "replay/replayrenderer.h"
#include "econ/econ_controls.h"
// memdbgon must be the last include file in a .cpp file!!!
#include <tier0/memdbgon.h>
//-----------------------------------------------------------------------------
extern IReplayMovieManager *g_pReplayMovieManager;
//-----------------------------------------------------------------------------
using namespace vgui;
//-----------------------------------------------------------------------------
#define TMP_ENCODED_AUDIO ".tmp.aac"
#ifdef USE_WEBM_FOR_REPLAY
#define TMP_ENCODED_VIDEO ".tmp.webm"
#else
#define TMP_ENCODED_VIDEO ".tmp.mov"
#endif
//-----------------------------------------------------------------------------
ConVar replay_enablerenderpreview( "replay_enablerenderpreview", "1", FCVAR_CLIENTDLL | FCVAR_DONTRECORD | FCVAR_ARCHIVE, "Enable preview during replay render." );
//-----------------------------------------------------------------------------
void OnRenderCancelDialogButtonPressed( bool bConfirm, void *pContext )
{
if ( bConfirm )
{
g_pReplayMovieManager->CancelRender();
}
}
//-----------------------------------------------------------------------------
CReplayRenderOverlay::CReplayRenderOverlay( Panel *pParent )
: BaseClass( pParent, "ReplayRenderOverlay" ),
m_pBottom( NULL ),
m_pCancelButton( NULL ),
m_pTitleLabel( NULL ),
m_pProgressLabel( NULL ),
m_pFilenameLabel( NULL ),
m_pRenderProgress( NULL ),
m_pRenderer( NULL ),
m_pPreviewCheckButton( NULL ),
m_unNumFrames( 0 ),
m_flStartTime( 0.0f ),
m_flPreviousTimeLeft( 0.0f )
{
if ( pParent == NULL )
{
vgui::HScheme scheme = vgui::scheme()->LoadSchemeFromFileEx( enginevgui->GetPanel( PANEL_CLIENTDLL ), "resource/ClientScheme.res", "ClientScheme");
SetScheme(scheme);
SetProportional( true );
}
ivgui()->AddTickSignal( GetVPanel(), 10 );
m_pRenderer = new CReplayRenderer( this );
}
CReplayRenderOverlay::~CReplayRenderOverlay()
{
ivgui()->RemoveTickSignal( GetVPanel() );
delete m_pRenderer;
}
void CReplayRenderOverlay::Show()
{
// Setup panel
SetVisible( true );
SetMouseInputEnabled( true );
SetKeyBoardInputEnabled( true );
MakePopup( true );
MoveToFront();
TFModalStack()->PushModal( this );
// Make sure game UI is hidden
engine->ClientCmd_Unrestricted( "gameui_hide" );
InvalidateLayout( false, true );
}
void CReplayRenderOverlay::Hide()
{
SetVisible( false );
TFModalStack()->PopModal( this );
MarkForDeletion();
}
void CReplayRenderOverlay::ApplySchemeSettings( IScheme *pScheme )
{
BaseClass::ApplySchemeSettings( pScheme );
// Load controls
LoadControlSettings( "Resource/UI/replayrenderoverlay.res", "GAME" );
// Layout bottom
m_pBottom = dynamic_cast< EditablePanel * >( FindChildByName( "BottomPanel" ) );
if ( !m_pBottom )
return;
// Find some controls
m_pTitleLabel = dynamic_cast< CExLabel * >( FindChildByName( "TitleLabel" ) );
m_pProgressLabel = dynamic_cast< CExLabel * >( FindChildByName( "ProgressLabel" ) );
m_pRenderProgress = dynamic_cast< ProgressBar * >( FindChildByName( "RenderProgress" ) );
m_pCancelButton = dynamic_cast< CExButton * >( FindChildByName( "CancelButton" ) );
m_pFilenameLabel = dynamic_cast< CExLabel * >( FindChildByName( "FilenameLabel" ) );
m_pPreviewCheckButton = dynamic_cast< CheckButton * >( FindChildByName( "PreviewCheckButton" ) );
m_pPreviewCheckButton->SetProportional( false );
m_pPreviewCheckButton->SetSelected( replay_enablerenderpreview.GetBool() );
m_pPreviewCheckButton->AddActionSignalTarget( this );
const char *pMovieFilename = m_pRenderer->GetMovieFilename();
if ( m_pFilenameLabel && pMovieFilename )
{
const char *pFilename = V_UnqualifiedFileName( pMovieFilename );
m_pFilenameLabel->SetText( pFilename );
}
}
void CReplayRenderOverlay::PerformLayout()
{
BaseClass::PerformLayout();
if ( !m_pBottom )
return;
int sw, sh;
vgui::surface()->GetScreenSize( sw, sh );
SetBounds( 0, 0, sw, sh );
int nBottomPanelHeight = sh * .13f;
int nBottomPanelStartY = sh - nBottomPanelHeight;
m_pBottom->SetBounds( 0, nBottomPanelStartY, sw, nBottomPanelHeight );
int nBottomW = sw;
int nBottomH = nBottomPanelHeight;
// Setup progress bar
if ( !m_pRenderProgress )
return;
int nProgHeight = YRES(20);
int nMargin = nBottomW/5;
int nProgX = nMargin;
int nProgY = nBottomPanelStartY + ( nBottomH - nProgHeight ) / 2;
int nProgW = nBottomW - 2*nMargin;
// Only show progress bar if replay is valid and length of render is non-zero, and the record start tick exists
CReplay *pReplay = g_pReplayManager->GetPlayingReplay();
if ( pReplay )
{
const float flTotalTime = pReplay->m_flLength;
const int nServerRecordStartTick = g_pClientReplayContext->GetRecordingSessionManager()->GetServerStartTickForSession( pReplay->m_hSession ); // NOTE: Returns -1 on fail
if ( flTotalTime > 0.0f && nServerRecordStartTick >= 0 )
{
m_pRenderProgress->SetVisible( true );
m_pRenderProgress->SetBounds( nProgX, nProgY, nProgW, nProgHeight );
m_pRenderProgress->SetSegmentInfo( XRES(1), XRES(8) );
}
}
// Layout title label
const int nTitleLabelY = nBottomPanelStartY + ( m_pBottom->GetTall() - m_pTitleLabel->GetTall() ) / 2;
if ( m_pTitleLabel )
{
m_pTitleLabel->SizeToContents();
m_pTitleLabel->SetPos( ( nProgX - m_pTitleLabel->GetWide() ) / 2, nTitleLabelY );
}
// Layout preview check button
if ( m_pPreviewCheckButton )
{
m_pPreviewCheckButton->SizeToContents();
m_pPreviewCheckButton->SetPos( ( nProgX - m_pPreviewCheckButton->GetWide() ) / 2, nTitleLabelY + m_pTitleLabel->GetTall() + YRES(3) );
}
// Layout filename label
if ( m_pFilenameLabel )
{
int nProgBottomY = nProgY + nProgHeight;
m_pFilenameLabel->SizeToContents();
m_pFilenameLabel->SetPos( nProgX, nProgBottomY + ( sh - nProgBottomY - m_pFilenameLabel->GetTall() ) / 2 );
}
// Layout progress label
if ( m_pProgressLabel )
{
int nProgBottomY = nProgY + nProgHeight;
m_pProgressLabel->SizeToContents();
m_pProgressLabel->SetPos( nProgX, nProgBottomY + ( sh - nProgBottomY - m_pProgressLabel->GetTall() ) / 2 );
m_pProgressLabel->SetWide( nProgW );
}
// Layout cancel button
if ( !m_pCancelButton )
return;
// Put cancel button half way in between progress bar and screen right
int nProgRightX = nProgX + nProgW;
m_pCancelButton->SetPos(
nProgRightX + ( m_pBottom->GetWide() - nProgRightX - m_pCancelButton->GetWide() ) / 2,
nBottomPanelStartY + ( m_pBottom->GetTall() - m_pCancelButton->GetTall() ) / 2
);
SetXToRed( m_pCancelButton );
m_pCancelButton->RequestFocus();
}
void CReplayRenderOverlay::OnTick()
{
#if _DEBUG
if ( m_bReloadScheme )
{
InvalidateLayout( true, true );
m_bReloadScheme = false;
}
#endif
// Update progress
if ( m_pRenderProgress )
{
CReplay *pReplay = g_pReplayManager->GetPlayingReplay();
if ( pReplay && m_pRenderProgress->IsVisible() )
{
float flCurTime, flTotalTime;
g_pClientReplayContext->GetPlaybackTimes( flCurTime, flTotalTime, pReplay, m_pRenderer->GetPerformance() );
const float flProgress = ( flTotalTime == 0.0f ) ? 1.0f : ( flCurTime / flTotalTime );
Assert( flTotalTime > 0.0f ); // NOTE: Progress bar will always be invisible if total time is 0, but check anyway to be safe.
m_pRenderProgress->SetProgress( MAX( m_pRenderProgress->GetProgress(), flProgress ) ); // The MAX() here keeps the progress bar from thrashing
if ( m_pProgressLabel )
{
// @note Tom Bui: this is a horribly ugly hack, but the first couple of frames take a really freaking long time, so that
// really blows out the estimate
float flTimePassed = 0.0f;
++m_unNumFrames;
const uint32 kNumFramesToWait = 10;
if ( m_unNumFrames < kNumFramesToWait )
{
m_flStartTime = gpGlobals->realtime;
}
else if ( m_unNumFrames > kNumFramesToWait )
{
flTimePassed = gpGlobals->realtime - m_flStartTime;
float flEstimatedTimeLeft = flProgress > 0.0f ? ( flTimePassed / flProgress ) - flTimePassed : 0.0f;
// exponential moving average FIR filter
// S(t) = smoothing_factor * Y(t) + (1 - smoothing_factor)* Y(t-1)
// previous value is essentially 90% of the current value
const float kSmoothingFactor = 0.1f;
if ( m_flPreviousTimeLeft == 0.0f )
{
m_flPreviousTimeLeft = flEstimatedTimeLeft;
}
else
{
m_flPreviousTimeLeft = kSmoothingFactor * flEstimatedTimeLeft + ( 1 - kSmoothingFactor ) * m_flPreviousTimeLeft;
}
}
wchar_t wszTimeLeft[256];
wchar_t wszTime[256];
{
const char *pRenderTime = CReplayTime::FormatTimeString( RoundFloatToInt( m_flPreviousTimeLeft ) );
g_pVGuiLocalize->ConvertANSIToUnicode( pRenderTime, wszTimeLeft, sizeof( wszTimeLeft ) );
}
{
const char *pRenderTime = CReplayTime::FormatTimeString( RoundFloatToInt( flTimePassed ) );
g_pVGuiLocalize->ConvertANSIToUnicode( pRenderTime, wszTime, sizeof( wszTime ) );
}
wchar_t wszText[256];
g_pVGuiLocalize->ConstructString_safe( wszText, g_pVGuiLocalize->Find( "#Replay_RenderOverlay_TimeLeft" ), 2, wszTime, wszTimeLeft );
m_pProgressLabel->SetText( wszText );
}
}
}
}
void CReplayRenderOverlay::OnMousePressed( MouseCode nCode )
{
#if _DEBUG
m_bReloadScheme = true;
#endif
BaseClass::OnMousePressed( nCode );
}
void CReplayRenderOverlay::OnKeyCodeTyped( vgui::KeyCode nCode )
{
if ( nCode == KEY_ESCAPE )
{
if ( TFModalStack()->Top() == GetVPanel() )
{
OnCommand( "confirmcancel" );
return;
}
}
BaseClass::OnKeyCodeTyped( nCode );
}
void CReplayRenderOverlay::OnCommand( const char *pCommand )
{
if ( !V_stricmp( pCommand, "confirmcancel" ) )
{
ShowConfirmDialog( "#Replay_CancelRenderTitle", "#Replay_ConfirmCancelRender", "#Replay_YesCancel", "#Replay_No", OnRenderCancelDialogButtonPressed, this, NULL, "replay\\replaydialog_warn.wav" );
return;
}
BaseClass::OnCommand( pCommand );
}
void CReplayRenderOverlay::OnCheckButtonChecked( Panel *pPanel )
{
replay_enablerenderpreview.SetValue( (int)m_pPreviewCheckButton->IsSelected() );
}
//-----------------------------------------------------------------------------
static CReplayRenderOverlay *s_pRenderOverlay = NULL;
void ReplayUI_OpenReplayRenderOverlay()
{
if ( !g_pReplayMovieManager->IsRendering() )
return;
// Delete any existing panel
if ( s_pRenderOverlay )
{
s_pRenderOverlay->MarkForDeletion();
}
// Create the panel - get the render resolution from the settings
s_pRenderOverlay = SETUP_PANEL( new CReplayRenderOverlay( NULL ) ); // Parenting to NULL allows us to turn off world rendering in engine/view.cpp (V_RenderView())
// Set the panel as the movie renderer, so it can receive begin/end render calls from the engine
g_pClientReplayContext->SetMovieRenderer( s_pRenderOverlay->m_pRenderer );
}
void ReplayUI_HideRenderOverlay()
{
if ( s_pRenderOverlay )
{
s_pRenderOverlay->MarkForDeletion();
s_pRenderOverlay = NULL;
}
g_pClientReplayContext->SetMovieRenderer( NULL );
}
//-----------------------------------------------------------------------------
#endif
@@ -0,0 +1,73 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
//=======================================================================================//
#ifndef REPLAY_RENDEROVERLAY_H
#define REPLAY_RENDEROVERLAY_H
#ifdef _WIN32
#pragma once
#endif
//-----------------------------------------------------------------------------
#include "vgui_controls/Frame.h"
#include "vgui_controls/ProgressBar.h"
#include "replay/rendermovieparams.h"
//-----------------------------------------------------------------------------
class CExButton;
class CExLabel;
class IQuickTimeMovieMaker;
class CReplay;
class CReplayRenderer;
//-----------------------------------------------------------------------------
class CReplayRenderOverlay : public vgui::Frame
{
DECLARE_CLASS_SIMPLE( CReplayRenderOverlay, vgui::Frame );
public:
CReplayRenderOverlay( Panel *pParent );
~CReplayRenderOverlay();
void Show();
void Hide();
CReplayRenderer *m_pRenderer;
private:
virtual void ApplySchemeSettings( vgui::IScheme *pScheme );
virtual void PerformLayout();
virtual void OnTick();
virtual void OnMousePressed( vgui::MouseCode nCode );
virtual void OnKeyCodeTyped( vgui::KeyCode nCode );
virtual void OnCommand( const char *pCommand );
private:
MESSAGE_FUNC_PTR( OnCheckButtonChecked, "CheckButtonChecked", pPanel );
#if _DEBUG
bool m_bReloadScheme;
#endif
int m_unNumFrames;
float m_flStartTime;
float m_flPreviousTimeLeft;
EditablePanel *m_pBottom;
vgui::ProgressBar *m_pRenderProgress;
vgui::CheckButton *m_pPreviewCheckButton;
CExButton *m_pCancelButton;
CExLabel *m_pTitleLabel;
CExLabel *m_pFilenameLabel;
CExLabel *m_pProgressLabel;
};
//-----------------------------------------------------------------------------
void ReplayUI_OpenReplayRenderOverlay();
void ReplayUI_HideRenderOverlay();
//-----------------------------------------------------------------------------
#endif // REPLAY_RENDEROVERLAY_H