VGUI Screen Creation

From Valve Developer Community
< Zh
Revision as of 03:09, 24 April 2025 by MoRanYue (talk | contribs)
Jump to navigation Jump to search
Under construction.png
This page is actively undergoing a major edit.
As a courtesy, please do not edit this while this message is displayed.
If this page has not been edited for at least several hours to a few days, please remove this template. This message is intended to help reduce edit conflicts; please remove it between editing sessions to allow others to edit the page.

The person who added this notice will be listed in its edit history should you wish to contact them.

Info content.png
This page is being translated.
You can help by finishing the translation.
If this page cannot be translated for some reason, or is left untranslated for an extended period of time after this notice is posted, the page should be requested to be deleted.
Also, please make sure the article complies with the alternate languages guide.(en)
English (en)Русский (ru)中文 (zh)Translate (Translate)
Info content.png
This page is Machine translated
It is not recommended to use machine translation without any corrections.
If the article is not corrected in the long term, it will be removed.
Also, please make sure the article complies with the alternate languages guide.(en)
This notice is put here by LanguageBar template and if you want to remove it after updating the translation you can do so on this page.


Adding a VGUI screen to map

Note.png注意:This section assumes a mod where VGUI screens have been fixed (see the code modifications section below) but otherwise left the same. VGUI screens do not work in 半衰期2 半衰期2 or 半衰期2:死亡竞赛 半衰期2:死亡竞赛; they crash the game. (反恐精英:起源 反恐精英:起源 and many other games not tested.)
  1. Create a vgui_screen(en) entity. This is a point entity.
  2. Set its Panel Name to the name of the screen that should be shown. (This is not the filename of the screen.) The available screens are listed in vgui_screens.txt (which should be in the scripts directory).
  3. Set Panel Width in World and Panel Height in World to match the size of the brush. 64 wide by 32 tall would be a reasonable starting size.
  4. Compile the map and test.

The position of the entity in the map marks the bottom-left corner of the panel. The panel's direction (the normal of its face) is set by the entity's angle (Yaw).

Creating a VGUI screen

VGUI screen files have a .res extension and should be placed in scripts\screens\.

  1. 🖿vgui_test_screen.res is a good starting point for creating a VGUI screen file; it can be found at 🖿...\hl2\scripts\screens .
  2. The materials used in the .res file can be found in 🖿hl2_misc_dir.vpk. Extract the material files mentioned in the .res file to 🖿materials\vgui\screens.
  3. Add the screen to 🖿scripts\vgui_screens.txt. If it does not exist, create it. Here is an example which describes screen vgui_test_screen at 🖿scripts/screens/vgui_test_screen.res. Adjust it for your screen.
"VGUI_Screens"
{
   "vgui_test_screen"
   {
       // This is our example screen
       "type"		"vgui_screen_panel"
       "pixelswide"	480
       "pixelshigh"	240
       // This must be the file you created in step 1
       "resfile"	"scripts/screens/vgui_test_screen.res"
   } 
}

An example 🖿vgui_screen.txt file can be found at 🖿root/hl2/scripts.

VGUI code modifications

There is a problem with VGUI screens receiving input in certain games. Unless it is fixed, the game may crash when the cursor points at the screen.

CInput::ExtraMouseSample calls g_pClientMode->CreateMove() without initializing the button flags, thus the VGui screen is updated with bad button input. Since IN_VALIDVGUIINPUT is only set from within CInput::CreateMove, the VGui screens only update when the button flags are valid.

There are two known fixes. They both involve code changes and therefore are only applicable to mods.

Fix 1

In src\game\shared\in_buttons.h, where the other flags are defined add:

   #define IN_VALIDVGUIINPUT		    (1 << 23) //bitflag for vgui fix

next, in src\game\client\in_main.cpp inside method CInput::CreateMove ( ... ) add:

   cmd->buttons |= IN_VALIDVGUIINPUT;

right above:

   g_pClientMode->CreateMove( input_sample_frametime, cmd )

next, in src\cl_dll\c_baseplayer.cpp inside method C_BasePlayer::CreateMove( ... ) add:

   if(pCmd->buttons & IN_VALIDVGUIINPUT)

right above:

   DetermineVguiInputMode( pCmd );

(So it only calls DetermineVguiInputMode if the buttons include our flag)

and finally, inside method C_BasePlayer::DetermineVguiInputMode( ... ) change both instances of:

   pCmd->buttons &= ~(IN_ATTACK | IN_ATTACK2);

to read:

   pCmd->buttons &= ~(IN_ATTACK | IN_ATTACK2 | IN_VALIDVGUIINPUT);

Since an HL2(en) engine update in October VGUI Screens will crash when you put your mouse over them. This is because the g_InputInternal function used in \src\cl_dll\c_vguiscreen.cpp is no longer working. Trying to access it makes it crash. For a workaround, the following C_VGuiScreen::ClientThink( void ) function has proven useful:

	// Convert (u,v) into (px,py)
	int px = (int)(u * m_nPixelWidth + 0.5f);
	int py = (int)(v * m_nPixelHeight + 0.5f);

// START TEDDYS FIX
	for (int i = 0; i < pPanel->GetChildCount(); i++)
	{
		vgui::Button *child = dynamic_cast<vgui::Button*>(pPanel->GetChild(i));
		if ( child )
		{
			int x1, x2, y1, y2;
			child->GetBounds( x1, y1, x2, y2 );

			// Generate mouse input commands
			if ( (m_nButtonState & IN_ATTACK) )
			{
				if ( px >= x1 && px <= x1 + x2 && py >= y1 && py <= y1 + y2 )
					child->FireActionSignal();
			}
		}
	}
// FIN TEDDYS FIX

	if ( m_bLooseThinkNextFrame == true )
	{
		m_bLooseThinkNextFrame = false;
		SetNextClientThink( CLIENT_THINK_NEVER );
	}

Fix 2

An alternative fix would be to add a new boolean variable to CUserCmd such as bButtonFlagsValid that can be set depending on the validity of the button flags. This would allow the structure to internally store this information for its whole lifetime while freeing up that extra button bit.

Example screenshots

VGUI screen used in mod
VGUI screen used to display dynamically drawn EKG data (Pulse!! game)
VGUI screen used to control the mortar in 黑山.