Updated ImGui.

This commit is contained in:
Бранимир Караџић 2019-09-17 07:14:49 -07:00
parent 2010e99f1b
commit c90ac70e38
6 changed files with 202 additions and 122 deletions

View File

@ -575,17 +575,17 @@ CODE
Q: Where is the documentation? Q: Where is the documentation?
A: This library is poorly documented at the moment and expects of the user to be acquainted with C/C++. A: This library is poorly documented at the moment and expects of the user to be acquainted with C/C++.
- Run the examples/ and explore them. - Run the examples/ and explore them.
- See demo code in imgui_demo.cpp and particularly the ImGui::ShowDemoWindow() function. - See demo code in imgui_demo.cpp and particularly the ImGui::ShowDemoWindow() function.
- The demo covers most features of Dear ImGui, so you can read the code and see its output. - The demo covers most features of Dear ImGui, so you can read the code and see its output.
- See documentation and comments at the top of imgui.cpp + effectively imgui.h. - See documentation and comments at the top of imgui.cpp + effectively imgui.h.
- Dozens of standalone example applications using e.g. OpenGL/DirectX are provided in the examples/ - Dozens of standalone example applications using e.g. OpenGL/DirectX are provided in the examples/
folder to explain how to integrate Dear ImGui with your own engine/application. folder to explain how to integrate Dear ImGui with your own engine/application.
- Your programming IDE is your friend, find the type or function declaration to find comments - Your programming IDE is your friend, find the type or function declaration to find comments
associated to it. associated to it.
Q: Which version should I get? Q: Which version should I get?
A: I occasionally tag Releases (https://github.com/ocornut/imgui/releases) but it is generally safe A: I occasionally tag Releases (https://github.com/ocornut/imgui/releases) but it is generally safe
and recommended to sync to master/latest. The library is fairly stable and regressions tend to be and recommended to sync to master/latest. The library is fairly stable and regressions tend to be
fixed fast when reported. You may also peak at the 'docking' branch which includes: fixed fast when reported. You may also peak at the 'docking' branch which includes:
- Docking/Merging features (https://github.com/ocornut/imgui/issues/2109) - Docking/Merging features (https://github.com/ocornut/imgui/issues/2109)
- Multi-viewport features (https://github.com/ocornut/imgui/issues/1542) - Multi-viewport features (https://github.com/ocornut/imgui/issues/1542)
@ -597,11 +597,11 @@ CODE
for a list of games/software which are publicly known to use dear imgui. Please add yours if you can! for a list of games/software which are publicly known to use dear imgui. Please add yours if you can!
Q: Why the odd dual naming, "Dear ImGui" vs "ImGui"? Q: Why the odd dual naming, "Dear ImGui" vs "ImGui"?
A: The library started its life as "ImGui" due to the fact that I didn't give it a proper name when A: The library started its life as "ImGui" due to the fact that I didn't give it a proper name when
when I released 1.0, and had no particular expectation that it would take off. However, the term IMGUI when I released 1.0, and had no particular expectation that it would take off. However, the term IMGUI
(immediate-mode graphical user interface) was coined before and is being used in variety of other (immediate-mode graphical user interface) was coined before and is being used in variety of other
situations (e.g. Unity uses it own implementation of the IMGUI paradigm). situations (e.g. Unity uses it own implementation of the IMGUI paradigm).
To reduce the ambiguity without affecting existing code bases, I have decided on an alternate, To reduce the ambiguity without affecting existing code bases, I have decided on an alternate,
longer name "Dear ImGui" that people can use to refer to this specific library. longer name "Dear ImGui" that people can use to refer to this specific library.
Please try to refer to this library as "Dear ImGui". Please try to refer to this library as "Dear ImGui".
@ -1080,7 +1080,7 @@ static bool BeginChildEx(const char* name, ImGuiID id, const ImVec2&
// Navigation // Navigation
static void NavUpdate(); static void NavUpdate();
static void NavUpdateWindowing(); static void NavUpdateWindowing();
static void NavUpdateWindowingList(); static void NavUpdateWindowingOverlay();
static void NavUpdateMoveResult(); static void NavUpdateMoveResult();
static float NavUpdatePageUpPageDown(int allowed_dir_flags); static float NavUpdatePageUpPageDown(int allowed_dir_flags);
static inline void NavUpdateAnyRequestFlag(); static inline void NavUpdateAnyRequestFlag();
@ -2490,14 +2490,18 @@ void ImGui::RenderTextClipped(const ImVec2& pos_min, const ImVec2& pos_max, cons
// Another overly complex function until we reorganize everything into a nice all-in-one helper. // Another overly complex function until we reorganize everything into a nice all-in-one helper.
// This is made more complex because we have dissociated the layout rectangle (pos_min..pos_max) which define _where_ the ellipsis is, from actual clipping of text and limit of the ellipsis display. // This is made more complex because we have dissociated the layout rectangle (pos_min..pos_max) which define _where_ the ellipsis is, from actual clipping of text and limit of the ellipsis display.
// This is because in the context of tabs we selectively hide part of the text when the Close Button appears, but we don't want the ellipsis to move. // This is because in the context of tabs we selectively hide part of the text when the Close Button appears, but we don't want the ellipsis to move.
void ImGui::RenderTextEllipsis(ImDrawList* draw_list, const ImVec2& pos_min, const ImVec2& pos_max, float clip_max_x, float ellipsis_max_x, const char* text, const char* text_end_full, const ImVec2* text_size_if_known) void ImGui::RenderTextEllipsis(ImDrawList* draw_list, const ImVec2& pos_min, const ImVec2& pos_max, float clip_max_x, float ellipsis_max_x, const char* text, const char* text_end_full, const ImVec2* text_size_if_known)
{ {
ImGuiContext& g = *GImGui; ImGuiContext& g = *GImGui;
if (text_end_full == NULL) if (text_end_full == NULL)
text_end_full = FindRenderedTextEnd(text); text_end_full = FindRenderedTextEnd(text);
const ImVec2 text_size = text_size_if_known ? *text_size_if_known : CalcTextSize(text, text_end_full, false, 0.0f); const ImVec2 text_size = text_size_if_known ? *text_size_if_known : CalcTextSize(text, text_end_full, false, 0.0f);
//draw_list->AddLine(ImVec2(pos_max.x, pos_min.y - 4), ImVec2(pos_max.x, pos_max.y + 4), IM_COL32(0, 0, 255, 255));
//draw_list->AddLine(ImVec2(ellipsis_max_x, pos_min.y-2), ImVec2(ellipsis_max_x, pos_max.y+2), IM_COL32(0, 255, 0, 255));
//draw_list->AddLine(ImVec2(clip_max_x, pos_min.y), ImVec2(clip_max_x, pos_max.y), IM_COL32(255, 0, 0, 255));
// FIXME: We could technically remove (last_glyph->AdvanceX - last_glyph->X1) from text_size.x here and save a few pixels.
if (text_size.x > pos_max.x - pos_min.x) if (text_size.x > pos_max.x - pos_min.x)
{ {
// Hello wo... // Hello wo...
@ -2505,15 +2509,33 @@ void ImGui::RenderTextEllipsis(ImDrawList* draw_list, const ImVec2& pos_min,
// min max ellipsis_max // min max ellipsis_max
// <-> this is generally some padding value // <-> this is generally some padding value
// FIXME-STYLE: RenderPixelEllipsis() style should use actual font data.
const ImFont* font = draw_list->_Data->Font; const ImFont* font = draw_list->_Data->Font;
const float font_size = draw_list->_Data->FontSize; const float font_size = draw_list->_Data->FontSize;
const int ellipsis_dot_count = 3;
const float ellipsis_width = (1.0f + 1.0f) * ellipsis_dot_count - 1.0f;
const char* text_end_ellipsis = NULL; const char* text_end_ellipsis = NULL;
float text_width = ImMax((pos_max.x - ellipsis_width) - pos_min.x, 1.0f); ImWchar ellipsis_char = font->EllipsisChar;
float text_size_clipped_x = font->CalcTextSizeA(font_size, text_width, 0.0f, text, text_end_full, &text_end_ellipsis).x; int ellipsis_char_count = 1;
if (ellipsis_char == (ImWchar)-1)
{
ellipsis_char = (ImWchar)'.';
ellipsis_char_count = 3;
}
const ImFontGlyph* glyph = font->FindGlyph(ellipsis_char);
float ellipsis_glyph_width = glyph->X1; // Width of the glyph with no padding on either side
float ellipsis_total_width = ellipsis_glyph_width; // Full width of entire ellipsis
if (ellipsis_char_count > 1)
{
// Full ellipsis size without free spacing after it.
const float spacing_between_dots = 1.0f * (draw_list->_Data->FontSize / font->FontSize);
ellipsis_glyph_width = glyph->X1 - glyph->X0 + spacing_between_dots;
ellipsis_total_width = ellipsis_glyph_width * (float)ellipsis_char_count - spacing_between_dots;
}
// We can now claim the space between pos_max.x and ellipsis_max.x
const float text_avail_width = ImMax((ImMax(pos_max.x, ellipsis_max_x) - ellipsis_total_width) - pos_min.x, 1.0f);
float text_size_clipped_x = font->CalcTextSizeA(font_size, text_avail_width, 0.0f, text, text_end_full, &text_end_ellipsis).x;
if (text == text_end_ellipsis && text_end_ellipsis < text_end_full) if (text == text_end_ellipsis && text_end_ellipsis < text_end_full)
{ {
// Always display at least 1 character if there's no room for character + ellipsis // Always display at least 1 character if there's no room for character + ellipsis
@ -2522,15 +2544,20 @@ void ImGui::RenderTextEllipsis(ImDrawList* draw_list, const ImVec2& pos_min,
} }
while (text_end_ellipsis > text && ImCharIsBlankA(text_end_ellipsis[-1])) while (text_end_ellipsis > text && ImCharIsBlankA(text_end_ellipsis[-1]))
{ {
// Trim trailing space before ellipsis // Trim trailing space before ellipsis (FIXME: Supporting non-ascii blanks would be nice, for this we need a function to backtrack in UTF-8 text)
text_end_ellipsis--; text_end_ellipsis--;
text_size_clipped_x -= font->CalcTextSizeA(font_size, FLT_MAX, 0.0f, text_end_ellipsis, text_end_ellipsis + 1).x; // Ascii blanks are always 1 byte text_size_clipped_x -= font->CalcTextSizeA(font_size, FLT_MAX, 0.0f, text_end_ellipsis, text_end_ellipsis + 1).x; // Ascii blanks are always 1 byte
} }
RenderTextClippedEx(draw_list, pos_min, ImVec2(clip_max_x, pos_max.y), text, text_end_ellipsis, &text_size, ImVec2(0.0f, 0.0f));
const float ellipsis_x = pos_min.x + text_size_clipped_x + 1.0f; // Render text, render ellipsis
if (ellipsis_x + ellipsis_width - 1.0f <= ellipsis_max_x) RenderTextClippedEx(draw_list, pos_min, ImVec2(clip_max_x, pos_max.y), text, text_end_ellipsis, &text_size, ImVec2(0.0f, 0.0f));
RenderPixelEllipsis(draw_list, ImVec2(ellipsis_x, pos_min.y), GetColorU32(ImGuiCol_Text), ellipsis_dot_count); float ellipsis_x = pos_min.x + text_size_clipped_x;
if (ellipsis_x + ellipsis_total_width <= ellipsis_max_x)
for (int i = 0; i < ellipsis_char_count; i++)
{
font->RenderChar(draw_list, font_size, ImVec2(ellipsis_x, pos_min.y), GetColorU32(ImGuiCol_Text), ellipsis_char);
ellipsis_x += ellipsis_glyph_width;
}
} }
else else
{ {
@ -2998,8 +3025,8 @@ bool ImGui::ItemAdd(const ImRect& bb, ImGuiID id, const ImRect* nav_bb_arg)
{ {
// Navigation processing runs prior to clipping early-out // Navigation processing runs prior to clipping early-out
// (a) So that NavInitRequest can be honored, for newly opened windows to select a default widget // (a) So that NavInitRequest can be honored, for newly opened windows to select a default widget
// (b) So that we can scroll up/down past clipped items. This adds a small O(N) cost to regular navigation requests // (b) So that we can scroll up/down past clipped items. This adds a small O(N) cost to regular navigation requests
// unfortunately, but it is still limited to one window. It may not scale very well for windows with ten of // unfortunately, but it is still limited to one window. It may not scale very well for windows with ten of
// thousands of item, but at least NavMoveRequest is only set on user interaction, aka maximum once a frame. // thousands of item, but at least NavMoveRequest is only set on user interaction, aka maximum once a frame.
// We could early out with "if (is_clipped && !g.NavInitRequest) return false;" but when we wouldn't be able // We could early out with "if (is_clipped && !g.NavInitRequest) return false;" but when we wouldn't be able
// to reach unclipped widgets. This would work if user had explicit scrolling control (e.g. mapped on a stick). // to reach unclipped widgets. This would work if user had explicit scrolling control (e.g. mapped on a stick).
@ -4046,7 +4073,7 @@ static void AddDrawListToDrawData(ImVector<ImDrawList*>* out_list, ImDrawList* d
return; return;
} }
// Draw list sanity check. Detect mismatch between PrimReserve() calls and incrementing _VtxCurrentIdx, _VtxWritePtr etc. // Draw list sanity check. Detect mismatch between PrimReserve() calls and incrementing _VtxCurrentIdx, _VtxWritePtr etc.
// May trigger for you if you are using PrimXXX functions incorrectly. // May trigger for you if you are using PrimXXX functions incorrectly.
IM_ASSERT(draw_list->VtxBuffer.Size == 0 || draw_list->_VtxWritePtr == draw_list->VtxBuffer.Data + draw_list->VtxBuffer.Size); IM_ASSERT(draw_list->VtxBuffer.Size == 0 || draw_list->_VtxWritePtr == draw_list->VtxBuffer.Data + draw_list->VtxBuffer.Size);
IM_ASSERT(draw_list->IdxBuffer.Size == 0 || draw_list->_IdxWritePtr == draw_list->IdxBuffer.Data + draw_list->IdxBuffer.Size); IM_ASSERT(draw_list->IdxBuffer.Size == 0 || draw_list->_IdxWritePtr == draw_list->IdxBuffer.Data + draw_list->IdxBuffer.Size);
@ -4055,7 +4082,7 @@ static void AddDrawListToDrawData(ImVector<ImDrawList*>* out_list, ImDrawList* d
// Check that draw_list doesn't use more vertices than indexable (default ImDrawIdx = unsigned short = 2 bytes = 64K vertices per ImDrawList = per window) // Check that draw_list doesn't use more vertices than indexable (default ImDrawIdx = unsigned short = 2 bytes = 64K vertices per ImDrawList = per window)
// If this assert triggers because you are drawing lots of stuff manually: // If this assert triggers because you are drawing lots of stuff manually:
// - First, make sure you are coarse clipping yourself and not trying to draw many things outside visible bounds. // - First, make sure you are coarse clipping yourself and not trying to draw many things outside visible bounds.
// Be mindful that the ImDrawList API doesn't filter vertices. Use the Metrics window to inspect draw list contents. // Be mindful that the ImDrawList API doesn't filter vertices. Use the Metrics window to inspect draw list contents.
// - If you want large meshes with more than 64K vertices, you can either: // - If you want large meshes with more than 64K vertices, you can either:
// (A) Handle the ImDrawCmd::VtxOffset value in your renderer back-end, and set 'io.BackendFlags |= ImGuiBackendFlags_RendererHasVtxOffset'. // (A) Handle the ImDrawCmd::VtxOffset value in your renderer back-end, and set 'io.BackendFlags |= ImGuiBackendFlags_RendererHasVtxOffset'.
@ -4064,9 +4091,9 @@ static void AddDrawListToDrawData(ImVector<ImDrawList*>* out_list, ImDrawList* d
// (B) Or handle 32-bits indices in your renderer back-end, and uncomment '#define ImDrawIdx unsigned int' line in imconfig.h. // (B) Or handle 32-bits indices in your renderer back-end, and uncomment '#define ImDrawIdx unsigned int' line in imconfig.h.
// Most example back-ends already support this. For example, the OpenGL example code detect index size at compile-time: // Most example back-ends already support this. For example, the OpenGL example code detect index size at compile-time:
// glDrawElements(GL_TRIANGLES, (GLsizei)pcmd->ElemCount, sizeof(ImDrawIdx) == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT, idx_buffer_offset); // glDrawElements(GL_TRIANGLES, (GLsizei)pcmd->ElemCount, sizeof(ImDrawIdx) == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT, idx_buffer_offset);
// Your own engine or render API may use different parameters or function calls to specify index sizes. // Your own engine or render API may use different parameters or function calls to specify index sizes.
// 2 and 4 bytes indices are generally supported by most graphics API. // 2 and 4 bytes indices are generally supported by most graphics API.
// - If for some reason neither of those solutions works for you, a workaround is to call BeginChild()/EndChild() before reaching // - If for some reason neither of those solutions works for you, a workaround is to call BeginChild()/EndChild() before reaching
// the 64K limit to split your draw commands in multiple draw lists. // the 64K limit to split your draw commands in multiple draw lists.
if (sizeof(ImDrawIdx) == 2) if (sizeof(ImDrawIdx) == 2)
IM_ASSERT(draw_list->_VtxCurrentIdx < (1 << 16) && "Too many vertices in ImDrawList using 16-bit indices. Read comment above"); IM_ASSERT(draw_list->_VtxCurrentIdx < (1 << 16) && "Too many vertices in ImDrawList using 16-bit indices. Read comment above");
@ -4186,8 +4213,8 @@ void ImGui::EndFrame()
End(); End();
// Show CTRL+TAB list window // Show CTRL+TAB list window
if (g.NavWindowingTarget) if (g.NavWindowingTarget != NULL)
NavUpdateWindowingList(); NavUpdateWindowingOverlay();
// Drag and Drop: Elapse payload (if delivered, or if source stops being submitted) // Drag and Drop: Elapse payload (if delivered, or if source stops being submitted)
if (g.DragDropActive) if (g.DragDropActive)
@ -4383,7 +4410,7 @@ int ImGui::GetKeyIndex(ImGuiKey imgui_key)
// Note that imgui doesn't know the semantic of each entry of io.KeysDown[]. Use your own indices/enums according to how your back-end/engine stored them into io.KeysDown[]! // Note that imgui doesn't know the semantic of each entry of io.KeysDown[]. Use your own indices/enums according to how your back-end/engine stored them into io.KeysDown[]!
bool ImGui::IsKeyDown(int user_key_index) bool ImGui::IsKeyDown(int user_key_index)
{ {
if (user_key_index < 0) if (user_key_index < 0)
return false; return false;
ImGuiContext& g = *GImGui; ImGuiContext& g = *GImGui;
IM_ASSERT(user_key_index >= 0 && user_key_index < IM_ARRAYSIZE(g.IO.KeysDown)); IM_ASSERT(user_key_index >= 0 && user_key_index < IM_ARRAYSIZE(g.IO.KeysDown));
@ -5743,7 +5770,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
window->OuterRectClipped.ClipWith(host_rect); window->OuterRectClipped.ClipWith(host_rect);
// Inner rectangle // Inner rectangle
// Not affected by window border size. Used by: // Not affected by window border size. Used by:
// - InnerClipRect // - InnerClipRect
// - ScrollToBringRectIntoView() // - ScrollToBringRectIntoView()
// - NavUpdatePageUpPageDown() // - NavUpdatePageUpPageDown()
@ -5821,7 +5848,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
render_decorations_in_parent = true; render_decorations_in_parent = true;
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 // 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); const bool title_bar_is_highlight = want_focus || (window_to_highlight && window->RootWindowForTitleBarHighlight == window_to_highlight->RootWindowForTitleBarHighlight);
@ -8076,7 +8103,7 @@ void ImGui::NavMoveRequestForward(ImGuiDir move_dir, ImGuiDir clip_dir, const Im
{ {
ImGuiContext& g = *GImGui; ImGuiContext& g = *GImGui;
IM_ASSERT(g.NavMoveRequestForward == ImGuiNavForward_None); IM_ASSERT(g.NavMoveRequestForward == ImGuiNavForward_None);
ImGui::NavMoveRequestCancel(); NavMoveRequestCancel();
g.NavMoveDir = move_dir; g.NavMoveDir = move_dir;
g.NavMoveClipDir = clip_dir; g.NavMoveClipDir = clip_dir;
g.NavMoveRequestForward = ImGuiNavForward_ForwardQueued; g.NavMoveRequestForward = ImGuiNavForward_ForwardQueued;
@ -8412,10 +8439,10 @@ static void ImGui::NavUpdate()
g.NavMoveRequestFlags = ImGuiNavMoveFlags_None; g.NavMoveRequestFlags = ImGuiNavMoveFlags_None;
if (g.NavWindow && !g.NavWindowingTarget && allowed_dir_flags && !(g.NavWindow->Flags & ImGuiWindowFlags_NoNavInputs)) if (g.NavWindow && !g.NavWindowingTarget && allowed_dir_flags && !(g.NavWindow->Flags & ImGuiWindowFlags_NoNavInputs))
{ {
if ((allowed_dir_flags & (1<<ImGuiDir_Left)) && IsNavInputPressedAnyOfTwo(ImGuiNavInput_DpadLeft, ImGuiNavInput_KeyLeft_, ImGuiInputReadMode_Repeat)) g.NavMoveDir = ImGuiDir_Left; if ((allowed_dir_flags & (1 << ImGuiDir_Left)) && IsNavInputPressedAnyOfTwo(ImGuiNavInput_DpadLeft, ImGuiNavInput_KeyLeft_, ImGuiInputReadMode_Repeat)) { g.NavMoveDir = ImGuiDir_Left; }
if ((allowed_dir_flags & (1<<ImGuiDir_Right)) && IsNavInputPressedAnyOfTwo(ImGuiNavInput_DpadRight,ImGuiNavInput_KeyRight_,ImGuiInputReadMode_Repeat)) g.NavMoveDir = ImGuiDir_Right; if ((allowed_dir_flags & (1 << ImGuiDir_Right)) && IsNavInputPressedAnyOfTwo(ImGuiNavInput_DpadRight,ImGuiNavInput_KeyRight_,ImGuiInputReadMode_Repeat)) { g.NavMoveDir = ImGuiDir_Right; }
if ((allowed_dir_flags & (1<<ImGuiDir_Up)) && IsNavInputPressedAnyOfTwo(ImGuiNavInput_DpadUp, ImGuiNavInput_KeyUp_, ImGuiInputReadMode_Repeat)) g.NavMoveDir = ImGuiDir_Up; if ((allowed_dir_flags & (1 << ImGuiDir_Up)) && IsNavInputPressedAnyOfTwo(ImGuiNavInput_DpadUp, ImGuiNavInput_KeyUp_, ImGuiInputReadMode_Repeat)) { g.NavMoveDir = ImGuiDir_Up; }
if ((allowed_dir_flags & (1<<ImGuiDir_Down)) && IsNavInputPressedAnyOfTwo(ImGuiNavInput_DpadDown, ImGuiNavInput_KeyDown_, ImGuiInputReadMode_Repeat)) g.NavMoveDir = ImGuiDir_Down; if ((allowed_dir_flags & (1 << ImGuiDir_Down)) && IsNavInputPressedAnyOfTwo(ImGuiNavInput_DpadDown, ImGuiNavInput_KeyDown_, ImGuiInputReadMode_Repeat)) { g.NavMoveDir = ImGuiDir_Down; }
} }
g.NavMoveClipDir = g.NavMoveDir; g.NavMoveClipDir = g.NavMoveDir;
} }
@ -8428,7 +8455,8 @@ static void ImGui::NavUpdate()
g.NavMoveRequestForward = ImGuiNavForward_ForwardActive; g.NavMoveRequestForward = ImGuiNavForward_ForwardActive;
} }
// Update PageUp/PageDown scroll // Update PageUp/PageDown/Home/End scroll
// FIXME-NAV: Consider enabling those keys even without the master ImGuiConfigFlags_NavEnableKeyboard flag?
float nav_scoring_rect_offset_y = 0.0f; float nav_scoring_rect_offset_y = 0.0f;
if (nav_keyboard_active) if (nav_keyboard_active)
nav_scoring_rect_offset_y = NavUpdatePageUpPageDown(allowed_dir_flags); nav_scoring_rect_offset_y = NavUpdatePageUpPageDown(allowed_dir_flags);
@ -8547,8 +8575,18 @@ static void ImGui::NavUpdateMoveResult()
// Scroll to keep newly navigated item fully into view. // Scroll to keep newly navigated item fully into view.
if (g.NavLayer == 0) if (g.NavLayer == 0)
{ {
ImRect rect_abs = ImRect(result->RectRel.Min + result->Window->Pos, result->RectRel.Max + result->Window->Pos); ImVec2 delta_scroll;
ImVec2 delta_scroll = ScrollToBringRectIntoView(result->Window, rect_abs); if (g.NavMoveRequestFlags & ImGuiNavMoveFlags_ScrollToEdge)
{
float scroll_target = (g.NavMoveDir == ImGuiDir_Up) ? result->Window->ScrollMax.y : 0.0f;
delta_scroll.y = result->Window->Scroll.y - scroll_target;
SetScrollY(result->Window, scroll_target);
}
else
{
ImRect rect_abs = ImRect(result->RectRel.Min + result->Window->Pos, result->RectRel.Max + result->Window->Pos);
delta_scroll = ScrollToBringRectIntoView(result->Window, rect_abs);
}
// Offset our result position so mouse position can be applied immediately after in NavUpdate() // Offset our result position so mouse position can be applied immediately after in NavUpdate()
result->RectRel.TranslateX(-delta_scroll.x); result->RectRel.TranslateX(-delta_scroll.x);
@ -8567,6 +8605,7 @@ static void ImGui::NavUpdateMoveResult()
g.NavMoveFromClampedRefRect = false; g.NavMoveFromClampedRefRect = false;
} }
// Handle PageUp/PageDown/Home/End keys
static float ImGui::NavUpdatePageUpPageDown(int allowed_dir_flags) static float ImGui::NavUpdatePageUpPageDown(int allowed_dir_flags)
{ {
ImGuiContext& g = *GImGui; ImGuiContext& g = *GImGui;
@ -8576,9 +8615,11 @@ static float ImGui::NavUpdatePageUpPageDown(int allowed_dir_flags)
return 0.0f; return 0.0f;
ImGuiWindow* window = g.NavWindow; ImGuiWindow* window = g.NavWindow;
bool page_up_held = IsKeyDown(g.IO.KeyMap[ImGuiKey_PageUp]) && (allowed_dir_flags & (1 << ImGuiDir_Up)); const 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)); const 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 const bool home_pressed = IsKeyPressed(g.IO.KeyMap[ImGuiKey_Home]) && (allowed_dir_flags & (1 << ImGuiDir_Up));
const bool end_pressed = IsKeyPressed(g.IO.KeyMap[ImGuiKey_End]) && (allowed_dir_flags & (1 << ImGuiDir_Down));
if (page_up_held != page_down_held || home_pressed != end_pressed) // If either (not both) are pressed
{ {
if (window->DC.NavLayerActiveMask == 0x00 && window->DC.NavHasScroll) if (window->DC.NavLayerActiveMask == 0x00 && window->DC.NavHasScroll)
{ {
@ -8587,26 +8628,49 @@ static float ImGui::NavUpdatePageUpPageDown(int allowed_dir_flags)
SetScrollY(window, window->Scroll.y - window->InnerRect.GetHeight()); SetScrollY(window, window->Scroll.y - window->InnerRect.GetHeight());
else if (IsKeyPressed(g.IO.KeyMap[ImGuiKey_PageDown], true)) else if (IsKeyPressed(g.IO.KeyMap[ImGuiKey_PageDown], true))
SetScrollY(window, window->Scroll.y + window->InnerRect.GetHeight()); SetScrollY(window, window->Scroll.y + window->InnerRect.GetHeight());
else if (home_pressed)
SetScrollY(window, 0.0f);
else if (end_pressed)
SetScrollY(window, window->ScrollMax.y);
} }
else else
{ {
const ImRect& nav_rect_rel = window->NavRectRel[g.NavLayer]; 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()); 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; float nav_scoring_rect_offset_y = 0.0f;
if (IsKeyPressed(g.IO.KeyMap[ImGuiKey_PageUp], true)) if (IsKeyPressed(g.IO.KeyMap[ImGuiKey_PageUp], true))
{ {
nav_scoring_rect_offset_y = -page_offset_y; 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.NavMoveDir = ImGuiDir_Down; // Because our scoring rect is offset up, we request the down direction (so we can always land on the last item)
g.NavMoveClipDir = ImGuiDir_Up; g.NavMoveClipDir = ImGuiDir_Up;
g.NavMoveRequestFlags = ImGuiNavMoveFlags_AllowCurrentNavId | ImGuiNavMoveFlags_AlsoScoreVisibleSet; g.NavMoveRequestFlags = ImGuiNavMoveFlags_AllowCurrentNavId | ImGuiNavMoveFlags_AlsoScoreVisibleSet;
} }
else if (IsKeyPressed(g.IO.KeyMap[ImGuiKey_PageDown], true)) else if (IsKeyPressed(g.IO.KeyMap[ImGuiKey_PageDown], true))
{ {
nav_scoring_rect_offset_y = +page_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.NavMoveDir = ImGuiDir_Up; // Because our scoring rect is offset down, we request the up direction (so we can always land on the last item)
g.NavMoveClipDir = ImGuiDir_Down; g.NavMoveClipDir = ImGuiDir_Down;
g.NavMoveRequestFlags = ImGuiNavMoveFlags_AllowCurrentNavId | ImGuiNavMoveFlags_AlsoScoreVisibleSet; g.NavMoveRequestFlags = ImGuiNavMoveFlags_AllowCurrentNavId | ImGuiNavMoveFlags_AlsoScoreVisibleSet;
} }
else if (home_pressed)
{
// FIXME-NAV: handling of Home/End is assuming that the top/bottom most item will be visible with Scroll.y == 0/ScrollMax.y
// Scrolling will be handled via the ImGuiNavMoveFlags_ScrollToEdge flag, we don't scroll immediately to avoid scrolling happening before nav result.
// Preserve current horizontal position if we have any.
nav_rect_rel.Min.y = nav_rect_rel.Max.y = -window->Scroll.y;
if (nav_rect_rel.IsInverted())
nav_rect_rel.Min.x = nav_rect_rel.Max.x = 0.0f;
g.NavMoveDir = ImGuiDir_Down;
g.NavMoveRequestFlags = ImGuiNavMoveFlags_AllowCurrentNavId | ImGuiNavMoveFlags_ScrollToEdge;
}
else if (end_pressed)
{
nav_rect_rel.Min.y = nav_rect_rel.Max.y = window->ScrollMax.y + window->SizeFull.y - window->Scroll.y;
if (nav_rect_rel.IsInverted())
nav_rect_rel.Min.x = nav_rect_rel.Max.x = 0.0f;
g.NavMoveDir = ImGuiDir_Up;
g.NavMoveRequestFlags = ImGuiNavMoveFlags_AllowCurrentNavId | ImGuiNavMoveFlags_ScrollToEdge;
}
return nav_scoring_rect_offset_y; return nav_scoring_rect_offset_y;
} }
} }
@ -8802,7 +8866,7 @@ static const char* GetFallbackWindowNameForWindowingList(ImGuiWindow* window)
} }
// Overlay displayed when using CTRL+TAB. Called by EndFrame(). // Overlay displayed when using CTRL+TAB. Called by EndFrame().
void ImGui::NavUpdateWindowingList() void ImGui::NavUpdateWindowingOverlay()
{ {
ImGuiContext& g = *GImGui; ImGuiContext& g = *GImGui;
IM_ASSERT(g.NavWindowingTarget != NULL); IM_ASSERT(g.NavWindowingTarget != NULL);
@ -9654,7 +9718,7 @@ static const char* GetClipboardTextFn_DefaultImpl(void*)
ItemCount item_count = 0; ItemCount item_count = 0;
PasteboardGetItemCount(main_clipboard, &item_count); PasteboardGetItemCount(main_clipboard, &item_count);
for (int i = 0; i < item_count; i++) for (ItemCount i = 0; i < item_count; i++)
{ {
PasteboardItemID item_id = 0; PasteboardItemID item_id = 0;
PasteboardGetItemIdentifier(main_clipboard, i + 1, &item_id); PasteboardGetItemIdentifier(main_clipboard, i + 1, &item_id);

View File

@ -329,7 +329,7 @@ namespace ImGui
IMGUI_API ImU32 GetColorU32(ImU32 col); // retrieve given color with style alpha applied IMGUI_API ImU32 GetColorU32(ImU32 col); // retrieve given color with style alpha applied
// Parameters stacks (current window) // Parameters stacks (current window)
IMGUI_API void PushItemWidth(float item_width); // set width of items for common large "item+label" widgets. >0.0f: width in pixels, <0.0f align xx pixels to the right of window (so -1.0f always align width to the right side). 0.0f = default to ~2/3 of windows width, IMGUI_API void PushItemWidth(float item_width); // set width of items for common large "item+label" widgets. >0.0f: width in pixels, <0.0f align xx pixels to the right of window (so -1.0f always align width to the right side). 0.0f = default to ~2/3 of windows width,
IMGUI_API void PopItemWidth(); IMGUI_API void PopItemWidth();
IMGUI_API void SetNextItemWidth(float item_width); // set width of the _next_ common large "item+label" widget. >0.0f: width in pixels, <0.0f align xx pixels to the right of window (so -1.0f always align width to the right side) IMGUI_API void SetNextItemWidth(float item_width); // set width of the _next_ common large "item+label" widget. >0.0f: width in pixels, <0.0f align xx pixels to the right of window (so -1.0f always align width to the right side)
IMGUI_API float CalcItemWidth(); // width of item given pushed settings and current cursor position. NOT necessarily the width of last item unlike most 'Item' functions. IMGUI_API float CalcItemWidth(); // width of item given pushed settings and current cursor position. NOT necessarily the width of last item unlike most 'Item' functions.
@ -1765,7 +1765,7 @@ struct ImColor
// Draw callbacks for advanced uses. // Draw callbacks for advanced uses.
// NB: You most likely do NOT need to use draw callbacks just to create your own widget or customized UI rendering, // NB: You most likely do NOT need to use draw callbacks just to create your own widget or customized UI rendering,
// you can poke into the draw list for that! Draw callback may be useful for example to: // you can poke into the draw list for that! Draw callback may be useful for example to:
// A) Change your GPU render state, // A) Change your GPU render state,
// B) render a complex 3D scene inside a UI element without an intermediate texture/render target, etc. // B) render a complex 3D scene inside a UI element without an intermediate texture/render target, etc.
// The expected behavior from your rendering function is 'if (cmd.UserCallback != NULL) { cmd.UserCallback(parent_list, cmd); } else { RenderTriangles() }' // The expected behavior from your rendering function is 'if (cmd.UserCallback != NULL) { cmd.UserCallback(parent_list, cmd); } else { RenderTriangles() }'
@ -1796,7 +1796,7 @@ struct ImDrawCmd
ImDrawCmd() { ElemCount = 0; TextureId = (ImTextureID)NULL; VtxOffset = IdxOffset = 0; UserCallback = NULL; UserCallbackData = NULL; } ImDrawCmd() { ElemCount = 0; TextureId = (ImTextureID)NULL; VtxOffset = IdxOffset = 0; UserCallback = NULL; UserCallbackData = NULL; }
}; };
// Vertex index // Vertex index
// (to allow large meshes with 16-bits indices: set 'io.BackendFlags |= ImGuiBackendFlags_RendererHasVtxOffset' and handle ImDrawCmd::VtxOffset in the renderer back-end) // (to allow large meshes with 16-bits indices: set 'io.BackendFlags |= ImGuiBackendFlags_RendererHasVtxOffset' and handle ImDrawCmd::VtxOffset in the renderer back-end)
// (to use 32-bits indices: override with '#define ImDrawIdx unsigned int' in imconfig.h) // (to use 32-bits indices: override with '#define ImDrawIdx unsigned int' in imconfig.h)
#ifndef ImDrawIdx #ifndef ImDrawIdx
@ -1827,7 +1827,7 @@ struct ImDrawChannel
}; };
// Split/Merge functions are used to split the draw list into different layers which can be drawn into out of order. // Split/Merge functions are used to split the draw list into different layers which can be drawn into out of order.
// This is used by the Columns api, so items of each column can be batched together in a same draw call. // This is used by the Columns api, so items of each column can be batched together in a same draw call.
struct ImDrawListSplitter struct ImDrawListSplitter
{ {
int _Current; // Current channel number (0) int _Current; // Current channel number (0)
@ -1868,7 +1868,7 @@ enum ImDrawListFlags_
// Draw command list // Draw command list
// This is the low-level list of polygons that ImGui:: functions are filling. At the end of the frame, // This is the low-level list of polygons that ImGui:: functions are filling. At the end of the frame,
// all command lists are passed to your ImGuiIO::RenderDrawListFn function for rendering. // all command lists are passed to your ImGuiIO::RenderDrawListFn function for rendering.
// Each dear imgui window contains its own ImDrawList. You can use ImGui::GetWindowDrawList() to // Each dear imgui window contains its own ImDrawList. You can use ImGui::GetWindowDrawList() to
// access the current window draw list and draw custom primitives. // access the current window draw list and draw custom primitives.
// You can interleave normal ImGui:: calls and adding primitives to the current draw list. // You can interleave normal ImGui:: calls and adding primitives to the current draw list.
// All positions are generally in pixel coordinates (top-left at (0,0), bottom-right at io.DisplaySize), but you are totally free to apply whatever transformation matrix to want to the data (if you apply such transformation you'll want to apply it to ClipRect as well) // All positions are generally in pixel coordinates (top-left at (0,0), bottom-right at io.DisplaySize), but you are totally free to apply whatever transformation matrix to want to the data (if you apply such transformation you'll want to apply it to ClipRect as well)
@ -2012,6 +2012,7 @@ struct ImFontConfig
bool MergeMode; // false // Merge into previous ImFont, so you can combine multiple inputs font into one ImFont (e.g. ASCII font + icons + Japanese glyphs). You may want to use GlyphOffset.y when merge font of different heights. bool MergeMode; // false // Merge into previous ImFont, so you can combine multiple inputs font into one ImFont (e.g. ASCII font + icons + Japanese glyphs). You may want to use GlyphOffset.y when merge font of different heights.
unsigned int RasterizerFlags; // 0x00 // Settings for custom font rasterizer (e.g. ImGuiFreeType). Leave as zero if you aren't using one. unsigned int RasterizerFlags; // 0x00 // Settings for custom font rasterizer (e.g. ImGuiFreeType). Leave as zero if you aren't using one.
float RasterizerMultiply; // 1.0f // Brighten (>1.0f) or darken (<1.0f) font output. Brightening small fonts may be a good workaround to make them more readable. float RasterizerMultiply; // 1.0f // Brighten (>1.0f) or darken (<1.0f) font output. Brightening small fonts may be a good workaround to make them more readable.
ImWchar EllipsisChar; // -1 // Explicitly specify unicode codepoint of ellipsis character. When fonts are being merged first specified ellipsis will be used.
// [Internal] // [Internal]
char Name[40]; // Name (strictly to ease debugging) char Name[40]; // Name (strictly to ease debugging)
@ -2127,9 +2128,9 @@ struct ImFontAtlas
// [BETA] Custom Rectangles/Glyphs API // [BETA] Custom Rectangles/Glyphs API
//------------------------------------------- //-------------------------------------------
// You can request arbitrary rectangles to be packed into the atlas, for your own purposes. // You can request arbitrary rectangles to be packed into the atlas, for your own purposes.
// After calling Build(), you can query the rectangle position and render your pixels. // After calling Build(), you can query the rectangle position and render your pixels.
// You can also request your rectangles to be mapped as font glyph (given a font + Unicode point), // You can also request your rectangles to be mapped as font glyph (given a font + Unicode point),
// so you can render e.g. custom colorful icons and use them as regular glyphs. // so you can render e.g. custom colorful icons and use them as regular glyphs.
// Read misc/fonts/README.txt for more details about using colorful icons. // Read misc/fonts/README.txt for more details about using colorful icons.
IMGUI_API int AddCustomRectRegular(unsigned int id, int width, int height); // Id needs to be >= 0x10000. Id >= 0x80000000 are reserved for ImGui and ImDrawList IMGUI_API int AddCustomRectRegular(unsigned int id, int width, int height); // Id needs to be >= 0x10000. Id >= 0x80000000 are reserved for ImGui and ImDrawList
@ -2188,7 +2189,8 @@ struct ImFont
ImFontAtlas* ContainerAtlas; // 4-8 // out // // What we has been loaded into ImFontAtlas* ContainerAtlas; // 4-8 // out // // What we has been loaded into
const ImFontConfig* ConfigData; // 4-8 // in // // Pointer within ContainerAtlas->ConfigData const ImFontConfig* ConfigData; // 4-8 // in // // Pointer within ContainerAtlas->ConfigData
short ConfigDataCount; // 2 // in // ~ 1 // Number of ImFontConfig involved in creating this font. Bigger than 1 when merging multiple font sources into one ImFont. short ConfigDataCount; // 2 // in // ~ 1 // Number of ImFontConfig involved in creating this font. Bigger than 1 when merging multiple font sources into one ImFont.
ImWchar FallbackChar; // 2 // in // = '?' // Replacement glyph if one isn't found. Only set via SetFallbackChar() ImWchar FallbackChar; // 2 // in // = '?' // Replacement character if a glyph isn't found. Only set via SetFallbackChar()
ImWchar EllipsisChar; // 2 // out // = -1 // Character used for ellipsis rendering.
float Scale; // 4 // in // = 1.f // Base font scale, multiplied by the per-window font scale which you can adjust with SetWindowFontScale() float Scale; // 4 // in // = 1.f // Base font scale, multiplied by the per-window font scale which you can adjust with SetWindowFontScale()
float Ascent, Descent; // 4+4 // out // // Ascent: distance from top to bottom of e.g. 'A' [0..FontSize] float Ascent, Descent; // 4+4 // out // // Ascent: distance from top to bottom of e.g. 'A' [0..FontSize]
int MetricsTotalSurface;// 4 // out // // Total surface in pixels to get an idea of the font rasterization/texture cost (not exact, we approximate the cost of padding between glyphs) int MetricsTotalSurface;// 4 // out // // Total surface in pixels to get an idea of the font rasterization/texture cost (not exact, we approximate the cost of padding between glyphs)

View File

@ -17,7 +17,7 @@
// In this demo code, we frequently we use 'static' variables inside functions. A static variable persist across calls, so it is // In this demo code, we frequently we use 'static' variables inside functions. A static variable persist across calls, so it is
// essentially like a global variable but declared inside the scope of the function. We do this as a way to gather code and data // essentially like a global variable but declared inside the scope of the function. We do this as a way to gather code and data
// in the same place, to make the demo source code faster to read, faster to write, and smaller in size. // in the same place, to make the demo source code faster to read, faster to write, and smaller in size.
// It also happens to be a convenient way of storing simple UI related information as long as your function doesn't need to be // It also happens to be a convenient way of storing simple UI related information as long as your function doesn't need to be
// reentrant or used in multiple threads. This might be a pattern you will want to use in your code, but most of the real data // reentrant or used in multiple threads. This might be a pattern you will want to use in your code, but most of the real data
// you would be editing is likely going to be stored outside your functions. // you would be editing is likely going to be stored outside your functions.
@ -589,7 +589,7 @@ static void ShowDemoWindowWidgets()
{ {
for (int i = 0; i < 5; i++) for (int i = 0; i < 5; i++)
{ {
// Use SetNextItemOpen() so set the default state of a node to be open. // Use SetNextItemOpen() so set the default state of a node to be open.
// We could also use TreeNodeEx() with the ImGuiTreeNodeFlags_DefaultOpen flag to achieve the same thing! // We could also use TreeNodeEx() with the ImGuiTreeNodeFlags_DefaultOpen flag to achieve the same thing!
if (i == 0) if (i == 0)
ImGui::SetNextItemOpen(true, ImGuiCond_Once); ImGui::SetNextItemOpen(true, ImGuiCond_Once);
@ -1109,7 +1109,7 @@ static void ShowDemoWindowWidgets()
if (progress <= -0.1f) { progress = -0.1f; progress_dir *= -1.0f; } if (progress <= -0.1f) { progress = -0.1f; progress_dir *= -1.0f; }
} }
// Typically we would use ImVec2(-1.0f,0.0f) or ImVec2(-FLT_MIN,0.0f) to use all available width, // Typically we would use ImVec2(-1.0f,0.0f) or ImVec2(-FLT_MIN,0.0f) to use all available width,
// or ImVec2(width,0.0f) for a specified width. ImVec2(0.0f,0.0f) uses ItemWidth. // or ImVec2(width,0.0f) for a specified width. ImVec2(0.0f,0.0f) uses ItemWidth.
ImGui::ProgressBar(progress, ImVec2(0.0f,0.0f)); ImGui::ProgressBar(progress, ImVec2(0.0f,0.0f));
ImGui::SameLine(0.0f, ImGui::GetStyle().ItemInnerSpacing.x); ImGui::SameLine(0.0f, ImGui::GetStyle().ItemInnerSpacing.x);
@ -1451,7 +1451,7 @@ static void ShowDemoWindowWidgets()
ImGui::PushID("set2"); ImGui::PushID("set2");
static float values2[4] = { 0.20f, 0.80f, 0.40f, 0.25f }; static float values2[4] = { 0.20f, 0.80f, 0.40f, 0.25f };
const int rows = 3; const int rows = 3;
const ImVec2 small_slider_size(18, (160.0f-(rows-1)*spacing)/rows); const ImVec2 small_slider_size(18, (float)(int)((160.0f - (rows - 1) * spacing) / rows));
for (int nx = 0; nx < 4; nx++) for (int nx = 0; nx < 4; nx++)
{ {
if (nx > 0) ImGui::SameLine(); if (nx > 0) ImGui::SameLine();
@ -2259,7 +2259,7 @@ static void ShowDemoWindowLayout()
ImGui::SameLine(); ImGui::SameLine();
ImGui::SetNextItemWidth(100); ImGui::SetNextItemWidth(100);
ImGui::DragFloat("##csx", &contents_size_x); ImGui::DragFloat("##csx", &contents_size_x);
ImVec2 p = ImGui::GetCursorScreenPos(); ImVec2 p = ImGui::GetCursorScreenPos();
ImGui::GetWindowDrawList()->AddRectFilled(p, ImVec2(p.x + 10, p.y + 10), IM_COL32_WHITE); ImGui::GetWindowDrawList()->AddRectFilled(p, ImVec2(p.x + 10, p.y + 10), IM_COL32_WHITE);
ImGui::GetWindowDrawList()->AddRectFilled(ImVec2(p.x + contents_size_x - 10, p.y), ImVec2(p.x + contents_size_x, p.y + 10), IM_COL32_WHITE); ImGui::GetWindowDrawList()->AddRectFilled(ImVec2(p.x + contents_size_x - 10, p.y), ImVec2(p.x + contents_size_x, p.y + 10), IM_COL32_WHITE);
ImGui::Dummy(ImVec2(0, 10)); ImGui::Dummy(ImVec2(0, 10));
@ -3283,7 +3283,8 @@ void ImGui::ShowStyleEditor(ImGuiStyle* ref)
ImGui::SameLine(); HelpMarker("Note than the default embedded font is NOT meant to be scaled.\n\nFont are currently rendered into bitmaps at a given size at the time of building the atlas. You may oversample them to get some flexibility with scaling. You can also render at multiple sizes and select which one to use at runtime.\n\n(Glimmer of hope: the atlas system should hopefully be rewritten in the future to make scaling more natural and automatic.)"); ImGui::SameLine(); HelpMarker("Note than the default embedded font is NOT meant to be scaled.\n\nFont are currently rendered into bitmaps at a given size at the time of building the atlas. You may oversample them to get some flexibility with scaling. You can also render at multiple sizes and select which one to use at runtime.\n\n(Glimmer of hope: the atlas system should hopefully be rewritten in the future to make scaling more natural and automatic.)");
ImGui::InputFloat("Font offset", &font->DisplayOffset.y, 1, 1, "%.0f"); ImGui::InputFloat("Font offset", &font->DisplayOffset.y, 1, 1, "%.0f");
ImGui::Text("Ascent: %f, Descent: %f, Height: %f", font->Ascent, font->Descent, font->Ascent - font->Descent); ImGui::Text("Ascent: %f, Descent: %f, Height: %f", font->Ascent, font->Descent, font->Ascent - font->Descent);
ImGui::Text("Fallback character: '%c' (%d)", font->FallbackChar, font->FallbackChar); ImGui::Text("Fallback character: '%c' (U+%04X)", font->FallbackChar, font->FallbackChar);
ImGui::Text("Ellipsis character: '%c' (U+%04X)", font->EllipsisChar);
const float surface_sqrt = sqrtf((float)font->MetricsTotalSurface); const float surface_sqrt = sqrtf((float)font->MetricsTotalSurface);
ImGui::Text("Texture surface: %d pixels (approx) ~ %dx%d", font->MetricsTotalSurface, (int)surface_sqrt, (int)surface_sqrt); ImGui::Text("Texture surface: %d pixels (approx) ~ %dx%d", font->MetricsTotalSurface, (int)surface_sqrt, (int)surface_sqrt);
for (int config_i = 0; config_i < font->ConfigDataCount; config_i++) for (int config_i = 0; config_i < font->ConfigDataCount; config_i++)

View File

@ -1202,7 +1202,7 @@ void ImDrawListSplitter::ClearFreeMemory()
{ {
for (int i = 0; i < _Channels.Size; i++) for (int i = 0; i < _Channels.Size; i++)
{ {
if (i == _Current) if (i == _Current)
memset(&_Channels[i], 0, sizeof(_Channels[i])); // Current channel is a copy of CmdBuffer/IdxBuffer, don't destruct again memset(&_Channels[i], 0, sizeof(_Channels[i])); // Current channel is a copy of CmdBuffer/IdxBuffer, don't destruct again
_Channels[i]._CmdBuffer.clear(); _Channels[i]._CmdBuffer.clear();
_Channels[i]._IdxBuffer.clear(); _Channels[i]._IdxBuffer.clear();
@ -1307,7 +1307,7 @@ void ImDrawListSplitter::Merge(ImDrawList* draw_list)
void ImDrawListSplitter::SetCurrentChannel(ImDrawList* draw_list, int idx) void ImDrawListSplitter::SetCurrentChannel(ImDrawList* draw_list, int idx)
{ {
IM_ASSERT(idx >= 0 && idx < _Count); IM_ASSERT(idx >= 0 && idx < _Count);
if (_Current == idx) if (_Current == idx)
return; return;
// Overwrite ImVector (12/16 bytes), four times. This is merely a silly optimization instead of doing .swap() // Overwrite ImVector (12/16 bytes), four times. This is merely a silly optimization instead of doing .swap()
memcpy(&_Channels.Data[_Current]._CmdBuffer, &draw_list->CmdBuffer, sizeof(draw_list->CmdBuffer)); memcpy(&_Channels.Data[_Current]._CmdBuffer, &draw_list->CmdBuffer, sizeof(draw_list->CmdBuffer));
@ -1426,6 +1426,7 @@ ImFontConfig::ImFontConfig()
MergeMode = false; MergeMode = false;
RasterizerFlags = 0x00; RasterizerFlags = 0x00;
RasterizerMultiply = 1.0f; RasterizerMultiply = 1.0f;
EllipsisChar = (ImWchar)-1;
memset(Name, 0, sizeof(Name)); memset(Name, 0, sizeof(Name));
DstFont = NULL; DstFont = NULL;
} }
@ -1618,6 +1619,9 @@ ImFont* ImFontAtlas::AddFont(const ImFontConfig* font_cfg)
memcpy(new_font_cfg.FontData, font_cfg->FontData, (size_t)new_font_cfg.FontDataSize); memcpy(new_font_cfg.FontData, font_cfg->FontData, (size_t)new_font_cfg.FontDataSize);
} }
if (new_font_cfg.DstFont->EllipsisChar == (ImWchar)-1)
new_font_cfg.DstFont->EllipsisChar = font_cfg->EllipsisChar;
// Invalidate texture // Invalidate texture
ClearTexData(); ClearTexData();
return new_font_cfg.DstFont; return new_font_cfg.DstFont;
@ -1652,6 +1656,7 @@ ImFont* ImFontAtlas::AddFontDefault(const ImFontConfig* font_cfg_template)
font_cfg.SizePixels = 13.0f * 1.0f; font_cfg.SizePixels = 13.0f * 1.0f;
if (font_cfg.Name[0] == '\0') if (font_cfg.Name[0] == '\0')
ImFormatString(font_cfg.Name, IM_ARRAYSIZE(font_cfg.Name), "ProggyClean.ttf, %dpx", (int)font_cfg.SizePixels); ImFormatString(font_cfg.Name, IM_ARRAYSIZE(font_cfg.Name), "ProggyClean.ttf, %dpx", (int)font_cfg.SizePixels);
font_cfg.EllipsisChar = (ImWchar)0x0085;
const char* ttf_compressed_base85 = GetDefaultCompressedFontDataTTFBase85(); const char* ttf_compressed_base85 = GetDefaultCompressedFontDataTTFBase85();
const ImWchar* glyph_ranges = font_cfg.GlyphRanges != NULL ? font_cfg.GlyphRanges : GetGlyphRangesDefault(); const ImWchar* glyph_ranges = font_cfg.GlyphRanges != NULL ? font_cfg.GlyphRanges : GetGlyphRangesDefault();
@ -2196,6 +2201,23 @@ void ImFontAtlasBuildFinish(ImFontAtlas* atlas)
for (int i = 0; i < atlas->Fonts.Size; i++) for (int i = 0; i < atlas->Fonts.Size; i++)
if (atlas->Fonts[i]->DirtyLookupTables) if (atlas->Fonts[i]->DirtyLookupTables)
atlas->Fonts[i]->BuildLookupTable(); atlas->Fonts[i]->BuildLookupTable();
// Ellipsis character is required for rendering elided text. We prefer using U+2026 (horizontal ellipsis).
// However some old fonts may contain ellipsis at U+0085. Here we auto-detect most suitable ellipsis character.
// FIXME: Also note that 0x2026 is currently seldomly included in our font ranges. Because of this we are more likely to use three individual dots.
for (int i = 0; i < atlas->Fonts.size(); i++)
{
ImFont* font = atlas->Fonts[i];
if (font->EllipsisChar != (ImWchar)-1)
continue;
const ImWchar ellipsis_variants[] = { (ImWchar)0x2026, (ImWchar)0x0085 };
for (int j = 0; j < IM_ARRAYSIZE(ellipsis_variants); j++)
if (font->FindGlyphNoFallback(ellipsis_variants[j]) != NULL) // Verify glyph exists
{
font->EllipsisChar = ellipsis_variants[j];
break;
}
}
} }
// Retrieve list of range (2 int per range, values are inclusive) // Retrieve list of range (2 int per range, values are inclusive)
@ -2465,6 +2487,7 @@ ImFont::ImFont()
FontSize = 0.0f; FontSize = 0.0f;
FallbackAdvanceX = 0.0f; FallbackAdvanceX = 0.0f;
FallbackChar = (ImWchar)'?'; FallbackChar = (ImWchar)'?';
EllipsisChar = (ImWchar)-1;
DisplayOffset = ImVec2(0.0f, 0.0f); DisplayOffset = ImVec2(0.0f, 0.0f);
FallbackGlyph = NULL; FallbackGlyph = NULL;
ContainerAtlas = NULL; ContainerAtlas = NULL;
@ -3012,7 +3035,6 @@ void ImFont::RenderText(ImDrawList* draw_list, float size, ImVec2 pos, ImU32 col
// - RenderMouseCursor() // - RenderMouseCursor()
// - RenderArrowPointingAt() // - RenderArrowPointingAt()
// - RenderRectFilledRangeH() // - RenderRectFilledRangeH()
// - RenderPixelEllipsis()
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
void ImGui::RenderMouseCursor(ImDrawList* draw_list, ImVec2 pos, float scale, ImGuiMouseCursor mouse_cursor) void ImGui::RenderMouseCursor(ImDrawList* draw_list, ImVec2 pos, float scale, ImGuiMouseCursor mouse_cursor)
@ -3122,18 +3144,6 @@ void ImGui::RenderRectFilledRangeH(ImDrawList* draw_list, const ImRect& rect, Im
draw_list->PathFillConvex(col); draw_list->PathFillConvex(col);
} }
// FIXME: Rendering an ellipsis "..." is a surprisingly tricky problem for us... we cannot rely on font glyph having it,
// and regular dot are typically too wide. If we render a dot/shape ourselves it comes with the risk that it wouldn't match
// the boldness or positioning of what the font uses...
void ImGui::RenderPixelEllipsis(ImDrawList* draw_list, ImVec2 pos, ImU32 col, int count)
{
ImFont* font = draw_list->_Data->Font;
const float font_scale = draw_list->_Data->FontSize / font->FontSize;
pos.y += (float)(int)(font->DisplayOffset.y + font->Ascent * font_scale + 0.5f - 1.0f);
for (int dot_n = 0; dot_n < count; dot_n++)
draw_list->AddRectFilled(ImVec2(pos.x + dot_n * 2.0f, pos.y), ImVec2(pos.x + dot_n * 2.0f + 1.0f, pos.y + 1.0f), col);
}
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// [SECTION] Decompression code // [SECTION] Decompression code
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------

View File

@ -497,7 +497,8 @@ enum ImGuiNavMoveFlags_
ImGuiNavMoveFlags_WrapX = 1 << 2, // On failed request, request from opposite side one line down (when NavDir==right) or one line up (when NavDir==left) ImGuiNavMoveFlags_WrapX = 1 << 2, // On failed request, request from opposite side one line down (when NavDir==right) or one line up (when NavDir==left)
ImGuiNavMoveFlags_WrapY = 1 << 3, // This is not super useful for provided for completeness ImGuiNavMoveFlags_WrapY = 1 << 3, // This is not super useful for provided for completeness
ImGuiNavMoveFlags_AllowCurrentNavId = 1 << 4, // Allow scoring and considering the current NavId as a move target candidate. This is used when the move source is offset (e.g. pressing PageDown actually needs to send a Up move request, if we are pressing PageDown from the bottom-most item we need to stay in place) ImGuiNavMoveFlags_AllowCurrentNavId = 1 << 4, // Allow scoring and considering the current NavId as a move target candidate. This is used when the move source is offset (e.g. pressing PageDown actually needs to send a Up move request, if we are pressing PageDown from the bottom-most item we need to stay in place)
ImGuiNavMoveFlags_AlsoScoreVisibleSet = 1 << 5 // Store alternate result in NavMoveResultLocalVisibleSet that only comprise elements that are already fully visible. ImGuiNavMoveFlags_AlsoScoreVisibleSet = 1 << 5, // Store alternate result in NavMoveResultLocalVisibleSet that only comprise elements that are already fully visible.
ImGuiNavMoveFlags_ScrollToEdge = 1 << 6
}; };
enum ImGuiNavForward enum ImGuiNavForward
@ -808,7 +809,7 @@ struct ImGuiNextWindowData
void* SizeCallbackUserData; void* SizeCallbackUserData;
float BgAlphaVal; float BgAlphaVal;
ImVec2 MenuBarOffsetMinVal; // *Always on* This is not exposed publicly, so we don't clear it. ImVec2 MenuBarOffsetMinVal; // *Always on* This is not exposed publicly, so we don't clear it.
ImGuiNextWindowData() { memset(this, 0, sizeof(*this)); } ImGuiNextWindowData() { memset(this, 0, sizeof(*this)); }
inline void ClearFlags() { Flags = ImGuiNextWindowDataFlags_None; } inline void ClearFlags() { Flags = ImGuiNextWindowDataFlags_None; }
}; };
@ -960,7 +961,7 @@ struct ImGuiContext
ImGuiNavMoveFlags NavMoveRequestFlags; ImGuiNavMoveFlags NavMoveRequestFlags;
ImGuiNavForward NavMoveRequestForward; // None / ForwardQueued / ForwardActive (this is used to navigate sibling parent menus from a child menu) ImGuiNavForward NavMoveRequestForward; // None / ForwardQueued / ForwardActive (this is used to navigate sibling parent menus from a child menu)
ImGuiDir NavMoveDir, NavMoveDirLast; // Direction of the move request (left/right/up/down), direction of the previous move request ImGuiDir NavMoveDir, NavMoveDirLast; // Direction of the move request (left/right/up/down), direction of the previous move request
ImGuiDir NavMoveClipDir; ImGuiDir NavMoveClipDir; // FIXME-NAV: Describe the purpose of this better. Might want to rename?
ImGuiNavMoveResult NavMoveResultLocal; // Best move request candidate within NavWindow ImGuiNavMoveResult NavMoveResultLocal; // Best move request candidate within NavWindow
ImGuiNavMoveResult NavMoveResultLocalVisibleSet; // Best move request candidate within NavWindow that are mostly visible (when using ImGuiNavMoveFlags_AlsoScoreVisibleSet flag) ImGuiNavMoveResult NavMoveResultLocalVisibleSet; // Best move request candidate within NavWindow that are mostly visible (when using ImGuiNavMoveFlags_AlsoScoreVisibleSet flag)
ImGuiNavMoveResult NavMoveResultOther; // Best move request candidate within NavWindow's flattened hierarchy (when using ImGuiWindowFlags_NavFlattened flag) ImGuiNavMoveResult NavMoveResultOther; // Best move request candidate within NavWindow's flattened hierarchy (when using ImGuiWindowFlags_NavFlattened flag)
@ -1634,7 +1635,6 @@ namespace ImGui
IMGUI_API void RenderMouseCursor(ImDrawList* draw_list, ImVec2 pos, float scale, ImGuiMouseCursor mouse_cursor = ImGuiMouseCursor_Arrow); IMGUI_API void RenderMouseCursor(ImDrawList* draw_list, ImVec2 pos, float scale, ImGuiMouseCursor mouse_cursor = ImGuiMouseCursor_Arrow);
IMGUI_API void RenderArrowPointingAt(ImDrawList* draw_list, ImVec2 pos, ImVec2 half_sz, ImGuiDir direction, ImU32 col); IMGUI_API void RenderArrowPointingAt(ImDrawList* draw_list, ImVec2 pos, ImVec2 half_sz, ImGuiDir direction, ImU32 col);
IMGUI_API void RenderRectFilledRangeH(ImDrawList* draw_list, const ImRect& rect, ImU32 col, float x_start_norm, float x_end_norm, float rounding); IMGUI_API void RenderRectFilledRangeH(ImDrawList* draw_list, const ImRect& rect, ImU32 col, float x_start_norm, float x_end_norm, float rounding);
IMGUI_API void RenderPixelEllipsis(ImDrawList* draw_list, ImVec2 pos, ImU32 col, int count);
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS #ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
// 2019/06/07: Updating prototypes of some of the internal functions. Leaving those for reference for a short while. // 2019/06/07: Updating prototypes of some of the internal functions. Leaving those for reference for a short while.
@ -1709,7 +1709,7 @@ IMGUI_API void ImFontAtlasBuildMultiplyRectAlpha8(const unsigned ch
// Debug Tools // Debug Tools
// Use 'Metrics->Tools->Item Picker' to break into the call-stack of a specific item. // Use 'Metrics->Tools->Item Picker' to break into the call-stack of a specific item.
#ifndef IM_DEBUG_BREAK #ifndef IM_DEBUG_BREAK
#if defined(__clang__) #if defined(__clang__)
#define IM_DEBUG_BREAK() __builtin_debugtrap() #define IM_DEBUG_BREAK() __builtin_debugtrap()
#elif defined (_MSC_VER) #elif defined (_MSC_VER)

View File

@ -399,37 +399,37 @@ void ImGui::BulletTextV(const char* fmt, va_list args)
// See the series of events below and the corresponding state reported by dear imgui: // See the series of events below and the corresponding state reported by dear imgui:
//------------------------------------------------------------------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------------------------------------------------------------------
// with PressedOnClickRelease: return-value IsItemHovered() IsItemActive() IsItemActivated() IsItemDeactivated() IsItemClicked() // with PressedOnClickRelease: return-value IsItemHovered() IsItemActive() IsItemActivated() IsItemDeactivated() IsItemClicked()
// Frame N+0 (mouse is outside bb) - - - - - - // Frame N+0 (mouse is outside bb) - - - - - -
// Frame N+1 (mouse moves inside bb) - true - - - - // Frame N+1 (mouse moves inside bb) - true - - - -
// Frame N+2 (mouse button is down) - true true true - true // Frame N+2 (mouse button is down) - true true true - true
// Frame N+3 (mouse button is down) - true true - - - // Frame N+3 (mouse button is down) - true true - - -
// Frame N+4 (mouse moves outside bb) - - true - - - // Frame N+4 (mouse moves outside bb) - - true - - -
// Frame N+5 (mouse moves inside bb) - true true - - - // Frame N+5 (mouse moves inside bb) - true true - - -
// Frame N+6 (mouse button is released) true true - - true - // Frame N+6 (mouse button is released) true true - - true -
// Frame N+7 (mouse button is released) - true - - - - // Frame N+7 (mouse button is released) - true - - - -
// Frame N+8 (mouse moves outside bb) - - - - - - // Frame N+8 (mouse moves outside bb) - - - - - -
//------------------------------------------------------------------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------------------------------------------------------------------
// with PressedOnClick: return-value IsItemHovered() IsItemActive() IsItemActivated() IsItemDeactivated() IsItemClicked() // with PressedOnClick: return-value IsItemHovered() IsItemActive() IsItemActivated() IsItemDeactivated() IsItemClicked()
// Frame N+2 (mouse button is down) true true true true - true // Frame N+2 (mouse button is down) true true true true - true
// Frame N+3 (mouse button is down) - true true - - - // Frame N+3 (mouse button is down) - true true - - -
// Frame N+6 (mouse button is released) - true - - true - // Frame N+6 (mouse button is released) - true - - true -
// Frame N+7 (mouse button is released) - true - - - - // Frame N+7 (mouse button is released) - true - - - -
//------------------------------------------------------------------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------------------------------------------------------------------
// with PressedOnRelease: return-value IsItemHovered() IsItemActive() IsItemActivated() IsItemDeactivated() IsItemClicked() // with PressedOnRelease: return-value IsItemHovered() IsItemActive() IsItemActivated() IsItemDeactivated() IsItemClicked()
// Frame N+2 (mouse button is down) - true - - - true // Frame N+2 (mouse button is down) - true - - - true
// Frame N+3 (mouse button is down) - true - - - - // Frame N+3 (mouse button is down) - true - - - -
// Frame N+6 (mouse button is released) true true - - - - // Frame N+6 (mouse button is released) true true - - - -
// Frame N+7 (mouse button is released) - true - - - - // Frame N+7 (mouse button is released) - true - - - -
//------------------------------------------------------------------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------------------------------------------------------------------
// with PressedOnDoubleClick: return-value IsItemHovered() IsItemActive() IsItemActivated() IsItemDeactivated() IsItemClicked() // with PressedOnDoubleClick: return-value IsItemHovered() IsItemActive() IsItemActivated() IsItemDeactivated() IsItemClicked()
// Frame N+0 (mouse button is down) - true - - - true // Frame N+0 (mouse button is down) - true - - - true
// Frame N+1 (mouse button is down) - true - - - - // Frame N+1 (mouse button is down) - true - - - -
// Frame N+2 (mouse button is released) - true - - - - // Frame N+2 (mouse button is released) - true - - - -
// Frame N+3 (mouse button is released) - true - - - - // Frame N+3 (mouse button is released) - true - - - -
// Frame N+4 (mouse button is down) true true true true - true // Frame N+4 (mouse button is down) true true true true - true
// Frame N+5 (mouse button is down) - true true - - - // Frame N+5 (mouse button is down) - true true - - -
// Frame N+6 (mouse button is released) - true - - true - // Frame N+6 (mouse button is released) - true - - true -
// Frame N+7 (mouse button is released) - true - - - - // Frame N+7 (mouse button is released) - true - - - -
//------------------------------------------------------------------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------------------------------------------------------------------
// Note that some combinations are supported, // Note that some combinations are supported,
// - PressedOnDragDropHold can generally be associated with any flag. // - PressedOnDragDropHold can generally be associated with any flag.
@ -439,7 +439,7 @@ void ImGui::BulletTextV(const char* fmt, va_list args)
// Repeat+ Repeat+ Repeat+ Repeat+ // Repeat+ Repeat+ Repeat+ Repeat+
// PressedOnClickRelease PressedOnClick PressedOnRelease PressedOnDoubleClick // PressedOnClickRelease PressedOnClick PressedOnRelease PressedOnDoubleClick
//------------------------------------------------------------------------------------------------------------------------------------------------- //-------------------------------------------------------------------------------------------------------------------------------------------------
// Frame N+0 (mouse button is down) - true - true // Frame N+0 (mouse button is down) - true - true
// ... - - - - // ... - - - -
// Frame N + RepeatDelay true true - true // Frame N + RepeatDelay true true - true
// ... - - - - // ... - - - -
@ -1261,7 +1261,10 @@ void ImGui::SeparatorEx(ImGuiSeparatorFlags flags)
if (!ItemAdd(bb, 0)) if (!ItemAdd(bb, 0))
{ {
if (columns) if (columns)
{
PopColumnsBackground(); PopColumnsBackground();
columns->LineMinY = window->DC.CursorPos.y;
}
return; return;
} }
@ -1975,12 +1978,12 @@ bool ImGui::DragBehaviorT(ImGuiDataType data_type, TYPE* v, float v_speed, const
// Offset + round to user desired precision, with a curve on the v_min..v_max range to get more precision on one side of the range // Offset + round to user desired precision, with a curve on the v_min..v_max range to get more precision on one side of the range
FLOATTYPE v_old_norm_curved = ImPow((FLOATTYPE)(v_cur - v_min) / (FLOATTYPE)(v_max - v_min), (FLOATTYPE)1.0f / power); FLOATTYPE v_old_norm_curved = ImPow((FLOATTYPE)(v_cur - v_min) / (FLOATTYPE)(v_max - v_min), (FLOATTYPE)1.0f / power);
FLOATTYPE v_new_norm_curved = v_old_norm_curved + (g.DragCurrentAccum / (v_max - v_min)); FLOATTYPE v_new_norm_curved = v_old_norm_curved + (g.DragCurrentAccum / (v_max - v_min));
v_cur = v_min + (TYPE)ImPow(ImSaturate((float)v_new_norm_curved), power) * (v_max - v_min); v_cur = v_min + (SIGNEDTYPE)ImPow(ImSaturate((float)v_new_norm_curved), power) * (v_max - v_min);
v_old_ref_for_accum_remainder = v_old_norm_curved; v_old_ref_for_accum_remainder = v_old_norm_curved;
} }
else else
{ {
v_cur += (TYPE)g.DragCurrentAccum; v_cur += (SIGNEDTYPE)g.DragCurrentAccum;
} }
// Round to user desired precision based on format string // Round to user desired precision based on format string
@ -3234,21 +3237,21 @@ static bool STB_TEXTEDIT_INSERTCHARS(STB_TEXTEDIT_STRING* obj, int pos, const Im
} }
// We don't use an enum so we can build even with conflicting symbols (if another user of stb_textedit.h leak their STB_TEXTEDIT_K_* symbols) // We don't use an enum so we can build even with conflicting symbols (if another user of stb_textedit.h leak their STB_TEXTEDIT_K_* symbols)
#define STB_TEXTEDIT_K_LEFT 0x10000 // keyboard input to move cursor left #define STB_TEXTEDIT_K_LEFT 0x200000 // keyboard input to move cursor left
#define STB_TEXTEDIT_K_RIGHT 0x10001 // keyboard input to move cursor right #define STB_TEXTEDIT_K_RIGHT 0x200001 // keyboard input to move cursor right
#define STB_TEXTEDIT_K_UP 0x10002 // keyboard input to move cursor up #define STB_TEXTEDIT_K_UP 0x200002 // keyboard input to move cursor up
#define STB_TEXTEDIT_K_DOWN 0x10003 // keyboard input to move cursor down #define STB_TEXTEDIT_K_DOWN 0x200003 // keyboard input to move cursor down
#define STB_TEXTEDIT_K_LINESTART 0x10004 // keyboard input to move cursor to start of line #define STB_TEXTEDIT_K_LINESTART 0x200004 // keyboard input to move cursor to start of line
#define STB_TEXTEDIT_K_LINEEND 0x10005 // keyboard input to move cursor to end of line #define STB_TEXTEDIT_K_LINEEND 0x200005 // keyboard input to move cursor to end of line
#define STB_TEXTEDIT_K_TEXTSTART 0x10006 // keyboard input to move cursor to start of text #define STB_TEXTEDIT_K_TEXTSTART 0x200006 // keyboard input to move cursor to start of text
#define STB_TEXTEDIT_K_TEXTEND 0x10007 // keyboard input to move cursor to end of text #define STB_TEXTEDIT_K_TEXTEND 0x200007 // keyboard input to move cursor to end of text
#define STB_TEXTEDIT_K_DELETE 0x10008 // keyboard input to delete selection or character under cursor #define STB_TEXTEDIT_K_DELETE 0x200008 // keyboard input to delete selection or character under cursor
#define STB_TEXTEDIT_K_BACKSPACE 0x10009 // keyboard input to delete selection or character left of cursor #define STB_TEXTEDIT_K_BACKSPACE 0x200009 // keyboard input to delete selection or character left of cursor
#define STB_TEXTEDIT_K_UNDO 0x1000A // keyboard input to perform undo #define STB_TEXTEDIT_K_UNDO 0x20000A // keyboard input to perform undo
#define STB_TEXTEDIT_K_REDO 0x1000B // keyboard input to perform redo #define STB_TEXTEDIT_K_REDO 0x20000B // keyboard input to perform redo
#define STB_TEXTEDIT_K_WORDLEFT 0x1000C // keyboard input to move cursor left one word #define STB_TEXTEDIT_K_WORDLEFT 0x20000C // keyboard input to move cursor left one word
#define STB_TEXTEDIT_K_WORDRIGHT 0x1000D // keyboard input to move cursor right one word #define STB_TEXTEDIT_K_WORDRIGHT 0x20000D // keyboard input to move cursor right one word
#define STB_TEXTEDIT_K_SHIFT 0x20000 #define STB_TEXTEDIT_K_SHIFT 0x400000
#define STB_TEXTEDIT_IMPLEMENTATION #define STB_TEXTEDIT_IMPLEMENTATION
#include "imstb_textedit.h" #include "imstb_textedit.h"
@ -5519,7 +5522,7 @@ bool ImGui::Selectable(const char* label, bool selected, ImGuiSelectableFlags fl
bool hovered, held; bool hovered, held;
bool pressed = ButtonBehavior(bb, id, &hovered, &held, button_flags); bool pressed = ButtonBehavior(bb, id, &hovered, &held, button_flags);
// Update NavId when clicking or when Hovering (this doesn't happen on most widgets), so navigation can be resumed with gamepad/keyboard // Update NavId when clicking or when Hovering (this doesn't happen on most widgets), so navigation can be resumed with gamepad/keyboard
if (pressed || (hovered && (flags & ImGuiSelectableFlags_SetNavIdOnHover))) if (pressed || (hovered && (flags & ImGuiSelectableFlags_SetNavIdOnHover)))
{ {
if (!g.NavDisableMouseHover && g.NavWindow == window && g.NavLayer == window->DC.NavLayerCurrent) if (!g.NavDisableMouseHover && g.NavWindow == window && g.NavLayer == window->DC.NavLayerCurrent)
@ -5639,7 +5642,7 @@ bool ImGui::ListBoxHeader(const char* label, int items_count, int height_in_item
// We include ItemSpacing.y so that a list sized for the exact number of items doesn't make a scrollbar appears. We could also enforce that by passing a flag to BeginChild(). // We include ItemSpacing.y so that a list sized for the exact number of items doesn't make a scrollbar appears. We could also enforce that by passing a flag to BeginChild().
ImVec2 size; ImVec2 size;
size.x = 0.0f; size.x = 0.0f;
size.y = GetTextLineHeightWithSpacing() * height_in_items_f + style.FramePadding.y * 2.0f; size.y = ImFloor(GetTextLineHeightWithSpacing() * height_in_items_f + style.FramePadding.y * 2.0f);
return ListBoxHeader(label, size); return ListBoxHeader(label, size);
} }
@ -6944,7 +6947,7 @@ bool ImGui::TabItemEx(ImGuiTabBar* tab_bar, const char* label, bool* p_open,
ImRect bb(pos, pos + size); ImRect bb(pos, pos + size);
// We don't have CPU clipping primitives to clip the CloseButton (until it becomes a texture), so need to add an extra draw call (temporary in the case of vertical animation) // We don't have CPU clipping primitives to clip the CloseButton (until it becomes a texture), so need to add an extra draw call (temporary in the case of vertical animation)
bool want_clip_rect = (bb.Min.x < tab_bar->BarRect.Min.x) || (bb.Max.x >= tab_bar->BarRect.Max.x); bool want_clip_rect = (bb.Min.x < tab_bar->BarRect.Min.x) || (bb.Max.x > tab_bar->BarRect.Max.x);
if (want_clip_rect) if (want_clip_rect)
PushClipRect(ImVec2(ImMax(bb.Min.x, tab_bar->BarRect.Min.x), bb.Min.y - 1), ImVec2(tab_bar->BarRect.Max.x, bb.Max.y), true); PushClipRect(ImVec2(ImMax(bb.Min.x, tab_bar->BarRect.Min.x), bb.Min.y - 1), ImVec2(tab_bar->BarRect.Max.x, bb.Max.y), true);
@ -7303,7 +7306,7 @@ void ImGui::PushColumnsBackground()
return; return;
window->DrawList->ChannelsSetCurrent(0); window->DrawList->ChannelsSetCurrent(0);
int cmd_size = window->DrawList->CmdBuffer.Size; int cmd_size = window->DrawList->CmdBuffer.Size;
PushClipRect(columns->HostClipRect.Min, columns->HostClipRect.Max, false); PushClipRect(columns->HostClipRect.Min, columns->HostClipRect.Max, false);
IM_UNUSED(cmd_size); IM_UNUSED(cmd_size);
IM_ASSERT(cmd_size == window->DrawList->CmdBuffer.Size); // Being in channel 0 this should not have created an ImDrawCmd IM_ASSERT(cmd_size == window->DrawList->CmdBuffer.Size); // Being in channel 0 this should not have created an ImDrawCmd
} }