ShaderNode: Add inputs
This commit is contained in:
parent
5169e0fe83
commit
206724c911
|
|
@ -0,0 +1,132 @@
|
|||
#include <ShaderGraph.hpp>
|
||||
#include <DataModels/InputValue.hpp>
|
||||
#include <DataModels/VecValue.hpp>
|
||||
#include <Nazara/Renderer/ShaderBuilder.hpp>
|
||||
|
||||
InputValue::InputValue(ShaderGraph& graph) :
|
||||
ShaderNode(graph),
|
||||
m_currentInputIndex(0)
|
||||
{
|
||||
m_layout = new QVBoxLayout;
|
||||
|
||||
m_inputSelection = new QComboBox;
|
||||
m_inputSelection->setStyleSheet("background-color: rgba(255,255,255,255)");
|
||||
connect(m_inputSelection, qOverload<int>(&QComboBox::currentIndexChanged), [&](int index)
|
||||
{
|
||||
if (index < 0)
|
||||
return;
|
||||
|
||||
m_currentInputIndex = static_cast<std::size_t>(index);
|
||||
UpdatePreview();
|
||||
});
|
||||
|
||||
m_layout->addWidget(m_inputSelection);
|
||||
|
||||
m_previewLabel = new QLabel;
|
||||
|
||||
m_layout->addWidget(m_previewLabel);
|
||||
|
||||
m_widget = new QWidget;
|
||||
m_widget->setStyleSheet("background-color: rgba(0,0,0,0)");
|
||||
m_widget->setLayout(m_layout);
|
||||
|
||||
m_onInputListUpdateSlot.Connect(GetGraph().OnInputListUpdate, [&](ShaderGraph*) { UpdateInputList(); });
|
||||
m_onInputUpdateSlot.Connect(GetGraph().OnInputUpdate, [&](ShaderGraph*, std::size_t inputIndex)
|
||||
{
|
||||
if (m_currentInputIndex == inputIndex)
|
||||
UpdatePreview();
|
||||
});
|
||||
|
||||
UpdateInputList();
|
||||
UpdatePreview();
|
||||
}
|
||||
|
||||
QWidget* InputValue::embeddedWidget()
|
||||
{
|
||||
return m_widget;
|
||||
}
|
||||
|
||||
unsigned int InputValue::nPorts(QtNodes::PortType portType) const
|
||||
{
|
||||
switch (portType)
|
||||
{
|
||||
case QtNodes::PortType::In: return 0;
|
||||
case QtNodes::PortType::Out: return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void InputValue::UpdatePreview()
|
||||
{
|
||||
if (m_inputSelection->count() == 0)
|
||||
return;
|
||||
|
||||
Q_EMIT dataUpdated(0);
|
||||
}
|
||||
|
||||
void InputValue::UpdateInputList()
|
||||
{
|
||||
QString currentInput = m_inputSelection->currentText();
|
||||
m_inputSelection->clear();
|
||||
|
||||
for (const auto& inputEntry : GetGraph().GetInputs())
|
||||
m_inputSelection->addItem(QString::fromStdString(inputEntry.name));
|
||||
|
||||
m_inputSelection->setCurrentText(currentInput);
|
||||
}
|
||||
|
||||
Nz::ShaderAst::ExpressionPtr InputValue::GetExpression(Nz::ShaderAst::ExpressionPtr* expressions, std::size_t count) const
|
||||
{
|
||||
assert(count == 0);
|
||||
|
||||
const auto& inputEntry = GetGraph().GetInput(m_currentInputIndex);
|
||||
|
||||
Nz::ShaderAst::ExpressionType expression = [&]
|
||||
{
|
||||
switch (inputEntry.type)
|
||||
{
|
||||
case InputType::Bool: return Nz::ShaderAst::ExpressionType::Boolean;
|
||||
case InputType::Float1: return Nz::ShaderAst::ExpressionType::Float1;
|
||||
case InputType::Float2: return Nz::ShaderAst::ExpressionType::Float2;
|
||||
case InputType::Float3: return Nz::ShaderAst::ExpressionType::Float3;
|
||||
case InputType::Float4: return Nz::ShaderAst::ExpressionType::Float4;
|
||||
}
|
||||
|
||||
assert(false);
|
||||
throw std::runtime_error("Unhandled input type");
|
||||
}();
|
||||
|
||||
return Nz::ShaderBuilder::Input(inputEntry.name, expression);
|
||||
}
|
||||
|
||||
auto InputValue::dataType(QtNodes::PortType portType, QtNodes::PortIndex portIndex) const -> QtNodes::NodeDataType
|
||||
{
|
||||
assert(portType == QtNodes::PortType::Out);
|
||||
assert(portIndex == 0);
|
||||
|
||||
const auto& inputEntry = GetGraph().GetInput(m_currentInputIndex);
|
||||
switch (inputEntry.type)
|
||||
{
|
||||
//case InputType::Bool: return Nz::ShaderAst::ExpressionType::Boolean;
|
||||
//case InputType::Float1: return Nz::ShaderAst::ExpressionType::Float1;
|
||||
case InputType::Float2: return Vec2Data::Type();
|
||||
//case InputType::Float3: return Nz::ShaderAst::ExpressionType::Float3;
|
||||
case InputType::Float4: return Vec4Data::Type();
|
||||
}
|
||||
|
||||
assert(false);
|
||||
throw std::runtime_error("Unhandled input type");
|
||||
}
|
||||
|
||||
std::shared_ptr<QtNodes::NodeData> InputValue::outData(QtNodes::PortIndex port)
|
||||
{
|
||||
assert(port == 0);
|
||||
|
||||
const auto& inputEntry = GetGraph().GetInput(m_currentInputIndex);
|
||||
|
||||
auto vecData = std::make_shared<Vec4Data>();
|
||||
vecData->preview = QImage();
|
||||
|
||||
return vecData;
|
||||
}
|
||||
|
|
@ -0,0 +1,47 @@
|
|||
#pragma once
|
||||
|
||||
#ifndef NAZARA_SHADERNODES_INPUTVALUE_HPP
|
||||
#define NAZARA_SHADERNODES_INPUTVALUE_HPP
|
||||
|
||||
#include <QtWidgets/QComboBox>
|
||||
#include <QtWidgets/QVBoxLayout>
|
||||
#include <QtWidgets/QLabel>
|
||||
#include <ShaderGraph.hpp>
|
||||
#include <DataModels/ShaderNode.hpp>
|
||||
#include <array>
|
||||
|
||||
class InputValue : public ShaderNode
|
||||
{
|
||||
public:
|
||||
InputValue(ShaderGraph& graph);
|
||||
~InputValue() = default;
|
||||
|
||||
Nz::ShaderAst::ExpressionPtr GetExpression(Nz::ShaderAst::ExpressionPtr* /*expressions*/, std::size_t count) const override;
|
||||
|
||||
QString caption() const override { return "Input"; }
|
||||
QString name() const override { return "Input"; }
|
||||
|
||||
QWidget* embeddedWidget() override;
|
||||
unsigned int nPorts(QtNodes::PortType portType) const override;
|
||||
|
||||
QtNodes::NodeDataType dataType(QtNodes::PortType portType, QtNodes::PortIndex portIndex) const override;
|
||||
|
||||
std::shared_ptr<QtNodes::NodeData> outData(QtNodes::PortIndex port) override;
|
||||
|
||||
protected:
|
||||
void UpdatePreview();
|
||||
void UpdateInputList();
|
||||
|
||||
NazaraSlot(ShaderGraph, OnInputListUpdate, m_onInputListUpdateSlot);
|
||||
NazaraSlot(ShaderGraph, OnInputUpdate, m_onInputUpdateSlot);
|
||||
|
||||
std::size_t m_currentInputIndex;
|
||||
QComboBox* m_inputSelection;
|
||||
QLabel* m_previewLabel;
|
||||
QWidget* m_widget;
|
||||
QVBoxLayout* m_layout;
|
||||
};
|
||||
|
||||
#include <DataModels/InputValue.inl>
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
#include <DataModels/InputValue.hpp>
|
||||
#include <array>
|
||||
|
|
@ -94,7 +94,20 @@ Nz::ShaderAst::ExpressionPtr SampleTexture::GetExpression(Nz::ShaderAst::Express
|
|||
{
|
||||
assert(count == 1);
|
||||
|
||||
auto sampler = Nz::ShaderBuilder::Uniform("Texture0", Nz::ShaderAst::ExpressionType::Sampler2D);
|
||||
const auto& textureEntry = GetGraph().GetTexture(m_currentTextureIndex);
|
||||
|
||||
Nz::ShaderAst::ExpressionType expression = [&]
|
||||
{
|
||||
switch (textureEntry.type)
|
||||
{
|
||||
case TextureType::Sampler2D: return Nz::ShaderAst::ExpressionType::Sampler2D;
|
||||
}
|
||||
|
||||
assert(false);
|
||||
throw std::runtime_error("Unhandled texture type");
|
||||
}();
|
||||
|
||||
auto sampler = Nz::ShaderBuilder::Uniform(textureEntry.name, expression);
|
||||
|
||||
return Nz::ShaderBuilder::Sample2D(sampler, expressions[0]);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,42 @@
|
|||
#include <Enums.hpp>
|
||||
#include <cassert>
|
||||
|
||||
const char* EnumToString(InputRole role)
|
||||
{
|
||||
switch (role)
|
||||
{
|
||||
case InputRole::None: return "None";
|
||||
case InputRole::Normal: return "Normal";
|
||||
case InputRole::Position: return "Position";
|
||||
case InputRole::TexCoord: return "TexCoord";
|
||||
}
|
||||
|
||||
assert(false);
|
||||
return "<Unhandled>";
|
||||
}
|
||||
|
||||
const char* EnumToString(InputType input)
|
||||
{
|
||||
switch (input)
|
||||
{
|
||||
case InputType::Bool: return "Bool";
|
||||
case InputType::Float1: return "Float";
|
||||
case InputType::Float2: return "Float2";
|
||||
case InputType::Float3: return "Float3";
|
||||
case InputType::Float4: return "Float4";
|
||||
}
|
||||
|
||||
assert(false);
|
||||
return "<Unhandled>";
|
||||
}
|
||||
|
||||
const char* EnumToString(TextureType textureType)
|
||||
{
|
||||
switch (textureType)
|
||||
{
|
||||
case TextureType::Sampler2D: return "Sampler2D";
|
||||
}
|
||||
|
||||
assert(false);
|
||||
return "<Unhandled>";
|
||||
}
|
||||
|
|
@ -0,0 +1,48 @@
|
|||
#pragma once
|
||||
|
||||
#ifndef NAZARA_SHADERNODES_ENUMS_HPP
|
||||
#define NAZARA_SHADERNODES_ENUMS_HPP
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
enum class InputRole
|
||||
{
|
||||
None,
|
||||
Normal,
|
||||
Position,
|
||||
TexCoord,
|
||||
|
||||
Max = TexCoord
|
||||
};
|
||||
|
||||
constexpr std::size_t InputRoleCount = static_cast<std::size_t>(InputRole::Max) + 1;
|
||||
|
||||
enum class InputType
|
||||
{
|
||||
Bool,
|
||||
Float1,
|
||||
Float2,
|
||||
Float3,
|
||||
Float4,
|
||||
|
||||
Max = Float4
|
||||
};
|
||||
|
||||
constexpr std::size_t InputTypeCount = static_cast<std::size_t>(InputType::Max) + 1;
|
||||
|
||||
enum class TextureType
|
||||
{
|
||||
Sampler2D,
|
||||
|
||||
Max = Sampler2D
|
||||
};
|
||||
|
||||
constexpr std::size_t TextureTypeCount = static_cast<std::size_t>(TextureType::Max) + 1;
|
||||
|
||||
const char* EnumToString(InputRole role);
|
||||
const char* EnumToString(InputType input);
|
||||
const char* EnumToString(TextureType textureType);
|
||||
|
||||
#include <Enums.inl>
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1 @@
|
|||
#include <Enums.hpp>
|
||||
|
|
@ -1,6 +1,7 @@
|
|||
#include <ShaderGraph.hpp>
|
||||
#include <Nazara/Core/StackArray.hpp>
|
||||
#include <DataModels/FragmentOutput.hpp>
|
||||
#include <DataModels/InputValue.hpp>
|
||||
#include <DataModels/SampleTexture.hpp>
|
||||
#include <DataModels/ShaderNode.hpp>
|
||||
#include <DataModels/VecBinOp.hpp>
|
||||
|
|
@ -35,7 +36,21 @@ m_flowScene(BuildRegistry())
|
|||
m_flowScene.createConnection(node2, 0, node1, 0);
|
||||
}
|
||||
|
||||
std::size_t ShaderGraph::AddTexture(std::string name, Nz::ShaderAst::ExpressionType type)
|
||||
std::size_t ShaderGraph::AddInput(std::string name, InputType type, InputRole role, std::size_t roleIndex)
|
||||
{
|
||||
std::size_t index = m_inputs.size();
|
||||
auto& inputEntry = m_inputs.emplace_back();
|
||||
inputEntry.name = std::move(name);
|
||||
inputEntry.role = role;
|
||||
inputEntry.roleIndex = roleIndex;
|
||||
inputEntry.type = type;
|
||||
|
||||
OnInputListUpdate(this);
|
||||
|
||||
return index;
|
||||
}
|
||||
|
||||
std::size_t ShaderGraph::AddTexture(std::string name, TextureType type)
|
||||
{
|
||||
std::size_t index = m_textures.size();
|
||||
auto& textureEntry = m_textures.emplace_back();
|
||||
|
|
@ -85,6 +100,18 @@ Nz::ShaderAst::StatementPtr ShaderGraph::ToAst()
|
|||
return std::make_shared<Nz::ShaderAst::StatementBlock>(std::move(statements));
|
||||
}
|
||||
|
||||
void ShaderGraph::UpdateInput(std::size_t inputIndex, std::string name, InputType type, InputRole role, std::size_t roleIndex)
|
||||
{
|
||||
assert(inputIndex < m_inputs.size());
|
||||
auto& inputEntry = m_inputs[inputIndex];
|
||||
inputEntry.name = std::move(name);
|
||||
inputEntry.role = role;
|
||||
inputEntry.roleIndex = roleIndex;
|
||||
inputEntry.type = type;
|
||||
|
||||
OnInputUpdate(this, inputIndex);
|
||||
}
|
||||
|
||||
void ShaderGraph::UpdateTexturePreview(std::size_t textureIndex, QImage preview)
|
||||
{
|
||||
assert(textureIndex < m_textures.size());
|
||||
|
|
@ -98,7 +125,8 @@ void ShaderGraph::UpdateTexturePreview(std::size_t textureIndex, QImage preview)
|
|||
std::shared_ptr<QtNodes::DataModelRegistry> ShaderGraph::BuildRegistry()
|
||||
{
|
||||
auto registry = std::make_shared<QtNodes::DataModelRegistry>();
|
||||
RegisterShaderNode<FragmentOutput>(*this, registry, "Output");
|
||||
RegisterShaderNode<FragmentOutput>(*this, registry, "Outputs");
|
||||
RegisterShaderNode<InputValue>(*this, registry, "Inputs");
|
||||
RegisterShaderNode<SampleTexture>(*this, registry, "Texture");
|
||||
RegisterShaderNode<Vec4Add>(*this, registry, "Vector operations");
|
||||
RegisterShaderNode<Vec4Mul>(*this, registry, "Vector operations");
|
||||
|
|
|
|||
|
|
@ -6,35 +6,50 @@
|
|||
#include <Nazara/Core/Signal.hpp>
|
||||
#include <Nazara/Renderer/ShaderAst.hpp>
|
||||
#include <nodes/FlowScene>
|
||||
#include <nodes/FlowView>
|
||||
#include <Enums.hpp>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
class ShaderGraph
|
||||
{
|
||||
public:
|
||||
struct InputEntry;
|
||||
struct TextureEntry;
|
||||
|
||||
ShaderGraph();
|
||||
~ShaderGraph() = default;
|
||||
|
||||
std::size_t AddTexture(std::string name, Nz::ShaderAst::ExpressionType type);
|
||||
std::size_t AddInput(std::string name, InputType type, InputRole role, std::size_t roleIndex);
|
||||
std::size_t AddTexture(std::string name, TextureType type);
|
||||
|
||||
inline const InputEntry& GetInput(std::size_t inputIndex) const;
|
||||
inline const std::vector<InputEntry>& GetInputs() const;
|
||||
inline QtNodes::FlowScene& GetScene();
|
||||
inline const TextureEntry& GetTexture(std::size_t textureIndex) const;
|
||||
inline const std::vector<TextureEntry>& GetTextures();
|
||||
inline const std::vector<TextureEntry>& GetTextures() const;
|
||||
|
||||
Nz::ShaderAst::StatementPtr ToAst();
|
||||
|
||||
void UpdateInput(std::size_t inputIndex, std::string name, InputType type, InputRole role, std::size_t roleIndex);
|
||||
void UpdateTexturePreview(std::size_t texture, QImage preview);
|
||||
|
||||
struct InputEntry
|
||||
{
|
||||
std::size_t roleIndex;
|
||||
std::string name;
|
||||
InputRole role;
|
||||
InputType type;
|
||||
};
|
||||
|
||||
struct TextureEntry
|
||||
{
|
||||
std::string name;
|
||||
Nz::ShaderAst::ExpressionType type;
|
||||
TextureType type;
|
||||
QImage preview;
|
||||
};
|
||||
|
||||
NazaraSignal(OnInputListUpdate, ShaderGraph*);
|
||||
NazaraSignal(OnInputUpdate, ShaderGraph*, std::size_t /*inputIndex*/);
|
||||
NazaraSignal(OnTextureListUpdate, ShaderGraph*);
|
||||
NazaraSignal(OnTexturePreviewUpdate, ShaderGraph*, std::size_t /*textureIndex*/);
|
||||
|
||||
|
|
@ -42,6 +57,7 @@ class ShaderGraph
|
|||
std::shared_ptr<QtNodes::DataModelRegistry> BuildRegistry();
|
||||
|
||||
QtNodes::FlowScene m_flowScene;
|
||||
std::vector<InputEntry> m_inputs;
|
||||
std::vector<TextureEntry> m_textures;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,16 @@
|
|||
#include <ShaderGraph.hpp>
|
||||
|
||||
inline auto ShaderGraph::GetInput(std::size_t inputIndex) const -> const InputEntry&
|
||||
{
|
||||
assert(inputIndex < m_inputs.size());
|
||||
return m_inputs[inputIndex];
|
||||
}
|
||||
|
||||
inline auto ShaderGraph::GetInputs() const -> const std::vector<InputEntry>&
|
||||
{
|
||||
return m_inputs;
|
||||
}
|
||||
|
||||
inline QtNodes::FlowScene& ShaderGraph::GetScene()
|
||||
{
|
||||
return m_flowScene;
|
||||
|
|
@ -11,7 +22,7 @@ inline auto ShaderGraph::GetTexture(std::size_t textureIndex) const -> const Tex
|
|||
return m_textures[textureIndex];
|
||||
}
|
||||
|
||||
inline auto ShaderGraph::GetTextures() -> const std::vector<TextureEntry>&
|
||||
inline auto ShaderGraph::GetTextures() const -> const std::vector<TextureEntry>&
|
||||
{
|
||||
return m_textures;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,80 @@
|
|||
#include <Widgets/InputEditDialog.hpp>
|
||||
#include <QtWidgets/QComboBox>
|
||||
#include <QtWidgets/QDialogButtonBox>
|
||||
#include <QtWidgets/QFormLayout>
|
||||
#include <QtWidgets/QLineEdit>
|
||||
#include <QtWidgets/QMessageBox>
|
||||
#include <QtWidgets/QSpinBox>
|
||||
#include <QtWidgets/QVBoxLayout>
|
||||
|
||||
InputEditDialog::InputEditDialog(QWidget* parent) :
|
||||
QDialog(parent)
|
||||
{
|
||||
setWindowTitle(tr("Input edit dialog"));
|
||||
setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
|
||||
|
||||
m_inputName = new QLineEdit;
|
||||
|
||||
m_typeList = new QComboBox;
|
||||
for (std::size_t i = 0; i < InputTypeCount; ++i)
|
||||
m_typeList->addItem(EnumToString(static_cast<InputType>(i)));
|
||||
|
||||
m_roleList = new QComboBox;
|
||||
for (std::size_t i = 0; i < InputRoleCount; ++i)
|
||||
m_roleList->addItem(EnumToString(static_cast<InputRole>(i)));
|
||||
|
||||
m_roleIndex = new QSpinBox;
|
||||
|
||||
QFormLayout* formLayout = new QFormLayout;
|
||||
formLayout->addRow(tr("Name"), m_inputName);
|
||||
formLayout->addRow(tr("Type"), m_typeList);
|
||||
formLayout->addRow(tr("Role"), m_roleList);
|
||||
formLayout->addRow(tr("Role index"), m_roleIndex);
|
||||
|
||||
QDialogButtonBox* buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
|
||||
connect(buttonBox, &QDialogButtonBox::accepted, this, &InputEditDialog::OnAccept);
|
||||
connect(buttonBox, &QDialogButtonBox::rejected, this, &QDialog::reject);
|
||||
|
||||
QVBoxLayout* verticalLayout = new QVBoxLayout;
|
||||
verticalLayout->addLayout(formLayout);
|
||||
verticalLayout->addWidget(buttonBox);
|
||||
|
||||
setLayout(verticalLayout);
|
||||
}
|
||||
|
||||
InputEditDialog::InputEditDialog(const InputInfo& input, QWidget* parent) :
|
||||
InputEditDialog(parent)
|
||||
{
|
||||
m_inputName->setText(QString::fromStdString(input.name));
|
||||
m_roleIndex->setValue(int(input.roleIndex));
|
||||
m_roleList->setCurrentText(EnumToString(input.role));
|
||||
m_typeList->setCurrentText(EnumToString(input.type));
|
||||
}
|
||||
|
||||
InputInfo InputEditDialog::GetInputInfo() const
|
||||
{
|
||||
InputInfo inputInfo;
|
||||
inputInfo.name = m_inputName->text().toStdString();
|
||||
inputInfo.role = static_cast<InputRole>(m_roleList->currentIndex());
|
||||
inputInfo.roleIndex = static_cast<std::size_t>(m_roleIndex->value());
|
||||
inputInfo.type = static_cast<InputType>(m_typeList->currentIndex());
|
||||
|
||||
return inputInfo;
|
||||
}
|
||||
|
||||
void InputEditDialog::OnAccept()
|
||||
{
|
||||
if (m_inputName->text().isEmpty())
|
||||
{
|
||||
QMessageBox::critical(this, tr("Empty name"), tr("Input name must be set"), QMessageBox::Ok);
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_typeList->currentIndex() < 0)
|
||||
{
|
||||
QMessageBox::critical(this, tr("Invalid type"), tr("You must select a type"), QMessageBox::Ok);
|
||||
return;
|
||||
}
|
||||
|
||||
accept();
|
||||
}
|
||||
|
|
@ -0,0 +1,41 @@
|
|||
#pragma once
|
||||
|
||||
#ifndef NAZARA_SHADERNODES_INPUTEDITDIALOG_HPP
|
||||
#define NAZARA_SHADERNODES_INPUTEDITDIALOG_HPP
|
||||
|
||||
#include <Enums.hpp>
|
||||
#include <QtWidgets/QDialog>
|
||||
|
||||
class QComboBox;
|
||||
class QLineEdit;
|
||||
class QSpinBox;
|
||||
|
||||
struct InputInfo
|
||||
{
|
||||
std::size_t roleIndex;
|
||||
std::string name;
|
||||
InputRole role;
|
||||
InputType type;
|
||||
};
|
||||
|
||||
class InputEditDialog : public QDialog
|
||||
{
|
||||
public:
|
||||
InputEditDialog(QWidget* parent = nullptr);
|
||||
InputEditDialog(const InputInfo& input, QWidget* parent = nullptr);
|
||||
~InputEditDialog() = default;
|
||||
|
||||
InputInfo GetInputInfo() const;
|
||||
|
||||
private:
|
||||
void OnAccept();
|
||||
|
||||
QComboBox* m_roleList;
|
||||
QComboBox* m_typeList;
|
||||
QLineEdit* m_inputName;
|
||||
QSpinBox* m_roleIndex;
|
||||
};
|
||||
|
||||
#include <Widgets/InputEditor.inl>
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1 @@
|
|||
#include <Widgets/InputEditor.hpp>
|
||||
|
|
@ -0,0 +1,97 @@
|
|||
#include <Widgets/InputEditor.hpp>
|
||||
#include <Widgets/InputEditDialog.hpp>
|
||||
#include <ShaderGraph.hpp>
|
||||
#include <QtWidgets/QFileDialog>
|
||||
#include <QtWidgets/QLabel>
|
||||
#include <QtWidgets/QPushButton>
|
||||
#include <QtWidgets/QListWidget>
|
||||
#include <QtWidgets/QVBoxLayout>
|
||||
|
||||
InputEditor::InputEditor(ShaderGraph& graph) :
|
||||
m_shaderGraph(graph)
|
||||
{
|
||||
m_inputList = new QListWidget(this);
|
||||
connect(m_inputList, &QListWidget::currentRowChanged, this, &InputEditor::OnInputSelectionUpdate);
|
||||
connect(m_inputList, &QListWidget::itemDoubleClicked, [this](QListWidgetItem* item)
|
||||
{
|
||||
OnEditInput(m_inputList->row(item));
|
||||
});
|
||||
|
||||
QPushButton* addInputButton = new QPushButton(tr("Add input..."));
|
||||
connect(addInputButton, &QPushButton::released, this, &InputEditor::OnAddInput);
|
||||
|
||||
m_layout = new QVBoxLayout;
|
||||
m_layout->addWidget(m_inputList);
|
||||
m_layout->addWidget(addInputButton);
|
||||
|
||||
setLayout(m_layout);
|
||||
|
||||
m_onInputListUpdateSlot.Connect(m_shaderGraph.OnInputListUpdate, this, &InputEditor::OnInputListUpdate);
|
||||
m_onInputUpdateSlot.Connect(m_shaderGraph.OnInputUpdate, this, &InputEditor::OnInputUpdate);
|
||||
|
||||
RefreshInputs();
|
||||
}
|
||||
|
||||
void InputEditor::OnAddInput()
|
||||
{
|
||||
InputEditDialog* dialog = new InputEditDialog(this);
|
||||
dialog->setAttribute(Qt::WA_DeleteOnClose, true);
|
||||
connect(dialog, &QDialog::accepted, [this, dialog]
|
||||
{
|
||||
InputInfo inputInfo = dialog->GetInputInfo();
|
||||
m_shaderGraph.AddInput(std::move(inputInfo.name), inputInfo.type, inputInfo.role, inputInfo.roleIndex);
|
||||
});
|
||||
|
||||
dialog->open();
|
||||
}
|
||||
|
||||
void InputEditor::OnEditInput(int inputIndex)
|
||||
{
|
||||
const auto& input = m_shaderGraph.GetInput(inputIndex);
|
||||
|
||||
InputInfo info;
|
||||
info.name = input.name;
|
||||
info.type = input.type;
|
||||
info.role = input.role;
|
||||
info.roleIndex = input.roleIndex;
|
||||
|
||||
InputEditDialog* dialog = new InputEditDialog(std::move(info), this);
|
||||
dialog->setAttribute(Qt::WA_DeleteOnClose, true);
|
||||
connect(dialog, &QDialog::accepted, [this, dialog, inputIndex]
|
||||
{
|
||||
InputInfo inputInfo = dialog->GetInputInfo();
|
||||
m_shaderGraph.UpdateInput(inputIndex, std::move(inputInfo.name), inputInfo.type, inputInfo.role, inputInfo.roleIndex);
|
||||
});
|
||||
|
||||
dialog->open();
|
||||
}
|
||||
|
||||
void InputEditor::OnInputSelectionUpdate(int inputIndex)
|
||||
{
|
||||
if (inputIndex >= 0)
|
||||
{
|
||||
m_currentInputIndex = inputIndex;
|
||||
}
|
||||
else
|
||||
m_currentInputIndex.reset();
|
||||
}
|
||||
|
||||
void InputEditor::OnInputListUpdate(ShaderGraph* /*graph*/)
|
||||
{
|
||||
RefreshInputs();
|
||||
}
|
||||
|
||||
void InputEditor::OnInputUpdate(ShaderGraph* /*graph*/, std::size_t inputIndex)
|
||||
{
|
||||
const auto& inputEntry = m_shaderGraph.GetInput(inputIndex);
|
||||
m_inputList->item(int(inputIndex))->setText(QString::fromStdString(inputEntry.name));
|
||||
}
|
||||
|
||||
void InputEditor::RefreshInputs()
|
||||
{
|
||||
m_inputList->clear();
|
||||
m_inputList->setCurrentRow(-1);
|
||||
|
||||
for (const auto& inputEntry : m_shaderGraph.GetInputs())
|
||||
m_inputList->addItem(QString::fromStdString(inputEntry.name));
|
||||
}
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
#pragma once
|
||||
|
||||
#ifndef NAZARA_SHADERNODES_INPUTEDITOR_HPP
|
||||
#define NAZARA_SHADERNODES_INPUTEDITOR_HPP
|
||||
|
||||
#include <ShaderGraph.hpp>
|
||||
#include <QtWidgets/QWidget>
|
||||
#include <optional>
|
||||
|
||||
class QLabel;
|
||||
class QListWidget;
|
||||
class QVBoxLayout;
|
||||
|
||||
class InputEditor : public QWidget
|
||||
{
|
||||
public:
|
||||
InputEditor(ShaderGraph& graph);
|
||||
~InputEditor() = default;
|
||||
|
||||
private:
|
||||
void OnAddInput();
|
||||
void OnEditInput(int inputIndex);
|
||||
void OnInputSelectionUpdate(int inputIndex);
|
||||
void OnInputListUpdate(ShaderGraph* graph);
|
||||
void OnInputUpdate(ShaderGraph* graph, std::size_t inputIndex);
|
||||
void RefreshInputs();
|
||||
|
||||
NazaraSlot(ShaderGraph, OnInputListUpdate, m_onInputListUpdateSlot);
|
||||
NazaraSlot(ShaderGraph, OnInputUpdate, m_onInputUpdateSlot);
|
||||
|
||||
std::optional<std::size_t> m_currentInputIndex;
|
||||
ShaderGraph& m_shaderGraph;
|
||||
QListWidget* m_inputList;
|
||||
QVBoxLayout* m_layout;
|
||||
};
|
||||
|
||||
#include <Widgets/InputEditor.inl>
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1 @@
|
|||
#include <Widgets/InputEditor.hpp>
|
||||
|
|
@ -1,8 +1,10 @@
|
|||
#include <Widgets/MainWindow.hpp>
|
||||
#include <Nazara/Renderer/GlslWriter.hpp>
|
||||
#include <ShaderGraph.hpp>
|
||||
#include <Widgets/InputEditor.hpp>
|
||||
#include <Widgets/TextureEditor.hpp>
|
||||
#include <nodes/FlowView>
|
||||
#include <QtWidgets/QDockWidget>
|
||||
#include <QtWidgets/QMenuBar>
|
||||
#include <QtWidgets/QTextEdit>
|
||||
#include <iostream>
|
||||
|
|
@ -17,6 +19,13 @@ m_shaderGraph(graph)
|
|||
QtNodes::FlowView* flowView = new QtNodes::FlowView(scene);
|
||||
setCentralWidget(flowView);
|
||||
|
||||
QDockWidget* inputDock = new QDockWidget(tr("&Inputs"));
|
||||
|
||||
InputEditor* inputEditor = new InputEditor(m_shaderGraph);
|
||||
inputDock->setWidget(inputEditor);
|
||||
|
||||
addDockWidget(Qt::LeftDockWidgetArea, inputDock);
|
||||
|
||||
QDockWidget* textureDock = new QDockWidget(tr("&Textures"));
|
||||
|
||||
TextureEditor* textureEditor = new TextureEditor(m_shaderGraph);
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@
|
|||
TextureEditor::TextureEditor(ShaderGraph& graph) :
|
||||
m_shaderGraph(graph)
|
||||
{
|
||||
m_textureList = new QListWidget(this);
|
||||
m_textureList = new QListWidget;
|
||||
connect(m_textureList, &QListWidget::currentRowChanged, this, &TextureEditor::OnTextureSelectionUpdate);
|
||||
|
||||
m_pixmapLabel = new QLabel;
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
#define NAZARA_SHADERNODES_TEXTUREEDITOR_HPP
|
||||
|
||||
#include <ShaderGraph.hpp>
|
||||
#include <QtWidgets/QDockWidget>
|
||||
#include <QtWidgets/QWidget>
|
||||
#include <optional>
|
||||
|
||||
class QLabel;
|
||||
|
|
|
|||
|
|
@ -8,8 +8,8 @@ int main(int argc, char* argv[])
|
|||
QApplication app(argc, argv);
|
||||
|
||||
ShaderGraph shaderGraph;
|
||||
shaderGraph.AddTexture("Potato", Nz::ShaderAst::ExpressionType::Sampler2D);
|
||||
shaderGraph.AddTexture("Blackbird", Nz::ShaderAst::ExpressionType::Sampler2D);
|
||||
shaderGraph.AddInput("UV", InputType::Float2, InputRole::TexCoord, 0);
|
||||
shaderGraph.AddTexture("Potato", TextureType::Sampler2D);
|
||||
|
||||
MainWindow mainWindow(shaderGraph);
|
||||
mainWindow.resize(1280, 720);
|
||||
|
|
|
|||
Loading…
Reference in New Issue