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:
Pour information: Fichier : demoGLUT/convert.c #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 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);
} Ce document a été traduit de LaTeX par HeVeA |