Display: Don't move the center of the viewport when zooming in when the map is narrower/shorter than the viewport

In the test scenario, toggling between 50%/100% zoom on 1920x1080 will
now correctly switch between "Show the entire map" (50%) and "Show just
the center of the map" (100%).

Fixes #1951
This commit is contained in:
josteph 2019-10-09 21:17:21 +00:00 committed by jostephd
parent c0427b504e
commit f9fc82d9b9
3 changed files with 24 additions and 2 deletions

View file

@ -2016,13 +2016,28 @@ bool display::set_zoom(unsigned int amount, const bool validate_value_and_set_in
zoom_index_ = std::distance(zoom_levels.begin(), iter);
}
const SDL_Rect& outside_area = map_outside_area();
const SDL_Rect& area = map_area();
// Turn the zoom factor to a double in order to avoid rounding errors.
double zoom_factor = static_cast<double>(new_zoom) / static_cast<double>(zoom_);
// INVARIANT: xpos_ + area.w == xend where xend is as in bounds_check_position()
//
// xpos_: Position of the leftmost visible map pixel of the viewport, in pixels.
// Affected by the current zoom: this->zoom_ pixels to the hex.
//
// xpos_ + area.w/2: Position of the center of the viewport, in pixels.
//
// (xpos_ + area.w/2) * new_zoom/zoom_: Position of the center of the
// viewport, as it would be under new_zoom.
//
// (xpos_ + area.w/2) * new_zoom/zoom_ - area.w/2: Position of the
// leftmost visible map pixel, as it would be under new_zoom.
xpos_ = std::round(((xpos_ + area.w / 2) * zoom_factor) - (area.w / 2));
ypos_ = std::round(((ypos_ + area.h / 2) * zoom_factor) - (area.h / 2));
xpos_ -= (outside_area.w - area.w) / 2;
ypos_ -= (outside_area.h - area.h) / 2;
zoom_ = new_zoom;
bounds_check_position(xpos_, ypos_);

View file

@ -733,11 +733,18 @@ protected:
CVideo& screen_;
std::size_t currentTeam_;
bool dont_show_all_; //const team *viewpoint_;
/// Position of the top-left corner of the viewport, in pixels.
///
/// Dependent on zoom_.. For example, ypos_==72 only means we're one
/// hex below the top of the map when zoom_ == 72 (the default value).
int xpos_, ypos_;
bool view_locked_;
theme theme_;
/// The current zoom, in pixels (on screen) per 72 pixels (in the
/// graphic assets), i.e., 72 means 100%.
static unsigned int zoom_;
int zoom_index_;
/// The previous value of zoom_.
static unsigned int last_zoom_;
const std::unique_ptr<fake_unit_manager> fake_unit_man_;
const std::unique_ptr<terrain_builder> builder_;

View file

@ -121,10 +121,10 @@ public:
bool is_odd,
bool ignore_special_locations);
/** Effective map width. */
/** Effective map width, in hexes. */
int w() const { return w_; }
/** Effective map height. */
/** Effective map height, in hexes. */
int h() const { return h_; }
/** Size of the map border. */