nelarius / imnodes Goto Github PK
View Code? Open in Web Editor NEWA small, dependency-free node editor for dear imgui
License: MIT License
A small, dependency-free node editor for dear imgui
License: MIT License
When rendering a complex node graph, the links will often be in the way of editing the nodes. If there was an option to render the links under everything else it would fix many problems I am having when changing node attributes.
I know this might be too hard to implement because of the immediate nature of imgui.
Thanks for sharing this nice project!
object_pool_update clears the in_use flag to false for all nodes. At exit, none of the node positions are saved to save_load.ini, since the SaveEditorStateToIniString checks for in_use.
Commenting out this check makes it work. Why was that check there?
I had to move the node creation (released key A) right after BeginNodeEditor and before the rendering of all nodes, otherwise some assert triggered in EndNodeEditor. This happens when you start with an empty editor (no nodes, no ini file) and press 'a'. The assert was this one:
void draw_list_activate_node_background(const int node_idx)
{
const int submission_idx =
g.node_idx_to_submission_idx.GetInt(static_cast<ImGuiID>(node_idx), -1);
assert(submission_idx != -1);
There currently aren't any examples showing how to remove a node and all links connected to it's attributes.
Hi,
I'd like to integrate this library as a part of my blueprint framework as it looks simple and easy to use. In the blueprint design window, I'd like to let the user reset the position of the canvas if we have many nodes on the canvas and do not know where are we now.
I didn't found the function via the source code, may I know how to do that?
Thanks
Now we PushColorStyle function to change the color for node and pin.
How about adding a way to support to change the shape of Pin? We could get a good result if we can change the shape when using the node system with some of the basic shapes listed below:
PinShape
{
CIRCLE,
TRIANGLE,
SQUARE,
PENTAGON,
STAR,
SEMICIRCLE,
HEX,
CROSS,
RING,
ARROW,
QUATREFOIL,
RHOMBUS,
HEART,
OCTAGON,
};
Besides, it would be great if there have a way to change the node's icon like this:
Hi,
I'd like to draw a rectangle with color by "ImGui::GetWindowDrawList()-AddRectFilled", and the layout of the rectangle should between the background and nodes.
Why do this?
Sometimes, we want to group some nodes as one group, to let the user know it clear, we would draw a background rectangle for these nodes.
May I know how to do that?
Thanks
I have done a C wrapping of imnodes in https://github.com/cimgui/cimnodes
It would be much better for default arguments on pointers to be NULL than 0
bool IsLinkCreated(
int* started_at_attribute_id,
int* ended_at_attribute_id,
bool* created_from_snap = NULL);
Would you mind doing this changes?
I've tried to compile & run this app on macOS but unfortunately it looks like this:
As you can see, the display is only shown on the lower left corner as if it was the entire screen, and dragging/resizing any window outside that quarter is impossible (it disappears as if I was moving the window outside the visible screen). However the mouse input detects the entire screen, which makes it rather difficult to interact with the imgui windows, as I have to click and drag where there's nothing.
My guess is that the high-dpi screen affects the rendering somehow.
Hope to get this fixed soon! The library looks awesome, good job!
I'm getting the below linking errors when I attempt to include imnodes in my project. I can include the files and it recognizes the functions but won't compile them. ImGui works fine when I don't attempt to use imnodes. Any thoughts.
Thanks!
VisualState.obj : error LNK2019: unresolved external symbol "void __cdecl imnodes::Initialize(void)" (?Initialize@imnodes@@YAXXZ) referenced in function "public: void __cdecl VisualState::VisualZone(void)" (?VisualZone@VisualState@@QEAAXXZ) 1>VisualState.obj : error LNK2019: unresolved external symbol "void __cdecl imnodes::Shutdown(void)" (?Shutdown@imnodes@@YAXXZ) referenced in function "public: void __cdecl VisualState::VisualZone(void)" (?VisualZone@VisualState@@QEAAXXZ) 1>VisualState.obj : error LNK2019: unresolved external symbol "void __cdecl imnodes::BeginNode(int)" (?BeginNode@imnodes@@YAXH@Z) referenced in function "public: void __cdecl VisualState::VisualZone(void)" (?VisualZone@VisualState@@QEAAXXZ) 1>VisualState.obj : error LNK2019: unresolved external symbol "void __cdecl imnodes::EndNode(void)" (?EndNode@imnodes@@YAXXZ) referenced in function "public: void __cdecl VisualState::VisualZone(void)" (?VisualZone@VisualState@@QEAAXXZ) 1>VisualState.obj : error LNK2019: unresolved external symbol "void __cdecl imnodes::BeginOutputAttribute(int,enum imnodes::PinShape)" (?BeginOutputAttribute@imnodes@@YAXHW4PinShape@1@@Z) referenced in function "public: void __cdecl VisualState::VisualZone(void)" (?VisualZone@VisualState@@QEAAXXZ) 1>VisualState.obj : error LNK2019: unresolved external symbol "void __cdecl imnodes::EndAttribute(void)" (?EndAttribute@imnodes@@YAXXZ) referenced in function "public: void __cdecl VisualState::VisualZone(void)" (?VisualZone@VisualState@@QEAAXXZ)
First, thank you for this library!
However, IMHO, The find_or_create_new
function in ObjectPool
can lead to a memory error. Indeed, this function allocates memory to grow memory for internal container objects (Using the ImVector::resize
function). But many structures store NodeData
, PinData
or NodeData
pointer directly.
In my tests if the number of PinData
grows (from 8, to 12, then 16), a random error occured in ImVec2 get_screen_space_pin_coordinates(const PinData& pin)
with random data in PinData
.
To quickly fix it, I add the following reserve
in EditorContext
constructor but this is not a real solution.
EditorContext()
: nodes(), pins(), links(), panning(0.f, 0.f), link_dragged(),
box_selector()
{
nodes.pool.reserve(1024);
nodes.in_use.reserve(1024);
nodes.free_list.reserve(1024);
nodes.id_map.Data.reserve(1024);
pins.pool.reserve(1024);
pins.in_use.reserve(1024);
pins.free_list.reserve(1024);
pins.id_map.Data.reserve(1024);
links.pool.reserve(1024);
links.in_use.reserve(1024);
links.free_list.reserve(1024);
links.id_map.Data.reserve(1024);
}
This imgui node library is really nice!
In my setup, i have need to make an "input & output" attribute, where i give a label to something coming in to the node, which also then goes out of the node.
Alternately, if i could give a label to the input and none to the output, but have the pins show at the same height, that would solve my problem as well.
Is there a way to do this currently?
If not, does anyone have thoughts on how the code could be modified to do this?
Thanks!
I have a property panel that shows info for the selected node, but whenever i click on the property panel, the selected nodes are cleared due to this code in EndNodeEditor() (like 1343)
// check to see if the mouse was near any node
if (g.node_hovered == INVALID_INDEX)
{
if (is_mouse_clicked)
{
editor.selected_nodes.clear();
}
}
Changing the if to this fixes my issue. Is this correct / should i submit a pull request?
// check to see if the mouse was near any node
if (g.node_hovered == INVALID_INDEX && ImGui::IsWindowHovered())
{
if (is_mouse_clicked)
{
editor.selected_nodes.clear();
}
}
Hi,
I would like to share a compute graph made with imnodes in LuaJIT-ImGui
All above line https://github.com/sonoro1234/LuaJIT-ImGui/blob/master/examples/imnodes_graph_sample.lua#L435 are the classes needed for the example, below this line there is the user code defining the nodes which can be changed at will.
When a node is selected by clicking it or by drawing a selection box, we can know about it by calling GetSelectedNodes
and finding its id
in an array of NumSelectedNodes
elements. I noticed that, if the node is deleted while selected, those functions still return its id
until a new click interaction is performed by the user. While this is not a big problem, I found it out because it generated a little issue for me.
I tried to implement locally a temporary fix, but before sending a PR I would like to have some feedback about the issue itself and the need to solve it. For now I thought it might be useful to simply show here the fix I just tried and wait for people's opinion.
Since NumSelectedNodes
must be called after EndNodeEditor
, in EndNodeEditor
I inserted the following code, starting from line 2175, after pools update and before the call to draw_list_sort_channels_by_depth
//for each selected node
for (int selection_idx = 0; selection_idx < editor.selected_node_indices.Size;
selection_idx++)
{
//check if the node is currently in use
int *node_id_ptr = &editor.selected_node_indices[selection_idx];
if (!editor.nodes.in_use[*node_id_ptr])
{
//if it is not used, then from now on it is also not selected
editor.selected_node_indices.erase_unsorted(node_id_ptr);
}
}
Something very similar follows to handle the same issue for the selected links.
When creating a link the bezier curve visually snaps to nearby attributes, IsLinkedCreated/Destroyed could be based on this visual snapping instead of the mouse click. It would show the effects of the link you are creating as you drag it over different attributes, which is good feedback for the user.
Hopefully you understand what I'm envisioning, I think this would work well alongside the AttributeFlags_EnableLinkDetachWithDragClick
flag. Thanks for this great node graph editor!
assert(value_stack.size() == 3ull);
fails if you connect two wires to one input. It leaves an extra value on the stack.
One possible recreation is to create 3 boxes: sine, sine and output. and connect both sine outputs to the 'r' input of 'output'. But any other connection of two outputs to an input failed for me as well.
When the window with the node editor is covered by another window and the other window gets dragged, a box selection appears in the node editor window.
One might add a check for ImGui::IsWindowHovered()
.
This code in EndNodeEditor()
fixes this behavior:
const bool is_mouse_clicked_in_canvas =
is_mouse_clicked &&
ImGui::IsWindowHovered() &&
g.canvas_rect_screen_space.Contains(ImGui::GetMousePos());
Related to this discussion: #17
It should be fairly easy to add at least the primitives supported by ImGui's draw list.
Hi, are there any plans on implementing zooming? Asking if I should look into it myself.
Running the code at the end in a plugin of my application causes the following exception to be thrown. I'm totally lost as to why this would happen.
// This usually assert if there is a mismatch between the ImGuiWindowFlags_ChildWindow / ParentWindow values and DC.ChildWindows[] in parents, aka we've done something wrong.
IM_ASSERT(g.Windows.Size == g.WindowsTempSortBuffer.Size);
static bool init = false;
if (!init) {
imnodes::Initialize();
init = true;
}
ImGui::Begin("simple node editor");
imnodes::BeginNodeEditor();
imnodes::EndNodeEditor();
ImGui::End();
Create a window and put a node editor inside. Run the program. If you click in the window top bar then drag it up and left, a selection box appears inside the node editor. I didn't expect a box selection tool when I clicked and dragged somewhere outside the node editor.
Edit: this also happens if you click and drag somewhere outside the ImGui window. For example, click and drag from just outside the right side of the window up to just above the top of the window. A selection box will appear in the node editor.
Where to find / how to understand the default user interaction commands?
I just started exploring imnodes and successfully used IsLinkCreated
to create links with drag and drop from one pin to an other one, but on the other side, I don't find a way to make IsLinkDestroyed
return true
. I tried to push the DELETE key selecting the link and also to drag the link away from a pin without success. I don't know how to proceed in order to understand if I am not pushing the right key or if in my software the event is not triggered because of an issue or misconfiguration.
Recently I tried a node editor that is able to delete selected nodes. The problem is that imnodes uses the node index to keep track of selected nodes which causes from assertion fails to invalid nodes being reported as selected. The solution I took was to clear the selection every time I deleted a selected node. I can make a pr if you like the solution.
Would it be possible to add a public method similar to the one below?
void SetImGuiContext(ImGuiContext* ctx) {
ImGui::SetCurrentContext(ctx);
}
The reason behind this is that globals are not shared between dlls, so when compiling imgui into a dll and imnodes into another, the context is not shared, and I end up getting access violations
You can read more about this here
I can also submit a PR to this if you wish, but I'm not exactly familiar with c++, although it does seems like an easy change
In the example project, SDL is missing. Would it be possible to add?
A zoom feature would be really useful for large node graphs. Are you planning to implement this? Or maybe some other option for faster navigation through the graph?
Any plans in the future for zooming in and out? Would be really useful. Love your work, cheers!
If I were to set up my node editor such that I draw a node, then a link, and then more nodes, like in the pseudo-code below, creating a second link, and only a second link, causes an assert - crashing the whole app. I have found 2 solutions to this issue which are also below.
I store links within my nodes, so to simplify things I wrote something like below:
for (auto node : nodes)
{
imnodes::BeginNode(node.id);
// draw node things
imnodes::EndNode();
for (auto links : node.links)
{
// draw link
imnodes::Link(link.id, link.start_id, link.end_id);
}
}
However, because I intertwine nodes and links I get,
click_interaction_update
function, and under the link creation caseif (snapping_pin_changed && g.snap_link_idx.has_value())
to
if (snapping_pin_changed && g.snap_link_idx.has_value()
&& editor.click_interaction_state.link_creation.end_pin_idx.has_value())
When using ImGui::Separator()
within a node, its width isn't respected and the separator appears to continue infinitely.
Currently, having an active attribute selects the node, which prevents users from dragging things in an attribute, because it drags the node instead. For example, focusing an input field in an attribute will prevent the user from dragging to select text within the field, and if its multiline the scrollbar cannot be dragged with the mouse.
To solve this, a flag could be added to attributes to prevent them from selecting the node when becoming active, or a method could be added to deselect a node, and that could be called when IsAnyAttributeActive returns true.
edit: If you end up adding the method to deselect the node (or all nodes), it could also be used to, e.g., deselect all nodes after deleting them. That is, if I delete all selected nodes, it would be nice if imnodes didn't still return those IDs in the next GetSelectedNodes call
In Blender it's possible to click and drag a link to disconnect it from a node, which is a very convenient feature.
Current plans:
IsLinkDestroyed
function)imnodes::shutdown does not set initialized to false, thus it is impossible to reinitialize imnodes.
Disclaimer: Not sure if this is a bug or a feature, but it's not consistent with other node editors I've used.
Create a node editor and put two nodes in it. Click and drag one of them to move it. Now click and drag the other one. The first one remained selected so they both move when you try to move the second one.
I expected to be able to move each node individually without having to deselect each after moving them.
Perhaps I might be doing something very wrong.
Using visual studio 2019.
In the hello.cpp example project;
Create a second node (by copy-pasting the first node).
Starting from 0, id the node and attributes in ascending order.
Start from 1, and things will work as expected.
If I make the first node's ID larger than the attribute ID (similar way to colornode), I get this assertion error:
assert(node_idx_depth_order.Size == g.node_idx_submission_order.Size);
in imnodes.cpp
It also appears that I get this assertion error again with arbitrary values, so it's probably not tied with the attribute id values.
I've had to go into the graph.h file and make the return values start from 1 and adjust when the node id is determined to get my node editor to create new nodes.
In the README, I think there's a typo. In the section about creating an output attribute, you have the following code snippet:
...
ImGui::Text("output pin");
ImGui::EndAttribute();
imnodes::EndNode();
...
I believe it should be:
...
ImGui::Text("output pin");
imnodes::EndAttribute(); // this should be imnodes, not ImGui
imnodes::EndNode();
...
Hi,
I have a crash that I can reproduce in 3 frames. First you need to draw two nodes in a editor. Then draw none and finally draw one.
The application will assert on line 874 in the function object_pool_update.
Here is a code exemple:
ImGui::Begin("test");
imnodes::BeginNodeEditor();
if (i == 0) { // frame 1
imnodes::BeginNode(0);
imnodes::EndNode();
imnodes::BeginNode(1);
imnodes::EndNode();
i++;
} else if (i == 1) { // frame 2
i++;
} else if (i == 2) { // frame 3
imnodes::BeginNode(0);
imnodes::EndNode();
i++;
}
imnodes::EndNodeEditor();
ImGui::End();
You don't need anything more than that. The crash doesn't happen if on frame 3 the node use another id so it is maybe an intended crash ? If that's the case I still think that at least the error reporting is sub-par but still I don't see why this couldn't work.
I do admit that I'm not familiar with imnodes so I might be missing something, I hope that you have all the informations you need.
If the editor contains two nodes, clicking and dragging on the one in the front won't be possible if an imgui widget is behind your mouse cursor, and you will be interacting with that widget instead, even if you cannot see it. I noticed it when playing around with sliders. You can also still interact with the pins of the node behind the one shown. Perhaps it is related to the changes in this commit? fd96ac2
Hi,
I am trying to build the project on Linux using premake5 gmake
When I do the make
, I obtain the following error:
==== Building imgui (debug) ====
imgui_impl_sdl.cpp
../../imgui/imgui_impl_sdl.cpp:47:10: fatal error: SDL.h: No such file or directory
#include <SDL.h>
^~~~~~~
compilation terminated.
imgui.make:141: recipe for target 'obj/Debug/imgui/imgui_impl_sdl.o' failed
make[1]: *** [obj/Debug/imgui/imgui_impl_sdl.o] Error 1
Makefile:40: recipe for target 'imgui' failed
make: *** [imgui] Error 2
I tried to manually modify the imgui.make file to add -I/usr/include/SDL
to the path but I only add many errors.
I never used premake before, so it's totally probable that i'm doing something wrong here.
In the README, there's a section about checking for new links where you instruct users to call imnodes::IsLinkCreated()
.
Is there an equivalent function for detecting that a link should be destroyed? In Blender, when you click and drag one of the endpoints of an existing link, it disconnects the two nodes and the link follows the mouse until you reconnect it somewhere or let go of the mouse button and it disappears. Is similar functionality possible with imnodes?
3>imnodes.obj : error LNK2001: unresolved external symbol "public: static char const * const ImGuiTextBuffer::EmptyString" (?EmptyString@ImGuiTextBuffer@@2QBDB)
3>F:\Cpp\Falcor\Bin\x64\Release\MultiPassPostProcess.exe : fatal error LNK1120: 1 unresolved externals
I have try to switch many different projects,and it turns out every of them has the same link issue.I spend 2 hours on it ,didn't find anything wrong.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.