NazaraEngine/src/ShaderNode/DataModels/VecDecomposition.cpp

174 lines
4.1 KiB
C++

#include <ShaderNode/DataModels/VecDecomposition.hpp>
#include <NZSL/ShaderBuilder.hpp>
#include <ShaderNode/ShaderGraph.hpp>
#include <ShaderNode/DataTypes/BoolData.hpp>
#include <ShaderNode/DataTypes/FloatData.hpp>
#include <ShaderNode/DataTypes/Matrix4Data.hpp>
#include <ShaderNode/DataTypes/VecData.hpp>
#include <QtWidgets/QComboBox>
#include <QtWidgets/QFormLayout>
#include <limits>
VecDecomposition::VecDecomposition(ShaderGraph& graph) :
ShaderNode(graph)
{
DisablePreview();
DisableCustomVariableName();
}
nzsl::Ast::NodePtr VecDecomposition::BuildNode(nzsl::Ast::ExpressionPtr* expressions, std::size_t count, std::size_t outputIndex) const
{
assert(count == 1);
assert(outputIndex < m_outputs.size());
return nzsl::ShaderBuilder::Swizzle(std::move(expressions[0]), { Nz::SafeCast<Nz::UInt32>(outputIndex) });
}
QString VecDecomposition::caption() const
{
return "Vector decomposition";
}
QString VecDecomposition::name() const
{
return "vec_decompose";
}
QtNodes::NodeDataType VecDecomposition::dataType(QtNodes::PortType portType, QtNodes::PortIndex portIndex) const
{
switch (portType)
{
case QtNodes::PortType::In:
{
assert(portIndex == 0);
return VecData::Type();
}
case QtNodes::PortType::Out:
{
assert(portIndex >= 0 && portIndex < m_outputs.size());
return FloatData::Type();
}
default:
break;
}
assert(false);
throw std::runtime_error("Invalid port type");
}
unsigned int VecDecomposition::nPorts(QtNodes::PortType portType) const
{
switch (portType)
{
case QtNodes::PortType::In: return 1;
case QtNodes::PortType::Out: return static_cast<unsigned int>(m_outputs.size());
default:
break;
}
assert(false);
throw std::runtime_error("Invalid port type");
}
QString VecDecomposition::portCaption(QtNodes::PortType portType, QtNodes::PortIndex portIndex) const
{
assert(portType == QtNodes::PortType::Out);
assert(portIndex >= 0 && portIndex < s_vectorComponents.size());
return QString(QChar(s_vectorComponents[portIndex]));
}
bool VecDecomposition::portCaptionVisible(QtNodes::PortType portType, QtNodes::PortIndex portIndex) const
{
switch (portType)
{
case QtNodes::PortType::In: return false;
case QtNodes::PortType::Out: return true;
default:
break;
}
assert(false);
throw std::runtime_error("Invalid port type");
}
std::shared_ptr<QtNodes::NodeData> VecDecomposition::outData(QtNodes::PortIndex port)
{
if (!m_input)
return {};
return m_outputs[port];
}
void VecDecomposition::setInData(std::shared_ptr<QtNodes::NodeData> value, int index)
{
assert(index == 0);
std::shared_ptr<VecData> castedValue;
if (value && value->type().id == VecData::Type().id)
castedValue = std::static_pointer_cast<VecData>(value);
m_input = std::move(castedValue);
UpdateOutputs();
}
QtNodes::NodeValidationState VecDecomposition::validationState() const
{
if (!m_input)
return QtNodes::NodeValidationState::Error;
return QtNodes::NodeValidationState::Valid;
}
QString VecDecomposition::validationMessage() const
{
if (!m_input)
return "Missing input";
return QString();
}
void VecDecomposition::UpdateOutputs()
{
if (validationState() != QtNodes::NodeValidationState::Valid)
{
auto dummy = std::make_shared<FloatData>();
dummy->preview = PreviewValues(1, 1);
dummy->preview.Fill(nzsl::Vector4f32(0.f, 0.f, 0.f, 0.f));
m_outputs.fill(dummy);
return;
}
std::size_t previewWidth = m_input->preview.GetWidth();
std::size_t previewHeight = m_input->preview.GetHeight();
std::size_t pixelCount = previewWidth * previewHeight;
for (std::size_t i = 0; i < m_input->componentCount; ++i)
{
m_outputs[i] = std::make_shared<FloatData>();
m_outputs[i]->preview = PreviewValues(previewWidth, previewHeight);
const nzsl::Vector4f32* inputData = m_input->preview.GetData();
nzsl::Vector4f32* outputData = m_outputs[i]->preview.GetData();
for (std::size_t j = 0; j < pixelCount; ++j)
{
const nzsl::Vector4f32& input = *inputData++;
*outputData++ = nzsl::Vector4f32(input[i], input[i], input[i], input[i]);
}
Q_EMIT dataUpdated(i);
}
for (std::size_t i = m_input->componentCount; i < m_outputs.size(); ++i)
m_outputs[i] = nullptr;
UpdatePreview();
}