Supports de cours
Le polycopié est téléchargeable ICI.

On donne un certain nombre de programmes interactifs de démonstration des fonctions de base d’OpenGL:

Les sources, exécutables compilés pour Windows ainsi que les images utilisées pour les texture sont regroupés dans les trois archives suivantes:

Sources :demoGLUT/glut-demos-src.zip
Exécutables pour Windows :demoGLUT/glut-demos-win32exe.zip
Fichiers bitmap pour les textures :demoGLUT/glut-demos-bmp.zip

Pour information:
Ces programmes contiennent une partie de code C auto-généré pour définir un comportement interactif par l’utilisation de code muni de valeurs que l’utilisateur peut modifier. C’est le programme convert qui se charge d’effectuer la conversion selon un format prédéfini.

#include <stdio.h> #include <stdlib.h> #define CLASS_TEXT 0x0 #define CLASS_FLOAT 0x1 #define CLASS_INT 0x2 #define CLASS_ENUM 0x4 typedef struct { struct { int Count; struct { int Count; struct { int Class; char Text[256]; int Index; } Items[32]; } Lines[256]; } Content; struct { int Count; int Min[256],Value[256],Max[256]; } Ints; struct { int Count; float Min[256],Value[256],Max[256]; } Floats; struct { int Count; struct { int Count; char Values[32][256]; } Lists[256]; } Enums; } data; data *Data; int expression(char *s){ int class,index,i,j; switch (s[0]){ case 'f': class=CLASS_FLOAT; index=Data->Floats.Count; switch(sscanf(s+1," %f : %f : %f",Data->Floats.Min+Data->Floats.Count,Data->Floats.Value+Data->Floats.Count,Data->Floats.Max+Data->Floats.Count)){ case 2: Data->Floats.Max[Data->Floats.Count]=Data->Floats.Value[Data->Floats.Count]; case 3: Data->Floats.Count++; break; default: printf("Invalid float expression specifier (\"%s\")",s); return 0; } break; case 'i': class=CLASS_INT; index=Data->Ints.Count; switch(sscanf(s+1," %i : %i : %i",Data->Ints.Min+Data->Ints.Count,Data->Ints.Value+Data->Ints.Count,Data->Ints.Max+Data->Ints.Count)){ case 2: Data->Ints.Max[Data->Ints.Count]=Data->Ints.Value[Data->Ints.Count]; case 3: Data->Ints.Count++; break; default: printf("Invalid int expression specifier (\"%s\")",s); return 0; } break; case 'e': class=CLASS_ENUM; index=Data->Enums.Count; i=0; j=0; Data->Enums.Lists[Data->Enums.Count].Count=1; while (s[i++]){ switch (s[i]){ case 0: case ':': Data->Enums.Lists[Data->Enums.Count].Values[Data->Enums.Lists[Data->Enums.Count].Count-1][j]=0; j=0; Data->Enums.Lists[Data->Enums.Count].Count++; break; default: Data->Enums.Lists[Data->Enums.Count].Values[Data->Enums.Lists[Data->Enums.Count].Count-1][j]=s[i]; j++; } } Data->Enums.Lists[Data->Enums.Count].Count--; Data->Enums.Count++; break; default: printf("Unrecognized expression tag ('%c')",s[0]); return 0; } Data->Content.Lines[Data->Content.Count-1].Items[Data->Content.Lines[Data->Content.Count-1].Count].Class=class; Data->Content.Lines[Data->Content.Count-1].Items[Data->Content.Lines[Data->Content.Count-1].Count].Index=index; sprintf(Data->Content.Lines[Data->Content.Count-1].Items[Data->Content.Lines[Data->Content.Count-1].Count].Text,s); Data->Content.Lines[Data->Content.Count-1].Count++; return 1; } int fconvert(FILE *src,FILE *dst,char *Prefix){ int l=0,i,j,k,m; while (!feof(src)){ char s[256],t[2]; if (fscanf(src,"%255[^#\n]",s)==1){ Data->Content.Lines[Data->Content.Count-1].Items[Data->Content.Lines[Data->Content.Count-1].Count].Class=CLASS_TEXT; Data->Content.Lines[Data->Content.Count-1].Items[Data->Content.Lines[Data->Content.Count-1].Count].Index=-1; sprintf(Data->Content.Lines[Data->Content.Count-1].Items[Data->Content.Lines[Data->Content.Count-1].Count].Text,s); Data->Content.Lines[Data->Content.Count-1].Count++; if (fscanf(src,"%1[\n]",t)==1){ Data->Content.Lines[Data->Content.Count].Count=0; Data->Content.Count++; l++; } } else { if (fscanf(src,"#%255[^#]#",s)==1){ if (!expression(s)) return 0; } else { char c; if ((c=fgetc(src))=='#'){ printf("Unmatched '#' (near line %d)\n",l); return 0; } else { Data->Content.Lines[Data->Content.Count-1].Items[Data->Content.Lines[Data->Content.Count-1].Count].Class=CLASS_TEXT; Data->Content.Lines[Data->Content.Count-1].Items[Data->Content.Lines[Data->Content.Count-1].Count].Index=-1; sprintf(Data->Content.Lines[Data->Content.Count-1].Items[Data->Content.Lines[Data->Content.Count-1].Count].Text,""); Data->Content.Lines[Data->Content.Count-1].Count++; Data->Content.Lines[Data->Content.Count].Count=0; Data->Content.Count++; l++; } } } } if (Data->Ints.Count){ fprintf(dst,"static int _%s_Ints[%i]={",Prefix,Data->Ints.Count); for (i=0;i<Data->Ints.Count;i++){ fprintf(dst,"%i",Data->Ints.Value[i]); if (i<Data->Ints.Count-1) fprintf(dst,","); } fprintf(dst,"};\n\n"); } if (Data->Floats.Count){ fprintf(dst,"static float _%s_Floats[%i]={",Prefix,Data->Floats.Count); for (i=0;i<Data->Floats.Count;i++){ fprintf(dst,"%f",Data->Floats.Value[i]); if (i<Data->Floats.Count-1) fprintf(dst,","); } fprintf(dst,"};\n\n"); } if (Data->Enums.Count){ fprintf(dst,"static int _%s_Enums[%i]={",Prefix,Data->Enums.Count); for (i=0;i<Data->Enums.Count;i++){ fprintf(dst,"%s",Data->Enums.Lists[i].Values[0]); if (i<Data->Enums.Count-1) fprintf(dst,","); } fprintf(dst,"};\n\n"); } for (i=0;i<Data->Content.Count-1;i++){ for (j=0;j<Data->Content.Lines[i].Count;j++){ k=Data->Content.Lines[i].Items[j].Index; switch (Data->Content.Lines[i].Items[j].Class){ case CLASS_TEXT: fprintf(dst,"static char *_%s_Line%i_Item%i=\"%s\";\n",Prefix,i,j,Data->Content.Lines[i].Items[j].Text); break; case CLASS_INT: fprintf(dst,"static item_int _%s_Line%i_Item%i={%i,_%s_Ints+%i,%i};\n",Prefix,i,j,Data->Ints.Min[k],Prefix,k,Data->Ints.Max[k]); break; case CLASS_FLOAT: fprintf(dst,"static item_float _%s_Line%i_Item%i={%f,_%s_Floats+%i,%f};\n",Prefix,i,j,Data->Floats.Min[k],Prefix,k,Data->Floats.Max[k]); break; case CLASS_ENUM: fprintf(dst,"static char * _%s_Line%i_Item%i_List[%i]={",Prefix,i,j,Data->Enums.Lists[k].Count); for (m=0;m<Data->Enums.Lists[k].Count;m++){ fprintf(dst,"\"%s\"",Data->Enums.Lists[k].Values[m]); if (m<Data->Enums.Lists[k].Count-1) fprintf(dst,","); } fprintf(dst,"};\n"); fprintf(dst,"static int _%s_Line%i_Item%i_Values[%i]={",Prefix,i,j,Data->Enums.Lists[k].Count); for (m=0;m<Data->Enums.Lists[k].Count;m++){ fprintf(dst,"%s",Data->Enums.Lists[k].Values[m]); if (m<Data->Enums.Lists[k].Count-1) fprintf(dst,","); } fprintf(dst,"};\n"); fprintf(dst,"static item_enum _%s_Line%i_Item%i={%i,_%s_Enums+%i,0,_%s_Line%i_Item%i_List,_%s_Line%i_Item%i_Values};\n",Prefix,i,j,Data->Enums.Lists[k].Count,Prefix,k,Prefix,i,j,Prefix,i,j); break; } } fprintf(dst,"static item _%s_Line%i_Items[]={\n",Prefix,i); for (j=0;j<Data->Content.Lines[i].Count;j++){ fprintf(dst," {"); switch (Data->Content.Lines[i].Items[j].Class){ case CLASS_TEXT:fprintf(dst,"ITEM_TEXT");break; case CLASS_INT:fprintf(dst,"ITEM_INT");break; case CLASS_FLOAT:fprintf(dst,"ITEM_FLOAT");break; case CLASS_ENUM:fprintf(dst,"ITEM_ENUM");break; } if (Data->Content.Lines[i].Items[j].Class) fprintf(dst,",&_%s_Line%i_Item%i}",Prefix,i,j); else fprintf(dst,",_%s_Line%i_Item%i}",Prefix,i,j); if (j<Data->Content.Lines[i].Count-1) fprintf(dst,",\n"); } fprintf(dst,"\n};\n\n"); } fprintf(dst,"static line %sLines[%i]={\n",Prefix,Data->Content.Count-1); for (i=0;i<Data->Content.Count-1;i++){ fprintf(dst," {%i,_%s_Line%i_Items}",Data->Content.Lines[i].Count,Prefix,i); if (i<Data->Content.Count-2) fprintf(dst,",\n"); } fprintf(dst,"\n};\n\n"); fprintf(dst,"void %sDisplay(float MouseX,float MouseY){\n",Prefix); for (i=0;i<Data->Content.Count-1;i++){ fprintf(dst," "); for (j=0;j<Data->Content.Lines[i].Count;j++){ switch (Data->Content.Lines[i].Items[j].Class){ case CLASS_TEXT: fprintf(dst,"%s",Data->Content.Lines[i].Items[j].Text); break; case CLASS_INT: fprintf(dst,"_%s_Ints[%i]",Prefix,Data->Content.Lines[i].Items[j].Index); break; case CLASS_FLOAT: fprintf(dst,"_%s_Floats[%i]",Prefix,Data->Content.Lines[i].Items[j].Index); break; case CLASS_ENUM: fprintf(dst,"_%s_Enums[%i]",Prefix,Data->Content.Lines[i].Items[j].Index); break; } } fprintf(dst,"\n"); } fprintf(dst,"}\n"); return 1; } int convert(char *s,char *t,char *u){ FILE *src,*dst; int r=0; Data=malloc(sizeof(data)); Data->Content.Count=1; Data->Content.Lines[0].Count=0; Data->Ints.Count=0; Data->Floats.Count=0; Data->Enums.Count=0; if (src=fopen(s,"r")){ if (dst=fopen(t,"w")){ r=fconvert(src,dst,u); fclose(dst); } else printf("Cannot write file \"%s\"",t); fclose(src); } else printf("Cannot read file \"%s\"",s); free(Data); return r; } int main(int argc,char *argv[]){ char t[256]; switch (argc){ case 2: sprintf(t,"%s.h",argv[1]); return !convert(argv[1],t,""); case 3: return !convert(argv[1],argv[2],""); case 4: return !convert(argv[1],argv[2],argv[3]); default: printf("usage : convert source [dest] [prefix]\n"); return 0; } }

Le fichier demo.h contient le code nécessaire au fonctionnement de l’interface graphique multi-fenêtre, en utilisant GLUT:

Fichier : demoGLUT/demo.h
#include <stdlib.h> #include <stdio.h> #include <math.h> #include <time.h> #include <assert.h> #include "glut_import.h" /********************************************************************* * CONSTANTS *********************************************************************/ #define INVALID_WINDOW_INDEX (-1) #define PI 3.141592653589793 /********************************************************************* * TYPES *********************************************************************/ typedef struct { int X,Y,Width,Height; } rect; /********************************************************************* * UTILITIES *********************************************************************/ int inrect(int X,int Y,rect Rect){ return X>=Rect.X && X<Rect.X+Rect.Width && Y>=Rect.Y && Y<Rect.Y+Rect.Height; } /********************************************************************* * ITEM CLASSES *********************************************************************/ #define ITEM_TEXT 0x0 #define ITEM_INT 0x1 #define ITEM_FLOAT 0x2 #define ITEM_ENUM 0x4 /********************************************************************* * ITEM TYPES *********************************************************************/ typedef struct { int Min,*Value,Max,LastValue; char Text[32]; } item_int; typedef struct { float Min,*Value,Max,LastValue; char Text[32]; } item_float; typedef struct { int Count,*Value,Index; char **List; int *Values; } item_enum; typedef struct { int Class; union{ void *Reference; char *Text; item_int *Int; item_float *Float; item_enum *Enum; } Data; rect Rect; } item; typedef struct { int Count; item *Items; } line; /********************************************************************* * WIDGET CLASSES *********************************************************************/ #define WIDGET_SCENE 0x01 #define WIDGET_CONTROL 0x02 #define WIDGET_SPLIT 0x04 #define WIDGET_TABS 0x08 /********************************************************************* * WIDGET TYPES *********************************************************************/ typedef struct { int Horizontal; float Position; struct widget *Widget1,*Widget2; } split; typedef struct { void (*onDisplay)(float,float); void (*onReshape)(int,int); int Index,X,Y,LastX,LastY; } scene; typedef struct { int Count; line *Lines; int Font; item *Capture; } control; typedef struct { char *Text; struct widget *Child; rect Rect; } tab; typedef struct { int Count,Index; tab *Tabs; int Font; } tabs; typedef struct widget { int Class; union { void *Reference; split *Split; scene *Scene; control *Control; tabs *Tabs; } Data; rect Rect; } widget; /********************************************************************* * WIDGET DESIGN MACRO *********************************************************************/ #define SPLIT(_NAME,_HORIZONTAL,_POSITION,_WIDGET1,_WIDGET2) \ static split _NAME##_DATA={_HORIZONTAL,_POSITION,_WIDGET1,_WIDGET2}; \ static widget _NAME={WIDGET_SPLIT,{&_NAME##_DATA}} #define SCENE(_NAME,_ONDISPLAY,_ONRESHAPE) \ static scene _NAME##_DATA={_ONDISPLAY,_ONRESHAPE,INVALID_WINDOW_INDEX,0,0,0,0}; \ static widget _NAME={WIDGET_SCENE,{&_NAME##_DATA}} #define CONTROL(_NAME,_LINES) \ static control _NAME##_DATA={sizeof(_LINES)/sizeof(*_LINES),_LINES}; \ static widget _NAME={WIDGET_CONTROL,{&_NAME##_DATA}} #define TAB(_NAME,_TEXT,_CHILD) \ static tab _NAME={_TEXT,_CHILD}; #define TABS(_NAME,_TABS) \ static tabs _NAME##_DATA={sizeof(_TABS)/sizeof(*_TABS),0,_TABS}; \ static widget _NAME={WIDGET_TABS,{&_NAME##_DATA}} /********************************************************************* * WIDGET DATA *********************************************************************/ struct { widget *Root; int Index; void *Fonts[3]; int FontSizes[3]; widget *Capture; struct { int X,Y; } CaptureStart; } MainWindow={ NULL, INVALID_WINDOW_INDEX, {GLUT_BITMAP_HELVETICA_10,GLUT_BITMAP_HELVETICA_12,GLUT_BITMAP_HELVETICA_18}, {13,16,23}, NULL }; /********************************************************************* * FUNCTIONS *********************************************************************/ int strWidth(void *,char *); void strPaint(void *,char *,float,float); widget *findCurrentWidget(int,widget *); widget *currentSceneWidget(void); char *itemText(item *); void updateItem(item *); void updateScene(int,scene *); void updateControl(int,control *); void updateSplit(int,split *); void updateTabs(int,tabs *); void updateWidget(int,widget *); void postRedisplayScene(scene *); void postRedisplayMainWindow(void); void postRedisplayWidget(widget *); void postRedisplayScenes(void); void postRedisplay(void); void displayControl(int,control *); void displaySplit(rect,split *); void displayTabs(int,tabs *); void displayWidget(widget *); void reshapeScene(rect,scene *); void reshapeControl(rect,int *,int *,int,control *); void reshapeSplit(rect,split *); void reshapeTabs(rect,int *,int *,int,tabs *); void reshapeWidget(widget *); void reshapeMainWindow(void); int mouseDownItem(int,int,item *); int mouseDownControl(int,int,control *); int mouseDownTabs(int,int,tabs *); int mouseDownWidget(int,int,widget *); void mouseMoveItem(int,int,item *); void mouseMoveWidget(int,int,widget *); void mouseUpItem(int,int,item*); void mouseUpWidget(int,int,widget *); void sceneDisplayFunc(void); void sceneMouseFunc(int,int,int,int); void sceneMotionFunc(int,int); void mainDisplayFunc(void); void mainReshapeFunc(int,int); void mainMouseFunc(int,int,int,int); void mainMotionFunc(int,int); void createSubWindow(widget *); void createWindow(widget *,char *); /********************************************************************* * DRAWING UTILITIES *********************************************************************/ int strWidth(void *font,char *str){ int w=0; char c; while (c=*(str++)) w+=glutBitmapWidth(font,c); return w; } void strPaint(void *font,char *str,float x,float y){ char c; glRasterPos2f(x,y); while (c=*(str++)) glutBitmapCharacter(font,c); } /********************************************************************* * WIDGET UTILITIES *********************************************************************/ widget *findCurrentWidget(int Index,widget *Widget){ widget *w; int i; switch (Widget->Class){ case WIDGET_SPLIT: if (w=findCurrentWidget(Index,Widget->Data.Split->Widget1)) return w; if (w=findCurrentWidget(Index,Widget->Data.Split->Widget2)) return w; break; case WIDGET_SCENE: if (Widget->Data.Scene->Index==Index) return Widget; break; case WIDGET_TABS: for (i=0;i<Widget->Data.Tabs->Count;i++) if (w=findCurrentWidget(Index,Widget->Data.Tabs->Tabs[i].Child)) return w; } return NULL; } widget *currentSceneWidget(void){ return findCurrentWidget(glutGetWindow(),MainWindow.Root); } char *itemText(item *Item){ switch (Item->Class){ case ITEM_TEXT: return Item->Data.Text; case ITEM_INT: return Item->Data.Int->Text; case ITEM_FLOAT: return Item->Data.Float->Text; case ITEM_ENUM: return Item->Data.Enum->List[Item->Data.Enum->Index]; } } /********************************************************************* * WIDGET UPDATING *********************************************************************/ void updateItem(item *Item){ switch (Item->Class){ case ITEM_INT: sprintf(Item->Data.Int->Text,"%i",*Item->Data.Int->Value); break; case ITEM_FLOAT: sprintf(Item->Data.Float->Text,"%f",*Item->Data.Float->Value); break; } } void updateScene(int Visible,scene *Scene){ glutSetWindow(Scene->Index); if (Visible) glutShowWindow(); else glutHideWindow(); } void updateControl(int Visible,control *Control){ int i; for (i=0;i<Control->Count;i++){ int j; for (j=0;j<Control->Lines[i].Count;j++) updateItem(Control->Lines[i].Items+j); } } void updateSplit(int Visible,split *Split){ updateWidget(Visible,Split->Widget1); updateWidget(Visible,Split->Widget2); } void updateTabs(int Visible,tabs *Tabs){ int i; for (i=0;i<Tabs->Count;i++) updateWidget(i==Tabs->Index,Tabs->Tabs[i].Child); } void updateWidget(int Visible,widget *Widget){ int i; switch (Widget->Class){ case WIDGET_SCENE: updateScene(Visible,Widget->Data.Scene); break; case WIDGET_CONTROL: updateControl(Visible,Widget->Data.Control); break; case WIDGET_SPLIT: updateSplit(Visible,Widget->Data.Split); break; case WIDGET_TABS: for (i=0;i<Widget->Data.Tabs->Count;i++) updateWidget(Visible && i==Widget->Data.Tabs->Index,Widget->Data.Tabs->Tabs[i].Child); } } /********************************************************************* * WIDGET REDISPLAY *********************************************************************/ void postRedisplayScene(scene *Scene){ glutSetWindow(Scene->Index); glutPostRedisplay(); } void postRedisplayMainWindow(void){ glutSetWindow(MainWindow.Index); glutPostRedisplay(); } void postRedisplayWidget(widget *Widget){ switch (Widget->Class){ case WIDGET_SCENE: postRedisplayScene(Widget->Data.Scene); break; case WIDGET_SPLIT: postRedisplayWidget(Widget->Data.Split->Widget1); postRedisplayWidget(Widget->Data.Split->Widget2); break; case WIDGET_TABS: postRedisplayWidget(Widget->Data.Tabs->Tabs[Widget->Data.Tabs->Index].Child); } } void postRedisplayScenes(void){ postRedisplayWidget(MainWindow.Root); } void postRedisplay(void){ postRedisplayScenes(); postRedisplayMainWindow(); } /********************************************************************* * WIDGET DRAWING *********************************************************************/ void displayControl(int Font,control *Control){ int i; for (i=0;i<Control->Count;i++){ int j; for (j=0;j<Control->Lines[i].Count;j++){ if (Control->Lines[i].Items[j].Class){ if (Control->Capture==Control->Lines[i].Items+j) glColor3f(0,1,0); else glColor3f(1,0,0); } else glColor3f(0,0,1); strPaint(MainWindow.Fonts[Font],itemText(Control->Lines[i].Items+j),Control->Lines[i].Items[j].Rect.X,Control->Lines[i].Items[j].Rect.Y+MainWindow.FontSizes[Font]); } } } void displaySplit(rect Rect,split * Split){ glColor3f(0.3,0.4,0.8); if (Split->Horizontal) glRecti(Split->Widget1->Rect.X+Split->Widget1->Rect.Width,Rect.Y,Split->Widget2->Rect.X,Rect.Y+Rect.Height); else glRecti(Rect.X,Split->Widget1->Rect.Y+Split->Widget1->Rect.Height,Rect.X+Rect.Width,Split->Widget2->Rect.Y); displayWidget(Split->Widget1); displayWidget(Split->Widget2); }; void displayTabs(int Font,tabs *Tabs){ int i; for (i=0;i<Tabs->Count;i++){ if (i==Tabs->Index) glColor3f(1,0,0); else glColor3f(0,0,0); strPaint(MainWindow.Fonts[Font],Tabs->Tabs[i].Text,Tabs->Tabs[i].Rect.X+MainWindow.FontSizes[Font]/2,Tabs->Tabs[i].Rect.Y+MainWindow.FontSizes[Font]); } displayWidget(Tabs->Tabs[Tabs->Index].Child); } void displayWidget(widget *Widget){ switch (Widget->Class){ case WIDGET_CONTROL: displayControl(Widget->Data.Control->Font,Widget->Data.Control); break; case WIDGET_SPLIT: displaySplit(Widget->Rect,Widget->Data.Split); break; case WIDGET_TABS: displayTabs(Widget->Data.Tabs->Font,Widget->Data.Tabs); break; } } /********************************************************************* * WIDGET RESHAPE *********************************************************************/ void reshapeScene(rect Rect,scene *Scene){ glutSetWindow(Scene->Index); glutReshapeWindow(Rect.Width,Rect.Height); glutPositionWindow(Rect.X,Rect.Y); } void reshapeControl(rect Rect,int *Width,int *Height,int Font,control *Control){ int i,x,y; *Width=0; *Height=0; for (i=0;i<Control->Count;i++){ int j,w=0; for (j=0;j<Control->Lines[i].Count;j++){ Control->Lines[i].Items[j].Rect.X=Rect.X+w; Control->Lines[i].Items[j].Rect.Y=Rect.Y+*Height; Control->Lines[i].Items[j].Rect.Width=strWidth(MainWindow.Fonts[Font],itemText(Control->Lines[i].Items+j)); Control->Lines[i].Items[j].Rect.Height=MainWindow.FontSizes[Font]; w+=Control->Lines[i].Items[j].Rect.Width; } if (w>*Width) *Width=w; *Height+=MainWindow.FontSizes[Font]; } x=(Rect.Width-*Width)/2; if (x<0) x=0; y=(Rect.Height-*Height)/2; if (y<0) y=0; for (i=0;i<Control->Count;i++){ int j; for (j=0;j<Control->Lines[i].Count;j++){ Control->Lines[i].Items[j].Rect.X+=x; Control->Lines[i].Items[j].Rect.Y+=y; } } } void reshapeSplit(rect Rect,split *Split){ float f; Split->Widget1->Rect=Rect; Split->Widget2->Rect=Rect; if (Split->Horizontal){ f=Split->Widget1->Rect.Width*Split->Position-1; Split->Widget2->Rect.X=3+(Split->Widget1->Rect.Width=(int) f); Split->Widget2->Rect.Width=Rect.Width-Split->Widget2->Rect.X; } else { f=Split->Widget1->Rect.Height*Split->Position; Split->Widget2->Rect.Y=3+(Split->Widget1->Rect.Height=(int) f); Split->Widget2->Rect.Height=Rect.Height-Split->Widget2->Rect.Y; } reshapeWidget(Split->Widget1); reshapeWidget(Split->Widget2); } void reshapeTabs(rect Rect,int *Width,int *Height,int Font,tabs *Tabs){ int i,x,y; *Width=0; *Height=MainWindow.FontSizes[Font]*3/2; Rect.Height-=*Height; for (i=0;i<Tabs->Count;i++){ Tabs->Tabs[i].Rect.X=*Width+Rect.X; Tabs->Tabs[i].Rect.Y=Rect.Y; Tabs->Tabs[i].Rect.Width=strWidth(MainWindow.Fonts[Font],Tabs->Tabs[i].Text)+MainWindow.FontSizes[Font]; Tabs->Tabs[i].Rect.Height=*Height; *Width+=Tabs->Tabs[i].Rect.Width; Tabs->Tabs[i].Child->Rect=Rect; Tabs->Tabs[i].Child->Rect.Y+=*Height; reshapeWidget(Tabs->Tabs[i].Child); } } void reshapeWidget(widget *Widget){ int w,h; switch (Widget->Class){ case WIDGET_SCENE: reshapeScene(Widget->Rect,Widget->Data.Scene); break; case WIDGET_CONTROL: Widget->Data.Control->Font=3; do { Widget->Data.Control->Font--; reshapeControl(Widget->Rect,&w,&h,Widget->Data.Control->Font,Widget->Data.Control); } while ((w>Widget->Rect.Width || h>Widget->Rect.Height) && Widget->Data.Control->Font); break; case WIDGET_SPLIT: reshapeSplit(Widget->Rect,Widget->Data.Split); break; case WIDGET_TABS: Widget->Data.Tabs->Font=3; do { Widget->Data.Tabs->Font--; reshapeTabs(Widget->Rect,&w,&h,Widget->Data.Tabs->Font,Widget->Data.Tabs); } while ((w>Widget->Rect.Width || h>Widget->Rect.Height) && Widget->Data.Tabs->Font); } } void reshapeMainWindow(void){ reshapeWidget(MainWindow.Root); } /********************************************************************* * WIDGET MOUSEDOWN *********************************************************************/ int mouseDownItem(int X,int Y,item *Item){ switch (Item->Class){ case ITEM_INT: Item->Data.Int->LastValue=*Item->Data.Int->Value; return inrect(X,Y,Item->Rect); case ITEM_FLOAT: Item->Data.Float->LastValue=*Item->Data.Float->Value; return inrect(X,Y,Item->Rect); case ITEM_ENUM: return inrect(X,Y,Item->Rect); } return 0; } int mouseDownControl(int X,int Y,control *Control){ int i; for (i=0;i<Control->Count;i++){ int j; for (j=0;j<Control->Lines[i].Count;j++) if (mouseDownItem(X,Y,Control->Lines[i].Items+j)){ Control->Capture=Control->Lines[i].Items+j; return 1; }; } Control->Capture=NULL; return 0; } int mouseDownTabs(int X,int Y,tabs *Tabs){ int i; for (i=0;i<Tabs->Count;i++){ if (inrect(X,Y,Tabs->Tabs[i].Rect)){ Tabs->Index=i; postRedisplayMainWindow(); updateTabs(1,Tabs); return 0; } } return mouseDownWidget(X,Y,Tabs->Tabs[Tabs->Index].Child); } int mouseDownWidget(int X,int Y,widget *Widget){ if (!inrect(X,Y,Widget->Rect)) return 0; switch (Widget->Class){ case WIDGET_SPLIT: return mouseDownWidget(X,Y,Widget->Data.Split->Widget1) || mouseDownWidget(X,Y,Widget->Data.Split->Widget2); case WIDGET_CONTROL: if (mouseDownControl(X,Y,Widget->Data.Control)){ MainWindow.Capture=Widget; postRedisplayMainWindow(); return 1; } break; case WIDGET_TABS: return mouseDownTabs(X,Y,Widget->Data.Tabs); } return 0; } /********************************************************************* * WIDGET MOUSEMOVE *********************************************************************/ void mouseMoveItem(int X,int Y,item *Item){ int dx=X-MainWindow.CaptureStart.X,dy=MainWindow.CaptureStart.Y-Y; switch (Item->Class){ case ITEM_INT: *Item->Data.Int->Value=Item->Data.Int->LastValue+dy/3; if (*Item->Data.Int->Value>Item->Data.Int->Max) *Item->Data.Int->Value=Item->Data.Int->Max; if (*Item->Data.Int->Value<Item->Data.Int->Min) *Item->Data.Int->Value=Item->Data.Int->Min; updateItem(Item); reshapeMainWindow(); postRedisplay(); break; case ITEM_FLOAT: *Item->Data.Float->Value=Item->Data.Float->LastValue+(Item->Data.Float->Max-Item->Data.Float->Min)*0.003*dy; if (*Item->Data.Float->Value>Item->Data.Float->Max) *Item->Data.Float->Value=Item->Data.Float->Max; if (*Item->Data.Float->Value<Item->Data.Float->Min) *Item->Data.Float->Value=Item->Data.Float->Min; updateItem(Item); reshapeMainWindow(); postRedisplay(); break; case ITEM_ENUM: break; } } void mouseMoveWidget(int X,int Y,widget *Widget){ switch (Widget->Class){ case WIDGET_CONTROL: if (Widget->Data.Control->Capture) mouseMoveItem(X,Y,Widget->Data.Control->Capture); } } /********************************************************************* * WIDGET MOUSEUP *********************************************************************/ void mouseUpItem(int X,int Y,item* Item){ switch (Item->Class){ case ITEM_ENUM: if (inrect(X,Y,Item->Rect)){ Item->Data.Enum->Index=(Item->Data.Enum->Index+1) % Item->Data.Enum->Count; *Item->Data.Enum->Value=Item->Data.Enum->Values[Item->Data.Enum->Index]; reshapeMainWindow(); postRedisplay(); } postRedisplayMainWindow(); } } void mouseUpWidget(int X,int Y,widget *Widget){ mouseMoveWidget(X,Y,Widget); switch (Widget->Class){ case WIDGET_CONTROL: if (Widget->Data.Control->Capture) mouseUpItem(X,Y,Widget->Data.Control->Capture); Widget->Data.Control->Capture=NULL; } } /********************************************************************* * WIDGET CALLBACKS *********************************************************************/ void sceneDisplayFunc(void){ widget *Widget; if (Widget=currentSceneWidget()) Widget->Data.Scene->onDisplay(Widget->Data.Scene->LastX-Widget->Data.Scene->X,Widget->Data.Scene->Y-Widget->Data.Scene->LastY); } void sceneMouseFunc(int Button,int State,int X,int Y){ widget *Widget; switch (State){ case GLUT_DOWN: if (Widget=currentSceneWidget()){ MainWindow.Capture=Widget; Widget->Data.Scene->X=X; Widget->Data.Scene->Y=Y; } break; case GLUT_UP: MainWindow.Capture=NULL; break; } } void sceneMotionFunc(int X,int Y){ widget *Widget; if (MainWindow.Capture==(Widget=currentSceneWidget())){ Widget->Data.Scene->LastX=X; Widget->Data.Scene->LastY=Y; postRedisplayScenes(); } } void mainDisplayFunc(void){ glClearColor(0.95,0.97,0.99,0); glClear(GL_COLOR_BUFFER_BIT); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluOrtho2D(0,MainWindow.Root->Rect.Width,MainWindow.Root->Rect.Height,0); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); displayWidget(MainWindow.Root); glFlush(); glutSwapBuffers(); } void mainReshapeFunc(int Width,int Height){ rect r={0,0}; r.Width=Width; r.Height=Height; glViewport(0,0,Width,Height); MainWindow.Root->Rect=r; reshapeMainWindow(); } void mainMouseFunc(int Button,int State,int X,int Y){ switch (State){ case GLUT_DOWN: if (!mouseDownWidget(X,Y,MainWindow.Root)) MainWindow.Capture=NULL; else { MainWindow.CaptureStart.X=X; MainWindow.CaptureStart.Y=Y; } break; case GLUT_UP: if (MainWindow.Capture) mouseUpWidget(X,Y,MainWindow.Capture); MainWindow.Capture=NULL; } } void mainMotionFunc(int X,int Y){ if (MainWindow.Capture) mouseMoveWidget(X,Y,MainWindow.Capture); } /********************************************************************* * WIDGET CREATION *********************************************************************/ void createSubWindow(widget *Widget){ int i; switch (Widget->Class){ case WIDGET_SPLIT: createSubWindow(Widget->Data.Split->Widget1); createSubWindow(Widget->Data.Split->Widget2); break; case WIDGET_SCENE: Widget->Data.Scene->Index=glutCreateSubWindow(MainWindow.Index,0,0,10,10); glutDisplayFunc(sceneDisplayFunc); glutMouseFunc(sceneMouseFunc); glutMotionFunc(sceneMotionFunc); if (Widget->Data.Scene->onReshape) glutReshapeFunc(Widget->Data.Scene->onReshape); break; case WIDGET_CONTROL: Widget->Data.Control->Capture=NULL; updateControl(1,Widget->Data.Control); break; case WIDGET_TABS: for (i=0;i<Widget->Data.Tabs->Count;i++) createSubWindow(Widget->Data.Tabs->Tabs[i].Child); updateTabs(1,Widget->Data.Tabs); break; } } void createWindow(widget *Root,char *Name){ MainWindow.Root=Root; MainWindow.Index=glutCreateWindow(Name); glutDisplayFunc(mainDisplayFunc); glutReshapeFunc(mainReshapeFunc); glutMouseFunc(mainMouseFunc); glutMotionFunc(mainMotionFunc); createSubWindow(Root); }
Dernière modification le 18/3/2010
Ce document a été traduit de LaTeX par HeVeA