implement further node functionality. logic break, rework interpreter

This commit is contained in:
sshumakov3
2020-12-08 01:02:26 +03:00
parent eaa5cda65e
commit 43949ac071
19 changed files with 520 additions and 138 deletions

View File

@@ -94,22 +94,16 @@ namespace noggit
QJsonObject save() const override;
void restore(QJsonObject const& json_obj) override;
virtual bool isLogicNode() { return _is_logic_node; };
void setIsLogicNode(bool state) { _is_logic_node = state; };
virtual unsigned int nLogicBranches() { return _n_logic_branches; };
void setNLogicBranches(int n_branches) { _n_logic_branches = n_branches; };
virtual bool isComputed() { return _computed; };
void setComputed(bool state) { _computed = state; };
int logicBranchToExecute() { return _current_logic_branch; };
void setLogicBranchToExecute(int branch) { _current_logic_branch = branch; };
virtual bool isLogicNode() { return false; };
void setValidationMessage(QString const& message){_validation_error = message;};
void setValidationState(NodeValidationState state){_validation_state = state;};
virtual void compute() = 0;
virtual NodeValidationState validate() { return _validation_state; };
bool isComputed() { return _is_computed; };
void setComputed(bool state) { _is_computed = state; };
public Q_SLOTS:
@@ -143,10 +137,7 @@ namespace noggit
NodeValidationState _validation_state = NodeValidationState::Warning;
QString _validation_error = QString("Missing or incorrect inputs");
bool _is_logic_node = false;
unsigned int _n_logic_branches = 1;
int _current_logic_branch = 1;
bool _computed = false;
bool _is_computed = false;
};
}

View File

@@ -44,11 +44,8 @@ ConditionNode::ConditionNode()
void ConditionNode::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 = static_cast<DecimalData*>(_in_ports[0].in_value.lock().get());
auto second = static_cast<DecimalData*>( _in_ports[1].in_value.lock().get());
// handle defaults
double first_number = first ? first->value() : _first->value();
@@ -113,3 +110,4 @@ void ConditionNode::restore(const QJsonObject& json_obj)
}

View File

@@ -46,6 +46,15 @@ struct UnderlyingTypeConvertGeneric
}
};
template<typename T_from>
struct StringConverter
{
static std::string convert(T_from const& value)
{
return std::to_string(value);
}
};
#define DECLARE_TYPE_CONVERTER(DATA_FROM, DATA_TO, UTYPE_FROM, UTYPE_TO) \
@@ -54,6 +63,11 @@ struct UnderlyingTypeConvertGeneric
UnderlyingTypeConvertGeneric<UTYPE_FROM, UTYPE_TO>>;
#define DECLARE_TYPE_CONVERTER_EXT(DATA_FROM, DATA_TO, CONVERT_FUNCTOR) \
using DATA_FROM##To##DATA_TO##TypeConverter = \
GenericTypeConverter<DATA_FROM##Data, DATA_TO##Data, CONVERT_FUNCTOR>;
DECLARE_TYPE_CONVERTER(Decimal, Integer, double, int)
DECLARE_TYPE_CONVERTER(Decimal, Boolean, double, bool)
@@ -62,8 +76,8 @@ DECLARE_TYPE_CONVERTER(Integer, Boolean, int, bool)
DECLARE_TYPE_CONVERTER(Boolean, Integer, bool, int)
DECLARE_TYPE_CONVERTER(Boolean, Decimal, bool, double)
//DECLARE_TYPE_CONVERTER(Decimal, String)
//DECLARE_TYPE_CONVERTER(Integer, String)
DECLARE_TYPE_CONVERTER_EXT(Decimal, String, StringConverter<double>)
DECLARE_TYPE_CONVERTER_EXT(Integer, String, StringConverter<int>)

View File

@@ -0,0 +1,116 @@
// This file is part of Noggit3, licensed under GNU General Public License (version 3).
#include "ForLoopNode.hpp"
#include "BaseNode.inl"
#include "Data/GenericData.hpp"
using namespace noggit::Red::PresetEditor::Nodes;
ForLoopNode::ForLoopNode()
: LogicNodeBase()
{
setName("ForLoopNode");
setCaption("Repeat");
_validation_state = NodeValidationState::Valid;
addPort<LogicData>(PortType::In, "Logic", true);
addWidget(new QLabel(&_embedded_widget), 0);
addPort<IntegerData>(PortType::In, "Times", true);
_n_iterations_default = new QSpinBox(&_embedded_widget);
_n_iterations_default->setMinimum(0);
addWidget(_n_iterations_default, 1);
addPort<LogicData>(PortType::Out, "Logic", true, ConnectionPolicy::One);
addPort<IntegerData>(PortType::Out, "Index", true, ConnectionPolicy::Many);
setIsIterable(true);
}
void ForLoopNode::compute()
{
auto logic = static_cast<LogicData*>(_in_ports[0].in_value.lock().get());
if(!logic->value())
{
setLogicBranchToExecute(-1);
return;
}
auto n_iterations_ptr = static_cast<IntegerData*>(_in_ports[1].in_value.lock().get());
int n_iterations = n_iterations_ptr ? n_iterations_ptr->value() : _n_iterations_default->value();
if (!n_iterations)
{
setIterationIndex(-1);
return;
}
if (_iteration_index == n_iterations)
{
setIterationIndex(-1);
return;
}
_out_ports[0].out_value = std::make_shared<LogicData>(true);
Q_EMIT dataUpdated(0);
_out_ports[1].out_value = std::make_shared<IntegerData>(getIterationindex());
Q_EMIT dataUpdated(1);
setIterationIndex(getIterationindex() + 1);
}
QJsonObject ForLoopNode::save() const
{
QJsonObject json_obj;
json_obj["name"] = name();
json_obj["caption"] = caption();
json_obj["n_iterations"] = _n_iterations_default->value();
return json_obj;
}
void ForLoopNode::restore(const QJsonObject& json_obj)
{
setName(json_obj["name"].toString());
setCaption(json_obj["caption"].toString());
_n_iterations_default->setValue(json_obj["n_iterations"].toInt());
}
NodeValidationState ForLoopNode::validate()
{
setValidationState(NodeValidationState::Valid);
auto logic = static_cast<LogicData*>(_in_ports[0].in_value.lock().get());
if (!logic)
{
setValidationState(NodeValidationState::Error);
setValidationMessage("Error: Failed to evaluate logic input.");
_out_ports[0].out_value = std::make_shared<LogicData>(false);
Q_EMIT dataUpdated(0);
setLogicBranchToExecute(-1);
}
auto n_iterations_ptr = static_cast<IntegerData*>(_in_ports[1].in_value.lock().get());
int n_iterations = n_iterations_ptr ? n_iterations_ptr->value() : _n_iterations_default->value();
if (!n_iterations)
{
setIterationIndex(-1);
}
setIterationIndex(0);
setNIterations(std::max(0, n_iterations));
return _validation_state;
}

View File

@@ -0,0 +1,39 @@
// This file is part of Noggit3, licensed under GNU General Public License (version 3).
#ifndef NOGGIT_FORLOOPNODE_HPP
#define NOGGIT_FORLOOPNODE_HPP
#include "LogicNodeBase.hpp"
using QtNodes::PortType;
using QtNodes::PortIndex;
using QtNodes::NodeData;
using QtNodes::NodeDataType;
using QtNodes::NodeDataModel;
using QtNodes::NodeValidationState;
namespace noggit
{
namespace Red::PresetEditor::Nodes
{
class ForLoopNode : public LogicNodeBase
{
Q_OBJECT
public:
ForLoopNode();
void compute() override;
NodeValidationState validate() override;
QJsonObject save() const override;
void restore(QJsonObject const& json_obj) override;
private:
QSpinBox* _n_iterations_default;
};
}
}
#endif //NOGGIT_FORLOOPNODE_HPP

View File

@@ -6,20 +6,17 @@
using namespace noggit::Red::PresetEditor::Nodes;
LogicBeginNode::LogicBeginNode()
: BaseNode()
: LogicNodeBase()
{
setName("LogicBeginNode");
setCaption("Begin");
_validation_state = NodeValidationState::Valid;
addPort<LogicData>(PortType::Out, "Logic", true, ConnectionPolicy::One);
_is_logic_node = true;
}
void LogicBeginNode::compute()
{
_out_ports[0].out_value = std::make_shared<LogicData>(true);
Q_EMIT dataUpdated(0);
setComputed(true);
}

View File

@@ -1,7 +1,7 @@
#ifndef NOGGIT_LOGICBEGINNODE_HPP
#define NOGGIT_LOGICBEGINNODE_HPP
#include "BaseNode.hpp"
#include "LogicNodeBase.hpp"
using QtNodes::PortType;
using QtNodes::PortIndex;
@@ -15,7 +15,7 @@ namespace noggit
{
namespace Red::PresetEditor::Nodes
{
class LogicBeginNode : public BaseNode
class LogicBeginNode : public LogicNodeBase
{
Q_OBJECT

View File

@@ -0,0 +1,48 @@
// This file is part of Noggit3, licensed under GNU General Public License (version 3).
#include "LogicBreakNode.hpp"
#include "BaseNode.inl"
#include "Data/GenericData.hpp"
using namespace noggit::Red::PresetEditor::Nodes;
LogicBreakNode::LogicBreakNode()
: LogicNodeBase()
{
setName("LogicBreakNode");
setCaption("Break");
_validation_state = NodeValidationState::Valid;
addPort<LogicData>(PortType::In, "Logic", true);
}
void LogicBreakNode::compute()
{
auto logic = static_cast<LogicData*>(_in_ports[0].in_value.lock().get());
setDoBreak(logic->value());
}
NodeValidationState LogicBreakNode::validate()
{
setValidationState(NodeValidationState::Valid);
auto logic = static_cast<LogicData*>(_in_ports[0].in_value.lock().get());
if (!logic)
{
setValidationState(NodeValidationState::Error);
setValidationMessage("Error: Failed to evaluate logic input");
_out_ports[0].out_value = std::make_shared<LogicData>(false);
_out_ports[1].out_value = std::make_shared<LogicData>(false);
Q_EMIT dataUpdated(0);
Q_EMIT dataUpdated(1);
setLogicBranchToExecute(-1);
}
return _validation_state;
}

View File

@@ -0,0 +1,40 @@
// This file is part of Noggit3, licensed under GNU General Public License (version 3).
#ifndef NOGGIT_LOGICBREAKNODE_HPP
#define NOGGIT_LOGICBREAKNODE_HPP
#include "LogicNodeBase.hpp"
using QtNodes::PortType;
using QtNodes::PortIndex;
using QtNodes::NodeData;
using QtNodes::NodeDataType;
using QtNodes::NodeDataModel;
using QtNodes::NodeValidationState;
namespace noggit
{
namespace Red::PresetEditor::Nodes
{
class LogicBreakNode : public LogicNodeBase
{
Q_OBJECT
public:
LogicBreakNode();
void compute() override;
NodeValidationState validate() override;
bool doBreak() { return _do_break; };
bool setDoBreak(bool state) { _do_break = state; };
private:
bool _do_break = false;
};
}
}
#endif //NOGGIT_LOGICBREAKNODE_HPP

View File

@@ -6,10 +6,10 @@
using namespace noggit::Red::PresetEditor::Nodes;
LogicIfNode::LogicIfNode()
: BaseNode()
: LogicNodeBase()
{
setName("LogicIfNode");
setCaption("If / Else");
setCaption("Branch");
_validation_state = NodeValidationState::Valid;
addPort<LogicData>(PortType::In, "Logic", true);
@@ -17,31 +17,12 @@ LogicIfNode::LogicIfNode()
addPort<LogicData>(PortType::Out, "Then", true, ConnectionPolicy::One);
addPort<LogicData>(PortType::Out, "Else", true, ConnectionPolicy::One);
setIsLogicNode(true);
setNLogicBranches(2);
}
void LogicIfNode::compute()
{
auto logic = static_cast<BooleanData*>(_in_ports[0].in_value.lock().get());
if (!logic)
{
setValidationState(NodeValidationState::Error);
setValidationMessage("Error: Failed to evaluate logic input");
_out_ports[0].out_value = std::make_shared<LogicData>(false);
_out_ports[1].out_value = std::make_shared<LogicData>(false);
Q_EMIT dataUpdated(0);
Q_EMIT dataUpdated(1);
setLogicBranchToExecute(-1);
return;
}
setValidationState(NodeValidationState::Valid);
auto logic = static_cast<LogicData*>(_in_ports[0].in_value.lock().get());
if(!logic->value())
{
@@ -49,10 +30,9 @@ void LogicIfNode::compute()
return;
}
auto in_bool = _in_ports[1].in_value.lock();
auto in_bool_ptr = static_cast<BooleanData*>(in_bool.get());
auto in_bool = static_cast<BooleanData*>(_in_ports[1].in_value.lock().get());
if (!in_bool_ptr)
if (!in_bool)
{
setValidationState(NodeValidationState::Error);
setValidationMessage("Missing boolean input.");
@@ -60,7 +40,7 @@ void LogicIfNode::compute()
return;
}
if (in_bool_ptr->value())
if (in_bool->value())
{
_out_ports[0].out_value = std::make_shared<LogicData>(true);
_out_ports[1].out_value = std::make_shared<LogicData>(false);
@@ -77,7 +57,41 @@ void LogicIfNode::compute()
Q_EMIT dataUpdated(1);
setValidationState(NodeValidationState::Warning);
setValidationMessage(in_bool_ptr->value() ? "Debug: true" : "Debug: false");
setValidationMessage(in_bool->value() ? "Debug: true" : "Debug: false");
}
NodeValidationState LogicIfNode::validate()
{
setValidationState(NodeValidationState::Valid);
auto logic = static_cast<LogicData*>(_in_ports[0].in_value.lock().get());
if (!logic)
{
setValidationState(NodeValidationState::Error);
setValidationMessage("Error: Failed to evaluate logic input");
_out_ports[0].out_value = std::make_shared<LogicData>(false);
_out_ports[1].out_value = std::make_shared<LogicData>(false);
Q_EMIT dataUpdated(0);
Q_EMIT dataUpdated(1);
setLogicBranchToExecute(-1);
return _validation_state;
}
auto in_bool = _in_ports[1].in_value.lock();
auto in_bool_ptr = static_cast<BooleanData*>(in_bool.get());
if (!in_bool_ptr)
{
setValidationState(NodeValidationState::Error);
setValidationMessage("Missing boolean input.");
setLogicBranchToExecute(-1);
return _validation_state;
}
return _validation_state;
}

View File

@@ -1,7 +1,7 @@
#ifndef NOGGIT_LOGICIFNODE_HPP
#define NOGGIT_LOGICIFNODE_HPP
#include "BaseNode.hpp"
#include "LogicNodeBase.hpp"
using QtNodes::PortType;
using QtNodes::PortIndex;
@@ -15,13 +15,14 @@ namespace noggit
{
namespace Red::PresetEditor::Nodes
{
class LogicIfNode : public BaseNode
class LogicIfNode : public LogicNodeBase
{
Q_OBJECT
public:
LogicIfNode();
void compute() override;
NodeValidationState validate() override;
};
}

View File

@@ -0,0 +1,63 @@
// This file is part of Noggit3, licensed under GNU General Public License (version 3).
#ifndef NOGGIT_LOGICNODEBASE_HPP
#define NOGGIT_LOGICNODEBASE_HPP
#include "BaseNode.hpp"
using QtNodes::PortType;
using QtNodes::PortIndex;
using QtNodes::NodeData;
using QtNodes::NodeDataType;
using QtNodes::NodeDataModel;
using QtNodes::NodeValidationState;
namespace noggit
{
namespace Red::PresetEditor::Nodes
{
class LogicNodeBase : public BaseNode
{
Q_OBJECT
public:
LogicNodeBase() {};
void resetInterationIndex() { _iteration_index = 0; };
int getIterationindex() { return _iteration_index; };
int logicBranchToExecute() { return _current_logic_branch; };
void setLogicBranchToExecute(int branch) { _current_logic_branch = branch; };
virtual bool isLogicNode() override { return true; };
virtual unsigned int nLogicBranches() { return _n_logic_branches; };
void setNLogicBranches(int n_branches) { _n_logic_branches = n_branches; };
bool isIterable() { return _is_iterable; };
void setNIterations(int n_iterations) { _n_iterations = n_iterations; };
int getNIteraitons() { return _n_iterations; };
void setIterationIndex(int index) { _iteration_index = index; };
protected:
void setIsIterable(bool is_iterable) { _is_iterable = is_iterable; };
int _iteration_index = 0;
int _n_iterations = 0;
unsigned int _n_logic_branches = 1;
int _current_logic_branch = 1;
bool _is_iterable = false;
};
}
}
#endif //NOGGIT_LOGICNODEBASE_HPP

View File

@@ -102,3 +102,4 @@ void MathNode::restore(const QJsonObject& json_obj)
_operation->setCurrentIndex(json_obj["operation"].toInt());
}

View File

@@ -7,7 +7,7 @@
using namespace noggit::Red::PresetEditor::Nodes;
PrintNode::PrintNode()
: BaseNode()
: LogicNodeBase()
{
setName("PrintNode");
setCaption("Print()");
@@ -16,7 +16,7 @@ PrintNode::PrintNode()
addPort<LogicData>(PortType::In, "Logic", true);
addWidget(new QLabel(&_embedded_widget), 0);
addPort<DecimalData>(PortType::In, "String", true);
addPort<StringData>(PortType::In, "String", true);
_text = new QLineEdit(&_embedded_widget);
addWidget(_text, 1);
@@ -26,23 +26,9 @@ PrintNode::PrintNode()
void PrintNode::compute()
{
auto logic = _in_ports[0].in_value.lock();
auto logic_ptr = static_cast<LogicData*>(logic.get());
auto logic = static_cast<LogicData*>(_in_ports[0].in_value.lock().get());
if (!logic_ptr)
{
setValidationState(NodeValidationState::Error);
setValidationMessage("Error: Failed to evaluate logic input");
_out_ports[0].out_value = std::make_shared<LogicData>(false);
Q_EMIT dataUpdated(0);
return;
}
setValidationState(NodeValidationState::Valid);
if(!logic_ptr->value())
if(!logic->value())
return;
auto text = _in_ports[1].in_value.lock();
@@ -73,4 +59,22 @@ void PrintNode::restore(const QJsonObject& json_obj)
_text->setText(json_obj["text"].toString());
}
NodeValidationState PrintNode::validate()
{
setValidationState(NodeValidationState::Valid);
auto logic = static_cast<LogicData*>(_in_ports[0].in_value.lock().get());
if (!logic)
{
setValidationState(NodeValidationState::Error);
setValidationMessage("Error: Failed to evaluate logic input");
_out_ports[0].out_value = std::make_shared<LogicData>(false);
Q_EMIT dataUpdated(0);
}
return _validation_state;
}

View File

@@ -1,7 +1,7 @@
#ifndef NOGGIT_PRINTNODE_HPP
#define NOGGIT_PRINTNODE_HPP
#include "BaseNode.hpp"
#include "LogicNodeBase.hpp"
#include <QLineEdit>
using QtNodes::PortType;
@@ -16,13 +16,14 @@ namespace noggit
{
namespace Red::PresetEditor::Nodes
{
class PrintNode : public BaseNode
class PrintNode : public LogicNodeBase
{
Q_OBJECT
public:
PrintNode();
void compute() override;
NodeValidationState validate() override;
QJsonObject save() const override;
void restore(QJsonObject const& json_obj) override;

View File

@@ -1,5 +1,7 @@
#include "LogicBranch.hpp"
#include "../BaseNode.hpp"
#include "../LogicNodeBase.hpp"
#include "../LogicBreakNode.hpp"
#include <stdexcept>
@@ -8,48 +10,15 @@ using namespace noggit::Red::PresetEditor::Nodes;
LogicBranch::LogicBranch(Node* logic_node)
: _logic_node(logic_node)
{
processNode(logic_node);
}
void LogicBranch::processNode(Node* node)
{
auto model = static_cast<BaseNode*>(node->nodeDataModel());
auto nodeState = node->nodeState();
for (int i = 0; i < model->nPorts(PortType::Out); ++i)
{
auto const& connections = nodeState.connections(PortType::Out, i);
for (auto const& pair : connections)
{
auto connected_node = pair.second->getNode(PortType::In);
if (!connected_node)
continue;
auto connected_model = static_cast<BaseNode*>(connected_node->nodeDataModel());
if (connected_model->isLogicNode())
{
for (unsigned int j = 0; j < connected_model->nLogicBranches(); ++j)
{
_sub_branches[connected_node].emplace_back(connected_node);
}
}
else
{
_nodes.push_back(connected_node);
processNode(connected_node);
}
}
}
}
void LogicBranch::execute()
{
executeNode(_logic_node);
executeNode(_logic_node, nullptr);
}
void LogicBranch::executeNode(Node *node)
void LogicBranch::executeNode(Node* node, Node* source_node)
{
auto model = static_cast<BaseNode*>(node->nodeDataModel());
auto nodeState = node->nodeState();
@@ -57,10 +26,17 @@ void LogicBranch::executeNode(Node *node)
if (model->isComputed())
return;
executeNodeLeaves(node);
model->compute();
model->setComputed(true);
if(model->isLogicNode()
&& static_cast<LogicNodeBase*>(model)->name() == "LogicBreakNode"
&& static_cast<LogicBreakNode*>(model)->doBreak())
{
static_cast<LogicNodeBase*>(getCurrentLoop()->nodeDataModel())->setIterationIndex(-1);
static_cast<LogicBreakNode*>(model)->setDoBreak(false);
}
for (int i = 0; i < model->nPorts(PortType::Out); ++i)
{
auto const& connections = nodeState.connections(PortType::Out, i);
@@ -75,23 +51,43 @@ void LogicBranch::executeNode(Node *node)
auto connected_model = static_cast<BaseNode*>(connected_node->nodeDataModel());
if (connected_model->isLogicNode())
{
executeNodeLeaves(connected_node);
executeNode(connected_node);
}
else
{
executeNodeLeaves(connected_node);
executeNode(connected_node);
executeNodeLeaves(connected_node, node);
if (connected_model->validate() != NodeValidationState::Error)
{
auto logic_model = static_cast<LogicNodeBase*>(connected_node->nodeDataModel());
if (logic_model->isIterable())
{
setCurrentLoop(connected_node);
int it_index = logic_model->getIterationindex();
while (it_index >= 0 && it_index < logic_model->getNIteraitons())
{
markNodesComputed(connected_node, false);
executeNode(connected_node, node);
logic_model->setComputed(true);
it_index = logic_model->getIterationindex();
}
unsetCurrentLoop();
}
else
{
executeNode(connected_node, node);
}
}
}
}
}
}
void LogicBranch::executeNodeLeaves(Node *node)
void LogicBranch::executeNodeLeaves(Node* node, Node* source_node)
{
auto model = static_cast<BaseNode *>(node->nodeDataModel());
auto model = static_cast<BaseNode*>(node->nodeDataModel());
auto nodeState = node->nodeState();
if (model->isComputed())
return;
for (int i = 0; i < model->nPorts(PortType::In); ++i)
{
auto const& connections = nodeState.connections(PortType::In, i);
@@ -105,22 +101,70 @@ void LogicBranch::executeNodeLeaves(Node *node)
auto connected_model = static_cast<BaseNode*>(connected_node->nodeDataModel());
if (connected_model->isComputed() || connected_node == node)
if (connected_node == source_node || connected_model->isComputed() || connected_node == getCurrentLoop())
continue;
if (connected_model->isLogicNode())
{
connected_model->setValidationMessage("Error: A leaf should not represent a logic node!");
connected_model->setValidationState(NodeValidationState::Error);
connected_model->setComputed(true);
connected_model->setValidationMessage("Error: Logic node is out of logic flow.");
continue;
}
else if (!connected_model->isComputed())
{
executeNodeLeaves(connected_node);
connected_model->compute();
connected_model->setComputed(true);
}
executeNodeLeaves(connected_node, node);
connected_model->compute();
}
}
}
void LogicBranch::markNodesComputed(Node* start_node, bool state)
{
auto model = static_cast<BaseNode*>(start_node->nodeDataModel());
auto nodeState = start_node->nodeState();
model->setComputed(state);
for (int i = 0; i < model->nPorts(PortType::Out); ++i)
{
auto const& connections = nodeState.connections(PortType::Out, i);
for (auto const& pair : connections)
{
auto connected_node = pair.second->getNode(PortType::In);
if (!connected_node)
continue;
markNodeLeavesComputed(connected_node, start_node, state);
markNodesComputed(connected_node, state);
}
}
}
void LogicBranch::markNodeLeavesComputed(Node* start_node, Node* source_node, bool state)
{
auto model = static_cast<BaseNode*>(start_node->nodeDataModel());
auto nodeState = start_node->nodeState();
model->setComputed(state);
for (int i = 0; i < model->nPorts(PortType::In); ++i)
{
auto const& connections = nodeState.connections(PortType::In, i);
for (auto const& pair : connections)
{
auto connected_node = pair.second->getNode(PortType::Out);
auto connected_model = static_cast<BaseNode*>(connected_node->nodeDataModel());
if (!connected_node || connected_node == source_node || connected_model->isLogicNode())
continue;
markNodeLeavesComputed(connected_node, start_node, state);
}
}
}

View File

@@ -3,8 +3,7 @@
#include <external/NodeEditor/include/nodes/FlowScene>
#include <external/NodeEditor/include/nodes/Node>
#include <vector>
#include <unordered_map>
#include <stack>
using QtNodes::PortType;
using QtNodes::PortIndex;
@@ -24,15 +23,18 @@ namespace noggit
{
public:
explicit LogicBranch(Node* logic_node);
void processNode(Node* node);
void executeNode(Node* node);
void executeNodeLeaves(Node* node);
void executeNode(Node* node, Node* source_node);
void 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.top(); };
void execute();
private:
Node* _logic_node;
std::vector<Node*> _nodes;
std::unordered_map<Node*, std::vector<LogicBranch>> _sub_branches;
std::stack<Node*> _loop_stack;
};
}

View File

@@ -20,6 +20,7 @@ void NodeScene::execute()
if (model->isLogicNode() && model->name() == "LogicBeginNode")
{
begin = pair.second.get();
break;
}
}

View File

@@ -12,7 +12,9 @@
#include <noggit/Red/PresetEditor/Nodes/ConditionNode.hpp>
#include <noggit/Red/PresetEditor/Nodes/LogicIfNode.hpp>
#include <noggit/Red/PresetEditor/Nodes/LogicBeginNode.hpp>
#include <noggit/Red/PresetEditor/Nodes/LogicBreakNode.hpp>
#include <noggit/Red/PresetEditor/Nodes/PrintNode.hpp>
#include <noggit/Red/PresetEditor/Nodes/ForLoopNode.hpp>
#include <noggit/Red/PresetEditor/Nodes/BaseNode.hpp>
#include <noggit/Red/PresetEditor/Nodes/Data/GenericTypeConverter.hpp>
#include <noggit/Red/PresetEditor/Nodes/Scene/NodeScene.hpp>
@@ -33,6 +35,8 @@ using noggit::Red::PresetEditor::Nodes::ConditionNode;
using noggit::Red::PresetEditor::Nodes::LogicIfNode;
using noggit::Red::PresetEditor::Nodes::LogicBeginNode;
using noggit::Red::PresetEditor::Nodes::PrintNode;
using noggit::Red::PresetEditor::Nodes::ForLoopNode;
using noggit::Red::PresetEditor::Nodes::LogicBreakNode;
using noggit::Red::PresetEditor::Nodes::BaseNode;
using noggit::Red::PresetEditor::Nodes::NodeScene;
@@ -53,6 +57,8 @@ registerDataModels()
ret->registerModel<ConditionNode>("Logic");
ret->registerModel<LogicBeginNode>("Logic//Flow");
ret->registerModel<LogicIfNode>("Logic//Flow");
ret->registerModel<ForLoopNode>("Logic//Flow");
ret->registerModel<LogicBreakNode>("Logic//Flow");
ret->registerModel<PrintNode>("Functions//Generic");
ret->REGISTER_TYPE_CONVERTER(Decimal, Integer);
@@ -61,6 +67,8 @@ registerDataModels()
ret->REGISTER_TYPE_CONVERTER(Integer, Boolean);
ret->REGISTER_TYPE_CONVERTER(Boolean, Decimal);
ret->REGISTER_TYPE_CONVERTER(Boolean, Integer);
ret->REGISTER_TYPE_CONVERTER(Integer, String);
ret->REGISTER_TYPE_CONVERTER(Decimal, String);
return ret;
}