ImDrawList: Small refactor toward removing dependency on GImGui + PushClipRectFullscreen now correctly uses data provided by imgui which can takes account of DisplaySize + Removed static variable in PathArcToFast() which caused linking issues to some.

This commit is contained in:
omar 2017-12-21 18:50:27 +01:00
parent 230f826ef5
commit 531c11d5c7
4 changed files with 71 additions and 43 deletions

View File

@ -1818,7 +1818,7 @@ bool ImGuiListClipper::Step()
// ImGuiWindow
//-----------------------------------------------------------------------------
ImGuiWindow::ImGuiWindow(const char* name)
ImGuiWindow::ImGuiWindow(ImGuiContext* context, const char* name)
{
Name = ImStrdup(name);
ID = ImHash(name, 0);
@ -1859,7 +1859,7 @@ ImGuiWindow::ImGuiWindow(const char* name)
FontWindowScale = 1.0f;
DrawList = (ImDrawList*)ImGui::MemAlloc(sizeof(ImDrawList));
IM_PLACEMENT_NEW(DrawList) ImDrawList();
IM_PLACEMENT_NEW(DrawList) ImDrawList(&context->DrawListSharedData);
DrawList->_OwnerName = Name;
ParentWindow = NULL;
RootWindow = NULL;
@ -2254,6 +2254,11 @@ ImDrawList* ImGui::GetOverlayDrawList()
return &GImGui->OverlayDrawList;
}
ImDrawListSharedData* ImGui::GetDrawListSharedData()
{
return &GImGui->DrawListSharedData;
}
void ImGui::NewFrame()
{
ImGuiContext& g = *GImGui;
@ -2274,6 +2279,8 @@ void ImGui::NewFrame()
SetCurrentFont(GetDefaultFont());
IM_ASSERT(g.Font->IsLoaded());
g.DrawListSharedData.ClipRectFullscreen = ImVec4(0.0f, 0.0f, g.IO.DisplaySize.x, g.IO.DisplaySize.y);
g.DrawListSharedData.CurveTessellationTol = g.Style.CurveTessellationTol;
g.Time += g.IO.DeltaTime;
g.FrameCount += 1;
@ -4145,7 +4152,7 @@ static ImGuiWindow* CreateNewWindow(const char* name, ImVec2 size, ImGuiWindowFl
// Create window the first time
ImGuiWindow* window = (ImGuiWindow*)ImGui::MemAlloc(sizeof(ImGuiWindow));
IM_PLACEMENT_NEW(window) ImGuiWindow(name);
IM_PLACEMENT_NEW(window) ImGuiWindow(&g, name);
window->Flags = flags;
g.WindowsById.SetVoidPtr(window->ID, window);
@ -5243,7 +5250,11 @@ static void SetCurrentFont(ImFont* font)
g.Font = font;
g.FontBaseSize = g.IO.FontGlobalScale * g.Font->FontSize * g.Font->Scale;
g.FontSize = g.CurrentWindow ? g.CurrentWindow->CalcFontSize() : 0.0f;
g.FontTexUvWhitePixel = g.Font->ContainerAtlas->TexUvWhitePixel;
ImFontAtlas* atlas = g.Font->ContainerAtlas;
g.DrawListSharedData.TexUvWhitePixel = atlas->TexUvWhitePixel;
g.DrawListSharedData.Font = g.Font;
g.DrawListSharedData.FontSize = g.FontSize;
}
void ImGui::PushFont(ImFont* font)
@ -5820,7 +5831,7 @@ float ImGui::GetFontSize()
ImVec2 ImGui::GetFontTexUvWhitePixel()
{
return GImGui->FontTexUvWhitePixel;
return GImGui->DrawListSharedData.TexUvWhitePixel;
}
void ImGui::SetWindowFontScale(float scale)
@ -10489,7 +10500,7 @@ bool ImGui::ColorPicker4(const char* label, float col[4], ImGuiColorEditFlags fl
ImVec2 tra = wheel_center + ImRotate(triangle_pa, cos_hue_angle, sin_hue_angle);
ImVec2 trb = wheel_center + ImRotate(triangle_pb, cos_hue_angle, sin_hue_angle);
ImVec2 trc = wheel_center + ImRotate(triangle_pc, cos_hue_angle, sin_hue_angle);
ImVec2 uv_white = g.FontTexUvWhitePixel;
ImVec2 uv_white = GetFontTexUvWhitePixel();
draw_list->PrimReserve(6, 6);
draw_list->PrimVtx(tra, uv_white, hue_color32);
draw_list->PrimVtx(trb, uv_white, hue_color32);
@ -11609,7 +11620,6 @@ void ImGui::ShowMetricsWindow(bool* p_open)
return;
ImDrawList* overlay_draw_list = &GImGui->OverlayDrawList; // Render additional visuals into the top-most draw list
overlay_draw_list->PushClipRectFullScreen();
int elem_offset = 0;
for (const ImDrawCmd* pcmd = draw_list->CmdBuffer.begin(); pcmd < draw_list->CmdBuffer.end(); elem_offset += pcmd->ElemCount, pcmd++)
{
@ -11652,7 +11662,6 @@ void ImGui::ShowMetricsWindow(bool* p_open)
}
ImGui::TreePop();
}
overlay_draw_list->PopClipRect();
ImGui::TreePop();
}

View File

@ -50,6 +50,7 @@ struct ImDrawChannel; // Temporary storage for outputting drawing
struct ImDrawCmd; // A single draw command within a parent ImDrawList (generally maps to 1 GPU draw call)
struct ImDrawData; // All draw command lists required to render the frame
struct ImDrawList; // A single draw command list (generally one per window)
struct ImDrawListSharedData; // Data shared among multiple draw lists (typically owned by parent ImGui context, but you may create one yourself)
struct ImDrawVert; // A single vertex (20 bytes by default, override layout with IMGUI_OVERRIDE_DRAWVERT_STRUCT_LAYOUT)
struct ImFont; // Runtime data for a single font within a parent ImFontAtlas
struct ImFontAtlas; // Runtime data for multiple fonts, bake multiple fonts into a single texture, TTF/OTF font loader
@ -466,6 +467,7 @@ namespace ImGui
IMGUI_API float GetTime();
IMGUI_API int GetFrameCount();
IMGUI_API ImDrawList* GetOverlayDrawList(); // this draw list will be the last rendered one, useful to quickly draw overlays shapes/text
IMGUI_API ImDrawListSharedData* GetDrawListSharedData();
IMGUI_API const char* GetStyleColorName(ImGuiCol idx);
IMGUI_API ImVec2 CalcItemRectClosestPoint(const ImVec2& pos, bool on_edge = false, float outward = +0.0f); // utility to find the closest point the last item bounding rectangle edge. useful to visually link items
IMGUI_API ImVec2 CalcTextSize(const char* text, const char* text_end = NULL, bool hide_text_after_double_hash = false, float wrap_width = -1.0f);
@ -1325,7 +1327,7 @@ struct ImDrawCmd
ImDrawCallback UserCallback; // If != NULL, call the function instead of rendering the vertices. clip_rect and texture_id will be set normally.
void* UserCallbackData; // The draw callback code can access this.
ImDrawCmd() { ElemCount = 0; ClipRect.x = ClipRect.y = -8192.0f; ClipRect.z = ClipRect.w = +8192.0f; TextureId = NULL; UserCallback = NULL; UserCallbackData = NULL; }
ImDrawCmd() { ElemCount = 0; ClipRect.x = ClipRect.y = ClipRect.z = ClipRect.w = 0.0f; TextureId = NULL; UserCallback = NULL; UserCallbackData = NULL; }
};
// Vertex index (override with '#define ImDrawIdx unsigned int' inside in imconfig.h)
@ -1384,6 +1386,7 @@ struct ImDrawList
ImVector<ImDrawVert> VtxBuffer; // Vertex buffer.
// [Internal, used while building lists]
const ImDrawListSharedData* _Data; // Pointer to shared draw data (you can use ImGui::GetDrawListSharedData() to get the one from current ImGui context)
const char* _OwnerName; // Pointer to owner window's name for debugging
unsigned int _VtxCurrentIdx; // [Internal] == VtxBuffer.Size
ImDrawVert* _VtxWritePtr; // [Internal] point within VtxBuffer.Data after each add command (to avoid using the ImVector<> operators too much)
@ -1395,7 +1398,7 @@ struct ImDrawList
int _ChannelsCount; // [Internal] number of active channels (1+)
ImVector<ImDrawChannel> _Channels; // [Internal] draw channels for columns API (not resized down so _ChannelsCount may be smaller than _Channels.Size)
ImDrawList() { _OwnerName = NULL; Clear(); }
ImDrawList(const ImDrawListSharedData* shared_data) { _Data = shared_data; _OwnerName = NULL; Clear(); }
~ImDrawList() { ClearFreeMemory(); }
IMGUI_API void PushClipRect(ImVec2 clip_rect_min, ImVec2 clip_rect_max, bool intersect_with_current_clip_rect = false); // Render-level scissoring. This is passed down to your render function but not used for CPU-side coarse clipping. Prefer using higher-level ImGui::PushClipRect() to affect logic (hit-testing and widget culling)
IMGUI_API void PushClipRectFullScreen();

View File

@ -277,10 +277,27 @@ void ImGui::StyleColorsLight(ImGuiStyle* dst)
}
//-----------------------------------------------------------------------------
// ImDrawList
// ImDrawListData
//-----------------------------------------------------------------------------
static const ImVec4 GNullClipRect(-8192.0f, -8192.0f, +8192.0f, +8192.0f); // Large values that are easy to encode in a few bits+shift
ImDrawListSharedData::ImDrawListSharedData()
{
Font = NULL;
FontSize = 0.0f;
CurveTessellationTol = 0.0f;
ClipRectFullscreen = ImVec4(-8192.0f, -8192.0f, +8192.0f, +8192.0f);
// Const data
for (int i = 0; i < IM_ARRAYSIZE(CircleVtx12); i++)
{
const float a = ((float)i * 2 * IM_PI) / (float)IM_ARRAYSIZE(CircleVtx12);
CircleVtx12[i] = ImVec2(cosf(a), sinf(a));
}
}
//-----------------------------------------------------------------------------
// ImDrawList
//-----------------------------------------------------------------------------
void ImDrawList::Clear()
{
@ -321,7 +338,7 @@ void ImDrawList::ClearFreeMemory()
}
// Using macros because C++ is a terrible language, we want guaranteed inline, no code in header, and no overhead in Debug builds
#define GetCurrentClipRect() (_ClipRectStack.Size ? _ClipRectStack.Data[_ClipRectStack.Size-1] : GNullClipRect)
#define GetCurrentClipRect() (_ClipRectStack.Size ? _ClipRectStack.Data[_ClipRectStack.Size-1] : _Data->ClipRectFullscreen)
#define GetCurrentTextureId() (_TextureIdStack.Size ? _TextureIdStack.Data[_TextureIdStack.Size-1] : NULL)
void ImDrawList::AddDrawCmd()
@ -412,8 +429,7 @@ void ImDrawList::PushClipRect(ImVec2 cr_min, ImVec2 cr_max, bool intersect_with_
void ImDrawList::PushClipRectFullScreen()
{
PushClipRect(ImVec2(GNullClipRect.x, GNullClipRect.y), ImVec2(GNullClipRect.z, GNullClipRect.w));
//PushClipRect(GetVisibleRect()); // FIXME-OPT: This would be more correct but we're not supposed to access ImGuiContext from here?
PushClipRect(ImVec2(_Data->ClipRectFullscreen.x, _Data->ClipRectFullscreen.y), ImVec2(_Data->ClipRectFullscreen.z, _Data->ClipRectFullscreen.w));
}
void ImDrawList::PopClipRect()
@ -533,7 +549,7 @@ void ImDrawList::PrimReserve(int idx_count, int vtx_count)
// Fully unrolled with inline call to keep our debug builds decently fast.
void ImDrawList::PrimRect(const ImVec2& a, const ImVec2& c, ImU32 col)
{
ImVec2 b(c.x, a.y), d(a.x, c.y), uv(GImGui->FontTexUvWhitePixel);
ImVec2 b(c.x, a.y), d(a.x, c.y), uv(_Data->TexUvWhitePixel);
ImDrawIdx idx = (ImDrawIdx)_VtxCurrentIdx;
_IdxWritePtr[0] = idx; _IdxWritePtr[1] = (ImDrawIdx)(idx+1); _IdxWritePtr[2] = (ImDrawIdx)(idx+2);
_IdxWritePtr[3] = idx; _IdxWritePtr[4] = (ImDrawIdx)(idx+2); _IdxWritePtr[5] = (ImDrawIdx)(idx+3);
@ -581,7 +597,7 @@ void ImDrawList::AddPolyline(const ImVec2* points, const int points_count, ImU32
if (points_count < 2)
return;
const ImVec2 uv = GImGui->FontTexUvWhitePixel;
const ImVec2 uv = _Data->TexUvWhitePixel;
anti_aliased &= GImGui->Style.AntiAliasedLines;
//if (ImGui::GetIO().KeyCtrl) anti_aliased = false; // Debug
@ -759,7 +775,7 @@ void ImDrawList::AddPolyline(const ImVec2* points, const int points_count, ImU32
void ImDrawList::AddConvexPolyFilled(const ImVec2* points, const int points_count, ImU32 col, bool anti_aliased)
{
const ImVec2 uv = GImGui->FontTexUvWhitePixel;
const ImVec2 uv = _Data->TexUvWhitePixel;
anti_aliased &= GImGui->Style.AntiAliasedShapes;
//if (ImGui::GetIO().KeyCtrl) anti_aliased = false; // Debug
@ -842,20 +858,6 @@ void ImDrawList::AddConvexPolyFilled(const ImVec2* points, const int points_coun
void ImDrawList::PathArcToFast(const ImVec2& centre, float radius, int a_min_of_12, int a_max_of_12)
{
static ImVec2 circle_vtx[12];
static bool circle_vtx_builds = false;
const int circle_vtx_count = IM_ARRAYSIZE(circle_vtx);
if (!circle_vtx_builds)
{
for (int i = 0; i < circle_vtx_count; i++)
{
const float a = ((float)i / (float)circle_vtx_count) * 2*IM_PI;
circle_vtx[i].x = cosf(a);
circle_vtx[i].y = sinf(a);
}
circle_vtx_builds = true;
}
if (radius == 0.0f || a_min_of_12 > a_max_of_12)
{
_Path.push_back(centre);
@ -864,7 +866,7 @@ void ImDrawList::PathArcToFast(const ImVec2& centre, float radius, int a_min_of_
_Path.reserve(_Path.Size + (a_max_of_12 - a_min_of_12 + 1));
for (int a = a_min_of_12; a <= a_max_of_12; a++)
{
const ImVec2& c = circle_vtx[a % circle_vtx_count];
const ImVec2& c = _Data->CircleVtx12[a % IM_ARRAYSIZE(_Data->CircleVtx12)];
_Path.push_back(ImVec2(centre.x + c.x * radius, centre.y + c.y * radius));
}
}
@ -916,7 +918,7 @@ void ImDrawList::PathBezierCurveTo(const ImVec2& p2, const ImVec2& p3, const ImV
if (num_segments == 0)
{
// Auto-tessellated
PathBezierToCasteljau(&_Path, p1.x, p1.y, p2.x, p2.y, p3.x, p3.y, p4.x, p4.y, GImGui->Style.CurveTessellationTol, 0);
PathBezierToCasteljau(&_Path, p1.x, p1.y, p2.x, p2.y, p3.x, p3.y, p4.x, p4.y, _Data->CurveTessellationTol, 0);
}
else
{
@ -998,7 +1000,7 @@ void ImDrawList::AddRectFilledMultiColor(const ImVec2& a, const ImVec2& c, ImU32
if (((col_upr_left | col_upr_right | col_bot_right | col_bot_left) & IM_COL32_A_MASK) == 0)
return;
const ImVec2 uv = GImGui->FontTexUvWhitePixel;
const ImVec2 uv = _Data->TexUvWhitePixel;
PrimReserve(6, 4);
PrimWriteIdx((ImDrawIdx)(_VtxCurrentIdx)); PrimWriteIdx((ImDrawIdx)(_VtxCurrentIdx+1)); PrimWriteIdx((ImDrawIdx)(_VtxCurrentIdx+2));
PrimWriteIdx((ImDrawIdx)(_VtxCurrentIdx)); PrimWriteIdx((ImDrawIdx)(_VtxCurrentIdx+2)); PrimWriteIdx((ImDrawIdx)(_VtxCurrentIdx+3));
@ -1094,12 +1096,11 @@ void ImDrawList::AddText(const ImFont* font, float font_size, const ImVec2& pos,
if (text_begin == text_end)
return;
// IMPORTANT: This is one of the few instance of breaking the encapsulation of ImDrawList, as we pull this from ImGui state, but it is just SO useful.
// Might just move Font/FontSize to ImDrawList?
// Pull default font/size from the shared ImDrawListSharedData instance
if (font == NULL)
font = GImGui->Font;
font = _Data->Font;
if (font_size == 0.0f)
font_size = GImGui->FontSize;
font_size = _Data->FontSize;
IM_ASSERT(font->ContainerAtlas->TexID == _TextureIdStack.back()); // Use high-level ImGui::PushFont() or low-level ImDrawList::PushTextureId() to change font.

View File

@ -453,6 +453,21 @@ struct ImGuiColumnsSet
}
};
struct ImDrawListSharedData
{
ImVec2 TexUvWhitePixel; // UV of white pixel in the atlas
ImFont* Font; // Current/default font (optional, for simplified AddText overload)
float FontSize; // Current/default font size (optional, for simplified AddText overload)
float CurveTessellationTol;
ImVec4 ClipRectFullscreen; // Value for PushClipRectFullscreen()
// Const data
// FIXME: Bake rounded corners fill/borders in atlas
ImVec2 CircleVtx12[12];
ImDrawListSharedData();
};
// Main state for ImGui
struct ImGuiContext
{
@ -462,7 +477,7 @@ struct ImGuiContext
ImFont* Font; // (Shortcut) == FontStack.empty() ? IO.Font : FontStack.back()
float FontSize; // (Shortcut) == FontBaseSize * g.CurrentWindow->FontWindowScale == window->FontSize(). Text height for current window.
float FontBaseSize; // (Shortcut) == IO.FontGlobalScale * Font->Scale * Font->FontSize. Base text height.
ImVec2 FontTexUvWhitePixel; // (Shortcut) == Font->TexUvWhitePixel
ImDrawListSharedData DrawListSharedData;
float Time;
int FrameCount;
@ -574,12 +589,11 @@ struct ImGuiContext
int WantTextInputNextFrame;
char TempBuffer[1024*3+1]; // temporary text buffer
ImGuiContext()
ImGuiContext() : OverlayDrawList(NULL)
{
Initialized = false;
Font = NULL;
FontSize = FontBaseSize = 0.0f;
FontTexUvWhitePixel = ImVec2(0.0f, 0.0f);
Time = 0.0f;
FrameCount = 0;
@ -639,6 +653,7 @@ struct ImGuiContext
OsImePosRequest = OsImePosSet = ImVec2(-1.0f, -1.0f);
ModalWindowDarkeningRatio = 0.0f;
OverlayDrawList._Data = &DrawListSharedData;
OverlayDrawList._OwnerName = "##Overlay"; // Give it a name for debugging
MouseCursor = ImGuiMouseCursor_Arrow;
memset(MouseCursorData, 0, sizeof(MouseCursorData));
@ -805,7 +820,7 @@ struct IMGUI_API ImGuiWindow
int FocusIdxTabRequestNext; // "
public:
ImGuiWindow(const char* name);
ImGuiWindow(ImGuiContext* context, const char* name);
~ImGuiWindow();
ImGuiID GetID(const char* str, const char* str_end = NULL);