|
@@ -94,7 +94,7 @@ using namespace IMGUI_STB_NAMESPACE;
|
|
// ImDrawList
|
|
// ImDrawList
|
|
//-----------------------------------------------------------------------------
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
|
-static ImVec4 GNullClipRect(-8192.0f, -8192.0f, +8192.0f, +8192.0f); // Large values that are easy to encode in a few bits+shift
|
|
|
|
|
|
+static const ImVec4 GNullClipRect(-8192.0f, -8192.0f, +8192.0f, +8192.0f); // Large values that are easy to encode in a few bits+shift
|
|
|
|
|
|
void ImDrawList::Clear()
|
|
void ImDrawList::Clear()
|
|
{
|
|
{
|
|
@@ -134,11 +134,15 @@ void ImDrawList::ClearFreeMemory()
|
|
_Channels.clear();
|
|
_Channels.clear();
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+// Use macros because C++ is a terrible language, we want guaranteed inline, no code in header, and no overhead in Debug mode
|
|
|
|
+#define GetCurrentClipRect() (_ClipRectStack.Size ? _ClipRectStack.Data[_ClipRectStack.Size-1] : GNullClipRect)
|
|
|
|
+#define GetCurrentTextureId() (_TextureIdStack.Size ? _TextureIdStack.Data[_TextureIdStack.Size-1] : NULL)
|
|
|
|
+
|
|
void ImDrawList::AddDrawCmd()
|
|
void ImDrawList::AddDrawCmd()
|
|
{
|
|
{
|
|
ImDrawCmd draw_cmd;
|
|
ImDrawCmd draw_cmd;
|
|
- draw_cmd.ClipRect = _ClipRectStack.Size ? _ClipRectStack.back() : GNullClipRect;
|
|
|
|
- draw_cmd.TextureId = _TextureIdStack.Size ? _TextureIdStack.back() : NULL;
|
|
|
|
|
|
+ draw_cmd.ClipRect = GetCurrentClipRect();
|
|
|
|
+ draw_cmd.TextureId = GetCurrentTextureId();
|
|
|
|
|
|
IM_ASSERT(draw_cmd.ClipRect.x <= draw_cmd.ClipRect.z && draw_cmd.ClipRect.y <= draw_cmd.ClipRect.w);
|
|
IM_ASSERT(draw_cmd.ClipRect.x <= draw_cmd.ClipRect.z && draw_cmd.ClipRect.y <= draw_cmd.ClipRect.w);
|
|
CmdBuffer.push_back(draw_cmd);
|
|
CmdBuffer.push_back(draw_cmd);
|
|
@@ -155,27 +159,52 @@ void ImDrawList::AddCallback(ImDrawCallback callback, void* callback_data)
|
|
current_cmd->UserCallback = callback;
|
|
current_cmd->UserCallback = callback;
|
|
current_cmd->UserCallbackData = callback_data;
|
|
current_cmd->UserCallbackData = callback_data;
|
|
|
|
|
|
- // Force a new command after us (we function this way so that the most common calls AddLine, AddRect, etc. always have a command to add to without doing any check).
|
|
|
|
- AddDrawCmd();
|
|
|
|
|
|
+ AddDrawCmd(); // Force a new command after us (see comment below)
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+// Our scheme may appears a bit unusual, basically we want the most-common calls AddLine AddRect etc. to not have to perform any check so we always have a command ready in the stack.
|
|
|
|
+// The cost of figuring out if a new command has to be added or if we can merge is paid in those Update** functions only.
|
|
void ImDrawList::UpdateClipRect()
|
|
void ImDrawList::UpdateClipRect()
|
|
{
|
|
{
|
|
- ImDrawCmd* current_cmd = CmdBuffer.Size ? &CmdBuffer.back() : NULL;
|
|
|
|
- if (!current_cmd || (current_cmd->ElemCount != 0) || current_cmd->UserCallback != NULL)
|
|
|
|
|
|
+ // If current command is used with different settings we need to add a new command
|
|
|
|
+ const ImVec4 curr_clip_rect = GetCurrentClipRect();
|
|
|
|
+ ImDrawCmd* curr_cmd = CmdBuffer.Size > 0 ? &CmdBuffer.Data[CmdBuffer.Size-1] : NULL;
|
|
|
|
+ if (!curr_cmd || (curr_cmd->ElemCount != 0 && memcmp(&curr_cmd->ClipRect, &curr_clip_rect, sizeof(ImVec4)) != 0) || curr_cmd->UserCallback != NULL)
|
|
{
|
|
{
|
|
AddDrawCmd();
|
|
AddDrawCmd();
|
|
|
|
+ return;
|
|
}
|
|
}
|
|
|
|
+
|
|
|
|
+ // Try to merge with previous command if it matches, else use current command
|
|
|
|
+ ImDrawCmd* prev_cmd = CmdBuffer.Size > 1 ? &CmdBuffer.Data[CmdBuffer.Size-2] : NULL;
|
|
|
|
+ if (prev_cmd && memcmp(&prev_cmd->ClipRect, &curr_clip_rect, sizeof(ImVec4)) == 0 && prev_cmd->TextureId == GetCurrentTextureId())
|
|
|
|
+ CmdBuffer.pop_back();
|
|
else
|
|
else
|
|
|
|
+ curr_cmd->ClipRect = curr_clip_rect;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+void ImDrawList::UpdateTextureID()
|
|
|
|
+{
|
|
|
|
+ // If current command is used with different settings we need to add a new command
|
|
|
|
+ const ImTextureID curr_texture_id = GetCurrentTextureId();
|
|
|
|
+ ImDrawCmd* curr_cmd = CmdBuffer.Size ? &CmdBuffer.back() : NULL;
|
|
|
|
+ if (!curr_cmd || (curr_cmd->ElemCount != 0 && curr_cmd->TextureId != curr_texture_id) || curr_cmd->UserCallback != NULL)
|
|
{
|
|
{
|
|
- ImVec4 current_clip_rect = _ClipRectStack.Size ? _ClipRectStack.back() : GNullClipRect;
|
|
|
|
- if (CmdBuffer.Size >= 2 && ImLengthSqr(CmdBuffer.Data[CmdBuffer.Size-2].ClipRect - current_clip_rect) < 0.00001f)
|
|
|
|
- CmdBuffer.pop_back();
|
|
|
|
- else
|
|
|
|
- current_cmd->ClipRect = current_clip_rect;
|
|
|
|
|
|
+ AddDrawCmd();
|
|
|
|
+ return;
|
|
}
|
|
}
|
|
|
|
+
|
|
|
|
+ // Try to merge with previous command if it matches, else use current command
|
|
|
|
+ ImDrawCmd* prev_cmd = CmdBuffer.Size > 1 ? &CmdBuffer.Data[CmdBuffer.Size-2] : NULL;
|
|
|
|
+ if (prev_cmd && prev_cmd->TextureId == curr_texture_id && memcmp(&prev_cmd->ClipRect, &GetCurrentClipRect(), sizeof(ImVec4)) == 0)
|
|
|
|
+ CmdBuffer.pop_back();
|
|
|
|
+ else
|
|
|
|
+ curr_cmd->TextureId = curr_texture_id;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+#undef GetCurrentClipRect
|
|
|
|
+#undef GetCurrentTextureId
|
|
|
|
+
|
|
// Scissoring. The values in clip_rect are x1, y1, x2, y2.
|
|
// Scissoring. The values in clip_rect are x1, y1, x2, y2.
|
|
void ImDrawList::PushClipRect(const ImVec4& clip_rect)
|
|
void ImDrawList::PushClipRect(const ImVec4& clip_rect)
|
|
{
|
|
{
|
|
@@ -199,16 +228,6 @@ void ImDrawList::PopClipRect()
|
|
UpdateClipRect();
|
|
UpdateClipRect();
|
|
}
|
|
}
|
|
|
|
|
|
-void ImDrawList::UpdateTextureID()
|
|
|
|
-{
|
|
|
|
- ImDrawCmd* current_cmd = CmdBuffer.Size ? &CmdBuffer.back() : NULL;
|
|
|
|
- const ImTextureID texture_id = _TextureIdStack.Size ? _TextureIdStack.back() : NULL;
|
|
|
|
- if (!current_cmd || (current_cmd->ElemCount != 0 && current_cmd->TextureId != texture_id) || current_cmd->UserCallback != NULL)
|
|
|
|
- AddDrawCmd();
|
|
|
|
- else
|
|
|
|
- current_cmd->TextureId = texture_id;
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
void ImDrawList::PushTextureID(const ImTextureID& texture_id)
|
|
void ImDrawList::PushTextureID(const ImTextureID& texture_id)
|
|
{
|
|
{
|
|
_TextureIdStack.push_back(texture_id);
|
|
_TextureIdStack.push_back(texture_id);
|