thedmd / imgui-node-editor

Node Editor built using Dear ImGui
MIT License
3.73k stars 551 forks source link

No exposed API for detecting dragging of node(s) #271

Closed paccerdk closed 10 months ago

paccerdk commented 11 months ago

There doesn't seem to be a straightforward method to detect the dragging of nodes. My attempts to find an exposed API for this functionality have been unsuccessful, and I haven't had any success with a proper manual implementation so far.

Manual Method Issues:


Additional Observations:

I'm not sure if this is intended or not, and whether its worth filing a separate issue for:

  1. ax::NodeEditor::HasSelectionChanged():

    • This function appears to always return false, regardless of changes in the selection.
  2. GetActionContext:

    • ax::NodeEditor::GetActionContextNodes() appears identical to ax::NodeEditor::GetSelectedNodes().
    • Similarly, ax::NodeEditor::GetActionContextLinks() mirrors ax::NodeEditor::GetSelectedLinks().
paccerdk commented 11 months ago

Turns out that detecting dragging of a node is possible by using: ax::NodeEditor::GetHoveredNode() and ImGui::IsMouseDragging(ImGuiMouseButton_Left, 1) (I wasn't previously setting the second parameter of IsMouseDragging)

This is what i ended up doing (also checks if we're dragging a group of nodes):

void updateDraggedNodes() {
    if (ImGui::IsMouseDragging(ImGuiMouseButton_Left, 1)) {
        if (!draggedNodeId) {
            draggedNodeId = nodeEd::GetHoveredNode();
            // started dragging node(s)
        } else {
            // currently dragging node(s)
        }
    } else if (draggedNodeId) {
        // stopped dragging node(s)
        handleNodeDrop(draggedNodeId);
        draggedNodeId = 0;
    }
}

void handleNodeDrop(const nodeEd::NodeId draggedNodeId) {
    std::vector<nodeEd::NodeId> nodesToUpdate;
    nodesToUpdate.resize(nodeEd::GetSelectedObjectCount());
    int nodeCount = nodeEd::GetSelectedNodes(nodesToUpdate.data(), nodesToUpdate.size());
    nodesToUpdate.resize(nodeCount); // Resize to actual number of nodes

    if ((nodeCount == 0) || std::find(nodesToUpdate.begin(), nodesToUpdate.end(), draggedNodeId) == nodesToUpdate.end()) {
        // If the dragged node is not in the selected group, or group is empty, update only the dragged node
        nodesToUpdate = { draggedNodeId };
    }

    for (const auto& nodeId : nodesToUpdate) {
       //logic here that i use to update state of nodes
    }

}

This might not be an ideal solution, but it works for now. Leaving the issue open since an exposed API for dragged nodes would still be nice

thedmd commented 11 months ago

Well, whole point of node editor was to hide this kind of interaction from user. 😅

Can you tell me what is your use case?

paccerdk commented 10 months ago

I need more control for my project, it features network synchronized UI and no-UI editing/processing mode, I'm considering rolling my own based on imgui_canvas.h fork, or switching to Nuklear which seems more suitable for my usage scenario, thanks!

Did you review the Additional Observations?