Sommaire Index Rechercher Liens A Propos
[LinuxFocus Image]
[Barre de Navigation]
  Nouveautés   Archives

GLUT: Utilisation des Menus

par Miguel Angel Sepulveda


Cet article est le troisième dans notre série sur la Boite à Outils pour OpenGL (GLUT - GL Utility Toolkit) écrite par Mark Kilgard. GLUT est très utile pour les développeurs car elle encapsule dans une API simple à apprendre et simple à utiliser, toute ce qui dans une application OpenGL, dépend de la plate-forme.

Comme nous le disions dans les articles précédents, OpenGL à été conçue pour être une librairie graphique 3D de haut niveau totalement indépendante de la plate-forme. Ouvrir des fenêtres, contrôler le clavier, etc... sont fortement dépendant de la plate-forme et donc en-dehors des attributions d'OpenGL. GLUT nous permet d'écrire du code totalement portable en offrant une interface commune à toutes les plates-formes pour gérer les choses comme les fenêtres, le double buffer, le rendu de texte, les événements clavier et les menus.

Aujourd'hui nous allons explorer l'utilisation des menus à l'intérieur de notre application OpenGL. Les menus sont un des moyens de communications de l'utilisateurs. Dans notre article précédent ( Gestion des Fenêtres ) nous avons fait la démonstration d'une autre technique : les événements clavier. GLUT capture les événements claviers et souris et nous permet de définir la fonction de traitement associée (NDT : appelées fonctions callback). L'inconvénient des raccourcis claviers, c'est qu'ils sont invisibles et que l'utilisateur doit lire le manuel ou se rappeler quelle touche fait quoi. Les menus sont beaucoup plus pratiques et flexibles car ils sont graphiques et montre à l'utilisateur les options disponibles.

Pour illustrer notre propos, voici un programme d'exemple ( ../../common/May1998/example1.tar.gz ). Ce programme modifie l'exemple de notre précédent article sur la Gestion des Fenêtres . Chargez le programme et compilez le en utilisant le makefile fourni.

La compilation nécessite une implémentation des librairies OpenGL (par exemple Mesa) et GLUT. Ces deux librairies sont largement disponibles et inclus d'une manière ou d'une autre dans la plupart des distributions Linux. Après la compilation nous obtenons un exécutable, example1. Lancez le, vous devriez voir un une nouvelle fenêtre avec un triangle aux arêtes rouge - vert - bleu (cf. figure de gauche).

Le cadre contient une fenêtre principale avec un fond noir et un triangle au milieu et une sous-fenêtre avec un fond gris et du texte à l'intérieur. Notre exemple est en fait une animation temps-réel aussi le compteur de la zone de texte doit s'incrémenter.

Bougez le pointeur de la souris sur la fenêtre principale cliquez et maintenez enfoncé le bouton gauche. Cet événement est traité par notre exemple et doit faire apparaître le menu suivant :

Le menu contient trois actions ( démarrer/arrêter la rotation, démarrer/arrêter la translation, changer de couleur) et une dernière option pour quitter l'application. Tout en maintenant enfoncé le bouton gauche bougez sur chaque action pour voir ce qui se passe.

En sélectionnant "Rotation On", le triangle commencera à tourner autour de son centre de gravité , "Translation On" le fera se déplacer horizontalement en revenant au début quand le bord est atteint. L'option "Change Color" déclenchera un sous-menu avec ces nouvelles options:

  • Red Dessine le triangle en rouge
  • Blue Dessine le triangle en bleu
  • Green Dessine le triangle en vert
  • RGB Dessine le triangle en rouge, vert, bleu

C'est un exemple très simple d'utilisation de menus dans une application OpenGL. L'aspect des menus et sous-menus dépend de la plate-forme. L'apparence ci-dessus est celle obtenue avec GLUT sous Linux, compilé et lancé sous Windows 95/NT les menus auraient un autre aspect. Ce qui compte c'est que la fonctionnalité est portable aussi longtemps que vous utiliserez GLUT.

Vous remarquerez que le menu principal a deux types d'entrées différentes. Le premier type (Rotation On, Translation On) change après que l'action demandée est été exécutée. ce qui veut dire qu'après avoir lancé le triangle en rotation, la prochaine fois que vous verrez le menu il y aura marqué "Rotation Off". L'autre type d'entrée reste constante c'est le cas de "Change Color", "Red", "Blue" et "Green".

Il y a deux ou trois choses intéressantes dont je voudrais entretenir le lecteur avant de continuer sur les menus. Est-ce que vous vous souvenez que ce programme à deux touches de commandes ? ( Gestion des Fenêtres ). Ces touches sont "q" pour quitter et "i" pour activer/désactiver la zone de texte. Essayez les maintenant, elles marchent encore.
Alors que la zone de texte est active (la sous-fenêtre) placez le pointeur de souris dans la région grise et cliquez sur le bouton gauche? Surprise! Vous voyez un nouveau menu:

Ce qui démontre que les menus ne sont pas uniquement attachés aux événements mais qu'ils sont transmis au contexte courant. Nous avions déjà mentionné dans notre article sur les sous-fenêtres qu'elles possèdent le propre contexte OpenGL, nous voyons ici une autre conséquence de ce fait. Deux menus ont été attachés au même événement (le click gauche) mais à différents contextes. Le développeurs à maintenant un main un outil puissant pour écrire une interface utilisateur graphique sophistiquée à ses applications.

Encore plus intéressant, si vous enlevez la zone de texte en pressant sur "i" et que vous placez votre souris sur le bord haut du cadre vous ne pourrez pas retrouver l'affichage "this is a dummy menu". Pourquoi ? Car en cachant la sous-fenêtre vous cachez son sous-contexte (les menus attachés également).

Maintenant décrivons le contenu du programme, Je supposerai dans ce qui suit que le lecteur est familier avec les sujets traités dans les articles précédents sur GLUT et OpenGL. La fonction main() contient plusieurs sections distinctes, l'ordre est important ! :

  • Initialisation de GLUT. Ouvre une fenêtre d'affichage, transmet les arguments de la ligne de commande, fixe le mode d'affichage et les options.
  • Création de la fenêtre principale. Crée la fenêtre principale, fixe les fonctions callback associées à cette fenêtre, fixe la fonction callback idle.
  • Création d'un sous-menu. C sous menu gère l'action " Change Color " et sera inclus dans le menu principal qui suit.
  • Création du menu principal.Crée le menu principal, ajoute les entrées du menu ainsi que le sous-menu précédent. Enfin, attache ce menu à l'événement clique gauche. Vous noterez que nous sommes toujours dans le contexte de la fenêtre principale.
  • Création d'une liste d'appel GL. Ceci est une fonctionnalité avancée d'OpenGL et ne sera pas traitée complètement ici. Pour l'instant il vous suffit de savoir qu'une telle liste permet de construire et d'encapsuler des objets OpenGL duran,t l'éxécution pour une utilisation ultérieure. Utiliser un élément d'une liste d'appel GL est plus efficace que de construire et reconstruire sans cesse les objets. Dans cet exemple il ya quatre éléments à notre liste : un triangle rouge, un bleu, un vert et un rouge - vert - bleu.
  • Création d'une sous-fenêtre. Crée une sous-fenêtre, sauvegarde un identifiant de cette fenêtre [NDT : un "handle"], fixe les fonctions callback appropriées. Après que la sous-fenêtre est été crée, un nouveau contexte est activé.
  • Création du menu principal de la sous-fenêtre. Comme précédemment nous créons un nouveau menu, ajoutons les entrées et nous le rattachons à l'événements "clique gauche". Le menu sera attaché au contexte de la sous-fenêtre.

A part la création des menus, les autres sections devraient être familière au lecteur. Une rapide lecture du code source de l'exemple révèle combien cela est facile à réaliser. Les Menus sont créés par la directive int glutCreateMenu( void (f*)(int) ) la fonction f est la fonction callback qui recois comme argument le numéro identifiant l'entrée du menu sélectionné et est chargé d'accomplir l'action associée. La valeur retournée par la fonction int glutCreateMenu( void (f*)(int) ) est un entier identifiant la nouvelle fenêtre créée.

La fonction callback utilisée pour gérer les évènements menus est simple. Regardez la fonction void mainMenu(int) ou void subMenu(int) , elles sont essentiellement constituées d'une structure conditionnelle "switch" qui traite l'action choisie.

Après la création du menu, notre code ajoute les entrées du menu par l'appel de void glutAddMenuEntry(char*s,int nr), ou s est le texte à écrire dans le menu et nr un entier identifiant cette entrée, c'est ce numéro qui est passé comme argument à la fonction callback lorsque cette option est choisie. Evidemment il ne vaut mieux pas utiliser deux fois le même identifiant.

Les sous-menus sont ajoutés de manière similaire en utilisant la fonction void glutAddSubMenu(char *s, int nr).

Enfin pour terminer la déclaration du menu, il est attaché à un événement (le bouton gauche de la souris) en utilisant la fonction glutAttachMenu. Cette fonction peut également prender comme argument GLUT_RIGHT_BUTTON, GLUT_MIDDLE_BUTTON.

Les entrées du menus peuvent être changées à l'exécution en utilisant la fonction void glutChangeToMenuEntry(int entry, char *s, int value), qui remplace l'entrée "entry" de la fenêtre courante par un autre ayant le texte s et l'identifiant value. Dans notre exemple nous utilisons

   glutChangeToMenuEntry(2, "Translation On", 2);
	

afin de changer le texte de la seconde entrée du menu principal (de même pour les autres entrées).

GLUT permet d'autre choses encore : transformer une entrée en un sous-menu et vice-versa, détruire un menu, enlever des entrées, etc. Nous ne détaillerons pas toutes ces fonctions ici car je crois que l'exemple présenté est simple mais suffit déjà pour la plupart des utilisations. Si vous avez besoin d'autres fonctionnalités, regardez dans les manuels de GLUT les plus récents.


Traduit par Mathieu Veron

Pour en savoir plus:
© 1998 Miguel Angel Sepulveda
Ce site Web est maintenu par Miguel A Sepulveda.