diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..277a16e --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +build/ +cmake-build-*/ +external/* +.idea/ diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..21100d8 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,33 @@ +cmake_minimum_required(VERSION 3.12) +project(node_clipping_issue) +set(CMAKE_CXX_STANDARD 17) + +if (NOT IS_DIRECTORY ${CMAKE_CURRENT_LIST_DIR}/external/imgui) + message(FATAL_ERROR "Please run ./fetch_external.sh in order to populate external/") +endif() + +########################################################## +# Add ImGui & HelloImGui +########################################################## +# i. HelloImGui will build ImGui as part of its build (and here, we tell it to use our own version in external/imgui) +set(HELLOIMGUI_IMGUI_SOURCE_DIR "${CMAKE_CURRENT_LIST_DIR}/external/imgui") +add_subdirectory(external/hello_imgui) +# ii. HelloImGui provides a function `hello_imgui_add_app` available in order to easily add applications +list(APPEND CMAKE_MODULE_PATH ${HELLOIMGUI_CMAKE_PATH}) +include(hello_imgui_add_app) + + +########################################################## +# Add imgui-node-editor +########################################################## +set(imgui_node_editor_dir ${CMAKE_CURRENT_LIST_DIR}/external/imgui-node-editor) +file(GLOB imgui_node_editor_src ${imgui_node_editor_dir}/*.cpp ${imgui_node_editor_dir}/*.h) +add_library(imgui_node_editor ${imgui_node_editor_src}) +target_include_directories(imgui_node_editor PUBLIC ${imgui_node_editor_dir}) +target_link_libraries(imgui_node_editor PUBLIC imgui) + +########################################################## +# Build your app +########################################################## +hello_imgui_add_app(node_clipping_issue node_clipping_issue.cpp) +target_link_libraries(node_clipping_issue PRIVATE imgui_node_editor) diff --git a/Readme.md b/Readme.md new file mode 100644 index 0000000..b5f8d7d --- /dev/null +++ b/Readme.md @@ -0,0 +1,39 @@ +# Example code for reproducing https://github.com/thedmd/imgui-node-editor/issues/205 + +## Build instructions + +``` +./fetch_external.sh +mkdir build +cd build +cmake .. +make -j +``` + +## Code explanation + +This code is self-contained in a short file: [node_clipping_issue.cpp](node_clipping_issue.cpp) + +It uses HelloImGui in order to simplify the example creation. HelloImGui is based on a quite recent version of the ImGui docking branch. + +It was not possible to use the ImGui version inside node editor, since it is outdated, and adds stack layout patches to ImGui which are not trivial to rebase. + +## Fixes applied to imgui-node-editor: + +#### [remove duplicate ImVec2 operator-](https://github.com/pthom/imgui-node-editor/commit/0da24eb1bbc4355113509ab519d37b1f856660c0) +(operator- is now provided by imgui) + +#### [ed::CreateItemAction::Begin: if (m_CurrentStage == None) => m_InActive = false](https://github.com/pthom/imgui-node-editor/commit/2ba8ca4f3a36ee086950d98b34422c81e550722c) +(Undo this commit to see the related issue: execution will fail at startup) + +Workaround another unrelated issue that is triggered by this example. + +#### [Fix #205: workaround clipping issues when link with docked windows](https://github.com/pthom/imgui-node-editor/commit/2265a4bad141a07478292186eb282c85a4bb6991) +(Undo this commit to see the issue: clipping issues will appear when creating links) + +This is a workaround for +https://github.com/thedmd/imgui-node-editor/issues/205 +https://github.com/pthom/imgui_bundle/issues/117 +Adding a simple pixel at m_WidgetRect.Max is enough to bypass the issue. + +This is not a real fix, since it merely adds a fake pixel at (xmax, ymax), so that the app knows where the clipping should end. A better solution would be required. diff --git a/fetch_external.sh b/fetch_external.sh new file mode 100755 index 0000000..b98d2ba --- /dev/null +++ b/fetch_external.sh @@ -0,0 +1,11 @@ +THIS_DIR=$(dirname "$0") +echo THIS_DIR=$THIS_DIR +mkdir -p external +cd $THIS_DIR/external + +git clone -b docking https://github.com/ocornut/imgui.git +git clone -b master https://github.com/pthom/hello_imgui.git + +# Clone imgui-node-editor +#git clone -b develop https://github.com/thedmd/imgui-node-editor.git # official version +git clone -b fix_win_clipping https://github.com/pthom/imgui-node-editor.git # fork with fixes + workaround diff --git a/node_clipping_issue.cpp b/node_clipping_issue.cpp new file mode 100644 index 0000000..5f1b88f --- /dev/null +++ b/node_clipping_issue.cpp @@ -0,0 +1,91 @@ +#include "imgui.h" +#include "imgui_node_editor.h" +#include "hello_imgui/hello_imgui.h" + +namespace ed = ax::NodeEditor; + +// A simple utility to get reproducible ids at each frame +struct IdCounter +{ + int _next_id = 0; + int id() + { + _next_id++; + return _next_id; + } + void reset(){ + _next_id = 0; + } +}; + + +// this is the main Gui function: it draws two nodes and enables to initiate a link +void gui() +{ + static IdCounter next_id; + static IdCounter next_link_id; + next_id.reset(); + next_link_id.reset(); + + ImGui::SetNextWindowSize(ImVec2(0.0f, 0.0f)); + ed::Begin("My Editor"); + + ed::BeginNode(next_id.id()); + ImGui::Text("Node 1"); + ed::BeginPin(next_id.id(), ed::PinKind::Output); + ImGui::Text("Out ->"); + ed::EndPin(); + ed::EndNode(); + + ed::BeginNode(next_id.id()); + ImGui::Text("Node 2"); + ed::BeginPin(next_id.id(), ed::PinKind::Input); + ImGui::Text("-> In"); + ed::EndPin(); + ed::EndNode(); + + if (ed::BeginCreate()) + { + ed::PinId input_pin_id; + ed::PinId output_pin_id; + if (ed::QueryNewLink(&input_pin_id, &output_pin_id)) + { + if (ed::AcceptNewItem()) + ed::Link(next_link_id.id(), input_pin_id, output_pin_id); + } + ed::EndCreate(); + } + + ed::End(); +} + + +int main(int, char**) +{ + // Prepare the node editor context + ed::Config gNodeEditorConfig; + ed::EditorContext *gNodeEditorContext = ed::CreateEditor(&gNodeEditorConfig); + ed::SetCurrentEditor(gNodeEditorContext); + + // We use HelloImGui, with a DockSpace (since the issue will occur with dockable windows) + HelloImGui::RunnerParams runner_params; + runner_params.imGuiWindowParams.defaultImGuiWindowType = HelloImGui::DefaultImGuiWindowType::ProvideFullScreenDockSpace; + // runner_params.imGuiWindowParams.enableViewports = true; + + // We create a dockable window in HelloImGui + HelloImGui::DockableWindow dockableWindow; + { + dockableWindow.GuiFunction = gui; + dockableWindow.label = "graph"; + dockableWindow.dockSpaceName = "MainDockSpace"; + } + runner_params.dockingParams.dockableWindows = { dockableWindow }; + + // Run the app + HelloImGui::Run(runner_params); + + // Destroy node editor context + ed::DestroyEditor(gNodeEditorContext); + + return 0; +}