add two-finger pan and pinch-to-zoom to the waterfall
This commit is contained in:
@@ -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();
|
||||||
|
|||||||
@@ -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_;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user