Commit d51a34d8 authored by Isaak Lim's avatar Isaak Lim

added support for mutltiple objects (OpenMesh) Thanks to Alexander Dielen

git-svn-id: http://www.openflipper.org/svnrepo/OpenFlipper/branches/Free@21166 383ad7c9-94d9-4d36-a494-682f7c89f535
parent 8aa8d9ef
#include "MultiObjectPropertyModel.hh"
#include "PropertyModelFactory.hh"
#include "OpenMesh/OMPropertyModel.hh"
#include "OpenVolumeMesh/OVMPropertyModel.hh"
#include "OpenVolumeMesh/Mesh/HexahedralMesh.hh"
MultiObjectPropertyModel::MultiObjectPropertyModel(const QStringList& res, QObject *parent) :
PropertyModel(parent), restriction(res), widget(0)
{
QVBoxLayout* layout = new QVBoxLayout();
widget = new QWidget();
widget->setLayout(layout);
}
MultiObjectPropertyModel::~MultiObjectPropertyModel()
{
for (size_t i = 0; i < propWidgets.size(); ++i)
{
delete propWidgets[i];
}
delete widget;
}
QVariant MultiObjectPropertyModel::data(const QModelIndex & index, int role) const
{
switch (role) {
case Qt::DisplayRole:
return QVariant(propNames[index.row()]);
default:
return QVariant::Invalid;
}
}
int MultiObjectPropertyModel::rowCount(const QModelIndex & parent) const
{
return propNames.size();
}
QVariant MultiObjectPropertyModel::headerData(int section, Qt::Orientation orientation, int role) const
{
return QVariant::Invalid;
}
void MultiObjectPropertyModel::objectUpdated()
{
using namespace PluginFunctions;
for (ObjectIterator o_it(restriction, DATA_TRIANGLE_MESH | DATA_POLY_MESH); o_it != objectsEnd(); ++o_it)
{
// get the property model and call objectUpdated
PropertyModel* model = PropertyModelFactory::Instance().getModel(o_it->id());
if (model == 0) continue;
model->objectUpdated();
}
}
void MultiObjectPropertyModel::visualize(QModelIndexList selectedIndices, QWidgetList widgets)
{
using namespace PluginFunctions;
// return if nothing is selected
if (selectedIndices.size() < 1) return;
for (ObjectIterator o_it(restriction, DATA_TRIANGLE_MESH | DATA_POLY_MESH); o_it != objectsEnd(); ++o_it)
{
// get the property model and update it
PropertyModel* model = PropertyModelFactory::Instance().getModel(o_it->id());
if (model == 0) continue;
model->gatherProperties();
QModelIndexList indexList;
QWidgetList widgetList;
for (int i = 0; i < selectedIndices.size(); ++i)
{
const QString name = selectedIndices[i].data().toString();
// skip this property if it does not exist
const QModelIndex idx = model->indexFromPropName(name);
if (!idx.isValid()) continue;
// insert items into lists
indexList.append(idx);
widgetList.append(propWidgets[selectedIndices[i].row()]);
}
// visualize the property
model->visualize(indexList, widgetList);
}
}
void MultiObjectPropertyModel::removeProperty(QModelIndexList selectedIndices)
{
using namespace PluginFunctions;
// return if nothing is selected
if (selectedIndices.size() < 1) return;
for (ObjectIterator o_it(restriction, DATA_TRIANGLE_MESH | DATA_POLY_MESH); o_it != objectsEnd(); ++o_it)
{
PropertyModel* model = PropertyModelFactory::Instance().getModel(o_it->id());
if (model == 0) continue;
QModelIndexList indexList;
for (int i = 0; i < selectedIndices.size(); ++i)
{
const QString name = selectedIndices[i].data().toString();
// skip this property if it does not exist
const QModelIndex idx = model->indexFromPropName(name);
if (!idx.isValid()) continue;
// insert item into list
indexList.append(idx);
}
model->removeProperty(indexList);
}
// update this model
gatherProperties();
}
void MultiObjectPropertyModel::duplicateProperty(QModelIndexList selectedIndices)
{
using namespace PluginFunctions;
// return if nothing is selected
if (selectedIndices.size() < 1) return;
for (ObjectIterator o_it(restriction, DATA_TRIANGLE_MESH | DATA_POLY_MESH); o_it != objectsEnd(); ++o_it)
{
PropertyModel* model = PropertyModelFactory::Instance().getModel(o_it->id());
if (model == 0) continue;
QModelIndexList indexList;
for (int i = 0; i < selectedIndices.size(); ++i)
{
const QString name = selectedIndices[i].data().toString();
// skip this property if it does not exist
const QModelIndex idx = model->indexFromPropName(name);
if (!idx.isValid()) continue;
// insert item into list
indexList.append(idx);
}
model->duplicateProperty(indexList);
}
// update this model
gatherProperties();
}
void MultiObjectPropertyModel::gatherProperties()
{
using namespace PluginFunctions;
beginResetModel();
propNames.clear();
propInfos.clear();
for (size_t i = 0; i < propWidgets.size(); ++i)
{
delete propWidgets[i];
}
propWidgets.clear();
endResetModel();
for (ObjectIterator o_it(restriction, DATA_TRIANGLE_MESH | DATA_POLY_MESH); o_it != objectsEnd(); ++o_it)
{
PropertyModel* model = PropertyModelFactory::Instance().getModel(o_it->id());
if (model == 0) continue;
model->gatherProperties();
for (int i = 0; i < model->rowCount(); ++i)
{
const QModelIndex idx = model->index(i, 0);
const QString name = idx.data().toString();
// add property
if (std::find(propNames.begin(), propNames.end(), name) == propNames.end())
{
PropertyInfo info = model->getPropertyInfo(idx);
QWidget* widget = createWidgetForType(info.typeinfo());
setRange(info, widget);
propNames.push_back(name);
propInfos.push_back(info);
propWidgets.push_back(widget);
}
}
}
}
void MultiObjectPropertyModel::clear(QModelIndexList selectedIndices)
{
using namespace PluginFunctions;
// return if nothing is selected
if (selectedIndices.size() < 1) return;
for (ObjectIterator o_it(restriction, DATA_TRIANGLE_MESH | DATA_POLY_MESH); o_it != objectsEnd(); ++o_it)
{
PropertyModel* model = PropertyModelFactory::Instance().getModel(o_it->id());
if (model == 0) continue;
QModelIndexList indexList;
for (int i = 0; i < selectedIndices.size(); ++i)
{
const QString name = selectedIndices[i].data().toString();
// skip this property if it does not exist
const QModelIndex idx = model->indexFromPropName(name);
if (!idx.isValid()) continue;
// insert item into list
indexList.append(idx);
}
model->clear(indexList);
}
}
void MultiObjectPropertyModel::hideWidget()
{
widget->hide();
}
QWidget* MultiObjectPropertyModel::getWidget()
{
return widget;
}
void MultiObjectPropertyModel::updateWidget(const QModelIndexList& selectedIndices)
{
QLayout* layout = widget->layout();
for (unsigned int i = 0; i < propWidgets.size(); ++i)
{
propWidgets[i]->hide();
}
for (int i = 0; i < selectedIndices.size(); ++i)
{
const int row = selectedIndices[i].row();
QWidget* w = propWidgets[row];
layout->addWidget(w);
w->show();
}
widget->setLayout(layout);
}
void MultiObjectPropertyModel::connectLogs(PropertyVisualizer* propViz)
{
}
PropertyInfo MultiObjectPropertyModel::getPropertyInfo(const QModelIndex index) const
{
return propInfos[index.row()];
}
QWidget* MultiObjectPropertyModel::createWidgetForType(const TypeInfoWrapper& info) const
{
// OpenMesh
// ----------------------------------------
if (info == OMPropertyModel<TriMesh>::proptype_bool)
return new BooleanWidget();
if (info == OMPropertyModel<TriMesh>::proptype_int)
return new IntegerWidget();
if (info == OMPropertyModel<TriMesh>::proptype_uint)
return new IntegerWidget();
if (info == OMPropertyModel<TriMesh>::proptype_double)
return new DoubleWidget();
if (info == OMPropertyModel<TriMesh>::proptype_Vec3d)
return new VectorWidget;
if (info == OMPropertyModel<TriMesh>::proptype_Vec3f)
return new VectorWidget;
if (info == OMPropertyModel<TriMesh>::proptype_Vec2d)
return new VectorWidget;
if (info == OMPropertyModel<TriMesh>::proptype_Vec2f)
return new VectorWidget;
#ifdef ENABLE_SKELETON_SUPPORT
if (info == OMPropertyModel<TriMesh>::proptype_SkinWeights)
return new SkinWeightsWidget;
#endif
// OpenVolumeMesh
// ----------------------------------------
if (OVMPropertyModel<HexahedralMesh>::isBoolType(info))
return new BooleanWidget();
if (OVMPropertyModel<HexahedralMesh>::isIntType(info))
return new IntegerWidget();
if (OVMPropertyModel<HexahedralMesh>::isUnsignedIntType(info))
return new IntegerWidget();
if (OVMPropertyModel<HexahedralMesh>::isDoubleType(info))
return new DoubleWidget();
if (OVMPropertyModel<HexahedralMesh>::isVec3dType(info))
return new VectorWidget();
if (OVMPropertyModel<HexahedralMesh>::isVec3fType(info))
return new VectorWidget();
// Other
// ----------------------------------------
return new QWidget();
}
template <typename ItemHandle, typename PropHandle, typename T>
void range2(const OpenMesh::BaseKernel* mesh, unsigned int n, const std::string& name, T& min, T& max)
{
PropHandle ph;
mesh->get_property_handle(ph, name);
if (!ph.is_valid()) return;
for (unsigned int i = 0; i < n; ++i)
{
const ItemHandle ih(i);
min = std::min(min, mesh->property(ph, ih));
max = std::max(max, mesh->property(ph, ih));
}
}
template <typename T>
void range1(const BaseObject* obj, const PropertyInfo& info, T& min, T& max)
{
using namespace PluginFunctions;
OpenMesh::BaseKernel* mesh = 0;
if (obj->dataType(DATA_TRIANGLE_MESH))
mesh = triMesh(obj->id());
if (obj->dataType(DATA_POLY_MESH))
mesh = polyMesh(obj->id());
if (mesh == 0) return;
if (info.isVertexProp())
range2<OpenMesh::VertexHandle, OpenMesh::VPropHandleT<T>, T>
(mesh, mesh->n_vertices(), info.propName(), min, max);
if (info.isHalfedgeProp())
range2<OpenMesh::HalfedgeHandle, OpenMesh::HPropHandleT<T>, T>
(mesh, mesh->n_halfedges(), info.propName(), min, max);
if (info.isEdgeProp())
range2<OpenMesh::EdgeHandle, OpenMesh::EPropHandleT<T>, T>
(mesh, mesh->n_edges(), info.propName(), min, max);
if (info.isFaceProp())
range2<OpenMesh::FaceHandle, OpenMesh::FPropHandleT<T>, T>
(mesh, mesh->n_faces(), info.propName(), min, max);
}
void MultiObjectPropertyModel::setRange(const PropertyInfo& info, QWidget* widget) const
{
using namespace PluginFunctions;
if (info.typeinfo() == OMPropertyModel<TriMesh>::proptype_double)
{
double min = +DBL_MAX;
double max = -DBL_MAX;
for (ObjectIterator o_it(restriction, DATA_TRIANGLE_MESH | DATA_POLY_MESH); o_it != objectsEnd(); ++o_it)
{
range1<double>(*o_it, info, min, max);
}
DoubleWidget* w = static_cast<DoubleWidget*>(widget);
w->doubleFixedRange->toggle();
w->doubleFixedRangeMin->setValue(min);
w->doubleFixedRangeMax->setValue(max);
}
if (info.typeinfo() == OMPropertyModel<TriMesh>::proptype_int)
{
int min = +INT_MAX;
int max = -INT_MAX;
for (ObjectIterator o_it(restriction, DATA_TRIANGLE_MESH | DATA_POLY_MESH); o_it != objectsEnd(); ++o_it)
{
range1<int>(*o_it, info, min, max);
}
IntegerWidget* w = static_cast<IntegerWidget*>(widget);
w->intFixedRange->toggle();
w->intFixedRangeMin->setValue(min);
w->intFixedRangeMax->setValue(max);
}
}
#ifndef MULTI_OBJECT_PROPERTY_MODEL_H
#define MULTI_OBJECT_PROPERTY_MODEL_H
#include "PropertyModel.hh"
class PropertyVisualizer;
class MultiObjectPropertyModel: public PropertyModel
{
Q_OBJECT
public:
MultiObjectPropertyModel(const QStringList& res, QObject *parent = 0);
virtual ~MultiObjectPropertyModel();
virtual int rowCount(const QModelIndex & parent = QModelIndex()) const;
virtual QVariant data(const QModelIndex & index, int role = Qt::DisplayRole) const;
virtual QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const;
/// Revisualizes visualized properties.
virtual void objectUpdated();
/// Visualizes the selected properties.
virtual void visualize(QModelIndexList selectedIndices, QWidgetList widgets = QWidgetList());
/// Removes the selected properties.
virtual void removeProperty(QModelIndexList selectedIndices);
/// Duplicates the selected properties.
virtual void duplicateProperty(QModelIndexList selectedIndices);
/// Searches for properties and creates PropertyVisualizers.
virtual void gatherProperties();
/// Clears the selected property visualization.
virtual void clear(QModelIndexList selectedIndices);
/// Hides the widget.
virtual void hideWidget();
/// Returns the widget.
virtual QWidget* getWidget();
/// Updates the widget
virtual void updateWidget(const QModelIndexList& selectedIndices);
/// Connects the PropertyVisualizer log signals with the log slot.
virtual void connectLogs(PropertyVisualizer* propViz);
/// Returns the property info for the property with the given index.
virtual PropertyInfo getPropertyInfo(const QModelIndex index) const;
private:
QWidget* createWidgetForType(const TypeInfoWrapper& info) const;
void setRange(const PropertyInfo& info, QWidget* widget) const;
private:
const QStringList restriction;
std::vector<QString> propNames;
std::vector<PropertyInfo> propInfos;
std::vector<QWidget*> propWidgets;
QWidget* widget;
};
#endif /* MULTI_OBJECT_PROPERTY_MODEL_H */
......@@ -89,6 +89,10 @@ void ObjectListItemModel::removeObject(int _id)
void ObjectListItemModel::refresh(const DataType &datatype) {
std::vector<ObjectInfo> objects;
objects.push_back(ObjectInfo("ALL_OBJECTS", -13));
objects.push_back(ObjectInfo("TARGET_OBJECTS", -14));
objects.push_back(ObjectInfo("SOURCE_OBJECTS", -15));
for (PluginFunctions::ObjectIterator o_it(PluginFunctions::ALL_OBJECTS, datatype);
o_it != PluginFunctions::objectsEnd(); ++o_it) {
objects.push_back(ObjectInfo(o_it->name(), o_it->id()));
......
......@@ -50,7 +50,7 @@
#ifndef OM_PROPERTY_MODEL_H
#define OM_PROPERTY_MODEL_H
#include "../PropertyModel.hh"
#include "SingleObjectPropertyModel.hh"
#include "OMPropertyVisualizer.hh"
#include "Widgets/LoadSaveWidget.hh"
......@@ -69,12 +69,12 @@ class PropertyVisPlugin;
* slots or Q_OBJECT"
* http://doc.trolltech.com/qq/qq15-academic.html
*/
class OMPropertyModelSubclass: public PropertyModel
class OMPropertyModelSubclass: public SingleObjectPropertyModel
{
Q_OBJECT
public:
OMPropertyModelSubclass(QObject *parent = 0)
: PropertyModel(parent)
: SingleObjectPropertyModel(parent)
{
}
......@@ -161,9 +161,22 @@ private:
/// Adds a new property to the mesh.
void addProperty(QString propName, QString friendlyTypeName, PropertyInfo::ENTITY_FILTER filter);
void initializeSupportedPropertyTypes();
public:
static const TypeInfoWrapper proptype_bool;
static const TypeInfoWrapper proptype_int;
static const TypeInfoWrapper proptype_uint;
static const TypeInfoWrapper proptype_double;
static const TypeInfoWrapper proptype_Vec3d;
static const TypeInfoWrapper proptype_Vec3f;
static const TypeInfoWrapper proptype_Vec2d;
static const TypeInfoWrapper proptype_Vec2f;
#ifdef ENABLE_SKELETON_SUPPORT
static const TypeInfoWrapper proptype_SkinWeights;
#endif
private:
MeshT* mesh_;
......@@ -180,24 +193,35 @@ private:
std::string lastPickMode;
Viewer::ActionMode lastActionMode;
TypeInfoWrapper proptype_bool;
TypeInfoWrapper proptype_int;
TypeInfoWrapper proptype_uint;
TypeInfoWrapper proptype_double;
TypeInfoWrapper proptype_Vec3d;
TypeInfoWrapper proptype_Vec3f;
TypeInfoWrapper proptype_Vec2d;
TypeInfoWrapper proptype_Vec2f;
#ifdef ENABLE_SKELETON_SUPPORT
TypeInfoWrapper proptype_SkinWeights;
#endif
typedef std::set<TypeInfoWrapper> TypeInfoWrapperSet;
TypeInfoWrapperSet supportedPropertyTypes;
};
template <typename T> const TypeInfoWrapper OMPropertyModel<T>::proptype_bool
= TypeInfoWrapper(typeid(OpenMesh::PropertyT<bool>), "bool");
template <typename T> const TypeInfoWrapper OMPropertyModel<T>::proptype_int
= TypeInfoWrapper(typeid(OpenMesh::PropertyT<int>), "int");
template <typename T> const TypeInfoWrapper OMPropertyModel<T>::proptype_uint
= TypeInfoWrapper(typeid(OpenMesh::PropertyT<unsigned int>), "unsigned int");
template <typename T> const TypeInfoWrapper OMPropertyModel<T>::proptype_double
= TypeInfoWrapper(typeid(OpenMesh::PropertyT<double>), "double");
template <typename T> const TypeInfoWrapper OMPropertyModel<T>::proptype_Vec3d
= TypeInfoWrapper(typeid(OpenMesh::PropertyT<ACG::Vec3d>), "Vec3d");
template <typename T> const TypeInfoWrapper OMPropertyModel<T>::proptype_Vec3f
= TypeInfoWrapper(typeid(OpenMesh::PropertyT<ACG::Vec3f>), "Vec3f");
template <typename T> const TypeInfoWrapper OMPropertyModel<T>::proptype_Vec2d
= TypeInfoWrapper(typeid(OpenMesh::PropertyT<ACG::Vec2d>), "Vec2d");
template <typename T> const TypeInfoWrapper OMPropertyModel<T>::proptype_Vec2f
= TypeInfoWrapper(typeid(OpenMesh::PropertyT<ACG::Vec2f>), "Vec2f");
#ifdef ENABLE_SKELETON_SUPPORT
template <typename T> const TypeInfoWrapper OMPropertyModel<T>::proptype_SkinWeights
= TypeInfoWrapper(typeid(OpenMesh::PropertyT<BaseSkin::SkinWeights>), "SkinWeights");
#endif
#if defined(INCLUDE_TEMPLATES) && !defined(OM_PROPERTY_MODEL_CC)
#include "OMPropertyModelT.cc"
#endif
......
......@@ -75,18 +75,7 @@ OMPropertyModel<MeshT>::OMPropertyModel(MeshT* mesh, int objectID, QObject *pare
objectID_(objectID),
mCombineProperty1(0),
mCombineProperty2(0),
pickModeActive(false),
proptype_bool(TypeInfoWrapper(typeid(OpenMesh::PropertyT<bool>), "bool")),
proptype_int(TypeInfoWrapper(typeid(OpenMesh::PropertyT<int>), "int")),
proptype_uint(TypeInfoWrapper(typeid(OpenMesh::PropertyT<unsigned int>), "unsigned int")),
proptype_double(TypeInfoWrapper(typeid(OpenMesh::PropertyT<double>), "double")),
proptype_Vec3d(TypeInfoWrapper(typeid(OpenMesh::PropertyT<ACG::Vec3d>), "Vec3d")),
proptype_Vec3f(TypeInfoWrapper(typeid(OpenMesh::PropertyT<ACG::Vec3f>), "Vec3f")),
proptype_Vec2d(TypeInfoWrapper(typeid(OpenMesh::PropertyT<ACG::Vec2d>), "Vec2d")),
proptype_Vec2f(TypeInfoWrapper(typeid(OpenMesh::PropertyT<ACG::Vec2f>), "Vec2f"))
#ifdef ENABLE_SKELETON_SUPPORT
,proptype_SkinWeights(TypeInfoWrapper(typeid(OpenMesh::PropertyT<BaseSkin::SkinWeights>), "SkinWeights"))
#endif
pickModeActive(false)
{
gatherProperties();
bCombine.setText(tr("Combine"));
......@@ -112,7 +101,7 @@ OMPropertyModel<MeshT>::OMPropertyModel(MeshT* mesh, int objectID, QObject *pare
lastPickMode = PluginFunctions::pickMode();
lastActionMode = PluginFunctions::actionMode();
initializeSupportedPropertyTypes();
}
......@@ -120,7 +109,7 @@ OMPropertyModel<MeshT>::OMPropertyModel(MeshT* mesh, int objectID, QObject *pare
template<typename MeshT>
void OMPropertyModel<MeshT>::updateWidget(const QModelIndexList& selectedIndices)
{
PropertyModel::updateWidget(selectedIndices);
SingleObjectPropertyModel::updateWidget(selectedIndices);
if (selectedIndices.size() == 2)
{
......@@ -227,7 +216,7 @@ void OMPropertyModel<MeshT>::saveProperty()
{
for (QModelIndexList::const_iterator it = currentlySelectedIndices.begin(), it_end = currentlySelectedIndices.end();
it != it_end; ++it) {
PropertyModel::saveProperty(it->row());
SingleObjectPropertyModel::saveProperty(it->row());
}
}
......@@ -333,7 +322,7 @@ void OMPropertyModel<MeshT>::setPropertyFromFile(QTextStream*& file_stream_, uns
else
#endif
{
PropertyModel::setPropertyFromFile(file_stream_, n, propVis);
SingleObjectPropertyModel::setPropertyFromFile(file_stream_, n, propVis);
}
}
......@@ -750,8 +739,8 @@ void OMPropertyModel<MeshT>:: addProperty(QString propName, QString friendlyType
template<typename MeshT>
void OMPropertyModel<MeshT>::initializeSupportedPropertyTypes()
{