Merge branch 'master' into docking

# Conflicts:
#	imgui.cpp
This commit is contained in:
omar
2019-07-23 13:35:01 -07:00
9 changed files with 176 additions and 119 deletions

169
imgui.cpp
View File

@ -1054,6 +1054,7 @@ static const float NAV_WINDOWING_LIST_APPEAR_DELAY = 0.15f; // Time
// Window resizing from edges (when io.ConfigWindowsResizeFromEdges = true and ImGuiBackendFlags_HasMouseCursors is set in io.BackendFlags by back-end)
static const float WINDOWS_RESIZE_FROM_EDGES_HALF_THICKNESS = 4.0f; // Extend outside and inside windows. Affect FindHoveredWindow().
static const float WINDOWS_RESIZE_FROM_EDGES_FEEDBACK_TIMER = 0.04f; // Reduce visual noise by only highlighting the border after a certain time.
static const float WINDOWS_MOUSE_WHEEL_SCROLL_LOCK_TIMER = 2.00f; // Lock scrolled window (so it doesn't pick child windows that are scrolling through) for a certaint time, unless mouse moved.
// Docking
static const float DOCKING_TRANSPARENT_PAYLOAD_ALPHA = 0.50f; // For use with io.ConfigDockingTransparentPayload. Apply to Viewport _or_ WindowBg in host viewport.
@ -3630,19 +3631,45 @@ static void ImGui::UpdateMouseInputs()
}
}
static void StartLockWheelingWindow(ImGuiWindow* window)
{
ImGuiContext& g = *GImGui;
if (g.WheelingWindow == window)
return;
g.WheelingWindow = window;
g.WheelingWindowRefMousePos = g.IO.MousePos;
g.WheelingWindowTimer = WINDOWS_MOUSE_WHEEL_SCROLL_LOCK_TIMER;
}
void ImGui::UpdateMouseWheel()
{
ImGuiContext& g = *GImGui;
if (!g.HoveredWindow || g.HoveredWindow->Collapsed)
return;
// Reset the locked window if we move the mouse or after the timer elapses
if (g.WheelingWindow != NULL)
{
g.WheelingWindowTimer -= g.IO.DeltaTime;
if (IsMousePosValid() && ImLengthSqr(g.IO.MousePos - g.WheelingWindowRefMousePos) > g.IO.MouseDragThreshold * g.IO.MouseDragThreshold)
g.WheelingWindowTimer = 0.0f;
if (g.WheelingWindowTimer <= 0.0f)
{
g.WheelingWindow = NULL;
g.WheelingWindowTimer = 0.0f;
}
}
if (g.IO.MouseWheel == 0.0f && g.IO.MouseWheelH == 0.0f)
return;
ImGuiWindow* window = g.WheelingWindow ? g.WheelingWindow : g.HoveredWindow;
if (!window || window->Collapsed)
return;
// Zoom / Scale window
// FIXME-OBSOLETE: This is an old feature, it still works but pretty much nobody is using it and may be best redesigned.
if (g.IO.MouseWheel != 0.0f && g.IO.KeyCtrl && g.IO.FontAllowUserScaling)
{
ImGuiWindow* window = g.HoveredWindow;
StartLockWheelingWindow(window);
const float new_font_scale = ImClamp(window->FontWindowScale + g.IO.MouseWheel * 0.10f, 0.50f, 2.50f);
const float scale = new_font_scale / window->FontWindowScale;
window->FontWindowScale = new_font_scale;
@ -3658,20 +3685,19 @@ void ImGui::UpdateMouseWheel()
// Mouse wheel scrolling
// If a child window has the ImGuiWindowFlags_NoScrollWithMouse flag, we give a chance to scroll its parent
// FIXME: Lock scrolling window while not moving (see #2604)
// Vertical Mouse Wheel scrolling
const float wheel_y = (g.IO.MouseWheel != 0.0f && !g.IO.KeyShift) ? g.IO.MouseWheel : 0.0f;
if (wheel_y != 0.0f && !g.IO.KeyCtrl)
{
ImGuiWindow* window = g.HoveredWindow;
StartLockWheelingWindow(window);
while ((window->Flags & ImGuiWindowFlags_ChildWindow) && ((window->ScrollMax.y == 0.0f) || ((window->Flags & ImGuiWindowFlags_NoScrollWithMouse) && !(window->Flags & ImGuiWindowFlags_NoMouseInputs))))
window = window->ParentWindow;
if (!(window->Flags & ImGuiWindowFlags_NoScrollWithMouse) && !(window->Flags & ImGuiWindowFlags_NoMouseInputs))
{
float max_step = window->InnerRect.GetHeight() * 0.67f;
float scroll_step = ImFloor(ImMin(5 * window->CalcFontSize(), max_step));
SetWindowScrollY(window, window->Scroll.y - wheel_y * scroll_step);
SetScrollY(window, window->Scroll.y - wheel_y * scroll_step);
}
}
@ -3679,14 +3705,14 @@ void ImGui::UpdateMouseWheel()
const float wheel_x = (g.IO.MouseWheelH != 0.0f && !g.IO.KeyShift) ? g.IO.MouseWheelH : (g.IO.MouseWheel != 0.0f && g.IO.KeyShift) ? g.IO.MouseWheel : 0.0f;
if (wheel_x != 0.0f && !g.IO.KeyCtrl)
{
ImGuiWindow* window = g.HoveredWindow;
StartLockWheelingWindow(window);
while ((window->Flags & ImGuiWindowFlags_ChildWindow) && ((window->ScrollMax.x == 0.0f) || ((window->Flags & ImGuiWindowFlags_NoScrollWithMouse) && !(window->Flags & ImGuiWindowFlags_NoMouseInputs))))
window = window->ParentWindow;
if (!(window->Flags & ImGuiWindowFlags_NoScrollWithMouse) && !(window->Flags & ImGuiWindowFlags_NoMouseInputs))
{
float max_step = window->InnerRect.GetWidth() * 0.67f;
float scroll_step = ImFloor(ImMin(2 * window->CalcFontSize(), max_step));
SetWindowScrollX(window, window->Scroll.x - wheel_x * scroll_step);
SetScrollX(window, window->Scroll.x - wheel_x * scroll_step);
}
}
}
@ -4151,10 +4177,16 @@ void ImGui::Shutdown(ImGuiContext* context)
g.FontStack.clear();
g.OpenPopupStack.clear();
g.BeginPopupStack.clear();
g.CurrentViewport = g.MouseViewport = g.MouseLastHoveredViewport = NULL;
for (int i = 0; i < g.Viewports.Size; i++)
IM_DELETE(g.Viewports[i]);
g.Viewports.clear();
g.TabBars.Clear();
g.CurrentTabBarStack.clear();
g.ShrinkWidthBuffer.clear();
g.PrivateClipboard.clear();
g.InputTextState.ClearFreeMemory();
@ -6314,6 +6346,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
if (render_decorations_in_parent)
window->DrawList = parent_window->DrawList;
// Handle title bar, scrollbar, resize grips and resize borders
const ImGuiWindow* window_to_highlight = g.NavWindowingTarget ? g.NavWindowingTarget : g.NavWindow;
const bool title_bar_is_highlight = want_focus || (window_to_highlight && (window->RootWindowForTitleBarHighlight == window_to_highlight->RootWindowForTitleBarHighlight || (window->DockNode && window->DockNode == window_to_highlight->DockNode)));
RenderWindowDecorations(window, title_bar_rect, title_bar_is_highlight, handle_borders_and_resize_grips, resize_grip_count, resize_grip_col, resize_grip_draw_size);
@ -7168,16 +7201,6 @@ ImVec2 ImGui::GetWindowPos()
return window->Pos;
}
void ImGui::SetWindowScrollX(ImGuiWindow* window, float new_scroll_x)
{
window->Scroll.x = new_scroll_x;
}
void ImGui::SetWindowScrollY(ImGuiWindow* window, float new_scroll_y)
{
window->Scroll.y = new_scroll_y;
}
void ImGui::SetWindowPos(ImGuiWindow* window, const ImVec2& pos, ImGuiCond cond)
{
// Test condition (NB: bit 0 is always true) and clear flags for next time
@ -7411,7 +7434,8 @@ void ImGui::SetNextWindowClass(const ImGuiWindowClass* window_class)
// FIXME: This is in window space (not screen space!). We should try to obsolete all those functions.
ImVec2 ImGui::GetContentRegionMax()
{
ImGuiWindow* window = GImGui->CurrentWindow;
ImGuiContext& g = *GImGui;
ImGuiWindow* window = g.CurrentWindow;
ImVec2 mx = window->ContentsRegionRect.Max - window->Pos;
if (window->DC.CurrentColumns)
mx.x = window->WorkRect.Max.x - window->Pos.x;
@ -7421,7 +7445,8 @@ ImVec2 ImGui::GetContentRegionMax()
// [Internal] Absolute coordinate. Saner. This is not exposed until we finishing refactoring work rect features.
ImVec2 ImGui::GetContentRegionMaxAbs()
{
ImGuiWindow* window = GImGui->CurrentWindow;
ImGuiContext& g = *GImGui;
ImGuiWindow* window = g.CurrentWindow;
ImVec2 mx = window->ContentsRegionRect.Max;
if (window->DC.CurrentColumns)
mx.x = window->WorkRect.Max.x;
@ -7618,6 +7643,18 @@ void ImGui::SetScrollY(float scroll_y)
window->ScrollTargetCenterRatio.y = 0.0f;
}
void ImGui::SetScrollX(ImGuiWindow* window, float new_scroll_x)
{
window->ScrollTarget.x = new_scroll_x;
window->ScrollTargetCenterRatio.x = 0.0f;
}
void ImGui::SetScrollY(ImGuiWindow* window, float new_scroll_y)
{
window->ScrollTarget.y = new_scroll_y;
window->ScrollTargetCenterRatio.y = 0.0f;
}
void ImGui::SetScrollFromPosX(float local_x, float center_x_ratio)
{
// We store a target position so centering can occur on the next frame when we are guaranteed to have a known window size
@ -9050,9 +9087,9 @@ static void ImGui::NavUpdate()
if (window->DC.NavLayerActiveMask == 0x00 && window->DC.NavHasScroll && g.NavMoveRequest)
{
if (g.NavMoveDir == ImGuiDir_Left || g.NavMoveDir == ImGuiDir_Right)
SetWindowScrollX(window, ImFloor(window->Scroll.x + ((g.NavMoveDir == ImGuiDir_Left) ? -1.0f : +1.0f) * scroll_speed));
SetScrollX(window, ImFloor(window->Scroll.x + ((g.NavMoveDir == ImGuiDir_Left) ? -1.0f : +1.0f) * scroll_speed));
if (g.NavMoveDir == ImGuiDir_Up || g.NavMoveDir == ImGuiDir_Down)
SetWindowScrollY(window, ImFloor(window->Scroll.y + ((g.NavMoveDir == ImGuiDir_Up) ? -1.0f : +1.0f) * scroll_speed));
SetScrollY(window, ImFloor(window->Scroll.y + ((g.NavMoveDir == ImGuiDir_Up) ? -1.0f : +1.0f) * scroll_speed));
}
// *Normal* Manual scroll with NavScrollXXX keys
@ -9060,12 +9097,12 @@ static void ImGui::NavUpdate()
ImVec2 scroll_dir = GetNavInputAmount2d(ImGuiNavDirSourceFlags_PadLStick, ImGuiInputReadMode_Down, 1.0f/10.0f, 10.0f);
if (scroll_dir.x != 0.0f && window->ScrollbarX)
{
SetWindowScrollX(window, ImFloor(window->Scroll.x + scroll_dir.x * scroll_speed));
SetScrollX(window, ImFloor(window->Scroll.x + scroll_dir.x * scroll_speed));
g.NavMoveFromClampedRefRect = true;
}
if (scroll_dir.y != 0.0f)
{
SetWindowScrollY(window, ImFloor(window->Scroll.y + scroll_dir.y * scroll_speed));
SetScrollY(window, ImFloor(window->Scroll.y + scroll_dir.y * scroll_speed));
g.NavMoveFromClampedRefRect = true;
}
}
@ -9169,42 +9206,44 @@ static void ImGui::NavUpdateMoveResult()
static float ImGui::NavUpdatePageUpPageDown(int allowed_dir_flags)
{
ImGuiContext& g = *GImGui;
if (g.NavMoveDir == ImGuiDir_None && g.NavWindow && !(g.NavWindow->Flags & ImGuiWindowFlags_NoNavInputs) && !g.NavWindowingTarget && g.NavLayer == 0)
if (g.NavMoveDir != ImGuiDir_None || g.NavWindow == NULL)
return 0.0f;
if ((g.NavWindow->Flags & ImGuiWindowFlags_NoNavInputs) || g.NavWindowingTarget != NULL || g.NavLayer != 0)
return 0.0f;
ImGuiWindow* window = g.NavWindow;
bool page_up_held = IsKeyDown(g.IO.KeyMap[ImGuiKey_PageUp]) && (allowed_dir_flags & (1 << ImGuiDir_Up));
bool page_down_held = IsKeyDown(g.IO.KeyMap[ImGuiKey_PageDown]) && (allowed_dir_flags & (1 << ImGuiDir_Down));
if (page_up_held != page_down_held) // If either (not both) are pressed
{
ImGuiWindow* window = g.NavWindow;
bool page_up_held = IsKeyDown(g.IO.KeyMap[ImGuiKey_PageUp]) && (allowed_dir_flags & (1 << ImGuiDir_Up));
bool page_down_held = IsKeyDown(g.IO.KeyMap[ImGuiKey_PageDown]) && (allowed_dir_flags & (1 << ImGuiDir_Down));
if (page_up_held != page_down_held) // If either (not both) are pressed
if (window->DC.NavLayerActiveMask == 0x00 && window->DC.NavHasScroll)
{
if (window->DC.NavLayerActiveMask == 0x00 && window->DC.NavHasScroll)
// Fallback manual-scroll when window has no navigable item
if (IsKeyPressed(g.IO.KeyMap[ImGuiKey_PageUp], true))
SetScrollY(window, window->Scroll.y - window->InnerRect.GetHeight());
else if (IsKeyPressed(g.IO.KeyMap[ImGuiKey_PageDown], true))
SetScrollY(window, window->Scroll.y + window->InnerRect.GetHeight());
}
else
{
const ImRect& nav_rect_rel = window->NavRectRel[g.NavLayer];
const float page_offset_y = ImMax(0.0f, window->InnerRect.GetHeight() - window->CalcFontSize() * 1.0f + nav_rect_rel.GetHeight());
float nav_scoring_rect_offset_y = 0.0f;
if (IsKeyPressed(g.IO.KeyMap[ImGuiKey_PageUp], true))
{
// Fallback manual-scroll when window has no navigable item
if (IsKeyPressed(g.IO.KeyMap[ImGuiKey_PageUp], true))
SetWindowScrollY(window, window->Scroll.y - window->InnerRect.GetHeight());
else if (IsKeyPressed(g.IO.KeyMap[ImGuiKey_PageDown], true))
SetWindowScrollY(window, window->Scroll.y + window->InnerRect.GetHeight());
nav_scoring_rect_offset_y = -page_offset_y;
g.NavMoveDir = ImGuiDir_Down; // Because our scoring rect is offset, we intentionally request the opposite direction (so we can always land on the last item)
g.NavMoveClipDir = ImGuiDir_Up;
g.NavMoveRequestFlags = ImGuiNavMoveFlags_AllowCurrentNavId | ImGuiNavMoveFlags_AlsoScoreVisibleSet;
}
else
else if (IsKeyPressed(g.IO.KeyMap[ImGuiKey_PageDown], true))
{
const ImRect& nav_rect_rel = window->NavRectRel[g.NavLayer];
const float page_offset_y = ImMax(0.0f, window->InnerRect.GetHeight() - window->CalcFontSize() * 1.0f + nav_rect_rel.GetHeight());
float nav_scoring_rect_offset_y = 0.0f;
if (IsKeyPressed(g.IO.KeyMap[ImGuiKey_PageUp], true))
{
nav_scoring_rect_offset_y = -page_offset_y;
g.NavMoveDir = ImGuiDir_Down; // Because our scoring rect is offset, we intentionally request the opposite direction (so we can always land on the last item)
g.NavMoveClipDir = ImGuiDir_Up;
g.NavMoveRequestFlags = ImGuiNavMoveFlags_AllowCurrentNavId | ImGuiNavMoveFlags_AlsoScoreVisibleSet;
}
else if (IsKeyPressed(g.IO.KeyMap[ImGuiKey_PageDown], true))
{
nav_scoring_rect_offset_y = +page_offset_y;
g.NavMoveDir = ImGuiDir_Up; // Because our scoring rect is offset, we intentionally request the opposite direction (so we can always land on the last item)
g.NavMoveClipDir = ImGuiDir_Down;
g.NavMoveRequestFlags = ImGuiNavMoveFlags_AllowCurrentNavId | ImGuiNavMoveFlags_AlsoScoreVisibleSet;
}
return nav_scoring_rect_offset_y;
nav_scoring_rect_offset_y = +page_offset_y;
g.NavMoveDir = ImGuiDir_Up; // Because our scoring rect is offset, we intentionally request the opposite direction (so we can always land on the last item)
g.NavMoveClipDir = ImGuiDir_Down;
g.NavMoveRequestFlags = ImGuiNavMoveFlags_AllowCurrentNavId | ImGuiNavMoveFlags_AlsoScoreVisibleSet;
}
return nav_scoring_rect_offset_y;
}
}
return 0.0f;
@ -14404,15 +14443,17 @@ void ImGui::ShowMetricsWindow(bool* p_open)
return;
}
// State
enum { WRT_OuterRect, WRT_OuterRectClipped, WRT_InnerRect, WRT_InnerClipRect, WRT_WorkRect, WRT_Contents, WRT_ContentsRegionRect, WRT_Count }; // Windows Rect Type
const char* wrt_rects_names[WRT_Count] = { "OuterRect", "OuterRectClipped", "InnerRect", "InnerClipRect", "WorkRect", "Contents", "ContentsRegionRect" };
static bool show_windows_begin_order = false;
static bool show_windows_rects = false;
static int show_windows_rect_type = WRT_WorkRect;
static bool show_windows_begin_order = false;
static bool show_drawcmd_clip_rects = true;
static bool show_window_dock_info = false;
static bool show_docking_nodes = false;
// Basic info
ImGuiContext& g = *GImGui;
ImGuiIO& io = ImGui::GetIO();
ImGui::Text("Dear ImGui %s", ImGui::GetVersion());
ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / io.Framerate, io.Framerate);
@ -14666,8 +14707,6 @@ void ImGui::ShowMetricsWindow(bool* p_open)
}
};
// Access private state, we are going to display the draw lists from last frame
ImGuiContext& g = *GImGui;
Funcs::NodeWindows(g.Windows, "Windows");
if (ImGui::TreeNode("Viewport", "Viewports (%d)", g.Viewports.Size))
{
@ -14712,7 +14751,7 @@ void ImGui::ShowMetricsWindow(bool* p_open)
if (ImGui::TreeNode("Docking"))
{
ImGuiDockContext* dc = g.DockContext;
ImGui::Checkbox("Ctrl shows window dock info", &show_window_dock_info);
ImGui::Checkbox("Ctrl shows window dock info", &show_docking_nodes);
if (ImGui::TreeNode("Dock nodes"))
{
@ -14759,6 +14798,13 @@ void ImGui::ShowMetricsWindow(bool* p_open)
ImGui::TreePop();
}
#if 0
if (ImGui::TreeNode("Tables", "Tables (%d)", g.Tables.Data.Size))
{
ImGui::TreePop();
}
#endif
if (ImGui::TreeNode("Internal state"))
{
const char* input_source_names[] = { "None", "Mouse", "Nav", "NavKeyboard", "NavGamepad" }; IM_ASSERT(IM_ARRAYSIZE(input_source_names) == ImGuiInputSource_COUNT);
@ -14807,6 +14853,7 @@ void ImGui::ShowMetricsWindow(bool* p_open)
ImGui::TreePop();
}
// Tool: Display windows Rectangles and Begin Order
if (show_windows_rects || show_windows_begin_order)
{
for (int n = 0; n < g.Windows.Size; n++)
@ -14831,7 +14878,7 @@ void ImGui::ShowMetricsWindow(bool* p_open)
}
}
if (show_window_dock_info && g.IO.KeyCtrl)
if (show_docking_nodes && g.IO.KeyCtrl)
{
for (int n = 0; n < g.DockContext->Nodes.Data.Size; n++)
if (ImGuiDockNode* node = (ImGuiDockNode*)g.DockContext->Nodes.Data[n].val_p)