From 738ed4267397cd3510bbdc1c7f3ec2be186e5da5 Mon Sep 17 00:00:00 2001 From: Timerix22 Date: Thu, 22 Feb 2024 04:44:26 +0600 Subject: [PATCH] NodeEditor class --- .gitignore | 3 +- src/gui/NodeEditor.cpp | 118 +++++++++++++++++++++++++++++++++++++++ src/gui/NodeEditor.hpp | 57 +++++++++++++++++++ src/gui/gui_internal.hpp | 4 -- src/gui/main_window.cpp | 13 ++++- src/gui/node_editor2.cpp | 81 --------------------------- 6 files changed, 187 insertions(+), 89 deletions(-) create mode 100644 src/gui/NodeEditor.cpp create mode 100644 src/gui/NodeEditor.hpp delete mode 100644 src/gui/node_editor2.cpp diff --git a/.gitignore b/.gitignore index 9121301..9dcc8ce 100644 --- a/.gitignore +++ b/.gitignore @@ -15,4 +15,5 @@ libs/ # user files .old*/ current.config -src/generated/ \ No newline at end of file +src/generated/ +imgui.ini diff --git a/src/gui/NodeEditor.cpp b/src/gui/NodeEditor.cpp new file mode 100644 index 0000000..1e0890b --- /dev/null +++ b/src/gui/NodeEditor.cpp @@ -0,0 +1,118 @@ +#include "gui_internal.hpp" +#include +#include "NodeEditor.hpp" + +namespace GraphC::gui { + +NodeAttribute::NodeAttribute(id_t _id, NodeAttributeType _type, std::string _title) + : id(_id), type(_type), title(_title) {} + +NodeAttributeLink::NodeAttributeLink(id_t _id, id_t _in, id_t _out) + : id(_id), in_attr_id(_in), out_attr_id(_out) {} + +Node::Node(id_t _id, std::string _title) + : id(_id), title(_title) {} + +void Node::draw(){ + ImNodes::BeginNode(id); + ImNodes::BeginNodeTitleBar(); + ImGui::TextUnformatted(title.c_str()); + ImNodes::EndNodeTitleBar(); + + for(NodeAttribute& a : attributes) + { + switch (a.type) + { + case NodeAttributeType::Input: + ImNodes::BeginInputAttribute(a.id); + ImGui::Text("%s", a.title.c_str()); + ImNodes::EndInputAttribute(); + break; + case NodeAttributeType::Output: + ImNodes::BeginOutputAttribute(a.id); + ImGui::Text("%s", a.title.c_str()); + ImGui::Indent(40); + ImNodes::EndOutputAttribute(); + break; + case NodeAttributeType::Static: + ImNodes::BeginStaticAttribute(a.id); + ImGui::Text("%s", a.title.c_str()); + ImNodes::EndStaticAttribute(); + break; + default: + throw "Node::draw() invalid type"; + break; + } + } + ImNodes::EndNode(); +} + + +Node CreateExampleNode(id_t* next_id, std::string title){ + Node a = Node((*next_id)++, title); + a.attributes.push_back(NodeAttribute((*next_id)++, NodeAttributeType::Input, "In")); + a.attributes.push_back(NodeAttribute((*next_id)++, NodeAttributeType::Output, "Out")); + a.attributes.push_back(NodeAttribute((*next_id)++, NodeAttributeType::Static, "Static")); + return a; +} + +NodeEditor::NodeEditor(std::string _title) : title(_title) { + nodes.push_back(CreateExampleNode(&next_id, "node A")); + nodes.push_back(CreateExampleNode(&next_id, "node B")); +} + +void NodeEditor::show(){ + editor_open = true; +} + +void NodeEditor::hide(){ + editor_open = false; +} + +void NodeEditor::draw(){ + if(!editor_open) + return; + + ImGui::Begin(title.c_str(), &editor_open); + + ImGui::SetWindowSizeMin(300,300); + ImNodes::BeginNodeEditor(); + // draw nodes + for(Node& n : nodes){ + n.draw(); + } + // draw links + for(const NodeAttributeLink& l : links){ + ImNodes::Link(l.id, l.in_attr_id, l.out_attr_id); + } + ImNodes::EndNodeEditor(); + + // handle link creation + id_t in_attr_id; + id_t out_attr_id; + if (ImNodes::IsLinkCreated(&in_attr_id, &out_attr_id)) + { + kprintf("new link id: %i\n", next_id); + NodeAttributeLink link(next_id++, in_attr_id, out_attr_id); + links.push_back(link); + } + + // handle link destruction + id_t link_id; + if (ImNodes::IsLinkDestroyed(&link_id)) + { + kprintf("link destroyed %i\n", link_id); + auto iter = std::find_if(links.begin(), links.end(), + [link_id](const NodeAttributeLink& link) -> bool { + kprintf("destroyed link found\n"); + return link.id == link_id; + }); + assert(iter != links.end()); + links.erase(iter); + kprintf("destroyed link erased\n"); + } + + ImGui::End(); +} + +} diff --git a/src/gui/NodeEditor.hpp b/src/gui/NodeEditor.hpp new file mode 100644 index 0000000..e75ca10 --- /dev/null +++ b/src/gui/NodeEditor.hpp @@ -0,0 +1,57 @@ +#pragma once + +#include "../../dependencies/imnodes/imnodes.h" +#include +#include + +namespace GraphC::gui { + +typedef i32 id_t; + +enum class NodeAttributeType { + Input, Output, Static +}; + +struct NodeAttribute { + id_t id; + NodeAttributeType type; + std::string title; + + NodeAttribute(id_t _id, NodeAttributeType _type, std::string _title); +}; + +struct Node { + id_t id; + std::string title; + std::vector attributes; + + Node(id_t _id, std::string _title); + + void draw(); +}; + +struct NodeAttributeLink { + id_t id; + id_t in_attr_id; + id_t out_attr_id; + + NodeAttributeLink(id_t _id, id_t _in, id_t _out); +}; + +class NodeEditor { + std::string title=nullptr; + bool editor_open=false; + ImNodesContext* editor_context=nullptr; + id_t next_id=1; + std::vector nodes; + std::vector links; + +public: + NodeEditor(std::string _title); + + void draw(); + void show(); + void hide(); +}; + +} \ No newline at end of file diff --git a/src/gui/gui_internal.hpp b/src/gui/gui_internal.hpp index b45300f..bb4f342 100644 --- a/src/gui/gui_internal.hpp +++ b/src/gui/gui_internal.hpp @@ -43,10 +43,6 @@ void main_window_destroy(); void draw_debug_window(ImGuiIO& io, bool* main_loop_wait_for_input); void draw_bg_window(); -void node_editor_create(const char* title); -void draw_node_editor(); -void node_editor_destroy(); - ////////////////////////////////////// // Macros // ////////////////////////////////////// diff --git a/src/gui/main_window.cpp b/src/gui/main_window.cpp index 7320448..14ac066 100644 --- a/src/gui/main_window.cpp +++ b/src/gui/main_window.cpp @@ -1,4 +1,6 @@ #include "gui_internal.hpp" +#include "NodeEditor.hpp" +using namespace GraphC::gui; #define default_font_name font_DroidSans const f32 default_font_size=14.0f; @@ -7,6 +9,7 @@ bool loop_running=false; SDL_Window* sdl_window; SDL_GLContext gl_context; bool main_loop_wait_for_input=true; +NodeEditor node_editor("new editor"); f32 getMainWindowDPI(){ int w=0, h=0; @@ -75,7 +78,10 @@ Maybe main_window_open(const char* window_title){ io.FontDefault=ImFont_LoadEmbedded(default_font_name, default_font_size); ImFont_LoadEmbedded(font_Cousine_Regular, default_font_size); - node_editor_create("node editor"); + ImNodes::CreateContext(); + ImNodes::StyleColorsDark(); + ImNodes::PushAttributeFlag(ImNodesAttributeFlags_EnableLinkDetachWithDragClick); + node_editor=NodeEditor("node editor"); return MaybeNull; } @@ -119,7 +125,8 @@ Maybe draw_frame(){ // Draw UI draw_bg_window(); draw_debug_window(io, &main_loop_wait_for_input); - draw_node_editor(); + node_editor.show(); + node_editor.draw(); // Rendering ImGui::Render(); @@ -197,7 +204,7 @@ Maybe main_window_close(){ } void main_window_destroy(){ - node_editor_destroy(); + ImNodes::DestroyContext(); ImGui_ImplOpenGL3_Shutdown(); ImGui_ImplSDL2_Shutdown(); ImGui::DestroyContext(); diff --git a/src/gui/node_editor2.cpp b/src/gui/node_editor2.cpp deleted file mode 100644 index 57e4ff8..0000000 --- a/src/gui/node_editor2.cpp +++ /dev/null @@ -1,81 +0,0 @@ -#include "gui_internal.hpp" -#include "../../dependencies/imnodes/imnodes.h" -#include -#include - -struct Link { - int id; - int in_attr_id; - int out_attr_id; -}; - -const char* editor_title=nullptr; -bool editor_open=false; -ImNodesContext* editor_context=nullptr; -int next_id=1; -std::vector links; - -void node_editor_create(const char* title){ - editor_title=title; - editor_open=true; - editor_context=ImNodes::CreateContext(); - ImNodes::StyleColorsDark(); - links=std::vector(); -} - -void node_editor_destroy(){ - editor_open=false; - ImNodes::DestroyContext(editor_context); - links.clear(); -} - -void draw_example_node(const char* node_title){ - ImNodes::BeginNode(next_id++); - ImNodes::BeginNodeTitleBar(); - ImGui::TextUnformatted(node_title); - ImNodes::EndNodeTitleBar(); - ImNodes::BeginInputAttribute(next_id++); - ImGui::Text("input"); - ImNodes::EndInputAttribute(); - ImNodes::BeginOutputAttribute(next_id++); - ImGui::Indent(40); - ImGui::Text("output"); - ImNodes::EndOutputAttribute(); - ImNodes::EndNode(); -} - -void draw_node_editor(){ - if(!editor_open) - return; - next_id=1; - ImGui::Begin(editor_title, &editor_open); - ImGui::SetWindowSizeMin(300,300); - ImNodes::BeginNodeEditor(); - draw_example_node("node A"); - draw_example_node("node B"); - for(const Link& link : links){ - - } - ImNodes::EndNodeEditor(); - - Link link; - if (ImNodes::IsLinkCreated(&link.in_attr_id, &link.out_attr_id)) - { - link.id=next_id++; - links.push_back(link); - } - - - int link_id; - if (ImNodes::IsLinkDestroyed(&link_id)) - { - auto iter = std::find_if(links.begin(), links.end(), - [link_id](const Link& link) -> bool { - return link.id == link_id; - }); - assert(iter != links.end()); - links.erase(iter); - } - - ImGui::End(); -}