Bläddra i källkod

Updated imgui.

Branimir Karadžić 10 år sedan
förälder
incheckning
cf2cbf61c1

+ 24 - 13
3rdparty/ocornut-imgui/imgui.cpp

@@ -396,6 +396,7 @@
  - input text: add ImGuiInputTextFlags_EnterToApply? (off #218)
  - input text: add ImGuiInputTextFlags_EnterToApply? (off #218)
  - input text multi-line: way to dynamically grow the buffer without forcing the user to initially allocate for worse case (follow up on #200)
  - input text multi-line: way to dynamically grow the buffer without forcing the user to initially allocate for worse case (follow up on #200)
  - input text multi-line: line numbers? status bar? (follow up on #200)
  - input text multi-line: line numbers? status bar? (follow up on #200)
+ - input text: read-only mode (can still select/copy, always display input buffer)
  - input number: optional range min/max for Input*() functions
  - input number: optional range min/max for Input*() functions
  - input number: holding [-]/[+] buttons could increase the step speed non-linearly (or user-controlled)
  - input number: holding [-]/[+] buttons could increase the step speed non-linearly (or user-controlled)
  - input number: use mouse wheel to step up/down
  - input number: use mouse wheel to step up/down
@@ -776,13 +777,13 @@ const ImWchar* ImStrbolW(const ImWchar* buf_mid_line, const ImWchar* buf_begin)
     return buf_mid_line;
     return buf_mid_line;
 }
 }
 
 
-const char* ImStristr(const char* haystack, const char* needle, const char* needle_end)
+const char* ImStristr(const char* haystack, const char* haystack_end, const char* needle, const char* needle_end)
 {
 {
     if (!needle_end)
     if (!needle_end)
         needle_end = needle + strlen(needle);
         needle_end = needle + strlen(needle);
 
 
     const char un0 = (char)toupper(*needle);
     const char un0 = (char)toupper(*needle);
-    while (*haystack)
+    while ((!haystack_end && *haystack) || (haystack_end && haystack < haystack_end))
     {
     {
         if (toupper(*haystack) == un0)
         if (toupper(*haystack) == un0)
         {
         {
@@ -815,9 +816,9 @@ int ImFormatStringV(char* buf, int buf_size, const char* fmt, va_list args)
     return (w == -1) ? buf_size : w;
     return (w == -1) ? buf_size : w;
 }
 }
 
 
-// Pass data_size==0 for zero-terminated string
+// 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.
 // FIXME-OPT: Replace with e.g. FNV1a hash? CRC32 pretty much randomly access 1KB. Need to do proper measurements.
-ImU32 ImHash(const void* data, int data_size, ImU32 seed = 0) 
+ImU32 ImHash(const void* data, int data_size, ImU32 seed) 
 { 
 { 
     static ImU32 crc32_lut[256] = { 0 };
     static ImU32 crc32_lut[256] = { 0 };
     if (!crc32_lut[1])
     if (!crc32_lut[1])
@@ -1282,10 +1283,10 @@ ImGuiTextFilter::ImGuiTextFilter(const char* default_filter)
 
 
 void ImGuiTextFilter::Draw(const char* label, float width)
 void ImGuiTextFilter::Draw(const char* label, float width)
 {
 {
-    if (width > 0.0f)
+    if (width != 0.0f)
         ImGui::PushItemWidth(width);
         ImGui::PushItemWidth(width);
     ImGui::InputText(label, InputBuf, IM_ARRAYSIZE(InputBuf));
     ImGui::InputText(label, InputBuf, IM_ARRAYSIZE(InputBuf));
-    if (width > 0.0f)
+    if (width != 0.0f)
         ImGui::PopItemWidth();
         ImGui::PopItemWidth();
     Build();
     Build();
 }
 }
@@ -1325,13 +1326,13 @@ void ImGuiTextFilter::Build()
     }
     }
 }
 }
 
 
-bool ImGuiTextFilter::PassFilter(const char* val) const
+bool ImGuiTextFilter::PassFilter(const char* text, const char* text_end) const
 {
 {
     if (Filters.empty())
     if (Filters.empty())
         return true;
         return true;
 
 
-    if (val == NULL)
-        val = "";
+    if (text == NULL)
+        text = "";
 
 
     for (int i = 0; i != Filters.Size; i++)
     for (int i = 0; i != Filters.Size; i++)
     {
     {
@@ -1341,13 +1342,13 @@ bool ImGuiTextFilter::PassFilter(const char* val) const
         if (f.front() == '-')
         if (f.front() == '-')
         {
         {
             // Subtract
             // Subtract
-            if (ImStristr(val, f.begin()+1, f.end()) != NULL)
+            if (ImStristr(text, text_end, f.begin()+1, f.end()) != NULL)
                 return false;
                 return false;
         }
         }
         else
         else
         {
         {
             // Grep
             // Grep
-            if (ImStristr(val, f.begin(), f.end()) != NULL)
+            if (ImStristr(text, text_end, f.begin(), f.end()) != NULL)
                 return true;
                 return true;
         }
         }
     }
     }
@@ -2634,6 +2635,7 @@ ImVec2 ImGui::CalcTextSize(const char* text, const char* text_end, bool hide_tex
 
 
 // Helper to calculate coarse clipping of large list of evenly sized items. 
 // Helper to calculate coarse clipping of large list of evenly sized items. 
 // NB: Prefer using the ImGuiListClipper higher-level helper if you can!
 // NB: Prefer using the ImGuiListClipper higher-level helper if you can!
+// NB: 'items_count' is only used to clamp the result, if you don't know your count you can use INT_MAX
 // If you are displaying thousands of items and you have a random access to the list, you can perform clipping yourself to save on CPU.
 // If you are displaying thousands of items and you have a random access to the list, you can perform clipping yourself to save on CPU.
 // {
 // {
 //    float item_height = ImGui::GetTextLineHeightWithSpacing();
 //    float item_height = ImGui::GetTextLineHeightWithSpacing();
@@ -2824,6 +2826,14 @@ ImVec2 ImGui::GetMousePos()
     return GImGui->IO.MousePos;
     return GImGui->IO.MousePos;
 }
 }
 
 
+ImVec2 ImGui::GetMousePosOnOpeningCurrentPopup()
+{
+    ImGuiState& g = *GImGui;
+	if (g.CurrentPopupStack.Size > 0)
+		return g.OpenedPopupStack[g.CurrentPopupStack.Size-1].MousePosOnOpen;
+	return g.IO.MousePos;
+}
+
 ImVec2 ImGui::GetMouseDragDelta(int button, float lock_threshold)
 ImVec2 ImGui::GetMouseDragDelta(int button, float lock_threshold)
 {
 {
     ImGuiState& g = *GImGui;
     ImGuiState& g = *GImGui;
@@ -2980,7 +2990,7 @@ void ImGui::OpenPopup(const char* str_id)
     ImGuiWindow* window = GetCurrentWindow();
     ImGuiWindow* window = GetCurrentWindow();
     ImGuiID id = window->GetID(str_id);
     ImGuiID id = window->GetID(str_id);
     int current_stack_size = g.CurrentPopupStack.Size;
     int current_stack_size = g.CurrentPopupStack.Size;
-    ImGuiPopupRef popup_ref = ImGuiPopupRef(id, window, window->GetID("##menus")); // Tagged as new ref because constructor sets Window to NULL (we are passing the ParentWindow info here)
+    ImGuiPopupRef popup_ref = ImGuiPopupRef(id, window, window->GetID("##menus"), g.IO.MousePos); // Tagged as new ref because constructor sets Window to NULL (we are passing the ParentWindow info here)
     if (g.OpenedPopupStack.Size < current_stack_size + 1)
     if (g.OpenedPopupStack.Size < current_stack_size + 1)
         g.OpenedPopupStack.push_back(popup_ref);
         g.OpenedPopupStack.push_back(popup_ref);
     else if (g.OpenedPopupStack[current_stack_size].PopupID != id)
     else if (g.OpenedPopupStack[current_stack_size].PopupID != id)
@@ -4672,6 +4682,7 @@ void ImGui::SetScrollFromPosY(float pos_y, float center_y_ratio)
     window->ScrollTargetCenterRatioY = center_y_ratio;
     window->ScrollTargetCenterRatioY = center_y_ratio;
 }
 }
 
 
+// center_y_ratio: 0.0f top of last item, 0.5f vertical center of last item, 1.0f bottom of last item.
 void ImGui::SetScrollHere(float center_y_ratio)
 void ImGui::SetScrollHere(float center_y_ratio)
 {
 {
     ImGuiWindow* window = GetCurrentWindow();
     ImGuiWindow* window = GetCurrentWindow();
@@ -8830,7 +8841,7 @@ void ImGui::ShowMetricsWindow(bool* opened)
     {
     {
         ImGui::Text("ImGui %s", ImGui::GetVersion());
         ImGui::Text("ImGui %s", ImGui::GetVersion());
         ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate);
         ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate);
-        ImGui::Text("%d vertices, %d triangles", ImGui::GetIO().MetricsRenderVertices, ImGui::GetIO().MetricsRenderIndices / 3);
+        ImGui::Text("%d vertices, %d indices (%d triangles)", ImGui::GetIO().MetricsRenderVertices, ImGui::GetIO().MetricsRenderIndices, ImGui::GetIO().MetricsRenderIndices / 3);
         ImGui::Text("%d allocations", ImGui::GetIO().MetricsAllocs);
         ImGui::Text("%d allocations", ImGui::GetIO().MetricsAllocs);
         static bool show_clip_rects = true;
         static bool show_clip_rects = true;
         ImGui::Checkbox("Show clipping rectangles when hovering ImDrawList", &show_clip_rects);
         ImGui::Checkbox("Show clipping rectangles when hovering ImDrawList", &show_clip_rects);

+ 7 - 4
3rdparty/ocornut-imgui/imgui.h

@@ -398,6 +398,7 @@ namespace ImGui
     IMGUI_API bool          IsMouseHoveringRect(const ImVec2& pos_min, const ImVec2& pos_max);  // is mouse hovering given bounding rect (in screen space). clipped by current clipping settings. disregarding of consideration of focus/window ordering/blocked by a popup.
     IMGUI_API bool          IsMouseHoveringRect(const ImVec2& pos_min, const ImVec2& pos_max);  // is mouse hovering given bounding rect (in screen space). clipped by current clipping settings. disregarding of consideration of focus/window ordering/blocked by a popup.
     IMGUI_API bool          IsMouseDragging(int button = 0, float lock_threshold = -1.0f);      // is mouse dragging. if lock_threshold < -1.0f uses io.MouseDraggingThreshold
     IMGUI_API bool          IsMouseDragging(int button = 0, float lock_threshold = -1.0f);      // is mouse dragging. if lock_threshold < -1.0f uses io.MouseDraggingThreshold
     IMGUI_API ImVec2        GetMousePos();                                                      // shortcut to ImGui::GetIO().MousePos provided by user, to be consistent with other calls
     IMGUI_API ImVec2        GetMousePos();                                                      // shortcut to ImGui::GetIO().MousePos provided by user, to be consistent with other calls
+	IMGUI_API ImVec2		GetMousePosOnOpeningCurrentPopup();									// retrieve backup of mouse positioning at the time of opening popup we have BeginPopup() into
     IMGUI_API ImVec2        GetMouseDragDelta(int button = 0, float lock_threshold = -1.0f);    // dragging amount since clicking, also see: GetItemActiveDragDelta(). if lock_threshold < -1.0f uses io.MouseDraggingThreshold
     IMGUI_API ImVec2        GetMouseDragDelta(int button = 0, float lock_threshold = -1.0f);    // dragging amount since clicking, also see: GetItemActiveDragDelta(). if lock_threshold < -1.0f uses io.MouseDraggingThreshold
     IMGUI_API void          ResetMouseDragDelta(int button = 0);                                // 
     IMGUI_API void          ResetMouseDragDelta(int button = 0);                                // 
     IMGUI_API ImGuiMouseCursor GetMouseCursor();                                                // get desired cursor type, reset in ImGui::NewFrame(), this updated during the frame. valid before Render(). If you use software rendering by setting io.MouseDrawCursor ImGui will render those for you
     IMGUI_API ImGuiMouseCursor GetMouseCursor();                                                // get desired cursor type, reset in ImGui::NewFrame(), this updated during the frame. valid before Render(). If you use software rendering by setting io.MouseDrawCursor ImGui will render those for you
@@ -850,8 +851,8 @@ struct ImGuiTextFilter
 
 
     ImGuiTextFilter(const char* default_filter = "");
     ImGuiTextFilter(const char* default_filter = "");
     void Clear() { InputBuf[0] = 0; Build(); }
     void Clear() { InputBuf[0] = 0; Build(); }
-    void Draw(const char* label = "Filter (inc,-exc)", float width = -1.0f);    // Helper calling InputText+Build
-    bool PassFilter(const char* val) const;
+    void Draw(const char* label = "Filter (inc,-exc)", float width = 0.0f);    // Helper calling InputText+Build
+    bool PassFilter(const char* text, const char* text_end = NULL) const;
     bool IsActive() const { return !Filters.empty(); }
     bool IsActive() const { return !Filters.empty(); }
     IMGUI_API void Build();
     IMGUI_API void Build();
 };
 };
@@ -862,10 +863,11 @@ struct ImGuiTextBuffer
     ImVector<char>      Buf;
     ImVector<char>      Buf;
 
 
     ImGuiTextBuffer()   { Buf.push_back(0); }
     ImGuiTextBuffer()   { Buf.push_back(0); }
+    inline char         operator[](int i) { return Buf.Data[i]; }
     const char*         begin() const { return &Buf.front(); }
     const char*         begin() const { return &Buf.front(); }
     const char*         end() const { return &Buf.back(); }      // Buf is zero-terminated, so end() will point on the zero-terminator
     const char*         end() const { return &Buf.back(); }      // Buf is zero-terminated, so end() will point on the zero-terminator
-    int                 size() const { return Buf.Size-1; }
-    bool                empty() { return size() >= 1; }
+    int                 size() const { return Buf.Size - 1; }
+    bool                empty() { return Buf.Size >= 2; }
     void                clear() { Buf.clear(); Buf.push_back(0); }
     void                clear() { Buf.clear(); Buf.push_back(0); }
     IMGUI_API void      append(const char* fmt, ...) IM_PRINTFARGS(2);
     IMGUI_API void      append(const char* fmt, ...) IM_PRINTFARGS(2);
     IMGUI_API void      appendv(const char* fmt, va_list args);
     IMGUI_API void      appendv(const char* fmt, va_list args);
@@ -962,6 +964,7 @@ struct ImColor
 //    for (int i = clipper.DisplayStart; i < clipper.DisplayEnd; i++) // display only visible items
 //    for (int i = clipper.DisplayStart; i < clipper.DisplayEnd; i++) // display only visible items
 //        ImGui::Text("line number %d", i);
 //        ImGui::Text("line number %d", i);
 //    clipper.End();
 //    clipper.End();
+// NB: 'count' is only used to clamp the result, if you don't know your count you can use INT_MAX
 struct ImGuiListClipper
 struct ImGuiListClipper
 {
 {
     float   ItemsHeight;
     float   ItemsHeight;

+ 88 - 3
3rdparty/ocornut-imgui/imgui_demo.cpp

@@ -44,6 +44,7 @@
 #ifndef IMGUI_DISABLE_TEST_WINDOWS
 #ifndef IMGUI_DISABLE_TEST_WINDOWS
 
 
 static void ShowExampleAppConsole(bool* opened);
 static void ShowExampleAppConsole(bool* opened);
+static void ShowExampleAppLog(bool* opened);
 static void ShowExampleAppLayout(bool* opened);
 static void ShowExampleAppLayout(bool* opened);
 static void ShowExampleAppLongText(bool* opened);
 static void ShowExampleAppLongText(bool* opened);
 static void ShowExampleAppAutoResize(bool* opened);
 static void ShowExampleAppAutoResize(bool* opened);
@@ -89,6 +90,7 @@ void ImGui::ShowTestWindow(bool* opened)
     static bool show_app_metrics = false;
     static bool show_app_metrics = false;
     static bool show_app_main_menu_bar = false;
     static bool show_app_main_menu_bar = false;
     static bool show_app_console = false;
     static bool show_app_console = false;
+    static bool show_app_log = false;
     static bool show_app_layout = false;
     static bool show_app_layout = false;
     static bool show_app_long_text = false;
     static bool show_app_long_text = false;
     static bool show_app_auto_resize = false;
     static bool show_app_auto_resize = false;
@@ -99,6 +101,7 @@ void ImGui::ShowTestWindow(bool* opened)
     if (show_app_metrics) ImGui::ShowMetricsWindow(&show_app_metrics);
     if (show_app_metrics) ImGui::ShowMetricsWindow(&show_app_metrics);
     if (show_app_main_menu_bar) ShowExampleAppMainMenuBar();
     if (show_app_main_menu_bar) ShowExampleAppMainMenuBar();
     if (show_app_console) ShowExampleAppConsole(&show_app_console);
     if (show_app_console) ShowExampleAppConsole(&show_app_console);
+    if (show_app_log) ShowExampleAppLog(&show_app_log);
     if (show_app_layout) ShowExampleAppLayout(&show_app_layout);
     if (show_app_layout) ShowExampleAppLayout(&show_app_layout);
     if (show_app_long_text) ShowExampleAppLongText(&show_app_long_text);
     if (show_app_long_text) ShowExampleAppLongText(&show_app_long_text);
     if (show_app_auto_resize) ShowExampleAppAutoResize(&show_app_auto_resize);
     if (show_app_auto_resize) ShowExampleAppAutoResize(&show_app_auto_resize);
@@ -157,6 +160,7 @@ void ImGui::ShowTestWindow(bool* opened)
         {
         {
             ImGui::MenuItem("Main menu bar", NULL, &show_app_main_menu_bar);
             ImGui::MenuItem("Main menu bar", NULL, &show_app_main_menu_bar);
             ImGui::MenuItem("Console", NULL, &show_app_console);
             ImGui::MenuItem("Console", NULL, &show_app_console);
+            ImGui::MenuItem("Log", NULL, &show_app_log);
             ImGui::MenuItem("Simple layout", NULL, &show_app_layout);
             ImGui::MenuItem("Simple layout", NULL, &show_app_layout);
             ImGui::MenuItem("Long text display", NULL, &show_app_long_text);
             ImGui::MenuItem("Long text display", NULL, &show_app_long_text);
             ImGui::MenuItem("Auto-resizing window", NULL, &show_app_auto_resize);
             ImGui::MenuItem("Auto-resizing window", NULL, &show_app_auto_resize);
@@ -1715,7 +1719,7 @@ struct ExampleAppConsole
         ScrollToBottom = true;
         ScrollToBottom = true;
     }
     }
 
 
-    void    Run(const char* title, bool* opened)
+    void    Draw(const char* title, bool* opened)
     {
     {
         ImGui::SetNextWindowSize(ImVec2(520,600), ImGuiSetCond_FirstUseEver);
         ImGui::SetNextWindowSize(ImVec2(520,600), ImGuiSetCond_FirstUseEver);
         if (!ImGui::Begin(title, opened))
         if (!ImGui::Begin(title, opened))
@@ -1938,7 +1942,88 @@ struct ExampleAppConsole
 static void ShowExampleAppConsole(bool* opened)
 static void ShowExampleAppConsole(bool* opened)
 {
 {
     static ExampleAppConsole console;
     static ExampleAppConsole console;
-    console.Run("Example: Console", opened);
+    console.Draw("Example: Console", opened);
+}
+
+// Usage:
+//  static ExampleAppLog my_log;
+//  my_log.AddLog("Hello %d world\n", 123);
+//  my_log.Draw("title");
+struct ExampleAppLog
+{
+    ImGuiTextBuffer     Buf;
+    ImGuiTextFilter     Filter;
+    ImVector<int>       LineOffsets;        // Index to lines offset
+    bool                ScrollToBottom;
+
+    void    Clear()     { Buf.clear(); LineOffsets.clear(); }
+
+    void    AddLog(const char* fmt, ...) IM_PRINTFARGS(2)
+    {
+        int old_size = Buf.size();
+        va_list args;
+        va_start(args, fmt);
+        Buf.appendv(fmt, args);
+        va_end(args);
+        for (int new_size = Buf.size(); old_size < new_size; old_size++)
+            if (Buf[old_size] == '\n')
+                LineOffsets.push_back(old_size);
+        ScrollToBottom = true;
+    }
+
+    void    Draw(const char* title, bool* p_opened = NULL)
+    {
+        ImGui::SetNextWindowSize(ImVec2(500,400), ImGuiSetCond_FirstUseEver);
+        ImGui::Begin(title, p_opened);
+        if (ImGui::Button("Clear")) Clear();
+        ImGui::SameLine();
+        bool copy = ImGui::Button("Copy");
+        ImGui::SameLine();
+        Filter.Draw("Filter", -100.0f);
+        ImGui::Separator();
+        ImGui::BeginChild("scrolling");
+        if (copy) ImGui::LogToClipboard();
+
+        if (Filter.IsActive())
+        {
+            const char* buf_begin = Buf.begin();
+            const char* line = buf_begin;
+            for (int line_no = 0; line != NULL; line_no++)
+            {
+                const char* line_end = (line_no < LineOffsets.Size) ? buf_begin + LineOffsets[line_no] : NULL;
+                if (Filter.PassFilter(line, line_end))
+                    ImGui::TextUnformatted(line, line_end);
+                line = line_end && line_end[1] ? line_end + 1 : NULL;
+            }
+        }
+        else
+        {
+            ImGui::TextUnformatted(Buf.begin());
+        }
+
+        if (ScrollToBottom)
+            ImGui::SetScrollHere(1.0f);
+        ScrollToBottom = false;
+        ImGui::EndChild();
+        ImGui::End();
+    }
+};
+
+static void ShowExampleAppLog(bool* opened)
+{
+    static ExampleAppLog log;
+
+    // Demo fill
+    static float last_time = -1.0f;
+    float time = ImGui::GetTime();
+    if (time - last_time >= 0.3f)
+    {
+        const char* random_words[] = { "system", "info", "warning", "error", "fatal", "notice", "log" };
+        log.AddLog("[%s] Hello, time is %.1f, rand() %d\n", random_words[rand() % IM_ARRAYSIZE(random_words)], time, (int)rand());
+        last_time = time;
+    }
+
+    log.Draw("Example: Log", opened);
 }
 }
 
 
 static void ShowExampleAppLayout(bool* opened)
 static void ShowExampleAppLayout(bool* opened)
@@ -1999,7 +2084,7 @@ static void ShowExampleAppLongText(bool* opened)
     static ImGuiTextBuffer log;
     static ImGuiTextBuffer log;
     static int lines = 0;
     static int lines = 0;
     ImGui::Text("Printing unusually long amount of text.");
     ImGui::Text("Printing unusually long amount of text.");
-    ImGui::Combo("Test type", &test_type, "Single call to TextUnformatted()\0Multiple calls to Text(), clipped manually\0Multiple calls to Text(), not clipped"); 
+    ImGui::Combo("Test type", &test_type, "Single call to TextUnformatted()\0Multiple calls to Text(), clipped manually\0Multiple calls to Text(), not clipped\0"); 
     ImGui::Text("Buffer contents: %d lines, %d bytes", lines, log.size());
     ImGui::Text("Buffer contents: %d lines, %d bytes", lines, log.size());
     if (ImGui::Button("Clear")) { log.clear(); lines = 0; }
     if (ImGui::Button("Clear")) { log.clear(); lines = 0; }
     ImGui::SameLine();
     ImGui::SameLine();

+ 4 - 3
3rdparty/ocornut-imgui/imgui_internal.h

@@ -81,7 +81,7 @@ int                 ImTextCountCharsFromUtf8(const char* in_text, const char* in
 int                 ImTextCountUtf8BytesFromStr(const ImWchar* in_text, const ImWchar* in_text_end);                   // return number of bytes to express string as UTF-8 code-points
 int                 ImTextCountUtf8BytesFromStr(const ImWchar* in_text, const ImWchar* in_text_end);                   // return number of bytes to express string as UTF-8 code-points
 
 
 // Helpers: Misc
 // Helpers: Misc
-ImU32               ImHash(const void* data, int data_size, ImU32 seed);
+ImU32               ImHash(const void* data, int data_size, ImU32 seed = 0);	// Pass data_size==0 for zero-terminated strings
 bool                ImLoadFileToMemory(const char* filename, const char* file_open_mode, void** out_file_data, int* out_file_size = NULL, int padding_bytes = 0);
 bool                ImLoadFileToMemory(const char* filename, const char* file_open_mode, void** out_file_data, int* out_file_size = NULL, int padding_bytes = 0);
 bool                ImIsPointInTriangle(const ImVec2& p, const ImVec2& a, const ImVec2& b, const ImVec2& c);
 bool                ImIsPointInTriangle(const ImVec2& p, const ImVec2& a, const ImVec2& b, const ImVec2& c);
 static inline bool  ImCharIsSpace(int c)            { return c == ' ' || c == '\t' || c == 0x3000; }
 static inline bool  ImCharIsSpace(int c)            { return c == ' ' || c == '\t' || c == 0x3000; }
@@ -93,7 +93,7 @@ int                 ImStrnicmp(const char* str1, const char* str2, int count);
 char*               ImStrdup(const char* str);
 char*               ImStrdup(const char* str);
 int                 ImStrlenW(const ImWchar* str);
 int                 ImStrlenW(const ImWchar* str);
 const ImWchar*      ImStrbolW(const ImWchar* buf_mid_line, const ImWchar* buf_begin); // Find beginning-of-line
 const ImWchar*      ImStrbolW(const ImWchar* buf_mid_line, const ImWchar* buf_begin); // Find beginning-of-line
-const char*         ImStristr(const char* haystack, const char* needle, const char* needle_end);
+const char*         ImStristr(const char* haystack, const char* haystack_end, const char* needle, const char* needle_end);
 int                 ImFormatString(char* buf, int buf_size, const char* fmt, ...) IM_PRINTFARGS(3);
 int                 ImFormatString(char* buf, int buf_size, const char* fmt, ...) IM_PRINTFARGS(3);
 int                 ImFormatStringV(char* buf, int buf_size, const char* fmt, va_list args);
 int                 ImFormatStringV(char* buf, int buf_size, const char* fmt, va_list args);
 
 
@@ -305,8 +305,9 @@ struct ImGuiPopupRef
     ImGuiWindow*        Window;         // Resolved on BeginPopup() - may stay unresolved if user never calls OpenPopup()
     ImGuiWindow*        Window;         // Resolved on BeginPopup() - may stay unresolved if user never calls OpenPopup()
     ImGuiWindow*        ParentWindow;   // Set on OpenPopup()
     ImGuiWindow*        ParentWindow;   // Set on OpenPopup()
     ImGuiID             ParentMenuSet;  // Set on OpenPopup()
     ImGuiID             ParentMenuSet;  // Set on OpenPopup()
+	ImVec2				MousePosOnOpen;	// Copy of mouse position at the time of opening popup
 
 
-    ImGuiPopupRef(ImGuiID id, ImGuiWindow* parent_window, ImGuiID parent_menu_set) { PopupID = id; Window = NULL; ParentWindow = parent_window; ParentMenuSet = parent_menu_set; }
+    ImGuiPopupRef(ImGuiID id, ImGuiWindow* parent_window, ImGuiID parent_menu_set, const ImVec2& mouse_pos) { PopupID = id; Window = NULL; ParentWindow = parent_window; ParentMenuSet = parent_menu_set; MousePosOnOpen = mouse_pos; }
 };
 };
 
 
 // Main state for ImGui
 // Main state for ImGui

+ 1 - 1
examples/common/imgui/ocornut_imgui.cpp

@@ -163,7 +163,7 @@ struct OcornutImguiContext
 			vsmem = bgfx::makeRef(vs_ocornut_imgui_mtl, sizeof(vs_ocornut_imgui_mtl) );
 			vsmem = bgfx::makeRef(vs_ocornut_imgui_mtl, sizeof(vs_ocornut_imgui_mtl) );
 			fsmem = bgfx::makeRef(fs_ocornut_imgui_mtl, sizeof(fs_ocornut_imgui_mtl) );
 			fsmem = bgfx::makeRef(fs_ocornut_imgui_mtl, sizeof(fs_ocornut_imgui_mtl) );
 			break;
 			break;
-				
+
 		default:
 		default:
 			vsmem = bgfx::makeRef(vs_ocornut_imgui_glsl, sizeof(vs_ocornut_imgui_glsl) );
 			vsmem = bgfx::makeRef(vs_ocornut_imgui_glsl, sizeof(vs_ocornut_imgui_glsl) );
 			fsmem = bgfx::makeRef(fs_ocornut_imgui_glsl, sizeof(fs_ocornut_imgui_glsl) );
 			fsmem = bgfx::makeRef(fs_ocornut_imgui_glsl, sizeof(fs_ocornut_imgui_glsl) );