Странные проблемы с рендерингом при ручной модификации DrawList в ImGUI.C#

Место общения программистов C#
Ответить
Anonymous
 Странные проблемы с рендерингом при ручной модификации DrawList в ImGUI.

Сообщение Anonymous »

Я пытаюсь создать простую систему холста узлов, используя ImGUI.NET на основе https://github.com/thedmd/imgui-node-ed ... canvas.cpp. Я считаю, что этот вопрос по-прежнему применим к общему ImGUI, поскольку по сути это просто оболочка библиотеки C++.
Это работает путем захвата всех команд и вершин, добавленных ImGUI между ними. вызывает Canvas.Begin() и Canvas.End() и преобразует их из локального пространства холста в пространство экрана. По сути, это означает, что внутри блока между Canvas.Begin() и Canvas.End() все позиции экрана фактически являются позициями внутри холста.
проблема в том, что по какой-то причине, если я устанавливаю элементы для рендеринга в (0, 0), они отказываются рендериться, если координата y родительского окна не является отрицательной, а также происходит какое-то странное поведение маскировки.
Я демонстрирую это в этом видео: https://files.catbox.moe/uxex96.mp4
Пожалуйста, найдите мой код ниже:

Код: Выделить всё

private Vector2 _widgetPos;
private Vector2 _widgetSize;

private ImDrawListPtr _drawList;

private Vector2 _offset;
private float _scale = 1f;

private int _vtxBufferStart;
private int _cmdBufferStart;

private const float GridStep = 64f;

public void Begin()
{
_widgetPos = ImGui.GetCursorScreenPos();
_widgetSize = ImGui.GetContentRegionAvail();

_drawList = ImGui.GetWindowDrawList();

// Draw Grid (Grid jumps a bit when scaling - TODO: fix this)
var localMin = WidgetToLocal(Vector2.Zero);
var localMax = WidgetToLocal(_widgetSize);
var gridColour = ImGui.ColorConvertFloat4ToU32(new Vector4(220, 220, 220, 50) / 255);
for (float x = localMin.X % GridStep; x < localMax.X - localMin.X; x += GridStep)
_drawList.AddLine(LocalToScreen(new Vector2(localMax.X - x, localMin.Y)),
LocalToScreen(new Vector2(localMax.X - x, localMax.Y)), gridColour);
for (float y = localMin.Y % GridStep; y < localMax.Y - localMin.Y; y += GridStep)
_drawList.AddLine(LocalToScreen(new Vector2(localMin.X, localMax.Y - y)),
LocalToScreen(new Vector2(localMax.X, localMax.Y - y)), gridColour);

// Clip to control
_drawList.PushClipRect(ScreenToLocal(_widgetPos), ScreenToLocal(_widgetPos + _widgetSize), false);

// Any UI drawn past this point will be in canvas space
_vtxBufferStart = _drawList.VtxBuffer.Size;
_cmdBufferStart = _drawList.CmdBuffer.Size;

// Start Drawing from (0, 0) in the canvas
ImGui.SetCursorScreenPos(Vector2.Zero);
}

public Vector2 ScreenToLocal(Vector2 screen) => WidgetToLocal(screen - _widgetPos);
public Vector2 LocalToScreen(Vector2 local) => LocalToWidget(local) + _widgetPos;

public Vector2 LocalToWidget(Vector2 local) => (local + _offset) * _scale;
public Vector2 WidgetToLocal(Vector2 widget) => widget / _scale - _offset;

public void End()
{
// Any UI drawn past this point is in screen space
var vtxBufferEnd = _drawList.VtxBuffer.Size;
var cmdBufferEnd = _drawList.CmdBuffer.Size;

for (int idx = _vtxBufferStart; idx < vtxBufferEnd; idx++) // Update vertices
{
var vtx = _drawList.VtxBuffer[idx];
vtx.pos = LocalToScreen(vtx.pos);
}

for (int idx = _cmdBufferStart; idx < cmdBufferEnd; idx++) // Update clipping
{
var cmd = _drawList.CmdBuffer[idx];
var (min, max) = Util.SplitVector4(cmd.ClipRect);
cmd.ClipRect = Util.MergeVector2s(LocalToScreen(min), LocalToScreen(max));
}

_drawList.PopClipRect(); // We are done with clipping now

// Zooming
var io = ImGui.GetIO();
_scale += io.MouseWheel * _scale * 0.1f;

// Draw Invisible Button to capture click and focus events
ImGui.SetCursorScreenPos(_widgetPos);
ImGui.InvisibleButton("Canvas", _widgetSize);
bool isHovered = ImGui.IsItemHovered();
bool isClicked = ImGui.IsItemActive();
if (isClicked)
{
_offset += WidgetToLocal(io.MousePos) - WidgetToLocal(io.MousePosPrev);
}
}
Затем холст используется следующим образом:

Код: Выделить всё

ImGui.Begin("StoryGraph", ref _open);

_canvas.Begin();

ImGui.Button("Example Button!");

_canvas.End();

ImGui.End();
Я совершенно уверен, что проблема не в границах моего прямоугольника отсечения. Я попробовал следующее, чтобы диагностировать это, и ни один из них не помог:
  • Удалить весь обтравочный код
    < /li>
    Сделать обтравочную маску размером всего экрана
  • Сделать обтравочную маску из (- от 9999, -9999) до (9999, 9999)
  • Всегда сохранять обтравочную маску в координатах экранного пространства
Ни один из них не изменил главную проблему простого исчезновения элементов. Рисование кнопки в том положении, в котором она обычно появляется (

Код: Выделить всё

ImGui.SetCursorScreenPos(_widgetPos)
вместо ImGui.SetCursorScreenPos(Vector2.Zero)) приводит к появлению кнопки, но тогда ее позиционирование неверно, так как преобразование холста затем применяется поверх уже позиции в экранном пространстве. p>
Я также был бы рад принять альтернативное решение для холста в ImGUI, при условии, что я могу масштабировать и перемещать бесконечный холст, на котором я могу рисовать обычные элементы ImGUI (с возможностью событий мыши). ).

Подробнее здесь: https://stackoverflow.com/questions/791 ... n-in-imgui
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «C#»