Merge branch 'master' into docking

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

View File

@ -122,7 +122,6 @@ Other Changes:
any more. Forwarding can still be disabled by setting ImGuiWindowFlags_NoInputs. (amend #1502, #1380). any more. Forwarding can still be disabled by setting ImGuiWindowFlags_NoInputs. (amend #1502, #1380).
- Window: Fixed old SetWindowFontScale() api value from not being inherited by child window. Added - Window: Fixed old SetWindowFontScale() api value from not being inherited by child window. Added
comments about the right way to scale your UI (load a font at the right side, rebuild atlas, scale style). comments about the right way to scale your UI (load a font at the right side, rebuild atlas, scale style).
- Scrollbar: Avoid overlapping the opposite side when window (often a child window) is forcibly too small.
- Combo: Hide arrow when there's not enough space even for the square button. - Combo: Hide arrow when there's not enough space even for the square button.
- TabBar: Fixed unfocused tab bar separator color (was using ImGuiCol_Tab, should use ImGuiCol_TabUnfocusedActive). - TabBar: Fixed unfocused tab bar separator color (was using ImGuiCol_Tab, should use ImGuiCol_TabUnfocusedActive).
- Columns: Fixed a regression from 1.71 where the right-side of the contents rectangle within each column - Columns: Fixed a regression from 1.71 where the right-side of the contents rectangle within each column
@ -131,11 +130,21 @@ Other Changes:
worth of asymmetrical/extraneous padding, note that there's another half that conservatively has to offset worth of asymmetrical/extraneous padding, note that there's another half that conservatively has to offset
the right-most column, otherwise it's clipping width won't match the other column). (#125, #2666) the right-most column, otherwise it's clipping width won't match the other column). (#125, #2666)
- Columns: Improved honoring alignment with various values of ItemSpacing.x and WindowPadding.x. (#125, #2666) - Columns: Improved honoring alignment with various values of ItemSpacing.x and WindowPadding.x. (#125, #2666)
- Word-wrapping: Fixed overzealous word-wrapping when glyph edge lands exactly on the limit. Because
of this, auto-fitting exactly unwrapped text would make it wrap. (fixes initial 1.15 commit, 78645a7d).
- Columns: Made GetColumnOffset() and GetColumnWidth() behave when there's no column set, consistently with - Columns: Made GetColumnOffset() and GetColumnWidth() behave when there's no column set, consistently with
other column functions. (#2683) other column functions. (#2683)
- InputTextMultiline: Fixed vertical scrolling tracking glitch.
- Word-wrapping: Fixed overzealous word-wrapping when glyph edge lands exactly on the limit. Because
of this, auto-fitting exactly unwrapped text would make it wrap. (fixes initial 1.15 commit, 78645a7d).
- Scrolling: Made mouse-wheel scrolling lock the underlying window until the mouse is moved again or
until a short delay expires (2 seconds). This allow uninterrupted scroll even if child windows are
passing under the mouse cursor. (#2604)
- Scrolling: Made it possible for mouse wheel and navigation-triggered scrolling to override a call to
SetScrollX()/SetScrollY(), making it possible to use a simpler stateless pattern for auto-scrolling:
// (Submit items..)
if (ImGui::GetScrollY() >= ImGui::GetScrollMaxY()) // Keep scrolling at the bottom if already
ImGui::SetScrollHereY(1.0f);
- Scrolling: Added SetScrollHereX(), SetScrollFromPosX() for completeness. (#1580) [@kevreco] - Scrolling: Added SetScrollHereX(), SetScrollFromPosX() for completeness. (#1580) [@kevreco]
- Scrollbar: Avoid overlapping the opposite side when window (often a child window) is forcibly too small.
- Style: Attenuated default opacity of ImGuiCol_Separator in Classic and Light styles. - Style: Attenuated default opacity of ImGuiCol_Separator in Classic and Light styles.
- Style: Added style.ColorButtonPosition (left/right, defaults to ImGuiDir_Right) to move the color button - Style: Added style.ColorButtonPosition (left/right, defaults to ImGuiDir_Right) to move the color button
of ColorEdit3/ColorEdit4 functions to either side of the inputs. of ColorEdit3/ColorEdit4 functions to either side of the inputs.
@ -154,6 +163,7 @@ Other Changes:
- ImDrawListSplitter: Fixed memory leak when using low-level split api (was not affecting ImDrawList api, - ImDrawListSplitter: Fixed memory leak when using low-level split api (was not affecting ImDrawList api,
also this type was added in 1.71 and not advertised as a public-facing feature). also this type was added in 1.71 and not advertised as a public-facing feature).
- Fonts: binary_to_compressed_c.cpp: Display an error message if failing to open/read the input font file. - Fonts: binary_to_compressed_c.cpp: Display an error message if failing to open/read the input font file.
- Demo: Log, Console: Using a simpler stateless pattern for auto-scrolling.
- Backends: DX10/DX11: Backup, clear and restore Geometry Shader is any is bound when calling renderer. - Backends: DX10/DX11: Backup, clear and restore Geometry Shader is any is bound when calling renderer.
- Backends: DX11: Clear Hull Shader, Domain Shader, Compute Shader before rendering. Not backing/restoring them. - Backends: DX11: Clear Hull Shader, Domain Shader, Compute Shader before rendering. Not backing/restoring them.
- Backends: OSX: Disabled default native Mac clipboard copy/paste implementation in core library (added in 1.71), - Backends: OSX: Disabled default native Mac clipboard copy/paste implementation in core library (added in 1.71),

View File

@ -1,6 +1,6 @@
dear imgui dear imgui
===== =====
[![Build Status](https://travis-ci.org/ocornut/imgui.svg?branch=master)](https://travis-ci.org/ocornut/imgui) [![Build Status](https://api.travis-ci.com/ocornut/imgui.svg?branch=master)](https://travis-ci.com/ocornut/imgui)
[![Coverity Status](https://scan.coverity.com/projects/4720/badge.svg)](https://scan.coverity.com/projects/4720) [![Coverity Status](https://scan.coverity.com/projects/4720/badge.svg)](https://scan.coverity.com/projects/4720)
_(This library is free as in freedom, but needs your support to sustain its development. In addition to maintenance and stability there are many desirable features yet to be added. If your company is using dear imgui, please consider reaching out for invoiced financial support. If you are an individual using dear imgui, please consider donating via Patreon or PayPal.)_ _(This library is free as in freedom, but needs your support to sustain its development. In addition to maintenance and stability there are many desirable features yet to be added. If your company is using dear imgui, please consider reaching out for invoiced financial support. If you are an individual using dear imgui, please consider donating via Patreon or PayPal.)_

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) // 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_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_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 // Docking
static const float DOCKING_TRANSPARENT_PAYLOAD_ALPHA = 0.50f; // For use with io.ConfigDockingTransparentPayload. Apply to Viewport _or_ WindowBg in host viewport. 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() void ImGui::UpdateMouseWheel()
{ {
ImGuiContext& g = *GImGui; 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) if (g.IO.MouseWheel == 0.0f && g.IO.MouseWheelH == 0.0f)
return; return;
ImGuiWindow* window = g.WheelingWindow ? g.WheelingWindow : g.HoveredWindow;
if (!window || window->Collapsed)
return;
// Zoom / Scale window // 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. // 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) 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 new_font_scale = ImClamp(window->FontWindowScale + g.IO.MouseWheel * 0.10f, 0.50f, 2.50f);
const float scale = new_font_scale / window->FontWindowScale; const float scale = new_font_scale / window->FontWindowScale;
window->FontWindowScale = new_font_scale; window->FontWindowScale = new_font_scale;
@ -3658,20 +3685,19 @@ void ImGui::UpdateMouseWheel()
// Mouse wheel scrolling // Mouse wheel scrolling
// If a child window has the ImGuiWindowFlags_NoScrollWithMouse flag, we give a chance to scroll its parent // 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 // Vertical Mouse Wheel scrolling
const float wheel_y = (g.IO.MouseWheel != 0.0f && !g.IO.KeyShift) ? g.IO.MouseWheel : 0.0f; 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) 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)))) while ((window->Flags & ImGuiWindowFlags_ChildWindow) && ((window->ScrollMax.y == 0.0f) || ((window->Flags & ImGuiWindowFlags_NoScrollWithMouse) && !(window->Flags & ImGuiWindowFlags_NoMouseInputs))))
window = window->ParentWindow; window = window->ParentWindow;
if (!(window->Flags & ImGuiWindowFlags_NoScrollWithMouse) && !(window->Flags & ImGuiWindowFlags_NoMouseInputs)) if (!(window->Flags & ImGuiWindowFlags_NoScrollWithMouse) && !(window->Flags & ImGuiWindowFlags_NoMouseInputs))
{ {
float max_step = window->InnerRect.GetHeight() * 0.67f; float max_step = window->InnerRect.GetHeight() * 0.67f;
float scroll_step = ImFloor(ImMin(5 * window->CalcFontSize(), max_step)); 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; 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) 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)))) while ((window->Flags & ImGuiWindowFlags_ChildWindow) && ((window->ScrollMax.x == 0.0f) || ((window->Flags & ImGuiWindowFlags_NoScrollWithMouse) && !(window->Flags & ImGuiWindowFlags_NoMouseInputs))))
window = window->ParentWindow; window = window->ParentWindow;
if (!(window->Flags & ImGuiWindowFlags_NoScrollWithMouse) && !(window->Flags & ImGuiWindowFlags_NoMouseInputs)) if (!(window->Flags & ImGuiWindowFlags_NoScrollWithMouse) && !(window->Flags & ImGuiWindowFlags_NoMouseInputs))
{ {
float max_step = window->InnerRect.GetWidth() * 0.67f; float max_step = window->InnerRect.GetWidth() * 0.67f;
float scroll_step = ImFloor(ImMin(2 * window->CalcFontSize(), max_step)); 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.FontStack.clear();
g.OpenPopupStack.clear(); g.OpenPopupStack.clear();
g.BeginPopupStack.clear(); g.BeginPopupStack.clear();
g.CurrentViewport = g.MouseViewport = g.MouseLastHoveredViewport = NULL; g.CurrentViewport = g.MouseViewport = g.MouseLastHoveredViewport = NULL;
for (int i = 0; i < g.Viewports.Size; i++) for (int i = 0; i < g.Viewports.Size; i++)
IM_DELETE(g.Viewports[i]); IM_DELETE(g.Viewports[i]);
g.Viewports.clear(); g.Viewports.clear();
g.TabBars.Clear();
g.CurrentTabBarStack.clear();
g.ShrinkWidthBuffer.clear();
g.PrivateClipboard.clear(); g.PrivateClipboard.clear();
g.InputTextState.ClearFreeMemory(); g.InputTextState.ClearFreeMemory();
@ -6314,6 +6346,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
if (render_decorations_in_parent) if (render_decorations_in_parent)
window->DrawList = parent_window->DrawList; 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 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))); 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); 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; 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) void ImGui::SetWindowPos(ImGuiWindow* window, const ImVec2& pos, ImGuiCond cond)
{ {
// Test condition (NB: bit 0 is always true) and clear flags for next time // 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. // FIXME: This is in window space (not screen space!). We should try to obsolete all those functions.
ImVec2 ImGui::GetContentRegionMax() ImVec2 ImGui::GetContentRegionMax()
{ {
ImGuiWindow* window = GImGui->CurrentWindow; ImGuiContext& g = *GImGui;
ImGuiWindow* window = g.CurrentWindow;
ImVec2 mx = window->ContentsRegionRect.Max - window->Pos; ImVec2 mx = window->ContentsRegionRect.Max - window->Pos;
if (window->DC.CurrentColumns) if (window->DC.CurrentColumns)
mx.x = window->WorkRect.Max.x - window->Pos.x; 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. // [Internal] Absolute coordinate. Saner. This is not exposed until we finishing refactoring work rect features.
ImVec2 ImGui::GetContentRegionMaxAbs() ImVec2 ImGui::GetContentRegionMaxAbs()
{ {
ImGuiWindow* window = GImGui->CurrentWindow; ImGuiContext& g = *GImGui;
ImGuiWindow* window = g.CurrentWindow;
ImVec2 mx = window->ContentsRegionRect.Max; ImVec2 mx = window->ContentsRegionRect.Max;
if (window->DC.CurrentColumns) if (window->DC.CurrentColumns)
mx.x = window->WorkRect.Max.x; mx.x = window->WorkRect.Max.x;
@ -7618,6 +7643,18 @@ void ImGui::SetScrollY(float scroll_y)
window->ScrollTargetCenterRatio.y = 0.0f; 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) 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 // 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 (window->DC.NavLayerActiveMask == 0x00 && window->DC.NavHasScroll && g.NavMoveRequest)
{ {
if (g.NavMoveDir == ImGuiDir_Left || g.NavMoveDir == ImGuiDir_Right) 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) 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 // *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); ImVec2 scroll_dir = GetNavInputAmount2d(ImGuiNavDirSourceFlags_PadLStick, ImGuiInputReadMode_Down, 1.0f/10.0f, 10.0f);
if (scroll_dir.x != 0.0f && window->ScrollbarX) 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; g.NavMoveFromClampedRefRect = true;
} }
if (scroll_dir.y != 0.0f) 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; g.NavMoveFromClampedRefRect = true;
} }
} }
@ -9169,42 +9206,44 @@ static void ImGui::NavUpdateMoveResult()
static float ImGui::NavUpdatePageUpPageDown(int allowed_dir_flags) static float ImGui::NavUpdatePageUpPageDown(int allowed_dir_flags)
{ {
ImGuiContext& g = *GImGui; 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; if (window->DC.NavLayerActiveMask == 0x00 && window->DC.NavHasScroll)
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) // 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 nav_scoring_rect_offset_y = -page_offset_y;
if (IsKeyPressed(g.IO.KeyMap[ImGuiKey_PageUp], true)) 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)
SetWindowScrollY(window, window->Scroll.y - window->InnerRect.GetHeight()); g.NavMoveClipDir = ImGuiDir_Up;
else if (IsKeyPressed(g.IO.KeyMap[ImGuiKey_PageDown], true)) g.NavMoveRequestFlags = ImGuiNavMoveFlags_AllowCurrentNavId | ImGuiNavMoveFlags_AlsoScoreVisibleSet;
SetWindowScrollY(window, window->Scroll.y + window->InnerRect.GetHeight());
} }
else else if (IsKeyPressed(g.IO.KeyMap[ImGuiKey_PageDown], true))
{ {
const ImRect& nav_rect_rel = window->NavRectRel[g.NavLayer]; nav_scoring_rect_offset_y = +page_offset_y;
const float page_offset_y = ImMax(0.0f, window->InnerRect.GetHeight() - window->CalcFontSize() * 1.0f + nav_rect_rel.GetHeight()); 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)
float nav_scoring_rect_offset_y = 0.0f; g.NavMoveClipDir = ImGuiDir_Down;
if (IsKeyPressed(g.IO.KeyMap[ImGuiKey_PageUp], true)) g.NavMoveRequestFlags = ImGuiNavMoveFlags_AllowCurrentNavId | ImGuiNavMoveFlags_AlsoScoreVisibleSet;
{
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;
} }
return nav_scoring_rect_offset_y;
} }
} }
return 0.0f; return 0.0f;
@ -14404,15 +14443,17 @@ void ImGui::ShowMetricsWindow(bool* p_open)
return; return;
} }
// State
enum { WRT_OuterRect, WRT_OuterRectClipped, WRT_InnerRect, WRT_InnerClipRect, WRT_WorkRect, WRT_Contents, WRT_ContentsRegionRect, WRT_Count }; // Windows Rect Type 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" }; 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 bool show_windows_rects = false;
static int show_windows_rect_type = WRT_WorkRect; 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_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(); ImGuiIO& io = ImGui::GetIO();
ImGui::Text("Dear ImGui %s", ImGui::GetVersion()); ImGui::Text("Dear ImGui %s", ImGui::GetVersion());
ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / io.Framerate, io.Framerate); 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"); Funcs::NodeWindows(g.Windows, "Windows");
if (ImGui::TreeNode("Viewport", "Viewports (%d)", g.Viewports.Size)) if (ImGui::TreeNode("Viewport", "Viewports (%d)", g.Viewports.Size))
{ {
@ -14712,7 +14751,7 @@ void ImGui::ShowMetricsWindow(bool* p_open)
if (ImGui::TreeNode("Docking")) if (ImGui::TreeNode("Docking"))
{ {
ImGuiDockContext* dc = g.DockContext; 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")) if (ImGui::TreeNode("Dock nodes"))
{ {
@ -14759,6 +14798,13 @@ void ImGui::ShowMetricsWindow(bool* p_open)
ImGui::TreePop(); ImGui::TreePop();
} }
#if 0
if (ImGui::TreeNode("Tables", "Tables (%d)", g.Tables.Data.Size))
{
ImGui::TreePop();
}
#endif
if (ImGui::TreeNode("Internal state")) if (ImGui::TreeNode("Internal state"))
{ {
const char* input_source_names[] = { "None", "Mouse", "Nav", "NavKeyboard", "NavGamepad" }; IM_ASSERT(IM_ARRAYSIZE(input_source_names) == ImGuiInputSource_COUNT); 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(); ImGui::TreePop();
} }
// Tool: Display windows Rectangles and Begin Order
if (show_windows_rects || show_windows_begin_order) if (show_windows_rects || show_windows_begin_order)
{ {
for (int n = 0; n < g.Windows.Size; n++) 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++) for (int n = 0; n < g.DockContext->Nodes.Data.Size; n++)
if (ImGuiDockNode* node = (ImGuiDockNode*)g.DockContext->Nodes.Data[n].val_p) if (ImGuiDockNode* node = (ImGuiDockNode*)g.DockContext->Nodes.Data[n].val_p)

View File

@ -1931,6 +1931,7 @@ struct ImDrawListSplitter
enum ImDrawCornerFlags_ enum ImDrawCornerFlags_
{ {
ImDrawCornerFlags_None = 0,
ImDrawCornerFlags_TopLeft = 1 << 0, // 0x1 ImDrawCornerFlags_TopLeft = 1 << 0, // 0x1
ImDrawCornerFlags_TopRight = 1 << 1, // 0x2 ImDrawCornerFlags_TopRight = 1 << 1, // 0x2
ImDrawCornerFlags_BotLeft = 1 << 2, // 0x4 ImDrawCornerFlags_BotLeft = 1 << 2, // 0x4
@ -1991,8 +1992,8 @@ struct ImDrawList
// Primitives // Primitives
IMGUI_API void AddLine(const ImVec2& a, const ImVec2& b, ImU32 col, float thickness = 1.0f); IMGUI_API void AddLine(const ImVec2& a, const ImVec2& b, ImU32 col, float thickness = 1.0f);
IMGUI_API void AddRect(const ImVec2& a, const ImVec2& b, ImU32 col, float rounding = 0.0f, int rounding_corners_flags = ImDrawCornerFlags_All, float thickness = 1.0f); // a: upper-left, b: lower-right (== upper-left + size), rounding_corners_flags: 4-bits corresponding to which corner to round IMGUI_API void AddRect(const ImVec2& a, const ImVec2& b, ImU32 col, float rounding = 0.0f, ImDrawCornerFlags rounding_corners = ImDrawCornerFlags_All, float thickness = 1.0f); // a: upper-left, b: lower-right (== upper-left + size), rounding_corners_flags: 4-bits corresponding to which corner to round
IMGUI_API void AddRectFilled(const ImVec2& a, const ImVec2& b, ImU32 col, float rounding = 0.0f, int rounding_corners_flags = ImDrawCornerFlags_All); // a: upper-left, b: lower-right (== upper-left + size) IMGUI_API void AddRectFilled(const ImVec2& a, const ImVec2& b, ImU32 col, float rounding = 0.0f, ImDrawCornerFlags rounding_corners = ImDrawCornerFlags_All); // a: upper-left, b: lower-right (== upper-left + size)
IMGUI_API void AddRectFilledMultiColor(const ImVec2& a, const ImVec2& b, ImU32 col_upr_left, ImU32 col_upr_right, ImU32 col_bot_right, ImU32 col_bot_left); IMGUI_API void AddRectFilledMultiColor(const ImVec2& a, const ImVec2& b, ImU32 col_upr_left, ImU32 col_upr_right, ImU32 col_bot_right, ImU32 col_bot_left);
IMGUI_API void AddQuad(const ImVec2& a, const ImVec2& b, const ImVec2& c, const ImVec2& d, ImU32 col, float thickness = 1.0f); IMGUI_API void AddQuad(const ImVec2& a, const ImVec2& b, const ImVec2& c, const ImVec2& d, ImU32 col, float thickness = 1.0f);
IMGUI_API void AddQuadFilled(const ImVec2& a, const ImVec2& b, const ImVec2& c, const ImVec2& d, ImU32 col); IMGUI_API void AddQuadFilled(const ImVec2& a, const ImVec2& b, const ImVec2& c, const ImVec2& d, ImU32 col);
@ -2004,7 +2005,7 @@ struct ImDrawList
IMGUI_API void AddText(const ImFont* font, float font_size, const ImVec2& pos, ImU32 col, const char* text_begin, const char* text_end = NULL, float wrap_width = 0.0f, const ImVec4* cpu_fine_clip_rect = NULL); IMGUI_API void AddText(const ImFont* font, float font_size, const ImVec2& pos, ImU32 col, const char* text_begin, const char* text_end = NULL, float wrap_width = 0.0f, const ImVec4* cpu_fine_clip_rect = NULL);
IMGUI_API void AddImage(ImTextureID user_texture_id, const ImVec2& a, const ImVec2& b, const ImVec2& uv_a = ImVec2(0,0), const ImVec2& uv_b = ImVec2(1,1), ImU32 col = IM_COL32_WHITE); IMGUI_API void AddImage(ImTextureID user_texture_id, const ImVec2& a, const ImVec2& b, const ImVec2& uv_a = ImVec2(0,0), const ImVec2& uv_b = ImVec2(1,1), ImU32 col = IM_COL32_WHITE);
IMGUI_API void AddImageQuad(ImTextureID user_texture_id, const ImVec2& a, const ImVec2& b, const ImVec2& c, const ImVec2& d, const ImVec2& uv_a = ImVec2(0,0), const ImVec2& uv_b = ImVec2(1,0), const ImVec2& uv_c = ImVec2(1,1), const ImVec2& uv_d = ImVec2(0,1), ImU32 col = IM_COL32_WHITE); IMGUI_API void AddImageQuad(ImTextureID user_texture_id, const ImVec2& a, const ImVec2& b, const ImVec2& c, const ImVec2& d, const ImVec2& uv_a = ImVec2(0,0), const ImVec2& uv_b = ImVec2(1,0), const ImVec2& uv_c = ImVec2(1,1), const ImVec2& uv_d = ImVec2(0,1), ImU32 col = IM_COL32_WHITE);
IMGUI_API void AddImageRounded(ImTextureID user_texture_id, const ImVec2& a, const ImVec2& b, const ImVec2& uv_a, const ImVec2& uv_b, ImU32 col, float rounding, int rounding_corners = ImDrawCornerFlags_All); IMGUI_API void AddImageRounded(ImTextureID user_texture_id, const ImVec2& a, const ImVec2& b, const ImVec2& uv_a, const ImVec2& uv_b, ImU32 col, float rounding, ImDrawCornerFlags rounding_corners = ImDrawCornerFlags_All);
IMGUI_API void AddPolyline(const ImVec2* points, int num_points, ImU32 col, bool closed, float thickness); IMGUI_API void AddPolyline(const ImVec2* points, int num_points, ImU32 col, bool closed, float thickness);
IMGUI_API void AddConvexPolyFilled(const ImVec2* points, int num_points, ImU32 col); // Note: Anti-aliased filling requires points to be in clockwise order. IMGUI_API void AddConvexPolyFilled(const ImVec2* points, int num_points, ImU32 col); // Note: Anti-aliased filling requires points to be in clockwise order.
IMGUI_API void AddBezierCurve(const ImVec2& pos0, const ImVec2& cp0, const ImVec2& cp1, const ImVec2& pos1, ImU32 col, float thickness, int num_segments = 0); IMGUI_API void AddBezierCurve(const ImVec2& pos0, const ImVec2& cp0, const ImVec2& cp1, const ImVec2& pos1, ImU32 col, float thickness, int num_segments = 0);
@ -2018,7 +2019,7 @@ struct ImDrawList
IMGUI_API void PathArcTo(const ImVec2& centre, float radius, float a_min, float a_max, int num_segments = 10); IMGUI_API void PathArcTo(const ImVec2& centre, float radius, float a_min, float a_max, int num_segments = 10);
IMGUI_API void PathArcToFast(const ImVec2& centre, float radius, int a_min_of_12, int a_max_of_12); // Use precomputed angles for a 12 steps circle IMGUI_API void PathArcToFast(const ImVec2& centre, float radius, int a_min_of_12, int a_max_of_12); // Use precomputed angles for a 12 steps circle
IMGUI_API void PathBezierCurveTo(const ImVec2& p1, const ImVec2& p2, const ImVec2& p3, int num_segments = 0); IMGUI_API void PathBezierCurveTo(const ImVec2& p1, const ImVec2& p2, const ImVec2& p3, int num_segments = 0);
IMGUI_API void PathRect(const ImVec2& rect_min, const ImVec2& rect_max, float rounding = 0.0f, int rounding_corners_flags = ImDrawCornerFlags_All); IMGUI_API void PathRect(const ImVec2& rect_min, const ImVec2& rect_max, float rounding = 0.0f, ImDrawCornerFlags rounding_corners = ImDrawCornerFlags_All);
// Advanced // Advanced
IMGUI_API void AddCallback(ImDrawCallback callback, void* callback_data); // Your rendering function must check for 'UserCallback' in ImDrawCmd and call the function instead of rendering triangles. IMGUI_API void AddCallback(ImDrawCallback callback, void* callback_data); // Your rendering function must check for 'UserCallback' in ImDrawCmd and call the function instead of rendering triangles.

View File

@ -1167,7 +1167,7 @@ static void ShowDemoWindowWidgets()
ImGui::Checkbox("With Drag and Drop", &drag_and_drop); ImGui::Checkbox("With Drag and Drop", &drag_and_drop);
ImGui::Checkbox("With Options Menu", &options_menu); ImGui::SameLine(); HelpMarker("Right-click on the individual color widget to show options."); ImGui::Checkbox("With Options Menu", &options_menu); ImGui::SameLine(); HelpMarker("Right-click on the individual color widget to show options.");
ImGui::Checkbox("With HDR", &hdr); ImGui::SameLine(); HelpMarker("Currently all this does is to lift the 0..1 limits on dragging widgets."); ImGui::Checkbox("With HDR", &hdr); ImGui::SameLine(); HelpMarker("Currently all this does is to lift the 0..1 limits on dragging widgets.");
int misc_flags = (hdr ? ImGuiColorEditFlags_HDR : 0) | (drag_and_drop ? 0 : ImGuiColorEditFlags_NoDragDrop) | (alpha_half_preview ? ImGuiColorEditFlags_AlphaPreviewHalf : (alpha_preview ? ImGuiColorEditFlags_AlphaPreview : 0)) | (options_menu ? 0 : ImGuiColorEditFlags_NoOptions); ImGuiColorEditFlags misc_flags = (hdr ? ImGuiColorEditFlags_HDR : 0) | (drag_and_drop ? 0 : ImGuiColorEditFlags_NoDragDrop) | (alpha_half_preview ? ImGuiColorEditFlags_AlphaPreviewHalf : (alpha_preview ? ImGuiColorEditFlags_AlphaPreview : 0)) | (options_menu ? 0 : ImGuiColorEditFlags_NoOptions);
ImGui::Text("Color widget:"); ImGui::Text("Color widget:");
ImGui::SameLine(); HelpMarker("Click on the colored square to open a color picker.\nCTRL+click on individual component to input value.\n"); ImGui::SameLine(); HelpMarker("Click on the colored square to open a color picker.\nCTRL+click on individual component to input value.\n");
@ -3528,7 +3528,7 @@ struct ExampleAppConsole
Commands.push_back("CLEAR"); Commands.push_back("CLEAR");
Commands.push_back("CLASSIFY"); // "classify" is only here to provide an example of "C"+[tab] completing to "CL" and displaying matches. Commands.push_back("CLASSIFY"); // "classify" is only here to provide an example of "C"+[tab] completing to "CL" and displaying matches.
AutoScroll = true; AutoScroll = true;
ScrollToBottom = true; ScrollToBottom = false;
AddLog("Welcome to Dear ImGui!"); AddLog("Welcome to Dear ImGui!");
} }
~ExampleAppConsole() ~ExampleAppConsole()
@ -3549,7 +3549,6 @@ struct ExampleAppConsole
for (int i = 0; i < Items.Size; i++) for (int i = 0; i < Items.Size; i++)
free(Items[i]); free(Items[i]);
Items.clear(); Items.clear();
ScrollToBottom = true;
} }
void AddLog(const char* fmt, ...) IM_FMTARGS(2) void AddLog(const char* fmt, ...) IM_FMTARGS(2)
@ -3562,8 +3561,6 @@ struct ExampleAppConsole
buf[IM_ARRAYSIZE(buf)-1] = 0; buf[IM_ARRAYSIZE(buf)-1] = 0;
va_end(args); va_end(args);
Items.push_back(Strdup(buf)); Items.push_back(Strdup(buf));
if (AutoScroll)
ScrollToBottom = true;
} }
void Draw(const char* title, bool* p_open) void Draw(const char* title, bool* p_open)
@ -3592,8 +3589,7 @@ struct ExampleAppConsole
if (ImGui::SmallButton("Add Dummy Text")) { AddLog("%d some text", Items.Size); AddLog("some more text"); AddLog("display very important message here!"); } ImGui::SameLine(); if (ImGui::SmallButton("Add Dummy Text")) { AddLog("%d some text", Items.Size); AddLog("some more text"); AddLog("display very important message here!"); } ImGui::SameLine();
if (ImGui::SmallButton("Add Dummy Error")) { AddLog("[error] something went wrong"); } ImGui::SameLine(); if (ImGui::SmallButton("Add Dummy Error")) { AddLog("[error] something went wrong"); } ImGui::SameLine();
if (ImGui::SmallButton("Clear")) { ClearLog(); } ImGui::SameLine(); if (ImGui::SmallButton("Clear")) { ClearLog(); } ImGui::SameLine();
bool copy_to_clipboard = ImGui::SmallButton("Copy"); ImGui::SameLine(); bool copy_to_clipboard = ImGui::SmallButton("Copy");
if (ImGui::SmallButton("Scroll to bottom")) ScrollToBottom = true;
//static float t = 0.0f; if (ImGui::GetTime() - t > 0.02f) { t = ImGui::GetTime(); AddLog("Spam %f", t); } //static float t = 0.0f; if (ImGui::GetTime() - t > 0.02f) { t = ImGui::GetTime(); AddLog("Spam %f", t); }
ImGui::Separator(); ImGui::Separator();
@ -3601,9 +3597,7 @@ struct ExampleAppConsole
// Options menu // Options menu
if (ImGui::BeginPopup("Options")) if (ImGui::BeginPopup("Options"))
{ {
if (ImGui::Checkbox("Auto-scroll", &AutoScroll)) ImGui::Checkbox("Auto-scroll", &AutoScroll);
if (AutoScroll)
ScrollToBottom = true;
ImGui::EndPopup(); ImGui::EndPopup();
} }
@ -3652,9 +3646,11 @@ struct ExampleAppConsole
} }
if (copy_to_clipboard) if (copy_to_clipboard)
ImGui::LogFinish(); ImGui::LogFinish();
if (ScrollToBottom)
if (ScrollToBottom || (AutoScroll && ImGui::GetScrollY() >= ImGui::GetScrollMaxY()))
ImGui::SetScrollHereY(1.0f); ImGui::SetScrollHereY(1.0f);
ScrollToBottom = false; ScrollToBottom = false;
ImGui::PopStyleVar(); ImGui::PopStyleVar();
ImGui::EndChild(); ImGui::EndChild();
ImGui::Separator(); ImGui::Separator();
@ -3846,13 +3842,11 @@ struct ExampleAppLog
ImGuiTextBuffer Buf; ImGuiTextBuffer Buf;
ImGuiTextFilter Filter; ImGuiTextFilter Filter;
ImVector<int> LineOffsets; // Index to lines offset. We maintain this with AddLog() calls, allowing us to have a random access on lines ImVector<int> LineOffsets; // Index to lines offset. We maintain this with AddLog() calls, allowing us to have a random access on lines
bool AutoScroll; bool AutoScroll; // Keep scrolling if already at the bottom
bool ScrollToBottom;
ExampleAppLog() ExampleAppLog()
{ {
AutoScroll = true; AutoScroll = true;
ScrollToBottom = false;
Clear(); Clear();
} }
@ -3873,8 +3867,6 @@ struct ExampleAppLog
for (int new_size = Buf.size(); old_size < new_size; old_size++) for (int new_size = Buf.size(); old_size < new_size; old_size++)
if (Buf[old_size] == '\n') if (Buf[old_size] == '\n')
LineOffsets.push_back(old_size + 1); LineOffsets.push_back(old_size + 1);
if (AutoScroll)
ScrollToBottom = true;
} }
void Draw(const char* title, bool* p_open = NULL) void Draw(const char* title, bool* p_open = NULL)
@ -3888,9 +3880,7 @@ struct ExampleAppLog
// Options menu // Options menu
if (ImGui::BeginPopup("Options")) if (ImGui::BeginPopup("Options"))
{ {
if (ImGui::Checkbox("Auto-scroll", &AutoScroll)) ImGui::Checkbox("Auto-scroll", &AutoScroll);
if (AutoScroll)
ScrollToBottom = true;
ImGui::EndPopup(); ImGui::EndPopup();
} }
@ -3955,9 +3945,9 @@ struct ExampleAppLog
} }
ImGui::PopStyleVar(); ImGui::PopStyleVar();
if (ScrollToBottom) if (AutoScroll && ImGui::GetScrollY() >= ImGui::GetScrollMaxY())
ImGui::SetScrollHereY(1.0f); ImGui::SetScrollHereY(1.0f);
ScrollToBottom = false;
ImGui::EndChild(); ImGui::EndChild();
ImGui::End(); ImGui::End();
} }

View File

@ -949,7 +949,7 @@ void ImDrawList::PathBezierCurveTo(const ImVec2& p2, const ImVec2& p3, const ImV
} }
} }
void ImDrawList::PathRect(const ImVec2& a, const ImVec2& b, float rounding, int rounding_corners) void ImDrawList::PathRect(const ImVec2& a, const ImVec2& b, float rounding, ImDrawCornerFlags rounding_corners)
{ {
rounding = ImMin(rounding, ImFabs(b.x - a.x) * ( ((rounding_corners & ImDrawCornerFlags_Top) == ImDrawCornerFlags_Top) || ((rounding_corners & ImDrawCornerFlags_Bot) == ImDrawCornerFlags_Bot) ? 0.5f : 1.0f ) - 1.0f); rounding = ImMin(rounding, ImFabs(b.x - a.x) * ( ((rounding_corners & ImDrawCornerFlags_Top) == ImDrawCornerFlags_Top) || ((rounding_corners & ImDrawCornerFlags_Bot) == ImDrawCornerFlags_Bot) ? 0.5f : 1.0f ) - 1.0f);
rounding = ImMin(rounding, ImFabs(b.y - a.y) * ( ((rounding_corners & ImDrawCornerFlags_Left) == ImDrawCornerFlags_Left) || ((rounding_corners & ImDrawCornerFlags_Right) == ImDrawCornerFlags_Right) ? 0.5f : 1.0f ) - 1.0f); rounding = ImMin(rounding, ImFabs(b.y - a.y) * ( ((rounding_corners & ImDrawCornerFlags_Left) == ImDrawCornerFlags_Left) || ((rounding_corners & ImDrawCornerFlags_Right) == ImDrawCornerFlags_Right) ? 0.5f : 1.0f ) - 1.0f);
@ -984,24 +984,24 @@ void ImDrawList::AddLine(const ImVec2& a, const ImVec2& b, ImU32 col, float thic
} }
// a: upper-left, b: lower-right. we don't render 1 px sized rectangles properly. // a: upper-left, b: lower-right. we don't render 1 px sized rectangles properly.
void ImDrawList::AddRect(const ImVec2& a, const ImVec2& b, ImU32 col, float rounding, int rounding_corners_flags, float thickness) void ImDrawList::AddRect(const ImVec2& a, const ImVec2& b, ImU32 col, float rounding, ImDrawCornerFlags rounding_corners, float thickness)
{ {
if ((col & IM_COL32_A_MASK) == 0) if ((col & IM_COL32_A_MASK) == 0)
return; return;
if (Flags & ImDrawListFlags_AntiAliasedLines) if (Flags & ImDrawListFlags_AntiAliasedLines)
PathRect(a + ImVec2(0.5f,0.5f), b - ImVec2(0.50f,0.50f), rounding, rounding_corners_flags); PathRect(a + ImVec2(0.5f,0.5f), b - ImVec2(0.50f,0.50f), rounding, rounding_corners);
else else
PathRect(a + ImVec2(0.5f,0.5f), b - ImVec2(0.49f,0.49f), rounding, rounding_corners_flags); // Better looking lower-right corner and rounded non-AA shapes. PathRect(a + ImVec2(0.5f,0.5f), b - ImVec2(0.49f,0.49f), rounding, rounding_corners); // Better looking lower-right corner and rounded non-AA shapes.
PathStroke(col, true, thickness); PathStroke(col, true, thickness);
} }
void ImDrawList::AddRectFilled(const ImVec2& a, const ImVec2& b, ImU32 col, float rounding, int rounding_corners_flags) void ImDrawList::AddRectFilled(const ImVec2& a, const ImVec2& b, ImU32 col, float rounding, ImDrawCornerFlags rounding_corners)
{ {
if ((col & IM_COL32_A_MASK) == 0) if ((col & IM_COL32_A_MASK) == 0)
return; return;
if (rounding > 0.0f) if (rounding > 0.0f)
{ {
PathRect(a, b, rounding, rounding_corners_flags); PathRect(a, b, rounding, rounding_corners);
PathFillConvex(col); PathFillConvex(col);
} }
else else
@ -1170,7 +1170,7 @@ void ImDrawList::AddImageQuad(ImTextureID user_texture_id, const ImVec2& a, cons
PopTextureID(); PopTextureID();
} }
void ImDrawList::AddImageRounded(ImTextureID user_texture_id, const ImVec2& a, const ImVec2& b, const ImVec2& uv_a, const ImVec2& uv_b, ImU32 col, float rounding, int rounding_corners) void ImDrawList::AddImageRounded(ImTextureID user_texture_id, const ImVec2& a, const ImVec2& b, const ImVec2& uv_a, const ImVec2& uv_b, ImU32 col, float rounding, ImDrawCornerFlags rounding_corners)
{ {
if ((col & IM_COL32_A_MASK) == 0) if ((col & IM_COL32_A_MASK) == 0)
return; return;

View File

@ -366,7 +366,8 @@ enum ImGuiSelectableFlagsPrivate_
ImGuiSelectableFlags_PressedOnClick = 1 << 21, ImGuiSelectableFlags_PressedOnClick = 1 << 21,
ImGuiSelectableFlags_PressedOnRelease = 1 << 22, ImGuiSelectableFlags_PressedOnRelease = 1 << 22,
ImGuiSelectableFlags_DrawFillAvailWidth = 1 << 23, // FIXME: We may be able to remove this (added in 6251d379 for menus) ImGuiSelectableFlags_DrawFillAvailWidth = 1 << 23, // FIXME: We may be able to remove this (added in 6251d379 for menus)
ImGuiSelectableFlags_AllowItemOverlap = 1 << 24 ImGuiSelectableFlags_AllowItemOverlap = 1 << 24,
ImGuiSelectableFlags_DrawHoveredWhenHeld= 1 << 25 // Always show active when held, even is not hovered. This concept could probably be renamed/formalized somehow.
}; };
// Extend ImGuiTreeNodeFlags_ // Extend ImGuiTreeNodeFlags_
@ -885,13 +886,13 @@ struct ImGuiShrinkWidthItem
float Width; float Width;
}; };
struct ImGuiTabBarRef struct ImGuiPtrOrIndex
{ {
ImGuiTabBar* Ptr; // Either field can be set, not both. Dock node tab bars are loose while BeginTabBar() ones are in a pool. void* Ptr; // Either field can be set, not both. e.g. Dock node tab bars are loose while BeginTabBar() ones are in a pool.
int IndexInMainPool; int Index; // Usually index in a main pool.
ImGuiTabBarRef(ImGuiTabBar* ptr) { Ptr = ptr; IndexInMainPool = -1; } ImGuiPtrOrIndex(void* ptr) { Ptr = ptr; Index = -1; }
ImGuiTabBarRef(int index_in_main_pool) { Ptr = NULL; IndexInMainPool = index_in_main_pool; } ImGuiPtrOrIndex(int index) { Ptr = NULL; Index = index; }
}; };
// Extend ImGuiDockNodeFlags_ // Extend ImGuiDockNodeFlags_
@ -1010,6 +1011,9 @@ struct ImGuiContext
ImGuiWindow* HoveredRootWindow; // Will catch mouse inputs (for focus/move only) ImGuiWindow* HoveredRootWindow; // Will catch mouse inputs (for focus/move only)
ImGuiWindow* HoveredWindowUnderMovingWindow; // Hovered window ignoring MovingWindow. Only set if MovingWindow is set. ImGuiWindow* HoveredWindowUnderMovingWindow; // Hovered window ignoring MovingWindow. Only set if MovingWindow is set.
ImGuiWindow* MovingWindow; // Track the window we clicked on (in order to preserve focus). The actually window that is moved is generally MovingWindow->RootWindow. ImGuiWindow* MovingWindow; // Track the window we clicked on (in order to preserve focus). The actually window that is moved is generally MovingWindow->RootWindow.
ImGuiWindow* WheelingWindow;
ImVec2 WheelingWindowRefMousePos;
float WheelingWindowTimer;
// Item/widgets state and tracking information // Item/widgets state and tracking information
ImGuiID HoveredId; // Hovered widget ImGuiID HoveredId; // Hovered widget
@ -1129,9 +1133,9 @@ struct ImGuiContext
unsigned char DragDropPayloadBufLocal[8]; // Local buffer for small payloads unsigned char DragDropPayloadBufLocal[8]; // Local buffer for small payloads
// Tab bars // Tab bars
ImPool<ImGuiTabBar> TabBars;
ImGuiTabBar* CurrentTabBar; ImGuiTabBar* CurrentTabBar;
ImVector<ImGuiTabBarRef> CurrentTabBarStack; ImPool<ImGuiTabBar> TabBars;
ImVector<ImGuiPtrOrIndex> CurrentTabBarStack;
ImVector<ImGuiShrinkWidthItem> ShrinkWidthBuffer; ImVector<ImGuiShrinkWidthItem> ShrinkWidthBuffer;
// Widget state // Widget state
@ -1211,6 +1215,8 @@ struct ImGuiContext
HoveredRootWindow = NULL; HoveredRootWindow = NULL;
HoveredWindowUnderMovingWindow = NULL; HoveredWindowUnderMovingWindow = NULL;
MovingWindow = NULL; MovingWindow = NULL;
WheelingWindow = NULL;
WheelingWindowTimer = 0.0f;
HoveredId = 0; HoveredId = 0;
HoveredIdAllowOverlap = false; HoveredIdAllowOverlap = false;
@ -1605,7 +1611,7 @@ struct ImGuiTabBar
float ScrollingSpeed; float ScrollingSpeed;
ImGuiTabBarFlags Flags; ImGuiTabBarFlags Flags;
ImGuiID ReorderRequestTabId; ImGuiID ReorderRequestTabId;
int ReorderRequestDir; ImS8 ReorderRequestDir;
bool WantLayout; bool WantLayout;
bool VisibleTabWasSubmitted; bool VisibleTabWasSubmitted;
short LastTabItemIdx; // For BeginTabItem()/EndTabItem() short LastTabItemIdx; // For BeginTabItem()/EndTabItem()
@ -1647,8 +1653,8 @@ namespace ImGui
IMGUI_API ImVec2 CalcWindowExpectedSize(ImGuiWindow* window); IMGUI_API ImVec2 CalcWindowExpectedSize(ImGuiWindow* window);
IMGUI_API bool IsWindowChildOf(ImGuiWindow* window, ImGuiWindow* potential_parent); IMGUI_API bool IsWindowChildOf(ImGuiWindow* window, ImGuiWindow* potential_parent);
IMGUI_API bool IsWindowNavFocusable(ImGuiWindow* window); IMGUI_API bool IsWindowNavFocusable(ImGuiWindow* window);
IMGUI_API void SetWindowScrollX(ImGuiWindow* window, float new_scroll_x); IMGUI_API void SetScrollX(ImGuiWindow* window, float new_scroll_x);
IMGUI_API void SetWindowScrollY(ImGuiWindow* window, float new_scroll_y); IMGUI_API void SetScrollY(ImGuiWindow* window, float new_scroll_y);
IMGUI_API ImRect GetWindowAllowedExtentRect(ImGuiWindow* window); IMGUI_API ImRect GetWindowAllowedExtentRect(ImGuiWindow* window);
IMGUI_API void SetWindowPos(ImGuiWindow* window, const ImVec2& pos, ImGuiCond cond = 0); IMGUI_API void SetWindowPos(ImGuiWindow* window, const ImVec2& pos, ImGuiCond cond = 0);
IMGUI_API void SetWindowSize(ImGuiWindow* window, const ImVec2& size, ImGuiCond cond = 0); IMGUI_API void SetWindowSize(ImGuiWindow* window, const ImVec2& size, ImGuiCond cond = 0);

View File

@ -1095,6 +1095,7 @@ bool ImGui::RadioButton(const char* label, bool active)
return pressed; return pressed;
} }
// FIXME: This would work nicely if it was a public template, e.g. 'template<T> RadioButton(const char* label, T* v, T v_button)', but I'm not sure how we would expose it..
bool ImGui::RadioButton(const char* label, int* v, int v_button) bool ImGui::RadioButton(const char* label, int* v, int v_button)
{ {
const bool pressed = RadioButton(label, *v == v_button); const bool pressed = RadioButton(label, *v == v_button);
@ -3644,8 +3645,8 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
if (IsKeyPressedMap(ImGuiKey_LeftArrow)) { state->OnKeyPressed((is_startend_key_down ? STB_TEXTEDIT_K_LINESTART : is_wordmove_key_down ? STB_TEXTEDIT_K_WORDLEFT : STB_TEXTEDIT_K_LEFT) | k_mask); } if (IsKeyPressedMap(ImGuiKey_LeftArrow)) { state->OnKeyPressed((is_startend_key_down ? STB_TEXTEDIT_K_LINESTART : is_wordmove_key_down ? STB_TEXTEDIT_K_WORDLEFT : STB_TEXTEDIT_K_LEFT) | k_mask); }
else if (IsKeyPressedMap(ImGuiKey_RightArrow)) { state->OnKeyPressed((is_startend_key_down ? STB_TEXTEDIT_K_LINEEND : is_wordmove_key_down ? STB_TEXTEDIT_K_WORDRIGHT : STB_TEXTEDIT_K_RIGHT) | k_mask); } else if (IsKeyPressedMap(ImGuiKey_RightArrow)) { state->OnKeyPressed((is_startend_key_down ? STB_TEXTEDIT_K_LINEEND : is_wordmove_key_down ? STB_TEXTEDIT_K_WORDRIGHT : STB_TEXTEDIT_K_RIGHT) | k_mask); }
else if (IsKeyPressedMap(ImGuiKey_UpArrow) && is_multiline) { if (io.KeyCtrl) SetWindowScrollY(draw_window, ImMax(draw_window->Scroll.y - g.FontSize, 0.0f)); else state->OnKeyPressed((is_startend_key_down ? STB_TEXTEDIT_K_TEXTSTART : STB_TEXTEDIT_K_UP) | k_mask); } else if (IsKeyPressedMap(ImGuiKey_UpArrow) && is_multiline) { if (io.KeyCtrl) SetScrollY(draw_window, ImMax(draw_window->Scroll.y - g.FontSize, 0.0f)); else state->OnKeyPressed((is_startend_key_down ? STB_TEXTEDIT_K_TEXTSTART : STB_TEXTEDIT_K_UP) | k_mask); }
else if (IsKeyPressedMap(ImGuiKey_DownArrow) && is_multiline) { if (io.KeyCtrl) SetWindowScrollY(draw_window, ImMin(draw_window->Scroll.y + g.FontSize, GetScrollMaxY())); else state->OnKeyPressed((is_startend_key_down ? STB_TEXTEDIT_K_TEXTEND : STB_TEXTEDIT_K_DOWN) | k_mask); } else if (IsKeyPressedMap(ImGuiKey_DownArrow) && is_multiline) { if (io.KeyCtrl) SetScrollY(draw_window, ImMin(draw_window->Scroll.y + g.FontSize, GetScrollMaxY())); else state->OnKeyPressed((is_startend_key_down ? STB_TEXTEDIT_K_TEXTEND : STB_TEXTEDIT_K_DOWN) | k_mask); }
else if (IsKeyPressedMap(ImGuiKey_Home)) { state->OnKeyPressed(io.KeyCtrl ? STB_TEXTEDIT_K_TEXTSTART | k_mask : STB_TEXTEDIT_K_LINESTART | k_mask); } else if (IsKeyPressedMap(ImGuiKey_Home)) { state->OnKeyPressed(io.KeyCtrl ? STB_TEXTEDIT_K_TEXTSTART | k_mask : STB_TEXTEDIT_K_LINESTART | k_mask); }
else if (IsKeyPressedMap(ImGuiKey_End)) { state->OnKeyPressed(io.KeyCtrl ? STB_TEXTEDIT_K_TEXTEND | k_mask : STB_TEXTEDIT_K_LINEEND | k_mask); } else if (IsKeyPressedMap(ImGuiKey_End)) { state->OnKeyPressed(io.KeyCtrl ? STB_TEXTEDIT_K_TEXTEND | k_mask : STB_TEXTEDIT_K_LINEEND | k_mask); }
else if (IsKeyPressedMap(ImGuiKey_Delete) && !is_readonly) { state->OnKeyPressed(STB_TEXTEDIT_K_DELETE | k_mask); } else if (IsKeyPressedMap(ImGuiKey_Delete) && !is_readonly) { state->OnKeyPressed(STB_TEXTEDIT_K_DELETE | k_mask); }
@ -4000,9 +4001,8 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
scroll_y = ImMax(0.0f, cursor_offset.y - g.FontSize); scroll_y = ImMax(0.0f, cursor_offset.y - g.FontSize);
else if (cursor_offset.y - size.y >= scroll_y) else if (cursor_offset.y - size.y >= scroll_y)
scroll_y = cursor_offset.y - size.y; scroll_y = cursor_offset.y - size.y;
draw_window->DC.CursorPos.y += (draw_window->Scroll.y - scroll_y); // Manipulate cursor pos immediately avoid a frame of lag draw_pos.y += (draw_window->Scroll.y - scroll_y); // Manipulate cursor pos immediately avoid a frame of lag
draw_window->Scroll.y = scroll_y; draw_window->Scroll.y = scroll_y;
draw_pos.y = draw_window->DC.CursorPos.y;
} }
state->CursorFollow = false; state->CursorFollow = false;
@ -5500,6 +5500,8 @@ bool ImGui::Selectable(const char* label, bool selected, ImGuiSelectableFlags fl
window->DC.LastItemStatusFlags |= ImGuiItemStatusFlags_ToggledSelection; window->DC.LastItemStatusFlags |= ImGuiItemStatusFlags_ToggledSelection;
// Render // Render
if (held && (flags & ImGuiSelectableFlags_DrawHoveredWhenHeld))
hovered = true;
if (hovered || selected) if (hovered || selected)
{ {
const ImU32 col = GetColorU32((held && hovered) ? ImGuiCol_HeaderActive : hovered ? ImGuiCol_HeaderHovered : ImGuiCol_Header); const ImU32 col = GetColorU32((held && hovered) ? ImGuiCol_HeaderActive : hovered ? ImGuiCol_HeaderHovered : ImGuiCol_Header);
@ -6283,18 +6285,18 @@ static int IMGUI_CDECL TabItemComparerByVisibleOffset(const void* lhs, const voi
return (int)(a->Offset - b->Offset); return (int)(a->Offset - b->Offset);
} }
static ImGuiTabBar* GetTabBarFromTabBarRef(const ImGuiTabBarRef& ref) static ImGuiTabBar* GetTabBarFromTabBarRef(const ImGuiPtrOrIndex& ref)
{ {
ImGuiContext& g = *GImGui; ImGuiContext& g = *GImGui;
return ref.Ptr ? ref.Ptr : g.TabBars.GetByIndex(ref.IndexInMainPool); return ref.Ptr ? (ImGuiTabBar*)ref.Ptr : g.TabBars.GetByIndex(ref.Index);
} }
static ImGuiTabBarRef GetTabBarRefFromTabBar(ImGuiTabBar* tab_bar) static ImGuiPtrOrIndex GetTabBarRefFromTabBar(ImGuiTabBar* tab_bar)
{ {
ImGuiContext& g = *GImGui; ImGuiContext& g = *GImGui;
if (g.TabBars.Contains(tab_bar)) if (g.TabBars.Contains(tab_bar))
return ImGuiTabBarRef(g.TabBars.GetIndex(tab_bar)); return ImGuiPtrOrIndex(g.TabBars.GetIndex(tab_bar));
return ImGuiTabBarRef(tab_bar); return ImGuiPtrOrIndex(tab_bar);
} }
bool ImGui::BeginTabBar(const char* str_id, ImGuiTabBarFlags flags) bool ImGui::BeginTabBar(const char* str_id, ImGuiTabBarFlags flags)
@ -6692,7 +6694,7 @@ void ImGui::TabBarQueueChangeTabOrder(ImGuiTabBar* tab_bar, const ImGuiTabItem*
IM_ASSERT(dir == -1 || dir == +1); IM_ASSERT(dir == -1 || dir == +1);
IM_ASSERT(tab_bar->ReorderRequestTabId == 0); IM_ASSERT(tab_bar->ReorderRequestTabId == 0);
tab_bar->ReorderRequestTabId = tab->ID; tab_bar->ReorderRequestTabId = tab->ID;
tab_bar->ReorderRequestDir = dir; tab_bar->ReorderRequestDir = (ImS8)dir;
} }
static ImGuiTabItem* ImGui::TabBarScrollingButtons(ImGuiTabBar* tab_bar) static ImGuiTabItem* ImGui::TabBarScrollingButtons(ImGuiTabBar* tab_bar)

View File

@ -646,7 +646,8 @@ static void* FreeType_Realloc(FT_Memory /*memory*/, long cur_size, long new_size
bool ImGuiFreeType::BuildFontAtlas(ImFontAtlas* atlas, unsigned int extra_flags) bool ImGuiFreeType::BuildFontAtlas(ImFontAtlas* atlas, unsigned int extra_flags)
{ {
// FreeType memory management: https://www.freetype.org/freetype2/docs/design/design-4.html // FreeType memory management: https://www.freetype.org/freetype2/docs/design/design-4.html
FT_MemoryRec_ memory_rec = { 0 }; FT_MemoryRec_ memory_rec = {};
memory_rec.user = NULL;
memory_rec.alloc = &FreeType_Alloc; memory_rec.alloc = &FreeType_Alloc;
memory_rec.free = &FreeType_Free; memory_rec.free = &FreeType_Free;
memory_rec.realloc = &FreeType_Realloc; memory_rec.realloc = &FreeType_Realloc;