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