|
|
@@ -678,6 +678,7 @@ static bool DataTypeApplyOpFromText(const char* buf, const char* ini
|
|
|
|
|
|
namespace ImGui
|
|
|
{
|
|
|
+static void UpdateManualResize(ImGuiWindow* window, const ImVec2& size_auto_fit, int* border_held, ImU32 resize_grip_col[4]);
|
|
|
static void FocusFrontMostActiveWindow(ImGuiWindow* ignore_window);
|
|
|
}
|
|
|
|
|
|
@@ -4166,14 +4167,13 @@ static ImGuiWindow* CreateNewWindow(const char* name, ImVec2 size, ImGuiWindowFl
|
|
|
{
|
|
|
// Retrieve settings from .ini file
|
|
|
// Use SetWindowPos() or SetNextWindowPos() with the appropriate condition flag to change the initial position of a window.
|
|
|
- window->PosFloat = ImVec2(60, 60);
|
|
|
- window->Pos = ImVec2((float)(int)window->PosFloat.x, (float)(int)window->PosFloat.y);
|
|
|
+ window->Pos = window->PosFloat = ImVec2(60, 60);
|
|
|
|
|
|
if (ImGuiWindowSettings* settings = ImGui::FindWindowSettings(window->ID))
|
|
|
{
|
|
|
SetWindowConditionAllowFlags(window, ImGuiCond_FirstUseEver, false);
|
|
|
window->PosFloat = settings->Pos;
|
|
|
- window->Pos = ImVec2((float)(int)window->PosFloat.x, (float)(int)window->PosFloat.y);
|
|
|
+ window->Pos = ImFloor(window->PosFloat);
|
|
|
window->Collapsed = settings->Collapsed;
|
|
|
if (ImLengthSqr(settings->Size) > 0.00001f)
|
|
|
size = settings->Size;
|
|
|
@@ -4342,6 +4342,93 @@ static ImRect GetBorderRect(ImGuiWindow* window, int border_n, float perp_paddin
|
|
|
return ImRect();
|
|
|
}
|
|
|
|
|
|
+// Handle resize for: Resize Grips, Borders, Gamepad
|
|
|
+static void ImGui::UpdateManualResize(ImGuiWindow* window, const ImVec2& size_auto_fit, int* border_held, ImU32 resize_grip_col[4])
|
|
|
+{
|
|
|
+ ImGuiContext& g = *GImGui;
|
|
|
+ ImGuiWindowFlags flags = window->Flags;
|
|
|
+ if ((flags & ImGuiWindowFlags_NoResize) || (flags & ImGuiWindowFlags_AlwaysAutoResize) || window->AutoFitFramesX > 0 || window->AutoFitFramesY > 0)
|
|
|
+ return;
|
|
|
+
|
|
|
+ const int resize_grip_count = (flags & ImGuiWindowFlags_ResizeFromAnySide) ? 2 : 1; // 4
|
|
|
+ const int resize_border_count = (flags & ImGuiWindowFlags_ResizeFromAnySide) ? 4 : 0;
|
|
|
+ const float grip_draw_size = (float)(int)ImMax(g.FontSize * 1.35f, window->WindowRounding + 1.0f + g.FontSize * 0.2f);
|
|
|
+ const float grip_hover_size = (float)(int)(grip_draw_size * 0.75f);
|
|
|
+
|
|
|
+ ImVec2 pos_target(FLT_MAX, FLT_MAX);
|
|
|
+ ImVec2 size_target(FLT_MAX, FLT_MAX);
|
|
|
+
|
|
|
+ // Manual resize grips
|
|
|
+ PushID("#RESIZE");
|
|
|
+ for (int resize_grip_n = 0; resize_grip_n < resize_grip_count; resize_grip_n++)
|
|
|
+ {
|
|
|
+ const ImGuiResizeGripDef& grip = resize_grip_def[resize_grip_n];
|
|
|
+ const ImVec2 corner = ImLerp(window->Pos, window->Pos + window->Size, grip.CornerPos);
|
|
|
+
|
|
|
+ // Using the FlattenChilds button flag we make the resize button accessible even if we are hovering over a child window
|
|
|
+ ImRect resize_rect(corner, corner + grip.InnerDir * grip_hover_size);
|
|
|
+ resize_rect.FixInverted();
|
|
|
+ bool hovered, held;
|
|
|
+ ButtonBehavior(resize_rect, window->GetID((void*)(intptr_t)resize_grip_n), &hovered, &held, ImGuiButtonFlags_FlattenChildren);
|
|
|
+ if (hovered || held)
|
|
|
+ g.MouseCursor = (resize_grip_n & 1) ? ImGuiMouseCursor_ResizeNESW : ImGuiMouseCursor_ResizeNWSE;
|
|
|
+
|
|
|
+ if (g.HoveredWindow == window && held && g.IO.MouseDoubleClicked[0] && resize_grip_n == 0)
|
|
|
+ {
|
|
|
+ // Manual auto-fit when double-clicking
|
|
|
+ size_target = CalcSizeAfterConstraint(window, size_auto_fit);
|
|
|
+ ClearActiveID();
|
|
|
+ }
|
|
|
+ else if (held)
|
|
|
+ {
|
|
|
+ // Resize from any of the four corners
|
|
|
+ // We don't use an incremental MouseDelta but rather compute an absolute target size based on mouse position
|
|
|
+ ImVec2 corner_target = g.IO.MousePos - g.ActiveIdClickOffset + resize_rect.GetSize() * grip.CornerPos; // Corner of the window corresponding to our corner grip
|
|
|
+ CalcResizePosSizeFromAnyCorner(window, corner_target, grip.CornerPos, &pos_target, &size_target);
|
|
|
+ }
|
|
|
+ if (resize_grip_n == 0 || held || hovered)
|
|
|
+ resize_grip_col[resize_grip_n] = GetColorU32(held ? ImGuiCol_ResizeGripActive : hovered ? ImGuiCol_ResizeGripHovered : ImGuiCol_ResizeGrip);
|
|
|
+ }
|
|
|
+ for (int border_n = 0; border_n < resize_border_count; border_n++)
|
|
|
+ {
|
|
|
+ const float BORDER_SIZE = 5.0f; // FIXME: Only works _inside_ window because of HoveredWindow check.
|
|
|
+ const float BORDER_APPEAR_TIMER = 0.05f; // Reduce visual noise
|
|
|
+ bool hovered, held;
|
|
|
+ ImRect border_rect = GetBorderRect(window, border_n, grip_hover_size, BORDER_SIZE);
|
|
|
+ ButtonBehavior(border_rect, window->GetID((void*)(intptr_t)(border_n + 4)), &hovered, &held, ImGuiButtonFlags_FlattenChildren);
|
|
|
+ if ((hovered && g.HoveredIdTimer > BORDER_APPEAR_TIMER) || held)
|
|
|
+ {
|
|
|
+ g.MouseCursor = (border_n & 1) ? ImGuiMouseCursor_ResizeEW : ImGuiMouseCursor_ResizeNS;
|
|
|
+ if (held) *border_held = border_n;
|
|
|
+ }
|
|
|
+ if (held)
|
|
|
+ {
|
|
|
+ ImVec2 border_target = window->Pos;
|
|
|
+ ImVec2 border_posn;
|
|
|
+ if (border_n == 0) { border_posn = ImVec2(0, 0); border_target.y = (g.IO.MousePos.y - g.ActiveIdClickOffset.y); }
|
|
|
+ if (border_n == 1) { border_posn = ImVec2(1, 0); border_target.x = (g.IO.MousePos.x - g.ActiveIdClickOffset.x + BORDER_SIZE); }
|
|
|
+ if (border_n == 2) { border_posn = ImVec2(0, 1); border_target.y = (g.IO.MousePos.y - g.ActiveIdClickOffset.y + BORDER_SIZE); }
|
|
|
+ if (border_n == 3) { border_posn = ImVec2(0, 0); border_target.x = (g.IO.MousePos.x - g.ActiveIdClickOffset.x); }
|
|
|
+ CalcResizePosSizeFromAnyCorner(window, border_target, border_posn, &pos_target, &size_target);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ PopID();
|
|
|
+
|
|
|
+ // Apply back modified position/size to window
|
|
|
+ if (size_target.x != FLT_MAX)
|
|
|
+ {
|
|
|
+ window->SizeFull = size_target;
|
|
|
+ MarkIniSettingsDirty(window);
|
|
|
+ }
|
|
|
+ if (pos_target.x != FLT_MAX)
|
|
|
+ {
|
|
|
+ window->Pos = window->PosFloat = ImFloor(pos_target);
|
|
|
+ MarkIniSettingsDirty(window);
|
|
|
+ }
|
|
|
+
|
|
|
+ window->Size = window->SizeFull;
|
|
|
+}
|
|
|
+
|
|
|
// Push a new ImGui window to add widgets to.
|
|
|
// - A default window called "Debug" is automatically stacked at the beginning of every frame so you can use widgets without explicitly calling a Begin/End pair.
|
|
|
// - Begin/End can be called multiple times during the frame with the same window name to append content.
|
|
|
@@ -4482,22 +4569,19 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
|
|
|
window->LastFrameActive = current_frame;
|
|
|
window->IDStack.resize(1);
|
|
|
|
|
|
- // Setup draw list and outer clipping rectangle
|
|
|
- window->DrawList->Clear();
|
|
|
- window->DrawList->Flags = (g.Style.AntiAliasedLines ? ImDrawListFlags_AntiAliasedLines : 0) | (g.Style.AntiAliasedFill ? ImDrawListFlags_AntiAliasedFill : 0);
|
|
|
- window->DrawList->PushTextureID(g.Font->ContainerAtlas->TexID);
|
|
|
- ImRect fullscreen_rect(GetVisibleRect());
|
|
|
- if ((flags & ImGuiWindowFlags_ChildWindow) && !(flags & ImGuiWindowFlags_Popup))
|
|
|
- PushClipRect(parent_window->ClipRect.Min, parent_window->ClipRect.Max, true);
|
|
|
- else
|
|
|
- PushClipRect(fullscreen_rect.Min, fullscreen_rect.Max, true);
|
|
|
+ // Lock window rounding, border size and rounding so that altering the border sizes for children doesn't have side-effects.
|
|
|
+ window->WindowRounding = (flags & ImGuiWindowFlags_ChildWindow) ? style.ChildRounding : ((flags & ImGuiWindowFlags_Popup) && !(flags & ImGuiWindowFlags_Modal)) ? style.PopupRounding : style.WindowRounding;
|
|
|
+ window->WindowBorderSize = (flags & ImGuiWindowFlags_ChildWindow) ? style.ChildBorderSize : ((flags & ImGuiWindowFlags_Popup) && !(flags & ImGuiWindowFlags_Modal)) ? style.PopupBorderSize : style.WindowBorderSize;
|
|
|
+ window->WindowPadding = style.WindowPadding;
|
|
|
+ if ((flags & ImGuiWindowFlags_ChildWindow) && !(flags & (ImGuiWindowFlags_AlwaysUseWindowPadding | ImGuiWindowFlags_Popup)) && window->WindowBorderSize == 0.0f)
|
|
|
+ window->WindowPadding = ImVec2(0.0f, (flags & ImGuiWindowFlags_MenuBar) ? style.WindowPadding.y : 0.0f);
|
|
|
|
|
|
if (window_just_activated_by_user)
|
|
|
{
|
|
|
// Popup first latch mouse position, will position itself when it appears next frame
|
|
|
window->AutoPosLastDirection = ImGuiDir_None;
|
|
|
if ((flags & ImGuiWindowFlags_Popup) != 0 && !window_pos_set_by_api)
|
|
|
- window->PosFloat = g.CurrentPopupStack.back().OpenPopupPos;
|
|
|
+ window->Pos = window->PosFloat = g.CurrentPopupStack.back().OpenPopupPos;
|
|
|
}
|
|
|
|
|
|
// Collapse window by double-clicking on title bar
|
|
|
@@ -4538,15 +4622,6 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- // Lock window rounding, border size and rounding so that altering the border sizes for children doesn't have side-effects.
|
|
|
- window->WindowRounding = (flags & ImGuiWindowFlags_ChildWindow) ? style.ChildRounding : ((flags & ImGuiWindowFlags_Popup) && !(flags & ImGuiWindowFlags_Modal)) ? style.PopupRounding : style.WindowRounding;
|
|
|
- window->WindowBorderSize = (flags & ImGuiWindowFlags_ChildWindow) ? style.ChildBorderSize : ((flags & ImGuiWindowFlags_Popup) && !(flags & ImGuiWindowFlags_Modal)) ? style.PopupBorderSize : style.WindowBorderSize;
|
|
|
- window->WindowPadding = style.WindowPadding;
|
|
|
- if ((flags & ImGuiWindowFlags_ChildWindow) && !(flags & (ImGuiWindowFlags_AlwaysUseWindowPadding | ImGuiWindowFlags_Popup)) && window->WindowBorderSize == 0.0f)
|
|
|
- window->WindowPadding = ImVec2(0.0f, (flags & ImGuiWindowFlags_MenuBar) ? style.WindowPadding.y : 0.0f);
|
|
|
- const float window_rounding = window->WindowRounding;
|
|
|
- const float window_border_size = window->WindowBorderSize;
|
|
|
-
|
|
|
// Calculate auto-fit size, handle automatic resize
|
|
|
const ImVec2 size_auto_fit = CalcSizeAutoFit(window, window->SizeContents);
|
|
|
ImVec2 size_full_modified(FLT_MAX, FLT_MAX);
|
|
|
@@ -4651,7 +4726,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
|
|
|
window->PosFloat = ImMin(window->PosFloat, g.IO.DisplaySize - padding);
|
|
|
}
|
|
|
}
|
|
|
- window->Pos = ImVec2((float)(int)window->PosFloat.x, (float)(int)window->PosFloat.y);
|
|
|
+ window->Pos = ImFloor(window->PosFloat);
|
|
|
|
|
|
// Default item width. Make it proportional to window size if window manually resizes
|
|
|
if (window->Size.x > 0.0f && !(flags & ImGuiWindowFlags_Tooltip) && !(flags & ImGuiWindowFlags_AlwaysAutoResize))
|
|
|
@@ -4675,11 +4750,25 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
|
|
|
if (!(flags & (ImGuiWindowFlags_ChildWindow | ImGuiWindowFlags_Tooltip)) || (flags & ImGuiWindowFlags_Popup))
|
|
|
want_focus = true;
|
|
|
|
|
|
+ // DRAWING
|
|
|
+
|
|
|
+ // Setup draw list and outer clipping rectangle
|
|
|
+ window->DrawList->Clear();
|
|
|
+ window->DrawList->Flags = (g.Style.AntiAliasedLines ? ImDrawListFlags_AntiAliasedLines : 0) | (g.Style.AntiAliasedFill ? ImDrawListFlags_AntiAliasedFill : 0);
|
|
|
+ window->DrawList->PushTextureID(g.Font->ContainerAtlas->TexID);
|
|
|
+ ImRect fullscreen_rect(GetVisibleRect());
|
|
|
+ if ((flags & ImGuiWindowFlags_ChildWindow) && !(flags & ImGuiWindowFlags_Popup))
|
|
|
+ PushClipRect(parent_window->ClipRect.Min, parent_window->ClipRect.Max, true);
|
|
|
+ else
|
|
|
+ PushClipRect(fullscreen_rect.Min, fullscreen_rect.Max, true);
|
|
|
+
|
|
|
// Draw modal window background (darkens what is behind them)
|
|
|
if ((flags & ImGuiWindowFlags_Modal) != 0 && window == GetFrontMostModalRootWindow())
|
|
|
window->DrawList->AddRectFilled(fullscreen_rect.Min, fullscreen_rect.Max, GetColorU32(ImGuiCol_ModalWindowDarkening, g.ModalWindowDarkeningRatio));
|
|
|
|
|
|
// Draw window + handle manual resize
|
|
|
+ const float window_rounding = window->WindowRounding;
|
|
|
+ const float window_border_size = window->WindowBorderSize;
|
|
|
ImRect title_bar_rect = window->TitleBarRect();
|
|
|
if (window->Collapsed)
|
|
|
{
|
|
|
@@ -4695,86 +4784,9 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
|
|
|
int border_held = -1;
|
|
|
ImU32 resize_grip_col[4] = { 0 };
|
|
|
const int resize_grip_count = (flags & ImGuiWindowFlags_ResizeFromAnySide) ? 2 : 1; // 4
|
|
|
- const int resize_border_count = (flags & ImGuiWindowFlags_ResizeFromAnySide) ? 4 : 0;
|
|
|
-
|
|
|
- const float grip_draw_size = (float)(int)ImMax(g.FontSize * 1.35f, window_rounding + 1.0f + g.FontSize * 0.2f);
|
|
|
- const float grip_hover_size = (float)(int)(grip_draw_size * 0.75f);
|
|
|
- if (!(flags & ImGuiWindowFlags_AlwaysAutoResize) && window->AutoFitFramesX <= 0 && window->AutoFitFramesY <= 0 && !(flags & ImGuiWindowFlags_NoResize))
|
|
|
- {
|
|
|
- ImVec2 pos_target(FLT_MAX, FLT_MAX);
|
|
|
- ImVec2 size_target(FLT_MAX, FLT_MAX);
|
|
|
-
|
|
|
- // Manual resize grips
|
|
|
- PushID("#RESIZE");
|
|
|
- for (int resize_grip_n = 0; resize_grip_n < resize_grip_count; resize_grip_n++)
|
|
|
- {
|
|
|
- const ImGuiResizeGripDef& grip = resize_grip_def[resize_grip_n];
|
|
|
- const ImVec2 corner = ImLerp(window->Pos, window->Pos + window->Size, grip.CornerPos);
|
|
|
-
|
|
|
- // Using the FlattenChilds button flag we make the resize button accessible even if we are hovering over a child window
|
|
|
- ImRect resize_rect(corner, corner + grip.InnerDir * grip_hover_size);
|
|
|
- resize_rect.FixInverted();
|
|
|
- bool hovered, held;
|
|
|
- ButtonBehavior(resize_rect, window->GetID((void*)(intptr_t)resize_grip_n), &hovered, &held, ImGuiButtonFlags_FlattenChildren);
|
|
|
- if (hovered || held)
|
|
|
- g.MouseCursor = (resize_grip_n & 1) ? ImGuiMouseCursor_ResizeNESW : ImGuiMouseCursor_ResizeNWSE;
|
|
|
-
|
|
|
- if (g.HoveredWindow == window && held && g.IO.MouseDoubleClicked[0] && resize_grip_n == 0)
|
|
|
- {
|
|
|
- // Manual auto-fit when double-clicking
|
|
|
- size_target = CalcSizeAfterConstraint(window, size_auto_fit);
|
|
|
- ClearActiveID();
|
|
|
- }
|
|
|
- else if (held)
|
|
|
- {
|
|
|
- // Resize from any of the four corners
|
|
|
- // We don't use an incremental MouseDelta but rather compute an absolute target size based on mouse position
|
|
|
- ImVec2 corner_target = g.IO.MousePos - g.ActiveIdClickOffset + resize_rect.GetSize() * grip.CornerPos; // Corner of the window corresponding to our corner grip
|
|
|
- CalcResizePosSizeFromAnyCorner(window, corner_target, grip.CornerPos, &pos_target, &size_target);
|
|
|
- }
|
|
|
- if (resize_grip_n == 0 || held || hovered)
|
|
|
- resize_grip_col[resize_grip_n] = GetColorU32(held ? ImGuiCol_ResizeGripActive : hovered ? ImGuiCol_ResizeGripHovered : ImGuiCol_ResizeGrip);
|
|
|
- }
|
|
|
- for (int border_n = 0; border_n < resize_border_count; border_n++)
|
|
|
- {
|
|
|
- const float BORDER_SIZE = 5.0f; // FIXME: Only works _inside_ window because of HoveredWindow check.
|
|
|
- const float BORDER_APPEAR_TIMER = 0.05f; // Reduce visual noise
|
|
|
- bool hovered, held;
|
|
|
- ImRect border_rect = GetBorderRect(window, border_n, grip_hover_size, BORDER_SIZE);
|
|
|
- ButtonBehavior(border_rect, window->GetID((void*)(intptr_t)(border_n+4)), &hovered, &held, ImGuiButtonFlags_FlattenChildren);
|
|
|
- if ((hovered && g.HoveredIdTimer > BORDER_APPEAR_TIMER) || held)
|
|
|
- {
|
|
|
- g.MouseCursor = (border_n & 1) ? ImGuiMouseCursor_ResizeEW : ImGuiMouseCursor_ResizeNS;
|
|
|
- if (held) border_held = border_n;
|
|
|
- }
|
|
|
- if (held)
|
|
|
- {
|
|
|
- ImVec2 border_target = window->Pos;
|
|
|
- ImVec2 border_posn;
|
|
|
- if (border_n == 0) { border_posn = ImVec2(0, 0); border_target.y = (g.IO.MousePos.y - g.ActiveIdClickOffset.y); }
|
|
|
- if (border_n == 1) { border_posn = ImVec2(1, 0); border_target.x = (g.IO.MousePos.x - g.ActiveIdClickOffset.x + BORDER_SIZE); }
|
|
|
- if (border_n == 2) { border_posn = ImVec2(0, 1); border_target.y = (g.IO.MousePos.y - g.ActiveIdClickOffset.y + BORDER_SIZE); }
|
|
|
- if (border_n == 3) { border_posn = ImVec2(0, 0); border_target.x = (g.IO.MousePos.x - g.ActiveIdClickOffset.x); }
|
|
|
- CalcResizePosSizeFromAnyCorner(window, border_target, border_posn, &pos_target, &size_target);
|
|
|
- }
|
|
|
- }
|
|
|
- PopID();
|
|
|
-
|
|
|
- // Apply back modified position/size to window
|
|
|
- if (size_target.x != FLT_MAX)
|
|
|
- {
|
|
|
- window->SizeFull = size_target;
|
|
|
- MarkIniSettingsDirty(window);
|
|
|
- }
|
|
|
- if (pos_target.x != FLT_MAX)
|
|
|
- {
|
|
|
- window->Pos = window->PosFloat = ImVec2((float)(int)pos_target.x, (float)(int)pos_target.y);
|
|
|
- MarkIniSettingsDirty(window);
|
|
|
- }
|
|
|
-
|
|
|
- window->Size = window->SizeFull;
|
|
|
- title_bar_rect = window->TitleBarRect();
|
|
|
- }
|
|
|
+ const float grip_draw_size = (float)(int)ImMax(g.FontSize * 1.35f, window->WindowRounding + 1.0f + g.FontSize * 0.2f);
|
|
|
+ UpdateManualResize(window, size_auto_fit, &border_held, &resize_grip_col[0]);
|
|
|
+ title_bar_rect = window->TitleBarRect();
|
|
|
|
|
|
// Window background, Default Alpha
|
|
|
ImU32 bg_col = GetColorU32(GetWindowBgColorIdxFromFlags(flags));
|
|
|
@@ -5597,7 +5609,7 @@ static void SetWindowPos(ImGuiWindow* window, const ImVec2& pos, ImGuiCond cond)
|
|
|
// Set
|
|
|
const ImVec2 old_pos = window->Pos;
|
|
|
window->PosFloat = pos;
|
|
|
- window->Pos = ImVec2((float)(int)window->PosFloat.x, (float)(int)window->PosFloat.y);
|
|
|
+ window->Pos = ImFloor(pos);
|
|
|
window->DC.CursorPos += (window->Pos - old_pos); // As we happen to move the window while it is being appended to (which is a bad idea - will smear) let's at least offset the cursor
|
|
|
window->DC.CursorMaxPos += (window->Pos - old_pos); // And more importantly we need to adjust this so size calculation doesn't get affected.
|
|
|
}
|