Implement bone name edit and keep bone load order
parent
797ffd0b87
commit
5b6861be44
|
@ -4,6 +4,7 @@
|
|||
#include "theme.h"
|
||||
#include <QGroupBox>
|
||||
#include <QHBoxLayout>
|
||||
#include <QLineEdit>
|
||||
#include <QPushButton>
|
||||
#include <QVBoxLayout>
|
||||
#include <unordered_set>
|
||||
|
@ -19,8 +20,25 @@ BonePropertyWidget::BonePropertyWidget(Document* document,
|
|||
|
||||
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);
|
||||
|
||||
connect(this, &BonePropertyWidget::renameBone, m_document, &Document::renameBone);
|
||||
connect(this, &BonePropertyWidget::groupOperationAdded, m_document, &Document::saveSnapshot);
|
||||
|
||||
setLayout(mainLayout);
|
||||
|
@ -36,3 +54,12 @@ void BonePropertyWidget::prepareBoneIds()
|
|||
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 <dust3d/base/uuid.h>
|
||||
|
||||
class QLineEdit;
|
||||
|
||||
class BonePropertyWidget : public QWidget {
|
||||
Q_OBJECT
|
||||
signals:
|
||||
void renameBone(const dust3d::Uuid& boneId, const QString& name);
|
||||
void groupOperationAdded();
|
||||
|
||||
public:
|
||||
BonePropertyWidget(Document* document,
|
||||
const std::vector<dust3d::Uuid>& boneIds,
|
||||
QWidget* parent = nullptr);
|
||||
public slots:
|
||||
private slots:
|
||||
void nameEditChanged();
|
||||
|
||||
private:
|
||||
Document* m_document = nullptr;
|
||||
std::vector<dust3d::Uuid> m_boneIds;
|
||||
dust3d::Uuid m_boneId;
|
||||
const Document::Bone* m_bone = nullptr;
|
||||
QLineEdit* m_nameEdit = nullptr;
|
||||
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.attachBoneJointIndex = dust3d::String::toInt(dust3d::String::valueOrEmpty(boneKv.second, "attachBoneJointIndex"));
|
||||
boneMap.emplace(boneId, std::move(bone));
|
||||
boneIdList.push_back(boneId);
|
||||
newAddedBoneIds.insert(boneId);
|
||||
}
|
||||
for (const auto& boneIdString : snapshot.boneIdList) {
|
||||
boneIdList.push_back(oldNewIdMap[dust3d::Uuid(boneIdString)]);
|
||||
}
|
||||
for (const auto& boneKv : snapshot.bones) {
|
||||
auto attachBoneId = dust3d::Uuid(dust3d::String::valueOrEmpty(boneKv.second, "attachBoneId"));
|
||||
if (!attachBoneId.isNull()) {
|
||||
|
|
|
@ -571,6 +571,9 @@ DocumentWindow::DocumentWindow()
|
|||
connect(canvasGraphicsWidget, &SkeletonGraphicsWidget::setPartRoundState, m_document, &Document::setPartRoundState);
|
||||
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::setYlockState, m_document, &Document::setYlockState);
|
||||
connect(canvasGraphicsWidget, &SkeletonGraphicsWidget::setZlockState, m_document, &Document::setZlockState);
|
||||
|
|
|
@ -276,6 +276,27 @@ void SkeletonGraphicsWidget::showContextMenu(const QPoint& pos)
|
|||
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);
|
||||
if (hasItems()) {
|
||||
connect(&selectAllAction, &QAction::triggered, this, &SkeletonGraphicsWidget::selectAll);
|
||||
|
@ -2935,3 +2956,33 @@ void SkeletonGraphicsWidget::markSelectedAsNotBoneJoint()
|
|||
|
||||
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 moveNodeBy(dust3d::Uuid nodeId, float x, float y, float z);
|
||||
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 removePart(dust3d::Uuid partId);
|
||||
void setEditMode(Document::EditMode mode);
|
||||
|
@ -236,6 +238,8 @@ private:
|
|||
void rotateAllSideProfile(int degree);
|
||||
bool isFloatEqual(float a, float b);
|
||||
void setNodeBoneJointStates(const std::vector<dust3d::Uuid>& nodeIds, bool boneJoint);
|
||||
void addSelectedToBone(const dust3d::Uuid& boneId);
|
||||
void removeSelectedFromBone(const dust3d::Uuid& boneId);
|
||||
|
||||
private:
|
||||
const Document* m_document = nullptr;
|
||||
|
|
|
@ -163,3 +163,8 @@ void Theme::initIconButton(QPushButton* button)
|
|||
{
|
||||
button->setFixedSize(Theme::toolIconSize, Theme::toolIconSize);
|
||||
}
|
||||
|
||||
void Theme::initLineEdit(QLineEdit* edit)
|
||||
{
|
||||
edit->setStyleSheet("QLineEdit { background-color: black }");
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
#include <QCheckBox>
|
||||
#include <QColor>
|
||||
#include <QLabel>
|
||||
#include <QLineEdit>
|
||||
#include <QPushButton>
|
||||
|
||||
class Theme {
|
||||
|
@ -42,6 +43,7 @@ public:
|
|||
static void initToolButton(QPushButton* button);
|
||||
static void initCheckbox(QCheckBox* checkbox);
|
||||
static void initIconButton(QPushButton* button);
|
||||
static void initLineEdit(QLineEdit* edit);
|
||||
};
|
||||
|
||||
#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");
|
||||
|
@ -232,13 +238,15 @@ void saveSnapshotToXmlString(const Snapshot& snapshot, std::string& xmlString)
|
|||
}
|
||||
xmlString += " </parts>\n";
|
||||
|
||||
if (!snapshot.bones.empty()) {
|
||||
if (!snapshot.boneIdList.empty()) {
|
||||
xmlString += " <bones>\n";
|
||||
std::map<std::string, std::map<std::string, std::string>>::const_iterator boneIterator;
|
||||
for (boneIterator = snapshot.bones.begin(); boneIterator != snapshot.bones.end(); boneIterator++) {
|
||||
for (const auto& boneId : snapshot.boneIdList) {
|
||||
auto findBone = snapshot.bones.find(boneId);
|
||||
if (findBone == snapshot.bones.end())
|
||||
continue;
|
||||
std::map<std::string, std::string>::const_iterator boneAttributeIterator;
|
||||
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, "__"))
|
||||
continue;
|
||||
xmlString += " " + boneAttributeIterator->first + "=\"" + boneAttributeIterator->second + "\"";
|
||||
|
|
Loading…
Reference in New Issue