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
32 #include <ObjectTypes/PolyMesh/PolyMesh.hh>
33 #include <ObjectTypes/TriangleMesh/TriangleMesh.hh>
34
35 #include "OpenFlipper/BasePlugin/PluginFunctions.hh"
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
199 ACG::SceneGraph::MouseEventAction action(_event, PluginFunctions::viewerProperties().glState());
200 PluginFunctions::traverse(action);
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 ) )
252 transformMesh(object->manipulatorNode()->matrix(), (*PluginFunctions::triMesh(object)));
253 if ( object->dataType( DATA_POLY_MESH ) )
254 transformMesh(object->manipulatorNode()->matrix(), (*PluginFunctions::polyMesh(object)));
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
314 ACG::SceneGraph::BaseNode* node = ACG::SceneGraph::find_node(
315 PluginFunctions::getSceneGraphRootNode(), objectId);
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
PluginFunctions::scenegraphPick
bool scenegraphPick(ACG::SceneGraph::PickTarget _pickTarget, const QPoint &_mousePos, size_t &_nodeIdx, size_t &_targetIdx, ACG::Vec3d *_hitPointPtr=0)
Execute picking operation on scenegraph.
Definition: PluginFunctions.cc:480
UPDATE_GEOMETRY
const UpdateType UPDATE_GEOMETRY(UpdateTypeSet(1)<< 2)
Geometry updated.
DATA_TRIANGLE_MESH
#define DATA_TRIANGLE_MESH
Definition: TriangleMesh.hh:60
DATA_POLY_MESH
#define DATA_POLY_MESH
Definition: PolyMesh.hh:59
PluginFunctions::polyMesh
PolyMesh * polyMesh(BaseObjectData *_object)
Get a poly mesh from an object.
Definition: PluginFunctionsPolyMesh.cc:128
ACG
Namespace providing different geometric functions concerning angles.
Definition: BaseObjectData.hh:68
ACG::SceneGraph::TransformNode::matrix
const GLMatrixd & matrix() const
Returns a const reference to the current transformation matrix.
Definition: TransformNode.hh:158
PluginFunctions::getObject
bool getObject(const int _identifier, BaseObject *&_object)
Get the object which has the given identifier.
Definition: PluginFunctions.cc:296
PluginFunctions::getSceneGraphRootNode
ACG::SceneGraph::BaseNode * getSceneGraphRootNode()
get scenegraph root node
Definition: PluginFunctions.cc:959
OpenMesh::VectorT
Definition: Vector11T.hh:83
PluginFunctions::triMesh
TriMesh * triMesh(BaseObjectData *_object)
Get a triangle mesh from an object.
Definition: PluginFunctionsTriangleMesh.cc:134
PluginFunctions.hh
ACG::Matrix4x4T::transform_point
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_impl.hh:196
BaseObject::id
int id() const
Definition: BaseObject.cc:190
Core::log
void log(Logtype _type, QString _message)
Logg with OUT,WARN or ERR as type.
BaseObject::dataType
bool dataType(DataType _type) const
Definition: BaseObject.cc:221
ACG::SceneGraph::TransformNode::loadIdentity
void loadIdentity()
Definition: TransformNode.cc:91
BaseObjectData::manipulatorNode
QtTranslationManipulatorNode * manipulatorNode()
Definition: BaseObjectData.cc:255
MeshFunctions::transformMesh
void transformMesh(ACG::Matrix4x4d _matrix, MeshT &_mesh)
Definition: MeshFunctionsT_impl.hh:231
TriangleMesh.hh
PluginFunctions::actionMode
Viewer::ActionMode actionMode()
Get the current Action mode.
Definition: PluginFunctions.cc:588
ACG::SceneGraph::PICK_ANYTHING
pick any of the prior targets (should be implemented for all nodes)
Definition: PickTarget.hh:84
ACG::Matrix4x4T::transform_vector
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_impl.hh:219
ACG::SceneGraph::find_node
BaseNode * find_node(BaseNode *_root, unsigned int _node_idx)
Find a node in the scene graph.
Definition: SceneGraph.cc:77
BaseObjectData::hide
virtual void hide()
Sets the whole Scenegraph subtree of this node to invisible.
Definition: BaseObjectData.cc:197
ACG::Matrix4x4T< double >
ACG::SceneGraph::BaseNode
Definition: BaseNode.hh:104
BaseObjectData
Definition: BaseObjectData.hh:102
PluginFunctions::traverse
void traverse(ACG::SceneGraph::MouseEventAction &_action)
Definition: PluginFunctions.cc:571
PluginFunctions::pickMode
const std::string pickMode()
Get the current Picking mode.
Definition: PluginFunctions.cc:577
PolyMesh.hh
Core::updateView
void updateView()
Called when a plugin requests an update in the viewer.
Definition: Core.cc:943
ACG::SceneGraph::MouseEventAction
Definition: SceneGraph.hh:799
PluginFunctions::viewerProperties
Viewer::ViewerProperties & viewerProperties(int _id)
Get the viewer properties Use this functions to get basic viewer properties such as backgroundcolor o...
Definition: PluginFunctions.cc:611
Core::addToolbox
void addToolbox(QString _name, QWidget *_widget)
Add a Toolbox from a plugin or from scripting.
Definition: scripting.cc:253
PluginFunctions::getPickedObject
bool getPickedObject(const size_t _node_idx, BaseObjectData *&_object)
Get the picked mesh.
Definition: PluginFunctions.cc:261
CONTEXTOBJECTMENU
The Menu will be shown when an object was picked.
Definition: ContextMenuInterface.hh:59
ACG::Vec3d
VectorT< double, 3 > Vec3d
Definition: VectorT.hh:121
LOGINFO
Definition: LoggingInterface.hh:94