diff --git a/.gitmodules b/.gitmodules index 140dde4..9577c44 100644 --- a/.gitmodules +++ b/.gitmodules @@ -16,3 +16,7 @@ path = imgui-node-editor url = https://github.com/Timerix22/imgui-node-editor.git branch = develop_cbuild +[submodule "imnodes"] + path = imnodes + url = https://github.com/Timerix22/imnodes + branch = master_cbuild diff --git a/Makefile b/Makefile index 49a8b38..9da40d9 100644 --- a/Makefile +++ b/Makefile @@ -2,9 +2,7 @@ ###### Build tasks ####### ###################################### -all: build_exec_dbg - -rebuild_all: rebuild_kerep rebuild_imgui rebuild_imgui_node_editor embed_fonts +default: build_exec_dbg # creates executable using profile info generated by profile build_exec: rebuild_all # profile @@ -64,16 +62,20 @@ fix_log: # recompile kerep.a in the next build task rebuild_kerep: - @cbuild/call_task.sh rebuild_kerep + @tasks/rebuild_lib.sh kerep # recompile imgui.a in the next build task rebuild_imgui: - @cbuild/call_task.sh rebuild_imgui + @tasks/rebuild_lib.sh imgui -rebuild_imgui_node_editor: - @cbuild/call_task.sh rebuild_imgui_node_editor +rebuild_imgui-node-editor: + @tasks/rebuild_lib.sh imgui-node-editor +rebuild_imnodes: + @tasks/rebuild_lib.sh imnodes # writes ttf fonts fron ./fonts/ to C compressed arrays in C source files # builds static library from font arrays definitions embed_fonts: @cbuild/call_task.sh embed_fonts + +rebuild_all: rebuild_kerep rebuild_imgui rebuild_imgui-node-editor rebuild_imnodes embed_fonts diff --git a/default.config b/default.config index 89d7de4..6d829ca 100644 --- a/default.config +++ b/default.config @@ -41,16 +41,6 @@ esac # TASKS case "$TASK" in - rebuild_kerep) - TASK_SCRIPT=tasks/rebuild_kerep.sh - ;; - rebuild_imgui) - TASK_SCRIPT=tasks/rebuild_imgui.sh - ;; - rebuild_imgui_node_editor) - TASK_SCRIPT=tasks/rebuild_imgui-node-editor.sh - ;; - # writes ttf fonts fron ./fonts/ to C compressed arrays in C source files # builds static library from font arrays definitions embed_fonts) @@ -74,7 +64,7 @@ case "$TASK" in LINKER_ARGS="$CPP_ARGS $LINKER_LIBS" PRE_TASK_SCRIPT=tasks/pre_build.sh TASK_SCRIPT=cbuild/default_tasks/build_exec.sh - KEREP_BUILD_TASK=build_static_lib + DEPS_BUILD_TASK=build_static_lib ;; # creates executable with debug info and no optimizations build_exec_dbg) @@ -83,7 +73,7 @@ case "$TASK" in LINKER_ARGS="$CPP_ARGS $LINKER_LIBS" PRE_TASK_SCRIPT=tasks/pre_build.sh TASK_SCRIPT=cbuild/default_tasks/build_exec.sh - KEREP_BUILD_TASK=build_static_lib_dbg + DEPS_BUILD_TASK=build_static_lib_dbg ;; # executes $EXEC_FILE exec) @@ -109,7 +99,7 @@ case "$TASK" in PRE_TASK_SCRIPT=tasks/pre_build.sh TASK_SCRIPT=cbuild/default_tasks/build_exec.sh POST_TASK_SCRIPT=cbuild/default_tasks/profile.sh - KEREP_BUILD_TASK=build_static_lib + DEPS_BUILD_TASK=build_static_lib ;; # compiles program with -pg and runs it with gprof # uses gprof2dot python script to generate function call tree (pip install gprof2dot) @@ -123,7 +113,7 @@ case "$TASK" in PRE_TASK_SCRIPT=tasks/pre_build.sh TASK_SCRIPT=cbuild/default_tasks/build_exec.sh POST_TASK_SCRIPT=cbuild/default_tasks/gprof.sh - KEREP_BUILD_TASK=build_static_lib + DEPS_BUILD_TASK=build_static_lib ;; # compiles executable with sanitizers and executes it to find errors and warnings sanitize) @@ -134,7 +124,7 @@ case "$TASK" in PRE_TASK_SCRIPT=tasks/pre_build.sh TASK_SCRIPT=cbuild/default_tasks/build_exec.sh POST_TASK_SCRIPT=cbuild/default_tasks/exec.sh - KEREP_BUILD_TASK=build_static_lib + DEPS_BUILD_TASK=build_static_lib ;; # deletes generated files clean) diff --git a/imnodes b/imnodes new file mode 160000 index 0000000..3dbb910 --- /dev/null +++ b/imnodes @@ -0,0 +1 @@ +Subproject commit 3dbb9105083a9b8dc48bec020198050dba81a4e1 diff --git a/src/gui/gui_internal.hpp b/src/gui/gui_internal.hpp index 8793b5b..01078b3 100644 --- a/src/gui/gui_internal.hpp +++ b/src/gui/gui_internal.hpp @@ -43,9 +43,9 @@ void main_window_destroy(); void draw_debug_window(ImGuiIO& io, bool* main_loop_wait_for_input); void draw_bg_window(); -void node_editor_open(const char* title); +void node_editor_create(const char* title); void draw_node_editor(); -void node_editor_close(); +void node_editor_destroy(); ////////////////////////////////////// // Macros // diff --git a/src/gui/main_window.cpp b/src/gui/main_window.cpp index 2a17c4c..03b30ba 100644 --- a/src/gui/main_window.cpp +++ b/src/gui/main_window.cpp @@ -72,7 +72,7 @@ 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_open("node editor"); + node_editor_create("node editor"); return MaybeNull; } @@ -194,7 +194,7 @@ Maybe main_window_close(){ } void main_window_destroy(){ - node_editor_close(); + node_editor_destroy(); ImGui_ImplOpenGL3_Shutdown(); ImGui_ImplSDL2_Shutdown(); ImGui::DestroyContext(); diff --git a/src/gui/node_editor.cpp b/src/gui/node_editor.cpp deleted file mode 100644 index 7c68678..0000000 --- a/src/gui/node_editor.cpp +++ /dev/null @@ -1,60 +0,0 @@ -#include "gui_internal.hpp" -#include "../../imgui-node-editor/imgui_node_editor.h" -namespace NE = ax::NodeEditor; - -NE::EditorContext* editor_context=nullptr; -const char* editor_title; - -void draw_example_node(); - - -void node_editor_open(const char* title){ - NE::Config config; - config.SettingsFile = "node_editor.json"; - editor_context=NE::CreateEditor(&config); - editor_title=title; - NE::Style& style=NE::GetStyle(); -} - -void node_editor_close(){ - NE::DestroyEditor(editor_context); - editor_context=nullptr; -} - -u32 node_id_next; -u32 pin_id_next; -u32 link_id_next; - -void draw_node_editor(){ - if(editor_context==nullptr) - return; - - node_id_next=0; - pin_id_next=0; - link_id_next=0; - ImGui::Begin(editor_title); - ImGui::SetWindowSizeMin(300,300); - NE::SetCurrentEditor(editor_context); - NE::Begin(editor_title); - // Start drawing nodes. - draw_example_node(); - ImVec2 node_pos=NE::GetNodePosition(node_id_next-1); - NE::SetNodePosition(node_id_next, ImVec2Add(node_pos, ImVec2(50, 20))); - draw_example_node(); - NE::End(); - NE::SetCurrentEditor(nullptr); - ImGui::End(); -} - -void draw_example_node(){ - NE::BeginNode(node_id_next++); - ImGui::Text("Node A"); - NE::BeginPin(pin_id_next++, NE::PinKind::Input); - ImGui::Text("-> In"); - NE::EndPin(); - ImGui::SameLine(); - NE::BeginPin(pin_id_next++, NE::PinKind::Output); - ImGui::Text("Out ->"); - NE::EndPin(); - NE::EndNode(); -} diff --git a/src/gui/node_editor.cpp_ b/src/gui/node_editor.cpp_ new file mode 100644 index 0000000..9885f3c --- /dev/null +++ b/src/gui/node_editor.cpp_ @@ -0,0 +1,117 @@ +#include "gui_internal.hpp" +#include "../../imgui-node-editor/imgui_node_editor.h" +namespace NE = ax::NodeEditor; + +NE::EditorContext* editor_context=nullptr; +const char* editor_title; + +void draw_example_node(const char* title); + + +void node_editor_create(const char* title){ + NE::Config config; + config.SettingsFile = "node_editor.json"; + editor_context=NE::CreateEditor(&config); + editor_title=title; + //NE::Style& style=NE::GetStyle(); +} + +void node_editor_destroy(){ + NE::DestroyEditor(editor_context); + editor_context=nullptr; +} + +u32 node_id_next; +u32 pin_id_next; +u32 link_id_next; + +void draw_node_editor(){ + if(editor_context==nullptr) + return; + + node_id_next=0; + pin_id_next=0; + link_id_next=0; + ImGui::Begin(editor_title); + ImGui::SetWindowSizeMin(300,300); + NE::SetCurrentEditor(editor_context); + NE::Begin(editor_title); + // Start drawing nodes. + draw_example_node("node A"); + // ImVec2 node_pos=NE::GetNodePosition(node_id_next-1); + // NE::SetNodePosition(node_id_next, ImVec2Add(node_pos, ImVec2(50, 20))); + draw_example_node("node B"); + + + // Handle creation action, returns true if editor want to create new object (node or link) + if (NE::BeginCreate()) + { + NE::PinId inputPinId, outputPinId; + if (NE::QueryNewLink(&inputPinId, &outputPinId)) + { + // QueryNewLink returns true if editor want to create new link between pins. + // + // Link can be created only for two valid pins, it is up to you to + // validate if connection make sense. Editor is happy to make any. + // + // Link always goes from input to output. User may choose to drag + // link from output pin or input pin. This determine which pin ids + // are valid and which are not: + // * input valid, output invalid - user started to drag new ling from input pin + // * input invalid, output valid - user started to drag new ling from output pin + // * input valid, output valid - user dragged link over other pin, can be validated + + if (inputPinId && outputPinId) // both are valid, let's accept link + { + // NE::AcceptNewItem() return true when user release mouse button. + if (NE::AcceptNewItem()) + { + // Draw new link. + NE::Link(link_id_next++, inputPinId, outputPinId); + } + + // You may choose to reject connection between these nodes + // by calling NE::RejectNewItem(). This will allow editor to give + // visual feedback by changing link thickness and color. + } + } + } + NE::EndCreate(); // Wraps up object creation action handling. + + + // Handle deletion action + if (NE::BeginDelete()) + { + // There may be many links marked for deletion, let's loop over them. + NE::LinkId deletedLinkId; + while (NE::QueryDeletedLink(&deletedLinkId)) + { + // If you agree that link can be deleted, accept deletion. + if (NE::AcceptDeletedItem()) + { + } + + // You may reject link deletion by calling: + // NE::RejectDeletedItem(); + } + } + NE::EndDelete(); // Wrap up deletion action + + + NE::End(); + NE::SetCurrentEditor(nullptr); + ImGui::End(); +} + +void draw_example_node(const char* title){ + NE::BeginNode(node_id_next++); + ImGui::Text(title); + NE::BeginPin(pin_id_next++, NE::PinKind::Input); + ImGui::Text("-> In"); + NE::EndPin(); + ImGui::SameLine(); + NE::BeginPin(pin_id_next++, NE::PinKind::Output); + ImGui::Text("Out ->"); + NE::EndPin(); + NE::EndNode(); +} diff --git a/src/gui/node_editor2.cpp b/src/gui/node_editor2.cpp new file mode 100644 index 0000000..2ffc191 --- /dev/null +++ b/src/gui/node_editor2.cpp @@ -0,0 +1,81 @@ +#include "gui_internal.hpp" +#include "../../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(); +} diff --git a/tasks/clean_additions.sh b/tasks/clean_additions.sh index fb6d9ab..3657e49 100644 --- a/tasks/clean_additions.sh +++ b/tasks/clean_additions.sh @@ -1,6 +1,6 @@ #!/usr/bin/bash -try_delete_dir_or_file .rebuild_kerep.tmp -try_delete_dir_or_file .rebuild_imgui.tmp -try_delete_dir_or_file .rebuild_imgui-node-editor.tmp +for tmpfile in $(ls .rebuild_*.tmp); do + try_delete_dir_or_file "$tmpfile" +done try_delete_dir_or_file fonts/generated try_delete_dir_or_file libs/fonts_embedded.a diff --git a/tasks/pre_build.sh b/tasks/pre_build.sh index 15d452b..dd9d65c 100644 --- a/tasks/pre_build.sh +++ b/tasks/pre_build.sh @@ -26,9 +26,10 @@ if [ ! -f libs/fonts_embedded.a ]; then fi fi -handle_static_dependency kerep $KEREP_BUILD_TASK -handle_static_dependency imgui $KEREP_BUILD_TASK -handle_static_dependency imgui-node-editor $KEREP_BUILD_TASK +handle_static_dependency kerep $DEPS_BUILD_TASK +handle_static_dependency imgui $DEPS_BUILD_TASK +handle_static_dependency imgui-node-editor $DEPS_BUILD_TASK +handle_static_dependency imnodes $DEPS_BUILD_TASK # copy all precompiled libs cp libs/* $OBJDIR/libs/ diff --git a/tasks/rebuild_imgui-node-editor.sh b/tasks/rebuild_imgui-node-editor.sh deleted file mode 100644 index dfd580b..0000000 --- a/tasks/rebuild_imgui-node-editor.sh +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/bash -touch .rebuild_imgui-node-editor.tmp -myprint "${YELLOW}imgui-node-editor.a will be rebuilt in the next build task" diff --git a/tasks/rebuild_imgui.sh b/tasks/rebuild_imgui.sh deleted file mode 100644 index 75b8aaf..0000000 --- a/tasks/rebuild_imgui.sh +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/bash -touch .rebuild_imgui.tmp -myprint "${YELLOW}imgui.a will be rebuilt in the next build task" diff --git a/tasks/rebuild_kerep.sh b/tasks/rebuild_kerep.sh deleted file mode 100644 index 7698a61..0000000 --- a/tasks/rebuild_kerep.sh +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/bash -touch .rebuild_kerep.tmp -myprint "${YELLOW}kerep.a will be rebuilt in the next build task" diff --git a/tasks/rebuild_lib.sh b/tasks/rebuild_lib.sh new file mode 100644 index 0000000..3c62a17 --- /dev/null +++ b/tasks/rebuild_lib.sh @@ -0,0 +1,5 @@ +#!/bin/bash +source cbuild/colors.sh +source cbuild/functions.sh +touch ".rebuild_$1.tmp" +myprint "${YELLOW}$1.a will be rebuilt in the next build task"