mirror of
https://github.com/Drezil/imgui.git
synced 2024-11-22 20:07:01 +00:00
Fixed range-version of PushID() and GetID() not honoring the ### operator to restart from the seed value.
This commit is contained in:
parent
28901dd104
commit
f14f93ef6e
@ -35,6 +35,7 @@ HOW TO UPDATE?
|
|||||||
|
|
||||||
Other Changes:
|
Other Changes:
|
||||||
- Added .editorconfig file for text editors to standardize using spaces. (#2038) [@kudaba]
|
- Added .editorconfig file for text editors to standardize using spaces. (#2038) [@kudaba]
|
||||||
|
- Fixed range-version of PushID() and GetID() not honoring the ### operator to restart from the seed value.
|
||||||
- ImDrawList: Fixed AddCircle(), AddCircleFilled() angle step being off, which was visible when drawing a "circle"
|
- ImDrawList: Fixed AddCircle(), AddCircleFilled() angle step being off, which was visible when drawing a "circle"
|
||||||
with a small number of segments (e.g. an hexagon). (#2287) [@baktery]
|
with a small number of segments (e.g. an hexagon). (#2287) [@baktery]
|
||||||
- ImGuiTextBuffer: Added append() function (unformatted).
|
- ImGuiTextBuffer: Added append() function (unformatted).
|
||||||
|
78
imgui.cpp
78
imgui.cpp
@ -702,8 +702,8 @@ CODE
|
|||||||
you to animate labels. For example you may want to include varying information in a window title bar,
|
you to animate labels. For example you may want to include varying information in a window title bar,
|
||||||
but windows are uniquely identified by their ID. Use "###" to pass a label that isn't part of ID:
|
but windows are uniquely identified by their ID. Use "###" to pass a label that isn't part of ID:
|
||||||
|
|
||||||
Button("Hello###ID"); // Label = "Hello", ID = hash of (..., "ID")
|
Button("Hello###ID"); // Label = "Hello", ID = hash of (..., "###ID")
|
||||||
Button("World###ID"); // Label = "World", ID = hash of (..., "ID") // Same as above, even though the label looks different
|
Button("World###ID"); // Label = "World", ID = hash of (..., "###ID") // Same as above, even though the label looks different
|
||||||
|
|
||||||
sprintf(buf, "My game (%f FPS)###MyGame", fps);
|
sprintf(buf, "My game (%f FPS)###MyGame", fps);
|
||||||
Begin(buf); // Variable title, ID = hash of "MyGame"
|
Begin(buf); // Variable title, ID = hash of "MyGame"
|
||||||
@ -1435,7 +1435,7 @@ int ImFormatStringV(char* buf, size_t buf_size, const char* fmt, va_list args)
|
|||||||
|
|
||||||
// CRC32 needs a 1KB lookup table (not cache friendly)
|
// CRC32 needs a 1KB lookup table (not cache friendly)
|
||||||
// Although the code to generate the table is simple and shorter than the table itself, using a const table allows us to easily:
|
// Although the code to generate the table is simple and shorter than the table itself, using a const table allows us to easily:
|
||||||
// - avoid an unnecessary branch/memory tap, - keep the ImHash() function usable by static constructors, - make it thread-safe.
|
// - avoid an unnecessary branch/memory tap, - keep the ImHashXXX functions usable by static constructors, - make it thread-safe.
|
||||||
static const ImU32 GCrc32LookupTable[256] =
|
static const ImU32 GCrc32LookupTable[256] =
|
||||||
{
|
{
|
||||||
0x00000000,0x77073096,0xEE0E612C,0x990951BA,0x076DC419,0x706AF48F,0xE963A535,0x9E6495A3,0x0EDB8832,0x79DCB8A4,0xE0D5E91E,0x97D2D988,0x09B64C2B,0x7EB17CBD,0xE7B82D07,0x90BF1D91,
|
0x00000000,0x77073096,0xEE0E612C,0x990951BA,0x076DC419,0x706AF48F,0xE963A535,0x9E6495A3,0x0EDB8832,0x79DCB8A4,0xE0D5E91E,0x97D2D988,0x09B64C2B,0x7EB17CBD,0xE7B82D07,0x90BF1D91,
|
||||||
@ -1456,33 +1456,46 @@ static const ImU32 GCrc32LookupTable[256] =
|
|||||||
0xBDBDF21C,0xCABAC28A,0x53B39330,0x24B4A3A6,0xBAD03605,0xCDD70693,0x54DE5729,0x23D967BF,0xB3667A2E,0xC4614AB8,0x5D681B02,0x2A6F2B94,0xB40BBE37,0xC30C8EA1,0x5A05DF1B,0x2D02EF8D,
|
0xBDBDF21C,0xCABAC28A,0x53B39330,0x24B4A3A6,0xBAD03605,0xCDD70693,0x54DE5729,0x23D967BF,0xB3667A2E,0xC4614AB8,0x5D681B02,0x2A6F2B94,0xB40BBE37,0xC30C8EA1,0x5A05DF1B,0x2D02EF8D,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Pass data_size == 0 for zero-terminated strings, data_size > 0 for non-string data.
|
// Known size hash
|
||||||
// Pay attention that data_size==0 will yield different results than passing strlen(data) because the zero-terminated codepath handles ###.
|
// It is ok to call ImHashData on a string with known length but the ### operator won't be supported.
|
||||||
// This should technically be split into two distinct functions (ImHashData/ImHashStr), perhaps once we remove the silly static variable.
|
|
||||||
// FIXME-OPT: Replace with e.g. FNV1a hash? CRC32 pretty much randomly access 1KB. Need to do proper measurements.
|
// FIXME-OPT: Replace with e.g. FNV1a hash? CRC32 pretty much randomly access 1KB. Need to do proper measurements.
|
||||||
ImU32 ImHash(const void* data, int data_size, ImU32 seed)
|
ImU32 ImHashData(const void* data_p, size_t data_size, ImU32 seed)
|
||||||
|
{
|
||||||
|
ImU32 crc = ~seed;
|
||||||
|
const unsigned char* data = (const unsigned char*)data_p;
|
||||||
|
const ImU32* crc32_lut = GCrc32LookupTable;
|
||||||
|
while (data_size-- != 0)
|
||||||
|
crc = (crc >> 8) ^ crc32_lut[(crc & 0xFF) ^ *data++];
|
||||||
|
return ~crc;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Zero-terminated string hash, with support for ### to reset back to seed value
|
||||||
|
// We support a syntax of "label###id" where only "###id" is included in the hash, and only "label" gets displayed.
|
||||||
|
// Because this syntax is rarely used we are optimizing for the common case.
|
||||||
|
// - If we reach ### in the string we discard the hash so far and reset to the seed.
|
||||||
|
// - We don't do 'current += 2; continue;' after handling ### to keep the code smaller/faster (measured ~10% diff in Debug build)
|
||||||
|
// FIXME-OPT: Replace with e.g. FNV1a hash? CRC32 pretty much randomly access 1KB. Need to do proper measurements.
|
||||||
|
ImU32 ImHashStr(const char* data, size_t data_size, ImU32 seed)
|
||||||
{
|
{
|
||||||
seed = ~seed;
|
seed = ~seed;
|
||||||
ImU32 crc = seed;
|
ImU32 crc = seed;
|
||||||
const unsigned char* current = (const unsigned char*)data;
|
const unsigned char* src = (const unsigned char*)data;
|
||||||
const ImU32* crc32_lut = GCrc32LookupTable;
|
const ImU32* crc32_lut = GCrc32LookupTable;
|
||||||
|
if (data_size != 0)
|
||||||
if (data_size > 0)
|
|
||||||
{
|
{
|
||||||
// Known size
|
while (data_size-- != 0)
|
||||||
while (data_size--)
|
{
|
||||||
crc = (crc >> 8) ^ crc32_lut[(crc & 0xFF) ^ *current++];
|
unsigned char c = *src++;
|
||||||
|
if (c == '#' && src[0] == '#' && src[1] == '#')
|
||||||
|
crc = seed;
|
||||||
|
crc = (crc >> 8) ^ crc32_lut[(crc & 0xFF) ^ c];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Zero-terminated string
|
while (unsigned char c = *src++)
|
||||||
while (unsigned char c = *current++)
|
|
||||||
{
|
{
|
||||||
// We support a syntax of "label###id" where only "###id" is included in the hash, and only "label" gets displayed.
|
if (c == '#' && src[0] == '#' && src[1] == '#')
|
||||||
// Because this syntax is rarely used we are optimizing for the common case.
|
|
||||||
// - If we reach ### in the string we discard the hash so far and reset to the seed.
|
|
||||||
// - We don't do 'current += 2; continue;' after handling ### to keep the code smaller.
|
|
||||||
if (c == '#' && current[0] == '#' && current[1] == '#')
|
|
||||||
crc = seed;
|
crc = seed;
|
||||||
crc = (crc >> 8) ^ crc32_lut[(crc & 0xFF) ^ c];
|
crc = (crc >> 8) ^ crc32_lut[(crc & 0xFF) ^ c];
|
||||||
}
|
}
|
||||||
@ -2479,7 +2492,7 @@ ImGuiWindow::ImGuiWindow(ImGuiContext* context, const char* name)
|
|||||||
: DrawListInst(&context->DrawListSharedData)
|
: DrawListInst(&context->DrawListSharedData)
|
||||||
{
|
{
|
||||||
Name = ImStrdup(name);
|
Name = ImStrdup(name);
|
||||||
ID = ImHash(name, 0);
|
ID = ImHashStr(name, 0);
|
||||||
IDStack.push_back(ID);
|
IDStack.push_back(ID);
|
||||||
Flags = ImGuiWindowFlags_None;
|
Flags = ImGuiWindowFlags_None;
|
||||||
Pos = ImVec2(0.0f, 0.0f);
|
Pos = ImVec2(0.0f, 0.0f);
|
||||||
@ -2547,9 +2560,8 @@ ImGuiWindow::~ImGuiWindow()
|
|||||||
|
|
||||||
ImGuiID ImGuiWindow::GetID(const char* str, const char* str_end)
|
ImGuiID ImGuiWindow::GetID(const char* str, const char* str_end)
|
||||||
{
|
{
|
||||||
// FIXME: ImHash with str_end doesn't behave same as with identical zero-terminated string, because of ### handling.
|
|
||||||
ImGuiID seed = IDStack.back();
|
ImGuiID seed = IDStack.back();
|
||||||
ImGuiID id = ImHash(str, str_end ? (int)(str_end - str) : 0, seed);
|
ImGuiID id = ImHashStr(str, str_end ? (str_end - str) : 0, seed);
|
||||||
ImGui::KeepAliveID(id);
|
ImGui::KeepAliveID(id);
|
||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
@ -2557,7 +2569,7 @@ ImGuiID ImGuiWindow::GetID(const char* str, const char* str_end)
|
|||||||
ImGuiID ImGuiWindow::GetID(const void* ptr)
|
ImGuiID ImGuiWindow::GetID(const void* ptr)
|
||||||
{
|
{
|
||||||
ImGuiID seed = IDStack.back();
|
ImGuiID seed = IDStack.back();
|
||||||
ImGuiID id = ImHash(&ptr, sizeof(void*), seed);
|
ImGuiID id = ImHashData(&ptr, sizeof(void*), seed);
|
||||||
ImGui::KeepAliveID(id);
|
ImGui::KeepAliveID(id);
|
||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
@ -2565,13 +2577,13 @@ ImGuiID ImGuiWindow::GetID(const void* ptr)
|
|||||||
ImGuiID ImGuiWindow::GetIDNoKeepAlive(const char* str, const char* str_end)
|
ImGuiID ImGuiWindow::GetIDNoKeepAlive(const char* str, const char* str_end)
|
||||||
{
|
{
|
||||||
ImGuiID seed = IDStack.back();
|
ImGuiID seed = IDStack.back();
|
||||||
return ImHash(str, str_end ? (int)(str_end - str) : 0, seed);
|
return ImHashStr(str, str_end ? (str_end - str) : 0, seed);
|
||||||
}
|
}
|
||||||
|
|
||||||
ImGuiID ImGuiWindow::GetIDNoKeepAlive(const void* ptr)
|
ImGuiID ImGuiWindow::GetIDNoKeepAlive(const void* ptr)
|
||||||
{
|
{
|
||||||
ImGuiID seed = IDStack.back();
|
ImGuiID seed = IDStack.back();
|
||||||
return ImHash(&ptr, sizeof(void*), seed);
|
return ImHashData(&ptr, sizeof(void*), seed);
|
||||||
}
|
}
|
||||||
|
|
||||||
// This is only used in rare/specific situations to manufacture an ID out of nowhere.
|
// This is only used in rare/specific situations to manufacture an ID out of nowhere.
|
||||||
@ -2579,7 +2591,7 @@ ImGuiID ImGuiWindow::GetIDFromRectangle(const ImRect& r_abs)
|
|||||||
{
|
{
|
||||||
ImGuiID seed = IDStack.back();
|
ImGuiID seed = IDStack.back();
|
||||||
const int r_rel[4] = { (int)(r_abs.Min.x - Pos.x), (int)(r_abs.Min.y - Pos.y), (int)(r_abs.Max.x - Pos.x), (int)(r_abs.Max.y - Pos.y) };
|
const int r_rel[4] = { (int)(r_abs.Min.x - Pos.x), (int)(r_abs.Min.y - Pos.y), (int)(r_abs.Max.x - Pos.x), (int)(r_abs.Max.y - Pos.y) };
|
||||||
ImGuiID id = ImHash(&r_rel, sizeof(r_rel), seed);
|
ImGuiID id = ImHashData(&r_rel, sizeof(r_rel), seed);
|
||||||
ImGui::KeepAliveID(id);
|
ImGui::KeepAliveID(id);
|
||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
@ -3523,7 +3535,7 @@ void ImGui::Initialize(ImGuiContext* context)
|
|||||||
// Add .ini handle for ImGuiWindow type
|
// Add .ini handle for ImGuiWindow type
|
||||||
ImGuiSettingsHandler ini_handler;
|
ImGuiSettingsHandler ini_handler;
|
||||||
ini_handler.TypeName = "Window";
|
ini_handler.TypeName = "Window";
|
||||||
ini_handler.TypeHash = ImHash("Window", 0, 0);
|
ini_handler.TypeHash = ImHashStr("Window", 0);
|
||||||
ini_handler.ReadOpenFn = SettingsHandlerWindow_ReadOpen;
|
ini_handler.ReadOpenFn = SettingsHandlerWindow_ReadOpen;
|
||||||
ini_handler.ReadLineFn = SettingsHandlerWindow_ReadLine;
|
ini_handler.ReadLineFn = SettingsHandlerWindow_ReadLine;
|
||||||
ini_handler.WriteAllFn = SettingsHandlerWindow_WriteAll;
|
ini_handler.WriteAllFn = SettingsHandlerWindow_WriteAll;
|
||||||
@ -4432,7 +4444,7 @@ ImGuiWindow* ImGui::FindWindowByID(ImGuiID id)
|
|||||||
|
|
||||||
ImGuiWindow* ImGui::FindWindowByName(const char* name)
|
ImGuiWindow* ImGui::FindWindowByName(const char* name)
|
||||||
{
|
{
|
||||||
ImGuiID id = ImHash(name, 0);
|
ImGuiID id = ImHashStr(name, 0);
|
||||||
return FindWindowByID(id);
|
return FindWindowByID(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -8437,7 +8449,7 @@ bool ImGui::BeginDragDropSource(ImGuiDragDropFlags flags)
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
window = NULL;
|
window = NULL;
|
||||||
source_id = ImHash("#SourceExtern", 0);
|
source_id = ImHashStr("#SourceExtern", 0);
|
||||||
source_drag_active = true;
|
source_drag_active = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -8852,7 +8864,7 @@ ImGuiWindowSettings* ImGui::CreateNewWindowSettings(const char* name)
|
|||||||
g.SettingsWindows.push_back(ImGuiWindowSettings());
|
g.SettingsWindows.push_back(ImGuiWindowSettings());
|
||||||
ImGuiWindowSettings* settings = &g.SettingsWindows.back();
|
ImGuiWindowSettings* settings = &g.SettingsWindows.back();
|
||||||
settings->Name = ImStrdup(name);
|
settings->Name = ImStrdup(name);
|
||||||
settings->ID = ImHash(name, 0);
|
settings->ID = ImHashStr(name, 0);
|
||||||
return settings;
|
return settings;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -8878,7 +8890,7 @@ void ImGui::LoadIniSettingsFromDisk(const char* ini_filename)
|
|||||||
ImGuiSettingsHandler* ImGui::FindSettingsHandler(const char* type_name)
|
ImGuiSettingsHandler* ImGui::FindSettingsHandler(const char* type_name)
|
||||||
{
|
{
|
||||||
ImGuiContext& g = *GImGui;
|
ImGuiContext& g = *GImGui;
|
||||||
const ImGuiID type_hash = ImHash(type_name, 0, 0);
|
const ImGuiID type_hash = ImHashStr(type_name, 0);
|
||||||
for (int handler_n = 0; handler_n < g.SettingsHandlers.Size; handler_n++)
|
for (int handler_n = 0; handler_n < g.SettingsHandlers.Size; handler_n++)
|
||||||
if (g.SettingsHandlers[handler_n].TypeHash == type_hash)
|
if (g.SettingsHandlers[handler_n].TypeHash == type_hash)
|
||||||
return &g.SettingsHandlers[handler_n];
|
return &g.SettingsHandlers[handler_n];
|
||||||
@ -8982,7 +8994,7 @@ const char* ImGui::SaveIniSettingsToMemory(size_t* out_size)
|
|||||||
|
|
||||||
static void* SettingsHandlerWindow_ReadOpen(ImGuiContext*, ImGuiSettingsHandler*, const char* name)
|
static void* SettingsHandlerWindow_ReadOpen(ImGuiContext*, ImGuiSettingsHandler*, const char* name)
|
||||||
{
|
{
|
||||||
ImGuiWindowSettings* settings = ImGui::FindWindowSettings(ImHash(name, 0));
|
ImGuiWindowSettings* settings = ImGui::FindWindowSettings(ImHashStr(name, 0));
|
||||||
if (!settings)
|
if (!settings)
|
||||||
settings = ImGui::CreateNewWindowSettings(name);
|
settings = ImGui::CreateNewWindowSettings(name);
|
||||||
return (void*)settings;
|
return (void*)settings;
|
||||||
|
@ -147,7 +147,8 @@ IMGUI_API int ImTextCountUtf8BytesFromChar(const char* in_text, const
|
|||||||
IMGUI_API int ImTextCountUtf8BytesFromStr(const ImWchar* in_text, const ImWchar* in_text_end); // return number of bytes to express string in UTF-8
|
IMGUI_API int ImTextCountUtf8BytesFromStr(const ImWchar* in_text, const ImWchar* in_text_end); // return number of bytes to express string in UTF-8
|
||||||
|
|
||||||
// Helpers: Misc
|
// Helpers: Misc
|
||||||
IMGUI_API ImU32 ImHash(const void* data, int data_size, ImU32 seed = 0); // Pass data_size==0 for zero-terminated strings
|
IMGUI_API ImU32 ImHashData(const void* data, size_t data_size, ImU32 seed = 0);
|
||||||
|
IMGUI_API ImU32 ImHashStr(const char* data, size_t data_size, ImU32 seed = 0);
|
||||||
IMGUI_API void* ImFileLoadToMemory(const char* filename, const char* file_open_mode, size_t* out_file_size = NULL, int padding_bytes = 0);
|
IMGUI_API void* ImFileLoadToMemory(const char* filename, const char* file_open_mode, size_t* out_file_size = NULL, int padding_bytes = 0);
|
||||||
IMGUI_API FILE* ImFileOpen(const char* filename, const char* file_open_mode);
|
IMGUI_API FILE* ImFileOpen(const char* filename, const char* file_open_mode);
|
||||||
static inline bool ImCharIsBlankA(char c) { return c == ' ' || c == '\t'; }
|
static inline bool ImCharIsBlankA(char c) { return c == ' ' || c == '\t'; }
|
||||||
@ -155,6 +156,9 @@ static inline bool ImCharIsBlankW(unsigned int c) { return c == ' ' || c =
|
|||||||
static inline bool ImIsPowerOfTwo(int v) { return v != 0 && (v & (v - 1)) == 0; }
|
static inline bool ImIsPowerOfTwo(int v) { return v != 0 && (v & (v - 1)) == 0; }
|
||||||
static inline int ImUpperPowerOfTwo(int v) { v--; v |= v >> 1; v |= v >> 2; v |= v >> 4; v |= v >> 8; v |= v >> 16; v++; return v; }
|
static inline int ImUpperPowerOfTwo(int v) { v--; v |= v >> 1; v |= v >> 2; v |= v >> 4; v |= v >> 8; v |= v >> 16; v++; return v; }
|
||||||
#define ImQsort qsort
|
#define ImQsort qsort
|
||||||
|
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
|
||||||
|
static inline ImU32 ImHash(const void* data, int size, ImU32 seed = 0) { return size ? ImHashData(data, (size_t)size, seed) : ImHashStr((const char*)data, 0, seed); } // [moved to ImHashStr/ImHashData in 1.68]
|
||||||
|
#endif
|
||||||
|
|
||||||
// Helpers: Geometry
|
// Helpers: Geometry
|
||||||
IMGUI_API ImVec2 ImLineClosestPoint(const ImVec2& a, const ImVec2& b, const ImVec2& p);
|
IMGUI_API ImVec2 ImLineClosestPoint(const ImVec2& a, const ImVec2& b, const ImVec2& p);
|
||||||
|
@ -6084,7 +6084,7 @@ static ImU32 ImGui::TabBarCalcTabID(ImGuiTabBar* tab_bar, const char* label)
|
|||||||
{
|
{
|
||||||
if (tab_bar->Flags & ImGuiTabBarFlags_DockNode)
|
if (tab_bar->Flags & ImGuiTabBarFlags_DockNode)
|
||||||
{
|
{
|
||||||
ImGuiID id = ImHash(label, 0);
|
ImGuiID id = ImHashStr(label, 0);
|
||||||
KeepAliveID(id);
|
KeepAliveID(id);
|
||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user