Obsoleted using SetCursorPos()/SetCursorScreenPos() to extend parent window/cell boundaries. (#5548)

This incorrect pattern has been mentioned or suggested in: #4510, #3355, #1760, #1490, #4152, #150
This commit is contained in:
ocornut 2022-08-05 21:19:12 +02:00
parent 5867a43dc8
commit edcd5b113e
5 changed files with 78 additions and 8 deletions

View File

@ -60,6 +60,20 @@ Breaking changes:
- requires an explicit identifier. You may still use e.g. PushID() calls and then pass an empty identifier. - requires an explicit identifier. You may still use e.g. PushID() calls and then pass an empty identifier.
- always uses style.FramePadding for padding, to be consistent with other buttons. You may use PushStyleVar() to alter this. - always uses style.FramePadding for padding, to be consistent with other buttons. You may use PushStyleVar() to alter this.
- As always we are keeping a redirection function available (will obsolete later). - As always we are keeping a redirection function available (will obsolete later).
- Obsoleted using SetCursorPos()/SetCursorScreenPos() to extend parent window/cell boundaries. (#5548)
This relates to when moving the cursor position beyond current boundaries WITHOUT submitting an item.
- Previously this would make the window content size ~200x200:
Begin(...) + SetCursorScreenPos(GetCursorScreenPos() + ImVec2(200,200)) + End();
- Instead, please submit an item:
Begin(...) + SetCursorScreenPos(GetCursorScreenPos() + ImVec2(200,200)) + Dummy(ImVec2(0,0)) + End();
- Alternative:
Begin(...) + Dummy(ImVec2(200,200)) + End();
Content size is now only extended when submitting an item.
With '#define IMGUI_DISABLE_OBSOLETE_FUNCTIONS' this will now be detected and assert.
Without '#define IMGUI_DISABLE_OBSOLETE_FUNCTIONS' this will silently be fixed until we obsolete it.
(This incorrect pattern has been mentioned or suggested in: #4510, #3355, #1760, #1490, #4152, #150,
threads have been amended to refer to this issue).
Other Changes: Other Changes:

View File

@ -384,6 +384,17 @@ CODE
When you are not sure about an old symbol or function name, try using the Search/Find function of your IDE to look for comments or references in all imgui files. When you are not sure about an old symbol or function name, try using the Search/Find function of your IDE to look for comments or references in all imgui files.
You can read releases logs https://github.com/ocornut/imgui/releases for more details. You can read releases logs https://github.com/ocornut/imgui/releases for more details.
- 2022/09/02 (1.89) - obsoleted using SetCursorPos()/SetCursorScreenPos() to extend parent window/cell boundaries.
this relates to when moving the cursor position beyond current boundaries WITHOUT submitting an item.
- previously this would make the window content size ~200x200:
Begin(...) + SetCursorScreenPos(GetCursorScreenPos() + ImVec2(200,200)) + End();
- instead, please submit an item:
Begin(...) + SetCursorScreenPos(GetCursorScreenPos() + ImVec2(200,200)) + Dummy(ImVec2(0,0)) + End();
- alternative:
Begin(...) + Dummy(ImVec2(200,200)) + End();
- content size is now only extended when submitting an item!
- with '#define IMGUI_DISABLE_OBSOLETE_FUNCTIONS' this will now be detected and assert.
- without '#define IMGUI_DISABLE_OBSOLETE_FUNCTIONS' this will silently be fixed until we obsolete it.
- 2022/08/03 (1.89) - changed signature of ImageButton() function. Kept redirection function (will obsolete). - 2022/08/03 (1.89) - changed signature of ImageButton() function. Kept redirection function (will obsolete).
- added 'const char* str_id' parameter + removed 'int frame_padding = -1' parameter. - added 'const char* str_id' parameter + removed 'int frame_padding = -1' parameter.
- old signature: bool ImageButton(ImTextureID tex_id, ImVec2 size, ImVec2 uv0 = ImVec2(0,0), ImVec2 uv1 = ImVec2(1,1), int frame_padding = -1, ImVec4 bg_col = ImVec4(0,0,0,0), ImVec4 tint_col = ImVec4(1,1,1,1)); - old signature: bool ImageButton(ImTextureID tex_id, ImVec2 size, ImVec2 uv0 = ImVec2(0,0), ImVec2 uv1 = ImVec2(1,1), int frame_padding = -1, ImVec4 bg_col = ImVec4(0,0,0,0), ImVec4 tint_col = ImVec4(1,1,1,1));
@ -6690,7 +6701,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
window->DC.IdealMaxPos = window->DC.CursorStartPos; window->DC.IdealMaxPos = window->DC.CursorStartPos;
window->DC.CurrLineSize = window->DC.PrevLineSize = ImVec2(0.0f, 0.0f); window->DC.CurrLineSize = window->DC.PrevLineSize = ImVec2(0.0f, 0.0f);
window->DC.CurrLineTextBaseOffset = window->DC.PrevLineTextBaseOffset = 0.0f; window->DC.CurrLineTextBaseOffset = window->DC.PrevLineTextBaseOffset = 0.0f;
window->DC.IsSameLine = false; window->DC.IsSameLine = window->DC.IsSetPos = false;
window->DC.NavLayerCurrent = ImGuiNavLayer_Main; window->DC.NavLayerCurrent = ImGuiNavLayer_Main;
window->DC.NavLayersActiveMask = window->DC.NavLayersActiveMaskNext; window->DC.NavLayersActiveMask = window->DC.NavLayersActiveMaskNext;
@ -6841,6 +6852,9 @@ void ImGui::End()
if (!(window->Flags & ImGuiWindowFlags_ChildWindow)) // FIXME: add more options for scope of logging if (!(window->Flags & ImGuiWindowFlags_ChildWindow)) // FIXME: add more options for scope of logging
LogFinish(); LogFinish();
if (window->DC.IsSetPos)
ErrorCheckUsingSetCursorPosToExtendParentBoundaries();
// Pop from window stack // Pop from window stack
g.LastItemData = g.CurrentWindowStack.back().ParentLastItemDataBackup; g.LastItemData = g.CurrentWindowStack.back().ParentLastItemDataBackup;
if (window->Flags & ImGuiWindowFlags_ChildMenu) if (window->Flags & ImGuiWindowFlags_ChildMenu)
@ -8229,6 +8243,36 @@ bool ImGui::DebugCheckVersionAndDataLayout(const char* version, size_t sz_io, si
return !error; return !error;
} }
// Until 1.89 (IMGUI_VERSION_NUM < 18814) it was legal to use SetCursorPos() to extend the boundary of a parent (e.g. window or table cell)
// This is causing issues and ambiguity and we need to retire that.
// See https://github.com/ocornut/imgui/issues/5548 for more details.
// [Scenario 1]
// Previously this would make the window content size ~200x200:
// Begin(...) + SetCursorScreenPos(GetCursorScreenPos() + ImVec2(200,200)) + End(); // NOT OK
// Instead, please submit an item:
// Begin(...) + SetCursorScreenPos(GetCursorScreenPos() + ImVec2(200,200)) + Dummy(ImVec2(0,0)) + End(); // OK
// Alternative:
// Begin(...) + Dummy(ImVec2(200,200)) + End(); // OK
// [Scenario 2]
// For reference this is one of the issue what we aim to fix with this change:
// BeginGroup() + SomeItem("foobar") + SetCursorScreenPos(GetCursorScreenPos()) + EndGroup()
// The previous logic made SetCursorScreenPos(GetCursorScreenPos()) have a side-effect! It would erroneously incorporate ItemSpacing.y after the item into content size, making the group taller!
// While this code is a little twisted, no-one would expect SetXXX(GetXXX()) to have a side-effect. Using vertical alignment patterns could trigger this issue.
void ImGui::ErrorCheckUsingSetCursorPosToExtendParentBoundaries()
{
ImGuiContext& g = *GImGui;
ImGuiWindow* window = g.CurrentWindow;
IM_ASSERT(window->DC.IsSetPos);
window->DC.IsSetPos = false;
#ifdef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
if (window->DC.CursorPos.x <= window->DC.CursorMaxPos.x && window->DC.CursorPos.y <= window->DC.CursorMaxPos.y)
return;
IM_ASSERT(0 && "Code uses SetCursorPos()/SetCursorScreenPos() to extend window/parent boundaries. Please submit an item e.g. Dummy() to validate extent.");
#else
window->DC.CursorMaxPos = ImMax(window->DC.CursorMaxPos, window->DC.CursorPos);
#endif
}
static void ImGui::ErrorCheckNewFrameSanityChecks() static void ImGui::ErrorCheckNewFrameSanityChecks()
{ {
ImGuiContext& g = *GImGui; ImGuiContext& g = *GImGui;
@ -8499,7 +8543,7 @@ void ImGui::ItemSize(const ImVec2& size, float text_baseline_y)
window->DC.CurrLineSize.y = 0.0f; window->DC.CurrLineSize.y = 0.0f;
window->DC.PrevLineTextBaseOffset = ImMax(window->DC.CurrLineTextBaseOffset, text_baseline_y); window->DC.PrevLineTextBaseOffset = ImMax(window->DC.CurrLineTextBaseOffset, text_baseline_y);
window->DC.CurrLineTextBaseOffset = 0.0f; window->DC.CurrLineTextBaseOffset = 0.0f;
window->DC.IsSameLine = false; window->DC.IsSameLine = window->DC.IsSetPos = false;
// Horizontal layout mode // Horizontal layout mode
if (window->DC.LayoutType == ImGuiLayoutType_Horizontal) if (window->DC.LayoutType == ImGuiLayoutType_Horizontal)
@ -8619,7 +8663,8 @@ void ImGui::SetCursorScreenPos(const ImVec2& pos)
{ {
ImGuiWindow* window = GetCurrentWindow(); ImGuiWindow* window = GetCurrentWindow();
window->DC.CursorPos = pos; window->DC.CursorPos = pos;
window->DC.CursorMaxPos = ImMax(window->DC.CursorMaxPos, window->DC.CursorPos); //window->DC.CursorMaxPos = ImMax(window->DC.CursorMaxPos, window->DC.CursorPos);
window->DC.IsSetPos = true;
} }
// User generally sees positions in window coordinates. Internally we store CursorPos in absolute screen coordinates because it is more convenient. // User generally sees positions in window coordinates. Internally we store CursorPos in absolute screen coordinates because it is more convenient.
@ -8646,21 +8691,24 @@ void ImGui::SetCursorPos(const ImVec2& local_pos)
{ {
ImGuiWindow* window = GetCurrentWindow(); ImGuiWindow* window = GetCurrentWindow();
window->DC.CursorPos = window->Pos - window->Scroll + local_pos; window->DC.CursorPos = window->Pos - window->Scroll + local_pos;
window->DC.CursorMaxPos = ImMax(window->DC.CursorMaxPos, window->DC.CursorPos); //window->DC.CursorMaxPos = ImMax(window->DC.CursorMaxPos, window->DC.CursorPos);
window->DC.IsSetPos = true;
} }
void ImGui::SetCursorPosX(float x) void ImGui::SetCursorPosX(float x)
{ {
ImGuiWindow* window = GetCurrentWindow(); ImGuiWindow* window = GetCurrentWindow();
window->DC.CursorPos.x = window->Pos.x - window->Scroll.x + x; window->DC.CursorPos.x = window->Pos.x - window->Scroll.x + x;
window->DC.CursorMaxPos.x = ImMax(window->DC.CursorMaxPos.x, window->DC.CursorPos.x); //window->DC.CursorMaxPos.x = ImMax(window->DC.CursorMaxPos.x, window->DC.CursorPos.x);
window->DC.IsSetPos = true;
} }
void ImGui::SetCursorPosY(float y) void ImGui::SetCursorPosY(float y)
{ {
ImGuiWindow* window = GetCurrentWindow(); ImGuiWindow* window = GetCurrentWindow();
window->DC.CursorPos.y = window->Pos.y - window->Scroll.y + y; window->DC.CursorPos.y = window->Pos.y - window->Scroll.y + y;
window->DC.CursorMaxPos.y = ImMax(window->DC.CursorMaxPos.y, window->DC.CursorPos.y); //window->DC.CursorMaxPos.y = ImMax(window->DC.CursorMaxPos.y, window->DC.CursorPos.y);
window->DC.IsSetPos = true;
} }
ImVec2 ImGui::GetCursorStartPos() ImVec2 ImGui::GetCursorStartPos()
@ -8877,6 +8925,9 @@ void ImGui::EndGroup()
ImGuiGroupData& group_data = g.GroupStack.back(); ImGuiGroupData& group_data = g.GroupStack.back();
IM_ASSERT(group_data.WindowID == window->ID); // EndGroup() in wrong window? IM_ASSERT(group_data.WindowID == window->ID); // EndGroup() in wrong window?
if (window->DC.IsSetPos)
ErrorCheckUsingSetCursorPosToExtendParentBoundaries();
ImRect group_bb(group_data.BackupCursorPos, ImMax(window->DC.CursorMaxPos, group_data.BackupCursorPos)); ImRect group_bb(group_data.BackupCursorPos, ImMax(window->DC.CursorMaxPos, group_data.BackupCursorPos));
window->DC.CursorPos = group_data.BackupCursorPos; window->DC.CursorPos = group_data.BackupCursorPos;

View File

@ -65,7 +65,7 @@ Index of this file:
// Version // Version
// (Integer encoded as XYYZZ for use in #if preprocessor conditionals. Work in progress versions typically starts at XYY99 then bounce up to XYY00, XYY01 etc. when release tagging happens) // (Integer encoded as XYYZZ for use in #if preprocessor conditionals. Work in progress versions typically starts at XYY99 then bounce up to XYY00, XYY01 etc. when release tagging happens)
#define IMGUI_VERSION "1.89 WIP" #define IMGUI_VERSION "1.89 WIP"
#define IMGUI_VERSION_NUM 18813 #define IMGUI_VERSION_NUM 18814
#define IMGUI_CHECKVERSION() ImGui::DebugCheckVersionAndDataLayout(IMGUI_VERSION, sizeof(ImGuiIO), sizeof(ImGuiStyle), sizeof(ImVec2), sizeof(ImVec4), sizeof(ImDrawVert), sizeof(ImDrawIdx)) #define IMGUI_CHECKVERSION() ImGui::DebugCheckVersionAndDataLayout(IMGUI_VERSION, sizeof(ImGuiIO), sizeof(ImGuiStyle), sizeof(ImVec2), sizeof(ImVec4), sizeof(ImDrawVert), sizeof(ImDrawIdx))
#define IMGUI_HAS_TABLE #define IMGUI_HAS_TABLE

View File

@ -2034,6 +2034,7 @@ struct IMGUI_API ImGuiWindowTempData
float CurrLineTextBaseOffset; // Baseline offset (0.0f by default on a new line, generally == style.FramePadding.y when a framed item has been added). float CurrLineTextBaseOffset; // Baseline offset (0.0f by default on a new line, generally == style.FramePadding.y when a framed item has been added).
float PrevLineTextBaseOffset; float PrevLineTextBaseOffset;
bool IsSameLine; bool IsSameLine;
bool IsSetPos;
ImVec1 Indent; // Indentation / start position from left of window (increased by TreePush/TreePop, etc.) ImVec1 Indent; // Indentation / start position from left of window (increased by TreePush/TreePop, etc.)
ImVec1 ColumnsOffset; // Offset to the current column (if ColumnsCurrent > 0). FIXME: This and the above should be a stack to allow use cases like Tree->Column->Tree. Need revamp columns API. ImVec1 ColumnsOffset; // Offset to the current column (if ColumnsCurrent > 0). FIXME: This and the above should be a stack to allow use cases like Tree->Column->Tree. Need revamp columns API.
ImVec1 GroupOffset; ImVec1 GroupOffset;
@ -2915,6 +2916,7 @@ namespace ImGui
// Debug Tools // Debug Tools
IMGUI_API void ErrorCheckEndFrameRecover(ImGuiErrorLogCallback log_callback, void* user_data = NULL); IMGUI_API void ErrorCheckEndFrameRecover(ImGuiErrorLogCallback log_callback, void* user_data = NULL);
IMGUI_API void ErrorCheckEndWindowRecover(ImGuiErrorLogCallback log_callback, void* user_data = NULL); IMGUI_API void ErrorCheckEndWindowRecover(ImGuiErrorLogCallback log_callback, void* user_data = NULL);
IMGUI_API void ErrorCheckUsingSetCursorPosToExtendParentBoundaries();
inline void DebugDrawItemRect(ImU32 col = IM_COL32(255,0,0,255)) { ImGuiContext& g = *GImGui; ImGuiWindow* window = g.CurrentWindow; GetForegroundDrawList(window)->AddRect(g.LastItemData.Rect.Min, g.LastItemData.Rect.Max, col); } inline void DebugDrawItemRect(ImU32 col = IM_COL32(255,0,0,255)) { ImGuiContext& g = *GImGui; ImGuiWindow* window = g.CurrentWindow; GetForegroundDrawList(window)->AddRect(g.LastItemData.Rect.Min, g.LastItemData.Rect.Max, col); }
inline void DebugStartItemPicker() { ImGuiContext& g = *GImGui; g.DebugItemPickerActive = true; } inline void DebugStartItemPicker() { ImGuiContext& g = *GImGui; g.DebugItemPickerActive = true; }
IMGUI_API void ShowFontAtlas(ImFontAtlas* atlas); IMGUI_API void ShowFontAtlas(ImFontAtlas* atlas);

View File

@ -1718,7 +1718,7 @@ void ImGui::TableBeginRow(ImGuiTable* table)
table->RowIndentOffsetX = window->DC.Indent.x - table->HostIndentX; // Lock indent table->RowIndentOffsetX = window->DC.Indent.x - table->HostIndentX; // Lock indent
window->DC.PrevLineTextBaseOffset = 0.0f; window->DC.PrevLineTextBaseOffset = 0.0f;
window->DC.CurrLineSize = ImVec2(0.0f, 0.0f); window->DC.CurrLineSize = ImVec2(0.0f, 0.0f);
window->DC.IsSameLine = false; window->DC.IsSameLine = window->DC.IsSetPos = false;
window->DC.CursorMaxPos.y = next_y1; window->DC.CursorMaxPos.y = next_y1;
// Making the header BG color non-transparent will allow us to overlay it multiple times when handling smooth dragging. // Making the header BG color non-transparent will allow us to overlay it multiple times when handling smooth dragging.
@ -2000,6 +2000,9 @@ void ImGui::TableEndCell(ImGuiTable* table)
ImGuiTableColumn* column = &table->Columns[table->CurrentColumn]; ImGuiTableColumn* column = &table->Columns[table->CurrentColumn];
ImGuiWindow* window = table->InnerWindow; ImGuiWindow* window = table->InnerWindow;
if (window->DC.IsSetPos)
ErrorCheckUsingSetCursorPosToExtendParentBoundaries();
// Report maximum position so we can infer content size per column. // Report maximum position so we can infer content size per column.
float* p_max_pos_x; float* p_max_pos_x;
if (table->RowFlags & ImGuiTableRowFlags_Headers) if (table->RowFlags & ImGuiTableRowFlags_Headers)