Difference between revisions of "VGUI Image Progress Bar"

From Valve Developer Community
Jump to: navigation, search
m (recat)
m (Added syntax highlighting)
 
(5 intermediate revisions by 5 users not shown)
Line 1: Line 1:
[[Category:VGUI|I]]
+
[[Category:Custom VGUI Controls|I]]
 
[[Category:Tutorials]]
 
[[Category:Tutorials]]
 
[[Category:Free source code]]
 
[[Category:Free source code]]
Line 5: Line 5:
 
[[Image:Image_progress_bars.jpg]]
 
[[Image:Image_progress_bars.jpg]]
  
This is an extension of the <code>[[ContinuousProgressBar]]</code> class that Valve already has in place in the VGUI lib. This tutorial is a purely copy/paste tutorial and should not require any modification. However, if I've done something wrong or there's a better way to do something inside my code, please feel free to correct it.
+
This is an extension of the <code>[[ContinuousProgressBar]]</code> 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 ==
 
== The Header (.h) File ==
 
'''game/client/game_controls/ImageProgressBar.h'''
 
'''game/client/game_controls/ImageProgressBar.h'''
<pre>
+
<source lang=cpp>
 
#ifndef IMAGEPROGRESSBAR_H
 
#ifndef IMAGEPROGRESSBAR_H
 
#define IMAGEPROGRESSBAR_H
 
#define IMAGEPROGRESSBAR_H
Line 45: Line 45:
  
 
#endif
 
#endif
</pre>
+
</source>
  
 
== The Source (.cpp) File ==
 
== The Source (.cpp) File ==
 
'''game/client/game_controls/ImageProgressBar.cpp'''
 
'''game/client/game_controls/ImageProgressBar.cpp'''
<pre>
+
<source lang=cpp>
 
#include "cbase.h"
 
#include "cbase.h"
 
#include <vgui/ISurface.h>
 
#include <vgui/ISurface.h>
Line 168: Line 168:
 
}
 
}
 
}
 
}
</pre>
+
</source>
  
 
== Usage ==
 
== Usage ==
To use this in a .res file, you may use it like any other progress bar. I've added a couple of keys to the resource data so you can change the images uses via the .res files. 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:
+
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.
 
First, include the ImageProgressBar class.
<pre>
+
<source lang=cpp>
 
   #include "ImageProgressBar.h"
 
   #include "ImageProgressBar.h"
</pre>
+
</source>
  
Next, declare the new handle for the image progress bar for your new hud class:
+
Next, declare the new handle for the image progress bar for the new hud class:
<pre>
+
<source lang=cpp>
 
protected:
 
protected:
int m_pHealthProgressBar;
+
ImageProgressBar *m_pHealthProgressBar;
</pre>
+
</source>
  
 
Place this within the constructor of your new hud class:
 
Place this within the constructor of your new hud class:
<pre>
+
<source lang=cpp>
 
m_pHealthProgressBar = new ImageProgressBar( this, "HealthProgressBar", "vgui/gfx/HUD/health_bar");
 
m_pHealthProgressBar = new ImageProgressBar( this, "HealthProgressBar", "vgui/gfx/HUD/health_bar");
 
m_pHealthProgressBar->SetProgressDirection( ProgressBar::PROGRESS_EAST );
 
m_pHealthProgressBar->SetProgressDirection( ProgressBar::PROGRESS_EAST );
</pre>
+
</source>
And if you want to set a top and bottom material manually, then add this instead of the code above:
+
If top and bottom materials need to be added via code, add this instead of the code above:
<pre>
+
<source lang=cpp>
 
m_pHealthProgressBar = new ImageProgressBar( this, "HealthProgressBar");
 
m_pHealthProgressBar = new ImageProgressBar( this, "HealthProgressBar");
 
m_pHealthProgressBar->SetProgressDirection( ProgressBar::PROGRESS_EAST );
 
m_pHealthProgressBar->SetProgressDirection( ProgressBar::PROGRESS_EAST );
 
m_pHealthProgressBar->SetTopTexture( <top texture> );
 
m_pHealthProgressBar->SetTopTexture( <top texture> );
 
m_pHealthProgressBar->SetBottomTexture( <bottom texture> );
 
m_pHealthProgressBar->SetBottomTexture( <bottom texture> );
</pre>
+
</source>
  
And place this within the Think function of your hud class:
+
And place this within the Think function of the hud class:
<pre>
+
<source lang=cpp>
 
//Edit this part for whatever value your image bar needs to be.
 
//Edit this part for whatever value your image bar needs to be.
 
m_pHealthProgressBar->SetProgress( Value );
 
m_pHealthProgressBar->SetProgress( Value );
</pre>
+
</source>
{{Note|You must place this into the think function, otherwise the image bar won't adjust to your new value. Also you must make sure you set the progress of the bar only if the value has changed. It's much safer that way and more memory efficient.}}
+
{{Note|This must be placed in the think function, otherwise the image bar won't adjust to the new value. Also make sure the progress of the bar is set only if the value changes. It's much safer that way and more memory efficient; do not keep setting the same value repeatedly.}}
  
 
And to finish it off, place this inside '''\scripts\HudLayout.res''':
 
And to finish it off, place this inside '''\scripts\HudLayout.res''':
Line 221: Line 221:
 
</pre>
 
</pre>
  
{{Note|This has been tested with progress directions PROGRESS_NORTH and PROGRESS_EAST. I have not tested the others, but the code is there. If they are wrong and you correct it in your code, please update this document to reflect the changes you made to get the other directions working properly.}}
+
{{Note|This has been tested with progress directions PROGRESS_NORTH and PROGRESS_EAST. It has not been tested with the others, but the code is there. If they are not correct, please correct this page.}}

Latest revision as of 23:55, 25 March 2010


Image progress bars.jpg

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 );
Note.png Note: This must be placed in the think function, otherwise the image bar won't adjust to the new value. Also make sure the progress of the bar is set only if the value changes. It's much safer that way and more memory efficient; do not keep setting the same value repeatedly.

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"
}
Note.png Note: This has been tested with progress directions PROGRESS_NORTH and PROGRESS_EAST. It has not been tested with the others, but the code is there. If they are not correct, please correct this page.