Save/load bone info to/from document

master
Jeremy HU 2022-11-09 22:41:47 +11:00
parent b2048cfbc7
commit eba729d785
4 changed files with 86 additions and 3 deletions

View File

@ -1677,6 +1677,13 @@ void Document::toSnapshot(dust3d::Snapshot* snapshot, const std::set<dust3d::Uui
} }
if (!nodeIt.second.name.isEmpty()) if (!nodeIt.second.name.isEmpty())
node["name"] = nodeIt.second.name.toUtf8().constData(); node["name"] = nodeIt.second.name.toUtf8().constData();
std::vector<std::string> 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) if (nodeIt.second.boneJoint)
node["boneJoint"] = "true"; node["boneJoint"] = "true";
snapshot->nodes[node["id"]] = node; snapshot->nodes[node["id"]] = node;
@ -1741,6 +1748,8 @@ void Document::toSnapshot(dust3d::Snapshot* snapshot, const std::set<dust3d::Uui
bone["id"] = boneIt.second.id.toString(); bone["id"] = boneIt.second.id.toString();
bone["attachBoneId"] = boneIt.second.attachBoneId.toString(); bone["attachBoneId"] = boneIt.second.attachBoneId.toString();
bone["attachBoneJointIndex"] = std::to_string(boneIt.second.attachBoneJointIndex); bone["attachBoneJointIndex"] = std::to_string(boneIt.second.attachBoneJointIndex);
if (!boneIt.second.name.isEmpty())
bone["name"] = boneIt.second.name.toUtf8().constData();
snapshot->bones[bone["id"]] = bone; snapshot->bones[bone["id"]] = bone;
} }
} }
@ -1773,6 +1782,7 @@ void Document::addFromSnapshot(const dust3d::Snapshot& snapshot, enum SnapshotSo
std::set<dust3d::Uuid> newAddedEdgeIds; std::set<dust3d::Uuid> newAddedEdgeIds;
std::set<dust3d::Uuid> newAddedPartIds; std::set<dust3d::Uuid> newAddedPartIds;
std::set<dust3d::Uuid> newAddedComponentIds; std::set<dust3d::Uuid> newAddedComponentIds;
std::set<dust3d::Uuid> newAddedBoneIds;
std::set<dust3d::Uuid> inversePartIds; std::set<dust3d::Uuid> inversePartIds;
@ -1857,6 +1867,20 @@ void Document::addFromSnapshot(const dust3d::Snapshot& snapshot, enum SnapshotSo
part.setCutFaceLinkedId(findNewLinkedId->second); 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) { 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()) 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; 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; nodeMap[node.id] = node;
newAddedNodeIds.insert(node.id); newAddedNodeIds.insert(node.id);
} }
@ -1985,6 +2014,11 @@ void Document::addFromSnapshot(const dust3d::Snapshot& snapshot, enum SnapshotSo
emit componentChildrenChanged(dust3d::Uuid()); emit componentChildrenChanged(dust3d::Uuid());
if (isOriginChanged) if (isOriginChanged)
emit originChanged(); emit originChanged();
for (const auto& boneIt : newAddedBoneIds) {
emit boneAdded(boneIt);
}
emit skeletonChanged(); emit skeletonChanged();
for (const auto& partIt : newAddedPartIds) { for (const auto& partIt : newAddedPartIds) {
@ -2874,3 +2908,15 @@ void Document::setBoneAttachment(const dust3d::Uuid& boneId, const dust3d::Uuid&
emit boneAttachmentChanged(boneId); emit boneAttachmentChanged(boneId);
emit rigChanged(); 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();
}

View File

@ -562,7 +562,8 @@ public:
public: public:
dust3d::Uuid id; dust3d::Uuid id;
dust3d::Uuid attachBoneId; dust3d::Uuid attachBoneId;
int attachBoneJointIndex; int attachBoneJointIndex = 0;
QString name;
Bone(const dust3d::Uuid& withId = dust3d::Uuid()); Bone(const dust3d::Uuid& withId = dust3d::Uuid());
}; };
@ -641,6 +642,7 @@ signals:
void boneRemoved(const dust3d::Uuid& boneId); void boneRemoved(const dust3d::Uuid& boneId);
void boneAttachmentChanged(const dust3d::Uuid& boneId); void boneAttachmentChanged(const dust3d::Uuid& boneId);
void boneNodesChanged(const dust3d::Uuid& boneId); void boneNodesChanged(const dust3d::Uuid& boneId);
void boneNameChanged(const dust3d::Uuid& boneId);
void rigChanged(); void rigChanged();
public: // need initialize public: // need initialize
@ -668,10 +670,9 @@ public: // need initialize
std::map<dust3d::Uuid, Node> nodeMap; std::map<dust3d::Uuid, Node> nodeMap;
std::map<dust3d::Uuid, Edge> edgeMap; std::map<dust3d::Uuid, Edge> edgeMap;
std::map<dust3d::Uuid, Component> componentMap; std::map<dust3d::Uuid, Component> componentMap;
Component rootComponent;
std::map<dust3d::Uuid, Bone> boneMap; std::map<dust3d::Uuid, Bone> boneMap;
std::vector<dust3d::Uuid> boneIdList; std::vector<dust3d::Uuid> boneIdList;
Component rootComponent;
Bone rootBone;
public: public:
Document(); Document();
@ -872,6 +873,7 @@ public slots:
void removeNodesFromBone(const dust3d::Uuid& boneId, const std::vector<dust3d::Uuid>& nodeIds); void removeNodesFromBone(const dust3d::Uuid& boneId, const std::vector<dust3d::Uuid>& nodeIds);
void removeBone(const dust3d::Uuid& boneId); void removeBone(const dust3d::Uuid& boneId);
void setBoneAttachment(const dust3d::Uuid& boneId, const dust3d::Uuid& toBoneId, int toBoneJointIndex); void setBoneAttachment(const dust3d::Uuid& boneId, const dust3d::Uuid& toBoneId, int toBoneJointIndex);
void renameBone(const dust3d::Uuid& boneId, const QString& name);
private: private:
void resolveSnapshotBoundingBox(const dust3d::Snapshot& snapshot, QRectF* mainProfile, QRectF* sideProfile); void resolveSnapshotBoundingBox(const dust3d::Snapshot& snapshot, QRectF* mainProfile, QRectF* sideProfile);

View File

@ -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<std::string, std::string>* 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"); rapidxml::xml_node<>* partIdList = canvas->first_node("partIdList");
if (nullptr != partIdList) { if (nullptr != partIdList) {
for (rapidxml::xml_node<>* partId = partIdList->first_node(); nullptr != partId; partId = partId->next_sibling()) { 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 += " </parts>\n"; xmlString += " </parts>\n";
if (!snapshot.bones.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++) {
std::map<std::string, std::string>::const_iterator boneAttributeIterator;
xmlString += " <bone";
for (boneAttributeIterator = boneIterator->second.begin(); boneAttributeIterator != boneIterator->second.end(); boneAttributeIterator++) {
if (String::startsWith(boneAttributeIterator->first, "__"))
continue;
xmlString += " " + boneAttributeIterator->first + "=\"" + boneAttributeIterator->second + "\"";
}
xmlString += "/>\n";
}
xmlString += " </bones>\n";
}
const auto& childrenIds = snapshot.rootComponent.find("children"); const auto& childrenIds = snapshot.rootComponent.find("children");
if (childrenIds != snapshot.rootComponent.end()) { if (childrenIds != snapshot.rootComponent.end()) {
xmlString += " <components>\n"; xmlString += " <components>\n";

View File

@ -87,6 +87,11 @@ namespace String {
return (float)std::stod(string); return (float)std::stod(string);
} }
inline int toInt(const std::string& string)
{
return std::stoi(string);
}
std::string join(const std::vector<std::string>& stringList, const char* separator); std::string join(const std::vector<std::string>& stringList, const char* separator);
inline std::string valueOrEmpty(const std::map<std::string, std::string>& map, const std::string& key) inline std::string valueOrEmpty(const std::map<std::string, std::string>& map, const std::string& key)