various changes to nodes

This commit is contained in:
sshumakov3
2020-12-04 21:58:31 +03:00
parent 0d89f12875
commit ce5c458cc2
12 changed files with 306 additions and 109 deletions

View File

@@ -148,7 +148,7 @@ Q_SIGNALS:
void nodeContextMenu(Node& n, const QPointF& pos);
private:
protected:
using SharedConnection = std::shared_ptr<Connection>;
using UniqueNode = std::unique_ptr<Node>;

View File

@@ -5,6 +5,9 @@
#include <QClipboard>
#include <QCursor>
#include <QDebug>
#include <QWidget>
#include <QPushButton>
#include <QPalette>
#include <unordered_map>
#include <stdexcept>
@@ -75,6 +78,8 @@ void ImGuiRenderer::initialize(WindowWrapper *window, ImGuiContext* context) {
};
window->installEventFilter(this);
applyQtStyle();
}
void ImGuiRenderer::renderDrawList(ImDrawData *draw_data)
@@ -437,4 +442,134 @@ ImGuiRenderer* ImGuiRenderer::instance() {
return instance;
}
void ImGuiRenderer::applyQtStyle()
{
auto temp = new QWidget();
auto temp_btn = new QPushButton();
temp->ensurePolished();
temp_btn->ensurePolished();
auto& palette = temp->palette();
auto& palette_btn = temp_btn->palette();
auto& style = ImGui::GetStyle();
ImVec4* colors = style.Colors;
auto& qBgColor = palette.color(QPalette::Window);
const ImVec4 bgColor = {static_cast<float>(qBgColor.redF()),
static_cast<float>(qBgColor.greenF()),
static_cast<float>(qBgColor.blueF()),
static_cast<float>(qBgColor.alphaF())};
auto& qLightBgColor = palette.color(QPalette::AlternateBase);
const ImVec4 lightBgColor = {static_cast<float>(qLightBgColor.redF()),
static_cast<float>(qLightBgColor.greenF()),
static_cast<float>(qLightBgColor.blueF()),
static_cast<float>(qLightBgColor.alphaF())};
auto& qVeryLightBgColor = palette.color(QPalette::Light);
const ImVec4 veryLightBgColor = {static_cast<float>(qVeryLightBgColor.redF()),
static_cast<float>(qVeryLightBgColor.greenF()),
static_cast<float>(qVeryLightBgColor.blueF()),
static_cast<float>(qVeryLightBgColor.alphaF())};
auto& qPanelColor = palette_btn.color(QPalette::Window);
const ImVec4 panelColor = {static_cast<float>(qPanelColor.redF()),
static_cast<float>(qPanelColor.greenF()),
static_cast<float>(qPanelColor.blueF()),
static_cast<float>(qPanelColor.alphaF())};
auto& qPanelHoverColor = palette.color(QPalette::Highlight);
const ImVec4 panelHoverColor = {static_cast<float>(qPanelHoverColor.redF()),
static_cast<float>(qPanelHoverColor.greenF()),
static_cast<float>(qPanelHoverColor.blueF()),
static_cast<float>(qPanelHoverColor.alphaF())};
auto& qPanelActiveColor = palette.color(QPalette::Highlight);
const ImVec4 panelActiveColor = {static_cast<float>(qPanelActiveColor.redF()),
static_cast<float>(qPanelActiveColor.greenF()),
static_cast<float>(qPanelActiveColor.blueF()),
static_cast<float>(qPanelActiveColor.alphaF())};
auto& qTextColor = palette.color(QPalette::WindowText);
const ImVec4 textColor = {static_cast<float>(qTextColor.redF()),
static_cast<float>(qTextColor.greenF()),
static_cast<float>(qTextColor.blueF()),
static_cast<float>(qTextColor.alphaF())};
auto& qTextDisabledColor = palette.color(QPalette::Inactive, QPalette::WindowText);
const ImVec4 textDisabledColor = {static_cast<float>(qTextDisabledColor.redF()),
static_cast<float>(qTextDisabledColor.greenF()),
static_cast<float>(qTextDisabledColor.blueF()),
static_cast<float>(qTextDisabledColor.alphaF())};
auto& qBorderColor = palette_btn.color(QPalette::Window);
const ImVec4 borderColor = {static_cast<float>(qBorderColor.redF()),
static_cast<float>(qBorderColor.greenF()),
static_cast<float>(qBorderColor.blueF()),
static_cast<float>(qBorderColor.alphaF())};
delete temp;
delete temp_btn;
colors[ImGuiCol_Text] = textColor;
colors[ImGuiCol_TextDisabled] = textDisabledColor;
colors[ImGuiCol_TextSelectedBg] = panelActiveColor;
colors[ImGuiCol_WindowBg] = bgColor;
colors[ImGuiCol_ChildBg] = bgColor;
colors[ImGuiCol_PopupBg] = bgColor;
colors[ImGuiCol_Border] = borderColor;
colors[ImGuiCol_BorderShadow] = borderColor;
colors[ImGuiCol_FrameBg] = panelColor;
colors[ImGuiCol_FrameBgHovered] = panelHoverColor;
colors[ImGuiCol_FrameBgActive] = panelActiveColor;
colors[ImGuiCol_TitleBg] = bgColor;
colors[ImGuiCol_TitleBgActive] = bgColor;
colors[ImGuiCol_TitleBgCollapsed] = bgColor;
colors[ImGuiCol_MenuBarBg] = panelColor;
colors[ImGuiCol_ScrollbarBg] = panelColor;
colors[ImGuiCol_ScrollbarGrab] = lightBgColor;
colors[ImGuiCol_ScrollbarGrabHovered] = veryLightBgColor;
colors[ImGuiCol_ScrollbarGrabActive] = veryLightBgColor;
colors[ImGuiCol_CheckMark] = panelActiveColor;
colors[ImGuiCol_SliderGrab] = panelHoverColor;
colors[ImGuiCol_SliderGrabActive] = panelActiveColor;
colors[ImGuiCol_Button] = panelColor;
colors[ImGuiCol_ButtonHovered] = panelHoverColor;
colors[ImGuiCol_ButtonActive] = panelHoverColor;
colors[ImGuiCol_Header] = panelColor;
colors[ImGuiCol_HeaderHovered] = panelHoverColor;
colors[ImGuiCol_HeaderActive] = panelActiveColor;
colors[ImGuiCol_Separator] = borderColor;
colors[ImGuiCol_SeparatorHovered] = borderColor;
colors[ImGuiCol_SeparatorActive] = borderColor;
colors[ImGuiCol_ResizeGrip] = bgColor;
colors[ImGuiCol_ResizeGripHovered] = panelColor;
colors[ImGuiCol_ResizeGripActive] = lightBgColor;
colors[ImGuiCol_PlotLines] = panelActiveColor;
colors[ImGuiCol_PlotLinesHovered] = panelHoverColor;
colors[ImGuiCol_PlotHistogram] = panelActiveColor;
colors[ImGuiCol_PlotHistogramHovered] = panelHoverColor;
colors[ImGuiCol_ModalWindowDarkening] = bgColor;
colors[ImGuiCol_DragDropTarget] = bgColor;
colors[ImGuiCol_NavHighlight] = bgColor;
colors[ImGuiCol_Tab] = bgColor;
colors[ImGuiCol_TabActive] = panelActiveColor;
colors[ImGuiCol_TabUnfocused] = bgColor;
colors[ImGuiCol_TabUnfocusedActive] = panelActiveColor;
colors[ImGuiCol_TabHovered] = panelHoverColor;
style.WindowRounding = 0.0f;
style.ChildRounding = 0.0f;
style.FrameRounding = 0.0f;
style.GrabRounding = 0.0f;
style.PopupRounding = 0.0f;
style.ScrollbarRounding = 0.0f;
style.TabRounding = 0.0f;
}
}

View File

@@ -27,6 +27,7 @@ class ImGuiRenderer : public QObject, QOpenGLExtraFunctions {
Q_OBJECT
public:
void initialize(WindowWrapper *window, ImGuiContext* context);
void applyQtStyle();
void newFrame();
bool eventFilter(QObject *watched, QEvent *event);

View File

@@ -128,6 +128,12 @@ unsigned int BaseNode::nPorts(PortType port_type) const
}
}
ConnectionPolicy BaseNode::portOutConnectionPolicy(PortIndex port_index) const
{
return _out_ports[port_index].connection_policy;
}
QWidget* BaseNode::portDefaultValueWidget(PortIndex port_index)
{
return _in_ports[port_index].default_widget;
@@ -149,6 +155,22 @@ void BaseNode::inputConnectionCreated(const Connection& connection)
default_widget->setVisible(false);
}
QJsonObject BaseNode::save() const
{
QJsonObject json_obj;
json_obj["name"] = name();
json_obj["caption"] = caption();
return json_obj;
}
void BaseNode::restore(const QJsonObject& json_obj)
{
setName(json_obj["name"].toString());
setCaption(json_obj["caption"].toString());
}

View File

@@ -27,6 +27,7 @@ using QtNodes::NodeDataType;
using QtNodes::NodeDataModel;
using QtNodes::NodeValidationState;
using QtNodes::Connection;
using ConnectionPolicy = QtNodes::NodeDataModel::ConnectionPolicy;
namespace noggit
@@ -50,6 +51,7 @@ namespace noggit
bool caption_visible = true;
std::unique_ptr<NodeData> data_type;
std::shared_ptr<NodeData> out_value;
ConnectionPolicy connection_policy = ConnectionPolicy::Many;
};
@@ -85,8 +87,28 @@ namespace noggit
bool portCaptionVisible(PortType port_type, PortIndex port_index) const override;
ConnectionPolicy portOutConnectionPolicy(PortIndex port_index) const override;
QWidget* portDefaultValueWidget(PortIndex port_index) override;
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; };
void setValidationMessage(QString const& message){_validation_error = message;};
void setValidationState(NodeValidationState state){_validation_state = state;};
virtual void compute() = 0;
public Q_SLOTS:
@@ -98,13 +120,14 @@ namespace noggit
void setName(QString const& name) {_name = name;};
void setCaption(QString const& caption){_caption = caption;};
void setValidationMessage(QString const& message){_validation_error = message;};
void setValidationState(NodeValidationState state){_validation_state = state;};
void addWidget(QWidget* widget, PortIndex in_port = -1);
void addWidget(QWidget* widget, QString const& label_text, PortIndex in_port = -1);
template<typename T>
void addPort(PortType port_type, QString const& caption, bool caption_visible);
void addPort(PortType port_type,
QString const& caption,
bool caption_visible,
ConnectionPolicy out_policy = ConnectionPolicy::Many);
protected:
@@ -119,6 +142,11 @@ 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;
};
}

View File

@@ -4,7 +4,10 @@
#include "BaseNode.hpp"
template<typename T>
void noggit::Red::PresetEditor::Nodes::BaseNode::addPort(PortType port_type, const QString &caption, bool caption_visible)
void noggit::Red::PresetEditor::Nodes::BaseNode::addPort(PortType port_type,
const QString &caption,
bool caption_visible,
ConnectionPolicy out_policy)
{
if (port_type == PortType::In)
{
@@ -15,6 +18,7 @@ void noggit::Red::PresetEditor::Nodes::BaseNode::addPort(PortType port_type, con
{
auto& port = _out_ports.emplace_back(caption, caption_visible);
port.data_type = std::make_unique<T>();
port.connection_policy = out_policy;
}
else
{

View File

@@ -1,42 +0,0 @@
#ifndef NOGGIT_DECIMALDATA_HPP
#define NOGGIT_DECIMALDATA_HPP
#include <external/NodeEditor/include/nodes/NodeDataModel>
using QtNodes::NodeDataType;
using QtNodes::NodeData;
/// The class can potentially incapsulate any user data which
/// need to be transferred within the Node Editor graph
class DecimalData : public NodeData
{
public:
DecimalData()
: _number(0.0)
{}
DecimalData(double const number)
: _number(number)
{}
NodeDataType type() const override
{
return NodeDataType {"decimal",
"Decimal"};
}
double number() const
{ return _number; }
QString numberAsText() const
{ return QString::number(_number, 'f'); }
private:
double _number;
};
#endif //NOGGIT_DECIMALDATA_HPP

View File

@@ -0,0 +1,72 @@
#ifndef NOGGIT_GENERICDATA_HPP
#define NOGGIT_GENERICDATA_HPP
#include <external/NodeEditor/include/nodes/NodeDataModel>
#include <external/glm/glm.hpp>
#include <type_traits>
#include <QString>
#include <functional>
using QtNodes::NodeDataType;
using QtNodes::NodeData;
template<typename Ty, const char* type_id, const char* type_name, typename C>
class GenericData : public NodeData
{
/* bypassing indirection overhead: passing by value if Ty fits into a machine word, passing by reference otherwise */
typedef std::conditional_t<sizeof(Ty) <= sizeof(std::size_t), Ty, Ty const&> Type;
public:
GenericData()
: _value{} { }
GenericData(Type value)
: _value{value} { }
[[nodiscard]]
NodeDataType type() const override
{
return NodeDataType {type_id, type_name};
}
[[nodiscard]]
Type value() const { return _value; }
[[nodiscard]]
QString toQString() const { return C::to_string(_value); }
private:
Ty _value;
};
template<typename T>
struct toQStringGeneric
{
static QString to_string(T const& value) { QString(std::to_string(value).c_str()); }
};
#define DECLARE_NODE_DATA_TYPE(TYPE_ID, TYPE_NAME, UNDERLYING_TYPE) \
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>>;
DECLARE_NODE_DATA_TYPE(int, Integer, int)
DECLARE_NODE_DATA_TYPE(double, Decimal, double)
DECLARE_NODE_DATA_TYPE(bool, Boolean, bool)
DECLARE_NODE_DATA_TYPE(string, String, std::string)
DECLARE_NODE_DATA_TYPE(logic, Logic, bool)
// GLM types
DECLARE_NODE_DATA_TYPE(vec2, Vector2D, glm::vec2)
DECLARE_NODE_DATA_TYPE(vec3, Vector3D, glm::vec3)
DECLARE_NODE_DATA_TYPE(vec4, Vector4D, glm::vec4)
DECLARE_NODE_DATA_TYPE(mat4, Matrix4x4, glm::mat4)
DECLARE_NODE_DATA_TYPE(mat3, Matrix3x3, glm::mat3)
DECLARE_NODE_DATA_TYPE(quat, Quaternion, glm::quat)
#endif //NOGGIT_GENERICDATA_HPP

View File

@@ -1,40 +0,0 @@
#ifndef NOGGIT_INTEGERDATA_HPP
#define NOGGIT_INTEGERDATA_HPP
#include <external/NodeEditor/include/nodes/NodeDataModel>
using QtNodes::NodeDataType;
using QtNodes::NodeData;
class IntegerData : public NodeData
{
public:
IntegerData()
: _number(0.0)
{}
IntegerData(int const number)
: _number(number)
{}
NodeDataType type() const override
{
return NodeDataType {"integer",
"Integer"};
}
int number() const
{ return _number; }
QString numberAsText() const
{ return QString::number(_number); }
private:
int _number;
};
#endif //NOGGIT_INTEGERDATA_HPP

View File

@@ -1,6 +1,6 @@
#include "MathNode.hpp"
#include "BaseNode.inl"
#include "Data/DecimalData.hpp"
#include "Data/GenericData.hpp"
#include <cmath>
using namespace noggit::Red::PresetEditor::Nodes;
@@ -43,12 +43,12 @@ void MathNode::compute()
auto first_shared = _in_ports[0].in_value.lock();
auto second_shared = _in_ports[1].in_value.lock();
auto first = dynamic_cast<DecimalData*>(first_shared.get());
auto second = dynamic_cast<DecimalData*>(second_shared.get());
auto first = static_cast<DecimalData*>(first_shared.get());
auto second = static_cast<DecimalData*>(second_shared.get());
// handle defaults
double first_number = first ? first->number() : _first->value();
double second_number = second ? second->number() : _second->value();
double first_number = first ? first->value() : _first->value();
double second_number = second ? second->value() : _second->value();
setValidationState(NodeValidationState::Warning);

View File

@@ -28,7 +28,7 @@ namespace noggit
QJsonObject save() const override;
void restore(QJsonObject const& json_obj) override;
private:
protected:
QDoubleSpinBox* _first;
QDoubleSpinBox* _second;
QComboBox* _operation;

View File

@@ -9,9 +9,13 @@
#include <external/NodeEditor/include/nodes/ConnectionStyle>
#include <external/NodeEditor/include/nodes/TypeConverter>
#include <noggit/Red/PresetEditor/Nodes/MathNode.hpp>
#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/PrintNode.hpp>
#include <noggit/Red/PresetEditor/Nodes/BaseNode.hpp>
#include <noggit/Red/PresetEditor/Nodes/Data/DecimalData.hpp>
#include <noggit/Red/PresetEditor/Nodes/Data/IntegerData.hpp>
#include <noggit/Red/PresetEditor/Nodes/Data/GenericTypeConverter.hpp>
#include <noggit/Red/PresetEditor/Nodes/Scene/NodeScene.hpp>
using namespace noggit::Red::PresetEditor::Ui;
@@ -25,7 +29,17 @@ using QtNodes::TypeConverter;
using QtNodes::TypeConverterId;
using noggit::Red::PresetEditor::Nodes::MathNode;
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::BaseNode;
using noggit::Red::PresetEditor::Nodes::NodeScene;
#define REGISTER_TYPE_CONVERTER(T_FROM, T_TO) \
registerTypeConverter(std::make_pair(T_FROM##Data().type(), \
T_TO##Data().type()), \
TypeConverter{T_FROM##To##T_TO##TypeConverter()})
static std::shared_ptr<DataModelRegistry>
registerDataModels()
@@ -35,20 +49,18 @@ registerDataModels()
//ret->registerModel<NumberDisplayDataModel>("I/O//Displays");
ret->registerModel<MathNode>("Operators");
ret->registerModel<MathNode>("Math");
ret->registerModel<ConditionNode>("Logic");
ret->registerModel<LogicBeginNode>("Logic//Flow");
ret->registerModel<LogicIfNode>("Logic//Flow");
ret->registerModel<PrintNode>("Functions//Generic");
/*
ret->registerTypeConverter(std::make_pair(DecimalData().type(),
IntegerData().type()),
TypeConverter{DecimalToIntegerConverter()});
ret->registerTypeConverter(std::make_pair(IntegerData().type(),
DecimalData().type()),
TypeConverter{IntegerToDecimalConverter()});
*/
ret->REGISTER_TYPE_CONVERTER(Decimal, Integer);
ret->REGISTER_TYPE_CONVERTER(Decimal, Boolean);
ret->REGISTER_TYPE_CONVERTER(Integer, Decimal);
ret->REGISTER_TYPE_CONVERTER(Integer, Boolean);
ret->REGISTER_TYPE_CONVERTER(Boolean, Decimal);
ret->REGISTER_TYPE_CONVERTER(Boolean, Integer);
return ret;
}
@@ -202,7 +214,7 @@ PresetEditorWidget::PresetEditorWidget(QWidget *parent)
// Handles nodes
::setStyle();
auto nodes_tab = ui->editorTabs->widget(1);
auto scene = new FlowScene(::registerDataModels(), nodes_tab);
auto scene = new NodeScene(::registerDataModels(), nodes_tab);
nodes_tab->setLayout(new QVBoxLayout(nodes_tab));
nodes_tab->layout()->addWidget(new FlowView(scene));
nodes_tab->layout()->setContentsMargins(0, 0, 0, 0);
@@ -212,13 +224,18 @@ PresetEditorWidget::PresetEditorWidget(QWidget *parent)
connect(ui->executeButton, &QPushButton::clicked
, [this, scene]()
{
/*
scene->iterateOverNodeDataDependentOrder(
[](NodeDataModel* model)
{
reinterpret_cast<BaseNode*>(model)->compute();
}
);
*/
scene->execute();
});
}
void PresetEditorWidget::setupConnectsCommon()