diff --git a/src/graphicswin.cpp b/src/graphicswin.cpp index c7c74d98..98ed54d6 100644 --- a/src/graphicswin.cpp +++ b/src/graphicswin.cpp @@ -712,16 +712,47 @@ double GraphicsWindow::ZoomToFit(const Camera &camera, return scale; } + +void GraphicsWindow::ZoomToMouse(double zoomMultiplyer) { + double offsetRight = offset.Dot(projRight); + double offsetUp = offset.Dot(projUp); + + double width, height; + window->GetContentSize(&width, &height); + + double righti = currentMousePosition.x / scale - offsetRight; + double upi = currentMousePosition.y / scale - offsetUp; + + // zoomMultiplyer of 1 gives a default zoom factor of 1.2x: zoomMultiplyer * 1.2 + // zoom = adjusted zoom negative zoomMultiplyer will zoom out, positive will zoom in + // + + scale *= exp(0.1823216 * zoomMultiplyer); // ln(1.2) = 0.1823216 + + double rightf = currentMousePosition.x / scale - offsetRight; + double upf = currentMousePosition.y / scale - offsetUp; + + offset = offset.Plus(projRight.ScaledBy(rightf - righti)); + offset = offset.Plus(projUp.ScaledBy(upf - upi)); + + if(SS.TW.shown.screen == TextWindow::Screen::EDIT_VIEW) { + if(havePainted) { + SS.ScheduleShowTW(); + } + } + havePainted = false; + Invalidate(); +} + + void GraphicsWindow::MenuView(Command id) { switch(id) { case Command::ZOOM_IN: - SS.GW.scale *= 1.2; - SS.ScheduleShowTW(); + SS.GW.ZoomToMouse(1); break; case Command::ZOOM_OUT: - SS.GW.scale /= 1.2; - SS.ScheduleShowTW(); + SS.GW.ZoomToMouse(-1); break; case Command::ZOOM_TO_FIT: diff --git a/src/mouse.cpp b/src/mouse.cpp index 5e7cde26..d183f58a 100644 --- a/src/mouse.cpp +++ b/src/mouse.cpp @@ -914,7 +914,7 @@ bool GraphicsWindow::MouseEvent(Platform::MouseEvent event) { break; case MouseEvent::Type::SCROLL_VERT: - this->MouseScroll(event.x, event.y, event.shiftDown ? event.scrollDelta / 10 : event.scrollDelta); + this->MouseScroll(event.shiftDown ? event.scrollDelta / 10 : event.scrollDelta); break; case MouseEvent::Type::LEAVE: @@ -1478,17 +1478,10 @@ void GraphicsWindow::EditControlDone(const std::string &s) { } } -void GraphicsWindow::MouseScroll(double x, double y, double delta) { - double offsetRight = offset.Dot(projRight); - double offsetUp = offset.Dot(projUp); - - double righti = x/scale - offsetRight; - double upi = y/scale - offsetUp; - - // The default zoom factor is 1.2x for one scroll wheel click (delta==1). +void GraphicsWindow::MouseScroll(double zoomMultiplyer) { // To support smooth scrolling where scroll wheel events come in increments // smaller (or larger) than 1 we do: - // scale *= exp(ln(1.2) * delta); + // scale *= exp(ln(1.2) * zoomMultiplyer); // to ensure that the same total scroll delta always results in the same // total zoom irrespective of in how many increments the zoom was applied. // For example if we scroll a total delta of a+b in two events vs. one then @@ -1496,21 +1489,7 @@ void GraphicsWindow::MouseScroll(double x, double y, double delta) { // while // scale * a * b != scale * (a+b) // So this constant is ln(1.2) = 0.1823216 to make the default zoom 1.2x - scale *= exp(0.1823216 * delta); - - double rightf = x/scale - offsetRight; - double upf = y/scale - offsetUp; - - offset = offset.Plus(projRight.ScaledBy(rightf - righti)); - offset = offset.Plus(projUp.ScaledBy(upf - upi)); - - if(SS.TW.shown.screen == TextWindow::Screen::EDIT_VIEW) { - if(havePainted) { - SS.ScheduleShowTW(); - } - } - havePainted = false; - Invalidate(); + ZoomToMouse(zoomMultiplyer); } void GraphicsWindow::MouseLeave() { diff --git a/src/ui.h b/src/ui.h index 0d121b64..c4ffff2b 100644 --- a/src/ui.h +++ b/src/ui.h @@ -622,6 +622,7 @@ public: void HandlePointForZoomToFit(Vector p, Point2d *pmax, Point2d *pmin, double *wmin, bool usePerspective, const Camera &camera); + void ZoomToMouse(double delta); void LoopOverPoints(const std::vector &entities, const std::vector &constraints, const std::vector &faces, @@ -842,7 +843,7 @@ public: void MouseLeftDoubleClick(double x, double y); void MouseMiddleOrRightDown(double x, double y); void MouseRightUp(double x, double y); - void MouseScroll(double x, double y, double delta); + void MouseScroll(double delta); void MouseLeave(); bool KeyboardEvent(Platform::KeyboardEvent event); void EditControlDone(const std::string &s);