summaryrefslogtreecommitdiff
path: root/common/vgui
diff options
context:
space:
mode:
Diffstat (limited to 'common/vgui')
-rw-r--r--common/vgui/vgui_basebudgetpanel.cpp443
-rw-r--r--common/vgui/vgui_basebudgetpanel.h145
-rw-r--r--common/vgui/vgui_budgetbargraphpanel.cpp252
-rw-r--r--common/vgui/vgui_budgetbargraphpanel.h43
-rw-r--r--common/vgui/vgui_budgethistorypanel.cpp136
-rw-r--r--common/vgui/vgui_budgethistorypanel.h48
-rw-r--r--common/vgui/vgui_budgetpanelshared.cpp263
-rw-r--r--common/vgui/vgui_budgetpanelshared.h71
8 files changed, 1401 insertions, 0 deletions
diff --git a/common/vgui/vgui_basebudgetpanel.cpp b/common/vgui/vgui_basebudgetpanel.cpp
new file mode 100644
index 0000000..3a2f639
--- /dev/null
+++ b/common/vgui/vgui_basebudgetpanel.cpp
@@ -0,0 +1,443 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+//=============================================================================//
+
+#include "vgui_basebudgetpanel.h"
+#include "vgui_controls/Label.h"
+
+// memdbgon must be the last include file in a .cpp file!!!
+#include "tier0/memdbgon.h"
+
+CBaseBudgetPanel::CBaseBudgetPanel( vgui::Panel *pParent, const char *pElementName )
+ : vgui::Panel( pParent, pElementName )
+{
+ m_BudgetHistoryOffset = 0;
+
+ SetProportional( false );
+ SetKeyBoardInputEnabled( false );
+ SetMouseInputEnabled( false );
+ SetVisible( true );
+
+ // set the scheme before any child control is created
+ vgui::HScheme scheme = vgui::scheme()->LoadSchemeFromFile("resource/SourceScheme.res", "Client");
+ SetScheme( scheme );
+
+ m_pBudgetHistoryPanel = NULL;
+ m_pBudgetBarGraphPanel = NULL;
+ SetZPos( 1001 );
+
+ m_bDedicated = false;
+}
+
+
+CBaseBudgetPanel::~CBaseBudgetPanel()
+{
+}
+
+
+float CBaseBudgetPanel::GetBudgetGroupPercent( float value )
+{
+ if ( m_ConfigData.m_flBarGraphRange == 0.0f )
+ return 1.0f;
+ return value / m_ConfigData.m_flBarGraphRange;
+}
+
+
+const double *CBaseBudgetPanel::GetBudgetGroupData( int &nGroups, int &nSamplesPerGroup, int &nSampleOffset ) const
+{
+ nGroups = m_ConfigData.m_BudgetGroupInfo.Count();
+ nSamplesPerGroup = BUDGET_HISTORY_COUNT;
+ nSampleOffset = m_BudgetHistoryOffset;
+ if( m_BudgetGroupTimes.Count() == 0 )
+ {
+ return NULL;
+ }
+ else
+ {
+ return &m_BudgetGroupTimes[0].m_Time[0];
+ }
+}
+
+
+void CBaseBudgetPanel::ClearTimesForAllGroupsForThisFrame( void )
+{
+ int i;
+ for( i = 0; i < m_ConfigData.m_BudgetGroupInfo.Count(); i++ )
+ {
+ m_BudgetGroupTimes[i].m_Time[m_BudgetHistoryOffset] = 0.0;
+ }
+}
+
+void CBaseBudgetPanel::ClearAllTimesForGroup( int groupID )
+{
+ int i;
+ for( i = 0; i < BUDGET_HISTORY_COUNT; i++ )
+ {
+ m_BudgetGroupTimes[groupID].m_Time[i] = 0.0;
+ }
+}
+
+
+void CBaseBudgetPanel::OnConfigDataChanged( const CBudgetPanelConfigData &data )
+{
+ int oldNumGroups = m_ConfigData.m_BudgetGroupInfo.Count();
+
+ // Copy in the config data and rebuild everything.
+ Rebuild( data );
+
+ if ( m_ConfigData.m_BudgetGroupInfo.Count() > m_BudgetGroupTimes.Count() )
+ {
+ m_BudgetGroupTimes.EnsureCount( m_ConfigData.m_BudgetGroupInfo.Count() );
+ for ( int i = oldNumGroups; i < m_ConfigData.m_BudgetGroupInfo.Count(); i++ )
+ {
+ ClearAllTimesForGroup( i );
+ }
+ }
+ else
+ {
+ m_BudgetGroupTimes.SetSize( m_ConfigData.m_BudgetGroupInfo.Count() );
+ for ( int i = 0; i < m_BudgetGroupTimes.Count(); i++ )
+ {
+ ClearAllTimesForGroup( i );
+ }
+ }
+
+ InvalidateLayout( false, true );
+}
+
+
+void CBaseBudgetPanel::ResetAll()
+{
+ m_ConfigData.m_BudgetGroupInfo.Purge();
+
+ for ( int i=0; i < m_GraphLabels.Count(); i++ )
+ m_GraphLabels[i]->MarkForDeletion();
+ m_GraphLabels.Purge();
+
+ for ( int i=0; i < m_TimeLabels.Count(); i++ )
+ m_TimeLabels[i]->MarkForDeletion();
+ m_TimeLabels.Purge();
+}
+
+
+void CBaseBudgetPanel::Rebuild( const CBudgetPanelConfigData &data )
+{
+ int oldNumBudgetGroups = m_ConfigData.m_BudgetGroupInfo.Count();
+ int oldNumHistoryLabels = m_ConfigData.m_HistoryLabelValues.Count();
+
+ int oldNumTimeLabels = m_TimeLabels.Count();
+
+ // Copy the new config in.
+ m_ConfigData = data;
+
+ int nParentWidth, nParentHeight;
+ GetParent()->GetSize( nParentWidth, nParentHeight );
+ if ( m_ConfigData.m_Width > nParentWidth )
+ {
+ m_ConfigData.m_Width = nParentWidth;
+ }
+ if ( m_ConfigData.m_Height > nParentHeight )
+ {
+ m_ConfigData.m_Height = nParentHeight;
+ }
+ if ( m_ConfigData.m_xCoord + m_ConfigData.m_Width > nParentWidth )
+ {
+ m_ConfigData.m_xCoord = nParentWidth - m_ConfigData.m_Width;
+ }
+ if ( m_ConfigData.m_yCoord + m_ConfigData.m_Height > nParentHeight )
+ {
+ m_ConfigData.m_yCoord = nParentHeight - m_ConfigData.m_Height;
+ }
+
+ // Recreate the history and bar graph panels.
+ if( m_pBudgetHistoryPanel )
+ {
+ m_pBudgetHistoryPanel->MarkForDeletion();
+ }
+ m_pBudgetHistoryPanel = new CBudgetHistoryPanel( this, "FrametimeHistory" );
+
+ if( m_pBudgetBarGraphPanel )
+ {
+ m_pBudgetBarGraphPanel->MarkForDeletion();
+ }
+ m_pBudgetBarGraphPanel = new CBudgetBarGraphPanel( this, "BudgetBarGraph" );
+
+ // Create any new labels we need.
+ int i;
+
+ if ( m_ConfigData.m_BudgetGroupInfo.Count() > m_GraphLabels.Count() )
+ {
+ m_GraphLabels.EnsureCount( m_ConfigData.m_BudgetGroupInfo.Count() );
+ for( i = oldNumBudgetGroups; i < m_ConfigData.m_BudgetGroupInfo.Count(); i++ )
+ {
+ const char *pBudgetGroupName = m_ConfigData.m_BudgetGroupInfo[i].m_Name.String();
+ m_GraphLabels[i] = new vgui::Label( this, pBudgetGroupName, pBudgetGroupName );
+ }
+ }
+ else
+ {
+ while ( m_GraphLabels.Count() > m_ConfigData.m_BudgetGroupInfo.Count() )
+ {
+ m_GraphLabels[m_GraphLabels.Count()-1]->MarkForDeletion();
+ m_GraphLabels.Remove( m_GraphLabels.Count()-1 );
+ }
+ }
+ Assert( m_GraphLabels.Count() == m_ConfigData.m_BudgetGroupInfo.Count() );
+
+
+ // Create new history labels.
+ if ( m_ConfigData.m_HistoryLabelValues.Count() > m_HistoryLabels.Count() )
+ {
+ m_HistoryLabels.EnsureCount( m_ConfigData.m_HistoryLabelValues.Count() );
+ for ( i=oldNumHistoryLabels; i < m_HistoryLabels.Count(); i++ )
+ {
+ m_HistoryLabels[i] = new vgui::Label( this, "history label", "history label" );
+ }
+ }
+ else
+ {
+ while ( m_HistoryLabels.Count() > m_ConfigData.m_HistoryLabelValues.Count() )
+ {
+ m_HistoryLabels[m_HistoryLabels.Count()-1]->MarkForDeletion();
+ m_HistoryLabels.Remove( m_HistoryLabels.Count()-1 );
+ }
+ }
+ SetHistoryLabelText();
+
+
+ // Note: the time lines still use milliseconds for the computations about where to draw them,
+ // but each BudgetGroupDataType_t has its own scale.
+ int nTimeLabels = m_ConfigData.m_flBarGraphRange + data.m_flTimeLabelInterval;
+ if ( data.m_flTimeLabelInterval != 0.0f )
+ {
+ nTimeLabels /= data.m_flTimeLabelInterval;
+ }
+
+ if ( nTimeLabels > m_TimeLabels.Count() )
+ {
+ m_TimeLabels.EnsureCount( nTimeLabels );
+ for( i = oldNumTimeLabels; i < m_TimeLabels.Count(); i++ )
+ {
+ char name[1024];
+ Q_snprintf( name, sizeof( name ), "time_label_%d", i );
+ m_TimeLabels[i] = new vgui::Label( this, name, "TEXT NOT SET YET" );
+ }
+ }
+ else
+ {
+ while ( m_TimeLabels.Count() > nTimeLabels )
+ {
+ m_TimeLabels[m_TimeLabels.Count()-1]->MarkForDeletion();
+ m_TimeLabels.Remove( m_TimeLabels.Count()-1 );
+ }
+ }
+
+ SetTimeLabelText();
+}
+
+void CBaseBudgetPanel::UpdateWindowGeometry()
+{
+ if( m_ConfigData.m_Width > BUDGET_HISTORY_COUNT )
+ {
+ m_ConfigData.m_Width = BUDGET_HISTORY_COUNT;
+ }
+
+ SetPos( m_ConfigData.m_xCoord, m_ConfigData.m_yCoord );
+ SetSize( m_ConfigData.m_Width, m_ConfigData.m_Height );
+}
+
+void CBaseBudgetPanel::PerformLayout()
+{
+ if ( !m_pBudgetHistoryPanel || !m_pBudgetBarGraphPanel )
+ return;
+
+
+ int maxFPSLabelWidth = 0;
+ int i;
+ for( i = 0; i < m_HistoryLabels.Count(); i++ )
+ {
+ int labelWidth, labelHeight;
+ m_HistoryLabels[i]->GetContentSize( labelWidth, labelHeight );
+ if( labelWidth > maxFPSLabelWidth )
+ {
+ maxFPSLabelWidth = labelWidth;
+ }
+ }
+
+ m_pBudgetHistoryPanel->SetRange( 0, m_ConfigData.m_flHistoryRange );
+
+
+ float bottomOfHistoryPercentage = m_ConfigData.m_flBottomOfHistoryFraction;
+ UpdateWindowGeometry();
+ int x, y, totalWidth, totalHeight;
+ int totalHeightMinusTimeLabels;
+ GetPos( x, y );
+ GetSize( totalWidth, totalHeight );
+
+ int maxTimeLabelHeight = 0;
+ for( i = 0; i < m_TimeLabels.Count(); i++ )
+ {
+ int labelWidth, labelHeight;
+ m_TimeLabels[i]->GetContentSize( labelWidth, labelHeight );
+ maxTimeLabelHeight = max( maxTimeLabelHeight, labelHeight );
+ }
+
+ totalHeightMinusTimeLabels = totalHeight - maxTimeLabelHeight;
+
+ m_pBudgetHistoryPanel->SetPos( 0, 0 );
+ int budgetHistoryHeight = totalHeightMinusTimeLabels * bottomOfHistoryPercentage;
+ m_pBudgetHistoryPanel->SetSize( totalWidth - maxFPSLabelWidth,
+ budgetHistoryHeight );
+
+ int maxLabelWidth = 0;
+ for( i = 0; i < m_GraphLabels.Count(); i++ )
+ {
+ int width, height;
+ m_GraphLabels[i]->GetContentSize( width, height );
+ if( maxLabelWidth < width )
+ {
+ maxLabelWidth = width;
+ }
+ }
+
+ m_pBudgetBarGraphPanel->SetPos( maxLabelWidth,
+ totalHeightMinusTimeLabels * bottomOfHistoryPercentage );
+ m_pBudgetBarGraphPanel->SetSize( totalWidth - maxLabelWidth,
+ totalHeightMinusTimeLabels * ( 1 - bottomOfHistoryPercentage ) );
+
+ for( i = 0; i < m_GraphLabels.Count(); i++ )
+ {
+ m_GraphLabels[i]->SetPos( 0,
+ ( bottomOfHistoryPercentage * totalHeightMinusTimeLabels ) +
+ ( i * totalHeightMinusTimeLabels *
+ ( 1 - bottomOfHistoryPercentage ) ) / m_ConfigData.m_BudgetGroupInfo.Count() );
+ // fudge height by 1 for rounding
+ m_GraphLabels[i]->SetSize( maxLabelWidth, 1 + ( totalHeightMinusTimeLabels *
+ ( 1 - bottomOfHistoryPercentage ) ) / m_ConfigData.m_BudgetGroupInfo.Count() );
+ m_GraphLabels[i]->SetContentAlignment( vgui::Label::a_east );
+ }
+
+ // Note: the time lines still use milliseconds for the computations about where to draw them,
+ // but each BudgetGroupDataType_t has its own scale.
+ float fRange = m_ConfigData.m_flBarGraphRange;
+ for( i = 0; i < m_TimeLabels.Count(); i++ )
+ {
+ int labelWidth, labelHeight;
+ m_TimeLabels[i]->GetContentSize( labelWidth, labelHeight );
+ x = maxLabelWidth + ( i * m_ConfigData.m_flTimeLabelInterval ) / fRange * ( totalWidth - maxLabelWidth );
+
+ m_TimeLabels[i]->SetPos( x - ( labelWidth * 0.5 ), totalHeight - labelHeight );
+ m_TimeLabels[i]->SetSize( labelWidth, labelHeight );
+ m_TimeLabels[i]->SetContentAlignment( vgui::Label::a_east );
+ }
+
+
+ // position the fps labels
+ fRange = m_ConfigData.m_flHistoryRange;
+ for( i = 0; i < m_HistoryLabels.Count(); i++ )
+ {
+ int labelWidth, labelHeight;
+ m_HistoryLabels[i]->GetContentSize( labelWidth, labelHeight );
+ y = (fRange != 0) ? budgetHistoryHeight * m_ConfigData.m_HistoryLabelValues[i] / ( float )fRange : 0.0f;
+ int top = ( int )( budgetHistoryHeight - y - 1 - labelHeight * 0.5f );
+ m_HistoryLabels[i]->SetPos( totalWidth - maxFPSLabelWidth, top );
+ m_HistoryLabels[i]->SetSize( labelWidth, labelHeight );
+ m_HistoryLabels[i]->SetContentAlignment( vgui::Label::a_east );
+ }
+}
+
+void CBaseBudgetPanel::ApplySchemeSettings( vgui::IScheme *pScheme )
+{
+ BaseClass::ApplySchemeSettings( pScheme );
+
+ int i;
+ for( i = 0; i < m_ConfigData.m_BudgetGroupInfo.Count(); i++ )
+ {
+ m_GraphLabels[i]->SetFgColor( m_ConfigData.m_BudgetGroupInfo[i].m_Color );
+ m_GraphLabels[i]->SetBgColor( Color( 0, 0, 0, 255 ) );
+ m_GraphLabels[i]->SetPaintBackgroundEnabled( false );
+ m_GraphLabels[i]->SetFont( pScheme->GetFont( "BudgetLabel", IsProportional() ) );
+ if ( m_bDedicated )
+ {
+ m_GraphLabels[i]->SetBgColor( pScheme->GetColor( "ControlBG", Color( 0, 0, 0, 255 ) ) );
+ }
+ }
+
+ for( i = 0; i < m_TimeLabels.Count(); i++ )
+ {
+ int red, green, blue, alpha;
+ red = green = blue = alpha = 255;
+ m_TimeLabels[i]->SetFgColor( Color( red, green, blue, alpha ) );
+ m_TimeLabels[i]->SetBgColor( Color( 0, 0, 0, 255 ) );
+ m_TimeLabels[i]->SetPaintBackgroundEnabled( false );
+ m_TimeLabels[i]->SetFont( pScheme->GetFont( "BudgetLabel", IsProportional() ) );
+ if ( m_bDedicated )
+ {
+ m_TimeLabels[i]->SetBgColor( pScheme->GetColor( "ControlBG", Color( 0, 0, 0, 255 ) ) );
+ }
+ }
+
+ for( i = 0; i < m_HistoryLabels.Count(); i++ )
+ {
+ int red, green, blue, alpha;
+ red = green = blue = alpha = 255;
+ m_HistoryLabels[i]->SetFgColor( Color( red, green, blue, alpha ) );
+ m_HistoryLabels[i]->SetBgColor( Color( 0, 0, 0, 255 ) );
+ m_HistoryLabels[i]->SetPaintBackgroundEnabled( false );
+ m_HistoryLabels[i]->SetFont( pScheme->GetFont( "BudgetLabel", IsProportional() ) );
+ if ( m_bDedicated )
+ {
+ m_HistoryLabels[i]->SetBgColor( pScheme->GetColor( "ControlBG", Color( 0, 0, 0, 255 ) ) );
+ }
+ }
+
+ m_hFont = pScheme->GetFont( "DefaultFixed" );
+
+ if ( m_bDedicated )
+ {
+ SetBgColor( pScheme->GetColor( "ControlBG", Color( 0, 0, 0, 255 ) ) );
+ }
+ SetPaintBackgroundEnabled( true );
+}
+
+void CBaseBudgetPanel::PaintBackground()
+{
+ if ( m_bDedicated )
+ {
+ m_pBudgetBarGraphPanel->SetBgColor( GetBgColor() );
+ }
+ else
+ {
+ SetBgColor( Color( 0, 0, 0, m_ConfigData.m_flBackgroundAlpha ) );
+ }
+ BaseClass::PaintBackground();
+}
+
+void CBaseBudgetPanel::Paint()
+{
+ m_pBudgetHistoryPanel->SetData( &m_BudgetGroupTimes[0].m_Time[0], GetNumCachedBudgetGroups(), BUDGET_HISTORY_COUNT, m_BudgetHistoryOffset );
+ BaseClass::Paint();
+}
+
+void CBaseBudgetPanel::MarkForFullRepaint()
+{
+ Repaint();
+ m_pBudgetHistoryPanel->Repaint();
+ m_pBudgetBarGraphPanel->Repaint();
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CBaseBudgetPanel::GetGraphLabelScreenSpaceTopAndBottom( int id, int &top, int &bottom )
+{
+ int x = 0;
+ int y = 0;
+ m_GraphLabels[id]->LocalToScreen( x, y );
+ top = y;
+ bottom = top + m_GraphLabels[id]->GetTall();
+}
+
diff --git a/common/vgui/vgui_basebudgetpanel.h b/common/vgui/vgui_basebudgetpanel.h
new file mode 100644
index 0000000..27115bc
--- /dev/null
+++ b/common/vgui/vgui_basebudgetpanel.h
@@ -0,0 +1,145 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+//=============================================================================//
+
+#ifndef VGUI_BASEBUDGETPANEL_H
+#define VGUI_BASEBUDGETPANEL_H
+
+#ifdef _WIN32
+#pragma once
+#endif
+
+
+#include <vgui_controls/Frame.h>
+#include <vgui/IScheme.h>
+#include "vgui_budgethistorypanel.h"
+#include "vgui_budgetbargraphpanel.h"
+#include "utlsymbol.h"
+//#include "hudelement.h"
+
+
+#define BUDGET_HISTORY_COUNT 1024
+
+class CBudgetGroupInfo
+{
+public:
+ CUtlSymbol m_Name;
+ Color m_Color;
+};
+
+// Derived classes supply this configuration data with OnConfigDataChanged.
+class CBudgetPanelConfigData
+{
+public:
+ // NOTE: nothing can ever be removed from this list once you've called
+ // OnConfigDataChanged. Elements can only be added to it.
+ CUtlVector<CBudgetGroupInfo> m_BudgetGroupInfo;
+
+ float m_flHistoryRange;
+ float m_flBottomOfHistoryFraction;
+ CUtlVector<float> m_HistoryLabelValues; // A label will be placed at each of these values.
+
+ // How much range the bar graph represents.
+ float m_flBarGraphRange;
+
+ // Controls how many labels are shown.
+ float m_flTimeLabelInterval;
+ int m_nLinesPerTimeLabel; // How many vertical lines per time label?
+
+ // How translucent is the background.
+ float m_flBackgroundAlpha;
+
+ // Where to position it on the screen.
+ int m_xCoord;
+ int m_yCoord;
+ int m_Width;
+ int m_Height;
+};
+
+
+class CBaseBudgetPanel : public vgui::Panel
+{
+ typedef vgui::Panel BaseClass;
+
+public:
+ CBaseBudgetPanel( vgui::Panel *pParent, const char *pElementName );
+ ~CBaseBudgetPanel();
+
+ // This should be called when starting up and whenever this data changes.
+ void OnConfigDataChanged( const CBudgetPanelConfigData &data );
+
+ // Call this to reset everything.
+ virtual void ResetAll();
+
+ // The derived class should implement this and set the text in the time labels.
+ virtual void SetTimeLabelText() {}
+ virtual void SetHistoryLabelText() {}
+
+ virtual void ApplySchemeSettings( vgui::IScheme *pScheme );
+ virtual void Paint();
+ virtual void PaintBackground();
+ virtual void PerformLayout();
+ void MarkAsDedicatedServer() { m_bDedicated = true; } // plays nicer as part of a vgui window setup
+ bool IsDedicated() const { return m_bDedicated; }
+
+ const double *GetBudgetGroupData( int &nGroups, int &nSamplesPerGroup, int &nSampleOffset ) const;
+
+ void GetGraphLabelScreenSpaceTopAndBottom( int id, int &top, int &bottom );
+
+ // What percentage is the specified value of the (bargraph) range?
+ float GetBudgetGroupPercent( float value );
+
+ // Get the current config data.
+ const CBudgetPanelConfigData& GetConfigData() const;
+
+ // Returns the number of budget groups in the last OnConfigDataChanged call.
+ int GetNumCachedBudgetGroups() const;
+
+ // (Used by dedicated server, mark everything for a repaint).
+ void MarkForFullRepaint();
+
+protected:
+ void UpdateWindowGeometry();
+ void ClearTimesForAllGroupsForThisFrame( void );
+ void ClearAllTimesForGroup( int groupID );
+ void Rebuild( const CBudgetPanelConfigData &data );
+
+protected:
+ int m_BudgetHistoryOffset;
+
+ // This defines all the positioning, label names, etc.
+ CBudgetPanelConfigData m_ConfigData;
+
+ CUtlVector<vgui::Label *> m_GraphLabels;
+ CUtlVector<vgui::Label *> m_TimeLabels;
+ CUtlVector<vgui::Label *> m_HistoryLabels;
+
+ CBudgetHistoryPanel *m_pBudgetHistoryPanel;
+ CBudgetBarGraphPanel *m_pBudgetBarGraphPanel;
+
+ struct BudgetGroupTimeData_t
+ {
+ double m_Time[BUDGET_HISTORY_COUNT];
+ };
+ CUtlVector<BudgetGroupTimeData_t> m_BudgetGroupTimes; // [m_CachedNumBudgetGroups][BUDGET_HISTORY_COUNT]
+ int m_CachedNumTimeLabels;
+ vgui::HFont m_hFont;
+
+ bool m_bDedicated;
+};
+
+
+inline const CBudgetPanelConfigData& CBaseBudgetPanel::GetConfigData() const
+{
+ return m_ConfigData;
+}
+
+inline int CBaseBudgetPanel::GetNumCachedBudgetGroups() const
+{
+ return m_ConfigData.m_BudgetGroupInfo.Count();
+}
+
+
+#endif // VGUI_BASEBUDGETPANEL_H
diff --git a/common/vgui/vgui_budgetbargraphpanel.cpp b/common/vgui/vgui_budgetbargraphpanel.cpp
new file mode 100644
index 0000000..2db8fad
--- /dev/null
+++ b/common/vgui/vgui_budgetbargraphpanel.cpp
@@ -0,0 +1,252 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+//=============================================================================//
+
+#include "vgui_budgetbargraphpanel.h"
+#include "vgui_basebudgetpanel.h"
+#include <vgui/ISurface.h>
+#include "vgui_controls/Label.h"
+#include "convar.h"
+
+// memdbgon must be the last include file in a .cpp file!!!
+#include "tier0/memdbgon.h"
+
+ConVar budget_bargraph_background_alpha( "budget_bargraph_background_alpha", "128", FCVAR_ARCHIVE, "how translucent the budget panel is" );
+
+ConVar budget_peaks_window( "budget_peaks_window", "30", FCVAR_ARCHIVE, "number of frames to look at when figuring out peak frametimes" );
+ConVar budget_averages_window( "budget_averages_window", "30", FCVAR_ARCHIVE, "number of frames to look at when figuring out average frametimes" );
+ConVar budget_show_peaks( "budget_show_peaks", "1", FCVAR_ARCHIVE, "enable/disable peaks in the budget panel" );
+ConVar budget_show_averages( "budget_show_averages", "0", FCVAR_ARCHIVE, "enable/disable averages in the budget panel" );
+
+
+CBudgetBarGraphPanel::CBudgetBarGraphPanel( CBaseBudgetPanel *pParent, const char *pPanelName ) :
+ BaseClass( pParent, pPanelName )
+{
+ m_pBudgetPanel = pParent;
+
+ SetProportional( false );
+ SetKeyBoardInputEnabled( false );
+ SetMouseInputEnabled( false );
+ SetVisible( true );
+
+ SetPaintBackgroundEnabled( true );
+ SetBgColor( Color( 255, 0, 0, budget_bargraph_background_alpha.GetInt() ) );
+}
+
+CBudgetBarGraphPanel::~CBudgetBarGraphPanel()
+{
+}
+
+void CBudgetBarGraphPanel::GetBudgetGroupTopAndBottom( int id, int &top, int &bottom )
+{
+ // Ask where the corresponding graph label is.
+ m_pBudgetPanel->GetGraphLabelScreenSpaceTopAndBottom( id, top, bottom );
+ int tall = bottom - top;
+
+ int x = 0;
+ ScreenToLocal( x, top );
+
+ bottom = top + tall;
+}
+
+void CBudgetBarGraphPanel::DrawBarAtIndex( int id, float percent )
+{
+ int panelWidth, panelHeight;
+ GetSize( panelWidth, panelHeight );
+
+ int top, bottom;
+ GetBudgetGroupTopAndBottom( id, top, bottom );
+
+ int left = 0;
+ int right = panelWidth * percent;
+
+ int red, green, blue, alpha;
+ m_pBudgetPanel->GetConfigData().m_BudgetGroupInfo[id].m_Color.GetColor( red, green, blue, alpha );
+
+ // DrawFilledRect is panel relative
+ vgui::surface()->DrawSetColor( 0, 0, 0, alpha );
+ vgui::surface()->DrawFilledRect( left, top, right+2, bottom );
+
+ vgui::surface()->DrawSetColor( 255, 255, 255, alpha );
+ vgui::surface()->DrawFilledRect( left, top+1, right+1, bottom-1 );
+
+ vgui::surface()->DrawSetColor( red, green, blue, alpha );
+ vgui::surface()->DrawFilledRect( left, top+2, right, bottom-2 );
+}
+
+void CBudgetBarGraphPanel::DrawTickAtIndex( int id, float percent, int red, int green, int blue, int alpha )
+{
+ if( percent > 1.0f )
+ {
+ percent = 1.0f;
+ }
+ int panelWidth, panelHeight;
+ GetSize( panelWidth, panelHeight );
+
+ int top, bottom;
+ GetBudgetGroupTopAndBottom( id, top, bottom );
+
+ int right = ( int )( panelWidth * percent + 1.0f );
+ int left = right - 2;
+
+ // DrawFilledRect is panel relative
+ vgui::surface()->DrawSetColor( 0, 0, 0, alpha );
+ vgui::surface()->DrawFilledRect( left-2, top, right+2, bottom );
+
+ vgui::surface()->DrawSetColor( 255, 255, 255, alpha );
+ vgui::surface()->DrawFilledRect( left-1, top+1, right+1, bottom-1 );
+
+ vgui::surface()->DrawSetColor( red, green, blue, alpha );
+ vgui::surface()->DrawFilledRect( left, top+2, right, bottom-2 );
+}
+
+void CBudgetBarGraphPanel::DrawTimeLines( void )
+{
+ int panelWidth, panelHeight;
+ GetSize( panelWidth, panelHeight );
+ int i;
+ int left, right, top, bottom;
+ top = 0;
+ bottom = panelHeight;
+
+ const CBudgetPanelConfigData &config = m_pBudgetPanel->GetConfigData();
+
+ float flValueInterval = config.m_flTimeLabelInterval;
+ if ( config.m_nLinesPerTimeLabel != 0.0f )
+ {
+ flValueInterval = config.m_flTimeLabelInterval / config.m_nLinesPerTimeLabel;
+ }
+
+ int nTotalLines = config.m_flBarGraphRange;
+ if ( flValueInterval != 0.0f )
+ {
+ nTotalLines /= flValueInterval;
+ }
+ nTotalLines += 2;
+
+ for( i = 0; i < nTotalLines; i++ )
+ {
+ int alpha;
+ if( i % (config.m_nLinesPerTimeLabel*2) == 0 )
+ {
+ alpha = 150;
+ }
+ else if( i % config.m_nLinesPerTimeLabel == 0 )
+ {
+ alpha = 100;
+ }
+ else
+ {
+ alpha = 50;
+ }
+
+ float flTemp = ( config.m_flBarGraphRange != 0.0f ) ? ( flValueInterval / config.m_flBarGraphRange ) : flValueInterval;
+ left = -0.5f + panelWidth * ( float )( i * flTemp );
+ right = left + 1;
+
+ vgui::surface()->DrawSetColor( 0, 0, 0, alpha );
+ vgui::surface()->DrawFilledRect( left-1, top, right+1, bottom );
+
+ vgui::surface()->DrawSetColor( 255, 255, 255, alpha );
+ vgui::surface()->DrawFilledRect( left, top+1, right, bottom-1 );
+ }
+}
+
+void CBudgetBarGraphPanel::DrawInstantaneous()
+{
+ int nGroups, nSamplesPerGroup, nSampleOffset;
+ const double *pBudgetGroupTimes = m_pBudgetPanel->GetBudgetGroupData( nGroups, nSamplesPerGroup, nSampleOffset );
+ if( !pBudgetGroupTimes )
+ {
+ return;
+ }
+
+ int i;
+ for( i = 0; i < nGroups; i++ )
+ {
+ float percent = m_pBudgetPanel->GetBudgetGroupPercent( pBudgetGroupTimes[nSamplesPerGroup * i + nSampleOffset] );
+ DrawBarAtIndex( i, percent );
+ }
+}
+
+void CBudgetBarGraphPanel::DrawPeaks()
+{
+ int nGroups, nSamplesPerGroup, nSampleOffset;
+ const double *pBudgetGroupTimes = m_pBudgetPanel->GetBudgetGroupData( nGroups, nSamplesPerGroup, nSampleOffset );
+ if( !pBudgetGroupTimes )
+ {
+ return;
+ }
+ int numSamples = budget_peaks_window.GetInt();
+ int i;
+ for( i = 0; i < nGroups; i++ )
+ {
+ double max = 0;
+ int j;
+ for( j = 0; j < numSamples; j++ )
+ {
+ double tmp;
+ int offset = ( nSampleOffset - j + BUDGET_HISTORY_COUNT ) % BUDGET_HISTORY_COUNT;
+ tmp = pBudgetGroupTimes[i * nSamplesPerGroup + offset];
+ if( tmp > max )
+ {
+ max = tmp;
+ }
+ }
+ float percent = m_pBudgetPanel->GetBudgetGroupPercent( max );
+ DrawTickAtIndex( i, percent, 255, 0, 0, 255 );
+ }
+}
+
+void CBudgetBarGraphPanel::DrawAverages()
+{
+ int nGroups, nSamplesPerGroup, nSampleOffset;
+ const double *pBudgetGroupTimes = m_pBudgetPanel->GetBudgetGroupData( nGroups, nSamplesPerGroup, nSampleOffset );
+ if( !pBudgetGroupTimes )
+ {
+ return;
+ }
+ int numSamples = budget_averages_window.GetInt();
+ int i;
+ for( i = 0; i < nGroups; i++ )
+ {
+ int red, green, blue, alpha;
+ m_pBudgetPanel->GetConfigData().m_BudgetGroupInfo[i].m_Color.GetColor( red, green, blue, alpha );
+
+ double sum = 0;
+ int j;
+ for( j = 0; j < numSamples; j++ )
+ {
+ int offset = ( nSampleOffset - j + BUDGET_HISTORY_COUNT ) % BUDGET_HISTORY_COUNT;
+ sum += pBudgetGroupTimes[i * nSamplesPerGroup + offset];
+ }
+ sum *= ( 1.0f / numSamples );
+ float percent = m_pBudgetPanel->GetBudgetGroupPercent( sum );
+ DrawTickAtIndex( i, percent, red, green, blue, alpha );
+ }
+}
+
+void CBudgetBarGraphPanel::Paint( void )
+{
+ int width, height;
+ GetSize( width, height );
+
+ if ( !m_pBudgetPanel->IsDedicated() )
+ {
+ SetBgColor( Color( 255, 0, 0, budget_bargraph_background_alpha.GetInt() ) );
+ }
+
+ DrawTimeLines();
+ DrawInstantaneous();
+ if( budget_show_peaks.GetBool() )
+ {
+ DrawPeaks();
+ }
+ if( budget_show_averages.GetBool() )
+ {
+ DrawAverages();
+ }
+}
+
diff --git a/common/vgui/vgui_budgetbargraphpanel.h b/common/vgui/vgui_budgetbargraphpanel.h
new file mode 100644
index 0000000..ef9da30
--- /dev/null
+++ b/common/vgui/vgui_budgetbargraphpanel.h
@@ -0,0 +1,43 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+//=============================================================================//
+
+#ifndef VGUI_BUDGETBARGRAPHPANEL_H
+#define VGUI_BUDGETBARGRAPHPANEL_H
+#ifdef _WIN32
+#pragma once
+#endif
+
+#include <vgui_controls/Frame.h>
+
+
+class CBaseBudgetPanel;
+
+
+class CBudgetBarGraphPanel : public vgui::Panel
+{
+ typedef vgui::Panel BaseClass;
+
+public:
+ CBudgetBarGraphPanel( CBaseBudgetPanel *pParent, const char *pPanelName );
+ ~CBudgetBarGraphPanel();
+ virtual void Paint( void );
+
+private:
+
+ void DrawInstantaneous();
+ void DrawPeaks();
+ void DrawAverages();
+ void DrawTimeLines( void );
+ void GetBudgetGroupTopAndBottom( int id, int &top, int &bottom );
+ void DrawBarAtIndex( int id, float percent );
+ void DrawTickAtIndex( int id, float percent, int red, int green, int blue, int alpha );
+
+private:
+
+ CBaseBudgetPanel *m_pBudgetPanel;
+};
+
+#endif // VGUI_BUDGETBARGRAPHPANEL_H
diff --git a/common/vgui/vgui_budgethistorypanel.cpp b/common/vgui/vgui_budgethistorypanel.cpp
new file mode 100644
index 0000000..e9b42fd
--- /dev/null
+++ b/common/vgui/vgui_budgethistorypanel.cpp
@@ -0,0 +1,136 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+//=============================================================================//
+
+#include "vgui_basebudgetpanel.h"
+#include "vgui_budgethistorypanel.h"
+#include <vgui/ISurface.h>
+#include "tier0/vprof.h"
+#include "convar.h"
+
+// memdbgon must be the last include file in a .cpp file!!!
+#include "tier0/memdbgon.h"
+
+ConVar budget_show_history( "budget_show_history", "1", FCVAR_ARCHIVE, "turn history graph off and on. . good to turn off on low end" );
+ConVar budget_history_numsamplesvisible( "budget_history_numsamplesvisible", "100", FCVAR_ARCHIVE, "number of samples to draw in the budget history window. The lower the better as far as rendering overhead of the budget panel" );
+
+CBudgetHistoryPanel::CBudgetHistoryPanel( CBaseBudgetPanel *pParent, const char *pPanelName ) :
+ BaseClass( pParent, pPanelName )
+{
+ m_pBudgetPanel = pParent;
+
+ m_nSamplesPerGroup = 0;
+ SetProportional( false );
+ SetKeyBoardInputEnabled( false );
+ SetMouseInputEnabled( false );
+ SetVisible( true );
+ SetPaintBackgroundEnabled( false );
+ SetBgColor( Color( 0, 0, 0, 255 ) );
+
+ // For some reason, vgui::Frame likes to set the minimum size to (128,66) and we may want to get smaller.
+ SetMinimumSize( 0, 0 );
+}
+
+CBudgetHistoryPanel::~CBudgetHistoryPanel()
+{
+}
+
+void CBudgetHistoryPanel::Paint()
+{
+ if( m_nSamplesPerGroup == 0 )
+ {
+ // SetData hasn't been called yet.
+ return;
+ }
+ if( !budget_show_history.GetBool() )
+ {
+ return;
+ }
+
+ int width, height;
+ GetSize( width, height );
+
+ int startID = m_nSampleOffset - width;
+ while( startID < 0 )
+ {
+ startID += m_nSamplesPerGroup;
+ }
+ int endID = startID + width;
+ int numSamplesVisible = budget_history_numsamplesvisible.GetInt();
+ int xOffset = 0;
+ if( endID - startID > numSamplesVisible )
+ {
+ xOffset = ( endID - numSamplesVisible ) - startID;
+ startID = endID - numSamplesVisible;
+ }
+ static CUtlVector<vgui::IntRect> s_Rects;
+ static CUtlVector<float> s_CurrentHeight;
+ s_Rects.EnsureCount( ( endID - startID ) );
+ s_CurrentHeight.EnsureCount( endID - startID );
+ memset( &s_CurrentHeight[0], 0, sizeof( float ) * ( endID - startID ) );
+ int j;
+ float ooRangeMaxMinusMin = 1.0f / ( m_fRangeMax - m_fRangeMin );
+ for( j = 0; j < m_nGroups; j++ )
+ {
+ int i;
+ for( i = startID; i < endID; i++ )
+ {
+ int sampleOffset = i % m_nSamplesPerGroup;
+ int left = i - startID + xOffset;
+ int right = left + 1;
+ float &curHeight = s_CurrentHeight[i - startID];
+ int bottom = ( curHeight - m_fRangeMin ) * ooRangeMaxMinusMin * height;
+ curHeight += m_pData[sampleOffset + m_nSamplesPerGroup * j];
+ int top = ( curHeight - m_fRangeMin ) * ooRangeMaxMinusMin * height;
+ bottom = height - bottom - 1;
+ top = height - top - 1;
+ vgui::IntRect& rect = s_Rects[( i - startID )];
+ rect.x0 = left;
+ rect.x1 = right;
+ rect.y0 = top;
+ rect.y1 = bottom;
+ }
+
+ int red, green, blue, alpha;
+ m_pBudgetPanel->GetConfigData().m_BudgetGroupInfo[j].m_Color.GetColor( red, green, blue, alpha );
+
+ vgui::surface()->DrawSetColor( red, green, blue, alpha );
+ vgui::surface()->DrawFilledRectArray( &s_Rects[0], endID - startID );
+ }
+
+ for ( int i=0; i < m_pBudgetPanel->GetConfigData().m_HistoryLabelValues.Count(); i++ )
+ {
+ DrawBudgetLine( m_pBudgetPanel->GetConfigData().m_HistoryLabelValues[i] );
+ }
+}
+
+// Only call this from Paint!!!!!
+void CBudgetHistoryPanel::DrawBudgetLine( float val )
+{
+ int width, height;
+ GetSize( width, height );
+ double y = ( val - m_fRangeMin ) * ( 1.0f / ( m_fRangeMax - m_fRangeMin ) ) * height;
+ int bottom = ( int )( height - y - 1 + .5 );
+ int top = ( int )( height - y - 1 - .5 );
+ vgui::surface()->DrawSetColor( 0, 0, 0, 255 );
+ vgui::surface()->DrawFilledRect( 0, top-1, width, bottom+1 );
+ vgui::surface()->DrawSetColor( 255, 255, 255, 255 );
+ vgui::surface()->DrawFilledRect( 0, top, width, bottom );
+}
+
+
+void CBudgetHistoryPanel::SetData( double *pData, int nGroups, int nSamplesPerGroup, int nSampleOffset )
+{
+ m_pData = pData;
+ m_nGroups = nGroups;
+ m_nSamplesPerGroup = nSamplesPerGroup;
+ m_nSampleOffset = nSampleOffset;
+}
+
+void CBudgetHistoryPanel::SetRange( float fMin, float fMax )
+{
+ m_fRangeMin = fMin;
+ m_fRangeMax = fMax;
+}
diff --git a/common/vgui/vgui_budgethistorypanel.h b/common/vgui/vgui_budgethistorypanel.h
new file mode 100644
index 0000000..0436362
--- /dev/null
+++ b/common/vgui/vgui_budgethistorypanel.h
@@ -0,0 +1,48 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+//=============================================================================//
+
+#ifndef VGUI_BudgetHistoryPanel_H
+#define VGUI_BudgetHistoryPanel_H
+#ifdef _WIN32
+#pragma once
+#endif
+
+#include <vgui_controls/Frame.h>
+
+class CBaseBudgetPanel;
+
+class CBudgetHistoryPanel : public vgui::Panel
+{
+ typedef vgui::Panel BaseClass;
+
+public:
+ CBudgetHistoryPanel( CBaseBudgetPanel *pParent, const char *pPanelName );
+ ~CBudgetHistoryPanel();
+ void SetData( double *pData, int numCategories, int numItems, int offsetIntoData );
+ void SetRange( float fMin, float fMax );
+
+
+protected:
+
+ void Paint();
+
+private:
+
+ void DrawBudgetLine( float val );
+
+private:
+
+ CBaseBudgetPanel *m_pBudgetPanel;
+
+ double *m_pData;
+ int m_nGroups;
+ int m_nSamplesPerGroup;
+ int m_nSampleOffset;
+ float m_fRangeMin;
+ float m_fRangeMax;
+};
+
+#endif // VGUI_BudgetHistoryPanel_H
diff --git a/common/vgui/vgui_budgetpanelshared.cpp b/common/vgui/vgui_budgetpanelshared.cpp
new file mode 100644
index 0000000..0cc075a
--- /dev/null
+++ b/common/vgui/vgui_budgetpanelshared.cpp
@@ -0,0 +1,263 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+//=============================================================================//
+
+#include "vgui_budgetpanelshared.h"
+#include "vgui/IVGui.h"
+#include "vgui/ILocalize.h"
+#include "vgui/ISurface.h"
+#include "vgui_controls/Label.h"
+#include "ivprofexport.h"
+#include "convar.h"
+#include "mathlib/mathlib.h"
+
+// NOTE: This has to be the last file included!
+#include "tier0/memdbgon.h"
+
+
+#ifdef VPROF_ENABLED
+
+#ifdef BUDGET_ADMIN_SERVER
+ #define BUDGET_CVAR_CALLBACK NULL
+#else
+ #define BUDGET_CVAR_CALLBACK PanelGeometryChangedCallBack
+#endif
+
+
+// Global ConVars.
+ConVar budget_history_range_ms( "budget_history_range_ms", "66.666666667", FCVAR_ARCHIVE, "budget history range in milliseconds", BUDGET_CVAR_CALLBACK );
+ConVar budget_panel_bottom_of_history_fraction( "budget_panel_bottom_of_history_fraction", ".25", FCVAR_ARCHIVE, "number between 0 and 1", BUDGET_CVAR_CALLBACK );
+ConVar budget_bargraph_range_ms( "budget_bargraph_range_ms", "16.6666666667", FCVAR_ARCHIVE, "budget bargraph range in milliseconds", BUDGET_CVAR_CALLBACK );
+ConVar budget_background_alpha( "budget_background_alpha", "128", FCVAR_ARCHIVE, "how translucent the budget panel is" );
+
+ConVar budget_panel_x( "budget_panel_x", "0", FCVAR_ARCHIVE, "number of pixels from the left side of the game screen to draw the budget panel", BUDGET_CVAR_CALLBACK );
+ConVar budget_panel_y( "budget_panel_y", "50", FCVAR_ARCHIVE, "number of pixels from the top side of the game screen to draw the budget panel", BUDGET_CVAR_CALLBACK );
+ConVar budget_panel_width( "budget_panel_width", "512", FCVAR_ARCHIVE, "width in pixels of the budget panel", BUDGET_CVAR_CALLBACK );
+ConVar budget_panel_height( "budget_panel_height", "384", FCVAR_ARCHIVE, "height in pixels of the budget panel", BUDGET_CVAR_CALLBACK );
+
+
+static CUtlVector<IVProfExport::CExportedBudgetGroupInfo> g_TempBudgetGroupSpace;
+
+
+double CBudgetPanelShared::g_fFrameTimeLessBudget = 0;
+double CBudgetPanelShared::g_fFrameRate = 0;
+
+static CFastTimer g_TimerLessBudget;
+static CBudgetPanelShared *g_pBudgetPanelShared = NULL;
+extern IVProfExport *g_pVProfExport;
+
+
+void PanelGeometryChangedCallBack( IConVar *var, const char *pOldString, float flOldValue )
+{
+ // screw it . . rebuild the whole damn thing.
+ // GetBudgetPanel()->InvalidateLayout();
+ if ( g_pBudgetPanelShared )
+ {
+ g_pBudgetPanelShared->SendConfigDataToBase();
+ }
+}
+
+
+// -------------------------------------------------------------------------------------------------------------------- //
+// CBudgetPanelShared implementation.
+// -------------------------------------------------------------------------------------------------------------------- //
+
+CBudgetPanelShared::CBudgetPanelShared( vgui::Panel *pParent, const char *pElementName, int budgetFlagsFilter )
+ : BaseClass( pParent, pElementName )
+{
+ Assert( !g_pBudgetPanelShared );
+ g_pBudgetPanelShared = this;
+
+ if ( g_pVProfExport )
+ g_pVProfExport->SetBudgetFlagsFilter( budgetFlagsFilter );
+
+ SendConfigDataToBase();
+ SetZPos( 1001 );
+ SetVisible( false );
+ vgui::ivgui()->AddTickSignal( GetVPanel() );
+ SetPostChildPaintEnabled( true ); // so we can turn vprof back on
+}
+
+
+CBudgetPanelShared::~CBudgetPanelShared()
+{
+ Assert( g_pBudgetPanelShared == this );
+ g_pBudgetPanelShared = NULL;
+}
+
+
+void CBudgetPanelShared::OnNumBudgetGroupsChanged()
+{
+ SendConfigDataToBase();
+}
+
+
+void CBudgetPanelShared::SetupCustomConfigData( CBudgetPanelConfigData &data )
+{
+ data.m_xCoord = budget_panel_x.GetInt();
+ data.m_yCoord = budget_panel_y.GetInt();
+ data.m_Width = budget_panel_width.GetInt();
+ data.m_Height = budget_panel_height.GetInt();
+}
+
+
+void CBudgetPanelShared::SendConfigDataToBase()
+{
+ // Setup all the data.
+ CBudgetPanelConfigData data;
+
+ // Copy the budget group names in.
+ int nGroups = 0;
+ if ( g_pVProfExport )
+ {
+ nGroups = g_pVProfExport->GetNumBudgetGroups();
+
+ // Make sure we have space to store the results.
+ if ( g_TempBudgetGroupSpace.Count() < nGroups )
+ g_TempBudgetGroupSpace.SetSize( nGroups );
+
+ g_pVProfExport->GetBudgetGroupInfos( g_TempBudgetGroupSpace.Base() );
+ }
+
+ data.m_BudgetGroupInfo.SetSize( nGroups );
+ for ( int i=0; i < nGroups; i++ )
+ {
+ data.m_BudgetGroupInfo[i].m_Name = g_TempBudgetGroupSpace[i].m_pName;
+ data.m_BudgetGroupInfo[i].m_Color = g_TempBudgetGroupSpace[i].m_Color;
+ }
+
+ data.m_HistoryLabelValues.AddToTail( 1000.0 / 20 );
+ data.m_HistoryLabelValues.AddToTail( 1000.0 / 30 );
+ data.m_HistoryLabelValues.AddToTail( 1000.0 / 60 );
+
+ // Copy all the cvars in.
+ data.m_flHistoryRange = budget_history_range_ms.GetFloat();
+ data.m_flBottomOfHistoryFraction = budget_panel_bottom_of_history_fraction.GetFloat();
+
+ data.m_flBarGraphRange = budget_bargraph_range_ms.GetFloat();
+ data.m_flTimeLabelInterval = 5;
+ data.m_nLinesPerTimeLabel = 5;
+
+ data.m_flBackgroundAlpha = budget_background_alpha.GetFloat();
+
+ SetupCustomConfigData( data );
+
+ // Send the config data to the base class.
+ OnConfigDataChanged( data );
+}
+
+
+void CBudgetPanelShared::DrawColoredText(
+ vgui::HFont font,
+ int x, int y,
+ int r, int g, int b, int a,
+ const char *pText,
+ ... )
+{
+ char msg[4096];
+ va_list marker;
+ va_start( marker, pText );
+ _vsnprintf( msg, sizeof( msg ), pText, marker );
+ va_end( marker );
+
+ wchar_t unicodeStr[4096];
+ int nChars = g_pVGuiLocalize->ConvertANSIToUnicode( msg, unicodeStr, sizeof( unicodeStr ) );
+
+ vgui::surface()->DrawSetTextFont( font );
+ vgui::surface()->DrawSetTextColor( r, g, b, a );
+ vgui::surface()->DrawSetTextPos( x, y );
+ vgui::surface()->DrawPrintText( unicodeStr, nChars );
+}
+
+
+void CBudgetPanelShared::PaintBackground()
+{
+ if ( g_pVProfExport )
+ g_pVProfExport->PauseProfile();
+
+ BaseClass::PaintBackground();
+}
+
+
+void CBudgetPanelShared::Paint()
+{
+ if( m_BudgetGroupTimes.Count() == 0 )
+ {
+ return;
+ }
+
+ static bool TimerInitialized = false;
+ if( !TimerInitialized )
+ {
+ g_TimerLessBudget.Start();
+ TimerInitialized=true;
+ }
+
+ g_TimerLessBudget.End();
+
+ BaseClass::Paint();
+
+ g_fFrameTimeLessBudget = ( g_TimerLessBudget.GetDuration().GetSeconds() );
+ g_fFrameRate = 1.0 / g_fFrameTimeLessBudget;
+}
+
+void CBudgetPanelShared::PostChildPaint()
+{
+ g_TimerLessBudget.Start();
+
+ if ( g_pVProfExport )
+ g_pVProfExport->ResumeProfile();
+}
+
+void CBudgetPanelShared::SnapshotVProfHistory( float filteredtime )
+{
+ m_BudgetHistoryOffset = ( m_BudgetHistoryOffset + 1 ) % BUDGET_HISTORY_COUNT;
+ ClearTimesForAllGroupsForThisFrame();
+
+ if ( g_pVProfExport )
+ {
+ if ( GetNumCachedBudgetGroups() != g_pVProfExport->GetNumBudgetGroups() )
+ {
+ SendConfigDataToBase();
+ }
+
+ float times[IVProfExport::MAX_BUDGETGROUP_TIMES];
+ g_pVProfExport->GetBudgetGroupTimes( times );
+
+ for ( int groupID=0; groupID < GetNumCachedBudgetGroups(); groupID++ )
+ {
+ float dt = times[groupID];
+ // Hack: add filtered time into unnaccounted group...
+ if ( groupID == VPROF_BUDGET_GROUP_ID_UNACCOUNTED )
+ {
+ dt += 1000.0f * filteredtime;
+ }
+ m_BudgetGroupTimes[groupID].m_Time[m_BudgetHistoryOffset] = dt;
+ }
+ }
+}
+
+
+void CBudgetPanelShared::SetTimeLabelText()
+{
+ for ( int i=0; i < m_TimeLabels.Count(); i++ )
+ {
+ char text[512];
+ Q_snprintf( text, sizeof( text ), "%dms", (int)( i * GetConfigData().m_flTimeLabelInterval ) );
+ m_TimeLabels[i]->SetText( text );
+ }
+}
+
+
+void CBudgetPanelShared::SetHistoryLabelText()
+{
+ Assert( m_HistoryLabels.Count() == 3 );
+ m_HistoryLabels[0]->SetText( "20 fps (50 ms)" );
+ m_HistoryLabels[1]->SetText( "30 fps (33 1/3 ms)" );
+ m_HistoryLabels[2]->SetText( "60 fps (16 2/3 ms)" );
+}
+
+
+#endif // VPROF_ENABLED
diff --git a/common/vgui/vgui_budgetpanelshared.h b/common/vgui/vgui_budgetpanelshared.h
new file mode 100644
index 0000000..5713604
--- /dev/null
+++ b/common/vgui/vgui_budgetpanelshared.h
@@ -0,0 +1,71 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+//===========================================================================//
+
+#ifndef VGUI_BUDGETPANELSHARED_H
+#define VGUI_BUDGETPANELSHARED_H
+
+#ifdef _WIN32
+#pragma once
+#endif
+
+
+#include "vgui_basebudgetpanel.h"
+
+
+class IConVar;
+
+
+// Shared between the engine and dedicated server.
+class CBudgetPanelShared : public CBaseBudgetPanel
+{
+ typedef CBaseBudgetPanel BaseClass;
+
+public:
+
+ // budgetFlagsFilter is a combination of BUDGETFLAG_ defines that filters out which budget groups we are interested in.
+ CBudgetPanelShared( vgui::Panel *pParent, const char *pElementName, int budgetFlagsFilter );
+ ~CBudgetPanelShared();
+
+ // Override this to set the window position.
+ virtual void SetupCustomConfigData( CBudgetPanelConfigData &data );
+
+ virtual void SetTimeLabelText();
+ virtual void SetHistoryLabelText();
+
+ virtual void PaintBackground();
+ virtual void Paint( void );
+ virtual void PostChildPaint();
+
+ virtual void SnapshotVProfHistory( float filteredtime );
+
+ // Command handlers
+ void OnNumBudgetGroupsChanged( void );
+
+ void SendConfigDataToBase();
+
+
+public:
+
+ static double g_fFrameTimeLessBudget;
+ static double g_fFrameRate;
+
+
+private:
+
+ void DrawColoredText(
+ vgui::HFont font,
+ int x, int y,
+ int r, int g, int b, int a,
+ PRINTF_FORMAT_STRING const char *pText,
+ ... ) FMTFUNCTION( 9, 10 );
+};
+
+
+// CVars that change the layout can hook this.
+void PanelGeometryChangedCallBack( IConVar *var, const char *pOldString, float flOldValue );
+
+
+#endif // VGUI_BUDGETPANELSHARED_H