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