Developer Documentation
SelectionBasePlugin.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  * $Author$ *
46  * $Date$ *
47  * *
48 \*===========================================================================*/
49 
50 #include "SelectionBasePlugin.hh"
51 
53 
54 // Standard selection mode icon files
55 #define TOGGLE_IMG "selection_toggle.png"
56 #define LASSO_IMG "selection_lasso.png"
57 #define VOLUME_LASSO_IMG "selection_lasso2.png"
58 #define SURFACE_LASSO_IMG "surface-lasso.png"
59 #define SPHERE_IMG "selection_paintSphere.png"
60 #define BOUNDARY_IMG "selection_boundary.png"
61 #define FLOODFILL_IMG "selection_floodFill.png"
62 #define COMPONENTS_IMG "selection_connected.png"
63 
64 // Standard selection mode descriptions
65 #define TOGGLE_DESC "Toggle Selection"
66 #define LASSO_DESC "Lasso Selection"
67 #define VOLUME_LASSO_DESC "Volume Lasso Selection"
68 #define SURFACE_LASSO_DESC "Surface Lasso Selection"
69 #define SPHERE_DESC "Sphere Selection"
70 #define BOUNDARY_DESC "Boundary Selection"
71 #define FLOODFILL_DESC "Floodfill Selection"
72 #define COMPONENTS_DESC "Selected Components Selection"
73 
74 // Standard selection mode names
75 #define SB_TOGGLE "sb_toggle"
76 #define SB_LASSO "sb_lasso"
77 #define SB_VOLUME_LASSO "sb_volumelasso"
78 #define SB_SURFACE_LASSO "sb_surfacelasso"
79 #define SB_SPHERE "sb_sphere"
80 #define SB_BOUNDARY "sb_closestboundary"
81 #define SB_FLOODFILL "sb_floodfill"
82 #define SB_COMPONENTS "sb_components"
83 
84 // Constant to set if no selection picking is enabled
85 #define NO_SELECTION_PICKING "No_Selection_Picking"
86 #define NO_SELECTION_MODE "No_Selection_Mode"
87 
88 #define SELECTION_PICKING "SelectionBasePicking"
89 
90 // Constructor
92 toolBar_(0),
93 tool_(0),
94 primitivesBarGroup_(0),
95 pickModeToolBar_(0),
96 selectionModesGroup_(0),
97 toggleSelectionAction_(0),
98 lassoSelectionAction_(0),
99 volumeLassoSelectionAction_(0),
100 surfaceLassoSelectionAction_(0),
101 sphereSelectionAction_(0),
102 boundarySelectionAction_(0),
103 floodFillSelectionAction_(0),
104 componentsSelectionAction_(0),
105 nextFreePrimitiveType_(1u),
106 sphere_mat_node_(0),
107 sphere_node_(0),
108 line_node_(0),
109 lassoSelection_(false),
110 toolIcon_(0),
111 availableObjectTypes_(0u)
112 {
113 
114  // Reset active pick mode
115  currentPickMode_ = NO_SELECTION_PICKING;
116  lastPickMode_ = NO_SELECTION_PICKING;
117  currentSelectionMode_ = NO_SELECTION_MODE;
118 
119  currentPrimitiveType_ = 0u;
120 
121  // We initially want selection, not deselection
122  deselection_ = false;
123 
124  sphere_radius_ = 0.0;
125 }
126 
127 //============================================================================================
128 
129 void SelectionBasePlugin::initializePlugin() {
130 
131  // Skip if no gui is available
132  if (OpenFlipper::Options::nogui())
133  return;
134 
135  // Create tool box
136  tool_ = new SelectionBaseToolboxWidget();
137  QSize size(300, 300);
138  tool_->resize(size);
139 
140  // Connect load/save buttons
141  connect(tool_->loadSelection, SIGNAL(clicked()), this, SLOT(slotLoadSelectionButton()));
142  connect(tool_->saveSelection, SIGNAL(clicked()), this, SLOT(slotSaveSelectionButton()));
143 
144  // Add toolbox to OpenFlipper main window
145  toolIcon_ = new QIcon(OpenFlipper::Options::iconDirStr()+OpenFlipper::Options::dirSeparator()+"selection_base.png");
146  emit addToolbox("Selections", tool_, toolIcon_ );
147 
148  // Create toolbar that holds the selection environment buttons
149  toolBar_ = new QToolBar(tr("Selection Base"));
150  emit addToolbar(toolBar_);
151 
152  QString iconPath = OpenFlipper::Options::iconDirStr() + OpenFlipper::Options::dirSeparator();
153  QAction* selectionEnvironmentButton = new QAction(QIcon(iconPath + "selection_base.png"), "Selections", toolBar_);
154  toolBar_->addAction(selectionEnvironmentButton);
155 
156  // Connect QAction to local function that switches mode
157  connect(selectionEnvironmentButton, SIGNAL(triggered(bool)), this, SLOT(slotSelectionEnvironmentRequested(bool)));
158 
159  // Register keys
160  emit registerKey(Qt::Key_Control, Qt::NoModifier, tr("Deselection"), true);
161  emit registerKey(Qt::Key_Control, Qt::ControlModifier, tr("Deselection"), true);
162 
163  emit registerKey(Qt::Key_Shift, Qt::NoModifier, tr("Source/Target Selection"), true);
164  emit registerKey(Qt::Key_Shift, Qt::ShiftModifier, tr("Source/Target Selection"), true);
165 
166  // Add pickmode for the selection environment
167  emit addPickMode(SELECTION_PICKING);
168  // Enable mouse tracking for all pick modes
169  emit setPickModeMouseTracking(SELECTION_PICKING, true);
170 
171  // Set tabs widget movable
172  tool_->typeTabWidget->setMovable(true);
173 
174  // Set pick mode toolbar
175  pickModeToolBar_ = new QToolBar("Selection Picking Toolbar");
176  pickModeToolBar_->setObjectName("Selection_Picking_Toolbar");
177 
178  // Create primitive toolbar
179  primitivesBarGroup_ = new QActionGroup(pickModeToolBar_);
180  primitivesBarGroup_->setExclusive(true);
181 
182 
183  // Create default selection mode actions
184  selectionModesGroup_ = new QActionGroup(pickModeToolBar_);
185  selectionModesGroup_->setExclusive(true);
186  toggleSelectionAction_ = new HandleAction(QIcon(iconPath + TOGGLE_IMG), TOGGLE_DESC, selectionModesGroup_);
187  toggleSelectionAction_->setCheckable(true);
188  toggleSelectionAction_->selectionModeHandle(SB_TOGGLE);
189  connect(toggleSelectionAction_, SIGNAL(triggered(bool)), this, SLOT(slotEnterSelectionMode(bool)));
190  lassoSelectionAction_ = new HandleAction(QIcon(iconPath + LASSO_IMG), LASSO_DESC, selectionModesGroup_);
191  lassoSelectionAction_->setCheckable(true);
192  lassoSelectionAction_->selectionModeHandle(SB_LASSO);
193  connect(lassoSelectionAction_, SIGNAL(triggered(bool)), this, SLOT(slotEnterSelectionMode(bool)));
194  volumeLassoSelectionAction_ = new HandleAction(QIcon(iconPath + VOLUME_LASSO_IMG), VOLUME_LASSO_DESC, selectionModesGroup_);
195  volumeLassoSelectionAction_->setCheckable(true);
196  volumeLassoSelectionAction_->selectionModeHandle(SB_VOLUME_LASSO);
197  connect(volumeLassoSelectionAction_, SIGNAL(triggered(bool)), this, SLOT(slotEnterSelectionMode(bool)));
198  surfaceLassoSelectionAction_ = new HandleAction(QIcon(iconPath + SURFACE_LASSO_IMG), SURFACE_LASSO_DESC, selectionModesGroup_);
199  surfaceLassoSelectionAction_->setCheckable(true);
200  surfaceLassoSelectionAction_->selectionModeHandle(SB_SURFACE_LASSO);
201  connect(surfaceLassoSelectionAction_, SIGNAL(triggered(bool)), this, SLOT(slotEnterSelectionMode(bool)));
202  sphereSelectionAction_ = new HandleAction(QIcon(iconPath + SPHERE_IMG), SPHERE_DESC, selectionModesGroup_);
203  sphereSelectionAction_->setCheckable(true);
204  sphereSelectionAction_->selectionModeHandle(SB_SPHERE);
205  connect(sphereSelectionAction_, SIGNAL(triggered(bool)), this, SLOT(slotEnterSelectionMode(bool)));
206  boundarySelectionAction_ = new HandleAction(QIcon(iconPath + BOUNDARY_IMG), BOUNDARY_DESC, selectionModesGroup_);
207  boundarySelectionAction_->setCheckable(true);
208  boundarySelectionAction_->selectionModeHandle(SB_BOUNDARY);
209  connect(boundarySelectionAction_, SIGNAL(triggered(bool)), this, SLOT(slotEnterSelectionMode(bool)));
210  floodFillSelectionAction_ = new HandleAction(QIcon(iconPath + FLOODFILL_IMG), FLOODFILL_DESC, selectionModesGroup_);
211  floodFillSelectionAction_->setCheckable(true);
212  floodFillSelectionAction_->selectionModeHandle(SB_FLOODFILL);
213  connect(floodFillSelectionAction_, SIGNAL(triggered(bool)), this, SLOT(slotEnterSelectionMode(bool)));
214  componentsSelectionAction_ = new HandleAction(QIcon(iconPath + COMPONENTS_IMG), COMPONENTS_DESC, selectionModesGroup_);
215  componentsSelectionAction_->setCheckable(true);
216  componentsSelectionAction_->selectionModeHandle(SB_COMPONENTS);
217  connect(componentsSelectionAction_, SIGNAL(triggered(bool)), this, SLOT(slotEnterSelectionMode(bool)));
218 
219  pickModeToolBar_->clear();
220  pickModeToolBar_->addActions(primitivesBarGroup_->actions());
221  pickModeToolBar_->addSeparator();
222  pickModeToolBar_->addActions(selectionModesGroup_->actions());
223 
224 #if defined(ARCH_DARWIN)
225  // Workaround for QPainter using an unsupported rendering backend on core profiles
226  // See https://bugreports.qt.io/browse/QTBUG-32639
227  // setting opacity to a value smaller than 1 forces rasterizer engine
228  pickModeToolBar_->setWindowOpacity(0.99);
229 #endif
230 
231  emit setPickModeToolbar(SELECTION_PICKING, pickModeToolBar_);
232 }
233 
234 //============================================================================================
235 
236 void SelectionBasePlugin::pluginsInitialized() {
237 
238  // Initialize scenegraph nodes that are used for the
239  // rendering of the selection tools (e.g. sphere, lasso, etc.)
240 
241  // Sphere node
242 
243  std::string nodeName = std::string( tr("Selection Base Plugin: Selection Sphere Material").toUtf8() );
244  sphere_mat_node_ = new ACG::SceneGraph::MaterialNode(0, nodeName );
245  PluginFunctions::addGlobalNode(sphere_mat_node_);
246  sphere_mat_node_->applyProperties( MaterialNode::Blending |
250 
251  sphere_mat_node_->set_color(ACG::Vec4f(1.f, 0.f, 0.f, 0.3f));
252  sphere_mat_node_->enable_blending();
253  sphere_mat_node_->disable_alpha_test();
254  sphere_mat_node_->enable_backface_culling();
255 
256  nodeName = std::string( tr("Selection Base Plugin: Selection Sphere").toUtf8() );
257  sphere_node_ = new ACG::SceneGraph::GlutPrimitiveNode(ACG::SceneGraph::GlutPrimitiveNode::SPHERE, sphere_mat_node_, nodeName);
259  sphere_node_->get_primitive(0).color = ACG::Vec4f(1.f, 0.f, 0.f,0.3f);
260  sphere_node_->hide();
261 
262  // Line node
263 
264  nodeName = std::string( tr("Selection Base Plugin: Lasso Selection Line").toUtf8() );
265  line_node_ = new ACG::SceneGraph::LineNode (ACG::SceneGraph::LineNode::PolygonMode, 0, nodeName );
266  PluginFunctions::addGlobalNode(line_node_);
267  line_node_->set_line_width (2.0);
268  line_node_->alwaysOnTop() = true;
270  line_node_->set_color(ACG::Vec4f(1.0,0.0,0.0,1.0));
271  line_node_->set_base_color(ACG::Vec4f(1.0,0.0,0.0,1.0));
272  line_node_->hide();
273 }
274 
275 //============================================================================================
276 
278 
279  SelectionTypeFrameWidget* tab = new SelectionTypeFrameWidget(tool_->typeTabWidget);
280 
281  // Layout in tool box that contains the primitive buttons
282  _env.primitivesBar = new QHBoxLayout(tab->toolPrimitivesBar);
283 
284  // Layout in tool box that contains the operation buttons
285  _env.operationsBar = new QVBoxLayout(tab->toolOperationsWidget);
286 
287  QSizePolicy policy;
288  policy.setVerticalPolicy(QSizePolicy::MinimumExpanding);
289  policy.setHorizontalPolicy(QSizePolicy::Preferred);
290  tab->selectionGroup->setSizePolicy(policy);
291 
292  tab->toolPrimitivesBar->setLayout(_env.primitivesBar);
293  tab->toolPrimitivesBar->setMinimumHeight(68);
294  tab->toolOperationsWidget->setLayout(_env.operationsBar);
295  tab->toolOperationsWidget->setMinimumHeight(150);
296 
297  _env.primitiveActions = new QActionGroup(0);
298  _env.primitiveActions->setExclusive(true);
299 
300  return tab;
301 }
302 
303 //============================================================================================
304 
305 void SelectionBasePlugin::slotLoadSelectionButton() {
306  // Load selection button has been clicked
307 
308  QString filename = QFileDialog::getOpenFileName(0, tr("Load Selection"), "selection.ini", tr("Selection files ( *.ini )"));
309 
310  if(filename.length() > 0) {
311 
312  INIFile file;
313 
314  if(!file.connect(filename, false)) {
315  emit log(LOGERR, QString("Could not read file '%1'!").arg(filename));
316  return;
317  }
318 
319  // Pass ini-file to all object selection implementations
320  emit loadSelection(file);
321 
322  // Close file
323  file.disconnect();
324  }
325 }
326 
327 //============================================================================================
328 
329 void SelectionBasePlugin::slotSaveSelectionButton() {
330  // Save selection button has been clicked
331 
332  QString filename = QFileDialog::getSaveFileName(0, tr("Save Selection"), "selection.ini", tr("Selection files ( *.ini )"));
333 
334  if(filename.length() > 0) {
335 
336  INIFile file;
337 
338  if(!file.connect(filename, true)) {
339  emit log(LOGERR, QString("Could not create file '%1'!").arg(filename));
340  return;
341  }
342 
343  // Pass ini-file to all object selection implementations
344  emit saveSelection(file);
345 
346  // Write all data to the file
347  file.disconnect();
348  }
349 }
350 
351 //============================================================================================
352 
353 void SelectionBasePlugin::slotKeyEvent(QKeyEvent* _event) {
354 
355  // Check if we want to select or deselect
356  if ((_event->modifiers() & Qt::ControlModifier) || (_event->key() == Qt::Key_Control)) {
357  deselection_ = true;
358  primitivesBarGroup_->setExclusive(false);
359  } else {
360  deselection_ = false;
361  primitivesBarGroup_->setExclusive(true);
362  }
363 
364  // Check if we want to source or target selection
365  if ((_event->modifiers() & Qt::ShiftModifier) || (_event->key() == Qt::Key_Shift))
366  tool_->restrictOnTargets->setChecked(true);
367  else
368  tool_->restrictOnTargets->setChecked(false);
369 
370  // We have to store and search for registered key combinations at this point
371  // in order to preserve the possibility to register some key events exclusively
372  // for SelectionBasePlugin (whithout passing them on to al type selection plugins...
373 
374  // Search for key combination
375  std::set<std::pair<int,Qt::KeyboardModifiers> >::iterator f =
376  registeredKeys_.find(std::pair<int,Qt::KeyboardModifiers>(_event->key(), _event->modifiers()));
377 
378  if(f != registeredKeys_.end()) {
379  // Some registered key found
380  emit keyShortcutEvent((*f).first,(*f).second);
381  }
382 }
383 
384 //============================================================================================
385 
386 void SelectionBasePlugin::slotKeyReleaseEvent(QKeyEvent* _event) {
387 
388  //check if we want to select or deselect
389  if ((_event->modifiers() & Qt::ControlModifier) || (_event->key() == Qt::Key_Control)) {
390  deselection_ = false;
391  primitivesBarGroup_->setExclusive(true);
392  }
393 
394  // Check if we want to source or target selection
395  if ((_event->modifiers() & Qt::ShiftModifier) || (_event->key() == Qt::Key_Shift))
396  tool_->restrictOnTargets->setChecked(false);
397 }
398 
399 //============================================================================================
400 
401 void SelectionBasePlugin::loadIniFileOptionsLast(INIFile &_ini)
402 {
403  emit loadSelection(_ini);
404 }
405 
406 //============================================================================================
407 
408 void SelectionBasePlugin::slotAddSelectionEnvironment(QString _modeName, QString _description, QString _icon, QString& _handleName) {
409 
410  /*
411  A new selection environment is to be added. We first test if the
412  associated selection environment already exists. If not, we create
413  a new button and hide it.
414  */
415  std::map<QString,SelectionEnvironment>::iterator it =
416  selectionEnvironments_.begin();
417 
418  for(; it != selectionEnvironments_.end(); ++it) {
419  if(_modeName == (*it).second.name) {
420  emit log(LOGINFO, QString("Selection environment %1 already exists.").arg(_modeName));
421  return;
422  }
423  }
424 
425  // Create new selection environment
427  env.name = _modeName;
428 
430 
431  if ( OpenFlipper::Options::gui() ) {
432 
433  // Add type frame to tab widget
434  int index = tool_->typeTabWidget->addTab(tab, QIcon(_icon), _modeName);
435  env.tabWidget = tool_->typeTabWidget->widget(index);
436 
437  // Disable type frame unless there's at least one
438  // object of the desired type in the scene
439  tool_->typeTabWidget->setTabEnabled(index, false);
440  tool_->typeTabWidget->widget(index)->setEnabled(false);
441 
442  }
443 
444  // Create a unique handle name for this selection environment
445  _handleName = getUniqueHandleName("h_" + _modeName.replace(" ", "_"));
446 
447  // Set handle for selection environment
448  env.handle = _handleName;
449 
450  // Update pick mode toolbar
452 
453  // Add selection environment to local map
454  selectionEnvironments_.insert(std::pair<QString,SelectionEnvironment>(_handleName, env));
455 }
456 
457 //============================================================================================
458 
459 void SelectionBasePlugin::slotRegisterType(QString _handleName, DataType _type) {
460  /*
461  Register new data type under the selection environment with
462  handle name _handleName.
463  */
465 
466  // If the associated selection environment has been found,
467  // we add the specified data type to the list of supported data types
468  if(getSelectionEnvironment(env, _handleName)) {
469  // Search if the data type has already been added before...
470  for(std::vector<DataType>::iterator t_it = env->types.begin();
471  t_it != env->types.end(); ++t_it) {
472  // If the type already exists in the list -> return
473  if ((*t_it) == _type) return;
474  }
475  // ...if not, add it.
476  env->types.push_back(_type);
477  // And show selection environment button if at least one object
478  // of the associated type already exists in the scenegraph
479  if(typeExists(_type)) {
480  // Show selection environment's tab widget
481  tool_->typeTabWidget->setTabEnabled(tool_->typeTabWidget->indexOf(env->tabWidget), true);
482  env->tabWidget->setEnabled(true);
483  }
484 
485  } else {
486  emit log(LOGERR, "The specified selection environment has not been found! The data type could not be registered.");
487  }
488 }
489 
490 //============================================================================================
491 
493 
494  // Add newly added primitive and tool buttons
495  QList<QAction*> primitivesList = primitivesBarGroup_->actions();
496 
497  for(QList<QAction*>::iterator it = primitivesList.begin(); it != primitivesList.end(); ++it) {
498  (*it)->setEnabled(false);
499 
500  // If at least one object of this type exists in the scene,
501  // don't grey out the button
502  PrimitiveAction* act = dynamic_cast<PrimitiveAction*>(*it);
503  if(act) {
504  std::map<QString,SelectionEnvironment>::iterator sit =
505  selectionEnvironments_.find(act->selectionEnvironmentHandle());
506  if(sit != selectionEnvironments_.end()) {
507 
508  bool atLeastOne = false;
509  for(std::vector<DataType>::iterator tit = (*sit).second.types.begin();
510  tit != (*sit).second.types.end(); ++tit) {
511  if(typeExists(*tit)) {
512  atLeastOne = true;
513  break;
514  }
515  }
516  if(atLeastOne) {
517  (*it)->setEnabled(true);
518  }
519  }
520  }
521  }
522 
523  // Only activate those tools, that are available for the current
524  // active primitive type
525 
526  for(std::map<QString,SelectionEnvironment>::iterator it = selectionEnvironments_.begin();
527  it != selectionEnvironments_.end(); ++it) {
528 
529  // Default selection modes
530  toggleSelectionAction_->setEnabled(toggleSelectionAction_->isAssociated(currentPrimitiveType_, true));
531  lassoSelectionAction_->setEnabled(lassoSelectionAction_->isAssociated(currentPrimitiveType_, true));
532  volumeLassoSelectionAction_->setEnabled(volumeLassoSelectionAction_->isAssociated(currentPrimitiveType_, true));
533  surfaceLassoSelectionAction_->setEnabled(surfaceLassoSelectionAction_->isAssociated(currentPrimitiveType_, true));
534  sphereSelectionAction_->setEnabled(sphereSelectionAction_->isAssociated(currentPrimitiveType_, true));
535  boundarySelectionAction_->setEnabled(boundarySelectionAction_->isAssociated(currentPrimitiveType_, true));
536  floodFillSelectionAction_->setEnabled(floodFillSelectionAction_->isAssociated(currentPrimitiveType_, true));
537  componentsSelectionAction_->setEnabled(componentsSelectionAction_->isAssociated(currentPrimitiveType_, true));
538 
539  // Custom selection modes
540  for(std::set<HandleAction*>::iterator cit = (*it).second.customSelectionModes.begin();
541  cit != (*it).second.customSelectionModes.end(); ++cit) {
542 
543  (*cit)->setEnabled((availableObjectTypes_ & (*cit)->objectTypeRestriction()) &&
544  (*cit)->isAssociated(currentPrimitiveType_, true));
545  }
546  }
547 }
548 
549 //============================================================================================
550 
551 void SelectionBasePlugin::slotMouseWheelEvent(QWheelEvent* _event, const std::string& _mode) {
552 
553  if(currentPickMode_ == NO_SELECTION_PICKING) return;
554 
555  // Increase sphere radius
556  if (currentSelectionMode_ == SB_SPHERE) {
557 
558  float d = -(float)_event->delta() / 120.0 * 0.1;
559  sphere_radius_ *= 1.0 + d;
560 
561  sphere_node_->set_size(sphere_radius_);
562  sphere_node_->show();
563 
564  emit updateView();
565  }
566 }
567 
568 //============================================================================================
569 
570 void SelectionBasePlugin::slotMouseEvent(QMouseEvent* _event) {
571 
572  if(currentPickMode_ == NO_SELECTION_PICKING) return;
573 
574  // Go into appropriate pick processing
575  if(currentSelectionMode_ == SB_TOGGLE) {
576  slotMouseToggleSelection(_event);
577  } else if (currentSelectionMode_ == SB_LASSO) {
578  slotMouseLassoSelection(_event);
579  } else if (currentSelectionMode_ == SB_VOLUME_LASSO) {
580  slotMouseVolumeLassoSelection(_event);
581  } else if (currentSelectionMode_ == SB_SURFACE_LASSO) {
582  slotMouseSurfaceLassoSelection(_event);
583  } else if (currentSelectionMode_ == SB_SPHERE) {
584  slotMouseSphereSelection(_event);
585  } else if (currentSelectionMode_ == SB_BOUNDARY) {
586  slotMouseBoundarySelection(_event);
587  } else if (currentSelectionMode_ == SB_FLOODFILL) {
588  slotMouseFloodFillSelection(_event);
589  } else if (currentSelectionMode_ == SB_COMPONENTS) {
590  slotMouseComponentsSelection(_event);
591  } else {
592  // Custom selection mode
593  slotMouseCustomSelection(_event);
594  }
595 }
596 
597 //============================================================================================
598 
599 void SelectionBasePlugin::slotAddPrimitiveType(QString _handleName, QString _name, QString _icon, SelectionInterface::PrimitiveType& _typeHandle) {
600 
601  if ( !OpenFlipper::Options::gui() )
602  return;
603 
604  // Get selection environment
606  if(! getSelectionEnvironment(env,_handleName))
607  {
608  emit log(LOGERR, QString("Could not find selection environment width handle '%1'!").arg(_handleName));
609  return;
610  }
611 
612  // Test if there's a free primitive type available
613  // Note: This is actually limited to 31
614  if(nextFreePrimitiveType_ > nextFreePrimitiveType_ << 1) {
615  emit log(LOGERR, "Maximum number of custom primitive types for selection reached!");
616  return;
617  }
618 
619  // Test if there's a custom type with the same name already
620  QList<QAction*>::const_iterator a_it = env->primitiveActions->actions().constBegin();
621  for(; a_it != env->primitiveActions->actions().constEnd(); ++a_it) {
622  if((*a_it)->text() == _name) {
623  emit log(LOGERR, QString("A custom primitive type with name \"%1\" already exists!").arg(_name));
624  return;
625  }
626  }
627 
628  // Add custom primitive type
629  PrimitiveAction* action = new PrimitiveAction(QIcon(_icon), _name, env->primitiveActions);
630  action->setCheckable(true);
631  action->selectionEnvironmentHandle(_handleName);
632  primitivesBarGroup_->addAction(action);
633  pickModeToolBar_->clear();
634  pickModeToolBar_->addActions(primitivesBarGroup_->actions());
635  pickModeToolBar_->addSeparator();
636  pickModeToolBar_->addActions(selectionModesGroup_->actions());
637 
638  // Also add type button to tool box of environment tab
639  ActionButton* button = new ActionButton(action);
640  button->setMinimumSize(QSize(32,32));
641  button->setMaximumSize(QSize(64,64));
642  env->primitivesBar->addWidget(button);
643 
644  _typeHandle = nextFreePrimitiveType_;
645  action->primitiveType(_typeHandle);
646 
647  // Add primitive type to environment
648  env->primitiveTypes |= _typeHandle;
649 
650  primitiveTypeButtons_.insert(std::pair<PrimitiveType,QAction*>(_typeHandle,action));
651 
652  // Go over to next free primitive type
653  nextFreePrimitiveType_ <<= 1;
654 
655  // Connect action to local slot in order to keep track of active primitive types
656  connect(action, SIGNAL(toggled(bool)), this, SLOT(updateActivePrimitiveTypes(bool)));
657 
659 }
660 
661 //============================================================================================
662 
663 void SelectionBasePlugin::updateActivePrimitiveTypes(bool _checked) {
664 
665  QObject* sender = QObject::sender();
666  PrimitiveAction* clickedAction = 0;
667  clickedAction = dynamic_cast<PrimitiveAction*>(sender);
668 
669  if(!clickedAction) return;
670 
671  // Change button state
672  clickedAction->setChecked(_checked);
673 
674  // Reset types
675  currentPrimitiveType_ = 0u;
676 
677  QList<QAction*> actions = primitivesBarGroup_->actions();
678  for(int i = 0; i < actions.size(); ++i) {
679 
680  if(actions[i]->isChecked()) {
681  PrimitiveAction* pa = 0;
682  pa = dynamic_cast<PrimitiveAction*>(actions[i]);
683  if(pa) {
684  currentPrimitiveType_ |= pa->primitiveType();
685  }
686  }
687  }
688 
689  // If the primitive type button has been activated,
690  // automatically go into the associated selection environment's
691  // picking mode
692  if(_checked) {
693  slotSelectionEnvironmentRequested(_checked);
694  }
695 
696  // If currently selected selection mode is not available
697  // for the currently active primitive types, reset selection mode
698  QList<QAction*> sm_actions = selectionModesGroup_->actions();
699  bool atLeastOneSelectionMode = false;
700  for(int i = 0; i < sm_actions.size(); ++i) {
701 
702  if(sm_actions[i]->isChecked()) {
703  atLeastOneSelectionMode = true;
704  HandleAction* ha = 0;
705  ha = dynamic_cast<HandleAction*>(sm_actions[i]);
706  if(ha) {
707  if(!ha->isAssociated(currentPrimitiveType_)) {
708  ha->blockSignals(true);
709  ha->setChecked(false);
710  ha->blockSignals(false);
711  toggleSelectionAction_->trigger();
712  }
713  }
714  }
715  }
716  // If no selection mode is active, automatically go into toggle mode
717  if(!atLeastOneSelectionMode) {
718  toggleSelectionAction_->trigger();
719  }
720 
721  // Automatically show tab widget associated to this primitive type
722  SelectionEnvironment* env = nullptr;
723  if(getSelectionEnvironment(env, clickedAction->selectionEnvironmentHandle()) && _checked) {
724  tool_->typeTabWidget->setCurrentIndex(tool_->typeTabWidget->indexOf(env->tabWidget));
725  }
726 
727  // Clear lines
728  line_node_->clear();
729  linePoints_.clear();
730  lassoSelection_ = false;
731 
732  // Hide and show selection functions that are associated
733  // with the currently active primitive types
734  slotShowAndHideOperations();
735  slotShowAndHideParameters();
736 
737  // Update pick modes bar
739 }
740 
741 //============================================================================================
742 
744  if (_metaphor == SB_TOGGLE)
745  toggleSelectionAction_->trigger();
746  else if (_metaphor == SB_LASSO)
747  lassoSelectionAction_->trigger();
748  else if (_metaphor == SB_VOLUME_LASSO)
749  volumeLassoSelectionAction_->trigger();
750  else if (_metaphor == SB_SURFACE_LASSO)
751  surfaceLassoSelectionAction_->trigger();
752  else if (_metaphor == SB_SPHERE)
753  sphereSelectionAction_->trigger();
754  else if (_metaphor == SB_BOUNDARY)
755  boundarySelectionAction_->trigger();
756  else if (_metaphor == SB_FLOODFILL)
757  floodFillSelectionAction_->trigger();
758  else if (_metaphor == SB_COMPONENTS)
759  componentsSelectionAction_->trigger();
760  else {
761  // check custom selection modes and pick the first one that matches
762  std::map<QString,SelectionEnvironment>::iterator it = selectionEnvironments_.begin();
763  bool found(false);
764  for (; it != selectionEnvironments_.end() && !found; ++it) {
765  std::set<HandleAction*>::iterator e = it->second.customSelectionModes.begin();
766  for(; e != it->second.customSelectionModes.end(); ++e) {
767  // build fancy custom selection mode string that is used when adding custom selections
768  QString customModeName = QString((*e)->selectionEnvironmentHandle() + "_" + _metaphor).replace(" ", "_");
769  if((*e)->selectionModeHandle().contains(customModeName)) {
770  (*e)->trigger();
771  found = true;
772  break;
773  }
774  }
775  }
776  }
777 }
778 
779 //============================================================================================
780 
782  QList<QAction*>::iterator a_it = primitivesBarGroup_->actions().begin();
783  for(; a_it != primitivesBarGroup_->actions().end(); ++a_it) {
784  if((*a_it)->text() == _primitive) {
785  (*a_it)->trigger();
786  break;
787  }
788  }
789 }
790 
791 //============================================================================================
792 
793 void SelectionBasePlugin::slotAddSelectionOperations(QString _handleName, QStringList _operationsList, QString _category, PrimitiveType _type) {
794 
795  // Get selection environment
796  SelectionEnvironment* env = nullptr;
797  if(!getSelectionEnvironment(env,_handleName)) {
798  emit log(LOGERR, QString("Could not find selection environment with handle '%1'!").arg(_handleName));
799  return;
800  }
801 
802  // Find associated layout from category
803  std::map<QString,std::pair<FillingLayout*,QGroupBox*> >::iterator it = env->categories.find(_category);
804  if(it == env->categories.end()) {
805  // Create new category
806  FillingLayout* fillLayout = new FillingLayout(2);
807  QGroupBox* group = new QGroupBox(_category);
808  group->setLayout(fillLayout);
809  // Insert newly created fillLayout into map
810  std::pair<std::map<QString,std::pair<FillingLayout*,QGroupBox*> >::iterator,bool> ret;
811  ret = env->categories.insert(std::pair<QString,std::pair<FillingLayout*,QGroupBox*> >(_category,
812  std::pair<FillingLayout*,QGroupBox*>(fillLayout,group)));
813  it = ret.first;
814  // Add group box to vertical operations layout
815  env->operationsBar->addWidget(group);
816  }
817 
818  // Add buttons with function names to operations widget
819  for(int i = 0; i < _operationsList.size(); ++i) {
820  QPushButton* button = new QPushButton(_operationsList[i]);
821  button->setDisabled(true);
822  button->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Fixed);
823  int width = button->fontMetrics().width(_operationsList[i]);
824  button->setMinimumWidth(width);
825  button->setFixedHeight(26);
826 
827  connect(button, SIGNAL(clicked()), this, SLOT(slotOperationRequested()));
828  // Add operation to local list
829  env->operations.insert(std::pair<PrimitiveType,QPushButton*>(_type, button));
830  // Add button to operations widget in tool box
831  (*it).second.first->addWidget(button);
832  }
833  // Show operations if in supported primitive type mode
834  slotShowAndHideOperations();
835 }
836 
837 //============================================================================================
838 
839 void SelectionBasePlugin::slotAddSelectionParameters(QString _handleName, QWidget* _widget, QString _category, PrimitiveType _type)
840 {
841  // Get selection environment
842  SelectionEnvironment* env = nullptr;
843  if(!getSelectionEnvironment(env,_handleName)) {
844  emit log(LOGERR, QString("Could not find selection environment with handle '%1'!").arg(_handleName));
845  return;
846  }
847 
848  // Find associated layout from category
849  std::map<QString,std::pair<FillingLayout*,QGroupBox*> >::iterator it = env->categories.find(_category);
850  if(it == env->categories.end()) {
851  // Create new category
852  FillingLayout* fillLayout = new FillingLayout(2);
853  QGroupBox* group = new QGroupBox(_category);
854  group->setLayout(fillLayout);
855  // Insert newly created fillLayout into map
856  std::pair<std::map<QString,std::pair<FillingLayout*,QGroupBox*> >::iterator,bool> ret;
857  ret = env->categories.insert(std::pair<QString,std::pair<FillingLayout*,QGroupBox*> >(_category,
858  std::pair<FillingLayout*,QGroupBox*>(fillLayout,group)));
859  it = ret.first;
860  // Add group box to vertical operations layout
861  env->operationsBar->addWidget(group);
862  }
863 
864  // Add widget to local list
865  env->parameters.insert(std::pair<PrimitiveType,QWidget*>(_type, _widget));
866  // Add widget to operations widget in tool box
867  (*it).second.first->addWidget(_widget);
868 
869  // Show operations if in supported primitive type mode
870  slotShowAndHideParameters();
871 }
872 
873 //============================================================================================
874 
875 void SelectionBasePlugin::slotOperationRequested() {
876 
877  QObject* sender = QObject::sender();
878  QPushButton* button = 0;
879  button = dynamic_cast<QPushButton*>(sender);
880 
881  if(!button) return;
882 
883  emit selectionOperation(button->text());
884 }
885 
886 //============================================================================================
887 
888 void SelectionBasePlugin::slotShowAndHideOperations() {
889 
890  for(std::map<QString,SelectionEnvironment>::iterator e_it = selectionEnvironments_.begin();
891  e_it != selectionEnvironments_.end(); ++e_it) {
892 
893  for(std::multimap<PrimitiveType,QPushButton*>::iterator it = (*e_it).second.operations.begin();
894  it != (*e_it).second.operations.end(); ++it) {
895 
896  if((currentPrimitiveType_ & (*it).first) || (*it).first == 0u) {
897  // Type is currently active -> show button
898  (*it).second->setDisabled(false);
899  } else {
900  // Type is currently not active -> hide button
901  (*it).second->setDisabled(true);
902  }
903  }
904  }
905 }
906 
907 //============================================================================================
908 
909 void SelectionBasePlugin::slotShowAndHideParameters() {
910 
911  for(std::map<QString,SelectionEnvironment>::iterator e_it = selectionEnvironments_.begin();
912  e_it != selectionEnvironments_.end(); ++e_it) {
913 
914  for(std::multimap<PrimitiveType,QWidget*>::iterator it = (*e_it).second.parameters.begin();
915  it != (*e_it).second.parameters.end(); ++it) {
916 
917  if((currentPrimitiveType_ & (*it).first) || (*it).first == 0u) {
918  // Type is currently active -> show widget
919  (*it).second->setDisabled(false);
920  } else {
921  // Type is currently not active -> hide widget
922  (*it).second->setDisabled(true);
923  }
924  }
925  }
926 }
927 
928 //============================================================================================
929 
930 void SelectionBasePlugin::slotSelectionEnvironmentRequested(bool _checked) {
931 
933 
934  PluginFunctions::actionMode(Viewer::PickingMode);
935  PluginFunctions::pickMode(SELECTION_PICKING);
936 
937  currentPickMode_ = SELECTION_PICKING;
938 }
939 
940 //============================================================================================
941 
942 void SelectionBasePlugin::slotEnterSelectionMode(bool _checked) {
943 
944  QObject* obj = QObject::sender();
945  HandleAction* act = 0;
946  act = dynamic_cast<HandleAction*>(obj);
947 
948  if(act == 0) return;
949 
950  // Make button checked
951  act->setChecked(_checked);
952 
953  // Keep active selection mode
954  if(_checked) {
955  currentSelectionMode_ = act->selectionModeHandle();
956  }
957 
958  // Clear lines
959  line_node_->clear();
960  linePoints_.clear();
961  lassoSelection_ = false;
962 
963  if(currentSelectionMode_ == SB_SPHERE) {
964  // Adjust sphere radius to have size defined relatively to the scene radius
965  sphere_radius_ = 0.03 * PluginFunctions::sceneRadius();
966  }
967 }
968 
969 //============================================================================================
970 
971 void SelectionBasePlugin::slotPickModeChanged (const std::string& _pickmode) {
972 
973  // Test if current pickmode is a selection pick mode
974  bool selectionPicking = (_pickmode == "SelectionBasePicking");
975 
976  // Show/hode line and sphere node
977  if(currentSelectionMode_ == SB_SPHERE)
978  sphere_node_->show();
979  else
980  sphere_node_->hide();
981 
982  if(currentSelectionMode_ == SB_LASSO || currentSelectionMode_ == SB_VOLUME_LASSO)
983  line_node_->show();
984  else
985  line_node_->hide();
986 
987  bool resetPickToolBar = false;
988 
989  if(currentPickMode_ != NO_SELECTION_PICKING) {
990  // We go into examiner (or some other) mode for the first time
991 
992  // Just hide line and sphere nodes
993  sphere_node_->hide();
994  line_node_->hide();
995 
996  // Save values
997  lastPickMode_ = currentPickMode_;
998  currentPickMode_ = NO_SELECTION_PICKING;
999 
1000  } else if (selectionPicking && currentPickMode_ == NO_SELECTION_PICKING && lastPickMode_ != NO_SELECTION_PICKING) {
1001  // We come back from examiner mode (windows key hit)
1002 
1003  currentPickMode_ = lastPickMode_;
1004 
1005  } else if (!selectionPicking && currentPickMode_ == NO_SELECTION_PICKING) {
1006  // We go into some other picking mode
1007 
1008  // Clear line nodes
1009  linePoints_.clear();
1010  line_node_->clear_points();
1011 
1012  // A completely different pick mode has been chosen that
1013  // is not handled by this plugin, so reset current pickmode
1014  currentPickMode_ = NO_SELECTION_PICKING;
1015  currentSelectionMode_ = NO_SELECTION_MODE;
1016  lastPickMode_ = NO_SELECTION_PICKING;
1017 
1018  // We don't want no tool to be selected anymore
1019  resetPickToolBar = true;
1020 
1021  } else {
1022  // We return from some other pickimg mode (or mutliple examiner sessions)
1023  // to selection mode
1024 
1025  lastPickMode_ = currentPickMode_ = _pickmode.c_str();
1026 
1027  // Reset pick toolbar
1028  resetPickToolBar = true;
1029 
1030  // Clear line nodes
1031  linePoints_.clear();
1032  line_node_->clear_points();
1033  }
1034 
1035  // Make sure that the pick mode buttons are in correct state
1036  toggleSelectionAction_->setChecked(!resetPickToolBar && currentSelectionMode_ == SB_TOGGLE);
1037  lassoSelectionAction_->setChecked(!resetPickToolBar && currentSelectionMode_ == SB_LASSO);
1038  volumeLassoSelectionAction_->setChecked(!resetPickToolBar && currentSelectionMode_ == SB_VOLUME_LASSO);
1039  surfaceLassoSelectionAction_->setChecked(!resetPickToolBar && currentSelectionMode_ == SB_SURFACE_LASSO);
1040  sphereSelectionAction_->setChecked(!resetPickToolBar && currentSelectionMode_ == SB_SPHERE);
1041  boundarySelectionAction_->setChecked(!resetPickToolBar && currentSelectionMode_ == SB_BOUNDARY);
1042  floodFillSelectionAction_->setChecked(!resetPickToolBar && currentSelectionMode_ == SB_FLOODFILL);
1043  componentsSelectionAction_->setChecked(!resetPickToolBar && currentSelectionMode_ == SB_COMPONENTS);
1044 
1045  for(std::map<QString,SelectionEnvironment>::iterator it = selectionEnvironments_.begin();
1046  it != selectionEnvironments_.end(); ++it) {
1047 
1048  // Custom selection modes
1049  for(std::set<HandleAction*>::iterator csm_it = (*it).second.customSelectionModes.begin();
1050  csm_it != (*it).second.customSelectionModes.end(); ++csm_it) {
1051  (*csm_it)->setChecked(!resetPickToolBar && currentSelectionMode_ == (*csm_it)->selectionModeHandle());
1052  }
1053  }
1054 
1055  if(selectionPicking)
1057 }
1058 
1059 //============================================================================================
1060 
1061 void SelectionBasePlugin::showSelectionMode(QString _mode, QString _icon, QString _desc, QString _handleName,
1062  bool _show, SelectionInterface::PrimitiveType _associatedTypes,
1063  QString& _customIdentifier, bool _custom, DataType _objectTypeRestriction) {
1064 
1065  if ( !OpenFlipper::Options::gui() )
1066  return;
1067 
1068  // Find selection environment that is associated to _handleName
1069  // Return if the requested selection environment was not found
1070  SelectionEnvironment* env = nullptr;
1071  if(!getSelectionEnvironment(env,_handleName) ) return;
1072 
1073  if(!_custom) {
1074  if(_mode == SB_TOGGLE) {
1075  selectionModeShowSwitch(_show,env,toggleSelectionAction_,_associatedTypes);
1076  } else if (_mode == SB_LASSO) {
1077  selectionModeShowSwitch(_show,env,lassoSelectionAction_,_associatedTypes);
1078  } else if (_mode == SB_VOLUME_LASSO) {
1079  selectionModeShowSwitch(_show,env,volumeLassoSelectionAction_,_associatedTypes);
1080  } else if (_mode == SB_SURFACE_LASSO) {
1081  selectionModeShowSwitch(_show,env,surfaceLassoSelectionAction_,_associatedTypes);
1082  } else if (_mode == SB_SPHERE) {
1083  selectionModeShowSwitch(_show,env,sphereSelectionAction_,_associatedTypes);
1084  } else if (_mode == SB_BOUNDARY) {
1085  selectionModeShowSwitch(_show,env,boundarySelectionAction_,_associatedTypes);
1086  } else if (_mode == SB_FLOODFILL) {
1087  selectionModeShowSwitch(_show,env,floodFillSelectionAction_,_associatedTypes);
1088  } else if (_mode == SB_COMPONENTS) {
1089  selectionModeShowSwitch(_show,env,componentsSelectionAction_,_associatedTypes);
1090  }
1091  } else {
1092  if(_show) {
1093  // Create custom function
1094  // Create action for associated function
1095  _customIdentifier = getUniqueIdentifierName(QString(_handleName + "_" + _mode).replace(" ", "_"));
1096 
1097  // Create action
1098  HandleAction* action = new HandleAction(QIcon(_icon), _desc, selectionModesGroup_, _objectTypeRestriction);
1099  action->setCheckable(true);
1100  action->selectionEnvironmentHandle(_handleName);
1101  action->selectionModeHandle(_customIdentifier);
1102  action->addAssociatedType(_associatedTypes);
1103 
1104  // Add action to tools bar
1105  selectionModesGroup_->addAction(action);
1106  pickModeToolBar_->clear();
1107  pickModeToolBar_->addActions(primitivesBarGroup_->actions());
1108  pickModeToolBar_->addSeparator();
1109  pickModeToolBar_->addActions(selectionModesGroup_->actions());
1110 
1111  // Add pickmode name and button to selection environment's container
1112  env->customSelectionModes.insert(action);
1113 
1114  connect(action, SIGNAL(triggered(bool)), this, SLOT(slotEnterSelectionMode(bool)));
1115  } else {
1116  // Search custom selection mode
1117  std::set<HandleAction*>::iterator e = env->customSelectionModes.begin();
1118  for(; e != env->customSelectionModes.end(); ++e) {
1119  if((*e)->selectionEnvironmentHandle() == _handleName)
1120  break;
1121  }
1122 
1123  // Delete action from list
1124  if(e != env->customSelectionModes.end()) {
1125  (*e)->removeAssociatedType(_associatedTypes);
1126  env->customSelectionModes.erase(e);
1127  }
1128  }
1129  }
1130 }
1131 
1132 //============================================================================================
1133 
1134 void SelectionBasePlugin::slotAddCustomSelectionMode(QString _handleName, QString _modeName, QString _description, QString _icon,
1135  SelectionInterface::PrimitiveType _associatedTypes, QString& _customIdentifier) {
1136 
1137  showSelectionMode(_modeName, _icon, _description, _handleName, true, _associatedTypes, _customIdentifier, true);
1139 }
1140 
1141 //============================================================================================
1142 
1143 void SelectionBasePlugin::slotAddCustomSelectionMode(QString _handleName, QString _modeName, QString _description, QString _icon,
1144  SelectionInterface::PrimitiveType _associatedTypes, QString& _customIdentifier,
1145  DataType _objectTypeRestriction) {
1146 
1147  showSelectionMode(_modeName, _icon, _description, _handleName, true, _associatedTypes, _customIdentifier, true, _objectTypeRestriction);
1149 }
1150 
1151 //============================================================================================
1152 
1153 void SelectionBasePlugin::slotShowToggleSelectionMode(QString _handleName, bool _show, SelectionInterface::PrimitiveType _associatedTypes) {
1154 
1155  QString iconPath = OpenFlipper::Options::iconDirStr() + OpenFlipper::Options::dirSeparator();
1156  QString dummy;
1157  showSelectionMode(SB_TOGGLE, iconPath + TOGGLE_IMG, TOGGLE_DESC, _handleName, _show, _associatedTypes, dummy);
1159 }
1160 
1161 //============================================================================================
1162 
1163 void SelectionBasePlugin::slotShowLassoSelectionMode(QString _handleName, bool _show, SelectionInterface::PrimitiveType _associatedTypes) {
1164 
1165  QString iconPath = OpenFlipper::Options::iconDirStr() + OpenFlipper::Options::dirSeparator();
1166  QString dummy;
1167  showSelectionMode(SB_LASSO, iconPath + LASSO_IMG, LASSO_DESC, _handleName, _show, _associatedTypes, dummy);
1169 }
1170 
1171 //============================================================================================
1172 
1173 void SelectionBasePlugin::slotShowVolumeLassoSelectionMode(QString _handleName, bool _show, SelectionInterface::PrimitiveType _associatedTypes) {
1174 
1175  QString iconPath = OpenFlipper::Options::iconDirStr() + OpenFlipper::Options::dirSeparator();
1176  QString dummy;
1177  showSelectionMode(SB_VOLUME_LASSO, iconPath + VOLUME_LASSO_IMG, VOLUME_LASSO_DESC, _handleName, _show, _associatedTypes, dummy);
1179 }
1180 
1181 //============================================================================================
1182 
1183 void SelectionBasePlugin::slotShowSurfaceLassoSelectionMode(QString _handleName, bool _show, SelectionInterface::PrimitiveType _associatedTypes) {
1184 
1185  QString iconPath = OpenFlipper::Options::iconDirStr() + OpenFlipper::Options::dirSeparator();
1186  QString dummy;
1187  showSelectionMode(SB_SURFACE_LASSO, iconPath + SURFACE_LASSO_IMG, SURFACE_LASSO_DESC, _handleName, _show, _associatedTypes, dummy);
1189 }
1190 
1191 //============================================================================================
1192 
1193 void SelectionBasePlugin::slotShowSphereSelectionMode(QString _handleName, bool _show, SelectionInterface::PrimitiveType _associatedTypes) {
1194 
1195  QString iconPath = OpenFlipper::Options::iconDirStr() + OpenFlipper::Options::dirSeparator();
1196  QString dummy;
1197  showSelectionMode(SB_SPHERE, iconPath + SPHERE_IMG, SPHERE_DESC, _handleName, _show, _associatedTypes, dummy);
1199 }
1200 
1201 //============================================================================================
1202 
1203 void SelectionBasePlugin::slotShowClosestBoundarySelectionMode(QString _handleName, bool _show, SelectionInterface::PrimitiveType _associatedTypes) {
1204 
1205  QString iconPath = OpenFlipper::Options::iconDirStr() + OpenFlipper::Options::dirSeparator();
1206  QString dummy;
1207  showSelectionMode(SB_BOUNDARY, iconPath + BOUNDARY_IMG, BOUNDARY_DESC, _handleName, _show, _associatedTypes, dummy);
1209 }
1210 
1211 //============================================================================================
1212 
1213 void SelectionBasePlugin::slotShowFloodFillSelectionMode(QString _handleName, bool _show, SelectionInterface::PrimitiveType _associatedTypes) {
1214 
1215  QString iconPath = OpenFlipper::Options::iconDirStr() + OpenFlipper::Options::dirSeparator();
1216  QString dummy;
1217  showSelectionMode(SB_FLOODFILL, iconPath + FLOODFILL_IMG, FLOODFILL_DESC, _handleName, _show, _associatedTypes, dummy);
1219 }
1220 
1221 //============================================================================================
1222 
1223 void SelectionBasePlugin::slotShowComponentsSelectionMode(QString _handleName, bool _show, SelectionInterface::PrimitiveType _associatedTypes) {
1224 
1225  QString iconPath = OpenFlipper::Options::iconDirStr() + OpenFlipper::Options::dirSeparator();
1226  QString dummy;
1227  showSelectionMode(SB_COMPONENTS, iconPath + COMPONENTS_IMG, COMPONENTS_DESC, _handleName, _show, _associatedTypes, dummy);
1229 }
1230 
1231 //============================================================================================
1232 
1233 void SelectionBasePlugin::slotGetActiveDataTypes(TypeList& _types) {
1234 
1235  if(currentPickMode_ == NO_SELECTION_PICKING) {
1236  _types = TypeList();
1237  } else {
1238  std::map<QString,SelectionEnvironment>::iterator it = selectionEnvironments_.find(currentPickMode_);
1239  if(it == selectionEnvironments_.end()) {
1240  _types = TypeList();
1241  } else {
1242  _types = (*it).second.types;
1243  }
1244  }
1245 }
1246 
1247 //============================================================================================
1248 
1249 void SelectionBasePlugin::slotGetActivePrimitiveType(SelectionInterface::PrimitiveType& _type) {
1250 
1251  _type = currentPrimitiveType_;
1252 }
1253 
1254 //============================================================================================
1255 
1256 void SelectionBasePlugin::slotMouseToggleSelection(QMouseEvent* _event) {
1257 
1258  // Only emit toggleSelection if left mouse button was clicked
1259  if (_event->type() == QEvent::MouseButtonPress) {
1260 
1261  if (_event->button() == Qt::RightButton) return;
1262 
1263  emit toggleSelection(_event, currentPrimitiveType_, deselection_);
1264  }
1265 }
1266 
1267 //============================================================================================
1268 
1269 void SelectionBasePlugin::slotMouseLassoSelection(QMouseEvent* _event) {
1270 
1271  // Ignore context menu for lasso selection
1272  if (_event->button() == Qt::RightButton) return;
1273 
1274  size_t node_idx, target_idx;
1275  ACG::Vec3d hit_point;
1276 
1277  int y = PluginFunctions::viewerProperties().glState().context_height() - _event->pos().y();
1278  if (!PluginFunctions::scenegraphPick(ACG::SceneGraph::PICK_FACE, _event->pos(), node_idx, target_idx, &hit_point))
1279  hit_point = PluginFunctions::viewerProperties().glState().unproject(ACG::Vec3d(_event->pos().x(), y, 0.5));
1280 
1281  // Do rendering of mouse tool...
1282  if(_event->type() == QEvent::MouseButtonPress && _event->button() == Qt::LeftButton) {
1283  // If mouse button has been pressed
1284 
1285  if(!lassoSelection_) {
1286  // Initiate lasso selection
1287  linePoints_.clear();
1288  lassoSelection_ = true;
1289  }
1290 
1291  if(line_node_->hidden())
1292  line_node_->show();
1293 
1294  linePoints_.push_back(hit_point);
1295 
1296  // Inform selection plugins about the performed action
1297  emit lassoSelection(_event, currentPrimitiveType_, deselection_);
1298 
1299  } else if(_event->type() == QEvent::MouseMove) {
1300 
1301  if(!lassoSelection_) return;
1302 
1303  if (deselection_) {
1304  line_node_->set_color(ACG::Vec4f(1.0,0.0,0.0,1.0));
1305  line_node_->set_base_color(ACG::Vec4f(1.0,0.0,0.0,1.0));
1306  } else {
1307  line_node_->set_color(ACG::Vec4f(0.0, 1.0, 0.0, 1.0));
1308  line_node_->set_base_color(ACG::Vec4f(0.0, 1.0, 0.0, 1.0));
1309  }
1310 
1311  line_node_->clear();
1312  for (std::vector< ACG::Vec3d >::iterator it = linePoints_.begin(); it != linePoints_.end(); ++it)
1313  line_node_->add_point(*it);
1314 
1315  line_node_->add_point(hit_point);
1316 
1317  // Close lasso
1318  if( !linePoints_.empty() )
1319  line_node_->add_point(linePoints_[0]);
1320 
1321  } else if(_event->type() == QEvent::MouseButtonDblClick) {
1322 
1323  // Double click
1324  lassoSelection_ = false;
1325  linePoints_.clear();
1326  line_node_->clear();
1327  line_node_->hide();
1328 
1329  // Inform selection plugins about the performed action
1330  emit lassoSelection(_event, currentPrimitiveType_, deselection_);
1331  }
1332 }
1333 
1334 //============================================================================================
1335 
1336 void SelectionBasePlugin::slotMouseVolumeLassoSelection(QMouseEvent* _event) {
1337 
1338  // Ignore context menu for volume lasso selection
1339  if (_event->button() == Qt::RightButton) return;
1340 
1341  size_t node_idx, target_idx;
1342  ACG::Vec3d hit_point;
1343 
1344  int y = PluginFunctions::viewerProperties().glState().context_height() - _event->pos().y();
1345  if (!PluginFunctions::scenegraphPick(ACG::SceneGraph::PICK_FACE, _event->pos(), node_idx, target_idx, &hit_point))
1346  hit_point = PluginFunctions::viewerProperties().glState().unproject(ACG::Vec3d(_event->pos().x(), y, 0.5));
1347 
1348  // Do rendering of mouse tool...
1349  if(_event->type() == QEvent::MouseButtonPress && _event->button() == Qt::LeftButton) {
1350  // If mouse button has been pressed
1351 
1352  if(!lassoSelection_) {
1353  // Initiate lasso selection
1354  linePoints_.clear();
1355  lassoSelection_ = true;
1356  line_node_->show();
1357  }
1358 
1359  if(line_node_->hidden())
1360  line_node_->show();
1361 
1362  linePoints_.push_back(hit_point);
1363 
1364  // Inform selection plugins about the performed action
1365  emit volumeLassoSelection(_event, currentPrimitiveType_, deselection_);
1366 
1367  } else if(_event->type() == QEvent::MouseMove) {
1368 
1369  if(!lassoSelection_) return;
1370 
1371  if (deselection_) {
1372  line_node_->set_color(ACG::Vec4f(1.0,0.0,0.0,1.0));
1373  line_node_->set_base_color(ACG::Vec4f(1.0,0.0,0.0,1.0));
1374  } else {
1375  line_node_->set_color(ACG::Vec4f(0.0, 1.0, 0.0, 1.0));
1376  line_node_->set_base_color(ACG::Vec4f(0.0, 1.0, 0.0, 1.0));
1377  }
1378 
1379  line_node_->clear();
1380  for (std::vector< ACG::Vec3d >::iterator it = linePoints_.begin(); it != linePoints_.end(); ++it)
1381  line_node_->add_point(*it);
1382 
1383  line_node_->add_point(hit_point);
1384 
1385  // Close lasso
1386  if( !linePoints_.empty() )
1387  line_node_->add_point(linePoints_[0]);
1388 
1389  } else if(_event->type() == QEvent::MouseButtonDblClick) {
1390 
1391  // Double click
1392  lassoSelection_ = false;
1393  linePoints_.clear();
1394  line_node_->clear();
1395  line_node_->hide();
1396 
1397  // Inform selection plugins about the performed action
1398  emit volumeLassoSelection(_event, currentPrimitiveType_, deselection_);
1399  }
1400 }
1401 
1402 //============================================================================================
1403 
1404 void SelectionBasePlugin::slotMouseSurfaceLassoSelection(QMouseEvent* _event) {
1405 
1406  /* NOT IMPLEMENTED YET */
1407 }
1408 
1409 //============================================================================================
1410 
1411 void SelectionBasePlugin::slotMouseSphereSelection(QMouseEvent* _event) {
1412 
1413  // Ignore context menu for sphere selection
1414  if (_event->button() == Qt::RightButton) return;
1415 
1416  // Do rendering of mouse tool...
1417  size_t node_idx, target_idx;
1418  ACG::Vec3d hit_point;
1419 
1420  // Hide sphere node in order to avoid self picking
1421  sphere_node_->hide();
1422 
1423  // Pick anything to find all possible objects
1425  _event->pos(), node_idx, target_idx, &hit_point)) {
1426 
1427  BaseObjectData* object = 0;
1428 
1429  if (PluginFunctions::getPickedObject(node_idx, object)) {
1430 
1431  // update brush sphere
1432  sphere_node_->show();
1433  sphere_node_->set_position(hit_point);
1434  sphere_node_->set_size(sphere_radius_);
1435  sphere_node_->enablePicking(false);
1436 
1437  if( (_event->buttons() & Qt::LeftButton) //left button
1438  ||( (_event->buttons() == Qt::NoButton) && (_event->type() == QEvent::MouseButtonRelease)) // or release of left button
1439  ) {
1440  // Inform selection plugins about the performed action
1441  emit sphereSelection(_event, sphere_radius_, currentPrimitiveType_, deselection_);
1442  }
1443 
1444  }
1445  } else {
1446  // Hide sphere node if no object was picked
1447  sphere_node_->hide();
1448  }
1449 }
1450 
1451 //============================================================================================
1452 
1453 void SelectionBasePlugin::slotMouseBoundarySelection(QMouseEvent* _event) {
1454 
1455  // Only emit toggleSelection if left mouse button was clicked
1456  if (_event->type() == QEvent::MouseButtonPress) {
1457 
1458  if (_event->button() == Qt::RightButton) return;
1459 
1460  emit closestBoundarySelection(_event, currentPrimitiveType_, deselection_);
1461  }
1462 }
1463 
1464 //============================================================================================
1465 
1466 void SelectionBasePlugin::slotMouseFloodFillSelection(QMouseEvent* _event) {
1467 
1468  // Only emit toggleSelection if left mouse button was clicked
1469  if (_event->type() == QEvent::MouseButtonPress) {
1470 
1471  if (_event->button() == Qt::RightButton) return;
1472 
1473  emit floodFillSelection(_event, currentPrimitiveType_, deselection_);
1474  }
1475 }
1476 
1477 //============================================================================================
1478 
1479 void SelectionBasePlugin::slotMouseComponentsSelection(QMouseEvent* _event) {
1480 
1481  // Only emit componentsSelection if left mouse button was clicked
1482  if (_event->type() == QEvent::MouseButtonPress) {
1483 
1484  if (_event->button() == Qt::RightButton) return;
1485 
1486  emit componentsSelection(_event, currentPrimitiveType_, deselection_);
1487  }
1488 }
1489 
1490 //============================================================================================
1491 
1492 void SelectionBasePlugin::slotMouseCustomSelection(QMouseEvent* _event) {
1493 
1494  emit customSelection(_event, currentPrimitiveType_, currentSelectionMode_, deselection_);
1495 }
1496 
1497 //============================================================================================
1498 
1499 void SelectionBasePlugin::addedEmptyObject (int _id) {
1500  /*
1501  If an empty object has been added we will check if
1502  there exists a selection environment for the associated
1503  object type. If so and if this selection environment is
1504  not yet available, we will make it available from now on.
1505  */
1506  SelectionEnvironment* env = nullptr;
1507  bool found = false;
1508  BaseObjectData* obj = nullptr;
1509  if(findObjectType(obj,found, env, _id))
1510  {
1511 
1512  // Keep track of all data types in the scene
1513  availableObjectTypes_ |= obj->dataType();
1514 
1515  } else {
1516  BaseObject* bObject = 0;
1517  PluginFunctions::getObject(_id, bObject);
1518 
1519  // Groups are ok, others will cause an error
1520  if (bObject && !bObject->isGroup()) {
1521  emit log(LOGERR, "Could not retrieve object type! Maybe a selection environment will be missing.");
1522  }
1523  return;
1524  }
1525  if(found) {
1526  // We have found a selection environment for the
1527  // recently loaded data type -> show tab widget
1528  tool_->typeTabWidget->setTabEnabled(tool_->typeTabWidget->indexOf(env->tabWidget), true);
1529  env->tabWidget->setEnabled(true);
1530  }
1531 
1532  // Increase the number of available objects for that type
1533  QMap<DataType, int>::iterator iterator = typeCounter_.find(obj->dataType());
1534  if ( iterator != typeCounter_.end() ) {
1535  typeCounter_[obj->dataType()] = typeCounter_[obj->dataType()] + 1;
1536  } else {
1537  typeCounter_[obj->dataType()] = 1;
1538  }
1539 
1541 
1542  updateTabsOrder();
1543 }
1544 
1545 //============================================================================================
1546 
1547 void SelectionBasePlugin::objectDeleted (int _id) {
1548  /*
1549  If an object was deleted, we will check if
1550  there exists a selection environment for the associated
1551  object type. If so and if this selection environment is
1552  available, we will remove it if there's no object
1553  of the given data type left in the scenegraph.
1554  */
1555  SelectionEnvironment* env = nullptr;
1556  bool found = false;
1557  BaseObjectData* obj = nullptr;
1558  if(findObjectType(obj,found, env, _id))
1559  {
1560  availableObjectTypes_ = (availableObjectTypes_ & ~obj->dataType().value());
1561  } else {
1562  emit log(LOGERR, "Could not retrieve object type!");
1563  return;
1564  }
1565 
1566  if(found) {
1567  // If we have found a selection environment for the
1568  // recently deleted data type AND if there's no
1569  // other object with the same data type in the
1570  // scene graph -> hide button
1571 
1572  // Search for other objects for *all* supported data types
1573  bool atLeastOne = false;
1574  for(std::vector<DataType>::iterator t_it = env->types.begin();
1575  t_it != env->types.end(); ++t_it) {
1576 
1577  if(typeExists(*t_it, _id)) {
1578  atLeastOne = true;
1579  break;
1580  }
1581  }
1582  // Show tab widget if at least one object of supported data type was found
1583  // Hide it otherwise
1584  tool_->typeTabWidget->setTabEnabled(tool_->typeTabWidget->indexOf(env->tabWidget), atLeastOne);
1585  env->tabWidget->setEnabled(atLeastOne);
1586  }
1587 
1588  // Decrease the number of available objects for that type
1589  // We track that here because otherwise we had to iterate over all objects
1590  // which would cause a linear runtime which is bad for high object counts.
1591  QMap<DataType, int>::iterator iterator = typeCounter_.find(obj->dataType());
1592  if ( iterator != typeCounter_.end() ) {
1593  typeCounter_[obj->dataType()] = typeCounter_[obj->dataType()] - 1;
1594  if ( typeCounter_[obj->dataType()] < 0 ) {
1595  std::cerr << "====== ERROR =======" << std::endl;
1596  std::cerr << "Negative counter for type " << obj->dataType().name().toStdString() << std::endl;
1597  }
1598  } else {
1599  std::cerr << "Error: No counter for type " << obj->dataType().name().toStdString() << std::endl;
1600  }
1601 
1603 
1604  updateTabsOrder();
1605 }
1606 
1607 //============================================================================================
1608 
1609 void SelectionBasePlugin::updateTabsOrder() {
1610 
1611  std::map<int, int> newMappings;
1612 
1613  int firstFree = 0;
1614  for(int i = 0; i < tool_->typeTabWidget->count(); ++i) {
1615  if(tool_->typeTabWidget->isTabEnabled(i)) {
1616  tool_->typeTabWidget->insertTab(firstFree, tool_->typeTabWidget->widget(i), tool_->typeTabWidget->tabText(i));
1617  newMappings.insert(std::pair<int,int>(i,firstFree));
1618  ++firstFree;
1619  } else {
1620  // Tab remains in old order
1621  newMappings.insert(std::pair<int,int>(i,i));
1622  }
1623  }
1624 
1625  // Choose first active tab
1626  if(tool_->typeTabWidget->count() > 0) tool_->typeTabWidget->setCurrentIndex(0);
1627 }
1628 
1629 //============================================================================================
1630 
1631 void SelectionBasePlugin::slotTargetObjectsOnly(bool& _targetsOnly) {
1632 
1633  if(OpenFlipper::Options::nogui() || tool_ == 0) {
1634  _targetsOnly = true;
1635  } else {
1636  _targetsOnly = tool_->restrictOnTargets->isChecked();
1637  }
1638 }
1639 
1640 //============================================================================================
1641 
1642 QString SelectionBasePlugin::getUniqueIdentifierName(QString _name, int _num) {
1643  /*
1644  This makes sure that we always have unique pickmode names
1645  in order to avoid double mappings.
1646 
1647  So we iterate over all selection modes and look if
1648  _name already exists as pickmode name. If the name exists,
1649  we append a number at the end of the string.
1650  */
1651  QString needle = _name;;
1652 
1653  if(_num != 0) {
1654  needle.append(QString::number(_num));
1655  }
1656 
1657  // Iterate over all selection environments
1658  for(std::map<QString,SelectionEnvironment>::iterator it = selectionEnvironments_.begin();
1659  it != selectionEnvironments_.end(); ++it) {
1660 
1661  // Iterate over all selection modes for this selection environment
1662  // This also includes the standard selection modes (toggle, sphere, etc.)
1663  for(std::set<HandleAction*>::iterator dsm_it = (*it).second.defaultSelectionModes.begin();
1664  dsm_it != (*it).second.defaultSelectionModes.end(); ++dsm_it) {
1665 
1666  if((*dsm_it)->selectionModeHandle() == needle) {
1667  // Recursive call with increased number
1668  return getUniqueIdentifierName(_name, _num + 1);
1669  }
1670  }
1671  }
1672 
1673  return needle;
1674 }
1675 
1676 //============================================================================================
1677 
1678 QString SelectionBasePlugin::getUniqueHandleName(QString _name, int _num) {
1679  /*
1680  This makes sure that we always have unique handle names
1681  in order to avoid double mappings.
1682 
1683  So we iterate over all selection environments and look if
1684  _name already exists as handle name. If the name exists,
1685  we append a number at the end of the string.
1686  */
1687  QString needle = _name;;
1688 
1689  if(_num != 0) {
1690  needle.append(QString::number(_num));
1691  }
1692 
1693  // Iterate over all selection environments
1694  for(std::map<QString,SelectionEnvironment>::iterator it = selectionEnvironments_.begin();
1695  it != selectionEnvironments_.end(); ++it) {
1696 
1697  if((*it).first == needle) {
1698  // Recursive call with increased number
1699  return getUniqueHandleName(_name, _num + 1);
1700  }
1701  }
1702 
1703  return needle;
1704 }
1705 
1706 //============================================================================================
1707 
1708 bool SelectionBasePlugin::typeExists(DataType _type, int _excludeId) {
1709 
1710  // Check the number of available objects for that type
1711  QMap<DataType, int>::iterator iterator = typeCounter_.find(_type);
1712  if ( iterator != typeCounter_.end() ) {
1713 
1714  // We count objects of a specific type and decrease the number by one
1715  // which basically happens, if we are about to remove an object.
1716  if ( _excludeId != -1 ) {
1717 
1718  // Sanity check. If the object is of a different type, something went wrong.
1719  BaseObject* object;
1720  PluginFunctions::getObject(_excludeId,object);
1721 
1722  if ( object == 0 ) {
1723  std::cerr << "Unable to get Object for type exists" << std::endl;
1724  } else {
1725  // mismatching exclude type
1726  if (_type != object->dataType()) {
1727  // return as if not excluded
1728  if ( typeCounter_[_type] > 0) {
1729  return true; // At least one object of this type exists
1730  } else if ( typeCounter_[_type] == 0 ){
1731  return false; // No object of this type exists
1732  } else {
1733  std::cerr << "Type exists Error after mismatch exclude: " << _type.name().toStdString() << " negative count" << std::endl;
1734  return false;
1735  }
1736  }
1737  }
1738 
1739  // Check the counter of the type
1740  if ( typeCounter_[_type] - 1 > 0) {
1741  return true; // At least one object of this type exists if we delete the excluded one
1742  } else if ( typeCounter_[_type] - 1 == 0 ){
1743  return false; // No object of this type exists if we delete the excluded one
1744  } else {
1745  std::cerr << "Type exists Error " << _type.name().toStdString() << " negative count" << std::endl;
1746  return false;
1747  }
1748  } else {
1749 
1750  // If we don't exclude items, we directly take the number we found.
1751  if ( typeCounter_[_type] > 0) {
1752  return true; // At least one object of this type exists
1753  } else if ( typeCounter_[_type] == 0 ){
1754  return false; // No object of this type exists
1755  } else {
1756  std::cerr << "Type exists Error " << _type.name().toStdString() << " negative count" << std::endl;
1757  return false;
1758  }
1759  }
1760 
1761  } else {
1762  // No counter available, which basically means it is equal to zero
1763  return false;
1764  }
1765 
1766  // This should never be reached!
1767  return false;
1768 }
1769 
1770 //============================================================================================
1771 
1772 void SelectionBasePlugin::slotRegisterKeyShortcut(int _key, Qt::KeyboardModifiers _modifiers) {
1773 
1774  std::set<std::pair<int,Qt::KeyboardModifiers> >::iterator f =
1775  registeredKeys_.find(std::pair<int,Qt::KeyboardModifiers>(_key,_modifiers));
1776 
1777  if(f == registeredKeys_.end()) {
1778  // Register key shortcut
1779  emit registerKey(_key, _modifiers, QString("Selection base key %1").arg(_key), true);
1780  registeredKeys_.insert(std::pair<int,Qt::KeyboardModifiers>(_key,_modifiers));
1781  }
1782 }
1783 
1784 //============================================================================================
1785 
1787 {
1788  // Find selection environment that is associated to _handleName
1789  std::map<QString,SelectionEnvironment>::iterator it = selectionEnvironments_.find(_handleName);
1790 
1791  // Return if the requested selection environment was not found
1792  if(it == selectionEnvironments_.end()) return false;
1793  env = &(it->second);
1794  return true;
1795 }
1796 
1797 //============================================================================================
1798 
1800  HandleAction* toggleSelectionAction_, PrimitiveType& _associatedTypes)
1801 {
1802  if(_show) {
1803  env->defaultSelectionModes.insert(toggleSelectionAction_);
1804  toggleSelectionAction_->addAssociatedType(_associatedTypes);
1805  } else {
1806  std::set<HandleAction*>::iterator e = env->defaultSelectionModes.find(toggleSelectionAction_);
1807  if(e != env->defaultSelectionModes.end()) {
1808  env->defaultSelectionModes.erase(e);
1809  toggleSelectionAction_->removeAssociatedType(_associatedTypes);
1810  }
1811  }
1812 }
1813 
1814 //============================================================================================
1815 
1817 {
1818  std::map<QString,SelectionEnvironment>::iterator it = selectionEnvironments_.begin();
1819  found = false;
1820  DataType t;
1821  PluginFunctions::getObject(_id, obj);
1822  if (obj) {
1823  t = obj->dataType();
1824 
1825  // Iterate over all selection environments
1826  for(;it != selectionEnvironments_.end(); ++it) {
1827 
1828  // Iterate over all supported data types of a selection environment
1829  for(std::vector<DataType>::iterator t_it = (*it).second.types.begin();
1830  t_it != (*it).second.types.end(); ++t_it) {
1831 
1832  if(t == (*t_it)) {
1833  found = true;
1834  break;
1835  }
1836  }
1837  if(found) break;
1838  }
1839  if (found)
1840  env = &it->second;
1841  return true;
1842  }
1843  else
1844  return false;
1845 }
1846 
1847 
1848 
bool scenegraphPick(ACG::SceneGraph::PickTarget _pickTarget, const QPoint &_mousePos, size_t &_nodeIdx, size_t &_targetIdx, ACG::Vec3d *_hitPointPtr=0)
Execute picking operation on scenegraph.
void setTraverseMode(unsigned int _mode)
Set traverse mode for node.
void selectionEnvironmentHandle(const QString _handle)
Get/Set associated selection environment handle.
void set_color(const Vec4f &_c)
Override material node&#39;s set color function in order to locally add color.
Definition: LineNode.cc:130
bool findObjectType(BaseObjectData *&obj, bool &found, SelectionEnvironment *&env, int _id)
helper function to find a baseObjectData and selection environment given a specific id ...
void disconnect()
Remove connection of this object to a file.
Definition: INIFile.cc:122
SelectionBasePlugin()
Default constructor.
picks faces (should be implemented for all nodes)
Definition: PickTarget.hh:78
DrawModes::DrawMode drawMode() const
Return the own draw modes of this node.
QString name() const
Return the name of this type as text.
Definition: Types.cc:416
VectorT< float, 4 > Vec4f
Definition: VectorT.hh:138
bool getObject(const int _identifier, BaseObject *&_object)
Get the object which has the given identifier.
Draw node in second pass.
Definition: BaseNode.hh:445
void clear()
clear points/lines and colors
Definition: LineNode.cc:101
void hide()
Hide Node: set status to HideNode.
void set_line_width(float _sz)
set line width (default: 1.0)
bool typeExists(DataType _type, int _excludeId=-1)
Test if at least one object of type _type is in the scene graph.
void add_point(const Vec3d &_v)
add point (for LineMode == PolygonMode)
Definition: LineNode.cc:141
void enable_blending(GLenum _p1=GL_SRC_ALPHA, GLenum _p2=GL_ONE_MINUS_SRC_ALPHA)
enable blending with Parameters (_p1, _p2)
QString getUniqueIdentifierName(QString _name, int _num=0)
Get a unique pickmode name.
bool hidden()
Is node not visible (status != Active)?
Predefined datatypes.
Definition: DataTypes.hh:83
void clear_points()
clear points/lines
Definition: LineNode.cc:109
DrawMode SOLID_SMOOTH_SHADED
draw smooth shaded (Gouraud shaded) faces (requires halfedge normals)
Definition: DrawModes.cc:82
void disable_alpha_test()
disable alpha test
void setSelectionMetaphor(QString _metaphor)
Enables setting the selection metaphor via scripting The default selection metaphors are: ...
QString getUniqueHandleName(QString _name, int _num=0)
Get a unique handle name.
bool dataType(DataType _type) const
Definition: BaseObject.cc:221
Vec3d unproject(const Vec3d &_winPoint) const
unproject point in window coordinates _winPoint to world coordinates
Definition: GLState.cc:651
void set_position(const Vec3d &_p, int _idx=0)
set position
Viewer::ActionMode actionMode()
Get the current Action mode.
pick any of the prior targets (should be implemented for all nodes)
Definition: PickTarget.hh:84
double sceneRadius()
Returns the current scene radius from the active examiner widget.
void selectionModeShowSwitch(bool _show, SelectionEnvironment *&env, HandleAction *toggleSelectionAction_, SelectionInterface::PrimitiveType &_associatedTypes)
helper function for showSelectionMode
void show()
Show node: set status to Active.
const std::string pickMode()
Get the current Picking mode.
void addAssociatedType(unsigned int _associatedType)
Get/Set associated primitive types.
unsigned int applyProperties() const
get properties that will be applied (OR&#39;ed ApplyProperties)
Primitive & get_primitive(int _idx)
get a primitive
void primitiveType(unsigned int _type)
Get/Set primitive type.
bool & alwaysOnTop()
get and set always on top
Definition: LineNode.hh:198
bool isGroup() const
Check if object is a group.
Definition: BaseObject.cc:619
Execute action on node first and then on its children.
Definition: BaseNode.hh:441
void enable_backface_culling()
enable backface culling (not active by default, see applyProperties)
Class for the handling of simple configuration files.
Definition: INIFile.hh:99
void addGlobalNode(ACG::SceneGraph::BaseNode *_node)
Add a global node.
void set_base_color(const Vec4f &_c)
set the base color ( Same as set_emission(const Vec4f& _c) )
QMap< DataType, int > typeCounter_
Caches the number of available elements of a certain data type for the typeExists function...
bool connect(const QString &name, const bool create)
Connect INIFile object with given filename.
Definition: INIFile.cc:70
Viewer::ViewerProperties & viewerProperties(int _id)
Get the viewer properties Use this functions to get basic viewer properties such as backgroundcolor o...
ACG::SceneGraph::MaterialNode MaterialNode
Materialnode.
bool getSelectionEnvironment(SelectionEnvironment *&env, const QString &_handleName)
Get a selectionEnvironment by a given name.
int context_height() const
get gl context height
Definition: GLState.hh:830
SelectionTypeFrameWidget * createNewTypeFrame(SelectionEnvironment &_env)
Create new type frame for tabs widget.
void set_size(double _s, int _idx=0)
set size
bool getPickedObject(const size_t _node_idx, BaseObjectData *&_object)
Get the picked mesh.
void setSelectionPrimitiveType(QString _primitive)
Enables setting the selection primitive via scripting The default primitives for OpenMesh are: ...
apply material (ambient, diffuse, specular, shininess)
void selectionEnvironmentHandle(QString _handle)
Get/Set selection environment handle name.
void updatePickModeToolBar()
Update the pickmode toolbar.
void selectionModeHandle(QString _handle)
Get/Set selection mode handle name.
ACG::GLState & glState()
Get the glState of the Viewer.
void set_color(const Vec4f &_c)
set color (base, ambient, diffuse, specular) based on _c
void showSelectionMode(QString _mode, QString _icon, QString _desc, QString _handleName, bool _show, SelectionInterface::PrimitiveType _associatedTypes, QString &_customIdentifier, bool _custom=false, DataType _objectTypeRestriction=DATA_ALL)