Implement map scrolling with hotkeys.

This leverages the new hotkey release support to implement scrolling
with hotkeys rather than keyboard polling.
This allows users to rebind the scroll keys in the hotkey menu.
Previously they were fixed to the arrow keys.
This commit is contained in:
Ryan Roden-Corrent 2016-03-24 22:49:46 -04:00
parent fa75608873
commit 0a05828da3
8 changed files with 93 additions and 25 deletions

View File

@ -34,6 +34,8 @@ controller_base::controller_base(
: game_config_(game_config)
, key_()
, scrolling_(false)
, scrollx_(0)
, scrolly_(0)
, joystick_manager_()
{
}
@ -129,11 +131,10 @@ void controller_base::process_keyup_event(const SDL_Event& /*event*/) {
//no action by default
}
bool controller_base::handle_scroll(CKey& key, int mousex, int mousey, int mouse_flags, double x_axis, double y_axis)
bool controller_base::handle_scroll(int mousex, int mousey, int mouse_flags, double x_axis, double y_axis)
{
bool mouse_in_window = (SDL_GetAppState() & SDL_APPMOUSEFOCUS) != 0
|| preferences::get("scroll_when_mouse_outside", true);
bool keyboard_focus = have_keyboard_focus();
int scroll_speed = preferences::scroll_speed();
int dx = 0, dy = 0;
int scroll_threshold = (preferences::mouse_scroll_enabled())
@ -143,26 +144,24 @@ bool controller_base::handle_scroll(CKey& key, int mousex, int mousey, int mouse
scroll_threshold = 0;
}
}
if ((key[SDLK_UP] && keyboard_focus) ||
(mousey < scroll_threshold && mouse_in_window))
{
dy -= scroll_speed;
}
if ((key[SDLK_DOWN] && keyboard_focus) ||
(mousey > get_display().h() - scroll_threshold && mouse_in_window))
{
dy += scroll_speed;
}
if ((key[SDLK_LEFT] && keyboard_focus) ||
(mousex < scroll_threshold && mouse_in_window))
{
dx -= scroll_speed;
}
if ((key[SDLK_RIGHT] && keyboard_focus) ||
(mousex > get_display().w() - scroll_threshold && mouse_in_window))
{
dx += scroll_speed;
// scroll with keyboard
dx += scrollx_ * scroll_speed;
dy += scrolly_ * scroll_speed;
// scroll if mouse is placed near the edge of the screen
if (mouse_in_window) {
if (mousey < scroll_threshold)
dy -= scroll_speed;
if (mousey > get_display().h() - scroll_threshold)
dy += scroll_speed;
if (mousex < scroll_threshold)
dx -= scroll_speed;
if (mousex > get_display().w() - scroll_threshold)
dx += scroll_speed;
}
// scroll with middle-mouse if enabled
if ((mouse_flags & SDL_BUTTON_MMASK) != 0 && preferences::middle_click_scrolls()) {
const map_location original_loc = get_mouse_handler_base().get_scroll_start();
@ -186,6 +185,7 @@ bool controller_base::handle_scroll(CKey& key, int mousex, int mousey, int mouse
}
}
// scroll with joystick
dx += round_double( x_axis * scroll_speed);
dy += round_double( y_axis * scroll_speed);
@ -239,7 +239,7 @@ void controller_base::play_slice(bool is_delay_enabled)
mousey += values.second * 10;
SDL_WarpMouse(mousex, mousey);
*/
scrolling_ = handle_scroll(key, mousex, mousey, mouse_flags, joystickx, joysticky);
scrolling_ = handle_scroll(mousex, mousey, mouse_flags, joystickx, joysticky);
map_location highlighted_hex = get_display().mouseover_hex();
@ -342,3 +342,11 @@ const config& controller_base::get_theme(const config& game_config, std::string
static config empty;
return empty;
}
void controller_base::keyboard_scroll(int x, int y)
{
if (have_keyboard_focus()) {
scrollx_ += x;
scrolly_ += y;
}
}

View File

@ -64,6 +64,8 @@ public:
void play_slice(bool is_delay_enabled = true);
static const config &get_theme(const config& game_config, std::string theme_name);
void keyboard_scroll(int x, int y);
protected:
virtual bool is_browsing() const
{ return false; }
@ -105,7 +107,7 @@ protected:
* @see scrolling_, which is set if the display is being scrolled
* @return true when there was any scrolling, false otherwise
*/
bool handle_scroll(CKey& key, int mousex, int mousey, int mouse_flags, double joystickx, double joysticky);
bool handle_scroll(int mousex, int mousey, int mouse_flags, double joystickx, double joysticky);
/**
* Process mouse- and keypress-events from SDL.
@ -141,6 +143,8 @@ protected:
const config& game_config_;
CKey key_;
bool scrolling_;
int scrollx_;
int scrolly_;
joystick_manager joystick_manager_;
};

View File

@ -74,9 +74,47 @@ static void event_execute(const SDL_Event& event, command_executor* executor);
bool command_executor::execute_command(const hotkey_command& cmd, int /*index*/, HOTKEY_EVENT_TYPE type)
{
if (type == HOTKEY_EVENT_RELEASE)
return false; // nothing responds to a release yet
if (type == HOTKEY_EVENT_RELEASE) {
switch(cmd.id) {
// release a scroll key, un-apply scrolling in the given direction
case HOTKEY_SCROLL_UP:
keyboard_scroll(0, 1);
break;
case HOTKEY_SCROLL_DOWN:
keyboard_scroll(0, -1);
break;
case HOTKEY_SCROLL_LEFT:
keyboard_scroll(1, 0);
break;
case HOTKEY_SCROLL_RIGHT:
keyboard_scroll(-1, 0);
break;
default:
return false; // nothing else handles a hotkey release
}
return true;
}
// special handling for scroll keys, which do not handle repeat
if (type == HOTKEY_EVENT_PRESS) {
switch(cmd.id) {
case HOTKEY_SCROLL_UP:
keyboard_scroll(0, -1);
return true;
case HOTKEY_SCROLL_DOWN:
keyboard_scroll(0, 1);
return true;
case HOTKEY_SCROLL_LEFT:
keyboard_scroll(-1, 0);
return true;
case HOTKEY_SCROLL_RIGHT:
keyboard_scroll(1, 0);
return true;
}
}
// everything following responds to a press or repeat, but not release
switch(cmd.id) {
case HOTKEY_CYCLE_UNITS:
cycle_units();

View File

@ -108,6 +108,7 @@ public:
virtual void left_mouse_click() {}
virtual void right_mouse_click() {}
virtual void toggle_accelerated_speed() {}
virtual void keyboard_scroll(int /*x*/, int /*y*/) {}
virtual void lua_console();
virtual void zoom_in() {}
virtual void zoom_out() {}

View File

@ -35,6 +35,10 @@ namespace {
hotkey::hk_scopes scope_main(1 << hotkey::SCOPE_MAIN_MENU);
// this contains all static hotkeys
hotkey::hotkey_command_temp hotkey_list_[] = {
{ hotkey::HOTKEY_SCROLL_UP, "scroll-up", N_("Scroll Up"), false, scope_game | scope_editor, "" },
{ hotkey::HOTKEY_SCROLL_DOWN, "scroll-down", N_("Scroll Down"), false, scope_game | scope_editor, "" },
{ hotkey::HOTKEY_SCROLL_LEFT, "scroll-left", N_("Scroll Left"), false, scope_game | scope_editor, "" },
{ hotkey::HOTKEY_SCROLL_RIGHT, "scroll-right", N_("Scroll Right"), false, scope_game | scope_editor, "" },
{ hotkey::HOTKEY_CANCEL, N_("cancel"), N_("Cancel"), false, scope_game | scope_editor | scope_main, "" },
{ hotkey::HOTKEY_SELECT_HEX, "selecthex", N_("Select Hex"), false, scope_game, "" },

View File

@ -67,6 +67,9 @@ enum HOTKEY_COMMAND {
HOTKEY_SELECT_HEX, HOTKEY_DESELECT_HEX,
HOTKEY_MOVE_ACTION, HOTKEY_SELECT_AND_ACTION,
// Camera movement
HOTKEY_SCROLL_UP, HOTKEY_SCROLL_DOWN, HOTKEY_SCROLL_LEFT, HOTKEY_SCROLL_RIGHT,
// Dialog control
HOTKEY_CANCEL, HOTKEY_OKAY,

View File

@ -218,6 +218,11 @@ void play_controller::hotkey_handler::toggle_accelerated_speed()
}
}
void play_controller::hotkey_handler::keyboard_scroll(int x, int y)
{
play_controller_.keyboard_scroll(x, y);
}
bool play_controller::hotkey_handler::execute_command(const hotkey::hotkey_command& cmd, int index, hotkey::HOTKEY_EVENT_TYPE type)
{
hotkey::HOTKEY_COMMAND command = cmd.id;
@ -302,6 +307,10 @@ bool play_controller::hotkey_handler::can_execute_command(const hotkey::hotkey_c
case hotkey::HOTKEY_SAVE_REPLAY:
case hotkey::HOTKEY_LABEL_SETTINGS:
case hotkey::LUA_CONSOLE:
case hotkey::HOTKEY_SCROLL_UP:
case hotkey::HOTKEY_SCROLL_DOWN:
case hotkey::HOTKEY_SCROLL_LEFT:
case hotkey::HOTKEY_SCROLL_RIGHT:
return true;
// Commands that have some preconditions:

View File

@ -117,6 +117,7 @@ public:
virtual void toggle_grid();
virtual void search();
virtual void toggle_accelerated_speed();
virtual void keyboard_scroll(int x, int y);
virtual void replay_skip_animation() override
{ return play_controller_.toggle_skipping_replay(); }