diff --git a/headers/3rdparty/imgui/imgui.cpp b/headers/3rdparty/imgui/imgui.cpp index 92af81d0..89a9358c 100644 --- a/headers/3rdparty/imgui/imgui.cpp +++ b/headers/3rdparty/imgui/imgui.cpp @@ -1,4 +1,4 @@ -// dear imgui, v1.74 +// dear imgui, v1.75 WIP // (main code and documentation) // Call and read ImGui::ShowDemoWindow() in imgui_demo.cpp for demo code. @@ -11,8 +11,8 @@ // Developed by Omar Cornut and every direct or indirect contributors to the GitHub. // See LICENSE.txt for copyright and licensing details (standard MIT License). // This library is free but I need your support to sustain development and maintenance. -// Businesses: you can support continued maintenance and development via support contracts or sponsoring, see docs/README. -// Individuals: you can support continued maintenance and development via donations or Patreon https://www.patreon.com/imgui. +// Businesses: you can support continued development via invoiced technical support, maintenance and sponsoring contracts. Please reach out to "contact AT dearimgui.org". +// Individuals: you can support continued development via donations. See docs/README or web page. // It is recommended that you don't modify imgui.cpp! It will become difficult for you to update the library. // Note that 'ImGui::' being a namespace, you can add functions into the namespace from your own source files, without @@ -45,7 +45,8 @@ CODE // [SECTION] FORWARD DECLARATIONS // [SECTION] CONTEXT AND MEMORY ALLOCATORS // [SECTION] MAIN USER FACING STRUCTURES (ImGuiStyle, ImGuiIO) -// [SECTION] MISC HELPERS/UTILITIES (Geomtry, String, Format, Hash, File functions) +// [SECTION] MISC HELPERS/UTILITIES (Geometry functions) +// [SECTION] MISC HELPERS/UTILITIES (String, Format, Hash functions) // [SECTION] MISC HELPERS/UTILITIES (File functions) // [SECTION] MISC HELPERS/UTILITIES (ImText* functions) // [SECTION] MISC HELPERS/UTILITIES (Color functions) @@ -312,9 +313,18 @@ CODE USING GAMEPAD/KEYBOARD NAVIGATION CONTROLS ------------------------------------------ - The gamepad/keyboard navigation is fairly functional and keeps being improved. - - Gamepad support is particularly useful to use dear imgui on a console system (e.g. PS4, Switch, XB1) without a mouse! + - Gamepad support is particularly useful to use Dear ImGui on a console system (e.g. PS4, Switch, XB1) without a mouse! - You can ask questions and report issues at https://github.com/ocornut/imgui/issues/787 - The initial focus was to support game controllers, but keyboard is becoming increasingly and decently usable. + - Keyboard: + - Set io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard to enable. + NewFrame() will automatically fill io.NavInputs[] based on your io.KeysDown[] + io.KeyMap[] arrays. + - When keyboard navigation is active (io.NavActive + ImGuiConfigFlags_NavEnableKeyboard), the io.WantCaptureKeyboard flag + will be set. For more advanced uses, you may want to read from: + - io.NavActive: true when a window is focused and it doesn't have the ImGuiWindowFlags_NoNavInputs flag set. + - io.NavVisible: true when the navigation cursor is visible (and usually goes false when mouse is used). + - or query focus information with e.g. IsWindowFocused(ImGuiFocusedFlags_AnyWindow), IsItemFocused() etc. functions. + Please reach out if you think the game vs navigation input sharing could be improved. - Gamepad: - Set io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad to enable. - Backend: Set io.BackendFlags |= ImGuiBackendFlags_HasGamepad + fill the io.NavInputs[] fields before calling NewFrame(). @@ -326,15 +336,6 @@ CODE - You can download PNG/PSD files depicting the gamepad controls for common controllers at: http://goo.gl/9LgVZW. - If you need to share inputs between your game and the imgui parts, the easiest approach is to go all-or-nothing, with a buttons combo to toggle the target. Please reach out if you think the game vs navigation input sharing could be improved. - - Keyboard: - - Set io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard to enable. - NewFrame() will automatically fill io.NavInputs[] based on your io.KeysDown[] + io.KeyMap[] arrays. - - When keyboard navigation is active (io.NavActive + ImGuiConfigFlags_NavEnableKeyboard), the io.WantCaptureKeyboard flag - will be set. For more advanced uses, you may want to read from: - - io.NavActive: true when a window is focused and it doesn't have the ImGuiWindowFlags_NoNavInputs flag set. - - io.NavVisible: true when the navigation cursor is visible (and usually goes false when mouse is used). - - or query focus information with e.g. IsWindowFocused(ImGuiFocusedFlags_AnyWindow), IsItemFocused() etc. functions. - Please reach out if you think the game vs navigation input sharing could be improved. - Mouse: - PS4 users: Consider emulating a mouse cursor with DualShock4 touch pad or a spare analog stick as a mouse-emulation fallback. - Consoles/Tablet/Phone users: Consider using a Synergy 1.x server (on your PC) + uSynergy.c (on your console/tablet/phone app) to share your PC mouse/keyboard. @@ -364,10 +365,30 @@ CODE - 2019/XX/XX (1.XX) - Moved IME support functions from io.ImeSetInputScreenPosFn, io.ImeWindowHandle to the PlatformIO api. + - 2019/12/17 (1.75) - made Columns() limited to 64 columns by asserting above that limit. While the current code technically supports it, future code may not so we're putting the restriction ahead. + - 2019/12/13 (1.75) - [imgui_internal.h] changed ImRect() default constructor initializes all fields to 0.0f instead of (FLT_MAX,FLT_MAX,-FLT_MAX,-FLT_MAX). If you used ImRect::Add() to create bounding boxes by adding multiple points into it, you may need to fix your initial value. + - 2019/12/08 (1.75) - removed redirecting functions/enums that were marked obsolete in 1.53 (December 2017): + - ShowTestWindow() -> use ShowDemoWindow() + - IsRootWindowFocused() -> use IsWindowFocused(ImGuiFocusedFlags_RootWindow) + - IsRootWindowOrAnyChildFocused() -> use IsWindowFocused(ImGuiFocusedFlags_RootAndChildWindows) + - SetNextWindowContentWidth(w) -> use SetNextWindowContentSize(ImVec2(w, 0.0f) + - GetItemsLineHeightWithSpacing() -> use GetFrameHeightWithSpacing() + - ImGuiCol_ChildWindowBg -> use ImGuiCol_ChildBg + - ImGuiStyleVar_ChildWindowRounding -> use ImGuiStyleVar_ChildRounding + - ImGuiTreeNodeFlags_AllowOverlapMode -> use ImGuiTreeNodeFlags_AllowItemOverlap + - IMGUI_DISABLE_TEST_WINDOWS -> use IMGUI_DISABLE_DEMO_WINDOWS + - 2019/12/08 (1.75) - obsoleted calling ImDrawList::PrimReserve() with a negative count (which was the vaguely documented and rarely if ever used). Instead we added an explicit PrimUnreserve() API. + - 2019/12/06 (1.75) - removed implicit default parameter to IsMouseDragging(int button = 0) to be consistent with other mouse functions (none of the other functions have it). +>>>>>>> refs/heads/master - 2019/11/21 (1.74) - ImFontAtlas::AddCustomRectRegular() now requires an ID larger than 0x110000 (instead of 0x10000) to conform with supporting Unicode planes 1-16 in a future update. ID below 0x110000 will now assert. - 2019/11/19 (1.74) - renamed IMGUI_DISABLE_FORMAT_STRING_FUNCTIONS to IMGUI_DISABLE_DEFAULT_FORMAT_FUNCTIONS for consistency. - 2019/11/19 (1.74) - renamed IMGUI_DISABLE_MATH_FUNCTIONS to IMGUI_DISABLE_DEFAULT_MATH_FUNCTIONS for consistency. - - 2019/10/22 (1.74) - removed redirecting functions/enums that were marked obsolete in 1.52 (October 2017): Begin() (5 arguments signature), IsRootWindowOrAnyChildHovered(), AlignFirstTextHeightToWidgets(), SetNextWindowPosCenter(), ImFont::Glyph. See docs/Changelog.txt or grep this log for details and new names, or see how they were implemented until 1.73. + - 2019/10/22 (1.74) - removed redirecting functions/enums that were marked obsolete in 1.52 (October 2017): + - Begin() [old 5 args version] -> use Begin() [3 args], use SetNextWindowSize() SetNextWindowBgAlpha() if needed + - IsRootWindowOrAnyChildHovered() -> use IsWindowHovered(ImGuiHoveredFlags_RootAndChildWindows) + - AlignFirstTextHeightToWidgets() -> use AlignTextToFramePadding() + - SetNextWindowPosCenter() -> use SetNextWindowPos() with a pivot of (0.5f, 0.5f) + - ImFont::Glyph -> use ImFontGlyph - 2019/10/14 (1.74) - inputs: Fixed a miscalculation in the keyboard/mouse "typematic" repeat delay/rate calculation, used by keys and e.g. repeating mouse buttons as well as the GetKeyPressedAmount() function. if you were using a non-default value for io.KeyRepeatRate (previous default was 0.250), you can add +io.KeyRepeatDelay to it to compensate for the fix. The function was triggering on: 0.0 and (delay+rate*N) where (N>=1). Fixed formula responds to (N>=0). Effectively it made io.KeyRepeatRate behave like it was set to (io.KeyRepeatRate + io.KeyRepeatDelay). @@ -486,7 +507,7 @@ CODE - 2016/07/30 (1.50) - SameLine(x) with x>0.0f is now relative to left of column/group if any, and not always to left of window. This was sort of always the intent and hopefully breakage should be minimal. - 2016/05/12 (1.49) - title bar (using ImGuiCol_TitleBg/ImGuiCol_TitleBgActive colors) isn't rendered over a window background (ImGuiCol_WindowBg color) anymore. If your TitleBg/TitleBgActive alpha was 1.0f or you are using the default theme it will not affect you, otherwise if <1.0f you need tweak your custom theme to readjust for the fact that we don't draw a WindowBg background behind the title bar. - This helper function will convert an old TitleBg/TitleBgActive color into a new one with the same visual output, given the OLD color and the OLD WindowBg color: + This helper function will convert an old TitleBg/TitleBgActive color into a new one with the same visual output, given the OLD color and the OLD WindowBg color: ImVec4 ConvertTitleBgCol(const ImVec4& win_bg_col, const ImVec4& title_bg_col) { float new_a = 1.0f - ((1.0f - win_bg_col.w) * (1.0f - title_bg_col.w)), k = title_bg_col.w / new_a; return ImVec4((win_bg_col.x * win_bg_col.w + title_bg_col.x) * k, (win_bg_col.y * win_bg_col.w + title_bg_col.y) * k, (win_bg_col.z * win_bg_col.w + title_bg_col.z) * k, new_a); } If this is confusing, pick the RGB value from title bar from an old screenshot and apply this as TitleBg/TitleBgActive. Or you may just create TitleBgActive from a tweaked TitleBg color. - 2016/05/07 (1.49) - removed confusing set of GetInternalState(), GetInternalStateSize(), SetInternalState() functions. Now using CreateContext(), DestroyContext(), GetCurrentContext(), SetCurrentContext(). @@ -546,14 +567,13 @@ CODE - 2015/02/01 (1.31) - removed IO.MemReallocFn (unused) - 2015/01/19 (1.30) - renamed ImGuiStorage::GetIntPtr()/GetFloatPtr() to GetIntRef()/GetIntRef() because Ptr was conflicting with actual pointer storage functions. - 2015/01/11 (1.30) - big font/image API change! now loads TTF file. allow for multiple fonts. no need for a PNG loader. - (1.30) - removed GetDefaultFontData(). uses io.Fonts->GetTextureData*() API to retrieve uncompressed pixels. - font init: { const void* png_data; unsigned int png_size; ImGui::GetDefaultFontData(NULL, NULL, &png_data, &png_size); <..Upload texture to GPU..>; } - became: { unsigned char* pixels; int width, height; io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height); <..Upload texture to GPU>; io.Fonts->TexId = YourTextureIdentifier; } - you now have more flexibility to load multiple TTF fonts and manage the texture buffer for internal needs. - it is now recommended that you sample the font texture with bilinear interpolation. - (1.30) - added texture identifier in ImDrawCmd passed to your render function (we can now render images). make sure to set io.Fonts->TexID. - (1.30) - removed IO.PixelCenterOffset (unnecessary, can be handled in user projection matrix) - (1.30) - removed ImGui::IsItemFocused() in favor of ImGui::IsItemActive() which handles all widgets + - 2015/01/11 (1.30) - removed GetDefaultFontData(). uses io.Fonts->GetTextureData*() API to retrieve uncompressed pixels. + - old: const void* png_data; unsigned int png_size; ImGui::GetDefaultFontData(NULL, NULL, &png_data, &png_size); [..Upload texture to GPU..]; + - new: unsigned char* pixels; int width, height; io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height); [..Upload texture to GPU..]; io.Fonts->TexId = YourTexIdentifier; + you now have more flexibility to load multiple TTF fonts and manage the texture buffer for internal needs. It is now recommended that you sample the font texture with bilinear interpolation. + - 2015/01/11 (1.30) - added texture identifier in ImDrawCmd passed to your render function (we can now render images). make sure to set io.Fonts->TexID. + - 2015/01/11 (1.30) - removed IO.PixelCenterOffset (unnecessary, can be handled in user projection matrix) + - 2015/01/11 (1.30) - removed ImGui::IsItemFocused() in favor of ImGui::IsItemActive() which handles all widgets - 2014/12/10 (1.18) - removed SetNewWindowDefaultPos() in favor of new generic API SetNextWindowPos(pos, ImGuiSetCondition_FirstUseEver) - 2014/11/28 (1.17) - moved IO.Font*** options to inside the IO.Font-> structure (FontYOffset, FontTexUvForWhite, FontBaseScale, FontFallbackGlyph) - 2014/11/26 (1.17) - reworked syntax of IMGUI_ONCE_UPON_A_FRAME helper macro to increase compiler compatibility @@ -582,13 +602,16 @@ CODE - 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. - 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/ - folder to explain how to integrate Dear ImGui with your own engine/application. + - 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. + - The Wiki (https://github.com/ocornut/imgui/wiki) has many resources and links. + - The Glossary (https://github.com/ocornut/imgui/wiki/Glossary) page also may be useful. - Your programming IDE is your friend, find the type or function declaration to find comments associated to it. Q: Which version should I get? Q: Why the names "Dear ImGui" vs "ImGui"? + >> This library is called "Dear ImGui", please don't call it "ImGui" :) >> See https://www.dearimgui.org/faq Q&A: Concerns @@ -618,6 +641,7 @@ CODE have 'io.WantCaptureKeyboard=false'. Depending on your application logic it may or not be inconvenient. You might want to track which key-downs were targeted for Dear ImGui, e.g. with an array of bool, and filter out the corresponding key-ups.) + Q. How can I enable keyboard controls? Q: How can I use this without a mouse, without a keyboard or without a screen? (gamepad, input share, remote display) Q: I integrated Dear ImGui in my engine and the text or lines are blurry.. Q: I integrated Dear ImGui in my engine and some elements are clipping or disappearing when I move windows around.. @@ -763,11 +787,13 @@ CODE ============== Q: How can I help? - A: - If you are experienced with Dear ImGui and C++, look at the github issues, look at the Wiki, read docs/TODO.txt + A: - Businesses: please reach out to "contact AT dearimgui.org" if you work in a place using Dear ImGui! + We can discuss ways for your company to fund development via invoiced technical support, maintenance or sponsoring contacts. + This is among the most useful thing you can do for Dear ImGui. With increased funding we can hire more people working on this project. + - Individuals: you can support continued development via PayPal donations. See README. + - If you are experienced with Dear ImGui and C++, look at the github issues, look at the Wiki, read docs/TODO.txt and see how you want to help and can help! - - Businesses: convince your company to fund development via support contracts/sponsoring! This is among the most useful thing you can do for dear imgui. - - Individuals: you can also become a Patron (http://www.patreon.com/imgui) or donate on PayPal! See README. - - Disclose your usage of dear imgui via a dev blog post, a tweet, a screenshot, a mention somewhere etc. + - Disclose your usage of Dear ImGui via a dev blog post, a tweet, a screenshot, a mention somewhere etc. You may post screenshot or links in the gallery threads (github.com/ocornut/imgui/issues/2847). Visuals are ideal as they inspire other programmers. But even without visuals, disclosing your use of dear imgui help the library grow credibility, and help other teams and programmers with taking decisions. - If you have issues or if you need to hack into the library, even if you don't expect any support it is useful that you share your issues (on github or privately). @@ -869,8 +895,6 @@ static void SetClipboardTextFn_DefaultImpl(void* user_data, const ch namespace ImGui { -static bool BeginChildEx(const char* name, ImGuiID id, const ImVec2& size_arg, bool border, ImGuiWindowFlags flags); - // Navigation static void NavUpdate(); static void NavUpdateWindowing(); @@ -1027,6 +1051,7 @@ ImGuiIO::ImGuiIO() { // Most fields are initialized with zero memset(this, 0, sizeof(*this)); + IM_ASSERT(IM_ARRAYSIZE(ImGuiIO::MouseDown) == ImGuiMouseButton_COUNT && IM_ARRAYSIZE(ImGuiIO::MouseClicked) == ImGuiMouseButton_COUNT); // Our pre-C++11 IM_STATIC_ASSERT() macros triggers warning on modern compilers so we don't use it here. // Settings ConfigFlags = ImGuiConfigFlags_None; @@ -1120,9 +1145,77 @@ void ImGuiIO::ClearInputCharacters() } //----------------------------------------------------------------------------- -// [SECTION] MISC HELPERS/UTILITIES (Geometry, String, Format, Hash, File functions) +// [SECTION] MISC HELPERS/UTILITIES (Geometry functions) //----------------------------------------------------------------------------- +ImVec2 ImBezierClosestPoint(const ImVec2& p1, const ImVec2& p2, const ImVec2& p3, const ImVec2& p4, const ImVec2& p, int num_segments) +{ + IM_ASSERT(num_segments > 0); // Use ImBezierClosestPointCasteljau() + ImVec2 p_last = p1; + ImVec2 p_closest; + float p_closest_dist2 = FLT_MAX; + float t_step = 1.0f / (float)num_segments; + for (int i_step = 1; i_step <= num_segments; i_step++) + { + ImVec2 p_current = ImBezierCalc(p1, p2, p3, p4, t_step * i_step); + ImVec2 p_line = ImLineClosestPoint(p_last, p_current, p); + float dist2 = ImLengthSqr(p - p_line); + if (dist2 < p_closest_dist2) + { + p_closest = p_line; + p_closest_dist2 = dist2; + } + p_last = p_current; + } + return p_closest; +} + +// Closely mimics PathBezierToCasteljau() in imgui_draw.cpp +static void BezierClosestPointCasteljauStep(const ImVec2& p, ImVec2& p_closest, ImVec2& p_last, float& p_closest_dist2, float x1, float y1, float x2, float y2, float x3, float y3, float x4, float y4, float tess_tol, int level) +{ + float dx = x4 - x1; + float dy = y4 - y1; + float d2 = ((x2 - x4) * dy - (y2 - y4) * dx); + float d3 = ((x3 - x4) * dy - (y3 - y4) * dx); + d2 = (d2 >= 0) ? d2 : -d2; + d3 = (d3 >= 0) ? d3 : -d3; + if ((d2+d3) * (d2+d3) < tess_tol * (dx*dx + dy*dy)) + { + ImVec2 p_current(x4, y4); + ImVec2 p_line = ImLineClosestPoint(p_last, p_current, p); + float dist2 = ImLengthSqr(p - p_line); + if (dist2 < p_closest_dist2) + { + p_closest = p_line; + p_closest_dist2 = dist2; + } + p_last = p_current; + } + else if (level < 10) + { + float x12 = (x1+x2)*0.5f, y12 = (y1+y2)*0.5f; + float x23 = (x2+x3)*0.5f, y23 = (y2+y3)*0.5f; + float x34 = (x3+x4)*0.5f, y34 = (y3+y4)*0.5f; + float x123 = (x12+x23)*0.5f, y123 = (y12+y23)*0.5f; + float x234 = (x23+x34)*0.5f, y234 = (y23+y34)*0.5f; + float x1234 = (x123+x234)*0.5f, y1234 = (y123+y234)*0.5f; + BezierClosestPointCasteljauStep(p, p_closest, p_last, p_closest_dist2, x1, y1, x12, y12, x123, y123, x1234, y1234, tess_tol, level + 1); + BezierClosestPointCasteljauStep(p, p_closest, p_last, p_closest_dist2, x1234, y1234, x234, y234, x34, y34, x4, y4, tess_tol, level + 1); + } +} + +// tess_tol is generally the same value you would find in ImGui::GetStyle().CurveTessellationTol +// Because those ImXXX functions are lower-level than ImGui:: we cannot access this value automatically. +ImVec2 ImBezierClosestPointCasteljau(const ImVec2& p1, const ImVec2& p2, const ImVec2& p3, const ImVec2& p4, const ImVec2& p, float tess_tol) +{ + IM_ASSERT(tess_tol > 0.0f); + ImVec2 p_last = p1; + ImVec2 p_closest; + float p_closest_dist2 = FLT_MAX; + BezierClosestPointCasteljauStep(p, p_closest, p_last, p_closest_dist2, p1.x, p1.y, p2.x, p2.y, p3.x, p3.y, p4.x, p4.y, tess_tol, 0); + return p_closest; +} + ImVec2 ImLineClosestPoint(const ImVec2& a, const ImVec2& b, const ImVec2& p) { ImVec2 ap = p - a; @@ -1171,6 +1264,10 @@ ImVec2 ImTriangleClosestPoint(const ImVec2& a, const ImVec2& b, const ImVec2& c, return proj_ca; } +//----------------------------------------------------------------------------- +// [SECTION] MISC HELPERS/UTILITIES (String, Format, Hash functions) +//----------------------------------------------------------------------------- + // Consider using _stricmp/_strnicmp under Windows or strcasecmp/strncasecmp. We don't actually use either ImStricmp/ImStrnicmp in the codebase any more. int ImStricmp(const char* str1, const char* str2) { @@ -1295,8 +1392,8 @@ const char* ImStrSkipBlank(const char* str) #ifndef IMGUI_DISABLE_DEFAULT_FORMAT_FUNCTIONS // We support stb_sprintf which is much faster (see: https://github.com/nothings/stb/blob/master/stb_sprintf.h) -// You may set IMGUI_USE_STB_SPRINTF to use our default wrapper, or set IMGUI_DISABLE_DEFAULT_FORMAT_FUNCTIONS -// and setup the wrapper yourself. (FIXME-OPT: Some of our high-level operations such as ImGuiTextBuffer::appendfv() are +// You may set IMGUI_USE_STB_SPRINTF to use our default wrapper, or set IMGUI_DISABLE_DEFAULT_FORMAT_FUNCTIONS +// and setup the wrapper yourself. (FIXME-OPT: Some of our high-level operations such as ImGuiTextBuffer::appendfv() are // designed using two-passes worst case, which probably could be improved using the stbsp_vsprintfcb() function.) //#define IMGUI_USE_STB_SPRINTF #ifdef IMGUI_USE_STB_SPRINTF @@ -1421,7 +1518,7 @@ ImU32 ImHashStr(const char* data_p, size_t data_size, ImU32 seed) ImFileHandle ImFileOpen(const char* filename, const char* mode) { #if defined(_WIN32) && !defined(IMGUI_DISABLE_WIN32_FUNCTIONS) && !defined(__CYGWIN__) && !defined(__GNUC__) - // We need a fopen() wrapper because MSVC/Windows fopen doesn't handle UTF-8 filenames. + // We need a fopen() wrapper because MSVC/Windows fopen doesn't handle UTF-8 filenames. const int filename_wsize = ImTextCountCharsFromUtf8(filename, NULL) + 1; const int mode_wsize = ImTextCountCharsFromUtf8(mode, NULL) + 1; ImVector buf; @@ -1741,38 +1838,6 @@ void ImGui::ColorConvertHSVtoRGB(float h, float s, float v, float& out_r, float& } } -ImU32 ImGui::GetColorU32(ImGuiCol idx, float alpha_mul) -{ - ImGuiStyle& style = GImGui->Style; - ImVec4 c = style.Colors[idx]; - c.w *= style.Alpha * alpha_mul; - return ColorConvertFloat4ToU32(c); -} - -ImU32 ImGui::GetColorU32(const ImVec4& col) -{ - ImGuiStyle& style = GImGui->Style; - ImVec4 c = col; - c.w *= style.Alpha; - return ColorConvertFloat4ToU32(c); -} - -const ImVec4& ImGui::GetStyleColorVec4(ImGuiCol idx) -{ - ImGuiStyle& style = GImGui->Style; - return style.Colors[idx]; -} - -ImU32 ImGui::GetColorU32(ImU32 col) -{ - float style_alpha = GImGui->Style.Alpha; - if (style_alpha >= 1.0f) - return col; - ImU32 a = (col & IM_COL32_A_MASK) >> IM_COL32_A_SHIFT; - a = (ImU32)(a * style_alpha); // We don't need to clamp 0..255 because Style.Alpha is in 0..1 range. - return (col & ~IM_COL32_A_MASK) | (a << IM_COL32_A_SHIFT); -} - //----------------------------------------------------------------------------- // [SECTION] ImGuiStorage // Helper: Key->value storage @@ -2230,10 +2295,42 @@ bool ImGuiListClipper::Step() //----------------------------------------------------------------------------- // [SECTION] RENDER HELPERS -// Those (internal) functions are currently quite a legacy mess - their signature and behavior will change. +// Some of those (internal) functions are currently quite a legacy mess - their signature and behavior will change. // Also see imgui_draw.cpp for some more which have been reworked to not rely on ImGui:: state. //----------------------------------------------------------------------------- +ImU32 ImGui::GetColorU32(ImGuiCol idx, float alpha_mul) +{ + ImGuiStyle& style = GImGui->Style; + ImVec4 c = style.Colors[idx]; + c.w *= style.Alpha * alpha_mul; + return ColorConvertFloat4ToU32(c); +} + +ImU32 ImGui::GetColorU32(const ImVec4& col) +{ + ImGuiStyle& style = GImGui->Style; + ImVec4 c = col; + c.w *= style.Alpha; + return ColorConvertFloat4ToU32(c); +} + +const ImVec4& ImGui::GetStyleColorVec4(ImGuiCol idx) +{ + ImGuiStyle& style = GImGui->Style; + return style.Colors[idx]; +} + +ImU32 ImGui::GetColorU32(ImU32 col) +{ + ImGuiStyle& style = GImGui->Style; + if (style.Alpha >= 1.0f) + return col; + ImU32 a = (col & IM_COL32_A_MASK) >> IM_COL32_A_SHIFT; + a = (ImU32)(a * style.Alpha); // We don't need to clamp 0..255 because Style.Alpha is in 0..1 range. + return (col & ~IM_COL32_A_MASK) | (a << IM_COL32_A_SHIFT); +} + const char* ImGui::FindRenderedTextEnd(const char* text, const char* text_end) { const char* text_display_end = text; @@ -4010,6 +4107,20 @@ void ImGui::Initialize(ImGuiContext* context) g.SettingsHandlers.push_back(ini_handler); } +#ifdef IMGUI_HAS_TABLE + // Add .ini handle for ImGuiTable type + { + ImGuiSettingsHandler ini_handler; + ini_handler.TypeName = "Table"; + ini_handler.TypeHash = ImHashStr("Table"); + ini_handler.ReadOpenFn = TableSettingsHandler_ReadOpen; + ini_handler.ReadLineFn = TableSettingsHandler_ReadLine; + ini_handler.WriteAllFn = TableSettingsHandler_WriteAll; + g.SettingsHandlers.push_back(ini_handler); + } +#endif // #ifdef IMGUI_HAS_TABLE + +#ifdef IMGUI_HAS_DOCK // Create default viewport ImGuiViewportP* viewport = IM_NEW(ImGuiViewportP)(); viewport->ID = IMGUI_VIEWPORT_DEFAULT_ID; @@ -4022,6 +4133,7 @@ void ImGui::Initialize(ImGuiContext* context) // Extensions IM_ASSERT(g.DockContext == NULL); DockContextInitialize(&g); +#endif // #ifdef IMGUI_HAS_DOCK g.Initialized = true; } @@ -4582,7 +4694,8 @@ int ImGui::GetKeyIndex(ImGuiKey imgui_key) return g.IO.KeyMap[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 dear 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) { if (user_key_index < 0) @@ -4642,23 +4755,14 @@ bool ImGui::IsKeyReleased(int user_key_index) return g.IO.KeysDownDurationPrev[user_key_index] >= 0.0f && !g.IO.KeysDown[user_key_index]; } -bool ImGui::IsMouseDown(int button) +bool ImGui::IsMouseDown(ImGuiMouseButton button) { ImGuiContext& g = *GImGui; IM_ASSERT(button >= 0 && button < IM_ARRAYSIZE(g.IO.MouseDown)); return g.IO.MouseDown[button]; } -bool ImGui::IsAnyMouseDown() -{ - ImGuiContext& g = *GImGui; - for (int n = 0; n < IM_ARRAYSIZE(g.IO.MouseDown); n++) - if (g.IO.MouseDown[n]) - return true; - return false; -} - -bool ImGui::IsMouseClicked(int button, bool repeat) +bool ImGui::IsMouseClicked(ImGuiMouseButton button, bool repeat) { ImGuiContext& g = *GImGui; IM_ASSERT(button >= 0 && button < IM_ARRAYSIZE(g.IO.MouseDown)); @@ -4673,18 +4777,17 @@ bool ImGui::IsMouseClicked(int button, bool repeat) if (amount > 0) return true; } - return false; } -bool ImGui::IsMouseReleased(int button) +bool ImGui::IsMouseReleased(ImGuiMouseButton button) { ImGuiContext& g = *GImGui; IM_ASSERT(button >= 0 && button < IM_ARRAYSIZE(g.IO.MouseDown)); return g.IO.MouseReleased[button]; } -bool ImGui::IsMouseDoubleClicked(int button) +bool ImGui::IsMouseDoubleClicked(ImGuiMouseButton button) { ImGuiContext& g = *GImGui; IM_ASSERT(button >= 0 && button < IM_ARRAYSIZE(g.IO.MouseDown)); @@ -4692,7 +4795,7 @@ bool ImGui::IsMouseDoubleClicked(int button) } // [Internal] This doesn't test if the button is pressed -bool ImGui::IsMouseDragPastThreshold(int button, float lock_threshold) +bool ImGui::IsMouseDragPastThreshold(ImGuiMouseButton button, float lock_threshold) { ImGuiContext& g = *GImGui; IM_ASSERT(button >= 0 && button < IM_ARRAYSIZE(g.IO.MouseDown)); @@ -4701,7 +4804,7 @@ bool ImGui::IsMouseDragPastThreshold(int button, float lock_threshold) return g.IO.MouseDragMaxDistanceSqr[button] >= lock_threshold * lock_threshold; } -bool ImGui::IsMouseDragging(int button, float lock_threshold) +bool ImGui::IsMouseDragging(ImGuiMouseButton button, float lock_threshold) { ImGuiContext& g = *GImGui; IM_ASSERT(button >= 0 && button < IM_ARRAYSIZE(g.IO.MouseDown)); @@ -4712,7 +4815,8 @@ bool ImGui::IsMouseDragging(int button, float lock_threshold) ImVec2 ImGui::GetMousePos() { - return GImGui->IO.MousePos; + ImGuiContext& g = *GImGui; + return g.IO.MousePos; } // NB: prefer to call right after BeginPopup(). At the time Selectable/MenuItem is activated, the popup is already closed! @@ -4735,10 +4839,19 @@ bool ImGui::IsMousePosValid(const ImVec2* mouse_pos) return p.x >= MOUSE_INVALID && p.y >= MOUSE_INVALID; } +bool ImGui::IsAnyMouseDown() +{ + ImGuiContext& g = *GImGui; + for (int n = 0; n < IM_ARRAYSIZE(g.IO.MouseDown); n++) + if (g.IO.MouseDown[n]) + return true; + return false; +} + // Return the delta from the initial clicking position while the mouse button is clicked or was just released. // This is locked and return 0.0f until the mouse moves past a distance threshold at least once. // NB: This is only valid if IsMousePosValid(). Back-ends in theory should always keep mouse position valid when dragging even outside the client window. -ImVec2 ImGui::GetMouseDragDelta(int button, float lock_threshold) +ImVec2 ImGui::GetMouseDragDelta(ImGuiMouseButton button, float lock_threshold) { ImGuiContext& g = *GImGui; IM_ASSERT(button >= 0 && button < IM_ARRAYSIZE(g.IO.MouseDown)); @@ -4751,7 +4864,7 @@ ImVec2 ImGui::GetMouseDragDelta(int button, float lock_threshold) return ImVec2(0.0f, 0.0f); } -void ImGui::ResetMouseDragDelta(int button) +void ImGui::ResetMouseDragDelta(ImGuiMouseButton button) { ImGuiContext& g = *GImGui; IM_ASSERT(button >= 0 && button < IM_ARRAYSIZE(g.IO.MouseDown)); @@ -4833,7 +4946,7 @@ bool ImGui::IsItemFocused() return true; } -bool ImGui::IsItemClicked(int mouse_button) +bool ImGui::IsItemClicked(ImGuiMouseButton mouse_button) { return IsMouseClicked(mouse_button) && IsItemHovered(ImGuiHoveredFlags_None); } @@ -4908,7 +5021,7 @@ ImVec2 ImGui::GetItemRectSize() return window->DC.LastItemRect.GetSize(); } -static bool ImGui::BeginChildEx(const char* name, ImGuiID id, const ImVec2& size_arg, bool border, ImGuiWindowFlags flags) +bool ImGui::BeginChildEx(const char* name, ImGuiID id, const ImVec2& size_arg, bool border, ImGuiWindowFlags flags) { ImGuiContext& g = *GImGui; ImGuiWindow* parent_window = g.CurrentWindow; @@ -4977,7 +5090,7 @@ void ImGui::EndChild() ImGuiWindow* window = g.CurrentWindow; IM_ASSERT(g.WithinEndChild == false); - IM_ASSERT(window->Flags & ImGuiWindowFlags_ChildWindow); // Mismatched BeginChild()/EndChild() callss + IM_ASSERT(window->Flags & ImGuiWindowFlags_ChildWindow); // Mismatched BeginChild()/EndChild() calls g.WithinEndChild = true; if (window->BeginCount > 1) @@ -6650,7 +6763,7 @@ void ImGui::FocusTopMostWindowUnderOne(ImGuiWindow* under_this_window, ImGuiWind if (window != ignore_window && window->WasActive && !(window->Flags & ImGuiWindowFlags_ChildWindow)) if ((window->Flags & (ImGuiWindowFlags_NoMouseInputs | ImGuiWindowFlags_NoNavInputs)) != (ImGuiWindowFlags_NoMouseInputs | ImGuiWindowFlags_NoNavInputs)) { - // FIXME-DOCKING: This is failing (lagging by one frame) for docked windows. + // FIXME-DOCK: This is failing (lagging by one frame) for docked windows. // If A and B are docked into window and B disappear, at the NewFrame() call site window->NavLastChildNavWindow will still point to B. // We might leverage the tab order implicitly stored in window->DockNodeAsHost->TabBar (essentially the 'most_recently_selected_tab' code in tab bar will do that but on next update) // to tell which is the "previous" window. Or we may leverage 'LastFrameFocused/LastFrameJustFocused' and have this function handle child window itself? @@ -8299,7 +8412,7 @@ void ImGui::EndPopup() g.WithinEndChild = false; } -bool ImGui::OpenPopupOnItemClick(const char* str_id, int mouse_button) +bool ImGui::OpenPopupOnItemClick(const char* str_id, ImGuiMouseButton mouse_button) { ImGuiWindow* window = GImGui->CurrentWindow; if (IsMouseReleased(mouse_button) && IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup)) @@ -8315,7 +8428,7 @@ bool ImGui::OpenPopupOnItemClick(const char* str_id, int mouse_button) // This is a helper to handle the simplest case of associating one named popup to one given widget. // You may want to handle this on user side if you have specific needs (e.g. tweaking IsItemHovered() parameters). // You can pass a NULL str_id to use the identifier of the last item. -bool ImGui::BeginPopupContextItem(const char* str_id, int mouse_button) +bool ImGui::BeginPopupContextItem(const char* str_id, ImGuiMouseButton mouse_button) { ImGuiWindow* window = GImGui->CurrentWindow; if (window->SkipItems) @@ -8327,7 +8440,7 @@ bool ImGui::BeginPopupContextItem(const char* str_id, int mouse_button) return BeginPopupEx(id, ImGuiWindowFlags_AlwaysAutoResize|ImGuiWindowFlags_NoTitleBar|ImGuiWindowFlags_NoSavedSettings); } -bool ImGui::BeginPopupContextWindow(const char* str_id, int mouse_button, bool also_over_items) +bool ImGui::BeginPopupContextWindow(const char* str_id, ImGuiMouseButton mouse_button, bool also_over_items) { if (!str_id) str_id = "window_context"; @@ -8338,7 +8451,7 @@ bool ImGui::BeginPopupContextWindow(const char* str_id, int mouse_button, bool a return BeginPopupEx(id, ImGuiWindowFlags_AlwaysAutoResize|ImGuiWindowFlags_NoTitleBar|ImGuiWindowFlags_NoSavedSettings); } -bool ImGui::BeginPopupContextVoid(const char* str_id, int mouse_button) +bool ImGui::BeginPopupContextVoid(const char* str_id, ImGuiMouseButton mouse_button) { if (!str_id) str_id = "void_context"; @@ -9563,7 +9676,7 @@ bool ImGui::BeginDragDropSource(ImGuiDragDropFlags flags) bool source_drag_active = false; ImGuiID source_id = 0; ImGuiID source_parent_id = 0; - int mouse_button = 0; + ImGuiMouseButton mouse_button = ImGuiMouseButton_Left; if (!(flags & ImGuiDragDropFlags_SourceExtern)) { source_id = window->DC.LastItemId; @@ -11241,7 +11354,7 @@ namespace ImGui static void DockNodeUpdateVisibleFlag(ImGuiDockNode* node); static void DockNodeStartMouseMovingWindow(ImGuiDockNode* node, ImGuiWindow* window); static bool DockNodeIsDropAllowed(ImGuiWindow* host_window, ImGuiWindow* payload_window); - static void DockNodePreviewDockCalc(ImGuiWindow* host_window, ImGuiDockNode* host_node, ImGuiWindow* payload_window, ImGuiDockPreviewData* preview_data, bool is_explicit_target, bool is_outer_docking); + static void DockNodePreviewDockSetup(ImGuiWindow* host_window, ImGuiDockNode* host_node, ImGuiWindow* payload_window, ImGuiDockPreviewData* preview_data, bool is_explicit_target, bool is_outer_docking); static void DockNodePreviewDockRender(ImGuiWindow* host_window, ImGuiDockNode* host_node, ImGuiWindow* payload_window, const ImGuiDockPreviewData* preview_data); static void DockNodeCalcTabBarLayout(const ImGuiDockNode* node, ImRect* out_title_rect, ImRect* out_tab_bar_rect, ImVec2* out_window_menu_button_pos); static void DockNodeCalcSplitRects(ImVec2& pos_old, ImVec2& size_old, ImVec2& pos_new, ImVec2& size_new, ImGuiDir dir, ImVec2 size_new_desired); @@ -11423,7 +11536,7 @@ static ImGuiDockNode* ImGui::DockContextFindNodeByID(ImGuiContext* ctx, ImGuiID ImGuiID ImGui::DockContextGenNodeID(ImGuiContext* ctx) { // Generate an ID for new node (the exact ID value doesn't matter as long as it is not already used) - // FIXME-OPT FIXME-DOCKING: This is suboptimal, even if the node count is small enough not to be a worry. We should poke in ctx->Nodes to find a suitable ID faster. + // FIXME-OPT FIXME-DOCK: This is suboptimal, even if the node count is small enough not to be a worry. We should poke in ctx->Nodes to find a suitable ID faster. ImGuiID id = 0x0001; while (DockContextFindNodeByID(ctx, id) != NULL) id++; @@ -11740,7 +11853,7 @@ void ImGui::DockContextProcessDock(ImGuiContext* ctx, ImGuiDockRequest* req) // We can dock a split payload into a node that already has windows _only_ if our payload is a node tree with a single visible node. // In this situation, we move the windows of the target node into the currently visible node of the payload. // This allows us to preserve some of the underlying dock tree settings nicely. - IM_ASSERT(payload_node->OnlyNodeWithWindows != NULL); // The docking should have been blocked by DockNodePreviewDockCalc() early on and never submitted. + IM_ASSERT(payload_node->OnlyNodeWithWindows != NULL); // The docking should have been blocked by DockNodePreviewDockSetup() early on and never submitted. ImGuiDockNode* visible_node = payload_node->OnlyNodeWithWindows; if (visible_node->TabBar) IM_ASSERT(visible_node->TabBar->Tabs.Size > 0); @@ -11751,7 +11864,7 @@ void ImGui::DockContextProcessDock(ImGuiContext* ctx, ImGuiDockRequest* req) if (node->IsCentralNode()) { // Central node property needs to be moved to a leaf node, pick the last focused one. - // FIXME-DOCKING: If we had to transfer other flags here, what would the policy be? + // FIXME-DOCK: If we had to transfer other flags here, what would the policy be? ImGuiDockNode* last_focused_node = DockContextFindNodeByID(ctx, payload_node->LastFocusedNodeID); IM_ASSERT(last_focused_node != NULL); ImGuiDockNode* last_focused_root_node = DockNodeGetRootNode(last_focused_node); @@ -11847,7 +11960,7 @@ bool ImGui::DockContextCalcDropPosForDocking(ImGuiWindow* target, ImGuiDockNode* else { ImGuiDockPreviewData split_data; - DockNodePreviewDockCalc(target, target_node, payload, &split_data, false, split_outer); + DockNodePreviewDockSetup(target, target_node, payload, &split_data, false, split_outer); if (split_data.DropRectsDraw[split_dir+1].IsInverted()) return false; *out_pos = split_data.DropRectsDraw[split_dir+1].GetCenter(); @@ -11882,7 +11995,7 @@ bool ImGui::DockContextCalcDropPosForDocking(ImGuiWindow* target, ImGuiDockNode* // - DockNodeCalcTabBarLayout() // - DockNodeCalcSplitRects() // - DockNodeCalcDropRectsAndTestMousePos() -// - DockNodePreviewDockCalc() +// - DockNodePreviewDockSetup() // - DockNodePreviewDockRender() //----------------------------------------------------------------------------- @@ -12664,7 +12777,7 @@ static void ImGui::DockNodeUpdateTabBar(ImGuiDockNode* node, ImGuiWindow* host_w const bool has_close_button = (node_flags & ImGuiDockNodeFlags_NoCloseButton) == 0; // In a dock node, the Collapse Button turns into the Window Menu button. - // FIXME-DOCK FIXME-OPT: Could we recycle popups id accross multiple dock nodes? + // FIXME-DOCK FIXME-OPT: Could we recycle popups id across multiple dock nodes? if (has_window_menu_button && IsPopupOpen("#WindowMenu")) { if (ImGuiID tab_id = DockNodeUpdateWindowMenu(node, tab_bar)) @@ -12707,7 +12820,7 @@ static void ImGui::DockNodeUpdateTabBar(ImGuiDockNode* node, ImGuiWindow* host_w int tabs_unsorted_start = tab_bar->Tabs.Size; for (int tab_n = tab_bar->Tabs.Size - 1; tab_n >= 0 && (tab_bar->Tabs[tab_n].Flags & ImGuiTabItemFlags_Unsorted); tab_n--) { - // FIXME-DOCKING: Consider only clearing the flag after the tab has been alive for a few consecutive frames, allowing late comers to not break sorting? + // FIXME-DOCK: Consider only clearing the flag after the tab has been alive for a few consecutive frames, allowing late comers to not break sorting? tab_bar->Tabs[tab_n].Flags &= ~ImGuiTabItemFlags_Unsorted; tabs_unsorted_start = tab_n; } @@ -13007,40 +13120,42 @@ bool ImGui::DockNodeCalcDropRectsAndTestMousePos(const ImRect& parent, ImGuiDir // host_node may be NULL if the window doesn't have a DockNode already. // FIXME-DOCK: This is misnamed since it's also doing the filtering. -static void ImGui::DockNodePreviewDockCalc(ImGuiWindow* host_window, ImGuiDockNode* host_node, ImGuiWindow* root_payload, ImGuiDockPreviewData* data, bool is_explicit_target, bool is_outer_docking) +static void ImGui::DockNodePreviewDockSetup(ImGuiWindow* host_window, ImGuiDockNode* host_node, ImGuiWindow* root_payload, ImGuiDockPreviewData* data, bool is_explicit_target, bool is_outer_docking) { ImGuiContext& g = *GImGui; // There is an edge case when docking into a dockspace which only has inactive nodes. // In this case DockNodeTreeFindNodeByPos() will have selected a leaf node which is inactive. // Because the inactive leaf node doesn't have proper pos/size yet, we'll use the root node as reference. + ImGuiDockNode* root_payload_as_host = root_payload->DockNodeAsHost; ImGuiDockNode* ref_node_for_rect = (host_node && !host_node->IsVisible) ? DockNodeGetRootNode(host_node) : host_node; if (ref_node_for_rect) IM_ASSERT(ref_node_for_rect->IsVisible); - // Build a tentative future node (reuse same structure because it is practical) - data->FutureNode.HasCloseButton = (host_node ? host_node->HasCloseButton : host_window->HasCloseButton) || (root_payload->HasCloseButton); - data->FutureNode.HasWindowMenuButton = host_node ? true : ((host_window->Flags & ImGuiWindowFlags_NoCollapse) == 0); - data->FutureNode.Pos = host_node ? ref_node_for_rect->Pos : host_window->Pos; - data->FutureNode.Size = host_node ? ref_node_for_rect->Size : host_window->Size; - - // Figure out here we are allowed to dock + // Filter, figure out where we are allowed to dock ImGuiDockNodeFlags host_node_flags = host_node ? host_node->GetMergedFlags() : 0; - const bool src_is_visibly_splitted = root_payload->DockNodeAsHost && root_payload->DockNodeAsHost->IsSplitNode() && (root_payload->DockNodeAsHost->OnlyNodeWithWindows == NULL); - data->IsCenterAvailable = !is_outer_docking; - if (src_is_visibly_splitted && (!host_node || !host_node->IsEmpty())) + data->IsCenterAvailable = true; + if (is_outer_docking) data->IsCenterAvailable = false; - if (host_node && (host_node_flags & ImGuiDockNodeFlags_NoDocking)) + else if (host_node && (host_node_flags & ImGuiDockNodeFlags_NoDocking)) data->IsCenterAvailable = false; - if (host_node && (host_node_flags & ImGuiDockNodeFlags_NoDockingInCentralNode) && host_node->IsCentralNode()) + else if (host_node && (host_node_flags & ImGuiDockNodeFlags_NoDockingInCentralNode) && host_node->IsCentralNode()) + data->IsCenterAvailable = false; + else if ((!host_node || !host_node->IsEmpty()) && root_payload_as_host && root_payload_as_host->IsSplitNode() && (root_payload_as_host->OnlyNodeWithWindows == NULL)) // Is _visibly_ split? data->IsCenterAvailable = false; data->IsSidesAvailable = true; if ((host_node && (host_node_flags & ImGuiDockNodeFlags_NoSplit)) || g.IO.ConfigDockingNoSplit) data->IsSidesAvailable = false; - if (!is_outer_docking && host_node && host_node->ParentNode == NULL && host_node->IsCentralNode()) + else if (!is_outer_docking && host_node && host_node->ParentNode == NULL && host_node->IsCentralNode()) data->IsSidesAvailable = false; + // Build a tentative future node (reuse same structure because it is practical. Shape will be readjusted when previewing a split) + data->FutureNode.HasCloseButton = (host_node ? host_node->HasCloseButton : host_window->HasCloseButton) || (root_payload->HasCloseButton); + data->FutureNode.HasWindowMenuButton = host_node ? true : ((host_window->Flags & ImGuiWindowFlags_NoCollapse) == 0); + data->FutureNode.Pos = host_node ? ref_node_for_rect->Pos : host_window->Pos; + data->FutureNode.Size = host_node ? ref_node_for_rect->Size : host_window->Size; + // Calculate drop shapes geometry for allowed splitting directions IM_ASSERT(ImGuiDir_None == -1); data->SplitNode = host_node; @@ -13590,6 +13705,12 @@ void ImGui::DockSpace(ImGuiID id, const ImVec2& size_arg, ImGuiDockNodeFlags fla if (!(g.IO.ConfigFlags & ImGuiConfigFlags_DockingEnable)) return; + // Early out if parent window is hidden/collapsed + // This is faster but also DockNodeUpdateTabBar() relies on TabBarLayout() running (which won't if SkipItems=true) to set NextSelectedTabId = 0). See #2960. + // If for whichever reason this is causing problem we would need to ensure that DockNodeUpdateTabBar() ends up clearing NextSelectedTabId even if SkipItems=true. + if (window->SkipItems) + flags |= ImGuiDockNodeFlags_KeepAliveOnly; + IM_ASSERT((flags & ImGuiDockNodeFlags_DockSpace) == 0); ImGuiDockNode* node = DockContextFindNodeByID(ctx, id); if (!node) @@ -13634,7 +13755,7 @@ void ImGui::DockSpace(ImGuiID id, const ImVec2& size_arg, ImGuiDockNodeFlags fla SetNextWindowSize(node->Size); g.NextWindowData.PosUndock = false; - // FIXME-DOCKING: Why do we need a child window to host a dockspace, could we host it in the existing window? + // FIXME-DOCK Why do we need a child window to host a dockspace, could we host it in the existing window? ImGuiWindowFlags window_flags = ImGuiWindowFlags_ChildWindow | ImGuiWindowFlags_DockNodeHost; window_flags |= ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoTitleBar; window_flags |= ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse; @@ -14353,11 +14474,11 @@ void ImGui::BeginDockableDragDropTarget(ImGuiWindow* window) if (node && (node->ParentNode || node->IsCentralNode())) if (ImGuiDockNode* root_node = DockNodeGetRootNode(node)) { - DockNodePreviewDockCalc(window, root_node, payload_window, &split_outer, is_explicit_target, true); + DockNodePreviewDockSetup(window, root_node, payload_window, &split_outer, is_explicit_target, true); if (split_outer.IsSplitDirExplicit) split_data = &split_outer; } - DockNodePreviewDockCalc(window, node, payload_window, &split_inner, is_explicit_target, false); + DockNodePreviewDockSetup(window, node, payload_window, &split_inner, is_explicit_target, false); if (split_data == &split_outer) split_inner.IsDropAllowed = false; @@ -14561,13 +14682,14 @@ static void ImGui::DockSettingsHandler_WriteAll(ImGuiContext* ctx, ImGuiSettings buf->appendf("%*s", ImMax(2, (line_start_pos + 92) - buf->size()), ""); // Align everything if (node->IsDockSpace() && node->HostWindow && node->HostWindow->ParentWindow) buf->appendf(" ; in '%s'", node->HostWindow->ParentWindow->Name); + // Iterate settings so we can give info about windows that didn't exist during the session. int contains_window = 0; - for (int window_n = 0; window_n < ctx->SettingsWindows.Size; window_n++) // Iterate settings so we can give info about windows that didn't exist during the session. - if (ctx->SettingsWindows[window_n].DockId == node_settings->ID) + for (ImGuiWindowSettings* settings = g.SettingsWindows.begin(); settings != NULL; settings = g.SettingsWindows.next_chunk(settings)) + if (settings->DockId == node_settings->ID) { if (contains_window++ == 0) buf->appendf(" ; contains "); - buf->appendf("'%s' ", ctx->SettingsWindows[window_n].Name); + buf->appendf("'%s' ", settings->GetName()); } } #endif @@ -14809,12 +14931,18 @@ void ImGui::ShowMetricsWindow(bool* p_open) return; } - // State + // Debugging enums enum { WRT_OuterRect, WRT_OuterRectClipped, WRT_InnerRect, WRT_InnerClipRect, WRT_WorkRect, WRT_Content, WRT_ContentRegionRect, WRT_Count }; // Windows Rect Type const char* wrt_rects_names[WRT_Count] = { "OuterRect", "OuterRectClipped", "InnerRect", "InnerClipRect", "WorkRect", "Content", "ContentRegionRect" }; + enum { TRT_OuterRect, TRT_WorkRect, TRT_HostClipRect, TRT_InnerClipRect, TRT_BackgroundClipRect, TRT_ColumnsRect, TRT_ColumnsClipRect, TRT_ColumnsContentHeadersUsed, TRT_ColumnsContentHeadersDesired, TRT_ColumnsContentRowsFrozen, TRT_ColumnsContentRowsUnfrozen, TRT_Count }; // Tables Rect Type + const char* trt_rects_names[TRT_Count] = { "OuterRect", "WorkRect", "HostClipRect", "InnerClipRect", "BackgroundClipRect", "ColumnsRect", "ColumnsClipRect", "ColumnsContentHeadersUsed", "ColumnsContentHeadersDesired", "ColumnsContentRowsFrozen", "ColumnsContentRowsUnfrozen" }; + + // State static bool show_windows_rects = false; static int show_windows_rect_type = WRT_WorkRect; static bool show_windows_begin_order = false; + static bool show_tables_rects = false; + static int show_tables_rect_type = TRT_WorkRect; static bool show_drawcmd_details = true; static bool show_docking_nodes = false; @@ -14829,13 +14957,14 @@ void ImGui::ShowMetricsWindow(bool* p_open) ImGui::Separator(); // Helper functions to display common structures: - // - NodeDrawList - // - NodeColumns - // - NodeWindow - // - NodeWindows - // - NodeViewport - // - NodeDockNode - // - NodeTabBar + // - NodeDrawList() + // - NodeColumns() + // - NodeWindow() + // - NodeWindows() + // - NodeViewport() + // - NodeDockNode() + // - NodeTabBar() + // - NodeStorage() struct Funcs { static ImRect GetWindowRect(ImGuiWindow* window, int rect_type) @@ -14891,7 +15020,7 @@ void ImGui::ShowMetricsWindow(bool* p_open) if (show_drawcmd_details && fg_draw_list && ImGui::IsItemHovered()) { ImRect clip_rect = pcmd->ClipRect; - ImRect vtxs_rect; + ImRect vtxs_rect(FLT_MAX, FLT_MAX, -FLT_MAX, -FLT_MAX); for (unsigned int i = elem_offset; i < elem_offset + (int)pcmd->ElemCount; i++) vtxs_rect.Add(draw_list->VtxBuffer[idx_buffer ? idx_buffer[i] : i].pos); fg_draw_list->AddRect(ImFloor(clip_rect.Min), ImFloor(clip_rect.Max), IM_COL32(255,0,255,255)); @@ -14970,6 +15099,19 @@ void ImGui::ShowMetricsWindow(bool* p_open) ImGui::TreePop(); } + static void NodeWindows(ImVector& windows, const char* label) + { + if (!ImGui::TreeNode(label, "%s (%d)", label, windows.Size)) + return; + for (int i = 0; i < windows.Size; i++) + { + ImGui::PushID(windows[i]); + Funcs::NodeWindow(windows[i], "Window"); + ImGui::PopID(); + } + ImGui::TreePop(); + } + static void NodeWindow(ImGuiWindow* window, const char* label) { if (window == NULL) @@ -14977,7 +15119,7 @@ void ImGui::ShowMetricsWindow(bool* p_open) ImGui::BulletText("%s: NULL", label); return; } - bool open = ImGui::TreeNode(window, "%s '%s', %d @ 0x%p", label, window->Name, (window->Active || window->WasActive), window); + bool open = ImGui::TreeNode(label, "%s '%s', %d @ 0x%p", label, window->Name, (window->Active || window->WasActive), window); if (ImGui::IsItemHovered() && window->WasActive) ImGui::GetForegroundDrawList()->AddRect(window->Pos, window->Pos + window->Size, IM_COL32(255, 255, 0, 255)); if (!open) @@ -15018,15 +15160,6 @@ void ImGui::ShowMetricsWindow(bool* p_open) ImGui::TreePop(); } - static void NodeWindows(ImVector& windows, const char* label) - { - if (!ImGui::TreeNode(label, "%s (%d)", label, windows.Size)) - return; - for (int i = 0; i < windows.Size; i++) - Funcs::NodeWindow(windows[i], "Window"); - ImGui::TreePop(); - } - static void NodeViewport(ImGuiViewportP* viewport) { ImGui::SetNextItemOpen(true, ImGuiCond_Once); @@ -15155,6 +15288,7 @@ void ImGui::ShowMetricsWindow(bool* p_open) ImGui::TreePop(); } + // Details for Popups if (ImGui::TreeNode("Popups", "Popups (%d)", g.OpenPopupStack.Size)) { for (int i = 0; i < g.OpenPopupStack.Size; i++) @@ -15165,6 +15299,7 @@ void ImGui::ShowMetricsWindow(bool* p_open) ImGui::TreePop(); } + // Details for TabBars if (ImGui::TreeNode("TabBars", "Tab Bars (%d)", g.TabBars.GetSize())) { for (int n = 0; n < g.TabBars.GetSize(); n++) @@ -15172,6 +15307,21 @@ void ImGui::ShowMetricsWindow(bool* p_open) ImGui::TreePop(); } + // Details for Tables + IM_UNUSED(trt_rects_names); + IM_UNUSED(show_tables_rects); + IM_UNUSED(show_tables_rect_type); +#ifdef IMGUI_HAS_TABLE + if (ImGui::TreeNode("Tables", "Tables (%d)", g.Tables.GetSize())) + { + for (int n = 0; n < g.Tables.GetSize(); n++) + Funcs::NodeTable(g.Tables.GetByIndex(n)); + ImGui::TreePop(); + } +#endif // #define IMGUI_HAS_TABLE + + // Details for Docking +#ifdef IMGUI_HAS_DOCK if (ImGui::TreeNode("Docking")) { ImGuiDockContext* dc = g.DockContext; @@ -15218,17 +15368,11 @@ void ImGui::ShowMetricsWindow(bool* p_open) } ImGui::TreePop(); } - ImGui::TreePop(); } +#endif // #define IMGUI_HAS_DOCK -#if 0 - if (ImGui::TreeNode("Tables", "Tables (%d)", g.Tables.GetSize())) - { - ImGui::TreePop(); - } -#endif - + // Misc Details if (ImGui::TreeNode("Internal state")) { const char* input_source_names[] = { "None", "Mouse", "Nav", "NavKeyboard", "NavGamepad" }; IM_ASSERT(IM_ARRAYSIZE(input_source_names) == ImGuiInputSource_COUNT); @@ -15251,6 +15395,7 @@ void ImGui::ShowMetricsWindow(bool* p_open) ImGui::TreePop(); } + // Tools if (ImGui::TreeNode("Tools")) { // The Item Picker tool is super useful to visually select an item and break into the call-stack of where it was submitted. @@ -15263,7 +15408,7 @@ void ImGui::ShowMetricsWindow(bool* p_open) ImGui::Checkbox("Show windows rectangles", &show_windows_rects); ImGui::SameLine(); ImGui::SetNextItemWidth(ImGui::GetFontSize() * 12); - show_windows_rects |= ImGui::Combo("##show_windows_rect_type", &show_windows_rect_type, wrt_rects_names, WRT_Count); + show_windows_rects |= ImGui::Combo("##show_windows_rect_type", &show_windows_rect_type, wrt_rects_names, WRT_Count, WRT_Count); if (show_windows_rects && g.NavWindow) { ImGui::BulletText("'%s':", g.NavWindow->Name); @@ -15279,7 +15424,7 @@ void ImGui::ShowMetricsWindow(bool* p_open) ImGui::TreePop(); } - // Tool: Display windows Rectangles and Begin Order + // Overlay: Display windows Rectangles and Begin Order if (show_windows_rects || show_windows_begin_order) { for (int n = 0; n < g.Windows.Size; n++) @@ -15304,6 +15449,19 @@ void ImGui::ShowMetricsWindow(bool* p_open) } } +#ifdef IMGUI_HAS_TABLE + // Overlay: Display Tables Rectangles + if (show_tables_rects) + { + for (int table_n = 0; table_n < g.Tables.GetSize(); table_n++) + { + ImGuiTable* table = g.Tables.GetByIndex(table_n); + } + } +#endif // #define IMGUI_HAS_TABLE + +#ifdef IMGUI_HAS_DOCK + // Overlay: Display Docking info if (show_docking_nodes && g.IO.KeyCtrl) { for (int n = 0; n < g.DockContext->Nodes.Data.Size; n++) @@ -15327,6 +15485,7 @@ void ImGui::ShowMetricsWindow(bool* p_open) overlay_draw_list->AddText(NULL, 0.0f, pos, IM_COL32(255, 255, 255, 255), buf); } } +#endif // #define IMGUI_HAS_DOCK ImGui::End(); } diff --git a/headers/3rdparty/imgui/imgui.h b/headers/3rdparty/imgui/imgui.h index 3766ce53..9922952b 100644 --- a/headers/3rdparty/imgui/imgui.h +++ b/headers/3rdparty/imgui/imgui.h @@ -1,4 +1,4 @@ -// dear imgui, v1.74 +// dear imgui, v1.75 WIP // (headers) // See imgui.cpp file for documentation. @@ -48,8 +48,8 @@ Index of this file: // Version // (Integer encoded as XYYZZ for use in #if preprocessor conditionals. Work in progress versions typically starts at XYY99 then bounce up to XYY00, XYY01 etc. when release tagging happens) -#define IMGUI_VERSION "1.74" -#define IMGUI_VERSION_NUM 17400 +#define IMGUI_VERSION "1.75 WIP" +#define IMGUI_VERSION_NUM 17401 #define IMGUI_CHECKVERSION() ImGui::DebugCheckVersionAndDataLayout(IMGUI_VERSION, sizeof(ImGuiIO), sizeof(ImGuiStyle), sizeof(ImVec2), sizeof(ImVec4), sizeof(ImDrawVert), sizeof(ImDrawIdx)) #define IMGUI_HAS_VIEWPORT 1 // Viewport WIP branch #define IMGUI_HAS_DOCK 1 // Docking WIP branch @@ -145,6 +145,7 @@ typedef int ImGuiDataType; // -> enum ImGuiDataType_ // Enum: A typedef int ImGuiDir; // -> enum ImGuiDir_ // Enum: A cardinal direction typedef int ImGuiKey; // -> enum ImGuiKey_ // Enum: A key identifier (ImGui-side enum) typedef int ImGuiNavInput; // -> enum ImGuiNavInput_ // Enum: An input identifier for navigation +typedef int ImGuiMouseButton; // -> enum ImGuiMouseButton_ // Enum: A mouse button identifier (0=left, 1=right, 2=middle) typedef int ImGuiMouseCursor; // -> enum ImGuiMouseCursor_ // Enum: A mouse cursor identifier typedef int ImGuiStyleVar; // -> enum ImGuiStyleVar_ // Enum: A variable identifier for styling typedef int ImDrawCornerFlags; // -> enum ImDrawCornerFlags_ // Flags: for ImDrawList::AddRect(), AddRectFilled() etc. @@ -445,6 +446,7 @@ namespace ImGui // - Adjust format string to decorate the value with a prefix, a suffix, or adapt the editing and display precision e.g. "%.3f" -> 1.234; "%5.2f secs" -> 01.23 secs; "Biscuit: %.0f" -> Biscuit: 1; etc. // - Speed are per-pixel of mouse movement (v_speed=0.2f: mouse needs to move by 5 pixels to increase value by 1). For gamepad/keyboard navigation, minimum speed is Max(v_speed, minimum_step_at_given_precision). // - Use v_min < v_max to clamp edits to given limits. Note that CTRL+Click manual input can override those limits. + // - Use v_max = FLT_MAX / INT_MAX etc to avoid clamping to a maximum, same with v_min = -FLT_MAX / INT_MIN to avoid clamping to a minimum. // - Use v_min > v_max to lock edits. IMGUI_API bool DragFloat(const char* label, float* v, float v_speed = 1.0f, float v_min = 0.0f, float v_max = 0.0f, const char* format = "%.3f", float power = 1.0f); // If v_min >= v_max we have no bound IMGUI_API bool DragFloat2(const char* label, float v[2], float v_speed = 1.0f, float v_min = 0.0f, float v_max = 0.0f, const char* format = "%.3f", float power = 1.0f); @@ -478,7 +480,7 @@ namespace ImGui IMGUI_API bool VSliderScalar(const char* label, const ImVec2& size, ImGuiDataType data_type, void* p_data, const void* p_min, const void* p_max, const char* format = NULL, float power = 1.0f); // Widgets: Input with Keyboard - // - If you want to use InputText() with a dynamic string type such as std::string or your own, see misc/cpp/imgui_stdlib.h + // - If you want to use InputText() with std::string or any custom dynamic string type, see misc/cpp/imgui_stdlib.h and comments in imgui_demo.cpp. // - Most of the ImGuiInputTextFlags flags are only useful for InputText() and not for InputFloatX, InputIntX, InputDouble etc. IMGUI_API bool InputText(const char* label, char* buf, size_t buf_size, ImGuiInputTextFlags flags = 0, ImGuiInputTextCallback callback = NULL, void* user_data = NULL); IMGUI_API bool InputTextMultiline(const char* label, char* buf, size_t buf_size, const ImVec2& size = ImVec2(0,0), ImGuiInputTextFlags flags = 0, ImGuiInputTextCallback callback = NULL, void* user_data = NULL); @@ -577,22 +579,24 @@ namespace ImGui // - Unless modal, they can be closed by clicking anywhere outside them, or by pressing ESCAPE. // - Their visibility state (~bool) is held internally by imgui instead of being held by the programmer as we are used to with regular Begin() calls. // User can manipulate the visibility state by calling OpenPopup(). + // - We default to use the right mouse (ImGuiMouseButton_Right=1) for the Popup Context functions. // (*) You can use IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup) to bypass it and detect hovering even when normally blocked by a popup. // Those three properties are connected. The library needs to hold their visibility state because it can close popups at any time. IMGUI_API void OpenPopup(const char* str_id); // call to mark popup as open (don't call every frame!). popups are closed when user click outside, or if CloseCurrentPopup() is called within a BeginPopup()/EndPopup() block. By default, Selectable()/MenuItem() are calling CloseCurrentPopup(). Popup identifiers are relative to the current ID-stack (so OpenPopup and BeginPopup needs to be at the same level). IMGUI_API bool BeginPopup(const char* str_id, ImGuiWindowFlags flags = 0); // return true if the popup is open, and you can start outputting to it. only call EndPopup() if BeginPopup() returns true! - IMGUI_API bool BeginPopupContextItem(const char* str_id = NULL, int mouse_button = 1); // helper to open and begin popup when clicked on last item. if you can pass a NULL str_id only if the previous item had an id. If you want to use that on a non-interactive item such as Text() you need to pass in an explicit ID here. read comments in .cpp! - IMGUI_API bool BeginPopupContextWindow(const char* str_id = NULL, int mouse_button = 1, bool also_over_items = true); // helper to open and begin popup when clicked on current window. - IMGUI_API bool BeginPopupContextVoid(const char* str_id = NULL, int mouse_button = 1); // helper to open and begin popup when clicked in void (where there are no imgui windows). + IMGUI_API bool BeginPopupContextItem(const char* str_id = NULL, ImGuiMouseButton mouse_button = 1); // helper to open and begin popup when clicked on last item. if you can pass a NULL str_id only if the previous item had an id. If you want to use that on a non-interactive item such as Text() you need to pass in an explicit ID here. read comments in .cpp! + IMGUI_API bool BeginPopupContextWindow(const char* str_id = NULL, ImGuiMouseButton mouse_button = 1, bool also_over_items = true); // helper to open and begin popup when clicked on current window. + IMGUI_API bool BeginPopupContextVoid(const char* str_id = NULL, ImGuiMouseButton mouse_button = 1); // helper to open and begin popup when clicked in void (where there are no imgui windows). IMGUI_API bool BeginPopupModal(const char* name, bool* p_open = NULL, ImGuiWindowFlags flags = 0); // modal dialog (regular window with title bar, block interactions behind the modal window, can't close the modal window by clicking outside) IMGUI_API void EndPopup(); // only call EndPopup() if BeginPopupXXX() returns true! - IMGUI_API bool OpenPopupOnItemClick(const char* str_id = NULL, int mouse_button = 1); // helper to open popup when clicked on last item (note: actually triggers on the mouse _released_ event to be consistent with popup behaviors). return true when just opened. + IMGUI_API bool OpenPopupOnItemClick(const char* str_id = NULL, ImGuiMouseButton mouse_button = 1); // helper to open popup when clicked on last item (note: actually triggers on the mouse _released_ event to be consistent with popup behaviors). return true when just opened. IMGUI_API bool IsPopupOpen(const char* str_id); // return true if the popup is open at the current begin-ed level of the popup stack. IMGUI_API void CloseCurrentPopup(); // close the popup we have begin-ed into. clicking on a MenuItem or Selectable automatically close the current popup. // Columns // - You can also use SameLine(pos_x) to mimic simplified columns. // - The columns API is work-in-progress and rather lacking (columns are arguably the worst part of dear imgui at the moment!) + // - There is a maximum of 64 columns. // - By end of the 2019 we will expose a new 'Table' api which will replace columns. IMGUI_API void Columns(int count = 1, const char* id = NULL, bool border = true); IMGUI_API void NextColumn(); // next column, defaults to current row or next row if the current row is finished @@ -660,7 +664,7 @@ namespace ImGui IMGUI_API bool IsItemHovered(ImGuiHoveredFlags flags = 0); // is the last item hovered? (and usable, aka not blocked by a popup, etc.). See ImGuiHoveredFlags for more options. IMGUI_API bool IsItemActive(); // is the last item active? (e.g. button being held, text field being edited. This will continuously return true while holding mouse button on an item. Items that don't interact will always return false) IMGUI_API bool IsItemFocused(); // is the last item focused for keyboard/gamepad navigation? - IMGUI_API bool IsItemClicked(int mouse_button = 0); // is the last item clicked? (e.g. button/node just clicked on) == IsMouseClicked(mouse_button) && IsItemHovered() + IMGUI_API bool IsItemClicked(ImGuiMouseButton mouse_button = 0); // is the last item clicked? (e.g. button/node just clicked on) == IsMouseClicked(mouse_button) && IsItemHovered() IMGUI_API bool IsItemVisible(); // is the last item visible? (items may be out of sight because of clipping/scrolling) IMGUI_API bool IsItemEdited(); // did the last item modify its underlying value this frame? or was pressed? This is generally the same as the "bool" return value of many widgets. IMGUI_API bool IsItemActivated(); // was the last item just made active (item was previously inactive). @@ -699,27 +703,34 @@ namespace ImGui IMGUI_API void ColorConvertRGBtoHSV(float r, float g, float b, float& out_h, float& out_s, float& out_v); IMGUI_API void ColorConvertHSVtoRGB(float h, float s, float v, float& out_r, float& out_g, float& out_b); - // Inputs Utilities + // Inputs Utilities: Keyboard + // - For 'int user_key_index' you can use your own indices/enums according to how your backend/engine stored them in io.KeysDown[]. + // - We don't know the meaning of those value. You can use GetKeyIndex() to map a ImGuiKey_ value into the user index. IMGUI_API int GetKeyIndex(ImGuiKey imgui_key); // map ImGuiKey_* values into user's key index. == io.KeyMap[key] - IMGUI_API bool IsKeyDown(int user_key_index); // is key being held. == io.KeysDown[user_key_index]. note that imgui doesn't know the semantic of each entry of io.KeysDown[]. Use your own indices/enums according to how your backend/engine stored them into io.KeysDown[]! - IMGUI_API bool IsKeyPressed(int user_key_index, bool repeat = true); // was key pressed (went from !Down to Down). if repeat=true, uses io.KeyRepeatDelay / KeyRepeatRate - IMGUI_API bool IsKeyReleased(int user_key_index); // was key released (went from Down to !Down).. + IMGUI_API bool IsKeyDown(int user_key_index); // is key being held. == io.KeysDown[user_key_index]. + IMGUI_API bool IsKeyPressed(int user_key_index, bool repeat = true); // was key pressed (went from !Down to Down)? if repeat=true, uses io.KeyRepeatDelay / KeyRepeatRate + IMGUI_API bool IsKeyReleased(int user_key_index); // was key released (went from Down to !Down)? IMGUI_API int GetKeyPressedAmount(int key_index, float repeat_delay, float rate); // uses provided repeat rate/delay. return a count, most often 0 or 1 but might be >1 if RepeatRate is small enough that DeltaTime > RepeatRate - IMGUI_API bool IsMouseDown(int button); // is mouse button held (0=left, 1=right, 2=middle) - IMGUI_API bool IsAnyMouseDown(); // is any mouse button held - IMGUI_API bool IsMouseClicked(int button, bool repeat = false); // did mouse button clicked (went from !Down to Down) (0=left, 1=right, 2=middle) - IMGUI_API bool IsMouseDoubleClicked(int button); // did mouse button double-clicked. a double-click returns false in IsMouseClicked(). uses io.MouseDoubleClickTime. - IMGUI_API bool IsMouseReleased(int button); // did mouse button released (went from Down to !Down) - IMGUI_API bool IsMouseDragging(int button = 0, float lock_threshold = -1.0f); // is mouse dragging. if lock_threshold < -1.0f uses io.MouseDraggingThreshold - IMGUI_API bool IsMouseHoveringRect(const ImVec2& r_min, const ImVec2& r_max, bool clip = true); // is mouse hovering given bounding rect (in screen space). clipped by current clipping settings, but disregarding of other consideration of focus/window ordering/popup-block. - IMGUI_API bool IsMousePosValid(const ImVec2* mouse_pos = NULL); // by convention we use (-FLT_MAX,-FLT_MAX) to denote that there is no mouse - IMGUI_API ImVec2 GetMousePos(); // shortcut to ImGui::GetIO().MousePos provided by user, to be consistent with other calls - IMGUI_API ImVec2 GetMousePosOnOpeningCurrentPopup(); // retrieve backup of mouse position at the time of opening popup we have BeginPopup() into - IMGUI_API ImVec2 GetMouseDragDelta(int button = 0, float lock_threshold = -1.0f); // return the delta from the initial clicking position while the mouse button is pressed or was just released. This is locked and return 0.0f until the mouse moves past a distance threshold at least once. If lock_threshold < -1.0f uses io.MouseDraggingThreshold. - IMGUI_API void ResetMouseDragDelta(int button = 0); // - IMGUI_API ImGuiMouseCursor GetMouseCursor(); // get desired cursor type, reset in ImGui::NewFrame(), this is updated during the frame. valid before Render(). If you use software rendering by setting io.MouseDrawCursor ImGui will render those for you - IMGUI_API void SetMouseCursor(ImGuiMouseCursor type); // set desired cursor type IMGUI_API void CaptureKeyboardFromApp(bool want_capture_keyboard_value = true); // attention: misleading name! manually override io.WantCaptureKeyboard flag next frame (said flag is entirely left for your application to handle). e.g. force capture keyboard when your widget is being hovered. This is equivalent to setting "io.WantCaptureKeyboard = want_capture_keyboard_value"; after the next NewFrame() call. + + // Inputs Utilities: Mouse + // - To refer to a mouse button, you may use named enums in your code e.g. ImGuiMouseButton_Left, ImGuiMouseButton_Right. + // - You can also use regular integer: it is forever guaranteed that 0=Left, 1=Right, 2=Middle. + // - Dragging operations are only reported after mouse has moved a certain distance away from the initial clicking position (see 'lock_threshold' and 'io.MouseDraggingThreshold') + IMGUI_API bool IsMouseDown(ImGuiMouseButton button); // is mouse button held? + IMGUI_API bool IsMouseClicked(ImGuiMouseButton button, bool repeat = false); // did mouse button clicked? (went from !Down to Down) + IMGUI_API bool IsMouseReleased(ImGuiMouseButton button); // did mouse button released? (went from Down to !Down) + IMGUI_API bool IsMouseDoubleClicked(ImGuiMouseButton button); // did mouse button double-clicked? a double-click returns false in IsMouseClicked(). uses io.MouseDoubleClickTime. + IMGUI_API bool IsMouseHoveringRect(const ImVec2& r_min, const ImVec2& r_max, bool clip = true);// is mouse hovering given bounding rect (in screen space). clipped by current clipping settings, but disregarding of other consideration of focus/window ordering/popup-block. + IMGUI_API bool IsMousePosValid(const ImVec2* mouse_pos = NULL); // by convention we use (-FLT_MAX,-FLT_MAX) to denote that there is no mouse available + IMGUI_API bool IsAnyMouseDown(); // is any mouse button held? + IMGUI_API ImVec2 GetMousePos(); // shortcut to ImGui::GetIO().MousePos provided by user, to be consistent with other calls + IMGUI_API ImVec2 GetMousePosOnOpeningCurrentPopup(); // retrieve mouse position at the time of opening popup we have BeginPopup() into (helper to avoid user backing that value themselves) + IMGUI_API bool IsMouseDragging(ImGuiMouseButton button, float lock_threshold = -1.0f); // is mouse dragging? (if lock_threshold < -1.0f, uses io.MouseDraggingThreshold) + IMGUI_API ImVec2 GetMouseDragDelta(ImGuiMouseButton button = 0, float lock_threshold = -1.0f); // return the delta from the initial clicking position while the mouse button is pressed or was just released. This is locked and return 0.0f until the mouse moves past a distance threshold at least once (if lock_threshold < -1.0f, uses io.MouseDraggingThreshold) + IMGUI_API void ResetMouseDragDelta(ImGuiMouseButton button = 0); // + IMGUI_API ImGuiMouseCursor GetMouseCursor(); // get desired cursor type, reset in ImGui::NewFrame(), this is updated during the frame. valid before Render(). If you use software rendering by setting io.MouseDrawCursor ImGui will render those for you + IMGUI_API void SetMouseCursor(ImGuiMouseCursor cursor_type); // set desired cursor type IMGUI_API void CaptureMouseFromApp(bool want_capture_mouse_value = true); // attention: misleading name! manually override io.WantCaptureMouse flag next frame (said flag is entirely left for your application to handle). This is equivalent to setting "io.WantCaptureMouse = want_capture_mouse_value;" after the next NewFrame() call. // Clipboard Utilities (also see the LogToClipboard() function to capture or output text data to the clipboard) @@ -797,8 +808,8 @@ enum ImGuiWindowFlags_ ImGuiWindowFlags_DockNodeHost = 1 << 29 // Don't use! For internal use by Begin()/NewFrame() // [Obsolete] - //ImGuiWindowFlags_ShowBorders = 1 << 7, // --> Set style.FrameBorderSize=1.0f / style.WindowBorderSize=1.0f to enable borders around windows and items - //ImGuiWindowFlags_ResizeFromAnySide = 1 << 17, // --> Set io.ConfigWindowsResizeFromEdges and make sure mouse cursors are supported by back-end (io.BackendFlags & ImGuiBackendFlags_HasMouseCursors) + //ImGuiWindowFlags_ShowBorders = 1 << 7, // --> Set style.FrameBorderSize=1.0f or style.WindowBorderSize=1.0f to enable borders around items or windows. + //ImGuiWindowFlags_ResizeFromAnySide = 1 << 17, // --> Set io.ConfigWindowsResizeFromEdges=true and make sure mouse cursors are supported by back-end (io.BackendFlags & ImGuiBackendFlags_HasMouseCursors) }; // Flags for ImGui::InputText() @@ -849,11 +860,6 @@ enum ImGuiTreeNodeFlags_ ImGuiTreeNodeFlags_NavLeftJumpsBackHere = 1 << 13, // (WIP) Nav: left direction may move to this TreeNode() from any of its child (items submitted between TreeNode and TreePop) //ImGuiTreeNodeFlags_NoScrollOnOpen = 1 << 14, // FIXME: TODO: Disable automatic scroll on TreePop() if node got just open and contents is not visible ImGuiTreeNodeFlags_CollapsingHeader = ImGuiTreeNodeFlags_Framed | ImGuiTreeNodeFlags_NoTreePushOnOpen | ImGuiTreeNodeFlags_NoAutoOpenOnLog - - // Obsolete names (will be removed) -#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS - , ImGuiTreeNodeFlags_AllowOverlapMode = ImGuiTreeNodeFlags_AllowItemOverlap // [renamed in 1.53] -#endif }; // Flags for ImGui::Selectable() @@ -1160,9 +1166,7 @@ enum ImGuiCol_ // Obsolete names (will be removed) #ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS , ImGuiCol_ModalWindowDarkening = ImGuiCol_ModalWindowDimBg // [renamed in 1.63] - , ImGuiCol_ChildWindowBg = ImGuiCol_ChildBg // [renamed in 1.53] - //ImGuiCol_CloseButton, ImGuiCol_CloseButtonActive, ImGuiCol_CloseButtonHovered, // [unused since 1.60+] the close button now uses regular button colors. - //ImGuiCol_ComboBg, // [unused since 1.53+] ComboBg has been merged with PopupBg, so a redirect isn't accurate. + //, ImGuiCol_CloseButton, ImGuiCol_CloseButtonActive, ImGuiCol_CloseButtonHovered// [unused since 1.60+] the close button now uses regular button colors. #endif }; @@ -1199,8 +1203,7 @@ enum ImGuiStyleVar_ // Obsolete names (will be removed) #ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS - , ImGuiStyleVar_Count_ = ImGuiStyleVar_COUNT // [renamed in 1.60] - , ImGuiStyleVar_ChildWindowRounding = ImGuiStyleVar_ChildRounding // [renamed in 1.53] + , ImGuiStyleVar_Count_ = ImGuiStyleVar_COUNT // [renamed in 1.60] #endif }; @@ -1249,6 +1252,16 @@ enum ImGuiColorEditFlags_ #endif }; +// Identify a mouse button. +// Those values are guaranteed to be stable and we frequently use 0/1 directly. Named enums provided for convenience. +enum ImGuiMouseButton_ +{ + ImGuiMouseButton_Left = 0, + ImGuiMouseButton_Right = 1, + ImGuiMouseButton_Middle = 2, + ImGuiMouseButton_COUNT = 5 +}; + // Enumeration for GetMouseCursor() // User code may request binding to display given cursor by calling SetMouseCursor(), which is why we have some cursors that are marked unused here enum ImGuiMouseCursor_ @@ -1262,6 +1275,7 @@ enum ImGuiMouseCursor_ ImGuiMouseCursor_ResizeNESW, // When hovering over the bottom-left corner of a window ImGuiMouseCursor_ResizeNWSE, // When hovering over the bottom-right corner of a window ImGuiMouseCursor_Hand, // (Unused by Dear ImGui functions. Use for e.g. hyperlinks) + ImGuiMouseCursor_NotAllowed, // When hovering something with disallowed interaction. Usually a crossed circle. ImGuiMouseCursor_COUNT // Obsolete names (will be removed) @@ -1270,7 +1284,7 @@ enum ImGuiMouseCursor_ #endif }; -// Enumateration for ImGui::SetWindow***(), SetNextWindow***(), SetNextItem***() functions +// Enumeration for ImGui::SetWindow***(), SetNextWindow***(), SetNextItem***() functions // Represent a condition. // Important: Treat as a regular enum! Do NOT combine multiple values using binary operators! All the functions above treat 0 as a shortcut to ImGuiCond_Always. enum ImGuiCond_ @@ -1347,7 +1361,7 @@ struct ImVector inline int _grow_capacity(int sz) const { int new_capacity = Capacity ? (Capacity + Capacity/2) : 8; return new_capacity > sz ? new_capacity : sz; } inline void resize(int new_size) { if (new_size > Capacity) reserve(_grow_capacity(new_size)); Size = new_size; } inline void resize(int new_size, const T& v) { if (new_size > Capacity) reserve(_grow_capacity(new_size)); if (new_size > Size) for (int n = Size; n < new_size; n++) memcpy(&Data[n], &v, sizeof(v)); Size = new_size; } - inline void shrink(int new_size) { IM_ASSERT(new_size <= Size); Size = new_size; } + inline void shrink(int new_size) { IM_ASSERT(new_size <= Size); Size = new_size; } // Resize a vector to a smaller size, guaranteed not to cause a reallocation inline void reserve(int new_capacity) { if (new_capacity <= Capacity) return; T* new_data = (T*)IM_ALLOC((size_t)new_capacity * sizeof(T)); if (Data) { memcpy(new_data, Data, (size_t)Size * sizeof(T)); IM_FREE(Data); } Data = new_data; Capacity = new_capacity; } // NB: It is illegal to call push_back/push_front/insert with a reference pointing inside the ImVector data itself! e.g. v.push_back(v[10]) is forbidden. @@ -1476,9 +1490,9 @@ struct ImGuiIO // Optional: Platform/Renderer back-end name (informational only! will be displayed in About Window) + User data for back-end/wrappers to store their own stuff. const char* BackendPlatformName; // = NULL const char* BackendRendererName; // = NULL - void* BackendPlatformUserData; // = NULL - void* BackendRendererUserData; // = NULL - void* BackendLanguageUserData; // = NULL + void* BackendPlatformUserData; // = NULL // User data for platform back-end + void* BackendRendererUserData; // = NULL // User data for renderer back-end + void* BackendLanguageUserData; // = NULL // User data for non C++ programming language back-end // Optional: Access OS clipboard // (default to use native Win32 clipboard on Windows, otherwise uses a private clipboard. Override to access OS clipboard on other architectures) @@ -1536,7 +1550,7 @@ struct ImGuiIO ImVec2 MouseDelta; // Mouse delta. Note that this is zero if either current or previous position are invalid (-FLT_MAX,-FLT_MAX), so a disappearing/reappearing mouse won't have a huge delta. //------------------------------------------------------------------ - // [Internal] ImGui will maintain those fields. Forward compatibility not guaranteed! + // [Internal] Dear ImGui will maintain those fields. Forward compatibility not guaranteed! //------------------------------------------------------------------ ImVec2 MousePosPrev; // Previous mouse position (note that MouseDelta is not necessary == MousePos-MousePosPrev, in case either position is invalid) @@ -1679,12 +1693,6 @@ namespace ImGui static inline bool IsAnyWindowFocused() { return IsWindowFocused(ImGuiFocusedFlags_AnyWindow); } static inline bool IsAnyWindowHovered() { return IsWindowHovered(ImGuiHoveredFlags_AnyWindow); } static inline ImVec2 CalcItemRectClosestPoint(const ImVec2& pos, bool on_edge = false, float outward = 0.f) { IM_UNUSED(on_edge); IM_UNUSED(outward); IM_ASSERT(0); return pos; } - // OBSOLETED in 1.53 (between Oct 2017 and Dec 2017) - static inline void ShowTestWindow() { return ShowDemoWindow(); } - static inline bool IsRootWindowFocused() { return IsWindowFocused(ImGuiFocusedFlags_RootWindow); } - static inline bool IsRootWindowOrAnyChildFocused() { return IsWindowFocused(ImGuiFocusedFlags_RootAndChildWindows); } - static inline void SetNextWindowContentWidth(float w) { SetNextWindowContentSize(ImVec2(w, 0.0f)); } - static inline float GetItemsLineHeightWithSpacing() { return GetFrameHeightWithSpacing(); } } typedef ImGuiInputTextCallback ImGuiTextEditCallback; // OBSOLETED in 1.63 (from Aug 2018): made the names consistent typedef ImGuiInputTextCallbackData ImGuiTextEditCallbackData; @@ -1816,9 +1824,13 @@ struct ImGuiStorage // - Step 3: the clipper validate that we have reached the expected Y position (corresponding to element DisplayEnd), advance the cursor to the end of the list and then returns 'false' to end the loop. struct ImGuiListClipper { - float StartPosY; + int DisplayStart, DisplayEnd; + int ItemsCount; + + // [Internal] + int StepNo; float ItemsHeight; - int ItemsCount, StepNo, DisplayStart, DisplayEnd; + float StartPosY; // items_count: Use -1 to ignore (you can call Begin later). Use INT_MAX if you don't know how many items you have (in which case the cursor won't be advanced in the final step). // items_height: Use -1.0f to be calculated automatically on first step. Otherwise pass in the distance between your items, typically GetTextLineHeightWithSpacing() or GetFrameHeightWithSpacing(). @@ -2029,11 +2041,13 @@ struct ImDrawList IMGUI_API void AddTriangleFilled(const ImVec2& p1, const ImVec2& p2, const ImVec2& p3, ImU32 col); IMGUI_API void AddCircle(const ImVec2& center, float radius, ImU32 col, int num_segments = 12, float thickness = 1.0f); IMGUI_API void AddCircleFilled(const ImVec2& center, float radius, ImU32 col, int num_segments = 12); + IMGUI_API void AddNgon(const ImVec2& center, float radius, ImU32 col, int num_segments, float thickness = 1.0f); + IMGUI_API void AddNgonFilled(const ImVec2& center, float radius, ImU32 col, int num_segments); IMGUI_API void AddText(const ImVec2& pos, ImU32 col, const char* text_begin, const char* text_end = NULL); IMGUI_API void AddText(const ImFont* font, float font_size, const ImVec2& pos, ImU32 col, const char* text_begin, const char* text_end = NULL, float wrap_width = 0.0f, const ImVec4* cpu_fine_clip_rect = NULL); IMGUI_API void AddPolyline(const ImVec2* points, int num_points, ImU32 col, bool closed, float thickness); IMGUI_API void AddConvexPolyFilled(const ImVec2* points, int num_points, ImU32 col); // Note: Anti-aliased filling requires points to be in clockwise order. - IMGUI_API void AddBezierCurve(const ImVec2& pos0, const ImVec2& cp0, const ImVec2& cp1, const ImVec2& pos1, ImU32 col, float thickness, int num_segments = 0); + IMGUI_API void AddBezierCurve(const ImVec2& p1, const ImVec2& p2, const ImVec2& p3, const ImVec2& p4, ImU32 col, float thickness, int num_segments = 0); // Image primitives // - Read FAQ to understand what ImTextureID is. @@ -2051,7 +2065,7 @@ struct ImDrawList inline void PathStroke(ImU32 col, bool closed, float thickness = 1.0f) { AddPolyline(_Path.Data, _Path.Size, col, closed, thickness); _Path.Size = 0; } IMGUI_API void PathArcTo(const ImVec2& center, float radius, float a_min, float a_max, int num_segments = 10); IMGUI_API void PathArcToFast(const ImVec2& center, float radius, int a_min_of_12, int a_max_of_12); // Use precomputed angles for a 12 steps circle - IMGUI_API void PathBezierCurveTo(const ImVec2& p1, const ImVec2& p2, const ImVec2& p3, int num_segments = 0); + IMGUI_API void PathBezierCurveTo(const ImVec2& p2, const ImVec2& p3, const ImVec2& p4, int num_segments = 0); IMGUI_API void PathRect(const ImVec2& rect_min, const ImVec2& rect_max, float rounding = 0.0f, ImDrawCornerFlags rounding_corners = ImDrawCornerFlags_All); // Advanced @@ -2071,6 +2085,7 @@ struct ImDrawList IMGUI_API void Clear(); IMGUI_API void ClearFreeMemory(); IMGUI_API void PrimReserve(int idx_count, int vtx_count); + IMGUI_API void PrimUnreserve(int idx_count, int vtx_count); IMGUI_API void PrimRect(const ImVec2& a, const ImVec2& b, ImU32 col); // Axis aligned rectangle (composed of two triangles) IMGUI_API void PrimRectUV(const ImVec2& a, const ImVec2& b, const ImVec2& uv_a, const ImVec2& uv_b, ImU32 col); IMGUI_API void PrimQuadUV(const ImVec2& a, const ImVec2& b, const ImVec2& c, const ImVec2& d, const ImVec2& uv_a, const ImVec2& uv_b, const ImVec2& uv_c, const ImVec2& uv_d, ImU32 col); diff --git a/headers/3rdparty/imgui/imgui_demo.cpp b/headers/3rdparty/imgui/imgui_demo.cpp index 450bd11b..ba24e906 100644 --- a/headers/3rdparty/imgui/imgui_demo.cpp +++ b/headers/3rdparty/imgui/imgui_demo.cpp @@ -1,4 +1,4 @@ -// dear imgui, v1.74 +// dear imgui, v1.75 WIP // (demo code) // Message to the person tempted to delete this file when integrating Dear ImGui into their code base: @@ -116,10 +116,6 @@ Index of this file: // [SECTION] Forward Declarations, Helpers //----------------------------------------------------------------------------- -#if !defined(IMGUI_DISABLE_OBSOLETE_FUNCTIONS) && defined(IMGUI_DISABLE_TEST_WINDOWS) && !defined(IMGUI_DISABLE_DEMO_WINDOWS) // Obsolete name since 1.53, TEST->DEMO -#define IMGUI_DISABLE_DEMO_WINDOWS -#endif - #if !defined(IMGUI_DISABLE_DEMO_WINDOWS) // Forward Declarations @@ -573,6 +569,8 @@ static void ShowDemoWindowWidgets() } { + // To wire InputText() with std::string or any other custom string type, + // see the "Text Input > Resize Callback" section of this demo, and the misc/cpp/imgui_stdlib.h file. static char str0[128] = "Hello, world!"; ImGui::InputText("input text", str0, IM_ARRAYSIZE(str0)); ImGui::SameLine(); HelpMarker("USER:\nHold SHIFT or use mouse to select text.\n" "CTRL+Left/Right to word jump.\n" "CTRL+A or double-click to select all.\n" "CTRL+X,CTRL+C,CTRL+V clipboard.\n" "CTRL+Z,CTRL+Y undo/redo.\n" "ESCAPE to revert.\n\nPROGRAMMER:\nYou can use the ImGuiInputTextFlags_CallbackResize facility if you need to wire InputText() to a dynamic string type. See misc/cpp/imgui_stdlib.h for an example (this is not demonstrated in imgui_demo.cpp)."); @@ -1048,6 +1046,8 @@ static void ShowDemoWindowWidgets() ImGui::TreePop(); } + // To wire InputText() with std::string or any other custom string type, + // see the "Text Input > Resize Callback" section of this demo, and the misc/cpp/imgui_stdlib.h file. if (ImGui::TreeNode("Text Input")) { if (ImGui::TreeNode("Multi-line Text Input")) @@ -1067,7 +1067,7 @@ static void ShowDemoWindowWidgets() "\tlock cmpxchg8b eax\n"; static ImGuiInputTextFlags flags = ImGuiInputTextFlags_AllowTabInput; - HelpMarker("You can use the ImGuiInputTextFlags_CallbackResize facility if you need to wire InputTextMultiline() to a dynamic string type. See misc/cpp/imgui_stdlib.h for an example. (This is not demonstrated in imgui_demo.cpp)"); + HelpMarker("You can use the ImGuiInputTextFlags_CallbackResize facility if you need to wire InputTextMultiline() to a dynamic string type. See misc/cpp/imgui_stdlib.h for an example. (This is not demonstrated in imgui_demo.cpp because we don't want to include in here)"); ImGui::CheckboxFlags("ImGuiInputTextFlags_ReadOnly", (unsigned int*)&flags, ImGuiInputTextFlags_ReadOnly); ImGui::CheckboxFlags("ImGuiInputTextFlags_AllowTabInput", (unsigned int*)&flags, ImGuiInputTextFlags_AllowTabInput); ImGui::CheckboxFlags("ImGuiInputTextFlags_CtrlEnterForNewLine", (unsigned int*)&flags, ImGuiInputTextFlags_CtrlEnterForNewLine); @@ -1096,8 +1096,9 @@ static void ShowDemoWindowWidgets() if (ImGui::TreeNode("Resize Callback")) { - // If you have a custom string type you would typically create a ImGui::InputText() wrapper than takes your type as input. - // See misc/cpp/imgui_stdlib.h and .cpp for an implementation of this using std::string. + // To wire InputText() with std::string or any other custom string type, + // you can use the ImGuiInputTextFlags_CallbackResize flag + create a custom ImGui::InputText() wrapper using your prefered type. + // See misc/cpp/imgui_stdlib.h for an implementation of this using std::string. HelpMarker("Demonstrate using ImGuiInputTextFlags_CallbackResize to wire your resizable string type to InputText().\n\nSee misc/cpp/imgui_stdlib.h for an implementation of this for std::string."); struct Funcs { @@ -2085,7 +2086,7 @@ static void ShowDemoWindowLayout() if (ImGui::BeginTabBar("MyTabBar", tab_bar_flags)) { for (int n = 0; n < IM_ARRAYSIZE(opened); n++) - if (opened[n] && ImGui::BeginTabItem(names[n], &opened[n])) + if (opened[n] && ImGui::BeginTabItem(names[n], &opened[n], ImGuiTabItemFlags_None)) { ImGui::Text("This is the %s tab!", names[n]); if (n & 1) @@ -2263,10 +2264,10 @@ static void ShowDemoWindowLayout() ImGui::SameLine(140); enable_track |= ImGui::DragInt("##item", &track_item, 0.25f, 0, 99, "Item = %d"); bool scroll_to_off = ImGui::Button("Scroll Offset"); - ImGui::SameLine(140); scroll_to_off |= ImGui::DragFloat("##off", &scroll_to_off_px, 1.00f, 0, 9999, "+%.0f px"); + ImGui::SameLine(140); scroll_to_off |= ImGui::DragFloat("##off", &scroll_to_off_px, 1.00f, 0, FLT_MAX, "+%.0f px"); bool scroll_to_pos = ImGui::Button("Scroll To Pos"); - ImGui::SameLine(140); scroll_to_pos |= ImGui::DragFloat("##pos", &scroll_to_pos_px, 1.00f, -10, 9999, "X/Y = %.0f px"); + ImGui::SameLine(140); scroll_to_pos |= ImGui::DragFloat("##pos", &scroll_to_pos_px, 1.00f, -10, FLT_MAX, "X/Y = %.0f px"); ImGui::PopItemWidth(); if (scroll_to_off || scroll_to_pos) @@ -2503,7 +2504,7 @@ static void ShowDemoWindowLayout() ImVec2 pos = ImGui::GetCursorScreenPos(); ImVec4 clip_rect(pos.x, pos.y, pos.x + size.x, pos.y + size.y); ImGui::InvisibleButton("##dummy", size); - if (ImGui::IsItemActive() && ImGui::IsMouseDragging()) { offset.x += ImGui::GetIO().MouseDelta.x; offset.y += ImGui::GetIO().MouseDelta.y; } + if (ImGui::IsItemActive() && ImGui::IsMouseDragging(0)) { offset.x += ImGui::GetIO().MouseDelta.x; offset.y += ImGui::GetIO().MouseDelta.y; } ImGui::GetWindowDrawList()->AddRectFilled(pos, ImVec2(pos.x + size.x, pos.y + size.y), IM_COL32(90, 90, 120, 255)); ImGui::GetWindowDrawList()->AddText(ImGui::GetFont(), ImGui::GetFontSize()*2.0f, ImVec2(pos.x + offset.x, pos.y + offset.y), IM_COL32(255, 255, 255, 255), "Line 1 hello\nLine 2 clip me!", NULL, 0.0f, &clip_rect); ImGui::TreePop(); @@ -3109,7 +3110,7 @@ static void ShowDemoWindowMisc() if (ImGui::TreeNode("Mouse cursors")) { - const char* mouse_cursors_names[] = { "Arrow", "TextInput", "Move", "ResizeNS", "ResizeEW", "ResizeNESW", "ResizeNWSE", "Hand" }; + const char* mouse_cursors_names[] = { "Arrow", "TextInput", "ResizeAll", "ResizeNS", "ResizeEW", "ResizeNESW", "ResizeNWSE", "Hand", "NotAllowed" }; IM_ASSERT(IM_ARRAYSIZE(mouse_cursors_names) == ImGuiMouseCursor_COUNT); ImGui::Text("Current mouse cursor = %d: %s", ImGui::GetMouseCursor(), mouse_cursors_names[ImGui::GetMouseCursor()]); @@ -4528,9 +4529,11 @@ static void ShowExampleAppCustomRendering(bool* p_open) { static float sz = 36.0f; static float thickness = 3.0f; + static int ngon_sides = 6; static ImVec4 colf = 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::SliderInt("n-gon sides", &ngon_sides, 3, 12); ImGui::ColorEdit4("Color", &colf.x); const ImVec2 p = ImGui::GetCursorScreenPos(); const ImU32 col = ImColor(colf); @@ -4543,7 +4546,7 @@ static void ShowExampleAppCustomRendering(bool* p_open) { // First line uses a thickness of 1.0f, 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, col, 6, th); x += sz + spacing; // Hexagon + draw_list->AddNgon(ImVec2(x + sz*0.5f, y + sz*0.5f), sz*0.5f, col, ngon_sides, th); x += sz + spacing; // n-gon draw_list->AddCircle(ImVec2(x + sz*0.5f, y + sz*0.5f), sz*0.5f, col, 20, th); x += sz + spacing; // Circle draw_list->AddRect(ImVec2(x, y), ImVec2(x + sz, y + sz), col, 0.0f, corners_none, th); x += sz + spacing; // Square draw_list->AddRect(ImVec2(x, y), ImVec2(x + sz, y + sz), col, 10.0f, corners_all, th); x += sz + spacing; // Square with all rounded corners @@ -4557,7 +4560,7 @@ static void ShowExampleAppCustomRendering(bool* p_open) x = p.x + 4; y += sz + spacing; } - draw_list->AddCircleFilled(ImVec2(x + sz*0.5f, y + sz*0.5f), sz*0.5f, col, 6); x += sz + spacing; // Hexagon + draw_list->AddNgonFilled(ImVec2(x + sz * 0.5f, y + sz * 0.5f), sz*0.5f, col, ngon_sides); x += sz + spacing; // n-gon draw_list->AddCircleFilled(ImVec2(x + sz*0.5f, y + sz*0.5f), sz*0.5f, col, 32); x += sz + spacing; // Circle draw_list->AddRectFilled(ImVec2(x, y), ImVec2(x + sz, y + sz), col); x += sz + spacing; // Square draw_list->AddRectFilled(ImVec2(x, y), ImVec2(x + sz, y + sz), col, 10.0f); x += sz + spacing; // Square with all rounded corners diff --git a/headers/3rdparty/imgui/imgui_draw.cpp b/headers/3rdparty/imgui/imgui_draw.cpp index dfd4447d..99713440 100644 --- a/headers/3rdparty/imgui/imgui_draw.cpp +++ b/headers/3rdparty/imgui/imgui_draw.cpp @@ -1,4 +1,4 @@ -// dear imgui, v1.74 +// dear imgui, v1.75 WIP // (drawing and font code) /* @@ -522,10 +522,13 @@ void ImDrawList::PopTextureID() UpdateTextureID(); } -// NB: this can be called with negative count for removing primitives (as long as the result does not underflow) +// Reserve space for a number of vertices and indices. +// You must finish filling your reserved data before calling PrimReserve() again, as it may reallocate or +// submit the intermediate results. PrimUnreserve() can be used to release unused allocations. void ImDrawList::PrimReserve(int idx_count, int vtx_count) { // Large mesh support (when enabled) + IM_ASSERT_PARANOID(idx_count >= 0 && vtx_count >= 0); if (sizeof(ImDrawIdx) == 2 && (_VtxCurrentIdx + vtx_count >= (1 << 16)) && (Flags & ImDrawListFlags_AllowVtxOffset)) { _VtxCurrentOffset = VtxBuffer.Size; @@ -533,7 +536,7 @@ void ImDrawList::PrimReserve(int idx_count, int vtx_count) AddDrawCmd(); } - ImDrawCmd& draw_cmd = CmdBuffer.Data[CmdBuffer.Size-1]; + ImDrawCmd& draw_cmd = CmdBuffer.Data[CmdBuffer.Size - 1]; draw_cmd.ElemCount += idx_count; int vtx_buffer_old_size = VtxBuffer.Size; @@ -545,6 +548,17 @@ void ImDrawList::PrimReserve(int idx_count, int vtx_count) _IdxWritePtr = IdxBuffer.Data + idx_buffer_old_size; } +// Release the a number of reserved vertices/indices from the end of the last reservation made with PrimReserve(). +void ImDrawList::PrimUnreserve(int idx_count, int vtx_count) +{ + IM_ASSERT_PARANOID(idx_count >= 0 && vtx_count >= 0); + + ImDrawCmd& draw_cmd = CmdBuffer.Data[CmdBuffer.Size - 1]; + draw_cmd.ElemCount -= idx_count; + VtxBuffer.shrink(VtxBuffer.Size - vtx_count); + IdxBuffer.shrink(IdxBuffer.Size - idx_count); +} + // Fully unrolled with inline call to keep our debug builds decently fast. void ImDrawList::PrimRect(const ImVec2& a, const ImVec2& c, ImU32 col) { @@ -899,6 +913,17 @@ void ImDrawList::PathArcTo(const ImVec2& center, float radius, float a_min, floa } } +ImVec2 ImBezierCalc(const ImVec2& p1, const ImVec2& p2, const ImVec2& p3, const ImVec2& p4, float t) +{ + float u = 1.0f - t; + float w1 = u*u*u; + float w2 = 3*u*u*t; + float w3 = 3*u*t*t; + float w4 = t*t*t; + return ImVec2(w1*p1.x + w2*p2.x + w3*p3.x + w4*p4.x, w1*p1.y + w2*p2.y + w3*p3.y + w4*p4.y); +} + +// Closely mimics BezierClosestPointCasteljauStep() in imgui.cpp static void PathBezierToCasteljau(ImVector* path, float x1, float y1, float x2, float y2, float x3, float y3, float x4, float y4, float tess_tol, int level) { float dx = x4 - x1; @@ -919,7 +944,6 @@ static void PathBezierToCasteljau(ImVector* path, float x1, float y1, fl float x123 = (x12+x23)*0.5f, y123 = (y12+y23)*0.5f; float x234 = (x23+x34)*0.5f, y234 = (y23+y34)*0.5f; float x1234 = (x123+x234)*0.5f, y1234 = (y123+y234)*0.5f; - PathBezierToCasteljau(path, x1,y1, x12,y12, x123,y123, x1234,y1234, tess_tol, level+1); PathBezierToCasteljau(path, x1234,y1234, x234,y234, x34,y34, x4,y4, tess_tol, level+1); } @@ -930,22 +954,13 @@ void ImDrawList::PathBezierCurveTo(const ImVec2& p2, const ImVec2& p3, const ImV ImVec2 p1 = _Path.back(); if (num_segments == 0) { - // Auto-tessellated - PathBezierToCasteljau(&_Path, p1.x, p1.y, p2.x, p2.y, p3.x, p3.y, p4.x, p4.y, _Data->CurveTessellationTol, 0); + PathBezierToCasteljau(&_Path, p1.x, p1.y, p2.x, p2.y, p3.x, p3.y, p4.x, p4.y, _Data->CurveTessellationTol, 0); // Auto-tessellated } else { float t_step = 1.0f / (float)num_segments; for (int i_step = 1; i_step <= num_segments; i_step++) - { - float t = t_step * i_step; - float u = 1.0f - t; - float w1 = u*u*u; - float w2 = 3*u*u*t; - float w3 = 3*u*t*t; - float w4 = t*t*t; - _Path.push_back(ImVec2(w1*p1.x + w2*p2.x + w3*p3.x + w4*p4.x, w1*p1.y + w2*p2.y + w3*p3.y + w4*p4.y)); - } + _Path.push_back(ImBezierCalc(p1, p2, p3, p4, t_step * i_step)); } } @@ -1096,13 +1111,38 @@ void ImDrawList::AddCircleFilled(const ImVec2& center, float radius, ImU32 col, PathFillConvex(col); } -void ImDrawList::AddBezierCurve(const ImVec2& pos0, const ImVec2& cp0, const ImVec2& cp1, const ImVec2& pos1, ImU32 col, float thickness, int num_segments) +// Guaranteed to honor 'num_segments' +void ImDrawList::AddNgon(const ImVec2& center, float radius, ImU32 col, int num_segments, float thickness) +{ + 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(center, radius - 0.5f, 0.0f, a_max, num_segments - 1); + PathStroke(col, true, thickness); +} + +// Guaranteed to honor 'num_segments' +void ImDrawList::AddNgonFilled(const ImVec2& center, float radius, ImU32 col, int num_segments) +{ + 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(center, radius, 0.0f, a_max, num_segments - 1); + PathFillConvex(col); +} + +// Cubic Bezier takes 4 controls points +void ImDrawList::AddBezierCurve(const ImVec2& p1, const ImVec2& p2, const ImVec2& p3, const ImVec2& p4, ImU32 col, float thickness, int num_segments) { if ((col & IM_COL32_A_MASK) == 0) return; - PathLineTo(pos0); - PathBezierCurveTo(cp0, cp1, pos1, num_segments); + PathLineTo(p1); + PathBezierCurveTo(p2, p3, p4, num_segments); PathStroke(col, false, thickness); } @@ -1281,7 +1321,7 @@ void ImDrawListSplitter::Merge(ImDrawList* draw_list) // Merge previous channel last draw command with current channel first draw command if matching. last_cmd->ElemCount += ch._CmdBuffer[0].ElemCount; idx_offset += ch._CmdBuffer[0].ElemCount; - ch._CmdBuffer.erase(ch._CmdBuffer.Data); + ch._CmdBuffer.erase(ch._CmdBuffer.Data); // FIXME-OPT: Improve for multiple merges. } if (ch._CmdBuffer.Size > 0) last_cmd = &ch._CmdBuffer.back(); @@ -1679,7 +1719,7 @@ ImFont* ImFontAtlas::AddFontFromFileTTF(const char* filename, float size_pixels, void* data = ImFileLoadToMemory(filename, "rb", &data_size, 0); if (!data) { - IM_ASSERT(0); // Could not load file. + IM_ASSERT_USER_ERROR(0, "Could not load font file!"); return NULL; } ImFontConfig font_cfg = font_cfg_template ? *font_cfg_template : ImFontConfig(); diff --git a/headers/3rdparty/imgui/imgui_internal.h b/headers/3rdparty/imgui/imgui_internal.h index eeaefb7b..1059cbdf 100644 --- a/headers/3rdparty/imgui/imgui_internal.h +++ b/headers/3rdparty/imgui/imgui_internal.h @@ -1,4 +1,4 @@ -// dear imgui, v1.74 +// dear imgui, v1.75 WIP // (internal structures/api) // You may use this file to debug, understand or extend ImGui features but we don't provide any guarantee of forward compatibility! @@ -167,17 +167,18 @@ extern IMGUI_API ImGuiContext* GImGui; // Current implicit context pointer #endif // "Paranoid" Debug Asserts are meant to only be enabled during specific debugging/work, otherwise would slow down the code too much. -#define IMGUI_DEBUG_PARANOID 0 -#if IMGUI_DEBUG_PARANOID +// We currently don't have many of those so the effect is currently negligible, but onward intent to add more aggressive ones in the code. +//#define IMGUI_DEBUG_PARANOID +#ifdef IMGUI_DEBUG_PARANOID #define IM_ASSERT_PARANOID(_EXPR) IM_ASSERT(_EXPR) #else -#define IM_ASSERT_PARANOID(_EXPR) +#define IM_ASSERT_PARANOID(_EXPR) #endif // Error handling // Down the line in some frameworks/languages we would like to have a way to redirect those to the programmer and recover from more faults. #ifndef IM_ASSERT_USER_ERROR -#define IM_ASSERT_USER_ERROR(_EXP,_MSG) IM_ASSERT((_EXP) && (_MSG)) // Recoverable User Error +#define IM_ASSERT_USER_ERROR(_EXP,_MSG) IM_ASSERT((_EXP) && _MSG) // Recoverable User Error #endif // Misc Macros @@ -202,6 +203,8 @@ extern IMGUI_API ImGuiContext* GImGui; // Current implicit context pointer //----------------------------------------------------------------------------- // Generic helpers +// Note that the ImXXX helpers functions are lower-level than ImGui functions. +// ImGui functions or the ImGui context are never called/used from other ImXXX functions. //----------------------------------------------------------------------------- // - Helpers: Misc // - Helpers: Bit manipulation @@ -348,6 +351,9 @@ static inline float ImLinearSweep(float current, float target, float speed) static inline ImVec2 ImMul(const ImVec2& lhs, const ImVec2& rhs) { return ImVec2(lhs.x * rhs.x, lhs.y * rhs.y); } // Helpers: Geometry +IMGUI_API ImVec2 ImBezierCalc(const ImVec2& p1, const ImVec2& p2, const ImVec2& p3, const ImVec2& p4, float t); // Cubic Bezier +IMGUI_API ImVec2 ImBezierClosestPoint(const ImVec2& p1, const ImVec2& p2, const ImVec2& p3, const ImVec2& p4, const ImVec2& p, int num_segments); // For curves with explicit number of segments +IMGUI_API ImVec2 ImBezierClosestPointCasteljau(const ImVec2& p1, const ImVec2& p2, const ImVec2& p3, const ImVec2& p4, const ImVec2& p, float tess_tol);// For auto-tessellated curves you can use tess_tol = style.CurveTessellationTol IMGUI_API ImVec2 ImLineClosestPoint(const ImVec2& a, const ImVec2& b, const ImVec2& p); IMGUI_API bool ImTriangleContainsPoint(const ImVec2& a, const ImVec2& b, const ImVec2& c, const ImVec2& p); IMGUI_API ImVec2 ImTriangleClosestPoint(const ImVec2& a, const ImVec2& b, const ImVec2& c, const ImVec2& p); @@ -423,20 +429,22 @@ enum ImGuiButtonFlags_ { ImGuiButtonFlags_None = 0, ImGuiButtonFlags_Repeat = 1 << 0, // hold to repeat - ImGuiButtonFlags_PressedOnClickRelease = 1 << 1, // [Default] return true on click + release on same item - ImGuiButtonFlags_PressedOnClick = 1 << 2, // return true on click (default requires click+release) - ImGuiButtonFlags_PressedOnRelease = 1 << 3, // return true on release (default requires click+release) - ImGuiButtonFlags_PressedOnDoubleClick = 1 << 4, // return true on double-click (default requires click+release) - ImGuiButtonFlags_FlattenChildren = 1 << 5, // allow interactions even if a child window is overlapping - ImGuiButtonFlags_AllowItemOverlap = 1 << 6, // require previous frame HoveredId to either match id or be null before being usable, use along with SetItemAllowOverlap() - ImGuiButtonFlags_DontClosePopups = 1 << 7, // disable automatically closing parent popup on press // [UNUSED] - ImGuiButtonFlags_Disabled = 1 << 8, // disable interactions - ImGuiButtonFlags_AlignTextBaseLine = 1 << 9, // vertically align button to match text baseline - ButtonEx() only // FIXME: Should be removed and handled by SmallButton(), not possible currently because of DC.CursorPosPrevLine - ImGuiButtonFlags_NoKeyModifiers = 1 << 10, // disable mouse interaction if a key modifier is held - ImGuiButtonFlags_NoHoldingActiveID = 1 << 11, // don't set ActiveId while holding the mouse (ImGuiButtonFlags_PressedOnClick only) - ImGuiButtonFlags_PressedOnDragDropHold = 1 << 12, // press when held into while we are drag and dropping another item (used by e.g. tree nodes, collapsing headers) - ImGuiButtonFlags_NoNavFocus = 1 << 13, // don't override navigation focus when activated - ImGuiButtonFlags_NoHoveredOnNav = 1 << 14 // don't report as hovered when navigated on + ImGuiButtonFlags_PressedOnClick = 1 << 1, // return true on click (mouse down event) + ImGuiButtonFlags_PressedOnClickRelease = 1 << 2, // [Default] return true on click + release on same item <-- this is what the majority of Button are using + ImGuiButtonFlags_PressedOnClickReleaseAnywhere = 1 << 3, // return true on click + release even if the release event is not done while hovering the item + ImGuiButtonFlags_PressedOnRelease = 1 << 4, // return true on release (default requires click+release) + ImGuiButtonFlags_PressedOnDoubleClick = 1 << 5, // return true on double-click (default requires click+release) + ImGuiButtonFlags_PressedOnDragDropHold = 1 << 6, // return true when held into while we are drag and dropping another item (used by e.g. tree nodes, collapsing headers) + ImGuiButtonFlags_FlattenChildren = 1 << 7, // allow interactions even if a child window is overlapping + ImGuiButtonFlags_AllowItemOverlap = 1 << 8, // require previous frame HoveredId to either match id or be null before being usable, use along with SetItemAllowOverlap() + ImGuiButtonFlags_DontClosePopups = 1 << 9, // disable automatically closing parent popup on press // [UNUSED] + ImGuiButtonFlags_Disabled = 1 << 10, // disable interactions + ImGuiButtonFlags_AlignTextBaseLine = 1 << 11, // vertically align button to match text baseline - ButtonEx() only // FIXME: Should be removed and handled by SmallButton(), not possible currently because of DC.CursorPosPrevLine + ImGuiButtonFlags_NoKeyModifiers = 1 << 12, // disable mouse interaction if a key modifier is held + ImGuiButtonFlags_NoHoldingActiveID = 1 << 13, // don't set ActiveId while holding the mouse (ImGuiButtonFlags_PressedOnClick only) + ImGuiButtonFlags_NoNavFocus = 1 << 14, // don't override navigation focus when activated + ImGuiButtonFlags_NoHoveredOnNav = 1 << 15, // don't report as hovered when navigated on + ImGuiButtonFlags_PressedOnMask_ = ImGuiButtonFlags_PressedOnClick | ImGuiButtonFlags_PressedOnClickRelease | ImGuiButtonFlags_PressedOnClickReleaseAnywhere | ImGuiButtonFlags_PressedOnRelease | ImGuiButtonFlags_PressedOnDoubleClick | ImGuiButtonFlags_PressedOnDragDropHold }; enum ImGuiSliderFlags_ @@ -511,7 +519,7 @@ enum ImGuiItemStatusFlags_ ImGuiItemStatusFlags_HasDisplayRect = 1 << 1, ImGuiItemStatusFlags_Edited = 1 << 2, // Value exposed by item was edited in the current frame (should match the bool return value of most widgets) ImGuiItemStatusFlags_ToggledSelection = 1 << 3, // Set when Selectable(), TreeNode() reports toggling a selection. We can't report "Selected" because reporting the change allows us to handle clipping with less issues. - ImGuiItemStatusFlags_ToggledOpen = 1 << 4, // Set when TreeNode() reports toggling their open state. + ImGuiItemStatusFlags_ToggledOpen = 1 << 4, // Set when TreeNode() reports toggling their open state. ImGuiItemStatusFlags_HasDeactivated = 1 << 5, // Set if the widget/group is able to provide data for the ImGuiItemStatusFlags_Deactivated flag. ImGuiItemStatusFlags_Deactivated = 1 << 6 // Only valid if ImGuiItemStatusFlags_HasDeactivated is set. @@ -655,7 +663,7 @@ struct IMGUI_API ImRect ImVec2 Min; // Upper-left ImVec2 Max; // Lower-right - ImRect() : Min(FLT_MAX,FLT_MAX), Max(-FLT_MAX,-FLT_MAX) {} + ImRect() : Min(0.0f, 0.0f), Max(0.0f, 0.0f) {} ImRect(const ImVec2& min, const ImVec2& max) : Min(min), Max(max) {} ImRect(const ImVec4& v) : Min(v.x, v.y), Max(v.z, v.w) {} ImRect(float x1, float y1, float x2, float y2) : Min(x1, y1), Max(x2, y2) {} @@ -864,7 +872,7 @@ struct IMGUI_API ImDrawListSharedData ImVec2 TexUvWhitePixel; // UV of white pixel in the atlas ImFont* Font; // Current/default font (optional, for simplified AddText overload) float FontSize; // Current/default font size (optional, for simplified AddText overload) - float CurveTessellationTol; + float CurveTessellationTol; // Tessellation tolerance when using PathBezierCurveTo() ImVec4 ClipRectFullscreen; // Value for PushClipRectFullscreen() ImDrawListFlags InitialFlags; // Initial flags at the beginning of the frame (it is possible to alter flags on a per-drawlist basis afterwards) @@ -1053,7 +1061,7 @@ struct ImGuiDockNode ImVec2 Size; // Current size ImVec2 SizeRef; // [Split node only] Last explicitly written-to size (overridden when using a splitter affecting the node), used to calculate Size. int SplitAxis; // [Split node only] Split axis (X or Y) - ImGuiWindowClass WindowClass; + ImGuiWindowClass WindowClass; // [Root node only] ImGuiDockNodeState State; ImGuiWindow* HostWindow; @@ -1269,6 +1277,7 @@ struct ImGuiContext ImGuiID TempInputTextId; // Temporary text input when CTRL+clicking on a slider, etc. ImGuiColorEditFlags ColorEditOptions; // Store user options for color edit widgets float ColorEditLastHue; // Backup of last Hue associated to LastColor[3], so we can restore Hue in lossy RGB<>HSV round trips + float ColorEditLastSat; // Backup of last Saturation associated to LastColor[3], so we can restore Saturation in lossy RGB<>HSV round trips float ColorEditLastColor[3]; ImVec4 ColorPickerRef; // Initial/reference color at the time of opening the color picker. bool DragCurrentAccumDirty; @@ -1424,7 +1433,7 @@ struct ImGuiContext LastValidMousePos = ImVec2(0.0f, 0.0f); TempInputTextId = 0; ColorEditOptions = ImGuiColorEditFlags__OptionsDefault; - ColorEditLastHue = 0.0f; + ColorEditLastHue = ColorEditLastSat = 0.0f; ColorEditLastColor[0] = ColorEditLastColor[1] = ColorEditLastColor[2] = FLT_MAX; DragCurrentAccumDirty = false; DragCurrentAccum = 0.0f; @@ -1703,7 +1712,7 @@ enum ImGuiTabBarFlagsPrivate_ // Extend ImGuiTabItemFlags_ enum ImGuiTabItemFlagsPrivate_ { - ImGuiTabItemFlags_NoCloseButton = 1 << 20, // Store whether p_open is set or not, which we need to recompute ContentWidth during layout. + ImGuiTabItemFlags_NoCloseButton = 1 << 20, // Track whether p_open was set or not (we'll need this info on the next frame to recompute ContentWidth during layout) ImGuiTabItemFlags_Unsorted = 1 << 21, // [Docking] Trailing tabs with the _Unsorted flag will be sorted based on the DockOrder of their Window. ImGuiTabItemFlags_Preview = 1 << 22 // [Docking] Display tab shape for docking preview (height is adjusted slightly to compensate for the yet missing tab bar) }; @@ -1865,6 +1874,7 @@ namespace ImGui IMGUI_API void LogToBuffer(int auto_open_depth = -1); // Start logging/capturing to internal buffer // Popups, Modals, Tooltips + IMGUI_API bool BeginChildEx(const char* name, ImGuiID id, const ImVec2& size_arg, bool border, ImGuiWindowFlags flags); IMGUI_API void OpenPopupEx(ImGuiID id); IMGUI_API void ClosePopupToLevel(int remaining, bool restore_focus_to_window_under_popup); IMGUI_API void ClosePopupsOverWindow(ImGuiWindow* ref_window, bool restore_focus_to_window_under_popup); @@ -1893,7 +1903,7 @@ namespace ImGui inline bool IsActiveIdUsingNavDir(ImGuiDir dir) { ImGuiContext& g = *GImGui; return (g.ActiveIdUsingNavDirMask & (1 << dir)) != 0; } inline bool IsActiveIdUsingNavInput(ImGuiNavInput input) { ImGuiContext& g = *GImGui; return (g.ActiveIdUsingNavInputMask & (1 << input)) != 0; } inline bool IsActiveIdUsingKey(ImGuiKey key) { ImGuiContext& g = *GImGui; IM_ASSERT(key < 64); return (g.ActiveIdUsingKeyInputMask & ((ImU64)1 << key)) != 0; } - IMGUI_API bool IsMouseDragPastThreshold(int button, float lock_threshold = -1.0f); + IMGUI_API bool IsMouseDragPastThreshold(ImGuiMouseButton button, float lock_threshold = -1.0f); inline bool IsKeyPressedMap(ImGuiKey key, bool repeat = true) { ImGuiContext& g = *GImGui; const int key_index = g.IO.KeyMap[key]; return (key_index >= 0) ? IsKeyPressed(key_index, repeat) : false; } inline bool IsNavInputDown(ImGuiNavInput n) { ImGuiContext& g = *GImGui; return g.IO.NavInputs[n] > 0.0f; } inline bool IsNavInputTest(ImGuiNavInput n, ImGuiInputReadMode rm) { return (GetNavInputAmount(n, rm) > 0.0f); } diff --git a/headers/3rdparty/imgui/imgui_widgets.cpp b/headers/3rdparty/imgui/imgui_widgets.cpp index 088639bf..ddcee606 100644 --- a/headers/3rdparty/imgui/imgui_widgets.cpp +++ b/headers/3rdparty/imgui/imgui_widgets.cpp @@ -1,4 +1,4 @@ -// dear imgui, v1.74 +// dear imgui, v1.75 WIP // (widgets code) /* @@ -462,7 +462,7 @@ bool ImGui::ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool } // Default behavior requires click+release on same spot - if ((flags & (ImGuiButtonFlags_PressedOnClickRelease | ImGuiButtonFlags_PressedOnClick | ImGuiButtonFlags_PressedOnRelease | ImGuiButtonFlags_PressedOnDoubleClick)) == 0) + if ((flags & ImGuiButtonFlags_PressedOnMask_) == 0) flags |= ImGuiButtonFlags_PressedOnClickRelease; ImGuiWindow* backup_hovered_window = g.HoveredWindow; @@ -507,7 +507,7 @@ bool ImGui::ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool { if (!(flags & ImGuiButtonFlags_NoKeyModifiers) || (!g.IO.KeyCtrl && !g.IO.KeyShift && !g.IO.KeyAlt)) { - if ((flags & ImGuiButtonFlags_PressedOnClickRelease) && g.IO.MouseClicked[0]) + if ((flags & (ImGuiButtonFlags_PressedOnClickRelease | ImGuiButtonFlags_PressedOnClickReleaseAnywhere)) && g.IO.MouseClicked[0]) { SetActiveID(id, window); if (!(flags & ImGuiButtonFlags_NoNavFocus)) @@ -577,7 +577,9 @@ bool ImGui::ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool } else { - if (hovered && (flags & ImGuiButtonFlags_PressedOnClickRelease) && !g.DragDropActive) + const bool release_in = hovered && (flags & ImGuiButtonFlags_PressedOnClickRelease) != 0; + const bool release_anywhere = (flags & ImGuiButtonFlags_PressedOnClickReleaseAnywhere) != 0; + if ((release_in || release_anywhere) && !g.DragDropActive) { bool is_double_click_release = (flags & ImGuiButtonFlags_PressedOnDoubleClick) && g.IO.MouseDownWasDoubleClick[0]; bool is_repeating_already = (flags & ImGuiButtonFlags_Repeat) && g.IO.MouseDownDurationPrev[0] >= g.IO.KeyRepeatDelay; // Repeat mode trumps @@ -1266,21 +1268,14 @@ void ImGui::SeparatorEx(ImGuiSeparatorFlags flags) // We don't provide our width to the layout so that it doesn't get feed back into AutoFit const ImRect bb(ImVec2(x1, window->DC.CursorPos.y), ImVec2(x2, window->DC.CursorPos.y + thickness_draw)); ItemSize(ImVec2(0.0f, thickness_layout)); - if (!ItemAdd(bb, 0)) + const bool item_visible = ItemAdd(bb, 0); + if (item_visible) { - if (columns) - { - PopColumnsBackground(); - columns->LineMinY = window->DC.CursorPos.y; - } - return; + // Draw + window->DrawList->AddLine(bb.Min, ImVec2(bb.Max.x, bb.Min.y), GetColorU32(ImGuiCol_Separator)); + if (g.LogEnabled) + LogRenderedText(&bb.Min, "--------------------------------"); } - - // Draw - window->DrawList->AddLine(bb.Min, ImVec2(bb.Max.x, bb.Min.y), GetColorU32(ImGuiCol_Separator)); - if (g.LogEnabled) - LogRenderedText(&bb.Min, "--------------------------------"); - if (columns) { PopColumnsBackground(); @@ -4239,8 +4234,13 @@ bool ImGui::ColorEdit4(const char* label, float col[4], ImGuiColorEditFlags flag { // Hue is lost when converting from greyscale rgb (saturation=0). Restore it. ColorConvertRGBtoHSV(f[0], f[1], f[2], f[0], f[1], f[2]); - if (f[1] == 0 && memcmp(g.ColorEditLastColor, col, sizeof(float) * 3) == 0) - f[0] = g.ColorEditLastHue; + if (memcmp(g.ColorEditLastColor, col, sizeof(float) * 3) == 0) + { + if (f[1] == 0) + f[0] = g.ColorEditLastHue; + if (f[2] == 0) + f[1] = g.ColorEditLastSat; + } } int i[4] = { IM_F32_TO_INT8_UNBOUND(f[0]), IM_F32_TO_INT8_UNBOUND(f[1]), IM_F32_TO_INT8_UNBOUND(f[2]), IM_F32_TO_INT8_UNBOUND(f[3]) }; @@ -4279,16 +4279,15 @@ bool ImGui::ColorEdit4(const char* label, float col[4], ImGuiColorEditFlags flag SameLine(0, style.ItemInnerSpacing.x); SetNextItemWidth((n + 1 < components) ? w_item_one : w_item_last); - // Disable Hue edit when Saturation is zero - const bool disable_hue_edit = (n == 0 && (flags & ImGuiColorEditFlags_DisplayHSV) && i[1] == 0); + // FIXME: When ImGuiColorEditFlags_HDR flag is passed HS values snap in weird ways when SV values go below 0. if (flags & ImGuiColorEditFlags_Float) { - value_changed |= DragFloat(ids[n], &f[n], 1.0f/255.0f, disable_hue_edit ? +FLT_MAX : 0.0f, disable_hue_edit ? -FLT_MAX : hdr ? 0.0f : 1.0f, fmt_table_float[fmt_idx][n]); + value_changed |= DragFloat(ids[n], &f[n], 1.0f/255.0f, 0.0f, hdr ? 0.0f : 1.0f, fmt_table_float[fmt_idx][n]); value_changed_as_float |= value_changed; } else { - value_changed |= DragInt(ids[n], &i[n], 1.0f, disable_hue_edit ? INT_MAX : 0, disable_hue_edit ? INT_MIN : hdr ? 0 : 255, fmt_table_int[fmt_idx][n]); + value_changed |= DragInt(ids[n], &i[n], 1.0f, 0, hdr ? 0 : 255, fmt_table_int[fmt_idx][n]); } if (!(flags & ImGuiColorEditFlags_NoOptions)) OpenPopupOnItemClick("context"); @@ -4357,7 +4356,8 @@ bool ImGui::ColorEdit4(const char* label, float col[4], ImGuiColorEditFlags flag if (label != label_display_end && !(flags & ImGuiColorEditFlags_NoLabel)) { - window->DC.CursorPos = ImVec2(pos.x + w_full + style.ItemInnerSpacing.x, pos.y + style.FramePadding.y); + const float text_offset_x = (flags & ImGuiColorEditFlags_NoInputs) ? w_button : w_full + style.ItemInnerSpacing.x; + window->DC.CursorPos = ImVec2(pos.x + text_offset_x, pos.y + style.FramePadding.y); TextEx(label, label_display_end); } @@ -4370,6 +4370,7 @@ bool ImGui::ColorEdit4(const char* label, float col[4], ImGuiColorEditFlags flag if ((flags & ImGuiColorEditFlags_DisplayHSV) && (flags & ImGuiColorEditFlags_InputRGB)) { g.ColorEditLastHue = f[0]; + g.ColorEditLastSat = f[1]; ColorConvertHSVtoRGB(f[0], f[1], f[2], f[0], f[1], f[2]); memcpy(g.ColorEditLastColor, f, sizeof(float) * 3); } @@ -4552,8 +4553,13 @@ bool ImGui::ColorPicker4(const char* label, float col[4], ImGuiColorEditFlags fl { // Hue is lost when converting from greyscale rgb (saturation=0). Restore it. ColorConvertRGBtoHSV(R, G, B, H, S, V); - if (S == 0 && memcmp(g.ColorEditLastColor, col, sizeof(float) * 3) == 0) - H = g.ColorEditLastHue; + if (memcmp(g.ColorEditLastColor, col, sizeof(float) * 3) == 0) + { + if (S == 0) + H = g.ColorEditLastHue; + if (V == 0) + S = g.ColorEditLastSat; + } } else if (flags & ImGuiColorEditFlags_InputHSV) { @@ -4681,6 +4687,7 @@ bool ImGui::ColorPicker4(const char* label, float col[4], ImGuiColorEditFlags fl { ColorConvertHSVtoRGB(H >= 1.0f ? H - 10 * 1e-6f : H, S > 0.0f ? S : 10*1e-6f, V > 0.0f ? V : 1e-6f, col[0], col[1], col[2]); g.ColorEditLastHue = H; + g.ColorEditLastSat = S; memcpy(g.ColorEditLastColor, col, sizeof(float) * 3); } else if (flags & ImGuiColorEditFlags_InputHSV) @@ -4735,8 +4742,13 @@ bool ImGui::ColorPicker4(const char* label, float col[4], ImGuiColorEditFlags fl G = col[1]; B = col[2]; ColorConvertRGBtoHSV(R, G, B, H, S, V); - if (S == 0 && memcmp(g.ColorEditLastColor, col, sizeof(float) * 3) == 0) // Fix local Hue as display below will use it immediately. - H = g.ColorEditLastHue; + if (memcmp(g.ColorEditLastColor, col, sizeof(float) * 3) == 0) // Fix local Hue as display below will use it immediately. + { + if (S == 0) + H = g.ColorEditLastHue; + if (V == 0) + S = g.ColorEditLastSat; + } } else if (flags & ImGuiColorEditFlags_InputHSV) { @@ -5288,10 +5300,12 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* l button_flags |= ImGuiButtonFlags_AllowItemOverlap; if (flags & ImGuiTreeNodeFlags_OpenOnDoubleClick) button_flags |= ImGuiButtonFlags_PressedOnDoubleClick | ((flags & ImGuiTreeNodeFlags_OpenOnArrow) ? ImGuiButtonFlags_PressedOnClickRelease : 0); + else + button_flags |= ImGuiButtonFlags_PressedOnClickRelease; if (!is_leaf) button_flags |= ImGuiButtonFlags_PressedOnDragDropHold; - // We allow clicking on the arrow section with keyboard modifiers held, in order to easily + // We allow clicking on the arrow section with keyboard modifiers held, in order to easily // allow browsing a tree while preserving selection with code implementing multi-selection patterns. // When clicking on the rest of the tree node we always disallow keyboard modifiers. const float hit_padding_x = style.TouchExtraPadding.x; @@ -5299,7 +5313,7 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* l const float arrow_hit_x2 = (text_pos.x - text_offset_x) + (g.FontSize + padding.x * 2.0f) + hit_padding_x; if (window != g.HoveredWindow || !(g.IO.MousePos.x >= arrow_hit_x1 && g.IO.MousePos.x < arrow_hit_x2)) button_flags |= ImGuiButtonFlags_NoKeyModifiers; - + bool selected = (flags & ImGuiTreeNodeFlags_Selected) != 0; const bool was_selected = selected; @@ -5573,12 +5587,12 @@ bool ImGui::Selectable(const char* label, bool selected, ImGuiSelectableFlags fl // We use NoHoldingActiveID on menus so user can click and _hold_ on a menu then drag to browse child entries ImGuiButtonFlags button_flags = 0; - if (flags & ImGuiSelectableFlags_NoHoldingActiveID) button_flags |= ImGuiButtonFlags_NoHoldingActiveID; - if (flags & ImGuiSelectableFlags_PressedOnClick) button_flags |= ImGuiButtonFlags_PressedOnClick; - if (flags & ImGuiSelectableFlags_PressedOnRelease) button_flags |= ImGuiButtonFlags_PressedOnRelease; - if (flags & ImGuiSelectableFlags_Disabled) button_flags |= ImGuiButtonFlags_Disabled; - if (flags & ImGuiSelectableFlags_AllowDoubleClick) button_flags |= ImGuiButtonFlags_PressedOnClickRelease | ImGuiButtonFlags_PressedOnDoubleClick; - if (flags & ImGuiSelectableFlags_AllowItemOverlap) button_flags |= ImGuiButtonFlags_AllowItemOverlap; + if (flags & ImGuiSelectableFlags_NoHoldingActiveID) { button_flags |= ImGuiButtonFlags_NoHoldingActiveID; } + if (flags & ImGuiSelectableFlags_PressedOnClick) { button_flags |= ImGuiButtonFlags_PressedOnClick; } + if (flags & ImGuiSelectableFlags_PressedOnRelease) { button_flags |= ImGuiButtonFlags_PressedOnRelease; } + if (flags & ImGuiSelectableFlags_Disabled) { button_flags |= ImGuiButtonFlags_Disabled; } + if (flags & ImGuiSelectableFlags_AllowDoubleClick) { button_flags |= ImGuiButtonFlags_PressedOnClickRelease | ImGuiButtonFlags_PressedOnDoubleClick; } + if (flags & ImGuiSelectableFlags_AllowItemOverlap) { button_flags |= ImGuiButtonFlags_AllowItemOverlap; } if (flags & ImGuiSelectableFlags_Disabled) selected = false; @@ -6981,6 +6995,12 @@ bool ImGui::TabItemEx(ImGuiTabBar* tab_bar, const char* label, bool* p_open, return false; } + // Store into ImGuiTabItemFlags_NoCloseButton, also honor ImGuiTabItemFlags_NoCloseButton passed by user (although not documented) + if (flags & ImGuiTabItemFlags_NoCloseButton) + p_open = NULL; + else if (p_open == NULL) + flags |= ImGuiTabItemFlags_NoCloseButton; + // Calculate tab contents size ImVec2 size = TabItemCalcSize(label, p_open != NULL); @@ -6998,9 +7018,6 @@ bool ImGui::TabItemEx(ImGuiTabBar* tab_bar, const char* label, bool* p_open, tab_bar->LastTabItemIdx = (short)tab_bar->Tabs.index_from_ptr(tab); tab->ContentWidth = size.x; - if (p_open == NULL) - flags |= ImGuiTabItemFlags_NoCloseButton; - const bool tab_bar_appearing = (tab_bar->PrevFrameVisible + 1 < g.FrameCount); const bool tab_bar_focused = (tab_bar->Flags & ImGuiTabBarFlags_IsFocused) != 0; const bool tab_appearing = (tab->LastFrameVisible + 1 < g.FrameCount); @@ -7525,8 +7542,8 @@ void ImGui::BeginColumns(const char* str_id, int columns_count, ImGuiColumnsFlag ImGuiContext& g = *GImGui; ImGuiWindow* window = GetCurrentWindow(); - IM_ASSERT(columns_count >= 1); - IM_ASSERT(window->DC.CurrentColumns == NULL); // Nested columns are currently not supported + IM_ASSERT(columns_count >= 1 && columns_count <= 64); // Maximum 64 columns + IM_ASSERT(window->DC.CurrentColumns == NULL); // Nested columns are currently not supported // Acquire storage for the columns set ImGuiID id = GetColumnsID(str_id, columns_count); diff --git a/headers/3rdparty/rapidjson/rapidjson.h b/headers/3rdparty/rapidjson/rapidjson.h index b71ea79b..329ce92b 100644 --- a/headers/3rdparty/rapidjson/rapidjson.h +++ b/headers/3rdparty/rapidjson/rapidjson.h @@ -631,7 +631,8 @@ RAPIDJSON_NAMESPACE_END #if RAPIDJSON_HAS_CXX11_NOEXCEPT #define RAPIDJSON_NOEXCEPT_ASSERT(x) #else -#define RAPIDJSON_NOEXCEPT_ASSERT(x) RAPIDJSON_ASSERT(x) +#include +#define RAPIDJSON_NOEXCEPT_ASSERT(x) assert(x) #endif // RAPIDJSON_HAS_CXX11_NOEXCEPT #else #define RAPIDJSON_NOEXCEPT_ASSERT(x) RAPIDJSON_ASSERT(x) diff --git a/headers/3rdparty/rapidjson/schema.h b/headers/3rdparty/rapidjson/schema.h index 1ff8883d..fc39d06c 100644 --- a/headers/3rdparty/rapidjson/schema.h +++ b/headers/3rdparty/rapidjson/schema.h @@ -443,7 +443,6 @@ public: exclusiveMaximum_(false), defaultValueLength_(0) { - typedef typename SchemaDocumentType::ValueType ValueType; typedef typename ValueType::ConstValueIterator ConstValueIterator; typedef typename ValueType::ConstMemberIterator ConstMemberIterator; diff --git a/headers/3rdparty/sol/bytecode.hpp b/headers/3rdparty/sol/bytecode.hpp index cf85371a..ff1c2d82 100644 --- a/headers/3rdparty/sol/bytecode.hpp +++ b/headers/3rdparty/sol/bytecode.hpp @@ -75,11 +75,13 @@ namespace sol { using base_t::rend; - using base_t::swap; using base_t::get_allocator; + using base_t::swap; + using base_t::clear; using base_t::emplace; using base_t::emplace_back; + using base_t::erase; using base_t::insert; using base_t::pop_back; using base_t::push_back; @@ -87,7 +89,7 @@ namespace sol { using base_t::resize; using base_t::shrink_to_fit; - string_view as_string_view () const { + string_view as_string_view() const { return string_view(reinterpret_cast(this->data()), this->size()); } }; @@ -97,12 +99,16 @@ namespace sol { using storage_t = Container; const std::byte* p_code = static_cast(memory); storage_t& bc = *static_cast(userdata); +#if defined(SOL_NO_EXCEPTIONS) && SOL_NO_EXCEPTIONS != 0 + bc.insert(bc.cend(), p_code, p_code + memory_size); +#else try { bc.insert(bc.cend(), p_code, p_code + memory_size); } - catch ( ... ) { + catch (...) { return -1; } +#endif return 0; } diff --git a/headers/3rdparty/sol/call.hpp b/headers/3rdparty/sol/call.hpp index 811ce57d..1f2d1f5a 100644 --- a/headers/3rdparty/sol/call.hpp +++ b/headers/3rdparty/sol/call.hpp @@ -147,7 +147,8 @@ namespace sol { typedef meta::tuple_types return_types; typedef typename traits::free_args_list args_list; // compile-time eliminate any functions that we know ahead of time are of improper arity - if constexpr (!traits::runtime_variadics_t::value && meta::find_in_pack_v, meta::index_value...>::value) { + if constexpr (!traits::runtime_variadics_t::value + && meta::find_in_pack_v, meta::index_value...>::value) { return overload_match_arity(types(), std::index_sequence(), std::index_sequence(), @@ -161,25 +162,25 @@ namespace sol { if constexpr (!traits::runtime_variadics_t::value) { if (traits::free_arity != fxarity) { return overload_match_arity(types(), - std::index_sequence(), - std::index_sequence(), - std::forward(matchfx), - L, - fxarity, - start, - std::forward(args)...); + std::index_sequence(), + std::index_sequence(), + std::forward(matchfx), + L, + fxarity, + start, + std::forward(args)...); } } stack::record tracking{}; if (!stack::stack_detail::check_types(args_list(), L, start, no_panic, tracking)) { return overload_match_arity(types(), - std::index_sequence(), - std::index_sequence(), - std::forward(matchfx), - L, - fxarity, - start, - std::forward(args)...); + std::index_sequence(), + std::index_sequence(), + std::forward(matchfx), + L, + fxarity, + start, + std::forward(args)...); } return matchfx(types(), meta::index_value(), return_types(), args_list(), L, fxarity, start, std::forward(args)...); } @@ -216,15 +217,17 @@ namespace sol { start, std::forward(args)...); } - if (!traits::runtime_variadics_t::value && traits::free_arity != fxarity) { - return overload_match_arity(types<>(), - std::index_sequence<>(), - std::index_sequence(), - std::forward(matchfx), - L, - fxarity, - start, - std::forward(args)...); + if constexpr (!traits::runtime_variadics_t::value) { + if (traits::free_arity != fxarity) { + return overload_match_arity(types<>(), + std::index_sequence<>(), + std::index_sequence(), + std::forward(matchfx), + L, + fxarity, + start, + std::forward(args)...); + } } return matchfx(types(), meta::index_value(), return_types(), args_list(), L, fxarity, start, std::forward(args)...); } @@ -237,7 +240,8 @@ namespace sol { typedef meta::tuple_types return_types; typedef typename traits::free_args_list args_list; // compile-time eliminate any functions that we know ahead of time are of improper arity - if constexpr (!traits::runtime_variadics_t::value && meta::find_in_pack_v, meta::index_value...>::value) { + if constexpr (!traits::runtime_variadics_t::value + && meta::find_in_pack_v, meta::index_value...>::value) { return overload_match_arity(types(), std::index_sequence(), std::index_sequence(), @@ -251,25 +255,25 @@ namespace sol { if constexpr (!traits::runtime_variadics_t::value) { if (traits::free_arity != fxarity) { return overload_match_arity(types(), - std::index_sequence(), - std::index_sequence(), - std::forward(matchfx), - L, - fxarity, - start, - std::forward(args)...); + std::index_sequence(), + std::index_sequence(), + std::forward(matchfx), + L, + fxarity, + start, + std::forward(args)...); } } stack::record tracking{}; if (!stack::stack_detail::check_types(args_list(), L, start, no_panic, tracking)) { - return overload_match_arity(types(), - std::index_sequence(), - std::index_sequence(), - std::forward(matchfx), - L, - fxarity, - start, - std::forward(args)...); + return overload_match_arity(types(), + std::index_sequence(), + std::index_sequence(), + std::forward(matchfx), + L, + fxarity, + start, + std::forward(args)...); } return matchfx(types(), meta::index_value(), return_types(), args_list(), L, fxarity, start, std::forward(args)...); } @@ -313,6 +317,8 @@ namespace sol { stack::stack_detail::undefined_metatable umf(L, &meta[0], &stack::stack_detail::set_undefined_methods_on); umf(); + // put userdata at the first index + lua_insert(L, 1); construct_match(constructor_match(obj), L, argcount, 1 + static_cast(syntax)); userdataref.push(); @@ -330,7 +336,7 @@ namespace sol { template static int call(lua_State* L, Fx&& f, Args&&... args) { - if constexpr(is_lua_reference_v>) { + if constexpr (is_lua_reference_v>) { if constexpr (is_index) { return stack::push(L, std::forward(f), std::forward(args)...); } @@ -373,6 +379,7 @@ namespace sol { } else { if constexpr (std::is_const_v>) { + (void)f; return luaL_error(L, "sol: cannot write to a readonly (const) variable"); } else { @@ -502,8 +509,13 @@ namespace sol { else { using returns_list = typename wrap::returns_list; using caller = typename wrap::caller; - return stack::call_into_lua( - returns_list(), types<>(), L, boost + (is_variable ? 3 : 2), caller(), std::forward(fx), std::forward(args)...); + return stack::call_into_lua(returns_list(), + types<>(), + L, + boost + (is_variable ? 3 : 2), + caller(), + std::forward(fx), + std::forward(args)...); } } else { @@ -528,16 +540,16 @@ namespace sol { using caller = typename wrap::caller; if constexpr (sizeof...(Args) > 0) { return stack::call_into_lua(types(), - args_list(), - L, - boost + (is_variable ? 3 : 2), - caller(), - std::forward(fx), - std::forward(args)...); + args_list(), + L, + boost + (is_variable ? 3 : 2), + caller(), + std::forward(fx), + std::forward(args)...); } else { using Ta = meta::conditional_t, object_type, T>; - #if defined(SOL_SAFE_USERTYPE) && SOL_SAFE_USERTYPE +#if defined(SOL_SAFE_USERTYPE) && SOL_SAFE_USERTYPE auto maybeo = stack::check_get(L, 1); if (!maybeo || maybeo.value() == nullptr) { if (is_variable) { @@ -547,12 +559,12 @@ namespace sol { } object_type* po = static_cast(maybeo.value()); object_type& o = *po; - #else +#else object_type& o = static_cast(*stack::get>(L, 1)); - #endif // Safety +#endif // Safety return stack::call_into_lua( - types(), args_list(), L, boost + (is_variable ? 3 : 2), caller(), std::forward(fx), o); + types(), args_list(), L, boost + (is_variable ? 3 : 2), caller(), std::forward(fx), o); } } } @@ -631,7 +643,9 @@ namespace sol { stack::stack_detail::undefined_metatable umf(L, &meta[0], &stack::stack_detail::set_undefined_methods_on); umf(); - construct_match(constructor_match(obj), L, argcount, boost + 1 + static_cast(syntax)); + // put userdata at the first index + lua_insert(L, 1); + construct_match(constructor_match(obj), L, argcount, boost + 1 + 1 + static_cast(syntax)); userdataref.push(); return 1; @@ -652,7 +666,9 @@ namespace sol { umf(); auto& func = std::get(f.functions); - stack::call_into_lua(r, a, L, boost + start, func, detail::implicit_wrapper(obj)); + // put userdata at the first index + lua_insert(L, 1); + stack::call_into_lua(r, a, L, boost + 1 + start, func, detail::implicit_wrapper(obj)); userdataref.push(); return 1; @@ -727,8 +743,7 @@ namespace sol { template static int call(lua_State* L, F&& f, Args&&... args) { - constexpr bool is_specialized = meta::any< - std::is_same, + constexpr bool is_specialized = meta::any, meta::is_specialization_of, meta::is_specialization_of, meta::is_specialization_of, @@ -747,7 +762,7 @@ namespace sol { } else { constexpr bool non_class_object_type = meta::any, - meta::boolean>::value != type::userdata>>::value; + meta::boolean>::value != type::userdata>>::value; if constexpr (non_class_object_type) { // The type being void means we don't have any arguments, so it might be a free functions? using args_list = typename traits_type::free_args_list; @@ -861,7 +876,8 @@ namespace sol { } } - template + template inline int call_user(lua_State* L) { auto& fx = stack::unqualified_get>(L, upvalue_index(start)); return call_wrapped(L, fx); diff --git a/headers/3rdparty/sol/compatibility.hpp b/headers/3rdparty/sol/compatibility.hpp index 7e904afd..bd1c0607 100644 --- a/headers/3rdparty/sol/compatibility.hpp +++ b/headers/3rdparty/sol/compatibility.hpp @@ -42,7 +42,9 @@ #ifndef COMPAT53_INCLUDE_SOURCE #define COMPAT53_INCLUDE_SOURCE 1 #endif // Build Compat Layer Inline + #include "compatibility/compat-5.3.h" +#include "compatibility/compat-5.4.h" #endif // SOL_NO_COMPAT diff --git a/headers/3rdparty/sol/compatibility/compat-5.4.h b/headers/3rdparty/sol/compatibility/compat-5.4.h new file mode 100644 index 00000000..80d65bd7 --- /dev/null +++ b/headers/3rdparty/sol/compatibility/compat-5.4.h @@ -0,0 +1,25 @@ +#ifndef NOT_KEPLER_PROJECT_COMPAT54_H_ +#define NOT_KEPLER_PROJECT_COMPAT54_H_ + +#if defined(__cplusplus) && !defined(COMPAT53_LUA_CPP) +extern "C" { +#endif +#include +#include +#include +#if defined(__cplusplus) && !defined(COMPAT53_LUA_CPP) +} +#endif + +#if defined(LUA_VERSION_NUM) && LUA_VERSION_NUM == 504 + +#if !defined(LUA_ERRGCMM) +/* So Lua 5.4 actually removes this, which breaks sol2... + man, this API is quite unstable...! +*/ +# define LUA_ERRGCMM (LUA_ERRERR + 2) +#endif /* LUA_ERRGCMM define */ + +#endif // Lua 5.4 only + +#endif // NOT_KEPLER_PROJECT_COMPAT54_H_ \ No newline at end of file diff --git a/headers/3rdparty/sol/config.hpp b/headers/3rdparty/sol/config.hpp index 975c50e0..459bc7b9 100644 --- a/headers/3rdparty/sol/config.hpp +++ b/headers/3rdparty/sol/config.hpp @@ -65,14 +65,14 @@ #endif // vc++ || clang++/g++ // Compatibility Define -#if defined(SOL_CHECK_ARGUMENTS) && SOL_CHECK_ARGUMENTS +#if defined(SOL_CHECK_ARGUMENTS) && SOL_CHECK_ARGUMENTS != 0 #if defined(SOL_ALL_SAFETIES_ON) #define SOL_ALL_SAFETIES_ON 1 #endif // turn all the safeties on -#endif // Compatibility define +#endif // Compatibility Define for Safety // If this is defined, turn on all the safety checks automatically -#if defined(SOL_ALL_SAFETIES_ON) && SOL_ALL_SAFETIES_ON +#if defined(SOL_ALL_SAFETIES_ON) && SOL_ALL_SAFETIES_ON != 0 // Checks low-level getter function // (and thusly, affects nearly entire framework) @@ -142,7 +142,7 @@ #endif // Turn on Safety for all if top-level macro is defined // If we are in debug, turn on certain safety checks -#if defined(SOL_IN_DEBUG_DETECTED) && SOL_IN_DEBUG_DETECTED +#if defined(SOL_IN_DEBUG_DETECTED) && SOL_IN_DEBUG_DETECTED != 0 #if !defined(SOL_SAFE_REFERENCES) // Ensure that references are forcefully type-checked upon construction diff --git a/headers/3rdparty/sol/dump_handler.hpp b/headers/3rdparty/sol/dump_handler.hpp index aa3fd581..28d389dc 100644 --- a/headers/3rdparty/sol/dump_handler.hpp +++ b/headers/3rdparty/sol/dump_handler.hpp @@ -39,7 +39,7 @@ namespace sol { dump_error(int error_code_) : error("dump returned non-zero error of " + std::to_string(error_code_)), ec_(error_code_) { } - int error_code () const { + int error_code() const { return ec_; } }; @@ -52,14 +52,6 @@ namespace sol { return result_code; } - inline int dump_throw_on_error(lua_State* L, int result_code, lua_Writer writer_function, void* userdata, bool strip) { - (void)L; - (void)writer_function; - (void)userdata; - (void)strip; - throw dump_error(result_code); - } - inline int dump_panic_on_error(lua_State* L, int result_code, lua_Writer writer_function, void* userdata, bool strip) { (void)L; (void)writer_function; @@ -68,6 +60,18 @@ namespace sol { return luaL_error(L, "a non-zero error code (%d) was returned by the lua_Writer for the dump function", result_code); } + inline int dump_throw_on_error(lua_State* L, int result_code, lua_Writer writer_function, void* userdata, bool strip) { +#if defined(SOL_NO_EXCEPTIONS) && SOL_NO_EXCEPTIONS != 0 + return dump_panic_on_error(L, result_code, writer_function, userdata, strip); +#else + (void)L; + (void)writer_function; + (void)userdata; + (void)strip; + throw dump_error(result_code); +#endif // no exceptions stuff + } + } // namespace sol #endif // SOL_DUMP_HANDLER_HPP diff --git a/headers/3rdparty/sol/error_handler.hpp b/headers/3rdparty/sol/error_handler.hpp index 49831b0d..7e019cc9 100644 --- a/headers/3rdparty/sol/error_handler.hpp +++ b/headers/3rdparty/sol/error_handler.hpp @@ -1,4 +1,4 @@ -// sol3 +// sol3 // The MIT License (MIT) @@ -27,9 +27,17 @@ #include "types.hpp" #include "demangle.hpp" +#include + namespace sol { namespace detail { + constexpr const char* not_a_number = "not a numeric type"; + constexpr const char* not_a_number_or_number_string = "not a numeric type or numeric string"; + constexpr const char* not_a_number_integral = "not a numeric type that fits exactly an integer (has significant decimals)"; + constexpr const char* not_a_number_or_number_string_integral + = "not a numeric type or a numeric string that fits exactly an integer (has significant decimals)"; + constexpr const char* not_enough_stack_space = "not enough space left on Lua stack"; constexpr const char* not_enough_stack_space_floating = "not enough space left on Lua stack for a floating point number"; constexpr const char* not_enough_stack_space_integral = "not enough space left on Lua stack for an integral number"; @@ -40,21 +48,20 @@ namespace sol { constexpr const char* not_enough_stack_space_environment = "not enough space left on Lua stack to retrieve environment"; constexpr const char* protected_function_error = "caught (...) unknown error during protected_function call"; - inline void accumulate_and_mark(const std::string& n, std::string& addendum, int& marker) { + inline void accumulate_and_mark(const std::string& n, std::string& aux_message, int& marker) { if (marker > 0) { - addendum += ", "; + aux_message += ", "; } - addendum += n; + aux_message += n; ++marker; } - } + } // namespace detail inline std::string associated_type_name(lua_State* L, int index, type t) { switch (t) { case type::poly: return "anything"; - case type::userdata: - { + case type::userdata: { #if defined(SOL_SAFE_STACK_CHECK) && SOL_SAFE_STACK_CHECK luaL_checkstack(L, 2, "not enough space to push get the type name"); #endif // make sure stack doesn't overflow @@ -75,63 +82,67 @@ namespace sol { return lua_typename(L, static_cast(t)); } - inline int type_panic_string(lua_State* L, int index, type expected, type actual, const std::string& message = "") noexcept(false) { - const char* err = message.empty() ? "stack index %d, expected %s, received %s" : "stack index %d, expected %s, received %s: %s"; - std::string actualname = associated_type_name(L, index, actual); - return luaL_error(L, err, index, - expected == type::poly ? "anything" : lua_typename(L, static_cast(expected)), - actualname.c_str(), - message.c_str()); + inline int push_type_panic_string(lua_State* L, int index, type expected, type actual, string_view message, string_view aux_message) noexcept { + const char* err = message.size() == 0 + ? (aux_message.size() == 0 ? "stack index %d, expected %s, received %s" : "stack index %d, expected %s, received %s: %s") + : "stack index %d, expected %s, received %s: %s %s"; + const char* type_name = expected == type::poly ? "anything" : lua_typename(L, static_cast(expected)); + { + std::string actual_name = associated_type_name(L, index, actual); + lua_pushfstring(L, err, index, type_name, actual_name.c_str(), message.data(), aux_message.data()); + } + return 1; + } + + inline int type_panic_string(lua_State* L, int index, type expected, type actual, string_view message = "") noexcept(false) { + push_type_panic_string(L, index, expected, actual, message, ""); + return lua_error(L); } inline int type_panic_c_str(lua_State* L, int index, type expected, type actual, const char* message = nullptr) noexcept(false) { - const char* err = message == nullptr || (std::char_traits::length(message) == 0) ? "stack index %d, expected %s, received %s" : "stack index %d, expected %s, received %s: %s"; - std::string actualname = associated_type_name(L, index, actual); - return luaL_error(L, err, index, - expected == type::poly ? "anything" : lua_typename(L, static_cast(expected)), - actualname.c_str(), - message); + push_type_panic_string(L, index, expected, actual, message == nullptr ? "" : message, ""); + return lua_error(L); } struct type_panic_t { int operator()(lua_State* L, int index, type expected, type actual) const noexcept(false) { return type_panic_c_str(L, index, expected, actual, nullptr); } - int operator()(lua_State* L, int index, type expected, type actual, const char* message) const noexcept(false) { - return type_panic_c_str(L, index, expected, actual, message); - } - int operator()(lua_State* L, int index, type expected, type actual, const std::string& message) const noexcept(false) { - return type_panic_string(L, index, expected, actual, message); + int operator()(lua_State* L, int index, type expected, type actual, string_view message) const noexcept(false) { + return type_panic_c_str(L, index, expected, actual, message.data()); } }; const type_panic_t type_panic = {}; struct constructor_handler { - int operator()(lua_State* L, int index, type expected, type actual, const std::string& message) const noexcept(false) { - std::string str = "(type check failed in constructor)"; - return type_panic_string(L, index, expected, actual, message.empty() ? str : message + " " + str); + int operator()(lua_State* L, int index, type expected, type actual, string_view message) const noexcept(false) { + push_type_panic_string(L, index, expected, actual, message, "(type check failed in constructor)"); + return lua_error(L); } }; template struct argument_handler { - int operator()(lua_State* L, int index, type expected, type actual, const std::string& message) const noexcept(false) { - std::string str = "(bad argument to variable or function call)"; - return type_panic_string(L, index, expected, actual, message.empty() ? str : message + " " + str ); + int operator()(lua_State* L, int index, type expected, type actual, string_view message) const noexcept(false) { + push_type_panic_string(L, index, expected, actual, message, "(bad argument to variable or function call)"); + return lua_error(L); } }; template struct argument_handler> { - int operator()(lua_State* L, int index, type expected, type actual, const std::string& message) const noexcept(false) { - std::string addendum = "(bad argument into '"; - addendum += detail::demangle(); - addendum += "("; - int marker = 0; - (void)detail::swallow{int(), (detail::accumulate_and_mark(detail::demangle(), addendum, marker), int())...}; - addendum += ")')"; - return type_panic_string(L, index, expected, actual, message.empty() ? addendum : message + " " + addendum); + int operator()(lua_State* L, int index, type expected, type actual, string_view message) const noexcept(false) { + { + std::string aux_message = "(bad argument into '"; + aux_message += detail::demangle(); + aux_message += "("; + int marker = 0; + (void)detail::swallow{ int(), (detail::accumulate_and_mark(detail::demangle(), aux_message, marker), int())... }; + aux_message += ")')"; + push_type_panic_string(L, index, expected, actual, message, aux_message); + } + return lua_error(L); } }; diff --git a/headers/3rdparty/sol/feature_test.hpp b/headers/3rdparty/sol/feature_test.hpp index dd3b7077..e257c9a1 100644 --- a/headers/3rdparty/sol/feature_test.hpp +++ b/headers/3rdparty/sol/feature_test.hpp @@ -24,7 +24,7 @@ #ifndef SOL_FEATURE_TEST_HPP #define SOL_FEATURE_TEST_HPP -#if (defined(__cplusplus) && __cplusplus == 201703L) || (defined(_MSC_VER) && _MSC_VER > 1900 && ((defined(_HAS_CXX17) && _HAS_CXX17 == 1) || (defined(_MSVC_LANG) && (_MSVC_LANG > 201402L)))) +#if (defined(__cplusplus) && __cplusplus >= 201703L) || (defined(_MSC_VER) && _MSC_VER > 1900 && ((defined(_HAS_CXX17) && _HAS_CXX17 == 1) || (defined(_MSVC_LANG) && (_MSVC_LANG > 201402L)))) #ifndef SOL_CXX17_FEATURES #define SOL_CXX17_FEATURES 1 #endif // C++17 features macro diff --git a/headers/3rdparty/sol/forward.hpp b/headers/3rdparty/sol/forward.hpp index d8389890..1e81da74 100644 --- a/headers/3rdparty/sol/forward.hpp +++ b/headers/3rdparty/sol/forward.hpp @@ -28,17 +28,20 @@ #include #include +#include #if defined(SOL_USING_CXX_LUA) && SOL_USING_CXX_LUA struct lua_State; #else extern "C" { - struct lua_State; +struct lua_State; } #endif // C++ Mangling for Lua vs. Not namespace sol { + enum class type; + class stateless_reference; template class basic_reference; @@ -56,7 +59,7 @@ namespace sol { template struct proxy_base; template - struct proxy; + struct table_proxy; template class basic_table_core; @@ -235,6 +238,8 @@ namespace sol { class optional; #endif + using check_handler_type = int(lua_State*, int, type, type, const char*); + } // namespace sol #define SOL_BASE_CLASSES(T, ...) \ diff --git a/headers/3rdparty/sol/function.hpp b/headers/3rdparty/sol/function.hpp index 84dcaf67..bbbfc5ef 100644 --- a/headers/3rdparty/sol/function.hpp +++ b/headers/3rdparty/sol/function.hpp @@ -114,7 +114,7 @@ namespace sol { template static std::function get_std_func(types, lua_State* L, int index) { detail::std_shim fx(unsafe_function(L, index)); - return std::move(fx); + return fx; } static std::function get(lua_State* L, int index, record& tracking) { diff --git a/headers/3rdparty/sol/function_types.hpp b/headers/3rdparty/sol/function_types.hpp index cad99097..e17c4a4e 100644 --- a/headers/3rdparty/sol/function_types.hpp +++ b/headers/3rdparty/sol/function_types.hpp @@ -129,7 +129,7 @@ namespace sol { dFx memfxptr(std::forward(fx)); auto userptr = detail::ptr(std::forward(args)...); lua_CFunction freefunc - = &function_detail::upvalue_member_variable, meta::unqualified_t, is_yielding>::call; + = &function_detail::upvalue_member_variable, meta::unqualified_t, is_yielding>::call; int upvalues = 0; upvalues += stack::push(L, nullptr); @@ -250,13 +250,29 @@ namespace sol { namespace stack { template struct unqualified_pusher> { + template + static int push(lua_State* L, Arg0&& arg0, Args&&... args) { + if constexpr (meta::is_specialization_of_v, std::function>) { + if constexpr (is_yielding) { + return stack::push>(L, detail::yield_tag, std::forward(arg0), std::forward(args)...); + } + else { + return stack::push(L, std::forward(arg0), std::forward(args)...); + } + } + else { + function_detail::select(L, std::forward(arg0), std::forward(args)...); + return 1; + } + } + template static int push(lua_State* L, Arg0&& arg0, Args&&... args) { if constexpr (std::is_same_v, detail::yield_tag_t>) { - function_detail::select(L, std::forward(args)...); + push(L, std::forward(args)...); } else { - function_detail::select(L, std::forward(arg0), std::forward(args)...); + push(L, std::forward(arg0), std::forward(args)...); } return 1; } @@ -266,14 +282,24 @@ namespace sol { struct unqualified_pusher> { template static int push(lua_State* L, const yielding_t& f, Args&&... args) { - function_detail::select(L, f.func, std::forward(args)...); - return 1; + if constexpr (meta::is_specialization_of_v, std::function>) { + return stack::push(L, detail::yield_tag, f.func, std::forward(args)...); + } + else { + function_detail::select(L, f.func, std::forward(args)...); + return 1; + } } template static int push(lua_State* L, yielding_t&& f, Args&&... args) { - function_detail::select(L, std::move(f.func), std::forward(args)...); - return 1; + if constexpr (meta::is_specialization_of_v, std::function>) { + return stack::push(L, detail::yield_tag, std::move(f.func), std::forward(args)...); + } + else { + function_detail::select(L, std::move(f.func), std::forward(args)...); + return 1; + } } }; @@ -295,14 +321,36 @@ namespace sol { template struct unqualified_pusher> { + static int push(lua_State* L, detail::yield_tag_t, const std::function& fx) { + if (fx) { + function_detail::select(L, fx); + return 1; + } + return stack::push(L, lua_nil); + } + + static int push(lua_State* L, detail::yield_tag_t, std::function&& fx) { + if (fx) { + function_detail::select(L, std::move(fx)); + return 1; + } + return stack::push(L, lua_nil); + } + static int push(lua_State* L, const std::function& fx) { - function_detail::select(L, fx); - return 1; + if (fx) { + function_detail::select(L, fx); + return 1; + } + return stack::push(L, lua_nil); } static int push(lua_State* L, std::function&& fx) { - function_detail::select(L, std::move(fx)); - return 1; + if (fx) { + function_detail::select(L, std::move(fx)); + return 1; + } + return stack::push(L, lua_nil); } }; diff --git a/headers/3rdparty/sol/inheritance.hpp b/headers/3rdparty/sol/inheritance.hpp index 68799e5a..6abe6ad9 100644 --- a/headers/3rdparty/sol/inheritance.hpp +++ b/headers/3rdparty/sol/inheritance.hpp @@ -37,6 +37,9 @@ namespace sol { typedef bases<> base_classes_tag; const auto base_classes = base_classes_tag(); + template + struct is_to_stringable> : std::false_type {}; + namespace detail { inline decltype(auto) base_class_check_key() { diff --git a/headers/3rdparty/sol/optional_implementation.hpp b/headers/3rdparty/sol/optional_implementation.hpp index 0d9abc0e..833fc83f 100644 --- a/headers/3rdparty/sol/optional_implementation.hpp +++ b/headers/3rdparty/sol/optional_implementation.hpp @@ -48,6 +48,7 @@ #include #include #include +#include #if (defined(_MSC_VER) && _MSC_VER == 1900) #define SOL_TL_OPTIONAL_MSVC2015 @@ -109,7 +110,7 @@ namespace sol { namespace detail { /// \exclude #define SOL_TL_OPTIONAL_11_CONSTEXPR #else -/// \exclude + /// \exclude #define SOL_TL_OPTIONAL_11_CONSTEXPR constexpr #endif @@ -448,10 +449,12 @@ namespace sol { // This specialization is for when T is not trivially copy constructible template struct optional_copy_base : optional_operations_base { - using optional_operations_base::optional_operations_base; + using base_t = optional_operations_base; + + using base_t::base_t; optional_copy_base() = default; - optional_copy_base(const optional_copy_base& rhs) { + optional_copy_base(const optional_copy_base& rhs) : base_t() { if (rhs.has_value()) { this->construct(rhs.get()); } @@ -500,7 +503,8 @@ namespace sol { // This class manages conditionally having a trivial copy assignment operator template + bool = SOL_TL_OPTIONAL_IS_TRIVIALLY_COPY_ASSIGNABLE(T) && SOL_TL_OPTIONAL_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(T) + && SOL_TL_OPTIONAL_IS_TRIVIALLY_DESTRUCTIBLE(T)> struct optional_copy_assign_base : optional_move_base { using optional_move_base::optional_move_base; }; @@ -1124,8 +1128,8 @@ namespace sol { } #if 0 // SOL_MODIFICATION - /// Constructs the stored value with `u`. - /// \synopsis template constexpr optional(U &&u); + /// Constructs the stored value with `u`. + /// \synopsis template constexpr optional(U &&u); template ::value>* = nullptr, detail::enable_forward_value* = nullptr> constexpr optional(U&& u) : base(in_place, std::forward(u)) { } @@ -1368,20 +1372,32 @@ namespace sol { SOL_TL_OPTIONAL_11_CONSTEXPR T& value() & { if (has_value()) return this->m_value; +#if defined(SOL_NO_EXCEPTIONS) && SOL_NO_EXCEPTIONS != 0 + std::abort(); +#else throw bad_optional_access(); +#endif // No exceptions allowed } /// \group value /// \synopsis constexpr const T &value() const; SOL_TL_OPTIONAL_11_CONSTEXPR const T& value() const& { if (has_value()) return this->m_value; +#if defined(SOL_NO_EXCEPTIONS) && SOL_NO_EXCEPTIONS != 0 + std::abort(); +#else throw bad_optional_access(); +#endif // No exceptions allowed } /// \exclude SOL_TL_OPTIONAL_11_CONSTEXPR T&& value() && { if (has_value()) return std::move(this->m_value); +#if defined(SOL_NO_EXCEPTIONS) && SOL_NO_EXCEPTIONS != 0 + std::abort(); +#else throw bad_optional_access(); +#endif // No exceptions allowed } #ifndef SOL_TL_OPTIONAL_NO_CONSTRR @@ -1389,7 +1405,11 @@ namespace sol { SOL_TL_OPTIONAL_11_CONSTEXPR const T&& value() const&& { if (has_value()) return std::move(this->m_value); +#if defined(SOL_NO_EXCEPTIONS) && SOL_NO_EXCEPTIONS != 0 + std::abort(); +#else throw bad_optional_access(); +#endif // No exceptions allowed } #endif @@ -2227,14 +2247,22 @@ namespace sol { SOL_TL_OPTIONAL_11_CONSTEXPR T& value() { if (has_value()) return *m_value; +#if defined(SOL_NO_EXCEPTIONS) && SOL_NO_EXCEPTIONS != 0 + std::abort(); +#else throw bad_optional_access(); +#endif // No exceptions allowed } /// \group value /// \synopsis constexpr const T &value() const; SOL_TL_OPTIONAL_11_CONSTEXPR const T& value() const { if (has_value()) return *m_value; +#if defined(SOL_NO_EXCEPTIONS) && SOL_NO_EXCEPTIONS != 0 + std::abort(); +#else throw bad_optional_access(); +#endif // No exceptions allowed } /// \returns the stored value if there is one, otherwise returns `u` @@ -2259,12 +2287,12 @@ namespace sol { namespace std { // TODO SFINAE template - struct hash< ::sol::optional > { + struct hash<::sol::optional> { ::std::size_t operator()(const ::sol::optional& o) const { if (!o.has_value()) return 0; - return ::std::hash< ::sol::detail::remove_const_t>()(*o); + return ::std::hash<::sol::detail::remove_const_t>()(*o); } }; } // namespace std diff --git a/headers/3rdparty/sol/pointer_like.hpp b/headers/3rdparty/sol/pointer_like.hpp index 054aee5a..569cf42e 100644 --- a/headers/3rdparty/sol/pointer_like.hpp +++ b/headers/3rdparty/sol/pointer_like.hpp @@ -71,9 +71,9 @@ namespace sol { } template - inline decltype(auto) deref_non_pointer(T&& item) { + inline decltype(auto) deref_move_only(T&& item) { using Tu = meta::unqualified_t; - if constexpr (meta::is_pointer_like_v && !std::is_pointer_v) { + if constexpr (meta::is_pointer_like_v && !std::is_pointer_v && !std::is_copy_constructible_v) { return *std::forward(item); } else { diff --git a/headers/3rdparty/sol/policies.hpp b/headers/3rdparty/sol/policies.hpp index 7b8d738e..9bba77c8 100644 --- a/headers/3rdparty/sol/policies.hpp +++ b/headers/3rdparty/sol/policies.hpp @@ -1,4 +1,4 @@ -// sol3 +// sol3 // The MIT License (MIT) @@ -46,10 +46,9 @@ namespace sol { std::size_t len; template - stack_dependencies(int stack_target, Args&&... args) - : target(stack_target), stack_indices(), len(sizeof...(Args)) { + stack_dependencies(int stack_target, Args&&... args) : target(stack_target), stack_indices(), len(sizeof...(Args)) { std::size_t i = 0; - (void)detail::swallow{int(), (stack_indices[i++] = static_cast(std::forward(args)), int())...}; + (void)detail::swallow{ int(), (stack_indices[i++] = static_cast(std::forward(args)), int())... }; } int& operator[](std::size_t i) { @@ -73,8 +72,7 @@ namespace sol { std::tuple policies; template , policy_wrapper>>> = meta::enabler> - policy_wrapper(Fx&& fx, Args&&... args) - : value(std::forward(fx)), policies(std::forward(args)...) { + policy_wrapper(Fx&& fx, Args&&... args) : value(std::forward(fx)), policies(std::forward(args)...) { } policy_wrapper(const policy_wrapper&) = default; @@ -91,10 +89,10 @@ namespace sol { namespace detail { template using is_policy = meta::is_specialization_of; - + template inline constexpr bool is_policy_v = is_policy::value; - } + } // namespace detail } // namespace sol #endif // SOL_FILTERS_HPP diff --git a/headers/3rdparty/sol/reference.hpp b/headers/3rdparty/sol/reference.hpp index 3859beab..d5fba1d5 100644 --- a/headers/3rdparty/sol/reference.hpp +++ b/headers/3rdparty/sol/reference.hpp @@ -557,11 +557,11 @@ namespace sol { } basic_reference(const basic_reference& o) noexcept - : basic_reference(detail::pick_main_thread < main_only && !main_only > (o.lua_state(), o.lua_state()), o) { + : basic_reference(detail::pick_main_thread(o.lua_state(), o.lua_state()), o) { } basic_reference(basic_reference&& o) noexcept - : stateless_reference(std::move(o)), luastate(detail::pick_main_thread(o.lua_state(), o.lua_state())) { + : stateless_reference(std::move(o)), luastate(detail::pick_main_thread(o.lua_state(), o.lua_state())) { o.luastate = nullptr; o.ref = LUA_NOREF; } diff --git a/headers/3rdparty/sol/stack_check_unqualified.hpp b/headers/3rdparty/sol/stack_check_unqualified.hpp index 1694658a..025961c4 100644 --- a/headers/3rdparty/sol/stack_check_unqualified.hpp +++ b/headers/3rdparty/sol/stack_check_unqualified.hpp @@ -111,7 +111,7 @@ namespace sol { namespace stack { const bool success = isnum != 0; if (!success) { // expected type, actual type - handler(L, index, type::number, type_of(L, index), "not a numeric type or numeric string"); + handler(L, index, type::number, type_of(L, index), detail::not_a_number_or_number_string_integral); } #elif (defined(SOL_SAFE_NUMERICS) && SOL_SAFE_NUMERICS) && !(defined(SOL_NO_CHECK_NUMBER_PRECISION) && SOL_NO_CHECK_NUMBER_PRECISION) // this check is precise, does not convert @@ -121,7 +121,7 @@ namespace sol { namespace stack { const bool success = false; if (!success) { // expected type, actual type - handler(L, index, type::number, type_of(L, index), "not a numeric type that fits exactly an integer (has significant decimals)"); + handler(L, index, type::number, type_of(L, index), detail::not_a_number_integral); } #else type t = type_of(L, index); @@ -129,7 +129,7 @@ namespace sol { namespace stack { #endif // If numbers are enabled, use the imprecise check if (!success) { // expected type, actual type - handler(L, index, type::number, type_of(L, index), "not a numeric type"); + handler(L, index, type::number, type_of(L, index), detail::not_a_number); } return success; #else @@ -138,7 +138,7 @@ namespace sol { namespace stack { type t = type_of(L, index); if (t != type::number) { // expected type, actual type - handler(L, index, type::number, t, "not a numeric type"); + handler(L, index, type::number, t, detail::not_a_number); return false; } #endif // Do not allow strings to be numbers @@ -152,11 +152,11 @@ namespace sol { namespace stack { if (!success) { // expected type, actual type #if defined(SOL_STRINGS_ARE_NUMBERS) && SOL_STRINGS_ARE_NUMBERS - handler(L, index, type::number, type_of(L, index), "not a numeric type or numeric string"); + handler(L, index, type::number, type_of(L, index), detail::not_a_number_or_number_string); #elif (defined(SOL_SAFE_NUMERICS) && SOL_SAFE_NUMERICS) - handler(L, index, type::number, t, "not a numeric type that fits exactly an integer (has significant decimals)"); + handler(L, index, type::number, t, detail::not_a_number_or_number_string); #else - handler(L, index, type::number, t, "not a numeric type"); + handler(L, index, type::number, t, detail::not_a_number); #endif } return success; @@ -168,7 +168,7 @@ namespace sol { namespace stack { bool success = lua_isnumber(L, index) == 1; if (!success) { // expected type, actual type - handler(L, index, type::number, type_of(L, index), "not a numeric type or numeric string"); + handler(L, index, type::number, type_of(L, index), detail::not_a_number_or_number_string); } return success; #else @@ -176,7 +176,7 @@ namespace sol { namespace stack { bool success = t == type::number; if (!success) { // expected type, actual type - handler(L, index, type::number, t, "not a numeric type"); + handler(L, index, type::number, t, detail::not_a_number); } return success; #endif // Strings are Numbers diff --git a/headers/3rdparty/sol/stack_field.hpp b/headers/3rdparty/sol/stack_field.hpp index 90615874..036ad3ed 100644 --- a/headers/3rdparty/sol/stack_field.hpp +++ b/headers/3rdparty/sol/stack_field.hpp @@ -29,13 +29,15 @@ #include "stack_get.hpp" #include "stack_check_get.hpp" -namespace sol { -namespace stack { +namespace sol { namespace stack { template struct field_getter { - static constexpr int default_table_index = meta::conditional_t || (std::is_integral_v && !std::is_same_v) - || (std::is_integral_v && !std::is_same_v) || (raw && std::is_void_v>), - std::integral_constant, std::integral_constant> ::value; + static constexpr int default_table_index = meta::conditional_t < meta::is_c_str_v +#if SOL_LUA_VERSION >= 503 + || (std::is_integral_v && !std::is_same_v) +#endif // integer global keys 5.3 or better + || (raw && std::is_void_v>), + std::integral_constant, std::integral_constant> ::value; template void get(lua_State* L, Key&& key, int tableindex = default_table_index) { @@ -61,7 +63,7 @@ namespace stack { if (lua_getmetatable(L, tableindex) == 0) push(L, lua_nil); } - else if constexpr(raw) { + else if constexpr (raw) { if constexpr (std::is_integral_v && !std::is_same_v) { lua_rawgeti(L, tableindex, static_cast(key)); } @@ -69,7 +71,7 @@ namespace stack { else if constexpr (std::is_void_v>) { lua_rawgetp(L, tableindex, key); } -#endif // Lua 5.3.x +#endif // Lua 5.2.x+ else { push(L, std::forward(key)); lua_rawget(L, tableindex); @@ -89,7 +91,7 @@ namespace stack { else if constexpr (std::is_integral_v && !std::is_same_v) { lua_geti(L, tableindex, static_cast(key)); } -#endif // Lua 5.3.x +#endif // Lua 5.3.x+ else { push(L, std::forward(key)); lua_gettable(L, tableindex); @@ -103,7 +105,7 @@ namespace stack { template void apply(std::index_sequence<0, I...>, lua_State* L, Keys&& keys, int tableindex) { get_field(L, std::get<0>(std::forward(keys)), tableindex); - void(detail::swallow { (get_field(L, std::get(std::forward(keys))), 0)... }); + void(detail::swallow{ (get_field(L, std::get(std::forward(keys))), 0)... }); reference saved(L, -1); lua_pop(L, static_cast(sizeof...(I))); saved.push(); @@ -143,9 +145,10 @@ namespace stack { template struct field_setter { - static constexpr int default_table_index = meta::conditional_t<(meta::is_c_str_v || meta::is_string_of_v) || (std::is_integral_v && !std::is_same_v) + static constexpr int default_table_index + = meta::conditional_t < (meta::is_c_str_v || meta::is_string_of_v) || (std::is_integral_v && !std::is_same_v) || (std::is_integral_v && !std::is_same_v) || (raw && std::is_void_v>), - std::integral_constant, std::integral_constant> ::value; + std::integral_constant, std::integral_constant> ::value; template void set(lua_State* L, Key&& key, Value&& value, int tableindex = default_table_index) { @@ -190,7 +193,7 @@ namespace stack { } } #if SOL_LUA_VERSION >= 503 - else if constexpr(std::is_integral_v && !std::is_same_v) { + else if constexpr (std::is_integral_v && !std::is_same_v) { push(L, std::forward(value)); lua_seti(L, tableindex, static_cast(key)); } @@ -240,7 +243,6 @@ namespace stack { lua_pop(L, 1); } }; -} -} // namespace sol::stack +}} // namespace sol::stack #endif // SOL_STACK_FIELD_HPP diff --git a/headers/3rdparty/sol/state_view.hpp b/headers/3rdparty/sol/state_view.hpp index cb5f1ead..6ba092e4 100644 --- a/headers/3rdparty/sol/state_view.hpp +++ b/headers/3rdparty/sol/state_view.hpp @@ -682,12 +682,12 @@ namespace sol { } template - proxy> operator[](T&& key) { + table_proxy> operator[](T&& key) { return global[std::forward(key)]; } template - proxy> operator[](T&& key) const { + table_proxy> operator[](T&& key) const { return global[std::forward(key)]; } diff --git a/headers/3rdparty/sol/table_core.hpp b/headers/3rdparty/sol/table_core.hpp index 1786fe9a..d68c180b 100644 --- a/headers/3rdparty/sol/table_core.hpp +++ b/headers/3rdparty/sol/table_core.hpp @@ -24,7 +24,7 @@ #ifndef SOL_TABLE_CORE_HPP #define SOL_TABLE_CORE_HPP -#include "proxy.hpp" +#include "table_proxy.hpp" #include "stack.hpp" #include "function_types.hpp" #include "table_iterator.hpp" @@ -318,8 +318,9 @@ namespace sol { basic_table_core(lua_State* L, T&& r) : base_t(L, std::forward(r)) { #if defined(SOL_SAFE_REFERENCES) && SOL_SAFE_REFERENCES auto pp = stack::push_pop(*this); + int table_index = pp.index_of(*this); constructor_handler handler{}; - stack::check(lua_state(), -1, handler); + stack::check(lua_state(), table_index, handler); #endif // Safety } basic_table_core(lua_State* L, const new_table& nt) : base_t(L, -stack::push(L, nt)) { @@ -336,8 +337,9 @@ namespace sol { basic_table_core(lua_State* L, ref_index index) : basic_table_core(detail::no_safety, L, index) { #if defined(SOL_SAFE_REFERENCES) && SOL_SAFE_REFERENCES auto pp = stack::push_pop(*this); + int table_index = pp.index_of(*this); constructor_handler handler{}; - stack::check(lua_state(), -1, handler); + stack::check(lua_state(), table_index, handler); #endif // Safety } template >::value) { auto pp = stack::push_pop(*this); + int table_index = pp.index_of(*this); constructor_handler handler{}; - stack::check(lua_state(), -1, handler); + stack::check(lua_state(), table_index, handler); } #endif // Safety } @@ -535,8 +538,9 @@ namespace sol { lua_State* L = base_t::lua_state(); if constexpr (std::is_invocable_v) { auto pp = stack::push_pop(*this); + int table_index = pp.index_of(*this); stack::push(L, lua_nil); - while (lua_next(L, -2)) { + while (lua_next(L, table_index)) { Key key(L, -2); Value value(L, -1); auto pn = stack::pop_n(L, 1); @@ -545,8 +549,9 @@ namespace sol { } else { auto pp = stack::push_pop(*this); + int table_index = pp.index_of(*this); stack::push(L, lua_nil); - while (lua_next(L, -2)) { + while (lua_next(L, table_index)) { Key key(L, -2); Value value(L, -1); auto pn = stack::pop_n(L, 1); @@ -558,8 +563,9 @@ namespace sol { size_t size() const { auto pp = stack::push_pop(*this); + int table_index = pp.index_of(*this); lua_State* L = base_t::lua_state(); - lua_len(L, -1); + lua_len(L, table_index); return stack::pop(L); } @@ -569,17 +575,17 @@ namespace sol { template auto operator[](T&& key) & { - return proxy>(*this, std::forward(key)); + return table_proxy>(*this, std::forward(key)); } template auto operator[](T&& key) const& { - return proxy>(*this, std::forward(key)); + return table_proxy>(*this, std::forward(key)); } template auto operator[](T&& key) && { - return proxy>(std::move(*this), std::forward(key)); + return table_proxy>(std::move(*this), std::forward(key)); } template diff --git a/headers/3rdparty/sol/table_proxy.hpp b/headers/3rdparty/sol/table_proxy.hpp new file mode 100644 index 00000000..f0905b57 --- /dev/null +++ b/headers/3rdparty/sol/table_proxy.hpp @@ -0,0 +1,337 @@ +// sol3 + +// The MIT License (MIT) + +// Copyright (c) 2013-2019 Rapptz, ThePhD and contributors + +// Permission is hereby granted, free of charge, to any person obtaining a copy of +// this software and associated documentation files (the "Software"), to deal in +// the Software without restriction, including without limitation the rights to +// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +// the Software, and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: + +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +#ifndef SOL_TABLE_PROXY_HPP +#define SOL_TABLE_PROXY_HPP + +#include "traits.hpp" +#include "function.hpp" +#include "protected_function.hpp" +#include "proxy_base.hpp" + +namespace sol { + + template + struct table_proxy : public proxy_base> { + private: + using key_type = detail::proxy_key_t; + + template + decltype(auto) tuple_get(std::index_sequence) const& { + return tbl.template traverse_get(std::get(key)...); + } + + template + decltype(auto) tuple_get(std::index_sequence) && { + return tbl.template traverse_get(std::get(std::move(key))...); + } + + template + void tuple_set(std::index_sequence, T&& value) & { + tbl.traverse_set(std::get(key)..., std::forward(value)); + } + + template + void tuple_set(std::index_sequence, T&& value) && { + tbl.traverse_set(std::get(std::move(key))..., std::forward(value)); + } + + auto setup_table(std::true_type) { + auto p = stack::probe_get_field, global_table>>(lua_state(), key, tbl.stack_index()); + lua_pop(lua_state(), p.levels); + return p; + } + + bool is_valid(std::false_type) { + auto pp = stack::push_pop(tbl); + auto p = stack::probe_get_field, global_table>>(lua_state(), key, lua_gettop(lua_state())); + lua_pop(lua_state(), p.levels); + return p; + } + + public: + Table tbl; + key_type key; + + template + table_proxy(Table table, T&& k) : tbl(table), key(std::forward(k)) { + } + + template + table_proxy& set(T&& item) & { + tuple_set(std::make_index_sequence>>(), std::forward(item)); + return *this; + } + + template + table_proxy&& set(T&& item) && { + tuple_set(std::make_index_sequence>>(), std::forward(item)); + return std::move(*this); + } + + template + table_proxy& set_function(Args&&... args) & { + tbl.set_function(key, std::forward(args)...); + return *this; + } + + template + table_proxy&& set_function(Args&&... args) && { + tbl.set_function(std::move(key), std::forward(args)...); + return std::move(*this); + } + + template + table_proxy& operator=(T&& other) & { + using Tu = meta::unwrap_unqualified_t; + if constexpr (!is_lua_reference_or_proxy_v && meta::is_callable_v) { + return set_function(std::forward(other)); + } + else { + return set(std::forward(other)); + } + } + + template + table_proxy&& operator=(T&& other) && { + using Tu = meta::unwrap_unqualified_t; + if constexpr (!is_lua_reference_or_proxy_v && meta::is_callable_v) { + return std::move(*this).set_function(std::forward(other)); + } + else { + return std::move(*this).set(std::forward(other)); + } + } + + template + table_proxy& operator=(std::initializer_list other) & { + return set(std::move(other)); + } + + template + table_proxy&& operator=(std::initializer_list other) && { + return std::move(*this).set(std::move(other)); + } + + template + decltype(auto) get() const& { + using idx_seq = std::make_index_sequence>>; + return tuple_get(idx_seq()); + } + + template + decltype(auto) get() && { + using idx_seq = std::make_index_sequence>>; + return std::move(*this).template tuple_get(idx_seq()); + } + + template + decltype(auto) get_or(T&& otherwise) const { + typedef decltype(get()) U; + optional option = get>(); + if (option) { + return static_cast(option.value()); + } + return static_cast(std::forward(otherwise)); + } + + template + decltype(auto) get_or(D&& otherwise) const { + optional option = get>(); + if (option) { + return static_cast(option.value()); + } + return static_cast(std::forward(otherwise)); + } + + + template + decltype(auto) get_or_create() { + return get_or_create(new_table()); + } + + template + decltype(auto) get_or_create(Otherwise&& other) { + if (!this->valid()) { + this->set(std::forward(other)); + } + return get(); + } + + template + decltype(auto) operator[](K&& k) const& { + auto keys = meta::tuplefy(key, std::forward(k)); + return table_proxy(tbl, std::move(keys)); + } + + template + decltype(auto) operator[](K&& k) & { + auto keys = meta::tuplefy(key, std::forward(k)); + return table_proxy(tbl, std::move(keys)); + } + + template + decltype(auto) operator[](K&& k) && { + auto keys = meta::tuplefy(std::move(key), std::forward(k)); + return table_proxy(tbl, std::move(keys)); + } + + template + decltype(auto) call(Args&&... args) { + lua_State* L = this->lua_state(); + push(L); + int idx = lua_gettop(L); + stack_aligned_function func(L, idx); + return func.call(std::forward(args)...); + } + + template + decltype(auto) operator()(Args&&... args) { + return call<>(std::forward(args)...); + } + + bool valid() const { + auto pp = stack::push_pop(tbl); + auto p = stack::probe_get_field, global_table>::value>(lua_state(), key, lua_gettop(lua_state())); + lua_pop(lua_state(), p.levels); + return p; + } + + int push() const noexcept { + return push(this->lua_state()); + } + + int push(lua_State* L) const noexcept { + if constexpr (std::is_same_v, global_table> || is_stack_table_v>) { + auto pp = stack::push_pop(tbl); + int tableindex = pp.index_of(tbl); + int top_index = lua_gettop(L); + stack::get_field(lua_state(), key, tableindex); + lua_replace(L, top_index + 1); + lua_settop(L, top_index + 1); + } + else { + auto pp = stack::push_pop(tbl); + int tableindex = pp.index_of(tbl); + int aftertableindex = lua_gettop(L); + stack::get_field(lua_state(), key, tableindex); + lua_replace(L, tableindex); + lua_settop(L, aftertableindex + 1); + } + return 1; + } + + type get_type() const { + type t = type::none; + auto pp = stack::push_pop(tbl); + auto p = stack::probe_get_field, global_table>::value>(lua_state(), key, lua_gettop(lua_state())); + if (p) { + t = type_of(lua_state(), -1); + } + lua_pop(lua_state(), p.levels); + return t; + } + + lua_State* lua_state() const { + return tbl.lua_state(); + } + + table_proxy& force() { + if (!this->valid()) { + this->set(new_table()); + } + return *this; + } + }; + + template + inline bool operator==(T&& left, const table_proxy& right) { + using G = decltype(stack::get(nullptr, 0)); + return right.template get>() == left; + } + + template + inline bool operator==(const table_proxy& right, T&& left) { + using G = decltype(stack::get(nullptr, 0)); + return right.template get>() == left; + } + + template + inline bool operator!=(T&& left, const table_proxy& right) { + using G = decltype(stack::get(nullptr, 0)); + return right.template get>() != left; + } + + template + inline bool operator!=(const table_proxy& right, T&& left) { + using G = decltype(stack::get(nullptr, 0)); + return right.template get>() != left; + } + + template + inline bool operator==(lua_nil_t, const table_proxy& right) { + return !right.valid(); + } + + template + inline bool operator==(const table_proxy& right, lua_nil_t) { + return !right.valid(); + } + + template + inline bool operator!=(lua_nil_t, const table_proxy& right) { + return right.valid(); + } + + template + inline bool operator!=(const table_proxy& right, lua_nil_t) { + return right.valid(); + } + + template + template + basic_reference& basic_reference::operator=(proxy_base&& r) { + basic_reference v = r; + this->operator=(std::move(v)); + return *this; + } + + template + template + basic_reference& basic_reference::operator=(const proxy_base& r) { + basic_reference v = r; + this->operator=(std::move(v)); + return *this; + } + + namespace stack { + template + struct unqualified_pusher> { + static int push(lua_State* L, const table_proxy& p) { + return p.push(L); + } + }; + } // namespace stack +} // namespace sol + +#endif // SOL_TABLE_PROXY_HPP diff --git a/headers/3rdparty/sol/traits.hpp b/headers/3rdparty/sol/traits.hpp index ca6a841b..b47fdc94 100644 --- a/headers/3rdparty/sol/traits.hpp +++ b/headers/3rdparty/sol/traits.hpp @@ -283,7 +283,7 @@ namespace sol { std::enable_if_t>::value && std::is_class>::value && std::is_destructible>::value>> { struct F { - void operator()(); + void operator()() {}; }; struct Derived : T, F {}; template @@ -303,7 +303,7 @@ namespace sol { std::enable_if_t>::value && std::is_class>::value && !std::is_destructible>::value>> { struct F { - void operator()(); + void operator()() {}; }; struct Derived : T, F { ~Derived() = delete; diff --git a/headers/3rdparty/sol/types.hpp b/headers/3rdparty/sol/types.hpp index 7441df30..96c62e82 100644 --- a/headers/3rdparty/sol/types.hpp +++ b/headers/3rdparty/sol/types.hpp @@ -422,7 +422,7 @@ namespace sol { struct as_container_t { private: T value_; - + public: using type = T; @@ -504,7 +504,7 @@ namespace sol { return std::move(value_); } - const T& value() const & { + const T& value() const& { return value_; } }; @@ -867,16 +867,14 @@ namespace sol { } template - struct is_lua_reference : std::integral_constant || std::is_base_of_v - || std::is_base_of_v> {}; + struct is_lua_reference + : std::integral_constant || std::is_base_of_v || std::is_base_of_v> {}; template inline constexpr bool is_lua_reference_v = is_lua_reference::value; template - struct is_lua_reference_or_proxy - : std::integral_constant || meta::is_specialization_of_v> {}; + struct is_lua_reference_or_proxy : std::integral_constant || meta::is_specialization_of_v> {}; template inline constexpr bool is_lua_reference_or_proxy_v = is_lua_reference_or_proxy::value; @@ -901,7 +899,8 @@ namespace sol { template struct is_container : std::integral_constant && !std::is_same_v && !meta::is_initializer_list_v && !meta::is_string_like_v && !meta::is_string_literal_array_v && !is_transparent_argument_v && !is_lua_reference_v && (meta::has_begin_end_v || std::is_array_v)> { + !std::is_same_v && !std::is_same_v && !meta::is_initializer_list_v && !meta::is_string_like_v && !meta::is_string_literal_array_v && !is_transparent_argument_v && !is_lua_reference_v && (meta::has_begin_end_v || std::is_array_v)> { }; template @@ -1098,7 +1097,8 @@ namespace sol { struct lua_type_of : std::integral_constant {}; template - struct lua_type_of || std::is_same_v || std::is_same_v>> : std::integral_constant {}; + struct lua_type_of || std::is_same_v || std::is_same_v>> + : std::integral_constant {}; template struct lua_type_of>> : std::integral_constant {}; @@ -1114,8 +1114,7 @@ namespace sol { #endif // SOL_CXX17_FEATURES template - struct lua_type_of> - : meta::conditional_t<::sol::is_container_v, std::integral_constant, lua_type_of> {}; + struct lua_type_of> : meta::conditional_t<::sol::is_container_v, std::integral_constant, lua_type_of> {}; template class V, typename... Args> struct accumulate : std::integral_constant {}; @@ -1172,11 +1171,10 @@ namespace sol { template struct is_lua_primitive : std::integral_constant - || ((type::userdata == lua_type_of_v) && detail::has_internal_marker_v> - && !detail::has_internal_marker_v>) - || is_lua_reference_v || meta::is_specialization_of_v - || meta::is_specialization_of_v> {}; + type::userdata + != lua_type_of_v< + T> || ((type::userdata == lua_type_of_v)&&detail::has_internal_marker_v> && !detail::has_internal_marker_v>) + || is_lua_reference_or_proxy_v || meta::is_specialization_of_v || meta::is_specialization_of_v> {}; template constexpr inline bool is_lua_primitive_v = is_lua_primitive::value; @@ -1265,6 +1263,16 @@ namespace sol { template inline constexpr bool is_table_v = is_table::value; + template + struct is_stack_table : std::false_type {}; + template + struct is_stack_table> : std::integral_constant> {}; + template + struct is_stack_table> : std::integral_constant> {}; + + template + inline constexpr bool is_stack_table_v = is_stack_table::value; + template struct is_function : std::false_type {}; template @@ -1300,7 +1308,8 @@ namespace sol { template struct is_automagical : std::integral_constant> || !std::is_same_v, state> || !std::is_same_v, state_view>> {}; + std::is_array_v> || !std::is_same_v, state> || !std::is_same_v, state_view>> { + }; template inline type type_of() { diff --git a/headers/3rdparty/sol/unique_usertype_traits.hpp b/headers/3rdparty/sol/unique_usertype_traits.hpp index fbd3e179..75b248dd 100644 --- a/headers/3rdparty/sol/unique_usertype_traits.hpp +++ b/headers/3rdparty/sol/unique_usertype_traits.hpp @@ -95,8 +95,8 @@ namespace sol { inline constexpr bool is_unique_usertype_v = is_unique_usertype::value; namespace detail { - template - using is_base_rebindable_test = decltype(T::rebind_base); + template + using is_base_rebindable_test = typename T::template rebind_base; } template @@ -106,7 +106,7 @@ namespace sol { inline constexpr bool is_base_rebindable_v = is_base_rebindable::value; namespace detail { - template + template struct is_base_rebindable_non_void_sfinae : std::false_type {}; template diff --git a/headers/3rdparty/sol/usertype_container.hpp b/headers/3rdparty/sol/usertype_container.hpp index f48232d0..995e90c6 100644 --- a/headers/3rdparty/sol/usertype_container.hpp +++ b/headers/3rdparty/sol/usertype_container.hpp @@ -64,7 +64,8 @@ namespace sol { struct has_erase_after_test { private: template - static meta::sfinae_yes_t test(decltype(std::declval().erase_after(std::declval>()))*); + static meta::sfinae_yes_t test( + decltype(std::declval().erase_after(std::declval>()))*); template static meta::sfinae_no_t test(...); @@ -108,6 +109,18 @@ namespace sol { static constexpr bool value = std::is_same_v(0)), meta::sfinae_yes_t>; }; + template + struct has_erase_key_test { + private: + template + static meta::sfinae_yes_t test(decltype(std::declval().erase(std::declval()))*); + template + static meta::sfinae_no_t test(...); + + public: + static constexpr bool value = std::is_same_v(0)), meta::sfinae_yes_t>; + }; + template struct has_traits_find_test { private: @@ -288,6 +301,9 @@ namespace sol { template using has_erase = meta::boolean::value>; + template + using has_erase_key = meta::boolean::value>; + template using has_erase_after = meta::boolean::value>; @@ -404,7 +420,8 @@ namespace sol { } static int index_set(lua_State* L) { - return luaL_error(L, "sol: cannot call 'container[key] = value' on type '%s': it is not recognized as a container", detail::demangle().c_str()); + return luaL_error( + L, "sol: cannot call 'container[key] = value' on type '%s': it is not recognized as a container", detail::demangle().c_str()); } static int add(lua_State* L) { @@ -463,7 +480,9 @@ namespace sol { }; template - struct usertype_container_default>, meta::has_value_type>>, meta::has_iterator>>>::value>> { + struct usertype_container_default>, meta::has_value_type>>, + meta::has_iterator>>>::value>> { private: using T = std::remove_pointer_t>>; @@ -475,32 +494,21 @@ namespace sol { using is_matched_lookup = meta::is_matched_lookup; using iterator = typename T::iterator; using value_type = typename T::value_type; - typedef meta::conditional_t, - meta::conditional_t>> - KV; + typedef meta::conditional_t, + meta::conditional_t>> + KV; typedef typename KV::first_type K; typedef typename KV::second_type V; typedef meta::conditional_t next_K; typedef decltype(*std::declval()) iterator_return; - typedef meta::conditional_t, - meta::conditional_t> - captured_type; + typedef meta::conditional_t, + meta::conditional_t> + captured_type; typedef typename meta::iterator_tag::type iterator_category; typedef std::is_same is_input_iterator; - typedef meta::conditional_t()))> - push_type; + typedef meta::conditional_t()))> push_type; typedef std::is_copy_assignable is_copyable; - typedef meta::neg, std::is_const>, meta::neg>> - is_writable; + typedef meta::neg, std::is_const>, meta::neg>> is_writable; typedef meta::unqualified_t>()))> key_type; typedef meta::all, meta::neg>> is_linear_integral; @@ -509,12 +517,10 @@ namespace sol { iterator it; std::size_t i; - iter(T& source, iterator it) - : source(source), it(std::move(it)), i(0) { + iter(T& source, iterator it) : source(source), it(std::move(it)), i(0) { } ~iter() { - } }; @@ -522,10 +528,13 @@ namespace sol { #if defined(SOL_SAFE_USERTYPE) && SOL_SAFE_USERTYPE auto p = stack::unqualified_check_get(L, 1); if (!p) { - luaL_error(L, "sol: 'self' is not of type '%s' (pass 'self' as first argument with ':' or call on proper type)", detail::demangle().c_str()); + luaL_error(L, + "sol: 'self' is not of type '%s' (pass 'self' as first argument with ':' or call on proper type)", + detail::demangle().c_str()); } if (p.value() == nullptr) { - luaL_error(L, "sol: 'self' argument is nil (pass 'self' as first argument with ':' or call on a '%s' type)", detail::demangle().c_str()); + luaL_error( + L, "sol: 'self' argument is nil (pass 'self' as first argument with ':' or call on a '%s' type)", detail::demangle().c_str()); } return *p.value(); #else @@ -570,12 +579,12 @@ namespace sol { template static detail::error_result get_associative(std::true_type, lua_State* L, Iter& it) { decltype(auto) v = *it; - return stack::stack_detail::push_reference(L, detail::deref_non_pointer(v.second)); + return stack::stack_detail::push_reference(L, detail::deref_move_only(v.second)); } template static detail::error_result get_associative(std::false_type, lua_State* L, Iter& it) { - return stack::stack_detail::push_reference(L, detail::deref_non_pointer(*it)); + return stack::stack_detail::push_reference(L, detail::deref_move_only(*it)); } static detail::error_result get_category(std::input_iterator_tag, lua_State* L, T& self, K& key) { @@ -613,9 +622,7 @@ namespace sol { } static detail::error_result get_comparative(std::true_type, lua_State* L, T& self, K& key) { - auto fx = [&](const value_type& r) -> bool { - return key == get_key(is_associative(), r); - }; + auto fx = [&](const value_type& r) -> bool { return key == get_key(is_associative(), r); }; auto e = deferred_uc::end(L, self); auto it = std::find_if(deferred_uc::begin(L, self), e, std::ref(fx)); if (it == e) { @@ -625,7 +632,9 @@ namespace sol { } static detail::error_result get_comparative(std::false_type, lua_State*, T&, K&) { - return detail::error_result("cannot get this key on '%s': no suitable way to increment iterator and compare to key value '%s'", detail::demangle().data(), detail::demangle().data()); + return detail::error_result("cannot get this key on '%s': no suitable way to increment iterator and compare to key value '%s'", + detail::demangle().data(), + detail::demangle().data()); } static detail::error_result get_it(std::false_type, lua_State* L, T& self, K& key) { @@ -649,7 +658,8 @@ namespace sol { } static detail::error_result set_writable(std::false_type, lua_State*, T&, iterator&, stack_object) { - return detail::error_result("cannot perform a 'set': '%s's iterator reference is not writable (non-copy-assignable or const)", detail::demangle().data()); + return detail::error_result( + "cannot perform a 'set': '%s's iterator reference is not writable (non-copy-assignable or const)", detail::demangle().data()); } static detail::error_result set_category(std::input_iterator_tag, lua_State* L, T& self, stack_object okey, stack_object value) { @@ -690,11 +700,10 @@ namespace sol { static detail::error_result set_comparative(std::true_type, lua_State* L, T& self, stack_object okey, stack_object value) { decltype(auto) key = okey.as(); if (!is_writable::value) { - return detail::error_result("cannot perform a 'set': '%s's iterator reference is not writable (non-copy-assignable or const)", detail::demangle().data()); + return detail::error_result( + "cannot perform a 'set': '%s's iterator reference is not writable (non-copy-assignable or const)", detail::demangle().data()); } - auto fx = [&](const value_type& r) -> bool { - return key == get_key(is_associative(), r); - }; + auto fx = [&](const value_type& r) -> bool { return key == get_key(is_associative(), r); }; auto e = deferred_uc::end(L, self); auto it = std::find_if(deferred_uc::begin(L, self), e, std::ref(fx)); if (it == e) { @@ -704,19 +713,39 @@ namespace sol { } static detail::error_result set_comparative(std::false_type, lua_State*, T&, stack_object, stack_object) { - return detail::error_result("cannot set this value on '%s': no suitable way to increment iterator or compare to '%s' key", detail::demangle().data(), detail::demangle().data()); + return detail::error_result("cannot set this value on '%s': no suitable way to increment iterator or compare to '%s' key", + detail::demangle().data(), + detail::demangle().data()); } template static detail::error_result set_associative_insert(std::true_type, lua_State*, T& self, Iter& it, K& key, stack_object value) { - self.insert(it, value_type(key, value.as())); - return {}; + if constexpr (meta::has_insert::value) { + self.insert(it, value_type(key, value.as())); + return {}; + } + else { + (void)self; + (void)it; + (void)key; + return detail::error_result( + "cannot call 'set' on '%s': there is no 'insert' function on this associative type", detail::demangle().c_str()); + } } template static detail::error_result set_associative_insert(std::false_type, lua_State*, T& self, Iter& it, K& key, stack_object) { - self.insert(it, key); - return {}; + if constexpr (meta::has_insert::value) { + self.insert(it, key); + return {}; + } + else { + (void)self; + (void)it; + (void)key; + return detail::error_result( + "cannot call 'set' on '%s': there is no 'insert' function on this non-associative type", detail::demangle().c_str()); + } } static detail::error_result set_associative_find(std::true_type, lua_State* L, T& self, stack_object okey, stack_object value) { @@ -806,7 +835,8 @@ namespace sol { template static detail::error_result find_comparative(std::false_type, lua_State*, T&) { - return detail::error_result("cannot call 'find' on '%s': there is no 'find' function and the value_type is not equality comparable", detail::demangle().c_str()); + return detail::error_result("cannot call 'find' on '%s': there is no 'find' function and the value_type is not equality comparable", + detail::demangle().c_str()); } template @@ -898,8 +928,18 @@ namespace sol { template static detail::error_result add_associative(std::true_type, lua_State* L, T& self, stack_object key, Iter& pos) { - self.insert(pos, value_type(key.as(), stack::unqualified_get(L, 3))); - return {}; + if constexpr (meta::has_insert::value) { + self.insert(pos, value_type(key.as(), stack::unqualified_get(L, 3))); + return {}; + } + else { + (void)L; + (void)self; + (void)key; + (void)pos; + return detail::error_result( + "cannot call 'insert' on '%s': there is no 'insert' function on this associative type", detail::demangle().c_str()); + } } static detail::error_result add_associative(std::true_type, lua_State* L, T& self, stack_object key) { @@ -965,7 +1005,8 @@ namespace sol { } static detail::error_result insert_after_has(std::false_type, lua_State*, T&, stack_object, stack_object) { - return detail::error_result("cannot call 'insert' on '%s': no suitable or similar functionality detected on this container", detail::demangle().data()); + return detail::error_result( + "cannot call 'insert' on '%s': no suitable or similar functionality detected on this container", detail::demangle().data()); } static detail::error_result insert_has(std::true_type, lua_State* L, T& self, stack_object key, stack_object value) { @@ -994,9 +1035,7 @@ namespace sol { } static detail::error_result erase_integral(std::false_type, lua_State* L, T& self, const K& key) { - auto fx = [&](const value_type& r) -> bool { - return key == r; - }; + auto fx = [&](const value_type& r) -> bool { return key == r; }; auto e = deferred_uc::end(L, self); auto it = std::find_if(deferred_uc::begin(L, self), e, std::ref(fx)); if (it == e) { @@ -1035,12 +1074,20 @@ namespace sol { return detail::error_result("sol: cannot call erase on '%s'", detail::demangle().c_str()); } + static detail::error_result erase_key_has(std::true_type, lua_State* L, T& self, K& key) { + return erase_associative_lookup(meta::any(), L, self, key); + } + + static detail::error_result erase_key_has(std::false_type, lua_State* L, T& self, K& key) { + return erase_after_has(has_erase_after(), L, self, key); + } + static detail::error_result erase_has(std::true_type, lua_State* L, T& self, K& key) { return erase_associative_lookup(meta::any(), L, self, key); } static detail::error_result erase_has(std::false_type, lua_State* L, T& self, K& key) { - return erase_after_has(has_erase_after(), L, self, key); + return erase_key_has(has_erase_key(), L, self, key); } static auto size_has(std::false_type, lua_State* L, T& self) { @@ -1067,10 +1114,23 @@ namespace sol { return deferred_uc::begin(L, self) == deferred_uc::end(L, self); } - static detail::error_result get_start(lua_State* L, T& self, K& key) { + static detail::error_result get_associative_find(std::true_type, lua_State* L, T& self, K& key) { + auto it = self.find(key); + if (it == deferred_uc::end(L, self)) { + stack::push(L, lua_nil); + return {}; + } + return get_associative(std::true_type(), L, it); + } + + static detail::error_result get_associative_find(std::false_type, lua_State* L, T& self, K& key) { return get_it(is_linear_integral(), L, self, key); } + static detail::error_result get_start(lua_State* L, T& self, K& key) { + return get_associative_find(std::integral_constant < bool, is_associative::value&& has_find::value > (), L, self, key); + } + static detail::error_result set_start(lua_State* L, T& self, stack_object key, stack_object value) { return set_it(is_linear_integral(), L, self, std::move(key), std::move(value)); } @@ -1107,7 +1167,7 @@ namespace sol { else { p = stack::push_reference(L, it->first); } - p += stack::stack_detail::push_reference(L, detail::deref_non_pointer(it->second)); + p += stack::stack_detail::push_reference(L, detail::deref_move_only(it->second)); std::advance(it, 1); return p; } @@ -1128,7 +1188,7 @@ namespace sol { else { p = stack::stack_detail::push_reference(L, k + 1); } - p += stack::stack_detail::push_reference(L, detail::deref_non_pointer(*it)); + p += stack::stack_detail::push_reference(L, detail::deref_move_only(*it)); std::advance(it, 1); return p; } @@ -1221,13 +1281,23 @@ namespace sol { } static iterator begin(lua_State*, T& self) { - using std::begin; - return begin(self); + if constexpr (meta::has_begin_end_v) { + return self.begin(); + } + else { + using std::begin; + return begin(self); + } } static iterator end(lua_State*, T& self) { - using std::end; - return end(self); + if constexpr (meta::has_begin_end_v) { + return self.end(); + } + else { + using std::end; + return end(self); + } } static int size(lua_State* L) { @@ -1295,8 +1365,7 @@ namespace sol { T& source; iterator it; - iter(T& source, iterator it) - : source(source), it(std::move(it)) { + iter(T& source, iterator it) : source(source), it(std::move(it)) { } }; @@ -1304,10 +1373,13 @@ namespace sol { auto p = stack::unqualified_check_get(L, 1); #if defined(SOL_SAFE_USERTYPE) && SOL_SAFE_USERTYPE if (!p) { - luaL_error(L, "sol: 'self' is not of type '%s' (pass 'self' as first argument with ':' or call on proper type)", detail::demangle().c_str()); + luaL_error(L, + "sol: 'self' is not of type '%s' (pass 'self' as first argument with ':' or call on proper type)", + detail::demangle().c_str()); } if (p.value() == nullptr) { - luaL_error(L, "sol: 'self' argument is nil (pass 'self' as first argument with ':' or call on a '%s' type)", detail::demangle().c_str()); + luaL_error( + L, "sol: 'self' argument is nil (pass 'self' as first argument with ':' or call on a '%s' type)", detail::demangle().c_str()); } #endif // Safe getting with error return *p.value(); @@ -1342,7 +1414,7 @@ namespace sol { } int p; p = stack::push(L, k + 1); - p += stack::push_reference(L, detail::deref_non_pointer(*it)); + p += stack::push_reference(L, detail::deref_move_only(*it)); std::advance(it, 1); return p; } @@ -1375,7 +1447,7 @@ namespace sol { if (idx >= static_cast(std::extent::value) || idx < 0) { return stack::push(L, lua_nil); } - return stack::push_reference(L, detail::deref_non_pointer(self[idx])); + return stack::push_reference(L, detail::deref_move_only(self[idx])); } static int index_get(lua_State* L) { diff --git a/headers/3rdparty/sol/usertype_storage.hpp b/headers/3rdparty/sol/usertype_storage.hpp index 690f65f9..1b0ca1de 100644 --- a/headers/3rdparty/sol/usertype_storage.hpp +++ b/headers/3rdparty/sol/usertype_storage.hpp @@ -175,17 +175,14 @@ namespace sol { namespace u_detail { index_call_storage* p_ics = nullptr; usertype_storage_base* p_usb = nullptr; void* p_derived_usb = nullptr; - lua_CFunction idx_call = nullptr, - new_idx_call = nullptr, - meta_idx_call = nullptr, - meta_new_idx_call = nullptr; + lua_CFunction idx_call = nullptr, new_idx_call = nullptr, meta_idx_call = nullptr, meta_new_idx_call = nullptr; change_indexing_mem_func change_indexing; - + void operator()(lua_State* L, submetatable_type smt, reference& fast_index_table) { std::string& key = *p_key; usertype_storage_base& usb = *p_usb; index_call_storage& ics = *p_ics; - + if (smt == submetatable_type::named) { // do not override __call or // other specific meta functions on named metatable: @@ -196,14 +193,7 @@ namespace sol { namespace u_detail { int fast_index_table_push = fast_index_table.push(); stack_reference t(L, -fast_index_table_push); if (poison_indexing) { - (usb.*change_indexing)(L, - smt, - p_derived_usb, - t, - idx_call, - new_idx_call, - meta_idx_call, - meta_new_idx_call); + (usb.*change_indexing)(L, smt, p_derived_usb, t, idx_call, new_idx_call, meta_idx_call, meta_new_idx_call); } if (is_destruction && (smt == submetatable_type::reference || smt == submetatable_type::const_reference || smt == submetatable_type::named @@ -264,14 +254,7 @@ namespace sol { namespace u_detail { stack::set_field(L, detail::base_class_check_key(), reinterpret_cast(base_class_check_func), t.stack_index()); stack::set_field(L, detail::base_class_cast_key(), reinterpret_cast(base_class_cast_func), t.stack_index()); // change indexing, forcefully - (p_usb->*change_indexing)(L, - smt, - p_derived_usb, - t, - idx_call, - new_idx_call, - meta_idx_call, - meta_new_idx_call); + (p_usb->*change_indexing)(L, smt, p_derived_usb, t, idx_call, new_idx_call, meta_idx_call, meta_new_idx_call); t.pop(); } }; @@ -279,7 +262,8 @@ namespace sol { namespace u_detail { struct binding_data_equals { void* binding_data; - binding_data_equals(void* b) : binding_data(b) {} + binding_data_equals(void* b) : binding_data(b) { + } bool operator()(const std::unique_ptr& ptr) const { return binding_data == ptr->data(); @@ -446,7 +430,7 @@ namespace sol { namespace u_detail { type_table = lua_nil; gc_names_table = lua_nil; named_metatable = lua_nil; - + storage.clear(); string_keys.clear(); auxiliary_keys.clear(); @@ -466,7 +450,7 @@ namespace sol { namespace u_detail { #else optional&> maybe_base_storage = maybe_get_usertype_storage(L); if (static_cast(maybe_base_storage)) { - base_result = self_index_call(bases(), L, *maybe_base_storage); + base_result = self_index_call(bases(), L, *maybe_base_storage); keep_going = base_result == base_walking_failed_index; } #endif // Fast versus slow, safe base lookup @@ -504,7 +488,7 @@ namespace sol { namespace u_detail { } } if (target != nullptr) { - if constexpr(is_new_index) { + if constexpr (is_new_index) { // set value and return *target = reference(L, 3); return 0; @@ -633,7 +617,7 @@ namespace sol { namespace u_detail { }; template - inline int destruct_usertype_storage (lua_State* L) { + inline int destruct_usertype_storage(lua_State* L) { return detail::user_alloc_destruct>(L); } @@ -644,6 +628,7 @@ namespace sol { namespace u_detail { using Binding = binding; using is_var_bind = is_variable_binding; if constexpr (std::is_same_v) { + (void)key; std::unique_ptr p_binding = std::make_unique(std::forward(value)); Binding& b = *p_binding; this->storage.push_back(std::move(p_binding)); @@ -658,6 +643,7 @@ namespace sol { namespace u_detail { this->named_index_table.pop(); } else if constexpr (std::is_same_v) { + (void)key; this->update_bases(L, std::forward(value)); } else if constexpr ((meta::is_string_like_or_constructible::value || std::is_same_v)) { @@ -688,10 +674,11 @@ namespace sol { namespace u_detail { void* derived_this = static_cast(static_cast*>(this)); index_call_storage ics; ics.binding_data = b.data(); - ics.index = is_index || is_static_index ? &Binding::template call_with_ : &Binding::template index_call_with_; - ics.new_index - = is_new_index || is_static_new_index ? &Binding::template call_with_ : &Binding::template index_call_with_; - + ics.index = is_index || is_static_index ? &Binding::template call_with_ + : &Binding::template index_call_with_; + ics.new_index = is_new_index || is_static_new_index ? &Binding::template call_with_ + : &Binding::template index_call_with_; + string_for_each_metatable_func for_each_fx; for_each_fx.is_destruction = is_destruction; for_each_fx.is_index = is_index; @@ -703,7 +690,7 @@ namespace sol { namespace u_detail { for_each_fx.p_ics = &ics; if constexpr (is_lua_c_function_v) { for_each_fx.is_unqualified_lua_CFunction = true; - for_each_fx.call_func = *static_cast(ics.binding_data); + for_each_fx.call_func = *static_cast(ics.binding_data); } else if constexpr (is_lua_reference_or_proxy_v) { for_each_fx.is_unqualified_lua_reference = true; diff --git a/modules/catch2 b/modules/catch2 index e1c9d556..d10b9bd0 160000 --- a/modules/catch2 +++ b/modules/catch2 @@ -1 +1 @@ -Subproject commit e1c9d5569dc4135babb9c81891d70a8ba8ed938c +Subproject commit d10b9bd02e098476670f5eb0527d2c7281476e8a diff --git a/modules/glfw b/modules/glfw index 2bac7ee8..09384626 160000 --- a/modules/glfw +++ b/modules/glfw @@ -1 +1 @@ -Subproject commit 2bac7ee8da526257d808bd026b027246c98e4f2f +Subproject commit 09384626161b67dbd70c4a6221263842fe18a838 diff --git a/modules/imgui b/modules/imgui index a1e4af62..861f786d 160000 --- a/modules/imgui +++ b/modules/imgui @@ -1 +1 @@ -Subproject commit a1e4af62d35bdd271b3e0546258f8533b7f7ea5e +Subproject commit 861f786d816eac498be9ef95a3fabe49289ea6ee diff --git a/modules/miniz b/modules/miniz index f66b3e19..e48d8bab 160000 --- a/modules/miniz +++ b/modules/miniz @@ -1 +1 @@ -Subproject commit f66b3e19017fad1e7f836ce5ecf94c88c0f9d497 +Subproject commit e48d8bab887deeddb608d713128529c9261bf9e7 diff --git a/modules/rapidjson b/modules/rapidjson index 35e480fc..dfbe1db9 160000 --- a/modules/rapidjson +++ b/modules/rapidjson @@ -1 +1 @@ -Subproject commit 35e480fc4ddf4ec4f7ad34d96353eef0aabf002d +Subproject commit dfbe1db9da455552f7a9ad5d2aea17dd9d832ac1 diff --git a/modules/sol2 b/modules/sol2 index 230928c0..e26475e7 160000 --- a/modules/sol2 +++ b/modules/sol2 @@ -1 +1 @@ -Subproject commit 230928c0451544dbc97b2e0a007ca16c3566df66 +Subproject commit e26475e75b0a116de95ce710b573989008b82a57 diff --git a/sources/3rdparty/miniz/miniz_zip.c b/sources/3rdparty/miniz/miniz_zip.c index 6dfe8076..5ae31932 100644 --- a/sources/3rdparty/miniz/miniz_zip.c +++ b/sources/3rdparty/miniz/miniz_zip.c @@ -97,7 +97,7 @@ static FILE *mz_freopen(const char *pPath, const char *pMode, FILE *pStream) #define MZ_FFLUSH fflush #define MZ_FREOPEN(f, m, s) freopen(f, m, s) #define MZ_DELETE_FILE remove -#elif defined(__USE_LARGEFILE64) // gcc, clang +#elif defined(__USE_LARGEFILE64) /* gcc, clang */ #ifndef MINIZ_NO_TIME #include #endif @@ -1645,7 +1645,9 @@ void *mz_zip_reader_extract_file_to_heap(mz_zip_archive *pZip, const char *pFile mz_bool mz_zip_reader_extract_to_callback(mz_zip_archive *pZip, mz_uint file_index, mz_file_write_func pCallback, void *pOpaque, mz_uint flags) { int status = TINFL_STATUS_DONE; +#ifndef MINIZ_DISABLE_ZIP_READER_CRC32_CHECKS mz_uint file_crc32 = MZ_CRC32_INIT; +#endif mz_uint64 read_buf_size, read_buf_ofs = 0, read_buf_avail, comp_remaining, out_buf_ofs = 0, cur_file_ofs; mz_zip_archive_file_stat file_stat; void *pRead_buf = NULL; @@ -3233,8 +3235,8 @@ mz_bool mz_zip_writer_add_mem_ex_v2(mz_zip_archive *pZip, const char *pArchive_n if (!pState->m_zip64) { /* Bail early if the archive would obviously become too large */ - if ((pZip->m_archive_size + num_alignment_padding_bytes + MZ_ZIP_LOCAL_DIR_HEADER_SIZE + archive_name_size - + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + archive_name_size + comment_size + user_extra_data_len + + if ((pZip->m_archive_size + num_alignment_padding_bytes + MZ_ZIP_LOCAL_DIR_HEADER_SIZE + archive_name_size + + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + archive_name_size + comment_size + user_extra_data_len + pState->m_central_dir.m_size + MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE + user_extra_data_central_len + MZ_ZIP_DATA_DESCRIPTER_SIZE32) > 0xFFFFFFFF) { diff --git a/untests/catch/catch.hpp b/untests/catch/catch.hpp index b4eccfc1..6c1756a6 100644 --- a/untests/catch/catch.hpp +++ b/untests/catch/catch.hpp @@ -1,6 +1,6 @@ /* - * Catch v2.11.0 - * Generated: 2019-11-15 15:01:56.628356 + * Catch v2.11.1 + * Generated: 2019-12-28 21:22:11.930976 * ---------------------------------------------------------- * This file has been merged from multiple headers. Please don't edit it directly * Copyright (c) 2019 Two Blue Cubes Ltd. All rights reserved. @@ -15,7 +15,7 @@ #define CATCH_VERSION_MAJOR 2 #define CATCH_VERSION_MINOR 11 -#define CATCH_VERSION_PATCH 0 +#define CATCH_VERSION_PATCH 1 #ifdef __clang__ # pragma clang system_header @@ -241,9 +241,12 @@ namespace Catch { // MSVC traditional preprocessor needs some workaround for __VA_ARGS__ // _MSVC_TRADITIONAL == 0 means new conformant preprocessor // _MSVC_TRADITIONAL == 1 means old traditional non-conformant preprocessor -# if !defined(_MSVC_TRADITIONAL) || (defined(_MSVC_TRADITIONAL) && _MSVC_TRADITIONAL) -# define CATCH_INTERNAL_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR -# endif +# if !defined(__clang__) // Handle Clang masquerading for msvc +# if !defined(_MSVC_TRADITIONAL) || (defined(_MSVC_TRADITIONAL) && _MSVC_TRADITIONAL) +# define CATCH_INTERNAL_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR +# endif // MSVC_TRADITIONAL +# endif // __clang__ + #endif // _MSC_VER #if defined(_REENTRANT) || defined(_MSC_VER) @@ -3907,7 +3910,6 @@ namespace Generators { class SingleValueGenerator final : public IGenerator { T m_value; public: - SingleValueGenerator(T const& value) : m_value( value ) {} SingleValueGenerator(T&& value) : m_value(std::move(value)) {} T const& get() const override { @@ -3970,21 +3972,21 @@ namespace Generators { m_generators.emplace_back(std::move(generator)); } void populate(T&& val) { - m_generators.emplace_back(value(std::move(val))); + m_generators.emplace_back(value(std::forward(val))); } template void populate(U&& val) { - populate(T(std::move(val))); + populate(T(std::forward(val))); } template - void populate(U&& valueOrGenerator, Gs... moreGenerators) { + void populate(U&& valueOrGenerator, Gs &&... moreGenerators) { populate(std::forward(valueOrGenerator)); populate(std::forward(moreGenerators)...); } public: template - Generators(Gs... moreGenerators) { + Generators(Gs &&... moreGenerators) { m_generators.reserve(sizeof...(Gs)); populate(std::forward(moreGenerators)...); } @@ -4015,7 +4017,7 @@ namespace Generators { struct as {}; template - auto makeGenerators( GeneratorWrapper&& generator, Gs... moreGenerators ) -> Generators { + auto makeGenerators( GeneratorWrapper&& generator, Gs &&... moreGenerators ) -> Generators { return Generators(std::move(generator), std::forward(moreGenerators)...); } template @@ -4023,11 +4025,11 @@ namespace Generators { return Generators(std::move(generator)); } template - auto makeGenerators( T&& val, Gs... moreGenerators ) -> Generators { + auto makeGenerators( T&& val, Gs &&... moreGenerators ) -> Generators { return makeGenerators( value( std::forward( val ) ), std::forward( moreGenerators )... ); } template - auto makeGenerators( as, U&& val, Gs... moreGenerators ) -> Generators { + auto makeGenerators( as, U&& val, Gs &&... moreGenerators ) -> Generators { return makeGenerators( value( T( std::forward( val ) ) ), std::forward( moreGenerators )... ); } @@ -4053,11 +4055,11 @@ namespace Generators { } // namespace Catch #define GENERATE( ... ) \ - Catch::Generators::generate( CATCH_INTERNAL_LINEINFO, [ ]{ using namespace Catch::Generators; return makeGenerators( __VA_ARGS__ ); } ) + Catch::Generators::generate( CATCH_INTERNAL_LINEINFO, [ ]{ using namespace Catch::Generators; return makeGenerators( __VA_ARGS__ ); } ) //NOLINT(google-build-using-namespace) #define GENERATE_COPY( ... ) \ - Catch::Generators::generate( CATCH_INTERNAL_LINEINFO, [=]{ using namespace Catch::Generators; return makeGenerators( __VA_ARGS__ ); } ) + Catch::Generators::generate( CATCH_INTERNAL_LINEINFO, [=]{ using namespace Catch::Generators; return makeGenerators( __VA_ARGS__ ); } ) //NOLINT(google-build-using-namespace) #define GENERATE_REF( ... ) \ - Catch::Generators::generate( CATCH_INTERNAL_LINEINFO, [&]{ using namespace Catch::Generators; return makeGenerators( __VA_ARGS__ ); } ) + Catch::Generators::generate( CATCH_INTERNAL_LINEINFO, [&]{ using namespace Catch::Generators; return makeGenerators( __VA_ARGS__ ); } ) //NOLINT(google-build-using-namespace) // end catch_generators.hpp // start catch_generators_generic.hpp @@ -7320,60 +7322,65 @@ namespace Catch { #include namespace Catch { - namespace Detail { - template - struct ObjectStorage - { - using TStorage = typename std::aligned_storage::value>::type; - - ObjectStorage() : data() {} - - ObjectStorage(const ObjectStorage& other) + namespace Benchmark { + namespace Detail { + template + struct ObjectStorage { - new(&data) T(other.stored_object()); - } + using TStorage = typename std::aligned_storage::value>::type; - ObjectStorage(ObjectStorage&& other) - { - new(&data) T(std::move(other.stored_object())); - } + ObjectStorage() : data() {} - ~ObjectStorage() { destruct_on_exit(); } + ObjectStorage(const ObjectStorage& other) + { + new(&data) T(other.stored_object()); + } - template - void construct(Args&&... args) - { - new (&data) T(std::forward(args)...); - } + ObjectStorage(ObjectStorage&& other) + { + new(&data) T(std::move(other.stored_object())); + } - template - typename std::enable_if::type destruct() - { - stored_object().~T(); - } + ~ObjectStorage() { destruct_on_exit(); } - private: - // If this is a constructor benchmark, destruct the underlying object - template - void destruct_on_exit(typename std::enable_if::type* = 0) { destruct(); } - // Otherwise, don't - template - void destruct_on_exit(typename std::enable_if::type* = 0) { } + template + void construct(Args&&... args) + { + new (&data) T(std::forward(args)...); + } - T& stored_object() - { - return *static_cast(static_cast(&data)); - } + template + typename std::enable_if::type destruct() + { + stored_object().~T(); + } - TStorage data; - }; + private: + // If this is a constructor benchmark, destruct the underlying object + template + void destruct_on_exit(typename std::enable_if::type* = 0) { destruct(); } + // Otherwise, don't + template + void destruct_on_exit(typename std::enable_if::type* = 0) { } + + T& stored_object() { + return *static_cast(static_cast(&data)); + } + + T const& stored_object() const { + return *static_cast(static_cast(&data)); + } + + TStorage data; + }; + } + + template + using storage_for = Detail::ObjectStorage; + + template + using destructable_object = Detail::ObjectStorage; } - - template - using storage_for = Detail::ObjectStorage; - - template - using destructable_object = Detail::ObjectStorage; } // end catch_constructor.hpp @@ -7854,6 +7861,17 @@ namespace Catch { #define CATCH_TRAP() __asm__("int $3\n" : : ) /* NOLINT */ +#elif defined(CATCH_PLATFORM_IPHONE) + + // use inline assembler + #if defined(__i386__) || defined(__x86_64__) + #define CATCH_TRAP() __asm__("int $3") + #elif defined(__aarch64__) + #define CATCH_TRAP() __asm__(".inst 0xd4200000") + #elif defined(__arm__) + #define CATCH_TRAP() __asm__(".inst 0xe7f001f0") + #endif + #elif defined(CATCH_PLATFORM_LINUX) // If we can use inline assembler, do it because this allows us to break // directly at the location of the failing check instead of breaking inside @@ -10094,7 +10112,7 @@ namespace { bool useColourOnPlatform() { return -#ifdef CATCH_PLATFORM_MAC +#if defined(CATCH_PLATFORM_MAC) || defined(CATCH_PLATFORM_IPHONE) !isDebuggerActive() && #endif #if !(defined(__DJGPP__) && defined(__STRICT_ANSI__)) @@ -10271,7 +10289,7 @@ namespace Catch { // end catch_debug_console.cpp // start catch_debugger.cpp -#ifdef CATCH_PLATFORM_MAC +#if defined(CATCH_PLATFORM_MAC) || defined(CATCH_PLATFORM_IPHONE) # include # include @@ -15050,7 +15068,7 @@ namespace Catch { } Version const& libraryVersion() { - static Version version( 2, 11, 0, "", 0 ); + static Version version( 2, 11, 1, "", 0 ); return version; }