|
20 | 20 | # include <streambuf>
|
21 | 21 | # include <type_traits>
|
22 | 22 |
|
| 23 | +#include <stack> |
| 24 | + |
23 | 25 | // https://stackoverflow.com/a/8597498
|
24 | 26 | # define DECLARE_HAS_NESTED(Name, Member) \
|
25 | 27 | \
|
@@ -5413,6 +5415,91 @@ ed::NodeBuilder::~NodeBuilder()
|
5413 | 5415 | m_PinSplitter.ClearFreeMemory();
|
5414 | 5416 | }
|
5415 | 5417 |
|
| 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 | + |
5416 | 5503 | void ed::NodeBuilder::Begin(NodeId nodeId)
|
5417 | 5504 | {
|
5418 | 5505 | IM_ASSERT(nullptr == m_CurrentNode);
|
@@ -5493,10 +5580,18 @@ void ed::NodeBuilder::Begin(NodeId nodeId)
|
5493 | 5580 | ImGui::SetCursorPos(ImGui::GetCursorPos() + ImVec2(editorStyle.NodePadding.x, editorStyle.NodePadding.y));
|
5494 | 5581 | ImGui::BeginGroup();
|
5495 | 5582 | }
|
| 5583 | + |
| 5584 | + // [ADAPT_IMGUI_BUNDLE] |
| 5585 | + if (GetConfig().ForceWindowContentWidthToNodeWidth) |
| 5586 | + sForceWindowContentWidthToNodeWidth.OnBeginNode(nodeId); |
5496 | 5587 | }
|
5497 | 5588 |
|
5498 | 5589 | void ed::NodeBuilder::End()
|
5499 | 5590 | {
|
| 5591 | + // [ADAPT_IMGUI_BUNDLE] |
| 5592 | + if (GetConfig().ForceWindowContentWidthToNodeWidth) |
| 5593 | + sForceWindowContentWidthToNodeWidth.OnEndNode(); |
| 5594 | + |
5500 | 5595 | IM_ASSERT(nullptr != m_CurrentNode);
|
5501 | 5596 |
|
5502 | 5597 | if (auto drawList = Editor->GetDrawList())
|
|
0 commit comments