Scroll at a consistent speed.

Fixes #3607
This commit is contained in:
Tommy 2022-04-25 22:44:31 +12:00
parent dc48c6dc63
commit 4e58b57e95
2 changed files with 53 additions and 11 deletions

View file

@ -43,6 +43,9 @@ controller_base::controller_base()
, scroll_down_(false)
, scroll_left_(false)
, scroll_right_(false)
, last_scroll_tick_(0)
, scroll_carry_x_(0.0)
, scroll_carry_y_(0.0)
, key_release_listener_(*this)
, last_mouse_is_touch_(false)
, long_touch_timer_(0)
@ -273,7 +276,7 @@ bool controller_base::handle_scroll(int mousex, int mousey, int mouse_flags)
|| preferences::get("scroll_when_mouse_outside", true);
int scroll_speed = preferences::scroll_speed();
int dx = 0, dy = 0;
double dx = 0.0, dy = 0.0;
int scroll_threshold = preferences::mouse_scroll_enabled()
? preferences::mouse_scroll_threshold()
@ -285,28 +288,41 @@ bool controller_base::handle_scroll(int mousex, int mousey, int mouse_flags)
}
}
// Scale scroll distance according to time passed
uint32_t tick_now = SDL_GetTicks();
// If we weren't previously scrolling, start small.
int dt = 1;
if (scrolling_) {
dt = tick_now - last_scroll_tick_;
}
// scroll_speed is in percent. Ticks are in milliseconds.
// Let's assume the maximum speed (100) moves 50 hexes per second,
// i.e. 3600 pixels per 1000 ticks.
double scroll_amount = double(dt) * 0.036 * double(scroll_speed);
last_scroll_tick_ = tick_now;
// Apply keyboard scrolling
dy -= scroll_up_ * scroll_speed;
dy += scroll_down_ * scroll_speed;
dx -= scroll_left_ * scroll_speed;
dx += scroll_right_ * scroll_speed;
dy -= scroll_up_ * scroll_amount;
dy += scroll_down_ * scroll_amount;
dx -= scroll_left_ * scroll_amount;
dx += scroll_right_ * scroll_amount;
// Scroll if mouse is placed near the edge of the screen
if(mouse_in_window) {
if(mousey < scroll_threshold) {
dy -= scroll_speed;
dy -= scroll_amount;
}
if(mousey > get_display().video().get_height() - scroll_threshold) {
dy += scroll_speed;
dy += scroll_amount;
}
if(mousex < scroll_threshold) {
dx -= scroll_speed;
dx -= scroll_amount;
}
if(mousex > get_display().video().get_width() - scroll_threshold) {
dx += scroll_speed;
dx += scroll_amount;
}
}
@ -322,7 +338,7 @@ bool controller_base::handle_scroll(int mousex, int mousey, int mouse_flags)
if(sdl::point_in_rect(mousex, mousey, rect) && mh_base.scroll_started()) {
// Scroll speed is proportional from the distance from the first
// middle click and scrolling speed preference.
const double speed = 0.04 * std::sqrt(static_cast<double>(scroll_speed));
const double speed = 0.01 * scroll_amount;
const double snap_dist = 16; // Snap to horizontal/vertical scrolling
const double x_diff = (mousex - original_loc.x);
const double y_diff = (mousey - original_loc.y);
@ -340,7 +356,27 @@ bool controller_base::handle_scroll(int mousex, int mousey, int mouse_flags)
}
}
return get_display().scroll(dx, dy);
// If nothing is scrolling, just return.
if (!dx && !dy) {
return false;
}
// If we are continuing a scroll, carry over any subpixel movement.
if (scrolling_) {
dx += scroll_carry_x_;
dy += scroll_carry_y_;
}
int dx_int = int(dx);
int dy_int = int(dy);
scroll_carry_x_ = dx - double(dx_int);
scroll_carry_y_ = dy - double(dy_int);
// Scroll the display
get_display().scroll(dx_int, dy_int);
// Even if the integer parts are both zero, we are still scrolling.
// The subpixel amounts will add up.
return true;
}
void controller_base::play_slice(bool is_delay_enabled)

View file

@ -189,6 +189,12 @@ protected:
bool scroll_down_;
bool scroll_left_;
bool scroll_right_;
/* When the last scroll tick was processed */
uint32_t last_scroll_tick_;
/* Sub-pixel movement left over from a previous scroll tick.
* This is added to the next scroll tick, if scrolling continues. */
double scroll_carry_x_;
double scroll_carry_y_;
private:
/* A separate class for listening key-up events.