openFunctions.cc

00001 /*===========================================================================*\
00002  *                                                                           *
00003  *                              OpenFlipper                                  *
00004  *      Copyright (C) 2001-2009 by Computer Graphics Group, RWTH Aachen      *
00005  *                           www.openflipper.org                             *
00006  *                                                                           *
00007  *---------------------------------------------------------------------------*
00008  *  This file is part of OpenFlipper.                                        *
00009  *                                                                           *
00010  *  OpenFlipper is free software: you can redistribute it and/or modify      *
00011  *  it under the terms of the GNU Lesser General Public License as           *
00012  *  published by the Free Software Foundation, either version 3 of           *
00013  *  the License, or (at your option) any later version with the              *
00014  *  following exceptions:                                                    *
00015  *                                                                           *
00016  *  If other files instantiate templates or use macros                       *
00017  *  or inline functions from this file, or you compile this file and         *
00018  *  link it with other files to produce an executable, this file does        *
00019  *  not by itself cause the resulting executable to be covered by the        *
00020  *  GNU Lesser General Public License. This exception does not however       *
00021  *  invalidate any other reasons why the executable file might be            *
00022  *  covered by the GNU Lesser General Public License.                        *
00023  *                                                                           *
00024  *  OpenFlipper is distributed in the hope that it will be useful,           *
00025  *  but WITHOUT ANY WARRANTY; without even the implied warranty of           *
00026  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the            *
00027  *  GNU Lesser General Public License for more details.                      *
00028  *                                                                           *
00029  *  You should have received a copy of the GNU LesserGeneral Public          *
00030  *  License along with OpenFlipper. If not,                                  *
00031  *  see <http://www.gnu.org/licenses/>.                                      *
00032  *                                                                           *
00033 \*===========================================================================*/
00034 
00035 /*===========================================================================*\
00036  *                                                                           *
00037  *   $Revision: 7306 $                                                         *
00038  *   $Author: kremer $                                                      *
00039  *   $Date: 2009-10-02 15:25:40 +0200 (Fr, 02. Okt 2009) $                   *
00040  *                                                                           *
00041 \*===========================================================================*/
00042 
00043 
00044 
00045 
00046 
00047 #include "Core.hh"
00048 
00049 #include <ACG/QtWidgets/QtFileDialog.hh>
00050 
00051 #include "OpenFlipper/common/GlobalOptions.hh"
00052 #include "OpenFlipper/BasePlugin/PluginFunctions.hh"
00053 
00054 #include "OpenFlipper/widgets/loadWidget/loadWidget.hh"
00055 #include "OpenFlipper/widgets/addEmptyWidget/addEmptyWidget.hh"
00056 
00057 #include <OpenFlipper/common/Types.hh>
00058 #include <ObjectTypes/PolyMesh/PolyMesh.hh>
00059 
00060 #include <time.h>
00061 
00062 void Core::resetScenegraph( bool _resetTrackBall  ) {
00063   if ( OpenFlipper::Options::gui() && !OpenFlipper::Options::loadingSettings() ) {
00064 
00065     for ( unsigned int i = 0 ; i < OpenFlipper::Options::examinerWidgets() ; ++i ) {
00066       // update scene graph (get new bounding box and set projection right, including near and far plane)
00067       PluginFunctions::viewerProperties(i).lockUpdate();
00068       coreWidget_->examiner_widgets_[i]->sceneGraph(root_node_scenegraph_, _resetTrackBall );
00069       PluginFunctions::viewerProperties(i).unLockUpdate();
00070       coreWidget_->examiner_widgets_[i]->updateGL();
00071     }
00072 
00073   }
00074 
00075   // Update the draw Modes Menu
00076   if ( OpenFlipper::Options::gui() )
00077     coreWidget_->slotUpdateGlobalDrawMenu();
00078 }
00079 
00080 //========================================================================================
00081 // ===            Open/Add-Empty Functions                    ============================
00082 //========================================================================================
00083 
00084 
00085 void Core::slotGetAllFilters ( QStringList& _list){
00086 
00087   for (int i=0; i < (int)supportedTypes_.size(); i++){
00088     QString f = supportedTypes_[i].plugin->getLoadFilters();
00089     f = f.section(")",0,0).section("(",1,1).trimmed();
00090     _list << (QString::number(supportedTypes_[i].plugin->supportedType()) + " " + f);
00091   }
00092 }
00093 
00094 void Core::commandLineOpen(const char* _filename, bool asPolyMesh ){
00095 
00096         QString file(_filename);
00097 
00098         if ( !file.startsWith("/") && !file.contains(":") ) {
00099 
00100                 file = QDir::currentPath();
00101                 file += OpenFlipper::Options::dirSeparator();
00102                 file += _filename;
00103         }
00104 
00105         commandLineFileNames_.push_back(std::pair< std::string , bool >(file.toStdString(), asPolyMesh));
00106 }
00107 
00108 void Core::commandLineScript(const char* _filename ) {
00109   commandLineScriptNames_.push_back(_filename);
00110 }
00111 
00112 void Core::slotExecuteAfterStartup() {
00113 
00114   //check if we have scripting support:
00115   bool scriptingSupport = false;
00116   slotPluginExists("scripting",scriptingSupport);
00117   if ( ! scriptingSupport ) {
00118     emit log(LOGERR ,tr("No scripting support available, please check if we load a scripting plugin .. Skipping script execution on startup"));
00119   }
00120 
00121   // Collect all script files from the scripting subdirectory and execute them if possible
00122   if ( scriptingSupport ) {
00123 
00124     QDir scriptDir = OpenFlipper::Options::scriptDir();
00125     QStringList scriptFiles = scriptDir.entryList(QDir::Files,QDir::Name);
00126 
00127     for ( int i = 0 ; i  < scriptFiles.size(); ++i )
00128       if ( scriptFiles[i].endsWith("ofs") )
00129         emit executeFileScript(scriptDir.path() + QDir::separator() + scriptFiles[i]);
00130 
00131   }
00132 
00133   for ( uint i = 0 ; i < commandLineFileNames_.size() ; ++i ) {
00134 
00135     // Skip scripts here as they will be handled by a different function
00136     QString tmp = QString::fromStdString(commandLineFileNames_[i].first);
00137     if ( tmp.endsWith("ofs") ) {
00138       commandLineScriptNames_.push_back(commandLineFileNames_[i].first);
00139       continue;
00140     }
00141 
00142     if (commandLineFileNames_[i].second)
00143       loadObject(DATA_POLY_MESH, QString::fromStdString(commandLineFileNames_[i].first));
00144     else {
00145       loadObject(QString::fromStdString(commandLineFileNames_[i].first));
00146     }
00147   }
00148 
00149   if ( scriptingSupport )
00150     for ( uint i = 0 ; i < commandLineScriptNames_.size() ; ++i ) {
00151       // Add the full path to the script to set scripting dir right
00152       QString tmp = QString::fromStdString(commandLineScriptNames_[i]);
00153       tmp = QDir::currentPath() + QDir::separator() + tmp;
00154       emit executeFileScript(tmp);
00155     }
00156 
00157   if ( !OpenFlipper::Options::gui() && !OpenFlipper::Options::remoteControl())
00158     exitApplication();
00159 }
00160 
00162 int Core::loadObject ( QString _filename ) {
00163 
00164   if (_filename.endsWith(".ini")) {
00165 
00166     // Load all information from the given ini file
00167     openIniFile(_filename,true,true,true);
00168 
00169     if ( OpenFlipper::Options::gui() )
00170       coreWidget_->addRecent(_filename, DATA_UNKNOWN);
00171 
00172     return -2;
00173   } else
00174   if (_filename.endsWith(".ofs")) {
00175      emit log(LOGINFO ,tr("Starting script execution of %1.").arg( _filename)) ;
00176      emit executeFileScript(_filename);
00177   } else
00178     return loadObject( DATA_TRIANGLE_MESH, _filename);
00179 
00180   return -1;
00181 }
00182 
00184 int Core::loadObject( DataType _type, QString _filename) {
00185 
00186   if (_type == DATA_UNKNOWN)
00187     return loadObject(_filename);
00188 
00189   for (int i=0; i < (int)supportedTypes_.size(); i++)
00190     if (supportedTypes_[i].type == _type) {
00191 
00192 
00193       if ( OpenFlipper::Options::gui() ) {
00194         coreWidget_->statusMessage( tr("Loading %1 ... ").arg(_filename));
00195         if ( !OpenFlipper::Options::loadingSettings() )
00196           coreWidget_->setStatus(ApplicationStatus::PROCESSING );
00197       }
00198 
00199       //load file
00200       int id = supportedTypes_[i].plugin->loadObject(_filename);
00201 
00202       if ( OpenFlipper::Options::gui() ) {
00203         if ( id != -1 )
00204           coreWidget_->statusMessage( tr("Loading %1 ... done").arg(_filename), 4000 );
00205         else
00206           coreWidget_->statusMessage( tr("Loading %1 ... failed!").arg(_filename), 4000 );
00207 
00208         if ( !OpenFlipper::Options::loadingSettings() )
00209           coreWidget_->setStatus(ApplicationStatus::READY );
00210       }
00211 
00212       return id;
00213     }
00214   return -1; //no plugin found
00215 }
00216 
00218 int Core::addEmptyObject( DataType _type ) {
00219   for (int i=0; i < (int)supportedTypes_.size(); i++)
00220     if (supportedTypes_[i].type == _type)
00221       return supportedTypes_[i].plugin->addEmpty();
00222   return -1; //no plugin found
00223 }
00224 
00225 //========================================================================================
00226 // ===             Open/Add-Empty Slots                       ============================
00227 //========================================================================================
00228 
00230 void Core::slotAddEmptyObject( DataType _type , int& _id ) {
00231   _id = addEmptyObject( _type );
00232 }
00233 
00235 void Core::slotCopyObject( int _oldId , int& _newId ) {
00236 
00237   if ( _oldId == -1 ) {
00238     emit log(LOGERR,tr("Requested copy for illegal Object id: %1").arg(_oldId) );
00239     _newId = -1;
00240     return;
00241   }
00242 
00243   // get the node
00244   BaseObject* object = objectRoot_->childExists(_oldId);
00245 
00246   if ( !object ) {
00247     emit log(LOGERR,tr("Requested copy for unknown Object id: %1 ").arg(_oldId) );
00248     _newId = -1;
00249     return ;
00250   }
00251 
00252   // Copy the item
00253   BaseObject* copy = object->copy();
00254 
00255   if ( copy == 0 ) {
00256     emit log(LOGERR,tr("Unable to create a copy of the object."));
00257     return;
00258   }
00259 
00260   // Integrate into object tree
00261   copy->setParent( object->parent() );
00262   if ( object->parent() )
00263     object->parent()->appendChild(copy);
00264   else
00265     std::cerr << "Unable to add copy to object list" << std::endl;
00266 
00267   // return the new id
00268   _newId = copy->id();
00269 
00270   // tell plugins that a new object has been created
00271   slotEmptyObjectAdded(_newId);
00272 
00273   // tell plugins that the object has been updated
00274   slotObjectUpdated(_newId);
00275 
00276 }
00277 
00279 void Core::slotLoad(QString _filename, DataType _type, int& _id) {
00280   _id = loadObject(_type,_filename);
00281 
00282   // Check if it is a polymesh
00283   if ( _type == DATA_POLY_MESH ) {
00284 
00285     PolyMeshObject* poly = 0;
00286     PluginFunctions::getObject(_id,poly);
00287 
00288     if ( poly != 0 ) {
00289         PolyMesh& mesh = *poly->mesh();
00290 
00291         bool isTriangleMesh = true;
00292 
00293         for ( PolyMesh::FaceIter f_it = mesh.faces_begin(); f_it != mesh.faces_end() ; ++f_it) {
00294 
00295           // Count number of vertices for the current face
00296           uint count = 0;
00297           for ( PolyMesh::FaceVertexIter fv_it( mesh,f_it); fv_it; ++fv_it )
00298             ++count;
00299 
00300           // Check if it is a triangle. If not, this is really a poly mesh
00301           if ( count != 3 ) {
00302             isTriangleMesh = false;
00303             break;
00304           }
00305 
00306         }
00307 
00308         // Mesh loaded as polymesh is actually a triangle mesh. Ask the user to reload as triangle mesh or keep it as poly mesh.
00309         if ( isTriangleMesh ) {
00310           QMessageBox::StandardButton result = QMessageBox::question ( 0,
00311                                                                       tr("TriMesh loaded as PolyMesh"),
00312                                                                       tr("You opened the mesh as a poly mesh but actually its a triangle mesh. \nShould it be opened as a triangle mesh?"),
00313                                                                       (QMessageBox::Yes | QMessageBox::No ),
00314                                                                       QMessageBox::Yes );
00315           // User decided to reload as triangle mesh
00316           if ( result == QMessageBox::Yes ) {
00317             slotDeleteObject(_id);
00318             _id = loadObject(DATA_TRIANGLE_MESH ,_filename);
00319             _type = DATA_TRIANGLE_MESH;
00320           }
00321         }
00322 
00323     }
00324   }
00325   if ( _id < 0 )
00326     _id = -1;
00327   else
00328     if ( OpenFlipper::Options::gui() )
00329       coreWidget_->addRecent(_filename,_type);
00330 }
00331 
00333 void Core::slotObjectOpened ( int _id ) {
00334   if ( OpenFlipper::Options::doSlotDebugging() ) {
00335     if ( sender() != 0 ) {
00336       if ( sender()->metaObject() != 0 ) {
00337         emit log(LOGINFO,tr("slotObjectOpened( ") + QString::number(_id) + tr(" ) called by ") +
00338                   QString( sender()->metaObject()->className() ) );
00339       }
00340     } else {
00341       emit log(LOGINFO,tr("slotObjectOpened( ") + QString::number(_id) + tr(" ) called by Core") );
00342     }
00343   }
00344 
00345   // get the opened object
00346   BaseObjectData* object;
00347   PluginFunctions::getObject(_id,object);
00348 
00349   QColor color;
00350 
00351   if ( OpenFlipper::Options::randomBaseColor() ){
00352       //init random seed
00353       srand ( time(NULL) );
00354 
00355       QColor bckgrnd = OpenFlipper::Options::defaultBackgroundColor();
00356       int diff;
00357 
00358       do{
00359         color.setRgb(rand()%255, rand()%255, rand()%255);
00360 
00361         diff = (bckgrnd.red()   - color.red())  *(bckgrnd.red()   - color.red())
00362               +(bckgrnd.green() - color.green())*(bckgrnd.green() - color.green())
00363               +(bckgrnd.blue()  - color.blue()) *(bckgrnd.blue()  - color.blue());
00364       }while (diff < 70000);
00365   }
00366   else{
00367       color = OpenFlipper::Options::defaultBaseColor();
00368   }
00369 
00370   ACG::Vec4f colorV;
00371   colorV[0] = color.redF();
00372   colorV[1] = color.greenF();
00373   colorV[2] = color.blueF();
00374   colorV[3] = color.alphaF();
00375 
00376   object->setBaseColor( colorV );
00377 
00378   // ================================================================================
00379   // Set defaults for DrawMode, ViewingDirection and Projection if this is the first opened object
00380   // If a plugin changes the drawmode later, this setting will be overridden!
00381   // ================================================================================
00382   if ( PluginFunctions::objectCount() == 1 && OpenFlipper::Options::gui() && !OpenFlipper::Options::loadingSettings() )
00383     for ( unsigned int i = 0 ; i < OpenFlipper::Options::examinerWidgets() ; ++i ){
00384       PluginFunctions::viewerProperties(i).drawMode( OpenFlipper::Options::defaultDrawMode(i) );
00385 
00386       if ( OpenFlipper::Options::defaultProjectionMode(i) == 0 )
00387         PluginFunctions::orthographicProjection(i);
00388       else
00389         PluginFunctions::perspectiveProjection(i);
00390 
00391       PluginFunctions::setFixedView(OpenFlipper::Options::defaultViewingDirection(i), i );
00392     }
00393 
00394   // ================================================================================
00395   // Recompute bounding box and scenegraph info
00396   // Reset scene center here to include new object
00397   // ================================================================================
00398   resetScenegraph(true);
00399 
00400   // ================================================================================
00401   // Tell plugins, that a file has been opened
00402   // ================================================================================
00403   emit openedFile( _id );
00404 
00405   // ================================================================================
00406   // Tell plugins, that the Object is updated and the active object has changed
00407   // ================================================================================
00408   emit signalObjectUpdated(_id);
00409   emit objectSelectionChanged( _id );
00410 
00411   // ================================================================================
00412   // Create initial backup
00413   // ================================================================================
00414   backupRequest(_id,"Original Object");
00415 
00416   // ================================================================================
00417   // Add the file to the recent files menu
00418   // ================================================================================
00419   QString filename = object->path() + OpenFlipper::Options::dirSeparator() + object->name();
00420   BaseObject* object2;
00421   PluginFunctions::getObject(_id,object2);
00422   if ( OpenFlipper::Options::gui() )
00423     coreWidget_->addRecent( filename, object2->dataType() );
00424 
00425   // ================================================================================
00426   // if this is the first object opend, reset the global view
00427   // ================================================================================
00428   if ( PluginFunctions::objectCount() == 1 && OpenFlipper::Options::gui() && !OpenFlipper::Options::loadingSettings() )
00429     for ( unsigned int i = 0 ; i < OpenFlipper::Options::examinerWidgets() ; ++i ) {
00430       coreWidget_->examiner_widgets_[i]->viewAll();
00431     }
00432 
00433   // objectRoot_->dumpTree();
00434 }
00435 
00437 void Core::slotEmptyObjectAdded ( int _id ) {
00438   if ( OpenFlipper::Options::doSlotDebugging() ) {
00439     if ( sender() != 0 ) {
00440       if ( sender()->metaObject() != 0 ) {
00441         emit log(LOGINFO,tr("slotEmptyObjectAdded( ") + QString::number(_id) + tr(" ) called by ") +
00442                   QString( sender()->metaObject()->className() ) );
00443       }
00444     } else {
00445       emit log(LOGINFO,tr("slotEmptyObjectAdded( ") + QString::number(_id) + tr(" ) called by Core") );
00446     }
00447   }
00448 
00449   // get the opened object
00450   BaseObjectData* object;
00451   PluginFunctions::getObject(_id,object);
00452 
00453   emit emptyObjectAdded( _id );
00454 
00455   // Tell the Plugins that the Object List and the active object have changed
00456   emit signalObjectUpdated(_id);
00457   emit objectSelectionChanged(_id);
00458 
00459   backupRequest(_id,"Original Object");
00460 
00462 //    QString filename = object->path() + OpenFlipper::Options::dirSeparator() + object->name();
00463 
00464 //    addRecent(filename);
00465 }
00466 
00467 //========================================================================================
00468 // ===             Menu Slots                                 ============================
00469 //========================================================================================
00470 
00472 void Core::slotAddEmptyObjectMenu() {
00473   if (supportedTypes_.size() != 0){
00474     static addEmptyWidget* widget = 0;
00475     if ( !widget ){
00476       std::vector< DataType > types;
00477       QStringList typeNames;
00478       for (int i=0; i < (int)supportedTypes_.size(); i++) {
00479         types.push_back(supportedTypes_[i].type);
00480         typeNames.push_back(supportedTypes_[i].plugin->typeName());
00481       }
00482       widget = new addEmptyWidget(types,typeNames);
00483       widget->setWindowIcon( OpenFlipper::Options::OpenFlipperIcon() );
00484       connect(widget,SIGNAL(chosen(DataType, int&)),this,SLOT(slotAddEmptyObject(DataType, int&)));
00485     }
00486     widget->show();
00487   }else
00488     emit log(LOGERR,tr("Could not show 'add Empty' dialog. Missing file-plugins."));
00489 }
00490 
00491 //========================================================================================
00492 // ===             Public Slots                                 ============================
00493 //========================================================================================
00494 
00496 void Core::loadObject() {
00497 
00498   if ( OpenFlipper::Options::gui() ){
00499 
00500     if (supportedTypes_.size() != 0){
00501       LoadWidget* widget = new LoadWidget(supportedTypes_);
00502       connect(widget,SIGNAL(load(QString, DataType, int&)),this,SLOT(slotLoad(QString, DataType, int&)));
00503       connect(widget,SIGNAL(save(int, QString)),this,SLOT(saveObject(int, QString)));
00504 
00505       widget->setWindowIcon( OpenFlipper::Options::OpenFlipperIcon() );
00506 
00507       widget->showLoad();
00508 
00509       widget->disconnect();
00510       delete widget;
00511 
00512     }else
00513       emit log(LOGERR,tr("Could not show 'load objects' dialog. Missing file-plugins."));
00514 
00515   }
00516 }
00517 
00519 void Core::loadSettings(){
00520 
00521   if ( OpenFlipper::Options::gui() ){
00522 
00523     QString complete_name;
00524 
00525 
00526     QFileDialog fileDialog( coreWidget_,
00527                             tr("Load Settings"),
00528                             OpenFlipper::Options::currentDirStr(),
00529                             tr("INI files (*.ini);;OBJ files (*.obj )") );
00530 
00531     fileDialog.setOption (QFileDialog::DontUseNativeDialog, true);
00532     fileDialog.setAcceptMode ( QFileDialog::AcceptOpen );
00533     fileDialog.setFileMode ( QFileDialog::AnyFile );
00534 
00535     QGridLayout *layout = (QGridLayout*)fileDialog.layout();
00536 
00537     QGroupBox* optionsBox = new QGroupBox( &fileDialog ) ;
00538     optionsBox->setSizePolicy( QSizePolicy ( QSizePolicy::Expanding , QSizePolicy::Preferred ) );
00539     optionsBox->setTitle(tr("Options"));
00540     layout->addWidget( optionsBox, layout->rowCount() , 0 , 1,layout->columnCount() );
00541 
00542     QCheckBox *loadProgramSettings = new QCheckBox(optionsBox);
00543     loadProgramSettings->setText(tr("Load program settings"));
00544     loadProgramSettings->setToolTip(tr("Load all current program settings from the file ( This will include view settings, colors,...) "));
00545     loadProgramSettings->setCheckState( Qt::Unchecked );
00546 
00547     QCheckBox *loadPluginSettings = new QCheckBox(optionsBox);
00548     loadPluginSettings->setText(tr("Load per Plugin Settings"));
00549     loadPluginSettings->setToolTip(tr("Plugins should load their current global settings from the file"));
00550     loadPluginSettings->setCheckState( Qt::Checked );
00551 
00552     QCheckBox *loadObjectInfo = new QCheckBox(optionsBox);
00553     loadObjectInfo->setText(tr("Load all objects defined in the file"));
00554     loadObjectInfo->setToolTip(tr("Load all objects which are defined in the file"));
00555     loadObjectInfo->setCheckState( Qt::Checked );
00556 
00557     QBoxLayout* frameLayout = new QBoxLayout(QBoxLayout::TopToBottom,optionsBox);
00558     frameLayout->addWidget( loadProgramSettings , 0 , 0);
00559     frameLayout->addWidget( loadPluginSettings  , 1 , 0);
00560     frameLayout->addWidget( loadObjectInfo      , 2 , 0);
00561     frameLayout->addStretch();
00562 
00563     fileDialog.resize(550 ,500);
00564 
00565     // ========================================================================================
00566     // show the saveSettings-Dialog and get the target file
00567     // ========================================================================================
00568     QStringList fileNames;
00569     if (fileDialog.exec()) {
00570       fileNames = fileDialog.selectedFiles();
00571     } else {
00572       return;
00573     }
00574 
00575     if ( fileNames.size() > 1 ) {
00576       std::cerr << "Too many save filenames selected" << std::endl;
00577       return;
00578     }
00579 
00580     complete_name = fileNames[0];
00581 
00582 
00583     QString newpath = complete_name.section(OpenFlipper::Options::dirSeparator(),0,-2);
00584     OpenFlipper::Options::currentDir(newpath);
00585 
00586     if ( complete_name.endsWith("ini") ) {
00587       openIniFile( complete_name,
00588                    loadProgramSettings->isChecked(),
00589                    loadPluginSettings->isChecked(),
00590                    loadObjectInfo->isChecked());
00591       if ( loadProgramSettings->isChecked() )
00592         applyOptions();
00593     } else if ( complete_name.endsWith("obj") ) {
00594       openObjFile(complete_name);
00595       if ( loadProgramSettings->isChecked() )
00596         applyOptions();
00597     }
00598 
00599     coreWidget_->addRecent(complete_name, DATA_UNKNOWN);
00600   }
00601 }
00602 
00604 void Core::loadSettings(QString _filename){
00605 
00606   if ( !QFile(_filename).exists() )
00607     return;
00608 
00609   QString newpath = _filename.section(OpenFlipper::Options::dirSeparator(),0,-2);
00610   OpenFlipper::Options::currentDir(newpath);
00611 
00612   if ( _filename.endsWith("ini") ) {
00613     // Loaded function for recent files. Load everything.
00614     openIniFile(_filename,true,true,true);
00615     applyOptions();
00616   } else if ( _filename.endsWith("obj") ) {
00617     openObjFile(_filename);
00618     applyOptions();
00619   }
00620 
00621 }

acg pic Project OpenFlipper, ©  Computer Graphics Group, RWTH Aachen. Documentation generated using doxygen .