diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 00000000..39320baa --- /dev/null +++ b/.editorconfig @@ -0,0 +1,17 @@ +# editorconfig.org + +# top-most EditorConfig file +root = true + +# Default settings: +# Use 4 spaces as indentation +[*] +indent_style = space +indent_size = 4 +insert_final_newline = true +trim_trailing_whitespace = true + +# Makefile +[Makefile] +indent_style = tab +indent_size = 4 diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 6af7b22a..babf0e8d 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -63,7 +63,6 @@ Breaking Changes: - IO: Moved IME support functions from io.ImeSetInputScreenPosFn, io.ImeWindowHandle to the PlatformIO api. - IO: Removed io.DisplayVisibleMin, io.DisplayVisibleMax settings (they were marked obsoleted, used to clip within the (0,0)..(DisplaySize) range). - Other changes: (FIXME: This need a fuller explanation!) @@ -88,13 +87,18 @@ Other changes: ----------------------------------------------------------------------- - VERSION 1.68 + VERSION 1.68 (In progress) ----------------------------------------------------------------------- Other Changes: -- Examples: Win32: Using GetForegroundWindow() instead of GetActiveWindow() to be compatible with windows created - in a different thread. (#1951, #2087, #2156, #2232) [many people] +- Added .editorconfig file for text editors to standardize using spaces. (#2038) [@kudaba] +- ImDrawList: Fixed AddCircle(), AddCircleFilled() angle step being off, which was visible when drawing a "circle" + with a small number of segments (e.g. an hexagon). (#2287) [@baktery] +- Fonts: imgui_freetype: Added support for imgui allocators + custom FreeType only SetAllocatorFunctions. (#2285) [@Vuhdo] +- Examples: Win32: Using GetForegroundWindow()+IsChild() instead of GetActiveWindow() to be compatible with windows created + in a different thread or parent. (#1951, #2087, #2156, #2232) [many people] - Examples: Win32: Added support for XInput games (if ImGuiConfigFlags_NavEnableGamepad is enabled). +- Examples: DirectX9: Explicitly disable fog (D3DRS_FOGENABLE) before drawing in case user state has it set. (#2288, #2230) ----------------------------------------------------------------------- diff --git a/docs/TODO.txt b/docs/TODO.txt index ebd19f5a..e311b169 100644 --- a/docs/TODO.txt +++ b/docs/TODO.txt @@ -38,7 +38,7 @@ It's mostly a bunch of personal notes, probably incomplete. Feel free to query i - drawlist: maintaining bounding box per command would allow to merge draw command when clipping isn't relied on (typical non-scrolling window or non-overflowing column would merge with previous command). - drawlist: primitives/helpers to manipulate vertices post submission, so e.g. a quad/rect can be resized to fit later submitted content, _without_ using the ChannelSplit api - drawlist: make it easier to toggle AA per primitive, so we can use e.g. non-AA fill + AA borders more naturally - - drawlist: non-AA strokes have gaps between points (#593, #288), especially RenderCheckmark(). + - drawlist: non-AA strokes have gaps between points (#593, #288), glitch especially on RenderCheckmark() and ColorPicker4(). - drawlist: would be good to be able to deep copy of ImDrawData (we have a deep copy of ImDrawList now). - drawlist: rendering: provide a way for imgui to output to a single/global vertex buffer, re-order indices only at the end of the frame (ref: https://gist.github.com/floooh/10388a0afbe08fce9e617d8aefa7d302) - drawlist: callback: add an extra void* in ImDrawCallback to allow passing render-local data to the callback (would break API). diff --git a/examples/example_win32_directx12/example_win32_directx12.vcxproj b/examples/example_win32_directx12/example_win32_directx12.vcxproj index 38c83351..dabd6d84 100644 --- a/examples/example_win32_directx12/example_win32_directx12.vcxproj +++ b/examples/example_win32_directx12/example_win32_directx12.vcxproj @@ -21,7 +21,7 @@ {b4cf9797-519d-4afe-a8f4-5141a6b521d3} example_win32_directx12 - 10.0.16299.0 + 10.0.14393.0 diff --git a/examples/imgui_impl_dx9.cpp b/examples/imgui_impl_dx9.cpp index cb026763..e1f582cc 100644 --- a/examples/imgui_impl_dx9.cpp +++ b/examples/imgui_impl_dx9.cpp @@ -10,6 +10,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) +// 2019-01-16: Misc: Disabled fog before drawing UI's. Fixes issue #2288. // 2018-11-30: Misc: Setting up io.BackendRendererName so it can be displayed in the About Window. // 2018-06-08: Misc: Extracted imgui_impl_dx9.cpp/.h away from the old combined DX9+Win32 example. // 2018-06-08: DirectX9: Use draw_data->DisplayPos and draw_data->DisplaySize to setup projection matrix and clipping rectangle. @@ -131,6 +132,7 @@ void ImGui_ImplDX9_RenderDrawData(ImDrawData* draw_data) g_pd3dDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA); g_pd3dDevice->SetRenderState(D3DRS_SCISSORTESTENABLE, true); g_pd3dDevice->SetRenderState(D3DRS_SHADEMODE, D3DSHADE_GOURAUD); + g_pd3dDevice->SetRenderState(D3DRS_FOGENABLE, false); g_pd3dDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE); g_pd3dDevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE); g_pd3dDevice->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE); diff --git a/examples/imgui_impl_win32.cpp b/examples/imgui_impl_win32.cpp index cea9e6d9..230fc22b 100644 --- a/examples/imgui_impl_win32.cpp +++ b/examples/imgui_impl_win32.cpp @@ -20,7 +20,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) // 2018-XX-XX: Platform: Added support for multiple windows via the ImGuiPlatformIO interface. -// 2019-01-15: Inputs: Using GetForegroundWindow() instead of GetActiveWindow() to be compatible with windows created in a different thread. +// 2019-01-17: Inputs: Using GetForegroundWindow()+IsChild() instead of GetActiveWindow() to be compatible with windows created in a different thread or parent. // 2019-01-15: Inputs: Added support for XInput gamepads (if ImGuiConfigFlags_NavEnableGamepad is set by user application). // 2018-11-30: Misc: Setting up io.BackendPlatformName so it can be displayed in the About Window. // 2018-06-29: Inputs: Added support for the ImGuiMouseCursor_Hand cursor. @@ -164,6 +164,8 @@ static void ImGui_ImplWin32_UpdateMousePos() return; if (HWND focused_hwnd = ::GetForegroundWindow()) { + if (::IsChild(focused_hwnd, g_hWnd)) + focused_hwnd = g_hWnd; if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable) { // Multi-viewport mode: mouse position in OS absolute coordinates (io.MousePos is (0,0) when the mouse is on the upper-left of the primary monitor) @@ -194,6 +196,14 @@ static void ImGui_ImplWin32_UpdateMousePos() if (ImGuiViewport* viewport = ImGui::FindViewportByPlatformHandle((void*)hovered_hwnd)) if ((viewport->Flags & ImGuiViewportFlags_NoInputs) == 0) // FIXME: We still get our NoInputs window with WM_NCHITTEST/HTTRANSPARENT code when decorated? io.MouseHoveredViewport = viewport->ID; + +#if 0 + POINT pos; + if (HWND active_window = ::GetForegroundWindow()) + if (active_window == g_hWnd || ::IsChild(active_window, g_hWnd)) + if (::GetCursorPos(&pos) && ::ScreenToClient(g_hWnd, &pos)) + io.MousePos = ImVec2((float)pos.x, (float)pos.y); +#endif } #ifdef _MSC_VER diff --git a/imgui.cpp b/imgui.cpp index 438f89fa..dbdcb783 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -3013,7 +3013,7 @@ bool ImGui::DebugCheckVersionAndDataLayout(const char* version, size_t sz_io, si return !error; } -void ImGui::SetAllocatorFunctions(void* (*alloc_func)(size_t sz, void* user_data), void(*free_func)(void* ptr, void* user_data), void* user_data) +void ImGui::SetAllocatorFunctions(void* (*alloc_func)(size_t sz, void* user_data), void (*free_func)(void* ptr, void* user_data), void* user_data) { GImAllocatorAllocFunc = alloc_func; GImAllocatorFreeFunc = free_func; diff --git a/imgui.h b/imgui.h index a9e3be33..8445ec2e 100644 --- a/imgui.h +++ b/imgui.h @@ -698,7 +698,7 @@ namespace ImGui // Memory Utilities // - All those functions are not reliant on the current context. // - If you reload the contents of imgui.cpp at runtime, you may need to call SetCurrentContext() + SetAllocatorFunctions() again. - IMGUI_API void SetAllocatorFunctions(void* (*alloc_func)(size_t sz, void* user_data), void(*free_func)(void* ptr, void* user_data), void* user_data = NULL); + IMGUI_API void SetAllocatorFunctions(void* (*alloc_func)(size_t sz, void* user_data), void (*free_func)(void* ptr, void* user_data), void* user_data = NULL); IMGUI_API void* MemAlloc(size_t size); IMGUI_API void MemFree(void* ptr); diff --git a/imgui_demo.cpp b/imgui_demo.cpp index fb3f22cb..7906a5e1 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -3944,27 +3944,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; diff --git a/imgui_draw.cpp b/imgui_draw.cpp index 4c30ccb5..d20df78e 100644 --- a/imgui_draw.cpp +++ b/imgui_draw.cpp @@ -961,6 +961,9 @@ void ImDrawList::PathArcTo(const ImVec2& centre, float radius, float a_min, floa _Path.push_back(centre); return; } + + // Note that we are adding a point at both a_min and a_max. + // If you are trying to draw a full closed circle you don't want the overlapping points! _Path.reserve(_Path.Size + (num_segments + 1)); for (int i = 0; i <= num_segments; i++) { @@ -1144,21 +1147,23 @@ void ImDrawList::AddTriangleFilled(const ImVec2& a, const ImVec2& b, const ImVec void ImDrawList::AddCircle(const ImVec2& centre, float radius, ImU32 col, int num_segments, float thickness) { - if ((col & IM_COL32_A_MASK) == 0) + if ((col & IM_COL32_A_MASK) == 0 || num_segments <= 2) return; + // Because we are filling a closed shape we remove 1 from the count of segments/points const float a_max = IM_PI*2.0f * ((float)num_segments - 1.0f) / (float)num_segments; - PathArcTo(centre, radius-0.5f, 0.0f, a_max, num_segments); + PathArcTo(centre, radius-0.5f, 0.0f, a_max, num_segments - 1); PathStroke(col, true, thickness); } void ImDrawList::AddCircleFilled(const ImVec2& centre, float radius, ImU32 col, int num_segments) { - if ((col & IM_COL32_A_MASK) == 0) + if ((col & IM_COL32_A_MASK) == 0 || num_segments <= 2) return; + // Because we are filling a closed shape we remove 1 from the count of segments/points const float a_max = IM_PI*2.0f * ((float)num_segments - 1.0f) / (float)num_segments; - PathArcTo(centre, radius, 0.0f, a_max, num_segments); + PathArcTo(centre, radius, 0.0f, a_max, num_segments - 1); PathFillConvex(col); } diff --git a/misc/freetype/README.md b/misc/freetype/README.md index 885451a4..156e6511 100644 --- a/misc/freetype/README.md +++ b/misc/freetype/README.md @@ -121,6 +121,5 @@ struct FreeTypeTest ``` ### Known issues -- FreeType's memory allocator is not overridden. - `cfg.OversampleH`, `OversampleV` are ignored (but perhaps not so necessary with this rasterizer). diff --git a/misc/freetype/imgui_freetype.cpp b/misc/freetype/imgui_freetype.cpp index 7c5403b6..cef5a716 100644 --- a/misc/freetype/imgui_freetype.cpp +++ b/misc/freetype/imgui_freetype.cpp @@ -5,12 +5,13 @@ // Changelog: // - v0.50: (2017/08/16) imported from https://github.com/Vuhdo/imgui_freetype into http://www.github.com/ocornut/imgui_club, updated for latest changes in ImFontAtlas, minor tweaks. // - v0.51: (2017/08/26) cleanup, optimizations, support for ImFontConfig::RasterizerFlags, ImFontConfig::RasterizerMultiply. -// - v0.52: (2017/09/26) fixes for imgui internal changes -// - v0.53: (2017/10/22) minor inconsequential change to match change in master (removed an unnecessary statement) -// - v0.54: (2018/01/22) fix for addition of ImFontAtlas::TexUvscale member +// - v0.52: (2017/09/26) fixes for imgui internal changes. +// - v0.53: (2017/10/22) minor inconsequential change to match change in master (removed an unnecessary statement). +// - v0.54: (2018/01/22) fix for addition of ImFontAtlas::TexUvscale member. // - v0.55: (2018/02/04) moved to main imgui repository (away from http://www.github.com/ocornut/imgui_club) -// - v0.56: (2018/06/08) added support for ImFontConfig::GlyphMinAdvanceX, GlyphMaxAdvanceX +// - v0.56: (2018/06/08) added support for ImFontConfig::GlyphMinAdvanceX, GlyphMaxAdvanceX. // - v0.60: (2019/01/10) re-factored to match big update in STB builder. fixed texture height waste. fixed redundant glyphs when merging. support for glyph padding. +// - v0.61: (2019/01/15) added support for imgui allocators + added FreeType only override function SetAllocatorFunctions(). // Gamma Correct Blending: // FreeType assumes blending in linear space rather than gamma space. @@ -18,7 +19,6 @@ // For correct results you need to be using sRGB and convert to linear space in the pixel shader output. // The default imgui styles will be impacted by this change (alpha values will need tweaking). -// FIXME: FreeType's memory allocator is not overridden. // FIXME: cfg.OversampleH, OversampleV are not supported (but perhaps not so necessary with this rasterizer). #include "imgui_freetype.h" @@ -26,6 +26,7 @@ #include #include #include FT_FREETYPE_H // +#include FT_MODULE_H // #include FT_GLYPH_H // #include FT_SYNTHESIS_H // @@ -115,7 +116,6 @@ namespace bool FreeTypeFont::InitFont(FT_Library ft_library, const ImFontConfig& cfg, unsigned int extra_user_flags) { - // FIXME: substitute allocator FT_Error error = FT_New_Memory_Face(ft_library, (uint8_t*)cfg.FontData, (uint32_t)cfg.FontDataSize, (uint32_t)cfg.FontNo, &Face); if (error != 0) return false; @@ -566,15 +566,75 @@ bool ImFontAtlasBuildWithFreeType(FT_Library ft_library, ImFontAtlas* atlas, uns return true; } +// Default memory allocators +static void* ImFreeTypeDefaultAllocFunc(size_t size, void* user_data) { (void)user_data; return ImGui::MemAlloc(size); } +static void ImFreeTypeDefaultFreeFunc(void* ptr, void* user_data) { (void)user_data; ImGui::MemFree(ptr); } + +// Current memory allocators +static void* (*GImFreeTypeAllocFunc)(size_t size, void* user_data) = ImFreeTypeDefaultAllocFunc; +static void (*GImFreeTypeFreeFunc)(void* ptr, void* user_data) = ImFreeTypeDefaultFreeFunc; +static void* GImFreeTypeAllocatorUserData = NULL; + +// FreeType memory allocation callbacks +static void* FreeType_Alloc(FT_Memory /*memory*/, long size) +{ + return GImFreeTypeAllocFunc((size_t)size, GImFreeTypeAllocatorUserData); +} + +static void FreeType_Free(FT_Memory /*memory*/, void* block) +{ + GImFreeTypeFreeFunc(block, GImFreeTypeAllocatorUserData); +} + +static void* FreeType_Realloc(FT_Memory /*memory*/, long cur_size, long new_size, void* block) +{ + // Implement realloc() as we don't ask user to provide it. + if (block == NULL) + return GImFreeTypeAllocFunc((size_t)new_size, GImFreeTypeAllocatorUserData); + + if (new_size == 0) + { + GImFreeTypeFreeFunc(block, GImFreeTypeAllocatorUserData); + return NULL; + } + + if (new_size > cur_size) + { + void* new_block = GImFreeTypeAllocFunc((size_t)new_size, GImFreeTypeAllocatorUserData); + memcpy(new_block, block, (size_t)cur_size); + GImFreeTypeFreeFunc(block, GImFreeTypeAllocatorUserData); + return new_block; + } + + return block; +} + bool ImGuiFreeType::BuildFontAtlas(ImFontAtlas* atlas, unsigned int extra_flags) { + // FreeType memory management: https://www.freetype.org/freetype2/docs/design/design-4.html + FT_MemoryRec_ memory_rec = { 0 }; + memory_rec.alloc = &FreeType_Alloc; + memory_rec.free = &FreeType_Free; + memory_rec.realloc = &FreeType_Realloc; + + // https://www.freetype.org/freetype2/docs/reference/ft2-module_management.html#FT_New_Library FT_Library ft_library; - FT_Error error = FT_Init_FreeType(&ft_library); + FT_Error error = FT_New_Library(&memory_rec, &ft_library); if (error != 0) return false; + // If you don't call FT_Add_Default_Modules() the rest of code may work, but FreeType won't use our custom allocator. + FT_Add_Default_Modules(ft_library); + bool ret = ImFontAtlasBuildWithFreeType(ft_library, atlas, extra_flags); - FT_Done_FreeType(ft_library); + FT_Done_Library(ft_library); return ret; } + +void ImGuiFreeType::SetAllocatorFunctions(void* (*alloc_func)(size_t sz, void* user_data), void (*free_func)(void* ptr, void* user_data), void* user_data) +{ + GImFreeTypeAllocFunc = alloc_func; + GImFreeTypeFreeFunc = free_func; + GImFreeTypeAllocatorUserData = user_data; +} diff --git a/misc/freetype/imgui_freetype.h b/misc/freetype/imgui_freetype.h index aa0aba63..a0503bff 100644 --- a/misc/freetype/imgui_freetype.h +++ b/misc/freetype/imgui_freetype.h @@ -28,4 +28,8 @@ namespace ImGuiFreeType }; IMGUI_API bool BuildFontAtlas(ImFontAtlas* atlas, unsigned int extra_flags = 0); + + // By default ImGuiFreeType will use ImGui::MemAlloc()/MemFree(). + // However, as FreeType does lots of allocations we provide a way for the user to redirect it to a separate memory heap if desired: + IMGUI_API void SetAllocatorFunctions(void* (*alloc_func)(size_t sz, void* user_data), void (*free_func)(void* ptr, void* user_data), void* user_data = NULL); }