View3DInventor.cpp

Go to the documentation of this file.
00001 /***************************************************************************
00002  *   Copyright (c) 2004 Jürgen Riegel <juergen.riegel@web.de>              *
00003  *                                                                         *
00004  *   This file is part of the FreeCAD CAx development system.              *
00005  *                                                                         *
00006  *   This library is free software; you can redistribute it and/or         *
00007  *   modify it under the terms of the GNU Library General Public           *
00008  *   License as published by the Free Software Foundation; either          *
00009  *   version 2 of the License, or (at your option) any later version.      *
00010  *                                                                         *
00011  *   This library  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 Library General Public License for more details.                  *
00015  *                                                                         *
00016  *   You should have received a copy of the GNU Library General Public     *
00017  *   License along with this library; see the file COPYING.LIB. If not,    *
00018  *   write to the Free Software Foundation, Inc., 59 Temple Place,         *
00019  *   Suite 330, Boston, MA  02111-1307, USA                                *
00020  *                                                                         *
00021  ***************************************************************************/
00022 
00023 
00024 #include "PreCompiled.h"
00025 
00026 #ifndef _PreComp_
00027 # include <QAction>
00028 # include <QApplication>
00029 # include <QFileInfo>
00030 # include <QKeyEvent>
00031 # include <QEvent>
00032 # include <QDropEvent>
00033 # include <QDragEnterEvent>
00034 # include <QFileDialog>
00035 # include <QPainter>
00036 # include <QPrinter>
00037 # include <QPrintDialog>
00038 # include <QPrintPreviewDialog>
00039 # include <QStackedWidget>
00040 # include <QTimer>
00041 # include <QUrl>
00042 # include <Inventor/actions/SoWriteAction.h>
00043 # include <Inventor/actions/SoGetPrimitiveCountAction.h>
00044 # include <Inventor/nodes/SoDirectionalLight.h>
00045 # include <Inventor/nodes/SoMaterial.h>
00046 # include <Inventor/nodes/SoOrthographicCamera.h>
00047 # include <Inventor/nodes/SoPerspectiveCamera.h>
00048 # include <Inventor/nodes/SoSeparator.h>
00049 # include <Inventor/nodes/SoShapeHints.h>
00050 # include <Inventor/events/SoEvent.h>
00051 # include <Inventor/fields/SoSFString.h>
00052 # include <Inventor/fields/SoSFColor.h>
00053 #endif
00054 # include <QStackedWidget>
00055 
00056 #include <Base/Exception.h>
00057 #include <Base/Console.h>
00058 #include <Base/FileInfo.h>
00059 
00060 #include <App/DocumentObject.h>
00061 
00062 #include "View3DInventor.h"
00063 #include "View3DInventorViewer.h"
00064 #include "Document.h"
00065 #include "FileDialog.h"
00066 #include "Application.h"
00067 #include "MainWindow.h"
00068 #include "MenuManager.h"
00069 #include "WaitCursor.h"
00070 #include "SoFCVectorizeSVGAction.h"
00071 
00072 // build in Inventor
00073 #include "Inventor/Qt/viewers/SoQtExaminerViewer.h"
00074 #include <Inventor/nodes/SoPerspectiveCamera.h>
00075 #include <Inventor/nodes/SoOrthographicCamera.h>
00076 
00077 #include "View3DInventorExamples.h"
00078 #include "SoFCSelectionAction.h"
00079 #include "View3DPy.h"
00080 #include "SoFCDB.h"
00081 #include "NavigationStyle.h"
00082 
00083 #include <locale>
00084 
00085 using namespace Gui;
00086 
00087 void GLOverlayWidget::paintEvent(QPaintEvent* ev)
00088 {
00089     QPainter paint(this);
00090     paint.drawImage(0,0,image);
00091     paint.end();
00092 }
00093 
00094 /* TRANSLATOR Gui::View3DInventor */
00095 
00096 TYPESYSTEM_SOURCE_ABSTRACT(Gui::View3DInventor,Gui::BaseView);
00097 
00098 View3DInventor::View3DInventor(Gui::Document* pcDocument, QWidget* parent, Qt::WFlags wflags)
00099     : MDIView(pcDocument, parent, wflags), _viewerPy(0)
00100 {
00101     stack = new QStackedWidget(this);
00102     // important for highlighting 
00103     setMouseTracking(true);
00104     // accept drops on the window, get handled in dropEvent, dragEnterEvent   
00105     setAcceptDrops(true);
00106   
00107     // attach parameter Observer
00108     hGrp = App::GetApplication().GetParameterGroupByPath("User parameter:BaseApp/Preferences/View");
00109     hGrp->Attach(this);
00110 
00111     // create the inventor widget and set the defaults
00112 #if !defined (NO_USE_QT_MDI_AREA)
00113     _viewer = new View3DInventorViewer(0);
00114     stack->addWidget(_viewer->getWidget());
00115     setCentralWidget(stack);
00116 #else
00117     _viewer = new View3DInventorViewer(this);
00118 #endif
00119     // apply the user settings
00120     OnChange(*hGrp,"EyeDistance");
00121     OnChange(*hGrp,"CornerCoordSystem");
00122     OnChange(*hGrp,"UseAutoRotation");
00123     OnChange(*hGrp,"Gradient");
00124     OnChange(*hGrp,"BackgroundColor");
00125     OnChange(*hGrp,"BackgroundColor2");
00126     OnChange(*hGrp,"BackgroundColor3");
00127     OnChange(*hGrp,"BackgroundColor4");
00128     OnChange(*hGrp,"UseBackgroundColorMid");
00129     OnChange(*hGrp,"UseAntialiasing");
00130     OnChange(*hGrp,"ShowFPS");
00131     OnChange(*hGrp,"Orthographic");
00132     OnChange(*hGrp,"HeadlightColor");
00133     OnChange(*hGrp,"HeadlightDirection");
00134     OnChange(*hGrp,"HeadlightIntensity");
00135     OnChange(*hGrp,"EnableBacklight");
00136     OnChange(*hGrp,"BacklightColor");
00137     OnChange(*hGrp,"BacklightDirection");
00138     OnChange(*hGrp,"BacklightIntensity");
00139     OnChange(*hGrp,"NavigationStyle");
00140     OnChange(*hGrp,"OrbitStyle");
00141 
00142     stopSpinTimer = new QTimer(this);
00143     connect(stopSpinTimer, SIGNAL(timeout()), this, SLOT(stopAnimating()));
00144 }
00145 
00146 View3DInventor::~View3DInventor()
00147 {
00148     hGrp->Detach(this);
00149 
00150     //If we destroy this viewer by calling 'delete' directly the focus proxy widget which is defined 
00151     //by a widget in SoQtViewer isn't resetted. This widget becomes to a dangling pointer and makes
00152     //the application crash. (Probably it's better to destroy this viewer by calling close().)
00153     //See also Gui::Document::~Document().
00154     QWidget* foc = qApp->focusWidget();
00155     if (foc) {
00156         QWidget* par = foc->parentWidget();
00157         while (par) {
00158             if (par == this) {
00159                 foc->setFocusProxy(0);
00160                 foc->clearFocus();
00161                 break;
00162             }
00163             par = par->parentWidget();
00164         }
00165     }
00166 
00167     if (_viewerPy) {
00168         static_cast<View3DInventorPy*>(_viewerPy)->_view = 0;
00169         Py_DECREF(_viewerPy);
00170     }
00171 
00172     // here is from time to time trouble!!!
00173     delete _viewer;
00174 }
00175 
00176 PyObject *View3DInventor::getPyObject(void)
00177 {
00178     if (!_viewerPy)
00179         _viewerPy = new View3DInventorPy(this);
00180 
00181     Py_INCREF(_viewerPy);
00182     return _viewerPy;
00183 }
00184 
00185 void View3DInventor::OnChange(ParameterGrp::SubjectType &rCaller,ParameterGrp::MessageType Reason)
00186 {
00187     const ParameterGrp& rGrp = static_cast<ParameterGrp&>(rCaller);
00188     if (strcmp(Reason,"HeadlightColor") == 0) {
00189         unsigned long headlight = rGrp.GetUnsigned("HeadlightColor",ULONG_MAX); // default color (white)
00190         float transparency;
00191         SbColor headlightColor;
00192         headlightColor.setPackedValue((uint32_t)headlight, transparency);
00193         _viewer->getHeadlight()->color.setValue(headlightColor);
00194     }
00195     else if (strcmp(Reason,"HeadlightDirection") == 0) {
00196         std::string pos = rGrp.GetASCII("HeadlightDirection");
00197         QString flt = QString::fromAscii("([-+]?[0-9]+\\.?[0-9]+)");
00198         QRegExp rx(QString::fromAscii("^\\(%1,%1,%1\\)$").arg(flt));
00199         if (rx.indexIn(QLatin1String(pos.c_str())) > -1) {
00200             float x = rx.cap(1).toFloat();
00201             float y = rx.cap(2).toFloat();
00202             float z = rx.cap(3).toFloat();
00203             _viewer->getHeadlight()->direction.setValue(x,y,z);
00204         }
00205     }
00206     else if (strcmp(Reason,"HeadlightIntensity") == 0) {
00207         long value = rGrp.GetInt("HeadlightIntensity", 100);
00208         _viewer->getHeadlight()->intensity.setValue((float)value/100.0f);
00209     }
00210     else if (strcmp(Reason,"EnableBacklight") == 0) {
00211         _viewer->setBacklight(rGrp.GetBool("EnableBacklight", false));
00212     }
00213     else if (strcmp(Reason,"BacklightColor") == 0) {
00214         unsigned long backlight = rGrp.GetUnsigned("BacklightColor",ULONG_MAX); // default color (white)
00215         float transparency;
00216         SbColor backlightColor;
00217         backlightColor.setPackedValue((uint32_t)backlight, transparency);
00218         _viewer->getBacklight()->color.setValue(backlightColor);
00219     }
00220     else if (strcmp(Reason,"BacklightDirection") == 0) {
00221         std::string pos = rGrp.GetASCII("BacklightDirection");
00222         QString flt = QString::fromAscii("([-+]?[0-9]+\\.?[0-9]+)");
00223         QRegExp rx(QString::fromAscii("^\\(%1,%1,%1\\)$").arg(flt));
00224         if (rx.indexIn(QLatin1String(pos.c_str())) > -1) {
00225             float x = rx.cap(1).toFloat();
00226             float y = rx.cap(2).toFloat();
00227             float z = rx.cap(3).toFloat();
00228             _viewer->getBacklight()->direction.setValue(x,y,z);
00229         }
00230     }
00231     else if (strcmp(Reason,"BacklightIntensity") == 0) {
00232         long value = rGrp.GetInt("BacklightIntensity", 100);
00233         _viewer->getBacklight()->intensity.setValue((float)value/100.0f);
00234     }
00235     else if (strcmp(Reason,"EnablePreselection") == 0) {
00236         const ParameterGrp& rclGrp = ((ParameterGrp&)rCaller);
00237         SoFCEnableHighlightAction cAct(rclGrp.GetBool("EnablePreselection", true));
00238         cAct.apply(_viewer->getSceneGraph());
00239     }
00240     else if (strcmp(Reason,"EnableSelection") == 0) {
00241         const ParameterGrp& rclGrp = ((ParameterGrp&)rCaller);
00242         SoFCEnableSelectionAction cAct(rclGrp.GetBool("EnableSelection", true));
00243         cAct.apply(_viewer->getSceneGraph());
00244     }
00245     else if (strcmp(Reason,"HighlightColor") == 0) {
00246         float transparency;
00247         SbColor highlightColor(0.8f, 0.1f, 0.1f);
00248         unsigned long highlight = (unsigned long)(highlightColor.getPackedValue());
00249         highlight = rGrp.GetUnsigned("HighlightColor", highlight);
00250         highlightColor.setPackedValue((uint32_t)highlight, transparency);
00251         SoSFColor col; col.setValue(highlightColor);
00252         SoFCHighlightColorAction cAct(col);
00253         cAct.apply(_viewer->getSceneGraph());
00254     }
00255     else if (strcmp(Reason,"SelectionColor") == 0) {
00256         float transparency;
00257         SbColor selectionColor(0.1f, 0.8f, 0.1f);
00258         unsigned long selection = (unsigned long)(selectionColor.getPackedValue());
00259         selection = rGrp.GetUnsigned("SelectionColor", selection);
00260         selectionColor.setPackedValue((uint32_t)selection, transparency);
00261         SoSFColor col; col.setValue(selectionColor);
00262         SoFCSelectionColorAction cAct(col);
00263         cAct.apply(_viewer->getSceneGraph());
00264     }
00265     else if (strcmp(Reason,"NavigationStyle") == 0) {
00266         // check whether the simple or the full mouse model is used
00267         std::string model = rGrp.GetASCII("NavigationStyle",CADNavigationStyle::getClassTypeId().getName());
00268         Base::Type type = Base::Type::fromName(model.c_str());
00269         _viewer->setNavigationType(type);
00270     }
00271     else if (strcmp(Reason,"OrbitStyle") == 0) {
00272         int style = rGrp.GetInt("OrbitStyle",1);
00273         _viewer->navigationStyle()->setOrbitStyle(NavigationStyle::OrbitStyle(style));
00274     }
00275     else if (strcmp(Reason,"InvertZoom") == 0) {
00276         bool on = rGrp.GetBool("InvertZoom", false);
00277         _viewer->navigationStyle()->setZoomInverted(on);
00278     }
00279     else if (strcmp(Reason,"EyeDistance") == 0) {
00280         _viewer->setStereoOffset(rGrp.GetFloat("EyeDistance",65.0));
00281     }
00282     else if (strcmp(Reason,"CornerCoordSystem") == 0) {
00283         _viewer->setFeedbackVisibility(rGrp.GetBool("CornerCoordSystem",true));
00284     }
00285     else if (strcmp(Reason,"UseAutoRotation") == 0) {
00286         _viewer->setAnimationEnabled(rGrp.GetBool("UseAutoRotation",true));
00287     }
00288     else if (strcmp(Reason,"Gradient") == 0) {
00289         _viewer->setGradientBackgroud((rGrp.GetBool("Gradient",true)));
00290     }
00291     else if (strcmp(Reason,"UseAntialiasing") == 0) {
00292         _viewer->getGLRenderAction()->setSmoothing(rGrp.GetBool("UseAntialiasing",false));
00293     }
00294     else if (strcmp(Reason,"ShowFPS") == 0) {
00295         _viewer->setEnabledFPSCounter(rGrp.GetBool("ShowFPS",false));
00296     }
00297     else if (strcmp(Reason,"Orthographic") == 0) {
00298         // check whether a perspective or orthogrphic camera should be set
00299         if (rGrp.GetBool("Orthographic", true))
00300             _viewer->setCameraType(SoOrthographicCamera::getClassTypeId());
00301         else
00302             _viewer->setCameraType(SoPerspectiveCamera::getClassTypeId());
00303     }
00304     else {
00305         unsigned long col1 = rGrp.GetUnsigned("BackgroundColor",3940932863UL);
00306         unsigned long col2 = rGrp.GetUnsigned("BackgroundColor2",859006463UL); // default color (dark blue)
00307         unsigned long col3 = rGrp.GetUnsigned("BackgroundColor3",2880160255UL); // default color (blue/grey)
00308         unsigned long col4 = rGrp.GetUnsigned("BackgroundColor4",1869583359UL); // default color (blue/grey)
00309         float r1,g1,b1,r2,g2,b2,r3,g3,b3,r4,g4,b4;
00310         r1 = ((col1 >> 24) & 0xff) / 255.0; g1 = ((col1 >> 16) & 0xff) / 255.0; b1 = ((col1 >> 8) & 0xff) / 255.0;
00311         r2 = ((col2 >> 24) & 0xff) / 255.0; g2 = ((col2 >> 16) & 0xff) / 255.0; b2 = ((col2 >> 8) & 0xff) / 255.0;
00312         r3 = ((col3 >> 24) & 0xff) / 255.0; g3 = ((col3 >> 16) & 0xff) / 255.0; b3 = ((col3 >> 8) & 0xff) / 255.0;
00313         r4 = ((col4 >> 24) & 0xff) / 255.0; g4 = ((col4 >> 16) & 0xff) / 255.0; b4 = ((col4 >> 8) & 0xff) / 255.0;
00314         _viewer->setBackgroundColor(SbColor(r1, g1, b1));
00315         if (rGrp.GetBool("UseBackgroundColorMid",false) == false)
00316             _viewer->setGradientBackgroudColor(SbColor(r2, g2, b2), SbColor(r3, g3, b3));
00317         else
00318             _viewer->setGradientBackgroudColor(SbColor(r2, g2, b2), SbColor(r3, g3, b3), SbColor(r4, g4, b4));
00319     }
00320 }
00321 
00322 void View3DInventor::onRename(Gui::Document *pDoc)
00323 {
00324     SoSFString name;
00325     name.setValue(pDoc->getDocument()->getName());
00326     SoFCDocumentAction cAct(name);
00327     cAct.apply(_viewer->getSceneGraph());
00328 }
00329 
00330 void View3DInventor::onUpdate(void)
00331 {
00332 #ifdef FC_LOGUPDATECHAIN
00333     Base::Console().Log("Acti: Gui::View3DInventor::onUpdate()");
00334 #endif
00335     update();  
00336     _viewer->render();
00337 }
00338 
00339 void View3DInventor::viewAll()
00340 {
00341     _viewer->viewAll();
00342 }
00343 
00344 const char *View3DInventor::getName(void) const
00345 {
00346     return "View3DInventor";
00347 }
00348 
00349 void View3DInventor::print()
00350 {
00351     QPrinter printer(QPrinter::HighResolution);
00352     printer.setFullPage(true);
00353     QPrintDialog dlg(&printer, this);
00354     if (dlg.exec() == QDialog::Accepted) {
00355         Gui::WaitCursor wc;
00356         print(&printer);
00357     }
00358 }
00359 
00360 void View3DInventor::printPdf()
00361 {
00362     QString filename = FileDialog::getSaveFileName(this, tr("Export PDF"), QString(), tr("PDF file (*.pdf)"));
00363     if (!filename.isEmpty()) {
00364         Gui::WaitCursor wc;
00365         QPrinter printer(QPrinter::HighResolution);
00366         printer.setOutputFormat(QPrinter::PdfFormat);
00367         printer.setOutputFileName(filename);
00368         print(&printer);
00369     }
00370 }
00371 
00372 void View3DInventor::printPreview()
00373 {
00374     QPrinter printer(QPrinter::HighResolution);
00375     printer.setFullPage(true);
00376     //printer.setPageSize(QPrinter::A3);
00377     printer.setOrientation(QPrinter::Landscape);
00378 
00379     QPrintPreviewDialog dlg(&printer, this);
00380     connect(&dlg, SIGNAL(paintRequested (QPrinter *)),
00381             this, SLOT(print(QPrinter *)));
00382     dlg.exec();
00383 }
00384 
00385 void View3DInventor::print(QPrinter* printer)
00386 {
00387     // The SVG output needs to be improved
00388 #if 0
00389     SoFCVectorizeSVGAction action;
00390     SoSVGVectorOutput* out = action.getSVGOutput();
00391     std::string tmp = Base::FileInfo::getTempFileName();
00392     if (!out || !out->openFile(tmp.c_str()))
00393         return;
00394     SoVectorizeAction::PageSize ps;
00395     switch (printer->pageSize()) {
00396     case QPrinter::A0:
00397         ps = SoVectorizeAction::A0;
00398         break;
00399     case QPrinter::A1:
00400         ps = SoVectorizeAction::A1;
00401         break;
00402     case QPrinter::A2:
00403         ps = SoVectorizeAction::A2;
00404         break;
00405     case QPrinter::A3:
00406         ps = SoVectorizeAction::A3;
00407         break;
00408     case QPrinter::A4:
00409         ps = SoVectorizeAction::A4;
00410         break;
00411     case QPrinter::A5:
00412         ps = SoVectorizeAction::A5;
00413         break;
00414     case QPrinter::A6:
00415         ps = SoVectorizeAction::A6;
00416         break;
00417     case QPrinter::A7:
00418         ps = SoVectorizeAction::A7;
00419         break;
00420     case QPrinter::A8:
00421         ps = SoVectorizeAction::A8;
00422         break;
00423     case QPrinter::A9:
00424         ps = SoVectorizeAction::A9;
00425         break;
00426     default:
00427         ps = SoVectorizeAction::A4;
00428         break;
00429     }
00430     _viewer->saveGraphic(ps,View3DInventorViewer::White,&action);
00431     out->closeFile();
00432     QSvgRenderer svg;
00433     if (svg.load(QString::fromUtf8(tmp.c_str()))) {
00434         QPainter p(printer);
00435         svg.render(&p);
00436         p.end();
00437     }
00438 #else
00439     QImage img;
00440     QPainter p(printer);
00441     QRect rect = printer->pageRect();
00442     _viewer->savePicture(rect.width(), rect.height(), View3DInventorViewer::White, img);
00443     p.drawImage(0,0,img);
00444     p.end();
00445 #endif
00446 }
00447 
00448 // **********************************************************************************
00449 
00450 bool View3DInventor::onMsg(const char* pMsg, const char** ppReturn)
00451 {
00452     if (strcmp("ViewFit",pMsg) == 0) {
00453         _viewer->viewAll();
00454         return true;
00455     }
00456     else if(strcmp("ViewSelection",pMsg) == 0) {
00457         _viewer->viewSelection();
00458         return true;
00459     // comment out on older Inventor
00460 #if SOQT_MAJOR_VERSION > 1 || (SOQT_MAJOR_VERSION == 1 && SOQT_MINOR_VERSION >= 2)
00461     }
00462     else if(strcmp("SetStereoRedGreen",pMsg) == 0 ) {
00463         _viewer->setStereoType(SoQtViewer::STEREO_ANAGLYPH);
00464         return true;
00465     }
00466     else if(strcmp("SetStereoQuadBuff",pMsg) == 0 ) {
00467         _viewer->setStereoType(SoQtViewer::STEREO_QUADBUFFER );
00468         return true;
00469     }
00470     else if(strcmp("SetStereoInterleavedRows",pMsg) == 0 ) {
00471         _viewer->setStereoType(SoQtViewer::STEREO_INTERLEAVED_ROWS );
00472         return true;
00473     }
00474     else if(strcmp("SetStereoInterleavedColumns",pMsg) == 0 ) {
00475         _viewer->setStereoType(SoQtViewer::STEREO_INTERLEAVED_COLUMNS  );
00476         return true;
00477     }
00478     else if(strcmp("SetStereoOff",pMsg) == 0 ) {
00479         _viewer->setStereoType(SoQtViewer::STEREO_NONE );
00480         return true;
00481 #else
00482     }
00483     else if(strcmp("SetStereoRedGreen",pMsg) == 0 ) {
00484         Base::Console().Warning("Use SoQt 1.2.x or later!\n");
00485         return true;
00486     }
00487     else if(strcmp("SetStereoQuadBuff",pMsg) == 0 ) {
00488         Base::Console().Warning("Use SoQt 1.2.x or later!\n");
00489         return true;
00490     }
00491     else if(strcmp("SetStereoInterleavedRows",pMsg) == 0 ) {
00492         Base::Console().Warning("Use SoQt 1.2.x or later!\n");
00493         return true;
00494     }
00495     else if(strcmp("SetStereoInterleavedColumns",pMsg) == 0 ) {
00496         Base::Console().Warning("Use SoQt 1.2.x or later!\n");
00497         return true;
00498     }
00499     else if(strcmp("SetStereoOff",pMsg) == 0 ) {
00500         Base::Console().Warning("Use SoQt 1.2.x or later!\n");
00501         return true;
00502 #endif
00503     }
00504     else if(strcmp("Example1",pMsg) == 0 ) {
00505         SoSeparator * root = new SoSeparator;
00506         Texture3D(root);
00507         _viewer->setSceneGraph(root);
00508         return true;
00509     }
00510     else if(strcmp("Example2",pMsg) == 0 ) {
00511         SoSeparator * root = new SoSeparator;
00512         LightManip(root);
00513         _viewer->setSceneGraph(root);
00514         return true;
00515     }
00516     else if(strcmp("Example3",pMsg) == 0 ) {
00517         SoSeparator * root = new SoSeparator;
00518         AnimationTexture(root);
00519         _viewer->setSceneGraph(root);
00520         return true;
00521     }
00522     else if(strcmp("GetCamera",pMsg) == 0 ) {
00523         SoCamera * Cam = _viewer->getCamera();
00524         if (!Cam) return false;
00525         *ppReturn = SoFCDB::writeNodesToString(Cam).c_str();
00526         return true;
00527     }
00528     else if(strncmp("SetCamera",pMsg,9) == 0 ) {
00529         return setCamera(pMsg+10);
00530     }
00531     else if(strncmp("Dump",pMsg,4) == 0 ) {
00532         dump(pMsg+5);
00533         return true;
00534     }
00535     else if(strcmp("ViewBottom",pMsg) == 0 ) {
00536         _viewer->setCameraOrientation(SbRotation(-1, 0, 0, 0));
00537         _viewer->viewAll();
00538         return true;
00539     }
00540     else if(strcmp("ViewFront",pMsg) == 0 ) {
00541         float root = (float)(sqrt(2.0)/2.0);
00542         _viewer->setCameraOrientation(SbRotation(-root, 0, 0, -root));
00543         _viewer->viewAll();
00544         return true;
00545     }
00546     else if(strcmp("ViewLeft",pMsg) == 0 ) {
00547         _viewer->setCameraOrientation(SbRotation(-0.5, 0.5, 0.5, -0.5));
00548         _viewer->viewAll();
00549         return true;
00550     }
00551     else if(strcmp("ViewRear",pMsg) == 0 ) {
00552         float root = (float)(sqrt(2.0)/2.0);
00553         _viewer->setCameraOrientation(SbRotation(0, root, root, 0));
00554         _viewer->viewAll();
00555         return true;
00556     }
00557     else if(strcmp("ViewRight",pMsg) == 0 ) {
00558         _viewer->setCameraOrientation(SbRotation(0.5, 0.5, 0.5, 0.5));
00559         _viewer->viewAll();
00560         return true;
00561     }
00562     else if(strcmp("ViewTop",pMsg) == 0 ) {
00563         _viewer->setCameraOrientation(SbRotation(0, 0, 0, 1));
00564         _viewer->viewAll();
00565         return true;
00566     }
00567     else if(strcmp("ViewAxo",pMsg) == 0 ) {
00568         _viewer->setCameraOrientation(SbRotation
00569             (-0.353553f, -0.146447f, -0.353553f, -0.853553f));
00570         _viewer->viewAll();
00571         return true;
00572     }
00573     else if(strcmp("OrthographicCamera",pMsg) == 0 ) {
00574         _viewer->setCameraType(SoOrthographicCamera::getClassTypeId());
00575         return true;
00576     }
00577     else if(strcmp("PerspectiveCamera",pMsg) == 0 ) {
00578         _viewer->setCameraType(SoPerspectiveCamera::getClassTypeId());
00579         return true;
00580     }
00581     else  if(strcmp("Undo",pMsg) == 0 ) {
00582         getGuiDocument()->undo(1);
00583         return true;
00584     }
00585     else  if(strcmp("Redo",pMsg) == 0 ) {
00586         getGuiDocument()->redo(1);
00587         return true;
00588     }
00589     else if (strcmp("Save",pMsg) == 0) {
00590         getGuiDocument()->save();
00591         return true;
00592     }
00593     else if (strcmp("SaveAs",pMsg) == 0) {
00594         getGuiDocument()->saveAs();
00595         return true;
00596     }
00597     else
00598         return false;
00599 }
00600 
00601 bool View3DInventor::onHasMsg(const char* pMsg) const
00602 {
00603     if  (strcmp("Save",pMsg) == 0)
00604         return true;
00605     else if (strcmp("SaveAs",pMsg) == 0)
00606         return true;
00607     else if (strcmp("Undo",pMsg) == 0)
00608         return getAppDocument()->getAvailableUndos() > 0;
00609     else if (strcmp("Redo",pMsg) == 0)
00610         return getAppDocument()->getAvailableRedos() > 0; 
00611     else if (strcmp("Print",pMsg) == 0)
00612         return true; 
00613     else if (strcmp("PrintPreview",pMsg) == 0)
00614         return true; 
00615     else if (strcmp("PrintPdf",pMsg) == 0)
00616         return true; 
00617     else if(strcmp("SetStereoRedGreen",pMsg) == 0)
00618         return true;
00619     else if(strcmp("SetStereoQuadBuff",pMsg) == 0)
00620         return true;
00621     else if(strcmp("SetStereoInterleavedRows",pMsg) == 0)
00622         return true;
00623     else if(strcmp("SetStereoInterleavedColumns",pMsg) == 0)
00624         return true;
00625     else if(strcmp("SetStereoOff",pMsg) == 0)
00626         return true;
00627     else if(strcmp("Example1",pMsg) == 0)
00628         return true;
00629     else if(strcmp("Example2",pMsg) == 0)
00630         return true;
00631     else if(strcmp("Example3",pMsg) == 0)
00632         return true;
00633     else if(strcmp("ViewFit",pMsg) == 0)
00634         return true;
00635     else if(strcmp("ViewSelection",pMsg) == 0)
00636         return true;
00637     else if(strcmp("ViewBottom",pMsg) == 0)
00638         return true;
00639     else if(strcmp("ViewFront",pMsg) == 0)
00640         return true;
00641     else if(strcmp("ViewLeft",pMsg) == 0)
00642         return true;
00643     else if(strcmp("ViewRear",pMsg) == 0)
00644         return true;
00645     else if(strcmp("ViewRight",pMsg) == 0)
00646         return true;
00647     else if(strcmp("ViewTop",pMsg) == 0)
00648         return true;
00649     else if(strcmp("ViewAxo",pMsg) == 0)
00650         return true;
00651     else if(strcmp("GetCamera",pMsg) == 0)
00652         return true;
00653     else if(strncmp("SetCamera",pMsg,9) == 0)
00654         return true;
00655     else if(strncmp("Dump",pMsg,4) == 0)
00656         return true;
00657     return false;
00658 }
00659 
00660 bool View3DInventor::setCamera(const char* pCamera)
00661 {
00662     SoCamera * CamViewer = _viewer->getCamera();
00663     if (!CamViewer) {
00664         throw Base::Exception("No camera set so far...");
00665     }
00666 
00667     SoInput in;
00668     in.setBuffer((void*)pCamera,std::strlen(pCamera));
00669 
00670     SoNode * Cam;
00671     SoDB::read(&in,Cam);
00672 
00673     if (!Cam){
00674         throw Base::Exception("Camera settings failed to read");
00675     }
00676 
00677     // toggle between persepective and orthographic camera
00678     if (Cam->getTypeId() != CamViewer->getTypeId())
00679     {
00680         _viewer->setCameraType(Cam->getTypeId());
00681         CamViewer = _viewer->getCamera();
00682     }
00683 
00684     SoPerspectiveCamera  * CamViewerP = 0;
00685     SoOrthographicCamera * CamViewerO = 0;
00686 
00687     if (CamViewer->getTypeId() == SoPerspectiveCamera::getClassTypeId()) {
00688         CamViewerP = (SoPerspectiveCamera *)CamViewer;  // safe downward cast, knows the type
00689     } else if (CamViewer->getTypeId() == SoOrthographicCamera::getClassTypeId()) {
00690         CamViewerO = (SoOrthographicCamera *)CamViewer;  // safe downward cast, knows the type
00691     }
00692 
00693     if (Cam->getTypeId() == SoPerspectiveCamera::getClassTypeId()) {
00694         if (CamViewerP){
00695             CamViewerP->position      = ((SoPerspectiveCamera *)Cam)->position;
00696             CamViewerP->orientation   = ((SoPerspectiveCamera *)Cam)->orientation;
00697             CamViewerP->nearDistance  = ((SoPerspectiveCamera *)Cam)->nearDistance;
00698             CamViewerP->farDistance   = ((SoPerspectiveCamera *)Cam)->farDistance;
00699             CamViewerP->focalDistance = ((SoPerspectiveCamera *)Cam)->focalDistance;
00700         } else {
00701             throw Base::Exception("Camera type mismatch");
00702         }
00703     } else if (Cam->getTypeId() == SoOrthographicCamera::getClassTypeId()) {
00704         if (CamViewerO){
00705             CamViewerO->viewportMapping  = ((SoOrthographicCamera *)Cam)->viewportMapping;
00706             CamViewerO->position         = ((SoOrthographicCamera *)Cam)->position;
00707             CamViewerO->orientation      = ((SoOrthographicCamera *)Cam)->orientation;
00708             CamViewerO->nearDistance     = ((SoOrthographicCamera *)Cam)->nearDistance;
00709             CamViewerO->farDistance      = ((SoOrthographicCamera *)Cam)->farDistance;
00710             CamViewerO->focalDistance    = ((SoOrthographicCamera *)Cam)->focalDistance;
00711             CamViewerO->aspectRatio      = ((SoOrthographicCamera *)Cam)->aspectRatio ;
00712             CamViewerO->height           = ((SoOrthographicCamera *)Cam)->height;
00713         } else {
00714             throw Base::Exception("Camera type mismatch");
00715         }
00716     }
00717 
00718     return true;
00719 }
00720 
00721 void View3DInventor::toggleClippingPlane()
00722 {
00723     _viewer->toggleClippingPlane();
00724 }
00725 
00726 bool View3DInventor::hasClippingPlane() const
00727 {
00728     return _viewer->hasClippingPlane();
00729 }
00730 
00731 void View3DInventor::setOverlayWidget(GLOverlayWidget* widget)
00732 {
00733     removeOverlayWidget();
00734     QGLWidget* w = static_cast<QGLWidget*>(_viewer->getGLWidget());
00735     QImage img = w->grabFrameBuffer();
00736     widget->setImage(img);
00737     stack->addWidget(widget);
00738     stack->setCurrentIndex(1);
00739 }
00740 
00741 void View3DInventor::removeOverlayWidget()
00742 {
00743     stack->setCurrentIndex(0);
00744     QWidget* overlay = stack->widget(1);
00745     if (overlay) stack->removeWidget(overlay);
00746 }
00747 
00748 void View3DInventor::setCursor(const QCursor& aCursor)
00749 {
00750     _viewer->getWidget()->setCursor(aCursor);
00751 }
00752 
00753 void View3DInventor::setCursor(Qt::CursorShape aCursor)
00754 {
00755     _viewer->getWidget()->setCursor(aCursor);
00756 }
00757 
00758 void View3DInventor::dump(const char* filename)
00759 {
00760     SoGetPrimitiveCountAction action;
00761     action.setCanApproximate(true);
00762     action.apply(_viewer->getSceneGraph());
00763 
00764     if ( action.getTriangleCount() > 100000 || action.getPointCount() > 30000 || action.getLineCount() > 10000 )
00765         _viewer->dumpToFile(filename,true);
00766     else
00767         _viewer->dumpToFile(filename,false);
00768 }
00769 
00770 void View3DInventor::windowStateChanged(MDIView* view)
00771 {
00772     bool canStartTimer = false;
00773     if (this != view) {
00774         // If both views are child widgets of the workspace and view is maximized this view 
00775         // must be hidden, hence we can start the timer.
00776         // Note: If view is top-level or fullscreen it doesn't necessarily hide the other view
00777         // e.g. if it is on a second monitor.
00778         canStartTimer = (!this->isTopLevel() && !view->isTopLevel() && view->isMaximized());
00779     } else if (isMinimized()) {
00780         // I am the active view but minimized
00781         canStartTimer = true;
00782     }
00783 
00784     if (canStartTimer) {
00785         // do a single shot event (maybe insert a checkbox in viewer settings)
00786         int msecs = hGrp->GetInt("stopAnimatingIfDeactivated", 3000);
00787         if (!stopSpinTimer->isActive() && msecs >= 0) { // if < 0 do not stop rotation
00788             stopSpinTimer->setSingleShot(true);
00789             stopSpinTimer->start(msecs);
00790         }
00791     } else if (stopSpinTimer->isActive()) {
00792         // If this view may be visible again we can stop the timer
00793         stopSpinTimer->stop();
00794     }
00795 }
00796 
00797 void View3DInventor::stopAnimating()
00798 {
00799     _viewer->stopAnimating();
00800 }
00801 
00805 void View3DInventor::dropEvent (QDropEvent * e)
00806 {
00807     const QMimeData* data = e->mimeData();
00808     if (data->hasUrls()) {
00809         getMainWindow()->loadUrls(getAppDocument(), data->urls());
00810     }
00811     else {
00812         MDIView::dropEvent(e);
00813     }
00814 }
00815 
00816 void View3DInventor::dragEnterEvent (QDragEnterEvent * e)
00817 {
00818     // Here we must allow uri drafs and check them in dropEvent
00819     const QMimeData* data = e->mimeData();
00820     if (data->hasUrls())
00821         e->accept();
00822     else
00823         e->ignore();
00824 }
00825 
00826 void View3DInventor::setCurrentViewMode(ViewMode newmode)
00827 {
00828     ViewMode oldmode = MDIView::currentViewMode();
00829     if (oldmode == newmode)
00830         return;
00831     MDIView::setCurrentViewMode(newmode);
00832 
00833     // This widget becomes the focus proxy of the embedded GL widget if we leave 
00834     // the 'Child' mode. If we reenter 'Child' mode the focus proxy is reset to 0.
00835     // If we change from 'TopLevel' mode to 'Fullscreen' mode or vice versa nothing
00836     // happens.
00837     // Grabbing keyboard when leaving 'Child' mode (as done in a recent version) should
00838     // be avoided because when two or more windows are either in 'TopLevel' or 'Fullscreen'
00839     // mode only the last window gets all key event even if it is not the active one.
00840     //
00841     // It is important to set the focus proxy to get all key events otherwise we would loose
00842     // control after redirecting the first key event to the GL widget.
00843     // We redirect these events in keyPressEvent() and keyReleaseEvent().
00844     if (oldmode == Child) {
00845         // To make a global shortcut working from this window we need to add
00846         // all existing actions from the mainwindow and its sub-widgets 
00847         QList<QAction*> acts = getMainWindow()->findChildren<QAction*>();
00848         this->addActions(acts);
00849         _viewer->getGLWidget()->setFocusProxy(this);
00850         // To be notfified for new actions
00851         qApp->installEventFilter(this);
00852     }
00853     else if (newmode == Child) {
00854         _viewer->getGLWidget()->setFocusProxy(0);
00855         qApp->removeEventFilter(this);
00856         QList<QAction*> acts = this->actions();
00857         for (QList<QAction*>::Iterator it = acts.begin(); it != acts.end(); ++it)
00858             this->removeAction(*it);
00859     }
00860 }
00861 
00862 bool View3DInventor::eventFilter(QObject* watched, QEvent* e)
00863 {
00864     // As long as this widget is a top-level window (either in 'TopLevel' or 'FullScreen' mode) we
00865     // need to be notified when an action is added to a widget. This action must also be added to 
00866     // this window to allow to make use of its shortcut (if defined).
00867     // Note: We don't need to care about removing an action if its parent widget gets destroyed.
00868     // This does the action itself for us.
00869     if (watched != this && e->type() == QEvent::ActionAdded) {
00870         QActionEvent* a = static_cast<QActionEvent*>(e);
00871         QAction* action = a->action();
00872 
00873         if (!action->isSeparator()) {
00874             QList<QAction*> actions = this->actions();
00875             if (!actions.contains(action))
00876                 this->addAction(action);
00877         }
00878     }
00879 
00880     return false;
00881 }
00882 
00883 void View3DInventor::keyPressEvent (QKeyEvent* e)
00884 {
00885     ViewMode mode = MDIView::currentViewMode();
00886     if (mode != Child) {
00887         // If the widget is in fullscreen mode then we can return to normal mode either
00888         // by pressing the matching accelerator or ESC. 
00889         if (e->key() == Qt::Key_Escape) {
00890             setCurrentViewMode(Child);
00891         }
00892         else {
00893             // Note: The key events should be redirected directly to the GL widget and not to the main window
00894             // otherwise the first redirected key event always disappears in hyperspace.
00895             //
00896             // send the event to the GL widget that converts to and handles an SoEvent
00897             QWidget* w = _viewer->getGLWidget();
00898             QApplication::sendEvent(w,e);
00899         }
00900     }
00901     else {
00902         QMainWindow::keyPressEvent(e);
00903     }
00904 }
00905 
00906 void View3DInventor::keyReleaseEvent (QKeyEvent* e)
00907 {
00908     ViewMode mode = MDIView::currentViewMode();
00909     if (mode != Child) {
00910         // send the event to the GL widget that converts to and handles an SoEvent
00911         QWidget* w = _viewer->getGLWidget();
00912         QApplication::sendEvent(w,e);
00913     } else {
00914         QMainWindow::keyReleaseEvent(e);
00915     }
00916 }
00917 
00918 void View3DInventor::focusInEvent (QFocusEvent * e)
00919 {
00920     _viewer->getGLWidget()->setFocus();
00921 }
00922 
00923 void View3DInventor::contextMenuEvent (QContextMenuEvent*e)
00924 {
00925     MDIView::contextMenuEvent(e);
00926 }
00927 
00928 void View3DInventor::customEvent(QEvent * e)
00929 {
00930     if (e->type() == QEvent::User) {
00931         NavigationStyleEvent* se = static_cast<NavigationStyleEvent*>(e);
00932         _viewer->setNavigationType(se->style());
00933     }
00934 }
00935 
00936 
00937 #include "moc_View3DInventor.cpp"

Generated on Wed Nov 23 19:00:57 2011 for FreeCAD by  doxygen 1.6.1