Commit 4fc50d11 authored by Jan Möbius's avatar Jan Möbius
Browse files

git-svn-id: http://www.openflipper.org/svnrepo/OpenFlipper/branches/Free@14034 383ad7c9-94d9-4d36-a494-682f7c89f535
parents
include (plugin)
openflipper_plugin ()
/*
* ObjectListItemModel.cc
*
* Created on: Feb 29, 2012
* Author: ebke
*/
#include "ObjectListItemModel.hh"
#include <algorithm>
#include <OpenFlipper/BasePlugin/PluginFunctions.hh>
ObjectListItemModel::ObjectListItemModel() {
}
ObjectListItemModel::~ObjectListItemModel() {
}
int ObjectListItemModel::rowCount(const QModelIndex & parent) const {
return objects_.size() + 1;
}
QVariant ObjectListItemModel::data(const QModelIndex & index, int role) const {
switch (role) {
case Qt::DisplayRole:
if (index.row() <= 0) return tr("<none>");
return objects_[index.row() - 1].getName();
case Qt::UserRole:
if (index.row() <= 0) return QVariant::fromValue<int>(-1);
return QVariant::fromValue(objects_[index.row() - 1].getId());
default:
return QVariant::Invalid;
}
}
void ObjectListItemModel::refresh(const DataType &datatype) {
std::vector<ObjectInfo> objects;
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()));
}
std::sort(objects.begin(), objects.end());
if (objects != objects_) {
beginResetModel();
objects.swap(objects_);
endResetModel();
}
}
/*
* ObjectListItemModel.hh
*
* Created on: Feb 29, 2012
* Author: ebke
*/
#ifndef OBJECTLISTITEMMODEL_HH_
#define OBJECTLISTITEMMODEL_HH_
#include <QAbstractItemModel>
#include <OpenFlipper/common/DataTypes.hh>
class ObjectListItemModel: public QAbstractListModel {
public:
ObjectListItemModel();
virtual ~ObjectListItemModel();
virtual int rowCount(const QModelIndex & parent = QModelIndex()) const;
virtual QVariant data(const QModelIndex & index, int role = Qt::DisplayRole) const;
void refresh(const DataType &datatype);
protected:
class ObjectInfo {
public:
ObjectInfo(const QString &name, const int id) : name(name), id(id) {}
bool operator<(const ObjectInfo &rhs) const {
const int nameCmp = name.compare(rhs.name);
if (!nameCmp) return id < rhs.id;
return nameCmp < 0;
}
bool operator==(const ObjectInfo &rhs) const {
return id == rhs.id && name == rhs.name;
}
const QString &getName() const { return name; }
int getId() const { return id; }
private:
QString name;
int id;
};
std::vector<ObjectInfo> objects_;
};
#endif /* OBJECTLISTITEMMODEL_HH_ */
################################################################################
#
################################################################################
include( $$TOPDIR/qmake/all.include )
Plugin()
#qwt()
#gmm()
#lapack()
#physim2()
#cgal()
DIRECTORIES = .
# Input
HEADERS += $$getFilesFromDir($$DIRECTORIES,*.hh)
SOURCES += $$getFilesFromDir($$DIRECTORIES,*.cc)
FORMS += $$getFilesFromDir($$DIRECTORIES,*.ui)
################################################################################
/*
* PropertyNameListModel.cc
*
* Created on: Feb 29, 2012
* Author: ebke
*/
#include "PropertyNameListModel.hh"
#include <OpenMesh/Core/Utils/Property.hh>
#include <ACG/Math/VectorT.hh>
#include <ObjectTypes/Skeleton/BaseSkin.hh>
#include <map>
#include <vector>
const PropertyNameListModel::TypeInfoWrapper PropertyNameListModel::proptype_bool =
PropertyNameListModel::TypeInfoWrapper(typeid(OpenMesh::PropertyT<bool>), "bool");
const PropertyNameListModel::TypeInfoWrapper PropertyNameListModel::proptype_int =
PropertyNameListModel::TypeInfoWrapper(typeid(OpenMesh::PropertyT<int>), "int");
const PropertyNameListModel::TypeInfoWrapper PropertyNameListModel::proptype_uint =
PropertyNameListModel::TypeInfoWrapper(typeid(OpenMesh::PropertyT<unsigned int>), "unsigned int");
const PropertyNameListModel::TypeInfoWrapper PropertyNameListModel::proptype_double =
PropertyNameListModel::TypeInfoWrapper(typeid(OpenMesh::PropertyT<double>), "double");
const PropertyNameListModel::TypeInfoWrapper PropertyNameListModel::proptype_Vec3d =
PropertyNameListModel::TypeInfoWrapper(typeid(OpenMesh::PropertyT<ACG::Vec3d>), "Vec3d");
const PropertyNameListModel::TypeInfoWrapper PropertyNameListModel::proptype_Vec3f =
PropertyNameListModel::TypeInfoWrapper(typeid(OpenMesh::PropertyT<ACG::Vec3f>), "Vec3f");
const PropertyNameListModel::TypeInfoWrapper PropertyNameListModel::proptype_SkinWeights =
PropertyNameListModel::TypeInfoWrapper(typeid(OpenMesh::PropertyT<BaseSkin::SkinWeights>), "SkinWeights");
/*
* I'd love to do this with boost::assign but I'm not allowed to. :-(
*/
const PropertyNameListModel::TypeInfoWrapper PropertyNameListModel::prop_types[] = {
proptype_bool,
proptype_int,
proptype_uint,
proptype_double,
proptype_Vec3d,
proptype_Vec3f,
proptype_SkinWeights,
};
const PropertyNameListModel::TYPE_INFO_SET PropertyNameListModel::sane_prop_types(prop_types, prop_types + 7);
const char *PropertyNameListModel::entity2str(ENTITY_FILTER entity) {
switch (entity) {
case EF_EDGE:
return "→";
case EF_FACE:
return "△";
case EF_HALFEDGE:
return "⇀";
case EF_VERTEX:
return "•";
default:
return "error";
}
}
PropertyNameListModel::PropertyNameListModel(QObject *parent) :
QAbstractListModel(parent) {
}
PropertyNameListModel::~PropertyNameListModel() {
}
int PropertyNameListModel::rowCount(const QModelIndex & parent) const {
return propList_.size();
}
QVariant PropertyNameListModel::data(const QModelIndex & index, int role) const {
switch (role) {
case Qt::DisplayRole:
return propList_[index.row()].toString();
default:
return QVariant::Invalid;
}
}
QVariant PropertyNameListModel::headerData(int section, Qt::Orientation orientation, int role) const {
switch (role) {
case Qt::DisplayRole:
return tr("Some header. %1 %2").arg(section).arg(orientation);
break;
default:
return QAbstractListModel::headerData(section, orientation, role);
}
}
namespace {
class InsDel {
public:
enum OP { INS, DEL };
InsDel(OP op, int first, int count, int before) : op(op), first(first), count(count), before(before) {}
OP op;
int first, count, before;
};
}
bool PropertyNameListModel::tryInsertionsDeletions(std::vector<PROP_INFO> &propList) {
std::vector<InsDel> result;
typedef std::vector<PROP_INFO>::iterator IT;
int correction = 0;
IT oldIt, newIt;
for (oldIt = propList_.begin(), newIt = propList.begin(); oldIt < propList_.end() && newIt < propList.end(); ++oldIt, ++newIt) {
if (*oldIt == *newIt) continue;
const IT nextNew = std::find(newIt+1, propList.end(), *oldIt);
if (nextNew != propList.end()) {
const int count = std::distance(newIt, nextNew);
result.push_back(InsDel(InsDel::INS, std::distance(propList.begin(), newIt), count, std::distance(propList_.begin(), oldIt) + correction));
correction += count;
newIt += count;
continue;
}
const IT nextOld = std::find(oldIt+1, propList_.end(), *newIt);
if (nextOld != propList_.end()) {
const int count = std::distance(oldIt, nextOld);
result.push_back(InsDel(InsDel::DEL, std::distance(propList_.begin(), oldIt) + correction, count, 0));
correction -= count;
oldIt += count;
continue;
}
return false;
}
if (oldIt < propList_.end() && newIt < propList.end()) {
return false;
}
if (oldIt < propList_.end())
result.push_back(InsDel(InsDel::DEL, std::distance(propList_.begin(), oldIt) + correction, std::distance(oldIt, propList_.end()), 0));
if (newIt < propList.end())
result.push_back(InsDel(InsDel::INS, std::distance(propList.begin(), newIt), std::distance(newIt, propList.end()), propList_.size() + correction));
for (std::vector<InsDel>::iterator it = result.begin(); it != result.end(); ++it) {
if (it->op == InsDel::INS) {
beginInsertRows(QModelIndex(), it->before, it->before + it->count - 1);
propList_.insert(propList_.begin() + it->before, propList.begin() + it->first, propList.begin() + it->first + it->count);
endInsertRows();
} else {
beginRemoveRows(QModelIndex(), it->first, it->first + it->count - 1);
propList_.erase(propList_.begin() + it->first, propList_.begin() + it->first + it->count);
endRemoveRows();
}
}
if (propList_ != propList) {
std::cerr << "Apparently, the function PropertyNameListModel::tryInsertionsDeletions() has an implementation error." << std::endl;
throw std::logic_error("Apparently, the function PropertyNameListModel::tryInsertionsDeletions() has an implementation error.");
}
return true;
}
/*
* PropertyNameListModel.hh
*
* Created on: Feb 29, 2012
* Author: ebke
*/
#ifndef PROPERTYNAMELISTMODEL_HH_
#define PROPERTYNAMELISTMODEL_HH_
#include <OpenMesh/Core/Utils/BaseProperty.hh>
#include <QAbstractListModel>
#include <set>
#include <vector>
#include <algorithm>
class PropertyNameListModel: public QAbstractListModel {
public:
enum ENTITY_FILTER {
EF_ANY = 0x0F,
EF_FACE = 0x01,
EF_EDGE = 0x02,
EF_HALFEDGE = 0x04,
EF_VERTEX = 0x08,
};
static const char *entity2str(ENTITY_FILTER entity);
class TypeInfoWrapper {
public:
TypeInfoWrapper(const std::type_info & ti, const char *friendlyName) : ti(&ti), friendlyName(friendlyName) {}
TypeInfoWrapper(const std::type_info & ti) : ti(&ti) {}
operator const std::type_info *() const { return ti; }
operator const std::type_info &() const { return *ti; }
operator const char *() const { return friendlyName; }
const std::type_info *operator->() const { return ti; }
const std::type_info &get() const { return *ti; }
const char *getName() const { return friendlyName; }
bool operator==(const TypeInfoWrapper & other) const {
/*
* We compare name strings, not the type ids themselves because
* the same type from different SOs will give different type ids.
*/
return strcmp(ti->name(), other.ti->name()) == 0;
}
bool operator<(const TypeInfoWrapper & other) const {
return strcmp(ti->name(), other.ti->name()) < 0;
}
private:
const std::type_info *ti;
const char *friendlyName;
};
class PROP_INFO {
public:
PROP_INFO(const std::string &propName, const TypeInfoWrapper &typeinfo, ENTITY_FILTER entity) :
propName_(propName), typeinfo_(typeinfo), entity(entity) {}
QString toString() const {
return tr("%3 %1 : %2").arg(propName_.c_str()).arg(friendlyTypeName()).arg(QString::fromUtf8(entity2str(entity)));
}
bool operator==(const PROP_INFO &rhs) const {
return propName_ == rhs.propName_ && typeinfo_ == rhs.typeinfo_ && entity == rhs.entity;
}
bool operator<(const PROP_INFO &rhs) const {
if (entity != rhs.entity) return entity < rhs.entity;
int result = propName_.compare(rhs.propName_);
if (result) return result < 0;
return typeinfo_ < rhs.typeinfo_;
}
inline bool isFaceProp() const { return entity == EF_FACE; }
inline bool isEdgeProp() const { return entity == EF_EDGE; }
inline bool isHalfedgeProp() const { return entity == EF_HALFEDGE; }
inline bool isVertexProp() const { return entity == EF_VERTEX; }
inline const std::string &propName() const { return propName_; }
inline const char *friendlyTypeName() const { return typeinfo_.getName(); }
inline const TypeInfoWrapper &typeinfo() const { return typeinfo_; }
inline ENTITY_FILTER entityType() const { return entity; }
private:
std::string propName_;
TypeInfoWrapper typeinfo_;
ENTITY_FILTER entity;
};
public:
PropertyNameListModel(QObject *parent = 0);
virtual ~PropertyNameListModel();
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;
/**
* @param typeIdFilter If NULL, do not filter by type.
*/
template<typename MeshT>
void refresh(MeshT *mesh, ENTITY_FILTER entityFilterMask, std::type_info *typeIdFilter) {
std::vector<PROP_INFO> propList;
if (mesh) {
if (entityFilterMask & EF_FACE)
gatherProperties(mesh, mesh->fprops_begin(), mesh->fprops_end(), typeIdFilter, std::back_inserter(propList), EF_FACE);
if (entityFilterMask & EF_EDGE)
gatherProperties(mesh, mesh->eprops_begin(), mesh->eprops_end(), typeIdFilter, std::back_inserter(propList), EF_EDGE);
if (entityFilterMask & EF_HALFEDGE)
gatherProperties(mesh, mesh->hprops_begin(), mesh->hprops_end(), typeIdFilter, std::back_inserter(propList), EF_HALFEDGE);
if (entityFilterMask & EF_VERTEX)
gatherProperties(mesh, mesh->vprops_begin(), mesh->vprops_end(), typeIdFilter, std::back_inserter(propList), EF_VERTEX);
}
std::sort(propList.begin(), propList.end());
if (propList != propList_) {
if (!tryInsertionsDeletions(propList)) {
beginResetModel();
propList_.swap(propList);
endResetModel();
}
}
}
/** Implements an unsophisticated heuristic to translate the difference
* between propList and propList_ into a series of insertions and deletions.
*
* @return True if such a sequence was found, false otherwise.
*/
bool tryInsertionsDeletions(std::vector<PROP_INFO> &propList);
template<typename MeshT, typename OUTPUT_ITERATOR>
void gatherProperties(MeshT *mesh,
typename MeshT::prop_iterator props_first,
typename MeshT::prop_iterator props_last,
std::type_info *typeIdFilter, OUTPUT_ITERATOR oit,
ENTITY_FILTER entity) {
for (typename MeshT::prop_iterator pit = props_first; pit != props_last; ++pit) {
OpenMesh::BaseProperty * const baseProp = *pit;
if (!baseProp) continue;
TypeInfoWrapper bp_type = typeid(*baseProp);
TYPE_INFO_SET::const_iterator sane_prop_it = sane_prop_types.find(bp_type);
if ((typeIdFilter == 0 || TypeInfoWrapper(*typeIdFilter) == bp_type) && sane_prop_it != sane_prop_types.end()) {
*oit++ = PROP_INFO(baseProp->name(), *sane_prop_it, entity);
}
}
}
const PROP_INFO &operator[] (size_t index) {
return propList_[index];
}
protected:
std::vector<PROP_INFO> propList_;
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_SkinWeights;
private:
typedef std::set<TypeInfoWrapper> TYPE_INFO_SET;
static const TypeInfoWrapper prop_types[];
static const TYPE_INFO_SET sane_prop_types;
};
#endif /* PROPERTYNAMELISTMODEL_HH_ */
//=============================================================================
//
// CLASS PropertyVisPlugin - IMPLEMENTATION
//
//=============================================================================
//== INCLUDES =================================================================
#include <Qt>
#include <QtGui>
#include <QSpacerItem>
#include <QFileDialog>
#include "PropertyVisPlugin.hh"
#include <iostream>
#include <vector>
#include <algorithm>
#include <cmath>
#include "OpenFlipper/INIFile/INIFile.hh"
#include <OpenFlipper/BasePlugin/PluginFunctions.hh>
#include <ACG/Utils/ColorCoder.hh>
//== IMPLEMENTATION ==========================================================
#define PROP_VIS "PropertyVisualization"
PropertyVisPlugin::PropertyVisPlugin() :
pickModeActive_(false),
lastPickMode_(""),
tool_(0),
file_stream_(0)
{
}
void PropertyVisPlugin::initializePlugin()
{
tool_ = new PropertyVisToolbar();
QSize size(300,300);
tool_->resize(size);
// connect toolbox elements
connect(tool_->meshNames, SIGNAL( currentIndexChanged(int) ), this, SLOT( slotMeshChanged(int) ) );
connect(tool_->visualizeButton, SIGNAL( clicked() ), this, SLOT( slotVisualize() ) );
connect(tool_->clearButton, SIGNAL( clicked() ), this, SLOT( slotAllCleared() ) );
connect(tool_->createNewButton, SIGNAL( clicked() ), this, SLOT( slotCreateProperty() ) );
connect(tool_->load_property, SIGNAL( clicked() ), this, SLOT( loadSelectedProperty() ) );
connect(tool_->save_property, SIGNAL( clicked() ), this, SLOT( saveSelectedProperty() ) );
connect(tool_->refresh_property_names_tb, SIGNAL( clicked() ), this, SLOT( slotMeshChanged() ) );
connect(tool_->duplicate_property_tb, SIGNAL( clicked() ), this, SLOT( slotDuplicateProperty() ) );
connect(tool_->remove_property_tb, SIGNAL( clicked() ), this, SLOT( slotRemoveProperty() ) );
connect(tool_, SIGNAL( widgetShown() ), this, SLOT( updateGUI() ) );
tool_->propertyName_lv->setModel(&propertyNameListModel_);
connect(tool_->propertyName_lv->selectionModel(),
SIGNAL( selectionChanged(const QItemSelection &, const QItemSelection &) ),
this,
SLOT( propertySelectionChanged() ));
connect(&propertyNameListModel_, SIGNAL( modelReset() ), this, SLOT( propertySelectionChanged() ));
tool_->meshNames->setModel(&objectListItemModel_);
emit addHiddenPickMode( PROP_VIS );
pickModeActive_ = false;
connect(tool_->pickButton, SIGNAL( clicked() ), this, SLOT( pickValue() ) );
QString iconPath = OpenFlipper::Options::iconDirStr() + OpenFlipper::Options::dirSeparator();
tool_->pickButton->setIcon( QIcon(iconPath + "color-picker.png") );
emit addToolbox( tr("Property Visualization") , tool_ );
}
//-----------------------------------------------------------------------------
void PropertyVisPlugin::pluginsInitialized()
{
propertySelectionChanged();
}
//-----------------------------------------------------------------------------
void PropertyVisPlugin::slotPickModeChanged( const std::string& _mode)
{
pickModeActive_ = (_mode == PROP_VIS);
tool_->pickButton->setChecked(pickModeActive_);
}
//-----------------------------------------------------------------------------
void PropertyVisPlugin::pickValue()
{
if ( tool_->pickButton->isChecked() ){
lastPickMode_ = PluginFunctions::pickMode();
lastActionMode_ = PluginFunctions::actionMode();
PluginFunctions::pickMode(PROP_VIS);
PluginFunctions::actionMode(Viewer::PickingMode);
} else {
PluginFunctions::pickMode(lastPickMode_);
PluginFunctions::actionMode(lastActionMode_);
}
}
//-----------------------------------------------------------------------------
void PropertyVisPlugin::slotAllCleared()
{
for(unsigned int i=0; i<lineNodes_.size(); ++i)
delete lineNodes_[i];
lineNodes_.clear();
emit updateView();
}