146 lines
4.5 KiB
C++
146 lines
4.5 KiB
C++
#include "graph.h"
|
|
using namespace Xybrid::Data;
|
|
|
|
#include "config/pluginregistry.h"
|
|
using namespace Xybrid::Config;
|
|
|
|
#include "data/project.h"
|
|
#include "uisocket.h"
|
|
#include "mainwindow.h"
|
|
|
|
#include "util/strings.h"
|
|
|
|
#include <QCborMap>
|
|
#include <QCborArray>
|
|
#include <QMetaType>
|
|
#include <QMetaEnum>
|
|
|
|
namespace {
|
|
std::shared_ptr<PluginInfo> inf;
|
|
bool c = PluginRegistry::enqueueRegistration([] {
|
|
auto i = std::make_shared<PluginInfo>();
|
|
i->id = "graph";
|
|
i->displayName = "Subgraph";
|
|
i->createInstance = []{ return std::make_shared<Graph>(); };
|
|
PluginRegistry::registerPlugin(i);
|
|
inf = i;
|
|
});
|
|
}
|
|
|
|
//std::string Graph::pluginName() const { return "Subgraph"; }
|
|
|
|
Graph::Graph() {
|
|
plugin = inf; // harder bind
|
|
}
|
|
|
|
// propagate
|
|
void Graph::reset() { for (auto c : children) c->reset(); }
|
|
|
|
void Graph::saveData(QCborMap& m) {
|
|
// graph properties
|
|
// ... maybe there will be some at some point
|
|
|
|
std::unordered_map<Node*, int> indices;
|
|
{ /* children */ } {
|
|
QCborArray c;
|
|
|
|
int idx = 0;
|
|
for (auto ch : children) {
|
|
if (!ch->plugin) continue;
|
|
indices[ch.get()] = idx++;
|
|
QCborMap chm;
|
|
|
|
chm.insert(QString("id"), QString::fromStdString(ch->plugin->id));
|
|
if (!ch->name.empty()) chm.insert(QString("name"), QString::fromStdString(ch->name));
|
|
chm.insert(QString("x"), ch->x);
|
|
chm.insert(QString("y"), ch->y);
|
|
ch->saveData(chm);
|
|
|
|
c << chm;
|
|
}
|
|
|
|
m.insert(QString("children"), c);
|
|
}
|
|
|
|
{ /* connections */ } {
|
|
// mapped from output to input
|
|
// array { oIdx, dataType, pIdx, iIdx, dataType, pIdx }
|
|
QCborArray cn;
|
|
|
|
for (auto ch : children) {
|
|
if (!ch->plugin) continue; // already skipped over
|
|
int idx = indices[ch.get()];
|
|
for (auto dt : ch->outputs) {
|
|
for (auto op : dt.second) {
|
|
auto o = op.second;
|
|
o->cleanConnections(); // let's just do some groundskeeping here
|
|
for (auto iw : o->connections) {
|
|
auto i = iw.lock();
|
|
QCborArray c;
|
|
c << idx;
|
|
c << Util::enumName(o->dataType());
|
|
c << o->index;
|
|
c << indices[i->owner.lock().get()];
|
|
c << Util::enumName(i->dataType());
|
|
c << i->index;
|
|
cn << c;
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
m.insert(QString("connections"), cn);
|
|
}
|
|
|
|
}
|
|
|
|
void Graph::loadData(QCborMap& m) {
|
|
auto g = std::static_pointer_cast<Graph>(shared_from_this());
|
|
// graph properties (none)
|
|
|
|
{ /* children */ } {
|
|
QCborArray c = m.value("children").toArray();
|
|
|
|
for (auto chmv : c) {
|
|
auto chm = chmv.toMap();
|
|
auto ch = PluginRegistry::createInstance(chm.value("id").toString().toStdString());
|
|
ch->parentTo(g);
|
|
ch->name = chm.value("name").toString().toStdString();
|
|
ch->x = static_cast<int>(chm.value("x").toInteger());
|
|
ch->y = static_cast<int>(chm.value("y").toInteger());
|
|
ch->loadData(chm);
|
|
}
|
|
}
|
|
|
|
{ /* connections */ } {
|
|
QCborArray cn = m.value("connections").toArray();
|
|
|
|
auto pmt = QMetaType::metaObjectForType(QMetaType::type("Xybrid::Data::Port"));
|
|
auto dtm = pmt->enumerator(pmt->indexOfEnumerator("DataType"));
|
|
|
|
for (auto cv : cn) {
|
|
auto c = cv.toArray();
|
|
if (c.empty()) continue;
|
|
auto on = children[static_cast<size_t>(c[0].toInteger())];
|
|
auto in = children[static_cast<size_t>(c[3].toInteger())];
|
|
auto op = on->port(Port::Output, static_cast<Port::DataType>(dtm.keyToValue(c[1].toString().toStdString().c_str())), static_cast<uint8_t>(c[2].toInteger()));
|
|
auto ip = in->port(Port::Input, static_cast<Port::DataType>(dtm.keyToValue(c[4].toString().toStdString().c_str())), static_cast<uint8_t>(c[5].toInteger()));
|
|
if (op && ip) op->connect(ip);
|
|
}
|
|
}
|
|
}
|
|
|
|
void Graph::onParent(std::shared_ptr<Graph>) {
|
|
// propagate project pointer
|
|
for (auto c : children) {
|
|
c->project = project;
|
|
// let this handle the recursion for us, since this is all this function does
|
|
if (c->plugin == inf) c->onParent(c->parent.lock());
|
|
}
|
|
}
|
|
|
|
void Graph::onDoubleClick() {
|
|
emit project->socket->openGraph(this);
|
|
}
|