Welcome, Guest! Login | Register

Creating a New VGUI Menu - Part 2 [Print this Article]
Posted by: rkzad
Date posted: Jun 09 2003
User Rating: 5 out of 5.0
Number of views: 6838
Number of comments: 0
Description: Panels, Labels, Buttons, and Commands
Well I'm moving this tutorial over from Half-Life Coding Index to Wavelength since HLCI is hosted at Wavelength anyways, and HLCI is an index, not a tutorial. Feel free to PM/E-Mail me about any mistakes, but if you have any problems with VGUI please ask your questions on the Half-Life coding forum. I haven't touched Half-Life in about a year aside from updating my website, so I'm sure there are more qualified people who are willing to help on the forum. This tutorial also requires you have finished Part 1! It's a continuation. All that aside, welcome to the second part of the VGUI tutorial!

Oh yeah, Be sure you have the menu we did in the First Part in your code, because that's what we will be editing.

So we have a cancel button... not the best thing is it? Well, no... let's make our menu a bit better now. First off, we're actually going to make it look like the Cancel button is part of a menu. So we need a menu box. Open up the cl_dll project and open vgui_TeamFortressViewport.h at line 1121 and add:
 CODE (C++) 
class CFirstMenu : public CMenuPanel
{
private:
    CommandButton       *m_pCancelButton;
    CTransparentPanel   *m_pPanel; // VGUI Tutorial 2
 
public:

m_pPanel will be our panel which contains all the menu buttons. Now let's actally give this panel some properties. Open up vgui_FirstMenu.cpp and change the constructor function to the following:
 CODE (C++) 
CFirstMenu :: CFirstMenu(int iTrans, int iRemoveMe, int x, int y, int wide, int tall) : CMenuPanel(iTrans, iRemoveMe, x,y,wide,tall)
{
    m_pPanel = new CTransparentPanel( 200, XRES(80), YRES(80), XRES(480), YRES(329));
    m_pPanel->setParent( this );
    m_pPanel->setBorder( new LineBorder( Color(255 * 0.7,170 * 0.7,0,0) ) );
 
    m_pCancelButton = new CommandButton( gHUD.m_TextMessage.BufferedLocaliseTextString( "Cancel" ),
                                         XRES(50), YRES(279), XRES(378), YRES(42));
    m_pCancelButton->setContentAlignment(vgui::Label::a_center);
    m_pCancelButton->setParent( m_pPanel );
    m_pCancelButton->addActionSignal( new CMenuHandler_TextWindow(HIDE_TEXTWINDOW) );
}

Now, compile that and put it in your mod's cl_dlls folder. Run a game and open up the vgui menu (vguimenu 30) and something like the following should appear:

user posted image

The extra space is where our new menu objects will be. Now then, what would be one of the most important things be? A title! Let's add one! Open up vgui_TeamFortressViewport.h at line 1122 and add:
 CODE (C++) 
class CFirstMenu : public CMenuPanel
{
private:
    CommandButton       *m_pCancelButton;
    CTransparentPanel   *m_pPanel;
    Label               *m_pTitle; // VGUI Tutorial 2
 
public:

That label will be our title. Now let's go back to vgui_FirstMenu.cpp and, once again, modify our CFirstMenu constructor to:
 CODE (C++) 
CFirstMenu :: CFirstMenu(int iTrans, int iRemoveMe, int x, int y, int wide, int tall) : CMenuPanel(iTrans, iRemoveMe, x,y,wide,tall)
{
    // Start - VGUI Tutorial 2
    CSchemeManager *pSchemes = gViewPort->GetSchemeManager();
    SchemeHandle_t hTitleScheme = pSchemes->getSchemeHandle( "Title Font" );
 
    int r, g, b, a;
    // End - VGUI Tutorial 2
 
    m_pPanel = new CTransparentPanel( 200, XRES(80), YRES(80), XRES(480), YRES(329));
    m_pPanel->setParent( this );
    m_pPanel->setBorder( new LineBorder( Color(255 * 0.7,170 * 0.7,0,0) ) );
 
    m_pCancelButton = new CommandButton( gHUD.m_TextMessage.BufferedLocaliseTextString( "Cancel" ),
                                         XRES(50), YRES(279), XRES(378), YRES(42));
    m_pCancelButton->setContentAlignment(vgui::Label::a_center);
    m_pCancelButton->setParent( m_pPanel );
    m_pCancelButton->addActionSignal( new CMenuHandler_TextWindow(HIDE_TEXTWINDOW) );
 
    // Start - VGUI Tutorial 2
    m_pTitle = new Label( "", XRES(1), YRES(1), XRES(478), YRES(58) );
    m_pTitle->setParent( m_pPanel );
    m_pTitle->setFont( pSchemes->getFont(hTitleScheme) );
    pSchemes->getFgColor( hTitleScheme, r, g, b, a );
    m_pTitle->setFgColor( r, g, b, a );
    pSchemes->getBgColor( hTitleScheme, r, g, b, a );
    m_pTitle->setBgColor( r, g, b, a );
    m_pTitle->setContentAlignment( vgui::Label::a_center );
    m_pTitle->setText( "Your First Menu" );
    // End - VGUI Tutorial 2
}

Egads! There's something about schemes at the beginning of the function now! Don't fret. First line, about GetSchemeManager. This gets all the info about the TextSchemes for your resolution. So for instance you're resolution was 800x600, it would look in 800_textscheme.txt. You may find this file and all the other xxx_textscheme.txt files in your half-life\valve directory. You are free to modify these as you wish, but I suggest you move these files to your own mod folder before doing so. We're gonna be playing around with these textschemes a while later. Next line gets certain information from our xxx_textscheme.txt. In this case, it's getting the info about 'SchemeName "Title Font"'. So now, in hTitleScheme, we now have all the specifications on the properties of a "Title Font". We will be using the FgColor, BgColor and font. Now. m_pTitle is our new label we had declared in our class. First line about it is positioning it. Then we set the font from our "Title Font" scheme. The next line gets the foreground color from the "Title Font" scheme assigns the colour values to r, g, b and a. Then the next line sets the foreground colour of our label to what we had gotten from the "Title Font" scheme. The BgColor uses the same method. setContentAlignment is aligning where the text will be in our label. In this case we made it so that it would completely centered. Horizontally and vertically. The last line just sets the text of our label. Yes, you can set the text for the label in the constructor, but setText works better. There's a possibility that your text will take more lines than necessary if you set it in the constructor. Geez that was a long explanation. If you were to compile your code and test it out, you should see the following:

user posted image

Now let's add another button. This time I will show you how to send a command that can be then be dealt with in ClientCommand on the mp dll side! Isn't exciting? heheheh. OK! Let's go back to vgui_TeamFortress.h to our CFirstMenu stuff and add this into it:
 CODE (C++) 
    CTransparentPanel   *m_pPanel;
    Label               *m_pTitle;
    CommandButton       *m_pSpeak; // VGUI Tutorial 2
 
public:

There. We have our new CommandButton. Now let's open up vgui_FirstMenu.cpp and change our constructor to look like this:
 CODE (C++) 
CFirstMenu :: CFisrtMenu(int iTrans, int iRemoveMe, int x, int y, int wide, int tall) : CMenuPanel(iTrans, iRemoveMe, x,y,wide,tall)
{
    CSchemeManager *pSchemes = gViewPort->GetSchemeManager();
    SchemeHandle_t hTitleScheme = pSchemes->getSchemeHandle( "Title Font" );
 
    int r, g, b, a;
 
    m_pPanel = new CTransparentPanel( 200, XRES(80), YRES(80), XRES(480), YRES(329));
    m_pPanel->setParent( this );
    m_pPanel->setBorder( new LineBorder( Color(255 * 0.7,170 * 0.7,0,0) ) );
 
    m_pCancelButton = new CommandButton( gHUD.m_TextMessage.BufferedLocaliseTextString( "Cancel" ),
                                         XRES(50), YRES(279), XRES(378), YRES(42));
    m_pCancelButton->setContentAlignment(vgui::Label::a_center);
    m_pCancelButton->setParent( m_pPanel );
    m_pCancelButton->addActionSignal( new CMenuHandler_TextWindow(HIDE_TEXTWINDOW) );
 
    m_pTitle = new Label( "", XRES(1), YRES(1), XRES(478), YRES(58) );
    m_pTitle->setParent( m_pPanel );
    m_pTitle->setFont( pSchemes->getFont(hTitleScheme) );
    pSchemes->getFgColor( hTitleScheme, r, g, b, a );
    m_pTitle->setFgColor( r, g, b, a );
    pSchemes->getBgColor( hTitleScheme, r, g, b, a );
    m_pTitle->setBgColor( r, g, b, a );
    m_pTitle->setContentAlignment( vgui::Label::a_center );
    m_pTitle->setText( "Your First Menu" );
 
    // Start - VGUI Tutorial 2
    m_pSpeak = new CommandButton( "Say something", XRES(1), YRES(61), XRES(478), YRES(58));
    m_pSpeak->setContentAlignment( vgui::Label::a_center );
    m_pSpeak->setParent( m_pPanel );
    m_pSpeak->addActionSignal( new CMenuHandler_StringCommand( "test_say" ) );
    // End - VGUI Tutorial 2
}

Simple, no? All this is is creating a new button with "Say something" on it with those coordinates in mind, sets it as part of our panel, and then the last line is where we tell the button what it should do when we click it. In this case, we're telling it to send out this command to the console.

Compile the client workspace and have it ready for playing. Then, open up the mp workspace and open client.cpp to line 385 and add:
 CODE (C++) 
    else if ( FStrEq(pcmd, "vguimenu" ) )
    {
        if (CMD_ARGC() >= 2)
            GetClassPtr((CBasePlayer *)pev)->ShowVGUIMenu(atoi(CMD_ARGV(1)));
    }
    // Start - VGUI Tutorial 2
    else if ( FStrEq(pcmd, "test_say" ) )
    {
        ClientPrint(pev, MSG_ONE, "Good job!  It worked!\n");
    }
    // End - VGUI Tutorial 2
    else if ( g_pGameRules->ClientCommand( GetClassPtr((CBasePlayer *)pev), pcmd ) )
    {

Not so bad, eh? There's another example of something you can do with a button (the first one was hiding your window). Compile the mp dll and then put the code to the test... the menu should now look like this:

user posted image

Now let's add a couple more buttons... but this time there's gonna be a lot more to it! These buttons will respectively show an object and hide an object of our panel. Exciting, no? This time we will be using InputSignals. Let's open up the client workspace again and (uh oh!) update vgui_TeamFortressViewport.h at our CFirstMenu class and change it to:
 CODE (C++) 
class CFirstMenu : public CMenuPanel
{
private:
    CommandButton       *m_pCancelButton;
    CTransparentPanel   *m_pPanel;
    Label               *m_pTitle;
    CommandButton       *m_pSpeak;
    // Start - VGUI Tutorial 2
    int                 m_iShowText;
    Label               *m_pText;
    CommandButton       *m_pShowButton;
    CommandButton       *m_pHideButton;
    // End - VGUI Tutorial 2
 
public:
    CFirstMenu(int iTrans, int iRemoveMe, int x, int y, int wide, int tall);
    void SetActiveInfo( int iShowText ); // VGUI Tutorial 2
};

OK. m_iShowText will have an integer so that we know which text is showing. 0 will be nothing, 1 will be m_pText (our label to hide/show). m_pShowButton is the button that will show our m_pText label and m_pHideButton is the button that will hide our m_pText label. SetActiveInfo will change our m_iShowText variable and either hide or show the m_pText label, depending on the status of what the label is now. Now let's get coding. Let's open up vgui_FirstMenu.cpp and change our constructor too:
 CODE (C++) 
CFirstMenu :: CFirstMenu(int iTrans, int iRemoveMe, int x, int y, int wide, int tall) : CMenuPanel(iTrans, iRemoveMe, x,y,wide,tall)
{
    CSchemeManager *pSchemes = gViewPort->GetSchemeManager();
    SchemeHandle_t hTitleScheme = pSchemes->getSchemeHandle( "Title Font" );
 
    int r, g, b, a;
 
    m_pPanel = new CTransparentPanel( 200, XRES(80), YRES(80), XRES(480), YRES(329));
    m_pPanel->setParent( this );
    m_pPanel->setBorder( new LineBorder( Color(255 * 0.7,170 * 0.7,0,0) ) );
 
    m_pCancelButton = new CommandButton( gHUD.m_TextMessage.BufferedLocaliseTextString( "Cancel" ),
                                         XRES(50), YRES(279), XRES(378), YRES(42));
    m_pCancelButton->setContentAlignment(vgui::Label::a_center);
    m_pCancelButton->setParent( m_pPanel );
    m_pCancelButton->addActionSignal( new CMenuHandler_TextWindow(HIDE_TEXTWINDOW) );
 
    m_pTitle = new Label( "", XRES(1), YRES(1), XRES(478), YRES(58) );
    m_pTitle->setParent( m_pPanel );
    m_pTitle->setFont( pSchemes->getFont(hTitleScheme) );
    pSchemes->getFgColor( hTitleScheme, r, g, b, a );
    m_pTitle->setFgColor( r, g, b, a );
    pSchemes->getBgColor( hTitleScheme, r, g, b, a );
    m_pTitle->setBgColor( r, g, b, a );
    m_pTitle->setContentAlignment( vgui::Label::a_center );
    m_pTitle->setText( "Your First Menu" );
 
    m_pSpeak = new CommandButton( "Say something", XRES(1), YRES(61), XRES(478), YRES(58));
    m_pSpeak->setContentAlignment( vgui::Label::a_center);
    m_pSpeak->setParent( m_pPanel );
    m_pSpeak->setBoundKey( 's' );
    m_pSpeak->addActionSignal( new CMenuHandler_StringCommand( "test_say" ) );
 
    // Start - VGUI Tutorial 2
    m_pText = new Label( "", XRES(1), YRES(181), XRES(478), YRES(58));
    m_pText->setParent( m_pPanel );
    m_pText->setFont( pSchemes->getFont(hTitleScheme) );
    pSchemes->getFgColor( hTitleScheme, r, g, b, a );
    m_pText->setFgColor( r, g, b, a );
    pSchemes->getBgColor( hTitleScheme, r, g, b, a );
    m_pText->setBgColor( r, g, b, a );
    m_pText->setContentAlignment( vgui::Label::a_center );
    m_pText->setText( "BOO! Scared you?" );
    m_pText->setVisible( false );
 
    m_pShowButton = new CommandButton( "Show text", XRES(1), YRES(121), XRES(230), YRES(58));
    m_pShowButton->setContentAlignment( vgui::Label::a_center );
    m_pShowButton->setParent( m_pPanel );
    m_pShowButton->addInputSignal( new CHandler_MenuButtonOver(this, 1) );
 
    m_pHideButton = new CommandButton( "Hide text", XRES(239), YRES(121), XRES(230), YRES(58));
    m_pHideButton->setContentAlignment( vgui::Label::a_center );
    m_pHideButton->setParent( m_pPanel );
    m_pHideButton->addInputSignal( new CHandler_MenuButtonOver(this, 0) );
    // End - VGUI Tutorial 2
}

First, we create our label. This is almost exactly like the m_pTitle label except that we set it so that it is not visible. Next is our show button. Like the button before. But notice that we used addInputSignal rather than addActionSignal. In this case, we are using it so that when the mouse will go over this button, call our SetActiveInfo with the value of 1. The second button does the same but with the value of 0. Now let's implement our SetActiveInfo function so that it will actually do something. Write this underneath our constructor:
 CODE (C++) 
void CFirstMenu :: SetActiveInfo( int iShowText )
{
    if (iShowText == 0)
    {
        m_pText->setVisible( false );
    }
    else
    {
        m_pText->setVisible( true );
    }
}

So, what this does is, depending on whether iShowText equals 0 or 1, shows or hides our text label. Simple stuff! Within these two conditions you can do a series of commands. So the possibilities aren't very limited! Now compile this up and put your code to the test. Put your cursor over the "Show text" button and the label should pop up!

user posted image

That's it for part 2! There's a bit left in Part 3, so check it out.

Rate This Article
This article is currently rated: 5 out of 5.0 (1 Votes)

You have to register to rate this article.
Related Files
Zip FileFilename: pic5.gif
File Size: 35.9 KB
Zip FileFilename: pic3.gif
File Size: 17.1 KB
Zip FileFilename: pic4.gif
File Size: 34.4 KB
Zip FileFilename: pic6.gif
File Size: 34.8 KB

User Comments

No User Comments

You must register to post a comment. If you have already registered, you must login.

Latest Articles
3rd person View in Multiplayer
Half-Life 2 | Coding | Client Side Tutorials
How to enable it in HL2DM

By: cct | Nov 13 2006

Making a Camera
Half-Life 2 | Level Design
This camera is good for when you join a map, it gives you a view of the map before you join a team

By: slackiller | Mar 05 2006

Making a camera , Part 2
Half-Life 2 | Level Design
these cameras are working monitors that turn on when a button is pushed.

By: slackiller | Mar 04 2006

Storing weapons on ladder
Half-Life 2 | Coding | Snippets
like Raven Sheild or BF2

By: British_Bomber | Dec 24 2005

Implementation of a string lookup table
Half-Life 2 | Coding | Snippets
A string lookup table is a set of functions that is used to convert strings to pre-defined values

By: deathz0rz | Nov 13 2005


Latest Comments
knock knock
General | News
By: omega | Dec 22 2016
 
knock knock
General | News
By: MIFUNE | Oct 10 2015
 
New HL HUD Message System
Half-Life | Coding | Shared Tutorials
By: chbrules | Dec 31 2011
 
knock knock
General | News
By: Whistler | Nov 05 2011
 
Particle Engine tutorial part 4
Half-Life | Coding | Client Side Tutorials
By: darkPhoenix | Feb 18 2010
 
Particle Engine tutorial part 2
Half-Life | Coding | Client Side Tutorials
By: darkPhoenix | Feb 11 2010
 
Particle Engine tutorial part 3
Half-Life | Coding | Client Side Tutorials
By: darkPhoenix | Feb 11 2010
 
Game Movement Series #2: Analog Jumping and Floating
Half-Life 2 | Coding | Shared Tutorials
By: mars3554 | Oct 26 2009
 
Particle Engine tutorial part 5
Half-Life | Coding | Client Side Tutorials
By: Deadpool | Aug 02 2009
 
Particle Engine tutorial part 5
Half-Life | Coding | Client Side Tutorials
By: Persuter | Aug 02 2009
 

Site Info
297 Approved Articless
8 Pending Articles
3940 Registered Members
0 People Online (7 guests)
About - Credits - Contact Us

Wavelength version: 3.0.0.9
Valid XHTML 1.0! Valid CSS!