ShaderAst: Add node editor window
This commit is contained in:
parent
b1b9030359
commit
09e08255fb
|
|
@ -18,13 +18,14 @@ class CastVec : public ShaderNode
|
||||||
CastVec(ShaderGraph& graph);
|
CastVec(ShaderGraph& graph);
|
||||||
~CastVec() = default;
|
~CastVec() = default;
|
||||||
|
|
||||||
|
void BuildNodeEdition(QVBoxLayout* layout) override;
|
||||||
|
|
||||||
Nz::ShaderAst::ExpressionPtr GetExpression(Nz::ShaderAst::ExpressionPtr* expressions, std::size_t count) const override;
|
Nz::ShaderAst::ExpressionPtr GetExpression(Nz::ShaderAst::ExpressionPtr* expressions, std::size_t count) const override;
|
||||||
|
|
||||||
QString caption() const override;
|
QString caption() const override;
|
||||||
QString name() const override;
|
QString name() const override;
|
||||||
|
|
||||||
QtNodes::NodeDataType dataType(QtNodes::PortType portType, QtNodes::PortIndex portIndex) const override;
|
QtNodes::NodeDataType dataType(QtNodes::PortType portType, QtNodes::PortIndex portIndex) const override;
|
||||||
QWidget* embeddedWidget() override;
|
|
||||||
unsigned int nPorts(QtNodes::PortType portType) const override;
|
unsigned int nPorts(QtNodes::PortType portType) const override;
|
||||||
|
|
||||||
std::shared_ptr<QtNodes::NodeData> outData(QtNodes::PortIndex port) override;
|
std::shared_ptr<QtNodes::NodeData> outData(QtNodes::PortIndex port) override;
|
||||||
|
|
@ -36,13 +37,10 @@ class CastVec : public ShaderNode
|
||||||
static constexpr std::size_t ToComponents = To::ComponentCount;
|
static constexpr std::size_t ToComponents = To::ComponentCount;
|
||||||
static constexpr std::size_t ComponentDiff = (ToComponents >= FromComponents) ? ToComponents - FromComponents : 0;
|
static constexpr std::size_t ComponentDiff = (ToComponents >= FromComponents) ? ToComponents - FromComponents : 0;
|
||||||
|
|
||||||
void ComputePreview(QPixmap& pixmap) const;
|
bool ComputePreview(QPixmap& pixmap) override;
|
||||||
void UpdatePreview();
|
void UpdateOutput();
|
||||||
|
|
||||||
QLabel* m_pixmapLabel;
|
VecType<ComponentDiff> m_overflowComponents;
|
||||||
QPixmap m_pixmap;
|
|
||||||
QWidget* m_widget;
|
|
||||||
std::array<QDoubleSpinBox*, ComponentDiff> m_spinboxes;
|
|
||||||
std::shared_ptr<From> m_input;
|
std::shared_ptr<From> m_input;
|
||||||
std::shared_ptr<To> m_output;
|
std::shared_ptr<To> m_output;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -6,41 +6,35 @@ template<typename From, typename To>
|
||||||
CastVec<From, To>::CastVec(ShaderGraph& graph) :
|
CastVec<From, To>::CastVec(ShaderGraph& graph) :
|
||||||
ShaderNode(graph)
|
ShaderNode(graph)
|
||||||
{
|
{
|
||||||
constexpr std::array<char, 4> componentName = { 'X', 'Y', 'Z', 'W' };
|
static_assert(ComponentDiff <= s_vectorComponents.size());
|
||||||
static_assert(ComponentDiff <= componentName.size());
|
}
|
||||||
|
|
||||||
QFormLayout* layout = new QFormLayout;
|
template<typename From, typename To>
|
||||||
|
void CastVec<From, To>::BuildNodeEdition(QVBoxLayout* layout)
|
||||||
|
{
|
||||||
|
ShaderNode::BuildNodeEdition(layout);
|
||||||
|
|
||||||
if constexpr (ComponentDiff > 0)
|
if constexpr (ComponentDiff > 0)
|
||||||
{
|
{
|
||||||
|
QFormLayout* formLayout = new QFormLayout;
|
||||||
|
|
||||||
for (std::size_t i = 0; i < ComponentDiff; ++i)
|
for (std::size_t i = 0; i < ComponentDiff; ++i)
|
||||||
{
|
{
|
||||||
m_spinboxes[i] = new QDoubleSpinBox;
|
QDoubleSpinBox* spinbox = new QDoubleSpinBox;
|
||||||
m_spinboxes[i]->setDecimals(6);
|
spinbox->setDecimals(6);
|
||||||
m_spinboxes[i]->setValue(1.0);
|
spinbox->setValue(m_overflowComponents[i]);
|
||||||
m_spinboxes[i]->setStyleSheet("background-color: rgba(255,255,255,255)");
|
|
||||||
connect(m_spinboxes[i], qOverload<double>(&QDoubleSpinBox::valueChanged), [this](double)
|
connect(spinbox, qOverload<double>(&QDoubleSpinBox::valueChanged), [=](double)
|
||||||
{
|
{
|
||||||
UpdatePreview();
|
m_overflowComponents[i] = spinbox->value();
|
||||||
|
UpdateOutput();
|
||||||
});
|
});
|
||||||
|
|
||||||
layout->addRow(QString::fromUtf8(&componentName[FromComponents + i], 1), m_spinboxes[i]);
|
formLayout->addRow(QString::fromUtf8(&s_vectorComponents[FromComponents + i], 1), spinbox);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
layout->addLayout(formLayout);
|
||||||
}
|
}
|
||||||
|
|
||||||
m_pixmap = QPixmap(64, 64);
|
|
||||||
m_pixmap.fill();
|
|
||||||
|
|
||||||
m_pixmapLabel = new QLabel;
|
|
||||||
m_pixmapLabel->setPixmap(m_pixmap);
|
|
||||||
|
|
||||||
layout->addWidget(m_pixmapLabel);
|
|
||||||
|
|
||||||
m_widget = new QWidget;
|
|
||||||
m_widget->setStyleSheet("background-color: rgba(0,0,0,0)");
|
|
||||||
m_widget->setLayout(layout);
|
|
||||||
|
|
||||||
m_output = std::make_shared<To>();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename From, typename To>
|
template<typename From, typename To>
|
||||||
|
|
@ -52,7 +46,7 @@ Nz::ShaderAst::ExpressionPtr CastVec<From, To>::GetExpression(Nz::ShaderAst::Exp
|
||||||
{
|
{
|
||||||
std::array<Nz::ShaderAst::ExpressionPtr, ComponentDiff> constants;
|
std::array<Nz::ShaderAst::ExpressionPtr, ComponentDiff> constants;
|
||||||
for (std::size_t i = 0; i < ComponentDiff; ++i)
|
for (std::size_t i = 0; i < ComponentDiff; ++i)
|
||||||
constants[i] = Nz::ShaderBuilder::Constant(float(m_spinboxes[i]->value()));
|
constants[i] = Nz::ShaderBuilder::Constant(m_overflowComponents[i]);
|
||||||
|
|
||||||
return std::apply([&](auto&&... values)
|
return std::apply([&](auto&&... values)
|
||||||
{
|
{
|
||||||
|
|
@ -102,12 +96,6 @@ QtNodes::NodeDataType CastVec<From, To>::dataType(QtNodes::PortType portType, Qt
|
||||||
throw std::runtime_error("Invalid port type");
|
throw std::runtime_error("Invalid port type");
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename From, typename To>
|
|
||||||
QWidget* CastVec<From, To>::embeddedWidget()
|
|
||||||
{
|
|
||||||
return m_widget;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename From, typename To>
|
template<typename From, typename To>
|
||||||
unsigned int CastVec<From, To>::nPorts(QtNodes::PortType portType) const
|
unsigned int CastVec<From, To>::nPorts(QtNodes::PortType portType) const
|
||||||
{
|
{
|
||||||
|
|
@ -124,6 +112,10 @@ template<typename From, typename To>
|
||||||
std::shared_ptr<QtNodes::NodeData> CastVec<From, To>::outData(QtNodes::PortIndex port)
|
std::shared_ptr<QtNodes::NodeData> CastVec<From, To>::outData(QtNodes::PortIndex port)
|
||||||
{
|
{
|
||||||
assert(port == 0);
|
assert(port == 0);
|
||||||
|
|
||||||
|
if (!m_input)
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
return m_output;
|
return m_output;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -139,13 +131,28 @@ void CastVec<From, To>::setInData(std::shared_ptr<QtNodes::NodeData> value, int
|
||||||
else
|
else
|
||||||
m_input.reset();
|
m_input.reset();
|
||||||
|
|
||||||
UpdatePreview();
|
UpdateOutput();
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename From, typename To>
|
template<typename From, typename To>
|
||||||
void CastVec<From, To>::ComputePreview(QPixmap& pixmap) const
|
bool CastVec<From, To>::ComputePreview(QPixmap& pixmap)
|
||||||
{
|
{
|
||||||
assert(m_input);
|
if (!m_input)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
pixmap = QPixmap::fromImage(m_output->preview);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename From, typename To>
|
||||||
|
void CastVec<From, To>::UpdateOutput()
|
||||||
|
{
|
||||||
|
if (!m_input)
|
||||||
|
{
|
||||||
|
m_output->preview = QImage(1, 1, QImage::Format_RGBA8888);
|
||||||
|
m_output->preview.fill(QColor::fromRgb(0, 0, 0, 0));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const QImage& input = m_input->preview;
|
const QImage& input = m_input->preview;
|
||||||
|
|
||||||
|
|
@ -156,8 +163,11 @@ void CastVec<From, To>::ComputePreview(QPixmap& pixmap) const
|
||||||
output = QImage(inputWidth, inputHeight, QImage::Format_RGBA8888);
|
output = QImage(inputWidth, inputHeight, QImage::Format_RGBA8888);
|
||||||
|
|
||||||
std::array<std::uint8_t, ComponentDiff> constants;
|
std::array<std::uint8_t, ComponentDiff> constants;
|
||||||
for (std::size_t i = 0; i < ComponentDiff; ++i)
|
if constexpr (ComponentDiff > 0)
|
||||||
constants[i] = static_cast<std::uint8_t>(std::clamp(int(m_spinboxes[i]->value() * 255), 0, 255));
|
{
|
||||||
|
for (std::size_t i = 0; i < ComponentDiff; ++i)
|
||||||
|
constants[i] = static_cast<std::uint8_t>(std::clamp(int(m_overflowComponents[i] * 255), 0, 255));
|
||||||
|
}
|
||||||
|
|
||||||
std::uint8_t* outputPtr = output.bits();
|
std::uint8_t* outputPtr = output.bits();
|
||||||
const std::uint8_t* inputPtr = input.constBits();
|
const std::uint8_t* inputPtr = input.constBits();
|
||||||
|
|
@ -181,21 +191,7 @@ void CastVec<From, To>::ComputePreview(QPixmap& pixmap) const
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pixmap = QPixmap::fromImage(output).scaled(64, 64);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename From, typename To>
|
|
||||||
void CastVec<From, To>::UpdatePreview()
|
|
||||||
{
|
|
||||||
if (!m_input)
|
|
||||||
{
|
|
||||||
m_pixmap = QPixmap(64, 64);
|
|
||||||
m_pixmap.fill(QColor::fromRgb(255, 255, 255, 0));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
ComputePreview(m_pixmap);
|
|
||||||
|
|
||||||
m_pixmapLabel->setPixmap(m_pixmap);
|
|
||||||
|
|
||||||
Q_EMIT dataUpdated(0);
|
Q_EMIT dataUpdated(0);
|
||||||
|
|
||||||
|
UpdatePreview();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -22,11 +22,6 @@ QtNodes::NodeDataType FragmentOutput::dataType(QtNodes::PortType portType, QtNod
|
||||||
return Vec4Data::Type();
|
return Vec4Data::Type();
|
||||||
}
|
}
|
||||||
|
|
||||||
QWidget* FragmentOutput::embeddedWidget()
|
|
||||||
{
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int FragmentOutput::nPorts(QtNodes::PortType portType) const
|
unsigned int FragmentOutput::nPorts(QtNodes::PortType portType) const
|
||||||
{
|
{
|
||||||
switch (portType)
|
switch (portType)
|
||||||
|
|
@ -42,3 +37,26 @@ std::shared_ptr<QtNodes::NodeData> FragmentOutput::outData(QtNodes::PortIndex /*
|
||||||
{
|
{
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void FragmentOutput::setInData(std::shared_ptr<QtNodes::NodeData> value, int index)
|
||||||
|
{
|
||||||
|
assert(index == 0);
|
||||||
|
if (value)
|
||||||
|
{
|
||||||
|
assert(dynamic_cast<Vec4Data*>(value.get()) != nullptr);
|
||||||
|
m_input = std::static_pointer_cast<Vec4Data>(value);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
m_input.reset();
|
||||||
|
|
||||||
|
UpdatePreview();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FragmentOutput::ComputePreview(QPixmap& pixmap)
|
||||||
|
{
|
||||||
|
if (!m_input)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
pixmap = QPixmap::fromImage(m_input->preview);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@
|
||||||
#define NAZARA_SHADERNODES_FRAGMENTOUTPUT_HPP
|
#define NAZARA_SHADERNODES_FRAGMENTOUTPUT_HPP
|
||||||
|
|
||||||
#include <ShaderNode/DataModels/ShaderNode.hpp>
|
#include <ShaderNode/DataModels/ShaderNode.hpp>
|
||||||
|
#include <ShaderNode/DataModels/VecValue.hpp>
|
||||||
#include <QtWidgets/QDoubleSpinBox>
|
#include <QtWidgets/QDoubleSpinBox>
|
||||||
#include <QtWidgets/QFormLayout>
|
#include <QtWidgets/QFormLayout>
|
||||||
|
|
||||||
|
|
@ -19,13 +20,16 @@ class FragmentOutput : public ShaderNode
|
||||||
|
|
||||||
QtNodes::NodeDataType dataType(QtNodes::PortType portType, QtNodes::PortIndex portIndex) const override;
|
QtNodes::NodeDataType dataType(QtNodes::PortType portType, QtNodes::PortIndex portIndex) const override;
|
||||||
|
|
||||||
QWidget* embeddedWidget() override;
|
|
||||||
unsigned int nPorts(QtNodes::PortType portType) const override;
|
unsigned int nPorts(QtNodes::PortType portType) const override;
|
||||||
|
|
||||||
std::shared_ptr<QtNodes::NodeData> outData(QtNodes::PortIndex port) override;
|
std::shared_ptr<QtNodes::NodeData> outData(QtNodes::PortIndex port) override;
|
||||||
|
|
||||||
void setInData(std::shared_ptr<QtNodes::NodeData>, int) override {};
|
void setInData(std::shared_ptr<QtNodes::NodeData> value, int index) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool ComputePreview(QPixmap& pixmap) override;
|
||||||
|
|
||||||
|
std::shared_ptr<Vec4Data> m_input;
|
||||||
};
|
};
|
||||||
|
|
||||||
#include <ShaderNode/DataModels/FragmentOutput.inl>
|
#include <ShaderNode/DataModels/FragmentOutput.inl>
|
||||||
|
|
|
||||||
|
|
@ -3,4 +3,6 @@
|
||||||
inline FragmentOutput::FragmentOutput(ShaderGraph& graph) :
|
inline FragmentOutput::FragmentOutput(ShaderGraph& graph) :
|
||||||
ShaderNode(graph)
|
ShaderNode(graph)
|
||||||
{
|
{
|
||||||
|
SetPreviewSize({ 128, 128 });
|
||||||
|
EnablePreview(true);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,48 +4,18 @@
|
||||||
#include <Nazara/Renderer/ShaderBuilder.hpp>
|
#include <Nazara/Renderer/ShaderBuilder.hpp>
|
||||||
|
|
||||||
InputValue::InputValue(ShaderGraph& graph) :
|
InputValue::InputValue(ShaderGraph& graph) :
|
||||||
ShaderNode(graph),
|
ShaderNode(graph)
|
||||||
m_currentInputIndex(0)
|
|
||||||
{
|
{
|
||||||
m_layout = new QVBoxLayout;
|
m_onInputListUpdateSlot.Connect(GetGraph().OnInputListUpdate, [&](ShaderGraph*) { OnInputListUpdate(); });
|
||||||
|
|
||||||
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)
|
m_onInputUpdateSlot.Connect(GetGraph().OnInputUpdate, [&](ShaderGraph*, std::size_t inputIndex)
|
||||||
{
|
{
|
||||||
if (m_currentInputIndex == inputIndex)
|
if (m_currentInputIndex == inputIndex)
|
||||||
UpdatePreview();
|
UpdatePreview();
|
||||||
});
|
});
|
||||||
|
|
||||||
UpdateInputList();
|
|
||||||
UpdatePreview();
|
UpdatePreview();
|
||||||
}
|
}
|
||||||
|
|
||||||
QWidget* InputValue::embeddedWidget()
|
|
||||||
{
|
|
||||||
return m_widget;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int InputValue::nPorts(QtNodes::PortType portType) const
|
unsigned int InputValue::nPorts(QtNodes::PortType portType) const
|
||||||
{
|
{
|
||||||
switch (portType)
|
switch (portType)
|
||||||
|
|
@ -57,36 +27,66 @@ unsigned int InputValue::nPorts(QtNodes::PortType portType) const
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void InputValue::UpdatePreview()
|
bool InputValue::ComputePreview(QPixmap& pixmap)
|
||||||
{
|
{
|
||||||
if (m_inputSelection->count() == 0)
|
if (!m_currentInputIndex)
|
||||||
return;
|
return false;
|
||||||
|
|
||||||
const ShaderGraph& graph = GetGraph();
|
const ShaderGraph& graph = GetGraph();
|
||||||
const auto& inputEntry = graph.GetInput(m_currentInputIndex);
|
const auto& inputEntry = graph.GetInput(*m_currentInputIndex);
|
||||||
const auto& preview = graph.GetPreviewModel();
|
const auto& preview = graph.GetPreviewModel();
|
||||||
|
|
||||||
m_previewLabel->setPixmap(QPixmap::fromImage(preview.GetImage(inputEntry.role, inputEntry.roleIndex)));
|
pixmap = QPixmap::fromImage(preview.GetImage(inputEntry.role, inputEntry.roleIndex));
|
||||||
|
return true;
|
||||||
Q_EMIT dataUpdated(0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void InputValue::UpdateInputList()
|
void InputValue::OnInputListUpdate()
|
||||||
{
|
{
|
||||||
QString currentInput = m_inputSelection->currentText();
|
m_currentInputIndex.reset();
|
||||||
m_inputSelection->clear();
|
|
||||||
|
std::size_t inputIndex = 0;
|
||||||
|
for (const auto& inputEntry : GetGraph().GetInputs())
|
||||||
|
{
|
||||||
|
if (inputEntry.name == m_currentInputText)
|
||||||
|
{
|
||||||
|
m_currentInputIndex = inputIndex;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
inputIndex++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void InputValue::BuildNodeEdition(QVBoxLayout* layout)
|
||||||
|
{
|
||||||
|
ShaderNode::BuildNodeEdition(layout);
|
||||||
|
|
||||||
|
QComboBox* inputSelection = new QComboBox;
|
||||||
|
|
||||||
|
connect(inputSelection, qOverload<int>(&QComboBox::currentIndexChanged), [&](int index)
|
||||||
|
{
|
||||||
|
if (index >= 0)
|
||||||
|
m_currentInputIndex = static_cast<std::size_t>(index);
|
||||||
|
else
|
||||||
|
m_currentInputIndex.reset();
|
||||||
|
|
||||||
|
UpdatePreview();
|
||||||
|
});
|
||||||
|
|
||||||
for (const auto& inputEntry : GetGraph().GetInputs())
|
for (const auto& inputEntry : GetGraph().GetInputs())
|
||||||
m_inputSelection->addItem(QString::fromStdString(inputEntry.name));
|
inputSelection->addItem(QString::fromStdString(inputEntry.name));
|
||||||
|
|
||||||
m_inputSelection->setCurrentText(currentInput);
|
layout->addWidget(inputSelection);
|
||||||
}
|
}
|
||||||
|
|
||||||
Nz::ShaderAst::ExpressionPtr InputValue::GetExpression(Nz::ShaderAst::ExpressionPtr* /*expressions*/, std::size_t count) const
|
Nz::ShaderAst::ExpressionPtr InputValue::GetExpression(Nz::ShaderAst::ExpressionPtr* /*expressions*/, std::size_t count) const
|
||||||
{
|
{
|
||||||
assert(count == 0);
|
assert(count == 0);
|
||||||
|
|
||||||
const auto& inputEntry = GetGraph().GetInput(m_currentInputIndex);
|
if (!m_currentInputIndex)
|
||||||
|
throw std::runtime_error("no input");
|
||||||
|
|
||||||
|
const auto& inputEntry = GetGraph().GetInput(*m_currentInputIndex);
|
||||||
|
|
||||||
Nz::ShaderAst::ExpressionType expression = [&]
|
Nz::ShaderAst::ExpressionType expression = [&]
|
||||||
{
|
{
|
||||||
|
|
@ -108,10 +108,13 @@ Nz::ShaderAst::ExpressionPtr InputValue::GetExpression(Nz::ShaderAst::Expression
|
||||||
|
|
||||||
auto InputValue::dataType(QtNodes::PortType portType, QtNodes::PortIndex portIndex) const -> QtNodes::NodeDataType
|
auto InputValue::dataType(QtNodes::PortType portType, QtNodes::PortIndex portIndex) const -> QtNodes::NodeDataType
|
||||||
{
|
{
|
||||||
|
if (!m_currentInputIndex)
|
||||||
|
return Vec4Data::Type();
|
||||||
|
|
||||||
assert(portType == QtNodes::PortType::Out);
|
assert(portType == QtNodes::PortType::Out);
|
||||||
assert(portIndex == 0);
|
assert(portIndex == 0);
|
||||||
|
|
||||||
const auto& inputEntry = GetGraph().GetInput(m_currentInputIndex);
|
const auto& inputEntry = GetGraph().GetInput(*m_currentInputIndex);
|
||||||
switch (inputEntry.type)
|
switch (inputEntry.type)
|
||||||
{
|
{
|
||||||
//case InputType::Bool: return Nz::ShaderAst::ExpressionType::Boolean;
|
//case InputType::Bool: return Nz::ShaderAst::ExpressionType::Boolean;
|
||||||
|
|
@ -127,10 +130,13 @@ auto InputValue::dataType(QtNodes::PortType portType, QtNodes::PortIndex portInd
|
||||||
|
|
||||||
std::shared_ptr<QtNodes::NodeData> InputValue::outData(QtNodes::PortIndex port)
|
std::shared_ptr<QtNodes::NodeData> InputValue::outData(QtNodes::PortIndex port)
|
||||||
{
|
{
|
||||||
|
if (!m_currentInputIndex)
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
assert(port == 0);
|
assert(port == 0);
|
||||||
|
|
||||||
const ShaderGraph& graph = GetGraph();
|
const ShaderGraph& graph = GetGraph();
|
||||||
const auto& inputEntry = graph.GetInput(m_currentInputIndex);
|
const auto& inputEntry = graph.GetInput(*m_currentInputIndex);
|
||||||
const auto& preview = graph.GetPreviewModel();
|
const auto& preview = graph.GetPreviewModel();
|
||||||
|
|
||||||
auto vecData = std::make_shared<Vec2Data>();
|
auto vecData = std::make_shared<Vec2Data>();
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@
|
||||||
#include <ShaderNode/ShaderGraph.hpp>
|
#include <ShaderNode/ShaderGraph.hpp>
|
||||||
#include <ShaderNode/DataModels/ShaderNode.hpp>
|
#include <ShaderNode/DataModels/ShaderNode.hpp>
|
||||||
#include <array>
|
#include <array>
|
||||||
|
#include <optional>
|
||||||
|
|
||||||
class InputValue : public ShaderNode
|
class InputValue : public ShaderNode
|
||||||
{
|
{
|
||||||
|
|
@ -16,30 +17,28 @@ class InputValue : public ShaderNode
|
||||||
InputValue(ShaderGraph& graph);
|
InputValue(ShaderGraph& graph);
|
||||||
~InputValue() = default;
|
~InputValue() = default;
|
||||||
|
|
||||||
|
void BuildNodeEdition(QVBoxLayout* layout) override;
|
||||||
|
|
||||||
Nz::ShaderAst::ExpressionPtr GetExpression(Nz::ShaderAst::ExpressionPtr* /*expressions*/, std::size_t count) const override;
|
Nz::ShaderAst::ExpressionPtr GetExpression(Nz::ShaderAst::ExpressionPtr* /*expressions*/, std::size_t count) const override;
|
||||||
|
|
||||||
QString caption() const override { return "Input"; }
|
QString caption() const override { return "Input"; }
|
||||||
QString name() const override { return "Input"; }
|
QString name() const override { return "Input"; }
|
||||||
|
|
||||||
QWidget* embeddedWidget() override;
|
|
||||||
unsigned int nPorts(QtNodes::PortType portType) const override;
|
unsigned int nPorts(QtNodes::PortType portType) const override;
|
||||||
|
|
||||||
QtNodes::NodeDataType dataType(QtNodes::PortType portType, QtNodes::PortIndex portIndex) const override;
|
QtNodes::NodeDataType dataType(QtNodes::PortType portType, QtNodes::PortIndex portIndex) const override;
|
||||||
|
|
||||||
std::shared_ptr<QtNodes::NodeData> outData(QtNodes::PortIndex port) override;
|
std::shared_ptr<QtNodes::NodeData> outData(QtNodes::PortIndex port) override;
|
||||||
|
|
||||||
protected:
|
private:
|
||||||
void UpdatePreview();
|
bool ComputePreview(QPixmap& pixmap) override;
|
||||||
void UpdateInputList();
|
void OnInputListUpdate();
|
||||||
|
|
||||||
NazaraSlot(ShaderGraph, OnInputListUpdate, m_onInputListUpdateSlot);
|
NazaraSlot(ShaderGraph, OnInputListUpdate, m_onInputListUpdateSlot);
|
||||||
NazaraSlot(ShaderGraph, OnInputUpdate, m_onInputUpdateSlot);
|
NazaraSlot(ShaderGraph, OnInputUpdate, m_onInputUpdateSlot);
|
||||||
|
|
||||||
std::size_t m_currentInputIndex;
|
std::optional<std::size_t> m_currentInputIndex;
|
||||||
QComboBox* m_inputSelection;
|
std::string m_currentInputText;
|
||||||
QLabel* m_previewLabel;
|
|
||||||
QWidget* m_widget;
|
|
||||||
QVBoxLayout* m_layout;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#include <ShaderNode/DataModels/InputValue.inl>
|
#include <ShaderNode/DataModels/InputValue.inl>
|
||||||
|
|
|
||||||
|
|
@ -4,52 +4,16 @@
|
||||||
#include <Nazara/Renderer/ShaderBuilder.hpp>
|
#include <Nazara/Renderer/ShaderBuilder.hpp>
|
||||||
|
|
||||||
SampleTexture::SampleTexture(ShaderGraph& graph) :
|
SampleTexture::SampleTexture(ShaderGraph& graph) :
|
||||||
ShaderNode(graph),
|
ShaderNode(graph)
|
||||||
m_currentTextureIndex(0)
|
|
||||||
{
|
{
|
||||||
m_output = std::make_shared<Vec4Data>();
|
m_output = std::make_shared<Vec4Data>();
|
||||||
|
|
||||||
m_layout = new QVBoxLayout;
|
m_onTextureListUpdateSlot.Connect(GetGraph().OnTextureListUpdate, [&](ShaderGraph*) { OnTextureListUpdate(); });
|
||||||
|
|
||||||
m_textureSelection = new QComboBox;
|
|
||||||
m_textureSelection->setStyleSheet("background-color: rgba(255,255,255,255)");
|
|
||||||
connect(m_textureSelection, qOverload<int>(&QComboBox::currentIndexChanged), [&](int index)
|
|
||||||
{
|
|
||||||
if (index < 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
m_currentTextureIndex = static_cast<std::size_t>(index);
|
|
||||||
UpdatePreview();
|
|
||||||
});
|
|
||||||
|
|
||||||
m_layout->addWidget(m_textureSelection);
|
|
||||||
|
|
||||||
m_pixmap = QPixmap(64, 64);
|
|
||||||
m_pixmap.fill();
|
|
||||||
|
|
||||||
m_pixmapLabel = new QLabel;
|
|
||||||
m_pixmapLabel->setPixmap(m_pixmap);
|
|
||||||
|
|
||||||
m_layout->addWidget(m_pixmapLabel);
|
|
||||||
|
|
||||||
m_widget = new QWidget;
|
|
||||||
m_widget->setStyleSheet("background-color: rgba(0,0,0,0)");
|
|
||||||
m_widget->setLayout(m_layout);
|
|
||||||
|
|
||||||
m_onTextureListUpdateSlot.Connect(GetGraph().OnTextureListUpdate, [&](ShaderGraph*) { UpdateTextureList(); });
|
|
||||||
m_onTexturePreviewUpdateSlot.Connect(GetGraph().OnTexturePreviewUpdate, [&](ShaderGraph*, std::size_t textureIndex)
|
m_onTexturePreviewUpdateSlot.Connect(GetGraph().OnTexturePreviewUpdate, [&](ShaderGraph*, std::size_t textureIndex)
|
||||||
{
|
{
|
||||||
if (m_currentTextureIndex == textureIndex)
|
if (m_currentTextureIndex == textureIndex)
|
||||||
UpdatePreview();
|
UpdatePreview();
|
||||||
});
|
});
|
||||||
|
|
||||||
UpdateTextureList();
|
|
||||||
UpdatePreview();
|
|
||||||
}
|
|
||||||
|
|
||||||
QWidget* SampleTexture::embeddedWidget()
|
|
||||||
{
|
|
||||||
return m_widget;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int SampleTexture::nPorts(QtNodes::PortType portType) const
|
unsigned int SampleTexture::nPorts(QtNodes::PortType portType) const
|
||||||
|
|
@ -63,39 +27,39 @@ unsigned int SampleTexture::nPorts(QtNodes::PortType portType) const
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SampleTexture::UpdatePreview()
|
void SampleTexture::OnTextureListUpdate()
|
||||||
{
|
{
|
||||||
if (m_textureSelection->count() == 0)
|
m_currentTextureIndex.reset();
|
||||||
return;
|
|
||||||
|
|
||||||
ComputePreview(m_pixmap);
|
|
||||||
m_pixmapLabel->setPixmap(m_pixmap);
|
|
||||||
|
|
||||||
Q_EMIT dataUpdated(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SampleTexture::UpdateTextureList()
|
|
||||||
{
|
|
||||||
QString currentTexture = m_textureSelection->currentText();
|
|
||||||
m_textureSelection->clear();
|
|
||||||
|
|
||||||
|
std::size_t inputIndex = 0;
|
||||||
for (const auto& textureEntry : GetGraph().GetTextures())
|
for (const auto& textureEntry : GetGraph().GetTextures())
|
||||||
m_textureSelection->addItem(QString::fromStdString(textureEntry.name));
|
{
|
||||||
|
if (textureEntry.name == m_currentTextureText)
|
||||||
|
{
|
||||||
|
m_currentTextureIndex = inputIndex;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
m_textureSelection->setCurrentText(currentTexture);
|
inputIndex++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SampleTexture::ComputePreview(QPixmap& pixmap) const
|
void SampleTexture::UpdateOutput()
|
||||||
{
|
{
|
||||||
if (!m_uv)
|
QImage& output = m_output->preview;
|
||||||
return;
|
|
||||||
|
|
||||||
const auto& textureEntry = GetGraph().GetTexture(m_currentTextureIndex);
|
if (!m_currentTextureIndex || !m_uv)
|
||||||
|
{
|
||||||
|
output = QImage(1, 1, QImage::Format_RGBA8888);
|
||||||
|
output.fill(QColor::fromRgb(0, 0, 0, 0));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto& textureEntry = GetGraph().GetTexture(*m_currentTextureIndex);
|
||||||
|
|
||||||
int textureWidth = textureEntry.preview.width();
|
int textureWidth = textureEntry.preview.width();
|
||||||
int textureHeight = textureEntry.preview.height();
|
int textureHeight = textureEntry.preview.height();
|
||||||
|
|
||||||
QImage& output = m_output->preview;
|
|
||||||
const QImage& uv = m_uv->preview;
|
const QImage& uv = m_uv->preview;
|
||||||
|
|
||||||
int uvWidth = uv.width();
|
int uvWidth = uv.width();
|
||||||
|
|
@ -125,14 +89,49 @@ void SampleTexture::ComputePreview(QPixmap& pixmap) const
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pixmap = QPixmap::fromImage(output).scaled(128, 128, Qt::KeepAspectRatio);
|
Q_EMIT dataUpdated(0);
|
||||||
|
|
||||||
|
UpdatePreview();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SampleTexture::ComputePreview(QPixmap& pixmap)
|
||||||
|
{
|
||||||
|
if (!m_currentTextureIndex || !m_uv)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
pixmap = QPixmap::fromImage(m_output->preview);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SampleTexture::BuildNodeEdition(QVBoxLayout* layout)
|
||||||
|
{
|
||||||
|
ShaderNode::BuildNodeEdition(layout);
|
||||||
|
|
||||||
|
QComboBox* textureSelection = new QComboBox;
|
||||||
|
connect(textureSelection, qOverload<int>(&QComboBox::currentIndexChanged), [&](int index)
|
||||||
|
{
|
||||||
|
if (index >= 0)
|
||||||
|
m_currentTextureIndex = static_cast<std::size_t>(index);
|
||||||
|
else
|
||||||
|
m_currentTextureIndex.reset();
|
||||||
|
|
||||||
|
UpdateOutput();
|
||||||
|
});
|
||||||
|
|
||||||
|
for (const auto& textureEntry : GetGraph().GetTextures())
|
||||||
|
textureSelection->addItem(QString::fromStdString(textureEntry.name));
|
||||||
|
|
||||||
|
layout->addWidget(textureSelection);
|
||||||
}
|
}
|
||||||
|
|
||||||
Nz::ShaderAst::ExpressionPtr SampleTexture::GetExpression(Nz::ShaderAst::ExpressionPtr* expressions, std::size_t count) const
|
Nz::ShaderAst::ExpressionPtr SampleTexture::GetExpression(Nz::ShaderAst::ExpressionPtr* expressions, std::size_t count) const
|
||||||
{
|
{
|
||||||
|
if (!m_currentTextureIndex || !m_uv)
|
||||||
|
throw std::runtime_error("invalid inputs");
|
||||||
|
|
||||||
assert(count == 1);
|
assert(count == 1);
|
||||||
|
|
||||||
const auto& textureEntry = GetGraph().GetTexture(m_currentTextureIndex);
|
const auto& textureEntry = GetGraph().GetTexture(*m_currentTextureIndex);
|
||||||
|
|
||||||
Nz::ShaderAst::ExpressionType expression = [&]
|
Nz::ShaderAst::ExpressionType expression = [&]
|
||||||
{
|
{
|
||||||
|
|
@ -203,6 +202,9 @@ std::shared_ptr<QtNodes::NodeData> SampleTexture::outData(QtNodes::PortIndex por
|
||||||
{
|
{
|
||||||
assert(port == 0);
|
assert(port == 0);
|
||||||
|
|
||||||
|
if (!m_currentTextureIndex)
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
return m_output;
|
return m_output;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -219,5 +221,5 @@ void SampleTexture::setInData(std::shared_ptr<QtNodes::NodeData> value, int inde
|
||||||
else
|
else
|
||||||
m_uv.reset();
|
m_uv.reset();
|
||||||
|
|
||||||
UpdatePreview();
|
UpdateOutput();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -17,12 +17,13 @@ class SampleTexture : public ShaderNode
|
||||||
SampleTexture(ShaderGraph& graph);
|
SampleTexture(ShaderGraph& graph);
|
||||||
~SampleTexture() = default;
|
~SampleTexture() = default;
|
||||||
|
|
||||||
|
void BuildNodeEdition(QVBoxLayout* layout) override;
|
||||||
|
|
||||||
Nz::ShaderAst::ExpressionPtr GetExpression(Nz::ShaderAst::ExpressionPtr* /*expressions*/, std::size_t count) const override;
|
Nz::ShaderAst::ExpressionPtr GetExpression(Nz::ShaderAst::ExpressionPtr* /*expressions*/, std::size_t count) const override;
|
||||||
|
|
||||||
QString caption() const override { return "Sample texture"; }
|
QString caption() const override { return "Sample texture"; }
|
||||||
QString name() const override { return "SampleTexture"; }
|
QString name() const override { return "SampleTexture"; }
|
||||||
|
|
||||||
QWidget* embeddedWidget() override;
|
|
||||||
unsigned int nPorts(QtNodes::PortType portType) const override;
|
unsigned int nPorts(QtNodes::PortType portType) const override;
|
||||||
|
|
||||||
QtNodes::NodeDataType dataType(QtNodes::PortType portType, QtNodes::PortIndex portIndex) const override;
|
QtNodes::NodeDataType dataType(QtNodes::PortType portType, QtNodes::PortIndex portIndex) const override;
|
||||||
|
|
@ -36,21 +37,17 @@ class SampleTexture : public ShaderNode
|
||||||
void setInData(std::shared_ptr<QtNodes::NodeData> value, int index) override;
|
void setInData(std::shared_ptr<QtNodes::NodeData> value, int index) override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void ComputePreview(QPixmap& pixmap) const;
|
bool ComputePreview(QPixmap& pixmap) override;
|
||||||
void UpdatePreview();
|
void OnTextureListUpdate();
|
||||||
void UpdateTextureList();
|
void UpdateOutput();
|
||||||
|
|
||||||
NazaraSlot(ShaderGraph, OnTextureListUpdate, m_onTextureListUpdateSlot);
|
NazaraSlot(ShaderGraph, OnTextureListUpdate, m_onTextureListUpdateSlot);
|
||||||
NazaraSlot(ShaderGraph, OnTexturePreviewUpdate, m_onTexturePreviewUpdateSlot);
|
NazaraSlot(ShaderGraph, OnTexturePreviewUpdate, m_onTexturePreviewUpdateSlot);
|
||||||
|
|
||||||
std::size_t m_currentTextureIndex;
|
std::optional<std::size_t> m_currentTextureIndex;
|
||||||
std::shared_ptr<Vec2Data> m_uv;
|
std::shared_ptr<Vec2Data> m_uv;
|
||||||
std::shared_ptr<Vec4Data> m_output;
|
std::shared_ptr<Vec4Data> m_output;
|
||||||
QComboBox* m_textureSelection;
|
std::string m_currentTextureText;
|
||||||
QLabel* m_pixmapLabel;
|
|
||||||
QPixmap m_pixmap;
|
|
||||||
QWidget* m_widget;
|
|
||||||
QVBoxLayout* m_layout;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#include <ShaderNode/DataModels/SampleTexture.inl>
|
#include <ShaderNode/DataModels/SampleTexture.inl>
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,81 @@
|
||||||
#include <ShaderNode/DataModels/ShaderNode.hpp>
|
#include <ShaderNode/DataModels/ShaderNode.hpp>
|
||||||
|
#include <QtWidgets/QCheckBox>
|
||||||
|
#include <QtWidgets/QLabel>
|
||||||
|
#include <QtWidgets/QVBoxLayout>
|
||||||
|
|
||||||
|
ShaderNode::ShaderNode(ShaderGraph& graph) :
|
||||||
|
m_previewSize(64, 64),
|
||||||
|
m_pixmapLabel(nullptr),
|
||||||
|
m_graph(graph),
|
||||||
|
m_isPreviewEnabled(false)
|
||||||
|
{
|
||||||
|
m_pixmapLabel = new QLabel;
|
||||||
|
m_pixmapLabel->setStyleSheet("background-color: rgba(0,0,0,0)");
|
||||||
|
}
|
||||||
|
|
||||||
|
void ShaderNode::BuildNodeEdition(QVBoxLayout* layout)
|
||||||
|
{
|
||||||
|
QCheckBox* checkbox = new QCheckBox(tr("Enable preview"));
|
||||||
|
checkbox->setCheckState((m_isPreviewEnabled) ? Qt::Checked : Qt::Unchecked);
|
||||||
|
|
||||||
|
connect(checkbox, &QCheckBox::stateChanged, [&](int state)
|
||||||
|
{
|
||||||
|
EnablePreview(state == Qt::Checked);
|
||||||
|
});
|
||||||
|
|
||||||
|
layout->addWidget(checkbox);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ShaderNode::EnablePreview(bool enable)
|
||||||
|
{
|
||||||
|
if (m_isPreviewEnabled != enable)
|
||||||
|
{
|
||||||
|
m_isPreviewEnabled = enable;
|
||||||
|
|
||||||
|
if (m_isPreviewEnabled)
|
||||||
|
{
|
||||||
|
m_pixmap.emplace(m_previewSize.x, m_previewSize.y);
|
||||||
|
|
||||||
|
UpdatePreview();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_pixmapLabel->clear();
|
||||||
|
m_pixmap.reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
embeddedWidgetSizeUpdated();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QWidget* ShaderNode::embeddedWidget()
|
||||||
|
{
|
||||||
|
return m_pixmapLabel;
|
||||||
|
}
|
||||||
|
|
||||||
void ShaderNode::setInData(std::shared_ptr<QtNodes::NodeData>, int)
|
void ShaderNode::setInData(std::shared_ptr<QtNodes::NodeData>, int)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool ShaderNode::ComputePreview(QPixmap& /*pixmap*/)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ShaderNode::UpdatePreview()
|
||||||
|
{
|
||||||
|
if (!m_pixmap)
|
||||||
|
return;
|
||||||
|
|
||||||
|
QPixmap& pixmap = *m_pixmap;
|
||||||
|
|
||||||
|
if (!ComputePreview(pixmap))
|
||||||
|
{
|
||||||
|
pixmap = QPixmap(m_previewSize.x, m_previewSize.y);
|
||||||
|
pixmap.fill(QColor::fromRgb(255, 255, 255, 0));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
pixmap = pixmap.scaled(m_previewSize.x, m_previewSize.y);
|
||||||
|
|
||||||
|
m_pixmapLabel->setPixmap(pixmap);
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,24 +3,46 @@
|
||||||
#ifndef NAZARA_SHADERNODES_SHADERNODE_HPP
|
#ifndef NAZARA_SHADERNODES_SHADERNODE_HPP
|
||||||
#define NAZARA_SHADERNODES_SHADERNODE_HPP
|
#define NAZARA_SHADERNODES_SHADERNODE_HPP
|
||||||
|
|
||||||
|
#include <Nazara/Math/Vector2.hpp>
|
||||||
#include <Nazara/Renderer/ShaderAst.hpp>
|
#include <Nazara/Renderer/ShaderAst.hpp>
|
||||||
#include <nodes/NodeDataModel>
|
#include <nodes/NodeDataModel>
|
||||||
|
#include <QtGui/QPixmap>
|
||||||
|
#include <optional>
|
||||||
|
|
||||||
|
class QLabel;
|
||||||
|
class QVBoxLayout;
|
||||||
class ShaderGraph;
|
class ShaderGraph;
|
||||||
|
|
||||||
class ShaderNode : public QtNodes::NodeDataModel
|
class ShaderNode : public QtNodes::NodeDataModel
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
inline ShaderNode(ShaderGraph& graph);
|
ShaderNode(ShaderGraph& graph);
|
||||||
|
|
||||||
|
virtual void BuildNodeEdition(QVBoxLayout* layout);
|
||||||
|
|
||||||
|
void EnablePreview(bool enable);
|
||||||
|
|
||||||
virtual Nz::ShaderAst::ExpressionPtr GetExpression(Nz::ShaderAst::ExpressionPtr* expressions, std::size_t count) const = 0;
|
virtual Nz::ShaderAst::ExpressionPtr GetExpression(Nz::ShaderAst::ExpressionPtr* expressions, std::size_t count) const = 0;
|
||||||
inline ShaderGraph& GetGraph();
|
inline ShaderGraph& GetGraph();
|
||||||
inline const ShaderGraph& GetGraph() const;
|
inline const ShaderGraph& GetGraph() const;
|
||||||
|
|
||||||
|
void SetPreviewSize(const Nz::Vector2i& size);
|
||||||
|
|
||||||
|
QWidget* embeddedWidget() final;
|
||||||
|
|
||||||
void setInData(std::shared_ptr<QtNodes::NodeData>, int) override;
|
void setInData(std::shared_ptr<QtNodes::NodeData>, int) override;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void UpdatePreview();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
virtual bool ComputePreview(QPixmap& pixmap);
|
||||||
|
|
||||||
|
Nz::Vector2i m_previewSize;
|
||||||
|
QLabel* m_pixmapLabel;
|
||||||
|
std::optional<QPixmap> m_pixmap;
|
||||||
ShaderGraph& m_graph;
|
ShaderGraph& m_graph;
|
||||||
|
bool m_isPreviewEnabled;
|
||||||
};
|
};
|
||||||
|
|
||||||
#include <ShaderNode/DataModels/ShaderNode.inl>
|
#include <ShaderNode/DataModels/ShaderNode.inl>
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,5 @@
|
||||||
#include <ShaderNode/DataModels/ShaderNode.hpp>
|
#include <ShaderNode/DataModels/ShaderNode.hpp>
|
||||||
|
|
||||||
inline ShaderNode::ShaderNode(ShaderGraph& graph) :
|
|
||||||
m_graph(graph)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
inline ShaderGraph& ShaderNode::GetGraph()
|
inline ShaderGraph& ShaderNode::GetGraph()
|
||||||
{
|
{
|
||||||
|
|
@ -14,3 +10,10 @@ inline const ShaderGraph& ShaderNode::GetGraph() const
|
||||||
{
|
{
|
||||||
return m_graph;
|
return m_graph;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline void ShaderNode::SetPreviewSize(const Nz::Vector2i& size)
|
||||||
|
{
|
||||||
|
m_previewSize = size;
|
||||||
|
if (m_isPreviewEnabled)
|
||||||
|
UpdatePreview();
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,6 @@ class VecBinOp : public ShaderNode
|
||||||
|
|
||||||
Nz::ShaderAst::ExpressionPtr GetExpression(Nz::ShaderAst::ExpressionPtr* expressions, std::size_t count) const override;
|
Nz::ShaderAst::ExpressionPtr GetExpression(Nz::ShaderAst::ExpressionPtr* expressions, std::size_t count) const override;
|
||||||
|
|
||||||
QWidget* embeddedWidget() override;
|
|
||||||
unsigned int nPorts(QtNodes::PortType portType) const override;
|
unsigned int nPorts(QtNodes::PortType portType) const override;
|
||||||
|
|
||||||
QtNodes::NodeDataType dataType(QtNodes::PortType portType, QtNodes::PortIndex portIndex) const override;
|
QtNodes::NodeDataType dataType(QtNodes::PortType portType, QtNodes::PortIndex portIndex) const override;
|
||||||
|
|
@ -26,10 +25,10 @@ class VecBinOp : public ShaderNode
|
||||||
|
|
||||||
private:
|
private:
|
||||||
virtual void ApplyOp(const std::uint8_t* left, const std::uint8_t* right, std::uint8_t* output, std::size_t pixelCount) = 0;
|
virtual void ApplyOp(const std::uint8_t* left, const std::uint8_t* right, std::uint8_t* output, std::size_t pixelCount) = 0;
|
||||||
void UpdatePreview();
|
|
||||||
|
|
||||||
QLabel* m_pixmapLabel;
|
bool ComputePreview(QPixmap& pixmap) override;
|
||||||
QPixmap m_preview;
|
void UpdateOutput();
|
||||||
|
|
||||||
std::shared_ptr<Data> m_lhs;
|
std::shared_ptr<Data> m_lhs;
|
||||||
std::shared_ptr<Data> m_rhs;
|
std::shared_ptr<Data> m_rhs;
|
||||||
std::shared_ptr<Data> m_output;
|
std::shared_ptr<Data> m_output;
|
||||||
|
|
|
||||||
|
|
@ -7,9 +7,7 @@ ShaderNode(graph)
|
||||||
{
|
{
|
||||||
m_output = std::make_shared<Data>();
|
m_output = std::make_shared<Data>();
|
||||||
|
|
||||||
m_pixmapLabel = new QLabel;
|
UpdateOutput();
|
||||||
m_pixmapLabel->setStyleSheet("background-color: rgba(0,0,0,0)");
|
|
||||||
UpdatePreview();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Data, Nz::ShaderAst::BinaryType BinOp>
|
template<typename Data, Nz::ShaderAst::BinaryType BinOp>
|
||||||
|
|
@ -21,12 +19,6 @@ Nz::ShaderAst::ExpressionPtr VecBinOp<Data, BinOp>::GetExpression(Nz::ShaderAst:
|
||||||
return builder(expressions[0], expressions[1]);
|
return builder(expressions[0], expressions[1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Data, Nz::ShaderAst::BinaryType BinOp>
|
|
||||||
QWidget* VecBinOp<Data, BinOp>::embeddedWidget()
|
|
||||||
{
|
|
||||||
return m_pixmapLabel;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename Data, Nz::ShaderAst::BinaryType BinOp>
|
template<typename Data, Nz::ShaderAst::BinaryType BinOp>
|
||||||
QtNodes::NodeDataType VecBinOp<Data, BinOp>::dataType(QtNodes::PortType /*portType*/, QtNodes::PortIndex portIndex) const
|
QtNodes::NodeDataType VecBinOp<Data, BinOp>::dataType(QtNodes::PortType /*portType*/, QtNodes::PortIndex portIndex) const
|
||||||
{
|
{
|
||||||
|
|
@ -72,42 +64,49 @@ void VecBinOp<Data, BinOp>::setInData(std::shared_ptr<QtNodes::NodeData> value,
|
||||||
else
|
else
|
||||||
m_rhs = std::move(castedValue);
|
m_rhs = std::move(castedValue);
|
||||||
|
|
||||||
UpdatePreview();
|
UpdateOutput();
|
||||||
|
|
||||||
Q_EMIT dataUpdated(0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Data, Nz::ShaderAst::BinaryType BinOp>
|
template<typename Data, Nz::ShaderAst::BinaryType BinOp>
|
||||||
void VecBinOp<Data, BinOp>::UpdatePreview()
|
bool VecBinOp<Data, BinOp>::ComputePreview(QPixmap& pixmap)
|
||||||
{
|
{
|
||||||
if (m_lhs && m_rhs)
|
if (!m_lhs || !m_rhs)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
pixmap = QPixmap::fromImage(m_output->preview);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Data, Nz::ShaderAst::BinaryType BinOp>
|
||||||
|
void VecBinOp<Data, BinOp>::UpdateOutput()
|
||||||
|
{
|
||||||
|
if (!m_lhs || !m_rhs)
|
||||||
{
|
{
|
||||||
const QImage& leftPreview = m_lhs->preview;
|
m_output->preview = QImage(1, 1, QImage::Format_RGBA8888);
|
||||||
const QImage& rightPreview = m_rhs->preview;
|
m_output->preview.fill(QColor::fromRgb(0, 0, 0, 0));
|
||||||
int maxWidth = std::max(leftPreview.width(), rightPreview.width());
|
return;
|
||||||
int maxHeight = std::max(leftPreview.height(), rightPreview.height());
|
|
||||||
|
|
||||||
// Exploit COW
|
|
||||||
QImage leftResized = leftPreview;
|
|
||||||
if (leftResized.width() != maxWidth || leftResized.height() != maxHeight)
|
|
||||||
leftResized = leftResized.scaled(maxWidth, maxHeight);
|
|
||||||
|
|
||||||
QImage rightResized = rightPreview;
|
|
||||||
if (rightResized.width() != maxWidth || rightResized.height() != maxHeight)
|
|
||||||
rightResized = rightResized.scaled(maxWidth, maxHeight);
|
|
||||||
|
|
||||||
m_output->preview = QImage(maxWidth, maxHeight, QImage::Format_RGBA8888);
|
|
||||||
ApplyOp(leftResized.constBits(), rightResized.constBits(), m_output->preview.bits(), maxWidth * maxHeight * 4);
|
|
||||||
|
|
||||||
m_preview = QPixmap::fromImage(m_output->preview).scaled(64, 64);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
m_preview = QPixmap(64, 64);
|
|
||||||
m_preview.fill(QColor::fromRgb(255, 255, 0, 0));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
m_pixmapLabel->setPixmap(m_preview);
|
const QImage& leftPreview = m_lhs->preview;
|
||||||
|
const QImage& rightPreview = m_rhs->preview;
|
||||||
|
int maxWidth = std::max(leftPreview.width(), rightPreview.width());
|
||||||
|
int maxHeight = std::max(leftPreview.height(), rightPreview.height());
|
||||||
|
|
||||||
|
// Exploit COW
|
||||||
|
QImage leftResized = leftPreview;
|
||||||
|
if (leftResized.width() != maxWidth || leftResized.height() != maxHeight)
|
||||||
|
leftResized = leftResized.scaled(maxWidth, maxHeight);
|
||||||
|
|
||||||
|
QImage rightResized = rightPreview;
|
||||||
|
if (rightResized.width() != maxWidth || rightResized.height() != maxHeight)
|
||||||
|
rightResized = rightResized.scaled(maxWidth, maxHeight);
|
||||||
|
|
||||||
|
m_output->preview = QImage(maxWidth, maxHeight, QImage::Format_RGBA8888);
|
||||||
|
ApplyOp(leftResized.constBits(), rightResized.constBits(), m_output->preview.bits(), maxWidth * maxHeight * 4);
|
||||||
|
|
||||||
|
Q_EMIT dataUpdated(0);
|
||||||
|
|
||||||
|
UpdatePreview();
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Data>
|
template<typename Data>
|
||||||
|
|
|
||||||
|
|
@ -62,6 +62,45 @@ struct Vec4Data : public VecData
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct VecTypeDummy {};
|
||||||
|
|
||||||
|
template<std::size_t N>
|
||||||
|
struct VecTypeHelper;
|
||||||
|
|
||||||
|
template<>
|
||||||
|
struct VecTypeHelper<0>
|
||||||
|
{
|
||||||
|
using Type = VecTypeDummy;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<>
|
||||||
|
struct VecTypeHelper<1>
|
||||||
|
{
|
||||||
|
using Type = std::array<float, 1>;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<>
|
||||||
|
struct VecTypeHelper<2>
|
||||||
|
{
|
||||||
|
using Type = Nz::Vector2f;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<>
|
||||||
|
struct VecTypeHelper<3>
|
||||||
|
{
|
||||||
|
using Type = Nz::Vector3f;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<>
|
||||||
|
struct VecTypeHelper<4>
|
||||||
|
{
|
||||||
|
using Type = Nz::Vector4f;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<std::size_t N> using VecType = typename VecTypeHelper<N>::template Type;
|
||||||
|
|
||||||
|
constexpr std::array<char, 4> s_vectorComponents = { 'X', 'Y', 'Z', 'W' };
|
||||||
|
|
||||||
#include <ShaderNode/DataModels/VecData.inl>
|
#include <ShaderNode/DataModels/VecData.inl>
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -11,29 +11,6 @@
|
||||||
#include <ShaderNode/DataModels/VecData.hpp>
|
#include <ShaderNode/DataModels/VecData.hpp>
|
||||||
#include <array>
|
#include <array>
|
||||||
|
|
||||||
template<std::size_t N>
|
|
||||||
struct VecTypeHelper;
|
|
||||||
|
|
||||||
template<>
|
|
||||||
struct VecTypeHelper<2>
|
|
||||||
{
|
|
||||||
using Type = Nz::Vector2f;
|
|
||||||
};
|
|
||||||
|
|
||||||
template<>
|
|
||||||
struct VecTypeHelper<3>
|
|
||||||
{
|
|
||||||
using Type = Nz::Vector3f;
|
|
||||||
};
|
|
||||||
|
|
||||||
template<>
|
|
||||||
struct VecTypeHelper<4>
|
|
||||||
{
|
|
||||||
using Type = Nz::Vector4f;
|
|
||||||
};
|
|
||||||
|
|
||||||
template<std::size_t N> using VecType = typename VecTypeHelper<N>::template Type;
|
|
||||||
|
|
||||||
template<typename Data>
|
template<typename Data>
|
||||||
class VecValue : public ShaderNode
|
class VecValue : public ShaderNode
|
||||||
{
|
{
|
||||||
|
|
@ -46,25 +23,22 @@ class VecValue : public ShaderNode
|
||||||
|
|
||||||
QtNodes::NodeDataType dataType(QtNodes::PortType portType, QtNodes::PortIndex portIndex) const override;
|
QtNodes::NodeDataType dataType(QtNodes::PortType portType, QtNodes::PortIndex portIndex) const override;
|
||||||
|
|
||||||
QWidget* embeddedWidget() override;
|
|
||||||
unsigned int nPorts(QtNodes::PortType portType) const override;
|
unsigned int nPorts(QtNodes::PortType portType) const override;
|
||||||
|
|
||||||
std::shared_ptr<QtNodes::NodeData> outData(QtNodes::PortIndex port) override;
|
std::shared_ptr<QtNodes::NodeData> outData(QtNodes::PortIndex port) override;
|
||||||
|
|
||||||
|
void BuildNodeEdition(QVBoxLayout* layout) override;
|
||||||
|
|
||||||
Nz::ShaderAst::ExpressionPtr GetExpression(Nz::ShaderAst::ExpressionPtr* expressions, std::size_t count) const override;
|
Nz::ShaderAst::ExpressionPtr GetExpression(Nz::ShaderAst::ExpressionPtr* expressions, std::size_t count) const override;
|
||||||
|
|
||||||
protected:
|
private:
|
||||||
|
bool ComputePreview(QPixmap& pixmap) override;
|
||||||
|
|
||||||
static constexpr std::size_t ComponentCount = Data::ComponentCount;
|
static constexpr std::size_t ComponentCount = Data::ComponentCount;
|
||||||
|
|
||||||
QColor ToColor() const;
|
QColor ToColor() const;
|
||||||
VecType<ComponentCount> ToVector() const;
|
|
||||||
void UpdatePreview();
|
|
||||||
|
|
||||||
QLabel* m_pixmapLabel;
|
VecType<ComponentCount> m_value;
|
||||||
QPixmap m_pixmap;
|
|
||||||
QWidget* m_widget;
|
|
||||||
QFormLayout* m_layout;
|
|
||||||
std::array<QDoubleSpinBox*, ComponentCount> m_spinboxes;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
using Vec2Value = VecValue<Vec2Data>;
|
using Vec2Value = VecValue<Vec2Data>;
|
||||||
|
|
|
||||||
|
|
@ -8,37 +8,14 @@ template<typename Data>
|
||||||
VecValue<Data>::VecValue(ShaderGraph& graph) :
|
VecValue<Data>::VecValue(ShaderGraph& graph) :
|
||||||
ShaderNode(graph)
|
ShaderNode(graph)
|
||||||
{
|
{
|
||||||
constexpr std::array<char, 4> componentName = { 'X', 'Y', 'Z', 'W' };
|
static_assert(ComponentCount <= s_vectorComponents.size());
|
||||||
static_assert(ComponentCount <= componentName.size());
|
|
||||||
|
std::array<float, ComponentCount> defaultValues;
|
||||||
|
|
||||||
m_layout = new QFormLayout;
|
|
||||||
for (std::size_t i = 0; i < ComponentCount; ++i)
|
for (std::size_t i = 0; i < ComponentCount; ++i)
|
||||||
{
|
defaultValues[i] = (i == 3) ? 1.f : 0.f;
|
||||||
m_spinboxes[i] = new QDoubleSpinBox;
|
|
||||||
m_spinboxes[i]->setDecimals(6);
|
|
||||||
m_spinboxes[i]->setValue(1.0);
|
|
||||||
m_spinboxes[i]->setStyleSheet("background-color: rgba(255,255,255,255)");
|
|
||||||
connect(m_spinboxes[i], qOverload<double>(&QDoubleSpinBox::valueChanged), [this](double)
|
|
||||||
{
|
|
||||||
UpdatePreview();
|
|
||||||
|
|
||||||
Q_EMIT dataUpdated(0);
|
m_value.Set(defaultValues.data());
|
||||||
});
|
|
||||||
|
|
||||||
m_layout->addRow(QString::fromUtf8(&componentName[i], 1), m_spinboxes[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
m_pixmap = QPixmap(32, 32);
|
|
||||||
m_pixmap.fill();
|
|
||||||
|
|
||||||
m_pixmapLabel = new QLabel;
|
|
||||||
m_pixmapLabel->setPixmap(m_pixmap);
|
|
||||||
|
|
||||||
m_layout->addWidget(m_pixmapLabel);
|
|
||||||
|
|
||||||
m_widget = new QWidget;
|
|
||||||
m_widget->setStyleSheet("background-color: rgba(0,0,0,0)");
|
|
||||||
m_widget->setLayout(m_layout);
|
|
||||||
|
|
||||||
UpdatePreview();
|
UpdatePreview();
|
||||||
}
|
}
|
||||||
|
|
@ -66,12 +43,6 @@ QtNodes::NodeDataType VecValue<Data>::dataType(QtNodes::PortType portType, QtNod
|
||||||
return Data::Type();
|
return Data::Type();
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Data>
|
|
||||||
QWidget* VecValue<Data>::embeddedWidget()
|
|
||||||
{
|
|
||||||
return m_widget;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename Data>
|
template<typename Data>
|
||||||
unsigned int VecValue<Data>::nPorts(QtNodes::PortType portType) const
|
unsigned int VecValue<Data>::nPorts(QtNodes::PortType portType) const
|
||||||
{
|
{
|
||||||
|
|
@ -96,12 +67,45 @@ std::shared_ptr<QtNodes::NodeData> VecValue<Data>::outData(QtNodes::PortIndex po
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename Data>
|
||||||
|
void VecValue<Data>::BuildNodeEdition(QVBoxLayout* layout)
|
||||||
|
{
|
||||||
|
ShaderNode::BuildNodeEdition(layout);
|
||||||
|
|
||||||
|
QFormLayout* formLayout = new QFormLayout;
|
||||||
|
for (std::size_t i = 0; i < ComponentCount; ++i)
|
||||||
|
{
|
||||||
|
QDoubleSpinBox* spinbox = new QDoubleSpinBox;
|
||||||
|
spinbox->setDecimals(6);
|
||||||
|
spinbox->setValue(m_value[i]);
|
||||||
|
|
||||||
|
connect(spinbox, qOverload<double>(&QDoubleSpinBox::valueChanged), [=](double)
|
||||||
|
{
|
||||||
|
m_value[i] = spinbox->value();
|
||||||
|
Q_EMIT dataUpdated(0);
|
||||||
|
|
||||||
|
UpdatePreview();
|
||||||
|
});
|
||||||
|
|
||||||
|
formLayout->addRow(QString::fromUtf8(&s_vectorComponents[i], 1), spinbox);
|
||||||
|
}
|
||||||
|
|
||||||
|
layout->addLayout(formLayout);
|
||||||
|
}
|
||||||
|
|
||||||
template<typename Data>
|
template<typename Data>
|
||||||
Nz::ShaderAst::ExpressionPtr VecValue<Data>::GetExpression(Nz::ShaderAst::ExpressionPtr* /*expressions*/, std::size_t count) const
|
Nz::ShaderAst::ExpressionPtr VecValue<Data>::GetExpression(Nz::ShaderAst::ExpressionPtr* /*expressions*/, std::size_t count) const
|
||||||
{
|
{
|
||||||
assert(count == 0);
|
assert(count == 0);
|
||||||
|
|
||||||
return Nz::ShaderBuilder::Constant(ToVector());
|
return Nz::ShaderBuilder::Constant(m_value);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Data>
|
||||||
|
bool VecValue<Data>::ComputePreview(QPixmap& pixmap)
|
||||||
|
{
|
||||||
|
pixmap.fill(ToColor());
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Data>
|
template<typename Data>
|
||||||
|
|
@ -110,28 +114,7 @@ QColor VecValue<Data>::ToColor() const
|
||||||
std::array<float, 4> values = { 0.f, 0.f, 0.f, 1.f };
|
std::array<float, 4> values = { 0.f, 0.f, 0.f, 1.f };
|
||||||
|
|
||||||
for (std::size_t i = 0; i < ComponentCount; ++i)
|
for (std::size_t i = 0; i < ComponentCount; ++i)
|
||||||
values[i] = std::clamp(float(m_spinboxes[i]->value()), 0.f, 1.f);
|
values[i] = std::clamp(m_value[i], 0.f, 1.f);
|
||||||
|
|
||||||
return QColor::fromRgbF(values[0], values[1], values[2], values[3]);
|
return QColor::fromRgbF(values[0], values[1], values[2], values[3]);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Data>
|
|
||||||
auto VecValue<Data>::ToVector() const -> VecType<ComponentCount>
|
|
||||||
{
|
|
||||||
std::array<float, ComponentCount> values;
|
|
||||||
|
|
||||||
for (std::size_t i = 0; i < ComponentCount; ++i)
|
|
||||||
values[i] = std::clamp(float(m_spinboxes[i]->value()), 0.f, 1.f);
|
|
||||||
|
|
||||||
return std::apply([](auto... values)
|
|
||||||
{
|
|
||||||
return VecType<ComponentCount>(values...);
|
|
||||||
}, values);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename Data>
|
|
||||||
void VecValue<Data>::UpdatePreview()
|
|
||||||
{
|
|
||||||
m_pixmap.fill(ToColor());
|
|
||||||
m_pixmapLabel->setPixmap(m_pixmap);
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -29,6 +29,17 @@ namespace
|
||||||
ShaderGraph::ShaderGraph() :
|
ShaderGraph::ShaderGraph() :
|
||||||
m_flowScene(BuildRegistry())
|
m_flowScene(BuildRegistry())
|
||||||
{
|
{
|
||||||
|
m_previewModel = std::make_unique<QuadPreview>();
|
||||||
|
|
||||||
|
QObject::connect(&m_flowScene, &QGraphicsScene::selectionChanged, [&]
|
||||||
|
{
|
||||||
|
auto selectedNodes = m_flowScene.selectedNodes();
|
||||||
|
if (selectedNodes.size() == 1)
|
||||||
|
OnSelectedNodeUpdate(this, static_cast<ShaderNode*>(selectedNodes.front()->nodeDataModel()));
|
||||||
|
else
|
||||||
|
OnSelectedNodeUpdate(this, nullptr);
|
||||||
|
});
|
||||||
|
|
||||||
auto& node1 = m_flowScene.createNode(std::make_unique<Vec4Value>(*this));
|
auto& node1 = m_flowScene.createNode(std::make_unique<Vec4Value>(*this));
|
||||||
node1.nodeGraphicsObject().setPos(200, 200);
|
node1.nodeGraphicsObject().setPos(200, 200);
|
||||||
|
|
||||||
|
|
@ -36,8 +47,6 @@ m_flowScene(BuildRegistry())
|
||||||
node2.nodeGraphicsObject().setPos(500, 300);
|
node2.nodeGraphicsObject().setPos(500, 300);
|
||||||
|
|
||||||
m_flowScene.createConnection(node2, 0, node1, 0);
|
m_flowScene.createConnection(node2, 0, node1, 0);
|
||||||
|
|
||||||
m_previewModel = std::make_unique<QuadPreview>();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ShaderGraph::~ShaderGraph()
|
ShaderGraph::~ShaderGraph()
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,8 @@
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
class ShaderNode;
|
||||||
|
|
||||||
class ShaderGraph
|
class ShaderGraph
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
@ -52,6 +54,7 @@ class ShaderGraph
|
||||||
|
|
||||||
NazaraSignal(OnInputListUpdate, ShaderGraph*);
|
NazaraSignal(OnInputListUpdate, ShaderGraph*);
|
||||||
NazaraSignal(OnInputUpdate, ShaderGraph*, std::size_t /*inputIndex*/);
|
NazaraSignal(OnInputUpdate, ShaderGraph*, std::size_t /*inputIndex*/);
|
||||||
|
NazaraSignal(OnSelectedNodeUpdate, ShaderGraph*, ShaderNode* /*node*/);
|
||||||
NazaraSignal(OnTextureListUpdate, ShaderGraph*);
|
NazaraSignal(OnTextureListUpdate, ShaderGraph*);
|
||||||
NazaraSignal(OnTexturePreviewUpdate, ShaderGraph*, std::size_t /*textureIndex*/);
|
NazaraSignal(OnTexturePreviewUpdate, ShaderGraph*, std::size_t /*textureIndex*/);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@
|
||||||
#include <Nazara/Renderer/GlslWriter.hpp>
|
#include <Nazara/Renderer/GlslWriter.hpp>
|
||||||
#include <ShaderNode/ShaderGraph.hpp>
|
#include <ShaderNode/ShaderGraph.hpp>
|
||||||
#include <ShaderNode/Widgets/InputEditor.hpp>
|
#include <ShaderNode/Widgets/InputEditor.hpp>
|
||||||
|
#include <ShaderNode/Widgets/NodeEditor.hpp>
|
||||||
#include <ShaderNode/Widgets/TextureEditor.hpp>
|
#include <ShaderNode/Widgets/TextureEditor.hpp>
|
||||||
#include <nodes/FlowView>
|
#include <nodes/FlowView>
|
||||||
#include <QtWidgets/QDockWidget>
|
#include <QtWidgets/QDockWidget>
|
||||||
|
|
@ -19,20 +20,44 @@ 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);
|
InputEditor* inputEditor = new InputEditor(m_shaderGraph);
|
||||||
|
|
||||||
|
QDockWidget* inputDock = new QDockWidget(tr("Inputs"));
|
||||||
|
inputDock->setFeatures(QDockWidget::DockWidgetFloatable | QDockWidget::DockWidgetMovable);
|
||||||
inputDock->setWidget(inputEditor);
|
inputDock->setWidget(inputEditor);
|
||||||
|
|
||||||
addDockWidget(Qt::LeftDockWidgetArea, inputDock);
|
addDockWidget(Qt::LeftDockWidgetArea, inputDock);
|
||||||
|
|
||||||
QDockWidget* textureDock = new QDockWidget(tr("&Textures"));
|
|
||||||
|
|
||||||
TextureEditor* textureEditor = new TextureEditor(m_shaderGraph);
|
TextureEditor* textureEditor = new TextureEditor(m_shaderGraph);
|
||||||
|
|
||||||
|
QDockWidget* textureDock = new QDockWidget(tr("Textures"));
|
||||||
|
textureDock->setFeatures(QDockWidget::DockWidgetFloatable | QDockWidget::DockWidgetMovable);
|
||||||
textureDock->setWidget(textureEditor);
|
textureDock->setWidget(textureEditor);
|
||||||
|
|
||||||
addDockWidget(Qt::LeftDockWidgetArea, textureDock);
|
addDockWidget(Qt::LeftDockWidgetArea, textureDock);
|
||||||
|
|
||||||
|
m_nodeEditor = new NodeEditor;
|
||||||
|
|
||||||
|
QDockWidget* nodeEditorDock = new QDockWidget(tr("Node editor"));
|
||||||
|
nodeEditorDock->setFeatures(QDockWidget::DockWidgetFloatable | QDockWidget::DockWidgetMovable);
|
||||||
|
nodeEditorDock->setWidget(m_nodeEditor);
|
||||||
|
|
||||||
|
addDockWidget(Qt::RightDockWidgetArea, nodeEditorDock);
|
||||||
|
|
||||||
|
m_onSelectedNodeUpdate.Connect(m_shaderGraph.OnSelectedNodeUpdate, [&](ShaderGraph*, ShaderNode* node)
|
||||||
|
{
|
||||||
|
if (node)
|
||||||
|
{
|
||||||
|
m_nodeEditor->UpdateContent(node->caption(), [node](QVBoxLayout* layout)
|
||||||
|
{
|
||||||
|
node->BuildNodeEdition(layout);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else
|
||||||
|
m_nodeEditor->Clear();
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
BuildMenu();
|
BuildMenu();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,9 +4,10 @@
|
||||||
#define NAZARA_SHADERNODES_MAINWINDOW_HPP
|
#define NAZARA_SHADERNODES_MAINWINDOW_HPP
|
||||||
|
|
||||||
#include <QtWidgets/QMainWindow>
|
#include <QtWidgets/QMainWindow>
|
||||||
|
#include <ShaderNode/ShaderGraph.hpp>
|
||||||
#include <ShaderNode/DataModels/ShaderNode.hpp>
|
#include <ShaderNode/DataModels/ShaderNode.hpp>
|
||||||
|
|
||||||
class ShaderGraph;
|
class NodeEditor;
|
||||||
|
|
||||||
class MainWindow : public QMainWindow
|
class MainWindow : public QMainWindow
|
||||||
{
|
{
|
||||||
|
|
@ -18,6 +19,9 @@ class MainWindow : public QMainWindow
|
||||||
void BuildMenu();
|
void BuildMenu();
|
||||||
void OnCompileToGLSL();
|
void OnCompileToGLSL();
|
||||||
|
|
||||||
|
NazaraSlot(ShaderGraph, OnSelectedNodeUpdate, m_onSelectedNodeUpdate);
|
||||||
|
|
||||||
|
NodeEditor* m_nodeEditor;
|
||||||
ShaderGraph& m_shaderGraph;
|
ShaderGraph& m_shaderGraph;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,20 @@
|
||||||
|
#include <ShaderNode/Widgets/NodeEditor.hpp>
|
||||||
|
#include <QtWidgets/QLabel>
|
||||||
|
#include <QtWidgets/QVBoxLayout>
|
||||||
|
|
||||||
|
NodeEditor::NodeEditor() :
|
||||||
|
m_layout(nullptr)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void NodeEditor::Clear()
|
||||||
|
{
|
||||||
|
if (m_layout)
|
||||||
|
{
|
||||||
|
while (QWidget* w = findChild<QWidget*>())
|
||||||
|
delete w;
|
||||||
|
|
||||||
|
delete m_layout;
|
||||||
|
m_layout = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,27 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#ifndef NAZARA_SHADERNODES_NODEEDITOR_HPP
|
||||||
|
#define NAZARA_SHADERNODES_NODEEDITOR_HPP
|
||||||
|
|
||||||
|
#include <ShaderNode/ShaderGraph.hpp>
|
||||||
|
#include <QtWidgets/QVBoxLayout>
|
||||||
|
#include <QtWidgets/QWidget>
|
||||||
|
#include <optional>
|
||||||
|
|
||||||
|
class NodeEditor : public QWidget
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
NodeEditor();
|
||||||
|
~NodeEditor() = default;
|
||||||
|
|
||||||
|
void Clear();
|
||||||
|
|
||||||
|
template<typename F> void UpdateContent(QString nodeName, F&& callback);
|
||||||
|
|
||||||
|
private:
|
||||||
|
QVBoxLayout* m_layout;
|
||||||
|
};
|
||||||
|
|
||||||
|
#include <ShaderNode/Widgets/NodeEditor.inl>
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
@ -0,0 +1,16 @@
|
||||||
|
#include <ShaderNode/Widgets/NodeEditor.hpp>
|
||||||
|
#include <QtWidgets/QLabel>
|
||||||
|
|
||||||
|
template<typename F>
|
||||||
|
void NodeEditor::UpdateContent(QString nodeName, F&& callback)
|
||||||
|
{
|
||||||
|
Clear();
|
||||||
|
|
||||||
|
m_layout = new QVBoxLayout;
|
||||||
|
setLayout(m_layout);
|
||||||
|
|
||||||
|
QLabel* label = new QLabel(nodeName);
|
||||||
|
m_layout->addWidget(label);
|
||||||
|
|
||||||
|
callback(m_layout);
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue