Override GameUI: Difference between revisions
(Genesis: Day One) |
Thunder4ik (talk | contribs) m (→top: Unicodifying, replaced: [[Image: → [[File:) |
||
(8 intermediate revisions by 6 users not shown) | |||
Line 1: | Line 1: | ||
The [[Source SDK 2013|Source 2013]] branch offers two new functions for '''overriding [[GameUI]]'''. This is the method used by the current main menu of ''[[Team Fortress 2]]'', and can now be used to have more control over any mod's UI. The first function (which is covered by most of this tutorial) is SetMainMenuOverride(), which takes a [[VPANEL]] and makes it the sole visible child of the GameUI root. | The [[Source SDK 2013|Source 2013]] branch offers two new functions for '''overriding [[GameUI]]'''. This is the method used by the current main menu of ''[[Team Fortress 2]]'', and can now be used to have more control over any mod's UI. The first function (which is covered by most of this tutorial) is SetMainMenuOverride(), which takes a [[VPANEL]] and makes it the sole visible child of the GameUI root. | ||
[[File:TF2_Main_Menu.jpeg|right|thumb|The main menu of [[Team Fortress 2]].]] | |||
==Requirements== | ==Requirements== | ||
Line 9: | Line 11: | ||
==Creating a root panel== | ==Creating a root panel== | ||
The first and most important part of the overriding process is the panel that is used. Here, we will be using a child class that includes functions to access the GameUI interface. These files need to be saved in a folder under the client project. | The first and most important part of the overriding process is the panel that is used. Here, we will be using a child class that includes functions to access the GameUI interface. These files need to be saved in a folder/filter under the client project in Visual Studio. | ||
{{todo|This panel needs to handle an actual menu as a child of this at some point.}} | {{todo|This panel needs to handle an actual menu as a child of this at some point.}} | ||
=== | ===OverrideUI_RootPanel.h=== | ||
<source lang="cpp"> | <source lang="cpp"> | ||
#include "vgui_controls/Panel.h" | #include "vgui_controls/Panel.h" | ||
Line 40: | Line 42: | ||
extern OverrideUI_RootPanel *guiroot; | extern OverrideUI_RootPanel *guiroot; | ||
</source> | </source> | ||
=== | ===OverrideUI_RootPanel.cpp=== | ||
Here, we're going to be doing a couple things in advance. First of all, we have an interface to the GameUI DLL, which will be ready to access whenever need be. The OverrideGameUI() function will be used to call our needed functions straight from the DLL once the panel has been created. | Here, we're going to be doing a couple things in advance. First of all, we have an interface to the GameUI DLL, which will be ready to access whenever need be. The OverrideGameUI() function will be used to call our needed functions straight from the DLL once the panel has been created. | ||
<source lang="cpp"> | <source lang="cpp"> | ||
Line 62: | Line 64: | ||
static CDllDemandLoader g_GameUIDLL( "GameUI" ); | static CDllDemandLoader g_GameUIDLL( "GameUI" ); | ||
OverrideUI_RootPanel *guiroot = NULL; | |||
void OverrideGameUI() | void OverrideGameUI() | ||
Line 139: | Line 141: | ||
} | } | ||
</source> | </source> | ||
==Creating an interface== | ==Creating an interface== | ||
The next thing to do is create an interface to create and destroy the panel. The difference between this and the panel in [[VGUI2: Creating a panel|this tutorial]] is that the panel will be created without a parent and will be redirected afterwards. These files should also be put in the same folder as above for easy access. | The next thing to do is create an interface to create and destroy the panel. The difference between this and the panel in [[VGUI2: Creating a panel|this tutorial]] is that the panel will be created without a parent and will be redirected afterwards. These files should also be put in the same folder as above for easy access. | ||
Line 164: | Line 167: | ||
#include "cbase.h" | #include "cbase.h" | ||
#include "ioverrideinterface.h" | #include "ioverrideinterface.h" | ||
#include " | #include "Overrideui_RootPanel.h" | ||
// Derived class of override interface | // Derived class of override interface | ||
Line 173: | Line 176: | ||
public: | public: | ||
UI_Interface( void ) | int UI_Interface( void ) | ||
{ | { | ||
MainMenu = NULL; | MainMenu = NULL; | ||
Line 205: | Line 208: | ||
IOverrideInterface *OverrideUI = ( IOverrideInterface * )&g_SMenu; | IOverrideInterface *OverrideUI = ( IOverrideInterface * )&g_SMenu; | ||
</source> | </source> | ||
==Calling the functions== | ==Calling the functions== | ||
Finally, we're going to be plugging these functions into the VGUI client loading function VGui_CreateGlobalPanels(). This is found about halfway through the vgui_int.cpp file. Right after the first set of VPANEL declarations, enter this in: | Finally, we're going to be plugging these functions into the VGUI client loading function VGui_CreateGlobalPanels(). This is found about halfway through the vgui_int.cpp file. Right after the first set of VPANEL declarations, enter this in: | ||
Line 211: | Line 215: | ||
OverrideGameUI(); | OverrideGameUI(); | ||
</source> | </source> | ||
Once that's done, move to the top of the file and include the IOverrideInterface.h and | Once that's done, move to the top of the file and include the '''IOverrideInterface.h''' and '''Overrideui_RootPanel.h''' files. And after the MP3 player functions are declared below that, add: | ||
<source lang="cpp"> | <source lang="cpp"> | ||
void OverrideGameUI(); | void OverrideGameUI(); | ||
</source> | </source> | ||
==Calling menu commands== | ==Calling menu commands== | ||
The second new function that IGameUI offers is SendMainMenuCommand(), which takes dialog-opening command strings that can normally be found in the command values in GameMenu.res. When making a new menu, be sure to keep this function in mind if you don't want to make your own versions of these dialogs. | The second new function that IGameUI offers is SendMainMenuCommand(), which takes dialog-opening command strings that can normally be found in the command values in [[GameMenu]].res. When making a new menu, be sure to keep this function in mind if you don't want to make your own versions of these dialogs. | ||
==Conclusion== | ==Conclusion== | ||
Feel free to play around with this setup. It took innumerable tries to get a setup to work correctly, and this is the result. Be sure to report any issues with or suggest corrections to this tutorial. | Feel free to play around with this setup. It took innumerable tries to get a setup to work correctly, and this is the result. Be sure to report any issues with or suggest corrections to this tutorial. | ||
==Changelog== | |||
<source lang="cpp">UI_RootPanel *guiroot = NULL;</source> (line 21 of Override_RootPanel.cpp) changed to <source lang="cpp">OverrideUI_RootPanel *guiroot = NULL;</source> to solve undefined error | |||
<source lang="cpp">UI_Interface(void)</source> (line 12 of OverrideInterface.cpp) changed to <source lang="cpp">int UI_Interface(void)</source> to solve int expected error | |||
[[Category:Tutorials]] | [[Category:Tutorials]] | ||
[[Category:Programming]] | [[Category:Programming]] | ||
[[Category:SDK 2013]] | [[Category:SDK 2013]] |
Latest revision as of 11:42, 8 January 2024
The Source 2013 branch offers two new functions for overriding GameUI. This is the method used by the current main menu of Team Fortress 2, and can now be used to have more control over any mod's UI. The first function (which is covered by most of this tutorial) is SetMainMenuOverride(), which takes a VPANEL and makes it the sole visible child of the GameUI root.

Requirements
- A mod running on Source SDK 2013
- Knowledge of C++
Have read and/or understand:
Creating a root panel
The first and most important part of the overriding process is the panel that is used. Here, we will be using a child class that includes functions to access the GameUI interface. These files need to be saved in a folder/filter under the client project in Visual Studio.
OverrideUI_RootPanel.h
#include "vgui_controls/Panel.h"
#include "GameUI/IGameUI.h"
// This class is what is actually used instead of the main menu.
class OverrideUI_RootPanel : public vgui::Panel
{
DECLARE_CLASS_SIMPLE( OverrideUI_RootPanel, vgui::Panel );
public:
OverrideUI_RootPanel(vgui::VPANEL parent);
virtual ~OverrideUI_RootPanel();
IGameUI* GetGameUI();
protected:
virtual void ApplySchemeSettings(vgui::IScheme *pScheme);
private:
bool LoadGameUI();
int m_ExitingFrameCount;
bool m_bCopyFrameBuffer;
IGameUI* gameui;
};
extern OverrideUI_RootPanel *guiroot;
OverrideUI_RootPanel.cpp
Here, we're going to be doing a couple things in advance. First of all, we have an interface to the GameUI DLL, which will be ready to access whenever need be. The OverrideGameUI() function will be used to call our needed functions straight from the DLL once the panel has been created.
#include "cbase.h"
#include "overrideui_rootpanel.h"
#include "ioverrideinterface.h"
#include "vgui/ILocalize.h"
#include "vgui/IPanel.h"
#include "vgui/ISurface.h"
#include "vgui/ISystem.h"
#include "vgui/IVGui.h"
#include "ienginevgui.h"
#include <engine/IEngineSound.h>
#include "filesystem.h"
using namespace vgui;
// See interface.h/.cpp for specifics: basically this ensures that we actually Sys_UnloadModule the dll and that we don't call Sys_LoadModule
// over and over again.
static CDllDemandLoader g_GameUIDLL( "GameUI" );
OverrideUI_RootPanel *guiroot = NULL;
void OverrideGameUI()
{
if( !OverrideUI->GetPanel() )
{
OverrideUI->Create(NULL);
}
if( guiroot->GetGameUI() )
{
guiroot->GetGameUI()->SetMainMenuOverride( guiroot->GetVPanel() );
return;
}
}
OverrideUI_RootPanel::OverrideUI_RootPanel(VPANEL parent) : Panel( NULL, "OverrideUIRootPanel" )
{
SetParent(parent);
guiroot = this;
m_bCopyFrameBuffer = false;
gameui = NULL;
LoadGameUI();
m_ExitingFrameCount = 0;
}
IGameUI *OverrideUI_RootPanel::GetGameUI()
{
if( !gameui )
{
if ( !LoadGameUI() )
return NULL;
}
return gameui;
}
bool OverrideUI_RootPanel::LoadGameUI()
{
if( !gameui )
{
CreateInterfaceFn gameUIFactory = g_GameUIDLL.GetFactory();
if ( gameUIFactory )
{
gameui = (IGameUI *) gameUIFactory(GAMEUI_INTERFACE_VERSION, NULL);
if( !gameui )
{
return false;
}
}
else
{
return false;
}
}
return true;
}
OverrideUI_RootPanel::~OverrideUI_RootPanel()
{
gameui = NULL;
g_GameUIDLL.Unload();
}
void OverrideUI_RootPanel::ApplySchemeSettings(IScheme *pScheme)
{
BaseClass::ApplySchemeSettings(pScheme);
// Resize the panel to the screen size
// Otherwise, it'll just be in a little corner
int wide, tall;
vgui::surface()->GetScreenSize(wide, tall);
SetSize(wide,tall);
}
Creating an interface
The next thing to do is create an interface to create and destroy the panel. The difference between this and the panel in this tutorial is that the panel will be created without a parent and will be redirected afterwards. These files should also be put in the same folder as above for easy access.
IOverrideInterface.h
#include <vgui/VGUI.h>
namespace vgui
{
class Panel;
}
class IOverrideInterface
{
public:
virtual void Create( vgui::VPANEL parent ) = 0;
virtual vgui::VPANEL GetPanel( void ) = 0;
virtual void Destroy( void ) = 0;
};
extern IOverrideInterface *OverrideUI;
OverrideInterface.cpp
#include "cbase.h"
#include "ioverrideinterface.h"
#include "Overrideui_RootPanel.h"
// Derived class of override interface
class COverrideInterface : public IOverrideInterface
{
private:
OverrideUI_RootPanel *MainMenu;
public:
int UI_Interface( void )
{
MainMenu = NULL;
}
void Create( vgui::VPANEL parent )
{
// Create immediately
MainMenu = new OverrideUI_RootPanel(parent);
}
vgui::VPANEL GetPanel( void )
{
if ( !MainMenu )
return NULL;
return MainMenu->GetVPanel();
}
void Destroy( void )
{
if ( MainMenu )
{
MainMenu->SetParent( (vgui::Panel *)NULL );
delete MainMenu;
}
}
};
static COverrideInterface g_SMenu;
IOverrideInterface *OverrideUI = ( IOverrideInterface * )&g_SMenu;
Calling the functions
Finally, we're going to be plugging these functions into the VGUI client loading function VGui_CreateGlobalPanels(). This is found about halfway through the vgui_int.cpp file. Right after the first set of VPANEL declarations, enter this in:
OverrideUI->Create( NULL );
OverrideGameUI();
Once that's done, move to the top of the file and include the IOverrideInterface.h and Overrideui_RootPanel.h files. And after the MP3 player functions are declared below that, add:
void OverrideGameUI();
The second new function that IGameUI offers is SendMainMenuCommand(), which takes dialog-opening command strings that can normally be found in the command values in GameMenu.res. When making a new menu, be sure to keep this function in mind if you don't want to make your own versions of these dialogs.
Conclusion
Feel free to play around with this setup. It took innumerable tries to get a setup to work correctly, and this is the result. Be sure to report any issues with or suggest corrections to this tutorial.
Changelog
UI_RootPanel *guiroot = NULL;
(line 21 of Override_RootPanel.cpp) changed to
OverrideUI_RootPanel *guiroot = NULL;
to solve undefined error
UI_Interface(void)
(line 12 of OverrideInterface.cpp) changed to
int UI_Interface(void)
to solve int expected error