implement saving of procedure nodes

This commit is contained in:
sshumakov3
2020-12-22 16:33:09 +03:00
parent 7e00c60964
commit 4072ae4ffe
5 changed files with 156 additions and 67 deletions

View File

@@ -13,6 +13,7 @@
#include <functional>
#include <limits>
#include <cstdint>
#include <array>
#include <QSpinBox>
#include <QDoubleSpinBox>
@@ -72,7 +73,11 @@ public:
data_ptr.reset();
return data_ptr;
}
return std::make_shared<GenericData<Ty, type_id, type_name, C, D>>(value);
else
{
return std::make_shared<GenericData<Ty, type_id, type_name, C, D>>(value);
}
}
void to_json(QWidget* widget, QJsonObject& json_obj, const std::string& name) override
@@ -219,14 +224,38 @@ struct NoDefaultWidget
};
struct TypeFactory
{
static NodeData* create(const std::string& id)
{
const Creators_t::const_iterator iter = static_creators().find(id);
return iter == static_creators().end() ? 0 : (*iter->second)();
}
private:
typedef NodeData* Creator_t();
typedef std::map<std::string, Creator_t*> Creators_t;
static Creators_t& static_creators() { static Creators_t s_creators; return s_creators; }
template<typename T> struct Register
{
static NodeData* create() { return new T(); };
static Creator_t* init_creator(const std::string& id) { return static_creators()[id] = create; }
static Creator_t* creator;
};
};
#define DECLARE_NODE_DATA_TYPE(TYPE_ID, TYPE_NAME, UNDERLYING_TYPE, DEFAULT_WIDGET_GEN) \
constexpr char TYPE_ID##_typeid[] = #TYPE_ID; \
constexpr char TYPE_ID##_typename[] = #TYPE_NAME; \
using TYPE_NAME##Data = GenericData<UNDERLYING_TYPE, \
TYPE_ID##_typeid, TYPE_ID##_typename, toQStringGeneric<UNDERLYING_TYPE>, DEFAULT_WIDGET_GEN>;
TYPE_ID##_typeid, TYPE_ID##_typename, toQStringGeneric<UNDERLYING_TYPE>, DEFAULT_WIDGET_GEN>; \
template<> TypeFactory::Creator_t* TypeFactory::Register<GenericData<UNDERLYING_TYPE, \
TYPE_ID##_typeid, TYPE_ID##_typename, toQStringGeneric<UNDERLYING_TYPE>, DEFAULT_WIDGET_GEN>>::creator = TypeFactory::Register<GenericData<UNDERLYING_TYPE, \
TYPE_ID##_typeid, TYPE_ID##_typename, toQStringGeneric<UNDERLYING_TYPE>, DEFAULT_WIDGET_GEN>>::init_creator(#TYPE_ID);
DECLARE_NODE_DATA_TYPE(int, Integer, int, DefaultIntWidget)
DECLARE_NODE_DATA_TYPE(double, Decimal, double, DefaultDecimalWidget)
DECLARE_NODE_DATA_TYPE(bool, Boolean, bool, DefaultBooleanWidget)
DECLARE_NODE_DATA_TYPE(string, String, std::string, DefaultStringWidget)
@@ -238,11 +267,10 @@ DECLARE_NODE_DATA_TYPE(vec3, Vector3D, glm::vec3, NoDefaultWidget)
DECLARE_NODE_DATA_TYPE(vec4, Vector4D, glm::vec4, NoDefaultWidget)
DECLARE_NODE_DATA_TYPE(mat4, Matrix4x4, glm::mat4, NoDefaultWidget)
DECLARE_NODE_DATA_TYPE(mat3, Matrix3x3, glm::mat3, NoDefaultWidget)
DECLARE_NODE_DATA_TYPE(quat, Quaternion, glm::quat, NoDefaultWidget)
//DECLARE_NODE_DATA_TYPE(quat, Quaternion, glm::quat, NoDefaultWidget)
DECLARE_NODE_DATA_TYPE(any, Any, std::nullptr_t, NoDefaultWidget);
DECLARE_NODE_DATA_TYPE(procedure, Procedure, std::string, DefaultProcedureWidget);
#endif //NOGGIT_GENERICDATA_HPP

View File

@@ -34,66 +34,7 @@ LogicProcedureNode::LogicProcedureNode()
connect(static_cast<ProcedureSelector*>(_procedure_default), &ProcedureSelector::entry_updated
,[this](QString const& path)
{
_scene_path = path;
clearDynamicPorts();
setValidationState(NodeValidationState::Valid);
_scene = new NodeScene(::registerDataModels(), this);
if (!_scene->load(QDir("./scripts/").absoluteFilePath(path)))
{
setValidationState(NodeValidationState::Error);
setValidationMessage("Error: Scene loading failed.");
return;
}
_scene->validate();
// handle in signature
auto begin_node = _scene->getBeginNode();
if (!begin_node)
{
setValidationState(NodeValidationState::Error);
setValidationMessage("Error: No entry point found. (Begin node missing)");
return;
}
auto in_signature = static_cast<LogicBeginNode*>(begin_node->nodeDataModel())->getInSignature();
for (int i = 1; i < in_signature->size(); ++i)
{
auto& port = (*in_signature)[i];
if (!port.connected)
continue;
addPort<LogicData>(PortType::In, port.caption, true);
_in_ports[_in_ports.size() - 1].data_type = port.data_type->instantiate();
emit portAdded();
}
auto return_node = _scene->getReturnNode();
if (return_node)
{
auto out_signature = static_cast<LogicReturnNode*>(return_node->nodeDataModel())->getOutSignature();
for (int i = 1; i < out_signature->size(); ++i)
{
auto& port = (*out_signature)[i];
if (!port.connected)
continue;
addPort<LogicData>(PortType::Out, port.caption, true);
_out_ports[_out_ports.size() - 1].data_type = port.data_type->instantiate();
emit portAdded();
}
}
delete _scene;
_scene = nullptr;
emit visualsNeedUpdate();
setProcedure(path);
});
addPort<LogicData>(PortType::Out, "Logic", true, ConnectionPolicy::One);
@@ -112,6 +53,8 @@ void LogicProcedureNode::compute()
{
setValidationState(NodeValidationState::Error);
setValidationMessage("Error: Scene loading failed.");
_out_ports[0].out_value = std::make_shared<LogicData>(false);
Q_EMIT dataUpdated(0);
return;
}
@@ -124,6 +67,8 @@ void LogicProcedureNode::compute()
{
setValidationState(NodeValidationState::Error);
setValidationMessage("Error: No entry point found. (Begin node missing)");
_out_ports[0].out_value = std::make_shared<LogicData>(false);
Q_EMIT dataUpdated(0);
return;
}
@@ -171,6 +116,9 @@ void LogicProcedureNode::compute()
setValidationMessage(message.str().c_str());
delete _scene;
_out_ports[0].out_value = std::make_shared<LogicData>(false);
Q_EMIT dataUpdated(0);
return;
sig_index_ret++;
@@ -181,13 +129,12 @@ void LogicProcedureNode::compute()
Q_EMIT dataUpdated(i);
}
_out_ports[0].out_value = std::make_shared<LogicData>(true);
Q_EMIT dataUpdated(0);
delete _scene;
}
_out_ports[0].out_value = std::make_shared<LogicData>(true);
Q_EMIT dataUpdated(0);
}
@@ -195,12 +142,48 @@ QJsonObject LogicProcedureNode::save() const
{
QJsonObject json_obj = BaseNode::save();
json_obj["procedure"] = static_cast<ProcedureSelector*>(_procedure_default)->getPath();
json_obj["n_dynamic_in_ports"] = static_cast<int>(_in_ports.size() - 2);
json_obj["n_dynamic_out_ports"] = static_cast<int>(_out_ports.size() - 1);
for (int i = 2; i < _in_ports.size(); ++i)
{
json_obj[("in_port_" + std::to_string(i)).c_str()] = _in_ports[i].data_type->type().id;
json_obj[("in_port_" + std::to_string(i) + "_caption").c_str()] = _in_ports[i].caption;
}
for (int i = 1; i < _out_ports.size(); ++i)
{
json_obj[("out_port_" + std::to_string(i)).c_str()] = _out_ports[i].data_type->type().id;
json_obj[("out_port_" + std::to_string(i) + "_caption").c_str()] = _out_ports[i].caption;
}
return json_obj;
}
void LogicProcedureNode::restore(const QJsonObject& json_obj)
{
BaseNode::restore(json_obj);
_scene_path = json_obj["procedure"].toString();
static_cast<ProcedureSelector*>(_procedure_default)->setPath(_scene_path);
for (int i = 0; i < json_obj["n_dynamic_in_ports"].toInt(); ++i)
{
addPort<LogicData>(PortType::In, json_obj[("in_port_" + std::to_string(i + 2) + "_caption").c_str()].toString(), true);
_in_ports[_in_ports.size() - 1].data_type = TypeFactory::create(json_obj[("in_port_" + std::to_string(i + 2)).c_str()].toString().toStdString())->instantiate();
emit portAdded();
}
for (int i = 0; i < json_obj["n_dynamic_out_ports"].toInt(); ++i)
{
addPort<LogicData>(PortType::Out, json_obj[("out_port_" + std::to_string(i + 1) + "_caption").c_str()].toString(), true);
_out_ports[_out_ports.size() - 1].data_type = TypeFactory::create(json_obj[("out_port_" + std::to_string(i + 1)).c_str()].toString().toStdString())->instantiate();
emit portAdded();
}
}
NodeValidationState LogicProcedureNode::validate()
@@ -244,3 +227,67 @@ void LogicProcedureNode::clearDynamicPorts()
}
}
void LogicProcedureNode::setProcedure(const QString& path)
{
_scene_path = path;
clearDynamicPorts();
setValidationState(NodeValidationState::Valid);
_scene = new NodeScene(::registerDataModels(), this);
if (!_scene->load(QDir("./scripts/").absoluteFilePath(path)))
{
setValidationState(NodeValidationState::Error);
setValidationMessage("Error: Scene loading failed.");
return;
}
_scene->validate();
// handle in signature
auto begin_node = _scene->getBeginNode();
if (!begin_node)
{
setValidationState(NodeValidationState::Error);
setValidationMessage("Error: No entry point found. (Begin node missing)");
return;
}
auto in_signature = static_cast<LogicBeginNode*>(begin_node->nodeDataModel())->getInSignature();
for (int i = 1; i < in_signature->size(); ++i)
{
auto& port = (*in_signature)[i];
if (!port.connected)
continue;
addPort<LogicData>(PortType::In, port.caption, true);
_in_ports[_in_ports.size() - 1].data_type = port.data_type->instantiate();
emit portAdded();
}
auto return_node = _scene->getReturnNode();
if (return_node)
{
auto out_signature = static_cast<LogicReturnNode*>(return_node->nodeDataModel())->getOutSignature();
for (int i = 1; i < out_signature->size(); ++i)
{
auto& port = (*out_signature)[i];
if (!port.connected)
continue;
addPort<LogicData>(PortType::Out, port.caption, true);
_out_ports[_out_ports.size() - 1].data_type = port.data_type->instantiate();
emit portAdded();
}
}
delete _scene;
_scene = nullptr;
emit visualsNeedUpdate();
}

View File

@@ -30,6 +30,7 @@ namespace noggit
NodeValidationState validate() override;
QJsonObject save() const override;
void restore(QJsonObject const& json_obj) override;
void setProcedure(QString const& path);
private:

View File

@@ -106,3 +106,14 @@ ProcedureSelector::ProcedureSelector(QWidget *parent)
model->setNameFilters(filters_search);
});
}
QString ProcedureSelector::getPath()
{
return static_cast<QPushButton*>(layout()->itemAt(0)->widget())->text();
}
void ProcedureSelector::setPath(QString const& path)
{
static_cast<QPushButton*>(layout()->itemAt(0)->widget())->setText(path);
}

View File

@@ -15,6 +15,8 @@ namespace noggit
public:
explicit ProcedureSelector(QWidget* parent = nullptr);
QString getPath();
void setPath(QString const& path);
signals:
void entry_updated(QString const& entry);