implement further node functionality. logic break, rework interpreter
This commit is contained in:
@@ -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;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -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>)
|
||||
|
||||
|
||||
|
||||
|
||||
116
src/noggit/Red/PresetEditor/Nodes/ForLoopNode.cpp
Normal file
116
src/noggit/Red/PresetEditor/Nodes/ForLoopNode.cpp
Normal 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;
|
||||
}
|
||||
|
||||
39
src/noggit/Red/PresetEditor/Nodes/ForLoopNode.hpp
Normal file
39
src/noggit/Red/PresetEditor/Nodes/ForLoopNode.hpp
Normal 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
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
48
src/noggit/Red/PresetEditor/Nodes/LogicBreakNode.cpp
Normal file
48
src/noggit/Red/PresetEditor/Nodes/LogicBreakNode.cpp
Normal 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;
|
||||
}
|
||||
|
||||
|
||||
40
src/noggit/Red/PresetEditor/Nodes/LogicBreakNode.hpp
Normal file
40
src/noggit/Red/PresetEditor/Nodes/LogicBreakNode.hpp
Normal 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
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
63
src/noggit/Red/PresetEditor/Nodes/LogicNodeBase.hpp
Normal file
63
src/noggit/Red/PresetEditor/Nodes/LogicNodeBase.hpp
Normal 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
|
||||
@@ -102,3 +102,4 @@ void MathNode::restore(const QJsonObject& json_obj)
|
||||
_operation->setCurrentIndex(json_obj["operation"].toInt());
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@ void NodeScene::execute()
|
||||
if (model->isLogicNode() && model->name() == "LogicBeginNode")
|
||||
{
|
||||
begin = pair.second.get();
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user