Merge branch 'master' into navigation

# Conflicts:
#	imgui.cpp
#	imgui.h
#	imgui_demo.cpp
#	imgui_internal.h
This commit is contained in:
omar
2017-10-20 18:10:07 +02:00
3 changed files with 170 additions and 102 deletions

148
imgui.cpp
View File

@ -252,11 +252,13 @@
Here is a change-log of API breaking changes, if you are using one of the functions listed, expect to have to fix some code.
Also read releases logs https://github.com/ocornut/imgui/releases for more details.
- 2017/10/20 (1.52) - changed IsWindowHovered() default parameters behavior to return false if a popup window is blocking access to the window or an item is active in another window. You can use the newly introduced IsWindowHovered() flags to requests those specific behavior if you need them.
- 2017/10/20 (1.52) - removed the IsItemRectHovered()/IsWindowRectHovered() names introduced in 1.51, the new flags available for IsItemHovered() and IsWindowHovered() are providing much more details/options, and those legacy entry points were confusing/misleading.
- 2017/10/17 (1.52) - marked the old 5-parameters version of Begin() as obsolete (still available). Use SetNextWindowSize()+Begin() instead!
- 2017/10/11 (1.52) - renamed AlignFirstTextHeightToWidgets() to AlignTextToFramePadding(). Kept inline redirection function (will obsolete).
- 2017/09/25 (1.52) - removed SetNextWindowPosCenter() because SetNextWindowPos() now has the optional pivot information to do the same and more. Kept redirection function (will obsolete).
- 2017/08/25 (1.52) - io.MousePos needs to be set to ImVec2(-FLT_MAX,-FLT_MAX) when mouse is unavailable/missing. Previously ImVec2(-1,-1) was enough but we now accept negative mouse coordinates. In your binding if you need to support unavailable mouse, make sure to replace "io.MousePos = ImVec2(-1,-1)" with "io.MousePos = ImVec2(-FLT_MAX,-FLT_MAX)".
- 2017/08/22 (1.51) - renamed IsItemHoveredRect() to IsItemRectHovered(). Kept inline redirection function (will obsolete).
- 2017/08/22 (1.51) - renamed IsItemHoveredRect() to IsItemRectHovered(). Kept inline redirection function (will obsolete). -> (1.52) use IsItemHovered(ImGuiHoveredFlags_RectOnly)!
- renamed IsMouseHoveringAnyWindow() to IsAnyWindowHovered() for consistency. Kept inline redirection function (will obsolete).
- renamed IsMouseHoveringWindow() to IsWindowRectHovered() for consistency. Kept inline redirection function (will obsolete).
- 2017/08/20 (1.51) - renamed GetStyleColName() to GetStyleColorName() for consistency.
@ -681,7 +683,7 @@ static void MarkIniSettingsDirty(ImGuiWindow* window);
static ImRect GetVisibleRect();
static void CloseInactivePopups();
static void CloseInactivePopups(ImGuiWindow* ref_window);
static void ClosePopupToLevel(int remaining);
static ImGuiWindow* GetFrontMostModalRootWindow();
static ImVec2 FindBestPopupWindowPos(const ImVec2& base_pos, const ImVec2& size, int* last_dir, const ImRect& rect_to_avoid);
@ -2055,15 +2057,22 @@ void ImGui::KeepAliveID(ImGuiID id)
g.ActiveIdIsAlive = true;
}
static inline bool IsWindowContentHoverable(ImGuiWindow* window)
static inline bool IsWindowContentHoverable(ImGuiWindow* window, ImGuiHoveredFlags flags)
{
// An active popup disable hovering on other windows (apart from its own children)
// FIXME-OPT: This could be cached/stored within the window.
ImGuiContext& g = *GImGui;
if (g.NavWindow)
if (ImGuiWindow* focused_root_window = g.NavWindow->RootWindow)
if ((focused_root_window->Flags & ImGuiWindowFlags_Popup) != 0 && focused_root_window->WasActive && focused_root_window != window->RootWindow)
return false;
if (focused_root_window->WasActive && focused_root_window != window->RootWindow)
{
// For the purpose of those flags we differentiate "standard popup" from "modal popup"
// NB: The order of those two tests is important because Modal windows are also Popups.
if (focused_root_window->Flags & ImGuiWindowFlags_Modal)
return false;
if ((focused_root_window->Flags & ImGuiWindowFlags_Popup) && !(flags & ImGuiHoveredFlags_AllowWhenBlockedByPopup))
return false;
}
return true;
}
@ -2336,7 +2345,7 @@ bool ImGui::ItemAdd(const ImRect& bb, ImGuiID id, const ImRect* nav_bb_arg)
// This is roughly matching the behavior of internal-facing ItemHoverable()
// - we allow hovering to be true when ActiveId==window->MoveID, so that clicking on non-interactive items such as a Text() item still returns true with IsItemHovered())
// - this should work even for non-interactive items that have no ID, so we cannot use LastItemId
bool ImGui::IsItemHovered()
bool ImGui::IsItemHovered(ImGuiHoveredFlags flags)
{
ImGuiContext& g = *GImGui;
@ -2350,21 +2359,16 @@ bool ImGui::IsItemHovered()
// Until a solution is found I believe reverting to the test from 2017/09/27 is safe since this was the test that has been running for a long while.
//if (g.HoveredWindow != window)
// return false;
if (g.HoveredRootWindow != window->RootWindow)
if (g.HoveredRootWindow != window->RootWindow && !(flags & ImGuiHoveredFlags_AllowWhenOverlapped))
return false;
if (g.ActiveId != 0 && g.ActiveId != window->DC.LastItemId && !g.ActiveIdAllowOverlap && g.ActiveId != window->MoveId)
return false;
if (g.NavDisableMouseHover || !IsWindowContentHoverable(window))
if (!(flags & ImGuiHoveredFlags_AllowWhenBlockedByActiveItem))
if (g.ActiveId != 0 && g.ActiveId != window->DC.LastItemId && !g.ActiveIdAllowOverlap && g.ActiveId != window->MoveId)
return false;
if (g.NavDisableMouseHover || !IsWindowContentHoverable(window, flags))
return false;
return true;
}
bool ImGui::IsItemRectHovered()
{
ImGuiWindow* window = GetCurrentWindowRead();
return window->DC.LastItemRectHoveredRect;
}
// Internal facing ItemHoverable() used when submitting widgets. Differs slightly from IsItemHovered().
bool ImGui::ItemHoverable(const ImRect& bb, ImGuiID id)
{
@ -2379,7 +2383,7 @@ bool ImGui::ItemHoverable(const ImRect& bb, ImGuiID id)
return false;
if (!IsMouseHoveringRect(bb.Min, bb.Max))
return false;
if (g.NavDisableMouseHover || !IsWindowContentHoverable(window))
if (!g.NavDisableMouseHover || !IsWindowContentHoverable(window, ImGuiHoveredFlags_Default))
return false;
SetHoveredID(id);
@ -3236,7 +3240,7 @@ void ImGui::NewFrame()
// But in order to allow the user to call NewFrame() multiple times without calling Render(), we are doing an explicit clear.
g.CurrentWindowStack.resize(0);
g.CurrentPopupStack.resize(0);
CloseInactivePopups();
CloseInactivePopups(g.NavWindow);
// Create implicit window - we will only render it if the user has added something to it.
// We don't use "Debug" to avoid colliding with user trying to create a "Debug" window with custom flags.
@ -3566,33 +3570,43 @@ void ImGui::EndFrame()
g.CurrentWindow->Active = false;
ImGui::End();
// Click to focus window and start moving (after we're done with all our widgets)
if (g.ActiveId == 0 && g.HoveredId == 0 && g.IO.MouseClicked[0])
if (g.ActiveId == 0 && g.HoveredId == 0)
{
if (!(g.NavWindow && !g.NavWindow->WasActive && g.NavWindow->Active)) // Unless we just made a popup appear
if (!g.NavWindow || !g.NavWindow->Appearing) // Unless we just made a window/popup appear
{
if (g.HoveredRootWindow != NULL)
// Click to focus window and start moving (after we're done with all our widgets)
if (g.IO.MouseClicked[0])
{
FocusWindow(g.HoveredWindow);
// FIXME-NAV: This never execute because of the FocusWindow call above, however we may might this behavior?
/*
if (g.NavWindow != g.HoveredWindow)
if (g.HoveredRootWindow != NULL)
{
g.NavRefRectRel = ImRect(g.IO.MousePos - g.HoveredWindow->Pos, g.IO.MousePos - g.HoveredWindow->Pos); //ImRect(0,0,0,0);
g.NavDisableHighlight = true;
FocusWindow(g.HoveredWindow);
// FIXME-NAV: This never execute because of the FocusWindow call above, however we may might this behavior?
/*
if (g.NavWindow != g.HoveredWindow)
{
g.NavRefRectRel = ImRect(g.IO.MousePos - g.HoveredWindow->Pos, g.IO.MousePos - g.HoveredWindow->Pos); //ImRect(0,0,0,0);
g.NavDisableHighlight = true;
}
*/
if (!(g.HoveredWindow->Flags & ImGuiWindowFlags_NoMove) && !(g.HoveredRootWindow->Flags & ImGuiWindowFlags_NoMove))
{
g.MovedWindow = g.HoveredWindow;
g.MovedWindowMoveId = g.HoveredWindow->MoveId;
SetActiveID(g.MovedWindowMoveId, g.HoveredRootWindow);
}
}
*/
if (!(g.HoveredWindow->Flags & ImGuiWindowFlags_NoMove))
else if (g.NavWindow != NULL && GetFrontMostModalRootWindow() == NULL)
{
g.MovedWindow = g.HoveredWindow;
g.MovedWindowMoveId = g.HoveredWindow->MoveId;
SetActiveID(g.MovedWindowMoveId, g.HoveredRootWindow);
// Clicking on void disable focus
FocusWindow(NULL);
}
}
else if (g.NavWindow != NULL && GetFrontMostModalRootWindow() == NULL)
// With right mouse button we close popups without changing focus
// (The left mouse button path calls FocusWindow which will lead NewFrame->CloseInactivePopups to trigger)
if (g.IO.MouseClicked[1])
{
// Clicking on void disable focus
FocusWindow(NULL);
CloseInactivePopups(g.HoveredWindow);
}
}
}
@ -4425,7 +4439,7 @@ void ImGui::OpenPopup(const char* str_id)
OpenPopupEx(g.CurrentWindow->GetID(str_id), false);
}
static void CloseInactivePopups()
static void CloseInactivePopups(ImGuiWindow* ref_window)
{
ImGuiContext& g = *GImGui;
if (g.OpenPopupStack.empty())
@ -4434,7 +4448,7 @@ static void CloseInactivePopups()
// When popups are stacked, clicking on a lower level popups puts focus back to it and close popups above it.
// Don't close our own child popup windows
int n = 0;
if (g.NavWindow)
if (ref_window)
{
for (n = 0; n < g.OpenPopupStack.Size; n++)
{
@ -4447,7 +4461,7 @@ static void CloseInactivePopups()
bool has_focus = false;
for (int m = n; m < g.OpenPopupStack.Size && !has_focus; m++)
has_focus = (g.OpenPopupStack[m].Window && g.OpenPopupStack[m].Window->RootWindow == g.NavWindow->RootWindow);
has_focus = (g.OpenPopupStack[m].Window && g.OpenPopupStack[m].Window->RootWindow == ref_window->RootWindow);
if (!has_focus)
break;
}
@ -4623,9 +4637,10 @@ bool ImGui::BeginPopupContextItem(const char* str_id, int mouse_button)
ImGuiWindow* window = GImGui->CurrentWindow;
ImGuiID id = str_id ? window->GetID(str_id) : window->DC.LastItemId; // If user hasn't passed an ID, we can use the LastItemID. Using LastItemID as a Popup ID won't conflict!
IM_ASSERT(id != 0); // However, you cannot pass a NULL str_id if the last item has no identifier (e.g. a Text() item)
if (IsItemHovered() && IsMouseClicked(mouse_button))
OpenPopupEx(id, false);
return BeginPopupEx(id, 0);
if (IsMouseClicked(mouse_button))
if (IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup))
OpenPopupEx(id, true);
return BeginPopupEx(id, ImGuiWindowFlags_ShowBorders | ImGuiWindowFlags_AlwaysAutoResize);
}
bool ImGui::BeginPopupContextWindow(const char* str_id, int mouse_button, bool also_over_items)
@ -4633,10 +4648,11 @@ bool ImGui::BeginPopupContextWindow(const char* str_id, int mouse_button, bool a
if (!str_id)
str_id = "window_context";
ImGuiID id = GImGui->CurrentWindow->GetID(str_id);
if (IsWindowRectHovered() && IsMouseClicked(mouse_button))
if (also_over_items || !IsAnyItemHovered())
OpenPopupEx(id, true);
return BeginPopupEx(id, 0);
if (IsMouseClicked(mouse_button))
if (IsWindowHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup))
if (also_over_items || !IsAnyItemHovered())
OpenPopupEx(id, true);
return BeginPopupEx(id, ImGuiWindowFlags_ShowBorders | ImGuiWindowFlags_AlwaysAutoResize);
}
bool ImGui::BeginPopupContextVoid(const char* str_id, int mouse_button)
@ -4646,7 +4662,7 @@ bool ImGui::BeginPopupContextVoid(const char* str_id, int mouse_button)
ImGuiID id = GImGui->CurrentWindow->GetID(str_id);
if (!IsAnyWindowHovered() && IsMouseClicked(mouse_button))
OpenPopupEx(id, true);
return BeginPopupEx(id, 0);
return BeginPopupEx(id, ImGuiWindowFlags_ShowBorders | ImGuiWindowFlags_AlwaysAutoResize);
}
static bool BeginChildEx(const char* name, ImGuiID id, const ImVec2& size_arg, bool border, ImGuiWindowFlags extra_flags)
@ -4654,6 +4670,7 @@ static bool BeginChildEx(const char* name, ImGuiID id, const ImVec2& size_arg, b
ImGuiContext& g = *GImGui;
ImGuiWindow* parent_window = ImGui::GetCurrentWindow();
ImGuiWindowFlags flags = ImGuiWindowFlags_NoTitleBar|ImGuiWindowFlags_NoResize|ImGuiWindowFlags_NoSavedSettings|ImGuiWindowFlags_ChildWindow;
flags |= (parent_window->Flags & ImGuiWindowFlags_NoMove); // Inherit the NoMove flag
const ImVec2 content_avail = ImGui::GetContentRegionAvail();
ImVec2 size = ImFloor(size_arg);
@ -6051,16 +6068,18 @@ const char* ImGui::GetStyleColorName(ImGuiCol idx)
return "Unknown";
}
bool ImGui::IsWindowHovered()
bool ImGui::IsWindowHovered(ImGuiHoveredFlags flags)
{
IM_ASSERT((flags & ImGuiHoveredFlags_AllowWhenOverlapped) == 0); // Flags not supported by this function
ImGuiContext& g = *GImGui;
return g.HoveredWindow == g.CurrentWindow && IsWindowContentHoverable(g.HoveredRootWindow);
}
bool ImGui::IsWindowRectHovered()
{
ImGuiContext& g = *GImGui;
return g.HoveredWindow == g.CurrentWindow;
if (g.HoveredWindow != g.CurrentWindow)
return false;
if (!IsWindowContentHoverable(g.HoveredRootWindow, flags))
return false;
if (!(flags & ImGuiHoveredFlags_AllowWhenBlockedByActiveItem))
if (g.ActiveId != 0 && g.ActiveIdWindow != g.CurrentWindow)
return false;
return true;
}
bool ImGui::IsWindowFocused()
@ -6081,10 +6100,18 @@ bool ImGui::IsRootWindowOrAnyChildFocused()
return g.NavWindow && g.NavWindow->RootWindow == g.CurrentWindow->RootWindow;
}
bool ImGui::IsRootWindowOrAnyChildHovered()
bool ImGui::IsRootWindowOrAnyChildHovered(ImGuiHoveredFlags flags)
{
IM_ASSERT((flags & ImGuiHoveredFlags_AllowWhenOverlapped) == 0); // Flags not supported by this function
ImGuiContext& g = *GImGui;
return g.HoveredRootWindow && (g.HoveredRootWindow == g.CurrentWindow->RootWindow) && IsWindowContentHoverable(g.HoveredRootWindow);
if (!g.HoveredRootWindow || (g.HoveredRootWindow != g.CurrentWindow->RootWindow))
return false;
if (!IsWindowContentHoverable(g.HoveredRootWindow, flags))
return false;
if (!(flags & ImGuiHoveredFlags_AllowWhenBlockedByActiveItem))
if (g.ActiveId != 0 && g.ActiveIdWindow != g.CurrentWindow)
return false;
return true;
}
float ImGui::GetWindowWidth()
@ -6256,13 +6283,6 @@ void ImGui::SetNextWindowPos(const ImVec2& pos, ImGuiCond cond, const ImVec2& pi
g.SetNextWindowPosCond = cond ? cond : ImGuiCond_Always;
}
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
void ImGui::SetNextWindowPosCenter(ImGuiCond cond)
{
SetNextWindowPos(GetIO().DisplaySize * 0.5f, cond, ImVec2(0.5f, 0.5f));
}
#endif
void ImGui::SetNextWindowSize(const ImVec2& size, ImGuiCond cond)
{
ImGuiContext& g = *GImGui;