rokups / ImNodes

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

Inquiry #26

Open flamendless opened 3 years ago

flamendless commented 3 years ago

Hi, im looking for node graph libraries that i can use for a school project. Ive been keeping an eye on this library for a while now and i have some questions which I would be really glad if someone can answer.

I think this one is easier to use than the other imnodes library.

Thank you.

rokups commented 3 years ago

Is the title text of the node editable? (Clicking in the title bar of the node to go into text input mode or something)

There isnt really a titltle as such. You are responsible for rendering it. You may edit text input in place of title if you desire. Ez namespace renders just a text. Ez is more of an example how to use low level library functions rather than a code intended for consumption, but you can copy it and customize node rendering to your liking.

Can nodes have different components? For example, a node with only integers input can be connected/linked into another node with a string input.

I suppose you mean slots? Slots are differentiated by you passing a number representing slot kind. For example you could have an enum defining all kinds of slots. You can connect slots that have a matching slot kind. There is no way to connect two slots with different kinds, however.

How will these nodes of different structures be put in a single container? Im thinking of vector of node struct, but the node can have different struct definition (this is more like cpp general question)

sample.cpp has an example of that. You keep a std::vector<> of nodes, each node keeps a list of it's connections.

flamendless commented 3 years ago

Thank you!

flamendless commented 3 years ago

So to not create a new issue. In the sample it says that the order is important for

ImNodes::Ez::InputSlots(node->m_in_slots.data(), node->m_in_slots.size());
// draw node content
ImNodes::Ez::OutputSlots(node->m_out_slots.data(), node->m_out_slots.size());

but what i want is for the node to look different so i do:

// draw node content
ImNodes::Ez::InputSlots(node->m_in_slots.data(), node->m_in_slots.size());
ImNodes::Ez::OutputSlots(node->m_out_slots.data(), node->m_out_slots.size());

and there seems to be no issue with this. Is the "order important" only meant for the order of InputSlots() and OutputSlots call and not for the drawing of the content of the node?

rokups commented 3 years ago

Order is important because Ez implementation renders node in three columns: | input slots | content | output slots |. Therefore if you need something to appear between input and output slots - it has to go between ImNodes::Ez::InputSlots() and ImNodes::Ez::OutputSlots() contents.

ImNodes::Ez::InputSlots(node->InputSlots.data(), node->InputSlots.size());
ImGui::Text("Content of %s", node->Title);
ImNodes::Ez::OutputSlots(node->OutputSlots.data(), node->OutputSlots.size());

image

Rendering content before input and output slots will simply put them above slots. If that is what you want - it is ok to do as well.

ImGui::Text("Content of %s", node->Title);
ImNodes::Ez::InputSlots(node->InputSlots.data(), node->InputSlots.size());
ImNodes::Ez::OutputSlots(node->OutputSlots.data(), node->OutputSlots.size());

image

flamendless commented 3 years ago

Im doing the latter. I was just confused by the "order" as i thought that means that it is important runtime-wise.

flamendless commented 3 years ago

How can one query if the node is hovered by the mouse? Putting if (ImGui::IsWindowHovered()) inside the BeginNode returns true for each node (even if not hovered by the mouse)

rokups commented 3 years ago

Try ImGui::IsItemHovered() after ImNodes::Ez::EndNode();. If you need to check this inside the node - it is not so simple, because node size is not yet known.

flamendless commented 3 years ago

I was about to edit my comment and add that IsItemHovered works only if it's placed after Ez::EndNode. Thanks!

flamendless commented 3 years ago

How are individual connection to be styled according to their state?

I've added a test bool is_true = true; flag to the struct Connection, some connection's flag are set to false for testing.

I've tried this but it doesnt change the style:

//render connections
    for (const Connection& connection : node.m_connections)
    {
        if (connection.out_node != &node) continue;

               ImGuiStyle& imgui_style = ImGui::GetStyle();

        if (connection.is_true)
            ImGui::PushStyleColor(ImGuiCol_PlotLines, imgui_style.Colors[ImGuiCol_PlotLines]);
        else
                {
                        PLOGD << 1; //this prints
            ImGui::PushStyleColor(ImGuiCol_PlotLines, ImVec4(1, 0, 0, 1));
                }

        //query removed connection
        if (!ImNodes::Connection(connection.in_node, connection.in_slot,
                connection.out_node, connection.out_slot))
        {
            Node* in_node = static_cast<Node*>(connection.in_node);
            Node* out_node = static_cast<Node*>(connection.out_node);

            in_node->delete_connection(connection);
            out_node->delete_connection(connection);
        }

        ImGui::PopStyleColor(1);
    }
rokups commented 3 years ago

CanvasState::Colors is used for storing colors. There is no push/pop api for them so changing them based on a parameter will be awkward. I never anticipated this would be a desired feature.

flamendless commented 3 years ago

Indeed, modifying the CanvasState::Colors is what im doing right now. So far i think it's okay and no need for push/pop style, but others may want that as following the spirit and api of dear imgui