Developer Documentation
MovePlugin.cc
1 /*===========================================================================*\
2 * *
3 * OpenFlipper *
4  * Copyright (c) 2001-2015, RWTH-Aachen University *
5  * Department of Computer Graphics and Multimedia *
6  * All rights reserved. *
7  * www.openflipper.org *
8  * *
9  *---------------------------------------------------------------------------*
10  * This file is part of OpenFlipper. *
11  *---------------------------------------------------------------------------*
12  * *
13  * Redistribution and use in source and binary forms, with or without *
14  * modification, are permitted provided that the following conditions *
15  * are met: *
16  * *
17  * 1. Redistributions of source code must retain the above copyright notice, *
18  * this list of conditions and the following disclaimer. *
19  * *
20  * 2. Redistributions in binary form must reproduce the above copyright *
21  * notice, this list of conditions and the following disclaimer in the *
22  * documentation and/or other materials provided with the distribution. *
23  * *
24  * 3. Neither the name of the copyright holder nor the names of its *
25  * contributors may be used to endorse or promote products derived from *
26  * this software without specific prior written permission. *
27  * *
28  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *
29  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *
30  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
31  * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER *
32  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, *
33  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, *
34  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR *
35  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
36  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING *
37  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS *
38  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
39 * *
40 \*===========================================================================*/
41 
42 /*===========================================================================*\
43 * *
44 * $Revision$ *
45 * $LastChangedBy$ *
46 * $Date$ *
47 * *
48 \*===========================================================================*/
49 
50 
51 #include "MovePlugin.hh"
52 
53 #include <MeshTools/MeshInfoT.hh>
54 
55 #ifdef USE_OPENMP
56 #endif
57 
58 #if QT_VERSION >= 0x050000
59 #else
60 #include <QtGui>
61 #endif
62 
63 #ifdef ENABLE_POLYLINE_SUPPORT
65 #endif
66 
67 #ifdef ENABLE_TSPLINEMESH_SUPPORT
68 #include <ObjectTypes/TSplineMesh/TSplineMesh.hh>
69 #endif
70 
71 #ifdef ENABLE_SKELETON_SUPPORT
72 #include <ObjectTypes/Skeleton/Helper/SkeletonTransform.hh>
73 #endif
74 
75 #ifdef ENABLE_OPENVOLUMEMESH_HEXAHEDRAL_SUPPORT
77 #endif
78 
79 #ifdef ENABLE_OPENVOLUMEMESH_TETRAHEDRAL_SUPPORT
81 #endif
82 
83 #ifdef ENABLE_OPENVOLUMEMESH_POLYHEDRAL_SUPPORT
85 #endif
86 
91 axisA_(0),
92 axisB_(1),
93 toolboxActive_(false),
94 tool_(0),
95 toolIcon_(0),
96 moveAction_(0),
97 moveSelectionAction_(0),
98 toolBarActions_(0),
99 toolbar_(0),
100 pickToolbar_(0),
101 placeAction_(0),
102 rotateTranslateAction_(0),
103 rotateManipAction_(0),
104 resizeAction_(0),
105 biggerManipAction_(0),
106 smallerManipAction_(0),
107 fixChildManipAction_(0),
108 transformRefPoseManipAction_(0),
109 currentPoseManipAction_(0),
110 placeAndSnapAction_(0),
111 pickToolBarActions_(0),
112 manip_size_(1.0),
113 manip_size_modifier_(1.0),
114 lastActiveManipulator_(-1),
115 manMode_(QtTranslationManipulatorNode::TranslationRotation),
116 selectionType_(VERTEX),
117 contextAction_(0),
118 contextActionHide_(0),
119 toAllTargets_(0),
120 contextMenuManipControl_(0),
121 contextMenuManipControlsAction_(0),
122 hide_(true),
123 allTargets_(false),
124 placeMode_(false),
125 transformedSelected_(false)
126 {
127 
128 }
129 
134 
135  if(contextAction_) {
136  delete contextAction_;
137  }
138 
139  if(contextActionHide_) {
140  delete contextActionHide_;
141  }
142 
143  if(toAllTargets_) {
144  delete toAllTargets_;
145  }
146 
147  for(QList<movePropsWidget*>::iterator it = propsWindows_.begin();
148  it != propsWindows_.end(); ++it) {
149 
150  if(*it) {
151  delete *it;
152  }
153  }
154 }
155 
156 
157 /*******************************************************************************
158  BaseInterface implementation
159  *******************************************************************************/
160 
165 
166  //PICKMODES
167  emit addPickMode("Separator");
168  emit addHiddenPickMode("Move");
169  emit setPickModeMouseTracking ("Move", true);
170  emit addHiddenPickMode("MoveSelection");
171  emit setPickModeMouseTracking ("MoveSelection", true);
172 
173  //KEYS
174  emit registerKey (Qt::Key_Shift, Qt::NoModifier, tr("Manipulator rotation"), true);
175  emit registerKey (Qt::Key_Shift, Qt::ShiftModifier, tr("Manipulator rotation"), true);
176  emit registerKey (Qt::Key_Shift, Qt::ControlModifier | Qt::ShiftModifier, tr("Manipulator rotation"), true);
177  emit registerKey (Qt::Key_Control, Qt::NoModifier, tr("Resize"), true);
178  emit registerKey (Qt::Key_Control, Qt::ControlModifier, tr("Resize"), true);
179  emit registerKey (Qt::Key_Control, Qt::ShiftModifier | Qt::ControlModifier, tr("Resize"), true);
180 
181  //SCRIPTING SLOT DESCRIPTIONS
182  setDescriptions();
183 
184  // ==================================
185  // Toolbar
186  // ==================================
187 
188  WhatsThisGenerator whatsThis("Move");
189  WhatsThisGenerator whatsThisUser("user");
190 
191  toolbar_ = new QToolBar(tr("Transform and Move"));
192  toolbar_->setObjectName("TransformAndMoveToolBar");
193 
194  toolBarActions_ = new QActionGroup(toolbar_);
195 
196  moveAction_ = new QAction(tr("<B>Move Object</B><br>Move an object in 3D"), toolBarActions_);
197  moveAction_->setStatusTip(tr("Move object in 3D."));
198  moveAction_->setIcon(QIcon(OpenFlipper::Options::iconDirStr()+OpenFlipper::Options::dirSeparator()+"move-objects.png") );
199  moveAction_->setCheckable(true);
200  whatsThis.setWhatsThis(moveAction_,tr("Move the whole object."));
201  toolbar_->addAction(moveAction_);
202 
203  moveSelectionAction_ = new QAction(tr("<B>Move Selection</B><br>Move a selection on an object"), toolBarActions_);
204  moveSelectionAction_->setStatusTip(tr("Move selections in 3D."));
205  moveSelectionAction_->setIcon(QIcon(OpenFlipper::Options::iconDirStr()+OpenFlipper::Options::dirSeparator()+"move-selections.png") );
206  moveSelectionAction_->setCheckable(true);
207  whatsThis.setWhatsThis(moveSelectionAction_,tr("Move only a selection."));
208  toolbar_->addAction(moveSelectionAction_);
209 
210  connect(toolBarActions_, SIGNAL(triggered(QAction*)), this, SLOT(slotSetMoveMode(QAction*)) );
211 
212  emit addToolbar(toolbar_);
213 
214  // ==================================
215  // Pick Toolbar
216  // ==================================
217 
218  pickToolbar_ = new QToolBar(tr("Transform and Move PickTool bar"));
219  pickToolbar_->setObjectName("TransformAndMovePickToolBar");
220 
221  pickToolbar_->setAttribute(Qt::WA_AlwaysShowToolTips, true);
222  pickToolBarActions_ = new QActionGroup(pickToolbar_);
223  pickToolBarActions_->setExclusive (false);
224 
225  placeAction_ = new QAction(tr("Place manipulator"), pickToolBarActions_);
226  placeAction_->setStatusTip(tr("Place manipulator on object. <Doubleclick>"));
227  placeAction_->setToolTip(tr("Place manipulator on object. <Doubleclick>"));
228  placeAction_->setIcon(QIcon(OpenFlipper::Options::iconDirStr()+OpenFlipper::Options::dirSeparator()+"move-place.png") );
229  whatsThisUser.setWhatsThis(placeAction_,tr("Place the manipulator."),"obj_man","manipulator.html");
230  placeAction_->setCheckable(true);
231  pickToolbar_->addAction(placeAction_);
232 
233  pickToolbar_->addSeparator ();
234 
235  rotateTranslateAction_ = new QAction(tr("Rotate/Translate object"), pickToolBarActions_);
236  rotateTranslateAction_->setStatusTip(tr("Rotate/Translate object."));
237  rotateTranslateAction_->setToolTip(tr("Rotate/Translate object."));
238  rotateTranslateAction_->setIcon(QIcon(OpenFlipper::Options::iconDirStr()+OpenFlipper::Options::dirSeparator()+"move-translaterotate.png") );
239  rotateTranslateAction_->setCheckable(true);
240  rotateTranslateAction_->setChecked(true);
241  whatsThisUser.setWhatsThis(rotateTranslateAction_,tr("Rotate or translate an object or selection."),"obj_translation","manipulator.html");
243 
244  resizeAction_ = new QAction(tr("Resize object"), pickToolBarActions_);
245  resizeAction_->setStatusTip(tr("Resize object. <Control>"));
246  resizeAction_->setToolTip(tr("Resize object. <Control>"));
247  resizeAction_->setIcon(QIcon(OpenFlipper::Options::iconDirStr()+OpenFlipper::Options::dirSeparator()+"move-resize.png") );
248  whatsThisUser.setWhatsThis(resizeAction_,tr("Resize object or selection."),"obj_resizing","manipulator.html");
249  resizeAction_->setCheckable(true);
250  pickToolbar_->addAction(resizeAction_);
251 
252  pickToolbar_->addSeparator ();
253 
254  rotateManipAction_ = new QAction(tr("Rotate manipulator"), pickToolBarActions_);
255  rotateManipAction_->setStatusTip(tr("Rotate manipulator. <Shift>"));
256  rotateManipAction_->setToolTip(tr("Rotate manipulator. <Shift>"));
257  rotateManipAction_->setIcon(QIcon(OpenFlipper::Options::iconDirStr()+OpenFlipper::Options::dirSeparator()+"move-maniprotate.png") );
258  whatsThisUser.setWhatsThis(rotateManipAction_,tr("Rotate only the Manipulator."),"man_rotating","manipulator.html");
259  rotateManipAction_->setCheckable(true);
260  pickToolbar_->addAction(rotateManipAction_);
261 
262  placeAndSnapAction_ = new QAction(tr("Locally translate manipulator"), pickToolBarActions_);
263  placeAndSnapAction_->setStatusTip(tr("Locally translate manipulator. Press and hold <Alt> for snapping."));
264  whatsThisUser.setWhatsThis(placeAndSnapAction_,tr("Translate only the Manipulator."),"man_translation","manipulator.html");
265  placeAndSnapAction_->setIcon(QIcon(OpenFlipper::Options::iconDirStr()+OpenFlipper::Options::dirSeparator()+"move-placeandsnap.png") );
266  placeAndSnapAction_->setCheckable(true);
267  pickToolbar_->addAction(placeAndSnapAction_);
268 
269  smallerManipAction_ = new QAction(tr("Decrease size of manipulator"), pickToolBarActions_);
270  smallerManipAction_->setStatusTip(tr("Make manipulator smaller. <Mouse wheel up>"));
271  smallerManipAction_->setToolTip(tr("Make manipulator smaller. <Mouse wheel up>"));
272  whatsThisUser.setWhatsThis(smallerManipAction_,tr("Resize the Manipulator to a smaller one."),"man_resizing","manipulator.html");
273  smallerManipAction_->setIcon(QIcon(OpenFlipper::Options::iconDirStr()+OpenFlipper::Options::dirSeparator()+"move-manipsmall.png") );
274  smallerManipAction_->setCheckable(false);
275  pickToolbar_->addAction(smallerManipAction_);
276 
277  biggerManipAction_ = new QAction(tr("Increase size of manipulator"), pickToolBarActions_);
278  biggerManipAction_->setStatusTip(tr("Make manipulator bigger. <Mouse wheel down>"));
279  biggerManipAction_->setToolTip(tr("Make manipulator bigger. <Mouse wheel down>"));
280  whatsThisUser.setWhatsThis(biggerManipAction_,tr("Resize the Manipulator to a bigger one."),"man_resizing","manipulator.html");
281  biggerManipAction_->setIcon(QIcon(OpenFlipper::Options::iconDirStr()+OpenFlipper::Options::dirSeparator()+"move-manipbig.png") );
282  biggerManipAction_->setCheckable(false);
283  pickToolbar_->addAction(biggerManipAction_);
284 
285  connect(pickToolBarActions_, SIGNAL(triggered(QAction*)), this, SLOT(slotPickToolbarAction(QAction*)) );
286 
287  emit setPickModeToolbar ("Move", pickToolbar_);
288  emit setPickModeToolbar ("MoveSelection", pickToolbar_);
289 
290  // ==================================
291  // CONTEXT MENU
292  // ==================================
293  toAllTargets_ = new QAction(tr("Apply to all targets"), this);
294  toAllTargets_->setCheckable(true);
295  toAllTargets_->setToolTip(tr("Apply transformation to all target objects"));
296  toAllTargets_->setStatusTip( toAllTargets_->toolTip() );
297 
298  contextAction_ = new QAction(tr("Set properties"), this);
299  contextAction_->setToolTip(tr("Set properties"));
300  contextAction_->setStatusTip( contextAction_->toolTip() );
301  contextAction_->setIcon(QIcon(OpenFlipper::Options::iconDirStr()+OpenFlipper::Options::dirSeparator()+"move-properties.png") );
302 
303  contextActionHide_ = new QAction(tr("Hide Manipulator"), this);
304  contextActionHide_->setToolTip(tr("Hide Manipulator"));
305  contextActionHide_->setStatusTip( contextActionHide_->toolTip() );
306  contextActionHide_->setIcon(QIcon(OpenFlipper::Options::iconDirStr()+OpenFlipper::Options::dirSeparator()+"move-hide.png") );
307 
308  // QMenu replicating the relevant pick toolbar actions
309  contextMenuManipControl_ = new QMenu(tr("Manipulator Controls"));
316 
317 
319 
320  emit addContextMenuItem(toAllTargets_ , CONTEXTNODEMENU );
321  emit addContextMenuItem(contextAction_ , CONTEXTNODEMENU );
322  emit addContextMenuItem(contextActionHide_ , CONTEXTNODEMENU );
323  emit addContextMenuItem(contextMenuManipControlsAction_ , CONTEXTNODEMENU );
324 
325  connect( toAllTargets_ , SIGNAL(toggled(bool) ), this, SLOT(setAllTargets(bool)));
326  connect( contextAction_ , SIGNAL( triggered() ), this, SLOT(showProps()) );
327  connect( contextActionHide_ , SIGNAL( triggered() ), this, SLOT(hideManipulator()) );
328 }
329 
330 
331 /*******************************************************************************
332  ToolBoxInterface implementation
333  *******************************************************************************/
334 
335 void MovePlugin::initializePlugin()
336 {
337  toolboxActive_ = false;
338  tool_ = new moveToolbarWidget();
339 
340  connect(tool_->moveToOrigin,SIGNAL(clicked() ),this,SLOT(slotMoveToOrigin()));
341 
342  tool_->moveToOrigin->setIcon( QIcon(OpenFlipper::Options::iconDirStr() + OpenFlipper::Options::dirSeparator() + "moveToCOG.png") );
343  tool_->moveToOrigin->setIconSize(QSize(48,48));
344  WhatsThisGenerator whatsThis("Move");
345  tool_->moveToOrigin->setWhatsThis(QString(tr("Moves the selected objects such that their center of gravity is at the origin."))
346  +whatsThis.generateLink("move_cog"));
347 
348  connect(tool_->unifyBoundingBoxDiagonal,SIGNAL(clicked() ),this,SLOT(slotUnifyBoundingBoxDiagonal()));
349  tool_->unifyBoundingBoxDiagonal->setIcon( QIcon(OpenFlipper::Options::iconDirStr() + OpenFlipper::Options::dirSeparator() + "unifyBB.png") );
350  tool_->unifyBoundingBoxDiagonal->setIconSize(QSize(48,48));
351  tool_->unifyBoundingBoxDiagonal->setWhatsThis(QString(tr("Rescale objects such that its bounding box diagonal has length one."))
352  +whatsThis.generateLink("unifyBB"));
353 
354  connect(tool_->unifyBoundingBoxLongest,SIGNAL(clicked() ),this,SLOT(slotUnifyBoundingBoxLongestAxis()));
355  tool_->unifyBoundingBoxLongest->setIcon( QIcon(OpenFlipper::Options::iconDirStr() + OpenFlipper::Options::dirSeparator() + "unifyBB_longest.png") );
356  tool_->unifyBoundingBoxLongest->setIconSize(QSize(48,48));
357 
358  connect(tool_->unifyBoundingBoxAll,SIGNAL(clicked() ),this,SLOT(slotUnifyBoundingBoxAllAxis()));
359  tool_->unifyBoundingBoxAll->setIcon( QIcon(OpenFlipper::Options::iconDirStr() + OpenFlipper::Options::dirSeparator() + "unifyBB_all.png") );
360  tool_->unifyBoundingBoxAll->setIconSize(QSize(48,48));
361 
363 
364  toolIcon_ = new QIcon(OpenFlipper::Options::iconDirStr()+OpenFlipper::Options::dirSeparator()+"move-toolBox.png");
365  emit addToolbox( tr("Move") , tool_, toolIcon_ );
366 }
367 
368 
369 /*******************************************************************************
370  MouseInterface implementation
371  *******************************************************************************/
372 
373 void MovePlugin::slotMouseWheelEvent(QWheelEvent * _event, const std::string & /*_mode*/)
374 {
375  // Skip execution if this is not our pick mode
376  if( ( (PluginFunctions::pickMode() != "Move")
377  && (PluginFunctions::pickMode() != "MoveSelection") )
378  || PluginFunctions::actionMode() != Viewer::PickingMode)
379  return;
380 
381  // compute the manipulator size modifier based on the mouse wheel change
382  manip_size_modifier_ = manip_size_modifier_ - (float)_event->delta() / 120.0 * 0.1;
383 
384  //dont scroll into negative sizes
385  if (manip_size_modifier_ < 0.0)
386  manip_size_modifier_ = 0.0;
387 
388  // Resize all manipulators based on the modifier on all objects
390  o_it->manipulatorNode()->set_size(manip_size_ * manip_size_modifier_);
391 
392  // Redraw scene with updated manipulators
393  emit updateView();
394 }
395 
396 
397 //------------------------------------------------------------------------------
398 
403 void MovePlugin::slotMouseEvent(QMouseEvent* _event) {
404  if (((PluginFunctions::pickMode() == ("Move"))
405  || (PluginFunctions::pickMode() == ("MoveSelection")))
406  && PluginFunctions::actionMode() == Viewer::PickingMode) {
407 
408  if (_event->type() == QEvent::MouseButtonDblClick || (_event->type() == QEvent::MouseButtonPress
409  && _event->button() == Qt::LeftButton && (placeAction_->isChecked() || placeMode_))) {
410 
411  bool snap = (placeMode_ && (PluginFunctions::pickMode() == ("MoveSelection")));
412 
413  placeManip(_event, snap);
414  placeAction_->setChecked(false);
416 
417  if (placeMode_) {
418  manMode_ = QtTranslationManipulatorNode::TranslationRotation;
419 
421  != PluginFunctions::objectsEnd(); ++o_it)
422  if (o_it->manipPlaced())
423  o_it->manipulatorNode()->setMode(manMode_);
424 
425  resizeAction_->setChecked(false);
426  rotateManipAction_->setChecked(false);
427  rotateTranslateAction_->setChecked(true);
428  placeAndSnapAction_->setChecked(false);
429  }
430 
431  placeMode_ = false;
432  return;
433 
434  } else if (placeMode_) {
435 
436  /*
437  * Move manipulator along with cursor if placeAndSnap mode
438  * is active. Snap to nearest geometry element (vertex, line, face center)
439  * depending on which selection type is active.
440  *
441  */
442 
443  placeManip(_event, (PluginFunctions::pickMode() != ("Move")));
445  return;
446  }
447 
448  // interaction
451 
452  if (_event->buttons() == Qt::LeftButton)
453  emit nodeVisibilityChanged(-1);
454 
455  }
456 }
457 
458 /*******************************************************************************
459  KeyInterface implementation
460  *******************************************************************************/
461 
462 void MovePlugin::slotKeyEvent (QKeyEvent* _event)
463 {
464  if ((_event->key() == Qt::Key_Control) && _event->modifiers() != Qt::ShiftModifier) {
465  setManipMode (QtTranslationManipulatorNode::Resize);
466  return;
467  } else if ((_event->key () == Qt::Key_Shift) && _event->modifiers() != Qt::ControlModifier) {
468  setManipMode (QtTranslationManipulatorNode::LocalRotation);
469  return;
470  }
471 
472  // Return to normal mode if Ctrl + Shift is pressed since this
473  // is used in translation manipulator node for rotation rasterization
474  setManipMode (QtTranslationManipulatorNode::TranslationRotation);
475 }
476 
477 //------------------------------------------------------------------------------
478 
480 {
481  PluginFunctions::pickMode("MoveSelection");
482 }
483 
484 //------------------------------------------------------------------------------
486 {
488 }
489 //------------------------------------------------------------------------------
490 
491 void MovePlugin::slotKeyReleaseEvent (QKeyEvent* _event)
492 {
493  if ((_event->key() == Qt::Key_Control && manMode_ == QtTranslationManipulatorNode::Resize) ||
494  (_event->key() == Qt::Key_Shift && manMode_ == QtTranslationManipulatorNode::LocalRotation))
495  setManipMode (QtTranslationManipulatorNode::TranslationRotation);
496 }
497 
498 void MovePlugin::setPickModeProps(movePropsWidget* _pW, const std::string &_pickmode)
499 {
500  if (_pickmode == "Move")
501  {
502  _pW->objectRadioButton->setChecked(true);
503  }
504  else if (_pickmode == "MoveSelection")
505  {
506  _pW->selectionRadioButton->setChecked(true);
507  }
508  else
509  {
510  //not supported, so deselect all radio buttons
511  _pW->objectRadioButton->setAutoExclusive(false);
512  _pW->selectionRadioButton->setAutoExclusive(false);
513  _pW->objectRadioButton->setChecked(false);
514  _pW->selectionRadioButton->setChecked(false);
515  _pW->objectRadioButton->setAutoExclusive(true);
516  _pW->selectionRadioButton->setAutoExclusive(true);
517  }
518 }
519 
520 /*******************************************************************************
521  PickingInterface implementation
522  *******************************************************************************/
523 
528 void MovePlugin::slotPickModeChanged( const std::string& _mode)
529 {
530  moveAction_->setChecked(_mode == "Move");
531  moveSelectionAction_->setChecked(_mode == "MoveSelection");
532 
533  hide_ = !(_mode == "Move" || _mode == "MoveSelection");
534 
536 
537  if (!hide_)
538  {
539  switch (manMode_)
540  {
541  case QtTranslationManipulatorNode::Rotation:
543  break;
544  case QtTranslationManipulatorNode::Resize:
546  break;
547  case QtTranslationManipulatorNode::LocalRotation:
549  break;
550  case QtTranslationManipulatorNode::Place:
552  break;
553  case QtTranslationManipulatorNode::TranslationRotation:
555  break;
556  }
557  }
558  else
560 
561  //change the selection mode in propety widget
562  for (int i = 0; i < propsWindows_.size(); ++i)
563  setPickModeProps(propsWindows_[i], _mode);
564 
565 }
566 
567 
568 /*******************************************************************************
569  MovePlugin implementation
570  *******************************************************************************/
571 
578  BaseObjectData* object;
579  if ( ! PluginFunctions::getObject(_id,object) )
580  return;
581 
582  if ( mat.is_identity() )
583  return;
584 
585  if ( object->dataType() == DATA_TRIANGLE_MESH ) {
586  transformMesh(mat , *PluginFunctions::triMesh(object) );
587  } else if ( object->dataType() == DATA_POLY_MESH ) {
588  transformMesh(mat , *PluginFunctions::polyMesh(object) );
589 #ifdef ENABLE_TSPLINEMESH_SUPPORT
590  } else if ( object->dataType() == DATA_TSPLINE_MESH ) {
591  transformMesh(mat , *PluginFunctions::tsplineMesh(object) );
592 #endif
593 #ifdef ENABLE_POLYLINE_SUPPORT
594  } else if ( object->dataType() == DATA_POLY_LINE ) {
595  transformPolyLine(mat , *PluginFunctions::polyLine(object) );
596 #endif
597 #ifdef ENABLE_SKELETON_SUPPORT
598  } else if ( object->dataType() == DATA_SKELETON ) {
599  transformSkeleton(mat , *PluginFunctions::skeleton(object) );
600 #endif
601 #ifdef ENABLE_OPENVOLUMEMESH_HEXAHEDRAL_SUPPORT
602  } else if ( object->dataType() == DATA_HEXAHEDRAL_MESH ) {
604  transformVolumeMesh(mat , *obj->mesh() , obj->normals() );
605 #endif
606 #ifdef ENABLE_OPENVOLUMEMESH_TETRAHEDRAL_SUPPORT
607  } else if ( object->dataType() == DATA_TETRAHEDRAL_MESH ) {
608  TetrahedralMeshObject* obj = PluginFunctions::tetrahedralMeshObject(object);
609  transformVolumeMesh(mat , *obj->mesh() , obj->normals() );
610 #endif
611 #ifdef ENABLE_OPENVOLUMEMESH_POLYHEDRAL_SUPPORT
612  } else if ( object->dataType() == DATA_POLYHEDRAL_MESH ) {
614  transformVolumeMesh(mat , *obj->mesh() , obj->normals() );
615 #endif
616  } else if ( object->dataType() == DATA_PLANE ) {
617  PluginFunctions::plane(object)->transform(mat);
618  } else {
619 
620  emit log(LOGERR,tr("moveObject called for unsupported Object Type"));
621  return;
622  }
623 
624  emit updatedObject(_id, UPDATE_GEOMETRY);
625  emit createBackup(_id, "Move Object", UPDATE_GEOMETRY);
626 }
627 
628 
629 //------------------------------------------------------------------------------
630 
641 void MovePlugin::moveSelection(ACG::Matrix4x4d _mat, int _id, QEvent::Type _type) {
642  // Get currently active primitive type
644 
645  if ( !_mat.is_identity() ){
646  if (selectionType_ & VERTEX) {
648  }
649  if (selectionType_ & FACE) {
651  }
652  if (selectionType_ & EDGE) {
654  }
655  if (selectionType_ & CELL) {
657  }
658 
659  emit updatedObject(_id, UPDATE_GEOMETRY);
660  }
661 
662  //only create backups on mouseRelease and something has to have been selected and transformed
663  if ( _type == QEvent::MouseButtonRelease && transformedSelected_ )
664  emit createBackup(_id,"Move Selection", UPDATE_GEOMETRY);
665 
666 }
667 
668 //------------------------------------------------------------------------------
669 
675 {
676  if (_mode != manMode_)
677  {
678  manMode_ = _mode;
679 
680  // Iterate over all objects that have a placed manip and set their mode
682  if ( o_it->manipPlaced() )
683  o_it->manipulatorNode()->setMode (_mode);
684 
685 
686  if (!hide_) {
687  switch (manMode_)
688  {
689  case QtTranslationManipulatorNode::Rotation:
691  placeMode_ = false;
692  break;
693  case QtTranslationManipulatorNode::Resize:
695  placeMode_ = false;
696  break;
697  case QtTranslationManipulatorNode::LocalRotation:
699  placeMode_ = false;
700  break;
701  case QtTranslationManipulatorNode::Place:
703  placeMode_ = true;
704  break;
705  case QtTranslationManipulatorNode::TranslationRotation:
707  placeMode_ = false;
708  break;
709  }
710  }
711 
712  // Update the toolbar icons
713  switch (manMode_)
714  {
715  case QtTranslationManipulatorNode::Resize:
716  resizeAction_->setChecked (true);
717  rotateManipAction_->setChecked (false);
718  rotateTranslateAction_->setChecked (false);
719  placeAndSnapAction_->setChecked (false);
720  break;
721  case QtTranslationManipulatorNode::LocalRotation:
722  resizeAction_->setChecked (false);
723  rotateManipAction_->setChecked (true);
724  rotateTranslateAction_->setChecked (false);
725  placeAndSnapAction_->setChecked (false);
726  break;
727  case QtTranslationManipulatorNode::TranslationRotation:
728  resizeAction_->setChecked (false);
729  rotateManipAction_->setChecked (false);
730  rotateTranslateAction_->setChecked (true);
731  placeAndSnapAction_->setChecked (false);
732  break;
733  case QtTranslationManipulatorNode::Place:
734  resizeAction_->setChecked (false);
735  rotateManipAction_->setChecked (false);
736  rotateTranslateAction_->setChecked (false);
737  placeAndSnapAction_->setChecked (true);
738  break;
739  case QtTranslationManipulatorNode::Rotation:
740  resizeAction_->setChecked(false);
741  rotateManipAction_->setChecked(true);
742  rotateTranslateAction_->setChecked(false);
743  placeAndSnapAction_->setChecked(false);
744  break;
745  }
746  }
747 }
748 
749 //------------------------------------------------------------------------------
750 
756 
758 
759  if (node == 0)
760  return;
761 
762  if (node->className() != "QtTranslationManipulatorNode") {
763  contextAction_->setVisible(false);
764  } else {
765  contextAction_->setVisible(true);
766  }
767 }
768 
769 //------------------------------------------------------------------------------
770 
776 void MovePlugin::manipulatorMoved( QtTranslationManipulatorNode* _node , QMouseEvent* _event) {
777 
778  // React on event only in move mode
779  if ( PluginFunctions::pickMode() != "Move"
780  && PluginFunctions::pickMode() != "MoveSelection" )
781  return;
782 
783  OpenFlipper::Options::redrawDisabled( true );
784 
785  // Apply changes only on Release for moveMode and after every movement in MoveSelection Mode
786  if ( !placeMode_ && ((_event->type() == QEvent::MouseButtonRelease) ||
787  (PluginFunctions::pickMode() != "Move" && _event->buttons() != Qt::NoButton)) ) {
788 
789  int objectId = _node->getIdentifier();
790 
791  ACG::Matrix4x4d mat;
792  mat.identity();
793  mat = _node->matrix();
794 
795  // Reset Node
796  _node->loadIdentity();
797  _node->set_center(mat.transform_point(_node->center()));
798 
799  // move the object which corresponds to the manipulator
800  if (PluginFunctions::pickMode() == "Move")
801  moveObject( mat, objectId );
802  else if (PluginFunctions::pickMode() == "MoveSelection")
803  moveSelection( mat, objectId, _event->type() );
804 
805  // move all other targets without manipulator
806  if(allTargets_) {
808  != PluginFunctions::objectsEnd(); ++o_it) {
809  if ((o_it->id() != objectId) && !o_it->manipulatorNode()->draw_manipulator()) { // If it has its own manipulator active, dont move it
810 
811  // move the object which corresponds to the manipulator
812  if (PluginFunctions::pickMode() == "Move")
813  moveObject( mat, o_it->id() );
814  else if (PluginFunctions::pickMode() == "MoveSelection")
815  moveSelection( mat, o_it->id(), _event->type() );
816  }
817  }
818  }
819 
820  lastActiveManipulator_ = objectId;
822  }
823 
824  OpenFlipper::Options::redrawDisabled( false );
825 }
826 
827 
828 //------------------------------------------------------------------------------
829 
835 
836  // Position has been changed of the manipulator by a direct function
837  int objectId = _node->getIdentifier();
838 
839  if ( objectId > 0 ){
840 
841  BaseObjectData* object;
842  PluginFunctions::getObject(objectId,object);
843 
844  // Assume that it has a good position now
845  object->manipPlaced( true );
846  }
847 
848  // Show manipulator only if in Move mode
849  if ( PluginFunctions::pickMode() == "Move" )
850  _node->show();
851 
852  lastActiveManipulator_ = objectId;
854 
855 }
856 
857 
858 //------------------------------------------------------------------------------
859 
865 void MovePlugin::placeManip(QMouseEvent * _event, bool _snap) {
866  unsigned int node_idx, target_idx;
867  OpenMesh::Vec3d hitPoint;
868  BaseObjectData* object;
869 
870  bool successfullyPicked = false;
871 
872 
873 
874  /*
875  * Snap manipulator to nearest geometry
876  * element depending on which selection type is
877  * active.
878  */
879  if (_snap) {
880 
881  successfullyPicked = PluginFunctions::scenegraphPick(ACG::SceneGraph::PICK_FACE, _event->pos(), node_idx,
882  target_idx, &hitPoint) && PluginFunctions::getPickedObject(node_idx, object);
883 
884  if(!successfullyPicked) {
885  //emit log(LOGWARN, tr("Picking failed"));
886  return;
887  }
888 
889  if (selectionType_ == VERTEX) {
890  if ( object->dataType(DATA_TRIANGLE_MESH) ) {
891  hitPoint = getNearestVertex(PluginFunctions::triMesh(object), target_idx, hitPoint);
892  } else if ( object->dataType(DATA_POLY_MESH) ) {
893  hitPoint = getNearestVertex(PluginFunctions::polyMesh(object), target_idx, hitPoint);
894 #ifdef ENABLE_TSPLINEMESH_SUPPORT
895  } else if ( object->dataType(DATA_TSPLINE_MESH) ) {
896  hitPoint = getNearestVertex(PluginFunctions::tsplineMesh(object), target_idx, hitPoint);
897 #endif
898  }
899  } else if (selectionType_ == EDGE) {
900  if ( object->dataType(DATA_TRIANGLE_MESH) ) {
901  hitPoint = getNearestEdge(PluginFunctions::triMesh(object), target_idx, hitPoint);
902  } else if ( object->dataType(DATA_POLY_MESH) ) {
903  hitPoint = getNearestEdge(PluginFunctions::polyMesh(object), target_idx, hitPoint);
904 #ifdef ENABLE_TSPLINEMESH_SUPPORT
905  } else if ( object->dataType(DATA_TSPLINE_MESH) ) {
906  hitPoint = getNearestEdge(PluginFunctions::tsplineMesh(object), target_idx, hitPoint);
907 #endif
908  }
909  } else if (selectionType_ == FACE) {
910  if ( object->dataType(DATA_TRIANGLE_MESH) ) {
911  hitPoint = getNearestFace(PluginFunctions::triMesh(object), target_idx, hitPoint);
912  } else if ( object->dataType(DATA_POLY_MESH) ) {
913  hitPoint = getNearestFace(PluginFunctions::polyMesh(object), target_idx, hitPoint);
914 #ifdef ENABLE_TSPLINEMESH_SUPPORT
915  } else if ( object->dataType(DATA_TSPLINE_MESH) ) {
916  hitPoint = getNearestFace(PluginFunctions::tsplineMesh(object), target_idx, hitPoint);
917 #endif
918  }
919  }
920 
921  } else {
922  successfullyPicked = PluginFunctions::scenegraphPick(ACG::SceneGraph::PICK_ANYTHING, _event->pos(), node_idx,
923  target_idx, &hitPoint) && PluginFunctions::getPickedObject(node_idx, object);
924  }
925 
926  if (successfullyPicked) {
927 
928  object->manipPlaced(true);
929 
931  int data = -1;
932  if (data != -1)
933  object->manipulatorNode()->setData( data );
934 
935  object->manipulatorNode()->loadIdentity();
936  object->manipulatorNode()->set_center(hitPoint);
937  object->manipulatorNode()->set_draw_cylinder(true);
938  object->manipulatorNode()->set_autosize(QtTranslationManipulatorNode::Once);
939  object->manipulatorNode()->set_size(manip_size_ * manip_size_modifier_);
940  object->manipulatorNode()->setMode(manMode_);
941  object->manipulatorNode()->show();
942 
943  object->manipulatorNode()->apply_transformation(PluginFunctions::pickMode() == "Move");
944 
945  // Disconnect a previously connected Signal
946  disconnect(object->manipulatorNode() , SIGNAL(manipulatorMoved(QtTranslationManipulatorNode*,QMouseEvent*)),
947  this , SLOT( manipulatorMoved(QtTranslationManipulatorNode*,QMouseEvent*)));
948 
949  disconnect(object->manipulatorNode() , SIGNAL(positionChanged(QtTranslationManipulatorNode*)),
951 
952  // Reconnect the signals.
953  connect(object->manipulatorNode() , SIGNAL(manipulatorMoved(QtTranslationManipulatorNode*,QMouseEvent*)),
954  this , SLOT( manipulatorMoved(QtTranslationManipulatorNode*,QMouseEvent*)));
955 
956  connect(object->manipulatorNode() , SIGNAL(positionChanged(QtTranslationManipulatorNode*)),
958 
959  lastActiveManipulator_ = object->id();
960 
961  emit updateView();
962 
963  bool found = false;
964 
965  for (uint i=0; i < activeManipulators_.size(); i++)
966  if ( activeManipulators_[i] == object->id() ){
967  found = true;
968  break;
969  }
970 
971  if ( !found )
972  activeManipulators_.push_back( object->id() );
973 
974  } else {
975  //emit log(LOGWARN, tr("Picking failed"));
976  }
977 }
978 
979 
980 //------------------------------------------------------------------------------
981 
986 {
987 
988  if (!hide_ && (toolboxActive_ || (PluginFunctions::pickMode() == "Move")
989  || (PluginFunctions::pickMode() == "MoveSelection"))) {
990 
991  for (uint i=0; i < activeManipulators_.size(); i++){
992 
993  BaseObjectData* obj = 0;
994 
996 
997  if (obj != 0 && obj->manipPlaced()) {
998  obj->manipulatorNode()->show();
999  obj->manipulatorNode()->apply_transformation( PluginFunctions::pickMode() == "Move" );
1000  emit nodeVisibilityChanged(obj->id());
1001  }
1002  }
1003 
1004  } else {
1005 
1006  for (uint i=0; i < activeManipulators_.size(); i++){
1007 
1008  BaseObjectData* obj = 0;
1009 
1011 
1012  if ( obj != 0 ) {
1013  obj->manipulatorNode()->hide();
1014  emit nodeVisibilityChanged(obj->id());
1015  }
1016  }
1017  }
1018 
1019  emit updateView();
1020 
1021 }
1022 
1023 //------------------------------------------------------------------------------
1024 
1030 
1031  if(_but == 0) return 0;
1032  return dynamic_cast<movePropsWidget*>((((_but->parentWidget())->parentWidget())->parentWidget()));
1033 }
1034 //------------------------------------------------------------------------------
1035 
1040 
1041  QPushButton* but = dynamic_cast<QPushButton*>(QObject::sender());
1043  if(pW == 0) return;
1044 
1045  TriMesh::Point newpos;
1046 
1047  bool ok = false;
1048  newpos[0] = (pW->nposx->text()).toDouble(&ok);
1049  if ( !ok ) { emit log(LOGERR,tr("Wrong Format for X Coordinate")); return; }
1050  newpos[1] = (pW->nposy->text()).toDouble(&ok);
1051  if ( !ok ) { emit log(LOGERR,tr("Wrong Format for Y Coordinate")); return; }
1052  newpos[2] = (pW->nposz->text()).toDouble(&ok);
1053  if ( !ok ) { emit log(LOGERR,tr("Wrong Format for Z Coordinate")); return; }
1054 
1055  BaseObjectData* object;
1057  if ( object->manipulatorNode()->visible() ) {
1058  // Compute translation vector
1059  ACG::Vec3d translation = newpos;
1060  translation -= object->manipulatorNode()->center();
1061  object->manipulatorNode()->set_center(newpos);
1062  // Stuff it into transformation matrix
1063  ACG::GLMatrixd m;
1064  m.identity();
1065  m.translate(translation);
1066  if (PluginFunctions::pickMode() == "Move")
1067  {
1068  // ...and transform mesh
1069  if(object->dataType() == DATA_TRIANGLE_MESH)
1071  else if(object->dataType() == DATA_POLY_MESH)
1073 
1074  // Create backup
1075  emit createBackup(object->id(), "Object Translation");
1076 
1077  }
1078  else if (PluginFunctions::pickMode() == "MoveSelection")
1079  {
1081  if (selectionType_ & VERTEX) {
1082  transformVertexSelection(object->id(), m);
1083  }
1084  if (selectionType_ & FACE) {
1085  transformFaceSelection(object->id(), m);
1086  }
1087  if (selectionType_ & EDGE) {
1088  transformEdgeSelection(object->id(), m);
1089  }
1090 
1091  // Create backup
1092  emit createBackup(object->id(), "Translation of selection");
1093  }
1094 
1095 
1096  emit updatedObject(object->id(), UPDATE_GEOMETRY);
1097  }
1099  emit updateView();
1100  }
1101 }
1102 
1103 
1104 //------------------------------------------------------------------------------
1105 
1110 
1111  QPushButton* but = dynamic_cast<QPushButton*>(QObject::sender());
1113  if(pW == 0) return;
1114 
1115  axisA_ = (axisA_ + 1) % 3;
1116 
1117  if (axisA_ == axisB_)
1118  axisA_ = (axisA_ + 1) % 3;
1119 
1120  switch(axisA_){
1121  case 0: pW->axisAButton->setText(tr("X Direction")); break;
1122  case 1: pW->axisAButton->setText(tr("Y Direction")); break;
1123  case 2: pW->axisAButton->setText(tr("Z Direction")); break;
1124  default: break;
1125  }
1126 }
1127 
1128 
1129 //------------------------------------------------------------------------------
1130 
1135 
1136  QPushButton* but = dynamic_cast<QPushButton*>(QObject::sender());
1138  if(pW == 0) return;
1139 
1140  axisB_ = (axisB_ + 1) % 3;
1141 
1142  if (axisA_ == axisB_)
1143  axisB_ = (axisB_ + 1) % 3;
1144 
1145  switch(axisB_){
1146  case 0: pW->axisBButton->setText(tr("X Direction")); break;
1147  case 1: pW->axisBButton->setText(tr("Y Direction")); break;
1148  case 2: pW->axisBButton->setText(tr("Z Direction")); break;
1149  default: break;
1150  }
1151 }
1152 
1153 
1154 //------------------------------------------------------------------------------
1155 
1160 
1161  QPushButton* but = dynamic_cast<QPushButton*>(QObject::sender());
1163  if(pW == 0) return;
1164 
1165  ACG::Vec3d newdirA,newdirB;
1166  ACG::Vec3d dirX,dirY;
1167  ACG::Vec3d dirZ(0.0,0.0,0.0);
1168 
1169  bool ok = false;
1170  newdirA[0] = (pW->ndirAx->text()).toDouble(&ok);
1171  if ( !ok ) { emit log(LOGERR,tr("Wrong Format for X Coordinate")); return; }
1172  newdirA[1] = (pW->ndirAy->text()).toDouble(&ok);
1173  if ( !ok ) { emit log(LOGERR,tr("Wrong Format for Y Coordinate")); return; }
1174  newdirA[2] = (pW->ndirAz->text()).toDouble(&ok);
1175  if ( !ok ) { emit log(LOGERR,tr("Wrong Format for Z Coordinate")); return; }
1176 
1177  newdirB[0] = (pW->ndirBx->text()).toDouble(&ok);
1178  if ( !ok ) { emit log(LOGERR,tr("Wrong Format for X Coordinate")); return; }
1179  newdirB[1] = (pW->ndirBy->text()).toDouble(&ok);
1180  if ( !ok ) { emit log(LOGERR,tr("Wrong Format for Y Coordinate")); return; }
1181  newdirB[2] = (pW->ndirBz->text()).toDouble(&ok);
1182  if ( !ok ) { emit log(LOGERR,tr("Wrong Format for Z Coordinate")); return; }
1183 
1184  bool xAxis = false;
1185  bool yAxis = false;
1186 
1187  switch(axisA_){
1188  case 0: dirX = newdirA; xAxis = true; break;
1189  case 1: dirY = newdirA; yAxis = true; break;
1190  default: dirZ = newdirA; break;
1191  }
1192 
1193  switch(axisB_){
1194  case 0: dirX = newdirB; xAxis = true; break;
1195  case 1: dirY = newdirB; yAxis = true; break;
1196  default: dirZ = newdirB; break;
1197  }
1198 
1199  if (!xAxis)
1200  dirX = dirY % dirZ;
1201 
1202  if (!yAxis)
1203  dirY = dirX % dirZ;
1204 
1205 
1206  if ( (dirX | dirY) != 0.0){
1207  emit log(LOGERR,tr("The axes of the new direction have to be orthogonal"));
1208  return;
1209  }
1210 
1211 // // Apply to All Target Objects
1212 // if ( pW->targetObjects->isChecked() ) {
1213 // for ( PluginFunctions::ObjectIterator o_it(PluginFunctions::TARGET_OBJECTS) ;
1214 // o_it PluginFunctions::objectsEnd(); ++o_it){
1215 //
1216 // o_it->manipulatorNode()->set_direction( dirX, dirY );
1217 // }
1218 // }
1219 
1220 
1221  BaseObjectData* object = 0;
1222  PluginFunctions::getObject(pW->getBaseObjectDataId(),object);
1223  if ( object != 0 ) {
1224  if ( object->manipulatorNode()->visible() ){
1225 
1226  object->manipulatorNode()->set_direction( dirX, dirY );
1227  }
1228  } else return;
1229 
1231  emit updateView();
1232 }
1233 
1234 
1235 //------------------------------------------------------------------------------
1236 
1241 
1242  QPushButton* but = dynamic_cast<QPushButton*>(QObject::sender());
1244  if(pW == 0) return;
1245 
1246  ACG::Vec3d translation;
1247 
1248  bool ok = false;
1249  translation[0] = (pW->translationX->text()).toDouble(&ok);
1250  if ( !ok ) { emit log(LOGERR,tr("Wrong Format for X Coordinate")); return; }
1251  translation[1] = (pW->translationY->text()).toDouble(&ok);
1252  if ( !ok ) { emit log(LOGERR,tr("Wrong Format for Y Coordinate")); return; }
1253  translation[2] = (pW->translationZ->text()).toDouble(&ok);
1254  if ( !ok ) { emit log(LOGERR,tr("Wrong Format for Z Coordinate")); return; }
1255 
1256  BaseObjectData* object = 0;
1257  PluginFunctions::getObject(pW->getBaseObjectDataId(),object);
1258 
1259  if (object != 0) {
1260  if (object->manipulatorNode()->visible()) {
1261 
1262  object->manipulatorNode()->set_center(
1263  object->manipulatorNode()->center() + translation);
1264 
1265  if (PluginFunctions::pickMode() == "Move")
1266  {
1267 
1268  translate(object->id(), translation);
1269 
1270  // Create backup
1271  emit createBackup(object->id(), "Translation of Object");
1272 
1273  }
1274  else if (PluginFunctions::pickMode() == "MoveSelection")
1275  {
1277  if (selectionType_ & VERTEX) {
1278  translateVertexSelection(object->id(), translation);
1279  }
1280  if (selectionType_ & FACE) {
1281  translateFaceSelection(object->id(), translation);
1282  }
1283  if (selectionType_ & EDGE) {
1284  translateEdgeSelection(object->id(), translation);
1285  }
1286  emit createBackup(object->id(), "Translation of selection");
1287  }
1288 
1289 
1290 
1291  emit updatedObject(object->id(), UPDATE_GEOMETRY);
1292 
1293 
1294  // move all other targets without manipulator
1295  if(allTargets_) {
1296 
1298  != PluginFunctions::objectsEnd(); ++o_it) {
1299  if ((o_it->id() != object->id()) && !o_it->manipulatorNode()->draw_manipulator()) { // If it has its own manipulator active, dont move it
1300  if (PluginFunctions::pickMode() == "Move") {
1301 
1302  translate(o_it->id(), translation);
1303 
1304  // Create backup
1305  emit createBackup(o_it->id(), "Translation of object");
1306 
1307  } else if (PluginFunctions::pickMode() == "MoveSelection") {
1309  if (selectionType_ & VERTEX) {
1310  translateVertexSelection(o_it->id(), translation);
1311  }
1312  if (selectionType_ & FACE) {
1313  translateFaceSelection(o_it->id(), translation);
1314  }
1315  if (selectionType_ & EDGE) {
1316  translateEdgeSelection(o_it->id(), translation);
1317  }
1318 
1319  emit createBackup(o_it->id(), "Translation of selection");
1320  }
1321 
1322 
1323  emit updatedObject(o_it->id(), UPDATE_GEOMETRY);
1324  }
1325  }
1326 
1327  }
1328  }
1329  } else {
1330  return;
1331  }
1332 
1333 
1335  emit scriptInfo(QString("slotTranslation()"));
1336  emit updateView();
1337 }
1338 
1339 
1340 //------------------------------------------------------------------------------
1341 
1346 
1347  QPushButton* but = dynamic_cast<QPushButton*>(QObject::sender());
1349  if(pW == 0) return;
1350 
1351  if ( allTargets_ ) {
1352  emit log(LOGWARN,tr("TODO Project for multiple targets"));
1353  return;
1354  } else {
1355  emit log(LOGWARN,tr("TODO Project for one target"));
1356  return;
1357  }
1358 
1359 }
1360 
1361 
1362 //------------------------------------------------------------------------------
1363 
1368 
1369  QPushButton* but = dynamic_cast<QPushButton*>(QObject::sender());
1371  if(pW == 0) return;
1372 
1373 
1374 // if ( pW->targetObjects->isChecked() ) {
1375 // for ( PluginFunctions::ObjectIterator o_it(PluginFunctions::TARGET_OBJECTS) ; o_it != PluginFunctions::objectsEnd(); ++o_it) {
1376 // if ( o_it->manipulatorNode()->hidden() )
1377 // continue;
1378 //
1379 // if ( o_it->dataType( DATA_TRIANGLE_MESH ) )
1380 // o_it->manipulatorNode()->set_center( MeshInfo::cog(*PluginFunctions::triMesh(*o_it) ) );
1381 // else if ( o_it->dataType( DATA_POLY_MESH ) )
1382 // o_it->manipulatorNode()->set_center( MeshInfo::cog(*PluginFunctions::polyMesh(*o_it)) );
1383 //
1384 // updateManipulatorDialog();
1385 // o_it->manipulatorNode()->loadIdentity();
1386 // }
1387 // } else {
1388 
1389  BaseObjectData* object = 0;
1390  PluginFunctions::getObject(pW->getBaseObjectDataId(),object);
1391  if ( object != 0 ) {
1392  if ( object->manipulatorNode()->visible() ){
1393 
1394  if ( object->dataType( DATA_TRIANGLE_MESH ) )
1395  object->manipulatorNode()->set_center( MeshInfo::cog(PluginFunctions::triMesh(object)) );
1396  else if ( object->dataType( DATA_POLY_MESH ) )
1397  object->manipulatorNode()->set_center( MeshInfo::cog(PluginFunctions::polyMesh(object)) );
1398 #ifdef ENABLE_TSPLINEMESH_SUPPORT
1399  else if ( object->dataType( DATA_TSPLINE_MESH ) )
1400  object->manipulatorNode()->set_center( MeshInfo::cog(PluginFunctions::tsplineMesh(object)) );
1401 #endif
1402 #ifdef ENABLE_OPENVOLUMEMESH_HEXAHEDRAL_SUPPORT
1403  else if ( object->dataType( DATA_HEXAHEDRAL_MESH ) )
1404  object->manipulatorNode()->set_center( cogVolumeMesh(*PluginFunctions::hexahedralMesh(object)) );
1405 #endif
1406 #ifdef ENABLE_OPENVOLUMEMESH_TETRAHEDRAL_SUPPORT
1407  else if ( object->dataType( DATA_TETRAHEDRAL_MESH ) )
1408  object->manipulatorNode()->set_center( cogVolumeMesh(*PluginFunctions::tetrahedralMesh(object)) );
1409 #endif
1410 #ifdef ENABLE_OPENVOLUMEMESH_POLYHEDRAL_SUPPORT
1411  else if ( object->dataType( DATA_POLYHEDRAL_MESH ) )
1412  object->manipulatorNode()->set_center( cogVolumeMesh(*PluginFunctions::polyhedralMesh(object)) );
1413 #endif
1414 
1416  object->manipulatorNode()->loadIdentity();
1417  }
1418  }
1419 
1420  emit updateView();
1421 }
1422 
1423 
1424 //------------------------------------------------------------------------------
1425 
1430 
1431  QPushButton* but = dynamic_cast<QPushButton*>(QObject::sender());
1433  if(pW == 0) return;
1434 
1435  TriMesh::Point axis;
1436  double angle;
1437 
1438  bool ok = false;
1439  axis[0] = (pW->rotx->text()).toDouble(&ok);
1440  if ( !ok ) { emit log(LOGERR,tr("Wrong Format for X Coordinate")); return; }
1441  axis[1] = (pW->roty->text()).toDouble(&ok);
1442  if ( !ok ) { emit log(LOGERR,tr("Wrong Format for Y Coordinate")); return; }
1443  axis[2] = (pW->rotz->text()).toDouble(&ok);
1444  if ( !ok ) { emit log(LOGERR,tr("Wrong Format for Z Coordinate")); return; }
1445 
1446  angle = (pW->rotAngle->text()).toDouble(&ok);
1447  if ( !ok ) { emit log(LOGERR,tr("Wrong Format for Angle")); return; }
1448 
1449  BaseObjectData* object = 0;
1450  PluginFunctions::getObject(pW->getBaseObjectDataId(),object);
1451  if (object != 0) {
1452  if (object->manipulatorNode()->visible() && (object->target() || !allTargets_)) {
1453 
1454  object->manipulatorNode()->rotate(angle, axis);
1455 
1457 
1458  if (PluginFunctions::pickMode() == "Move")
1459  {
1460  if (object->dataType(DATA_TRIANGLE_MESH))
1461  transformMesh(m, (*PluginFunctions::triMesh(object)));
1462 
1463  if (object->dataType(DATA_POLY_MESH))
1465 
1466  #ifdef ENABLE_TSPLINEMESH_SUPPORT
1467  if (object->dataType(DATA_TSPLINE_MESH))
1468  transformMesh(m, (*PluginFunctions::tsplineMesh(object)));
1469  #endif
1470  #ifdef ENABLE_OPENVOLUMEMESH_HEXAHEDRAL_SUPPORT
1471  if (object->dataType(DATA_HEXAHEDRAL_MESH))
1472  transformVolumeMesh(m, (*PluginFunctions::hexahedralMesh(object)), (PluginFunctions::hexahedralMeshObject(object)->normals()));
1473  #endif
1474  #ifdef ENABLE_OPENVOLUMEMESH_TETRAHEDRAL_SUPPORT
1475  if (object->dataType(DATA_TETRAHEDRAL_MESH))
1476  transformVolumeMesh(m, (*PluginFunctions::tetrahedralMesh(object)), (PluginFunctions::tetrahedralMeshObject(object)->normals()));
1477  #endif
1478  #ifdef ENABLE_OPENVOLUMEMESH_POLYHEDRAL_SUPPORT
1479  if (object->dataType(DATA_POLYHEDRAL_MESH))
1480  transformVolumeMesh(m, (*PluginFunctions::polyhedralMesh(object)), (PluginFunctions::polyhedralMeshObject(object)->normals()));
1481  #endif
1482 
1483  // Create backup
1484  emit createBackup(object->id(), "Rotation of object");
1485 
1486  }
1487  else if (PluginFunctions::pickMode() == "MoveSelection")
1488  {
1490  if (selectionType_ & VERTEX) {
1491  transformVertexSelection(object->id(), m);
1492  }
1493  if (selectionType_ & FACE) {
1494  transformFaceSelection(object->id(), m);
1495  }
1496  if (selectionType_ & EDGE) {
1497  transformEdgeSelection(object->id(), m);
1498  }
1499  if (selectionType_ & CELL) {
1500  transformCellSelection(object->id(), m);
1501  }
1502 
1503  // Create backup
1504  emit createBackup(object->id(), "Rotation of selection");
1505  }
1506 
1507  // move all other targets without manipulator
1508  if(allTargets_) {
1509 
1511 
1512  // If it has its own manipulator active, don't move it
1513  if ((o_it->id() != object->id()) && !o_it->manipulatorNode()->draw_manipulator()) {
1514 
1515  if (PluginFunctions::pickMode() == "Move")
1516  {
1517  if (o_it->dataType(DATA_TRIANGLE_MESH))
1519 
1520  if (o_it->dataType(DATA_POLY_MESH))
1522  #ifdef ENABLE_TSPLINEMESH_SUPPORT
1523  if (o_it->dataType(DATA_TSPLINE_MESH))
1524  transformMesh(m, (*PluginFunctions::tsplineMesh(o_it)));
1525  #endif
1526  #ifdef ENABLE_OPENVOLUMEMESH_HEXAHEDRAL_SUPPORT
1527  if (object->dataType(DATA_HEXAHEDRAL_MESH))
1528  transformVolumeMesh(m, (*PluginFunctions::hexahedralMesh(object)), (PluginFunctions::hexahedralMeshObject(object)->normals()));
1529  #endif
1530  #ifdef ENABLE_OPENVOLUMEMESH_TETRAHEDRAL_SUPPORT
1531  if (object->dataType(DATA_TETRAHEDRAL_MESH))
1532  transformVolumeMesh(m, (*PluginFunctions::tetrahedralMesh(object)), (PluginFunctions::tetrahedralMeshObject(object)->normals()));
1533  #endif
1534  #ifdef ENABLE_OPENVOLUMEMESH_POLYHEDRAL_SUPPORT
1535  if (object->dataType(DATA_POLYHEDRAL_MESH))
1536  transformVolumeMesh(m, (*PluginFunctions::polyhedralMesh(object)), (PluginFunctions::polyhedralMeshObject(object)->normals()));
1537  #endif
1538 
1539  // Create backup
1540  emit createBackup(o_it->id(), "Rotation of object");
1541  }
1542  else if (PluginFunctions::pickMode() == "MoveSelection")
1543  {
1545  if (selectionType_ & VERTEX) {
1546  transformVertexSelection(o_it->id(), m);
1547  }
1548  if (selectionType_ & FACE) {
1549  transformFaceSelection(o_it->id(), m);
1550  }
1551  if (selectionType_ & EDGE) {
1552  transformEdgeSelection(o_it->id(), m);
1553  }
1554  if (selectionType_ & CELL) {
1555  transformCellSelection(o_it->id(), m);
1556  }
1557 
1558  // Create backup
1559  emit createBackup(o_it->id(), "Rotation of selection");
1560  }
1561 
1562  emit updatedObject(o_it->id(), UPDATE_GEOMETRY);
1563  }
1564  }
1565 
1566  }
1567 
1569 
1570  emit updatedObject(object->id(), UPDATE_GEOMETRY);
1571 
1572  }
1573  }
1574 
1575  emit scriptInfo(QString("slotRotate()"));
1576  emit updateView();
1577 }
1578 
1579 
1580 //------------------------------------------------------------------------------
1581 
1586 
1587  QPushButton* but = dynamic_cast<QPushButton*>(QObject::sender());
1589  if(pW == 0) return;
1590 
1591 
1592  TriMesh::Point scale;
1593 
1594  bool ok = false;
1595  scale[0] = (pW->scalex->text()).toDouble(&ok);
1596  if ( !ok ) { emit log(LOGERR,tr("Wrong Format for factor 1")); return; }
1597  scale[1] = (pW->scaley->text()).toDouble(&ok);
1598  if ( !ok ) { emit log(LOGERR,tr("Wrong Format for factor 2")); return; }
1599  scale[2] = (pW->scalez->text()).toDouble(&ok);
1600  if ( !ok ) { emit log(LOGERR,tr("Wrong Format for factor 3")); return; }
1601 
1602  BaseObjectData* object = 0;
1603  PluginFunctions::getObject(pW->getBaseObjectDataId(),object);
1604  if (object != 0) {
1605  if (object->manipulatorNode()->visible() && (object->target()
1606  || !allTargets_)) {
1607 
1608  object->manipulatorNode()->scale(scale);
1609 
1611 
1612  if (PluginFunctions::pickMode() == "Move")
1613  {
1614  if (object->dataType(DATA_TRIANGLE_MESH))
1616  if (object->dataType(DATA_POLY_MESH))
1618  #ifdef ENABLE_TSPLINEMESH_SUPPORT
1619  if (object->dataType(DATA_TSPLINE_MESH))
1620  transformMesh(m, (*PluginFunctions::tsplineMesh(object)));
1621  #endif
1622  #ifdef ENABLE_OPENVOLUMEMESH_HEXAHEDRAL_SUPPORT
1623  if (object->dataType(DATA_HEXAHEDRAL_MESH))
1624  transformVolumeMesh(m, (*PluginFunctions::hexahedralMesh(object)), (PluginFunctions::hexahedralMeshObject(object)->normals()));
1625  #endif
1626  #ifdef ENABLE_OPENVOLUMEMESH_TETRAHEDRAL_SUPPORT
1627  if (object->dataType(DATA_TETRAHEDRAL_MESH))
1628  transformVolumeMesh(m, (*PluginFunctions::tetrahedralMesh(object)), (PluginFunctions::tetrahedralMeshObject(object)->normals()));
1629  #endif
1630  #ifdef ENABLE_OPENVOLUMEMESH_POLYHEDRAL_SUPPORT
1631  if (object->dataType(DATA_POLYHEDRAL_MESH))
1632  transformVolumeMesh(m, (*PluginFunctions::polyhedralMesh(object)), (PluginFunctions::polyhedralMeshObject(object)->normals()));
1633  #endif
1634 
1635  // Create backup
1636  emit createBackup(object->id(), "Scaling of object");
1637  }
1638  else if (PluginFunctions::pickMode() == "MoveSelection")
1639  {
1641  if (selectionType_ & VERTEX) {
1642  transformVertexSelection(object->id(), m);
1643  }
1644  if (selectionType_ & FACE) {
1645  transformFaceSelection(object->id(), m);
1646  }
1647  if (selectionType_ & EDGE) {
1648  transformEdgeSelection(object->id(), m);
1649  }
1650  if (selectionType_ & CELL) {
1651  transformCellSelection(object->id(), m);
1652  }
1653 
1654  // Create backup
1655  emit createBackup(object->id(), "Scaling of selection");
1656  }
1657 
1658  // move all other targets without manipulator
1659  if(allTargets_) {
1660 
1662  != PluginFunctions::objectsEnd(); ++o_it) {
1663  if ((o_it->id() != object->id()) && !o_it->manipulatorNode()->draw_manipulator()) { // If it has its own manipulator active, dont move it
1664 
1665  if (PluginFunctions::pickMode() == "Move")
1666  {
1667  if (o_it->dataType(DATA_TRIANGLE_MESH))
1669 
1670  if (o_it->dataType(DATA_POLY_MESH))
1672  #ifdef ENABLE_TSPLINEMESH_SUPPORT
1673  if (o_it->dataType(DATA_TSPLINE_MESH))
1674  transformMesh(m, (*PluginFunctions::tsplineMesh(o_it)));
1675  #endif
1676  #ifdef ENABLE_OPENVOLUMEMESH_HEXAHEDRAL_SUPPORT
1677  if (object->dataType(DATA_HEXAHEDRAL_MESH))
1678  transformVolumeMesh(m, (*PluginFunctions::hexahedralMesh(object)), (PluginFunctions::hexahedralMeshObject(object)->normals()));
1679  #endif
1680  #ifdef ENABLE_OPENVOLUMEMESH_TETRAHEDRAL_SUPPORT
1681  if (object->dataType(DATA_TETRAHEDRAL_MESH))
1682  transformVolumeMesh(m, (*PluginFunctions::tetrahedralMesh(object)), (PluginFunctions::tetrahedralMeshObject(object)->normals()));
1683  #endif
1684  #ifdef ENABLE_OPENVOLUMEMESH_POLYHEDRAL_SUPPORT
1685  if (object->dataType(DATA_POLYHEDRAL_MESH))
1686  transformVolumeMesh(m, (*PluginFunctions::polyhedralMesh(object)), (PluginFunctions::polyhedralMeshObject(object)->normals()));
1687  #endif
1688 
1689  // Create backup
1690  emit createBackup(o_it->id(), "Scaling of object");
1691  }
1692  else if (PluginFunctions::pickMode() == "MoveSelection")
1693  {
1695  if (selectionType_ & VERTEX) {
1696  transformVertexSelection(o_it->id(), m);
1697  }
1698  if (selectionType_ & FACE) {
1699  transformFaceSelection(o_it->id(), m);
1700  }
1701  if (selectionType_ & EDGE) {
1702  transformEdgeSelection(o_it->id(), m);
1703  }
1704  if (selectionType_ & CELL) {
1705  transformCellSelection(o_it->id(), m);
1706  }
1707 
1708  // Create backup
1709  emit createBackup(o_it->id(), "Scaling of selection");
1710  }
1711 
1712  emit updatedObject(o_it->id(), UPDATE_GEOMETRY);
1713  }
1714  }
1715 
1716  }
1717 
1719 
1720  emit createBackup(object->id(), "Scaling");
1721  emit updatedObject(object->id(), UPDATE_GEOMETRY);
1722  }
1723  }
1724 
1725  emit scriptInfo(QString("slotScale()"));
1726  emit updateView();
1727 }
1728 
1729 
1730 //------------------------------------------------------------------------------
1731 
1732 
1737 
1738  bool useCommonCOG = false;
1739  ACG::Vec3d cog = ACG::Vec3d(0.0,0.0,0.0);
1740 
1741  if ( PluginFunctions::targetCount() > 1 ) {
1742  if ( OpenFlipper::Options::gui()) {
1743  QMessageBox::StandardButton button = QMessageBox::question( 0, tr("Use common COG?"), tr("Should the targets be moved depending on their common cog?"),QMessageBox::Yes|QMessageBox::No);
1744 
1745 
1746  useCommonCOG = ( button == QMessageBox::Yes );
1747  }
1748 
1749  if ( useCommonCOG ) {
1750 
1751  double vertexCount = 0.0;
1752 
1753  // Compute cog for all objects
1755  if ( o_it->dataType( DATA_TRIANGLE_MESH )) {
1756  TriMesh* mesh = PluginFunctions::triMesh(*o_it);
1757  cog += MeshInfo::cog(mesh) * double(mesh->n_vertices());
1758  vertexCount += double(mesh->n_vertices());
1759  }
1760 
1761  if ( o_it->dataType( DATA_POLY_MESH )) {
1762  PolyMesh* mesh = PluginFunctions::polyMesh(*o_it);
1763  cog += MeshInfo::cog(mesh) * double(mesh->n_vertices());
1764  vertexCount += double(mesh->n_vertices());
1765  }
1766 
1767 #ifdef ENABLE_TSPLINEMESH_SUPPORT
1768  if ( o_it->dataType( DATA_TSPLINE_MESH )) {
1769  TSplineMesh& mesh = *PluginFunctions::tsplineMesh(*o_it);
1770  cog += MeshInfo::cog(mesh) * double(mesh.n_vertices());
1771  vertexCount += double(mesh.n_vertices());
1772  }
1773 #endif
1774 
1775 #ifdef ENABLE_OPENVOLUMEMESH_HEXAHEDRAL_SUPPORT
1776  if ( o_it->dataType( DATA_HEXAHEDRAL_MESH )) {
1778  cog += cogVolumeMesh(mesh) * double(mesh.n_vertices());
1779  vertexCount += double(mesh.n_vertices());
1780  }
1781 #endif
1782 
1783 #ifdef ENABLE_OPENVOLUMEMESH_TETRAHEDRAL_SUPPORT
1784  if ( o_it->dataType( DATA_TETRAHEDRAL_MESH )) {
1785  TetrahedralMesh& mesh = *PluginFunctions::tetrahedralMesh(*o_it);
1786  cog += cogVolumeMesh(mesh) * double(mesh.n_vertices());
1787  vertexCount += double(mesh.n_vertices());
1788  }
1789 #endif
1790 
1791 #ifdef ENABLE_OPENVOLUMEMESH_POLYHEDRAL_SUPPORT
1792  if ( o_it->dataType( DATA_POLYHEDRAL_MESH )) {
1794  cog += cogVolumeMesh(mesh) * double(mesh.n_vertices());
1795  vertexCount += double(mesh.n_vertices());
1796  }
1797 #endif
1798  }
1799 
1800  cog = cog / vertexCount;
1801  }
1802 
1803  }
1804 
1806  if ( o_it->dataType( DATA_TRIANGLE_MESH )) {
1807  TriMesh* mesh = PluginFunctions::triMesh(*o_it);
1808 
1809  if ( !useCommonCOG )
1810  cog = MeshInfo::cog(mesh);
1811 
1812  for ( TriMesh::VertexIter v_it = mesh->vertices_begin(); v_it != mesh->vertices_end() ; ++v_it)
1813  mesh->set_point(*v_it , ( mesh->point(*v_it) ) - cog );
1814 
1815  o_it->manipulatorNode()->set_center( o_it->manipulatorNode()->center() - cog );
1816  }
1817 
1818  if ( o_it->dataType( DATA_POLY_MESH )) {
1819  PolyMesh* mesh = PluginFunctions::polyMesh(*o_it);
1820 
1821  if ( !useCommonCOG )
1822  cog = MeshInfo::cog(mesh);
1823 
1824  for ( PolyMesh::VertexIter v_it = mesh->vertices_begin(); v_it != mesh->vertices_end() ; ++v_it)
1825  mesh->set_point(*v_it , ( mesh->point(*v_it) ) - cog );
1826 
1827  o_it->manipulatorNode()->set_center( o_it->manipulatorNode()->center() - cog );
1828 
1829  }
1830 
1831 #ifdef ENABLE_TSPLINEMESH_SUPPORT
1832  if ( o_it->dataType( DATA_TSPLINE_MESH )) {
1833  TSplineMesh* mesh = PluginFunctions::tsplineMesh(*o_it);
1834 
1835  if ( !useCommonCOG )
1836  cog = MeshInfo::cog(mesh);
1837 
1838  for ( TSplineMesh::VertexIter v_it = mesh->vertices_begin(); v_it != mesh->vertices_end() ; ++v_it)
1839  mesh->set_point(v_it , ( mesh->point(v_it) ) - cog );
1840 
1841  o_it->manipulatorNode()->set_center( o_it->manipulatorNode()->center() - cog );
1842 
1843  }
1844 #endif
1845 
1846 #ifdef ENABLE_OPENVOLUMEMESH_HEXAHEDRAL_SUPPORT
1847  if ( o_it->dataType( DATA_HEXAHEDRAL_MESH )) {
1849 
1850  if ( !useCommonCOG )
1851  cog = cogVolumeMesh(mesh);
1852 
1853  for ( OpenVolumeMesh::VertexIter v_it = mesh.vertices_begin(); v_it != mesh.vertices_end() ; ++v_it)
1854  mesh.set_vertex(*v_it , mesh.vertex(*v_it) - cog );
1855 
1856  o_it->manipulatorNode()->set_center( o_it->manipulatorNode()->center() - cog );
1857 
1858  }
1859 #endif
1860 
1861 #ifdef ENABLE_OPENVOLUMEMESH_TETRAHEDRAL_SUPPORT
1862  if ( o_it->dataType( DATA_TETRAHEDRAL_MESH )) {
1863  TetrahedralMesh& mesh = *PluginFunctions::tetrahedralMesh(*o_it);
1864 
1865  if ( !useCommonCOG )
1866  cog = cogVolumeMesh(mesh);
1867 
1868  for ( OpenVolumeMesh::VertexIter v_it = mesh.vertices_begin(); v_it != mesh.vertices_end() ; ++v_it)
1869  mesh.set_vertex(*v_it , mesh.vertex(*v_it) - cog );
1870 
1871  o_it->manipulatorNode()->set_center( o_it->manipulatorNode()->center() - cog );
1872 
1873  }
1874 #endif
1875 
1876 #ifdef ENABLE_OPENVOLUMEMESH_POLYHEDRAL_SUPPORT
1877  if ( o_it->dataType( DATA_POLYHEDRAL_MESH )) {
1879 
1880  if ( !useCommonCOG )
1881  cog = cogVolumeMesh(mesh);
1882 
1883  for ( OpenVolumeMesh::VertexIter v_it = mesh.vertices_begin(); v_it != mesh.vertices_end() ; ++v_it)
1884  mesh.set_vertex(*v_it , mesh.vertex(*v_it) - cog );
1885 
1886  o_it->manipulatorNode()->set_center( o_it->manipulatorNode()->center() - cog );
1887 
1888  }
1889 #endif
1890 
1891 
1892  emit updatedObject( o_it->id(), UPDATE_GEOMETRY );
1893 
1895  o_it->manipulatorNode()->loadIdentity();
1896 
1897  emit createBackup(o_it->id(),"Move to origin");
1898  }
1899 
1900  emit updateView();
1901 }
1902 
1903 
1904 //------------------------------------------------------------------------------
1905 
1910 {
1911  unifyBoundingBox(MovePlugin::DIAGONAL);
1912 }
1913 
1915 {
1916  unifyBoundingBox((MovePlugin::LONGEST_AXIS));
1917 }
1918 
1920 {
1921  unifyBoundingBox(MovePlugin::ALL_AXIS);
1922 }
1923 
1925 {
1926  bool useCommonBB = false;
1927  ACG::Vec3d bb_min = ACG::Vec3d(FLT_MAX,FLT_MAX,FLT_MAX);
1928  ACG::Vec3d bb_max = ACG::Vec3d(FLT_MIN,FLT_MIN,FLT_MIN);
1929 
1930  if ( PluginFunctions::targetCount() > 1 ) {
1931  if ( OpenFlipper::Options::gui()) {
1932  QMessageBox::StandardButton button = QMessageBox::question( 0, tr("Use common BB?"), tr("Should the targets be scaled depending on their common Bounding Box?"),QMessageBox::Yes|QMessageBox::No);
1933 
1934 
1935  useCommonBB = ( button == QMessageBox::Yes );
1936  }
1937 
1938 
1939  if ( useCommonBB ) {
1940 
1941  // Compute cog for all objects
1943  ACG::Vec3d bb_min_tmp(0.0,0.0,0.0);
1944  ACG::Vec3d bb_max_tmp(0.0,0.0,0.0);
1945 
1946  if ( o_it->dataType( DATA_TRIANGLE_MESH )) {
1947  TriMesh& mesh = *PluginFunctions::triMesh(*o_it);
1948  getBB(mesh,bb_min_tmp,bb_max_tmp);
1949  bb_min.minimize(bb_min_tmp);
1950  bb_max.maximize(bb_max_tmp);
1951  }
1952 
1953  if ( o_it->dataType( DATA_POLY_MESH )) {
1954  PolyMesh& mesh = *PluginFunctions::polyMesh(*o_it);
1955  getBB(mesh,bb_min_tmp,bb_max_tmp);
1956  bb_min.minimize(bb_min_tmp);
1957  bb_max.maximize(bb_max_tmp);
1958  }
1959 
1960 #ifdef ENABLE_TSPLINEMESH_SUPPORT
1961  if ( o_it->dataType( DATA_TSPLINE_MESH )) {
1962  TSplineMesh& mesh = *PluginFunctions::tsplineMesh(*o_it);
1963  getBB(mesh,bb_min_tmp,bb_max_tmp);
1964  bb_min.minimize(bb_min_tmp);
1965  bb_max.maximize(bb_max_tmp);
1966  }
1967 #endif
1968 
1969 #ifdef ENABLE_OPENVOLUMEMESH_HEXAHEDRAL_SUPPORT
1970  if ( o_it->dataType( DATA_HEXAHEDRAL_MESH )) {
1972  getBBVolumeMesh(mesh,bb_min_tmp,bb_max_tmp);
1973  bb_min.minimize(bb_min_tmp);
1974  bb_max.maximize(bb_max_tmp);
1975  }
1976 #endif
1977 
1978 #ifdef ENABLE_OPENVOLUMEMESH_TETRAHEDRAL_SUPPORT
1979  if ( o_it->dataType( DATA_TETRAHEDRAL_MESH )) {
1980  TetrahedralMesh& mesh = *PluginFunctions::tetrahedralMesh(*o_it);
1981  getBBVolumeMesh(mesh,bb_min_tmp,bb_max_tmp);
1982  bb_min.minimize(bb_min_tmp);
1983  bb_max.maximize(bb_max_tmp);
1984  }
1985 #endif
1986 
1987 #ifdef ENABLE_OPENVOLUMEMESH_POLYHEDRAL_SUPPORT
1988  if ( o_it->dataType( DATA_POLYHEDRAL_MESH )) {
1990  getBBVolumeMesh(mesh,bb_min_tmp,bb_max_tmp);
1991  bb_min.minimize(bb_min_tmp);
1992  bb_max.maximize(bb_max_tmp);
1993  }
1994 #endif
1995  }
1996  }
1997 
1998  }
1999 
2001  if ( useCommonBB ) {
2002  if ( o_it->dataType( DATA_TRIANGLE_MESH ) )
2003  unifyBB(*PluginFunctions::triMesh(*o_it),bb_min,bb_max, u);
2004  else if ( o_it->dataType( DATA_POLY_MESH ) )
2005  unifyBB(*PluginFunctions::polyMesh(*o_it),bb_min,bb_max, u);
2006 #ifdef ENABLE_TSPLINEMESH_SUPPORT
2007  else if ( o_it->dataType( DATA_TSPLINE_MESH ) )
2008  unifyBB(*PluginFunctions::tsplineMesh(*o_it),bb_min,bb_max, u);
2009 #endif
2010 #ifdef ENABLE_OPENVOLUMEMESH_HEXAHEDRAL_SUPPORT
2011  else if ( o_it->dataType( DATA_HEXAHEDRAL_MESH ) )
2012  unifyBBVolumeMesh(*PluginFunctions::hexahedralMesh(*o_it),(PluginFunctions::hexahedralMeshObject(*o_it)->normals()),bb_min,bb_max, u);
2013 #endif
2014 #ifdef ENABLE_OPENVOLUMEMESH_TETRAHEDRAL_SUPPORT
2015  else if ( o_it->dataType( DATA_TETRAHEDRAL_MESH ) )
2016  unifyBBVolumeMesh(*PluginFunctions::tetrahedralMesh(*o_it),(PluginFunctions::tetrahedralMeshObject(*o_it)->normals()),bb_min,bb_max, u);
2017 #endif
2018 #ifdef ENABLE_OPENVOLUMEMESH_POLYHEDRAL_SUPPORT
2019  else if ( o_it->dataType( DATA_POLYHEDRAL_MESH ) )
2020  unifyBBVolumeMesh(*PluginFunctions::polyhedralMesh(*o_it),(PluginFunctions::polyhedralMeshObject(*o_it)->normals()),bb_min,bb_max, u);
2021 #endif
2022  } else {
2023  if ( o_it->dataType( DATA_TRIANGLE_MESH ) )
2024  unifyBB(*PluginFunctions::triMesh(*o_it), u);
2025  else if ( o_it->dataType( DATA_POLY_MESH ) )
2026  unifyBB(*PluginFunctions::polyMesh(*o_it), u);
2027 #ifdef ENABLE_TSPLINEMESH_SUPPORT
2028  else if ( o_it->dataType( DATA_TSPLINE_MESH ) )
2029  unifyBB(*PluginFunctions::tsplineMesh(*o_it), u);
2030 #endif
2031 #ifdef ENABLE_OPENVOLUMEMESH_HEXAHEDRAL_SUPPORT
2032  else if ( o_it->dataType( DATA_HEXAHEDRAL_MESH ) )
2033  unifyBBVolumeMesh(*PluginFunctions::hexahedralMesh(*o_it),(PluginFunctions::hexahedralMeshObject(*o_it)->normals()), u);
2034 #endif
2035 #ifdef ENABLE_OPENVOLUMEMESH_TETRAHEDRAL_SUPPORT
2036  else if ( o_it->dataType( DATA_TETRAHEDRAL_MESH ) )
2037  unifyBBVolumeMesh(*PluginFunctions::tetrahedralMesh(*o_it),(PluginFunctions::tetrahedralMeshObject(*o_it)->normals()), u);
2038 #endif
2039 #ifdef ENABLE_OPENVOLUMEMESH_POLYHEDRAL_SUPPORT
2040  else if ( o_it->dataType( DATA_POLYHEDRAL_MESH ) )
2041  unifyBBVolumeMesh(*PluginFunctions::polyhedralMesh(*o_it),(PluginFunctions::polyhedralMeshObject(*o_it)->normals()), u);
2042 #endif
2043  }
2044 
2045  emit updatedObject( o_it->id(), UPDATE_GEOMETRY );
2046 
2047  }
2048 
2049  emit updateView();
2050 }
2051 
2052 
2053 //------------------------------------------------------------------------------
2054 
2059 
2060  BaseObjectData* object;
2062  return;
2063  }
2064 
2065  if ( object->manipulatorNode()->visible() ) {
2066 
2067  // Get properties widget that corresponds to
2068  // to the last manipulated object
2069  movePropsWidget* pW = getDialogWidget(object);
2070 
2071  // If there's no properties dialog yet...
2072  if(pW == 0) return;
2073 
2074  const TriMesh::Point pos = object->manipulatorNode()->center();
2075 
2076  QString num;
2077 
2078  num = QString::number(pos[0]); pW->posx->setText(num);
2079  num = QString::number(pos[1]); pW->posy->setText(num);
2080  num = QString::number(pos[2]); pW->posz->setText(num);
2081 
2082  TriMesh::Point direction = object->manipulatorNode()->directionX();
2083  num = QString::number(direction[0]); pW->dirxx->setText(num);
2084  num = QString::number(direction[1]); pW->dirxy->setText(num);
2085  num = QString::number(direction[2]); pW->dirxz->setText(num);
2086 
2087  direction = object->manipulatorNode()->directionY();
2088  num = QString::number(direction[0]); pW->diryx->setText(num);
2089  num = QString::number(direction[1]); pW->diryy->setText(num);
2090  num = QString::number(direction[2]); pW->diryz->setText(num);
2091 
2092  direction = object->manipulatorNode()->directionZ();
2093  num = QString::number(direction[0]); pW->dirzx->setText(num);
2094  num = QString::number(direction[1]); pW->dirzy->setText(num);
2095  num = QString::number(direction[2]); pW->dirzz->setText(num);
2096 
2097  }
2098 }
2099 
2100 //------------------------------------------------------------------------------
2101 
2107 
2108  for(QList<movePropsWidget*>::iterator it = propsWindows_.begin();
2109  it != propsWindows_.end(); ++it) {
2110  if ( (*it)->getBaseObjectDataId() == _obj->id() )
2111  return *it;
2112  }
2113  return 0;
2114 }
2115 //------------------------------------------------------------------------------
2116 
2121 void MovePlugin::slotSetMoveMode(QAction* _action) {
2122 
2123  if (_action == moveAction_){
2124  PluginFunctions::actionMode(Viewer::PickingMode);
2125  PluginFunctions::pickMode("Move");
2126 
2127  moveAction_->setChecked( true );
2128  }
2129 
2130  if (_action == moveSelectionAction_){
2131 
2132  PluginFunctions::actionMode(Viewer::PickingMode);
2133  PluginFunctions::pickMode("MoveSelection");
2134 
2135  moveSelectionAction_->setChecked( true );
2136  }
2137 }
2138 
2139 //------------------------------------------------------------------------------
2140 
2147 {
2148 
2149  if (_action == rotateTranslateAction_)
2150  {
2151  setManipMode (QtTranslationManipulatorNode::TranslationRotation);
2152  }
2153 
2154  if (_action == rotateManipAction_)
2155  {
2156  setManipMode (QtTranslationManipulatorNode::LocalRotation);
2157  }
2158 
2159  if (_action == placeAndSnapAction_)
2160  {
2161  setManipMode(QtTranslationManipulatorNode::Place);
2162  }
2163 
2164  if (_action == resizeAction_)
2165  {
2166  setManipMode(QtTranslationManipulatorNode::Resize);
2167  }
2168 
2169  if (_action == biggerManipAction_)
2170  {
2173  o_it->manipulatorNode()->set_size(manip_size_ * manip_size_modifier_);
2174  emit nodeVisibilityChanged (-1);
2175  }
2176 
2177  if (_action == smallerManipAction_)
2178  {
2181  o_it->manipulatorNode()->set_size(manip_size_ * manip_size_modifier_);
2182  emit nodeVisibilityChanged (-1);
2183  }
2184 }
2185 
2186 
2187 //------------------------------------------------------------------------------
2188 
2195  ACG::Matrix4x4d matrix;
2196  matrix.identity();
2197 
2198  BaseObjectData* object;
2200  if ( object->manipulatorNode()->visible() ) {
2201  matrix = object->manipulatorNode()->matrix();
2202  if (_reset)
2203  object->manipulatorNode()->loadIdentity();
2204  }
2205  return matrix;
2206 }
2207 
2208 
2209 //------------------------------------------------------------------------------
2210 
2219 template< typename MeshT >
2220 void MovePlugin::transformMesh(ACG::Matrix4x4d _mat , MeshT& _mesh ) {
2221  // Get the inverse matrix of the transformation for the normals
2222  ACG::Matrix4x4d invTranspMat = _mat;
2223 
2224  // Build inverse transposed matrix of _mat
2225  invTranspMat.invert();
2226  invTranspMat.transpose();
2227 
2228  typename MeshT::VertexIter v_it = _mesh.vertices_begin();
2229  typename MeshT::VertexIter v_end = _mesh.vertices_end();
2230  for (; v_it!=v_end; ++v_it) {
2231 
2232  // transform the mesh vertex
2233  _mesh.set_point(*v_it,_mat.transform_point(_mesh.point(*v_it)));
2234 
2235  // transform the vertex normal
2236  typename MeshT::Normal n = invTranspMat.transform_vector(_mesh.normal(*v_it));
2237 
2238  n.normalize();
2239 
2240  _mesh.set_normal(*v_it,n);
2241  }
2242 
2243  typename MeshT::FaceIter f_it = _mesh.faces_begin();
2244  typename MeshT::FaceIter f_end = _mesh.faces_end();
2245  for (; f_it != f_end; ++f_it) {
2246 
2247  // transform the face normal
2248  typename MeshT::Normal n = invTranspMat.transform_vector(_mesh.normal(*f_it));
2249 
2250  n.normalize();
2251 
2252  _mesh.set_normal(*f_it,n);
2253  }
2254 }
2255 
2256 
2257 //------------------------------------------------------------------------------
2258 
2259 #ifdef ENABLE_POLYLINE_SUPPORT
2260 
2266 template< class PolyLineT >
2267 void MovePlugin::transformPolyLine( ACG::Matrix4x4d _mat , PolyLineT& _polyLine ) {
2268  #ifdef USE_OPENMP
2269  #pragma omp parallel for
2270  #endif
2271  for ( int i = 0 ; i < (int)_polyLine.n_vertices(); ++i )
2272  _polyLine.point(i) = _mat.transform_point( _polyLine.point(i) );
2273 }
2274 
2275 #endif
2276 
2277 
2278 //------------------------------------------------------------------------------
2279 
2280 #ifdef ENABLE_SKELETON_SUPPORT
2281 
2287 void MovePlugin::transformSkeleton( ACG::Matrix4x4d _mat , Skeleton& _skeleton ) {
2288 
2289  SkeletonTransform transformer(_skeleton);
2290  transformer.transformSkeleton(_mat);
2291 }
2292 
2293 #endif
2294 
2295 #ifdef ENABLE_OPENVOLUMEMESH_SUPPORT
2296 
2305 template< typename VolumeMeshT >
2306 void MovePlugin::transformVolumeMesh(ACG::Matrix4x4d _mat , VolumeMeshT& _mesh , OpenVolumeMesh::NormalAttrib<VolumeMeshT>& _normalAttrib )
2307 {
2308  // Get the inverse matrix of the transformation for the normals
2309  ACG::Matrix4x4d invTranspMat = _mat;
2310 
2311  // Build inverse transposed matrix of _mat
2312  invTranspMat.invert();
2313  invTranspMat.transpose();
2314 
2315  OpenVolumeMesh::VertexIter v_begin = _mesh.vertices_begin();
2316  OpenVolumeMesh::VertexIter v_end = _mesh.vertices_end();
2317 
2318  // transform the mesh vertices
2319  for (OpenVolumeMesh::VertexIter v_it = v_begin; v_it != v_end; ++v_it)
2320  _mesh.set_vertex(*v_it, _mat.transform_point(_mesh.vertex(*v_it)));
2321 
2322  // transform the vertex normals
2323  for (OpenVolumeMesh::VertexIter v_it = v_begin; v_it != v_end; ++v_it)
2324  _normalAttrib[*v_it] = invTranspMat.transform_vector(_normalAttrib[*v_it]).normalized();
2325 
2326 
2327  // transform the face normals
2328  OpenVolumeMesh::FaceIter f_begin = _mesh.faces_begin();
2329  OpenVolumeMesh::FaceIter f_end = _mesh.faces_end();
2330  for (OpenVolumeMesh::FaceIter f_it = f_begin; f_it != f_end; ++f_it)
2331  _normalAttrib[*f_it] = invTranspMat.transform_vector(_normalAttrib[*f_it]).normalized();
2332 }
2333 
2334 //------------------------------------------------------------------------------
2335 
2340 template< typename VolumeMeshT >
2341 ACG::Vec3d MovePlugin::cogVolumeMesh( VolumeMeshT& _mesh )
2342 {
2343  ACG::Vec3d cog = ACG::Vec3d(0.0,0.0,0.0);
2344  OpenVolumeMesh::VertexIter v_it = _mesh.vertices_begin();
2345  OpenVolumeMesh::VertexIter v_end = _mesh.vertices_end();
2346  for (; v_it!=v_end; ++v_it)
2347  cog += _mesh.vertex(*v_it);
2348 
2349  return cog/(double)_mesh.n_vertices();
2350 }
2351 
2352 //------------------------------------------------------------------------------
2353 
2360 template< typename VolumeMeshT >
2361 void MovePlugin::getBBVolumeMesh( VolumeMeshT& _mesh, ACG::Vec3d& _bb_min, ACG::Vec3d& _bb_max)
2362 {
2363  OpenVolumeMesh::VertexIter v_it = _mesh.vertices_begin();
2364  OpenVolumeMesh::VertexIter v_end = _mesh.vertices_end();
2365 
2366  // no vertices?
2367  if( v_it == v_end) return;
2368 
2369  _bb_min = _mesh.vertex(*v_it);
2370  _bb_max = _mesh.vertex(*v_it);
2371 
2372  for(; v_it!=v_end; ++v_it)
2373  {
2374  _bb_min.minimize( _mesh.vertex(*v_it));
2375  _bb_max.maximize( _mesh.vertex(*v_it));
2376  }
2377 }
2378 
2379 //------------------------------------------------------------------------------
2380 
2386 template< typename VolumeMeshT >
2387 void MovePlugin::unifyBBVolumeMesh(VolumeMeshT& _mesh, OpenVolumeMesh::NormalAttrib<VolumeMeshT>& _normalAttrib, Unificationtype u)
2388 {
2389  // no vertices?
2390  if( _mesh.n_vertices() == 0) return;
2391 
2392  ACG::Vec3d bb_min, bb_max;
2393  getBBVolumeMesh( _mesh, bb_min, bb_max );
2394 
2395  unifyBBVolumeMesh( _mesh, _normalAttrib, bb_min, bb_max, u );
2396 }
2397 
2398 //------------------------------------------------------------------------------
2399 
2408 template< typename VolumeMeshT >
2409 void MovePlugin::unifyBBVolumeMesh( VolumeMeshT& _mesh, OpenVolumeMesh::NormalAttrib<VolumeMeshT>& _normalAttrib, ACG::Vec3d& _bb_min, ACG::Vec3d& _bb_max, Unificationtype u)
2410 {
2411  ACG::Vec3d bb_center = 0.5 * (_bb_min + _bb_max) ;
2412  ACG::Vec3d bb_diagonal = _bb_max-_bb_min;
2413  double bb_longestAxis = bb_diagonal.max();
2414 
2415  ACG::Vec3d scale;
2416  switch(u)
2417  {
2418  case MovePlugin::DIAGONAL :
2419  scale = ACG::Vec3d(1.0/(_bb_max-_bb_min).norm());
2420  break;
2421  case MovePlugin::LONGEST_AXIS :
2422  scale = ACG::Vec3d(1.0/(bb_longestAxis));
2423  break;
2424  case MovePlugin::ALL_AXIS :
2425  scale = ACG::Vec3d(ACG::Vec3d(1.0)/bb_diagonal);
2426  break;
2427  default:
2428  scale = ACG::Vec3d(1.0/(_bb_max-_bb_min).norm());
2429  }
2430 
2431 
2432  for( OpenVolumeMesh::VertexIter v_it = _mesh.vertices_begin(); v_it!=_mesh.vertices_end(); ++v_it)
2433  _mesh.set_vertex(*v_it, (_mesh.vertex(*v_it) - bb_center) * scale + bb_center);
2434 
2435  _normalAttrib.update_vertex_normals();
2436 }
2437 
2438 #endif
2439 
2440 //------------------------------------------------------------------------------
2441 
2447 template< typename MeshT >
2448 void MovePlugin::unifyBB(MeshT& _mesh , Unificationtype u)
2449 {
2450  typename MeshT::VertexIter v_it = _mesh.vertices_begin();
2451  typename MeshT::VertexIter v_end = _mesh.vertices_end();
2452 
2453  // no vertices?
2454  if( v_it == v_end) return;
2455 
2456  typename MeshT::Point bb_min = _mesh.point(*v_it);
2457  typename MeshT::Point bb_max = _mesh.point(*v_it);
2458 
2459  for(; v_it!=v_end; ++v_it)
2460  {
2461  bb_min.minimize( _mesh.point(*v_it));
2462  bb_max.maximize( _mesh.point(*v_it));
2463  }
2464 
2465  typename MeshT::Point bb_center = 0.5 * (bb_min + bb_max) ;
2466  ACG::Vec3d bb_diagonal = bb_max-bb_min;
2467  typename MeshT::Scalar bb_longestAxis = bb_diagonal.max();
2468 
2469  ACG::Vec3d scale;
2470  switch(u)
2471  {
2472  case MovePlugin::DIAGONAL :
2473  scale = ACG::Vec3d(1.0/(bb_max-bb_min).norm());
2474  break;
2475  case MovePlugin::LONGEST_AXIS :
2476  scale = ACG::Vec3d(1.0 / bb_longestAxis);
2477  break;
2478  case MovePlugin::ALL_AXIS :
2479  scale = ACG::Vec3d(ACG::Vec3d(1.0)/bb_diagonal);
2480  break;
2481  default:
2482  scale = ACG::Vec3d(1.0/(bb_max-bb_min).norm());
2483  }
2484 
2485  for( v_it = _mesh.vertices_begin(); v_it!=v_end; ++v_it)
2486  {
2487 
2488  _mesh.point(*v_it) = (_mesh.point(*v_it) - bb_center) * scale + bb_center;
2489  }
2490 
2491  _mesh.update_normals();
2492 
2493 }
2494 
2501 template< typename MeshT >
2502 void MovePlugin::getBB( MeshT& _mesh, ACG::Vec3d& _bb_min, ACG::Vec3d& _bb_max )
2503 {
2504  typename MeshT::VertexIter v_it = _mesh.vertices_begin();
2505  typename MeshT::VertexIter v_end = _mesh.vertices_end();
2506 
2507  // no vertices?
2508  if( v_it == v_end) return;
2509 
2510  _bb_min = _mesh.point(*v_it);
2511  _bb_max = _mesh.point(*v_it);
2512 
2513  for(; v_it!=v_end; ++v_it)
2514  {
2515  _bb_min.minimize( _mesh.point(*v_it));
2516  _bb_max.maximize( _mesh.point(*v_it));
2517  }
2518 
2519 
2520 }
2521 
2529 template< typename MeshT >
2530 void MovePlugin::unifyBB(MeshT& _mesh, ACG::Vec3d& _bb_min, ACG::Vec3d& _bb_max , Unificationtype u)
2531 {
2532 
2533  typename MeshT::Point bb_center = 0.5 * (_bb_min + _bb_max) ;
2534  ACG::Vec3d bb_diagonal = _bb_max-_bb_min;
2535  typename MeshT::Scalar bb_longestAxis = bb_diagonal.max();
2536  ACG::Vec3d scale;
2537  switch(u)
2538  {
2539  case MovePlugin::DIAGONAL :
2540  scale = ACG::Vec3d(1.0/(_bb_max-_bb_min).norm());
2541  break;
2542  case MovePlugin::LONGEST_AXIS :
2543  scale = ACG::Vec3d(1.0 / bb_longestAxis);
2544  break;
2545  case MovePlugin::ALL_AXIS :
2546  scale = ACG::Vec3d(ACG::Vec3d(1.0)/bb_diagonal);
2547  break;
2548  default:
2549  scale = ACG::Vec3d(1.0/(_bb_max-_bb_min).norm());
2550  }
2551 
2552  typename MeshT::VertexIter v_it;
2553 
2554  for( v_it = _mesh.vertices_begin(); v_it!=_mesh.vertices_end(); ++v_it)
2555  _mesh.point(*v_it) = (_mesh.point(*v_it) - bb_center) * scale + bb_center;
2556 
2557  _mesh.update_normals();
2558 
2559 }
2560 
2561 
2562 //------------------------------------------------------------------------------
2563 
2568 
2569  bool functionExistsMeshV;
2570  emit functionExists("meshobjectselection", "vertexTypeActive()", functionExistsMeshV);
2571  bool functionExistsMeshE;
2572  emit functionExists("meshobjectselection", "edgeTypeActive()", functionExistsMeshE);
2573  bool functionExistsMeshF;
2574  emit functionExists("meshobjectselection", "faceTypeActive()", functionExistsMeshF);
2575 
2576  bool connected = false;
2577  selectionType_ = 0u;
2578 
2579  if(functionExistsMeshV && functionExistsMeshE && functionExistsMeshF) {
2580 
2581  connected = true;
2582 
2583  // Make RPC call
2584  if(RPC::callFunctionValue<bool>("meshobjectselection", "vertexTypeActive")) {
2585  selectionType_ |= VERTEX;
2586  }
2587  if(RPC::callFunctionValue<bool>("meshobjectselection", "edgeTypeActive")) {
2588  selectionType_ |= EDGE;
2589  }
2590  if(RPC::callFunctionValue<bool>("meshobjectselection", "faceTypeActive")) {
2591  selectionType_ |= FACE;
2592  }
2593 
2594  }
2595 
2596 #ifdef ENABLE_OPENVOLUMEMESH_SUPPORT
2597  bool functionExistsVolumeMeshV;
2598  emit functionExists("volumemeshselection", "vertexTypeActive()", functionExistsVolumeMeshV);
2599  bool functionExistsVolumeMeshE;
2600  emit functionExists("volumemeshselection", "edgeTypeActive()", functionExistsVolumeMeshE);
2601  bool functionExistsVolumeMeshF;
2602  emit functionExists("volumemeshselection", "faceTypeActive()", functionExistsVolumeMeshF);
2603  bool functionExistsVolumeMeshC;
2604  emit functionExists("volumemeshselection", "cellTypeActive()", functionExistsVolumeMeshC);
2605 
2606  if ( functionExistsVolumeMeshV && functionExistsVolumeMeshE && functionExistsVolumeMeshF && functionExistsVolumeMeshC) {
2607 
2608  connected = true;
2609 
2610  // Make RPC call
2611  if(RPC::callFunctionValue<bool>("volumemeshselection", "vertexTypeActive")) {
2612  selectionType_ |= VERTEX;
2613  }
2614  if(RPC::callFunctionValue<bool>("volumemeshselection", "edgeTypeActive")) {
2615  selectionType_ |= EDGE;
2616  }
2617  if(RPC::callFunctionValue<bool>("volumemeshselection", "faceTypeActive")) {
2618  selectionType_ |= FACE;
2619  }
2620  if(RPC::callFunctionValue<bool>("volumemeshselection", "cellTypeActive")) {
2621  selectionType_ |= CELL;
2622  }
2623  }
2624 #endif
2625 
2626  if (!connected) {
2627  emit log(LOGWARN, tr("Unable to connect to Selection-Plugin. MoveSelection will work on vertices only."));
2628  selectionType_ = VERTEX;
2629  }
2630 }
2631 
2632 //------------------------------------------------------------------------------
2633 
2639 void MovePlugin::setAllTargets(bool _state) {
2640  allTargets_ = _state;
2641 }
2642 
2643 //--------------------------------------------------------------------------------
2644 
2648 template< typename MeshType >
2649 OpenMesh::Vec3d MovePlugin::getNearestVertex(MeshType* _mesh, uint _fh, OpenMesh::Vec3d &_hitPoint) {
2650 
2651  typename MeshType::FaceHandle fh = _mesh->face_handle(_fh);
2652 
2653  if ( !fh.is_valid() )
2654  return OpenMesh::Vec3d(0.0, 0.0, 0.0);
2655 
2656  typename MeshType::FaceVertexIter fv_it(*_mesh, fh);
2657  typename MeshType::Point hitPointP = (typename MeshType::Point) _hitPoint;
2658  typename MeshType::Scalar shortest_distance = (_mesh->point(*fv_it) - hitPointP).sqrnorm();
2659  typename MeshType::VertexHandle vh = *fv_it;
2660 
2661  for (; fv_it.is_valid(); ++fv_it) {
2662 
2663  typename MeshType::Scalar tmpdist =
2664  (_mesh->point(*fv_it) - hitPointP).sqrnorm();
2665 
2666  if(tmpdist < shortest_distance) {
2667  shortest_distance = tmpdist;
2668  vh = *fv_it;
2669  }
2670  }
2671 
2672  return (OpenMesh::Vec3d)_mesh->point(vh);
2673 }
2674 
2675 //--------------------------------------------------------------------------------
2676 
2680 template< typename MeshType >
2681 OpenMesh::Vec3d MovePlugin::getNearestEdge(MeshType* _mesh, uint _fh, OpenMesh::Vec3d &_hitPoint) {
2682 
2683  typename MeshType::FaceHandle fh = _mesh->face_handle(_fh);
2684 
2685  if (!fh.is_valid())
2686  return OpenMesh::Vec3d(0.0, 0.0, 0.0);
2687 
2688  typename MeshType::FaceEdgeIter fe_it(*_mesh, fh);
2689  typename MeshType::Point hitPointP = (typename MeshType::Point) _hitPoint;
2690 
2691  typename MeshType::Point center;
2692  typename MeshType::Scalar closest_dist(-1);
2693 
2694  for (; fe_it.is_valid(); ++fe_it) {
2695 
2696  typename MeshType::HalfedgeHandle heh0 = _mesh->halfedge_handle(*fe_it, 0);
2697  typename MeshType::HalfedgeHandle heh1 = _mesh->halfedge_handle(*fe_it, 1);
2698 
2699  typename MeshType::Point lp0 = _mesh->point(_mesh->to_vertex_handle(heh0));
2700  typename MeshType::Point lp1 = _mesh->point(_mesh->to_vertex_handle(heh1));
2701 
2702  double dist_new = ACG::Geometry::distPointLineSquared( hitPointP, lp0, lp1);
2703 
2704  /*typename MeshType::Point b(hitPointP - lp0), a(((lp1 - lp0).sqrnorm()));
2705  typename MeshType::Scalar d = b|a;
2706  typename MeshType::Point x = lp0 + a * d;
2707  double dist_new = (hitPointP - x).length();*/
2708 
2709  if (dist_new < closest_dist || closest_dist == -1) {
2710  // save closest Edge
2711  closest_dist = dist_new;
2712  center = lp0 + (lp1 - lp0) * .5;
2713 
2714  }
2715  }
2716 
2717  return (OpenMesh::Vec3d)center;
2718 }
2719 
2720 //--------------------------------------------------------------------------------
2721 
2725 template< typename MeshType >
2726 OpenMesh::Vec3d MovePlugin::getNearestFace(MeshType* _mesh, uint _fh, OpenMesh::Vec3d &_hitPoint) {
2727 
2728  typename MeshType::FaceHandle fh = _mesh->face_handle(_fh);
2729 
2730  if ( !fh.is_valid() )
2731  return OpenMesh::Vec3d(0.0, 0.0, 0.0);
2732 
2733  typename MeshType::FaceVertexIter fv_it(*_mesh, fh);
2734 
2735  typename MeshType::Point cog(0.0,0.0,0.0);
2736  uint count = 0;
2737 
2738  for (; fv_it.is_valid(); ++fv_it) {
2739 
2740  cog += _mesh->point(*fv_it);
2741  ++count;
2742  }
2743 
2744  return (OpenMesh::Vec3d)cog/count;
2745 }
2746 
2747 //--------------------------------------------------------------------------------
2748 
2749 void MovePlugin::slotAllCleared(){
2750  activeManipulators_.clear();
2751 }
2752 
2753 //--------------------------------------------------------------------------------
2754 
2755 void MovePlugin::objectDeleted( int _id ){
2756 
2757  for (uint i=0; i < activeManipulators_.size(); i++)
2758  if ( activeManipulators_[i] == _id ){
2759  activeManipulators_.erase( activeManipulators_.begin() + i );
2760  return;
2761  }
2762 }
2763 
2764 //--------------------------------------------------------------------------------
2765 
2766 #if QT_VERSION < 0x050000
2767  Q_EXPORT_PLUGIN2( moveplugin , MovePlugin );
2768 #endif
2769 
void traverse(ACG::SceneGraph::MouseEventAction &_action)
void setDescriptions()
Set Descriptions for scriptable functions.
ViewObjectMarker * defaultViewObjectMarker()
Get the default ViewObjectMarker.
BaseNode * find_node(BaseNode *_root, unsigned int _node_idx)
Find a node in the scene graph.
Definition: SceneGraph.cc:83
const VecT & vertex(const VertexHandle &_vh) const
Get point _vh&#39;s coordinates.
bool transformEdgeSelection(int _objectId, Matrix4x4 _matrix)
transform current selection of an Object by a given matrix
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 transpose()
transpose matrix
Definition: Matrix4x4T.cc:272
QMenu * contextMenuManipControl_
Additional Context Menu replicating the toolbar stuff.
Definition: MovePlugin.hh:495
QAction * moveSelectionAction_
Called by Toolbar to enable move mode.
Definition: MovePlugin.hh:279
~MovePlugin()
Destructor.
Definition: MovePlugin.cc:133
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
void slotMouseEvent(QMouseEvent *_event)
MousePress event occured.
Definition: MovePlugin.cc:403
QAction * moveAction_
Called by Toolbar to enable move mode.
Definition: MovePlugin.hh:278
bool toolboxActive_
True if the toolbox widget is active.
Definition: MovePlugin.hh:263
void slotToggleAxisB()
Toggle the second axis for changing direction in tab.
Definition: MovePlugin.cc:1134
Add normals to mesh item (vertices/faces)
Definition: Attributes.hh:87
void translate(Scalar _x, Scalar _y, Scalar _z, MultiplyFrom _mult_from=MULT_FROM_RIGHT)
multiply self with translation matrix (x,y,z)
Definition: GLMatrixT.cc:102
QList< movePropsWidget * > propsWindows_
List of properties dialogs (each corresponding to one manipulator)
Definition: MovePlugin.hh:483
bool transformFaceSelection(int _objectId, Matrix4x4 _matrix)
transform current selection of an Object by a given matrix
void moveObject(ACG::Matrix4x4d mat, int _id)
Move an object with given id.
Definition: MovePlugin.cc:577
The Menu will be shown when a node was picked.
OpenMesh::Vec3d getNearestEdge(MeshType *_mesh, uint _fh, OpenMesh::Vec3d &_hitPoint)
Get closest edge to hitpoint.
Definition: MovePlugin.cc:2681
SelectionType selectionType_
Current SelectionType of SelectionPlugin.
Definition: MovePlugin.hh:442
Vec::value_type distPointLineSquared(const Vec &_p, const Vec &_v0, const Vec &_v1, Vec *_min_v)
squared distance from point _p to line segment (_v0,_v1)
Definition: Algorithms.cc:300
bool getObject(int _identifier, BSplineCurveObject *&_object)
QToolBar * toolbar_
Called by Toolbar to enable move mode.
Definition: MovePlugin.hh:283
PolyMesh * polyMesh(BaseObjectData *_object)
Get a poly mesh from an object.
bool dataType(DataType _type) const
Definition: BaseObject.cc:232
QActionGroup * pickToolBarActions_
Called by pick Toolbar.
Definition: MovePlugin.hh:314
bool transformVertexSelection(int _objectId, Matrix4x4 _matrix)
transform current selection of an Object by a given matrix
const QStringList TARGET_OBJECTS("target")
Iterable object range.
void slotToggleAxisA()
Toggle the first axis for changing direction in tab.
Definition: MovePlugin.cc:1109
QIcon * toolIcon_
stores the current axes in the tool
Definition: MovePlugin.hh:268
void pluginsInitialized()
Initialization of the plugin when it is loaded by the core.
Definition: MovePlugin.cc:164
void updateSelectionType()
Get current primitive selection.
Definition: MovePlugin.cc:2567
MovePlugin()
Default Constructor.
Definition: MovePlugin.cc:90
bool visible()
Is node visible (status == Active)?
Definition: MeshNode2T.cc:440
#define DATA_POLYHEDRAL_MESH
void translateEdgeSelection(int _objectId, Vector _vector)
translate current edge selection of an Object by a given vector
QAction * rotateManipAction_
Called by pick Toolbar.
Definition: MovePlugin.hh:302
QAction * placeAndSnapAction_
Called by pick Toolbar.
Definition: MovePlugin.hh:312
MeshT * mesh()
return a pointer to the mesh
void hideManipulator()
Hide the manipulator( Called via context for picking. Get the picked id from the Qvariant attached to...
void setManipMode(QtTranslationManipulatorNode::ManipulatorMode _mode)
Set the manipulator manipulation mode.
Definition: MovePlugin.cc:674
void showProps()
Show properties of move manipulator in a dialog ( Called via context for picking. Get the picked id f...
Skeleton transformation class.
QAction * smallerManipAction_
Called by pick Toolbar.
Definition: MovePlugin.hh:306
int getIdentifier()
Get an identifier for that manipulator.
int id() const
Definition: BaseObject.cc:201
void slotEnableSelectionMode()
stores the current axes in the tool
Definition: MovePlugin.cc:479
const QStringList ALL_OBJECTS
Iterable object range.
void slotUnifyBoundingBoxAllAxis()
Scale all Boundingbox axis to unit size.
Definition: MovePlugin.cc:1919
void set_vertex(const VertexHandle &_vh, const VecT &_p)
Set the coordinates of point _vh.
bool getPickedObject(const unsigned int _node_idx, BaseObjectData *&_object)
Get the picked mesh.
QtTranslationManipulatorNode * manipulatorNode()
void slotUnifyBoundingBoxLongestAxis()
Scale Boundingbox longest axis to unit size (keeps aspect ratio)
Definition: MovePlugin.cc:1914
void moveSelection(ACG::Matrix4x4d mat, int _id, QEvent::Type _type)
Move selection on an object with given id.
Definition: MovePlugin.cc:641
#define DATA_POLY_LINE
Definition: PolyLine.hh:70
QToolBar * pickToolbar_
Called by pick Toolbar.
Definition: MovePlugin.hh:298
const GLMatrixd & matrix() const
Returns a const reference to the current transformation matrix.
a class which provides an link generator for WhatsThisMessages linking to the user doc If you have an...
bool is_identity() const
check if the matrix is the identity ( up to an epsilon )
Definition: Matrix4x4T.hh:220
void translate(int _objectId, Vector _vector)
translate an Object by a given vector
void slotProjectToTangentPlane()
Project the current manipulator onto the tangent plane of the object.
Definition: MovePlugin.cc:1345
PolyLine * polyLine(BaseObjectData *_object)
Get a poly Line from an object.
void identity()
setup an identity matrix
Definition: Matrix4x4T.cc:256
const std::string pickMode()
Get the current Picking mode.
vector_type & maximize(const vector_type &_rhs)
maximize values: same as *this = max(*this, _rhs), but faster
Definition: Vector11T.hh:562
bool transformedSelected_
stores if any selected elements where transformed
Definition: MovePlugin.hh:624
void slotMoveToOrigin()
Move target Meshes cog to the origin.
Definition: MovePlugin.cc:1736
void transformMesh(ACG::Matrix4x4d _mat, MeshT &_mesh)
Transform a mesh with the given transformation matrix.
Definition: MovePlugin.cc:2220
const NormalAttrib & normals() const
return a pointer to the mesh
bool transformCellSelection(int _objectId, Matrix4x4 _matrix)
transform current selection of an Object by a given matrix
#define DATA_HEXAHEDRAL_MESH
HexahedralMeshObject * hexahedralMeshObject(BaseObjectData *_object)
Cast an BaseObject to an HexahedralMeshObject if possible.
virtual const std::string & className() const =0
Return class name (implemented by the ACG_CLASSNAME macro)
void manipulatorMoved(QtTranslationManipulatorNode *_node, QMouseEvent *_event)
move the object when its manipulator moves
Definition: MovePlugin.cc:776
Viewer::ViewerProperties & viewerProperties(int _id)
Get the viewer properties Use this functions to get basic viewer properties such as backgroundcolor o...
QAction * contextAction_
Context menu entry for showing per manipulator settings.
Definition: MovePlugin.hh:486
MoveObjectMarker objectMarker_
Object marker to dimm Objects during manipulator transformation.
Definition: MovePlugin.hh:425
movePropsWidget * getDialogWidget(BaseObjectData *_obj)
Get properties dialog widget that is attached to BaseDataObject obj.
Definition: MovePlugin.cc:2106
void slotRotate()
Rotate Manipulator (with values from Tab)
Definition: MovePlugin.cc:1429
void slotUnifyBoundingBoxDiagonal()
Scale Boundingbox Diagonal to unit size.
Definition: MovePlugin.cc:1909
ACG::Matrix4x4d getLastManipulatorMatrix(bool _reset=true)
Get the Matrix of the last active Manipulator ( Identity if not found or hidden Manipulator ) ...
Definition: MovePlugin.cc:2194
const UpdateType UPDATE_GEOMETRY(UpdateTypeSet(1)<< 2)
Geometry updated.
void setViewObjectMarker(ViewObjectMarker *_marker)
Unificationtype
stores the current axes in the tool
Definition: MovePlugin.hh:205
ManipulatorMode
enum to define the manipulator mode
void updateManipulatorDialog()
Update the Dialog with the last clicked manipulator.
Definition: MovePlugin.cc:2058
const Vec3d & center() const
get center
void slotPickToolbarAction(QAction *_action)
Called by pick Toolbar.
Definition: MovePlugin.cc:2146
void translateVertexSelection(int _objectId, Vector _vector)
translate current vertex selection of an Object by a given vector
movePropsWidget * getDialogFromButton(QPushButton *_but)
Get parent properties dialog widget of QPushButton but.
Definition: MovePlugin.cc:1029
void slotUpdateContextMenuNode(int _nodeId)
Hide context menu entry when right clicking on node other than manipulator node.
Definition: MovePlugin.cc:755
QAction * toAllTargets_
Checked if transformation should be applied to all target objs.
Definition: MovePlugin.hh:492
void setPickModeProps(movePropsWidget *_pW, const std::string &_pickmode)
List of properties dialogs (each corresponding to one manipulator)
Definition: MovePlugin.cc:498
void unifyBoundingBox(Unificationtype u)
Size for the manipulators.
Definition: MovePlugin.cc:1924
void slotTranslation()
perform a translation for Manipulator in tab
Definition: MovePlugin.cc:1240
QAction * resizeAction_
Called by pick Toolbar.
Definition: MovePlugin.hh:303
Plane * plane(BaseObjectData *_object)
Get a Plane from an object.
void getBB(MeshT &_mesh, ACG::Vec3d &_bb_min, ACG::Vec3d &_bb_max)
get bounding box diagonal of a mesh
Definition: MovePlugin.cc:2502
QAction * placeAction_
Called by pick Toolbar.
Definition: MovePlugin.hh:300
OpenMesh::Vec3d getNearestVertex(MeshType *_mesh, uint _fh, OpenMesh::Vec3d &_hitPoint)
Get closest vertex to hitpoint.
Definition: MovePlugin.cc:2649
Viewer::ActionMode actionMode()
Get the current Action mode.
double manip_size_
Size for the manipulators.
Definition: MovePlugin.hh:407
void slotMoveManipToCOG()
Move the current manipulator to the cog of the object.
Definition: MovePlugin.cc:1367
void ManipulatorPositionChanged(QtTranslationManipulatorNode *_node)
update object when its manipulator changes position
Definition: MovePlugin.cc:834
QActionGroup * toolBarActions_
Called by Toolbar to enable move mode.
Definition: MovePlugin.hh:281
double manip_size_modifier_
Modifier for the Size (changed by Mousewheel Events)
Definition: MovePlugin.hh:410
void unifyBB(MeshT &_mesh, Unificationtype u=MovePlugin::DIAGONAL)
scale mesh to have a boundingboxdiagonal of one
Definition: MovePlugin.cc:2448
int targetCount()
Get the number of target objects.
PolyhedralMesh * polyhedralMesh(BaseObjectData *_object)
Get an PolyhedralMesh from an object.
void setAllTargets(bool _state)
Sets whether all targets should be affected or not.
Definition: MovePlugin.cc:2639
bool invert()
matrix inversion (returns true on success)
Definition: Matrix4x4T.cc:297
void transformSkeleton(Matrix4x4 _transformation, Skeleton::Pose *_pose=0)
transform the skeleton
int axisA_
stores the current axes in the tool
Definition: MovePlugin.hh:202
int lastActiveManipulator_
Stores the last manipulator which has been clicked ( used for the toolbox dialog) ...
Definition: MovePlugin.hh:413
OpenMesh::Vec3d getNearestFace(MeshType *_mesh, uint _fh, OpenMesh::Vec3d &_hitPoint)
Get closest face to hitpoint.
Definition: MovePlugin.cc:2726
void placeManip(QMouseEvent *_event, bool _snap=false)
Place and show the Manipulator.
Definition: MovePlugin.cc:865
void slotSetPosition()
Position of manipulator in tab changed.
Definition: MovePlugin.cc:1039
Skeleton * skeleton(BaseObjectData *_object)
Get a skeleton from an object.
bool manipPlaced()
Check if the manipulator has been placed.
void translateFaceSelection(int _objectId, Vector _vector)
translate current face selection of an Object by a given vector
#define DATA_SKELETON
Definition: Skeleton.hh:70
void setWhatsThis(QAction *_action, const QString &_msg, const QString &_ref="", const QString &_site="index.html") const
sets a whatsThis Message plus link to the doc for the given QAction
Kernel::Point Point
Coordinate type.
Definition: PolyMeshT.hh:115
Scalar max() const
return the maximal component
Definition: Vector11T.hh:492
PolyhedralMeshObject * polyhedralMeshObject(BaseObjectData *_object)
Cast an BaseObject to an PolyhedralMeshObject if possible.
QAction * contextMenuManipControlsAction_
Action holding the context menu for toolbar replication.
Definition: MovePlugin.hh:498
QAction * rotateTranslateAction_
Called by pick Toolbar.
Definition: MovePlugin.hh:301
void slotPickModeChanged(const std::string &_mode)
slot is called when the pickMode changed
Definition: MovePlugin.cc:528
pick any of the prior targets (should be implemented for all nodes)
Definition: BaseNode.hh:110
vector_type & minimize(const vector_type &_rhs)
minimize values: same as *this = min(*this, _rhs), but faster
Definition: Vector11T.hh:534
ACG::SceneGraph::BaseNode * getSceneGraphRootNode()
get scenegraph root node
#define DATA_POLY_MESH
Definition: PolyMesh.hh:65
QAction * biggerManipAction_
Called by pick Toolbar.
Definition: MovePlugin.hh:305
QAction * contextActionHide_
Context menu entry to hide a manipulator.
Definition: MovePlugin.hh:489
#define DATA_PLANE
Definition: Plane.hh:64
int axisB_
stores the current axes in the tool
Definition: MovePlugin.hh:203
moveToolbarWidget * tool_
Widget for Toolbox.
Definition: MovePlugin.hh:266
void showManipulators()
Checks if the manipulators should be visible or not.
Definition: MovePlugin.cc:985
VectorT< double, 3 > Vec3d
Definition: VectorT.hh:127
void transform(const ACG::Matrix4x4d &_mat)
Transform the plane with given matrix.
Definition: PlaneType.cc:97
#define DATA_TRIANGLE_MESH
Definition: TriangleMesh.hh:66
picks faces (should be implemented for all nodes)
Definition: BaseNode.hh:104
QString generateLink(const QString &_ref="", const QString &_site="index.html") const
generates a clickable link to the documentation for whatsThis Messages
void slotSetMoveMode(QAction *_action)
Called by Toolbar to enable move mode.
Definition: MovePlugin.cc:2121
HexahedralMesh * hexahedralMesh(BaseObjectData *_object)
Get an HexahedralMesh from an object.
DLLEXPORT ObjectIterator objectsEnd()
Return Iterator to Object End.
void slotEnableObjectMode()
stores the current axes in the tool
Definition: MovePlugin.cc:485
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
void update_vertex_normals()
A simple heuristic to estimate the vertex normals.
void slotScale()
Scale (with values from Tab)
Definition: MovePlugin.cc:1585
void slotSetDirection()
Set Direction of manipulator in tab changed.
Definition: MovePlugin.cc:1159
TriMesh * triMesh(BaseObjectData *_object)
Get a triangle mesh from an object.
QtTranslationManipulatorNode::ManipulatorMode manMode_
Holds the current manipulator mode.
Definition: MovePlugin.hh:430
std::vector< int > activeManipulators_
Size for the manipulators.
Definition: MovePlugin.hh:330