summaryrefslogtreecommitdiff
path: root/engine/cl_demouipanel.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'engine/cl_demouipanel.cpp')
-rw-r--r--engine/cl_demouipanel.cpp1031
1 files changed, 1031 insertions, 0 deletions
diff --git a/engine/cl_demouipanel.cpp b/engine/cl_demouipanel.cpp
new file mode 100644
index 0000000..70124d0
--- /dev/null
+++ b/engine/cl_demouipanel.cpp
@@ -0,0 +1,1031 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+// $NoKeywords: $
+//=============================================================================//
+
+#include "client_pch.h"
+
+#include <vgui/ISystem.h>
+#include <vgui/ISurface.h>
+#include <vgui/IVGui.h>
+#include <KeyValues.h>
+
+#include <vgui_controls/BuildGroup.h>
+#include <vgui_controls/Tooltip.h>
+#include <vgui_controls/TextImage.h>
+#include <vgui_controls/CheckButton.h>
+#include <vgui_controls/Label.h>
+#include <vgui_controls/PropertySheet.h>
+#include <vgui_controls/FileOpenDialog.h>
+#include <vgui_controls/ProgressBar.h>
+#include <vgui_controls/Slider.h>
+#include <vgui_controls/Controls.h>
+#include <vgui_controls/TextEntry.h>
+#include <vgui/IInput.h>
+
+#include "cl_demoactionmanager.h"
+
+#include "filesystem.h"
+#include "filesystem_engine.h"
+#include "cl_demoeditorpanel.h"
+#include "cl_demosmootherpanel.h"
+#include "cl_demouipanel.h"
+#include "iprediction.h"
+
+// memdbgon must be the last include file in a .cpp file!!!
+#include "tier0/memdbgon.h"
+
+using namespace vgui;
+
+//////////////////////////////////////////////////////////////////////////
+//
+// CDemoUIPanel
+//
+//////////////////////////////////////////////////////////////////////////
+
+CDemoUIPanel *g_pDemoUI = NULL;
+
+void CDemoUIPanel::InstallDemoUI( vgui::Panel *parent )
+{
+ if ( g_pDemoUI )
+ return; // UI already created
+
+ g_pDemoUI = new CDemoUIPanel( parent );
+ Assert( g_pDemoUI );
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Basic help dialog
+//-----------------------------------------------------------------------------
+CDemoUIPanel::CDemoUIPanel( vgui::Panel *parent ) : vgui::Frame( parent, "DemoUIPanel")
+{
+ SetTitle("Demo Playback", true);
+
+ m_pPlayPauseResume = new vgui::Button( this, "DemoPlayPauseResume", "PlayPauseResume" );
+ m_pStop = new vgui::Button( this, "DemoStop", "Stop" );
+ m_pLoad = new vgui::Button( this, "DemoLoad", "Load..." );
+ m_pEdit = new vgui::Button( this, "DemoEdit", "Edit..." );
+ m_pSmooth = new vgui::Button( this, "DemoSmooth", "Smooth..." );
+ m_pDriveCamera = new vgui::ToggleButton( this, "DemoDriveCamera", "Drive..." );
+
+ m_pGoStart = new vgui::ToggleButton( this, "DemoGoStart", "Go Start" );
+ m_pGoEnd = new vgui::Button( this, "DemoGoEnd", "Go End" );
+ m_pFastForward = new vgui::Button( this, "DemoFastForward", "Fast Fwd" );
+ m_pFastBackward = new vgui::Button( this, "DemoFastBackward", "Fast Bwd" );
+ m_pPrevFrame = new vgui::Button( this, "DemoPrevFrame", "Prev Frame" );
+ m_pNextFrame = new vgui::Button( this, "DemoNextFrame", "Next Frame" );
+
+ m_pCurrentDemo = new vgui::Label( this, "DemoName", "" );
+
+ m_pProgress = new vgui::ProgressBar( this, "DemoProgress" );
+ m_pProgress->SetSegmentInfo( 2, 2 );
+
+ m_pProgressLabelFrame = new vgui::Label( this, "DemoProgressLabelFrame", "" );
+ m_pProgressLabelTime = new vgui::Label( this, "DemoProgressLabelTime", "" );
+
+ m_pSpeedScale = new vgui::Slider( this, "DemoSpeedScale" );
+ // 1000 == 10x %
+ m_pSpeedScale->SetRange( 0, 1000 );
+ m_pSpeedScale->SetValue( 500 );
+ m_pSpeedScale->AddActionSignalTarget( this );
+
+ m_pSpeedScaleLabel = new vgui::Label( this, "SpeedScale", "" );
+
+ m_pGo = new vgui::Button( this, "DemoGo", "Go" );
+ m_pGotoTick = new vgui::TextEntry( this, "DemoGoToTick" );
+
+ vgui::ivgui()->AddTickSignal( GetVPanel(), 0 );
+
+ LoadControlSettings("Resource\\DemoUIPanel.res");
+
+ SetVisible( false );
+ SetSizeable( false );
+ SetMoveable( true );
+
+ m_ViewOrigin.Init();
+ m_ViewAngles.Init();
+ memset( m_nOldCursor, 0, sizeof( m_nOldCursor ) );
+ m_bInputActive = false;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+CDemoUIPanel::~CDemoUIPanel()
+{
+}
+
+void CDemoUIPanel::GetCurrentView()
+{
+ g_pClientSidePrediction->GetViewOrigin( m_ViewOrigin );
+ g_pClientSidePrediction->GetViewAngles( m_ViewAngles );
+}
+
+bool CDemoUIPanel::IsInDriveMode()
+{
+ return m_pDriveCamera->IsSelected();
+}
+
+void CDemoUIPanel::GetDriveViewPoint( Vector &origin, QAngle &angle )
+{
+ origin = m_ViewOrigin;
+ angle = m_ViewAngles;
+}
+
+void CDemoUIPanel::SetDriveViewPoint( Vector &origin, QAngle &angle )
+{
+ m_ViewOrigin = origin;
+ m_ViewAngles = angle;
+}
+
+void CDemoUIPanel::OnTick()
+{
+ BaseClass::OnTick();
+
+ if ( !IsVisible() )
+ return;
+
+ char curtime[32];
+ char totaltime[32];
+ int curtick = 0;
+ int totalticks = 0;
+ float fProgress = 0.0f;
+
+ bool bIsPlaying = demoplayer->IsPlayingBack();
+
+ // enable/disable all playback control buttons
+ m_pPlayPauseResume->SetEnabled( bIsPlaying );
+ m_pStop->SetEnabled( bIsPlaying );
+ m_pNextFrame->SetEnabled( bIsPlaying );
+ m_pFastForward->SetEnabled( bIsPlaying );
+ m_pGoStart->SetEnabled( bIsPlaying );
+ m_pGoEnd->SetEnabled( bIsPlaying );
+ m_pGo->SetEnabled( bIsPlaying );
+
+ bool bEnabled = bIsPlaying && false;
+
+ // if player can go back in time
+ m_pFastBackward->SetEnabled( bEnabled );
+ m_pPrevFrame->SetEnabled( bEnabled );
+
+ // set filename text
+ m_pCurrentDemo->SetText( demoaction->GetCurrentDemoFile() );
+ bool bHasDemoFile = demoaction->GetCurrentDemoFile()[0] != 0;
+
+ // set play button text
+ if ( bIsPlaying )
+ {
+ m_pPlayPauseResume->SetText( demoplayer->IsPlaybackPaused() ? "Resume" : "Pause" );
+ }
+ else
+ {
+ if ( bHasDemoFile )
+ {
+ m_pPlayPauseResume->SetText( "Play" );
+ m_pPlayPauseResume->SetEnabled( true );
+ }
+ }
+
+ if ( bIsPlaying )
+ {
+ curtick = demoplayer->GetPlaybackTick();
+ totalticks = demoplayer->GetTotalTicks();
+
+ fProgress = (float)curtick/(float)totalticks;
+ fProgress = clamp( fProgress, 0.0f, 1.0f );
+ }
+
+ m_pProgress->SetProgress( fProgress );
+ m_pProgressLabelFrame->SetText( va( "Tick: %i / %i", curtick, totalticks ) );
+
+ Q_strncpy( curtime, COM_FormatSeconds( host_state.interval_per_tick * curtick ), 32 );
+ Q_strncpy( totaltime, COM_FormatSeconds( host_state.interval_per_tick * totalticks ), 32 );
+ m_pProgressLabelTime->SetText( va( "Time: %s / %s", curtime, totaltime ) );
+
+ m_pFastForward->SetEnabled( demoplayer->IsPlayingBack() && !demoplayer->IsPlaybackPaused() );
+
+ float fScale = demoplayer->GetPlaybackTimeScale();
+
+ SetPlaybackScale( fScale ); // set slider
+
+ m_pSpeedScaleLabel->SetText( va( "%.1f %%", fScale * 100.0f ) );
+}
+
+// Command issued
+void CDemoUIPanel::OnCommand(const char *command)
+{
+ if ( !Q_strcasecmp( command, "stop" ) )
+ {
+ Cbuf_AddText( "disconnect\n" );
+ }
+ else if ( !Q_strcasecmp( command, "play" ) )
+ {
+ if ( !demoplayer->IsPlayingBack() )
+ {
+ char cmd[ 256 ];
+ Q_snprintf( cmd, sizeof( cmd ), "playdemo %s\n", demoaction->GetCurrentDemoFile() );
+
+ Cbuf_AddText( cmd );
+ }
+ else
+ {
+ Cbuf_AddText( !demoplayer->IsPlaybackPaused() ? "demo_pause\n" : "demo_resume\n" );
+ }
+ }
+ else if ( !Q_strcasecmp( command, "load" ) )
+ {
+ OnLoad();
+ }
+ else if ( !Q_strcasecmp( command, "reload" ) )
+ {
+ Cbuf_AddText( "demo_gototick 0 0 1\n" );
+ }
+ else if ( !Q_strcasecmp( command, "edit" ) )
+ {
+ OnEdit();
+ }
+ else if ( !Q_strcasecmp( command, "smooth" ) )
+ {
+ OnSmooth();
+ }
+ else if ( !Q_strcasecmp( command, "nextframe" ) )
+ {
+ demoplayer->SkipToTick( 1, true, true );
+ }
+ else if ( !Q_strcasecmp( command, "gototick" ) )
+ {
+ char tick[ 32 ];
+ m_pGotoTick->GetText( tick, sizeof( tick ) );
+
+ char cmd[256];
+ Q_snprintf( cmd, sizeof(cmd), "demo_gototick %s 0 1\n", tick );
+
+ Cbuf_AddText( cmd );
+
+ // demoplayer->PausePlayback( -1 );
+ // demoplayer->SkipToTick( Q_atoi(tick), false );
+ }
+ else if ( !Q_strcasecmp( command, "drive" ) )
+ {
+ GetCurrentView();
+ }
+ else
+ {
+ BaseClass::OnCommand( command );
+ }
+}
+
+void CDemoUIPanel::OnMessage(const KeyValues *params, VPANEL fromPanel)
+{
+ BaseClass::OnMessage( params, fromPanel );
+
+ if ( !Q_strcmp( "SliderMoved", params->GetName() ) )
+ {
+ demoplayer->SetPlaybackTimeScale( GetPlaybackScale() );
+ }
+}
+
+void CDemoUIPanel::OnEdit()
+{
+ if ( m_hDemoEditor != 0 )
+ {
+ m_hDemoEditor->SetVisible( true );
+ m_hDemoEditor->MoveToFront();
+ m_hDemoEditor->OnVDMChanged();
+ return;
+ }
+
+ m_hDemoEditor = new CDemoEditorPanel( this );
+}
+
+void CDemoUIPanel::OnSmooth()
+{
+ if ( m_hDemoSmoother != 0 )
+ {
+ m_hDemoSmoother->SetVisible( true );
+ m_hDemoSmoother->MoveToFront();
+ m_hDemoSmoother->OnVDMChanged();
+ return;
+ }
+
+ m_hDemoSmoother = new CDemoSmootherPanel( this );
+}
+
+void CDemoUIPanel::OnLoad()
+{
+ if ( !m_hFileOpenDialog.Get() )
+ {
+ m_hFileOpenDialog = new FileOpenDialog( this, "Choose .dem file", true );
+ if ( m_hFileOpenDialog != 0 )
+ {
+ m_hFileOpenDialog->AddFilter("*.dem", "Demo Files (*.dem)", true);
+ }
+ }
+ if ( m_hFileOpenDialog )
+ {
+ char startPath[ MAX_PATH ];
+ Q_strncpy( startPath, com_gamedir, sizeof( startPath ) );
+ Q_FixSlashes( startPath );
+ m_hFileOpenDialog->SetStartDirectory( startPath );
+ m_hFileOpenDialog->DoModal( false );
+ }
+}
+
+void CDemoUIPanel::OnFileSelected( char const *fullpath )
+{
+ if ( !fullpath || !fullpath[ 0 ] )
+ return;
+
+ char relativepath[ 512 ];
+ g_pFileSystem->FullPathToRelativePath( fullpath, relativepath, sizeof( relativepath ) );
+
+ char ext[ 10 ];
+ Q_ExtractFileExtension( relativepath, ext, sizeof( ext ) );
+
+ if ( Q_strcasecmp( ext, "dem" ) )
+ {
+ return;
+ }
+
+ // It's a dem file
+ Cbuf_AddText( va( "playdemo %s\n", relativepath ) );
+ Cbuf_AddText( "demopauseafterinit\n" );
+
+ if ( m_hFileOpenDialog != 0 )
+ {
+ m_hFileOpenDialog->MarkForDeletion();
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CDemoUIPanel::OnVDMChanged( void )
+{
+ if ( m_hDemoEditor != 0 )
+ {
+ m_hDemoEditor->OnVDMChanged();
+ }
+ if ( m_hDemoSmoother != 0 )
+ {
+ m_hDemoSmoother->OnVDMChanged();
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+// Output : Returns true on success, false on failure.
+//-----------------------------------------------------------------------------
+bool CDemoUIPanel::IsHoldingFastForward( void )
+{
+ if ( !m_pFastForward->IsVisible() )
+ return false;
+
+ if ( !m_pFastForward->IsEnabled() )
+ return false;
+
+ return m_pFastForward->IsSelected();
+}
+
+float CDemoUIPanel::GetPlaybackScale( void )
+{
+ float scale = 1.0f;
+ float curval = (float)m_pSpeedScale->GetValue() ;
+
+ if ( curval <= 500.0f )
+ {
+ scale = curval / 500.0f;
+ }
+ else
+ {
+ scale = 1.0f + ( curval - 500.0f ) / 100.0f;
+ }
+ return scale;
+}
+
+void CDemoUIPanel::SetPlaybackScale( float scale )
+{
+ if ( scale <= 0 )
+ {
+ m_pSpeedScale->SetValue( 0 ) ;
+ }
+ else if ( scale <= 1.0f )
+ {
+ m_pSpeedScale->SetValue( scale * 500.0f ) ;
+ }
+ else
+ {
+ m_pSpeedScale->SetValue( (scale - 1.0f) * 100.0f + 500.0f ) ;
+ }
+
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+// Input : frame -
+// elapsed -
+// info -
+// Output : Returns true on success, false on failure.
+//-----------------------------------------------------------------------------
+bool CDemoUIPanel::OverrideView( democmdinfo_t& info, int tick )
+{
+ if ( IsInDriveMode() )
+ {
+ // manual camera override, overrides anyting
+ HandleInput( vgui::input()->IsMouseDown( MOUSE_LEFT ) );
+
+ info.viewOrigin = m_ViewOrigin;
+ info.viewAngles = m_ViewAngles;
+ info.localViewAngles = m_ViewAngles;
+
+ return true;
+ }
+
+ if ( m_hDemoSmoother != 0 )
+ {
+ // demo smoother override
+ if ( m_hDemoSmoother->OverrideView( info, tick ) )
+ {
+ m_ViewOrigin = info.GetViewOrigin();
+ m_ViewAngles = info.GetViewAngles();
+ return true;
+ }
+ }
+
+ m_ViewOrigin = info.GetViewOrigin();
+ m_ViewAngles = info.GetViewAngles();
+
+ return false;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+// Input : frame -
+// elapsed -
+// smoothing -
+//-----------------------------------------------------------------------------
+void CDemoUIPanel::DrawDebuggingInfo()
+{
+ if ( m_hDemoSmoother != 0 )
+ {
+ m_hDemoSmoother->DrawDebuggingInfo( 1, 1 ); // MOTODO
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CDemoUIPanel::HandleInput( bool active )
+{
+ if ( m_bInputActive ^ active )
+ {
+ if ( m_bInputActive && !active )
+ {
+ // Restore mouse
+ vgui::input()->SetCursorPos( m_nOldCursor[0], m_nOldCursor[1] );
+ }
+ else
+ {
+ GetCurrentView();
+ vgui::input()->GetCursorPos( m_nOldCursor[0], m_nOldCursor[1] );
+ }
+ }
+
+ if ( active )
+ {
+ float f = 0.0f;
+ float s = 0.0f;
+ float u = 0.0f;
+
+ bool shiftdown = vgui::input()->IsKeyDown( KEY_LSHIFT ) || vgui::input()->IsKeyDown( KEY_RSHIFT );
+ float movespeed = shiftdown ? 40.0f : 400.0f;
+
+ if ( vgui::input()->IsKeyDown( KEY_W ) )
+ {
+ f = movespeed * host_frametime;
+ }
+ if ( vgui::input()->IsKeyDown( KEY_S ) )
+ {
+ f = -movespeed * host_frametime;
+ }
+ if ( vgui::input()->IsKeyDown( KEY_A ) )
+ {
+ s = -movespeed * host_frametime;
+ }
+ if ( vgui::input()->IsKeyDown( KEY_D ) )
+ {
+ s = movespeed * host_frametime;
+ }
+ if ( vgui::input()->IsKeyDown( KEY_X ) )
+ {
+ u = movespeed * host_frametime;
+ }
+ if ( vgui::input()->IsKeyDown( KEY_Z ) )
+ {
+ u = -movespeed * host_frametime;
+ }
+
+ int mx, my;
+ int dx, dy;
+
+ vgui::input()->GetCursorPos( mx, my );
+
+ dx = mx - m_nOldCursor[0];
+ dy = my - m_nOldCursor[1];
+
+ vgui::input()->SetCursorPos( m_nOldCursor[0], m_nOldCursor[1] );
+
+ // Convert to pitch/yaw
+
+ float pitch = (float)dy * 0.22f;
+ float yaw = -(float)dx * 0.22;
+
+ // Apply mouse
+ m_ViewAngles.x += pitch;
+
+ m_ViewAngles.x = clamp( m_ViewAngles.x, -89.0f, 89.0f );
+
+ m_ViewAngles.y += yaw;
+ if ( m_ViewAngles.y > 180.0f )
+ {
+ m_ViewAngles.y -= 360.0f;
+ }
+ else if ( m_ViewAngles.y < -180.0f )
+ {
+ m_ViewAngles.y += 360.0f;
+ }
+
+ // Now apply forward, side, up
+
+ Vector fwd, side, up;
+
+ AngleVectors( m_ViewAngles, &fwd, &side, &up );
+
+ m_ViewOrigin += fwd * f;
+ m_ViewOrigin += side * s;
+ m_ViewOrigin += up * u;
+ }
+
+ m_bInputActive = active;
+}
+
+void DemoUI_f()
+{
+ if ( !g_pDemoUI )
+ return;
+
+ if ( g_pDemoUI->IsVisible() )
+ {
+ g_pDemoUI->Close();
+ }
+ else
+ {
+ g_pDemoUI->Activate();
+ }
+}
+
+static ConCommand demoui( "demoui", DemoUI_f, "Show/hide the demo player UI.", FCVAR_DONTRECORD );
+
+
+
+
+
+
+//////////////////////////////////////////////////////////////////////////
+//
+// CDemoUIPanel2
+//
+//////////////////////////////////////////////////////////////////////////
+
+CDemoUIPanel2 *g_pDemoUI2 = NULL;
+
+void CDemoUIPanel2::Install( vgui::Panel *pParentBkgnd, vgui::Panel *pParentFgnd, bool bPutToForeground )
+{
+ if ( g_pDemoUI2 )
+ return; // UI already created
+
+ g_pDemoUI2 = new CDemoUIPanel2( pParentBkgnd, pParentFgnd, bPutToForeground );
+ Assert( g_pDemoUI2 );
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Basic help dialog
+//-----------------------------------------------------------------------------
+CDemoUIPanel2::CDemoUIPanel2( vgui::Panel *pParentBkgnd, vgui::Panel *pParentFgnd, bool bPutToForeground ) :
+ vgui::Frame( bPutToForeground ? pParentFgnd : pParentBkgnd, "DemoUIPanel2")
+{
+ m_arrParents[0] = pParentBkgnd;
+ m_arrParents[1] = pParentFgnd;
+ m_bIsInForeground = bPutToForeground;
+
+ SetTitle("Demo Playback - ", true);
+
+ m_pPlayPauseResume = new vgui::Button( this, "DemoPlayPauseResume", "PlayPauseResume" );
+ m_pStop = new vgui::Button( this, "DemoStop", "Stop" );
+ m_pLoad = new vgui::Button( this, "DemoLoad", "Load..." );
+
+ m_pGoStart = new vgui::ToggleButton( this, "DemoGoStart", "Go Start" );
+ m_pGoEnd = new vgui::Button( this, "DemoGoEnd", "Go End" );
+ m_pFastForward = new vgui::Button( this, "DemoFastForward", "Fast Fwd" );
+ m_pFastBackward = new vgui::Button( this, "DemoFastBackward", "Fast Bwd" );
+ m_pPrevFrame = new vgui::Button( this, "DemoPrevFrame", "Prev Frame" );
+ m_pNextFrame = new vgui::Button( this, "DemoNextFrame", "Next Frame" );
+
+ m_pProgress = new vgui::Slider( this, "DemoProgress" );
+ m_pProgress->SetRange( 0, 0 );
+ m_pProgress->SetValue( 0, false );
+ m_pProgress->AddActionSignalTarget( this );
+ m_pProgress->SetDragOnRepositionNob( true );
+
+ m_pProgressLabelFrame = new vgui::Label( this, "DemoProgressLabelFrame", "" );
+ m_pProgressLabelTime = new vgui::Label( this, "DemoProgressLabelTime", "" );
+
+ m_pSpeedScale = new vgui::Slider( this, "DemoSpeedScale" );
+ // 1000 == 10x %
+ m_pSpeedScale->SetRange( 0, 1000 );
+ m_pSpeedScale->SetValue( 500 );
+ m_pSpeedScale->AddActionSignalTarget( this );
+ m_pSpeedScale->SetDragOnRepositionNob( true );
+
+ m_pSpeedScaleLabel = new vgui::Label( this, "SpeedScale", "" );
+
+ vgui::ivgui()->AddTickSignal( GetVPanel(), 0 );
+
+ LoadControlSettings("Resource\\DemoUIPanel2.res");
+
+ SetVisible( false );
+ SetSizeable( false );
+ SetMoveable( true );
+
+ memset( m_nOldCursor, 0, sizeof( m_nOldCursor ) );
+ m_bInputActive = false;
+}
+
+CDemoUIPanel2::~CDemoUIPanel2()
+{
+}
+
+bool CDemoUIPanel2::IsInDriveMode()
+{
+ return false;
+}
+
+void CDemoUIPanel2::GetDriveViewPoint( Vector &origin, QAngle &angle )
+{
+ NULL;
+}
+
+void CDemoUIPanel2::SetDriveViewPoint( Vector &origin, QAngle &angle )
+{
+ NULL;
+}
+
+void CDemoUIPanel2::OnTick()
+{
+ BaseClass::OnTick();
+
+ if ( !IsVisible() )
+ return;
+
+ char curtime[32];
+ char totaltime[32];
+ int curtick = 0;
+ int totalticks = 0;
+ float fProgress = 0.0f;
+
+ bool bIsPlaying = demoplayer->IsPlayingBack();
+
+ // enable/disable all playback control buttons
+ m_pPlayPauseResume->SetEnabled( bIsPlaying );
+ m_pStop->SetEnabled( bIsPlaying );
+ m_pNextFrame->SetEnabled( bIsPlaying );
+ m_pFastForward->SetEnabled( bIsPlaying );
+ m_pGoStart->SetEnabled( bIsPlaying );
+ m_pGoEnd->SetEnabled( bIsPlaying );
+
+ bool bEnabled = bIsPlaying && false;
+
+ // if player can go back in time
+ m_pFastBackward->SetEnabled( bEnabled );
+ m_pPrevFrame->SetEnabled( bEnabled );
+
+ // set filename text
+ SetTitle( va( "Demo Playback - %s", demoaction->GetCurrentDemoFile() ), true );
+ bool bHasDemoFile = demoaction->GetCurrentDemoFile()[0] != 0;
+
+ // set play button text
+ if ( bIsPlaying )
+ {
+ m_pPlayPauseResume->SetText( demoplayer->IsPlaybackPaused() ? "Resume" : "Pause" );
+ }
+ else
+ {
+ if ( bHasDemoFile )
+ {
+ m_pPlayPauseResume->SetText( "Play" );
+ m_pPlayPauseResume->SetEnabled( true );
+ }
+ }
+
+ if ( bIsPlaying )
+ {
+ curtick = demoplayer->GetPlaybackTick();
+ totalticks = demoplayer->GetTotalTicks();
+
+ fProgress = (float)curtick/(float)totalticks;
+ fProgress = clamp( fProgress, 0.0f, 1.0f );
+ }
+
+ if ( !m_pProgress->IsDragged() )
+ {
+ m_pProgress->SetRange( 0, max( totalticks, 0 ) );
+ m_pProgress->SetValue( min( max( curtick, 0 ), totalticks ), false );
+ m_pProgressLabelFrame->SetText( va( "Tick: %i / %i", curtick, totalticks ) );
+ }
+ else
+ {
+ m_pProgressLabelFrame->SetText( va( "Tick: %i / %i", m_pProgress->GetValue(), totalticks ) );
+ }
+
+ // Color in red when dragging back
+ m_pProgressLabelFrame->SetFgColor( ( m_pProgress->GetValue() < curtick ) ? Color( 255, 0, 0, 255 ) : m_pProgressLabelTime->GetFgColor() );
+
+ Q_strncpy( curtime, COM_FormatSeconds( host_state.interval_per_tick * curtick ), 32 );
+ Q_strncpy( totaltime, COM_FormatSeconds( host_state.interval_per_tick * totalticks ), 32 );
+ m_pProgressLabelTime->SetText( va( "Time: %s / %s", curtime, totaltime ) );
+
+ m_pFastForward->SetEnabled( demoplayer->IsPlayingBack() && !demoplayer->IsPlaybackPaused() );
+
+ float fScale = demoplayer->GetPlaybackTimeScale();
+
+ SetPlaybackScale( fScale ); // set slider
+
+ m_pSpeedScaleLabel->SetText( va( "%.1f %%", fScale * 100.0f ) );
+}
+
+// Command issued
+void CDemoUIPanel2::OnCommand(const char *command)
+{
+ if ( !Q_strcasecmp( command, "stop" ) )
+ {
+ Cbuf_AddText( "disconnect\n" );
+ }
+ else if ( !Q_strcasecmp( command, "play" ) )
+ {
+ if ( !demoplayer->IsPlayingBack() )
+ {
+ demoplayer->StartPlayback( demoaction->GetCurrentDemoFile(), false );
+ }
+ else
+ {
+ demoplayer->IsPlaybackPaused() ? demoplayer->ResumePlayback() : demoplayer->PausePlayback( -1.f );
+ }
+ }
+ else if ( !Q_strcasecmp( command, "load" ) )
+ {
+ OnLoad();
+ }
+ else if ( !Q_strcasecmp( command, "reload" ) )
+ {
+ Cbuf_AddText( "demo_gototick 0 0 1\n" );
+ }
+ else if ( !Q_strcasecmp( command, "nextframe" ) )
+ {
+ Cbuf_AddText( "demo_gototick 1 1 1\n" );
+ }
+ else
+ {
+ BaseClass::OnCommand( command );
+ }
+}
+
+void CDemoUIPanel2::OnMessage(const KeyValues *params, VPANEL fromPanel)
+{
+ BaseClass::OnMessage( params, fromPanel );
+
+ //
+ // Speed scale
+ //
+ if ( fromPanel == m_pSpeedScale->GetVPanel() )
+ {
+ if ( !Q_strcmp( "SliderMoved", params->GetName() ) )
+ {
+ demoplayer->SetPlaybackTimeScale( GetPlaybackScale() );
+ }
+ }
+
+ //
+ // Demo position
+ //
+ if ( fromPanel == m_pProgress->GetVPanel() )
+ {
+ if ( !Q_strcmp( "SliderDragStart", params->GetName() ) )
+ {
+ // Pause the demo when starting dragging around
+ if ( demoplayer->IsPlayingBack() && !demoplayer->IsPlaybackPaused() )
+ {
+ demoplayer->PausePlayback( -1.f );
+ }
+ }
+
+ if ( !Q_strcmp( "SliderDragEnd", params->GetName() ) )
+ {
+ int iNewTickPos = m_pProgress->GetValue();
+ int iDemoCurrentTickPos = demoplayer->GetPlaybackTick();
+
+ if ( iNewTickPos != iDemoCurrentTickPos )
+ Cbuf_AddText( va( "demo_gototick %d 0 1\n", iNewTickPos ) );
+ }
+
+ if ( !Q_strcmp( "SliderMoved", params->GetName() ) )
+ {
+ NULL;
+ }
+ }
+}
+
+void CDemoUIPanel2::OnLoad()
+{
+ if ( !m_hFileOpenDialog.Get() )
+ {
+ m_hFileOpenDialog = new FileOpenDialog( this, "Choose .dem file", true );
+ if ( m_hFileOpenDialog != 0 )
+ {
+ m_hFileOpenDialog->AddFilter("*.dem", "Demo Files (*.dem)", true);
+ }
+ }
+ if ( m_hFileOpenDialog )
+ {
+ char startPath[ MAX_PATH ];
+ Q_strncpy( startPath, com_gamedir, sizeof( startPath ) );
+ Q_FixSlashes( startPath );
+ m_hFileOpenDialog->SetStartDirectory( startPath );
+ m_hFileOpenDialog->DoModal( false );
+ }
+}
+
+void CDemoUIPanel2::OnFileSelected( char const *fullpath )
+{
+ if ( !fullpath || !fullpath[ 0 ] )
+ return;
+
+ char relativepath[ 512 ];
+ g_pFileSystem->FullPathToRelativePath( fullpath, relativepath, sizeof( relativepath ) );
+
+ char ext[ 10 ];
+ Q_ExtractFileExtension( relativepath, ext, sizeof( ext ) );
+
+ if ( Q_strcasecmp( ext, "dem" ) )
+ {
+ return;
+ }
+
+ // It's a dem file
+ Cbuf_AddText( va( "playdemo %s\n", relativepath ) );
+ Cbuf_AddText( "demopauseafterinit\n" );
+
+ if ( m_hFileOpenDialog != 0 )
+ {
+ m_hFileOpenDialog->MarkForDeletion();
+ }
+}
+
+void CDemoUIPanel2::OnVDMChanged( void )
+{
+ NULL;
+}
+
+bool CDemoUIPanel2::IsHoldingFastForward( void )
+{
+ if ( !m_pFastForward->IsVisible() )
+ return false;
+
+ if ( !m_pFastForward->IsEnabled() )
+ return false;
+
+ return m_pFastForward->IsSelected();
+}
+
+float CDemoUIPanel2::GetPlaybackScale( void )
+{
+ float scale = 1.0f;
+ float curval = (float)m_pSpeedScale->GetValue() ;
+
+ if ( curval <= 500.0f )
+ {
+ scale = curval / 500.0f;
+ }
+ else
+ {
+ scale = 1.0f + ( curval - 500.0f ) / 100.0f;
+ }
+ return scale;
+}
+
+void CDemoUIPanel2::SetPlaybackScale( float scale )
+{
+ if ( scale <= 0 )
+ {
+ m_pSpeedScale->SetValue( 0 ) ;
+ }
+ else if ( scale <= 1.0f )
+ {
+ m_pSpeedScale->SetValue( scale * 500.0f ) ;
+ }
+ else
+ {
+ m_pSpeedScale->SetValue( (scale - 1.0f) * 100.0f + 500.0f ) ;
+ }
+
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+// Input : frame -
+// elapsed -
+// info -
+// Output : Returns true on success, false on failure.
+//-----------------------------------------------------------------------------
+bool CDemoUIPanel2::OverrideView( democmdinfo_t& info, int tick )
+{
+ return false;
+}
+
+void CDemoUIPanel2::DrawDebuggingInfo()
+{
+ NULL;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CDemoUIPanel2::HandleInput( bool active )
+{
+ if ( m_bInputActive ^ active )
+ {
+ if ( m_bInputActive && !active )
+ {
+ // Restore mouse
+ vgui::input()->SetCursorPos( m_nOldCursor[0], m_nOldCursor[1] );
+ }
+ else
+ {
+ vgui::input()->GetCursorPos( m_nOldCursor[0], m_nOldCursor[1] );
+ }
+ }
+
+ m_bInputActive = active;
+}
+
+void CDemoUIPanel2::MakePanelForeground( bool bPutToForeground )
+{
+ m_bIsInForeground = bPutToForeground;
+
+ SetKeyBoardInputEnabled( m_bIsInForeground );
+ SetMouseInputEnabled( m_bIsInForeground );
+
+ SetParent( m_arrParents[ !!m_bIsInForeground ] );
+
+ if ( m_bIsInForeground )
+ {
+ g_pDemoUI2->Activate();
+ }
+}
+
+void DemoUI2_f()
+{
+ if ( !g_pDemoUI2 )
+ return;
+
+ if ( g_pDemoUI2->IsVisible() )
+ {
+ g_pDemoUI2->Close();
+ }
+ else
+ {
+ g_pDemoUI2->MakePanelForeground( true );
+ }
+}
+
+void DemoUI2_on()
+{
+ if ( !g_pDemoUI2 )
+ return;
+
+ g_pDemoUI2->MakePanelForeground( true );
+}
+
+void DemoUI2_off()
+{
+ if ( !g_pDemoUI2 )
+ return;
+
+ g_pDemoUI2->MakePanelForeground( false );
+}
+
+static ConCommand demoui2( "demoui2", DemoUI2_f, "Show/hide the advanced demo player UI (demoui2).", FCVAR_DONTRECORD );
+static ConCommand demoui2_on( "+demoui2", DemoUI2_on, "Bring the advanced demo player UI (demoui2) to foreground.", FCVAR_DONTRECORD );
+static ConCommand demoui2_off( "-demoui2", DemoUI2_off, "Send the advanced demo player UI (demoui2) to background.", FCVAR_DONTRECORD );
+