Counter Strike : Global Offensive Source Code
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.

1168 lines
29 KiB

  1. //========= Copyright � 1996-2005, 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_pPrevFrame = new vgui::Button( this, "DemoPrevFrame", "Prev Frame" );
  62. m_pNextFrame = new vgui::Button( this, "DemoNextFrame", "Next Frame" );
  63. m_pProgress = new vgui::Slider( this, "DemoProgress" );
  64. m_pProgress->SetRange( 0, 0 );
  65. m_pProgress->SetValue( 0, false );
  66. m_pProgress->AddActionSignalTarget( this );
  67. m_pProgress->SetDragOnRepositionNob( true );
  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. // 0 = 0%, 500 = 100%, 1400 == 1000%
  72. m_pSpeedScale->SetRange( 0, 1400 );
  73. m_pSpeedScale->SetValue( 500 );
  74. m_pSpeedScale->AddActionSignalTarget( this );
  75. m_pSpeedScaleLabel = new vgui::Label( this, "SpeedScale", "" );
  76. vgui::ivgui()->AddTickSignal( GetVPanel(), 0 );
  77. SetVisible( false );
  78. SetSizeable( false );
  79. SetMoveable( true );
  80. m_ViewOrigin.Init();
  81. m_ViewAngles.Init();
  82. memset( m_nOldCursor, 0, sizeof( m_nOldCursor ) );
  83. m_bInputActive = false;
  84. }
  85. //-----------------------------------------------------------------------------
  86. // Purpose:
  87. //-----------------------------------------------------------------------------
  88. CDemoUIPanel::~CDemoUIPanel()
  89. {
  90. }
  91. void CDemoUIPanel::ApplySchemeSettings( vgui::IScheme *pScheme )
  92. {
  93. BaseClass::ApplySchemeSettings( pScheme );
  94. LoadControlSettings("Resource\\DemoUIPanel.res");
  95. InvalidateLayout();
  96. }
  97. void CDemoUIPanel::GetCurrentView()
  98. {
  99. g_pClientSidePrediction->GetViewOrigin( m_ViewOrigin );
  100. g_pClientSidePrediction->GetViewAngles( m_ViewAngles );
  101. }
  102. bool CDemoUIPanel::IsInDriveMode()
  103. {
  104. return m_pDriveCamera->IsSelected();
  105. }
  106. void CDemoUIPanel::GetDriveViewPoint( Vector &origin, QAngle &angle )
  107. {
  108. origin = m_ViewOrigin;
  109. angle = m_ViewAngles;
  110. }
  111. void CDemoUIPanel::SetDriveViewPoint( Vector &origin, QAngle &angle )
  112. {
  113. m_ViewOrigin = origin;
  114. m_ViewAngles = angle;
  115. }
  116. void CDemoUIPanel::OnTick()
  117. {
  118. BaseClass::OnTick();
  119. if ( !IsVisible() )
  120. return;
  121. char curtime[32];
  122. char totaltime[32];
  123. int curtick = 0;
  124. int totalticks = 0;
  125. float fProgress = 0.0f;
  126. bool bIsPlaying = demoplayer->IsPlayingBack();
  127. // enable/disable all playback control buttons
  128. m_pPlayPauseResume->SetEnabled( bIsPlaying );
  129. m_pStop->SetEnabled( bIsPlaying );
  130. m_pNextFrame->SetEnabled( bIsPlaying );
  131. m_pPrevFrame->SetEnabled( bIsPlaying );
  132. m_pGoStart->SetEnabled( bIsPlaying );
  133. m_pGoEnd->SetEnabled( bIsPlaying );
  134. // set filename text
  135. SetTitle( va( "Demo Playback - %s", demoaction->GetCurrentDemoFile() ), true );
  136. bool bHasDemoFile = demoaction->GetCurrentDemoFile()[0] != 0;
  137. // set play button text
  138. if ( bIsPlaying )
  139. {
  140. m_pPlayPauseResume->SetText( demoplayer->IsPlaybackPaused() ? "Resume" : "Pause" );
  141. }
  142. else
  143. {
  144. if ( bHasDemoFile )
  145. {
  146. m_pPlayPauseResume->SetText( "Play" );
  147. m_pPlayPauseResume->SetEnabled( true );
  148. }
  149. }
  150. if ( bIsPlaying )
  151. {
  152. curtick = demoplayer->GetPlaybackTick();
  153. totalticks = demoplayer->GetDemoStream()->GetTotalTicks();
  154. fProgress = (float)curtick/(float)totalticks;
  155. fProgress = clamp( fProgress, 0.0f, 1.0f );
  156. }
  157. if ( !m_pProgress->IsDragged() && !demoplayer->IsSkipping() )
  158. {
  159. m_pProgress->SetRange( 0, MAX( totalticks, 0 ) );
  160. m_pProgress->SetValue( MIN( MAX( curtick, 0 ), totalticks ), false );
  161. m_pProgressLabelFrame->SetText( va( "Tick: %i / %i", curtick, totalticks ) );
  162. }
  163. else
  164. {
  165. m_pProgressLabelFrame->SetText( va( "Tick: %i / %i", m_pProgress->GetValue(), totalticks ) );
  166. }
  167. //m_pProgress->SetProgress( fProgress );
  168. //m_pProgressLabelFrame->SetText( va( "Tick: %i / %i", curtick, totalticks ) );
  169. Q_strncpy( curtime, COM_FormatSeconds( host_state.interval_per_tick * curtick ), 32 );
  170. Q_strncpy( totaltime, COM_FormatSeconds( host_state.interval_per_tick * totalticks ), 32 );
  171. m_pProgressLabelTime->SetText( va( "Time: %s / %s", curtime, totaltime ) );
  172. float fScale = demoplayer->GetPlaybackTimeScale();
  173. SetPlaybackScale( fScale ); // set slider
  174. m_pSpeedScaleLabel->SetText( va( "%.1f %%", fScale * 100.0f ) );
  175. }
  176. bool GoToImportantTickHelper( const char *pszEventName, bool bForward )
  177. {
  178. const DemoImportantGameEvent_t *pGameEvent = demoplayer->GetImportantGameEvent( pszEventName );
  179. if ( pGameEvent )
  180. {
  181. // start at our current location plus any offset given from the Important game event data
  182. int nStartTick = demoplayer->GetPlaybackTick() + ( ( bForward ? pGameEvent->flSeekForwardOffset : -pGameEvent->flSeekBackwardOffset ) / host_state.interval_per_tick );
  183. int nImportantTickIndex = bForward ? demoplayer->FindNextImportantTick( nStartTick, pszEventName ) : demoplayer->FindPreviousImportantTick( nStartTick, pszEventName );
  184. if ( nImportantTickIndex != -1 )
  185. {
  186. const DemoImportantTick_t *pTick = demoplayer->GetImportantTick( nImportantTickIndex );
  187. if ( pTick )
  188. {
  189. demoplayer->SkipToImportantTick( pTick );
  190. return true;
  191. }
  192. }
  193. }
  194. return false;
  195. }
  196. // Command issued
  197. void CDemoUIPanel::OnCommand(const char *command)
  198. {
  199. if ( !Q_strcasecmp( command, "uireload" ) )
  200. {
  201. LoadControlSettings("Resource\\DemoUIPanel.res");
  202. InvalidateLayout(true);
  203. }
  204. else if ( !Q_strcasecmp( command, "gotostart" ) )
  205. {
  206. demoplayer->SkipToTick( 1, false, true );
  207. }
  208. else if ( !Q_strcasecmp( command, "prevframe" ) )
  209. {
  210. int nTicksPerFrame = ( demoplayer->GetDemoStream()->GetTicksPerFrame() ) + 1;
  211. demoplayer->SkipToTick( -nTicksPerFrame, true, true );
  212. }
  213. else if ( !Q_strcasecmp( command, "play" ) )
  214. {
  215. if ( !demoplayer->IsPlayingBack() )
  216. {
  217. char cmd[ 256 ];
  218. Q_snprintf( cmd, sizeof( cmd ), "playdemo %s\n", demoaction->GetCurrentDemoFile() );
  219. Cbuf_AddText( Cbuf_GetCurrentPlayer(), cmd );
  220. }
  221. else
  222. {
  223. Cbuf_AddText( Cbuf_GetCurrentPlayer(), !demoplayer->IsPlaybackPaused() ? "demo_pause\n" : "demo_resume\n" );
  224. }
  225. }
  226. else if ( !Q_strcasecmp( command, "nextframe" ) )
  227. {
  228. demoplayer->SkipToTick( 0, true, true );
  229. }
  230. else if ( !Q_strcasecmp( command, "gotoend" ) )
  231. {
  232. int nImportantTickIndex = demoplayer->FindPreviousImportantTick( demoplayer->GetDemoStream()->GetTotalTicks() + 1, "announce_phase_end" );
  233. if ( nImportantTickIndex != -1 )
  234. {
  235. const DemoImportantTick_t *pTick = demoplayer->GetImportantTick( nImportantTickIndex );
  236. if ( pTick )
  237. {
  238. demoplayer->SkipToTick( pTick->nPreviousTick, false, true );
  239. }
  240. }
  241. else
  242. {
  243. Msg( "No phase end in this demo.\n" );
  244. }
  245. }
  246. else if ( !Q_strcasecmp( command, "timescale_quarter" ) )
  247. {
  248. SetPlaybackScale( 0.25f );
  249. }
  250. else if ( !Q_strcasecmp( command, "timescale_half" ) )
  251. {
  252. SetPlaybackScale( 0.5f );
  253. }
  254. else if ( !Q_strcasecmp( command, "timescale_one" ) )
  255. {
  256. SetPlaybackScale( 1.0f );
  257. }
  258. else if ( !Q_strcasecmp( command, "timescale_2x" ) )
  259. {
  260. SetPlaybackScale( 2.0f );
  261. }
  262. else if ( !Q_strcasecmp( command, "timescale_4x" ) )
  263. {
  264. SetPlaybackScale( 4.0f );
  265. }
  266. else if ( !Q_strcasecmp( command, "nextround" ) )
  267. {
  268. if ( !GoToImportantTickHelper( "round_start", true ) )
  269. {
  270. Msg( "This is the last round in the demo.\n" );
  271. }
  272. }
  273. else if ( !Q_strcasecmp( command, "previousround" ) )
  274. {
  275. if ( !GoToImportantTickHelper( "round_start", false ) )
  276. {
  277. Msg( "This is the first round in the demo.\n" );
  278. }
  279. }
  280. else if ( !Q_strcasecmp( command, "nextdeath" ) )
  281. {
  282. if ( !GoToImportantTickHelper( "player_death", true ) )
  283. {
  284. Msg( "No more player deaths later in this demo.\n" );
  285. }
  286. }
  287. else if ( !Q_strcasecmp( command, "prevdeath" ) )
  288. {
  289. if ( !GoToImportantTickHelper( "player_death", false ) )
  290. {
  291. Msg( "No more player deaths earlier in this demo.\n" );
  292. }
  293. }
  294. else if ( !Q_strcasecmp( command, "load" ) )
  295. {
  296. OnLoad();
  297. }
  298. else if ( !Q_strcasecmp( command, "edit" ) )
  299. {
  300. OnEdit();
  301. }
  302. else if ( !Q_strcasecmp( command, "smooth" ) )
  303. {
  304. OnSmooth();
  305. }
  306. else if ( !Q_strcasecmp( command, "drive" ) )
  307. {
  308. GetCurrentView();
  309. }
  310. else if ( !Q_strcasecmp( command, "stop" ) )
  311. {
  312. Cbuf_AddText( Cbuf_GetCurrentPlayer(), "disconnect\n" );
  313. }
  314. else
  315. {
  316. BaseClass::OnCommand( command );
  317. }
  318. }
  319. void CDemoUIPanel::OnMessage(const KeyValues *params, VPANEL fromPanel)
  320. {
  321. BaseClass::OnMessage( params, fromPanel );
  322. //
  323. // Speed scale
  324. //
  325. if ( fromPanel == m_pSpeedScale->GetVPanel() )
  326. {
  327. if ( !Q_strcmp( "SliderMoved", params->GetName() ) )
  328. {
  329. demoplayer->SetPlaybackTimeScale( GetPlaybackScale() );
  330. }
  331. }
  332. //
  333. // Demo position
  334. //
  335. if ( fromPanel == m_pProgress->GetVPanel() )
  336. {
  337. if ( !Q_strcmp( "SliderDragStart", params->GetName() ) )
  338. {
  339. // Pause the demo when starting dragging around
  340. if ( demoplayer->IsPlayingBack() && !demoplayer->IsPlaybackPaused() )
  341. {
  342. demoplayer->PausePlayback( -1.f );
  343. }
  344. }
  345. if ( !Q_strcmp( "SliderDragEnd", params->GetName() ) )
  346. {
  347. if ( demoplayer->IsPlayingBack() )
  348. {
  349. int iNewTickPos = m_pProgress->GetValue();
  350. int iDemoCurrentTickPos = demoplayer->GetPlaybackTick();
  351. if ( iNewTickPos != iDemoCurrentTickPos )
  352. Cbuf_AddText( Cbuf_GetCurrentPlayer(), va( "demo_gototick %d 0 1\n", iNewTickPos ) );
  353. }
  354. }
  355. if ( !Q_strcmp( "SliderMoved", params->GetName() ) )
  356. {
  357. NULL;
  358. }
  359. }
  360. }
  361. void CDemoUIPanel::OnEdit()
  362. {
  363. if ( m_hDemoEditor != NULL )
  364. {
  365. m_hDemoEditor->SetVisible( true );
  366. m_hDemoEditor->MoveToFront();
  367. m_hDemoEditor->OnVDMChanged();
  368. return;
  369. }
  370. m_hDemoEditor = new CDemoEditorPanel( this );
  371. }
  372. void CDemoUIPanel::OnSmooth()
  373. {
  374. if ( m_hDemoSmoother != NULL )
  375. {
  376. m_hDemoSmoother->SetVisible( true );
  377. m_hDemoSmoother->MoveToFront();
  378. m_hDemoSmoother->OnVDMChanged();
  379. return;
  380. }
  381. m_hDemoSmoother = new CDemoSmootherPanel( this );
  382. }
  383. void CDemoUIPanel::OnLoad()
  384. {
  385. if ( !m_hFileOpenDialog.Get() )
  386. {
  387. m_hFileOpenDialog = new FileOpenDialog( this, "Choose .dem file", true );
  388. if ( m_hFileOpenDialog != NULL )
  389. {
  390. m_hFileOpenDialog->SetDeleteSelfOnClose( false );
  391. m_hFileOpenDialog->AddFilter("*.dem", "Demo Files (*.dem)", true);
  392. }
  393. }
  394. if ( m_hFileOpenDialog )
  395. {
  396. char startPath[ MAX_PATH ];
  397. Q_strncpy( startPath, com_gamedir, sizeof( startPath ) );
  398. Q_FixSlashes( startPath );
  399. m_hFileOpenDialog->SetStartDirectory( startPath );
  400. m_hFileOpenDialog->DoModal( false );
  401. }
  402. }
  403. void CDemoUIPanel::OnFileSelected( char const *fullpath )
  404. {
  405. if ( !fullpath || !fullpath[ 0 ] )
  406. return;
  407. char relativepath[ 512 ];
  408. g_pFileSystem->FullPathToRelativePath( fullpath, relativepath, sizeof( relativepath ) );
  409. char ext[ 10 ];
  410. Q_ExtractFileExtension( relativepath, ext, sizeof( ext ) );
  411. if ( Q_strcasecmp( ext, "dem" ) )
  412. {
  413. return;
  414. }
  415. // It's a dem file
  416. Cbuf_AddText( Cbuf_GetCurrentPlayer(), va( "playdemo %s\n", relativepath ) );
  417. Cbuf_AddText( Cbuf_GetCurrentPlayer(), "demopauseafterinit\n" );
  418. if ( m_hFileOpenDialog != NULL )
  419. {
  420. m_hFileOpenDialog->MarkForDeletion();
  421. }
  422. }
  423. //-----------------------------------------------------------------------------
  424. // Purpose:
  425. //-----------------------------------------------------------------------------
  426. void CDemoUIPanel::OnVDMChanged( void )
  427. {
  428. if ( m_hDemoEditor != NULL )
  429. {
  430. m_hDemoEditor->OnVDMChanged();
  431. }
  432. if ( m_hDemoSmoother != NULL )
  433. {
  434. m_hDemoSmoother->OnVDMChanged();
  435. }
  436. }
  437. float CDemoUIPanel::GetPlaybackScale( void )
  438. {
  439. float scale = 1.0f;
  440. float curval = (float)m_pSpeedScale->GetValue() ;
  441. if ( curval <= 500.0f )
  442. {
  443. scale = curval / 500.0f;
  444. }
  445. else
  446. {
  447. scale = 1.0f + ( curval - 500.0f ) / 100.0f;
  448. }
  449. return scale;
  450. }
  451. void CDemoUIPanel::SetPlaybackScale( float scale )
  452. {
  453. if ( scale <= 0 )
  454. {
  455. m_pSpeedScale->SetValue( 0 ) ;
  456. }
  457. else if ( scale <= 1.0f )
  458. {
  459. m_pSpeedScale->SetValue( scale * 500.0f ) ;
  460. }
  461. else
  462. {
  463. m_pSpeedScale->SetValue( (scale - 1.0f) * 100.0f + 500.0f ) ;
  464. }
  465. }
  466. //-----------------------------------------------------------------------------
  467. // Purpose:
  468. // Input : frame -
  469. // elapsed -
  470. // info -
  471. // Output : Returns true on success, false on failure.
  472. //-----------------------------------------------------------------------------
  473. bool CDemoUIPanel::OverrideView( democmdinfo_t& info, int tick )
  474. {
  475. ASSERT_LOCAL_PLAYER_RESOLVABLE();
  476. int nSlot = GET_ACTIVE_SPLITSCREEN_SLOT();
  477. if ( IsInDriveMode() )
  478. {
  479. // manual camera override, overrides anyting
  480. HandleInput( vgui::input()->IsMouseDown( MOUSE_LEFT ) );
  481. info.u[ nSlot ].viewOrigin = m_ViewOrigin;
  482. info.u[ nSlot ].viewAngles = m_ViewAngles;
  483. info.u[ nSlot ].localViewAngles = m_ViewAngles;
  484. return true;
  485. }
  486. if ( m_hDemoSmoother != NULL )
  487. {
  488. // demo smoother override
  489. if ( m_hDemoSmoother->OverrideView( info, tick ) )
  490. {
  491. m_ViewOrigin = info.u[ nSlot ].GetViewOrigin();
  492. m_ViewAngles = info.u[ nSlot ].GetViewAngles();
  493. return true;
  494. }
  495. }
  496. m_ViewOrigin = info.u[ nSlot ].GetViewOrigin();
  497. m_ViewAngles = info.u[ nSlot ].GetViewAngles();
  498. return false;
  499. }
  500. //-----------------------------------------------------------------------------
  501. // Purpose:
  502. // Input : frame -
  503. // elapsed -
  504. // smoothing -
  505. //-----------------------------------------------------------------------------
  506. void CDemoUIPanel::DrawDebuggingInfo()
  507. {
  508. if ( m_hDemoSmoother != NULL )
  509. {
  510. m_hDemoSmoother->DrawDebuggingInfo( 1, 1 ); // MOTODO
  511. }
  512. }
  513. //-----------------------------------------------------------------------------
  514. // Purpose:
  515. //-----------------------------------------------------------------------------
  516. void CDemoUIPanel::HandleInput( bool active )
  517. {
  518. if ( m_bInputActive ^ active )
  519. {
  520. if ( m_bInputActive && !active )
  521. {
  522. // Restore mouse
  523. vgui::input()->SetCursorPos( m_nOldCursor[0], m_nOldCursor[1] );
  524. }
  525. else
  526. {
  527. GetCurrentView();
  528. vgui::input()->GetCursorPos( m_nOldCursor[0], m_nOldCursor[1] );
  529. }
  530. }
  531. if ( active )
  532. {
  533. float f = 0.0f;
  534. float s = 0.0f;
  535. float u = 0.0f;
  536. bool shiftdown = vgui::input()->IsKeyDown( KEY_LSHIFT ) || vgui::input()->IsKeyDown( KEY_RSHIFT );
  537. float movespeed = shiftdown ? 40.0f : 400.0f;
  538. if ( vgui::input()->IsKeyDown( KEY_W ) )
  539. {
  540. f = movespeed * host_frametime;
  541. }
  542. if ( vgui::input()->IsKeyDown( KEY_S ) )
  543. {
  544. f = -movespeed * host_frametime;
  545. }
  546. if ( vgui::input()->IsKeyDown( KEY_A ) )
  547. {
  548. s = -movespeed * host_frametime;
  549. }
  550. if ( vgui::input()->IsKeyDown( KEY_D ) )
  551. {
  552. s = movespeed * host_frametime;
  553. }
  554. if ( vgui::input()->IsKeyDown( KEY_X ) )
  555. {
  556. u = movespeed * host_frametime;
  557. }
  558. if ( vgui::input()->IsKeyDown( KEY_Z ) )
  559. {
  560. u = -movespeed * host_frametime;
  561. }
  562. int mx, my;
  563. int dx, dy;
  564. vgui::input()->GetCursorPos( mx, my );
  565. dx = mx - m_nOldCursor[0];
  566. dy = my - m_nOldCursor[1];
  567. vgui::input()->SetCursorPos( m_nOldCursor[0], m_nOldCursor[1] );
  568. // Convert to pitch/yaw
  569. float pitch = (float)dy * 0.22f;
  570. float yaw = -(float)dx * 0.22;
  571. // Apply mouse
  572. m_ViewAngles.x += pitch;
  573. m_ViewAngles.x = clamp( m_ViewAngles.x, -89.0f, 89.0f );
  574. m_ViewAngles.y += yaw;
  575. if ( m_ViewAngles.y > 180.0f )
  576. {
  577. m_ViewAngles.y -= 360.0f;
  578. }
  579. else if ( m_ViewAngles.y < -180.0f )
  580. {
  581. m_ViewAngles.y += 360.0f;
  582. }
  583. // Now apply forward, side, up
  584. Vector fwd, side, up;
  585. AngleVectors( m_ViewAngles, &fwd, &side, &up );
  586. m_ViewOrigin += fwd * f;
  587. m_ViewOrigin += side * s;
  588. m_ViewOrigin += up * u;
  589. }
  590. m_bInputActive = active;
  591. }
  592. void DemoUI_f()
  593. {
  594. if ( !g_pDemoUI )
  595. return;
  596. if ( g_pDemoUI->IsVisible() )
  597. {
  598. g_pDemoUI->Close();
  599. }
  600. else
  601. {
  602. g_pDemoUI->Activate();
  603. }
  604. }
  605. static ConCommand demoui( "demoui", DemoUI_f, "Show/hide the demo player UI.", FCVAR_DONTRECORD );
  606. #if 0
  607. //////////////////////////////////////////////////////////////////////////
  608. //
  609. // CDemoUIPanel2
  610. //
  611. //////////////////////////////////////////////////////////////////////////
  612. CDemoUIPanel2 *g_pDemoUI2 = NULL;
  613. void CDemoUIPanel2::Install( vgui::Panel *pParentBkgnd, vgui::Panel *pParentFgnd, bool bPutToForeground )
  614. {
  615. if ( g_pDemoUI2 )
  616. return; // UI already created
  617. g_pDemoUI2 = new CDemoUIPanel2( pParentBkgnd, pParentFgnd, bPutToForeground );
  618. Assert( g_pDemoUI2 );
  619. }
  620. //-----------------------------------------------------------------------------
  621. // Purpose: Basic help dialog
  622. //-----------------------------------------------------------------------------
  623. CDemoUIPanel2::CDemoUIPanel2( vgui::Panel *pParentBkgnd, vgui::Panel *pParentFgnd, bool bPutToForeground ) :
  624. vgui::Frame( bPutToForeground ? pParentFgnd : pParentBkgnd, "DemoUIPanel2")
  625. {
  626. m_arrParents[0] = pParentBkgnd;
  627. m_arrParents[1] = pParentFgnd;
  628. m_bIsInForeground = bPutToForeground;
  629. SetTitle("Demo Playback - ", true);
  630. m_pPlayPauseResume = new vgui::Button( this, "DemoPlayPauseResume", "PlayPauseResume" );
  631. m_pStop = new vgui::Button( this, "DemoStop", "Stop" );
  632. m_pLoad = new vgui::Button( this, "DemoLoad", "Load..." );
  633. m_pGoStart = new vgui::ToggleButton( this, "DemoGoStart", "Go Start" );
  634. m_pGoEnd = new vgui::Button( this, "DemoGoEnd", "Go End" );
  635. m_pPrevFrame = new vgui::Button( this, "DemoPrevFrame", "Prev Frame" );
  636. m_pNextFrame = new vgui::Button( this, "DemoNextFrame", "Next Frame" );
  637. m_pProgress = new vgui::Slider( this, "DemoProgress" );
  638. m_pProgress->SetRange( 0, 0 );
  639. m_pProgress->SetValue( 0, false );
  640. m_pProgress->AddActionSignalTarget( this );
  641. m_pProgress->SetDragOnRepositionNob( true );
  642. m_pProgressLabelFrame = new vgui::Label( this, "DemoProgressLabelFrame", "" );
  643. m_pProgressLabelTime = new vgui::Label( this, "DemoProgressLabelTime", "" );
  644. m_pSpeedScale = new vgui::Slider( this, "DemoSpeedScale" );
  645. // 0 = 0%, 500 = 100%, 1400 == 1000%
  646. m_pSpeedScale->SetRange( 0, 1400 );
  647. m_pSpeedScale->SetValue( 500 );
  648. m_pSpeedScale->AddActionSignalTarget( this );
  649. m_pSpeedScale->SetDragOnRepositionNob( true );
  650. m_pSpeedScaleLabel = new vgui::Label( this, "SpeedScale", "" );
  651. vgui::ivgui()->AddTickSignal( GetVPanel(), 0 );
  652. SetVisible( false );
  653. SetSizeable( false );
  654. SetMoveable( true );
  655. memset( m_nOldCursor, 0, sizeof( m_nOldCursor ) );
  656. m_bInputActive = false;
  657. }
  658. CDemoUIPanel2::~CDemoUIPanel2()
  659. {
  660. }
  661. void CDemoUIPanel2::ApplySchemeSettings( vgui::IScheme *pScheme )
  662. {
  663. BaseClass::ApplySchemeSettings( pScheme );
  664. LoadControlSettings("Resource\\DemoUIPanel2.res");
  665. InvalidateLayout();
  666. }
  667. bool CDemoUIPanel2::IsInDriveMode()
  668. {
  669. return false;
  670. }
  671. void CDemoUIPanel2::GetDriveViewPoint( Vector &origin, QAngle &angle )
  672. {
  673. NULL;
  674. }
  675. void CDemoUIPanel2::SetDriveViewPoint( Vector &origin, QAngle &angle )
  676. {
  677. NULL;
  678. }
  679. void CDemoUIPanel2::OnTick()
  680. {
  681. BaseClass::OnTick();
  682. if ( !IsVisible() )
  683. return;
  684. char curtime[32];
  685. char totaltime[32];
  686. int curtick = 0;
  687. int totalticks = 0;
  688. float fProgress = 0.0f;
  689. bool bIsPlaying = demoplayer->IsPlayingBack();
  690. // enable/disable all playback control buttons
  691. m_pPlayPauseResume->SetEnabled( bIsPlaying );
  692. m_pStop->SetEnabled( bIsPlaying );
  693. m_pNextFrame->SetEnabled( bIsPlaying );
  694. m_pPrevFrame->SetEnabled( bIsPlaying );
  695. m_pGoStart->SetEnabled( bIsPlaying );
  696. m_pGoEnd->SetEnabled( bIsPlaying );
  697. // set filename text
  698. SetTitle( va( "Demo Playback - %s", demoaction->GetCurrentDemoFile() ), true );
  699. bool bHasDemoFile = demoaction->GetCurrentDemoFile()[0] != 0;
  700. // set play button text
  701. if ( bIsPlaying )
  702. {
  703. m_pPlayPauseResume->SetText( demoplayer->IsPlaybackPaused() ? "Resume" : "Pause" );
  704. }
  705. else
  706. {
  707. if ( bHasDemoFile )
  708. {
  709. m_pPlayPauseResume->SetText( "Play" );
  710. m_pPlayPauseResume->SetEnabled( true );
  711. }
  712. }
  713. if ( bIsPlaying )
  714. {
  715. curtick = demoplayer->GetPlaybackTick();
  716. totalticks = demoplayer->GetDemoStream()->GetTotalTicks();
  717. fProgress = (float)curtick/(float)totalticks;
  718. fProgress = clamp( fProgress, 0.0f, 1.0f );
  719. }
  720. if ( !m_pProgress->IsDragged() )
  721. {
  722. m_pProgress->SetRange( 0, MAX( totalticks, 0 ) );
  723. m_pProgress->SetValue( MIN( MAX( curtick, 0 ), totalticks ), false );
  724. m_pProgressLabelFrame->SetText( va( "Tick: %i / %i", curtick, totalticks ) );
  725. }
  726. else
  727. {
  728. m_pProgressLabelFrame->SetText( va( "Tick: %i / %i", m_pProgress->GetValue(), totalticks ) );
  729. }
  730. // Color in red when dragging back
  731. m_pProgressLabelFrame->SetFgColor( ( m_pProgress->GetValue() < curtick ) ? Color( 255, 0, 0, 255 ) : m_pProgressLabelTime->GetFgColor() );
  732. Q_strncpy( curtime, COM_FormatSeconds( host_state.interval_per_tick * curtick ), 32 );
  733. Q_strncpy( totaltime, COM_FormatSeconds( host_state.interval_per_tick * totalticks ), 32 );
  734. m_pProgressLabelTime->SetText( va( "Time: %s / %s", curtime, totaltime ) );
  735. float fScale = demoplayer->GetPlaybackTimeScale();
  736. SetPlaybackScale( fScale ); // set slider
  737. m_pSpeedScaleLabel->SetText( va( "%.1f %%", fScale * 100.0f ) );
  738. }
  739. // Command issued
  740. void CDemoUIPanel2::OnCommand(const char *command)
  741. {
  742. if ( !Q_strcasecmp( command, "stop" ) )
  743. {
  744. Cbuf_AddText( Cbuf_GetCurrentPlayer(), "disconnect\n" );
  745. }
  746. else if ( !Q_strcasecmp( command, "play" ) )
  747. {
  748. if ( !demoplayer->IsPlayingBack() )
  749. {
  750. demoplayer->StartPlayback( demoaction->GetCurrentDemoFile(), false, NULL );
  751. }
  752. else
  753. {
  754. demoplayer->IsPlaybackPaused() ? demoplayer->ResumePlayback() : demoplayer->PausePlayback( -1.f );
  755. }
  756. }
  757. else if ( !Q_strcasecmp( command, "load" ) )
  758. {
  759. OnLoad();
  760. }
  761. else if ( !Q_strcasecmp( command, "reload" ) )
  762. {
  763. Cbuf_AddText( Cbuf_GetCurrentPlayer(), "demo_gototick 0 pause\n" );
  764. }
  765. else if ( !Q_strcasecmp( command, "nextframe" ) )
  766. {
  767. demoplayer->SkipToTick( 0, true, true );
  768. }
  769. else if ( !Q_strcasecmp( command, "prevframe" ) )
  770. {
  771. int nTicksPerFrame = ( demoplayer->GetDemoFile()->m_DemoHeader.playback_ticks / demoplayer->GetDemoFile()->m_DemoHeader.playback_frames ) + 1;
  772. demoplayer->SkipToTick( -nTicksPerFrame, true, true );
  773. }
  774. else if ( !Q_strcasecmp( command, "gototick" ) )
  775. {
  776. char tick[ 32 ];
  777. m_pGotoTick->GetText( tick, sizeof( tick ) );
  778. char cmd[256];
  779. Q_snprintf( cmd, sizeof(cmd), "demo_gototick %s 0 pause\n", tick );
  780. Cbuf_AddText( Cbuf_GetCurrentPlayer(), cmd );
  781. // demoplayer->PausePlayback( -1 );
  782. // demoplayer->SkipToTick( Q_atoi(tick), false );
  783. }
  784. else if ( !Q_strcasecmp( command, "gotomatchend" ) )
  785. {
  786. int nImportantTickIndex = demoplayer->FindPreviousImportantTick( demoplayer->GetDemoStream()->GetTotalTicks() + 1, "announce_phase_end" );
  787. if ( nImportantTickIndex != -1 )
  788. {
  789. const DemoImportantTick_t *pTick = demoplayer->GetImportantTick( nImportantTickIndex );
  790. if ( pTick )
  791. {
  792. demoplayer->SkipToTick( pTick->nPreviousTick, false, true );
  793. }
  794. }
  795. else
  796. {
  797. Msg( "No phase end in this demo.\n" );
  798. }
  799. }
  800. else
  801. {
  802. BaseClass::OnCommand( command );
  803. }
  804. }
  805. void CDemoUIPanel2::OnMessage(const KeyValues *params, VPANEL fromPanel)
  806. {
  807. BaseClass::OnMessage( params, fromPanel );
  808. //
  809. // Speed scale
  810. //
  811. if ( fromPanel == m_pSpeedScale->GetVPanel() )
  812. {
  813. if ( !Q_strcmp( "SliderMoved", params->GetName() ) )
  814. {
  815. demoplayer->SetPlaybackTimeScale( GetPlaybackScale() );
  816. }
  817. }
  818. //
  819. // Demo position
  820. //
  821. if ( fromPanel == m_pProgress->GetVPanel() )
  822. {
  823. if ( !Q_strcmp( "SliderDragStart", params->GetName() ) )
  824. {
  825. // Pause the demo when starting dragging around
  826. if ( demoplayer->IsPlayingBack() && !demoplayer->IsPlaybackPaused() )
  827. {
  828. demoplayer->PausePlayback( -1.f );
  829. }
  830. }
  831. if ( !Q_strcmp( "SliderDragEnd", params->GetName() ) )
  832. {
  833. if ( demoplayer->IsPlayingBack() )
  834. {
  835. int iNewTickPos = m_pProgress->GetValue();
  836. int iDemoCurrentTickPos = demoplayer->GetPlaybackTick();
  837. if ( iNewTickPos != iDemoCurrentTickPos )
  838. Cbuf_AddText( Cbuf_GetCurrentPlayer(), va( "demo_gototick %d 0 1\n", iNewTickPos ) );
  839. }
  840. }
  841. if ( !Q_strcmp( "SliderMoved", params->GetName() ) )
  842. {
  843. NULL;
  844. }
  845. }
  846. }
  847. void CDemoUIPanel2::OnLoad()
  848. {
  849. if ( !m_hFileOpenDialog.Get() )
  850. {
  851. m_hFileOpenDialog = new FileOpenDialog( this, "Choose .dem file", true );
  852. if ( m_hFileOpenDialog != NULL )
  853. {
  854. m_hFileOpenDialog->SetDeleteSelfOnClose( false );
  855. m_hFileOpenDialog->AddFilter("*.dem", "Demo Files (*.dem)", true);
  856. }
  857. }
  858. if ( m_hFileOpenDialog )
  859. {
  860. char startPath[ MAX_PATH ];
  861. Q_strncpy( startPath, com_gamedir, sizeof( startPath ) );
  862. Q_FixSlashes( startPath );
  863. m_hFileOpenDialog->SetStartDirectory( startPath );
  864. m_hFileOpenDialog->DoModal( false );
  865. }
  866. }
  867. void CDemoUIPanel2::OnFileSelected( char const *fullpath )
  868. {
  869. if ( !fullpath || !fullpath[ 0 ] )
  870. return;
  871. char relativepath[ 512 ];
  872. g_pFileSystem->FullPathToRelativePath( fullpath, relativepath, sizeof( relativepath ) );
  873. char ext[ 10 ];
  874. Q_ExtractFileExtension( relativepath, ext, sizeof( ext ) );
  875. if ( Q_strcasecmp( ext, "dem" ) )
  876. {
  877. return;
  878. }
  879. // It's a dem file
  880. Cbuf_AddText( Cbuf_GetCurrentPlayer(), va( "playdemo %s\n", relativepath ) );
  881. Cbuf_AddText( Cbuf_GetCurrentPlayer(), "demopauseafterinit\n" );
  882. if ( m_hFileOpenDialog != NULL )
  883. {
  884. m_hFileOpenDialog->MarkForDeletion();
  885. }
  886. }
  887. void CDemoUIPanel2::OnVDMChanged( void )
  888. {
  889. NULL;
  890. }
  891. float CDemoUIPanel2::GetPlaybackScale( void )
  892. {
  893. float scale = 1.0f;
  894. float curval = (float)m_pSpeedScale->GetValue() ;
  895. if ( curval <= 500.0f )
  896. {
  897. scale = curval / 500.0f;
  898. }
  899. else
  900. {
  901. scale = 1.0f + ( curval - 500.0f ) / 100.0f;
  902. }
  903. return scale;
  904. }
  905. void CDemoUIPanel2::SetPlaybackScale( float scale )
  906. {
  907. if ( scale <= 0 )
  908. {
  909. m_pSpeedScale->SetValue( 0 ) ;
  910. }
  911. else if ( scale <= 1.0f )
  912. {
  913. m_pSpeedScale->SetValue( scale * 500.0f ) ;
  914. }
  915. else
  916. {
  917. m_pSpeedScale->SetValue( (scale - 1.0f) * 100.0f + 500.0f ) ;
  918. }
  919. }
  920. //-----------------------------------------------------------------------------
  921. // Purpose:
  922. // Input : frame -
  923. // elapsed -
  924. // info -
  925. // Output : Returns true on success, false on failure.
  926. //-----------------------------------------------------------------------------
  927. bool CDemoUIPanel2::OverrideView( democmdinfo_t& info, int tick )
  928. {
  929. return false;
  930. }
  931. void CDemoUIPanel2::DrawDebuggingInfo()
  932. {
  933. NULL;
  934. }
  935. //-----------------------------------------------------------------------------
  936. // Purpose:
  937. //-----------------------------------------------------------------------------
  938. void CDemoUIPanel2::HandleInput( bool active )
  939. {
  940. if ( m_bInputActive ^ active )
  941. {
  942. if ( m_bInputActive && !active )
  943. {
  944. // Restore mouse
  945. vgui::input()->SetCursorPos( m_nOldCursor[0], m_nOldCursor[1] );
  946. }
  947. else
  948. {
  949. vgui::input()->GetCursorPos( m_nOldCursor[0], m_nOldCursor[1] );
  950. }
  951. }
  952. m_bInputActive = active;
  953. }
  954. void CDemoUIPanel2::MakePanelForeground( bool bPutToForeground )
  955. {
  956. m_bIsInForeground = bPutToForeground;
  957. SetKeyBoardInputEnabled( m_bIsInForeground );
  958. SetMouseInputEnabled( m_bIsInForeground );
  959. SetParent( m_arrParents[ !!m_bIsInForeground ] );
  960. if ( m_bIsInForeground )
  961. {
  962. g_pDemoUI2->Activate();
  963. }
  964. }
  965. void DemoUI2_f()
  966. {
  967. if ( !g_pDemoUI2 )
  968. return;
  969. if ( g_pDemoUI2->IsVisible() )
  970. {
  971. g_pDemoUI2->Close();
  972. }
  973. else
  974. {
  975. g_pDemoUI2->MakePanelForeground( true );
  976. }
  977. }
  978. void DemoUI2_on()
  979. {
  980. if ( !g_pDemoUI2 )
  981. return;
  982. g_pDemoUI2->MakePanelForeground( true );
  983. }
  984. void DemoUI2_off()
  985. {
  986. if ( !g_pDemoUI2 )
  987. return;
  988. g_pDemoUI2->MakePanelForeground( false );
  989. }
  990. static ConCommand demoui2( "demoui2", DemoUI2_f, "Show/hide the advanced demo player UI (demoui2).", FCVAR_DONTRECORD );
  991. static ConCommand demoui2_on( "+demoui2", DemoUI2_on, "Bring the advanced demo player UI (demoui2) to foreground.", FCVAR_DONTRECORD );
  992. static ConCommand demoui2_off( "-demoui2", DemoUI2_off, "Send the advanced demo player UI (demoui2) to background.", FCVAR_DONTRECORD );
  993. #endif