354 lines
20 KiB
C++
354 lines
20 KiB
C++
#include <stack>
|
|
#include <QUuid>
|
|
#include <QDebug>
|
|
#include "snapshotxml.h"
|
|
|
|
static void saveSkeletonComponent(Snapshot *snapshot, QXmlStreamWriter *writer, const QString &componentId)
|
|
{
|
|
const auto findComponent = snapshot->components.find(componentId);
|
|
if (findComponent == snapshot->components.end())
|
|
return;
|
|
auto &component = findComponent->second;
|
|
writer->writeStartElement("component");
|
|
std::map<QString, QString>::iterator componentAttributeIterator;
|
|
QString children;
|
|
for (componentAttributeIterator = component.begin(); componentAttributeIterator != component.end(); componentAttributeIterator++) {
|
|
if ("children" == componentAttributeIterator->first) {
|
|
children = componentAttributeIterator->second;
|
|
continue;
|
|
}
|
|
if ("dirty" == componentAttributeIterator->first)
|
|
continue;
|
|
writer->writeAttribute(componentAttributeIterator->first, componentAttributeIterator->second);
|
|
}
|
|
if (!children.isEmpty()) {
|
|
for (const auto &childId: children.split(",")) {
|
|
if (childId.isEmpty())
|
|
continue;
|
|
saveSkeletonComponent(snapshot, writer, childId);
|
|
}
|
|
}
|
|
writer->writeEndElement();
|
|
}
|
|
|
|
void saveSkeletonToXmlStream(Snapshot *snapshot, QXmlStreamWriter *writer)
|
|
{
|
|
writer->setAutoFormatting(true);
|
|
writer->writeStartDocument();
|
|
|
|
writer->writeStartElement("canvas");
|
|
std::map<QString, QString>::iterator canvasIterator;
|
|
for (canvasIterator = snapshot->canvas.begin(); canvasIterator != snapshot->canvas.end(); canvasIterator++) {
|
|
writer->writeAttribute(canvasIterator->first, canvasIterator->second);
|
|
}
|
|
|
|
writer->writeStartElement("nodes");
|
|
std::map<QString, std::map<QString, QString>>::iterator nodeIterator;
|
|
for (nodeIterator = snapshot->nodes.begin(); nodeIterator != snapshot->nodes.end(); nodeIterator++) {
|
|
std::map<QString, QString>::iterator nodeAttributeIterator;
|
|
writer->writeStartElement("node");
|
|
for (nodeAttributeIterator = nodeIterator->second.begin(); nodeAttributeIterator != nodeIterator->second.end(); nodeAttributeIterator++) {
|
|
writer->writeAttribute(nodeAttributeIterator->first, nodeAttributeIterator->second);
|
|
}
|
|
writer->writeEndElement();
|
|
}
|
|
writer->writeEndElement();
|
|
|
|
writer->writeStartElement("edges");
|
|
std::map<QString, std::map<QString, QString>>::iterator edgeIterator;
|
|
for (edgeIterator = snapshot->edges.begin(); edgeIterator != snapshot->edges.end(); edgeIterator++) {
|
|
std::map<QString, QString>::iterator edgeAttributeIterator;
|
|
writer->writeStartElement("edge");
|
|
for (edgeAttributeIterator = edgeIterator->second.begin(); edgeAttributeIterator != edgeIterator->second.end(); edgeAttributeIterator++) {
|
|
writer->writeAttribute(edgeAttributeIterator->first, edgeAttributeIterator->second);
|
|
}
|
|
writer->writeEndElement();
|
|
}
|
|
writer->writeEndElement();
|
|
|
|
writer->writeStartElement("parts");
|
|
std::map<QString, std::map<QString, QString>>::iterator partIterator;
|
|
for (partIterator = snapshot->parts.begin(); partIterator != snapshot->parts.end(); partIterator++) {
|
|
std::map<QString, QString>::iterator partAttributeIterator;
|
|
writer->writeStartElement("part");
|
|
for (partAttributeIterator = partIterator->second.begin(); partAttributeIterator != partIterator->second.end(); partAttributeIterator++) {
|
|
if ("dirty" == partAttributeIterator->first)
|
|
continue;
|
|
writer->writeAttribute(partAttributeIterator->first, partAttributeIterator->second);
|
|
}
|
|
writer->writeEndElement();
|
|
}
|
|
writer->writeEndElement();
|
|
|
|
const auto &childrenIds = snapshot->rootComponent.find("children");
|
|
if (childrenIds != snapshot->rootComponent.end()) {
|
|
writer->writeStartElement("components");
|
|
for (const auto &componentId: childrenIds->second.split(",")) {
|
|
if (componentId.isEmpty())
|
|
continue;
|
|
saveSkeletonComponent(snapshot, writer, componentId);
|
|
}
|
|
writer->writeEndElement();
|
|
}
|
|
|
|
writer->writeStartElement("materials");
|
|
std::vector<std::pair<std::map<QString, QString>, std::vector<std::pair<std::map<QString, QString>, std::vector<std::map<QString, QString>>>>>>::iterator materialIterator;
|
|
for (materialIterator = snapshot->materials.begin(); materialIterator != snapshot->materials.end(); materialIterator++) {
|
|
std::map<QString, QString>::iterator materialAttributeIterator;
|
|
writer->writeStartElement("material");
|
|
for (materialAttributeIterator = materialIterator->first.begin(); materialAttributeIterator != materialIterator->first.end(); materialAttributeIterator++) {
|
|
writer->writeAttribute(materialAttributeIterator->first, materialAttributeIterator->second);
|
|
}
|
|
writer->writeStartElement("layers");
|
|
std::vector<std::pair<std::map<QString, QString>, std::vector<std::map<QString, QString>>>>::iterator layerIterator;
|
|
for (layerIterator = materialIterator->second.begin(); layerIterator != materialIterator->second.end(); layerIterator++) {
|
|
std::map<QString, QString>::iterator layerAttributeIterator;
|
|
writer->writeStartElement("layer");
|
|
for (layerAttributeIterator = layerIterator->first.begin(); layerAttributeIterator != layerIterator->first.end(); layerAttributeIterator++) {
|
|
writer->writeAttribute(layerAttributeIterator->first, layerAttributeIterator->second);
|
|
}
|
|
writer->writeStartElement("maps");
|
|
std::vector<std::map<QString, QString>>::iterator mapIterator;
|
|
for (mapIterator = layerIterator->second.begin(); mapIterator != layerIterator->second.end(); mapIterator++) {
|
|
std::map<QString, QString>::iterator attributesIterator;
|
|
writer->writeStartElement("map");
|
|
for (attributesIterator = mapIterator->begin(); attributesIterator != mapIterator->end();
|
|
attributesIterator++) {
|
|
writer->writeAttribute(attributesIterator->first, attributesIterator->second);
|
|
}
|
|
writer->writeEndElement();
|
|
}
|
|
writer->writeEndElement();
|
|
writer->writeEndElement();
|
|
}
|
|
writer->writeEndElement();
|
|
writer->writeEndElement();
|
|
}
|
|
writer->writeEndElement();
|
|
|
|
writer->writeStartElement("poses");
|
|
//std::vector<std::pair<std::map<QString, QString>, std::map<QString, std::map<QString, QString>>>>::iterator poseIterator;
|
|
std::vector<std::pair<std::map<QString, QString>, std::vector<std::pair<std::map<QString, QString>, std::map<QString, std::map<QString, QString>>>>>>::iterator poseIterator;
|
|
for (poseIterator = snapshot->poses.begin(); poseIterator != snapshot->poses.end(); poseIterator++) {
|
|
std::map<QString, QString>::iterator poseAttributeIterator;
|
|
writer->writeStartElement("pose");
|
|
for (poseAttributeIterator = poseIterator->first.begin(); poseAttributeIterator != poseIterator->first.end(); poseAttributeIterator++) {
|
|
writer->writeAttribute(poseAttributeIterator->first, poseAttributeIterator->second);
|
|
}
|
|
writer->writeStartElement("frames");
|
|
std::vector<std::pair<std::map<QString, QString>, std::map<QString, std::map<QString, QString>>>>::iterator frameIterator;
|
|
for (frameIterator = poseIterator->second.begin(); frameIterator != poseIterator->second.end(); frameIterator++) {
|
|
std::map<QString, QString>::iterator frameAttributeIterator;
|
|
writer->writeStartElement("frame");
|
|
for (frameAttributeIterator = frameIterator->first.begin(); frameAttributeIterator != frameIterator->first.end(); frameAttributeIterator++) {
|
|
writer->writeAttribute(frameAttributeIterator->first, frameAttributeIterator->second);
|
|
}
|
|
writer->writeStartElement("parameters");
|
|
std::map<QString, std::map<QString, QString>>::iterator itemsIterator;
|
|
for (itemsIterator = frameIterator->second.begin(); itemsIterator != frameIterator->second.end(); itemsIterator++) {
|
|
std::map<QString, QString>::iterator parametersIterator;
|
|
writer->writeStartElement("parameter");
|
|
writer->writeAttribute("for", itemsIterator->first);
|
|
for (parametersIterator = itemsIterator->second.begin(); parametersIterator != itemsIterator->second.end();
|
|
parametersIterator++) {
|
|
writer->writeAttribute(parametersIterator->first, parametersIterator->second);
|
|
}
|
|
writer->writeEndElement();
|
|
}
|
|
writer->writeEndElement();
|
|
writer->writeEndElement();
|
|
}
|
|
writer->writeEndElement();
|
|
writer->writeEndElement();
|
|
}
|
|
writer->writeEndElement();
|
|
|
|
writer->writeStartElement("motions");
|
|
std::vector<std::pair<std::map<QString, QString>, std::vector<std::map<QString, QString>>>>::iterator motionIterator;
|
|
for (motionIterator = snapshot->motions.begin(); motionIterator != snapshot->motions.end(); motionIterator++) {
|
|
std::map<QString, QString>::iterator motionAttributeIterator;
|
|
writer->writeStartElement("motion");
|
|
for (motionAttributeIterator = std::get<0>(*motionIterator).begin(); motionAttributeIterator != std::get<0>(*motionIterator).end(); motionAttributeIterator++) {
|
|
writer->writeAttribute(motionAttributeIterator->first, motionAttributeIterator->second);
|
|
}
|
|
writer->writeStartElement("clips");
|
|
{
|
|
std::vector<std::map<QString, QString>>::iterator itemsIterator;
|
|
for (itemsIterator = std::get<1>(*motionIterator).begin(); itemsIterator != std::get<1>(*motionIterator).end(); itemsIterator++) {
|
|
std::map<QString, QString>::iterator attributesIterator;
|
|
writer->writeStartElement("clip");
|
|
for (attributesIterator = itemsIterator->begin(); attributesIterator != itemsIterator->end();
|
|
attributesIterator++) {
|
|
writer->writeAttribute(attributesIterator->first, attributesIterator->second);
|
|
}
|
|
writer->writeEndElement();
|
|
}
|
|
}
|
|
writer->writeEndElement();
|
|
writer->writeEndElement();
|
|
}
|
|
writer->writeEndElement();
|
|
|
|
writer->writeEndElement();
|
|
|
|
writer->writeEndDocument();
|
|
}
|
|
|
|
void loadSkeletonFromXmlStream(Snapshot *snapshot, QXmlStreamReader &reader)
|
|
{
|
|
std::stack<QString> componentStack;
|
|
std::vector<QString> elementNameStack;
|
|
std::pair<std::map<QString, QString>, std::vector<std::map<QString, QString>>> currentMaterialLayer;
|
|
std::pair<std::map<QString, QString>, std::vector<std::pair<std::map<QString, QString>, std::vector<std::map<QString, QString>>>>> currentMaterial;
|
|
std::pair<std::map<QString, QString>, std::vector<std::pair<std::map<QString, QString>, std::map<QString, std::map<QString, QString>>>>> currentPose;
|
|
std::pair<std::map<QString, QString>, std::map<QString, std::map<QString, QString>>> currentPoseFrame;
|
|
std::pair<std::map<QString, QString>, std::vector<std::map<QString, QString>>> currentMotion;
|
|
while (!reader.atEnd()) {
|
|
reader.readNext();
|
|
if (!reader.isStartElement() && !reader.isEndElement()) {
|
|
if (!reader.name().toString().isEmpty())
|
|
qDebug() << "Skip xml element:" << reader.name().toString() << " tokenType:" << reader.tokenType();
|
|
continue;
|
|
}
|
|
QString baseName = reader.name().toString();
|
|
if (reader.isStartElement())
|
|
elementNameStack.push_back(baseName);
|
|
QStringList nameItems;
|
|
for (const auto &nameItem: elementNameStack) {
|
|
nameItems.append(nameItem);
|
|
}
|
|
QString fullName = nameItems.join(".");
|
|
if (reader.isEndElement())
|
|
elementNameStack.pop_back();
|
|
//qDebug() << (reader.isStartElement() ? "<" : ">") << "fullName:" << fullName << "baseName:" << baseName;
|
|
if (reader.isStartElement()) {
|
|
if (fullName == "canvas") {
|
|
foreach(const QXmlStreamAttribute &attr, reader.attributes()) {
|
|
snapshot->canvas[attr.name().toString()] = attr.value().toString();
|
|
}
|
|
} else if (fullName == "canvas.nodes.node") {
|
|
QString nodeId = reader.attributes().value("id").toString();
|
|
if (nodeId.isEmpty())
|
|
continue;
|
|
std::map<QString, QString> *nodeMap = &snapshot->nodes[nodeId];
|
|
foreach(const QXmlStreamAttribute &attr, reader.attributes()) {
|
|
(*nodeMap)[attr.name().toString()] = attr.value().toString();
|
|
}
|
|
} else if (fullName == "canvas.edges.edge") {
|
|
QString edgeId = reader.attributes().value("id").toString();
|
|
if (edgeId.isEmpty())
|
|
continue;
|
|
std::map<QString, QString> *edgeMap = &snapshot->edges[edgeId];
|
|
foreach(const QXmlStreamAttribute &attr, reader.attributes()) {
|
|
(*edgeMap)[attr.name().toString()] = attr.value().toString();
|
|
}
|
|
} else if (fullName == "canvas.parts.part") {
|
|
QString partId = reader.attributes().value("id").toString();
|
|
if (partId.isEmpty())
|
|
continue;
|
|
std::map<QString, QString> *partMap = &snapshot->parts[partId];
|
|
foreach(const QXmlStreamAttribute &attr, reader.attributes()) {
|
|
(*partMap)[attr.name().toString()] = attr.value().toString();
|
|
}
|
|
} else if (fullName == "canvas.partIdList.partId") {
|
|
QString partId = reader.attributes().value("id").toString();
|
|
if (partId.isEmpty())
|
|
continue;
|
|
QString componentId = QUuid::createUuid().toString();
|
|
auto &component = snapshot->components[componentId];
|
|
component["id"] = componentId;
|
|
component["linkData"] = partId;
|
|
component["linkDataType"] = "partId";
|
|
auto &childrenIds = snapshot->rootComponent["children"];
|
|
if (!childrenIds.isEmpty())
|
|
childrenIds += ",";
|
|
childrenIds += componentId;
|
|
} else if (fullName.startsWith("canvas.components.component")) {
|
|
QString componentId = reader.attributes().value("id").toString();
|
|
QString parentId;
|
|
if (!componentStack.empty())
|
|
parentId = componentStack.top();
|
|
componentStack.push(componentId);
|
|
if (componentId.isEmpty())
|
|
continue;
|
|
std::map<QString, QString> *componentMap = &snapshot->components[componentId];
|
|
foreach(const QXmlStreamAttribute &attr, reader.attributes()) {
|
|
(*componentMap)[attr.name().toString()] = attr.value().toString();
|
|
}
|
|
auto &parentChildrenIds = parentId.isEmpty() ? snapshot->rootComponent["children"] : snapshot->components[parentId]["children"];
|
|
if (!parentChildrenIds.isEmpty())
|
|
parentChildrenIds += ",";
|
|
parentChildrenIds += componentId;
|
|
} else if (fullName == "canvas.materials.material.layers.layer") {
|
|
currentMaterialLayer = decltype(currentMaterialLayer)();
|
|
foreach(const QXmlStreamAttribute &attr, reader.attributes()) {
|
|
currentMaterialLayer.first[attr.name().toString()] = attr.value().toString();
|
|
}
|
|
} else if (fullName == "canvas.materials.material.layers.layer.maps.map") {
|
|
std::map<QString, QString> attributes;
|
|
foreach(const QXmlStreamAttribute &attr, reader.attributes()) {
|
|
attributes[attr.name().toString()] = attr.value().toString();
|
|
}
|
|
currentMaterialLayer.second.push_back(attributes);
|
|
} else if (fullName == "canvas.materials.material") {
|
|
QString materialId = reader.attributes().value("id").toString();
|
|
if (materialId.isEmpty())
|
|
continue;
|
|
currentMaterial = decltype(currentMaterial)();
|
|
foreach(const QXmlStreamAttribute &attr, reader.attributes()) {
|
|
currentMaterial.first[attr.name().toString()] = attr.value().toString();
|
|
}
|
|
} else if (fullName == "canvas.poses.pose") {
|
|
QString poseId = reader.attributes().value("id").toString();
|
|
if (poseId.isEmpty())
|
|
continue;
|
|
currentPose = decltype(currentPose)();
|
|
foreach(const QXmlStreamAttribute &attr, reader.attributes()) {
|
|
currentPose.first[attr.name().toString()] = attr.value().toString();
|
|
}
|
|
} else if (fullName == "canvas.poses.pose.frames.frame") {
|
|
foreach(const QXmlStreamAttribute &attr, reader.attributes()) {
|
|
currentPoseFrame.first[attr.name().toString()] = attr.value().toString();
|
|
}
|
|
} else if (fullName == "canvas.poses.pose.frames.frame.parameters.parameter") {
|
|
QString forWhat = reader.attributes().value("for").toString();
|
|
if (forWhat.isEmpty())
|
|
continue;
|
|
foreach(const QXmlStreamAttribute &attr, reader.attributes()) {
|
|
if ("for" == attr.name().toString())
|
|
continue;
|
|
currentPoseFrame.second[forWhat][attr.name().toString()] = attr.value().toString();
|
|
}
|
|
} else if (fullName == "canvas.motions.motion") {
|
|
QString motionId = reader.attributes().value("id").toString();
|
|
if (motionId.isEmpty())
|
|
continue;
|
|
currentMotion = decltype(currentMotion)();
|
|
foreach(const QXmlStreamAttribute &attr, reader.attributes()) {
|
|
currentMotion.first[attr.name().toString()] = attr.value().toString();
|
|
}
|
|
} else if (fullName == "canvas.motions.motion.clips.clip") {
|
|
std::map<QString, QString> attributes;
|
|
foreach(const QXmlStreamAttribute &attr, reader.attributes()) {
|
|
attributes[attr.name().toString()] = attr.value().toString();
|
|
}
|
|
currentMotion.second.push_back(attributes);
|
|
}
|
|
} else if (reader.isEndElement()) {
|
|
if (fullName.startsWith("canvas.components.component")) {
|
|
componentStack.pop();
|
|
} else if (fullName == "canvas.materials.material.layers.layer") {
|
|
currentMaterial.second.push_back(currentMaterialLayer);
|
|
} else if (fullName == "canvas.materials.material") {
|
|
snapshot->materials.push_back(currentMaterial);
|
|
} else if (fullName == "canvas.poses.pose.frames.frame") {
|
|
currentPose.second.push_back(currentPoseFrame);
|
|
} else if (fullName == "canvas.poses.pose") {
|
|
snapshot->poses.push_back(currentPose);
|
|
} else if (fullName == "canvas.motions.motion") {
|
|
snapshot->motions.push_back(currentMotion);
|
|
}
|
|
}
|
|
}
|
|
}
|