Imported vanilla contents from upstream
[construo.git] / glut_display.cxx
blobb79b88c572c81e1bdd271a805180d7ce67eca1b2
1 // $Id: glut_display.cxx,v 1.25 2003/07/28 22:46:48 grumbel Exp $
2 //
3 // Construo - A wire-frame construction gamee
4 // Copyright (C) 2002 Ingo Ruhnke <grumbel@gmx.de>
5 //
6 // This program is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU General Public License
8 // as published by the Free Software Foundation; either version 2
9 // of the License, or (at your option) any later version.
11 // This program is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 // GNU General Public License for more details.
16 // You should have received a copy of the GNU General Public License
17 // along with this program; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 #include <config.h>
22 #ifdef HAVE_FREEGLUT
23 # include <GL/freeglut.h>
24 #else
25 # include <GL/glut.h>
26 #endif
28 #include <stdio.h>
29 #include <assert.h>
30 #include <iostream>
31 #include "buttons.hxx"
32 #include "events.hxx"
33 #include "settings.hxx"
34 #include "construo_main.hxx"
35 #include "screen_manager.hxx"
36 #include "glut_display.hxx"
38 GlutDisplay* GlutDisplay::instance_ = 0;
40 void reshape_func(int w, int h)
42 GlutDisplay::instance()->reshape_func(w, h);
45 void display_func ()
47 GlutDisplay::instance()->display_func();
50 void mouse_func (int button, int button_state, int x, int y)
52 GlutDisplay::instance()->mouse_func(button, button_state, x, y);
55 void idle_func ()
57 GlutDisplay::instance()->idle_func();
60 void keyboard_func (unsigned char key, int x, int y)
62 GlutDisplay::instance()->keyboard_func(key, x, y);
65 void special_func (int key, int x, int y)
67 GlutDisplay::instance()->special_func(key, x, y);
70 void mouse_motion_func (int x, int y)
72 GlutDisplay::instance()->mouse_motion_func(x, y);
75 GlutDisplay::GlutDisplay (int w, int h, int fullscreen)
77 instance_ = this;
79 update_display = 0;
80 width = w;
81 height = h;
83 int argc = 1;
84 char* argv[] = { "construo", "\0" };
86 glutInit(&argc, argv); // Only pass empty dummies
87 glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA);
88 glutInitWindowSize(width, height);
89 //glutInitWindowPosition(100, 100); don't care
90 glutSetWindow(glutCreateWindow(construo_main->get_title()));
92 glutDisplayFunc(::display_func);
93 glutReshapeFunc(::reshape_func);
94 glutMouseFunc(::mouse_func);
96 glutMotionFunc (::mouse_motion_func);
97 glutPassiveMotionFunc (::mouse_motion_func);
99 glutIdleFunc (::idle_func);
100 glutKeyboardFunc(::keyboard_func);
101 glutSpecialFunc(::special_func);
103 glClearColor (0.0, 0.0, 0.0, 0.1);
104 if (settings.alphablending)
106 glShadeModel (GL_SMOOTH);
107 glEnable(GL_BLEND);
108 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
111 if (settings.antialiasing && settings.alphablending)
113 glEnable(GL_LINE_SMOOTH);
116 //glEnable(GL_SCISSOR_TEST);
117 //glScissor(0, 0, settings.screen_width, settings.screen_height);
118 glutSetCursor(GLUT_CURSOR_FULL_CROSSHAIR);
120 window_x_pos = 0;
121 window_y_pos = 0;
122 window_width = w;
123 window_height = h;
125 if (fullscreen)
126 enter_fullscreen();
129 void
130 GlutDisplay::run()
132 std::cout << "Starting glut mainloop" << std::endl;
133 glutMainLoop();
134 std::cout << "Ending glut mainloop" << std::endl;
137 GlutDisplay::~GlutDisplay()
141 void
142 GlutDisplay::draw_lines (std::vector<Line>& lines, Color color, int wide)
144 if (settings.thick_lines)
145 glLineWidth (wide);
147 glBegin (GL_LINES);
148 for (std::vector<Line>::const_iterator i = lines.begin(); i != lines.end(); ++i)
150 glVertex2f (i->x1, i->y1);
151 glVertex2f (i->x2, i->y2);
153 glEnd ();
156 void
157 GlutDisplay::draw_line(float x1, float y1, float x2, float y2, Color color, int wide)
159 if (settings.thick_lines)
160 glLineWidth (wide);
162 glColor4f (color.r, color.g, color.b, color.a);
163 glBegin (GL_LINES);
164 glVertex2f (x1, y1);
165 glVertex2f (x2, y2);
166 glEnd ();
169 void
170 GlutDisplay::draw_rect(float x1, float y1, float x2, float y2, Color color)
172 if (settings.thick_lines)
173 glLineWidth (2);
175 glColor4f (color.r, color.g, color.b, color.a);
176 glBegin (GL_LINE_STRIP);
177 glVertex2f (x1, y1);
178 glVertex2f (x2, y1);
179 glVertex2f (x2, y2);
180 glVertex2f (x1, y2);
181 glVertex2f (x1, y1);
182 glEnd ();
185 void
186 GlutDisplay::draw_fill_rect(float x1, float y1, float x2, float y2, Color color)
188 if (settings.thick_lines)
189 glLineWidth (.5f);
191 glColor4f (color.r, color.g, color.b, color.a);
192 glBegin (GL_QUADS);
193 glVertex2f (x1, y1);
194 glVertex2f (x2, y1);
195 glVertex2f (x2, y2);
196 glVertex2f (x1, y2);
197 glEnd ();
200 void
201 GlutDisplay::draw_circles(std::vector<Circle>& circles, Color color)
203 for (std::vector<Circle>::iterator i = circles.begin(); i != circles.end(); ++i)
205 draw_circle(i->x, i->y, i->r, color);
209 void
210 GlutDisplay::draw_circle(float x, float y, float r, Color color)
212 glColor4f (color.r, color.g, color.b, color.a);
214 GLUquadricObj* qobj = gluNewQuadric ();
215 gluQuadricDrawStyle(qobj, GLU_SILHOUETTE);
216 //gluQuadricNormals (qobj, GLU_FLAT);
217 glPushMatrix();
218 glTranslatef (x, y, 0);
219 gluDisk (qobj, 0, r, 8, 1);
220 /*draw_rect (x - r, y - r, x + r, y + r,
221 color);*/
222 glPopMatrix ();
223 gluDeleteQuadric (qobj);
226 void
227 GlutDisplay::draw_fill_circle(float x, float y, float r, Color color)
229 glColor4f (color.r, color.g, color.b, color.a);
230 //draw_fill_rect (x - r, y - r, x + r, y + r,
231 // color);
233 GLUquadricObj* qobj = gluNewQuadric ();
234 gluQuadricDrawStyle(qobj, GLU_FILL);
235 //gluQuadricNormals (qobj, GLU_FLAT);
236 glPushMatrix();
237 glTranslatef (x, y, 0);
238 gluDisk (qobj, 0, r, 8, 1);
239 /*draw_rect (x - r, y - r, x + r, y + r,
240 color);*/
241 glPopMatrix ();
242 gluDeleteQuadric (qobj);
245 void
246 GlutDisplay::draw_string(float x, float y, const std::string& str, Color color)
248 if (settings.thick_lines)
249 glLineWidth (1.0f);
251 glColor4f (color.r, color.g, color.b, color.a);
252 glPushMatrix();
253 glTranslatef (x , y, 0);
254 glScalef (.07f, -.07, 0);
256 for (std::string::const_iterator i = str.begin (); i != str.end (); ++i)
258 #ifdef HAVE_FREEGLUT
259 glutBitmapCharacter (GLUT_BITMAP_8_BY_13, *i);
260 #else
261 glutStrokeCharacter (GLUT_STROKE_MONO_ROMAN, *i);
262 //glutStrokeWidth (GLUT_STROKE_MONO_ROMAN, *i);
263 #endif
265 glPopMatrix();
269 void
270 GlutDisplay::draw_string_centered(float x, float y, const std::string& str, Color color)
272 draw_string(x - (7.5 * str.length())/2,
273 y, str, color);
276 bool
277 GlutDisplay::get_key (int key)
279 return false;
283 GlutDisplay::get_mouse_x ()
285 return mouse_x;
289 GlutDisplay::get_mouse_y ()
291 return mouse_y;
294 void
295 GlutDisplay::clear ()
297 glClear(GL_COLOR_BUFFER_BIT);
300 void
301 GlutDisplay::flip ()
303 glutSwapBuffers();
306 void
307 GlutDisplay::flip (int x1, int y1, int x2, int y2)
309 assert (false);
313 void
314 GlutDisplay::reshape_func(int w, int h)
316 std::cout << "Reshape: " << w << " " << h << std::endl;
317 glViewport (0,0, w, h);
318 glMatrixMode(GL_PROJECTION);
319 glLoadIdentity();
320 gluOrtho2D (0, w, h, 0);
321 glMatrixMode(GL_MODELVIEW);
322 width = w;
323 height = h;
326 void
327 GlutDisplay::display_func ()
329 ScreenManager::instance()->run_once();
332 void
333 GlutDisplay::mouse_func (int button, int button_state, int x, int y)
335 mouse_x = x;
336 mouse_y = y;
338 Event event;
339 event.type = BUTTON_EVENT;
341 //std::cout << "mouse button press: " << button << " " << button_state << " " << x << " " << y << std::endl;
343 if (button_state == 0)
344 event.button.pressed = true;
345 else
346 event.button.pressed = false;
348 switch (button)
350 case 0:
351 event.button.id = BUTTON_PRIMARY;
352 break;
353 case 1:
354 event.button.id = BUTTON_TERTIARY;
355 break;
356 case 2:
357 event.button.id = BUTTON_SECONDARY;
358 break;
359 case 3:
360 event.button.id = BUTTON_ZOOM_IN;
361 break;
362 case 4:
363 event.button.id = BUTTON_ZOOM_OUT;
364 break;
365 default:
366 std::cout << "GlutDisplay: Unhandle mouse button press: " << button << " " << button_state << std::endl;
367 return;
369 events.push (event);
372 void
373 GlutDisplay::idle_func ()
375 /* if (Controller::instance()->is_running() || update_display > 0)
377 //system_context->sleep (0); // limit CPU usage via brute force
378 update_display = 0;
380 if (!ScreenManager::instance ()->is_finished())
382 ScreenManager::instance ()->run_once();
384 else
386 construo_main->exit();
390 void
391 GlutDisplay::special_func (int key, int x, int y)
393 switch (key)
395 case GLUT_KEY_F11:
396 if (is_fullscreen)
397 leave_fullscreen();
398 else
399 enter_fullscreen();
400 break;
404 void
405 GlutDisplay::keyboard_func (unsigned char key, int x, int y)
407 //std::cout << "GlutDisplay: keypress: " << key << " (" << int(key) << ") " << x << " " << y << std::endl;
409 Event event;
410 event.type = BUTTON_EVENT;
411 event.button.pressed = true;
413 switch (key)
415 case 127: // Delete
416 event.button.id = BUTTON_DELETE;
417 break;
418 case 32: // Space
419 event.button.id = BUTTON_RUN;
420 break;
421 case 9: // Tab
422 event.button.id = BUTTON_TOGGLESLOWMO;
423 break;
424 case 27: // Escape
425 case 'q':
426 event.button.id = BUTTON_ESCAPE;
427 break;
428 case 'h':
429 event.button.id = BUTTON_FLIP;
430 break;
431 case 'f':
432 event.button.id = BUTTON_FIX;
433 break;
434 case 'd':
435 event.button.id = BUTTON_DUPLICATE;
436 break;
438 case 'v':
439 event.button.id = BUTTON_SETVELOCITY;
440 break;
442 case 'c':
443 event.button.id = BUTTON_CLEAR;
444 break;
446 case 'j':
447 event.button.id = BUTTON_JOIN;
448 break;
450 case 's':
451 event.button.id = BUTTON_SCALE;
452 break;
454 case 'a':
455 event.button.id = BUTTON_ACTIONCAM;
456 break;
458 case 'o':
459 event.button.id = BUTTON_HIDEDOTS;
460 break;
462 case '!':
463 event.button.id = BUTTON_QUICKLOAD1;
464 break;
466 case '@':
467 event.button.id = BUTTON_QUICKLOAD2;
468 break;
470 case '#':
471 event.button.id = BUTTON_QUICKLOAD3;
472 break;
474 case '$':
475 event.button.id = BUTTON_QUICKLOAD4;
476 break;
478 case '%':
479 event.button.id = BUTTON_QUICKLOAD5;
480 break;
482 case '^':
483 event.button.id = BUTTON_QUICKLOAD6;
484 break;
486 case '&':
487 event.button.id = BUTTON_QUICKLOAD7;
488 break;
490 case '*':
491 event.button.id = BUTTON_QUICKLOAD8;
492 break;
494 case '(':
495 event.button.id = BUTTON_QUICKLOAD9;
496 break;
498 case ')':
499 event.button.id = BUTTON_QUICKLOAD0;
500 break;
502 case '0':
503 event.button.id = BUTTON_QUICKSAVE0;
504 break;
506 case '1':
507 event.button.id = BUTTON_QUICKSAVE1;
508 break;
510 case '2':
511 event.button.id = BUTTON_QUICKSAVE2;
512 break;
514 case '3':
515 event.button.id = BUTTON_QUICKSAVE3;
516 break;
518 case '4':
519 event.button.id = BUTTON_QUICKSAVE4;
520 break;
522 case '5':
523 event.button.id = BUTTON_QUICKSAVE5;
524 break;
526 case '6':
527 event.button.id = BUTTON_QUICKSAVE6;
528 break;
530 case '7':
531 event.button.id = BUTTON_QUICKSAVE7;
532 break;
534 case '8':
535 event.button.id = BUTTON_QUICKSAVE8;
536 break;
538 case '9':
539 event.button.id = BUTTON_QUICKSAVE9;
540 break;
542 case 'g':
543 event.button.id = BUTTON_GRID;
544 break;
546 case 'u':
547 event.button.id = BUTTON_UNDO;
548 break;
549 case 'r':
550 event.button.id = BUTTON_REDO;
551 break;
552 case '+':
553 case '=': // so that people don't have to press shift
554 event.button.id = BUTTON_ZOOM_IN;
555 break;
556 case '-':
557 event.button.id = BUTTON_ZOOM_OUT;
558 break;
559 default:
560 #ifdef DEBUG
561 std::cout << "GlutDisplay: Unhandled keypress: '" << key << "'[" << int(key) << "] x/y: "
562 << x << ", " << y << std::endl;
563 #endif
564 return;
567 events.push(event);
570 void
571 GlutDisplay::mouse_motion_func (int x, int y)
573 //std::cout << "Motion: " << x << " " << y << std::endl;
574 mouse_x = x;
575 mouse_y = y;
578 void
579 GlutDisplay::leave_fullscreen()
581 std::cout << "GlutDisplay: leaving fullscreen: restoring to: pos: "
582 << window_x_pos << ", " << window_y_pos << " - WxH: "
583 << window_width << ", " << window_height << std::endl;
585 glutReshapeWindow(window_width, window_height);
586 glutPositionWindow(window_x_pos, window_y_pos);
588 is_fullscreen = false;
591 void
592 GlutDisplay::enter_fullscreen()
594 #if 0
595 char mode[64];
596 snprintf (mode, 64, "%dx%d:%d@%d", width, height, 16, 80);
597 std::cout << "GlutDisplay: switching to: " << mode << std::endl;
598 glutGameModeString(mode);
599 glutEnterGameMode();
600 is_fullscreen = true;
601 #else
602 std::cout << "GlutDisplay: Entering fullscreen" << std::endl;
604 window_x_pos = glutGet((GLenum)GLUT_WINDOW_X);
605 window_y_pos = glutGet((GLenum)GLUT_WINDOW_Y);
606 window_width = glutGet((GLenum)GLUT_WINDOW_WIDTH);
607 window_height = glutGet((GLenum)GLUT_WINDOW_HEIGHT);
609 std::cout << "Saving window: " << window_x_pos << ", " << window_y_pos << " - WxH: "
610 << window_width << ", " << window_height << std::endl;
612 glutFullScreen();
614 is_fullscreen = true;
615 #endif
618 void
619 GlutDisplay::set_clip_rect (int x1, int y1, int x2, int y2)
621 //std::cout << "Setting cliprect: " << x1<< " " <<y1<< " " <<x2-x1+1<< " " <<y2-y1+1<<std::endl;
622 // FIXME: doesn't really work for some reason
623 //std::cout << "Clip: " << x1 << ", " << y1 << " - " << x2-x1+1 << "x" << y2-y1+1 << std::endl;
624 //glScissor(x1, y1, x2-x1+1, y2-y1+1);
627 void
628 GlutDisplay::push_quick_draw()
630 if (settings.antialiasing && settings.alphablending)
632 glDisable(GL_LINE_SMOOTH);
636 void
637 GlutDisplay::pop_quick_draw()
639 if (settings.antialiasing && settings.alphablending)
641 glEnable(GL_LINE_SMOOTH);
645 void
646 GlutDisplay::set_cursor_real(CursorType cursor)
648 switch(cursor)
650 case CURSOR_INSERT:
651 glutSetCursor(GLUT_CURSOR_CROSSHAIR);
652 break;
653 case CURSOR_SCROLL:
654 glutSetCursor(GLUT_CURSOR_INFO);
655 break;
656 case CURSOR_ZOOM:
657 glutSetCursor(GLUT_CURSOR_HELP);
658 break;
659 case CURSOR_COLLIDER:
660 glutSetCursor(GLUT_CURSOR_CROSSHAIR);
661 break;
662 case CURSOR_SELECT:
663 glutSetCursor(GLUT_CURSOR_INHERIT);
664 break;
665 case CURSOR_ROTATE:
666 glutSetCursor(GLUT_CURSOR_CYCLE);
667 break;
668 default:
669 std::cout << "GlutDisplay: Unhandled cursor type: " << cursor << std::endl;
670 break;
675 /* EOF */