Save/load bone info to/from document
parent
b2048cfbc7
commit
eba729d785
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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";
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in New Issue