MouseAndKeyPlugin.cc

00001 //=============================================================================
00002 //
00003 //                               OpenFlipper
00004 //        Copyright (C) 2008 by Computer Graphics Group, RWTH Aachen
00005 //                           www.openflipper.org
00006 //
00007 //-----------------------------------------------------------------------------
00008 //
00009 //                                License
00010 //
00011 //  OpenFlipper is free software: you can redistribute it and/or modify
00012 //  it under the terms of the GNU Lesser General Public License as published by
00013 //  the Free Software Foundation, either version 3 of the License, or
00014 //  (at your option) any later version.
00015 //
00016 //  OpenFlipper is distributed in the hope that it will be useful,
00017 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
00018 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00019 //  GNU Lesser General Public License for more details.
00020 //
00021 //  You should have received a copy of the GNU Lesser General Public License
00022 //  along with OpenFlipper.  If not, see <http://www.gnu.org/licenses/>.
00023 //
00024 //-----------------------------------------------------------------------------
00025 //
00026 //   $Revision: 8520 $
00027 //   $Author: moebius $
00028 //   $Date: 2010-02-10 15:56:59 +0100 (Mi, 10. Feb 2010) $
00029 //
00030 //=============================================================================
00031 
00032 #include "MouseAndKeyPlugin.hh"
00033 
00034 
00035 #include <ObjectTypes/PolyMesh/PolyMesh.hh>
00036 #include <ObjectTypes/TriangleMesh/TriangleMesh.hh>
00037 
00038 #include "OpenFlipper/BasePlugin/PluginFunctions.hh"
00039 
00040 /*
00041  * Initialize plugin
00042  */
00043 void MouseAndKeyPlugin::initializePlugin() {
00044 
00045         // Set active object to -1
00046         activeObject_ = -1;
00047 
00048         // Set rotation axes to x, y and z axis
00049         axis_x_ = ACG::Vec3d(1.0, 0.0, 0.0);
00050         axis_y_ = ACG::Vec3d(0.0, 1.0, 0.0);
00051 
00052         // Register keys
00053         emit registerKey(Qt::Key_W,     Qt::NoModifier, "Rotate object down");
00054         emit registerKey(Qt::Key_S,     Qt::NoModifier, "Rotate object up");
00055         emit registerKey(Qt::Key_A,     Qt::NoModifier, "Rotate object left");
00056         emit registerKey(Qt::Key_D,     Qt::NoModifier, "Rotate object right");
00057         
00058         tool_ = new QWidget();
00059         QSize size(300, 300);
00060         tool_->resize(size);
00061         
00062         // Create button that can be toggled
00063         // to (de)activate plugin's picking mode
00064         pickButton_ = new QPushButton(tr("Select object"));
00065         pickButton_->setCheckable(true);
00066         
00067         // Create label
00068         QLabel* label = new QLabel();
00069         label->setText("(De)activate pick mode");
00070         
00071         // Set label to be above the button
00072         QGridLayout* grid = new QGridLayout;
00073         grid->addWidget(label, 0, 0);
00074         grid->addWidget(pickButton_, 1, 0);
00075         
00076         tool_->setLayout(grid);
00077         
00078         // Connect button to slotButtonClicked()
00079         connect( pickButton_, SIGNAL(clicked()), this, SLOT(slotButtonClicked()));
00080         
00081         // Add the Toolbox
00082         emit addToolbox( tr("Mouse and Key") , tool_ );
00083 
00084 } // End initializePlugin
00085 
00086 /*
00087  * Is called after all plugins have been initialized
00088  */
00089 void MouseAndKeyPlugin::pluginsInitialized() {
00090 
00091         // Add pickmode
00092         emit addPickMode("MouseAndKeyPlugin");
00093 
00094         // Add context menu entry
00095 
00096         // Create submenu
00097         contextMenuEntry_ = new QMenu("Mouse and key plugin");
00098 
00099         QAction* lastAction;
00100 
00101         // Add action to recently created menu
00102         lastAction = contextMenuEntry_->addAction( "Hide object" );
00103         lastAction->setToolTip("Hide selected object");
00104         lastAction->setStatusTip( lastAction->toolTip() );
00105 
00106         // Finally insert created context submenu to OpenFlipper's context menu
00107         // We want our action to be visible for triangle and polygon meshes
00108         emit addContextMenuItem(contextMenuEntry_->menuAction() , DATA_TRIANGLE_MESH , CONTEXTOBJECTMENU );
00109         emit addContextMenuItem(contextMenuEntry_->menuAction() , DATA_POLY_MESH , CONTEXTOBJECTMENU );
00110 
00111         // Connect the created context menu entry to local function contextMenuItemSelected(QAction*)
00112         connect(contextMenuEntry_, SIGNAL(triggered(QAction*)), this, SLOT(contextMenuItemSelected(QAction*)));
00113 
00114 } // End pluginsInitialized
00115 
00116 
00117 /*
00118  * Is called when button in toolbox has been clicked
00119  */
00120 void MouseAndKeyPlugin::slotButtonClicked() {
00121 
00122         if(pickButton_->isChecked()) {
00123                 // Picking mode of our plugin shall be activated
00124                 // set OpenFlipper's action mode to picking
00125                 PluginFunctions::actionMode( Viewer::PickingMode );
00126 
00127                 // Now activate our picking mode
00128                 PluginFunctions::pickMode( "MouseAndKeyPlugin" );
00129         } else {
00130                 // Picking mode shall be deactivated
00131                 PluginFunctions::actionMode( Viewer::ExamineMode );
00132         }
00133 
00134 } // End slotButtonClicked
00135 
00136 /*
00137  * Is called when pick mode is changed in OpenFlipper
00138  */
00139 void MouseAndKeyPlugin::slotPickModeChanged(const std::string& _mode) {
00140 
00141         // Set button checked if pick mode is our
00142         // plugin's pick mode
00143         pickButton_->setChecked(_mode == "MouseAndKeyPlugin");
00144 
00145 } // End slotPickModeChanged
00146 
00147 /*
00148  * Is called each time the mouse has moved or been clicked
00149  */
00150 void MouseAndKeyPlugin::slotMouseEvent(QMouseEvent* _event) {
00151 
00152         if ( PluginFunctions::pickMode() == "MouseAndKeyPlugin" &&
00153                 PluginFunctions::actionMode() == Viewer::PickingMode ) {
00154 
00155                 // If double click has been performed
00156                 if (_event->type() == QEvent::MouseButtonDblClick) {
00157 
00158                         unsigned int node_idx, target_idx;
00159                         OpenMesh::Vec3d hitPoint;
00160 
00161                         // Get picked object's identifier
00162                         if ( PluginFunctions::scenegraphPick(ACG::SceneGraph::PICK_ANYTHING,_event->pos(), node_idx, target_idx, &hitPoint) ) {
00163 
00164                                 BaseObjectData* object;
00165 
00166                                 // Get picked object
00167                                 if ( PluginFunctions::getPickedObject(node_idx, object) ) {
00168 
00169                                         // Show small dialog window
00170                                         QDialog* dlg = new QDialog;
00171 
00172                                         QGridLayout* grid = new QGridLayout;
00173                                         QLabel* label = new QLabel;
00174                                         QString str = QString("You selected object ");
00175                                         str += QString::number(node_idx);
00176                                         label->setText(str);
00177                                         grid->addWidget(label, 0,0);
00178 
00179                                         dlg->setLayout(grid);
00180 
00181                                         dlg->show();
00182 
00183                                         // Set last selected object
00184                                         activeObject_ = node_idx;
00185                                 }
00186                                 else {
00187                                         emit log(LOGINFO, "Picking failed");
00188                                 }
00189                         }
00190 
00191                         return;
00192                 }
00193 
00194                 // Continue traversing scene graph
00195                 ACG::SceneGraph::MouseEventAction action(_event);
00196                 PluginFunctions::traverse(action);
00197         }
00198 
00199 } // End slotMouseEvent
00200 
00201 /*
00202  * Is called when a key on the keyboard is pressed
00203  */
00204 void MouseAndKeyPlugin::slotKeyEvent( QKeyEvent* _event ) {
00205 
00206         BaseObjectData* object;
00207 
00208         // Get last clicked object (selected in pick mode)
00209         if ( PluginFunctions::getPickedObject(activeObject_, object) ) {
00210 
00211                 // Switch pressed keys
00212                 switch (_event->key())
00213                 {
00214                         case Qt::Key_W:
00215 
00216                                 object->manipulatorNode()->loadIdentity();
00217                                 object->manipulatorNode()->rotate(10.0, axis_x_);
00218 
00219                                 break;
00220 
00221                         case Qt::Key_S :
00222 
00223                                 object->manipulatorNode()->loadIdentity();
00224                                 object->manipulatorNode()->rotate(-10.0, axis_x_);
00225 
00226                                 break;
00227 
00228                         case Qt::Key_A :
00229 
00230                                 object->manipulatorNode()->loadIdentity();
00231                                 object->manipulatorNode()->rotate(10.0, axis_y_);
00232 
00233                                 break;
00234 
00235                         case Qt::Key_D :
00236 
00237                                 object->manipulatorNode()->loadIdentity();
00238                                 object->manipulatorNode()->rotate(-10.0, axis_y_);
00239 
00240                                 break;
00241 
00242                         default:
00243                         break;
00244                 }
00245 
00246                 // Perform rotation
00247                 if ( object->dataType( DATA_TRIANGLE_MESH ) )
00248                         transformMesh(object->manipulatorNode()->matrix(), (*PluginFunctions::triMesh(object)));
00249                 if ( object->dataType( DATA_POLY_MESH ) )
00250                         transformMesh(object->manipulatorNode()->matrix(), (*PluginFunctions::polyMesh(object)));
00251 
00252                 // Tell core that object has been modified
00253                 updatedObject(object->id());
00254 
00255                 // Update view
00256                 emit updateView();
00257         } else {
00258                 emit log(LOGINFO, "No object has been selected to rotate! Select object first.");
00259         }
00260 
00261 } // End slotKeyEvent
00262 
00263 /*
00264  * Transform a mesh with the given transformation matrix
00265  *
00266  * _mat : transformation matrix
00267  * _mesh : the mesh
00268  */
00269 template<typename MeshT>
00270 void MouseAndKeyPlugin::transformMesh(ACG::Matrix4x4d _mat, MeshT& _mesh) {
00271 
00272         typename MeshT::VertexIter v_it = _mesh.vertices_begin();
00273         typename MeshT::VertexIter v_end = _mesh.vertices_end();
00274 
00275         // Iterator over all vertices and transform them by _mat
00276         // Update normals
00277         for (; v_it != v_end; ++v_it) {
00278                 _mesh.set_point(v_it, (typename MeshT::Point) _mat.transform_point(
00279                                 (OpenMesh::Vec3d)(_mesh.point(v_it))));
00280                 _mesh.set_normal(v_it, (typename MeshT::Point) _mat.transform_vector(
00281                                 (OpenMesh::Vec3d)(_mesh.normal(v_it))));
00282         }
00283 
00284         typename MeshT::FaceIter f_it = _mesh.faces_begin();
00285         typename MeshT::FaceIter f_end = _mesh.faces_end();
00286 
00287         // Iterate over all faces and update face normals
00288         for (; f_it != f_end; ++f_it)
00289                 _mesh.set_normal(f_it, (typename MeshT::Point) _mat.transform_vector(
00290                                 (OpenMesh::Vec3d)(_mesh.normal(f_it))));
00291 
00292 } // End transformMesh
00293 
00294 /*
00295  * Is called when context menu entry has been clicked
00296  */
00297 void MouseAndKeyPlugin::contextMenuItemSelected(QAction* _action) {
00298 
00299         // Get object id from QAction object
00300         QVariant contextObject = _action->data();
00301         int objectId = contextObject.toInt();
00302 
00303         if (objectId == -1) {
00304 
00305                 log(LOGINFO, "Could not get associated object id.");
00306                 return;
00307         }
00308 
00309         // Get node associated to object id
00310         ACG::SceneGraph::BaseNode* node = ACG::SceneGraph::find_node(
00311                         PluginFunctions::getSceneGraphRootNode(), objectId);
00312 
00313         // Return if node id was not valid
00314         if (!node) {
00315 
00316                 log(LOGINFO, "Could not find associated object.");
00317                 return;
00318         }
00319 
00320         BaseObjectData* obj;
00321         if (!PluginFunctions::getObject(objectId, obj))
00322                 return;
00323 
00324         // Hide object
00325         obj->hide();
00326 
00327 } // End contextMenuItemSelected
00328 
00329 Q_EXPORT_PLUGIN2( mouseandkeyplugin , MouseAndKeyPlugin );
00330 

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