SetNextWindowPos: added a ImVec2 pivot parameter for positioning a given a center, bottom-right position, etc. As a generalization of SetNextWindowPosCenter() which is now obsolete. This will be useful for combo-like popups as well.

Demo: Simple-overlay window uses the SetWindowPos pivot to select a corner to position itself at.
This commit is contained in:
omar 2017-09-25 18:25:43 +02:00
parent 0a55573288
commit 4b82759598
4 changed files with 46 additions and 27 deletions

View File

@ -204,6 +204,7 @@
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. 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. Also read releases logs https://github.com/ocornut/imgui/releases for more details.
- 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/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).
- renamed IsMouseHoveringAnyWindow() to IsAnyWindowHovered() for consistency. Kept inline redirection function (will obsolete). - renamed IsMouseHoveringAnyWindow() to IsAnyWindowHovered() for consistency. Kept inline redirection function (will obsolete).
@ -1804,7 +1805,7 @@ ImGuiWindow::ImGuiWindow(const char* name)
AutoPosLastDirection = -1; AutoPosLastDirection = -1;
HiddenFrames = 0; HiddenFrames = 0;
SetWindowPosAllowFlags = SetWindowSizeAllowFlags = SetWindowCollapsedAllowFlags = ImGuiCond_Always | ImGuiCond_Once | ImGuiCond_FirstUseEver | ImGuiCond_Appearing; SetWindowPosAllowFlags = SetWindowSizeAllowFlags = SetWindowCollapsedAllowFlags = ImGuiCond_Always | ImGuiCond_Once | ImGuiCond_FirstUseEver | ImGuiCond_Appearing;
SetWindowPosCenterWanted = false; SetWindowPosVal = SetWindowPosPivot = ImVec2(FLT_MAX, FLT_MAX);
LastFrameActive = -1; LastFrameActive = -1;
ItemWidthDefault = 0.0f; ItemWidthDefault = 0.0f;
@ -3619,11 +3620,15 @@ bool ImGui::BeginPopupModal(const char* name, bool* p_open, ImGuiWindowFlags ext
return false; return false;
} }
// Center modal windows by default
if ((window->SetWindowPosAllowFlags & g.SetNextWindowPosCond) == 0)
SetNextWindowPos(g.IO.DisplaySize * 0.5f, ImGuiCond_Appearing, ImVec2(0.5f, 0.5f));
ImGuiWindowFlags flags = extra_flags|ImGuiWindowFlags_Popup|ImGuiWindowFlags_Modal|ImGuiWindowFlags_NoCollapse|ImGuiWindowFlags_NoSavedSettings; ImGuiWindowFlags flags = extra_flags|ImGuiWindowFlags_Popup|ImGuiWindowFlags_Modal|ImGuiWindowFlags_NoCollapse|ImGuiWindowFlags_NoSavedSettings;
bool is_open = ImGui::Begin(name, p_open, flags); bool is_open = ImGui::Begin(name, p_open, flags);
if (!is_open || (p_open && !*p_open)) // NB: is_open can be 'false' when the popup is completely clipped (e.g. zero size display) if (!is_open || (p_open && !*p_open)) // NB: is_open can be 'false' when the popup is completely clipped (e.g. zero size display)
{ {
ImGui::EndPopup(); EndPopup();
if (is_open) if (is_open)
ClosePopup(id); ClosePopup(id);
return false; return false;
@ -3994,9 +3999,12 @@ bool ImGui::Begin(const char* name, bool* p_open, const ImVec2& size_on_first_us
if (window->Appearing) if (window->Appearing)
window->SetWindowPosAllowFlags |= ImGuiCond_Appearing; window->SetWindowPosAllowFlags |= ImGuiCond_Appearing;
window_pos_set_by_api = (window->SetWindowPosAllowFlags & g.SetNextWindowPosCond) != 0; window_pos_set_by_api = (window->SetWindowPosAllowFlags & g.SetNextWindowPosCond) != 0;
if (window_pos_set_by_api && ImLengthSqr(g.SetNextWindowPosVal - ImVec2(-FLT_MAX,-FLT_MAX)) < 0.001f) if (window_pos_set_by_api && ImLengthSqr(g.SetNextWindowPosPivot) > 0.00001f)
{ {
window->SetWindowPosCenterWanted = true; // May be processed on the next frame if this is our first frame and we are measuring size // May be processed on the next frame if this is our first frame and we are measuring size
// FIXME: Look into removing the branch so everything can go through this same codepath for consistency.
window->SetWindowPosVal = g.SetNextWindowPosVal;
window->SetWindowPosPivot = g.SetNextWindowPosPivot;
window->SetWindowPosAllowFlags &= ~(ImGuiCond_Once | ImGuiCond_FirstUseEver | ImGuiCond_Appearing); window->SetWindowPosAllowFlags &= ~(ImGuiCond_Once | ImGuiCond_FirstUseEver | ImGuiCond_Appearing);
} }
else else
@ -4178,13 +4186,11 @@ bool ImGui::Begin(const char* name, bool* p_open, const ImVec2& size_on_first_us
window->Size = window->SizeFull = size_on_first_use; // NB: argument name 'size_on_first_use' misleading here, it's really just 'size' as provided by user passed via BeginChild()->Begin(). window->Size = window->SizeFull = size_on_first_use; // NB: argument name 'size_on_first_use' misleading here, it's really just 'size' as provided by user passed via BeginChild()->Begin().
} }
bool window_pos_center = false; const bool window_pos_with_pivot = (window->SetWindowPosVal.x != FLT_MAX && window->HiddenFrames == 0);
window_pos_center |= (window->SetWindowPosCenterWanted && window->HiddenFrames == 0); if (window_pos_with_pivot)
window_pos_center |= ((flags & ImGuiWindowFlags_Modal) && !window_pos_set_by_api && window_just_appearing_after_hidden_for_resize);
if (window_pos_center)
{ {
// Center (any sort of window) // Position given a pivot (e.g. for centering)
SetWindowPos(window, ImMax(style.DisplaySafeAreaPadding, fullscreen_rect.GetCenter() - window->SizeFull * 0.5f), 0); SetWindowPos(window, ImMax(style.DisplaySafeAreaPadding, window->SetWindowPosVal - window->SizeFull * window->SetWindowPosPivot), 0);
} }
else if (flags & ImGuiWindowFlags_ChildMenu) else if (flags & ImGuiWindowFlags_ChildMenu)
{ {
@ -5010,7 +5016,7 @@ static void SetWindowPos(ImGuiWindow* window, const ImVec2& pos, ImGuiCond cond)
if (cond && (window->SetWindowPosAllowFlags & cond) == 0) if (cond && (window->SetWindowPosAllowFlags & cond) == 0)
return; return;
window->SetWindowPosAllowFlags &= ~(ImGuiCond_Once | ImGuiCond_FirstUseEver | ImGuiCond_Appearing); window->SetWindowPosAllowFlags &= ~(ImGuiCond_Once | ImGuiCond_FirstUseEver | ImGuiCond_Appearing);
window->SetWindowPosCenterWanted = false; window->SetWindowPosVal = ImVec2(FLT_MAX, FLT_MAX);
// Set // Set
const ImVec2 old_pos = window->Pos; const ImVec2 old_pos = window->Pos;
@ -5133,19 +5139,20 @@ void ImGui::SetWindowFocus(const char* name)
} }
} }
void ImGui::SetNextWindowPos(const ImVec2& pos, ImGuiCond cond) void ImGui::SetNextWindowPos(const ImVec2& pos, ImGuiCond cond, const ImVec2& pivot)
{ {
ImGuiContext& g = *GImGui; ImGuiContext& g = *GImGui;
g.SetNextWindowPosVal = pos; g.SetNextWindowPosVal = pos;
g.SetNextWindowPosPivot = pivot;
g.SetNextWindowPosCond = cond ? cond : ImGuiCond_Always; g.SetNextWindowPosCond = cond ? cond : ImGuiCond_Always;
} }
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
void ImGui::SetNextWindowPosCenter(ImGuiCond cond) void ImGui::SetNextWindowPosCenter(ImGuiCond cond)
{ {
ImGuiContext& g = *GImGui; SetNextWindowPos(ImGui::GetIO().DisplaySize * 0.5f, cond, ImVec2(0.5f, 0.5f));
g.SetNextWindowPosVal = ImVec2(-FLT_MAX, -FLT_MAX);
g.SetNextWindowPosCond = cond ? cond : ImGuiCond_Always;
} }
#endif
void ImGui::SetNextWindowSize(const ImVec2& size, ImGuiCond cond) void ImGui::SetNextWindowSize(const ImVec2& size, ImGuiCond cond)
{ {

View File

@ -152,8 +152,7 @@ namespace ImGui
IMGUI_API bool IsWindowAppearing(); IMGUI_API bool IsWindowAppearing();
IMGUI_API void SetWindowFontScale(float scale); // per-window font scale. Adjust IO.FontGlobalScale if you want to scale all windows IMGUI_API void SetWindowFontScale(float scale); // per-window font scale. Adjust IO.FontGlobalScale if you want to scale all windows
IMGUI_API void SetNextWindowPos(const ImVec2& pos, ImGuiCond cond = 0); // set next window position. call before Begin() IMGUI_API void SetNextWindowPos(const ImVec2& pos, ImGuiCond cond = 0, const ImVec2& pivot = ImVec2(0,0)); // set next window position. call before Begin(). use pivot=(0.5f,0.5f) to center on given point, etc.
IMGUI_API void SetNextWindowPosCenter(ImGuiCond cond = 0); // set next window position to be centered on screen. call before Begin()
IMGUI_API void SetNextWindowSize(const ImVec2& size, ImGuiCond cond = 0); // set next window size. set axis to 0.0f to force an auto-fit on this axis. call before Begin() IMGUI_API void SetNextWindowSize(const ImVec2& size, ImGuiCond cond = 0); // set next window size. set axis to 0.0f to force an auto-fit on this axis. call before Begin()
IMGUI_API void SetNextWindowSizeConstraints(const ImVec2& size_min, const ImVec2& size_max, ImGuiSizeConstraintCallback custom_callback = NULL, void* custom_callback_data = NULL); // set next window size limits. use -1,-1 on either X/Y axis to preserve the current size. Use callback to apply non-trivial programmatic constraints. IMGUI_API void SetNextWindowSizeConstraints(const ImVec2& size_min, const ImVec2& size_max, ImGuiSizeConstraintCallback custom_callback = NULL, void* custom_callback_data = NULL); // set next window size limits. use -1,-1 on either X/Y axis to preserve the current size. Use callback to apply non-trivial programmatic constraints.
IMGUI_API void SetNextWindowContentSize(const ImVec2& size); // set next window content size (enforce the range of scrollbars). set axis to 0.0f to leave it automatic. call before Begin() IMGUI_API void SetNextWindowContentSize(const ImVec2& size); // set next window content size (enforce the range of scrollbars). set axis to 0.0f to leave it automatic. call before Begin()
@ -489,6 +488,7 @@ namespace ImGui
// Obsolete functions (Will be removed! Also see 'API BREAKING CHANGES' section in imgui.cpp) // Obsolete functions (Will be removed! Also see 'API BREAKING CHANGES' section in imgui.cpp)
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS #ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
static void SetNextWindowPosCenter(ImGuiCond cond = 0); // OBSOLETE 1.52+
static inline bool IsItemHoveredRect() { return IsItemRectHovered(); } // OBSOLETE 1.51+ static inline bool IsItemHoveredRect() { return IsItemRectHovered(); } // OBSOLETE 1.51+
static inline bool IsPosHoveringAnyWindow(const ImVec2&) { IM_ASSERT(0); return false; } // OBSOLETE 1.51+. This was partly broken. You probably wanted to use ImGui::GetIO().WantCaptureMouse instead. static inline bool IsPosHoveringAnyWindow(const ImVec2&) { IM_ASSERT(0); return false; } // OBSOLETE 1.51+. This was partly broken. You probably wanted to use ImGui::GetIO().WantCaptureMouse instead.
static inline bool IsMouseHoveringAnyWindow() { return IsAnyWindowHovered(); } // OBSOLETE 1.51+ static inline bool IsMouseHoveringAnyWindow() { return IsAnyWindowHovered(); } // OBSOLETE 1.51+

View File

@ -2114,20 +2114,30 @@ static void ShowExampleAppConstrainedResize(bool* p_open)
ImGui::End(); ImGui::End();
} }
// Demonstrate creating a simple static window with no decoration. // Demonstrate creating a simple static window with no decoration + a context-menu to choose which corner of the screen to use.
static void ShowExampleAppFixedOverlay(bool* p_open) static void ShowExampleAppFixedOverlay(bool* p_open)
{ {
ImGui::SetNextWindowPos(ImVec2(10,10)); const float DISTANCE = 10.0f;
static int corner = 0;
ImVec2 window_pos = ImVec2((corner & 1) ? ImGui::GetIO().DisplaySize.x - DISTANCE : DISTANCE, (corner & 2) ? ImGui::GetIO().DisplaySize.y - DISTANCE : DISTANCE);
ImVec2 window_pos_pivot = ImVec2((corner & 1) ? 1.0f : 0.0f, (corner & 2) ? 1.0f : 0.0f);
ImGui::SetNextWindowPos(window_pos, ImGuiCond_Always, window_pos_pivot);
ImGui::PushStyleColor(ImGuiCol_WindowBg, ImVec4(0.0f, 0.0f, 0.0f, 0.3f)); ImGui::PushStyleColor(ImGuiCol_WindowBg, ImVec4(0.0f, 0.0f, 0.0f, 0.3f));
if (!ImGui::Begin("Example: Fixed Overlay", p_open, ImGuiWindowFlags_NoTitleBar|ImGuiWindowFlags_NoResize|ImGuiWindowFlags_NoMove|ImGuiWindowFlags_NoSavedSettings)) if (ImGui::Begin("Example: Fixed Overlay", p_open, ImGuiWindowFlags_NoTitleBar|ImGuiWindowFlags_NoResize|ImGuiWindowFlags_NoMove|ImGuiWindowFlags_NoSavedSettings))
{ {
ImGui::End(); ImGui::Text("Simple overlay\nin the corner of the screen.\n(right-click to change position)");
return;
}
ImGui::Text("Simple overlay\non the top-left side of the screen.");
ImGui::Separator(); ImGui::Separator();
ImGui::Text("Mouse Position: (%.1f,%.1f)", ImGui::GetIO().MousePos.x, ImGui::GetIO().MousePos.y); ImGui::Text("Mouse Position: (%.1f,%.1f)", ImGui::GetIO().MousePos.x, ImGui::GetIO().MousePos.y);
if (ImGui::BeginPopupContextWindow())
{
if (ImGui::MenuItem("Top-left", NULL, corner == 0)) corner = 0;
if (ImGui::MenuItem("Top-right", NULL, corner == 1)) corner = 1;
if (ImGui::MenuItem("Bottom-left", NULL, corner == 2)) corner = 2;
if (ImGui::MenuItem("Bottom-right", NULL, corner == 3)) corner = 3;
ImGui::EndPopup();
}
ImGui::End(); ImGui::End();
}
ImGui::PopStyleColor(); ImGui::PopStyleColor();
} }

View File

@ -437,6 +437,7 @@ struct ImGuiContext
// Storage for SetNexWindow** and SetNextTreeNode*** functions // Storage for SetNexWindow** and SetNextTreeNode*** functions
ImVec2 SetNextWindowPosVal; ImVec2 SetNextWindowPosVal;
ImVec2 SetNextWindowPosPivot;
ImVec2 SetNextWindowSizeVal; ImVec2 SetNextWindowSizeVal;
ImVec2 SetNextWindowContentSizeVal; ImVec2 SetNextWindowContentSizeVal;
bool SetNextWindowCollapsedVal; bool SetNextWindowCollapsedVal;
@ -696,7 +697,8 @@ struct IMGUI_API ImGuiWindow
ImGuiCond SetWindowPosAllowFlags; // store condition flags for next SetWindowPos() call. ImGuiCond SetWindowPosAllowFlags; // store condition flags for next SetWindowPos() call.
ImGuiCond SetWindowSizeAllowFlags; // store condition flags for next SetWindowSize() call. ImGuiCond SetWindowSizeAllowFlags; // store condition flags for next SetWindowSize() call.
ImGuiCond SetWindowCollapsedAllowFlags; // store condition flags for next SetWindowCollapsed() call. ImGuiCond SetWindowCollapsedAllowFlags; // store condition flags for next SetWindowCollapsed() call.
bool SetWindowPosCenterWanted; ImVec2 SetWindowPosVal; // store window position when using a non-zero Pivot (position set needs to be processed when we know the window size)
ImVec2 SetWindowPosPivot; // store window pivot for positioning. ImVec2(0,0) when positioning from top-left corner; ImVec2(0.5f,0.5f) for centering; ImVec2(1,1) for bottom right.
ImGuiDrawContext DC; // Temporary per-window data, reset at the beginning of the frame ImGuiDrawContext DC; // Temporary per-window data, reset at the beginning of the frame
ImVector<ImGuiID> IDStack; // ID stack. ID are hashes seeded with the value at the top of the stack ImVector<ImGuiID> IDStack; // ID stack. ID are hashes seeded with the value at the top of the stack