VGUI Partie 1 : Appel d'un menu et création de la classe

Écrit le 03/07/2003 par Kurim
Dernière mise à jour : 30/01/2006

Introduction

Bon c'est mon premier tutorial, j'ai pas trop l'habitude alors je vais essayer d'être le plus clair possible. Dans ce tut, on va voir comment créer sa propre fenêtre VGUI, la personnaliser, mettre ce qu�on veut dedans, et le faire apparaître en créant une fonction coté serveur (bref un tut complet, qui regroupe certaines chose d'autres tut). Je vais d'abord expliquer comment on crée la fonction pour afficher un menu coté serveur, puis on va créer le nouveau menu coté client et créer les fonctions pour l'afficher. Ensuite j'expliquerai un a un comment mettre en place tout type d'élément dans votre menu (sauf les images, mais bon y'a déjà un autre tut la dessus). Attention !! : c'est pas un tut pour faire du copier coller, on va juste faire un menu sans intérêt, donc lisez les explications, sinon ça sert à rien...

NOTE IMPORTANTE : Ce tutorial fait partie d'un article composé en réalité de 3 tutoriaux. Il est important de lire les 2 autres tutoriaux car celui-ci, seul, n'aboutit à aucun résultat.

Créer une fonction pour appeler un menu VGUI

Donc ça commence coté serveur, on va créer une fonction pour afficher un menu VGUI. La c'est simple, y'a plein de tut qui expliquent comment faire, voici une méthode de plus : côté client, le code cherche à lire un message, « VGUIMenu », qui n'est jamais envoyé coté serveur parce qu'il n'existe pas (le VGUI vient en fait de TFC, et pas de HL, donc bien que le sdk comporte tout ce qu'il faut pour en créer, les codeurs de valve n'ont pas fait de fonction pour en afficher coté serveur). Donc la tout ce joue dans player.h et .cpp. On commence par le .h, on déclare notre fonction qui va nous permettre d'afficher le menu. A la fin du fichier, avant le }; mettez :

void ShowVGUI(  int iMenu );

Ensuite player.cpp, on déclare le message à envoyer au client. Ajoutez ça au bon endroit (au début) :

int gmsgGeigerRange = 0;
int gmsgVGUIMenu = 0;//

puis, un peu plus loin, on enregistre son nom (VGUIMenu) et sa taille (1 octet) :

gmsgAmmoX = REG_USER_MSG("AmmoX", 2);
gmsgVGUIMenu = REG_USER_MSG("VGUIMenu", 1);

et, en fin de fichier, on crée notre fonction qui envoie simplement l'id du menu qu'on veut afficher :

void CBasePlayer::ShowVGUI(  int iMenu )
{
    MESSAGE_BEGIN( MSG_ONE, gmsgVGUIMenu, NULL, pev );
    WRITE_BYTE( iMenu );
    MESSAGE_END();
}

Maintenant on va créer une commande console pour faire apparaître le menu qu'on veut. En fait pour utiliser un menu, appelez cette fonction (ShowVGUI) la ou vous voulez le lancer. Par exemple, pour lancer un menu quand le joueur naît, mettez le ShowVGUI dans CBasePlayer::Spawn(). Bon pour la commande console, c'est dans client.cpp après :

else if (FStrEq(pcmd, "lastinv" ))
{
    GetClassPtr((CBasePlayer *)pev)->SelectLastItem();
}
else if (FStrEq(pcmd, "showvgui" ))
{
    GetClassPtr((CBasePlayer *)pev)->ShowVGUI( atoi( CMD_ARGV(1) );
}

Et la, en tapant « showvgui 2 » par exemple dans la console, ça lancera le menu VGUI avec l'id 2, le menu pour le choix de l'équipe en l'occurrence. (voir dans la partie d'après pour l'id des menus). Voila je pense que cette partie est claire, de toute façon vous pouvez retrouver ce code dans quasiment n'importe quel tut sur le VGUI...

Créer un nouveau VGUI

Bon avant de pouvoir intégrer des éléments à notre menu, il va d'abord falloir le créer... Il faut d'abord déclarer une nouvelle classe, dans vgui_TeamFortressViewport.h, cherchez :

class CTeamMenuPanel;

et ajoutez en dessous :

class CMonMenuPanel;

ensuite on va créer des fonctions pour créer et afficher le menu, après ces deux lignes :

void        CreateClassMenu( void );
CMenuPanel*    ShowClassMenu( void );

ajoutez :

void        CreateMonMenu( void );
CMenuPanel*    ShowMonMenu( void );

maintenant on va créer le pointeur sur cette classe afin de pouvoir travailler dessus, après :

CClassMenuPanel    *m_pClassMenu;

mettez :

CMonMenuPanel    *m_pMonMenu;

Voilà pour les déclarations. On passe maintenant à vgui_TeamFortressViewport.cpp. On va d'abord réinitialiser le pointeur. Cherchez :

m_pClassMenu = NULL;

et ajoutez après :

m_pMonMenu = NULL;

Puis plus bas dans cette même fonction, après :

CreateClassMenu();

mettez :

CreateMonMenu();

On lance donc la création du menu ici. Donc normalement, lors de l'initialisation de TeamFortressViewport, le menu va se créer (mais pas apparaître). Donc on va créer la fonction CreateMonMenu(), histoire de voir à quoi elle sert... recherchez :

void TeamFortressViewport::CreateClassMenu()
{
    // Create the panel
    m_pClassMenu = new CClassMenuPanel(100, false, 0, 0, ScreenWidth, ScreenHeight);
    m_pClassMenu->setParent(this);
    m_pClassMenu->setVisible( false );
}

et après cette fonction de 3 lignes, mettez :

void TeamFortressViewport::CreateMonMenu()
{
    m_pMonMenu = new CMonMenuPanel(100, false, 0, 0, ScreenWidth, ScreenHeight);
    m_pMonMenu->setParent(this);
    m_pMonMenu->setVisible(false);
}

Voilà, ici on remplie le pointeur avec une nouvelle fenêtre, le premier paramètre est la transparence, de 0 à 255, les 4 suivants sont les coordonnés de la fenêtre, X, Y, LongueurX et LargeurY, donc ici on crée juste la base du menu, un panneau semi-transparent qui couvre tout l'écran. On lui donne comme parent this, c'est-à-dire le viewport (ce que représente la classe TeamfortressViewPort, voir un peu plus loin pour les explications des liens de parentés), puis on le rend invisible. Avec ça, on a créer un nouveau menu. Donc après on remonte dans le fichier vers

void TeamFortressViewport::Initialize( void )

et on rajoute, après le if de m_pClassMenu toujours, ça :

if (m_pMonMenu)
{
    m_pMonMenu->Initialize();
}

Donc ça ça veut dire, si le menu existe (si il a été créé avec CreateMonMenu), alors on l'initialise. La fonction Initialize() du menu sera créé plus tard parce qu'elle se trouvera dans un autre fichier, le fichier du menu. Là on va faire la fonction ShowMonMenu(), fonction qui sera appelé quand on doit faire apparaître le menu. Donc retournez la ou vous avez fait le CreateMonMenu, et ajoutez ça après :

CMenuPanel* TeamFortressViewport::ShowMonMenu()
{
    m_pMonMenu->Reset();
    return m_pMonMenu;
}

Cette fonction est appelée par ShowVGUIMenu(), pour connaître quel menu il doit afficher. Là on reset le menu (on le remet comme au début au cas ou il soit déjà utilisé et qu'il y ait des trucs à remettre à zéro), puis on retourne m_pMonMenu, le pointeur de notre menu, pour que la fonction ShowVGUIMenu() puisse l'afficher. On va d'ailleurs s'en occuper maintenant. Pour note, cette fonction est directement appelé par MsgFunc_VGUIMenu(), la fonction qui lit le message qu'on envoie coté serveur (avec l'id du menu). On attribue donc un n° d'id à notre menu, et si le n° correspond à celui du message, on l'affiche. Dans la fonction ShowVGUIMenu(), après :

case MENU_CLASS:
    pNewMenu = ShowClassMenu();
    break;

faite un nouveau case comme ça :

case MENU_MONMENU:
    pNewMenu = ShowMonMenu();
    break;

MENU_MONMENU est le define qui correspond à l'id, il faut le déclarer dans tf_defs.h après :

#define MENU_REPEATHELP      8

faire :

#define MENU_MONMENU        9

Donc notre menu à le n°9, donc pour le faire apparaître coté serveur, il faut faire un ShowVGUI(9), ou alors vous pouvez recopier les defines des menus coté serveur et les mettre dans util.h, et dans ce cas vous faite un ShowVGUI(MENU_MONMENU). Si vous faite un autre menu après, mettez-lui le n°10, etc.