Team Fortress 2 Source Code as on 22/4/2020
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

639 lines
24 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. //=======================================================================================//
  4. #include "cbase.h"
  5. #if defined( REPLAY_ENABLED )
  6. #include "replaybrowserrenderdialog.h"
  7. #include "vgui_controls/TextImage.h"
  8. #include "vgui_controls/CheckButton.h"
  9. #include "vgui_controls/TextEntry.h"
  10. #include "vgui/IInput.h"
  11. #include "replay/genericclassbased_replay.h"
  12. #include "ienginevgui.h"
  13. #include "replayrenderoverlay.h"
  14. #include "replay/ireplaymanager.h"
  15. #include "replay/ireplaymoviemanager.h"
  16. #include "video/ivideoservices.h"
  17. #include "confirm_dialog.h"
  18. #include "replay/replayrenderer.h"
  19. #include "replay/performance.h"
  20. #include "replay/replayvideo.h"
  21. #include "replay_gamestats_shared.h"
  22. #include "econ/econ_controls.h"
  23. // memdbgon must be the last include file in a .cpp file!!!
  24. #include <tier0/memdbgon.h>
  25. //-----------------------------------------------------------------------------
  26. extern IReplayMovieManager *g_pReplayMovieManager;
  27. //-----------------------------------------------------------------------------
  28. ConVar replay_rendersetting_quitwhendone( "replay_rendersetting_quitwhendone", "0", FCVAR_CLIENTDLL | FCVAR_DONTRECORD, "Quit after rendering is completed.", true, 0.0f, true, 1.0f );
  29. 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 );
  30. ConVar replay_rendersetting_motionblurquality( "replay_rendersetting_motionblurquality", "0", FCVAR_CLIENTDLL | FCVAR_DONTRECORD, "Motion blur quality.", true, 0, true, MAX_MOTION_BLUR_QUALITY );
  31. ConVar replay_rendersetting_motionblurenabled( "replay_rendersetting_motionblurenabled", "1", FCVAR_CLIENTDLL | FCVAR_DONTRECORD, "Motion blur enabled/disabled.", true, 0.0f, true, 1.0f );
  32. 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 );
  33. ConVar replay_rendersetting_motionblur_can_toggle( "replay_rendersetting_motionblur_can_toggle", "0", FCVAR_CLIENTDLL | FCVAR_DONTRECORD, "" );
  34. ConVar replay_rendersetting_renderglow( "replay_rendersetting_renderglow", "0", FCVAR_CLIENTDLL | FCVAR_DONTRECORD | FCVAR_ARCHIVE, "Glow effect enabled/disabled.", true, 0.0f, true, 1.0f );
  35. //-----------------------------------------------------------------------------
  36. CReplayRenderDialog::CReplayRenderDialog( Panel *pParent, ReplayHandle_t hReplay, bool bSetQuit, int iPerformance )
  37. : BaseClass( pParent, "RenderDialog" ),
  38. m_bShowAdvancedOptions( false ),
  39. m_hReplay( hReplay ),
  40. m_bSetQuit( bSetQuit ),
  41. m_iPerformance( iPerformance ),
  42. m_pVideoModesCombo( NULL ),
  43. m_pCodecCombo( NULL ),
  44. m_pPlayVoiceCheck( NULL ),
  45. m_pShowAdvancedOptionsCheck( NULL ),
  46. m_pQuitWhenDoneCheck( NULL ),
  47. m_pExportRawCheck( NULL ),
  48. m_pTitleText( NULL ),
  49. m_pResolutionNoteLabel( NULL ),
  50. m_pEnterANameLabel( NULL ),
  51. m_pVideoModeLabel( NULL ),
  52. m_pCodecLabel( NULL ),
  53. m_pMotionBlurLabel( NULL ),
  54. m_pMotionBlurSlider( NULL ),
  55. m_pQualityLabel( NULL ),
  56. m_pQualitySlider( NULL ),
  57. m_pTitleLabel( NULL ),
  58. m_pCancelButton( NULL ),
  59. m_pRenderButton( NULL ),
  60. m_pBgPanel( NULL ),
  61. m_pMotionBlurCheck( NULL ),
  62. m_pQualityPresetLabel( NULL ),
  63. m_pQualityPresetCombo( NULL ),
  64. m_pSeparator( NULL ),
  65. m_pGlowEnabledCheck( NULL )
  66. {
  67. m_iQualityPreset = ReplayVideo_GetDefaultQualityPreset();
  68. }
  69. void CReplayRenderDialog::UpdateControlsValues()
  70. {
  71. ConVarRef replay_voice_during_playback( "replay_voice_during_playback" );
  72. m_pQuitWhenDoneCheck->SetSelected( replay_rendersetting_quitwhendone.GetBool() );
  73. m_pExportRawCheck->SetSelected( replay_rendersetting_exportraw.GetBool() );
  74. m_pShowAdvancedOptionsCheck->SetSelected( m_bShowAdvancedOptions );
  75. m_pMotionBlurSlider->SetValue( replay_rendersetting_motionblurquality.GetInt() );
  76. m_pMotionBlurCheck->SetSelected( replay_rendersetting_motionblurenabled.GetBool() );
  77. m_pQualitySlider->SetValue( replay_rendersetting_encodingquality.GetInt() / ReplayVideo_GetQualityInterval() );
  78. if ( m_pGlowEnabledCheck )
  79. {
  80. m_pGlowEnabledCheck->SetSelected( replay_rendersetting_renderglow.GetBool() );
  81. }
  82. if ( replay_voice_during_playback.IsValid() )
  83. {
  84. m_pPlayVoiceCheck->SetSelected( replay_voice_during_playback.GetBool() );
  85. }
  86. else
  87. {
  88. m_pPlayVoiceCheck->SetEnabled( false );
  89. }
  90. }
  91. void CReplayRenderDialog::AddControlToAutoLayout( Panel *pPanel, bool bAdvanced )
  92. {
  93. LayoutInfo_t *pNewLayoutInfo = new LayoutInfo_t;
  94. pNewLayoutInfo->pPanel = pPanel;
  95. // Use the positions from the .res file as relative positions for auto-layout
  96. pPanel->GetPos( pNewLayoutInfo->nOffsetX, pNewLayoutInfo->nOffsetY );
  97. pNewLayoutInfo->bAdvanced = bAdvanced;
  98. // Add to the list
  99. m_lstControls.AddToTail( pNewLayoutInfo );
  100. }
  101. void CReplayRenderDialog::SetValuesFromQualityPreset()
  102. {
  103. const ReplayQualityPreset_t &preset = ReplayVideo_GetQualityPreset( m_iQualityPreset );
  104. replay_rendersetting_motionblurquality.SetValue( preset.m_iMotionBlurQuality );
  105. replay_rendersetting_motionblurenabled.SetValue( (int)preset.m_bMotionBlurEnabled );
  106. replay_rendersetting_encodingquality.SetValue( preset.m_iQuality );
  107. for ( int i = 0; i < ReplayVideo_GetCodecCount(); ++i )
  108. {
  109. const ReplayCodec_t &CurCodec = ReplayVideo_GetCodec( i );
  110. if ( CurCodec.m_nCodecId == preset.m_nCodecId )
  111. {
  112. m_pCodecCombo->ActivateItem( m_pCodecCombo->GetItemIDFromRow( i ) );
  113. break;
  114. }
  115. }
  116. UpdateControlsValues();
  117. InvalidateLayout();
  118. }
  119. void CReplayRenderDialog::ApplySchemeSettings( vgui::IScheme *pScheme )
  120. {
  121. int i;
  122. // Link in TF scheme
  123. extern IEngineVGui *enginevgui;
  124. vgui::HScheme pTFScheme = vgui::scheme()->LoadSchemeFromFileEx( enginevgui->GetPanel( PANEL_CLIENTDLL ), "resource/ClientScheme.res", "ClientScheme" );
  125. SetScheme( pTFScheme );
  126. SetProportional( true );
  127. BaseClass::ApplySchemeSettings( vgui::scheme()->GetIScheme( pTFScheme ) );
  128. LoadControlSettings( "Resource/UI/replaybrowser/renderdialog.res", "GAME" );
  129. // retrieve controls
  130. m_pPlayVoiceCheck = dynamic_cast< CheckButton * >( FindChildByName( "PlayVoice" ) );
  131. m_pShowAdvancedOptionsCheck = dynamic_cast< CheckButton * >( FindChildByName( "ShowAdvancedOptions" ) );
  132. m_pQuitWhenDoneCheck = dynamic_cast< CheckButton * >( FindChildByName( "QuitWhenDone" ) );
  133. m_pExportRawCheck = dynamic_cast< CheckButton * >( FindChildByName( "ExportRaw" ) );
  134. m_pTitleText = dynamic_cast< TextEntry * >( FindChildByName( "TitleInput" ) );
  135. m_pResolutionNoteLabel = dynamic_cast< CExLabel * >( FindChildByName( "ResolutionNoteLabel" ) );
  136. m_pEnterANameLabel = dynamic_cast< CExLabel * >( FindChildByName( "EnterANameLabel" ) );
  137. m_pVideoModeLabel = dynamic_cast< CExLabel * >( FindChildByName( "VideoModeLabel" ) );
  138. m_pCodecLabel = dynamic_cast< CExLabel * >( FindChildByName( "CodecLabel" ) );
  139. m_pMotionBlurLabel = dynamic_cast< CExLabel * >( FindChildByName( "MotionBlurLabel" ) );
  140. m_pMotionBlurSlider = dynamic_cast< Slider * >( FindChildByName( "MotionBlurSlider" ) );
  141. m_pQualityLabel = dynamic_cast< CExLabel * >( FindChildByName( "QualityLabel" ) );
  142. m_pQualitySlider = dynamic_cast< Slider * >( FindChildByName( "QualitySlider" ) );
  143. m_pTitleLabel = dynamic_cast< CExLabel * >( FindChildByName( "TitleLabel" ) );
  144. m_pRenderButton = dynamic_cast< CExButton * >( FindChildByName( "RenderButton" ) );
  145. m_pCancelButton = dynamic_cast< CExButton * >( FindChildByName( "CancelButton" ) );
  146. m_pBgPanel = dynamic_cast< EditablePanel * >( FindChildByName( "BGPanel" ) );
  147. m_pMotionBlurCheck = dynamic_cast< CheckButton * >( FindChildByName( "MotionBlurEnabled" ) );
  148. m_pQualityPresetLabel = dynamic_cast< CExLabel * >( FindChildByName( "QualityPresetLabel" ) );
  149. m_pQualityPresetCombo = dynamic_cast< vgui::ComboBox * >( FindChildByName( "QualityPresetCombo" ) );
  150. m_pCodecCombo = dynamic_cast< vgui::ComboBox * >( FindChildByName( "CodecCombo" ) );
  151. m_pVideoModesCombo = dynamic_cast< vgui::ComboBox * >( FindChildByName( "VideoModeCombo" ) );
  152. m_pEstimateTimeLabel = dynamic_cast< CExLabel * >( FindChildByName( "EstimateTimeLabel" ) );
  153. m_pEstimateFileLabel = dynamic_cast< CExLabel * >( FindChildByName( "EstimateFileLabel" ) );
  154. m_pSeparator = FindChildByName( "SeparatorLine" );
  155. m_pGlowEnabledCheck = dynamic_cast< CheckButton * >( FindChildByName( "GlowEnabled" ) );
  156. m_pLockWarningLabel = dynamic_cast< CExLabel * >( FindChildByName( "LockWarningLabel" ) );
  157. #if defined( TF_CLIENT_DLL )
  158. if ( m_pBgPanel )
  159. {
  160. m_pBgPanel->SetPaintBackgroundType( 2 ); // Rounded.
  161. }
  162. #endif
  163. AddControlToAutoLayout( m_pTitleLabel, false );
  164. // The replay may be REPLAY_HANDLE_INVALID in the case that we are about to render all unrendered replays
  165. if ( m_hReplay != REPLAY_HANDLE_INVALID )
  166. {
  167. CGenericClassBasedReplay *pReplay = GetGenericClassBasedReplay( m_hReplay );
  168. m_pTitleText->SetText( pReplay->m_wszTitle );
  169. m_pTitleText->SetVisible( true );
  170. m_pTitleLabel->SetText( "#Replay_RenderReplay" );
  171. m_pEnterANameLabel->SetVisible( true );
  172. AddControlToAutoLayout( m_pEnterANameLabel, false );
  173. }
  174. else
  175. {
  176. m_pTitleLabel->SetText( "#Replay_RenderReplays" );
  177. }
  178. m_pTitleText->SelectAllOnFocusAlways( true );
  179. AddControlToAutoLayout( m_pTitleText, false );
  180. // Update controls based on preset
  181. SetValuesFromQualityPreset();
  182. // Set quit button if necessary
  183. if ( m_bSetQuit )
  184. {
  185. m_pQuitWhenDoneCheck->SetSelected( true );
  186. }
  187. m_pPlayVoiceCheck->SetProportional( false );
  188. m_pQuitWhenDoneCheck->SetProportional( false );
  189. m_pShowAdvancedOptionsCheck->SetProportional( false );
  190. m_pMotionBlurCheck->SetProportional( false );
  191. m_pMotionBlurSlider->InvalidateLayout( false, true ); // Without this, the range labels show up with "..." because of an invalid font in TextImage::ApplySchemeSettings().
  192. m_pExportRawCheck->SetProportional( false );
  193. m_pQualitySlider->InvalidateLayout( false, true ); // Without this, the range labels show up with "..." because of an invalid font in TextImage::ApplySchemeSettings().
  194. if ( m_pGlowEnabledCheck )
  195. {
  196. m_pGlowEnabledCheck->SetProportional( false );
  197. }
  198. // Fill in combo box with preset quality levels
  199. const int nQualityPresetCount = ReplayVideo_GetQualityPresetCount();
  200. m_pQualityPresetCombo->SetNumberOfEditLines( nQualityPresetCount );
  201. for ( i = 0; i < nQualityPresetCount; ++i )
  202. {
  203. const ReplayQualityPreset_t &CurQualityPreset = ReplayVideo_GetQualityPreset( i );
  204. m_pQualityPresetCombo->AddItem( CurQualityPreset.m_pName, NULL );
  205. m_pQualityPresetCombo->SetItemEnabled( i, true );
  206. }
  207. m_pQualityPresetCombo->ActivateItem( m_pQualityPresetCombo->GetItemIDFromRow( m_iQualityPreset ) );
  208. // Fill in combo box with video modes
  209. int nScreenW = ScreenWidth();
  210. int nScreenH = ScreenHeight();
  211. const int nVidModeCount = ReplayVideo_GetVideoModeCount();
  212. m_pVideoModesCombo->SetNumberOfEditLines( nVidModeCount );
  213. bool bAtLeastOneVideoModeAdded = false;
  214. bool bEnable = false;
  215. bool bSkipped = false;
  216. for ( i = 0; i < nVidModeCount; ++i )
  217. {
  218. // Only offer display modes less than the current window size
  219. const ReplayVideoMode_t &CurVideoMode = ReplayVideo_GetVideoMode( i );
  220. int nMw = CurVideoMode.m_nWidth;
  221. int nMh = CurVideoMode.m_nHeight;
  222. // Only display modes that fit in the current window
  223. bEnable = ( nMw <= nScreenW && nMh <= nScreenH );
  224. if (!bEnable)
  225. bSkipped = true;
  226. m_pVideoModesCombo->AddItem( CurVideoMode.m_pName, NULL );
  227. m_pVideoModesCombo->SetItemEnabled( i, bEnable );
  228. if (bEnable)
  229. bAtLeastOneVideoModeAdded = true;
  230. }
  231. if ( bAtLeastOneVideoModeAdded )
  232. {
  233. m_pVideoModesCombo->ActivateItem( m_pVideoModesCombo->GetItemIDFromRow( 0 ) );
  234. }
  235. // fill in the combo box with codecs
  236. const int nNumCodecs = ReplayVideo_GetCodecCount();
  237. m_pCodecCombo->SetNumberOfEditLines( nNumCodecs );
  238. for ( i = 0; i < nNumCodecs; ++i )
  239. {
  240. const ReplayCodec_t &CurCodec = ReplayVideo_GetCodec( i );
  241. m_pCodecCombo->AddItem( CurCodec.m_pName, NULL );
  242. m_pCodecCombo->SetItemEnabled( i, true );
  243. }
  244. m_pCodecCombo->ActivateItem( m_pCodecCombo->GetItemIDFromRow( 0 ) );
  245. // now layout
  246. // simplified options
  247. AddControlToAutoLayout( m_pVideoModeLabel, false );
  248. AddControlToAutoLayout( m_pVideoModesCombo, false );
  249. // Show the note about "not all resolutions are available?"
  250. if ( bSkipped && m_pResolutionNoteLabel )
  251. {
  252. m_pResolutionNoteLabel->SetVisible( true );
  253. AddControlToAutoLayout( m_pResolutionNoteLabel, false );
  254. }
  255. // other simplified options
  256. AddControlToAutoLayout( m_pQualityPresetLabel, false );
  257. AddControlToAutoLayout( m_pQualityPresetCombo, false );
  258. AddControlToAutoLayout( m_pEstimateTimeLabel, false );
  259. AddControlToAutoLayout( m_pEstimateFileLabel, false );
  260. AddControlToAutoLayout( m_pPlayVoiceCheck, false );
  261. AddControlToAutoLayout( m_pShowAdvancedOptionsCheck, false );
  262. AddControlToAutoLayout( m_pQuitWhenDoneCheck, false );
  263. AddControlToAutoLayout( m_pLockWarningLabel, false );
  264. // now advanced options
  265. AddControlToAutoLayout( m_pSeparator, true );
  266. AddControlToAutoLayout( m_pCodecLabel, true );
  267. AddControlToAutoLayout( m_pCodecCombo, true );
  268. if ( replay_rendersetting_motionblur_can_toggle.GetBool() )
  269. {
  270. AddControlToAutoLayout( m_pMotionBlurCheck, true );
  271. }
  272. else
  273. {
  274. m_pMotionBlurCheck->SetVisible( false );
  275. }
  276. AddControlToAutoLayout( m_pMotionBlurLabel, true );
  277. AddControlToAutoLayout( m_pMotionBlurSlider, true );
  278. AddControlToAutoLayout( m_pQualityLabel, true );
  279. AddControlToAutoLayout( m_pQualitySlider, true );
  280. AddControlToAutoLayout( m_pExportRawCheck, true );
  281. if ( m_pGlowEnabledCheck )
  282. {
  283. AddControlToAutoLayout( m_pGlowEnabledCheck, true );
  284. }
  285. // these buttons always show up
  286. AddControlToAutoLayout( m_pRenderButton, false );
  287. AddControlToAutoLayout( m_pCancelButton, false );
  288. }
  289. void CReplayRenderDialog::PerformLayout()
  290. {
  291. BaseClass::PerformLayout();
  292. m_pResolutionNoteLabel->SizeToContents(); // Get the proper height
  293. int nY = m_nStartY;
  294. Panel *pPrevPanel = NULL;
  295. int nLastCtrlHeight = 0;
  296. FOR_EACH_LL( m_lstControls, i )
  297. {
  298. LayoutInfo_t *pLayoutInfo = m_lstControls[ i ];
  299. Panel *pPanel = pLayoutInfo->pPanel;
  300. // should an advanced option be shown?
  301. if ( pLayoutInfo->bAdvanced )
  302. {
  303. if ( pPanel->IsVisible() != m_bShowAdvancedOptions )
  304. {
  305. pPanel->SetVisible( m_bShowAdvancedOptions );
  306. }
  307. }
  308. if ( !pPanel->IsVisible() )
  309. continue;
  310. if ( pPrevPanel && pLayoutInfo->nOffsetY >= 0 )
  311. {
  312. nY += pPrevPanel->GetTall() + pLayoutInfo->nOffsetY + m_nVerticalBuffer;
  313. }
  314. pPanel->SetPos( pLayoutInfo->nOffsetX ? pLayoutInfo->nOffsetX : m_nDefaultX, nY );
  315. pPrevPanel = pPanel;
  316. nLastCtrlHeight = pPanel->GetTall();
  317. }
  318. m_pBgPanel->SetTall( nY + nLastCtrlHeight + 2 * m_nVerticalBuffer );
  319. }
  320. void CReplayRenderDialog::Close()
  321. {
  322. SetVisible( false );
  323. MarkForDeletion();
  324. TFModalStack()->PopModal( this );
  325. }
  326. void CReplayRenderDialog::OnCommand( const char *pCommand )
  327. {
  328. if ( FStrEq( pCommand, "cancel" ) )
  329. {
  330. Close();
  331. }
  332. else if ( FStrEq( pCommand, "render" ) )
  333. {
  334. Close();
  335. Render();
  336. }
  337. else
  338. {
  339. engine->ClientCmd( const_cast<char *>( pCommand ) );
  340. }
  341. BaseClass::OnCommand( pCommand );
  342. }
  343. void CReplayRenderDialog::Render()
  344. {
  345. // Only complain about QuickTime if we aren't exporting raw TGA's/WAV
  346. if ( !m_pExportRawCheck->IsSelected() )
  347. {
  348. #ifndef USE_WEBM_FOR_REPLAY
  349. if ( !g_pVideo || !g_pVideo->IsVideoSystemAvailable( VideoSystem::QUICKTIME ) )
  350. {
  351. ShowMessageBox( "#Replay_QuicktimeTitle", "#Replay_NeedQuicktime", "#GameUI_OK" );
  352. return;
  353. }
  354. if ( g_pVideo->GetVideoSystemStatus( VideoSystem::QUICKTIME ) != VideoSystemStatus::OK )
  355. {
  356. if ( g_pVideo->GetVideoSystemStatus( VideoSystem::QUICKTIME ) == VideoSystemStatus::NOT_CURRENT_VERSION )
  357. {
  358. ShowMessageBox( "#Replay_QuicktimeTitle", "#Replay_NeedQuicktimeNewer", "#GameUI_OK" );
  359. return;
  360. }
  361. ShowMessageBox( "#Replay_QuicktimeTitle", "#Replay_Err_QT_FailedToLoad", "#GameUI_OK" );
  362. return;
  363. }
  364. #endif
  365. }
  366. // Update convars from settings
  367. const int nMotionBlurQuality = clamp( m_pMotionBlurSlider->GetValue(), 0, MAX_MOTION_BLUR_QUALITY );
  368. replay_rendersetting_quitwhendone.SetValue( (int)m_pQuitWhenDoneCheck->IsSelected() );
  369. replay_rendersetting_exportraw.SetValue( (int)m_pExportRawCheck->IsSelected() );
  370. replay_rendersetting_motionblurquality.SetValue( nMotionBlurQuality );
  371. replay_rendersetting_motionblurenabled.SetValue( replay_rendersetting_motionblur_can_toggle.GetBool() ? (int)m_pMotionBlurCheck->IsSelected() : 1 );
  372. replay_rendersetting_encodingquality.SetValue( clamp( m_pQualitySlider->GetValue() * ReplayVideo_GetQualityInterval(), 0, 100 ) );
  373. if ( m_pGlowEnabledCheck )
  374. {
  375. replay_rendersetting_renderglow.SetValue( m_pGlowEnabledCheck->IsSelected() );
  376. }
  377. ConVarRef replay_voice_during_playback( "replay_voice_during_playback" );
  378. if ( replay_voice_during_playback.IsValid() && m_pPlayVoiceCheck->IsEnabled() )
  379. {
  380. replay_voice_during_playback.SetValue( (int)m_pPlayVoiceCheck->IsSelected() );
  381. }
  382. // Setup parameters for render
  383. RenderMovieParams_t params;
  384. params.m_hReplay = m_hReplay;
  385. params.m_iPerformance = m_iPerformance; // Use performance passed in from details panel
  386. params.m_bQuitWhenFinished = m_pQuitWhenDoneCheck->IsSelected();
  387. params.m_bExportRaw = m_pExportRawCheck->IsSelected();
  388. m_pTitleText->GetText( params.m_wszTitle, sizeof( params.m_wszTitle ) );
  389. #ifdef USE_WEBM_FOR_REPLAY
  390. V_strcpy_safe( params.m_szExtension, ".webm" ); // Use .webm
  391. #else
  392. V_strcpy_safe( params.m_szExtension, ".mov" ); // Use .mov for Quicktime
  393. #endif
  394. const int iRes = m_pVideoModesCombo->GetActiveItem();
  395. const ReplayVideoMode_t &VideoMode = ReplayVideo_GetVideoMode( iRes );
  396. params.m_Settings.m_bMotionBlurEnabled = replay_rendersetting_motionblurenabled.GetBool();
  397. params.m_Settings.m_bAAEnabled = replay_rendersetting_motionblurenabled.GetBool();
  398. params.m_Settings.m_nMotionBlurQuality = nMotionBlurQuality;
  399. params.m_Settings.m_nWidth = VideoMode.m_nWidth;
  400. params.m_Settings.m_nHeight = VideoMode.m_nHeight;
  401. params.m_Settings.m_FPS.SetFPS( VideoMode.m_nBaseFPS, VideoMode.m_bNTSCRate );
  402. params.m_Settings.m_Codec = ReplayVideo_GetCodec( m_pCodecCombo->GetActiveItem() ).m_nCodecId;
  403. params.m_Settings.m_nEncodingQuality = replay_rendersetting_encodingquality.GetInt();
  404. params.m_Settings.m_bRaw = m_pExportRawCheck->IsSelected();
  405. // Calculate the framerate for the engine - for each engine frame, we need the # of motion blur timesteps,
  406. // x 2, since the shutter is open for nNumMotionBlurTimeSteps and closed for nNumMotionBlurTimeSteps,
  407. // with the engine frame centered in the shutter open state (ie when we're half way through the motion blur
  408. // timesteps). Antialiasing does not factor in here because it doesn't require extra frames - the AA jitter
  409. // is interwoven in with the motion sub-frames.
  410. const int nNumMotionBlurTimeSteps = ( params.m_Settings.m_bMotionBlurEnabled ) ? CReplayRenderer::GetNumMotionBlurTimeSteps( params.m_Settings.m_nMotionBlurQuality ) : 1;
  411. if ( params.m_Settings.m_bMotionBlurEnabled )
  412. {
  413. params.m_flEngineFps = 2 * nNumMotionBlurTimeSteps * params.m_Settings.m_FPS.GetFPS();
  414. }
  415. else
  416. {
  417. Assert( nNumMotionBlurTimeSteps == 1 );
  418. params.m_flEngineFps = params.m_Settings.m_FPS.GetFPS();
  419. }
  420. // Close the browser
  421. extern void ReplayUI_CloseReplayBrowser();
  422. ReplayUI_CloseReplayBrowser();
  423. // Hide the console
  424. engine->ExecuteClientCmd( "hideconsole" );
  425. // Stats tracking.
  426. GetReplayGameStatsHelper().SW_ReplayStats_WriteRenderDataStart( params, this );
  427. // Render the movie
  428. g_pReplayMovieManager->RenderMovie( params );
  429. }
  430. void CReplayRenderDialog::OnKeyCodeTyped( vgui::KeyCode code )
  431. {
  432. if( code == KEY_ENTER )
  433. {
  434. OnCommand( "render" );
  435. }
  436. else if ( code == KEY_ESCAPE )
  437. {
  438. MarkForDeletion();
  439. }
  440. else
  441. {
  442. BaseClass::OnKeyCodeTyped( code );
  443. }
  444. }
  445. void CReplayRenderDialog::OnThink()
  446. {
  447. if ( m_pEstimateTimeLabel == NULL || m_pEstimateFileLabel == NULL )
  448. return;
  449. // The replay may be NULL if this dialog is created by 'save all' from the quit confirmation dialog. In this
  450. // case, we don't want to a replay-specific time estimate anyway, so we can just early out here.
  451. CGenericClassBasedReplay *pReplay = ToGenericClassBasedReplay( g_pReplayManager->GetReplay( m_hReplay) );
  452. if ( !pReplay )
  453. return;
  454. const int nMotionBlurQuality = clamp( m_pMotionBlurSlider->GetValue(), 0, MAX_MOTION_BLUR_QUALITY );
  455. const int nCodecQuality = clamp( m_pQualitySlider->GetValue(), 0, ReplayVideo_GetQualityRange() );
  456. VideoEncodeCodec::EVideoEncodeCodec_t eCodec = ReplayVideo_GetCodec( m_pCodecCombo->GetActiveItem() ).m_nCodecId;
  457. // fFrameSize is the scale factor based on the size of the rendered frame.
  458. const int iRes = m_pVideoModesCombo->GetActiveItem();
  459. const ReplayVideoMode_t &VideoMode = ReplayVideo_GetVideoMode( iRes );
  460. float fFrameSize = (float)(VideoMode.m_nWidth * VideoMode.m_nHeight)/(float)(640*480);
  461. float flEstimatedFileSize = 0;
  462. float flEstimatedRenderTime_Min = 0;
  463. static float mjpegToMotionBlurMultiplierTable[] = { 2.0f, 3.0f, 5.5f, 12.0f };
  464. static float h264ToMotionBlurMultiplierTable[] = { 2.8f, 4.2f, 6.4f, 13.0f };
  465. static float webmToMotionBlurMultiplierTable[] = { 2.8f, 4.2f, 6.4f, 13.0f };
  466. static float mjpegToQualityMultiplierTable[] = { 620.0f, 736.0f, 1284.0f, 2115.0f, 3028.0f };
  467. static float h264ToQualityMultiplierTable[] = { 276.0f, 384.0f, 595.0f, 1026.0f, 1873.0f };
  468. static float webmToQualityMultiplierTable[] = { 125.0f, 250.0f, 312.0f, 673.0f, 1048.0f };
  469. switch ( eCodec )
  470. {
  471. case VideoEncodeCodec::WEBM_CODEC:
  472. flEstimatedFileSize = pReplay->m_flLength * webmToQualityMultiplierTable[nCodecQuality]*fFrameSize;
  473. flEstimatedRenderTime_Min = pReplay->m_flLength * webmToMotionBlurMultiplierTable[nMotionBlurQuality];
  474. break;
  475. case VideoEncodeCodec::H264_CODEC:
  476. flEstimatedFileSize = pReplay->m_flLength * h264ToQualityMultiplierTable[nCodecQuality];
  477. flEstimatedRenderTime_Min = pReplay->m_flLength * h264ToMotionBlurMultiplierTable[nMotionBlurQuality];
  478. break;
  479. case VideoEncodeCodec::MJPEG_A_CODEC:
  480. flEstimatedFileSize = pReplay->m_flLength * mjpegToQualityMultiplierTable[nCodecQuality];
  481. flEstimatedRenderTime_Min = pReplay->m_flLength * mjpegToMotionBlurMultiplierTable[nMotionBlurQuality];
  482. break;
  483. }
  484. float flEstimatedRenderTime_Max = flEstimatedRenderTime_Min * 3.0f;
  485. // @todo Tom Bui: if this goes into hours, we are in trouble...
  486. wchar_t wzFileSize[64];
  487. _snwprintf( wzFileSize, ARRAYSIZE( wzFileSize ), L"%d", (int)flEstimatedFileSize );
  488. wchar_t wzTimeMin[64];
  489. wchar_t wzTimeMax[64];
  490. g_pVGuiLocalize->ConvertANSIToUnicode( CReplayTime::FormatTimeString( flEstimatedRenderTime_Min ), wzTimeMin, sizeof( wzTimeMin ) );
  491. g_pVGuiLocalize->ConvertANSIToUnicode( CReplayTime::FormatTimeString( flEstimatedRenderTime_Max ), wzTimeMax, sizeof( wzTimeMax ) );
  492. wchar_t wzText[256] = L"";
  493. g_pVGuiLocalize->ConstructString_safe( wzText, g_pVGuiLocalize->Find( "#Replay_RenderEstimate_File" ), 1,
  494. wzFileSize,
  495. wzTimeMin,
  496. wzTimeMax );
  497. m_pEstimateFileLabel->SetText( wzText );
  498. g_pVGuiLocalize->ConstructString_safe( wzText, g_pVGuiLocalize->Find( "#Replay_RenderEstimate_Time" ), 2,
  499. wzTimeMin,
  500. wzTimeMax );
  501. m_pEstimateTimeLabel->SetText( wzText );
  502. }
  503. void CReplayRenderDialog::OnTextChanged( KeyValues *data )
  504. {
  505. Panel *pPanel = reinterpret_cast<vgui::Panel *>( data->GetPtr("panel") );
  506. vgui::ComboBox *pComboBox = dynamic_cast<vgui::ComboBox *>( pPanel );
  507. if ( pComboBox == m_pQualityPresetCombo )
  508. {
  509. m_iQualityPreset = m_pQualityPresetCombo->GetActiveItem();
  510. SetValuesFromQualityPreset();
  511. }
  512. }
  513. void CReplayRenderDialog::OnCheckButtonChecked( vgui::Panel *panel )
  514. {
  515. if ( panel == m_pShowAdvancedOptionsCheck )
  516. {
  517. m_bShowAdvancedOptions = m_pShowAdvancedOptionsCheck->IsSelected();
  518. InvalidateLayout( true, false );
  519. }
  520. }
  521. void CReplayRenderDialog::OnSetFocus()
  522. {
  523. m_pTitleText->RequestFocus();
  524. }
  525. void ReplayUI_ShowRenderDialog( Panel* pParent, ReplayHandle_t hReplay, bool bSetQuit, int iPerformance )
  526. {
  527. CReplayRenderDialog *pRenderDialog = vgui::SETUP_PANEL( new CReplayRenderDialog( pParent, hReplay, bSetQuit, iPerformance ) );
  528. pRenderDialog->SetVisible( true );
  529. pRenderDialog->MakePopup();
  530. pRenderDialog->MoveToFront();
  531. pRenderDialog->SetKeyBoardInputEnabled( true );
  532. pRenderDialog->SetMouseInputEnabled( true );
  533. TFModalStack()->PushModal( pRenderDialog );
  534. }
  535. #endif