Skip to content

Commit

Permalink
added available nodes to add dialogs functionalities and deleted the …
Browse files Browse the repository at this point in the history
…V layout to switch for a tree layout (the Add Node button is now under the scene tree which is more convenient, yaay)

Signed-off-by: Saif Kandil <74428638+k0T0z@users.noreply.github.com>
  • Loading branch information
k0T0z committed Sep 5, 2024
1 parent f7f3832 commit 06d3ea5
Show file tree
Hide file tree
Showing 2 changed files with 207 additions and 29 deletions.
181 changes: 157 additions & 24 deletions Editors/VisualShaderEditor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@
#include <QtWidgets/QGroupBox>
#include <QtWidgets/QRadioButton>

#include <unordered_map>

#include <QtNodes/GraphicsView>

#include "VisualShader.pb.h"
Expand All @@ -45,12 +47,12 @@ using QtNodes::NodeRole;

VisualShaderEditor::VisualShaderEditor(MessageModel* model, QWidget* parent) : BaseEditor(model, parent),
layout(nullptr),
layers_layout(nullptr),
scene_layer(nullptr),
scene_layer_layout(nullptr),
scene_layer(nullptr),
graph(nullptr),
scene(nullptr),
view(nullptr),
top_layer(nullptr),
menu_bar(nullptr),
create_node_button(nullptr),
preview_shader_button(nullptr),
Expand All @@ -62,12 +64,7 @@ VisualShaderEditor::VisualShaderEditor(MessageModel* model, QWidget* parent) : B
layout->setSpacing(0);
layout->setAlignment(Qt::AlignVCenter | Qt::AlignHCenter);

// Create the layers widget.
layers_layout = new QVBoxLayout();
layers_layout->setContentsMargins(0, 0, 0, 0); // Left, top, right, bottom
layers_layout->setSizeConstraint(QLayout::SetNoConstraint);
layers_layout->setSpacing(2);
layers_layout->setAlignment(Qt::AlignTop | Qt::AlignLeft);
//////////////// End of Header ////////////////

// Create the scene layer.
scene_layer = new QWidget();
Expand Down Expand Up @@ -106,15 +103,15 @@ VisualShaderEditor::VisualShaderEditor(MessageModel* model, QWidget* parent) : B
// Set the scene layer layout.
scene_layer->setLayout(scene_layer_layout);

// Create the menu bar layer.
top_layer = new QWidget();
// Create the menu bar layer on top of the scene layer.
top_layer = new QWidget(view);
top_layer->setContentsMargins(0, 0, 0, 0); // Left, top, right, bottom
top_layer->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);

// Create the menu bar layout.
menu_bar = new QHBoxLayout(top_layer);
menu_bar->setContentsMargins(10, 10, 10, 10); // Left, top, right, bottom
menu_bar->setSpacing(5); // Adjust spacing as needed
menu_bar->setSpacing(5); // Adjust spacing as needed
menu_bar->setAlignment(Qt::AlignTop | Qt::AlignLeft);
menu_bar->setSizeConstraint(QLayout::SetMinimumSize);

Expand All @@ -124,28 +121,68 @@ VisualShaderEditor::VisualShaderEditor(MessageModel* model, QWidget* parent) : B
create_node_button->setContentsMargins(0, 0, 0, 0); // Left, top, right, bottom
menu_bar->addWidget(create_node_button);
QObject::connect(create_node_button, &QPushButton::clicked, this, &VisualShaderEditor::show_create_node_dialog);
create_node_button->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);

// Create the preview shader button.
preview_shader_button = new QPushButton("Preview Shader", top_layer);
preview_shader_button->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
preview_shader_button->setContentsMargins(0, 0, 0, 0); // Left, top, right, bottom
menu_bar->addWidget(preview_shader_button);
preview_shader_button->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);

// Set the top layer layout.
top_layer->setLayout(menu_bar);

// Add the top layer to the layers widget and set it as the current widget.
layers_layout->addWidget(top_layer);

// Add the scene layer to the layers widget.
layers_layout->addWidget(scene_layer);
// Add the scene layer to the main layout.
layout->addWidget(scene_layer);

layout->addLayout(layers_layout);
////////////////////////////////////
// CreateNodeDialog Nodes Tree
////////////////////////////////////

// Create the create node dialog.
// Create the create node dialog under the main layout.
create_node_dialog = new CreateNodeDialog(this);
create_node_dialog->setContentsMargins(0, 0, 0, 0); // Left, top, right, bottom
create_node_dialog->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);

//////////////////////////////////////////
// CreateNodeDialog Nodes Tree Children
//////////////////////////////////////////

const VisualShaderEditor::CreateNodeDialogNodesTreeItem* items {VisualShaderEditor::create_node_dialog_nodes_tree_items};

// Map to store category items
std::unordered_map<std::string, QTreeWidgetItem*> category_path_map;

int i{0};

while (items[i].return_type != VisualShaderNode::PortType::PORT_TYPE_ENUM_SIZE) {
const CreateNodeDialogNodesTreeItem& item {items[i]};

// Parse the category string into a vector of strings
std::vector<std::string> categories {pasre_node_category_path(item.category_path)};
QTreeWidgetItem* parent {nullptr}; // Start from the root

std::string current_category_path;
// Create/find each level of categories
for (const std::string& category : categories) {
if (!current_category_path.empty()) {
current_category_path += "/";
}

current_category_path += category;

parent = find_or_create_category_item(parent, category, current_category_path, create_node_dialog->get_nodes_tree(), category_path_map);
}

// Now add the item to its corresponding parent category
QTreeWidgetItem *node_item = new QTreeWidgetItem(parent);
node_item->setText(0, QString::fromStdString(item.name));

i++;
}

//////////////// Start of Footer ////////////////

graph->set_visual_shader_editor(this);

this->setContentsMargins(0, 0, 0, 0); // Left, top, right, bottom

Expand All @@ -165,12 +202,19 @@ VisualShaderEditor::~VisualShaderEditor() {
if (view) delete view;
if (scene) delete scene;
if (graph) delete graph;
if (scene_layer_layout) delete scene_layer_layout;
if (scene_layer) delete scene_layer;
if (layers_layout) delete layers_layout;
if (scene_layer_layout) delete scene_layer_layout;
if (layout) delete layout;
}

const VisualShaderEditor::CreateNodeDialogNodesTreeItem VisualShaderEditor::create_node_dialog_nodes_tree_items[] = {
{"Color", "Input/All", "VisualShaderNodeInput", "Color", { "color" }, VisualShaderNode::PortType::PORT_TYPE_VECTOR_4D},
{"Time", "Input/All", "VisualShaderNodeInput", "Time", { "time" }, VisualShaderNode::PortType::PORT_TYPE_SCALAR},
{"UV", "Input/All", "VisualShaderNodeInput", "UV", { "uv" }, VisualShaderNode::PortType::PORT_TYPE_VECTOR_2D},

{"", "", "", "", {}, VisualShaderNode::PortType::PORT_TYPE_ENUM_SIZE}, // End of list.
};

void VisualShaderEditor::create_node() {
std::cout << "Creating node" << std::endl;
VisualShaderEditor::add_node();
Expand All @@ -195,38 +239,127 @@ void VisualShaderEditor::show_create_node_dialog(const bool& custom_mouse_pos) {
}
}

std::vector<std::string> VisualShaderEditor::pasre_node_category_path(const std::string& node_category_path) {
std::vector<std::string> tokens;
std::stringstream ss(node_category_path);
std::string token;
while (std::getline(ss, token, '/')) {
tokens.push_back(token);
}
return tokens;
}

QTreeWidgetItem* VisualShaderEditor::find_or_create_category_item(QTreeWidgetItem* parent, const std::string& category, const std::string& category_path, QTreeWidget* create_node_dialog_nodes_tree, std::unordered_map<std::string, QTreeWidgetItem*>& category_path_map) {
// Check if category already exists under parent
if (category_path_map.find(category_path) != category_path_map.end()) {
return category_path_map[category_path];
}

// Create a new QTreeWidgetItem
QTreeWidgetItem* new_item;

if (parent) {
new_item = new QTreeWidgetItem(parent);
} else {
new_item = new QTreeWidgetItem(create_node_dialog_nodes_tree);
}

new_item->setText(0, QString::fromStdString(category));

// Add the new category to the map
category_path_map[category_path] = new_item;

return new_item;
}

/*************************************/
/* CreateNodeDialog */
/*************************************/

CreateNodeDialog::CreateNodeDialog(QWidget* parent) : QDialog(parent),
layout(nullptr),
create_node_dialog_nodes_tree_layout(nullptr),
create_node_dialog_nodes_tree(nullptr),
create_node_dialog_nodes_description(nullptr),
buttons_layout(nullptr),
create_button(nullptr),
cancel_button(nullptr) {
layout = new QVBoxLayout(this);
layout->setContentsMargins(0, 0, 0, 0); // Left, top, right, bottom
layout->setSizeConstraint(QLayout::SetNoConstraint);
layout->setSpacing(0);
layout->setAlignment(Qt::AlignVCenter | Qt::AlignHCenter);

//////////////// End of Header ////////////////

// Create the nodes tree layout.
create_node_dialog_nodes_tree_layout = new QVBoxLayout();
create_node_dialog_nodes_tree_layout->setContentsMargins(0, 0, 0, 0); // Left, top, right, bottom
create_node_dialog_nodes_tree_layout->setSpacing(0); // Adjust spacing as needed
create_node_dialog_nodes_tree_layout->setAlignment(Qt::AlignVCenter | Qt::AlignHCenter);
create_node_dialog_nodes_tree_layout->setSizeConstraint(QLayout::SetMinimumSize);

// Add the nodes tree layout to the main layout.
layout->addLayout(create_node_dialog_nodes_tree_layout);

// Create the nodes tree.
create_node_dialog_nodes_tree = new QTreeWidget();
create_node_dialog_nodes_tree->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
create_node_dialog_nodes_tree->setContentsMargins(0, 0, 0, 0); // Left, top, right, bottom
create_node_dialog_nodes_tree->setColumnCount(1);
create_node_dialog_nodes_tree->setHeaderHidden(true);

// Add the nodes tree to the nodes tree layout.
create_node_dialog_nodes_tree_layout->addWidget(create_node_dialog_nodes_tree, 2); // 2x the size of the nodes description.

// Create the nodes description.
create_node_dialog_nodes_description = new QTextEdit();
create_node_dialog_nodes_description->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
create_node_dialog_nodes_description->setContentsMargins(0, 0, 0, 0); // Left, top, right, bottom
create_node_dialog_nodes_description->setReadOnly(true);
create_node_dialog_nodes_description->setAlignment(Qt::AlignTop | Qt::AlignLeft);

// Add the nodes description to the nodes tree layout.
create_node_dialog_nodes_tree_layout->addWidget(create_node_dialog_nodes_description, 1);

// Create the buttons layout.
buttons_layout = new QHBoxLayout();
layout->setContentsMargins(0, 0, 0, 0); // Left, top, right, bottom
layout->setSizeConstraint(QLayout::SetNoConstraint);
layout->setSpacing(0);
layout->setAlignment(Qt::AlignVCenter | Qt::AlignHCenter);

create_button = new QPushButton("Create", this);
create_button = new QPushButton("Create");
QObject::connect(create_button, &QPushButton::clicked, this, &CreateNodeDialog::on_CreateButtonTriggered);
create_button->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
create_button->setContentsMargins(0, 0, 0, 0); // Left, top, right, bottom

cancel_button = new QPushButton("Cancel", this);
cancel_button = new QPushButton("Cancel");
QObject::connect(cancel_button, &QPushButton::clicked, this, &CreateNodeDialog::on_CancelButtonTriggered);
cancel_button->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
cancel_button->setContentsMargins(0, 0, 0, 0); // Left, top, right, bottom

// Add the buttons to the buttons layout.
buttons_layout->addWidget(create_button);
buttons_layout->addWidget(cancel_button);

// Add the buttons layout to the main layout.
layout->addLayout(buttons_layout);

//////////////// Start of Footer ////////////////

this->setWindowTitle("Create Shader Node");

this->setLayout(layout);
}

CreateNodeDialog::~CreateNodeDialog() {
if (cancel_button) delete cancel_button;
if (create_button) delete create_button;
if (buttons_layout) delete buttons_layout;
if (create_node_dialog_nodes_tree) delete create_node_dialog_nodes_tree;
if (create_node_dialog_nodes_description) delete create_node_dialog_nodes_description;
if (create_node_dialog_nodes_tree_layout) delete create_node_dialog_nodes_tree_layout;
if (layout) delete layout;
}

Expand Down
Loading

0 comments on commit 06d3ea5

Please sign in to comment.