Skip to content

Commit d434670

Browse files
committed
LeaveLocalSpace(): Search for ImDrawCallback_ImCanvas after m_DrawListFirstCommandIndex (proposed fix for thedmd#282)
Analysis of the bug thedmd#282 when using this repro: https://github.com/pthom/node_window_clipping_issue/tree/suspend_resume_issue2 At the 4th call of LeaveLocalSpace(), we have: this = {ImGuiEx::Canvas *} m_DrawList = {ImDrawList *} mDrawList is of size 4 CmdBuffer = {ImVector<ImDrawCmd>} its elements at index 2 Size = {int} 4 has UserCallback == {ImDrawCallback_ImCanvas} Capacity = {int} 8 Data = {ImDrawCmd *} m_ExpectedChannel = {int} 0 m_DrawListFirstCommandIndex = {int} 2 m_DrawListCommadBufferSize = {int} 1 m_DrawListStartVertexIndex = {int} 8 We have m_DrawListFirstCommandIndex = 2, however, the tests in the original code will test only at index 0 and 1! if (m_DrawList->CmdBuffer.size() > m_DrawListCommadBufferSize && m_DrawList->CmdBuffer[m_DrawListCommadBufferSize].UserCallback == ImDrawCallback_ImCanvas) m_DrawList->CmdBuffer.erase(m_DrawList->CmdBuffer.Data + m_DrawListCommadBufferSize); else if (m_DrawList->CmdBuffer.size() >= m_DrawListCommadBufferSize && m_DrawList->CmdBuffer[m_DrawListCommadBufferSize - 1].UserCallback == ImDrawCallback_ImCanvas) m_DrawList->CmdBuffer.erase(m_DrawList->CmdBuffer.Data + m_DrawListCommadBufferSize - 1); // Proposed solution: test all commands from index >= m_DrawListFirstCommandIndex // and remove the one with UserCallback == ImDrawCallback_ImCanvas // (based on the original code, it seems there can be only one) int idxCommand_ImDrawCallback_ImCanvas = -1; for (int i = m_DrawListFirstCommandIndex; i < m_DrawList->CmdBuffer.size(); ++i) { auto & command = m_DrawList->CmdBuffer[i]; if (command.UserCallback == ImDrawCallback_ImCanvas) { idxCommand_ImDrawCallback_ImCanvas = i; break; } } if (idxCommand_ImDrawCallback_ImCanvas >= 0) m_DrawList->CmdBuffer.erase(m_DrawList->CmdBuffer.Data + idxCommand_ImDrawCallback_ImCanvas);
1 parent 06892b1 commit d434670

File tree

1 file changed

+43
-0
lines changed

1 file changed

+43
-0
lines changed

imgui_canvas.cpp

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -537,10 +537,53 @@ void ImGuiEx::Canvas::LeaveLocalSpace()
537537
// Remove sentinel draw command if present
538538
if (m_DrawListCommadBufferSize > 0)
539539
{
540+
/*
541+
Analysis of the bug https://github.com/thedmd/imgui-node-editor/issues/282
542+
when using this repro: https://github.com/pthom/node_window_clipping_issue/tree/suspend_resume_issue2
543+
544+
At the 4th call of LeaveLocalSpace(), we have:
545+
546+
this = {ImGuiEx::Canvas *}
547+
m_DrawList = {ImDrawList *} mDrawList is of size 4
548+
CmdBuffer = {ImVector<ImDrawCmd>} its elements at index 2
549+
Size = {int} 4 has UserCallback == {ImDrawCallback_ImCanvas}
550+
Capacity = {int} 8
551+
Data = {ImDrawCmd *}
552+
m_ExpectedChannel = {int} 0
553+
m_DrawListFirstCommandIndex = {int} 2
554+
m_DrawListCommadBufferSize = {int} 1
555+
m_DrawListStartVertexIndex = {int} 8
556+
557+
We have m_DrawListFirstCommandIndex = 2, however, the tests in the original code will test only at index 0 and 1!
558+
if (m_DrawList->CmdBuffer.size() > m_DrawListCommadBufferSize && m_DrawList->CmdBuffer[m_DrawListCommadBufferSize].UserCallback == ImDrawCallback_ImCanvas)
559+
m_DrawList->CmdBuffer.erase(m_DrawList->CmdBuffer.Data + m_DrawListCommadBufferSize);
560+
else if (m_DrawList->CmdBuffer.size() >= m_DrawListCommadBufferSize && m_DrawList->CmdBuffer[m_DrawListCommadBufferSize - 1].UserCallback == ImDrawCallback_ImCanvas)
561+
m_DrawList->CmdBuffer.erase(m_DrawList->CmdBuffer.Data + m_DrawListCommadBufferSize - 1);
562+
563+
564+
*/
565+
566+
// Original tests; this test will fail because it tests at index 0 and 1
540567
if (m_DrawList->CmdBuffer.size() > m_DrawListCommadBufferSize && m_DrawList->CmdBuffer[m_DrawListCommadBufferSize].UserCallback == ImDrawCallback_ImCanvas)
541568
m_DrawList->CmdBuffer.erase(m_DrawList->CmdBuffer.Data + m_DrawListCommadBufferSize);
542569
else if (m_DrawList->CmdBuffer.size() >= m_DrawListCommadBufferSize && m_DrawList->CmdBuffer[m_DrawListCommadBufferSize - 1].UserCallback == ImDrawCallback_ImCanvas)
543570
m_DrawList->CmdBuffer.erase(m_DrawList->CmdBuffer.Data + m_DrawListCommadBufferSize - 1);
571+
572+
// Proposed solution: test all commands from index >= m_DrawListFirstCommandIndex
573+
// and remove the one with UserCallback == ImDrawCallback_ImCanvas
574+
// (based on the original code, it seems there can be only one)
575+
int idxCommand_ImDrawCallback_ImCanvas = -1;
576+
for (int i = m_DrawListFirstCommandIndex; i < m_DrawList->CmdBuffer.size(); ++i)
577+
{
578+
auto & command = m_DrawList->CmdBuffer[i];
579+
if (command.UserCallback == ImDrawCallback_ImCanvas)
580+
{
581+
idxCommand_ImDrawCallback_ImCanvas = i;
582+
break;
583+
}
584+
}
585+
if (idxCommand_ImDrawCallback_ImCanvas >= 0)
586+
m_DrawList->CmdBuffer.erase(m_DrawList->CmdBuffer.Data + idxCommand_ImDrawCallback_ImCanvas);
544587
}
545588

546589
auto& fringeScale = ImFringeScaleRef(m_DrawList);

0 commit comments

Comments
 (0)