From eba729d785f02fc757ab743ea6c29c4327e80486 Mon Sep 17 00:00:00 2001 From: Jeremy HU Date: Wed, 9 Nov 2022 22:41:47 +1100 Subject: [PATCH] Save/load bone info to/from document --- application/sources/document.cc | 46 +++++++++++++++++++++++++++++++++ application/sources/document.h | 8 +++--- dust3d/base/snapshot_xml.cc | 30 +++++++++++++++++++++ dust3d/base/string.h | 5 ++++ 4 files changed, 86 insertions(+), 3 deletions(-) diff --git a/application/sources/document.cc b/application/sources/document.cc index efb8be28..32bd932d 100644 --- a/application/sources/document.cc +++ b/application/sources/document.cc @@ -1677,6 +1677,13 @@ void Document::toSnapshot(dust3d::Snapshot* snapshot, const std::set nodeBoneIdList; + for (const auto& boneId : nodeIt.second.boneIds) { + nodeBoneIdList.push_back(boneId.toString()); + } + std::string boneIds = dust3d::String::join(nodeBoneIdList, ","); + if (!boneIds.empty()) + node["boneIdList"] = boneIds; if (nodeIt.second.boneJoint) node["boneJoint"] = "true"; snapshot->nodes[node["id"]] = node; @@ -1741,6 +1748,8 @@ void Document::toSnapshot(dust3d::Snapshot* snapshot, const std::setbones[bone["id"]] = bone; } } @@ -1773,6 +1782,7 @@ void Document::addFromSnapshot(const dust3d::Snapshot& snapshot, enum SnapshotSo std::set newAddedEdgeIds; std::set newAddedPartIds; std::set newAddedComponentIds; + std::set newAddedBoneIds; std::set inversePartIds; @@ -1857,6 +1867,20 @@ void Document::addFromSnapshot(const dust3d::Snapshot& snapshot, enum SnapshotSo part.setCutFaceLinkedId(findNewLinkedId->second); } } + for (const auto& boneKv : snapshot.bones) { + Document::Bone bone; + oldNewIdMap[dust3d::Uuid(boneKv.first)] = bone.id; + bone.name = dust3d::String::valueOrEmpty(boneKv.second, "name").c_str(); + bone.attachBoneJointIndex = dust3d::String::toInt(dust3d::String::valueOrEmpty(boneKv.second, "attachBoneJointIndex").c_str()); + boneMap.emplace(bone.id, std::move(bone)); + newAddedBoneIds.insert(bone.id); + } + for (const auto& boneKv : snapshot.bones) { + auto attachBoneId = dust3d::Uuid(dust3d::String::valueOrEmpty(boneKv.second, "attachBoneId")); + if (!attachBoneId.isNull()) { + boneMap[oldNewIdMap[dust3d::Uuid(boneKv.first)]].attachBoneId = oldNewIdMap[attachBoneId]; + } + } for (const auto& nodeKv : snapshot.nodes) { if (nodeKv.second.find("radius") == nodeKv.second.end() || nodeKv.second.find("x") == nodeKv.second.end() || nodeKv.second.find("y") == nodeKv.second.end() || nodeKv.second.find("z") == nodeKv.second.end() || nodeKv.second.find("partId") == nodeKv.second.end()) continue; @@ -1889,6 +1913,11 @@ void Document::addFromSnapshot(const dust3d::Snapshot& snapshot, enum SnapshotSo } } } + for (const auto& boneIdString : dust3d::String::split(dust3d::String::valueOrEmpty(nodeKv.second, "boneIdList"), ',')) { + if (boneIdString.empty()) + continue; + node.boneIds.insert(oldNewIdMap[dust3d::Uuid(boneIdString)]); + } nodeMap[node.id] = node; newAddedNodeIds.insert(node.id); } @@ -1985,6 +2014,11 @@ void Document::addFromSnapshot(const dust3d::Snapshot& snapshot, enum SnapshotSo emit componentChildrenChanged(dust3d::Uuid()); if (isOriginChanged) emit originChanged(); + + for (const auto& boneIt : newAddedBoneIds) { + emit boneAdded(boneIt); + } + emit skeletonChanged(); for (const auto& partIt : newAddedPartIds) { @@ -2874,3 +2908,15 @@ void Document::setBoneAttachment(const dust3d::Uuid& boneId, const dust3d::Uuid& emit boneAttachmentChanged(boneId); emit rigChanged(); } + +void Document::renameBone(const dust3d::Uuid& boneId, const QString& name) +{ + auto boneIt = boneMap.find(boneId); + if (boneIt == boneMap.end()) + return; + if (boneIt->second.name == name) + return; + boneIt->second.name = name; + emit boneNameChanged(boneId); + emit rigChanged(); +} diff --git a/application/sources/document.h b/application/sources/document.h index f7140241..fb68d9cf 100644 --- a/application/sources/document.h +++ b/application/sources/document.h @@ -562,7 +562,8 @@ public: public: dust3d::Uuid id; dust3d::Uuid attachBoneId; - int attachBoneJointIndex; + int attachBoneJointIndex = 0; + QString name; Bone(const dust3d::Uuid& withId = dust3d::Uuid()); }; @@ -641,6 +642,7 @@ signals: void boneRemoved(const dust3d::Uuid& boneId); void boneAttachmentChanged(const dust3d::Uuid& boneId); void boneNodesChanged(const dust3d::Uuid& boneId); + void boneNameChanged(const dust3d::Uuid& boneId); void rigChanged(); public: // need initialize @@ -668,10 +670,9 @@ public: // need initialize std::map nodeMap; std::map edgeMap; std::map componentMap; + Component rootComponent; std::map boneMap; std::vector boneIdList; - Component rootComponent; - Bone rootBone; public: Document(); @@ -872,6 +873,7 @@ public slots: void removeNodesFromBone(const dust3d::Uuid& boneId, const std::vector& nodeIds); void removeBone(const dust3d::Uuid& boneId); void setBoneAttachment(const dust3d::Uuid& boneId, const dust3d::Uuid& toBoneId, int toBoneJointIndex); + void renameBone(const dust3d::Uuid& boneId, const QString& name); private: void resolveSnapshotBoundingBox(const dust3d::Snapshot& snapshot, QRectF* mainProfile, QRectF* sideProfile); diff --git a/dust3d/base/snapshot_xml.cc b/dust3d/base/snapshot_xml.cc index 08cec7f8..ddbf05d6 100644 --- a/dust3d/base/snapshot_xml.cc +++ b/dust3d/base/snapshot_xml.cc @@ -103,6 +103,20 @@ void loadSnapshotFromXmlString(Snapshot* snapshot, char* xmlString) } } + rapidxml::xml_node<>* bones = canvas->first_node("bones"); + if (nullptr != bones) { + 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) { + std::map* boneMap = &snapshot->bones[idAttribute->value()]; + for (rapidxml::xml_attribute<>* attribute = node->first_attribute(); + attribute; attribute = attribute->next_attribute()) { + (*boneMap)[attribute->name()] = attribute->value(); + } + } + } + } + rapidxml::xml_node<>* partIdList = canvas->first_node("partIdList"); if (nullptr != partIdList) { for (rapidxml::xml_node<>* partId = partIdList->first_node(); nullptr != partId; partId = partId->next_sibling()) { @@ -218,6 +232,22 @@ void saveSnapshotToXmlString(const Snapshot& snapshot, std::string& xmlString) } xmlString += " \n"; + if (!snapshot.bones.empty()) { + xmlString += " \n"; + std::map>::const_iterator boneIterator; + for (boneIterator = snapshot.bones.begin(); boneIterator != snapshot.bones.end(); boneIterator++) { + std::map::const_iterator boneAttributeIterator; + xmlString += " second.begin(); boneAttributeIterator != boneIterator->second.end(); boneAttributeIterator++) { + if (String::startsWith(boneAttributeIterator->first, "__")) + continue; + xmlString += " " + boneAttributeIterator->first + "=\"" + boneAttributeIterator->second + "\""; + } + xmlString += "/>\n"; + } + xmlString += " \n"; + } + const auto& childrenIds = snapshot.rootComponent.find("children"); if (childrenIds != snapshot.rootComponent.end()) { xmlString += " \n"; diff --git a/dust3d/base/string.h b/dust3d/base/string.h index 831c2b97..cad4293c 100644 --- a/dust3d/base/string.h +++ b/dust3d/base/string.h @@ -87,6 +87,11 @@ namespace String { return (float)std::stod(string); } + inline int toInt(const std::string& string) + { + return std::stoi(string); + } + std::string join(const std::vector& stringList, const char* separator); inline std::string valueOrEmpty(const std::map& map, const std::string& key)