VGUI屏幕创建

From Valve Developer Community
< Zh
Jump to navigation Jump to search
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.


在关卡中添加VGUI屏幕

Note.png注意:本节假设您已在模组中修复VGUI屏幕问题(参见下文代码修改部分)。VGUI屏幕在半衰期2 半衰期2半衰期2:死亡竞赛 半衰期2:死亡竞赛无法运行,会导致游戏崩溃。(未测试反恐精英:起源 反恐精英:起源等其他游戏)
  1. 创建vgui_screen(en)实体。这是一个点实体。
  2. 设置其面板名称为需要显示的屏幕名称(非屏幕文件名)。可用屏幕列表位于vgui_screens.txt(应位于scripts目录)。
  3. 设置面板世界宽度面板世界高度以匹配笔刷尺寸。初始建议尺寸为宽64单位,高32单位。
  4. 编译地图并测试。

实体在地图中的位置标记面板左下角。面板方向(表面法线)由实体角度(Yaw)决定。

创建VGUI屏幕

VGUI屏幕文件使用.res扩展名,应存放于scripts\screens\目录。

  1. 使用🖿vgui_test_screen.res作为创建VGUI屏幕文件的模板,该文件位于🖿...\hl2\scripts\screens
  2. .res文件中使用的材质可从🖿hl2_misc_dir.vpk提取。将.res文件提到的材质文件解压到🖿materials\vgui\screens
  3. 将屏幕添加到🖿scripts\vgui_screens.txt。若文件不存在则新建。以下是描述🖿scripts/screens/vgui_test_screen.resvgui_test_screen的示例,请根据实际调整:
"VGUI_Screens"
{
   "vgui_test_screen"
   {
       // 示例屏幕配置
       "type"		"vgui_screen_panel"
       "pixelswide"	480
       "pixelshigh"	240
       // 必须与步骤1创建的文件名一致
       "resfile"	"scripts/screens/vgui_test_screen.res"
   } 
}

示例🖿vgui_screen.txt文件可在🖿root/hl2/scripts找到。

VGUI代码修改

部分游戏中存在VGUI屏幕接收输入导致崩溃的问题,需进行以下修复。

CInput::ExtraMouseSample调用g_pClientMode->CreateMove()时未初始化按钮标志,导致VGUI屏幕使用错误输入更新。由于IN_VALIDVGUIINPUT仅在CInput::CreateMove中设置,VGUI屏幕只能在按钮标志有效时更新。

有两种已知修复方案,均涉及代码修改,仅适用于模组开发。

方案一

src\game\shared\in_buttons.h的按钮标志定义处添加:

   #define IN_VALIDVGUIINPUT		    (1 << 23) //VGUI修复用位标记

接着在src\game\client\in_main.cppCInput::CreateMove ( ... )方法内: 在以下代码上方添加:

   cmd->buttons |= IN_VALIDVGUIINPUT;

原代码:

   g_pClientMode->CreateMove( input_sample_frametime, cmd )

然后在src\cl_dll\c_baseplayer.cppC_BasePlayer::CreateMove( ... )方法内: 在以下代码前添加条件判断:

   if(pCmd->buttons & IN_VALIDVGUIINPUT)

原代码:

   DetermineVguiInputMode( pCmd );

(即仅当按钮包含标记时才调用DetermineVguiInputMode

最后在C_BasePlayer::DetermineVguiInputMode( ... )方法中: 将两处出现的:

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

修改为:

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

自10月HL2(en)引擎更新后,鼠标悬停VGUI屏幕会导致崩溃。这是因为\src\cl_dll\c_vguiscreen.cpp中使用的g_InputInternal函数失效。以下修改后的C_VGuiScreen::ClientThink( void )可作为临时解决方案:

	// 将(u,v)转换为(px,py)
	int px = (int)(u * m_nPixelWidth + 0.5f);
	int py = (int)(v * m_nPixelHeight + 0.5f);

// TEDDY修复代码开始
	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 );

			// 生成鼠标输入指令
			if ( (m_nButtonState & IN_ATTACK) )
			{
				if ( px >= x1 && px <= x1 + x2 && py >= y1 && py <= y1 + y2 )
					child->FireActionSignal();
			}
		}
	}
// TEDDY修复代码结束

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

方案二

另一种方案是在CUserCmd结构体中添加布尔变量bButtonFlagsValid来标记按钮标志的有效性。这样可在整个生命周期内存储该信息,同时释放按钮位资源。

示例截图

模组中使用的VGUI屏幕
用于动态显示心电图数据的VGUI屏幕(Pulse!!游戏)
黑山中用于控制迫击炮的VGUI屏幕