stop script execution on error
implement dynamic types to MathNode
This commit is contained in:
2
src/external/NodeEditor/src/Node.cpp
vendored
2
src/external/NodeEditor/src/Node.cpp
vendored
@@ -315,6 +315,6 @@ recalculateVisuals() const
|
||||
//Recalculate the nodes visuals. A data change can result in the node taking more space than before, so this forces a recalculate+repaint on the affected node
|
||||
_nodeGraphicsObject->setGeometryChanged();
|
||||
_nodeGeometry.recalculateSize();
|
||||
_nodeGraphicsObject->update();
|
||||
_nodeGraphicsObject->update(_nodeGeometry.boundingRect());
|
||||
_nodeGraphicsObject->moveConnections();
|
||||
}
|
||||
@@ -167,7 +167,11 @@ QWidget* BaseNode::portDefaultValueWidget(PortType port_type, PortIndex port_ind
|
||||
|
||||
void BaseNode::inputConnectionDeleted(const Connection& connection)
|
||||
{
|
||||
auto default_widget = _in_ports[connection.getPortIndex(PortType::In)].default_widget;
|
||||
auto& port = _in_ports[connection.getPortIndex(PortType::In)];
|
||||
|
||||
port.connected = false;
|
||||
|
||||
auto default_widget = port.default_widget;
|
||||
|
||||
if (default_widget)
|
||||
default_widget->setVisible(true);
|
||||
@@ -175,12 +179,29 @@ void BaseNode::inputConnectionDeleted(const Connection& connection)
|
||||
|
||||
void BaseNode::inputConnectionCreated(const Connection& connection)
|
||||
{
|
||||
auto default_widget = _in_ports[connection.getPortIndex(PortType::In)].default_widget;
|
||||
auto& port = _in_ports[connection.getPortIndex(PortType::In)];
|
||||
|
||||
port.connected = true;
|
||||
|
||||
auto default_widget = port.default_widget;
|
||||
|
||||
if (default_widget)
|
||||
default_widget->setVisible(false);
|
||||
}
|
||||
|
||||
void BaseNode::outputConnectionCreated(const Connection& connection)
|
||||
{
|
||||
auto& port = _out_ports[connection.getPortIndex(PortType::Out)];
|
||||
port.connected = true;
|
||||
}
|
||||
|
||||
void BaseNode::outputConnectionDeleted(const Connection& connection)
|
||||
{
|
||||
auto& port = _out_ports[connection.getPortIndex(PortType::Out)];
|
||||
port.connected = false;
|
||||
}
|
||||
|
||||
|
||||
QJsonObject BaseNode::save() const
|
||||
{
|
||||
QJsonObject json_obj;
|
||||
|
||||
@@ -114,6 +114,8 @@ namespace noggit
|
||||
|
||||
void inputConnectionCreated(Connection const& connection) override;
|
||||
void inputConnectionDeleted(Connection const& connection) override;
|
||||
void outputConnectionCreated(Connection const& connection) override;
|
||||
void outputConnectionDeleted(Connection const& connection) override;
|
||||
|
||||
protected:
|
||||
|
||||
@@ -132,6 +134,13 @@ namespace noggit
|
||||
bool caption_visible,
|
||||
ConnectionPolicy out_policy = ConnectionPolicy::Many);
|
||||
|
||||
template<typename T>
|
||||
void addPort(PortType port_type,
|
||||
PortIndex port_index,
|
||||
QString const& caption,
|
||||
bool caption_visible,
|
||||
ConnectionPolicy out_policy = ConnectionPolicy::Many);
|
||||
|
||||
void deletePort(PortType port_type, PortIndex port_index);
|
||||
void deleteDefaultWidget(PortType port_type, PortIndex port_index);
|
||||
|
||||
|
||||
@@ -26,4 +26,28 @@ void noggit::Red::NodeEditor::Nodes::BaseNode::addPort(PortType port_type,
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void noggit::Red::NodeEditor::Nodes::BaseNode::addPort(PortType port_type,
|
||||
PortIndex port_index,
|
||||
const QString &caption,
|
||||
bool caption_visible,
|
||||
ConnectionPolicy out_policy)
|
||||
{
|
||||
if (port_type == PortType::In)
|
||||
{
|
||||
auto port = _in_ports.emplace(_in_ports.begin() + port_index, caption, caption_visible);
|
||||
port->data_type = std::make_unique<T>();
|
||||
}
|
||||
else if (port_type == PortType::Out)
|
||||
{
|
||||
auto port = _out_ports.emplace(_out_ports.begin() + port_index, caption, caption_visible);
|
||||
port->data_type = std::make_unique<T>();
|
||||
port->connection_policy = out_policy;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw std::logic_error("Incorrect port type or port type None.");
|
||||
}
|
||||
}
|
||||
|
||||
#endif // NOGGIT_BASENODE_INL
|
||||
@@ -255,6 +255,7 @@ private:
|
||||
template<> TypeFactory::Creator_t* TypeFactory::Register<TYPE_NAME##Data>::creator = TypeFactory::Register<TYPE_NAME##Data>::init_creator(#TYPE_ID);
|
||||
|
||||
DECLARE_NODE_DATA_TYPE(int, Integer, int, DefaultIntWidget)
|
||||
DECLARE_NODE_DATA_TYPE(uint, UnsignedInteger, unsigned int, DefaultIntWidget)
|
||||
|
||||
DECLARE_NODE_DATA_TYPE(double, Decimal, double, DefaultDecimalWidget)
|
||||
DECLARE_NODE_DATA_TYPE(bool, Boolean, bool, DefaultBooleanWidget)
|
||||
@@ -270,6 +271,7 @@ DECLARE_NODE_DATA_TYPE(mat3, Matrix3x3, glm::mat3, NoDefaultWidget)
|
||||
DECLARE_NODE_DATA_TYPE(quat, Quaternion, glm::quat, NoDefaultWidget)
|
||||
|
||||
DECLARE_NODE_DATA_TYPE(any, Any, std::nullptr_t, NoDefaultWidget);
|
||||
DECLARE_NODE_DATA_TYPE(undefined, Undefined, std::nullptr_t, NoDefaultWidget);
|
||||
DECLARE_NODE_DATA_TYPE(procedure, Procedure, std::string, DefaultProcedureWidget);
|
||||
|
||||
|
||||
|
||||
@@ -90,7 +90,14 @@ void LogicProcedureNode::compute()
|
||||
sig_index++;
|
||||
}
|
||||
|
||||
_scene->execute();
|
||||
if (!_scene->execute())
|
||||
{
|
||||
setValidationState(NodeValidationState::Error);
|
||||
setValidationMessage("Error: Some error occured while executing procedure.");
|
||||
delete _scene;
|
||||
_scene = nullptr;
|
||||
return;
|
||||
}
|
||||
|
||||
auto return_node = _scene->getReturnNode();
|
||||
|
||||
@@ -177,14 +184,22 @@ void LogicProcedureNode::restore(const QJsonObject& json_obj)
|
||||
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();
|
||||
|
||||
std::unique_ptr<NodeData> type;
|
||||
type.reset(TypeFactory::create(json_obj[("in_port_" + std::to_string(i + 2)).c_str()].toString().toStdString()));
|
||||
|
||||
_in_ports[_in_ports.size() - 1].data_type = std::move(type);
|
||||
emit portAdded(PortType::In, _in_ports.size() - 1);
|
||||
}
|
||||
|
||||
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();
|
||||
|
||||
std::unique_ptr<NodeData> type;
|
||||
type.reset(TypeFactory::create(json_obj[("out_port_" + std::to_string(i + 1)).c_str()].toString().toStdString()));
|
||||
|
||||
_out_ports[_out_ports.size() - 1].data_type = std::move(type);
|
||||
emit portAdded(PortType::Out, _out_ports.size() - 1);
|
||||
}
|
||||
|
||||
|
||||
@@ -2,9 +2,11 @@
|
||||
#include "BaseNode.inl"
|
||||
#include "noggit/Red/NodeEditor/Nodes/Data/GenericData.hpp"
|
||||
#include <cmath>
|
||||
#include <stdexcept>
|
||||
|
||||
using namespace noggit::Red::NodeEditor::Nodes;
|
||||
|
||||
|
||||
MathNode::MathNode()
|
||||
: BaseNode()
|
||||
{
|
||||
@@ -27,15 +29,11 @@ MathNode::MathNode()
|
||||
}
|
||||
);
|
||||
|
||||
addPort<DecimalData>(PortType::In, "Value", true);
|
||||
_first = new QDoubleSpinBox(&_embedded_widget);
|
||||
addDefaultWidget(_first, PortType::In, 0);
|
||||
addPort<AnyData>(PortType::In, "Any*", true);
|
||||
|
||||
addPort<DecimalData>(PortType::In, "Value", true);
|
||||
_second = new QDoubleSpinBox(&_embedded_widget);
|
||||
addDefaultWidget(_second, PortType::In, 1);
|
||||
addPort<AnyData>(PortType::In, "Any*", true);
|
||||
|
||||
addPort<DecimalData>(PortType::Out, "Value", true);
|
||||
addPort<UndefinedData>(PortType::Out, "Undefined", true);
|
||||
}
|
||||
|
||||
void MathNode::compute()
|
||||
@@ -43,63 +41,333 @@ void MathNode::compute()
|
||||
auto first_shared = _in_ports[0].in_value.lock();
|
||||
auto second_shared = _in_ports[1].in_value.lock();
|
||||
|
||||
auto first = static_cast<DecimalData*>(first_shared.get());
|
||||
auto second = static_cast<DecimalData*>(second_shared.get());
|
||||
auto first_type_id = _in_ports[0].data_type->type().id;
|
||||
auto second_type_id = _in_ports[1].data_type->type().id;
|
||||
|
||||
// handle defaults
|
||||
double first_number = first ? first->value() : _first->value();
|
||||
double second_number = second ? second->value() : _second->value();
|
||||
int winning_type = std::max(_type_map[first_type_id.toStdString()], _type_map[second_type_id.toStdString()]);
|
||||
int winning_port = first_type_id < second_type_id;
|
||||
|
||||
setValidationState(NodeValidationState::Warning);
|
||||
|
||||
double result = 0.0;
|
||||
|
||||
switch (_operation->currentIndex())
|
||||
switch (winning_type)
|
||||
{
|
||||
case 0:
|
||||
result = first_number + second_number;
|
||||
{
|
||||
auto first = commonCast<int>(first_shared.get());
|
||||
auto second = commonCast<int>(second_shared.get());
|
||||
handleOperation(first, second);
|
||||
break;
|
||||
}
|
||||
case 1:
|
||||
result = first_number - second_number;
|
||||
{
|
||||
auto first = commonCast<unsigned int>(first_shared.get());
|
||||
auto second = commonCast<unsigned int>(second_shared.get());
|
||||
handleOperation(first, second);
|
||||
break;
|
||||
}
|
||||
case 2:
|
||||
result = first_number * second_number;
|
||||
{
|
||||
auto first = commonCast<double>(first_shared.get());
|
||||
auto second = commonCast<double>(second_shared.get());
|
||||
handleOperation(first, second);
|
||||
break;
|
||||
}
|
||||
case 3:
|
||||
result = first_number / second_number;
|
||||
{
|
||||
auto first = commonCast<std::string>(first_shared.get());
|
||||
auto second = commonCast<std::string>(second_shared.get());
|
||||
handleOperation(first, second);
|
||||
break;
|
||||
case 4:
|
||||
result = std::fmod(first_number, second_number);
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
_out_ports[0].out_value = std::make_shared<DecimalData>(result);
|
||||
|
||||
setValidationMessage(("Debug: " + std::to_string(result)).c_str());
|
||||
|
||||
Q_EMIT dataUpdated(0);
|
||||
}
|
||||
|
||||
QJsonObject MathNode::save() const
|
||||
{
|
||||
QJsonObject modelJson;
|
||||
QJsonObject json_obj = BaseNode::save();
|
||||
|
||||
modelJson["name"] = name();
|
||||
modelJson["caption"] = caption();
|
||||
modelJson["default_first"] = _first->value();
|
||||
modelJson["default_second"] = _second->value();
|
||||
modelJson["operation"] = _operation->currentIndex();
|
||||
auto first_type_id = _in_ports[0].data_type->type().id;
|
||||
json_obj["first_type_id"] = first_type_id;
|
||||
|
||||
return modelJson;
|
||||
auto second_type_id = _in_ports[1].data_type->type().id;
|
||||
json_obj["second_type_id"] = second_type_id;
|
||||
|
||||
json_obj["ret_type_id"] = _out_ports[0].data_type->type().id;
|
||||
|
||||
json_obj["operation"] = _operation->currentIndex();
|
||||
|
||||
return json_obj;
|
||||
}
|
||||
|
||||
void MathNode::restore(const QJsonObject& json_obj)
|
||||
{
|
||||
setName(json_obj["name"].toString());
|
||||
setCaption(json_obj["caption"].toString());
|
||||
_first->setValue(json_obj["default_first"].toDouble());
|
||||
_second->setValue(json_obj["default_second"].toDouble());
|
||||
BaseNode::restore(json_obj);
|
||||
|
||||
auto first_type_id = json_obj["first_type_id"].toString();
|
||||
|
||||
_in_ports[0].data_type.reset(TypeFactory::create(first_type_id.toStdString()));
|
||||
_in_ports[0].caption = _in_ports[0].data_type->type().name;
|
||||
|
||||
auto second_type_id = json_obj["second_type_id"].toString();
|
||||
|
||||
_in_ports[1].data_type.reset(TypeFactory::create(second_type_id.toStdString()));
|
||||
_in_ports[1].caption = _in_ports[1].data_type->type().name;
|
||||
|
||||
auto ret_type_id = json_obj["ret_type_id"].toString().toStdString();
|
||||
_out_ports[0].data_type.reset(TypeFactory::create(ret_type_id));
|
||||
_out_ports[0].caption = _out_ports[0].data_type->type().name;
|
||||
|
||||
_operation->setCurrentIndex(json_obj["operation"].toInt());
|
||||
}
|
||||
|
||||
void MathNode::inputConnectionCreated(const Connection& connection)
|
||||
{
|
||||
BaseNode::inputConnectionCreated(connection);
|
||||
|
||||
PortIndex port_index = connection.getPortIndex(PortType::In);
|
||||
PortIndex other_port_index = port_index ? 0 : 1;
|
||||
|
||||
bool supported_type = false;
|
||||
|
||||
// Disconnect types which are not supported by the node.
|
||||
if (_type_map.find(connection.dataType(PortType::Out).id.toStdString()) == _type_map.end())
|
||||
{
|
||||
deletePort(PortType::In, port_index);
|
||||
addPort<AnyData>(PortType::In, port_index, "Any*", true);
|
||||
emit portAdded(PortType::In, port_index);
|
||||
|
||||
deletePort(PortType::Out, 0);
|
||||
addPort<UndefinedData>(PortType::Out, "Undefined", true);
|
||||
emit portAdded(PortType::Out, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
_in_ports[port_index].data_type.reset(TypeFactory::create(connection.dataType(PortType::Out).id.toStdString()));
|
||||
_in_ports[port_index].caption = _in_ports[port_index].data_type->type().name;
|
||||
|
||||
auto other_type_id = _in_ports[other_port_index].data_type->type().id.toStdString();
|
||||
if (other_type_id != "any")
|
||||
{
|
||||
auto result_type_id = std::max(_type_map[_in_ports[port_index].data_type->type().id.toStdString()], _type_map[other_type_id]);
|
||||
|
||||
std::string result_type_id_str;
|
||||
|
||||
for (auto& it : _type_map)
|
||||
{
|
||||
if (it.second == result_type_id)
|
||||
{
|
||||
result_type_id_str = it.first;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (result_type_id_str == "string" && _operation->currentIndex())
|
||||
{
|
||||
setValidationState(NodeValidationState::Error);
|
||||
setValidationMessage("Error: String type only supports concatenation (Add).");
|
||||
deletePort(PortType::Out, 0);
|
||||
addPort<UndefinedData>(PortType::Out, 0, "Undefined", true);
|
||||
emit portAdded(PortType::Out, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
if (_out_ports[0].data_type->type().id.toStdString() != result_type_id_str)
|
||||
{
|
||||
deletePort(PortType::Out, 0);
|
||||
auto new_type = TypeFactory::create(result_type_id_str);
|
||||
addPort<UndefinedData>(PortType::Out, 0, new_type->type().name, true);
|
||||
_out_ports[0].data_type.reset(new_type);
|
||||
emit portAdded(PortType::Out, 0);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void MathNode::inputConnectionDeleted(const Connection& connection)
|
||||
{
|
||||
BaseNode::inputConnectionDeleted(connection);
|
||||
|
||||
PortIndex port_index = connection.getPortIndex(PortType::In);
|
||||
deletePort(PortType::In, port_index);
|
||||
addPort<AnyData>(PortType::In, port_index, "Any*", true);
|
||||
emit portAdded(PortType::In, port_index);
|
||||
|
||||
deletePort(PortType::Out, 0);
|
||||
addPort<UndefinedData>(PortType::Out, "Undefined", true);
|
||||
emit portAdded(PortType::Out, 0);
|
||||
}
|
||||
|
||||
NodeValidationState MathNode::validate()
|
||||
{
|
||||
setValidationState(NodeValidationState::Valid);
|
||||
|
||||
if (_out_ports[0].data_type->type().id == "undefined")
|
||||
{
|
||||
setValidationState(NodeValidationState::Error);
|
||||
setValidationMessage("Error: result of operation is of undefined type.");
|
||||
return _validation_state;
|
||||
}
|
||||
|
||||
return _validation_state;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T MathNode::commonCast(NodeData* data)
|
||||
{
|
||||
int type_id_to;
|
||||
|
||||
if constexpr (std::is_same<T, int>::value)
|
||||
type_id_to = 0;
|
||||
else if constexpr (std::is_same<T, unsigned int>::value)
|
||||
type_id_to = 1;
|
||||
else if constexpr (std::is_same<T, double>::value)
|
||||
type_id_to = 2;
|
||||
else if constexpr (std::is_same<T, std::string>::value)
|
||||
type_id_to = 3;
|
||||
|
||||
if constexpr (std::is_same<T, std::string>::value)
|
||||
{
|
||||
switch (_type_map[data->type().id.toStdString()])
|
||||
{
|
||||
case 0:
|
||||
return std::move(std::to_string(static_cast<IntegerData*>(data)->value()));
|
||||
break;
|
||||
case 1:
|
||||
return std::move(std::to_string(static_cast<UnsignedIntegerData*>(data)->value()));
|
||||
break;
|
||||
case 2:
|
||||
return std::move(std::to_string(static_cast<DecimalData*>(data)->value()));
|
||||
break;
|
||||
case 3:
|
||||
return static_cast<StringData*>(data)->value();
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (_type_map[data->type().id.toStdString()])
|
||||
{
|
||||
case 0:
|
||||
return static_cast<T>(static_cast<IntegerData*>(data)->value());
|
||||
break;
|
||||
case 1:
|
||||
return static_cast<T>(static_cast<UnsignedIntegerData*>(data)->value());
|
||||
break;
|
||||
case 2:
|
||||
return static_cast<T>(static_cast<DecimalData*>(data)->value());
|
||||
break;
|
||||
case 3:
|
||||
throw std::logic_error("Casting String type to numeric types is not supported in MathNode.");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
throw std::logic_error("Invalid types for MathNode operation.");
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void MathNode::handleOperation(T first, T second)
|
||||
{
|
||||
setValidationState(NodeValidationState::Warning);
|
||||
|
||||
T result;
|
||||
|
||||
if constexpr (!std::is_same<T, std::string>::value)
|
||||
{
|
||||
switch (_operation->currentIndex())
|
||||
{
|
||||
case 0:
|
||||
result = first + first;
|
||||
break;
|
||||
case 1:
|
||||
result = first - first;
|
||||
break;
|
||||
case 2:
|
||||
result = first * first;
|
||||
break;
|
||||
case 3:
|
||||
if constexpr (std::is_same<T, int>::value || std::is_same<T, unsigned int>::value)
|
||||
{
|
||||
if (!second)
|
||||
{
|
||||
setValidationState(NodeValidationState::Error);
|
||||
setValidationMessage("Error: division by zero");
|
||||
return;
|
||||
}
|
||||
|
||||
result = first / first;
|
||||
}
|
||||
else
|
||||
{
|
||||
result = first / first;
|
||||
}
|
||||
break;
|
||||
case 4:
|
||||
if constexpr (std::is_same<T, int>::value || std::is_same<T, unsigned int>::value)
|
||||
{
|
||||
if (!second)
|
||||
{
|
||||
setValidationState(NodeValidationState::Error);
|
||||
setValidationMessage("Error: modulo by zero");
|
||||
return;
|
||||
}
|
||||
|
||||
result = first % second;
|
||||
}
|
||||
else
|
||||
{
|
||||
result = std::fmod(first, first);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (_operation->currentIndex())
|
||||
{
|
||||
case 0:
|
||||
result = first + first;
|
||||
break;
|
||||
default:
|
||||
throw std::logic_error("String type only supports concatenation in MathNode.");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if constexpr (std::is_same<T, int>::value)
|
||||
{
|
||||
_out_ports[0].out_value = std::make_shared<IntegerData>(result);
|
||||
|
||||
setValidationMessage(("Debug: " + std::to_string(result)).c_str());
|
||||
|
||||
Q_EMIT dataUpdated(0);
|
||||
}
|
||||
else if constexpr (std::is_same<T, unsigned int>::value)
|
||||
{
|
||||
_out_ports[0].out_value = std::make_shared<UnsignedIntegerData>(result);
|
||||
|
||||
setValidationMessage(("Debug: " + std::to_string(result)).c_str());
|
||||
|
||||
Q_EMIT dataUpdated(0);
|
||||
}
|
||||
else if constexpr (std::is_same<T, double>::value)
|
||||
{
|
||||
_out_ports[0].out_value = std::make_shared<DecimalData>(result);
|
||||
|
||||
setValidationMessage(("Debug: " + std::to_string(result)).c_str());
|
||||
|
||||
Q_EMIT dataUpdated(0);
|
||||
}
|
||||
else if constexpr (std::is_same<T, std::string>::value)
|
||||
{
|
||||
_out_ports[0].out_value = std::make_shared<StringData>(result);
|
||||
|
||||
setValidationMessage(("Debug: " + result).c_str());
|
||||
|
||||
Q_EMIT dataUpdated(0);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
#include "BaseNode.hpp"
|
||||
|
||||
#include <QDoubleSpinBox>
|
||||
#include <unordered_map>
|
||||
#include <QComboBox>
|
||||
|
||||
using QtNodes::PortType;
|
||||
@@ -26,12 +26,25 @@ namespace noggit
|
||||
MathNode();
|
||||
void compute() override;
|
||||
QJsonObject save() const override;
|
||||
NodeValidationState validate() override;
|
||||
void restore(QJsonObject const& json_obj) override;
|
||||
|
||||
public Q_SLOTS:
|
||||
void inputConnectionCreated(const Connection& connection) override;
|
||||
void inputConnectionDeleted(const Connection& connection) override;
|
||||
|
||||
protected:
|
||||
QDoubleSpinBox* _first;
|
||||
QDoubleSpinBox* _second;
|
||||
QComboBox* _operation;
|
||||
std::unordered_map<std::string, int> _type_map = {{"int", 0},
|
||||
{"uint", 1},
|
||||
{"double", 2},
|
||||
{"string", 3}};
|
||||
|
||||
template <typename T>
|
||||
T commonCast(NodeData* data);
|
||||
|
||||
template <typename T>
|
||||
void handleOperation(T first, T second);
|
||||
|
||||
};
|
||||
|
||||
|
||||
@@ -15,22 +15,22 @@ LogicBranch::LogicBranch(Node* logic_node)
|
||||
}
|
||||
|
||||
|
||||
void LogicBranch::execute()
|
||||
bool LogicBranch::execute()
|
||||
{
|
||||
_return = false;
|
||||
executeNode(_logic_node, nullptr);
|
||||
return executeNode(_logic_node, nullptr);
|
||||
}
|
||||
|
||||
void LogicBranch::executeNode(Node* node, Node* source_node)
|
||||
bool LogicBranch::executeNode(Node* node, Node* source_node)
|
||||
{
|
||||
if (_return)
|
||||
return;
|
||||
return true;
|
||||
|
||||
auto model = static_cast<BaseNode*>(node->nodeDataModel());
|
||||
auto nodeState = node->nodeState();
|
||||
|
||||
if (model->isComputed())
|
||||
return;
|
||||
return true;
|
||||
|
||||
model->compute();
|
||||
model->setComputed(true);
|
||||
@@ -75,16 +75,16 @@ void LogicBranch::executeNode(Node* node, Node* source_node)
|
||||
loop_model->setComputed(false);
|
||||
}
|
||||
}
|
||||
else if (logic_node_model->name() == "LogicReturnNoDataNode")
|
||||
else if (logic_node_model->name() == "LogicReturnNoDataNode" || logic_node_model->name() == "LogicReturnNode")
|
||||
{
|
||||
_return = true;
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// do not continue further if validation or execution has found a problem
|
||||
if (model->validationState() == NodeValidationState::Error)
|
||||
return;
|
||||
return false;
|
||||
|
||||
// Handle dependant nodes
|
||||
for (int i = 0; i < model->nPorts(PortType::Out); ++i)
|
||||
@@ -108,7 +108,14 @@ void LogicBranch::executeNode(Node* node, Node* source_node)
|
||||
|
||||
auto connected_model = static_cast<BaseNode*>(connected_node->nodeDataModel());
|
||||
|
||||
executeNodeLeaves(connected_node, node); // Execute data node leaves
|
||||
// Execute data node leaves
|
||||
if (!executeNodeLeaves(connected_node, node))
|
||||
{
|
||||
connected_model->setValidationState(NodeValidationState::Error);
|
||||
connected_model->setValidationMessage("Error: dependant leave nodes failed to execute.");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (connected_model->validate() != NodeValidationState::Error)
|
||||
{
|
||||
auto logic_model = static_cast<LogicNodeBase*>(connected_node->nodeDataModel());
|
||||
@@ -120,7 +127,10 @@ void LogicBranch::executeNode(Node* node, Node* source_node)
|
||||
while (it_index >= 0 && it_index < logic_model->getNIteraitons() && !_return)
|
||||
{
|
||||
markNodesComputed(connected_node, false);
|
||||
executeNode(connected_node, node);
|
||||
|
||||
if (!executeNode(connected_node, node))
|
||||
return false;
|
||||
|
||||
logic_model->setComputed(true);
|
||||
it_index = logic_model->getIterationindex();
|
||||
}
|
||||
@@ -129,21 +139,24 @@ void LogicBranch::executeNode(Node* node, Node* source_node)
|
||||
}
|
||||
else // haandle regular nodes
|
||||
{
|
||||
executeNode(connected_node, node);
|
||||
if (!executeNode(connected_node, node))
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void LogicBranch::executeNodeLeaves(Node* node, Node* source_node)
|
||||
bool LogicBranch::executeNodeLeaves(Node* node, Node* source_node)
|
||||
{
|
||||
auto model = static_cast<BaseNode*>(node->nodeDataModel());
|
||||
auto nodeState = node->nodeState();
|
||||
|
||||
if (model->isComputed())
|
||||
return;
|
||||
return true;
|
||||
|
||||
for (int i = 0; i < model->nPorts(PortType::In); ++i)
|
||||
{
|
||||
@@ -168,10 +181,20 @@ void LogicBranch::executeNodeLeaves(Node* node, Node* source_node)
|
||||
continue;
|
||||
}
|
||||
|
||||
executeNodeLeaves(connected_node, node);
|
||||
if (!executeNodeLeaves(connected_node, node))
|
||||
return false;
|
||||
|
||||
if (connected_model->validate() == NodeValidationState::Error)
|
||||
return false;
|
||||
|
||||
connected_model->compute();
|
||||
|
||||
if (connected_model->validationState() == NodeValidationState::Error)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void LogicBranch::markNodesComputed(Node* start_node, bool state)
|
||||
@@ -195,7 +218,6 @@ void LogicBranch::markNodesComputed(Node* start_node, bool state)
|
||||
markNodeLeavesComputed(connected_node, start_node, state);
|
||||
markNodesComputed(connected_node, state);
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -23,14 +23,14 @@ namespace noggit
|
||||
{
|
||||
public:
|
||||
explicit LogicBranch(Node* logic_node);
|
||||
void executeNode(Node* node, Node* source_node);
|
||||
void executeNodeLeaves(Node* node, Node* source_node);
|
||||
bool executeNode(Node* node, Node* source_node);
|
||||
bool executeNodeLeaves(Node* node, Node* source_node);
|
||||
void markNodesComputed(Node* start_node, bool state);
|
||||
void markNodeLeavesComputed(Node* start_node, Node* source_node, bool state);
|
||||
void setCurrentLoop(Node* node) { _loop_stack.push(node); };
|
||||
void unsetCurrentLoop() { _loop_stack.pop(); };
|
||||
Node* getCurrentLoop() { return _loop_stack.empty() ? nullptr : _loop_stack.top(); };
|
||||
void execute();
|
||||
bool execute();
|
||||
|
||||
private:
|
||||
Node* _logic_node;
|
||||
|
||||
@@ -8,13 +8,13 @@
|
||||
using namespace noggit::Red::NodeEditor::Nodes;
|
||||
|
||||
|
||||
void NodeScene::execute()
|
||||
bool NodeScene::execute()
|
||||
{
|
||||
if (!validate())
|
||||
return;
|
||||
return false;
|
||||
|
||||
auto main_branch = LogicBranch(_begin_node);
|
||||
main_branch.execute();
|
||||
return main_branch.execute();
|
||||
}
|
||||
|
||||
bool NodeScene::validate()
|
||||
|
||||
@@ -16,7 +16,7 @@ namespace noggit
|
||||
public:
|
||||
NodeScene(std::shared_ptr<DataModelRegistry> registry,
|
||||
QObject* parent = Q_NULLPTR) : FlowScene(std::move(registry), parent) {};
|
||||
void execute();
|
||||
bool execute();
|
||||
bool validate();
|
||||
|
||||
Node* getBeginNode() {return _begin_node; };
|
||||
|
||||
Reference in New Issue
Block a user