rokups / ImNodes

Node graph implementation for Dear ImGui. Used in https://github.com/rokups/rbfx
MIT License
668 stars 57 forks source link

Better sample code and documentation #45

Open GreedyTactician opened 2 years ago

GreedyTactician commented 2 years ago

I pasted the sample code on the readme. I got this imgui/ImNodesEz.cpp:125: bool ImNodes::Ez::BeginNode(void, const char, ImVec2, bool): Assertion `GContext != nullptr' failed. Aborted (core dumped)

something something context. OK. You have another sample code. Looked through it. Ah!

Pasted this in: static ImNodes::Ez::Context* context = ImNodes::Ez::CreateContext();

Only to be met with a new assertion fail! imgui/imgui_draw.cpp:1792: void ImDrawListSplitter::SetCurrentChannel(ImDrawList*, int): Assertion `idx >= 0 && idx < _Count' failed.

Perhaps the sample code was written for a previous version of the library which is now outdated. In any case, having something to run and play with incrementally is immensely helpful.

NPatch commented 2 years ago

Hit that too. Looking at the sample.cpp code, I realise the home page snippet does not deal with initialization and shutdown code:

... context = ImNodes::Ez::CreateContext() //much like imgui
...
ImNodes::Ez::FreeContext(context)

Although to be fair, the snippet does say a very simplistic example.

As for the canvas code in the snippet and the assertion crash, the issues are these:

static ImNodes::CanvasState canvas;
...
    ImNodes::BeginCanvas(&canvas);
    ...

    for (Node& node : nodes)
    {
        if (ImNodes::Ez::BeginNode(&node, "Node Title", &node.pos, &node.selected))
        {
            ImNodes::Ez::InputSlots(node.inputs, 1);
            ImNodes::Ez::OutputSlots(node.outputs, 1);
            ImNodes::Ez::EndNode();
        }
    }

    ImNodes::EndCanvas();

Basically all functions that are within the Ez namespace internally work with the context and its own CanvasState. In the code above though, BeginCanvas is not from the Ez namespace and instead uses a local CanvasState, yet all the inner nodes and slots are calling into Ez namespace.

Since we don't call ImNodes::Ez::BeginCanvas, the inner CanvasState of the context is not properly initialized (and internally split) and that split is what raises the internal _Count which is referenced in that assertion. Instead the local CanvasState is initialized.

Later inside the node loop, we call ImNodes::Ez::BeginNode which will try to use the context's CanvasState which is not initialized (therefore its _Count is still 0) so the assertion will be hit.

If you switch

    ImNodes::BeginCanvas(&canvas);

and its correspondent EndCanvas to the Ez namespace and without parameters

    ImNodes::Ez::BeginCanvas();

it will work.

The other option, if you wish to work with a local CanvasState instead, would be to remove ::Ez:: from all calls in the middle and provide the local canvas as parameter. I have not tested this, but I imagine it works as internally functions in the Ez namespace do that using the context.State canvas.

sonoro1234 commented 1 year ago

The other option, if you wish to work with a local CanvasState instead, would be to remove ::Ez:: from all calls in the middle and provide the local canvas as parameter. I have not tested this, but I imagine it works as internally functions in the Ez namespace do that using the context.State canvas.

It does not work for me. I wish there was a sample with this possibiity also.