Graphics: rework ubershaders to prevent duplicate shaders modules

Also rename all remaining conditions to options
This commit is contained in:
Jérôme Leclercq
2021-07-08 14:52:39 +02:00
parent 9ab47edd11
commit a895e553d4
38 changed files with 524 additions and 485 deletions

View File

@@ -14,20 +14,20 @@
ConditionalExpression::ConditionalExpression(ShaderGraph& graph) :
ShaderNode(graph)
{
m_onConditionListUpdateSlot.Connect(GetGraph().OnConditionListUpdate, [&](ShaderGraph*) { OnConditionListUpdate(); });
m_onConditionUpdateSlot.Connect(GetGraph().OnConditionUpdate, [&](ShaderGraph*, std::size_t conditionIndex)
m_onOptionListUpdateSlot.Connect(GetGraph().OnOptionListUpdate, [&](ShaderGraph*) { OnOptionListUpdate(); });
m_onOptionUpdateSlot.Connect(GetGraph().OnOptionUpdate, [&](ShaderGraph*, std::size_t optionIndex)
{
if (m_currentConditionIndex == conditionIndex)
if (m_currentOptionIndex == optionIndex)
{
UpdatePreview();
Q_EMIT dataUpdated(0);
}
});
if (graph.GetConditionCount() > 0)
if (graph.GetOptionCount() > 0)
{
m_currentConditionIndex = 0;
UpdateConditionText();
m_currentOptionIndex = 0;
UpdateOptionText();
}
EnablePreview();
@@ -40,18 +40,18 @@ Nz::ShaderAst::NodePtr ConditionalExpression::BuildNode(Nz::ShaderAst::Expressio
assert(count == 2);
assert(outputIndex == 0);
if (!m_currentConditionIndex)
throw std::runtime_error("no condition");
if (!m_currentOptionIndex)
throw std::runtime_error("no option");
const ShaderGraph& graph = GetGraph();
const auto& conditionEntry = graph.GetCondition(*m_currentConditionIndex);
return Nz::ShaderBuilder::ConditionalExpression(Nz::ShaderBuilder::Identifier(conditionEntry.name), std::move(expressions[0]), std::move(expressions[1]));
const auto& optionEntry = graph.GetOption(*m_currentOptionIndex);
return Nz::ShaderBuilder::ConditionalExpression(Nz::ShaderBuilder::Identifier(optionEntry.name), std::move(expressions[0]), std::move(expressions[1]));
}
QString ConditionalExpression::caption() const
{
return "ConditionalExpression (" + QString::fromStdString(m_currentConditionText) + ")";
return "ConditionalExpression (" + QString::fromStdString(m_currentOptionText) + ")";
}
QString ConditionalExpression::name() const
@@ -74,29 +74,29 @@ void ConditionalExpression::BuildNodeEdition(QFormLayout* layout)
{
ShaderNode::BuildNodeEdition(layout);
QComboBox* conditionSelection = new QComboBox;
for (const auto& conditionEntry : GetGraph().GetConditions())
conditionSelection->addItem(QString::fromStdString(conditionEntry.name));
QComboBox* optionSelection = new QComboBox;
for (const auto& optionEntry : GetGraph().GetOptions())
optionSelection->addItem(QString::fromStdString(optionEntry.name));
if (m_currentConditionIndex)
conditionSelection->setCurrentIndex(int(*m_currentConditionIndex));
if (m_currentOptionIndex)
optionSelection->setCurrentIndex(int(*m_currentOptionIndex));
else
conditionSelection->setCurrentIndex(-1);
optionSelection->setCurrentIndex(-1);
connect(conditionSelection, qOverload<int>(&QComboBox::currentIndexChanged), [&](int index)
connect(optionSelection, qOverload<int>(&QComboBox::currentIndexChanged), [&](int index)
{
if (index >= 0)
m_currentConditionIndex = static_cast<std::size_t>(index);
m_currentOptionIndex = static_cast<std::size_t>(index);
else
m_currentConditionIndex.reset();
m_currentOptionIndex.reset();
UpdateConditionText();
UpdateOptionText();
UpdatePreview();
Q_EMIT dataUpdated(0);
});
layout->addRow(tr("Condition"), conditionSelection);
layout->addRow(tr("Option"), optionSelection);
}
auto ConditionalExpression::dataType(QtNodes::PortType portType, QtNodes::PortIndex portIndex) const -> QtNodes::NodeDataType
@@ -178,17 +178,17 @@ bool ConditionalExpression::portCaptionVisible(QtNodes::PortType portType, QtNod
std::shared_ptr<QtNodes::NodeData> ConditionalExpression::outData(QtNodes::PortIndex port)
{
if (!m_currentConditionIndex)
if (!m_currentOptionIndex)
return nullptr;
assert(port == 0);
return (GetGraph().IsConditionEnabled(*m_currentConditionIndex)) ? m_truePath : m_falsePath;
return (GetGraph().IsOptionEnabled(*m_currentOptionIndex)) ? m_truePath : m_falsePath;
}
void ConditionalExpression::restore(const QJsonObject& data)
{
m_currentConditionText = data["condition_name"].toString().toStdString();
OnConditionListUpdate();
m_currentOptionText = data["option_name"].toString().toStdString();
OnOptionListUpdate();
ShaderNode::restore(data);
}
@@ -196,7 +196,7 @@ void ConditionalExpression::restore(const QJsonObject& data)
QJsonObject ConditionalExpression::save() const
{
QJsonObject data = ShaderNode::save();
data["condition_name"] = QString::fromStdString(m_currentConditionText);
data["option_name"] = QString::fromStdString(m_currentOptionText);
return data;
}
@@ -223,8 +223,8 @@ QtNodes::NodeValidationState ConditionalExpression::validationState() const
QString ConditionalExpression::validationMessage() const
{
if (!m_currentConditionIndex)
return "Invalid condition";
if (!m_currentOptionIndex)
return "Invalid option";
if (!m_truePath || !m_falsePath)
return "Missing input";
@@ -234,7 +234,7 @@ QString ConditionalExpression::validationMessage() const
bool ConditionalExpression::ComputePreview(QPixmap& pixmap)
{
if (!m_currentConditionIndex)
if (!m_currentOptionIndex)
return false;
auto input = outData(0);
@@ -248,30 +248,30 @@ bool ConditionalExpression::ComputePreview(QPixmap& pixmap)
return true;
}
void ConditionalExpression::OnConditionListUpdate()
void ConditionalExpression::OnOptionListUpdate()
{
m_currentConditionIndex.reset();
m_currentOptionIndex.reset();
std::size_t conditionIndex = 0;
for (const auto& conditionEntry : GetGraph().GetConditions())
std::size_t optionIndex = 0;
for (const auto& optionEntry : GetGraph().GetOptions())
{
if (conditionEntry.name == m_currentConditionText)
if (optionEntry.name == m_currentOptionText)
{
m_currentConditionIndex = conditionIndex;
m_currentOptionIndex = optionIndex;
break;
}
conditionIndex++;
optionIndex++;
}
}
void ConditionalExpression::UpdateConditionText()
void ConditionalExpression::UpdateOptionText()
{
if (m_currentConditionIndex)
if (m_currentOptionIndex)
{
auto& condition = GetGraph().GetCondition(*m_currentConditionIndex);
m_currentConditionText = condition.name;
auto& option = GetGraph().GetOption(*m_currentOptionIndex);
m_currentOptionText = option.name;
}
else
m_currentConditionText.clear();
m_currentOptionText.clear();
}

View File

@@ -40,16 +40,16 @@ class ConditionalExpression : public ShaderNode
private:
bool ComputePreview(QPixmap& pixmap) override;
void OnConditionListUpdate();
void UpdateConditionText();
void OnOptionListUpdate();
void UpdateOptionText();
NazaraSlot(ShaderGraph, OnConditionListUpdate, m_onConditionListUpdateSlot);
NazaraSlot(ShaderGraph, OnConditionUpdate, m_onConditionUpdateSlot);
NazaraSlot(ShaderGraph, OnOptionListUpdate, m_onOptionListUpdateSlot);
NazaraSlot(ShaderGraph, OnOptionUpdate, m_onOptionUpdateSlot);
std::optional<std::size_t> m_currentConditionIndex;
std::optional<std::size_t> m_currentOptionIndex;
std::shared_ptr<QtNodes::NodeData> m_falsePath;
std::shared_ptr<QtNodes::NodeData> m_truePath;
std::string m_currentConditionText;
std::string m_currentOptionText;
};
#include <ShaderNode/DataModels/BufferField.inl>

View File

@@ -121,13 +121,13 @@ std::size_t ShaderGraph::AddBuffer(std::string name, BufferType bufferType, std:
return index;
}
std::size_t ShaderGraph::AddCondition(std::string name)
std::size_t ShaderGraph::AddOption(std::string name)
{
std::size_t index = m_conditions.size();
auto& conditionEntry = m_conditions.emplace_back();
conditionEntry.name = std::move(name);
std::size_t index = m_options.size();
auto& optionEntry = m_options.emplace_back();
optionEntry.name = std::move(name);
OnConditionListUpdate(this);
OnOptionListUpdate(this);
return index;
}
@@ -194,7 +194,7 @@ void ShaderGraph::Clear()
m_flowScene->clear();
m_buffers.clear();
m_conditions.clear();
m_options.clear();
m_inputs.clear();
m_structs.clear();
m_outputs.clear();
@@ -207,13 +207,13 @@ void ShaderGraph::Clear()
OnTextureListUpdate(this);
}
void ShaderGraph::EnableCondition(std::size_t conditionIndex, bool enable)
void ShaderGraph::EnableOption(std::size_t optionIndex, bool enable)
{
assert(conditionIndex < m_conditions.size());
auto& conditionEntry = m_conditions[conditionIndex];
conditionEntry.enabled = enable;
assert(optionIndex < m_options.size());
auto& optionEntry = m_options[optionIndex];
optionEntry.enabled = enable;
OnConditionUpdate(this, conditionIndex);
OnOptionUpdate(this, optionIndex);
}
void ShaderGraph::Load(const QJsonObject& data)
@@ -238,16 +238,16 @@ void ShaderGraph::Load(const QJsonObject& data)
OnBufferListUpdate(this);
QJsonArray conditionArray = data["conditions"].toArray();
for (const auto& conditionDocRef : conditionArray)
QJsonArray optionArray = data["options"].toArray();
for (const auto& optionDocRef : optionArray)
{
QJsonObject conditionDoc = conditionDocRef.toObject();
QJsonObject optionDoc = optionDocRef.toObject();
ConditionEntry& condition = m_conditions.emplace_back();
condition.name = conditionDoc["name"].toString().toStdString();
OptionEntry& option = m_options.emplace_back();
option.name = optionDoc["name"].toString().toStdString();
}
OnConditionListUpdate(this);
OnOptionListUpdate(this);
QJsonArray inputArray = data["inputs"].toArray();
for (const auto& inputDocRef : inputArray)
@@ -345,17 +345,17 @@ QJsonObject ShaderGraph::Save()
}
sceneJson["buffers"] = bufferArray;
QJsonArray conditionArray;
QJsonArray optionArray;
{
for (const auto& condition : m_conditions)
for (const auto& option : m_options)
{
QJsonObject inputDoc;
inputDoc["name"] = QString::fromStdString(condition.name);
inputDoc["name"] = QString::fromStdString(option.name);
conditionArray.append(inputDoc);
optionArray.append(inputDoc);
}
}
sceneJson["conditions"] = conditionArray;
sceneJson["options"] = optionArray;
QJsonArray inputArray;
{
@@ -462,8 +462,8 @@ Nz::ShaderAst::StatementPtr ShaderGraph::ToAst() const
std::vector<Nz::ShaderAst::StatementPtr> statements;
// Declare all options
for (const auto& condition : m_conditions)
statements.push_back(Nz::ShaderBuilder::DeclareOption(condition.name, Nz::ShaderAst::PrimitiveType::Boolean));
for (const auto& option : m_options)
statements.push_back(Nz::ShaderBuilder::DeclareOption(option.name, Nz::ShaderAst::PrimitiveType::Boolean));
// Declare all structures
for (const auto& structInfo : m_structs)
@@ -590,13 +590,13 @@ void ShaderGraph::UpdateBuffer(std::size_t bufferIndex, std::string name, Buffer
OnBufferUpdate(this, bufferIndex);
}
void ShaderGraph::UpdateCondition(std::size_t conditionIndex, std::string condition)
void ShaderGraph::UpdateOption(std::size_t optionIndex, std::string option)
{
assert(conditionIndex < m_conditions.size());
auto& conditionEntry = m_conditions[conditionIndex];
conditionEntry.name = std::move(condition);
assert(optionIndex < m_options.size());
auto& optionEntry = m_options[optionIndex];
optionEntry.name = std::move(option);
OnConditionUpdate(this, conditionIndex);
OnOptionUpdate(this, optionIndex);
}
void ShaderGraph::UpdateInput(std::size_t inputIndex, std::string name, PrimitiveType type, InputRole role, std::size_t roleIndex, std::size_t locationIndex)

View File

@@ -19,7 +19,7 @@ class ShaderGraph
{
public:
struct BufferEntry;
struct ConditionEntry;
struct OptionEntry;
struct InputEntry;
struct OutputEntry;
struct StructEntry;
@@ -30,7 +30,7 @@ class ShaderGraph
~ShaderGraph();
std::size_t AddBuffer(std::string name, BufferType bufferType, std::size_t structIndex, std::size_t setIndex, std::size_t bindingIndex);
std::size_t AddCondition(std::string name);
std::size_t AddOption(std::string name);
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);
@@ -38,17 +38,17 @@ class ShaderGraph
void Clear();
void EnableCondition(std::size_t conditionIndex, bool enable);
void EnableOption(std::size_t optionIndex, bool enable);
inline const BufferEntry& GetBuffer(std::size_t bufferIndex) const;
inline std::size_t GetBufferCount() const;
inline const std::vector<BufferEntry>& GetBuffers() const;
inline const ConditionEntry& GetCondition(std::size_t conditionIndex) const;
inline std::size_t GetConditionCount() const;
inline const std::vector<ConditionEntry>& GetConditions() 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 OptionEntry& GetOption(std::size_t optionIndex) const;
inline std::size_t GetOptionCount() const;
inline const std::vector<OptionEntry>& GetOptions() const;
inline const OutputEntry& GetOutput(std::size_t outputIndex) const;
inline std::size_t GetOutputCount() const;
inline const std::vector<OutputEntry>& GetOutputs() const;
@@ -62,7 +62,7 @@ class ShaderGraph
inline const std::vector<TextureEntry>& GetTextures() const;
inline ShaderType GetType() const;
inline bool IsConditionEnabled(std::size_t conditionIndex) const;
inline bool IsOptionEnabled(std::size_t optionIndex) const;
void Load(const QJsonObject& data);
QJsonObject Save();
@@ -71,7 +71,7 @@ class ShaderGraph
Nz::ShaderAst::ExpressionType ToShaderExpressionType(const std::variant<PrimitiveType, std::size_t>& type) const;
void UpdateBuffer(std::size_t bufferIndex, std::string name, BufferType bufferType, std::size_t structIndex, std::size_t setIndex, std::size_t bindingIndex);
void UpdateCondition(std::size_t conditionIndex, std::string condition);
void UpdateOption(std::size_t optionIndex, std::string option);
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);
@@ -88,7 +88,7 @@ class ShaderGraph
BufferType type;
};
struct ConditionEntry
struct OptionEntry
{
std::string name;
bool enabled = false;
@@ -133,8 +133,8 @@ class ShaderGraph
NazaraSignal(OnBufferListUpdate, ShaderGraph*);
NazaraSignal(OnBufferUpdate, ShaderGraph*, std::size_t /*bufferIndex*/);
NazaraSignal(OnConditionListUpdate, ShaderGraph*);
NazaraSignal(OnConditionUpdate, ShaderGraph*, std::size_t /*conditionIndex*/);
NazaraSignal(OnOptionListUpdate, ShaderGraph*);
NazaraSignal(OnOptionUpdate, ShaderGraph*, std::size_t /*optionIndex*/);
NazaraSignal(OnInputListUpdate, ShaderGraph*);
NazaraSignal(OnInputUpdate, ShaderGraph*, std::size_t /*inputIndex*/);
NazaraSignal(OnOutputListUpdate, ShaderGraph*);
@@ -158,7 +158,7 @@ class ShaderGraph
mutable std::optional<QtNodes::FlowScene> m_flowScene;
std::vector<BufferEntry> m_buffers;
std::vector<ConditionEntry> m_conditions;
std::vector<OptionEntry> m_options;
std::vector<InputEntry> m_inputs;
std::vector<OutputEntry> m_outputs;
std::vector<StructEntry> m_structs;

View File

@@ -16,22 +16,6 @@ inline auto ShaderGraph::GetBuffers() const -> const std::vector<BufferEntry>&
return m_buffers;
}
inline auto ShaderGraph::GetCondition(std::size_t conditionIndex) const -> const ConditionEntry&
{
assert(conditionIndex < m_conditions.size());
return m_conditions[conditionIndex];
}
inline std::size_t ShaderGraph::GetConditionCount() const
{
return m_conditions.size();
}
inline auto ShaderGraph::GetConditions() const -> const std::vector<ConditionEntry>&
{
return m_conditions;
}
inline auto ShaderGraph::GetInput(std::size_t inputIndex) const -> const InputEntry&
{
assert(inputIndex < m_inputs.size());
@@ -48,6 +32,22 @@ inline auto ShaderGraph::GetInputs() const -> const std::vector<InputEntry>&
return m_inputs;
}
inline auto ShaderGraph::GetOption(std::size_t optionIndex) const -> const OptionEntry&
{
assert(optionIndex < m_options.size());
return m_options[optionIndex];
}
inline std::size_t ShaderGraph::GetOptionCount() const
{
return m_options.size();
}
inline auto ShaderGraph::GetOptions() const -> const std::vector<OptionEntry>&
{
return m_options;
}
inline auto ShaderGraph::GetOutput(std::size_t outputIndex) const -> const OutputEntry&
{
assert(outputIndex < m_outputs.size());
@@ -111,9 +111,9 @@ inline ShaderType ShaderGraph::GetType() const
return m_type;
}
inline bool ShaderGraph::IsConditionEnabled(std::size_t conditionIndex) const
inline bool ShaderGraph::IsOptionEnabled(std::size_t optionIndex) const
{
assert(conditionIndex < m_conditions.size());
return m_conditions[conditionIndex].enabled;
assert(optionIndex < m_options.size());
return m_options[optionIndex].enabled;
}

View File

@@ -55,11 +55,11 @@ void CodeOutputWidget::Refresh()
{
try
{
Nz::UInt64 enabledConditions = 0;
for (std::size_t i = 0; i < m_shaderGraph.GetConditionCount(); ++i)
Nz::UInt64 enabledOptions = 0;
for (std::size_t i = 0; i < m_shaderGraph.GetOptionCount(); ++i)
{
if (m_shaderGraph.IsConditionEnabled(i))
enabledConditions = Nz::SetBit<Nz::UInt64>(enabledConditions, i);
if (m_shaderGraph.IsOptionEnabled(i))
enabledOptions = Nz::SetBit<Nz::UInt64>(enabledOptions, i);
}
Nz::ShaderAst::StatementPtr shaderAst = m_shaderGraph.ToAst();
@@ -69,14 +69,14 @@ void CodeOutputWidget::Refresh()
shaderAst = Nz::ShaderAst::Sanitize(*shaderAst);
Nz::ShaderAst::AstOptimizer::Options optimOptions;
optimOptions.enabledOptions = enabledConditions;
optimOptions.enabledOptions = enabledOptions;
Nz::ShaderAst::AstOptimizer optimiser;
shaderAst = optimiser.Optimise(*shaderAst, optimOptions);
}
Nz::ShaderWriter::States states;
states.enabledOptions = enabledConditions;
states.enabledOptions = enabledOptions;
std::string output;
OutputLanguage outputLang = static_cast<OutputLanguage>(m_outputLang->currentIndex());

View File

@@ -1,55 +0,0 @@
#include <ShaderNode/Widgets/ConditionEditDialog.hpp>
#include <QtWidgets/QComboBox>
#include <QtWidgets/QDialogButtonBox>
#include <QtWidgets/QFormLayout>
#include <QtWidgets/QLineEdit>
#include <QtWidgets/QMessageBox>
#include <QtWidgets/QSpinBox>
#include <QtWidgets/QVBoxLayout>
ConditionEditDialog::ConditionEditDialog(QWidget* parent) :
QDialog(parent)
{
setWindowTitle(tr("Condition edit dialog"));
setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
m_conditionName = new QLineEdit;
QFormLayout* formLayout = new QFormLayout;
formLayout->addRow(tr("Name"), m_conditionName);
QDialogButtonBox* buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
connect(buttonBox, &QDialogButtonBox::accepted, this, &ConditionEditDialog::OnAccept);
connect(buttonBox, &QDialogButtonBox::rejected, this, &QDialog::reject);
QVBoxLayout* verticalLayout = new QVBoxLayout;
verticalLayout->addLayout(formLayout);
verticalLayout->addWidget(buttonBox);
setLayout(verticalLayout);
}
ConditionEditDialog::ConditionEditDialog(const ConditionInfo& condition, QWidget* parent) :
ConditionEditDialog(parent)
{
m_conditionName->setText(QString::fromStdString(condition.name));
}
ConditionInfo ConditionEditDialog::GetConditionInfo() const
{
ConditionInfo inputInfo;
inputInfo.name = m_conditionName->text().toStdString();
return inputInfo;
}
void ConditionEditDialog::OnAccept()
{
if (m_conditionName->text().isEmpty())
{
QMessageBox::critical(this, tr("Empty name"), tr("Condition name must be set"), QMessageBox::Ok);
return;
}
accept();
}

View File

@@ -1,35 +0,0 @@
#pragma once
#ifndef NAZARA_SHADERNODES_CONDITIONEDITDIALOG_HPP
#define NAZARA_SHADERNODES_CONDITIONEDITDIALOG_HPP
#include <ShaderNode/Enums.hpp>
#include <QtWidgets/QDialog>
class QComboBox;
class QLineEdit;
class QSpinBox;
struct ConditionInfo
{
std::string name;
};
class ConditionEditDialog : public QDialog
{
public:
ConditionEditDialog(QWidget* parent = nullptr);
ConditionEditDialog(const ConditionInfo& input, QWidget* parent = nullptr);
~ConditionEditDialog() = default;
ConditionInfo GetConditionInfo() const;
private:
void OnAccept();
QLineEdit* m_conditionName;
};
#include <ShaderNode/Widgets/ConditionEditDialog.inl>
#endif

View File

@@ -1 +0,0 @@
#include <ShaderNode/Widgets/ConditionEditDialog.hpp>

View File

@@ -1,119 +0,0 @@
#include <ShaderNode/Widgets/ConditionEditor.hpp>
#include <ShaderNode/Widgets/ConditionEditDialog.hpp>
#include <ShaderNode/ShaderGraph.hpp>
#include <QtGui/QStandardItemModel>
#include <QtWidgets/QLabel>
#include <QtWidgets/QPushButton>
#include <QtWidgets/QListWidget>
#include <QtWidgets/QTableView>
#include <QtWidgets/QVBoxLayout>
ConditionEditor::ConditionEditor(ShaderGraph& graph) :
m_shaderGraph(graph)
{
QTableView* tableView = new QTableView;
m_model = new QStandardItemModel(0, 2, tableView);
tableView->setModel(m_model);
m_model->setHorizontalHeaderLabels({ tr("Condition"), tr("Enabled") });
connect(tableView, &QTableView::doubleClicked, [this](const QModelIndex& index)
{
if (index.column() == 0)
OnEditCondition(index.row());
});
connect(m_model, &QStandardItemModel::itemChanged, [this](QStandardItem* item)
{
if (item->column() == 1)
{
std::size_t conditionIndex = static_cast<std::size_t>(item->row());
bool value = item->checkState() == Qt::Checked;
m_shaderGraph.EnableCondition(conditionIndex, value);
}
});
QPushButton* addStructButton = new QPushButton(tr("Add condition..."));
connect(addStructButton, &QPushButton::released, this, &ConditionEditor::OnAddCondition);
m_layout = new QVBoxLayout;
m_layout->addWidget(tableView);
m_layout->addWidget(addStructButton);
setLayout(m_layout);
m_onConditionListUpdateSlot.Connect(m_shaderGraph.OnConditionListUpdate, this, &ConditionEditor::OnConditionListUpdate);
m_onConditionUpdateSlot.Connect(m_shaderGraph.OnConditionUpdate, this, &ConditionEditor::OnConditionUpdate);
RefreshConditions();
}
void ConditionEditor::OnAddCondition()
{
ConditionEditDialog* dialog = new ConditionEditDialog(this);
dialog->setAttribute(Qt::WA_DeleteOnClose, true);
connect(dialog, &QDialog::accepted, [this, dialog]
{
ConditionInfo conditionInfo = dialog->GetConditionInfo();
m_shaderGraph.AddCondition(std::move(conditionInfo.name));
});
dialog->open();
}
void ConditionEditor::OnEditCondition(int conditionIndex)
{
const auto& conditionInfo = m_shaderGraph.GetCondition(conditionIndex);
ConditionInfo info;
info.name = conditionInfo.name;
ConditionEditDialog* dialog = new ConditionEditDialog(info, this);
dialog->setAttribute(Qt::WA_DeleteOnClose, true);
connect(dialog, &QDialog::accepted, [this, dialog, conditionIndex]
{
ConditionInfo conditionInfo = dialog->GetConditionInfo();
m_shaderGraph.UpdateCondition(conditionIndex, std::move(conditionInfo.name));
});
dialog->open();
}
void ConditionEditor::OnConditionListUpdate(ShaderGraph* /*graph*/)
{
RefreshConditions();
}
void ConditionEditor::OnConditionUpdate(ShaderGraph* /*graph*/, std::size_t conditionIndex)
{
const auto& conditionEntry = m_shaderGraph.GetCondition(conditionIndex);
int row = int(conditionIndex);
m_model->item(row, 0)->setText(QString::fromStdString(conditionEntry.name));
m_model->item(row, 1)->setCheckState((conditionEntry.enabled) ? Qt::CheckState::Checked : Qt::CheckState::Unchecked);
}
void ConditionEditor::RefreshConditions()
{
m_model->setRowCount(int(m_shaderGraph.GetConditionCount()));
int rowIndex = 0;
for (const auto& conditionEntry : m_shaderGraph.GetConditions())
{
QStandardItem* label = new QStandardItem(1);
label->setEditable(false);
label->setText(QString::fromStdString(conditionEntry.name));
m_model->setItem(rowIndex, 0, label);
QStandardItem* checkbox = new QStandardItem(1);
checkbox->setCheckable(true);
checkbox->setCheckState((conditionEntry.enabled) ? Qt::CheckState::Checked : Qt::CheckState::Unchecked);
m_model->setItem(rowIndex, 1, checkbox);
rowIndex++;
}

View File

@@ -1,36 +0,0 @@
#pragma once
#ifndef NAZARA_SHADERNODES_CONDITIONEDITOR_HPP
#define NAZARA_SHADERNODES_CONDITIONEDITOR_HPP
#include <ShaderNode/ShaderGraph.hpp>
#include <QtWidgets/QWidget>
#include <optional>
class QStandardItemModel;
class QVBoxLayout;
class ConditionEditor : public QWidget
{
public:
ConditionEditor(ShaderGraph& graph);
~ConditionEditor() = default;
private:
void OnAddCondition();
void OnConditionListUpdate(ShaderGraph* graph);
void OnConditionUpdate(ShaderGraph* graph, std::size_t conditionIndex);
void OnEditCondition(int inputIndex);
void RefreshConditions();
NazaraSlot(ShaderGraph, OnStructListUpdate, m_onConditionListUpdateSlot);
NazaraSlot(ShaderGraph, OnStructUpdate, m_onConditionUpdateSlot);
ShaderGraph& m_shaderGraph;
QStandardItemModel* m_model;
QVBoxLayout* m_layout;
};
#include <ShaderNode/Widgets/ConditionEditor.inl>
#endif

View File

@@ -1 +0,0 @@
#include <ShaderNode/Widgets/ConditionEditor.hpp>

View File

@@ -5,7 +5,7 @@
#include <ShaderNode/ShaderGraph.hpp>
#include <ShaderNode/Widgets/BufferEditor.hpp>
#include <ShaderNode/Widgets/CodeOutputWidget.hpp>
#include <ShaderNode/Widgets/ConditionEditor.hpp>
#include <ShaderNode/Widgets/OptionEditor.hpp>
#include <ShaderNode/Widgets/InputEditor.hpp>
#include <ShaderNode/Widgets/OutputEditor.hpp>
#include <ShaderNode/Widgets/NodeEditor.hpp>
@@ -81,13 +81,13 @@ m_shaderGraph(graph)
addDockWidget(Qt::RightDockWidgetArea, structDock);
// Condition editor
ConditionEditor* conditionEditor = new ConditionEditor(m_shaderGraph);
// Option editor
OptionEditor* optionEditor = new OptionEditor(m_shaderGraph);
QDockWidget* conditionDock = new QDockWidget(tr("Conditions"));
conditionDock->setWidget(conditionEditor);
QDockWidget* optionDock = new QDockWidget(tr("Options"));
optionDock->setWidget(optionEditor);
addDockWidget(Qt::RightDockWidgetArea, conditionDock);
addDockWidget(Qt::RightDockWidgetArea, optionDock);
// Code output
CodeOutputWidget* codeOutput = new CodeOutputWidget(m_shaderGraph);
@@ -120,7 +120,7 @@ m_shaderGraph(graph)
view->addAction(nodeEditorDock->toggleViewAction());
view->addAction(bufferDock->toggleViewAction());
view->addAction(structDock->toggleViewAction());
view->addAction(conditionDock->toggleViewAction());
view->addAction(optionDock->toggleViewAction());
view->addAction(codeOutputDock->toggleViewAction());
}
@@ -142,7 +142,7 @@ m_shaderGraph(graph)
});
});
m_onConditionUpdate.Connect(m_shaderGraph.OnConditionUpdate, [=](ShaderGraph*, std::size_t /*conditionIndex*/)
m_onOptionUpdate.Connect(m_shaderGraph.OnOptionUpdate, [=](ShaderGraph*, std::size_t /*optionIndex*/)
{
if (codeOutput->isVisible())
codeOutput->Refresh();

View File

@@ -22,7 +22,7 @@ class MainWindow : public QMainWindow
void OnSave();
void OnUpdateInfo();
NazaraSlot(ShaderGraph, OnConditionUpdate, m_onConditionUpdate);
NazaraSlot(ShaderGraph, OnOptionUpdate, m_onOptionUpdate);
NazaraSlot(ShaderGraph, OnSelectedNodeUpdate, m_onSelectedNodeUpdate);
NodeEditor* m_nodeEditor;

View File

@@ -0,0 +1,55 @@
#include <ShaderNode/Widgets/OptionEditDialog.hpp>
#include <QtWidgets/QComboBox>
#include <QtWidgets/QDialogButtonBox>
#include <QtWidgets/QFormLayout>
#include <QtWidgets/QLineEdit>
#include <QtWidgets/QMessageBox>
#include <QtWidgets/QSpinBox>
#include <QtWidgets/QVBoxLayout>
OptionEditDialog::OptionEditDialog(QWidget* parent) :
QDialog(parent)
{
setWindowTitle(tr("Option edit dialog"));
setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
m_optionName = new QLineEdit;
QFormLayout* formLayout = new QFormLayout;
formLayout->addRow(tr("Name"), m_optionName);
QDialogButtonBox* buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
connect(buttonBox, &QDialogButtonBox::accepted, this, &OptionEditDialog::OnAccept);
connect(buttonBox, &QDialogButtonBox::rejected, this, &QDialog::reject);
QVBoxLayout* verticalLayout = new QVBoxLayout;
verticalLayout->addLayout(formLayout);
verticalLayout->addWidget(buttonBox);
setLayout(verticalLayout);
}
OptionEditDialog::OptionEditDialog(const OptionInfo& option, QWidget* parent) :
OptionEditDialog(parent)
{
m_optionName->setText(QString::fromStdString(option.name));
}
OptionInfo OptionEditDialog::GetOptionInfo() const
{
OptionInfo inputInfo;
inputInfo.name = m_optionName->text().toStdString();
return inputInfo;
}
void OptionEditDialog::OnAccept()
{
if (m_optionName->text().isEmpty())
{
QMessageBox::critical(this, tr("Empty name"), tr("Option name must be set"), QMessageBox::Ok);
return;
}
accept();
}

View File

@@ -0,0 +1,35 @@
#pragma once
#ifndef NAZARA_SHADERNODES_OPTIONEDITDIALOG_HPP
#define NAZARA_SHADERNODES_OPTIONEDITDIALOG_HPP
#include <ShaderNode/Enums.hpp>
#include <QtWidgets/QDialog>
class QComboBox;
class QLineEdit;
class QSpinBox;
struct OptionInfo
{
std::string name;
};
class OptionEditDialog : public QDialog
{
public:
OptionEditDialog(QWidget* parent = nullptr);
OptionEditDialog(const OptionInfo& input, QWidget* parent = nullptr);
~OptionEditDialog() = default;
OptionInfo GetOptionInfo() const;
private:
void OnAccept();
QLineEdit* m_optionName;
};
#include <ShaderNode/Widgets/OptionEditDialog.inl>
#endif

View File

@@ -0,0 +1 @@
#include <ShaderNode/Widgets/OptionEditDialog.hpp>

View File

@@ -0,0 +1,119 @@
#include <ShaderNode/Widgets/OptionEditor.hpp>
#include <ShaderNode/Widgets/OptionEditDialog.hpp>
#include <ShaderNode/ShaderGraph.hpp>
#include <QtGui/QStandardItemModel>
#include <QtWidgets/QLabel>
#include <QtWidgets/QPushButton>
#include <QtWidgets/QListWidget>
#include <QtWidgets/QTableView>
#include <QtWidgets/QVBoxLayout>
OptionEditor::OptionEditor(ShaderGraph& graph) :
m_shaderGraph(graph)
{
QTableView* tableView = new QTableView;
m_model = new QStandardItemModel(0, 2, tableView);
tableView->setModel(m_model);
m_model->setHorizontalHeaderLabels({ tr("Option"), tr("Enabled") });
connect(tableView, &QTableView::doubleClicked, [this](const QModelIndex& index)
{
if (index.column() == 0)
OnEditOption(index.row());
});
connect(m_model, &QStandardItemModel::itemChanged, [this](QStandardItem* item)
{
if (item->column() == 1)
{
std::size_t optionIndex = static_cast<std::size_t>(item->row());
bool value = item->checkState() == Qt::Checked;
m_shaderGraph.EnableOption(optionIndex, value);
}
});
QPushButton* addStructButton = new QPushButton(tr("Add option..."));
connect(addStructButton, &QPushButton::released, this, &OptionEditor::OnAddOption);
m_layout = new QVBoxLayout;
m_layout->addWidget(tableView);
m_layout->addWidget(addStructButton);
setLayout(m_layout);
m_onOptionListUpdateSlot.Connect(m_shaderGraph.OnOptionListUpdate, this, &OptionEditor::OnOptionListUpdate);
m_onOptionUpdateSlot.Connect(m_shaderGraph.OnOptionUpdate, this, &OptionEditor::OnOptionUpdate);
RefreshOptions();
}
void OptionEditor::OnAddOption()
{
OptionEditDialog* dialog = new OptionEditDialog(this);
dialog->setAttribute(Qt::WA_DeleteOnClose, true);
connect(dialog, &QDialog::accepted, [this, dialog]
{
OptionInfo optionInfo = dialog->GetOptionInfo();
m_shaderGraph.AddOption(std::move(optionInfo.name));
});
dialog->open();
}
void OptionEditor::OnEditOption(int optionIndex)
{
const auto& optionInfo = m_shaderGraph.GetOption(optionIndex);
OptionInfo info;
info.name = optionInfo.name;
OptionEditDialog* dialog = new OptionEditDialog(info, this);
dialog->setAttribute(Qt::WA_DeleteOnClose, true);
connect(dialog, &QDialog::accepted, [this, dialog, optionIndex]
{
OptionInfo optionInfo = dialog->GetOptionInfo();
m_shaderGraph.UpdateOption(optionIndex, std::move(optionInfo.name));
});
dialog->open();
}
void OptionEditor::OnOptionListUpdate(ShaderGraph* /*graph*/)
{
RefreshOptions();
}
void OptionEditor::OnOptionUpdate(ShaderGraph* /*graph*/, std::size_t optionIndex)
{
const auto& optionEntry = m_shaderGraph.GetOption(optionIndex);
int row = int(optionIndex);
m_model->item(row, 0)->setText(QString::fromStdString(optionEntry.name));
m_model->item(row, 1)->setCheckState((optionEntry.enabled) ? Qt::CheckState::Checked : Qt::CheckState::Unchecked);
}
void OptionEditor::RefreshOptions()
{
m_model->setRowCount(int(m_shaderGraph.GetOptionCount()));
int rowIndex = 0;
for (const auto& optionEntry : m_shaderGraph.GetOptions())
{
QStandardItem* label = new QStandardItem(1);
label->setEditable(false);
label->setText(QString::fromStdString(optionEntry.name));
m_model->setItem(rowIndex, 0, label);
QStandardItem* checkbox = new QStandardItem(1);
checkbox->setCheckable(true);
checkbox->setCheckState((optionEntry.enabled) ? Qt::CheckState::Checked : Qt::CheckState::Unchecked);
m_model->setItem(rowIndex, 1, checkbox);
rowIndex++;
}

View File

@@ -0,0 +1,36 @@
#pragma once
#ifndef NAZARA_SHADERNODES_OPTIONEDITOR_HPP
#define NAZARA_SHADERNODES_OPTIONEDITOR_HPP
#include <ShaderNode/ShaderGraph.hpp>
#include <QtWidgets/QWidget>
#include <optional>
class QStandardItemModel;
class QVBoxLayout;
class OptionEditor : public QWidget
{
public:
OptionEditor(ShaderGraph& graph);
~OptionEditor() = default;
private:
void OnAddOption();
void OnOptionListUpdate(ShaderGraph* graph);
void OnOptionUpdate(ShaderGraph* graph, std::size_t optionIndex);
void OnEditOption(int optionIndex);
void RefreshOptions();
NazaraSlot(ShaderGraph, OnStructListUpdate, m_onOptionListUpdateSlot);
NazaraSlot(ShaderGraph, OnStructUpdate, m_onOptionUpdateSlot);
ShaderGraph& m_shaderGraph;
QStandardItemModel* m_model;
QVBoxLayout* m_layout;
};
#include <ShaderNode/Widgets/OptionEditor.inl>
#endif

View File

@@ -0,0 +1 @@
#include <ShaderNode/Widgets/OptionEditor.hpp>