diff options
Diffstat (limited to 'imgui/imgui_demo.cpp')
-rw-r--r-- | imgui/imgui_demo.cpp | 338 |
1 files changed, 224 insertions, 114 deletions
diff --git a/imgui/imgui_demo.cpp b/imgui/imgui_demo.cpp index c5cd34aa..d2fa3a3b 100644 --- a/imgui/imgui_demo.cpp +++ b/imgui/imgui_demo.cpp @@ -1,24 +1,24 @@ -// dear imgui, v1.67 +// dear imgui, v1.68 // (demo code) // Message to the person tempted to delete this file when integrating Dear ImGui into their code base: // Do NOT remove this file from your project! Think again! It is the most useful reference code that you and other coders -// will want to refer to and call. Have the ImGui::ShowDemoWindow() function wired in an always-available debug menu of -// your game/app! Removing this file from your project is hindering access to documentation for everyone in your team, +// will want to refer to and call. Have the ImGui::ShowDemoWindow() function wired in an always-available debug menu of +// your game/app! Removing this file from your project is hindering access to documentation for everyone in your team, // likely leading you to poorer usage of the library. // Everything in this file will be stripped out by the linker if you don't call ImGui::ShowDemoWindow(). -// If you want to link core Dear ImGui in your shipped builds but want an easy guarantee that the demo will not be linked, +// If you want to link core Dear ImGui in your shipped builds but want an easy guarantee that the demo will not be linked, // you can setup your imconfig.h with #define IMGUI_DISABLE_DEMO_WINDOWS and those functions will be empty. // In other situation, whenever you have Dear ImGui available you probably want this to be available for reference. // Thank you, // -Your beloved friend, imgui_demo.cpp (that you won't delete) -// Message to beginner C/C++ programmers about the meaning of the 'static' keyword: -// 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 +// Message to beginner C/C++ programmers about the meaning of the 'static' keyword: +// 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 // 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 reentrant -// or used in 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 +// or used in 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. /* @@ -62,7 +62,6 @@ Index of this file: #ifdef _MSC_VER #pragma warning (disable: 4996) // 'This function or variable may be unsafe': strcpy, strdup, sprintf, vsnprintf, sscanf, fopen -#define vsnprintf _vsnprintf #endif #ifdef __clang__ #pragma clang diagnostic ignored "-Wold-style-cast" // warning : use of old-style cast // yes, they are more terse. @@ -70,7 +69,10 @@ Index of this file: #pragma clang diagnostic ignored "-Wint-to-void-pointer-cast" // warning : cast to 'void *' from smaller integer type 'int' #pragma clang diagnostic ignored "-Wformat-security" // warning : warning: format string is not a string literal #pragma clang diagnostic ignored "-Wexit-time-destructors" // warning : declaration requires an exit-time destructor // exit-time destruction order is undefined. if MemFree() leads to users code that has been disabled before exit it might cause problems. ImGui coding style welcomes static/globals. +#pragma clang diagnostic ignored "-Wunused-macros" // warning : warning: macro is not used // we define snprintf/vsnprintf on Windows so they are available, but not always used. +#if __has_warning("-Wzero-as-null-pointer-constant") #pragma clang diagnostic ignored "-Wzero-as-null-pointer-constant" // warning : zero as null pointer constant // some standard header variations use #define NULL 0 +#endif #if __has_warning("-Wdouble-promotion") #pragma clang diagnostic ignored "-Wdouble-promotion" // warning: implicit conversion from 'float' to 'double' when passing argument to function // using printf() is a misery with this as C++ va_arg ellipsis changes float to double. #endif @@ -89,9 +91,11 @@ Index of this file: // Play it nice with Windows users. Notepad in 2017 still doesn't display text data with Unix-style \n. #ifdef _WIN32 -#define IM_NEWLINE "\r\n" +#define IM_NEWLINE "\r\n" +#define snprintf _snprintf +#define vsnprintf _vsnprintf #else -#define IM_NEWLINE "\n" +#define IM_NEWLINE "\n" #endif #define IM_MAX(_A,_B) (((_A) >= (_B)) ? (_A) : (_B)) @@ -336,6 +340,7 @@ void ImGui::ShowDemoWindow(bool* p_open) if (ImGui::TreeNode("Backend Flags")) { + ShowHelpMarker("Those flags are set by the back-ends (imgui_impl_xxx files) to specify their capabilities."); ImGuiBackendFlags backend_flags = io.BackendFlags; // Make a local copy to avoid modifying the back-end flags. ImGui::CheckboxFlags("io.BackendFlags: HasGamepad", (unsigned int *)&backend_flags, ImGuiBackendFlags_HasGamepad); ImGui::CheckboxFlags("io.BackendFlags: HasMouseCursors", (unsigned int *)&backend_flags, ImGuiBackendFlags_HasMouseCursors); @@ -419,7 +424,7 @@ static void ShowDemoWindowWidgets() // Color buttons, demonstrate using PushID() to add unique identifier in the ID stack, and changing style. for (int i = 0; i < 7; i++) { - if (i > 0) + if (i > 0) ImGui::SameLine(); ImGui::PushID(i); ImGui::PushStyleColor(ImGuiCol_Button, (ImVec4)ImColor::HSV(i/7.0f, 0.6f, 0.6f)); @@ -871,23 +876,44 @@ static void ShowDemoWindowWidgets() } if (ImGui::TreeNode("Grid")) { - static bool selected[16] = { true, false, false, false, false, true, false, false, false, false, true, false, false, false, false, true }; - for (int i = 0; i < 16; i++) + static bool selected[4*4] = { true, false, false, false, false, true, false, false, false, false, true, false, false, false, false, true }; + for (int i = 0; i < 4*4; i++) { ImGui::PushID(i); if (ImGui::Selectable("Sailor", &selected[i], 0, ImVec2(50,50))) { - int x = i % 4, y = i / 4; - if (x > 0) selected[i - 1] ^= 1; - if (x < 3) selected[i + 1] ^= 1; - if (y > 0) selected[i - 4] ^= 1; - if (y < 3) selected[i + 4] ^= 1; + // Note: We _unnecessarily_ test for both x/y and i here only to silence some static analyzer. The second part of each test is unnecessary. + int x = i % 4; + int y = i / 4; + if (x > 0) { selected[i - 1] ^= 1; } + if (x < 3 && i < 15) { selected[i + 1] ^= 1; } + if (y > 0 && i > 3) { selected[i - 4] ^= 1; } + if (y < 3 && i < 12) { selected[i + 4] ^= 1; } } if ((i % 4) < 3) ImGui::SameLine(); ImGui::PopID(); } ImGui::TreePop(); } + if (ImGui::TreeNode("Alignment")) + { + ShowHelpMarker("Alignment applies when a selectable is larger than its text content.\nBy default, Selectables uses style.SelectableTextAlign but it can be overriden on a per-item basis using PushStyleVar()."); + static bool selected[3*3] = { true, false, true, false, true, false, true, false, true }; + for (int y = 0; y < 3; y++) + { + for (int x = 0; x < 3; x++) + { + ImVec2 alignment = ImVec2((float)x / 2.0f, (float)y / 2.0f); + char name[32]; + sprintf(name, "(%.1f,%.1f)", alignment.x, alignment.y); + if (x > 0) ImGui::SameLine(); + ImGui::PushStyleVar(ImGuiStyleVar_SelectableTextAlign, alignment); + ImGui::Selectable(name, &selected[3*y+x], ImGuiSelectableFlags_None, ImVec2(80,80)); + ImGui::PopStyleVar(); + } + } + ImGui::TreePop(); + } ImGui::TreePop(); } @@ -912,7 +938,7 @@ static void ShowDemoWindowWidgets() if (ImGui::TreeNode("Multi-line Text Input")) { - // Note: we are using a fixed-sized buffer for simplicity here. See ImGuiInputTextFlags_CallbackResize + // Note: we are using a fixed-sized buffer for simplicity here. See ImGuiInputTextFlags_CallbackResize // and the code in misc/cpp/imgui_stdlib.h for how to setup InputText() for dynamically resizing strings. static bool read_only = false; static char text[1024*16] = @@ -947,7 +973,7 @@ static void ShowDemoWindowWidgets() static float values[90] = { 0 }; static int values_offset = 0; static double refresh_time = 0.0; - if (!animate || refresh_time == 0.0f) + if (!animate || refresh_time == 0.0) refresh_time = ImGui::GetTime(); while (refresh_time < ImGui::GetTime()) // Create dummy data at fixed 60 hz rate for the demo { @@ -1000,7 +1026,7 @@ static void ShowDemoWindowWidgets() if (ImGui::TreeNode("Color/Picker Widgets")) { - static ImVec4 color = ImColor(114, 144, 154, 200); + static ImVec4 color = ImVec4(114.0f/255.0f, 144.0f/255.0f, 154.0f/255.0f, 200.0f/255.0f); static bool alpha_preview = true; static bool alpha_half_preview = false; @@ -1030,16 +1056,18 @@ static void ShowDemoWindowWidgets() ImGui::Text("Color button with Custom Picker Popup:"); - // Generate a dummy palette - static bool saved_palette_inited = false; - static ImVec4 saved_palette[32]; - if (!saved_palette_inited) + // Generate a dummy default palette. The palette will persist and can be edited. + static bool saved_palette_init = true; + static ImVec4 saved_palette[32] = { }; + if (saved_palette_init) + { for (int n = 0; n < IM_ARRAYSIZE(saved_palette); n++) { ImGui::ColorConvertHSVtoRGB(n / 31.0f, 0.8f, 0.8f, saved_palette[n].x, saved_palette[n].y, saved_palette[n].z); saved_palette[n].w = 1.0f; // Alpha } - saved_palette_inited = true; + saved_palette_init = false; + } static ImVec4 backup_color; bool open_popup = ImGui::ColorButton("MyColor##3b", color, misc_flags); @@ -1052,12 +1080,12 @@ static void ShowDemoWindowWidgets() } if (ImGui::BeginPopup("mypicker")) { - // FIXME: Adding a drag and drop example here would be perfect! ImGui::Text("MY CUSTOM COLOR PICKER WITH AN AMAZING PALETTE!"); ImGui::Separator(); ImGui::ColorPicker4("##picker", (float*)&color, misc_flags | ImGuiColorEditFlags_NoSidePreview | ImGuiColorEditFlags_NoSmallPreview); ImGui::SameLine(); - ImGui::BeginGroup(); + + ImGui::BeginGroup(); // Lock X position ImGui::Text("Current"); ImGui::ColorButton("##current", color, ImGuiColorEditFlags_NoPicker | ImGuiColorEditFlags_AlphaPreviewHalf, ImVec2(60,40)); ImGui::Text("Previous"); @@ -1073,6 +1101,8 @@ static void ShowDemoWindowWidgets() if (ImGui::ColorButton("##palette", saved_palette[n], ImGuiColorEditFlags_NoAlpha | ImGuiColorEditFlags_NoPicker | ImGuiColorEditFlags_NoTooltip, ImVec2(20,20))) color = ImVec4(saved_palette[n].x, saved_palette[n].y, saved_palette[n].z, color.w); // Preserve alpha! + // Allow user to drop colors into each palette entry + // (Note that ColorButton is already a drag source by default, unless using ImGuiColorEditFlags_NoDragDrop) if (ImGui::BeginDragDropTarget()) { if (const ImGuiPayload* payload = ImGui::AcceptDragDropPayload(IMGUI_PAYLOAD_TYPE_COLOR_3F)) @@ -1149,15 +1179,15 @@ static void ShowDemoWindowWidgets() if (ImGui::TreeNode("Data Types")) { // The DragScalar/InputScalar/SliderScalar functions allow various data types: signed/unsigned int/long long and float/double - // To avoid polluting the public API with all possible combinations, we use the ImGuiDataType enum to pass the type, - // and passing all arguments by address. + // To avoid polluting the public API with all possible combinations, we use the ImGuiDataType enum to pass the type, + // and passing all arguments by address. // This is the reason the test code below creates local variables to hold "zero" "one" etc. for each types. - // In practice, if you frequently use a given type that is not covered by the normal API entry points, you can wrap it - // yourself inside a 1 line function which can take typed argument as value instead of void*, and then pass their address + // In practice, if you frequently use a given type that is not covered by the normal API entry points, you can wrap it + // yourself inside a 1 line function which can take typed argument as value instead of void*, and then pass their address // to the generic function. For example: - // bool MySliderU64(const char *label, u64* value, u64 min = 0, u64 max = 0, const char* format = "%lld") - // { - // return SliderScalar(label, ImGuiDataType_U64, value, &min, &max, format); + // bool MySliderU64(const char *label, u64* value, u64 min = 0, u64 max = 0, const char* format = "%lld") + // { + // return SliderScalar(label, ImGuiDataType_U64, value, &min, &max, format); // } // Limits (as helper variables that we can take the address of) @@ -1352,7 +1382,7 @@ static void ShowDemoWindowWidgets() static int mode = 0; if (ImGui::RadioButton("Copy", mode == Mode_Copy)) { mode = Mode_Copy; } ImGui::SameLine(); if (ImGui::RadioButton("Move", mode == Mode_Move)) { mode = Mode_Move; } ImGui::SameLine(); - if (ImGui::RadioButton("Swap", mode == Mode_Swap)) { mode = Mode_Swap; } + if (ImGui::RadioButton("Swap", mode == Mode_Swap)) { mode = Mode_Swap; } static const char* names[9] = { "Bobby", "Beatrice", "Betty", "Brianna", "Barry", "Bernard", "Bibi", "Blaine", "Bryn" }; for (int n = 0; n < IM_ARRAYSIZE(names); n++) { @@ -1411,7 +1441,7 @@ static void ShowDemoWindowWidgets() static float col4f[4] = { 1.0f, 0.5, 0.0f, 1.0f }; ImGui::RadioButton("Text", &item_type, 0); ImGui::RadioButton("Button", &item_type, 1); - ImGui::RadioButton("CheckBox", &item_type, 2); + ImGui::RadioButton("Checkbox", &item_type, 2); ImGui::RadioButton("SliderFloat", &item_type, 3); ImGui::RadioButton("ColorEdit4", &item_type, 4); ImGui::RadioButton("ListBox", &item_type, 5); @@ -1419,7 +1449,7 @@ static void ShowDemoWindowWidgets() bool ret = false; if (item_type == 0) { ImGui::Text("ITEM: Text"); } // Testing text items with no identifier/interaction if (item_type == 1) { ret = ImGui::Button("ITEM: Button"); } // Testing button - if (item_type == 2) { ret = ImGui::Checkbox("ITEM: CheckBox", &b); } // Testing checkbox + if (item_type == 2) { ret = ImGui::Checkbox("ITEM: Checkbox", &b); } // Testing checkbox if (item_type == 3) { ret = ImGui::SliderFloat("ITEM: SliderFloat", &col4f[0], 0.0f, 1.0f); } // Testing basic item if (item_type == 4) { ret = ImGui::ColorEdit4("ITEM: ColorEdit4", col4f); } // Testing multi-component items (IsItemXXX flags are reported merged) if (item_type == 5) { const char* items[] = { "Apple", "Banana", "Cherry", "Kiwi" }; static int current = 1; ret = ImGui::ListBox("ITEM: ListBox", ¤t, items, IM_ARRAYSIZE(items), IM_ARRAYSIZE(items)); } @@ -1433,6 +1463,7 @@ static void ShowDemoWindowWidgets() "IsItemHovered(_RectOnly) = %d\n" "IsItemActive() = %d\n" "IsItemEdited() = %d\n" + "IsItemActivated() = %d\n" "IsItemDeactivated() = %d\n" "IsItemDeactivatedEdit() = %d\n" "IsItemVisible() = %d\n" @@ -1448,6 +1479,7 @@ static void ShowDemoWindowWidgets() ImGui::IsItemHovered(ImGuiHoveredFlags_RectOnly), ImGui::IsItemActive(), ImGui::IsItemEdited(), + ImGui::IsItemActivated(), ImGui::IsItemDeactivated(), ImGui::IsItemDeactivatedAfterEdit(), ImGui::IsItemVisible(), @@ -1497,7 +1529,7 @@ static void ShowDemoWindowWidgets() if (embed_all_inside_a_child_window) ImGui::EndChild(); - // Calling IsItemHovered() after begin returns the hovered status of the title bar. + // Calling IsItemHovered() after begin returns the hovered status of the title bar. // This is useful in particular if you want to create a context menu (with BeginPopupContextItem) associated to the title bar of a window. static bool test_window = false; ImGui::Checkbox("Hovered/Active tests after Begin() for title bar testing", &test_window); @@ -1765,6 +1797,7 @@ static void ShowDemoWindowLayout() static ImGuiTabBarFlags tab_bar_flags = ImGuiTabBarFlags_Reorderable; ImGui::CheckboxFlags("ImGuiTabBarFlags_Reorderable", (unsigned int*)&tab_bar_flags, ImGuiTabBarFlags_Reorderable); ImGui::CheckboxFlags("ImGuiTabBarFlags_AutoSelectNewTabs", (unsigned int*)&tab_bar_flags, ImGuiTabBarFlags_AutoSelectNewTabs); + ImGui::CheckboxFlags("ImGuiTabBarFlags_TabListPopupButton", (unsigned int*)&tab_bar_flags, ImGuiTabBarFlags_TabListPopupButton); ImGui::CheckboxFlags("ImGuiTabBarFlags_NoCloseWithMiddleMouseButton", (unsigned int*)&tab_bar_flags, ImGuiTabBarFlags_NoCloseWithMiddleMouseButton); if ((tab_bar_flags & ImGuiTabBarFlags_FittingPolicyMask_) == 0) tab_bar_flags |= ImGuiTabBarFlags_FittingPolicyDefault_; @@ -1975,9 +2008,9 @@ static void ShowDemoWindowLayout() ImGui::EndChild(); ImGui::PopStyleVar(2); float scroll_x_delta = 0.0f; - ImGui::SmallButton("<<"); if (ImGui::IsItemActive()) scroll_x_delta = -ImGui::GetIO().DeltaTime * 1000.0f; ImGui::SameLine(); + ImGui::SmallButton("<<"); if (ImGui::IsItemActive()) { scroll_x_delta = -ImGui::GetIO().DeltaTime * 1000.0f; } ImGui::SameLine(); ImGui::Text("Scroll from code"); ImGui::SameLine(); - ImGui::SmallButton(">>"); if (ImGui::IsItemActive()) scroll_x_delta = +ImGui::GetIO().DeltaTime * 1000.0f; ImGui::SameLine(); + ImGui::SmallButton(">>"); if (ImGui::IsItemActive()) { scroll_x_delta = +ImGui::GetIO().DeltaTime * 1000.0f; } ImGui::SameLine(); ImGui::Text("%.0f/%.0f", scroll_x, scroll_max_x); if (scroll_x_delta != 0.0f) { @@ -2023,7 +2056,7 @@ static void ShowDemoWindowPopups() // if (ImGui::Button("Open")) ImGui::OpenPopup("MyPopup"); if (ImGui::BeginPopup("MyPopup") { [...] EndPopup(); } // With popups we have to go through a library call (here OpenPopup) to manipulate the visibility state. - // This may be a bit confusing at first but it should quickly make sense. Follow on the examples below. + // This may be a bit confusing at first but it should quickly make sense. Follow on the examples below. if (ImGui::TreeNode("Popups")) { @@ -2119,7 +2152,7 @@ static void ShowDemoWindowPopups() ImGui::Text("(You can also right-click me to the same popup as above.)"); ImGui::OpenPopupOnItemClick("item context menu", 1); - // When used after an item that has an ID (here the Button), we can skip providing an ID to BeginPopupContextItem(). + // When used after an item that has an ID (here the Button), we can skip providing an ID to BeginPopupContextItem(). // BeginPopupContextItem() will use the last item ID as the popup ID. // In addition here, we want to include your editable label inside the button label. We use the ### operator to override the ID (read FAQ about ID for details) static char name[32] = "Label1"; @@ -2167,13 +2200,24 @@ static void ShowDemoWindowPopups() if (ImGui::Button("Stacked modals..")) ImGui::OpenPopup("Stacked 1"); - if (ImGui::BeginPopupModal("Stacked 1")) + if (ImGui::BeginPopupModal("Stacked 1", NULL, ImGuiWindowFlags_MenuBar)) { + if (ImGui::BeginMenuBar()) + { + if (ImGui::BeginMenu("File")) + { + if (ImGui::MenuItem("Dummy menu item")) {} + ImGui::EndMenu(); + } + ImGui::EndMenuBar(); + } ImGui::Text("Hello from Stacked The First\nUsing style.Colors[ImGuiCol_ModalWindowDimBg] behind it."); + + // Testing behavior of widgets stacking their own regular popups over the modal. static int item = 1; - ImGui::Combo("Combo", &item, "aaaa\0bbbb\0cccc\0dddd\0eeee\0\0"); static float color[4] = { 0.4f,0.7f,0.0f,0.5f }; - ImGui::ColorEdit4("color", color); // This is to test behavior of stacked regular popups over a modal + ImGui::Combo("Combo", &item, "aaaa\0bbbb\0cccc\0dddd\0eeee\0\0"); + ImGui::ColorEdit4("color", color); if (ImGui::Button("Add another modal..")) ImGui::OpenPopup("Stacked 2"); @@ -2505,9 +2549,9 @@ static void ShowDemoWindowMisc() // Use >= 0 parameter to SetKeyboardFocusHere() to focus an upcoming item static float f3[3] = { 0.0f, 0.0f, 0.0f }; int focus_ahead = -1; - if (ImGui::Button("Focus on X")) focus_ahead = 0; ImGui::SameLine(); - if (ImGui::Button("Focus on Y")) focus_ahead = 1; ImGui::SameLine(); - if (ImGui::Button("Focus on Z")) focus_ahead = 2; + if (ImGui::Button("Focus on X")) { focus_ahead = 0; } ImGui::SameLine(); + if (ImGui::Button("Focus on Y")) { focus_ahead = 1; } ImGui::SameLine(); + if (ImGui::Button("Focus on Z")) { focus_ahead = 2; } if (focus_ahead != -1) ImGui::SetKeyboardFocusHere(focus_ahead); ImGui::SliderFloat3("Float3", &f3[0], 0.0f, 1.0f); @@ -2667,6 +2711,7 @@ void ImGui::ShowAboutWindow(bool* p_open) ImGui::Separator(); ImGui::Text("io.Fonts: %d fonts, Flags: 0x%08X, TexSize: %d,%d", io.Fonts->Fonts.Size, io.Fonts->Flags, io.Fonts->TexWidth, io.Fonts->TexHeight); ImGui::Text("io.DisplaySize: %.2f,%.2f", io.DisplaySize.x, io.DisplaySize.y); + ImGui::Text("io.DisplayFramebufferScale: %.2f,%.2f", io.DisplayFramebufferScale.x, io.DisplayFramebufferScale.y); ImGui::Separator(); ImGui::Text("style.WindowPadding: %.2f,%.2f", style.WindowPadding.x, style.WindowPadding.y); ImGui::Text("style.WindowBorderSize: %.2f", style.WindowBorderSize); @@ -2714,8 +2759,13 @@ void ImGui::ShowFontSelector(const char* label) if (ImGui::BeginCombo(label, font_current->GetDebugName())) { for (int n = 0; n < io.Fonts->Fonts.Size; n++) - if (ImGui::Selectable(io.Fonts->Fonts[n]->GetDebugName(), io.Fonts->Fonts[n] == font_current)) - io.FontDefault = io.Fonts->Fonts[n]; + { + ImFont* font = io.Fonts->Fonts[n]; + ImGui::PushID((void*)font); + if (ImGui::Selectable(font->GetDebugName(), font == font_current)) + io.FontDefault = font; + ImGui::PopID(); + } ImGui::EndCombo(); } ImGui::SameLine(); @@ -2772,7 +2822,6 @@ void ImGui::ShowStyleEditor(ImGuiStyle* ref) { ImGui::Text("Main"); ImGui::SliderFloat2("WindowPadding", (float*)&style.WindowPadding, 0.0f, 20.0f, "%.0f"); - ImGui::SliderFloat("PopupRounding", &style.PopupRounding, 0.0f, 16.0f, "%.0f"); ImGui::SliderFloat2("FramePadding", (float*)&style.FramePadding, 0.0f, 20.0f, "%.0f"); ImGui::SliderFloat2("ItemSpacing", (float*)&style.ItemSpacing, 0.0f, 20.0f, "%.0f"); ImGui::SliderFloat2("ItemInnerSpacing", (float*)&style.ItemInnerSpacing, 0.0f, 20.0f, "%.0f"); @@ -2787,15 +2836,17 @@ void ImGui::ShowStyleEditor(ImGuiStyle* ref) ImGui::SliderFloat("FrameBorderSize", &style.FrameBorderSize, 0.0f, 1.0f, "%.0f"); ImGui::SliderFloat("TabBorderSize", &style.TabBorderSize, 0.0f, 1.0f, "%.0f"); ImGui::Text("Rounding"); - ImGui::SliderFloat("WindowRounding", &style.WindowRounding, 0.0f, 14.0f, "%.0f"); - ImGui::SliderFloat("ChildRounding", &style.ChildRounding, 0.0f, 16.0f, "%.0f"); + ImGui::SliderFloat("WindowRounding", &style.WindowRounding, 0.0f, 12.0f, "%.0f"); + ImGui::SliderFloat("ChildRounding", &style.ChildRounding, 0.0f, 12.0f, "%.0f"); ImGui::SliderFloat("FrameRounding", &style.FrameRounding, 0.0f, 12.0f, "%.0f"); + ImGui::SliderFloat("PopupRounding", &style.PopupRounding, 0.0f, 12.0f, "%.0f"); ImGui::SliderFloat("ScrollbarRounding", &style.ScrollbarRounding, 0.0f, 12.0f, "%.0f"); ImGui::SliderFloat("GrabRounding", &style.GrabRounding, 0.0f, 12.0f, "%.0f"); ImGui::SliderFloat("TabRounding", &style.TabRounding, 0.0f, 12.0f, "%.0f"); ImGui::Text("Alignment"); ImGui::SliderFloat2("WindowTitleAlign", (float*)&style.WindowTitleAlign, 0.0f, 1.0f, "%.2f"); ImGui::SliderFloat2("ButtonTextAlign", (float*)&style.ButtonTextAlign, 0.0f, 1.0f, "%.2f"); ImGui::SameLine(); ShowHelpMarker("Alignment applies when a button is larger than its text content."); + ImGui::SliderFloat2("SelectableTextAlign", (float*)&style.SelectableTextAlign, 0.0f, 1.0f, "%.2f"); ImGui::SameLine(); ShowHelpMarker("Alignment applies when a selectable is larger than its text content."); ImGui::Text("Safe Area Padding"); ImGui::SameLine(); ShowHelpMarker("Adjust if you cannot see the edges of your screen (e.g. on a TV where scaling has not been configured)."); ImGui::SliderFloat2("DisplaySafeAreaPadding", (float*)&style.DisplaySafeAreaPadding, 0.0f, 30.0f, "%.0f"); ImGui::EndTabItem(); @@ -2861,7 +2912,8 @@ void ImGui::ShowStyleEditor(ImGuiStyle* ref) if (ImGui::BeginTabItem("Fonts")) { - ImFontAtlas* atlas = ImGui::GetIO().Fonts; + ImGuiIO& io = ImGui::GetIO(); + ImFontAtlas* atlas = io.Fonts; ShowHelpMarker("Read FAQ and misc/fonts/README.txt for details on font loading."); ImGui::PushItemWidth(120); for (int i = 0; i < atlas->Fonts.Size; i++) @@ -2869,7 +2921,7 @@ void ImGui::ShowStyleEditor(ImGuiStyle* ref) ImFont* font = atlas->Fonts[i]; ImGui::PushID(font); bool font_details_opened = ImGui::TreeNode(font, "Font %d: \"%s\"\n%.2f px, %d glyphs, %d file(s)", i, font->ConfigData ? font->ConfigData[0].Name : "", font->FontSize, font->Glyphs.Size, font->ConfigDataCount); - ImGui::SameLine(); if (ImGui::SmallButton("Set as default")) ImGui::GetIO().FontDefault = font; + ImGui::SameLine(); if (ImGui::SmallButton("Set as default")) { io.FontDefault = font; } if (font_details_opened) { ImGui::PushFont(font); @@ -2880,9 +2932,10 @@ void ImGui::ShowStyleEditor(ImGuiStyle* ref) 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("Fallback character: '%c' (%d)", font->FallbackChar, font->FallbackChar); - ImGui::Text("Texture surface: %d pixels (approx) ~ %dx%d", font->MetricsTotalSurface, (int)sqrtf((float)font->MetricsTotalSurface), (int)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); for (int config_i = 0; config_i < font->ConfigDataCount; config_i++) - if (ImFontConfig* cfg = &font->ConfigData[config_i]) + if (const ImFontConfig* cfg = &font->ConfigData[config_i]) ImGui::BulletText("Input %d: \'%s\', Oversample: (%d,%d), PixelSnapH: %d", config_i, cfg->Name, cfg->OversampleH, cfg->OversampleV, cfg->PixelSnapH); if (ImGui::TreeNode("Glyphs", "Glyphs (%d)", font->Glyphs.Size)) { @@ -2934,9 +2987,9 @@ void ImGui::ShowStyleEditor(ImGuiStyle* ref) } static float window_scale = 1.0f; - if (ImGui::DragFloat("this window scale", &window_scale, 0.005f, 0.3f, 2.0f, "%.1f")) // scale only this window + if (ImGui::DragFloat("this window scale", &window_scale, 0.005f, 0.3f, 2.0f, "%.2f")) // scale only this window ImGui::SetWindowFontScale(window_scale); - ImGui::DragFloat("global scale", &ImGui::GetIO().FontGlobalScale, 0.005f, 0.3f, 2.0f, "%.1f"); // scale everything + ImGui::DragFloat("global scale", &io.FontGlobalScale, 0.005f, 0.3f, 2.0f, "%.2f"); // scale everything ImGui::PopItemWidth(); ImGui::EndTabItem(); @@ -3064,10 +3117,12 @@ struct ExampleAppConsole { char InputBuf[256]; ImVector<char*> Items; - bool ScrollToBottom; + ImVector<const char*> Commands; ImVector<char*> History; int HistoryPos; // -1: new line, 0..History.Size-1 browsing history. - ImVector<const char*> Commands; + ImGuiTextFilter Filter; + bool AutoScroll; + bool ScrollToBottom; ExampleAppConsole() { @@ -3078,6 +3133,8 @@ struct ExampleAppConsole Commands.push_back("HISTORY"); 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. + AutoScroll = true; + ScrollToBottom = true; AddLog("Welcome to Dear ImGui!"); } ~ExampleAppConsole() @@ -3090,7 +3147,7 @@ struct ExampleAppConsole // Portable helpers static int Stricmp(const char* str1, const char* str2) { int d; while ((d = toupper(*str2) - toupper(*str1)) == 0 && *str1) { str1++; str2++; } return d; } static int Strnicmp(const char* str1, const char* str2, int n) { int d = 0; while (n > 0 && (d = toupper(*str2) - toupper(*str1)) == 0 && *str1) { str1++; str2++; n--; } return d; } - static char* Strdup(const char *str) { size_t len = strlen(str) + 1; void* buff = malloc(len); return (char*)memcpy(buff, (const void*)str, len); } + static char* Strdup(const char *str) { size_t len = strlen(str) + 1; void* buf = malloc(len); IM_ASSERT(buf); return (char*)memcpy(buf, (const void*)str, len); } static void Strtrim(char* str) { char* str_end = str + strlen(str); while (str_end > str && str_end[-1] == ' ') str_end--; *str_end = 0; } void ClearLog() @@ -3111,7 +3168,8 @@ struct ExampleAppConsole buf[IM_ARRAYSIZE(buf)-1] = 0; va_end(args); Items.push_back(Strdup(buf)); - ScrollToBottom = true; + if (AutoScroll) + ScrollToBottom = true; } void Draw(const char* title, bool* p_open) @@ -3137,7 +3195,7 @@ struct ExampleAppConsole // TODO: display items starting from the bottom - 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("Clear")) { ClearLog(); } ImGui::SameLine(); bool copy_to_clipboard = ImGui::SmallButton("Copy"); ImGui::SameLine(); @@ -3146,10 +3204,20 @@ struct ExampleAppConsole ImGui::Separator(); - ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0,0)); - static ImGuiTextFilter filter; - filter.Draw("Filter (\"incl,-excl\") (\"error\")", 180); - ImGui::PopStyleVar(); + // Options menu + if (ImGui::BeginPopup("Options")) + { + if (ImGui::Checkbox("Auto-scroll", &AutoScroll)) + if (AutoScroll) + ScrollToBottom = true; + ImGui::EndPopup(); + } + + // Options, Filter + if (ImGui::Button("Options")) + ImGui::OpenPopup("Options"); + ImGui::SameLine(); + Filter.Draw("Filter (\"incl,-excl\") (\"error\")", 180); ImGui::Separator(); const float footer_height_to_reserve = ImGui::GetStyle().ItemSpacing.y + ImGui::GetFrameHeightWithSpacing(); // 1 separator, 1 input text @@ -3174,18 +3242,19 @@ struct ExampleAppConsole ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(4,1)); // Tighten spacing if (copy_to_clipboard) ImGui::LogToClipboard(); - ImVec4 col_default_text = ImGui::GetStyleColorVec4(ImGuiCol_Text); for (int i = 0; i < Items.Size; i++) { const char* item = Items[i]; - if (!filter.PassFilter(item)) + if (!Filter.PassFilter(item)) continue; - ImVec4 col = col_default_text; - if (strstr(item, "[error]")) col = ImColor(1.0f,0.4f,0.4f,1.0f); - else if (strncmp(item, "# ", 2) == 0) col = ImColor(1.0f,0.78f,0.58f,1.0f); - ImGui::PushStyleColor(ImGuiCol_Text, col); + + // Normally you would store more information in your item (e.g. make Items[] an array of structure, store color/type etc.) + bool pop_color = false; + if (strstr(item, "[error]")) { ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(1.0f, 0.4f, 0.4f, 1.0f)); pop_color = true; } + else if (strncmp(item, "# ", 2) == 0) { ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(1.0f, 0.8f, 0.6f, 1.0f)); pop_color = true; } ImGui::TextUnformatted(item); - ImGui::PopStyleColor(); + if (pop_color) + ImGui::PopStyleColor(); } if (copy_to_clipboard) ImGui::LogFinish(); @@ -3252,6 +3321,9 @@ struct ExampleAppConsole { AddLog("Unknown command: '%s'\n", command_line); } + + // On commad input, we scroll to bottom even if AutoScroll==false + ScrollToBottom = true; } static int TextEditCallbackStub(ImGuiInputTextCallbackData* data) // In C++11 you are better off using lambdas for this sort of forwarding callbacks @@ -3380,12 +3452,20 @@ struct ExampleAppLog ImGuiTextBuffer Buf; ImGuiTextFilter Filter; 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 ScrollToBottom; - void Clear() - { - Buf.clear(); - LineOffsets.clear(); + ExampleAppLog() + { + AutoScroll = true; + ScrollToBottom = false; + Clear(); + } + + void Clear() + { + Buf.clear(); + LineOffsets.clear(); LineOffsets.push_back(0); } @@ -3399,7 +3479,8 @@ struct ExampleAppLog for (int new_size = Buf.size(); old_size < new_size; old_size++) if (Buf[old_size] == '\n') LineOffsets.push_back(old_size + 1); - ScrollToBottom = true; + if (AutoScroll) + ScrollToBottom = true; } void Draw(const char* title, bool* p_open = NULL) @@ -3409,13 +3490,31 @@ struct ExampleAppLog ImGui::End(); return; } - if (ImGui::Button("Clear")) Clear(); + + // Options menu + if (ImGui::BeginPopup("Options")) + { + if (ImGui::Checkbox("Auto-scroll", &AutoScroll)) + if (AutoScroll) + ScrollToBottom = true; + ImGui::EndPopup(); + } + + // Main window + if (ImGui::Button("Options")) + ImGui::OpenPopup("Options"); + ImGui::SameLine(); + bool clear = ImGui::Button("Clear"); ImGui::SameLine(); bool copy = ImGui::Button("Copy"); ImGui::SameLine(); Filter.Draw("Filter", -100.0f); + ImGui::Separator(); ImGui::BeginChild("scrolling", ImVec2(0,0), false, ImGuiWindowFlags_HorizontalScrollbar); + + if (clear) + Clear(); if (copy) ImGui::LogToClipboard(); @@ -3424,6 +3523,10 @@ struct ExampleAppLog const char* buf_end = Buf.end(); if (Filter.IsActive()) { + // In this example we don't use the clipper when Filter is enabled. + // This is because we don't have a random access on the result on our filter. + // A real application processing logs with ten of thousands of entries may want to store the result of search/filter. + // especially if the filtering function is not trivial (e.g. reg-exp). for (int line_no = 0; line_no < LineOffsets.Size; line_no++) { const char* line_start = buf + LineOffsets[line_no]; @@ -3435,11 +3538,11 @@ struct ExampleAppLog else { // The simplest and easy way to display the entire buffer: - // ImGui::TextUnformatted(buf_begin, buf_end); + // ImGui::TextUnformatted(buf_begin, buf_end); // And it'll just work. TextUnformatted() has specialization for large blob of text and will fast-forward to skip non-visible lines. // Here we instead demonstrate using the clipper to only process lines that are within the visible area. // If you have tens of thousands of items and their processing cost is non-negligible, coarse clipping them on your side is recommended. - // Using ImGuiListClipper requires A) random access into your data, and B) items all being the same height, + // Using ImGuiListClipper requires A) random access into your data, and B) items all being the same height, // both of which we can handle since we an array pointing to the beginning of each line of text. // When using the filter (in the block of code above) we don't have random access into the data to display anymore, which is why we don't use the clipper. // Storing or skimming through the search result would make it possible (and would be recommended if you want to search through tens of thousands of entries) @@ -3471,18 +3574,19 @@ static void ShowExampleAppLog(bool* p_open) { static ExampleAppLog log; - // For the demo: add a debug button before the normal log window contents + // For the demo: add a debug button _BEFORE_ the normal log window contents // We take advantage of the fact that multiple calls to Begin()/End() are appending to the same window. + // Most of the contents of the window will be added by the log.Draw() call. ImGui::SetNextWindowSize(ImVec2(500, 400), ImGuiCond_FirstUseEver); ImGui::Begin("Example: Log", p_open); - if (ImGui::SmallButton("Add 5 entries")) + if (ImGui::SmallButton("[Debug] Add 5 entries")) { static int counter = 0; for (int n = 0; n < 5; n++) { const char* categories[3] = { "info", "warn", "error" }; const char* words[] = { "Bumfuzzled", "Cattywampus", "Snickersnee", "Abibliophobia", "Absquatulate", "Nincompoop", "Pauciloquent" }; - log.AddLog("[%05d] [%s] Hello, current time is %.1f, here's a word: '%s'\n", + log.AddLog("[%05d] [%s] Hello, current time is %.1f, here's a word: '%s'\n", ImGui::GetFrameCount(), categories[counter % IM_ARRAYSIZE(categories)], ImGui::GetTime(), words[counter % IM_ARRAYSIZE(words)]); counter++; } @@ -3726,8 +3830,8 @@ static void ShowExampleAppConstrainedResize(bool* p_open) if (type == 2) ImGui::SetNextWindowSizeConstraints(ImVec2(100, 100), ImVec2(FLT_MAX, FLT_MAX)); // Width > 100, Height > 100 if (type == 3) ImGui::SetNextWindowSizeConstraints(ImVec2(400, -1), ImVec2(500, -1)); // Width 400-500 if (type == 4) ImGui::SetNextWindowSizeConstraints(ImVec2(-1, 400), ImVec2(-1, 500)); // Height 400-500 - if (type == 5) ImGui::SetNextWindowSizeConstraints(ImVec2(0, 0), ImVec2(FLT_MAX, FLT_MAX), CustomConstraints::Square); // Always Square - if (type == 6) ImGui::SetNextWindowSizeConstraints(ImVec2(0, 0), ImVec2(FLT_MAX, FLT_MAX), CustomConstraints::Step, (void*)100);// Fixed Step + if (type == 5) ImGui::SetNextWindowSizeConstraints(ImVec2(0, 0), ImVec2(FLT_MAX, FLT_MAX), CustomConstraints::Square); // Always Square + if (type == 6) ImGui::SetNextWindowSizeConstraints(ImVec2(0, 0), ImVec2(FLT_MAX, FLT_MAX), CustomConstraints::Step, (void*)(intptr_t)100); // Fixed Step ImGuiWindowFlags flags = auto_resize ? ImGuiWindowFlags_AlwaysAutoResize : 0; if (ImGui::Begin("Example: Constrained Resize", p_open, flags)) @@ -3765,17 +3869,20 @@ static void ShowExampleAppSimpleOverlay(bool* p_open) { const float DISTANCE = 10.0f; static int corner = 0; - ImVec2 window_pos = ImVec2((corner & 1) ? ImGui::GetIO().DisplaySize.x - DISTANCE : DISTANCE, (corner & 2) ? ImGui::GetIO().DisplaySize.y - DISTANCE : DISTANCE); - ImVec2 window_pos_pivot = ImVec2((corner & 1) ? 1.0f : 0.0f, (corner & 2) ? 1.0f : 0.0f); + ImGuiIO& io = ImGui::GetIO(); if (corner != -1) + { + ImVec2 window_pos = ImVec2((corner & 1) ? io.DisplaySize.x - DISTANCE : DISTANCE, (corner & 2) ? io.DisplaySize.y - DISTANCE : DISTANCE); + ImVec2 window_pos_pivot = ImVec2((corner & 1) ? 1.0f : 0.0f, (corner & 2) ? 1.0f : 0.0f); ImGui::SetNextWindowPos(window_pos, ImGuiCond_Always, window_pos_pivot); + } ImGui::SetNextWindowBgAlpha(0.3f); // Transparent background if (ImGui::Begin("Example: Simple overlay", p_open, (corner != -1 ? ImGuiWindowFlags_NoMove : 0) | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_NoFocusOnAppearing | ImGuiWindowFlags_NoNav)) { ImGui::Text("Simple overlay\n" "in the corner of the screen.\n" "(right-click to change position)"); ImGui::Separator(); if (ImGui::IsMousePosValid()) - ImGui::Text("Mouse Position: (%.1f,%.1f)", ImGui::GetIO().MousePos.x, ImGui::GetIO().MousePos.y); + ImGui::Text("Mouse Position: (%.1f,%.1f)", io.MousePos.x, io.MousePos.y); else ImGui::Text("Mouse Position: <invalid>"); if (ImGui::BeginPopupContextWindow()) @@ -3850,27 +3957,30 @@ static void ShowExampleAppCustomRendering(bool* p_open) static ImVec4 col = ImVec4(1.0f, 1.0f, 0.4f, 1.0f); ImGui::DragFloat("Size", &sz, 0.2f, 2.0f, 72.0f, "%.0f"); ImGui::DragFloat("Thickness", &thickness, 0.05f, 1.0f, 8.0f, "%.02f"); - ImGui::ColorEdit3("Color", &col.x); + ImGui::ColorEdit4("Color", &col.x); { const ImVec2 p = ImGui::GetCursorScreenPos(); const ImU32 col32 = ImColor(col); float x = p.x + 4.0f, y = p.y + 4.0f, spacing = 8.0f; for (int n = 0; n < 2; n++) { - float curr_thickness = (n == 0) ? 1.0f : thickness; - draw_list->AddCircle(ImVec2(x+sz*0.5f, y+sz*0.5f), sz*0.5f, col32, 20, curr_thickness); x += sz+spacing; - draw_list->AddRect(ImVec2(x, y), ImVec2(x+sz, y+sz), col32, 0.0f, ImDrawCornerFlags_All, curr_thickness); x += sz+spacing; - draw_list->AddRect(ImVec2(x, y), ImVec2(x+sz, y+sz), col32, 10.0f, ImDrawCornerFlags_All, curr_thickness); x += sz+spacing; - draw_list->AddRect(ImVec2(x, y), ImVec2(x+sz, y+sz), col32, 10.0f, ImDrawCornerFlags_TopLeft|ImDrawCornerFlags_BotRight, curr_thickness); x += sz+spacing; - draw_list->AddTriangle(ImVec2(x+sz*0.5f, y), ImVec2(x+sz,y+sz-0.5f), ImVec2(x,y+sz-0.5f), col32, curr_thickness); x += sz+spacing; - draw_list->AddLine(ImVec2(x, y), ImVec2(x+sz, y ), col32, curr_thickness); x += sz+spacing; // Horizontal line (note: drawing a filled rectangle will be faster!) - draw_list->AddLine(ImVec2(x, y), ImVec2(x, y+sz), col32, curr_thickness); x += spacing; // Vertical line (note: drawing a filled rectangle will be faster!) - draw_list->AddLine(ImVec2(x, y), ImVec2(x+sz, y+sz), col32, curr_thickness); x += sz+spacing; // Diagonal line - draw_list->AddBezierCurve(ImVec2(x, y), ImVec2(x+sz*1.3f,y+sz*0.3f), ImVec2(x+sz-sz*1.3f,y+sz-sz*0.3f), ImVec2(x+sz, y+sz), col32, curr_thickness); + // First line uses a thickness of 1.0, second line uses the configurable thickness + float th = (n == 0) ? 1.0f : thickness; + draw_list->AddCircle(ImVec2(x+sz*0.5f, y+sz*0.5f), sz*0.5f, col32, 6, th); x += sz+spacing; // Hexagon + draw_list->AddCircle(ImVec2(x+sz*0.5f, y+sz*0.5f), sz*0.5f, col32, 20, th); x += sz+spacing; // Circle + draw_list->AddRect(ImVec2(x, y), ImVec2(x+sz, y+sz), col32, 0.0f, ImDrawCornerFlags_All, th); x += sz+spacing; + draw_list->AddRect(ImVec2(x, y), ImVec2(x+sz, y+sz), col32, 10.0f, ImDrawCornerFlags_All, th); x += sz+spacing; + draw_list->AddRect(ImVec2(x, y), ImVec2(x+sz, y+sz), col32, 10.0f, ImDrawCornerFlags_TopLeft|ImDrawCornerFlags_BotRight, th); x += sz+spacing; + draw_list->AddTriangle(ImVec2(x+sz*0.5f, y), ImVec2(x+sz,y+sz-0.5f), ImVec2(x,y+sz-0.5f), col32, th); x += sz+spacing; + draw_list->AddLine(ImVec2(x, y), ImVec2(x+sz, y ), col32, th); x += sz+spacing; // Horizontal line (note: drawing a filled rectangle will be faster!) + draw_list->AddLine(ImVec2(x, y), ImVec2(x, y+sz), col32, th); x += spacing; // Vertical line (note: drawing a filled rectangle will be faster!) + draw_list->AddLine(ImVec2(x, y), ImVec2(x+sz, y+sz), col32, th); x += sz+spacing; // Diagonal line + draw_list->AddBezierCurve(ImVec2(x, y), ImVec2(x+sz*1.3f,y+sz*0.3f), ImVec2(x+sz-sz*1.3f,y+sz-sz*0.3f), ImVec2(x+sz, y+sz), col32, th); x = p.x + 4; y += sz+spacing; } - draw_list->AddCircleFilled(ImVec2(x+sz*0.5f, y+sz*0.5f), sz*0.5f, col32, 32); x += sz+spacing; + draw_list->AddCircleFilled(ImVec2(x+sz*0.5f, y+sz*0.5f), sz*0.5f, col32, 6); x += sz+spacing; // Hexagon + draw_list->AddCircleFilled(ImVec2(x+sz*0.5f, y+sz*0.5f), sz*0.5f, col32, 32); x += sz+spacing; // Circle draw_list->AddRectFilled(ImVec2(x, y), ImVec2(x+sz, y+sz), col32); x += sz+spacing; draw_list->AddRectFilled(ImVec2(x, y), ImVec2(x+sz, y+sz), col32, 10.0f); x += sz+spacing; draw_list->AddRectFilled(ImVec2(x, y), ImVec2(x+sz, y+sz), col32, 10.0f, ImDrawCornerFlags_TopLeft|ImDrawCornerFlags_BotRight); x += sz+spacing; @@ -3945,16 +4055,16 @@ struct MyDocument bool Open; // Set when the document is open (in this demo, we keep an array of all available documents to simplify the demo) bool OpenPrev; // Copy of Open from last update. bool Dirty; // Set when the document has been modified - bool WantClose; // Set when the document + bool WantClose; // Set when the document ImVec4 Color; // An arbitrary variable associated to the document MyDocument(const char* name, bool open = true, const ImVec4& color = ImVec4(1.0f,1.0f,1.0f,1.0f)) - { - Name = name; - Open = OpenPrev = open; - Dirty = false; - WantClose = false; - Color = color; + { + Name = name; + Open = OpenPrev = open; + Dirty = false; + WantClose = false; + Color = color; } void DoOpen() { Open = true; } void DoQueueClose() { WantClose = true; } @@ -4011,8 +4121,8 @@ struct ExampleAppDocuments // [Optional] Notify the system of Tabs/Windows closure that happened outside the regular tab interface. // If a tab has been closed programmatically (aka closed from another source such as the Checkbox() in the demo, as opposed -// to clicking on the regular tab closing button) and stops being submitted, it will take a frame for the tab bar to notice its absence. -// During this frame there will be a gap in the tab bar, and if the tab that has disappeared was the selected one, the tab bar +// to clicking on the regular tab closing button) and stops being submitted, it will take a frame for the tab bar to notice its absence. +// During this frame there will be a gap in the tab bar, and if the tab that has disappeared was the selected one, the tab bar // will report no selected tab during the frame. This will effectively give the impression of a flicker for one frame. // We call SetTabItemClosed() to manually notify the Tab Bar or Docking system of removed tabs to avoid this glitch. // Note that this completely optional, and only affect tab bars with the ImGuiTabBarFlags_Reorderable flag. |