From 4b7be31197ca3bad44ec9d9a12a94001ab097b74 Mon Sep 17 00:00:00 2001 From: Dale Kim Date: Fri, 3 Apr 2015 09:01:48 -0500 Subject: [PATCH 01/19] Fixed modifier key state setting in GLFW callbacks. --- .../opengl3_example/imgui_impl_glfw_gl3.cpp | 44 ++++++++++++++++--- examples/opengl_example/imgui_impl_glfw.cpp | 44 ++++++++++++++++--- 2 files changed, 78 insertions(+), 10 deletions(-) diff --git a/examples/opengl3_example/imgui_impl_glfw_gl3.cpp b/examples/opengl3_example/imgui_impl_glfw_gl3.cpp index 1cd2faf0..fa756500 100644 --- a/examples/opengl3_example/imgui_impl_glfw_gl3.cpp +++ b/examples/opengl3_example/imgui_impl_glfw_gl3.cpp @@ -138,12 +138,46 @@ void ImGui_ImplGlfwGL3_KeyCallback(GLFWwindow*, int key, int, int action, int mo { ImGuiIO& io = ImGui::GetIO(); if (action == GLFW_PRESS) - io.KeysDown[key] = true; + { + switch (key) + { + case GLFW_KEY_LEFT_CONTROL: + case GLFW_KEY_RIGHT_CONTROL: + io.KeyCtrl = true; + break; + case GLFW_KEY_LEFT_SHIFT: + case GLFW_KEY_RIGHT_SHIFT: + io.KeyShift = true; + break; + case GLFW_KEY_LEFT_ALT: + case GLFW_KEY_RIGHT_ALT: + io.KeyAlt = true; + break; + default: + io.KeysDown[key] = true; + } + } + if (action == GLFW_RELEASE) - io.KeysDown[key] = false; - io.KeyCtrl = (mods & GLFW_MOD_CONTROL) != 0; - io.KeyShift = (mods & GLFW_MOD_SHIFT) != 0; - io.KeyAlt = (mods & GLFW_MOD_ALT) != 0; + { + switch (key) + { + case GLFW_KEY_LEFT_CONTROL: + case GLFW_KEY_RIGHT_CONTROL: + io.KeyCtrl = false; + break; + case GLFW_KEY_LEFT_SHIFT: + case GLFW_KEY_RIGHT_SHIFT: + io.KeyShift = false; + break; + case GLFW_KEY_LEFT_ALT: + case GLFW_KEY_RIGHT_ALT: + io.KeyAlt = false; + break; + default: + io.KeysDown[key] = false; + } + } } void ImGui_ImplGlfwGL3_CharCallback(GLFWwindow*, unsigned int c) diff --git a/examples/opengl_example/imgui_impl_glfw.cpp b/examples/opengl_example/imgui_impl_glfw.cpp index 8c9cb216..3349a266 100644 --- a/examples/opengl_example/imgui_impl_glfw.cpp +++ b/examples/opengl_example/imgui_impl_glfw.cpp @@ -119,12 +119,46 @@ void ImGui_ImplGlFw_KeyCallback(GLFWwindow*, int key, int, int action, int mods) { ImGuiIO& io = ImGui::GetIO(); if (action == GLFW_PRESS) - io.KeysDown[key] = true; + { + switch (key) + { + case GLFW_KEY_LEFT_CONTROL: + case GLFW_KEY_RIGHT_CONTROL: + io.KeyCtrl = true; + break; + case GLFW_KEY_LEFT_SHIFT: + case GLFW_KEY_RIGHT_SHIFT: + io.KeyShift = true; + break; + case GLFW_KEY_LEFT_ALT: + case GLFW_KEY_RIGHT_ALT: + io.KeyAlt = true; + break; + default: + io.KeysDown[key] = true; + } + } + if (action == GLFW_RELEASE) - io.KeysDown[key] = false; - io.KeyCtrl = (mods & GLFW_MOD_CONTROL) != 0; - io.KeyShift = (mods & GLFW_MOD_SHIFT) != 0; - io.KeyAlt = (mods & GLFW_MOD_ALT) != 0; + { + switch (key) + { + case GLFW_KEY_LEFT_CONTROL: + case GLFW_KEY_RIGHT_CONTROL: + io.KeyCtrl = false; + break; + case GLFW_KEY_LEFT_SHIFT: + case GLFW_KEY_RIGHT_SHIFT: + io.KeyShift = false; + break; + case GLFW_KEY_LEFT_ALT: + case GLFW_KEY_RIGHT_ALT: + io.KeyAlt = false; + break; + default: + io.KeysDown[key] = false; + } + } } void ImGui_ImplGlfw_CharCallback(GLFWwindow*, unsigned int c) From d809abbe1c6bb67ccb7b2b9ce7e1de9886abbe6c Mon Sep 17 00:00:00 2001 From: ocornut Date: Thu, 9 Apr 2015 23:32:36 +0100 Subject: [PATCH 02/19] Examples: DirectX11: tidying up. --- examples/directx11_example/imgui_impl_dx11.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/examples/directx11_example/imgui_impl_dx11.cpp b/examples/directx11_example/imgui_impl_dx11.cpp index 4b5513ad..a18ba09e 100644 --- a/examples/directx11_example/imgui_impl_dx11.cpp +++ b/examples/directx11_example/imgui_impl_dx11.cpp @@ -47,8 +47,7 @@ static void ImGui_ImplDX11_RenderDrawLists(ImDrawList** const cmd_lists, int cmd for (int n = 0; n < cmd_lists_count; n++) { const ImDrawList* cmd_list = cmd_lists[n]; - const ImDrawVert* vtx_src = &cmd_list->vtx_buffer[0]; - memcpy(vtx_dst, vtx_src, cmd_list->vtx_buffer.size() * sizeof(ImDrawVert)); + memcpy(vtx_dst, &cmd_list->vtx_buffer[0], cmd_list->vtx_buffer.size() * sizeof(ImDrawVert)); vtx_dst += cmd_list->vtx_buffer.size(); } g_pd3dDeviceContext->Unmap(g_pVB, 0); From ac740170b966e6ffa3cb021abd290192585d4164 Mon Sep 17 00:00:00 2001 From: ocornut Date: Sat, 11 Apr 2015 17:52:51 +0100 Subject: [PATCH 03/19] Added ImFontAtlas::AddFontFromCompressedTTF() helper + binary_to_compressed_c.cpp tool --- extra_fonts/binary_to_compressed_c.cpp | 330 +++++++++++++++++++++++++ imgui.cpp | 23 +- imgui.h | 3 +- 3 files changed, 345 insertions(+), 11 deletions(-) create mode 100644 extra_fonts/binary_to_compressed_c.cpp diff --git a/extra_fonts/binary_to_compressed_c.cpp b/extra_fonts/binary_to_compressed_c.cpp new file mode 100644 index 00000000..e5e3b00a --- /dev/null +++ b/extra_fonts/binary_to_compressed_c.cpp @@ -0,0 +1,330 @@ +// ImGui - binary_to_compressed_c.cpp +// Helper tool to turn a file into a C array. +// The data is first compressed with stb_compress() to reduce source code size a little. +// Useful if you want to embed fonts into your code. +// Note that the output array is likely to be bigger than the binary file.. +// Load compressed TTF fonts with ImGui::GetIO().Fonts->AddFontFromMemoryCompressedTTF() + +#define _CRT_SECURE_NO_WARNINGS +#include +#include +#include +#include + +const int COLUMNS = 12; + +// stb_compress* from stb.h - declaration +typedef unsigned int stb_uint; +typedef unsigned char stb_uchar; +stb_uint stb_compress(stb_uchar *out,stb_uchar *in,stb_uint len); + +static bool binary_to_compressed_c(const char* filename, const char* symbol); + +int main(int argc, char** argv) +{ + if (argc < 3) + { + printf("Syntax: %s \n", argv[0]); + return 0; + } + + binary_to_compressed_c(argv[1], argv[2]); + return 1; +} + +bool binary_to_compressed_c(const char* filename, const char* symbol) +{ + // Read file + FILE* f = fopen(filename, "rb"); + if (!f) return false; + int data_sz; + if (fseek(f, 0, SEEK_END) || (data_sz = (int)ftell(f)) == -1 || fseek(f, 0, SEEK_SET)) { fclose(f); return false; } + char* data = new char[data_sz+4]; + if (fread(data, 1, data_sz, f) != (size_t)data_sz) { fclose(f); delete[] data; return false; } + memset((void *)(((char*)data) + data_sz), 0, 4); + fclose(f); + + // Compress + int maxlen = data_sz + 512 + (data_sz >> 2) + sizeof(int); // total guess + char* compressed = new char[maxlen]; + int compressed_sz = stb_compress((stb_uchar*)compressed, (stb_uchar*)data, data_sz); + memset(compressed + compressed_sz, 0, maxlen - compressed_sz); + + // Output + FILE* out = stdout; + fprintf(out, "// File: '%s' (%d bytes)\n", filename, (int)data_sz); + fprintf(out, "// Exported using binary_to_compressed_c\n"); + fprintf(out, "static const unsigned int %s_compressed_size = %d;\n", symbol, (int)compressed_sz); + fprintf(out, "static const unsigned int %s_compressed_data[%d/4] =\n{", symbol, (int)((compressed_sz+3)/4)*4); + int column = 0; + for (int i = 0; i < compressed_sz; i += 4) + { + unsigned int d = *(unsigned int*)(compressed + i); + if ((column++ % COLUMNS) == 0) + fprintf(out, "\n 0x%08x, ", d); + else + fprintf(out, "0x%08x, ", d); + } + fprintf(out, "\n};\n\n"); + + // Cleanup + delete[] data; + delete[] compressed; + return true; +} + +// stb_compress* from stb.h - definition + +//////////////////// compressor /////////////////////// + +static stb_uint stb_adler32(stb_uint adler32, stb_uchar *buffer, stb_uint buflen) +{ + const unsigned long ADLER_MOD = 65521; + unsigned long s1 = adler32 & 0xffff, s2 = adler32 >> 16; + unsigned long blocklen, i; + + blocklen = buflen % 5552; + while (buflen) { + for (i=0; i + 7 < blocklen; i += 8) { + s1 += buffer[0], s2 += s1; + s1 += buffer[1], s2 += s1; + s1 += buffer[2], s2 += s1; + s1 += buffer[3], s2 += s1; + s1 += buffer[4], s2 += s1; + s1 += buffer[5], s2 += s1; + s1 += buffer[6], s2 += s1; + s1 += buffer[7], s2 += s1; + + buffer += 8; + } + + for (; i < blocklen; ++i) + s1 += *buffer++, s2 += s1; + + s1 %= ADLER_MOD, s2 %= ADLER_MOD; + buflen -= blocklen; + blocklen = 5552; + } + return (s2 << 16) + s1; +} + +static unsigned int stb_matchlen(stb_uchar *m1, stb_uchar *m2, stb_uint maxlen) +{ + stb_uint i; + for (i=0; i < maxlen; ++i) + if (m1[i] != m2[i]) return i; + return i; +} + +// simple implementation that just takes the source data in a big block + +static stb_uchar *stb__out; +static FILE *stb__outfile; +static stb_uint stb__outbytes; + +static void stb__write(unsigned char v) +{ + fputc(v, stb__outfile); + ++stb__outbytes; +} + +#define stb_out(v) (stb__out ? *stb__out++ = (stb_uchar) (v) : stb__write((stb_uchar) (v))) + +static void stb_out2(stb_uint v) +{ + stb_out(v >> 8); + stb_out(v); +} + +static void stb_out3(stb_uint v) { stb_out(v >> 16); stb_out(v >> 8); stb_out(v); } +static void stb_out4(stb_uint v) { stb_out(v >> 24); stb_out(v >> 16); +stb_out(v >> 8 ); stb_out(v); } + +static void outliterals(stb_uchar *in, int numlit) +{ + while (numlit > 65536) { + outliterals(in,65536); + in += 65536; + numlit -= 65536; + } + + if (numlit == 0) ; + else if (numlit <= 32) stb_out (0x000020 + numlit-1); + else if (numlit <= 2048) stb_out2(0x000800 + numlit-1); + else /* numlit <= 65536) */ stb_out3(0x070000 + numlit-1); + + if (stb__out) { + memcpy(stb__out,in,numlit); + stb__out += numlit; + } else + fwrite(in, 1, numlit, stb__outfile); +} + +static int stb__window = 0x40000; // 256K + +static int stb_not_crap(int best, int dist) +{ + return ((best > 2 && dist <= 0x00100) + || (best > 5 && dist <= 0x04000) + || (best > 7 && dist <= 0x80000)); +} + +static stb_uint stb__hashsize = 32768; + +// note that you can play with the hashing functions all you +// want without needing to change the decompressor +#define stb__hc(q,h,c) (((h) << 7) + ((h) >> 25) + q[c]) +#define stb__hc2(q,h,c,d) (((h) << 14) + ((h) >> 18) + (q[c] << 7) + q[d]) +#define stb__hc3(q,c,d,e) ((q[c] << 14) + (q[d] << 7) + q[e]) + +static unsigned int stb__running_adler; + +static int stb_compress_chunk(stb_uchar *history, + stb_uchar *start, + stb_uchar *end, + int length, + int *pending_literals, + stb_uchar **chash, + stb_uint mask) +{ + (void)history; + int window = stb__window; + stb_uint match_max; + stb_uchar *lit_start = start - *pending_literals; + stb_uchar *q = start; + +#define STB__SCRAMBLE(h) (((h) + ((h) >> 16)) & mask) + + // stop short of the end so we don't scan off the end doing + // the hashing; this means we won't compress the last few bytes + // unless they were part of something longer + while (q < start+length && q+12 < end) { + int m; + stb_uint h1,h2,h3,h4, h; + stb_uchar *t; + int best = 2, dist=0; + + if (q+65536 > end) + match_max = end-q; + else + match_max = 65536; + +#define stb__nc(b,d) ((d) <= window && ((b) > 9 || stb_not_crap(b,d))) + +#define STB__TRY(t,p) /* avoid retrying a match we already tried */ \ + if (p ? dist != q-t : 1) \ + if ((m = stb_matchlen(t, q, match_max)) > best) \ + if (stb__nc(m,q-(t))) \ + best = m, dist = q - (t) + + // rather than search for all matches, only try 4 candidate locations, + // chosen based on 4 different hash functions of different lengths. + // this strategy is inspired by LZO; hashing is unrolled here using the + // 'hc' macro + h = stb__hc3(q,0, 1, 2); h1 = STB__SCRAMBLE(h); + t = chash[h1]; if (t) STB__TRY(t,0); + h = stb__hc2(q,h, 3, 4); h2 = STB__SCRAMBLE(h); + h = stb__hc2(q,h, 5, 6); t = chash[h2]; if (t) STB__TRY(t,1); + h = stb__hc2(q,h, 7, 8); h3 = STB__SCRAMBLE(h); + h = stb__hc2(q,h, 9,10); t = chash[h3]; if (t) STB__TRY(t,1); + h = stb__hc2(q,h,11,12); h4 = STB__SCRAMBLE(h); + t = chash[h4]; if (t) STB__TRY(t,1); + + // because we use a shared hash table, can only update it + // _after_ we've probed all of them + chash[h1] = chash[h2] = chash[h3] = chash[h4] = q; + + if (best > 2) + assert(dist > 0); + + // see if our best match qualifies + if (best < 3) { // fast path literals + ++q; + } else if (best > 2 && best <= 0x80 && dist <= 0x100) { + outliterals(lit_start, q-lit_start); lit_start = (q += best); + stb_out(0x80 + best-1); + stb_out(dist-1); + } else if (best > 5 && best <= 0x100 && dist <= 0x4000) { + outliterals(lit_start, q-lit_start); lit_start = (q += best); + stb_out2(0x4000 + dist-1); + stb_out(best-1); + } else if (best > 7 && best <= 0x100 && dist <= 0x80000) { + outliterals(lit_start, q-lit_start); lit_start = (q += best); + stb_out3(0x180000 + dist-1); + stb_out(best-1); + } else if (best > 8 && best <= 0x10000 && dist <= 0x80000) { + outliterals(lit_start, q-lit_start); lit_start = (q += best); + stb_out3(0x100000 + dist-1); + stb_out2(best-1); + } else if (best > 9 && dist <= 0x1000000) { + if (best > 65536) best = 65536; + outliterals(lit_start, q-lit_start); lit_start = (q += best); + if (best <= 0x100) { + stb_out(0x06); + stb_out3(dist-1); + stb_out(best-1); + } else { + stb_out(0x04); + stb_out3(dist-1); + stb_out2(best-1); + } + } else { // fallback literals if no match was a balanced tradeoff + ++q; + } + } + + // if we didn't get all the way, add the rest to literals + if (q-start < length) + q = start+length; + + // the literals are everything from lit_start to q + *pending_literals = (q - lit_start); + + stb__running_adler = stb_adler32(stb__running_adler, start, q - start); + return q - start; +} + +static int stb_compress_inner(stb_uchar *input, stb_uint length) +{ + int literals = 0; + stb_uint len,i; + + stb_uchar **chash; + chash = (stb_uchar**) malloc(stb__hashsize * sizeof(stb_uchar*)); + if (chash == NULL) return 0; // failure + for (i=0; i < stb__hashsize; ++i) + chash[i] = NULL; + + // stream signature + stb_out(0x57); stb_out(0xbc); + stb_out2(0); + + stb_out4(0); // 64-bit length requires 32-bit leading 0 + stb_out4(length); + stb_out4(stb__window); + + stb__running_adler = 1; + + len = stb_compress_chunk(input, input, input+length, length, &literals, chash, stb__hashsize-1); + assert(len == length); + + outliterals(input+length - literals, literals); + + free(chash); + + stb_out2(0x05fa); // end opcode + + stb_out4(stb__running_adler); + + return 1; // success +} + +stb_uint stb_compress(stb_uchar *out, stb_uchar *input, stb_uint length) +{ + stb__out = out; + stb__outfile = NULL; + + stb_compress_inner(input, length); + + return stb__out - out; +} diff --git a/imgui.cpp b/imgui.cpp index fe12074d..d70f72bc 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -8101,18 +8101,10 @@ static unsigned int stb_decompress(unsigned char *output, unsigned char *i, unsi // Load embedded ProggyClean.ttf at size 13 ImFont* ImFontAtlas::AddFontDefault() { - // Get compressed data unsigned int ttf_compressed_size; const void* ttf_compressed; GetDefaultCompressedFontDataTTF(&ttf_compressed, &ttf_compressed_size); - - // Decompress - const size_t buf_decompressed_size = stb_decompress_length((unsigned char*)ttf_compressed); - unsigned char* buf_decompressed = (unsigned char *)ImGui::MemAlloc(buf_decompressed_size); - stb_decompress(buf_decompressed, (unsigned char*)ttf_compressed, ttf_compressed_size); - - // Add - ImFont* font = AddFontFromMemoryTTF(buf_decompressed, buf_decompressed_size, 13.0f, GetGlyphRangesDefault(), 0); + ImFont* font = AddFontFromMemoryCompressedTTF(ttf_compressed, ttf_compressed_size, 13.0f, GetGlyphRangesDefault(), 0); font->DisplayOffset.y += 1; return font; } @@ -8127,7 +8119,6 @@ ImFont* ImFontAtlas::AddFontFromFileTTF(const char* filename, float size_pixels, return NULL; } - // Add ImFont* font = AddFontFromMemoryTTF(data, data_size, size_pixels, glyph_ranges, font_no); return font; } @@ -8157,6 +8148,18 @@ ImFont* ImFontAtlas::AddFontFromMemoryTTF(void* in_ttf_data, size_t in_ttf_data_ return font; } +ImFont* ImFontAtlas::AddFontFromMemoryCompressedTTF(const void* in_compressed_ttf_data, size_t in_compressed_ttf_data_size, float size_pixels, const ImWchar* glyph_ranges, int font_no) +{ + // Decompress + const size_t buf_decompressed_size = stb_decompress_length((unsigned char*)in_compressed_ttf_data); + unsigned char* buf_decompressed = (unsigned char *)ImGui::MemAlloc(buf_decompressed_size); + stb_decompress(buf_decompressed, (unsigned char*)in_compressed_ttf_data, in_compressed_ttf_data_size); + + // Add + ImFont* font = AddFontFromMemoryTTF(buf_decompressed, buf_decompressed_size, size_pixels, glyph_ranges, font_no); + return font; +} + bool ImFontAtlas::Build() { IM_ASSERT(InputData.size() > 0); diff --git a/imgui.h b/imgui.h index 1ff50c6e..00547089 100644 --- a/imgui.h +++ b/imgui.h @@ -947,7 +947,8 @@ struct ImFontAtlas IMGUI_API ~ImFontAtlas(); IMGUI_API ImFont* AddFontDefault(); IMGUI_API ImFont* AddFontFromFileTTF(const char* filename, float size_pixels, const ImWchar* glyph_ranges = NULL, int font_no = 0); - IMGUI_API ImFont* AddFontFromMemoryTTF(void* in_ttf_data, size_t in_ttf_data_size, float size_pixels, const ImWchar* glyph_ranges = NULL, int font_no = 0); // Pass ownership of 'in_ttf_data' memory. + IMGUI_API ImFont* AddFontFromMemoryTTF(void* in_ttf_data, unsigned int in_ttf_data_size, float size_pixels, const ImWchar* glyph_ranges = NULL, int font_no = 0); // Pass ownership of 'in_ttf_data' memory, will be deleted after build + IMGUI_API ImFont* AddFontFromMemoryCompressedTTF(const void* in_compressed_ttf_data, unsigned int in_compressed_ttf_data_size, float size_pixels, const ImWchar* glyph_ranges = NULL, int font_no = 0); // 'in_compressed_ttf_data' untouched and still owned by caller. compress with binary_to_compressed_c. IMGUI_API void ClearTexData(); // Saves RAM once the texture has been copied to graphics memory. IMGUI_API void Clear(); From 7ca21a1bc207788bfb9d208d8f44d54e03c02b47 Mon Sep 17 00:00:00 2001 From: ocornut Date: Sat, 11 Apr 2015 18:12:11 +0100 Subject: [PATCH 04/19] Fixed prototypes --- imgui.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index d70f72bc..4fa8f16a 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -8124,7 +8124,7 @@ ImFont* ImFontAtlas::AddFontFromFileTTF(const char* filename, float size_pixels, } // NB: ownership of 'data' is given to ImFontAtlas which will clear it. -ImFont* ImFontAtlas::AddFontFromMemoryTTF(void* in_ttf_data, size_t in_ttf_data_size, float size_pixels, const ImWchar* glyph_ranges, int font_no) +ImFont* ImFontAtlas::AddFontFromMemoryTTF(void* in_ttf_data, unsigned int in_ttf_data_size, float size_pixels, const ImWchar* glyph_ranges, int font_no) { // Create new font ImFont* font = (ImFont*)ImGui::MemAlloc(sizeof(ImFont)); @@ -8148,7 +8148,7 @@ ImFont* ImFontAtlas::AddFontFromMemoryTTF(void* in_ttf_data, size_t in_ttf_data_ return font; } -ImFont* ImFontAtlas::AddFontFromMemoryCompressedTTF(const void* in_compressed_ttf_data, size_t in_compressed_ttf_data_size, float size_pixels, const ImWchar* glyph_ranges, int font_no) +ImFont* ImFontAtlas::AddFontFromMemoryCompressedTTF(const void* in_compressed_ttf_data, unsigned int in_compressed_ttf_data_size, float size_pixels, const ImWchar* glyph_ranges, int font_no) { // Decompress const size_t buf_decompressed_size = stb_decompress_length((unsigned char*)in_compressed_ttf_data); From adae98664ee734371dc3efa30580c9cc434092fb Mon Sep 17 00:00:00 2001 From: ocornut Date: Sun, 12 Apr 2015 10:31:10 +0100 Subject: [PATCH 05/19] Comment on the newly added binary_to_compressed_c.cpp helper program --- imgui.cpp | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 4fa8f16a..15ed86c5 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -10917,16 +10917,9 @@ static void ShowExampleAppLongText(bool* opened) //----------------------------------------------------------------------------- // FONT DATA //----------------------------------------------------------------------------- - -//----------------------------------------------------------------------------- -// ProggyClean.ttf -// Copyright (c) 2004, 2005 Tristan Grimmer -// MIT license (see License.txt in http://www.upperbounds.net/download/ProggyClean.ttf.zip) -// Download and more information at http://upperbounds.net -//----------------------------------------------------------------------------- // Compressed with stb_compress() then converted to a C array. -// Decompressor from stb.h (public domain) by Sean Barrett -// https://github.com/nothings/stb/blob/master/stb.h +// Use the program in extra_fonts/binary_to_compressed_c.cpp to create the array from a TTF file. +// Decompressor from stb.h (public domain) by Sean Barrett https://github.com/nothings/stb/blob/master/stb.h //----------------------------------------------------------------------------- static unsigned int stb_decompress_length(unsigned char *input) @@ -10935,7 +10928,6 @@ static unsigned int stb_decompress_length(unsigned char *input) } static unsigned char *stb__barrier, *stb__barrier2, *stb__barrier3, *stb__barrier4; - static unsigned char *stb__dout; static void stb__match(unsigned char *data, unsigned int length) { @@ -11041,6 +11033,12 @@ static unsigned int stb_decompress(unsigned char *output, unsigned char *i, unsi } } +//----------------------------------------------------------------------------- +// ProggyClean.ttf +// Copyright (c) 2004, 2005 Tristan Grimmer +// MIT license (see License.txt in http://www.upperbounds.net/download/ProggyClean.ttf.zip) +// Download and more information at http://upperbounds.net +//----------------------------------------------------------------------------- static const unsigned int proggy_clean_ttf_compressed_size = 9583; static const unsigned int proggy_clean_ttf_compressed_data[9584/4] = { From b308d2728b8e172c1406abc35a384e316a63db22 Mon Sep 17 00:00:00 2001 From: ocornut Date: Sun, 12 Apr 2015 10:45:00 +0100 Subject: [PATCH 06/19] Remove stray tabs --- imgui.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 15ed86c5..8f584ba1 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -7720,8 +7720,8 @@ void ImDrawList::PrimTriangle(const ImVec2& a, const ImVec2& b, const ImVec2& c, void ImDrawList::PrimRect(const ImVec2& a, const ImVec2& c, ImU32 col) { const ImVec2 uv = GImGui->FontTexUvWhitePixel; - const ImVec2 b(c.x, a.y); - const ImVec2 d(a.x, c.y); + const ImVec2 b(c.x, a.y); + const ImVec2 d(a.x, c.y); vtx_write[0].pos = a; vtx_write[0].uv = uv; vtx_write[0].col = col; vtx_write[1].pos = b; vtx_write[1].uv = uv; vtx_write[1].col = col; vtx_write[2].pos = c; vtx_write[2].uv = uv; vtx_write[2].col = col; @@ -7733,10 +7733,10 @@ void ImDrawList::PrimRect(const ImVec2& a, const ImVec2& c, ImU32 col) void ImDrawList::PrimRectUV(const ImVec2& a, const ImVec2& c, const ImVec2& uv_a, const ImVec2& uv_c, ImU32 col) { - const ImVec2 b(c.x, a.y); - const ImVec2 d(a.x, c.y); - const ImVec2 uv_b(uv_c.x, uv_a.y); - const ImVec2 uv_d(uv_a.x, uv_c.y); + const ImVec2 b(c.x, a.y); + const ImVec2 d(a.x, c.y); + const ImVec2 uv_b(uv_c.x, uv_a.y); + const ImVec2 uv_d(uv_a.x, uv_c.y); vtx_write[0].pos = a; vtx_write[0].uv = uv_a; vtx_write[0].col = col; vtx_write[1].pos = b; vtx_write[1].uv = uv_b; vtx_write[1].col = col; vtx_write[2].pos = c; vtx_write[2].uv = uv_c; vtx_write[2].col = col; @@ -10205,7 +10205,7 @@ void ImGui::ShowTestWindow(bool* opened) ImGui::Spacing(); // Scrolling columns - /* + /* ImGui::Text("Scrolling:"); ImGui::BeginChild("##header", ImVec2(0, ImGui::GetTextLineHeightWithSpacing()+ImGui::GetStyle().ItemSpacing.y)); ImGui::Columns(3); @@ -10228,7 +10228,7 @@ void ImGui::ShowTestWindow(bool* opened) ImGui::Separator(); ImGui::Spacing(); - */ + */ // Create multiple items in a same cell before switching to next column ImGui::Text("Mixed items:"); From 62abde5b37e82fe5a77962efcf01a50e717a7e3e Mon Sep 17 00:00:00 2001 From: ocornut Date: Sun, 12 Apr 2015 19:07:48 +0100 Subject: [PATCH 07/19] DragFloat() latch value internally, allows finer control, honor precision settings, slow step with integer works #180 --- imgui.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/imgui.h b/imgui.h index 00547089..f689a3de 100644 --- a/imgui.h +++ b/imgui.h @@ -317,7 +317,7 @@ namespace ImGui // Widgets: Drags (tip: ctrl+click on a drag box to input text) // ImGui 1.38+ work-in-progress, may change name or API. IMGUI_API bool DragFloat(const char* label, float* v, float v_step = 1.0f, float v_min = 0.0f, float v_max = 0.0f, const char* display_format = "%.3f"); // If v_max >= v_max we have no bound - IMGUI_API bool DragInt(const char* label, int* v, int v_step = 1, int v_min = 0, int v_max = 0, const char* display_format = "%.0f"); // If v_max >= v_max we have no bound + IMGUI_API bool DragInt(const char* label, int* v, int v_step = 1, int v_min = 0, int v_max = 0, const char* display_format = "%.0f"); // If v_max >= v_max we have no bound // Widgets: Input IMGUI_API bool InputText(const char* label, char* buf, size_t buf_size, ImGuiInputTextFlags flags = 0, ImGuiTextEditCallback callback = NULL, void* user_data = NULL); From 0dc3d07e7f638eaea452c3c1932299cb9b7126f9 Mon Sep 17 00:00:00 2001 From: ocornut Date: Sun, 12 Apr 2015 19:08:56 +0100 Subject: [PATCH 08/19] DragInt() step given as float to allow finer control of speed #180 --- imgui.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/imgui.h b/imgui.h index f689a3de..9a01fe85 100644 --- a/imgui.h +++ b/imgui.h @@ -317,7 +317,7 @@ namespace ImGui // Widgets: Drags (tip: ctrl+click on a drag box to input text) // ImGui 1.38+ work-in-progress, may change name or API. IMGUI_API bool DragFloat(const char* label, float* v, float v_step = 1.0f, float v_min = 0.0f, float v_max = 0.0f, const char* display_format = "%.3f"); // If v_max >= v_max we have no bound - IMGUI_API bool DragInt(const char* label, int* v, int v_step = 1, int v_min = 0, int v_max = 0, const char* display_format = "%.0f"); // If v_max >= v_max we have no bound + IMGUI_API bool DragInt(const char* label, int* v, float v_step = 1.0f, int v_min = 0, int v_max = 0, const char* display_format = "%.0f"); // If v_max >= v_max we have no bound // Widgets: Input IMGUI_API bool InputText(const char* label, char* buf, size_t buf_size, ImGuiInputTextFlags flags = 0, ImGuiTextEditCallback callback = NULL, void* user_data = NULL); From f5ad3629124d717cf5ba5251a71dc686a6156fb2 Mon Sep 17 00:00:00 2001 From: ocornut Date: Sun, 12 Apr 2015 19:15:55 +0100 Subject: [PATCH 09/19] DragFloat() latch value internally, allows finer control, honor precision settings, slow step with integer works #180 --- imgui.cpp | 77 ++++++++++++++++++++++++++++++++++++------------------- imgui.h | 4 +-- 2 files changed, 53 insertions(+), 28 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 8f584ba1..33f78cd0 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -1108,10 +1108,11 @@ struct ImGuiState ImGuiWindow* FocusedWindow; // Will catch keyboard inputs ImGuiWindow* HoveredWindow; // Will catch mouse inputs ImGuiWindow* HoveredRootWindow; // Will catch mouse inputs (for focus/move only) - ImGuiID HoveredId; - ImGuiID ActiveId; + ImGuiID HoveredId; // Hovered widget + ImGuiID ActiveId; // Active widget ImGuiID ActiveIdPreviousFrame; bool ActiveIdIsAlive; + bool ActiveIdIsJustActivated; // Set when bool ActiveIdIsFocusedOnly; // Set only by active widget. Denote focus but no active interaction. ImGuiWindow* MovedWindow; // Track the child window we clicked on to move a window. Only valid if ActiveID is the "#MOVE" identifier of a window. float SettingsDirtyTimer; @@ -1144,6 +1145,7 @@ struct ImGuiState ImGuiID ScalarAsInputTextId; // Temporary text input when CTRL+clicking on a slider, etc. ImGuiStorage ColorEditModeStorage; // for user selection ImGuiID ActiveComboID; + float DragCurrentValue; ImVec2 DragLastMouseDelta; float DragSpeedScaleSlow; float DragSpeedScaleFast; @@ -1182,6 +1184,7 @@ struct ImGuiState ActiveId = 0; ActiveIdPreviousFrame = 0; ActiveIdIsAlive = false; + ActiveIdIsJustActivated = false; ActiveIdIsFocusedOnly = false; MovedWindow = NULL; SettingsDirtyTimer = 0.0f; @@ -1199,6 +1202,7 @@ struct ImGuiState ScalarAsInputTextId = 0; ActiveComboID = 0; + DragCurrentValue = 0.0f; DragLastMouseDelta = ImVec2(0.0f, 0.0f); DragSpeedScaleSlow = 0.01f; DragSpeedScaleFast = 10.0f; @@ -1314,6 +1318,7 @@ static void SetActiveId(ImGuiID id) ImGuiState& g = *GImGui; g.ActiveId = id; g.ActiveIdIsFocusedOnly = false; + g.ActiveIdIsJustActivated = true; } static void RegisterAliveId(ImGuiID id) @@ -1935,6 +1940,7 @@ void ImGui::NewFrame() SetActiveId(0); g.ActiveIdPreviousFrame = g.ActiveId; g.ActiveIdIsAlive = false; + g.ActiveIdIsJustActivated = false; if (!g.ActiveId) g.MovedWindow = NULL; @@ -5055,7 +5061,7 @@ static bool SliderFloatAsInputText(const char* label, float* v, ImGuiID id, int } // Parse display precision back from the display format string -static void ParseFormat(const char* fmt, int& decimal_precision) +static inline void ParseFormat(const char* fmt, int& decimal_precision) { while ((fmt = strchr(fmt, '%')) != NULL) { @@ -5073,6 +5079,21 @@ static void ParseFormat(const char* fmt, int& decimal_precision) } } +static inline float RoundScalar(float value, int decimal_precision) +{ + // Round past decimal precision + // 0: 1, 1: 0.1, 2: 0.01, etc. + // So when our value is 1.99999 with a precision of 0.001 we'll end up rounding to 2.0 + // FIXME: Investigate better rounding methods + const float min_step = 1.0f / powf(10.0f, (float)decimal_precision); + const float remainder = fmodf(value, min_step); + if (remainder <= min_step*0.5f) + value -= remainder; + else + value += (min_step - remainder); + return value; +} + static bool SliderBehavior(const ImRect& frame_bb, const ImRect& slider_bb, ImGuiID id, float* v, float v_min, float v_max, float power, int decimal_precision, bool horizontal) { ImGuiState& g = *GImGui; @@ -5151,14 +5172,7 @@ static bool SliderBehavior(const ImRect& frame_bb, const ImRect& slider_bb, ImGu } // Round past decimal precision - // 0->1, 1->0.1, 2->0.01, etc. - // So when our value is 1.99999 with a precision of 0.001 we'll end up rounding to 2.0 - const float min_step = 1.0f / powf(10.0f, (float)decimal_precision); - const float remainder = fmodf(new_value, min_step); - if (remainder <= min_step*0.5f) - new_value -= remainder; - else - new_value += (min_step - remainder); + new_value = RoundScalar(new_value, decimal_precision); if (*v != new_value) { @@ -5464,7 +5478,7 @@ bool ImGui::SliderInt4(const char* label, int v[4], int v_min, int v_max, const } // FIXME-WIP: Work in progress. May change API / behavior. -static bool DragScalarBehavior(const ImRect& frame_bb, ImGuiID id, float* v, float v_step, float v_min, float v_max) +static bool DragScalarBehavior(const ImRect& frame_bb, ImGuiID id, float* v, float v_speed, float v_min, float v_max, int decimal_precision) { ImGuiState& g = *GImGui; ImGuiWindow* window = GetCurrentWindow(); @@ -5481,23 +5495,34 @@ static bool DragScalarBehavior(const ImRect& frame_bb, ImGuiID id, float* v, flo { if (g.IO.MouseDown[0]) { - const ImVec2 mouse_drag_delta = ImGui::GetMouseDragDelta(0); + if (g.ActiveIdIsJustActivated) + { + // Lock current value on click + g.DragCurrentValue = *v; + g.DragLastMouseDelta = ImVec2(0.f, 0.f); + } + const ImVec2 mouse_drag_delta = ImGui::GetMouseDragDelta(0, 1.0f); if (fabsf(mouse_drag_delta.x - g.DragLastMouseDelta.x) > 0.0f) { - float step = v_step; + float step = v_speed; if (g.IO.KeyShift && g.DragSpeedScaleFast >= 0.0f) - step = v_step * g.DragSpeedScaleFast; + step = v_speed * g.DragSpeedScaleFast; if (g.IO.KeyAlt && g.DragSpeedScaleSlow >= 0.0f) - step = v_step * g.DragSpeedScaleSlow; + step = v_speed * g.DragSpeedScaleSlow; - *v += (mouse_drag_delta.x - g.DragLastMouseDelta.x) * step; + g.DragCurrentValue += (mouse_drag_delta.x - g.DragLastMouseDelta.x) * step; + g.DragLastMouseDelta.x = mouse_drag_delta.x; if (v_min < v_max) - *v = ImClamp(*v, v_min, v_max); + g.DragCurrentValue = ImClamp(g.DragCurrentValue, v_min, v_max); - g.DragLastMouseDelta.x = mouse_drag_delta.x; - value_changed = true; + float new_value = RoundScalar(g.DragCurrentValue, decimal_precision); + if (*v != new_value) + { + *v = new_value; + value_changed = true; + } } } else @@ -5509,7 +5534,7 @@ static bool DragScalarBehavior(const ImRect& frame_bb, ImGuiID id, float* v, flo return value_changed; } -bool ImGui::DragFloat(const char* label, float *v, float v_step, float v_min, float v_max, const char* display_format) +bool ImGui::DragFloat(const char* label, float *v, float v_speed, float v_min, float v_max, const char* display_format) { ImGuiState& g = *GImGui; ImGuiWindow* window = GetCurrentWindow(); @@ -5548,7 +5573,6 @@ bool ImGui::DragFloat(const char* label, float *v, float v_step, float v_min, fl { SetActiveId(id); FocusWindow(window); - g.DragLastMouseDelta = ImVec2(0.f, 0.f); if (tab_focus_requested || g.IO.KeyCtrl || g.IO.MouseDoubleClicked[0]) { @@ -5562,7 +5586,7 @@ bool ImGui::DragFloat(const char* label, float *v, float v_step, float v_min, fl ItemSize(total_bb, style.FramePadding.y); // Actual drag behavior - const bool value_changed = DragScalarBehavior(frame_bb, id, v, v_step, v_min, v_max); + const bool value_changed = DragScalarBehavior(frame_bb, id, v, v_speed, v_min, v_max, decimal_precision); // Display value using user-provided display format so user can add prefix/suffix/decorations to the value. char value_buf[64]; @@ -5576,12 +5600,13 @@ bool ImGui::DragFloat(const char* label, float *v, float v_step, float v_min, fl return value_changed; } -bool ImGui::DragInt(const char* label, int* v, int v_step, int v_min, int v_max, const char* display_format) +// NB: v_speed is float to allow adjusting the drag speed with more precision +bool ImGui::DragInt(const char* label, int* v, float v_speed, int v_min, int v_max, const char* display_format) { if (!display_format) display_format = "%.0f"; float v_f = (float)*v; - bool value_changed = ImGui::DragFloat(label, &v_f, (float)v_step, (float)v_min, (float)v_max, display_format); + bool value_changed = ImGui::DragFloat(label, &v_f, v_speed, (float)v_min, (float)v_max, display_format); *v = (int)v_f; return value_changed; } @@ -7029,7 +7054,7 @@ bool ImGui::ColorEdit4(const char* label, float col[4], bool alpha) ImGui::SameLine(0, (int)style.ItemInnerSpacing.x); if (n + 1 == components) ImGui::PushItemWidth(w_item_last); - value_changed |= ImGui::DragInt(ids[n], &i[n], 1, 0, 255, fmt[n]); + value_changed |= ImGui::DragInt(ids[n], &i[n], 1.0f, 0, 255, fmt[n]); } ImGui::PopItemWidth(); ImGui::PopItemWidth(); diff --git a/imgui.h b/imgui.h index 9a01fe85..70b98cb2 100644 --- a/imgui.h +++ b/imgui.h @@ -316,8 +316,8 @@ namespace ImGui // Widgets: Drags (tip: ctrl+click on a drag box to input text) // ImGui 1.38+ work-in-progress, may change name or API. - IMGUI_API bool DragFloat(const char* label, float* v, float v_step = 1.0f, float v_min = 0.0f, float v_max = 0.0f, const char* display_format = "%.3f"); // If v_max >= v_max we have no bound - IMGUI_API bool DragInt(const char* label, int* v, float v_step = 1.0f, int v_min = 0, int v_max = 0, const char* display_format = "%.0f"); // If v_max >= v_max we have no bound + IMGUI_API bool DragFloat(const char* label, float* v, float v_speed = 1.0f, float v_min = 0.0f, float v_max = 0.0f, const char* display_format = "%.3f"); // If v_max >= v_max we have no bound + IMGUI_API bool DragInt(const char* label, int* v, float v_speed = 1.0f, int v_min = 0, int v_max = 0, const char* display_format = "%.0f"); // If v_max >= v_max we have no bound // Widgets: Input IMGUI_API bool InputText(const char* label, char* buf, size_t buf_size, ImGuiInputTextFlags flags = 0, ImGuiTextEditCallback callback = NULL, void* user_data = NULL); From 6ed06a8dc8817828d199436b4b679c2b9c248847 Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 13 Apr 2015 00:03:57 +0100 Subject: [PATCH 10/19] DragFloat() added power parameter for logarithmic drag on both side of zero #180 --- imgui.cpp | 44 +++++++++++++++++++++++++++++++------------- imgui.h | 4 ++-- 2 files changed, 33 insertions(+), 15 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 33f78cd0..8ec6e2c3 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -1,4 +1,4 @@ -// ImGui library v1.38 WIP +// ImGui library v1.38 WIP // See ImGui::ShowTestWindow() for sample code. // Read 'Programmer guide' below for notes on how to setup ImGui in your codebase. // Get latest version at https://github.com/ocornut/imgui @@ -1145,7 +1145,7 @@ struct ImGuiState ImGuiID ScalarAsInputTextId; // Temporary text input when CTRL+clicking on a slider, etc. ImGuiStorage ColorEditModeStorage; // for user selection ImGuiID ActiveComboID; - float DragCurrentValue; + float DragCurrentValue; // current dragged value, always float, not rounded by end-user precision settings ImVec2 DragLastMouseDelta; float DragSpeedScaleSlow; float DragSpeedScaleFast; @@ -5478,7 +5478,7 @@ bool ImGui::SliderInt4(const char* label, int v[4], int v_min, int v_max, const } // FIXME-WIP: Work in progress. May change API / behavior. -static bool DragScalarBehavior(const ImRect& frame_bb, ImGuiID id, float* v, float v_speed, float v_min, float v_max, int decimal_precision) +static bool DragScalarBehavior(const ImRect& frame_bb, ImGuiID id, float* v, float v_speed, float v_min, float v_max, int decimal_precision, float power) { ImGuiState& g = *GImGui; ImGuiWindow* window = GetCurrentWindow(); @@ -5505,22 +5505,40 @@ static bool DragScalarBehavior(const ImRect& frame_bb, ImGuiID id, float* v, flo const ImVec2 mouse_drag_delta = ImGui::GetMouseDragDelta(0, 1.0f); if (fabsf(mouse_drag_delta.x - g.DragLastMouseDelta.x) > 0.0f) { - float step = v_speed; + float speed = v_speed; if (g.IO.KeyShift && g.DragSpeedScaleFast >= 0.0f) - step = v_speed * g.DragSpeedScaleFast; + speed = v_speed * g.DragSpeedScaleFast; if (g.IO.KeyAlt && g.DragSpeedScaleSlow >= 0.0f) - step = v_speed * g.DragSpeedScaleSlow; + speed = v_speed * g.DragSpeedScaleSlow; - g.DragCurrentValue += (mouse_drag_delta.x - g.DragLastMouseDelta.x) * step; + float v_cur = g.DragCurrentValue; + float delta = (mouse_drag_delta.x - g.DragLastMouseDelta.x) * speed; + if (fabsf(power - 1.0f) > 0.001f) + { + // Logarithmic curve on both side of 0.0 + float v0_abs = v_cur >= 0.0f ? v_cur : -v_cur; + float v0_sign = v_cur >= 0.0f ? 1.0f : -1.0f; + float v1 = powf(v0_abs, 1.0f / power) + (delta * v0_sign); + float v1_abs = v1 >= 0.0f ? v1 : -v1; + float v1_sign = v1 >= 0.0f ? 1.0f : -1.0f; // Crossed sign line + v_cur = powf(v1_abs, power) * v0_sign * v1_sign; // Reapply sign + } + else + { + v_cur += delta; + } g.DragLastMouseDelta.x = mouse_drag_delta.x; + // Clamp if (v_min < v_max) - g.DragCurrentValue = ImClamp(g.DragCurrentValue, v_min, v_max); + g.DragCurrentValue = ImClamp(v_cur, v_min, v_max); + g.DragCurrentValue = v_cur; - float new_value = RoundScalar(g.DragCurrentValue, decimal_precision); - if (*v != new_value) + // Round to user desired precision, then apply + v_cur = RoundScalar(v_cur, decimal_precision); + if (*v != v_cur) { - *v = new_value; + *v = v_cur; value_changed = true; } } @@ -5534,7 +5552,7 @@ static bool DragScalarBehavior(const ImRect& frame_bb, ImGuiID id, float* v, flo return value_changed; } -bool ImGui::DragFloat(const char* label, float *v, float v_speed, float v_min, float v_max, const char* display_format) +bool ImGui::DragFloat(const char* label, float *v, float v_speed, float v_min, float v_max, const char* display_format, float power) { ImGuiState& g = *GImGui; ImGuiWindow* window = GetCurrentWindow(); @@ -5586,7 +5604,7 @@ bool ImGui::DragFloat(const char* label, float *v, float v_speed, float v_min, f ItemSize(total_bb, style.FramePadding.y); // Actual drag behavior - const bool value_changed = DragScalarBehavior(frame_bb, id, v, v_speed, v_min, v_max, decimal_precision); + const bool value_changed = DragScalarBehavior(frame_bb, id, v, v_speed, v_min, v_max, decimal_precision, power); // Display value using user-provided display format so user can add prefix/suffix/decorations to the value. char value_buf[64]; diff --git a/imgui.h b/imgui.h index 70b98cb2..1d26dfd2 100644 --- a/imgui.h +++ b/imgui.h @@ -316,8 +316,8 @@ namespace ImGui // Widgets: Drags (tip: ctrl+click on a drag box to input text) // ImGui 1.38+ work-in-progress, may change name or API. - IMGUI_API bool DragFloat(const char* label, float* v, float v_speed = 1.0f, float v_min = 0.0f, float v_max = 0.0f, const char* display_format = "%.3f"); // If v_max >= v_max we have no bound - IMGUI_API bool DragInt(const char* label, int* v, float v_speed = 1.0f, int v_min = 0, int v_max = 0, const char* display_format = "%.0f"); // If v_max >= v_max we have no bound + IMGUI_API bool DragFloat(const char* label, float* v, float v_speed = 1.0f, float v_min = 0.0f, float v_max = 0.0f, const char* display_format = "%.3f", float power = 1.0f); // If v_max >= v_max we have no bound + IMGUI_API bool DragInt(const char* label, int* v, float v_speed = 1.0f, int v_min = 0, int v_max = 0, const char* display_format = "%.0f"); // If v_max >= v_max we have no bound // Widgets: Input IMGUI_API bool InputText(const char* label, char* buf, size_t buf_size, ImGuiInputTextFlags flags = 0, ImGuiTextEditCallback callback = NULL, void* user_data = NULL); From 750b6c9224e7dd13aa9d59fdd2c0277af52c8cbb Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 13 Apr 2015 00:07:41 +0100 Subject: [PATCH 11/19] DragFloat() fixed clamping #180 --- imgui.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/imgui.cpp b/imgui.cpp index 8ec6e2c3..691a8239 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -5531,7 +5531,7 @@ static bool DragScalarBehavior(const ImRect& frame_bb, ImGuiID id, float* v, flo // Clamp if (v_min < v_max) - g.DragCurrentValue = ImClamp(v_cur, v_min, v_max); + v_cur = ImClamp(v_cur, v_min, v_max); g.DragCurrentValue = v_cur; // Round to user desired precision, then apply From a143e2e77255165e416fc440fd0bbbe45e7ac2b4 Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 13 Apr 2015 14:45:27 +0100 Subject: [PATCH 12/19] Added PushId() GetId() variants that takes string range to avoid user making unnecessary copies --- imgui.cpp | 18 +++++++++++++++--- imgui.h | 2 ++ 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 691a8239..5190157f 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -1275,7 +1275,7 @@ public: ImGuiWindow(const char* name); ~ImGuiWindow(); - ImGuiID GetID(const char* str); + ImGuiID GetID(const char* str, const char* str_end = NULL); ImGuiID GetID(const void* ptr); bool FocusItemRegister(bool is_active, bool tab_stop = true); // Return true if focus is requested @@ -1621,10 +1621,10 @@ ImGuiWindow::~ImGuiWindow() Name = NULL; } -ImGuiID ImGuiWindow::GetID(const char* str) +ImGuiID ImGuiWindow::GetID(const char* str, const char* str_end) { ImGuiID seed = IDStack.back(); - const ImGuiID id = ImHash(str, 0, seed); + const ImGuiID id = ImHash(str, str_end ? str_end - str : 0, seed); RegisterAliveId(id); return id; } @@ -4948,6 +4948,12 @@ void ImGui::PushID(const char* str_id) window->IDStack.push_back(window->GetID(str_id)); } +void ImGui::PushID(const char* str_id_begin, const char* str_id_end) +{ + ImGuiWindow* window = GetCurrentWindow(); + window->IDStack.push_back(window->GetID(str_id_begin, str_id_end)); +} + void ImGui::PushID(const void* ptr_id) { ImGuiWindow* window = GetCurrentWindow(); @@ -4973,6 +4979,12 @@ ImGuiID ImGui::GetID(const char* str_id) return window->GetID(str_id); } +ImGuiID ImGui::GetID(const char* str_id_begin, const char* str_id_end) +{ + ImGuiWindow* window = GetCurrentWindow(); + return window->GetID(str_id_begin, str_id_end); +} + ImGuiID ImGui::GetID(const void* ptr_id) { ImGuiWindow* window = GetCurrentWindow(); diff --git a/imgui.h b/imgui.h index 1d26dfd2..4db43e1d 100644 --- a/imgui.h +++ b/imgui.h @@ -260,10 +260,12 @@ namespace ImGui // If you are creating widgets in a loop you most likely want to push a unique identifier so ImGui can differentiate them // You can also use "##extra" within your widget name to distinguish them from each others (see 'Programmer Guide') IMGUI_API void PushID(const char* str_id); // push identifier into the ID stack. IDs are hash of the *entire* stack! + IMGUI_API void PushID(const char* str_id_begin, const char* str_id_end); IMGUI_API void PushID(const void* ptr_id); IMGUI_API void PushID(const int int_id); IMGUI_API void PopID(); IMGUI_API ImGuiID GetID(const char* str_id); // calculate unique ID (hash of whole ID stack + given parameter). useful if you want to query into ImGuiStorage yourself. otherwise rarely needed + IMGUI_API ImGuiID GetID(const char* str_id_begin, const char* str_id_end); IMGUI_API ImGuiID GetID(const void* ptr_id); // Widgets From 9918ec31d6ce25d911b9ac7f7dcbf76b001e806b Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 13 Apr 2015 19:54:40 +0100 Subject: [PATCH 13/19] Added ResetMouseDragDelta() for iterative dragging operations --- imgui.cpp | 8 ++++++++ imgui.h | 1 + 2 files changed, 9 insertions(+) diff --git a/imgui.cpp b/imgui.cpp index 5190157f..b69b9cac 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -2699,6 +2699,14 @@ ImVec2 ImGui::GetMouseDragDelta(int button, float lock_threshold) return ImVec2(0.0f, 0.0f); } +void ImGui::ResetMouseDragDelta(int button) +{ + ImGuiState& g = *GImGui; + IM_ASSERT(button >= 0 && button < IM_ARRAYSIZE(g.IO.MouseDown)); + // NB: We don't need to reset g.IO.MouseDragMaxDistanceSqr + g.IO.MouseClickedPos[button] = g.IO.MousePos; +} + ImGuiMouseCursor ImGui::GetMouseCursor() { return GImGui->MouseCursor; diff --git a/imgui.h b/imgui.h index 4db43e1d..e2707d58 100644 --- a/imgui.h +++ b/imgui.h @@ -390,6 +390,7 @@ namespace ImGui IMGUI_API bool IsPosHoveringAnyWindow(const ImVec2& pos); // is given position hovering any active imgui window IMGUI_API ImVec2 GetMousePos(); // shortcut to ImGui::GetIO().MousePos provided by user, to be consistent with other calls IMGUI_API ImVec2 GetMouseDragDelta(int button = 0, float lock_threshold = -1.0f); // dragging amount since clicking, also see: GetItemActiveDragDelta(). if lock_threshold < -1.0f uses io.MouseDraggingThreshold + IMGUI_API void ResetMouseDragDelta(int button = 0); IMGUI_API ImGuiMouseCursor GetMouseCursor(); // get desired cursor type, reset in ImGui::NewFrame(), this updated during the frame. valid before Render(). If you use software rendering by setting io.MouseDrawCursor ImGui will render those for you IMGUI_API void SetMouseCursor(ImGuiMouseCursor type); // set desired cursor type IMGUI_API float GetTime(); From 16ddd796f3d76a580589673d71e80893baf1430b Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 13 Apr 2015 20:59:44 +0100 Subject: [PATCH 14/19] Active widgets is not clipped, so it can always release its active state (mentioned in #143) Otherwise a change in layout moving active widget to a clipped region may lock the active id. --- imgui.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index b69b9cac..1330943e 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -7265,8 +7265,11 @@ static bool ItemAdd(const ImRect& bb, const ImGuiID* id) window->DC.LastItemRect = bb; if (IsClipped(bb)) { - window->DC.LastItemHoveredAndUsable = window->DC.LastItemHoveredRect = false; - return false; + if (!id || *id != GImGui->ActiveId) + { + window->DC.LastItemHoveredAndUsable = window->DC.LastItemHoveredRect = false; + return false; + } } // This is a sensible default, but widgets are free to override it after calling ItemAdd() From d11b4160aac28aa118d7481dd92878408edefa7c Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 13 Apr 2015 21:52:38 +0100 Subject: [PATCH 15/19] Added IsItemVisible(). Made IsClipped() also return false when log is enabled. --- imgui.cpp | 26 ++++++++++++++++++-------- imgui.h | 3 ++- 2 files changed, 20 insertions(+), 9 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 1330943e..e5e8713f 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -491,7 +491,7 @@ static bool ItemAdd(const ImRect& bb, const ImGuiID* id); static void ItemSize(ImVec2 size, float text_offset_y = 0.0f); static void ItemSize(const ImRect& bb, float text_offset_y = 0.0f); static void PushColumnClipRect(int column_index = -1); -static bool IsClipped(const ImRect& bb); +static bool IsClippedEx(const ImRect& bb, bool clip_even_when_logged); static bool IsMouseHoveringRect(const ImRect& bb); static bool IsKeyPressedMap(ImGuiKey key, bool repeat = true); @@ -2746,6 +2746,13 @@ bool ImGui::IsAnyItemActive() return g.ActiveId != 0; } +bool ImGui::IsItemVisible() +{ + ImGuiWindow* window = GetCurrentWindow(); + ImRect r(window->ClipRectStack.back()); + return r.Overlaps(window->DC.LastItemRect); +} + ImVec2 ImGui::GetItemRectMin() { ImGuiWindow* window = GetCurrentWindow(); @@ -4245,7 +4252,7 @@ void ImGui::TextUnformatted(const char* text, const char* text_end) while (line < text_end) { const char* line_end = strchr(line, '\n'); - if (IsClipped(line_rect)) + if (IsClippedEx(line_rect, false)) break; const ImVec2 line_size = CalcTextSize(line, line_end, false); @@ -7242,20 +7249,23 @@ static inline void ItemSize(const ImRect& bb, float text_offset_y) ItemSize(bb.GetSize(), text_offset_y); } -static bool IsClipped(const ImRect& bb) +static bool IsClippedEx(const ImRect& bb, bool clip_even_when_logged) { ImGuiState& g = *GImGui; ImGuiWindow* window = GetCurrentWindow(); - if (!bb.Overlaps(ImRect(window->ClipRectStack.back())) && !g.LogEnabled) - return true; + if (!bb.Overlaps(ImRect(window->ClipRectStack.back()))) + { + if (clip_even_when_logged || !g.LogEnabled) + return true; + } return false; } bool ImGui::IsClipped(const ImVec2& item_size) { ImGuiWindow* window = GetCurrentWindow(); - return IsClipped(ImRect(window->DC.CursorPos, window->DC.CursorPos + item_size)); + return IsClippedEx(ImRect(window->DC.CursorPos, window->DC.CursorPos + item_size), true); } static bool ItemAdd(const ImRect& bb, const ImGuiID* id) @@ -7263,7 +7273,7 @@ static bool ItemAdd(const ImRect& bb, const ImGuiID* id) ImGuiWindow* window = GetCurrentWindow(); window->DC.LastItemID = id ? *id : 0; window->DC.LastItemRect = bb; - if (IsClipped(bb)) + if (IsClippedEx(bb, false)) { if (!id || *id != GImGui->ActiveId) { @@ -7498,7 +7508,7 @@ void ImGui::Columns(int columns_count, const char* id, bool border) const ImGuiID column_id = window->DC.ColumnsSetID + ImGuiID(i); const ImRect column_rect(ImVec2(x-4,y1),ImVec2(x+4,y2)); - if (IsClipped(column_rect)) + if (IsClippedEx(column_rect, false)) continue; bool hovered, held; diff --git a/imgui.h b/imgui.h index e2707d58..3009b83f 100644 --- a/imgui.h +++ b/imgui.h @@ -373,7 +373,8 @@ namespace ImGui IMGUI_API bool IsItemHoveredRect(); // was the last item hovered by mouse? even if another item is active while we are hovering this IMGUI_API bool IsItemActive(); // was the last item active? (e.g. button being held, text field being edited- items that don't interact will always return false) IMGUI_API bool IsAnyItemActive(); // - IMGUI_API ImVec2 GetItemRectMin(); // get bounding rect of last item + IMGUI_API bool IsItemVisible(); + IMGUI_API ImVec2 GetItemRectMin(); // get bounding rect of last item in screen space IMGUI_API ImVec2 GetItemRectMax(); // " IMGUI_API ImVec2 GetItemRectSize(); // " IMGUI_API bool IsWindowFocused(); // is current window focused (differentiate child windows from each others) From dd36e8bf2b4d9da2bcd2f54618fa3d7fa6207a2b Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 13 Apr 2015 22:04:28 +0100 Subject: [PATCH 16/19] Renamed IsClipped() to IsRectClipped(). Kept inline redirection function (will obsolete). --- imgui.cpp | 5 +++-- imgui.h | 3 ++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index e5e8713f..7432156d 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -135,6 +135,7 @@ Occasionally introducing changes that are breaking the API. The breakage are generally minor and easy to fix. Here is a change-log of API breaking changes, if you are using one of the functions listed, expect to have to fix some code. + - 2015/04/13 (1.38) - renamed IsClipped() to IsRectClipped(). Kept inline redirection function (will obsolete). - 2015/04/09 (1.38) - renamed ImDrawList::AddArc() to ImDrawList::AddArcFast() for compatibility with future API - 2015/04/03 (1.38) - removed ImGuiCol_CheckHovered, ImGuiCol_CheckActive, replaced with the more general ImGuiCol_FrameBgHovered, ImGuiCol_FrameBgActive. - 2014/04/03 (1.38) - removed support for passing -FLT_MAX..+FLT_MAX as the range for a SliderFloat(). Use DragFloat() or Inputfloat() instead. @@ -7262,10 +7263,10 @@ static bool IsClippedEx(const ImRect& bb, bool clip_even_when_logged) return false; } -bool ImGui::IsClipped(const ImVec2& item_size) +bool ImGui::IsRectClipped(const ImVec2& size) { ImGuiWindow* window = GetCurrentWindow(); - return IsClippedEx(ImRect(window->DC.CursorPos, window->DC.CursorPos + item_size), true); + return IsClippedEx(ImRect(window->DC.CursorPos, window->DC.CursorPos + size), true); } static bool ItemAdd(const ImRect& bb, const ImGuiID* id) diff --git a/imgui.h b/imgui.h index 3009b83f..5d3ac4aa 100644 --- a/imgui.h +++ b/imgui.h @@ -380,7 +380,7 @@ namespace ImGui IMGUI_API bool IsWindowFocused(); // is current window focused (differentiate child windows from each others) IMGUI_API bool IsRootWindowFocused(); // is current root window focused IMGUI_API bool IsRootWindowOrAnyChildFocused(); // is current root window or any of its child (including current window) focused - IMGUI_API bool IsClipped(const ImVec2& item_size); // to perform coarse clipping on user's side (as an optimization) + IMGUI_API bool IsRectClipped(const ImVec2& size); // test if rectangle of given size starting from cursor pos is out of clipping region. to perform coarse clipping on user's side (as an optimization) IMGUI_API bool IsKeyPressed(int key_index, bool repeat = true); // key_index into the keys_down[512] array, imgui doesn't know the semantic of each entry IMGUI_API bool IsMouseClicked(int button, bool repeat = false); IMGUI_API bool IsMouseDoubleClicked(int button); @@ -420,6 +420,7 @@ namespace ImGui static inline bool GetWindowIsFocused() { return ImGui::IsWindowFocused(); } // OBSOLETE static inline ImVec2 GetItemBoxMin() { return GetItemRectMin(); } // OBSOLETE static inline ImVec2 GetItemBoxMax() { return GetItemRectMax(); } // OBSOLETE + static inline bool IsClipped(const ImVec2& size) { return IsRectClipped(size); } // OBSOLETE static inline bool IsMouseHoveringBox(const ImVec2& rect_min, const ImVec2& rect_max) { return IsMouseHoveringRect(rect_min, rect_max); } // OBSOLETE } // namespace ImGui From b28ec1f3b11868cbde93e7613cc6234e317e5b30 Mon Sep 17 00:00:00 2001 From: Stephan Dilly Date: Tue, 14 Apr 2015 00:40:46 +0200 Subject: [PATCH 17/19] fix outdated documentation --- imgui.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/imgui.h b/imgui.h index 5d3ac4aa..49bc50c2 100644 --- a/imgui.h +++ b/imgui.h @@ -945,7 +945,7 @@ struct ImDrawList // 2. Call GetTexDataAsAlpha8() or GetTexDataAsRGBA32() to build and retrieve pixels data. // 3. Upload the pixels data into a texture within your graphics system. // 4. Call SetTexID(my_tex_id); and pass the pointer/identifier to your texture. This value will be passed back to you during rendering to identify the texture. -// 5. Call ClearPixelsData() to free textures memory on the heap. +// 5. Call ClearTexData() to free textures memory on the heap. struct ImFontAtlas { IMGUI_API ImFontAtlas(); From fe157561294f7ac010dafea69eb1a312887a07e5 Mon Sep 17 00:00:00 2001 From: Dale Kim Date: Mon, 13 Apr 2015 20:04:53 -0500 Subject: [PATCH 18/19] Simplified glfw keyboard callbacks. --- .../opengl3_example/imgui_impl_glfw_gl3.cpp | 54 +++++-------------- examples/opengl_example/imgui_impl_glfw.cpp | 54 +++++-------------- 2 files changed, 28 insertions(+), 80 deletions(-) diff --git a/examples/opengl3_example/imgui_impl_glfw_gl3.cpp b/examples/opengl3_example/imgui_impl_glfw_gl3.cpp index fa756500..0c18b32c 100644 --- a/examples/opengl3_example/imgui_impl_glfw_gl3.cpp +++ b/examples/opengl3_example/imgui_impl_glfw_gl3.cpp @@ -134,50 +134,24 @@ void ImGui_ImplGlfwGL3_ScrollCallback(GLFWwindow*, double /*xoffset*/, double yo g_MouseWheel += (float)yoffset; // Use fractional mouse wheel, 1.0 unit 5 lines. } -void ImGui_ImplGlfwGL3_KeyCallback(GLFWwindow*, int key, int, int action, int mods) +void ImGui_ImplGlfwGL3_KeyCallback(GLFWwindow* window, int key, int, int action, int mods) { ImGuiIO& io = ImGui::GetIO(); if (action == GLFW_PRESS) - { - switch (key) - { - case GLFW_KEY_LEFT_CONTROL: - case GLFW_KEY_RIGHT_CONTROL: - io.KeyCtrl = true; - break; - case GLFW_KEY_LEFT_SHIFT: - case GLFW_KEY_RIGHT_SHIFT: - io.KeyShift = true; - break; - case GLFW_KEY_LEFT_ALT: - case GLFW_KEY_RIGHT_ALT: - io.KeyAlt = true; - break; - default: - io.KeysDown[key] = true; - } - } - + io.KeysDown[key] = true; if (action == GLFW_RELEASE) - { - switch (key) - { - case GLFW_KEY_LEFT_CONTROL: - case GLFW_KEY_RIGHT_CONTROL: - io.KeyCtrl = false; - break; - case GLFW_KEY_LEFT_SHIFT: - case GLFW_KEY_RIGHT_SHIFT: - io.KeyShift = false; - break; - case GLFW_KEY_LEFT_ALT: - case GLFW_KEY_RIGHT_ALT: - io.KeyAlt = false; - break; - default: - io.KeysDown[key] = false; - } - } + io.KeysDown[key] = false; + + bool leftCtrl = glfwGetKey(window, GLFW_KEY_LEFT_CONTROL) == GLFW_PRESS; + bool rightCtrl = glfwGetKey(window, GLFW_KEY_RIGHT_CONTROL) == GLFW_PRESS; + bool leftShift = glfwGetKey(window, GLFW_KEY_LEFT_SHIFT) == GLFW_PRESS; + bool rightShift = glfwGetKey(window, GLFW_KEY_RIGHT_SHIFT) == GLFW_PRESS; + bool leftAlt = glfwGetKey(window, GLFW_KEY_LEFT_ALT) == GLFW_PRESS; + bool rightAlt = glfwGetKey(window, GLFW_KEY_RIGHT_ALT) == GLFW_PRESS; + + io.KeyCtrl = leftCtrl || rightCtrl; + io.KeyShift = leftShift || rightShift; + io.KeyAlt = leftAlt || rightAlt; } void ImGui_ImplGlfwGL3_CharCallback(GLFWwindow*, unsigned int c) diff --git a/examples/opengl_example/imgui_impl_glfw.cpp b/examples/opengl_example/imgui_impl_glfw.cpp index 3349a266..1e56ab13 100644 --- a/examples/opengl_example/imgui_impl_glfw.cpp +++ b/examples/opengl_example/imgui_impl_glfw.cpp @@ -115,50 +115,24 @@ void ImGui_ImplGlfw_ScrollCallback(GLFWwindow*, double /*xoffset*/, double yoffs g_MouseWheel += (float)yoffset; // Use fractional mouse wheel, 1.0 unit 5 lines. } -void ImGui_ImplGlFw_KeyCallback(GLFWwindow*, int key, int, int action, int mods) +void ImGui_ImplGlFw_KeyCallback(GLFWwindow* window, int key, int, int action, int mods) { ImGuiIO& io = ImGui::GetIO(); if (action == GLFW_PRESS) - { - switch (key) - { - case GLFW_KEY_LEFT_CONTROL: - case GLFW_KEY_RIGHT_CONTROL: - io.KeyCtrl = true; - break; - case GLFW_KEY_LEFT_SHIFT: - case GLFW_KEY_RIGHT_SHIFT: - io.KeyShift = true; - break; - case GLFW_KEY_LEFT_ALT: - case GLFW_KEY_RIGHT_ALT: - io.KeyAlt = true; - break; - default: - io.KeysDown[key] = true; - } - } - + io.KeysDown[key] = true; if (action == GLFW_RELEASE) - { - switch (key) - { - case GLFW_KEY_LEFT_CONTROL: - case GLFW_KEY_RIGHT_CONTROL: - io.KeyCtrl = false; - break; - case GLFW_KEY_LEFT_SHIFT: - case GLFW_KEY_RIGHT_SHIFT: - io.KeyShift = false; - break; - case GLFW_KEY_LEFT_ALT: - case GLFW_KEY_RIGHT_ALT: - io.KeyAlt = false; - break; - default: - io.KeysDown[key] = false; - } - } + io.KeysDown[key] = false; + + bool leftCtrl = glfwGetKey(window, GLFW_KEY_LEFT_CONTROL) == GLFW_PRESS; + bool rightCtrl = glfwGetKey(window, GLFW_KEY_RIGHT_CONTROL) == GLFW_PRESS; + bool leftShift = glfwGetKey(window, GLFW_KEY_LEFT_SHIFT) == GLFW_PRESS; + bool rightShift = glfwGetKey(window, GLFW_KEY_RIGHT_SHIFT) == GLFW_PRESS; + bool leftAlt = glfwGetKey(window, GLFW_KEY_LEFT_ALT) == GLFW_PRESS; + bool rightAlt = glfwGetKey(window, GLFW_KEY_RIGHT_ALT) == GLFW_PRESS; + + io.KeyCtrl = leftCtrl || rightCtrl; + io.KeyShift = leftShift || rightShift; + io.KeyAlt = leftAlt || rightAlt; } void ImGui_ImplGlfw_CharCallback(GLFWwindow*, unsigned int c) From 71429d306e747b429ba64cecb3fecadfae599bba Mon Sep 17 00:00:00 2001 From: ocornut Date: Tue, 14 Apr 2015 09:45:27 +0100 Subject: [PATCH 19/19] Examples: Simplified GLFW keyboard callbacks --- examples/opengl3_example/imgui_impl_glfw_gl3.cpp | 14 ++++---------- examples/opengl_example/imgui_impl_glfw.cpp | 14 ++++---------- 2 files changed, 8 insertions(+), 20 deletions(-) diff --git a/examples/opengl3_example/imgui_impl_glfw_gl3.cpp b/examples/opengl3_example/imgui_impl_glfw_gl3.cpp index 1a5a09c1..9953a963 100644 --- a/examples/opengl3_example/imgui_impl_glfw_gl3.cpp +++ b/examples/opengl3_example/imgui_impl_glfw_gl3.cpp @@ -142,16 +142,10 @@ void ImGui_ImplGlfwGL3_KeyCallback(GLFWwindow* window, int key, int, int action, if (action == GLFW_RELEASE) io.KeysDown[key] = false; - bool leftCtrl = glfwGetKey(window, GLFW_KEY_LEFT_CONTROL) == GLFW_PRESS; - bool rightCtrl = glfwGetKey(window, GLFW_KEY_RIGHT_CONTROL) == GLFW_PRESS; - bool leftShift = glfwGetKey(window, GLFW_KEY_LEFT_SHIFT) == GLFW_PRESS; - bool rightShift = glfwGetKey(window, GLFW_KEY_RIGHT_SHIFT) == GLFW_PRESS; - bool leftAlt = glfwGetKey(window, GLFW_KEY_LEFT_ALT) == GLFW_PRESS; - bool rightAlt = glfwGetKey(window, GLFW_KEY_RIGHT_ALT) == GLFW_PRESS; - - io.KeyCtrl = leftCtrl || rightCtrl; - io.KeyShift = leftShift || rightShift; - io.KeyAlt = leftAlt || rightAlt; + (void)mods; // Modifiers are not reliable across systems + io.KeyCtrl = glfwGetKey(window, GLFW_KEY_LEFT_CONTROL) == GLFW_PRESS || glfwGetKey(window, GLFW_KEY_RIGHT_CONTROL) == GLFW_PRESS; + io.KeyShift = glfwGetKey(window, GLFW_KEY_LEFT_SHIFT) == GLFW_PRESS || glfwGetKey(window, GLFW_KEY_RIGHT_SHIFT) == GLFW_PRESS; + io.KeyAlt = glfwGetKey(window, GLFW_KEY_LEFT_ALT) == GLFW_PRESS || glfwGetKey(window, GLFW_KEY_RIGHT_ALT) == GLFW_PRESS; } void ImGui_ImplGlfwGL3_CharCallback(GLFWwindow*, unsigned int c) diff --git a/examples/opengl_example/imgui_impl_glfw.cpp b/examples/opengl_example/imgui_impl_glfw.cpp index 3babcba1..341d418d 100644 --- a/examples/opengl_example/imgui_impl_glfw.cpp +++ b/examples/opengl_example/imgui_impl_glfw.cpp @@ -124,16 +124,10 @@ void ImGui_ImplGlFw_KeyCallback(GLFWwindow* window, int key, int, int action, in if (action == GLFW_RELEASE) io.KeysDown[key] = false; - bool leftCtrl = glfwGetKey(window, GLFW_KEY_LEFT_CONTROL) == GLFW_PRESS; - bool rightCtrl = glfwGetKey(window, GLFW_KEY_RIGHT_CONTROL) == GLFW_PRESS; - bool leftShift = glfwGetKey(window, GLFW_KEY_LEFT_SHIFT) == GLFW_PRESS; - bool rightShift = glfwGetKey(window, GLFW_KEY_RIGHT_SHIFT) == GLFW_PRESS; - bool leftAlt = glfwGetKey(window, GLFW_KEY_LEFT_ALT) == GLFW_PRESS; - bool rightAlt = glfwGetKey(window, GLFW_KEY_RIGHT_ALT) == GLFW_PRESS; - - io.KeyCtrl = leftCtrl || rightCtrl; - io.KeyShift = leftShift || rightShift; - io.KeyAlt = leftAlt || rightAlt; + (void)mods; // Modifiers are not reliable across systems + io.KeyCtrl = glfwGetKey(window, GLFW_KEY_LEFT_CONTROL) == GLFW_PRESS || glfwGetKey(window, GLFW_KEY_RIGHT_CONTROL) == GLFW_PRESS; + io.KeyShift = glfwGetKey(window, GLFW_KEY_LEFT_SHIFT) == GLFW_PRESS || glfwGetKey(window, GLFW_KEY_RIGHT_SHIFT) == GLFW_PRESS; + io.KeyAlt = glfwGetKey(window, GLFW_KEY_LEFT_ALT) == GLFW_PRESS || glfwGetKey(window, GLFW_KEY_RIGHT_ALT) == GLFW_PRESS; } void ImGui_ImplGlfw_CharCallback(GLFWwindow*, unsigned int c)