#include #include #include #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::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::iterator canvasIterator; for (canvasIterator = snapshot->canvas.begin(); canvasIterator != snapshot->canvas.end(); canvasIterator++) { writer->writeAttribute(canvasIterator->first, canvasIterator->second); } writer->writeStartElement("nodes"); std::map>::iterator nodeIterator; for (nodeIterator = snapshot->nodes.begin(); nodeIterator != snapshot->nodes.end(); nodeIterator++) { std::map::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>::iterator edgeIterator; for (edgeIterator = snapshot->edges.begin(); edgeIterator != snapshot->edges.end(); edgeIterator++) { std::map::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>::iterator partIterator; for (partIterator = snapshot->parts.begin(); partIterator != snapshot->parts.end(); partIterator++) { std::map::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::vector, std::vector>>>>>::iterator materialIterator; for (materialIterator = snapshot->materials.begin(); materialIterator != snapshot->materials.end(); materialIterator++) { std::map::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::vector>>>::iterator layerIterator; for (layerIterator = materialIterator->second.begin(); layerIterator != materialIterator->second.end(); layerIterator++) { std::map::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>::iterator mapIterator; for (mapIterator = layerIterator->second.begin(); mapIterator != layerIterator->second.end(); mapIterator++) { std::map::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::map>>>::iterator poseIterator; std::vector, std::vector, std::map>>>>>::iterator poseIterator; for (poseIterator = snapshot->poses.begin(); poseIterator != snapshot->poses.end(); poseIterator++) { std::map::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::map>>>::iterator frameIterator; for (frameIterator = poseIterator->second.begin(); frameIterator != poseIterator->second.end(); frameIterator++) { std::map::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>::iterator itemsIterator; for (itemsIterator = frameIterator->second.begin(); itemsIterator != frameIterator->second.end(); itemsIterator++) { std::map::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::vector>>>::iterator motionIterator; for (motionIterator = snapshot->motions.begin(); motionIterator != snapshot->motions.end(); motionIterator++) { std::map::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>::iterator itemsIterator; for (itemsIterator = std::get<1>(*motionIterator).begin(); itemsIterator != std::get<1>(*motionIterator).end(); itemsIterator++) { std::map::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 componentStack; std::vector elementNameStack; std::pair, std::vector>> currentMaterialLayer; std::pair, std::vector, std::vector>>>> currentMaterial; std::pair, std::vector, std::map>>>> currentPose; std::pair, std::map>> currentPoseFrame; std::pair, std::vector>> 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 *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 *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 *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 *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 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 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); } } } }