220 lines
5.5 KiB
C++
220 lines
5.5 KiB
C++
#include <ShaderNode/DataModels/OutputValue.hpp>
|
|
#include <Nazara/Renderer/ShaderBuilder.hpp>
|
|
#include <ShaderNode/ShaderGraph.hpp>
|
|
#include <ShaderNode/DataTypes/VecData.hpp>
|
|
#include <QtWidgets/QComboBox>
|
|
#include <QtWidgets/QFormLayout>
|
|
|
|
OutputValue::OutputValue(ShaderGraph& graph) :
|
|
ShaderNode(graph)
|
|
{
|
|
m_onOutputListUpdateSlot.Connect(GetGraph().OnOutputListUpdate, [&](ShaderGraph*) { OnOutputListUpdate(); });
|
|
m_onOutputUpdateSlot.Connect(GetGraph().OnOutputUpdate, [&](ShaderGraph*, std::size_t inputIndex)
|
|
{
|
|
if (m_currentOutputIndex == inputIndex)
|
|
UpdatePreview();
|
|
});
|
|
|
|
if (graph.GetOutputCount() > 0)
|
|
{
|
|
m_currentOutputIndex = 0;
|
|
UpdateOutputText();
|
|
}
|
|
|
|
EnablePreview();
|
|
SetPreviewSize({ 128, 128 });
|
|
DisableCustomVariableName();
|
|
}
|
|
|
|
void OutputValue::BuildNodeEdition(QFormLayout* layout)
|
|
{
|
|
ShaderNode::BuildNodeEdition(layout);
|
|
|
|
QComboBox* outputSelection = new QComboBox;
|
|
for (const auto& outputEntry : GetGraph().GetOutputs())
|
|
outputSelection->addItem(QString::fromStdString(outputEntry.name));
|
|
|
|
if (m_currentOutputIndex)
|
|
outputSelection->setCurrentIndex(int(*m_currentOutputIndex));
|
|
|
|
connect(outputSelection, qOverload<int>(&QComboBox::currentIndexChanged), [&](int index)
|
|
{
|
|
if (index >= 0)
|
|
m_currentOutputIndex = static_cast<std::size_t>(index);
|
|
else
|
|
m_currentOutputIndex.reset();
|
|
|
|
UpdateOutputText();
|
|
UpdatePreview();
|
|
});
|
|
|
|
layout->addRow(tr("Output"), outputSelection);
|
|
}
|
|
|
|
Nz::ShaderNodes::ExpressionPtr OutputValue::GetExpression(Nz::ShaderNodes::ExpressionPtr* expressions, std::size_t count) const
|
|
{
|
|
using namespace Nz::ShaderBuilder;
|
|
using namespace Nz::ShaderNodes;
|
|
|
|
assert(count == 1);
|
|
|
|
if (!m_currentOutputIndex)
|
|
throw std::runtime_error("no output");
|
|
|
|
const auto& outputEntry = GetGraph().GetOutput(*m_currentOutputIndex);
|
|
|
|
Nz::ShaderNodes::ExpressionType expression = [&]
|
|
{
|
|
switch (outputEntry.type)
|
|
{
|
|
case InOutType::Bool: return Nz::ShaderNodes::ExpressionType::Boolean;
|
|
case InOutType::Float1: return Nz::ShaderNodes::ExpressionType::Float1;
|
|
case InOutType::Float2: return Nz::ShaderNodes::ExpressionType::Float2;
|
|
case InOutType::Float3: return Nz::ShaderNodes::ExpressionType::Float3;
|
|
case InOutType::Float4: return Nz::ShaderNodes::ExpressionType::Float4;
|
|
}
|
|
|
|
assert(false);
|
|
throw std::runtime_error("Unhandled output type");
|
|
}();
|
|
|
|
auto output = Nz::ShaderBuilder::Identifier(Nz::ShaderBuilder::Output(outputEntry.name, expression));
|
|
|
|
return Nz::ShaderBuilder::Assign(std::move(output), *expressions);
|
|
}
|
|
|
|
QtNodes::NodeDataType OutputValue::dataType(QtNodes::PortType portType, QtNodes::PortIndex portIndex) const
|
|
{
|
|
assert(portType == QtNodes::PortType::In);
|
|
assert(portIndex == 0);
|
|
|
|
if (!m_currentOutputIndex)
|
|
return VecData::Type();
|
|
|
|
const auto& outputEntry = GetGraph().GetOutput(*m_currentOutputIndex);
|
|
switch (outputEntry.type)
|
|
{
|
|
//case InOutType::Bool: return Nz::ShaderNodes::ExpressionType::Boolean;
|
|
//case InOutType::Float1: return Nz::ShaderNodes::ExpressionType::Float1;
|
|
case InOutType::Float2:
|
|
case InOutType::Float3:
|
|
case InOutType::Float4:
|
|
return VecData::Type();
|
|
}
|
|
|
|
assert(false);
|
|
throw std::runtime_error("Unhandled output type");
|
|
}
|
|
|
|
unsigned int OutputValue::nPorts(QtNodes::PortType portType) const
|
|
{
|
|
switch (portType)
|
|
{
|
|
case QtNodes::PortType::In: return 1;
|
|
case QtNodes::PortType::Out: return 0;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
std::shared_ptr<QtNodes::NodeData> OutputValue::outData(QtNodes::PortIndex /*port*/)
|
|
{
|
|
return {};
|
|
}
|
|
|
|
void OutputValue::setInData(std::shared_ptr<QtNodes::NodeData> value, int index)
|
|
{
|
|
assert(index == 0);
|
|
if (value)
|
|
{
|
|
assert(dynamic_cast<VecData*>(value.get()) != nullptr);
|
|
m_input = std::static_pointer_cast<VecData>(value);
|
|
}
|
|
else
|
|
m_input.reset();
|
|
|
|
UpdatePreview();
|
|
}
|
|
|
|
QtNodes::NodeValidationState OutputValue::validationState() const
|
|
{
|
|
if (!m_currentOutputIndex || !m_input)
|
|
return QtNodes::NodeValidationState::Error;
|
|
|
|
const auto& outputEntry = GetGraph().GetOutput(*m_currentOutputIndex);
|
|
if (GetComponentCount(outputEntry.type) != m_input->componentCount)
|
|
return QtNodes::NodeValidationState::Error;
|
|
|
|
return QtNodes::NodeValidationState::Valid;
|
|
}
|
|
|
|
QString OutputValue::validationMessage() const
|
|
{
|
|
if (!m_currentOutputIndex)
|
|
return "No output selected";
|
|
|
|
if (!m_input)
|
|
return "Missing input";
|
|
|
|
const auto& outputEntry = GetGraph().GetOutput(*m_currentOutputIndex);
|
|
std::size_t outputComponentCount = GetComponentCount(outputEntry.type);
|
|
|
|
if (m_input->componentCount != outputComponentCount)
|
|
return "Incompatible component count (expected " + QString::number(outputComponentCount) + ", got " + QString::number(m_input->componentCount) + ")";
|
|
|
|
return QString();
|
|
}
|
|
|
|
bool OutputValue::ComputePreview(QPixmap& pixmap)
|
|
{
|
|
if (!m_input)
|
|
return false;
|
|
|
|
pixmap = QPixmap::fromImage(m_input->preview.GenerateImage());
|
|
return true;
|
|
}
|
|
|
|
void OutputValue::OnOutputListUpdate()
|
|
{
|
|
m_currentOutputIndex.reset();
|
|
|
|
std::size_t inputIndex = 0;
|
|
for (const auto& inputEntry : GetGraph().GetOutputs())
|
|
{
|
|
if (inputEntry.name == m_currentOutputText)
|
|
{
|
|
m_currentOutputIndex = inputIndex;
|
|
break;
|
|
}
|
|
|
|
inputIndex++;
|
|
}
|
|
}
|
|
|
|
void OutputValue::UpdateOutputText()
|
|
{
|
|
if (m_currentOutputIndex)
|
|
{
|
|
auto& output = GetGraph().GetOutput(*m_currentOutputIndex);
|
|
m_currentOutputText = output.name;
|
|
}
|
|
else
|
|
m_currentOutputText.clear();
|
|
}
|
|
|
|
void OutputValue::restore(const QJsonObject& data)
|
|
{
|
|
m_currentOutputText = data["output"].toString().toStdString();
|
|
OnOutputListUpdate();
|
|
|
|
ShaderNode::restore(data);
|
|
}
|
|
|
|
QJsonObject OutputValue::save() const
|
|
{
|
|
QJsonObject data = ShaderNode::save();
|
|
data["output"] = QString::fromStdString(m_currentOutputText);
|
|
|
|
return data;
|
|
}
|