mirror of
https://github.com/Drezil/imgui.git
synced 2024-11-15 01:17:00 +00:00
Nav: Added experiment ImGuiWindowFlags_NavFlattened flag to cross over between parent and non-scrolling child windows (#323)
This commit is contained in:
parent
769a1dd748
commit
b3cba62b80
38
imgui.cpp
38
imgui.cpp
@ -1755,9 +1755,10 @@ ImGuiWindow::ImGuiWindow(const char* name)
|
|||||||
DrawList = (ImDrawList*)ImGui::MemAlloc(sizeof(ImDrawList));
|
DrawList = (ImDrawList*)ImGui::MemAlloc(sizeof(ImDrawList));
|
||||||
IM_PLACEMENT_NEW(DrawList) ImDrawList();
|
IM_PLACEMENT_NEW(DrawList) ImDrawList();
|
||||||
DrawList->_OwnerName = Name;
|
DrawList->_OwnerName = Name;
|
||||||
|
ParentWindow = NULL;
|
||||||
RootWindow = NULL;
|
RootWindow = NULL;
|
||||||
RootNonPopupWindow = NULL;
|
RootNonPopupWindow = NULL;
|
||||||
ParentWindow = NULL;
|
RootNavWindow = NULL;
|
||||||
|
|
||||||
FocusIdxAllCounter = FocusIdxTabCounter = -1;
|
FocusIdxAllCounter = FocusIdxTabCounter = -1;
|
||||||
FocusIdxAllRequestCurrent = FocusIdxTabRequestCurrent = INT_MAX;
|
FocusIdxAllRequestCurrent = FocusIdxTabRequestCurrent = INT_MAX;
|
||||||
@ -1917,7 +1918,7 @@ static float NavScoreItemDistInterval(float a0, float a1, float b0, float b1)
|
|||||||
static bool NavScoreItem(ImRect cand)
|
static bool NavScoreItem(ImRect cand)
|
||||||
{
|
{
|
||||||
ImGuiContext& g = *GImGui;
|
ImGuiContext& g = *GImGui;
|
||||||
ImGuiWindow* window = g.CurrentWindow;
|
ImGuiWindow* window = g.NavWindow;
|
||||||
if (g.NavLayer != window->DC.NavLayerCurrent)
|
if (g.NavLayer != window->DC.NavLayerCurrent)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
@ -2059,10 +2060,10 @@ bool ImGui::ItemAdd(const ImRect& bb, const ImGuiID* id, const ImRect* nav_bb_ar
|
|||||||
// We could early out with `if (is_clipped && !g.NavInitDefaultRequest) return false;` but when we wouldn't be able to reach unclipped widgets. This would work if user had explicit scrolling control (e.g. mapped on a stick)
|
// We could early out with `if (is_clipped && !g.NavInitDefaultRequest) return false;` but when we wouldn't be able to reach unclipped widgets. This would work if user had explicit scrolling control (e.g. mapped on a stick)
|
||||||
// A more pragmatic solution for handling last lists is relying on the fact that they are likely evenly spread items (so that clipper can work) and we could nav at higher-level (apply index, etc.)
|
// A more pragmatic solution for handling last lists is relying on the fact that they are likely evenly spread items (so that clipper can work) and we could nav at higher-level (apply index, etc.)
|
||||||
// So eventually we would like to provide the user will the primitives to be able to implement that sort of customized/efficient navigation handling whenever necessary.
|
// So eventually we would like to provide the user will the primitives to be able to implement that sort of customized/efficient navigation handling whenever necessary.
|
||||||
if (id != NULL && g.NavWindow == window && g.IO.NavUsable)
|
if (id != NULL && g.NavWindow == window->RootNavWindow && g.IO.NavUsable)
|
||||||
{
|
{
|
||||||
const ImRect& nav_bb = nav_bb_arg ? *nav_bb_arg : bb;
|
const ImRect& nav_bb = nav_bb_arg ? *nav_bb_arg : bb;
|
||||||
const ImRect nav_bb_rel(nav_bb.Min - window->Pos, nav_bb.Max - window->Pos);
|
const ImRect nav_bb_rel(nav_bb.Min - g.NavWindow->Pos, nav_bb.Max - g.NavWindow->Pos);
|
||||||
if (g.NavInitDefaultRequest && g.NavLayer == window->DC.NavLayerCurrent && window->DC.AllowNavDefaultFocus)
|
if (g.NavInitDefaultRequest && g.NavLayer == window->DC.NavLayerCurrent && window->DC.AllowNavDefaultFocus)
|
||||||
{
|
{
|
||||||
g.NavInitDefaultRequest = g.NavInitDefaultResultExplicit = false; // Clear flag immediately, first item gets default, also simplify the if() in ItemAdd()
|
g.NavInitDefaultRequest = g.NavInitDefaultResultExplicit = false; // Clear flag immediately, first item gets default, also simplify the if() in ItemAdd()
|
||||||
@ -2070,8 +2071,8 @@ bool ImGui::ItemAdd(const ImRect& bb, const ImGuiID* id, const ImRect* nav_bb_ar
|
|||||||
g.NavInitDefaultResultRectRel = nav_bb_rel;
|
g.NavInitDefaultResultRectRel = nav_bb_rel;
|
||||||
}
|
}
|
||||||
|
|
||||||
const bool DEBUG_NAV = false; // [DEBUG] Enable to test scoring on all items.
|
//const bool DEBUG_NAV = false; // [DEBUG] Enable to test scoring on all items.
|
||||||
if ((g.NavMoveRequest || DEBUG_NAV) && g.NavId != *id)
|
if ((g.NavMoveRequest /*|| DEBUG_NAV*/) && g.NavId != *id)
|
||||||
{
|
{
|
||||||
//if (DEBUG_NAV && !g.NavMoveRequest) g.NavMoveDir = ImGuiNavDir_N;
|
//if (DEBUG_NAV && !g.NavMoveRequest) g.NavMoveDir = ImGuiNavDir_N;
|
||||||
if (NavScoreItem(nav_bb)) //if (!DEBUG || g.NavMoveRequest)
|
if (NavScoreItem(nav_bb)) //if (!DEBUG || g.NavMoveRequest)
|
||||||
@ -2389,7 +2390,7 @@ static void NavUpdate()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Apply result from previous navigation directional move request
|
// Apply result from previous frame navigation directional move request
|
||||||
ImGui::SetActiveID(0);
|
ImGui::SetActiveID(0);
|
||||||
SetNavIdMoveMouse(g.NavMoveResultId, g.NavMoveResultRectRel);
|
SetNavIdMoveMouse(g.NavMoveResultId, g.NavMoveResultRectRel);
|
||||||
g.NavMoveFromClampedRefRect = false;
|
g.NavMoveFromClampedRefRect = false;
|
||||||
@ -3864,7 +3865,7 @@ void ImGui::SetItemAllowOverlap()
|
|||||||
void ImGui::SetItemDefaultFocus()
|
void ImGui::SetItemDefaultFocus()
|
||||||
{
|
{
|
||||||
ImGuiContext& g = *GImGui;
|
ImGuiContext& g = *GImGui;
|
||||||
if (g.NavWindow == g.CurrentWindow && (g.NavInitDefaultRequest || g.NavInitDefaultResultId != 0))
|
if (g.NavWindow == g.CurrentWindow->RootNavWindow && (g.NavInitDefaultRequest || g.NavInitDefaultResultId != 0))
|
||||||
{
|
{
|
||||||
g.NavInitDefaultRequest = false;
|
g.NavInitDefaultRequest = false;
|
||||||
g.NavInitDefaultResultExplicit = true;
|
g.NavInitDefaultResultExplicit = true;
|
||||||
@ -4186,7 +4187,7 @@ bool ImGui::BeginChild(const char* str_id, const ImVec2& size_arg, bool border,
|
|||||||
|
|
||||||
// Process navigation-in immediately so NavInit can run on first frame
|
// Process navigation-in immediately so NavInit can run on first frame
|
||||||
const ImGuiID id = parent_window->GetChildID(child_window);
|
const ImGuiID id = parent_window->GetChildID(child_window);
|
||||||
if ((child_window->DC.NavLayerActiveFlags != 0 || child_window->DC.NavHasScroll) && GImGui->NavActivateId == id)
|
if (!(flags & ImGuiWindowFlags_NavFlattened) && (child_window->DC.NavLayerActiveFlags != 0 || child_window->DC.NavHasScroll) && GImGui->NavActivateId == id)
|
||||||
{
|
{
|
||||||
FocusWindow(child_window);
|
FocusWindow(child_window);
|
||||||
NavInitWindow(child_window, false);
|
NavInitWindow(child_window, false);
|
||||||
@ -4227,16 +4228,15 @@ void ImGui::EndChild()
|
|||||||
ImGuiID id = parent_window->GetChildID(window);
|
ImGuiID id = parent_window->GetChildID(window);
|
||||||
ImRect bb(parent_window->DC.CursorPos, parent_window->DC.CursorPos + sz);
|
ImRect bb(parent_window->DC.CursorPos, parent_window->DC.CursorPos + sz);
|
||||||
ItemSize(sz);
|
ItemSize(sz);
|
||||||
ItemAdd(bb, (window->DC.NavLayerActiveFlags != 0 || window->DC.NavHasScroll) ? &id : NULL);
|
if (!(window->Flags & ImGuiWindowFlags_NavFlattened) && (window->DC.NavLayerActiveFlags != 0 || window->DC.NavHasScroll))
|
||||||
if (window->DC.NavLayerActiveFlags != 0 || window->DC.NavHasScroll)
|
|
||||||
{
|
{
|
||||||
//if (!window->DC.NavHasItems && window->DC.NavHasScroll && g.NavWindow == window) // As a special case, we render nav highlight of child when inside when only scrolling is possible
|
ItemAdd(bb, &id);
|
||||||
//{
|
|
||||||
// bb.Expand(-1.0f);
|
|
||||||
// id = g.NavId;
|
|
||||||
//}
|
|
||||||
RenderNavHighlight(id, bb);
|
RenderNavHighlight(id, bb);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ItemAdd(bb, NULL);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4428,6 +4428,9 @@ bool ImGui::Begin(const char* name, bool* p_open, const ImVec2& size_on_first_us
|
|||||||
if (flags & ImGuiWindowFlags_NoInputs)
|
if (flags & ImGuiWindowFlags_NoInputs)
|
||||||
flags |= ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize;
|
flags |= ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize;
|
||||||
|
|
||||||
|
if (flags & ImGuiWindowFlags_NavFlattened)
|
||||||
|
IM_ASSERT(flags & ImGuiWindowFlags_ChildWindow);
|
||||||
|
|
||||||
// Find or create
|
// Find or create
|
||||||
bool window_is_new = false;
|
bool window_is_new = false;
|
||||||
ImGuiWindow* window = FindWindowByName(name);
|
ImGuiWindow* window = FindWindowByName(name);
|
||||||
@ -4524,6 +4527,9 @@ bool ImGui::Begin(const char* name, bool* p_open, const ImVec2& size_on_first_us
|
|||||||
window->ParentWindow = parent_window;
|
window->ParentWindow = parent_window;
|
||||||
window->RootWindow = g.CurrentWindowStack[root_idx];
|
window->RootWindow = g.CurrentWindowStack[root_idx];
|
||||||
window->RootNonPopupWindow = g.CurrentWindowStack[root_non_popup_idx]; // Used to display TitleBgActive color and for selecting which window to use for NavWindowing
|
window->RootNonPopupWindow = g.CurrentWindowStack[root_non_popup_idx]; // Used to display TitleBgActive color and for selecting which window to use for NavWindowing
|
||||||
|
window->RootNavWindow = window;
|
||||||
|
while (window->RootNavWindow->Flags & ImGuiWindowFlags_NavFlattened)
|
||||||
|
window->RootNavWindow = window->RootNavWindow->ParentWindow;
|
||||||
|
|
||||||
// When reusing window again multiple times a frame, just append content (don't need to setup again)
|
// When reusing window again multiple times a frame, just append content (don't need to setup again)
|
||||||
if (first_begin_of_the_frame)
|
if (first_begin_of_the_frame)
|
||||||
|
1
imgui.h
1
imgui.h
@ -511,6 +511,7 @@ enum ImGuiWindowFlags_
|
|||||||
ImGuiWindowFlags_AlwaysUseWindowPadding = 1 << 16, // Ensure child windows without border uses style.WindowPadding (ignored by default for non-bordered child windows, because more convenient)
|
ImGuiWindowFlags_AlwaysUseWindowPadding = 1 << 16, // Ensure child windows without border uses style.WindowPadding (ignored by default for non-bordered child windows, because more convenient)
|
||||||
ImGuiWindowFlags_NoNavFocus = 1 << 17, // No focusing of this window with gamepad/keyboard navigation
|
ImGuiWindowFlags_NoNavFocus = 1 << 17, // No focusing of this window with gamepad/keyboard navigation
|
||||||
ImGuiWindowFlags_NoNavInputs = 1 << 18, // No gamepad/keyboard navigation within the window
|
ImGuiWindowFlags_NoNavInputs = 1 << 18, // No gamepad/keyboard navigation within the window
|
||||||
|
ImGuiWindowFlags_NavFlattened = 1 << 19, // Allow gamepad/keyboard navigation to cross over parent border to this child (only use on child that have no scrolling!)
|
||||||
// [Internal]
|
// [Internal]
|
||||||
ImGuiWindowFlags_ChildWindow = 1 << 20, // Don't use! For internal use by BeginChild()
|
ImGuiWindowFlags_ChildWindow = 1 << 20, // Don't use! For internal use by BeginChild()
|
||||||
ImGuiWindowFlags_ChildWindowAutoFitX = 1 << 21, // Don't use! For internal use by BeginChild()
|
ImGuiWindowFlags_ChildWindowAutoFitX = 1 << 21, // Don't use! For internal use by BeginChild()
|
||||||
|
@ -2443,7 +2443,7 @@ static void ShowExampleAppLayout(bool* p_open)
|
|||||||
ImGui::Separator();
|
ImGui::Separator();
|
||||||
ImGui::TextWrapped("Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. ");
|
ImGui::TextWrapped("Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. ");
|
||||||
ImGui::EndChild();
|
ImGui::EndChild();
|
||||||
ImGui::BeginChild("buttons");
|
ImGui::BeginChild("buttons", ImVec2(0,0), false, ImGuiWindowFlags_NavFlattened);
|
||||||
if (ImGui::Button("Revert")) {}
|
if (ImGui::Button("Revert")) {}
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
if (ImGui::Button("Save")) {}
|
if (ImGui::Button("Save")) {}
|
||||||
|
@ -718,9 +718,10 @@ struct IMGUI_API ImGuiWindow
|
|||||||
ImGuiStorage StateStorage;
|
ImGuiStorage StateStorage;
|
||||||
float FontWindowScale; // Scale multiplier per-window
|
float FontWindowScale; // Scale multiplier per-window
|
||||||
ImDrawList* DrawList;
|
ImDrawList* DrawList;
|
||||||
ImGuiWindow* RootWindow; // If we are a child window, this is pointing to the first non-child parent window. Else point to ourself.
|
|
||||||
ImGuiWindow* RootNonPopupWindow; // Used to display TitleBgActive color and for selecting which window to use for NavWindowing
|
|
||||||
ImGuiWindow* ParentWindow; // Immediate parent in the window stack *regardless* of whether this window is a child window or not)
|
ImGuiWindow* ParentWindow; // Immediate parent in the window stack *regardless* of whether this window is a child window or not)
|
||||||
|
ImGuiWindow* RootWindow; // Generally point to ourself. If we are a child window, this is pointing to the first non-child parent window.
|
||||||
|
ImGuiWindow* RootNonPopupWindow; // Generally point to ourself. Used to display TitleBgActive color and for selecting which window to use for NavWindowing
|
||||||
|
ImGuiWindow* RootNavWindow; // Generally point to ourself. If we are a child window with the ImGuiWindowFlags_NavFlattenedChild flag, point to parent. Used to display TitleBgActive color and for selecting which window to use for NavWindowing.
|
||||||
|
|
||||||
// Navigation / Focus
|
// Navigation / Focus
|
||||||
// FIXME-NAVIGATION: Merge all this with the new Nav system, at least the request variables should be moved to ImGuiContext
|
// FIXME-NAVIGATION: Merge all this with the new Nav system, at least the request variables should be moved to ImGuiContext
|
||||||
@ -746,7 +747,7 @@ public:
|
|||||||
ImRect TitleBarRect() const { return ImRect(Pos, ImVec2(Pos.x + SizeFull.x, Pos.y + TitleBarHeight())); }
|
ImRect TitleBarRect() const { return ImRect(Pos, ImVec2(Pos.x + SizeFull.x, Pos.y + TitleBarHeight())); }
|
||||||
float MenuBarHeight() const { return (Flags & ImGuiWindowFlags_MenuBar) ? CalcFontSize() + GImGui->Style.FramePadding.y * 2.0f : 0.0f; }
|
float MenuBarHeight() const { return (Flags & ImGuiWindowFlags_MenuBar) ? CalcFontSize() + GImGui->Style.FramePadding.y * 2.0f : 0.0f; }
|
||||||
ImRect MenuBarRect() const { float y1 = Pos.y + TitleBarHeight(); return ImRect(Pos.x, y1, Pos.x + SizeFull.x, y1 + MenuBarHeight()); }
|
ImRect MenuBarRect() const { float y1 = Pos.y + TitleBarHeight(); return ImRect(Pos.x, y1, Pos.x + SizeFull.x, y1 + MenuBarHeight()); }
|
||||||
bool IsNavigableTo() const { return Active && this == this->RootNonPopupWindow && (!(Flags & ImGuiWindowFlags_NoNavFocus) || this == GImGui->FocusedWindow); }
|
bool IsNavigableTo() const { return Active && this == RootNonPopupWindow && (!(Flags & ImGuiWindowFlags_NoNavFocus) || this == GImGui->FocusedWindow); }
|
||||||
};
|
};
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
Loading…
Reference in New Issue
Block a user