Windows, Internal: added experimental SkipRefresh mode. (#3515, #4763, #7556, #5116 , #4076, #2749, #2268)
currently: ImGui::SetNextWindowRefreshPolicy(ImGuiWindowRefreshFlags_TryToAvoidRefresh); - This is NOT meant to replace frame-wide/app-wide idle mode. - This is another tool: the idea that a given window could avoid refresh and reuse last frame contents. - I think it needs to be backed by a careful and smart design overall (refresh policy, load balancing, making it easy and obvious to user). - It's not there yet, this is currently a toy for experimenting. My other issues with this: - It appears to be very simple, but skipping most of Begin() logic will inevitably lead to tricky/confusing bugs. Let's see how it goes. - I don't like very much that this opens a door to varying inconsistencies - I don't like very much that it can lead us to situation where the lazy refresh gets disabled in bulk due to some reason (e.g. resizing a dock space) and we get sucked in the temptation to update for idle rather than update for dynamism.
This commit is contained in:
parent
0b309471f2
commit
d4495446d5
56
imgui.cpp
56
imgui.cpp
@ -6334,6 +6334,30 @@ void ImGui::UpdateWindowParentAndRootLinks(ImGuiWindow* window, ImGuiWindowFlags
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// [EXPERIMENTAL] Called by Begin(). NextWindowData is valid at this point.
|
||||||
|
// This is designed as a toy/test-bed for
|
||||||
|
void ImGui::UpdateWindowSkipRefresh(ImGuiWindow* window)
|
||||||
|
{
|
||||||
|
ImGuiContext& g = *GImGui;
|
||||||
|
window->SkipRefresh = false;
|
||||||
|
if ((g.NextWindowData.Flags & ImGuiNextWindowDataFlags_HasRefreshPolicy) == 0)
|
||||||
|
return;
|
||||||
|
if (g.NextWindowData.RefreshFlagsVal & ImGuiWindowRefreshFlags_TryToAvoidRefresh)
|
||||||
|
{
|
||||||
|
// FIXME-IDLE: Tests for e.g. mouse clicks or keyboard while focused.
|
||||||
|
if (window->Appearing) // If currently appearing
|
||||||
|
return;
|
||||||
|
if (window->Hidden) // If was hidden (previous frame)
|
||||||
|
return;
|
||||||
|
if ((g.NextWindowData.RefreshFlagsVal & ImGuiWindowRefreshFlags_RefreshOnHover) && g.HoveredWindow && window->RootWindow == g.HoveredWindow->RootWindow)
|
||||||
|
return;
|
||||||
|
if ((g.NextWindowData.RefreshFlagsVal & ImGuiWindowRefreshFlags_RefreshOnFocus) && g.NavWindow && window->RootWindow == g.NavWindow->RootWindow)
|
||||||
|
return;
|
||||||
|
window->DrawList = NULL;
|
||||||
|
window->SkipRefresh = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// When a modal popup is open, newly created windows that want focus (i.e. are not popups and do not specify ImGuiWindowFlags_NoFocusOnAppearing)
|
// When a modal popup is open, newly created windows that want focus (i.e. are not popups and do not specify ImGuiWindowFlags_NoFocusOnAppearing)
|
||||||
// should be positioned behind that modal window, unless the window was created inside the modal begin-stack.
|
// should be positioned behind that modal window, unless the window was created inside the modal begin-stack.
|
||||||
// In case of multiple stacked modals newly created window honors begin stack order and does not go below its own modal parent.
|
// In case of multiple stacked modals newly created window honors begin stack order and does not go below its own modal parent.
|
||||||
@ -6532,11 +6556,14 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
|
|||||||
if (window->Appearing)
|
if (window->Appearing)
|
||||||
SetWindowConditionAllowFlags(window, ImGuiCond_Appearing, false);
|
SetWindowConditionAllowFlags(window, ImGuiCond_Appearing, false);
|
||||||
|
|
||||||
|
// [EXPERIMENTAL] Skip Refresh mode
|
||||||
|
UpdateWindowSkipRefresh(window);
|
||||||
|
|
||||||
// We intentionally set g.CurrentWindow to NULL to prevent usage until when the viewport is set, then will call SetCurrentWindow()
|
// We intentionally set g.CurrentWindow to NULL to prevent usage until when the viewport is set, then will call SetCurrentWindow()
|
||||||
g.CurrentWindow = NULL;
|
g.CurrentWindow = NULL;
|
||||||
|
|
||||||
// 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 && !window->SkipRefresh)
|
||||||
{
|
{
|
||||||
// Initialize
|
// Initialize
|
||||||
const bool window_is_child_tooltip = (flags & ImGuiWindowFlags_ChildWindow) && (flags & ImGuiWindowFlags_Tooltip); // FIXME-WIP: Undocumented behavior of Child+Tooltip for pinned tooltip (#1345)
|
const bool window_is_child_tooltip = (flags & ImGuiWindowFlags_ChildWindow) && (flags & ImGuiWindowFlags_Tooltip); // FIXME-WIP: Undocumented behavior of Child+Tooltip for pinned tooltip (#1345)
|
||||||
@ -7027,11 +7054,16 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
// Skip refresh always mark active
|
||||||
|
if (window->SkipRefresh)
|
||||||
|
window->Active = true;
|
||||||
|
|
||||||
// Append
|
// Append
|
||||||
SetCurrentWindow(window);
|
SetCurrentWindow(window);
|
||||||
SetLastItemDataForWindow(window, window->TitleBarRect());
|
SetLastItemDataForWindow(window, window->TitleBarRect());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!window->SkipRefresh)
|
||||||
PushClipRect(window->InnerClipRect.Min, window->InnerClipRect.Max, true);
|
PushClipRect(window->InnerClipRect.Min, window->InnerClipRect.Max, true);
|
||||||
|
|
||||||
// Clear 'accessed' flag last thing (After PushClipRect which will set the flag. We want the flag to stay false when the default "Debug" window is unused)
|
// Clear 'accessed' flag last thing (After PushClipRect which will set the flag. We want the flag to stay false when the default "Debug" window is unused)
|
||||||
@ -7040,7 +7072,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
|
|||||||
g.NextWindowData.ClearFlags();
|
g.NextWindowData.ClearFlags();
|
||||||
|
|
||||||
// Update visibility
|
// Update visibility
|
||||||
if (first_begin_of_the_frame)
|
if (first_begin_of_the_frame && !window->SkipRefresh)
|
||||||
{
|
{
|
||||||
if ((flags & ImGuiWindowFlags_ChildWindow) && !(flags & ImGuiWindowFlags_ChildMenu))
|
if ((flags & ImGuiWindowFlags_ChildWindow) && !(flags & ImGuiWindowFlags_ChildMenu))
|
||||||
{
|
{
|
||||||
@ -7086,6 +7118,11 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
|
|||||||
skip_items = true;
|
skip_items = true;
|
||||||
window->SkipItems = skip_items;
|
window->SkipItems = skip_items;
|
||||||
}
|
}
|
||||||
|
else if (first_begin_of_the_frame)
|
||||||
|
{
|
||||||
|
// Skip refresh mode
|
||||||
|
window->SkipItems = true;
|
||||||
|
}
|
||||||
|
|
||||||
// [DEBUG] io.ConfigDebugBeginReturnValue override return value to test Begin/End and BeginChild/EndChild behaviors.
|
// [DEBUG] io.ConfigDebugBeginReturnValue override return value to test Begin/End and BeginChild/EndChild behaviors.
|
||||||
// (The implicit fallback window is NOT automatically ended allowing it to always be able to receive commands without crashing)
|
// (The implicit fallback window is NOT automatically ended allowing it to always be able to receive commands without crashing)
|
||||||
@ -7128,9 +7165,16 @@ void ImGui::End()
|
|||||||
// Close anything that is open
|
// Close anything that is open
|
||||||
if (window->DC.CurrentColumns)
|
if (window->DC.CurrentColumns)
|
||||||
EndColumns();
|
EndColumns();
|
||||||
|
if (!window->SkipRefresh)
|
||||||
PopClipRect(); // Inner window clip rectangle
|
PopClipRect(); // Inner window clip rectangle
|
||||||
PopFocusScope();
|
PopFocusScope();
|
||||||
|
|
||||||
|
if (window->SkipRefresh)
|
||||||
|
{
|
||||||
|
IM_ASSERT(window->DrawList == NULL);
|
||||||
|
window->DrawList = &window->DrawListInst;
|
||||||
|
}
|
||||||
|
|
||||||
// Stop logging
|
// Stop logging
|
||||||
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();
|
||||||
@ -7815,6 +7859,14 @@ void ImGui::SetNextWindowBgAlpha(float alpha)
|
|||||||
g.NextWindowData.BgAlphaVal = alpha;
|
g.NextWindowData.BgAlphaVal = alpha;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This is experimental and meant to be a toy for exploring a future/wider range of features.
|
||||||
|
void ImGui::SetNextWindowRefreshPolicy(ImGuiWindowRefreshFlags flags)
|
||||||
|
{
|
||||||
|
ImGuiContext& g = *GImGui;
|
||||||
|
g.NextWindowData.Flags |= ImGuiNextWindowDataFlags_HasRefreshPolicy;
|
||||||
|
g.NextWindowData.RefreshFlagsVal = flags;
|
||||||
|
}
|
||||||
|
|
||||||
ImDrawList* ImGui::GetWindowDrawList()
|
ImDrawList* ImGui::GetWindowDrawList()
|
||||||
{
|
{
|
||||||
ImGuiWindow* window = GetCurrentWindow();
|
ImGuiWindow* window = GetCurrentWindow();
|
||||||
|
@ -10,6 +10,11 @@
|
|||||||
// Read top of imgui.cpp and imgui.h for many details, documentation, comments, links.
|
// Read top of imgui.cpp and imgui.h for many details, documentation, comments, links.
|
||||||
// Get the latest version at https://github.com/ocornut/imgui
|
// Get the latest version at https://github.com/ocornut/imgui
|
||||||
|
|
||||||
|
// How to easily locate code?
|
||||||
|
// - Use the Item Picker to debug break in code by clicking any widgets: https://github.com/ocornut/imgui/wiki/Debug-Tools
|
||||||
|
// - Browse an online version the demo with code linked to hovered widgets: https://pthom.github.io/imgui_manual_online/manual/imgui_manual.html
|
||||||
|
// - Find a visible string and search for it in the code!
|
||||||
|
|
||||||
//---------------------------------------------------
|
//---------------------------------------------------
|
||||||
// PLEASE DO NOT REMOVE THIS FILE FROM YOUR PROJECT!
|
// PLEASE DO NOT REMOVE THIS FILE FROM YOUR PROJECT!
|
||||||
//---------------------------------------------------
|
//---------------------------------------------------
|
||||||
|
@ -385,6 +385,7 @@ void ImDrawListSharedData::SetCircleTessellationMaxError(float max_error)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Initialize before use in a new frame. We always have a command ready in the buffer.
|
// Initialize before use in a new frame. We always have a command ready in the buffer.
|
||||||
|
// In the majority of cases, you would want to call PushClipRect() and PushTextureID() after this.
|
||||||
void ImDrawList::_ResetForNewFrame()
|
void ImDrawList::_ResetForNewFrame()
|
||||||
{
|
{
|
||||||
// Verify that the ImDrawCmd fields we want to memcmp() are contiguous in memory.
|
// Verify that the ImDrawCmd fields we want to memcmp() are contiguous in memory.
|
||||||
|
@ -182,6 +182,7 @@ typedef int ImGuiSeparatorFlags; // -> enum ImGuiSeparatorFlags_ // F
|
|||||||
typedef int ImGuiTextFlags; // -> enum ImGuiTextFlags_ // Flags: for TextEx()
|
typedef int ImGuiTextFlags; // -> enum ImGuiTextFlags_ // Flags: for TextEx()
|
||||||
typedef int ImGuiTooltipFlags; // -> enum ImGuiTooltipFlags_ // Flags: for BeginTooltipEx()
|
typedef int ImGuiTooltipFlags; // -> enum ImGuiTooltipFlags_ // Flags: for BeginTooltipEx()
|
||||||
typedef int ImGuiTypingSelectFlags; // -> enum ImGuiTypingSelectFlags_ // Flags: for GetTypingSelectRequest()
|
typedef int ImGuiTypingSelectFlags; // -> enum ImGuiTypingSelectFlags_ // Flags: for GetTypingSelectRequest()
|
||||||
|
typedef int ImGuiWindowRefreshFlags; // -> enum ImGuiWindowRefreshFlags_ // Flags: for SetNextWindowRefreshPolicy()
|
||||||
|
|
||||||
typedef void (*ImGuiErrorLogCallback)(void* user_data, const char* fmt, ...);
|
typedef void (*ImGuiErrorLogCallback)(void* user_data, const char* fmt, ...);
|
||||||
|
|
||||||
@ -1117,6 +1118,15 @@ struct IMGUI_API ImGuiInputTextState
|
|||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum ImGuiWindowRefreshFlags_
|
||||||
|
{
|
||||||
|
ImGuiWindowRefreshFlags_None = 0,
|
||||||
|
ImGuiWindowRefreshFlags_TryToAvoidRefresh = 1 << 0, // [EXPERIMENTAL] Try to keep existing contents, USER MUST NOT HONOR BEGIN() RETURNING FALSE AND NOT APPEND.
|
||||||
|
ImGuiWindowRefreshFlags_RefreshOnHover = 1 << 1, // [EXPERIMENTAL] Always refresh on hover
|
||||||
|
ImGuiWindowRefreshFlags_RefreshOnFocus = 1 << 2, // [EXPERIMENTAL] Always refresh on focus
|
||||||
|
// Refresh policy/frequency, Load Balancing etc.
|
||||||
|
};
|
||||||
|
|
||||||
enum ImGuiNextWindowDataFlags_
|
enum ImGuiNextWindowDataFlags_
|
||||||
{
|
{
|
||||||
ImGuiNextWindowDataFlags_None = 0,
|
ImGuiNextWindowDataFlags_None = 0,
|
||||||
@ -1129,6 +1139,7 @@ enum ImGuiNextWindowDataFlags_
|
|||||||
ImGuiNextWindowDataFlags_HasBgAlpha = 1 << 6,
|
ImGuiNextWindowDataFlags_HasBgAlpha = 1 << 6,
|
||||||
ImGuiNextWindowDataFlags_HasScroll = 1 << 7,
|
ImGuiNextWindowDataFlags_HasScroll = 1 << 7,
|
||||||
ImGuiNextWindowDataFlags_HasChildFlags = 1 << 8,
|
ImGuiNextWindowDataFlags_HasChildFlags = 1 << 8,
|
||||||
|
ImGuiNextWindowDataFlags_HasRefreshPolicy = 1 << 9,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Storage for SetNexWindow** functions
|
// Storage for SetNexWindow** functions
|
||||||
@ -1150,6 +1161,7 @@ struct ImGuiNextWindowData
|
|||||||
void* SizeCallbackUserData;
|
void* SizeCallbackUserData;
|
||||||
float BgAlphaVal; // Override background alpha
|
float BgAlphaVal; // Override background alpha
|
||||||
ImVec2 MenuBarOffsetMinVal; // (Always on) This is not exposed publicly, so we don't clear it and it doesn't have a corresponding flag (could we? for consistency?)
|
ImVec2 MenuBarOffsetMinVal; // (Always on) This is not exposed publicly, so we don't clear it and it doesn't have a corresponding flag (could we? for consistency?)
|
||||||
|
ImGuiWindowRefreshFlags RefreshFlagsVal;
|
||||||
|
|
||||||
ImGuiNextWindowData() { memset(this, 0, sizeof(*this)); }
|
ImGuiNextWindowData() { memset(this, 0, sizeof(*this)); }
|
||||||
inline void ClearFlags() { Flags = ImGuiNextWindowDataFlags_None; }
|
inline void ClearFlags() { Flags = ImGuiNextWindowDataFlags_None; }
|
||||||
@ -2534,6 +2546,7 @@ struct IMGUI_API ImGuiWindow
|
|||||||
bool Collapsed; // Set when collapsing window to become only title-bar
|
bool Collapsed; // Set when collapsing window to become only title-bar
|
||||||
bool WantCollapseToggle;
|
bool WantCollapseToggle;
|
||||||
bool SkipItems; // Set when items can safely be all clipped (e.g. window not visible or collapsed)
|
bool SkipItems; // Set when items can safely be all clipped (e.g. window not visible or collapsed)
|
||||||
|
bool SkipRefresh; // [EXPERIMENTAL] Reuse previous frame drawn contents, Begin() returns false.
|
||||||
bool Appearing; // Set during the frame where the window is appearing (or re-appearing)
|
bool Appearing; // Set during the frame where the window is appearing (or re-appearing)
|
||||||
bool Hidden; // Do not display (== HiddenFrames*** > 0)
|
bool Hidden; // Do not display (== HiddenFrames*** > 0)
|
||||||
bool IsFallbackWindow; // Set on the "Debug##Default" window.
|
bool IsFallbackWindow; // Set on the "Debug##Default" window.
|
||||||
@ -3007,6 +3020,7 @@ namespace ImGui
|
|||||||
IMGUI_API ImGuiWindow* FindWindowByID(ImGuiID id);
|
IMGUI_API ImGuiWindow* FindWindowByID(ImGuiID id);
|
||||||
IMGUI_API ImGuiWindow* FindWindowByName(const char* name);
|
IMGUI_API ImGuiWindow* FindWindowByName(const char* name);
|
||||||
IMGUI_API void UpdateWindowParentAndRootLinks(ImGuiWindow* window, ImGuiWindowFlags flags, ImGuiWindow* parent_window);
|
IMGUI_API void UpdateWindowParentAndRootLinks(ImGuiWindow* window, ImGuiWindowFlags flags, ImGuiWindow* parent_window);
|
||||||
|
IMGUI_API void UpdateWindowSkipRefresh(ImGuiWindow* window);
|
||||||
IMGUI_API ImVec2 CalcWindowNextAutoFitSize(ImGuiWindow* window);
|
IMGUI_API ImVec2 CalcWindowNextAutoFitSize(ImGuiWindow* window);
|
||||||
IMGUI_API bool IsWindowChildOf(ImGuiWindow* window, ImGuiWindow* potential_parent, bool popup_hierarchy);
|
IMGUI_API bool IsWindowChildOf(ImGuiWindow* window, ImGuiWindow* potential_parent, bool popup_hierarchy);
|
||||||
IMGUI_API bool IsWindowWithinBeginStackOf(ImGuiWindow* window, ImGuiWindow* potential_parent);
|
IMGUI_API bool IsWindowWithinBeginStackOf(ImGuiWindow* window, ImGuiWindow* potential_parent);
|
||||||
@ -3032,6 +3046,9 @@ namespace ImGui
|
|||||||
IMGUI_API int FindWindowDisplayIndex(ImGuiWindow* window);
|
IMGUI_API int FindWindowDisplayIndex(ImGuiWindow* window);
|
||||||
IMGUI_API ImGuiWindow* FindBottomMostVisibleWindowWithinBeginStack(ImGuiWindow* window);
|
IMGUI_API ImGuiWindow* FindBottomMostVisibleWindowWithinBeginStack(ImGuiWindow* window);
|
||||||
|
|
||||||
|
// Windows: Idle, Refresh Policies [EXPERIMENTAL]
|
||||||
|
IMGUI_API void SetNextWindowRefreshPolicy(ImGuiWindowRefreshFlags flags);
|
||||||
|
|
||||||
// Fonts, drawing
|
// Fonts, drawing
|
||||||
IMGUI_API void SetCurrentFont(ImFont* font);
|
IMGUI_API void SetCurrentFont(ImFont* font);
|
||||||
inline ImFont* GetDefaultFont() { ImGuiContext& g = *GImGui; return g.IO.FontDefault ? g.IO.FontDefault : g.IO.Fonts->Fonts[0]; }
|
inline ImFont* GetDefaultFont() { ImGuiContext& g = *GImGui; return g.IO.FontDefault ? g.IO.FontDefault : g.IO.Fonts->Fonts[0]; }
|
||||||
|
Loading…
Reference in New Issue
Block a user