VGUI Screen Creation: Difference between revisions
m (→VGUI code modifications: path to in_buttons.h) |
m (Nesciuse moved page VGUI Screen Creation/en to VGUI Screen Creation without leaving a redirect: Move en subpage to basepage) |
||
(40 intermediate revisions by 19 users not shown) | |||
Line 1: | Line 1: | ||
{{LanguageBar}} | |||
==Adding a VGUI screen to | == Adding a VGUI screen to map== | ||
{{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.)}} | |||
# Create a [[VGUI_Screen|vgui_screen]] entity. This is a point entity. | # Create a [[VGUI_Screen|vgui_screen]] entity. This is a point entity. | ||
# 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 | # 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). | ||
# 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. | # 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. | ||
# Compile the map and test. | # Compile the map and test. | ||
Line 12: | Line 11: | ||
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). | 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== | == Creating a VGUI screen == | ||
VGUI screen files have a ''.res'' extension and should be placed in {{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}} . | |||
# 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}}. | |||
# | # 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. | ||
# The materials used in the ''.res'' file can be found in | |||
# Add the screen to | |||
"VGUI_Screens" | "VGUI_Screens" | ||
Line 33: | Line 31: | ||
} | } | ||
An example | An example {{file|vgui_screen|txt}} file can be found at {{path|root/hl2/scripts}}. | ||
==VGUI code modifications== | ==VGUI code modifications== | ||
There is a problem with VGUI screens receiving input. Unless it is fixed, the game may crash when the cursor points at the screen. | 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. | ||
{{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. | |||
There are two known fixes. They both involve code changes and therefore are only applicable to mods. | There are two known fixes. They both involve code changes and therefore are only applicable to mods. | ||
=== Fix 1 === | === Fix 1 === | ||
In '''src\game\shared\in_buttons.h''', where the other flags are defined add: | |||
In '''src\ | |||
#define IN_VALIDVGUIINPUT (1 << 23) //bitflag for vgui fix | #define IN_VALIDVGUIINPUT (1 << 23) //bitflag for vgui fix | ||
next, in '''in_main.cpp''' inside method | next, in '''src\game\client\in_main.cpp''' inside method {{code|CInput::CreateMove ( ''...'' )}} | ||
add: | add: | ||
cmd->buttons |= IN_VALIDVGUIINPUT; | cmd->buttons |= IN_VALIDVGUIINPUT; | ||
right above: | right above: | ||
g_pClientMode->CreateMove( input_sample_frametime, cmd ) | g_pClientMode->CreateMove( input_sample_frametime, cmd ) | ||
next, in '''c_baseplayer.cpp''' inside method | next, in '''src\cl_dll\c_baseplayer.cpp''' inside method {{code|C_BasePlayer::CreateMove( ''...'' )}} | ||
add: | add: | ||
if(pCmd->buttons & IN_VALIDVGUIINPUT) | if(pCmd->buttons & IN_VALIDVGUIINPUT) | ||
right above: | right above: | ||
DetermineVguiInputMode( pCmd ); | DetermineVguiInputMode( pCmd ); | ||
''(So it only calls | ''(So it only calls {{code|DetermineVguiInputMode}} if the buttons include our flag)'' | ||
and finally, inside method | and finally, inside method {{code|C_BasePlayer::DetermineVguiInputMode( ''...'' )}} | ||
change '''both''' instances of: | change '''both''' instances of: | ||
pCmd->buttons &= ~(IN_ATTACK | IN_ATTACK2); | pCmd->buttons &= ~(IN_ATTACK | IN_ATTACK2); | ||
to read: | to read: | ||
pCmd->buttons &= ~(IN_ATTACK | IN_ATTACK2 | IN_VALIDVGUIINPUT); | pCmd->buttons &= ~(IN_ATTACK | IN_ATTACK2 | IN_VALIDVGUIINPUT); | ||
Since an [[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: | |||
// 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 === | === 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. | |||
== Example screenshots == | |||
[[File:Granted_vgui.jpg|thumb|left|VGUI screen used in mod]] | |||
== | [[File:Ekg_vgui.jpg|thumb|left|VGUI screen used to display dynamically drawn EKG data (Pulse!! game)]] | ||
[[File:Bms mortar vgui.jpg|thumb|left|VGUI screen used to control the mortar in {{bms|3.1}}.]] | |||
[[Category:Programming]] | |||
[[Category:Tutorials]] | |||
[[Category:VGUI|S]] |
Latest revision as of 11:54, 12 July 2024
Adding a VGUI screen to map




- Create a vgui_screen entity. This is a point entity.
- 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).
- 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.
- 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\.
vgui_test_screen.res
is a good starting point for creating a VGUI screen file; it can be found at...\hl2\scripts\screens
.- The materials used in the .res file can be found in
hl2_misc_dir.vpk
. Extract the material files mentioned in the .res file tomaterials\vgui\screens
. - 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 atscripts/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 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
