Zh/VGUI Screen Creation: Difference between revisions

From Valve Developer Community
< Zh
Jump to navigation Jump to search
No edit summary
(deepseek translation)
Line 1: Line 1:
{{wip}}{{translating}}
{{Machine Translation}}
{{LanguageBar}}
{{LanguageBar|title=VGUI屏幕创建}}


== Adding a VGUI screen to map==
== 在关卡中添加VGUI屏幕 ==
{{note|This section assumes a mod where VGUI screens have been fixed (see the [[#VGUI code modifications|code modifications section]] below) but otherwise left the same. VGUI screens do ''not'' work in {{hl2|4}} or {{hl2dm|4}}; they crash the game. ({{css|4}} and many other games not tested.)}}
{{note|本节假设您已在模组中修复VGUI屏幕问题(参见下文[[#VGUI代码修改|代码修改部分]])。VGUI屏幕在{{hl2|4}}{{hl2dm|4}}中''无法运行'',会导致游戏崩溃。(未测试{{css|4}}等其他游戏)}}


# Create a {{L|VGUI_Screen|vgui_screen}} entity. This is a point entity.
# 创建{{L|VGUI_Screen|vgui_screen}}实体。这是一个点实体。
# 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 {{code|vgui_screens.txt}} (which should be in the {{code|scripts}} directory).
# 设置其'''面板名称'''为需要显示的屏幕名称(非屏幕文件名)。可用屏幕列表位于{{code|vgui_screens.txt}}(应位于{{code|scripts}}目录)。
# 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.
# 设置'''面板世界宽度''''''面板世界高度'''以匹配笔刷尺寸。初始建议尺寸为宽64单位,高32单位。
# 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).
实体在地图中的位置标记面板左下角。面板方向(表面法线)由实体角度(Yaw)决定。


== Creating a VGUI screen ==
== 创建VGUI屏幕 ==
VGUI screen files have a ''.res'' extension and should be placed in {{code|scripts\screens\}}.
VGUI屏幕文件使用''.res''扩展名,应存放于{{code|scripts\screens\}}目录。


# {{path|vgui_test_screen|res}} is a good starting point for creating a VGUI screen file; it can be found at {{path|...\hl2\scripts\screens}} .
# 使用{{path|vgui_test_screen|res}}作为创建VGUI屏幕文件的模板,该文件位于{{path|...\hl2\scripts\screens}}
# The materials used in the ''.res'' file can be found in {{path|hl2_misc_dir|vpk}}. Extract the material files mentioned in the ''.res'' file to {{path|materials\vgui\screens}}.
# ''.res''文件中使用的材质可从{{path|hl2_misc_dir|vpk}}提取。将.res文件提到的材质文件解压到{{path|materials\vgui\screens}}
# Add the screen to {{path|scripts\vgui_screens|txt}}. If it does not exist, create it. Here is an example which describes screen {{code|vgui_test_screen}} at {{path|scripts/screens/vgui_test_screen|res}}. Adjust it for your screen.
# 将屏幕添加到{{path|scripts\vgui_screens|txt}}。若文件不存在则新建。以下是描述{{path|scripts/screens/vgui_test_screen|res}}中{{code|vgui_test_screen}}的示例,请根据实际调整:


  "VGUI_Screens"
  "VGUI_Screens"
Line 23: Line 23:
     "vgui_test_screen"
     "vgui_test_screen"
     {
     {
         // This is our example screen
         // 示例屏幕配置
         "type" "vgui_screen_panel"
         "type" "vgui_screen_panel"
         "pixelswide" 480
         "pixelswide" 480
         "pixelshigh" 240
         "pixelshigh" 240
         // This must be the file you created in step 1
         // 必须与步骤1创建的文件名一致
         "resfile" "scripts/screens/vgui_test_screen.res"
         "resfile" "scripts/screens/vgui_test_screen.res"
     }  
     }  
  }
  }


An example {{file|vgui_screen|txt}} file can be found at {{path|root/hl2/scripts}}.
示例{{file|vgui_screen|txt}}文件可在{{path|root/hl2/scripts}}找到。


==VGUI code modifications==
==VGUI代码修改==


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.
部分游戏中存在VGUI屏幕接收输入导致崩溃的问题,需进行以下修复。


{{code|CInput::ExtraMouseSample}} calls {{code|g_pClientMode->CreateMove()}} without initializing the button flags, thus the VGui screen is updated with bad button input.  Since {{code|IN_VALIDVGUIINPUT}} is only set from within {{code|CInput::CreateMove}}, the VGui screens only update when the button flags are valid.
{{code|CInput::ExtraMouseSample}}调用{{code|g_pClientMode->CreateMove()}}时未初始化按钮标志,导致VGUI屏幕使用错误输入更新。由于{{code|IN_VALIDVGUIINPUT}}仅在{{code|CInput::CreateMove}}中设置,VGUI屏幕只能在按钮标志有效时更新。


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:
'''src\game\shared\in_buttons.h'''的按钮标志定义处添加:
     #define IN_VALIDVGUIINPUT     (1 << 23) //bitflag for vgui fix
     #define IN_VALIDVGUIINPUT     (1 << 23) //VGUI修复用位标记


next, in '''src\game\client\in_main.cpp''' inside method {{code|CInput::CreateMove ( ''...'' )}}
接着在'''src\game\client\in_main.cpp'''{{code|CInput::CreateMove ( ''...'' )}}方法内:
add:
在以下代码上方添加:
     cmd->buttons |= IN_VALIDVGUIINPUT;
     cmd->buttons |= IN_VALIDVGUIINPUT;
right above:
原代码:
     g_pClientMode->CreateMove( input_sample_frametime, cmd )
     g_pClientMode->CreateMove( input_sample_frametime, cmd )


next, in '''src\cl_dll\c_baseplayer.cpp''' inside method {{code|C_BasePlayer::CreateMove( ''...'' )}}
然后在'''src\cl_dll\c_baseplayer.cpp'''{{code|C_BasePlayer::CreateMove( ''...'' )}}方法内:
add:
在以下代码前添加条件判断:
     if(pCmd->buttons & IN_VALIDVGUIINPUT)
     if(pCmd->buttons & IN_VALIDVGUIINPUT)
right above:
原代码:
     DetermineVguiInputMode( pCmd );
     DetermineVguiInputMode( pCmd );
''(So it only calls {{code|DetermineVguiInputMode}} if the buttons include our flag)''
(即仅当按钮包含标记时才调用{{code|DetermineVguiInputMode}}


and finally, inside method {{code|C_BasePlayer::DetermineVguiInputMode( ''...'' )}}
最后在{{code|C_BasePlayer::DetermineVguiInputMode( ''...'' )}}方法中:
change '''both''' instances of:
'''两处'''出现的:
     pCmd->buttons &= ~(IN_ATTACK | IN_ATTACK2);
     pCmd->buttons &= ~(IN_ATTACK | IN_ATTACK2);
to read:
修改为:
     pCmd->buttons &= ~(IN_ATTACK | IN_ATTACK2 | IN_VALIDVGUIINPUT);
     pCmd->buttons &= ~(IN_ATTACK | IN_ATTACK2 | IN_VALIDVGUIINPUT);


Since an {{L|HL2}} engine update in October VGUI Screens will crash when you put your mouse over them. This is because the {{code|g_InputInternal}} function used in {{code|\src\cl_dll\c_vguiscreen.cpp}} is no longer working. Trying to access it makes it crash. For a workaround, the following {{code|C_VGuiScreen::ClientThink( void )}} function has proven useful:
自10月{{L|HL2}}引擎更新后,鼠标悬停VGUI屏幕会导致崩溃。这是因为{{code|\src\cl_dll\c_vguiscreen.cpp}}中使用的{{code|g_InputInternal}}函数失效。以下修改后的{{code|C_VGuiScreen::ClientThink( void )}}可作为临时解决方案:


  // Convert (u,v) into (px,py)
  // (u,v)转换为(px,py)
  int px = (int)(u * m_nPixelWidth + 0.5f);
  int px = (int)(u * m_nPixelWidth + 0.5f);
  int py = (int)(v * m_nPixelHeight + 0.5f);
  int py = (int)(v * m_nPixelHeight + 0.5f);
   
   
  // START TEDDYS FIX
  // TEDDY修复代码开始
  for (int i = 0; i < pPanel->GetChildCount(); i++)
  for (int i = 0; i < pPanel->GetChildCount(); i++)
  {
  {
Line 80: Line 80:
  child->GetBounds( x1, y1, x2, y2 );
  child->GetBounds( x1, y1, x2, y2 );
   
   
  // Generate mouse input commands
  // 生成鼠标输入指令
  if ( (m_nButtonState & IN_ATTACK) )
  if ( (m_nButtonState & IN_ATTACK) )
  {
  {
Line 88: Line 88:
  }
  }
  }
  }
  // FIN TEDDYS FIX
  // TEDDY修复代码结束
   
   
  if ( m_bLooseThinkNextFrame == true )
  if ( m_bLooseThinkNextFrame == true )
Line 96: Line 96:
  }
  }


=== Fix 2 ===
=== 方案二 ===
An alternative fix would be to add a new boolean variable to {{code|CUserCmd}} such as {{code|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.
另一种方案是在{{code|CUserCmd}}结构体中添加布尔变量{{code|bButtonFlagsValid}}来标记按钮标志的有效性。这样可在整个生命周期内存储该信息,同时释放按钮位资源。


== Example screenshots ==
== 示例截图 ==
[[File:Granted_vgui.jpg|thumb|left|VGUI screen used in mod]]
[[File:Granted_vgui.jpg|thumb|left|模组中使用的VGUI屏幕]]
[[File:Ekg_vgui.jpg|thumb|left|VGUI screen used to display dynamically drawn EKG data (Pulse!! game)]]
[[File:Ekg_vgui.jpg|thumb|left|用于动态显示心电图数据的VGUI屏幕(Pulse!!游戏)]]
[[File:Bms mortar vgui.jpg|thumb|left|VGUI screen used to control the mortar in {{bms|3.1}}.]]
[[File:Bms mortar vgui.jpg|thumb|left|{{bms|3.1}}中用于控制迫击炮的VGUI屏幕]]
{{ACategory|Programming}}
{{ACategory|程序设计}}
{{ACategory|Tutorials}}
{{ACategory|教程指南}}
{{ACategory|VGUI|S}}
{{ACategory|VGUI|S}}

Revision as of 03:11, 24 April 2025

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)
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屏幕