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