Skip to content

Commit 06c9890

Browse files
committed
Editor: Pan from a widget of a node that does not use the navigate button
Since the fix of thedmd#238, a pan needs the press to make the background or an object active. A press on a widget of a node (a button, which uses the left mouse button) made neither: the view did not pan. Now a press of the navigate button inside the editor that no item owns is remembered: - once the mouse drags, the background takes the button until its release (SetKeyOwner()), and the view pans; - a click stays a click: the context menus of the widget and of its node open, as before; - a widget that uses the navigate button owns it, and keeps it; - the release that ends a pan is locked for its frame: no context menu opens under the mouse; - a drag pressed outside the editor still does not pan (thedmd#238). Needs Dear ImGui 1.89 (input ownership). With an older one, nothing changes.
1 parent 1e0e494 commit 06c9890

2 files changed

Lines changed: 57 additions & 1 deletion

File tree

‎imgui_node_editor.cpp‎

Lines changed: 52 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,14 @@ static const auto c_AllRoundCornersFlags = 0xF0; // ImDrawFlags_RoundCornersAll
156156
static const auto c_AllRoundCornersFlags = 15;
157157
#endif
158158

159+
// ImGui 1.89 introduced the input ownership (SetKeyOwner(), GetKeyOwner(), the lock flags): the editor's background
160+
// takes the navigate button with it, for a pan that starts on a widget of a node.
161+
#if IMGUI_VERSION_NUM >= 19070
162+
static const auto c_NoKeyOwner = ImGuiKeyOwner_NoOwner;
163+
#elif IMGUI_VERSION_NUM >= 18900
164+
static const auto c_NoKeyOwner = ImGuiKeyOwner_None; // ImGuiKeyOwner_NoOwner since ImGui 1.90.7
165+
#endif
166+
159167

160168
//------------------------------------------------------------------------------
161169
# if defined(_DEBUG) && defined(_WIN32)
@@ -1223,6 +1231,18 @@ void ed::EditorContext::Begin(const char* id, const ImVec2& size)
12231231
m_EditorActiveId = ImGui::GetID(id);
12241232
ImGui::PushID(id);
12251233

1234+
# if IMGUI_VERSION_NUM >= 18900
1235+
// The release that ends a pan is no click for the items under the mouse, which moved with the view: a context menu
1236+
// would open there. Locked before the items are submitted.
1237+
const auto& io = ImGui::GetIO();
1238+
const auto navigateButton = m_Config.NavigateButtonIndex;
1239+
const auto isPanning = m_NavigateAction.m_IsActive;
1240+
const auto isReleased = io.MouseReleased[navigateButton];
1241+
const auto wasDragged = io.MouseDragMaxDistanceSqr[navigateButton] >= io.MouseDragThreshold * io.MouseDragThreshold;
1242+
if (isPanning && isReleased && wasDragged)
1243+
ImGui::SetKeyOwner(ImGui::MouseButtonToKey(navigateButton), m_BackgroundId, ImGuiInputFlags_LockThisFrame);
1244+
# endif
1245+
12261246
m_BeginColorStackSize = m_Style.GetColorStackSize();
12271247
m_BeginVarStackSize = m_Style.GetVarStackSize();
12281248

@@ -2271,6 +2291,15 @@ bool ed::EditorContext::IsHoveredWithoutOverlapp() const
22712291
return m_IsHoveredWithoutOverlapp;
22722292
}
22732293

2294+
bool ed::EditorContext::OwnsNavigateButton() const
2295+
{
2296+
# if IMGUI_VERSION_NUM >= 18900
2297+
return ImGui::GetKeyOwner(ImGui::MouseButtonToKey(m_Config.NavigateButtonIndex)) == m_BackgroundId;
2298+
# else
2299+
return false;
2300+
# endif
2301+
}
2302+
22742303
bool ed::EditorContext::CanAcceptUserInput() const
22752304
{
22762305
return m_IsFocused && m_IsHovered;
@@ -2801,6 +2830,27 @@ ed::Control ed::EditorContext::BuildControl(bool allowOffscreen)
28012830
auto backgroundClickButonIndex = emitInteractiveAreaEx(ObjectId(), editorRect, backgroundExtraFlags);
28022831
auto backgroundDoubleClickButtonIndex = isMouseDoubleClickOverBackground();
28032832
auto isBackgroundActive = ImGui::IsItemActive();
2833+
2834+
# if IMGUI_VERSION_NUM >= 18900
2835+
m_BackgroundId = ImGui::GetItemID();
2836+
// A press of the navigate button inside the editor that no item takes (on a widget of a node which does not use
2837+
// this button, for example) may start a pan: once the mouse drags, the background takes the button until its
2838+
// release. A click leaves the button to the items (the context menu of a widget, or of its node). A widget which
2839+
// uses the button owns it, and keeps it.
2840+
const auto navigateButton = m_Config.NavigateButtonIndex;
2841+
const auto navigateKey = ImGui::MouseButtonToKey(navigateButton);
2842+
const auto isUnowned = ImGui::GetKeyOwner(navigateKey) == c_NoKeyOwner;
2843+
if (ImGui::IsMouseClicked(navigateButton))
2844+
{
2845+
const auto isOverEditor = ImGui::IsItemHovered(ImGuiHoveredFlags_RectOnly) && ImGui::IsWindowHovered();
2846+
m_IsNavigatePressInside = isUnowned && isOverEditor;
2847+
}
2848+
else if (!ImGui::GetIO().MouseDown[navigateButton])
2849+
m_IsNavigatePressInside = false;
2850+
const auto isDragged = ImGui::IsMouseDragPastThreshold(navigateButton);
2851+
if (m_IsNavigatePressInside && isDragged && isUnowned)
2852+
ImGui::SetKeyOwner(navigateKey, m_BackgroundId, ImGuiInputFlags_LockUntilRelease);
2853+
# endif
28042854
auto isBackgroundHot = !hotObject;
28052855
auto isDragging = ImGui::IsMouseDragging(0, 1) || ImGui::IsMouseDragging(1, 1) || ImGui::IsMouseDragging(2, 1);
28062856

@@ -3634,7 +3684,8 @@ ed::EditorAction::AcceptResult ed::NavigateAction::Accept(const Control& control
36343684
return False;
36353685

36363686
// A drag that enters the editor from another window was pressed on nothing of the editor's.
3637-
const auto isPressedOnEditor = control.BackgroundActive || control.ActiveObject != nullptr;
3687+
// A press on a widget of a node which does not use the navigate button is taken by the background (see BuildControl()).
3688+
const auto isPressedOnEditor = control.BackgroundActive || control.ActiveObject != nullptr || Editor->OwnsNavigateButton();
36383689
if (Editor->CanAcceptUserInput() && isPressedOnEditor && ImGui::IsMouseDragging(Editor->GetConfig().NavigateButtonIndex, 0.0f))
36393690
{
36403691
m_Animation.Stop();

‎imgui_node_editor_internal.h‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1417,6 +1417,7 @@ struct EditorContext
14171417
bool IsFocused();
14181418
bool IsHovered() const;
14191419
bool IsHoveredWithoutOverlapp() const;
1420+
bool OwnsNavigateButton() const; // the press of the navigate button was taken by the editor's background
14201421
bool CanAcceptUserInput() const;
14211422

14221423
// True for a frame whose host window skips items. Item rectangles are stale
@@ -1546,6 +1547,10 @@ struct EditorContext
15461547
bool m_IsFocused;
15471548
bool m_IsHovered;
15481549
bool m_IsHoveredWithoutOverlapp;
1550+
# if IMGUI_VERSION_NUM >= 18900
1551+
ImGuiID m_BackgroundId = 0; // the item that covers the editor: it takes the navigate button for a pan
1552+
bool m_IsNavigatePressInside = false; // the navigate button was pressed inside the editor, on no item that owns it
1553+
# endif
15491554

15501555
bool m_ShortcutsEnabled;
15511556

0 commit comments

Comments
 (0)