NodeEditor class

This commit is contained in:
Timerix22 2024-02-22 04:44:26 +06:00
parent 14c677a0f5
commit 738ed42673
6 changed files with 187 additions and 89 deletions

3
.gitignore vendored
View File

@ -15,4 +15,5 @@ libs/
# user files # user files
.old*/ .old*/
current.config current.config
src/generated/ src/generated/
imgui.ini

118
src/gui/NodeEditor.cpp Normal file
View File

@ -0,0 +1,118 @@
#include "gui_internal.hpp"
#include <algorithm>
#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();
}
}

57
src/gui/NodeEditor.hpp Normal file
View File

@ -0,0 +1,57 @@
#pragma once
#include "../../dependencies/imnodes/imnodes.h"
#include <vector>
#include <string>
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<NodeAttribute> 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<Node> nodes;
std::vector<NodeAttributeLink> links;
public:
NodeEditor(std::string _title);
void draw();
void show();
void hide();
};
}

View File

@ -43,10 +43,6 @@ void main_window_destroy();
void draw_debug_window(ImGuiIO& io, bool* main_loop_wait_for_input); void draw_debug_window(ImGuiIO& io, bool* main_loop_wait_for_input);
void draw_bg_window(); void draw_bg_window();
void node_editor_create(const char* title);
void draw_node_editor();
void node_editor_destroy();
////////////////////////////////////// //////////////////////////////////////
// Macros // // Macros //
////////////////////////////////////// //////////////////////////////////////

View File

@ -1,4 +1,6 @@
#include "gui_internal.hpp" #include "gui_internal.hpp"
#include "NodeEditor.hpp"
using namespace GraphC::gui;
#define default_font_name font_DroidSans #define default_font_name font_DroidSans
const f32 default_font_size=14.0f; const f32 default_font_size=14.0f;
@ -7,6 +9,7 @@ bool loop_running=false;
SDL_Window* sdl_window; SDL_Window* sdl_window;
SDL_GLContext gl_context; SDL_GLContext gl_context;
bool main_loop_wait_for_input=true; bool main_loop_wait_for_input=true;
NodeEditor node_editor("new editor");
f32 getMainWindowDPI(){ f32 getMainWindowDPI(){
int w=0, h=0; 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); io.FontDefault=ImFont_LoadEmbedded(default_font_name, default_font_size);
ImFont_LoadEmbedded(font_Cousine_Regular, 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; return MaybeNull;
} }
@ -119,7 +125,8 @@ Maybe draw_frame(){
// Draw UI // Draw UI
draw_bg_window(); draw_bg_window();
draw_debug_window(io, &main_loop_wait_for_input); draw_debug_window(io, &main_loop_wait_for_input);
draw_node_editor(); node_editor.show();
node_editor.draw();
// Rendering // Rendering
ImGui::Render(); ImGui::Render();
@ -197,7 +204,7 @@ Maybe main_window_close(){
} }
void main_window_destroy(){ void main_window_destroy(){
node_editor_destroy(); ImNodes::DestroyContext();
ImGui_ImplOpenGL3_Shutdown(); ImGui_ImplOpenGL3_Shutdown();
ImGui_ImplSDL2_Shutdown(); ImGui_ImplSDL2_Shutdown();
ImGui::DestroyContext(); ImGui::DestroyContext();

View File

@ -1,81 +0,0 @@
#include "gui_internal.hpp"
#include "../../dependencies/imnodes/imnodes.h"
#include <vector>
#include <algorithm>
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<Link> links;
void node_editor_create(const char* title){
editor_title=title;
editor_open=true;
editor_context=ImNodes::CreateContext();
ImNodes::StyleColorsDark();
links=std::vector<Link>();
}
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();
}