Developer Documentation
Loading...
Searching...
No Matches
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 */
40MouseAndKeyPlugin::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 */
54void 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 */
93void 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 */
124void 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 */
143void 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 */
154void 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 */
208void 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 */
273template<typename MeshT>
274void 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 */
301void 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
@ CONTEXTOBJECTMENU
The Menu will be shown when an object was picked.
@ LOGINFO
#define DATA_POLY_MESH
Definition PolyMesh.hh:59
#define DATA_TRIANGLE_MESH
VectorT< T, 3 > transform_vector(const VectorT< T, 3 > &_v) const
transform vector (x',y',z',0) = A * (x,y,z,0)
VectorT< T, 3 > transform_point(const VectorT< T, 3 > &_v) const
transform point (x',y',z',1) = M * (x,y,z,1)
const GLMatrixd & matrix() const
Returns a const reference to the current transformation matrix.
virtual void hide()
Sets the whole Scenegraph subtree of this node to invisible.
QtTranslationManipulatorNode * manipulatorNode()
bool dataType(DataType _type) const
int id() const
PointT normal(HalfFaceHandle _hfh) const
const UpdateType UPDATE_GEOMETRY(UpdateTypeSet(4))
Geometry updated.
BaseNode * find_node(BaseNode *_root, unsigned int _node_idx)
Find a node in the scene graph.
Definition SceneGraph.cc:77
@ PICK_ANYTHING
pick any of the prior targets (should be implemented for all nodes)
Definition PickTarget.hh:84
Namespace providing different geometric functions concerning angles.
Viewer::ViewerProperties & viewerProperties(int _id)
Get the viewer properties Use this functions to get basic viewer properties such as backgroundcolor o...
bool getObject(const int _identifier, BaseObject *&_object)
Get the object which has the given identifier.
TriMesh * triMesh(BaseObjectData *_object)
Get a triangle mesh from an object.
const std::string pickMode()
Get the current Picking mode.
PolyMesh * polyMesh(BaseObjectData *_object)
Get a poly mesh from an object.
bool getPickedObject(const size_t _node_idx, BaseObjectData *&_object)
Get the picked mesh.
void traverse(ACG::SceneGraph::MouseEventAction &_action)
bool scenegraphPick(ACG::SceneGraph::PickTarget _pickTarget, const QPoint &_mousePos, size_t &_nodeIdx, size_t &_targetIdx, ACG::Vec3d *_hitPointPtr=0)
Execute picking operation on scenegraph.
Viewer::ActionMode actionMode()
Get the current Action mode.
ACG::SceneGraph::BaseNode * getSceneGraphRootNode()
get scenegraph root node