Developer Documentation
ObjectSelectionPlugin.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 "ObjectSelectionPlugin.hh"
51 
53 
54 // Primitive type icons
55 #define OBJECT_TYPE "selection_object.png"
56 // =======================================
57 // Define operations
58 // =======================================
59 // Vertices:
60 #define O_SELECT_ALL "Select All Objects"
61 #define O_DESELECT_ALL "Deselect All Objects"
62 #define O_INVERT "Invert Object Selection"
63 #define O_DELETE "Delete Selected Objects"
64 
67 objectType_(0) {
68 }
69 
70 //==============================================================================================
71 
73 }
74 
75 //==============================================================================================
76 
77 void ObjectSelectionPlugin::initializePlugin() {
78 
79  // Tell core about all scriptable slots
81 }
82 
83 //==============================================================================================
84 
85 void ObjectSelectionPlugin::pluginsInitialized() {
86  // Create new selection environment for polylines
87  // and register polyline data type for the environment.
88 
89  QString iconPath = OpenFlipper::Options::iconDirStr() + OpenFlipper::Options::dirSeparator();
90 
91  emit addSelectionEnvironment("Object Selections", "Select objects.",
92  iconPath + OBJECT_TYPE, environmentHandle_);
93 
94  // Register mesh object types
95  emit registerType(environmentHandle_, DATA_ALL);
96 
97  emit addPrimitiveType(environmentHandle_, "Select Objects", iconPath + OBJECT_TYPE, objectType_);
98 
99  // Determine, which selection modes are requested
100  emit showToggleSelectionMode(environmentHandle_, true, objectType_);
101  emit showVolumeLassoSelectionMode(environmentHandle_, true, objectType_);
102 
103  // Define object operations
104  QStringList objectOperations;
105  objectOperations.append(O_SELECT_ALL);
106  objectOperations.append(O_DESELECT_ALL);
107  objectOperations.append(O_INVERT);
108  objectOperations.append(O_DELETE);
109 
110  emit addSelectionOperations(environmentHandle_, objectOperations, "Object Operations", objectType_);
111 
112  // Register key shortcuts:
113 
114  // Select (a)ll
115  emit registerKeyShortcut(Qt::Key_A, Qt::ControlModifier);
116  // (C)lear selection
117  emit registerKeyShortcut(Qt::Key_C, Qt::NoModifier);
118  // (I)nvert selection
119  emit registerKeyShortcut(Qt::Key_I, Qt::NoModifier);
120  // Delete selected entities
121  emit registerKeyShortcut(Qt::Key_Delete, Qt::NoModifier);
122 }
123 
124 //==============================================================================================
125 
127 
128  emit setSlotDescription("selectAllObjects(int)", tr("Select all objects"),
129  QStringList("objectId"), QStringList("Id of object"));
130  emit setSlotDescription("deselectAllObjects(int)", tr("Deselect all objects"),
131  QStringList("objectId"), QStringList("Id of object"));
132  emit setSlotDescription("invertObjectSelection(int)", tr("Invert object selection"),
133  QStringList("objectId"), QStringList("Id of object"));
134  emit setSlotDescription("deleteSelectedObjects(int)", tr("Delete selected objects"),
135  QStringList("objectId"), QStringList("Id of object"));
136  emit setSlotDescription("selectObjects(int,IdList)", tr("Select the specified objects"),
137  QString("objectId,objectList").split(","), QString("Id of object,List of objects").split(","));
138 
139  emit setSlotDescription("loadSelection(int,QString)", tr("Load selection from selection file"),
140  QString("objectId,filename").split(","), QString("Id of an object,Selection file").split(","));
141 }
142 
143 //==============================================================================================
144 
146 
147  SelectionInterface::PrimitiveType type = 0u;
148  emit getActivePrimitiveType(type);
149 
150  if((type & objectType_) == 0)
151  return;
152 
153  if(_operation == O_SELECT_ALL) {
154  // Select all objects
156  } else if (_operation == O_DESELECT_ALL) {
157  // Deselect all objects
159  } else if (_operation == O_INVERT) {
160  // Invert object selection
162  } else if (_operation == O_DELETE) {
163  // Delete selected objects
165  }
166 }
167 
168 //==============================================================================================
169 
170 void ObjectSelectionPlugin::slotToggleSelection(QMouseEvent* _event, SelectionInterface::PrimitiveType _currentType, bool _deselect) {
171 
172  // Return if none of the currently active types is handled by this plugin
173  if((_currentType & objectType_) == 0) return;
174 
175  // Return if mouse event is not a left-button click
176  if(_event->button() != Qt::LeftButton) return;
177 
178  unsigned int node_idx = 0;
179  unsigned int target_idx = 0;
180  ACG::Vec3d hit_point;
181 
182  BaseObjectData* object = 0;
183 
184  bool successfullyPicked = PluginFunctions::scenegraphPick(ACG::SceneGraph::PICK_ANYTHING, _event->pos(), node_idx,
185  target_idx, &hit_point) && PluginFunctions::getPickedObject(node_idx, object);
186 
187  if(successfullyPicked) {
188 
189  if(object->target() || _deselect)
190  object->target(false);
191  else
192  object->target(true);
193 
194  emit updatedObject(object->id(), UPDATE_SELECTION);
195  }
196 }
197 
198 //==============================================================================================
199 
200 void ObjectSelectionPlugin::slotVolumeLassoSelection(QMouseEvent* _event, SelectionInterface::PrimitiveType _currentType, bool _deselect) {
201 
202  // Return if none of the currently active types is handled by this plugin
203  if((_currentType & objectType_) == 0) return;
204 
205  ACG::Vec3d hit_point;
206 
207  if(_event->type() == QEvent::MouseButtonPress) {
208 
210  QPoint p(_event->pos().x(), state.viewport_height() - _event->pos().y());
211 
212  volumeLassoPoints_.append(p);
213 
214  return;
215 
216  } else if(_event->type() == QEvent::MouseButtonDblClick) {
217 
219 
220  QPolygon polygon(volumeLassoPoints_);
221 
222  // Select all vertices that lie in this region
224  o_it != PluginFunctions::objectsEnd(); ++o_it) {
225 
226  if (o_it->visible()) {
227 
228  // Look if COG of object lies within polygon
229  ACG::Vec3d bbmin(0.0);
230  ACG::Vec3d bbmax(0.0);
231  o_it->getBoundingBox(bbmin, bbmax);
232  ACG::Vec3d c = (bbmin + bbmax)/2.0;
233 
234  ACG::Vec3d pc = state.project(c);
235  QPoint p((int)pc[0], (int)pc[1]);
236 
237  if(polygon.containsPoint(p, Qt::OddEvenFill)) {
238  o_it->target(!_deselect);
239  }
240  }
241 
242  emit updatedObject(o_it->id(), UPDATE_SELECTION);
243  }
244 
245 
246  // Clear lasso points
247  volumeLassoPoints_.clear();
248  }
249 }
250 
251 //==============================================================================================
252 
253 void ObjectSelectionPlugin::loadSelection(int _objId, const QString& _filename) {
254 
255  // Load ini file
256  INIFile file;
257 
258  if(!file.connect(_filename, false)) {
259  emit log(LOGERR, QString("Could not read file '%1'!").arg(_filename));
260  return;
261  }
262 
263  // Load selection from file
264  loadIniFile(file, _objId);
265 }
266 
267 //==============================================================================================
268 
269 void ObjectSelectionPlugin::loadIniFile(INIFile& _ini, int _id) {
270  // From INI Interface
271  // Load plugin specific settings
272 }
273 
274 //==============================================================================================
275 
276 void ObjectSelectionPlugin::saveIniFile(INIFile& _ini, int _id) {
277  // From INI Interface
278  // Save plugin specific settings
279 }
280 
281 //==============================================================================================
282 
284 
285  // Iterate over all polyline objects in the scene and save
286  // the selections for all supported entity types
288  o_it != PluginFunctions::objectsEnd(); ++o_it) {
289 
290  // Read section for each object
291  // Append object name to section identifier
292  QString section = QString("ObjectSelection") + "//" + o_it->name();
293  if(!_file.section_exists(section)) {
294  continue;
295  }
296 
297  std::vector<int> ids;
298  // Load vertex selection:
299  _file.get_entry(ids, section, "Target");
300  selectObjects(ids);
301  ids.clear();
302 
303  emit updatedObject(o_it->id(), UPDATE_SELECTION);
304  }
305 }
306 
307 //==============================================================================================
308 
310 
311  // Iterate over all polyline objects in the scene and save
312  // the selections for all vertices
314  o_it != PluginFunctions::objectsEnd(); ++o_it) {
315 
316  // Create section for each object
317  // Append object name to section identifier
318  QString section = QString("ObjectSelection") + "//" + o_it->name();
319 
320  // Store vertex selection:
321  _file.add_entry(section, "Target", getObjectSelection());
322  }
323 }
324 
325 //==============================================================================================
326 
327 void ObjectSelectionPlugin::slotKeyShortcutEvent(int _key, Qt::KeyboardModifiers _modifiers) {
328 
329  SelectionInterface::PrimitiveType type = 0u;
330  emit getActivePrimitiveType(type);
331 
332  if((type & objectType_) == 0) {
333  // No supported type is active
334  return;
335  }
336 
337  if(_key == Qt::Key_A && _modifiers == Qt::ControlModifier) {
338  // Select all objects
340  } else if(_key == Qt::Key_C && _modifiers == Qt::NoModifier) {
341  // Deselect all vertices
343  } else if(_key == Qt::Key_I && _modifiers == Qt::NoModifier) {
344  // Invert object selection
346  } else if(_key == Qt::Key_Delete && _modifiers == Qt::NoModifier) {
347  // Delete selected objects
349  }
350 }
351 
352 //==============================================================================================
353 
354 #if QT_VERSION < 0x050000
355  Q_EXPORT_PLUGIN2(objectselectionplugin, ObjectSelectionPlugin);
356 #endif
357 
358 
bool scenegraphPick(ACG::SceneGraph::PickTarget _pickTarget, const QPoint &_mousePos, unsigned int &_nodeIdx, unsigned int &_targetIdx, ACG::Vec3d *_hitPointPtr=0)
Execute picking operation on scenegraph.
Predefined datatypes.
Definition: DataTypes.hh:96
void updateSlotDescriptions()
Set slot descriptions for scripting functions.
ACG::GLState & glState()
Get the glState of the Viewer.
void slotSelectionOperation(QString _operation)
A specific operation is requested.
PrimitiveType objectType_
Primitive type handles:
void slotKeyShortcutEvent(int _key, Qt::KeyboardModifiers _modifiers)
One of the previously registered keys has been pressed.
void slotLoadSelection(const INIFile &_file)
Load selection for specific objects in the scene.
int id() const
Definition: BaseObject.cc:201
const QStringList ALL_OBJECTS
Iterable object range.
bool getPickedObject(const unsigned int _node_idx, BaseObjectData *&_object)
Get the picked mesh.
Vec3d project(const Vec3d &_point) const
project point in world coordinates to window coordinates
Definition: GLState.cc:638
void slotToggleSelection(QMouseEvent *_event, SelectionInterface::PrimitiveType _currentType, bool _deselect)
Called whenever the user performs a toggle selection.
bool target()
Definition: BaseObject.cc:284
bool get_entry(QString &_val, const QString &_section, const QString &_key) const
Access to a string entry.
Definition: INIFile.cc:439
~ObjectSelectionPlugin()
Default destructor.
void selectAllObjects()
Select all objects.
Viewer::ViewerProperties & viewerProperties(int _id)
Get the viewer properties Use this functions to get basic viewer properties such as backgroundcolor o...
IdList getObjectSelection()
Get selected objects.
const DataType DATA_ALL(UINT_MAX)
Identifier for all available objects.
QString environmentHandle_
Handle to selection environment.
bool section_exists(const QString &_section) const
Check if given section exists in the current INI file.
Definition: INIFile.cc:233
void slotSaveSelection(INIFile &_file)
Save selection for all objects in the scene.
bool connect(const QString &name, const bool create)
Connect INIFile object with given filename.
Definition: INIFile.cc:76
Class for the handling of simple configuration files.
Definition: INIFile.hh:105
QVector< QPoint > volumeLassoPoints_
Keep volume lasso points.
const UpdateType UPDATE_SELECTION(UpdateTypeSet(1)<< 4)
Selection updated.
void slotVolumeLassoSelection(QMouseEvent *_event, SelectionInterface::PrimitiveType _currentType, bool _deselect)
Called whenever the user performs a volume lasso selection.
pick any of the prior targets (should be implemented for all nodes)
Definition: BaseNode.hh:110
int viewport_height() const
get viewport height
Definition: GLState.hh:827
void deselectAllObjects()
Deselect all objects.
ObjectSelectionPlugin()
Default constructor.
void add_entry(const QString &_section, const QString &_key, const QString &_value)
Addition / modification of a string entry.
Definition: INIFile.cc:263
DLLEXPORT ObjectIterator objectsEnd()
Return Iterator to Object End.
void deleteSelectedObjects()
Delete selected objects.
void selectObjects(IdList _list)
Select specified objects.
void invertObjectSelection()
Invert object selection.