ocornut/imgui

Inertial scrolling [help needed]

Aberta

#2.675 aberto em 18 de jul. de 2019

 (1 comentário) (0 reação) (0 responsável)C++ (12.004 forks)batch import
help wantedscrolling

Métricas do repositório

Stars
 (75.667 estrelas)
Métricas de merge de PR
 (Mesclagem média 2h 46m) (4 fundiu PRs em 30d)

Description

Version: 1.72WIP Branch: master

Back-ends: imgui_impl_directX11.cpp + imgui_impl_win32.cpp Compiler: VS2017 Operating System: Windows 7 SP1 x64

I started an attempt to add inertial (kinetic/ballistic) scrolling to ImGui for a touch based application.

For now, I just started implementing the related gesture detection and the realtime speed computation.

This part of the code is added inside the ImGui::UpdateMouseInputs() function in ImGui.ccp

The code is very small for now, just some lines.

// Moving mouse less than this duration and distance (pixels) does not launch an inertial scroll.
const float InertialScrollThresholdTime = 0.25f;
const float InertialScrollThresholdDistance = 10.0f;

// SpeedDecay for each frame once scroll is launched, 0.95 means 95% of the preceding speed
const float InertialScrollSpeedDecay = 0.95f;
bool InertialScrollOngoing = false;
float CurrentInertialScrollSpeed =  0.0f;

static void ImGui::UpdateMouseInputs()
{
  ImGuiContext& g = *GImGui;

...
  for (int i = 0; i < IM_ARRAYSIZE(g.IO.MouseDown); i++)
  {
    g.IO.MouseClicked[i] = g.IO.MouseDown[i] && g.IO.MouseDownDuration[i] < 0.0f;
    g.IO.MouseReleased[i] = !g.IO.MouseDown[i] && g.IO.MouseDownDuration[i] >= 0.0f;
    g.IO.MouseDownDurationPrev[i] = g.IO.MouseDownDuration[i];
    g.IO.MouseDownDuration[i] = g.IO.MouseDown[i] ? (g.IO.MouseDownDuration[i] < 0.0f ? 0.0f : g.IO.MouseDownDuration[i] + g.IO.DeltaTime) : -1.0f;
    g.IO.MouseDoubleClicked[i] = false;

    // New code for inertial scroll
    if (InertialScrollOngoing == true)
    {
      //TODO: Use deltatime instead of update on each frame.
      CurrentInertialScrollSpeed *= InertialScrollSpeedDecay;
      if (CurrentInertialScrollSpeed < 0.001f)
        InertialScrollOngoing = false;
    }

    if (g.IO.MouseReleased[i] &&
       (g.IO.MouseDownDurationPrev[i] >= InertialScrollThresholdTime) &&
       (g.IO.MouseDragMaxDistanceAbs[i].y > InertialScrollThresholdDistance))
    {
      // launch inertial scroll
      InertialScrollOngoing = true;
      CurrentInertialScrollSpeed = g.IO.MouseDragMaxDistanceAbs[i].y;
    }
    // end of new code for inertial scroll
...

In the following example, the red text is the actual speed of the scroll (CurrentInertialScrollSpeed ) we would apply on a scrolling area inertial

The detection of the movement to launch the scroll is not always working correctly. I do not know why so I just wanted to share and maybe someone has already worked on the subject. Do not consider this as an issue it is just some discussion.

Once detection and speed handling is working I have to do the actual scroll. And to be touch friendly it would be good to have the possibility to initiate the scroll from other areas than the scrollbar itself. I have no idea to handle this for now neither.

Guia do colaborador