upgrade imgui to 1.91.1, sokol to sept 10 2024

This commit is contained in:
John Alanbrook 2024-09-14 12:15:08 -05:00
parent 640c8389f3
commit a3f68316ca
16 changed files with 3828 additions and 1412 deletions

View file

@ -21,10 +21,11 @@
//---- Define attributes of all API symbols declarations, e.g. for DLL under Windows //---- Define attributes of all API symbols declarations, e.g. for DLL under Windows
// Using Dear ImGui via a shared library is not recommended, because of function call overhead and because we don't guarantee backward nor forward ABI compatibility. // Using Dear ImGui via a shared library is not recommended, because of function call overhead and because we don't guarantee backward nor forward ABI compatibility.
// DLL users: heaps and globals are not shared across DLL boundaries! You will need to call SetCurrentContext() + SetAllocatorFunctions() // - Windows DLL users: heaps and globals are not shared across DLL boundaries! You will need to call SetCurrentContext() + SetAllocatorFunctions()
// for each static/DLL boundary you are calling from. Read "Context and Memory Allocators" section of imgui.cpp for more details. // for each static/DLL boundary you are calling from. Read "Context and Memory Allocators" section of imgui.cpp for more details.
//#define IMGUI_API __declspec( dllexport ) //#define IMGUI_API __declspec(dllexport) // MSVC Windows: DLL export
//#define IMGUI_API __declspec( dllimport ) //#define IMGUI_API __declspec(dllimport) // MSVC Windows: DLL import
//#define IMGUI_API __attribute__((visibility("default"))) // GCC/Clang: override visibility when set is hidden
//---- Don't define obsolete functions/enums/behaviors. Consider enabling from time to time after updating to clean your code of obsolete function/names. //---- Don't define obsolete functions/enums/behaviors. Consider enabling from time to time after updating to clean your code of obsolete function/names.
//#define IMGUI_DISABLE_OBSOLETE_FUNCTIONS //#define IMGUI_DISABLE_OBSOLETE_FUNCTIONS
@ -42,6 +43,7 @@
//#define IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS // [Win32] [Default with non-Visual Studio compilers] Don't implement default IME handler (won't require imm32.lib/.a) //#define IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS // [Win32] [Default with non-Visual Studio compilers] Don't implement default IME handler (won't require imm32.lib/.a)
//#define IMGUI_DISABLE_WIN32_FUNCTIONS // [Win32] Won't use and link with any Win32 function (clipboard, IME). //#define IMGUI_DISABLE_WIN32_FUNCTIONS // [Win32] Won't use and link with any Win32 function (clipboard, IME).
//#define IMGUI_ENABLE_OSX_DEFAULT_CLIPBOARD_FUNCTIONS // [OSX] Implement default OSX clipboard handler (need to link with '-framework ApplicationServices', this is why this is not the default). //#define IMGUI_ENABLE_OSX_DEFAULT_CLIPBOARD_FUNCTIONS // [OSX] Implement default OSX clipboard handler (need to link with '-framework ApplicationServices', this is why this is not the default).
//#define IMGUI_DISABLE_DEFAULT_SHELL_FUNCTIONS // Don't implement default platform_io.Platform_OpenInShellFn() handler (Win32: ShellExecute(), require shell32.lib/.a, Mac/Linux: use system("")).
//#define IMGUI_DISABLE_DEFAULT_FORMAT_FUNCTIONS // Don't implement ImFormatString/ImFormatStringV so you can implement them yourself (e.g. if you don't want to link with vsnprintf) //#define IMGUI_DISABLE_DEFAULT_FORMAT_FUNCTIONS // Don't implement ImFormatString/ImFormatStringV so you can implement them yourself (e.g. if you don't want to link with vsnprintf)
//#define IMGUI_DISABLE_DEFAULT_MATH_FUNCTIONS // Don't implement ImFabs/ImSqrt/ImPow/ImFmod/ImCos/ImSin/ImAcos/ImAtan2 so you can implement them yourself. //#define IMGUI_DISABLE_DEFAULT_MATH_FUNCTIONS // Don't implement ImFabs/ImSqrt/ImPow/ImFmod/ImCos/ImSin/ImAcos/ImAtan2 so you can implement them yourself.
//#define IMGUI_DISABLE_FILE_FUNCTIONS // Don't implement ImFileOpen/ImFileClose/ImFileRead/ImFileWrite and ImFileHandle at all (replace them with dummies) //#define IMGUI_DISABLE_FILE_FUNCTIONS // Don't implement ImFileOpen/ImFileClose/ImFileRead/ImFileWrite and ImFileHandle at all (replace them with dummies)
@ -49,6 +51,9 @@
//#define IMGUI_DISABLE_DEFAULT_ALLOCATORS // Don't implement default allocators calling malloc()/free() to avoid linking with them. You will need to call ImGui::SetAllocatorFunctions(). //#define IMGUI_DISABLE_DEFAULT_ALLOCATORS // Don't implement default allocators calling malloc()/free() to avoid linking with them. You will need to call ImGui::SetAllocatorFunctions().
//#define IMGUI_DISABLE_SSE // Disable use of SSE intrinsics even if available //#define IMGUI_DISABLE_SSE // Disable use of SSE intrinsics even if available
//---- Enable Test Engine / Automation features.
//#define IMGUI_ENABLE_TEST_ENGINE // Enable imgui_test_engine hooks. Generally set automatically by include "imgui_te_config.h", see Test Engine for details.
//---- Include imgui_user.h at the end of imgui.h as a convenience //---- Include imgui_user.h at the end of imgui.h as a convenience
// May be convenient for some users to only explicitly include vanilla imgui.h and have extra stuff included. // May be convenient for some users to only explicitly include vanilla imgui.h and have extra stuff included.
//#define IMGUI_INCLUDE_IMGUI_USER_H //#define IMGUI_INCLUDE_IMGUI_USER_H

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -1,4 +1,4 @@
// dear imgui, v1.90.8 WIP // dear imgui, v1.91.1
// (drawing and font code) // (drawing and font code)
/* /*
@ -211,11 +211,13 @@ void ImGui::StyleColorsDark(ImGuiStyle* dst)
colors[ImGuiCol_ResizeGrip] = ImVec4(0.26f, 0.59f, 0.98f, 0.20f); colors[ImGuiCol_ResizeGrip] = ImVec4(0.26f, 0.59f, 0.98f, 0.20f);
colors[ImGuiCol_ResizeGripHovered] = ImVec4(0.26f, 0.59f, 0.98f, 0.67f); colors[ImGuiCol_ResizeGripHovered] = ImVec4(0.26f, 0.59f, 0.98f, 0.67f);
colors[ImGuiCol_ResizeGripActive] = ImVec4(0.26f, 0.59f, 0.98f, 0.95f); colors[ImGuiCol_ResizeGripActive] = ImVec4(0.26f, 0.59f, 0.98f, 0.95f);
colors[ImGuiCol_Tab] = ImLerp(colors[ImGuiCol_Header], colors[ImGuiCol_TitleBgActive], 0.80f);
colors[ImGuiCol_TabHovered] = colors[ImGuiCol_HeaderHovered]; colors[ImGuiCol_TabHovered] = colors[ImGuiCol_HeaderHovered];
colors[ImGuiCol_TabActive] = ImLerp(colors[ImGuiCol_HeaderActive], colors[ImGuiCol_TitleBgActive], 0.60f); colors[ImGuiCol_Tab] = ImLerp(colors[ImGuiCol_Header], colors[ImGuiCol_TitleBgActive], 0.80f);
colors[ImGuiCol_TabUnfocused] = ImLerp(colors[ImGuiCol_Tab], colors[ImGuiCol_TitleBg], 0.80f); colors[ImGuiCol_TabSelected] = ImLerp(colors[ImGuiCol_HeaderActive], colors[ImGuiCol_TitleBgActive], 0.60f);
colors[ImGuiCol_TabUnfocusedActive] = ImLerp(colors[ImGuiCol_TabActive], colors[ImGuiCol_TitleBg], 0.40f); colors[ImGuiCol_TabSelectedOverline] = colors[ImGuiCol_HeaderActive];
colors[ImGuiCol_TabDimmed] = ImLerp(colors[ImGuiCol_Tab], colors[ImGuiCol_TitleBg], 0.80f);
colors[ImGuiCol_TabDimmedSelected] = ImLerp(colors[ImGuiCol_TabSelected], colors[ImGuiCol_TitleBg], 0.40f);
colors[ImGuiCol_TabDimmedSelectedOverline] = ImVec4(0.50f, 0.50f, 0.50f, 1.00f);
colors[ImGuiCol_PlotLines] = ImVec4(0.61f, 0.61f, 0.61f, 1.00f); colors[ImGuiCol_PlotLines] = ImVec4(0.61f, 0.61f, 0.61f, 1.00f);
colors[ImGuiCol_PlotLinesHovered] = ImVec4(1.00f, 0.43f, 0.35f, 1.00f); colors[ImGuiCol_PlotLinesHovered] = ImVec4(1.00f, 0.43f, 0.35f, 1.00f);
colors[ImGuiCol_PlotHistogram] = ImVec4(0.90f, 0.70f, 0.00f, 1.00f); colors[ImGuiCol_PlotHistogram] = ImVec4(0.90f, 0.70f, 0.00f, 1.00f);
@ -225,6 +227,7 @@ void ImGui::StyleColorsDark(ImGuiStyle* dst)
colors[ImGuiCol_TableBorderLight] = ImVec4(0.23f, 0.23f, 0.25f, 1.00f); // Prefer using Alpha=1.0 here colors[ImGuiCol_TableBorderLight] = ImVec4(0.23f, 0.23f, 0.25f, 1.00f); // Prefer using Alpha=1.0 here
colors[ImGuiCol_TableRowBg] = ImVec4(0.00f, 0.00f, 0.00f, 0.00f); colors[ImGuiCol_TableRowBg] = ImVec4(0.00f, 0.00f, 0.00f, 0.00f);
colors[ImGuiCol_TableRowBgAlt] = ImVec4(1.00f, 1.00f, 1.00f, 0.06f); colors[ImGuiCol_TableRowBgAlt] = ImVec4(1.00f, 1.00f, 1.00f, 0.06f);
colors[ImGuiCol_TextLink] = colors[ImGuiCol_HeaderActive];
colors[ImGuiCol_TextSelectedBg] = ImVec4(0.26f, 0.59f, 0.98f, 0.35f); colors[ImGuiCol_TextSelectedBg] = ImVec4(0.26f, 0.59f, 0.98f, 0.35f);
colors[ImGuiCol_DragDropTarget] = ImVec4(1.00f, 1.00f, 0.00f, 0.90f); colors[ImGuiCol_DragDropTarget] = ImVec4(1.00f, 1.00f, 0.00f, 0.90f);
colors[ImGuiCol_NavHighlight] = ImVec4(0.26f, 0.59f, 0.98f, 1.00f); colors[ImGuiCol_NavHighlight] = ImVec4(0.26f, 0.59f, 0.98f, 1.00f);
@ -271,11 +274,13 @@ void ImGui::StyleColorsClassic(ImGuiStyle* dst)
colors[ImGuiCol_ResizeGrip] = ImVec4(1.00f, 1.00f, 1.00f, 0.10f); colors[ImGuiCol_ResizeGrip] = ImVec4(1.00f, 1.00f, 1.00f, 0.10f);
colors[ImGuiCol_ResizeGripHovered] = ImVec4(0.78f, 0.82f, 1.00f, 0.60f); colors[ImGuiCol_ResizeGripHovered] = ImVec4(0.78f, 0.82f, 1.00f, 0.60f);
colors[ImGuiCol_ResizeGripActive] = ImVec4(0.78f, 0.82f, 1.00f, 0.90f); colors[ImGuiCol_ResizeGripActive] = ImVec4(0.78f, 0.82f, 1.00f, 0.90f);
colors[ImGuiCol_Tab] = ImLerp(colors[ImGuiCol_Header], colors[ImGuiCol_TitleBgActive], 0.80f);
colors[ImGuiCol_TabHovered] = colors[ImGuiCol_HeaderHovered]; colors[ImGuiCol_TabHovered] = colors[ImGuiCol_HeaderHovered];
colors[ImGuiCol_TabActive] = ImLerp(colors[ImGuiCol_HeaderActive], colors[ImGuiCol_TitleBgActive], 0.60f); colors[ImGuiCol_Tab] = ImLerp(colors[ImGuiCol_Header], colors[ImGuiCol_TitleBgActive], 0.80f);
colors[ImGuiCol_TabUnfocused] = ImLerp(colors[ImGuiCol_Tab], colors[ImGuiCol_TitleBg], 0.80f); colors[ImGuiCol_TabSelected] = ImLerp(colors[ImGuiCol_HeaderActive], colors[ImGuiCol_TitleBgActive], 0.60f);
colors[ImGuiCol_TabUnfocusedActive] = ImLerp(colors[ImGuiCol_TabActive], colors[ImGuiCol_TitleBg], 0.40f); colors[ImGuiCol_TabSelectedOverline] = colors[ImGuiCol_HeaderActive];
colors[ImGuiCol_TabDimmed] = ImLerp(colors[ImGuiCol_Tab], colors[ImGuiCol_TitleBg], 0.80f);
colors[ImGuiCol_TabDimmedSelected] = ImLerp(colors[ImGuiCol_TabSelected], colors[ImGuiCol_TitleBg], 0.40f);
colors[ImGuiCol_TabDimmedSelectedOverline] = colors[ImGuiCol_HeaderActive];
colors[ImGuiCol_PlotLines] = ImVec4(1.00f, 1.00f, 1.00f, 1.00f); colors[ImGuiCol_PlotLines] = ImVec4(1.00f, 1.00f, 1.00f, 1.00f);
colors[ImGuiCol_PlotLinesHovered] = ImVec4(0.90f, 0.70f, 0.00f, 1.00f); colors[ImGuiCol_PlotLinesHovered] = ImVec4(0.90f, 0.70f, 0.00f, 1.00f);
colors[ImGuiCol_PlotHistogram] = ImVec4(0.90f, 0.70f, 0.00f, 1.00f); colors[ImGuiCol_PlotHistogram] = ImVec4(0.90f, 0.70f, 0.00f, 1.00f);
@ -285,6 +290,7 @@ void ImGui::StyleColorsClassic(ImGuiStyle* dst)
colors[ImGuiCol_TableBorderLight] = ImVec4(0.26f, 0.26f, 0.28f, 1.00f); // Prefer using Alpha=1.0 here colors[ImGuiCol_TableBorderLight] = ImVec4(0.26f, 0.26f, 0.28f, 1.00f); // Prefer using Alpha=1.0 here
colors[ImGuiCol_TableRowBg] = ImVec4(0.00f, 0.00f, 0.00f, 0.00f); colors[ImGuiCol_TableRowBg] = ImVec4(0.00f, 0.00f, 0.00f, 0.00f);
colors[ImGuiCol_TableRowBgAlt] = ImVec4(1.00f, 1.00f, 1.00f, 0.07f); colors[ImGuiCol_TableRowBgAlt] = ImVec4(1.00f, 1.00f, 1.00f, 0.07f);
colors[ImGuiCol_TextLink] = colors[ImGuiCol_HeaderActive];
colors[ImGuiCol_TextSelectedBg] = ImVec4(0.00f, 0.00f, 1.00f, 0.35f); colors[ImGuiCol_TextSelectedBg] = ImVec4(0.00f, 0.00f, 1.00f, 0.35f);
colors[ImGuiCol_DragDropTarget] = ImVec4(1.00f, 1.00f, 0.00f, 0.90f); colors[ImGuiCol_DragDropTarget] = ImVec4(1.00f, 1.00f, 0.00f, 0.90f);
colors[ImGuiCol_NavHighlight] = colors[ImGuiCol_HeaderHovered]; colors[ImGuiCol_NavHighlight] = colors[ImGuiCol_HeaderHovered];
@ -332,11 +338,13 @@ void ImGui::StyleColorsLight(ImGuiStyle* dst)
colors[ImGuiCol_ResizeGrip] = ImVec4(0.35f, 0.35f, 0.35f, 0.17f); colors[ImGuiCol_ResizeGrip] = ImVec4(0.35f, 0.35f, 0.35f, 0.17f);
colors[ImGuiCol_ResizeGripHovered] = ImVec4(0.26f, 0.59f, 0.98f, 0.67f); colors[ImGuiCol_ResizeGripHovered] = ImVec4(0.26f, 0.59f, 0.98f, 0.67f);
colors[ImGuiCol_ResizeGripActive] = ImVec4(0.26f, 0.59f, 0.98f, 0.95f); colors[ImGuiCol_ResizeGripActive] = ImVec4(0.26f, 0.59f, 0.98f, 0.95f);
colors[ImGuiCol_Tab] = ImLerp(colors[ImGuiCol_Header], colors[ImGuiCol_TitleBgActive], 0.90f);
colors[ImGuiCol_TabHovered] = colors[ImGuiCol_HeaderHovered]; colors[ImGuiCol_TabHovered] = colors[ImGuiCol_HeaderHovered];
colors[ImGuiCol_TabActive] = ImLerp(colors[ImGuiCol_HeaderActive], colors[ImGuiCol_TitleBgActive], 0.60f); colors[ImGuiCol_Tab] = ImLerp(colors[ImGuiCol_Header], colors[ImGuiCol_TitleBgActive], 0.90f);
colors[ImGuiCol_TabUnfocused] = ImLerp(colors[ImGuiCol_Tab], colors[ImGuiCol_TitleBg], 0.80f); colors[ImGuiCol_TabSelected] = ImLerp(colors[ImGuiCol_HeaderActive], colors[ImGuiCol_TitleBgActive], 0.60f);
colors[ImGuiCol_TabUnfocusedActive] = ImLerp(colors[ImGuiCol_TabActive], colors[ImGuiCol_TitleBg], 0.40f); colors[ImGuiCol_TabSelectedOverline] = colors[ImGuiCol_HeaderActive];
colors[ImGuiCol_TabDimmed] = ImLerp(colors[ImGuiCol_Tab], colors[ImGuiCol_TitleBg], 0.80f);
colors[ImGuiCol_TabDimmedSelected] = ImLerp(colors[ImGuiCol_TabSelected], colors[ImGuiCol_TitleBg], 0.40f);
colors[ImGuiCol_TabDimmedSelectedOverline] = ImVec4(0.26f, 0.59f, 1.00f, 1.00f);
colors[ImGuiCol_PlotLines] = ImVec4(0.39f, 0.39f, 0.39f, 1.00f); colors[ImGuiCol_PlotLines] = ImVec4(0.39f, 0.39f, 0.39f, 1.00f);
colors[ImGuiCol_PlotLinesHovered] = ImVec4(1.00f, 0.43f, 0.35f, 1.00f); colors[ImGuiCol_PlotLinesHovered] = ImVec4(1.00f, 0.43f, 0.35f, 1.00f);
colors[ImGuiCol_PlotHistogram] = ImVec4(0.90f, 0.70f, 0.00f, 1.00f); colors[ImGuiCol_PlotHistogram] = ImVec4(0.90f, 0.70f, 0.00f, 1.00f);
@ -346,6 +354,7 @@ void ImGui::StyleColorsLight(ImGuiStyle* dst)
colors[ImGuiCol_TableBorderLight] = ImVec4(0.68f, 0.68f, 0.74f, 1.00f); // Prefer using Alpha=1.0 here colors[ImGuiCol_TableBorderLight] = ImVec4(0.68f, 0.68f, 0.74f, 1.00f); // Prefer using Alpha=1.0 here
colors[ImGuiCol_TableRowBg] = ImVec4(0.00f, 0.00f, 0.00f, 0.00f); colors[ImGuiCol_TableRowBg] = ImVec4(0.00f, 0.00f, 0.00f, 0.00f);
colors[ImGuiCol_TableRowBgAlt] = ImVec4(0.30f, 0.30f, 0.30f, 0.09f); colors[ImGuiCol_TableRowBgAlt] = ImVec4(0.30f, 0.30f, 0.30f, 0.09f);
colors[ImGuiCol_TextLink] = colors[ImGuiCol_HeaderActive];
colors[ImGuiCol_TextSelectedBg] = ImVec4(0.26f, 0.59f, 0.98f, 0.35f); colors[ImGuiCol_TextSelectedBg] = ImVec4(0.26f, 0.59f, 0.98f, 0.35f);
colors[ImGuiCol_DragDropTarget] = ImVec4(0.26f, 0.59f, 0.98f, 0.95f); colors[ImGuiCol_DragDropTarget] = ImVec4(0.26f, 0.59f, 0.98f, 0.95f);
colors[ImGuiCol_NavHighlight] = colors[ImGuiCol_HeaderHovered]; colors[ImGuiCol_NavHighlight] = colors[ImGuiCol_HeaderHovered];
@ -517,7 +526,6 @@ void ImDrawList::_OnChangedClipRect()
CmdBuffer.pop_back(); CmdBuffer.pop_back();
return; return;
} }
curr_cmd->ClipRect = _CmdHeader.ClipRect; curr_cmd->ClipRect = _CmdHeader.ClipRect;
} }
@ -540,7 +548,6 @@ void ImDrawList::_OnChangedTextureID()
CmdBuffer.pop_back(); CmdBuffer.pop_back();
return; return;
} }
curr_cmd->TextureId = _CmdHeader.TextureId; curr_cmd->TextureId = _CmdHeader.TextureId;
} }
@ -616,6 +623,15 @@ void ImDrawList::PopTextureID()
_OnChangedTextureID(); _OnChangedTextureID();
} }
// This is used by ImGui::PushFont()/PopFont(). It works because we never use _TextureIdStack[] elsewhere than in PushTextureID()/PopTextureID().
void ImDrawList::_SetTextureID(ImTextureID texture_id)
{
if (_CmdHeader.TextureId == texture_id)
return;
_CmdHeader.TextureId = texture_id;
_OnChangedTextureID();
}
// Reserve space for a number of vertices and indices. // 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 // 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. // submit the intermediate results. PrimUnreserve() can be used to release unused allocations.
@ -2806,8 +2822,9 @@ static bool ImFontAtlasBuildWithStbTruetype(ImFontAtlas* atlas)
for (const ImWchar* src_range = src_tmp.SrcRanges; src_range[0] && src_range[1]; src_range += 2) for (const ImWchar* src_range = src_tmp.SrcRanges; src_range[0] && src_range[1]; src_range += 2)
{ {
// Check for valid range. This may also help detect *some* dangling pointers, because a common // Check for valid range. This may also help detect *some* dangling pointers, because a common
// user error is to setup ImFontConfig::GlyphRanges with a pointer to data that isn't persistent. // user error is to setup ImFontConfig::GlyphRanges with a pointer to data that isn't persistent,
IM_ASSERT(src_range[0] <= src_range[1]); // or to forget to zero-terminate the glyph range array.
IM_ASSERT(src_range[0] <= src_range[1] && "Invalid range: is your glyph range array persistent? it is zero-terminated?");
src_tmp.GlyphsHighest = ImMax(src_tmp.GlyphsHighest, (int)src_range[1]); src_tmp.GlyphsHighest = ImMax(src_tmp.GlyphsHighest, (int)src_range[1]);
} }
dst_tmp.SrcCount++; dst_tmp.SrcCount++;

View file

@ -1,4 +1,4 @@
// dear imgui, v1.90.8 WIP // dear imgui, v1.91.1
// (internal structures/api) // (internal structures/api)
// You may use this file to debug, understand or extend Dear ImGui features but we don't provide any guarantee of forward compatibility. // You may use this file to debug, understand or extend Dear ImGui features but we don't provide any guarantee of forward compatibility.
@ -14,14 +14,15 @@ Index of this file:
// [SECTION] Macros // [SECTION] Macros
// [SECTION] Generic helpers // [SECTION] Generic helpers
// [SECTION] ImDrawList support // [SECTION] ImDrawList support
// [SECTION] Widgets support: flags, enums, data structures
// [SECTION] Data types support // [SECTION] Data types support
// [SECTION] Widgets support: flags, enums, data structures
// [SECTION] Popup support // [SECTION] Popup support
// [SECTION] Inputs support // [SECTION] Inputs support
// [SECTION] Clipper support // [SECTION] Clipper support
// [SECTION] Navigation support // [SECTION] Navigation support
// [SECTION] Typing-select support // [SECTION] Typing-select support
// [SECTION] Columns support // [SECTION] Columns support
// [SECTION] Box-select support
// [SECTION] Multi-select support // [SECTION] Multi-select support
// [SECTION] Docking support // [SECTION] Docking support
// [SECTION] Viewport support // [SECTION] Viewport support
@ -93,6 +94,7 @@ Index of this file:
#pragma GCC diagnostic push #pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wpragmas" // warning: unknown option after '#pragma GCC diagnostic' kind #pragma GCC diagnostic ignored "-Wpragmas" // warning: unknown option after '#pragma GCC diagnostic' kind
#pragma GCC diagnostic ignored "-Wclass-memaccess" // [__GNUC__ >= 8] warning: 'memset/memcpy' clearing/writing an object of type 'xxxx' with no trivial copy-assignment; use assignment or value-initialization instead #pragma GCC diagnostic ignored "-Wclass-memaccess" // [__GNUC__ >= 8] warning: 'memset/memcpy' clearing/writing an object of type 'xxxx' with no trivial copy-assignment; use assignment or value-initialization instead
#pragma GCC diagnostic ignored "-Wdeprecated-enum-enum-conversion" // warning: bitwise operation between different enumeration types ('XXXFlags_' and 'XXXFlagsPrivate_') is deprecated
#endif #endif
// In 1.89.4, we moved the implementation of "courtesy maths operators" from imgui_internal.h in imgui.h // In 1.89.4, we moved the implementation of "courtesy maths operators" from imgui_internal.h in imgui.h
@ -123,6 +125,7 @@ struct ImBitVector; // Store 1-bit per value
struct ImRect; // An axis-aligned rectangle (2 points) struct ImRect; // An axis-aligned rectangle (2 points)
struct ImDrawDataBuilder; // Helper to build a ImDrawData instance struct ImDrawDataBuilder; // Helper to build a ImDrawData instance
struct ImDrawListSharedData; // Data shared between all ImDrawList instances struct ImDrawListSharedData; // Data shared between all ImDrawList instances
struct ImGuiBoxSelectState; // Box-selection state (currently used by multi-selection, could potentially be used by others)
struct ImGuiColorMod; // Stacked color modifier, backup of modified data so we can restore it struct ImGuiColorMod; // Stacked color modifier, backup of modified data so we can restore it
struct ImGuiContext; // Main Dear ImGui context struct ImGuiContext; // Main Dear ImGui context
struct ImGuiContextHook; // Hook for extensions like ImGuiTestEngine struct ImGuiContextHook; // Hook for extensions like ImGuiTestEngine
@ -134,8 +137,9 @@ struct ImGuiInputTextDeactivateData;// Short term storage to backup text of a de
struct ImGuiLastItemData; // Status storage for last submitted items struct ImGuiLastItemData; // Status storage for last submitted items
struct ImGuiLocEntry; // A localization entry. struct ImGuiLocEntry; // A localization entry.
struct ImGuiMenuColumns; // Simple column measurement, currently used for MenuItem() only struct ImGuiMenuColumns; // Simple column measurement, currently used for MenuItem() only
struct ImGuiMultiSelectState; // Multi-selection persistent state (for focused selection).
struct ImGuiMultiSelectTempData; // Multi-selection temporary state (while traversing).
struct ImGuiNavItemData; // Result of a gamepad/keyboard directional navigation move query result struct ImGuiNavItemData; // Result of a gamepad/keyboard directional navigation move query result
struct ImGuiNavTreeNodeData; // Temporary storage for last TreeNode() being a Left arrow landing candidate.
struct ImGuiMetricsConfig; // Storage for ShowMetricsWindow() and DebugNodeXXX() functions struct ImGuiMetricsConfig; // Storage for ShowMetricsWindow() and DebugNodeXXX() functions
struct ImGuiNextWindowData; // Storage for SetNextWindow** functions struct ImGuiNextWindowData; // Storage for SetNextWindow** functions
struct ImGuiNextItemData; // Storage for SetNextItem** functions struct ImGuiNextItemData; // Storage for SetNextItem** functions
@ -154,6 +158,7 @@ struct ImGuiTableInstanceData; // Storage for one instance of a same table
struct ImGuiTableTempData; // Temporary storage for one table (one per table in the stack), shared between tables. struct ImGuiTableTempData; // Temporary storage for one table (one per table in the stack), shared between tables.
struct ImGuiTableSettings; // Storage for a table .ini settings struct ImGuiTableSettings; // Storage for a table .ini settings
struct ImGuiTableColumnsSettings; // Storage for a column .ini settings struct ImGuiTableColumnsSettings; // Storage for a column .ini settings
struct ImGuiTreeNodeStackData; // Temporary storage for TreeNode().
struct ImGuiTypingSelectState; // Storage for GetTypingSelectRequest() struct ImGuiTypingSelectState; // Storage for GetTypingSelectRequest()
struct ImGuiTypingSelectRequest; // Storage for GetTypingSelectRequest() (aimed to be public) struct ImGuiTypingSelectRequest; // Storage for GetTypingSelectRequest() (aimed to be public)
struct ImGuiWindow; // Storage for one window struct ImGuiWindow; // Storage for one window
@ -169,7 +174,6 @@ typedef int ImGuiLayoutType; // -> enum ImGuiLayoutType_ // E
typedef int ImGuiActivateFlags; // -> enum ImGuiActivateFlags_ // Flags: for navigation/focus function (will be for ActivateItem() later) typedef int ImGuiActivateFlags; // -> enum ImGuiActivateFlags_ // Flags: for navigation/focus function (will be for ActivateItem() later)
typedef int ImGuiDebugLogFlags; // -> enum ImGuiDebugLogFlags_ // Flags: for ShowDebugLogWindow(), g.DebugLogFlags typedef int ImGuiDebugLogFlags; // -> enum ImGuiDebugLogFlags_ // Flags: for ShowDebugLogWindow(), g.DebugLogFlags
typedef int ImGuiFocusRequestFlags; // -> enum ImGuiFocusRequestFlags_ // Flags: for FocusWindow(); typedef int ImGuiFocusRequestFlags; // -> enum ImGuiFocusRequestFlags_ // Flags: for FocusWindow();
typedef int ImGuiItemFlags; // -> enum ImGuiItemFlags_ // Flags: for PushItemFlag(), g.LastItemData.InFlags
typedef int ImGuiItemStatusFlags; // -> enum ImGuiItemStatusFlags_ // Flags: for g.LastItemData.StatusFlags typedef int ImGuiItemStatusFlags; // -> enum ImGuiItemStatusFlags_ // Flags: for g.LastItemData.StatusFlags
typedef int ImGuiOldColumnFlags; // -> enum ImGuiOldColumnFlags_ // Flags: for BeginColumns() typedef int ImGuiOldColumnFlags; // -> enum ImGuiOldColumnFlags_ // Flags: for BeginColumns()
typedef int ImGuiNavHighlightFlags; // -> enum ImGuiNavHighlightFlags_ // Flags: for RenderNavHighlight() typedef int ImGuiNavHighlightFlags; // -> enum ImGuiNavHighlightFlags_ // Flags: for RenderNavHighlight()
@ -348,6 +352,7 @@ namespace ImStb
// - Helper: ImPool<> // - Helper: ImPool<>
// - Helper: ImChunkStream<> // - Helper: ImChunkStream<>
// - Helper: ImGuiTextIndex // - Helper: ImGuiTextIndex
// - Helper: ImGuiStorage
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Helpers: Hashing // Helpers: Hashing
@ -384,6 +389,7 @@ IM_MSVC_RUNTIME_CHECKS_OFF
static inline char ImToUpper(char c) { return (c >= 'a' && c <= 'z') ? c &= ~32 : c; } static inline char ImToUpper(char c) { return (c >= 'a' && c <= 'z') ? c &= ~32 : c; }
static inline bool ImCharIsBlankA(char c) { return c == ' ' || c == '\t'; } static inline bool ImCharIsBlankA(char c) { return c == ' ' || c == '\t'; }
static inline bool ImCharIsBlankW(unsigned int c) { return c == ' ' || c == '\t' || c == 0x3000; } static inline bool ImCharIsBlankW(unsigned int c) { return c == ' ' || c == '\t' || c == 0x3000; }
static inline bool ImCharIsXdigitA(char c) { return (c >= '0' && c <= '9') || (c >= 'A' && c <= 'F') || (c >= 'a' && c <= 'f'); }
IM_MSVC_RUNTIME_CHECKS_RESTORE IM_MSVC_RUNTIME_CHECKS_RESTORE
// Helpers: Formatting // Helpers: Formatting
@ -488,6 +494,7 @@ static inline int ImModPositive(int a, int b)
static inline float ImDot(const ImVec2& a, const ImVec2& b) { return a.x * b.x + a.y * b.y; } static inline float ImDot(const ImVec2& a, const ImVec2& b) { return a.x * b.x + a.y * b.y; }
static inline ImVec2 ImRotate(const ImVec2& v, float cos_a, float sin_a) { return ImVec2(v.x * cos_a - v.y * sin_a, v.x * sin_a + v.y * cos_a); } static inline ImVec2 ImRotate(const ImVec2& v, float cos_a, float sin_a) { return ImVec2(v.x * cos_a - v.y * sin_a, v.x * sin_a + v.y * cos_a); }
static inline float ImLinearSweep(float current, float target, float speed) { if (current < target) return ImMin(current + speed, target); if (current > target) return ImMax(current - speed, target); return current; } static inline float ImLinearSweep(float current, float target, float speed) { if (current < target) return ImMin(current + speed, target); if (current > target) return ImMax(current - speed, target); return current; }
static inline float ImLinearRemapClamp(float s0, float s1, float d0, float d1, float x) { return ImSaturate((x - s0) / (s1 - s0)) * (d1 - d0) + d0; }
static inline ImVec2 ImMul(const ImVec2& lhs, const ImVec2& rhs) { return ImVec2(lhs.x * rhs.x, lhs.y * rhs.y); } static inline ImVec2 ImMul(const ImVec2& lhs, const ImVec2& rhs) { return ImVec2(lhs.x * rhs.x, lhs.y * rhs.y); }
static inline bool ImIsFloatAboveGuaranteedIntegerPrecision(float f) { return f <= -16777216 || f >= 16777216; } static inline bool ImIsFloatAboveGuaranteedIntegerPrecision(float f) { return f <= -16777216 || f >= 16777216; }
static inline float ImExponentialMovingAverage(float avg, float sample, int n) { avg -= avg / n; avg += sample / n; return avg; } static inline float ImExponentialMovingAverage(float avg, float sample, int n) { avg -= avg / n; avg += sample / n; return avg; }
@ -722,7 +729,7 @@ struct ImChunkStream
void swap(ImChunkStream<T>& rhs) { rhs.Buf.swap(Buf); } void swap(ImChunkStream<T>& rhs) { rhs.Buf.swap(Buf); }
}; };
// Helper: ImGuiTextIndex<> // Helper: ImGuiTextIndex
// Maintain a line index for a text buffer. This is a strong candidate to be moved into the public API. // Maintain a line index for a text buffer. This is a strong candidate to be moved into the public API.
struct ImGuiTextIndex struct ImGuiTextIndex
{ {
@ -736,6 +743,8 @@ struct ImGuiTextIndex
void append(const char* base, int old_size, int new_size); void append(const char* base, int old_size, int new_size);
}; };
// Helper: ImGuiStorage
IMGUI_API ImGuiStoragePair* ImLowerBound(ImGuiStoragePair* in_begin, ImGuiStoragePair* in_end, ImGuiID key);
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// [SECTION] ImDrawList support // [SECTION] ImDrawList support
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -772,6 +781,7 @@ struct IMGUI_API ImDrawListSharedData
ImVec2 TexUvWhitePixel; // UV of white pixel in the atlas ImVec2 TexUvWhitePixel; // UV of white pixel in the atlas
ImFont* Font; // Current/default font (optional, for simplified AddText overload) ImFont* Font; // Current/default font (optional, for simplified AddText overload)
float FontSize; // Current/default font size (optional, for simplified AddText overload) float FontSize; // Current/default font size (optional, for simplified AddText overload)
float FontScale; // Current/default font scale (== FontSize / Font->FontSize)
float CurveTessellationTol; // Tessellation tolerance when using PathBezierCurveTo() float CurveTessellationTol; // Tessellation tolerance when using PathBezierCurveTo()
float CircleSegmentMaxError; // Number of circle segments to use per pixel of radius for AddCircle() etc float CircleSegmentMaxError; // Number of circle segments to use per pixel of radius for AddCircle() etc
ImVec4 ClipRectFullscreen; // Value for PushClipRectFullscreen() ImVec4 ClipRectFullscreen; // Value for PushClipRectFullscreen()
@ -798,33 +808,65 @@ struct ImDrawDataBuilder
ImDrawDataBuilder() { memset(this, 0, sizeof(*this)); } ImDrawDataBuilder() { memset(this, 0, sizeof(*this)); }
}; };
//-----------------------------------------------------------------------------
// [SECTION] Data types support
//-----------------------------------------------------------------------------
struct ImGuiDataVarInfo
{
ImGuiDataType Type;
ImU32 Count; // 1+
ImU32 Offset; // Offset in parent structure
void* GetVarPtr(void* parent) const { return (void*)((unsigned char*)parent + Offset); }
};
struct ImGuiDataTypeStorage
{
ImU8 Data[8]; // Opaque storage to fit any data up to ImGuiDataType_COUNT
};
// Type information associated to one ImGuiDataType. Retrieve with DataTypeGetInfo().
struct ImGuiDataTypeInfo
{
size_t Size; // Size in bytes
const char* Name; // Short descriptive name for the type, for debugging
const char* PrintFmt; // Default printf format for the type
const char* ScanFmt; // Default scanf format for the type
};
// Extend ImGuiDataType_
enum ImGuiDataTypePrivate_
{
ImGuiDataType_String = ImGuiDataType_COUNT + 1,
ImGuiDataType_Pointer,
ImGuiDataType_ID,
};
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// [SECTION] Widgets support: flags, enums, data structures // [SECTION] Widgets support: flags, enums, data structures
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Flags used by upcoming items // Extend ImGuiItemFlags
// - input: PushItemFlag() manipulates g.CurrentItemFlags, ItemAdd() calls may add extra flags. // - input: PushItemFlag() manipulates g.CurrentItemFlags, ItemAdd() calls may add extra flags.
// - output: stored in g.LastItemData.InFlags // - output: stored in g.LastItemData.InFlags
// Current window shared by all windows. enum ImGuiItemFlagsPrivate_
// This is going to be exposed in imgui.h when stabilized enough.
enum ImGuiItemFlags_
{ {
// Controlled by user // Controlled by user
ImGuiItemFlags_None = 0, ImGuiItemFlags_Disabled = 1 << 10, // false // Disable interactions (DOES NOT affect visuals, see BeginDisabled()/EndDisabled() for full disable feature, and github #211).
ImGuiItemFlags_NoTabStop = 1 << 0, // false // Disable keyboard tabbing. This is a "lighter" version of ImGuiItemFlags_NoNav. ImGuiItemFlags_ReadOnly = 1 << 11, // false // [ALPHA] Allow hovering interactions but underlying value is not changed.
ImGuiItemFlags_ButtonRepeat = 1 << 1, // false // Button() will return true multiple times based on io.KeyRepeatDelay and io.KeyRepeatRate settings. ImGuiItemFlags_MixedValue = 1 << 12, // false // [BETA] Represent a mixed/indeterminate value, generally multi-selection where values differ. Currently only supported by Checkbox() (later should support all sorts of widgets)
ImGuiItemFlags_Disabled = 1 << 2, // false // Disable interactions but doesn't affect visuals. See BeginDisabled()/EndDisabled(). See github.com/ocornut/imgui/issues/211 ImGuiItemFlags_NoWindowHoverableCheck = 1 << 13, // false // Disable hoverable check in ItemHoverable()
ImGuiItemFlags_NoNav = 1 << 3, // false // Disable any form of focusing (keyboard/gamepad directional navigation and SetKeyboardFocusHere() calls) ImGuiItemFlags_AllowOverlap = 1 << 14, // false // Allow being overlapped by another widget. Not-hovered to Hovered transition deferred by a frame.
ImGuiItemFlags_NoNavDefaultFocus = 1 << 4, // false // Disable item being a candidate for default focus (e.g. used by title bar items)
ImGuiItemFlags_SelectableDontClosePopup = 1 << 5, // false // Disable MenuItem/Selectable() automatically closing their popup window
ImGuiItemFlags_MixedValue = 1 << 6, // false // [BETA] Represent a mixed/indeterminate value, generally multi-selection where values differ. Currently only supported by Checkbox() (later should support all sorts of widgets)
ImGuiItemFlags_ReadOnly = 1 << 7, // false // [ALPHA] Allow hovering interactions but underlying value is not changed.
ImGuiItemFlags_NoWindowHoverableCheck = 1 << 8, // false // Disable hoverable check in ItemHoverable()
ImGuiItemFlags_AllowOverlap = 1 << 9, // false // Allow being overlapped by another widget. Not-hovered to Hovered transition deferred by a frame.
// Controlled by widget code // Controlled by widget code
ImGuiItemFlags_Inputable = 1 << 10, // false // [WIP] Auto-activate input mode when tab focused. Currently only used and supported by a few items before it becomes a generic feature. ImGuiItemFlags_Inputable = 1 << 20, // false // [WIP] Auto-activate input mode when tab focused. Currently only used and supported by a few items before it becomes a generic feature.
ImGuiItemFlags_HasSelectionUserData = 1 << 11, // false // Set by SetNextItemSelectionUserData() ImGuiItemFlags_HasSelectionUserData = 1 << 21, // false // Set by SetNextItemSelectionUserData()
ImGuiItemFlags_IsMultiSelect = 1 << 22, // false // Set by SetNextItemSelectionUserData()
ImGuiItemFlags_Default_ = ImGuiItemFlags_AutoClosePopups, // Please don't change, use PushItemFlag() instead.
// Obsolete
//ImGuiItemFlags_SelectableDontClosePopup = !ImGuiItemFlags_AutoClosePopups, // Can't have a redirect as we inverted the behavior
}; };
// Status flags for an already submitted item // Status flags for an already submitted item
@ -927,8 +969,9 @@ enum ImGuiSelectableFlagsPrivate_
// Extend ImGuiTreeNodeFlags_ // Extend ImGuiTreeNodeFlags_
enum ImGuiTreeNodeFlagsPrivate_ enum ImGuiTreeNodeFlagsPrivate_
{ {
ImGuiTreeNodeFlags_ClipLabelForTrailingButton = 1 << 20, ImGuiTreeNodeFlags_ClipLabelForTrailingButton = 1 << 28,// FIXME-WIP: Hard-coded for CollapsingHeader()
ImGuiTreeNodeFlags_UpsideDownArrow = 1 << 21,// (FIXME-WIP) Turn Down arrow into an Up arrow, but reversed trees (#6517) ImGuiTreeNodeFlags_UpsideDownArrow = 1 << 29,// FIXME-WIP: Turn Down arrow into an Up arrow, but reversed trees (#6517)
ImGuiTreeNodeFlags_OpenOnMask_ = ImGuiTreeNodeFlags_OpenOnDoubleClick | ImGuiTreeNodeFlags_OpenOnArrow,
}; };
enum ImGuiSeparatorFlags_ enum ImGuiSeparatorFlags_
@ -1079,7 +1122,7 @@ struct IMGUI_API ImGuiInputTextState
ImVector<char> InitialTextA; // value to revert to when pressing Escape = backup of end-user buffer at the time of focus (in UTF-8, unaltered) ImVector<char> InitialTextA; // value to revert to when pressing Escape = backup of end-user buffer at the time of focus (in UTF-8, unaltered)
bool TextAIsValid; // temporary UTF8 buffer is not initially valid before we make the widget active (until then we pull the data from user argument) bool TextAIsValid; // temporary UTF8 buffer is not initially valid before we make the widget active (until then we pull the data from user argument)
int BufCapacityA; // end-user buffer capacity int BufCapacityA; // end-user buffer capacity
float ScrollX; // horizontal scrolling/offset ImVec2 Scroll; // horizontal offset (managed manually) + vertical scrolling (pulled from child window's own Scroll.y)
ImStb::STB_TexteditState Stb; // state for stb_textedit.h ImStb::STB_TexteditState Stb; // state for stb_textedit.h
float CursorAnim; // timer for cursor blink, reset on every user action so the cursor reappears immediately float CursorAnim; // timer for cursor blink, reset on every user action so the cursor reappears immediately
bool CursorFollow; // set when we want scrolling to follow the current cursor position (not always!) bool CursorFollow; // set when we want scrolling to follow the current cursor position (not always!)
@ -1167,29 +1210,30 @@ struct ImGuiNextWindowData
inline void ClearFlags() { Flags = ImGuiNextWindowDataFlags_None; } inline void ClearFlags() { Flags = ImGuiNextWindowDataFlags_None; }
}; };
// Multi-Selection item index or identifier when using SetNextItemSelectionUserData()/BeginMultiSelect()
// (Most users are likely to use this store an item INDEX but this may be used to store a POINTER as well.)
typedef ImS64 ImGuiSelectionUserData;
enum ImGuiNextItemDataFlags_ enum ImGuiNextItemDataFlags_
{ {
ImGuiNextItemDataFlags_None = 0, ImGuiNextItemDataFlags_None = 0,
ImGuiNextItemDataFlags_HasWidth = 1 << 0, ImGuiNextItemDataFlags_HasWidth = 1 << 0,
ImGuiNextItemDataFlags_HasOpen = 1 << 1, ImGuiNextItemDataFlags_HasOpen = 1 << 1,
ImGuiNextItemDataFlags_HasShortcut = 1 << 2, ImGuiNextItemDataFlags_HasShortcut = 1 << 2,
ImGuiNextItemDataFlags_HasRefVal = 1 << 3,
ImGuiNextItemDataFlags_HasStorageID = 1 << 4,
}; };
struct ImGuiNextItemData struct ImGuiNextItemData
{ {
ImGuiNextItemDataFlags Flags; ImGuiNextItemDataFlags Flags;
ImGuiItemFlags ItemFlags; // Currently only tested/used for ImGuiItemFlags_AllowOverlap. ImGuiItemFlags ItemFlags; // Currently only tested/used for ImGuiItemFlags_AllowOverlap and ImGuiItemFlags_HasSelectionUserData.
// Non-flags members are NOT cleared by ItemAdd() meaning they are still valid during NavProcessItem() // Non-flags members are NOT cleared by ItemAdd() meaning they are still valid during NavProcessItem()
ImGuiID FocusScopeId; // Set by SetNextItemSelectionUserData()
ImGuiSelectionUserData SelectionUserData; // Set by SetNextItemSelectionUserData() (note that NULL/0 is a valid value, we use -1 == ImGuiSelectionUserData_Invalid to mark invalid values) ImGuiSelectionUserData SelectionUserData; // Set by SetNextItemSelectionUserData() (note that NULL/0 is a valid value, we use -1 == ImGuiSelectionUserData_Invalid to mark invalid values)
float Width; // Set by SetNextItemWidth() float Width; // Set by SetNextItemWidth()
ImGuiKeyChord Shortcut; // Set by SetNextItemShortcut() ImGuiKeyChord Shortcut; // Set by SetNextItemShortcut()
ImGuiInputFlags ShortcutFlags; // Set by SetNextItemShortcut() ImGuiInputFlags ShortcutFlags; // Set by SetNextItemShortcut()
bool OpenVal; // Set by SetNextItemOpen() bool OpenVal; // Set by SetNextItemOpen()
ImGuiCond OpenCond : 8; ImU8 OpenCond; // Set by SetNextItemOpen()
ImGuiDataTypeStorage RefVal; // Not exposed yet, for ImGuiInputTextFlags_ParseEmptyAsRefVal
ImGuiID StorageId; // Set by SetNextItemStorageID()
ImGuiNextItemData() { memset(this, 0, sizeof(*this)); SelectionUserData = -1; } ImGuiNextItemData() { memset(this, 0, sizeof(*this)); SelectionUserData = -1; }
inline void ClearFlags() { Flags = ImGuiNextItemDataFlags_None; ItemFlags = ImGuiItemFlags_None; } // Also cleared manually by ItemAdd()! inline void ClearFlags() { Flags = ImGuiNextItemDataFlags_None; ItemFlags = ImGuiItemFlags_None; } // Also cleared manually by ItemAdd()!
@ -1211,14 +1255,16 @@ struct ImGuiLastItemData
ImGuiLastItemData() { memset(this, 0, sizeof(*this)); } ImGuiLastItemData() { memset(this, 0, sizeof(*this)); }
}; };
// Store data emitted by TreeNode() for usage by TreePop() to implement ImGuiTreeNodeFlags_NavLeftJumpsBackHere. // Store data emitted by TreeNode() for usage by TreePop()
// This is the minimum amount of data that we need to perform the equivalent of NavApplyItemToResult() and which we can't infer in TreePop() // - To implement ImGuiTreeNodeFlags_NavLeftJumpsBackHere: store the minimum amount of data
// Only stored when the node is a potential candidate for landing on a Left arrow jump. // which we can't infer in TreePop(), to perform the equivalent of NavApplyItemToResult().
struct ImGuiNavTreeNodeData // Only stored when the node is a potential candidate for landing on a Left arrow jump.
struct ImGuiTreeNodeStackData
{ {
ImGuiID ID; ImGuiID ID;
ImGuiItemFlags InFlags; ImGuiTreeNodeFlags TreeFlags;
ImRect NavRect; ImGuiItemFlags InFlags; // Used for nav landing
ImRect NavRect; // Used for nav landing
}; };
struct IMGUI_API ImGuiStackSizes struct IMGUI_API ImGuiStackSizes
@ -1263,40 +1309,6 @@ struct ImGuiPtrOrIndex
ImGuiPtrOrIndex(int index) { Ptr = NULL; Index = index; } ImGuiPtrOrIndex(int index) { Ptr = NULL; Index = index; }
}; };
//-----------------------------------------------------------------------------
// [SECTION] Data types support
//-----------------------------------------------------------------------------
struct ImGuiDataVarInfo
{
ImGuiDataType Type;
ImU32 Count; // 1+
ImU32 Offset; // Offset in parent structure
void* GetVarPtr(void* parent) const { return (void*)((unsigned char*)parent + Offset); }
};
struct ImGuiDataTypeTempStorage
{
ImU8 Data[8]; // Can fit any data up to ImGuiDataType_COUNT
};
// Type information associated to one ImGuiDataType. Retrieve with DataTypeGetInfo().
struct ImGuiDataTypeInfo
{
size_t Size; // Size in bytes
const char* Name; // Short descriptive name for the type, for debugging
const char* PrintFmt; // Default printf format for the type
const char* ScanFmt; // Default scanf format for the type
};
// Extend ImGuiDataType_
enum ImGuiDataTypePrivate_
{
ImGuiDataType_String = ImGuiDataType_COUNT + 1,
ImGuiDataType_Pointer,
ImGuiDataType_ID,
};
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// [SECTION] Popup support // [SECTION] Popup support
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -1347,8 +1359,8 @@ typedef ImBitArray<ImGuiKey_NamedKey_COUNT, -ImGuiKey_NamedKey_BEGIN> ImBitAr
#define ImGuiKey_NavKeyboardTweakFast ImGuiMod_Shift #define ImGuiKey_NavKeyboardTweakFast ImGuiMod_Shift
#define ImGuiKey_NavGamepadTweakSlow ImGuiKey_GamepadL1 #define ImGuiKey_NavGamepadTweakSlow ImGuiKey_GamepadL1
#define ImGuiKey_NavGamepadTweakFast ImGuiKey_GamepadR1 #define ImGuiKey_NavGamepadTweakFast ImGuiKey_GamepadR1
#define ImGuiKey_NavGamepadActivate ImGuiKey_GamepadFaceDown #define ImGuiKey_NavGamepadActivate (g.IO.ConfigNavSwapGamepadButtons ? ImGuiKey_GamepadFaceRight : ImGuiKey_GamepadFaceDown)
#define ImGuiKey_NavGamepadCancel ImGuiKey_GamepadFaceRight #define ImGuiKey_NavGamepadCancel (g.IO.ConfigNavSwapGamepadButtons ? ImGuiKey_GamepadFaceDown : ImGuiKey_GamepadFaceRight)
#define ImGuiKey_NavGamepadMenu ImGuiKey_GamepadFaceLeft #define ImGuiKey_NavGamepadMenu ImGuiKey_GamepadFaceLeft
#define ImGuiKey_NavGamepadInput ImGuiKey_GamepadFaceUp #define ImGuiKey_NavGamepadInput ImGuiKey_GamepadFaceUp
@ -1594,7 +1606,7 @@ struct ImGuiNavItemData
float DistBox; // Move // Best candidate box distance to current NavId float DistBox; // Move // Best candidate box distance to current NavId
float DistCenter; // Move // Best candidate center distance to current NavId float DistCenter; // Move // Best candidate center distance to current NavId
float DistAxial; // Move // Best candidate axial distance to current NavId float DistAxial; // Move // Best candidate axial distance to current NavId
ImGuiSelectionUserData SelectionUserData;//I+Mov // Best candidate SetNextItemSelectionData() value. ImGuiSelectionUserData SelectionUserData;//I+Mov // Best candidate SetNextItemSelectionUserData() value. Valid if (InFlags & ImGuiItemFlags_HasSelectionUserData)
ImGuiNavItemData() { Clear(); } ImGuiNavItemData() { Clear(); }
void Clear() { Window = NULL; ID = FocusScopeId = 0; InFlags = 0; SelectionUserData = -1; DistBox = DistCenter = DistAxial = FLT_MAX; } void Clear() { Window = NULL; ID = FocusScopeId = 0; InFlags = 0; SelectionUserData = -1; DistBox = DistCenter = DistAxial = FLT_MAX; }
@ -1700,6 +1712,34 @@ struct ImGuiOldColumns
ImGuiOldColumns() { memset(this, 0, sizeof(*this)); } ImGuiOldColumns() { memset(this, 0, sizeof(*this)); }
}; };
//-----------------------------------------------------------------------------
// [SECTION] Box-select support
//-----------------------------------------------------------------------------
struct ImGuiBoxSelectState
{
// Active box-selection data (persistent, 1 active at a time)
ImGuiID ID;
bool IsActive;
bool IsStarting;
bool IsStartedFromVoid; // Starting click was not from an item.
bool IsStartedSetNavIdOnce;
bool RequestClear;
ImGuiKeyChord KeyMods : 16; // Latched key-mods for box-select logic.
ImVec2 StartPosRel; // Start position in window-contents relative space (to support scrolling)
ImVec2 EndPosRel; // End position in window-contents relative space
ImVec2 ScrollAccum; // Scrolling accumulator (to behave at high-frame spaces)
ImGuiWindow* Window;
// Temporary/Transient data
bool UnclipMode; // (Temp/Transient, here in hot area). Set/cleared by the BeginMultiSelect()/EndMultiSelect() owning active box-select.
ImRect UnclipRect; // Rectangle where ItemAdd() clipping may be temporarily disabled. Need support by multi-select supporting widgets.
ImRect BoxSelectRectPrev; // Selection rectangle in absolute coordinates (derived every frame from BoxSelectStartPosRel and MousePos)
ImRect BoxSelectRectCurr;
ImGuiBoxSelectState() { memset(this, 0, sizeof(*this)); }
};
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// [SECTION] Multi-select support // [SECTION] Multi-select support
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -1707,9 +1747,45 @@ struct ImGuiOldColumns
// We always assume that -1 is an invalid value (which works for indices and pointers) // We always assume that -1 is an invalid value (which works for indices and pointers)
#define ImGuiSelectionUserData_Invalid ((ImGuiSelectionUserData)-1) #define ImGuiSelectionUserData_Invalid ((ImGuiSelectionUserData)-1)
#ifdef IMGUI_HAS_MULTI_SELECT // Temporary storage for multi-select
// <this is filled in 'range_select' branch> struct IMGUI_API ImGuiMultiSelectTempData
#endif // #ifdef IMGUI_HAS_MULTI_SELECT {
ImGuiMultiSelectIO IO; // MUST BE FIRST FIELD. Requests are set and returned by BeginMultiSelect()/EndMultiSelect() + written to by user during the loop.
ImGuiMultiSelectState* Storage;
ImGuiID FocusScopeId; // Copied from g.CurrentFocusScopeId (unless another selection scope was pushed manually)
ImGuiMultiSelectFlags Flags;
ImVec2 ScopeRectMin;
ImVec2 BackupCursorMaxPos;
ImGuiSelectionUserData LastSubmittedItem; // Copy of last submitted item data, used to merge output ranges.
ImGuiID BoxSelectId;
ImGuiKeyChord KeyMods;
ImS8 LoopRequestSetAll; // -1: no operation, 0: clear all, 1: select all.
bool IsEndIO; // Set when switching IO from BeginMultiSelect() to EndMultiSelect() state.
bool IsFocused; // Set if currently focusing the selection scope (any item of the selection). May be used if you have custom shortcut associated to selection.
bool IsKeyboardSetRange; // Set by BeginMultiSelect() when using Shift+Navigation. Because scrolling may be affected we can't afford a frame of lag with Shift+Navigation.
bool NavIdPassedBy;
bool RangeSrcPassedBy; // Set by the item that matches RangeSrcItem.
bool RangeDstPassedBy; // Set by the item that matches NavJustMovedToId when IsSetRange is set.
ImGuiMultiSelectTempData() { Clear(); }
void Clear() { size_t io_sz = sizeof(IO); ClearIO(); memset((void*)(&IO + 1), 0, sizeof(*this) - io_sz); } // Zero-clear except IO as we preserve IO.Requests[] buffer allocation.
void ClearIO() { IO.Requests.resize(0); IO.RangeSrcItem = IO.NavIdItem = ImGuiSelectionUserData_Invalid; IO.NavIdSelected = IO.RangeSrcReset = false; }
};
// Persistent storage for multi-select (as long as selection is alive)
struct IMGUI_API ImGuiMultiSelectState
{
ImGuiWindow* Window;
ImGuiID ID;
int LastFrameActive; // Last used frame-count, for GC.
int LastSelectionSize; // Set by BeginMultiSelect() based on optional info provided by user. May be -1 if unknown.
ImS8 RangeSelected; // -1 (don't have) or true/false
ImS8 NavIdSelected; // -1 (don't have) or true/false
ImGuiSelectionUserData RangeSrcItem; //
ImGuiSelectionUserData NavIdItem; // SetNextItemSelectionUserData() value for NavId (if part of submitted items)
ImGuiMultiSelectState() { Window = NULL; ID = 0; LastFrameActive = LastSelectionSize = 0; RangeSelected = NavIdSelected = -1; RangeSrcItem = NavIdItem = ImGuiSelectionUserData_Invalid; }
};
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// [SECTION] Docking support // [SECTION] Docking support
@ -1731,23 +1807,28 @@ struct ImGuiViewportP : public ImGuiViewport
ImDrawList* BgFgDrawLists[2]; // Convenience background (0) and foreground (1) draw lists. We use them to draw software mouser cursor when io.MouseDrawCursor is set and to draw most debug overlays. ImDrawList* BgFgDrawLists[2]; // Convenience background (0) and foreground (1) draw lists. We use them to draw software mouser cursor when io.MouseDrawCursor is set and to draw most debug overlays.
ImDrawData DrawDataP; ImDrawData DrawDataP;
ImDrawDataBuilder DrawDataBuilder; // Temporary data while building final ImDrawData ImDrawDataBuilder DrawDataBuilder; // Temporary data while building final ImDrawData
ImVec2 WorkOffsetMin; // Work Area: Offset from Pos to top-left corner of Work Area. Generally (0,0) or (0,+main_menu_bar_height). Work Area is Full Area but without menu-bars/status-bars (so WorkArea always fit inside Pos/Size!)
ImVec2 WorkOffsetMax; // Work Area: Offset from Pos+Size to bottom-right corner of Work Area. Generally (0,0) or (0,-status_bar_height). // Per-viewport work area
ImVec2 BuildWorkOffsetMin; // Work Area: Offset being built during current frame. Generally >= 0.0f. // - Insets are >= 0.0f values, distance from viewport corners to work area.
ImVec2 BuildWorkOffsetMax; // Work Area: Offset being built during current frame. Generally <= 0.0f. // - BeginMainMenuBar() and DockspaceOverViewport() tend to use work area to avoid stepping over existing contents.
// - Generally 'safeAreaInsets' in iOS land, 'DisplayCutout' in Android land.
ImVec2 WorkInsetMin; // Work Area inset locked for the frame. GetWorkRect() always fits within GetMainRect().
ImVec2 WorkInsetMax; // "
ImVec2 BuildWorkInsetMin; // Work Area inset accumulator for current frame, to become next frame's WorkInset
ImVec2 BuildWorkInsetMax; // "
ImGuiViewportP() { BgFgDrawListsLastFrame[0] = BgFgDrawListsLastFrame[1] = -1; BgFgDrawLists[0] = BgFgDrawLists[1] = NULL; } ImGuiViewportP() { BgFgDrawListsLastFrame[0] = BgFgDrawListsLastFrame[1] = -1; BgFgDrawLists[0] = BgFgDrawLists[1] = NULL; }
~ImGuiViewportP() { if (BgFgDrawLists[0]) IM_DELETE(BgFgDrawLists[0]); if (BgFgDrawLists[1]) IM_DELETE(BgFgDrawLists[1]); } ~ImGuiViewportP() { if (BgFgDrawLists[0]) IM_DELETE(BgFgDrawLists[0]); if (BgFgDrawLists[1]) IM_DELETE(BgFgDrawLists[1]); }
// Calculate work rect pos/size given a set of offset (we have 1 pair of offset for rect locked from last frame data, and 1 pair for currently building rect) // Calculate work rect pos/size given a set of offset (we have 1 pair of offset for rect locked from last frame data, and 1 pair for currently building rect)
ImVec2 CalcWorkRectPos(const ImVec2& off_min) const { return ImVec2(Pos.x + off_min.x, Pos.y + off_min.y); } ImVec2 CalcWorkRectPos(const ImVec2& inset_min) const { return ImVec2(Pos.x + inset_min.x, Pos.y + inset_min.y); }
ImVec2 CalcWorkRectSize(const ImVec2& off_min, const ImVec2& off_max) const { return ImVec2(ImMax(0.0f, Size.x - off_min.x + off_max.x), ImMax(0.0f, Size.y - off_min.y + off_max.y)); } ImVec2 CalcWorkRectSize(const ImVec2& inset_min, const ImVec2& inset_max) const { return ImVec2(ImMax(0.0f, Size.x - inset_min.x - inset_max.x), ImMax(0.0f, Size.y - inset_min.y - inset_max.y)); }
void UpdateWorkRect() { WorkPos = CalcWorkRectPos(WorkOffsetMin); WorkSize = CalcWorkRectSize(WorkOffsetMin, WorkOffsetMax); } // Update public fields void UpdateWorkRect() { WorkPos = CalcWorkRectPos(WorkInsetMin); WorkSize = CalcWorkRectSize(WorkInsetMin, WorkInsetMax); } // Update public fields
// Helpers to retrieve ImRect (we don't need to store BuildWorkRect as every access tend to change it, hence the code asymmetry) // Helpers to retrieve ImRect (we don't need to store BuildWorkRect as every access tend to change it, hence the code asymmetry)
ImRect GetMainRect() const { return ImRect(Pos.x, Pos.y, Pos.x + Size.x, Pos.y + Size.y); } ImRect GetMainRect() const { return ImRect(Pos.x, Pos.y, Pos.x + Size.x, Pos.y + Size.y); }
ImRect GetWorkRect() const { return ImRect(WorkPos.x, WorkPos.y, WorkPos.x + WorkSize.x, WorkPos.y + WorkSize.y); } ImRect GetWorkRect() const { return ImRect(WorkPos.x, WorkPos.y, WorkPos.x + WorkSize.x, WorkPos.y + WorkSize.y); }
ImRect GetBuildWorkRect() const { ImVec2 pos = CalcWorkRectPos(BuildWorkOffsetMin); ImVec2 size = CalcWorkRectSize(BuildWorkOffsetMin, BuildWorkOffsetMax); return ImRect(pos.x, pos.y, pos.x + size.x, pos.y + size.y); } ImRect GetBuildWorkRect() const { ImVec2 pos = CalcWorkRectPos(BuildWorkInsetMin); ImVec2 size = CalcWorkRectSize(BuildWorkInsetMin, BuildWorkInsetMax); return ImRect(pos.x, pos.y, pos.x + size.x, pos.y + size.y); }
}; };
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -1801,6 +1882,7 @@ enum ImGuiLocKey : int
ImGuiLocKey_WindowingMainMenuBar, ImGuiLocKey_WindowingMainMenuBar,
ImGuiLocKey_WindowingPopup, ImGuiLocKey_WindowingPopup,
ImGuiLocKey_WindowingUntitled, ImGuiLocKey_WindowingUntitled,
ImGuiLocKey_CopyLink,
ImGuiLocKey_COUNT ImGuiLocKey_COUNT
}; };
@ -1918,10 +2000,12 @@ struct ImGuiContext
bool Initialized; bool Initialized;
bool FontAtlasOwnedByContext; // IO.Fonts-> is owned by the ImGuiContext and will be destructed along with it. bool FontAtlasOwnedByContext; // IO.Fonts-> is owned by the ImGuiContext and will be destructed along with it.
ImGuiIO IO; ImGuiIO IO;
ImGuiPlatformIO PlatformIO;
ImGuiStyle Style; ImGuiStyle Style;
ImFont* Font; // (Shortcut) == FontStack.empty() ? IO.Font : FontStack.back() ImFont* Font; // (Shortcut) == FontStack.empty() ? IO.Font : FontStack.back()
float FontSize; // (Shortcut) == FontBaseSize * g.CurrentWindow->FontWindowScale == window->FontSize(). Text height for current window. float FontSize; // (Shortcut) == FontBaseSize * g.CurrentWindow->FontWindowScale == window->FontSize(). Text height for current window.
float FontBaseSize; // (Shortcut) == IO.FontGlobalScale * Font->Scale * Font->FontSize. Base text height. float FontBaseSize; // (Shortcut) == IO.FontGlobalScale * Font->Scale * Font->FontSize. Base text height.
float FontScale; // == FontSize / Font->FontSize
float CurrentDpiScale; // Current window/viewport DpiScale float CurrentDpiScale; // Current window/viewport DpiScale
ImDrawListSharedData DrawListSharedData; ImDrawListSharedData DrawListSharedData;
double Time; double Time;
@ -1934,6 +2018,7 @@ struct ImGuiContext
bool GcCompactAll; // Request full GC bool GcCompactAll; // Request full GC
bool TestEngineHookItems; // Will call test engine hooks: ImGuiTestEngineHook_ItemAdd(), ImGuiTestEngineHook_ItemInfo(), ImGuiTestEngineHook_Log() bool TestEngineHookItems; // Will call test engine hooks: ImGuiTestEngineHook_ItemAdd(), ImGuiTestEngineHook_ItemInfo(), ImGuiTestEngineHook_Log()
void* TestEngine; // Test engine user data void* TestEngine; // Test engine user data
char ContextName[16]; // Storage for a context name (to facilitate debugging multi-context setups)
// Inputs // Inputs
ImVector<ImGuiInputEvent> InputEventsQueue; // Input events which will be trickled/written into IO structure. ImVector<ImGuiInputEvent> InputEventsQueue; // Input events which will be trickled/written into IO structure.
@ -1953,6 +2038,7 @@ struct ImGuiContext
ImGuiWindow* CurrentWindow; // Window being drawn into ImGuiWindow* CurrentWindow; // Window being drawn into
ImGuiWindow* HoveredWindow; // Window the mouse is hovering. Will typically catch mouse inputs. ImGuiWindow* HoveredWindow; // Window the mouse is hovering. Will typically catch mouse inputs.
ImGuiWindow* HoveredWindowUnderMovingWindow; // Hovered window ignoring MovingWindow. Only set if MovingWindow is set. ImGuiWindow* HoveredWindowUnderMovingWindow; // Hovered window ignoring MovingWindow. Only set if MovingWindow is set.
ImGuiWindow* HoveredWindowBeforeClear; // Window the mouse is hovering. Filled even with _NoMouse. This is currently useful for multi-context compositors.
ImGuiWindow* MovingWindow; // Track the window we clicked on (in order to preserve focus). The actual window that is moved is generally MovingWindow->RootWindow. ImGuiWindow* MovingWindow; // Track the window we clicked on (in order to preserve focus). The actual window that is moved is generally MovingWindow->RootWindow.
ImGuiWindow* WheelingWindow; // Track the window we started mouse-wheeling on. Until a timer elapse or mouse has moved, generally keep scrolling the same window even if during the course of scrolling the mouse ends up hovering a child window. ImGuiWindow* WheelingWindow; // Track the window we started mouse-wheeling on. Until a timer elapse or mouse has moved, generally keep scrolling the same window even if during the course of scrolling the mouse ends up hovering a child window.
ImVec2 WheelingWindowRefMousePos; ImVec2 WheelingWindowRefMousePos;
@ -1969,7 +2055,7 @@ struct ImGuiContext
float HoveredIdTimer; // Measure contiguous hovering time float HoveredIdTimer; // Measure contiguous hovering time
float HoveredIdNotActiveTimer; // Measure contiguous hovering time where the item has not been active float HoveredIdNotActiveTimer; // Measure contiguous hovering time where the item has not been active
bool HoveredIdAllowOverlap; bool HoveredIdAllowOverlap;
bool HoveredIdDisabled; // At least one widget passed the rect test, but has been discarded by disabled flag or popup inhibit. May be true even if HoveredId == 0. bool HoveredIdIsDisabled; // At least one widget passed the rect test, but has been discarded by disabled flag or popup inhibit. May be true even if HoveredId == 0.
bool ItemUnclipByLog; // Disable ItemAdd() clipping, essentially a memory-locality friendly copy of LogEnabled bool ItemUnclipByLog; // Disable ItemAdd() clipping, essentially a memory-locality friendly copy of LogEnabled
ImGuiID ActiveId; // Active widget ImGuiID ActiveId; // Active widget
ImGuiID ActiveIdIsAlive; // Active widget has been seen this frame (we can't use a bool as the ActiveId may change within the frame) ImGuiID ActiveIdIsAlive; // Active widget has been seen this frame (we can't use a bool as the ActiveId may change within the frame)
@ -2003,11 +2089,9 @@ struct ImGuiContext
ImGuiKeyOwnerData KeysOwnerData[ImGuiKey_NamedKey_COUNT]; ImGuiKeyOwnerData KeysOwnerData[ImGuiKey_NamedKey_COUNT];
ImGuiKeyRoutingTable KeysRoutingTable; ImGuiKeyRoutingTable KeysRoutingTable;
ImU32 ActiveIdUsingNavDirMask; // Active widget will want to read those nav move requests (e.g. can activate a button and move away from it) ImU32 ActiveIdUsingNavDirMask; // Active widget will want to read those nav move requests (e.g. can activate a button and move away from it)
bool ActiveIdUsingAllKeyboardKeys; // Active widget will want to read all keyboard keys inputs. (FIXME: This is a shortcut for not taking ownership of 100+ keys but perhaps best to not have the inconsistency) bool ActiveIdUsingAllKeyboardKeys; // Active widget will want to read all keyboard keys inputs. (this is a shortcut for not taking ownership of 100+ keys, frequently used by drag operations)
ImGuiKeyChord DebugBreakInShortcutRouting; // Set to break in SetShortcutRouting()/Shortcut() calls. ImGuiKeyChord DebugBreakInShortcutRouting; // Set to break in SetShortcutRouting()/Shortcut() calls.
#ifndef IMGUI_DISABLE_OBSOLETE_KEYIO //ImU32 ActiveIdUsingNavInputMask; // [OBSOLETE] Since (IMGUI_VERSION_NUM >= 18804) : 'g.ActiveIdUsingNavInputMask |= (1 << ImGuiNavInput_Cancel);' becomes --> 'SetKeyOwner(ImGuiKey_Escape, g.ActiveId) and/or SetKeyOwner(ImGuiKey_NavGamepadCancel, g.ActiveId);'
ImU32 ActiveIdUsingNavInputMask; // If you used this. Since (IMGUI_VERSION_NUM >= 18804) : 'g.ActiveIdUsingNavInputMask |= (1 << ImGuiNavInput_Cancel);' becomes 'SetKeyOwner(ImGuiKey_Escape, g.ActiveId) and/or SetKeyOwner(ImGuiKey_NavGamepadCancel, g.ActiveId);'
#endif
// Next window/item data // Next window/item data
ImGuiID CurrentFocusScopeId; // Value for currently appending items == g.FocusScopeStack.back(). Not to be mistaken with g.NavFocusScopeId. ImGuiID CurrentFocusScopeId; // Value for currently appending items == g.FocusScopeStack.back(). Not to be mistaken with g.NavFocusScopeId.
@ -2028,7 +2112,7 @@ struct ImGuiContext
ImVector<ImGuiGroupData> GroupStack; // Stack for BeginGroup()/EndGroup() - not inherited by Begin() ImVector<ImGuiGroupData> GroupStack; // Stack for BeginGroup()/EndGroup() - not inherited by Begin()
ImVector<ImGuiPopupData> OpenPopupStack; // Which popups are open (persistent) ImVector<ImGuiPopupData> OpenPopupStack; // Which popups are open (persistent)
ImVector<ImGuiPopupData> BeginPopupStack; // Which level of BeginPopup() we are in (reset every frame) ImVector<ImGuiPopupData> BeginPopupStack; // Which level of BeginPopup() we are in (reset every frame)
ImVector<ImGuiNavTreeNodeData> NavTreeNodeStack; // Stack for TreeNode() when a NavLeft requested is emitted. ImVector<ImGuiTreeNodeStackData>TreeNodeStack; // Stack for TreeNode()
// Viewports // Viewports
ImVector<ImGuiViewportP*> Viewports; // Active viewports (Size==1 in 'master' branch). Each viewports hold their copy of ImDrawData. ImVector<ImGuiViewportP*> Viewports; // Active viewports (Size==1 in 'master' branch). Each viewports hold their copy of ImDrawData.
@ -2037,6 +2121,7 @@ struct ImGuiContext
ImGuiWindow* NavWindow; // Focused window for navigation. Could be called 'FocusedWindow' ImGuiWindow* NavWindow; // Focused window for navigation. Could be called 'FocusedWindow'
ImGuiID NavId; // Focused item for navigation ImGuiID NavId; // Focused item for navigation
ImGuiID NavFocusScopeId; // Focused focus scope (e.g. selection code often wants to "clear other items" when landing on an item of the same scope) ImGuiID NavFocusScopeId; // Focused focus scope (e.g. selection code often wants to "clear other items" when landing on an item of the same scope)
ImGuiNavLayer NavLayer; // Focused layer (main scrolling layer, or menu/title bar layer)
ImGuiID NavActivateId; // ~~ (g.ActiveId == 0) && (IsKeyPressed(ImGuiKey_Space) || IsKeyDown(ImGuiKey_Enter) || IsKeyPressed(ImGuiKey_NavGamepadActivate)) ? NavId : 0, also set when calling ActivateItem() ImGuiID NavActivateId; // ~~ (g.ActiveId == 0) && (IsKeyPressed(ImGuiKey_Space) || IsKeyDown(ImGuiKey_Enter) || IsKeyPressed(ImGuiKey_NavGamepadActivate)) ? NavId : 0, also set when calling ActivateItem()
ImGuiID NavActivateDownId; // ~~ IsKeyDown(ImGuiKey_Space) || IsKeyDown(ImGuiKey_Enter) || IsKeyDown(ImGuiKey_NavGamepadActivate) ? NavId : 0 ImGuiID NavActivateDownId; // ~~ IsKeyDown(ImGuiKey_Space) || IsKeyDown(ImGuiKey_Enter) || IsKeyDown(ImGuiKey_NavGamepadActivate) ? NavId : 0
ImGuiID NavActivatePressedId; // ~~ IsKeyPressed(ImGuiKey_Space) || IsKeyPressed(ImGuiKey_Enter) || IsKeyPressed(ImGuiKey_NavGamepadActivate) ? NavId : 0 (no repeat) ImGuiID NavActivatePressedId; // ~~ IsKeyPressed(ImGuiKey_Space) || IsKeyPressed(ImGuiKey_Enter) || IsKeyPressed(ImGuiKey_NavGamepadActivate) ? NavId : 0 (no repeat)
@ -2044,13 +2129,9 @@ struct ImGuiContext
ImVector<ImGuiFocusScopeData> NavFocusRoute; // Reversed copy focus scope stack for NavId (should contains NavFocusScopeId). This essentially follow the window->ParentWindowForFocusRoute chain. ImVector<ImGuiFocusScopeData> NavFocusRoute; // Reversed copy focus scope stack for NavId (should contains NavFocusScopeId). This essentially follow the window->ParentWindowForFocusRoute chain.
ImGuiID NavHighlightActivatedId; ImGuiID NavHighlightActivatedId;
float NavHighlightActivatedTimer; float NavHighlightActivatedTimer;
ImGuiID NavJustMovedToId; // Just navigated to this id (result of a successfully MoveRequest).
ImGuiID NavJustMovedToFocusScopeId; // Just navigated to this focus scope id (result of a successfully MoveRequest).
ImGuiKeyChord NavJustMovedToKeyMods;
ImGuiID NavNextActivateId; // Set by ActivateItem(), queued until next frame. ImGuiID NavNextActivateId; // Set by ActivateItem(), queued until next frame.
ImGuiActivateFlags NavNextActivateFlags; ImGuiActivateFlags NavNextActivateFlags;
ImGuiInputSource NavInputSource; // Keyboard or Gamepad mode? THIS CAN ONLY BE ImGuiInputSource_Keyboard or ImGuiInputSource_Mouse ImGuiInputSource NavInputSource; // Keyboard or Gamepad mode? THIS CAN ONLY BE ImGuiInputSource_Keyboard or ImGuiInputSource_Mouse
ImGuiNavLayer NavLayer; // Layer we are navigating on. For now the system is hard-coded for 0=main contents and 1=menu/title bar, may expose layers later.
ImGuiSelectionUserData NavLastValidSelectionUserData; // Last valid data passed to SetNextItemSelectionUser(), or -1. For current window. Not reset when focusing an item that doesn't have selection data. ImGuiSelectionUserData NavLastValidSelectionUserData; // Last valid data passed to SetNextItemSelectionUser(), or -1. For current window. Not reset when focusing an item that doesn't have selection data.
bool NavIdIsAlive; // Nav widget has been seen this frame ~~ NavRectRel is valid bool NavIdIsAlive; // Nav widget has been seen this frame ~~ NavRectRel is valid
bool NavMousePosDirty; // When set we will update mouse position if (io.ConfigFlags & ImGuiConfigFlags_NavEnableSetMousePos) if set (NB: this not enabled by default) bool NavMousePosDirty; // When set we will update mouse position if (io.ConfigFlags & ImGuiConfigFlags_NavEnableSetMousePos) if set (NB: this not enabled by default)
@ -2081,6 +2162,14 @@ struct ImGuiContext
ImGuiNavItemData NavMoveResultOther; // Best move request candidate within NavWindow's flattened hierarchy (when using ImGuiWindowFlags_NavFlattened flag) ImGuiNavItemData NavMoveResultOther; // Best move request candidate within NavWindow's flattened hierarchy (when using ImGuiWindowFlags_NavFlattened flag)
ImGuiNavItemData NavTabbingResultFirst; // First tabbing request candidate within NavWindow and flattened hierarchy ImGuiNavItemData NavTabbingResultFirst; // First tabbing request candidate within NavWindow and flattened hierarchy
// Navigation: record of last move request
ImGuiID NavJustMovedFromFocusScopeId; // Just navigated from this focus scope id (result of a successfully MoveRequest).
ImGuiID NavJustMovedToId; // Just navigated to this id (result of a successfully MoveRequest).
ImGuiID NavJustMovedToFocusScopeId; // Just navigated to this focus scope id (result of a successfully MoveRequest).
ImGuiKeyChord NavJustMovedToKeyMods;
bool NavJustMovedToIsTabbing; // Copy of ImGuiNavMoveFlags_IsTabbing. Maybe we should store whole flags.
bool NavJustMovedToHasSelectionData; // Copy of move result's InFlags & ImGuiItemFlags_HasSelectionUserData). Maybe we should just store ImGuiNavItemData.
// Navigation: Windowing (CTRL+TAB for list, or Menu button + keys or directional pads to move/resize) // Navigation: Windowing (CTRL+TAB for list, or Menu button + keys or directional pads to move/resize)
ImGuiKeyChord ConfigNavWindowingKeyNext; // = ImGuiMod_Ctrl | ImGuiKey_Tab (or ImGuiMod_Super | ImGuiKey_Tab on OS X). For reconfiguration (see #4828) ImGuiKeyChord ConfigNavWindowingKeyNext; // = ImGuiMod_Ctrl | ImGuiKey_Tab (or ImGuiMod_Super | ImGuiKey_Tab on OS X). For reconfiguration (see #4828)
ImGuiKeyChord ConfigNavWindowingKeyPrev; // = ImGuiMod_Ctrl | ImGuiMod_Shift | ImGuiKey_Tab (or ImGuiMod_Super | ImGuiMod_Shift | ImGuiKey_Tab on OS X) ImGuiKeyChord ConfigNavWindowingKeyPrev; // = ImGuiMod_Ctrl | ImGuiMod_Shift | ImGuiKey_Tab (or ImGuiMod_Super | ImGuiMod_Shift | ImGuiKey_Tab on OS X)
@ -2136,6 +2225,13 @@ struct ImGuiContext
ImVector<ImGuiPtrOrIndex> CurrentTabBarStack; ImVector<ImGuiPtrOrIndex> CurrentTabBarStack;
ImVector<ImGuiShrinkWidthItem> ShrinkWidthBuffer; ImVector<ImGuiShrinkWidthItem> ShrinkWidthBuffer;
// Multi-Select state
ImGuiBoxSelectState BoxSelectState;
ImGuiMultiSelectTempData* CurrentMultiSelect;
int MultiSelectTempDataStacked; // Temporary multi-select data size (because we leave previous instances undestructed, we generally don't use MultiSelectTempData.Size)
ImVector<ImGuiMultiSelectTempData> MultiSelectTempData;
ImPool<ImGuiMultiSelectState> MultiSelectStorage;
// Hover Delay system // Hover Delay system
ImGuiID HoverItemDelayId; ImGuiID HoverItemDelayId;
ImGuiID HoverItemDelayIdPreviousFrame; ImGuiID HoverItemDelayIdPreviousFrame;
@ -2154,6 +2250,7 @@ struct ImGuiContext
ImGuiInputTextDeactivatedState InputTextDeactivatedState; ImGuiInputTextDeactivatedState InputTextDeactivatedState;
ImFont InputTextPasswordFont; ImFont InputTextPasswordFont;
ImGuiID TempInputId; // Temporary text input when CTRL+clicking on a slider, etc. ImGuiID TempInputId; // Temporary text input when CTRL+clicking on a slider, etc.
ImGuiDataTypeStorage DataTypeZeroValue; // 0 for all data types
int BeginMenuDepth; int BeginMenuDepth;
int BeginComboDepth; int BeginComboDepth;
ImGuiColorEditFlags ColorEditOptions; // Store user options for color edit widgets ImGuiColorEditFlags ColorEditOptions; // Store user options for color edit widgets
@ -2184,7 +2281,7 @@ struct ImGuiContext
// Platform support // Platform support
ImGuiPlatformImeData PlatformImeData; // Data updated by current frame ImGuiPlatformImeData PlatformImeData; // Data updated by current frame
ImGuiPlatformImeData PlatformImeDataPrev; // Previous frame data (when changing we will call io.SetPlatformImeDataFn ImGuiPlatformImeData PlatformImeDataPrev; // Previous frame data. When changed we call the platform_io.Platform_SetImeDataFn() handler.
// Settings // Settings
bool SettingsLoaded; bool SettingsLoaded;
@ -2251,7 +2348,7 @@ struct ImGuiContext
Initialized = false; Initialized = false;
FontAtlasOwnedByContext = shared_font_atlas ? false : true; FontAtlasOwnedByContext = shared_font_atlas ? false : true;
Font = NULL; Font = NULL;
FontSize = FontBaseSize = CurrentDpiScale = 0.0f; FontSize = FontBaseSize = FontScale = CurrentDpiScale = 0.0f;
IO.Fonts = shared_font_atlas ? shared_font_atlas : IM_NEW(ImFontAtlas)(); IO.Fonts = shared_font_atlas ? shared_font_atlas : IM_NEW(ImFontAtlas)();
Time = 0.0f; Time = 0.0f;
FrameCount = 0; FrameCount = 0;
@ -2260,6 +2357,7 @@ struct ImGuiContext
GcCompactAll = false; GcCompactAll = false;
TestEngineHookItems = false; TestEngineHookItems = false;
TestEngine = NULL; TestEngine = NULL;
memset(ContextName, 0, sizeof(ContextName));
InputEventsNextMouseSource = ImGuiMouseSource_Mouse; InputEventsNextMouseSource = ImGuiMouseSource_Mouse;
InputEventsNextEventId = 1; InputEventsNextEventId = 1;
@ -2268,6 +2366,7 @@ struct ImGuiContext
CurrentWindow = NULL; CurrentWindow = NULL;
HoveredWindow = NULL; HoveredWindow = NULL;
HoveredWindowUnderMovingWindow = NULL; HoveredWindowUnderMovingWindow = NULL;
HoveredWindowBeforeClear = NULL;
MovingWindow = NULL; MovingWindow = NULL;
WheelingWindow = NULL; WheelingWindow = NULL;
WheelingWindowStartFrame = WheelingWindowScrolledFrame = -1; WheelingWindowStartFrame = WheelingWindowScrolledFrame = -1;
@ -2276,7 +2375,7 @@ struct ImGuiContext
DebugHookIdInfo = 0; DebugHookIdInfo = 0;
HoveredId = HoveredIdPreviousFrame = 0; HoveredId = HoveredIdPreviousFrame = 0;
HoveredIdAllowOverlap = false; HoveredIdAllowOverlap = false;
HoveredIdDisabled = false; HoveredIdIsDisabled = false;
HoveredIdTimer = HoveredIdNotActiveTimer = 0.0f; HoveredIdTimer = HoveredIdNotActiveTimer = 0.0f;
ItemUnclipByLog = false; ItemUnclipByLog = false;
ActiveId = 0; ActiveId = 0;
@ -2304,9 +2403,6 @@ struct ImGuiContext
ActiveIdUsingNavDirMask = 0x00; ActiveIdUsingNavDirMask = 0x00;
ActiveIdUsingAllKeyboardKeys = false; ActiveIdUsingAllKeyboardKeys = false;
#ifndef IMGUI_DISABLE_OBSOLETE_KEYIO
ActiveIdUsingNavInputMask = 0x00;
#endif
CurrentFocusScopeId = 0; CurrentFocusScopeId = 0;
CurrentItemFlags = ImGuiItemFlags_None; CurrentItemFlags = ImGuiItemFlags_None;
@ -2314,18 +2410,18 @@ struct ImGuiContext
NavWindow = NULL; NavWindow = NULL;
NavId = NavFocusScopeId = NavActivateId = NavActivateDownId = NavActivatePressedId = 0; NavId = NavFocusScopeId = NavActivateId = NavActivateDownId = NavActivatePressedId = 0;
NavJustMovedToId = NavJustMovedToFocusScopeId = NavNextActivateId = 0; NavLayer = ImGuiNavLayer_Main;
NavNextActivateId = 0;
NavActivateFlags = NavNextActivateFlags = ImGuiActivateFlags_None; NavActivateFlags = NavNextActivateFlags = ImGuiActivateFlags_None;
NavHighlightActivatedId = 0; NavHighlightActivatedId = 0;
NavHighlightActivatedTimer = 0.0f; NavHighlightActivatedTimer = 0.0f;
NavJustMovedToKeyMods = ImGuiMod_None;
NavInputSource = ImGuiInputSource_Keyboard; NavInputSource = ImGuiInputSource_Keyboard;
NavLayer = ImGuiNavLayer_Main;
NavLastValidSelectionUserData = ImGuiSelectionUserData_Invalid; NavLastValidSelectionUserData = ImGuiSelectionUserData_Invalid;
NavIdIsAlive = false; NavIdIsAlive = false;
NavMousePosDirty = false; NavMousePosDirty = false;
NavDisableHighlight = true; NavDisableHighlight = true;
NavDisableMouseHover = false; NavDisableMouseHover = false;
NavAnyRequest = false; NavAnyRequest = false;
NavInitRequest = false; NavInitRequest = false;
NavInitRequestFromMove = false; NavInitRequestFromMove = false;
@ -2340,6 +2436,11 @@ struct ImGuiContext
NavTabbingDir = 0; NavTabbingDir = 0;
NavTabbingCounter = 0; NavTabbingCounter = 0;
NavJustMovedFromFocusScopeId = NavJustMovedToId = NavJustMovedToFocusScopeId = 0;
NavJustMovedToKeyMods = ImGuiMod_None;
NavJustMovedToIsTabbing = false;
NavJustMovedToHasSelectionData = false;
// All platforms use Ctrl+Tab but Ctrl<>Super are swapped on Mac... // All platforms use Ctrl+Tab but Ctrl<>Super are swapped on Mac...
// FIXME: Because this value is stored, it annoyingly interfere with toggling io.ConfigMacOSXBehaviors updating this.. // FIXME: Because this value is stored, it annoyingly interfere with toggling io.ConfigMacOSXBehaviors updating this..
ConfigNavWindowingKeyNext = IO.ConfigMacOSXBehaviors ? (ImGuiMod_Super | ImGuiKey_Tab) : (ImGuiMod_Ctrl | ImGuiKey_Tab); ConfigNavWindowingKeyNext = IO.ConfigMacOSXBehaviors ? (ImGuiMod_Super | ImGuiKey_Tab) : (ImGuiMod_Ctrl | ImGuiKey_Tab);
@ -2368,6 +2469,8 @@ struct ImGuiContext
CurrentTable = NULL; CurrentTable = NULL;
TablesTempDataStacked = 0; TablesTempDataStacked = 0;
CurrentTabBar = NULL; CurrentTabBar = NULL;
CurrentMultiSelect = NULL;
MultiSelectTempDataStacked = 0;
HoverItemDelayId = HoverItemDelayIdPreviousFrame = HoverItemUnlockedStationaryId = HoverWindowUnlockedStationaryId = 0; HoverItemDelayId = HoverItemDelayIdPreviousFrame = HoverItemUnlockedStationaryId = HoverWindowUnlockedStationaryId = 0;
HoverItemDelayTimer = HoverItemDelayClearTimer = 0.0f; HoverItemDelayTimer = HoverItemDelayClearTimer = 0.0f;
@ -2376,6 +2479,7 @@ struct ImGuiContext
MouseStationaryTimer = 0.0f; MouseStationaryTimer = 0.0f;
TempInputId = 0; TempInputId = 0;
memset(&DataTypeZeroValue, 0, sizeof(DataTypeZeroValue));
BeginMenuDepth = BeginComboDepth = 0; BeginMenuDepth = BeginComboDepth = 0;
ColorEditOptions = ImGuiColorEditFlags_DefaultOptions_; ColorEditOptions = ImGuiColorEditFlags_DefaultOptions_;
ColorEditCurrentID = ColorEditSavedID = 0; ColorEditCurrentID = ColorEditSavedID = 0;
@ -2479,7 +2583,7 @@ struct IMGUI_API ImGuiWindowTempData
ImVec2 MenuBarOffset; // MenuBarOffset.x is sort of equivalent of a per-layer CursorPos.x, saved/restored as we switch to the menu bar. The only situation when MenuBarOffset.y is > 0 if when (SafeAreaPadding.y > FramePadding.y), often used on TVs. ImVec2 MenuBarOffset; // MenuBarOffset.x is sort of equivalent of a per-layer CursorPos.x, saved/restored as we switch to the menu bar. The only situation when MenuBarOffset.y is > 0 if when (SafeAreaPadding.y > FramePadding.y), often used on TVs.
ImGuiMenuColumns MenuColumns; // Simplified columns storage for menu items measurement ImGuiMenuColumns MenuColumns; // Simplified columns storage for menu items measurement
int TreeDepth; // Current tree depth. int TreeDepth; // Current tree depth.
ImU32 TreeJumpToParentOnPopMask; // Store a copy of !g.NavIdIsAlive for TreeDepth 0..31.. Could be turned into a ImU64 if necessary. ImU32 TreeHasStackDataDepthMask; // Store whether given depth has ImGuiTreeNodeStackData data. Could be turned into a ImU64 if necessary.
ImVector<ImGuiWindow*> ChildWindows; ImVector<ImGuiWindow*> ChildWindows;
ImGuiStorage* StateStorage; // Current persistent per-window storage (store e.g. tree node open/close state) ImGuiStorage* StateStorage; // Current persistent per-window storage (store e.g. tree node open/close state)
ImGuiOldColumns* CurrentColumns; // Current columns set ImGuiOldColumns* CurrentColumns; // Current columns set
@ -2514,7 +2618,7 @@ struct IMGUI_API ImGuiWindow
ImVec2 WindowPadding; // Window padding at the time of Begin(). ImVec2 WindowPadding; // Window padding at the time of Begin().
float WindowRounding; // Window rounding at the time of Begin(). May be clamped lower to avoid rendering artifacts with title bar, menu bar etc. float WindowRounding; // Window rounding at the time of Begin(). May be clamped lower to avoid rendering artifacts with title bar, menu bar etc.
float WindowBorderSize; // Window border size at the time of Begin(). float WindowBorderSize; // Window border size at the time of Begin().
float TitleBarHeight, MenuBarHeight; float TitleBarHeight, MenuBarHeight; // Note that those used to be function before 2024/05/28. If you have old code calling TitleBarHeight() you can change it to TitleBarHeight.
float DecoOuterSizeX1, DecoOuterSizeY1; // Left/Up offsets. Sum of non-scrolling outer decorations (X1 generally == 0.0f. Y1 generally = TitleBarHeight + MenuBarHeight). Locked during Begin(). float DecoOuterSizeX1, DecoOuterSizeY1; // Left/Up offsets. Sum of non-scrolling outer decorations (X1 generally == 0.0f. Y1 generally = TitleBarHeight + MenuBarHeight). Locked during Begin().
float DecoOuterSizeX2, DecoOuterSizeY2; // Right/Down offsets (X2 generally == ScrollbarSize.x, Y2 == ScrollbarSizes.y). float DecoOuterSizeX2, DecoOuterSizeY2; // Right/Down offsets (X2 generally == ScrollbarSize.x, Y2 == ScrollbarSizes.y).
float DecoInnerSizeX1, DecoInnerSizeY1; // Applied AFTER/OVER InnerRect. Specialized for Tables as they use specialized form of clipping and frozen rows/columns are inside InnerRect (and not part of regular decoration sizes). float DecoInnerSizeX1, DecoInnerSizeY1; // Applied AFTER/OVER InnerRect. Specialized for Tables as they use specialized form of clipping and frozen rows/columns are inside InnerRect (and not part of regular decoration sizes).
@ -2611,6 +2715,7 @@ public:
ImGuiID GetID(const char* str, const char* str_end = NULL); ImGuiID GetID(const char* str, const char* str_end = NULL);
ImGuiID GetID(const void* ptr); ImGuiID GetID(const void* ptr);
ImGuiID GetID(int n); ImGuiID GetID(int n);
ImGuiID GetIDFromPos(const ImVec2& p_abs);
ImGuiID GetIDFromRectangle(const ImRect& r_abs); ImGuiID GetIDFromRectangle(const ImRect& r_abs);
// We don't use g.FontSize because the window may be != g.CurrentWindow. // We don't use g.FontSize because the window may be != g.CurrentWindow.
@ -2722,6 +2827,7 @@ struct ImGuiTableColumn
float MaxX; float MaxX;
float WidthRequest; // Master width absolute value when !(Flags & _WidthStretch). When Stretch this is derived every frame from StretchWeight in TableUpdateLayout() float WidthRequest; // Master width absolute value when !(Flags & _WidthStretch). When Stretch this is derived every frame from StretchWeight in TableUpdateLayout()
float WidthAuto; // Automatic width float WidthAuto; // Automatic width
float WidthMax; // Maximum width (FIXME: overwritten by each instance)
float StretchWeight; // Master width weight when (Flags & _WidthStretch). Often around ~1.0f initially. float StretchWeight; // Master width weight when (Flags & _WidthStretch). Often around ~1.0f initially.
float InitStretchWeightOrWidth; // Value passed to TableSetupColumn(). For Width it is a content width (_without padding_). float InitStretchWeightOrWidth; // Value passed to TableSetupColumn(). For Width it is a content width (_without padding_).
ImRect ClipRect; // Clipping rectangle for the column ImRect ClipRect; // Clipping rectangle for the column
@ -3020,6 +3126,7 @@ namespace ImGui
inline void SetWindowParentWindowForFocusRoute(ImGuiWindow* window, ImGuiWindow* parent_window) { window->ParentWindowForFocusRoute = parent_window; } inline void SetWindowParentWindowForFocusRoute(ImGuiWindow* window, ImGuiWindow* parent_window) { window->ParentWindowForFocusRoute = parent_window; }
inline ImRect WindowRectAbsToRel(ImGuiWindow* window, const ImRect& r) { ImVec2 off = window->DC.CursorStartPos; return ImRect(r.Min.x - off.x, r.Min.y - off.y, r.Max.x - off.x, r.Max.y - off.y); } inline ImRect WindowRectAbsToRel(ImGuiWindow* window, const ImRect& r) { ImVec2 off = window->DC.CursorStartPos; return ImRect(r.Min.x - off.x, r.Min.y - off.y, r.Max.x - off.x, r.Max.y - off.y); }
inline ImRect WindowRectRelToAbs(ImGuiWindow* window, const ImRect& r) { ImVec2 off = window->DC.CursorStartPos; return ImRect(r.Min.x + off.x, r.Min.y + off.y, r.Max.x + off.x, r.Max.y + off.y); } inline ImRect WindowRectRelToAbs(ImGuiWindow* window, const ImRect& r) { ImVec2 off = window->DC.CursorStartPos; return ImRect(r.Min.x + off.x, r.Min.y + off.y, r.Max.x + off.x, r.Max.y + off.y); }
inline ImVec2 WindowPosAbsToRel(ImGuiWindow* window, const ImVec2& p) { ImVec2 off = window->DC.CursorStartPos; return ImVec2(p.x - off.x, p.y - off.y); }
inline ImVec2 WindowPosRelToAbs(ImGuiWindow* window, const ImVec2& p) { ImVec2 off = window->DC.CursorStartPos; return ImVec2(p.x + off.x, p.y + off.y); } inline ImVec2 WindowPosRelToAbs(ImGuiWindow* window, const ImVec2& p) { ImVec2 off = window->DC.CursorStartPos; return ImVec2(p.x + off.x, p.y + off.y); }
// Windows: Display Order and Focus Order // Windows: Display Order and Focus Order
@ -3096,7 +3203,7 @@ namespace ImGui
//#endif //#endif
// Basic Accessors // Basic Accessors
inline ImGuiItemStatusFlags GetItemStatusFlags(){ ImGuiContext& g = *GImGui; return g.LastItemData.StatusFlags; } inline ImGuiItemStatusFlags GetItemStatusFlags() { ImGuiContext& g = *GImGui; return g.LastItemData.StatusFlags; }
inline ImGuiItemFlags GetItemFlags() { ImGuiContext& g = *GImGui; return g.LastItemData.InFlags; } inline ImGuiItemFlags GetItemFlags() { ImGuiContext& g = *GImGui; return g.LastItemData.InFlags; }
inline ImGuiID GetActiveID() { ImGuiContext& g = *GImGui; return g.ActiveId; } inline ImGuiID GetActiveID() { ImGuiContext& g = *GImGui; return g.ActiveId; }
inline ImGuiID GetFocusID() { ImGuiContext& g = *GImGui; return g.NavId; } inline ImGuiID GetFocusID() { ImGuiContext& g = *GImGui; return g.NavId; }
@ -3122,13 +3229,9 @@ namespace ImGui
IMGUI_API ImVec2 CalcItemSize(ImVec2 size, float default_w, float default_h); IMGUI_API ImVec2 CalcItemSize(ImVec2 size, float default_w, float default_h);
IMGUI_API float CalcWrapWidthForPos(const ImVec2& pos, float wrap_pos_x); IMGUI_API float CalcWrapWidthForPos(const ImVec2& pos, float wrap_pos_x);
IMGUI_API void PushMultiItemsWidths(int components, float width_full); IMGUI_API void PushMultiItemsWidths(int components, float width_full);
IMGUI_API bool IsItemToggledSelection(); // Was the last item selection toggled? (after Selectable(), TreeNode() etc. We only returns toggle _event_ in order to handle clipping correctly)
IMGUI_API ImVec2 GetContentRegionMaxAbs();
IMGUI_API void ShrinkWidths(ImGuiShrinkWidthItem* items, int count, float width_excess); IMGUI_API void ShrinkWidths(ImGuiShrinkWidthItem* items, int count, float width_excess);
// Parameter stacks (shared) // Parameter stacks (shared)
IMGUI_API void PushItemFlag(ImGuiItemFlags option, bool enabled);
IMGUI_API void PopItemFlag();
IMGUI_API const ImGuiDataVarInfo* GetStyleVarInfo(ImGuiStyleVar idx); IMGUI_API const ImGuiDataVarInfo* GetStyleVarInfo(ImGuiStyleVar idx);
IMGUI_API void BeginDisabledOverrideReenable(); IMGUI_API void BeginDisabledOverrideReenable();
IMGUI_API void EndDisabledOverrideReenable(); IMGUI_API void EndDisabledOverrideReenable();
@ -3139,16 +3242,16 @@ namespace ImGui
IMGUI_API void LogRenderedText(const ImVec2* ref_pos, const char* text, const char* text_end = NULL); IMGUI_API void LogRenderedText(const ImVec2* ref_pos, const char* text, const char* text_end = NULL);
IMGUI_API void LogSetNextTextDecoration(const char* prefix, const char* suffix); IMGUI_API void LogSetNextTextDecoration(const char* prefix, const char* suffix);
// Popups, Modals, Tooltips // Childs
IMGUI_API bool BeginChildEx(const char* name, ImGuiID id, const ImVec2& size_arg, ImGuiChildFlags child_flags, ImGuiWindowFlags window_flags); IMGUI_API bool BeginChildEx(const char* name, ImGuiID id, const ImVec2& size_arg, ImGuiChildFlags child_flags, ImGuiWindowFlags window_flags);
// Popups, Modals
IMGUI_API bool BeginPopupEx(ImGuiID id, ImGuiWindowFlags extra_window_flags);
IMGUI_API void OpenPopupEx(ImGuiID id, ImGuiPopupFlags popup_flags = ImGuiPopupFlags_None); IMGUI_API void OpenPopupEx(ImGuiID id, ImGuiPopupFlags popup_flags = ImGuiPopupFlags_None);
IMGUI_API void ClosePopupToLevel(int remaining, bool restore_focus_to_window_under_popup); 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); IMGUI_API void ClosePopupsOverWindow(ImGuiWindow* ref_window, bool restore_focus_to_window_under_popup);
IMGUI_API void ClosePopupsExceptModals(); IMGUI_API void ClosePopupsExceptModals();
IMGUI_API bool IsPopupOpen(ImGuiID id, ImGuiPopupFlags popup_flags); IMGUI_API bool IsPopupOpen(ImGuiID id, ImGuiPopupFlags popup_flags);
IMGUI_API bool BeginPopupEx(ImGuiID id, ImGuiWindowFlags extra_flags);
IMGUI_API bool BeginTooltipEx(ImGuiTooltipFlags tooltip_flags, ImGuiWindowFlags extra_window_flags);
IMGUI_API bool BeginTooltipHidden();
IMGUI_API ImRect GetPopupAllowedExtentRect(ImGuiWindow* window); IMGUI_API ImRect GetPopupAllowedExtentRect(ImGuiWindow* window);
IMGUI_API ImGuiWindow* GetTopMostPopupModal(); IMGUI_API ImGuiWindow* GetTopMostPopupModal();
IMGUI_API ImGuiWindow* GetTopMostAndVisiblePopupModal(); IMGUI_API ImGuiWindow* GetTopMostAndVisiblePopupModal();
@ -3156,6 +3259,10 @@ namespace ImGui
IMGUI_API ImVec2 FindBestWindowPosForPopup(ImGuiWindow* window); IMGUI_API ImVec2 FindBestWindowPosForPopup(ImGuiWindow* window);
IMGUI_API ImVec2 FindBestWindowPosForPopupEx(const ImVec2& ref_pos, const ImVec2& size, ImGuiDir* last_dir, const ImRect& r_outer, const ImRect& r_avoid, ImGuiPopupPositionPolicy policy); IMGUI_API ImVec2 FindBestWindowPosForPopupEx(const ImVec2& ref_pos, const ImVec2& size, ImGuiDir* last_dir, const ImRect& r_outer, const ImRect& r_avoid, ImGuiPopupPositionPolicy policy);
// Tooltips
IMGUI_API bool BeginTooltipEx(ImGuiTooltipFlags tooltip_flags, ImGuiWindowFlags extra_window_flags);
IMGUI_API bool BeginTooltipHidden();
// Menus // Menus
IMGUI_API bool BeginViewportSideBar(const char* name, ImGuiViewport* viewport, ImGuiDir dir, float size, ImGuiWindowFlags window_flags); IMGUI_API bool BeginViewportSideBar(const char* name, ImGuiViewport* viewport, ImGuiDir dir, float size, ImGuiWindowFlags window_flags);
IMGUI_API bool BeginMenuEx(const char* label, const char* icon, bool enabled = true); IMGUI_API bool BeginMenuEx(const char* label, const char* icon, bool enabled = true);
@ -3173,7 +3280,7 @@ namespace ImGui
IMGUI_API void NavMoveRequestSubmit(ImGuiDir move_dir, ImGuiDir clip_dir, ImGuiNavMoveFlags move_flags, ImGuiScrollFlags scroll_flags); IMGUI_API void NavMoveRequestSubmit(ImGuiDir move_dir, ImGuiDir clip_dir, ImGuiNavMoveFlags move_flags, ImGuiScrollFlags scroll_flags);
IMGUI_API void NavMoveRequestForward(ImGuiDir move_dir, ImGuiDir clip_dir, ImGuiNavMoveFlags move_flags, ImGuiScrollFlags scroll_flags); IMGUI_API void NavMoveRequestForward(ImGuiDir move_dir, ImGuiDir clip_dir, ImGuiNavMoveFlags move_flags, ImGuiScrollFlags scroll_flags);
IMGUI_API void NavMoveRequestResolveWithLastItem(ImGuiNavItemData* result); IMGUI_API void NavMoveRequestResolveWithLastItem(ImGuiNavItemData* result);
IMGUI_API void NavMoveRequestResolveWithPastTreeNode(ImGuiNavItemData* result, ImGuiNavTreeNodeData* tree_node_data); IMGUI_API void NavMoveRequestResolveWithPastTreeNode(ImGuiNavItemData* result, ImGuiTreeNodeStackData* tree_node_data);
IMGUI_API void NavMoveRequestCancel(); IMGUI_API void NavMoveRequestCancel();
IMGUI_API void NavMoveRequestApplyResult(); IMGUI_API void NavMoveRequestApplyResult();
IMGUI_API void NavMoveRequestTryWrapping(ImGuiWindow* window, ImGuiNavMoveFlags move_flags); IMGUI_API void NavMoveRequestTryWrapping(ImGuiWindow* window, ImGuiNavMoveFlags move_flags);
@ -3200,7 +3307,7 @@ namespace ImGui
inline bool IsGamepadKey(ImGuiKey key) { return key >= ImGuiKey_Gamepad_BEGIN && key < ImGuiKey_Gamepad_END; } inline bool IsGamepadKey(ImGuiKey key) { return key >= ImGuiKey_Gamepad_BEGIN && key < ImGuiKey_Gamepad_END; }
inline bool IsMouseKey(ImGuiKey key) { return key >= ImGuiKey_Mouse_BEGIN && key < ImGuiKey_Mouse_END; } inline bool IsMouseKey(ImGuiKey key) { return key >= ImGuiKey_Mouse_BEGIN && key < ImGuiKey_Mouse_END; }
inline bool IsAliasKey(ImGuiKey key) { return key >= ImGuiKey_Aliases_BEGIN && key < ImGuiKey_Aliases_END; } inline bool IsAliasKey(ImGuiKey key) { return key >= ImGuiKey_Aliases_BEGIN && key < ImGuiKey_Aliases_END; }
inline bool IsModKey(ImGuiKey key) { return key >= ImGuiKey_LeftCtrl && key <= ImGuiKey_RightSuper; } inline bool IsLRModKey(ImGuiKey key) { return key >= ImGuiKey_LeftCtrl && key <= ImGuiKey_RightSuper; }
ImGuiKeyChord FixupKeyChord(ImGuiKeyChord key_chord); ImGuiKeyChord FixupKeyChord(ImGuiKeyChord key_chord);
inline ImGuiKey ConvertSingleModFlagToKey(ImGuiKey key) inline ImGuiKey ConvertSingleModFlagToKey(ImGuiKey key)
{ {
@ -3238,7 +3345,7 @@ namespace ImGui
IMGUI_API ImGuiID GetKeyOwner(ImGuiKey key); IMGUI_API ImGuiID GetKeyOwner(ImGuiKey key);
IMGUI_API void SetKeyOwner(ImGuiKey key, ImGuiID owner_id, ImGuiInputFlags flags = 0); IMGUI_API void SetKeyOwner(ImGuiKey key, ImGuiID owner_id, ImGuiInputFlags flags = 0);
IMGUI_API void SetKeyOwnersForKeyChord(ImGuiKeyChord key, ImGuiID owner_id, ImGuiInputFlags flags = 0); IMGUI_API void SetKeyOwnersForKeyChord(ImGuiKeyChord key, ImGuiID owner_id, ImGuiInputFlags flags = 0);
IMGUI_API void SetItemKeyOwner(ImGuiKey key, ImGuiInputFlags flags = 0); // Set key owner to last item if it is hovered or active. Equivalent to 'if (IsItemHovered() || IsItemActive()) { SetKeyOwner(key, GetItemID());'. IMGUI_API void SetItemKeyOwner(ImGuiKey key, ImGuiInputFlags flags); // Set key owner to last item if it is hovered or active. Equivalent to 'if (IsItemHovered() || IsItemActive()) { SetKeyOwner(key, GetItemID());'.
IMGUI_API bool TestKeyOwner(ImGuiKey key, ImGuiID owner_id); // Test that key is either not owned, either owned by 'owner_id' IMGUI_API bool TestKeyOwner(ImGuiKey key, ImGuiID owner_id); // Test that key is either not owned, either owned by 'owner_id'
inline ImGuiKeyOwnerData* GetKeyOwnerData(ImGuiContext* ctx, ImGuiKey key) { if (key & ImGuiMod_Mask_) key = ConvertSingleModFlagToKey(key); IM_ASSERT(IsNamedKey(key)); return &ctx->KeysOwnerData[key - ImGuiKey_NamedKey_BEGIN]; } inline ImGuiKeyOwnerData* GetKeyOwnerData(ImGuiContext* ctx, ImGuiKey key) { if (key & ImGuiMod_Mask_) key = ConvertSingleModFlagToKey(key); IM_ASSERT(IsNamedKey(key)); return &ctx->KeysOwnerData[key - ImGuiKey_NamedKey_BEGIN]; }
@ -3301,6 +3408,18 @@ namespace ImGui
IMGUI_API int TypingSelectFindNextSingleCharMatch(ImGuiTypingSelectRequest* req, int items_count, const char* (*get_item_name_func)(void*, int), void* user_data, int nav_item_idx); IMGUI_API int TypingSelectFindNextSingleCharMatch(ImGuiTypingSelectRequest* req, int items_count, const char* (*get_item_name_func)(void*, int), void* user_data, int nav_item_idx);
IMGUI_API int TypingSelectFindBestLeadingMatch(ImGuiTypingSelectRequest* req, int items_count, const char* (*get_item_name_func)(void*, int), void* user_data); IMGUI_API int TypingSelectFindBestLeadingMatch(ImGuiTypingSelectRequest* req, int items_count, const char* (*get_item_name_func)(void*, int), void* user_data);
// Box-Select API
IMGUI_API bool BeginBoxSelect(const ImRect& scope_rect, ImGuiWindow* window, ImGuiID box_select_id, ImGuiMultiSelectFlags ms_flags);
IMGUI_API void EndBoxSelect(const ImRect& scope_rect, ImGuiMultiSelectFlags ms_flags);
// Multi-Select API
IMGUI_API void MultiSelectItemHeader(ImGuiID id, bool* p_selected, ImGuiButtonFlags* p_button_flags);
IMGUI_API void MultiSelectItemFooter(ImGuiID id, bool* p_selected, bool* p_pressed);
IMGUI_API void MultiSelectAddSetAll(ImGuiMultiSelectTempData* ms, bool selected);
IMGUI_API void MultiSelectAddSetRange(ImGuiMultiSelectTempData* ms, bool selected, int range_dir, ImGuiSelectionUserData first_item, ImGuiSelectionUserData last_item);
inline ImGuiBoxSelectState* GetBoxSelectState(ImGuiID id) { ImGuiContext& g = *GImGui; return (id != 0 && g.BoxSelectState.ID == id && g.BoxSelectState.IsActive) ? &g.BoxSelectState : NULL; }
inline ImGuiMultiSelectState* GetMultiSelectState(ImGuiID id) { ImGuiContext& g = *GImGui; return g.MultiSelectStorage.GetByKey(id); }
// Internal Columns API (this is not exposed because we will encourage transitioning to the Tables API) // Internal Columns API (this is not exposed because we will encourage transitioning to the Tables API)
IMGUI_API void SetWindowClipRectBeforeSetChannel(ImGuiWindow* window, const ImRect& clip_rect); IMGUI_API void SetWindowClipRectBeforeSetChannel(ImGuiWindow* window, const ImRect& clip_rect);
IMGUI_API void BeginColumns(const char* str_id, int count, ImGuiOldColumnFlags flags = 0); // setup number of columns. use an identifier to distinguish multiple column sets. close with EndColumns(). IMGUI_API void BeginColumns(const char* str_id, int count, ImGuiOldColumnFlags flags = 0); // setup number of columns. use an identifier to distinguish multiple column sets. close with EndColumns().
@ -3317,7 +3436,6 @@ namespace ImGui
IMGUI_API void TableOpenContextMenu(int column_n = -1); IMGUI_API void TableOpenContextMenu(int column_n = -1);
IMGUI_API void TableSetColumnWidth(int column_n, float width); IMGUI_API void TableSetColumnWidth(int column_n, float width);
IMGUI_API void TableSetColumnSortDirection(int column_n, ImGuiSortDirection sort_direction, bool append_to_sort_specs); IMGUI_API void TableSetColumnSortDirection(int column_n, ImGuiSortDirection sort_direction, bool append_to_sort_specs);
IMGUI_API int TableGetHoveredColumn(); // May use (TableGetColumnFlags() & ImGuiTableColumnFlags_IsHovered) instead. Return hovered column. return -1 when table is not hovered. return columns_count if the unused space at the right of visible columns is hovered.
IMGUI_API int TableGetHoveredRow(); // Retrieve *PREVIOUS FRAME* hovered row. This difference with TableGetHoveredColumn() is the reason why this is not public yet. IMGUI_API int TableGetHoveredRow(); // Retrieve *PREVIOUS FRAME* hovered row. This difference with TableGetHoveredColumn() is the reason why this is not public yet.
IMGUI_API float TableGetHeaderRowHeight(); IMGUI_API float TableGetHeaderRowHeight();
IMGUI_API float TableGetHeaderAngledMaxLabelWidth(); IMGUI_API float TableGetHeaderAngledMaxLabelWidth();
@ -3353,7 +3471,7 @@ namespace ImGui
IMGUI_API ImRect TableGetCellBgRect(const ImGuiTable* table, int column_n); IMGUI_API ImRect TableGetCellBgRect(const ImGuiTable* table, int column_n);
IMGUI_API const char* TableGetColumnName(const ImGuiTable* table, int column_n); IMGUI_API const char* TableGetColumnName(const ImGuiTable* table, int column_n);
IMGUI_API ImGuiID TableGetColumnResizeID(ImGuiTable* table, int column_n, int instance_no = 0); IMGUI_API ImGuiID TableGetColumnResizeID(ImGuiTable* table, int column_n, int instance_no = 0);
IMGUI_API float TableGetMaxColumnWidth(const ImGuiTable* table, int column_n); IMGUI_API float TableCalcMaxColumnWidth(const ImGuiTable* table, int column_n);
IMGUI_API void TableSetColumnWidthAutoSingle(ImGuiTable* table, int column_n); IMGUI_API void TableSetColumnWidthAutoSingle(ImGuiTable* table, int column_n);
IMGUI_API void TableSetColumnWidthAutoAll(ImGuiTable* table); IMGUI_API void TableSetColumnWidthAutoAll(ImGuiTable* table);
IMGUI_API void TableRemove(ImGuiTable* table); IMGUI_API void TableRemove(ImGuiTable* table);
@ -3398,7 +3516,7 @@ namespace ImGui
IMGUI_API void RenderTextClipped(const ImVec2& pos_min, const ImVec2& pos_max, const char* text, const char* text_end, const ImVec2* text_size_if_known, const ImVec2& align = ImVec2(0, 0), const ImRect* clip_rect = NULL); IMGUI_API void RenderTextClipped(const ImVec2& pos_min, const ImVec2& pos_max, const char* text, const char* text_end, const ImVec2* text_size_if_known, const ImVec2& align = ImVec2(0, 0), const ImRect* clip_rect = NULL);
IMGUI_API void RenderTextClippedEx(ImDrawList* draw_list, const ImVec2& pos_min, const ImVec2& pos_max, const char* text, const char* text_end, const ImVec2* text_size_if_known, const ImVec2& align = ImVec2(0, 0), const ImRect* clip_rect = NULL); IMGUI_API void RenderTextClippedEx(ImDrawList* draw_list, const ImVec2& pos_min, const ImVec2& pos_max, const char* text, const char* text_end, const ImVec2* text_size_if_known, const ImVec2& align = ImVec2(0, 0), const ImRect* clip_rect = NULL);
IMGUI_API void RenderTextEllipsis(ImDrawList* draw_list, const ImVec2& pos_min, const ImVec2& pos_max, float clip_max_x, float ellipsis_max_x, const char* text, const char* text_end, const ImVec2* text_size_if_known); IMGUI_API void RenderTextEllipsis(ImDrawList* draw_list, const ImVec2& pos_min, const ImVec2& pos_max, float clip_max_x, float ellipsis_max_x, const char* text, const char* text_end, const ImVec2* text_size_if_known);
IMGUI_API void RenderFrame(ImVec2 p_min, ImVec2 p_max, ImU32 fill_col, bool border = true, float rounding = 0.0f); IMGUI_API void RenderFrame(ImVec2 p_min, ImVec2 p_max, ImU32 fill_col, bool borders = true, float rounding = 0.0f);
IMGUI_API void RenderFrameBorder(ImVec2 p_min, ImVec2 p_max, float rounding = 0.0f); IMGUI_API void RenderFrameBorder(ImVec2 p_min, ImVec2 p_max, float rounding = 0.0f);
IMGUI_API void RenderColorRectWithAlphaCheckerboard(ImDrawList* draw_list, ImVec2 p_min, ImVec2 p_max, ImU32 fill_col, float grid_step, ImVec2 grid_off, float rounding = 0.0f, ImDrawFlags flags = 0); IMGUI_API void RenderColorRectWithAlphaCheckerboard(ImDrawList* draw_list, ImVec2 p_min, ImVec2 p_max, ImU32 fill_col, float grid_step, ImVec2 grid_off, float rounding = 0.0f, ImDrawFlags flags = 0);
IMGUI_API void RenderNavHighlight(const ImRect& bb, ImGuiID id, ImGuiNavHighlightFlags flags = ImGuiNavHighlightFlags_None); // Navigation highlight IMGUI_API void RenderNavHighlight(const ImRect& bb, ImGuiID id, ImGuiNavHighlightFlags flags = ImGuiNavHighlightFlags_None); // Navigation highlight
@ -3438,11 +3556,13 @@ namespace ImGui
IMGUI_API bool DragBehavior(ImGuiID id, ImGuiDataType data_type, void* p_v, float v_speed, const void* p_min, const void* p_max, const char* format, ImGuiSliderFlags flags); IMGUI_API bool DragBehavior(ImGuiID id, ImGuiDataType data_type, void* p_v, float v_speed, const void* p_min, const void* p_max, const char* format, ImGuiSliderFlags flags);
IMGUI_API bool SliderBehavior(const ImRect& bb, ImGuiID id, ImGuiDataType data_type, void* p_v, const void* p_min, const void* p_max, const char* format, ImGuiSliderFlags flags, ImRect* out_grab_bb); IMGUI_API bool SliderBehavior(const ImRect& bb, ImGuiID id, ImGuiDataType data_type, void* p_v, const void* p_min, const void* p_max, const char* format, ImGuiSliderFlags flags, ImRect* out_grab_bb);
IMGUI_API bool SplitterBehavior(const ImRect& bb, ImGuiID id, ImGuiAxis axis, float* size1, float* size2, float min_size1, float min_size2, float hover_extend = 0.0f, float hover_visibility_delay = 0.0f, ImU32 bg_col = 0); IMGUI_API bool SplitterBehavior(const ImRect& bb, ImGuiID id, ImGuiAxis axis, float* size1, float* size2, float min_size1, float min_size2, float hover_extend = 0.0f, float hover_visibility_delay = 0.0f, ImU32 bg_col = 0);
// Widgets: Tree Nodes
IMGUI_API bool TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* label, const char* label_end = NULL); IMGUI_API bool TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* label, const char* label_end = NULL);
IMGUI_API void TreePushOverrideID(ImGuiID id); IMGUI_API void TreePushOverrideID(ImGuiID id);
IMGUI_API void TreeNodeSetOpen(ImGuiID id, bool open); IMGUI_API bool TreeNodeGetOpen(ImGuiID storage_id);
IMGUI_API bool TreeNodeUpdateNextOpen(ImGuiID id, ImGuiTreeNodeFlags flags); // Return open state. Consume previous SetNextItemOpen() data, if any. May return true when logging. IMGUI_API void TreeNodeSetOpen(ImGuiID storage_id, bool open);
IMGUI_API void SetNextItemSelectionUserData(ImGuiSelectionUserData selection_user_data); IMGUI_API bool TreeNodeUpdateNextOpen(ImGuiID storage_id, ImGuiTreeNodeFlags flags); // Return open state. Consume previous SetNextItemOpen() data, if any. May return true when logging.
// Template functions are instantiated in imgui_widgets.cpp for a finite number of types. // Template functions are instantiated in imgui_widgets.cpp for a finite number of types.
// To use them externally (for custom widget) you may need an "extern template" statement in your code in order to link to existing instances and silence Clang warnings (see #2036). // To use them externally (for custom widget) you may need an "extern template" statement in your code in order to link to existing instances and silence Clang warnings (see #2036).
@ -3458,7 +3578,7 @@ namespace ImGui
IMGUI_API const ImGuiDataTypeInfo* DataTypeGetInfo(ImGuiDataType data_type); IMGUI_API const ImGuiDataTypeInfo* DataTypeGetInfo(ImGuiDataType data_type);
IMGUI_API int DataTypeFormatString(char* buf, int buf_size, ImGuiDataType data_type, const void* p_data, const char* format); IMGUI_API int DataTypeFormatString(char* buf, int buf_size, ImGuiDataType data_type, const void* p_data, const char* format);
IMGUI_API void DataTypeApplyOp(ImGuiDataType data_type, int op, void* output, const void* arg_1, const void* arg_2); IMGUI_API void DataTypeApplyOp(ImGuiDataType data_type, int op, void* output, const void* arg_1, const void* arg_2);
IMGUI_API bool DataTypeApplyFromText(const char* buf, ImGuiDataType data_type, void* p_data, const char* format); IMGUI_API bool DataTypeApplyFromText(const char* buf, ImGuiDataType data_type, void* p_data, const char* format, void* p_data_when_empty = NULL);
IMGUI_API int DataTypeCompare(ImGuiDataType data_type, const void* arg_1, const void* arg_2); IMGUI_API int DataTypeCompare(ImGuiDataType data_type, const void* arg_1, const void* arg_2);
IMGUI_API bool DataTypeClamp(ImGuiDataType data_type, void* p_data, const void* p_min, const void* p_max); IMGUI_API bool DataTypeClamp(ImGuiDataType data_type, void* p_data, const void* p_min, const void* p_max);
@ -3469,6 +3589,7 @@ namespace ImGui
IMGUI_API bool TempInputScalar(const ImRect& bb, ImGuiID id, const char* label, ImGuiDataType data_type, void* p_data, const char* format, const void* p_clamp_min = NULL, const void* p_clamp_max = NULL); IMGUI_API bool TempInputScalar(const ImRect& bb, ImGuiID id, const char* label, ImGuiDataType data_type, void* p_data, const char* format, const void* p_clamp_min = NULL, const void* p_clamp_max = NULL);
inline bool TempInputIsActive(ImGuiID id) { ImGuiContext& g = *GImGui; return (g.ActiveId == id && g.TempInputId == id); } inline bool TempInputIsActive(ImGuiID id) { ImGuiContext& g = *GImGui; return (g.ActiveId == id && g.TempInputId == id); }
inline ImGuiInputTextState* GetInputTextState(ImGuiID id) { ImGuiContext& g = *GImGui; return (id != 0 && g.InputTextState.ID == id) ? &g.InputTextState : NULL; } // Get input text state if active inline ImGuiInputTextState* GetInputTextState(ImGuiID id) { ImGuiContext& g = *GImGui; return (id != 0 && g.InputTextState.ID == id) ? &g.InputTextState : NULL; } // Get input text state if active
IMGUI_API void SetNextItemRefVal(ImGuiDataType data_type, void* p_data);
// Color // Color
IMGUI_API void ColorTooltip(const char* text, const float* col, ImGuiColorEditFlags flags); IMGUI_API void ColorTooltip(const char* text, const float* col, ImGuiColorEditFlags flags);
@ -3488,12 +3609,8 @@ namespace ImGui
IMGUI_API void GcCompactTransientWindowBuffers(ImGuiWindow* window); IMGUI_API void GcCompactTransientWindowBuffers(ImGuiWindow* window);
IMGUI_API void GcAwakeTransientWindowBuffers(ImGuiWindow* window); IMGUI_API void GcAwakeTransientWindowBuffers(ImGuiWindow* window);
// Debug Log
IMGUI_API void DebugLog(const char* fmt, ...) IM_FMTARGS(1);
IMGUI_API void DebugLogV(const char* fmt, va_list args) IM_FMTLIST(1);
IMGUI_API void DebugAllocHook(ImGuiDebugAllocInfo* info, int frame_count, void* ptr, size_t size); // size >= 0 : alloc, size = -1 : free
// Debug Tools // Debug Tools
IMGUI_API void DebugAllocHook(ImGuiDebugAllocInfo* info, int frame_count, void* ptr, size_t size); // size >= 0 : alloc, size = -1 : free
IMGUI_API void ErrorCheckEndFrameRecover(ImGuiErrorLogCallback log_callback, void* user_data = NULL); IMGUI_API void ErrorCheckEndFrameRecover(ImGuiErrorLogCallback log_callback, void* user_data = NULL);
IMGUI_API void ErrorCheckEndWindowRecover(ImGuiErrorLogCallback log_callback, void* user_data = NULL); IMGUI_API void ErrorCheckEndWindowRecover(ImGuiErrorLogCallback log_callback, void* user_data = NULL);
IMGUI_API void ErrorCheckUsingSetCursorPosToExtendParentBoundaries(); IMGUI_API void ErrorCheckUsingSetCursorPosToExtendParentBoundaries();
@ -3520,6 +3637,7 @@ namespace ImGui
IMGUI_API void DebugNodeTableSettings(ImGuiTableSettings* settings); IMGUI_API void DebugNodeTableSettings(ImGuiTableSettings* settings);
IMGUI_API void DebugNodeInputTextState(ImGuiInputTextState* state); IMGUI_API void DebugNodeInputTextState(ImGuiInputTextState* state);
IMGUI_API void DebugNodeTypingSelectState(ImGuiTypingSelectState* state); IMGUI_API void DebugNodeTypingSelectState(ImGuiTypingSelectState* state);
IMGUI_API void DebugNodeMultiSelectState(ImGuiMultiSelectState* state);
IMGUI_API void DebugNodeWindow(ImGuiWindow* window, const char* label); IMGUI_API void DebugNodeWindow(ImGuiWindow* window, const char* label);
IMGUI_API void DebugNodeWindowSettings(ImGuiWindowSettings* settings); IMGUI_API void DebugNodeWindowSettings(ImGuiWindowSettings* settings);
IMGUI_API void DebugNodeWindowsList(ImVector<ImGuiWindow*>* windows, const char* label); IMGUI_API void DebugNodeWindowsList(ImVector<ImGuiWindow*>* windows, const char* label);

View file

@ -1,4 +1,4 @@
// dear imgui, v1.90.8 WIP // dear imgui, v1.91.1
// (tables and columns code) // (tables and columns code)
/* /*
@ -412,8 +412,8 @@ bool ImGui::BeginTableEx(const char* name, ImGuiID id, int columns_count, ImG
SetNextWindowScroll(ImVec2(0.0f, 0.0f)); SetNextWindowScroll(ImVec2(0.0f, 0.0f));
// Create scrolling region (without border and zero window padding) // Create scrolling region (without border and zero window padding)
ImGuiWindowFlags child_flags = (flags & ImGuiTableFlags_ScrollX) ? ImGuiWindowFlags_HorizontalScrollbar : ImGuiWindowFlags_None; ImGuiWindowFlags child_window_flags = (flags & ImGuiTableFlags_ScrollX) ? ImGuiWindowFlags_HorizontalScrollbar : ImGuiWindowFlags_None;
BeginChildEx(name, instance_id, outer_rect.GetSize(), false, child_flags); BeginChildEx(name, instance_id, outer_rect.GetSize(), ImGuiChildFlags_None, child_window_flags);
table->InnerWindow = g.CurrentWindow; table->InnerWindow = g.CurrentWindow;
table->WorkRect = table->InnerWindow->WorkRect; table->WorkRect = table->InnerWindow->WorkRect;
table->OuterRect = table->InnerWindow->Rect(); table->OuterRect = table->InnerWindow->Rect();
@ -460,16 +460,27 @@ bool ImGui::BeginTableEx(const char* name, ImGuiID id, int columns_count, ImG
temp_data->HostBackupItemWidthStackSize = outer_window->DC.ItemWidthStack.Size; temp_data->HostBackupItemWidthStackSize = outer_window->DC.ItemWidthStack.Size;
inner_window->DC.PrevLineSize = inner_window->DC.CurrLineSize = ImVec2(0.0f, 0.0f); inner_window->DC.PrevLineSize = inner_window->DC.CurrLineSize = ImVec2(0.0f, 0.0f);
// Make left and top borders not overlap our contents by offsetting HostClipRect (#6765) // Make borders not overlap our contents by offsetting HostClipRect (#6765, #7428, #3752)
// (we normally shouldn't alter HostClipRect as we rely on TableMergeDrawChannels() expanding non-clipped column toward the // (we normally shouldn't alter HostClipRect as we rely on TableMergeDrawChannels() expanding non-clipped column toward the
// limits of that rectangle, in order for ImDrawListSplitter::Merge() to merge the draw commands. However since the overlap // limits of that rectangle, in order for ImDrawListSplitter::Merge() to merge the draw commands. However since the overlap
// problem only affect scrolling tables in this case we can get away with doing it without extra cost). // problem only affect scrolling tables in this case we can get away with doing it without extra cost).
if (inner_window != outer_window) if (inner_window != outer_window)
{ {
// FIXME: Because inner_window's Scrollbar doesn't know about border size, since it's not encoded in window->WindowBorderSize,
// it already overlaps it and doesn't need an extra offset. Ideally we should be able to pass custom border size with
// different x/y values to BeginChild().
if (flags & ImGuiTableFlags_BordersOuterV) if (flags & ImGuiTableFlags_BordersOuterV)
{
table->HostClipRect.Min.x = ImMin(table->HostClipRect.Min.x + TABLE_BORDER_SIZE, table->HostClipRect.Max.x); table->HostClipRect.Min.x = ImMin(table->HostClipRect.Min.x + TABLE_BORDER_SIZE, table->HostClipRect.Max.x);
if (inner_window->DecoOuterSizeX2 == 0.0f)
table->HostClipRect.Max.x = ImMax(table->HostClipRect.Max.x - TABLE_BORDER_SIZE, table->HostClipRect.Min.x);
}
if (flags & ImGuiTableFlags_BordersOuterH) if (flags & ImGuiTableFlags_BordersOuterH)
{
table->HostClipRect.Min.y = ImMin(table->HostClipRect.Min.y + TABLE_BORDER_SIZE, table->HostClipRect.Max.y); table->HostClipRect.Min.y = ImMin(table->HostClipRect.Min.y + TABLE_BORDER_SIZE, table->HostClipRect.Max.y);
if (inner_window->DecoOuterSizeY2 == 0.0f)
table->HostClipRect.Max.y = ImMax(table->HostClipRect.Max.y - TABLE_BORDER_SIZE, table->HostClipRect.Min.y);
}
} }
// Padding and Spacing // Padding and Spacing
@ -497,7 +508,7 @@ bool ImGui::BeginTableEx(const char* name, ImGuiID id, int columns_count, ImG
table->InnerClipRect = (inner_window == outer_window) ? table->WorkRect : inner_window->ClipRect; table->InnerClipRect = (inner_window == outer_window) ? table->WorkRect : inner_window->ClipRect;
table->InnerClipRect.ClipWith(table->WorkRect); // We need this to honor inner_width table->InnerClipRect.ClipWith(table->WorkRect); // We need this to honor inner_width
table->InnerClipRect.ClipWithFull(table->HostClipRect); table->InnerClipRect.ClipWithFull(table->HostClipRect);
table->InnerClipRect.Max.y = (flags & ImGuiTableFlags_NoHostExtendY) ? ImMin(table->InnerClipRect.Max.y, inner_window->WorkRect.Max.y) : inner_window->ClipRect.Max.y; table->InnerClipRect.Max.y = (flags & ImGuiTableFlags_NoHostExtendY) ? ImMin(table->InnerClipRect.Max.y, inner_window->WorkRect.Max.y) : table->HostClipRect.Max.y;
table->RowPosY1 = table->RowPosY2 = table->WorkRect.Min.y; // This is needed somehow table->RowPosY1 = table->RowPosY2 = table->WorkRect.Min.y; // This is needed somehow
table->RowTextBaseline = 0.0f; // This will be cleared again by TableBeginRow() table->RowTextBaseline = 0.0f; // This will be cleared again by TableBeginRow()
@ -1059,16 +1070,12 @@ void ImGui::TableUpdateLayout(ImGuiTable* table)
continue; continue;
} }
// Detect hovered column
if (is_hovering_table && mouse_skewed_x >= column->ClipRect.Min.x && mouse_skewed_x < column->ClipRect.Max.x)
table->HoveredColumnBody = (ImGuiTableColumnIdx)column_n;
// Lock start position // Lock start position
column->MinX = offset_x; column->MinX = offset_x;
// Lock width based on start position and minimum/maximum width for this position // Lock width based on start position and minimum/maximum width for this position
float max_width = TableGetMaxColumnWidth(table, column_n); column->WidthMax = TableCalcMaxColumnWidth(table, column_n);
column->WidthGiven = ImMin(column->WidthGiven, max_width); column->WidthGiven = ImMin(column->WidthGiven, column->WidthMax);
column->WidthGiven = ImMax(column->WidthGiven, ImMin(column->WidthRequest, table->MinColumnWidth)); column->WidthGiven = ImMax(column->WidthGiven, ImMin(column->WidthRequest, table->MinColumnWidth));
column->MaxX = offset_x + column->WidthGiven + table->CellSpacingX1 + table->CellSpacingX2 + table->CellPaddingX * 2.0f; column->MaxX = offset_x + column->WidthGiven + table->CellSpacingX1 + table->CellSpacingX2 + table->CellPaddingX * 2.0f;
@ -1117,8 +1124,13 @@ void ImGui::TableUpdateLayout(ImGuiTable* table)
column->Flags |= ImGuiTableColumnFlags_IsVisible; column->Flags |= ImGuiTableColumnFlags_IsVisible;
if (column->SortOrder != -1) if (column->SortOrder != -1)
column->Flags |= ImGuiTableColumnFlags_IsSorted; column->Flags |= ImGuiTableColumnFlags_IsSorted;
if (table->HoveredColumnBody == column_n)
// Detect hovered column
if (is_hovering_table && mouse_skewed_x >= column->ClipRect.Min.x && mouse_skewed_x < column->ClipRect.Max.x)
{
column->Flags |= ImGuiTableColumnFlags_IsHovered; column->Flags |= ImGuiTableColumnFlags_IsHovered;
table->HoveredColumnBody = (ImGuiTableColumnIdx)column_n;
}
// Alignment // Alignment
// FIXME-TABLE: This align based on the whole column width, not per-cell, and therefore isn't useful in // FIXME-TABLE: This align based on the whole column width, not per-cell, and therefore isn't useful in
@ -1249,7 +1261,7 @@ void ImGui::TableUpdateLayout(ImGuiTable* table)
if (table->Flags & ImGuiTableFlags_NoClip) if (table->Flags & ImGuiTableFlags_NoClip)
table->DrawSplitter->SetCurrentChannel(inner_window->DrawList, TABLE_DRAW_CHANNEL_NOCLIP); table->DrawSplitter->SetCurrentChannel(inner_window->DrawList, TABLE_DRAW_CHANNEL_NOCLIP);
else else
inner_window->DrawList->PushClipRect(inner_window->ClipRect.Min, inner_window->ClipRect.Max, false); inner_window->DrawList->PushClipRect(inner_window->InnerClipRect.Min, inner_window->InnerClipRect.Max, false);
} }
// Process hit-testing on resizing borders. Actual size change will be applied in EndTable() // Process hit-testing on resizing borders. Actual size change will be applied in EndTable()
@ -1996,34 +2008,37 @@ void ImGui::TableEndRow(ImGuiTable* table)
// We need to do that in TableEndRow() instead of TableBeginRow() so the list clipper can mark end of row and // We need to do that in TableEndRow() instead of TableBeginRow() so the list clipper can mark end of row and
// get the new cursor position. // get the new cursor position.
if (unfreeze_rows_request) if (unfreeze_rows_request)
{
for (int column_n = 0; column_n < table->ColumnsCount; column_n++) for (int column_n = 0; column_n < table->ColumnsCount; column_n++)
table->Columns[column_n].NavLayerCurrent = ImGuiNavLayer_Main; table->Columns[column_n].NavLayerCurrent = ImGuiNavLayer_Main;
if (unfreeze_rows_actual)
{
IM_ASSERT(table->IsUnfrozenRows == false);
const float y0 = ImMax(table->RowPosY2 + 1, window->InnerClipRect.Min.y); const float y0 = ImMax(table->RowPosY2 + 1, window->InnerClipRect.Min.y);
table->IsUnfrozenRows = true;
table_instance->LastFrozenHeight = y0 - table->OuterRect.Min.y; table_instance->LastFrozenHeight = y0 - table->OuterRect.Min.y;
// BgClipRect starts as table->InnerClipRect, reduce it now and make BgClipRectForDrawCmd == BgClipRect if (unfreeze_rows_actual)
table->BgClipRect.Min.y = table->Bg2ClipRectForDrawCmd.Min.y = ImMin(y0, window->InnerClipRect.Max.y);
table->BgClipRect.Max.y = table->Bg2ClipRectForDrawCmd.Max.y = window->InnerClipRect.Max.y;
table->Bg2DrawChannelCurrent = table->Bg2DrawChannelUnfrozen;
IM_ASSERT(table->Bg2ClipRectForDrawCmd.Min.y <= table->Bg2ClipRectForDrawCmd.Max.y);
float row_height = table->RowPosY2 - table->RowPosY1;
table->RowPosY2 = window->DC.CursorPos.y = table->WorkRect.Min.y + table->RowPosY2 - table->OuterRect.Min.y;
table->RowPosY1 = table->RowPosY2 - row_height;
for (int column_n = 0; column_n < table->ColumnsCount; column_n++)
{ {
ImGuiTableColumn* column = &table->Columns[column_n]; IM_ASSERT(table->IsUnfrozenRows == false);
column->DrawChannelCurrent = column->DrawChannelUnfrozen; table->IsUnfrozenRows = true;
column->ClipRect.Min.y = table->Bg2ClipRectForDrawCmd.Min.y;
}
// Update cliprect ahead of TableBeginCell() so clipper can access to new ClipRect->Min.y // BgClipRect starts as table->InnerClipRect, reduce it now and make BgClipRectForDrawCmd == BgClipRect
SetWindowClipRectBeforeSetChannel(window, table->Columns[0].ClipRect); table->BgClipRect.Min.y = table->Bg2ClipRectForDrawCmd.Min.y = ImMin(y0, window->InnerClipRect.Max.y);
table->DrawSplitter->SetCurrentChannel(window->DrawList, table->Columns[0].DrawChannelCurrent); table->BgClipRect.Max.y = table->Bg2ClipRectForDrawCmd.Max.y = window->InnerClipRect.Max.y;
table->Bg2DrawChannelCurrent = table->Bg2DrawChannelUnfrozen;
IM_ASSERT(table->Bg2ClipRectForDrawCmd.Min.y <= table->Bg2ClipRectForDrawCmd.Max.y);
float row_height = table->RowPosY2 - table->RowPosY1;
table->RowPosY2 = window->DC.CursorPos.y = table->WorkRect.Min.y + table->RowPosY2 - table->OuterRect.Min.y;
table->RowPosY1 = table->RowPosY2 - row_height;
for (int column_n = 0; column_n < table->ColumnsCount; column_n++)
{
ImGuiTableColumn* column = &table->Columns[column_n];
column->DrawChannelCurrent = column->DrawChannelUnfrozen;
column->ClipRect.Min.y = table->Bg2ClipRectForDrawCmd.Min.y;
}
// Update cliprect ahead of TableBeginCell() so clipper can access to new ClipRect->Min.y
SetWindowClipRectBeforeSetChannel(window, table->Columns[0].ClipRect);
table->DrawSplitter->SetCurrentChannel(window->DrawList, table->Columns[0].DrawChannelCurrent);
}
} }
if (!(table->RowFlags & ImGuiTableRowFlags_Headers)) if (!(table->RowFlags & ImGuiTableRowFlags_Headers))
@ -2192,8 +2207,8 @@ void ImGui::TableEndCell(ImGuiTable* table)
// Note that actual columns widths are computed in TableUpdateLayout(). // Note that actual columns widths are computed in TableUpdateLayout().
//------------------------------------------------------------------------- //-------------------------------------------------------------------------
// Maximum column content width given current layout. Use column->MinX so this value on a per-column basis. // Maximum column content width given current layout. Use column->MinX so this value differs on a per-column basis.
float ImGui::TableGetMaxColumnWidth(const ImGuiTable* table, int column_n) float ImGui::TableCalcMaxColumnWidth(const ImGuiTable* table, int column_n)
{ {
const ImGuiTableColumn* column = &table->Columns[column_n]; const ImGuiTableColumn* column = &table->Columns[column_n];
float max_width = FLT_MAX; float max_width = FLT_MAX;
@ -2255,7 +2270,7 @@ void ImGui::TableSetColumnWidth(int column_n, float width)
// Compare both requested and actual given width to avoid overwriting requested width when column is stuck (minimum size, bounded) // Compare both requested and actual given width to avoid overwriting requested width when column is stuck (minimum size, bounded)
IM_ASSERT(table->MinColumnWidth > 0.0f); IM_ASSERT(table->MinColumnWidth > 0.0f);
const float min_width = table->MinColumnWidth; const float min_width = table->MinColumnWidth;
const float max_width = ImMax(min_width, TableGetMaxColumnWidth(table, column_n)); const float max_width = ImMax(min_width, column_0->WidthMax); // Don't use TableCalcMaxColumnWidth() here as it would rely on MinX from last instance (#7933)
column_0_width = ImClamp(column_0_width, min_width, max_width); column_0_width = ImClamp(column_0_width, min_width, max_width);
if (column_0->WidthGiven == column_0_width || column_0->WidthRequest == column_0_width) if (column_0->WidthGiven == column_0_width || column_0->WidthRequest == column_0_width)
return; return;
@ -2740,7 +2755,7 @@ void ImGui::TableDrawBorders(ImGuiTable* table)
const ImU32 outer_col = table->BorderColorStrong; const ImU32 outer_col = table->BorderColorStrong;
if ((table->Flags & ImGuiTableFlags_BordersOuter) == ImGuiTableFlags_BordersOuter) if ((table->Flags & ImGuiTableFlags_BordersOuter) == ImGuiTableFlags_BordersOuter)
{ {
inner_drawlist->AddRect(outer_border.Min, outer_border.Max + ImVec2(1, 1), outer_col, 0.0f, 0, border_size); inner_drawlist->AddRect(outer_border.Min, outer_border.Max, outer_col, 0.0f, 0, border_size);
} }
else if (table->Flags & ImGuiTableFlags_BordersOuterV) else if (table->Flags & ImGuiTableFlags_BordersOuterV)
{ {
@ -3004,7 +3019,8 @@ float ImGui::TableGetHeaderAngledMaxLabelWidth()
// The intent is that advanced users willing to create customized headers would not need to use this helper // The intent is that advanced users willing to create customized headers would not need to use this helper
// and can create their own! For example: TableHeader() may be preceded by Checkbox() or other custom widgets. // and can create their own! For example: TableHeader() may be preceded by Checkbox() or other custom widgets.
// See 'Demo->Tables->Custom headers' for a demonstration of implementing a custom version of this. // See 'Demo->Tables->Custom headers' for a demonstration of implementing a custom version of this.
// This code is constructed to not make much use of internal functions, as it is intended to be a template to copy. // This code is intentionally written to not make much use of internal functions, to give you better direction
// if you need to write your own.
// FIXME-TABLE: TableOpenContextMenu() and TableGetHeaderRowHeight() are not public. // FIXME-TABLE: TableOpenContextMenu() and TableGetHeaderRowHeight() are not public.
void ImGui::TableHeadersRow() void ImGui::TableHeadersRow()
{ {
@ -3012,7 +3028,8 @@ void ImGui::TableHeadersRow()
ImGuiTable* table = g.CurrentTable; ImGuiTable* table = g.CurrentTable;
IM_ASSERT(table != NULL && "Need to call TableHeadersRow() after BeginTable()!"); IM_ASSERT(table != NULL && "Need to call TableHeadersRow() after BeginTable()!");
// Layout if not already done (this is automatically done by TableNextRow, we do it here solely to facilitate stepping in debugger as it is frequent to step in TableUpdateLayout) // Call layout if not already done. This is automatically done by TableNextRow: we do it here _only_ to make
// it easier to debug-step in TableUpdateLayout(). Your own version of this function doesn't need this.
if (!table->IsLayoutLocked) if (!table->IsLayoutLocked)
TableUpdateLayout(table); TableUpdateLayout(table);
@ -3029,8 +3046,7 @@ void ImGui::TableHeadersRow()
if (!TableSetColumnIndex(column_n)) if (!TableSetColumnIndex(column_n))
continue; continue;
// Push an id to allow unnamed labels (generally accidental, but let's behave nicely with them) // Push an id to allow empty/unnamed headers. This is also idiomatic as it ensure there is a consistent ID path to access columns (for e.g. automation)
// In your own code you may omit the PushID/PopID all-together, provided you know they won't collide.
const char* name = (TableGetColumnFlags(column_n) & ImGuiTableColumnFlags_NoHeaderLabel) ? "" : TableGetColumnName(column_n); const char* name = (TableGetColumnFlags(column_n) & ImGuiTableColumnFlags_NoHeaderLabel) ? "" : TableGetColumnName(column_n);
PushID(column_n); PushID(column_n);
TableHeader(name); TableHeader(name);
@ -3269,7 +3285,7 @@ void ImGui::TableAngledHeadersRowEx(ImGuiID row_id, float angle, float max_label
ButtonBehavior(row_r, row_id, NULL, NULL); ButtonBehavior(row_r, row_id, NULL, NULL);
KeepAliveID(row_id); KeepAliveID(row_id);
const float ascent_scaled = g.Font->Ascent * (g.FontSize / g.Font->FontSize); // FIXME: Standardize those scaling factors better const float ascent_scaled = g.Font->Ascent * g.FontScale; // FIXME: Standardize those scaling factors better
const float line_off_for_ascent_x = (ImMax((g.FontSize - ascent_scaled) * 0.5f, 0.0f) / -sin_a) * (flip_label ? -1.0f : 1.0f); const float line_off_for_ascent_x = (ImMax((g.FontSize - ascent_scaled) * 0.5f, 0.0f) / -sin_a) * (flip_label ? -1.0f : 1.0f);
const ImVec2 padding = g.Style.CellPadding; // We will always use swapped component const ImVec2 padding = g.Style.CellPadding; // We will always use swapped component
const ImVec2 align = g.Style.TableAngledHeadersTextAlign; const ImVec2 align = g.Style.TableAngledHeadersTextAlign;
@ -3471,7 +3487,7 @@ void ImGui::TableDrawDefaultContextMenu(ImGuiTable* table, ImGuiTableFlags flags
Separator(); Separator();
want_separator = true; want_separator = true;
PushItemFlag(ImGuiItemFlags_SelectableDontClosePopup, true); PushItemFlag(ImGuiItemFlags_AutoClosePopups, false);
for (int other_column_n = 0; other_column_n < table->ColumnsCount; other_column_n++) for (int other_column_n = 0; other_column_n < table->ColumnsCount; other_column_n++)
{ {
ImGuiTableColumn* other_column = &table->Columns[other_column_n]; ImGuiTableColumn* other_column = &table->Columns[other_column_n];
@ -4425,12 +4441,12 @@ void ImGui::EndColumns()
NavUpdateCurrentWindowIsScrollPushableX(); NavUpdateCurrentWindowIsScrollPushableX();
} }
void ImGui::Columns(int columns_count, const char* id, bool border) void ImGui::Columns(int columns_count, const char* id, bool borders)
{ {
ImGuiWindow* window = GetCurrentWindow(); ImGuiWindow* window = GetCurrentWindow();
IM_ASSERT(columns_count >= 1); IM_ASSERT(columns_count >= 1);
ImGuiOldColumnFlags flags = (border ? 0 : ImGuiOldColumnFlags_NoBorder); ImGuiOldColumnFlags flags = (borders ? 0 : ImGuiOldColumnFlags_NoBorder);
//flags |= ImGuiOldColumnFlags_NoPreserveWidths; // NB: Legacy behavior //flags |= ImGuiOldColumnFlags_NoPreserveWidths; // NB: Legacy behavior
ImGuiOldColumns* columns = window->DC.CurrentColumns; ImGuiOldColumns* columns = window->DC.CurrentColumns;
if (columns != NULL && columns->Count == columns_count && columns->Flags == flags) if (columns != NULL && columns->Count == columns_count && columns->Flags == flags)

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -453,6 +453,7 @@
the standard logger in sokol_log.h instead, otherwise you won't see any warnings or the standard logger in sokol_log.h instead, otherwise you won't see any warnings or
errors. errors.
LICENSE LICENSE
======= =======
@ -1067,6 +1068,7 @@ typedef struct {
/* sokol-audio state */ /* sokol-audio state */
typedef struct { typedef struct {
bool valid; bool valid;
bool setup_called;
void (*stream_cb)(float* buffer, int num_frames, int num_channels); void (*stream_cb)(float* buffer, int num_frames, int num_channels);
void (*stream_userdata_cb)(float* buffer, int num_frames, int num_channels, void* user_data); void (*stream_userdata_cb)(float* buffer, int num_frames, int num_channels, void* user_data);
void* user_data; void* user_data;
@ -2486,9 +2488,11 @@ void _saudio_backend_shutdown(void) {
// >>public // >>public
SOKOL_API_IMPL void saudio_setup(const saudio_desc* desc) { SOKOL_API_IMPL void saudio_setup(const saudio_desc* desc) {
SOKOL_ASSERT(!_saudio.valid); SOKOL_ASSERT(!_saudio.valid);
SOKOL_ASSERT(!_saudio.setup_called);
SOKOL_ASSERT(desc); SOKOL_ASSERT(desc);
SOKOL_ASSERT((desc->allocator.alloc_fn && desc->allocator.free_fn) || (!desc->allocator.alloc_fn && !desc->allocator.free_fn)); SOKOL_ASSERT((desc->allocator.alloc_fn && desc->allocator.free_fn) || (!desc->allocator.alloc_fn && !desc->allocator.free_fn));
_saudio_clear(&_saudio, sizeof(_saudio)); _saudio_clear(&_saudio, sizeof(_saudio));
_saudio.setup_called = true;
_saudio.desc = *desc; _saudio.desc = *desc;
_saudio.stream_cb = desc->stream_cb; _saudio.stream_cb = desc->stream_cb;
_saudio.stream_userdata_cb = desc->stream_userdata_cb; _saudio.stream_userdata_cb = desc->stream_userdata_cb;
@ -2519,6 +2523,8 @@ SOKOL_API_IMPL void saudio_setup(const saudio_desc* desc) {
} }
SOKOL_API_IMPL void saudio_shutdown(void) { SOKOL_API_IMPL void saudio_shutdown(void) {
SOKOL_ASSERT(_saudio.setup_called);
_saudio.setup_called = false;
if (_saudio.valid) { if (_saudio.valid) {
_saudio_backend_shutdown(); _saudio_backend_shutdown();
_saudio_fifo_shutdown(&_saudio.fifo); _saudio_fifo_shutdown(&_saudio.fifo);
@ -2532,26 +2538,32 @@ SOKOL_API_IMPL bool saudio_isvalid(void) {
} }
SOKOL_API_IMPL void* saudio_userdata(void) { SOKOL_API_IMPL void* saudio_userdata(void) {
SOKOL_ASSERT(_saudio.setup_called);
return _saudio.desc.user_data; return _saudio.desc.user_data;
} }
SOKOL_API_IMPL saudio_desc saudio_query_desc(void) { SOKOL_API_IMPL saudio_desc saudio_query_desc(void) {
SOKOL_ASSERT(_saudio.setup_called);
return _saudio.desc; return _saudio.desc;
} }
SOKOL_API_IMPL int saudio_sample_rate(void) { SOKOL_API_IMPL int saudio_sample_rate(void) {
SOKOL_ASSERT(_saudio.setup_called);
return _saudio.sample_rate; return _saudio.sample_rate;
} }
SOKOL_API_IMPL int saudio_buffer_frames(void) { SOKOL_API_IMPL int saudio_buffer_frames(void) {
SOKOL_ASSERT(_saudio.setup_called);
return _saudio.buffer_frames; return _saudio.buffer_frames;
} }
SOKOL_API_IMPL int saudio_channels(void) { SOKOL_API_IMPL int saudio_channels(void) {
SOKOL_ASSERT(_saudio.setup_called);
return _saudio.num_channels; return _saudio.num_channels;
} }
SOKOL_API_IMPL bool saudio_suspended(void) { SOKOL_API_IMPL bool saudio_suspended(void) {
SOKOL_ASSERT(_saudio.setup_called);
#if defined(_SAUDIO_EMSCRIPTEN) #if defined(_SAUDIO_EMSCRIPTEN)
if (_saudio.valid) { if (_saudio.valid) {
return 1 == saudio_js_suspended(); return 1 == saudio_js_suspended();
@ -2565,6 +2577,7 @@ SOKOL_API_IMPL bool saudio_suspended(void) {
} }
SOKOL_API_IMPL int saudio_expect(void) { SOKOL_API_IMPL int saudio_expect(void) {
SOKOL_ASSERT(_saudio.setup_called);
if (_saudio.valid) { if (_saudio.valid) {
const int num_frames = _saudio_fifo_writable_bytes(&_saudio.fifo) / _saudio.bytes_per_frame; const int num_frames = _saudio_fifo_writable_bytes(&_saudio.fifo) / _saudio.bytes_per_frame;
return num_frames; return num_frames;
@ -2575,6 +2588,7 @@ SOKOL_API_IMPL int saudio_expect(void) {
} }
SOKOL_API_IMPL int saudio_push(const float* frames, int num_frames) { SOKOL_API_IMPL int saudio_push(const float* frames, int num_frames) {
SOKOL_ASSERT(_saudio.setup_called);
SOKOL_ASSERT(frames && (num_frames > 0)); SOKOL_ASSERT(frames && (num_frames > 0));
if (_saudio.valid) { if (_saudio.valid) {
const int num_bytes = num_frames * _saudio.bytes_per_frame; const int num_bytes = num_frames * _saudio.bytes_per_frame;

View file

@ -1201,6 +1201,11 @@ inline sfetch_handle_t sfetch_send(const sfetch_request_t& request) { return sfe
#define _SFETCH_HAS_THREADS (1) #define _SFETCH_HAS_THREADS (1)
#endif #endif
#ifdef _MSC_VER
#pragma warning(push)
#pragma warning(disable:4724) // potential mod by 0
#endif
// ███████ ████████ ██████ ██ ██ ██████ ████████ ███████ // ███████ ████████ ██████ ██ ██ ██████ ████████ ███████
// ██ ██ ██ ██ ██ ██ ██ ██ ██ // ██ ██ ██ ██ ██ ██ ██ ██ ██
// ███████ ██ ██████ ██ ██ ██ ██ ███████ // ███████ ██ ██████ ██ ██ ██ ██ ███████
@ -2806,4 +2811,9 @@ SOKOL_API_IMPL void sfetch_cancel(sfetch_handle_t h) {
item->user.cancel = true; item->user.cancel = true;
} }
} }
#ifdef _MSC_VER
#pragma warning(pop)
#endif
#endif /* SOKOL_FETCH_IMPL */ #endif /* SOKOL_FETCH_IMPL */

View file

@ -963,7 +963,7 @@
ON STORAGE BUFFERS ON STORAGE BUFFERS
================== ==================
Storage buffers can be used to pass large amounts of random access structured Storage buffers can be used to pass large amounts of random access structured
data fromt the CPU side to the shaders. They are similar to data textures, but are data from the CPU side to the shaders. They are similar to data textures, but are
more convenient to use both on the CPU and shader side since they can be accessed more convenient to use both on the CPU and shader side since they can be accessed
in shaders as as a 1-dimensional array of struct items. in shaders as as a 1-dimensional array of struct items.
@ -1496,6 +1496,7 @@
.wgpu.num_bindgroup_cache_hits .wgpu.num_bindgroup_cache_hits
.wgpu.num_bindgroup_cache_misses .wgpu.num_bindgroup_cache_misses
.wgpu.num_bindgroup_cache_collisions .wgpu.num_bindgroup_cache_collisions
.wgpu_num_bindgroup_cache_invalidates
.wgpu.num_bindgroup_cache_vs_hash_key_mismatch .wgpu.num_bindgroup_cache_vs_hash_key_mismatch
The value to pay attention to is `.wgpu.num_bindgroup_cache_collisions`, The value to pay attention to is `.wgpu.num_bindgroup_cache_collisions`,
@ -2097,13 +2098,10 @@ typedef enum sg_primitive_type {
used in the sg_sampler_desc.min_filter, sg_sampler_desc.mag_filter used in the sg_sampler_desc.min_filter, sg_sampler_desc.mag_filter
and sg_sampler_desc.mipmap_filter members when creating a sampler object. and sg_sampler_desc.mipmap_filter members when creating a sampler object.
For min_filter and mag_filter the default is SG_FILTER_NEAREST. For the default is SG_FILTER_NEAREST.
For mipmap_filter the default is SG_FILTER_NONE.
*/ */
typedef enum sg_filter { typedef enum sg_filter {
_SG_FILTER_DEFAULT, // value 0 reserved for default-init _SG_FILTER_DEFAULT, // value 0 reserved for default-init
SG_FILTER_NONE, // FIXME: deprecated
SG_FILTER_NEAREST, SG_FILTER_NEAREST,
SG_FILTER_LINEAR, SG_FILTER_LINEAR,
_SG_FILTER_NUM, _SG_FILTER_NUM,
@ -2892,7 +2890,7 @@ typedef struct sg_image_desc {
.min_filter: SG_FILTER_NEAREST .min_filter: SG_FILTER_NEAREST
.mag_filter: SG_FILTER_NEAREST .mag_filter: SG_FILTER_NEAREST
.mipmap_filter SG_FILTER_NONE .mipmap_filter SG_FILTER_NEAREST
.wrap_u: SG_WRAP_REPEAT .wrap_u: SG_WRAP_REPEAT
.wrap_v: SG_WRAP_REPEAT .wrap_v: SG_WRAP_REPEAT
.wrap_w: SG_WRAP_REPEAT (only SG_IMAGETYPE_3D) .wrap_w: SG_WRAP_REPEAT (only SG_IMAGETYPE_3D)
@ -3482,6 +3480,7 @@ typedef struct sg_frame_stats_wgpu_bindings {
uint32_t num_bindgroup_cache_hits; uint32_t num_bindgroup_cache_hits;
uint32_t num_bindgroup_cache_misses; uint32_t num_bindgroup_cache_misses;
uint32_t num_bindgroup_cache_collisions; uint32_t num_bindgroup_cache_collisions;
uint32_t num_bindgroup_cache_invalidates;
uint32_t num_bindgroup_cache_hash_vs_key_mismatch; uint32_t num_bindgroup_cache_hash_vs_key_mismatch;
} sg_frame_stats_wgpu_bindings; } sg_frame_stats_wgpu_bindings;
@ -3592,7 +3591,7 @@ typedef struct sg_frame_stats {
_SG_LOGITEM_XMACRO(WGPU_ATTACHMENTS_CREATE_TEXTURE_VIEW_FAILED, "wgpuTextureCreateView() failed in create attachments") \ _SG_LOGITEM_XMACRO(WGPU_ATTACHMENTS_CREATE_TEXTURE_VIEW_FAILED, "wgpuTextureCreateView() failed in create attachments") \
_SG_LOGITEM_XMACRO(IDENTICAL_COMMIT_LISTENER, "attempting to add identical commit listener") \ _SG_LOGITEM_XMACRO(IDENTICAL_COMMIT_LISTENER, "attempting to add identical commit listener") \
_SG_LOGITEM_XMACRO(COMMIT_LISTENER_ARRAY_FULL, "commit listener array full") \ _SG_LOGITEM_XMACRO(COMMIT_LISTENER_ARRAY_FULL, "commit listener array full") \
_SG_LOGITEM_XMACRO(TRACE_HOOKS_NOT_ENABLED, "sg_install_trace_hooks() called, but SG_TRACE_HOOKS is not defined") \ _SG_LOGITEM_XMACRO(TRACE_HOOKS_NOT_ENABLED, "sg_install_trace_hooks() called, but SOKOL_TRACE_HOOKS is not defined") \
_SG_LOGITEM_XMACRO(DEALLOC_BUFFER_INVALID_STATE, "sg_dealloc_buffer(): buffer must be in ALLOC state") \ _SG_LOGITEM_XMACRO(DEALLOC_BUFFER_INVALID_STATE, "sg_dealloc_buffer(): buffer must be in ALLOC state") \
_SG_LOGITEM_XMACRO(DEALLOC_IMAGE_INVALID_STATE, "sg_dealloc_image(): image must be in alloc state") \ _SG_LOGITEM_XMACRO(DEALLOC_IMAGE_INVALID_STATE, "sg_dealloc_image(): image must be in alloc state") \
_SG_LOGITEM_XMACRO(DEALLOC_SAMPLER_INVALID_STATE, "sg_dealloc_sampler(): sampler must be in alloc state") \ _SG_LOGITEM_XMACRO(DEALLOC_SAMPLER_INVALID_STATE, "sg_dealloc_sampler(): sampler must be in alloc state") \
@ -3650,8 +3649,6 @@ typedef struct sg_frame_stats {
_SG_LOGITEM_XMACRO(VALIDATE_IMAGEDESC_DYNAMIC_NO_DATA, "dynamic/stream images cannot be initialized with data") \ _SG_LOGITEM_XMACRO(VALIDATE_IMAGEDESC_DYNAMIC_NO_DATA, "dynamic/stream images cannot be initialized with data") \
_SG_LOGITEM_XMACRO(VALIDATE_IMAGEDESC_COMPRESSED_IMMUTABLE, "compressed images must be immutable") \ _SG_LOGITEM_XMACRO(VALIDATE_IMAGEDESC_COMPRESSED_IMMUTABLE, "compressed images must be immutable") \
_SG_LOGITEM_XMACRO(VALIDATE_SAMPLERDESC_CANARY, "sg_sampler_desc not initialized") \ _SG_LOGITEM_XMACRO(VALIDATE_SAMPLERDESC_CANARY, "sg_sampler_desc not initialized") \
_SG_LOGITEM_XMACRO(VALIDATE_SAMPLERDESC_MINFILTER_NONE, "sg_sampler_desc.min_filter cannot be SG_FILTER_NONE") \
_SG_LOGITEM_XMACRO(VALIDATE_SAMPLERDESC_MAGFILTER_NONE, "sg_sampler_desc.mag_filter cannot be SG_FILTER_NONE") \
_SG_LOGITEM_XMACRO(VALIDATE_SAMPLERDESC_ANISTROPIC_REQUIRES_LINEAR_FILTERING, "sg_sampler_desc.max_anisotropy > 1 requires min/mag/mipmap_filter to be SG_FILTER_LINEAR") \ _SG_LOGITEM_XMACRO(VALIDATE_SAMPLERDESC_ANISTROPIC_REQUIRES_LINEAR_FILTERING, "sg_sampler_desc.max_anisotropy > 1 requires min/mag/mipmap_filter to be SG_FILTER_LINEAR") \
_SG_LOGITEM_XMACRO(VALIDATE_SHADERDESC_CANARY, "sg_shader_desc not initialized") \ _SG_LOGITEM_XMACRO(VALIDATE_SHADERDESC_CANARY, "sg_shader_desc not initialized") \
_SG_LOGITEM_XMACRO(VALIDATE_SHADERDESC_SOURCE, "shader source code required") \ _SG_LOGITEM_XMACRO(VALIDATE_SHADERDESC_SOURCE, "shader source code required") \
@ -3887,6 +3884,12 @@ typedef enum sg_log_item {
before sg_setup() is called before sg_setup() is called
.environment.d3d11.device_context .environment.d3d11.device_context
a pointer to the ID3D11DeviceContext object a pointer to the ID3D11DeviceContext object
.d3d11_shader_debugging
set this to true to compile shaders which are provided as HLSL source
code with debug information and without optimization, this allows
shader debugging in tools like RenderDoc, to output source code
instead of byte code from sokol-shdc, omit the `--binary` cmdline
option
WebGPU specific: WebGPU specific:
.wgpu_disable_bindgroups_cache .wgpu_disable_bindgroups_cache
@ -3999,6 +4002,7 @@ typedef struct sg_desc {
int uniform_buffer_size; int uniform_buffer_size;
int max_commit_listeners; int max_commit_listeners;
bool disable_validation; // disable validation layer even in debug mode, useful for tests bool disable_validation; // disable validation layer even in debug mode, useful for tests
bool d3d11_shader_debugging; // if true, HLSL shaders are compiled with D3DCOMPILE_DEBUG | D3DCOMPILE_SKIP_OPTIMIZATION
bool mtl_force_managed_storage_mode; // for debugging: use Metal managed storage mode for resources even with UMA bool mtl_force_managed_storage_mode; // for debugging: use Metal managed storage mode for resources even with UMA
bool mtl_use_command_buffer_with_retained_references; // Metal: use a managed MTLCommandBuffer which ref-counts used resources bool mtl_use_command_buffer_with_retained_references; // Metal: use a managed MTLCommandBuffer which ref-counts used resources
bool wgpu_disable_bindgroups_cache; // set to true to disable the WebGPU backend BindGroup cache bool wgpu_disable_bindgroups_cache; // set to true to disable the WebGPU backend BindGroup cache
@ -5783,10 +5787,20 @@ typedef struct {
uint32_t id; uint32_t id;
} _sg_wgpu_bindgroup_handle_t; } _sg_wgpu_bindgroup_handle_t;
#define _SG_WGPU_BINDGROUPSCACHE_NUM_ITEMS (1 + _SG_WGPU_MAX_BINDGROUP_ENTRIES) typedef enum {
_SG_WGPU_BINDGROUPSCACHEITEMTYPE_NONE = 0,
_SG_WGPU_BINDGROUPSCACHEITEMTYPE_IMAGE = 0x1111111111111111,
_SG_WGPU_BINDGROUPSCACHEITEMTYPE_SAMPLER = 0x2222222222222222,
_SG_WGPU_BINDGROUPSCACHEITEMTYPE_STORAGEBUFFER = 0x3333333333333333,
_SG_WGPU_BINDGROUPSCACHEITEMTYPE_PIPELINE = 0x4444444444444444,
} _sg_wgpu_bindgroups_cache_item_type_t;
#define _SG_WGPU_BINDGROUPSCACHEKEY_NUM_ITEMS (1 + _SG_WGPU_MAX_BINDGROUP_ENTRIES)
typedef struct { typedef struct {
uint64_t hash; uint64_t hash;
uint32_t items[_SG_WGPU_BINDGROUPSCACHE_NUM_ITEMS]; // the format of cache key items is (_sg_wgpu_bindgroups_cache_item_type_t << 32) | handle.id,
// where the item type is a per-resource-type bit pattern
uint64_t items[_SG_WGPU_BINDGROUPSCACHEKEY_NUM_ITEMS];
} _sg_wgpu_bindgroups_cache_key_t; } _sg_wgpu_bindgroups_cache_key_t;
typedef struct { typedef struct {
@ -7142,14 +7156,12 @@ _SOKOL_PRIVATE GLenum _sg_gl_blend_op(sg_blend_op op) {
_SOKOL_PRIVATE GLenum _sg_gl_min_filter(sg_filter min_f, sg_filter mipmap_f) { _SOKOL_PRIVATE GLenum _sg_gl_min_filter(sg_filter min_f, sg_filter mipmap_f) {
if (min_f == SG_FILTER_NEAREST) { if (min_f == SG_FILTER_NEAREST) {
switch (mipmap_f) { switch (mipmap_f) {
case SG_FILTER_NONE: return GL_NEAREST;
case SG_FILTER_NEAREST: return GL_NEAREST_MIPMAP_NEAREST; case SG_FILTER_NEAREST: return GL_NEAREST_MIPMAP_NEAREST;
case SG_FILTER_LINEAR: return GL_NEAREST_MIPMAP_LINEAR; case SG_FILTER_LINEAR: return GL_NEAREST_MIPMAP_LINEAR;
default: SOKOL_UNREACHABLE; return (GLenum)0; default: SOKOL_UNREACHABLE; return (GLenum)0;
} }
} else if (min_f == SG_FILTER_LINEAR) { } else if (min_f == SG_FILTER_LINEAR) {
switch (mipmap_f) { switch (mipmap_f) {
case SG_FILTER_NONE: return GL_LINEAR;
case SG_FILTER_NEAREST: return GL_LINEAR_MIPMAP_NEAREST; case SG_FILTER_NEAREST: return GL_LINEAR_MIPMAP_NEAREST;
case SG_FILTER_LINEAR: return GL_LINEAR_MIPMAP_LINEAR; case SG_FILTER_LINEAR: return GL_LINEAR_MIPMAP_LINEAR;
default: SOKOL_UNREACHABLE; return (GLenum)0; default: SOKOL_UNREACHABLE; return (GLenum)0;
@ -8299,40 +8311,57 @@ _SOKOL_PRIVATE sg_resource_state _sg_gl_create_image(_sg_image_t* img, const sg_
_sg_gl_cache_store_texture_sampler_binding(0); _sg_gl_cache_store_texture_sampler_binding(0);
_sg_gl_cache_bind_texture_sampler(0, img->gl.target, img->gl.tex[slot], 0); _sg_gl_cache_bind_texture_sampler(0, img->gl.target, img->gl.tex[slot], 0);
glTexParameteri(img->gl.target, GL_TEXTURE_MAX_LEVEL, img->cmn.num_mipmaps - 1); glTexParameteri(img->gl.target, GL_TEXTURE_MAX_LEVEL, img->cmn.num_mipmaps - 1);
const int num_faces = img->cmn.type == SG_IMAGETYPE_CUBE ? 6 : 1;
int data_index = 0; // NOTE: workaround for https://issues.chromium.org/issues/355605685
for (int face_index = 0; face_index < num_faces; face_index++) { // FIXME: on GLES3 and GL 4.3 (e.g. not macOS) the texture initialization
for (int mip_index = 0; mip_index < img->cmn.num_mipmaps; mip_index++, data_index++) { // should be rewritten to use glTexStorage + glTexSubImage
GLenum gl_img_target = img->gl.target; bool tex_storage_allocated = false;
if (SG_IMAGETYPE_CUBE == img->cmn.type) { #if defined(__EMSCRIPTEN__)
gl_img_target = _sg_gl_cubeface_target(face_index); if (desc->data.subimage[0][0].ptr == 0) {
} tex_storage_allocated = true;
const GLvoid* data_ptr = desc->data.subimage[face_index][mip_index].ptr;
const int mip_width = _sg_miplevel_dim(img->cmn.width, mip_index);
const int mip_height = _sg_miplevel_dim(img->cmn.height, mip_index);
if ((SG_IMAGETYPE_2D == img->cmn.type) || (SG_IMAGETYPE_CUBE == img->cmn.type)) { if ((SG_IMAGETYPE_2D == img->cmn.type) || (SG_IMAGETYPE_CUBE == img->cmn.type)) {
if (is_compressed) { glTexStorage2D(img->gl.target, img->cmn.num_mipmaps, gl_internal_format, img->cmn.width, img->cmn.height);
const GLsizei data_size = (GLsizei) desc->data.subimage[face_index][mip_index].size;
glCompressedTexImage2D(gl_img_target, mip_index, gl_internal_format,
mip_width, mip_height, 0, data_size, data_ptr);
} else {
const GLenum gl_type = _sg_gl_teximage_type(img->cmn.pixel_format);
glTexImage2D(gl_img_target, mip_index, (GLint)gl_internal_format,
mip_width, mip_height, 0, gl_format, gl_type, data_ptr);
}
} else if ((SG_IMAGETYPE_3D == img->cmn.type) || (SG_IMAGETYPE_ARRAY == img->cmn.type)) { } else if ((SG_IMAGETYPE_3D == img->cmn.type) || (SG_IMAGETYPE_ARRAY == img->cmn.type)) {
int mip_depth = img->cmn.num_slices; glTexStorage3D(img->gl.target, img->cmn.num_mipmaps, gl_internal_format, img->cmn.width, img->cmn.height, img->cmn.num_slices);
if (SG_IMAGETYPE_3D == img->cmn.type) { }
mip_depth = _sg_miplevel_dim(mip_depth, mip_index); }
#endif
if (!tex_storage_allocated) {
const int num_faces = img->cmn.type == SG_IMAGETYPE_CUBE ? 6 : 1;
int data_index = 0;
for (int face_index = 0; face_index < num_faces; face_index++) {
for (int mip_index = 0; mip_index < img->cmn.num_mipmaps; mip_index++, data_index++) {
GLenum gl_img_target = img->gl.target;
if (SG_IMAGETYPE_CUBE == img->cmn.type) {
gl_img_target = _sg_gl_cubeface_target(face_index);
} }
if (is_compressed) { const GLvoid* data_ptr = desc->data.subimage[face_index][mip_index].ptr;
const GLsizei data_size = (GLsizei) desc->data.subimage[face_index][mip_index].size; const int mip_width = _sg_miplevel_dim(img->cmn.width, mip_index);
glCompressedTexImage3D(gl_img_target, mip_index, gl_internal_format, const int mip_height = _sg_miplevel_dim(img->cmn.height, mip_index);
mip_width, mip_height, mip_depth, 0, data_size, data_ptr); if ((SG_IMAGETYPE_2D == img->cmn.type) || (SG_IMAGETYPE_CUBE == img->cmn.type)) {
} else { if (is_compressed) {
const GLenum gl_type = _sg_gl_teximage_type(img->cmn.pixel_format); const GLsizei data_size = (GLsizei) desc->data.subimage[face_index][mip_index].size;
glTexImage3D(gl_img_target, mip_index, (GLint)gl_internal_format, glCompressedTexImage2D(gl_img_target, mip_index, gl_internal_format,
mip_width, mip_height, mip_depth, 0, gl_format, gl_type, data_ptr); mip_width, mip_height, 0, data_size, data_ptr);
} else {
const GLenum gl_type = _sg_gl_teximage_type(img->cmn.pixel_format);
glTexImage2D(gl_img_target, mip_index, (GLint)gl_internal_format,
mip_width, mip_height, 0, gl_format, gl_type, data_ptr);
}
} else if ((SG_IMAGETYPE_3D == img->cmn.type) || (SG_IMAGETYPE_ARRAY == img->cmn.type)) {
int mip_depth = img->cmn.num_slices;
if (SG_IMAGETYPE_3D == img->cmn.type) {
mip_depth = _sg_miplevel_dim(mip_depth, mip_index);
}
if (is_compressed) {
const GLsizei data_size = (GLsizei) desc->data.subimage[face_index][mip_index].size;
glCompressedTexImage3D(gl_img_target, mip_index, gl_internal_format,
mip_width, mip_height, mip_depth, 0, data_size, data_ptr);
} else {
const GLenum gl_type = _sg_gl_teximage_type(img->cmn.pixel_format);
glTexImage3D(gl_img_target, mip_index, (GLint)gl_internal_format,
mip_width, mip_height, mip_depth, 0, gl_format, gl_type, data_ptr);
}
} }
} }
} }
@ -10683,6 +10712,12 @@ _SOKOL_PRIVATE ID3DBlob* _sg_d3d11_compile_shader(const sg_shader_stage_desc* st
return NULL; return NULL;
} }
SOKOL_ASSERT(stage_desc->d3d11_target); SOKOL_ASSERT(stage_desc->d3d11_target);
UINT flags1 = D3DCOMPILE_PACK_MATRIX_COLUMN_MAJOR;
if (_sg.desc.d3d11_shader_debugging) {
flags1 |= D3DCOMPILE_DEBUG | D3DCOMPILE_SKIP_OPTIMIZATION;
} else {
flags1 |= D3DCOMPILE_OPTIMIZATION_LEVEL3;
}
ID3DBlob* output = NULL; ID3DBlob* output = NULL;
ID3DBlob* errors_or_warnings = NULL; ID3DBlob* errors_or_warnings = NULL;
HRESULT hr = _sg.d3d11.D3DCompile_func( HRESULT hr = _sg.d3d11.D3DCompile_func(
@ -10693,7 +10728,7 @@ _SOKOL_PRIVATE ID3DBlob* _sg_d3d11_compile_shader(const sg_shader_stage_desc* st
NULL, // pInclude NULL, // pInclude
stage_desc->entry ? stage_desc->entry : "main", // pEntryPoint stage_desc->entry ? stage_desc->entry : "main", // pEntryPoint
stage_desc->d3d11_target, // pTarget stage_desc->d3d11_target, // pTarget
D3DCOMPILE_PACK_MATRIX_COLUMN_MAJOR | D3DCOMPILE_OPTIMIZATION_LEVEL3, // Flags1 flags1, // Flags1
0, // Flags2 0, // Flags2
&output, // ppCode &output, // ppCode
&errors_or_warnings); // ppErrorMsgs &errors_or_warnings); // ppErrorMsgs
@ -11437,12 +11472,15 @@ _SOKOL_PRIVATE void _sg_d3d11_append_buffer(_sg_buffer_t* buf, const sg_range* d
} }
} }
// see: https://learn.microsoft.com/en-us/windows/win32/direct3d11/overviews-direct3d-11-resources-subresources
// also see: https://learn.microsoft.com/en-us/windows/win32/api/d3d11/nf-d3d11-d3d11calcsubresource
_SOKOL_PRIVATE void _sg_d3d11_update_image(_sg_image_t* img, const sg_image_data* data) { _SOKOL_PRIVATE void _sg_d3d11_update_image(_sg_image_t* img, const sg_image_data* data) {
SOKOL_ASSERT(img && data); SOKOL_ASSERT(img && data);
SOKOL_ASSERT(_sg.d3d11.ctx); SOKOL_ASSERT(_sg.d3d11.ctx);
SOKOL_ASSERT(img->d3d11.res); SOKOL_ASSERT(img->d3d11.res);
const int num_faces = (img->cmn.type == SG_IMAGETYPE_CUBE) ? 6:1; const int num_faces = (img->cmn.type == SG_IMAGETYPE_CUBE) ? 6:1;
const int num_slices = (img->cmn.type == SG_IMAGETYPE_ARRAY) ? img->cmn.num_slices:1; const int num_slices = (img->cmn.type == SG_IMAGETYPE_ARRAY) ? img->cmn.num_slices:1;
const int num_depth_slices = (img->cmn.type == SG_IMAGETYPE_3D) ? img->cmn.num_slices:1;
UINT subres_index = 0; UINT subres_index = 0;
HRESULT hr; HRESULT hr;
D3D11_MAPPED_SUBRESOURCE d3d11_msr; D3D11_MAPPED_SUBRESOURCE d3d11_msr;
@ -11452,26 +11490,35 @@ _SOKOL_PRIVATE void _sg_d3d11_update_image(_sg_image_t* img, const sg_image_data
SOKOL_ASSERT(subres_index < (SG_MAX_MIPMAPS * SG_MAX_TEXTUREARRAY_LAYERS)); SOKOL_ASSERT(subres_index < (SG_MAX_MIPMAPS * SG_MAX_TEXTUREARRAY_LAYERS));
const int mip_width = _sg_miplevel_dim(img->cmn.width, mip_index); const int mip_width = _sg_miplevel_dim(img->cmn.width, mip_index);
const int mip_height = _sg_miplevel_dim(img->cmn.height, mip_index); const int mip_height = _sg_miplevel_dim(img->cmn.height, mip_index);
const int src_pitch = _sg_row_pitch(img->cmn.pixel_format, mip_width, 1); const int src_row_pitch = _sg_row_pitch(img->cmn.pixel_format, mip_width, 1);
const int src_depth_pitch = _sg_surface_pitch(img->cmn.pixel_format, mip_width, mip_height, 1);
const sg_range* subimg_data = &(data->subimage[face_index][mip_index]); const sg_range* subimg_data = &(data->subimage[face_index][mip_index]);
const size_t slice_size = subimg_data->size / (size_t)num_slices; const size_t slice_size = subimg_data->size / (size_t)num_slices;
SOKOL_ASSERT(slice_size == (size_t)(src_depth_pitch * num_depth_slices));
const size_t slice_offset = slice_size * (size_t)slice_index; const size_t slice_offset = slice_size * (size_t)slice_index;
const uint8_t* slice_ptr = ((const uint8_t*)subimg_data->ptr) + slice_offset; const uint8_t* slice_ptr = ((const uint8_t*)subimg_data->ptr) + slice_offset;
hr = _sg_d3d11_Map(_sg.d3d11.ctx, img->d3d11.res, subres_index, D3D11_MAP_WRITE_DISCARD, 0, &d3d11_msr); hr = _sg_d3d11_Map(_sg.d3d11.ctx, img->d3d11.res, subres_index, D3D11_MAP_WRITE_DISCARD, 0, &d3d11_msr);
_sg_stats_add(d3d11.num_map, 1); _sg_stats_add(d3d11.num_map, 1);
if (SUCCEEDED(hr)) { if (SUCCEEDED(hr)) {
// FIXME: need to handle difference in depth-pitch for 3D textures as well! const uint8_t* src_ptr = slice_ptr;
if (src_pitch == (int)d3d11_msr.RowPitch) { uint8_t* dst_ptr = (uint8_t*)d3d11_msr.pData;
memcpy(d3d11_msr.pData, slice_ptr, slice_size); for (int depth_index = 0; depth_index < num_depth_slices; depth_index++) {
} else { if (src_row_pitch == (int)d3d11_msr.RowPitch) {
SOKOL_ASSERT(src_pitch < (int)d3d11_msr.RowPitch); const size_t copy_size = slice_size / (size_t)num_depth_slices;
const uint8_t* src_ptr = slice_ptr; SOKOL_ASSERT((copy_size * (size_t)num_depth_slices) == slice_size);
uint8_t* dst_ptr = (uint8_t*) d3d11_msr.pData; memcpy(dst_ptr, src_ptr, copy_size);
for (int row_index = 0; row_index < mip_height; row_index++) { } else {
memcpy(dst_ptr, src_ptr, (size_t)src_pitch); SOKOL_ASSERT(src_row_pitch < (int)d3d11_msr.RowPitch);
src_ptr += src_pitch; const uint8_t* src_row_ptr = src_ptr;
dst_ptr += d3d11_msr.RowPitch; uint8_t* dst_row_ptr = dst_ptr;
for (int row_index = 0; row_index < mip_height; row_index++) {
memcpy(dst_row_ptr, src_row_ptr, (size_t)src_row_pitch);
src_row_ptr += src_row_pitch;
dst_row_ptr += d3d11_msr.RowPitch;
}
} }
src_ptr += src_depth_pitch;
dst_ptr += d3d11_msr.DepthPitch;
} }
_sg_d3d11_Unmap(_sg.d3d11.ctx, img->d3d11.res, subres_index); _sg_d3d11_Unmap(_sg.d3d11.ctx, img->d3d11.res, subres_index);
_sg_stats_add(d3d11.num_unmap, 1); _sg_stats_add(d3d11.num_unmap, 1);
@ -11853,8 +11900,6 @@ _SOKOL_PRIVATE MTLSamplerMinMagFilter _sg_mtl_minmag_filter(sg_filter f) {
_SOKOL_PRIVATE MTLSamplerMipFilter _sg_mtl_mipmap_filter(sg_filter f) { _SOKOL_PRIVATE MTLSamplerMipFilter _sg_mtl_mipmap_filter(sg_filter f) {
switch (f) { switch (f) {
case SG_FILTER_NONE:
return MTLSamplerMipFilterNotMipmapped;
case SG_FILTER_NEAREST: case SG_FILTER_NEAREST:
return MTLSamplerMipFilterNearest; return MTLSamplerMipFilterNearest;
case SG_FILTER_LINEAR: case SG_FILTER_LINEAR:
@ -13410,7 +13455,6 @@ _SOKOL_PRIVATE WGPUFilterMode _sg_wgpu_sampler_minmag_filter(sg_filter f) {
_SOKOL_PRIVATE WGPUMipmapFilterMode _sg_wgpu_sampler_mipmap_filter(sg_filter f) { _SOKOL_PRIVATE WGPUMipmapFilterMode _sg_wgpu_sampler_mipmap_filter(sg_filter f) {
switch (f) { switch (f) {
case SG_FILTER_NONE:
case SG_FILTER_NEAREST: case SG_FILTER_NEAREST:
return WGPUMipmapFilterMode_Nearest; return WGPUMipmapFilterMode_Nearest;
case SG_FILTER_LINEAR: case SG_FILTER_LINEAR:
@ -14005,6 +14049,26 @@ _SOKOL_PRIVATE uint64_t _sg_wgpu_hash(const void* key, int len, uint64_t seed) {
return h; return h;
} }
_SOKOL_PRIVATE uint64_t _sg_wgpu_bindgroups_cache_item(_sg_wgpu_bindgroups_cache_item_type_t type, uint32_t id) {
return (((uint64_t)type) << 32) | id;
}
_SOKOL_PRIVATE uint64_t _sg_wgpu_bindgroups_cache_pip_item(uint32_t id) {
return _sg_wgpu_bindgroups_cache_item(_SG_WGPU_BINDGROUPSCACHEITEMTYPE_PIPELINE, id);
}
_SOKOL_PRIVATE uint64_t _sg_wgpu_bindgroups_cache_image_item(uint32_t id) {
return _sg_wgpu_bindgroups_cache_item(_SG_WGPU_BINDGROUPSCACHEITEMTYPE_IMAGE, id);
}
_SOKOL_PRIVATE uint64_t _sg_wgpu_bindgroups_cache_sampler_item(uint32_t id) {
return _sg_wgpu_bindgroups_cache_item(_SG_WGPU_BINDGROUPSCACHEITEMTYPE_SAMPLER, id);
}
_SOKOL_PRIVATE uint64_t _sg_wgpu_bindgroups_cache_sbuf_item(uint32_t id) {
return _sg_wgpu_bindgroups_cache_item(_SG_WGPU_BINDGROUPSCACHEITEMTYPE_STORAGEBUFFER, id);
}
_SOKOL_PRIVATE void _sg_wgpu_init_bindgroups_cache_key(_sg_wgpu_bindgroups_cache_key_t* key, const _sg_bindings_t* bnd) { _SOKOL_PRIVATE void _sg_wgpu_init_bindgroups_cache_key(_sg_wgpu_bindgroups_cache_key_t* key, const _sg_bindings_t* bnd) {
SOKOL_ASSERT(bnd); SOKOL_ASSERT(bnd);
SOKOL_ASSERT(bnd->pip); SOKOL_ASSERT(bnd->pip);
@ -14016,38 +14080,39 @@ _SOKOL_PRIVATE void _sg_wgpu_init_bindgroups_cache_key(_sg_wgpu_bindgroups_cache
SOKOL_ASSERT(bnd->num_fs_sbufs <= SG_MAX_SHADERSTAGE_STORAGEBUFFERS); SOKOL_ASSERT(bnd->num_fs_sbufs <= SG_MAX_SHADERSTAGE_STORAGEBUFFERS);
_sg_clear(key->items, sizeof(key->items)); _sg_clear(key->items, sizeof(key->items));
key->items[0] = bnd->pip->slot.id; int item_idx = 0;
const int vs_imgs_offset = 1; key->items[item_idx++] = _sg_wgpu_bindgroups_cache_pip_item(bnd->pip->slot.id);
const int vs_smps_offset = vs_imgs_offset + SG_MAX_SHADERSTAGE_IMAGES;
const int vs_sbufs_offset = vs_smps_offset + SG_MAX_SHADERSTAGE_SAMPLERS;
const int fs_imgs_offset = vs_sbufs_offset + SG_MAX_SHADERSTAGE_STORAGEBUFFERS;
const int fs_smps_offset = fs_imgs_offset + SG_MAX_SHADERSTAGE_IMAGES;
const int fs_sbufs_offset = fs_smps_offset + SG_MAX_SHADERSTAGE_SAMPLERS;
SOKOL_ASSERT((fs_sbufs_offset + SG_MAX_SHADERSTAGE_STORAGEBUFFERS) == _SG_WGPU_BINDGROUPSCACHE_NUM_ITEMS);
for (int i = 0; i < bnd->num_vs_imgs; i++) { for (int i = 0; i < bnd->num_vs_imgs; i++) {
SOKOL_ASSERT(bnd->vs_imgs[i]); SOKOL_ASSERT(bnd->vs_imgs[i]);
key->items[vs_imgs_offset + i] = bnd->vs_imgs[i]->slot.id; SOKOL_ASSERT(item_idx < _SG_WGPU_BINDGROUPSCACHEKEY_NUM_ITEMS);
key->items[item_idx++] = _sg_wgpu_bindgroups_cache_image_item(bnd->vs_imgs[i]->slot.id);
} }
for (int i = 0; i < bnd->num_vs_smps; i++) { for (int i = 0; i < bnd->num_vs_smps; i++) {
SOKOL_ASSERT(bnd->vs_smps[i]); SOKOL_ASSERT(bnd->vs_smps[i]);
key->items[vs_smps_offset + i] = bnd->vs_smps[i]->slot.id; SOKOL_ASSERT(item_idx < _SG_WGPU_BINDGROUPSCACHEKEY_NUM_ITEMS);
key->items[item_idx++] = _sg_wgpu_bindgroups_cache_sampler_item(bnd->vs_smps[i]->slot.id);
} }
for (int i = 0; i < bnd->num_vs_sbufs; i++) { for (int i = 0; i < bnd->num_vs_sbufs; i++) {
SOKOL_ASSERT(bnd->vs_sbufs[i]); SOKOL_ASSERT(bnd->vs_sbufs[i]);
key->items[vs_sbufs_offset + i] = bnd->vs_sbufs[i]->slot.id; SOKOL_ASSERT(item_idx < _SG_WGPU_BINDGROUPSCACHEKEY_NUM_ITEMS);
key->items[item_idx++] = _sg_wgpu_bindgroups_cache_sbuf_item(bnd->vs_sbufs[i]->slot.id);
} }
for (int i = 0; i < bnd->num_fs_imgs; i++) { for (int i = 0; i < bnd->num_fs_imgs; i++) {
SOKOL_ASSERT(bnd->fs_imgs[i]); SOKOL_ASSERT(bnd->fs_imgs[i]);
key->items[fs_imgs_offset + i] = bnd->fs_imgs[i]->slot.id; SOKOL_ASSERT(item_idx < _SG_WGPU_BINDGROUPSCACHEKEY_NUM_ITEMS);
key->items[item_idx++] = _sg_wgpu_bindgroups_cache_image_item(bnd->fs_imgs[i]->slot.id);
} }
for (int i = 0; i < bnd->num_fs_smps; i++) { for (int i = 0; i < bnd->num_fs_smps; i++) {
SOKOL_ASSERT(bnd->fs_smps[i]); SOKOL_ASSERT(bnd->fs_smps[i]);
key->items[fs_smps_offset + i] = bnd->fs_smps[i]->slot.id; SOKOL_ASSERT(item_idx < _SG_WGPU_BINDGROUPSCACHEKEY_NUM_ITEMS);
key->items[item_idx++] = _sg_wgpu_bindgroups_cache_sampler_item(bnd->fs_smps[i]->slot.id);
} }
for (int i = 0; i < bnd->num_fs_sbufs; i++) { for (int i = 0; i < bnd->num_fs_sbufs; i++) {
SOKOL_ASSERT(bnd->fs_sbufs[i]); SOKOL_ASSERT(bnd->fs_sbufs[i]);
key->items[fs_sbufs_offset + i] = bnd->fs_sbufs[i]->slot.id; SOKOL_ASSERT(item_idx < _SG_WGPU_BINDGROUPSCACHEKEY_NUM_ITEMS);
key->items[item_idx++] = _sg_wgpu_bindgroups_cache_sbuf_item(bnd->fs_sbufs[i]->slot.id);
} }
SOKOL_ASSERT(item_idx == (1 + bnd->num_vs_imgs + bnd->num_vs_smps + bnd->num_vs_sbufs + bnd->num_fs_imgs + bnd->num_fs_smps + bnd->num_fs_sbufs));
key->hash = _sg_wgpu_hash(&key->items, (int)sizeof(key->items), 0x1234567887654321); key->hash = _sg_wgpu_hash(&key->items, (int)sizeof(key->items), 0x1234567887654321);
} }
@ -14199,6 +14264,33 @@ _SOKOL_PRIVATE uint32_t _sg_wgpu_bindgroups_cache_get(uint64_t hash) {
return _sg.wgpu.bindgroups_cache.items[index].id; return _sg.wgpu.bindgroups_cache.items[index].id;
} }
// called from wgpu resource destroy functions to also invalidate any
// bindgroups cache slot and bindgroup referencing that resource
_SOKOL_PRIVATE void _sg_wgpu_bindgroups_cache_invalidate(_sg_wgpu_bindgroups_cache_item_type_t type, uint32_t id) {
const uint64_t key_item = _sg_wgpu_bindgroups_cache_item(type, id);
SOKOL_ASSERT(_sg.wgpu.bindgroups_cache.items);
for (uint32_t cache_item_idx = 0; cache_item_idx < _sg.wgpu.bindgroups_cache.num; cache_item_idx++) {
const uint32_t bg_id = _sg.wgpu.bindgroups_cache.items[cache_item_idx].id;
if (bg_id != SG_INVALID_ID) {
_sg_wgpu_bindgroup_t* bg = _sg_wgpu_lookup_bindgroup(bg_id);
SOKOL_ASSERT(bg && (bg->slot.state == SG_RESOURCESTATE_VALID));
// check if resource is in bindgroup, if yes discard bindgroup and invalidate cache slot
bool invalidate_cache_item = false;
for (int key_item_idx = 0; key_item_idx < _SG_WGPU_BINDGROUPSCACHEKEY_NUM_ITEMS; key_item_idx++) {
if (bg->key.items[key_item_idx] == key_item) {
invalidate_cache_item = true;
break;
}
}
if (invalidate_cache_item) {
_sg_wgpu_discard_bindgroup(bg); bg = 0;
_sg_wgpu_bindgroups_cache_set(cache_item_idx, SG_INVALID_ID);
_sg_stats_add(wgpu.bindings.num_bindgroup_cache_invalidates, 1);
}
}
}
}
_SOKOL_PRIVATE void _sg_wgpu_bindings_cache_clear(void) { _SOKOL_PRIVATE void _sg_wgpu_bindings_cache_clear(void) {
memset(&_sg.wgpu.bindings_cache, 0, sizeof(_sg.wgpu.bindings_cache)); memset(&_sg.wgpu.bindings_cache, 0, sizeof(_sg.wgpu.bindings_cache));
} }
@ -14259,7 +14351,7 @@ _SOKOL_PRIVATE void _sg_wgpu_bindings_cache_bg_update(const _sg_wgpu_bindgroup_t
} }
} }
_SOKOL_PRIVATE void _sg_wgpu_set_bindings_bindgroup(_sg_wgpu_bindgroup_t* bg) { _SOKOL_PRIVATE void _sg_wgpu_set_bindgroup(_sg_wgpu_bindgroup_t* bg) {
if (_sg_wgpu_bindings_cache_bg_dirty(bg)) { if (_sg_wgpu_bindings_cache_bg_dirty(bg)) {
_sg_wgpu_bindings_cache_bg_update(bg); _sg_wgpu_bindings_cache_bg_update(bg);
_sg_stats_add(wgpu.bindings.num_set_bindgroup, 1); _sg_stats_add(wgpu.bindings.num_set_bindgroup, 1);
@ -14305,7 +14397,7 @@ _SOKOL_PRIVATE bool _sg_wgpu_apply_bindgroup(_sg_bindings_t* bnd) {
_sg_wgpu_bindgroups_cache_set(key.hash, bg->slot.id); _sg_wgpu_bindgroups_cache_set(key.hash, bg->slot.id);
} }
if (bg && bg->slot.state == SG_RESOURCESTATE_VALID) { if (bg && bg->slot.state == SG_RESOURCESTATE_VALID) {
_sg_wgpu_set_bindings_bindgroup(bg); _sg_wgpu_set_bindgroup(bg);
} else { } else {
return false; return false;
} }
@ -14314,7 +14406,7 @@ _SOKOL_PRIVATE bool _sg_wgpu_apply_bindgroup(_sg_bindings_t* bnd) {
_sg_wgpu_bindgroup_t* bg = _sg_wgpu_create_bindgroup(bnd); _sg_wgpu_bindgroup_t* bg = _sg_wgpu_create_bindgroup(bnd);
if (bg) { if (bg) {
if (bg->slot.state == SG_RESOURCESTATE_VALID) { if (bg->slot.state == SG_RESOURCESTATE_VALID) {
_sg_wgpu_set_bindings_bindgroup(bg); _sg_wgpu_set_bindgroup(bg);
} }
_sg_wgpu_discard_bindgroup(bg); _sg_wgpu_discard_bindgroup(bg);
} else { } else {
@ -14322,7 +14414,7 @@ _SOKOL_PRIVATE bool _sg_wgpu_apply_bindgroup(_sg_bindings_t* bnd) {
} }
} }
} else { } else {
_sg_wgpu_set_bindings_bindgroup(0); _sg_wgpu_set_bindgroup(0);
} }
return true; return true;
} }
@ -14455,8 +14547,10 @@ _SOKOL_PRIVATE sg_resource_state _sg_wgpu_create_buffer(_sg_buffer_t* buf, const
_SOKOL_PRIVATE void _sg_wgpu_discard_buffer(_sg_buffer_t* buf) { _SOKOL_PRIVATE void _sg_wgpu_discard_buffer(_sg_buffer_t* buf) {
SOKOL_ASSERT(buf); SOKOL_ASSERT(buf);
if (buf->cmn.type == SG_BUFFERTYPE_STORAGEBUFFER) {
_sg_wgpu_bindgroups_cache_invalidate(_SG_WGPU_BINDGROUPSCACHEITEMTYPE_STORAGEBUFFER, buf->slot.id);
}
if (buf->wgpu.buf) { if (buf->wgpu.buf) {
wgpuBufferDestroy(buf->wgpu.buf);
wgpuBufferRelease(buf->wgpu.buf); wgpuBufferRelease(buf->wgpu.buf);
} }
} }
@ -14592,12 +14686,12 @@ _SOKOL_PRIVATE sg_resource_state _sg_wgpu_create_image(_sg_image_t* img, const s
_SOKOL_PRIVATE void _sg_wgpu_discard_image(_sg_image_t* img) { _SOKOL_PRIVATE void _sg_wgpu_discard_image(_sg_image_t* img) {
SOKOL_ASSERT(img); SOKOL_ASSERT(img);
_sg_wgpu_bindgroups_cache_invalidate(_SG_WGPU_BINDGROUPSCACHEITEMTYPE_IMAGE, img->slot.id);
if (img->wgpu.view) { if (img->wgpu.view) {
wgpuTextureViewRelease(img->wgpu.view); wgpuTextureViewRelease(img->wgpu.view);
img->wgpu.view = 0; img->wgpu.view = 0;
} }
if (img->wgpu.tex) { if (img->wgpu.tex) {
wgpuTextureDestroy(img->wgpu.tex);
wgpuTextureRelease(img->wgpu.tex); wgpuTextureRelease(img->wgpu.tex);
img->wgpu.tex = 0; img->wgpu.tex = 0;
} }
@ -14638,6 +14732,7 @@ _SOKOL_PRIVATE sg_resource_state _sg_wgpu_create_sampler(_sg_sampler_t* smp, con
_SOKOL_PRIVATE void _sg_wgpu_discard_sampler(_sg_sampler_t* smp) { _SOKOL_PRIVATE void _sg_wgpu_discard_sampler(_sg_sampler_t* smp) {
SOKOL_ASSERT(smp); SOKOL_ASSERT(smp);
_sg_wgpu_bindgroups_cache_invalidate(_SG_WGPU_BINDGROUPSCACHEITEMTYPE_SAMPLER, smp->slot.id);
if (smp->wgpu.smp) { if (smp->wgpu.smp) {
wgpuSamplerRelease(smp->wgpu.smp); wgpuSamplerRelease(smp->wgpu.smp);
smp->wgpu.smp = 0; smp->wgpu.smp = 0;
@ -14875,6 +14970,7 @@ _SOKOL_PRIVATE sg_resource_state _sg_wgpu_create_pipeline(_sg_pipeline_t* pip, _
_SOKOL_PRIVATE void _sg_wgpu_discard_pipeline(_sg_pipeline_t* pip) { _SOKOL_PRIVATE void _sg_wgpu_discard_pipeline(_sg_pipeline_t* pip) {
SOKOL_ASSERT(pip); SOKOL_ASSERT(pip);
_sg_wgpu_bindgroups_cache_invalidate(_SG_WGPU_BINDGROUPSCACHEITEMTYPE_PIPELINE, pip->slot.id);
if (pip == _sg.wgpu.cur_pipeline) { if (pip == _sg.wgpu.cur_pipeline) {
_sg.wgpu.cur_pipeline = 0; _sg.wgpu.cur_pipeline = 0;
_sg.wgpu.cur_pipeline_id.id = SG_INVALID_ID; _sg.wgpu.cur_pipeline_id.id = SG_INVALID_ID;
@ -16219,8 +16315,6 @@ _SOKOL_PRIVATE bool _sg_validate_sampler_desc(const sg_sampler_desc* desc) {
_sg_validate_begin(); _sg_validate_begin();
_SG_VALIDATE(desc->_start_canary == 0, VALIDATE_SAMPLERDESC_CANARY); _SG_VALIDATE(desc->_start_canary == 0, VALIDATE_SAMPLERDESC_CANARY);
_SG_VALIDATE(desc->_end_canary == 0, VALIDATE_SAMPLERDESC_CANARY); _SG_VALIDATE(desc->_end_canary == 0, VALIDATE_SAMPLERDESC_CANARY);
_SG_VALIDATE(desc->min_filter != SG_FILTER_NONE, VALIDATE_SAMPLERDESC_MINFILTER_NONE);
_SG_VALIDATE(desc->mag_filter != SG_FILTER_NONE, VALIDATE_SAMPLERDESC_MAGFILTER_NONE);
// restriction from WebGPU: when anisotropy > 1, all filters must be linear // restriction from WebGPU: when anisotropy > 1, all filters must be linear
if (desc->max_anisotropy > 1) { if (desc->max_anisotropy > 1) {
_SG_VALIDATE((desc->min_filter == SG_FILTER_LINEAR) _SG_VALIDATE((desc->min_filter == SG_FILTER_LINEAR)
@ -17040,7 +17134,7 @@ _SOKOL_PRIVATE sg_sampler_desc _sg_sampler_desc_defaults(const sg_sampler_desc*
sg_sampler_desc def = *desc; sg_sampler_desc def = *desc;
def.min_filter = _sg_def(def.min_filter, SG_FILTER_NEAREST); def.min_filter = _sg_def(def.min_filter, SG_FILTER_NEAREST);
def.mag_filter = _sg_def(def.mag_filter, SG_FILTER_NEAREST); def.mag_filter = _sg_def(def.mag_filter, SG_FILTER_NEAREST);
def.mipmap_filter = _sg_def(def.mipmap_filter, SG_FILTER_NONE); def.mipmap_filter = _sg_def(def.mipmap_filter, SG_FILTER_NEAREST);
def.wrap_u = _sg_def(def.wrap_u, SG_WRAP_REPEAT); def.wrap_u = _sg_def(def.wrap_u, SG_WRAP_REPEAT);
def.wrap_v = _sg_def(def.wrap_v, SG_WRAP_REPEAT); def.wrap_v = _sg_def(def.wrap_v, SG_WRAP_REPEAT);
def.wrap_w = _sg_def(def.wrap_w, SG_WRAP_REPEAT); def.wrap_w = _sg_def(def.wrap_w, SG_WRAP_REPEAT);

View file

@ -1661,7 +1661,6 @@ static int _sfons_render_create(void* user_ptr, int width, int height) {
_sfons_clear(&smp_desc, sizeof(smp_desc)); _sfons_clear(&smp_desc, sizeof(smp_desc));
smp_desc.min_filter = SG_FILTER_LINEAR; smp_desc.min_filter = SG_FILTER_LINEAR;
smp_desc.mag_filter = SG_FILTER_LINEAR; smp_desc.mag_filter = SG_FILTER_LINEAR;
smp_desc.mipmap_filter = SG_FILTER_NONE;
sfons->smp = sg_make_sampler(&smp_desc); sfons->smp = sg_make_sampler(&smp_desc);
} }

View file

@ -1287,7 +1287,6 @@ _SOKOL_PRIVATE const char* _sgimgui_pixelformat_string(sg_pixel_format fmt) {
_SOKOL_PRIVATE const char* _sgimgui_filter_string(sg_filter f) { _SOKOL_PRIVATE const char* _sgimgui_filter_string(sg_filter f) {
switch (f) { switch (f) {
case SG_FILTER_NONE: return "SG_FILTER_NONE";
case SG_FILTER_NEAREST: return "SG_FILTER_NEAREST"; case SG_FILTER_NEAREST: return "SG_FILTER_NEAREST";
case SG_FILTER_LINEAR: return "SG_FILTER_LINEAR"; case SG_FILTER_LINEAR: return "SG_FILTER_LINEAR";
default: return "???"; default: return "???";
@ -4287,7 +4286,7 @@ _SOKOL_PRIVATE void _sgimgui_draw_frame_stats_panel(sgimgui_t* ctx) {
ImGuiTableFlags_SizingFixedFit | ImGuiTableFlags_SizingFixedFit |
ImGuiTableFlags_Borders; ImGuiTableFlags_Borders;
if (igBeginTable("##frame_stats_table", 2, flags, IMVEC2(0, 0), 0)) { if (igBeginTable("##frame_stats_table", 2, flags, IMVEC2(0, 0), 0)) {
igTableSetupScrollFreeze(0, 2); igTableSetupScrollFreeze(0, 1);
igTableSetupColumn("key", ImGuiTableColumnFlags_None, 0, 0); igTableSetupColumn("key", ImGuiTableColumnFlags_None, 0, 0);
igTableSetupColumn("value", ImGuiTableColumnFlags_None, 0, 0); igTableSetupColumn("value", ImGuiTableColumnFlags_None, 0, 0);
igTableHeadersRow(); igTableHeadersRow();
@ -4335,6 +4334,7 @@ _SOKOL_PRIVATE void _sgimgui_draw_frame_stats_panel(sgimgui_t* ctx) {
_sgimgui_frame_stats(wgpu.bindings.num_bindgroup_cache_hits); _sgimgui_frame_stats(wgpu.bindings.num_bindgroup_cache_hits);
_sgimgui_frame_stats(wgpu.bindings.num_bindgroup_cache_misses); _sgimgui_frame_stats(wgpu.bindings.num_bindgroup_cache_misses);
_sgimgui_frame_stats(wgpu.bindings.num_bindgroup_cache_collisions); _sgimgui_frame_stats(wgpu.bindings.num_bindgroup_cache_collisions);
_sgimgui_frame_stats(wgpu.bindings.num_bindgroup_cache_invalidates);
_sgimgui_frame_stats(wgpu.bindings.num_bindgroup_cache_hash_vs_key_mismatch); _sgimgui_frame_stats(wgpu.bindings.num_bindgroup_cache_hash_vs_key_mismatch);
break; break;
case SG_BACKEND_METAL_MACOS: case SG_BACKEND_METAL_MACOS:

View file

@ -372,8 +372,8 @@
the last call to sgl_draw() through sokol-gfx, and will 'rewind' the internal the last call to sgl_draw() through sokol-gfx, and will 'rewind' the internal
vertex-, uniform- and command-buffers. vertex-, uniform- and command-buffers.
--- each sokol-gl context tracks an internal error code, to query the --- each sokol-gl context tracks internal error states which can
current error code for the currently active context call: be obtains via:
sgl_error_t sgl_error() sgl_error_t sgl_error()
@ -381,18 +381,28 @@
sgl_error_t sgl_context_error(ctx); sgl_error_t sgl_context_error(ctx);
...which can return the following error codes: ...this returns a struct with the following booleans:
SGL_NO_ERROR - all OK, no error occurred since last sgl_draw() .any - true if any of the below errors is true
SGL_ERROR_VERTICES_FULL - internal vertex buffer is full (checked in sgl_end()) .vertices_full - internal vertex buffer is full (checked in sgl_end())
SGL_ERROR_UNIFORMS_FULL - the internal uniforms buffer is full (checked in sgl_end()) .uniforms_full - the internal uniforms buffer is full (checked in sgl_end())
SGL_ERROR_COMMANDS_FULL - the internal command buffer is full (checked in sgl_end()) .commands_full - the internal command buffer is full (checked in sgl_end())
SGL_ERROR_STACK_OVERFLOW - matrix- or pipeline-stack overflow .stack_overflow - matrix- or pipeline-stack overflow
SGL_ERROR_STACK_UNDERFLOW - matrix- or pipeline-stack underflow .stack_underflow - matrix- or pipeline-stack underflow
SGL_ERROR_NO_CONTEXT - the active context no longer exists .no_context - the active context no longer exists
...if sokol-gl is in an error-state, sgl_draw() will skip any rendering, ...depending on the above error state, sgl_draw() may skip rendering
and reset the error code to SGL_NO_ERROR. completely, or only draw partial geometry
--- you can get the number of recorded vertices and draw commands in the current
frame and active sokol-gl context via:
int sgl_num_vertices()
int sgl_num_commands()
...this allows you to check whether the vertex or command pools are running
full before the overflow actually happens (in this case you could also
check the error booleans in the result of sgl_error()).
RENDER LAYERS RENDER LAYERS
============= =============
@ -762,14 +772,14 @@ typedef struct sgl_context { uint32_t id; } sgl_context;
Errors are reset each frame after calling sgl_draw(), Errors are reset each frame after calling sgl_draw(),
get the last error code with sgl_error() get the last error code with sgl_error()
*/ */
typedef enum sgl_error_t { typedef struct sgl_error_t {
SGL_NO_ERROR = 0, bool any;
SGL_ERROR_VERTICES_FULL, bool vertices_full;
SGL_ERROR_UNIFORMS_FULL, bool uniforms_full;
SGL_ERROR_COMMANDS_FULL, bool commands_full;
SGL_ERROR_STACK_OVERFLOW, bool stack_overflow;
SGL_ERROR_STACK_UNDERFLOW, bool stack_underflow;
SGL_ERROR_NO_CONTEXT, bool no_context;
} sgl_error_t; } sgl_error_t;
/* /*
@ -832,6 +842,10 @@ SOKOL_GL_API_DECL void sgl_set_context(sgl_context ctx);
SOKOL_GL_API_DECL sgl_context sgl_get_context(void); SOKOL_GL_API_DECL sgl_context sgl_get_context(void);
SOKOL_GL_API_DECL sgl_context sgl_default_context(void); SOKOL_GL_API_DECL sgl_context sgl_default_context(void);
/* get information about recorded vertices and commands in current context */
SOKOL_GL_API_DECL int sgl_num_vertices(void);
SOKOL_GL_API_DECL int sgl_num_commands(void);
/* draw recorded commands (call inside a sokol-gfx render pass) */ /* draw recorded commands (call inside a sokol-gfx render pass) */
SOKOL_GL_API_DECL void sgl_draw(void); SOKOL_GL_API_DECL void sgl_draw(void);
SOKOL_GL_API_DECL void sgl_context_draw(sgl_context ctx); SOKOL_GL_API_DECL void sgl_context_draw(sgl_context ctx);
@ -2342,7 +2356,7 @@ typedef struct {
/* state tracking */ /* state tracking */
int base_vertex; int base_vertex;
int vtx_count; /* number of times vtx function has been called, used for non-triangle primitives */ int quad_vtx_count; /* number of times vtx function has been called, used for non-triangle primitives */
sgl_error_t error; sgl_error_t error;
bool in_begin; bool in_begin;
int layer_id; int layer_id;
@ -2903,10 +2917,24 @@ static void _sgl_destroy_context(sgl_context ctx_id) {
// ██ ██ ██ ███████ ██████ // ██ ██ ██ ███████ ██████
// //
// >>misc // >>misc
static sgl_error_t _sgl_error_defaults(void) {
sgl_error_t defaults = {0};
return defaults;
}
static int _sgl_num_vertices(_sgl_context_t* ctx) {
return ctx->vertices.next;
}
static int _sgl_num_commands(_sgl_context_t* ctx) {
return ctx->commands.next;
}
static void _sgl_begin(_sgl_context_t* ctx, _sgl_primitive_type_t mode) { static void _sgl_begin(_sgl_context_t* ctx, _sgl_primitive_type_t mode) {
ctx->in_begin = true; ctx->in_begin = true;
ctx->base_vertex = ctx->vertices.next; ctx->base_vertex = ctx->vertices.next;
ctx->vtx_count = 0; ctx->quad_vtx_count = 0;
ctx->cur_prim_type = mode; ctx->cur_prim_type = mode;
} }
@ -2916,7 +2944,7 @@ static void _sgl_rewind(_sgl_context_t* ctx) {
ctx->uniforms.next = 0; ctx->uniforms.next = 0;
ctx->commands.next = 0; ctx->commands.next = 0;
ctx->base_vertex = 0; ctx->base_vertex = 0;
ctx->error = SGL_NO_ERROR; ctx->error = _sgl_error_defaults();
ctx->layer_id = 0; ctx->layer_id = 0;
ctx->matrix_dirty = true; ctx->matrix_dirty = true;
} }
@ -2938,7 +2966,8 @@ static _sgl_vertex_t* _sgl_next_vertex(_sgl_context_t* ctx) {
if (ctx->vertices.next < ctx->vertices.cap) { if (ctx->vertices.next < ctx->vertices.cap) {
return &ctx->vertices.ptr[ctx->vertices.next++]; return &ctx->vertices.ptr[ctx->vertices.next++];
} else { } else {
ctx->error = SGL_ERROR_VERTICES_FULL; ctx->error.vertices_full = true;
ctx->error.any = true;
return 0; return 0;
} }
} }
@ -2947,7 +2976,8 @@ static _sgl_uniform_t* _sgl_next_uniform(_sgl_context_t* ctx) {
if (ctx->uniforms.next < ctx->uniforms.cap) { if (ctx->uniforms.next < ctx->uniforms.cap) {
return &ctx->uniforms.ptr[ctx->uniforms.next++]; return &ctx->uniforms.ptr[ctx->uniforms.next++];
} else { } else {
ctx->error = SGL_ERROR_UNIFORMS_FULL; ctx->error.uniforms_full = true;
ctx->error.any = true;
return 0; return 0;
} }
} }
@ -2964,7 +2994,8 @@ static _sgl_command_t* _sgl_next_command(_sgl_context_t* ctx) {
if (ctx->commands.next < ctx->commands.cap) { if (ctx->commands.next < ctx->commands.cap) {
return &ctx->commands.ptr[ctx->commands.next++]; return &ctx->commands.ptr[ctx->commands.next++];
} else { } else {
ctx->error = SGL_ERROR_COMMANDS_FULL; ctx->error.commands_full = true;
ctx->error.any = true;
return 0; return 0;
} }
} }
@ -2991,7 +3022,7 @@ static void _sgl_vtx(_sgl_context_t* ctx, float x, float y, float z, float u, fl
SOKOL_ASSERT(ctx->in_begin); SOKOL_ASSERT(ctx->in_begin);
_sgl_vertex_t* vtx; _sgl_vertex_t* vtx;
/* handle non-native primitive types */ /* handle non-native primitive types */
if ((ctx->cur_prim_type == SGL_PRIMITIVETYPE_QUADS) && ((ctx->vtx_count & 3) == 3)) { if ((ctx->cur_prim_type == SGL_PRIMITIVETYPE_QUADS) && ((ctx->quad_vtx_count & 3) == 3)) {
/* for quads, before writing the last quad vertex, reuse /* for quads, before writing the last quad vertex, reuse
the first and third vertex to start the second triangle in the quad the first and third vertex to start the second triangle in the quad
*/ */
@ -3007,7 +3038,7 @@ static void _sgl_vtx(_sgl_context_t* ctx, float x, float y, float z, float u, fl
vtx->rgba = rgba; vtx->rgba = rgba;
vtx->psize = ctx->point_size; vtx->psize = ctx->point_size;
} }
ctx->vtx_count++; ctx->quad_vtx_count++;
} }
static void _sgl_identity(_sgl_matrix_t* m) { static void _sgl_identity(_sgl_matrix_t* m) {
@ -3342,7 +3373,7 @@ static bool _sgl_is_default_context(sgl_context ctx_id) {
static void _sgl_draw(_sgl_context_t* ctx, int layer_id) { static void _sgl_draw(_sgl_context_t* ctx, int layer_id) {
SOKOL_ASSERT(ctx); SOKOL_ASSERT(ctx);
if ((ctx->error == SGL_NO_ERROR) && (ctx->vertices.next > 0) && (ctx->commands.next > 0)) { if ((ctx->vertices.next > 0) && (ctx->commands.next > 0)) {
sg_push_debug_group("sokol-gl"); sg_push_debug_group("sokol-gl");
uint32_t cur_pip_id = SG_INVALID_ID; uint32_t cur_pip_id = SG_INVALID_ID;
@ -3356,6 +3387,8 @@ static void _sgl_draw(_sgl_context_t* ctx, int layer_id) {
sg_update_buffer(ctx->vbuf, &range); sg_update_buffer(ctx->vbuf, &range);
} }
// render all successfully recorded commands (this may be less than the
// issued commands if we're in an error state)
for (int i = 0; i < ctx->commands.next; i++) { for (int i = 0; i < ctx->commands.next; i++) {
const _sgl_command_t* cmd = &ctx->commands.ptr[i]; const _sgl_command_t* cmd = &ctx->commands.ptr[i];
if (cmd->layer_id != layer_id) { if (cmd->layer_id != layer_id) {
@ -3463,7 +3496,10 @@ SOKOL_API_IMPL sgl_error_t sgl_error(void) {
if (ctx) { if (ctx) {
return ctx->error; return ctx->error;
} else { } else {
return SGL_ERROR_NO_CONTEXT; sgl_error_t err = _sgl_error_defaults();
err.no_context = true;
err.any = true;
return err;
} }
} }
@ -3472,7 +3508,10 @@ SOKOL_API_IMPL sgl_error_t sgl_context_error(sgl_context ctx_id) {
if (ctx) { if (ctx) {
return ctx->error; return ctx->error;
} else { } else {
return SGL_ERROR_NO_CONTEXT; sgl_error_t err = _sgl_error_defaults();
err.no_context = true;
err.any = true;
return err;
} }
} }
@ -3521,6 +3560,26 @@ SOKOL_API_IMPL sgl_context sgl_default_context(void) {
return SGL_DEFAULT_CONTEXT; return SGL_DEFAULT_CONTEXT;
} }
SOKOL_API_IMPL int sgl_num_vertices(void) {
SOKOL_ASSERT(_SGL_INIT_COOKIE == _sgl.init_cookie);
_sgl_context_t* ctx = _sgl.cur_ctx;
if (ctx) {
return _sgl_num_vertices(ctx);
} else {
return 0;
}
}
SOKOL_API_IMPL int sgl_num_commands(void) {
SOKOL_ASSERT(_SGL_INIT_COOKIE == _sgl.init_cookie);
_sgl_context_t* ctx = _sgl.cur_ctx;
if (ctx) {
return _sgl_num_commands(ctx);
} else {
return 0;
}
}
SOKOL_API_IMPL sgl_pipeline sgl_make_pipeline(const sg_pipeline_desc* desc) { SOKOL_API_IMPL sgl_pipeline sgl_make_pipeline(const sg_pipeline_desc* desc) {
SOKOL_ASSERT(_SGL_INIT_COOKIE == _sgl.init_cookie); SOKOL_ASSERT(_SGL_INIT_COOKIE == _sgl.init_cookie);
_sgl_context_t* ctx = _sgl.cur_ctx; _sgl_context_t* ctx = _sgl.cur_ctx;
@ -3576,7 +3635,8 @@ SOKOL_API_IMPL void sgl_push_pipeline(void) {
ctx->pip_tos++; ctx->pip_tos++;
ctx->pip_stack[ctx->pip_tos] = ctx->pip_stack[ctx->pip_tos-1]; ctx->pip_stack[ctx->pip_tos] = ctx->pip_stack[ctx->pip_tos-1];
} else { } else {
ctx->error = SGL_ERROR_STACK_OVERFLOW; ctx->error.stack_overflow = true;
ctx->error.any = true;
} }
} }
@ -3589,7 +3649,8 @@ SOKOL_API_IMPL void sgl_pop_pipeline(void) {
if (ctx->pip_tos > 0) { if (ctx->pip_tos > 0) {
ctx->pip_tos--; ctx->pip_tos--;
} else { } else {
ctx->error = SGL_ERROR_STACK_UNDERFLOW; ctx->error.stack_underflow = true;
ctx->error.any = true;
} }
} }
@ -3778,6 +3839,7 @@ SOKOL_API_IMPL void sgl_end(void) {
SOKOL_ASSERT(ctx->in_begin); SOKOL_ASSERT(ctx->in_begin);
SOKOL_ASSERT(ctx->vertices.next >= ctx->base_vertex); SOKOL_ASSERT(ctx->vertices.next >= ctx->base_vertex);
ctx->in_begin = false; ctx->in_begin = false;
bool matrix_dirty = ctx->matrix_dirty; bool matrix_dirty = ctx->matrix_dirty;
if (matrix_dirty) { if (matrix_dirty) {
ctx->matrix_dirty = false; ctx->matrix_dirty = false;
@ -3787,6 +3849,12 @@ SOKOL_API_IMPL void sgl_end(void) {
uni->tm = *_sgl_matrix_texture(ctx); uni->tm = *_sgl_matrix_texture(ctx);
} }
} }
// don't record any new commands when we're in an error state
if (ctx->error.any) {
return;
}
// check if command can be merged with current command // check if command can be merged with current command
sg_pipeline pip = _sgl_get_pipeline(ctx->pip_stack[ctx->pip_tos], ctx->cur_prim_type); sg_pipeline pip = _sgl_get_pipeline(ctx->pip_stack[ctx->pip_tos], ctx->cur_prim_type);
sg_image img = ctx->texturing_enabled ? ctx->cur_img : _sgl.def_img; sg_image img = ctx->texturing_enabled ? ctx->cur_img : _sgl.def_img;
@ -4205,7 +4273,8 @@ SOKOL_GL_API_DECL void sgl_push_matrix(void) {
_sgl_matrix_t* dst = _sgl_matrix(ctx); _sgl_matrix_t* dst = _sgl_matrix(ctx);
*dst = *src; *dst = *src;
} else { } else {
ctx->error = SGL_ERROR_STACK_OVERFLOW; ctx->error.stack_overflow = true;
ctx->error.any = true;
} }
} }
@ -4220,7 +4289,8 @@ SOKOL_GL_API_DECL void sgl_pop_matrix(void) {
if (ctx->matrix_tos[ctx->cur_matrix_mode] > 0) { if (ctx->matrix_tos[ctx->cur_matrix_mode] > 0) {
ctx->matrix_tos[ctx->cur_matrix_mode]--; ctx->matrix_tos[ctx->cur_matrix_mode]--;
} else { } else {
ctx->error = SGL_ERROR_STACK_UNDERFLOW; ctx->error.stack_underflow = true;
ctx->error.any = true;
} }
} }

View file

@ -1844,13 +1844,13 @@ static const char* _simgui_fs_source_dummy = "";
#endif #endif
#if !defined(SOKOL_IMGUI_NO_SOKOL_APP) #if !defined(SOKOL_IMGUI_NO_SOKOL_APP)
static void _simgui_set_clipboard(void* user_data, const char* text) { static void _simgui_set_clipboard(ImGuiContext* ctx, const char* text) {
(void)user_data; (void)ctx;
sapp_set_clipboard_string(text); sapp_set_clipboard_string(text);
} }
static const char* _simgui_get_clipboard(void* user_data) { static const char* _simgui_get_clipboard(ImGuiContext* ctx) {
(void)user_data; (void)ctx;
return sapp_get_clipboard_string(); return sapp_get_clipboard_string();
} }
#endif #endif
@ -2200,6 +2200,7 @@ SOKOL_API_IMPL void simgui_setup(const simgui_desc_t* desc) {
ImGui::CreateContext(); ImGui::CreateContext();
ImGui::StyleColorsDark(); ImGui::StyleColorsDark();
ImGuiIO* io = &ImGui::GetIO(); ImGuiIO* io = &ImGui::GetIO();
ImGuiPlatformIO* pio = &ImGui::GetPlatformIO();
if (!_simgui.desc.no_default_font) { if (!_simgui.desc.no_default_font) {
io->Fonts->AddFontDefault(); io->Fonts->AddFontDefault();
} }
@ -2207,6 +2208,7 @@ SOKOL_API_IMPL void simgui_setup(const simgui_desc_t* desc) {
igCreateContext(NULL); igCreateContext(NULL);
igStyleColorsDark(igGetStyle()); igStyleColorsDark(igGetStyle());
ImGuiIO* io = igGetIO(); ImGuiIO* io = igGetIO();
ImGuiPlatformIO* pio = igGetPlatformIO();
if (!_simgui.desc.no_default_font) { if (!_simgui.desc.no_default_font) {
ImFontAtlas_AddFontDefault(io->Fonts, NULL); ImFontAtlas_AddFontDefault(io->Fonts, NULL);
} }
@ -2218,8 +2220,8 @@ SOKOL_API_IMPL void simgui_setup(const simgui_desc_t* desc) {
if (!_simgui.desc.disable_set_mouse_cursor) { if (!_simgui.desc.disable_set_mouse_cursor) {
io->BackendFlags |= ImGuiBackendFlags_HasMouseCursors; io->BackendFlags |= ImGuiBackendFlags_HasMouseCursors;
} }
io->SetClipboardTextFn = _simgui_set_clipboard; pio->Platform_SetClipboardTextFn = _simgui_set_clipboard;
io->GetClipboardTextFn = _simgui_get_clipboard; pio->Platform_GetClipboardTextFn = _simgui_get_clipboard;
#endif #endif
io->ConfigWindowsResizeFromEdges = !_simgui.desc.disable_windows_resize_from_edges; io->ConfigWindowsResizeFromEdges = !_simgui.desc.disable_windows_resize_from_edges;
@ -2400,7 +2402,6 @@ SOKOL_API_IMPL void simgui_create_fonts_texture(const simgui_font_tex_desc_t* de
font_smp_desc.wrap_v = SG_WRAP_CLAMP_TO_EDGE; font_smp_desc.wrap_v = SG_WRAP_CLAMP_TO_EDGE;
font_smp_desc.min_filter = desc->min_filter; font_smp_desc.min_filter = desc->min_filter;
font_smp_desc.mag_filter = desc->mag_filter; font_smp_desc.mag_filter = desc->mag_filter;
font_smp_desc.mipmap_filter = SG_FILTER_NONE;
font_smp_desc.label = "sokol-imgui-font-sampler"; font_smp_desc.label = "sokol-imgui-font-sampler";
_simgui.font_smp = sg_make_sampler(&font_smp_desc); _simgui.font_smp = sg_make_sampler(&font_smp_desc);

View file

@ -236,7 +236,7 @@
.overrides = { .overrides = {
.min_filter = SG_FILTER_NEAREST, .min_filter = SG_FILTER_NEAREST,
.mag_filter = SG_FILTER_NEAREST, .mag_filter = SG_FILTER_NEAREST,
.mipmap_filter = SG_FILTER_NONE, .mipmap_filter = SG_FILTER_NEAREST,
.wrap_u = SG_WRAP_MIRROR, .wrap_u = SG_WRAP_MIRROR,
.wrap_v = SG_WRAP_MIRROR, .wrap_v = SG_WRAP_MIRROR,
.premul_alpha_enabled = ..., .premul_alpha_enabled = ...,
@ -4573,15 +4573,19 @@ static sg_filter _sspine_as_sampler_filter(spAtlasFilter filter) {
static sg_filter _sspine_as_sampler_mipmap_filter(spAtlasFilter filter) { static sg_filter _sspine_as_sampler_mipmap_filter(spAtlasFilter filter) {
switch (filter) { switch (filter) {
case SP_ATLAS_UNKNOWN_FILTER: return _SG_FILTER_DEFAULT; case SP_ATLAS_UNKNOWN_FILTER:
case SP_ATLAS_NEAREST: return SG_FILTER_NONE; return _SG_FILTER_DEFAULT;
case SP_ATLAS_LINEAR: return SG_FILTER_NONE; case SP_ATLAS_NEAREST:
case SP_ATLAS_MIPMAP: return SG_FILTER_NEAREST; case SP_ATLAS_LINEAR:
case SP_ATLAS_MIPMAP_NEAREST_NEAREST: return SG_FILTER_NEAREST; case SP_ATLAS_MIPMAP:
case SP_ATLAS_MIPMAP_LINEAR_NEAREST: return SG_FILTER_NEAREST; case SP_ATLAS_MIPMAP_NEAREST_NEAREST:
case SP_ATLAS_MIPMAP_NEAREST_LINEAR: return SG_FILTER_LINEAR; case SP_ATLAS_MIPMAP_LINEAR_NEAREST:
case SP_ATLAS_MIPMAP_LINEAR_LINEAR: return SG_FILTER_LINEAR; return SG_FILTER_NEAREST;
default: return SG_FILTER_NEAREST; case SP_ATLAS_MIPMAP_NEAREST_LINEAR:
case SP_ATLAS_MIPMAP_LINEAR_LINEAR:
return SG_FILTER_LINEAR;
default:
return SG_FILTER_NEAREST;
} }
} }