VGUI Image Progress Bar

I
Category:Tutorials
Category:Free source code
This is an extension of the ContinuousProgressBar class that Valve already has in place in the VGUI lib (Orange Box). This tutorial is a purely copy/paste tutorial and should not require any modification. If there are any areas that need improvement or corrections, feel free to make/add them.
== The Header (.h) File ==
game/client/game_controls/ImageProgressBar.h
#ifndef IMAGEPROGRESSBAR_H
#define IMAGEPROGRESSBAR_H
#ifdef _WIN32
#pragma once
#endif
#include <vgui/VGUI.h>
#include <vgui_controls/ProgressBar.h>
using namespace vgui;
class ImageProgressBar : public ContinuousProgressBar
{
	DECLARE_CLASS_SIMPLE( ImageProgressBar, ContinuousProgressBar );
public:
	ImageProgressBar( Panel *parent, const char *panelName );
	ImageProgressBar( Panel *parent, const char *panelName, const char *topTexturename, const char *bottomTextureName );
	virtual void Paint( void );
	virtual void ApplySettings( KeyValues *inResourceData );
	virtual void GetSettings( KeyValues *outResourceData );
	void	SetTopTexture( const char *topTextureName );
	void	SetBottomTexture( const char *bottomTextureName );
private:
	int	m_iTopTextureId;
	int	m_iBottomTextureId;
	char	m_szTopTextureName[64];
	char	m_szBottomTextureName[64];
};
#endif
== The Source (.cpp) File ==
game/client/game_controls/ImageProgressBar.cpp
#include "cbase.h"
#include <vgui/ISurface.h>
#include <KeyValues.h>
#include "ImageProgressBar.h"
#include "tier0/memdbgon.h"
using namespace vgui;
DECLARE_BUILD_FACTORY( ImageProgressBar );
ImageProgressBar::ImageProgressBar( Panel *parent, const char *panelName ) : BaseClass( parent, panelName )
{
	m_iTopTextureId = m_iBottomTextureId = -1;
	memset( m_szTopTextureName, 0, sizeof( m_szTopTextureName ) );
	memset( m_szBottomTextureName, 0, sizeof( m_szBottomTextureName ) );
}
ImageProgressBar::ImageProgressBar(vgui::Panel *parent, const char *panelName, const char *topTextureName, const char *bottomTextureName ) : BaseClass( parent, panelName )
{
	SetTopTexture( topTextureName );
	SetBottomTexture( bottomTextureName );
}
void ImageProgressBar::SetTopTexture(const char *topTextureName)
{
	if( topTextureName != NULL && topTextureName[0] )
	{
		Q_strncpy( m_szTopTextureName, topTextureName, 64 );
		m_iTopTextureId = surface()->DrawGetTextureId( topTextureName );
		if( m_iTopTextureId == -1 )
		{
			m_iTopTextureId = surface()->CreateNewTextureID();
			surface()->DrawSetTextureFile( m_iTopTextureId, topTextureName, false, true );
		}
	}
	else
	{
		memset( m_szTopTextureName, 0, sizeof( m_szTopTextureName ) );
		m_iTopTextureId = -1;
	}
}
void ImageProgressBar::SetBottomTexture(const char *bottomTextureName)
{
	if( bottomTextureName != NULL && bottomTextureName[0] )
	{
		Q_strncpy( m_szBottomTextureName, bottomTextureName, 64 );
		m_iBottomTextureId = surface()->DrawGetTextureId( bottomTextureName );
		if( m_iBottomTextureId == -1 )
		{
			m_iBottomTextureId = surface()->CreateNewTextureID();
			surface()->DrawSetTextureFile( m_iBottomTextureId, bottomTextureName, false, true );
		}
	}
	else
	{
		memset( m_szBottomTextureName, 0, sizeof( m_szBottomTextureName ) );
		m_iBottomTextureId = -1;
	}
}
void ImageProgressBar::ApplySettings( KeyValues *inResourceData )
{
	const char *topTextureName = inResourceData->GetString("TopImage", "");
	SetTopTexture( topTextureName );
	const char *bottomTextureName = inResourceData->GetString("BottomImage", "");
	SetBottomTexture( bottomTextureName );
	BaseClass::ApplySettings( inResourceData );
}
void ImageProgressBar::GetSettings( KeyValues *outResourceData )
{
	BaseClass::GetSettings( outResourceData );
	outResourceData->SetString( "TopImage", m_szTopTextureName );
	outResourceData->SetString( "BottomImage", m_szBottomTextureName );
}
void ImageProgressBar::Paint( void )
{
	if( m_iTopTextureId == -1 )
		return;
	int x = 0, y = 0;
	int wide, tall;
	GetSize( wide, tall );
	if( m_iBottomTextureId != -1 )
	{
		surface()->DrawSetTexture( m_iBottomTextureId );
		surface()->DrawSetColor( 255, 255, 255, 255 );
		surface()->DrawTexturedRect( x, y, wide, tall );
	}
	surface()->DrawSetTexture( m_iTopTextureId );
	surface()->DrawSetColor( 255, 255, 255, 255 );
	switch( m_iProgressDirection )
	{
	case PROGRESS_EAST:
		surface()->DrawTexturedSubRect( x, y, x + (int)(wide * _progress), y + tall,
			0.0f, 0.0f, _progress, 1.0f );
		break;
	case PROGRESS_WEST:
		surface()->DrawTexturedSubRect( x + (int)(wide * (1.0f - _progress) ), y, x + wide, y + tall,
			1.0f - _progress, 0.0f, 1.0f, 1.0f );
		break;
	case PROGRESS_NORTH:
		surface()->DrawTexturedSubRect( x, y + (int)(tall * (1.0f - _progress) ), x + wide, y + tall,
			0.0f, 0.0f, 1.0f, _progress );
		break;
	case PROGRESS_SOUTH:
		surface()->DrawTexturedSubRect( x, y, x + wide, y + (int)( tall * _progress),
			0.0f, 1.0f - _progress, 1.0f, 1.0f );
		break;
	}
}
== Usage ==
To use this in a .res file, use it like any other progress bar. There are added keys to the *.res file so it is possible to change the images via text instead of hard-code. Here's an example that does not use a background progress bar image. Background progress images aren't required, but can be used if needed:
First, include the ImageProgressBar class.
 #include "ImageProgressBar.h"
Next, declare the new handle for the image progress bar for the new hud class:
protected:
	ImageProgressBar *m_pHealthProgressBar;
Place this within the constructor of your new hud class:
m_pHealthProgressBar = new ImageProgressBar( this, "HealthProgressBar", "vgui/gfx/HUD/health_bar");
m_pHealthProgressBar->SetProgressDirection( ProgressBar::PROGRESS_EAST );
If top and bottom materials need to be added via code, add this instead of the code above:
m_pHealthProgressBar = new ImageProgressBar( this, "HealthProgressBar");
m_pHealthProgressBar->SetProgressDirection( ProgressBar::PROGRESS_EAST );
m_pHealthProgressBar->SetTopTexture( <top texture> );
m_pHealthProgressBar->SetBottomTexture( <bottom texture> );
And place this within the Think function of the hud class:
//Edit this part for whatever value your image bar needs to be.
m_pHealthProgressBar->SetProgress( Value );
And to finish it off, place this inside \scripts\HudLayout.res:
"HealthProgressBar"
{
	"ControlName"	"ImageProgressBar"
	"fieldName"	"HealthProgressBar"
	"xpos"		"10"
	"ypos"		"25"
	"wide"		"200"
	"tall"		"32"
	"autoResize"	"1"
	"visible"	"1"
	"enabled"	"1"
	"tabPosition"	"0"
}