Explorar el Código

Added mouse cursor types handling + embed mouse cursor data #155

ocornut hace 10 años
padre
commit
810fcd8bcb
Se han modificado 2 ficheros con 273 adiciones y 55 borrados
  1. 256 53
      imgui.cpp
  2. 17 2
      imgui.h

+ 256 - 53
imgui.cpp

@@ -484,17 +484,6 @@ static const char*  GetClipboardTextFn_DefaultImpl();
 static void         SetClipboardTextFn_DefaultImpl(const char* text);
 static void         ImeSetInputScreenPosFn_DefaultImpl(int x, int y);
 
-//-----------------------------------------------------------------------------
-// Texture Atlas data
-//-----------------------------------------------------------------------------
-
-// Technically we should use the rect pack API for that, but it's just simpler to hard-core the positions for now.
-// As we start using more of the texture atlas (for rounded corners) we can change that.
-static const ImVec2 TEX_ATLAS_SIZE(32, 32);
-static const ImVec2 TEX_ATLAS_POS_MOUSE_CURSOR_BLACK(1, 3);
-static const ImVec2 TEX_ATLAS_POS_MOUSE_CURSOR_WHITE(14, 3);
-static const ImVec2 TEX_ATLAS_SIZE_MOUSE_CURSOR(12, 19);
-
 //-----------------------------------------------------------------------------
 // User facing structures
 //-----------------------------------------------------------------------------
@@ -1038,6 +1027,15 @@ struct ImGuiIniData
     ~ImGuiIniData() { if (Name) { ImGui::MemFree(Name); Name = NULL; } }
 };
 
+struct ImGuiMouseCursorData
+{
+    ImGuiMouseCursor    Type;
+    ImVec2              Offset;
+    ImVec2              Size;
+    ImVec2              TexUvMin[2];
+    ImVec2              TexUvMax[2];
+};
+
 // Main state for ImGui
 struct ImGuiState
 {
@@ -1082,7 +1080,11 @@ struct ImGuiState
     // Render
     ImVector<ImDrawList*>   RenderDrawLists;
     ImVector<ImGuiWindow*>  RenderSortedWindows;
-    ImDrawList              CursorDrawList;
+
+    // Mouse cursor
+    ImGuiMouseCursor        MouseCursor;
+    ImDrawList              MouseCursorDrawList;                // Optional software render of mouse cursors, if io.MouseDrawCursor is set
+    ImGuiMouseCursorData    MouseCursorData[ImGuiMouseCursor_Count_];
 
     // Widget state
     ImGuiTextEditState      InputTextState;
@@ -1901,6 +1903,7 @@ void ImGui::NewFrame()
     bool mouse_owned_by_application = mouse_earliest_button_down != -1 && !g.IO.MouseDownOwned[mouse_earliest_button_down];
     g.IO.WantCaptureMouse = (!mouse_owned_by_application && g.HoveredWindow != NULL) || (g.ActiveId != 0);
     g.IO.WantCaptureKeyboard = (g.ActiveId != 0);
+    g.MouseCursor = ImGuiMouseCursor_Arrow;
 
     // If mouse was first clicked outside of ImGui bounds we also cancel out hovering.
     if (mouse_owned_by_application)
@@ -1990,7 +1993,7 @@ void ImGui::Shutdown()
     g.FontStack.clear();
     g.RenderDrawLists.clear();
     g.RenderSortedWindows.clear();
-    g.CursorDrawList.ClearFreeMemory();
+    g.MouseCursorDrawList.ClearFreeMemory();
     g.ColorEditModeStorage.Clear();
     if (g.PrivateClipboard)
     {
@@ -2140,18 +2143,18 @@ void ImGui::Render()
 
         if (g.IO.MouseDrawCursor)
         {
-            const ImVec2 pos = g.IO.MousePos;
-            const ImVec2 size = TEX_ATLAS_SIZE_MOUSE_CURSOR;
+            const ImGuiMouseCursorData& cursor_data = g.MouseCursorData[g.MouseCursor];
+            const ImVec2 pos = g.IO.MousePos - cursor_data.Offset;
+            const ImVec2 size = cursor_data.Size;
             const ImTextureID tex_id = g.IO.Fonts->TexID;
-            const ImVec2 tex_uv_scale(1.0f/g.IO.Fonts->TexWidth, 1.0f/g.IO.Fonts->TexHeight);
-            g.CursorDrawList.Clear();
-            g.CursorDrawList.PushTextureID(tex_id);
-            g.CursorDrawList.AddImage(tex_id, pos+ImVec2(1,0), pos+ImVec2(1,0) + size, TEX_ATLAS_POS_MOUSE_CURSOR_BLACK * tex_uv_scale, (TEX_ATLAS_POS_MOUSE_CURSOR_BLACK + size) * tex_uv_scale, 0x30000000); // Shadow
-            g.CursorDrawList.AddImage(tex_id, pos+ImVec2(2,0), pos+ImVec2(2,0) + size, TEX_ATLAS_POS_MOUSE_CURSOR_BLACK * tex_uv_scale, (TEX_ATLAS_POS_MOUSE_CURSOR_BLACK + size) * tex_uv_scale, 0x30000000); // Shadow
-            g.CursorDrawList.AddImage(tex_id, pos,             pos + size,             TEX_ATLAS_POS_MOUSE_CURSOR_BLACK * tex_uv_scale, (TEX_ATLAS_POS_MOUSE_CURSOR_BLACK + size) * tex_uv_scale, 0xFF000000); // Black border
-            g.CursorDrawList.AddImage(tex_id, pos,             pos + size,             TEX_ATLAS_POS_MOUSE_CURSOR_WHITE * tex_uv_scale, (TEX_ATLAS_POS_MOUSE_CURSOR_WHITE + size) * tex_uv_scale, 0xFFFFFFFF); // White fill
-            g.CursorDrawList.PopTextureID();
-            AddDrawListToRenderList(&g.CursorDrawList);
+            g.MouseCursorDrawList.Clear();
+            g.MouseCursorDrawList.PushTextureID(tex_id);
+            g.MouseCursorDrawList.AddImage(tex_id, pos+ImVec2(1,0), pos+ImVec2(1,0) + size, cursor_data.TexUvMin[0], cursor_data.TexUvMax[0], 0x30000000); // Shadow
+            g.MouseCursorDrawList.AddImage(tex_id, pos+ImVec2(2,0), pos+ImVec2(2,0) + size, cursor_data.TexUvMin[0], cursor_data.TexUvMax[0], 0x30000000); // Shadow
+            g.MouseCursorDrawList.AddImage(tex_id, pos,             pos + size,             cursor_data.TexUvMin[0], cursor_data.TexUvMax[0], 0xFF000000); // Black border
+            g.MouseCursorDrawList.AddImage(tex_id, pos,             pos + size,             cursor_data.TexUvMin[1], cursor_data.TexUvMax[1], 0xFFFFFFFF); // White fill
+            g.MouseCursorDrawList.PopTextureID();
+            AddDrawListToRenderList(&g.MouseCursorDrawList);
         }
 
         // Render
@@ -2580,6 +2583,16 @@ ImVec2 ImGui::GetMouseDragDelta(int button, float lock_threshold)
     return ImVec2(0.0f, 0.0f);
 }
 
+ImGuiMouseCursor ImGui::GetMouseCursor()
+{
+    return GImGui->MouseCursor;
+}
+
+void ImGui::SetMouseCursor(ImGuiMouseCursor cursor_type)
+{
+    GImGui->MouseCursor = cursor_type;
+}
+
 bool ImGui::IsItemHovered()
 {
     ImGuiWindow* window = GetCurrentWindow();
@@ -3065,12 +3078,15 @@ bool ImGui::Begin(const char* name, bool* p_opened, const ImVec2& size, float bg
                 else if (!(window->Flags & ImGuiWindowFlags_NoResize))
                 {
                     // Manual resize grip
-                    const ImRect resize_rect(window->Rect().GetBR()-ImVec2(18,18), window->Rect().GetBR());
+                    const ImRect resize_rect(window->Rect().GetBR()-ImVec2(14,14), window->Rect().GetBR());
                     const ImGuiID resize_id = window->GetID("#RESIZE");
                     bool hovered, held;
                     ButtonBehavior(resize_rect, resize_id, &hovered, &held, true);
                     resize_col = window->Color(held ? ImGuiCol_ResizeGripActive : hovered ? ImGuiCol_ResizeGripHovered : ImGuiCol_ResizeGrip);
 
+                    if (hovered || held)
+                        g.MouseCursor = ImGuiMouseCursor_ResizeNWSE;
+
                     if (g.HoveredWindow == window && held && g.IO.MouseDoubleClicked[0])
                     {
                         // Manual auto-fit when double-clicking
@@ -5858,7 +5874,10 @@ bool ImGui::InputText(const char* label, char* buf, size_t buf_size, ImGuiInputT
 
     const bool hovered = IsHovered(frame_bb, id);
     if (hovered)
+    {
         g.HoveredId = id;
+        g.MouseCursor = ImGuiMouseCursor_TextInput;
+    }
     const bool user_clicked = hovered && io.MouseClicked[0];
 
     bool select_all = (g.ActiveId != id) && (flags & ImGuiInputTextFlags_AutoSelectAll) != 0;
@@ -5948,7 +5967,7 @@ bool ImGui::InputText(const char* label, char* buf, size_t buf_size, ImGuiInputT
             edit_state.CursorAnimReset();
         }
         if (edit_state.SelectedAllMouseLock && !io.MouseDown[0])
-             edit_state.SelectedAllMouseLock = false;
+            edit_state.SelectedAllMouseLock = false;
 
         if (g.IO.InputCharacters[0])
         {
@@ -7644,7 +7663,7 @@ ImFontAtlas::ImFontAtlas()
     TexPixelsAlpha8 = NULL;
     TexPixelsRGBA32 = NULL;
     TexWidth = TexHeight = 0;
-    TexExtraDataPos = TexUvWhitePixel = ImVec2(0, 0);
+    TexUvWhitePixel = ImVec2(0, 0);
 }
 
 ImFontAtlas::~ImFontAtlas()
@@ -7802,7 +7821,7 @@ bool    ImFontAtlas::Build()
 
     TexID = NULL;
     TexWidth = TexHeight = 0;
-    TexExtraDataPos = TexUvWhitePixel = ImVec2(0, 0);
+    TexUvWhitePixel = ImVec2(0, 0);
     ClearTexData();
 
     // Initialize font information early (so we can error without any cleanup) + count glyphs
@@ -7835,12 +7854,14 @@ bool    ImFontAtlas::Build()
     IM_ASSERT(ret);
     stbtt_PackSetOversampling(&spc, 1, 1);
 
-    // Pack our extra data rectangle first, so it will be on the upper-left corner of our texture (UV will have small values).
-    stbrp_rect extra_rect;
-    extra_rect.w = (stbrp_coord)TEX_ATLAS_SIZE.x;
-    extra_rect.h = (stbrp_coord)TEX_ATLAS_SIZE.y;
-    stbrp_pack_rects((stbrp_context*)spc.pack_info, &extra_rect, 1);
-    TexExtraDataPos = ImVec2(extra_rect.x, extra_rect.y);
+    // Pack our extra data rectangles first, so it will be on the upper-left corner of our texture (UV will have small values).
+    ImVector<stbrp_rect> extra_rects;
+    RenderCustomTexData(0, &extra_rects);
+    stbrp_pack_rects((stbrp_context*)spc.pack_info, &extra_rects[0], (int)extra_rects.size());
+    int tex_height = 0;
+    for (size_t i = 0; i < extra_rects.size(); i++)
+        if (extra_rects[i].was_packed)
+            tex_height = ImMax(tex_height, extra_rects[i].y + extra_rects[i].h);
 
     // Allocate packing character data and flag packed characters buffer as non-packed (x0=y0=x1=y1=0)
     int buf_packedchars_n = 0, buf_rects_n = 0, buf_ranges_n = 0;
@@ -7848,11 +7869,10 @@ bool    ImFontAtlas::Build()
     stbrp_rect* buf_rects = (stbrp_rect*)ImGui::MemAlloc(total_glyph_count * sizeof(stbrp_rect));
     stbtt_pack_range* buf_ranges = (stbtt_pack_range*)ImGui::MemAlloc(total_glyph_range_count * sizeof(stbtt_pack_range));
     memset(buf_packedchars, 0, total_glyph_count * sizeof(stbtt_packedchar));
-    memset(buf_rects, 0, total_glyph_count * sizeof(stbrp_rect));              // Unnessary but let's clear this for the sake of sanity.
+    memset(buf_rects, 0, total_glyph_count * sizeof(stbrp_rect));              // Unnecessary but let's clear this for the sake of sanity.
     memset(buf_ranges, 0, total_glyph_range_count * sizeof(stbtt_pack_range));
 
-    // First pass: pack all glyphs (no rendering at this point, we are working with glyph sizes only)
-    int tex_height = extra_rect.y + extra_rect.h;
+    // First font pass: pack all glyphs (no rendering at this point, we are working with glyph sizes only)
     for (size_t input_i = 0; input_i < InputData.size(); input_i++)
     {
         ImFontAtlasData& data = *InputData[input_i];
@@ -7964,22 +7984,67 @@ bool    ImFontAtlas::Build()
     ClearInputData();
 
     // Render into our custom data block
-    RenderCustomTexData();
+    RenderCustomTexData(1, &extra_rects);
 
     return true;
 }
 
-void ImFontAtlas::RenderCustomTexData()
+static void AddMouseCursor(int pass, ImVector<stbrp_rect>& rects, int& rect_i, ImGuiMouseCursor type, const ImVec2& offset, const ImVec2& size, const char* in_char_pixels, unsigned char* tex_pixels, const ImVec2& tex_uv_scale, int tex_pitch)
+{
+    if (pass == 0)
+    {
+        stbrp_rect r; 
+        r.w = (unsigned short)((size.x*2)+1);
+        r.h = (unsigned short)(size.y);
+        rects.push_back(r);
+    }
+    else if (pass == 1)
+    {
+        ImGuiMouseCursorData& cursor_data = GImGui->MouseCursorData[type];
+        cursor_data.Type = type;
+        cursor_data.Size = size;
+        cursor_data.Offset = offset;
+        const stbrp_rect& r = rects[rect_i++];
+        ImVec2 pos((float)r.x, (float)r.y);
+        for (int layer = 0; layer < 2; layer++)
+        {
+            // Draw a mouse cursor into texture
+            // Because our font uses a single color channel, we have to spread the cursor in 2 layers (black/white) which will be rendered separately.
+            const char layer_char = layer ? '.' : 'X';
+            cursor_data.TexUvMin[layer] = (pos) * tex_uv_scale;
+            cursor_data.TexUvMax[layer] = (pos + size) * tex_uv_scale;
+            for (int y = 0, n = 0; y < (int)size.y; y++)
+                for (int x = 0; x < (int)size.x; x++, n++)
+                    tex_pixels[((int)pos.x + x) + ((int)pos.y + y) * tex_pitch] = (in_char_pixels[n] == layer_char) ? 0xFF : 0x00;
+            pos.x += size.x + 1;
+        }
+    }
+}
+
+void ImFontAtlas::RenderCustomTexData(int pass, void* rects_opaque)
 {
-    IM_ASSERT(TexExtraDataPos.x == 0.0f && TexExtraDataPos.y == 0.0f);
+    ImVector<stbrp_rect>& rects = *(ImVector<stbrp_rect>*)rects_opaque;
+    int rect_i = 0;
 
     // Draw white pixel into texture and make UV points to it
-    TexPixelsAlpha8[0] = TexPixelsAlpha8[1] = TexPixelsAlpha8[TexWidth+0] = TexPixelsAlpha8[TexWidth+1] = 0xFF;
-    TexUvWhitePixel = ImVec2((TexExtraDataPos.x + 0.5f) / TexWidth, (TexExtraDataPos.y + 0.5f) / TexHeight);
+    const ImVec2 uv_scale(1.0f / TexWidth, 1.0f / TexHeight);
+    if (pass == 0)
+    {
+        // Measure
+        stbrp_rect r; 
+        r.w = r.h = 3;
+        rects.push_back(r);
+    }
+    else if (pass == 1)
+    {
+        // Render
+        const stbrp_rect& r = rects[rect_i++];
+        const int offset = (int)r.x + (int)r.y * TexWidth;
+        TexPixelsAlpha8[offset] = TexPixelsAlpha8[offset+1] = TexPixelsAlpha8[TexWidth] = TexPixelsAlpha8[TexWidth+1] = 0xFF;
+        TexUvWhitePixel = ImVec2(r.x + 0.5f, r.y + 0.5f) * uv_scale;
+    }
 
-    // Draw a mouse cursor into texture
-    // Because our font uses a single color channel, we have to spread the cursor in 2 layers (black/white) which will be rendered separately.
-    const char cursor_pixels[] =
+    const char cursor_arrow[12*19+1] =
     {
         "X           "
         "XX          "
@@ -8001,13 +8066,136 @@ void ImFontAtlas::RenderCustomTexData()
         "      X..X  "
         "       XX   "
     };
-    IM_ASSERT(sizeof(cursor_pixels)-1 == (int)TEX_ATLAS_SIZE_MOUSE_CURSOR.x * (int)TEX_ATLAS_SIZE_MOUSE_CURSOR.y);
-    for (int y = 0, n = 0; y < 19; y++)
-        for (int x = 0; x < 12; x++, n++)
-        {
-            TexPixelsAlpha8[((int)TEX_ATLAS_POS_MOUSE_CURSOR_BLACK.x + x) + ((int)TEX_ATLAS_POS_MOUSE_CURSOR_BLACK.y + y) * TexWidth] = (cursor_pixels[n] == 'X') ? 0xFF : 0x00;
-            TexPixelsAlpha8[((int)TEX_ATLAS_POS_MOUSE_CURSOR_WHITE.x + x) + ((int)TEX_ATLAS_POS_MOUSE_CURSOR_WHITE.y + y) * TexWidth] = (cursor_pixels[n] == '.') ? 0xFF : 0x00;
-        }
+    const char cursor_text_input[7*16+1] =
+    {
+        "XXXXXXX"
+        "X.....X"
+        "XXX.XXX"
+        "  X.X  "
+        "  X.X  "
+        "  X.X  "
+        "  X.X  "
+        "  X.X  "
+        "  X.X  "
+        "  X.X  "
+        "  X.X  "
+        "  X.X  "
+        "  X.X  "
+        "XXX.XXX"
+        "X.....X"
+        "XXXXXXX"
+    };
+    const char cursor_move[23*23+1] =
+    {
+        "           X           "
+        "          X.X          "
+        "         X...X         "
+        "        X.....X        "
+        "       X.......X       "
+        "       XXXX.XXXX       "
+        "          X.X          "
+        "    XX    X.X    XX    "
+        "   X.X    X.X    X.X   "
+        "  X..X    X.X    X..X  "
+        " X...XXXXXX.XXXXXX...X "
+        "X.....................X"
+        " X...XXXXXX.XXXXXX...X "
+        "  X..X    X.X    X..X  "
+        "   X.X    X.X    X.X   "
+        "    XX    X.X    XX    "
+        "          X.X          "
+        "       XXXX.XXXX       "
+        "       X.......X       "
+        "        X.....X        "
+        "         X...X         "
+        "          X.X          "
+        "           X           "
+    };
+    const char cursor_resize_ns[9*23+1] =
+    {
+        "    X    "
+        "   X.X   "
+        "  X...X  "
+        " X.....X "
+        "X.......X"
+        "XXXX.XXXX"
+        "   X.X   "
+        "   X.X   "
+        "   X.X   "
+        "   X.X   "
+        "   X.X   "
+        "   X.X   "
+        "   X.X   "
+        "   X.X   "
+        "   X.X   "
+        "   X.X   "
+        "   X.X   "
+        "XXXX.XXXX"
+        "X.......X"
+        " X.....X "
+        "  X...X  "
+        "   X.X   "
+        "    X    "
+    };
+    const char cursor_resize_ew[23*9+1] =
+    {
+        "    XX           XX    "
+        "   X.X           X.X   "
+        "  X..X           X..X  "
+        " X...XXXXXXXXXXXXX...X "
+        "X.....................X"
+        " X...XXXXXXXXXXXXX...X "
+        "  X..X           X..X  "
+        "   X.X           X.X   "
+        "    XX           XX    "
+    };
+    const char cursor_resize_nwse[17*17+1] =
+    {
+        "XXXXXXX          "
+        "X.....X          "
+        "X....X           "
+        "X...X            "
+        "X..X.X           "
+        "X.X X.X          "
+        "XX   X.X         "
+        "      X.X        "
+        "       X.X       "
+        "        X.X      "
+        "         X.X   XX"
+        "          X.X X.X"
+        "           X.X..X"
+        "            X...X"
+        "           X....X"
+        "          X.....X"
+        "          XXXXXXX"
+    };
+    const char cursor_resize_nesw[17*17+1] =
+    {
+        "          XXXXXXX"
+        "          X.....X"
+        "           X....X"
+        "            X...X"
+        "           X.X..X"
+        "          X.X X.X"
+        "         X.X   XX"
+        "        X.X      "
+        "       X.X       "
+        "      X.X        "
+        "XX   X.X         "
+        "X.X X.X          "
+        "X..X.X           "
+        "X...X            "
+        "X....X           "
+        "X.....X          "
+        "XXXXXXX          "
+    };
+    AddMouseCursor(pass, rects, rect_i, ImGuiMouseCursor_Arrow,     ImVec2(0,0),    ImVec2(12,19),  cursor_arrow,       TexPixelsAlpha8, uv_scale, TexWidth);
+    AddMouseCursor(pass, rects, rect_i, ImGuiMouseCursor_TextInput, ImVec2(4,9),    ImVec2(7,16),   cursor_text_input,  TexPixelsAlpha8, uv_scale, TexWidth);
+    AddMouseCursor(pass, rects, rect_i, ImGuiMouseCursor_Move,      ImVec2(11,11),  ImVec2(23,23),  cursor_move,        TexPixelsAlpha8, uv_scale, TexWidth);
+    AddMouseCursor(pass, rects, rect_i, ImGuiMouseCursor_ResizeNS,  ImVec2(5,11),   ImVec2(9,23),   cursor_resize_ns,   TexPixelsAlpha8, uv_scale, TexWidth);
+    AddMouseCursor(pass, rects, rect_i, ImGuiMouseCursor_ResizeEW,  ImVec2(11,5),   ImVec2(23,9),   cursor_resize_ew,   TexPixelsAlpha8, uv_scale, TexWidth);
+    AddMouseCursor(pass, rects, rect_i, ImGuiMouseCursor_ResizeNESW,ImVec2(9,9),    ImVec2(17,17),  cursor_resize_nesw, TexPixelsAlpha8, uv_scale, TexWidth);
+    AddMouseCursor(pass, rects, rect_i, ImGuiMouseCursor_ResizeNWSE,ImVec2(9,9),    ImVec2(17,17),  cursor_resize_nwse, TexPixelsAlpha8, uv_scale, TexWidth);
 }
 
 //-----------------------------------------------------------------------------
@@ -9862,7 +10050,7 @@ void ImGui::ShowTestWindow(bool* opened)
                 ImGui::BulletText("%s", lines[i]);
     }
 
-    if (ImGui::CollapsingHeader("Keyboard & Focus"))
+    if (ImGui::CollapsingHeader("Keyboard, Mouse & Focus"))
     {
         if (ImGui::TreeNode("Tabbing"))
         {
@@ -9907,6 +10095,21 @@ void ImGui::ShowTestWindow(bool* opened)
             ImGui::TextWrapped("Cursor & selection are preserved when refocusing last used item in code.");
             ImGui::TreePop();
         }
+
+        if (ImGui::TreeNode("Mouse cursors"))
+        {
+            ImGui::TextWrapped("(Your application can render a different mouse cursor based on what ImGui::GetMouseCursor() returns. You can also set io.MouseDrawCursor to ask ImGui to render the cursor for you in software)");
+            ImGui::Checkbox("io.MouseDrawCursor", &ImGui::GetIO().MouseDrawCursor);
+            ImGui::Text("Hover to see mouse cursors:");
+            for (int i = 0; i < ImGuiMouseCursor_Count_; i++)
+            {
+                char label[32];
+                sprintf(label, "Mouse cursor %d", i);
+                ImGui::Bullet(); ImGui::Selectable(label, false); 
+                if (ImGui::IsItemHovered()) 
+                    ImGui::SetMouseCursor(i);
+            }
+        }
     }
 
     if (ImGui::CollapsingHeader("App Examples"))

+ 17 - 2
imgui.h

@@ -43,6 +43,7 @@ typedef int ImGuiCol;               // enum ImGuiCol_
 typedef int ImGuiStyleVar;          // enum ImGuiStyleVar_
 typedef int ImGuiKey;               // enum ImGuiKey_
 typedef int ImGuiColorEditMode;     // enum ImGuiColorEditMode_
+typedef int ImGuiMouseCursor;       // enum ImGuiMouseCursor_
 typedef int ImGuiWindowFlags;       // enum ImGuiWindowFlags_
 typedef int ImGuiSetCond;           // enum ImGuiSetCondition_
 typedef int ImGuiInputTextFlags;    // enum ImGuiInputTextFlags_
@@ -372,6 +373,8 @@ namespace ImGui
     IMGUI_API bool          IsPosHoveringAnyWindow(const ImVec2& pos);                          // is given position hovering any active imgui window
     IMGUI_API ImVec2        GetMousePos();                                                      // shortcut to ImGui::GetIO().MousePos provided by user, to be consistent with other calls
     IMGUI_API ImVec2        GetMouseDragDelta(int button = 0, float lock_threshold = -1.0f);    // dragging amount, also see: GetItemActiveDragDelta(). if lock_threshold < -1.0f uses io.MouseDraggingThreshold.
+    IMGUI_API ImGuiMouseCursor GetMouseCursor();                                                // get desired cursor type, reset in ImGui::NewFrame(), this updated during the frame. valid before Render(). If you use software rendering by setting io.MouseDrawCursor ImGui will render those for you.
+    IMGUI_API void          SetMouseCursor(ImGuiMouseCursor type);                              // set desired cursor type
     IMGUI_API float         GetTime();
     IMGUI_API int           GetFrameCount();
     IMGUI_API const char*   GetStyleColName(ImGuiCol idx);
@@ -533,6 +536,19 @@ enum ImGuiColorEditMode_
     ImGuiColorEditMode_HEX = 2
 };
 
+// Enumeration for io.MouseCursor
+enum ImGuiMouseCursor_
+{
+    ImGuiMouseCursor_Arrow = 0,
+    ImGuiMouseCursor_TextInput,
+    ImGuiMouseCursor_Move,                  // Unused by ImGui
+    ImGuiMouseCursor_ResizeNS,              // Unused by ImGui
+    ImGuiMouseCursor_ResizeEW,              // Unused by ImGui
+    ImGuiMouseCursor_ResizeNESW,            // Unused by ImGui
+    ImGuiMouseCursor_ResizeNWSE,
+    ImGuiMouseCursor_Count_
+};
+
 // Condition flags for ImGui::SetWindow***(), SetNextWindow***(), SetNextTreeNode***() functions
 // All those functions treat 0 as a shortcut to ImGuiSetCond_Always
 enum ImGuiSetCond_
@@ -936,7 +952,6 @@ struct ImFontAtlas
     unsigned int*               TexPixelsRGBA32;    // 4 component per pixel, each component is unsigned 8-bit. Total size = TexWidth * TexHeight * 4
     int                         TexWidth;
     int                         TexHeight;
-    ImVec2                      TexExtraDataPos;    // Position of our rectangle where we draw non-font graphics
     ImVec2                      TexUvWhitePixel;    // Texture coordinates to a white pixel (part of the TexExtraData block)
     ImVector<ImFont*>           Fonts;
 
@@ -945,7 +960,7 @@ struct ImFontAtlas
     ImVector<ImFontAtlasData*>  InputData;          // Internal data
     IMGUI_API bool              Build();            // Build pixels data. This is automatically for you by the GetTexData*** functions.
     IMGUI_API void              ClearInputData();   // Clear the input TTF data.
-    IMGUI_API void              RenderCustomTexData();
+    IMGUI_API void              RenderCustomTexData(int pass, void* rects);
 };
 
 // TTF font loading and rendering