Merge pull request #361 from fr500/master
Examples: OpenGL3: Add msys2/mingw64 target.
diff --git a/README.md b/README.md
index 32e829e..b225489 100644
--- a/README.md
+++ b/README.md
@@ -3,7 +3,7 @@
[](https://travis-ci.org/ocornut/imgui)
[](https://scan.coverity.com/projects/4720)
-<sub>(This library is free but I need your support to sustain development and maintenance. If you work for a company, please consider financial support)</sub>
+(This library is free but I need your support to sustain its development - there's lots of desirable new features and maintenance to do. If you work for a company using ImGui or have the means to do so, please consider financial support)
[](http://www.patreon.com/imgui) [](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=5Q73FPZ9C526U)
diff --git a/imgui.cpp b/imgui.cpp
index c704796..55854c9 100644
--- a/imgui.cpp
+++ b/imgui.cpp
@@ -282,9 +282,9 @@
Button("Hello###ID"; // Label = "Hello", ID = hash of "ID"
Button("World###ID"; // Label = "World", ID = hash of "ID" (same as above)
-
- sprintf(buf, "My game (%f FPS)###MyGame");
- Begin(buf); // Variable label, ID = hash of "MyGame"
+
+ sprintf(buf, "My game (%f FPS)###MyGame");
+ Begin(buf); // Variable label, ID = hash of "MyGame"
- Use PushID() / PopID() to create scopes and avoid ID conflicts within the same Window.
This is the most convenient way of distinguishing ID if you are iterating and creating many UI elements.
@@ -704,6 +704,10 @@
MouseDoubleClickTime = 0.30f;
MouseDoubleClickMaxDist = 6.0f;
MouseDragThreshold = 6.0f;
+ for (int i = 0; i < IM_ARRAYSIZE(MouseDownDuration); i++)
+ MouseDownDuration[i] = MouseDownDurationPrev[i] = -1.0f;
+ for (int i = 0; i < IM_ARRAYSIZE(KeysDownDuration); i++)
+ KeysDownDuration[i] = KeysDownDurationPrev[i] = -1.0f;
for (int i = 0; i < ImGuiKey_COUNT; i++)
KeyMap[i] = -1;
KeyRepeatDelay = 0.250f;
@@ -1572,11 +1576,18 @@
{
ImGuiState& g = *GImGui;
g.ActiveId = id;
- g.ActiveIdIsFocusedOnly = false;
+ g.ActiveIdAllowHoveringOthers = false;
g.ActiveIdIsJustActivated = true;
g.ActiveIdWindow = window;
}
+void ImGui::SetHoveredID(ImGuiID id)
+{
+ ImGuiState& g = *GImGui;
+ g.HoveredId = id;
+ g.HoveredIdAllowHoveringOthers = false;
+}
+
void ImGui::KeepAliveID(ImGuiID id)
{
ImGuiState& g = *GImGui;
@@ -1635,7 +1646,7 @@
window->DC.LastItemHoveredRect = true;
window->DC.LastItemHoveredAndUsable = false;
if (g.HoveredRootWindow == window->RootWindow)
- if (g.ActiveId == 0 || (id && g.ActiveId == *id) || g.ActiveIdIsFocusedOnly || (g.ActiveId == window->MoveID))
+ if (g.ActiveId == 0 || (id && g.ActiveId == *id) || g.ActiveIdAllowHoveringOthers || (g.ActiveId == window->MoveID))
if (IsWindowContentHoverable(window))
window->DC.LastItemHoveredAndUsable = true;
}
@@ -1664,11 +1675,11 @@
bool ImGui::IsHovered(const ImRect& bb, ImGuiID id, bool flatten_childs)
{
ImGuiState& g = *GImGui;
- if (g.HoveredId == 0 || g.HoveredId == id)
+ if (g.HoveredId == 0 || g.HoveredId == id || g.HoveredIdAllowHoveringOthers)
{
ImGuiWindow* window = GetCurrentWindowRead();
if (g.HoveredWindow == window || (flatten_childs && g.HoveredRootWindow == window->RootWindow))
- if ((g.ActiveId == 0 || g.ActiveId == id || g.ActiveIdIsFocusedOnly) && ImGui::IsMouseHoveringRect(bb.Min, bb.Max))
+ if ((g.ActiveId == 0 || g.ActiveId == id || g.ActiveIdAllowHoveringOthers) && ImGui::IsMouseHoveringRect(bb.Min, bb.Max))
if (IsWindowContentHoverable(g.HoveredRootWindow))
return true;
}
@@ -1885,6 +1896,7 @@
// Clear reference to active widget if the widget isn't alive anymore
g.HoveredIdPreviousFrame = g.HoveredId;
g.HoveredId = 0;
+ g.HoveredIdAllowHoveringOthers = false;
if (!g.ActiveIdIsAlive && g.ActiveIdPreviousFrame == g.ActiveId && g.ActiveId != 0)
SetActiveID(0);
g.ActiveIdPreviousFrame = g.ActiveId;
@@ -3290,13 +3302,13 @@
}
// Helper to create a child window / scrolling region that looks like a normal widget frame.
-bool ImGui::BeginChildFrame(ImGuiID id, const ImVec2& size)
+bool ImGui::BeginChildFrame(ImGuiID id, const ImVec2& size, ImGuiWindowFlags extra_flags)
{
ImGuiState& g = *GImGui;
const ImGuiStyle& style = g.Style;
ImGui::PushStyleColor(ImGuiCol_ChildWindowBg, style.Colors[ImGuiCol_FrameBg]);
ImGui::PushStyleVar(ImGuiStyleVar_ChildWindowRounding, style.FrameRounding);
- return ImGui::BeginChild(id, size, false, ImGuiWindowFlags_NoMove);
+ return ImGui::BeginChild(id, size, false, ImGuiWindowFlags_NoMove | extra_flags);
}
void ImGui::EndChildFrame()
@@ -4044,17 +4056,18 @@
bool other_scrollbar = (horizontal ? window->ScrollbarY : window->ScrollbarX);
float other_scrollbar_size_w = other_scrollbar ? style.ScrollbarSize : 0.0f;
const ImRect window_rect = window->Rect();
+ const float border_offset = (window->Flags & ImGuiWindowFlags_ShowBorders) ? 1.0f : 0.0f;
ImRect bb = horizontal
- ? ImRect(window->Pos.x, window_rect.Max.y - style.ScrollbarSize, window_rect.Max.x - other_scrollbar_size_w, window_rect.Max.y)
- : ImRect(window_rect.Max.x - style.ScrollbarSize, window->Pos.y + window->TitleBarHeight(), window_rect.Max.x, window_rect.Max.y - other_scrollbar_size_w);
+ ? ImRect(window->Pos.x + border_offset, window_rect.Max.y - style.ScrollbarSize, window_rect.Max.x - other_scrollbar_size_w, window_rect.Max.y)
+ : ImRect(window_rect.Max.x - style.ScrollbarSize, window->Pos.y + window->TitleBarHeight() + border_offset, window_rect.Max.x, window_rect.Max.y - other_scrollbar_size_w);
float window_rounding = (window->Flags & ImGuiWindowFlags_ChildWindow) ? style.ChildWindowRounding : style.WindowRounding;
- int window_rounding_corners;
- if (horizontal)
- window_rounding_corners = 8 | (other_scrollbar ? 0 : 4);
- else
- window_rounding_corners = ((window->Flags & ImGuiWindowFlags_NoTitleBar) ? 2 : 0) | (other_scrollbar ? 0 : 4);
- window->DrawList->AddRectFilled(bb.Min, bb.Max, window->Color(ImGuiCol_ScrollbarBg), window_rounding, window_rounding_corners);
+ int window_rounding_corners;
+ if (horizontal)
+ window_rounding_corners = 8 | (other_scrollbar ? 0 : 4);
+ else
+ window_rounding_corners = ((window->Flags & ImGuiWindowFlags_NoTitleBar) ? 2 : 0) | (other_scrollbar ? 0 : 4);
+ window->DrawList->AddRectFilled(bb.Min, bb.Max, window->Color(ImGuiCol_ScrollbarBg), window_rounding, window_rounding_corners);
bb.Reduce(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 axis of the scrollbar
@@ -4085,7 +4098,7 @@
// 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);
- g.HoveredId = id;
+ ImGui::SetHoveredID(id);
bool seek_absolute = false;
if (!previously_held)
@@ -5107,7 +5120,7 @@
const bool hovered = IsHovered(bb, id, (flags & ImGuiButtonFlags_FlattenChilds) != 0);
if (hovered)
{
- g.HoveredId = id;
+ SetHoveredID(id);
if (allow_key_modifiers || (!g.IO.KeyCtrl && !g.IO.KeyShift && !g.IO.KeyAlt))
{
if (g.IO.MouseClicked[0])
@@ -5846,7 +5859,7 @@
// Our replacement widget will override the focus ID (registered previously to allow for a TAB focus to happen)
SetActiveID(g.ScalarAsInputTextId, window);
- g.HoveredId = 0;
+ SetHoveredID(0);
FocusableItemUnregister(window);
char buf[32];
@@ -5857,7 +5870,7 @@
// First frame
IM_ASSERT(g.ActiveId == id); // InputText ID expected to match the Slider ID (else we'd need to store them both, which is also possible)
g.ScalarAsInputTextId = g.ActiveId;
- g.HoveredId = id;
+ SetHoveredID(id);
}
else if (g.ActiveId != g.ScalarAsInputTextId)
{
@@ -6063,7 +6076,7 @@
const bool hovered = IsHovered(frame_bb, id);
if (hovered)
- g.HoveredId = id;
+ SetHoveredID(id);
if (!display_format)
display_format = "%.3f";
@@ -6122,7 +6135,7 @@
const bool hovered = IsHovered(frame_bb, id);
if (hovered)
- g.HoveredId = id;
+ SetHoveredID(id);
if (!display_format)
display_format = "%.3f";
@@ -6363,7 +6376,7 @@
const bool hovered = IsHovered(frame_bb, id);
if (hovered)
- g.HoveredId = id;
+ SetHoveredID(id);
if (!display_format)
display_format = "%.3f";
@@ -7108,7 +7121,7 @@
const bool hovered = IsHovered(frame_bb, id);
if (hovered)
{
- g.HoveredId = id;
+ SetHoveredID(id);
g.MouseCursor = ImGuiMouseCursor_TextInput;
}
const bool user_clicked = hovered && io.MouseClicked[0];
@@ -7123,8 +7136,8 @@
// Take a copy of the initial buffer value (both in original UTF-8 format and converted to wchar)
// From the moment we focused we are ignoring the content of 'buf'
const int prev_len_w = edit_state.CurLenW;
- edit_state.Text.resize(buf_size); // wchar count <= utf-8 count
- edit_state.InitialText.resize(buf_size); // utf-8
+ edit_state.Text.resize(buf_size+1); // wchar count <= utf-8 count. we use +1 to make sure that .Data isn't NULL so it doesn't crash.
+ edit_state.InitialText.resize(buf_size+1); // utf-8. we use +1 to make sure that .Data isn't NULL so it doesn't crash.
ImFormatString(edit_state.InitialText.Data, edit_state.InitialText.Size, "%s", buf);
const char* buf_end = NULL;
edit_state.CurLenW = ImTextStrFromUtf8(edit_state.Text.Data, edit_state.Text.Size, buf, NULL, &buf_end);
@@ -7176,7 +7189,7 @@
// Although we are active we don't prevent mouse from hovering other elements unless we are interacting right now with the widget.
// Down the line we should have a cleaner concept of focused vs active in the library.
- g.ActiveIdIsFocusedOnly = !io.MouseDown[0];
+ g.ActiveIdAllowHoveringOthers = !io.MouseDown[0];
// Edit in progress
const float mouse_x = (g.IO.MousePos.x - frame_bb.Min.x - style.FramePadding.x) + edit_state.ScrollX;
@@ -7835,7 +7848,7 @@
bool menu_toggled = false;
if (hovered)
{
- g.HoveredId = id;
+ SetHoveredID(id);
if (g.IO.MouseClicked[0])
{
SetActiveID(0);
@@ -8520,7 +8533,10 @@
ImGuiWindow* window = GetCurrentWindow();
if (window->SkipItems)
return;
- ItemSize(size);
+
+ const ImRect bb(window->DC.CursorPos, window->DC.CursorPos + size);
+ ItemSize(bb);
+ ItemAdd(bb, NULL);
}
bool ImGui::IsRectVisible(const ImVec2& size)
diff --git a/imgui.h b/imgui.h
index b5d3a97..361ba83 100644
--- a/imgui.h
+++ b/imgui.h
@@ -386,7 +386,7 @@
IMGUI_API ImVec2 CalcTextSize(const char* text, const char* text_end = NULL, bool hide_text_after_double_hash = false, float wrap_width = -1.0f);
IMGUI_API void CalcListClipping(int items_count, float items_height, int* out_items_display_start, int* out_items_display_end); // calculate coarse clipping for large list of evenly sized items. Prefer using the ImGuiListClipper higher-level helper if you can.
- IMGUI_API bool BeginChildFrame(ImGuiID id, const ImVec2& size); // helper to create a child window / scrolling region that looks like a normal widget frame
+ IMGUI_API bool BeginChildFrame(ImGuiID id, const ImVec2& size, ImGuiWindowFlags extra_flags = 0); // helper to create a child window / scrolling region that looks like a normal widget frame
IMGUI_API void EndChildFrame();
IMGUI_API ImVec4 ColorConvertU32ToFloat4(ImU32 in);
diff --git a/imgui_draw.cpp b/imgui_draw.cpp
index dcf30d9..e91ba39 100644
--- a/imgui_draw.cpp
+++ b/imgui_draw.cpp
@@ -1079,7 +1079,16 @@
static unsigned int stb_decompress(unsigned char *output, unsigned char *i, unsigned int length);
static const char* GetDefaultCompressedFontDataTTFBase85();
static unsigned int Decode85Byte(char c) { return c >= '\\' ? c-36 : c-35; }
-static void Decode85(const unsigned char* src, unsigned int* dst) { for (; *src; src += 5) *dst++ = Decode85Byte(src[0]) + 85*(Decode85Byte(src[1]) + 85*(Decode85Byte(src[2]) + 85*(Decode85Byte(src[3]) + 85*Decode85Byte(src[4])))); }
+static void Decode85(const unsigned char* src, unsigned char* dst)
+{
+ while (*src)
+ {
+ unsigned int tmp = Decode85Byte(src[0]) + 85*(Decode85Byte(src[1]) + 85*(Decode85Byte(src[2]) + 85*(Decode85Byte(src[3]) + 85*Decode85Byte(src[4]))));
+ dst[0] = ((tmp >> 0) & 0xFF); dst[1] = ((tmp >> 8) & 0xFF); dst[2] = ((tmp >> 16) & 0xFF); dst[3] = ((tmp >> 24) & 0xFF); // We can't assume little-endianess.
+ src += 5;
+ dst += 4;
+ }
+}
// Load embedded ProggyClean.ttf at size 13, disable oversampling
ImFont* ImFontAtlas::AddFontDefault(const ImFontConfig* font_cfg_template)
@@ -1146,7 +1155,7 @@
{
int compressed_ttf_size = (((int)strlen(compressed_ttf_data_base85) + 4) / 5) * 4;
void* compressed_ttf = ImGui::MemAlloc(compressed_ttf_size);
- Decode85((const unsigned char*)compressed_ttf_data_base85, (unsigned int*)compressed_ttf);
+ Decode85((const unsigned char*)compressed_ttf_data_base85, (unsigned char*)compressed_ttf);
ImFont* font = AddFontFromMemoryCompressedTTF(compressed_ttf, compressed_ttf_size, size_pixels, font_cfg, glyph_ranges);
ImGui::MemFree(compressed_ttf);
return font;
diff --git a/imgui_internal.h b/imgui_internal.h
index 22f7e80..1fac432 100644
--- a/imgui_internal.h
+++ b/imgui_internal.h
@@ -346,12 +346,13 @@
ImGuiWindow* HoveredWindow; // Will catch mouse inputs
ImGuiWindow* HoveredRootWindow; // Will catch mouse inputs (for focus/move only)
ImGuiID HoveredId; // Hovered widget
+ bool HoveredIdAllowHoveringOthers;
ImGuiID HoveredIdPreviousFrame;
ImGuiID ActiveId; // Active widget
ImGuiID ActiveIdPreviousFrame;
bool ActiveIdIsAlive;
bool ActiveIdIsJustActivated; // Set at the time of activation for one frame
- bool ActiveIdIsFocusedOnly; // Set only by active widget. Denote focus but no active interaction
+ bool ActiveIdAllowHoveringOthers; // Set only by active widget
ImGuiWindow* ActiveIdWindow;
ImGuiWindow* MovedWindow; // Track the child window we clicked on to move a window. Pointer is only valid if ActiveID is the "#MOVE" identifier of a window.
ImVector<ImGuiIniData> Settings; // .ini Settings
@@ -428,12 +429,13 @@
HoveredWindow = NULL;
HoveredRootWindow = NULL;
HoveredId = 0;
+ HoveredIdAllowHoveringOthers = false;
HoveredIdPreviousFrame = 0;
ActiveId = 0;
ActiveIdPreviousFrame = 0;
ActiveIdIsAlive = false;
ActiveIdIsJustActivated = false;
- ActiveIdIsFocusedOnly = false;
+ ActiveIdAllowHoveringOthers = false;
ActiveIdWindow = NULL;
MovedWindow = NULL;
SettingsDirtyTimer = 0.0f;
@@ -647,6 +649,7 @@
IMGUI_API void FocusWindow(ImGuiWindow* window);
IMGUI_API void SetActiveID(ImGuiID id, ImGuiWindow* window);
+ IMGUI_API void SetHoveredID(ImGuiID id);
IMGUI_API void KeepAliveID(ImGuiID id);
IMGUI_API void EndFrame(); // This automatically called by Render()