NazaraEngine/src/ShaderNode/DataModels/VecValue.inl

147 lines
3.8 KiB
C++

#include <ShaderNode/DataModels/VecValue.hpp>
#include <Nazara/Core/Algorithm.hpp>
#include <Nazara/Renderer/ShaderBuilder.hpp>
#include <ShaderNode/DataTypes/VecData.hpp>
#include <QtCore/QJsonArray>
#include <array>
#include <tuple>
template<std::size_t ComponentCount>
VecValue<ComponentCount>::VecValue(ShaderGraph& graph) :
ShaderNode(graph)
{
static_assert(ComponentCount <= s_vectorComponents.size());
std::array<float, ComponentCount> defaultValues;
for (std::size_t i = 0; i < ComponentCount; ++i)
defaultValues[i] = (i == 3) ? 1.f : 0.f;
m_value.Set(defaultValues.data());
UpdatePreview();
}
template<std::size_t ComponentCount>
QString VecValue<ComponentCount>::caption() const
{
static QString caption = "Vector" + QString::number(ComponentCount) + " constant";
return caption;
}
template<std::size_t ComponentCount>
QString VecValue<ComponentCount>::name() const
{
static QString name = "vec" + QString::number(ComponentCount) + "_constant";
return name;
}
template<std::size_t ComponentCount>
QtNodes::NodeDataType VecValue<ComponentCount>::dataType(QtNodes::PortType portType, QtNodes::PortIndex portIndex) const
{
assert(portType == QtNodes::PortType::Out);
assert(portIndex == 0);
return VecData::Type();
}
template<std::size_t ComponentCount>
unsigned int VecValue<ComponentCount>::nPorts(QtNodes::PortType portType) const
{
switch (portType)
{
case QtNodes::PortType::In: return 0;
case QtNodes::PortType::Out: return 1;
}
return 0;
}
template<std::size_t ComponentCount>
std::shared_ptr<QtNodes::NodeData> VecValue<ComponentCount>::outData(QtNodes::PortIndex port)
{
assert(port == 0);
auto out = std::make_shared<VecData>(ComponentCount);
out->preview = QImage(1, 1, QImage::Format_RGBA8888);
out->preview.fill(ToColor());
return out;
}
template<std::size_t ComponentCount>
void VecValue<ComponentCount>::BuildNodeEdition(QFormLayout* layout)
{
ShaderNode::BuildNodeEdition(layout);
for (std::size_t i = 0; i < ComponentCount; ++i)
{
QDoubleSpinBox* spinbox = new QDoubleSpinBox;
spinbox->setDecimals(6);
spinbox->setRange(std::numeric_limits<float>::lowest(), std::numeric_limits<float>::max());
spinbox->setValue(m_value[i]);
connect(spinbox, qOverload<double>(&QDoubleSpinBox::valueChanged), [=](double)
{
m_value[i] = spinbox->value();
Q_EMIT dataUpdated(0);
UpdatePreview();
});
layout->addRow(QString::fromUtf8(&s_vectorComponents[i], 1), spinbox);
}
}
template<std::size_t ComponentCount>
Nz::ShaderNodes::ExpressionPtr VecValue<ComponentCount>::GetExpression(Nz::ShaderNodes::ExpressionPtr* /*expressions*/, std::size_t count) const
{
assert(count == 0);
return Nz::ShaderBuilder::Constant(m_value);
}
template<std::size_t ComponentCount>
bool VecValue<ComponentCount>::ComputePreview(QPixmap& pixmap)
{
pixmap.fill(ToColor());
return true;
}
template<std::size_t ComponentCount>
QColor VecValue<ComponentCount>::ToColor() const
{
std::array<float, 4> values = { 0.f, 0.f, 0.f, 1.f };
for (std::size_t i = 0; i < ComponentCount; ++i)
values[i] = std::clamp(m_value[i], 0.f, 1.f);
return QColor::fromRgbF(values[0], values[1], values[2], values[3]);
}
template<std::size_t ComponentCount>
void VecValue<ComponentCount>::restore(const QJsonObject& data)
{
QJsonArray vecValues = data["value"].toArray();
std::size_t commonValues = std::min(static_cast<std::size_t>(vecValues.size()), ComponentCount);
for (std::size_t i = 0; i < commonValues; ++i)
m_value[i] = float(vecValues[int(i)].toDouble(m_value[i]));
ShaderNode::restore(data);
}
template<std::size_t ComponentCount>
QJsonObject VecValue<ComponentCount>::save() const
{
QJsonObject data = ShaderNode::save();
QJsonArray vecValues;
for (std::size_t i = 0; i < ComponentCount; ++i)
vecValues.push_back(m_value[i]);
data["value"] = vecValues;
return data;
}