Add bone list model

master
Jeremy HU 2022-11-11 08:37:05 +11:00
parent eba729d785
commit 5c9898f25b
5 changed files with 147 additions and 0 deletions

View File

@ -95,6 +95,8 @@ include(third_party/QtAwesome/QtAwesome/QtAwesome.pri)
HEADERS += sources/about_widget.h
SOURCES += sources/about_widget.cc
HEADERS += sources/bone_list_model.h
SOURCES += sources/bone_list_model.cc
HEADERS += sources/ccd_ik_resolver.h
SOURCES += sources/ccd_ik_resolver.cc
HEADERS += sources/component_list_model.h

View File

@ -0,0 +1,103 @@
#include "bone_list_model.h"
#include <QAbstractListModel>
#include <dust3d/base/debug.h>
BoneListModel::BoneListModel(const Document* document, QObject* parent)
: QAbstractListModel(parent)
, m_document(document)
{
connect(m_document, &Document::bonePreviewPixmapChanged, [this](const dust3d::Uuid& boneId) {
auto findIndex = this->m_boneIdToIndexMap.find(boneId);
if (findIndex != this->m_boneIdToIndexMap.end()) {
emit this->dataChanged(findIndex->second, findIndex->second);
}
});
connect(m_document, &Document::cleanup, this, &BoneListModel::reload);
connect(m_document, &Document::boneIdListChanged, this, &BoneListModel::reload);
}
void BoneListModel::reload()
{
beginResetModel();
m_boneIdToIndexMap.clear();
for (int i = 0; i < (int)m_document->boneIdList.size(); ++i) {
m_boneIdToIndexMap[m_document->boneIdList[i]] = createIndex(i, 0);
}
endResetModel();
emit layoutChanged();
}
QModelIndex BoneListModel::boneIdToIndex(const dust3d::Uuid& boneId) const
{
auto findIndex = m_boneIdToIndexMap.find(boneId);
if (findIndex == m_boneIdToIndexMap.end())
return QModelIndex();
return findIndex->second;
}
int BoneListModel::rowCount(const QModelIndex& parent) const
{
if (parent.isValid())
return 0;
return (int)m_document->boneIdList.size();
}
int BoneListModel::columnCount(const QModelIndex& parent) const
{
if (parent.isValid())
return 0;
return 1;
}
const Document::Bone* BoneListModel::modelIndexToBone(const QModelIndex& index) const
{
if (index.row() >= (int)m_document->boneIdList.size()) {
dust3dDebug << "Bone list row is out of range, size:" << m_document->boneIdList.size() << "row:" << index.row();
return nullptr;
}
const auto& boneId = m_document->boneIdList[index.row()];
const Document::Bone* bone = m_document->findBone(boneId);
if (nullptr == bone) {
dust3dDebug << "Bone not found:" << boneId.toString();
return nullptr;
}
return bone;
}
const dust3d::Uuid BoneListModel::modelIndexToBoneId(const QModelIndex& index) const
{
if (index.row() >= (int)m_document->boneIdList.size()) {
dust3dDebug << "Bone list row is out of range, size:" << m_document->boneIdList.size() << "row:" << index.row();
return dust3d::Uuid();
}
const auto& boneId = m_document->boneIdList[index.row()];
return boneId;
}
QVariant BoneListModel::data(const QModelIndex& index, int role) const
{
switch (role) {
case Qt::ToolTipRole: {
const Document::Bone* bone = modelIndexToBone(index);
if (nullptr != bone) {
return bone->name;
}
} break;
case Qt::DecorationRole: {
const Document::Bone* bone = modelIndexToBone(index);
if (nullptr != bone) {
if (0 == bone->previewPixmap.width()) {
static QPixmap s_emptyPixmap;
if (0 == s_emptyPixmap.width()) {
QImage image((int)Theme::partPreviewImageSize, (int)Theme::partPreviewImageSize, QImage::Format_ARGB32);
image.fill(Qt::transparent);
s_emptyPixmap = QPixmap::fromImage(image);
}
return s_emptyPixmap;
}
return bone->previewPixmap;
}
} break;
}
return QVariant();
}

View File

@ -0,0 +1,28 @@
#ifndef DUST3D_APPLICATION_BONE_LIST_MODEL_H_
#define DUST3D_APPLICATION_BONE_LIST_MODEL_H_
#include "document.h"
#include <QAbstractListModel>
#include <dust3d/base/uuid.h>
#include <unordered_map>
class BoneListModel : public QAbstractListModel {
Q_OBJECT
public:
BoneListModel(const Document* document, QObject* parent = nullptr);
int rowCount(const QModelIndex& parent = QModelIndex()) const;
int columnCount(const QModelIndex& parent = QModelIndex()) const;
QVariant data(const QModelIndex& index, int role) const;
const Document::Bone* modelIndexToBone(const QModelIndex& index) const;
QModelIndex boneIdToIndex(const dust3d::Uuid& boneId) const;
const dust3d::Uuid modelIndexToBoneId(const QModelIndex& index) const;
public slots:
void reload();
private:
const Document* m_document = nullptr;
std::unordered_map<dust3d::Uuid, QModelIndex> m_boneIdToIndexMap;
};
#endif

View File

@ -2855,6 +2855,7 @@ void Document::addBone(const dust3d::Uuid& boneId)
boneMap.emplace(boneId, bone);
boneIdList.push_back(boneId);
emit boneAdded(boneId);
emit boneIdListChanged();
emit rigChanged();
}
@ -2893,6 +2894,7 @@ void Document::removeBone(const dust3d::Uuid& boneId)
boneIdList.erase(std::remove(boneIdList.begin(), boneIdList.end(), boneId), boneIdList.end());
boneMap.erase(boneId);
emit boneRemoved(boneId);
emit boneIdListChanged();
emit rigChanged();
}
@ -2920,3 +2922,11 @@ void Document::renameBone(const dust3d::Uuid& boneId, const QString& name)
emit boneNameChanged(boneId);
emit rigChanged();
}
const Document::Bone* Document::findBone(const dust3d::Uuid& boneId) const
{
auto boneIt = boneMap.find(boneId);
if (boneIt == boneMap.end())
return nullptr;
return &boneIt->second;
}

View File

@ -564,6 +564,7 @@ public:
dust3d::Uuid attachBoneId;
int attachBoneJointIndex = 0;
QString name;
QPixmap previewPixmap;
Bone(const dust3d::Uuid& withId = dust3d::Uuid());
};
@ -643,6 +644,8 @@ signals:
void boneAttachmentChanged(const dust3d::Uuid& boneId);
void boneNodesChanged(const dust3d::Uuid& boneId);
void boneNameChanged(const dust3d::Uuid& boneId);
void bonePreviewPixmapChanged(const dust3d::Uuid& boneId);
void boneIdListChanged();
void rigChanged();
public: // need initialize
@ -769,6 +772,7 @@ public:
void setComponentPreviewImage(const dust3d::Uuid& componentId, std::unique_ptr<QImage> image);
void resetDirtyFlags();
void markAllDirty();
const Bone* findBone(const dust3d::Uuid& boneId) const;
public slots:
void undo();