Skip to content

Commit 148a06d

Browse files
committed
[ADAPT_IMGUI_BUNDLE]: Add ForceWindowContentWidthToNodeWidth
// By default, ImGui::TextWrapped() and ImGui::Separator(), ImGui::SliderXXX // will not work in a Node because they will not respect the node's bounds. // Instead, they will use the bounds of the whole window. // This is a hack to fix that. // We will have to fix several elements in the current window data: // - WorkRect.Max.x: the maximum x value of the WorkRect // (used by ImGui::Separator()) // - ContentRegionRect.Max.x: the maximum x value of the ContentRegionRect // (used by ImGui::TextWrapped()) // - DC.ItemWidth: the width of the current item // (used by SliderFloat, and all items that may require a prior call // to ImGui::SetNextItemWidth()) // // Implementation note: // - WorkRect.Max.x and ContentRegionRect.Max.x are set to: // nodeSize.x + nodePos.x - ImGui::GetStyle().WindowPadding.x // - DC_ItemWidth is set to: // nodeSize.x - ImGui::GetStyle().WindowPadding.x * 2.f - largestLabelSize.x // (where largestLabelSize is the size of the largest label we want to handle by default: // it consists of 4 wide characters)
1 parent fa37efd commit 148a06d

File tree

2 files changed

+104
-0
lines changed

2 files changed

+104
-0
lines changed

imgui_node_editor.cpp

+95
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@
2020
# include <streambuf>
2121
# include <type_traits>
2222

23+
#include <stack>
24+
2325
// https://stackoverflow.com/a/8597498
2426
# define DECLARE_HAS_NESTED(Name, Member) \
2527
\
@@ -5413,6 +5415,91 @@ ed::NodeBuilder::~NodeBuilder()
54135415
m_PinSplitter.ClearFreeMemory();
54145416
}
54155417

5418+
5419+
// [ADAPT_IMGUI_BUNDLE]
5420+
// By default, ImGui::TextWrapped() and ImGui::Separator(), ImGui::SliderXXX
5421+
// will not work in a Node because they will not respect the node's bounds.
5422+
// Instead, they will use the bounds of the whole window.
5423+
// This is a hack to fix that.
5424+
// We will have to fix several elements in the current window data:
5425+
// - WorkRect.Max.x: the maximum x value of the WorkRect
5426+
// (used by ImGui::Separator())
5427+
// - ContentRegionRect.Max.x: the maximum x value of the ContentRegionRect
5428+
// (used by ImGui::TextWrapped())
5429+
// - DC.ItemWidth: the width of the current item
5430+
// (used by SliderFloat, and all items that may require a prior call
5431+
// to ImGui::SetNextItemWidth())
5432+
//
5433+
// Implementation note:
5434+
// - WorkRect.Max.x and ContentRegionRect.Max.x are set to:
5435+
// nodeSize.x + nodePos.x - ImGui::GetStyle().WindowPadding.x
5436+
// - DC_ItemWidth is set to:
5437+
// nodeSize.x - ImGui::GetStyle().WindowPadding.x * 2.f - largestLabelSize.x
5438+
// (where largestLabelSize is the size of the largest label we want to handle by default:
5439+
// it consists of 4 wide characters)
5440+
struct
5441+
{
5442+
struct ImGuiContentWidthData
5443+
{
5444+
float WorkRect_XMax = 0.f;
5445+
float ContentRegionRect_XMax = 0.f;
5446+
float DC_ItemWidth = 0.f;
5447+
};
5448+
std::stack<ImGuiContentWidthData> m_StackOldContentWidth;
5449+
public:
5450+
void OnBeginNode(ed::NodeId nodeId)
5451+
{
5452+
ImGuiWindow* window = ImGui::GetCurrentWindow();
5453+
5454+
ImGuiContentWidthData currentWindowContentWidth;
5455+
currentWindowContentWidth.WorkRect_XMax = window->WorkRect.Max.x;
5456+
currentWindowContentWidth.ContentRegionRect_XMax = window->ContentRegionRect.Max.x;
5457+
currentWindowContentWidth.DC_ItemWidth = window->DC.ItemWidth;
5458+
m_StackOldContentWidth.push(currentWindowContentWidth);
5459+
5460+
ImVec2 nodeSize = GetNodeSize(nodeId);
5461+
ImVec2 nodePos = GetNodePosition(nodeId);
5462+
bool hasNodePos = nodePos.x != FLT_MAX && nodePos.y != FLT_MAX;
5463+
if (hasNodePos)
5464+
{
5465+
// Fix WorkRect.Max: used by ImGui::Separator()
5466+
float newMax = nodeSize.x + nodePos.x - ImGui::GetStyle().WindowPadding.x * 2.f;
5467+
window->WorkRect.Max.x = newMax;
5468+
5469+
// Fix ContentRegionRect.Max: used by ImGui::TextWrapped()
5470+
window->ContentRegionRect.Max.x = newMax;
5471+
5472+
// Fix DC.ItemWidth: used by SliderFloat, and all items that may require a prior call to ImGui::SetNextItemWidth()
5473+
// We handle 4 wide characters at max: if the slider label is bigger, the node may begin to grow
5474+
// (and the user shall call ImGui::SetNextItemWidth to avoid this)
5475+
const char* largestLabelHandled = "MMMM";
5476+
ImVec2 largestLabelSize = ImGui::CalcTextSize(largestLabelHandled);
5477+
window->DC.ItemWidth = nodeSize.x - ImGui::GetStyle().WindowPadding.x * 2.f - largestLabelSize.x;
5478+
5479+
// And a call to PushTextWrapPos
5480+
float newWrapPos = nodeSize.x + nodePos.x - ImGui::GetStyle().WindowPadding.x;
5481+
ImGui::PushTextWrapPos(newWrapPos);
5482+
}
5483+
else
5484+
{
5485+
ImGui::PushTextWrapPos(ImGui::GetWindowPos().x + 20.f);
5486+
}
5487+
}
5488+
5489+
void OnEndNode()
5490+
{
5491+
ImGuiWindow* window = ImGui::GetCurrentWindow();
5492+
auto currentWindowContentWidth = m_StackOldContentWidth.top();
5493+
m_StackOldContentWidth.pop();
5494+
5495+
window->WorkRect.Max.x = currentWindowContentWidth.WorkRect_XMax;
5496+
window->ContentRegionRect.Max.x = currentWindowContentWidth.ContentRegionRect_XMax;
5497+
window->DC.ItemWidth = currentWindowContentWidth.DC_ItemWidth;
5498+
ImGui::PopTextWrapPos();
5499+
}
5500+
} sForceWindowContentWidthToNodeWidth;
5501+
5502+
54165503
void ed::NodeBuilder::Begin(NodeId nodeId)
54175504
{
54185505
IM_ASSERT(nullptr == m_CurrentNode);
@@ -5493,10 +5580,18 @@ void ed::NodeBuilder::Begin(NodeId nodeId)
54935580
ImGui::SetCursorPos(ImGui::GetCursorPos() + ImVec2(editorStyle.NodePadding.x, editorStyle.NodePadding.y));
54945581
ImGui::BeginGroup();
54955582
}
5583+
5584+
// [ADAPT_IMGUI_BUNDLE]
5585+
if (GetConfig().ForceWindowContentWidthToNodeWidth)
5586+
sForceWindowContentWidthToNodeWidth.OnBeginNode(nodeId);
54965587
}
54975588

54985589
void ed::NodeBuilder::End()
54995590
{
5591+
// [ADAPT_IMGUI_BUNDLE]
5592+
if (GetConfig().ForceWindowContentWidthToNodeWidth)
5593+
sForceWindowContentWidthToNodeWidth.OnEndNode();
5594+
55005595
IM_ASSERT(nullptr != m_CurrentNode);
55015596

55025597
if (auto drawList = Editor->GetDrawList())

imgui_node_editor.h

+9
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,14 @@ struct Config
109109
bool EnableSmoothZoom;
110110
float SmoothZoomPower;
111111

112+
// [ADAPT_IMGUI_BUNDLE]
113+
//
114+
// By default, ImGui::TextWrapped() and ImGui::Separator(), and ImGui::SliderXXX
115+
// will not work in a Node because they will not respect the node's bounds.
116+
// Instead, they will use the width of the whole window.
117+
// Set ForceWindowContentWidthToNodeWidth to true to fix this (this is disabled by default).
118+
bool ForceWindowContentWidthToNodeWidth;
119+
112120
Config()
113121
: SettingsFile("NodeEditor.json")
114122
, BeginSaveSession(nullptr)
@@ -130,6 +138,7 @@ struct Config
130138
# else
131139
, SmoothZoomPower(1.3f)
132140
# endif
141+
, ForceWindowContentWidthToNodeWidth(false)
133142
{
134143
}
135144
};

0 commit comments

Comments
 (0)