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