Implement bone name edit and keep bone load order
parent
797ffd0b87
commit
5b6861be44
|
@ -4,6 +4,7 @@
|
||||||
#include "theme.h"
|
#include "theme.h"
|
||||||
#include <QGroupBox>
|
#include <QGroupBox>
|
||||||
#include <QHBoxLayout>
|
#include <QHBoxLayout>
|
||||||
|
#include <QLineEdit>
|
||||||
#include <QPushButton>
|
#include <QPushButton>
|
||||||
#include <QVBoxLayout>
|
#include <QVBoxLayout>
|
||||||
#include <unordered_set>
|
#include <unordered_set>
|
||||||
|
@ -19,8 +20,25 @@ BonePropertyWidget::BonePropertyWidget(Document* document,
|
||||||
|
|
||||||
QVBoxLayout* mainLayout = new QVBoxLayout;
|
QVBoxLayout* mainLayout = new QVBoxLayout;
|
||||||
|
|
||||||
|
if (nullptr != m_bone) {
|
||||||
|
m_nameEdit = new QLineEdit;
|
||||||
|
Theme::initLineEdit(m_nameEdit);
|
||||||
|
m_nameEdit->setFixedWidth(Theme::partPreviewImageSize * 2.7);
|
||||||
|
m_nameEdit->setText(m_bone->name);
|
||||||
|
|
||||||
|
connect(m_nameEdit, &QLineEdit::textChanged, this, &BonePropertyWidget::nameEditChanged);
|
||||||
|
|
||||||
|
QHBoxLayout* renameLayout = new QHBoxLayout;
|
||||||
|
renameLayout->addWidget(new QLabel(tr("Name")));
|
||||||
|
renameLayout->addWidget(m_nameEdit);
|
||||||
|
renameLayout->addStretch();
|
||||||
|
|
||||||
|
mainLayout->addLayout(renameLayout);
|
||||||
|
}
|
||||||
|
|
||||||
mainLayout->setSizeConstraint(QLayout::SetFixedSize);
|
mainLayout->setSizeConstraint(QLayout::SetFixedSize);
|
||||||
|
|
||||||
|
connect(this, &BonePropertyWidget::renameBone, m_document, &Document::renameBone);
|
||||||
connect(this, &BonePropertyWidget::groupOperationAdded, m_document, &Document::saveSnapshot);
|
connect(this, &BonePropertyWidget::groupOperationAdded, m_document, &Document::saveSnapshot);
|
||||||
|
|
||||||
setLayout(mainLayout);
|
setLayout(mainLayout);
|
||||||
|
@ -36,3 +54,12 @@ void BonePropertyWidget::prepareBoneIds()
|
||||||
m_boneId = m_boneIds.front();
|
m_boneId = m_boneIds.front();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void BonePropertyWidget::nameEditChanged()
|
||||||
|
{
|
||||||
|
const Document::Bone* bone = m_document->findBone(m_boneId);
|
||||||
|
if (nullptr == bone)
|
||||||
|
return;
|
||||||
|
emit renameBone(m_boneId, m_nameEdit->text());
|
||||||
|
emit groupOperationAdded();
|
||||||
|
}
|
||||||
|
|
|
@ -5,22 +5,27 @@
|
||||||
#include <QWidget>
|
#include <QWidget>
|
||||||
#include <dust3d/base/uuid.h>
|
#include <dust3d/base/uuid.h>
|
||||||
|
|
||||||
|
class QLineEdit;
|
||||||
|
|
||||||
class BonePropertyWidget : public QWidget {
|
class BonePropertyWidget : public QWidget {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
signals:
|
signals:
|
||||||
|
void renameBone(const dust3d::Uuid& boneId, const QString& name);
|
||||||
void groupOperationAdded();
|
void groupOperationAdded();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
BonePropertyWidget(Document* document,
|
BonePropertyWidget(Document* document,
|
||||||
const std::vector<dust3d::Uuid>& boneIds,
|
const std::vector<dust3d::Uuid>& boneIds,
|
||||||
QWidget* parent = nullptr);
|
QWidget* parent = nullptr);
|
||||||
public slots:
|
private slots:
|
||||||
|
void nameEditChanged();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Document* m_document = nullptr;
|
Document* m_document = nullptr;
|
||||||
std::vector<dust3d::Uuid> m_boneIds;
|
std::vector<dust3d::Uuid> m_boneIds;
|
||||||
dust3d::Uuid m_boneId;
|
dust3d::Uuid m_boneId;
|
||||||
const Document::Bone* m_bone = nullptr;
|
const Document::Bone* m_bone = nullptr;
|
||||||
|
QLineEdit* m_nameEdit = nullptr;
|
||||||
void prepareBoneIds();
|
void prepareBoneIds();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1876,9 +1876,11 @@ void Document::addFromSnapshot(const dust3d::Snapshot& snapshot, enum SnapshotSo
|
||||||
bone.name = dust3d::String::valueOrEmpty(boneKv.second, "name").c_str();
|
bone.name = dust3d::String::valueOrEmpty(boneKv.second, "name").c_str();
|
||||||
bone.attachBoneJointIndex = dust3d::String::toInt(dust3d::String::valueOrEmpty(boneKv.second, "attachBoneJointIndex"));
|
bone.attachBoneJointIndex = dust3d::String::toInt(dust3d::String::valueOrEmpty(boneKv.second, "attachBoneJointIndex"));
|
||||||
boneMap.emplace(boneId, std::move(bone));
|
boneMap.emplace(boneId, std::move(bone));
|
||||||
boneIdList.push_back(boneId);
|
|
||||||
newAddedBoneIds.insert(boneId);
|
newAddedBoneIds.insert(boneId);
|
||||||
}
|
}
|
||||||
|
for (const auto& boneIdString : snapshot.boneIdList) {
|
||||||
|
boneIdList.push_back(oldNewIdMap[dust3d::Uuid(boneIdString)]);
|
||||||
|
}
|
||||||
for (const auto& boneKv : snapshot.bones) {
|
for (const auto& boneKv : snapshot.bones) {
|
||||||
auto attachBoneId = dust3d::Uuid(dust3d::String::valueOrEmpty(boneKv.second, "attachBoneId"));
|
auto attachBoneId = dust3d::Uuid(dust3d::String::valueOrEmpty(boneKv.second, "attachBoneId"));
|
||||||
if (!attachBoneId.isNull()) {
|
if (!attachBoneId.isNull()) {
|
||||||
|
|
|
@ -571,6 +571,9 @@ DocumentWindow::DocumentWindow()
|
||||||
connect(canvasGraphicsWidget, &SkeletonGraphicsWidget::setPartRoundState, m_document, &Document::setPartRoundState);
|
connect(canvasGraphicsWidget, &SkeletonGraphicsWidget::setPartRoundState, m_document, &Document::setPartRoundState);
|
||||||
connect(canvasGraphicsWidget, &SkeletonGraphicsWidget::setPartWrapState, m_document, &Document::setPartCutRotation);
|
connect(canvasGraphicsWidget, &SkeletonGraphicsWidget::setPartWrapState, m_document, &Document::setPartCutRotation);
|
||||||
|
|
||||||
|
connect(canvasGraphicsWidget, &SkeletonGraphicsWidget::addNodesToBone, m_document, &Document::addNodesToBone);
|
||||||
|
connect(canvasGraphicsWidget, &SkeletonGraphicsWidget::removeNodesFromBone, m_document, &Document::removeNodesFromBone);
|
||||||
|
|
||||||
connect(canvasGraphicsWidget, &SkeletonGraphicsWidget::setXlockState, m_document, &Document::setXlockState);
|
connect(canvasGraphicsWidget, &SkeletonGraphicsWidget::setXlockState, m_document, &Document::setXlockState);
|
||||||
connect(canvasGraphicsWidget, &SkeletonGraphicsWidget::setYlockState, m_document, &Document::setYlockState);
|
connect(canvasGraphicsWidget, &SkeletonGraphicsWidget::setYlockState, m_document, &Document::setYlockState);
|
||||||
connect(canvasGraphicsWidget, &SkeletonGraphicsWidget::setZlockState, m_document, &Document::setZlockState);
|
connect(canvasGraphicsWidget, &SkeletonGraphicsWidget::setZlockState, m_document, &Document::setZlockState);
|
||||||
|
|
|
@ -276,6 +276,27 @@ void SkeletonGraphicsWidget::showContextMenu(const QPoint& pos)
|
||||||
subMenu->addAction(&markAsNotBoneJointAction);
|
subMenu->addAction(&markAsNotBoneJointAction);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (hasNodeSelection() && !m_document->boneIdList.empty()) {
|
||||||
|
QMenu* addToBoneMenu = contextMenu.addMenu(tr("Add To Bone"));
|
||||||
|
QMenu* removeFromBoneMenu = contextMenu.addMenu(tr("Remove From Bone"));
|
||||||
|
|
||||||
|
for (const auto& boneId : m_document->boneIdList) {
|
||||||
|
const Document::Bone* bone = m_document->findBone(boneId);
|
||||||
|
if (nullptr == bone)
|
||||||
|
continue;
|
||||||
|
QAction* addAction = new QAction(bone->previewPixmap, bone->name, this);
|
||||||
|
connect(addAction, &QAction::triggered, this, [=]() {
|
||||||
|
this->addSelectedToBone(boneId);
|
||||||
|
});
|
||||||
|
QAction* removeAction = new QAction(bone->previewPixmap, bone->name, this);
|
||||||
|
connect(removeAction, &QAction::triggered, this, [=]() {
|
||||||
|
this->removeSelectedFromBone(boneId);
|
||||||
|
});
|
||||||
|
addToBoneMenu->addAction(addAction);
|
||||||
|
removeFromBoneMenu->addAction(removeAction);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
QAction selectAllAction(tr("Select All"), this);
|
QAction selectAllAction(tr("Select All"), this);
|
||||||
if (hasItems()) {
|
if (hasItems()) {
|
||||||
connect(&selectAllAction, &QAction::triggered, this, &SkeletonGraphicsWidget::selectAll);
|
connect(&selectAllAction, &QAction::triggered, this, &SkeletonGraphicsWidget::selectAll);
|
||||||
|
@ -2935,3 +2956,33 @@ void SkeletonGraphicsWidget::markSelectedAsNotBoneJoint()
|
||||||
|
|
||||||
setNodeBoneJointStates(nodeIds, false);
|
setNodeBoneJointStates(nodeIds, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SkeletonGraphicsWidget::addSelectedToBone(const dust3d::Uuid& boneId)
|
||||||
|
{
|
||||||
|
std::set<SkeletonGraphicsNodeItem*> nodeItems;
|
||||||
|
readMergedSkeletonNodeSetFromRangeSelection(&nodeItems);
|
||||||
|
if (nodeItems.empty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
std::vector<dust3d::Uuid> nodeIds;
|
||||||
|
for (const auto& it : nodeItems) {
|
||||||
|
nodeIds.push_back(it->id());
|
||||||
|
}
|
||||||
|
|
||||||
|
emit addNodesToBone(boneId, nodeIds);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SkeletonGraphicsWidget::removeSelectedFromBone(const dust3d::Uuid& boneId)
|
||||||
|
{
|
||||||
|
std::set<SkeletonGraphicsNodeItem*> nodeItems;
|
||||||
|
readMergedSkeletonNodeSetFromRangeSelection(&nodeItems);
|
||||||
|
if (nodeItems.empty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
std::vector<dust3d::Uuid> nodeIds;
|
||||||
|
for (const auto& it : nodeItems) {
|
||||||
|
nodeIds.push_back(it->id());
|
||||||
|
}
|
||||||
|
|
||||||
|
emit removeNodesFromBone(boneId, nodeIds);
|
||||||
|
}
|
||||||
|
|
|
@ -30,6 +30,8 @@ signals:
|
||||||
void scaleNodeByAddRadius(dust3d::Uuid nodeId, float amount);
|
void scaleNodeByAddRadius(dust3d::Uuid nodeId, float amount);
|
||||||
void moveNodeBy(dust3d::Uuid nodeId, float x, float y, float z);
|
void moveNodeBy(dust3d::Uuid nodeId, float x, float y, float z);
|
||||||
void setNodeBoneJointState(const dust3d::Uuid& nodeId, bool boneJoint);
|
void setNodeBoneJointState(const dust3d::Uuid& nodeId, bool boneJoint);
|
||||||
|
void addNodesToBone(const dust3d::Uuid& boneId, const std::vector<dust3d::Uuid>& nodeIds);
|
||||||
|
void removeNodesFromBone(const dust3d::Uuid& boneId, const std::vector<dust3d::Uuid>& nodeIds);
|
||||||
void removeNode(dust3d::Uuid nodeId);
|
void removeNode(dust3d::Uuid nodeId);
|
||||||
void removePart(dust3d::Uuid partId);
|
void removePart(dust3d::Uuid partId);
|
||||||
void setEditMode(Document::EditMode mode);
|
void setEditMode(Document::EditMode mode);
|
||||||
|
@ -236,6 +238,8 @@ private:
|
||||||
void rotateAllSideProfile(int degree);
|
void rotateAllSideProfile(int degree);
|
||||||
bool isFloatEqual(float a, float b);
|
bool isFloatEqual(float a, float b);
|
||||||
void setNodeBoneJointStates(const std::vector<dust3d::Uuid>& nodeIds, bool boneJoint);
|
void setNodeBoneJointStates(const std::vector<dust3d::Uuid>& nodeIds, bool boneJoint);
|
||||||
|
void addSelectedToBone(const dust3d::Uuid& boneId);
|
||||||
|
void removeSelectedFromBone(const dust3d::Uuid& boneId);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const Document* m_document = nullptr;
|
const Document* m_document = nullptr;
|
||||||
|
|
|
@ -163,3 +163,8 @@ void Theme::initIconButton(QPushButton* button)
|
||||||
{
|
{
|
||||||
button->setFixedSize(Theme::toolIconSize, Theme::toolIconSize);
|
button->setFixedSize(Theme::toolIconSize, Theme::toolIconSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Theme::initLineEdit(QLineEdit* edit)
|
||||||
|
{
|
||||||
|
edit->setStyleSheet("QLineEdit { background-color: black }");
|
||||||
|
}
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
#include <QCheckBox>
|
#include <QCheckBox>
|
||||||
#include <QColor>
|
#include <QColor>
|
||||||
#include <QLabel>
|
#include <QLabel>
|
||||||
|
#include <QLineEdit>
|
||||||
#include <QPushButton>
|
#include <QPushButton>
|
||||||
|
|
||||||
class Theme {
|
class Theme {
|
||||||
|
@ -42,6 +43,7 @@ public:
|
||||||
static void initToolButton(QPushButton* button);
|
static void initToolButton(QPushButton* button);
|
||||||
static void initCheckbox(QCheckBox* checkbox);
|
static void initCheckbox(QCheckBox* checkbox);
|
||||||
static void initIconButton(QPushButton* button);
|
static void initIconButton(QPushButton* button);
|
||||||
|
static void initLineEdit(QLineEdit* edit);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -115,6 +115,12 @@ void loadSnapshotFromXmlString(Snapshot* snapshot, char* xmlString)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
for (rapidxml::xml_node<>* node = bones->first_node(); nullptr != node; node = node->next_sibling()) {
|
||||||
|
rapidxml::xml_attribute<>* idAttribute = node->first_attribute("id");
|
||||||
|
if (nullptr != idAttribute) {
|
||||||
|
snapshot->boneIdList.push_back(idAttribute->value());
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
rapidxml::xml_node<>* partIdList = canvas->first_node("partIdList");
|
rapidxml::xml_node<>* partIdList = canvas->first_node("partIdList");
|
||||||
|
@ -232,13 +238,15 @@ void saveSnapshotToXmlString(const Snapshot& snapshot, std::string& xmlString)
|
||||||
}
|
}
|
||||||
xmlString += " </parts>\n";
|
xmlString += " </parts>\n";
|
||||||
|
|
||||||
if (!snapshot.bones.empty()) {
|
if (!snapshot.boneIdList.empty()) {
|
||||||
xmlString += " <bones>\n";
|
xmlString += " <bones>\n";
|
||||||
std::map<std::string, std::map<std::string, std::string>>::const_iterator boneIterator;
|
for (const auto& boneId : snapshot.boneIdList) {
|
||||||
for (boneIterator = snapshot.bones.begin(); boneIterator != snapshot.bones.end(); boneIterator++) {
|
auto findBone = snapshot.bones.find(boneId);
|
||||||
|
if (findBone == snapshot.bones.end())
|
||||||
|
continue;
|
||||||
std::map<std::string, std::string>::const_iterator boneAttributeIterator;
|
std::map<std::string, std::string>::const_iterator boneAttributeIterator;
|
||||||
xmlString += " <bone";
|
xmlString += " <bone";
|
||||||
for (boneAttributeIterator = boneIterator->second.begin(); boneAttributeIterator != boneIterator->second.end(); boneAttributeIterator++) {
|
for (boneAttributeIterator = findBone->second.begin(); boneAttributeIterator != findBone->second.end(); boneAttributeIterator++) {
|
||||||
if (String::startsWith(boneAttributeIterator->first, "__"))
|
if (String::startsWith(boneAttributeIterator->first, "__"))
|
||||||
continue;
|
continue;
|
||||||
xmlString += " " + boneAttributeIterator->first + "=\"" + boneAttributeIterator->second + "\"";
|
xmlString += " " + boneAttributeIterator->first + "=\"" + boneAttributeIterator->second + "\"";
|
||||||
|
|
Loading…
Reference in New Issue