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())
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)
node["boneJoint"] = "true";
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["attachBoneId"] = boneIt.second.attachBoneId.toString();
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;
}
}
@ -1773,6 +1782,7 @@ void Document::addFromSnapshot(const dust3d::Snapshot& snapshot, enum SnapshotSo
std::set<dust3d::Uuid> newAddedEdgeIds;
std::set<dust3d::Uuid> newAddedPartIds;
std::set<dust3d::Uuid> newAddedComponentIds;
std::set<dust3d::Uuid> newAddedBoneIds;
std::set<dust3d::Uuid> 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();
}

View File

@ -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<dust3d::Uuid, Node> nodeMap;
std::map<dust3d::Uuid, Edge> edgeMap;
std::map<dust3d::Uuid, Component> componentMap;
Component rootComponent;
std::map<dust3d::Uuid, Bone> boneMap;
std::vector<dust3d::Uuid> boneIdList;
Component rootComponent;
Bone rootBone;
public:
Document();
@ -872,6 +873,7 @@ public slots:
void removeNodesFromBone(const dust3d::Uuid& boneId, const std::vector<dust3d::Uuid>& 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);

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");
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 += " </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");
if (childrenIds != snapshot.rootComponent.end()) {
xmlString += " <components>\n";

View File

@ -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<std::string>& stringList, const char* separator);
inline std::string valueOrEmpty(const std::map<std::string, std::string>& map, const std::string& key)