add two-finger pan and pinch-to-zoom to the waterfall

This commit is contained in:
2026-03-25 23:11:53 +01:00
parent 91edca87e2
commit e8867e4b01
2 changed files with 82 additions and 0 deletions

View File

@@ -143,6 +143,7 @@ void Application::mainLoopStep() {
SDL_Event event; SDL_Event event;
while (SDL_PollEvent(&event)) { while (SDL_PollEvent(&event)) {
ImGui_ImplSDL2_ProcessEvent(&event); ImGui_ImplSDL2_ProcessEvent(&event);
handleTouchEvent(event);
if (event.type == SDL_QUIT) if (event.type == SDL_QUIT)
running_ = false; running_ = false;
if (event.type == SDL_KEYDOWN) { if (event.type == SDL_KEYDOWN) {
@@ -1122,6 +1123,75 @@ void Application::renderWaterfallPanel() {
ImGui::Dummy({availW, availH}); ImGui::Dummy({availW, availH});
} }
void Application::handleTouchEvent(const SDL_Event& event) {
if (event.type == SDL_FINGERDOWN) {
++touch_.count;
} else if (event.type == SDL_FINGERUP) {
touch_.count = std::max(0, touch_.count - 1);
}
// Two-finger gesture start: snapshot state
if (touch_.count == 2 && event.type == SDL_FINGERDOWN) {
int w, h;
SDL_GetWindowSize(window_, &w, &h);
// Get both finger positions from SDL touch API
SDL_TouchID tid = event.tfinger.touchId;
int nf = SDL_GetNumTouchFingers(tid);
if (nf >= 2) {
SDL_Finger* f0 = SDL_GetTouchFinger(tid, 0);
SDL_Finger* f1 = SDL_GetTouchFinger(tid, 1);
float x0 = f0->x * w, x1 = f1->x * w;
float dx = x1 - x0, dy = (f1->y - f0->y) * h;
touch_.startDist = std::sqrt(dx * dx + dy * dy);
touch_.lastDist = touch_.startDist;
touch_.startCenterX = (x0 + x1) * 0.5f;
touch_.lastCenterX = touch_.startCenterX;
touch_.startLo = viewLo_;
touch_.startHi = viewHi_;
}
}
// Two-finger motion: pinch + pan
if (touch_.count == 2 && event.type == SDL_FINGERMOTION) {
int w, h;
SDL_GetWindowSize(window_, &w, &h);
SDL_TouchID tid = event.tfinger.touchId;
int nf = SDL_GetNumTouchFingers(tid);
if (nf >= 2) {
SDL_Finger* f0 = SDL_GetTouchFinger(tid, 0);
SDL_Finger* f1 = SDL_GetTouchFinger(tid, 1);
float x0 = f0->x * w, x1 = f1->x * w;
float dx = x1 - x0, dy = (f1->y - f0->y) * h;
float dist = std::sqrt(dx * dx + dy * dy);
float centerX = (x0 + x1) * 0.5f;
if (touch_.startDist > 1.0f) {
// Zoom: scale the span by start/current distance ratio
float span0 = touch_.startHi - touch_.startLo;
float ratio = touch_.startDist / std::max(dist, 1.0f);
float newSpan = std::clamp(span0 * ratio, 0.001f, 1.0f);
// Anchor zoom at the initial midpoint (in view-fraction space)
float panelW = wfSizeX_ > 0 ? wfSizeX_ : static_cast<float>(w);
float panelX = wfPosX_;
float midFrac = (touch_.startCenterX - panelX) / panelW;
float midView = touch_.startLo + midFrac * span0;
// Pan: shift by finger midpoint movement
float panDelta = -(centerX - touch_.startCenterX) / panelW * newSpan;
float newLo = midView - midFrac * newSpan + panDelta;
float newHi = newLo + newSpan;
if (newLo < 0.0f) { newHi -= newLo; newLo = 0.0f; }
if (newHi > 1.0f) { newLo -= (newHi - 1.0f); newHi = 1.0f; }
viewLo_ = std::clamp(newLo, 0.0f, 1.0f);
viewHi_ = std::clamp(newHi, 0.0f, 1.0f);
}
}
}
}
void Application::handleSpectrumInput(float posX, float posY, void Application::handleSpectrumInput(float posX, float posY,
float sizeX, float sizeY) { float sizeX, float sizeY) {
ImGuiIO& io = ImGui::GetIO(); ImGuiIO& io = ImGui::GetIO();

View File

@@ -184,6 +184,18 @@ private:
HoverPanel hoverPanel_ = HoverPanel::None; HoverPanel hoverPanel_ = HoverPanel::None;
float hoverWfTimeOffset_ = 0.0f; // seconds from newest line float hoverWfTimeOffset_ = 0.0f; // seconds from newest line
// Touch gesture state (pinch-zoom / two-finger pan)
struct TouchState {
int count = 0; // active finger count
float startDist = 0.0f; // initial distance between two fingers
float startLo = 0.0f; // viewLo_ at gesture start
float startHi = 0.0f; // viewHi_ at gesture start
float startCenterX = 0.0f; // midpoint screen-X at gesture start
float lastCenterX = 0.0f; // last midpoint screen-X
float lastDist = 0.0f; // last distance between fingers
} touch_;
void handleTouchEvent(const SDL_Event& event);
// Config persistence // Config persistence
Config config_; Config config_;