Visualization Library v1.0.3A lightweight C++ OpenGL middleware for 2D/3D graphics |
[Download] [Tutorials] [All Classes] [Grouped Classes] |
00001 /**************************************************************************************/ 00002 /* */ 00003 /* Visualization Library */ 00004 /* http://visualizationlibrary.org */ 00005 /* */ 00006 /* Copyright (c) 2005-2010, Michele Bosi */ 00007 /* All rights reserved. */ 00008 /* */ 00009 /* Redistribution and use in source and binary forms, with or without modification, */ 00010 /* are permitted provided that the following conditions are met: */ 00011 /* */ 00012 /* - Redistributions of source code must retain the above copyright notice, this */ 00013 /* list of conditions and the following disclaimer. */ 00014 /* */ 00015 /* - Redistributions in binary form must reproduce the above copyright notice, this */ 00016 /* list of conditions and the following disclaimer in the documentation and/or */ 00017 /* other materials provided with the distribution. */ 00018 /* */ 00019 /* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND */ 00020 /* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED */ 00021 /* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE */ 00022 /* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR */ 00023 /* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES */ 00024 /* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; */ 00025 /* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON */ 00026 /* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ 00027 /* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS */ 00028 /* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ 00029 /* */ 00030 /**************************************************************************************/ 00031 00032 #include "vlSDL/SDLWindow.hpp" 00033 #include "vlGraphics/OpenGL.hpp" 00034 #include "vlGraphics/Applet.hpp" 00035 #include "vlCore/VisualizationLibrary.hpp" 00036 #include "vlCore/Log.hpp" 00037 #include "vlCore/Say.hpp" 00038 #include <algorithm> 00039 #include <SDL.h> 00040 #include <map> 00041 00042 #ifdef WIN32 00043 #include <SDL_syswm.h> 00044 #include <shellapi.h> 00045 #endif 00046 00047 using namespace vlSDL; 00048 using namespace vl; 00049 00050 namespace 00051 { 00052 SDLWindow* mSDLWindow = NULL; 00053 bool mUpdateFlag = true; 00054 00055 std::map<int, vl::EKey> key_translation_map; 00056 00057 int key_translation_vec[] = 00058 { 00059 SDLK_0, vl::Key_0, 00060 SDLK_1, vl::Key_1, 00061 SDLK_2, vl::Key_2, 00062 SDLK_3, vl::Key_3, 00063 SDLK_4, vl::Key_4, 00064 SDLK_5, vl::Key_5, 00065 SDLK_6, vl::Key_6, 00066 SDLK_7, vl::Key_7, 00067 SDLK_8, vl::Key_8, 00068 SDLK_9, vl::Key_9, 00069 00070 SDLK_a, vl::Key_A, 00071 SDLK_b, vl::Key_B, 00072 SDLK_c, vl::Key_C, 00073 SDLK_d, vl::Key_D, 00074 SDLK_e, vl::Key_E, 00075 SDLK_f, vl::Key_F, 00076 SDLK_g, vl::Key_G, 00077 SDLK_h, vl::Key_H, 00078 SDLK_i, vl::Key_I, 00079 SDLK_j, vl::Key_J, 00080 SDLK_k, vl::Key_K, 00081 SDLK_l, vl::Key_L, 00082 SDLK_m, vl::Key_M, 00083 SDLK_n, vl::Key_N, 00084 SDLK_o, vl::Key_O, 00085 SDLK_p, vl::Key_P, 00086 SDLK_q, vl::Key_Q, 00087 SDLK_r, vl::Key_R, 00088 SDLK_s, vl::Key_S, 00089 SDLK_t, vl::Key_T, 00090 SDLK_u, vl::Key_U, 00091 SDLK_v, vl::Key_V, 00092 SDLK_w, vl::Key_W, 00093 SDLK_x, vl::Key_X, 00094 SDLK_y, vl::Key_Y, 00095 SDLK_z, vl::Key_Z, 00096 00097 SDLK_RETURN, vl::Key_Return, 00098 SDLK_BACKSPACE, vl::Key_BackSpace, 00099 SDLK_SPACE, vl::Key_Space, 00100 SDLK_TAB, vl::Key_Tab, 00101 SDLK_CLEAR, vl::Key_Clear, 00102 SDLK_ESCAPE, vl::Key_Escape, 00103 SDLK_EXCLAIM, vl::Key_Exclam, 00104 SDLK_QUOTEDBL, vl::Key_QuoteDbl, 00105 SDLK_HASH, vl::Key_Hash, 00106 SDLK_DOLLAR, vl::Key_Dollar, 00107 SDLK_AMPERSAND, vl::Key_Ampersand, 00108 SDLK_QUOTE, vl::Key_Quote, 00109 SDLK_LEFTPAREN, vl::Key_LeftParen, 00110 SDLK_RIGHTPAREN, vl::Key_RightParen, 00111 SDLK_ASTERISK, vl::Key_Asterisk, 00112 SDLK_PLUS, vl::Key_Plus, 00113 SDLK_COMMA, vl::Key_Comma, 00114 SDLK_MINUS, vl::Key_Minus, 00115 SDLK_PERIOD, vl::Key_Period, 00116 SDLK_SLASH, vl::Key_Slash, 00117 SDLK_COLON, vl::Key_Colon, 00118 SDLK_SEMICOLON, vl::Key_Semicolon, 00119 SDLK_LESS, vl::Key_Less, 00120 SDLK_EQUALS, vl::Key_Equal, 00121 SDLK_GREATER, vl::Key_Greater, 00122 SDLK_QUESTION, vl::Key_Question, 00123 SDLK_AT, vl::Key_At, 00124 SDLK_LEFTBRACKET, vl::Key_LeftBracket, 00125 SDLK_BACKSLASH, vl::Key_BackSlash, 00126 SDLK_RIGHTBRACKET, vl::Key_RightBracket, 00127 SDLK_CARET, vl::Key_Caret, 00128 SDLK_UNDERSCORE, vl::Key_Underscore, 00129 SDLK_BACKQUOTE, vl::Key_QuoteLeft, 00130 00131 // non unicode 00132 00133 SDLK_LEFT, vl::Key_Left, 00134 SDLK_RIGHT, vl::Key_Right, 00135 SDLK_UP, vl::Key_Up, 00136 SDLK_DOWN, vl::Key_Down, 00137 SDLK_LCTRL, vl::Key_LeftCtrl, 00138 SDLK_RCTRL, vl::Key_RightCtrl, 00139 SDLK_LSHIFT, vl::Key_LeftShift, 00140 SDLK_RSHIFT, vl::Key_RightShift, 00141 SDLK_LALT, vl::Key_LeftAlt, 00142 SDLK_RALT, vl::Key_RightAlt, 00143 SDLK_INSERT, vl::Key_Insert, 00144 SDLK_DELETE, vl::Key_Delete, 00145 SDLK_HOME, vl::Key_Home, 00146 SDLK_END, vl::Key_End, 00147 SDLK_PAGEUP, vl::Key_PageUp, 00148 SDLK_PAGEDOWN, vl::Key_PageDown, 00149 SDLK_PAUSE, vl::Key_Pause, 00150 SDLK_PRINT, vl::Key_Print, 00151 SDLK_F1, vl::Key_F1, 00152 SDLK_F2, vl::Key_F2, 00153 SDLK_F3, vl::Key_F3, 00154 SDLK_F4, vl::Key_F4, 00155 SDLK_F5, vl::Key_F5, 00156 SDLK_F6, vl::Key_F6, 00157 SDLK_F7, vl::Key_F7, 00158 SDLK_F8, vl::Key_F8, 00159 SDLK_F9, vl::Key_F9, 00160 SDLK_F10, vl::Key_F10, 00161 SDLK_F11, vl::Key_F11, 00162 SDLK_F12, vl::Key_F12, 00163 0,0 00164 }; 00165 } 00166 //----------------------------------------------------------------------------- 00167 SDL_Surface* SDLWindow::mScreen = NULL; 00168 //----------------------------------------------------------------------------- 00169 SDLWindow::SDLWindow() 00170 { 00171 } 00172 //----------------------------------------------------------------------------- 00173 SDLWindow::~SDLWindow() 00174 { 00175 } 00176 //----------------------------------------------------------------------------- 00177 SDLWindow::SDLWindow( const vl::String& title, const vl::OpenGLContextFormat& info, int /*x*/, int /*y*/, int width, int height) 00178 { 00179 initSDLWindow(title, info, width, height); 00180 } 00181 //----------------------------------------------------------------------------- 00182 bool SDLWindow::initSDLWindow(const vl::String& title, const vl::OpenGLContextFormat& info, int x, int y, int width, int height) 00183 { 00184 if (mScreen || mSDLWindow) 00185 { 00186 vl::Log::error("SDL supports only one window at a time.\n"); 00187 VL_TRAP(); 00188 return false; 00189 } 00190 00191 framebuffer()->setWidth(width); 00192 framebuffer()->setHeight(height); 00193 mSDLWindow = this; 00194 00195 // init key translation map 00196 for(int i=0; key_translation_vec[i]; i+=2) 00197 key_translation_map[ key_translation_vec[i] ] = (vl::EKey)key_translation_vec[i+1]; 00198 00199 // SDL_VIDEO_WINDOW_POS 00200 00201 char win_pos[32] = {0}; 00202 sprintf ( win_pos, "SDL_VIDEO_WINDOW_POS=%d,%d", x, y ); 00203 SDL_putenv(win_pos); 00204 // setenv("SDL_VIDEO_CENTERED", "YES", 0); 00205 00206 // init SDL 00207 00208 if ( SDL_Init(SDL_INIT_VIDEO) < 0 ) 00209 { 00210 printf("Unable to init SDL: %s\n", SDL_GetError()); 00211 return false; 00212 } 00213 00214 SDL_GL_SetAttribute(SDL_GL_RED_SIZE, info.rgbaBits().r()); 00215 SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, info.rgbaBits().g()); 00216 SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, info.rgbaBits().b()); 00217 SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, info.rgbaBits().a()); 00218 00219 SDL_GL_SetAttribute(SDL_GL_ACCUM_RED_SIZE, info.accumRGBABits().r()); 00220 SDL_GL_SetAttribute(SDL_GL_ACCUM_GREEN_SIZE, info.accumRGBABits().g()); 00221 SDL_GL_SetAttribute(SDL_GL_ACCUM_BLUE_SIZE, info.accumRGBABits().b()); 00222 SDL_GL_SetAttribute(SDL_GL_ACCUM_ALPHA_SIZE, info.accumRGBABits().a()); 00223 00224 SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, info.depthBufferBits()); 00225 SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, info.stencilBufferBits()); 00226 00227 SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, info.doubleBuffer()?1:0); 00228 SDL_GL_SetAttribute(SDL_GL_STEREO, info.stereo()); 00229 SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, info.multisample()?1:0); 00230 if (info.multisample()) 00231 SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, info.multisampleSamples()); 00232 SDL_GL_SetAttribute(SDL_GL_SWAP_CONTROL, info.vSync()); 00233 00234 int bpp = SDL_GetVideoInfo()->vfmt->BitsPerPixel; 00235 Uint32 flags = SDL_OPENGL | (info.fullscreen() ? SDL_FULLSCREEN : 0); 00236 width = width !=0 ? width : SDL_GetVideoInfo()->current_w; 00237 height = height !=0 ? height : SDL_GetVideoInfo()->current_h; 00238 mScreen = SDL_SetVideoMode( width, height, bpp, flags ); 00239 if (mScreen == 0) 00240 { 00241 vl::Log::print( vl::Say("\n error: SDL_SetVideoMode(%n, %n, %n, %hn) failed: %s\n") << width << height << bpp << flags << SDL_GetError() ); 00242 exit(1); 00243 } 00244 00245 // window size problem 00246 00247 int viewport[4]; 00248 glGetIntegerv(GL_VIEWPORT, viewport); 00249 VL_CHECK(viewport[0] == 0); 00250 VL_CHECK(viewport[1] == 0); 00251 if (viewport[2] != mScreen->w || viewport[3] != mScreen->h) 00252 { 00253 vl::Log::print( vl::Say("\n warning: OpenGL reported %nx%n as video size but SDL says %nx%n\n") << viewport[2] << viewport[3] << mScreen->w << mScreen->h ); 00254 VL_TRAP() 00255 } 00256 00257 // OpenGL extensions initialization 00258 initGLContext(); 00259 00260 dispatchInitEvent(); 00261 dispatchResizeEvent(width, height); 00262 00263 #ifndef NDEBUG 00264 vl::Log::print( vl::Say("SDL screen: %n x %n x %n %s\n") << mScreen->w << mScreen->h << mScreen->format->BitsPerPixel << (info.fullscreen() ? "fullscreen" : "windowed") ); 00265 #endif 00266 00267 SDL_EnableUNICODE(1); 00268 00269 #ifdef WIN32 00270 // file drag & drop support 00271 SDL_EventState(SDL_SYSWMEVENT, SDL_ENABLE); 00272 static SDL_SysWMinfo pInfo; 00273 SDL_VERSION(&pInfo.version); 00274 SDL_GetWMInfo(&pInfo); 00275 HWND hWnd = pInfo.window; 00276 DWORD ExStyle = GetWindowLong(hWnd, GWL_EXSTYLE); 00277 ExStyle |= WS_EX_ACCEPTFILES; 00278 SetWindowLong(hWnd, GWL_EXSTYLE, ExStyle); 00279 // The SDL gurus decided not to give us this option... 00280 // DWORD Style = GetWindowLong(hWnd, GWL_STYLE); 00281 // Style |= WS_OVERLAPPEDWINDOW | WS_CLIPSIBLINGS | WS_CLIPCHILDREN; 00282 // SetWindowLong(hWnd, GWL_STYLE, Style); 00283 #endif 00284 00285 // mouse 00286 00287 SDL_ShowCursor(true); 00288 SDL_WM_GrabInput(SDL_GRAB_OFF); 00289 setWindowTitle(title); 00290 00291 // event cleaning 00292 00293 SDL_PumpEvents(); 00294 SDL_Event event; 00295 while ( SDL_PollEvent(&event) ) {} 00296 00297 return true; 00298 } 00299 //----------------------------------------------------------------------------- 00300 void SDLWindow::translateEvent( SDL_Event * ev ) 00301 { 00302 vl::EKey key = vl::Key_None; 00303 unsigned short unicode = 0; 00304 if ( ev && (ev->type == SDL_KEYDOWN || ev->type == SDL_KEYUP) ) 00305 { 00306 if( key_translation_map.find(ev->key.keysym.sym) != key_translation_map.end() ) 00307 key = key_translation_map[ ev->key.keysym.sym ]; 00308 else 00309 key = vl::Key_Unknown; 00310 00311 unicode = ev->key.keysym.unicode; 00312 } 00313 00315 //bool update = mUpdateFlag; 00317 //mUpdateFlag = continuousUpdate(); 00318 00319 //if (update) 00320 // dispatchRunEvent(); 00321 00322 if (ev->type == SDL_KEYDOWN) 00323 { 00324 switch(key) 00325 { 00326 default: break; 00327 00328 case vl::Key_LeftCtrl: 00329 case vl::Key_RightCtrl: 00330 dispatchKeyPressEvent(unicode, vl::Key_Ctrl); 00331 break; 00332 00333 case vl::Key_LeftShift: 00334 case vl::Key_RightShift: 00335 dispatchKeyPressEvent(unicode, vl::Key_Shift); 00336 break; 00337 00338 case vl::Key_LeftAlt: 00339 case vl::Key_RightAlt: 00340 dispatchKeyPressEvent(unicode, vl::Key_Alt); 00341 break; 00342 } 00343 dispatchKeyPressEvent(unicode, key); 00344 } 00345 else 00346 if (ev->type == SDL_KEYUP) 00347 { 00348 switch(key) 00349 { 00350 default: break; 00351 00352 case vl::Key_LeftCtrl: 00353 case vl::Key_RightCtrl: 00354 dispatchKeyReleaseEvent(unicode, vl::Key_Ctrl); 00355 break; 00356 00357 case vl::Key_LeftShift: 00358 case vl::Key_RightShift: 00359 dispatchKeyReleaseEvent(unicode, vl::Key_Shift); 00360 break; 00361 00362 case vl::Key_LeftAlt: 00363 case vl::Key_RightAlt: 00364 dispatchKeyReleaseEvent(unicode, vl::Key_Alt); 00365 break; 00366 } 00367 dispatchKeyReleaseEvent(unicode, key); 00368 } 00369 else 00370 if (ev->type == SDL_MOUSEBUTTONDOWN) 00371 { 00372 if (ev->button.button == SDL_BUTTON_WHEELUP) 00373 dispatchMouseWheelEvent(1); 00374 else 00375 if (ev->button.button == SDL_BUTTON_WHEELDOWN) 00376 dispatchMouseWheelEvent(-1); 00377 else 00378 if (ev->button.button == SDL_BUTTON_LEFT) 00379 dispatchMouseDownEvent(vl::LeftButton, ev->button.x, ev->button.y); 00380 else 00381 if (ev->button.button == SDL_BUTTON_RIGHT) 00382 dispatchMouseDownEvent(vl::RightButton, ev->button.x, ev->button.y); 00383 else 00384 if (ev->button.button == SDL_BUTTON_MIDDLE) 00385 dispatchMouseDownEvent(vl::MiddleButton, ev->button.x, ev->button.y); 00386 } 00387 else 00388 if (ev->type == SDL_MOUSEBUTTONUP) 00389 { 00390 // We only need SDL_MOUSEBUTTONDOWN's wheel messages 00391 /*if (ev->button.button == SDL_BUTTON_WHEELUP) 00392 mouseWheelEvent(1); 00393 else 00394 if (ev->button.button == SDL_BUTTON_WHEELDOWN) 00395 mouseWheelEvent(-1); 00396 else*/ 00397 if (ev->button.button == SDL_BUTTON_LEFT) 00398 dispatchMouseUpEvent(vl::LeftButton, ev->button.x, ev->button.y); 00399 else 00400 if (ev->button.button == SDL_BUTTON_RIGHT) 00401 dispatchMouseUpEvent(vl::RightButton, ev->button.x, ev->button.y); 00402 else 00403 if (ev->button.button == SDL_BUTTON_MIDDLE) 00404 dispatchMouseUpEvent(vl::MiddleButton, ev->button.x, ev->button.y); 00405 } 00406 else 00407 if (ev->type == SDL_MOUSEMOTION) 00408 { 00409 dispatchMouseMoveEvent(ev->motion.x, ev->motion.y); 00410 } 00411 else 00412 if (ev->type == SDL_VIDEORESIZE) 00413 { 00414 // SDL is not able to resize OpenGL contexts 00415 // resizeEvent(ev->resize.w, ev->resize.h); 00416 } 00417 else 00418 if( ev->type == SDL_SYSWMEVENT ) 00419 { 00420 #ifdef WIN32 00421 if (ev->syswm.msg->msg == WM_DROPFILES) 00422 { 00423 HDROP hDrop = (HDROP) ev->syswm.msg->wParam; 00424 int count = DragQueryFile(hDrop, 0xFFFFFFFF, 0, 0); 00425 const int char_count = 1024; 00426 std::vector<String> files; 00427 for(int i=0; i<count; ++i) 00428 { 00429 wchar_t file_path[char_count]; 00430 memset(file_path, 0, char_count); 00431 DragQueryFile(hDrop,i,file_path,char_count); 00432 files.push_back(file_path); 00433 } 00434 dispatchFileDroppedEvent(files); 00435 } 00436 #endif 00437 } 00438 else 00439 if (ev->type == SDL_QUIT) 00440 { 00441 quitApplication(); 00442 } 00443 } 00444 //----------------------------------------------------------------------------- 00445 void vlSDL::messageLoop() 00446 { 00447 SDL_Event ev; 00448 while(mSDLWindow) 00449 { 00450 if ( SDL_PollEvent(&ev) ) 00451 mSDLWindow->translateEvent(&ev); 00452 else 00453 { 00454 if ( mUpdateFlag || mSDLWindow->continuousUpdate() ) 00455 { 00456 mSDLWindow->dispatchRunEvent(); 00457 mUpdateFlag = false; 00458 } 00459 else 00460 { 00461 // rest for 10ms if there are not events to process, and we don't need to repaint 00462 SDL_Delay(10); 00463 } 00464 } 00465 } 00466 00467 SDL_Quit(); 00468 } 00469 //----------------------------------------------------------------------------- 00470 void SDLWindow::quitApplication() 00471 { 00472 dispatchDestroyEvent(); 00473 mSDLWindow = NULL; 00474 } 00475 //----------------------------------------------------------------------------- 00476 void SDLWindow::update() 00477 { 00478 mUpdateFlag = true; 00479 } 00480 //----------------------------------------------------------------------------- 00481 void SDLWindow::setWindowTitle(const vl::String& title) 00482 { 00483 SDL_WM_SetCaption(title.toStdString().c_str(), title.toStdString().c_str()); 00484 } 00485 //----------------------------------------------------------------------------- 00486 void SDLWindow::swapBuffers() 00487 { 00488 SDL_GL_SwapBuffers(); 00489 } 00490 //----------------------------------------------------------------------------- 00491 void SDLWindow::setPosition(int x, int y) 00492 { 00493 #ifdef WIN32 00494 static SDL_SysWMinfo pInfo; 00495 SDL_VERSION(&pInfo.version); 00496 SDL_GetWMInfo(&pInfo); 00497 HWND hWnd = pInfo.window; 00498 00499 SetWindowPos(hWnd, 0, x, y, 0, 0, SWP_NOSIZE ); 00500 #endif 00501 } 00502 //-----------------------------------------------------------------------------