Main Page   Namespace List   Class Hierarchy   Compound List   File List   Namespace Members   Compound Members   File Members  

glut_display.cxx

Go to the documentation of this file.
00001 //  $Id: glut_display.cxx,v 1.11 2003/01/12 19:06:08 grumbel Exp $
00002 //
00003 //  Construo - A wire-frame construction gamee
00004 //  Copyright (C) 2002 Ingo Ruhnke <grumbel@gmx.de>
00005 //
00006 //  This program is free software; you can redistribute it and/or
00007 //  modify it under the terms of the GNU General Public License
00008 //  as published by the Free Software Foundation; either version 2
00009 //  of the License, or (at your option) any later version.
00010 //
00011 //  This program is distributed in the hope that it will be useful,
00012 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
00013 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014 //  GNU General Public License for more details.
00015 //
00016 //  You should have received a copy of the GNU General Public License
00017 //  along with this program; if not, write to the Free Software
00018 //  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
00019 
00020 #include <config.h>
00021 
00022 #ifdef HAVE_FREEGLUT
00023 #  include <GL/freeglut.h>
00024 #else
00025 #  include <GL/glut.h>
00026 #endif
00027 
00028 #include <stdio.h>
00029 #include <assert.h>
00030 #include <iostream>
00031 #include "buttons.hxx"
00032 #include "events.hxx"
00033 #include "settings.hxx"
00034 #include "screen_manager.hxx"
00035 #include "glut_display.hxx"
00036 
00037 GlutDisplay* GlutDisplay::instance_ = 0;
00038 
00039 void reshape_func(int w, int h)
00040 {
00041   GlutDisplay::instance()->reshape_func(w, h);
00042 }
00043 
00044 void display_func ()
00045 {
00046   GlutDisplay::instance()->display_func();
00047 }
00048 
00049 void mouse_func (int button, int button_state, int x, int y)
00050 {
00051   GlutDisplay::instance()->mouse_func(button, button_state, x, y);
00052 }
00053 
00054 void idle_func ()
00055 {
00056   GlutDisplay::instance()->idle_func();
00057 }
00058 
00059 void keyboard_func (unsigned char key, int x, int y)
00060 {
00061   GlutDisplay::instance()->keyboard_func(key, x, y);
00062 }
00063 
00064 void mouse_motion_func (int x, int y)
00065 {
00066   GlutDisplay::instance()->mouse_motion_func(x, y);
00067 }
00068 
00069 GlutDisplay::GlutDisplay (int w, int h)
00070 {
00071   instance_ = this;
00072 
00073   update_display = 0;
00074   width  = w;
00075   height = h;
00076 
00077   int argc = 1;
00078   char* argv[] = { "construo", "\0" };
00079 
00080   glutInit(&argc, argv); // Only pass empty dummies
00081   glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA);
00082   glutInitWindowSize(width, height);
00083   //glutInitWindowPosition(100, 100); don't care
00084   glutSetWindow(glutCreateWindow(argv[0]));
00085 
00086   glutDisplayFunc(::display_func);
00087   glutReshapeFunc(::reshape_func);
00088   glutMouseFunc(::mouse_func);
00089 
00090   glutMotionFunc (::mouse_motion_func);
00091   glutPassiveMotionFunc (::mouse_motion_func);
00092 
00093   glutIdleFunc (::idle_func);
00094   glutKeyboardFunc(::keyboard_func);
00095 
00096   is_fullscreen = false;
00097   
00098   glClearColor (0.0, 0.0, 0.0, 0.1);
00099   if (settings.alphablending)
00100     {
00101       glShadeModel (GL_SMOOTH);
00102       glEnable(GL_BLEND);
00103       glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
00104     }
00105 
00106   if (settings.antialiasing && settings.alphablending)
00107     {
00108       glEnable(GL_LINE_SMOOTH);
00109     }
00110   
00111   glEnable(GL_SCISSOR_TEST);
00112   glScissor(0, 0, settings.screen_width, settings.screen_height);
00113 }
00114 
00115 void
00116 GlutDisplay::run()
00117 {
00118   std::cout << "Starting glut mainloop" << std::endl;
00119   glutMainLoop(); 
00120   std::cout << "Ending glut mainloop" << std::endl;
00121 }
00122 
00123 GlutDisplay::~GlutDisplay()
00124 {
00125 }
00126 
00127 void
00128 GlutDisplay::draw_lines (std::vector<Line>& lines, Color color, int wide)
00129 {
00130   glLineWidth (wide);
00131   
00132   glBegin (GL_LINES);
00133   for (std::vector<Line>::const_iterator i = lines.begin(); i != lines.end(); ++i)
00134     {
00135       glVertex2f (i->x1, i->y1);
00136       glVertex2f (i->x2, i->y2);     
00137     }
00138   glEnd ();
00139 }
00140 
00141 void 
00142 GlutDisplay::draw_line(float x1, float y1, float x2, float y2, Color color, int wide)
00143 {
00144   glLineWidth (wide);
00145   glColor4f (color.r, color.g, color.b, color.a);
00146   glBegin (GL_LINES);
00147   glVertex2f (x1, y1);
00148   glVertex2f (x2, y2);
00149   glEnd ();
00150 }
00151 
00152 void
00153 GlutDisplay::draw_rect(float x1, float y1, float x2, float y2, Color color)
00154 {
00155   glLineWidth (2);
00156   glColor4f (color.r, color.g, color.b, color.a);
00157   glBegin (GL_LINE_STRIP);
00158   glVertex2f (x1, y1);
00159   glVertex2f (x2, y1);
00160   glVertex2f (x2, y2);
00161   glVertex2f (x1, y2);
00162   glVertex2f (x1, y1);
00163   glEnd ();
00164 }
00165 
00166 void
00167 GlutDisplay::draw_fill_rect(float x1, float y1, float x2, float y2, Color color)
00168 {
00169   glLineWidth (.5f);
00170   glColor4f (color.r, color.g, color.b, color.a);
00171   glBegin (GL_QUADS);
00172   glVertex2f (x1, y1);
00173   glVertex2f (x2, y1);
00174   glVertex2f (x2, y2);
00175   glVertex2f (x1, y2);
00176   glEnd ();
00177 }
00178 
00179 void
00180 GlutDisplay::draw_circles(std::vector<Circle>& circles, Color color)
00181 {
00182   for (std::vector<Circle>::iterator i = circles.begin(); i != circles.end(); ++i)
00183     {
00184       draw_circle(i->x, i->y, i->r, color);
00185     }
00186 }
00187 
00188 void
00189 GlutDisplay::draw_circle(float x, float y, float r, Color color)
00190 {
00191   glColor4f (color.r, color.g, color.b, color.a);
00192   
00193   GLUquadricObj* qobj = gluNewQuadric ();
00194   gluQuadricDrawStyle(qobj, GLU_SILHOUETTE);
00195   //gluQuadricNormals (qobj, GLU_FLAT);
00196   glPushMatrix();
00197   glTranslatef (x, y, 0);
00198   gluDisk (qobj, 0, r, 8, 1);
00199   /*draw_rect (x - r, y - r, x + r, y + r,
00200     color);*/
00201   glPopMatrix ();
00202   gluDeleteQuadric (qobj);
00203 }
00204 
00205 void
00206 GlutDisplay::draw_fill_circle(float x, float y, float r, Color color)
00207 {
00208   glColor4f (color.r, color.g, color.b, color.a);
00209   //draw_fill_rect (x - r, y - r, x + r, y + r,
00210   //              color);
00211   
00212   GLUquadricObj* qobj = gluNewQuadric ();
00213   gluQuadricDrawStyle(qobj, GLU_FILL);
00214   //gluQuadricNormals (qobj, GLU_FLAT);
00215   glPushMatrix();
00216   glTranslatef (x, y, 0);
00217   gluDisk (qobj, 0, r, 8, 1);
00218   /*draw_rect (x - r, y - r, x + r, y + r,
00219     color);*/
00220   glPopMatrix ();
00221   gluDeleteQuadric (qobj);
00222 }
00223 
00224 void
00225 GlutDisplay::draw_string(float x, float y, const std::string& str, Color color)
00226 {
00227   glLineWidth (1.0f);
00228   glColor4f (color.r, color.g, color.b, color.a);
00229   glPushMatrix();
00230   glTranslatef (x , y, 0);
00231   glScalef (.07f, -.07, 0);
00232 
00233   for (std::string::const_iterator i = str.begin (); i != str.end (); ++i)
00234     {
00235 #ifdef HAVE_FREEGLUT
00236       glutBitmapCharacter  (GLUT_BITMAP_8_BY_13, *i);
00237 #else
00238       glutStrokeCharacter  (GLUT_STROKE_MONO_ROMAN, *i);
00239       //glutStrokeWidth (GLUT_STROKE_MONO_ROMAN, *i);
00240 #endif
00241     }
00242   glPopMatrix();
00243 }
00244 
00245 
00246 void
00247 GlutDisplay::draw_string_centered(float x, float y, const std::string& str, Color color)
00248 {
00249   draw_string(x - (7.5 * str.length())/2,
00250               y, str, color);
00251 }
00252 
00253 bool
00254 GlutDisplay::get_key (int key)
00255 {
00256   return false;
00257 }
00258 
00259 int
00260 GlutDisplay::get_mouse_x ()
00261 {
00262   return mouse_x;
00263 }
00264 
00265 int
00266 GlutDisplay::get_mouse_y ()
00267 {
00268   return mouse_y;
00269 }
00270 
00271 void
00272 GlutDisplay::clear ()
00273 {
00274   glClear(GL_COLOR_BUFFER_BIT);
00275 }
00276 
00277 void
00278 GlutDisplay::flip ()
00279 {
00280   glutSwapBuffers();
00281 }
00282 
00283 void
00284 GlutDisplay::flip (int x1, int y1, int x2, int y2)
00285 {
00286   assert (false);
00287 }
00288 
00289 
00290 void
00291 GlutDisplay::reshape_func(int w, int h)
00292 {
00293   glViewport (0,0, w, h);
00294   glLoadIdentity();
00295   gluOrtho2D (0, w, h, 0);
00296 }
00297 
00298 void
00299 GlutDisplay::display_func ()
00300 {
00301   ScreenManager::instance()->run_once();
00302 }
00303 
00304 void
00305 GlutDisplay::mouse_func (int button, int button_state, int x, int y)
00306 {
00307   mouse_x = x;
00308   mouse_y = y;
00309 
00310   Event event;
00311   event.type = BUTTON_EVENT;
00312   
00313   //std::cout << "mouse button press: " << button << " " << button_state <<  " " << x << " " << y << std::endl;
00314 
00315   if (button_state == 0)
00316     event.button.pressed = true;
00317   else
00318     event.button.pressed = false;
00319 
00320   switch (button)
00321     {
00322     case 0:
00323       event.button.id = BUTTON_PRIMARY;
00324       break;
00325     case 1:
00326       event.button.id = BUTTON_TERTIARY;
00327       break;
00328     case 2:
00329       event.button.id = BUTTON_SECONDARY;
00330       break;
00331     case 3:
00332       event.button.id = BUTTON_ZOOM_IN;
00333       break;
00334     case 4:
00335       event.button.id = BUTTON_ZOOM_OUT;
00336       break;
00337     default:
00338       std::cout << "GlutDisplay: Unhandle mouse button press: " << button << " " << button_state << std::endl;
00339       return;
00340     }
00341   events.push (event);
00342 }
00343 
00344 void
00345 GlutDisplay::idle_func ()
00346 {
00347   /*  if (Controller::instance()->is_running() || update_display > 0)
00348     {
00349       //system_context->sleep (0); // limit CPU usage via brute force
00350       update_display = 0;
00351     }*/
00352   if (!ScreenManager::instance ()->is_finished())
00353     {
00354       ScreenManager::instance ()->run_once();
00355     }
00356   else
00357     {
00358       // FIXME: is there a more gracefull way to end this?
00359       exit(EXIT_SUCCESS);
00360     }
00361 }
00362 
00363 void
00364 GlutDisplay::keyboard_func (unsigned char key, int x, int y)
00365 {
00366   //std::cout << "GlutDisplay: keypress: " << key << " (" << int(key) << ") " << x << " " << y << std::endl;
00367 
00368   Event event;
00369   event.type = BUTTON_EVENT;
00370   event.button.pressed = true;
00371 
00372   switch (key)
00373     {
00374     case 127: // Delete
00375       event.button.id = BUTTON_DELETE;
00376       break;
00377     case 32: // Space
00378       event.button.id = BUTTON_RUN;
00379       break;
00380     case 9: // Tab
00381       event.button.id = BUTTON_TOGGLESLOWMO;
00382       break;
00383     case 27: // Escape
00384     case 'q':
00385       event.button.id = BUTTON_ESCAPE;
00386       break;
00387     case 'f':
00388       event.button.id = BUTTON_FIX;
00389       break;
00390     case 'd':
00391       event.button.id = BUTTON_DUPLICATE;
00392       break;
00393 
00394     case 'v':
00395       event.button.id = BUTTON_SETVELOCITY;
00396       break;
00397 
00398     case 'c':
00399       event.button.id = BUTTON_CLEAR;
00400       break;
00401 
00402     case 'a':
00403       event.button.id = BUTTON_ACTIONCAM;
00404       break;
00405 
00406     case 'o':
00407       event.button.id = BUTTON_HIDEDOTS;
00408       break;
00409 
00410     case '!':
00411       event.button.id = BUTTON_QUICKLOAD1;
00412       break;
00413 
00414     case '@':
00415       event.button.id = BUTTON_QUICKLOAD2;
00416       break;
00417 
00418     case '#':
00419       event.button.id = BUTTON_QUICKLOAD3;
00420       break;
00421 
00422     case '$':
00423       event.button.id = BUTTON_QUICKLOAD4;
00424       break;
00425 
00426     case '%':
00427       event.button.id = BUTTON_QUICKLOAD5;
00428       break;
00429 
00430     case '^':
00431       event.button.id = BUTTON_QUICKLOAD6;
00432       break;
00433 
00434     case '&':
00435       event.button.id = BUTTON_QUICKLOAD7;
00436       break;
00437 
00438     case '*':
00439       event.button.id = BUTTON_QUICKLOAD8;
00440       break;
00441 
00442     case '(':
00443       event.button.id = BUTTON_QUICKLOAD9;
00444       break;
00445 
00446     case ')':
00447       event.button.id = BUTTON_QUICKLOAD0;
00448       break;
00449 
00450     case '0':
00451       event.button.id = BUTTON_QUICKSAVE0;
00452       break;
00453 
00454     case '1':
00455       event.button.id = BUTTON_QUICKSAVE1;
00456       break;
00457 
00458     case '2':
00459       event.button.id = BUTTON_QUICKSAVE2;
00460       break;
00461 
00462     case '3':
00463       event.button.id = BUTTON_QUICKSAVE3;
00464       break;
00465 
00466     case '4':
00467       event.button.id = BUTTON_QUICKSAVE4;
00468       break;
00469 
00470     case '5':
00471       event.button.id = BUTTON_QUICKSAVE5;
00472       break;
00473 
00474     case '6':
00475       event.button.id = BUTTON_QUICKSAVE6;
00476       break;
00477 
00478     case '7':
00479       event.button.id = BUTTON_QUICKSAVE7;
00480       break;
00481 
00482     case '8':
00483       event.button.id = BUTTON_QUICKSAVE8;
00484       break;
00485 
00486     case '9':
00487       event.button.id = BUTTON_QUICKSAVE9;
00488       break;
00489 
00490     case 'u':
00491       event.button.id = BUTTON_UNDO;
00492       break;
00493     case 'r':
00494       event.button.id = BUTTON_REDO;
00495       break;
00496     case '+':
00497     case '=': // so that people don't have to press shift
00498       event.button.id = BUTTON_ZOOM_IN;
00499       break;
00500     case '-':
00501       event.button.id = BUTTON_ZOOM_OUT;
00502       break;
00503     default:
00504       std::cout << "GlutDisplay: Unhandled keypress: '" << key << "'[" << int(key) << "] x/y: " 
00505                 << x << ", " << y << std::endl;
00506       return;
00507     }
00508 
00509   events.push(event); 
00510 }
00511 
00512 void
00513 GlutDisplay::mouse_motion_func (int x, int y)
00514 {
00515   //std::cout << "Motion: " << x << " " << y << std::endl;
00516   mouse_x = x;
00517   mouse_y = y;
00518 }
00519 
00520 void
00521 GlutDisplay::set_fullscreen (bool fullscreen)
00522 {
00523   if (fullscreen)
00524     {        
00525       char mode[64];
00526       snprintf (mode, 64, "%dx%d:%d@%d", width, height, 16, 80);
00527       std::cout << "GlutDisplay: switching to: " << mode << std::endl;
00528       glutGameModeString(mode);
00529       glutEnterGameMode();
00530       is_fullscreen = true;
00531     }
00532   else
00533     {
00534       is_fullscreen = false;
00535     }
00536 }
00537 
00538 void
00539 GlutDisplay::set_clip_rect (int x1, int y1, int x2, int y2)
00540 {
00541   //std::cout << "Setting cliprect: " << x1<< " " <<y1<< " " <<x2-x1+1<< " " <<y2-y1+1<<std::endl;
00542   // FIXME: doesn't really work for some reason
00543   //glScissor(x1, y1, x2-x1+1, y2-y1+1);
00544 }
00545 
00546 /* EOF */

Generated on Thu Jul 24 10:24:29 2003 for Construo by doxygen1.3-rc3