User:Psycommando/VGUI OverrideTest

From Valve Developer Community
Jump to navigation Jump to search


Author's note :

This page is a logbook for an experiment on VGUI. I put it here, so anybody can learn from my mistakes, or something. 
Its also a neat way to start messing around with vgui.

The Test

Valve hasn't given us access to the dll handling the main menu, loading screens, and console. But, those panels are still accessible and modifiable at runtime. Here is how it can be done (HL2 single player OrangeBox mod):

Add the following in your ..\src\game\client\vgui_int.cpp file. This is a simple console command to print out a list of childrens and basic infos. This can also be done with the vgui_drawtree 1 console command.


Add to end of file : ..\src\game\client\vgui_int.cpp

CON_COMMAND( 
             test_listinfoforpanel,  //The actual console command that we'll type in the console
             "Show infos for panel, including childrens listing, and HPanel#. If no params specified, displays info about root panel. : <HPanel#>"
           )
{
    VPANEL panel;

    if ( args.ArgC() == 2 )
    {
        //parse the HPanel #
        panel = vgui::ivgui()->HandleToPanel( Q_atoi( args.ArgV()[1] ) );
    }
    else
    {
        //Panel 1 is always the static panel (parent of gameuidll) at least it seams to be...
        panel = vgui::ivgui()->HandleToPanel( 1 );
    }

    GetInfoAboutPanel( panel );
}

void GetInfoAboutPanel( VPANEL panel )
{
    if( panel != 0 )
    {
        int NbChilds = vgui::ipanel()->GetChildCount(panel); //Get our ammount of children VPANELs

        DevMsg( "PanelName: %s, Class: %s, HPanel# : %d, NbChildrens: %d, IsVisible: %d\n",
            vgui::ipanel()->GetName( panel),
            vgui::ipanel()->GetClassName(panel),
            vgui::ivgui()->PanelToHandle( panel ),
            NbChilds,
            vgui::ipanel()->IsVisible(panel)
            );

        ListChilds(NbChilds,panel);
    }
}

void ListChilds( int nbchilds, VPANEL panel )
{
    for( int i = 0; i < nbchilds; ++i )
    {
        VPANEL tmppanel = vgui::ipanel()->GetChild( panel, i ); //Get the child of panel, at index i
        DevMsg( "- %d : ", i );
        int NbChilds = vgui::ipanel()->GetChildCount(tmppanel); //Get the ammount of child from panel's child VPANEL

        DevMsg( "PanelName: %s, Class: %s, HPanel# : %d, NbChildrens: %d, IsVisible: %d\n",
            vgui::ipanel()->GetName( tmppanel), 
            vgui::ipanel()->GetClassName(tmppanel),
            vgui::ivgui()->PanelToHandle( tmppanel ),
            NbChilds,
            vgui::ipanel()->IsVisible(tmppanel)
            );
    }
}

So, it's nice to print all this stuff on the console but why not use the info for something ? Let's make a console command to hide/show VPANEL based on their HPanel number.

Add to end of file : ..\src\game\client\vgui_int.cpp

CON_COMMAND( test_setvisible, "Show or hide the panel : <HPanel#> <1/0>." )
{
    if ( args.ArgC() == 3 )
    {
        //This convert the HPanel value into an actual VPANEL
        VPANEL panel = vgui::ivgui()->HandleToPanel( Q_atoi( args.ArgV()[1] ) );
        vgui::ipanel()->SetVisible( panel, (bool)Q_atoi( args.ArgV()[2] ) ); //Set our panel's visibility state
    }
    else
    {
        //Wrong number of params print the help message!
        engine->ClientCmd_Unrestricted( "help test_setvisible" );
    }
}

Have fun hiding panels, you can also try changing other params than visibility, just don't start deleting panels arbitrarily, or the game might crash when it tries to access those now deleted panels.

Oh, and don't assume that HPanel numbers( Panel Handle ) are always the same value, they may change at runtime or at the next launch.