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