text: //========= 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();
  	}
  }
  
  