epezent / implot

Immediate Mode Plotting
MIT License
4.55k stars 503 forks source link

Ability to treat point, line and rect drags as clicks #506

Closed pozemka closed 11 months ago

pozemka commented 11 months ago

Currently it is not possible to know if draggable point was clicked. ImPlot::DragPoint returns true only when point was dragged few pixels. This is needed for example for the ability to remove existing points on Ctrl+clicks.

I've added new flag ImPlotDragToolFlags_::ImPlotDragToolFlags_ClickIsDrag. If this flag is set ImPlot::Drag.. functions will return true when element is clicked.

This is achieved by using return result of ImGui::ButtonBehavior function.

Hope this patch will be useful.

If there is better way to detect clicks on draggable points please let me know.

Example code:

if (ImPlot::DragPoint(id, &x, &y, ImVec4(1, 0, 1, 1), 4.0f, ImPlotDragToolFlags_ClickIsDrag)) {
    if (ImGui::GetIO().KeyCtrl) {
        // remove point
    }
}

https://github.com/epezent/implot/assets/1259724/4bd38a4f-2c81-4969-8e06-bfe426cb71ff

epezent commented 11 months ago

Hi, thanks for the PR. The idea behind the return bool is to notify the user that the value of the point, line, or rect, has changed so they can easily call code upon this event.

if (DragPoint(id, &x, &y)) {
   // update code dependent on value of x and y
}

Clicking the tool does not change the value, so it doesn't make sense to return true in that case.

Alternatively, I wouldn't be opposed to a PR which adds optional arguments to get input events off these tools, e.g.:

bool DragPoint(int id, double* x, double* y, const ImVec4& col, float size = 4, ImPlotDragToolFlags flags=0, bool* clicked=0, bool* hovered=0, bool* held=0)

If those arguments are provided (not null), we can simple set them to the internal state before returning from the functions.

pozemka commented 11 months ago

This is good idea. Let's try version with additional arguments provided. I will close this PR and will open new one with new implementation