Mercurial > repos > rhope
view visuality.c @ 121:1af91ceaaf49
Fixed memory leak when an output is only attached to a single null input
author | Mike Pavone <pavone@retrodev.com> |
---|---|
date | Thu, 28 Oct 2010 21:04:12 -0400 |
parents | 76568becd6d6 |
children |
line wrap: on
line source
#include <stdio.h> #include <math.h> #include "structs.h" #include "visuality.h" #include "interp.h" #include "parser.h" #include "saveload.h" #define NUM_SPRITES 5 FILE * outfile; HGLRC hRC = NULL; HDC hDC = NULL; HWND hWnd = NULL; HINSTANCE hInstance; GLuint glyph_base; BOOL mouse_left_down=FALSE; BOOL mouse_leftstart_down=FALSE; int mouse_lastx; int mouse_lasty; int mouse_curx; int mouse_cury; int start_wire_worker=-1; int start_wire_ionum=-2; BOOL start_wire_isinput; BOOL checked_mouse_pos=FALSE; char new_name_buf[256]; int buf_size=0; extern char text_buf[256]; extern int text_buf_size=0; extern BOOL execute_active; worker * view_workerlist; wire * view_wirelist; int current_def=0; /* void save_program(char * filename) { worker * aworkerlist; wire * awirelist; FILE * savefile; int def_num, version = 1; savefile = fopen(filename, "wb"); if(!savefile) return; deflist[current_def].num_workers = num_workers; deflist[current_def].num_wires = num_wires; fwrite(&version, 4, 1, savefile); fwrite(&num_defs, 4, 1, savefile); fwrite(deflist, sizeof(worker_def), num_defs, savefile); for(def_num = 0; def_num < num_defs; ++def_num) { if(deflist[def_num].workerlist) { fwrite(&def_num, 4, 1, savefile); //fwrite(&(deflist[def_num].num_workers), 4, 1, savefile); fwrite(deflist[def_num].workerlist, sizeof(worker), deflist[def_num].num_workers, savefile); //fwrite(&(deflist[def_num].num_wires), 4, 1, savefile); fwrite(deflist[def_num].wirelist, sizeof(wire), deflist[def_num].num_wires, savefile); } } def_num = -1; fwrite(&def_num, 4, 1, savefile); fclose(savefile); } void load_program(char * filename) { char msg[256]; worker * aworkerlist; wire * awirelist; FILE * loadfile; int def_num, version; loadfile = fopen(filename, "rb"); if(!loadfile) { MessageBox(NULL, "Could not open file","Error",MB_OK); return; } fread(&version, 4, 1, loadfile); if(version != 1) { MessageBox(NULL, "Can't read files of this version.","Error",MB_OK); return; } fread(&num_defs, 4, 1, loadfile); fread(deflist, sizeof(worker_def), num_defs, loadfile); fread(&def_num, 4, 1, loadfile); while(def_num >= 0 && !feof(loadfile)) { sprintf(msg, "Reading def %X at %X", def_num, ftell(loadfile)); MessageBox(NULL, msg, "debug",MB_OK); deflist[def_num].workerlist = malloc((deflist[def_num].num_workers+512)*sizeof(worker)); fread(deflist[def_num].workerlist, sizeof(worker), deflist[def_num].num_workers, loadfile); deflist[def_num].wirelist = malloc((deflist[def_num].num_wires+1024)*sizeof(wire)); fread(deflist[def_num].wirelist, sizeof(wire), deflist[def_num].num_wires, loadfile); deflist[def_num].workers_to_wires_up = malloc((deflist[def_num].num_wires+1024)*sizeof(int)); deflist[def_num].workers_to_wires_down = malloc((deflist[def_num].num_wires+1024)*sizeof(int)); fread(&def_num, 4, 1, loadfile); } fclose(loadfile); view_workerlist = deflist[0].workerlist; view_wirelist = deflist[0].wirelist; num_workers = deflist[0].num_workers; num_wires = deflist[0].num_wires; initpredefworkers(); //sprintf(msg,"%d workers, %d wires in %s",deflist[0].num_workers,deflist[0].num_wires,deflist[0].name); //MessageBox(NULL,msg,"visdbg",MB_OK); }*/ BOOL keys[256]; BOOL active = TRUE; BOOL fullscreen=TRUE; BOOL gameover = FALSE; GLfloat xrot; // X Rotation ( NEW ) GLfloat yrot; // Y Rotation ( NEW ) GLfloat zrot; // Z Rotation ( NEW ) GLuint texture[NUM_SPRITES]; // Storage For One Texture ( NEW ) float xsizes[NUM_SPRITES] = {0.75f, 1.0f, 0.25f, 0.25f, 2.0f}; float ysizes[NUM_SPRITES] = {1.0f, 0.5f, 0.25f, 0.25f, 2.0f}; float xtexturefit[NUM_SPRITES] = {0.75f, 1.0f, 1.0f, 1.0f, 1.0f}; float ytexturefit[NUM_SPRITES] = {1.0f, 1.0f, 1.0f, 1.0f, 1.0f}; float gunxpos = 5.0f; char spritenames[NUM_SPRITES][32] = {"rini.bmp", "zapper.bmp", "heart.bmp", "fireball.bmp", "kiss.bmp"}; #define SCREEN_WIDTH_REL 8.8f #define SCREEN_HEIGHT_REL 6.6f #define PI 3.14159265 int selected_worker = -1; int selected_wire = -1; int killed = 0; LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); AUX_RGBImageRec *LoadBMP(char *Filename) // Loads A Bitmap Image { FILE *File=NULL; // File Handle if (!Filename) // Make Sure A Filename Was Given { return NULL; // If Not Return NULL } File=fopen(Filename,"r"); // Check To See If The File Exists if (File) // Does The File Exist? { fclose(File); // Close The Handle return auxDIBImageLoad(Filename); // Load The Bitmap And Return A Pointer } return NULL; // If Load Failed Return NULL } /* int LoadGLTextures() // Load Bitmaps And Convert To Textures { int Status=FALSE; // Status Indicator AUX_RGBImageRec *TextureImage[NUM_SPRITES]; // Create Storage Space For The Texture int i; for(i = 0; i < NUM_SPRITES; ++i) { TextureImage[i] = NULL; // Set The Pointer To NULL // Load The Bitmap, Check For Errors, If Bitmap's Not Found Quit if (TextureImage[i]=LoadBMP(spritenames[i])) { Status=TRUE; // Set The Status To TRUE glGenTextures(1, &texture[i]); // Create The Texture // Typical Texture Generation Using Data From The Bitmap glBindTexture(GL_TEXTURE_2D, texture[i]); // Generate The Texture glTexImage2D(GL_TEXTURE_2D, 0, 3, TextureImage[i]->sizeX, TextureImage[i]->sizeY, 0, GL_RGB, GL_UNSIGNED_BYTE, TextureImage[i]->data); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR); // Linear Filtering glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); // Linear Filtering } if (TextureImage[i]) // If Texture Exists { if (TextureImage[i]->data) // If Texture Image Exists { free(TextureImage[i]->data); // Free The Texture Image Memory } free(TextureImage[i]); // Free The Image Structure } //xsizes[i] = 0.5f; //ysizes[i] = 1.0f; } return Status; // Return The Status } */ GLvoid ReSizeGLScene(GLsizei width, GLsizei height) { if(height ==0) height = 1; glViewport(0,0,width,height); glMatrixMode(GL_PROJECTION); //Reset projection matrix glLoadIdentity(); //Calculate aspect ratio gluPerspective(45.0f, (GLfloat)width/ (GLfloat)height, 0.1f, 100.0f); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); //reset modelview matrix } int InitGL(GLvoid) { //if (!LoadGLTextures()) // Jump To Texture Loading Routine ( NEW ) //{ // return FALSE; // If Texture Didn't Load Return FALSE ( NEW ) //} HFONT font; glEnable(GL_TEXTURE_2D); glShadeModel(GL_SMOOTH); glClearColor(0.0f, 0.0f, 0.0f, 0.0f); //blackness glClearDepth(1.0f); glEnable(GL_DEPTH_TEST); glDepthFunc(GL_LEQUAL); glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); glEnable(GL_COLOR_MATERIAL); font = CreateFont(-24, 0, 0, 0, FW_BOLD, 0, 0, 0, ANSI_CHARSET, OUT_OUTLINE_PRECIS, CLIP_DEFAULT_PRECIS, ANTIALIASED_QUALITY, FF_SWISS || VARIABLE_PITCH, "Arial"); SelectObject(hDC, font); glyph_base = glGenLists(224); wglUseFontOutlines(hDC, 32, 224, glyph_base, 0.0, 0.0, WGL_FONT_POLYGONS, NULL); DeleteObject(font); return TRUE; } void drawtriangle(double xpos, double ypos, double width, double height, double angle) { if(xpos != 0.0 || ypos != 0.0) glTranslatef(xpos, ypos, 0.0); if(angle != 0.0) glRotatef(angle, 0.0,0.0,1.0); glBegin(GL_TRIANGLES); glVertex2f(0.0, height/2); //Top glVertex2f(0.0 - width/2, 0.0 - height/2); //Left glVertex2f(width/2, 0.0 - height/2); //Right glEnd(); if(angle != 0.0) glRotatef(0.0-angle, 0.0,0.0,1.0);//restore rotation without loading identity if(xpos != 0.0 || ypos != 0.0) glTranslatef(0.0-xpos, 0.0-ypos, 0.0); } void drawrect(double xpos, double ypos, double width, double height, double angle) { if(xpos != 0.0 || ypos != 0.0) glTranslatef(xpos, ypos, 0.0); if(angle != 0.0) glRotatef(angle, 0.0,0.0,1.0); glBegin(GL_QUADS); glVertex2f(0.0 - width/2, height/2.0); //Top Left glVertex2f(width/2, height/2.0); //Top Right glVertex2f(width/2, 0.0 - height/2.0); //Bottom Right glVertex2f(0.0 - width/2, 0.0 - height/2.0); //Bottom Left glEnd(); if(angle != 0.0) glRotatef(0.0-angle, 0.0,0.0,1.0);//restore rotation without loading identity if(xpos != 0.0 || ypos != 0.0) glTranslatef(0.0-xpos, 0.0-ypos, 0.0); } void drawshapestrip(int shape_type, double length, double ypos, double width, double height, int num) { double currentpos, spacing; int i; spacing = length/(double)num; currentpos = 0.0 - length/2.0 + spacing/2.0; for(i = 0; i < num; ++i) { if(shape_type == 0) drawtriangle(currentpos, ypos, width, height, 0.0); else drawrect(currentpos, ypos, width, height, 0.0); currentpos += spacing; } } double get_io_xpos(worker * some_worker, int output_num, BOOL is_input) { double length, currentpos, spacing; if(is_input && output_num == -1) return some_worker->xpos + some_worker->width/2.0 + INPUT_SIZE/2.0; if(some_worker->type == 2 && is_input) //Trapezoid length = 2.0*(some_worker->width)/3.0; else length = some_worker->width; fprintf(outfile, "Worker length: %f, worker width: %f\n"); if(is_input) spacing = length/(some_worker->num_inputs); else spacing = length/(some_worker->num_outputs); currentpos = some_worker->xpos - length/2.0 + spacing/2.0; return currentpos + spacing * (double)output_num; } double get_io_ypos(worker * some_worker, int output_num, BOOL is_input) { if(is_input && output_num != -1) return some_worker->ypos + (some_worker->height)/2.0; else return some_worker->ypos - ((some_worker->height)/2.0); } void drawshape(int shape_type, double xpos, double ypos, double width, double height, double angle, int inputs, int outputs, char *text, BOOL selected) { double x, y,temp, currentpos, spacing; double *inputx, *inputy, *outputx, *outputy; double ioangle, hypot; int i; glLoadIdentity(); glTranslatef(SCREEN_WIDTH_REL / (-2.0f) + xpos, SCREEN_HEIGHT_REL / (-2.0f) + ypos,-8.0f); xpos = 0.0; ypos = 0.0; glRotatef(angle, 0.0,0.0,1.0); if(selected) glColor3f(SELECT_RED, SELECT_GREEN, SELECT_BLUE); else glColor3f(BODY_RED, BODY_GREEN, BODY_BLUE); switch(shape_type) { case 0: //Triangle drawtriangle(0.0, 0.0, width, height, 0.0); glTranslatef(0.0-width/4.0, 0.0-height/4.0,0); break; case 1: //Rectangle drawrect(0.0, 0.0, width, height, angle); glColor3f(INPUT_RED, INPUT_GREEN, INPUT_BLUE); if(inputs) drawshapestrip(0, width, height/2.0 + INPUT_SIZE/2.0,INPUT_SIZE, INPUT_SIZE, inputs); drawtriangle(xpos + width/2.0 + INPUT_SIZE/2.0, ypos-height/2.0+INPUT_SIZE/2.0, INPUT_SIZE, INPUT_SIZE, 0.0); glColor3f(OUTPUT_RED, OUTPUT_GREEN, OUTPUT_BLUE); if(outputs) drawshapestrip(1, width, 0.0-(height/2.0 + OUTPUT_SIZE/2.0),OUTPUT_SIZE, OUTPUT_SIZE, outputs); glTranslatef(0.0-width/2.0 + width/16.0, 0.0-height/3.0, 0.0); break; case 2: //Trapezoid glBegin(GL_QUADS); glVertex2f(xpos - width/3.0 , ypos + height/2.0); //Top Left glVertex2f(xpos + width/3.0, ypos + height/2.0); //Top Right glVertex2f(xpos + width/2.0, ypos - height/2.0); //Bottom Right glVertex2f(xpos - width/2.0, ypos - height/2.0); //Bottom Left glEnd(); glColor3f(INPUT_RED, INPUT_GREEN, INPUT_BLUE); if(inputs) drawshapestrip(0, 2.0*(width/3.0), height/2.0 + INPUT_SIZE/2.0,INPUT_SIZE, INPUT_SIZE, inputs); drawtriangle(xpos + width/2.0 + INPUT_SIZE/2.0, ypos-height/2.0+INPUT_SIZE/2.0, INPUT_SIZE, INPUT_SIZE, 0.0); glColor3f(OUTPUT_RED, OUTPUT_GREEN, OUTPUT_BLUE); if(outputs) drawshapestrip(1, width, 0.0-(height/2.0 + OUTPUT_SIZE/2.0),OUTPUT_SIZE, OUTPUT_SIZE, outputs); glTranslatef(0.0-width/3.0, 0.0-height/3.0, 0.0); break; case 3: //Ellipse x = 3.4587; y = 2293.784; glBegin(GL_TRIANGLE_FAN); glVertex2f(0.0, 0.0); if(inputs) { spacing = width/(double)inputs; currentpos = 0.0-width/2.0 + spacing/2.0; inputx = (double *)malloc(inputs*sizeof(double)); inputy = (double *)malloc(inputs*sizeof(double)); i = 0; } for(x = 0.0-width/2 ; x <= width/2.0+CIRCLE_STEP; x += CIRCLE_STEP) { y = sqrt(fabs(pow(height/2.0,2) - (pow(height/2.0,2)*pow(x, 2))/pow(width/2.0, 2))); glVertex2f(x, y); if(inputs && x >= currentpos) { inputx[i] = x; inputy[i] = y; ++i; currentpos += spacing; } } x -= CIRCLE_STEP; while(x >= 0.0-width/2) { y = 0.0-sqrt(fabs(pow(height/2.0,2) - (pow(height/2.0,2)*pow(x, 2))/pow(width/2.0, 2))); glVertex2f(x+xpos, y+ypos); x -= CIRCLE_STEP; } glEnd(); glColor3f(INPUT_RED, INPUT_GREEN, INPUT_BLUE); for(i = 0; i < inputs; ++i) { ioangle = atan2(inputy[i], inputx[i]); hypot = sqrt(pow(inputx[i],2) + pow(inputy[i], 2)) + INPUT_SIZE/2; x = hypot * cos(ioangle); y = hypot * sin(ioangle); ioangle *= (180/PI); fprintf(outfile, "oldx: %f, oldy: %f, newx: %f, newy %f, hypot %f, angle %f\n",inputx[i],inputy[i],x,y,hypot, ioangle); drawtriangle(x,y,INPUT_SIZE,INPUT_SIZE, 90-ioangle); } glTranslatef(0.0-width/8.0, 0.0, 0.0); break; default: break; } if(text) { glColor3f(TEXT_RED, TEXT_GREEN, TEXT_BLUE); glPushAttrib(GL_LIST_BIT); glListBase(glyph_base-32); glScalef(0.25,0.25,0.25); glCallLists(strlen(text),GL_UNSIGNED_BYTE, text); glPopAttrib(); } } #define INTX_TO_FLOAT_REL(val) (((double)val)*SCREEN_WIDTH_REL/640.0) #define INTY_TO_FLOAT_REL(val) (((double)val)*SCREEN_HEIGHT_REL/480.0) //void drawshape(int shape_type, double xpos, double ypos, double width, double height, double angle, int inputs, int outputs) int DrawGLScene(GLvoid) { double line_startx; double line_starty; double line_endx; double line_endy; double m,b,x,y,mousey; int i,j; glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); for(i = 0; i < num_workers; ++i) { if(mouse_leftstart_down && INTX_TO_FLOAT_REL(mouse_curx) > (view_workerlist[i].xpos - view_workerlist[i].width/2.0) && INTX_TO_FLOAT_REL(mouse_curx) < (view_workerlist[i].xpos + view_workerlist[i].width/2.0) && INTY_TO_FLOAT_REL(mouse_cury) > (view_workerlist[i].ypos - view_workerlist[i].height/2.0) && INTY_TO_FLOAT_REL(mouse_cury) < (view_workerlist[i].ypos + view_workerlist[i].height/2.0)) { view_workerlist[i].grabbed = TRUE; selected_worker = i; selected_wire = -1; mouse_leftstart_down = FALSE; } else if(mouse_leftstart_down && INTX_TO_FLOAT_REL(mouse_curx) > (view_workerlist[i].xpos - view_workerlist[i].width/2.0) //Check for mouse in input or output area && INTX_TO_FLOAT_REL(mouse_curx) < (view_workerlist[i].xpos + view_workerlist[i].width/2.0) && (INTY_TO_FLOAT_REL(mouse_cury) > (view_workerlist[i].ypos - view_workerlist[i].height/2.0 - OUTPUT_SIZE)) && (INTY_TO_FLOAT_REL(mouse_cury) < (view_workerlist[i].ypos + view_workerlist[i].height/2.0 + INPUT_SIZE))) { if(INTY_TO_FLOAT_REL(mouse_cury) > view_workerlist[i].ypos && view_workerlist[i].num_inputs > 0)//is mouse above or below worker (inputs are above, outputs below)? { fputs("Hit on input region.\n", outfile); for(j = 0; j < view_workerlist[i].num_inputs; ++j) { if(INTX_TO_FLOAT_REL(mouse_curx) > (get_io_xpos(&view_workerlist[i], j, TRUE)-INPUT_SIZE/2.0) && INTX_TO_FLOAT_REL(mouse_curx) < (get_io_xpos(&view_workerlist[i], j, TRUE)+INPUT_SIZE/2.0)) { fprintf(outfile, "Hit on input number %d on worker %d.\n", j, i); mouse_leftstart_down = FALSE; if(start_wire_worker >= 0) { fprintf(outfile, "Adding wire %d. output_num: %d, input_num: %d", num_wires,start_wire_ionum, j); //Add wire view_wirelist[num_wires].start_worker = start_wire_worker; view_wirelist[num_wires].end_worker = i; view_wirelist[num_wires].output_num = start_wire_ionum;; view_wirelist[num_wires].input_num = j; ++num_wires; start_wire_worker = start_wire_ionum = -1; } else { fputs("Saving information for later wire creation.\n", outfile); start_wire_worker = i; start_wire_ionum = j; start_wire_isinput=TRUE; } break; } } } else if(view_workerlist[i].num_outputs > 0) { fputs("Hit on output region.\n", outfile); for(j = 0; j < view_workerlist[i].num_outputs; ++j) { fprintf(outfile, "Checking mouse x(%f) for hit on output number %d with position %f\n", INTX_TO_FLOAT_REL(mouse_curx), j, get_io_xpos(&view_workerlist[i], j, FALSE)); if(INTX_TO_FLOAT_REL(mouse_curx) > (get_io_xpos(&view_workerlist[i], j, FALSE)-OUTPUT_SIZE/2.0) && INTX_TO_FLOAT_REL(mouse_curx) < (get_io_xpos(&view_workerlist[i], j, FALSE)+OUTPUT_SIZE/2.0)) { fprintf(outfile, "Hit on output number %d on worker %d.\n", j, i); mouse_leftstart_down = FALSE; if(start_wire_worker >= 0) { fprintf(outfile, "Adding wire %d. output_num: %d, input_num: %d", num_wires, j, start_wire_ionum); //Add wire view_wirelist[num_wires].start_worker = i; view_wirelist[num_wires].end_worker = start_wire_worker; view_wirelist[num_wires].output_num = j; view_wirelist[num_wires].input_num = start_wire_ionum; if(start_wire_ionum == -1) view_workerlist[start_wire_worker].null_input = TRUE; ++num_wires; start_wire_worker = start_wire_ionum = -1; } else { fputs("Saving information for later wire creation.\n", outfile); start_wire_worker = i; start_wire_ionum = j; start_wire_isinput=FALSE; } break; } } } } else if(mouse_leftstart_down && INTX_TO_FLOAT_REL(mouse_curx) > (view_workerlist[i].xpos + view_workerlist[i].width/2.0) //Check for mouse in input or output area && INTX_TO_FLOAT_REL(mouse_curx) < (view_workerlist[i].xpos + view_workerlist[i].width/2.0+INPUT_SIZE) && (INTY_TO_FLOAT_REL(mouse_cury) > (view_workerlist[i].ypos - view_workerlist[i].height/2.0)) && (INTY_TO_FLOAT_REL(mouse_cury) < (view_workerlist[i].ypos - view_workerlist[i].height/2.0 + INPUT_SIZE))) { fprintf(outfile, "Click on NULL input at %f,%f\n", INTX_TO_FLOAT_REL(mouse_curx), INTY_TO_FLOAT_REL(mouse_cury)); mouse_leftstart_down = FALSE; if(start_wire_worker >= 0) { fprintf(outfile, "Adding wire %d. output_num: %d, input_num: %d", num_wires,start_wire_ionum, -1); //Add wire view_wirelist[num_wires].start_worker = start_wire_worker; view_wirelist[num_wires].end_worker = i; view_wirelist[num_wires].output_num = start_wire_ionum;; view_wirelist[num_wires].input_num = -1; view_workerlist[i].null_input = TRUE; ++num_wires; start_wire_worker = start_wire_ionum = -1; } else { fputs("Saving information for later wire creation.\n", outfile); start_wire_worker = i; start_wire_ionum = -1; start_wire_isinput=TRUE; } } else if(mouse_leftstart_down) { fprintf(outfile, "Click at %f,%f, worker at %f,%f with size %f,%f\n", INTX_TO_FLOAT_REL(mouse_curx), INTY_TO_FLOAT_REL(mouse_cury), view_workerlist[i].xpos, view_workerlist[i].ypos, view_workerlist[i].width, view_workerlist[i].height); } if(!mouse_left_down) view_workerlist[i].grabbed= FALSE; if(mouse_left_down && view_workerlist[i].grabbed && (mouse_curx != mouse_lastx || mouse_cury != mouse_lasty)) { view_workerlist[i].xpos += INTX_TO_FLOAT_REL(mouse_curx-mouse_lastx); view_workerlist[i].ypos += INTY_TO_FLOAT_REL(mouse_cury-mouse_lasty); } drawshape(view_workerlist[i].display_type, view_workerlist[i].xpos, view_workerlist[i].ypos, view_workerlist[i].width, view_workerlist[i].height, view_workerlist[i].angle, view_workerlist[i].num_inputs, view_workerlist[i].num_outputs, view_workerlist[i].name, selected_worker==i); } glLoadIdentity(); glTranslatef(SCREEN_WIDTH_REL / (-2.0f), SCREEN_HEIGHT_REL / (-2.0f),-8.0f); glColor3f(WIRE_RED, WIRE_GREEN, WIRE_BLUE); for(i = 0; i < num_wires; ++i) { fprintf(outfile, "Wire %d starts in worker %d at output %d of %d and ends in worker %d at input %d of %d\n", i, view_wirelist[i].start_worker, view_wirelist[i].output_num, view_workerlist[view_wirelist[i].start_worker].num_outputs, view_wirelist[i].end_worker, view_wirelist[i].input_num, view_workerlist[view_wirelist[i].end_worker].num_inputs); line_startx = get_io_xpos(&view_workerlist[view_wirelist[i].start_worker], view_wirelist[i].output_num, FALSE); line_starty = get_io_ypos(&view_workerlist[view_wirelist[i].start_worker], view_wirelist[i].output_num, FALSE)-OUTPUT_SIZE; line_endx = get_io_xpos(&view_workerlist[view_wirelist[i].end_worker], view_wirelist[i].input_num, TRUE); line_endy = get_io_ypos(&view_workerlist[view_wirelist[i].end_worker], view_wirelist[i].input_num, TRUE)+OUTPUT_SIZE; x = INTX_TO_FLOAT_REL(mouse_curx); mousey = INTY_TO_FLOAT_REL(mouse_cury); if(mouse_leftstart_down) { //y = mx=b if(line_startx < line_endx) { if(x >= line_startx && x <= line_endx) { m = (line_endy-line_starty)/(line_endx-line_starty); b = line_starty; x -= line_startx; y = m*x + b; fprintf(outfile, "y: %f, m: %f, x: %f, b: %f, mousey: %f\n", y,m,x,b,mousey); if(mousey >= (y-0.05) && mousey <= (y+0.05)) { selected_wire = i; selected_worker = -1; } } } else if(line_endx > line_startx) { if(x <= line_startx && x >= line_endx) { m = (line_starty-line_endy)/(line_startx-line_endy); b = line_endy; y = m*x + b; x -= line_endx; if(mousey >= (y-0.05) && mousey <= (y+0.05)) { selected_wire = i; selected_worker = -1; } } } else //avoid divide by zero error { if(x >= (line_startx-0.05) && x <= (line_startx+0.05)) { if(line_starty > line_endy) { if(mousey >= line_endy && mousey <= line_starty) { selected_wire = i; selected_worker = -1; } } else { if(mousey <= line_endy && mousey >= line_starty) { selected_wire = i; selected_worker = -1; } } } } } if(i == selected_wire) glColor3f(SELECT_RED, SELECT_GREEN, SELECT_BLUE); fprintf(outfile, "Start (%f,%f), End (%f, %f), Mouse(%f, %f)\n", line_startx, line_starty, line_endx, line_endy, x, mousey); glBegin(GL_QUADS); glVertex2f(line_startx, line_starty); glVertex2f(line_startx+0.1, line_starty); glVertex2f(line_endx+0.1, line_endy); glVertex2f(line_endx, line_endy); glEnd(); if(i == selected_wire) glColor3f(WIRE_RED, WIRE_GREEN, WIRE_BLUE); } mouse_leftstart_down = FALSE; //view_workerlist[3].angle += 1.0; checked_mouse_pos=TRUE; if(buf_size) { glColor3f(1.0, 1.0, 1.0); glPushAttrib(GL_LIST_BIT); glListBase(glyph_base-32); glScalef(0.25,0.25,0.25); glCallLists(buf_size,GL_UNSIGNED_BYTE, new_name_buf); glPopAttrib(); } /* if(execute_active) { for(i = 0; i < num_workers; ++i) process_worker(i); if(!execute_active) { for(i = 0; i < num_datum; ++i) { if(data[i].type & 0x80) free(data[i].contents); } } } */ mouse_lastx = mouse_curx; mouse_lasty = mouse_cury; return TRUE; } GLvoid KillGLWindow(GLvoid) { if(fullscreen) { ChangeDisplaySettings(NULL, 0); ShowCursor(TRUE); } if(hRC) { glDeleteLists(glyph_base, 224); if(!wglMakeCurrent(NULL,NULL)) MessageBox(NULL, "Release of DC and RC failed.","SHUTDOWN ERROR", MB_OK | MB_ICONINFORMATION); if(!wglDeleteContext(hRC)) MessageBox(NULL, "Release Rendering Context Failed.", "SHUTDOWN ERROR", MB_OK | MB_ICONINFORMATION); hRC = NULL; if(hDC && !ReleaseDC(hWnd,hDC)) { MessageBox(NULL,"Release Device Context Failed.", "SHUTDOWN ERROR", MB_OK | MB_ICONINFORMATION); hDC = NULL; } } if(hWnd && !DestroyWindow(hWnd)) { MessageBox(NULL, "Could not Release hWnd", "SHUTDOWN ERROR", MB_OK | MB_ICONINFORMATION); hWnd = NULL; } if(!UnregisterClass("OpenGL", hInstance)) { MessageBox(NULL, "Could Not Unregister Class.", "SHUTDOWN ERROR", MB_OK | MB_ICONINFORMATION); hInstance=NULL; } } BOOL CreateGLWindow(char * title, int width, int height, int bits, BOOL fullscreenflag) { GLuint PixelFormat; WNDCLASS wc; DWORD dwExStyle; DWORD dwStyle; static PIXELFORMATDESCRIPTOR pfd= // pfd Tells Windows How We Want Things To Be { sizeof(PIXELFORMATDESCRIPTOR), // Size Of This Pixel Format Descriptor 1, // Version Number PFD_DRAW_TO_WINDOW | // Format Must Support Window PFD_SUPPORT_OPENGL | // Format Must Support OpenGL PFD_DOUBLEBUFFER, // Must Support Double Buffering PFD_TYPE_RGBA, // Request An RGBA Format 0, // Select Our Color Depth 0, 0, 0, 0, 0, 0, // Color Bits Ignored 0, // No Alpha Buffer 0, // Shift Bit Ignored 0, // No Accumulation Buffer 0, 0, 0, 0, // Accumulation Bits Ignored 16, // 16Bit Z-Buffer (Depth Buffer) 0, // No Stencil Buffer 0, // No Auxiliary Buffer PFD_MAIN_PLANE, // Main Drawing Layer 0, // Reserved 0, 0, 0 // Layer Masks Ignored }; RECT WindowRect; WindowRect.left = (long)0; WindowRect.right = (long)width; WindowRect.top = (long)0; WindowRect.bottom=(long)height; fullscreen = fullscreenflag; hInstance = GetModuleHandle(NULL); // Grab An Instance For Our Window wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC; // Redraw On Move, And Own DC For Window wc.lpfnWndProc = (WNDPROC) WndProc; // WndProc Handles Messages wc.cbClsExtra = 0; // No Extra Window Data wc.cbWndExtra = 0; // No Extra Window Data wc.hInstance = hInstance; // Set The Instance wc.hIcon = LoadIcon(NULL, IDI_WINLOGO); // Load The Default Icon wc.hCursor = LoadCursor(NULL, IDC_ARROW); // Load The Arrow Pointer wc.hbrBackground = NULL; // No Background Required For GL wc.lpszMenuName = NULL; // We Don't Want A Menu wc.lpszClassName = "OpenGL"; // Set The Class Name if (!RegisterClass(&wc)) // Attempt To Register The Window Class { MessageBox(NULL,"Failed To Register The Window Class.","ERROR",MB_OK|MB_ICONEXCLAMATION); return FALSE; // Exit And Return FALSE } if (fullscreen) // Attempt Fullscreen Mode? { DEVMODE dmScreenSettings; // Device Mode memset(&dmScreenSettings,0,sizeof(dmScreenSettings)); // Makes Sure Memory's Cleared dmScreenSettings.dmSize=sizeof(dmScreenSettings); // Size Of The Devmode Structure dmScreenSettings.dmPelsWidth = width; // Selected Screen Width dmScreenSettings.dmPelsHeight = height; // Selected Screen Height dmScreenSettings.dmBitsPerPel = bits; // Selected Bits Per Pixel dmScreenSettings.dmFields=DM_BITSPERPEL|DM_PELSWIDTH|DM_PELSHEIGHT; // Try To Set Selected Mode And Get Results. NOTE: CDS_FULLSCREEN Gets Rid Of Start Bar. if (ChangeDisplaySettings(&dmScreenSettings,CDS_FULLSCREEN)!=DISP_CHANGE_SUCCESSFUL) { // If The Mode Fails, Offer Two Options. Quit Or Run In A Window. if (MessageBox(NULL,"The Requested Fullscreen Mode Is Not Supported By\nYour Video Card. Use Windowed Mode Instead?","NeHe GL",MB_YESNO|MB_ICONEXCLAMATION)==IDYES) { fullscreen=FALSE; // Select Windowed Mode (Fullscreen=FALSE) } else { // Pop Up A Message Box Letting User Know The Program Is Closing. MessageBox(NULL,"Program Will Now Close.","ERROR",MB_OK|MB_ICONSTOP); return FALSE; // Exit And Return FALSE } } } if (fullscreen) // Are We Still In Fullscreen Mode? { dwExStyle=WS_EX_APPWINDOW; // Window Extended Style dwStyle=WS_POPUP; // Windows Style ShowCursor(FALSE); // Hide Mouse Pointer } else { dwExStyle=WS_EX_APPWINDOW | WS_EX_WINDOWEDGE; // Window Extended Style dwStyle=WS_OVERLAPPEDWINDOW; // Windows Style } AdjustWindowRectEx(&WindowRect, dwStyle, FALSE, dwExStyle); // Adjust Window To True Requested Size if (!(hWnd=CreateWindowEx( dwExStyle, // Extended Style For The Window "OpenGL", // Class Name title, // Window Title WS_CLIPSIBLINGS | // Required Window Style WS_CLIPCHILDREN | // Required Window Style dwStyle, // Selected Window Style 0, 0, // Window Position WindowRect.right-WindowRect.left, // Calculate Adjusted Window Width WindowRect.bottom-WindowRect.top, // Calculate Adjusted Window Height NULL, // No Parent Window NULL, // No Menu hInstance, // Instance NULL))) // Don't Pass Anything To WM_CREATE { KillGLWindow(); // Reset The Display MessageBox(NULL,"Window Creation Error.","ERROR",MB_OK|MB_ICONEXCLAMATION); return FALSE; // Return FALSE } pfd.cColorBits = bits; if (!(hDC=GetDC(hWnd))) // Did We Get A Device Context? { KillGLWindow(); // Reset The Display MessageBox(NULL,"Can't Create A GL Device Context.","ERROR",MB_OK|MB_ICONEXCLAMATION); return FALSE; // Return FALSE } if (!(PixelFormat=ChoosePixelFormat(hDC,&pfd))) // Did Windows Find A Matching Pixel Format? { KillGLWindow(); // Reset The Display MessageBox(NULL,"Can't Find A Suitable PixelFormat.","ERROR",MB_OK|MB_ICONEXCLAMATION); return FALSE; // Return FALSE } if(!SetPixelFormat(hDC,PixelFormat,&pfd)) // Are We Able To Set The Pixel Format? { KillGLWindow(); // Reset The Display MessageBox(NULL,"Can't Set The PixelFormat.","ERROR",MB_OK|MB_ICONEXCLAMATION); return FALSE; // Return FALSE } if (!(hRC=wglCreateContext(hDC))) // Are We Able To Get A Rendering Context? { KillGLWindow(); // Reset The Display MessageBox(NULL,"Can't Create A GL Rendering Context.","ERROR",MB_OK|MB_ICONEXCLAMATION); return FALSE; // Return FALSE } if(!wglMakeCurrent(hDC,hRC)) // Try To Activate The Rendering Context { KillGLWindow(); // Reset The Display MessageBox(NULL,"Can't Activate The GL Rendering Context.","ERROR",MB_OK|MB_ICONEXCLAMATION); return FALSE; // Return FALSE } ShowWindow(hWnd,SW_SHOW); // Show The Window SetForegroundWindow(hWnd); // Slightly Higher Priority SetFocus(hWnd); // Sets Keyboard Focus To The Window ReSizeGLScene(width, height); // Set Up Our Perspective GL Screen if (!InitGL()) // Initialize Our Newly Created GL Window { KillGLWindow(); // Reset The Display MessageBox(NULL,"Initialization Failed.","ERROR",MB_OK|MB_ICONEXCLAMATION); return FALSE; // Return FALSE } return TRUE; // Success } LRESULT CALLBACK WndProc( HWND hWnd, // Handle For This Window UINT uMsg, // Message For This Window WPARAM wParam, // Additional Message Information LPARAM lParam) // Additional Message Information { int i; worker_def * def; FILE * loadfile; char * code; int size; switch (uMsg) // Check For Windows Messages { case WM_ACTIVATE: // Watch For Window Activate Message { if (!HIWORD(wParam)) // Check Minimization State { active=TRUE; // Program Is Active } else { active=FALSE; // Program Is No Longer Active } return 0; // Return To The Message Loop } case WM_SYSCOMMAND: // Intercept System Commands { switch (wParam) // Check System Calls { case SC_SCREENSAVE: // Screensaver Trying To Start? case SC_MONITORPOWER: // Monitor Trying To Enter Powersave? return 0; // Prevent From Happening } break; // Exit } case WM_CLOSE: // Did We Receive A Close Message? { PostQuitMessage(0); // Send A Quit Message return 0; // Jump Back } case WM_KEYDOWN: // Is A Key Being Held Down? { if(wParam == VK_BACK && buf_size > 0) --buf_size; else if(wParam == VK_F5 && !execute_active) { deflist[current_def].implement_func->num_workers = num_workers; deflist[current_def].implement_func->num_wires = num_wires; fprintf(outfile, "Starting execution.\n"); interp_start(-1,FALSE,0,NULL); } else if(wParam == VK_RETURN && buf_size > 0) { text_buf_size = buf_size; memcpy(text_buf, new_name_buf, buf_size); buf_size = 0; if(memcmp(text_buf, "Save:", strlen("Save:")) == 0) { text_buf[text_buf_size]='\0'; deflist[current_def].implement_func->num_workers = num_workers; deflist[current_def].implement_func->num_wires = num_wires; save_program(text_buf + strlen("Save:")); text_buf_size = 0; } else if(memcmp(text_buf, "Load:", strlen("Load:")) == 0) { text_buf[text_buf_size]='\0'; load_program(text_buf + strlen("Load:")); view_workerlist = deflist[0].implement_func->workerlist; view_wirelist = deflist[0].implement_func->wirelist; num_workers = deflist[0].implement_func->num_workers; num_wires = deflist[0].implement_func->num_wires; text_buf_size = 0; } else if (memcmp(text_buf, "View:", strlen("View:")) == 0) { text_buf[text_buf_size]='\0'; deflist[current_def].implement_func->num_workers = num_workers; deflist[current_def].implement_func->num_wires = num_wires; i = find_worker(text_buf+strlen("View:"), NULL, NULL); if(i < 0) current_def = create_worker(text_buf+strlen("View:"), 0, 0, USER_FLAG | WORKER_TYPE) - deflist; else current_def = i; num_workers = deflist[current_def].implement_func->num_workers; num_wires = deflist[current_def].implement_func->num_wires; view_workerlist = deflist[current_def].implement_func->workerlist; view_wirelist = deflist[current_def].implement_func->wirelist; text_buf_size = 0; selected_worker = -1; } else if(memcmp(text_buf, "Import:", strlen("Import:")) == 0) { deflist[current_def].implement_func->num_workers = num_workers; deflist[current_def].implement_func->num_wires = num_wires; text_buf[text_buf_size]='\0'; loadfile = fopen(text_buf+strlen("Import:"), "rb"); fseek(loadfile, 0, SEEK_END); size = ftell(loadfile); fseek(loadfile, 0, SEEK_SET); code = malloc(size+1); fread(code, 1, size, loadfile); parse(code, size); } } else if(wParam == VK_DELETE) { if(selected_worker != -1) { for(i = 0; i < num_wires; ++i) { if(view_wirelist[i].start_worker == selected_worker || view_wirelist[i].end_worker == selected_worker) { view_wirelist[i] = view_wirelist[num_wires-1]; --num_wires; --i; } } view_workerlist[selected_worker] = view_workerlist[num_workers-1]; for(i = 0; i < num_wires; ++i) { if(view_wirelist[i].start_worker == num_workers-1) view_wirelist[i].start_worker = selected_worker; if(view_wirelist[i].end_worker == num_workers-1) view_wirelist[i].end_worker = selected_worker; } --num_workers; selected_worker = -1; } } keys[wParam] = TRUE; // If So, Mark It As TRUE return 0; // Jump Back } case WM_KEYUP: // Has A Key Been Released? { keys[wParam] = FALSE; // If So, Mark It As FALSE return 0; // Jump Back } case WM_SIZE: // Resize The OpenGL Window { ReSizeGLScene(LOWORD(lParam),HIWORD(lParam)); // LoWord=Width, HiWord=Height return 0; // Jump Back } case WM_RBUTTONDOWN: { view_workerlist[num_workers].xpos = INTX_TO_FLOAT_REL(GET_X_LPARAM(lParam)); view_workerlist[num_workers].ypos = INTY_TO_FLOAT_REL(480-GET_Y_LPARAM(lParam)); view_workerlist[num_workers].height = 0.25; view_workerlist[num_workers].grabbed=FALSE; if(buf_size > strlen("Data:") && memcmp("Data:", new_name_buf, strlen("Data:")) == 0) { view_workerlist[num_workers].display_type=1;//Rectangle view_workerlist[num_workers].type=0;//Constant view_workerlist[num_workers].num_inputs=0;//Constants don't have inputs view_workerlist[num_workers].num_outputs=1;//Constants have one output view_workerlist[num_workers].null_input = FALSE; memcpy(view_workerlist[num_workers].name, new_name_buf+strlen("Data:"), buf_size-strlen("Data:")); view_workerlist[num_workers].name[buf_size-strlen("Data:")]='\0'; view_workerlist[num_workers].width = ((double)(buf_size-strlen("Data:"))+0.5) * INPUT_SIZE; ++num_workers; buf_size = 0; } else if(buf_size > strlen("Room:") && memcmp("Room:", new_name_buf, strlen("Room:")) == 0) { view_workerlist[num_workers].type=1;//Room view_workerlist[num_workers].display_type=1;//Rectangle view_workerlist[num_workers].num_inputs=1; view_workerlist[num_workers].num_outputs=1; view_workerlist[num_workers].null_input = FALSE; memcpy(view_workerlist[num_workers].name, new_name_buf+strlen("Room:"), buf_size-strlen("Room:")); view_workerlist[num_workers].name[buf_size-strlen("Room:")]='\0'; view_workerlist[num_workers].width = ((double)(buf_size-strlen("Room:"))+0.5) * INPUT_SIZE; ++num_workers; buf_size = 0; } else if(buf_size > strlen("Input:") && memcmp("Input:", new_name_buf, strlen("Input:")) == 0) { deflist[current_def].implement_func->num_workers = num_workers; new_name_buf[buf_size] = '\0'; MessageBox(NULL, new_name_buf,"Error",MB_OK); add_input(deflist+current_def, new_name_buf + strlen("Input:"), INTX_TO_FLOAT_REL(GET_X_LPARAM(lParam)), INTY_TO_FLOAT_REL(480-GET_Y_LPARAM(lParam))); num_workers = deflist[current_def].implement_func->num_workers; } else if(buf_size > strlen("Output:") && memcmp("Output:", new_name_buf, strlen("Output:")) == 0) { deflist[current_def].implement_func->num_workers = num_workers; new_name_buf[buf_size] = '\0'; add_output(deflist+current_def, new_name_buf + strlen("Output:"), INTX_TO_FLOAT_REL(GET_X_LPARAM(lParam)), INTY_TO_FLOAT_REL(480-GET_Y_LPARAM(lParam))); num_workers = deflist[current_def].implement_func->num_workers; } else if(buf_size > strlen("Express:") && memcmp("Express:", new_name_buf, strlen("Express:")) == 0) { deflist[current_def].implement_func->num_workers = num_workers; new_name_buf[buf_size] = '\0'; def = create_worker(new_name_buf+strlen("Express:"), 0, 0, USER_FLAG | WORKER_TYPE); parse_body(def, new_name_buf+strlen("Express:"), buf_size-strlen("Express:")); add_worker_to_def(deflist+current_def, def-deflist, INTX_TO_FLOAT_REL(GET_X_LPARAM(lParam)), INTY_TO_FLOAT_REL(480-GET_Y_LPARAM(lParam))); num_workers = deflist[current_def].implement_func->num_workers; buf_size = 0; } else { memcpy(view_workerlist[num_workers].name, new_name_buf, buf_size); view_workerlist[num_workers].name[buf_size] = '\0'; for(i = 0; i < num_defs; ++i) { fprintf(outfile, "Comparing %s with %s(%d)\n", view_workerlist[num_workers].name, deflist[i].name, i); if(strcmp(view_workerlist[num_workers].name, deflist[i].name)==0) { view_workerlist[num_workers].display_type=2;//Trapezoid view_workerlist[num_workers].type=2;//Worker view_workerlist[num_workers].num_inputs=deflist[i].num_inputs; view_workerlist[num_workers].num_outputs=deflist[i].num_outputs; view_workerlist[num_workers].null_input = FALSE; view_workerlist[num_workers].value_index = i; view_workerlist[num_workers].width = ((double)buf_size+0.5) * INPUT_SIZE; ++num_workers; buf_size = 0; break; } } if(i >= num_defs) { strcpy(new_name_buf, "I don't know a worker with that name."); buf_size = strlen(new_name_buf); } } if(view_workerlist[num_workers-1].width <= (double)view_workerlist[num_workers-1].num_outputs * OUTPUT_SIZE) view_workerlist[num_workers-1].width = (double)view_workerlist[num_workers-1].num_outputs * (OUTPUT_SIZE*1.1); if(view_workerlist[num_workers-1].width <= (double)view_workerlist[num_workers-1].num_inputs * INPUT_SIZE) view_workerlist[num_workers-1].width = (double)view_workerlist[num_workers-1].num_inputs * (INPUT_SIZE*1.1); break; } case WM_LBUTTONDOWN: { mouse_leftstart_down=mouse_left_down=TRUE; mouse_lastx = mouse_curx = GET_X_LPARAM(lParam); mouse_lasty = mouse_cury = 480-GET_Y_LPARAM(lParam); checked_mouse_pos=FALSE; return 0; } case WM_LBUTTONUP: { mouse_leftstart_down=mouse_left_down=FALSE; return 0; } case WM_MOUSEMOVE: { //If no one has checked the mouse position vars, this could cause bugs if(checked_mouse_pos) { mouse_lastx = mouse_curx; mouse_lasty = mouse_cury; } mouse_curx = GET_X_LPARAM(lParam); mouse_cury = 480-GET_Y_LPARAM(lParam); checked_mouse_pos=FALSE; return 0; } case WM_CHAR: { if(wParam >= 0x20) { new_name_buf[buf_size++]=wParam&0xFF; } return 0; } } // Pass All Unhandled Messages To DefWindowProc return DefWindowProc(hWnd,uMsg,wParam,lParam); } VOID CALLBACK DoFrame(HWND myhWnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime) { if(active) { DrawGLScene(); // Draw The Scene SwapBuffers(hDC); // Swap Buffers (Double Buffering) } } int WINAPI WinMain( HINSTANCE hInstance, // Instance HINSTANCE hPrevInstance, // Previous Instance LPSTR lpCmdLine, // Command Line Parameters int nCmdShow) // Window Show State { MSG msg; // Windows Message Structure BOOL done=FALSE; // Bool Variable To Exit Loop // Ask The User Which Screen Mode They Prefer if (MessageBox(NULL,"Would You Like To Run In Fullscreen Mode?", "Start FullScreen?",MB_YESNO|MB_ICONQUESTION)==IDNO) { fullscreen=FALSE; // Windowed Mode } // Create Our OpenGL Window if (!CreateGLWindow("Visuality",640,480,16,fullscreen)) { return 0; // Quit If Window Was Not Created } initworkers(); view_workerlist = deflist[0].implement_func->workerlist; view_wirelist = deflist[0].implement_func->wirelist; outfile = fopen("output.txt", "w"); SetTimer(hWnd, 1, 17, DoFrame); while(!done) // Loop That Runs Until done=TRUE { if (PeekMessage(&msg,NULL,0,0,PM_REMOVE)) // Is There A Message Waiting? { if (msg.message==WM_QUIT) // Have We Received A Quit Message? { done=TRUE; // If So done=TRUE } else // If Not, Deal With Window Messages { TranslateMessage(&msg); // Translate The Message DispatchMessage(&msg); // Dispatch The Message } } // Draw The Scene. Watch For ESC Key And Quit Messages From DrawGLScene() if (active) // Program Active? { if (keys[VK_ESCAPE]) // Was ESC Pressed? { done=TRUE; // ESC Signalled A Quit } else // Not Time To Quit, Update Screen { } if (keys[VK_F1]) // Is F1 Being Pressed? { keys[VK_F1]=FALSE; // If So Make Key FALSE KillTimer(hWnd, 1); KillGLWindow(); // Kill Our Current Window fullscreen=!fullscreen; // Toggle Fullscreen / Windowed Mode // Recreate Our OpenGL Window if (!CreateGLWindow("Rini's Love Quest",640,480,16,fullscreen)) { return 0; // Quit If Window Was Not Created } SetTimer(hWnd, 1, 17, DoFrame); } } Sleep(0); } KillTimer(hWnd, 1); // Shutdown KillGLWindow(); // Kill The Window return (msg.wParam); // Exit The Program }