diff --git a/src/lang/english.txt b/src/lang/english.txt index dee24733bc..eb565c0664 100644 --- a/src/lang/english.txt +++ b/src/lang/english.txt @@ -1321,6 +1321,12 @@ STR_CONFIG_SETTING_SNAP_RADIUS :{LTBLUE}Window STR_CONFIG_SETTING_SNAP_RADIUS_DISABLED :{LTBLUE}Window snap radius: {ORANGE}disabled STR_CONFIG_SETTING_SOFT_LIMIT :{LTBLUE}Maximum number of non-sticky windows: {ORANGE}{STRING1} STR_CONFIG_SETTING_SOFT_LIMIT_DISABLED :{LTBLUE}Maximum number of non-sticky windows: {ORANGE}disabled +STR_CONFIG_SETTING_ZOOM_MIN :{LTBLUE}Maximum zoom in level: {ORANGE}{STRING1} +STR_CONFIG_SETTING_ZOOM_MAX :{LTBLUE}Maximum zoom out level: {ORANGE}{STRING1} +STR_CONFIG_SETTING_ZOOM_LVL_MIN :Normal +STR_CONFIG_SETTING_ZOOM_LVL_OUT_2X :2x +STR_CONFIG_SETTING_ZOOM_LVL_OUT_4X :4x +STR_CONFIG_SETTING_ZOOM_LVL_OUT_8X :8x STR_CONFIG_SETTING_TOWN_GROWTH :{LTBLUE}Town growth speed: {ORANGE}{STRING1} STR_CONFIG_SETTING_TOWN_GROWTH_NONE :None STR_CONFIG_SETTING_TOWN_GROWTH_SLOW :Slow diff --git a/src/main_gui.cpp b/src/main_gui.cpp index 4d6f1a1702..1d57f51aaf 100644 --- a/src/main_gui.cpp +++ b/src/main_gui.cpp @@ -148,7 +148,7 @@ bool DoZoomInOutWindow(ZoomStateChange how, Window *w) break; case ZOOM_IN: - if (vp->zoom == ZOOM_LVL_MIN) return false; + if (vp->zoom <= _settings_client.gui.zoom_min) return false; vp->zoom = (ZoomLevel)((int)vp->zoom - 1); vp->virtual_width >>= 1; vp->virtual_height >>= 1; @@ -160,7 +160,7 @@ bool DoZoomInOutWindow(ZoomStateChange how, Window *w) w->viewport->follow_vehicle = INVALID_VEHICLE; break; case ZOOM_OUT: - if (vp->zoom == ZOOM_LVL_MAX) return false; + if (vp->zoom >= _settings_client.gui.zoom_max) return false; vp->zoom = (ZoomLevel)((int)vp->zoom + 1); w->viewport->scrollpos_x -= vp->virtual_width >> 1; @@ -188,7 +188,7 @@ void ZoomInOrOutToCursorWindow(bool in, Window *w) if (_game_mode != GM_MENU) { ViewPort *vp = w->viewport; - if ((in && vp->zoom == ZOOM_LVL_MIN) || (!in && vp->zoom == ZOOM_LVL_MAX)) return; + if ((in && vp->zoom <= _settings_client.gui.zoom_min) || (!in && vp->zoom >= _settings_client.gui.zoom_max)) return; Point pt = GetTileZoomCenterWindow(in, w); if (pt.x != -1) { @@ -313,7 +313,7 @@ struct MainWindow : Window case GHK_CENTER_ZOOM: { Point pt = GetTileBelowCursor(); if (pt.x != -1) { - bool instant = (num == GHK_CENTER_ZOOM && this->viewport->zoom != ZOOM_LVL_MIN); + bool instant = (num == GHK_CENTER_ZOOM && this->viewport->zoom != _settings_client.gui.zoom_min); if (num == GHK_CENTER_ZOOM) MaxZoomInOut(ZOOM_IN, this); ScrollMainWindowTo(pt.x, pt.y, -1, instant); } diff --git a/src/saveload/misc_sl.cpp b/src/saveload/misc_sl.cpp index ccfc7a2d36..9ca8067016 100644 --- a/src/saveload/misc_sl.cpp +++ b/src/saveload/misc_sl.cpp @@ -56,6 +56,10 @@ void ResetViewportAfterLoadGame() vp->virtual_width = ScaleByZoom(vp->width, vp->zoom); vp->virtual_height = ScaleByZoom(vp->height, vp->zoom); + /* Ensure zoom level is allowed */ + while (vp->zoom < _settings_client.gui.zoom_min) DoZoomInOutWindow(ZOOM_OUT, w); + while (vp->zoom > _settings_client.gui.zoom_max) DoZoomInOutWindow(ZOOM_IN, w); + DoZoomInOutWindow(ZOOM_NONE, w); // update button status MarkWholeScreenDirty(); } diff --git a/src/settings.cpp b/src/settings.cpp index 0cffb63609..28192a4d76 100644 --- a/src/settings.cpp +++ b/src/settings.cpp @@ -894,6 +894,13 @@ static bool InvalidateVehTimetableWindow(int32 p1) return true; } +static bool ZoomMinMaxChanged(int32 p1) +{ + extern void ConstrainAllViewportsZoom(); + ConstrainAllViewportsZoom(); + return true; +} + /** * Update any possible saveload window and delete any newgrf dialogue as * its widget parts might change. Reinit all windows as it allows access to the diff --git a/src/settings_gui.cpp b/src/settings_gui.cpp index 2a6c616092..019fd34908 100644 --- a/src/settings_gui.cpp +++ b/src/settings_gui.cpp @@ -1358,6 +1358,8 @@ static SettingEntry _settings_ui_display[] = { SettingEntry("gui.show_track_reservation"), SettingEntry("gui.expenses_layout"), SettingEntry("gui.smallmap_land_colour"), + SettingEntry("gui.zoom_min"), + SettingEntry("gui.zoom_max"), }; /** Display options sub-page */ static SettingsPage _settings_ui_display_page = {_settings_ui_display, lengthof(_settings_ui_display)}; diff --git a/src/settings_type.h b/src/settings_type.h index 9fe5502404..d23011eb7c 100644 --- a/src/settings_type.h +++ b/src/settings_type.h @@ -17,6 +17,7 @@ #include "transport_type.h" #include "network/core/config.h" #include "company_type.h" +#include "zoom_type.h" #include "openttd.h" /** Available industry map generation densities. */ @@ -79,6 +80,8 @@ struct GUISettings { uint8 statusbar_pos; ///< position of statusbar, 0=left, 1=center, 2=right uint8 window_snap_radius; ///< windows snap at each other if closer than this uint8 window_soft_limit; ///< soft limit of maximum number of non-stickied non-vital windows (0 = no limit) + ZoomLevelByte zoom_min; ///< minimum zoom out level + ZoomLevelByte zoom_max; ///< maximum zoom out level bool disable_unsuitable_building; ///< disable infrastructure building when no suitable vehicles are available byte autosave; ///< how often should we do autosaves? bool threaded_saves; ///< should we do threaded saves? diff --git a/src/table/settings.ini b/src/table/settings.ini index c19f718e25..3d57f868fa 100644 --- a/src/table/settings.ini +++ b/src/table/settings.ini @@ -40,6 +40,7 @@ static bool InvalidateIndustryViewWindow(int32 p1); static bool InvalidateAISettingsWindow(int32 p1); static bool RedrawTownAuthority(int32 p1); extern bool UpdateNewGRFConfigPalette(int32 p1); +static bool ZoomMinMaxChanged(int32 p1); #ifdef ENABLE_NETWORK static bool UpdateClientName(int32 p1); @@ -2071,6 +2072,30 @@ max = 255 interval = 1 str = STR_CONFIG_SETTING_SOFT_LIMIT +[SDTC_VAR] +var = gui.zoom_min +type = SLE_UINT8 +flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC +guiflags = SGF_MULTISTRING +def = ZOOM_LVL_MIN +min = ZOOM_LVL_MIN +max = ZOOM_LVL_MIN +str = STR_CONFIG_SETTING_ZOOM_MIN +strval = STR_CONFIG_SETTING_ZOOM_LVL_MIN +proc = ZoomMinMaxChanged + +[SDTC_VAR] +var = gui.zoom_max +type = SLE_UINT8 +flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC +guiflags = SGF_MULTISTRING +def = ZOOM_LVL_MAX +min = ZOOM_LVL_OUT_2X +max = ZOOM_LVL_MAX +str = STR_CONFIG_SETTING_ZOOM_MAX +strval = STR_CONFIG_SETTING_ZOOM_LVL_OUT_2X +proc = ZoomMinMaxChanged + [SDTC_BOOL] var = gui.population_in_label flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC diff --git a/src/viewport.cpp b/src/viewport.cpp index 7bcd83d3ef..b42acfdfc3 100644 --- a/src/viewport.cpp +++ b/src/viewport.cpp @@ -187,7 +187,7 @@ void InitializeWindowViewport(Window *w, int x, int y, vp->width = width; vp->height = height; - vp->zoom = zoom; + vp->zoom = static_cast(Clamp(zoom, _settings_client.gui.zoom_min, _settings_client.gui.zoom_max)); vp->virtual_width = ScaleByZoom(width, zoom); vp->virtual_height = ScaleByZoom(height, zoom); @@ -459,10 +459,10 @@ Point GetTileZoomCenterWindow(bool in, Window * w) */ void HandleZoomMessage(Window *w, const ViewPort *vp, byte widget_zoom_in, byte widget_zoom_out) { - w->SetWidgetDisabledState(widget_zoom_in, vp->zoom == ZOOM_LVL_MIN); + w->SetWidgetDisabledState(widget_zoom_in, vp->zoom <= _settings_client.gui.zoom_min); w->SetWidgetDirty(widget_zoom_in); - w->SetWidgetDisabledState(widget_zoom_out, vp->zoom == ZOOM_LVL_MAX); + w->SetWidgetDisabledState(widget_zoom_out, vp->zoom >= _settings_client.gui.zoom_max); w->SetWidgetDirty(widget_zoom_out); } @@ -1645,6 +1645,20 @@ void MarkAllViewportsDirty(int left, int top, int right, int bottom) } } +void ConstrainAllViewportsZoom() +{ + Window *w; + FOR_ALL_WINDOWS_FROM_FRONT(w) { + if (w->viewport == NULL) continue; + + ZoomLevel zoom = static_cast(Clamp(w->viewport->zoom, _settings_client.gui.zoom_min, _settings_client.gui.zoom_max)); + if (zoom != w->viewport->zoom) { + while (w->viewport->zoom < zoom) DoZoomInOutWindow(ZOOM_OUT, w); + while (w->viewport->zoom > zoom) DoZoomInOutWindow(ZOOM_IN, w); + } + } +} + /** * Mark a tile given by its index dirty for repaint. * @param tile The tile to mark dirty.