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
// 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()
// 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( dllimport )
// - 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.
//#define IMGUI_API __declspec(dllexport) // MSVC Windows: DLL export
//#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.
//#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_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_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_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)
@ -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_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
// May be convenient for some users to only explicitly include vanilla imgui.h and have extra stuff included.
//#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)
/*
@ -211,11 +211,13 @@ void ImGui::StyleColorsDark(ImGuiStyle* dst)
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_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_TabActive] = ImLerp(colors[ImGuiCol_HeaderActive], colors[ImGuiCol_TitleBgActive], 0.60f);
colors[ImGuiCol_TabUnfocused] = ImLerp(colors[ImGuiCol_Tab], colors[ImGuiCol_TitleBg], 0.80f);
colors[ImGuiCol_TabUnfocusedActive] = ImLerp(colors[ImGuiCol_TabActive], colors[ImGuiCol_TitleBg], 0.40f);
colors[ImGuiCol_Tab] = ImLerp(colors[ImGuiCol_Header], colors[ImGuiCol_TitleBgActive], 0.80f);
colors[ImGuiCol_TabSelected] = ImLerp(colors[ImGuiCol_HeaderActive], colors[ImGuiCol_TitleBgActive], 0.60f);
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_PlotLinesHovered] = ImVec4(1.00f, 0.43f, 0.35f, 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_TableRowBg] = ImVec4(0.00f, 0.00f, 0.00f, 0.00f);
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_DragDropTarget] = ImVec4(1.00f, 1.00f, 0.00f, 0.90f);
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_ResizeGripHovered] = ImVec4(0.78f, 0.82f, 1.00f, 0.60f);
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_TabActive] = ImLerp(colors[ImGuiCol_HeaderActive], colors[ImGuiCol_TitleBgActive], 0.60f);
colors[ImGuiCol_TabUnfocused] = ImLerp(colors[ImGuiCol_Tab], colors[ImGuiCol_TitleBg], 0.80f);
colors[ImGuiCol_TabUnfocusedActive] = ImLerp(colors[ImGuiCol_TabActive], colors[ImGuiCol_TitleBg], 0.40f);
colors[ImGuiCol_Tab] = ImLerp(colors[ImGuiCol_Header], colors[ImGuiCol_TitleBgActive], 0.80f);
colors[ImGuiCol_TabSelected] = ImLerp(colors[ImGuiCol_HeaderActive], colors[ImGuiCol_TitleBgActive], 0.60f);
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_PlotLinesHovered] = 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_TableRowBg] = ImVec4(0.00f, 0.00f, 0.00f, 0.00f);
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_DragDropTarget] = ImVec4(1.00f, 1.00f, 0.00f, 0.90f);
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_ResizeGripHovered] = ImVec4(0.26f, 0.59f, 0.98f, 0.67f);
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_TabActive] = ImLerp(colors[ImGuiCol_HeaderActive], colors[ImGuiCol_TitleBgActive], 0.60f);
colors[ImGuiCol_TabUnfocused] = ImLerp(colors[ImGuiCol_Tab], colors[ImGuiCol_TitleBg], 0.80f);
colors[ImGuiCol_TabUnfocusedActive] = ImLerp(colors[ImGuiCol_TabActive], colors[ImGuiCol_TitleBg], 0.40f);
colors[ImGuiCol_Tab] = ImLerp(colors[ImGuiCol_Header], colors[ImGuiCol_TitleBgActive], 0.90f);
colors[ImGuiCol_TabSelected] = ImLerp(colors[ImGuiCol_HeaderActive], colors[ImGuiCol_TitleBgActive], 0.60f);
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_PlotLinesHovered] = ImVec4(1.00f, 0.43f, 0.35f, 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_TableRowBg] = ImVec4(0.00f, 0.00f, 0.00f, 0.00f);
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_DragDropTarget] = ImVec4(0.26f, 0.59f, 0.98f, 0.95f);
colors[ImGuiCol_NavHighlight] = colors[ImGuiCol_HeaderHovered];
@ -517,7 +526,6 @@ void ImDrawList::_OnChangedClipRect()
CmdBuffer.pop_back();
return;
}
curr_cmd->ClipRect = _CmdHeader.ClipRect;
}
@ -540,7 +548,6 @@ void ImDrawList::_OnChangedTextureID()
CmdBuffer.pop_back();
return;
}
curr_cmd->TextureId = _CmdHeader.TextureId;
}
@ -616,6 +623,15 @@ void ImDrawList::PopTextureID()
_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.
// 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.
@ -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)
{
// 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.
IM_ASSERT(src_range[0] <= src_range[1]);
// user error is to setup ImFontConfig::GlyphRanges with a pointer to data that isn't persistent,
// 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]);
}
dst_tmp.SrcCount++;

View file

@ -1,4 +1,4 @@
// dear imgui, v1.90.8 WIP
// dear imgui, v1.91.1
// (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.
@ -14,14 +14,15 @@ Index of this file:
// [SECTION] Macros
// [SECTION] Generic helpers
// [SECTION] ImDrawList support
// [SECTION] Widgets support: flags, enums, data structures
// [SECTION] Data types support
// [SECTION] Widgets support: flags, enums, data structures
// [SECTION] Popup support
// [SECTION] Inputs support
// [SECTION] Clipper support
// [SECTION] Navigation support
// [SECTION] Typing-select support
// [SECTION] Columns support
// [SECTION] Box-select support
// [SECTION] Multi-select support
// [SECTION] Docking support
// [SECTION] Viewport support
@ -93,6 +94,7 @@ Index of this file:
#pragma GCC diagnostic push
#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 "-Wdeprecated-enum-enum-conversion" // warning: bitwise operation between different enumeration types ('XXXFlags_' and 'XXXFlagsPrivate_') is deprecated
#endif
// 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 ImDrawDataBuilder; // Helper to build a ImDrawData instance
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 ImGuiContext; // Main Dear ImGui context
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 ImGuiLocEntry; // A localization entry.
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 ImGuiNavTreeNodeData; // Temporary storage for last TreeNode() being a Left arrow landing candidate.
struct ImGuiMetricsConfig; // Storage for ShowMetricsWindow() and DebugNodeXXX() functions
struct ImGuiNextWindowData; // Storage for SetNextWindow** 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 ImGuiTableSettings; // Storage for a table .ini settings
struct ImGuiTableColumnsSettings; // Storage for a column .ini settings
struct ImGuiTreeNodeStackData; // Temporary storage for TreeNode().
struct ImGuiTypingSelectState; // Storage for GetTypingSelectRequest()
struct ImGuiTypingSelectRequest; // Storage for GetTypingSelectRequest() (aimed to be public)
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 ImGuiDebugLogFlags; // -> enum ImGuiDebugLogFlags_ // Flags: for ShowDebugLogWindow(), g.DebugLogFlags
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 ImGuiOldColumnFlags; // -> enum ImGuiOldColumnFlags_ // Flags: for BeginColumns()
typedef int ImGuiNavHighlightFlags; // -> enum ImGuiNavHighlightFlags_ // Flags: for RenderNavHighlight()
@ -348,6 +352,7 @@ namespace ImStb
// - Helper: ImPool<>
// - Helper: ImChunkStream<>
// - Helper: ImGuiTextIndex
// - Helper: ImGuiStorage
//-----------------------------------------------------------------------------
// 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 bool ImCharIsBlankA(char c) { return c == ' ' || c == '\t'; }
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
// 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 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 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 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; }
@ -722,7 +729,7 @@ struct ImChunkStream
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.
struct ImGuiTextIndex
{
@ -736,6 +743,8 @@ struct ImGuiTextIndex
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
//-----------------------------------------------------------------------------
@ -772,6 +781,7 @@ struct IMGUI_API ImDrawListSharedData
ImVec2 TexUvWhitePixel; // UV of white pixel in the atlas
ImFont* Font; // Current/default font (optional, for simplified AddText overload)
float FontSize; // Current/default font size (optional, for simplified AddText overload)
float FontScale; // Current/default font scale (== FontSize / Font->FontSize)
float CurveTessellationTol; // Tessellation tolerance when using PathBezierCurveTo()
float CircleSegmentMaxError; // Number of circle segments to use per pixel of radius for AddCircle() etc
ImVec4 ClipRectFullscreen; // Value for PushClipRectFullscreen()
@ -798,33 +808,65 @@ struct ImDrawDataBuilder
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
//-----------------------------------------------------------------------------
// Flags used by upcoming items
// Extend ImGuiItemFlags
// - input: PushItemFlag() manipulates g.CurrentItemFlags, ItemAdd() calls may add extra flags.
// - output: stored in g.LastItemData.InFlags
// Current window shared by all windows.
// This is going to be exposed in imgui.h when stabilized enough.
enum ImGuiItemFlags_
enum ImGuiItemFlagsPrivate_
{
// Controlled by user
ImGuiItemFlags_None = 0,
ImGuiItemFlags_NoTabStop = 1 << 0, // false // Disable keyboard tabbing. This is a "lighter" version of ImGuiItemFlags_NoNav.
ImGuiItemFlags_ButtonRepeat = 1 << 1, // false // Button() will return true multiple times based on io.KeyRepeatDelay and io.KeyRepeatRate settings.
ImGuiItemFlags_Disabled = 1 << 2, // false // Disable interactions but doesn't affect visuals. See BeginDisabled()/EndDisabled(). See github.com/ocornut/imgui/issues/211
ImGuiItemFlags_NoNav = 1 << 3, // false // Disable any form of focusing (keyboard/gamepad directional navigation and SetKeyboardFocusHere() calls)
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.
ImGuiItemFlags_Disabled = 1 << 10, // false // Disable interactions (DOES NOT affect visuals, see BeginDisabled()/EndDisabled() for full disable feature, and github #211).
ImGuiItemFlags_ReadOnly = 1 << 11, // false // [ALPHA] Allow hovering interactions but underlying value is not changed.
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_NoWindowHoverableCheck = 1 << 13, // false // Disable hoverable check in ItemHoverable()
ImGuiItemFlags_AllowOverlap = 1 << 14, // false // Allow being overlapped by another widget. Not-hovered to Hovered transition deferred by a frame.
// 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_HasSelectionUserData = 1 << 11, // false // Set by SetNextItemSelectionUserData()
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 << 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
@ -927,8 +969,9 @@ enum ImGuiSelectableFlagsPrivate_
// Extend ImGuiTreeNodeFlags_
enum ImGuiTreeNodeFlagsPrivate_
{
ImGuiTreeNodeFlags_ClipLabelForTrailingButton = 1 << 20,
ImGuiTreeNodeFlags_UpsideDownArrow = 1 << 21,// (FIXME-WIP) Turn Down arrow into an Up arrow, but reversed trees (#6517)
ImGuiTreeNodeFlags_ClipLabelForTrailingButton = 1 << 28,// FIXME-WIP: Hard-coded for CollapsingHeader()
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_
@ -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)
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
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
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!)
@ -1167,29 +1210,30 @@ struct ImGuiNextWindowData
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_
{
ImGuiNextItemDataFlags_None = 0,
ImGuiNextItemDataFlags_HasWidth = 1 << 0,
ImGuiNextItemDataFlags_HasOpen = 1 << 1,
ImGuiNextItemDataFlags_HasShortcut = 1 << 2,
ImGuiNextItemDataFlags_HasRefVal = 1 << 3,
ImGuiNextItemDataFlags_HasStorageID = 1 << 4,
};
struct ImGuiNextItemData
{
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()
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)
float Width; // Set by SetNextItemWidth()
ImGuiKeyChord Shortcut; // Set by SetNextItemShortcut()
ImGuiInputFlags ShortcutFlags; // Set by SetNextItemShortcut()
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; }
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)); }
};
// Store data emitted by TreeNode() for usage by TreePop() to implement ImGuiTreeNodeFlags_NavLeftJumpsBackHere.
// This is the minimum amount of data that we need to perform the equivalent of NavApplyItemToResult() and which we can't infer in TreePop()
// Only stored when the node is a potential candidate for landing on a Left arrow jump.
struct ImGuiNavTreeNodeData
// Store data emitted by TreeNode() for usage by TreePop()
// - To implement ImGuiTreeNodeFlags_NavLeftJumpsBackHere: store the minimum amount of data
// which we can't infer in TreePop(), to perform the equivalent of NavApplyItemToResult().
// Only stored when the node is a potential candidate for landing on a Left arrow jump.
struct ImGuiTreeNodeStackData
{
ImGuiID ID;
ImGuiItemFlags InFlags;
ImRect NavRect;
ImGuiTreeNodeFlags TreeFlags;
ImGuiItemFlags InFlags; // Used for nav landing
ImRect NavRect; // Used for nav landing
};
struct IMGUI_API ImGuiStackSizes
@ -1263,40 +1309,6 @@ struct ImGuiPtrOrIndex
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
//-----------------------------------------------------------------------------
@ -1347,8 +1359,8 @@ typedef ImBitArray<ImGuiKey_NamedKey_COUNT, -ImGuiKey_NamedKey_BEGIN> ImBitAr
#define ImGuiKey_NavKeyboardTweakFast ImGuiMod_Shift
#define ImGuiKey_NavGamepadTweakSlow ImGuiKey_GamepadL1
#define ImGuiKey_NavGamepadTweakFast ImGuiKey_GamepadR1
#define ImGuiKey_NavGamepadActivate ImGuiKey_GamepadFaceDown
#define ImGuiKey_NavGamepadCancel ImGuiKey_GamepadFaceRight
#define ImGuiKey_NavGamepadActivate (g.IO.ConfigNavSwapGamepadButtons ? ImGuiKey_GamepadFaceRight : ImGuiKey_GamepadFaceDown)
#define ImGuiKey_NavGamepadCancel (g.IO.ConfigNavSwapGamepadButtons ? ImGuiKey_GamepadFaceDown : ImGuiKey_GamepadFaceRight)
#define ImGuiKey_NavGamepadMenu ImGuiKey_GamepadFaceLeft
#define ImGuiKey_NavGamepadInput ImGuiKey_GamepadFaceUp
@ -1594,7 +1606,7 @@ struct ImGuiNavItemData
float DistBox; // Move // Best candidate box distance to current NavId
float DistCenter; // Move // Best candidate center 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(); }
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)); }
};
//-----------------------------------------------------------------------------
// [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
//-----------------------------------------------------------------------------
@ -1707,9 +1747,45 @@ struct ImGuiOldColumns
// We always assume that -1 is an invalid value (which works for indices and pointers)
#define ImGuiSelectionUserData_Invalid ((ImGuiSelectionUserData)-1)
#ifdef IMGUI_HAS_MULTI_SELECT
// <this is filled in 'range_select' branch>
#endif // #ifdef IMGUI_HAS_MULTI_SELECT
// Temporary storage for multi-select
struct IMGUI_API ImGuiMultiSelectTempData
{
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
@ -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.
ImDrawData DrawDataP;
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).
ImVec2 BuildWorkOffsetMin; // Work Area: Offset being built during current frame. Generally >= 0.0f.
ImVec2 BuildWorkOffsetMax; // Work Area: Offset being built during current frame. Generally <= 0.0f.
// Per-viewport work area
// - Insets are >= 0.0f values, distance from viewport corners to work area.
// - 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() { 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)
ImVec2 CalcWorkRectPos(const ImVec2& off_min) const { return ImVec2(Pos.x + off_min.x, Pos.y + off_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)); }
void UpdateWorkRect() { WorkPos = CalcWorkRectPos(WorkOffsetMin); WorkSize = CalcWorkRectSize(WorkOffsetMin, WorkOffsetMax); } // Update public fields
ImVec2 CalcWorkRectPos(const ImVec2& inset_min) const { return ImVec2(Pos.x + inset_min.x, Pos.y + inset_min.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(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)
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 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_WindowingPopup,
ImGuiLocKey_WindowingUntitled,
ImGuiLocKey_CopyLink,
ImGuiLocKey_COUNT
};
@ -1918,10 +2000,12 @@ struct ImGuiContext
bool Initialized;
bool FontAtlasOwnedByContext; // IO.Fonts-> is owned by the ImGuiContext and will be destructed along with it.
ImGuiIO IO;
ImGuiPlatformIO PlatformIO;
ImGuiStyle Style;
ImFont* Font; // (Shortcut) == FontStack.empty() ? IO.Font : FontStack.back()
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 FontScale; // == FontSize / Font->FontSize
float CurrentDpiScale; // Current window/viewport DpiScale
ImDrawListSharedData DrawListSharedData;
double Time;
@ -1934,6 +2018,7 @@ struct ImGuiContext
bool GcCompactAll; // Request full GC
bool TestEngineHookItems; // Will call test engine hooks: ImGuiTestEngineHook_ItemAdd(), ImGuiTestEngineHook_ItemInfo(), ImGuiTestEngineHook_Log()
void* TestEngine; // Test engine user data
char ContextName[16]; // Storage for a context name (to facilitate debugging multi-context setups)
// Inputs
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* HoveredWindow; // Window the mouse is hovering. Will typically catch mouse inputs.
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* 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;
@ -1969,7 +2055,7 @@ struct ImGuiContext
float HoveredIdTimer; // Measure contiguous hovering time
float HoveredIdNotActiveTimer; // Measure contiguous hovering time where the item has not been active
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
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)
@ -2003,11 +2089,9 @@ struct ImGuiContext
ImGuiKeyOwnerData KeysOwnerData[ImGuiKey_NamedKey_COUNT];
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)
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.
#ifndef IMGUI_DISABLE_OBSOLETE_KEYIO
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
//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);'
// Next window/item data
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<ImGuiPopupData> OpenPopupStack; // Which popups are open (persistent)
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
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'
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)
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 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)
@ -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.
ImGuiID NavHighlightActivatedId;
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.
ImGuiActivateFlags NavNextActivateFlags;
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.
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)
@ -2081,6 +2162,14 @@ struct ImGuiContext
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
// 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)
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)
@ -2136,6 +2225,13 @@ struct ImGuiContext
ImVector<ImGuiPtrOrIndex> CurrentTabBarStack;
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
ImGuiID HoverItemDelayId;
ImGuiID HoverItemDelayIdPreviousFrame;
@ -2154,6 +2250,7 @@ struct ImGuiContext
ImGuiInputTextDeactivatedState InputTextDeactivatedState;
ImFont InputTextPasswordFont;
ImGuiID TempInputId; // Temporary text input when CTRL+clicking on a slider, etc.
ImGuiDataTypeStorage DataTypeZeroValue; // 0 for all data types
int BeginMenuDepth;
int BeginComboDepth;
ImGuiColorEditFlags ColorEditOptions; // Store user options for color edit widgets
@ -2184,7 +2281,7 @@ struct ImGuiContext
// Platform support
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
bool SettingsLoaded;
@ -2251,7 +2348,7 @@ struct ImGuiContext
Initialized = false;
FontAtlasOwnedByContext = shared_font_atlas ? false : true;
Font = NULL;
FontSize = FontBaseSize = CurrentDpiScale = 0.0f;
FontSize = FontBaseSize = FontScale = CurrentDpiScale = 0.0f;
IO.Fonts = shared_font_atlas ? shared_font_atlas : IM_NEW(ImFontAtlas)();
Time = 0.0f;
FrameCount = 0;
@ -2260,6 +2357,7 @@ struct ImGuiContext
GcCompactAll = false;
TestEngineHookItems = false;
TestEngine = NULL;
memset(ContextName, 0, sizeof(ContextName));
InputEventsNextMouseSource = ImGuiMouseSource_Mouse;
InputEventsNextEventId = 1;
@ -2268,6 +2366,7 @@ struct ImGuiContext
CurrentWindow = NULL;
HoveredWindow = NULL;
HoveredWindowUnderMovingWindow = NULL;
HoveredWindowBeforeClear = NULL;
MovingWindow = NULL;
WheelingWindow = NULL;
WheelingWindowStartFrame = WheelingWindowScrolledFrame = -1;
@ -2276,7 +2375,7 @@ struct ImGuiContext
DebugHookIdInfo = 0;
HoveredId = HoveredIdPreviousFrame = 0;
HoveredIdAllowOverlap = false;
HoveredIdDisabled = false;
HoveredIdIsDisabled = false;
HoveredIdTimer = HoveredIdNotActiveTimer = 0.0f;
ItemUnclipByLog = false;
ActiveId = 0;
@ -2304,9 +2403,6 @@ struct ImGuiContext
ActiveIdUsingNavDirMask = 0x00;
ActiveIdUsingAllKeyboardKeys = false;
#ifndef IMGUI_DISABLE_OBSOLETE_KEYIO
ActiveIdUsingNavInputMask = 0x00;
#endif
CurrentFocusScopeId = 0;
CurrentItemFlags = ImGuiItemFlags_None;
@ -2314,18 +2410,18 @@ struct ImGuiContext
NavWindow = NULL;
NavId = NavFocusScopeId = NavActivateId = NavActivateDownId = NavActivatePressedId = 0;
NavJustMovedToId = NavJustMovedToFocusScopeId = NavNextActivateId = 0;
NavLayer = ImGuiNavLayer_Main;
NavNextActivateId = 0;
NavActivateFlags = NavNextActivateFlags = ImGuiActivateFlags_None;
NavHighlightActivatedId = 0;
NavHighlightActivatedTimer = 0.0f;
NavJustMovedToKeyMods = ImGuiMod_None;
NavInputSource = ImGuiInputSource_Keyboard;
NavLayer = ImGuiNavLayer_Main;
NavLastValidSelectionUserData = ImGuiSelectionUserData_Invalid;
NavIdIsAlive = false;
NavMousePosDirty = false;
NavDisableHighlight = true;
NavDisableMouseHover = false;
NavAnyRequest = false;
NavInitRequest = false;
NavInitRequestFromMove = false;
@ -2340,6 +2436,11 @@ struct ImGuiContext
NavTabbingDir = 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...
// 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);
@ -2368,6 +2469,8 @@ struct ImGuiContext
CurrentTable = NULL;
TablesTempDataStacked = 0;
CurrentTabBar = NULL;
CurrentMultiSelect = NULL;
MultiSelectTempDataStacked = 0;
HoverItemDelayId = HoverItemDelayIdPreviousFrame = HoverItemUnlockedStationaryId = HoverWindowUnlockedStationaryId = 0;
HoverItemDelayTimer = HoverItemDelayClearTimer = 0.0f;
@ -2376,6 +2479,7 @@ struct ImGuiContext
MouseStationaryTimer = 0.0f;
TempInputId = 0;
memset(&DataTypeZeroValue, 0, sizeof(DataTypeZeroValue));
BeginMenuDepth = BeginComboDepth = 0;
ColorEditOptions = ImGuiColorEditFlags_DefaultOptions_;
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.
ImGuiMenuColumns MenuColumns; // Simplified columns storage for menu items measurement
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;
ImGuiStorage* StateStorage; // Current persistent per-window storage (store e.g. tree node open/close state)
ImGuiOldColumns* CurrentColumns; // Current columns set
@ -2514,7 +2618,7 @@ struct IMGUI_API ImGuiWindow
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 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 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).
@ -2611,6 +2715,7 @@ public:
ImGuiID GetID(const char* str, const char* str_end = NULL);
ImGuiID GetID(const void* ptr);
ImGuiID GetID(int n);
ImGuiID GetIDFromPos(const ImVec2& p_abs);
ImGuiID GetIDFromRectangle(const ImRect& r_abs);
// We don't use g.FontSize because the window may be != g.CurrentWindow.
@ -2722,6 +2827,7 @@ struct ImGuiTableColumn
float MaxX;
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 WidthMax; // Maximum width (FIXME: overwritten by each instance)
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_).
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 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 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); }
// Windows: Display Order and Focus Order
@ -3096,7 +3203,7 @@ namespace ImGui
//#endif
// 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 ImGuiID GetActiveID() { ImGuiContext& g = *GImGui; return g.ActiveId; }
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 float CalcWrapWidthForPos(const ImVec2& pos, float wrap_pos_x);
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);
// Parameter stacks (shared)
IMGUI_API void PushItemFlag(ImGuiItemFlags option, bool enabled);
IMGUI_API void PopItemFlag();
IMGUI_API const ImGuiDataVarInfo* GetStyleVarInfo(ImGuiStyleVar idx);
IMGUI_API void BeginDisabledOverrideReenable();
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 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);
// 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 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 ClosePopupsExceptModals();
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 ImGuiWindow* GetTopMostPopupModal();
IMGUI_API ImGuiWindow* GetTopMostAndVisiblePopupModal();
@ -3156,6 +3259,10 @@ namespace ImGui
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);
// Tooltips
IMGUI_API bool BeginTooltipEx(ImGuiTooltipFlags tooltip_flags, ImGuiWindowFlags extra_window_flags);
IMGUI_API bool BeginTooltipHidden();
// Menus
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);
@ -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 NavMoveRequestForward(ImGuiDir move_dir, ImGuiDir clip_dir, ImGuiNavMoveFlags move_flags, ImGuiScrollFlags scroll_flags);
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 NavMoveRequestApplyResult();
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 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 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);
inline ImGuiKey ConvertSingleModFlagToKey(ImGuiKey key)
{
@ -3238,7 +3345,7 @@ namespace ImGui
IMGUI_API ImGuiID GetKeyOwner(ImGuiKey key);
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 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'
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 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)
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().
@ -3317,7 +3436,6 @@ namespace ImGui
IMGUI_API void TableOpenContextMenu(int column_n = -1);
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 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 float TableGetHeaderRowHeight();
IMGUI_API float TableGetHeaderAngledMaxLabelWidth();
@ -3353,7 +3471,7 @@ namespace ImGui
IMGUI_API ImRect TableGetCellBgRect(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 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 TableSetColumnWidthAutoAll(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 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 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 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
@ -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 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);
// Widgets: Tree Nodes
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 TreeNodeSetOpen(ImGuiID id, bool open);
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 SetNextItemSelectionUserData(ImGuiSelectionUserData selection_user_data);
IMGUI_API bool TreeNodeGetOpen(ImGuiID storage_id);
IMGUI_API void TreeNodeSetOpen(ImGuiID storage_id, bool open);
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.
// 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 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 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 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);
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
IMGUI_API void SetNextItemRefVal(ImGuiDataType data_type, void* p_data);
// Color
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 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
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 ErrorCheckEndWindowRecover(ImGuiErrorLogCallback log_callback, void* user_data = NULL);
IMGUI_API void ErrorCheckUsingSetCursorPosToExtendParentBoundaries();
@ -3520,6 +3637,7 @@ namespace ImGui
IMGUI_API void DebugNodeTableSettings(ImGuiTableSettings* settings);
IMGUI_API void DebugNodeInputTextState(ImGuiInputTextState* 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 DebugNodeWindowSettings(ImGuiWindowSettings* settings);
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)
/*
@ -412,8 +412,8 @@ bool ImGui::BeginTableEx(const char* name, ImGuiID id, int columns_count, ImG
SetNextWindowScroll(ImVec2(0.0f, 0.0f));
// Create scrolling region (without border and zero window padding)
ImGuiWindowFlags child_flags = (flags & ImGuiTableFlags_ScrollX) ? ImGuiWindowFlags_HorizontalScrollbar : ImGuiWindowFlags_None;
BeginChildEx(name, instance_id, outer_rect.GetSize(), false, child_flags);
ImGuiWindowFlags child_window_flags = (flags & ImGuiTableFlags_ScrollX) ? ImGuiWindowFlags_HorizontalScrollbar : ImGuiWindowFlags_None;
BeginChildEx(name, instance_id, outer_rect.GetSize(), ImGuiChildFlags_None, child_window_flags);
table->InnerWindow = g.CurrentWindow;
table->WorkRect = table->InnerWindow->WorkRect;
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;
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
// 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).
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)
{
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)
{
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
@ -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.ClipWith(table->WorkRect); // We need this to honor inner_width
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->RowTextBaseline = 0.0f; // This will be cleared again by TableBeginRow()
@ -1059,16 +1070,12 @@ void ImGui::TableUpdateLayout(ImGuiTable* table)
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
column->MinX = offset_x;
// Lock width based on start position and minimum/maximum width for this position
float max_width = TableGetMaxColumnWidth(table, column_n);
column->WidthGiven = ImMin(column->WidthGiven, max_width);
column->WidthMax = TableCalcMaxColumnWidth(table, column_n);
column->WidthGiven = ImMin(column->WidthGiven, column->WidthMax);
column->WidthGiven = ImMax(column->WidthGiven, ImMin(column->WidthRequest, table->MinColumnWidth));
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;
if (column->SortOrder != -1)
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;
table->HoveredColumnBody = (ImGuiTableColumnIdx)column_n;
}
// Alignment
// 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)
table->DrawSplitter->SetCurrentChannel(inner_window->DrawList, TABLE_DRAW_CHANNEL_NOCLIP);
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()
@ -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
// get the new cursor position.
if (unfreeze_rows_request)
{
for (int column_n = 0; column_n < table->ColumnsCount; column_n++)
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);
table->IsUnfrozenRows = true;
table_instance->LastFrozenHeight = y0 - table->OuterRect.Min.y;
// BgClipRect starts as table->InnerClipRect, reduce it now and make BgClipRectForDrawCmd == BgClipRect
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++)
if (unfreeze_rows_actual)
{
ImGuiTableColumn* column = &table->Columns[column_n];
column->DrawChannelCurrent = column->DrawChannelUnfrozen;
column->ClipRect.Min.y = table->Bg2ClipRectForDrawCmd.Min.y;
}
IM_ASSERT(table->IsUnfrozenRows == false);
table->IsUnfrozenRows = true;
// 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);
// BgClipRect starts as table->InnerClipRect, reduce it now and make BgClipRectForDrawCmd == BgClipRect
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];
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))
@ -2192,8 +2207,8 @@ void ImGui::TableEndCell(ImGuiTable* table)
// 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.
float ImGui::TableGetMaxColumnWidth(const ImGuiTable* table, int column_n)
// Maximum column content width given current layout. Use column->MinX so this value differs on a per-column basis.
float ImGui::TableCalcMaxColumnWidth(const ImGuiTable* table, int column_n)
{
const ImGuiTableColumn* column = &table->Columns[column_n];
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)
IM_ASSERT(table->MinColumnWidth > 0.0f);
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);
if (column_0->WidthGiven == column_0_width || column_0->WidthRequest == column_0_width)
return;
@ -2740,7 +2755,7 @@ void ImGui::TableDrawBorders(ImGuiTable* table)
const ImU32 outer_col = table->BorderColorStrong;
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)
{
@ -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
// 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.
// 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.
void ImGui::TableHeadersRow()
{
@ -3012,7 +3028,8 @@ void ImGui::TableHeadersRow()
ImGuiTable* table = g.CurrentTable;
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)
TableUpdateLayout(table);
@ -3029,8 +3046,7 @@ void ImGui::TableHeadersRow()
if (!TableSetColumnIndex(column_n))
continue;
// Push an id to allow unnamed labels (generally accidental, but let's behave nicely with them)
// In your own code you may omit the PushID/PopID all-together, provided you know they won't collide.
// 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)
const char* name = (TableGetColumnFlags(column_n) & ImGuiTableColumnFlags_NoHeaderLabel) ? "" : TableGetColumnName(column_n);
PushID(column_n);
TableHeader(name);
@ -3269,7 +3285,7 @@ void ImGui::TableAngledHeadersRowEx(ImGuiID row_id, float angle, float max_label
ButtonBehavior(row_r, row_id, NULL, NULL);
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 ImVec2 padding = g.Style.CellPadding; // We will always use swapped component
const ImVec2 align = g.Style.TableAngledHeadersTextAlign;
@ -3471,7 +3487,7 @@ void ImGui::TableDrawDefaultContextMenu(ImGuiTable* table, ImGuiTableFlags flags
Separator();
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++)
{
ImGuiTableColumn* other_column = &table->Columns[other_column_n];
@ -4425,12 +4441,12 @@ void ImGui::EndColumns()
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();
IM_ASSERT(columns_count >= 1);
ImGuiOldColumnFlags flags = (border ? 0 : ImGuiOldColumnFlags_NoBorder);
ImGuiOldColumnFlags flags = (borders ? 0 : ImGuiOldColumnFlags_NoBorder);
//flags |= ImGuiOldColumnFlags_NoPreserveWidths; // NB: Legacy behavior
ImGuiOldColumns* columns = window->DC.CurrentColumns;
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
errors.
LICENSE
=======
@ -1067,6 +1068,7 @@ typedef struct {
/* sokol-audio state */
typedef struct {
bool valid;
bool setup_called;
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* user_data;
@ -2486,9 +2488,11 @@ void _saudio_backend_shutdown(void) {
// >>public
SOKOL_API_IMPL void saudio_setup(const saudio_desc* desc) {
SOKOL_ASSERT(!_saudio.valid);
SOKOL_ASSERT(!_saudio.setup_called);
SOKOL_ASSERT(desc);
SOKOL_ASSERT((desc->allocator.alloc_fn && desc->allocator.free_fn) || (!desc->allocator.alloc_fn && !desc->allocator.free_fn));
_saudio_clear(&_saudio, sizeof(_saudio));
_saudio.setup_called = true;
_saudio.desc = *desc;
_saudio.stream_cb = desc->stream_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_ASSERT(_saudio.setup_called);
_saudio.setup_called = false;
if (_saudio.valid) {
_saudio_backend_shutdown();
_saudio_fifo_shutdown(&_saudio.fifo);
@ -2532,26 +2538,32 @@ SOKOL_API_IMPL bool saudio_isvalid(void) {
}
SOKOL_API_IMPL void* saudio_userdata(void) {
SOKOL_ASSERT(_saudio.setup_called);
return _saudio.desc.user_data;
}
SOKOL_API_IMPL saudio_desc saudio_query_desc(void) {
SOKOL_ASSERT(_saudio.setup_called);
return _saudio.desc;
}
SOKOL_API_IMPL int saudio_sample_rate(void) {
SOKOL_ASSERT(_saudio.setup_called);
return _saudio.sample_rate;
}
SOKOL_API_IMPL int saudio_buffer_frames(void) {
SOKOL_ASSERT(_saudio.setup_called);
return _saudio.buffer_frames;
}
SOKOL_API_IMPL int saudio_channels(void) {
SOKOL_ASSERT(_saudio.setup_called);
return _saudio.num_channels;
}
SOKOL_API_IMPL bool saudio_suspended(void) {
SOKOL_ASSERT(_saudio.setup_called);
#if defined(_SAUDIO_EMSCRIPTEN)
if (_saudio.valid) {
return 1 == saudio_js_suspended();
@ -2565,6 +2577,7 @@ SOKOL_API_IMPL bool saudio_suspended(void) {
}
SOKOL_API_IMPL int saudio_expect(void) {
SOKOL_ASSERT(_saudio.setup_called);
if (_saudio.valid) {
const int num_frames = _saudio_fifo_writable_bytes(&_saudio.fifo) / _saudio.bytes_per_frame;
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_ASSERT(_saudio.setup_called);
SOKOL_ASSERT(frames && (num_frames > 0));
if (_saudio.valid) {
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)
#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;
}
}
#ifdef _MSC_VER
#pragma warning(pop)
#endif
#endif /* SOKOL_FETCH_IMPL */

View file

@ -963,7 +963,7 @@
ON STORAGE BUFFERS
==================
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
in shaders as as a 1-dimensional array of struct items.
@ -1496,6 +1496,7 @@
.wgpu.num_bindgroup_cache_hits
.wgpu.num_bindgroup_cache_misses
.wgpu.num_bindgroup_cache_collisions
.wgpu_num_bindgroup_cache_invalidates
.wgpu.num_bindgroup_cache_vs_hash_key_mismatch
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
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 mipmap_filter the default is SG_FILTER_NONE.
For the default is SG_FILTER_NEAREST.
*/
typedef enum sg_filter {
_SG_FILTER_DEFAULT, // value 0 reserved for default-init
SG_FILTER_NONE, // FIXME: deprecated
SG_FILTER_NEAREST,
SG_FILTER_LINEAR,
_SG_FILTER_NUM,
@ -2892,7 +2890,7 @@ typedef struct sg_image_desc {
.min_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_v: SG_WRAP_REPEAT
.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_misses;
uint32_t num_bindgroup_cache_collisions;
uint32_t num_bindgroup_cache_invalidates;
uint32_t num_bindgroup_cache_hash_vs_key_mismatch;
} 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(IDENTICAL_COMMIT_LISTENER, "attempting to add identical commit listener") \
_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_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") \
@ -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_COMPRESSED_IMMUTABLE, "compressed images must be immutable") \
_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_SHADERDESC_CANARY, "sg_shader_desc not initialized") \
_SG_LOGITEM_XMACRO(VALIDATE_SHADERDESC_SOURCE, "shader source code required") \
@ -3887,6 +3884,12 @@ typedef enum sg_log_item {
before sg_setup() is called
.environment.d3d11.device_context
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:
.wgpu_disable_bindgroups_cache
@ -3999,6 +4002,7 @@ typedef struct sg_desc {
int uniform_buffer_size;
int max_commit_listeners;
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_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
@ -5783,10 +5787,20 @@ typedef struct {
uint32_t id;
} _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 {
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;
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) {
if (min_f == SG_FILTER_NEAREST) {
switch (mipmap_f) {
case SG_FILTER_NONE: return GL_NEAREST;
case SG_FILTER_NEAREST: return GL_NEAREST_MIPMAP_NEAREST;
case SG_FILTER_LINEAR: return GL_NEAREST_MIPMAP_LINEAR;
default: SOKOL_UNREACHABLE; return (GLenum)0;
}
} else if (min_f == SG_FILTER_LINEAR) {
switch (mipmap_f) {
case SG_FILTER_NONE: return GL_LINEAR;
case SG_FILTER_NEAREST: return GL_LINEAR_MIPMAP_NEAREST;
case SG_FILTER_LINEAR: return GL_LINEAR_MIPMAP_LINEAR;
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_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);
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);
}
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);
// NOTE: workaround for https://issues.chromium.org/issues/355605685
// FIXME: on GLES3 and GL 4.3 (e.g. not macOS) the texture initialization
// should be rewritten to use glTexStorage + glTexSubImage
bool tex_storage_allocated = false;
#if defined(__EMSCRIPTEN__)
if (desc->data.subimage[0][0].ptr == 0) {
tex_storage_allocated = true;
if ((SG_IMAGETYPE_2D == img->cmn.type) || (SG_IMAGETYPE_CUBE == img->cmn.type)) {
if (is_compressed) {
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);
}
glTexStorage2D(img->gl.target, img->cmn.num_mipmaps, gl_internal_format, img->cmn.width, img->cmn.height);
} 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);
glTexStorage3D(img->gl.target, img->cmn.num_mipmaps, gl_internal_format, img->cmn.width, img->cmn.height, img->cmn.num_slices);
}
}
#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 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);
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 (is_compressed) {
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)) {
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;
}
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* errors_or_warnings = NULL;
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
stage_desc->entry ? stage_desc->entry : "main", // pEntryPoint
stage_desc->d3d11_target, // pTarget
D3DCOMPILE_PACK_MATRIX_COLUMN_MAJOR | D3DCOMPILE_OPTIMIZATION_LEVEL3, // Flags1
flags1, // Flags1
0, // Flags2
&output, // ppCode
&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_ASSERT(img && data);
SOKOL_ASSERT(_sg.d3d11.ctx);
SOKOL_ASSERT(img->d3d11.res);
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_depth_slices = (img->cmn.type == SG_IMAGETYPE_3D) ? img->cmn.num_slices:1;
UINT subres_index = 0;
HRESULT hr;
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));
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 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 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 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);
_sg_stats_add(d3d11.num_map, 1);
if (SUCCEEDED(hr)) {
// FIXME: need to handle difference in depth-pitch for 3D textures as well!
if (src_pitch == (int)d3d11_msr.RowPitch) {
memcpy(d3d11_msr.pData, slice_ptr, slice_size);
} else {
SOKOL_ASSERT(src_pitch < (int)d3d11_msr.RowPitch);
const uint8_t* src_ptr = slice_ptr;
uint8_t* dst_ptr = (uint8_t*) d3d11_msr.pData;
for (int row_index = 0; row_index < mip_height; row_index++) {
memcpy(dst_ptr, src_ptr, (size_t)src_pitch);
src_ptr += src_pitch;
dst_ptr += d3d11_msr.RowPitch;
const uint8_t* src_ptr = slice_ptr;
uint8_t* dst_ptr = (uint8_t*)d3d11_msr.pData;
for (int depth_index = 0; depth_index < num_depth_slices; depth_index++) {
if (src_row_pitch == (int)d3d11_msr.RowPitch) {
const size_t copy_size = slice_size / (size_t)num_depth_slices;
SOKOL_ASSERT((copy_size * (size_t)num_depth_slices) == slice_size);
memcpy(dst_ptr, src_ptr, copy_size);
} else {
SOKOL_ASSERT(src_row_pitch < (int)d3d11_msr.RowPitch);
const uint8_t* src_row_ptr = src_ptr;
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_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) {
switch (f) {
case SG_FILTER_NONE:
return MTLSamplerMipFilterNotMipmapped;
case SG_FILTER_NEAREST:
return MTLSamplerMipFilterNearest;
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) {
switch (f) {
case SG_FILTER_NONE:
case SG_FILTER_NEAREST:
return WGPUMipmapFilterMode_Nearest;
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;
}
_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_ASSERT(bnd);
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);
_sg_clear(key->items, sizeof(key->items));
key->items[0] = bnd->pip->slot.id;
const int vs_imgs_offset = 1;
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);
int item_idx = 0;
key->items[item_idx++] = _sg_wgpu_bindgroups_cache_pip_item(bnd->pip->slot.id);
for (int i = 0; i < bnd->num_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++) {
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++) {
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++) {
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++) {
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++) {
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);
}
@ -14199,6 +14264,33 @@ _SOKOL_PRIVATE uint32_t _sg_wgpu_bindgroups_cache_get(uint64_t hash) {
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) {
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)) {
_sg_wgpu_bindings_cache_bg_update(bg);
_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);
}
if (bg && bg->slot.state == SG_RESOURCESTATE_VALID) {
_sg_wgpu_set_bindings_bindgroup(bg);
_sg_wgpu_set_bindgroup(bg);
} else {
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);
if (bg) {
if (bg->slot.state == SG_RESOURCESTATE_VALID) {
_sg_wgpu_set_bindings_bindgroup(bg);
_sg_wgpu_set_bindgroup(bg);
}
_sg_wgpu_discard_bindgroup(bg);
} else {
@ -14322,7 +14414,7 @@ _SOKOL_PRIVATE bool _sg_wgpu_apply_bindgroup(_sg_bindings_t* bnd) {
}
}
} else {
_sg_wgpu_set_bindings_bindgroup(0);
_sg_wgpu_set_bindgroup(0);
}
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_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) {
wgpuBufferDestroy(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_ASSERT(img);
_sg_wgpu_bindgroups_cache_invalidate(_SG_WGPU_BINDGROUPSCACHEITEMTYPE_IMAGE, img->slot.id);
if (img->wgpu.view) {
wgpuTextureViewRelease(img->wgpu.view);
img->wgpu.view = 0;
}
if (img->wgpu.tex) {
wgpuTextureDestroy(img->wgpu.tex);
wgpuTextureRelease(img->wgpu.tex);
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_ASSERT(smp);
_sg_wgpu_bindgroups_cache_invalidate(_SG_WGPU_BINDGROUPSCACHEITEMTYPE_SAMPLER, smp->slot.id);
if (smp->wgpu.smp) {
wgpuSamplerRelease(smp->wgpu.smp);
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_ASSERT(pip);
_sg_wgpu_bindgroups_cache_invalidate(_SG_WGPU_BINDGROUPSCACHEITEMTYPE_PIPELINE, pip->slot.id);
if (pip == _sg.wgpu.cur_pipeline) {
_sg.wgpu.cur_pipeline = 0;
_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(desc->_start_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
if (desc->max_anisotropy > 1) {
_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;
def.min_filter = _sg_def(def.min_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_v = _sg_def(def.wrap_v, 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));
smp_desc.min_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);
}

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) {
switch (f) {
case SG_FILTER_NONE: return "SG_FILTER_NONE";
case SG_FILTER_NEAREST: return "SG_FILTER_NEAREST";
case SG_FILTER_LINEAR: return "SG_FILTER_LINEAR";
default: return "???";
@ -4287,7 +4286,7 @@ _SOKOL_PRIVATE void _sgimgui_draw_frame_stats_panel(sgimgui_t* ctx) {
ImGuiTableFlags_SizingFixedFit |
ImGuiTableFlags_Borders;
if (igBeginTable("##frame_stats_table", 2, flags, IMVEC2(0, 0), 0)) {
igTableSetupScrollFreeze(0, 2);
igTableSetupScrollFreeze(0, 1);
igTableSetupColumn("key", ImGuiTableColumnFlags_None, 0, 0);
igTableSetupColumn("value", ImGuiTableColumnFlags_None, 0, 0);
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_misses);
_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);
break;
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
vertex-, uniform- and command-buffers.
--- each sokol-gl context tracks an internal error code, to query the
current error code for the currently active context call:
--- each sokol-gl context tracks internal error states which can
be obtains via:
sgl_error_t sgl_error()
@ -381,18 +381,28 @@
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()
SGL_ERROR_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())
SGL_ERROR_COMMANDS_FULL - the internal command buffer is full (checked in sgl_end())
SGL_ERROR_STACK_OVERFLOW - matrix- or pipeline-stack overflow
SGL_ERROR_STACK_UNDERFLOW - matrix- or pipeline-stack underflow
SGL_ERROR_NO_CONTEXT - the active context no longer exists
.any - true if any of the below errors is true
.vertices_full - internal vertex buffer is full (checked in sgl_end())
.uniforms_full - the internal uniforms buffer is full (checked in sgl_end())
.commands_full - the internal command buffer is full (checked in sgl_end())
.stack_overflow - matrix- or pipeline-stack overflow
.stack_underflow - matrix- or pipeline-stack underflow
.no_context - the active context no longer exists
...if sokol-gl is in an error-state, sgl_draw() will skip any rendering,
and reset the error code to SGL_NO_ERROR.
...depending on the above error state, sgl_draw() may skip rendering
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
=============
@ -762,14 +772,14 @@ typedef struct sgl_context { uint32_t id; } sgl_context;
Errors are reset each frame after calling sgl_draw(),
get the last error code with sgl_error()
*/
typedef enum sgl_error_t {
SGL_NO_ERROR = 0,
SGL_ERROR_VERTICES_FULL,
SGL_ERROR_UNIFORMS_FULL,
SGL_ERROR_COMMANDS_FULL,
SGL_ERROR_STACK_OVERFLOW,
SGL_ERROR_STACK_UNDERFLOW,
SGL_ERROR_NO_CONTEXT,
typedef struct sgl_error_t {
bool any;
bool vertices_full;
bool uniforms_full;
bool commands_full;
bool stack_overflow;
bool stack_underflow;
bool no_context;
} 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_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) */
SOKOL_GL_API_DECL void sgl_draw(void);
SOKOL_GL_API_DECL void sgl_context_draw(sgl_context ctx);
@ -2342,7 +2356,7 @@ typedef struct {
/* state tracking */
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;
bool in_begin;
int layer_id;
@ -2903,10 +2917,24 @@ static void _sgl_destroy_context(sgl_context ctx_id) {
// ██ ██ ██ ███████ ██████
//
// >>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) {
ctx->in_begin = true;
ctx->base_vertex = ctx->vertices.next;
ctx->vtx_count = 0;
ctx->quad_vtx_count = 0;
ctx->cur_prim_type = mode;
}
@ -2916,7 +2944,7 @@ static void _sgl_rewind(_sgl_context_t* ctx) {
ctx->uniforms.next = 0;
ctx->commands.next = 0;
ctx->base_vertex = 0;
ctx->error = SGL_NO_ERROR;
ctx->error = _sgl_error_defaults();
ctx->layer_id = 0;
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) {
return &ctx->vertices.ptr[ctx->vertices.next++];
} else {
ctx->error = SGL_ERROR_VERTICES_FULL;
ctx->error.vertices_full = true;
ctx->error.any = true;
return 0;
}
}
@ -2947,7 +2976,8 @@ static _sgl_uniform_t* _sgl_next_uniform(_sgl_context_t* ctx) {
if (ctx->uniforms.next < ctx->uniforms.cap) {
return &ctx->uniforms.ptr[ctx->uniforms.next++];
} else {
ctx->error = SGL_ERROR_UNIFORMS_FULL;
ctx->error.uniforms_full = true;
ctx->error.any = true;
return 0;
}
}
@ -2964,7 +2994,8 @@ static _sgl_command_t* _sgl_next_command(_sgl_context_t* ctx) {
if (ctx->commands.next < ctx->commands.cap) {
return &ctx->commands.ptr[ctx->commands.next++];
} else {
ctx->error = SGL_ERROR_COMMANDS_FULL;
ctx->error.commands_full = true;
ctx->error.any = true;
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);
_sgl_vertex_t* vtx;
/* 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
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->psize = ctx->point_size;
}
ctx->vtx_count++;
ctx->quad_vtx_count++;
}
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) {
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");
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);
}
// 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++) {
const _sgl_command_t* cmd = &ctx->commands.ptr[i];
if (cmd->layer_id != layer_id) {
@ -3463,7 +3496,10 @@ SOKOL_API_IMPL sgl_error_t sgl_error(void) {
if (ctx) {
return ctx->error;
} 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) {
return ctx->error;
} 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;
}
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_ASSERT(_SGL_INIT_COOKIE == _sgl.init_cookie);
_sgl_context_t* ctx = _sgl.cur_ctx;
@ -3576,7 +3635,8 @@ SOKOL_API_IMPL void sgl_push_pipeline(void) {
ctx->pip_tos++;
ctx->pip_stack[ctx->pip_tos] = ctx->pip_stack[ctx->pip_tos-1];
} 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) {
ctx->pip_tos--;
} 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->vertices.next >= ctx->base_vertex);
ctx->in_begin = false;
bool matrix_dirty = ctx->matrix_dirty;
if (matrix_dirty) {
ctx->matrix_dirty = false;
@ -3787,6 +3849,12 @@ SOKOL_API_IMPL void sgl_end(void) {
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
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;
@ -4205,7 +4273,8 @@ SOKOL_GL_API_DECL void sgl_push_matrix(void) {
_sgl_matrix_t* dst = _sgl_matrix(ctx);
*dst = *src;
} 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) {
ctx->matrix_tos[ctx->cur_matrix_mode]--;
} 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
#if !defined(SOKOL_IMGUI_NO_SOKOL_APP)
static void _simgui_set_clipboard(void* user_data, const char* text) {
(void)user_data;
static void _simgui_set_clipboard(ImGuiContext* ctx, const char* text) {
(void)ctx;
sapp_set_clipboard_string(text);
}
static const char* _simgui_get_clipboard(void* user_data) {
(void)user_data;
static const char* _simgui_get_clipboard(ImGuiContext* ctx) {
(void)ctx;
return sapp_get_clipboard_string();
}
#endif
@ -2200,6 +2200,7 @@ SOKOL_API_IMPL void simgui_setup(const simgui_desc_t* desc) {
ImGui::CreateContext();
ImGui::StyleColorsDark();
ImGuiIO* io = &ImGui::GetIO();
ImGuiPlatformIO* pio = &ImGui::GetPlatformIO();
if (!_simgui.desc.no_default_font) {
io->Fonts->AddFontDefault();
}
@ -2207,6 +2208,7 @@ SOKOL_API_IMPL void simgui_setup(const simgui_desc_t* desc) {
igCreateContext(NULL);
igStyleColorsDark(igGetStyle());
ImGuiIO* io = igGetIO();
ImGuiPlatformIO* pio = igGetPlatformIO();
if (!_simgui.desc.no_default_font) {
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) {
io->BackendFlags |= ImGuiBackendFlags_HasMouseCursors;
}
io->SetClipboardTextFn = _simgui_set_clipboard;
io->GetClipboardTextFn = _simgui_get_clipboard;
pio->Platform_SetClipboardTextFn = _simgui_set_clipboard;
pio->Platform_GetClipboardTextFn = _simgui_get_clipboard;
#endif
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.min_filter = desc->min_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";
_simgui.font_smp = sg_make_sampler(&font_smp_desc);

View file

@ -236,7 +236,7 @@
.overrides = {
.min_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_v = SG_WRAP_MIRROR,
.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) {
switch (filter) {
case SP_ATLAS_UNKNOWN_FILTER: return _SG_FILTER_DEFAULT;
case SP_ATLAS_NEAREST: return SG_FILTER_NONE;
case SP_ATLAS_LINEAR: return SG_FILTER_NONE;
case SP_ATLAS_MIPMAP: return SG_FILTER_NEAREST;
case SP_ATLAS_MIPMAP_NEAREST_NEAREST: return SG_FILTER_NEAREST;
case SP_ATLAS_MIPMAP_LINEAR_NEAREST: return SG_FILTER_NEAREST;
case SP_ATLAS_MIPMAP_NEAREST_LINEAR: return SG_FILTER_LINEAR;
case SP_ATLAS_MIPMAP_LINEAR_LINEAR: return SG_FILTER_LINEAR;
default: return SG_FILTER_NEAREST;
case SP_ATLAS_UNKNOWN_FILTER:
return _SG_FILTER_DEFAULT;
case SP_ATLAS_NEAREST:
case SP_ATLAS_LINEAR:
case SP_ATLAS_MIPMAP:
case SP_ATLAS_MIPMAP_NEAREST_NEAREST:
case SP_ATLAS_MIPMAP_LINEAR_NEAREST:
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;
}
}