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.

1031 lines
24 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. // $NoKeywords: $
  6. //=============================================================================//
  7. #include "client_pch.h"
  8. #include <vgui/ISystem.h>
  9. #include <vgui/ISurface.h>
  10. #include <vgui/IVGui.h>
  11. #include <KeyValues.h>
  12. #include <vgui_controls/BuildGroup.h>
  13. #include <vgui_controls/Tooltip.h>
  14. #include <vgui_controls/TextImage.h>
  15. #include <vgui_controls/CheckButton.h>
  16. #include <vgui_controls/Label.h>
  17. #include <vgui_controls/PropertySheet.h>
  18. #include <vgui_controls/FileOpenDialog.h>
  19. #include <vgui_controls/ProgressBar.h>
  20. #include <vgui_controls/Slider.h>
  21. #include <vgui_controls/Controls.h>
  22. #include <vgui_controls/TextEntry.h>
  23. #include <vgui/IInput.h>
  24. #include "cl_demoactionmanager.h"
  25. #include "filesystem.h"
  26. #include "filesystem_engine.h"
  27. #include "cl_demoeditorpanel.h"
  28. #include "cl_demosmootherpanel.h"
  29. #include "cl_demouipanel.h"
  30. #include "iprediction.h"
  31. // memdbgon must be the last include file in a .cpp file!!!
  32. #include "tier0/memdbgon.h"
  33. using namespace vgui;
  34. //////////////////////////////////////////////////////////////////////////
  35. //
  36. // CDemoUIPanel
  37. //
  38. //////////////////////////////////////////////////////////////////////////
  39. CDemoUIPanel *g_pDemoUI = NULL;
  40. void CDemoUIPanel::InstallDemoUI( vgui::Panel *parent )
  41. {
  42. if ( g_pDemoUI )
  43. return; // UI already created
  44. g_pDemoUI = new CDemoUIPanel( parent );
  45. Assert( g_pDemoUI );
  46. }
  47. //-----------------------------------------------------------------------------
  48. // Purpose: Basic help dialog
  49. //-----------------------------------------------------------------------------
  50. CDemoUIPanel::CDemoUIPanel( vgui::Panel *parent ) : vgui::Frame( parent, "DemoUIPanel")
  51. {
  52. SetTitle("Demo Playback", true);
  53. m_pPlayPauseResume = new vgui::Button( this, "DemoPlayPauseResume", "PlayPauseResume" );
  54. m_pStop = new vgui::Button( this, "DemoStop", "Stop" );
  55. m_pLoad = new vgui::Button( this, "DemoLoad", "Load..." );
  56. m_pEdit = new vgui::Button( this, "DemoEdit", "Edit..." );
  57. m_pSmooth = new vgui::Button( this, "DemoSmooth", "Smooth..." );
  58. m_pDriveCamera = new vgui::ToggleButton( this, "DemoDriveCamera", "Drive..." );
  59. m_pGoStart = new vgui::ToggleButton( this, "DemoGoStart", "Go Start" );
  60. m_pGoEnd = new vgui::Button( this, "DemoGoEnd", "Go End" );
  61. m_pFastForward = new vgui::Button( this, "DemoFastForward", "Fast Fwd" );
  62. m_pFastBackward = new vgui::Button( this, "DemoFastBackward", "Fast Bwd" );
  63. m_pPrevFrame = new vgui::Button( this, "DemoPrevFrame", "Prev Frame" );
  64. m_pNextFrame = new vgui::Button( this, "DemoNextFrame", "Next Frame" );
  65. m_pCurrentDemo = new vgui::Label( this, "DemoName", "" );
  66. m_pProgress = new vgui::ProgressBar( this, "DemoProgress" );
  67. m_pProgress->SetSegmentInfo( 2, 2 );
  68. m_pProgressLabelFrame = new vgui::Label( this, "DemoProgressLabelFrame", "" );
  69. m_pProgressLabelTime = new vgui::Label( this, "DemoProgressLabelTime", "" );
  70. m_pSpeedScale = new vgui::Slider( this, "DemoSpeedScale" );
  71. // 1000 == 10x %
  72. m_pSpeedScale->SetRange( 0, 1000 );
  73. m_pSpeedScale->SetValue( 500 );
  74. m_pSpeedScale->AddActionSignalTarget( this );
  75. m_pSpeedScaleLabel = new vgui::Label( this, "SpeedScale", "" );
  76. m_pGo = new vgui::Button( this, "DemoGo", "Go" );
  77. m_pGotoTick = new vgui::TextEntry( this, "DemoGoToTick" );
  78. vgui::ivgui()->AddTickSignal( GetVPanel(), 0 );
  79. LoadControlSettings("Resource\\DemoUIPanel.res");
  80. SetVisible( false );
  81. SetSizeable( false );
  82. SetMoveable( true );
  83. m_ViewOrigin.Init();
  84. m_ViewAngles.Init();
  85. memset( m_nOldCursor, 0, sizeof( m_nOldCursor ) );
  86. m_bInputActive = false;
  87. }
  88. //-----------------------------------------------------------------------------
  89. // Purpose:
  90. //-----------------------------------------------------------------------------
  91. CDemoUIPanel::~CDemoUIPanel()
  92. {
  93. }
  94. void CDemoUIPanel::GetCurrentView()
  95. {
  96. g_pClientSidePrediction->GetViewOrigin( m_ViewOrigin );
  97. g_pClientSidePrediction->GetViewAngles( m_ViewAngles );
  98. }
  99. bool CDemoUIPanel::IsInDriveMode()
  100. {
  101. return m_pDriveCamera->IsSelected();
  102. }
  103. void CDemoUIPanel::GetDriveViewPoint( Vector &origin, QAngle &angle )
  104. {
  105. origin = m_ViewOrigin;
  106. angle = m_ViewAngles;
  107. }
  108. void CDemoUIPanel::SetDriveViewPoint( Vector &origin, QAngle &angle )
  109. {
  110. m_ViewOrigin = origin;
  111. m_ViewAngles = angle;
  112. }
  113. void CDemoUIPanel::OnTick()
  114. {
  115. BaseClass::OnTick();
  116. if ( !IsVisible() )
  117. return;
  118. char curtime[32];
  119. char totaltime[32];
  120. int curtick = 0;
  121. int totalticks = 0;
  122. float fProgress = 0.0f;
  123. bool bIsPlaying = demoplayer->IsPlayingBack();
  124. // enable/disable all playback control buttons
  125. m_pPlayPauseResume->SetEnabled( bIsPlaying );
  126. m_pStop->SetEnabled( bIsPlaying );
  127. m_pNextFrame->SetEnabled( bIsPlaying );
  128. m_pFastForward->SetEnabled( bIsPlaying );
  129. m_pGoStart->SetEnabled( bIsPlaying );
  130. m_pGoEnd->SetEnabled( bIsPlaying );
  131. m_pGo->SetEnabled( bIsPlaying );
  132. bool bEnabled = bIsPlaying && false;
  133. // if player can go back in time
  134. m_pFastBackward->SetEnabled( bEnabled );
  135. m_pPrevFrame->SetEnabled( bEnabled );
  136. // set filename text
  137. m_pCurrentDemo->SetText( demoaction->GetCurrentDemoFile() );
  138. bool bHasDemoFile = demoaction->GetCurrentDemoFile()[0] != 0;
  139. // set play button text
  140. if ( bIsPlaying )
  141. {
  142. m_pPlayPauseResume->SetText( demoplayer->IsPlaybackPaused() ? "Resume" : "Pause" );
  143. }
  144. else
  145. {
  146. if ( bHasDemoFile )
  147. {
  148. m_pPlayPauseResume->SetText( "Play" );
  149. m_pPlayPauseResume->SetEnabled( true );
  150. }
  151. }
  152. if ( bIsPlaying )
  153. {
  154. curtick = demoplayer->GetPlaybackTick();
  155. totalticks = demoplayer->GetTotalTicks();
  156. fProgress = (float)curtick/(float)totalticks;
  157. fProgress = clamp( fProgress, 0.0f, 1.0f );
  158. }
  159. m_pProgress->SetProgress( fProgress );
  160. m_pProgressLabelFrame->SetText( va( "Tick: %i / %i", curtick, totalticks ) );
  161. Q_strncpy( curtime, COM_FormatSeconds( host_state.interval_per_tick * curtick ), 32 );
  162. Q_strncpy( totaltime, COM_FormatSeconds( host_state.interval_per_tick * totalticks ), 32 );
  163. m_pProgressLabelTime->SetText( va( "Time: %s / %s", curtime, totaltime ) );
  164. m_pFastForward->SetEnabled( demoplayer->IsPlayingBack() && !demoplayer->IsPlaybackPaused() );
  165. float fScale = demoplayer->GetPlaybackTimeScale();
  166. SetPlaybackScale( fScale ); // set slider
  167. m_pSpeedScaleLabel->SetText( va( "%.1f %%", fScale * 100.0f ) );
  168. }
  169. // Command issued
  170. void CDemoUIPanel::OnCommand(const char *command)
  171. {
  172. if ( !Q_strcasecmp( command, "stop" ) )
  173. {
  174. Cbuf_AddText( "disconnect\n" );
  175. }
  176. else if ( !Q_strcasecmp( command, "play" ) )
  177. {
  178. if ( !demoplayer->IsPlayingBack() )
  179. {
  180. char cmd[ 256 ];
  181. Q_snprintf( cmd, sizeof( cmd ), "playdemo %s\n", demoaction->GetCurrentDemoFile() );
  182. Cbuf_AddText( cmd );
  183. }
  184. else
  185. {
  186. Cbuf_AddText( !demoplayer->IsPlaybackPaused() ? "demo_pause\n" : "demo_resume\n" );
  187. }
  188. }
  189. else if ( !Q_strcasecmp( command, "load" ) )
  190. {
  191. OnLoad();
  192. }
  193. else if ( !Q_strcasecmp( command, "reload" ) )
  194. {
  195. Cbuf_AddText( "demo_gototick 0 0 1\n" );
  196. }
  197. else if ( !Q_strcasecmp( command, "edit" ) )
  198. {
  199. OnEdit();
  200. }
  201. else if ( !Q_strcasecmp( command, "smooth" ) )
  202. {
  203. OnSmooth();
  204. }
  205. else if ( !Q_strcasecmp( command, "nextframe" ) )
  206. {
  207. demoplayer->SkipToTick( 1, true, true );
  208. }
  209. else if ( !Q_strcasecmp( command, "gototick" ) )
  210. {
  211. char tick[ 32 ];
  212. m_pGotoTick->GetText( tick, sizeof( tick ) );
  213. char cmd[256];
  214. Q_snprintf( cmd, sizeof(cmd), "demo_gototick %s 0 1\n", tick );
  215. Cbuf_AddText( cmd );
  216. // demoplayer->PausePlayback( -1 );
  217. // demoplayer->SkipToTick( Q_atoi(tick), false );
  218. }
  219. else if ( !Q_strcasecmp( command, "drive" ) )
  220. {
  221. GetCurrentView();
  222. }
  223. else
  224. {
  225. BaseClass::OnCommand( command );
  226. }
  227. }
  228. void CDemoUIPanel::OnMessage(const KeyValues *params, VPANEL fromPanel)
  229. {
  230. BaseClass::OnMessage( params, fromPanel );
  231. if ( !Q_strcmp( "SliderMoved", params->GetName() ) )
  232. {
  233. demoplayer->SetPlaybackTimeScale( GetPlaybackScale() );
  234. }
  235. }
  236. void CDemoUIPanel::OnEdit()
  237. {
  238. if ( m_hDemoEditor != 0 )
  239. {
  240. m_hDemoEditor->SetVisible( true );
  241. m_hDemoEditor->MoveToFront();
  242. m_hDemoEditor->OnVDMChanged();
  243. return;
  244. }
  245. m_hDemoEditor = new CDemoEditorPanel( this );
  246. }
  247. void CDemoUIPanel::OnSmooth()
  248. {
  249. if ( m_hDemoSmoother != 0 )
  250. {
  251. m_hDemoSmoother->SetVisible( true );
  252. m_hDemoSmoother->MoveToFront();
  253. m_hDemoSmoother->OnVDMChanged();
  254. return;
  255. }
  256. m_hDemoSmoother = new CDemoSmootherPanel( this );
  257. }
  258. void CDemoUIPanel::OnLoad()
  259. {
  260. if ( !m_hFileOpenDialog.Get() )
  261. {
  262. m_hFileOpenDialog = new FileOpenDialog( this, "Choose .dem file", true );
  263. if ( m_hFileOpenDialog != 0 )
  264. {
  265. m_hFileOpenDialog->AddFilter("*.dem", "Demo Files (*.dem)", true);
  266. }
  267. }
  268. if ( m_hFileOpenDialog )
  269. {
  270. char startPath[ MAX_PATH ];
  271. Q_strncpy( startPath, com_gamedir, sizeof( startPath ) );
  272. Q_FixSlashes( startPath );
  273. m_hFileOpenDialog->SetStartDirectory( startPath );
  274. m_hFileOpenDialog->DoModal( false );
  275. }
  276. }
  277. void CDemoUIPanel::OnFileSelected( char const *fullpath )
  278. {
  279. if ( !fullpath || !fullpath[ 0 ] )
  280. return;
  281. char relativepath[ 512 ];
  282. g_pFileSystem->FullPathToRelativePath( fullpath, relativepath, sizeof( relativepath ) );
  283. char ext[ 10 ];
  284. Q_ExtractFileExtension( relativepath, ext, sizeof( ext ) );
  285. if ( Q_strcasecmp( ext, "dem" ) )
  286. {
  287. return;
  288. }
  289. // It's a dem file
  290. Cbuf_AddText( va( "playdemo %s\n", relativepath ) );
  291. Cbuf_AddText( "demopauseafterinit\n" );
  292. if ( m_hFileOpenDialog != 0 )
  293. {
  294. m_hFileOpenDialog->MarkForDeletion();
  295. }
  296. }
  297. //-----------------------------------------------------------------------------
  298. // Purpose:
  299. //-----------------------------------------------------------------------------
  300. void CDemoUIPanel::OnVDMChanged( void )
  301. {
  302. if ( m_hDemoEditor != 0 )
  303. {
  304. m_hDemoEditor->OnVDMChanged();
  305. }
  306. if ( m_hDemoSmoother != 0 )
  307. {
  308. m_hDemoSmoother->OnVDMChanged();
  309. }
  310. }
  311. //-----------------------------------------------------------------------------
  312. // Purpose:
  313. // Output : Returns true on success, false on failure.
  314. //-----------------------------------------------------------------------------
  315. bool CDemoUIPanel::IsHoldingFastForward( void )
  316. {
  317. if ( !m_pFastForward->IsVisible() )
  318. return false;
  319. if ( !m_pFastForward->IsEnabled() )
  320. return false;
  321. return m_pFastForward->IsSelected();
  322. }
  323. float CDemoUIPanel::GetPlaybackScale( void )
  324. {
  325. float scale = 1.0f;
  326. float curval = (float)m_pSpeedScale->GetValue() ;
  327. if ( curval <= 500.0f )
  328. {
  329. scale = curval / 500.0f;
  330. }
  331. else
  332. {
  333. scale = 1.0f + ( curval - 500.0f ) / 100.0f;
  334. }
  335. return scale;
  336. }
  337. void CDemoUIPanel::SetPlaybackScale( float scale )
  338. {
  339. if ( scale <= 0 )
  340. {
  341. m_pSpeedScale->SetValue( 0 ) ;
  342. }
  343. else if ( scale <= 1.0f )
  344. {
  345. m_pSpeedScale->SetValue( scale * 500.0f ) ;
  346. }
  347. else
  348. {
  349. m_pSpeedScale->SetValue( (scale - 1.0f) * 100.0f + 500.0f ) ;
  350. }
  351. }
  352. //-----------------------------------------------------------------------------
  353. // Purpose:
  354. // Input : frame -
  355. // elapsed -
  356. // info -
  357. // Output : Returns true on success, false on failure.
  358. //-----------------------------------------------------------------------------
  359. bool CDemoUIPanel::OverrideView( democmdinfo_t& info, int tick )
  360. {
  361. if ( IsInDriveMode() )
  362. {
  363. // manual camera override, overrides anyting
  364. HandleInput( vgui::input()->IsMouseDown( MOUSE_LEFT ) );
  365. info.viewOrigin = m_ViewOrigin;
  366. info.viewAngles = m_ViewAngles;
  367. info.localViewAngles = m_ViewAngles;
  368. return true;
  369. }
  370. if ( m_hDemoSmoother != 0 )
  371. {
  372. // demo smoother override
  373. if ( m_hDemoSmoother->OverrideView( info, tick ) )
  374. {
  375. m_ViewOrigin = info.GetViewOrigin();
  376. m_ViewAngles = info.GetViewAngles();
  377. return true;
  378. }
  379. }
  380. m_ViewOrigin = info.GetViewOrigin();
  381. m_ViewAngles = info.GetViewAngles();
  382. return false;
  383. }
  384. //-----------------------------------------------------------------------------
  385. // Purpose:
  386. // Input : frame -
  387. // elapsed -
  388. // smoothing -
  389. //-----------------------------------------------------------------------------
  390. void CDemoUIPanel::DrawDebuggingInfo()
  391. {
  392. if ( m_hDemoSmoother != 0 )
  393. {
  394. m_hDemoSmoother->DrawDebuggingInfo( 1, 1 ); // MOTODO
  395. }
  396. }
  397. //-----------------------------------------------------------------------------
  398. // Purpose:
  399. //-----------------------------------------------------------------------------
  400. void CDemoUIPanel::HandleInput( bool active )
  401. {
  402. if ( m_bInputActive ^ active )
  403. {
  404. if ( m_bInputActive && !active )
  405. {
  406. // Restore mouse
  407. vgui::input()->SetCursorPos( m_nOldCursor[0], m_nOldCursor[1] );
  408. }
  409. else
  410. {
  411. GetCurrentView();
  412. vgui::input()->GetCursorPos( m_nOldCursor[0], m_nOldCursor[1] );
  413. }
  414. }
  415. if ( active )
  416. {
  417. float f = 0.0f;
  418. float s = 0.0f;
  419. float u = 0.0f;
  420. bool shiftdown = vgui::input()->IsKeyDown( KEY_LSHIFT ) || vgui::input()->IsKeyDown( KEY_RSHIFT );
  421. float movespeed = shiftdown ? 40.0f : 400.0f;
  422. if ( vgui::input()->IsKeyDown( KEY_W ) )
  423. {
  424. f = movespeed * host_frametime;
  425. }
  426. if ( vgui::input()->IsKeyDown( KEY_S ) )
  427. {
  428. f = -movespeed * host_frametime;
  429. }
  430. if ( vgui::input()->IsKeyDown( KEY_A ) )
  431. {
  432. s = -movespeed * host_frametime;
  433. }
  434. if ( vgui::input()->IsKeyDown( KEY_D ) )
  435. {
  436. s = movespeed * host_frametime;
  437. }
  438. if ( vgui::input()->IsKeyDown( KEY_X ) )
  439. {
  440. u = movespeed * host_frametime;
  441. }
  442. if ( vgui::input()->IsKeyDown( KEY_Z ) )
  443. {
  444. u = -movespeed * host_frametime;
  445. }
  446. int mx, my;
  447. int dx, dy;
  448. vgui::input()->GetCursorPos( mx, my );
  449. dx = mx - m_nOldCursor[0];
  450. dy = my - m_nOldCursor[1];
  451. vgui::input()->SetCursorPos( m_nOldCursor[0], m_nOldCursor[1] );
  452. // Convert to pitch/yaw
  453. float pitch = (float)dy * 0.22f;
  454. float yaw = -(float)dx * 0.22;
  455. // Apply mouse
  456. m_ViewAngles.x += pitch;
  457. m_ViewAngles.x = clamp( m_ViewAngles.x, -89.0f, 89.0f );
  458. m_ViewAngles.y += yaw;
  459. if ( m_ViewAngles.y > 180.0f )
  460. {
  461. m_ViewAngles.y -= 360.0f;
  462. }
  463. else if ( m_ViewAngles.y < -180.0f )
  464. {
  465. m_ViewAngles.y += 360.0f;
  466. }
  467. // Now apply forward, side, up
  468. Vector fwd, side, up;
  469. AngleVectors( m_ViewAngles, &fwd, &side, &up );
  470. m_ViewOrigin += fwd * f;
  471. m_ViewOrigin += side * s;
  472. m_ViewOrigin += up * u;
  473. }
  474. m_bInputActive = active;
  475. }
  476. void DemoUI_f()
  477. {
  478. if ( !g_pDemoUI )
  479. return;
  480. if ( g_pDemoUI->IsVisible() )
  481. {
  482. g_pDemoUI->Close();
  483. }
  484. else
  485. {
  486. g_pDemoUI->Activate();
  487. }
  488. }
  489. static ConCommand demoui( "demoui", DemoUI_f, "Show/hide the demo player UI.", FCVAR_DONTRECORD );
  490. //////////////////////////////////////////////////////////////////////////
  491. //
  492. // CDemoUIPanel2
  493. //
  494. //////////////////////////////////////////////////////////////////////////
  495. CDemoUIPanel2 *g_pDemoUI2 = NULL;
  496. void CDemoUIPanel2::Install( vgui::Panel *pParentBkgnd, vgui::Panel *pParentFgnd, bool bPutToForeground )
  497. {
  498. if ( g_pDemoUI2 )
  499. return; // UI already created
  500. g_pDemoUI2 = new CDemoUIPanel2( pParentBkgnd, pParentFgnd, bPutToForeground );
  501. Assert( g_pDemoUI2 );
  502. }
  503. //-----------------------------------------------------------------------------
  504. // Purpose: Basic help dialog
  505. //-----------------------------------------------------------------------------
  506. CDemoUIPanel2::CDemoUIPanel2( vgui::Panel *pParentBkgnd, vgui::Panel *pParentFgnd, bool bPutToForeground ) :
  507. vgui::Frame( bPutToForeground ? pParentFgnd : pParentBkgnd, "DemoUIPanel2")
  508. {
  509. m_arrParents[0] = pParentBkgnd;
  510. m_arrParents[1] = pParentFgnd;
  511. m_bIsInForeground = bPutToForeground;
  512. SetTitle("Demo Playback - ", true);
  513. m_pPlayPauseResume = new vgui::Button( this, "DemoPlayPauseResume", "PlayPauseResume" );
  514. m_pStop = new vgui::Button( this, "DemoStop", "Stop" );
  515. m_pLoad = new vgui::Button( this, "DemoLoad", "Load..." );
  516. m_pGoStart = new vgui::ToggleButton( this, "DemoGoStart", "Go Start" );
  517. m_pGoEnd = new vgui::Button( this, "DemoGoEnd", "Go End" );
  518. m_pFastForward = new vgui::Button( this, "DemoFastForward", "Fast Fwd" );
  519. m_pFastBackward = new vgui::Button( this, "DemoFastBackward", "Fast Bwd" );
  520. m_pPrevFrame = new vgui::Button( this, "DemoPrevFrame", "Prev Frame" );
  521. m_pNextFrame = new vgui::Button( this, "DemoNextFrame", "Next Frame" );
  522. m_pProgress = new vgui::Slider( this, "DemoProgress" );
  523. m_pProgress->SetRange( 0, 0 );
  524. m_pProgress->SetValue( 0, false );
  525. m_pProgress->AddActionSignalTarget( this );
  526. m_pProgress->SetDragOnRepositionNob( true );
  527. m_pProgressLabelFrame = new vgui::Label( this, "DemoProgressLabelFrame", "" );
  528. m_pProgressLabelTime = new vgui::Label( this, "DemoProgressLabelTime", "" );
  529. m_pSpeedScale = new vgui::Slider( this, "DemoSpeedScale" );
  530. // 1000 == 10x %
  531. m_pSpeedScale->SetRange( 0, 1000 );
  532. m_pSpeedScale->SetValue( 500 );
  533. m_pSpeedScale->AddActionSignalTarget( this );
  534. m_pSpeedScale->SetDragOnRepositionNob( true );
  535. m_pSpeedScaleLabel = new vgui::Label( this, "SpeedScale", "" );
  536. vgui::ivgui()->AddTickSignal( GetVPanel(), 0 );
  537. LoadControlSettings("Resource\\DemoUIPanel2.res");
  538. SetVisible( false );
  539. SetSizeable( false );
  540. SetMoveable( true );
  541. memset( m_nOldCursor, 0, sizeof( m_nOldCursor ) );
  542. m_bInputActive = false;
  543. }
  544. CDemoUIPanel2::~CDemoUIPanel2()
  545. {
  546. }
  547. bool CDemoUIPanel2::IsInDriveMode()
  548. {
  549. return false;
  550. }
  551. void CDemoUIPanel2::GetDriveViewPoint( Vector &origin, QAngle &angle )
  552. {
  553. NULL;
  554. }
  555. void CDemoUIPanel2::SetDriveViewPoint( Vector &origin, QAngle &angle )
  556. {
  557. NULL;
  558. }
  559. void CDemoUIPanel2::OnTick()
  560. {
  561. BaseClass::OnTick();
  562. if ( !IsVisible() )
  563. return;
  564. char curtime[32];
  565. char totaltime[32];
  566. int curtick = 0;
  567. int totalticks = 0;
  568. float fProgress = 0.0f;
  569. bool bIsPlaying = demoplayer->IsPlayingBack();
  570. // enable/disable all playback control buttons
  571. m_pPlayPauseResume->SetEnabled( bIsPlaying );
  572. m_pStop->SetEnabled( bIsPlaying );
  573. m_pNextFrame->SetEnabled( bIsPlaying );
  574. m_pFastForward->SetEnabled( bIsPlaying );
  575. m_pGoStart->SetEnabled( bIsPlaying );
  576. m_pGoEnd->SetEnabled( bIsPlaying );
  577. bool bEnabled = bIsPlaying && false;
  578. // if player can go back in time
  579. m_pFastBackward->SetEnabled( bEnabled );
  580. m_pPrevFrame->SetEnabled( bEnabled );
  581. // set filename text
  582. SetTitle( va( "Demo Playback - %s", demoaction->GetCurrentDemoFile() ), true );
  583. bool bHasDemoFile = demoaction->GetCurrentDemoFile()[0] != 0;
  584. // set play button text
  585. if ( bIsPlaying )
  586. {
  587. m_pPlayPauseResume->SetText( demoplayer->IsPlaybackPaused() ? "Resume" : "Pause" );
  588. }
  589. else
  590. {
  591. if ( bHasDemoFile )
  592. {
  593. m_pPlayPauseResume->SetText( "Play" );
  594. m_pPlayPauseResume->SetEnabled( true );
  595. }
  596. }
  597. if ( bIsPlaying )
  598. {
  599. curtick = demoplayer->GetPlaybackTick();
  600. totalticks = demoplayer->GetTotalTicks();
  601. fProgress = (float)curtick/(float)totalticks;
  602. fProgress = clamp( fProgress, 0.0f, 1.0f );
  603. }
  604. if ( !m_pProgress->IsDragged() )
  605. {
  606. m_pProgress->SetRange( 0, max( totalticks, 0 ) );
  607. m_pProgress->SetValue( min( max( curtick, 0 ), totalticks ), false );
  608. m_pProgressLabelFrame->SetText( va( "Tick: %i / %i", curtick, totalticks ) );
  609. }
  610. else
  611. {
  612. m_pProgressLabelFrame->SetText( va( "Tick: %i / %i", m_pProgress->GetValue(), totalticks ) );
  613. }
  614. // Color in red when dragging back
  615. m_pProgressLabelFrame->SetFgColor( ( m_pProgress->GetValue() < curtick ) ? Color( 255, 0, 0, 255 ) : m_pProgressLabelTime->GetFgColor() );
  616. Q_strncpy( curtime, COM_FormatSeconds( host_state.interval_per_tick * curtick ), 32 );
  617. Q_strncpy( totaltime, COM_FormatSeconds( host_state.interval_per_tick * totalticks ), 32 );
  618. m_pProgressLabelTime->SetText( va( "Time: %s / %s", curtime, totaltime ) );
  619. m_pFastForward->SetEnabled( demoplayer->IsPlayingBack() && !demoplayer->IsPlaybackPaused() );
  620. float fScale = demoplayer->GetPlaybackTimeScale();
  621. SetPlaybackScale( fScale ); // set slider
  622. m_pSpeedScaleLabel->SetText( va( "%.1f %%", fScale * 100.0f ) );
  623. }
  624. // Command issued
  625. void CDemoUIPanel2::OnCommand(const char *command)
  626. {
  627. if ( !Q_strcasecmp( command, "stop" ) )
  628. {
  629. Cbuf_AddText( "disconnect\n" );
  630. }
  631. else if ( !Q_strcasecmp( command, "play" ) )
  632. {
  633. if ( !demoplayer->IsPlayingBack() )
  634. {
  635. demoplayer->StartPlayback( demoaction->GetCurrentDemoFile(), false );
  636. }
  637. else
  638. {
  639. demoplayer->IsPlaybackPaused() ? demoplayer->ResumePlayback() : demoplayer->PausePlayback( -1.f );
  640. }
  641. }
  642. else if ( !Q_strcasecmp( command, "load" ) )
  643. {
  644. OnLoad();
  645. }
  646. else if ( !Q_strcasecmp( command, "reload" ) )
  647. {
  648. Cbuf_AddText( "demo_gototick 0 0 1\n" );
  649. }
  650. else if ( !Q_strcasecmp( command, "nextframe" ) )
  651. {
  652. Cbuf_AddText( "demo_gototick 1 1 1\n" );
  653. }
  654. else
  655. {
  656. BaseClass::OnCommand( command );
  657. }
  658. }
  659. void CDemoUIPanel2::OnMessage(const KeyValues *params, VPANEL fromPanel)
  660. {
  661. BaseClass::OnMessage( params, fromPanel );
  662. //
  663. // Speed scale
  664. //
  665. if ( fromPanel == m_pSpeedScale->GetVPanel() )
  666. {
  667. if ( !Q_strcmp( "SliderMoved", params->GetName() ) )
  668. {
  669. demoplayer->SetPlaybackTimeScale( GetPlaybackScale() );
  670. }
  671. }
  672. //
  673. // Demo position
  674. //
  675. if ( fromPanel == m_pProgress->GetVPanel() )
  676. {
  677. if ( !Q_strcmp( "SliderDragStart", params->GetName() ) )
  678. {
  679. // Pause the demo when starting dragging around
  680. if ( demoplayer->IsPlayingBack() && !demoplayer->IsPlaybackPaused() )
  681. {
  682. demoplayer->PausePlayback( -1.f );
  683. }
  684. }
  685. if ( !Q_strcmp( "SliderDragEnd", params->GetName() ) )
  686. {
  687. int iNewTickPos = m_pProgress->GetValue();
  688. int iDemoCurrentTickPos = demoplayer->GetPlaybackTick();
  689. if ( iNewTickPos != iDemoCurrentTickPos )
  690. Cbuf_AddText( va( "demo_gototick %d 0 1\n", iNewTickPos ) );
  691. }
  692. if ( !Q_strcmp( "SliderMoved", params->GetName() ) )
  693. {
  694. NULL;
  695. }
  696. }
  697. }
  698. void CDemoUIPanel2::OnLoad()
  699. {
  700. if ( !m_hFileOpenDialog.Get() )
  701. {
  702. m_hFileOpenDialog = new FileOpenDialog( this, "Choose .dem file", true );
  703. if ( m_hFileOpenDialog != 0 )
  704. {
  705. m_hFileOpenDialog->AddFilter("*.dem", "Demo Files (*.dem)", true);
  706. }
  707. }
  708. if ( m_hFileOpenDialog )
  709. {
  710. char startPath[ MAX_PATH ];
  711. Q_strncpy( startPath, com_gamedir, sizeof( startPath ) );
  712. Q_FixSlashes( startPath );
  713. m_hFileOpenDialog->SetStartDirectory( startPath );
  714. m_hFileOpenDialog->DoModal( false );
  715. }
  716. }
  717. void CDemoUIPanel2::OnFileSelected( char const *fullpath )
  718. {
  719. if ( !fullpath || !fullpath[ 0 ] )
  720. return;
  721. char relativepath[ 512 ];
  722. g_pFileSystem->FullPathToRelativePath( fullpath, relativepath, sizeof( relativepath ) );
  723. char ext[ 10 ];
  724. Q_ExtractFileExtension( relativepath, ext, sizeof( ext ) );
  725. if ( Q_strcasecmp( ext, "dem" ) )
  726. {
  727. return;
  728. }
  729. // It's a dem file
  730. Cbuf_AddText( va( "playdemo %s\n", relativepath ) );
  731. Cbuf_AddText( "demopauseafterinit\n" );
  732. if ( m_hFileOpenDialog != 0 )
  733. {
  734. m_hFileOpenDialog->MarkForDeletion();
  735. }
  736. }
  737. void CDemoUIPanel2::OnVDMChanged( void )
  738. {
  739. NULL;
  740. }
  741. bool CDemoUIPanel2::IsHoldingFastForward( void )
  742. {
  743. if ( !m_pFastForward->IsVisible() )
  744. return false;
  745. if ( !m_pFastForward->IsEnabled() )
  746. return false;
  747. return m_pFastForward->IsSelected();
  748. }
  749. float CDemoUIPanel2::GetPlaybackScale( void )
  750. {
  751. float scale = 1.0f;
  752. float curval = (float)m_pSpeedScale->GetValue() ;
  753. if ( curval <= 500.0f )
  754. {
  755. scale = curval / 500.0f;
  756. }
  757. else
  758. {
  759. scale = 1.0f + ( curval - 500.0f ) / 100.0f;
  760. }
  761. return scale;
  762. }
  763. void CDemoUIPanel2::SetPlaybackScale( float scale )
  764. {
  765. if ( scale <= 0 )
  766. {
  767. m_pSpeedScale->SetValue( 0 ) ;
  768. }
  769. else if ( scale <= 1.0f )
  770. {
  771. m_pSpeedScale->SetValue( scale * 500.0f ) ;
  772. }
  773. else
  774. {
  775. m_pSpeedScale->SetValue( (scale - 1.0f) * 100.0f + 500.0f ) ;
  776. }
  777. }
  778. //-----------------------------------------------------------------------------
  779. // Purpose:
  780. // Input : frame -
  781. // elapsed -
  782. // info -
  783. // Output : Returns true on success, false on failure.
  784. //-----------------------------------------------------------------------------
  785. bool CDemoUIPanel2::OverrideView( democmdinfo_t& info, int tick )
  786. {
  787. return false;
  788. }
  789. void CDemoUIPanel2::DrawDebuggingInfo()
  790. {
  791. NULL;
  792. }
  793. //-----------------------------------------------------------------------------
  794. // Purpose:
  795. //-----------------------------------------------------------------------------
  796. void CDemoUIPanel2::HandleInput( bool active )
  797. {
  798. if ( m_bInputActive ^ active )
  799. {
  800. if ( m_bInputActive && !active )
  801. {
  802. // Restore mouse
  803. vgui::input()->SetCursorPos( m_nOldCursor[0], m_nOldCursor[1] );
  804. }
  805. else
  806. {
  807. vgui::input()->GetCursorPos( m_nOldCursor[0], m_nOldCursor[1] );
  808. }
  809. }
  810. m_bInputActive = active;
  811. }
  812. void CDemoUIPanel2::MakePanelForeground( bool bPutToForeground )
  813. {
  814. m_bIsInForeground = bPutToForeground;
  815. SetKeyBoardInputEnabled( m_bIsInForeground );
  816. SetMouseInputEnabled( m_bIsInForeground );
  817. SetParent( m_arrParents[ !!m_bIsInForeground ] );
  818. if ( m_bIsInForeground )
  819. {
  820. g_pDemoUI2->Activate();
  821. }
  822. }
  823. void DemoUI2_f()
  824. {
  825. if ( !g_pDemoUI2 )
  826. return;
  827. if ( g_pDemoUI2->IsVisible() )
  828. {
  829. g_pDemoUI2->Close();
  830. }
  831. else
  832. {
  833. g_pDemoUI2->MakePanelForeground( true );
  834. }
  835. }
  836. void DemoUI2_on()
  837. {
  838. if ( !g_pDemoUI2 )
  839. return;
  840. g_pDemoUI2->MakePanelForeground( true );
  841. }
  842. void DemoUI2_off()
  843. {
  844. if ( !g_pDemoUI2 )
  845. return;
  846. g_pDemoUI2->MakePanelForeground( false );
  847. }
  848. static ConCommand demoui2( "demoui2", DemoUI2_f, "Show/hide the advanced demo player UI (demoui2).", FCVAR_DONTRECORD );
  849. static ConCommand demoui2_on( "+demoui2", DemoUI2_on, "Bring the advanced demo player UI (demoui2) to foreground.", FCVAR_DONTRECORD );
  850. static ConCommand demoui2_off( "-demoui2", DemoUI2_off, "Send the advanced demo player UI (demoui2) to background.", FCVAR_DONTRECORD );