Branimir Karadžić 10 éve
szülő
commit
77bb76e83b

+ 46 - 35
3rdparty/ocornut-imgui/imgui.cpp

@@ -136,6 +136,7 @@
  Occasionally introducing changes that are breaking the API. The breakage are generally minor and easy to fix.
  Occasionally introducing changes that are breaking the API. The breakage are generally minor and easy to fix.
  Here is a change-log of API breaking changes, if you are using one of the functions listed, expect to have to fix some code.
  Here is a change-log of API breaking changes, if you are using one of the functions listed, expect to have to fix some code.
  
  
+ - 2015/07/10 (1.43) - changed SameLine() parameters from int to float.
  - 2015/07/02 (1.42) - renamed SetScrollPosHere() to SetScrollFromCursorPos(). Kept inline redirection function (will obsolete).
  - 2015/07/02 (1.42) - renamed SetScrollPosHere() to SetScrollFromCursorPos(). Kept inline redirection function (will obsolete).
  - 2015/07/02 (1.42) - renamed GetScrollPosY() to GetScrollY(). Necessary to reduce confusion along with other scrolling functions, because positions (e.g. cursor position) are not equivalent to scrolling amount.
  - 2015/07/02 (1.42) - renamed GetScrollPosY() to GetScrollY(). Necessary to reduce confusion along with other scrolling functions, because positions (e.g. cursor position) are not equivalent to scrolling amount.
  - 2015/06/14 (1.41) - changed ImageButton() default bg_col parameter from (0,0,0,1) (black) to (0,0,0,0) (transparent) - makes a difference when texture have transparence
  - 2015/06/14 (1.41) - changed ImageButton() default bg_col parameter from (0,0,0,1) (black) to (0,0,0,0) (transparent) - makes a difference when texture have transparence
@@ -1289,7 +1290,7 @@ struct ImGuiState
     bool                    ActiveIdIsJustActivated;            // Set at the time of activation for one frame
     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                    ActiveIdIsFocusedOnly;              // Set only by active widget. Denote focus but no active interaction
     ImGuiWindow*            ActiveIdWindow;
     ImGuiWindow*            ActiveIdWindow;
-    ImGuiWindow*            MovedWindow;                        // Track the child window we clicked on to move a window. Only valid if ActiveID is the "#MOVE" identifier of a window.
+    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.
     float                   SettingsDirtyTimer;
     float                   SettingsDirtyTimer;
     ImVector<ImGuiIniData>  Settings;
     ImVector<ImGuiIniData>  Settings;
     int                     DisableHideTextAfterDoubleHash;
     int                     DisableHideTextAfterDoubleHash;
@@ -2400,13 +2401,14 @@ void ImGui::Render()
         ImGui::End();
         ImGui::End();
 
 
         // Click to focus window and start moving (after we're done with all our widgets)
         // Click to focus window and start moving (after we're done with all our widgets)
+        if (!g.ActiveId)
+            g.MovedWindow = NULL;
         if (g.ActiveId == 0 && g.HoveredId == 0 && g.IO.MouseClicked[0])
         if (g.ActiveId == 0 && g.HoveredId == 0 && g.IO.MouseClicked[0])
         {
         {
             if (!(g.FocusedWindow && !g.FocusedWindow->WasActive && g.FocusedWindow->Active)) // Unless we just made a popup appear
             if (!(g.FocusedWindow && !g.FocusedWindow->WasActive && g.FocusedWindow->Active)) // Unless we just made a popup appear
             {
             {
                 if (g.HoveredRootWindow != NULL)
                 if (g.HoveredRootWindow != NULL)
                 {
                 {
-                    IM_ASSERT(g.MovedWindow == NULL);
                     g.MovedWindow = g.HoveredWindow;
                     g.MovedWindow = g.HoveredWindow;
                     SetActiveId(g.HoveredRootWindow->MoveID, g.HoveredRootWindow);
                     SetActiveId(g.HoveredRootWindow->MoveID, g.HoveredRootWindow);
                 }
                 }
@@ -6161,7 +6163,7 @@ static bool SliderFloatN(const char* label, float* v, int components, float v_mi
     {
     {
         ImGui::PushID(i);
         ImGui::PushID(i);
         value_changed |= ImGui::SliderFloat("##v", &v[i], v_min, v_max, display_format, power);
         value_changed |= ImGui::SliderFloat("##v", &v[i], v_min, v_max, display_format, power);
-        ImGui::SameLine(0, (int)g.Style.ItemInnerSpacing.x);
+        ImGui::SameLine(0, g.Style.ItemInnerSpacing.x);
         ImGui::PopID();
         ImGui::PopID();
         ImGui::PopItemWidth();
         ImGui::PopItemWidth();
     }
     }
@@ -6203,7 +6205,7 @@ static bool SliderIntN(const char* label, int* v, int components, int v_min, int
     {
     {
         ImGui::PushID(i);
         ImGui::PushID(i);
         value_changed |= ImGui::SliderInt("##v", &v[i], v_min, v_max, display_format);
         value_changed |= ImGui::SliderInt("##v", &v[i], v_min, v_max, display_format);
-        ImGui::SameLine(0, (int)g.Style.ItemInnerSpacing.x);
+        ImGui::SameLine(0, g.Style.ItemInnerSpacing.x);
         ImGui::PopID();
         ImGui::PopID();
         ImGui::PopItemWidth();
         ImGui::PopItemWidth();
     }
     }
@@ -6387,7 +6389,7 @@ static bool DragFloatN(const char* label, float* v, int components, float v_spee
     {
     {
         ImGui::PushID(i);
         ImGui::PushID(i);
         value_changed |= ImGui::DragFloat("##v", &v[i], v_speed, v_min, v_max, display_format, power);
         value_changed |= ImGui::DragFloat("##v", &v[i], v_speed, v_min, v_max, display_format, power);
-        ImGui::SameLine(0, (int)g.Style.ItemInnerSpacing.x);
+        ImGui::SameLine(0, g.Style.ItemInnerSpacing.x);
         ImGui::PopID();
         ImGui::PopID();
         ImGui::PopItemWidth();
         ImGui::PopItemWidth();
     }
     }
@@ -6427,10 +6429,10 @@ bool ImGui::DragFloatRange2(const char* label, float* v_current_min, float* v_cu
 
 
     bool value_changed = ImGui::DragFloat("##min", v_current_min, v_speed, (v_min >= v_max) ? -FLT_MAX : v_min, (v_min >= v_max) ? *v_current_max : ImMin(v_max, *v_current_max), display_format, power);
     bool value_changed = ImGui::DragFloat("##min", v_current_min, v_speed, (v_min >= v_max) ? -FLT_MAX : v_min, (v_min >= v_max) ? *v_current_max : ImMin(v_max, *v_current_max), display_format, power);
     ImGui::PopItemWidth();
     ImGui::PopItemWidth();
-    ImGui::SameLine(0, (int)g.Style.ItemInnerSpacing.x);
+    ImGui::SameLine(0, g.Style.ItemInnerSpacing.x);
     value_changed |= ImGui::DragFloat("##max", v_current_max, v_speed, (v_min >= v_max) ? *v_current_min : ImMax(v_min, *v_current_min), (v_min >= v_max) ? FLT_MAX : v_max, display_format_max ? display_format_max : display_format, power);
     value_changed |= ImGui::DragFloat("##max", v_current_max, v_speed, (v_min >= v_max) ? *v_current_min : ImMax(v_min, *v_current_min), (v_min >= v_max) ? FLT_MAX : v_max, display_format_max ? display_format_max : display_format, power);
     ImGui::PopItemWidth();
     ImGui::PopItemWidth();
-    ImGui::SameLine(0, (int)g.Style.ItemInnerSpacing.x);
+    ImGui::SameLine(0, g.Style.ItemInnerSpacing.x);
 
 
     ImGui::TextUnformatted(label, FindTextDisplayEnd(label));
     ImGui::TextUnformatted(label, FindTextDisplayEnd(label));
     ImGui::EndGroup();
     ImGui::EndGroup();
@@ -6465,7 +6467,7 @@ static bool DragIntN(const char* label, int* v, int components, float v_speed, i
     {
     {
         ImGui::PushID(i);
         ImGui::PushID(i);
         value_changed |= ImGui::DragInt("##v", &v[i], v_speed, v_min, v_max, display_format);
         value_changed |= ImGui::DragInt("##v", &v[i], v_speed, v_min, v_max, display_format);
-        ImGui::SameLine(0, (int)g.Style.ItemInnerSpacing.x);
+        ImGui::SameLine(0, g.Style.ItemInnerSpacing.x);
         ImGui::PopID();
         ImGui::PopID();
         ImGui::PopItemWidth();
         ImGui::PopItemWidth();
     }
     }
@@ -6505,10 +6507,10 @@ bool ImGui::DragIntRange2(const char* label, int* v_current_min, int* v_current_
 
 
     bool value_changed = ImGui::DragInt("##min", v_current_min, v_speed, (v_min >= v_max) ? IM_INT_MIN : v_min, (v_min >= v_max) ? *v_current_max : ImMin(v_max, *v_current_max), display_format);
     bool value_changed = ImGui::DragInt("##min", v_current_min, v_speed, (v_min >= v_max) ? IM_INT_MIN : v_min, (v_min >= v_max) ? *v_current_max : ImMin(v_max, *v_current_max), display_format);
     ImGui::PopItemWidth();
     ImGui::PopItemWidth();
-    ImGui::SameLine(0, (int)g.Style.ItemInnerSpacing.x);
+    ImGui::SameLine(0, g.Style.ItemInnerSpacing.x);
     value_changed |= ImGui::DragInt("##max", v_current_max, v_speed, (v_min >= v_max) ? *v_current_min : ImMax(v_min, *v_current_min), (v_min >= v_max) ? IM_INT_MAX : v_max, display_format_max ? display_format_max : display_format);
     value_changed |= ImGui::DragInt("##max", v_current_max, v_speed, (v_min >= v_max) ? *v_current_min : ImMax(v_min, *v_current_min), (v_min >= v_max) ? IM_INT_MAX : v_max, display_format_max ? display_format_max : display_format);
     ImGui::PopItemWidth();
     ImGui::PopItemWidth();
-    ImGui::SameLine(0, (int)g.Style.ItemInnerSpacing.x);
+    ImGui::SameLine(0, g.Style.ItemInnerSpacing.x);
 
 
     ImGui::TextUnformatted(label, FindTextDisplayEnd(label));
     ImGui::TextUnformatted(label, FindTextDisplayEnd(label));
     ImGui::EndGroup();
     ImGui::EndGroup();
@@ -6672,7 +6674,7 @@ bool ImGui::Checkbox(const char* label, bool* v)
 
 
     ImRect total_bb = check_bb;
     ImRect total_bb = check_bb;
     if (label_size.x > 0)
     if (label_size.x > 0)
-        SameLine(0, (int)style.ItemInnerSpacing.x);
+        SameLine(0, style.ItemInnerSpacing.x);
     const ImRect text_bb(window->DC.CursorPos + ImVec2(0,style.FramePadding.y), window->DC.CursorPos + ImVec2(0,style.FramePadding.y) + label_size);
     const ImRect text_bb(window->DC.CursorPos + ImVec2(0,style.FramePadding.y), window->DC.CursorPos + ImVec2(0,style.FramePadding.y) + label_size);
     if (label_size.x > 0)
     if (label_size.x > 0)
     {
     {
@@ -6730,7 +6732,7 @@ bool ImGui::RadioButton(const char* label, bool active)
 
 
     ImRect total_bb = check_bb;
     ImRect total_bb = check_bb;
     if (label_size.x > 0)
     if (label_size.x > 0)
-        SameLine(0, (int)style.ItemInnerSpacing.x);
+        SameLine(0, style.ItemInnerSpacing.x);
     const ImRect text_bb(window->DC.CursorPos + ImVec2(0, style.FramePadding.y), window->DC.CursorPos + ImVec2(0, style.FramePadding.y) + label_size);
     const ImRect text_bb(window->DC.CursorPos + ImVec2(0, style.FramePadding.y), window->DC.CursorPos + ImVec2(0, style.FramePadding.y) + label_size);
     if (label_size.x > 0)
     if (label_size.x > 0)
     {
     {
@@ -7121,6 +7123,8 @@ static bool InputTextEx(const char* label, char* buf, int buf_size, const ImVec2
                 edit_state.StbState.select_start = ImMin(edit_state.StbState.select_start, edit_state.CurLenW);
                 edit_state.StbState.select_start = ImMin(edit_state.StbState.select_start, edit_state.CurLenW);
                 edit_state.StbState.select_end = ImMin(edit_state.StbState.select_end, edit_state.CurLenW);
                 edit_state.StbState.select_end = ImMin(edit_state.StbState.select_end, edit_state.CurLenW);
             }
             }
+            if (flags & ImGuiInputTextFlags_AlwaysInsertMode)
+                edit_state.StbState.insert_mode = true;
             if (!is_multiline && (focus_requested_by_tab || (user_clicked && is_ctrl_down)))
             if (!is_multiline && (focus_requested_by_tab || (user_clicked && is_ctrl_down)))
                 select_all = true;
                 select_all = true;
         }
         }
@@ -7420,11 +7424,18 @@ static bool InputTextEx(const char* label, char* buf, int buf_size, const ImVec2
         if (edit_state.CursorFollow)
         if (edit_state.CursorFollow)
         {
         {
             // Horizontal scroll in chunks of quarter width
             // Horizontal scroll in chunks of quarter width
-            const float scroll_increment_x = size.x * 0.25f;
-            if (cursor_offset.x < edit_state.ScrollX)
-                edit_state.ScrollX = ImMax(0.0f, cursor_offset.x - scroll_increment_x);    
-            else if (cursor_offset.x - size.x >= edit_state.ScrollX)
-                edit_state.ScrollX = cursor_offset.x - size.x + scroll_increment_x;
+            if (!(flags & ImGuiInputTextFlags_NoHorizontalScroll))
+            {
+                const float scroll_increment_x = size.x * 0.25f;
+                if (cursor_offset.x < edit_state.ScrollX)
+                    edit_state.ScrollX = ImMax(0.0f, cursor_offset.x - scroll_increment_x);    
+                else if (cursor_offset.x - size.x >= edit_state.ScrollX)
+                    edit_state.ScrollX = cursor_offset.x - size.x + scroll_increment_x;
+            }
+            else
+            {
+                edit_state.ScrollX = 0.0f;
+            }
 
 
             // Vertical scroll
             // Vertical scroll
             if (is_multiline)
             if (is_multiline)
@@ -7566,13 +7577,13 @@ bool ImGui::InputFloat(const char* label, float *v, float step, float step_fast,
     if (step > 0.0f)
     if (step > 0.0f)
     {
     {
         ImGui::PopItemWidth();
         ImGui::PopItemWidth();
-        ImGui::SameLine(0, (int)style.ItemInnerSpacing.x);
+        ImGui::SameLine(0, style.ItemInnerSpacing.x);
         if (ButtonEx("-", button_sz, ImGuiButtonFlags_Repeat | ImGuiButtonFlags_DontClosePopups))
         if (ButtonEx("-", button_sz, ImGuiButtonFlags_Repeat | ImGuiButtonFlags_DontClosePopups))
         {
         {
             *v -= g.IO.KeyCtrl && step_fast > 0.0f ? step_fast : step;
             *v -= g.IO.KeyCtrl && step_fast > 0.0f ? step_fast : step;
             value_changed = true;
             value_changed = true;
         }
         }
-        ImGui::SameLine(0, (int)style.ItemInnerSpacing.x);
+        ImGui::SameLine(0, style.ItemInnerSpacing.x);
         if (ButtonEx("+", button_sz, ImGuiButtonFlags_Repeat | ImGuiButtonFlags_DontClosePopups))
         if (ButtonEx("+", button_sz, ImGuiButtonFlags_Repeat | ImGuiButtonFlags_DontClosePopups))
         {
         {
             *v += g.IO.KeyCtrl && step_fast > 0.0f ? step_fast : step;
             *v += g.IO.KeyCtrl && step_fast > 0.0f ? step_fast : step;
@@ -7583,7 +7594,7 @@ bool ImGui::InputFloat(const char* label, float *v, float step, float step_fast,
 
 
     if (label_size.x > 0)
     if (label_size.x > 0)
     {
     {
-        ImGui::SameLine(0, (int)style.ItemInnerSpacing.x);
+        ImGui::SameLine(0, style.ItemInnerSpacing.x);
         RenderText(ImVec2(window->DC.CursorPos.x, window->DC.CursorPos.y + style.FramePadding.y), label);
         RenderText(ImVec2(window->DC.CursorPos.x, window->DC.CursorPos.y + style.FramePadding.y), label);
         ItemSize(label_size, style.FramePadding.y);
         ItemSize(label_size, style.FramePadding.y);
     }
     }
@@ -7616,7 +7627,7 @@ static bool InputFloatN(const char* label, float* v, int components, int decimal
     {
     {
         ImGui::PushID(i);
         ImGui::PushID(i);
         value_changed |= ImGui::InputFloat("##v", &v[i], 0, 0, decimal_precision, extra_flags);
         value_changed |= ImGui::InputFloat("##v", &v[i], 0, 0, decimal_precision, extra_flags);
-        ImGui::SameLine(0, (int)g.Style.ItemInnerSpacing.x);
+        ImGui::SameLine(0, g.Style.ItemInnerSpacing.x);
         ImGui::PopID();
         ImGui::PopID();
         ImGui::PopItemWidth();
         ImGui::PopItemWidth();
     }
     }
@@ -7659,7 +7670,7 @@ static bool InputIntN(const char* label, int* v, int components, ImGuiInputTextF
     {
     {
         ImGui::PushID(i);
         ImGui::PushID(i);
         value_changed |= ImGui::InputInt("##v", &v[i], 0, 0, extra_flags);
         value_changed |= ImGui::InputInt("##v", &v[i], 0, 0, extra_flags);
-        ImGui::SameLine(0, (int)g.Style.ItemInnerSpacing.x);
+        ImGui::SameLine(0, g.Style.ItemInnerSpacing.x);
         ImGui::PopID();
         ImGui::PopID();
         ImGui::PopItemWidth();
         ImGui::PopItemWidth();
     }
     }
@@ -8333,7 +8344,7 @@ bool ImGui::ColorEdit4(const char* label, float col[4], bool alpha)
             for (int n = 0; n < components; n++)
             for (int n = 0; n < components; n++)
             {
             {
                 if (n > 0)
                 if (n > 0)
-                    ImGui::SameLine(0, (int)style.ItemInnerSpacing.x);
+                    ImGui::SameLine(0, style.ItemInnerSpacing.x);
                 if (n + 1 == components)
                 if (n + 1 == components)
                     ImGui::PushItemWidth(w_item_last);
                     ImGui::PushItemWidth(w_item_last);
                 value_changed |= ImGui::DragInt(ids[n], &i[n], 1.0f, 0, 255, fmt[n]);
                 value_changed |= ImGui::DragInt(ids[n], &i[n], 1.0f, 0, 255, fmt[n]);
@@ -8368,7 +8379,7 @@ bool ImGui::ColorEdit4(const char* label, float col[4], bool alpha)
         break;
         break;
     }
     }
 
 
-    ImGui::SameLine(0, (int)style.ItemInnerSpacing.x);
+    ImGui::SameLine(0, style.ItemInnerSpacing.x);
 
 
     const ImVec4 col_display(col[0], col[1], col[2], 1.0f);
     const ImVec4 col_display(col[0], col[1], col[2], 1.0f);
     if (ImGui::ColorButton(col_display))
     if (ImGui::ColorButton(col_display))
@@ -8376,7 +8387,7 @@ bool ImGui::ColorEdit4(const char* label, float col[4], bool alpha)
 
 
     if (window->DC.ColorEditMode == ImGuiColorEditMode_UserSelectShowButton)
     if (window->DC.ColorEditMode == ImGuiColorEditMode_UserSelectShowButton)
     {
     {
-        ImGui::SameLine(0, (int)style.ItemInnerSpacing.x);
+        ImGui::SameLine(0, style.ItemInnerSpacing.x);
         const char* button_titles[3] = { "RGB", "HSV", "HEX" };
         const char* button_titles[3] = { "RGB", "HSV", "HEX" };
         if (ButtonEx(button_titles[edit_mode], ImVec2(0,0), ImGuiButtonFlags_DontClosePopups))
         if (ButtonEx(button_titles[edit_mode], ImVec2(0,0), ImGuiButtonFlags_DontClosePopups))
             g.ColorEditModeStorage.SetInt(id, (edit_mode + 1) % 3); // Don't set local copy of 'edit_mode' right away!
             g.ColorEditModeStorage.SetInt(id, (edit_mode + 1) % 3); // Don't set local copy of 'edit_mode' right away!
@@ -8384,7 +8395,7 @@ bool ImGui::ColorEdit4(const char* label, float col[4], bool alpha)
     }
     }
     else
     else
     {
     {
-        ImGui::SameLine(0, (int)style.ItemInnerSpacing.x);
+        ImGui::SameLine(0, style.ItemInnerSpacing.x);
     }
     }
 
 
     ImGui::TextUnformatted(label, FindTextDisplayEnd(label));
     ImGui::TextUnformatted(label, FindTextDisplayEnd(label));
@@ -8606,11 +8617,11 @@ void ImGui::EndGroup()
 }
 }
 
 
 // Gets back to previous line and continue with horizontal layout
 // Gets back to previous line and continue with horizontal layout
-//      column_x == 0   : follow on previous item
-//      columm_x != 0   : align to specified column
+//      pos_x == 0   : follow on previous item
+//      pos_x != 0   : align to specified column
 //      spacing_w < 0   : use default spacing if column_x==0, no spacing if column_x!=0
 //      spacing_w < 0   : use default spacing if column_x==0, no spacing if column_x!=0
 //      spacing_w >= 0  : enforce spacing
 //      spacing_w >= 0  : enforce spacing
-void ImGui::SameLine(int column_x, int spacing_w)
+void ImGui::SameLine(float pos_x, float spacing_w)
 {
 {
     ImGuiState& g = *GImGui;
     ImGuiState& g = *GImGui;
     ImGuiWindow* window = GetCurrentWindow();
     ImGuiWindow* window = GetCurrentWindow();
@@ -8618,16 +8629,16 @@ void ImGui::SameLine(int column_x, int spacing_w)
         return;
         return;
     
     
     float x, y;
     float x, y;
-    if (column_x != 0)
+    if (pos_x != 0.0f)
     {
     {
-        if (spacing_w < 0) spacing_w = 0;
-        x = window->Pos.x + (float)column_x + (float)spacing_w;
+        if (spacing_w < 0.0f) spacing_w = 0.0f;
+        x = window->Pos.x + pos_x + spacing_w;
         y = window->DC.CursorPosPrevLine.y;
         y = window->DC.CursorPosPrevLine.y;
     }
     }
     else
     else
     {
     {
-        if (spacing_w < 0) spacing_w = (int)g.Style.ItemSpacing.x;
-        x = window->DC.CursorPosPrevLine.x + (float)spacing_w;
+        if (spacing_w < 0.0f) spacing_w = g.Style.ItemSpacing.x;
+        x = window->DC.CursorPosPrevLine.x + spacing_w;
         y = window->DC.CursorPosPrevLine.y;
         y = window->DC.CursorPosPrevLine.y;
     }
     }
     window->DC.CurrentLineHeight = window->DC.PrevLineHeight;
     window->DC.CurrentLineHeight = window->DC.PrevLineHeight;
@@ -11368,7 +11379,7 @@ void ImGui::ShowTestWindow(bool* opened)
             }
             }
         }
         }
         ImGui::PlotLines("##Graph", &values.front(), (int)values.Size, values_offset, "avg 0.0", -1.0f, 1.0f, ImVec2(0,80));
         ImGui::PlotLines("##Graph", &values.front(), (int)values.Size, values_offset, "avg 0.0", -1.0f, 1.0f, ImVec2(0,80));
-        ImGui::SameLine(0, (int)ImGui::GetStyle().ItemInnerSpacing.x); 
+        ImGui::SameLine(0, ImGui::GetStyle().ItemInnerSpacing.x); 
         ImGui::BeginGroup();
         ImGui::BeginGroup();
         ImGui::Text("Graph");
         ImGui::Text("Graph");
         ImGui::Checkbox("pause", &pause);
         ImGui::Checkbox("pause", &pause);

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

@@ -170,7 +170,7 @@ namespace ImGui
     IMGUI_API void          BeginGroup();                                                       // once closing a group it is seen as a single item (so you can use IsItemHovered() on a group, SameLine() between groups, etc. 
     IMGUI_API void          BeginGroup();                                                       // once closing a group it is seen as a single item (so you can use IsItemHovered() on a group, SameLine() between groups, etc. 
     IMGUI_API void          EndGroup();
     IMGUI_API void          EndGroup();
     IMGUI_API void          Separator();                                                        // horizontal line
     IMGUI_API void          Separator();                                                        // horizontal line
-    IMGUI_API void          SameLine(int column_x = 0, int spacing_w = -1);                     // call between widgets or groups to layout them horizontally
+    IMGUI_API void          SameLine(float pos_x = 0.0f, float spacing_w = -1.0f);              // call between widgets or groups to layout them horizontally
     IMGUI_API void          Spacing();                                                          // add spacing
     IMGUI_API void          Spacing();                                                          // add spacing
     IMGUI_API void          Dummy(const ImVec2& size);                                          // add a dummy item of given size
     IMGUI_API void          Dummy(const ImVec2& size);                                          // add a dummy item of given size
     IMGUI_API void          Indent();                                                           // move content position toward the right by style.IndentSpacing pixels
     IMGUI_API void          Indent();                                                           // move content position toward the right by style.IndentSpacing pixels
@@ -461,6 +461,8 @@ enum ImGuiInputTextFlags_
     ImGuiInputTextFlags_CallbackCharFilter  = 1 << 9,   // Call user function to filter character. Modify data->EventChar to replace/filter input, or return 1 to discard character.
     ImGuiInputTextFlags_CallbackCharFilter  = 1 << 9,   // Call user function to filter character. Modify data->EventChar to replace/filter input, or return 1 to discard character.
     ImGuiInputTextFlags_AllowTabInput       = 1 << 10,  // Pressing TAB input a '\t' character into the text field
     ImGuiInputTextFlags_AllowTabInput       = 1 << 10,  // Pressing TAB input a '\t' character into the text field
     ImGuiInputTextFlags_CtrlEnterForNewLine = 1 << 11,  // In multi-line mode, allow exiting edition by pressing Enter. Ctrl+Enter to add new line (by default adds new lines with Enter).
     ImGuiInputTextFlags_CtrlEnterForNewLine = 1 << 11,  // In multi-line mode, allow exiting edition by pressing Enter. Ctrl+Enter to add new line (by default adds new lines with Enter).
+    ImGuiInputTextFlags_NoHorizontalScroll  = 1 << 12,  // Disable following the cursor horizontally
+    ImGuiInputTextFlags_AlwaysInsertMode    = 1 << 13,  // Insert mode
     // [Internal]
     // [Internal]
     ImGuiInputTextFlags_Multiline           = 1 << 20   // For internal use by InputTextMultiline()
     ImGuiInputTextFlags_Multiline           = 1 << 20   // For internal use by InputTextMultiline()
 };
 };
@@ -920,6 +922,7 @@ struct ImGuiTextEditCallbackData
     // NB: calling those function loses selection.
     // NB: calling those function loses selection.
     void DeleteChars(int pos, int bytes_count);
     void DeleteChars(int pos, int bytes_count);
     void InsertChars(int pos, const char* text, const char* text_end = NULL);
     void InsertChars(int pos, const char* text, const char* text_end = NULL);
+    bool HasSelection() const { return SelectionStart != SelectionEnd; }
 };
 };
 
 
 // ImColor() is just a helper that implicity converts to either ImU32 (packed 4x1 byte) or ImVec4 (4x1 float)
 // ImColor() is just a helper that implicity converts to either ImU32 (packed 4x1 byte) or ImVec4 (4x1 float)

+ 210 - 0
3rdparty/ocornut-imgui/memory_editor.h

@@ -0,0 +1,210 @@
+// Mini memory editor for ImGui (to embed in your game/tools)
+// v0.10
+//
+// You can adjust the keyboard repeat delay/rate in ImGuiIO.
+// The code assume a mono-space font for simplicity! If you don't use the default font, use ImGui::PushFont()/PopFont() to switch to a mono-space font before caling this.
+//
+// Usage:
+//   static MemoryEditor memory_editor;                                                     // save your state somewhere
+//   memory_editor.Draw("Memory Editor", mem_block, mem_block_size, (size_t)mem_block);     // run
+//
+// TODO: better resizing policy (ImGui doesn't have flexible window resizing constraints yet)
+
+struct MemoryEditor
+{
+    bool    Open;
+    bool    AllowEdits;
+    int     Rows;
+    int     DataEditingAddr;
+    bool    DataEditingTakeFocus;
+    char    DataInput[32];
+    char    AddrInput[32];
+
+    MemoryEditor()
+    {
+        Open = true;
+        Rows = 16;
+        DataEditingAddr = -1;
+        DataEditingTakeFocus = false;
+        strcpy(DataInput, "");
+        strcpy(AddrInput, "");
+        AllowEdits = true;
+    }
+
+    void Draw(const char* title, unsigned char* mem_data, int mem_size, size_t base_display_addr = 0)
+    {
+        if (ImGui::Begin(title, &Open))
+        {
+            ImGui::BeginChild("##scrolling", ImVec2(0, -ImGui::GetItemsLineHeightWithSpacing()));
+
+            ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0,0));
+            ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0,0));
+
+            int addr_digits_count = 0;
+            for (int n = base_display_addr + mem_size - 1; n > 0; n >>= 4)
+                addr_digits_count++;
+
+            float glyph_width = ImGui::CalcTextSize("F").x;
+            float cell_width = glyph_width * 3; // "FF " we include trailing space in the width to easily catch clicks everywhere
+
+            float line_height = ImGui::GetTextLineHeight();
+            int line_total_count = (int)((mem_size + Rows-1) / Rows);
+            ImGuiListClipper clipper(line_total_count, line_height);
+            int visible_start_addr = clipper.DisplayStart * Rows;
+            int visible_end_addr = clipper.DisplayEnd * Rows;
+
+            bool data_next = false;
+
+            if (!AllowEdits || DataEditingAddr >= mem_size)
+                DataEditingAddr = -1;
+
+            int data_editing_addr_backup = DataEditingAddr;
+            if (DataEditingAddr != -1)
+            {
+                if (ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_UpArrow)) && DataEditingAddr >= Rows)                   { DataEditingAddr -= Rows; DataEditingTakeFocus = true; }
+                else if (ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_DownArrow)) && DataEditingAddr < mem_size - Rows)  { DataEditingAddr += Rows; DataEditingTakeFocus = true; }
+                else if (ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_LeftArrow)) && DataEditingAddr > 0)                { DataEditingAddr -= 1; DataEditingTakeFocus = true; }
+                else if (ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_RightArrow)) && DataEditingAddr < mem_size - 1)    { DataEditingAddr += 1; DataEditingTakeFocus = true; }
+            }
+            if ((DataEditingAddr / Rows) != (data_editing_addr_backup / Rows))
+            {
+                // Track cursor movements
+                float scroll_offset = ((DataEditingAddr / Rows) - (data_editing_addr_backup / Rows)) * line_height;
+                bool scroll_desired = (scroll_offset < 0.0f && DataEditingAddr < visible_start_addr + Rows*2) || (scroll_offset > 0.0f && DataEditingAddr > visible_end_addr - Rows*2);
+                if (scroll_desired)
+                    ImGui::SetScrollY(ImGui::GetScrollY() + scroll_offset);
+            }
+
+            bool draw_separator = true;
+            for (int line_i = clipper.DisplayStart; line_i < clipper.DisplayEnd; line_i++) // display only visible items
+            {
+                int addr = line_i * Rows;
+                ImGui::Text("%0*X: ", addr_digits_count, base_display_addr+addr);
+                ImGui::SameLine();
+
+                // Draw Hexadecimal
+                float line_start_x = ImGui::GetCursorPosX();
+                for (int n = 0; n < Rows && addr < mem_size; n++, addr++)
+                {
+                    ImGui::SameLine(line_start_x + cell_width * n);
+
+                    if (DataEditingAddr == addr)
+                    {
+                        // Display text input on current byte
+                        ImGui::PushID(addr);
+                        struct FuncHolder
+                        {
+                            // FIXME: We should have a way to retrieve the text edit cursor position more easily in the API, this is rather tedious.
+                            static int Callback(ImGuiTextEditCallbackData* data)
+                            {
+                                int* p_cursor_pos = (int*)data->UserData;
+                                if (!data->HasSelection())
+                                    *p_cursor_pos = data->CursorPos;
+                                return 0;
+                            }
+                        };
+                        int cursor_pos = -1;
+                        bool data_write = false;
+                        if (DataEditingTakeFocus)
+                        {
+                            ImGui::SetKeyboardFocusHere();
+                            sprintf(AddrInput, "%0*X", addr_digits_count, base_display_addr+addr);
+                            sprintf(DataInput, "%02X", mem_data[addr]);
+                        }
+                        ImGui::PushItemWidth(ImGui::CalcTextSize("FF").x);
+                        ImGuiInputTextFlags flags = ImGuiInputTextFlags_CharsHexadecimal|ImGuiInputTextFlags_EnterReturnsTrue|ImGuiInputTextFlags_AutoSelectAll|ImGuiInputTextFlags_NoHorizontalScroll|ImGuiInputTextFlags_AlwaysInsertMode|ImGuiInputTextFlags_CallbackAlways;
+                        if (ImGui::InputText("##data", DataInput, 32, flags, FuncHolder::Callback, &cursor_pos))
+                            data_write = data_next = true;
+                        else if (!DataEditingTakeFocus && !ImGui::IsItemActive())
+                            DataEditingAddr = -1;
+                        DataEditingTakeFocus = false;
+                        ImGui::PopItemWidth();
+                        if (cursor_pos >= 2)
+                            data_write = data_next = true;
+                        if (data_write)
+                        {
+                            int data;
+                            if (sscanf(DataInput, "%X", &data) == 1)
+                                mem_data[addr] = (unsigned char)data;
+                        }
+                        ImGui::PopID();
+                    }
+                    else
+                    {
+                        ImGui::Text("%02X ", mem_data[addr]);
+                        if (AllowEdits && ImGui::IsItemHovered() && ImGui::IsMouseClicked(0))
+                        {
+                            DataEditingTakeFocus = true;
+                            DataEditingAddr = addr;
+                        }
+                    }
+                }
+
+                ImGui::SameLine(line_start_x + cell_width * Rows + glyph_width * 2);
+
+                if (draw_separator)
+                {
+                    ImVec2 screen_pos = ImGui::GetCursorScreenPos();
+                    ImGui::GetWindowDrawList()->AddLine(ImVec2(screen_pos.x - glyph_width, screen_pos.y - 9999), ImVec2(screen_pos.x - glyph_width, screen_pos.y + 9999), ImColor(ImGui::GetStyle().Colors[ImGuiCol_Border]));
+                    draw_separator = false;
+                }
+
+                // Draw ASCII values
+                addr = line_i * Rows;
+                for (int n = 0; n < Rows && addr < mem_size; n++, addr++)
+                {
+                    if (n > 0) ImGui::SameLine();
+                    int c = mem_data[addr];
+                    ImGui::Text("%c", (c >= 32 && c < 128) ? c : '.');
+                }
+            }
+            clipper.End();
+            ImGui::PopStyleVar(2);
+            
+            ImGui::EndChild();
+
+            if (data_next && DataEditingAddr < mem_size)
+            {
+                DataEditingAddr = DataEditingAddr + 1;
+                DataEditingTakeFocus = true;
+            }
+
+            ImGui::Separator();
+
+            ImGui::AlignFirstTextHeightToWidgets();
+            ImGui::PushItemWidth(50);
+            ImGui::PushAllowKeyboardFocus(false);
+            int rows_backup = Rows;
+            if (ImGui::DragInt("##rows", &Rows, 0.2f, 4, 32, "%.0f rows"))
+            {
+                ImVec2 new_window_size = ImGui::GetWindowSize();
+                new_window_size.x += (Rows - rows_backup) * (cell_width + glyph_width);
+                ImGui::SetWindowSize(new_window_size);
+            }
+            ImGui::PopAllowKeyboardFocus();
+            ImGui::PopItemWidth();
+            ImGui::SameLine();
+            ImGui::Text("Range %0*X..%0*X", addr_digits_count, (int)base_display_addr, addr_digits_count, (int)base_display_addr+mem_size-1);
+            ImGui::SameLine();
+            ImGui::PushItemWidth(70);
+            if (ImGui::InputText("##addr", AddrInput, 32, ImGuiInputTextFlags_CharsHexadecimal | ImGuiInputTextFlags_EnterReturnsTrue))
+            {
+                int goto_addr;
+                if (sscanf(AddrInput, "%X", &goto_addr) == 1)
+                {
+                    goto_addr -= base_display_addr;
+                    if (goto_addr >= 0 && goto_addr < mem_size)
+                    {
+                        ImGui::BeginChild("##scrolling");
+                        ImGui::SetScrollFromPosY(ImGui::GetCursorStartPos().y + (goto_addr / Rows) * ImGui::GetTextLineHeight());
+                        ImGui::EndChild();
+                        DataEditingAddr = goto_addr;
+                        DataEditingTakeFocus = true;
+                    }
+                }
+            }
+            ImGui::PopItemWidth();
+        }
+        ImGui::End();
+    }
+};