topical media & game development

talk show tell print

lib-of-vs-libs-openFrameworks-app-ofAppGlutWindow.cpp / cpp



  include <ofAppGlutWindow.h>
  include <ofBaseApp.h>
  include <ofMain.h>
  
  // glut works with static callbacks UGH, so we need static variables here:
  
  int                                windowMode;
  bool                        bNewScreenMode;
  float                        timeNow, timeThen, fps;
  int                                nFramesForFPS;
  int                                nFrameCount;
  int                                buttonInUse;
  bool                        bEnableSetupScreen;
  
  bool                        bFrameRateSet;
  int                         millisForFrame;
  int                         prevMillis;
  int                         diffMillis;
  
  float                         frameRate;
  
  int                                requestedWidth;
  int                                requestedHeight;
  int                         nonFullScreenX;
  int                         nonFullScreenY;
  int                                mouseX, mouseY;
  ofBaseApp *                ofAppPtr;
  
  //----------------------------------------------------------
  ofAppGlutWindow::ofAppGlutWindow(){
          timeNow                                = 0;
          timeThen                        = 0;
          fps                                        = 60; //give a realistic starting value - win32 issues
          windowMode                        = OF_WINDOW;
          bNewScreenMode                = true;
          nFramesForFPS                = 0;
          nFrameCount                        = 0;
          buttonInUse                        = 0;
          bEnableSetupScreen        = true;
          bFrameRateSet                = false;
          millisForFrame                = 0;
          prevMillis                        = 0;
          diffMillis                        = 0;
          frameRate                        = 0;
          requestedWidth                = 0;
          requestedHeight                = 0;
          nonFullScreenX                = -1;
          nonFullScreenY                = -1;
          mouseX                                = 0;
          mouseY                                = 0;
  
  }
  
  //------------------------------------------------------------
  void ofAppGlutWindow::setupOpenGL(int w, int h, int screenMode){
  
          int argc = 1;
          char *argv = "openframeworks";
          char **vptr = &argv;
          glutInit(&argc, vptr);
          glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH | GLUT_ALPHA );
  
          windowMode = screenMode;
          bNewScreenMode = true;
  
          if (windowMode != OF_GAME_MODE){
                  glutInitWindowSize(w, h);
                  glutCreateWindow("");
  
                  //Default colors etc are now in ofGraphics - ofSetupGraphicDefaults
                  ofSetupGraphicDefaults();
  
                  /*
                  ofBackground(200,200,200);                // default bg color
                  ofSetColor(0xFFFFFF);                         // default draw color
                  // used to be black, but
                  // black + texture = black
                  // so maybe grey bg
                  // and "white" fg color
                  // as default works the best...
  		*/
  
                  requestedWidth  = glutGet(GLUT_WINDOW_WIDTH);
                  requestedHeight = glutGet(GLUT_WINDOW_HEIGHT);
          } else {
                  glutInitDisplayMode( GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH | GLUT_ALPHA );
              // w x h, 32bit pixel depth, 60Hz refresh rate
                  char gameStr[64];
                  sprintf( gameStr, "\%dx\%d:\%d@\%d", w, h, 32, 60 );
  
              glutGameModeString(gameStr);
  
              if (!glutGameModeGet(GLUT_GAME_MODE_POSSIBLE)){
                      ofLog(OF_LOG_ERROR,"game mode error: selected format (\%s) not available \n", gameStr);
              }
              // start fullscreen game mode
              glutEnterGameMode();
          }
  }
  
  //------------------------------------------------------------
  void ofAppGlutWindow::initializeWindow(){
  
           //----------------------
           // setup the callbacks
  
           glutMouseFunc(mouse_cb);
           glutMotionFunc(motion_cb);
           glutPassiveMotionFunc(passive_motion_cb);
           glutIdleFunc(idle_cb);
           glutDisplayFunc(display);
  
           glutKeyboardFunc(keyboard_cb);
           glutKeyboardUpFunc(keyboard_up_cb);
           glutSpecialFunc(special_key_cb);
           glutSpecialUpFunc(special_key_up_cb);
  
           glutReshapeFunc(resize_cb);
  
  }
  
  //------------------------------------------------------------
  void ofAppGlutWindow::runAppViaInfiniteLoop(ofBaseApp * appPtr){
          static ofEventArgs voidEventArgs;
  
          ofAppPtr = appPtr;
  
          if(ofAppPtr){
                  ofAppPtr->setup();
                  ofAppPtr->update();
          }
  
          #ifdef OF_USING_POCO
                  ofNotifyEvent( ofEvents.setup, voidEventArgs );
                  ofNotifyEvent( ofEvents.update, voidEventArgs );
          #endif
  
          glutMainLoop();
  }
  
  //------------------------------------------------------------
  void ofAppGlutWindow::exitApp(){
  
  //  -- This already exists in ofExitCallback
  
  //        static ofEventArgs voidEventArgs;
  //
  //        if(ofAppPtr)ofAppPtr->exit();
  //
  //        #ifdef OF_USING_POCO
  //                ofNotifyEvent( ofEvents.exit, voidEventArgs );
  //        #endif
  
          ofLog(OF_LOG_VERBOSE,"GLUT OF app is being terminated!");
  
          OF_EXIT_APP(0);
  }
  
  //------------------------------------------------------------
  float ofAppGlutWindow::getFrameRate(){
          return frameRate;
  }
  
  //------------------------------------------------------------
  int ofAppGlutWindow::getFrameNum(){
          return nFrameCount;
  }
  
  //------------------------------------------------------------
  void ofAppGlutWindow::setWindowTitle(string title){
          glutSetWindowTitle(title.c_str());
  }
  
  //------------------------------------------------------------
  ofPoint ofAppGlutWindow::getWindowSize(){
          int width = glutGet(GLUT_WINDOW_WIDTH);
          int height = glutGet(GLUT_WINDOW_HEIGHT);
          return ofPoint(width, height,0);
  }
  
  //------------------------------------------------------------
  ofPoint ofAppGlutWindow::getWindowPosition(){
          int x = glutGet(GLUT_WINDOW_X);
          int y = glutGet(GLUT_WINDOW_Y);
          return ofPoint(x,y,0);
  }
  
  //------------------------------------------------------------
  ofPoint ofAppGlutWindow::getScreenSize(){
          int width = glutGet(GLUT_SCREEN_WIDTH);
          int height = glutGet(GLUT_SCREEN_HEIGHT);
          return ofPoint(width, height,0);
  }
  
  //------------------------------------------------------------
  void ofAppGlutWindow::setWindowPosition(int x, int y){
          glutPositionWindow(x,y);
  }
  
  //------------------------------------------------------------
  void ofAppGlutWindow::setWindowShape(int w, int h){
          glutReshapeWindow(w, h);
          // this is useful, esp if we are in the first frame (setup):
          requestedWidth  = w;
          requestedHeight = h;
  }
  
  //------------------------------------------------------------
  void ofAppGlutWindow::hideCursor(){
          glutSetCursor(GLUT_CURSOR_NONE);
  }
  
  //------------------------------------------------------------
  void ofAppGlutWindow::showCursor(){
          glutSetCursor(GLUT_CURSOR_LEFT_ARROW);
  }
  
  //------------------------------------------------------------
  void ofAppGlutWindow::setFrameRate(float targetRate){
          // given this FPS, what is the amount of millis per frame
          // that should elapse?
  
          // --- > f / s
  
          if (targetRate == 0){
                  bFrameRateSet = false;
                  return;
          }
  
          bFrameRateSet                         = true;
          float durationOfFrame         = 1.0f / (float)targetRate;
          millisForFrame                         = (int)(1000.0f * durationOfFrame);
  
          frameRate                                = targetRate;
  
  }
  
  //------------------------------------------------------------
  int ofAppGlutWindow::getWindowMode(){
          return windowMode;
  }
  
  //------------------------------------------------------------
  void ofAppGlutWindow::toggleFullscreen(){
          if( windowMode == OF_GAME_MODE)return;
  
          if( windowMode == OF_WINDOW ){
                  windowMode = OF_FULLSCREEN;
          }else{
                  windowMode = OF_WINDOW;
          }
  
          bNewScreenMode = true;
  }
  
  //------------------------------------------------------------
  void ofAppGlutWindow::setFullscreen(bool fullscreen){
      if( windowMode == OF_GAME_MODE)return;
  
      if(fullscreen && windowMode != OF_FULLSCREEN){
          bNewScreenMode  = true;
          windowMode      = OF_FULLSCREEN;
      }else if(!fullscreen && windowMode != OF_WINDOW) {
          bNewScreenMode  = true;
          windowMode      = OF_WINDOW;
      }
  }
  
  //------------------------------------------------------------
  void ofAppGlutWindow::enableSetupScreen(){
          bEnableSetupScreen = true;
  }
  
  //------------------------------------------------------------
  void ofAppGlutWindow::disableSetupScreen(){
          bEnableSetupScreen = false;
  }
  
  //------------------------------------------------------------
  void ofAppGlutWindow::display(void){
          static ofEventArgs voidEventArgs;
  
          //--------------------------------
          // when I had "glutFullScreen()"
          // in the initOpenGl, I was gettings a "heap" allocation error
          // when debugging via visual studio.  putting it here, changes that.
          // maybe it's voodoo, or I am getting rid of the problem
          // by removing something unrelated, but everything seems
          // to work if I put fullscreen on the first frame of display.
  
          if (windowMode != OF_GAME_MODE){
                  if ( bNewScreenMode ){
                          if( windowMode == OF_FULLSCREEN){
  
                                  //----------------------------------------------------
                                  // before we go fullscreen, take a snapshot of where we are:
                                  nonFullScreenX = glutGet(GLUT_WINDOW_X);
                                  nonFullScreenY = glutGet(GLUT_WINDOW_Y);
                                  //----------------------------------------------------
  
                                  glutFullScreen();
  
                                  #ifdef TARGET_OSX
                                          SetSystemUIMode(kUIModeAllHidden,NULL);
                                  #endif
  
                          }else if( windowMode == OF_WINDOW ){
  
                                  glutReshapeWindow(requestedWidth, requestedHeight);
  
                                  //----------------------------------------------------
                                  // if we have recorded the screen posion, put it there
                                  // if not, better to let the system do it (and put it where it wants)
                                  if (nFrameCount > 0){
                                          glutPositionWindow(nonFullScreenX,nonFullScreenY);
                                  }
                                  //----------------------------------------------------
  
                                  #ifdef TARGET_OSX
                                          SetSystemUIMode(kUIModeNormal,NULL);
                                  #endif
                          }
                          bNewScreenMode = false;
                  }
          }
  
          int width, height;
  
          width  = ofGetWidth();
          height = ofGetHeight();
  
          height = height > 0 ? height : 1;
          // set viewport, clear the screen
          glViewport( 0, 0, width, height );
          float * bgPtr = ofBgColorPtr();
          bool bClearAuto = ofbClearBg();
  
          // I don't know why, I need more than one frame at the start in fullscreen mode
          // also, in non-fullscreen mode, windows/intel graphics, this bClearAuto just fails.
          // I seem to have 2 buffers, alot of flickering
          // and don't accumulate the way I expect.
          // with this line:   if ((bClearAuto == true) || nFrameCount < 3){
          // we do nFrameCount < 3, so that the buffers are cleared at the start of the app
          // or else we have video memory garbage to draw on to...
  
          #ifdef TARGET_WIN32
                  //windows doesn't get accumulation in window mode
                  if ((bClearAuto == true || windowMode == OF_WINDOW) || nFrameCount < 3){
          #else
                  //mac and linux does :)
                  if ( bClearAuto == true || nFrameCount < 3){
          #endif
                  glClearColor(bgPtr[0],bgPtr[1],bgPtr[2], bgPtr[3]);
                  glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
          }
  
          if( bEnableSetupScreen )ofSetupScreen();
  
          if(ofAppPtr)
                  ofAppPtr->draw();
  
          #ifdef OF_USING_POCO
                  ofNotifyEvent( ofEvents.draw, voidEventArgs );
          #endif
  
            glutSwapBuffers();
  
            // -------------- fps calculation:
          timeNow = ofGetElapsedTimef();
          if( (timeNow-timeThen) > 0.05f || nFramesForFPS == 0 ) {
                   fps = (double)nFramesForFPS / (timeNow-timeThen);
                timeThen = timeNow;
                  nFramesForFPS = 0;
  
                  //hack for windows - was getting NAN - maybe unitialized vars???
                  if( nFrameCount < 5) frameRate = fps;
                  else frameRate = 0.9f * frameRate + 0.1f * fps;
            }
            nFramesForFPS++;
            // --------------
  
          nFrameCount++;                // increase the overall frame count
  
          //setFrameNum(nFrameCount); // get this info to ofUtils for people to access
  
  }
  
  //------------------------------------------------------------
  void ofAppGlutWindow::mouse_cb(int button, int state, int x, int y) {
          static ofMouseEventArgs mouseEventArgs;
  
          if (nFrameCount > 0){
                  if(ofAppPtr){
                  ofAppPtr->mouseX = x;
                  ofAppPtr->mouseY = y;
                  }
  
                  if (state == GLUT_DOWN) {
                          if(ofAppPtr)
                                  ofAppPtr->mousePressed(x,y,button);
  
                          #ifdef OF_USING_POCO
                                  mouseEventArgs.x = x;
                                  mouseEventArgs.y = y;
                                  mouseEventArgs.button = button;
                                  ofNotifyEvent( ofEvents.mousePressed, mouseEventArgs );
                          #endif
                  } else if (state == GLUT_UP) {
                          if(ofAppPtr){
                                  ofAppPtr->mouseReleased(x,y,button);
                                  ofAppPtr->mouseReleased();
                          }
  
                          #ifdef OF_USING_POCO
                                  mouseEventArgs.x = x;
                                  mouseEventArgs.y = y;
                                  mouseEventArgs.button = button;
                                  ofNotifyEvent( ofEvents.mouseReleased, mouseEventArgs );
                          #endif
                  }
                  buttonInUse = button;
          }
  }
  
  //------------------------------------------------------------
  void ofAppGlutWindow::motion_cb(int x, int y) {
          static ofMouseEventArgs mouseEventArgs;
  
          if (nFrameCount > 0){
                  if(ofAppPtr){
                  ofAppPtr->mouseX = x;
                  ofAppPtr->mouseY = y;
                          ofAppPtr->mouseDragged(x,y,buttonInUse);
                  }
  
                  #ifdef OF_USING_POCO
                          mouseEventArgs.x = x;
                          mouseEventArgs.y = y;
                          mouseEventArgs.button = buttonInUse;
                          ofNotifyEvent( ofEvents.mouseDragged, mouseEventArgs );
                  #endif
          }
  
  }
  
  //------------------------------------------------------------
  void ofAppGlutWindow::passive_motion_cb(int x, int y) {
          static ofMouseEventArgs mouseEventArgs;
  
          if (nFrameCount > 0){
                  if(ofAppPtr){
                  ofAppPtr->mouseX = x;
                  ofAppPtr->mouseY = y;
                          ofAppPtr->mouseMoved(x,y);
                  }
  
                  #ifdef OF_USING_POCO
                          mouseEventArgs.x = x;
                          mouseEventArgs.y = y;
                          ofNotifyEvent( ofEvents.mouseMoved, mouseEventArgs );
                  #endif
          }
  }
  
  //------------------------------------------------------------
  void ofAppGlutWindow::idle_cb(void) {
          static ofEventArgs voidEventArgs;
  
          //        thanks to jorge for the fix:
          //        http://www.openframeworks.cc/forum/viewtopic.php?t=515&highlight=frame+rate
  
  	if (nFrameCount != 0 && bFrameRateSet == true){
                  diffMillis = ofGetElapsedTimeMillis() - prevMillis;
                  if (diffMillis > millisForFrame){
                          ; // we do nothing, we are already slower than target frame
                  } else {
                          int waitMillis = millisForFrame - diffMillis;
                          #ifdef TARGET_WIN32
                                  Sleep(waitMillis);         //windows sleep in milliseconds
                          #else
                                  usleep(waitMillis * 1000);   //mac sleep in microseconds - cooler :)
                          #endif
                  }
          }
          prevMillis = ofGetElapsedTimeMillis(); // you have to measure here
  
          if(ofAppPtr)
                  ofAppPtr->update();
  
                  #ifdef OF_USING_POCO
                  ofNotifyEvent( ofEvents.update, voidEventArgs);
                  #endif
  
          glutPostRedisplay();
  }
  
  //------------------------------------------------------------
  void ofAppGlutWindow::keyboard_cb(unsigned char key, int x, int y) {
          static ofKeyEventArgs keyEventArgs;
  
          if(ofAppPtr)
                  ofAppPtr->keyPressed(key);
  
          #ifdef OF_USING_POCO
                  keyEventArgs.key = key;
                  ofNotifyEvent( ofEvents.keyPressed, keyEventArgs );
          #endif
  
          if (key == OF_KEY_ESC){                                // "escape"
                  exitApp();
          }
  }
  
  //------------------------------------------------------------
  void ofAppGlutWindow::keyboard_up_cb(unsigned char key, int x, int y) {
          static ofKeyEventArgs keyEventArgs;
  
          if(ofAppPtr)
                  ofAppPtr->keyReleased(key);
  
          #ifdef OF_USING_POCO
                  keyEventArgs.key = key;
                  ofNotifyEvent( ofEvents.keyReleased, keyEventArgs );
          #endif
  }
  
  //------------------------------------------------------
  void ofAppGlutWindow::special_key_cb(int key, int x, int y) {
          static ofKeyEventArgs keyEventArgs;
  
          if(ofAppPtr)
                  ofAppPtr->keyPressed(key | OF_KEY_MODIFIER);
  
          #ifdef OF_USING_POCO
                  keyEventArgs.key = (key | OF_KEY_MODIFIER);
                  ofNotifyEvent( ofEvents.keyPressed, keyEventArgs );
          #endif
  }
  
  //------------------------------------------------------------
  void ofAppGlutWindow::special_key_up_cb(int key, int x, int y) {
          static ofKeyEventArgs keyEventArgs;
  
          if(ofAppPtr)
                  ofAppPtr->keyReleased(key | OF_KEY_MODIFIER);
  
          #ifdef OF_USING_POCO
                  keyEventArgs.key = (key | OF_KEY_MODIFIER);
                  ofNotifyEvent( ofEvents.keyReleased, keyEventArgs );
          #endif
  }
  
  //------------------------------------------------------------
  void ofAppGlutWindow::resize_cb(int w, int h) {
          static ofResizeEventArgs resizeEventArgs;
  
          if(ofAppPtr)
                  ofAppPtr->windowResized(w,h);
  
          #ifdef OF_USING_POCO
                  resizeEventArgs.width = w;
                  resizeEventArgs.height = h;
                  ofNotifyEvent( ofEvents.windowResized, resizeEventArgs );
          #endif
  }
  


(C) Æliens 04/09/2009

You may not copy or print any of this material without explicit permission of the author or the publisher. In case of other copyright issues, contact the author.