ShaderNode: Add buffers and structs
This commit is contained in:
parent
fbba281d14
commit
c7a8091e68
|
|
@ -120,11 +120,11 @@ Nz::ShaderNodes::ExpressionPtr InputValue::GetExpression(Nz::ShaderNodes::Expres
|
|||
{
|
||||
switch (inputEntry.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;
|
||||
case PrimitiveType::Bool: return Nz::ShaderNodes::ExpressionType::Boolean;
|
||||
case PrimitiveType::Float1: return Nz::ShaderNodes::ExpressionType::Float1;
|
||||
case PrimitiveType::Float2: return Nz::ShaderNodes::ExpressionType::Float2;
|
||||
case PrimitiveType::Float3: return Nz::ShaderNodes::ExpressionType::Float3;
|
||||
case PrimitiveType::Float4: return Nz::ShaderNodes::ExpressionType::Float4;
|
||||
}
|
||||
|
||||
assert(false);
|
||||
|
|
@ -146,12 +146,12 @@ auto InputValue::dataType(QtNodes::PortType portType, QtNodes::PortIndex portInd
|
|||
switch (inputEntry.type)
|
||||
{
|
||||
//case InputType::Bool: return Nz::ShaderNodes::ExpressionType::Boolean;
|
||||
case InOutType::Float1:
|
||||
case PrimitiveType::Float1:
|
||||
return FloatData::Type();
|
||||
|
||||
case InOutType::Float2:
|
||||
case InOutType::Float3:
|
||||
case InOutType::Float4:
|
||||
case PrimitiveType::Float2:
|
||||
case PrimitiveType::Float3:
|
||||
case PrimitiveType::Float4:
|
||||
return VecData::Type();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -67,11 +67,11 @@ Nz::ShaderNodes::ExpressionPtr OutputValue::GetExpression(Nz::ShaderNodes::Expre
|
|||
{
|
||||
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;
|
||||
case PrimitiveType::Bool: return Nz::ShaderNodes::ExpressionType::Boolean;
|
||||
case PrimitiveType::Float1: return Nz::ShaderNodes::ExpressionType::Float1;
|
||||
case PrimitiveType::Float2: return Nz::ShaderNodes::ExpressionType::Float2;
|
||||
case PrimitiveType::Float3: return Nz::ShaderNodes::ExpressionType::Float3;
|
||||
case PrimitiveType::Float4: return Nz::ShaderNodes::ExpressionType::Float4;
|
||||
}
|
||||
|
||||
assert(false);
|
||||
|
|
@ -96,9 +96,9 @@ QtNodes::NodeDataType OutputValue::dataType(QtNodes::PortType portType, QtNodes:
|
|||
{
|
||||
//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:
|
||||
case PrimitiveType::Float2:
|
||||
case PrimitiveType::Float3:
|
||||
case PrimitiveType::Float4:
|
||||
return VecData::Type();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,21 +1,32 @@
|
|||
#include <ShaderNode/Enums.hpp>
|
||||
#include <cassert>
|
||||
|
||||
std::size_t GetComponentCount(InOutType type)
|
||||
std::size_t GetComponentCount(PrimitiveType type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case InOutType::Bool: return 1;
|
||||
case InOutType::Float1: return 1;
|
||||
case InOutType::Float2: return 2;
|
||||
case InOutType::Float3: return 3;
|
||||
case InOutType::Float4: return 4;
|
||||
case PrimitiveType::Bool: return 1;
|
||||
case PrimitiveType::Float1: return 1;
|
||||
case PrimitiveType::Float2: return 2;
|
||||
case PrimitiveType::Float3: return 3;
|
||||
case PrimitiveType::Float4: return 4;
|
||||
}
|
||||
|
||||
assert(false);
|
||||
return 0;
|
||||
}
|
||||
|
||||
const char* EnumToString(BufferType bufferType)
|
||||
{
|
||||
switch (bufferType)
|
||||
{
|
||||
case BufferType::UniformBufferObject: return "UniformBufferObject";
|
||||
}
|
||||
|
||||
assert(false);
|
||||
return "<Unhandled>";
|
||||
}
|
||||
|
||||
const char* EnumToString(InputRole role)
|
||||
{
|
||||
switch (role)
|
||||
|
|
@ -30,15 +41,15 @@ const char* EnumToString(InputRole role)
|
|||
return "<Unhandled>";
|
||||
}
|
||||
|
||||
const char* EnumToString(InOutType input)
|
||||
const char* EnumToString(PrimitiveType input)
|
||||
{
|
||||
switch (input)
|
||||
{
|
||||
case InOutType::Bool: return "Bool";
|
||||
case InOutType::Float1: return "Float";
|
||||
case InOutType::Float2: return "Float2";
|
||||
case InOutType::Float3: return "Float3";
|
||||
case InOutType::Float4: return "Float4";
|
||||
case PrimitiveType::Bool: return "Bool";
|
||||
case PrimitiveType::Float1: return "Float";
|
||||
case PrimitiveType::Float2: return "Float2";
|
||||
case PrimitiveType::Float3: return "Float3";
|
||||
case PrimitiveType::Float4: return "Float4";
|
||||
}
|
||||
|
||||
assert(false);
|
||||
|
|
|
|||
|
|
@ -7,6 +7,15 @@
|
|||
#include <optional>
|
||||
#include <string>
|
||||
|
||||
enum class BufferType
|
||||
{
|
||||
UniformBufferObject,
|
||||
|
||||
Max = UniformBufferObject
|
||||
};
|
||||
|
||||
constexpr std::size_t BufferTypeCount = static_cast<std::size_t>(BufferType::Max) + 1;
|
||||
|
||||
enum class InputRole
|
||||
{
|
||||
None,
|
||||
|
|
@ -19,7 +28,7 @@ enum class InputRole
|
|||
|
||||
constexpr std::size_t InputRoleCount = static_cast<std::size_t>(InputRole::Max) + 1;
|
||||
|
||||
enum class InOutType
|
||||
enum class PrimitiveType
|
||||
{
|
||||
Bool,
|
||||
Float1,
|
||||
|
|
@ -30,7 +39,7 @@ enum class InOutType
|
|||
Max = Float4
|
||||
};
|
||||
|
||||
constexpr std::size_t InOutTypeCount = static_cast<std::size_t>(InOutType::Max) + 1;
|
||||
constexpr std::size_t PrimitiveTypeCount = static_cast<std::size_t>(PrimitiveType::Max) + 1;
|
||||
|
||||
enum class TextureType
|
||||
{
|
||||
|
|
@ -43,10 +52,11 @@ constexpr std::size_t TextureTypeCount = static_cast<std::size_t>(TextureType::M
|
|||
|
||||
|
||||
template<typename T> std::optional<T> DecodeEnum(const std::string_view& str);
|
||||
const char* EnumToString(BufferType bufferType);
|
||||
const char* EnumToString(InputRole role);
|
||||
const char* EnumToString(InOutType input);
|
||||
const char* EnumToString(PrimitiveType input);
|
||||
const char* EnumToString(TextureType textureType);
|
||||
std::size_t GetComponentCount(InOutType type);
|
||||
std::size_t GetComponentCount(PrimitiveType type);
|
||||
|
||||
#include <ShaderNode/Enums.inl>
|
||||
|
||||
|
|
|
|||
|
|
@ -12,10 +12,10 @@ inline const Nz::Vector4f* PreviewValues::GetData() const
|
|||
|
||||
inline std::size_t PreviewValues::GetHeight() const
|
||||
{
|
||||
return m_width;
|
||||
return m_height;
|
||||
}
|
||||
|
||||
inline std::size_t PreviewValues::GetWidth() const
|
||||
{
|
||||
return m_height;
|
||||
return m_width;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -46,9 +46,23 @@ m_flowScene(BuildRegistry())
|
|||
});
|
||||
|
||||
// Test
|
||||
AddInput("UV", InOutType::Float2, InputRole::TexCoord, 0, 0);
|
||||
AddOutput("RenderTarget0", InOutType::Float4, 0);
|
||||
AddInput("UV", PrimitiveType::Float2, InputRole::TexCoord, 0, 0);
|
||||
AddOutput("RenderTarget0", PrimitiveType::Float4, 0);
|
||||
AddTexture("Potato", TextureType::Sampler2D, 1);
|
||||
AddStruct("TestStruct", {
|
||||
{
|
||||
{ "position", PrimitiveType::Float3 },
|
||||
{ "normal", PrimitiveType::Float3 },
|
||||
{ "uv", PrimitiveType::Float2 },
|
||||
}
|
||||
});
|
||||
AddStruct("TestStruct2", {
|
||||
{
|
||||
{ "position", PrimitiveType::Float3 },
|
||||
{ "normal", PrimitiveType::Float3 },
|
||||
{ "uv", PrimitiveType::Float2 },
|
||||
}
|
||||
});
|
||||
|
||||
UpdateTexturePreview(0, QImage(R"(C:\Users\Lynix\Pictures\potatavril.png)"));
|
||||
|
||||
|
|
@ -79,7 +93,21 @@ ShaderGraph::~ShaderGraph()
|
|||
m_flowScene.clearScene();
|
||||
}
|
||||
|
||||
std::size_t ShaderGraph::AddInput(std::string name, InOutType type, InputRole role, std::size_t roleIndex, std::size_t locationIndex)
|
||||
std::size_t ShaderGraph::AddBuffer(std::string name, BufferType bufferType, std::size_t structIndex, std::size_t bindingIndex)
|
||||
{
|
||||
std::size_t index = m_buffers.size();
|
||||
auto& bufferEntry = m_buffers.emplace_back();
|
||||
bufferEntry.bindingIndex = bindingIndex;
|
||||
bufferEntry.name = std::move(name);
|
||||
bufferEntry.structIndex = structIndex;
|
||||
bufferEntry.type = bufferType;
|
||||
|
||||
OnBufferListUpdate(this);
|
||||
|
||||
return index;
|
||||
}
|
||||
|
||||
std::size_t ShaderGraph::AddInput(std::string name, PrimitiveType type, InputRole role, std::size_t roleIndex, std::size_t locationIndex)
|
||||
{
|
||||
std::size_t index = m_inputs.size();
|
||||
auto& inputEntry = m_inputs.emplace_back();
|
||||
|
|
@ -94,7 +122,7 @@ std::size_t ShaderGraph::AddInput(std::string name, InOutType type, InputRole ro
|
|||
return index;
|
||||
}
|
||||
|
||||
std::size_t ShaderGraph::AddOutput(std::string name, InOutType type, std::size_t locationIndex)
|
||||
std::size_t ShaderGraph::AddOutput(std::string name, PrimitiveType type, std::size_t locationIndex)
|
||||
{
|
||||
std::size_t index = m_outputs.size();
|
||||
auto& outputEntry = m_outputs.emplace_back();
|
||||
|
|
@ -107,6 +135,18 @@ std::size_t ShaderGraph::AddOutput(std::string name, InOutType type, std::size_t
|
|||
return index;
|
||||
}
|
||||
|
||||
std::size_t ShaderGraph::AddStruct(std::string name, std::vector<StructMemberEntry> members)
|
||||
{
|
||||
std::size_t index = m_structs.size();
|
||||
auto& structEntry = m_structs.emplace_back();
|
||||
structEntry.name = std::move(name);
|
||||
structEntry.members = std::move(members);
|
||||
|
||||
OnStructListUpdate(this);
|
||||
|
||||
return index;
|
||||
}
|
||||
|
||||
std::size_t ShaderGraph::AddTexture(std::string name, TextureType type, std::size_t bindingIndex)
|
||||
{
|
||||
std::size_t index = m_textures.size();
|
||||
|
|
@ -125,11 +165,15 @@ void ShaderGraph::Clear()
|
|||
m_flowScene.clearScene();
|
||||
m_flowScene.clear();
|
||||
|
||||
m_buffers.clear();
|
||||
m_inputs.clear();
|
||||
m_structs.clear();
|
||||
m_outputs.clear();
|
||||
m_textures.clear();
|
||||
|
||||
OnBufferListUpdate(this);
|
||||
OnInputListUpdate(this);
|
||||
OnStructListUpdate(this);
|
||||
OnOutputListUpdate(this);
|
||||
OnTextureListUpdate(this);
|
||||
}
|
||||
|
|
@ -138,6 +182,20 @@ void ShaderGraph::Load(const QJsonObject& data)
|
|||
{
|
||||
Clear();
|
||||
|
||||
QJsonArray bufferArray = data["buffers"].toArray();
|
||||
for (const auto& bufferDocRef : bufferArray)
|
||||
{
|
||||
QJsonObject bufferDoc = bufferDocRef.toObject();
|
||||
|
||||
BufferEntry& buffer = m_buffers.emplace_back();
|
||||
buffer.bindingIndex = static_cast<std::size_t>(bufferDoc["bindingIndex"].toInt(0));
|
||||
buffer.name = bufferDoc["name"].toString().toStdString();
|
||||
buffer.structIndex = bufferDoc["structIndex"].toInt();
|
||||
buffer.type = DecodeEnum<BufferType>(bufferDoc["type"].toString().toStdString()).value();
|
||||
}
|
||||
|
||||
OnBufferListUpdate(this);
|
||||
|
||||
QJsonArray inputArray = data["inputs"].toArray();
|
||||
for (const auto& inputDocRef : inputArray)
|
||||
{
|
||||
|
|
@ -148,7 +206,7 @@ void ShaderGraph::Load(const QJsonObject& data)
|
|||
input.name = inputDoc["name"].toString().toStdString();
|
||||
input.role = DecodeEnum<InputRole>(inputDoc["role"].toString().toStdString()).value();
|
||||
input.roleIndex = static_cast<std::size_t>(inputDoc["roleIndex"].toInt(0));
|
||||
input.type = DecodeEnum<InOutType>(inputDoc["type"].toString().toStdString()).value();
|
||||
input.type = DecodeEnum<PrimitiveType>(inputDoc["type"].toString().toStdString()).value();
|
||||
}
|
||||
|
||||
OnInputListUpdate(this);
|
||||
|
|
@ -161,11 +219,37 @@ void ShaderGraph::Load(const QJsonObject& data)
|
|||
OutputEntry& output = m_outputs.emplace_back();
|
||||
output.locationIndex = static_cast<std::size_t>(outputDoc["locationIndex"].toInt(0));
|
||||
output.name = outputDoc["name"].toString().toStdString();
|
||||
output.type = DecodeEnum<InOutType>(outputDoc["type"].toString().toStdString()).value();
|
||||
output.type = DecodeEnum<PrimitiveType>(outputDoc["type"].toString().toStdString()).value();
|
||||
}
|
||||
|
||||
OnOutputListUpdate(this);
|
||||
|
||||
QJsonArray structArray = data["structs"].toArray();
|
||||
for (const auto& structDocRef : structArray)
|
||||
{
|
||||
QJsonObject structDoc = structDocRef.toObject();
|
||||
|
||||
StructEntry& structInfo = m_structs.emplace_back();
|
||||
structInfo.name = structDoc["name"].toString().toStdString();
|
||||
|
||||
QJsonArray memberArray = structDoc["members"].toArray();
|
||||
for (const auto& memberDocRef : memberArray)
|
||||
{
|
||||
QJsonObject memberDoc = memberDocRef.toObject();
|
||||
|
||||
auto& memberInfo = structInfo.members.emplace_back();
|
||||
memberInfo.name = memberDoc["name"].toString().toStdString();
|
||||
|
||||
const auto& typeDocRef = memberDoc["type"];
|
||||
if (typeDocRef.isString())
|
||||
memberInfo.type = DecodeEnum<PrimitiveType>(typeDocRef.toString().toStdString()).value();
|
||||
else
|
||||
memberInfo.type = typeDocRef.toInt();
|
||||
}
|
||||
}
|
||||
|
||||
OnStructListUpdate(this);
|
||||
|
||||
QJsonArray textureArray = data["textures"].toArray();
|
||||
for (const auto& textureDocRef : textureArray)
|
||||
{
|
||||
|
|
@ -190,6 +274,21 @@ QJsonObject ShaderGraph::Save()
|
|||
{
|
||||
QJsonObject sceneJson;
|
||||
|
||||
QJsonArray bufferArray;
|
||||
{
|
||||
for (const auto& buffer : m_buffers)
|
||||
{
|
||||
QJsonObject bufferDoc;
|
||||
bufferDoc["bindingIndex"] = int(buffer.bindingIndex);
|
||||
bufferDoc["name"] = QString::fromStdString(buffer.name);
|
||||
bufferDoc["structIndex"] = int(buffer.structIndex);
|
||||
bufferDoc["type"] = QString(EnumToString(buffer.type));
|
||||
|
||||
bufferArray.append(bufferDoc);
|
||||
}
|
||||
}
|
||||
sceneJson["buffers"] = bufferArray;
|
||||
|
||||
QJsonArray inputArray;
|
||||
{
|
||||
for (const auto& input : m_inputs)
|
||||
|
|
@ -220,6 +319,39 @@ QJsonObject ShaderGraph::Save()
|
|||
}
|
||||
sceneJson["outputs"] = outputArray;
|
||||
|
||||
QJsonArray structArray;
|
||||
{
|
||||
for (const auto& s : m_structs)
|
||||
{
|
||||
QJsonObject structDoc;
|
||||
structDoc["name"] = QString::fromStdString(s.name);
|
||||
|
||||
QJsonArray memberArray;
|
||||
for (const auto& member : s.members)
|
||||
{
|
||||
QJsonObject memberDoc;
|
||||
memberDoc["name"] = QString::fromStdString(member.name);
|
||||
|
||||
std::visit([&](auto&& arg)
|
||||
{
|
||||
using T = std::decay_t<decltype(arg)>;
|
||||
if constexpr (std::is_same_v<T, PrimitiveType>)
|
||||
memberDoc["type"] = QString(EnumToString(arg));
|
||||
else if constexpr (std::is_same_v<T, std::size_t>)
|
||||
memberDoc["type"] = int(arg);
|
||||
else
|
||||
static_assert(AlwaysFalse<T>::value, "non-exhaustive visitor");
|
||||
}, member.type);
|
||||
|
||||
memberDoc["type"] = QString::fromStdString(member.name);
|
||||
}
|
||||
structDoc["members"] = memberArray;
|
||||
|
||||
structArray.append(structDoc);
|
||||
}
|
||||
}
|
||||
sceneJson["structs"] = structArray;
|
||||
|
||||
QJsonArray textureArray;
|
||||
{
|
||||
for (const auto& texture : m_textures)
|
||||
|
|
@ -366,7 +498,19 @@ Nz::ShaderNodes::StatementPtr ShaderGraph::ToAst()
|
|||
return Nz::ShaderNodes::StatementBlock::Build(std::move(statements));
|
||||
}
|
||||
|
||||
void ShaderGraph::UpdateInput(std::size_t inputIndex, std::string name, InOutType type, InputRole role, std::size_t roleIndex, std::size_t locationIndex)
|
||||
void ShaderGraph::UpdateBuffer(std::size_t bufferIndex, std::string name, BufferType bufferType, std::size_t structIndex, std::size_t bindingIndex)
|
||||
{
|
||||
assert(bufferIndex < m_buffers.size());
|
||||
auto& bufferEntry = m_buffers[bufferIndex];
|
||||
bufferEntry.bindingIndex = bindingIndex;
|
||||
bufferEntry.name = std::move(name);
|
||||
bufferEntry.structIndex = structIndex;
|
||||
bufferEntry.type = bufferType;
|
||||
|
||||
OnBufferUpdate(this, bufferIndex);
|
||||
}
|
||||
|
||||
void ShaderGraph::UpdateInput(std::size_t inputIndex, std::string name, PrimitiveType type, InputRole role, std::size_t roleIndex, std::size_t locationIndex)
|
||||
{
|
||||
assert(inputIndex < m_inputs.size());
|
||||
auto& inputEntry = m_inputs[inputIndex];
|
||||
|
|
@ -379,7 +523,7 @@ void ShaderGraph::UpdateInput(std::size_t inputIndex, std::string name, InOutTyp
|
|||
OnInputUpdate(this, inputIndex);
|
||||
}
|
||||
|
||||
void ShaderGraph::UpdateOutput(std::size_t outputIndex, std::string name, InOutType type, std::size_t locationIndex)
|
||||
void ShaderGraph::UpdateOutput(std::size_t outputIndex, std::string name, PrimitiveType type, std::size_t locationIndex)
|
||||
{
|
||||
assert(outputIndex < m_outputs.size());
|
||||
auto& outputEntry = m_outputs[outputIndex];
|
||||
|
|
@ -390,6 +534,16 @@ void ShaderGraph::UpdateOutput(std::size_t outputIndex, std::string name, InOutT
|
|||
OnOutputUpdate(this, outputIndex);
|
||||
}
|
||||
|
||||
void ShaderGraph::UpdateStruct(std::size_t structIndex, std::string name, std::vector<StructMemberEntry> members)
|
||||
{
|
||||
assert(structIndex < m_structs.size());
|
||||
auto& structEntry = m_structs[structIndex];
|
||||
structEntry.name = std::move(name);
|
||||
structEntry.members = std::move(members);
|
||||
|
||||
OnStructUpdate(this, structIndex);
|
||||
}
|
||||
|
||||
void ShaderGraph::UpdateTexture(std::size_t textureIndex, std::string name, TextureType type, std::size_t bindingIndex)
|
||||
{
|
||||
assert(textureIndex < m_textures.size());
|
||||
|
|
|
|||
|
|
@ -16,25 +16,36 @@ class ShaderNode;
|
|||
class ShaderGraph
|
||||
{
|
||||
public:
|
||||
struct BufferEntry;
|
||||
struct InputEntry;
|
||||
struct OutputEntry;
|
||||
struct StructEntry;
|
||||
struct StructMemberEntry;
|
||||
struct TextureEntry;
|
||||
|
||||
ShaderGraph();
|
||||
~ShaderGraph();
|
||||
|
||||
std::size_t AddInput(std::string name, InOutType type, InputRole role, std::size_t roleIndex, std::size_t locationIndex);
|
||||
std::size_t AddOutput(std::string name, InOutType type, std::size_t locationIndex);
|
||||
std::size_t AddBuffer(std::string name, BufferType bufferType, std::size_t structIndex, std::size_t bindingIndex);
|
||||
std::size_t AddInput(std::string name, PrimitiveType type, InputRole role, std::size_t roleIndex, std::size_t locationIndex);
|
||||
std::size_t AddOutput(std::string name, PrimitiveType type, std::size_t locationIndex);
|
||||
std::size_t AddStruct(std::string name, std::vector<StructMemberEntry> members);
|
||||
std::size_t AddTexture(std::string name, TextureType type, std::size_t bindingIndex);
|
||||
|
||||
void Clear();
|
||||
|
||||
inline const InputEntry& GetInput(std::size_t inputIndex) const;
|
||||
inline const BufferEntry& GetBuffer(std::size_t bufferIndex) const;
|
||||
inline std::size_t GetBufferCount() const;
|
||||
inline const std::vector<BufferEntry>& GetBuffers() const;
|
||||
inline const InputEntry& GetInput(std::size_t bufferIndex) const;
|
||||
inline std::size_t GetInputCount() const;
|
||||
inline const std::vector<InputEntry>& GetInputs() const;
|
||||
inline const OutputEntry& GetOutput(std::size_t outputIndex) const;
|
||||
inline std::size_t GetOutputCount() const;
|
||||
inline const std::vector<OutputEntry>& GetOutputs() const;
|
||||
inline const StructEntry& GetStruct(std::size_t structIndex) const;
|
||||
inline std::size_t GetStructCount() const;
|
||||
inline const std::vector<StructEntry>& GetStructs() const;
|
||||
inline const PreviewModel& GetPreviewModel() const;
|
||||
inline QtNodes::FlowScene& GetScene();
|
||||
inline const TextureEntry& GetTexture(std::size_t textureIndex) const;
|
||||
|
|
@ -46,25 +57,47 @@ class ShaderGraph
|
|||
|
||||
Nz::ShaderNodes::StatementPtr ToAst();
|
||||
|
||||
void UpdateInput(std::size_t inputIndex, std::string name, InOutType type, InputRole role, std::size_t roleIndex, std::size_t locationIndex);
|
||||
void UpdateOutput(std::size_t outputIndex, std::string name, InOutType type, std::size_t locationIndex);
|
||||
void UpdateBuffer(std::size_t bufferIndex, std::string name, BufferType bufferType, std::size_t structIndex, std::size_t bindingIndex);
|
||||
void UpdateInput(std::size_t inputIndex, std::string name, PrimitiveType type, InputRole role, std::size_t roleIndex, std::size_t locationIndex);
|
||||
void UpdateOutput(std::size_t outputIndex, std::string name, PrimitiveType type, std::size_t locationIndex);
|
||||
void UpdateStruct(std::size_t structIndex, std::string name, std::vector<StructMemberEntry> members);
|
||||
void UpdateTexture(std::size_t textureIndex, std::string name, TextureType type, std::size_t bindingIndex);
|
||||
void UpdateTexturePreview(std::size_t texture, QImage preview);
|
||||
|
||||
struct BufferEntry
|
||||
{
|
||||
std::size_t bindingIndex;
|
||||
std::size_t structIndex;
|
||||
std::string name;
|
||||
BufferType type;
|
||||
};
|
||||
|
||||
struct InputEntry
|
||||
{
|
||||
std::size_t locationIndex;
|
||||
std::size_t roleIndex;
|
||||
std::string name;
|
||||
InputRole role;
|
||||
InOutType type;
|
||||
PrimitiveType type;
|
||||
};
|
||||
|
||||
struct OutputEntry
|
||||
{
|
||||
std::size_t locationIndex;
|
||||
std::string name;
|
||||
InOutType type;
|
||||
PrimitiveType type;
|
||||
};
|
||||
|
||||
struct StructEntry
|
||||
{
|
||||
std::string name;
|
||||
std::vector<StructMemberEntry> members;
|
||||
};
|
||||
|
||||
struct StructMemberEntry
|
||||
{
|
||||
std::string name;
|
||||
std::variant<PrimitiveType, std::size_t /*structIndex*/> type;
|
||||
};
|
||||
|
||||
struct TextureEntry
|
||||
|
|
@ -75,11 +108,15 @@ class ShaderGraph
|
|||
QImage preview;
|
||||
};
|
||||
|
||||
NazaraSignal(OnBufferListUpdate, ShaderGraph*);
|
||||
NazaraSignal(OnBufferUpdate, ShaderGraph*, std::size_t /*outputIndex*/);
|
||||
NazaraSignal(OnInputListUpdate, ShaderGraph*);
|
||||
NazaraSignal(OnInputUpdate, ShaderGraph*, std::size_t /*inputIndex*/);
|
||||
NazaraSignal(OnOutputListUpdate, ShaderGraph*);
|
||||
NazaraSignal(OnOutputUpdate, ShaderGraph*, std::size_t /*outputIndex*/);
|
||||
NazaraSignal(OnSelectedNodeUpdate, ShaderGraph*, ShaderNode* /*node*/);
|
||||
NazaraSignal(OnStructListUpdate, ShaderGraph*);
|
||||
NazaraSignal(OnStructUpdate, ShaderGraph*, std::size_t /*structIndex*/);
|
||||
NazaraSignal(OnTextureListUpdate, ShaderGraph*);
|
||||
NazaraSignal(OnTexturePreviewUpdate, ShaderGraph*, std::size_t /*textureIndex*/);
|
||||
NazaraSignal(OnTextureUpdate, ShaderGraph*, std::size_t /*textureIndex*/);
|
||||
|
|
@ -88,8 +125,10 @@ class ShaderGraph
|
|||
std::shared_ptr<QtNodes::DataModelRegistry> BuildRegistry();
|
||||
|
||||
QtNodes::FlowScene m_flowScene;
|
||||
std::vector<BufferEntry> m_buffers;
|
||||
std::vector<InputEntry> m_inputs;
|
||||
std::vector<OutputEntry> m_outputs;
|
||||
std::vector<StructEntry> m_structs;
|
||||
std::vector<TextureEntry> m_textures;
|
||||
std::unique_ptr<PreviewModel> m_previewModel;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,5 +1,21 @@
|
|||
#include <ShaderNode/ShaderGraph.hpp>
|
||||
|
||||
inline auto ShaderGraph::GetBuffer(std::size_t bufferIndex) const -> const BufferEntry&
|
||||
{
|
||||
assert(bufferIndex < m_buffers.size());
|
||||
return m_buffers[bufferIndex];
|
||||
}
|
||||
|
||||
inline std::size_t ShaderGraph::GetBufferCount() const
|
||||
{
|
||||
return m_buffers.size();
|
||||
}
|
||||
|
||||
inline auto ShaderGraph::GetBuffers() const -> const std::vector<BufferEntry>&
|
||||
{
|
||||
return m_buffers;
|
||||
}
|
||||
|
||||
inline auto ShaderGraph::GetInput(std::size_t inputIndex) const -> const InputEntry&
|
||||
{
|
||||
assert(inputIndex < m_inputs.size());
|
||||
|
|
@ -32,6 +48,22 @@ inline auto ShaderGraph::GetOutputs() const -> const std::vector<OutputEntry>&
|
|||
return m_outputs;
|
||||
}
|
||||
|
||||
inline auto ShaderGraph::GetStruct(std::size_t structIndex) const -> const StructEntry&
|
||||
{
|
||||
assert(structIndex < m_structs.size());
|
||||
return m_structs[structIndex];
|
||||
}
|
||||
|
||||
inline std::size_t ShaderGraph::GetStructCount() const
|
||||
{
|
||||
return m_structs.size();
|
||||
}
|
||||
|
||||
inline auto ShaderGraph::GetStructs() const -> const std::vector<StructEntry>&
|
||||
{
|
||||
return m_structs;
|
||||
}
|
||||
|
||||
inline const PreviewModel& ShaderGraph::GetPreviewModel() const
|
||||
{
|
||||
return *m_previewModel;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,88 @@
|
|||
#include <ShaderNode/Widgets/BufferEditDialog.hpp>
|
||||
#include <ShaderNode/ShaderGraph.hpp>
|
||||
#include <QtWidgets/QComboBox>
|
||||
#include <QtWidgets/QDialogButtonBox>
|
||||
#include <QtWidgets/QFormLayout>
|
||||
#include <QtWidgets/QLineEdit>
|
||||
#include <QtWidgets/QMessageBox>
|
||||
#include <QtWidgets/QSpinBox>
|
||||
#include <QtWidgets/QVBoxLayout>
|
||||
|
||||
BufferEditDialog::BufferEditDialog(const ShaderGraph& shaderGraph, QWidget* parent) :
|
||||
QDialog(parent),
|
||||
m_shaderGraph(shaderGraph)
|
||||
{
|
||||
setWindowTitle(tr("Buffer edit dialog"));
|
||||
setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
|
||||
|
||||
m_outputName = new QLineEdit;
|
||||
|
||||
m_typeList = new QComboBox;
|
||||
for (std::size_t i = 0; i < BufferTypeCount; ++i)
|
||||
m_typeList->addItem(EnumToString(static_cast<BufferType>(i)));
|
||||
|
||||
m_structList = new QComboBox;
|
||||
for (const auto& structEntry : m_shaderGraph.GetStructs())
|
||||
m_structList->addItem(QString::fromStdString(structEntry.name));
|
||||
|
||||
m_bindingIndex = new QSpinBox;
|
||||
|
||||
QFormLayout* formLayout = new QFormLayout;
|
||||
formLayout->addRow(tr("Name"), m_outputName);
|
||||
formLayout->addRow(tr("Type"), m_typeList);
|
||||
formLayout->addRow(tr("Struct"), m_structList);
|
||||
formLayout->addRow(tr("Binding index"), m_bindingIndex);
|
||||
|
||||
QDialogButtonBox* buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
|
||||
connect(buttonBox, &QDialogButtonBox::accepted, this, &BufferEditDialog::OnAccept);
|
||||
connect(buttonBox, &QDialogButtonBox::rejected, this, &QDialog::reject);
|
||||
|
||||
QVBoxLayout* verticalLayout = new QVBoxLayout;
|
||||
verticalLayout->addLayout(formLayout);
|
||||
verticalLayout->addWidget(buttonBox);
|
||||
|
||||
setLayout(verticalLayout);
|
||||
}
|
||||
|
||||
BufferEditDialog::BufferEditDialog(const ShaderGraph& shaderGraph, const BufferInfo& buffer, QWidget* parent) :
|
||||
BufferEditDialog(shaderGraph, parent)
|
||||
{
|
||||
m_bindingIndex->setValue(int(buffer.bindingIndex));
|
||||
m_outputName->setText(QString::fromStdString(buffer.name));
|
||||
m_structList->setCurrentIndex(buffer.structIndex);
|
||||
m_typeList->setCurrentIndex(int(buffer.type));
|
||||
}
|
||||
|
||||
BufferInfo BufferEditDialog::GetBufferInfo() const
|
||||
{
|
||||
BufferInfo bufferInfo;
|
||||
bufferInfo.bindingIndex = static_cast<std::size_t>(m_bindingIndex->value());
|
||||
bufferInfo.name = m_outputName->text().toStdString();
|
||||
bufferInfo.structIndex = m_structList->currentIndex();
|
||||
bufferInfo.type = static_cast<BufferType>(m_typeList->currentIndex());
|
||||
|
||||
return bufferInfo;
|
||||
}
|
||||
|
||||
void BufferEditDialog::OnAccept()
|
||||
{
|
||||
if (m_outputName->text().isEmpty())
|
||||
{
|
||||
QMessageBox::critical(this, tr("Empty name"), tr("Buffer name must be set"), QMessageBox::Ok);
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_structList->currentIndex() < 0)
|
||||
{
|
||||
QMessageBox::critical(this, tr("Invalid struct"), tr("You must select a struct"), 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,43 @@
|
|||
#pragma once
|
||||
|
||||
#ifndef NAZARA_SHADERNODES_BUFFEREDITDIALOG_HPP
|
||||
#define NAZARA_SHADERNODES_BUFFEREDITDIALOG_HPP
|
||||
|
||||
#include <ShaderNode/Enums.hpp>
|
||||
#include <QtWidgets/QDialog>
|
||||
|
||||
class QComboBox;
|
||||
class QLineEdit;
|
||||
class QSpinBox;
|
||||
class ShaderGraph;
|
||||
|
||||
struct BufferInfo
|
||||
{
|
||||
std::size_t bindingIndex;
|
||||
std::size_t structIndex;
|
||||
std::string name;
|
||||
BufferType type;
|
||||
};
|
||||
|
||||
class BufferEditDialog : public QDialog
|
||||
{
|
||||
public:
|
||||
BufferEditDialog(const ShaderGraph& shaderGraph, QWidget* parent = nullptr);
|
||||
BufferEditDialog(const ShaderGraph& shaderGraph, const BufferInfo& output, QWidget* parent = nullptr);
|
||||
~BufferEditDialog() = default;
|
||||
|
||||
BufferInfo GetBufferInfo() const;
|
||||
|
||||
private:
|
||||
void OnAccept();
|
||||
|
||||
const ShaderGraph& m_shaderGraph;
|
||||
QComboBox* m_typeList;
|
||||
QComboBox* m_structList;
|
||||
QLineEdit* m_outputName;
|
||||
QSpinBox* m_bindingIndex;
|
||||
};
|
||||
|
||||
#include <ShaderNode/Widgets/BufferEditDialog.inl>
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1 @@
|
|||
#include <ShaderNode/Widgets/BufferEditDialog.hpp>
|
||||
|
|
@ -0,0 +1,85 @@
|
|||
#include <ShaderNode/Widgets/BufferEditor.hpp>
|
||||
#include <ShaderNode/Widgets/BufferEditDialog.hpp>
|
||||
#include <ShaderNode/ShaderGraph.hpp>
|
||||
#include <QtWidgets/QFileDialog>
|
||||
#include <QtWidgets/QLabel>
|
||||
#include <QtWidgets/QPushButton>
|
||||
#include <QtWidgets/QListWidget>
|
||||
#include <QtWidgets/QVBoxLayout>
|
||||
|
||||
BufferEditor::BufferEditor(ShaderGraph& graph) :
|
||||
m_shaderGraph(graph)
|
||||
{
|
||||
m_bufferList = new QListWidget(this);
|
||||
connect(m_bufferList, &QListWidget::itemDoubleClicked, [this](QListWidgetItem* item)
|
||||
{
|
||||
OnEditBuffer(m_bufferList->row(item));
|
||||
});
|
||||
|
||||
QPushButton* addBufferButton = new QPushButton(tr("Add buffer..."));
|
||||
connect(addBufferButton, &QPushButton::released, this, &BufferEditor::OnAddBuffer);
|
||||
|
||||
m_layout = new QVBoxLayout;
|
||||
m_layout->addWidget(m_bufferList);
|
||||
m_layout->addWidget(addBufferButton);
|
||||
|
||||
setLayout(m_layout);
|
||||
|
||||
m_onBufferListUpdateSlot.Connect(m_shaderGraph.OnBufferListUpdate, this, &BufferEditor::OnBufferListUpdate);
|
||||
m_onBufferUpdateSlot.Connect(m_shaderGraph.OnBufferUpdate, this, &BufferEditor::OnBufferUpdate);
|
||||
|
||||
RefreshBuffers();
|
||||
}
|
||||
|
||||
void BufferEditor::OnAddBuffer()
|
||||
{
|
||||
BufferEditDialog* dialog = new BufferEditDialog(m_shaderGraph, this);
|
||||
dialog->setAttribute(Qt::WA_DeleteOnClose, true);
|
||||
connect(dialog, &QDialog::accepted, [this, dialog]
|
||||
{
|
||||
BufferInfo bufferInfo = dialog->GetBufferInfo();
|
||||
m_shaderGraph.AddBuffer(std::move(bufferInfo.name), bufferInfo.type, bufferInfo.structIndex, bufferInfo.bindingIndex);
|
||||
});
|
||||
|
||||
dialog->open();
|
||||
}
|
||||
|
||||
void BufferEditor::OnEditBuffer(int inputIndex)
|
||||
{
|
||||
const auto& buffer = m_shaderGraph.GetBuffer(inputIndex);
|
||||
|
||||
BufferInfo info;
|
||||
info.name = buffer.name;
|
||||
info.structIndex = buffer.structIndex;
|
||||
info.type = buffer.type;
|
||||
|
||||
BufferEditDialog* dialog = new BufferEditDialog(m_shaderGraph, std::move(info), this);
|
||||
dialog->setAttribute(Qt::WA_DeleteOnClose, true);
|
||||
connect(dialog, &QDialog::accepted, [this, dialog, inputIndex]
|
||||
{
|
||||
BufferInfo bufferInfo = dialog->GetBufferInfo();
|
||||
m_shaderGraph.UpdateBuffer(inputIndex, std::move(bufferInfo.name), bufferInfo.type, bufferInfo.structIndex, bufferInfo.bindingIndex);
|
||||
});
|
||||
|
||||
dialog->open();
|
||||
}
|
||||
|
||||
void BufferEditor::OnBufferListUpdate(ShaderGraph* /*graph*/)
|
||||
{
|
||||
RefreshBuffers();
|
||||
}
|
||||
|
||||
void BufferEditor::OnBufferUpdate(ShaderGraph* /*graph*/, std::size_t bufferIndex)
|
||||
{
|
||||
const auto& bufferEntry = m_shaderGraph.GetBuffer(bufferIndex);
|
||||
m_bufferList->item(int(bufferIndex))->setText(QString::fromStdString(bufferEntry.name));
|
||||
}
|
||||
|
||||
void BufferEditor::RefreshBuffers()
|
||||
{
|
||||
m_bufferList->clear();
|
||||
m_bufferList->setCurrentRow(-1);
|
||||
|
||||
for (const auto& bufferEntry : m_shaderGraph.GetBuffers())
|
||||
m_bufferList->addItem(QString::fromStdString(bufferEntry.name));
|
||||
}
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
#pragma once
|
||||
|
||||
#ifndef NAZARA_SHADERNODES_BUFFEREDITOR_HPP
|
||||
#define NAZARA_SHADERNODES_BUFFEREDITOR_HPP
|
||||
|
||||
#include <ShaderNode/ShaderGraph.hpp>
|
||||
#include <QtWidgets/QWidget>
|
||||
|
||||
class QLabel;
|
||||
class QListWidget;
|
||||
class QVBoxLayout;
|
||||
|
||||
class BufferEditor : public QWidget
|
||||
{
|
||||
public:
|
||||
BufferEditor(ShaderGraph& graph);
|
||||
~BufferEditor() = default;
|
||||
|
||||
private:
|
||||
void OnAddBuffer();
|
||||
void OnEditBuffer(int inputIndex);
|
||||
void OnBufferListUpdate(ShaderGraph* graph);
|
||||
void OnBufferUpdate(ShaderGraph* graph, std::size_t inputIndex);
|
||||
void RefreshBuffers();
|
||||
|
||||
NazaraSlot(ShaderGraph, OnBufferListUpdate, m_onBufferListUpdateSlot);
|
||||
NazaraSlot(ShaderGraph, OnBufferUpdate, m_onBufferUpdateSlot);
|
||||
|
||||
ShaderGraph& m_shaderGraph;
|
||||
QListWidget* m_bufferList;
|
||||
QVBoxLayout* m_layout;
|
||||
};
|
||||
|
||||
#include <ShaderNode/Widgets/BufferEditor.inl>
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1 @@
|
|||
#include <ShaderNode/Widgets/BufferEditor.hpp>
|
||||
|
|
@ -16,8 +16,8 @@ QDialog(parent)
|
|||
m_inputName = new QLineEdit;
|
||||
|
||||
m_typeList = new QComboBox;
|
||||
for (std::size_t i = 0; i < InOutTypeCount; ++i)
|
||||
m_typeList->addItem(EnumToString(static_cast<InOutType>(i)));
|
||||
for (std::size_t i = 0; i < PrimitiveTypeCount; ++i)
|
||||
m_typeList->addItem(EnumToString(static_cast<PrimitiveType>(i)));
|
||||
|
||||
m_roleList = new QComboBox;
|
||||
for (std::size_t i = 0; i < InputRoleCount; ++i)
|
||||
|
|
@ -62,7 +62,7 @@ InputInfo InputEditDialog::GetInputInfo() const
|
|||
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<InOutType>(m_typeList->currentIndex());
|
||||
inputInfo.type = static_cast<PrimitiveType>(m_typeList->currentIndex());
|
||||
|
||||
return inputInfo;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ struct InputInfo
|
|||
std::size_t roleIndex;
|
||||
std::string name;
|
||||
InputRole role;
|
||||
InOutType type;
|
||||
PrimitiveType type;
|
||||
};
|
||||
|
||||
class InputEditDialog : public QDialog
|
||||
|
|
|
|||
|
|
@ -3,9 +3,11 @@
|
|||
#include <Nazara/Renderer/GlslWriter.hpp>
|
||||
#include <Nazara/Renderer/ShaderSerializer.hpp>
|
||||
#include <ShaderNode/ShaderGraph.hpp>
|
||||
#include <ShaderNode/Widgets/BufferEditor.hpp>
|
||||
#include <ShaderNode/Widgets/InputEditor.hpp>
|
||||
#include <ShaderNode/Widgets/OutputEditor.hpp>
|
||||
#include <ShaderNode/Widgets/NodeEditor.hpp>
|
||||
#include <ShaderNode/Widgets/StructEditor.hpp>
|
||||
#include <ShaderNode/Widgets/TextureEditor.hpp>
|
||||
#include <nodes/FlowView>
|
||||
#include <QtCore/QFile>
|
||||
|
|
@ -63,6 +65,24 @@ m_shaderGraph(graph)
|
|||
|
||||
addDockWidget(Qt::RightDockWidgetArea, nodeEditorDock);
|
||||
|
||||
// Buffer editor
|
||||
BufferEditor* bufferEditor = new BufferEditor(m_shaderGraph);
|
||||
|
||||
QDockWidget* bufferDock = new QDockWidget(tr("Buffers"));
|
||||
bufferDock->setFeatures(QDockWidget::DockWidgetFloatable | QDockWidget::DockWidgetMovable);
|
||||
bufferDock->setWidget(bufferEditor);
|
||||
|
||||
addDockWidget(Qt::RightDockWidgetArea, bufferDock);
|
||||
|
||||
// Struct editor
|
||||
StructEditor* structEditor = new StructEditor(m_shaderGraph);
|
||||
|
||||
QDockWidget* structDock = new QDockWidget(tr("Structs"));
|
||||
structDock->setFeatures(QDockWidget::DockWidgetFloatable | QDockWidget::DockWidgetMovable);
|
||||
structDock->setWidget(structEditor);
|
||||
|
||||
addDockWidget(Qt::RightDockWidgetArea, structDock);
|
||||
|
||||
m_onSelectedNodeUpdate.Connect(m_shaderGraph.OnSelectedNodeUpdate, [&](ShaderGraph*, ShaderNode* node)
|
||||
{
|
||||
if (node)
|
||||
|
|
@ -193,15 +213,15 @@ Nz::ShaderAst MainWindow::ToShader()
|
|||
Nz::ShaderNodes::StatementPtr shaderAst = m_shaderGraph.ToAst();
|
||||
|
||||
//TODO: Put in another function
|
||||
auto GetExpressionFromInOut = [&](InOutType type)
|
||||
auto GetExpressionFromInOut = [&](PrimitiveType type)
|
||||
{
|
||||
switch (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;
|
||||
case PrimitiveType::Bool: return Nz::ShaderNodes::ExpressionType::Boolean;
|
||||
case PrimitiveType::Float1: return Nz::ShaderNodes::ExpressionType::Float1;
|
||||
case PrimitiveType::Float2: return Nz::ShaderNodes::ExpressionType::Float2;
|
||||
case PrimitiveType::Float3: return Nz::ShaderNodes::ExpressionType::Float3;
|
||||
case PrimitiveType::Float4: return Nz::ShaderNodes::ExpressionType::Float4;
|
||||
}
|
||||
|
||||
assert(false);
|
||||
|
|
@ -226,8 +246,37 @@ Nz::ShaderAst MainWindow::ToShader()
|
|||
for (const auto& output : m_shaderGraph.GetOutputs())
|
||||
shader.AddOutput(output.name, GetExpressionFromInOut(output.type), output.locationIndex);
|
||||
|
||||
for (const auto& buffer : m_shaderGraph.GetBuffers())
|
||||
{
|
||||
const auto& structInfo = m_shaderGraph.GetStruct(buffer.structIndex);
|
||||
shader.AddUniform(buffer.name, structInfo.name, buffer.bindingIndex, Nz::ShaderNodes::MemoryLayout::Std140);
|
||||
}
|
||||
|
||||
for (const auto& uniform : m_shaderGraph.GetTextures())
|
||||
shader.AddUniform(uniform.name, GetExpressionFromTexture(uniform.type), uniform.bindingIndex);
|
||||
shader.AddUniform(uniform.name, GetExpressionFromTexture(uniform.type), uniform.bindingIndex, {});
|
||||
|
||||
for (const auto& s : m_shaderGraph.GetStructs())
|
||||
{
|
||||
std::vector<Nz::ShaderAst::StructMember> members;
|
||||
for (const auto& sMember : s.members)
|
||||
{
|
||||
auto& member = members.emplace_back();
|
||||
member.name = sMember.name;
|
||||
|
||||
std::visit([&](auto&& arg)
|
||||
{
|
||||
using T = std::decay_t<decltype(arg)>;
|
||||
if constexpr (std::is_same_v<T, PrimitiveType>)
|
||||
member.type = GetExpressionFromInOut(arg);
|
||||
else if constexpr (std::is_same_v<T, std::size_t>)
|
||||
member.type = m_shaderGraph.GetStruct(arg).name;
|
||||
else
|
||||
static_assert(AlwaysFalse<T>::value, "non-exhaustive visitor");
|
||||
}, sMember.type);
|
||||
}
|
||||
|
||||
shader.AddStruct(s.name, std::move(members));
|
||||
}
|
||||
|
||||
shader.AddFunction("main", shaderAst);
|
||||
|
||||
|
|
|
|||
|
|
@ -16,8 +16,8 @@ QDialog(parent)
|
|||
m_outputName = new QLineEdit;
|
||||
|
||||
m_typeList = new QComboBox;
|
||||
for (std::size_t i = 0; i < InOutTypeCount; ++i)
|
||||
m_typeList->addItem(EnumToString(static_cast<InOutType>(i)));
|
||||
for (std::size_t i = 0; i < PrimitiveTypeCount; ++i)
|
||||
m_typeList->addItem(EnumToString(static_cast<PrimitiveType>(i)));
|
||||
|
||||
m_locationIndex = new QSpinBox;
|
||||
|
||||
|
|
@ -50,7 +50,7 @@ OutputInfo OutputEditDialog::GetOutputInfo() const
|
|||
OutputInfo inputInfo;
|
||||
inputInfo.locationIndex = static_cast<std::size_t>(m_locationIndex->value());
|
||||
inputInfo.name = m_outputName->text().toStdString();
|
||||
inputInfo.type = static_cast<InOutType>(m_typeList->currentIndex());
|
||||
inputInfo.type = static_cast<PrimitiveType>(m_typeList->currentIndex());
|
||||
|
||||
return inputInfo;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ struct OutputInfo
|
|||
{
|
||||
std::size_t locationIndex;
|
||||
std::string name;
|
||||
InOutType type;
|
||||
PrimitiveType type;
|
||||
};
|
||||
|
||||
class OutputEditDialog : public QDialog
|
||||
|
|
|
|||
|
|
@ -0,0 +1,224 @@
|
|||
#include <ShaderNode/Widgets/StructEditDialog.hpp>
|
||||
#include <ShaderNode/Widgets/StructMemberEditDialog.hpp>
|
||||
#include <Nazara/Core/Algorithm.hpp>
|
||||
#include <ShaderNode/ShaderGraph.hpp>
|
||||
#include <QtWidgets/QComboBox>
|
||||
#include <QtWidgets/QDialogButtonBox>
|
||||
#include <QtWidgets/QFormLayout>
|
||||
#include <QtWidgets/QLineEdit>
|
||||
#include <QtWidgets/QListWidget>
|
||||
#include <QtWidgets/QMessageBox>
|
||||
#include <QtWidgets/QPushButton>
|
||||
#include <QtWidgets/QVBoxLayout>
|
||||
|
||||
StructEditDialog::StructEditDialog(ShaderGraph& graph, QWidget* parent) :
|
||||
QDialog(parent),
|
||||
m_shaderGraph(graph)
|
||||
{
|
||||
setWindowTitle(tr("Struct edit dialog"));
|
||||
setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
|
||||
|
||||
m_structName = new QLineEdit;
|
||||
connect(m_structName, &QLineEdit::textEdited, [this](QString newText)
|
||||
{
|
||||
m_info.name = newText.toStdString();
|
||||
});
|
||||
|
||||
m_memberList = new QListWidget;
|
||||
connect(m_memberList, &QListWidget::currentRowChanged, this, &StructEditDialog::OnMemberSelected);
|
||||
connect(m_memberList, &QListWidget::itemDoubleClicked, [this](QListWidgetItem* item)
|
||||
{
|
||||
OnEditMember(m_memberList->row(item));
|
||||
});
|
||||
|
||||
m_memberMoveUpButton = new QPushButton(tr("Move up"));
|
||||
m_memberMoveUpButton->setEnabled(false);
|
||||
connect(m_memberMoveUpButton, &QPushButton::released, this, &StructEditDialog::OnMemberMoveUp);
|
||||
|
||||
m_memberMoveDownButton = new QPushButton(tr("Move down"));
|
||||
m_memberMoveDownButton->setEnabled(false);
|
||||
connect(m_memberMoveDownButton, &QPushButton::released, this, &StructEditDialog::OnMemberMoveDown);
|
||||
|
||||
m_deleteMemberButton = new QPushButton(tr("Delete member"));
|
||||
m_deleteMemberButton->setEnabled(false);
|
||||
connect(m_deleteMemberButton, &QPushButton::released, this, &StructEditDialog::OnDeleteMember);
|
||||
|
||||
QPushButton* addMemberButton = new QPushButton(tr("Add member..."));
|
||||
connect(addMemberButton, &QPushButton::released, this, &StructEditDialog::OnAddMember);
|
||||
|
||||
QVBoxLayout* arrowLayout = new QVBoxLayout;
|
||||
arrowLayout->addWidget(m_memberMoveUpButton);
|
||||
arrowLayout->addWidget(m_memberMoveDownButton);
|
||||
arrowLayout->addWidget(m_deleteMemberButton);
|
||||
arrowLayout->addWidget(addMemberButton);
|
||||
|
||||
QHBoxLayout* entityListLayout = new QHBoxLayout;
|
||||
entityListLayout->addWidget(m_memberList);
|
||||
entityListLayout->addLayout(arrowLayout);
|
||||
|
||||
QFormLayout* formLayout = new QFormLayout;
|
||||
formLayout->addRow(tr("Name"), m_structName);
|
||||
formLayout->addRow(tr("Members"), entityListLayout);
|
||||
|
||||
QDialogButtonBox* buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
|
||||
connect(buttonBox, &QDialogButtonBox::accepted, this, &StructEditDialog::OnAccept);
|
||||
connect(buttonBox, &QDialogButtonBox::rejected, this, &QDialog::reject);
|
||||
|
||||
QVBoxLayout* verticalLayout = new QVBoxLayout;
|
||||
verticalLayout->addLayout(formLayout);
|
||||
verticalLayout->addWidget(buttonBox);
|
||||
|
||||
setLayout(verticalLayout);
|
||||
}
|
||||
|
||||
StructEditDialog::StructEditDialog(ShaderGraph& graph, const StructInfo& structInfo, QWidget* parent) :
|
||||
StructEditDialog(graph, parent)
|
||||
{
|
||||
m_info = structInfo;
|
||||
|
||||
m_structName->setText(QString::fromStdString(m_info.name));
|
||||
UpdateMemberList();
|
||||
}
|
||||
|
||||
const StructInfo& StructEditDialog::GetStructInfo() const
|
||||
{
|
||||
return m_info;
|
||||
}
|
||||
|
||||
QString StructEditDialog::GetMemberName(const StructInfo::Member& member)
|
||||
{
|
||||
QString name = QString::fromStdString(member.name) + " (";
|
||||
|
||||
std::visit([&](auto&& arg)
|
||||
{
|
||||
using T = std::decay_t<decltype(arg)>;
|
||||
if constexpr (std::is_same_v<T, PrimitiveType>)
|
||||
name += QString(EnumToString(arg));
|
||||
else if constexpr (std::is_same_v<T, std::size_t>)
|
||||
name += QString::fromStdString(m_shaderGraph.GetStruct(arg).name);
|
||||
else
|
||||
static_assert(AlwaysFalse<T>::value, "non-exhaustive visitor");
|
||||
},
|
||||
member.type);
|
||||
|
||||
name += ")";
|
||||
|
||||
return name;
|
||||
}
|
||||
|
||||
void StructEditDialog::OnAccept()
|
||||
{
|
||||
if (m_info.name.empty())
|
||||
{
|
||||
QMessageBox::critical(this, tr("Empty name"), tr("Struct name must be set"), QMessageBox::Ok);
|
||||
return;
|
||||
}
|
||||
|
||||
accept();
|
||||
}
|
||||
|
||||
void StructEditDialog::OnAddMember()
|
||||
{
|
||||
StructMemberEditDialog* dialog = new StructMemberEditDialog(m_shaderGraph, this);
|
||||
dialog->setAttribute(Qt::WA_DeleteOnClose, true);
|
||||
connect(dialog, &QDialog::accepted, [this, dialog]
|
||||
{
|
||||
const StructMemberInfo& structInfo = dialog->GetMemberInfo();
|
||||
|
||||
auto& memberInfo = m_info.members.emplace_back();
|
||||
memberInfo.name = structInfo.name;
|
||||
memberInfo.type = structInfo.type;
|
||||
|
||||
UpdateMemberList(true);
|
||||
});
|
||||
|
||||
dialog->open();
|
||||
}
|
||||
|
||||
void StructEditDialog::OnDeleteMember()
|
||||
{
|
||||
int memberIndex = m_memberList->currentRow();
|
||||
if (memberIndex < 0)
|
||||
return;
|
||||
|
||||
m_info.members.erase(m_info.members.begin() + memberIndex);
|
||||
UpdateMemberList();
|
||||
}
|
||||
|
||||
void StructEditDialog::OnEditMember(int memberIndex)
|
||||
{
|
||||
assert(memberIndex >= 0);
|
||||
|
||||
auto& memberInfo = m_info.members[memberIndex];
|
||||
|
||||
StructMemberInfo info;
|
||||
info.name = memberInfo.name;
|
||||
info.type = memberInfo.type;
|
||||
|
||||
StructMemberEditDialog* dialog = new StructMemberEditDialog(m_shaderGraph, std::move(info), this);
|
||||
dialog->setAttribute(Qt::WA_DeleteOnClose, true);
|
||||
connect(dialog, &QDialog::accepted, [this, dialog, &memberInfo]
|
||||
{
|
||||
const StructMemberInfo& structInfo = dialog->GetMemberInfo();
|
||||
memberInfo.name = structInfo.name;
|
||||
memberInfo.type = structInfo.type;
|
||||
|
||||
UpdateMemberList(true);
|
||||
});
|
||||
|
||||
dialog->open();
|
||||
}
|
||||
|
||||
void StructEditDialog::OnMemberMoveUp()
|
||||
{
|
||||
int memberIndex = m_memberList->currentRow();
|
||||
if (memberIndex <= 0)
|
||||
return;
|
||||
|
||||
std::size_t newMemberIndex = static_cast<std::size_t>(memberIndex - 1);
|
||||
std::swap(m_info.members[memberIndex], m_info.members[newMemberIndex]);
|
||||
UpdateMemberList();
|
||||
|
||||
m_memberList->setCurrentRow(int(newMemberIndex));
|
||||
}
|
||||
|
||||
void StructEditDialog::OnMemberMoveDown()
|
||||
{
|
||||
int memberIndex = m_memberList->currentRow();
|
||||
if (memberIndex < 0 || memberIndex + 1 >= m_memberList->count())
|
||||
return;
|
||||
|
||||
std::size_t newMemberIndex = static_cast<std::size_t>(memberIndex + 1);
|
||||
std::swap(m_info.members[memberIndex], m_info.members[newMemberIndex]);
|
||||
UpdateMemberList();
|
||||
|
||||
m_memberList->setCurrentRow(int(newMemberIndex));
|
||||
}
|
||||
|
||||
void StructEditDialog::OnMemberSelected(int memberIndex)
|
||||
{
|
||||
if (memberIndex >= 0)
|
||||
{
|
||||
m_deleteMemberButton->setEnabled(true);
|
||||
m_memberMoveDownButton->setEnabled(memberIndex + 1 < m_memberList->count());
|
||||
m_memberMoveUpButton->setEnabled(memberIndex != 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_deleteMemberButton->setEnabled(false);
|
||||
m_memberMoveDownButton->setEnabled(false);
|
||||
m_memberMoveUpButton->setEnabled(false);
|
||||
}
|
||||
}
|
||||
|
||||
void StructEditDialog::UpdateMemberList(bool keepSelection)
|
||||
{
|
||||
int selectionIndex = m_memberList->currentRow();
|
||||
|
||||
m_memberList->clear();
|
||||
for (const auto& memberInfo : m_info.members)
|
||||
m_memberList->addItem(GetMemberName(memberInfo));
|
||||
|
||||
if (keepSelection && selectionIndex >= 0 && selectionIndex < m_memberList->count())
|
||||
m_memberList->setCurrentRow(selectionIndex);
|
||||
}
|
||||
|
|
@ -0,0 +1,59 @@
|
|||
#pragma once
|
||||
|
||||
#ifndef NAZARA_SHADERNODES_STRUCTEDITDIALOG_HPP
|
||||
#define NAZARA_SHADERNODES_STRUCTEDITDIALOG_HPP
|
||||
|
||||
#include <ShaderNode/Enums.hpp>
|
||||
#include <QtWidgets/QDialog>
|
||||
#include <variant>
|
||||
#include <vector>
|
||||
|
||||
class QLineEdit;
|
||||
class QListWidget;
|
||||
class QPushButton;
|
||||
class ShaderGraph;
|
||||
|
||||
struct StructInfo
|
||||
{
|
||||
struct Member
|
||||
{
|
||||
std::string name;
|
||||
std::variant<PrimitiveType, std::size_t> type;
|
||||
};
|
||||
|
||||
std::string name;
|
||||
std::vector<Member> members;
|
||||
};
|
||||
|
||||
class StructEditDialog : public QDialog
|
||||
{
|
||||
public:
|
||||
StructEditDialog(ShaderGraph& graph, QWidget* parent = nullptr);
|
||||
StructEditDialog(ShaderGraph& graph, const StructInfo& output, QWidget* parent = nullptr);
|
||||
~StructEditDialog() = default;
|
||||
|
||||
const StructInfo& GetStructInfo() const;
|
||||
|
||||
private:
|
||||
QString GetMemberName(const StructInfo::Member& member);
|
||||
void OnAccept();
|
||||
void OnAddMember();
|
||||
void OnDeleteMember();
|
||||
void OnEditMember(int memberIndex);
|
||||
void OnMemberMoveUp();
|
||||
void OnMemberMoveDown();
|
||||
void OnMemberSelected(int memberIndex);
|
||||
void UpdateMemberList(bool keepSelection = false);
|
||||
|
||||
QLineEdit* m_structName;
|
||||
QListWidget* m_memberList;
|
||||
QPushButton* m_deleteMemberButton;
|
||||
QPushButton* m_memberMoveUpButton;
|
||||
QPushButton* m_memberMoveDownButton;
|
||||
ShaderGraph& m_shaderGraph;
|
||||
StructInfo m_info;
|
||||
};
|
||||
|
||||
#include <ShaderNode/Widgets/StructEditDialog.inl>
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1 @@
|
|||
#include <ShaderNode/Widgets/StructEditDialog.hpp>
|
||||
|
|
@ -0,0 +1,107 @@
|
|||
#include <ShaderNode/Widgets/StructEditor.hpp>
|
||||
#include <ShaderNode/Widgets/StructEditDialog.hpp>
|
||||
#include <ShaderNode/ShaderGraph.hpp>
|
||||
#include <QtWidgets/QFileDialog>
|
||||
#include <QtWidgets/QLabel>
|
||||
#include <QtWidgets/QPushButton>
|
||||
#include <QtWidgets/QListWidget>
|
||||
#include <QtWidgets/QVBoxLayout>
|
||||
|
||||
StructEditor::StructEditor(ShaderGraph& graph) :
|
||||
m_shaderGraph(graph)
|
||||
{
|
||||
m_structList = new QListWidget(this);
|
||||
connect(m_structList, &QListWidget::itemDoubleClicked, [this](QListWidgetItem* item)
|
||||
{
|
||||
OnEditStruct(m_structList->row(item));
|
||||
});
|
||||
|
||||
QPushButton* addStructButton = new QPushButton(tr("Add struct..."));
|
||||
connect(addStructButton, &QPushButton::released, this, &StructEditor::OnAddStruct);
|
||||
|
||||
m_layout = new QVBoxLayout;
|
||||
m_layout->addWidget(m_structList);
|
||||
m_layout->addWidget(addStructButton);
|
||||
|
||||
setLayout(m_layout);
|
||||
|
||||
m_onStructListUpdateSlot.Connect(m_shaderGraph.OnStructListUpdate, this, &StructEditor::OnStructListUpdate);
|
||||
m_onStructUpdateSlot.Connect(m_shaderGraph.OnStructUpdate, this, &StructEditor::OnStructUpdate);
|
||||
|
||||
RefreshStructs();
|
||||
}
|
||||
|
||||
void StructEditor::OnAddStruct()
|
||||
{
|
||||
StructEditDialog* dialog = new StructEditDialog(m_shaderGraph, this);
|
||||
dialog->setAttribute(Qt::WA_DeleteOnClose, true);
|
||||
connect(dialog, &QDialog::accepted, [this, dialog]
|
||||
{
|
||||
const StructInfo& structInfo = dialog->GetStructInfo();
|
||||
|
||||
std::vector<ShaderGraph::StructMemberEntry> members;
|
||||
for (const auto& memberInfo : structInfo.members)
|
||||
{
|
||||
auto& member = members.emplace_back();
|
||||
member.name = memberInfo.name;
|
||||
member.type = memberInfo.type;
|
||||
}
|
||||
|
||||
m_shaderGraph.AddStruct(std::move(structInfo.name), std::move(members));
|
||||
});
|
||||
|
||||
dialog->open();
|
||||
}
|
||||
|
||||
void StructEditor::OnEditStruct(int inputIndex)
|
||||
{
|
||||
const auto& structInfo = m_shaderGraph.GetStruct(inputIndex);
|
||||
|
||||
StructInfo info;
|
||||
info.name = structInfo.name;
|
||||
for (const auto& memberInfo : structInfo.members)
|
||||
{
|
||||
auto& member = info.members.emplace_back();
|
||||
member.name = memberInfo.name;
|
||||
member.type = memberInfo.type;
|
||||
}
|
||||
|
||||
StructEditDialog* dialog = new StructEditDialog(m_shaderGraph, std::move(info), this);
|
||||
dialog->setAttribute(Qt::WA_DeleteOnClose, true);
|
||||
connect(dialog, &QDialog::accepted, [this, dialog, inputIndex]
|
||||
{
|
||||
const StructInfo& structInfo = dialog->GetStructInfo();
|
||||
|
||||
std::vector<ShaderGraph::StructMemberEntry> members;
|
||||
for (const auto& memberInfo : structInfo.members)
|
||||
{
|
||||
auto& member = members.emplace_back();
|
||||
member.name = memberInfo.name;
|
||||
member.type = memberInfo.type;
|
||||
}
|
||||
|
||||
m_shaderGraph.UpdateStruct(inputIndex, std::move(structInfo.name), std::move(members));
|
||||
});
|
||||
|
||||
dialog->open();
|
||||
}
|
||||
|
||||
void StructEditor::OnStructListUpdate(ShaderGraph* /*graph*/)
|
||||
{
|
||||
RefreshStructs();
|
||||
}
|
||||
|
||||
void StructEditor::OnStructUpdate(ShaderGraph* /*graph*/, std::size_t structIndex)
|
||||
{
|
||||
const auto& structEntry = m_shaderGraph.GetStruct(structIndex);
|
||||
m_structList->item(int(structIndex))->setText(QString::fromStdString(structEntry.name));
|
||||
}
|
||||
|
||||
void StructEditor::RefreshStructs()
|
||||
{
|
||||
m_structList->clear();
|
||||
m_structList->setCurrentRow(-1);
|
||||
|
||||
for (const auto& structEntry : m_shaderGraph.GetStructs())
|
||||
m_structList->addItem(QString::fromStdString(structEntry.name));
|
||||
}
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
#pragma once
|
||||
|
||||
#ifndef NAZARA_SHADERNODES_STRUCTEDITOR_HPP
|
||||
#define NAZARA_SHADERNODES_STRUCTEDITOR_HPP
|
||||
|
||||
#include <ShaderNode/ShaderGraph.hpp>
|
||||
#include <QtWidgets/QWidget>
|
||||
#include <optional>
|
||||
|
||||
class QLabel;
|
||||
class QListWidget;
|
||||
class QVBoxLayout;
|
||||
|
||||
class StructEditor : public QWidget
|
||||
{
|
||||
public:
|
||||
StructEditor(ShaderGraph& graph);
|
||||
~StructEditor() = default;
|
||||
|
||||
private:
|
||||
void OnAddStruct();
|
||||
void OnEditStruct(int inputIndex);
|
||||
void OnStructListUpdate(ShaderGraph* graph);
|
||||
void OnStructUpdate(ShaderGraph* graph, std::size_t inputIndex);
|
||||
void RefreshStructs();
|
||||
|
||||
NazaraSlot(ShaderGraph, OnStructListUpdate, m_onStructListUpdateSlot);
|
||||
NazaraSlot(ShaderGraph, OnStructUpdate, m_onStructUpdateSlot);
|
||||
|
||||
ShaderGraph& m_shaderGraph;
|
||||
QListWidget* m_structList;
|
||||
QVBoxLayout* m_layout;
|
||||
};
|
||||
|
||||
#include <ShaderNode/Widgets/StructEditor.inl>
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1 @@
|
|||
#include <ShaderNode/Widgets/StructEditor.hpp>
|
||||
|
|
@ -0,0 +1,86 @@
|
|||
#include <ShaderNode/Widgets/StructMemberEditDialog.hpp>
|
||||
#include <ShaderNode/ShaderGraph.hpp>
|
||||
#include <QtWidgets/QComboBox>
|
||||
#include <QtWidgets/QDialogButtonBox>
|
||||
#include <QtWidgets/QFormLayout>
|
||||
#include <QtWidgets/QLineEdit>
|
||||
#include <QtWidgets/QMessageBox>
|
||||
#include <QtWidgets/QVBoxLayout>
|
||||
|
||||
StructMemberEditDialog::StructMemberEditDialog(const ShaderGraph& shaderGraph, QWidget* parent) :
|
||||
QDialog(parent),
|
||||
m_shaderGraph(shaderGraph)
|
||||
{
|
||||
setWindowTitle(tr("Struct member edit dialog"));
|
||||
setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
|
||||
|
||||
m_memberName = new QLineEdit;
|
||||
|
||||
m_typeList = new QComboBox;
|
||||
for (std::size_t i = 0; i < PrimitiveTypeCount; ++i)
|
||||
m_typeList->addItem(EnumToString(static_cast<PrimitiveType>(i)));
|
||||
|
||||
for (const auto& structInfo : m_shaderGraph.GetStructs())
|
||||
m_typeList->addItem(QString::fromStdString(structInfo.name));
|
||||
|
||||
QFormLayout* formLayout = new QFormLayout;
|
||||
formLayout->addRow(tr("Name"), m_memberName);
|
||||
formLayout->addRow(tr("Type"), m_typeList);
|
||||
|
||||
QDialogButtonBox* buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
|
||||
connect(buttonBox, &QDialogButtonBox::accepted, this, &StructMemberEditDialog::OnAccept);
|
||||
connect(buttonBox, &QDialogButtonBox::rejected, this, &QDialog::reject);
|
||||
|
||||
QVBoxLayout* verticalLayout = new QVBoxLayout;
|
||||
verticalLayout->addLayout(formLayout);
|
||||
verticalLayout->addWidget(buttonBox);
|
||||
|
||||
setLayout(verticalLayout);
|
||||
}
|
||||
|
||||
StructMemberEditDialog::StructMemberEditDialog(const ShaderGraph& shaderGraph, const StructMemberInfo& member, QWidget* parent) :
|
||||
StructMemberEditDialog(shaderGraph, parent)
|
||||
{
|
||||
m_memberName->setText(QString::fromStdString(member.name));
|
||||
std::visit([&](auto&& arg)
|
||||
{
|
||||
using T = std::decay_t<decltype(arg)>;
|
||||
if constexpr (std::is_same_v<T, PrimitiveType>)
|
||||
m_typeList->setCurrentIndex(static_cast<int>(arg));
|
||||
else if constexpr (std::is_same_v<T, std::size_t>)
|
||||
m_typeList->setCurrentIndex(static_cast<int>(PrimitiveTypeCount + arg));
|
||||
else
|
||||
static_assert(AlwaysFalse<T>::value, "non-exhaustive visitor");
|
||||
},
|
||||
member.type);
|
||||
}
|
||||
|
||||
StructMemberInfo StructMemberEditDialog::GetMemberInfo() const
|
||||
{
|
||||
StructMemberInfo inputInfo;
|
||||
inputInfo.name = m_memberName->text().toStdString();
|
||||
|
||||
if (m_typeList->currentIndex() < PrimitiveTypeCount)
|
||||
inputInfo.type = static_cast<PrimitiveType>(m_typeList->currentIndex());
|
||||
else
|
||||
inputInfo.type = static_cast<std::size_t>(m_typeList->currentIndex() - PrimitiveTypeCount);
|
||||
|
||||
return inputInfo;
|
||||
}
|
||||
|
||||
void StructMemberEditDialog::OnAccept()
|
||||
{
|
||||
if (m_memberName->text().isEmpty())
|
||||
{
|
||||
QMessageBox::critical(this, tr("Empty name"), tr("Struct member 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,39 @@
|
|||
#pragma once
|
||||
|
||||
#ifndef NAZARA_SHADERNODES_OUTPUTEDITDIALOG_HPP
|
||||
#define NAZARA_SHADERNODES_OUTPUTEDITDIALOG_HPP
|
||||
|
||||
#include <ShaderNode/Enums.hpp>
|
||||
#include <QtWidgets/QDialog>
|
||||
#include <variant>
|
||||
|
||||
class QComboBox;
|
||||
class QLineEdit;
|
||||
class ShaderGraph;
|
||||
|
||||
struct StructMemberInfo
|
||||
{
|
||||
std::string name;
|
||||
std::variant<PrimitiveType, std::size_t> type;
|
||||
};
|
||||
|
||||
class StructMemberEditDialog : public QDialog
|
||||
{
|
||||
public:
|
||||
StructMemberEditDialog(const ShaderGraph& shaderGraph, QWidget* parent = nullptr);
|
||||
StructMemberEditDialog(const ShaderGraph& shaderGraph, const StructMemberInfo& output, QWidget* parent = nullptr);
|
||||
~StructMemberEditDialog() = default;
|
||||
|
||||
StructMemberInfo GetMemberInfo() const;
|
||||
|
||||
private:
|
||||
void OnAccept();
|
||||
|
||||
const ShaderGraph& m_shaderGraph;
|
||||
QComboBox* m_typeList;
|
||||
QLineEdit* m_memberName;
|
||||
};
|
||||
|
||||
#include <ShaderNode/Widgets/StructMemberEditDialog.inl>
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1 @@
|
|||
#include <ShaderNode/Widgets/StructMemberEditDialog.hpp>
|
||||
Loading…
Reference in New Issue