thedmd / imgui-node-editor

Node Editor built using Dear ImGui
MIT License
3.64k stars 537 forks source link

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

Closed paccerdk closed 8 months ago

paccerdk commented 9 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 9 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 9 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 8 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?