Understanding VGUI2 Resource Files

From Valve Developer Community
Jump to: navigation, search

Introduction

I've witnessed a lot of confusion when I asked other coders how the VGUI2 system interacts with Resource Files, and I have not found any complete reference for using them, so here goes.

What they do

Resource files are used to automatically generate controls (=panels) that can be put in a parent control. This way, panel layout is far easier to do. Hence, resource files are very handy when you're creating your own in-game panel and want the heavy layout-lifting done automatically.

Note:Resource files have nothing to do with (automatically) creating new types of controls: they are simply a digest of what controls are placed where and how they are initialized.

The design

Resource files are simple KeyValues that are parsed from top to bottom: each control that is specified in the file is created with a control factory and has its settings applied in a hierarchical manner.

When creating a new in-game panel

Loading a resource file

To load a resource file for a panel, simply add the following in your constructor:

LoadControlSettings( "Path/To/Resource/File.res" );

Tweaking controls ingame

See The VGUI Build Mode for more information.

Modifying resource file-generated controls in code

Let's say you've made your own panel and put some ImagePanels in the resource file. If you wish to modify an automatically generated control, you only need to do a few things:

  • Create a pointer for the control in your header file:
vgui::ImagePanel* m_pTestImage;
  • Populate the control in your constructor:
m_pTestImage = dynamic_cast<ImagePanel*>( FindChildByName( "NameOfPanelInResourceFile", true ) );

If you're using Source SDK 2013, you can use the shorter template method instead:

m_pTestImage = FindControl<ImagePanel>( "NameOfPanelInResourceFile", true );

Warning: Make sure you call this line after you've loaded the resource file, or you'll always get a NULL pointer back!

  • Done! You can now access the ImagePanel (don't forget to check for null pointers!)

Don't worry about having to clean up the auto-generated panels; they do that themselves.

When creating a new type of control

Factory

The system needs to know which controls can be built using a factory method. This is necessary to automatically create controls when reading a resource file. It uses the following macro for this:

DECLARE_BUILD_FACTORY( Label );

This method will attempt to create an instance of the control with a constructor with two parameters, which are both NULL:

#define DECLARE_BUILD_FACTORY( className )										\
	static vgui::Panel *Create_##className##( void )							\
		{																		\
			return new className( NULL, NULL );									\
		};																		\
		static vgui::CBuildFactoryHelper g_##className##_Helper( #className, Create_##className## );\
	className *g_##className##LinkerHack = NULL;

If you want to pass other parameters, or you have non-nullable parameters that require a default value, you can use DECLARE_BUILD_FACTORY_CUSTOM:

// Example: ComboBoxNew inherits from ComboBox

// Custom ComboBoxNew method
vgui::Panel *ComboBoxNew_Factory()
{
	return new ComboBoxNew( NULL, NULL, 5, true );
}

// Takes the class name and the method name. Ensure that the method is defined before this line!
DECLARE_BUILD_FACTORY_CUSTOM( ComboBoxNew, ComboBoxNew_Factory );

Applying Settings

The method ApplySettings( KeyValues* inResourceData ) is what does the heavy lifting when laying out your control. Because of the hierarchical structure of the controls (A inherits from B, B inherits from C, etc), it is very easy to create a new control whose particular settings can be data-driven (that is, initialized from the resource file). Here is an example:

Say your control, ImagePanelBetter, inherits from ImagePanel. You would then override the virtual ApplySettings() function and read things for your control:

void ImagePanelBetter::ApplySettings(KeyValues *inResourceData)
{
	// VERY IMPORTANT: ALWAYS CALL THE BASE CLASS!
	BaseClass::ApplySettings( inResourceData );

	const char *value = NULL;
	value = inResourceData->GetString("normalImage", "");
	if (*value)
		UpdateNormalImage( value );

	value = inResourceData->GetString("mouseoverImage", "");
	if (*value)
		UpdateMouseOverImage( value );

	value = inResourceData->GetString("mouseclickImage", "");
	if (*value)
		UpdateMouseClickImage( value );

	value = inResourceData->GetString("command", "");
	if (*value)
		UpdateCommand( value );
}

Pretty simple, no?

Because resource files are simply KeyValues, you can also nest items:

void ImagePanelBetter::ApplySettings(KeyValues *inResourceData)
{
	// VERY IMPORTANT: ALWAYS CALL THE BASE CLASS!
	BaseClass::ApplySettings( inResourceData );

	KeyValues* nestedItem;
	nestedItem = inResourceData->FindKey( "NameOfNestedItemInResourceFile" );
	if (nestedItem )
		DoStuff( nestedItem );
}

Hierarchical overview of keys in resource files

This is an overview of which keys are defined where in code and what their function is.

Panel

Description: A simple control that is the basis for all other VGUI controls. Contains many overrideable functions.

Inherits from: None

  • fieldName: Determines the name of the control.
  • xpos: Determines the horizontal offset from the top left (by default) of the parent panel.
  • ypos; Determines the vertical offset from the top left (by default) of the parent panel.
  • wide: Determines the width of the control.
  • tall: Determines the height of the control.
Tip:You can apply an offset to these four position/size variables by using a position or size flag.
  • zpos: Determines the depth of the panel. Deeper panels are drawn first. Lower numbers = deeper.
  • visible: Determines if the control will be drawn.
Tip:Any controls that have this control as a parent will also be hidden/shown.
  • enabled: Determines if the control is enabled. Used by controls higher up the chain (like Buttons).
  • tabPosition: Determines the tab order of the control.
  • tooltiptext: Determines the tooltip text to show when you hover over this control.
  • paintbackground: Paint the background color of this control?
  • paintborder: Paint the border of this control?

There are also a number of overridable colors defined in several controls. Panel checks the ones of itself and its children and has the following defined:

  • fgcolor_override: Overrides the color of the foreground (for Labels, this is the text color).
  • bgcolor_override: Overrides the color of the background.
Tip:Write color values as follows: "R G B A" or "ColorNameInScheme". Example: "fgcolor_override" "255 0 0 255" or "fgcolor_override" "My.Custom.Color"

Label

Description: A control that can display (wrapped) text.

Inherits from: Panel

  • labelText: Determines the text that the label will display.
Tip:Putting text between a percentage sign will make it a localized variable. For example, the string %test% will create a localized string #var_test. See VGUI Localization for more info on localized strings.
Tip:You can also just assign a non-changing localized string by adding the control sign, #, in front of a string: #test will get looked up in the list of tokens, and the localized text will be displayed in its place.
  • textAlignment: Determines the alignment of the label.
Tip:Valid values are north-west, north, north-east, west, center, east, south-west, south and south-east.
  • associate: Allows the label to be associated with another control. To do: See what uses this has.
  • dulltext: A boolean that determines if text should be displayed in a dull manner.
  • brighttext: A boolean that determines if text should be displayed in a bright manner.
Tip:You can only have one of these two active. The one that is defined first is chosen.
  • font: Determines the font used by the label. Use the font name as defined in the SourceScheme.res file.
  • wrap: Determines if your label wraps around the available space.
  • centerwrap: Same as above, except it also works for centered text.
  • textinsetx: Additional horizontal offset space from whichever side it is aligned.
  • textinsety: Additional vertical offset space from whichever side it is aligned.

Button

Description: A control that can display (wrapped) text and act as a button.

Inherits from: Label

  • command: Determines which command to fire to the OnCommand handler when pressed.
  • default: A boolean that determines if this button is to be activated when the user presses the enter or space bar keys. Only one such button can exist.
  • selected: A boolean that determines if this button appears to have been selected.
  • sound_armed: Determines what sound the button makes when hovered over.
  • sound_depressed: Determines what sound the button makes when pressed upon.
  • sound_released: Determines what sound the button makes when released.

ImagePanel

Description: Essentially an image.

Inherits from: Panel

  • scaleImage: A boolean that determines whether to scale the image to its specified width and height.
  • scaleAmount: A float that determines how much the image should scale.
  • tileImage: A boolean that determines whether to tile the image.
  • tileHorizontally: A boolean that determines whether to tile the image horizontally.
  • tileVertically: A boolean that determines whether to tile the image vertically.
  • image: The actual image. Expects a path to a .VMT file in the /materials/vgui folder.
Tip:Example: Say that your .VMT file is called example1.vmt and is located in /materials/vgui/examples, then the path you should put here would be examples/example1.
Tip:Confirmed on Windows machine - You can go up a folder by including ../ in your file path. For example, to access example.vmt in /materials/images, use ../images/example as your path.
  • fillcolor: Determines the background color behind the image. Only painted if the alpha is higher than 0 (duh)
Tip:You can specify a color in both RGBA format or refer to a color in the scheme files by just putting its name as the value.
  • border: Determines the border around the image. You can only refer to colors defined in the scheme files here using the names of the colors!

EditablePanel

Description: A window-like control that can house other controls, which can be edited using the VGUI Build Mode.

Inherits from: Panel

Frame

Description: A dynamically resizeable control that can be dragged around. Has a title bar, close and minimization buttons, etc.

Inherits from: EditablePanel

Note:the Frame control overrides the "visible" key defined in Panel.
  • title: Determines the title of the frame.
  • title_font: Determines what font the title of the frame will use.
  • clientinsetx_override: Overrides the default horizontal offset from the left side of the panel.

Color overrides:

  • infocus_bgcolor_override: Override for the background color of the panel when it is in focus.
  • outoffocus_bgcolor_override: Override for the background color of the panel when it is out of focus.
  • titlebarbgcolor_override: Override for the background color of the title bar when it is in focus.
  • titlebardisabledbgcolor_override: Override for the background color of the title bar when it is out of focus.
  • titlebarfgcolor_override: Override for the foreground color of the title bar when it is in focus.
  • titlebardisabledfgcolor_override: Override for the foreground color of the title bar when it is out of focus.

To do: Not done yet!