diff --git a/modules/editor/grapheditor/editor/graph/abstractnodegraph.cpp b/modules/editor/grapheditor/editor/graph/abstractnodegraph.cpp index 09afc8db1..19e2868d4 100644 --- a/modules/editor/grapheditor/editor/graph/abstractnodegraph.cpp +++ b/modules/editor/grapheditor/editor/graph/abstractnodegraph.cpp @@ -3,6 +3,7 @@ #include "graphnode.h" #include +#include namespace { const char *gGraph("graph"); @@ -194,107 +195,96 @@ void AbstractNodeGraph::load(const TString &path) { } m_nodes.clear(); - QFile loadFile(path.data()); - if(!loadFile.open(QIODevice::ReadOnly)) { - qWarning("Couldn't open file."); - return; - } - QByteArray data(loadFile.readAll()); - loadFile.close(); - - QDomDocument doc; - doc.setContent(data); + pugi::xml_document doc; + QFile file(path.data()); + if(file.open(QIODevice::ReadOnly | QIODevice::Text)) { + pugi::xml_document doc; + if(doc.load_string(file.readAll().data()).status == pugi::status_ok) { + pugi::xml_node document = doc.first_child(); + int version = document.attribute("version").as_int(); - QDomElement document = doc.documentElement(); - int version = document.attribute("version", "0").toInt(); + blockSignals(true); - blockSignals(true); - - QDomNode p = document.firstChild(); - while(!p.isNull()) { - QDomElement element = p.toElement(); - if(!element.isNull()) { - loadGraph(element); - } - - p = p.nextSiblingElement(); - } + pugi::xml_node root = document.first_child(); + if(root) { + loadGraph(root); + } - blockSignals(false); + blockSignals(false); - emit graphUpdated(); + emit graphUpdated(); - if(version != m_version) { - save(path); + if(version != m_version) { + save(path); + } + } } emit graphLoaded(); } void AbstractNodeGraph::save(const TString &path) { - QDomDocument xml; - - QDomElement document = xml.createElement("document"); + pugi::xml_document xml; - document.setAttribute("version", m_version); + pugi::xml_node document = xml.append_child("document"); - saveGraph(document, xml); + document.append_attribute("version") = m_version; - xml.appendChild(document); + saveGraph(document); - QFile saveFile(path.data()); - if(saveFile.open(QIODevice::WriteOnly)) { - saveFile.write(xml.toByteArray(4)); - saveFile.close(); - } + xml.save_file(path.data(), " "); } StringList AbstractNodeGraph::nodeList() const { return StringList(); } -void AbstractNodeGraph::loadGraph(const QDomElement &parent) { - if(parent.tagName() == gGraph) { - QDomElement nodes = parent.firstChildElement(gNodes); - if(!nodes.isNull()) { - QDomElement nodeElement = nodes.firstChildElement(); - while(!nodeElement.isNull()) { - int32_t index = nodeElement.attribute(gIndex, "-1").toInt(); - TString type = nodeElement.attribute(gType).toStdString(); - GraphNode *node = nullptr; - if(type.isEmpty()) { - node = fallbackRoot(); - } else { - node = nodeCreate(type, index); - } - if(node) { - node->fromXml(nodeElement); +void AbstractNodeGraph::loadGraph(const pugi::xml_node &parent) { + if(std::string(parent.name()) == gGraph) { + pugi::xml_node nodes = parent.first_child(); + while(nodes) { + std::string name(nodes.name()); + if(name == gNodes) { + pugi::xml_node nodeElement = nodes.first_child(); + while(nodeElement) { + int32_t index = nodeElement.attribute(gIndex).as_int(-1); + TString type = nodeElement.attribute(gType).value(); + GraphNode *node = nullptr; + if(type.isEmpty()) { + node = fallbackRoot(); + } else { + node = nodeCreate(type, index); + } + if(node) { + node->fromXml(nodeElement); + } + + nodeElement = nodeElement.next_sibling(); } - - nodeElement = nodeElement.nextSiblingElement(); } - } - onNodesLoaded(); + if(name == gLinks) { + onNodesLoaded(); - QDomElement links = parent.firstChildElement(gLinks); - if(!links.isNull()) { - QDomElement linkElement = links.firstChildElement(); - while(!linkElement.isNull()) { - GraphNode *snd = node(linkElement.attribute(gSender).toInt()); - GraphNode *rcv = node(linkElement.attribute(gReceiver).toInt()); + pugi::xml_node linkElement = nodes.first_child(); + while(linkElement) { + GraphNode *snd = node(linkElement.attribute(gSender).as_int()); + GraphNode *rcv = node(linkElement.attribute(gReceiver).as_int()); - if(snd && rcv) { - int index1 = linkElement.attribute(gOut).toInt(); - NodePort *op = (index1 > -1) ? snd->port(index1) : nullptr; - int index2 = linkElement.attribute(gIn).toInt(); - NodePort *ip = (index2 > -1) ? rcv->port(index2) : nullptr; + if(snd && rcv) { + int index1 = linkElement.attribute(gOut).as_int(); + NodePort *op = (index1 > -1) ? snd->port(index1) : nullptr; + int index2 = linkElement.attribute(gIn).as_int(); + NodePort *ip = (index2 > -1) ? rcv->port(index2) : nullptr; - linkCreate(snd, op, rcv, ip); - } + linkCreate(snd, op, rcv, ip); + } - linkElement = linkElement.nextSiblingElement(); + linkElement = linkElement.next_sibling(); + } } + + nodes = nodes.next_sibling(); } } } @@ -307,52 +297,32 @@ GraphNode *AbstractNodeGraph::fallbackRoot() { return nullptr; } -void AbstractNodeGraph::saveGraph(QDomElement &parent, QDomDocument &xml) const { - QDomElement graph = xml.createElement(gGraph); +void AbstractNodeGraph::saveGraph(pugi::xml_node &parent) const { + pugi::xml_node graph = parent.append_child(gGraph); - QVariantList links; - - QDomElement nodesElement = xml.createElement(gNodes); - QDomElement linksElement = xml.createElement(gLinks); + pugi::xml_node nodesElement = graph.append_child(gNodes); + pugi::xml_node linksElement = graph.append_child(gLinks); for(auto node : m_nodes) { - QDomElement nodeElement = node->toXml(xml); - - nodesElement.appendChild(nodeElement); + pugi::xml_node nodeElement = node->toXml(); - for(auto link : saveLinks(node)) { - QDomElement linkElement = xml.createElement(gLink); + nodesElement.append_copy(nodeElement); - QVariantMap fields = link.toMap(); - for(auto &key : fields.keys()) { - linkElement.setAttribute(key, fields.value(key).toString()); - } - linksElement.appendChild(linkElement); - } + saveLinks(node, linksElement); } - - graph.appendChild(nodesElement); - graph.appendChild(linksElement); - - parent.appendChild(graph); } -QVariantList AbstractNodeGraph::saveLinks(GraphNode *node) const { - QVariantList result; - +void AbstractNodeGraph::saveLinks(GraphNode *node, pugi::xml_node &parent) const { for(auto l : m_links) { if(l->sender == node) { - QVariantMap link; - link[gSender] = AbstractNodeGraph::node(l->sender); - link[gOut] = (l->oport != nullptr) ? l->sender->portPosition(l->oport) : -1; - link[gReceiver] = AbstractNodeGraph::node(l->receiver); - link[gIn] = (l->iport != nullptr) ? l->receiver->portPosition(l->iport) : -1; + pugi::xml_node link = parent.append_child(gLink); - result.push_back(link); + link.append_attribute(gSender) = AbstractNodeGraph::node(l->sender); + link.append_attribute(gOut) = (l->oport != nullptr) ? l->sender->portPosition(l->oport) : -1; + link.append_attribute(gReceiver) = AbstractNodeGraph::node(l->receiver); + link.append_attribute(gIn) = (l->iport != nullptr) ? l->receiver->portPosition(l->iport) : -1; } } - - return result; } const AbstractNodeGraph::NodeList &AbstractNodeGraph::nodes() const { diff --git a/modules/editor/grapheditor/editor/graph/abstractnodegraph.h b/modules/editor/grapheditor/editor/graph/abstractnodegraph.h index a2a1c258c..62b221917 100644 --- a/modules/editor/grapheditor/editor/graph/abstractnodegraph.h +++ b/modules/editor/grapheditor/editor/graph/abstractnodegraph.h @@ -1,9 +1,7 @@ #ifndef ABSTRACTNODEGRAPH_H #define ABSTRACTNODEGRAPH_H -#include -#include -#include +#include #include @@ -77,15 +75,15 @@ class NODEGRAPH_EXPORT AbstractNodeGraph : public QObject { void menuVisible(bool visible); protected: - virtual void loadGraph(const QDomElement &parent); + virtual void loadGraph(const pugi::xml_node &parent); virtual void onNodesLoaded(); - virtual void saveGraph(QDomElement &parent, QDomDocument &xml) const; + virtual void saveGraph(pugi::xml_node &parent) const; virtual GraphNode *fallbackRoot(); - QVariantList saveLinks(GraphNode *node) const; + void saveLinks(GraphNode *node, pugi::xml_node &parent) const; friend class DeleteNodes; diff --git a/modules/editor/grapheditor/editor/graph/actions/deletenodes.cpp b/modules/editor/grapheditor/editor/graph/actions/deletenodes.cpp index d09fe651e..b90223762 100644 --- a/modules/editor/grapheditor/editor/graph/actions/deletenodes.cpp +++ b/modules/editor/grapheditor/editor/graph/actions/deletenodes.cpp @@ -9,45 +9,32 @@ DeleteNodes::DeleteNodes(const std::list &selection, GraphController *c } void DeleteNodes::undo() { - m_controller->graph()->loadGraph(m_document.firstChildElement()); + m_controller->graph()->loadGraph(m_document.first_child()); m_controller->selectNodes(m_indices); } void DeleteNodes::redo() { - m_document.clear(); + m_document.reset(); auto g = m_controller->graph(); - QDomElement graphElement = m_document.createElement("graph"); + pugi::xml_node graphElement = m_document.append_child("graph"); - QDomElement nodesElement = m_document.createElement("nodes"); - QDomElement linksElement = m_document.createElement("links"); + pugi::xml_node nodesElement = graphElement.append_child("nodes"); + pugi::xml_node linksElement = graphElement.append_child("links"); AbstractNodeGraph::NodeList list; for(auto &it : m_indices) { GraphNode *node = g->node(it); list.push_back(node); - for(auto link : g->saveLinks(node)) { - QDomElement linkElement = m_document.createElement("link"); - - QVariantMap fields = link.toMap(); - for(auto &key : fields.keys()) { - linkElement.setAttribute(key, fields.value(key).toString()); - } - linksElement.appendChild(linkElement); - } + + nodesElement.append_copy(node->toXml()); + g->saveLinks(node, linksElement); } for(auto it : list) { - QDomElement element = it->toXml(m_document); - nodesElement.appendChild(element); g->nodeDelete(it); } - graphElement.appendChild(nodesElement); - graphElement.appendChild(linksElement); - - m_document.appendChild(graphElement); - emit g->graphUpdated(); } diff --git a/modules/editor/grapheditor/editor/graph/actions/deletenodes.h b/modules/editor/grapheditor/editor/graph/actions/deletenodes.h index 60f5ce27e..af099973a 100644 --- a/modules/editor/grapheditor/editor/graph/actions/deletenodes.h +++ b/modules/editor/grapheditor/editor/graph/actions/deletenodes.h @@ -3,6 +3,8 @@ #include "../graphcontroller.h" +#include + class DeleteNodes : public UndoCommand { public: DeleteNodes(const std::list &selection, GraphController *ctrl, const QString &name = QObject::tr("Delete Node"), QUndoCommand *parent = nullptr); @@ -12,7 +14,7 @@ class DeleteNodes : public UndoCommand { private: std::list m_indices; - QDomDocument m_document; + pugi::xml_document m_document; GraphController *m_controller; diff --git a/modules/editor/grapheditor/editor/graph/actions/pastenodes.cpp b/modules/editor/grapheditor/editor/graph/actions/pastenodes.cpp index 93bc7aba2..995e3197d 100644 --- a/modules/editor/grapheditor/editor/graph/actions/pastenodes.cpp +++ b/modules/editor/grapheditor/editor/graph/actions/pastenodes.cpp @@ -7,7 +7,7 @@ PasteNodes::PasteNodes(const std::string &data, int x, int y, GraphController *c m_pos(x, y), UndoCommand(name, ctrl, parent) { - m_document.setContent(QByteArray(data.c_str())); + m_document.load_string(data.c_str()); } void PasteNodes::undo() { @@ -30,11 +30,11 @@ void PasteNodes::redo() { AbstractNodeGraph::NodeList nodes; - QDomElement nodesElement = m_document.firstChildElement(); - QDomElement nodeElement = nodesElement.firstChildElement(); - while(!nodeElement.isNull()) { + pugi::xml_node nodesElement = m_document.first_child(); + pugi::xml_node nodeElement = nodesElement.first_child(); + while(nodeElement) { int32_t index = -1; - const std::string type = nodeElement.attribute("type").toStdString(); + const std::string type = nodeElement.attribute("type").value(); GraphNode *node = g->nodeCreate(type, index); if(node) { node->fromXml(nodeElement); @@ -46,7 +46,7 @@ void PasteNodes::redo() { nodes.push_back(node); } - nodeElement = nodeElement.nextSiblingElement(); + nodeElement = nodeElement.next_sibling(); } for(auto it : nodes) { diff --git a/modules/editor/grapheditor/editor/graph/actions/pastenodes.h b/modules/editor/grapheditor/editor/graph/actions/pastenodes.h index 2f3e241a3..c296d8c75 100644 --- a/modules/editor/grapheditor/editor/graph/actions/pastenodes.h +++ b/modules/editor/grapheditor/editor/graph/actions/pastenodes.h @@ -3,6 +3,8 @@ #include "../graphcontroller.h" +#include + class PasteNodes : public UndoCommand { public: PasteNodes(const std::string &data, int x, int y, GraphController *ctrl, const QString &name = QObject::tr("Paste Node"), QUndoCommand *parent = nullptr); @@ -13,7 +15,7 @@ class PasteNodes : public UndoCommand { private: GraphController *m_controller; - QDomDocument m_document; + pugi::xml_document m_document; std::list m_list; std::list m_lastSelect; diff --git a/modules/editor/grapheditor/editor/graph/graphcontroller.cpp b/modules/editor/grapheditor/editor/graph/graphcontroller.cpp index 1e9dae59c..5c68a5819 100644 --- a/modules/editor/grapheditor/editor/graph/graphcontroller.cpp +++ b/modules/editor/grapheditor/editor/graph/graphcontroller.cpp @@ -12,6 +12,9 @@ #include #include +#include +#include + GraphController::GraphController(GraphView *view) : m_graph(nullptr), m_view(view), @@ -81,21 +84,21 @@ void GraphController::composeLinks() { } void GraphController::copySelected() { - QDomDocument doc; + pugi::xml_document doc; - QDomElement nodesElement = doc.createElement("nodes"); + pugi::xml_node nodesElement = doc.append_child("nodes"); for(auto it : m_selected) { GraphNode *node = m_graph->node(it); if(node->isRemovable()) { - QDomElement element = node->toXml(doc); + pugi::xml_node element = node->toXml(); - nodesElement.appendChild(element); + nodesElement.append_copy(element); } } - doc.appendChild(nodesElement); - - m_copyData = doc.toString().toStdString(); + std::stringstream stream; + doc.save(stream); + m_copyData = stream.str(); emit copied(); } diff --git a/modules/editor/grapheditor/editor/graph/graphnode.cpp b/modules/editor/grapheditor/editor/graph/graphnode.cpp index 4a7df4f14..cde65b836 100644 --- a/modules/editor/grapheditor/editor/graph/graphnode.cpp +++ b/modules/editor/grapheditor/editor/graph/graphnode.cpp @@ -1,7 +1,6 @@ #include "graphnode.h" -#include -#include +#include #include @@ -121,40 +120,38 @@ void GraphNode::onNameChanged() { } } -QDomElement GraphNode::fromVariantHelper(const Variant &value, QDomDocument &xml, const TString &annotation) { - QDomElement valueElement = xml.createElement(gValue); +pugi::xml_node GraphNode::fromVariantHelper(const Variant &value, const TString &annotation) { + pugi::xml_node valueElement; + valueElement.set_name(gValue); switch(value.userType()) { case MetaType::VECTOR2: { - valueElement.setAttribute(gType, "vec2"); + valueElement.append_attribute(gType) = "vec2"; Vector2 vec(value.toVector2()); - valueElement.appendChild(xml.createTextNode(QString::number(vec.x) + ", " + - QString::number(vec.y) )); + valueElement.set_value((TString::number(vec.x) + ", " + TString::number(vec.y)).data()); } break; case MetaType::VECTOR3: { - valueElement.setAttribute(gType, "vec3"); + valueElement.append_attribute(gType) = "vec3"; Vector3 vec(value.toVector3()); - valueElement.appendChild(xml.createTextNode(QString::number(vec.x) + ", " + - QString::number(vec.y) + ", " + - QString::number(vec.z) )); + valueElement.set_value((TString::number(vec.x) + ", " + TString::number(vec.y) + ", " + TString::number(vec.z)).data()); } break; case MetaType::VECTOR4: { Vector4 vec(value.toVector4()); if(annotation == "editor=Color") { - valueElement.setAttribute(gType, "color"); - valueElement.appendChild(xml.createTextNode(QString::number(int(vec.x * 255.0f)) + ", " + - QString::number(int(vec.y * 255.0f)) + ", " + - QString::number(int(vec.z * 255.0f)) + ", " + - QString::number(int(vec.w * 255.0f)) )); + valueElement.append_attribute(gType) = "color"; + valueElement.set_value((TString::number(int(vec.x * 255.0f)) + ", " + + TString::number(int(vec.y * 255.0f)) + ", " + + TString::number(int(vec.z * 255.0f)) + ", " + + TString::number(int(vec.w * 255.0f)) ).data()); } else { - valueElement.setAttribute(gType, "vec4"); - valueElement.appendChild(xml.createTextNode(QString::number(vec.x) + ", " + - QString::number(vec.y) + ", " + - QString::number(vec.z) + ", " + - QString::number(vec.w) )); + valueElement.append_attribute(gType) = "vec4"; + valueElement.set_value((TString::number(vec.x) + ", " + + TString::number(vec.y) + ", " + + TString::number(vec.z) + ", " + + TString::number(vec.w) ).data()); } } break; default: { @@ -162,12 +159,12 @@ QDomElement GraphNode::fromVariantHelper(const Variant &value, QDomDocument &xml Object *object = (value.data() == nullptr) ? nullptr : *(reinterpret_cast(value.data())); TString ref = Engine::reference(object); if(!ref.isEmpty()) { - valueElement.setAttribute(gType, "template"); - valueElement.appendChild(xml.createTextNode((ref + ", " + object->typeName()).data())); + valueElement.append_attribute(gType) = "template"; + valueElement.set_value((ref + ", " + object->typeName()).data()); } } else { - valueElement.setAttribute(gType, MetaType::name(value.type())); - valueElement.appendChild(xml.createTextNode(value.toString().data())); + valueElement.append_attribute(gType) = MetaType::name(value.type()); + valueElement.set_value(value.toString().data()); } } break; } @@ -226,8 +223,8 @@ Variant GraphNode::toVariantHelper(const TString &data, const TString &type) { } } else if(lowType == "template") { Object *object = Engine::loadResource(*std::next(list.begin(), 0)); - uint32_t type = MetaType::type((*std::next(list.begin(), 1)).data()) + 1; - result = Variant(type, &object); + uint32_t metaType = MetaType::type((*std::next(list.begin(), 1)).data()) + 1; + result = Variant(metaType, &object); } else if(lowType == "color") { if(list.size() == 4) { result = Vector4((*std::next(list.begin(), 0)).toFloat() / 255.0f, (*std::next(list.begin(), 1)).toFloat() / 255.0f, @@ -240,13 +237,16 @@ Variant GraphNode::toVariantHelper(const TString &data, const TString &type) { return result; } -QDomElement GraphNode::toXml(QDomDocument &xml) { - QDomElement node = xml.createElement(gNode); +pugi::xml_node GraphNode::toXml() { + pugi::xml_node node; + node.set_name(gNode); - node.setAttribute(gX, (int)m_pos.x); - node.setAttribute(gY, (int)m_pos.y); - node.setAttribute(gIndex, m_graph->node(this)); - node.setAttribute(gType, m_typeName.data()); + pugi::xml_attribute x; + + node.append_attribute(gX) = (int)m_pos.x; + node.append_attribute(gY) = (int)m_pos.y; + node.append_attribute(gIndex) = m_graph->node(this); + node.append_attribute(gType) = m_typeName.data(); const MetaObject *meta = metaObject(); for(int i = 0; i < meta->propertyCount(); i++) { @@ -258,37 +258,36 @@ QDomElement GraphNode::toXml(QDomDocument &xml) { annotation = text; } - QDomElement valueElement = fromVariantHelper(property.read(this), xml, annotation); - valueElement.setAttribute(gName, property.name()); + pugi::xml_node valueElement = fromVariantHelper(property.read(this), annotation); + valueElement.append_attribute(gName) = property.name(); - node.appendChild(valueElement); + node.append_copy(valueElement); } for(auto it : dynamicPropertyNames()) { - QDomElement valueElement = fromVariantHelper(property(it.data()), xml, TString()); - valueElement.setAttribute(gName, it.data()); + pugi::xml_node valueElement = fromVariantHelper(property(it.data()), TString()); + valueElement.append_attribute(gName) = it.data(); - node.appendChild(valueElement); + node.append_copy(valueElement); } return node; } -void GraphNode::fromXml(const QDomElement &element) { - setPosition(Vector2(element.attribute(gX).toInt(), - element.attribute(gY).toInt())); +void GraphNode::fromXml(const pugi::xml_node &element) { + setPosition(Vector2(element.attribute(gX).as_int(), + element.attribute(gY).as_int())); blockSignals(true); - QVariantMap values; - QDomElement valueElement = element.firstChildElement(gValue); - while(!valueElement.isNull()) { - TString type = valueElement.attribute(gType).toStdString(); - TString name = valueElement.attribute(gName).toStdString(); + pugi::xml_node valueElement = element.first_child(); + while(valueElement) { + TString type = valueElement.attribute(gType).value(); + TString name = valueElement.attribute(gName).value(); - setProperty(name.data(), toVariantHelper(valueElement.text().toStdString(), type)); + setProperty(name.data(), toVariantHelper(valueElement.child_value(), type)); - valueElement = valueElement.nextSiblingElement(); + valueElement = valueElement.next_sibling(); } blockSignals(false); diff --git a/modules/editor/grapheditor/editor/graph/graphnode.h b/modules/editor/grapheditor/editor/graph/graphnode.h index e0a71d8b4..963896503 100644 --- a/modules/editor/grapheditor/editor/graph/graphnode.h +++ b/modules/editor/grapheditor/editor/graph/graphnode.h @@ -19,8 +19,10 @@ class AbstractNodeGraph; class GraphNode; class Widget; -class QDomElement; -class QDomDocument; +namespace pugi { + class xml_node; + class xml_document; +} class NODEGRAPH_EXPORT NodePort { public: @@ -93,12 +95,12 @@ class NODEGRAPH_EXPORT GraphNode : public Object { std::vector &ports(); - virtual QDomElement toXml(QDomDocument &xml); - virtual void fromXml(const QDomElement &element); + virtual pugi::xml_node toXml(); + virtual void fromXml(const pugi::xml_node &element); static Variant toVariantHelper(const TString &data, const TString &type); - static QDomElement fromVariantHelper(const Variant &value, QDomDocument &xml, const TString &annotation); + static pugi::xml_node fromVariantHelper(const Variant &value, const TString &annotation); protected: void onNameChanged(); diff --git a/modules/editor/grapheditor/editor/graph/graphview.cpp b/modules/editor/grapheditor/editor/graph/graphview.cpp index 1a2949375..9779251dd 100644 --- a/modules/editor/grapheditor/editor/graph/graphview.cpp +++ b/modules/editor/grapheditor/editor/graph/graphview.cpp @@ -41,7 +41,6 @@ class ObjectObserver : public Object { A_OBJECT(ObjectObserver, Object, Editor) A_METHODS( - A_SLOT(ObjectObserver::onNodePressed), A_SLOT(ObjectObserver::onPortPressed), A_SLOT(ObjectObserver::onPortReleased) ) @@ -56,8 +55,6 @@ class ObjectObserver : public Object { m_view = view; } - void onNodePressed() { } - void onPortPressed(int port) { if(m_view) { NodeWidget *widget = dynamic_cast(sender()); @@ -301,7 +298,6 @@ void GraphView::onGraphUpdated() { if(actor->parent() == nullptr) { actor->setParent(m_view); - Object::connect(widget, _SIGNAL(pressed()), m_objectObserver, _SLOT(onNodePressed())); Object::connect(widget, _SIGNAL(portPressed(int)), m_objectObserver, _SLOT(onPortPressed(int))); Object::connect(widget, _SIGNAL(portReleased(int)), m_objectObserver, _SLOT(onPortReleased(int))); } diff --git a/modules/editor/grapheditor/grapheditor.qbs b/modules/editor/grapheditor/grapheditor.qbs index cf72d76f4..758312085 100644 --- a/modules/editor/grapheditor/grapheditor.qbs +++ b/modules/editor/grapheditor/grapheditor.qbs @@ -19,6 +19,7 @@ Project { "../../../thirdparty/next/inc", "../../../thirdparty/next/inc/math", "../../../thirdparty/next/inc/core", + "../../../thirdparty/pugixml/src", "../../../modules/uikit/includes/", "../../../modules/uikit/includes/components" ] @@ -32,7 +33,7 @@ Project { Depends { name: "next-editor" } Depends { name: "engine-editor" } Depends { name: "uikit-editor" } - Depends { name: "Qt"; submodules: ["core", "gui", "widgets", "xml"]; } + Depends { name: "Qt"; submodules: ["core", "gui", "widgets"]; } bundle.isBundle: false cpp.defines: ["SHARED_DEFINE", "NODEGRAPH_LIBRARY"] diff --git a/modules/editor/motiontools/converter/animationcontrollergraph.cpp b/modules/editor/motiontools/converter/animationcontrollergraph.cpp index a9d5d8cc6..62062b96c 100644 --- a/modules/editor/motiontools/converter/animationcontrollergraph.cpp +++ b/modules/editor/motiontools/converter/animationcontrollergraph.cpp @@ -1,10 +1,10 @@ #include "animationcontrollergraph.h" -#include - #include "basestate.h" #include "animationbuilder.h" + #include +#include namespace { const char *gEntry("Entry"); @@ -27,13 +27,13 @@ AnimationControllerGraph::AnimationControllerGraph() : m_functions.push_back(gBaseState); } -void AnimationControllerGraph::loadGraph(const QDomElement &parent) { +void AnimationControllerGraph::loadGraph(const pugi::xml_node &parent) { AbstractNodeGraph::loadGraph(parent); - if(parent.tagName() == gUser) { + if(std::string(parent.name()) == gUser) { GraphNode *initial = nullptr; - int32_t entry = parent.attribute(gEntry, "-1").toInt(); + int32_t entry = parent.attribute(gEntry).as_int(-1); if(entry > -1 && m_nodes.size() > entry + 1) { initial = *std::next(m_nodes.begin(), entry + 1); } diff --git a/modules/editor/motiontools/converter/animationcontrollergraph.h b/modules/editor/motiontools/converter/animationcontrollergraph.h index 3dd2a1e8a..88f1b4aec 100644 --- a/modules/editor/motiontools/converter/animationcontrollergraph.h +++ b/modules/editor/motiontools/converter/animationcontrollergraph.h @@ -9,7 +9,7 @@ class AnimationControllerGraph : public AbstractNodeGraph { public: AnimationControllerGraph(); - void loadGraph(const QDomElement &parent) override; + void loadGraph(const pugi::xml_node &parent) override; Variant object() const; diff --git a/modules/editor/motiontools/motiontools.qbs b/modules/editor/motiontools/motiontools.qbs index a712c10ec..f52c16381 100644 --- a/modules/editor/motiontools/motiontools.qbs +++ b/modules/editor/motiontools/motiontools.qbs @@ -22,6 +22,7 @@ Project { "../../../thirdparty/next/inc/math", "../../../thirdparty/next/inc/core", "../../../thirdparty/next/inc/anim", + "../../../thirdparty/pugixml/src", "../../../modules/editor/grapheditor" ] @@ -35,7 +36,7 @@ Project { Depends { name: "engine-editor" } Depends { name: "graph-editor" } Depends { name: "uikit-editor" } - Depends { name: "Qt"; submodules: ["core", "gui","widgets", "xml"]; } + Depends { name: "Qt"; submodules: ["core", "gui", "widgets"]; } bundle.isBundle: false cpp.defines: ["SHARED_DEFINE"] diff --git a/modules/editor/particletools/converter/effectgraph.cpp b/modules/editor/particletools/converter/effectgraph.cpp index 6315f2117..9562a0722 100644 --- a/modules/editor/particletools/converter/effectgraph.cpp +++ b/modules/editor/particletools/converter/effectgraph.cpp @@ -46,14 +46,14 @@ void EffectGraph::scanForFunctions() { for(auto &path : files) { QFile file(path); if(file.open(QIODevice::ReadOnly | QIODevice::Text)) { - QDomDocument doc; - if(doc.setContent(&file)) { - QDomElement function = doc.documentElement(); + pugi::xml_document doc; + if(doc.load_string(file.readAll().data()).status == pugi::status_ok) { + pugi::xml_node function = doc.document_element(); - QString name(function.attribute("name")); + TString name(function.attribute("name").as_string()); m_nodeTypes.push_back(name.toStdString()); - m_exposedModules[QFileInfo(name).baseName().toStdString()] = path.toStdString(); + m_exposedModules[QFileInfo(name.data()).baseName().toStdString()] = path.toStdString(); } } } diff --git a/modules/editor/particletools/converter/effectmodule.cpp b/modules/editor/particletools/converter/effectmodule.cpp index 7cf8342f6..c1acc6609 100644 --- a/modules/editor/particletools/converter/effectmodule.cpp +++ b/modules/editor/particletools/converter/effectmodule.cpp @@ -8,7 +8,7 @@ #include -#include +#include #include "effectrootnode.h" #include "effectgraph.h" @@ -119,52 +119,47 @@ TString EffectModule::path() const { void EffectModule::load(const TString &path) { m_path = path; - QFile file(m_path.data()); + QFile file(path.data()); if(file.open(QIODevice::ReadOnly | QIODevice::Text)) { - QDomDocument doc; - if(doc.setContent(&file)) { - QDomElement function = doc.documentElement(); + pugi::xml_document doc; + if(doc.load_string(file.readAll().data()).status == pugi::status_ok) { + pugi::xml_node function = doc.document_element(); - TString moduleName = QFileInfo(function.attribute(gName)).baseName().toStdString(); + TString moduleName = QFileInfo(function.attribute(gName).as_string()).baseName().toStdString(); setName(moduleName); - static const QMap stages = { + static const QMap stages = { {"spawn", Stage::Spawn}, {"update", Stage::Update}, {"render", Stage::Render} }; - m_stage = stages.value(function.attribute("stage").toLower(), Stage::Spawn); - - QDomNode n = function.firstChild(); - while(!n.isNull()) { - QDomElement element = n.toElement(); - - if(element.tagName() == "params") { // parse inputs - QDomNode paramNode = element.firstChild(); - while(!paramNode.isNull()) { - QDomElement paramElement = paramNode.toElement(); - + m_stage = stages.value(TString(function.attribute("stage").as_string()).toLower(), Stage::Spawn); + + pugi::xml_node element = function.first_child(); + while(element) { + std::string name(element.name()); + if(name == "params") { // parse inputs + pugi::xml_node paramElement = element.first_child(); + while(paramElement) { ParameterData data; - data.name = paramElement.attribute(gName).toStdString(); - data.modeType = paramElement.attribute("mode").toStdString(); - data.type = paramElement.attribute(gType).toStdString(); - data.max = data.min = EffectRootNode::toVariantHelper(paramElement.attribute("default").toStdString(), data.type); - QString visible = paramElement.attribute("visible"); + data.name = paramElement.attribute(gName).as_string(); + data.modeType = paramElement.attribute("mode").as_string(); + data.type = paramElement.attribute(gType).as_string(); + data.max = data.min = EffectRootNode::toVariantHelper(paramElement.attribute("default").as_string(), data.type); + TString visible = paramElement.attribute("visible").as_string(); if(!visible.isEmpty()) { data.visible = visible == "true"; } m_parameters.push_back(data); - paramNode = paramNode.nextSibling(); + paramElement = paramElement.next_sibling(); } - } else if(element.tagName() == "operations") { - QDomNode operationNode = element.firstChild(); - while(!operationNode.isNull()) { - QDomElement operationElement = operationNode.toElement(); - - static const QMap operations = { + } else if(name == "operations") { + pugi::xml_node operationElement = element.first_child(); + while(operationElement) { + static const QMap operations = { {"set", Operation::Set}, {"add", Operation::Add}, {"sub", Operation::Subtract}, @@ -173,35 +168,33 @@ void EffectModule::load(const TString &path) { }; OperationData data; - data.operation = operations.value(operationElement.attribute("code").toLower(), Operation::Set); - data.result = operationElement.attribute("result").toStdString(); - data.args.push_back(operationElement.attribute("arg0").toStdString()); - data.args.push_back(operationElement.attribute("arg1").toStdString()); + data.operation = operations.value(TString(operationElement.attribute("code").as_string()).toLower(), Operation::Set); + data.result = operationElement.attribute("result").as_string(); + data.args.push_back(operationElement.attribute("arg0").as_string()); + data.args.push_back(operationElement.attribute("arg1").as_string()); m_operations.push_back(data); - operationNode = operationNode.nextSibling(); + operationElement = operationElement.next_sibling(); } - } else if(element.tagName() == "bindings") { - QDomNode bindNode = element.firstChild(); - while(!bindNode.isNull()) { - QDomElement bindElement = bindNode.toElement(); - + } else if(name == "bindings") { + pugi::xml_node bindElement = element.first_child(); + while(bindElement) { int size = 1; - auto it = locals.find(bindElement.attribute(gType).toStdString()); + auto it = locals.find(bindElement.attribute(gType).as_string()); if(it != locals.end()) { size = it->second; } - m_effect->addAttribute(bindElement.attribute(gName).toStdString(), + m_effect->addAttribute(bindElement.attribute(gName).as_string(), size, - bindElement.attribute("offset").toInt()); + bindElement.attribute("offset").as_int()); - bindNode = bindNode.nextSibling(); + bindElement = bindElement.next_sibling(); } } - n = n.nextSibling(); + element = element.next_sibling(); } setRoot(m_effect); @@ -209,8 +202,8 @@ void EffectModule::load(const TString &path) { } } -void EffectModule::toXml(QDomElement &element, QDomDocument &xml) { - element.setAttribute(gType, name().data()); +void EffectModule::toXml(pugi::xml_node &element) { + element.append_attribute(gType) = name().data(); const MetaObject *meta = metaObject(); for(int i = 0; i < meta->propertyCount(); i++) { @@ -221,10 +214,10 @@ void EffectModule::toXml(QDomElement &element, QDomDocument &xml) { annotation = property.table()->annotation; } - QDomElement valueElement = EffectRootNode::fromVariantHelper(property.read(this), xml, annotation); - valueElement.setAttribute(gName, property.name()); + pugi::xml_node valueElement = EffectRootNode::fromVariantHelper(property.read(this), annotation); + valueElement.append_attribute(gName) = property.name(); - element.appendChild(valueElement); + element.append_copy(valueElement); } auto dynamicProperties = dynamicPropertyNames(); @@ -232,53 +225,52 @@ void EffectModule::toXml(QDomElement &element, QDomDocument &xml) { MetaEnum metaEnum = meta->enumerator(meta->indexOfEnumerator("Space")); for(auto dynProp : dynamicProperties) { if(dynProp.front() != '_') { - TString annotation = dynamicPropertyInfo(dynProp.data()); Variant value = property(dynProp.data()); if(annotation == "enum=Space") { - QDomElement valueElement = xml.createElement(gValue); - - valueElement.setAttribute(gName, dynProp.data()); - valueElement.setAttribute(gType, dynProp.data()); - valueElement.appendChild(xml.createTextNode(metaEnum.valueToKey(value.toInt()))); + pugi::xml_node valueElement = element.append_child(gValue); - element.appendChild(valueElement); + valueElement.append_attribute(gName) = dynProp.data(); + valueElement.append_attribute(gType) = dynProp.data(); + valueElement.set_value(metaEnum.valueToKey(value.toInt())); } else { - QDomElement valueElement = EffectRootNode::fromVariantHelper(value, xml, annotation); + pugi::xml_node valueElement = EffectRootNode::fromVariantHelper(value, annotation); - valueElement.setAttribute(gName, dynProp.data()); - element.appendChild(valueElement); + valueElement.append_attribute(gName) = dynProp.data(); + element.append_copy(valueElement); } } } } -void EffectModule::fromXml(const QDomElement &element) { +void EffectModule::fromXml(const pugi::xml_node &element) { const MetaObject *meta = metaObject(); MetaEnum metaEnum = meta->enumerator(meta->indexOfEnumerator("Space")); - QDomElement valueElement = element.firstChildElement(gValue); - while(!valueElement.isNull()) { - TString type = valueElement.attribute(gType).toStdString(); - TString name = valueElement.attribute(gName).toStdString(); - TString value = valueElement.text().toStdString(); + pugi::xml_node valueElement = element.first_child(); + while(valueElement) { + if(std::string(valueElement.name()) == gValue) { + TString type = valueElement.attribute(gType).value(); + TString name = valueElement.attribute(gName).value(); + TString value = valueElement.child_value(); - Variant variant = EffectRootNode::toVariantHelper(value, type); + Variant variant = EffectRootNode::toVariantHelper(value, type); - for(auto it : m_parameters) { - if(it.modeType == name) { - int enumValue = metaEnum.keyToValue(value.data()); - variant = Variant::fromValue(enumValue); + for(auto it : m_parameters) { + if(it.modeType == name) { + int enumValue = metaEnum.keyToValue(value.data()); + variant = Variant::fromValue(enumValue); - break; + break; + } } - } - setProperty(name.data(), variant); + setProperty(name.data(), variant); + } - valueElement = valueElement.nextSiblingElement(); + valueElement = valueElement.next_sibling(); } setRoot(m_effect); diff --git a/modules/editor/particletools/converter/effectmodule.h b/modules/editor/particletools/converter/effectmodule.h index 3e7b35d1e..4bf46456c 100644 --- a/modules/editor/particletools/converter/effectmodule.h +++ b/modules/editor/particletools/converter/effectmodule.h @@ -11,8 +11,10 @@ class CheckBox; class EffectRootNode; -class QDomElement; -class QDomDocument; +namespace pugi { +class xml_document; +class xml_node; +} class EffectModule : public Object { A_OBJECT(EffectModule, Object, Modificator) @@ -111,8 +113,8 @@ class EffectModule : public Object { void load(const TString &path); - void toXml(QDomElement &element, QDomDocument &xml); - void fromXml(const QDomElement &element); + void toXml(pugi::xml_node &element); + void fromXml(const pugi::xml_node &element); VariantList saveData() const override; diff --git a/modules/editor/particletools/converter/effectrootnode.cpp b/modules/editor/particletools/converter/effectrootnode.cpp index b0a6a2ee1..36d062fbf 100644 --- a/modules/editor/particletools/converter/effectrootnode.cpp +++ b/modules/editor/particletools/converter/effectrootnode.cpp @@ -54,39 +54,41 @@ Vector4 EffectRootNode::color() const { return Vector4(0.141f, 0.384f, 0.514f, 1.0f); } -QDomElement EffectRootNode::toXml(QDomDocument &xml) { - QDomElement result = GraphNode::toXml(xml); +pugi::xml_node EffectRootNode::toXml() { + pugi::xml_node result = GraphNode::toXml(); - QDomElement modulesElement = xml.createElement(gModules); + pugi::xml_node modulesElement = result.append_child(gModules); for(auto it : m_modules) { - QDomElement moduleElement = xml.createElement(gModule); - it->toXml(moduleElement, xml); - - modulesElement.appendChild(moduleElement); + pugi::xml_node moduleElement = modulesElement.append_child(gModule); + it->toXml(moduleElement); } - result.appendChild(modulesElement); return result; } -void EffectRootNode::fromXml(const QDomElement &element) { +void EffectRootNode::fromXml(const pugi::xml_node &element) { GraphNode::fromXml(element); - QDomElement modulesElement = element.firstChildElement(gModules); - if(!modulesElement.isNull()) { - EffectGraph *graph = static_cast(m_graph); + pugi::xml_node modulesElement = element.first_child(); + while(modulesElement) { + if(std::string(modulesElement.name()) == gModules) { + EffectGraph *graph = static_cast(m_graph); - QDomElement moduleElement = modulesElement.firstChildElement(gModule); - while(!moduleElement.isNull()) { - TString modulePath = graph->modulePath(moduleElement.attribute(gType).toStdString()); + pugi::xml_node moduleElement = modulesElement.first_child(); + while(moduleElement) { + if(std::string(moduleElement.name()) == gModule) { + TString modulePath = graph->modulePath(moduleElement.attribute(gType).value()); - EffectModule *module = insertModule(modulePath); - if(module) { - module->fromXml(moduleElement); - } + EffectModule *module = insertModule(modulePath); + if(module) { + module->fromXml(moduleElement); + } + } - moduleElement = moduleElement.nextSiblingElement(); + moduleElement = moduleElement.next_sibling(); + } } + modulesElement = modulesElement.next_sibling(); } } diff --git a/modules/editor/particletools/converter/effectrootnode.h b/modules/editor/particletools/converter/effectrootnode.h index 7452201ed..57dbfa626 100644 --- a/modules/editor/particletools/converter/effectrootnode.h +++ b/modules/editor/particletools/converter/effectrootnode.h @@ -7,6 +7,8 @@ #include #include +#include + class Foldout; class EffectModule; @@ -59,8 +61,8 @@ class EffectRootNode : public GraphNode { private: Vector4 color() const override; - QDomElement toXml(QDomDocument &xml) override; - void fromXml(const QDomElement &element) override; + pugi::xml_node toXml() override; + void fromXml(const pugi::xml_node &element) override; Widget *widget() override; diff --git a/modules/editor/particletools/editor/actions/deletemodule.cpp b/modules/editor/particletools/editor/actions/deletemodule.cpp index 39b328a89..60ce951af 100644 --- a/modules/editor/particletools/editor/actions/deletemodule.cpp +++ b/modules/editor/particletools/editor/actions/deletemodule.cpp @@ -17,7 +17,7 @@ void DeleteModule::undo() { if(root) { EffectModule *module = root->insertModule(m_path, m_index); if(module) { - module->fromXml(m_document.firstChild().toElement()); + module->fromXml(m_document.first_child()); m_graph->moduleChanged(); } @@ -25,16 +25,14 @@ void DeleteModule::undo() { } void DeleteModule::redo() { - m_document.clear(); + m_document.reset(); EffectModule *module = static_cast(Engine::findObject(m_object)); if(module) { m_path = module->path(); - QDomElement moduleElement = m_document.createElement("module"); - module->toXml(moduleElement, m_document); - - m_document.appendChild(moduleElement); + pugi::xml_node moduleElement = m_document.append_child("module"); + module->toXml(moduleElement); EffectRootNode *root = static_cast(module->parent()); m_root = root->uuid(); diff --git a/modules/editor/particletools/editor/actions/deletemodule.h b/modules/editor/particletools/editor/actions/deletemodule.h index 8864ee86e..c5dd550bc 100644 --- a/modules/editor/particletools/editor/actions/deletemodule.h +++ b/modules/editor/particletools/editor/actions/deletemodule.h @@ -3,6 +3,8 @@ #include "effectgraph.h" +#include + class EffectModule; class DeleteModule : public UndoCommand { @@ -14,7 +16,7 @@ class DeleteModule : public UndoCommand { protected: TString m_path; - QDomDocument m_document; + pugi::xml_document m_document; EffectGraph *m_graph; diff --git a/modules/editor/particletools/particletools.qbs b/modules/editor/particletools/particletools.qbs index 357c83a4c..af6b38ecd 100644 --- a/modules/editor/particletools/particletools.qbs +++ b/modules/editor/particletools/particletools.qbs @@ -26,6 +26,7 @@ Project { "../../../thirdparty/next/inc", "../../../thirdparty/next/inc/math", "../../../thirdparty/next/inc/core", + "../../../thirdparty/pugixml/src", "../../../modules/editor/grapheditor", "../../../modules/uikit/includes" ] @@ -40,7 +41,7 @@ Project { Depends { name: "engine-editor" } Depends { name: "graph-editor" } Depends { name: "uikit-editor" } - Depends { name: "Qt"; submodules: ["core", "gui", "widgets", "xml"]; } + Depends { name: "Qt"; submodules: ["core", "gui", "widgets"]; } bundle.isBundle: false cpp.defines: { diff --git a/modules/editor/pipelinetools/converter/pipelinetaskgraph.cpp b/modules/editor/pipelinetools/converter/pipelinetaskgraph.cpp index f5d8de224..2a06bd6e9 100644 --- a/modules/editor/pipelinetools/converter/pipelinetaskgraph.cpp +++ b/modules/editor/pipelinetools/converter/pipelinetaskgraph.cpp @@ -4,6 +4,7 @@ #include #include +#include namespace { const char *gRootNode("RootNode"); @@ -60,7 +61,7 @@ bool PipelineTaskGraph::buildGraph() { m_taskLinks.push_back(field); } else { - qDebug() << "Unable to find a link"; + aDebug() << "Unable to find a link"; } } } diff --git a/modules/editor/pipelinetools/pipelinetools.qbs b/modules/editor/pipelinetools/pipelinetools.qbs index 75c9833dc..b94346d70 100644 --- a/modules/editor/pipelinetools/pipelinetools.qbs +++ b/modules/editor/pipelinetools/pipelinetools.qbs @@ -32,7 +32,7 @@ Project { Depends { name: "next-editor" } Depends { name: "engine-editor" } Depends { name: "graph-editor" } - Depends { name: "Qt"; submodules: ["core", "gui", "widgets", "xml"]; } + Depends { name: "Qt"; submodules: ["core", "gui", "widgets"]; } bundle.isBundle: false cpp.defines: { diff --git a/modules/editor/shadertools/converter/functions/customfunction.h b/modules/editor/shadertools/converter/functions/customfunction.h index 7040cca8b..3adc99f2d 100644 --- a/modules/editor/shadertools/converter/functions/customfunction.h +++ b/modules/editor/shadertools/converter/functions/customfunction.h @@ -4,6 +4,7 @@ #include "function.h" #include +#include class CustomFunction : public ShaderNode { A_OBJECT(CustomFunction, ShaderNode, Graph) @@ -14,67 +15,62 @@ class CustomFunction : public ShaderNode { void exposeFunction(const TString &path) { QFile file(path.data()); if(file.open(QIODevice::ReadOnly | QIODevice::Text)) { - QDomDocument doc; - if(doc.setContent(&file)) { - QDomElement function = doc.documentElement(); + pugi::xml_document doc; + if(doc.load_string(file.readAll().data()).status == pugi::status_ok) { + pugi::xml_node function = doc.document_element(); - m_funcName = QFileInfo(function.attribute("name")).baseName().toStdString(); + m_funcName = QFileInfo(function.attribute("name").as_string()).baseName().toStdString(); setTypeName(m_funcName); setName(m_funcName); - QDomNode n = function.firstChild(); - while(!n.isNull()) { - QDomElement element = n.toElement(); + pugi::xml_node element = function.first_child(); + while(element) { + std::string name(element.name()); + if(name == "inputs") { // parse inputs + pugi::xml_node inputElement = element.first_child(); + while(inputElement) { + TString inputName = inputElement.attribute("name").as_string(); - if(element.tagName() == "inputs") { // parse inputs - QDomNode inputNode = element.firstChild(); - while(!inputNode.isNull()) { - QDomElement inputElement = inputNode.toElement(); - - QString inputName = inputElement.attribute("name"); - - uint32_t type = convertType(inputElement.attribute("type")); + uint32_t type = convertType(inputElement.attribute("type").as_string()); m_inputs.push_back(make_pair(inputName.toStdString(), type)); - QString value = inputElement.attribute("embedded"); + TString value = inputElement.attribute("embedded").as_string(); if(value.isEmpty()) { - value = inputElement.attribute("default"); + value = inputElement.attribute("default").as_string(); if(!value.isEmpty()) { - setProperty(qPrintable(inputName), convertValue(type, value)); + setProperty(inputName.data(), convertValue(type, value.data())); } } else { - setProperty(qPrintable(inputName), TString(value.toStdString())); + setProperty(inputName.data(), TString(value.toStdString())); } - inputNode = inputNode.nextSibling(); + inputElement = inputElement.next_sibling(); } - } else if(element.tagName() == "outputs") { - QDomNode outputNode = element.firstChild(); - while(!outputNode.isNull()) { - QDomElement outputElement = outputNode.toElement(); - - QString outputName = outputElement.attribute("name"); + } else if(name == "outputs") { + pugi::xml_node outputElement = element.first_child(); + while(outputElement) { + TString outputName = outputElement.attribute("name").as_string(); - uint32_t type = convertType(outputElement.attribute("type")); + uint32_t type = convertType(outputElement.attribute("type").as_string()); m_outputs.push_back(make_pair(outputName.toStdString(), type)); - outputNode = outputNode.nextSibling(); + outputElement = outputElement.next_sibling(); } - } else if(element.tagName() == "code") { - m_func = element.text().toStdString(); + } else if(name == "code") { + m_func = element.child_value(); } - n = n.nextSibling(); + element = element.next_sibling(); } - - ShaderNode::createParams(); } + + ShaderNode::createParams(); } } - uint32_t convertType(const QString &type) const { + uint32_t convertType(const TString &type) const { if(type == "int") { return MetaType::INTEGER; } else if(type == "float") { @@ -144,7 +140,7 @@ class CustomFunction : public ShaderNode { QString defaultValue(const TString &key, uint32_t &type) const override { Variant value = property(key.data()); - if(value.type() == QVariant::String) { + if(value.type() == MetaType::STRING) { return value.toString().data(); } diff --git a/modules/editor/shadertools/converter/shaderbuilder.cpp b/modules/editor/shadertools/converter/shaderbuilder.cpp index 82866f77e..616f826b2 100644 --- a/modules/editor/shadertools/converter/shaderbuilder.cpp +++ b/modules/editor/shadertools/converter/shaderbuilder.cpp @@ -1,7 +1,5 @@ #include "shaderbuilder.h" -#include - #include #include @@ -21,6 +19,7 @@ #include "../../config.h" #include +#include #define FORMAT_VERSION 14 @@ -442,40 +441,39 @@ bool ShaderBuilder::parseShaderFormat(const QString &path, VariantMap &user, int QByteArray data = file.readAll(); file.close(); - QDomDocument doc; - if(doc.setContent(data)) { + pugi::xml_document doc; + if(doc.load_string(data)) { std::map shaders; int materialType = Material::Surface; int lightingModel = Material::Unlit; - QDomElement shader = doc.documentElement(); - - uint32_t version = shader.attribute("version", "0").toInt(); - - QDomNode n = shader.firstChild(); - while(!n.isNull()) { - QDomElement element = n.toElement(); - if(!element.isNull()) { - if(element.tagName() == gFragment || element.tagName() == gVertex || element.tagName() == gGeometry) { - shaders[element.tagName().toStdString()] = element.text().toStdString(); - } else if(element.tagName() == gCompute) { - shaders[element.tagName().toStdString()] = element.text().toStdString(); - } else if(element.tagName() == gProperties) { - if(!parseProperties(element, user)) { - return false; - } - } else if(element.tagName() == gPass) { - user[PROPERTIES] = parsePassProperties(element, materialType, lightingModel); + pugi::xml_node shader = doc.document_element(); - if(version == 0) { - parsePassV0(element, user); - } else if(version >= 11) { - parsePassV11(element, user); - } + uint32_t version = shader.attribute("version").as_int(); + + pugi::xml_node element = shader.first_child(); + while(element) { + std::string name(element.name()); + if(name == gFragment || name == gVertex || name == gGeometry) { + shaders[name] = element.child_value(); + } else if(name == gCompute) { + shaders[name] = element.child_value(); + } else if(name == gProperties) { + if(!parseProperties(element, user)) { + return false; + } + } else if(name == gPass) { + user[PROPERTIES] = parsePassProperties(element, materialType, lightingModel); + + if(version == 0) { + parsePassV0(element, user); + } else if(version >= 11) { + parsePassV11(element, user); } } - n = n.nextSibling(); + + element = element.next_sibling(); } if(version != FORMAT_VERSION) { @@ -612,46 +610,44 @@ Uniform ShaderBuilder::uniformFromVariant(const Variant &variant) { } bool ShaderBuilder::saveShaderFormat(const QString &path, const std::map &shaders, const VariantMap &user) { - QDomDocument xml; - QDomElement shader = xml.createElement("shader"); + pugi::xml_document xml; + pugi::xml_node shader = xml.append_child("shader"); - shader.setAttribute("version", FORMAT_VERSION); + shader.append_attribute("version") = FORMAT_VERSION; - QDomElement properties(xml.createElement(gProperties)); + pugi::xml_node properties = shader.append_child(gProperties); auto it = user.find(UNIFORMS); if(it != user.end()) { for(auto &p : it->second.toList()) { - QDomElement property(xml.createElement("property")); + pugi::xml_node property = properties.append_child("property"); Uniform uniform = uniformFromVariant(p); - property.setAttribute("name", uniform.name.data()); - property.setAttribute("type", uniform.typeName.data()); + property.append_attribute("name") = uniform.name.data(); + property.append_attribute("type") = uniform.typeName.data(); if(uniform.count > 1) { - property.setAttribute("count", uniform.count); + property.append_attribute("count") = uniform.count; } - - properties.appendChild(property); } } it = user.find(TEXTURES); if(it != user.end()) { for(auto &p : it->second.toList()) { - QDomElement property(xml.createElement("property")); + pugi::xml_node property = properties.append_child("property"); VariantList fields = p.toList(); auto field = fields.begin(); TString path = field->toString(); if(!path.isEmpty()) { - property.setAttribute("path", path.data()); + property.append_attribute("path") = path.data(); } ++field; - property.setAttribute("name", field->toString().data()); + property.append_attribute("name") = field->toString().data(); ++field; - property.setAttribute("binding", field->toInt() - UNIFORM_BIND); + property.append_attribute("binding") = field->toInt() - UNIFORM_BIND; ++field; int32_t flags = field->toInt(); @@ -659,40 +655,34 @@ bool ShaderBuilder::saveShaderFormat(const QString &path, const std::mapsecond.toList(); auto field = fields.begin(); - pass.setAttribute("type", toMaterialType(field->toInt()).data()); + pass.append_attribute("type") = toMaterialType(field->toInt()).data(); ++field; - pass.setAttribute(gTwoSided, field->toBool() ? "true" : "false"); + pass.append_attribute(gTwoSided) = field->toBool(); ++field; - pass.setAttribute(gLightModel, toLightModel(field->toInt()).data()); + pass.append_attribute(gLightModel) = toLightModel(field->toInt()).data(); ++field; - pass.setAttribute(gWireFrame, field->toBool() ? "true" : "false"); + pass.append_attribute(gWireFrame) = field->toBool(); } it = user.find(BLENDSTATE); @@ -715,7 +705,7 @@ bool ShaderBuilder::saveShaderFormat(const QString &path, const std::maptoBool(); - saveBlendState(state, xml, pass); + saveBlendState(state, pass); } it = user.find(DEPTHSTATE); @@ -731,7 +721,7 @@ bool ShaderBuilder::saveShaderFormat(const QString &path, const std::maptoBool(); if(state.enabled) { - saveDepthState(state, xml, pass); + saveDepthState(state, pass); } } @@ -766,100 +756,87 @@ bool ShaderBuilder::saveShaderFormat(const QString &path, const std::maptoBool(); if(state.enabled) { - saveStencilState(state, xml, pass); + saveStencilState(state, pass); } } - shader.appendChild(pass); - - xml.appendChild(shader); - - QFile saveFile(path); - if(saveFile.open(QIODevice::WriteOnly)) { - saveFile.write(xml.toByteArray(4)); - saveFile.close(); - } - - return true; + return xml.save_file(qPrintable(path), " "); } -bool ShaderBuilder::parseProperties(const QDomElement &element, VariantMap &user) { +bool ShaderBuilder::parseProperties(const pugi::xml_node &parent, VariantMap &user) { int binding = UNIFORM_BIND; VariantList textures; VariantList uniforms; - QDomNode p = element.firstChild(); - while(!p.isNull()) { - QDomElement property = p.toElement(); - if(!property.isNull()) { - // Parse properties - QString name = property.attribute(gName); - QString type = property.attribute("type"); - if(name.isEmpty() || type.isEmpty()) { - return false; - } + pugi::xml_node property = parent.first_child(); + while(property) { + // Parse properties + TString name = property.attribute(gName).as_string(); + TString type = property.attribute("type").as_string(); + if(name.isEmpty() || type.isEmpty()) { + return false; + } - if(type.toLower() == gTexture2D || type.toLower() == gTextureCubemap) { // Texture sampler - ++binding; + if(type.toLower() == gTexture2D || type.toLower() == gTextureCubemap) { // Texture sampler + ++binding; - int flags = 0; - if(property.attribute("target", "false") == "true") { - flags |= ShaderRootNode::Target; - } - if(type.toLower() == gTextureCubemap) { - flags |= ShaderRootNode::Cube; - } + int flags = 0; + if(property.attribute("target").as_bool()) { + flags |= ShaderRootNode::Target; + } + if(type.toLower() == gTextureCubemap) { + flags |= ShaderRootNode::Cube; + } - int localBinding = binding; - QString b = property.attribute("binding"); - if(!b.isEmpty()) { - localBinding = UNIFORM_BIND + b.toInt(); - } + int localBinding = binding; + TString binding(property.attribute("binding").as_string()); + if(!binding.isEmpty()) { + localBinding = UNIFORM_BIND + binding.toInt(); + } - VariantList texture; - texture.push_back((flags & ShaderRootNode::Target) ? "" : TString(property.attribute("path").toStdString())); // path - texture.push_back(TString(name.toStdString())); // name - texture.push_back(localBinding); // binding - texture.push_back(flags); // flags - - textures.push_back(texture); - } else { // Uniform - VariantList data; - - uint32_t size = 0; - uint32_t count = property.attribute("count", "1").toInt(); - Variant value; - if(type == "bool") { - value = Variant(bool(property.attribute(gValue).toInt() != 0)); - size = sizeof(bool); - } else if(type == "int") { - value = Variant(property.attribute(gValue).toInt()); - size = sizeof(int); - } else if(type == "float") { - value = Variant(property.attribute(gValue).toFloat()); - size = sizeof(float); - } else if(type == "vec2") { - value = Variant(Vector2(1.0f)); - size = sizeof(Vector2); - } else if(type == "vec3") { - value = Variant(Vector3(1.0f)); - size = sizeof(Vector3); - } else if(type == "vec4") { - value = Variant(Vector4(1.0f)); - size = sizeof(Vector4); - } else if(type == "mat4") { - value = Variant(Matrix4()); - size = sizeof(Matrix4); - } + VariantList texture; + texture.push_back((flags & ShaderRootNode::Target) ? "" : TString(property.attribute("path").as_string())); // path + texture.push_back(TString(name.toStdString())); // name + texture.push_back(localBinding); // binding + texture.push_back(flags); // flags + + textures.push_back(texture); + } else { // Uniform + VariantList data; + + uint32_t size = 0; + uint32_t count = property.attribute("count").as_int(1); + Variant value; + if(type == "bool") { + value = Variant(bool(property.attribute(gValue).as_int() != 0)); + size = sizeof(bool); + } else if(type == "int") { + value = Variant(property.attribute(gValue).as_int()); + size = sizeof(int); + } else if(type == "float") { + value = Variant(property.attribute(gValue).as_float()); + size = sizeof(float); + } else if(type == "vec2") { + value = Variant(Vector2(1.0f)); + size = sizeof(Vector2); + } else if(type == "vec3") { + value = Variant(Vector3(1.0f)); + size = sizeof(Vector3); + } else if(type == "vec4") { + value = Variant(Vector4(1.0f)); + size = sizeof(Vector4); + } else if(type == "mat4") { + value = Variant(Matrix4()); + size = sizeof(Matrix4); + } - data.push_back(value); - data.push_back(size * count); - data.push_back(TString(name.toStdString())); + data.push_back(value); + data.push_back(size * count); + data.push_back(TString(name.toStdString())); - uniforms.push_back(data); - } + uniforms.push_back(data); } - p = p.nextSibling(); + property = property.next_sibling(); } user[TEXTURES] = textures; @@ -868,51 +845,49 @@ bool ShaderBuilder::parseProperties(const QDomElement &element, VariantMap &user return true; } -VariantList ShaderBuilder::parsePassProperties(const QDomElement &element, int &materialType, int &lightingModel) { +VariantList ShaderBuilder::parsePassProperties(const pugi::xml_node &element, int &materialType, int &lightingModel) { VariantList properties; - materialType = toMaterialType(element.attribute("type").toStdString()); + materialType = toMaterialType(element.attribute("type").as_string()); properties.push_back(materialType); - properties.push_back(element.attribute(gTwoSided, "true") == "true"); - lightingModel = toLightModel(element.attribute(gLightModel).toStdString()); + properties.push_back(element.attribute(gTwoSided).as_bool(true)); + lightingModel = toLightModel(element.attribute(gLightModel).as_string()); properties.push_back(lightingModel); - properties.push_back(element.attribute(gWireFrame, "false") == "true"); + properties.push_back(element.attribute(gWireFrame).as_bool()); return properties; } -void ShaderBuilder::parsePassV0(const QDomElement &element, VariantMap &user) { +void ShaderBuilder::parsePassV0(const pugi::xml_node &parent, VariantMap &user) { static const QMap blend = { {"Opaque", OldBlendType::Opaque}, {"Additive", OldBlendType::Additive}, {"Translucent", OldBlendType::Translucent}, }; - Material::BlendState blendState = fromBlendMode(blend.value(element.attribute("blendMode"), OldBlendType::Opaque)); + Material::BlendState blendState = fromBlendMode(blend.value(parent.attribute("blendMode").as_string(), OldBlendType::Opaque)); user[BLENDSTATE] = toVariant(blendState); Material::DepthState depthState; - depthState.enabled = (element.attribute("depthTest", "true") == "true"); - depthState.writeEnabled = (element.attribute("depthWrite", "true") == "true"); + depthState.enabled = parent.attribute("depthTest").as_bool(true); + depthState.writeEnabled = parent.attribute("depthWrite").as_bool(true); user[DEPTHSTATE] = toVariant(depthState); } -void ShaderBuilder::parsePassV11(const QDomElement &element, VariantMap &user) { - QDomNode p = element.firstChild(); - while(!p.isNull()) { - QDomElement element = p.toElement(); - if(!element.isNull()) { - if(element.tagName() == "blend") { - user[BLENDSTATE] = toVariant(loadBlendState(element)); - } else if(element.tagName() == "depth") { - user[DEPTHSTATE] = toVariant(loadDepthState(element)); - } else if(element.tagName() == "stencil") { - user[STENCILSTATE] = toVariant(loadStencilState(element)); - } +void ShaderBuilder::parsePassV11(const pugi::xml_node &parent, VariantMap &user) { + pugi::xml_node element = parent.first_child(); + while(element) { + std::string name(element.name()); + if(name == "blend") { + user[BLENDSTATE] = toVariant(loadBlendState(element)); + } else if(name == "depth") { + user[DEPTHSTATE] = toVariant(loadDepthState(element)); + } else if(name == "stencil") { + user[STENCILSTATE] = toVariant(loadStencilState(element)); } - p = p.nextSiblingElement(); + element = element.next_sibling(); } } @@ -1270,170 +1245,164 @@ Material::BlendState ShaderBuilder::fromBlendMode(uint32_t mode) { return blendState; } -Material::BlendState ShaderBuilder::loadBlendState(const QDomElement &element) { +Material::BlendState ShaderBuilder::loadBlendState(const pugi::xml_node &element) { Material::BlendState blendState; - if(!element.isNull()) { + if(element) { blendState.enabled = true; - if(element.hasAttribute(gOperation)) { - blendState.alphaOperation = toBlendOp(element.attribute(gOperation, "Add").toStdString()); + if(element.attribute(gOperation)) { + blendState.alphaOperation = toBlendOp(element.attribute(gOperation).as_string("Add")); blendState.colorOperation = blendState.alphaOperation; } else { - blendState.alphaOperation = toBlendOp(element.attribute(gAlphaOperation, "Add").toStdString()); - blendState.colorOperation = toBlendOp(element.attribute(gColorOperation, "Add").toStdString()); + blendState.alphaOperation = toBlendOp(element.attribute(gAlphaOperation).as_string("Add")); + blendState.colorOperation = toBlendOp(element.attribute(gColorOperation).as_string("Add")); } - if(element.hasAttribute(gDestination)) { - blendState.destinationAlphaBlendMode = toBlendFactor(element.attribute(gDestination, "One").toStdString()); + if(element.attribute(gDestination)) { + blendState.destinationAlphaBlendMode = toBlendFactor(element.attribute(gDestination).as_string("One")); blendState.destinationColorBlendMode = blendState.destinationAlphaBlendMode; } else { - blendState.destinationAlphaBlendMode = toBlendFactor(element.attribute(gAlphaDestination, "One").toStdString()); - blendState.destinationColorBlendMode = toBlendFactor(element.attribute(gColorDestination, "One").toStdString()); + blendState.destinationAlphaBlendMode = toBlendFactor(element.attribute(gAlphaDestination).as_string("One")); + blendState.destinationColorBlendMode = toBlendFactor(element.attribute(gColorDestination).as_string("One")); } - if(element.hasAttribute(gSource)) { - blendState.sourceAlphaBlendMode = toBlendFactor(element.attribute(gSource, "Zero").toStdString()); + if(element.attribute(gSource)) { + blendState.sourceAlphaBlendMode = toBlendFactor(element.attribute(gSource).as_string("Zero")); blendState.sourceColorBlendMode = blendState.sourceAlphaBlendMode; } else { - blendState.sourceAlphaBlendMode = toBlendFactor(element.attribute(gAlphaSource, "Zero").toStdString()); - blendState.sourceColorBlendMode = toBlendFactor(element.attribute(gColorSource, "Zero").toStdString()); + blendState.sourceAlphaBlendMode = toBlendFactor(element.attribute(gAlphaSource).as_string("Zero")); + blendState.sourceColorBlendMode = toBlendFactor(element.attribute(gColorSource).as_string("Zero")); } } return blendState; } -void ShaderBuilder::saveBlendState(const Material::BlendState &state, QDomDocument &document, QDomElement &parent) { +void ShaderBuilder::saveBlendState(const Material::BlendState &state, pugi::xml_node &parent) { if(state.enabled) { - QDomElement blend(document.createElement("blend")); + pugi::xml_node blend = parent.append_child("blend"); if(state.colorOperation == state.alphaOperation) { - blend.setAttribute(gOperation, toBlendOp(state.colorOperation).data()); + blend.append_attribute(gOperation) = toBlendOp(state.colorOperation).data(); } else { - blend.setAttribute(gAlphaOperation, toBlendOp(state.alphaOperation).data()); - blend.setAttribute(gColorOperation, toBlendOp(state.colorOperation).data()); + blend.append_attribute(gAlphaOperation) = toBlendOp(state.alphaOperation).data(); + blend.append_attribute(gColorOperation) = toBlendOp(state.colorOperation).data(); } if(state.destinationColorBlendMode == state.destinationAlphaBlendMode) { - blend.setAttribute(gDestination, toBlendFactor(state.destinationColorBlendMode).data()); + blend.append_attribute(gDestination) = toBlendFactor(state.destinationColorBlendMode).data(); } else { - blend.setAttribute(gAlphaDestination, toBlendFactor(state.destinationAlphaBlendMode).data()); - blend.setAttribute(gColorDestination, toBlendFactor(state.destinationColorBlendMode).data()); + blend.append_attribute(gAlphaDestination) = toBlendFactor(state.destinationAlphaBlendMode).data(); + blend.append_attribute(gColorDestination) = toBlendFactor(state.destinationColorBlendMode).data(); } if(state.sourceColorBlendMode == state.sourceAlphaBlendMode) { - blend.setAttribute(gSource, toBlendFactor(state.sourceColorBlendMode).data()); + blend.append_attribute(gSource) = toBlendFactor(state.sourceColorBlendMode).data(); } else { - blend.setAttribute(gAlphaSource, toBlendFactor(state.sourceAlphaBlendMode).data()); - blend.setAttribute(gColorSource, toBlendFactor(state.sourceColorBlendMode).data()); + blend.append_attribute(gAlphaSource) = toBlendFactor(state.sourceAlphaBlendMode).data(); + blend.append_attribute(gColorSource) = toBlendFactor(state.sourceColorBlendMode).data(); } - - parent.appendChild(blend); } } -Material::DepthState ShaderBuilder::loadDepthState(const QDomElement &element) { +Material::DepthState ShaderBuilder::loadDepthState(const pugi::xml_node &element) { Material::DepthState depthState; - if(!element.isNull()) { - depthState.enabled = (element.attribute(gTest, "true") == "true"); - depthState.writeEnabled = (element.attribute(gWrite, "true") == "true"); - depthState.compareFunction = toTestFunction(element.attribute(gCompare, "Less").toStdString()); + if(element) { + depthState.enabled = element.attribute(gTest).as_bool(true); + depthState.writeEnabled = element.attribute(gWrite).as_bool(true); + depthState.compareFunction = toTestFunction(element.attribute(gCompare).as_string("Less")); } return depthState; } -void ShaderBuilder::saveDepthState(const Material::DepthState &state, QDomDocument &document, QDomElement &parent) { - QDomElement depth(document.createElement("depth")); - - depth.setAttribute(gCompare, toTestFunction(state.compareFunction).data()); - depth.setAttribute(gWrite, state.writeEnabled ? "true" : "false"); - depth.setAttribute(gTest, state.enabled ? "true" : "false"); +void ShaderBuilder::saveDepthState(const Material::DepthState &state, pugi::xml_node &parent) { + pugi::xml_node depth = parent.append_child("depth"); - parent.appendChild(depth); + depth.append_attribute(gCompare) = toTestFunction(state.compareFunction).data(); + depth.append_attribute(gWrite) = state.writeEnabled; + depth.append_attribute(gTest) = state.enabled; } -Material::StencilState ShaderBuilder::loadStencilState(const QDomElement &element) { +Material::StencilState ShaderBuilder::loadStencilState(const pugi::xml_node &element) { Material::StencilState stencilState; - if(!element.isNull()) { - if(element.hasAttribute(gCompare)) { - stencilState.compareFunctionBack = toTestFunction(element.attribute(gCompare, "Always").toStdString()); + if(element) { + if(element.attribute(gCompare)) { + stencilState.compareFunctionBack = toTestFunction(element.attribute(gCompare).as_string("Always")); stencilState.compareFunctionFront = stencilState.compareFunctionBack; } else { - stencilState.compareFunctionBack = toTestFunction(element.attribute(gCompBack, "Always").toStdString()); - stencilState.compareFunctionFront = toTestFunction(element.attribute(gCompFront, "Always").toStdString()); + stencilState.compareFunctionBack = toTestFunction(element.attribute(gCompBack).as_string("Always")); + stencilState.compareFunctionFront = toTestFunction(element.attribute(gCompFront).as_string("Always")); } - if(element.hasAttribute(gFail)) { - stencilState.failOperationBack = toTestFunction(element.attribute(gFail, "Keep").toStdString()); + if(element.attribute(gFail)) { + stencilState.failOperationBack = toTestFunction(element.attribute(gFail).as_string("Keep")); stencilState.failOperationFront = stencilState.compareFunctionBack; } else { - stencilState.failOperationBack = toActionType(element.attribute(gFailBack, "Keep").toStdString()); - stencilState.failOperationFront = toActionType(element.attribute(gFailFront, "Keep").toStdString()); + stencilState.failOperationBack = toActionType(element.attribute(gFailBack).as_string("Keep")); + stencilState.failOperationFront = toActionType(element.attribute(gFailFront).as_string("Keep")); } - if(element.hasAttribute(gPass)) { - stencilState.passOperationBack = toTestFunction(element.attribute(gPass, "Keep").toStdString()); + if(element.attribute(gPass)) { + stencilState.passOperationBack = toTestFunction(element.attribute(gPass).as_string("Keep")); stencilState.passOperationFront = stencilState.passOperationBack; } else { - stencilState.passOperationBack = toActionType(element.attribute(gPassBack, "Keep").toStdString()); - stencilState.passOperationFront = toActionType(element.attribute(gPassFront, "Keep").toStdString()); + stencilState.passOperationBack = toActionType(element.attribute(gPassBack).as_string("Keep")); + stencilState.passOperationFront = toActionType(element.attribute(gPassFront).as_string("Keep")); } - if(element.hasAttribute(gPass)) { - stencilState.zFailOperationBack = toTestFunction(element.attribute(gZFail, "Keep").toStdString()); + if(element.attribute(gZFail)) { + stencilState.zFailOperationBack = toTestFunction(element.attribute(gZFail).as_string("Keep")); stencilState.zFailOperationFront = stencilState.zFailOperationBack; } else { - stencilState.zFailOperationBack = toActionType(element.attribute(gZFailBack, "Keep").toStdString()); - stencilState.zFailOperationFront = toActionType(element.attribute(gZFailFront, "Keep").toStdString()); + stencilState.zFailOperationBack = toActionType(element.attribute(gZFailBack).as_string("Keep")); + stencilState.zFailOperationFront = toActionType(element.attribute(gZFailFront).as_string("Keep")); } - stencilState.readMask = element.attribute(gReadMask, "1").toInt(); - stencilState.writeMask = element.attribute(gWriteMask, "1").toInt(); - stencilState.reference = element.attribute(gReference, "0").toInt(); - stencilState.enabled = (element.attribute(gTest, "true") == "true"); + stencilState.readMask = element.attribute(gReadMask).as_int(1); + stencilState.writeMask = element.attribute(gWriteMask).as_int(1); + stencilState.reference = element.attribute(gReference).as_int(0); + stencilState.enabled = element.attribute(gTest).as_bool(true); } return stencilState; } -void ShaderBuilder::saveStencilState(const Material::StencilState &state, QDomDocument &document, QDomElement &parent) { - QDomElement stencil(document.createElement("stencil")); +void ShaderBuilder::saveStencilState(const Material::StencilState &state, pugi::xml_node &parent) { + pugi::xml_node stencil = parent.append_child("stencil"); if(state.compareFunctionBack == state.compareFunctionFront) { - stencil.setAttribute(gCompare, toTestFunction(state.compareFunctionBack).data()); + stencil.append_attribute(gCompare) = toTestFunction(state.compareFunctionBack).data(); } else { - stencil.setAttribute(gCompBack, toTestFunction(state.compareFunctionBack).data()); - stencil.setAttribute(gCompFront, toTestFunction(state.compareFunctionFront).data()); + stencil.append_attribute(gCompBack) = toTestFunction(state.compareFunctionBack).data(); + stencil.append_attribute(gCompFront) = toTestFunction(state.compareFunctionFront).data(); } if(state.failOperationBack == state.failOperationFront) { - stencil.setAttribute(gFail, toTestFunction(state.failOperationBack).data()); + stencil.append_attribute(gFail) = toTestFunction(state.failOperationBack).data(); } else { - stencil.setAttribute(gFailBack, toActionType(state.failOperationBack).data()); - stencil.setAttribute(gFailFront, toActionType(state.failOperationFront).data()); + stencil.append_attribute(gFailBack) = toActionType(state.failOperationBack).data(); + stencil.append_attribute(gFailFront) = toActionType(state.failOperationFront).data(); } if(state.passOperationBack == state.passOperationFront) { - stencil.setAttribute(gPass, toTestFunction(state.passOperationBack).data()); + stencil.append_attribute(gPass) = toTestFunction(state.passOperationBack).data(); } else { - stencil.setAttribute(gPassBack, toActionType(state.passOperationBack).data()); - stencil.setAttribute(gPassFront, toActionType(state.passOperationFront).data()); + stencil.append_attribute(gPassBack) = toActionType(state.passOperationBack).data(); + stencil.append_attribute(gPassFront) = toActionType(state.passOperationFront).data(); } if(state.zFailOperationBack == state.zFailOperationFront) { - stencil.setAttribute(gZFail, toTestFunction(state.zFailOperationBack).data()); + stencil.append_attribute(gZFail) = toTestFunction(state.zFailOperationBack).data(); } else { - stencil.setAttribute(gZFailBack, toActionType(state.zFailOperationBack).data()); - stencil.setAttribute(gZFailFront, toActionType(state.zFailOperationFront).data()); + stencil.append_attribute(gZFailBack) = toActionType(state.zFailOperationBack).data(); + stencil.append_attribute(gZFailFront) = toActionType(state.zFailOperationFront).data(); } - stencil.setAttribute(gReadMask, state.readMask); - stencil.setAttribute(gWriteMask, state.writeMask); - stencil.setAttribute(gReference, state.reference); - stencil.setAttribute(gTest, state.enabled ? "true" : "false"); - - parent.appendChild(stencil); + stencil.append_attribute(gReadMask) = state.readMask; + stencil.append_attribute(gWriteMask) = state.writeMask; + stencil.append_attribute(gReference) = state.reference; + stencil.append_attribute(gTest) = state.enabled; } diff --git a/modules/editor/shadertools/converter/shaderbuilder.h b/modules/editor/shadertools/converter/shaderbuilder.h index 6c838a937..746b5b4f6 100644 --- a/modules/editor/shadertools/converter/shaderbuilder.h +++ b/modules/editor/shadertools/converter/shaderbuilder.h @@ -107,14 +107,14 @@ class ShaderBuilder : public AssetConverter { static Material::BlendState fromBlendMode(uint32_t mode); - static Material::BlendState loadBlendState(const QDomElement &element); - static void saveBlendState(const Material::BlendState &state, QDomDocument &document, QDomElement &parent); + static Material::BlendState loadBlendState(const pugi::xml_node &element); + static void saveBlendState(const Material::BlendState &state, pugi::xml_node &parent); - static Material::DepthState loadDepthState(const QDomElement &element); - static void saveDepthState(const Material::DepthState &state, QDomDocument &document, QDomElement &parent); + static Material::DepthState loadDepthState(const pugi::xml_node &element); + static void saveDepthState(const Material::DepthState &state, pugi::xml_node &parent); - static Material::StencilState loadStencilState(const QDomElement &element); - static void saveStencilState(const Material::StencilState &state, QDomDocument &document, QDomElement &parent); + static Material::StencilState loadStencilState(const pugi::xml_node &element); + static void saveStencilState(const Material::StencilState &state, pugi::xml_node &parent); static void compileData(VariantMap &data); @@ -135,11 +135,11 @@ class ShaderBuilder : public AssetConverter { bool parseShaderFormat(const QString &path, VariantMap &data, int flags = false); bool saveShaderFormat(const QString &path, const std::map &shaders, const VariantMap &user); - bool parseProperties(const QDomElement &element, VariantMap &user); + bool parseProperties(const pugi::xml_node &parent, VariantMap &user); - VariantList parsePassProperties(const QDomElement &element, int &materialType, int &lightingModel); - void parsePassV0(const QDomElement &element, VariantMap &user); - void parsePassV11(const QDomElement &element, VariantMap &user); + VariantList parsePassProperties(const pugi::xml_node &element, int &materialType, int &lightingModel); + void parsePassV0(const pugi::xml_node &parent, VariantMap &user); + void parsePassV11(const pugi::xml_node &parent, VariantMap &user); static TString loadShader(const TString &data, const TString &define, const PragmaMap &pragmas); diff --git a/modules/editor/shadertools/converter/shadergraph.cpp b/modules/editor/shadertools/converter/shadergraph.cpp index 38a45c3cc..3672266f0 100644 --- a/modules/editor/shadertools/converter/shadergraph.cpp +++ b/modules/editor/shadertools/converter/shadergraph.cpp @@ -256,14 +256,15 @@ void ShaderGraph::scanForCustomFunctions() { for(auto &path : files) { QFile file(path); if(file.open(QIODevice::ReadOnly | QIODevice::Text)) { - QDomDocument doc; - if(doc.setContent(&file)) { - QDomElement function = doc.documentElement(); + pugi::xml_document doc; + if(doc.load_string(file.readAll().data()).status == pugi::status_ok) { - QString name = function.attribute("name"); + pugi::xml_node function = doc.document_element(); + + TString name = function.attribute("name").as_string(); m_nodeTypes.push_back(name.toStdString()); - m_exposedFunctions[QFileInfo(name).baseName().toStdString()] = path.toStdString(); + m_exposedFunctions[QFileInfo(name.data()).baseName().toStdString()] = path.toStdString(); } } } diff --git a/modules/editor/shadertools/shadertools.qbs b/modules/editor/shadertools/shadertools.qbs index 180526eaa..483f5695d 100644 --- a/modules/editor/shadertools/shadertools.qbs +++ b/modules/editor/shadertools/shadertools.qbs @@ -23,6 +23,7 @@ Project { "../../../thirdparty/next/inc/math", "../../../thirdparty/next/inc/core", "../../../thirdparty/spirvcross/src", + "../../../thirdparty/pugixml/src", "../../../thirdparty/glsl", "../../../modules/editor/grapheditor", "../../../modules/uikit/includes"