Gestion des événements liés à la fenêtre et aux périphériques dentrée.

Slides:



Advertisements
Présentations similaires
Bratec Martin ..
Advertisements

NOTIFICATION ÉLECTRONIQUE
Fragilité : une notion fragile ?
SEMINAIRE DU 10 AVRIL 2010 programmation du futur Hôtel de Ville
Phono-sémantique différentielle des monosyllabes italiens
MAGGIO 1967 BOLOGNA - CERVIA ANOMALIES DU SOMMEIL CHEZ L'HOMME
droit + pub = ? vincent gautrais professeur agrégé – avocat
Transcription de la présentation:

Gestion des événements liés à la fenêtre et aux périphériques dentrée

2 Programmation par événement Lusager peut déplacer ou changer la dimension dune fenêtre à lécran au moyen de la souris, changer le repère de la caméra, modifier les caractéristiques géométriques des objets de la scène, etc. Habituellement, on opte pour un mode de gestion par événement des périphériques dentrée : - À chaque fois quun signal est transmis dun périphérique dentrée (pression dun bouton ou dune clé), un nouvel événement est créé. - La donnée obtenue et un identificateur du périphérique dentrée sont rangés dans une file dévénements. - Les événements sont traités selon un protocole « premier arrivé - premier servi ». - À chaque type dévénement est associé une fonction de prise en compte de cet événement permettant de gérer les actions à prendre selon létat dun périphérique. Le traitement dun événement dans la file consiste donc à exécuter cette fonction de prise en compte de ce type dévénement.

3 Gestion des événements en OpenGL OpenGL fournit différents outils pour faciliter la gestion des événements : glutMouseFunc(Souris); où « Souris » est la fonction de prise en compte dun événement associé à la souris. glutKeyboardFunc(Clavier); où « Clavier » est la fonction de prise en compte dun événement associé au clavier. Exemple :Lorsque vous pressez ou relâchez un bouton de la souris, pressez une touche du clavier, ou déplacez la souris, un nouvel événement est créé.

4 Gestion du clavier En pressant une touche sur le clavier, un événement est généré qui doit être pris en compte : glutKeyboardFunc(Clavier); Lentête de la fonction « Clavier » est comme suit : void Clavier(unsigned char cle, int x, int y); La valeur de « cle » correspond à la valeur ASCII de la touche sélectionnée. x et y désignent la position de la souris lorsque la touche a été pressée. Plusieurs clés peuvent être utilisées dans une application offrant un grand éventail de choix à lusager.

5 Usage de clés spéciales Les touches spéciales F1, F2, …. et les flèches peuvent être utilisées grâce à la primitive glutSpecialFunc (). En pressant une telle touche sur le clavier, un événement est généré qui doit être pris en compte : glutSpecialFunc(Touches_speciales); Lentête de la fonction « Clavier » est comme suit : void Touches_speciales(int cle, int x, int y); À lintérieur de cette fonction, on pourrait par ex. effectuer les tests suivants : if (cle == GLUT_KEY_F1)... ou encore if (cle == GLUT_KEY_UP)...

6 Usage de clés spéciales Les touches spéciales Ctrl, Alt et Shift peuvent être utilisées grâce à la primitive glutGetModifiers(). int glutGetModifiers(); Retourne lune des valeurs suivantes : GLUT_ACTIVE_SHIFT, GLUT_ACTIVE_CTRL, GLUT_ACTIVE_ALT, si cette touche est pressée au moment où un événement provenant du clavier ou de la souris est généré. Exemple : Arrêt dun programme lors de la prise en compte dun événement provenant du clavier. if ((glutGetModifiers() == GLUT_ACTIVE_CTRL) && ((cle == 'c' || (cle == 'C'))) exit(0);

7 Gestion de la souris Pour spécifier le nom de la fonction (en loccurrence, la fonction « Souris ») qui prendra en compte lévénement qui intervient lorsquun bouton de la souris est pressé ou relâché, on a linstruction dOpenGL suivante : glutMouseFunc(Souris); Lentête de cette fonction a la forme suivante : void Souris(int bouton, int etat, int x, int y); où« bouton » peut prendre lune des valeurs suivantes : GLUT_LEFT_BUTTON, GLUT_MIDDLE_BUTTON et GLUT_RIGHT_BUTTON, « etat » peut prendre lune des 2 valeurs GLUT_UP ou GLUT_DOWN, « x, y » désigne la position de la souris lorsque lévénement survient. Note :« x » désigne le # de pixels à partir de la gauche de la fenêtre, « y » désigne le # de pixels à partir du haut de la fenêtre.

8 Exemple I : Lorsque lusager presse le bouton gauche de la souris, un point sera affiché à la fenêtre de lécran à la position de la souris. Lorsquil presse le bouton droit, le programme termine. void Souris(int bouton, int etat, int x, int y) { if((bouton == GLUT_LEFT_BUTTON) && (etat == GLUT_DOWN)) { glBegin(GL_POINTS); glVertex2i(x, H – y); glEnd(); } else if ((bouton == GLUT_RIGHT_BUTTON) && (etat == GLUT_DOWN))exit(-1); } Note :H désigne la hauteur de la fenêtre en pixels.

9 Exemple II : Permet de tracer un rectangle à laide de la souris en pointant 2 sommets opposés de la figure. Chaque nouveau rectangle remplace le précédent; par conséquent, uniquement les 2 sommets du rectangle courant sont conservés. Lorsque les 2 sommets sont spécifiés, le rectangle est tracé. On peut aussi effacer lécran en pressant le bouton droit de la souris. void Souris(int bouton, int etat, int x, int y) { /*« static » permet de conserver les valeurs des variables dun appel de la fonction à un autre.*/ static GLint sommet_x[2]; static GLint sommet_y[2]; static int Nombre_de_sommets = 0;

10 if((bouton == GLUT_LEFT_BUTTON) && (etat == GLUT_DOWN)) { sommet_x[Nombre_de_sommets] = x; sommet_y[Nombre_de_sommets] = H – y; Nombre_de_sommets ++; if(Nombre_de_sommets == 2) { glRecti(sommet_x[0], sommet_y[0], sommet_x[1], sommet_y[1]); Nombre_de_sommets = 0; } else if ((bouton == GLUT_RIGHT_BUTTON) && (etat == GLUT_DOWN)) glClear(GL_COLOR_BUFFER_BIT); glFlush(); }

11 Exemple III : Nous allons tracer un « polyline » de manière interactive. La liste de sommets est spécifiée à laide de la souris; chaque nouveau sommet est rangé à la suite des autres. Si le nombre maximum de sommets est atteint, aucun nouveau sommet sera accepté. Lorsque le bouton de gauche est pressé, le dernier segment est tracé. Lorsque le bouton de droite est pressé, la fenêtre est effacée et tous les sommets sont détruits.

12 void Souris(int bouton, int etat, int x, int y) { #define MAX 20 typedef GLint point_2D[2]; static point_2D liste[MAX];static int dernier = -1; if((bouton == GLUT_LEFT_BUTTON) && (etat == GLUT_DOWN)) && (dernier < (MAX – 1))) { liste[++dernier][0] = x;liste[dernier][1] = H – y; if(dernier > 0) {glBegin(GL_LINES); glVertex2i(liste[dernier-1][0], liste[dernier-1][1]); glVertex2i(liste[dernier][0], liste[dernier][1]); glEnd(); glFlush(); } else if ((bouton == GLUT_RIGHT_BUTTON) && (etat == GLUT_DOWN)) { dernier = -1;glClear(GL_COLOR_BUFFER_BIT);glFlush(); }

13 Exemple IV : Tracé dune courbe ou dun polyline. static GLint dernier = -1; static GLint Liste[50][2]; void Initialisation(void) { glClearColor(0.0, 0.0, 0.0, 0.0); glClear(GL_COLOR_BUFFER_BIT); glColor3f(1.0, 0.0, 0.0); glMatrixMode(GL_PROJECTION);glLoadIdentity(); gluOrtho2D(0.0, 800.0, 0.0, 500.0); } void Affichage() {glFlush(); } void reconfiguration(int w, int h) { glViewport(0, 0, (GLsizei) w, (GLsizei) h); glMatrixMode(GL_PROJECTION);glLoadIdentity(); gluOrtho2D(0.0, (GLdouble) w, 0.0, (GLdouble) h); }

14 En conservant la clé t enfoncée tout en déplaçant la souris, cela revient à effectuer un tracé à la main. void Clavier(unsigned char cle, int sx, int sy) {int i; glColor3f(1.0, 0.0, 0.0); GLint x = sx;GLint y = sy; switch(cle) {case 't' :// Tracé dun point. glBegin(GL_POINTS); glVertex2i(x, y); glEnd(); break; case 'p' :// Tracé d'un polyline. glBegin(GL_LINE_STRIP); for (i = 0; i <= dernier; i++) glVertex2i(Liste[i][0], Liste[i][1]); glEnd(); break; case 'E' : exit(-1);// Permet de terminer le programme. default : break;// Aucune action. }; glFlush(); }

15 void Ajouter_Position(int cle, int sx, int sy) {// La clé « » permet dajouter une position à une liste. if (cle == GLUT_KEY_LEFT) {Liste[++dernier][0] = sx;Liste[dernier][1] = sy; }else exit(-1); } void main(int argc, char** argv) {glutInit(&argc, argv); glutInitDisplayMode (GLUT_RGB); glutInitWindowSize(800, 500); glutInitWindowPosition(500, 100); glutCreateWindow("Trace de courbe ou polyline"); glutDisplayFunc(Affichage); glutKeyboardFunc(Clavier); glutSpecialFunc(Ajouter_Position); glutReshapeFunc(reconfiguration); Initialisation(); glutMainLoop(); }

16 Exemple V : Affichage dun rectangle Dans les exemples précédents, les primitives daffichage se retrouvaient dans les fonctions de prise en charge des événements au lieu de la fonction « Affichage ». On peut corriger cette situation comme dans lexemple suivant. static GLint x1 = 0, y1 = 0, x2 = 0, y2 = 0; static bool premier = true; void Affichage() { glClear(GL_COLOR_BUFFER_BIT); glBegin(GL_POLYGON); glVertex2i(x1, y1); glVertex2i(x1, y2); glVertex2i(x2, y2); glVertex2i(x2, y1); glEnd(); glFlush(); }

17 void Souris(int bouton, int etat, int x, int y) { glColor3f(1.0, 0.0, 0.0); if(etat == GLUT_DOWN && bouton == GLUT_LEFT_BUTTON) exit(-1); if(etat == GLUT_DOWN && bouton == GLUT_RIGHT_BUTTON) { if (premier) { x1 = x;y1 = y; premier = ! premier; } else { premier = ! premier; x2 = x;y2 = y; glutPostRedisplay(); // Rappeler la fonction Affichage. } glFlush(); }

18 Mouvement de la souris Des événements sont aussi générés lorsque vous déplacez la souris. 1 er cas : la souris est déplacée en même temps que vous pressez sur un bouton. void glutMotionFunc(void(*f) (int x, int y)); La fonction f permet de prendre en compte cet événement où (x, y) désigne la position de la souris. 2 ième cas : la souris est déplacée sans que vous pressiez sur un bouton. void glutPassiveMotionFunc(void(*f) (int x, int y)); La fonction f permet de prendre en compte cet événement où (x, y) désigne la position de la souris.

19 Exemple VI : Affichage dune courbe en déplaçant la souris le long dune trajectoire tout en conservant un bouton pressé. GLint Largeur_brosse = 20; void Souris_en_mouvement(int sx, int sy) { glRecti(sx, sy, sx + Largeur_brosse, sy + Largeur_brosse); glFlush(); } void Affichage() { glClear(GL_COLOR_BUFFER_BIT); glFlush(); } void main(int argc, char** argv) {... glutDisplayFunc(Affichage); glutMotionFunc(Souris_en_mouvement); glutReshapeFunc(reconfiguration);... }

20 Gestion des menus GLUT permet de créer et de gérer des menus. Ces menus apparaissent lorsquon presse un bouton de la souris. 4 étapes : 1. Identification dune fonction qui prendra en compte chaque élément du menu. int glutCreateMenu(void (*f) (int v)); La fonction f pose les gestes voulus pour chaque valeur de v. Le menu créé devient le menu courant. 2. Ajout dune entrée au menu courant. void glutAddMenuEntry(char * nom, int v); Ajoute une entrée au menu identifiée par une chaîne de caractères. v désigne le numéro de cette entrée. 3. Établir le lien entre ce menu et un bouton de la souris (GLUT_RIGHT_BUTTON, GLUT_MIDDLE_BUTTON ou GLUT_LEFT_BUTTON). void glutAttachMenu(int bouton);

21 4. Implantation de la fonction qui prendra en compte chaque élément du menu. void f(int v) { if (v == 1)... if (v == 2) } Note : Le menu créé à létape 1 devient le menu courant mais celui-ci peut être changé grâce à la fonction :void glutSetMenu(int id); Nous pouvons ajouter des sous-menus à un menu principal : void glutAddSubMenu(char * nom, int m); « nom » désigne une nouvelle entrée au menu courant laquelle est un sous-menu dont le numéro « m » est la valeur entière retournée lorsque le sous-menu est créé.

22 Exemple VII : Reprise de lexemple IV où un menu principal est ajouté en lien avec le bouton droit de la souris. void Menu_principal(int valeur) { if (valeur == 1) { glBegin(GL_LINE_STRIP); for (int i = 0; i <= dernier; i++) glVertex2i(Liste[i][0], Liste[i][1]); glEnd(); }; if (valeur == 2) glClear(GL_COLOR_BUFFER_BIT); if (valeur == 3) exit(0); glFlush(); }

23 void main(int argc, char** argv) { glutInit(&argc, argv); glutInitDisplayMode (GLUT_RGB); glutInitWindowSize(800, 500); glutInitWindowPosition(500, 100); glutCreateWindow("Trace de courbe ou polyline"); glutDisplayFunc(Affichage); glutKeyboardFunc(Clavier); glutSpecialFunc(Ajouter_Position); glutCreateMenu(Menu_principal); glutAddMenuEntry("Affichez le polyline.", 1); glutAddMenuEntry("Effacez l'ecran.", 2); glutAddMenuEntry("Quittez l'application.", 3); glutAttachMenu(GLUT_RIGHT_BUTTON); glutReshapeFunc(reconfiguration); Initialisation(); glutMainLoop(); }

24 Gérer un processus à larrière-plan Vous pouvez spécifier une fonction qui devra sexécuter si aucun autre événement nest en cours : void glutIdleFunc(void (*f)(void)); Pour désactiver lexécution de la fonction, on peut utiliser la primitive précédente en passant en paramètre la valeur NULL. Cela est particulièrement intéressant en animation.

25 Gestion des événements liés aux fenêtres Spécifier la fonction appelée lorsque le contenu de la fenêtre doit être redessiné : void glutDisplayFunc(void (*f)(void)); Spécifier la fonction appelée lorsque la fenêtre est redimensionnée ou déplacée : void glutReshapeFunc(void (*f)(int L, int h)); Les 2 paramètres désignent la largeur et la hauteur de la fenêtre. En général, la fonction f renferme un appel à glViewport(), de manière que laffichage soit découpé à la nouvelle taille, et redéfinit la matrice de projection pour que le ratio de limage projetée corresponde au cadrage afin déviter les distorsions. Spécifier que le contenu de la fenêtre active doit être redessiné. void glutPostRedisplay(void); La fonction f de glutDisplayFunc sera appelée.