Showing with 150 additions and 35 deletions.
  1. +67 −5 src/wui/interactive_base.cc
  2. +76 −22 src/wui/interactive_gamebase.cc
  3. +2 −2 src/wui/interactive_gamebase.h
  4. +1 −1 src/wui/interactive_player.cc
  5. +3 −4 src/wui/mapview.cc
  6. +1 −1 src/wui/mapview.h
@@ -1368,7 +1368,8 @@ bool InteractiveBase::handle_key(bool const down, SDL_Keysym const code) {
}

// If one of the arrow keys is pressed, scroll this distance
constexpr uint32_t kScrollDistance = 10;
uint32_t kScrollDistanceY = g_gr->get_yres() / 4;
uint32_t kScrollDistanceX = g_gr->get_xres() / 4;

if (down) {
switch (code.sym) {
@@ -1379,32 +1380,93 @@ bool InteractiveBase::handle_key(bool const down, SDL_Keysym const code) {
}
FALLS_THROUGH;
case SDLK_UP:
map_view_.pan_by(Vector2i(0, -kScrollDistance));
if (get_key_state(SDL_SCANCODE_LEFT)) {
map_view_.pan_by(
Vector2i(-kScrollDistanceX, -kScrollDistanceY), MapView::Transition::Smooth);
} else if (get_key_state(SDL_SCANCODE_RIGHT)) {
map_view_.pan_by(
Vector2i(kScrollDistanceX, -kScrollDistanceY), MapView::Transition::Smooth);
} else {
map_view_.pan_by(Vector2i(0, -kScrollDistanceY), MapView::Transition::Smooth);
}
return true;
case SDLK_KP_2:
if (SDL_GetModState() & KMOD_NUM) {
break;
}
FALLS_THROUGH;
case SDLK_DOWN:
map_view_.pan_by(Vector2i(0, kScrollDistance));
if (get_key_state(SDL_SCANCODE_LEFT)) {
map_view_.pan_by(
Vector2i(-kScrollDistanceX, kScrollDistanceY), MapView::Transition::Smooth);
} else if (get_key_state(SDL_SCANCODE_RIGHT)) {
map_view_.pan_by(
Vector2i(kScrollDistanceX, kScrollDistanceY), MapView::Transition::Smooth);
} else {
map_view_.pan_by(Vector2i(0, kScrollDistanceY), MapView::Transition::Smooth);
}
return true;
case SDLK_KP_4:
if (SDL_GetModState() & KMOD_NUM) {
break;
}
FALLS_THROUGH;
case SDLK_LEFT:
map_view_.pan_by(Vector2i(-kScrollDistance, 0));
if (get_key_state(SDL_SCANCODE_UP)) {
map_view_.pan_by(
Vector2i(-kScrollDistanceX, -kScrollDistanceY), MapView::Transition::Smooth);
} else if (get_key_state(SDL_SCANCODE_DOWN)) {
map_view_.pan_by(
Vector2i(-kScrollDistanceX, kScrollDistanceY), MapView::Transition::Smooth);
} else {
map_view_.pan_by(Vector2i(-kScrollDistanceX, 0), MapView::Transition::Smooth);
}
return true;
case SDLK_KP_6:
if (SDL_GetModState() & KMOD_NUM) {
break;
}
FALLS_THROUGH;
case SDLK_RIGHT:
map_view_.pan_by(Vector2i(kScrollDistance, 0));
if (get_key_state(SDL_SCANCODE_UP)) {
map_view_.pan_by(
Vector2i(kScrollDistanceX, -kScrollDistanceY), MapView::Transition::Smooth);
} else if (get_key_state(SDL_SCANCODE_DOWN)) {
map_view_.pan_by(
Vector2i(kScrollDistanceX, kScrollDistanceY), MapView::Transition::Smooth);
} else {
map_view_.pan_by(Vector2i(kScrollDistanceX, 0), MapView::Transition::Smooth);
}
return true;
case SDLK_KP_1:
if (SDL_GetModState() & KMOD_NUM) {
break;
}
map_view_.pan_by(
Vector2i(-kScrollDistanceX, kScrollDistanceY), MapView::Transition::Smooth);
return true;
case SDLK_KP_3:
if (SDL_GetModState() & KMOD_NUM) {
break;
}
map_view_.pan_by(
Vector2i(kScrollDistanceX, kScrollDistanceY), MapView::Transition::Smooth);
return true;
case SDLK_KP_7:
if (SDL_GetModState() & KMOD_NUM) {
break;
}
map_view_.pan_by(
Vector2i(-kScrollDistanceX, -kScrollDistanceY), MapView::Transition::Smooth);
return true;
case SDLK_KP_9:
if (SDL_GetModState() & KMOD_NUM) {
break;
}
map_view_.pan_by(
Vector2i(kScrollDistanceX, -kScrollDistanceY), MapView::Transition::Smooth);
return true;

#ifndef NDEBUG // only in debug builds
case SDLK_F6:
GameChatMenu::create_script_console(
@@ -282,12 +282,24 @@ void InteractiveGameBase::rebuild_gamespeed_menu() {
void InteractiveGameBase::gamespeed_menu_selected(GameSpeedEntry entry) {
switch (entry) {
case GameSpeedEntry::kIncrease: {
increase_gamespeed();
if (SDL_GetModState() & KMOD_SHIFT) {
increase_gamespeed(250);
} else if (SDL_GetModState() & KMOD_CTRL) {
increase_gamespeed(10000);
} else {
increase_gamespeed(1000);
}
// Keep the window open so that the player can click this multiple times
gamespeedmenu_.toggle();
} break;
case GameSpeedEntry::kDecrease: {
decrease_gamespeed();
if (SDL_GetModState() & KMOD_SHIFT) {
decrease_gamespeed(250);
} else if (SDL_GetModState() & KMOD_CTRL) {
decrease_gamespeed(10000);
} else {
decrease_gamespeed(1000);
}
// Keep the window open so that the player can click this multiple times
gamespeedmenu_.toggle();
} break;
@@ -299,16 +311,54 @@ void InteractiveGameBase::gamespeed_menu_selected(GameSpeedEntry entry) {
}
}

void InteractiveGameBase::increase_gamespeed() {
void InteractiveGameBase::increase_gamespeed(uint32_t speed) {
if (GameController* const ctrl = get_game()->game_controller()) {
ctrl->set_desired_speed(ctrl->desired_speed() + 1000);
uint32_t const current_speed = ctrl->desired_speed();
switch (speed) {
case 250:
ctrl->set_desired_speed(current_speed + speed);
break;
case 1000:
if (current_speed < 1000) {
ctrl->set_desired_speed(1000);
} else {
ctrl->set_desired_speed(current_speed - current_speed % speed + speed);
}
break;
case 10000:
ctrl->set_desired_speed(
current_speed >= speed ? current_speed - current_speed % speed + speed : speed);
break;
default:
break;
}
}
}

void InteractiveGameBase::decrease_gamespeed() {
void InteractiveGameBase::decrease_gamespeed(uint32_t speed) {
if (GameController* const ctrl = get_game()->game_controller()) {
uint32_t const speed = ctrl->desired_speed();
ctrl->set_desired_speed(1000 < speed ? speed - 1000 : 0);
uint32_t const current_speed = ctrl->desired_speed();
switch (speed) {
case 250:
ctrl->set_desired_speed(current_speed > speed ? current_speed - speed : 0);
break;
case 1000:
if (current_speed >= 2000) {
ctrl->set_desired_speed(current_speed - current_speed % speed - speed);
} else if (current_speed > 1000) {
ctrl->set_desired_speed(1000);
} else {
ctrl->set_desired_speed(0);
}
break;
case 10000:
ctrl->set_desired_speed(
current_speed > speed ? current_speed - current_speed % speed - speed : 0);
break;
default:
ctrl->set_desired_speed(1000);
break;
}
}
}

@@ -327,26 +377,30 @@ bool InteractiveGameBase::handle_key(bool down, SDL_Keysym code) {

if (down) {
switch (code.sym) {
case SDLK_KP_9:
if (code.mod & KMOD_NUM) {
break;
}
FALLS_THROUGH;
case SDLK_PAGEUP:
increase_gamespeed();
if (code.mod & KMOD_SHIFT) {
increase_gamespeed(250);
} else if (code.mod & KMOD_CTRL) {
increase_gamespeed(10000);
} else {
increase_gamespeed(1000);
}
return true;

case SDLK_PAUSE:
toggle_game_paused();
return true;

case SDLK_KP_3:
if (code.mod & KMOD_NUM) {
break;
if (code.mod & KMOD_SHIFT) {
decrease_gamespeed(0);
} else {
toggle_game_paused();
}
FALLS_THROUGH;
return true;
case SDLK_PAGEDOWN:
decrease_gamespeed();
if (code.mod & KMOD_SHIFT) {
decrease_gamespeed(250);
} else if (code.mod & KMOD_CTRL) {
decrease_gamespeed(10000);
} else {
decrease_gamespeed(1000);
}
return true;
case SDLK_ESCAPE:
InteractiveGameBase::toggle_mainmenu();
@@ -154,9 +154,9 @@ class InteractiveGameBase : public InteractiveBase {
void rebuild_gamespeed_menu();

// Increases the gamespeed
void increase_gamespeed();
void increase_gamespeed(uint32_t speed);
// Decreases the gamespeed
void decrease_gamespeed();
void decrease_gamespeed(uint32_t speed);
// Pauses / Unpauses the game and calls rebuild_gamespeed_menu
void toggle_game_paused();

@@ -623,7 +623,7 @@ bool InteractivePlayer::handle_key(bool const down, SDL_Keysym const code) {
set_display_flag(dfShowWorkareaOverlap, !get_display_flag(dfShowWorkareaOverlap));
return true;

case SDLK_KP_7:
case SDLK_KP_5:
if (code.mod & KMOD_NUM)
break;
FALLS_THROUGH;
@@ -450,12 +450,11 @@ const MapView::View& MapView::view() const {
return view_;
}

void MapView::pan_by(Vector2i delta_pixels) {
void MapView::pan_by(Vector2i delta_pixels, const Transition& transition) {
if (is_animating()) {
return;
}
set_view(
{view_.viewpoint + delta_pixels.cast<float>() * view_.zoom, view_.zoom}, Transition::Jump);
set_view({view_.viewpoint + delta_pixels.cast<float>() * view_.zoom, view_.zoom}, transition);
}

void MapView::stop_dragging() {
@@ -496,7 +495,7 @@ bool MapView::handle_mousemove(

if (dragging_) {
if (state & SDL_BUTTON(SDL_BUTTON_RIGHT)) {
pan_by(Vector2i(xdiff, ydiff));
pan_by(Vector2i(xdiff, ydiff), Transition::Jump);
} else {
stop_dragging();
}
@@ -150,7 +150,7 @@ class MapView : public UI::Panel {
void mouse_to_pixel(const Vector2i& pixel, const Transition& transition);

// Move the view by 'delta_pixels'.
void pan_by(Vector2i delta_pixels);
void pan_by(Vector2i delta_pixels, const Transition& transition);

// The current view area visible in the MapView in map pixel coordinates.
// The returned value always has 'x' > 0 and 'y' > 0.