diff --git a/deps/cimgui/cimgui/cimgui.cpp b/deps/cimgui/cimgui/cimgui.cpp index 86a27278..09835c04 100644 --- a/deps/cimgui/cimgui/cimgui.cpp +++ b/deps/cimgui/cimgui/cimgui.cpp @@ -2,6 +2,10 @@ #include "../imgui/imgui.h" #include "cimgui.h" +// to use placement new +#define IMGUI_DEFINE_PLACEMENT_NEW +#include "../imgui/imgui_internal.h" + CIMGUI_API ImGuiIO* igGetIO() { return &ImGui::GetIO(); @@ -406,6 +410,16 @@ CIMGUI_API void igPopButtonRepeat() return ImGui::PopButtonRepeat(); } +CIMGUI_API void igPushNavDefaultFocus(bool default_focus) +{ + return ImGui::PushNavDefaultFocus(default_focus); +} + +CIMGUI_API void igPopNavDefaultFocus() +{ + return ImGui::PopNavDefaultFocus(); +} + // Tooltip CIMGUI_API void igSetTooltip(CONST char* fmt, ...) { @@ -633,43 +647,43 @@ CIMGUI_API int igGetColumnsCount() // ID scopes // 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') -CIMGUI_API void igPushIdStr(CONST char* str_id) +CIMGUI_API void igPushIDStr(CONST char* str_id) { return ImGui::PushID(str_id); } -CIMGUI_API void igPushIdStrRange(CONST char* str_begin, CONST char* str_end) +CIMGUI_API void igPushIDStrRange(CONST char* str_begin, CONST char* str_end) { return ImGui::PushID(str_begin, str_end); } -CIMGUI_API void igPushIdPtr(CONST void* ptr_id) +CIMGUI_API void igPushIDPtr(CONST void* ptr_id) { return ImGui::PushID(ptr_id); } -CIMGUI_API void igPushIdInt(int int_id) +CIMGUI_API void igPushIDInt(int int_id) { return ImGui::PushID(int_id); } -CIMGUI_API void igPopId() +CIMGUI_API void igPopID() { return ImGui::PopID(); } -CIMGUI_API ImGuiID igGetIdStr(CONST char* str_id) +CIMGUI_API ImGuiID igGetIDStr(CONST char* str_id) { return ImGui::GetID(str_id); } -CIMGUI_API ImGuiID igGetIdStrRange(CONST char* str_begin, CONST char* str_end) +CIMGUI_API ImGuiID igGetIDStrRange(CONST char* str_begin, CONST char* str_end) { return ImGui::GetID(str_begin, str_end); } -CIMGUI_API ImGuiID igGetIdPtr(CONST void* ptr_id) +CIMGUI_API ImGuiID igGetIDPtr(CONST void* ptr_id) { return ImGui::GetID(ptr_id); } @@ -922,7 +936,7 @@ CIMGUI_API bool igColorPicker3(CONST char* label, float col[3], ImGuiColorEditFl CIMGUI_API bool igColorPicker4(CONST char* label, float col[4], ImGuiColorEditFlags flags, CONST float* ref_col) { - return ImGui::ColorPicker4(label, col, flags); + return ImGui::ColorPicker4(label, col, flags, ref_col); } CIMGUI_API bool igColorButton(CONST char* desc_id, CONST ImVec4 col, ImGuiColorEditFlags flags, CONST ImVec2 size) @@ -1277,7 +1291,7 @@ CIMGUI_API void igLogText(CONST char* fmt, ...) char buffer[256]; va_list args; va_start(args, fmt); - snprintf(buffer, 256, fmt, args); + vsnprintf(buffer, 256, fmt, args); va_end(args); ImGui::LogText("%s",buffer); @@ -1299,11 +1313,6 @@ CIMGUI_API bool igIsItemHovered() return ImGui::IsItemHovered(); } -CIMGUI_API bool igIsItemRectHovered() -{ - return ImGui::IsItemRectHovered(); -} - CIMGUI_API bool igIsItemActive() { return ImGui::IsItemActive(); @@ -1334,11 +1343,6 @@ CIMGUI_API bool igIsAnyItemActive() return ImGui::IsAnyItemActive(); } -CIMGUI_API bool igIsAnyItemFocused() -{ - return ImGui::IsAnyItemFocused(); -} - CIMGUI_API void igGetItemRectMin(ImVec2* pOut) { *pOut = ImGui::GetItemRectMin(); @@ -1359,11 +1363,6 @@ CIMGUI_API void igSetItemAllowOverlap() ImGui::SetItemAllowOverlap(); } -CIMGUI_API void igSetItemDefaultFocus() -{ - ImGui::SetItemDefaultFocus(); -} - CIMGUI_API bool igIsWindowFocused() { return ImGui::IsWindowFocused(); @@ -1374,11 +1373,6 @@ CIMGUI_API bool igIsWindowHovered() return ImGui::IsWindowHovered(); } -CIMGUI_API bool igIsWindowRectHovered() -{ - return ImGui::IsWindowRectHovered(); -} - CIMGUI_API bool igIsRootWindowFocused() { return ImGui::IsRootWindowFocused(); @@ -1429,11 +1423,6 @@ CIMGUI_API bool igIsKeyReleased(int user_key_index) return ImGui::IsKeyReleased(user_key_index); } -CIMGUI_API int igGetKeyPressedAmount(int key_index, float repeat_delay, float rate) -{ - return ImGui::GetKeyPressedAmount(key_index, repeat_delay, rate); -} - CIMGUI_API bool igIsMouseDown(int button) { return ImGui::IsMouseDown(button); @@ -1624,121 +1613,202 @@ CIMGUI_API void ImGuiIO_ClearInputCharacters() return ImGui::GetIO().ClearInputCharacters(); } -CIMGUI_API void ImGuiTextFilter_Init(struct ImGuiTextFilter* filter, const char* default_filter) +CIMGUI_API struct ImGuiTextFilter* ImGuiTextFilter_Create(const char* default_filter) { - *filter = ImGuiTextFilter(default_filter); + ImGuiTextFilter* filter = (ImGuiTextFilter*)ImGui::MemAlloc(sizeof(ImGuiTextFilter)); + IM_PLACEMENT_NEW(filter) ImGuiTextFilter(); + return filter; } -CIMGUI_API void ImGuiTextFilter_Clear(struct ImGuiTextFilter* filter) +CIMGUI_API void ImGuiTextFilter_Destroy(struct ImGuiTextFilter* filter) { - filter->Clear(); + filter->~ImGuiTextFilter(); + ImGui::MemFree(filter); } -CIMGUI_API bool ImGuiTextFilter_Draw(struct ImGuiTextFilter* filter, const char* label, float width) +CIMGUI_API void ImGuiTextFilter_Clear(struct ImGuiTextFilter* filter) { - return filter->Draw(label, width); + filter->Clear(); } -CIMGUI_API bool ImGuiTextFilter_PassFilter(struct ImGuiTextFilter* filter, const char* text, const char* text_end) +CIMGUI_API bool ImGuiTextFilter_Draw(struct ImGuiTextFilter* filter, const char* label, float width) { - return filter->PassFilter(text, text_end); + return filter->Draw(label, width); } -CIMGUI_API bool ImGuiTextFilter_IsActive(struct ImGuiTextFilter* filter) +CIMGUI_API bool ImGuiTextFilter_PassFilter(const struct ImGuiTextFilter* filter, const char* text, const char* text_end) { - return filter->IsActive(); -} -CIMGUI_API void ImGuiTextFilter_Build(struct ImGuiTextFilter* filter) -{ - filter->Build(); + return filter->PassFilter(text, text_end); } -CIMGUI_API void ImGuiTextEditCallbackData_DeleteChars(struct ImGuiTextEditCallbackData* data, int pos, int bytes_count) +CIMGUI_API bool ImGuiTextFilter_IsActive(const struct ImGuiTextFilter* filter) { - data->DeleteChars(pos, bytes_count); + return filter->IsActive(); } -CIMGUI_API void ImGuiTextEditCallbackData_InsertChars(struct ImGuiTextEditCallbackData* data, int pos, const char* text, const char* text_end) +CIMGUI_API void ImGuiTextFilter_Build(struct ImGuiTextFilter* filter) { - data->InsertChars(pos, text, text_end); + filter->Build(); } -CIMGUI_API bool ImGuiTextEditCallbackData_HasSelection(struct ImGuiTextEditCallbackData* data) +CIMGUI_API const char* ImGuiTextFilter_GetInputBuf(struct ImGuiTextFilter* filter) { - return data->HasSelection(); + return filter->InputBuf; } -CIMGUI_API void ImGuiStorage_Init(struct ImGuiStorage* storage) +CIMGUI_API struct ImGuiTextBuffer* ImGuiTextBuffer_Create() { - *storage = ImGuiStorage(); + ImGuiTextBuffer* buffer = (ImGuiTextBuffer*)ImGui::MemAlloc(sizeof(ImGuiTextBuffer)); + IM_PLACEMENT_NEW(buffer) ImGuiTextBuffer(); + return buffer; +} + +CIMGUI_API void ImGuiTextBuffer_Destroy(struct ImGuiTextBuffer* buffer) +{ + buffer->~ImGuiTextBuffer(); + ImGui::MemFree(buffer); +} + +CIMGUI_API char ImGuiTextBuffer_index(struct ImGuiTextBuffer* buffer, int i) +{ + return (*buffer)[i]; +} + +CIMGUI_API const char* ImGuiTextBuffer_begin(const struct ImGuiTextBuffer* buffer) +{ + return buffer->begin(); +} + +CIMGUI_API const char* ImGuiTextBuffer_end(const struct ImGuiTextBuffer* buffer) +{ + return buffer->end(); +} + +CIMGUI_API int ImGuiTextBuffer_size(const struct ImGuiTextBuffer* buffer) +{ + return buffer->size(); +} + +CIMGUI_API bool ImGuiTextBuffer_empty(struct ImGuiTextBuffer* buffer) +{ + return buffer->empty(); +} + +CIMGUI_API void ImGuiTextBuffer_clear(struct ImGuiTextBuffer* buffer) +{ + buffer->clear(); +} + +CIMGUI_API const char* ImGuiTextBuffer_c_str(const struct ImGuiTextBuffer* buffer) +{ + return buffer->c_str(); +} + +CIMGUI_API void ImGuiTextBuffer_append(struct ImGuiTextBuffer* buffer, const char* fmt, ...) +{ + va_list args; + va_start(args, fmt); + buffer->appendv(fmt, args); + va_end(args); +} + +CIMGUI_API void ImGuiTextBuffer_appendv(struct ImGuiTextBuffer* buffer, const char* fmt, va_list args) +{ + buffer->appendv(fmt, args); +} + +CIMGUI_API struct ImGuiStorage* ImGuiStorage_Create() { + ImGuiStorage* storage = (ImGuiStorage*)ImGui::MemAlloc(sizeof(ImGuiStorage)); + IM_PLACEMENT_NEW(storage) ImGuiStorage(); + return storage; +} + +CIMGUI_API void ImGuiStorage_Destroy(struct ImGuiStorage* storage) { + storage->~ImGuiStorage(); + ImGui::MemFree(storage); } CIMGUI_API void ImGuiStorage_Clear(struct ImGuiStorage* storage) { - storage->Clear(); + storage->Clear(); } CIMGUI_API int ImGuiStorage_GetInt(struct ImGuiStorage* storage, ImGuiID key, int default_val) { - return storage->GetInt(key, default_val); + return storage->GetInt(key, default_val); } CIMGUI_API void ImGuiStorage_SetInt(struct ImGuiStorage* storage, ImGuiID key, int val) { - storage->SetInt(key, val); + storage->SetInt(key, val); } CIMGUI_API bool ImGuiStorage_GetBool(struct ImGuiStorage* storage, ImGuiID key, bool default_val) { - return storage->GetBool(key, default_val); + return storage->GetBool(key, default_val); } CIMGUI_API void ImGuiStorage_SetBool(struct ImGuiStorage* storage, ImGuiID key, bool val) { - storage->SetBool(key, val); + storage->SetBool(key, val); } CIMGUI_API float ImGuiStorage_GetFloat(struct ImGuiStorage* storage, ImGuiID key, float default_val) { - return storage->GetFloat(key, default_val); + return storage->GetFloat(key, default_val); } CIMGUI_API void ImGuiStorage_SetFloat(struct ImGuiStorage* storage, ImGuiID key, float val) { - storage->SetFloat(key, val); + storage->SetFloat(key, val); } CIMGUI_API void* ImGuiStorage_GetVoidPtr(struct ImGuiStorage* storage, ImGuiID key) { - return storage->GetVoidPtr(key); + return storage->GetVoidPtr(key); } CIMGUI_API void ImGuiStorage_SetVoidPtr(struct ImGuiStorage* storage, ImGuiID key, void* val) { - storage->SetVoidPtr(key, val); + storage->SetVoidPtr(key, val); } CIMGUI_API int* ImGuiStorage_GetIntRef(struct ImGuiStorage* storage, ImGuiID key, int default_val) { - return storage->GetIntRef(key, default_val); + return storage->GetIntRef(key, default_val); } CIMGUI_API bool* ImGuiStorage_GetBoolRef(struct ImGuiStorage* storage, ImGuiID key, bool default_val) { - return storage->GetBoolRef(key, default_val); + return storage->GetBoolRef(key, default_val); } CIMGUI_API float* ImGuiStorage_GetFloatRef(struct ImGuiStorage* storage, ImGuiID key, float default_val) { - return storage->GetFloatRef(key, default_val); + return storage->GetFloatRef(key, default_val); } CIMGUI_API void** ImGuiStorage_GetVoidPtrRef(struct ImGuiStorage* storage, ImGuiID key, void* default_val) { - return storage->GetVoidPtrRef(key, default_val); + return storage->GetVoidPtrRef(key, default_val); } CIMGUI_API void ImGuiStorage_SetAllInt(struct ImGuiStorage* storage, int val) { - storage->SetAllInt(val); + storage->SetAllInt(val); +} + +CIMGUI_API void ImGuiTextEditCallbackData_DeleteChars(struct ImGuiTextEditCallbackData* data, int pos, int bytes_count) +{ + data->DeleteChars(pos, bytes_count); +} + +CIMGUI_API void ImGuiTextEditCallbackData_InsertChars(struct ImGuiTextEditCallbackData* data, int pos, const char* text, const char* text_end) +{ + data->InsertChars(pos, text, text_end); +} + +CIMGUI_API bool ImGuiTextEditCallbackData_HasSelection(struct ImGuiTextEditCallbackData* data) +{ + return data->HasSelection(); } diff --git a/deps/cimgui/cimgui/cimgui.h b/deps/cimgui/cimgui/cimgui.h index a51f390a..d2e70e1b 100644 --- a/deps/cimgui/cimgui/cimgui.h +++ b/deps/cimgui/cimgui/cimgui.h @@ -7,7 +7,7 @@ #else #define API __declspec(dllexport) #endif -#ifdef __GNUC__ +#ifndef __GNUC__ #define snprintf sprintf_s #endif #else @@ -37,6 +37,7 @@ struct ImGuiStorage; struct ImFont; struct ImFontConfig; struct ImFontAtlas; +struct ImFontGlyph; struct ImDrawCmd; struct ImGuiListClipper; struct ImGuiTextFilter; @@ -93,7 +94,10 @@ enum { ImGuiWindowFlags_AlwaysVerticalScrollbar = 1 << 14, ImGuiWindowFlags_AlwaysHorizontalScrollbar = 1 << 15, ImGuiWindowFlags_AlwaysUseWindowPadding = 1 << 16, - ImGuiWindowFlags_NavFlattened = 1 << 19, + ImGuiWindowFlags_NoNavFocus = 1 << 17, + ImGuiWindowFlags_NoNavInputs = 1 << 18, + ImGuiWindowFlags_NavFlattened = 1 << 19, + ImGuiWindowFlags_NoNavScroll = 1 << 20, }; enum { @@ -202,6 +206,8 @@ enum { ImGuiCol_PlotHistogramHovered, ImGuiCol_TextSelectedBg, ImGuiCol_ModalWindowDarkening, + ImGuiCol_NavHighlight, + ImGuiCol_NavWindowingHighlight, ImGuiCol_COUNT }; @@ -510,6 +516,8 @@ CIMGUI_API void igPushAllowKeyboardFocus(bool v); CIMGUI_API void igPopAllowKeyboardFocus(); CIMGUI_API void igPushButtonRepeat(bool repeat); CIMGUI_API void igPopButtonRepeat(); +CIMGUI_API void igPushNavDefaultFocus(bool default_focus); +CIMGUI_API void igPopNavDefaultFocus(); // Layout CIMGUI_API void igSeparator(); @@ -548,14 +556,14 @@ CIMGUI_API int igGetColumnsCount(); // ID scopes // 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') -CIMGUI_API void igPushIdStr(CONST char* str_id); -CIMGUI_API void igPushIdStrRange(CONST char* str_begin, CONST char* str_end); -CIMGUI_API void igPushIdPtr(CONST void* ptr_id); -CIMGUI_API void igPushIdInt(int int_id); -CIMGUI_API void igPopId(); -CIMGUI_API ImGuiID igGetIdStr(CONST char* str_id); -CIMGUI_API ImGuiID igGetIdStrRange(CONST char* str_begin,CONST char* str_end); -CIMGUI_API ImGuiID igGetIdPtr(CONST void* ptr_id); +CIMGUI_API void igPushIDStr(CONST char* str_id); +CIMGUI_API void igPushIDStrRange(CONST char* str_begin, CONST char* str_end); +CIMGUI_API void igPushIDPtr(CONST void* ptr_id); +CIMGUI_API void igPushIDInt(int int_id); +CIMGUI_API void igPopID(); +CIMGUI_API ImGuiID igGetIDStr(CONST char* str_id); +CIMGUI_API ImGuiID igGetIDStrRange(CONST char* str_begin,CONST char* str_end); +CIMGUI_API ImGuiID igGetIDPtr(CONST void* ptr_id); // Widgets CIMGUI_API void igText(CONST char* fmt, ...); @@ -714,22 +722,18 @@ CIMGUI_API void igPopClipRect(); // Utilities CIMGUI_API bool igIsItemHovered(); -CIMGUI_API bool igIsItemRectHovered(); CIMGUI_API bool igIsItemActive(); CIMGUI_API bool igIsItemFocused(); CIMGUI_API bool igIsItemClicked(int mouse_button); CIMGUI_API bool igIsItemVisible(); CIMGUI_API bool igIsAnyItemHovered(); CIMGUI_API bool igIsAnyItemActive(); -CIMGUI_API bool igIsAnyItemFocused(); CIMGUI_API void igGetItemRectMin(struct ImVec2* pOut); CIMGUI_API void igGetItemRectMax(struct ImVec2* pOut); CIMGUI_API void igGetItemRectSize(struct ImVec2* pOut); CIMGUI_API void igSetItemAllowOverlap(); -CIMGUI_API void igSetItemDefaultFocus(); CIMGUI_API bool igIsWindowFocused(); CIMGUI_API bool igIsWindowHovered(); -CIMGUI_API bool igIsWindowRectHovered(); CIMGUI_API bool igIsRootWindowFocused(); CIMGUI_API bool igIsRootWindowOrAnyChildFocused(); CIMGUI_API bool igIsRootWindowOrAnyChildHovered(); @@ -755,7 +759,6 @@ CIMGUI_API int igGetKeyIndex(ImGuiKey imgui_key); CIMGUI_API bool igIsKeyDown(int user_key_index); CIMGUI_API bool igIsKeyPressed(int user_key_index, bool repeat); CIMGUI_API bool igIsKeyReleased(int user_key_index); -CIMGUI_API int igGetKeyPressedAmount(int key_index, float repeat_delay, float rate); CIMGUI_API bool igIsMouseDown(int button); CIMGUI_API bool igIsMouseClicked(int button, bool repeat); CIMGUI_API bool igIsMouseDoubleClicked(int button); @@ -778,47 +781,76 @@ CIMGUI_API CONST char* igGetClipboardText(); CIMGUI_API void igSetClipboardText(CONST char* text); // Internal state access - if you want to share ImGui state between modules (e.g. DLL) or allocate it yourself -CIMGUI_API CONST char* igGetVersion(); -CIMGUI_API struct ImGuiContext* igCreateContext(void* (*malloc_fn)(size_t), void (*free_fn)(void*)); -CIMGUI_API void igDestroyContext(struct ImGuiContext* ctx); -CIMGUI_API struct ImGuiContext* igGetCurrentContext(); -CIMGUI_API void igSetCurrentContext(struct ImGuiContext* ctx); +CIMGUI_API CONST char* igGetVersion(); +CIMGUI_API struct ImGuiContext* igCreateContext(void* (*malloc_fn)(size_t), void (*free_fn)(void*)); +CIMGUI_API void igDestroyContext(struct ImGuiContext* ctx); +CIMGUI_API struct ImGuiContext* igGetCurrentContext(); +CIMGUI_API void igSetCurrentContext(struct ImGuiContext* ctx); -CIMGUI_API void ImFontConfig_DefaultConstructor(struct ImFontConfig* config); +// ImGuiIO +CIMGUI_API void ImGuiIO_AddInputCharacter(unsigned short c); +CIMGUI_API void ImGuiIO_AddInputCharactersUTF8(CONST char* utf8_chars); +CIMGUI_API void ImGuiIO_ClearInputCharacters(); -CIMGUI_API void ImFontAtlas_GetTexDataAsRGBA32(struct ImFontAtlas* atlas, unsigned char** out_pixels, int* out_width, int* out_height, int* out_bytes_per_pixel); -CIMGUI_API void ImFontAtlas_GetTexDataAsAlpha8(struct ImFontAtlas* atlas, unsigned char** out_pixels, int* out_width, int* out_height, int* out_bytes_per_pixel); -CIMGUI_API void ImFontAtlas_SetTexID(struct ImFontAtlas* atlas, ImTextureID id); -CIMGUI_API struct ImFont* ImFontAtlas_AddFont(struct ImFontAtlas* atlas, CONST struct ImFontConfig* font_cfg); -CIMGUI_API struct ImFont* ImFontAtlas_AddFontDefault(struct ImFontAtlas* atlas, CONST struct ImFontConfig* font_cfg); -CIMGUI_API struct ImFont* ImFontAtlas_AddFontFromFileTTF(struct ImFontAtlas* atlas, CONST char* filename, float size_pixels, CONST struct ImFontConfig* font_cfg, CONST ImWchar* glyph_ranges); -CIMGUI_API struct ImFont* ImFontAtlas_AddFontFromMemoryTTF(struct ImFontAtlas* atlas, void* font_data, int font_size, float size_pixels, CONST struct ImFontConfig* font_cfg, CONST ImWchar* glyph_ranges); -CIMGUI_API struct ImFont* ImFontAtlas_AddFontFromMemoryCompressedTTF(struct ImFontAtlas* atlas, CONST void* compressed_font_data, int compressed_font_size, float size_pixels, CONST struct ImFontConfig* font_cfg, CONST ImWchar* glyph_ranges); -CIMGUI_API struct ImFont* ImFontAtlas_AddFontFromMemoryCompressedBase85TTF(struct ImFontAtlas* atlas, CONST char* compressed_font_data_base85, float size_pixels, CONST struct ImFontConfig* font_cfg, CONST ImWchar* glyph_ranges); -CIMGUI_API void ImFontAtlas_ClearTexData(struct ImFontAtlas* atlas); -CIMGUI_API void ImFontAtlas_Clear(struct ImFontAtlas* atlas); -CIMGUI_API CONST ImWchar* ImFontAtlas_GetGlyphRangesDefault(struct ImFontAtlas* atlas); -CIMGUI_API CONST ImWchar* ImFontAtlas_GetGlyphRangesKorean(struct ImFontAtlas* atlas); -CIMGUI_API CONST ImWchar* ImFontAtlas_GetGlyphRangesJapanese(struct ImFontAtlas* atlas); -CIMGUI_API CONST ImWchar* ImFontAtlas_GetGlyphRangesChinese(struct ImFontAtlas* atlas); -CIMGUI_API CONST ImWchar* ImFontAtlas_GetGlyphRangesCyrillic(struct ImFontAtlas* atlas); -CIMGUI_API CONST ImWchar* ImFontAtlas_GetGlyphRangesThai(struct ImFontAtlas* atlas); +// ImGuiTextFilter +CIMGUI_API struct ImGuiTextFilter* ImGuiTextFilter_Create(const char* default_filter); +CIMGUI_API void ImGuiTextFilter_Destroy(struct ImGuiTextFilter* filter); +CIMGUI_API void ImGuiTextFilter_Clear(struct ImGuiTextFilter* filter); +CIMGUI_API bool ImGuiTextFilter_Draw(struct ImGuiTextFilter* filter, const char* label, float width); +CIMGUI_API bool ImGuiTextFilter_PassFilter(const struct ImGuiTextFilter* filter, const char* text, const char* text_end); +CIMGUI_API bool ImGuiTextFilter_IsActive(const struct ImGuiTextFilter* filter); +CIMGUI_API void ImGuiTextFilter_Build(struct ImGuiTextFilter* filter); +CIMGUI_API const char* ImGuiTextFilter_GetInputBuf(struct ImGuiTextFilter* filter); -CIMGUI_API void ImGuiIO_AddInputCharacter(unsigned short c); -CIMGUI_API void ImGuiIO_AddInputCharactersUTF8(CONST char* utf8_chars); -CIMGUI_API void ImGuiIO_ClearInputCharacters(); +// ImGuiTextBuffer +CIMGUI_API struct ImGuiTextBuffer* ImGuiTextBuffer_Create(); +CIMGUI_API void ImGuiTextBuffer_Destroy(struct ImGuiTextBuffer* buffer); +CIMGUI_API char ImGuiTextBuffer_index(struct ImGuiTextBuffer* buffer, int i); +CIMGUI_API const char* ImGuiTextBuffer_begin(const struct ImGuiTextBuffer* buffer); +CIMGUI_API const char* ImGuiTextBuffer_end(const struct ImGuiTextBuffer* buffer); +CIMGUI_API int ImGuiTextBuffer_size(const struct ImGuiTextBuffer* buffer); +CIMGUI_API bool ImGuiTextBuffer_empty(struct ImGuiTextBuffer* buffer); +CIMGUI_API void ImGuiTextBuffer_clear(struct ImGuiTextBuffer* buffer); +CIMGUI_API const char* ImGuiTextBuffer_c_str(const struct ImGuiTextBuffer* buffer); +CIMGUI_API void ImGuiTextBuffer_append(struct ImGuiTextBuffer* buffer, const char* fmt, ...); +CIMGUI_API void ImGuiTextBuffer_appendv(struct ImGuiTextBuffer* buffer, const char* fmt, va_list args); -//ImDrawData -CIMGUI_API void ImDrawData_DeIndexAllBuffers(struct ImDrawData* drawData); -CIMGUI_API void ImDrawData_ScaleClipRects(struct ImDrawData* drawData, struct ImVec2 sc); +// ImGuiStorage +CIMGUI_API struct ImGuiStorage* ImGuiStorage_Create(); +CIMGUI_API void ImGuiStorage_Destroy(struct ImGuiStorage* storage); +CIMGUI_API int ImGuiStorage_GetInt(struct ImGuiStorage* storage, ImGuiID key, int default_val); +CIMGUI_API void ImGuiStorage_SetInt(struct ImGuiStorage* storage, ImGuiID key, int val); +CIMGUI_API bool ImGuiStorage_GetBool(struct ImGuiStorage* storage, ImGuiID key, bool default_val); +CIMGUI_API void ImGuiStorage_SetBool(struct ImGuiStorage* storage, ImGuiID key, bool val); +CIMGUI_API float ImGuiStorage_GetFloat(struct ImGuiStorage* storage, ImGuiID key, float default_val); +CIMGUI_API void ImGuiStorage_SetFloat(struct ImGuiStorage* storage, ImGuiID key, float val); +CIMGUI_API void* ImGuiStorage_GetVoidPtr(struct ImGuiStorage* storage, ImGuiID key); +CIMGUI_API void ImGuiStorage_SetVoidPtr(struct ImGuiStorage* storage, ImGuiID key, void* val); +CIMGUI_API int* ImGuiStorage_GetIntRef(struct ImGuiStorage* storage, ImGuiID key, int default_val); +CIMGUI_API bool* ImGuiStorage_GetBoolRef(struct ImGuiStorage* storage, ImGuiID key, bool default_val); +CIMGUI_API float* ImGuiStorage_GetFloatRef(struct ImGuiStorage* storage, ImGuiID key, float default_val); +CIMGUI_API void** ImGuiStorage_GetVoidPtrRef(struct ImGuiStorage* storage, ImGuiID key, void* default_val); +CIMGUI_API void ImGuiStorage_SetAllInt(struct ImGuiStorage* storage, int val); + +// ImGuiTextEditCallbackData +CIMGUI_API void ImGuiTextEditCallbackData_DeleteChars(struct ImGuiTextEditCallbackData* data, int pos, int bytes_count); +CIMGUI_API void ImGuiTextEditCallbackData_InsertChars(struct ImGuiTextEditCallbackData* data, int pos, const char* text, const char* text_end); +CIMGUI_API bool ImGuiTextEditCallbackData_HasSelection(struct ImGuiTextEditCallbackData* data); + +// ImGuiListClipper +CIMGUI_API void ImGuiListClipper_Begin(struct ImGuiListClipper* clipper, int count, float items_height); +CIMGUI_API void ImGuiListClipper_End(struct ImGuiListClipper* clipper); +CIMGUI_API bool ImGuiListClipper_Step(struct ImGuiListClipper* clipper); +CIMGUI_API int ImGuiListClipper_GetDisplayStart(struct ImGuiListClipper* clipper); +CIMGUI_API int ImGuiListClipper_GetDisplayEnd(struct ImGuiListClipper* clipper); //ImDrawList -CIMGUI_API int ImDrawList_GetVertexBufferSize(struct ImDrawList* list); -CIMGUI_API struct ImDrawVert* ImDrawList_GetVertexPtr(struct ImDrawList* list, int n); -CIMGUI_API int ImDrawList_GetIndexBufferSize(struct ImDrawList* list); -CIMGUI_API ImDrawIdx* ImDrawList_GetIndexPtr(struct ImDrawList* list, int n); -CIMGUI_API int ImDrawList_GetCmdSize(struct ImDrawList* list); -CIMGUI_API struct ImDrawCmd* ImDrawList_GetCmdPtr(struct ImDrawList* list, int n); +CIMGUI_API int ImDrawList_GetVertexBufferSize(struct ImDrawList* list); +CIMGUI_API struct ImDrawVert* ImDrawList_GetVertexPtr(struct ImDrawList* list, int n); +CIMGUI_API int ImDrawList_GetIndexBufferSize(struct ImDrawList* list); +CIMGUI_API ImDrawIdx* ImDrawList_GetIndexPtr(struct ImDrawList* list, int n); +CIMGUI_API int ImDrawList_GetCmdSize(struct ImDrawList* list); +CIMGUI_API struct ImDrawCmd* ImDrawList_GetCmdPtr(struct ImDrawList* list, int n); CIMGUI_API void ImDrawList_Clear(struct ImDrawList* list); CIMGUI_API void ImDrawList_ClearFreeMemory(struct ImDrawList* list); @@ -873,46 +905,83 @@ CIMGUI_API void ImDrawList_AddDrawCmd(struct ImDrawList* list); // T CIMGUI_API void ImDrawList_PrimReserve(struct ImDrawList* list, int idx_count, int vtx_count); CIMGUI_API void ImDrawList_PrimRect(struct ImDrawList* list, CONST struct ImVec2 a, CONST struct ImVec2 b, ImU32 col); CIMGUI_API void ImDrawList_PrimRectUV(struct ImDrawList* list, CONST struct ImVec2 a, CONST struct ImVec2 b, CONST struct ImVec2 uv_a, CONST struct ImVec2 uv_b, ImU32 col); -CIMGUI_API void ImDrawList_PrimQuadUV(struct ImDrawList* list,CONST struct ImVec2 a, CONST struct ImVec2 b, CONST struct ImVec2 c, CONST struct ImVec2 d, CONST struct ImVec2 uv_a, CONST struct ImVec2 uv_b, CONST struct ImVec2 uv_c, CONST struct ImVec2 uv_d, ImU32 col); +CIMGUI_API void ImDrawList_PrimQuadUV(struct ImDrawList* list, CONST struct ImVec2 a, CONST struct ImVec2 b, CONST struct ImVec2 c, CONST struct ImVec2 d, CONST struct ImVec2 uv_a, CONST struct ImVec2 uv_b, CONST struct ImVec2 uv_c, CONST struct ImVec2 uv_d, ImU32 col); CIMGUI_API void ImDrawList_PrimWriteVtx(struct ImDrawList* list, CONST struct ImVec2 pos, CONST struct ImVec2 uv, ImU32 col); CIMGUI_API void ImDrawList_PrimWriteIdx(struct ImDrawList* list, ImDrawIdx idx); CIMGUI_API void ImDrawList_PrimVtx(struct ImDrawList* list, CONST struct ImVec2 pos, CONST struct ImVec2 uv, ImU32 col); CIMGUI_API void ImDrawList_UpdateClipRect(struct ImDrawList* list); CIMGUI_API void ImDrawList_UpdateTextureID(struct ImDrawList* list); -// ImGuiListClipper -CIMGUI_API void ImGuiListClipper_Begin(struct ImGuiListClipper* clipper, int count, float items_height); -CIMGUI_API void ImGuiListClipper_End(struct ImGuiListClipper* clipper); -CIMGUI_API bool ImGuiListClipper_Step(struct ImGuiListClipper* clipper); -CIMGUI_API int ImGuiListClipper_GetDisplayStart(struct ImGuiListClipper* clipper); -CIMGUI_API int ImGuiListClipper_GetDisplayEnd(struct ImGuiListClipper* clipper); +// ImDrawData +CIMGUI_API void ImDrawData_DeIndexAllBuffers(struct ImDrawData* drawData); +CIMGUI_API void ImDrawData_ScaleClipRects(struct ImDrawData* drawData, const struct ImVec2 sc); -// ImGuiTextFilter -CIMGUI_API void ImGuiTextFilter_Init(struct ImGuiTextFilter* filter, const char* default_filter); -CIMGUI_API void ImGuiTextFilter_Clear(struct ImGuiTextFilter* filter); -CIMGUI_API bool ImGuiTextFilter_Draw(struct ImGuiTextFilter* filter, const char* label, float width); -CIMGUI_API bool ImGuiTextFilter_PassFilter(struct ImGuiTextFilter* filter, const char* text, const char* text_end); -CIMGUI_API bool ImGuiTextFilter_IsActive(struct ImGuiTextFilter* filter); -CIMGUI_API void ImGuiTextFilter_Build(struct ImGuiTextFilter* filter); +// ImFontAtlas +CIMGUI_API void ImFontAtlas_GetTexDataAsRGBA32(struct ImFontAtlas* atlas, unsigned char** out_pixels, int* out_width, int* out_height, int* out_bytes_per_pixel); +CIMGUI_API void ImFontAtlas_GetTexDataAsAlpha8(struct ImFontAtlas* atlas, unsigned char** out_pixels, int* out_width, int* out_height, int* out_bytes_per_pixel); +CIMGUI_API void ImFontAtlas_SetTexID(struct ImFontAtlas* atlas, ImTextureID id); +CIMGUI_API struct ImFont* ImFontAtlas_AddFont(struct ImFontAtlas* atlas, CONST struct ImFontConfig* font_cfg); +CIMGUI_API struct ImFont* ImFontAtlas_AddFontDefault(struct ImFontAtlas* atlas, CONST struct ImFontConfig* font_cfg); +CIMGUI_API struct ImFont* ImFontAtlas_AddFontFromFileTTF(struct ImFontAtlas* atlas, CONST char* filename, float size_pixels, CONST struct ImFontConfig* font_cfg, CONST ImWchar* glyph_ranges); +CIMGUI_API struct ImFont* ImFontAtlas_AddFontFromMemoryTTF(struct ImFontAtlas* atlas, void* font_data, int font_size, float size_pixels, CONST struct ImFontConfig* font_cfg, CONST ImWchar* glyph_ranges); +CIMGUI_API struct ImFont* ImFontAtlas_AddFontFromMemoryCompressedTTF(struct ImFontAtlas* atlas, CONST void* compressed_font_data, int compressed_font_size, float size_pixels, CONST struct ImFontConfig* font_cfg, CONST ImWchar* glyph_ranges); +CIMGUI_API struct ImFont* ImFontAtlas_AddFontFromMemoryCompressedBase85TTF(struct ImFontAtlas* atlas, CONST char* compressed_font_data_base85, float size_pixels, CONST struct ImFontConfig* font_cfg, CONST ImWchar* glyph_ranges); +CIMGUI_API void ImFontAtlas_ClearTexData(struct ImFontAtlas* atlas); +CIMGUI_API void ImFontAtlas_Clear(struct ImFontAtlas* atlas); +CIMGUI_API CONST ImWchar* ImFontAtlas_GetGlyphRangesDefault(struct ImFontAtlas* atlas); +CIMGUI_API CONST ImWchar* ImFontAtlas_GetGlyphRangesKorean(struct ImFontAtlas* atlas); +CIMGUI_API CONST ImWchar* ImFontAtlas_GetGlyphRangesJapanese(struct ImFontAtlas* atlas); +CIMGUI_API CONST ImWchar* ImFontAtlas_GetGlyphRangesChinese(struct ImFontAtlas* atlas); +CIMGUI_API CONST ImWchar* ImFontAtlas_GetGlyphRangesCyrillic(struct ImFontAtlas* atlas); +CIMGUI_API CONST ImWchar* ImFontAtlas_GetGlyphRangesThai(struct ImFontAtlas* atlas); -// ImGuiTextEditCallbackData -CIMGUI_API void ImGuiTextEditCallbackData_DeleteChars(struct ImGuiTextEditCallbackData* data, int pos, int bytes_count); -CIMGUI_API void ImGuiTextEditCallbackData_InsertChars(struct ImGuiTextEditCallbackData* data, int pos, const char* text, const char* text_end); -CIMGUI_API bool ImGuiTextEditCallbackData_HasSelection(struct ImGuiTextEditCallbackData* data); +CIMGUI_API ImTextureID ImFontAtlas_GetTexID(struct ImFontAtlas* atlas); +CIMGUI_API unsigned char* ImFontAtlas_GetTexPixelsAlpha8(struct ImFontAtlas* atlas); +CIMGUI_API unsigned int* ImFontAtlas_GetTexPixelsRGBA32(struct ImFontAtlas* atlas); +CIMGUI_API int ImFontAtlas_GetTexWidth(struct ImFontAtlas* atlas); +CIMGUI_API int ImFontAtlas_GetTexHeight(struct ImFontAtlas* atlas); +CIMGUI_API int ImFontAtlas_GetTexDesiredWidth(struct ImFontAtlas* atlas); +CIMGUI_API void ImFontAtlas_SetTexDesiredWidth(struct ImFontAtlas* atlas, int TexDesiredWidth_); +CIMGUI_API int ImFontAtlas_GetTexGlyphPadding(struct ImFontAtlas* atlas); +CIMGUI_API void ImFontAtlas_SetTexGlyphPadding(struct ImFontAtlas* atlas, int TexGlyphPadding_); +CIMGUI_API void ImFontAtlas_GetTexUvWhitePixel(struct ImFontAtlas* atlas, struct ImVec2* pOut); -// ImGuiStorage -CIMGUI_API void ImGuiStorage_Init(struct ImGuiStorage* storage); -CIMGUI_API void ImGuiStorage_Clear(struct ImGuiStorage* storage); -CIMGUI_API int ImGuiStorage_GetInt(struct ImGuiStorage* storage, ImGuiID key, int default_val); -CIMGUI_API void ImGuiStorage_SetInt(struct ImGuiStorage* storage, ImGuiID key, int val); -CIMGUI_API bool ImGuiStorage_GetBool(struct ImGuiStorage* storage, ImGuiID key, bool default_val); -CIMGUI_API void ImGuiStorage_SetBool(struct ImGuiStorage* storage, ImGuiID key, bool val); -CIMGUI_API float ImGuiStorage_GetFloat(struct ImGuiStorage* storage, ImGuiID key, float default_val); -CIMGUI_API void ImGuiStorage_SetFloat(struct ImGuiStorage* storage, ImGuiID key, float val); -CIMGUI_API void* ImGuiStorage_GetVoidPtr(struct ImGuiStorage* storage, ImGuiID key); -CIMGUI_API void ImGuiStorage_SetVoidPtr(struct ImGuiStorage* storage, ImGuiID key, void* val); -CIMGUI_API int* ImGuiStorage_GetIntRef(struct ImGuiStorage* storage, ImGuiID key, int default_val); -CIMGUI_API bool* ImGuiStorage_GetBoolRef(struct ImGuiStorage* storage, ImGuiID key, bool default_val); -CIMGUI_API float* ImGuiStorage_GetFloatRef(struct ImGuiStorage* storage, ImGuiID key, float default_val); -CIMGUI_API void** ImGuiStorage_GetVoidPtrRef(struct ImGuiStorage* storage, ImGuiID key, void* default_val); -CIMGUI_API void ImGuiStorage_SetAllInt(struct ImGuiStorage* storage, int val); +// ImFontAtlas::Fonts; +CIMGUI_API int ImFontAtlas_Fonts_size(struct ImFontAtlas* atlas); +CIMGUI_API struct ImFont* ImFontAtlas_Fonts_index(struct ImFontAtlas* atlas, int index); + +// ImFont +CIMGUI_API float ImFont_GetFontSize(const struct ImFont* font); +CIMGUI_API void ImFont_SetFontSize(struct ImFont* font, float FontSize_); +CIMGUI_API float ImFont_GetScale(const struct ImFont* font); +CIMGUI_API void ImFont_SetScale(struct ImFont* font, float Scale_); +CIMGUI_API void ImFont_GetDisplayOffset(const struct ImFont* font, struct ImVec2* pOut); +CIMGUI_API const struct ImFontGlyph* ImFont_GetFallbackGlyph(const struct ImFont* font); +CIMGUI_API void ImFont_SetFallbackGlyph(struct ImFont* font, const struct ImFontGlyph* FallbackGlyph_); +CIMGUI_API float ImFont_GetFallbackAdvanceX(const struct ImFont* font); +CIMGUI_API ImWchar ImFont_GetFallbackChar(const struct ImFont* font); +CIMGUI_API short ImFont_GetConfigDataCount(const struct ImFont* font); +CIMGUI_API struct ImFontConfig* ImFont_GetConfigData(struct ImFont* font); +CIMGUI_API struct ImFontAtlas* ImFont_GetContainerAtlas(struct ImFont* font); +CIMGUI_API float ImFont_GetAscent(const struct ImFont* font); +CIMGUI_API float ImFont_GetDescent(const struct ImFont* font); +CIMGUI_API int ImFont_GetMetricsTotalSurface(const struct ImFont* font); +CIMGUI_API void ImFont_ClearOutputData(struct ImFont* font); +CIMGUI_API void ImFont_BuildLookupTable(struct ImFont* font); +CIMGUI_API const struct ImFontGlyph* ImFont_FindGlyph(const struct ImFont* font, ImWchar c); +CIMGUI_API void ImFont_SetFallbackChar(struct ImFont* font, ImWchar c); +CIMGUI_API float ImFont_GetCharAdvance(const struct ImFont* font, ImWchar c); +CIMGUI_API bool ImFont_IsLoaded(const struct ImFont* font); +CIMGUI_API void ImFont_CalcTextSizeA(const struct ImFont* font, struct ImVec2* pOut, float size, float max_width, float wrap_width, const char* text_begin, const char* text_end, const char** remaining); // utf8 +CIMGUI_API const char* ImFont_CalcWordWrapPositionA(const struct ImFont* font, float scale, const char* text, const char* text_end, float wrap_width); +CIMGUI_API void ImFont_RenderChar(const struct ImFont* font, struct ImDrawList* draw_list, float size, struct ImVec2 pos, ImU32 col, unsigned short c); +CIMGUI_API void ImFont_RenderText(const struct ImFont* font, struct ImDrawList* draw_list, float size, struct ImVec2 pos, ImU32 col, const struct ImVec4* clip_rect, const char* text_begin, const char* text_end, float wrap_width, bool cpu_fine_clip); +// ImFont::Glyph +CIMGUI_API int ImFont_Glyphs_size(const struct ImFont* font); +CIMGUI_API struct ImFontGlyph* ImFont_Glyphs_index(struct ImFont* font, int index); +// ImFont::IndexAdvanceX +CIMGUI_API int ImFont_IndexAdvanceX_size(const struct ImFont* font); +CIMGUI_API float ImFont_IndexAdvanceX_index(const struct ImFont* font, int index); +// ImFont::IndexLookup +CIMGUI_API int ImFont_IndexLookup_size(const struct ImFont* font); +CIMGUI_API unsigned short ImFont_IndexLookup_index(const struct ImFont* font, int index); diff --git a/deps/cimgui/cimgui/drawList.cpp b/deps/cimgui/cimgui/drawList.cpp index c9a71d4d..9307495f 100644 --- a/deps/cimgui/cimgui/drawList.cpp +++ b/deps/cimgui/cimgui/drawList.cpp @@ -2,287 +2,287 @@ #include "../imgui/imgui.h" #include "cimgui.h" +CIMGUI_API void ImDrawData_DeIndexAllBuffers(ImDrawData* drawData) +{ + return drawData->DeIndexAllBuffers(); +} + +CIMGUI_API void ImDrawData_ScaleClipRects(ImDrawData* drawData, const struct ImVec2 sc) +{ + return drawData->ScaleClipRects(sc); +} + CIMGUI_API int ImDrawList_GetVertexBufferSize(ImDrawList* list) { - return list->VtxBuffer.size(); + return list->VtxBuffer.size(); } CIMGUI_API ImDrawVert* ImDrawList_GetVertexPtr(ImDrawList* list, int n) { - return &list->VtxBuffer[n]; + return &list->VtxBuffer[n]; } CIMGUI_API int ImDrawList_GetIndexBufferSize(ImDrawList* list) { - return list->IdxBuffer.size(); + return list->IdxBuffer.size(); } CIMGUI_API ImDrawIdx* ImDrawList_GetIndexPtr(ImDrawList* list, int n) { - return &list->IdxBuffer[n]; + return &list->IdxBuffer[n]; } CIMGUI_API int ImDrawList_GetCmdSize(ImDrawList* list) { - return list->CmdBuffer.size(); + return list->CmdBuffer.size(); } CIMGUI_API ImDrawCmd* ImDrawList_GetCmdPtr(ImDrawList* list, int n) { - return &list->CmdBuffer[n]; -} - -CIMGUI_API void ImDrawData_DeIndexAllBuffers(ImDrawData* drawData) -{ - return drawData->DeIndexAllBuffers(); -} - -CIMGUI_API void ImDrawData_ScaleClipRects(ImDrawData* drawData, struct ImVec2 sc) -{ - return drawData->ScaleClipRects(sc); + return &list->CmdBuffer[n]; } CIMGUI_API void ImDrawList_Clear(ImDrawList* list) { - return list->Clear(); + return list->Clear(); } CIMGUI_API void ImDrawList_ClearFreeMemory(ImDrawList* list) { - return list->ClearFreeMemory(); + return list->ClearFreeMemory(); } CIMGUI_API void ImDrawList_PushClipRect(ImDrawList* list, struct ImVec2 clip_rect_min, struct ImVec2 clip_rect_max, bool intersect_with_current_clip_rect) { - return list->PushClipRect(clip_rect_min,clip_rect_max,intersect_with_current_clip_rect); + return list->PushClipRect(clip_rect_min,clip_rect_max,intersect_with_current_clip_rect); } CIMGUI_API void ImDrawList_PushClipRectFullScreen(ImDrawList* list) { - return list->PushClipRectFullScreen(); + return list->PushClipRectFullScreen(); } CIMGUI_API void ImDrawList_PopClipRect(ImDrawList* list) { - return list->PopClipRect(); + return list->PopClipRect(); } CIMGUI_API void ImDrawList_PushTextureID(ImDrawList* list, CONST ImTextureID texture_id) { - return list->PushTextureID(texture_id); + return list->PushTextureID(texture_id); } CIMGUI_API void ImDrawList_PopTextureID(ImDrawList* list) { - return list->PopTextureID(); + return list->PopTextureID(); } CIMGUI_API void ImDrawList_GetClipRectMin(ImVec2* pOut, ImDrawList* list) { - *pOut = list->GetClipRectMin(); + *pOut = list->GetClipRectMin(); } CIMGUI_API void ImDrawList_GetClipRectMax(ImVec2* pOut, ImDrawList* list) { - *pOut = list->GetClipRectMax(); + *pOut = list->GetClipRectMax(); } CIMGUI_API void ImDrawList_AddLine(ImDrawList* list, CONST struct ImVec2 a, CONST struct ImVec2 b, ImU32 col, float thickness) { - return list->AddLine(a, b, col, thickness); + return list->AddLine(a, b, col, thickness); } CIMGUI_API void ImDrawList_AddRect(ImDrawList* list, CONST struct ImVec2 a, CONST struct ImVec2 b, ImU32 col, float rounding, int rounding_corners_flags, float thickness) { - return list->AddRect(a, b, col, rounding, rounding_corners_flags, thickness); + return list->AddRect(a, b, col, rounding, rounding_corners_flags, thickness); } CIMGUI_API void ImDrawList_AddRectFilled(ImDrawList* list, CONST struct ImVec2 a, CONST struct ImVec2 b, ImU32 col, float rounding, int rounding_corners_flags) { - return list->AddRectFilled(a, b, col, rounding, rounding_corners_flags); + return list->AddRectFilled(a, b, col, rounding, rounding_corners_flags); } CIMGUI_API void ImDrawList_AddRectFilledMultiColor(ImDrawList* list, CONST struct ImVec2 a, CONST struct ImVec2 b, ImU32 col_upr_left, ImU32 col_upr_right, ImU32 col_bot_right, ImU32 col_bot_left) { - return list->AddRectFilledMultiColor(a, b, col_upr_left, col_upr_right, col_bot_right, col_bot_left); + return list->AddRectFilledMultiColor(a, b, col_upr_left, col_upr_right, col_bot_right, col_bot_left); } CIMGUI_API void ImDrawList_AddQuad(ImDrawList* list, CONST struct ImVec2 a, CONST struct ImVec2 b, CONST struct ImVec2 c, CONST struct ImVec2 d, ImU32 col, float thickness) { - return list->AddQuad(a, b, c, d, col, thickness); + return list->AddQuad(a, b, c, d, col, thickness); } CIMGUI_API void ImDrawList_AddQuadFilled(ImDrawList* list, CONST struct ImVec2 a, CONST struct ImVec2 b, CONST struct ImVec2 c, CONST struct ImVec2 d, ImU32 col) { - return list->AddQuadFilled(a, b, c, d, col); + return list->AddQuadFilled(a, b, c, d, col); } CIMGUI_API void ImDrawList_AddTriangle(ImDrawList* list, CONST struct ImVec2 a, CONST struct ImVec2 b, CONST struct ImVec2 c, ImU32 col, float thickness) { - return list->AddTriangle(a,b,c,col,thickness); + return list->AddTriangle(a,b,c,col,thickness); } CIMGUI_API void ImDrawList_AddTriangleFilled(ImDrawList* list, CONST struct ImVec2 a, CONST struct ImVec2 b, CONST struct ImVec2 c, ImU32 col) { - return list->AddTriangleFilled(a, b, c, col); + return list->AddTriangleFilled(a, b, c, col); } CIMGUI_API void ImDrawList_AddCircle(ImDrawList* list, CONST struct ImVec2 centre, float radius, ImU32 col, int num_segments, float thickness) { - return list->AddCircle(centre, radius, col, num_segments, thickness); + return list->AddCircle(centre, radius, col, num_segments, thickness); } CIMGUI_API void ImDrawList_AddCircleFilled(ImDrawList* list, CONST struct ImVec2 centre, float radius, ImU32 col, int num_segments) { - return list->AddCircleFilled(centre, radius, col, num_segments); + return list->AddCircleFilled(centre, radius, col, num_segments); } CIMGUI_API void ImDrawList_AddText(ImDrawList* list, CONST struct ImVec2 pos, ImU32 col, CONST char* text_begin, CONST char* text_end) { - return list->AddText(pos, col, text_begin, text_end); + return list->AddText(pos, col, text_begin, text_end); } CIMGUI_API void ImDrawList_AddTextExt(ImDrawList* list, CONST ImFont* font, float font_size, CONST struct ImVec2 pos, ImU32 col, CONST char* text_begin, CONST char* text_end, float wrap_width, CONST ImVec4* cpu_fine_clip_rect) { - return list->AddText(font, font_size, pos, col, text_begin, text_end, wrap_width, cpu_fine_clip_rect); + return list->AddText(font, font_size, pos, col, text_begin, text_end, wrap_width, cpu_fine_clip_rect); } CIMGUI_API void ImDrawList_AddImage(ImDrawList* list, ImTextureID user_texture_id, CONST struct ImVec2 a, CONST struct ImVec2 b, CONST struct ImVec2 uv_a, CONST struct ImVec2 uv_b, ImU32 col) { - return list->AddImage(user_texture_id, a, b, uv_a, uv_b, col); + return list->AddImage(user_texture_id, a, b, uv_a, uv_b, col); } CIMGUI_API void ImDrawList_AddImageQuad(struct ImDrawList* list, ImTextureID user_texture_id, CONST struct ImVec2 a, CONST ImVec2 b, CONST ImVec2 c, CONST ImVec2 d, CONST ImVec2 uv_a, CONST ImVec2 uv_b, CONST ImVec2 uv_c, CONST ImVec2 uv_d, ImU32 col) { - return list->AddImageQuad(user_texture_id, a, b, c, d, uv_a, uv_b, uv_c, uv_d, col); + return list->AddImageQuad(user_texture_id, a, b, c, d, uv_a, uv_b, uv_c, uv_d, col); } CIMGUI_API void ImDrawList_AddPolyline(ImDrawList* list, CONST ImVec2* points, CONST int num_points, ImU32 col, bool closed, float thickness, bool anti_aliased) { - return list->AddPolyline(points, num_points, col, closed, thickness, anti_aliased); + return list->AddPolyline(points, num_points, col, closed, thickness, anti_aliased); } CIMGUI_API void ImDrawList_AddConvexPolyFilled(ImDrawList* list, CONST ImVec2* points, CONST int num_points, ImU32 col, bool anti_aliased) { - return list->AddConvexPolyFilled(points, num_points, col, anti_aliased); + return list->AddConvexPolyFilled(points, num_points, col, anti_aliased); } CIMGUI_API void ImDrawList_AddBezierCurve(ImDrawList* list, CONST struct ImVec2 pos0, CONST struct ImVec2 cp0, CONST struct ImVec2 cp1, CONST struct ImVec2 pos1, ImU32 col, float thickness, int num_segments) { - return list->AddBezierCurve(pos0, cp0, cp1, pos1, col, thickness, num_segments); + return list->AddBezierCurve(pos0, cp0, cp1, pos1, col, thickness, num_segments); } CIMGUI_API void ImDrawList_PathClear(ImDrawList* list) { - return list->PathClear(); + return list->PathClear(); } CIMGUI_API void ImDrawList_PathLineTo(ImDrawList* list, CONST struct ImVec2 pos) { - return list->PathLineTo(pos); + return list->PathLineTo(pos); } CIMGUI_API void ImDrawList_PathLineToMergeDuplicate(ImDrawList* list, CONST struct ImVec2 pos) { - return list->PathLineToMergeDuplicate(pos); + return list->PathLineToMergeDuplicate(pos); } CIMGUI_API void ImDrawList_PathFillConvex(ImDrawList* list, ImU32 col) { - return list->PathFillConvex(col); + return list->PathFillConvex(col); } CIMGUI_API void ImDrawList_PathStroke(ImDrawList* list, ImU32 col, bool closed, float thickness) { - return list->PathStroke(col, closed, thickness); + return list->PathStroke(col, closed, thickness); } CIMGUI_API void ImDrawList_PathArcTo(ImDrawList* list, CONST struct ImVec2 centre, float radius, float a_min, float a_max, int num_segments) { - return list->PathArcTo(centre, radius, a_min, a_max, num_segments); + return list->PathArcTo(centre, radius, a_min, a_max, num_segments); } CIMGUI_API void ImDrawList_PathArcToFast(ImDrawList* list, CONST struct ImVec2 centre, float radius, int a_min_of_12, int a_max_of_12) { - return list->PathArcToFast(centre, radius, a_min_of_12, a_max_of_12); + return list->PathArcToFast(centre, radius, a_min_of_12, a_max_of_12); } CIMGUI_API void ImDrawList_PathBezierCurveTo(ImDrawList* list, CONST struct ImVec2 p1, CONST struct ImVec2 p2, CONST struct ImVec2 p3, int num_segments) { - return list->PathBezierCurveTo(p1, p2, p3, num_segments); + return list->PathBezierCurveTo(p1, p2, p3, num_segments); } CIMGUI_API void ImDrawList_PathRect(ImDrawList* list, CONST struct ImVec2 rect_min, CONST struct ImVec2 rect_max, float rounding, int rounding_corners_flags) { - return list->PathRect(rect_min, rect_max, rounding, rounding_corners_flags); + return list->PathRect(rect_min, rect_max, rounding, rounding_corners_flags); } CIMGUI_API void ImDrawList_ChannelsSplit(ImDrawList* list, int channels_count) { - return list->ChannelsSplit(channels_count); + return list->ChannelsSplit(channels_count); } CIMGUI_API void ImDrawList_ChannelsMerge(ImDrawList* list) { - return list->ChannelsMerge(); + return list->ChannelsMerge(); } CIMGUI_API void ImDrawList_ChannelsSetCurrent(ImDrawList* list, int channel_index) { - return list->ChannelsSetCurrent(channel_index); + return list->ChannelsSetCurrent(channel_index); } CIMGUI_API void ImDrawList_AddCallback(ImDrawList* list, ImDrawCallback callback, void* callback_data) { - return list->AddCallback(callback, callback_data); + return list->AddCallback(callback, callback_data); } CIMGUI_API void ImDrawList_AddDrawCmd(ImDrawList* list) { - return list->AddDrawCmd(); + return list->AddDrawCmd(); } CIMGUI_API void ImDrawList_PrimReserve(ImDrawList* list, int idx_count, int vtx_count) { - return list->PrimReserve(idx_count, vtx_count); + return list->PrimReserve(idx_count, vtx_count); } CIMGUI_API void ImDrawList_PrimRect(ImDrawList* list, CONST struct ImVec2 a, CONST struct ImVec2 b, ImU32 col) { - return list->PrimRect(a, b, col); + return list->PrimRect(a, b, col); } CIMGUI_API void ImDrawList_PrimRectUV(ImDrawList* list, CONST struct ImVec2 a, CONST struct ImVec2 b, CONST struct ImVec2 uv_a, CONST struct ImVec2 uv_b, ImU32 col) { - return list->PrimRectUV(a, b, uv_a, uv_b, col); + return list->PrimRectUV(a, b, uv_a, uv_b, col); } CIMGUI_API void ImDrawList_PrimQuadUV(ImDrawList* list,CONST struct ImVec2 a, CONST struct ImVec2 b, CONST struct ImVec2 c, CONST struct ImVec2 d, CONST struct ImVec2 uv_a, CONST struct ImVec2 uv_b, CONST struct ImVec2 uv_c, CONST struct ImVec2 uv_d, ImU32 col) { - return list->PrimQuadUV(a,b,c,d,uv_a,uv_b,uv_c,uv_d,col); + return list->PrimQuadUV(a,b,c,d,uv_a,uv_b,uv_c,uv_d,col); } CIMGUI_API void ImDrawList_PrimVtx(ImDrawList* list, CONST struct ImVec2 pos, CONST struct ImVec2 uv, ImU32 col) { - return list->PrimVtx(pos, uv, col); + return list->PrimVtx(pos, uv, col); } CIMGUI_API void ImDrawList_PrimWriteVtx(ImDrawList* list, CONST struct ImVec2 pos, CONST struct ImVec2 uv, ImU32 col) { - return list->PrimWriteVtx(pos, uv, col); + return list->PrimWriteVtx(pos, uv, col); } CIMGUI_API void ImDrawList_PrimWriteIdx(ImDrawList* list, ImDrawIdx idx) { - return list->PrimWriteIdx(idx); + return list->PrimWriteIdx(idx); } CIMGUI_API void ImDrawList_UpdateClipRect(ImDrawList* list) { - return list->UpdateClipRect(); + return list->UpdateClipRect(); } CIMGUI_API void ImDrawList_UpdateTextureID(ImDrawList* list) { - return list->UpdateTextureID(); + return list->UpdateTextureID(); } diff --git a/deps/cimgui/cimgui/fontAtlas.cpp b/deps/cimgui/cimgui/fontAtlas.cpp index 5c79d8a0..a844a485 100644 --- a/deps/cimgui/cimgui/fontAtlas.cpp +++ b/deps/cimgui/cimgui/fontAtlas.cpp @@ -2,92 +2,317 @@ #include "../imgui/imgui.h" #include "cimgui.h" -CIMGUI_API void ImFontConfig_DefaultConstructor(ImFontConfig* config) -{ - *config = ImFontConfig(); -} - CIMGUI_API void ImFontAtlas_GetTexDataAsRGBA32(ImFontAtlas* atlas, unsigned char** out_pixels, int* out_width, int* out_height, int* out_bytes_per_pixel) { - atlas->GetTexDataAsRGBA32(out_pixels, out_width, out_height, out_bytes_per_pixel); + atlas->GetTexDataAsRGBA32(out_pixels, out_width, out_height, out_bytes_per_pixel); } CIMGUI_API void ImFontAtlas_GetTexDataAsAlpha8(ImFontAtlas* atlas, unsigned char** out_pixels, int* out_width, int* out_height, int* out_bytes_per_pixel) { - atlas->GetTexDataAsAlpha8(out_pixels, out_width, out_height, out_bytes_per_pixel); + atlas->GetTexDataAsAlpha8(out_pixels, out_width, out_height, out_bytes_per_pixel); } CIMGUI_API void ImFontAtlas_SetTexID(ImFontAtlas* atlas, ImTextureID id) { - atlas->TexID = id; + atlas->TexID = id; } CIMGUI_API ImFont* ImFontAtlas_AddFont(ImFontAtlas* atlas, CONST ImFontConfig* font_cfg) { - return atlas->AddFont(font_cfg); + return atlas->AddFont(font_cfg); } CIMGUI_API ImFont* ImFontAtlas_AddFontDefault(ImFontAtlas* atlas, CONST ImFontConfig* font_cfg) { - return atlas->AddFontDefault(font_cfg); + return atlas->AddFontDefault(font_cfg); } CIMGUI_API ImFont* ImFontAtlas_AddFontFromFileTTF(ImFontAtlas* atlas,CONST char* filename, float size_pixels, CONST ImFontConfig* font_cfg, CONST ImWchar* glyph_ranges) { - return atlas->AddFontFromFileTTF(filename, size_pixels, font_cfg, glyph_ranges); + return atlas->AddFontFromFileTTF(filename, size_pixels, font_cfg, glyph_ranges); } CIMGUI_API ImFont* ImFontAtlas_AddFontFromMemoryTTF(ImFontAtlas* atlas, void* font_data, int font_size, float size_pixels, CONST ImFontConfig* font_cfg, CONST ImWchar* glyph_ranges) { - return atlas->AddFontFromMemoryTTF(font_data, font_size, size_pixels, font_cfg, glyph_ranges); + return atlas->AddFontFromMemoryTTF(font_data, font_size, size_pixels, font_cfg, glyph_ranges); } CIMGUI_API ImFont* ImFontAtlas_AddFontFromMemoryCompressedTTF(ImFontAtlas* atlas, CONST void* compressed_font_data, int compressed_font_size, float size_pixels, CONST ImFontConfig* font_cfg, CONST ImWchar* glyph_ranges) { - return atlas->AddFontFromMemoryCompressedTTF(compressed_font_data, compressed_font_size, size_pixels, font_cfg, glyph_ranges); + return atlas->AddFontFromMemoryCompressedTTF(compressed_font_data, compressed_font_size, size_pixels, font_cfg, glyph_ranges); } CIMGUI_API ImFont* ImFontAtlas_AddFontFromMemoryCompressedBase85TTF(ImFontAtlas* atlas, CONST char* compressed_font_data_base85, float size_pixels, CONST ImFontConfig* font_cfg, CONST ImWchar* glyph_ranges) { - return atlas->AddFontFromMemoryCompressedBase85TTF(compressed_font_data_base85, size_pixels, font_cfg, glyph_ranges); + return atlas->AddFontFromMemoryCompressedBase85TTF(compressed_font_data_base85, size_pixels, font_cfg, glyph_ranges); } CIMGUI_API void ImFontAtlas_ClearTexData(ImFontAtlas* atlas) { - return atlas->ClearTexData(); + return atlas->ClearTexData(); +} + +CIMGUI_API void ImFontAtlas_ClearInputData(ImFontAtlas* atlas) +{ + return atlas->ClearInputData(); +} + +CIMGUI_API void ImFontAtlas_ClearFonts(ImFontAtlas* atlas) +{ + return atlas->ClearFonts(); } CIMGUI_API void ImFontAtlas_Clear(ImFontAtlas* atlas) { - return atlas->Clear(); + return atlas->Clear(); } CIMGUI_API CONST ImWchar* ImFontAtlas_GetGlyphRangesDefault(struct ImFontAtlas* atlas) { - return atlas->GetGlyphRangesDefault(); + return atlas->GetGlyphRangesDefault(); } CIMGUI_API CONST ImWchar* ImFontAtlas_GetGlyphRangesKorean(struct ImFontAtlas* atlas) { - return atlas->GetGlyphRangesKorean(); + return atlas->GetGlyphRangesKorean(); } CIMGUI_API CONST ImWchar* ImFontAtlas_GetGlyphRangesJapanese(struct ImFontAtlas* atlas) { - return atlas->GetGlyphRangesJapanese(); + return atlas->GetGlyphRangesJapanese(); } CIMGUI_API CONST ImWchar* ImFontAtlas_GetGlyphRangesChinese(struct ImFontAtlas* atlas) { - return atlas->GetGlyphRangesChinese(); + return atlas->GetGlyphRangesChinese(); } CIMGUI_API CONST ImWchar* ImFontAtlas_GetGlyphRangesCyrillic(struct ImFontAtlas* atlas) { - return atlas->GetGlyphRangesCyrillic(); + return atlas->GetGlyphRangesCyrillic(); } CIMGUI_API CONST ImWchar* ImFontAtlas_GetGlyphRangesThai(struct ImFontAtlas* atlas) { - return atlas->GetGlyphRangesThai(); + return atlas->GetGlyphRangesThai(); +} + +CIMGUI_API ImTextureID ImFontAtlas_GetTexID(struct ImFontAtlas* atlas) +{ + return atlas->TexID; +} + +CIMGUI_API unsigned char* ImFontAtlas_GetTexPixelsAlpha8(struct ImFontAtlas* atlas) +{ + return atlas->TexPixelsAlpha8; +} + +CIMGUI_API unsigned int* ImFontAtlas_GetTexPixelsRGBA32(struct ImFontAtlas* atlas) +{ + return atlas->TexPixelsRGBA32; +} + +CIMGUI_API int ImFontAtlas_GetTexWidth(struct ImFontAtlas* atlas) +{ + return atlas->TexWidth; +} + +CIMGUI_API int ImFontAtlas_GetTexHeight(struct ImFontAtlas* atlas) +{ + return atlas->TexHeight; +} + +CIMGUI_API int ImFontAtlas_GetTexDesiredWidth(struct ImFontAtlas* atlas) +{ + return atlas->TexDesiredWidth; +} + +CIMGUI_API void ImFontAtlas_SetTexDesiredWidth(struct ImFontAtlas* atlas, int TexDesiredWidth_) +{ + atlas->TexDesiredWidth = TexDesiredWidth_; +} + +CIMGUI_API int ImFontAtlas_GetTexGlyphPadding(struct ImFontAtlas* atlas) +{ + return atlas->TexGlyphPadding; +} + +CIMGUI_API void ImFontAtlas_SetTexGlyphPadding(struct ImFontAtlas* atlas, int TexGlyphPadding_) +{ + atlas->TexGlyphPadding = TexGlyphPadding_; +} + +CIMGUI_API void ImFontAtlas_GetTexUvWhitePixel(struct ImFontAtlas* atlas, ImVec2* pOut) +{ + *pOut = atlas->TexUvWhitePixel; +} + +// ImFontAtlas::Fonts; +CIMGUI_API int ImFontAtlas_Fonts_size(struct ImFontAtlas* atlas) +{ + return atlas->Fonts.size(); +} + +CIMGUI_API ImFont* ImFontAtlas_Fonts_index(struct ImFontAtlas* atlas, int index) +{ + return atlas->Fonts[index]; +} + +// ImFont +CIMGUI_API float ImFont_GetFontSize(const struct ImFont* font) +{ + return font->FontSize; +} + +CIMGUI_API void ImFont_SetFontSize(struct ImFont* font, float FontSize_) +{ + font->FontSize = FontSize_; +} + +CIMGUI_API float ImFont_GetScale(const struct ImFont* font) +{ + return font->Scale; +} + +CIMGUI_API void ImFont_SetScale(struct ImFont* font, float Scale_) +{ + font->Scale = Scale_; +} + +CIMGUI_API void ImFont_GetDisplayOffset(const struct ImFont* font, ImVec2* pOut) +{ + *pOut = font->DisplayOffset; +} + +CIMGUI_API const struct ImFontGlyph* ImFont_GetFallbackGlyph(const struct ImFont* font) +{ + return font->FallbackGlyph; +} + +CIMGUI_API void ImFont_SetFallbackGlyph(struct ImFont* font, const struct ImFontGlyph* FallbackGlyph_) +{ + font->FallbackGlyph = FallbackGlyph_; +} + +CIMGUI_API float ImFont_GetFallbackAdvanceX(const struct ImFont* font) +{ + return font->FallbackAdvanceX; +} + +CIMGUI_API ImWchar ImFont_GetFallbackChar(const struct ImFont* font) +{ + return font->FallbackChar; +} + +CIMGUI_API short ImFont_GetConfigDataCount(const struct ImFont* font) +{ + return font->ConfigDataCount; +} + +CIMGUI_API struct ImFontConfig* ImFont_GetConfigData(struct ImFont* font) +{ + return font->ConfigData; +} + +CIMGUI_API struct ImFontAtlas* ImFont_GetContainerAtlas(struct ImFont* font) +{ + return font->ContainerAtlas; +} + +CIMGUI_API float ImFont_GetAscent(const struct ImFont* font) +{ + return font->Ascent; +} + +CIMGUI_API float ImFont_GetDescent(const struct ImFont* font) +{ + return font->Descent; +} + +CIMGUI_API int ImFont_GetMetricsTotalSurface(const struct ImFont* font) +{ + return font->MetricsTotalSurface; +} + +CIMGUI_API void ImFont_ClearOutputData(struct ImFont* font) +{ + font->ClearOutputData(); +} + +CIMGUI_API void ImFont_BuildLookupTable(struct ImFont* font) +{ + font->BuildLookupTable(); +} + +CIMGUI_API const struct ImFontGlyph* ImFont_FindGlyph(const struct ImFont* font, ImWchar c) +{ + return font->FindGlyph(c); +} + +CIMGUI_API void ImFont_SetFallbackChar(struct ImFont* font, ImWchar c) +{ + font->SetFallbackChar(c); +} + +CIMGUI_API float ImFont_GetCharAdvance(const struct ImFont* font, ImWchar c) +{ + return font->GetCharAdvance(c); +} + +CIMGUI_API bool ImFont_IsLoaded(const struct ImFont* font) +{ + return font->IsLoaded(); +} + +CIMGUI_API void ImFont_CalcTextSizeA(const struct ImFont* font, ImVec2* pOut, float size, float max_width, float wrap_width, const char* text_begin, const char* text_end, const char** remaining) +{ + *pOut = font->CalcTextSizeA(size, max_width, wrap_width, text_begin, text_end, remaining); +} + +CIMGUI_API const char* ImFont_CalcWordWrapPositionA(const struct ImFont* font, float scale, const char* text, const char* text_end, float wrap_width) +{ + return font->CalcWordWrapPositionA(scale, text, text_end, wrap_width); +} + +CIMGUI_API void ImFont_RenderChar(const struct ImFont* font, ImDrawList* draw_list, float size, ImVec2 pos, ImU32 col, unsigned short c) +{ + return font->RenderChar(draw_list, size, pos, col, c); +} + +CIMGUI_API void ImFont_RenderText(const struct ImFont* font, ImDrawList* draw_list, float size, ImVec2 pos, ImU32 col, const ImVec4* clip_rect, const char* text_begin, const char* text_end, float wrap_width, bool cpu_fine_clip) +{ + return font->RenderText(draw_list, size, pos, col, *clip_rect, text_begin, text_end, wrap_width, cpu_fine_clip); +} + +// ImFontGlyph +CIMGUI_API int ImFont_Glyphs_size(const struct ImFont* font) +{ + return font->Glyphs.size(); +} + +CIMGUI_API struct ImFontGlyph* ImFont_Glyphs_index(struct ImFont* font, int index) +{ + return &font->Glyphs[index]; +} + +// ImFont::IndexXAdvance +CIMGUI_API int ImFont_IndexAdvanceX_size(const struct ImFont* font) +{ + return font->IndexAdvanceX.size(); +} + +CIMGUI_API float ImFont_IndexAdvanceX_index(const struct ImFont* font, int index) +{ + return font->IndexAdvanceX[index]; +} + +// ImFont::IndexLookup +CIMGUI_API int ImFont_IndexLookup_size(const struct ImFont* font) +{ + return font->IndexLookup.size(); +} + +CIMGUI_API unsigned short ImFont_IndexLookup_index(const struct ImFont* font, int index) +{ + return font->IndexLookup[index]; } diff --git a/deps/cimgui/imgui/README.md b/deps/cimgui/imgui/README.md index 5e1174b0..306a8e54 100644 --- a/deps/cimgui/imgui/README.md +++ b/deps/cimgui/imgui/README.md @@ -45,44 +45,44 @@ Binaries/Demo ------------- You should be able to build the examples from sources (tested on Windows/Mac/Linux). If you don't, let me know! If you want to have a quick look at some Dear ImGui features, you can download Windows binaries of the demo app here: -- [imgui-demo-binaries-20170723.zip](http://www.miracleworld.net/imgui/binaries/imgui-demo-binaries-20170723.zip) (Windows binaries, Dear ImGui 1.51+ 2017/07/23, 5 executables, 808 KB) +- [imgui-demo-binaries-20171013.zip](http://www.miracleworld.net/imgui/binaries/imgui-demo-binaries-20171013.zip) (Windows binaries, Dear ImGui 1.52 WIP built 2017/10/13, 5 executables) Bindings -------- +Integrating Dear ImGui within your custom engine is a matter of wiring mouse/keyboard inputs and providing a render function that can bind a texture and render simple textured triangles. The examples/ folder is populated with applications doing just that. If you are an experienced programmer it should take you less than an hour to integrate Dear ImGui in your custom engine, but make sure to spend time reading the FAQ, the comments and other documentation! + _NB: those third-party bindings may be more or less maintained, more or less close to the spirit of original API and therefore I cannot give much guarantee about them. People who create language bindings sometimes haven't used the C++ API themselves (for the good reason that they aren't C++ users). Dear ImGui was designed with C++ in mind and some of the subtleties may be lost in translation with other languages. If your language supports it, I would suggest replicating the function overloading and default parameters used in the original, else the API may be harder to use. In doubt, please check the original C++ version first!_ -_Integrating Dear ImGui within your custom engine is a matter of wiring mouse/keyboard inputs and providing a render function that can bind a texture and render simple textured triangles. The examples/ folder is populated with applications doing just that. If you are an experienced programmer it should take you less than an hour to integrate Dear ImGui in your custom engine, but make sure to spend time reading the FAQ, the comments and other documentation!_ - Languages: -- C - cimgui: thin c-api wrapper for ImGui https://github.com/Extrawurst/cimgui -- C#/.Net - ImGui.NET: An ImGui wrapper for .NET Core https://github.com/mellinoe/ImGui.NET -- D - DerelictImgui: Dynamic bindings for the D programming language: https://github.com/Extrawurst/DerelictImgui -- Go - go-imgui https://github.com/Armored-Dragon/go-imgui -- Lua - https://github.com/patrickriordan/imgui_lua_bindings -- Pascal - imgui-pas https://github.com/dpethes/imgui-pas -- Python - CyImGui: Python bindings for dear imgui using Cython: https://github.com/chromy/cyimgui -- Python - pyimgui: Another Python bindings for dear imgui: https://github.com/swistakm/pyimgui -- Rust - imgui-rs: Rust bindings for dear imgui https://github.com/Gekkio/imgui-rs +- C (cimgui): thin c-api wrapper for ImGui https://github.com/Extrawurst/cimgui +- C#/.Net (ImGui.NET): An ImGui wrapper for .NET Core https://github.com/mellinoe/ImGui.NET +- D (DerelictImgui): Dynamic bindings for the D programming language: https://github.com/Extrawurst/DerelictImgui +- Go (go-imgui): https://github.com/Armored-Dragon/go-imgui +- Lua: https://github.com/patrickriordan/imgui_lua_bindings +- Pascal (imgui-pas) https://github.com/dpethes/imgui-pas +- Python (CyImGui): Python bindings for dear imgui using Cython: https://github.com/chromy/cyimgui +- Python (pyimgui): Another Python bindings for dear imgui: https://github.com/swistakm/pyimgui +- Rust (imgui-rs): Rust bindings for dear imgui https://github.com/Gekkio/imgui-rs Frameworks: - Main ImGui repository include examples for DirectX9, DirectX10, DirectX11, OpenGL2/3, Vulkan, Allegro 5, SDL+GL2/3, iOS and Marmalade: https://github.com/ocornut/imgui/tree/master/examples -- Unmerged PR: DirectX12 example (with issues) https://github.com/ocornut/imgui/pull/301 -- Unmerged PR: SDL2 + OpenGLES + Emscripten example https://github.com/ocornut/imgui/pull/336 -- Unmerged PR: FreeGlut + OpenGL2 example https://github.com/ocornut/imgui/pull/801 -- Unmerged PR: Native Win32 and OSX example https://github.com/ocornut/imgui/pull/281 -- Unmerged PR: Android Example https://github.com/ocornut/imgui/pull/421 -- Cinder backend for dear imgui https://github.com/simongeilfus/Cinder-ImGui -- FlexGUI: Flexium/SFML backend for dear imgui https://github.com/DXsmiley/FlexGUI -- IrrIMGUI: Irrlicht backend for dear imgui https://github.com/ZahlGraf/IrrIMGUI -- UnrealEngine_ImGui: Unreal Engine 4 backend for dear imgui https://github.com/sronsse/UnrealEngine_ImGui -- LÖVE backend for dear imgui https://github.com/slages/love-imgui -- Ogre backend for dear imgui https://bitbucket.org/LMCrashy/ogreimgui/src -- ofxImGui: openFrameworks backend for dear imgui https://github.com/jvcleave/ofxImGui -- SFML backend for dear imgui https://github.com/EliasD/imgui-sfml -- SFML backend for dear imgui https://github.com/Mischa-Alff/imgui-backends -- cocos2d-x with imgui https://github.com/c0i/imguix https://github.com/ocornut/imgui/issues/551 -- NanoRT: software raytraced version https://github.com/syoyo/imgui/tree/nanort/examples/raytrace_example +- Unmerged PR: DirectX12: https://github.com/ocornut/imgui/pull/301 +- Unmerged PR: SDL2 + OpenGLES + Emscripten: https://github.com/ocornut/imgui/pull/336 +- Unmerged PR: FreeGlut + OpenGL2: https://github.com/ocornut/imgui/pull/801 +- Unmerged PR: Native Win32 and OSX: https://github.com/ocornut/imgui/pull/281 +- Unmerged PR: Android: https://github.com/ocornut/imgui/pull/421 +- Cinder: https://github.com/simongeilfus/Cinder-ImGui +- cocos2d-x: https://github.com/c0i/imguix https://github.com/ocornut/imgui/issues/551 +- Flexium/SFML (FlexGUI): https://github.com/DXsmiley/FlexGUI +- Irrlicht (IrrIMGUI): https://github.com/ZahlGraf/IrrIMGUI +- Ogre: https://bitbucket.org/LMCrashy/ogreimgui/src +- openFrameworks (ofxImGui): https://github.com/jvcleave/ofxImGui +- LÖVE: https://github.com/slages/love-imgui +- NanoRT (software raytraced) https://github.com/syoyo/imgui/tree/nanort/examples/raytrace_example +- Qt3d https://github.com/alpqr/imgui-qt3d +- Unreal Engine 4: https://github.com/segross/UnrealImGui or https://github.com/sronsse/UnrealEngine_ImGui +- SFML: https://github.com/EliasD/imgui-sfml or https://github.com/Mischa-Alff/imgui-backends For other bindings: see [this page](https://github.com/ocornut/imgui/wiki/Links/). Please contact me with the Issues tracker or Twitter to fix/update this list. @@ -91,6 +91,7 @@ Gallery ------- See the [Screenshots Thread](https://github.com/ocornut/imgui/issues/123) for some user creations. +Also see the [Mega screenshots](https://github.com/ocornut/imgui/issues/1273) for an idea of the available features. ![screenshot 1](https://raw.githubusercontent.com/wiki/ocornut/imgui/web/v148/examples_01.png) [![screenshot game](https://raw.githubusercontent.com/wiki/ocornut/imgui/web/v149/gallery_TheDragonsTrap-01-thumb.jpg)](https://cloud.githubusercontent.com/assets/8225057/20628927/33e14cac-b329-11e6-80f6-9524e93b048a.png) @@ -137,11 +138,15 @@ Frequently Asked Question (FAQ) - Standalone example applications using e.g. OpenGL/DirectX are provided in the examples/ folder. - We obviously needs better documentation! Consider contributing or becoming a [Patron](http://www.patreon.com/imgui) to promote this effort. +Which version should I get? + +I occasionally tag [Releases](https://github.com/ocornut/imgui/releases) but it is generally safe and recommended to sync to master. The library is fairly stable and regressions tend to be fixed fast when reported. You may also want to checkout the [navigation branch](https://github.com/ocornut/imgui/tree/navigation) if you want to use Dear ImGui with a gamepad (it is also possible to map keyboard inputs to some degree). The Navigation branch is being kept up to date with Master. + Why the odd dual naming, "dear imgui" vs "ImGui"? The library started its life and is best known as "ImGui" only due to the fact that I didn't give it a proper name when I released it. However, the term IMGUI (immediate-mode graphical user interface) was coined before and is being used in variety of other situations. It seemed confusing and unfair to hog the name. To reduce the ambiguity without affecting existing codebases, I have decided on an alternate, longer name "dear imgui" that people can use to refer to this specific library in ambiguous situations. -
What is ImTextureID and how do I display an image? +What is ImTextureID and how do I display an image?
I integrated Dear ImGui in my engine and the text or lines are blurry..
I integrated Dear ImGui in my engine and some elements are disappearing when I move windows around..
How can I have multiple widgets with the same label? Can I have widget without a label? (Yes). A primer on labels/IDs. @@ -157,13 +162,13 @@ See the FAQ in imgui.cpp for answers. How do you use Dear ImGui on a platform that may not have a mouse or keyboard? -I recommend using [Synergy](http://synergy-project.org) ([sources](https://github.com/symless/synergy)). In particular, the _src/micro/uSynergy.c_ file contains a small client that you can use on any platform to connect to your host PC. You can seamlessly use your PC input devices from a video game console or a tablet. Dear ImGui allows to increase the hit box of widgets (via the _TouchPadding_ setting) to accommodate a little for the lack of precision of touch inputs, but it is recommended you use a mouse to allow optimising for screen real-estate. +I recommend using [Synergy](http://synergy-project.org) ([sources](https://github.com/symless/synergy)). In particular, the _src/micro/uSynergy.c_ file contains a small client that you can use on any platform to connect to your host PC. You can seamlessly use your PC input devices from a video game console or a tablet. Dear ImGui allows to increase the hit box of widgets (via the _style.TouchPadding_ setting) to accommodate a little for the lack of precision of touch inputs, but it is recommended you use a mouse to allow optimising for screen real-estate. You can also checkout the beta [navigation branch](https://github.com/ocornut/imgui/tree/navigation) which provides support for using Dear ImGui with a game controller. Can you create elaborate/serious tools with Dear ImGui? -Yes. I have written data browsers, debuggers, profilers and all sort of non-trivial tools with the library. In my experience the simplicity of the API is very empowering. Your UI runs close to your live data. Make the tools always-on and everybody in the team will be inclined to create new tools (as opposed to more "offline" UI toolkits where only a fraction of your team effectively creates tools). +Yes. People have written game editors, data browsers, debuggers, profilers and all sort of non-trivial tools with the library. In my experience the simplicity of the API is very empowering. Your UI runs close to your live data. Make the tools always-on and everybody in the team will be inclined to create new tools (as opposed to more "offline" UI toolkits where only a fraction of your team effectively creates tools). -Dear ImGui is very programmer centric and the immediate-mode GUI paradigm might requires you to readjust some habits before you can realize its full potential. Many programmers have unfortunately been taught by their environment to make unnecessarily complicated things. Dear ImGui is about making things that are simple, efficient and powerful. +Dear ImGui is very programmer centric and the immediate-mode GUI paradigm might requires you to readjust some habits before you can realize its full potential. Dear ImGui is about making things that are simple, efficient and powerful. Is Dear ImGui fast? @@ -179,17 +184,15 @@ If you intend to display large lists of items (say, 1000+) it can be beneficial Can you reskin the look of Dear ImGui? -You can alter the look of the interface to some degree: changing colors, sizes, padding, rounding, fonts. However, as Dear ImGui is designed and optimised to create debug tools, the amount of skinning you can apply is limited. There is only so much you can stray away from the default look and feel of the interface. +You can alter the look of the interface to some degree: changing colors, sizes, padding, rounding, fonts. However, as Dear ImGui is designed and optimised to create debug tools, the amount of skinning you can apply is limited. There is only so much you can stray away from the default look and feel of the interface. Below is a screenshot from [LumixEngine](https://github.com/nem0/LumixEngine) with custom colors + a docking/tabs extension (both of which you can find in the Issues section and will eventually be merged): -This is [LumixEngine](https://github.com/nem0/LumixEngine) with a minor skinning hack + a docking/tabs extension (both of which you can find in the Issues section and will eventually be merged). - -[![Skinning in LumixEngine](https://cloud.githubusercontent.com/assets/8225057/13198792/92808c5c-d812-11e5-9507-16b63918b05b.jpg)](https://cloud.githubusercontent.com/assets/8225057/13044612/59f07aec-d3cf-11e5-8ccb-39adf2e13e69.png) +![LumixEngine](https://raw.githubusercontent.com/wiki/ocornut/imgui/web/v151/lumix-201710-rearranged.png) Why using C++ (as opposed to C)? -Dear ImGui takes advantage of a few C++ languages features for convenience but nothing anywhere Boost-insanity/quagmire. Dear ImGui doesn't use any C++ header file. Language-wise, function overloading and default parameters are used to make the API easier to use and code more terse. Doing so I believe the API is sitting on a sweet spot and giving up on those features would make the API more cumbersome. Other features such as namespace, constructors and templates (in the case of the ImVector<> class) are also relied on as a convenience. +Dear ImGui takes advantage of a few C++ languages features for convenience but nothing anywhere Boost-insanity/quagmire. Dear ImGui does NOT require C++11 so it can be used with most old C++ compilers. Dear ImGui doesn't use any C++ header file. Language-wise, function overloading and default parameters are used to make the API easier to use and code more terse. Doing so I believe the API is sitting on a sweet spot and giving up on those features would make the API more cumbersome. Other features such as namespace, constructors and templates (in the case of the ImVector<> class) are also relied on as a convenience. -There is an unofficial but reasonably maintained [c-api for ImGui](https://github.com/Extrawurst/cimgui) by Stephan Dilly. I would suggest using your target language functionality to try replicating the function overloading and default parameters used in C++ else the API may be harder to use. It was really designed with C++ in mind and may not make the same amount of sense with another language. Also see [Links](https://github.com/ocornut/imgui/wiki/Links) for third-party bindings to other languages. +There is an reasonably maintained [c-api for ImGui](https://github.com/Extrawurst/cimgui) by Stephan Dilly designed for binding in other languages. I would suggest using your target language functionalities to try replicating the function overloading and default parameters used in C++ else the API may be harder to use. Also see [Links](https://github.com/ocornut/imgui/wiki/Links) for third-party bindings to other languages. Support dear imgui ------------------ diff --git a/deps/cimgui/imgui/TODO.txt b/deps/cimgui/imgui/TODO.txt index 04e795fa..c305a411 100644 --- a/deps/cimgui/imgui/TODO.txt +++ b/deps/cimgui/imgui/TODO.txt @@ -7,6 +7,7 @@ It's mostly a bunch of personal notes, probably incomplete. Feel free to query i - doc/test: add a proper documentation+regression testing system (#435) - doc/test: checklist app to verify binding/integration of imgui (test inputs, rendering, callback, etc.). + - doc/tips: tips of the day: website? applet in imgui_club? - project: folder or separate repository with maintained helpers (e.g. imgui_memory_editor.h, imgui_stl.h, maybe imgui_dock would be there?) - window: calling SetNextWindowSize() every frame with <= 0 doesn't do anything, may be useful to allow (particularly when used for a single axis). (#690) @@ -20,7 +21,6 @@ It's mostly a bunch of personal notes, probably incomplete. Feel free to query i - window: a collapsed window can be stuck behind the main menu bar? - window: when window is very small, prioritize resize button over close button. - window: detect extra End() call that pop the "Debug" window out and assert at End() call site instead of at end of frame. - - window/tooltip: allow to set the width of a tooltip to allow TextWrapped() etc. while keeping the height automatic. - window: increase minimum size of a window with menus or fix the menu rendering so that it doesn't look odd. - window: double-clicking on title bar to minimize isn't consistent, perhaps move to single-click on left-most collapse icon? - window: expose contents size. (#1045) @@ -86,6 +86,7 @@ It's mostly a bunch of personal notes, probably incomplete. Feel free to query i - columns: optional sorting modifiers (up/down), sort list so sorting can be done multi-critera. notify user when sort order changed. - columns: option to alternate background colors on odd/even scanlines. - columns: allow columns to recurse. + - columns: allow a same columns set to be interrupted by e.g. CollapsingHeader and resume with columns in sync when moving them. - columns: separator function or parameter that works within the column (currently Separator() bypass all columns) (#125) - columns: flag to add horizontal separator above/below? - columns/layout: setup minimum line height (equivalent of automatically calling AlignFirstTextHeightToWidgets) @@ -152,7 +153,9 @@ It's mostly a bunch of personal notes, probably incomplete. Feel free to query i - popups: add variant using global identifier similar to Begin/End (#402) - popups: border options. richer api like BeginChild() perhaps? (#197) - tooltip: tooltip that doesn't fit in entire screen seems to lose their "last preferred direction" and may teleport when moving mouse. - + - tooltip: allow to set the width of a tooltip to allow TextWrapped() etc. while keeping the height automatic. + - tooltip: allow tooltips with timers? or general timer policy? (instaneous vs timed) + - menus: calling BeginMenu() twice with a same name doesn't append as Begin() does for regular windows (#1207) - statusbar: add a per-window status bar helper similar to what menubar does. - shortcuts: local-style shortcut api, e.g. parse "&Save" @@ -205,7 +208,8 @@ It's mostly a bunch of personal notes, probably incomplete. Feel free to query i - markup: simple markup language for color change? !- font: better CalcTextSizeA() API, at least for simple use cases. current one is horrible (perhaps have simple vs extended versions). - - font: enforce monospace through ImFontConfig (for icons?) + - font: better vertical centering (based e.g on height of lowercase 'x'?). currently Roboto-Medium size 16 px isn't currently centered. + - font: enforce monospace through ImFontConfig (for icons?) + create dual ImFont output from same input, reusing rasterized data but with different glyphs/AdvanceX - font: finish CustomRectRegister() to allow mapping unicode codepoint to custom texture data - font: PushFontSize API (#1018) - font/atlas: incremental updates @@ -236,6 +240,7 @@ It's mostly a bunch of personal notes, probably incomplete. Feel free to query i - misc: provide a way to compile out the entire implementation while providing a dummy API (e.g. #define IMGUI_DUMMY_IMPL) - misc: provide HoveredTime and ActivatedTime to ease the creation of animations. - misc: fix for compilation settings where stdcall isn't the default (e.g. vectorcall) (#1230) + - misc: detect user not calling Render() and suggest to call EndFrame()? - remote: make a system like RemoteImGui first-class citizen/project (#75) - demo: add vertical separator demo diff --git a/deps/cimgui/imgui/examples/README.txt b/deps/cimgui/imgui/examples/README.txt index 2769c1bf..35490b5b 100644 --- a/deps/cimgui/imgui/examples/README.txt +++ b/deps/cimgui/imgui/examples/README.txt @@ -8,15 +8,16 @@ Third party languages and frameworks bindings: https://github.com/ocornut/imgui/ TL;DR; - Newcomers, read 'PROGRAMMER GUIDE' in imgui.cpp for notes on how to setup ImGui in your codebase. - - To LEARN how the library is setup, you may refer to 'opengl2_example' because is the simplest one. - The other examples requires more boilerplate and are harder to read. - However, USE 'opengl3_example' in your application if you are using any modern OpenGL3+ calls. - Mixing old fixed pipeline OpenGL2 and programmable pipeline OpenGL3+ isn't well supported by some drivers. - If you are not sure, in doubt, use 'opengl3_example'. - If you are using of the backend provided here, so you can copy the imgui_impl_xxx.cpp/h files to your project and use them unmodified. - - If you have your own engine, you probably want to start from one of the OpenGL example and adapt it to - your engine, but you can read the other examples as well. + - To LEARN how the library is setup, you may refer to 'opengl2_example' because is the simplest one to read. + However, do NOT USE the 'opengl2_example' if your code is using any modern GL3+ calls. + Mixing old fixed-pipeline OpenGL2 and modern OpenGL3+ is going to make everything more complicated. + Read comments below for details. If you are not sure, in doubt, use 'opengl3_example'. + - If you have your own engine, you probably want to read a few of the examples first then adapt it to + your engine. Please note that if your engine is based on OpenGL/DirectX you can perfectly use the + existing rendering backends, don't feel forced to rewrite them with your own engine API, or you can + do that later when you already got things to work. ImGui is highly portable and only requires a few things to run: - Providing mouse/keyboard inputs @@ -45,12 +46,12 @@ Also note that some setup or GPU drivers may be causing extra lag (possibly by e leaving you with no option but sadness/anger (Intel GPU drivers were reported as such). opengl2_example/ + *DO NOT USE THIS CODE IF YOUR CODE/ENGINE IS USING MODERN OPENGL* GLFW + OpenGL example (old, fixed graphic pipeline). - This is only provided as a reference to learn how ImGui integration works, because it is easier to read. - However, if your code is using GL3+ context, using this may confuse your driver. Please use the GL3 example below. - (You might be able to use this code in a GL3/GL4 context but make sure you disable the programmable - pipeline by calling "glUseProgram(0)" before ImGui::Render. It appears that many librairies and drivers - are having issues mixing GL2 calls and newer GL3/GL4 calls. So it isn't recommended that you use that.) + This is mostly provided as a reference to learn how ImGui integration works, because it is easier to read. + If your code is using GL3+ context or any semi modern OpenGL calls, using this is likely to make everything + more complicated, will require your code to reset every single OpenGL attributes to their initial state, + and might confuse your GPU driver. Prefer using opengl3_example. opengl3_example/ GLFW + OpenGL example (programmable pipeline, binding modern functions with GL3W). @@ -74,7 +75,12 @@ apple_example/ Synergy keyboard integration is rather hacky. sdl_opengl2_example/ + *DO NOT USE THIS CODE IF YOUR CODE/ENGINE IS USING MODERN OPENGL* SDL2 + OpenGL example (old fixed pipeline). + This is mostly provided as a reference to learn how ImGui integration works, because it is easier to read. + If your code is using GL3+ context or any semi modern OpenGL calls, using this is likely to make everything + more complicated, will require your code to reset every single OpenGL attributes to their initial state, + and might confuse your GPU driver. Prefer using sdl_opengl3_example. sdl_opengl3_example/ SDL2 + OpenGL3 example. diff --git a/deps/cimgui/imgui/examples/allegro5_example/imgui_impl_a5.cpp b/deps/cimgui/imgui/examples/allegro5_example/imgui_impl_a5.cpp index 6f5b7b06..0d385923 100644 --- a/deps/cimgui/imgui/examples/allegro5_example/imgui_impl_a5.cpp +++ b/deps/cimgui/imgui/examples/allegro5_example/imgui_impl_a5.cpp @@ -204,6 +204,10 @@ void ImGui_ImplA5_Shutdown() ImGui::Shutdown(); } +// You can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if dear imgui wants to use your inputs. +// - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application. +// - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application. +// Generally you may always pass all inputs to dear imgui, and hide them from your application based on those two flags. bool ImGui_ImplA5_ProcessEvent(ALLEGRO_EVENT *ev) { ImGuiIO &io = ImGui::GetIO(); @@ -227,7 +231,6 @@ bool ImGui_ImplA5_ProcessEvent(ALLEGRO_EVENT *ev) return false; } - void ImGui_ImplA5_NewFrame() { if (!g_Texture) @@ -290,6 +293,6 @@ void ImGui_ImplA5_NewFrame() al_set_system_mouse_cursor(g_Display, cursor_id); } - // Start the frame + // Start the frame. This call will update the io.WantCaptureMouse, io.WantCaptureKeyboard flag that you can use to dispatch inputs (or not) to your application. ImGui::NewFrame(); } diff --git a/deps/cimgui/imgui/examples/allegro5_example/main.cpp b/deps/cimgui/imgui/examples/allegro5_example/main.cpp index cfff74ea..4eb9a4aa 100644 --- a/deps/cimgui/imgui/examples/allegro5_example/main.cpp +++ b/deps/cimgui/imgui/examples/allegro5_example/main.cpp @@ -26,14 +26,20 @@ int main(int, char**) ImGui_ImplA5_Init(display); // Load Fonts - // (there is a default font, this is only if you want to change it. see extra_fonts/README.txt for more details) + // - If no fonts are loaded, dear imgui will use the default font. You can also load multiple fonts and use ImGui::PushFont()/PopFont() to select them. + // - AddFontFromFileTTF() will return the ImFont* so you can store it if you need to select the font among multiple. + // - If the file cannot be loaded, the function will return NULL. Please handle those errors in your application (e.g. use an assertion, or display an error and quit). + // - The fonts will be rasterized at a given size (w/ oversampling) and stored into a texture when calling ImFontAtlas::Build()/GetTexDataAsXXXX(), which ImGui_ImplXXXX_NewFrame below will call. + // - Read 'extra_fonts/README.txt' for more instructions and details. + // - Remember that in C/C++ if you want to include a backslash \ in a string literal you need to write a double backslash \\ ! //ImGuiIO& io = ImGui::GetIO(); //io.Fonts->AddFontDefault(); + //io.Fonts->AddFontFromFileTTF("../../extra_fonts/Roboto-Medium.ttf", 16.0f); //io.Fonts->AddFontFromFileTTF("../../extra_fonts/Cousine-Regular.ttf", 15.0f); //io.Fonts->AddFontFromFileTTF("../../extra_fonts/DroidSans.ttf", 16.0f); - //io.Fonts->AddFontFromFileTTF("../../extra_fonts/Roboto-Medium.ttf", 16.0f); //io.Fonts->AddFontFromFileTTF("../../extra_fonts/ProggyTiny.ttf", 10.0f); - //io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\ArialUni.ttf", 18.0f, NULL, io.Fonts->GetGlyphRangesJapanese()); + //ImFont* font = io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\ArialUni.ttf", 18.0f, NULL, io.Fonts->GetGlyphRangesJapanese()); + //IM_ASSERT(font != NULL); bool show_test_window = true; bool show_another_window = false; @@ -43,11 +49,16 @@ int main(int, char**) bool running = true; while (running) { + // You can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if dear imgui wants to use your inputs. + // - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application. + // - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application. + // Generally you may always pass all inputs to dear imgui, and hide them from your application based on those two flags. ALLEGRO_EVENT ev; while (al_get_next_event(queue, &ev)) { ImGui_ImplA5_ProcessEvent(&ev); - if (ev.type == ALLEGRO_EVENT_DISPLAY_CLOSE) running = false; + if (ev.type == ALLEGRO_EVENT_DISPLAY_CLOSE) + running = false; if (ev.type == ALLEGRO_EVENT_DISPLAY_RESIZE) { ImGui_ImplA5_InvalidateDeviceObjects(); @@ -57,8 +68,8 @@ int main(int, char**) } ImGui_ImplA5_NewFrame(); - // 1. Show a simple window - // Tip: if we don't call ImGui::Begin()/ImGui::End() the widgets appears in a window automatically called "Debug" + // 1. Show a simple window. + // Tip: if we don't call ImGui::Begin()/ImGui::End() the widgets appears in a window automatically called "Debug". { static float f; ImGui::Text("Hello, world!"); @@ -69,7 +80,7 @@ int main(int, char**) ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f/ImGui::GetIO().Framerate, ImGui::GetIO().Framerate); } - // 2. Show another simple window, this time using an explicit Begin/End pair + // 2. Show another simple window. In most cases you will use an explicit Begin/End pair to name the window. if (show_another_window) { ImGui::Begin("Another Window", &show_another_window); @@ -77,7 +88,7 @@ int main(int, char**) ImGui::End(); } - // 3. Show the ImGui test window. Most of the sample code is in ImGui::ShowTestWindow() + // 3. Show the ImGui test window. Most of the sample code is in ImGui::ShowTestWindow(). if (show_test_window) { ImGui::SetNextWindowPos(ImVec2(650, 20), ImGuiCond_FirstUseEver); diff --git a/deps/cimgui/imgui/examples/directx10_example/imgui_impl_dx10.cpp b/deps/cimgui/imgui/examples/directx10_example/imgui_impl_dx10.cpp index f85edf9b..4670f053 100644 --- a/deps/cimgui/imgui/examples/directx10_example/imgui_impl_dx10.cpp +++ b/deps/cimgui/imgui/examples/directx10_example/imgui_impl_dx10.cpp @@ -225,49 +225,74 @@ void ImGui_ImplDX10_RenderDrawLists(ImDrawData* draw_data) ctx->IASetInputLayout(old.InputLayout); if (old.InputLayout) old.InputLayout->Release(); } -IMGUI_API LRESULT ImGui_ImplDX10_WndProcHandler(HWND, UINT msg, WPARAM wParam, LPARAM lParam) +static bool IsAnyMouseButtonDown() +{ + ImGuiIO& io = ImGui::GetIO(); + for (int n = 0; n < ARRAYSIZE(io.MouseDown); n++) + if (io.MouseDown[n]) + return true; + return false; +} + +// Process Win32 mouse/keyboard inputs. +// You can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if dear imgui wants to use your inputs. +// - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application. +// - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application. +// Generally you may always pass all inputs to dear imgui, and hide them from your application based on those two flags. +// PS: In this Win32 handler, we use the capture API (GetCapture/SetCapture/ReleaseCapture) to be able to read mouse coordinations when dragging mouse outside of our window bounds. +IMGUI_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { ImGuiIO& io = ImGui::GetIO(); switch (msg) { case WM_LBUTTONDOWN: - io.MouseDown[0] = true; - return true; - case WM_LBUTTONUP: - io.MouseDown[0] = false; - return true; case WM_RBUTTONDOWN: - io.MouseDown[1] = true; - return true; - case WM_RBUTTONUP: - io.MouseDown[1] = false; - return true; case WM_MBUTTONDOWN: - io.MouseDown[2] = true; - return true; + { + int button = 0; + if (msg == WM_LBUTTONDOWN) button = 0; + if (msg == WM_RBUTTONDOWN) button = 1; + if (msg == WM_MBUTTONDOWN) button = 2; + if (!IsAnyMouseButtonDown() && GetCapture() == NULL) + SetCapture(hwnd); + io.MouseDown[button] = true; + return 0; + } + case WM_LBUTTONUP: + case WM_RBUTTONUP: case WM_MBUTTONUP: - io.MouseDown[2] = false; - return true; + { + int button = 0; + if (msg == WM_LBUTTONUP) button = 0; + if (msg == WM_RBUTTONUP) button = 1; + if (msg == WM_MBUTTONUP) button = 2; + io.MouseDown[button] = false; + if (!IsAnyMouseButtonDown() && GetCapture() == hwnd) + ReleaseCapture(); + return 0; + } case WM_MOUSEWHEEL: io.MouseWheel += GET_WHEEL_DELTA_WPARAM(wParam) > 0 ? +1.0f : -1.0f; - return true; + return 0; case WM_MOUSEMOVE: io.MousePos.x = (signed short)(lParam); io.MousePos.y = (signed short)(lParam >> 16); - return true; + return 0; case WM_KEYDOWN: + case WM_SYSKEYDOWN: if (wParam < 256) io.KeysDown[wParam] = 1; - return true; + return 0; case WM_KEYUP: + case WM_SYSKEYUP: if (wParam < 256) io.KeysDown[wParam] = 0; - return true; + return 0; case WM_CHAR: // You can also use ToAscii()+GetKeyboardState() to retrieve characters. if (wParam > 0 && wParam < 0x10000) io.AddInputCharacter((unsigned short)wParam); - return true; + return 0; } return 0; } @@ -584,6 +609,6 @@ void ImGui_ImplDX10_NewFrame() if (io.MouseDrawCursor) SetCursor(NULL); - // Start the frame + // Start the frame. This call will update the io.WantCaptureMouse, io.WantCaptureKeyboard flag that you can use to dispatch inputs (or not) to your application. ImGui::NewFrame(); } diff --git a/deps/cimgui/imgui/examples/directx10_example/main.cpp b/deps/cimgui/imgui/examples/directx10_example/main.cpp index 4675a21d..3ece69f9 100644 --- a/deps/cimgui/imgui/examples/directx10_example/main.cpp +++ b/deps/cimgui/imgui/examples/directx10_example/main.cpp @@ -74,10 +74,10 @@ void CleanupDeviceD3D() if (g_pd3dDevice) { g_pd3dDevice->Release(); g_pd3dDevice = NULL; } } -extern LRESULT ImGui_ImplDX10_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); +extern LRESULT ImGui_ImplWin32_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); LRESULT WINAPI WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) { - if (ImGui_ImplDX10_WndProcHandler(hWnd, msg, wParam, lParam)) + if (ImGui_ImplWin32_WndProcHandler(hWnd, msg, wParam, lParam)) return true; switch (msg) @@ -126,14 +126,20 @@ int main(int, char**) ImGui_ImplDX10_Init(hwnd, g_pd3dDevice); // Load Fonts - // (there is a default font, this is only if you want to change it. see extra_fonts/README.txt for more details) + // - If no fonts are loaded, dear imgui will use the default font. You can also load multiple fonts and use ImGui::PushFont()/PopFont() to select them. + // - AddFontFromFileTTF() will return the ImFont* so you can store it if you need to select the font among multiple. + // - If the file cannot be loaded, the function will return NULL. Please handle those errors in your application (e.g. use an assertion, or display an error and quit). + // - The fonts will be rasterized at a given size (w/ oversampling) and stored into a texture when calling ImFontAtlas::Build()/GetTexDataAsXXXX(), which ImGui_ImplXXXX_NewFrame below will call. + // - Read 'extra_fonts/README.txt' for more instructions and details. + // - Remember that in C/C++ if you want to include a backslash \ in a string literal you need to write a double backslash \\ ! //ImGuiIO& io = ImGui::GetIO(); //io.Fonts->AddFontDefault(); + //io.Fonts->AddFontFromFileTTF("../../extra_fonts/Roboto-Medium.ttf", 16.0f); //io.Fonts->AddFontFromFileTTF("../../extra_fonts/Cousine-Regular.ttf", 15.0f); //io.Fonts->AddFontFromFileTTF("../../extra_fonts/DroidSans.ttf", 16.0f); - //io.Fonts->AddFontFromFileTTF("../../extra_fonts/Roboto-Medium.ttf", 16.0f); //io.Fonts->AddFontFromFileTTF("../../extra_fonts/ProggyTiny.ttf", 10.0f); - //io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\ArialUni.ttf", 18.0f, NULL, io.Fonts->GetGlyphRangesJapanese()); + //ImFont* font = io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\ArialUni.ttf", 18.0f, NULL, io.Fonts->GetGlyphRangesJapanese()); + //IM_ASSERT(font != NULL); bool show_test_window = true; bool show_another_window = false; @@ -144,6 +150,10 @@ int main(int, char**) ZeroMemory(&msg, sizeof(msg)); while (msg.message != WM_QUIT) { + // You can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if dear imgui wants to use your inputs. + // - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application. + // - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application. + // Generally you may always pass all inputs to dear imgui, and hide them from your application based on those two flags. if (PeekMessage(&msg, NULL, 0U, 0U, PM_REMOVE)) { TranslateMessage(&msg); @@ -152,8 +162,8 @@ int main(int, char**) } ImGui_ImplDX10_NewFrame(); - // 1. Show a simple window - // Tip: if we don't call ImGui::Begin()/ImGui::End() the widgets appears in a window automatically called "Debug" + // 1. Show a simple window. + // Tip: if we don't call ImGui::Begin()/ImGui::End() the widgets appears in a window automatically called "Debug". { static float f = 0.0f; ImGui::Text("Hello, world!"); @@ -164,7 +174,7 @@ int main(int, char**) ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate); } - // 2. Show another simple window, this time using an explicit Begin/End pair + // 2. Show another simple window. In most cases you will use an explicit Begin/End pair to name the window. if (show_another_window) { ImGui::Begin("Another Window", &show_another_window); @@ -172,7 +182,7 @@ int main(int, char**) ImGui::End(); } - // 3. Show the ImGui test window. Most of the sample code is in ImGui::ShowTestWindow() + // 3. Show the ImGui test window. Most of the sample code is in ImGui::ShowTestWindow(). if (show_test_window) { ImGui::SetNextWindowPos(ImVec2(650, 20), ImGuiCond_FirstUseEver); // Normally user code doesn't need/want to call it because positions are saved in .ini file anyway. Here we just want to make the demo initial state a bit more friendly! diff --git a/deps/cimgui/imgui/examples/directx11_example/imgui_impl_dx11.cpp b/deps/cimgui/imgui/examples/directx11_example/imgui_impl_dx11.cpp index 49a4aa48..df02577b 100644 --- a/deps/cimgui/imgui/examples/directx11_example/imgui_impl_dx11.cpp +++ b/deps/cimgui/imgui/examples/directx11_example/imgui_impl_dx11.cpp @@ -232,49 +232,74 @@ void ImGui_ImplDX11_RenderDrawLists(ImDrawData* draw_data) ctx->IASetInputLayout(old.InputLayout); if (old.InputLayout) old.InputLayout->Release(); } -IMGUI_API LRESULT ImGui_ImplDX11_WndProcHandler(HWND, UINT msg, WPARAM wParam, LPARAM lParam) +static bool IsAnyMouseButtonDown() +{ + ImGuiIO& io = ImGui::GetIO(); + for (int n = 0; n < ARRAYSIZE(io.MouseDown); n++) + if (io.MouseDown[n]) + return true; + return false; +} + +// Process Win32 mouse/keyboard inputs. +// You can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if dear imgui wants to use your inputs. +// - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application. +// - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application. +// Generally you may always pass all inputs to dear imgui, and hide them from your application based on those two flags. +// PS: In this Win32 handler, we use the capture API (GetCapture/SetCapture/ReleaseCapture) to be able to read mouse coordinations when dragging mouse outside of our window bounds. +IMGUI_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { ImGuiIO& io = ImGui::GetIO(); switch (msg) { case WM_LBUTTONDOWN: - io.MouseDown[0] = true; - return true; - case WM_LBUTTONUP: - io.MouseDown[0] = false; - return true; case WM_RBUTTONDOWN: - io.MouseDown[1] = true; - return true; - case WM_RBUTTONUP: - io.MouseDown[1] = false; - return true; case WM_MBUTTONDOWN: - io.MouseDown[2] = true; - return true; + { + int button = 0; + if (msg == WM_LBUTTONDOWN) button = 0; + if (msg == WM_RBUTTONDOWN) button = 1; + if (msg == WM_MBUTTONDOWN) button = 2; + if (!IsAnyMouseButtonDown() && GetCapture() == NULL) + SetCapture(hwnd); + io.MouseDown[button] = true; + return 0; + } + case WM_LBUTTONUP: + case WM_RBUTTONUP: case WM_MBUTTONUP: - io.MouseDown[2] = false; - return true; + { + int button = 0; + if (msg == WM_LBUTTONUP) button = 0; + if (msg == WM_RBUTTONUP) button = 1; + if (msg == WM_MBUTTONUP) button = 2; + io.MouseDown[button] = false; + if (!IsAnyMouseButtonDown() && GetCapture() == hwnd) + ReleaseCapture(); + return 0; + } case WM_MOUSEWHEEL: io.MouseWheel += GET_WHEEL_DELTA_WPARAM(wParam) > 0 ? +1.0f : -1.0f; - return true; + return 0; case WM_MOUSEMOVE: io.MousePos.x = (signed short)(lParam); io.MousePos.y = (signed short)(lParam >> 16); - return true; + return 0; case WM_KEYDOWN: + case WM_SYSKEYDOWN: if (wParam < 256) io.KeysDown[wParam] = 1; - return true; + return 0; case WM_KEYUP: + case WM_SYSKEYUP: if (wParam < 256) io.KeysDown[wParam] = 0; - return true; + return 0; case WM_CHAR: // You can also use ToAscii()+GetKeyboardState() to retrieve characters. if (wParam > 0 && wParam < 0x10000) io.AddInputCharacter((unsigned short)wParam); - return true; + return 0; } return 0; } @@ -587,6 +612,6 @@ void ImGui_ImplDX11_NewFrame() if (io.MouseDrawCursor) SetCursor(NULL); - // Start the frame + // Start the frame. This call will update the io.WantCaptureMouse, io.WantCaptureKeyboard flag that you can use to dispatch inputs (or not) to your application. ImGui::NewFrame(); } diff --git a/deps/cimgui/imgui/examples/directx11_example/main.cpp b/deps/cimgui/imgui/examples/directx11_example/main.cpp index 04321610..9bd8637c 100644 --- a/deps/cimgui/imgui/examples/directx11_example/main.cpp +++ b/deps/cimgui/imgui/examples/directx11_example/main.cpp @@ -77,10 +77,10 @@ void CleanupDeviceD3D() if (g_pd3dDevice) { g_pd3dDevice->Release(); g_pd3dDevice = NULL; } } -extern LRESULT ImGui_ImplDX11_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); +extern LRESULT ImGui_ImplWin32_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); LRESULT WINAPI WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) { - if (ImGui_ImplDX11_WndProcHandler(hWnd, msg, wParam, lParam)) + if (ImGui_ImplWin32_WndProcHandler(hWnd, msg, wParam, lParam)) return true; switch (msg) @@ -129,14 +129,20 @@ int main(int, char**) ImGui_ImplDX11_Init(hwnd, g_pd3dDevice, g_pd3dDeviceContext); // Load Fonts - // (there is a default font, this is only if you want to change it. see extra_fonts/README.txt for more details) + // - If no fonts are loaded, dear imgui will use the default font. You can also load multiple fonts and use ImGui::PushFont()/PopFont() to select them. + // - AddFontFromFileTTF() will return the ImFont* so you can store it if you need to select the font among multiple. + // - If the file cannot be loaded, the function will return NULL. Please handle those errors in your application (e.g. use an assertion, or display an error and quit). + // - The fonts will be rasterized at a given size (w/ oversampling) and stored into a texture when calling ImFontAtlas::Build()/GetTexDataAsXXXX(), which ImGui_ImplXXXX_NewFrame below will call. + // - Read 'extra_fonts/README.txt' for more instructions and details. + // - Remember that in C/C++ if you want to include a backslash \ in a string literal you need to write a double backslash \\ ! //ImGuiIO& io = ImGui::GetIO(); //io.Fonts->AddFontDefault(); + //io.Fonts->AddFontFromFileTTF("../../extra_fonts/Roboto-Medium.ttf", 16.0f); //io.Fonts->AddFontFromFileTTF("../../extra_fonts/Cousine-Regular.ttf", 15.0f); //io.Fonts->AddFontFromFileTTF("../../extra_fonts/DroidSans.ttf", 16.0f); - //io.Fonts->AddFontFromFileTTF("../../extra_fonts/Roboto-Medium.ttf", 16.0f); //io.Fonts->AddFontFromFileTTF("../../extra_fonts/ProggyTiny.ttf", 10.0f); - //io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\ArialUni.ttf", 18.0f, NULL, io.Fonts->GetGlyphRangesJapanese()); + //ImFont* font = io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\ArialUni.ttf", 18.0f, NULL, io.Fonts->GetGlyphRangesJapanese()); + //IM_ASSERT(font != NULL); bool show_test_window = true; bool show_another_window = false; @@ -147,6 +153,10 @@ int main(int, char**) ZeroMemory(&msg, sizeof(msg)); while (msg.message != WM_QUIT) { + // You can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if dear imgui wants to use your inputs. + // - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application. + // - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application. + // Generally you may always pass all inputs to dear imgui, and hide them from your application based on those two flags. if (PeekMessage(&msg, NULL, 0U, 0U, PM_REMOVE)) { TranslateMessage(&msg); @@ -155,8 +165,8 @@ int main(int, char**) } ImGui_ImplDX11_NewFrame(); - // 1. Show a simple window - // Tip: if we don't call ImGui::Begin()/ImGui::End() the widgets appears in a window automatically called "Debug" + // 1. Show a simple window. + // Tip: if we don't call ImGui::Begin()/ImGui::End() the widgets appears in a window automatically called "Debug". { static float f = 0.0f; ImGui::Text("Hello, world!"); @@ -167,7 +177,7 @@ int main(int, char**) ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate); } - // 2. Show another simple window, this time using an explicit Begin/End pair + // 2. Show another simple window. In most cases you will use an explicit Begin/End pair to name the window. if (show_another_window) { ImGui::Begin("Another Window", &show_another_window); @@ -175,7 +185,7 @@ int main(int, char**) ImGui::End(); } - // 3. Show the ImGui test window. Most of the sample code is in ImGui::ShowTestWindow() + // 3. Show the ImGui test window. Most of the sample code is in ImGui::ShowTestWindow(). if (show_test_window) { ImGui::SetNextWindowPos(ImVec2(650, 20), ImGuiCond_FirstUseEver); // Normally user code doesn't need/want to call it because positions are saved in .ini file anyway. Here we just want to make the demo initial state a bit more friendly! diff --git a/deps/cimgui/imgui/examples/directx9_example/imgui_impl_dx9.cpp b/deps/cimgui/imgui/examples/directx9_example/imgui_impl_dx9.cpp index 49012012..24f53ba3 100644 --- a/deps/cimgui/imgui/examples/directx9_example/imgui_impl_dx9.cpp +++ b/deps/cimgui/imgui/examples/directx9_example/imgui_impl_dx9.cpp @@ -171,49 +171,74 @@ void ImGui_ImplDX9_RenderDrawLists(ImDrawData* draw_data) d3d9_state_block->Release(); } -IMGUI_API LRESULT ImGui_ImplDX9_WndProcHandler(HWND, UINT msg, WPARAM wParam, LPARAM lParam) +static bool IsAnyMouseButtonDown() +{ + ImGuiIO& io = ImGui::GetIO(); + for (int n = 0; n < ARRAYSIZE(io.MouseDown); n++) + if (io.MouseDown[n]) + return true; + return false; +} + +// Process Win32 mouse/keyboard inputs. +// You can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if dear imgui wants to use your inputs. +// - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application. +// - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application. +// Generally you may always pass all inputs to dear imgui, and hide them from your application based on those two flags. +// PS: In this Win32 handler, we use the capture API (GetCapture/SetCapture/ReleaseCapture) to be able to read mouse coordinations when dragging mouse outside of our window bounds. +IMGUI_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { ImGuiIO& io = ImGui::GetIO(); switch (msg) { case WM_LBUTTONDOWN: - io.MouseDown[0] = true; - return true; - case WM_LBUTTONUP: - io.MouseDown[0] = false; - return true; case WM_RBUTTONDOWN: - io.MouseDown[1] = true; - return true; - case WM_RBUTTONUP: - io.MouseDown[1] = false; - return true; case WM_MBUTTONDOWN: - io.MouseDown[2] = true; - return true; + { + int button = 0; + if (msg == WM_LBUTTONDOWN) button = 0; + if (msg == WM_RBUTTONDOWN) button = 1; + if (msg == WM_MBUTTONDOWN) button = 2; + if (!IsAnyMouseButtonDown() && GetCapture() == NULL) + SetCapture(hwnd); + io.MouseDown[button] = true; + return 0; + } + case WM_LBUTTONUP: + case WM_RBUTTONUP: case WM_MBUTTONUP: - io.MouseDown[2] = false; - return true; + { + int button = 0; + if (msg == WM_LBUTTONUP) button = 0; + if (msg == WM_RBUTTONUP) button = 1; + if (msg == WM_MBUTTONUP) button = 2; + io.MouseDown[button] = false; + if (!IsAnyMouseButtonDown() && GetCapture() == hwnd) + ReleaseCapture(); + return 0; + } case WM_MOUSEWHEEL: io.MouseWheel += GET_WHEEL_DELTA_WPARAM(wParam) > 0 ? +1.0f : -1.0f; - return true; + return 0; case WM_MOUSEMOVE: io.MousePos.x = (signed short)(lParam); io.MousePos.y = (signed short)(lParam >> 16); - return true; + return 0; case WM_KEYDOWN: + case WM_SYSKEYDOWN: if (wParam < 256) io.KeysDown[wParam] = 1; - return true; + return 0; case WM_KEYUP: + case WM_SYSKEYUP: if (wParam < 256) io.KeysDown[wParam] = 0; - return true; + return 0; case WM_CHAR: // You can also use ToAscii()+GetKeyboardState() to retrieve characters. if (wParam > 0 && wParam < 0x10000) io.AddInputCharacter((unsigned short)wParam); - return true; + return 0; } return 0; } @@ -361,6 +386,6 @@ void ImGui_ImplDX9_NewFrame() if (io.MouseDrawCursor) SetCursor(NULL); - // Start the frame + // Start the frame. This call will update the io.WantCaptureMouse, io.WantCaptureKeyboard flag that you can use to dispatch inputs (or not) to your application. ImGui::NewFrame(); } diff --git a/deps/cimgui/imgui/examples/directx9_example/main.cpp b/deps/cimgui/imgui/examples/directx9_example/main.cpp index b8e5907c..5a5c0d19 100644 --- a/deps/cimgui/imgui/examples/directx9_example/main.cpp +++ b/deps/cimgui/imgui/examples/directx9_example/main.cpp @@ -12,10 +12,10 @@ static LPDIRECT3DDEVICE9 g_pd3dDevice = NULL; static D3DPRESENT_PARAMETERS g_d3dpp; -extern LRESULT ImGui_ImplDX9_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); +extern LRESULT ImGui_ImplWin32_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); LRESULT WINAPI WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) { - if (ImGui_ImplDX9_WndProcHandler(hWnd, msg, wParam, lParam)) + if (ImGui_ImplWin32_WndProcHandler(hWnd, msg, wParam, lParam)) return true; switch (msg) @@ -78,14 +78,20 @@ int main(int, char**) ImGui_ImplDX9_Init(hwnd, g_pd3dDevice); // Load Fonts - // (there is a default font, this is only if you want to change it. see extra_fonts/README.txt for more details) + // - If no fonts are loaded, dear imgui will use the default font. You can also load multiple fonts and use ImGui::PushFont()/PopFont() to select them. + // - AddFontFromFileTTF() will return the ImFont* so you can store it if you need to select the font among multiple. + // - If the file cannot be loaded, the function will return NULL. Please handle those errors in your application (e.g. use an assertion, or display an error and quit). + // - The fonts will be rasterized at a given size (w/ oversampling) and stored into a texture when calling ImFontAtlas::Build()/GetTexDataAsXXXX(), which ImGui_ImplXXXX_NewFrame below will call. + // - Read 'extra_fonts/README.txt' for more instructions and details. + // - Remember that in C/C++ if you want to include a backslash \ in a string literal you need to write a double backslash \\ ! //ImGuiIO& io = ImGui::GetIO(); //io.Fonts->AddFontDefault(); + //io.Fonts->AddFontFromFileTTF("../../extra_fonts/Roboto-Medium.ttf", 16.0f); //io.Fonts->AddFontFromFileTTF("../../extra_fonts/Cousine-Regular.ttf", 15.0f); //io.Fonts->AddFontFromFileTTF("../../extra_fonts/DroidSans.ttf", 16.0f); - //io.Fonts->AddFontFromFileTTF("../../extra_fonts/Roboto-Medium.ttf", 16.0f); //io.Fonts->AddFontFromFileTTF("../../extra_fonts/ProggyTiny.ttf", 10.0f); - //io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\ArialUni.ttf", 18.0f, NULL, io.Fonts->GetGlyphRangesJapanese()); + //ImFont* font = io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\ArialUni.ttf", 18.0f, NULL, io.Fonts->GetGlyphRangesJapanese()); + //IM_ASSERT(font != NULL); bool show_test_window = true; bool show_another_window = false; @@ -98,6 +104,10 @@ int main(int, char**) UpdateWindow(hwnd); while (msg.message != WM_QUIT) { + // You can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if dear imgui wants to use your inputs. + // - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application. + // - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application. + // Generally you may always pass all inputs to dear imgui, and hide them from your application based on those two flags. if (PeekMessage(&msg, NULL, 0U, 0U, PM_REMOVE)) { TranslateMessage(&msg); @@ -106,8 +116,8 @@ int main(int, char**) } ImGui_ImplDX9_NewFrame(); - // 1. Show a simple window - // Tip: if we don't call ImGui::Begin()/ImGui::End() the widgets appears in a window automatically called "Debug" + // 1. Show a simple window. + // Tip: if we don't call ImGui::Begin()/ImGui::End() the widgets appears in a window automatically called "Debug". { static float f = 0.0f; ImGui::Text("Hello, world!"); @@ -118,7 +128,7 @@ int main(int, char**) ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate); } - // 2. Show another simple window, this time using an explicit Begin/End pair + // 2. Show another simple window. In most cases you will use an explicit Begin/End pair to name the window. if (show_another_window) { ImGui::Begin("Another Window", &show_another_window); @@ -126,7 +136,7 @@ int main(int, char**) ImGui::End(); } - // 3. Show the ImGui test window. Most of the sample code is in ImGui::ShowTestWindow() + // 3. Show the ImGui test window. Most of the sample code is in ImGui::ShowTestWindow(). if (show_test_window) { ImGui::SetNextWindowPos(ImVec2(650, 20), ImGuiCond_FirstUseEver); diff --git a/deps/cimgui/imgui/examples/libs/glfw/lib-vc2010-32/glfw3.lib b/deps/cimgui/imgui/examples/libs/glfw/lib-vc2010-32/glfw3.lib new file mode 100644 index 00000000..348abecf Binary files /dev/null and b/deps/cimgui/imgui/examples/libs/glfw/lib-vc2010-32/glfw3.lib differ diff --git a/deps/cimgui/imgui/examples/libs/glfw/lib-vc2010-64/glfw3.lib b/deps/cimgui/imgui/examples/libs/glfw/lib-vc2010-64/glfw3.lib new file mode 100644 index 00000000..768f3083 Binary files /dev/null and b/deps/cimgui/imgui/examples/libs/glfw/lib-vc2010-64/glfw3.lib differ diff --git a/deps/cimgui/imgui/examples/marmalade_example/imgui_impl_marmalade.cpp b/deps/cimgui/imgui/examples/marmalade_example/imgui_impl_marmalade.cpp index ae7f10c0..6ecffa73 100644 --- a/deps/cimgui/imgui/examples/marmalade_example/imgui_impl_marmalade.cpp +++ b/deps/cimgui/imgui/examples/marmalade_example/imgui_impl_marmalade.cpp @@ -27,7 +27,7 @@ static char* g_ClipboardText = NULL; static bool g_osdKeyboardEnabled = false; // use this setting to scale the interface - e.g. on device you could use 2 or 3 scale factor -static ImVec2 g_scale = ImVec2(1.0f,1.0f); +static ImVec2 g_RenderScale = ImVec2(1.0f,1.0f); // This is the main rendering function that you have to implement and provide to ImGui (via setting up 'RenderDrawListsFn' in the ImGuiIO structure) void ImGui_Marmalade_RenderDrawLists(ImDrawData* draw_data) @@ -48,9 +48,9 @@ void ImGui_Marmalade_RenderDrawLists(ImDrawData* draw_data) for( int i=0; i < nVert; i++ ) { - // TODO: optimize multiplication on gpu using vertex shader - pVertStream[i].x = cmd_list->VtxBuffer[i].pos.x * g_scale.x; - pVertStream[i].y = cmd_list->VtxBuffer[i].pos.y * g_scale.y; + // TODO: optimize multiplication on gpu using vertex shader/projection matrix. + pVertStream[i].x = cmd_list->VtxBuffer[i].pos.x * g_RenderScale.x; + pVertStream[i].y = cmd_list->VtxBuffer[i].pos.y * g_RenderScale.y; pUVStream[i].x = cmd_list->VtxBuffer[i].uv.x; pUVStream[i].y = cmd_list->VtxBuffer[i].uv.y; pColStream[i] = cmd_list->VtxBuffer[i].col; @@ -287,7 +287,7 @@ void ImGui_Marmalade_NewFrame() // TODO: Hide OS mouse cursor if ImGui is drawing it // s3ePointerSetInt(S3E_POINTER_HIDE_CURSOR,(io.MouseDrawCursor ? 0 : 1)); - // Start the frame + // Start the frame. This call will update the io.WantCaptureMouse, io.WantCaptureKeyboard flag that you can use to dispatch inputs (or not) to your application. ImGui::NewFrame(); // Show/hide OSD keyboard diff --git a/deps/cimgui/imgui/examples/marmalade_example/main.cpp b/deps/cimgui/imgui/examples/marmalade_example/main.cpp index eb0938ab..f87b3bc5 100644 --- a/deps/cimgui/imgui/examples/marmalade_example/main.cpp +++ b/deps/cimgui/imgui/examples/marmalade_example/main.cpp @@ -18,14 +18,20 @@ int main(int, char**) ImGui_Marmalade_Init(true); // Load Fonts - // (there is a default font, this is only if you want to change it. see extra_fonts/README.txt for more details) + // - If no fonts are loaded, dear imgui will use the default font. You can also load multiple fonts and use ImGui::PushFont()/PopFont() to select them. + // - AddFontFromFileTTF() will return the ImFont* so you can store it if you need to select the font among multiple. + // - If the file cannot be loaded, the function will return NULL. Please handle those errors in your application (e.g. use an assertion, or display an error and quit). + // - The fonts will be rasterized at a given size (w/ oversampling) and stored into a texture when calling ImFontAtlas::Build()/GetTexDataAsXXXX(), which ImGui_ImplXXXX_NewFrame below will call. + // - Read 'extra_fonts/README.txt' for more instructions and details. + // - Remember that in C/C++ if you want to include a backslash \ in a string literal you need to write a double backslash \\ ! //ImGuiIO& io = ImGui::GetIO(); //io.Fonts->AddFontDefault(); + //io.Fonts->AddFontFromFileTTF("../../extra_fonts/Roboto-Medium.ttf", 16.0f); //io.Fonts->AddFontFromFileTTF("../../extra_fonts/Cousine-Regular.ttf", 15.0f); //io.Fonts->AddFontFromFileTTF("../../extra_fonts/DroidSans.ttf", 16.0f); - //io.Fonts->AddFontFromFileTTF("../../extra_fonts/Roboto-Medium.ttf", 16.0f); //io.Fonts->AddFontFromFileTTF("../../extra_fonts/ProggyTiny.ttf", 10.0f); - //io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\ArialUni.ttf", 18.0f, NULL, io.Fonts->GetGlyphRangesJapanese()); + //ImFont* font = io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\ArialUni.ttf", 18.0f, NULL, io.Fonts->GetGlyphRangesJapanese()); + //IM_ASSERT(font != NULL); bool show_test_window = true; bool show_another_window = false; @@ -37,12 +43,16 @@ int main(int, char**) if (s3eDeviceCheckQuitRequest()) break; + // You can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if dear imgui wants to use your inputs. + // - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application. + // - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application. + // Generally you may always pass all inputs to dear imgui, and hide them from your application based on those two flags. s3eKeyboardUpdate(); s3ePointerUpdate(); ImGui_Marmalade_NewFrame(); - // 1. Show a simple window - // Tip: if we don't call ImGui::Begin()/ImGui::End() the widgets appears in a window automatically called "Debug" + // 1. Show a simple window. + // Tip: if we don't call ImGui::Begin()/ImGui::End() the widgets appears in a window automatically called "Debug". { static float f = 0.0f; ImGui::Text("Hello, world!"); @@ -53,7 +63,7 @@ int main(int, char**) ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate); } - // 2. Show another simple window, this time using an explicit Begin/End pair + // 2. Show another simple window. In most cases you will use an explicit Begin/End pair to name the window. if (show_another_window) { ImGui::Begin("Another Window", &show_another_window); @@ -61,7 +71,7 @@ int main(int, char**) ImGui::End(); } - // 3. Show the ImGui test window. Most of the sample code is in ImGui::ShowTestWindow() + // 3. Show the ImGui test window. Most of the sample code is in ImGui::ShowTestWindow(). if (show_test_window) { ImGui::SetNextWindowPos(ImVec2(650, 20), ImGuiCond_FirstUseEver); diff --git a/deps/cimgui/imgui/examples/opengl2_example/imgui_impl_glfw.cpp b/deps/cimgui/imgui/examples/opengl2_example/imgui_impl_glfw.cpp index 236a2d10..52962c19 100644 --- a/deps/cimgui/imgui/examples/opengl2_example/imgui_impl_glfw.cpp +++ b/deps/cimgui/imgui/examples/opengl2_example/imgui_impl_glfw.cpp @@ -1,10 +1,13 @@ // ImGui GLFW binding with OpenGL // In this binding, ImTextureID is used to store an OpenGL 'GLuint' texture identifier. Read the FAQ about ImTextureID in imgui.cpp. +// (GLFW is a cross-platform general purpose library for handling windows, inputs, OpenGL/Vulkan graphics context creation, etc.) -// If your context or own usage of OpenGL involve anything GL3/GL4, prefer using the code in opengl3_example. -// If you are not sure what that means, prefer using the code in opengl3_example. -// You *might* use this code with a GL3/GL4 context but make sure you disable the programmable pipeline by calling "glUseProgram(0)" before ImGui::Render(). -// We cannot do that from GL2 code because the function doesn't exist. Mixing GL2 calls and GL3/GL4 calls is giving trouble to many librairies/drivers. +// *DO NOT USE THIS CODE IF YOUR CODE/ENGINE IS USING MODERN OPENGL* +// This is mostly provided as a reference to learn how ImGui integration works, because it is easier to read. +// If your code is using GL3+ context or any semi modern OpenGL calls, using this is likely to make everything +// more complicated, will require your code to reset every single OpenGL attributes to their initial state, +// and might confuse your GPU driver. Prefer using opengl3_example. +// The GL2 code is unable to reset attributes or even call e.g. "glUseProgram(0)" because they don't exist in that API. // You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this. // If you use this binding you'll need to call 4 functions: ImGui_ImplXXXX_Init(), ImGui_ImplXXXX_NewFrame(), ImGui::Render() and ImGui_ImplXXXX_Shutdown(). @@ -26,7 +29,7 @@ // Data static GLFWwindow* g_Window = NULL; static double g_Time = 0.0f; -static bool g_MousePressed[3] = { false, false, false }; +static bool g_MouseJustPressed[3] = { false, false, false }; static float g_MouseWheel = 0.0f; static GLuint g_FontTexture = 0; @@ -129,12 +132,12 @@ static void ImGui_ImplGlfwGL2_SetClipboardText(void* user_data, const char* text void ImGui_ImplGlfwGL2_MouseButtonCallback(GLFWwindow*, int button, int action, int /*mods*/) { if (action == GLFW_PRESS && button >= 0 && button < 3) - g_MousePressed[button] = true; + g_MouseJustPressed[button] = true; } void ImGui_ImplGlfwGL2_ScrollCallback(GLFWwindow*, double /*xoffset*/, double yoffset) { - g_MouseWheel += (float)yoffset; // Use fractional mouse wheel, 1.0 unit 5 lines. + g_MouseWheel += (float)yoffset; // Use fractional mouse wheel. } void ImGui_ImplGlfwGL2_KeyCallback(GLFWwindow*, int key, int, int action, int mods) @@ -287,8 +290,9 @@ void ImGui_ImplGlfwGL2_NewFrame() for (int i = 0; i < 3; i++) { - io.MouseDown[i] = g_MousePressed[i] || glfwGetMouseButton(g_Window, i) != 0; // If a mouse press event came, always pass it as "mouse held this frame", so we don't miss click-release events that are shorter than 1 frame. - g_MousePressed[i] = false; + // If a mouse press event came, always pass it as "mouse held this frame", so we don't miss click-release events that are shorter than 1 frame. + io.MouseDown[i] = g_MouseJustPressed[i] || glfwGetMouseButton(g_Window, i) != 0; + g_MouseJustPressed[i] = false; } io.MouseWheel = g_MouseWheel; @@ -297,6 +301,6 @@ void ImGui_ImplGlfwGL2_NewFrame() // Hide OS mouse cursor if ImGui is drawing it glfwSetInputMode(g_Window, GLFW_CURSOR, io.MouseDrawCursor ? GLFW_CURSOR_HIDDEN : GLFW_CURSOR_NORMAL); - // Start the frame + // Start the frame. This call will update the io.WantCaptureMouse, io.WantCaptureKeyboard flag that you can use to dispatch inputs (or not) to your application. ImGui::NewFrame(); } diff --git a/deps/cimgui/imgui/examples/opengl2_example/imgui_impl_glfw.h b/deps/cimgui/imgui/examples/opengl2_example/imgui_impl_glfw.h index 470863af..f17833ae 100644 --- a/deps/cimgui/imgui/examples/opengl2_example/imgui_impl_glfw.h +++ b/deps/cimgui/imgui/examples/opengl2_example/imgui_impl_glfw.h @@ -1,9 +1,9 @@ // ImGui GLFW binding with OpenGL // In this binding, ImTextureID is used to store an OpenGL 'GLuint' texture identifier. Read the FAQ about ImTextureID in imgui.cpp. +// (GLFW is a cross-platform general purpose library for handling windows, inputs, OpenGL/Vulkan graphics context creation, etc.) -// If your context is GL3/GL3 then prefer using the code in opengl3_example. -// You *might* use this code with a GL3/GL4 context but make sure you disable the programmable pipeline by calling "glUseProgram(0)" before ImGui::Render(). -// We cannot do that from GL2 code because the function doesn't exist. +// *DO NOT USE THIS CODE IF YOUR CODE/ENGINE IS USING MODERN OPENGL* +// See imgui_impl_glfw.cpp for details. // You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this. // If you use this binding you'll need to call 4 functions: ImGui_ImplXXXX_Init(), ImGui_ImplXXXX_NewFrame(), ImGui::Render() and ImGui_ImplXXXX_Shutdown(). diff --git a/deps/cimgui/imgui/examples/opengl2_example/main.cpp b/deps/cimgui/imgui/examples/opengl2_example/main.cpp index bb688c68..1f3336d2 100644 --- a/deps/cimgui/imgui/examples/opengl2_example/main.cpp +++ b/deps/cimgui/imgui/examples/opengl2_example/main.cpp @@ -1,5 +1,9 @@ -// ImGui - standalone example application for Glfw + OpenGL 2, using fixed pipeline +// ImGui - standalone example application for GLFW + OpenGL 2, using fixed pipeline // If you are new to ImGui, see examples/README.txt and documentation at the top of imgui.cpp. +// (GLFW is a cross-platform general purpose library for handling windows, inputs, OpenGL/Vulkan graphics context creation, etc.) + +// *DO NOT USE THIS CODE IF YOUR CODE/ENGINE IS USING MODERN OPENGL* +// See imgui_impl_glfw.cpp for details. #include #include "imgui_impl_glfw.h" @@ -25,14 +29,20 @@ int main(int, char**) ImGui_ImplGlfwGL2_Init(window, true); // Load Fonts - // (there is a default font, this is only if you want to change it. see extra_fonts/README.txt for more details) + // - If no fonts are loaded, dear imgui will use the default font. You can also load multiple fonts and use ImGui::PushFont()/PopFont() to select them. + // - AddFontFromFileTTF() will return the ImFont* so you can store it if you need to select the font among multiple. + // - If the file cannot be loaded, the function will return NULL. Please handle those errors in your application (e.g. use an assertion, or display an error and quit). + // - The fonts will be rasterized at a given size (w/ oversampling) and stored into a texture when calling ImFontAtlas::Build()/GetTexDataAsXXXX(), which ImGui_ImplXXXX_NewFrame below will call. + // - Read 'extra_fonts/README.txt' for more instructions and details. + // - Remember that in C/C++ if you want to include a backslash \ in a string literal you need to write a double backslash \\ ! //ImGuiIO& io = ImGui::GetIO(); //io.Fonts->AddFontDefault(); + //io.Fonts->AddFontFromFileTTF("../../extra_fonts/Roboto-Medium.ttf", 16.0f); //io.Fonts->AddFontFromFileTTF("../../extra_fonts/Cousine-Regular.ttf", 15.0f); //io.Fonts->AddFontFromFileTTF("../../extra_fonts/DroidSans.ttf", 16.0f); - //io.Fonts->AddFontFromFileTTF("../../extra_fonts/Roboto-Medium.ttf", 16.0f); //io.Fonts->AddFontFromFileTTF("../../extra_fonts/ProggyTiny.ttf", 10.0f); - //io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\ArialUni.ttf", 18.0f, NULL, io.Fonts->GetGlyphRangesJapanese()); + //ImFont* font = io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\ArialUni.ttf", 18.0f, NULL, io.Fonts->GetGlyphRangesJapanese()); + //IM_ASSERT(font != NULL); bool show_test_window = true; bool show_another_window = false; @@ -41,11 +51,15 @@ int main(int, char**) // Main loop while (!glfwWindowShouldClose(window)) { + // You can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if dear imgui wants to use your inputs. + // - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application. + // - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application. + // Generally you may always pass all inputs to dear imgui, and hide them from your application based on those two flags. glfwPollEvents(); ImGui_ImplGlfwGL2_NewFrame(); - // 1. Show a simple window - // Tip: if we don't call ImGui::Begin()/ImGui::End() the widgets appears in a window automatically called "Debug" + // 1. Show a simple window. + // Tip: if we don't call ImGui::Begin()/ImGui::End() the widgets appears in a window automatically called "Debug". { static float f = 0.0f; ImGui::Text("Hello, world!"); @@ -56,7 +70,7 @@ int main(int, char**) ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate); } - // 2. Show another simple window, this time using an explicit Begin/End pair + // 2. Show another simple window. In most cases you will use an explicit Begin/End pair to name the window. if (show_another_window) { ImGui::Begin("Another Window", &show_another_window); @@ -64,7 +78,7 @@ int main(int, char**) ImGui::End(); } - // 3. Show the ImGui test window. Most of the sample code is in ImGui::ShowTestWindow() + // 3. Show the ImGui test window. Most of the sample code is in ImGui::ShowTestWindow(). if (show_test_window) { ImGui::SetNextWindowPos(ImVec2(650, 20), ImGuiCond_FirstUseEver); @@ -77,7 +91,7 @@ int main(int, char**) glViewport(0, 0, display_w, display_h); glClearColor(clear_color.x, clear_color.y, clear_color.z, clear_color.w); glClear(GL_COLOR_BUFFER_BIT); - //glUseProgram(0); // You may want this if using this code in an OpenGL 3+ context where shaders may be bound + //glUseProgram(0); // You may want this if using this code in an OpenGL 3+ context where shaders may be bound, but prefer using the GL3+ code. ImGui::Render(); glfwSwapBuffers(window); } diff --git a/deps/cimgui/imgui/examples/opengl3_example/imgui_impl_glfw_gl3.cpp b/deps/cimgui/imgui/examples/opengl3_example/imgui_impl_glfw_gl3.cpp index ac711b91..7d924fcf 100644 --- a/deps/cimgui/imgui/examples/opengl3_example/imgui_impl_glfw_gl3.cpp +++ b/deps/cimgui/imgui/examples/opengl3_example/imgui_impl_glfw_gl3.cpp @@ -1,5 +1,7 @@ // ImGui GLFW binding with OpenGL3 + shaders // In this binding, ImTextureID is used to store an OpenGL 'GLuint' texture identifier. Read the FAQ about ImTextureID in imgui.cpp. +// (GLFW is a cross-platform general purpose library for handling windows, inputs, OpenGL/Vulkan graphics context creation, etc.) +// (GL3W is a helper library to access OpenGL functions since there is no standard header to access modern OpenGL functions easily. Alternatives are GLEW, Glad, etc.) // You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this. // If you use this binding you'll need to call 4 functions: ImGui_ImplXXXX_Init(), ImGui_ImplXXXX_NewFrame(), ImGui::Render() and ImGui_ImplXXXX_Shutdown(). @@ -22,7 +24,7 @@ // Data static GLFWwindow* g_Window = NULL; static double g_Time = 0.0f; -static bool g_MousePressed[3] = { false, false, false }; +static bool g_MouseJustPressed[3] = { false, false, false }; static float g_MouseWheel = 0.0f; static GLuint g_FontTexture = 0; static int g_ShaderHandle = 0, g_VertHandle = 0, g_FragHandle = 0; @@ -150,12 +152,12 @@ static void ImGui_ImplGlfwGL3_SetClipboardText(void* user_data, const char* text void ImGui_ImplGlfwGL3_MouseButtonCallback(GLFWwindow*, int button, int action, int /*mods*/) { if (action == GLFW_PRESS && button >= 0 && button < 3) - g_MousePressed[button] = true; + g_MouseJustPressed[button] = true; } void ImGui_ImplGlfwGL3_ScrollCallback(GLFWwindow*, double /*xoffset*/, double yoffset) { - g_MouseWheel += (float)yoffset; // Use fractional mouse wheel, 1.0 unit 5 lines. + g_MouseWheel += (float)yoffset; // Use fractional mouse wheel. } void ImGui_ImplGlfwGL3_KeyCallback(GLFWwindow*, int key, int, int action, int mods) @@ -401,8 +403,9 @@ void ImGui_ImplGlfwGL3_NewFrame() for (int i = 0; i < 3; i++) { - io.MouseDown[i] = g_MousePressed[i] || glfwGetMouseButton(g_Window, i) != 0; // If a mouse press event came, always pass it as "mouse held this frame", so we don't miss click-release events that are shorter than 1 frame. - g_MousePressed[i] = false; + // If a mouse press event came, always pass it as "mouse held this frame", so we don't miss click-release events that are shorter than 1 frame. + io.MouseDown[i] = g_MouseJustPressed[i] || glfwGetMouseButton(g_Window, i) != 0; + g_MouseJustPressed[i] = false; } io.MouseWheel = g_MouseWheel; @@ -411,6 +414,6 @@ void ImGui_ImplGlfwGL3_NewFrame() // Hide OS mouse cursor if ImGui is drawing it glfwSetInputMode(g_Window, GLFW_CURSOR, io.MouseDrawCursor ? GLFW_CURSOR_HIDDEN : GLFW_CURSOR_NORMAL); - // Start the frame + // Start the frame. This call will update the io.WantCaptureMouse, io.WantCaptureKeyboard flag that you can use to dispatch inputs (or not) to your application. ImGui::NewFrame(); } diff --git a/deps/cimgui/imgui/examples/opengl3_example/imgui_impl_glfw_gl3.h b/deps/cimgui/imgui/examples/opengl3_example/imgui_impl_glfw_gl3.h index 83c69aa8..5f304398 100644 --- a/deps/cimgui/imgui/examples/opengl3_example/imgui_impl_glfw_gl3.h +++ b/deps/cimgui/imgui/examples/opengl3_example/imgui_impl_glfw_gl3.h @@ -1,5 +1,7 @@ // ImGui GLFW binding with OpenGL3 + shaders // In this binding, ImTextureID is used to store an OpenGL 'GLuint' texture identifier. Read the FAQ about ImTextureID in imgui.cpp. +// (GLFW is a cross-platform general purpose library for handling windows, inputs, OpenGL/Vulkan graphics context creation, etc.) +// (GL3W is a helper library to access OpenGL functions since there is no standard header to access modern OpenGL functions easily. Alternatives are GLEW, Glad, etc.) // You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this. // If you use this binding you'll need to call 4 functions: ImGui_ImplXXXX_Init(), ImGui_ImplXXXX_NewFrame(), ImGui::Render() and ImGui_ImplXXXX_Shutdown(). diff --git a/deps/cimgui/imgui/examples/opengl3_example/main.cpp b/deps/cimgui/imgui/examples/opengl3_example/main.cpp index 6b20f8ce..062843d6 100644 --- a/deps/cimgui/imgui/examples/opengl3_example/main.cpp +++ b/deps/cimgui/imgui/examples/opengl3_example/main.cpp @@ -1,5 +1,7 @@ -// ImGui - standalone example application for Glfw + OpenGL 3, using programmable pipeline +// ImGui - standalone example application for GLFW + OpenGL 3, using programmable pipeline // If you are new to ImGui, see examples/README.txt and documentation at the top of imgui.cpp. +// (GLFW is a cross-platform general purpose library for handling windows, inputs, OpenGL/Vulkan graphics context creation, etc.) +// (GL3W is a helper library to access OpenGL functions since there is no standard header to access modern OpenGL functions easily. Alternatives are GLEW, Glad, etc.) #include #include "imgui_impl_glfw_gl3.h" @@ -33,14 +35,20 @@ int main(int, char**) ImGui_ImplGlfwGL3_Init(window, true); // Load Fonts - // (there is a default font, this is only if you want to change it. see extra_fonts/README.txt for more details) + // - If no fonts are loaded, dear imgui will use the default font. You can also load multiple fonts and use ImGui::PushFont()/PopFont() to select them. + // - AddFontFromFileTTF() will return the ImFont* so you can store it if you need to select the font among multiple. + // - If the file cannot be loaded, the function will return NULL. Please handle those errors in your application (e.g. use an assertion, or display an error and quit). + // - The fonts will be rasterized at a given size (w/ oversampling) and stored into a texture when calling ImFontAtlas::Build()/GetTexDataAsXXXX(), which ImGui_ImplXXXX_NewFrame below will call. + // - Read 'extra_fonts/README.txt' for more instructions and details. + // - Remember that in C/C++ if you want to include a backslash \ in a string literal you need to write a double backslash \\ ! //ImGuiIO& io = ImGui::GetIO(); //io.Fonts->AddFontDefault(); + //io.Fonts->AddFontFromFileTTF("../../extra_fonts/Roboto-Medium.ttf", 16.0f); //io.Fonts->AddFontFromFileTTF("../../extra_fonts/Cousine-Regular.ttf", 15.0f); //io.Fonts->AddFontFromFileTTF("../../extra_fonts/DroidSans.ttf", 16.0f); - //io.Fonts->AddFontFromFileTTF("../../extra_fonts/Roboto-Medium.ttf", 16.0f); //io.Fonts->AddFontFromFileTTF("../../extra_fonts/ProggyTiny.ttf", 10.0f); - //io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\ArialUni.ttf", 18.0f, NULL, io.Fonts->GetGlyphRangesJapanese()); + //ImFont* font = io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\ArialUni.ttf", 18.0f, NULL, io.Fonts->GetGlyphRangesJapanese()); + //IM_ASSERT(font != NULL); bool show_test_window = true; bool show_another_window = false; @@ -49,11 +57,15 @@ int main(int, char**) // Main loop while (!glfwWindowShouldClose(window)) { + // You can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if dear imgui wants to use your inputs. + // - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application. + // - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application. + // Generally you may always pass all inputs to dear imgui, and hide them from your application based on those two flags. glfwPollEvents(); ImGui_ImplGlfwGL3_NewFrame(); - // 1. Show a simple window - // Tip: if we don't call ImGui::Begin()/ImGui::End() the widgets appears in a window automatically called "Debug" + // 1. Show a simple window. + // Tip: if we don't call ImGui::Begin()/ImGui::End() the widgets appears in a window automatically called "Debug". { static float f = 0.0f; ImGui::Text("Hello, world!"); @@ -64,7 +76,7 @@ int main(int, char**) ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate); } - // 2. Show another simple window, this time using an explicit Begin/End pair + // 2. Show another simple window. In most cases you will use an explicit Begin/End pair to name the window. if (show_another_window) { ImGui::Begin("Another Window", &show_another_window); @@ -72,7 +84,7 @@ int main(int, char**) ImGui::End(); } - // 3. Show the ImGui test window. Most of the sample code is in ImGui::ShowTestWindow() + // 3. Show the ImGui test window. Most of the sample code is in ImGui::ShowTestWindow(). if (show_test_window) { ImGui::SetNextWindowPos(ImVec2(650, 20), ImGuiCond_FirstUseEver); diff --git a/deps/cimgui/imgui/examples/sdl_opengl2_example/imgui_impl_sdl.cpp b/deps/cimgui/imgui/examples/sdl_opengl2_example/imgui_impl_sdl.cpp index 78ce4035..2982f8de 100644 --- a/deps/cimgui/imgui/examples/sdl_opengl2_example/imgui_impl_sdl.cpp +++ b/deps/cimgui/imgui/examples/sdl_opengl2_example/imgui_impl_sdl.cpp @@ -1,8 +1,13 @@ // ImGui SDL2 binding with OpenGL // In this binding, ImTextureID is used to store an OpenGL 'GLuint' texture identifier. Read the FAQ about ImTextureID in imgui.cpp. +// (SDL is a cross-platform general purpose library for handling windows, inputs, OpenGL/Vulkan graphics context creation, etc.) -// If your context or own usage of OpenGL involve anything GL3/GL4, prefer using the code in sdl_opengl3_example. -// If you are not sure what that means, prefer using the code in sdl_opengl3_example. +// *DO NOT USE THIS CODE IF YOUR CODE/ENGINE IS USING MODERN OPENGL* +// This is mostly provided as a reference to learn how ImGui integration works, because it is easier to read. +// If your code is using GL3+ context or any semi modern OpenGL calls, using this is likely to make everything +// more complicated, will require your code to reset every single OpenGL attributes to their initial state, +// and might confuse your GPU driver. Prefer using sdl_opengl3_example. +// The GL2 code is unable to reset attributes or even call e.g. "glUseProgram(0)" because they don't exist in that API. // You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this. // If you use this binding you'll need to call 4 functions: ImGui_ImplXXXX_Init(), ImGui_ImplXXXX_NewFrame(), ImGui::Render() and ImGui_ImplXXXX_Shutdown(). @@ -117,6 +122,10 @@ static void ImGui_ImplSdl_SetClipboardText(void*, const char* text) SDL_SetClipboardText(text); } +// You can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if dear imgui wants to use your inputs. +// - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application. +// - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application. +// Generally you may always pass all inputs to dear imgui, and hide them from your application based on those two flags. bool ImGui_ImplSdlGL2_ProcessEvent(SDL_Event* event) { ImGuiIO& io = ImGui::GetIO(); @@ -281,6 +290,6 @@ void ImGui_ImplSdlGL2_NewFrame(SDL_Window *window) // Hide OS mouse cursor if ImGui is drawing it SDL_ShowCursor(io.MouseDrawCursor ? 0 : 1); - // Start the frame + // Start the frame. This call will update the io.WantCaptureMouse, io.WantCaptureKeyboard flag that you can use to dispatch inputs (or not) to your application. ImGui::NewFrame(); } diff --git a/deps/cimgui/imgui/examples/sdl_opengl2_example/imgui_impl_sdl.h b/deps/cimgui/imgui/examples/sdl_opengl2_example/imgui_impl_sdl.h index 65b2bd99..ea94f69a 100644 --- a/deps/cimgui/imgui/examples/sdl_opengl2_example/imgui_impl_sdl.h +++ b/deps/cimgui/imgui/examples/sdl_opengl2_example/imgui_impl_sdl.h @@ -1,5 +1,6 @@ // ImGui SDL2 binding with OpenGL // In this binding, ImTextureID is used to store an OpenGL 'GLuint' texture identifier. Read the FAQ about ImTextureID in imgui.cpp. +// (SDL is a cross-platform general purpose library for handling windows, inputs, OpenGL/Vulkan graphics context creation, etc.) // You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this. // If you use this binding you'll need to call 4 functions: ImGui_ImplXXXX_Init(), ImGui_ImplXXXX_NewFrame(), ImGui::Render() and ImGui_ImplXXXX_Shutdown(). diff --git a/deps/cimgui/imgui/examples/sdl_opengl2_example/main.cpp b/deps/cimgui/imgui/examples/sdl_opengl2_example/main.cpp index 9d8a8622..cfa43e8e 100644 --- a/deps/cimgui/imgui/examples/sdl_opengl2_example/main.cpp +++ b/deps/cimgui/imgui/examples/sdl_opengl2_example/main.cpp @@ -1,5 +1,9 @@ // ImGui - standalone example application for SDL2 + OpenGL // If you are new to ImGui, see examples/README.txt and documentation at the top of imgui.cpp. +// (SDL is a cross-platform general purpose library for handling windows, inputs, OpenGL/Vulkan graphics context creation, etc.) + +// *DO NOT USE THIS CODE IF YOUR CODE/ENGINE IS USING MODERN OPENGL* +// See imgui_impl_sdl.cpp for details. #include #include "imgui_impl_sdl.h" @@ -31,14 +35,20 @@ int main(int, char**) ImGui_ImplSdlGL2_Init(window); // Load Fonts - // (there is a default font, this is only if you want to change it. see extra_fonts/README.txt for more details) + // - If no fonts are loaded, dear imgui will use the default font. You can also load multiple fonts and use ImGui::PushFont()/PopFont() to select them. + // - AddFontFromFileTTF() will return the ImFont* so you can store it if you need to select the font among multiple. + // - If the file cannot be loaded, the function will return NULL. Please handle those errors in your application (e.g. use an assertion, or display an error and quit). + // - The fonts will be rasterized at a given size (w/ oversampling) and stored into a texture when calling ImFontAtlas::Build()/GetTexDataAsXXXX(), which ImGui_ImplXXXX_NewFrame below will call. + // - Read 'extra_fonts/README.txt' for more instructions and details. + // - Remember that in C/C++ if you want to include a backslash \ in a string literal you need to write a double backslash \\ ! //ImGuiIO& io = ImGui::GetIO(); //io.Fonts->AddFontDefault(); + //io.Fonts->AddFontFromFileTTF("../../extra_fonts/Roboto-Medium.ttf", 16.0f); //io.Fonts->AddFontFromFileTTF("../../extra_fonts/Cousine-Regular.ttf", 15.0f); //io.Fonts->AddFontFromFileTTF("../../extra_fonts/DroidSans.ttf", 16.0f); - //io.Fonts->AddFontFromFileTTF("../../extra_fonts/Roboto-Medium.ttf", 16.0f); //io.Fonts->AddFontFromFileTTF("../../extra_fonts/ProggyTiny.ttf", 10.0f); - //io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\ArialUni.ttf", 18.0f, NULL, io.Fonts->GetGlyphRangesJapanese()); + //ImFont* font = io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\ArialUni.ttf", 18.0f, NULL, io.Fonts->GetGlyphRangesJapanese()); + //IM_ASSERT(font != NULL); bool show_test_window = true; bool show_another_window = false; @@ -48,6 +58,10 @@ int main(int, char**) bool done = false; while (!done) { + // You can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if dear imgui wants to use your inputs. + // - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application. + // - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application. + // Generally you may always pass all inputs to dear imgui, and hide them from your application based on those two flags. SDL_Event event; while (SDL_PollEvent(&event)) { @@ -58,7 +72,7 @@ int main(int, char**) ImGui_ImplSdlGL2_NewFrame(window); // 1. Show a simple window - // Tip: if we don't call ImGui::Begin()/ImGui::End() the widgets appears in a window automatically called "Debug" + // Tip: if we don't call ImGui::Begin()/ImGui::End() the widgets appears in a window automatically called "Debug". { static float f = 0.0f; ImGui::Text("Hello, world!"); @@ -69,7 +83,7 @@ int main(int, char**) ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate); } - // 2. Show another simple window, this time using an explicit Begin/End pair + // 2. Show another simple window. In most cases you will use an explicit Begin/End pair to name the window. if (show_another_window) { ImGui::Begin("Another Window", &show_another_window); @@ -77,7 +91,7 @@ int main(int, char**) ImGui::End(); } - // 3. Show the ImGui test window. Most of the sample code is in ImGui::ShowTestWindow() + // 3. Show the ImGui test window. Most of the sample code is in ImGui::ShowTestWindow(). if (show_test_window) { ImGui::SetNextWindowPos(ImVec2(650, 20), ImGuiCond_FirstUseEver); diff --git a/deps/cimgui/imgui/examples/sdl_opengl3_example/imgui_impl_sdl_gl3.cpp b/deps/cimgui/imgui/examples/sdl_opengl3_example/imgui_impl_sdl_gl3.cpp index 0301d31b..68e27a68 100644 --- a/deps/cimgui/imgui/examples/sdl_opengl3_example/imgui_impl_sdl_gl3.cpp +++ b/deps/cimgui/imgui/examples/sdl_opengl3_example/imgui_impl_sdl_gl3.cpp @@ -1,5 +1,7 @@ // ImGui SDL2 binding with OpenGL3 // In this binding, ImTextureID is used to store an OpenGL 'GLuint' texture identifier. Read the FAQ about ImTextureID in imgui.cpp. +// (SDL is a cross-platform general purpose library for handling windows, inputs, OpenGL/Vulkan graphics context creation, etc.) +// (GL3W is a helper library to access OpenGL functions since there is no standard header to access modern OpenGL functions easily. Alternatives are GLEW, Glad, etc.) // You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this. // If you use this binding you'll need to call 4 functions: ImGui_ImplXXXX_Init(), ImGui_ImplXXXX_NewFrame(), ImGui::Render() and ImGui_ImplXXXX_Shutdown(). @@ -141,6 +143,10 @@ static void ImGui_ImplSdlGL3_SetClipboardText(void*, const char* text) SDL_SetClipboardText(text); } +// You can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if dear imgui wants to use your inputs. +// - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application. +// - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application. +// Generally you may always pass all inputs to dear imgui, and hide them from your application based on those two flags. bool ImGui_ImplSdlGL3_ProcessEvent(SDL_Event* event) { ImGuiIO& io = ImGui::GetIO(); @@ -396,6 +402,6 @@ void ImGui_ImplSdlGL3_NewFrame(SDL_Window* window) // Hide OS mouse cursor if ImGui is drawing it SDL_ShowCursor(io.MouseDrawCursor ? 0 : 1); - // Start the frame + // Start the frame. This call will update the io.WantCaptureMouse, io.WantCaptureKeyboard flag that you can use to dispatch inputs (or not) to your application. ImGui::NewFrame(); } diff --git a/deps/cimgui/imgui/examples/sdl_opengl3_example/imgui_impl_sdl_gl3.h b/deps/cimgui/imgui/examples/sdl_opengl3_example/imgui_impl_sdl_gl3.h index 99abd409..54381866 100644 --- a/deps/cimgui/imgui/examples/sdl_opengl3_example/imgui_impl_sdl_gl3.h +++ b/deps/cimgui/imgui/examples/sdl_opengl3_example/imgui_impl_sdl_gl3.h @@ -1,5 +1,7 @@ // ImGui SDL2 binding with OpenGL3 // In this binding, ImTextureID is used to store an OpenGL 'GLuint' texture identifier. Read the FAQ about ImTextureID in imgui.cpp. +// (SDL is a cross-platform general purpose library for handling windows, inputs, OpenGL/Vulkan graphics context creation, etc.) +// (GL3W is a helper library to access OpenGL functions since there is no standard header to access modern OpenGL functions easily. Alternatives are GLEW, Glad, etc.) // You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this. // If you use this binding you'll need to call 4 functions: ImGui_ImplXXXX_Init(), ImGui_ImplXXXX_NewFrame(), ImGui::Render() and ImGui_ImplXXXX_Shutdown(). diff --git a/deps/cimgui/imgui/examples/sdl_opengl3_example/main.cpp b/deps/cimgui/imgui/examples/sdl_opengl3_example/main.cpp index afd9fe58..e51b3208 100644 --- a/deps/cimgui/imgui/examples/sdl_opengl3_example/main.cpp +++ b/deps/cimgui/imgui/examples/sdl_opengl3_example/main.cpp @@ -1,5 +1,7 @@ // ImGui - standalone example application for SDL2 + OpenGL // If you are new to ImGui, see examples/README.txt and documentation at the top of imgui.cpp. +// (SDL is a cross-platform general purpose library for handling windows, inputs, OpenGL/Vulkan graphics context creation, etc.) +// (GL3W is a helper library to access OpenGL functions since there is no standard header to access modern OpenGL functions easily. Alternatives are GLEW, Glad, etc.) #include #include "imgui_impl_sdl_gl3.h" @@ -34,14 +36,20 @@ int main(int, char**) ImGui_ImplSdlGL3_Init(window); // Load Fonts - // (there is a default font, this is only if you want to change it. see extra_fonts/README.txt for more details) + // - If no fonts are loaded, dear imgui will use the default font. You can also load multiple fonts and use ImGui::PushFont()/PopFont() to select them. + // - AddFontFromFileTTF() will return the ImFont* so you can store it if you need to select the font among multiple. + // - If the file cannot be loaded, the function will return NULL. Please handle those errors in your application (e.g. use an assertion, or display an error and quit). + // - The fonts will be rasterized at a given size (w/ oversampling) and stored into a texture when calling ImFontAtlas::Build()/GetTexDataAsXXXX(), which ImGui_ImplXXXX_NewFrame below will call. + // - Read 'extra_fonts/README.txt' for more instructions and details. + // - Remember that in C/C++ if you want to include a backslash \ in a string literal you need to write a double backslash \\ ! //ImGuiIO& io = ImGui::GetIO(); //io.Fonts->AddFontDefault(); + //io.Fonts->AddFontFromFileTTF("../../extra_fonts/Roboto-Medium.ttf", 16.0f); //io.Fonts->AddFontFromFileTTF("../../extra_fonts/Cousine-Regular.ttf", 15.0f); //io.Fonts->AddFontFromFileTTF("../../extra_fonts/DroidSans.ttf", 16.0f); - //io.Fonts->AddFontFromFileTTF("../../extra_fonts/Roboto-Medium.ttf", 16.0f); //io.Fonts->AddFontFromFileTTF("../../extra_fonts/ProggyTiny.ttf", 10.0f); - //io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\ArialUni.ttf", 18.0f, NULL, io.Fonts->GetGlyphRangesJapanese()); + //ImFont* font = io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\ArialUni.ttf", 18.0f, NULL, io.Fonts->GetGlyphRangesJapanese()); + //IM_ASSERT(font != NULL); bool show_test_window = true; bool show_another_window = false; @@ -51,6 +59,10 @@ int main(int, char**) bool done = false; while (!done) { + // You can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if dear imgui wants to use your inputs. + // - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application. + // - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application. + // Generally you may always pass all inputs to dear imgui, and hide them from your application based on those two flags. SDL_Event event; while (SDL_PollEvent(&event)) { @@ -60,8 +72,8 @@ int main(int, char**) } ImGui_ImplSdlGL3_NewFrame(window); - // 1. Show a simple window - // Tip: if we don't call ImGui::Begin()/ImGui::End() the widgets appears in a window automatically called "Debug" + // 1. Show a simple window. + // Tip: if we don't call ImGui::Begin()/ImGui::End() the widgets appears in a window automatically called "Debug". { static float f = 0.0f; ImGui::Text("Hello, world!"); @@ -72,7 +84,7 @@ int main(int, char**) ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate); } - // 2. Show another simple window, this time using an explicit Begin/End pair + // 2. Show another simple window. In most cases you will use an explicit Begin/End pair to name the window. if (show_another_window) { ImGui::Begin("Another Window", &show_another_window); @@ -80,7 +92,7 @@ int main(int, char**) ImGui::End(); } - // 3. Show the ImGui test window. Most of the sample code is in ImGui::ShowTestWindow() + // 3. Show the ImGui test window. Most of the sample code is in ImGui::ShowTestWindow(). if (show_test_window) { ImGui::SetNextWindowPos(ImVec2(650, 20), ImGuiCond_FirstUseEver); diff --git a/deps/cimgui/imgui/examples/vulkan_example/CMakeLists.txt b/deps/cimgui/imgui/examples/vulkan_example/CMakeLists.txt new file mode 100644 index 00000000..d05b4516 --- /dev/null +++ b/deps/cimgui/imgui/examples/vulkan_example/CMakeLists.txt @@ -0,0 +1,36 @@ +cmake_minimum_required(VERSION 2.8) +project(ImGuiGLFWVulkanExample C CXX) + +if(NOT CMAKE_BUILD_TYPE) + set(CMAKE_BUILD_TYPE Debug CACHE STRING "" FORCE) +endif() + +set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DVK_PROTOTYPES") +set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DVK_PROTOTYPES") + +# GLFW +set(GLFW_DIR ../../../glfw) # Set this to point to an up-to-date GLFW repo +option(GLFW_BUILD_EXAMPLES "Build the GLFW example programs" OFF) +option(GLFW_BUILD_TESTS "Build the GLFW test programs" OFF) +option(GLFW_BUILD_DOCS "Build the GLFW documentation" OFF) +option(GLFW_INSTALL "Generate installation target" OFF) +option(GLFW_DOCUMENT_INTERNALS "Include internals in documentation" OFF) +add_subdirectory(${GLFW_DIR} binary_dir EXCLUDE_FROM_ALL) +include_directories(${GLFW_DIR}/include) + +# ImGui +set(IMGUI_DIR ../../) +include_directories(${IMGUI_DIR}) + +# Libraries +find_library(VULKAN_LIBRARY + NAMES vulkan vulkan-1) +set(LIBRARIES "glfw;${VULKAN_LIBRARY}") + +# Use vulkan headers from glfw: +include_directories(${GLFW_DIR}/deps) + +file(GLOB sources *.cpp) + +add_executable(vulkan_example ${sources} ${IMGUI_DIR}/imgui.cpp ${IMGUI_DIR}/imgui_draw.cpp ${IMGUI_DIR}/imgui_demo.cpp) +target_link_libraries(vulkan_example ${LIBRARIES}) diff --git a/deps/cimgui/imgui/examples/vulkan_example/imgui_impl_glfw_vulkan.cpp b/deps/cimgui/imgui/examples/vulkan_example/imgui_impl_glfw_vulkan.cpp index 90f78327..1d12e3f7 100644 --- a/deps/cimgui/imgui/examples/vulkan_example/imgui_impl_glfw_vulkan.cpp +++ b/deps/cimgui/imgui/examples/vulkan_example/imgui_impl_glfw_vulkan.cpp @@ -332,7 +332,7 @@ void ImGui_ImplGlfwVulkan_MouseButtonCallback(GLFWwindow*, int button, int actio void ImGui_ImplGlfwVulkan_ScrollCallback(GLFWwindow*, double /*xoffset*/, double yoffset) { - g_MouseWheel += (float)yoffset; // Use fractional mouse wheel, 1.0 unit 5 lines. + g_MouseWheel += (float)yoffset; // Use fractional mouse wheel. } void ImGui_ImplGlfwVulkan_KeyCallback(GLFWwindow*, int key, int, int action, int mods) @@ -830,7 +830,7 @@ void ImGui_ImplGlfwVulkan_NewFrame() // Hide OS mouse cursor if ImGui is drawing it glfwSetInputMode(g_Window, GLFW_CURSOR, io.MouseDrawCursor ? GLFW_CURSOR_HIDDEN : GLFW_CURSOR_NORMAL); - // Start the frame + // Start the frame. This call will update the io.WantCaptureMouse, io.WantCaptureKeyboard flag that you can use to dispatch inputs (or not) to your application. ImGui::NewFrame(); } diff --git a/deps/cimgui/imgui/examples/vulkan_example/main.cpp b/deps/cimgui/imgui/examples/vulkan_example/main.cpp index 37990174..9d54976a 100644 --- a/deps/cimgui/imgui/examples/vulkan_example/main.cpp +++ b/deps/cimgui/imgui/examples/vulkan_example/main.cpp @@ -626,14 +626,20 @@ int main(int, char**) ImGui_ImplGlfwVulkan_Init(window, true, &init_data); // Load Fonts - // (there is a default font, this is only if you want to change it. see extra_fonts/README.txt for more details) + // - If no fonts are loaded, dear imgui will use the default font. You can also load multiple fonts and use ImGui::PushFont()/PopFont() to select them. + // - AddFontFromFileTTF() will return the ImFont* so you can store it if you need to select the font among multiple. + // - If the file cannot be loaded, the function will return NULL. Please handle those errors in your application (e.g. use an assertion, or display an error and quit). + // - The fonts will be rasterized at a given size (w/ oversampling) and stored into a texture when calling ImFontAtlas::Build()/GetTexDataAsXXXX(), which ImGui_ImplXXXX_NewFrame below will call. + // - Read 'extra_fonts/README.txt' for more instructions and details. + // - Remember that in C/C++ if you want to include a backslash \ in a string literal you need to write a double backslash \\ ! //ImGuiIO& io = ImGui::GetIO(); //io.Fonts->AddFontDefault(); + //io.Fonts->AddFontFromFileTTF("../../extra_fonts/Roboto-Medium.ttf", 16.0f); //io.Fonts->AddFontFromFileTTF("../../extra_fonts/Cousine-Regular.ttf", 15.0f); //io.Fonts->AddFontFromFileTTF("../../extra_fonts/DroidSans.ttf", 16.0f); - //io.Fonts->AddFontFromFileTTF("../../extra_fonts/Roboto-Medium.ttf", 16.0f); //io.Fonts->AddFontFromFileTTF("../../extra_fonts/ProggyTiny.ttf", 10.0f); - //io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\ArialUni.ttf", 18.0f, NULL, io.Fonts->GetGlyphRangesJapanese()); + //ImFont* font = io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\ArialUni.ttf", 18.0f, NULL, io.Fonts->GetGlyphRangesJapanese()); + //IM_ASSERT(font != NULL); // Upload Fonts { @@ -680,11 +686,15 @@ int main(int, char**) // Main loop while (!glfwWindowShouldClose(window)) { + // You can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if dear imgui wants to use your inputs. + // - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application. + // - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application. + // Generally you may always pass all inputs to dear imgui, and hide them from your application based on those two flags. glfwPollEvents(); ImGui_ImplGlfwVulkan_NewFrame(); - // 1. Show a simple window - // Tip: if we don't call ImGui::Begin()/ImGui::End() the widgets appears in a window automatically called "Debug" + // 1. Show a simple window. + // Tip: if we don't call ImGui::Begin()/ImGui::End() the widgets appears in a window automatically called "Debug". { static float f = 0.0f; ImGui::Text("Hello, world!"); @@ -695,7 +705,7 @@ int main(int, char**) ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate); } - // 2. Show another simple window, this time using an explicit Begin/End pair + // 2. Show another simple window. In most cases you will use an explicit Begin/End pair to name the window. if (show_another_window) { ImGui::Begin("Another Window", &show_another_window); @@ -703,7 +713,7 @@ int main(int, char**) ImGui::End(); } - // 3. Show the ImGui test window. Most of the sample code is in ImGui::ShowTestWindow() + // 3. Show the ImGui test window. Most of the sample code is in ImGui::ShowTestWindow(). if (show_test_window) { ImGui::SetNextWindowPos(ImVec2(650, 20), ImGuiCond_FirstUseEver); diff --git a/deps/cimgui/imgui/imconfig.h b/deps/cimgui/imgui/imconfig.h index e557fa06..85eff5fd 100644 --- a/deps/cimgui/imgui/imconfig.h +++ b/deps/cimgui/imgui/imconfig.h @@ -13,24 +13,27 @@ //#define IMGUI_API __declspec( dllexport ) //#define IMGUI_API __declspec( dllimport ) +//---- Don't define obsolete functions names. Consider enabling from time to time or when updating to reduce like hood of using already obsolete function/names +//#define IMGUI_DISABLE_OBSOLETE_FUNCTIONS + //---- Include imgui_user.h at the end of imgui.h //#define IMGUI_INCLUDE_IMGUI_USER_H //---- Don't implement default handlers for Windows (so as not to link with OpenClipboard() and others Win32 functions) -//#define IMGUI_DISABLE_WIN32_DEFAULT_CLIPBOARD_FUNCS -//#define IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCS +//#define IMGUI_DISABLE_WIN32_DEFAULT_CLIPBOARD_FUNCTIONS +//#define IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS //---- Don't implement test window functionality (ShowTestWindow()/ShowStyleEditor()/ShowUserGuide() methods will be empty) //---- It is very strongly recommended to NOT disable the test windows. Please read the comment at the top of imgui_demo.cpp to learn why. //#define IMGUI_DISABLE_TEST_WINDOWS -//---- Don't define obsolete functions names. Consider enabling from time to time or when updating to reduce like hood of using already obsolete function/names -//#define IMGUI_DISABLE_OBSOLETE_FUNCTIONS +//---- Don't implement ImFormatString(), ImFormatStringV() so you can reimplement them yourself. +//#define IMGUI_DISABLE_FORMAT_STRING_FUNCTIONS //---- Pack colors to BGRA instead of RGBA (remove need to post process vertex buffer in back ends) //#define IMGUI_USE_BGRA_PACKED_COLOR -//---- Implement STB libraries in a namespace to avoid conflicts +//---- Implement STB libraries in a namespace to avoid linkage conflicts //#define IMGUI_STB_NAMESPACE ImGuiStb //---- Define constructor and implicit cast operators to convert back<>forth from your math types and ImVec2/ImVec4. diff --git a/deps/cimgui/imgui/imgui.cpp b/deps/cimgui/imgui/imgui.cpp index ced2f747..d4614772 100644 --- a/deps/cimgui/imgui/imgui.cpp +++ b/deps/cimgui/imgui/imgui.cpp @@ -1,4 +1,4 @@ -// dear imgui, v1.52 WIP +// dear imgui, v1.53 WIP // (main code and documentation) // ** EXPERIMENTAL GAMEPAD/KEYBOARD NAVIGATION BRANCH @@ -52,7 +52,8 @@ - Minimize setup and maintenance - Minimize state storage on user side - Portable, minimize dependencies, run on target (consoles, phones, etc.) - - Efficient runtime and memory consumption (NB- we do allocate when "growing" content - creating a window / opening a tree node for the first time, etc. - but a typical frame won't allocate anything) + - Efficient runtime and memory consumption (NB- we do allocate when "growing" content e.g. creating a window, opening a tree node + for the first time, etc. but a typical frame won't allocate anything) Designed for developers and content-creators, not the typical end-user! Some of the weaknesses includes: - Doesn't look fancy, doesn't animate @@ -62,23 +63,21 @@ END-USER GUIDE ============== - - Double-click title bar to collapse window - - Click upper right corner to close a window, available when 'bool* p_open' is passed to ImGui::Begin() - - Click and drag on lower right corner to resize window - - Click and drag on any empty space to move window - - Double-click/double-tap on lower right corner grip to auto-fit to content - - TAB/SHIFT+TAB to cycle through keyboard editable fields - - Use mouse wheel to scroll - - Use CTRL+mouse wheel to zoom window contents (if io.FontAllowScaling is true) - - CTRL+Click on a slider or drag box to input value as text + - Double-click on title bar to collapse window. + - Click upper right corner to close a window, available when 'bool* p_open' is passed to ImGui::Begin(). + - Click and drag on lower right corner to resize window (double-click to auto fit window to its contents). + - Click and drag on any empty space to move window. + - TAB/SHIFT+TAB to cycle through keyboard editable fields. + - CTRL+Click on a slider or drag box to input value as text. + - Use mouse wheel to scroll. - Text editor: - Hold SHIFT or use mouse to select text. - - CTRL+Left/Right to word jump - - CTRL+Shift+Left/Right to select words - - CTRL+A our Double-Click to select all - - CTRL+X,CTRL+C,CTRL+V to use OS clipboard - - CTRL+Z,CTRL+Y to undo/redo - - ESCAPE to revert text to its original value + - CTRL+Left/Right to word jump. + - CTRL+Shift+Left/Right to select words. + - CTRL+A our Double-Click to select all. + - CTRL+X,CTRL+C,CTRL+V to use OS clipboard/ + - CTRL+Z,CTRL+Y to undo/redo. + - ESCAPE to revert text to its original value. - You can apply arithmetic operators +,*,/ on numerical values. Use +- to subtract (because - would set a negative value!) - Controls are automatically adjusted for OSX to match standard OSX text editing operations. - Gamepad/keyboard navigation are in beta-phase, see Programmer Guide below. @@ -90,7 +89,8 @@ READ FIRST - Read the FAQ below this section! - - Your code creates the UI, if your code doesn't run the UI is gone! == very dynamic UI, no construction/destructions steps, less data retention on your side, no state duplication, less sync, less bugs. + - Your code creates the UI, if your code doesn't run the UI is gone! == very dynamic UI, no construction/destructions steps, less data retention + on your side, no state duplication, less sync, less bugs. - Call and read ImGui::ShowTestWindow() for demo code demonstrating most features. - You can learn about immediate-mode gui principles at http://www.johno.se/book/imgui.html or watch http://mollyrocket.com/861 @@ -105,25 +105,28 @@ GETTING STARTED WITH INTEGRATING DEAR IMGUI IN YOUR CODE/ENGINE - - Add the Dear ImGui source files to your projects, using your preferred build system. It is recommended you build the .cpp files as part of your project and not as a library. + - Add the Dear ImGui source files to your projects, using your preferred build system. + It is recommended you build the .cpp files as part of your project and not as a library. - You can later customize the imconfig.h file to tweak some compilation time behavior, such as integrating imgui types with your own maths types. - - See examples/ folder for standalone sample applications. To understand the integration process, you can read examples/opengl2_example/ because it is short, - then switch to the one more appropriate to your use case. + - See examples/ folder for standalone sample applications. To understand the integration process, you can read examples/opengl2_example/ because + it is short, then switch to the one more appropriate to your use case. - You may be able to grab and copy a ready made imgui_impl_*** file from the examples/. - When using Dear ImGui, your programming IDE is your friend: follow the declaration of variables, functions and types to find comments about them. - - Init: retrieve the ImGuiIO structure with ImGui::GetIO() and fill the fields marked 'Settings': at minimum you need to set io.DisplaySize (application resolution). - Later on you will fill your keyboard mapping, clipboard handlers, and other advanced features but for a basic integration you don't need to worry about it all. + - Init: retrieve the ImGuiIO structure with ImGui::GetIO() and fill the fields marked 'Settings': at minimum you need to set io.DisplaySize + (application resolution). Later on you will fill your keyboard mapping, clipboard handlers, and other advanced features but for a basic + integration you don't need to worry about it all. - Init: call io.Fonts->GetTexDataAsRGBA32(...), it will build the font atlas texture, then load the texture pixels into graphics memory. - Every frame: - In your main loop as early a possible, fill the IO fields marked 'Input' (e.g. mouse position, buttons, keyboard info, etc.) - Call ImGui::NewFrame() to begin the frame - You can use any ImGui function you want between NewFrame() and Render() - Call ImGui::Render() as late as you can to end the frame and finalize render data. it will call your io.RenderDrawListFn handler. - (if you don't need to render, you still need to call Render() and ignore the callback, or call EndFrame() instead. if you call neither some aspects of windows focusing/moving will appear broken.) + (Even if you don't render, call Render() and ignore the callback, or call EndFrame() instead. Otherwhise some features will break) - All rendering information are stored into command-lists until ImGui::Render() is called. - Dear ImGui never touches or knows about your GPU state. the only function that knows about GPU is the RenderDrawListFn handler that you provide. - - Effectively it means you can create widgets at any time in your code, regardless of considerations of being in "update" vs "render" phases of your own application. + - Effectively it means you can create widgets at any time in your code, regardless of considerations of being in "update" vs "render" phases + of your own application. - Refer to the examples applications in the examples/ folder for instruction on how to setup your code. - A minimal application skeleton may be: @@ -131,7 +134,7 @@ ImGuiIO& io = ImGui::GetIO(); io.DisplaySize.x = 1920.0f; io.DisplaySize.y = 1280.0f; - io.RenderDrawListsFn = MyRenderFunction; // Setup a render function, or set to NULL and call GetDrawData() after Render() to access the render data. + io.RenderDrawListsFn = MyRenderFunction; // Setup a render function, or set to NULL and call GetDrawData() after Render() to access render data. // TODO: Fill others settings of the io structure later. // Load texture atlas (there is a default font so you don't need to care about choosing a font yet) @@ -185,9 +188,16 @@ } else { - // Render 'pcmd->ElemCount/3' texture triangles + // The texture for the draw call is specified by pcmd->TextureId. + // The vast majority of draw calls with use the imgui texture atlas, which value you have set yourself during initialization. MyEngineBindTexture(pcmd->TextureId); + + // We are using scissoring to clip some objects. All low-level graphics API supports it. + // If your engine doesn't support scissoring yet, you will get some small glitches (some elements outside their bounds) which you can fix later. MyEngineScissor((int)pcmd->ClipRect.x, (int)pcmd->ClipRect.y, (int)(pcmd->ClipRect.z - pcmd->ClipRect.x), (int)(pcmd->ClipRect.w - pcmd->ClipRect.y)); + + // Render 'pcmd->ElemCount/3' indexed triangles. + // By default the indices ImDrawIdx are 16-bits, you can change them to 32-bits if your engine doesn't support 16-bits indices. MyEngineDrawIndexedTriangles(pcmd->ElemCount, sizeof(ImDrawIdx) == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT, idx_buffer, vtx_buffer); } idx_buffer += pcmd->ElemCount; @@ -240,9 +250,15 @@ 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. Also read releases logs https://github.com/ocornut/imgui/releases for more details. + - 2017/10/24 (1.52) - renamed IMGUI_DISABLE_WIN32_DEFAULT_CLIPBOARD_FUNCS/IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCS to IMGUI_DISABLE_WIN32_DEFAULT_CLIPBOARD_FUNCTIONS/IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS for consistency. + - 2017/10/20 (1.52) - changed IsWindowHovered() default parameters behavior to return false if an item is active in another window (e.g. click-dragging item from another window to this window). You can use the newly introduced IsWindowHovered() flags to requests this specific behavior if you need it. + - 2017/10/20 (1.52) - marked IsItemHoveredRect()/IsMouseHoveringWindow() as obsolete, in favor of using the newly introduced flags for IsItemHovered() and IsWindowHovered(). See https://github.com/ocornut/imgui/issues/1382 for details. + removed the IsItemRectHovered()/IsWindowRectHovered() names introduced in 1.51 since they were merely more consistent names for the two functions we are now obsoleting. + - 2017/10/17 (1.52) - marked the old 5-parameters version of Begin() as obsolete (still available). Use SetNextWindowSize()+Begin() instead! + - 2017/10/11 (1.52) - renamed AlignFirstTextHeightToWidgets() to AlignTextToFramePadding(). Kept inline redirection function (will obsolete). - 2017/09/25 (1.52) - removed SetNextWindowPosCenter() because SetNextWindowPos() now has the optional pivot information to do the same and more. Kept redirection function (will obsolete). - 2017/08/25 (1.52) - io.MousePos needs to be set to ImVec2(-FLT_MAX,-FLT_MAX) when mouse is unavailable/missing. Previously ImVec2(-1,-1) was enough but we now accept negative mouse coordinates. In your binding if you need to support unavailable mouse, make sure to replace "io.MousePos = ImVec2(-1,-1)" with "io.MousePos = ImVec2(-FLT_MAX,-FLT_MAX)". - - 2017/08/22 (1.51) - renamed IsItemHoveredRect() to IsItemRectHovered(). Kept inline redirection function (will obsolete). + - 2017/08/22 (1.51) - renamed IsItemHoveredRect() to IsItemRectHovered(). Kept inline redirection function (will obsolete). -> (1.52) use IsItemHovered(ImGuiHoveredFlags_RectOnly)! - renamed IsMouseHoveringAnyWindow() to IsAnyWindowHovered() for consistency. Kept inline redirection function (will obsolete). - renamed IsMouseHoveringWindow() to IsWindowRectHovered() for consistency. Kept inline redirection function (will obsolete). - 2017/08/20 (1.51) - renamed GetStyleColName() to GetStyleColorName() for consistency. @@ -394,21 +410,22 @@ Also make sure your orthographic projection matrix and io.DisplaySize matches your actual framebuffer dimension. Q: I integrated Dear ImGui in my engine and some elements are clipping or disappearing when I move windows around.. - A: Most likely you are mishandling the clipping rectangles in your render function. Rectangles provided by ImGui are defined as (x1=left,y1=top,x2=right,y2=bottom) and NOT as (x1,y1,width,height). + A: You are probably mishandling the clipping rectangles in your render function. + Rectangles provided by ImGui are defined as (x1=left,y1=top,x2=right,y2=bottom) and NOT as (x1,y1,width,height). Q: Can I have multiple widgets with the same label? Can I have widget without a label? A: Yes. A primer on the use of labels/IDs in Dear ImGui.. - Elements that are not clickable, such as Text() items don't need an ID. - - Interactive widgets require state to be carried over multiple frames (most typically Dear ImGui often needs to remember what is the "active" widget). - to do so they need a unique ID. unique ID are typically derived from a string label, an integer index or a pointer. + - Interactive widgets require state to be carried over multiple frames (most typically Dear ImGui often needs to remember what is + the "active" widget). to do so they need a unique ID. unique ID are typically derived from a string label, an integer index or a pointer. Button("OK"); // Label = "OK", ID = hash of "OK" Button("Cancel"); // Label = "Cancel", ID = hash of "Cancel" - - ID are uniquely scoped within windows, tree nodes, etc. so no conflict can happen if you have two buttons called "OK" in two different windows - or in two different locations of a tree. + - ID are uniquely scoped within windows, tree nodes, etc. so no conflict can happen if you have two buttons called "OK" + in two different windows or in two different locations of a tree. - If you have a same ID twice in the same location, you'll have a conflict: @@ -417,8 +434,8 @@ Fear not! this is easy to solve and there are many ways to solve it! - - When passing a label you can optionally specify extra unique ID information within string itself. This helps solving the simpler collision cases. - use "##" to pass a complement to the ID that won't be visible to the end-user: + - When passing a label you can optionally specify extra unique ID information within string itself. + This helps solving the simpler collision cases. Use "##" to pass a complement to the ID that won't be visible to the end-user: Button("Play"); // Label = "Play", ID = hash of "Play" Button("Play##foo1"); // Label = "Play", ID = hash of "Play##foo1" (different from above) @@ -486,18 +503,22 @@ - When working with trees, ID are used to preserve the open/close state of each tree node. Depending on your use cases you may want to use strings, indices or pointers as ID. - e.g. when displaying a single object that may change over time (1-1 relationship), using a static string as ID will preserve your node open/closed state when the targeted object change. - e.g. when displaying a list of objects, using indices or pointers as ID will preserve the node open/closed state differently. experiment and see what makes more sense! + e.g. when displaying a single object that may change over time (dynamic 1-1 relationship), using a static string as ID will preserve your + node open/closed state when the targeted object change. + e.g. when displaying a list of objects, using indices or pointers as ID will preserve the node open/closed state differently. + experiment and see what makes more sense! Q: How can I tell when Dear ImGui wants my mouse/keyboard inputs VS when I can pass them to my application? A: You can read the 'io.WantCaptureMouse'/'io.WantCaptureKeyboard'/'ioWantTextInput' flags from the ImGuiIO structure. - When 'io.WantCaptureMouse' or 'io.WantCaptureKeyboard' flags are set you may want to discard/hide the inputs from the rest of your application. - - When 'io.WantTextInput' is set to may want to notify your OS to popup an on-screen keyboard, if available (e.g. on a mobile phone, or console without a keyboard). - Preferably read the flags after calling ImGui::NewFrame() to avoid them lagging by one frame. But reading those flags before calling NewFrame() is also generally ok, - as the bool toggles fairly rarely and you don't generally expect to interact with either Dear ImGui or your application during the same frame when that transition occurs. - Dear ImGui is tracking dragging and widget activity that may occur outside the boundary of a window, so 'io.WantCaptureMouse' is more accurate and correct than checking if a window is hovered. - (Advanced note: text input releases focus on Return 'KeyDown', so the following Return 'KeyUp' event that your application receive will typically have 'io.WantCaptureKeyboard=false'. - Depending on your application logic it may or not be inconvenient. You might want to track which key-downs were for Dear ImGui (e.g. with an array of bool) and filter out the corresponding key-ups.) + - When 'io.WantTextInput' is set to may want to notify your OS to popup an on-screen keyboard, if available (e.g. on a mobile phone, or console OS). + Preferably read the flags after calling ImGui::NewFrame() to avoid them lagging by one frame. But reading those flags before calling NewFrame() is + also generally ok, as the bool toggles fairly rarely and you don't generally expect to interact with either Dear ImGui or your application during + the same frame when that transition occurs. Dear ImGui is tracking dragging and widget activity that may occur outside the boundary of a window, + so 'io.WantCaptureMouse' is more accurate and correct than checking if a window is hovered. + (Advanced note: text input releases focus on Return 'KeyDown', so the following Return 'KeyUp' event that your application receive will typically + have 'io.WantCaptureKeyboard=false'. Depending on your application logic it may or not be inconvenient. You might want to track which key-downs + were for Dear ImGui, e.g. with an array of bool, and filter out the corresponding key-ups.) Q: How can I load a different font than the default? (default is an embedded version of ProggyClean.ttf, rendered at size 13) A: Use the font atlas to load the TTF/OTF file you want: @@ -507,8 +528,8 @@ io.Fonts->GetTexDataAsRGBA32() or GetTexDataAsAlpha8() Q: How can I easily use icons in my application? - A: The most convenient and practical way is to merge an icon font such as FontAwesome inside you main font. Then you can refer to icons within your strings. - Read 'How can I load multiple fonts?' and the file 'extra_fonts/README.txt' for instructions. + A: The most convenient and practical way is to merge an icon font such as FontAwesome inside you main font. Then you can refer to icons within your + strings. Read 'How can I load multiple fonts?' and the file 'extra_fonts/README.txt' for instructions and useful header files. Q: How can I load multiple fonts? A: Use the font atlas to pack them into a single texture: @@ -558,19 +579,24 @@ Otherwise you can convert yourself to UTF-8 or load text data from file already saved as UTF-8. Text input: it is up to your application to pass the right character code to io.AddInputCharacter(). The applications in examples/ are doing that. - For languages using IME, on Windows you can copy the Hwnd of your application to io.ImeWindowHandle. The default implementation of io.ImeSetInputScreenPosFn() on Windows will set your IME position correctly. + For languages using IME, on Windows you can copy the Hwnd of your application to io.ImeWindowHandle. + The default implementation of io.ImeSetInputScreenPosFn() on Windows will set your IME position correctly. Q: How can I preserve my Dear ImGui context across reloading a DLL? (loss of the global/static variables) - A: Create your own context 'ctx = CreateContext()' + 'SetCurrentContext(ctx)' and your own font atlas 'ctx->GetIO().Fonts = new ImFontAtlas()' so you don't rely on the default globals. + A: Create your own context 'ctx = CreateContext()' + 'SetCurrentContext(ctx)' and your own font atlas 'ctx->GetIO().Fonts = new ImFontAtlas()' + so you don't rely on the default globals. Q: How can I use the drawing facilities without an ImGui window? (using ImDrawList API) - A: The easiest way is to create a dummy window. Call Begin() with NoTitleBar|NoResize|NoMove|NoScrollbar|NoSavedSettings|NoInputs flag, zero background alpha, - then retrieve the ImDrawList* via GetWindowDrawList() and draw to it in any way you like. - You can also perfectly create a standalone ImDrawList instance _but_ you need ImGui to be initialized because ImDrawList pulls from ImGui data to retrieve the coordinates of the white pixel. + A: The easiest way is to create a dummy window. Call Begin() with NoTitleBar|NoResize|NoMove|NoScrollbar|NoSavedSettings|NoInputs flag, + zero background alpha, then retrieve the ImDrawList* via GetWindowDrawList() and draw to it in any way you like. + You can also perfectly create a standalone ImDrawList instance _but_ you need ImGui to be initialized because ImDrawList pulls from ImGui + data to retrieve the coordinates of the white pixel. - - tip: the construct 'IMGUI_ONCE_UPON_A_FRAME { ... }' will run the block of code only once a frame. You can use it to quickly add custom UI in the middle of a deep nested inner loop in your code. - - tip: you can create widgets without a Begin()/End() block, they will go in an implicit window called "Debug" - - tip: you can call Begin() multiple times with the same name during the same frame, it will keep appending to the same window. this is also useful to set yourself in the context of another window (to get/set other settings) + - tip: you can call Begin() multiple times with the same name during the same frame, it will keep appending to the same window. + this is also useful to set yourself in the context of another window (to get/set other settings) + - tip: you can create widgets without a Begin()/End() block, they will go in an implicit window called "Debug". + - tip: the ImGuiOnceUponAFrame helper will allow run the block of code only once a frame. You can use it to quickly add custom UI in the middle + of a deep nested inner loop in your code. - tip: you can call Render() multiple times (e.g for VR renders). - tip: call and read the ShowTestWindow() code in imgui_demo.cpp for more example of how to use ImGui! @@ -639,11 +665,10 @@ static void SetWindowScrollY(ImGuiWindow* window, float new_scroll_y static void SetWindowPos(ImGuiWindow* window, const ImVec2& pos, ImGuiCond cond); static void SetWindowSize(ImGuiWindow* window, const ImVec2& size, ImGuiCond cond); static void SetWindowCollapsed(ImGuiWindow* window, bool collapsed, ImGuiCond cond); -static ImGuiWindow* FindHoveredWindow(ImVec2 pos, bool excluding_childs); +static ImGuiWindow* FindHoveredWindow(ImVec2 pos); static ImGuiWindow* CreateNewWindow(const char* name, ImVec2 size, ImGuiWindowFlags flags); static void ClearSetNextWindowData(); static void CheckStacksSize(ImGuiWindow* window, bool write); -static void Scrollbar(ImGuiWindow* window, bool horizontal); static ImVec2 CalcNextScrollFromScrollTargetAndClamp(ImGuiWindow* window); static void AddDrawListToRenderList(ImVector& out_render_list, ImDrawList* draw_list); @@ -658,7 +683,7 @@ static void MarkIniSettingsDirty(ImGuiWindow* window); static ImRect GetVisibleRect(); -static void CloseInactivePopups(); +static void CloseInactivePopups(ImGuiWindow* ref_window); static void ClosePopupToLevel(int remaining); static ImGuiWindow* GetFrontMostModalRootWindow(); static ImVec2 FindBestPopupWindowPos(const ImVec2& base_pos, const ImVec2& size, int* last_dir, const ImRect& rect_to_avoid); @@ -672,6 +697,14 @@ static inline void DataTypeFormatString(ImGuiDataType data_type, void* data static void DataTypeApplyOp(ImGuiDataType data_type, int op, void* value1, const void* value2); static bool DataTypeApplyOpFromText(const char* buf, const char* initial_value_buf, ImGuiDataType data_type, void* data_ptr, const char* scalar_format); +namespace ImGui +{ +static void NavUpdate(); +static void NavUpdateWindowing(); +static void NavProcessItem(ImGuiWindow* window, const ImRect& nav_bb, const ImGuiID id); +static void FocusPreviousWindow(); +} + //----------------------------------------------------------------------------- // Platform dependent default implementations //----------------------------------------------------------------------------- @@ -732,58 +765,6 @@ ImGuiStyle::ImGuiStyle() ImGui::StyleColorsClassic(this); } -void ImGui::StyleColorsClassic(ImGuiStyle* dst) -{ - ImGuiStyle* style = dst ? dst : &ImGui::GetStyle(); - ImVec4* colors = style->Colors; - - colors[ImGuiCol_Text] = ImVec4(0.90f, 0.90f, 0.90f, 1.00f); - colors[ImGuiCol_TextDisabled] = ImVec4(0.60f, 0.60f, 0.60f, 1.00f); - colors[ImGuiCol_WindowBg] = ImVec4(0.00f, 0.00f, 0.00f, 0.70f); - colors[ImGuiCol_ChildWindowBg] = ImVec4(0.00f, 0.00f, 0.00f, 0.00f); - colors[ImGuiCol_PopupBg] = ImVec4(0.05f, 0.05f, 0.10f, 0.90f); - colors[ImGuiCol_Border] = ImVec4(0.70f, 0.70f, 0.70f, 0.40f); - colors[ImGuiCol_BorderShadow] = ImVec4(0.00f, 0.00f, 0.00f, 0.00f); - colors[ImGuiCol_FrameBg] = ImVec4(0.80f, 0.80f, 0.80f, 0.30f); // Background of checkbox, radio button, plot, slider, text input - colors[ImGuiCol_FrameBgHovered] = ImVec4(0.90f, 0.80f, 0.80f, 0.40f); - colors[ImGuiCol_FrameBgActive] = ImVec4(0.90f, 0.65f, 0.65f, 0.45f); - colors[ImGuiCol_TitleBg] = ImVec4(0.24f, 0.24f, 0.50f, 0.83f); - colors[ImGuiCol_TitleBgCollapsed] = ImVec4(0.40f, 0.40f, 0.80f, 0.20f); - colors[ImGuiCol_TitleBgActive] = ImVec4(0.33f, 0.33f, 0.65f, 0.87f); - colors[ImGuiCol_MenuBarBg] = ImVec4(0.40f, 0.40f, 0.55f, 0.80f); - colors[ImGuiCol_ScrollbarBg] = ImVec4(0.20f, 0.25f, 0.30f, 0.60f); - colors[ImGuiCol_ScrollbarGrab] = ImVec4(0.40f, 0.40f, 0.80f, 0.30f); - colors[ImGuiCol_ScrollbarGrabHovered] = ImVec4(0.40f, 0.40f, 0.80f, 0.40f); - colors[ImGuiCol_ScrollbarGrabActive] = ImVec4(0.80f, 0.50f, 0.50f, 0.40f); - colors[ImGuiCol_ComboBg] = ImVec4(0.20f, 0.20f, 0.20f, 0.99f); - colors[ImGuiCol_CheckMark] = ImVec4(0.90f, 0.90f, 0.90f, 0.50f); - colors[ImGuiCol_SliderGrab] = ImVec4(1.00f, 1.00f, 1.00f, 0.30f); - colors[ImGuiCol_SliderGrabActive] = ImVec4(0.80f, 0.50f, 0.50f, 1.00f); - colors[ImGuiCol_Button] = ImVec4(0.67f, 0.40f, 0.40f, 0.60f); - colors[ImGuiCol_ButtonHovered] = ImVec4(0.67f, 0.40f, 0.40f, 1.00f); - colors[ImGuiCol_ButtonActive] = ImVec4(0.80f, 0.50f, 0.50f, 1.00f); - colors[ImGuiCol_Header] = ImVec4(0.40f, 0.40f, 0.90f, 0.45f); - colors[ImGuiCol_HeaderHovered] = ImVec4(0.45f, 0.45f, 0.90f, 0.80f); - colors[ImGuiCol_HeaderActive] = ImVec4(0.53f, 0.53f, 0.87f, 0.80f); - colors[ImGuiCol_Separator] = ImVec4(0.50f, 0.50f, 0.50f, 1.00f); - colors[ImGuiCol_SeparatorHovered] = ImVec4(0.60f, 0.60f, 0.70f, 1.00f); - colors[ImGuiCol_SeparatorActive] = ImVec4(0.70f, 0.70f, 0.90f, 1.00f); - colors[ImGuiCol_ResizeGrip] = ImVec4(1.00f, 1.00f, 1.00f, 0.30f); - colors[ImGuiCol_ResizeGripHovered] = ImVec4(1.00f, 1.00f, 1.00f, 0.60f); - colors[ImGuiCol_ResizeGripActive] = ImVec4(1.00f, 1.00f, 1.00f, 0.90f); - colors[ImGuiCol_CloseButton] = ImVec4(0.50f, 0.50f, 0.90f, 0.50f); - colors[ImGuiCol_CloseButtonHovered] = ImVec4(0.70f, 0.70f, 0.90f, 0.60f); - colors[ImGuiCol_CloseButtonActive] = ImVec4(0.70f, 0.70f, 0.70f, 1.00f); - colors[ImGuiCol_PlotLines] = ImVec4(1.00f, 1.00f, 1.00f, 1.00f); - colors[ImGuiCol_PlotLinesHovered] = ImVec4(0.90f, 0.70f, 0.00f, 1.00f); - colors[ImGuiCol_PlotHistogram] = ImVec4(0.90f, 0.70f, 0.00f, 1.00f); - colors[ImGuiCol_PlotHistogramHovered] = ImVec4(1.00f, 0.60f, 0.00f, 1.00f); - colors[ImGuiCol_TextSelectedBg] = ImVec4(0.00f, 0.00f, 1.00f, 0.35f); - colors[ImGuiCol_ModalWindowDarkening] = ImVec4(0.20f, 0.20f, 0.20f, 0.35f); - colors[ImGuiCol_NavHighlight] = colors[ImGuiCol_HeaderHovered]; - colors[ImGuiCol_NavWindowingHighlight] = ImVec4(1.00f, 1.00f, 1.00f, 0.12f); -} - // To scale your entire UI (e.g. if you want your app to use High DPI or generally be DPI aware) you may use this helper function. Scaling the fonts is done separately and is up to you. // Tips: if you need to change your scale multiple times, prefer calling this on a freshly initialized ImGuiStyle structure rather than scaling multiple times (because floating point multiplications are lossy). void ImGuiStyle::ScaleAllSizes(float scale_factor) @@ -1020,15 +1001,18 @@ static const char* ImAtoi(const char* src, int* output) return src; } -// MSVC version appears to return -1 on overflow, whereas glibc appears to return total count (which may be >= buf_size). +// A) MSVC version appears to return -1 on overflow, whereas glibc appears to return total count (which may be >= buf_size). // Ideally we would test for only one of those limits at runtime depending on the behavior the vsnprintf(), but trying to deduct it at compile time sounds like a pandora can of worm. +// B) When buf==NULL vsnprintf() will return the output size. +#ifndef IMGUI_DISABLE_FORMAT_STRING_FUNCTIONS int ImFormatString(char* buf, int buf_size, const char* fmt, ...) { - IM_ASSERT(buf_size > 0); va_list args; va_start(args, fmt); int w = vsnprintf(buf, buf_size, fmt, args); va_end(args); + if (buf == NULL) + return w; if (w == -1 || w >= buf_size) w = buf_size - 1; buf[w] = 0; @@ -1037,13 +1021,15 @@ int ImFormatString(char* buf, int buf_size, const char* fmt, ...) int ImFormatStringV(char* buf, int buf_size, const char* fmt, va_list args) { - IM_ASSERT(buf_size > 0); int w = vsnprintf(buf, buf_size, fmt, args); + if (buf == NULL) + return w; if (w == -1 || w >= buf_size) w = buf_size - 1; buf[w] = 0; return w; } +#endif // #ifdef IMGUI_DISABLE_FORMAT_STRING_FUNCTIONS // Pass data_size==0 for zero-terminated strings // FIXME-OPT: Replace with e.g. FNV1a hash? CRC32 pretty much randomly access 1KB. Need to do proper measurements. @@ -1679,7 +1665,7 @@ void ImGuiTextBuffer::appendv(const char* fmt, va_list args) va_list args_copy; va_copy(args_copy, args); - int len = vsnprintf(NULL, 0, fmt, args); // FIXME-OPT: could do a first pass write attempt, likely successful on first pass. + int len = ImFormatStringV(NULL, 0, fmt, args); // FIXME-OPT: could do a first pass write attempt, likely successful on first pass. if (len <= 0) return; @@ -1692,7 +1678,7 @@ void ImGuiTextBuffer::appendv(const char* fmt, va_list args) } Buf.resize(needed_sz); - ImFormatStringV(&Buf[write_off] - 1, len+1, fmt, args_copy); + ImFormatStringV(&Buf[write_off - 1], len + 1, fmt, args_copy); } void ImGuiTextBuffer::append(const char* fmt, ...) @@ -1940,10 +1926,31 @@ ImGuiWindow* ImGui::GetParentWindow() return g.CurrentWindowStack[(unsigned int)g.CurrentWindowStack.Size - 2]; } +static void SetNavID(ImGuiID id, int nav_layer) +{ + ImGuiContext& g = *GImGui; + IM_ASSERT(g.NavWindow); + IM_ASSERT(nav_layer == 0 || nav_layer == 1); + g.NavId = id; + g.NavWindow->NavLastIds[nav_layer] = g.NavId; +} + +static void SetNavIDAndMoveMouse(ImGuiID id, int nav_layer, const ImRect& rect_rel) +{ + ImGuiContext& g = *GImGui; + SetNavID(id, nav_layer); + g.NavWindow->NavRectRel[nav_layer] = rect_rel; + g.NavMousePosDirty = true; + g.NavDisableHighlight = false; + g.NavDisableMouseHover = true; +} + void ImGui::SetActiveID(ImGuiID id, ImGuiWindow* window) { ImGuiContext& g = *GImGui; g.ActiveIdIsJustActivated = (g.ActiveId != id); + if (g.ActiveIdIsJustActivated) + g.ActiveIdTimer = 0.0f; g.ActiveId = id; g.ActiveIdAllowNavDirFlags = 0; g.ActiveIdAllowOverlap = false; @@ -1951,32 +1958,34 @@ void ImGui::SetActiveID(ImGuiID id, ImGuiWindow* window) if (id) { g.ActiveIdIsAlive = true; - g.ActiveIdSource = (g.NavActivateId == id || g.NavInputId == id || g.NavJustTabbedId == id || g.NavJustNavigatedId == id) ? ImGuiInputSource_Nav : ImGuiInputSource_Mouse; - if (g.ActiveIdSource == ImGuiInputSource_Nav) - g.NavDisableMouseHover = true; - else - g.NavDisableHighlight = true; - g.NavId = id; - if (window) - g.NavLayer = window->DC.NavLayerCurrent; - if (window) // NB: We current assume that SetActiveId() is called in the context where its NavLayer is the current one, which should be the case. - window->NavLastIds[window->DC.NavLayerCurrent] = id; + g.ActiveIdSource = (g.NavActivateId == id || g.NavInputId == id || g.NavJustTabbedId == id || g.NavJustMovedToId == id) ? ImGuiInputSource_Nav : ImGuiInputSource_Mouse; } } -void ImGui::SetActiveIDNoNav(ImGuiID id, ImGuiWindow* window) +ImGuiID ImGui::GetActiveID() { ImGuiContext& g = *GImGui; - g.ActiveIdIsJustActivated = (g.ActiveId != id); - g.ActiveId = id; - g.ActiveIdAllowNavDirFlags = 0; - g.ActiveIdAllowOverlap = false; - g.ActiveIdWindow = window; - if (id) - { - g.ActiveIdIsAlive = true; - g.ActiveIdSource = (g.NavActivateId == id || g.NavInputId == id) ? ImGuiInputSource_Nav : ImGuiInputSource_Mouse; - } + return g.ActiveId; +} + +void ImGui::SetFocusID(ImGuiID id, ImGuiWindow* window) +{ + IM_ASSERT(id != 0); + ImGuiContext& g = *GImGui; + + // Assume that SetActiveID() is called in the context where its NavLayer is the current layer, which is the case everywhere we call it. + const int nav_layer = window->DC.NavLayerCurrent; + g.NavId = id; + g.NavWindow = window; + g.NavLayer = nav_layer; + window->NavLastIds[nav_layer] = id; + if (window->DC.LastItemId == id) + window->NavRectRel[nav_layer] = ImRect(window->DC.LastItemRect.Min - window->Pos, window->DC.LastItemRect.Max - window->Pos); + + if (g.ActiveIdSource == ImGuiInputSource_Nav) + g.NavDisableMouseHover = true; + else + g.NavDisableHighlight = true; } void ImGui::ClearActiveID() @@ -1989,6 +1998,13 @@ void ImGui::SetHoveredID(ImGuiID id) ImGuiContext& g = *GImGui; g.HoveredId = id; g.HoveredIdAllowOverlap = false; + g.HoveredIdTimer = (id != 0 && g.HoveredIdPreviousFrame == id) ? (g.HoveredIdTimer + g.IO.DeltaTime) : 0.0f; +} + +ImGuiID ImGui::GetHoveredID() +{ + ImGuiContext& g = *GImGui; + return g.HoveredId ? g.HoveredId : g.HoveredIdPreviousFrame; } void ImGui::KeepAliveID(ImGuiID id) @@ -1998,15 +2014,22 @@ void ImGui::KeepAliveID(ImGuiID id) g.ActiveIdIsAlive = true; } -static inline bool IsWindowContentHoverable(ImGuiWindow* window) +static inline bool IsWindowContentHoverable(ImGuiWindow* window, ImGuiHoveredFlags flags) { // An active popup disable hovering on other windows (apart from its own children) // FIXME-OPT: This could be cached/stored within the window. ImGuiContext& g = *GImGui; if (g.NavWindow) if (ImGuiWindow* focused_root_window = g.NavWindow->RootWindow) - if ((focused_root_window->Flags & ImGuiWindowFlags_Popup) != 0 && focused_root_window->WasActive && focused_root_window != window->RootWindow) - return false; + if (focused_root_window->WasActive && focused_root_window != window->RootWindow) + { + // For the purpose of those flags we differentiate "standard popup" from "modal popup" + // NB: The order of those two tests is important because Modal windows are also Popups. + if (focused_root_window->Flags & ImGuiWindowFlags_Modal) + return false; + if ((focused_root_window->Flags & ImGuiWindowFlags_Popup) && !(flags & ImGuiHoveredFlags_AllowWhenBlockedByPopup)) + return false; + } return true; } @@ -2045,15 +2068,31 @@ void ImGui::ItemSize(const ImRect& bb, float text_offset_y) static ImGuiDir NavScoreItemGetQuadrant(float dx, float dy) { - if (fabsf(dx) > fabsf(dy)) + // Favor the axis which most separates the items + float fx = fabsf(dx); + float fy = fabsf(dy); + if (fx > fy) return (dx > 0.0f) ? ImGuiDir_Right : ImGuiDir_Left; - return (dy > 0.0f) ? ImGuiDir_Down : ImGuiDir_Up; + else if (fy > fx) + return (dy > 0.0f) ? ImGuiDir_Down : ImGuiDir_Up; + return ImGuiDir_None; } -static float NavScoreItemDistInterval(float a0, float a1, float b0, float b1) +static float NavScoreItemCenterDist(float a0, float a1, float b0, float b1) { + // Return the distance between the center of the two overlapping ranges + if ((a0 < b0 && a1 < b1) || (b0 < a0 && b1 < a1)) + return ((a0 + a1) - (b0 + b1)) / 2.0f; + // Return zero if one range contains the other (force a tie) + return 0.0f; +} + +static float NavScoreItemAxialDist(float a0, float a1, float b0, float b1) +{ + // Return the distance between the two non-overlapping ranges if (a1 < b0) return a1 - b0; if (b1 < a0) return a0 - b1; + // Return zero if ranges overlap (force a tie) return 0.0f; } @@ -2065,7 +2104,7 @@ static bool NavScoreItem(ImRect cand) if (g.NavLayer != window->DC.NavLayerCurrent) return false; - const ImRect& curr = g.NavScoringRectScreen; // Current modified source rect (NB: we've applied Max.x = Min.x in NavUpdate() to inhibit the effect of having varied item width) + const ImRect& curr = g.NavScoringRectScreen; // Current modified source rect // We perform scoring on items bounding box clipped by their parent window on the other axis (clipping on our movement axis would give us equal scores for all clipped items) if (g.NavMoveDir == ImGuiDir_Left || g.NavMoveDir == ImGuiDir_Right) @@ -2079,94 +2118,74 @@ static bool NavScoreItem(ImRect cand) cand.Max.x = ImClamp(cand.Max.x, window->ClipRect.Min.x, window->ClipRect.Max.x); } - // Compute distance between boxes - // FIXME-NAVIGATION: Introducing biases for vertical navigation, needs to be removed. - float dbx = NavScoreItemDistInterval(cand.Min.x, cand.Max.x, curr.Min.x, curr.Max.x); - float dby = NavScoreItemDistInterval(ImLerp(cand.Min.y, cand.Max.y, 0.2f), ImLerp(cand.Min.y, cand.Max.y, 0.8f), ImLerp(curr.Min.y, curr.Max.y, 0.2f), ImLerp(curr.Min.y, curr.Max.y, 0.8f)); // Scale down on Y to keep using box-distance for vertically touching items - if (dby && dbx) - dbx = (dbx/1000.0f) + ((dbx > 0.0f) ? +1.0f : -1.0f); - float dist_box = fabsf(dbx) + fabsf(dby); + // Bias the contribution of each axis to favor horizontal movements + // TODO perhaps this scale could be dynamic based on the currently + // selected items size + float sy = 5.0f; + float sx = 1.0f / sy; - // Compute distance between centers (this is off by a factor of 2, but we only compare center distances with each other so it doesn't matter) - float dcx = (cand.Min.x + cand.Max.x) - (curr.Min.x + curr.Max.x); - float dcy = (cand.Min.y + cand.Max.y) - (curr.Min.y + curr.Max.y); - float dist_center = fabsf(dcx) + fabsf(dcy); // L1 metric (need this for our connectedness guarantee) + // Calculate the distance between the two items on both axes + float dax = NavScoreItemAxialDist(cand.Min.x, cand.Max.x, curr.Min.x, curr.Max.x) * sx; + float day = NavScoreItemAxialDist(cand.Min.y, cand.Max.y, curr.Min.y, curr.Max.y) * sy; + float da = fabsf(dax) + fabsf(day); - // Determine which quadrant of 'curr' our candidate item 'cand' lies in based on distance - ImGuiDir quadrant; - float dax = 0.0f, day = 0.0f, dist_axial = 0.0f; - if (dbx || dby) - { - // For non-overlapping boxes, use distance between boxes - dax = dbx; - day = dby; - dist_axial = dist_box; - quadrant = NavScoreItemGetQuadrant(dbx, dby); - } - else if (dcx || dcy) - { - // For overlapping boxes with different centers, use distance between centers - dax = dcx; - day = dcy; - dist_axial = dist_center; - quadrant = NavScoreItemGetQuadrant(dcx, dcy); - } - else - { - // Degenerate case: two overlapping buttons with same center, break ties arbitrarily (note that LastItemId here is really the _previous_ item order, but it doesn't matter) - quadrant = (window->DC.LastItemId < g.NavId) ? ImGuiDir_Left : ImGuiDir_Right; - } + float dcx = NavScoreItemCenterDist(cand.Min.x, cand.Max.x, curr.Min.x, curr.Max.x) * sx; + float dcy = NavScoreItemCenterDist(cand.Min.y, cand.Max.y, curr.Min.y, curr.Max.y) * sy; + float dc = fabsf(dcx) + fabsf(dcy); + + // Determine which quadrant of curr the candidate lies is in based on the + // axial distance + ImGuiDir quadrant = NavScoreItemGetQuadrant(dax, day); + + // If no quadrant could be determined, the items are overlapping, use the + // center distance to attempt to resolve + if (quadrant == ImGuiDir_None) + quadrant = NavScoreItemGetQuadrant(dcx, dcy); + + // If still no quadrant could be detemined, these items must be centered on + // top of eachother, say the item is valid to move to + if (quadrant == ImGuiDir_None) + quadrant = g.NavMoveDir; #if IMGUI_DEBUG_NAV if (ImGui::IsMouseHoveringRect(cand.Min, cand.Max)) { char buf[128]; - ImFormatString(buf, IM_ARRAYSIZE(buf), "dbox (%.2f,%.2f->%.4f) dcen (%.2f,%.2f->%.4f) d (%.2f,%.2f->%.4f) nav %c, quad %c", dbx, dby, dist_box, dcx, dcy, dist_center, dax, day, dist_axial, "WENS"[g.NavMoveDir], "WENS"[quadrant]); + ImGui::PushFont(NULL); + ImFormatString(buf, IM_ARRAYSIZE(buf), "min(%.2f,%.2f)\nmax(%.2f,%.2f)\nda (%.2f,%.2f->%.4f)\ndc (%.2f,%.2f,->%.4f)\nnav %c, quad %c", + cand.Min.x, cand.Min.y, cand.Max.x, cand.Max.y, dax, day, da, dcx, dcy, dc, " WENS"[g.NavMoveDir + 1], " WENS"[quadrant + 1]); g.OverlayDrawList.AddRect(cand.Min, cand.Max, IM_COL32(255,255,0,200)); g.OverlayDrawList.AddRectFilled(cand.Max-ImVec2(4,4), cand.Max+ImGui::CalcTextSize(buf)+ImVec2(4,4), IM_COL32(40,0,0,150)); g.OverlayDrawList.AddText(cand.Max, ~0U, buf); + ImGui::PopFont(); } #endif // Is it in the quadrant we're interesting in moving to? bool new_best = false; + if (quadrant == g.NavMoveDir) { // Does it beat the current best candidate? - if (dist_box < g.NavMoveResultDistBox) + if (da < g.NavMoveResultDistAxial) { - g.NavMoveResultDistBox = dist_box; - g.NavMoveResultDistCenter = dist_center; - return true; - } - if (dist_box == g.NavMoveResultDistBox) - { - // Try using distance between center points to break ties - if (dist_center < g.NavMoveResultDistCenter) - { - g.NavMoveResultDistCenter = dist_center; - new_best = true; - } - else if (dist_center == g.NavMoveResultDistCenter) - { - // Still tied! we need to be extra-careful to make sure everything gets linked properly. We consistently break ties by symbolically moving "later" items - // (with higher index) to the right/downwards by an infinitesimal amount since we the current "best" button already (so it must have a lower index), - // this is fairly easy. This rule ensures that all buttons with dx==dy==0 will end up being linked in order of appearance along the x axis. - if (((g.NavMoveDir == ImGuiDir_Up || g.NavMoveDir == ImGuiDir_Down) ? dby : dbx) < 0.0f) // moving bj to the right/down decreases distance - new_best = true; - } + g.NavMoveResultDistAxial = da; + g.NavMoveResultDistCenter = dc; + new_best = true; + } + // There's a tie based on axial distance (items are adjacent), break the + // tie based on the distance between each item's center + else if (da == g.NavMoveResultDistAxial && dc < g.NavMoveResultDistCenter) + { + g.NavMoveResultDistCenter = dc; + new_best = true; } - } - // Axial check: if 'curr' has no link at all in some direction and 'cand' lies roughly in that direction, add a tentative link. This will only be kept if no "real" matches - // are found, so it only augments the graph produced by the above method using extra links. (important, since it doesn't guarantee strong connectedness) - // This is just to avoid buttons having no links in a particular direction when there's a suitable neighbor. you get good graphs without this too. - // 2017/09/29: FIXME: This now currently only enabled inside menubars, ideally we'd disable it everywhere. Menus in particular need to catch failure. For general navigation it feels awkward. - // Disabling it may however lead to disconnected graphs when nodes are very spaced out on different axis. Perhaps consider offering this as an option? - if (g.NavMoveResultDistBox == FLT_MAX && dist_axial < g.NavMoveResultDistAxial) // Check axial match - if (g.NavLayer == 1 && !(g.NavWindow->Flags & ImGuiWindowFlags_ChildMenu)) - if ((g.NavMoveDir == ImGuiDir_Left && dax < 0.0f) || (g.NavMoveDir == ImGuiDir_Right && dax > 0.0f) || (g.NavMoveDir == ImGuiDir_Up && day < 0.0f) || (g.NavMoveDir == ImGuiDir_Down && day > 0.0f)) - g.NavMoveResultDistAxial = dist_axial, new_best = true; + // If there is still a tie, ignore it, favoring the earliest item. The + // idea being that items are normally added in the order that we'd like + // to navigate (left to right and top to bottom) and that order should + // be preferred + } return new_best; } @@ -2184,13 +2203,15 @@ static void NavMoveRequestCancel() NavUpdateAnyRequestFlag(); } -static void NavProcessItem(ImGuiWindow* window, const ImRect& nav_bb, const ImGuiID id) +// We get there when either NavId == id, or when g.NavAnyRequest is set (which is updated by NavUpdateAnyRequestFlag above) +static void ImGui::NavProcessItem(ImGuiWindow* window, const ImRect& nav_bb, const ImGuiID id) { ImGuiContext& g = *GImGui; //if (!g.IO.NavUsable) // [2017/10/06] Removed this possibly redundant test but I am not sure of all the side-effects yet. Some of the feature here will need to work regardless of using a _NoNavInputs flag. // return; + const ImGuiItemFlags item_flags = window->DC.ItemFlags; - const ImRect nav_bb_rel(nav_bb.Min - g.NavWindow->Pos, nav_bb.Max - g.NavWindow->Pos); + const ImRect nav_bb_rel(nav_bb.Min - window->Pos, nav_bb.Max - window->Pos); if (g.NavInitRequest && g.NavLayer == window->DC.NavLayerCurrent) { // Even if 'ImGuiItemFlags_NoNavDefaultFocus' is on (typically collapse/close button) we record the first ResultId so they can be used as a fallback @@ -2207,7 +2228,7 @@ static void NavProcessItem(ImGuiWindow* window, const ImRect& nav_bb, const ImGu } // Scoring for navigation - if (g.NavId != id) + if (g.NavId != id && !(item_flags & ImGuiItemFlags_NoNav)) { #if IMGUI_DEBUG_NAV // [DEBUG] Score all items in NavWindow at all times @@ -2228,9 +2249,11 @@ static void NavProcessItem(ImGuiWindow* window, const ImRect& nav_bb, const ImGu // Update window-relative bounding box of navigated item if (g.NavId == id) { - window->NavRectRel[window->DC.NavLayerCurrent] = nav_bb_rel; + g.NavWindow = window; // Always refresh g.NavWindow, because some operations such as FocusItem() don't have a window. + g.NavLayer = window->DC.NavLayerCurrent; g.NavIdIsAlive = true; g.NavIdTabCounter = window->FocusIdxTabCounter; + window->NavRectRel[window->DC.NavLayerCurrent] = nav_bb_rel; // Store item bounding box (relative to window position) } } @@ -2250,7 +2273,7 @@ bool ImGui::ItemAdd(const ImRect& bb, ImGuiID id, const ImRect* nav_bb_arg) // it may not scale very well for windows with ten of thousands of item, but at least NavMoveRequest is only set on user interaction, aka maximum once a frame. // We could early out with "if (is_clipped && !g.NavInitRequest) return false;" but when we wouldn't be able to reach unclipped widgets. This would work if user had explicit scrolling control (e.g. mapped on a stick) window->DC.NavLayerActiveMaskNext |= window->DC.NavLayerCurrentMask; - if (g.NavWindow == window->RootNavWindow) + if (g.NavWindow && g.NavWindow->RootNavWindow == window->RootNavWindow) if (g.NavId == id || g.NavAnyRequest) NavProcessItem(window, nav_bb_arg ? *nav_bb_arg : bb, id); } @@ -2272,9 +2295,10 @@ bool ImGui::ItemAdd(const ImRect& bb, ImGuiID id, const ImRect* nav_bb_arg) return true; } -// This is roughly matching the behavior of internal-facing ItemHoverable() which is -// - we allow hovering to be true when ActiveId==window->MoveID, so that clicking on non-interactive items such as a Text() item still returns true with IsItemHovered()) -bool ImGui::IsItemHovered() +// This is roughly matching the behavior of internal-facing ItemHoverable() +// - we allow hovering to be true when ActiveId==window->MoveID, so that clicking on non-interactive items such as a Text() item still returns true with IsItemHovered() +// - this should work even for non-interactive items that have no ID, so we cannot use LastItemId +bool ImGui::IsItemHovered(ImGuiHoveredFlags flags) { ImGuiContext& g = *GImGui; @@ -2284,21 +2308,22 @@ bool ImGui::IsItemHovered() if (!window->DC.LastItemRectHoveredRect) return false; - if (g.HoveredWindow != window) + // [2017/10/16] Reverted commit 344d48be3 and testing RootWindow instead. I believe it is correct to NOT test for RootWindow but this leaves us unable to use IsItemHovered() after EndChild() itself. + // Until a solution is found I believe reverting to the test from 2017/09/27 is safe since this was the test that has been running for a long while. + //if (g.HoveredWindow != window) + // return false; + if (g.HoveredRootWindow != window->RootWindow && !(flags & ImGuiHoveredFlags_AllowWhenOverlapped)) return false; - if (g.ActiveId != 0 && g.ActiveId != window->DC.LastItemId && !g.ActiveIdAllowOverlap && g.ActiveId != window->MoveId) + if (!(flags & ImGuiHoveredFlags_AllowWhenBlockedByActiveItem)) + if (g.ActiveId != 0 && g.ActiveId != window->DC.LastItemId && !g.ActiveIdAllowOverlap && g.ActiveId != window->MoveId) + return false; + if (g.NavDisableMouseHover || !IsWindowContentHoverable(window, flags)) return false; - if (g.NavDisableMouseHover || !IsWindowContentHoverable(window)) + if (window->DC.ItemFlags & ImGuiItemFlags_Disabled) return false; return true; } -bool ImGui::IsItemRectHovered() -{ - ImGuiWindow* window = GetCurrentWindowRead(); - return window->DC.LastItemRectHoveredRect; -} - // Internal facing ItemHoverable() used when submitting widgets. Differs slightly from IsItemHovered(). bool ImGui::ItemHoverable(const ImRect& bb, ImGuiID id) { @@ -2313,7 +2338,9 @@ bool ImGui::ItemHoverable(const ImRect& bb, ImGuiID id) return false; if (!IsMouseHoveringRect(bb.Min, bb.Max)) return false; - if (g.NavDisableMouseHover || !IsWindowContentHoverable(window)) + if (g.NavDisableMouseHover || !IsWindowContentHoverable(window, ImGuiHoveredFlags_Default)) + return false; + if (window->DC.ItemFlags & ImGuiItemFlags_Disabled) return false; SetHoveredID(id); @@ -2335,7 +2362,7 @@ bool ImGui::FocusableItemRegister(ImGuiWindow* window, ImGuiID id, bool tab_stop { ImGuiContext& g = *GImGui; - const bool allow_keyboard_focus = (window->DC.ItemFlags & ImGuiItemFlags_AllowKeyboardFocus) != 0; + const bool allow_keyboard_focus = (window->DC.ItemFlags & (ImGuiItemFlags_AllowKeyboardFocus | ImGuiItemFlags_Disabled)) == ImGuiItemFlags_AllowKeyboardFocus; window->FocusIdxAllCounter++; if (allow_keyboard_focus) window->FocusIdxTabCounter++; @@ -2480,25 +2507,6 @@ int ImGui::GetFrameCount() return GImGui->FrameCount; } -static void SetNavId(ImGuiID id, int nav_layer) -{ - ImGuiContext& g = *GImGui; - IM_ASSERT(g.NavWindow); - IM_ASSERT(nav_layer == 0 || nav_layer == 1); - g.NavId = id; - g.NavWindow->NavLastIds[nav_layer] = g.NavId; -} - -static void SetNavIdAndMoveMouse(ImGuiID id, int nav_layer, const ImRect& rect_rel) -{ - ImGuiContext& g = *GImGui; - SetNavId(id, nav_layer); - g.NavWindow->NavRectRel[nav_layer] = rect_rel; - g.NavMousePosDirty = true; - g.NavDisableHighlight = false; - g.NavDisableMouseHover = true; -} - // This needs to be called before we submit any widget (aka in or before Begin) static void NavInitWindow(ImGuiWindow* window, bool force_reinit) { @@ -2506,15 +2514,16 @@ static void NavInitWindow(ImGuiWindow* window, bool force_reinit) IM_ASSERT(window == g.NavWindow); bool init_for_nav = false; if (!(window->Flags & ImGuiWindowFlags_NoNavInputs)) - if (!(window->Flags & ImGuiWindowFlags_ChildWindow) || (window->Flags & ImGuiWindowFlags_Popup) || (window->NavLastIds[0] == 0) || force_reinit) + if ((window->Flags & ImGuiWindowFlags_Popup) || (window->NavLastIds[0] == 0) || force_reinit) init_for_nav = true; if (init_for_nav) { - SetNavId(0, g.NavLayer); + SetNavID(0, g.NavLayer); g.NavInitRequest = true; g.NavInitResultId = 0; g.NavInitResultExplicit = false; g.NavInitResultRectRel = ImRect(); + g.NavDisableHighlight = false; NavUpdateAnyRequestFlag(); } else @@ -2560,6 +2569,7 @@ enum ImGuiNavReadMode { ImGuiNavReadMode_Down, ImGuiNavReadMode_Pressed, + ImGuiNavReadMode_Released, ImGuiNavReadMode_Repeat, ImGuiNavReadMode_RepeatSlow, ImGuiNavReadMode_RepeatFast @@ -2574,6 +2584,8 @@ static float GetNavInputAmount(ImGuiNavInput n, ImGuiNavReadMode mode) const float t = g.IO.NavInputsDownDuration[n]; // Duration pressed if (mode == ImGuiNavReadMode_Pressed) // Return 1.0f when just pressed, no repeat, ignore analog input (we don't need it for Pressed logic) return (t == 0.0f) ? 1.0f : 0.0f; + if (mode == ImGuiNavReadMode_Released) // Return 1.0f when just release, no repeat, ignore analog input (we don't need it for Pressed logic) + return (t < 0.0f && g.IO.NavInputsDownDurationPrev[n] >= 0.0f) ? 1.0f : 0.0f; if (mode == ImGuiNavReadMode_Repeat) return (float)ImGui::CalcTypematicPressedRepeatAmount(t, t - g.IO.DeltaTime, g.IO.KeyRepeatDelay * 0.80f, g.IO.KeyRepeatRate * 0.80f); if (mode == ImGuiNavReadMode_RepeatSlow) @@ -2610,7 +2622,138 @@ static ImVec2 GetNavInputAmount2d(int stick_no, ImGuiNavReadMode mode, float slo return delta; } -static void NavUpdate() +// Window management mode (change focus, move/resize window, toggle menu layer) +static void ImGui::NavUpdateWindowing() +{ + ImGuiContext& g = *GImGui; + bool toggle_layer = false; + + if (!g.NavWindowingTarget && IsNavInputPressed(ImGuiNavInput_PadMenu, ImGuiNavReadMode_Pressed)) + { + ImGuiWindow* window = g.NavWindow; + if (!window) + window = FindWindowNavigable(g.Windows.Size - 1, -1, -1); + if (window) + { + g.NavWindowingTarget = window->RootNonPopupWindow; + g.NavWindowingDisplayAlpha = 0.0f; + g.NavWindowingToggleLayer = true; + } + } + if (g.NavWindowingTarget) + { + // Visuals only appears after a brief time holding the button, so that a fast tap (to toggle NavLayer) doesn't add visual noise + const float pressed_duration = g.IO.NavInputsDownDuration[ImGuiNavInput_PadMenu]; + g.NavWindowingDisplayAlpha = ImMax(g.NavWindowingDisplayAlpha, ImSaturate((pressed_duration - 0.20f) / 0.05f)); + g.NavWindowingToggleLayer &= (g.NavWindowingDisplayAlpha < 1.0f); // Once button is held long enough we don't consider it a tag-to-toggle-layer press anymore. + + // Select window to focus + const int focus_change_dir = (int)IsNavInputPressed(ImGuiNavInput_PadFocusPrev, ImGuiNavReadMode_RepeatSlow) - (int)IsNavInputPressed(ImGuiNavInput_PadFocusNext, ImGuiNavReadMode_RepeatSlow); + if (focus_change_dir != 0 && !(g.NavWindowingTarget->Flags & ImGuiWindowFlags_Modal)) + { + const int i_current = FindWindowIndex(g.NavWindowingTarget); + ImGuiWindow* window_target = FindWindowNavigable(i_current + focus_change_dir, -1, focus_change_dir); + if (!window_target) + window_target = FindWindowNavigable((focus_change_dir < 0) ? (g.Windows.Size - 1) : 0, i_current, focus_change_dir); + g.NavWindowingTarget = window_target; + g.NavWindowingToggleLayer = false; + g.NavWindowingDisplayAlpha = 1.0f; + } + + // Move window + if (g.NavWindowingTarget && !(g.NavWindowingTarget->Flags & ImGuiWindowFlags_NoMove)) + { + const ImVec2 move_delta = GetNavInputAmount2d(1, ImGuiNavReadMode_Down); + if (move_delta.x != 0.0f || move_delta.y != 0.0f) + { + const float move_speed = ImFloor(600 * g.IO.DeltaTime * ImMin(g.IO.DisplayFramebufferScale.x, g.IO.DisplayFramebufferScale.y)); + g.NavWindowingTarget->PosFloat += move_delta * move_speed; + g.NavDisableMouseHover = true; + MarkIniSettingsDirty(g.NavWindowingTarget); + } + } + + if (!IsNavInputDown(ImGuiNavInput_PadMenu)) + { + // Apply actual focus only when releasing the NavMenu button (until then the window was merely rendered front-most) + if (g.NavWindowingTarget && !g.NavWindowingToggleLayer && (!g.NavWindow || g.NavWindowingTarget != g.NavWindow->RootNonPopupWindow)) + { + FocusWindow(g.NavWindowingTarget); + g.NavDisableHighlight = false; + g.NavDisableMouseHover = true; + if (g.NavWindowingTarget->NavLastIds[0] == 0) + NavInitWindow(g.NavWindowingTarget, false); + + // If the window only has a menu layer, select it directly + if (g.NavWindowingTarget->DC.NavLayerActiveMask == 0x02) + g.NavLayer = 1; + } + + // Single press toggles NavLayer + if (g.NavWindowingToggleLayer && g.NavWindow) + toggle_layer = true; + g.NavWindowingTarget = NULL; + } + } + + // Keyboard: Press and release ALT to toggle menu + if ((g.ActiveId == 0 || g.ActiveIdAllowOverlap) && IsNavInputPressed(ImGuiNavInput_KeyMenu, ImGuiNavReadMode_Released)) + toggle_layer = true; + + if (toggle_layer && g.NavWindow) + { + if ((g.NavWindow->DC.NavLayerActiveMask & (1 << 1)) == 0 && (g.NavWindow->RootWindow->DC.NavLayerActiveMask & (1 << 1)) != 0) + FocusWindow(g.NavWindow->RootWindow); + g.NavLayer = (g.NavWindow->DC.NavLayerActiveMask & (1 << 1)) ? (g.NavLayer ^ 1) : 0; + g.NavDisableHighlight = false; + g.NavDisableMouseHover = true; + if (g.NavLayer == 0 && g.NavWindow->NavLastIds[0] != 0) + SetNavIDAndMoveMouse(g.NavWindow->NavLastIds[0], g.NavLayer, ImRect()); + else + NavInitWindow(g.NavWindow, true); + } +} + +// NB: We modify rect_rel by the amount we scrolled for, so it is immediately updated. +static void NavScrollToBringItemIntoView(ImGuiWindow* window, ImRect& item_rect_rel) +{ + if (window->Flags & ImGuiWindowFlags_NoNavScroll) + return; + + // Scroll to keep newly navigated item fully into view + ImRect window_rect_rel(window->InnerRect.Min - window->Pos - ImVec2(1, 1), window->InnerRect.Max - window->Pos + ImVec2(1, 1)); + //g.OverlayDrawList.AddRect(window->Pos + window_rect_rel.Min, window->Pos + window_rect_rel.Max, IM_COL32_WHITE); // [DEBUG] + if (window_rect_rel.Contains(item_rect_rel)) + return; + + ImGuiContext& g = *GImGui; + if (window->ScrollbarX && item_rect_rel.Min.x < window_rect_rel.Min.x) + { + window->ScrollTarget.x = item_rect_rel.Min.x + window->Scroll.x - g.Style.ItemSpacing.x; + window->ScrollTargetCenterRatio.x = 0.0f; + } + else if (window->ScrollbarX && item_rect_rel.Max.x >= window_rect_rel.Max.x) + { + window->ScrollTarget.x = item_rect_rel.Max.x + window->Scroll.x + g.Style.ItemSpacing.x; + window->ScrollTargetCenterRatio.x = 1.0f; + } + if (item_rect_rel.Min.y < window_rect_rel.Min.y) + { + window->ScrollTarget.y = item_rect_rel.Min.y + window->Scroll.y - g.Style.ItemSpacing.y; + window->ScrollTargetCenterRatio.y = 0.0f; + } + else if (item_rect_rel.Max.y >= window_rect_rel.Max.y) + { + window->ScrollTarget.y = item_rect_rel.Max.y + window->Scroll.y + g.Style.ItemSpacing.y; + window->ScrollTargetCenterRatio.y = 1.0f; + } + + // Estimate upcoming scroll so we can offset our relative mouse position so mouse position can be applied immediately (under this block) + ImVec2 next_scroll = CalcNextScrollFromScrollTargetAndClamp(window); + item_rect_rel.Translate(window->Scroll - next_scroll); +} + +static void ImGui::NavUpdate() { ImGuiContext& g = *GImGui; g.IO.WantMoveMouse = false; @@ -2618,59 +2761,43 @@ static void NavUpdate() // Process navigation init request (select first/default focus) if (g.NavInitResultId != 0 && (!g.NavDisableHighlight || g.NavInitResultExplicit)) { - // Apply result from previous navigation init request (typically select the first item, unless SetItemDefaultFocus() has been called) + // Apply result from previous navigation init request (will typically select the first item, unless SetItemDefaultFocus() has been called) IM_ASSERT(g.NavWindow); - SetNavId(g.NavInitResultId, g.NavLayer); + SetNavID(g.NavInitResultId, g.NavLayer); g.NavWindow->NavRectRel[g.NavLayer] = g.NavInitResultRectRel; if (g.NavDisableMouseHover) g.NavMousePosDirty = true; + g.NavIdIsAlive = true; } g.NavInitRequest = false; g.NavInitResultExplicit = false; g.NavInitResultId = 0; - g.NavJustNavigatedId = 0; + g.NavJustMovedToId = 0; + + // Keep something focused + if (g.NavWindow && !g.NavIdIsAlive) + { + SetNavID(0, g.NavLayer); + g.NavInitRequest = true; + g.NavInitResultId = 0; + g.NavInitResultExplicit = false; + g.NavInitResultRectRel = ImRect(); + g.NavDisableHighlight = false; + NavUpdateAnyRequestFlag(); + } // Process navigation move request if (g.NavMoveRequest && g.NavMoveResultId != 0) { - IM_ASSERT(g.NavWindow); - ImGuiWindow* window = g.NavWindow; - // Scroll to keep newly navigated item fully into view - ImRect window_rect_rel(window->InnerRect.Min - window->Pos - ImVec2(1,1), window->InnerRect.Max - window->Pos + ImVec2(1,1)); - //g.OverlayDrawList.AddRect(window->Pos + window_rect_rel.Min, window->Pos + window_rect_rel.Max, IM_COL32_WHITE); // [DEBUG] - if (g.NavLayer == 0 && !window_rect_rel.Contains(g.NavMoveResultRectRel)) - { - if (window->ScrollbarX && g.NavMoveResultRectRel.Min.x < window_rect_rel.Min.x) - { - window->ScrollTarget.x = g.NavMoveResultRectRel.Min.x + window->Scroll.x - g.Style.ItemSpacing.x; - window->ScrollTargetCenterRatio.x = 0.0f; - } - else if (window->ScrollbarX && g.NavMoveResultRectRel.Max.x >= window_rect_rel.Max.x) - { - window->ScrollTarget.x = g.NavMoveResultRectRel.Max.x + window->Scroll.x + g.Style.ItemSpacing.x; - window->ScrollTargetCenterRatio.x = 1.0f; - } - if (g.NavMoveResultRectRel.Min.y < window_rect_rel.Min.y) - { - window->ScrollTarget.y = g.NavMoveResultRectRel.Min.y + window->Scroll.y - g.Style.ItemSpacing.y; - window->ScrollTargetCenterRatio.y = 0.0f; - } - else if (g.NavMoveResultRectRel.Max.y >= window_rect_rel.Max.y) - { - window->ScrollTarget.y = g.NavMoveResultRectRel.Max.y + window->Scroll.y + g.Style.ItemSpacing.y; - window->ScrollTargetCenterRatio.y = 1.0f; - } - - // Estimate upcoming scroll so we can offset our relative mouse position so mouse position can be applied immediately (under this block) - ImVec2 next_scroll = CalcNextScrollFromScrollTargetAndClamp(window); - g.NavMoveResultRectRel.Translate(window->Scroll - next_scroll); - } + IM_ASSERT(g.NavWindow); + if (g.NavLayer == 0) + NavScrollToBringItemIntoView(g.NavWindow, g.NavMoveResultRectRel); // Apply result from previous frame navigation directional move request - ImGui::ClearActiveID(); - SetNavIdAndMoveMouse(g.NavMoveResultId, g.NavLayer, g.NavMoveResultRectRel); - g.NavJustNavigatedId = g.NavMoveResultId; + ClearActiveID(); + SetNavIDAndMoveMouse(g.NavMoveResultId, g.NavLayer, g.NavMoveResultRectRel); + g.NavJustMovedToId = g.NavMoveResultId; g.NavMoveFromClampedRefRect = false; } @@ -2696,102 +2823,30 @@ static void NavUpdate() } g.NavIdIsAlive = false; g.NavJustTabbedId = 0; - - // Navigation windowing mode (change focus, move/resize window) - if (!g.NavWindowingTarget && IsNavInputPressed(ImGuiNavInput_PadMenu, ImGuiNavReadMode_Pressed)) - { - ImGuiWindow* window = g.NavWindow; - if (!window) - window = FindWindowNavigable(g.Windows.Size-1, -1, -1); - if (window) - { - g.NavWindowingTarget = window->RootNonPopupWindow; - g.NavWindowingDisplayAlpha = 0.0f; - g.NavWindowingToggleLayer = true; - } - } - if (g.NavWindowingTarget) - { - // Visuals only appears after a brief time holding the button, so that a fast tap (to toggle NavLayer) doesn't add visual noise - const float pressed_duration = g.IO.NavInputsDownDuration[ImGuiNavInput_PadMenu]; - g.NavWindowingDisplayAlpha = ImMax(g.NavWindowingDisplayAlpha, ImSaturate((pressed_duration - 0.20f) / 0.05f)); - g.NavWindowingToggleLayer &= (g.NavWindowingDisplayAlpha < 1.0f); // Once button is held long enough we don't consider it a tag-to-toggle-layer press anymore. - - // Select window to focus - const int focus_change_dir = (int)IsNavInputPressed(ImGuiNavInput_PadFocusPrev, ImGuiNavReadMode_RepeatSlow) - (int)IsNavInputPressed(ImGuiNavInput_PadFocusNext, ImGuiNavReadMode_RepeatSlow); - if (focus_change_dir != 0 && !(g.NavWindowingTarget->Flags & ImGuiWindowFlags_Modal)) - { - const int i_current = FindWindowIndex(g.NavWindowingTarget); - ImGuiWindow* window_target = FindWindowNavigable(i_current + focus_change_dir, -1, focus_change_dir); - if (!window_target) - window_target = FindWindowNavigable((focus_change_dir < 0) ? (g.Windows.Size-1) : 0, i_current, focus_change_dir); - g.NavWindowingTarget = window_target; - g.NavWindowingToggleLayer = false; - g.NavWindowingDisplayAlpha = 1.0f; - } - - // Move window - if (g.NavWindowingTarget && !(g.NavWindowingTarget->Flags & ImGuiWindowFlags_NoMove)) - { - const ImVec2 move_delta = GetNavInputAmount2d(1, ImGuiNavReadMode_Down); - if (move_delta.x != 0.0f || move_delta.y != 0.0f) - { - const float move_speed = ImFloor(600 * g.IO.DeltaTime * ImMin(g.IO.DisplayFramebufferScale.x, g.IO.DisplayFramebufferScale.y)); - g.NavWindowingTarget->PosFloat += move_delta * move_speed; - g.NavDisableMouseHover = true; - MarkIniSettingsDirty(g.NavWindowingTarget); - } - } - - if (!IsNavInputDown(ImGuiNavInput_PadMenu)) - { - // Apply actual focus only when releasing the NavMenu button (until then the window was merely rendered front-most) - if (g.NavWindowingTarget && !g.NavWindowingToggleLayer && (!g.NavWindow || g.NavWindowingTarget != g.NavWindow->RootNonPopupWindow)) - { - ImGui::FocusWindow(g.NavWindowingTarget); - g.NavDisableHighlight = false; - g.NavDisableMouseHover = true; - if (g.NavWindowingTarget->NavLastIds[0] == 0) - NavInitWindow(g.NavWindowingTarget, false); - } - - // Single press toggles NavLayer - if (g.NavWindowingToggleLayer && g.NavWindow) - { - if ((g.NavWindow->DC.NavLayerActiveMask & (1<<1)) == 0 && (g.NavWindow->RootWindow->DC.NavLayerActiveMask & (1<<1)) != 0) - ImGui::FocusWindow(g.NavWindow->RootWindow); - g.NavLayer = (g.NavWindow->DC.NavLayerActiveMask & (1<<1)) ? (g.NavLayer ^ 1) : 0; - g.NavDisableHighlight = false; - g.NavDisableMouseHover = true; - if (g.NavLayer == 0 && g.NavWindow->NavLastIds[0] != 0) - SetNavIdAndMoveMouse(g.NavWindow->NavLastIds[0], g.NavLayer, ImRect()); - else - NavInitWindow(g.NavWindow, true); - } - g.NavWindowingTarget = NULL; - } - } IM_ASSERT(g.NavLayer == 0 || g.NavLayer == 1); + NavUpdateWindowing(); + // Set output flags for user application g.IO.NavUsable = g.NavWindow && !(g.NavWindow->Flags & ImGuiWindowFlags_NoNavInputs); g.IO.NavActive = (g.IO.NavUsable && g.NavId != 0 && !g.NavDisableHighlight) || (g.NavWindowingTarget != NULL) || g.NavInitRequest; // Process NavCancel input (to close a popup, get back to parent, clear focus) - if (IsNavInputPressed(ImGuiNavInput_PadCancel, ImGuiNavReadMode_Pressed)) + bool nav_focus_supported = !g.NavWindow || (g.NavWindow && !(g.NavWindow->Flags & ImGuiWindowFlags_NoNavFocus)); + if (nav_focus_supported && IsNavInputPressed(ImGuiNavInput_PadCancel, ImGuiNavReadMode_Pressed)) { if (g.ActiveId != 0) { - ImGui::ClearActiveID(); + ClearActiveID(); } else if (g.NavWindow && (g.NavWindow->Flags & ImGuiWindowFlags_ChildWindow) && !(g.NavWindow->Flags & ImGuiWindowFlags_Popup) && g.NavWindow->ParentWindow) { // Exit child window ImGuiWindow* child_window = g.NavWindow; ImGuiWindow* parent_window = g.NavWindow->ParentWindow; - ImGui::FocusWindow(parent_window); + FocusWindow(parent_window); IM_ASSERT(child_window->ChildId != 0); - SetNavId(child_window->ChildId, g.NavLayer); // FIXME-NAV: Layer not necessarily correct + SetNavID(child_window->ChildId, g.NavLayer); // FIXME-NAV: Layer not necessarily correct g.NavIdIsAlive = false; if (g.NavDisableMouseHover) g.NavMousePosDirty = true; @@ -2806,7 +2861,7 @@ static void NavUpdate() // Leave the "menu" layer g.NavLayer = 0; if (g.NavWindow->NavLastIds[0]) - SetNavIdAndMoveMouse(g.NavWindow->NavLastIds[0], g.NavLayer, ImRect()); + SetNavIDAndMoveMouse(g.NavWindow->NavLastIds[0], g.NavLayer, ImRect()); else NavInitWindow(g.NavWindow, true); } @@ -2885,7 +2940,7 @@ static void NavUpdate() // *Fallback* manual-scroll with NavUp/NavDown when window has no navigable item ImGuiWindow* window = g.NavWindow; const float scroll_speed = ImFloor(window->CalcFontSize() * 100 * g.IO.DeltaTime + 0.5f); // We need round the scrolling speed because sub-pixel scroll isn't reliably supported. - if (!window->DC.NavLayerActiveMask && window->DC.NavHasScroll && g.NavMoveRequest) + if (window->DC.NavLayerActiveMask == 0x00 && window->DC.NavHasScroll && g.NavMoveRequest) { if (g.NavMoveDir == ImGuiDir_Left || g.NavMoveDir == ImGuiDir_Right) SetWindowScrollX(window, ImFloor(window->Scroll.x + ((g.NavMoveDir == ImGuiDir_Left) ? -1.0f : +1.0f) * scroll_speed)); @@ -2894,6 +2949,7 @@ static void NavUpdate() } // *Normal* Manual scroll with NavScrollXXX keys + // Next movement request will clamp the NavId reference rectangle to the visible area, so navigation will resume within those bounds. ImVec2 scroll_dir = GetNavInputAmount2d(1, ImGuiNavReadMode_Down, 1.0f/10.0f, 10.0f); if (scroll_dir.x != 0.0f && window->ScrollbarX) { @@ -2910,9 +2966,9 @@ static void NavUpdate() // Reset search g.NavMoveResultId = 0; g.NavMoveResultParentId = 0; - g.NavMoveResultDistAxial = g.NavMoveResultDistBox = g.NavMoveResultDistCenter = FLT_MAX; + g.NavMoveResultDistAxial = g.NavMoveResultDistCenter = FLT_MAX; - // When we have manually scrolled (without using navigation) and NavId becomes out of bounds, we clamp its bounding box (used for search) to the visible area to restart navigation within visible items + // When we have manually scrolled (without using navigation) and NavId becomes out of bounds, we project its bounding box to the visible area to restart navigation within visible items if (g.NavMoveRequest && g.NavMoveFromClampedRefRect && g.NavLayer == 0) { ImGuiWindow* window = g.NavWindow; @@ -2927,10 +2983,7 @@ static void NavUpdate() g.NavMoveFromClampedRefRect = false; } - // For scoring we use a single segment on the left side our current item bounding box (not touching the edge to avoid box overlap with zero-spaced items) g.NavScoringRectScreen = g.NavWindow ? ImRect(g.NavWindow->Pos + g.NavWindow->NavRectRel[g.NavLayer].Min, g.NavWindow->Pos + g.NavWindow->NavRectRel[g.NavLayer].Max) : ImRect(); - g.NavScoringRectScreen.Min.x = ImMin(g.NavScoringRectScreen.Min.x + 1.0f, g.NavScoringRectScreen.Max.x); - g.NavScoringRectScreen.Max.x = g.NavScoringRectScreen.Min.x; //g.OverlayDrawList.AddRect(g.NavScoringRectScreen.Min, g.NavScoringRectScreen.Max, IM_COL32(255,200,0,255)); // [DEBUG] //if (g.NavWindow) for (int layer = 0; layer < 2; layer++) g.OverlayDrawList.AddRect(g.NavWindow->Pos + g.NavWindow->NavRectRel[layer].Min, g.NavWindow->Pos + g.NavWindow->NavRectRel[layer].Max, IM_COL32(255,200,0,255)); // [DEBUG] } @@ -2949,7 +3002,7 @@ void ImGui::NewFrame() // Initialize on first frame if (!g.Initialized) - ImGui::Initialize(); + Initialize(); SetCurrentFont(GetDefaultFont()); IM_ASSERT(g.Font->IsLoaded()); @@ -2967,11 +3020,15 @@ void ImGui::NewFrame() g.RenderDrawData.CmdListsCount = g.RenderDrawData.TotalVtxCount = g.RenderDrawData.TotalIdxCount = 0; // Clear reference to active widget if the widget isn't alive anymore + if (!g.HoveredIdPreviousFrame) + g.HoveredIdTimer = 0.0f; g.HoveredIdPreviousFrame = g.HoveredId; g.HoveredId = 0; g.HoveredIdAllowOverlap = false; if (!g.ActiveIdIsAlive && g.ActiveIdPreviousFrame == g.ActiveId && g.ActiveId != 0) ClearActiveID(); + if (g.ActiveId) + g.ActiveIdTimer += g.IO.DeltaTime; g.ActiveIdPreviousFrame = g.ActiveId; g.ActiveIdIsAlive = false; g.ActiveIdIsJustActivated = false; @@ -2982,7 +3039,7 @@ void ImGui::NewFrame() memcpy(g.IO.KeysDownDurationPrev, g.IO.KeysDownDuration, sizeof(g.IO.KeysDownDuration)); for (int i = 0; i < IM_ARRAYSIZE(g.IO.KeysDown); i++) g.IO.KeysDownDuration[i] = g.IO.KeysDown[i] ? (g.IO.KeysDownDuration[i] < 0.0f ? 0.0f : g.IO.KeysDownDuration[i] + g.IO.DeltaTime) : -1.0f; - memcpy(g.IO.NavInputsPrev, g.IO.NavInputs, sizeof(g.IO.NavInputs)); + memcpy(g.IO.NavInputsDownDurationPrev, g.IO.NavInputsDownDuration, sizeof(g.IO.NavInputsDownDuration)); for (int i = 0; i < IM_ARRAYSIZE(g.IO.NavInputs); i++) g.IO.NavInputsDownDuration[i] = (g.IO.NavInputs[i] > 0.0f) ? (g.IO.NavInputsDownDuration[i] < 0.0f ? 0.0f : g.IO.NavInputsDownDuration[i] + g.IO.DeltaTime) : -1.0f; @@ -3019,11 +3076,15 @@ void ImGui::NewFrame() g.IO.MouseClickedTime[i] = g.Time; } g.IO.MouseClickedPos[i] = g.IO.MousePos; + g.IO.MouseDragMaxDistanceAbs[i] = ImVec2(0.0f, 0.0f); g.IO.MouseDragMaxDistanceSqr[i] = 0.0f; } else if (g.IO.MouseDown[i]) { - g.IO.MouseDragMaxDistanceSqr[i] = ImMax(g.IO.MouseDragMaxDistanceSqr[i], ImLengthSqr(g.IO.MousePos - g.IO.MouseClickedPos[i])); + ImVec2 mouse_delta = g.IO.MousePos - g.IO.MouseClickedPos[i]; + g.IO.MouseDragMaxDistanceAbs[i].x = ImMax(g.IO.MouseDragMaxDistanceAbs[i].x, mouse_delta.x < 0.0f ? -mouse_delta.x : mouse_delta.x); + g.IO.MouseDragMaxDistanceAbs[i].y = ImMax(g.IO.MouseDragMaxDistanceAbs[i].y, mouse_delta.y < 0.0f ? -mouse_delta.y : mouse_delta.y); + g.IO.MouseDragMaxDistanceSqr[i] = ImMax(g.IO.MouseDragMaxDistanceSqr[i], ImLengthSqr(mouse_delta)); } if (g.IO.MouseClicked[i]) // Clicking any mouse button reactivate mouse hovering which may have been deactivated by gamepad/keyboard navigation g.NavDisableMouseHover = false; @@ -3036,29 +3097,29 @@ void ImGui::NewFrame() g.IO.Framerate = 1.0f / (g.FramerateSecPerFrameAccum / (float)IM_ARRAYSIZE(g.FramerateSecPerFrame)); // Handle user moving window with mouse (at the beginning of the frame to avoid input lag or sheering). Only valid for root windows. - if (g.MovedWindowMoveId && g.MovedWindowMoveId == g.ActiveId && g.ActiveIdSource == ImGuiInputSource_Mouse) + if (g.MovingWindowMoveId && g.MovingWindowMoveId == g.ActiveId && g.ActiveIdSource == ImGuiInputSource_Mouse) { - KeepAliveID(g.MovedWindowMoveId); - IM_ASSERT(g.MovedWindow && g.MovedWindow->RootWindow); - IM_ASSERT(g.MovedWindow->MoveId == g.MovedWindowMoveId); + KeepAliveID(g.MovingWindowMoveId); + IM_ASSERT(g.MovingWindow && g.MovingWindow->RootWindow); + IM_ASSERT(g.MovingWindow->MoveId == g.MovingWindowMoveId); if (g.IO.MouseDown[0]) { - g.MovedWindow->RootWindow->PosFloat += g.IO.MouseDelta; + g.MovingWindow->RootWindow->PosFloat += g.IO.MouseDelta; if (g.IO.MouseDelta.x != 0.0f || g.IO.MouseDelta.y != 0.0f) - MarkIniSettingsDirty(g.MovedWindow->RootWindow); - FocusWindow(g.MovedWindow); + MarkIniSettingsDirty(g.MovingWindow->RootWindow); + FocusWindow(g.MovingWindow); } else { ClearActiveID(); - g.MovedWindow = NULL; - g.MovedWindowMoveId = 0; + g.MovingWindow = NULL; + g.MovingWindowMoveId = 0; } } else { - g.MovedWindow = NULL; - g.MovedWindowMoveId = 0; + g.MovingWindow = NULL; + g.MovingWindowMoveId = 0; } // Delay saving settings so we don't spam disk too much @@ -3069,12 +3130,12 @@ void ImGui::NewFrame() SaveIniSettingsToDisk(g.IO.IniFilename); } - // Find the window we are hovering. Child windows can extend beyond the limit of their parent so we need to derive HoveredRootWindow from HoveredWindow - g.HoveredWindow = g.MovedWindow ? g.MovedWindow : FindHoveredWindow(g.IO.MousePos, false); - if (g.HoveredWindow && (g.HoveredWindow->Flags & ImGuiWindowFlags_ChildWindow)) - g.HoveredRootWindow = g.HoveredWindow->RootWindow; - else - g.HoveredRootWindow = g.MovedWindow ? g.MovedWindow->RootWindow : FindHoveredWindow(g.IO.MousePos, true); + // Find the window we are hovering + // - Child windows can extend beyond the limit of their parent so we need to derive HoveredRootWindow from HoveredWindow. + // - When moving a window we can skip the search, which also conveniently bypasses the fact that window->WindowRectClipped is lagging as this point. + // - We also support the moved window toggling the NoInputs flag after moving has started in order to be able to detect windows below it, which is useful for e.g. docking mechanisms. + g.HoveredWindow = (g.MovingWindow && !(g.MovingWindow->Flags & ImGuiWindowFlags_NoInputs)) ? g.MovingWindow : FindHoveredWindow(g.IO.MousePos); + g.HoveredRootWindow = g.HoveredWindow ? g.HoveredWindow->RootWindow : NULL; if (ImGuiWindow* modal_window = GetFrontMostModalRootWindow()) { @@ -3090,7 +3151,7 @@ void ImGui::NewFrame() g.ModalWindowDarkeningRatio = 0.0f; } - // Are we using inputs? Tell user so they can capture/discard the inputs away from the rest of their application. + // Update the WantCaptureMouse/WantCAptureKeyboard flags, so user can capture/discard the inputs away from the rest of their application. // When clicking outside of a window we assume the click is owned by the application and won't request capture. We need to track click ownership. int mouse_earliest_button_down = -1; bool mouse_any_down = false; @@ -3100,7 +3161,7 @@ void ImGui::NewFrame() g.IO.MouseDownOwned[i] = (g.HoveredWindow != NULL) || (!g.OpenPopupStack.empty()); mouse_any_down |= g.IO.MouseDown[i]; if (g.IO.MouseDown[i]) - if (mouse_earliest_button_down == -1 || g.IO.MouseClickedTime[mouse_earliest_button_down] > g.IO.MouseClickedTime[i]) + if (mouse_earliest_button_down == -1 || g.IO.MouseClickedTime[i] < g.IO.MouseClickedTime[mouse_earliest_button_down]) mouse_earliest_button_down = i; } bool mouse_avail_to_imgui = (mouse_earliest_button_down == -1) || g.IO.MouseDownOwned[mouse_earliest_button_down]; @@ -3115,6 +3176,7 @@ void ImGui::NewFrame() g.OsImePosRequest = ImVec2(1.0f, 1.0f); // OS Input Method Editor showing on top-left of our window by default // If mouse was first clicked outside of ImGui bounds we also cancel out hovering. + // FIXME: For patterns of drag and drop between "application" and "imgui" we may need to rework/remove this test (first committed 311c0ca9 on 2015/02) if (!mouse_avail_to_imgui) g.HoveredWindow = g.HoveredRootWindow = NULL; @@ -3164,23 +3226,18 @@ void ImGui::NewFrame() // Closing the focused window restore focus to the first active root window in descending z-order if (g.NavWindow && !g.NavWindow->WasActive) - for (int i = g.Windows.Size-1; i >= 0; i--) - if (g.Windows[i]->WasActive && !(g.Windows[i]->Flags & ImGuiWindowFlags_ChildWindow)) - { - FocusWindow(g.Windows[i]); - break; - } + FocusPreviousWindow(); // No window should be open at the beginning of the frame. // But in order to allow the user to call NewFrame() multiple times without calling Render(), we are doing an explicit clear. g.CurrentWindowStack.resize(0); g.CurrentPopupStack.resize(0); - CloseInactivePopups(); + CloseInactivePopups(g.NavWindow); // Create implicit window - we will only render it if the user has added something to it. // We don't use "Debug" to avoid colliding with user trying to create a "Debug" window with custom flags. - ImGui::SetNextWindowSize(ImVec2(400,400), ImGuiCond_FirstUseEver); - ImGui::Begin("Debug##Default"); + SetNextWindowSize(ImVec2(400,400), ImGuiCond_FirstUseEver); + Begin("Debug##Default"); } void ImGui::Initialize() @@ -3222,7 +3279,7 @@ void ImGui::Shutdown() g.HoveredWindow = NULL; g.HoveredRootWindow = NULL; g.ActiveIdWindow = NULL; - g.MovedWindow = NULL; + g.MovingWindow = NULL; for (int i = 0; i < g.Settings.Size; i++) ImGui::MemFree(g.Settings[i].Name); g.Settings.clear(); @@ -3505,33 +3562,57 @@ void ImGui::EndFrame() g.CurrentWindow->Active = false; ImGui::End(); - // Click to focus window and start moving (after we're done with all our widgets) - if (g.ActiveId == 0 && g.HoveredId == 0 && g.IO.MouseClicked[0]) + if (g.ActiveId == 0 && g.HoveredId == 0) { - if (!(g.NavWindow && !g.NavWindow->WasActive && g.NavWindow->Active)) // Unless we just made a popup appear + if (!g.NavWindow || !g.NavWindow->Appearing) // Unless we just made a window/popup appear { - if (g.HoveredRootWindow != NULL) + // Click to focus window and start moving (after we're done with all our widgets) + if (g.IO.MouseClicked[0]) { - FocusWindow(g.HoveredWindow); - // FIXME-NAV: This never execute because of the FocusWindow call above, however we may might this behavior? - /* - if (g.NavWindow != g.HoveredWindow) + if (g.HoveredRootWindow != NULL) { - g.NavRefRectRel = ImRect(g.IO.MousePos - g.HoveredWindow->Pos, g.IO.MousePos - g.HoveredWindow->Pos); //ImRect(0,0,0,0); - g.NavDisableHighlight = true; + FocusWindow(g.HoveredWindow); + // FIXME-NAV: This never execute because of the FocusWindow call above, however we may might this behavior? + /* + if (g.NavWindow != g.HoveredWindow) + { + g.NavRefRectRel = ImRect(g.IO.MousePos - g.HoveredWindow->Pos, g.IO.MousePos - g.HoveredWindow->Pos); //ImRect(0,0,0,0); + g.NavDisableHighlight = true; + } + */ + if (!(g.HoveredWindow->Flags & ImGuiWindowFlags_NoMove) && !(g.HoveredRootWindow->Flags & ImGuiWindowFlags_NoMove)) + { + g.MovingWindow = g.HoveredWindow; + g.MovingWindowMoveId = g.MovingWindow->MoveId; + SetActiveID(g.MovingWindowMoveId, g.HoveredRootWindow); + } } - */ - if (!(g.HoveredWindow->Flags & ImGuiWindowFlags_NoMove)) + else if (g.NavWindow != NULL && GetFrontMostModalRootWindow() == NULL) { - g.MovedWindow = g.HoveredWindow; - g.MovedWindowMoveId = g.HoveredWindow->MoveId; - SetActiveIDNoNav(g.MovedWindowMoveId, g.HoveredRootWindow); + // Clicking on void disable focus + FocusWindow(NULL); } } - else if (g.NavWindow != NULL && GetFrontMostModalRootWindow() == NULL) + + // With right mouse button we close popups without changing focus + // (The left mouse button path calls FocusWindow which will lead NewFrame->CloseInactivePopups to trigger) + if (g.IO.MouseClicked[1]) { - // Clicking on void disable focus - FocusWindow(NULL); + // Find the top-most window between HoveredWindow and the front most Modal Window. + // This is where we can trim the popup stack. + ImGuiWindow* modal = GetFrontMostModalRootWindow(); + bool hovered_window_above_modal = false; + if (modal == NULL) + hovered_window_above_modal = true; + for (int i = g.Windows.Size - 1; i >= 0 && hovered_window_above_modal == false; i--) + { + ImGuiWindow* window = g.Windows[i]; + if (window == modal) + break; + if (window == g.HoveredWindow) + hovered_window_above_modal = true; + } + CloseInactivePopups(hovered_window_above_modal ? g.HoveredWindow : modal); } } } @@ -3824,31 +3905,39 @@ void ImGui::RenderFrameBorder(ImVec2 p_min, ImVec2 p_max, float rounding) } // Render a triangle to denote expanded/collapsed state -void ImGui::RenderCollapseTriangle(ImVec2 p_min, bool is_open, float scale) +void ImGui::RenderTriangle(ImVec2 p_min, ImGuiDir dir, float scale) { ImGuiContext& g = *GImGui; ImGuiWindow* window = g.CurrentWindow; const float h = g.FontSize * 1.00f; - const float r = h * 0.40f * scale; - ImVec2 center = p_min + ImVec2(h*0.50f, h*0.50f*scale); + float r = h * 0.40f * scale; + ImVec2 center = p_min + ImVec2(h * 0.50f, h * 0.50f * scale); ImVec2 a, b, c; - if (is_open) + switch (dir) { - center.y -= r*0.25f; - a = center + ImVec2(0,1)*r; - b = center + ImVec2(-0.866f,-0.5f)*r; - c = center + ImVec2(0.866f,-0.5f)*r; - } - else - { - a = center + ImVec2(1,0)*r; - b = center + ImVec2(-0.500f,0.866f)*r; - c = center + ImVec2(-0.500f,-0.866f)*r; + case ImGuiDir_Up: + r = -r; // ...fall through, no break! + case ImGuiDir_Down: + center.y -= r * 0.25f; + a = ImVec2(0,1) * r; + b = ImVec2(-0.866f,-0.5f) * r; + c = ImVec2(+0.866f,-0.5f) * r; + break; + case ImGuiDir_Left: + r = -r; // ...fall through, no break! + case ImGuiDir_Right: + a = ImVec2(1,0) * r; + b = ImVec2(-0.500f,+0.866f) * r; + c = ImVec2(-0.500f,-0.866f) * r; + break; + default: + IM_ASSERT(0); + break; } - window->DrawList->AddTriangleFilled(a, b, c, GetColorU32(ImGuiCol_Text)); + window->DrawList->AddTriangleFilled(center + a, center + b, center + c, GetColorU32(ImGuiCol_Text)); } void ImGui::RenderBullet(ImVec2 pos) @@ -3858,18 +3947,22 @@ void ImGui::RenderBullet(ImVec2 pos) window->DrawList->AddCircleFilled(pos, GImGui->FontSize*0.20f, GetColorU32(ImGuiCol_Text), 8); } -void ImGui::RenderCheckMark(ImVec2 pos, ImU32 col) +void ImGui::RenderCheckMark(ImVec2 pos, ImU32 col, float sz) { ImGuiContext& g = *GImGui; ImGuiWindow* window = g.CurrentWindow; - float start_x = (float)(int)(g.FontSize * 0.307f + 0.5f); - float rem_third = (float)(int)((g.FontSize - start_x) / 3.0f); - float bx = pos.x + 0.5f + start_x + rem_third; - float by = pos.y - 1.0f + (float)(int)(g.Font->Ascent * (g.FontSize / g.Font->FontSize) + 0.5f) + (float)(int)(g.Font->DisplayOffset.y); - window->DrawList->PathLineTo(ImVec2(bx - rem_third, by - rem_third)); + + float thickness = ImMax(sz / 5.0f, 1.0f); + sz -= thickness*0.5f; + pos += ImVec2(thickness*0.25f, thickness*0.25f); + + float third = sz / 3.0f; + float bx = pos.x + third; + float by = pos.y + sz - third*0.5f; + window->DrawList->PathLineTo(ImVec2(bx - third, by - third)); window->DrawList->PathLineTo(ImVec2(bx, by)); - window->DrawList->PathLineTo(ImVec2(bx + rem_third*2, by - rem_third*2)); - window->DrawList->PathStroke(col, false); + window->DrawList->PathLineTo(ImVec2(bx + third*2, by - third*2)); + window->DrawList->PathStroke(col, false, thickness); } void ImGui::RenderNavHighlight(const ImRect& bb, ImGuiID id, ImGuiNavHighlightFlags flags) @@ -3877,7 +3970,7 @@ void ImGui::RenderNavHighlight(const ImRect& bb, ImGuiID id, ImGuiNavHighlightFl ImGuiContext& g = *GImGui; if (id != g.NavId) return; - if (g.NavDisableHighlight && !(flags & ImGuiNavHighlightFlags_AlwaysRender)) + if (g.NavDisableHighlight && !(flags & ImGuiNavHighlightFlags_AlwaysDraw)) return; ImGuiWindow* window = ImGui::GetCurrentWindow(); @@ -3965,20 +4058,18 @@ void ImGui::CalcListClipping(int items_count, float items_height, int* out_items // Find window given position, search front-to-back // FIXME: Note that we have a lag here because WindowRectClipped is updated in Begin() so windows moved by user via SetWindowPos() and not SetNextWindowPos() will have that rectangle lagging by a frame at the time FindHoveredWindow() is called, aka before the next Begin(). Moving window thankfully isn't affected. -static ImGuiWindow* FindHoveredWindow(ImVec2 pos, bool excluding_childs) +static ImGuiWindow* FindHoveredWindow(ImVec2 pos) { ImGuiContext& g = *GImGui; - for (int i = g.Windows.Size-1; i >= 0; i--) + for (int i = g.Windows.Size - 1; i >= 0; i--) { ImGuiWindow* window = g.Windows[i]; if (!window->Active) continue; if (window->Flags & ImGuiWindowFlags_NoInputs) continue; - if (excluding_childs && (window->Flags & ImGuiWindowFlags_ChildWindow) != 0) - continue; - // Using the clipped AABB so a child window will typically be clipped by its parent. + // Using the clipped AABB, a child window will typically be clipped by its parent (not always) ImRect bb(window->WindowRectClipped.Min - g.Style.TouchExtraPadding, window->WindowRectClipped.Max + g.Style.TouchExtraPadding); if (bb.Contains(pos)) return window; @@ -4210,7 +4301,7 @@ bool ImGui::IsItemFocused() bool ImGui::IsItemClicked(int mouse_button) { - return IsMouseClicked(mouse_button) && IsItemHovered(); + return IsMouseClicked(mouse_button) && IsItemHovered(ImGuiHoveredFlags_Default); } bool ImGui::IsAnyItemHovered() @@ -4282,7 +4373,7 @@ static ImRect GetVisibleRect() } // Not exposed publicly as BeginTooltip() because bool parameters are evil. Let's see if other needs arise first. -static void BeginTooltipEx(ImGuiWindowFlags extra_flags, bool override_previous_tooltip) +void ImGui::BeginTooltipEx(ImGuiWindowFlags extra_flags, bool override_previous_tooltip) { ImGuiContext& g = *GImGui; char window_name[16]; @@ -4343,6 +4434,11 @@ void ImGui::OpenPopupEx(ImGuiID id, bool reopen_existing) { g.OpenPopupStack.resize(current_stack_size+1); g.OpenPopupStack[current_stack_size] = popup_ref; + + // When reopening a popup we first refocus its parent, otherwise if its parent is itself a popup it would get closed by CloseInactivePopups(). + // This is equivalent to what ClosePopupToLevel() does. + if (g.OpenPopupStack[current_stack_size].PopupId == id) + FocusWindow(window); } } @@ -4352,16 +4448,16 @@ void ImGui::OpenPopup(const char* str_id) OpenPopupEx(g.CurrentWindow->GetID(str_id), false); } -static void CloseInactivePopups() +static void CloseInactivePopups(ImGuiWindow* ref_window) { ImGuiContext& g = *GImGui; if (g.OpenPopupStack.empty()) return; // When popups are stacked, clicking on a lower level popups puts focus back to it and close popups above it. - // Don't close our own child popup windows + // Don't close our own child popup windows. int n = 0; - if (g.NavWindow) + if (ref_window) { for (n = 0; n < g.OpenPopupStack.Size; n++) { @@ -4372,24 +4468,25 @@ static void CloseInactivePopups() if (popup.Window->Flags & ImGuiWindowFlags_ChildWindow) continue; + // Trim the stack if popups are not direct descendant of the reference window (which is often the NavWindow) bool has_focus = false; for (int m = n; m < g.OpenPopupStack.Size && !has_focus; m++) - has_focus = (g.OpenPopupStack[m].Window && g.OpenPopupStack[m].Window->RootWindow == g.NavWindow->RootWindow); + has_focus = (g.OpenPopupStack[m].Window && g.OpenPopupStack[m].Window->RootWindow == ref_window->RootWindow); if (!has_focus) break; } } - if (n < g.OpenPopupStack.Size) // This test is not required but it allows to set a useful breakpoint on the line below - g.OpenPopupStack.resize(n); + if (n < g.OpenPopupStack.Size) // This test is not required but it allows to set a convenient breakpoint on the block below + ClosePopupToLevel(n); } static ImGuiWindow* GetFrontMostModalRootWindow() { ImGuiContext& g = *GImGui; for (int n = g.OpenPopupStack.Size-1; n >= 0; n--) - if (ImGuiWindow* front_most_popup = g.OpenPopupStack.Data[n].Window) - if (front_most_popup->Flags & ImGuiWindowFlags_Modal) - return front_most_popup; + if (ImGuiWindow* popup = g.OpenPopupStack.Data[n].Window) + if (popup->Flags & ImGuiWindowFlags_Modal) + return popup; return NULL; } @@ -4537,38 +4634,52 @@ void ImGui::EndPopup() PopStyleVar(); } -// This is a helper to handle the most simple case of associating one named popup to one given widget. -// 1. If you have many possible popups (for different "instances" of a same widget, or for wholly different widgets), you may be better off handling -// this yourself so you can store data relative to the widget that opened the popup instead of choosing different popup identifiers. -// 2. If you want right-clicking on the same item to reopen the popup at new location, use the same code replacing IsItemHovered() with IsItemRectHovered() -// and passing true to the OpenPopupEx(). -// Because: hovering an item in a window below the popup won't normally trigger is hovering behavior/coloring. The pattern of ignoring the fact that -// the item can be interacted with (because it is blocked by the active popup) may useful in some situation when e.g. large canvas as one item, content of menu -// driven by click position. +bool ImGui::OpenPopupOnItemClick(const char* str_id, int mouse_button) +{ + ImGuiWindow* window = GImGui->CurrentWindow; + if (IsMouseClicked(mouse_button) && IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup)) + { + ImGuiID id = str_id ? window->GetID(str_id) : window->DC.LastItemId; // If user hasn't passed an ID, we can use the LastItemID. Using LastItemID as a Popup ID won't conflict! + IM_ASSERT(id != 0); // However, you cannot pass a NULL str_id if the last item has no identifier (e.g. a Text() item) + OpenPopupEx(id, true); + return true; + } + return false; +} + +// This is a helper to handle the simplest case of associating one named popup to one given widget. +// You may want to handle this on user side if you have specific needs (e.g. tweaking IsItemHovered() parameters). +// You can pass a NULL str_id to use the identifier of the last item. bool ImGui::BeginPopupContextItem(const char* str_id, int mouse_button) { - if (IsItemHovered() && IsMouseClicked(mouse_button)) - OpenPopupEx(GImGui->CurrentWindow->GetID(str_id), false); - return BeginPopup(str_id); + ImGuiWindow* window = GImGui->CurrentWindow; + ImGuiID id = str_id ? window->GetID(str_id) : window->DC.LastItemId; // If user hasn't passed an ID, we can use the LastItemID. Using LastItemID as a Popup ID won't conflict! + IM_ASSERT(id != 0); // However, you cannot pass a NULL str_id if the last item has no identifier (e.g. a Text() item) + if (IsMouseClicked(mouse_button) && IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup)) + OpenPopupEx(id, true); + return BeginPopupEx(id, ImGuiWindowFlags_ShowBorders | ImGuiWindowFlags_AlwaysAutoResize); } bool ImGui::BeginPopupContextWindow(const char* str_id, int mouse_button, bool also_over_items) { if (!str_id) str_id = "window_context"; - if (IsWindowRectHovered() && IsMouseClicked(mouse_button)) - if (also_over_items || !IsAnyItemHovered()) - OpenPopupEx(GImGui->CurrentWindow->GetID(str_id), true); - return BeginPopup(str_id); + ImGuiID id = GImGui->CurrentWindow->GetID(str_id); + if (IsMouseClicked(mouse_button)) + if (IsWindowHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup)) + if (also_over_items || !IsAnyItemHovered()) + OpenPopupEx(id, true); + return BeginPopupEx(id, ImGuiWindowFlags_ShowBorders | ImGuiWindowFlags_AlwaysAutoResize); } bool ImGui::BeginPopupContextVoid(const char* str_id, int mouse_button) { if (!str_id) str_id = "void_context"; + ImGuiID id = GImGui->CurrentWindow->GetID(str_id); if (!IsAnyWindowHovered() && IsMouseClicked(mouse_button)) - OpenPopupEx(GImGui->CurrentWindow->GetID(str_id), true); - return BeginPopup(str_id); + OpenPopupEx(id, true); + return BeginPopupEx(id, ImGuiWindowFlags_ShowBorders | ImGuiWindowFlags_AlwaysAutoResize); } static bool BeginChildEx(const char* name, ImGuiID id, const ImVec2& size_arg, bool border, ImGuiWindowFlags extra_flags) @@ -4576,6 +4687,7 @@ static bool BeginChildEx(const char* name, ImGuiID id, const ImVec2& size_arg, b ImGuiContext& g = *GImGui; ImGuiWindow* parent_window = ImGui::GetCurrentWindow(); ImGuiWindowFlags flags = ImGuiWindowFlags_NoTitleBar|ImGuiWindowFlags_NoResize|ImGuiWindowFlags_NoSavedSettings|ImGuiWindowFlags_ChildWindow; + flags |= (parent_window->Flags & ImGuiWindowFlags_NoMove); // Inherit the NoMove flag const ImVec2 content_avail = ImGui::GetContentRegionAvail(); ImVec2 size = ImFloor(size_arg); @@ -4594,7 +4706,8 @@ static bool BeginChildEx(const char* name, ImGuiID id, const ImVec2& size_arg, b else ImFormatString(title, IM_ARRAYSIZE(title), "%s/%08X", parent_window->Name, id); - bool ret = ImGui::Begin(title, NULL, size, -1.0f, flags); + ImGui::SetNextWindowSize(size); + bool ret = ImGui::Begin(title, NULL, flags); ImGuiWindow* child_window = ImGui::GetCurrentWindow(); child_window->ChildId = id; child_window->AutoFitChildAxises = auto_fit_axises; @@ -4602,11 +4715,11 @@ static bool BeginChildEx(const char* name, ImGuiID id, const ImVec2& size_arg, b child_window->Flags &= ~ImGuiWindowFlags_ShowBorders; // Process navigation-in immediately so NavInit can run on first frame - if (/*!(flags & ImGuiWindowFlags_NavFlattened) &&*/ (child_window->DC.NavLayerActiveMask != 0 || child_window->DC.NavHasScroll) && g.NavActivateId == id) + if (!(flags & ImGuiWindowFlags_NavFlattened) && (child_window->DC.NavLayerActiveMask != 0 || child_window->DC.NavHasScroll) && g.NavActivateId == id) { ImGui::FocusWindow(child_window); NavInitWindow(child_window, false); - ImGui::SetActiveIDNoNav(id+1, child_window); // Steal ActiveId with a dummy id so that key-press won't activate child item + ImGui::SetActiveID(id+1, child_window); // Steal ActiveId with a dummy id so that key-press won't activate child item g.ActiveIdSource = ImGuiInputSource_Nav; } @@ -4646,13 +4759,14 @@ void ImGui::EndChild() ImGuiWindow* parent_window = GetCurrentWindow(); ImRect bb(parent_window->DC.CursorPos, parent_window->DC.CursorPos + sz); ItemSize(sz); - if (/*!(window->Flags & ImGuiWindowFlags_NavFlattened) &&*/ (window->DC.NavLayerActiveMask != 0 || window->DC.NavHasScroll)) + if (!(window->Flags & ImGuiWindowFlags_NavFlattened) && (window->DC.NavLayerActiveMask != 0 || window->DC.NavHasScroll)) { ItemAdd(bb, window->ChildId); RenderNavHighlight(bb, window->ChildId); } else { + // Not navigable into ItemAdd(bb, 0); } } @@ -4864,21 +4978,25 @@ static ImVec2 CalcNextScrollFromScrollTargetAndClamp(ImGuiWindow* window) return scroll; } +static ImGuiCol GetWindowBgColorIdxFromFlags(ImGuiWindowFlags flags) +{ + if (flags & ImGuiWindowFlags_ComboBox) + return ImGuiCol_ComboBg; + if (flags & (ImGuiWindowFlags_Tooltip | ImGuiWindowFlags_Popup)) + return ImGuiCol_PopupBg; + if (flags & ImGuiWindowFlags_ChildWindow) + return ImGuiCol_ChildWindowBg; + return ImGuiCol_WindowBg; +} + // Push a new ImGui window to add widgets to. // - A default window called "Debug" is automatically stacked at the beginning of every frame so you can use widgets without explicitly calling a Begin/End pair. // - Begin/End can be called multiple times during the frame with the same window name to append content. -// - 'size_on_first_use' for a regular window denote the initial size for first-time creation (no saved data) and isn't that useful. Use SetNextWindowSize() prior to calling Begin() for more flexible window manipulation. // - The window name is used as a unique identifier to preserve window information across frames (and save rudimentary information to the .ini file). // You can use the "##" or "###" markers to use the same label with different id, or same id with different label. See documentation at the top of this file. // - Return false when window is collapsed, so you can early out in your code. You always need to call ImGui::End() even if false is returned. // - Passing 'bool* p_open' displays a Close button on the upper-right corner of the window, the pointed value will be set to false when the button is pressed. -// - Passing non-zero 'size' is roughly equivalent to calling SetNextWindowSize(size, ImGuiCond_FirstUseEver) prior to calling Begin(). bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) -{ - return ImGui::Begin(name, p_open, ImVec2(0.f, 0.f), -1.0f, flags); -} - -bool ImGui::Begin(const char* name, bool* p_open, const ImVec2& size_on_first_use, float bg_alpha, ImGuiWindowFlags flags) { ImGuiContext& g = *GImGui; const ImGuiStyle& style = g.Style; @@ -4889,14 +5007,15 @@ bool ImGui::Begin(const char* name, bool* p_open, const ImVec2& size_on_first_us if (flags & ImGuiWindowFlags_NoInputs) flags |= ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize; - //if (flags & ImGuiWindowFlags_NavFlattened) - // IM_ASSERT(flags & ImGuiWindowFlags_ChildWindow); + if (flags & ImGuiWindowFlags_NavFlattened) + IM_ASSERT(flags & ImGuiWindowFlags_ChildWindow); // Find or create bool window_is_new = false; ImGuiWindow* window = FindWindowByName(name); if (!window) { + ImVec2 size_on_first_use = (g.SetNextWindowSizeCond != 0) ? g.SetNextWindowSizeVal : ImVec2(0.0f, 0.0f); // Any condition flag will do since we are creating a new window here. window = CreateNewWindow(name, size_on_first_use, flags); window_is_new = true; } @@ -4994,8 +5113,8 @@ bool ImGui::Begin(const char* name, bool* p_open, const ImVec2& size_on_first_us window->RootWindow = g.CurrentWindowStack[root_idx]; window->RootNonPopupWindow = g.CurrentWindowStack[root_non_popup_idx]; // Used to display TitleBgActive color and for selecting which window to use for NavWindowing window->RootNavWindow = window; - //while (window->RootNavWindow->Flags & ImGuiWindowFlags_NavFlattened) - // window->RootNavWindow = window->RootNavWindow->ParentWindow; + while (window->RootNavWindow->Flags & ImGuiWindowFlags_NavFlattened) + window->RootNavWindow = window->RootNavWindow->ParentWindow; // When reusing window again multiple times a frame, just append content (don't need to setup again) if (first_begin_of_the_frame) @@ -5107,8 +5226,9 @@ bool ImGui::Begin(const char* name, bool* p_open, const ImVec2& size_on_first_us } if ((flags & ImGuiWindowFlags_ChildWindow) && !(flags & ImGuiWindowFlags_Popup)) { + IM_ASSERT(window_size_set_by_api); // Submitted by BeginChild() window->Pos = window->PosFloat = parent_window->DC.CursorPos; - window->Size = window->SizeFull = size_on_first_use; // NB: argument name 'size_on_first_use' misleading here, it's really just 'size' as provided by user passed via BeginChild()->Begin(). + window->Size = window->SizeFull; } const bool window_pos_with_pivot = (window->SetWindowPosVal.x != FLT_MAX && window->HiddenFrames == 0); @@ -5190,11 +5310,11 @@ bool ImGui::Begin(const char* name, bool* p_open, const ImVec2& size_on_first_us // Draw window + handle manual resize ImRect title_bar_rect = window->TitleBarRect(); const float window_rounding = (flags & ImGuiWindowFlags_ChildWindow) ? style.ChildWindowRounding : style.WindowRounding; + const bool window_is_focused = g.NavWindow && window->RootNonPopupWindow == g.NavWindow->RootNonPopupWindow; if (window->Collapsed) { // Title bar only - const bool is_focused = g.NavWindow && window->RootNonPopupWindow == g.NavWindow->RootNonPopupWindow && !g.NavDisableHighlight; - RenderFrame(title_bar_rect.Min, title_bar_rect.Max, GetColorU32(is_focused ? ImGuiCol_TitleBgActive : ImGuiCol_TitleBgCollapsed), true, window_rounding); + RenderFrame(title_bar_rect.Min, title_bar_rect.Max, GetColorU32((window_is_focused && !g.NavDisableHighlight) ? ImGuiCol_TitleBgActive : ImGuiCol_TitleBgCollapsed), true, window_rounding); } else { @@ -5208,7 +5328,7 @@ bool ImGui::Begin(const char* name, bool* p_open, const ImVec2& size_on_first_us const ImRect resize_rect(br - ImVec2(resize_corner_size * 0.75f, resize_corner_size * 0.75f), br); const ImGuiID resize_id = window->GetID("#RESIZE"); bool hovered, held; - ButtonBehavior(resize_rect, resize_id, &hovered, &held, ImGuiButtonFlags_FlattenChilds | ImGuiButtonFlags_NoNavOverride); + ButtonBehavior(resize_rect, resize_id, &hovered, &held, ImGuiButtonFlags_FlattenChilds | ImGuiButtonFlags_NoNavFocus); if (hovered || held) g.MouseCursor = ImGuiMouseCursor_ResizeNWSE; @@ -5263,24 +5383,12 @@ bool ImGui::Begin(const char* name, bool* p_open, const ImVec2& size_on_first_us window->BorderSize = (flags & ImGuiWindowFlags_ShowBorders) ? 1.0f : 0.0f; // Window background, Default Alpha - ImGuiCol bg_color_idx = ImGuiCol_WindowBg; - if ((flags & ImGuiWindowFlags_ComboBox) != 0) - bg_color_idx = ImGuiCol_ComboBg; - else if ((flags & ImGuiWindowFlags_Tooltip) != 0 || (flags & ImGuiWindowFlags_Popup) != 0) - bg_color_idx = ImGuiCol_PopupBg; - else if ((flags & ImGuiWindowFlags_ChildWindow) != 0) - bg_color_idx = ImGuiCol_ChildWindowBg; - ImVec4 bg_color = style.Colors[bg_color_idx]; // We don't use GetColorU32() because bg_alpha is assigned (not multiplied) below - if (bg_alpha >= 0.0f) - bg_color.w = bg_alpha; - bg_color.w *= style.Alpha; - if (bg_color.w > 0.0f) - window->DrawList->AddRectFilled(window->Pos+ImVec2(0,window->TitleBarHeight()), window->Pos+window->Size, ColorConvertFloat4ToU32(bg_color), window_rounding, (flags & ImGuiWindowFlags_NoTitleBar) ? ImGuiCorner_All : ImGuiCorner_BotLeft|ImGuiCorner_BotRight); + ImU32 bg_col = GetColorU32(GetWindowBgColorIdxFromFlags(flags)); + window->DrawList->AddRectFilled(window->Pos+ImVec2(0,window->TitleBarHeight()), window->Pos+window->Size, bg_col, window_rounding, (flags & ImGuiWindowFlags_NoTitleBar) ? ImGuiCorner_All : ImGuiCorner_BotLeft|ImGuiCorner_BotRight); // Title bar - const bool is_focused = g.NavWindow && window->RootNonPopupWindow == g.NavWindow->RootNonPopupWindow; if (!(flags & ImGuiWindowFlags_NoTitleBar)) - window->DrawList->AddRectFilled(title_bar_rect.GetTL(), title_bar_rect.GetBR(), GetColorU32(is_focused ? ImGuiCol_TitleBgActive : ImGuiCol_TitleBg), window_rounding, ImGuiCorner_TopLeft|ImGuiCorner_TopRight); + window->DrawList->AddRectFilled(title_bar_rect.GetTL(), title_bar_rect.GetBR(), GetColorU32(window_is_focused ? ImGuiCol_TitleBgActive : ImGuiCol_TitleBg), window_rounding, ImGuiCorner_TopLeft|ImGuiCorner_TopRight); // Menu bar if (flags & ImGuiWindowFlags_MenuBar) @@ -5293,9 +5401,9 @@ bool ImGui::Begin(const char* name, bool* p_open, const ImVec2& size_on_first_us // Scrollbars if (window->ScrollbarX) - Scrollbar(window, true); + Scrollbar(ImGuiLayoutType_Horizontal); if (window->ScrollbarY) - Scrollbar(window, false); + Scrollbar(ImGuiLayoutType_Vertical); // Render resize grip // (after the input handling so we don't have a frame of latency) @@ -5396,7 +5504,7 @@ bool ImGui::Begin(const char* name, bool* p_open, const ImVec2& size_on_first_us if (ButtonBehavior(bb, id, NULL, NULL)) window->CollapseToggleWanted = true; // Defer collapsing to next frame as we are too far in the Begin() function RenderNavHighlight(bb, id); - RenderCollapseTriangle(window->Pos + style.FramePadding, !window->Collapsed, 1.0f); + RenderTriangle(window->Pos + style.FramePadding, window->Collapsed ? ImGuiDir_Right : ImGuiDir_Down, 1.0f); } // Close button @@ -5439,20 +5547,20 @@ bool ImGui::Begin(const char* name, bool* p_open, const ImVec2& size_on_first_us if (g.IO.KeyCtrl && IsKeyPressedMap(ImGuiKey_C)) ImGui::LogToClipboard(); */ + + // Inner rectangle + // We set this up after processing the resize grip so that our clip rectangle doesn't lag by a frame + // Note that if our window is collapsed we will end up with a null clipping rectangle which is the correct behavior. + window->InnerRect.Min.x = title_bar_rect.Min.x; + window->InnerRect.Min.y = title_bar_rect.Max.y + window->MenuBarHeight(); + window->InnerRect.Max.x = window->Pos.x + window->Size.x - window->ScrollbarSizes.x; + window->InnerRect.Max.y = window->Pos.y + window->Size.y - window->ScrollbarSizes.y; + //window->DrawList->AddRect(window->InnerRect.Min, window->InnerRect.Max, IM_COL32_WHITE); } - // Inner rectangle and inner clipping rectangle - // We set this up after processing the resize grip so that our clip rectangle doesn't lag by a frame - // Note that if our window is collapsed we will end up with a null clipping rectangle which is the correct behavior. - const ImRect title_bar_rect = window->TitleBarRect(); - const float border_size = window->BorderSize; - window->InnerRect.Min.x = title_bar_rect.Min.x; - window->InnerRect.Min.y = title_bar_rect.Max.y + window->MenuBarHeight(); - window->InnerRect.Max.x = window->Pos.x + window->Size.x - window->ScrollbarSizes.x; - window->InnerRect.Max.y = window->Pos.y + window->Size.y - window->ScrollbarSizes.y; - //window->DrawList->AddRect(window->InnerRect.Min, window->InnerRect.Max, IM_COL32_WHITE); - + // Inner clipping rectangle // Force round operator last to ensure that e.g. (int)(max.x-min.x) in user's render code produce correct result. + const float border_size = window->BorderSize; ImRect clip_rect; clip_rect.Min.x = ImFloor(0.5f + window->InnerRect.Min.x + ImMax(border_size, ImFloor(window->WindowPadding.x*0.5f))); clip_rect.Min.y = ImFloor(0.5f + window->InnerRect.Min.y + border_size); @@ -5460,9 +5568,10 @@ bool ImGui::Begin(const char* name, bool* p_open, const ImVec2& size_on_first_us clip_rect.Max.y = ImFloor(0.5f + window->InnerRect.Max.y - border_size); PushClipRect(clip_rect.Min, clip_rect.Max, true); - // Clear 'accessed' flag last thing + // Clear 'accessed' flag last thing (After PushClipRect which will set the flag. We want the flag to stay false when the default "Debug" window is unused) if (first_begin_of_the_frame) window->Accessed = false; + window->BeginCount++; g.SetNextWindowSizeConstraint = false; @@ -5489,6 +5598,32 @@ bool ImGui::Begin(const char* name, bool* p_open, const ImVec2& size_on_first_us return !window->SkipItems; } +// Old Begin() API with 5 parameters, avoid calling this version directly! Use SetNextWindowSize()+Begin() instead. +#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS +bool ImGui::Begin(const char* name, bool* p_open, const ImVec2& size_on_first_use, float bg_alpha_override, ImGuiWindowFlags flags) +{ + // Old API feature: we could pass the initial window size as a parameter, however this was very misleading because in most cases it would only affect the window when it didn't have storage in the .ini file. + if (size_on_first_use.x != 0.0f || size_on_first_use.y != 0.0f) + SetNextWindowSize(size_on_first_use, ImGuiCond_FirstUseEver); + + // Old API feature: we could override the window background alpha with a parameter. This is actually tricky to reproduce manually because: + // (1) there are multiple variants of WindowBg (popup, tooltip, etc.) and (2) you can't call PushStyleColor before Begin and PopStyleColor just after Begin() because of how CheckStackSizes() behave. + // The user-side solution is to do backup = GetStyleColorVec4(ImGuiCol_xxxBG), PushStyleColor(ImGuiCol_xxxBg), Begin, PushStyleColor(ImGuiCol_xxxBg, backup), [...], PopStyleColor(), End(); PopStyleColor() - which is super awkward. + // The alpha override was rarely used but for now we'll leave the Begin() variant around for a bit. We may either lift the constraint on CheckStackSizes() either add a SetNextWindowBgAlpha() helper that does it magically. + ImGuiContext& g = *GImGui; + const ImGuiCol bg_color_idx = GetWindowBgColorIdxFromFlags(flags); + const ImVec4 bg_color_backup = g.Style.Colors[bg_color_idx]; + if (bg_alpha_override >= 0.0f) + g.Style.Colors[bg_color_idx].w = bg_alpha_override; + + bool ret = Begin(name, p_open, flags); + + if (bg_alpha_override >= 0.0f) + g.Style.Colors[bg_color_idx] = bg_color_backup; + return ret; +} +#endif // IMGUI_DISABLE_OBSOLETE_FUNCTIONS + void ImGui::End() { ImGuiContext& g = *GImGui; @@ -5516,9 +5651,12 @@ void ImGui::End() // - We handle absolute seeking (when first clicking outside the grab) and relative manipulation (afterward or when clicking inside the grab) // - We store values as normalized ratio and in a form that allows the window content to change while we are holding on a scrollbar // - We handle both horizontal and vertical scrollbars, which makes the terminology not ideal. -static void Scrollbar(ImGuiWindow* window, bool horizontal) +void ImGui::Scrollbar(ImGuiLayoutType direction) { ImGuiContext& g = *GImGui; + ImGuiWindow* window = g.CurrentWindow; + + const bool horizontal = (direction == ImGuiLayoutType_Horizontal); const ImGuiStyle& style = g.Style; const ImGuiID id = window->GetID(horizontal ? "#SCROLLX" : "#SCROLLY"); @@ -5541,7 +5679,7 @@ static void Scrollbar(ImGuiWindow* window, bool horizontal) window_rounding_corners = ImGuiCorner_BotLeft | (other_scrollbar ? 0 : ImGuiCorner_BotRight); else window_rounding_corners = (((window->Flags & ImGuiWindowFlags_NoTitleBar) && !(window->Flags & ImGuiWindowFlags_MenuBar)) ? ImGuiCorner_TopRight : 0) | (other_scrollbar ? 0 : ImGuiCorner_BotRight); - window->DrawList->AddRectFilled(bb.Min, bb.Max, ImGui::GetColorU32(ImGuiCol_ScrollbarBg), window_rounding, window_rounding_corners); + window->DrawList->AddRectFilled(bb.Min, bb.Max, GetColorU32(ImGuiCol_ScrollbarBg), window_rounding, window_rounding_corners); bb.Expand(ImVec2(-ImClamp((float)(int)((bb.Max.x - bb.Min.x - 2.0f) * 0.5f), 0.0f, 3.0f), -ImClamp((float)(int)((bb.Max.y - bb.Min.y - 2.0f) * 0.5f), 0.0f, 3.0f))); // V denote the main, longer axis of the scrollbar (= height for a vertical scrollbar) @@ -5561,7 +5699,7 @@ static void Scrollbar(ImGuiWindow* window, bool horizontal) bool held = false; bool hovered = false; const bool previously_held = (g.ActiveId == id); - ImGui::ButtonBehavior(bb, id, &hovered, &held, ImGuiButtonFlags_NoNavOverride); + ButtonBehavior(bb, id, &hovered, &held, ImGuiButtonFlags_NoNavFocus); float scroll_max = ImMax(1.0f, win_size_contents_v - win_size_avail_v); float scroll_ratio = ImSaturate(scroll_v / scroll_max); @@ -5574,7 +5712,7 @@ static void Scrollbar(ImGuiWindow* window, bool horizontal) // Click position in scrollbar normalized space (0.0f->1.0f) const float clicked_v_norm = ImSaturate((mouse_pos_v - scrollbar_pos_v) / scrollbar_size_v); - ImGui::SetHoveredID(id); + SetHoveredID(id); bool seek_absolute = false; if (!previously_held) @@ -5610,7 +5748,7 @@ static void Scrollbar(ImGuiWindow* window, bool horizontal) } // Render - const ImU32 grab_col = ImGui::GetColorU32(held ? ImGuiCol_ScrollbarGrabActive : hovered ? ImGuiCol_ScrollbarGrabHovered : ImGuiCol_ScrollbarGrab); + const ImU32 grab_col = GetColorU32(held ? ImGuiCol_ScrollbarGrabActive : hovered ? ImGuiCol_ScrollbarGrabHovered : ImGuiCol_ScrollbarGrab); if (horizontal) window->DrawList->AddRectFilled(ImVec2(ImLerp(bb.Min.x, bb.Max.x, grab_v_norm), bb.Min.y), ImVec2(ImLerp(bb.Min.x, bb.Max.x, grab_v_norm) + grab_h_pixels, bb.Max.y), grab_col, style.ScrollbarRounding); else @@ -5659,6 +5797,17 @@ void ImGui::FocusWindow(ImGuiWindow* window) g.Windows.push_back(window); } +void ImGui::FocusPreviousWindow() +{ + ImGuiContext& g = *GImGui; + for (int i = g.Windows.Size - 1; i >= 0; i--) + if (g.Windows[i] != g.NavWindow && g.Windows[i]->WasActive && !(g.Windows[i]->Flags & ImGuiWindowFlags_ChildWindow)) + { + FocusWindow(g.Windows[i]); + return; + } +} + void ImGui::PushItemWidth(float item_width) { ImGuiWindow* window = GetCurrentWindow(); @@ -5773,6 +5922,16 @@ void ImGui::PopButtonRepeat() PopItemFlag(); } +void ImGui::PushNavDefaultFocus(bool default_focus) +{ + PushItemFlag(ImGuiItemFlags_NoNavDefaultFocus, !default_focus); +} + +void ImGui::PopNavDefaultFocus() +{ + PopItemFlag(); +} + void ImGui::PushTextWrapPos(float wrap_pos_x) { ImGuiWindow* window = GetCurrentWindow(); @@ -5947,40 +6106,54 @@ const char* ImGui::GetStyleColorName(ImGuiCol idx) return "Unknown"; } -bool ImGui::IsWindowHovered() +bool ImGui::IsWindowHovered(ImGuiHoveredFlags flags) { + IM_ASSERT((flags & ImGuiHoveredFlags_AllowWhenOverlapped) == 0); // Flags not supported by this function ImGuiContext& g = *GImGui; - return g.HoveredWindow == g.CurrentWindow && IsWindowContentHoverable(g.HoveredRootWindow); -} - -bool ImGui::IsWindowRectHovered() -{ - ImGuiContext& g = *GImGui; - return g.HoveredWindow == g.CurrentWindow; + if (g.HoveredWindow != g.CurrentWindow) + return false; + if (!IsWindowContentHoverable(g.HoveredRootWindow, flags)) + return false; + if (!(flags & ImGuiHoveredFlags_AllowWhenBlockedByActiveItem)) + if (g.ActiveId != 0 && g.ActiveIdWindow != g.CurrentWindow) + return false; + return true; } bool ImGui::IsWindowFocused() { ImGuiContext& g = *GImGui; + IM_ASSERT(g.CurrentWindow); // Not inside a Begin()/End() return g.NavWindow == g.CurrentWindow; } bool ImGui::IsRootWindowFocused() { ImGuiContext& g = *GImGui; + IM_ASSERT(g.CurrentWindow); // Not inside a Begin()/End() return g.NavWindow == g.CurrentWindow->RootWindow; } bool ImGui::IsRootWindowOrAnyChildFocused() { ImGuiContext& g = *GImGui; + IM_ASSERT(g.CurrentWindow); // Not inside a Begin()/End() return g.NavWindow && g.NavWindow->RootWindow == g.CurrentWindow->RootWindow; } -bool ImGui::IsRootWindowOrAnyChildHovered() +bool ImGui::IsRootWindowOrAnyChildHovered(ImGuiHoveredFlags flags) { ImGuiContext& g = *GImGui; - return g.HoveredRootWindow && (g.HoveredRootWindow == g.CurrentWindow->RootWindow) && IsWindowContentHoverable(g.HoveredRootWindow); + IM_ASSERT((flags & ImGuiHoveredFlags_AllowWhenOverlapped) == 0); // Flags not supported by this function + IM_ASSERT(g.CurrentWindow); // Not inside a Begin()/End() + if (!g.HoveredRootWindow || (g.HoveredRootWindow != g.CurrentWindow->RootWindow)) + return false; + if (!IsWindowContentHoverable(g.HoveredRootWindow, flags)) + return false; + if (!(flags & ImGuiHoveredFlags_AllowWhenBlockedByActiveItem)) + if (g.ActiveId != 0 && g.ActiveIdWindow != g.CurrentWindow) + return false; + return true; } float ImGui::GetWindowWidth() @@ -6087,8 +6260,7 @@ void ImGui::SetWindowSize(const ImVec2& size, ImGuiCond cond) void ImGui::SetWindowSize(const char* name, const ImVec2& size, ImGuiCond cond) { - ImGuiWindow* window = FindWindowByName(name); - if (window) + if (ImGuiWindow* window = FindWindowByName(name)) SetWindowSize(window, size, cond); } @@ -6153,13 +6325,6 @@ void ImGui::SetNextWindowPos(const ImVec2& pos, ImGuiCond cond, const ImVec2& pi g.SetNextWindowPosCond = cond ? cond : ImGuiCond_Always; } -#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS -void ImGui::SetNextWindowPosCenter(ImGuiCond cond) -{ - SetNextWindowPos(GetIO().DisplaySize * 0.5f, cond, ImVec2(0.5f, 0.5f)); -} -#endif - void ImGui::SetNextWindowSize(const ImVec2& size, ImGuiCond cond) { ImGuiContext& g = *GImGui; @@ -6624,7 +6789,7 @@ void ImGui::TextUnformatted(const char* text, const char* text_end) } } -void ImGui::AlignFirstTextHeightToWidgets() +void ImGui::AlignTextToFramePadding() { ImGuiWindow* window = GetCurrentWindow(); if (window->SkipItems) @@ -6708,18 +6873,21 @@ bool ImGui::ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool // FIXME-NAVIGATION: We don't honor those different behaviors. if ((flags & ImGuiButtonFlags_PressedOnClickRelease) && g.IO.MouseClicked[0]) { - if (flags & ImGuiButtonFlags_NoNavOverride) - SetActiveIDNoNav(id, window); - else - SetActiveID(id, window); // Hold on ID + SetActiveID(id, window); + if (!(flags & ImGuiButtonFlags_NoNavFocus)) + SetFocusID(id, window); FocusWindow(window); g.ActiveIdClickOffset = g.IO.MousePos - bb.Min; } if (((flags & ImGuiButtonFlags_PressedOnClick) && g.IO.MouseClicked[0]) || ((flags & ImGuiButtonFlags_PressedOnDoubleClick) && g.IO.MouseDoubleClicked[0])) { pressed = true; - ClearActiveID(); + if (flags & ImGuiButtonFlags_NoHoldingActiveID) + ClearActiveID(); + else + SetActiveID(id, window); // Hold on ID FocusWindow(window); + g.ActiveIdClickOffset = g.IO.MousePos - bb.Min; } if ((flags & ImGuiButtonFlags_PressedOnRelease) && g.IO.MouseReleased[0]) { @@ -6739,21 +6907,23 @@ bool ImGui::ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool } // Gamepad/Keyboard navigation - if (g.NavId == id && !g.NavDisableHighlight && (g.ActiveId == 0 || g.ActiveId == id)) - { - // We report navigated item as hovered but we don't set g.HoveredId to not interfere with mouse + // We report navigated item as hovered but we don't set g.HoveredId to not interfere with mouse. + if (g.NavId == id && !g.NavDisableHighlight && (g.ActiveId == 0 || g.ActiveId == id || g.ActiveId == window->MoveId)) hovered = true; - } + if (g.NavActivateDownId == id) { - bool nav_pressed = (g.NavActivateId == id) || IsNavInputPressed(ImGuiNavInput_PadActivate, (flags & ImGuiButtonFlags_Repeat) ? ImGuiNavReadMode_Repeat : ImGuiNavReadMode_Pressed); - if (nav_pressed) + bool nav_activated_by_code = (g.NavActivateId == id); + bool nav_activated_by_inputs = IsNavInputPressed(ImGuiNavInput_PadActivate, (flags & ImGuiButtonFlags_Repeat) ? ImGuiNavReadMode_Repeat : ImGuiNavReadMode_Pressed); + if (nav_activated_by_code || nav_activated_by_inputs) pressed = true; - if (nav_pressed || g.ActiveId == id) + if (nav_activated_by_code || nav_activated_by_inputs || g.ActiveId == id) { // Set active id so it can be queried by user via IsItemActive(), equivalent of holding the mouse button. g.NavActivateId = id; // This is so SetActiveId assign a Nav source SetActiveID(id, window); + if (!(flags & ImGuiButtonFlags_NoNavFocus)) + SetFocusID(id, window); g.ActiveIdAllowNavDirFlags = (1 << ImGuiDir_Left) | (1 << ImGuiDir_Right) | (1 << ImGuiDir_Up) | (1 << ImGuiDir_Down); } } @@ -6774,7 +6944,7 @@ bool ImGui::ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool pressed = true; ClearActiveID(); } - if (!(flags & ImGuiButtonFlags_NoNavOverride)) + if (!(flags & ImGuiButtonFlags_NoNavFocus)) g.NavDisableHighlight = true; } else if (g.ActiveIdSource == ImGuiInputSource_Nav) @@ -7122,14 +7292,14 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* l ImGuiContext& g = *GImGui; const ImGuiStyle& style = g.Style; const bool display_frame = (flags & ImGuiTreeNodeFlags_Framed) != 0; - const ImVec2 padding = display_frame ? style.FramePadding : ImVec2(style.FramePadding.x, 0.0f); + const ImVec2 padding = (display_frame || (flags & ImGuiTreeNodeFlags_FramePadding)) ? style.FramePadding : ImVec2(style.FramePadding.x, 0.0f); if (!label_end) label_end = FindRenderedTextEnd(label); const ImVec2 label_size = CalcTextSize(label, label_end, false); // We vertically grow up to current line height up the typical widget height. - const float text_base_offset_y = ImMax(0.0f, window->DC.CurrentLineTextBaseOffset - padding.y); // Latch before ItemSize changes it + const float text_base_offset_y = ImMax(padding.y, window->DC.CurrentLineTextBaseOffset); // Latch before ItemSize changes it const float frame_height = ImMax(ImMin(window->DC.CurrentLineHeight, g.FontSize + style.FramePadding.y*2), label_size.y + padding.y*2); ImRect bb = ImRect(window->DC.CursorPos, ImVec2(window->Pos.x + GetContentRegionMax().x, window->DC.CursorPos.y + frame_height)); if (display_frame) @@ -7144,7 +7314,7 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* l ItemSize(ImVec2(text_width, frame_height), text_base_offset_y); // For regular tree nodes, we arbitrary allow to click past 2 worth of ItemSpacing - // (Ideally we'd want to add a flag for the user to specify we want want the hit test to be done up to the right side of the content or not) + // (Ideally we'd want to add a flag for the user to specify if we want the hit test to be done up to the right side of the content or not) const ImRect interact_bb = display_frame ? bb : ImRect(bb.Min.x, bb.Min.y, bb.Min.x + text_width + style.ItemSpacing.x*2, bb.Max.y); bool is_open = TreeNodeBehaviorIsOpen(id, flags); if (!ItemAdd(interact_bb, id)) @@ -7198,12 +7368,13 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* l // Render const ImU32 col = GetColorU32((held && hovered) ? ImGuiCol_HeaderActive : hovered ? ImGuiCol_HeaderHovered : ImGuiCol_Header); - const ImVec2 text_pos = bb.Min + ImVec2(text_offset_x, padding.y + text_base_offset_y); + const ImVec2 text_pos = bb.Min + ImVec2(text_offset_x, text_base_offset_y); if (display_frame) { // Framed type RenderFrame(bb.Min, bb.Max, col, true, style.FrameRounding); - RenderCollapseTriangle(bb.Min + padding + ImVec2(0.0f, text_base_offset_y), is_open, 1.0f); + RenderNavHighlight(bb, id, ImGuiNavHighlightFlags_TypeThin); + RenderTriangle(bb.Min + ImVec2(padding.x, text_base_offset_y), is_open ? ImGuiDir_Down : ImGuiDir_Right, 1.0f); if (g.LogEnabled) { // NB: '##' is normally used to hide text (as a library-wide feature), so we need to specify the text range to make sure the ## aren't stripped out here. @@ -7222,12 +7393,14 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* l { // Unframed typed for tree nodes if (hovered || (flags & ImGuiTreeNodeFlags_Selected)) + { RenderFrame(bb.Min, bb.Max, col, false); - + RenderNavHighlight(bb, id, ImGuiNavHighlightFlags_TypeThin); + } if (flags & ImGuiTreeNodeFlags_Bullet) RenderBullet(bb.Min + ImVec2(text_offset_x * 0.5f, g.FontSize*0.50f + text_base_offset_y)); else if (!(flags & ImGuiTreeNodeFlags_Leaf)) - RenderCollapseTriangle(bb.Min + ImVec2(padding.x, g.FontSize*0.15f + text_base_offset_y), is_open, 0.70f); + RenderTriangle(bb.Min + ImVec2(padding.x, g.FontSize*0.15f + text_base_offset_y), is_open ? ImGuiDir_Down : ImGuiDir_Right, 0.70f); if (g.LogEnabled) LogRenderedText(&text_pos, ">"); RenderText(text_pos, label, label_end, false); @@ -7265,8 +7438,11 @@ bool ImGui::CollapsingHeader(const char* label, bool* p_open, ImGuiTreeNodeFlags // Create a small overlapping close button // FIXME: We can evolve this into user accessible helpers to add extra buttons on title bars, headers, etc. ImGuiContext& g = *GImGui; float button_sz = g.FontSize * 0.5f; + ImGuiItemHoveredDataBackup last_item_backup; + last_item_backup.Backup(); if (CloseButton(window->GetID((void*)(intptr_t)(id+1)), ImVec2(ImMin(window->DC.LastItemRect.Max.x, window->ClipRect.Max.x) - g.Style.FramePadding.x - button_sz, window->DC.LastItemRect.Min.y + g.Style.FramePadding.y + button_sz), button_sz)) *p_open = false; + last_item_backup.Restore(); } return is_open; @@ -7373,6 +7549,8 @@ float ImGui::GetTreeNodeToLabelSpacing() void ImGui::SetNextTreeNodeOpen(bool is_open, ImGuiCond cond) { ImGuiContext& g = *GImGui; + if (g.CurrentWindow->SkipItems) + return; g.SetNextTreeNodeOpenVal = is_open; g.SetNextTreeNodeOpenCond = cond ? cond : ImGuiCond_Always; } @@ -7594,7 +7772,7 @@ bool ImGui::InputScalarAsWidgetReplacement(const ImRect& aabb, const char* label // Our replacement widget will override the focus ID (registered previously to allow for a TAB focus to happen) // On the first frame, g.ScalarAsInputTextId == 0, then on subsequent frames it becomes == id - SetActiveIDNoNav(g.ScalarAsInputTextId, window); + SetActiveID(g.ScalarAsInputTextId, window); g.ActiveIdAllowNavDirFlags = (1 << ImGuiDir_Up) | (1 << ImGuiDir_Down); SetHoveredID(0); FocusableItemUnregister(window); @@ -7863,6 +8041,7 @@ bool ImGui::SliderFloat(const char* label, float* v, float v_min, float v_max, c if (tab_focus_requested || (hovered && g.IO.MouseClicked[0]) || g.NavActivateId == id || g.NavInputId == id) { SetActiveID(id, window); + SetFocusID(id, window); FocusWindow(window); if (tab_focus_requested || g.IO.KeyCtrl || g.NavInputId == id) { @@ -7914,6 +8093,7 @@ bool ImGui::VSliderFloat(const char* label, const ImVec2& size, float* v, float if ((hovered && g.IO.MouseClicked[0]) || g.NavActivateId == id || g.NavInputId == id) { SetActiveID(id, window); + SetFocusID(id, window); FocusWindow(window); } @@ -8164,6 +8344,7 @@ bool ImGui::DragFloat(const char* label, float* v, float v_speed, float v_min, f if (tab_focus_requested || (hovered && (g.IO.MouseClicked[0] || g.IO.MouseDoubleClicked[0])) || g.NavActivateId == id || g.NavInputId == id) { SetActiveID(id, window); + SetFocusID(id, window); FocusWindow(window); if (tab_focus_requested || g.IO.KeyCtrl || g.IO.MouseDoubleClicked[0] || g.NavInputId == id) { @@ -8554,7 +8735,7 @@ bool ImGui::Checkbox(const char* label, bool* v) { const float check_sz = ImMin(check_bb.GetWidth(), check_bb.GetHeight()); const float pad = ImMax(1.0f, (float)(int)(check_sz / 6.0f)); - window->DrawList->AddRectFilled(check_bb.Min+ImVec2(pad,pad), check_bb.Max-ImVec2(pad,pad), GetColorU32(ImGuiCol_CheckMark), style.FrameRounding); + RenderCheckMark(check_bb.Min + ImVec2(pad,pad), GetColorU32(ImGuiCol_CheckMark), check_bb.GetWidth() - pad*2.0f); } if (g.LogEnabled) @@ -8931,6 +9112,7 @@ bool ImGui::InputTextEx(const char* label, char* buf, int buf_size, const ImVec2 ImGuiWindow* draw_window = window; if (is_multiline) { + ItemAdd(total_bb, id, &frame_bb); if (!BeginChildFrame(id, frame_bb.GetSize())) { EndChildFrame(); @@ -8979,7 +9161,7 @@ bool ImGui::InputTextEx(const char* label, char* buf, int buf_size, const ImVec2 bool clear_active_id = false; - bool select_all = (g.ActiveId != id) && (((flags & ImGuiInputTextFlags_AutoSelectAll) != 0) || (g.NavInputId == id)); + bool select_all = (g.ActiveId != id) && (((flags & ImGuiInputTextFlags_AutoSelectAll) != 0) || (g.NavInputId == id)) && (!is_multiline); if (focus_requested || user_clicked || user_scrolled || g.NavInputId == id) { if (g.ActiveId != id) @@ -9019,9 +9201,10 @@ bool ImGui::InputTextEx(const char* label, char* buf, int buf_size, const ImVec2 select_all = true; } SetActiveID(id, window); - if (!is_multiline) - g.ActiveIdAllowNavDirFlags = ((1 << ImGuiDir_Up) | (1 << ImGuiDir_Down)); + SetFocusID(id, window); FocusWindow(window); + if (!is_multiline && !(flags & ImGuiInputTextFlags_CallbackHistory)) + g.ActiveIdAllowNavDirFlags |= ((1 << ImGuiDir_Up) | (1 << ImGuiDir_Down)); } else if (io.MouseClicked[0]) { @@ -9602,7 +9785,6 @@ bool ImGui::InputFloatN(const char* label, float* v, int components, int decimal } PopID(); - window->DC.CurrentLineTextBaseOffset = ImMax(window->DC.CurrentLineTextBaseOffset, g.Style.FramePadding.y); TextUnformatted(label, FindRenderedTextEnd(label)); EndGroup(); @@ -9645,7 +9827,6 @@ bool ImGui::InputIntN(const char* label, int* v, int components, ImGuiInputTextF } PopID(); - window->DC.CurrentLineTextBaseOffset = ImMax(window->DC.CurrentLineTextBaseOffset, g.Style.FramePadding.y); TextUnformatted(label, FindRenderedTextEnd(label)); EndGroup(); @@ -9745,7 +9926,7 @@ bool ImGui::BeginCombo(const char* label, const char* preview_value, ImVec2 popu RenderNavHighlight(frame_bb, id); RenderFrame(frame_bb.Min, frame_bb.Max, GetColorU32(ImGuiCol_FrameBg), true, style.FrameRounding); RenderFrame(ImVec2(frame_bb.Max.x-arrow_size, frame_bb.Min.y), frame_bb.Max, GetColorU32(popup_open || hovered ? ImGuiCol_ButtonHovered : ImGuiCol_Button), true, style.FrameRounding); // FIXME-ROUNDING - RenderCollapseTriangle(ImVec2(frame_bb.Max.x - arrow_size + style.FramePadding.y, frame_bb.Min.y + style.FramePadding.y), true); + RenderTriangle(ImVec2(frame_bb.Max.x - arrow_size + style.FramePadding.y, frame_bb.Min.y + style.FramePadding.y), ImGuiDir_Down); if (preview_value != NULL) RenderTextClipped(frame_bb.Min + style.FramePadding, value_bb.Max, preview_value, NULL, NULL, ImVec2(0.0f,0.0f)); @@ -9891,7 +10072,7 @@ bool ImGui::Selectable(const char* label, bool selected, ImGuiSelectableFlags fl } ImGuiButtonFlags button_flags = 0; - if (flags & ImGuiSelectableFlags_Menu) button_flags |= ImGuiButtonFlags_PressedOnClick; + if (flags & ImGuiSelectableFlags_Menu) button_flags |= ImGuiButtonFlags_PressedOnClick | ImGuiButtonFlags_NoHoldingActiveID; if (flags & ImGuiSelectableFlags_MenuItem) button_flags |= ImGuiButtonFlags_PressedOnRelease; if (flags & ImGuiSelectableFlags_Disabled) button_flags |= ImGuiButtonFlags_Disabled; if (flags & ImGuiSelectableFlags_AllowDoubleClick) button_flags |= ImGuiButtonFlags_PressedOnClickRelease | ImGuiButtonFlags_PressedOnDoubleClick; @@ -9905,7 +10086,7 @@ bool ImGui::Selectable(const char* label, bool selected, ImGuiSelectableFlags fl if (!g.NavDisableMouseHover && g.NavWindow == window) { g.NavDisableHighlight = true; - SetNavId(id, window->DC.NavLayerCurrent); + SetNavID(id, window->DC.NavLayerCurrent); } // Render @@ -9913,6 +10094,7 @@ bool ImGui::Selectable(const char* label, bool selected, ImGuiSelectableFlags fl { const ImU32 col = GetColorU32((held && hovered) ? ImGuiCol_HeaderActive : hovered ? ImGuiCol_HeaderHovered : ImGuiCol_Header); RenderFrame(bb_with_spacing.Min, bb_with_spacing.Max, col, false, 0.0f); + RenderNavHighlight(bb_with_spacing, id, ImGuiNavHighlightFlags_TypeThin); } if ((flags & ImGuiSelectableFlags_SpanAllColumns) && window->DC.ColumnsCount > 1) @@ -10043,23 +10225,38 @@ bool ImGui::MenuItem(const char* label, const char* shortcut, bool selected, boo return false; ImGuiContext& g = *GImGui; + ImGuiStyle& style = g.Style; ImVec2 pos = window->DC.CursorPos; ImVec2 label_size = CalcTextSize(label, NULL, true); - ImVec2 shortcut_size = shortcut ? CalcTextSize(shortcut, NULL) : ImVec2(0.0f, 0.0f); - float w = window->MenuColumns.DeclColumns(label_size.x, shortcut_size.x, (float)(int)(g.FontSize * 1.20f)); // Feedback for next frame - float extra_w = ImMax(0.0f, GetContentRegionAvail().x - w); - bool pressed = Selectable(label, false, ImGuiSelectableFlags_MenuItem | ImGuiSelectableFlags_DrawFillAvailWidth | (enabled ? 0 : ImGuiSelectableFlags_Disabled), ImVec2(w, 0.0f)); - if (shortcut_size.x > 0.0f) + ImGuiSelectableFlags flags = ImGuiSelectableFlags_MenuItem | (enabled ? 0 : ImGuiSelectableFlags_Disabled); + bool pressed; + if (window->DC.LayoutType == ImGuiLayoutType_Horizontal) { - PushStyleColor(ImGuiCol_Text, g.Style.Colors[ImGuiCol_TextDisabled]); - RenderText(pos + ImVec2(window->MenuColumns.Pos[1] + extra_w, 0.0f), shortcut, NULL, false); - PopStyleColor(); + // Mimic the exact layout spacing of BeginMenu() to allow MenuItem() inside a menu bar, which is a little misleading but may be useful + // Note that in this situation we render neither the shortcut neither the selected tick mark + float w = label_size.x; + window->DC.CursorPos.x += (float)(int)(style.ItemSpacing.x * 0.5f); + PushStyleVar(ImGuiStyleVar_ItemSpacing, style.ItemSpacing * 2.0f); + pressed = Selectable(label, false, flags, ImVec2(w, 0.0f)); + PopStyleVar(); + window->DC.CursorPos.x += (float)(int)(style.ItemSpacing.x * (-1.0f + 0.5f)); // -1 spacing to compensate the spacing added when Selectable() did a SameLine(). It would also work to call SameLine() ourselves after the PopStyleVar(). + } + else + { + ImVec2 shortcut_size = shortcut ? CalcTextSize(shortcut, NULL) : ImVec2(0.0f, 0.0f); + float w = window->MenuColumns.DeclColumns(label_size.x, shortcut_size.x, (float)(int)(g.FontSize * 1.20f)); // Feedback for next frame + float extra_w = ImMax(0.0f, GetContentRegionAvail().x - w); + pressed = Selectable(label, false, flags | ImGuiSelectableFlags_DrawFillAvailWidth, ImVec2(w, 0.0f)); + if (shortcut_size.x > 0.0f) + { + PushStyleColor(ImGuiCol_Text, g.Style.Colors[ImGuiCol_TextDisabled]); + RenderText(pos + ImVec2(window->MenuColumns.Pos[1] + extra_w, 0.0f), shortcut, NULL, false); + PopStyleColor(); + } + if (selected) + RenderCheckMark(pos + ImVec2(window->MenuColumns.Pos[2] + extra_w + g.FontSize * (0.20f+0.200f), g.FontSize * 0.134f * 0.5f), GetColorU32(enabled ? ImGuiCol_Text : ImGuiCol_TextDisabled), g.FontSize * 0.866f); } - - if (selected) - RenderCheckMark(pos + ImVec2(window->MenuColumns.Pos[2] + extra_w + g.FontSize * 0.20f, 0.0f), GetColorU32(enabled ? ImGuiCol_Text : ImGuiCol_TextDisabled)); - return pressed; } @@ -10095,6 +10292,12 @@ bool ImGui::BeginMainMenuBar() void ImGui::EndMainMenuBar() { EndMenuBar(); + + // When the user has left the menu layer (typically: closed menus through activation of an item), we restore focus to the previous window + ImGuiContext& g = *GImGui; + if (g.CurrentWindow == g.NavWindow && g.NavLayer == 0) + FocusPreviousWindow(); + End(); PopStyleVar(2); } @@ -10117,7 +10320,7 @@ bool ImGui::BeginMenuBar() window->DC.NavLayerCurrent++; window->DC.NavLayerCurrentMask <<= 1; window->DC.MenuBarAppending = true; - AlignFirstTextHeightToWidgets(); + AlignTextToFramePadding(); return true; } @@ -10140,7 +10343,7 @@ void ImGui::EndMenuBar() // This involve a one-frame delay which isn't very problematic in this situation. We could remove it by scoring in advance for multiple window (probably not worth the hassle/cost) IM_ASSERT(window->DC.NavLayerActiveMaskNext & 0x02); // Sanity check FocusWindow(window); - SetNavIdAndMoveMouse(window->NavLastIds[1], 1, window->NavRectRel[1]); + SetNavIDAndMoveMouse(window->NavLastIds[1], 1, window->NavRectRel[1]); g.NavLayer = 1; g.NavDisableHighlight = true; // Hide highlight for the current frame so we don't see the intermediary selection. g.NavMoveRequestForwardStep = 1; @@ -10202,7 +10405,7 @@ bool ImGui::BeginMenu(const char* label, bool enabled) float extra_w = ImMax(0.0f, GetContentRegionAvail().x - w); pressed = Selectable(label, menu_is_open, ImGuiSelectableFlags_Menu | ImGuiSelectableFlags_DontClosePopups | ImGuiSelectableFlags_DrawFillAvailWidth | (!enabled ? ImGuiSelectableFlags_Disabled : 0), ImVec2(w, 0.0f)); if (!enabled) PushStyleColor(ImGuiCol_Text, g.Style.Colors[ImGuiCol_TextDisabled]); - RenderCollapseTriangle(pos + ImVec2(window->MenuColumns.Pos[2] + extra_w + g.FontSize * 0.20f, 0.0f), false); + RenderTriangle(pos + ImVec2(window->MenuColumns.Pos[2] + extra_w + g.FontSize * 0.20f, 0.0f), ImGuiDir_Right); if (!enabled) PopStyleColor(); } @@ -10316,7 +10519,7 @@ void ImGui::ColorTooltip(const char* text, const float* col, ImGuiColorEditFlags Separator(); } - ImVec2 sz(g.FontSize * 3, g.FontSize * 3); + ImVec2 sz(g.FontSize * 3 + g.Style.FramePadding.y * 2, g.FontSize * 3 + g.Style.FramePadding.y * 2); ColorButton("##preview", ImVec4(col[0], col[1], col[2], col[3]), (flags & (ImGuiColorEditFlags_NoAlpha | ImGuiColorEditFlags_AlphaPreview | ImGuiColorEditFlags_AlphaPreviewHalf)) | ImGuiColorEditFlags_NoTooltip, sz); SameLine(); if (flags & ImGuiColorEditFlags_NoAlpha) @@ -10403,7 +10606,7 @@ bool ImGui::ColorButton(const char* desc_id, const ImVec4& col, ImGuiColorEditFl if (size.y == 0.0f) size.y = default_size; const ImRect bb(window->DC.CursorPos, window->DC.CursorPos + size); - ItemSize(bb); + ItemSize(bb, (size.y >= default_size) ? g.Style.FramePadding.y : 0.0f); if (!ItemAdd(bb, id)) return false; @@ -10417,7 +10620,7 @@ bool ImGui::ColorButton(const char* desc_id, const ImVec4& col, ImGuiColorEditFl float grid_step = ImMin(size.x, size.y) / 2.99f; float rounding = ImMin(g.Style.FrameRounding, grid_step * 0.5f); ImRect bb_inner = bb; - float off = -0.75f; // The border (using Col_FrameBg) tends to look off when color is near-opaque and rounding is enabled. This offset seemed like a good middleground to reduce those artefacts. + float off = -0.75f; // The border (using Col_FrameBg) tends to look off when color is near-opaque and rounding is enabled. This offset seemed like a good middle ground to reduce those artifacts. bb_inner.Expand(off); if ((flags & ImGuiColorEditFlags_AlphaPreviewHalf) && col.w < 1.0f) { @@ -10427,7 +10630,12 @@ bool ImGui::ColorButton(const char* desc_id, const ImVec4& col, ImGuiColorEditFl } else { - RenderColorRectWithAlphaCheckerboard(bb_inner.Min, bb_inner.Max, GetColorU32((flags & ImGuiColorEditFlags_AlphaPreview) ? col : col_without_alpha), grid_step, ImVec2(off, off), rounding); + // Because GetColorU32() multiplies by the global style Alpha and we don't want to display a checkerboard if the source code had no alpha + ImVec4 col_source = (flags & ImGuiColorEditFlags_AlphaPreview) ? col : col_without_alpha; + if (col_source.w < 1.0f) + RenderColorRectWithAlphaCheckerboard(bb_inner.Min, bb_inner.Max, GetColorU32(col_source), grid_step, ImVec2(off, off), rounding); + else + window->DrawList->AddRectFilled(bb_inner.Min, bb_inner.Max, GetColorU32(col_source), rounding, ~0); } RenderNavHighlight(bb, id); if (window->Flags & ImGuiWindowFlags_ShowBorders) @@ -10435,7 +10643,7 @@ bool ImGui::ColorButton(const char* desc_id, const ImVec4& col, ImGuiColorEditFl else window->DrawList->AddRect(bb.Min, bb.Max, GetColorU32(ImGuiCol_FrameBg), rounding); // Color button are often in need of some sort of border - if (!(flags & ImGuiColorEditFlags_NoTooltip) && IsItemHovered()) // FIXME-NAVIGATION: 'hovered' ? + if (!(flags & ImGuiColorEditFlags_NoTooltip) && hovered) ColorTooltip(desc_id, &col.x, flags & (ImGuiColorEditFlags_NoAlpha | ImGuiColorEditFlags_AlphaPreview | ImGuiColorEditFlags_AlphaPreviewHalf)); return pressed; @@ -10475,16 +10683,16 @@ void ImGui::ColorEditOptionsPopup(const float* col, ImGuiColorEditFlags flags) { int cr = IM_F32_TO_INT8_SAT(col[0]), cg = IM_F32_TO_INT8_SAT(col[1]), cb = IM_F32_TO_INT8_SAT(col[2]), ca = (flags & ImGuiColorEditFlags_NoAlpha) ? 255 : IM_F32_TO_INT8_SAT(col[3]); char buf[64]; - sprintf(buf, "(%.3ff, %.3ff, %.3ff, %.3ff)", col[0], col[1], col[2], (flags & ImGuiColorEditFlags_NoAlpha) ? 1.0f : col[3]); + ImFormatString(buf, IM_ARRAYSIZE(buf), "(%.3ff, %.3ff, %.3ff, %.3ff)", col[0], col[1], col[2], (flags & ImGuiColorEditFlags_NoAlpha) ? 1.0f : col[3]); if (Selectable(buf)) SetClipboardText(buf); - sprintf(buf, "(%d,%d,%d,%d)", cr, cg, cb, ca); + ImFormatString(buf, IM_ARRAYSIZE(buf), "(%d,%d,%d,%d)", cr, cg, cb, ca); if (Selectable(buf)) SetClipboardText(buf); if (flags & ImGuiColorEditFlags_NoAlpha) - sprintf(buf, "0x%02X%02X%02X", cr, cg, cb); + ImFormatString(buf, IM_ARRAYSIZE(buf), "0x%02X%02X%02X", cr, cg, cb); else - sprintf(buf, "0x%02X%02X%02X%02X", cr, cg, cb, ca); + ImFormatString(buf, IM_ARRAYSIZE(buf), "0x%02X%02X%02X%02X", cr, cg, cb, ca); if (Selectable(buf)) SetClipboardText(buf); EndPopup(); @@ -10615,8 +10823,8 @@ bool ImGui::ColorEdit4(const char* label, float col[4], ImGuiColorEditFlags flag value_changed |= value_changed_as_float |= DragFloat(ids[n], &f[n], 1.0f/255.0f, 0.0f, hdr ? 0.0f : 1.0f, fmt_table_float[fmt_idx][n]); else value_changed |= DragInt(ids[n], &i[n], 1.0f, 0, hdr ? 0 : 255, fmt_table_int[fmt_idx][n]); - if (!(flags & ImGuiColorEditFlags_NoOptions) && IsItemHovered() && IsMouseClicked(1)) - OpenPopup("context"); + if (!(flags & ImGuiColorEditFlags_NoOptions)) + OpenPopupOnItemClick("context"); } PopItemWidth(); PopItemWidth(); @@ -10642,8 +10850,8 @@ bool ImGui::ColorEdit4(const char* label, float col[4], ImGuiColorEditFlags flag else sscanf(p, "%02X%02X%02X", (unsigned int*)&i[0], (unsigned int*)&i[1], (unsigned int*)&i[2]); } - if (!(flags & ImGuiColorEditFlags_NoOptions) && IsItemHovered() && IsMouseClicked(1)) - OpenPopup("context"); + if (!(flags & ImGuiColorEditFlags_NoOptions)) + OpenPopupOnItemClick("context"); PopItemWidth(); } @@ -10664,9 +10872,9 @@ bool ImGui::ColorEdit4(const char* label, float col[4], ImGuiColorEditFlags flag SetNextWindowPos(window->DC.LastItemRect.GetBL() + ImVec2(-1,style.ItemSpacing.y)); } } - if (!(flags & ImGuiColorEditFlags_NoOptions) && IsItemHovered() && IsMouseClicked(1)) - OpenPopup("context"); - + if (!(flags & ImGuiColorEditFlags_NoOptions)) + OpenPopupOnItemClick("context"); + if (BeginPopup("picker")) { picker_active = true; @@ -10744,21 +10952,6 @@ static void RenderArrowsForVerticalBar(ImDrawList* draw_list, ImVec2 pos, ImVec2 RenderArrow(draw_list, ImVec2(pos.x + bar_w - half_sz.x, pos.y), half_sz, ImGuiDir_Left, IM_COL32_WHITE); } -static void PaintVertsLinearGradientKeepAlpha(ImDrawVert* vert_start, ImDrawVert* vert_end, ImVec2 gradient_p0, ImVec2 gradient_p1, ImU32 col0, ImU32 col1) -{ - ImVec2 gradient_extent = gradient_p1 - gradient_p0; - float gradient_inv_length2 = 1.0f / ImLengthSqr(gradient_extent); - for (ImDrawVert* vert = vert_start; vert < vert_end; vert++) - { - float d = ImDot(vert->pos - gradient_p0, gradient_extent); - float t = ImClamp(d * gradient_inv_length2, 0.0f, 1.0f); - int r = ImLerp((int)(col0 >> IM_COL32_R_SHIFT) & 0xFF, (int)(col1 >> IM_COL32_R_SHIFT) & 0xFF, t); - int g = ImLerp((int)(col0 >> IM_COL32_G_SHIFT) & 0xFF, (int)(col1 >> IM_COL32_G_SHIFT) & 0xFF, t); - int b = ImLerp((int)(col0 >> IM_COL32_B_SHIFT) & 0xFF, (int)(col1 >> IM_COL32_B_SHIFT) & 0xFF, t); - vert->col = (r << IM_COL32_R_SHIFT) | (g << IM_COL32_G_SHIFT) | (b << IM_COL32_B_SHIFT) | (vert->col & IM_COL32_A_MASK); - } -} - // ColorPicker // Note: only access 3 floats if ImGuiColorEditFlags_NoAlpha flag is set. // FIXME: we adjust the big color square height based on item width, which may cause a flickering feedback loop (if automatic height makes a vertical scrollbar appears, affecting automatic width..) @@ -10847,8 +11040,8 @@ bool ImGui::ColorPicker4(const char* label, float col[4], ImGuiColorEditFlags fl value_changed = value_changed_sv = true; } } - if (!(flags & ImGuiColorEditFlags_NoOptions) && IsItemHovered() && IsMouseClicked(1)) - OpenPopup("context"); + if (!(flags & ImGuiColorEditFlags_NoOptions)) + OpenPopupOnItemClick("context"); } else if (flags & ImGuiColorEditFlags_PickerHueBar) { @@ -10860,8 +11053,8 @@ bool ImGui::ColorPicker4(const char* label, float col[4], ImGuiColorEditFlags fl V = 1.0f - ImSaturate((io.MousePos.y - picker_pos.y) / (sv_picker_size-1)); value_changed = value_changed_sv = true; } - if (!(flags & ImGuiColorEditFlags_NoOptions) && IsItemHovered() && IsMouseClicked(1)) - OpenPopup("context"); + if (!(flags & ImGuiColorEditFlags_NoOptions)) + OpenPopupOnItemClick("context"); // Hue bar logic SetCursorScreenPos(ImVec2(bar0_pos_x, picker_pos.y)); @@ -10979,7 +11172,7 @@ bool ImGui::ColorPicker4(const char* label, float col[4], ImGuiColorEditFlags fl // Paint colors over existing vertices ImVec2 gradient_p0(wheel_center.x + cosf(a0) * wheel_r_inner, wheel_center.y + sinf(a0) * wheel_r_inner); ImVec2 gradient_p1(wheel_center.x + cosf(a1) * wheel_r_inner, wheel_center.y + sinf(a1) * wheel_r_inner); - PaintVertsLinearGradientKeepAlpha(draw_list->_VtxWritePtr - (draw_list->_VtxCurrentIdx - vert_start_idx), draw_list->_VtxWritePtr, gradient_p0, gradient_p1, hue_colors[n], hue_colors[n+1]); + ShadeVertsLinearColorGradientKeepAlpha(draw_list->_VtxWritePtr - (draw_list->_VtxCurrentIdx - vert_start_idx), draw_list->_VtxWritePtr, gradient_p0, gradient_p1, hue_colors[n], hue_colors[n+1]); } // Render Cursor + preview on Hue Wheel @@ -11615,14 +11808,14 @@ void ImGui::Value(const char* prefix, float v, const char* float_format) // PLATFORM DEPENDENT HELPERS //----------------------------------------------------------------------------- -#if defined(_WIN32) && !defined(_WINDOWS_) && (!defined(IMGUI_DISABLE_WIN32_DEFAULT_CLIPBOARD_FUNCS) || !defined(IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCS)) +#if defined(_WIN32) && !defined(_WINDOWS_) && (!defined(IMGUI_DISABLE_WIN32_DEFAULT_CLIPBOARD_FUNCTIONS) || !defined(IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS)) #undef WIN32_LEAN_AND_MEAN #define WIN32_LEAN_AND_MEAN #include #endif // Win32 API clipboard implementation -#if defined(_WIN32) && !defined(IMGUI_DISABLE_WIN32_DEFAULT_CLIPBOARD_FUNCS) +#if defined(_WIN32) && !defined(IMGUI_DISABLE_WIN32_DEFAULT_CLIPBOARD_FUNCTIONS) #ifdef _MSC_VER #pragma comment(lib, "user32") @@ -11658,7 +11851,10 @@ static void SetClipboardTextFn_DefaultImpl(void*, const char* text) const int wbuf_length = ImTextCountCharsFromUtf8(text, NULL) + 1; HGLOBAL wbuf_handle = GlobalAlloc(GMEM_MOVEABLE, (SIZE_T)wbuf_length * sizeof(ImWchar)); if (wbuf_handle == NULL) + { + CloseClipboard(); return; + } ImWchar* wbuf_global = (ImWchar*)GlobalLock(wbuf_handle); ImTextStrFromUtf8(wbuf_global, wbuf_length, text, NULL); GlobalUnlock(wbuf_handle); @@ -11690,7 +11886,7 @@ static void SetClipboardTextFn_DefaultImpl(void*, const char* text) #endif // Win32 API IME support (for Asian languages, etc.) -#if defined(_WIN32) && !defined(__GNUC__) && !defined(IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCS) +#if defined(_WIN32) && !defined(__GNUC__) && !defined(IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS) #include #ifdef _MSC_VER @@ -11778,13 +11974,14 @@ void ImGui::ShowMetricsWindow(bool* p_open) while (clipper.Step()) for (int prim = clipper.DisplayStart, vtx_i = elem_offset + clipper.DisplayStart*3; prim < clipper.DisplayEnd; prim++) { - char buf[300], *buf_p = buf; + char buf[300]; + char *buf_p = buf, *buf_end = buf + IM_ARRAYSIZE(buf); ImVec2 triangles_pos[3]; for (int n = 0; n < 3; n++, vtx_i++) { ImDrawVert& v = draw_list->VtxBuffer[idx_buffer ? idx_buffer[vtx_i] : vtx_i]; triangles_pos[n] = v.pos; - buf_p += sprintf(buf_p, "%s %04d { pos = (%8.2f,%8.2f), uv = (%.6f,%.6f), col = %08X }\n", (n == 0) ? "vtx" : " ", vtx_i, v.pos.x, v.pos.y, v.uv.x, v.uv.y, v.col); + buf_p += ImFormatString(buf_p, (int)(buf_end - buf_p), "%s %04d { pos = (%8.2f,%8.2f), uv = (%.6f,%.6f), col = %08X }\n", (n == 0) ? "vtx" : " ", vtx_i, v.pos.x, v.pos.y, v.uv.x, v.uv.y, v.col); } ImGui::Selectable(buf, false); if (ImGui::IsItemHovered()) @@ -11847,8 +12044,8 @@ void ImGui::ShowMetricsWindow(bool* p_open) const char* input_source_names[] = { "None", "Mouse", "Nav" }; IM_ASSERT(IM_ARRAYSIZE(input_source_names) == ImGuiInputSource_Count_); ImGui::Text("HoveredWindow: '%s'", g.HoveredWindow ? g.HoveredWindow->Name : "NULL"); ImGui::Text("HoveredRootWindow: '%s'", g.HoveredRootWindow ? g.HoveredRootWindow->Name : "NULL"); - ImGui::Text("HoveredId: 0x%08X/0x%08X", g.HoveredId, g.HoveredIdPreviousFrame); // Data is "in-flight" so depending on when the Metrics window is called we may see current frame information or not - ImGui::Text("ActiveId: 0x%08X/0x%08X, ActiveIdSource: %s", g.ActiveId, g.ActiveIdPreviousFrame, input_source_names[g.ActiveIdSource]); + ImGui::Text("HoveredId: 0x%08X/0x%08X (%.2f sec)", g.HoveredId, g.HoveredIdPreviousFrame, g.HoveredIdTimer); // Data is "in-flight" so depending on when the Metrics window is called we may see current frame information or not + ImGui::Text("ActiveId: 0x%08X/0x%08X (%.2f sec), ActiveIdSource: %s", g.ActiveId, g.ActiveIdPreviousFrame, g.ActiveIdTimer, input_source_names[g.ActiveIdSource]); ImGui::Text("ActiveIdWindow: '%s'", g.ActiveIdWindow ? g.ActiveIdWindow->Name : "NULL"); ImGui::Text("NavWindow: '%s', NavId: 0x%08X, NavLayer: %d", g.NavWindow ? g.NavWindow->Name : "NULL", g.NavId, g.NavLayer); ImGui::Text("NavUsable: %d, NavActive: %d", g.IO.NavUsable, g.IO.NavActive); diff --git a/deps/cimgui/imgui/imgui.h b/deps/cimgui/imgui/imgui.h index 7dda2d3e..4fd85435 100644 --- a/deps/cimgui/imgui/imgui.h +++ b/deps/cimgui/imgui/imgui.h @@ -1,4 +1,4 @@ -// dear imgui, v1.52 WIP +// dear imgui, v1.53 WIP // (headers) // See imgui.cpp file for documentation. @@ -16,7 +16,8 @@ #include // ptrdiff_t, NULL #include // memset, memmove, memcpy, strlen, strchr, strcpy, strcmp -#define IMGUI_VERSION "1.52 WIP" +#define IMGUI_VERSION "1.53 WIP" +#define IMGUI_HAS_NAV // navigation branch // Define attributes of all API symbols declarations, e.g. for DLL under Windows. #ifndef IMGUI_API @@ -29,14 +30,16 @@ #define IM_ASSERT(_EXPR) assert(_EXPR) #endif +// Helpers // Some compilers support applying printf-style warnings to user functions. #if defined(__clang__) || defined(__GNUC__) -#define IM_FMTARGS(FMT) __attribute__((format(printf, FMT, FMT+1))) -#define IM_FMTLIST(FMT) __attribute__((format(printf, FMT, 0))) +#define IM_FMTARGS(FMT) __attribute__((format(printf, FMT, FMT+1))) +#define IM_FMTLIST(FMT) __attribute__((format(printf, FMT, 0))) #else #define IM_FMTARGS(FMT) #define IM_FMTLIST(FMT) #endif +#define IM_ARRAYSIZE(_ARR) ((int)(sizeof(_ARR)/sizeof(*_ARR))) #if defined(__clang__) #pragma clang diagnostic push @@ -81,6 +84,7 @@ typedef int ImGuiColumnsFlags; // flags: for *Columns*() typedef int ImGuiInputTextFlags; // flags: for InputText*() // enum ImGuiInputTextFlags_ typedef int ImGuiSelectableFlags; // flags: for Selectable() // enum ImGuiSelectableFlags_ typedef int ImGuiTreeNodeFlags; // flags: for TreeNode*(), Collapsing*() // enum ImGuiTreeNodeFlags_ +typedef int ImGuiHoveredFlags; // flags: for IsItemHovered() // enum ImGuiHoveredFlags_ typedef int (*ImGuiTextEditCallback)(ImGuiTextEditCallbackData *data); typedef void (*ImGuiSizeConstraintCallback)(ImGuiSizeConstraintCallbackData* data); #ifdef _MSC_VER @@ -127,13 +131,12 @@ namespace ImGui // Demo/Debug/Info IMGUI_API void ShowTestWindow(bool* p_open = NULL); // create demo/test window. demonstrate most ImGui features. call this to learn about the library! try to make it always available in your application! - IMGUI_API void ShowMetricsWindow(bool* p_open = NULL); // create metrics window. display ImGui internals: browse window list, draw commands, individual vertices, basic internal state, etc. + IMGUI_API void ShowMetricsWindow(bool* p_open = NULL); // create metrics window. display ImGui internals: draw commands (with individual draw calls and vertices), window list, basic internal state, etc. IMGUI_API void ShowStyleEditor(ImGuiStyle* ref = NULL); // add style editor block (not a window). you can pass in a reference ImGuiStyle structure to compare to, revert to and save to (else it uses the default style) IMGUI_API void ShowUserGuide(); // add basic help/info block (not a window): how to manipulate ImGui as a end-user (mouse/keyboard controls). // Window IMGUI_API bool Begin(const char* name, bool* p_open = NULL, ImGuiWindowFlags flags = 0); // push window to the stack and start appending to it. see .cpp for details. return false when window is collapsed, so you can early out in your code. 'bool* p_open' creates a widget on the upper-right to close the window (which sets your bool to false). - IMGUI_API bool Begin(const char* name, bool* p_open, const ImVec2& size_on_first_use, float bg_alpha = -1.0f, ImGuiWindowFlags flags = 0); // OBSOLETE. this is the older/longer API. the extra parameters aren't very relevant. call SetNextWindowSize() instead if you want to set a window size. For regular windows, 'size_on_first_use' only applies to the first time EVER the window is created and probably not what you want! might obsolete this API eventually. IMGUI_API void End(); // finish appending to current window, pop it off the window stack. IMGUI_API bool BeginChild(const char* str_id, const ImVec2& size = ImVec2(0,0), bool border = false, ImGuiWindowFlags extra_flags = 0); // begin a scrolling region. size==0.0f: use remaining window size, size<0.0f: use remaining window size minus abs(size). size>0.0f: fixed size. each axis can use a different mode, e.g. ImVec2(0,400). IMGUI_API bool BeginChild(ImGuiID id, const ImVec2& size = ImVec2(0,0), bool border = false, ImGuiWindowFlags extra_flags = 0); // " @@ -207,6 +210,8 @@ namespace ImGui IMGUI_API void PopAllowKeyboardFocus(); IMGUI_API void PushButtonRepeat(bool repeat); // in 'repeat' mode, Button*() functions return repeated true in a typematic manner (using io.KeyRepeatDelay/io.KeyRepeatRate setting). Note that you can call IsItemActive() after any Button() to tell if the button is held in the current frame. IMGUI_API void PopButtonRepeat(); + IMGUI_API void PushNavDefaultFocus(bool default_focus); + IMGUI_API void PopNavDefaultFocus(); // Cursor / Layout IMGUI_API void Separator(); // separator, generally horizontal. inside a menu bar or in horizontal layout mode, this becomes a vertical separator. @@ -227,7 +232,7 @@ namespace ImGui IMGUI_API ImVec2 GetCursorStartPos(); // initial cursor position IMGUI_API ImVec2 GetCursorScreenPos(); // cursor position in absolute screen coordinates [0..io.DisplaySize] (useful to work with ImDrawList API) IMGUI_API void SetCursorScreenPos(const ImVec2& pos); // cursor position in absolute screen coordinates [0..io.DisplaySize] - IMGUI_API void AlignFirstTextHeightToWidgets(); // call once if the first item on the line is a Text() item and you want to vertically lower it to match subsequent (bigger) widgets + IMGUI_API void AlignTextToFramePadding(); // vertically align/lower upcoming text to FramePadding.y so that it will aligns to upcoming widgets (call if you have text on a line before regular widgets) IMGUI_API float GetTextLineHeight(); // height of font == GetWindowFontSize() IMGUI_API float GetTextLineHeightWithSpacing(); // distance (in pixels) between 2 consecutive lines of text == GetWindowFontSize() + GetStyle().ItemSpacing.y IMGUI_API float GetItemsLineHeightWithSpacing(); // distance (in pixels) between 2 consecutive lines of standard height widgets == GetWindowFontSize() + GetStyle().FramePadding.y*2 + GetStyle().ItemSpacing.y @@ -391,11 +396,12 @@ namespace ImGui // Popups IMGUI_API void OpenPopup(const char* str_id); // call to mark popup as open (don't call every frame!). popups are closed when user click outside, or if CloseCurrentPopup() is called within a BeginPopup()/EndPopup() block. By default, Selectable()/MenuItem() are calling CloseCurrentPopup(). Popup identifiers are relative to the current ID-stack (so OpenPopup and BeginPopup needs to be at the same level). + IMGUI_API bool OpenPopupOnItemClick(const char* str_id = NULL, int mouse_button = 1); // helper to open popup when clicked on last item. return true when just opened. IMGUI_API bool BeginPopup(const char* str_id); // return true if the popup is open, and you can start outputting to it. only call EndPopup() if BeginPopup() returned true! IMGUI_API bool BeginPopupModal(const char* name, bool* p_open = NULL, ImGuiWindowFlags extra_flags = 0); // modal dialog (block interactions behind the modal window, can't close the modal window by clicking outside) - IMGUI_API bool BeginPopupContextItem(const char* str_id, int mouse_button = 1); // helper to open and begin popup when clicked on last item. read comments in .cpp! + IMGUI_API bool BeginPopupContextItem(const char* str_id = NULL, int mouse_button = 1); // helper to open and begin popup when clicked on last item. if you can pass a NULL str_id only if the previous item had an id. If you want to use that on a non-interactive item such as Text() you need to pass in an explicit ID here. read comments in .cpp! IMGUI_API bool BeginPopupContextWindow(const char* str_id = NULL, int mouse_button = 1, bool also_over_items = true); // helper to open and begin popup when clicked on current window. - IMGUI_API bool BeginPopupContextVoid(const char* str_id = NULL, int mouse_button = 1); // helper to open and begin popup when clicked in void (no window). + IMGUI_API bool BeginPopupContextVoid(const char* str_id = NULL, int mouse_button = 1); // helper to open and begin popup when clicked in void (where there are no imgui windows). IMGUI_API void EndPopup(); IMGUI_API bool IsPopupOpen(const char* str_id); // return true if the popup is open IMGUI_API void CloseCurrentPopup(); // close the popup we have begin-ed into. clicking on a MenuItem or Selectable automatically close the current popup. @@ -414,6 +420,7 @@ namespace ImGui // Styles IMGUI_API void StyleColorsClassic(ImGuiStyle* dst = NULL); + IMGUI_API void StyleColorsDark(ImGuiStyle* dst = NULL); // Focus, Activation IMGUI_API void ActivateItem(ImGuiID id); // remotely activate a button, checkbox, tree node etc. given its unique ID. activation is queued and processed on the next frame when the item is encountered again. @@ -422,8 +429,7 @@ namespace ImGui IMGUI_API void SetItemDefaultFocus(); // FIXME-NAVIGATION // make last item the default focused item of a window // Utilities - IMGUI_API bool IsItemHovered(); // is the last item hovered by mouse (and usable)? or we are currently using Nav and the item is focused. - IMGUI_API bool IsItemRectHovered(); // is the last item hovered by mouse? even if another item is active or window is blocked by popup while we are hovering this + IMGUI_API bool IsItemHovered(ImGuiHoveredFlags flags = 0); // is the last item hovered by mouse (and usable)? or we are currently using Nav and the item is focused. IMGUI_API bool IsItemActive(); // is 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 IsItemFocused(); // is the last item focused for keyboard/gamepad navigation? IMGUI_API bool IsItemClicked(int mouse_button = 0); // is the last item clicked? (e.g. button/node just clicked on) @@ -435,12 +441,11 @@ namespace ImGui IMGUI_API ImVec2 GetItemRectMax(); // " IMGUI_API ImVec2 GetItemRectSize(); // " IMGUI_API void SetItemAllowOverlap(); // allow last item to be overlapped by a subsequent item. sometimes useful with invisible buttons, selectables, etc. to catch unused area. - IMGUI_API bool IsWindowFocused(); // is current window focused - IMGUI_API bool IsWindowHovered(); // is current window hovered and hoverable (not blocked by a popup) (differentiate child windows from each others) - IMGUI_API bool IsWindowRectHovered(); // is current window rectangle hovered, disregarding of any consideration of being blocked by a popup. (unlike IsWindowHovered() this will return true even if the window is blocked because of a popup) - IMGUI_API bool IsRootWindowFocused(); // is current root window focused (root = top-most parent of a child, otherwise self) - IMGUI_API bool IsRootWindowOrAnyChildFocused(); // is current root window or any of its child (including current window) focused - IMGUI_API bool IsRootWindowOrAnyChildHovered(); // is current root window or any of its child (including current window) hovered and hoverable (not blocked by a popup) + IMGUI_API bool IsWindowFocused(); // is current Begin()-ed window focused? + IMGUI_API bool IsWindowHovered(ImGuiHoveredFlags flags = 0); // is current Begin()-ed window hovered (and typically: not blocked by a popup/modal)? + IMGUI_API bool IsRootWindowFocused(); // is current Begin()-ed root window focused (root = top-most parent of a child, otherwise self)? + IMGUI_API bool IsRootWindowOrAnyChildFocused(); // is current Begin()-ed root window or any of its child (including current window) focused? + IMGUI_API bool IsRootWindowOrAnyChildHovered(ImGuiHoveredFlags flags = 0); // is current Begin()-ed root window or any of its child (including current window) hovered and hoverable (not blocked by a popup)? IMGUI_API bool IsAnyWindowFocused(); IMGUI_API bool IsAnyWindowHovered(); // is mouse hovering any visible window IMGUI_API bool IsRectVisible(const ImVec2& size); // test if rectangle (of given size, starting from cursor position) is visible / not clipped. @@ -496,19 +501,6 @@ namespace ImGui IMGUI_API ImGuiContext* GetCurrentContext(); IMGUI_API void SetCurrentContext(ImGuiContext* ctx); - // Obsolete functions (Will be removed! Also see 'API BREAKING CHANGES' section in imgui.cpp) -#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS - void SetNextWindowPosCenter(ImGuiCond cond = 0); // OBSOLETE 1.52+ - static inline bool IsItemHoveredRect() { return IsItemRectHovered(); } // OBSOLETE 1.51+ - static inline bool IsPosHoveringAnyWindow(const ImVec2&) { IM_ASSERT(0); return false; } // OBSOLETE 1.51+. This was partly broken. You probably wanted to use ImGui::GetIO().WantCaptureMouse instead. - static inline bool IsMouseHoveringAnyWindow() { return IsAnyWindowHovered(); } // OBSOLETE 1.51+ - static inline bool IsMouseHoveringWindow() { return IsWindowRectHovered(); } // OBSOLETE 1.51+ - static inline bool CollapsingHeader(const char* label, const char* str_id, bool framed = true, bool default_open = false) { (void)str_id; (void)framed; ImGuiTreeNodeFlags default_open_flags = 1<<5; return CollapsingHeader(label, (default_open ? default_open_flags : 0)); } // OBSOLETE 1.49+ - static inline ImFont* GetWindowFont() { return GetFont(); } // OBSOLETE 1.48+ - static inline float GetWindowFontSize() { return GetFontSize(); } // OBSOLETE 1.48+ - static inline void SetScrollPosHere() { SetScrollHere(); } // OBSOLETE 1.42+ -#endif - } // namespace ImGui // Flags for ImGui::Begin() @@ -524,7 +516,7 @@ enum ImGuiWindowFlags_ ImGuiWindowFlags_AlwaysAutoResize = 1 << 6, // Resize every window to its content every frame ImGuiWindowFlags_ShowBorders = 1 << 7, // Show borders around windows and items ImGuiWindowFlags_NoSavedSettings = 1 << 8, // Never load/save settings in .ini file - ImGuiWindowFlags_NoInputs = 1 << 9, // Disable catching mouse or keyboard inputs + ImGuiWindowFlags_NoInputs = 1 << 9, // Disable catching mouse or keyboard inputs, hovering test with pass through. ImGuiWindowFlags_MenuBar = 1 << 10, // Has a menu-bar ImGuiWindowFlags_HorizontalScrollbar = 1 << 11, // Allow horizontal scrollbar to appear (off by default). You may use SetNextWindowContentSize(ImVec2(width,0.0f)); prior to calling Begin() to specify width. Read code in imgui_demo in the "Horizontal Scrolling" section. ImGuiWindowFlags_NoFocusOnAppearing = 1 << 12, // Disable taking focus when transitioning from hidden to visible state @@ -534,7 +526,8 @@ enum ImGuiWindowFlags_ ImGuiWindowFlags_AlwaysUseWindowPadding = 1 << 16, // Ensure child windows without border uses style.WindowPadding (ignored by default for non-bordered child windows, because more convenient) ImGuiWindowFlags_NoNavFocus = 1 << 17, // No focusing of this window with gamepad/keyboard navigation ImGuiWindowFlags_NoNavInputs = 1 << 18, // No gamepad/keyboard navigation within the window - //ImGuiWindowFlags_NavFlattened = 1 << 19, // Allow gamepad/keyboard navigation to cross over parent border to this child (only use on child that have no scrolling!) + ImGuiWindowFlags_NavFlattened = 1 << 19, // Allow gamepad/keyboard navigation to cross over parent border to this child (only use on child that have no scrolling!) + ImGuiWindowFlags_NoNavScroll = 1 << 20, // No scrolling of this window with gamepad/keyboard navigation // [Internal] ImGuiWindowFlags_ChildWindow = 1 << 22, // Don't use! For internal use by BeginChild() ImGuiWindowFlags_ComboBox = 1 << 23, // Don't use! For internal use by ComboBox() @@ -581,8 +574,9 @@ enum ImGuiTreeNodeFlags_ ImGuiTreeNodeFlags_OpenOnArrow = 1 << 7, // Only open when clicking on the arrow part. If ImGuiTreeNodeFlags_OpenOnDoubleClick is also set, single-click arrow or double-click all box to open. ImGuiTreeNodeFlags_Leaf = 1 << 8, // No collapsing, no arrow (use as a convenience for leaf nodes). ImGuiTreeNodeFlags_Bullet = 1 << 9, // Display a bullet instead of arrow - //ImGuITreeNodeFlags_SpanAllAvailWidth = 1 << 10, // FIXME: TODO: Extend hit box horizontally even if not framed - //ImGuiTreeNodeFlags_NoScrollOnOpen = 1 << 11, // FIXME: TODO: Disable automatic scroll on TreePop() if node got just open and contents is not visible + ImGuiTreeNodeFlags_FramePadding = 1 << 10, // Use FramePadding (even for an unframed text node) to vertically align text baseline to regular widget height. Equivalent to calling AlignTextToFramePadding(). + //ImGuITreeNodeFlags_SpanAllAvailWidth = 1 << 11, // FIXME: TODO: Extend hit box horizontally even if not framed + //ImGuiTreeNodeFlags_NoScrollOnOpen = 1 << 12, // FIXME: TODO: Disable automatic scroll on TreePop() if node got just open and contents is not visible ImGuiTreeNodeFlags_CollapsingHeader = ImGuiTreeNodeFlags_Framed | ImGuiTreeNodeFlags_NoAutoOpenOnLog }; @@ -595,6 +589,17 @@ enum ImGuiSelectableFlags_ ImGuiSelectableFlags_AllowDoubleClick = 1 << 2 // Generate press events on double clicks too }; +// Flags for ImGui::IsItemHovered(), ImGui::IsWindowHovered() +enum ImGuiHoveredFlags_ +{ + ImGuiHoveredFlags_Default = 0, // Return true if directly over the item/window, not obstructed by another window, not obstructed by an active popup or modal blocking inputs under them. + ImGuiHoveredFlags_AllowWhenBlockedByPopup = 1 << 0, // Return true even if a popup window is normally blocking access to this item/window + //ImGuiHoveredFlags_AllowWhenBlockedByModal = 1 << 1, // Return true even if a modal popup window is normally blocking access to this item/window. FIXME-TODO: Unavailable yet. + ImGuiHoveredFlags_AllowWhenBlockedByActiveItem = 1 << 2, // Return true even if an active item is blocking access to this item/window + ImGuiHoveredFlags_AllowWhenOverlapped = 1 << 3, // Return true even if the position is overlapped by another window + ImGuiHoveredFlags_RectOnly = ImGuiHoveredFlags_AllowWhenBlockedByPopup | ImGuiHoveredFlags_AllowWhenBlockedByActiveItem | ImGuiHoveredFlags_AllowWhenOverlapped +}; + // User fill ImGuiIO.KeyMap[] array with indices into the ImGuiIO.KeysDown[512] array enum ImGuiKey_ { @@ -643,6 +648,7 @@ enum ImGuiNavInput_ ImGuiNavInput_PadFocusNext, // prev window (with PadMenu held) // e.g. R-trigger ImGuiNavInput_PadTweakSlow, // slower tweaks // e.g. L-trigger, analog ImGuiNavInput_PadTweakFast, // faster tweaks // e.g. R-trigger, analog + ImGuiNavInput_KeyMenu, // access menu // e.g. ALT ImGuiNavInput_COUNT, }; @@ -896,41 +902,63 @@ struct ImGuiIO // Output - Retrieve after calling NewFrame() //------------------------------------------------------------------ - bool WantCaptureMouse; // Mouse is hovering a window or widget is active (= ImGui will use your mouse input). Use to hide mouse from the rest of your application - bool WantCaptureKeyboard; // Widget is active (= ImGui will use your keyboard input). Use to hide keyboard from the rest of your application - bool WantTextInput; // Some text input widget is active, which will read input characters from the InputCharacters array. Use to activate on screen keyboard if your system needs one - bool WantMoveMouse; // MousePos has been altered. back-end should reposition mouse on next frame. used only if 'NavMovesMouse=true'. - bool NavUsable; // Directional navigation is currently allowed (ImGuiKey_NavXXX events). - bool NavActive; // Directional navigation is active/visible and currently allowed (ImGuiKey_NavXXX events). + bool WantCaptureMouse; // When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application. This is set by ImGui when it wants to use your mouse (e.g. unclicked mouse is hovering a window, or a widget is active). + bool WantCaptureKeyboard; // When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application. This is set by ImGui when it wants to use your keyboard inputs. + bool WantTextInput; // Mobile/console: when io.WantTextInput is true, you may display an on-screen keyboard. This is set by ImGui when it wants textual keyboard input to happen (e.g. when a InputText widget is active). + bool WantMoveMouse; // MousePos has been altered, back-end should reposition mouse on next frame. Set only when 'NavMovesMouse=true'. + bool NavUsable; // Directional navigation is currently allowed (will handle ImGuiKey_NavXXX events). + bool NavActive; // Directional navigation is active/visible and currently allowed (will handle ImGuiKey_NavXXX events). float Framerate; // Application framerate estimation, in frame per second. Solely for convenience. Rolling average estimation based on IO.DeltaTime over 120 frames int MetricsAllocs; // Number of active memory allocations int MetricsRenderVertices; // Vertices output during last call to Render() int MetricsRenderIndices; // Indices output during last call to Render() = number of triangles * 3 int MetricsActiveWindows; // Number of visible root windows (exclude child windows) - ImVec2 MouseDelta; // Mouse delta. Note that this is zero if either current or previous position are negative, so a disappearing/reappearing mouse won't have a huge delta for one frame. + ImVec2 MouseDelta; // Mouse delta. Note that this is zero if either current or previous position are invalid (-FLT_MAX,-FLT_MAX), so a disappearing/reappearing mouse won't have a huge delta. //------------------------------------------------------------------ // [Internal] ImGui will maintain those fields. Forward compatibility not guaranteed! //------------------------------------------------------------------ ImVec2 MousePosPrev; // Previous mouse position temporary storage (nb: not for public use, set to MousePos in NewFrame()) - bool MouseClicked[5]; // Mouse button went from !Down to Down ImVec2 MouseClickedPos[5]; // Position at time of clicking float MouseClickedTime[5]; // Time of last click (used to figure out double-click) + bool MouseClicked[5]; // Mouse button went from !Down to Down bool MouseDoubleClicked[5]; // Has mouse button been double-clicked? bool MouseReleased[5]; // Mouse button went from Down to !Down bool MouseDownOwned[5]; // Track if button was clicked inside a window. We don't request mouse capture from the application if click started outside ImGui bounds. float MouseDownDuration[5]; // Duration the mouse button has been down (0.0f == just clicked) float MouseDownDurationPrev[5]; // Previous time the mouse button has been down - float MouseDragMaxDistanceSqr[5]; // Squared maximum distance of how much mouse has traveled from the click point + ImVec2 MouseDragMaxDistanceAbs[5]; // Maximum distance, absolute, on each axis, of how much mouse has traveled from the clicking point + float MouseDragMaxDistanceSqr[5]; // Squared maximum distance of how much mouse has traveled from the clicking point float KeysDownDuration[512]; // Duration the keyboard key has been down (0.0f == just pressed) float KeysDownDurationPrev[512]; // Previous duration the key has been down float NavInputsDownDuration[ImGuiNavInput_COUNT]; - float NavInputsPrev[ImGuiNavInput_COUNT]; + float NavInputsDownDurationPrev[ImGuiNavInput_COUNT]; IMGUI_API ImGuiIO(); }; +//----------------------------------------------------------------------------- +// Obsolete functions (Will be removed! Also see 'API BREAKING CHANGES' section in imgui.cpp) +//----------------------------------------------------------------------------- + +#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS +namespace ImGui +{ + bool Begin(const char* name, bool* p_open, const ImVec2& size_on_first_use, float bg_alpha_override = -1.0f, ImGuiWindowFlags flags = 0); // OBSOLETE 1.52+. use SetNextWindowSize() instead if you want to set a window size. + static inline void AlignFirstTextHeightToWidgets() { AlignTextToFramePadding(); } // OBSOLETE 1.52+ + static inline void SetNextWindowPosCenter(ImGuiCond cond = 0) { SetNextWindowPos(ImVec2(GetIO().DisplaySize.x * 0.5f, GetIO().DisplaySize.y * 0.5f), cond, ImVec2(0.5f, 0.5f)); } // OBSOLETE 1.52+ + static inline bool IsItemHoveredRect() { return IsItemHovered(ImGuiHoveredFlags_RectOnly); } // OBSOLETE 1.51+ + static inline bool IsPosHoveringAnyWindow(const ImVec2&) { IM_ASSERT(0); return false; } // OBSOLETE 1.51+. This was partly broken. You probably wanted to use ImGui::GetIO().WantCaptureMouse instead. + static inline bool IsMouseHoveringAnyWindow() { return IsAnyWindowHovered(); } // OBSOLETE 1.51+ + static inline bool IsMouseHoveringWindow() { return IsWindowHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup | ImGuiHoveredFlags_AllowWhenBlockedByActiveItem); } // OBSOLETE 1.51+ + static inline bool CollapsingHeader(const char* label, const char* str_id, bool framed = true, bool default_open = false) { (void)str_id; (void)framed; ImGuiTreeNodeFlags default_open_flags = 1 << 5; return CollapsingHeader(label, (default_open ? default_open_flags : 0)); } // OBSOLETE 1.49+ + static inline ImFont* GetWindowFont() { return GetFont(); } // OBSOLETE 1.48+ + static inline float GetWindowFontSize() { return GetFontSize(); } // OBSOLETE 1.48+ + static inline void SetScrollPosHere() { SetScrollHere(); } // OBSOLETE 1.42+ +} +#endif + //----------------------------------------------------------------------------- // Helpers //----------------------------------------------------------------------------- @@ -1417,9 +1445,9 @@ struct ImFontAtlas IMGUI_API ImFont* AddFont(const ImFontConfig* font_cfg); IMGUI_API ImFont* AddFontDefault(const ImFontConfig* font_cfg = NULL); IMGUI_API ImFont* AddFontFromFileTTF(const char* filename, float size_pixels, const ImFontConfig* font_cfg = NULL, const ImWchar* glyph_ranges = NULL); - IMGUI_API ImFont* AddFontFromMemoryTTF(void* font_data, int font_size, float size_pixels, const ImFontConfig* font_cfg = NULL, const ImWchar* glyph_ranges = NULL); // Transfer ownership of 'ttf_data' to ImFontAtlas, will be deleted after Build() - IMGUI_API ImFont* AddFontFromMemoryCompressedTTF(const void* compressed_font_data, int compressed_font_size, float size_pixels, const ImFontConfig* font_cfg = NULL, const ImWchar* glyph_ranges = NULL); // 'compressed_font_data' still owned by caller. Compress with binary_to_compressed_c.cpp - IMGUI_API ImFont* AddFontFromMemoryCompressedBase85TTF(const char* compressed_font_data_base85, float size_pixels, const ImFontConfig* font_cfg = NULL, const ImWchar* glyph_ranges = NULL); // 'compressed_font_data_base85' still owned by caller. Compress with binary_to_compressed_c.cpp with -base85 paramaeter + IMGUI_API ImFont* AddFontFromMemoryTTF(void* font_data, int font_size, float size_pixels, const ImFontConfig* font_cfg = NULL, const ImWchar* glyph_ranges = NULL); // Note: Transfer ownership of 'ttf_data' to ImFontAtlas! Will be deleted after Build(). Set font_cfg->FontDataOwnedByAtlas to false to keep ownership. + IMGUI_API ImFont* AddFontFromMemoryCompressedTTF(const void* compressed_font_data, int compressed_font_size, float size_pixels, const ImFontConfig* font_cfg = NULL, const ImWchar* glyph_ranges = NULL); // 'compressed_font_data' still owned by caller. Compress with binary_to_compressed_c.cpp. + IMGUI_API ImFont* AddFontFromMemoryCompressedBase85TTF(const char* compressed_font_data_base85, float size_pixels, const ImFontConfig* font_cfg = NULL, const ImWchar* glyph_ranges = NULL); // 'compressed_font_data_base85' still owned by caller. Compress with binary_to_compressed_c.cpp with -base85 parameter. IMGUI_API void ClearTexData(); // Clear the CPU-side texture data. Saves RAM once the texture has been copied to graphics memory. IMGUI_API void ClearInputData(); // Clear the input TTF data (inc sizes, glyph ranges) IMGUI_API void ClearFonts(); // Clear the ImGui-side font data (glyphs storage, UV coordinates) @@ -1529,7 +1557,7 @@ struct ImFont // Methods IMGUI_API ImFont(); IMGUI_API ~ImFont(); - IMGUI_API void Clear(); + IMGUI_API void ClearOutputData(); IMGUI_API void BuildLookupTable(); IMGUI_API const ImFontGlyph*FindGlyph(ImWchar c) const; IMGUI_API void SetFallbackChar(ImWchar c); diff --git a/deps/cimgui/imgui/imgui_demo.cpp b/deps/cimgui/imgui/imgui_demo.cpp index c058fa1e..89b73118 100644 --- a/deps/cimgui/imgui/imgui_demo.cpp +++ b/deps/cimgui/imgui/imgui_demo.cpp @@ -1,4 +1,4 @@ -// dear imgui, v1.52 WIP +// dear imgui, v1.53 WIP // (demo code) // Message to the person tempted to delete this file when integrating ImGui into their code base: @@ -101,23 +101,23 @@ static void ShowHelpMarker(const char* desc) void ImGui::ShowUserGuide() { ImGui::BulletText("Double-click on title bar to collapse window."); - ImGui::BulletText("Click and drag on lower right corner to resize window."); + ImGui::BulletText("Click and drag on lower right corner to resize window\n(double-click to auto fit window to its contents)."); ImGui::BulletText("Click and drag on any empty space to move window."); - ImGui::BulletText("Mouse Wheel to scroll."); + ImGui::BulletText("TAB/SHIFT+TAB to cycle through keyboard editable fields."); + ImGui::BulletText("CTRL+Click on a slider or drag box to input value as text."); if (ImGui::GetIO().FontAllowUserScaling) ImGui::BulletText("CTRL+Mouse Wheel to zoom window contents."); - ImGui::BulletText("TAB/SHIFT+TAB to cycle through keyboard editable fields."); - ImGui::BulletText("CTRL+Click on a slider or drag box to input text."); - ImGui::BulletText( - "While editing text:\n" - "- Hold SHIFT or use mouse to select text\n" - "- CTRL+Left/Right to word jump\n" - "- CTRL+A or double-click to select all\n" - "- CTRL+X,CTRL+C,CTRL+V clipboard\n" - "- CTRL+Z,CTRL+Y undo/redo\n" - "- ESCAPE to revert\n" - "- You can apply arithmetic operators +,*,/ on numerical values.\n" - " Use +- to subtract.\n"); + ImGui::BulletText("Mouse Wheel to scroll."); + ImGui::BulletText("While editing text:\n"); + ImGui::Indent(); + ImGui::BulletText("Hold SHIFT or use mouse to select text."); + ImGui::BulletText("CTRL+Left/Right to word jump."); + ImGui::BulletText("CTRL+A or double-click to select all."); + ImGui::BulletText("CTRL+X,CTRL+C,CTRL+V to use clipboard."); + ImGui::BulletText("CTRL+Z,CTRL+Y to undo/redo."); + ImGui::BulletText("ESCAPE to revert."); + ImGui::BulletText("You can apply arithmetic operators +,*,/ on numerical values.\nUse +- to subtract."); + ImGui::Unindent(); } // Demonstrate most ImGui features (big function!) @@ -232,7 +232,8 @@ void ImGui::ShowTestWindow(bool* p_open) ImGui::Spacing(); if (ImGui::CollapsingHeader("Help")) { - ImGui::TextWrapped("This window is being created by the ShowTestWindow() function. Please refer to the code for programming reference.\n\nUser Guide:"); + ImGui::TextWrapped("This window is being created by the ShowTestWindow() function. Please refer to the code in imgui_demo.cpp for reference.\n\n"); + ImGui::Text("USER GUIDE:"); ImGui::ShowUserGuide(); } @@ -432,7 +433,8 @@ void ImGui::ShowTestWindow(bool* p_open) else { // Leaf: The only reason we have a TreeNode at all is to allow selection of the leaf. Otherwise we can use BulletText() or TreeAdvanceToLabelPos()+Text(). - ImGui::TreeNodeEx((void*)(intptr_t)i, node_flags | ImGuiTreeNodeFlags_Leaf | ImGuiTreeNodeFlags_NoTreePushOnOpen, "Selectable Leaf %d", i); + node_flags |= ImGuiTreeNodeFlags_Leaf | ImGuiTreeNodeFlags_NoTreePushOnOpen; // ImGuiTreeNodeFlags_Bullet + ImGui::TreeNodeEx((void*)(intptr_t)i, node_flags, "Selectable Leaf %d", i); if (ImGui::IsItemClicked()) node_clicked = i; } @@ -459,11 +461,13 @@ void ImGui::ShowTestWindow(bool* p_open) ImGui::Checkbox("Enable extra group", &closable_group); if (ImGui::CollapsingHeader("Header")) { + ImGui::Text("IsItemHovered: %d", IsItemHovered()); for (int i = 0; i < 5; i++) ImGui::Text("Some content %d", i); } if (ImGui::CollapsingHeader("Header with a close button", &closable_group)) { + ImGui::Text("IsItemHovered: %d", IsItemHovered()); for (int i = 0; i < 5; i++) ImGui::Text("More content %d", i); } @@ -542,17 +546,27 @@ void ImGui::ShowTestWindow(bool* p_open) { ImGui::TextWrapped("Below we are displaying the font texture (which is the only texture we have access to in this demo). Use the 'ImTextureID' type as storage to pass pointers or identifier to your own texture data. Hover the texture for a zoomed view!"); ImVec2 tex_screen_pos = ImGui::GetCursorScreenPos(); - float tex_w = (float)ImGui::GetIO().Fonts->TexWidth; - float tex_h = (float)ImGui::GetIO().Fonts->TexHeight; - ImTextureID tex_id = ImGui::GetIO().Fonts->TexID; + ImGuiIO& io = ImGui::GetIO(); + + // Here we are grabbing the font texture because that's the only one we have access to inside the demo code. + // Remember that ImTextureID is just storage for whatever you want it to be, it is essentially a value that will be passed to the render function inside the ImDrawCmd structure. + // If you use one of the default imgui_impl_XXXX.cpp renderer, they all have comments at the top of their file to specify what they expect to be stored in ImTextureID. + // (for example, the imgui_impl_dx11.cpp renderer expect a 'ID3D11ShaderResourceView*' pointer. The imgui_impl_glfw_gl3.cpp renderer expect a GLuint OpenGL texture identifier etc.) + // If you decided that ImTextureID = MyEngineTexture*, then you can pass your MyEngineTexture* pointers to ImGui::Image(), and gather width/height through your own functions, etc. + // Using ShowMetricsWindow() as a "debugger" to inspect the draw data that are being passed to your render will help you debug issues if you are confused about this. + // Consider using the lower-level ImDrawList::AddImage() API, via ImGui::GetWindowDrawList()->AddImage(). + ImTextureID tex_id = io.Fonts->TexID; + float tex_w = (float)io.Fonts->TexWidth; + float tex_h = (float)io.Fonts->TexHeight; + ImGui::Text("%.0fx%.0f", tex_w, tex_h); ImGui::Image(tex_id, ImVec2(tex_w, tex_h), ImVec2(0,0), ImVec2(1,1), ImColor(255,255,255,255), ImColor(255,255,255,128)); if (ImGui::IsItemHovered()) { ImGui::BeginTooltip(); float focus_sz = 32.0f; - float focus_x = ImGui::GetMousePos().x - tex_screen_pos.x - focus_sz * 0.5f; if (focus_x < 0.0f) focus_x = 0.0f; else if (focus_x > tex_w - focus_sz) focus_x = tex_w - focus_sz; - float focus_y = ImGui::GetMousePos().y - tex_screen_pos.y - focus_sz * 0.5f; if (focus_y < 0.0f) focus_y = 0.0f; else if (focus_y > tex_h - focus_sz) focus_y = tex_h - focus_sz; + float focus_x = io.MousePos.x - tex_screen_pos.x - focus_sz * 0.5f; if (focus_x < 0.0f) focus_x = 0.0f; else if (focus_x > tex_w - focus_sz) focus_x = tex_w - focus_sz; + float focus_y = io.MousePos.y - tex_screen_pos.y - focus_sz * 0.5f; if (focus_y < 0.0f) focus_y = 0.0f; else if (focus_y > tex_h - focus_sz) focus_y = tex_h - focus_sz; ImGui::Text("Min: (%.2f, %.2f)", focus_x, focus_y); ImGui::Text("Max: (%.2f, %.2f)", focus_x + focus_sz, focus_y + focus_sz); ImVec2 uv0 = ImVec2((focus_x) / tex_w, (focus_y) / tex_h); @@ -1056,7 +1070,7 @@ void ImGui::ShowTestWindow(bool* p_open) ImGui::TextColored(ImVec4(1,1,0,1), "Sailor"); // Button - ImGui::AlignFirstTextHeightToWidgets(); + ImGui::AlignTextToFramePadding(); ImGui::Text("Normal buttons"); ImGui::SameLine(); ImGui::Button("Banana"); ImGui::SameLine(); ImGui::Button("Apple"); ImGui::SameLine(); @@ -1182,7 +1196,7 @@ void ImGui::ShowTestWindow(bool* p_open) ImGui::Text("TEST"); ImGui::SameLine(); ImGui::SmallButton("TEST##2"); - ImGui::AlignFirstTextHeightToWidgets(); // If your line starts with text, call this to align it to upcoming widgets. + ImGui::AlignTextToFramePadding(); // If your line starts with text, call this to align it to upcoming widgets. ImGui::Text("Text aligned to Widget"); ImGui::SameLine(); ImGui::Button("Widget##1"); ImGui::SameLine(); ImGui::Text("Widget"); ImGui::SameLine(); @@ -1195,7 +1209,7 @@ void ImGui::ShowTestWindow(bool* p_open) ImGui::SameLine(0.0f, spacing); if (ImGui::TreeNode("Node##1")) { for (int i = 0; i < 6; i++) ImGui::BulletText("Item %d..", i); ImGui::TreePop(); } // Dummy tree data - ImGui::AlignFirstTextHeightToWidgets(); // Vertically align text node a bit lower so it'll be vertically centered with upcoming widget. Otherwise you can use SmallButton (smaller fit). + ImGui::AlignTextToFramePadding(); // Vertically align text node a bit lower so it'll be vertically centered with upcoming widget. Otherwise you can use SmallButton (smaller fit). bool node_open = ImGui::TreeNode("Node##2"); // Common mistake to avoid: if we want to SameLine after TreeNode we need to do it before we add child content. ImGui::SameLine(0.0f, spacing); ImGui::Button("Button##2"); if (node_open) { for (int i = 0; i < 6; i++) ImGui::BulletText("Item %d..", i); ImGui::TreePop(); } // Dummy tree data @@ -1205,7 +1219,7 @@ void ImGui::ShowTestWindow(bool* p_open) ImGui::SameLine(0.0f, spacing); ImGui::BulletText("Bullet text"); - ImGui::AlignFirstTextHeightToWidgets(); + ImGui::AlignTextToFramePadding(); ImGui::BulletText("Node"); ImGui::SameLine(0.0f, spacing); ImGui::Button("Button##4"); @@ -1383,41 +1397,32 @@ void ImGui::ShowTestWindow(bool* p_open) ImGui::EndPopup(); } - ImGui::Spacing(); - ImGui::TextWrapped("Below we are testing adding menu items to a regular window. It's rather unusual but should work!"); - ImGui::Separator(); - // NB: As a quirk in this very specific example, we want to differentiate the parent of this menu from the parent of the various popup menus above. - // To do so we are encloding the items in a PushID()/PopID() block to make them two different menusets. If we don't, opening any popup above and hovering our menu here - // would open it. This is because once a menu is active, we allow to switch to a sibling menu by just hovering on it, which is the desired behavior for regular menus. - ImGui::PushID("foo"); - ImGui::MenuItem("Menu item", "CTRL+M"); - if (ImGui::BeginMenu("Menu inside a regular window")) - { - ShowExampleMenuFile(); - ImGui::EndMenu(); - } - ImGui::PopID(); - ImGui::Separator(); - ImGui::TreePop(); } if (ImGui::TreeNode("Context menus")) { + // BeginPopupContextItem() is a helper to provide common/simple popup behavior of essentially doing: + // if (IsItemHovered() && IsMouseClicked(0)) + // OpenPopup(id); + // return BeginPopup(id); + // For more advanced uses you may want to replicate and cuztomize this code. This the comments inside BeginPopupContextItem() implementation. static float value = 0.5f; ImGui::Text("Value = %.3f (<-- right-click here)", value); if (ImGui::BeginPopupContextItem("item context menu")) { if (ImGui::Selectable("Set to zero")) value = 0.0f; if (ImGui::Selectable("Set to PI")) value = 3.1415f; - ImGui::DragFloat("Value", &value, 0.1f, 0.0f, 0.0f); + ImGui::PushItemWidth(-1); + ImGui::DragFloat("##Value", &value, 0.1f, 0.0f, 0.0f); + ImGui::PopItemWidth(); ImGui::EndPopup(); } static char name[32] = "Label1"; - char buf[64]; sprintf(buf, "Button: %s###Button", name); // ### operator override ID ignoring the preceeding label + char buf[64]; sprintf(buf, "Button: %s###Button", name); // ### operator override ID ignoring the preceding label ImGui::Button(buf); - if (ImGui::BeginPopupContextItem("rename context menu")) + if (ImGui::BeginPopupContextItem()) // When used after an item that has an ID (here the Button), we can skip providing an ID to BeginPopupContextItem(). { ImGui::Text("Edit name:"); ImGui::InputText("##edit", name, IM_ARRAYSIZE(name)); @@ -1463,6 +1468,8 @@ void ImGui::ShowTestWindow(bool* p_open) ImGui::Text("Hello from Stacked The First\nUsing style.Colors[ImGuiCol_ModalWindowDarkening] for darkening."); static int item = 1; ImGui::Combo("Combo", &item, "aaaa\0bbbb\0cccc\0dddd\0eeee\0\0"); + static float color[4] = { 0.4f,0.7f,0.0f,0.5f }; + ImGui::ColorEdit4("color", color); // This is to test behavior of stacked regular popups over a modal if (ImGui::Button("Add another modal..")) ImGui::OpenPopup("Stacked 2"); @@ -1481,6 +1488,25 @@ void ImGui::ShowTestWindow(bool* p_open) ImGui::TreePop(); } + + if (ImGui::TreeNode("Menus inside a regular window")) + { + ImGui::TextWrapped("Below we are testing adding menu items to a regular window. It's rather unusual but should work!"); + ImGui::Separator(); + // NB: As a quirk in this very specific example, we want to differentiate the parent of this menu from the parent of the various popup menus above. + // To do so we are encloding the items in a PushID()/PopID() block to make them two different menusets. If we don't, opening any popup above and hovering our menu here + // would open it. This is because once a menu is active, we allow to switch to a sibling menu by just hovering on it, which is the desired behavior for regular menus. + ImGui::PushID("foo"); + ImGui::MenuItem("Menu item", "CTRL+M"); + if (ImGui::BeginMenu("Menu inside a regular window")) + { + ShowExampleMenuFile(); + ImGui::EndMenu(); + } + ImGui::PopID(); + ImGui::Separator(); + ImGui::TreePop(); + } } if (ImGui::CollapsingHeader("Columns")) @@ -1788,6 +1814,34 @@ void ImGui::ShowTestWindow(bool* p_open) } #endif + if (ImGui::TreeNode("Hovering")) + { + // Testing IsWindowHovered() function + ImGui::BulletText( + "IsWindowHovered() = %d\n" + "IsWindowHovered(_AllowWhenBlockedByPopup) = %d\n" + "IsWindowHovered(_AllowWhenBlockedByActiveItem) = %d\n", + ImGui::IsWindowHovered(), + ImGui::IsWindowHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup), + ImGui::IsWindowHovered(ImGuiHoveredFlags_AllowWhenBlockedByActiveItem)); + + // Testing IsItemHovered() function (because BulletText is an item itself and that would affect the output of IsItemHovered, we pass all lines in a single items to shorten the code) + ImGui::Button("ITEM"); + ImGui::BulletText( + "IsItemHovered() = %d\n" + "IsItemHovered(_AllowWhenBlockedByPopup) = %d\n" + "IsItemHovered(_AllowWhenBlockedByActiveItem) = %d\n" + "IsItemHovered(_AllowWhenOverlapped) = %d\n" + "IsItemhovered(_RectOnly) = %d\n", + ImGui::IsItemHovered(), + ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup), + ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByActiveItem), + ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenOverlapped), + ImGui::IsItemHovered(ImGuiHoveredFlags_RectOnly)); + + ImGui::TreePop(); + } + if (ImGui::TreeNode("Dragging")) { ImGui::TextWrapped("You can use ImGui::GetMouseDragDelta(0) to query for the dragged amount on any widget."); @@ -1946,6 +2000,7 @@ void ImGui::ShowStyleEditor(ImGuiStyle* ref) for (int i = 0; i < atlas->Fonts.Size; i++) { ImFont* font = atlas->Fonts[i]; + ImGui::PushID(font); bool font_details_opened = ImGui::TreeNode(font, "Font %d: \'%s\', %.2f px, %d glyphs", i, font->ConfigData ? font->ConfigData[0].Name : "", font->FontSize, font->Glyphs.Size); ImGui::SameLine(); if (ImGui::SmallButton("Set as default")) ImGui::GetIO().FontDefault = font; if (font_details_opened) @@ -2006,6 +2061,7 @@ void ImGui::ShowStyleEditor(ImGuiStyle* ref) } ImGui::TreePop(); } + ImGui::PopID(); } static float window_scale = 1.0f; ImGui::DragFloat("this window scale", &window_scale, 0.005f, 0.3f, 2.0f, "%.1f"); // scale only this window @@ -2162,7 +2218,7 @@ static void ShowExampleAppFixedOverlay(bool* p_open) ImVec2 window_pos = ImVec2((corner & 1) ? ImGui::GetIO().DisplaySize.x - DISTANCE : DISTANCE, (corner & 2) ? ImGui::GetIO().DisplaySize.y - DISTANCE : DISTANCE); ImVec2 window_pos_pivot = ImVec2((corner & 1) ? 1.0f : 0.0f, (corner & 2) ? 1.0f : 0.0f); ImGui::SetNextWindowPos(window_pos, ImGuiCond_Always, window_pos_pivot); - ImGui::PushStyleColor(ImGuiCol_WindowBg, ImVec4(0.0f, 0.0f, 0.0f, 0.3f)); + ImGui::PushStyleColor(ImGuiCol_WindowBg, ImVec4(0.0f, 0.0f, 0.0f, 0.3f)); // Transparent background if (ImGui::Begin("Example: Fixed Overlay", p_open, ImGuiWindowFlags_NoTitleBar|ImGuiWindowFlags_NoResize|ImGuiWindowFlags_AlwaysAutoResize|ImGuiWindowFlags_NoMove|ImGuiWindowFlags_NoSavedSettings|ImGuiWindowFlags_NoFocusOnAppearing|ImGuiWindowFlags_NoNavFocus|ImGuiWindowFlags_NoNavInputs)) { ImGui::Text("Simple overlay\nin the corner of the screen.\n(right-click to change position)"); @@ -2352,6 +2408,7 @@ struct ExampleAppConsole void AddLog(const char* fmt, ...) IM_FMTARGS(2) { + // FIXME-OPT char buf[1024]; va_list args; va_start(args, fmt); @@ -2752,10 +2809,10 @@ static void ShowExampleAppPropertyEditor(bool* p_open) static void ShowDummyObject(const char* prefix, int uid) { ImGui::PushID(uid); // Use object uid as identifier. Most commonly you could also use the object pointer as a base ID. - ImGui::AlignFirstTextHeightToWidgets(); // Text and Tree nodes are less high than regular widgets, here we add vertical spacing to make the tree lines equal high. + ImGui::AlignTextToFramePadding(); // Text and Tree nodes are less high than regular widgets, here we add vertical spacing to make the tree lines equal high. bool node_open = ImGui::TreeNode("Object", "%s_%u", prefix, uid); ImGui::NextColumn(); - ImGui::AlignFirstTextHeightToWidgets(); + ImGui::AlignTextToFramePadding(); ImGui::Text("my sailor is rich"); ImGui::NextColumn(); if (node_open) @@ -2770,7 +2827,7 @@ static void ShowExampleAppPropertyEditor(bool* p_open) } else { - ImGui::AlignFirstTextHeightToWidgets(); + ImGui::AlignTextToFramePadding(); // Here we use a Selectable (instead of Text) to highlight on hover //ImGui::Text("Field_%d", i); char label[32]; diff --git a/deps/cimgui/imgui/imgui_draw.cpp b/deps/cimgui/imgui/imgui_draw.cpp index 73647689..5ff98173 100644 --- a/deps/cimgui/imgui/imgui_draw.cpp +++ b/deps/cimgui/imgui/imgui_draw.cpp @@ -1,7 +1,8 @@ -// dear imgui, v1.52 WIP +// dear imgui, v1.53 WIP // (drawing and font code) // Contains implementation for +// - Default styles // - ImDrawList // - ImDrawData // - ImFontAtlas @@ -116,6 +117,113 @@ namespace IMGUI_STB_NAMESPACE using namespace IMGUI_STB_NAMESPACE; #endif +//----------------------------------------------------------------------------- +// Style functions +//----------------------------------------------------------------------------- + +void ImGui::StyleColorsClassic(ImGuiStyle* dst) +{ + ImGuiStyle* style = dst ? dst : &ImGui::GetStyle(); + ImVec4* colors = style->Colors; + + colors[ImGuiCol_Text] = ImVec4(0.90f, 0.90f, 0.90f, 1.00f); + colors[ImGuiCol_TextDisabled] = ImVec4(0.60f, 0.60f, 0.60f, 1.00f); + colors[ImGuiCol_WindowBg] = ImVec4(0.00f, 0.00f, 0.00f, 0.70f); + colors[ImGuiCol_ChildWindowBg] = ImVec4(0.00f, 0.00f, 0.00f, 0.00f); + colors[ImGuiCol_PopupBg] = ImVec4(0.05f, 0.05f, 0.10f, 0.90f); + colors[ImGuiCol_Border] = ImVec4(0.70f, 0.70f, 0.70f, 0.40f); + colors[ImGuiCol_BorderShadow] = ImVec4(0.00f, 0.00f, 0.00f, 0.00f); + colors[ImGuiCol_FrameBg] = ImVec4(0.80f, 0.80f, 0.80f, 0.30f); // Background of checkbox, radio button, plot, slider, text input + colors[ImGuiCol_FrameBgHovered] = ImVec4(0.90f, 0.80f, 0.80f, 0.40f); + colors[ImGuiCol_FrameBgActive] = ImVec4(0.90f, 0.65f, 0.65f, 0.45f); + colors[ImGuiCol_TitleBg] = ImVec4(0.24f, 0.24f, 0.50f, 0.83f); + colors[ImGuiCol_TitleBgCollapsed] = ImVec4(0.40f, 0.40f, 0.80f, 0.20f); + colors[ImGuiCol_TitleBgActive] = ImVec4(0.33f, 0.33f, 0.65f, 0.87f); + colors[ImGuiCol_MenuBarBg] = ImVec4(0.40f, 0.40f, 0.55f, 0.80f); + colors[ImGuiCol_ScrollbarBg] = ImVec4(0.20f, 0.25f, 0.30f, 0.60f); + colors[ImGuiCol_ScrollbarGrab] = ImVec4(0.40f, 0.40f, 0.80f, 0.30f); + colors[ImGuiCol_ScrollbarGrabHovered] = ImVec4(0.40f, 0.40f, 0.80f, 0.40f); + colors[ImGuiCol_ScrollbarGrabActive] = ImVec4(0.80f, 0.50f, 0.50f, 0.40f); + colors[ImGuiCol_ComboBg] = ImVec4(0.20f, 0.20f, 0.20f, 0.99f); + colors[ImGuiCol_CheckMark] = ImVec4(0.90f, 0.90f, 0.90f, 0.50f); + colors[ImGuiCol_SliderGrab] = ImVec4(1.00f, 1.00f, 1.00f, 0.30f); + colors[ImGuiCol_SliderGrabActive] = ImVec4(0.80f, 0.50f, 0.50f, 1.00f); + colors[ImGuiCol_Button] = ImVec4(0.67f, 0.40f, 0.40f, 0.60f); + colors[ImGuiCol_ButtonHovered] = ImVec4(0.67f, 0.40f, 0.40f, 1.00f); + colors[ImGuiCol_ButtonActive] = ImVec4(0.80f, 0.50f, 0.50f, 1.00f); + colors[ImGuiCol_Header] = ImVec4(0.40f, 0.40f, 0.90f, 0.45f); + colors[ImGuiCol_HeaderHovered] = ImVec4(0.45f, 0.45f, 0.90f, 0.80f); + colors[ImGuiCol_HeaderActive] = ImVec4(0.53f, 0.53f, 0.87f, 0.80f); + colors[ImGuiCol_Separator] = ImVec4(0.50f, 0.50f, 0.50f, 1.00f); + colors[ImGuiCol_SeparatorHovered] = ImVec4(0.60f, 0.60f, 0.70f, 1.00f); + colors[ImGuiCol_SeparatorActive] = ImVec4(0.70f, 0.70f, 0.90f, 1.00f); + colors[ImGuiCol_ResizeGrip] = ImVec4(1.00f, 1.00f, 1.00f, 0.30f); + colors[ImGuiCol_ResizeGripHovered] = ImVec4(1.00f, 1.00f, 1.00f, 0.60f); + colors[ImGuiCol_ResizeGripActive] = ImVec4(1.00f, 1.00f, 1.00f, 0.90f); + colors[ImGuiCol_CloseButton] = ImVec4(0.50f, 0.50f, 0.90f, 0.50f); + colors[ImGuiCol_CloseButtonHovered] = ImVec4(0.70f, 0.70f, 0.90f, 0.60f); + colors[ImGuiCol_CloseButtonActive] = ImVec4(0.70f, 0.70f, 0.70f, 1.00f); + colors[ImGuiCol_PlotLines] = ImVec4(1.00f, 1.00f, 1.00f, 1.00f); + colors[ImGuiCol_PlotLinesHovered] = ImVec4(0.90f, 0.70f, 0.00f, 1.00f); + colors[ImGuiCol_PlotHistogram] = ImVec4(0.90f, 0.70f, 0.00f, 1.00f); + colors[ImGuiCol_PlotHistogramHovered] = ImVec4(1.00f, 0.60f, 0.00f, 1.00f); + colors[ImGuiCol_TextSelectedBg] = ImVec4(0.00f, 0.00f, 1.00f, 0.35f); + colors[ImGuiCol_ModalWindowDarkening] = ImVec4(0.20f, 0.20f, 0.20f, 0.35f); + colors[ImGuiCol_NavHighlight] = colors[ImGuiCol_HeaderHovered]; + colors[ImGuiCol_NavWindowingHighlight] = ImVec4(1.00f, 1.00f, 1.00f, 0.12f); +} + +void ImGui::StyleColorsDark(ImGuiStyle* dst) +{ + ImGuiStyle* style = dst ? dst : &ImGui::GetStyle(); + ImVec4* colors = style->Colors; + + colors[ImGuiCol_Text] = ImVec4(1.00f, 1.00f, 1.00f, 1.00f); + colors[ImGuiCol_TextDisabled] = ImVec4(0.40f, 0.40f, 0.40f, 1.00f); + colors[ImGuiCol_WindowBg] = ImVec4(0.06f, 0.06f, 0.06f, 0.94f); + colors[ImGuiCol_Border] = ImVec4(1.00f, 1.00f, 1.00f, 0.19f); + colors[ImGuiCol_ChildWindowBg] = ImVec4(1.00f, 1.00f, 1.00f, 0.00f); + colors[ImGuiCol_PopupBg] = ImVec4(0.00f, 0.00f, 0.00f, 0.94f); + colors[ImGuiCol_FrameBg] = ImVec4(0.16f, 0.29f, 0.48f, 0.54f); + colors[ImGuiCol_FrameBgHovered] = ImVec4(0.26f, 0.59f, 0.98f, 0.40f); + colors[ImGuiCol_FrameBgActive] = ImVec4(0.26f, 0.59f, 0.98f, 0.67f); + colors[ImGuiCol_TitleBg] = ImVec4(0.04f, 0.04f, 0.04f, 1.00f); + colors[ImGuiCol_TitleBgCollapsed] = ImVec4(0.00f, 0.00f, 0.00f, 0.51f); + colors[ImGuiCol_TitleBgActive] = ImVec4(0.18f, 0.18f, 0.18f, 1.00f); + colors[ImGuiCol_MenuBarBg] = ImVec4(0.14f, 0.14f, 0.14f, 1.00f); + colors[ImGuiCol_ScrollbarBg] = ImVec4(0.02f, 0.02f, 0.02f, 0.53f); + colors[ImGuiCol_ScrollbarGrab] = ImVec4(0.31f, 0.31f, 0.31f, 1.00f); + colors[ImGuiCol_ScrollbarGrabHovered] = ImVec4(0.41f, 0.41f, 0.41f, 1.00f); + colors[ImGuiCol_ScrollbarGrabActive] = ImVec4(0.51f, 0.51f, 0.51f, 1.00f); + colors[ImGuiCol_ComboBg] = ImVec4(0.14f, 0.14f, 0.14f, 0.99f); + colors[ImGuiCol_CheckMark] = ImVec4(0.26f, 0.59f, 0.98f, 1.00f); + colors[ImGuiCol_SliderGrab] = ImVec4(0.24f, 0.52f, 0.88f, 1.00f); + colors[ImGuiCol_SliderGrabActive] = ImVec4(0.26f, 0.59f, 0.98f, 1.00f); + colors[ImGuiCol_Button] = ImVec4(0.26f, 0.59f, 0.98f, 0.40f); + colors[ImGuiCol_ButtonHovered] = ImVec4(0.26f, 0.59f, 0.98f, 1.00f); + colors[ImGuiCol_ButtonActive] = ImVec4(0.06f, 0.53f, 0.98f, 1.00f); + colors[ImGuiCol_Header] = ImVec4(0.26f, 0.59f, 0.98f, 0.31f); + colors[ImGuiCol_HeaderHovered] = ImVec4(0.26f, 0.59f, 0.98f, 0.80f); + colors[ImGuiCol_HeaderActive] = ImVec4(0.26f, 0.59f, 0.98f, 1.00f); + colors[ImGuiCol_Separator] = colors[ImGuiCol_Border];//ImVec4(0.61f, 0.61f, 0.61f, 1.00f); + colors[ImGuiCol_SeparatorHovered] = ImVec4(0.26f, 0.59f, 0.98f, 0.78f); + colors[ImGuiCol_SeparatorActive] = ImVec4(0.26f, 0.59f, 0.98f, 1.00f); + colors[ImGuiCol_ResizeGrip] = ImVec4(0.26f, 0.59f, 0.98f, 0.25f); + 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_CloseButton] = ImVec4(0.41f, 0.41f, 0.41f, 0.50f); + colors[ImGuiCol_CloseButtonHovered] = ImVec4(0.98f, 0.39f, 0.36f, 1.00f); + colors[ImGuiCol_CloseButtonActive] = ImVec4(0.98f, 0.39f, 0.36f, 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); + colors[ImGuiCol_PlotHistogramHovered] = ImVec4(1.00f, 0.60f, 0.00f, 1.00f); + colors[ImGuiCol_TextSelectedBg] = ImVec4(0.26f, 0.59f, 0.98f, 0.35f); + colors[ImGuiCol_ModalWindowDarkening] = ImVec4(0.80f, 0.80f, 0.80f, 0.35f); + colors[ImGuiCol_NavHighlight] = ImVec4(0.26f, 0.59f, 0.98f, 1.00f); + colors[ImGuiCol_NavWindowingHighlight] = ImVec4(1.00f, 1.00f, 1.00f, 0.12f); +} + //----------------------------------------------------------------------------- // ImDrawList //----------------------------------------------------------------------------- @@ -222,7 +330,7 @@ void ImDrawList::UpdateTextureID() // Try to merge with previous command if it matches, else use current command ImDrawCmd* prev_cmd = CmdBuffer.Size > 1 ? curr_cmd - 1 : NULL; - if (prev_cmd && prev_cmd->TextureId == curr_texture_id && memcmp(&prev_cmd->ClipRect, &GetCurrentClipRect(), sizeof(ImVec4)) == 0 && prev_cmd->UserCallback == NULL) + if (curr_cmd->ElemCount == 0 && prev_cmd && prev_cmd->TextureId == curr_texture_id && memcmp(&prev_cmd->ClipRect, &GetCurrentClipRect(), sizeof(ImVec4)) == 0 && prev_cmd->UserCallback == NULL) CmdBuffer.pop_back(); else curr_cmd->TextureId = curr_texture_id; @@ -339,7 +447,7 @@ void ImDrawList::ChannelsMerge() if (int sz = ch.CmdBuffer.Size) { memcpy(cmd_write, ch.CmdBuffer.Data, sz * sizeof(ImDrawCmd)); cmd_write += sz; } if (int sz = ch.IdxBuffer.Size) { memcpy(_IdxWritePtr, ch.IdxBuffer.Data, sz * sizeof(ImDrawIdx)); _IdxWritePtr += sz; } } - AddDrawCmd(); + UpdateClipRect(); // We call this instead of AddDrawCmd(), so that empty channels won't produce an extra draw call. _ChannelsCount = 1; } @@ -1034,6 +1142,43 @@ void ImDrawData::ScaleClipRects(const ImVec2& scale) } } +//----------------------------------------------------------------------------- +// Shade functions +//----------------------------------------------------------------------------- + +// Generic linear color gradient, write to RGB fields, leave A untouched. +void ImGui::ShadeVertsLinearColorGradientKeepAlpha(ImDrawVert* vert_start, ImDrawVert* vert_end, ImVec2 gradient_p0, ImVec2 gradient_p1, ImU32 col0, ImU32 col1) +{ + ImVec2 gradient_extent = gradient_p1 - gradient_p0; + float gradient_inv_length2 = 1.0f / ImLengthSqr(gradient_extent); + for (ImDrawVert* vert = vert_start; vert < vert_end; vert++) + { + float d = ImDot(vert->pos - gradient_p0, gradient_extent); + float t = ImClamp(d * gradient_inv_length2, 0.0f, 1.0f); + int r = ImLerp((int)(col0 >> IM_COL32_R_SHIFT) & 0xFF, (int)(col1 >> IM_COL32_R_SHIFT) & 0xFF, t); + int g = ImLerp((int)(col0 >> IM_COL32_G_SHIFT) & 0xFF, (int)(col1 >> IM_COL32_G_SHIFT) & 0xFF, t); + int b = ImLerp((int)(col0 >> IM_COL32_B_SHIFT) & 0xFF, (int)(col1 >> IM_COL32_B_SHIFT) & 0xFF, t); + vert->col = (r << IM_COL32_R_SHIFT) | (g << IM_COL32_G_SHIFT) | (b << IM_COL32_B_SHIFT) | (vert->col & IM_COL32_A_MASK); + } +} + +// Scan and shade backward from the end of given vertices. Assume vertices are text only (= vert_start..vert_end going left to right) so we can break as soon as we are out the gradient bounds. +void ImGui::ShadeVertsLinearAlphaGradientForLeftToRightText(ImDrawVert* vert_start, ImDrawVert* vert_end, float gradient_p0_x, float gradient_p1_x) +{ + float gradient_extent_x = gradient_p1_x - gradient_p0_x; + float gradient_inv_length2 = 1.0f / (gradient_extent_x * gradient_extent_x); + int full_alpha_count = 0; + for (ImDrawVert* vert = vert_end - 1; vert >= vert_start; vert--) + { + float d = (vert->pos.x - gradient_p0_x) * (gradient_extent_x); + float alpha_mul = 1.0f - ImClamp(d * gradient_inv_length2, 0.0f, 1.0f); + if (alpha_mul >= 1.0f && ++full_alpha_count > 2) + return; // Early out + int a = (int)(((vert->col >> IM_COL32_A_SHIFT) & 0xFF) * alpha_mul); + vert->col = (vert->col & ~IM_COL32_A_MASK) | (a << IM_COL32_A_SHIFT); + } +} + //----------------------------------------------------------------------------- // ImFontConfig //----------------------------------------------------------------------------- @@ -1438,7 +1583,10 @@ bool ImFontAtlasBuildWithStbTruetype(ImFontAtlas* atlas) const int font_offset = stbtt_GetFontOffsetForIndex((unsigned char*)cfg.FontData, cfg.FontNo); IM_ASSERT(font_offset >= 0); if (!stbtt_InitFont(&tmp.FontInfo, (unsigned char*)cfg.FontData, font_offset)) + { + ImGui::MemFree(tmp_array); return false; + } } // Allocate packing character data and flag packed characters buffer as non-packed (x0=y0=x1=y1=0) @@ -1540,7 +1688,6 @@ bool ImFontAtlasBuildWithStbTruetype(ImFontAtlas* atlas) const float off_x = cfg.GlyphOffset.x; const float off_y = cfg.GlyphOffset.y + (float)(int)(dst_font->Ascent + 0.5f); - dst_font->FallbackGlyph = NULL; // Always clear fallback so FindGlyph can return NULL. It will be set again in BuildLookupTable() for (int i = 0; i < tmp.RangesCount; i++) { stbtt_pack_range& range = tmp.Ranges[i]; @@ -1582,14 +1729,12 @@ void ImFontAtlasBuildSetupFont(ImFontAtlas* atlas, ImFont* font, ImFontConfig* f { if (!font_config->MergeMode) { - font->ContainerAtlas = atlas; - font->ConfigData = font_config; - font->ConfigDataCount = 0; + font->ClearOutputData(); font->FontSize = font_config->SizePixels; + font->ConfigData = font_config; + font->ContainerAtlas = atlas; font->Ascent = ascent; font->Descent = descent; - font->Glyphs.resize(0); - font->MetricsTotalSurface = 0; } font->ConfigDataCount++; } @@ -1814,6 +1959,7 @@ const ImWchar* ImFontAtlas::GetGlyphRangesThai() static const ImWchar ranges[] = { 0x0020, 0x00FF, // Basic Latin + 0x2010, 0x205E, // Punctuations 0x0E00, 0x0E7F, // Thai 0, }; @@ -1866,7 +2012,8 @@ ImFont::ImFont() { Scale = 1.0f; FallbackChar = (ImWchar)'?'; - Clear(); + DisplayOffset = ImVec2(0.0f, 1.0f); + ClearOutputData(); } ImFont::~ImFont() @@ -1879,13 +2026,12 @@ ImFont::~ImFont() if (g.Font == this) g.Font = NULL; */ - Clear(); + ClearOutputData(); } -void ImFont::Clear() +void ImFont::ClearOutputData() { FontSize = 0.0f; - DisplayOffset = ImVec2(0.0f, 1.0f); Glyphs.clear(); IndexAdvanceX.clear(); IndexLookup.clear(); diff --git a/deps/cimgui/imgui/imgui_internal.h b/deps/cimgui/imgui/imgui_internal.h index 77084dc7..d982dee7 100644 --- a/deps/cimgui/imgui/imgui_internal.h +++ b/deps/cimgui/imgui/imgui_internal.h @@ -1,4 +1,4 @@ -// dear imgui, v1.52 WIP +// dear imgui, v1.53 WIP // (internals) // You may use this file to debug, understand or extend ImGui features but we don't provide any guarantee of forward compatibility! @@ -45,13 +45,12 @@ struct ImGuiMouseCursorData; struct ImGuiPopupRef; struct ImGuiWindow; -typedef int ImGuiLayoutType; // enum ImGuiLayoutType_ -typedef int ImGuiButtonFlags; // enum ImGuiButtonFlags_ -typedef int ImGuiTreeNodeFlags; // enum ImGuiTreeNodeFlags_ -typedef int ImGuiSliderFlags; // enum ImGuiSliderFlags_ -typedef int ImGuiSeparatorFlags; // enum ImGuiSeparatorFlags_ -typedef int ImGuiItemFlags; // enum ImGuiItemFlags_ -typedef int ImGuiNavHighlightFlags; +typedef int ImGuiLayoutType; // enum: horizontal or vertical // enum ImGuiLayoutType_ +typedef int ImGuiButtonFlags; // flags: for ButtonEx(), ButtonBehavior() // enum ImGuiButtonFlags_ +typedef int ImGuiItemFlags; // flags: for PushItemFlag() // enum ImGuiItemFlags_ +typedef int ImGuiNavHighlightFlags; // flags: for RenderNavHighlight() // enum ImGuiNavHighlightFlags_ +typedef int ImGuiSeparatorFlags; // flags: for Separator() - internal // enum ImGuiSeparatorFlags_ +typedef int ImGuiSliderFlags; // flags: for SliderBehavior() // enum ImGuiSliderFlags_ //------------------------------------------------------------------------- // STB libraries @@ -81,9 +80,8 @@ extern IMGUI_API ImGuiContext* GImGui; // Current implicit ImGui context pointe // Helpers //----------------------------------------------------------------------------- -#define IM_ARRAYSIZE(_ARR) ((int)(sizeof(_ARR)/sizeof(*_ARR))) -#define IM_PI 3.14159265358979323846f -#define IM_OFFSETOF(_TYPE,_ELM) ((size_t)&(((_TYPE*)0)->_ELM)) +#define IM_PI 3.14159265358979323846f +#define IM_OFFSETOF(_TYPE,_ELM) ((size_t)&(((_TYPE*)0)->_ELM)) // Helpers: UTF-8 <> wchar IMGUI_API int ImTextStrToUtf8(char* buf, int buf_size, const ImWchar* in_text, const ImWchar* in_text_end); // return output UTF-8 bytes count @@ -109,6 +107,7 @@ IMGUI_API void ImTriangleBarycentricCoords(const ImVec2& a, const ImVec // Helpers: String IMGUI_API int ImStricmp(const char* str1, const char* str2); IMGUI_API int ImStrnicmp(const char* str1, const char* str2, int count); +IMGUI_API void ImStrncpy(char* dst, const char* src, int count); IMGUI_API char* ImStrdup(const char* str); IMGUI_API int ImStrlenW(const ImWchar* str); IMGUI_API const ImWchar*ImStrbolW(const ImWchar* buf_mid_line, const ImWchar* buf_begin); // Find beginning-of-line @@ -129,7 +128,9 @@ static inline ImVec2& operator+=(ImVec2& lhs, const ImVec2& rhs) static inline ImVec2& operator-=(ImVec2& lhs, const ImVec2& rhs) { lhs.x -= rhs.x; lhs.y -= rhs.y; return lhs; } static inline ImVec2& operator*=(ImVec2& lhs, const float rhs) { lhs.x *= rhs; lhs.y *= rhs; return lhs; } static inline ImVec2& operator/=(ImVec2& lhs, const float rhs) { lhs.x /= rhs; lhs.y /= rhs; return lhs; } +static inline ImVec4 operator+(const ImVec4& lhs, const ImVec4& rhs) { return ImVec4(lhs.x+rhs.x, lhs.y+rhs.y, lhs.z+rhs.z, lhs.w+rhs.w); } static inline ImVec4 operator-(const ImVec4& lhs, const ImVec4& rhs) { return ImVec4(lhs.x-rhs.x, lhs.y-rhs.y, lhs.z-rhs.z, lhs.w-rhs.w); } +static inline ImVec4 operator*(const ImVec4& lhs, const ImVec4& rhs) { return ImVec4(lhs.x*rhs.x, lhs.y*rhs.y, lhs.z*rhs.z, lhs.w*rhs.w); } #endif static inline int ImMin(int lhs, int rhs) { return lhs < rhs ? lhs : rhs; } @@ -142,11 +143,13 @@ static inline int ImClamp(int v, int mn, int mx) static inline float ImClamp(float v, float mn, float mx) { return (v < mn) ? mn : (v > mx) ? mx : v; } static inline ImVec2 ImClamp(const ImVec2& f, const ImVec2& mn, ImVec2 mx) { return ImVec2(ImClamp(f.x,mn.x,mx.x), ImClamp(f.y,mn.y,mx.y)); } static inline float ImSaturate(float f) { return (f < 0.0f) ? 0.0f : (f > 1.0f) ? 1.0f : f; } +static inline void ImSwap(int& a, int& b) { int tmp = a; a = b; b = tmp; } static inline void ImSwap(float& a, float& b) { float tmp = a; a = b; b = tmp; } static inline int ImLerp(int a, int b, float t) { return (int)(a + (b - a) * t); } static inline float ImLerp(float a, float b, float t) { return a + (b - a) * t; } static inline ImVec2 ImLerp(const ImVec2& a, const ImVec2& b, float t) { return ImVec2(a.x + (b.x - a.x) * t, a.y + (b.y - a.y) * t); } static inline ImVec2 ImLerp(const ImVec2& a, const ImVec2& b, const ImVec2& t) { return ImVec2(a.x + (b.x - a.x) * t.x, a.y + (b.y - a.y) * t.y); } +static inline ImVec4 ImLerp(const ImVec4& a, const ImVec4& b, float t) { return ImVec4(a.x + (b.x - a.x) * t, a.y + (b.y - a.y) * t, a.z + (b.z - a.z) * t, a.w + (b.w - a.w) * t); } static inline float ImLengthSqr(const ImVec2& lhs) { return lhs.x*lhs.x + lhs.y*lhs.y; } static inline float ImLengthSqr(const ImVec4& lhs) { return lhs.x*lhs.x + lhs.y*lhs.y + lhs.z*lhs.z + lhs.w*lhs.w; } static inline float ImInvLength(const ImVec2& lhs, float fail_value) { float d = lhs.x*lhs.x + lhs.y*lhs.y; if (d > 0.0f) return 1.0f / sqrtf(d); return fail_value; } @@ -154,6 +157,7 @@ static inline float ImFloor(float f) static inline ImVec2 ImFloor(const ImVec2& v) { return ImVec2((float)(int)v.x, (float)(int)v.y); } static inline float ImDot(const ImVec2& a, const ImVec2& b) { return a.x * b.x + a.y * b.y; } static inline ImVec2 ImRotate(const ImVec2& v, float cos_a, float sin_a) { return ImVec2(v.x * cos_a - v.y * sin_a, v.x * sin_a + v.y * cos_a); } +static inline 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; } // We call C++ constructor on own allocated memory via the placement "new(ptr) Type()" syntax. // Defining a custom placement new() with a dummy parameter allows us to bypass including which on some platforms complains when user has disabled exceptions. @@ -182,7 +186,8 @@ enum ImGuiButtonFlags_ ImGuiButtonFlags_AlignTextBaseLine = 1 << 8, // vertically align button to match text baseline - ButtonEx() only // FIXME: Should be removed and handled by SmallButton(), not possible currently because of DC.CursorPosPrevLine ImGuiButtonFlags_NoKeyModifiers = 1 << 9, // disable interaction if a key modifier is held ImGuiButtonFlags_AllowOverlapMode = 1 << 10, // require previous frame HoveredId to either match id or be null before being usable - ImGuiButtonFlags_NoNavOverride = 1 << 11 // don't override navigation id when activated + ImGuiButtonFlags_NoHoldingActiveID = 1 << 11, // don't set ActiveId while holding the mouse (ImGuiButtonFlags_PressedOnClick only) + ImGuiButtonFlags_NoNavFocus = 1 << 12 // don't override navigation focus when activated }; enum ImGuiSliderFlags_ @@ -255,7 +260,7 @@ enum ImGuiNavHighlightFlags_ { ImGuiNavHighlightFlags_TypeDefault = 1 << 0, ImGuiNavHighlightFlags_TypeThin = 1 << 1, - ImGuiNavHighlightFlags_AlwaysRender = 1 << 2 + ImGuiNavHighlightFlags_AlwaysDraw = 1 << 2 }; enum ImGuiCorner @@ -443,8 +448,10 @@ struct ImGuiContext ImGuiID HoveredId; // Hovered widget bool HoveredIdAllowOverlap; ImGuiID HoveredIdPreviousFrame; + float HoveredIdTimer; ImGuiID ActiveId; // Active widget ImGuiID ActiveIdPreviousFrame; + float ActiveIdTimer; bool ActiveIdIsAlive; // Active widget has been seen this frame bool ActiveIdIsJustActivated; // Set at the time of activation for one frame bool ActiveIdAllowOverlap; // Active widget allows another widget to steal active id (generally for overlapping widgets, but not always) @@ -452,8 +459,8 @@ struct ImGuiContext ImVec2 ActiveIdClickOffset; // Clicked offset from upper-left corner, if applicable (currently only set by ButtonBehavior) ImGuiWindow* ActiveIdWindow; ImGuiInputSource ActiveIdSource; // Activating with mouse or nav (gamepad/keyboard) - ImGuiWindow* MovedWindow; // Track the child window we clicked on to move a window (only apply to moving with mouse) - ImGuiID MovedWindowMoveId; // == MovedWindow->RootWindow->MoveId + ImGuiWindow* MovingWindow; // Track the child window we clicked on to move a window. + ImGuiID MovingWindowMoveId; // == MovingWindow->MoveId ImVector Settings; // .ini Settings float SettingsDirtyTimer; // Save .ini Settings on disk when time reaches zero ImVector ColorModifiers; // Stack for PushStyleColor()/PopStyleColor() @@ -463,13 +470,14 @@ struct ImGuiContext ImVector CurrentPopupStack; // Which level of BeginPopup() we are in (reset every frame) // Navigation data (for gamepad/keyboard) - ImGuiWindow* NavWindow; // Nav/focused window for navigation - ImGuiID NavId; // Nav/focused item for navigation - ImGuiID NavActivateId, NavActivateDownId; // ~~ IsNavInputPressed(ImGuiNavInput_PadActivate) ? NavId : 0, etc. - ImGuiID NavInputId; // ~~ IsNavInputPressed(ImGuiNavInput_PadInput) ? NavId : 0, etc. + ImGuiWindow* NavWindow; // Focused window for navigation. Could be called 'FocusWindow' + ImGuiID NavId; // Focused item for navigation + ImGuiID NavActivateId; // ~~ IsNavInputPressed(ImGuiNavInput_PadActivate) ? NavId : 0, also set when calling ActivateItem() + ImGuiID NavActivateDownId; // ~~ IsNavInputPressed(ImGuiNavInput_PadActivate) ? NavId : 0 + ImGuiID NavInputId; // ~~ IsNavInputPressed(ImGuiNavInput_PadInput) ? NavId : 0 ImGuiID NavJustTabbedId; // Just tabbed to this id. - ImGuiID NavJustNavigatedId; // Just navigated to this id (result of a successfully MoveRequest) ImGuiID NavNextActivateId; // Set by ActivateItem(), queued until next frame + ImGuiID NavJustMovedToId; // Just navigated to this id (result of a successfully MoveRequest) ImRect NavScoringRectScreen; // Rectangle used for scoring, in screen space. Based of window->DC.NavRefRectRel[], modified for directional navigation scoring. ImGuiWindow* NavWindowingTarget; float NavWindowingDisplayAlpha; @@ -492,9 +500,8 @@ struct ImGuiContext ImGuiDir NavMoveDirLast; // Direction of the previous move request ImGuiID NavMoveResultId; // Best move request candidate ImGuiID NavMoveResultParentId; // - float NavMoveResultDistBox; // Best move request candidate box distance to current NavId - float NavMoveResultDistCenter; // Best move request candidate center distance to current NavId float NavMoveResultDistAxial; + float NavMoveResultDistCenter; ImRect NavMoveResultRectRel; // Best move request candidate bounding box in window relative space // Storage for SetNexWindow** and SetNextTreeNode*** functions @@ -571,8 +578,10 @@ struct ImGuiContext HoveredId = 0; HoveredIdAllowOverlap = false; HoveredIdPreviousFrame = 0; + HoveredIdTimer = 0.0f; ActiveId = 0; ActiveIdPreviousFrame = 0; + ActiveIdTimer = 0.0f; ActiveIdIsAlive = false; ActiveIdIsJustActivated = false; ActiveIdAllowOverlap = false; @@ -580,13 +589,13 @@ struct ImGuiContext ActiveIdClickOffset = ImVec2(-1,-1); ActiveIdWindow = NULL; ActiveIdSource = ImGuiInputSource_None; - MovedWindow = NULL; - MovedWindowMoveId = 0; + MovingWindow = NULL; + MovingWindowMoveId = 0; SettingsDirtyTimer = 0.0f; NavWindow = NULL; NavId = NavActivateId = NavActivateDownId = NavInputId = 0; - NavJustTabbedId = NavJustNavigatedId = NavNextActivateId = 0; + NavJustTabbedId = NavJustMovedToId = NavNextActivateId = 0; NavScoringRectScreen = ImRect(); NavWindowingTarget = NULL; NavWindowingDisplayAlpha = 0.0f; @@ -607,7 +616,7 @@ struct ImGuiContext NavMoveDir = NavMoveDirLast = ImGuiDir_None; NavMoveResultId = 0; NavMoveResultParentId = 0; - NavMoveResultDistBox = NavMoveResultDistCenter = NavMoveResultDistAxial = 0.0f; + NavMoveResultDistAxial = NavMoveResultDistCenter = 0.0f; SetNextWindowPosVal = ImVec2(0.0f, 0.0f); SetNextWindowSizeVal = ImVec2(0.0f, 0.0f); @@ -659,7 +668,7 @@ enum ImGuiItemFlags_ { ImGuiItemFlags_AllowKeyboardFocus = 1 << 0, // true ImGuiItemFlags_ButtonRepeat = 1 << 1, // false // Button() will return true multiple times based on io.KeyRepeatDelay and io.KeyRepeatRate settings. - //ImGuiItemFlags_Disabled = 1 << 2, // false // All widgets appears are disabled + ImGuiItemFlags_Disabled = 1 << 2, // false // FIXME-WIP: Disable interactions but doesn't affect visuals. Should be: grey out and disable interactions with widgets that affect data + view widgets (WIP) ImGuiItemFlags_NoNav = 1 << 3, // false ImGuiItemFlags_NoNavDefaultFocus = 1 << 4, // false ImGuiItemFlags_SelectableDontClosePopup = 1 << 5, // false // MenuItem/Selectable() automatically closes current Popup window @@ -844,6 +853,17 @@ public: ImRect MenuBarRect() const { float y1 = Pos.y + TitleBarHeight(); return ImRect(Pos.x, y1, Pos.x + SizeFull.x, y1 + MenuBarHeight()); } }; +// Backup and restore just enough data to be able to use IsItemHovered() on item A after another B in the same window has overwritten the data. +struct ImGuiItemHoveredDataBackup +{ + ImGuiID LastItemId; + ImRect LastItemRect; + bool LastItemRectHoveredRect; + + void Backup() { ImGuiWindow* window = GImGui->CurrentWindow; LastItemId = window->DC.LastItemId; LastItemRect = window->DC.LastItemRect; LastItemRectHoveredRect = window->DC.LastItemRectHoveredRect; } + void Restore() { ImGuiWindow* window = GImGui->CurrentWindow; window->DC.LastItemId = LastItemId; window->DC.LastItemRect = LastItemRect; window->DC.LastItemRectHoveredRect = LastItemRectHoveredRect; } +}; + //----------------------------------------------------------------------------- // Internal API // No guarantee of forward compatibility here. @@ -865,9 +885,11 @@ namespace ImGui IMGUI_API void EndFrame(); // Ends the ImGui frame. Automatically called by Render()! you most likely don't need to ever call that yourself directly. If you don't need to render you can call EndFrame() but you'll have wasted CPU already. If you don't need to render, don't create any windows instead! IMGUI_API void SetActiveID(ImGuiID id, ImGuiWindow* window); - IMGUI_API void SetActiveIDNoNav(ImGuiID id, ImGuiWindow* window); + IMGUI_API ImGuiID GetActiveID(); + IMGUI_API void SetFocusID(ImGuiID id, ImGuiWindow* window); IMGUI_API void ClearActiveID(); IMGUI_API void SetHoveredID(ImGuiID id); + IMGUI_API ImGuiID GetHoveredID(); IMGUI_API void KeepAliveID(ImGuiID id); IMGUI_API void ItemSize(const ImVec2& size, float text_offset_y = 0.0f); @@ -887,9 +909,11 @@ namespace ImGui IMGUI_API void ClosePopup(ImGuiID id); IMGUI_API bool IsPopupOpen(ImGuiID id); IMGUI_API bool BeginPopupEx(ImGuiID id, ImGuiWindowFlags extra_flags); + IMGUI_API void BeginTooltipEx(ImGuiWindowFlags extra_flags, bool override_previous_tooltip = true); IMGUI_API int CalcTypematicPressedRepeatAmount(float t, float t_prev, float repeat_delay, float repeat_rate); + IMGUI_API void Scrollbar(ImGuiLayoutType direction); IMGUI_API void VerticalSeparator(); // Vertical separator, for menu bars (use current line height). not exposed because it is misleading what it doesn't have an effect on regular layout. // FIXME-WIP: New Columns API @@ -909,9 +933,9 @@ namespace ImGui IMGUI_API void RenderFrame(ImVec2 p_min, ImVec2 p_max, ImU32 fill_col, bool border = true, float rounding = 0.0f); IMGUI_API void RenderFrameBorder(ImVec2 p_min, ImVec2 p_max, float rounding = 0.0f); IMGUI_API void RenderColorRectWithAlphaCheckerboard(ImVec2 p_min, ImVec2 p_max, ImU32 fill_col, float grid_step, ImVec2 grid_off, float rounding = 0.0f, int rounding_corners_flags = ~0); - IMGUI_API void RenderCollapseTriangle(ImVec2 pos, bool is_open, float scale = 1.0f); + IMGUI_API void RenderTriangle(ImVec2 pos, ImGuiDir dir, float scale = 1.0f); IMGUI_API void RenderBullet(ImVec2 pos); - IMGUI_API void RenderCheckMark(ImVec2 pos, ImU32 col); + IMGUI_API void RenderCheckMark(ImVec2 pos, ImU32 col, float sz); IMGUI_API void RenderNavHighlight(const ImRect& bb, ImGuiID id, ImGuiNavHighlightFlags flags = ImGuiNavHighlightFlags_TypeDefault); // Navigation highlight IMGUI_API void RenderRectFilledRangeH(ImDrawList* draw_list, const ImRect& rect, ImU32 col, float x_start_norm, float x_end_norm, float rounding); IMGUI_API const char* FindRenderedTextEnd(const char* text, const char* text_end = NULL); // Find the optional ## from which we stop displaying text. @@ -946,6 +970,10 @@ namespace ImGui IMGUI_API int ParseFormatPrecision(const char* fmt, int default_value); IMGUI_API float RoundScalar(float value, int decimal_precision); + // Shade functions + IMGUI_API void ShadeVertsLinearColorGradientKeepAlpha(ImDrawVert* vert_start, ImDrawVert* vert_end, ImVec2 gradient_p0, ImVec2 gradient_p1, ImU32 col0, ImU32 col1); + IMGUI_API void ShadeVertsLinearAlphaGradientForLeftToRightText(ImDrawVert* vert_start, ImDrawVert* vert_end, float gradient_p0_x, float gradient_p1_x); + } // namespace ImGui // ImFontAtlas internals