|
@@ -904,10 +904,12 @@ static void ErrorCheckEndFrame();
|
|
|
static void ErrorCheckBeginEndCompareStacksSize(ImGuiWindow* window, bool write);
|
|
|
|
|
|
// Misc
|
|
|
+static void UpdateSettings();
|
|
|
static void UpdateMouseInputs();
|
|
|
static void UpdateMouseWheel();
|
|
|
-static bool UpdateManualResize(ImGuiWindow* window, const ImVec2& size_auto_fit, int* border_held, int resize_grip_count, ImU32 resize_grip_col[4]);
|
|
|
+static void UpdateTabFocus();
|
|
|
static void UpdateDebugToolItemPicker();
|
|
|
+static bool UpdateWindowManualResize(ImGuiWindow* window, const ImVec2& size_auto_fit, int* border_held, int resize_grip_count, ImU32 resize_grip_col[4]);
|
|
|
static void RenderWindowOuterBorders(ImGuiWindow* window);
|
|
|
static void RenderWindowDecorations(ImGuiWindow* window, const ImRect& title_bar_rect, bool title_bar_is_highlight, int resize_grip_count, const ImU32 resize_grip_col[4], float resize_grip_draw_size);
|
|
|
static void RenderWindowTitleBarContents(ImGuiWindow* window, const ImRect& title_bar_rect, const char* name, bool* p_open);
|
|
@@ -3495,6 +3497,42 @@ void ImGui::UpdateMouseWheel()
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+void ImGui::UpdateTabFocus()
|
|
|
+{
|
|
|
+ ImGuiContext& g = *GImGui;
|
|
|
+
|
|
|
+ // Pressing TAB activate widget focus
|
|
|
+ g.FocusTabPressed = (g.NavWindow && g.NavWindow->Active && !(g.NavWindow->Flags & ImGuiWindowFlags_NoNavInputs) && !g.IO.KeyCtrl && IsKeyPressedMap(ImGuiKey_Tab));
|
|
|
+ if (g.ActiveId == 0 && g.FocusTabPressed)
|
|
|
+ {
|
|
|
+ // Note that SetKeyboardFocusHere() sets the Next fields mid-frame. To be consistent we also
|
|
|
+ // manipulate the Next fields even, even though they will be turned into Curr fields by the code below.
|
|
|
+ g.FocusRequestNextWindow = g.NavWindow;
|
|
|
+ g.FocusRequestNextCounterRegular = INT_MAX;
|
|
|
+ if (g.NavId != 0 && g.NavIdTabCounter != INT_MAX)
|
|
|
+ g.FocusRequestNextCounterTabStop = g.NavIdTabCounter + 1 + (g.IO.KeyShift ? -1 : 1);
|
|
|
+ else
|
|
|
+ g.FocusRequestNextCounterTabStop = g.IO.KeyShift ? -1 : 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ // Turn queued focus request into current one
|
|
|
+ g.FocusRequestCurrWindow = NULL;
|
|
|
+ g.FocusRequestCurrCounterRegular = g.FocusRequestCurrCounterTabStop = INT_MAX;
|
|
|
+ if (g.FocusRequestNextWindow != NULL)
|
|
|
+ {
|
|
|
+ ImGuiWindow* window = g.FocusRequestNextWindow;
|
|
|
+ g.FocusRequestCurrWindow = window;
|
|
|
+ if (g.FocusRequestNextCounterRegular != INT_MAX && window->DC.FocusCounterRegular != -1)
|
|
|
+ g.FocusRequestCurrCounterRegular = ImModPositive(g.FocusRequestNextCounterRegular, window->DC.FocusCounterRegular + 1);
|
|
|
+ if (g.FocusRequestNextCounterTabStop != INT_MAX && window->DC.FocusCounterTabStop != -1)
|
|
|
+ g.FocusRequestCurrCounterTabStop = ImModPositive(g.FocusRequestNextCounterTabStop, window->DC.FocusCounterTabStop + 1);
|
|
|
+ g.FocusRequestNextWindow = NULL;
|
|
|
+ g.FocusRequestNextCounterRegular = g.FocusRequestNextCounterTabStop = INT_MAX;
|
|
|
+ }
|
|
|
+
|
|
|
+ g.NavIdTabCounter = INT_MAX;
|
|
|
+}
|
|
|
+
|
|
|
// The reason this is exposed in imgui_internal.h is: on touch-based system that don't have hovering, we want to dispatch inputs to the right target (imgui vs imgui+app)
|
|
|
void ImGui::UpdateHoveredWindowAndCaptureFlags()
|
|
|
{
|
|
@@ -3595,28 +3633,8 @@ void ImGui::NewFrame()
|
|
|
// Check and assert for various common IO and Configuration mistakes
|
|
|
NewFrameSanityChecks();
|
|
|
|
|
|
- // Load settings on first frame (if not explicitly loaded manually before)
|
|
|
- if (!g.SettingsLoaded)
|
|
|
- {
|
|
|
- IM_ASSERT(g.SettingsWindows.empty());
|
|
|
- if (g.IO.IniFilename)
|
|
|
- LoadIniSettingsFromDisk(g.IO.IniFilename);
|
|
|
- g.SettingsLoaded = true;
|
|
|
- }
|
|
|
-
|
|
|
- // Save settings (with a delay after the last modification, so we don't spam disk too much)
|
|
|
- if (g.SettingsDirtyTimer > 0.0f)
|
|
|
- {
|
|
|
- g.SettingsDirtyTimer -= g.IO.DeltaTime;
|
|
|
- if (g.SettingsDirtyTimer <= 0.0f)
|
|
|
- {
|
|
|
- if (g.IO.IniFilename != NULL)
|
|
|
- SaveIniSettingsToDisk(g.IO.IniFilename);
|
|
|
- else
|
|
|
- g.IO.WantSaveIniSettings = true; // Let user know they can call SaveIniSettingsToMemory(). user will need to clear io.WantSaveIniSettings themselves.
|
|
|
- g.SettingsDirtyTimer = 0.0f;
|
|
|
- }
|
|
|
- }
|
|
|
+ // Load settings on first frame, save settings when modified (after a delay)
|
|
|
+ UpdateSettings();
|
|
|
|
|
|
g.Time += g.IO.DeltaTime;
|
|
|
g.WithinFrameScope = true;
|
|
@@ -3625,6 +3643,12 @@ void ImGui::NewFrame()
|
|
|
g.WindowsActiveCount = 0;
|
|
|
g.MenusIdSubmittedThisFrame.resize(0);
|
|
|
|
|
|
+ // Calculate frame-rate for the user, as a purely luxurious feature
|
|
|
+ g.FramerateSecPerFrameAccum += g.IO.DeltaTime - g.FramerateSecPerFrame[g.FramerateSecPerFrameIdx];
|
|
|
+ g.FramerateSecPerFrame[g.FramerateSecPerFrameIdx] = g.IO.DeltaTime;
|
|
|
+ g.FramerateSecPerFrameIdx = (g.FramerateSecPerFrameIdx + 1) % IM_ARRAYSIZE(g.FramerateSecPerFrame);
|
|
|
+ g.IO.Framerate = (g.FramerateSecPerFrameAccum > 0.0f) ? (1.0f / (g.FramerateSecPerFrameAccum / (float)IM_ARRAYSIZE(g.FramerateSecPerFrame))) : FLT_MAX;
|
|
|
+
|
|
|
// Setup current font and draw list shared data
|
|
|
g.IO.Fonts->Locked = true;
|
|
|
SetCurrentFont(GetDefaultFont());
|
|
@@ -3655,7 +3679,7 @@ void ImGui::NewFrame()
|
|
|
if (g.DragDropActive && g.DragDropPayload.SourceId == g.ActiveId)
|
|
|
KeepAliveID(g.DragDropPayload.SourceId);
|
|
|
|
|
|
- // Clear reference to active widget if the widget isn't alive anymore
|
|
|
+ // Update HoveredId data
|
|
|
if (!g.HoveredIdPreviousFrame)
|
|
|
g.HoveredIdTimer = 0.0f;
|
|
|
if (!g.HoveredIdPreviousFrame || (g.HoveredId && g.ActiveId == g.HoveredId))
|
|
@@ -3667,6 +3691,8 @@ void ImGui::NewFrame()
|
|
|
g.HoveredIdPreviousFrame = g.HoveredId;
|
|
|
g.HoveredId = 0;
|
|
|
g.HoveredIdAllowOverlap = false;
|
|
|
+
|
|
|
+ // Update ActiveId data (clear reference to active widget if the widget isn't alive anymore)
|
|
|
if (g.ActiveIdIsAlive != g.ActiveId && g.ActiveIdPreviousFrame == g.ActiveId && g.ActiveId != 0)
|
|
|
ClearActiveID();
|
|
|
if (g.ActiveId)
|
|
@@ -3683,8 +3709,9 @@ void ImGui::NewFrame()
|
|
|
g.TempInputId = 0;
|
|
|
if (g.ActiveId == 0)
|
|
|
{
|
|
|
- g.ActiveIdUsingNavDirMask = g.ActiveIdUsingNavInputMask = 0;
|
|
|
- g.ActiveIdUsingKeyInputMask = 0;
|
|
|
+ g.ActiveIdUsingNavDirMask = 0x00;
|
|
|
+ g.ActiveIdUsingNavInputMask = 0x00;
|
|
|
+ g.ActiveIdUsingKeyInputMask = 0x00;
|
|
|
}
|
|
|
|
|
|
// Drag and drop
|
|
@@ -3704,12 +3731,6 @@ void ImGui::NewFrame()
|
|
|
// Update mouse input state
|
|
|
UpdateMouseInputs();
|
|
|
|
|
|
- // Calculate frame-rate for the user, as a purely luxurious feature
|
|
|
- g.FramerateSecPerFrameAccum += g.IO.DeltaTime - g.FramerateSecPerFrame[g.FramerateSecPerFrameIdx];
|
|
|
- g.FramerateSecPerFrame[g.FramerateSecPerFrameIdx] = g.IO.DeltaTime;
|
|
|
- g.FramerateSecPerFrameIdx = (g.FramerateSecPerFrameIdx + 1) % IM_ARRAYSIZE(g.FramerateSecPerFrame);
|
|
|
- g.IO.Framerate = (g.FramerateSecPerFrameAccum > 0.0f) ? (1.0f / (g.FramerateSecPerFrameAccum / (float)IM_ARRAYSIZE(g.FramerateSecPerFrame))) : FLT_MAX;
|
|
|
-
|
|
|
// Find hovered window
|
|
|
// (needs to be before UpdateMouseMovingWindowNewFrame so we fill g.HoveredWindowUnderMovingWindow on the mouse release frame)
|
|
|
UpdateHoveredWindowAndCaptureFlags();
|
|
@@ -3730,36 +3751,8 @@ void ImGui::NewFrame()
|
|
|
// Mouse wheel scrolling, scale
|
|
|
UpdateMouseWheel();
|
|
|
|
|
|
- // Pressing TAB activate widget focus
|
|
|
- g.FocusTabPressed = (g.NavWindow && g.NavWindow->Active && !(g.NavWindow->Flags & ImGuiWindowFlags_NoNavInputs) && !g.IO.KeyCtrl && IsKeyPressedMap(ImGuiKey_Tab));
|
|
|
- if (g.ActiveId == 0 && g.FocusTabPressed)
|
|
|
- {
|
|
|
- // Note that SetKeyboardFocusHere() sets the Next fields mid-frame. To be consistent we also
|
|
|
- // manipulate the Next fields even, even though they will be turned into Curr fields by the code below.
|
|
|
- g.FocusRequestNextWindow = g.NavWindow;
|
|
|
- g.FocusRequestNextCounterRegular = INT_MAX;
|
|
|
- if (g.NavId != 0 && g.NavIdTabCounter != INT_MAX)
|
|
|
- g.FocusRequestNextCounterTabStop = g.NavIdTabCounter + 1 + (g.IO.KeyShift ? -1 : 1);
|
|
|
- else
|
|
|
- g.FocusRequestNextCounterTabStop = g.IO.KeyShift ? -1 : 0;
|
|
|
- }
|
|
|
-
|
|
|
- // Turn queued focus request into current one
|
|
|
- g.FocusRequestCurrWindow = NULL;
|
|
|
- g.FocusRequestCurrCounterRegular = g.FocusRequestCurrCounterTabStop = INT_MAX;
|
|
|
- if (g.FocusRequestNextWindow != NULL)
|
|
|
- {
|
|
|
- ImGuiWindow* window = g.FocusRequestNextWindow;
|
|
|
- g.FocusRequestCurrWindow = window;
|
|
|
- if (g.FocusRequestNextCounterRegular != INT_MAX && window->DC.FocusCounterRegular != -1)
|
|
|
- g.FocusRequestCurrCounterRegular = ImModPositive(g.FocusRequestNextCounterRegular, window->DC.FocusCounterRegular + 1);
|
|
|
- if (g.FocusRequestNextCounterTabStop != INT_MAX && window->DC.FocusCounterTabStop != -1)
|
|
|
- g.FocusRequestCurrCounterTabStop = ImModPositive(g.FocusRequestNextCounterTabStop, window->DC.FocusCounterTabStop + 1);
|
|
|
- g.FocusRequestNextWindow = NULL;
|
|
|
- g.FocusRequestNextCounterRegular = g.FocusRequestNextCounterTabStop = INT_MAX;
|
|
|
- }
|
|
|
-
|
|
|
- g.NavIdTabCounter = INT_MAX;
|
|
|
+ // Update legacy TAB focus
|
|
|
+ UpdateTabFocus();
|
|
|
|
|
|
// Mark all windows as not visible and compact unused memory.
|
|
|
IM_ASSERT(g.WindowsFocusOrder.Size == g.Windows.Size);
|
|
@@ -4972,7 +4965,7 @@ ImGuiID ImGui::GetWindowResizeID(ImGuiWindow* window, int n)
|
|
|
|
|
|
// Handle resize for: Resize Grips, Borders, Gamepad
|
|
|
// Return true when using auto-fit (double click on resize grip)
|
|
|
-static bool ImGui::UpdateManualResize(ImGuiWindow* window, const ImVec2& size_auto_fit, int* border_held, int resize_grip_count, ImU32 resize_grip_col[4])
|
|
|
+static bool ImGui::UpdateWindowManualResize(ImGuiWindow* window, const ImVec2& size_auto_fit, int* border_held, int resize_grip_count, ImU32 resize_grip_col[4])
|
|
|
{
|
|
|
ImGuiContext& g = *GImGui;
|
|
|
ImGuiWindowFlags flags = window->Flags;
|
|
@@ -5645,7 +5638,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
|
|
|
const int resize_grip_count = g.IO.ConfigWindowsResizeFromEdges ? 2 : 1; // Allow resize from lower-left if we have the mouse cursor feedback for it.
|
|
|
const float resize_grip_draw_size = IM_FLOOR(ImMax(g.FontSize * 1.35f, window->WindowRounding + 1.0f + g.FontSize * 0.2f));
|
|
|
if (!window->Collapsed)
|
|
|
- if (UpdateManualResize(window, size_auto_fit, &border_held, resize_grip_count, &resize_grip_col[0]))
|
|
|
+ if (UpdateWindowManualResize(window, size_auto_fit, &border_held, resize_grip_count, &resize_grip_col[0]))
|
|
|
use_current_size_for_scrollbar_x = use_current_size_for_scrollbar_y = true;
|
|
|
window->ResizeBorderHeld = (signed char)border_held;
|
|
|
|
|
@@ -9444,6 +9437,34 @@ void ImGui::LogButtons()
|
|
|
// [SECTION] SETTINGS
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
|
+// Called by NewFrame()
|
|
|
+void ImGui::UpdateSettings()
|
|
|
+{
|
|
|
+ // Load settings on first frame (if not explicitly loaded manually before)
|
|
|
+ ImGuiContext& g = *GImGui;
|
|
|
+ if (!g.SettingsLoaded)
|
|
|
+ {
|
|
|
+ IM_ASSERT(g.SettingsWindows.empty());
|
|
|
+ if (g.IO.IniFilename)
|
|
|
+ LoadIniSettingsFromDisk(g.IO.IniFilename);
|
|
|
+ g.SettingsLoaded = true;
|
|
|
+ }
|
|
|
+
|
|
|
+ // Save settings (with a delay after the last modification, so we don't spam disk too much)
|
|
|
+ if (g.SettingsDirtyTimer > 0.0f)
|
|
|
+ {
|
|
|
+ g.SettingsDirtyTimer -= g.IO.DeltaTime;
|
|
|
+ if (g.SettingsDirtyTimer <= 0.0f)
|
|
|
+ {
|
|
|
+ if (g.IO.IniFilename != NULL)
|
|
|
+ SaveIniSettingsToDisk(g.IO.IniFilename);
|
|
|
+ else
|
|
|
+ g.IO.WantSaveIniSettings = true; // Let user know they can call SaveIniSettingsToMemory(). user will need to clear io.WantSaveIniSettings themselves.
|
|
|
+ g.SettingsDirtyTimer = 0.0f;
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
void ImGui::MarkIniSettingsDirty()
|
|
|
{
|
|
|
ImGuiContext& g = *GImGui;
|