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 #ifndef Qt4Window_INCLUDE_ONCE 00033 #define Qt4Window_INCLUDE_ONCE 00034 00035 #include <vlQt4/link_config.hpp> 00036 #include <vlCore/VisualizationLibrary.hpp> 00037 #include <vlGraphics/OpenGLContext.hpp> 00038 #include <QtGui/QApplication> 00039 #include <QtGui/QMouseEvent> 00040 #include <QtGui/QWidget> 00041 #include <QtCore/QUrl> 00042 #include <QtCore/QTimer> 00043 #include <QtCore/QObject> 00044 #include <QtOpenGL/QGLWidget> 00045 #include <QtOpenGL/QGLFormat> 00046 00047 namespace vlQt4 00048 { 00049 //----------------------------------------------------------------------------- 00050 // Qt4Widget 00051 //----------------------------------------------------------------------------- 00053 class VLQT4_EXPORT Qt4Widget : public QGLWidget, public vl::OpenGLContext 00054 { 00055 Q_OBJECT 00056 00057 public: 00058 using vl::Object::setObjectName; 00059 using QObject::setObjectName; 00060 00061 Qt4Widget(QWidget* parent=NULL, const QGLWidget* shareWidget=NULL, Qt::WindowFlags f=0) 00062 :QGLWidget(parent,shareWidget,f), 00063 mRefresh(10) // 100 fps 00064 { 00065 setContinuousUpdate(true); 00066 setMouseTracking(true); 00067 setAutoBufferSwap(false); 00068 setAcceptDrops(true); 00069 // let Qt take care of object destruction. 00070 vl::OpenGLContext::setAutomaticDelete(false); 00071 } 00072 00073 ~Qt4Widget() 00074 { 00075 dispatchDestroyEvent(); 00076 } 00077 00078 void dragEnterEvent(QDragEnterEvent *ev) 00079 { 00080 if (ev->mimeData()->hasUrls()) 00081 ev->acceptProposedAction(); 00082 } 00083 00084 void dropEvent(QDropEvent* ev) 00085 { 00086 if ( ev->mimeData()->hasUrls() ) 00087 { 00088 std::vector<vl::String> files; 00089 QList<QUrl> list = ev->mimeData()->urls(); 00090 for(int i=0; i<list.size(); ++i) 00091 { 00092 if (list[i].path().isEmpty()) 00093 continue; 00094 #ifdef WIN32 00095 if (list[i].path()[0] == '/') 00096 files.push_back( list[i].path().toStdString().c_str()+1 ); 00097 else 00098 files.push_back( list[i].path().toStdString().c_str() ); 00099 #else 00100 files.push_back( list[i].path().toStdString().c_str() ); 00101 #endif 00102 } 00103 dispatchFileDroppedEvent(files); 00104 } 00105 } 00106 00107 bool initQt4Widget(const vl::String& title, const vl::OpenGLContextFormat& info, const QGLContext* shareContext=0, int x=0, int y=0, int width=640, int height=480) 00108 { 00109 // setFormat(fmt) is marked as deprecated so we use this other method 00110 QGLContext* glctx = new QGLContext(context()->format(), this); 00111 QGLFormat fmt = context()->format(); 00112 00113 // double buffer 00114 fmt.setDoubleBuffer( info.doubleBuffer() ); 00115 00116 // color buffer 00117 fmt.setRedBufferSize( info.rgbaBits().r() ); 00118 fmt.setGreenBufferSize( info.rgbaBits().g() ); 00119 fmt.setBlueBufferSize( info.rgbaBits().b() ); 00120 // setAlpha == true makes the create() function alway fail 00121 // even if the returned format has the requested alpha channel 00122 fmt.setAlphaBufferSize( info.rgbaBits().a() ); 00123 fmt.setAlpha( info.rgbaBits().a() != 0 ); 00124 00125 // accumulation buffer 00126 int accum = vl::max( info.accumRGBABits().r(), info.accumRGBABits().g() ); 00127 accum = vl::max( accum, info.accumRGBABits().b() ); 00128 accum = vl::max( accum, info.accumRGBABits().a() ); 00129 fmt.setAccumBufferSize( accum ); 00130 fmt.setAccum( accum != 0 ); 00131 00132 // multisampling 00133 if (info.multisample()) 00134 fmt.setSamples( info.multisampleSamples() ); 00135 fmt.setSampleBuffers( info.multisample() ); 00136 00137 // depth buffer 00138 fmt.setDepthBufferSize( info.depthBufferBits() ); 00139 fmt.setDepth( info.depthBufferBits() != 0 ); 00140 00141 // stencil buffer 00142 fmt.setStencilBufferSize( info.stencilBufferBits() ); 00143 fmt.setStencil( info.stencilBufferBits() != 0 ); 00144 00145 // stereo 00146 fmt.setStereo( info.stereo() ); 00147 00148 // swap interval / v-sync 00149 fmt.setSwapInterval( info.vSync() ? 1 : 0 ); 00150 00151 glctx->setFormat(fmt); 00152 // this function returns false when we request an alpha buffer 00153 // even if the created context seem to have the alpha buffer 00154 /*bool ok = */glctx->create(shareContext); 00155 setContext(glctx); 00156 00157 initGLContext(); 00158 00159 framebuffer()->setWidth(width); 00160 framebuffer()->setHeight(height); 00161 00162 #ifndef NDEBUG 00163 printf("--------------------------------------------\n"); 00164 printf("REQUESTED OpenGL Format:\n"); 00165 printf("--------------------------------------------\n"); 00166 printf("rgba = %d %d %d %d\n", fmt.redBufferSize(), fmt.greenBufferSize(), fmt.blueBufferSize(), fmt.alphaBufferSize() ); 00167 printf("double buffer = %d\n", (int)fmt.doubleBuffer() ); 00168 printf("depth buffer size = %d\n", fmt.depthBufferSize() ); 00169 printf("depth buffer = %d\n", fmt.depth() ); 00170 printf("stencil buffer size = %d\n", fmt.stencilBufferSize() ); 00171 printf("stencil buffer = %d\n", fmt.stencil() ); 00172 printf("accum buffer size %d\n", fmt.accumBufferSize() ); 00173 printf("accum buffer %d\n", fmt.accum() ); 00174 printf("stereo = %d\n", (int)fmt.stereo() ); 00175 printf("swap interval = %d\n", fmt.swapInterval() ); 00176 printf("multisample = %d\n", (int)fmt.sampleBuffers() ); 00177 printf("multisample samples = %d\n", (int)fmt.samples() ); 00178 00179 fmt = format(); 00180 00181 printf("--------------------------------------------\n"); 00182 printf("OBTAINED OpenGL Format:\n"); 00183 printf("--------------------------------------------\n"); 00184 printf("rgba = %d %d %d %d\n", fmt.redBufferSize(), fmt.greenBufferSize(), fmt.blueBufferSize(), fmt.alphaBufferSize() ); 00185 printf("double buffer = %d\n", (int)fmt.doubleBuffer() ); 00186 printf("depth buffer size = %d\n", fmt.depthBufferSize() ); 00187 printf("depth buffer = %d\n", fmt.depth() ); 00188 printf("stencil buffer size = %d\n", fmt.stencilBufferSize() ); 00189 printf("stencil buffer = %d\n", fmt.stencil() ); 00190 printf("accum buffer size %d\n", fmt.accumBufferSize() ); 00191 printf("accum buffer %d\n", fmt.accum() ); 00192 printf("stereo = %d\n", (int)fmt.stereo() ); 00193 printf("swap interval = %d\n", fmt.swapInterval() ); 00194 printf("multisample = %d\n", (int)fmt.sampleBuffers() ); 00195 printf("multisample samples = %d\n", (int)fmt.samples() ); 00196 printf("--------------------------------------------\n"); 00197 #endif 00198 00199 setWindowTitle(title); 00200 move(x,y); 00201 resize(width,height); 00202 00203 if (info.fullscreen()) 00204 setFullscreen(true); 00205 00206 return true; 00207 } 00208 00209 virtual void setContinuousUpdate(bool continuous) 00210 { 00211 mContinuousUpdate = continuous; 00212 if (continuous) 00213 { 00214 disconnect(&mUpdateTimer, SIGNAL(timeout()), this, SLOT(updateGL())); 00215 connect(&mUpdateTimer, SIGNAL(timeout()), this, SLOT(updateGL())); 00216 mUpdateTimer.setSingleShot(false); 00217 mUpdateTimer.setInterval(mRefresh); 00218 mUpdateTimer.start(0); 00219 } 00220 else 00221 { 00222 disconnect(&mUpdateTimer, SIGNAL(timeout()), this, SLOT(updateGL())); 00223 mUpdateTimer.stop(); 00224 } 00225 } 00226 00227 void setRefreshRate( int msec ) 00228 { 00229 mRefresh = msec; 00230 mUpdateTimer.setInterval(mRefresh); 00231 } 00232 00233 int refreshRate() 00234 { 00235 return mRefresh; 00236 } 00237 00238 void initializeGL() 00239 { 00240 // OpenGL extensions initialization 00241 dispatchInitEvent(); 00242 } 00243 00244 void resizeGL(int width, int height) 00245 { 00246 dispatchResizeEvent(width, height); 00247 } 00248 00249 void paintGL() 00250 { 00251 dispatchRunEvent(); 00252 } 00253 00254 void update() 00255 { 00256 QGLWidget::update(); 00257 // QGLWidget::updateGL(); 00258 } 00259 00260 virtual void setWindowTitle(const vl::String& title) 00261 { 00262 QGLWidget::setWindowTitle( QString::fromStdString(title.toStdString()) ); 00263 } 00264 00265 virtual bool setFullscreen(bool fullscreen) 00266 { 00267 mFullscreen = fullscreen; 00268 if (fullscreen) 00269 QGLWidget::setWindowState(QGLWidget::windowState() | Qt::WindowFullScreen); 00270 else 00271 QGLWidget::setWindowState(QGLWidget::windowState() & (~Qt::WindowFullScreen)); 00272 return true; 00273 } 00274 00275 virtual void quitApplication() 00276 { 00277 eraseAllEventListeners(); 00278 QApplication::quit(); 00279 } 00280 00281 virtual void show() 00282 { 00283 QGLWidget::show(); 00284 } 00285 00286 virtual void hide() 00287 { 00288 QGLWidget::hide(); 00289 } 00290 00291 virtual void setPosition(int x, int y) 00292 { 00293 QGLWidget::move(x,y); 00294 } 00295 00296 virtual vl::ivec2 position() const 00297 { 00298 return vl::ivec2(QGLWidget::pos().x(), QGLWidget::pos().y()); 00299 } 00300 00301 virtual void setSize(int w, int h) 00302 { 00303 // this already excludes the window's frame so it's ok for Visualization Library standards 00304 QGLWidget::resize(w,h); 00305 } 00306 00307 virtual vl::ivec2 size() const 00308 { 00309 // this already excludes the window's frame so it's ok for Visualization Library standards 00310 return vl::ivec2(QGLWidget::size().width(), QGLWidget::size().height()); 00311 } 00312 00313 void swapBuffers() 00314 { 00315 QGLWidget::swapBuffers(); 00316 } 00317 00318 void makeCurrent() 00319 { 00320 QGLWidget::makeCurrent(); 00321 } 00322 00323 void setMousePosition(int x, int y) 00324 { 00325 QCursor::setPos( mapToGlobal(QPoint(x,y)) ); 00326 } 00327 00328 void mouseMoveEvent(QMouseEvent* ev) 00329 { 00330 if (!mIgnoreNextMouseMoveEvent) 00331 dispatchMouseMoveEvent(ev->x(), ev->y()); 00332 mIgnoreNextMouseMoveEvent = false; 00333 } 00334 00335 void mousePressEvent(QMouseEvent* ev) 00336 { 00337 vl::EMouseButton bt = vl::NoButton; 00338 switch(ev->button()) 00339 { 00340 case Qt::LeftButton: bt = vl::LeftButton; break; 00341 case Qt::RightButton: bt = vl::RightButton; break; 00342 case Qt::MidButton: bt = vl::MiddleButton; break; 00343 default: 00344 bt = vl::UnknownButton; break; 00345 } 00346 dispatchMouseDownEvent(bt, ev->x(), ev->y()); 00347 } 00348 00349 void mouseReleaseEvent(QMouseEvent* ev) 00350 { 00351 vl::EMouseButton bt = vl::NoButton; 00352 switch(ev->button()) 00353 { 00354 case Qt::LeftButton: bt = vl::LeftButton; break; 00355 case Qt::RightButton: bt = vl::RightButton; break; 00356 case Qt::MidButton: bt = vl::MiddleButton; break; 00357 default: 00358 bt = vl::UnknownButton; break; 00359 } 00360 dispatchMouseUpEvent(bt, ev->x(), ev->y()); 00361 } 00362 00363 void wheelEvent(QWheelEvent* ev) 00364 { 00365 dispatchMouseWheelEvent(ev->delta() / 120); 00366 } 00367 00368 void keyPressEvent(QKeyEvent* ev) 00369 { 00370 unsigned short unicode_ch = 0; 00371 vl::EKey key = vl::Key_None; 00372 translateKeyEvent(ev, unicode_ch, key); 00373 dispatchKeyPressEvent(unicode_ch, key); 00374 } 00375 00376 void keyReleaseEvent(QKeyEvent* ev) 00377 { 00378 unsigned short unicode_ch = 0; 00379 vl::EKey key = vl::Key_None; 00380 translateKeyEvent(ev, unicode_ch, key); 00381 dispatchKeyReleaseEvent(unicode_ch, key); 00382 } 00383 00384 virtual void setMouseVisible(bool visible) 00385 { 00386 mMouseVisible=visible; 00387 if (visible) 00388 QGLWidget::setCursor(Qt::ArrowCursor); 00389 else 00390 QGLWidget::setCursor(Qt::BlankCursor); 00391 } 00392 00393 virtual void getFocus() 00394 { 00395 QGLWidget::setFocus(Qt::OtherFocusReason); 00396 } 00397 00398 protected: 00399 void translateKeyEvent(QKeyEvent* ev, unsigned short& unicode_out, vl::EKey& key_out); 00400 00401 protected: 00402 int mRefresh; 00403 QTimer mUpdateTimer; 00404 }; 00405 //----------------------------------------------------------------------------- 00406 } 00407 00408 #endif