Skip to content

Commit

Permalink
Scroll at a consistent speed.
Browse files Browse the repository at this point in the history
  • Loading branch information
mesilliac committed Apr 25, 2022
1 parent dc48c6d commit 4e58b57
Show file tree
Hide file tree
Showing 2 changed files with 53 additions and 11 deletions.
58 changes: 47 additions & 11 deletions src/controller_base.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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()
Expand All @@ -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;
}
}

Expand All @@ -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);
Expand All @@ -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)
Expand Down
6 changes: 6 additions & 0 deletions src/controller_base.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,12 @@ class controller_base : public video2::draw_layering, public events::pump_monito
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.
Expand Down

0 comments on commit 4e58b57

Please sign in to comment.