Developer Documentation
MouseAndKeyPlugin.cc
1 //=============================================================================
2 //
3 // OpenFlipper
4 // Copyright (C) 2008 by Computer Graphics Group, RWTH Aachen
5 // www.openflipper.org
6 //
7 //-----------------------------------------------------------------------------
8 //
9 // License
10 //
11 // OpenFlipper is free software: you can redistribute it and/or modify
12 // it under the terms of the GNU Lesser General Public License as published by
13 // the Free Software Foundation, either version 3 of the License, or
14 // (at your option) any later version.
15 //
16 // OpenFlipper is distributed in the hope that it will be useful,
17 // but WITHOUT ANY WARRANTY; without even the implied warranty of
18 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 // GNU Lesser General Public License for more details.
20 //
21 // You should have received a copy of the GNU Lesser General Public License
22 // along with OpenFlipper. If not, see <http://www.gnu.org/licenses/>.
23 //
24 //-----------------------------------------------------------------------------
25 //
26 // $Revision$
27 // $Author$
28 // $Date$
29 //
30 //=============================================================================
31 
32 #include "MouseAndKeyPlugin.hh"
33 
34 
37 
39 
40 /*
41  * Constructor
42  */
43 MouseAndKeyPlugin::MouseAndKeyPlugin() :
44  contextMenuEntry_(0),
45  tool_(0),
46  pickButton_(0),
47  activeObject_(-1),
48  axis_x_(ACG::Vec3d(1.0, 0.0, 0.0)),
49  axis_y_(ACG::Vec3d(0.0, 1.0, 0.0))
50 {
51 
52 }
53 
54 /*
55  * Initialize plugin
56  */
57 void MouseAndKeyPlugin::initializePlugin() {
58 
59  // Register keys
60  emit registerKey(Qt::Key_J, Qt::NoModifier, "Rotate object down");
61  emit registerKey(Qt::Key_K, Qt::NoModifier, "Rotate object up");
62  emit registerKey(Qt::Key_H, Qt::NoModifier, "Rotate object left");
63  emit registerKey(Qt::Key_L, Qt::NoModifier, "Rotate object right");
64 
65  tool_ = new QWidget();
66  QSize size(300, 300);
67  tool_->resize(size);
68 
69  // Create button that can be toggled
70  // to (de)activate plugin's picking mode
71  pickButton_ = new QPushButton(tr("Select object"));
72  pickButton_->setCheckable(true);
73 
74  // Create label
75  QLabel* label = new QLabel();
76  label->setText("(De)activate pick mode");
77 
78  // Set label to be above the button
79  QGridLayout* grid = new QGridLayout;
80  grid->addWidget(label, 0, 0);
81  grid->addWidget(pickButton_, 1, 0);
82 
83  tool_->setLayout(grid);
84 
85  // Connect button to slotButtonClicked()
86  connect(pickButton_, SIGNAL(clicked()), this, SLOT(slotButtonClicked()));
87 
88  // Add the Toolbox
89  emit addToolbox(tr("Mouse and Key"), tool_);
90 
91 } // End initializePlugin
92 
93 /*
94  * Is called after all plugins have been initialized
95  */
96 void MouseAndKeyPlugin::pluginsInitialized() {
97 
98  // Add pickmode
99  emit addPickMode("MouseAndKeyPlugin");
100 
101  // Add context menu entry
102 
103  // Create submenu
104  contextMenuEntry_ = new QMenu("Mouse and key plugin");
105 
106  QAction* lastAction;
107 
108  // Add action to recently created menu
109  lastAction = contextMenuEntry_->addAction( "Hide object" );
110  lastAction->setToolTip("Hide selected object");
111  lastAction->setStatusTip( lastAction->toolTip() );
112 
113  // Finally insert created context submenu to OpenFlipper's context menu
114  // We want our action to be visible for triangle and polygon meshes
115  emit addContextMenuItem(contextMenuEntry_->menuAction() , DATA_TRIANGLE_MESH , CONTEXTOBJECTMENU );
116  emit addContextMenuItem(contextMenuEntry_->menuAction() , DATA_POLY_MESH , CONTEXTOBJECTMENU );
117 
118  // Connect the created context menu entry to local function contextMenuItemSelected(QAction*)
119  connect(contextMenuEntry_, SIGNAL(triggered(QAction*)), this, SLOT(contextMenuItemSelected(QAction*)));
120 
121 } // End pluginsInitialized
122 
123 
124 /*
125  * Is called when button in toolbox has been clicked
126  */
127 void MouseAndKeyPlugin::slotButtonClicked() {
128 
129  if(pickButton_->isChecked()) {
130  // Picking mode of our plugin shall be activated
131  // set OpenFlipper's action mode to picking
132  PluginFunctions::actionMode( Viewer::PickingMode );
133 
134  // Now activate our picking mode
135  PluginFunctions::pickMode( "MouseAndKeyPlugin" );
136  } else {
137  // Picking mode shall be deactivated
138  PluginFunctions::actionMode( Viewer::ExamineMode );
139  }
140 
141 } // End slotButtonClicked
142 
143 /*
144  * Is called when pick mode is changed in OpenFlipper
145  */
146 void MouseAndKeyPlugin::slotPickModeChanged(const std::string& _mode) {
147 
148  // Set button checked if pick mode is our
149  // plugin's pick mode
150  pickButton_->setChecked(_mode == "MouseAndKeyPlugin");
151 
152 } // End slotPickModeChanged
153 
154 /*
155  * Is called each time the mouse has moved or been clicked
156  */
157 void MouseAndKeyPlugin::slotMouseEvent(QMouseEvent* _event) {
158 
159  if ( PluginFunctions::pickMode() == "MouseAndKeyPlugin" &&
160  PluginFunctions::actionMode() == Viewer::PickingMode ) {
161 
162  // If double click has been performed
163  if (_event->type() == QEvent::MouseButtonDblClick) {
164 
165  unsigned int node_idx, target_idx;
166  OpenMesh::Vec3d hitPoint;
167 
168  // Get picked object's identifier
169  if ( PluginFunctions::scenegraphPick(ACG::SceneGraph::PICK_ANYTHING,_event->pos(), node_idx, target_idx, &hitPoint) ) {
170 
171  BaseObjectData* object;
172 
173  // Get picked object
174  if ( PluginFunctions::getPickedObject(node_idx, object) ) {
175 
176  // Show small dialog window
177  QDialog* dlg = new QDialog;
178 
179  QGridLayout* grid = new QGridLayout;
180  QLabel* label = new QLabel;
181  QString str = QString("You selected object ");
182  str += QString::number(node_idx);
183  label->setText(str);
184  grid->addWidget(label, 0,0);
185 
186  dlg->setLayout(grid);
187 
188  dlg->show();
189 
190  // Set last selected object
191  activeObject_ = node_idx;
192  }
193  else {
194  emit log(LOGINFO, "Picking failed");
195  }
196  }
197 
198  return;
199  }
200 
201  // Continue traversing scene graph
204  }
205 
206 } // End slotMouseEvent
207 
208 /*
209  * Is called when a key on the keyboard is pressed
210  */
211 void MouseAndKeyPlugin::slotKeyEvent( QKeyEvent* _event ) {
212 
213  BaseObjectData* object;
214 
215  // Get last clicked object (selected in pick mode)
216  if ( PluginFunctions::getPickedObject(activeObject_, object) ) {
217 
218  // Switch pressed keys
219  switch (_event->key())
220  {
221  case Qt::Key_J:
222 
223  object->manipulatorNode()->loadIdentity();
224  object->manipulatorNode()->rotate(10.0, axis_x_);
225 
226  break;
227 
228  case Qt::Key_K :
229 
230  object->manipulatorNode()->loadIdentity();
231  object->manipulatorNode()->rotate(-10.0, axis_x_);
232 
233  break;
234 
235  case Qt::Key_H :
236 
237  object->manipulatorNode()->loadIdentity();
238  object->manipulatorNode()->rotate(10.0, axis_y_);
239 
240  break;
241 
242  case Qt::Key_L :
243 
244  object->manipulatorNode()->loadIdentity();
245  object->manipulatorNode()->rotate(-10.0, axis_y_);
246 
247  break;
248 
249  default:
250  break;
251  }
252 
253  // Perform rotation
254  if ( object->dataType( DATA_TRIANGLE_MESH ) )
256  if ( object->dataType( DATA_POLY_MESH ) )
258 
259  // Tell core that object has been modified
260  emit updatedObject(object->id(), UPDATE_GEOMETRY);
261 
262  // Update view
263  emit updateView();
264  } else {
265  emit log(LOGINFO, "No object has been selected to rotate! Select object first.");
266  }
267 
268 } // End slotKeyEvent
269 
270 /*
271  * Transform a mesh with the given transformation matrix
272  *
273  * _mat : transformation matrix
274  * _mesh : the mesh
275  */
276 template<typename MeshT>
277 void MouseAndKeyPlugin::transformMesh(ACG::Matrix4x4d _mat, MeshT& _mesh) {
278 
279  typename MeshT::VertexIter v_it = _mesh.vertices_begin();
280  typename MeshT::VertexIter v_end = _mesh.vertices_end();
281 
282  // Iterator over all vertices and transform them by _mat
283  // Update normals
284  for (; v_it != v_end; ++v_it) {
285  _mesh.set_point(v_it, (typename MeshT::Point) _mat.transform_point(
286  (OpenMesh::Vec3d)(_mesh.point(v_it))));
287  _mesh.set_normal(v_it, (typename MeshT::Point) _mat.transform_vector(
288  (OpenMesh::Vec3d)(_mesh.normal(v_it))));
289  }
290 
291  typename MeshT::FaceIter f_it = _mesh.faces_begin();
292  typename MeshT::FaceIter f_end = _mesh.faces_end();
293 
294  // Iterate over all faces and update face normals
295  for (; f_it != f_end; ++f_it)
296  _mesh.set_normal(f_it, (typename MeshT::Point) _mat.transform_vector(
297  (OpenMesh::Vec3d)(_mesh.normal(f_it))));
298 
299 } // End transformMesh
300 
301 /*
302  * Is called when context menu entry has been clicked
303  */
304 void MouseAndKeyPlugin::contextMenuItemSelected(QAction* _action) {
305 
306  // Get object id from QAction object
307  QVariant contextObject = _action->data();
308  int objectId = contextObject.toInt();
309 
310  if (objectId == -1) {
311 
312  log(LOGINFO, "Could not get associated object id.");
313  return;
314  }
315 
316  // Get node associated to object id
319 
320  // Return if node id was not valid
321  if (!node) {
322 
323  log(LOGINFO, "Could not find associated object.");
324  return;
325  }
326 
327  BaseObjectData* obj;
328  if (!PluginFunctions::getObject(objectId, obj))
329  return;
330 
331  // Hide object
332  obj->hide();
333 
334 } // End contextMenuItemSelected
335 
336 Q_EXPORT_PLUGIN2( mouseandkeyplugin , MouseAndKeyPlugin );
337 
void traverse(ACG::SceneGraph::MouseEventAction &_action)
BaseNode * find_node(BaseNode *_root, unsigned int _node_idx)
Find a node in the scene graph.
Definition: SceneGraph.cc:83
bool scenegraphPick(ACG::SceneGraph::PickTarget _pickTarget, const QPoint &_mousePos, unsigned int &_nodeIdx, unsigned int &_targetIdx, ACG::Vec3d *_hitPointPtr=0)
Execute picking operation on scenegraph.
void transformMesh(ACG::Matrix4x4d _matrix, MeshT &_mesh)
virtual void hide()
Sets the whole Scenegraph subtree of this node to invisible.
VectorT< T, 3 > transform_point(const VectorT< T, 3 > &_v) const
transform point (x&#39;,y&#39;,z&#39;,1) = M * (x,y,z,1)
Definition: Matrix4x4T.cc:202
bool getObject(int _identifier, BSplineCurveObject *&_object)
PolyMesh * polyMesh(BaseObjectData *_object)
Get a poly mesh from an object.
bool dataType(DataType _type) const
Definition: BaseObject.cc:232
The Menu will be shown when an object was picked.
int id() const
Definition: BaseObject.cc:201
bool getPickedObject(const unsigned int _node_idx, BaseObjectData *&_object)
Get the picked mesh.
QtTranslationManipulatorNode * manipulatorNode()
void addToolbox(QString _name, QWidget *_widget)
Add a Toolbox from a plugin or from scripting.
Definition: scripting.cc:256
const GLMatrixd & matrix() const
Returns a const reference to the current transformation matrix.
const std::string pickMode()
Get the current Picking mode.
Viewer::ViewerProperties & viewerProperties(int _id)
Get the viewer properties Use this functions to get basic viewer properties such as backgroundcolor o...
const UpdateType UPDATE_GEOMETRY(UpdateTypeSet(1)<< 2)
Geometry updated.
Namespace providing different geometric functions concerning angles.
Definition: DBSCANT.cc:51
Viewer::ActionMode actionMode()
Get the current Action mode.
void updateView()
Called when a plugin requests an update in the viewer.
Definition: Core.cc:887
void log(Logtype _type, QString _message)
Logg with OUT,WARN or ERR as type.
pick any of the prior targets (should be implemented for all nodes)
Definition: BaseNode.hh:110
ACG::SceneGraph::BaseNode * getSceneGraphRootNode()
get scenegraph root node
#define DATA_POLY_MESH
Definition: PolyMesh.hh:65
VectorT< double, 3 > Vec3d
Definition: VectorT.hh:127
#define DATA_TRIANGLE_MESH
Definition: TriangleMesh.hh:66
VectorT< T, 3 > transform_vector(const VectorT< T, 3 > &_v) const
transform vector (x&#39;,y&#39;,z&#39;,0) = A * (x,y,z,0)
Definition: Matrix4x4T.cc:225
TriMesh * triMesh(BaseObjectData *_object)
Get a triangle mesh from an object.