Node with title bar gets expanded infinitely
I'm trying to make the default examples work. Here is my main loop:
void main_loop(App &app) {
ImGui::Begin("node editor");
ImNodes::BeginNodeEditor();
const int hardcoded_node_id = 1;
ImNodes::BeginNode(hardcoded_node_id + 1);
ImNodes::BeginNodeTitleBar();
ImGui::TextUnformatted("node");
ImNodes::EndNodeTitleBar();
ImNodes::EndNode();
ImNodes::EndNodeEditor();
ImGui::End();
}
// Elsewhere:
while (glfwWindowShouldClose(window) != GLFW_TRUE) {
glfwPollEvents();
ImGui_ImplOpenGL3_NewFrame();
ImGui_ImplGlfw_NewFrame();
ImGui::NewFrame();
main_loop(app);
ImGui::Render();
ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
glfwSwapBuffers(window);
}
For some reason, the node rectangle gets expanded every loop by the padding value at
ImNodes::EndNode(); -> node.Rect.Expand(node.LayoutStyle.Padding); -> Rect gets 8 pixel added to Max.x every loop (but not Max.y)
I don't really understand why it is doing this. Should I create a context and destroy it every frame ? I'm not doing it for ImGui and the examples do not seem to do it as well.
ImGui version 1.19.1 imnodes from branch master commit b2ec254
Seems that this works properly:
ImGui::Begin("node editor");
ImNodes::BeginNodeEditor();
ImNodes::BeginNode(1);
ImNodes::BeginNodeTitleBar();
ImGui::TextUnformatted("node");
ImNodes::EndNodeTitleBar();
ImNodes::BeginOutputAttribute(2);
ImGui::TextUnformatted("output pin");
ImNodes::EndOutputAttribute();
ImNodes::EndNode();
ImNodes::EndNodeEditor();
ImGui::End();
But this does not (expand infinitely):
ImGui::Begin("node editor");
ImNodes::BeginNodeEditor();
ImNodes::BeginNode(1);
ImNodes::BeginNodeTitleBar();
ImGui::TextUnformatted("node");
ImNodes::EndNodeTitleBar();
// Removed the BeginOutputAttribute and EndOutputAttribute calls
ImNodes::EndNode();
ImNodes::EndNodeEditor();
ImGui::End();
I experienced something similar. I found that if I don't layout any widgets or attributes after EndNodeTitleBar() that the width increases by 8 pixels on ever layout frame.
My solution (workaround) was to emit an ImGui::Dummy(0,0) between the EndNodeTitleBar() and EndNode() calls.
I believe the root cause is in the GetNodeTitleRect function: ` inline ImRect GetNodeTitleRect(const ImNodeData& node) { // 1. Get the rectangle occupied by the title bar's content (e.g., text), // and expand it slightly by adding padding. ImRect expanded_title_rect = node.TitleBarContentRect; expanded_title_rect.Expand(node.LayoutStyle.Padding);
// 2. Calculate and return the new title bar rectangle.
return ImRect(
expanded_title_rect.Min,
expanded_title_rect.Min + ImVec2(node.Rect.GetWidth(), 0.f) +
ImVec2(0.f, expanded_title_rect.GetHeight()));
}` The problem is: This implementation creates a feedback loop. The layout inside the title bar expands to fit the node's width, but the node's width is also being recalculated based on the content's width. As a result, if the function is called repeatedly, the node's width keeps growing.
I changed it to ignore the content's width for sizing and only use its height, like this: ` inline ImRect GetNodeTitleRect(const ImNodeData& node) { // Get the rectangle for the content. ImRect expanded_title_rect = node.TitleBarContentRect; // Add vertical padding. expanded_title_rect.Expand(node.LayoutStyle.Padding);
// Calculate and return the new title bar rectangle.
return ImRect(
// Use the content's top-left for the top-left coordinate.
expanded_title_rect.Min,
// The width (X) ignores the content's width and always uses the node's current width.
// The height (Y) uses the content's height to allow for collapsing/expanding.
expanded_title_rect.Min + ImVec2(node.Rect.GetWidth(), expanded_title_rect.GetHeight())
);
} `
This leads to another question: where is the node's width originally determined? Tracing this back reveals a different potential issue with the following function
inline ImRect GetItemRect() { return ImRect(ImGui::GetItemRectMin(), ImGui::GetItemRectMax()); }
While this appears harmless, it's important to note that this function returns the rect of the immediately preceding ImGui item, not necessarily the rect of the entire node.