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);
|
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]);
|
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 <ShaderGraph.hpp>
|
||||||
#include <Nazara/Core/StackArray.hpp>
|
#include <Nazara/Core/StackArray.hpp>
|
||||||
#include <DataModels/FragmentOutput.hpp>
|
#include <DataModels/FragmentOutput.hpp>
|
||||||
|
#include <DataModels/InputValue.hpp>
|
||||||
#include <DataModels/SampleTexture.hpp>
|
#include <DataModels/SampleTexture.hpp>
|
||||||
#include <DataModels/ShaderNode.hpp>
|
#include <DataModels/ShaderNode.hpp>
|
||||||
#include <DataModels/VecBinOp.hpp>
|
#include <DataModels/VecBinOp.hpp>
|
||||||
|
|
@ -35,7 +36,21 @@ m_flowScene(BuildRegistry())
|
||||||
m_flowScene.createConnection(node2, 0, node1, 0);
|
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();
|
std::size_t index = m_textures.size();
|
||||||
auto& textureEntry = m_textures.emplace_back();
|
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));
|
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)
|
void ShaderGraph::UpdateTexturePreview(std::size_t textureIndex, QImage preview)
|
||||||
{
|
{
|
||||||
assert(textureIndex < m_textures.size());
|
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()
|
std::shared_ptr<QtNodes::DataModelRegistry> ShaderGraph::BuildRegistry()
|
||||||
{
|
{
|
||||||
auto registry = std::make_shared<QtNodes::DataModelRegistry>();
|
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<SampleTexture>(*this, registry, "Texture");
|
||||||
RegisterShaderNode<Vec4Add>(*this, registry, "Vector operations");
|
RegisterShaderNode<Vec4Add>(*this, registry, "Vector operations");
|
||||||
RegisterShaderNode<Vec4Mul>(*this, registry, "Vector operations");
|
RegisterShaderNode<Vec4Mul>(*this, registry, "Vector operations");
|
||||||
|
|
|
||||||
|
|
@ -6,35 +6,50 @@
|
||||||
#include <Nazara/Core/Signal.hpp>
|
#include <Nazara/Core/Signal.hpp>
|
||||||
#include <Nazara/Renderer/ShaderAst.hpp>
|
#include <Nazara/Renderer/ShaderAst.hpp>
|
||||||
#include <nodes/FlowScene>
|
#include <nodes/FlowScene>
|
||||||
#include <nodes/FlowView>
|
#include <Enums.hpp>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
class ShaderGraph
|
class ShaderGraph
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
struct InputEntry;
|
||||||
struct TextureEntry;
|
struct TextureEntry;
|
||||||
|
|
||||||
ShaderGraph();
|
ShaderGraph();
|
||||||
~ShaderGraph() = default;
|
~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 QtNodes::FlowScene& GetScene();
|
||||||
inline const TextureEntry& GetTexture(std::size_t textureIndex) const;
|
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();
|
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);
|
void UpdateTexturePreview(std::size_t texture, QImage preview);
|
||||||
|
|
||||||
|
struct InputEntry
|
||||||
|
{
|
||||||
|
std::size_t roleIndex;
|
||||||
|
std::string name;
|
||||||
|
InputRole role;
|
||||||
|
InputType type;
|
||||||
|
};
|
||||||
|
|
||||||
struct TextureEntry
|
struct TextureEntry
|
||||||
{
|
{
|
||||||
std::string name;
|
std::string name;
|
||||||
Nz::ShaderAst::ExpressionType type;
|
TextureType type;
|
||||||
QImage preview;
|
QImage preview;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
NazaraSignal(OnInputListUpdate, ShaderGraph*);
|
||||||
|
NazaraSignal(OnInputUpdate, ShaderGraph*, std::size_t /*inputIndex*/);
|
||||||
NazaraSignal(OnTextureListUpdate, ShaderGraph*);
|
NazaraSignal(OnTextureListUpdate, ShaderGraph*);
|
||||||
NazaraSignal(OnTexturePreviewUpdate, ShaderGraph*, std::size_t /*textureIndex*/);
|
NazaraSignal(OnTexturePreviewUpdate, ShaderGraph*, std::size_t /*textureIndex*/);
|
||||||
|
|
||||||
|
|
@ -42,6 +57,7 @@ class ShaderGraph
|
||||||
std::shared_ptr<QtNodes::DataModelRegistry> BuildRegistry();
|
std::shared_ptr<QtNodes::DataModelRegistry> BuildRegistry();
|
||||||
|
|
||||||
QtNodes::FlowScene m_flowScene;
|
QtNodes::FlowScene m_flowScene;
|
||||||
|
std::vector<InputEntry> m_inputs;
|
||||||
std::vector<TextureEntry> m_textures;
|
std::vector<TextureEntry> m_textures;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,16 @@
|
||||||
#include <ShaderGraph.hpp>
|
#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()
|
inline QtNodes::FlowScene& ShaderGraph::GetScene()
|
||||||
{
|
{
|
||||||
return m_flowScene;
|
return m_flowScene;
|
||||||
|
|
@ -11,7 +22,7 @@ inline auto ShaderGraph::GetTexture(std::size_t textureIndex) const -> const Tex
|
||||||
return m_textures[textureIndex];
|
return m_textures[textureIndex];
|
||||||
}
|
}
|
||||||
|
|
||||||
inline auto ShaderGraph::GetTextures() -> const std::vector<TextureEntry>&
|
inline auto ShaderGraph::GetTextures() const -> const std::vector<TextureEntry>&
|
||||||
{
|
{
|
||||||
return m_textures;
|
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 <Widgets/MainWindow.hpp>
|
||||||
#include <Nazara/Renderer/GlslWriter.hpp>
|
#include <Nazara/Renderer/GlslWriter.hpp>
|
||||||
#include <ShaderGraph.hpp>
|
#include <ShaderGraph.hpp>
|
||||||
|
#include <Widgets/InputEditor.hpp>
|
||||||
#include <Widgets/TextureEditor.hpp>
|
#include <Widgets/TextureEditor.hpp>
|
||||||
#include <nodes/FlowView>
|
#include <nodes/FlowView>
|
||||||
|
#include <QtWidgets/QDockWidget>
|
||||||
#include <QtWidgets/QMenuBar>
|
#include <QtWidgets/QMenuBar>
|
||||||
#include <QtWidgets/QTextEdit>
|
#include <QtWidgets/QTextEdit>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
@ -17,6 +19,13 @@ m_shaderGraph(graph)
|
||||||
QtNodes::FlowView* flowView = new QtNodes::FlowView(scene);
|
QtNodes::FlowView* flowView = new QtNodes::FlowView(scene);
|
||||||
setCentralWidget(flowView);
|
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"));
|
QDockWidget* textureDock = new QDockWidget(tr("&Textures"));
|
||||||
|
|
||||||
TextureEditor* textureEditor = new TextureEditor(m_shaderGraph);
|
TextureEditor* textureEditor = new TextureEditor(m_shaderGraph);
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@
|
||||||
TextureEditor::TextureEditor(ShaderGraph& graph) :
|
TextureEditor::TextureEditor(ShaderGraph& graph) :
|
||||||
m_shaderGraph(graph)
|
m_shaderGraph(graph)
|
||||||
{
|
{
|
||||||
m_textureList = new QListWidget(this);
|
m_textureList = new QListWidget;
|
||||||
connect(m_textureList, &QListWidget::currentRowChanged, this, &TextureEditor::OnTextureSelectionUpdate);
|
connect(m_textureList, &QListWidget::currentRowChanged, this, &TextureEditor::OnTextureSelectionUpdate);
|
||||||
|
|
||||||
m_pixmapLabel = new QLabel;
|
m_pixmapLabel = new QLabel;
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@
|
||||||
#define NAZARA_SHADERNODES_TEXTUREEDITOR_HPP
|
#define NAZARA_SHADERNODES_TEXTUREEDITOR_HPP
|
||||||
|
|
||||||
#include <ShaderGraph.hpp>
|
#include <ShaderGraph.hpp>
|
||||||
#include <QtWidgets/QDockWidget>
|
#include <QtWidgets/QWidget>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
|
|
||||||
class QLabel;
|
class QLabel;
|
||||||
|
|
|
||||||
|
|
@ -8,8 +8,8 @@ int main(int argc, char* argv[])
|
||||||
QApplication app(argc, argv);
|
QApplication app(argc, argv);
|
||||||
|
|
||||||
ShaderGraph shaderGraph;
|
ShaderGraph shaderGraph;
|
||||||
shaderGraph.AddTexture("Potato", Nz::ShaderAst::ExpressionType::Sampler2D);
|
shaderGraph.AddInput("UV", InputType::Float2, InputRole::TexCoord, 0);
|
||||||
shaderGraph.AddTexture("Blackbird", Nz::ShaderAst::ExpressionType::Sampler2D);
|
shaderGraph.AddTexture("Potato", TextureType::Sampler2D);
|
||||||
|
|
||||||
MainWindow mainWindow(shaderGraph);
|
MainWindow mainWindow(shaderGraph);
|
||||||
mainWindow.resize(1280, 720);
|
mainWindow.resize(1280, 720);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue