50 #ifdef ENABLE_OPENVOLUMEMESH_SUPPORT 52 #define OVM_PROPERTY_MODEL_CC 54 #include "OVMPropertyModel.hh" 57 template <
typename MeshT>
58 OVMPropertyModel<MeshT>::OVMPropertyModel(MeshT* mesh,
int objectID, QObject *parent)
59 : OVMPropertyModelSubclass(parent),
66 bCombine.setText(tr(
"Combine"));
68 connect(&bCombine, SIGNAL(clicked()),
69 this, SLOT(slotCombine()));
70 widgets->layout()->addWidget(&bCombine);
72 widgets->layout()->addWidget(&mLoadSaveWidget);
74 connect(mLoadSaveWidget.save_property , SIGNAL(clicked()),
75 this, SLOT(slotSaveProperty()));
77 connect(mLoadSaveWidget.load_property , SIGNAL(clicked()),
78 this, SLOT(slotLoadProperty()));
80 widgets->layout()->addWidget(&mPickWidget);
81 connect(mPickWidget.pickButton, SIGNAL(clicked()),
82 this, SLOT(slotPickProperty()));
84 QString iconPath = OpenFlipper::Options::iconDirStr() + OpenFlipper::Options::dirSeparator();
85 mPickWidget.pickButton->setIcon( QIcon(iconPath +
"color-picker.png") );
90 initializeSupportedPropertyTypes();
93 #undef INITIALIZE_PROPTYPES 95 template <
typename MeshT>
96 void OVMPropertyModel<MeshT>::updateWidget(
const QModelIndexList& selectedIndices)
100 if (selectedIndices.size() == 2)
102 if (combinable(propertyVisualizers[selectedIndices[0].row()], propertyVisualizers[selectedIndices[1].row()]))
106 mCombineProperty1 = &propertyVisualizers[selectedIndices[0].row()]->getPropertyInfo();
107 mCombineProperty2 = &propertyVisualizers[selectedIndices[1].row()]->getPropertyInfo();
117 if (selectedIndices.size() == 1)
123 if (mPickWidget.pickButton->isChecked())
129 template <
typename MeshT>
130 void OVMPropertyModel<MeshT>::resetPicking()
142 template <
typename MeshT>
143 void OVMPropertyModel<MeshT>::pickProperty()
145 if ( mPickWidget.pickButton->isChecked() ){
158 template <
typename MeshT>
159 void OVMPropertyModel<MeshT>::pickModeChanged(
const std::string& _mode)
161 pickModeActive = (_mode == PROP_VIS);
165 lastPickMode = _mode;
168 mPickWidget.pickButton->setChecked(pickModeActive);
177 template <
typename MeshT>
178 void OVMPropertyModel<MeshT>::mouseEvent(QMouseEvent* _event)
180 if (!pickModeActive)
return;
181 if (currentlySelectedIndices.size() < 1)
return;
183 if (_event->type() == QEvent::MouseButtonPress)
185 unsigned int node_idx;
189 OVMPropertyVisualizer<MeshT>* viz =
dynamic_cast<OVMPropertyVisualizer<MeshT>*
>(propertyVisualizers[currentlySelectedIndices.first().row()]);
190 unsigned int entityId = 0;
193 if (viz->getPropertyInfo().isCellProp())
195 if (viz->getPropertyInfo().isFaceProp())
197 if (viz->getPropertyInfo().isHalffaceProp())
199 if (viz->getPropertyInfo().isEdgeProp())
201 if (viz->getPropertyInfo().isHalfedgeProp())
203 if (viz->getPropertyInfo().isVertexProp())
210 if (object->
id() == objectID_)
212 if (viz->getPropertyInfo().isHalfedgeProp() || viz->getPropertyInfo().isHalffaceProp())
213 entityId = viz->getClosestPrimitiveId(entityId, hit_point);
215 mPickWidget.pickedHandle->setText(tr(
"%1").arg(entityId));
216 mPickWidget.pickedValue->setText(viz->getPropertyText(entityId));
223 template <
typename MeshT>
224 bool OVMPropertyModel<MeshT>::parseHeader(QString header,
PropertyVisualizer*& propVis,
unsigned int& n)
226 QStringList headerParts = header.split(tr(
", "), QString::SkipEmptyParts );
227 int headerVersion = headerParts[0].toUInt();
228 if (headerVersion == 1)
230 n = headerParts[1].toUInt();
231 unsigned int nExpected = 0;
233 PropertyInfo::ENTITY_FILTER filter = (PropertyInfo::ENTITY_FILTER)headerParts[2].toInt();
236 case PropertyInfo::EF_CELL:
237 nExpected = mesh_->n_cells();
239 case PropertyInfo::EF_FACE:
240 nExpected = mesh_->n_faces();
242 case PropertyInfo::EF_HALFFACE:
243 nExpected = mesh_->n_halffaces();
245 case PropertyInfo::EF_EDGE:
246 nExpected = mesh_->n_edges();
248 case PropertyInfo::EF_HALFEDGE:
249 nExpected = mesh_->n_halfedges();
251 case PropertyInfo::EF_VERTEX:
252 nExpected = mesh_->n_vertices();
261 std::cerr <<
"unexpected number of entities" << std::endl;
265 QString friendlyName = headerParts[3];
267 if (!isSupported(friendlyName))
269 std::cerr <<
"unsupported property type " << friendlyName.toStdString() << std::endl;
274 TypeInfoWrapper typeInfo = getSupportedTypeInfoWrapper(friendlyName, filter);
276 QString propName = QInputDialog::getText(0,
"Property Name",
"Please enter name.",
QLineEdit::Normal,headerParts[4]);
277 if (propName ==
"")
return false;
279 bool replace =
false;
280 if (!(isPropertyFree(propName, filter, typeInfo) || replace))
286 propName = QInputDialog::getText(0,
"New Property Name",
"Please enter new name.");
287 else if (msgBox->cancel)
289 else if (msgBox->replace)
297 addProperty(propName, friendlyName, filter);
301 propVis = getPropertyVisualizer(propName, filter, typeInfo);
308 std::cerr <<
"unsupported header format" << std::endl;
314 template<
typename MeshT>
315 QString OVMPropertyModel<MeshT>::getLoadFilenameFilter()
318 filter = tr(
"Vertex Property (*.vprop)");
319 filter += tr(
";; HalfEdge Property (*.hprop)");
320 filter += tr(
";; Edge Property (*.eprop)");
321 filter += tr(
";; Halfface Property (*.hfprop)");
322 filter += tr(
";; Face Property (*.fprop)");
323 filter += tr(
";; Cell Property (*.cprop)");
324 filter += tr(
";; All Files (*)");
328 template<
typename MeshT>
329 QString OVMPropertyModel<MeshT>::getSaveFilenameFilter(
unsigned int propId)
336 filter = tr(
"Vertex Property (*.vprop)");
338 filter = tr(
"HalfEdge Property (*.hprop)");
340 filter = tr(
"Edge Property (*.eprop)");
342 filter = tr(
"Face Property (*.fprop)");
344 filter += tr(
";; All Files (*)");
359 template<
typename MeshT>
360 bool OVMPropertyModel<MeshT>::isPropertyFree(QString propName, PropertyInfo::ENTITY_FILTER filter,
TypeInfoWrapper typeInfo)
362 return getPropertyVisualizer(propName, filter, typeInfo) == 0;
373 template<
typename MeshT>
374 void OVMPropertyModel<MeshT>::combine()
377 propertyVisualizers.push_back(
new OVMPropertyVisualizerVectorFieldDifference<MeshT>(mesh_, objectID_, *mCombineProperty1, *mCombineProperty2));
381 template<
typename MeshT>
382 void OVMPropertyModel<MeshT>::saveProperty()
384 for (QModelIndexList::const_iterator it = currentlySelectedIndices.begin(), it_end = currentlySelectedIndices.end();
385 it != it_end; ++it) {
403 template<
typename MeshT>
411 return (isVectorType(typeInfo1) && isVectorType(typeInfo2)) && (propInfo1.entityType() == propInfo2.entityType());
414 template<
typename MeshT>
415 void OVMPropertyModel<MeshT>::gatherProperties( MeshT* mesh,
416 typename MeshT::Properties::const_iterator props_first,
417 typename MeshT::Properties::const_iterator props_last,
418 PropertyInfo::ENTITY_FILTER filter)
420 for (
typename MeshT::Properties::const_iterator pit = props_first; pit != props_last; ++pit) {
422 if (baseProp && isSupported(baseProp) && isNew(baseProp, filter))
423 addPropertyVisualizer(baseProp, mesh, filter);
428 template<
typename MeshT>
429 void OVMPropertyModel<MeshT>::gatherProperties()
433 gatherProperties(mesh_, mesh_->face_props_begin(), mesh_->face_props_end(), PropertyInfo::EF_FACE);
434 gatherProperties(mesh_, mesh_->edge_props_begin(), mesh_->edge_props_end(), PropertyInfo::EF_EDGE);
435 gatherProperties(mesh_, mesh_->halfedge_props_begin(), mesh_->halfedge_props_end(), PropertyInfo::EF_HALFEDGE);
436 gatherProperties(mesh_, mesh_->vertex_props_begin(), mesh_->vertex_props_end(), PropertyInfo::EF_VERTEX);
437 gatherProperties(mesh_, mesh_->halfface_props_begin(), mesh_->halfface_props_end(), PropertyInfo::EF_HALFFACE);
438 gatherProperties(mesh_, mesh_->cell_props_begin(), mesh_->cell_props_end(), PropertyInfo::EF_CELL);
451 template<
typename MeshT>
455 TypeInfoWrapperSet::const_iterator propIt = supportedPropertyTypes.find(bp_type);
456 return propIt != supportedPropertyTypes.end();
469 template<
typename MeshT>
470 bool OVMPropertyModel<MeshT>::isSupported(QString friendlyName)
const 472 for (TypeInfoWrapperSet::const_iterator it = supportedPropertyTypes.begin();
473 it != supportedPropertyTypes.end();
476 if (friendlyName.toStdString().compare(it->getName()) == 0)
490 template<
typename MeshT>
493 for (
unsigned int i = 0; i < propertyVisualizers.size(); ++i)
495 const PropertyInfo& propInfo = propertyVisualizers[i]->getPropertyInfo();
496 if (propInfo ==
PropertyInfo(baseProp->name(), getSupportedTypeInfoWrapper(baseProp) , filter))
510 template<
typename MeshT>
514 TypeInfoWrapperSet::const_iterator propIt = supportedPropertyTypes.find(bp_type);
515 if (propIt != supportedPropertyTypes.end())
519 std::cerr <<
"error" << std::endl;
532 template<
typename MeshT>
533 TypeInfoWrapper OVMPropertyModel<MeshT>::getSupportedTypeInfoWrapper(QString friendlyName, PropertyInfo::ENTITY_FILTER filter)
const 536 for (TypeInfoWrapperSet::const_iterator it = supportedPropertyTypes.begin();
537 it != supportedPropertyTypes.end();
540 if ((friendlyName.toStdString().compare(it->getName()) == 0) && isEntityType(*it, filter))
543 throw std::exception();
546 template<
typename MeshT>
547 bool OVMPropertyModel<MeshT>::isBoolType(
const PropertyInfo& propInfo)
549 return isBoolType(propInfo.typeinfo());
552 template<
typename MeshT>
553 bool OVMPropertyModel<MeshT>::isBoolType(
const TypeInfoWrapper& typeInfo)
555 return typeInfo == proptype_Cell_bool ||
556 typeInfo == proptype_Face_bool ||
557 typeInfo == proptype_HalfFace_bool ||
558 typeInfo == proptype_Edge_bool ||
559 typeInfo == proptype_HalfEdge_bool ||
560 typeInfo == proptype_Vertex_bool;
563 template<
typename MeshT>
564 bool OVMPropertyModel<MeshT>::isIntType(
const PropertyInfo& propInfo)
566 return isIntType(propInfo.typeinfo());
569 template<
typename MeshT>
570 bool OVMPropertyModel<MeshT>::isIntType(
const TypeInfoWrapper& typeInfo)
572 return typeInfo == proptype_Cell_int ||
573 typeInfo == proptype_Face_int ||
574 typeInfo == proptype_HalfFace_int ||
575 typeInfo == proptype_Edge_int ||
576 typeInfo == proptype_HalfEdge_int ||
577 typeInfo == proptype_Vertex_int;
580 template<
typename MeshT>
581 bool OVMPropertyModel<MeshT>::isDoubleType(
const PropertyInfo& propInfo)
583 return isDoubleType(propInfo.typeinfo());
586 template<
typename MeshT>
587 bool OVMPropertyModel<MeshT>::isDoubleType(
const TypeInfoWrapper& typeInfo)
589 return typeInfo == proptype_Cell_double ||
590 typeInfo == proptype_Face_double ||
591 typeInfo == proptype_HalfFace_double ||
592 typeInfo == proptype_Edge_double ||
593 typeInfo == proptype_HalfEdge_double ||
594 typeInfo == proptype_Vertex_double;
597 template<
typename MeshT>
598 bool OVMPropertyModel<MeshT>::isUnsignedIntType(
const PropertyInfo& propInfo)
600 return isUnsignedIntType(propInfo.typeinfo());
603 template<
typename MeshT>
604 bool OVMPropertyModel<MeshT>::isUnsignedIntType(
const TypeInfoWrapper& typeInfo)
606 return typeInfo == proptype_Cell_uint ||
607 typeInfo == proptype_Face_uint ||
608 typeInfo == proptype_HalfFace_uint ||
609 typeInfo == proptype_Edge_uint ||
610 typeInfo == proptype_HalfEdge_uint ||
611 typeInfo == proptype_Vertex_uint;
614 template<
typename MeshT>
615 bool OVMPropertyModel<MeshT>::isVec3dType(
const PropertyInfo& propInfo)
617 return isVec3dType(propInfo.typeinfo());
620 template<
typename MeshT>
621 bool OVMPropertyModel<MeshT>::isVec3dType(
const TypeInfoWrapper& typeInfo)
623 return typeInfo == proptype_Cell_Vec3d ||
624 typeInfo == proptype_Face_Vec3d ||
625 typeInfo == proptype_HalfFace_Vec3d ||
626 typeInfo == proptype_Edge_Vec3d ||
627 typeInfo == proptype_HalfEdge_Vec3d ||
628 typeInfo == proptype_Vertex_Vec3d;
631 template<
typename MeshT>
632 bool OVMPropertyModel<MeshT>::isVec3fType(
const PropertyInfo& propInfo)
634 return isVec3fType(propInfo.typeinfo());
637 template<
typename MeshT>
638 bool OVMPropertyModel<MeshT>::isVec3fType(
const TypeInfoWrapper& typeInfo)
640 return typeInfo == proptype_Cell_Vec3f ||
641 typeInfo == proptype_Face_Vec3f ||
642 typeInfo == proptype_HalfFace_Vec3f ||
643 typeInfo == proptype_Edge_Vec3f ||
644 typeInfo == proptype_HalfEdge_Vec3f ||
645 typeInfo == proptype_Vertex_Vec3f;
648 template<
typename MeshT>
649 bool OVMPropertyModel<MeshT>::isVectorType(
const PropertyInfo& propInfo)
651 return isVec3fType(propInfo) || isVec3dType(propInfo);
654 template<
typename MeshT>
655 bool OVMPropertyModel<MeshT>::isVectorType(
const TypeInfoWrapper& typeInfo)
657 return isVec3fType(typeInfo) || isVec3dType(typeInfo);
660 template<
typename MeshT>
661 bool OVMPropertyModel<MeshT>::isEntityType(
const TypeInfoWrapper& typeInfo, PropertyInfo::ENTITY_FILTER entity_type)
const 664 if (entity_type & PropertyInfo::EF_CELL)
666 result |= (typeInfo == proptype_Cell_bool)
667 || (typeInfo == proptype_Cell_int)
668 || (typeInfo == proptype_Cell_double)
669 || (typeInfo == proptype_Cell_uint)
670 || (typeInfo == proptype_Cell_Vec3d)
671 || (typeInfo == proptype_Cell_Vec3f);
673 if (entity_type & PropertyInfo::EF_FACE)
675 result |= (typeInfo == proptype_Face_bool)
676 || (typeInfo == proptype_Face_int)
677 || (typeInfo == proptype_Face_double)
678 || (typeInfo == proptype_Face_uint)
679 || (typeInfo == proptype_Face_Vec3d)
680 || (typeInfo == proptype_Face_Vec3f);
682 if (entity_type & PropertyInfo::EF_HALFFACE)
684 result |= (typeInfo == proptype_HalfFace_bool)
685 || (typeInfo == proptype_HalfFace_int)
686 || (typeInfo == proptype_HalfFace_double)
687 || (typeInfo == proptype_HalfFace_uint)
688 || (typeInfo == proptype_HalfFace_Vec3d)
689 || (typeInfo == proptype_HalfFace_Vec3f);
691 if (entity_type & PropertyInfo::EF_EDGE)
693 result |= (typeInfo == proptype_Edge_bool)
694 || (typeInfo == proptype_Edge_int)
695 || (typeInfo == proptype_Edge_double)
696 || (typeInfo == proptype_Edge_uint)
697 || (typeInfo == proptype_Edge_Vec3d)
698 || (typeInfo == proptype_Edge_Vec3f);
700 if (entity_type & PropertyInfo::EF_HALFEDGE)
702 result |= (typeInfo == proptype_HalfEdge_bool)
703 || (typeInfo == proptype_HalfEdge_int)
704 || (typeInfo == proptype_HalfEdge_double)
705 || (typeInfo == proptype_HalfEdge_uint)
706 || (typeInfo == proptype_HalfEdge_Vec3d)
707 || (typeInfo == proptype_HalfEdge_Vec3f);
709 if (entity_type & PropertyInfo::EF_VERTEX)
711 result |= (typeInfo == proptype_Vertex_bool)
712 || (typeInfo == proptype_Vertex_int)
713 || (typeInfo == proptype_Vertex_double)
714 || (typeInfo == proptype_Vertex_uint)
715 || (typeInfo == proptype_Vertex_Vec3d)
716 || (typeInfo == proptype_Vertex_Vec3f);
732 template<
typename MeshT>
733 void OVMPropertyModel<MeshT>::addPropertyVisualizer(
OpenVolumeMesh::BaseProperty*
const baseProp, MeshT* mesh, PropertyInfo::ENTITY_FILTER filter)
736 if (isBoolType(propInfo))
737 propertyVisualizers.push_back(
new OVMPropertyVisualizerBoolean<MeshT>(mesh, objectID_, propInfo));
738 else if (isIntType(propInfo))
739 propertyVisualizers.push_back(
new OVMPropertyVisualizerInteger<MeshT, int>(mesh, objectID_, propInfo,
false));
740 else if (isUnsignedIntType(propInfo))
741 propertyVisualizers.push_back(
new OVMPropertyVisualizerInteger<MeshT, unsigned int>(mesh, objectID_, propInfo,
true));
742 else if (isDoubleType(propInfo))
743 propertyVisualizers.push_back(
new OVMPropertyVisualizerDouble<MeshT>(mesh, objectID_, propInfo));
744 else if (isVectorType(propInfo))
745 propertyVisualizers.push_back(
new OVMPropertyVisualizerVector<MeshT>(mesh, objectID_, propInfo));
746 connectLogs(propertyVisualizers.back());
759 template<
typename MeshT>
760 void OVMPropertyModel<MeshT>::addProperty(QString propName, QString friendlyTypeName, PropertyInfo::ENTITY_FILTER filter)
763 QString dtype = friendlyTypeName;
764 std::string pname = propName.toStdString();
768 if ( filter == PropertyInfo::EF_VERTEX )
770 if ( (dtype == tr(
"Vec3d")) || (dtype == tr(
"Vec3f")) )
773 mesh->set_persistent(prop,
true);
775 else if ( dtype == tr(
"double") )
778 mesh->set_persistent(prop,
true);
780 else if ( dtype == tr(
"unsigned int") )
783 mesh->set_persistent(prop,
true);
785 else if ( dtype == tr(
"int") )
788 mesh->set_persistent(prop,
true);
790 else if ( dtype == tr(
"bool") )
793 mesh->set_persistent(prop,
true);
796 else if ( filter == PropertyInfo::EF_EDGE )
798 if ( (dtype == tr(
"Vec3d")) || (dtype == tr(
"Vec3f")) )
801 mesh->set_persistent(prop,
true);
803 else if ( dtype == tr(
"double") )
806 mesh->set_persistent(prop,
true);
808 else if ( dtype == tr(
"unsgined int") )
811 mesh->set_persistent(prop,
true);
813 else if ( dtype == tr(
"int") )
816 mesh->set_persistent(prop,
true);
818 else if ( dtype == tr(
"bool") )
821 mesh->set_persistent(prop,
true);
824 else if ( filter == PropertyInfo::EF_FACE )
826 if ( (dtype == tr(
"Vec3d")) || (dtype == tr(
"Vec3f")) )
829 mesh->set_persistent(prop,
true);
831 else if ( dtype == tr(
"double") )
834 mesh->set_persistent(prop,
true);
836 else if ( dtype == tr(
"unsigned int") )
839 mesh->set_persistent(prop,
true);
841 else if ( dtype == tr(
"int") )
844 mesh->set_persistent(prop,
true);
846 else if ( dtype == tr(
"bool") )
849 mesh->set_persistent(prop,
true);
852 else if ( filter == PropertyInfo::EF_HALFEDGE )
854 if ( (dtype == tr(
"Vec3d")) || (dtype == tr(
"Vec3f")) )
857 mesh->set_persistent(prop,
true);
859 else if ( dtype == tr(
"double") )
862 mesh->set_persistent(prop,
true);
864 else if ( dtype == tr(
"unsigned int") )
867 mesh->set_persistent(prop,
true);
869 else if ( dtype == tr(
"int") )
872 mesh->set_persistent(prop,
true);
874 else if ( dtype == tr(
"bool") )
877 mesh->set_persistent(prop,
true);
880 else if ( filter == PropertyInfo::EF_HALFFACE )
882 if ( (dtype == tr(
"Vec3d")) || (dtype == tr(
"Vec3f")) )
885 mesh->set_persistent(prop,
true);
887 else if ( dtype == tr(
"double") )
890 mesh->set_persistent(prop,
true);
892 else if ( dtype == tr(
"unsigned int") )
895 mesh->set_persistent(prop,
true);
897 else if ( dtype == tr(
"int") )
900 mesh->set_persistent(prop,
true);
902 else if ( dtype == tr(
"bool") )
905 mesh->set_persistent(prop,
true);
908 else if ( filter == PropertyInfo::EF_CELL )
910 if ( (dtype == tr(
"Vec3d")) || (dtype == tr(
"Vec3f")) )
913 mesh->set_persistent(prop,
true);
915 else if ( dtype == tr(
"double") )
918 mesh->set_persistent(prop,
true);
920 else if ( dtype == tr(
"unsigned int") )
923 mesh->set_persistent(prop,
true);
925 else if ( dtype == tr(
"int") )
928 mesh->set_persistent(prop,
true);
930 else if ( dtype == tr(
"bool") )
933 mesh->set_persistent(prop,
true);
939 template <
typename MeshT>
940 void OVMPropertyModel<MeshT>::initializeSupportedPropertyTypes()
943 #define INSERT_PROPTYPES(primitive) \ 944 supportedPropertyTypes.insert(proptype_##primitive##_bool); \ 945 supportedPropertyTypes.insert(proptype_##primitive##_int); \ 946 supportedPropertyTypes.insert(proptype_##primitive##_uint); \ 947 supportedPropertyTypes.insert(proptype_##primitive##_double); \ 948 supportedPropertyTypes.insert(proptype_##primitive##_Vec3d); \ 949 supportedPropertyTypes.insert(proptype_##primitive##_Vec3f); \ 951 INSERT_PROPTYPES(Cell)
952 INSERT_PROPTYPES(Face)
953 INSERT_PROPTYPES(HalfFace)
954 INSERT_PROPTYPES(Edge)
955 INSERT_PROPTYPES(HalfEdge)
956 INSERT_PROPTYPES(Vertex)
958 #undef INITIALIZE_PROPTYPES bool scenegraphPick(ACG::SceneGraph::PickTarget _pickTarget, const QPoint &_mousePos, unsigned int &_nodeIdx, unsigned int &_targetIdx, ACG::Vec3d *_hitPointPtr=0)
Execute picking operation on scenegraph.
Asks the user how to proceed after a name clash.
Add normals to mesh item (vertices/faces)
virtual void updateWidget(const QModelIndexList &selectedIndices)
Updates the widget.
Cellection of information about a property.
const PropertyInfo & getPropertyInfo() const
Returns the PropertyInfo.
This class vizualizes a property.
bool getPickedObject(const unsigned int _node_idx, BaseObjectData *&_object)
Get the picked mesh.
PickTarget
What target to use for picking.
const std::string pickMode()
Get the current Picking mode.
Property classes for the different entity types.
picks verices (may not be implemented for all nodes)
Viewer::ActionMode actionMode()
Get the current Action mode.
picks edges (may not be implemented for all nodes)
picks faces (may not be implemented for all nodes)
void saveProperty(unsigned int propId)
Saves property.
Wraps the information of a type.
picks faces (should be implemented for all nodes)