475 lines
11 KiB
C++
475 lines
11 KiB
C++
|
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||
|
//
|
||
|
//=======================================================================================//
|
||
|
|
||
|
#include "cl_replaymoviemanager.h"
|
||
|
#include "replay/ireplaymoviemanager.h"
|
||
|
#include "replay/ireplaymovierenderer.h"
|
||
|
#include "replay/replay.h"
|
||
|
#include "replay/replayutils.h"
|
||
|
#include "replay/rendermovieparams.h"
|
||
|
#include "replay/shared_defs.h"
|
||
|
#include "cl_replaymovie.h"
|
||
|
#include "cl_renderqueue.h"
|
||
|
#include "cl_replaycontext.h"
|
||
|
#include "filesystem.h"
|
||
|
#include "KeyValues.h"
|
||
|
#include "replaysystem.h"
|
||
|
#include "cl_replaymanager.h"
|
||
|
#include "materialsystem/imaterialsystem.h"
|
||
|
#include "materialsystem/materialsystem_config.h"
|
||
|
|
||
|
// memdbgon must be the last include file in a .cpp file!!!
|
||
|
#include "tier0/memdbgon.h"
|
||
|
|
||
|
//----------------------------------------------------------------------------------------
|
||
|
|
||
|
#define MOVIE_MANAGER_VERSION 1
|
||
|
|
||
|
//----------------------------------------------------------------------------------------
|
||
|
|
||
|
extern IMaterialSystem *materials;
|
||
|
|
||
|
//----------------------------------------------------------------------------------------
|
||
|
|
||
|
CReplayMovieManager::CReplayMovieManager()
|
||
|
: m_pPendingMovie( NULL ),
|
||
|
m_pVidModeSettings( NULL ),
|
||
|
m_pRenderMovieSettings( NULL ),
|
||
|
m_bIsRendering( false ),
|
||
|
m_bRenderingCancelled( false )
|
||
|
{
|
||
|
m_pVidModeSettings = new MaterialSystem_Config_t();
|
||
|
m_pRenderMovieSettings = new RenderMovieParams_t();
|
||
|
|
||
|
m_wszCachedMovieTitle[0] = L'\0';
|
||
|
}
|
||
|
|
||
|
CReplayMovieManager::~CReplayMovieManager()
|
||
|
{
|
||
|
delete m_pVidModeSettings;
|
||
|
}
|
||
|
|
||
|
bool CReplayMovieManager::Init()
|
||
|
{
|
||
|
// Create "rendered" dir
|
||
|
const char *pRenderedDir = Replay_va( "%s%s%c", CL_GetReplayBaseDir(), SUBDIR_RENDERED, CORRECT_PATH_SEPARATOR );
|
||
|
g_pFullFileSystem->CreateDirHierarchy( pRenderedDir );
|
||
|
|
||
|
return BaseClass::Init();
|
||
|
}
|
||
|
|
||
|
int CReplayMovieManager::GetMovieCount()
|
||
|
{
|
||
|
return Count();
|
||
|
}
|
||
|
|
||
|
void CReplayMovieManager::GetMovieList( CUtlLinkedList< IReplayMovie * > &list )
|
||
|
{
|
||
|
FOR_EACH_OBJ( this, i )
|
||
|
{
|
||
|
list.AddToTail( ToMovie( m_vecObjs[ i ] ) );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
IReplayMovie *CReplayMovieManager::GetMovie( ReplayHandle_t hMovie )
|
||
|
{
|
||
|
return ToMovie( Find( hMovie ) );
|
||
|
}
|
||
|
|
||
|
void CReplayMovieManager::AddMovie( CReplayMovie *pNewMovie )
|
||
|
{
|
||
|
Add( pNewMovie );
|
||
|
Save();
|
||
|
}
|
||
|
|
||
|
CReplayMovie *CReplayMovieManager::Create()
|
||
|
{
|
||
|
return new CReplayMovie();
|
||
|
}
|
||
|
|
||
|
const char *CReplayMovieManager::GetRelativeIndexPath() const
|
||
|
{
|
||
|
return Replay_va( "%s%c", SUBDIR_MOVIES, CORRECT_PATH_SEPARATOR );
|
||
|
}
|
||
|
|
||
|
IReplayMovie *CReplayMovieManager::CreateAndAddMovie( ReplayHandle_t hReplay )
|
||
|
{
|
||
|
CReplayMovie *pNewMovie = CreateAndGenerateHandle(); // Sets m_hThis (which is accessed via GetHandle())
|
||
|
|
||
|
// Cache replay handle.
|
||
|
pNewMovie->m_hReplay = hReplay;
|
||
|
|
||
|
// Copy cached render settings to the movie itself.
|
||
|
V_memcpy( &pNewMovie->m_RenderSettings, &m_pRenderMovieSettings->m_Settings, sizeof( ReplayRenderSettings_t ) );
|
||
|
|
||
|
AddMovie( pNewMovie );
|
||
|
|
||
|
return pNewMovie;
|
||
|
}
|
||
|
|
||
|
void CReplayMovieManager::DeleteMovie( ReplayHandle_t hMovie )
|
||
|
{
|
||
|
// Cache owner replay
|
||
|
CReplayMovie *pMovie = Find( hMovie );
|
||
|
CReplay *pOwnerReplay = pMovie ? CL_GetReplayManager()->GetReplay( pMovie->m_hReplay ) : NULL;
|
||
|
|
||
|
Remove( hMovie );
|
||
|
|
||
|
// If no more movies for the given replay, mark as unrendered & save
|
||
|
if ( pOwnerReplay && GetNumMoviesDependentOnReplay( pOwnerReplay ) == 0 )
|
||
|
{
|
||
|
pOwnerReplay->m_bRendered = false;
|
||
|
CL_GetReplayManager()->FlagReplayForFlush( pOwnerReplay, false );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
int CReplayMovieManager::GetNumMoviesDependentOnReplay( const CReplay *pReplay )
|
||
|
{
|
||
|
if ( !pReplay )
|
||
|
return 0;
|
||
|
|
||
|
// Go through all movies and find any that depend on the given replay
|
||
|
int nNumMovies = 0;
|
||
|
FOR_EACH_OBJ( this, i )
|
||
|
{
|
||
|
CReplayMovie *pMovie = ToMovie( m_vecObjs[ i ] );
|
||
|
if ( pMovie->m_hReplay == pReplay->GetHandle() )
|
||
|
{
|
||
|
++nNumMovies;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return nNumMovies;
|
||
|
}
|
||
|
|
||
|
void CReplayMovieManager::SetPendingMovie( IReplayMovie *pMovie )
|
||
|
{
|
||
|
m_pPendingMovie = pMovie;
|
||
|
}
|
||
|
|
||
|
IReplayMovie *CReplayMovieManager::GetPendingMovie()
|
||
|
{
|
||
|
return m_pPendingMovie;
|
||
|
}
|
||
|
|
||
|
void CReplayMovieManager::FlagMovieForFlush( IReplayMovie *pMovie, bool bImmediate )
|
||
|
{
|
||
|
FlagForFlush( CastMovie( pMovie ), bImmediate );
|
||
|
}
|
||
|
|
||
|
CReplayMovie *CReplayMovieManager::CastMovie( IReplayMovie *pMovie )
|
||
|
{
|
||
|
return static_cast< CReplayMovie * >( pMovie );
|
||
|
}
|
||
|
|
||
|
int CReplayMovieManager::GetVersion() const
|
||
|
{
|
||
|
return MOVIE_MANAGER_VERSION;
|
||
|
}
|
||
|
|
||
|
IReplayContext *CReplayMovieManager::GetReplayContext() const
|
||
|
{
|
||
|
return g_pClientReplayContextInternal;
|
||
|
}
|
||
|
|
||
|
float CReplayMovieManager::GetNextThinkTime() const
|
||
|
{
|
||
|
return 0.1f;
|
||
|
}
|
||
|
|
||
|
void CReplayMovieManager::CacheMovieTitle( const wchar_t *pTitle )
|
||
|
{
|
||
|
V_wcsncpy( m_wszCachedMovieTitle, pTitle, sizeof( m_wszCachedMovieTitle ) );
|
||
|
}
|
||
|
|
||
|
void CReplayMovieManager::GetCachedMovieTitleAndClear( wchar_t *pOut, int nOutBufLength )
|
||
|
{
|
||
|
const int nLength = wcslen( m_wszCachedMovieTitle );
|
||
|
wcsncpy( pOut, m_wszCachedMovieTitle, nOutBufLength );
|
||
|
pOut[ nLength ] = L'\0';
|
||
|
m_wszCachedMovieTitle[0] = L'\0';
|
||
|
}
|
||
|
|
||
|
void CReplayMovieManager::AddReplayForRender( CReplay *pReplay, int iPerformance )
|
||
|
{
|
||
|
if ( !g_pClientReplayContextInternal->ReconstructReplayIfNecessary( pReplay ) )
|
||
|
{
|
||
|
CL_GetErrorSystem()->AddErrorFromTokenName( "#Replay_Err_Render_ReconstructFailed" );
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
// Store in the demo player's list
|
||
|
g_pReplayDemoPlayer->AddReplayToList( pReplay->GetHandle(), iPerformance );
|
||
|
}
|
||
|
|
||
|
void CReplayMovieManager::ClearRenderCancelledFlag()
|
||
|
{
|
||
|
m_bRenderingCancelled = false;
|
||
|
}
|
||
|
|
||
|
void CReplayMovieManager::RenderMovie( RenderMovieParams_t const& params )
|
||
|
{
|
||
|
// Save state
|
||
|
m_bIsRendering = true;
|
||
|
|
||
|
// Change video settings for recording
|
||
|
SetupVideo( params );
|
||
|
|
||
|
// Clear any old replays in the player
|
||
|
g_pReplayDemoPlayer->ClearReplayList();
|
||
|
|
||
|
// Render all unrendered replays
|
||
|
if ( params.m_hReplay == REPLAY_HANDLE_INVALID )
|
||
|
{
|
||
|
CRenderQueue *pRenderQueue = g_pClientReplayContextInternal->m_pRenderQueue;
|
||
|
const int nQueueCount = pRenderQueue->GetCount();
|
||
|
for ( int i = 0; i < nQueueCount; ++i )
|
||
|
{
|
||
|
ReplayHandle_t hCurReplay;
|
||
|
int iCurPerformance;
|
||
|
|
||
|
if ( !pRenderQueue->GetEntryData( i, &hCurReplay, &iCurPerformance ) )
|
||
|
continue;
|
||
|
|
||
|
CReplay *pReplay = CL_GetReplayManager()->GetReplay( hCurReplay );
|
||
|
if ( !pReplay )
|
||
|
continue;
|
||
|
|
||
|
AddReplayForRender( pReplay, iCurPerformance );
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// Cache the title
|
||
|
CReplayMovieManager *pMovieManager = CL_GetMovieManager();
|
||
|
pMovieManager->CacheMovieTitle( params.m_wszTitle );
|
||
|
|
||
|
// Only render the specified replay
|
||
|
AddReplayForRender( CL_GetReplayManager()->GetReplay( params.m_hReplay ), params.m_iPerformance );
|
||
|
}
|
||
|
|
||
|
g_pReplayDemoPlayer->PlayNextReplay();
|
||
|
}
|
||
|
|
||
|
void CReplayMovieManager::RenderNextMovie()
|
||
|
{
|
||
|
m_bIsRendering = true;
|
||
|
|
||
|
g_pReplayDemoPlayer->PlayNextReplay();
|
||
|
}
|
||
|
|
||
|
void CReplayMovieManager::SetupHighDetailModels()
|
||
|
{
|
||
|
g_pEngine->Cbuf_AddText( "r_rootlod 0\n" );
|
||
|
}
|
||
|
|
||
|
void CReplayMovieManager::SetupHighDetailTextures()
|
||
|
{
|
||
|
g_pEngine->Cbuf_AddText( "mat_picmip -1\n" );
|
||
|
}
|
||
|
|
||
|
void CReplayMovieManager::SetupHighQualityAntialiasing()
|
||
|
{
|
||
|
int nNumSamples = 1;
|
||
|
int nQualityLevel = 0;
|
||
|
|
||
|
if ( materials->SupportsCSAAMode(8, 2) )
|
||
|
{
|
||
|
nNumSamples = 8;
|
||
|
nQualityLevel = 2;
|
||
|
}
|
||
|
else if ( materials->SupportsMSAAMode(8) )
|
||
|
{
|
||
|
nNumSamples = 8;
|
||
|
nQualityLevel = 0;
|
||
|
}
|
||
|
else if ( materials->SupportsCSAAMode(4, 4) )
|
||
|
{
|
||
|
nNumSamples = 4;
|
||
|
nQualityLevel = 4;
|
||
|
}
|
||
|
else if ( materials->SupportsCSAAMode(4, 2) )
|
||
|
{
|
||
|
nNumSamples = 4;
|
||
|
nQualityLevel = 2;
|
||
|
}
|
||
|
else if ( materials->SupportsMSAAMode(6) )
|
||
|
{
|
||
|
nNumSamples = 6;
|
||
|
nQualityLevel = 0;
|
||
|
}
|
||
|
else if ( materials->SupportsMSAAMode(4) )
|
||
|
{
|
||
|
nNumSamples = 4;
|
||
|
nQualityLevel = 0;
|
||
|
}
|
||
|
else if ( materials->SupportsMSAAMode(2) )
|
||
|
{
|
||
|
nNumSamples = 2;
|
||
|
nQualityLevel = 0;
|
||
|
}
|
||
|
|
||
|
g_pEngine->Cbuf_AddText( Replay_va( "mat_antialias %i\n", nNumSamples ) );
|
||
|
g_pEngine->Cbuf_AddText( Replay_va( "mat_aaquality %i\n", nQualityLevel ) );
|
||
|
}
|
||
|
|
||
|
void CReplayMovieManager::SetupHighQualityFiltering()
|
||
|
{
|
||
|
g_pEngine->Cbuf_AddText( "mat_forceaniso\n" );
|
||
|
}
|
||
|
|
||
|
void CReplayMovieManager::SetupHighQualityShadowDetail()
|
||
|
{
|
||
|
if ( materials->SupportsShadowDepthTextures() )
|
||
|
{
|
||
|
g_pEngine->Cbuf_AddText( "r_shadowrendertotexture 1\n" );
|
||
|
g_pEngine->Cbuf_AddText( "r_flashlightdepthtexture 1\n" );
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
g_pEngine->Cbuf_AddText( "r_shadowrendertotexture 1\n" );
|
||
|
g_pEngine->Cbuf_AddText( "r_flashlightdepthtexture 0\n" );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void CReplayMovieManager::SetupHighQualityHDR()
|
||
|
{
|
||
|
ConVarRef mat_dxlevel( "mat_dxlevel" );
|
||
|
if ( mat_dxlevel.GetInt() < 80 )
|
||
|
return;
|
||
|
|
||
|
g_pEngine->Cbuf_AddText( Replay_va( "mat_hdr_level %i\n", materials->SupportsHDRMode( HDR_TYPE_INTEGER ) ? 2 : 1 ) );
|
||
|
}
|
||
|
|
||
|
void CReplayMovieManager::SetupHighQualityWaterDetail()
|
||
|
{
|
||
|
#ifndef _X360
|
||
|
g_pEngine->Cbuf_AddText( "r_waterforceexpensive 1\n" );
|
||
|
#endif
|
||
|
g_pEngine->Cbuf_AddText( "r_waterforcereflectentities 1\n" );
|
||
|
}
|
||
|
|
||
|
void CReplayMovieManager::SetupMulticoreRender()
|
||
|
{
|
||
|
g_pEngine->Cbuf_AddText( "mat_queue_mode 0\n" );
|
||
|
}
|
||
|
|
||
|
void CReplayMovieManager::SetupHighQualityShaderDetail()
|
||
|
{
|
||
|
g_pEngine->Cbuf_AddText( "mat_reducefillrate 0\n" );
|
||
|
}
|
||
|
|
||
|
void CReplayMovieManager::SetupColorCorrection()
|
||
|
{
|
||
|
g_pEngine->Cbuf_AddText( "mat_colorcorrection 1\n" );
|
||
|
}
|
||
|
|
||
|
void CReplayMovieManager::SetupMotionBlur()
|
||
|
{
|
||
|
g_pEngine->Cbuf_AddText( "mat_motion_blur_enabled 1\n" );
|
||
|
}
|
||
|
|
||
|
void CReplayMovieManager::SetupVideo( RenderMovieParams_t const ¶ms )
|
||
|
{
|
||
|
// Get current video config
|
||
|
const MaterialSystem_Config_t &config = materials->GetCurrentConfigForVideoCard();
|
||
|
|
||
|
// Cache config
|
||
|
V_memcpy( m_pVidModeSettings, &config, sizeof( config ) );
|
||
|
|
||
|
// Cache quit when done
|
||
|
V_memcpy( m_pRenderMovieSettings, ¶ms, sizeof( params ) );
|
||
|
|
||
|
g_pEngine->Cbuf_Execute();
|
||
|
}
|
||
|
|
||
|
void CReplayMovieManager::CompleteRender( bool bSuccess, bool bShowBrowser )
|
||
|
{
|
||
|
// Store state
|
||
|
m_bIsRendering = false;
|
||
|
|
||
|
// Shutdown renderer
|
||
|
IReplayMovieRenderer *pRenderer = CL_GetMovieRenderer();
|
||
|
if ( pRenderer )
|
||
|
{
|
||
|
pRenderer->ShutdownRenderer();
|
||
|
}
|
||
|
|
||
|
if ( !bSuccess )
|
||
|
{
|
||
|
// Delete the movie from the manager
|
||
|
IReplayMovie *pMovie = CL_GetMovieManager()->GetPendingMovie();
|
||
|
if ( pMovie )
|
||
|
{
|
||
|
CL_GetMovieManager()->DeleteMovie( pMovie->GetMovieHandle() );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Clear render queue if we're done
|
||
|
if ( bShowBrowser )
|
||
|
{
|
||
|
CL_GetRenderQueue()->Clear();
|
||
|
}
|
||
|
|
||
|
// Notify UI that rendering is complete
|
||
|
g_pClient->OnRenderComplete( *m_pRenderMovieSettings, m_bRenderingCancelled, bSuccess, bShowBrowser );
|
||
|
|
||
|
// Quit now?
|
||
|
if ( m_pRenderMovieSettings->m_bQuitWhenFinished )
|
||
|
{
|
||
|
g_pEngine->HostState_Shutdown();
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
// Otherwise, play a sound.
|
||
|
g_pClient->PlaySound( "replay\\rendercomplete.wav" );
|
||
|
}
|
||
|
|
||
|
void CReplayMovieManager::CancelRender()
|
||
|
{
|
||
|
m_bRenderingCancelled = true;
|
||
|
CompleteRender( false, true );
|
||
|
g_pEngine->Host_Disconnect( false ); // CReplayDemoPlayer::StopPlayback() will be called
|
||
|
}
|
||
|
|
||
|
void CReplayMovieManager::GetMoviesAsQueryableItems( CUtlLinkedList< IQueryableReplayItem *, int > &lstMovies )
|
||
|
{
|
||
|
lstMovies.RemoveAll();
|
||
|
FOR_EACH_OBJ( this, i )
|
||
|
{
|
||
|
lstMovies.AddToHead( ToMovie( m_vecObjs[ i ] ) );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
const char *CReplayMovieManager::GetRenderDir() const
|
||
|
{
|
||
|
return Replay_va( "%s%s%c", g_pClientReplayContextInternal->GetBaseDir(), SUBDIR_RENDERED, CORRECT_PATH_SEPARATOR );
|
||
|
}
|
||
|
|
||
|
const char *CReplayMovieManager::GetRawExportDir() const
|
||
|
{
|
||
|
static CFmtStr s_fmtExportDir;
|
||
|
|
||
|
CReplayTime time;
|
||
|
time.InitDateAndTimeToNow();
|
||
|
|
||
|
int nDay, nMonth, nYear;
|
||
|
time.GetDate( nDay, nMonth, nYear );
|
||
|
|
||
|
int nHour, nMin, nSec;
|
||
|
time.GetTime( nHour, nMin, nSec );
|
||
|
|
||
|
s_fmtExportDir.sprintf(
|
||
|
"%smovie_%02i%02i%04i_%02i%02i%02i%c",
|
||
|
GetRenderDir(),
|
||
|
nMonth, nDay, nYear,
|
||
|
nHour, nMin, nSec,
|
||
|
CORRECT_PATH_SEPARATOR
|
||
|
);
|
||
|
|
||
|
return s_fmtExportDir.Access();
|
||
|
}
|
||
|
|
||
|
//----------------------------------------------------------------------------------------
|