diff options
author | peter1138 <peter1138@openttd.org> | 2011-11-24 12:38:48 +0000 |
---|---|---|
committer | peter1138 <peter1138@openttd.org> | 2011-11-24 12:38:48 +0000 |
commit | 81598273e9b6bb2ee20ebdd82f3d4646a02999ba (patch) | |
tree | 2d13cc93dc84f2d99cff6fc2bb02214d4453f033 | |
parent | 15d0a22aac6b90a2055e68d019cab4350376a8fd (diff) | |
download | openttd-81598273e9b6bb2ee20ebdd82f3d4646a02999ba.tar.xz |
(svn r23316) -Feature: Add ability to zoom in to 2x and 4x level.
-rw-r--r-- | src/aircraft_cmd.cpp | 7 | ||||
-rw-r--r-- | src/aircraft_gui.cpp | 11 | ||||
-rw-r--r-- | src/depot_gui.cpp | 11 | ||||
-rw-r--r-- | src/fontcache.cpp | 1 | ||||
-rw-r--r-- | src/gfx.cpp | 172 | ||||
-rw-r--r-- | src/gfx_func.h | 5 | ||||
-rw-r--r-- | src/landscape.h | 7 | ||||
-rw-r--r-- | src/lang/english.txt | 4 | ||||
-rw-r--r-- | src/newgrf_debug_gui.cpp | 2 | ||||
-rw-r--r-- | src/roadveh_cmd.cpp | 3 | ||||
-rw-r--r-- | src/saveload/afterload.cpp | 7 | ||||
-rw-r--r-- | src/saveload/misc_sl.cpp | 9 | ||||
-rw-r--r-- | src/screenshot.cpp | 2 | ||||
-rw-r--r-- | src/ship_cmd.cpp | 7 | ||||
-rw-r--r-- | src/ship_gui.cpp | 11 | ||||
-rw-r--r-- | src/smallmap_gui.cpp | 14 | ||||
-rw-r--r-- | src/sound.cpp | 2 | ||||
-rw-r--r-- | src/sprite.cpp | 7 | ||||
-rw-r--r-- | src/spritecache.h | 10 | ||||
-rw-r--r-- | src/spriteloader/grf.cpp | 18 | ||||
-rw-r--r-- | src/spriteloader/png.cpp | 19 | ||||
-rw-r--r-- | src/table/misc_settings.ini | 4 | ||||
-rw-r--r-- | src/table/settings.ini | 4 | ||||
-rw-r--r-- | src/texteff.cpp | 4 | ||||
-rw-r--r-- | src/train_cmd.cpp | 5 | ||||
-rw-r--r-- | src/vehicle.cpp | 18 | ||||
-rw-r--r-- | src/vehicle_gui.cpp | 7 | ||||
-rw-r--r-- | src/viewport.cpp | 60 | ||||
-rw-r--r-- | src/zoom_type.h | 30 |
29 files changed, 332 insertions, 129 deletions
diff --git a/src/aircraft_cmd.cpp b/src/aircraft_cmd.cpp index 861a88a08..de0182782 100644 --- a/src/aircraft_cmd.cpp +++ b/src/aircraft_cmd.cpp @@ -35,6 +35,7 @@ #include "engine_base.h" #include "core/random_func.hpp" #include "core/backup_type.hpp" +#include "zoom_func.h" #include "table/strings.h" @@ -190,7 +191,7 @@ void DrawAircraftEngine(int left, int right, int preferred_x, int y, EngineID en { SpriteID sprite = GetAircraftIcon(engine, image_type); const Sprite *real_sprite = GetSprite(sprite, ST_NORMAL); - preferred_x = Clamp(preferred_x, left - real_sprite->x_offs, right - real_sprite->width - real_sprite->x_offs); + preferred_x = Clamp(preferred_x, left - UnScaleByZoom(real_sprite->x_offs, ZOOM_LVL_GUI), right - UnScaleByZoom(real_sprite->width, ZOOM_LVL_GUI) - UnScaleByZoom(real_sprite->x_offs, ZOOM_LVL_GUI)); DrawSprite(sprite, pal, preferred_x, y); if (!(AircraftVehInfo(engine)->subtype & AIR_CTOL)) { @@ -210,8 +211,8 @@ void GetAircraftSpriteSize(EngineID engine, uint &width, uint &height, EngineIma { const Sprite *spr = GetSprite(GetAircraftIcon(engine, image_type), ST_NORMAL); - width = spr->width; - height = spr->height; + width = UnScaleByZoom(spr->width, ZOOM_LVL_GUI); + height = UnScaleByZoom(spr->height, ZOOM_LVL_GUI); } /** diff --git a/src/aircraft_gui.cpp b/src/aircraft_gui.cpp index 360c02a7f..faefaa907 100644 --- a/src/aircraft_gui.cpp +++ b/src/aircraft_gui.cpp @@ -17,6 +17,7 @@ #include "vehicle_func.h" #include "window_gui.h" #include "spritecache.h" +#include "zoom_func.h" #include "table/strings.h" @@ -83,7 +84,9 @@ void DrawAircraftImage(const Vehicle *v, int left, int right, int y, VehicleID s SpriteID sprite = v->GetImage(rtl ? DIR_E : DIR_W, image_type); const Sprite *real_sprite = GetSprite(sprite, ST_NORMAL); - int x = rtl ? right - real_sprite->width - real_sprite->x_offs : left - real_sprite->x_offs; + int width = UnScaleByZoom(real_sprite->width, ZOOM_LVL_GUI); + int x_offs = UnScaleByZoom(real_sprite->x_offs, ZOOM_LVL_GUI); + int x = rtl ? right - width - x_offs : left - x_offs; bool helicopter = v->subtype == AIR_HELICOPTER; PaletteID pal = (v->vehstatus & VS_CRASHED) ? PALETTE_CRASH : GetVehiclePalette(v); @@ -95,8 +98,8 @@ void DrawAircraftImage(const Vehicle *v, int left, int right, int y, VehicleID s DrawSprite(rotor_sprite, PAL_NONE, x, y + 5); } if (v->index == selection) { - x += real_sprite->x_offs; - y += real_sprite->y_offs + 10 - (helicopter ? 5 : 0); - DrawFrameRect(x - 1, y - 1, x + real_sprite->width + 1, y + real_sprite->height + (helicopter ? 5 : 0) + 1, COLOUR_WHITE, FR_BORDERONLY); + x += x_offs; + y += UnScaleByZoom(real_sprite->y_offs, ZOOM_LVL_GUI) + 10 - (helicopter ? 5 : 0); + DrawFrameRect(x - 1, y - 1, x + width + 1, y + UnScaleByZoom(real_sprite->height, ZOOM_LVL_GUI) + (helicopter ? 5 : 0) + 1, COLOUR_WHITE, FR_BORDERONLY); } } diff --git a/src/depot_gui.cpp b/src/depot_gui.cpp index 07fd635a8..cd0b4671d 100644 --- a/src/depot_gui.cpp +++ b/src/depot_gui.cpp @@ -28,6 +28,7 @@ #include "window_gui.h" #include "vehiclelist.h" #include "order_backup.h" +#include "zoom_func.h" #include "table/strings.h" @@ -297,7 +298,7 @@ struct DepotWindow : Window { case VEH_AIRCRAFT: { const Sprite *spr = GetSprite(v->GetImage(DIR_W, EIT_IN_DEPOT), ST_NORMAL); DrawAircraftImage(v, image_left, image_right, - y + max(spr->height + spr->y_offs - 14, 0), // tall sprites needs an y offset + y + max(UnScaleByZoom(spr->height, ZOOM_LVL_GUI) + UnScaleByZoom(spr->y_offs, ZOOM_LVL_GUI) - 14, 0), // tall sprites needs an y offset this->sel, EIT_IN_DEPOT); break; } @@ -608,14 +609,14 @@ struct DepotWindow : Window { Dimension unumber = { GetDigitWidth() * 4, FONT_HEIGHT_NORMAL }; const Sprite *spr = GetSprite(SPR_FLAG_VEH_STOPPED, ST_NORMAL); - this->flag_width = spr->width + WD_FRAMERECT_RIGHT; - this->flag_height = spr->height; + this->flag_width = UnScaleByZoom(spr->width, ZOOM_LVL_GUI) + WD_FRAMERECT_RIGHT; + this->flag_height = UnScaleByZoom(spr->height, ZOOM_LVL_GUI); if (this->type == VEH_TRAIN || this->type == VEH_ROAD) { - min_height = max<uint>(unumber.height + WD_MATRIX_TOP, spr->height); + min_height = max<uint>(unumber.height + WD_MATRIX_TOP, UnScaleByZoom(spr->height, ZOOM_LVL_GUI)); this->header_width = unumber.width + this->flag_width + WD_FRAMERECT_LEFT; } else { - min_height = unumber.height + spr->height + WD_MATRIX_TOP + WD_PAR_VSEP_NORMAL + WD_MATRIX_BOTTOM; + min_height = unumber.height + UnScaleByZoom(spr->height, ZOOM_LVL_GUI) + WD_MATRIX_TOP + WD_PAR_VSEP_NORMAL + WD_MATRIX_BOTTOM; this->header_width = max<uint>(unumber.width, this->flag_width) + WD_FRAMERECT_RIGHT; } int base_width = this->count_width + this->header_width; diff --git a/src/fontcache.cpp b/src/fontcache.cpp index 2e1882147..d203a4513 100644 --- a/src/fontcache.cpp +++ b/src/fontcache.cpp @@ -14,6 +14,7 @@ #include "blitter/factory.hpp" #include "core/math_func.hpp" #include "strings_func.h" +#include "zoom_type.h" #include "table/sprites.h" #include "table/control_codes.h" diff --git a/src/gfx.cpp b/src/gfx.cpp index 17fa1c9a0..b840fed3e 100644 --- a/src/gfx.cpp +++ b/src/gfx.cpp @@ -55,7 +55,8 @@ static byte _stringwidth_table[FS_END][224]; ///< Cache containing width of ofte DrawPixelInfo *_cur_dpi; byte _colour_gradient[COLOUR_END][8]; -static void GfxMainBlitter(const Sprite *sprite, int x, int y, BlitterMode mode, const SubSprite *sub = NULL, SpriteID sprite_id = SPR_CURSOR_MOUSE); +static void GfxMainBlitterViewport(const Sprite *sprite, int x, int y, BlitterMode mode, const SubSprite *sub = NULL, SpriteID sprite_id = SPR_CURSOR_MOUSE); +static void GfxMainBlitter(const Sprite *sprite, int x, int y, BlitterMode mode, const SubSprite *sub = NULL, SpriteID sprite_id = SPR_CURSOR_MOUSE, ZoomLevel zoom = ZOOM_LVL_NORMAL); /** * Text drawing parameters, which can change while drawing a line, but are kept between multiple parts @@ -1132,53 +1133,76 @@ skip_cont:; * @return Sprite size in pixels. * @note The size assumes (0, 0) as top-left coordinate and ignores any part of the sprite drawn at the left or above that position. */ -Dimension GetSpriteSize(SpriteID sprid, Point *offset) +Dimension GetSpriteSize(SpriteID sprid, Point *offset, ZoomLevel zoom) { const Sprite *sprite = GetSprite(sprid, ST_NORMAL); if (offset != NULL) { - offset->x = sprite->x_offs; - offset->y = sprite->y_offs; + offset->x = UnScaleByZoom(sprite->x_offs, zoom); + offset->y = UnScaleByZoom(sprite->y_offs, zoom); } Dimension d; - d.width = max<int>(0, sprite->x_offs + sprite->width); - d.height = max<int>(0, sprite->y_offs + sprite->height); + d.width = max<int>(0, UnScaleByZoom(sprite->x_offs + sprite->width, zoom)); + d.height = max<int>(0, UnScaleByZoom(sprite->y_offs + sprite->height, zoom)); return d; } /** - * Draw a sprite. + * Draw a sprite in a viewport. * @param img Image number to draw * @param pal Palette to use. - * @param x Left coordinate of image - * @param y Top coordinate of image + * @param x Left coordinate of image in viewport, scaled by zoom + * @param y Top coordinate of image in viewport, scaled by zoom * @param sub If available, draw only specified part of the sprite */ -void DrawSprite(SpriteID img, PaletteID pal, int x, int y, const SubSprite *sub) +void DrawSpriteViewport(SpriteID img, PaletteID pal, int x, int y, const SubSprite *sub) { SpriteID real_sprite = GB(img, 0, SPRITE_WIDTH); if (HasBit(img, PALETTE_MODIFIER_TRANSPARENT)) { _colour_remap_ptr = GetNonSprite(GB(pal, 0, PALETTE_WIDTH), ST_RECOLOUR) + 1; - GfxMainBlitter(GetSprite(real_sprite, ST_NORMAL), x, y, BM_TRANSPARENT, sub, real_sprite); + GfxMainBlitterViewport(GetSprite(real_sprite, ST_NORMAL), x, y, BM_TRANSPARENT, sub, real_sprite); } else if (pal != PAL_NONE) { _colour_remap_ptr = GetNonSprite(GB(pal, 0, PALETTE_WIDTH), ST_RECOLOUR) + 1; - GfxMainBlitter(GetSprite(real_sprite, ST_NORMAL), x, y, BM_COLOUR_REMAP, sub, real_sprite); + GfxMainBlitterViewport(GetSprite(real_sprite, ST_NORMAL), x, y, BM_COLOUR_REMAP, sub, real_sprite); } else { - GfxMainBlitter(GetSprite(real_sprite, ST_NORMAL), x, y, BM_NORMAL, sub, real_sprite); + GfxMainBlitterViewport(GetSprite(real_sprite, ST_NORMAL), x, y, BM_NORMAL, sub, real_sprite); } } -static void GfxMainBlitter(const Sprite *sprite, int x, int y, BlitterMode mode, const SubSprite *sub, SpriteID sprite_id) +/** + * Draw a sprite, not in a viewport + * @param img Image number to draw + * @param pal Palette to use. + * @param x Left coordinate of image in pixels + * @param y Top coordinate of image in pixels + * @param sub If available, draw only specified part of the sprite + * @param zoom Zoom level of sprite + */ +void DrawSprite(SpriteID img, PaletteID pal, int x, int y, const SubSprite *sub, ZoomLevel zoom) +{ + SpriteID real_sprite = GB(img, 0, SPRITE_WIDTH); + if (HasBit(img, PALETTE_MODIFIER_TRANSPARENT)) { + _colour_remap_ptr = GetNonSprite(GB(pal, 0, PALETTE_WIDTH), ST_RECOLOUR) + 1; + GfxMainBlitter(GetSprite(real_sprite, ST_NORMAL), x, y, BM_TRANSPARENT, sub, real_sprite, zoom); + } else if (pal != PAL_NONE) { + _colour_remap_ptr = GetNonSprite(GB(pal, 0, PALETTE_WIDTH), ST_RECOLOUR) + 1; + GfxMainBlitter(GetSprite(real_sprite, ST_NORMAL), x, y, BM_COLOUR_REMAP, sub, real_sprite, zoom); + } else { + GfxMainBlitter(GetSprite(real_sprite, ST_NORMAL), x, y, BM_NORMAL, sub, real_sprite, zoom); + } +} + +static void GfxMainBlitterViewport(const Sprite *sprite, int x, int y, BlitterMode mode, const SubSprite *sub, SpriteID sprite_id) { const DrawPixelInfo *dpi = _cur_dpi; Blitter::BlitterParams bp; /* Amount of pixels to clip from the source sprite */ - int clip_left = (sub != NULL ? max(0, -sprite->x_offs + sub->left ) : 0); - int clip_top = (sub != NULL ? max(0, -sprite->y_offs + sub->top ) : 0); - int clip_right = (sub != NULL ? max(0, sprite->width - (-sprite->x_offs + sub->right + 1)) : 0); - int clip_bottom = (sub != NULL ? max(0, sprite->height - (-sprite->y_offs + sub->bottom + 1)) : 0); + int clip_left = (sub != NULL ? max(0, -sprite->x_offs + sub->left * ZOOM_LVL_BASE ) : 0); + int clip_top = (sub != NULL ? max(0, -sprite->y_offs + sub->top * ZOOM_LVL_BASE ) : 0); + int clip_right = (sub != NULL ? max(0, sprite->width - (-sprite->x_offs + (sub->right + 1) * ZOOM_LVL_BASE)) : 0); + int clip_bottom = (sub != NULL ? max(0, sprite->height - (-sprite->y_offs + (sub->bottom + 1) * ZOOM_LVL_BASE)) : 0); if (clip_left + clip_right >= sprite->width) return; if (clip_top + clip_bottom >= sprite->height) return; @@ -1269,6 +1293,110 @@ static void GfxMainBlitter(const Sprite *sprite, int x, int y, BlitterMode mode, BlitterFactoryBase::GetCurrentBlitter()->Draw(&bp, mode, dpi->zoom); } +static void GfxMainBlitter(const Sprite *sprite, int x, int y, BlitterMode mode, const SubSprite *sub, SpriteID sprite_id, ZoomLevel zoom) +{ + const DrawPixelInfo *dpi = _cur_dpi; + Blitter::BlitterParams bp; + + /* Amount of pixels to clip from the source sprite */ + int clip_left = (sub != NULL ? max(0, -sprite->x_offs + sub->left ) : 0); + int clip_top = (sub != NULL ? max(0, -sprite->y_offs + sub->top ) : 0); + int clip_right = (sub != NULL ? max(0, sprite->width - (-sprite->x_offs + sub->right + 1)) : 0); + int clip_bottom = (sub != NULL ? max(0, sprite->height - (-sprite->y_offs + sub->bottom + 1)) : 0); + + if (clip_left + clip_right >= sprite->width) return; + if (clip_top + clip_bottom >= sprite->height) return; + + /* Scale it */ + x = ScaleByZoom(x, zoom); + y = ScaleByZoom(y, zoom); + + /* Move to the correct offset */ + x += sprite->x_offs; + y += sprite->y_offs; + + /* Copy the main data directly from the sprite */ + bp.sprite = sprite->data; + bp.sprite_width = sprite->width; + bp.sprite_height = sprite->height; + bp.width = UnScaleByZoom(sprite->width - clip_left - clip_right, zoom); + bp.height = UnScaleByZoom(sprite->height - clip_top - clip_bottom, zoom); + bp.top = 0; + bp.left = 0; + bp.skip_left = UnScaleByZoomLower(clip_left, zoom); + bp.skip_top = UnScaleByZoomLower(clip_top, zoom); + + x += ScaleByZoom(bp.skip_left, zoom); + y += ScaleByZoom(bp.skip_top, zoom); + + bp.dst = dpi->dst_ptr; + bp.pitch = dpi->pitch; + bp.remap = _colour_remap_ptr; + + assert(sprite->width > 0); + assert(sprite->height > 0); + + if (bp.width <= 0) return; + if (bp.height <= 0) return; + + y -= ScaleByZoom(dpi->top, zoom); + /* Check for top overflow */ + if (y < 0) { + bp.height -= -UnScaleByZoom(y, zoom); + if (bp.height <= 0) return; + bp.skip_top += -UnScaleByZoom(y, zoom); + y = 0; + } else { + bp.top = UnScaleByZoom(y, zoom); + } + + /* Check for bottom overflow */ + y += ScaleByZoom(bp.height - dpi->height, zoom); + if (y > 0) { + bp.height -= UnScaleByZoom(y, zoom); + if (bp.height <= 0) return; + } + + x -= ScaleByZoom(dpi->left, zoom); + /* Check for left overflow */ + if (x < 0) { + bp.width -= -UnScaleByZoom(x, zoom); + if (bp.width <= 0) return; + bp.skip_left += -UnScaleByZoom(x, zoom); + x = 0; + } else { + bp.left = UnScaleByZoom(x, zoom); + } + + /* Check for right overflow */ + x += ScaleByZoom(bp.width - dpi->width, zoom); + if (x > 0) { + bp.width -= UnScaleByZoom(x, zoom); + if (bp.width <= 0) return; + } + + assert(bp.skip_left + bp.width <= UnScaleByZoom(sprite->width, zoom)); + assert(bp.skip_top + bp.height <= UnScaleByZoom(sprite->height, zoom)); + + /* We do not want to catch the mouse. However we also use that spritenumber for unknown (text) sprites. */ + if (_newgrf_debug_sprite_picker.mode == SPM_REDRAW && sprite_id != SPR_CURSOR_MOUSE) { + Blitter *blitter = BlitterFactoryBase::GetCurrentBlitter(); + void *topleft = blitter->MoveTo(bp.dst, bp.left, bp.top); + void *bottomright = blitter->MoveTo(topleft, bp.width - 1, bp.height - 1); + + void *clicked = _newgrf_debug_sprite_picker.clicked_pixel; + + if (topleft <= clicked && clicked <= bottomright) { + uint offset = (((size_t)clicked - (size_t)topleft) / (blitter->GetScreenDepth() / 8)) % bp.pitch; + if (offset < (uint)bp.width) { + _newgrf_debug_sprite_picker.sprites.Include(sprite_id); + } + } + } + + BlitterFactoryBase::GetCurrentBlitter()->Draw(&bp, mode, zoom); +} + void DoPaletteAnimations(); void GfxInitPalettes() @@ -1785,10 +1913,10 @@ void UpdateCursorSize() CursorVars *cv = &_cursor; const Sprite *p = GetSprite(GB(cv->sprite, 0, SPRITE_WIDTH), ST_NORMAL); - cv->size.y = p->height; - cv->size.x = p->width; - cv->offs.x = p->x_offs; - cv->offs.y = p->y_offs; + cv->size.y = UnScaleByZoom(p->height, ZOOM_LVL_GUI); + cv->size.x = UnScaleByZoom(p->width, ZOOM_LVL_GUI); + cv->offs.x = UnScaleByZoom(p->x_offs, ZOOM_LVL_GUI); + cv->offs.y = UnScaleByZoom(p->y_offs, ZOOM_LVL_GUI); cv->dirty = true; } diff --git a/src/gfx_func.h b/src/gfx_func.h index 8023c3ee1..2061c9310 100644 --- a/src/gfx_func.h +++ b/src/gfx_func.h @@ -88,8 +88,9 @@ static const int DRAW_STRING_BUFFER = 2048; void RedrawScreenRect(int left, int top, int right, int bottom); void GfxScroll(int left, int top, int width, int height, int xo, int yo); -Dimension GetSpriteSize(SpriteID sprid, Point *offset = NULL); -void DrawSprite(SpriteID img, PaletteID pal, int x, int y, const SubSprite *sub = NULL); +Dimension GetSpriteSize(SpriteID sprid, Point *offset = NULL, ZoomLevel zoom = ZOOM_LVL_GUI); +void DrawSpriteViewport(SpriteID img, PaletteID pal, int x, int y, const SubSprite *sub = NULL); +void DrawSprite(SpriteID img, PaletteID pal, int x, int y, const SubSprite *sub = NULL, ZoomLevel zoom = ZOOM_LVL_GUI); /** How to align the to-be drawn text. */ enum StringAlignment { diff --git a/src/landscape.h b/src/landscape.h index c1680d1be..7a3dc03a8 100644 --- a/src/landscape.h +++ b/src/landscape.h @@ -14,6 +14,7 @@ #include "core/geometry_type.hpp" #include "tile_cmd.h" +#include "zoom_type.h" static const uint SNOW_LINE_MONTHS = 12; ///< Number of months in the snow line table. static const uint SNOW_LINE_DAYS = 32; ///< Number of days in each month in the snow line table. @@ -83,8 +84,8 @@ static inline Slope GetFoundationPixelSlope(TileIndex tile, int *z) static inline Point RemapCoords(int x, int y, int z) { Point pt; - pt.x = (y - x) * 2; - pt.y = y + x - z; + pt.x = (y - x) * 2 * ZOOM_LVL_BASE; + pt.y = (y + x - z) * ZOOM_LVL_BASE; return pt; } @@ -111,7 +112,7 @@ static inline Point RemapCoords2(int x, int y) */ static inline Point InverseRemapCoords(int x, int y) { - Point pt = {(y * 2 - x) >> 2, (y * 2 + x) >> 2}; + Point pt = {(y * 2 - x) >> (2 + ZOOM_LVL_SHIFT), (y * 2 + x) >> (2 + ZOOM_LVL_SHIFT)}; return pt; } diff --git a/src/lang/english.txt b/src/lang/english.txt index eb565c066..3e33db7ee 100644 --- a/src/lang/english.txt +++ b/src/lang/english.txt @@ -1323,7 +1323,9 @@ STR_CONFIG_SETTING_SOFT_LIMIT :{LTBLUE}Maximum 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_MIN :4x +STR_CONFIG_SETTING_ZOOM_LVL_IN_2X :2x +STR_CONFIG_SETTING_ZOOM_LVL_NORMAL :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 diff --git a/src/newgrf_debug_gui.cpp b/src/newgrf_debug_gui.cpp index 46a885a6f..c5c1705f3 100644 --- a/src/newgrf_debug_gui.cpp +++ b/src/newgrf_debug_gui.cpp @@ -725,7 +725,7 @@ struct SpriteAlignerWindow : Window { spr->y_offs + (spr->height + height) / 2 - 1, }; - DrawSprite(this->current_sprite, PAL_NONE, x, y, &subspr); + DrawSprite(this->current_sprite, PAL_NONE, x, y, &subspr, ZOOM_LVL_NORMAL); break; } diff --git a/src/roadveh_cmd.cpp b/src/roadveh_cmd.cpp index ff18089a5..0198dac82 100644 --- a/src/roadveh_cmd.cpp +++ b/src/roadveh_cmd.cpp @@ -35,6 +35,7 @@ #include "company_base.h" #include "core/backup_type.hpp" #include "newgrf.h" +#include "zoom_func.h" #include "table/strings.h" @@ -151,7 +152,7 @@ void DrawRoadVehEngine(int left, int right, int preferred_x, int y, EngineID eng { SpriteID sprite = GetRoadVehIcon(engine, image_type); const Sprite *real_sprite = GetSprite(sprite, ST_NORMAL); - preferred_x = Clamp(preferred_x, left - real_sprite->x_offs, right - real_sprite->width - real_sprite->x_offs); + preferred_x = Clamp(preferred_x, left - UnScaleByZoom(real_sprite->x_offs, ZOOM_LVL_GUI), right - UnScaleByZoom(real_sprite->width, ZOOM_LVL_GUI) - UnScaleByZoom(real_sprite->x_offs, ZOOM_LVL_GUI)); DrawSprite(sprite, pal, preferred_x, y); } diff --git a/src/saveload/afterload.cpp b/src/saveload/afterload.cpp index 5b86f4d0b..d231f6912 100644 --- a/src/saveload/afterload.cpp +++ b/src/saveload/afterload.cpp @@ -2688,6 +2688,13 @@ bool AfterLoadGame() } } + if (IsSavegameVersionBefore(165)) { + /* Adjust zoom level to account for new levels */ + _saved_scrollpos_zoom = _saved_scrollpos_zoom + ZOOM_LVL_SHIFT; + _saved_scrollpos_x *= ZOOM_LVL_BASE; + _saved_scrollpos_y *= ZOOM_LVL_BASE; + } + /* When any NewGRF has been changed the availability of some vehicles might * have been changed too. e->company_avail must be set to 0 in that case * which is done by StartupEngines(). */ diff --git a/src/saveload/misc_sl.cpp b/src/saveload/misc_sl.cpp index 9ca806701..877fa1269 100644 --- a/src/saveload/misc_sl.cpp +++ b/src/saveload/misc_sl.cpp @@ -56,9 +56,12 @@ 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); + /* If zoom_max is ZOOM_LVL_MIN then the setting has not been loaded yet, therefore all levels are allowed. */ + if (_settings_client.gui.zoom_max != ZOOM_LVL_MIN) { + /* 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/screenshot.cpp b/src/screenshot.cpp index 9cee75820..e1f83eb47 100644 --- a/src/screenshot.cpp +++ b/src/screenshot.cpp @@ -736,7 +736,7 @@ static bool MakeZoomedInScreenshot() Window *w = FindWindowById(WC_MAIN_WINDOW, 0); ViewPort vp; - vp.zoom = ZOOM_LVL_WORLD_SCREENSHOT; + vp.zoom = ZOOM_LVL_NORMAL; vp.left = w->viewport->left; vp.top = w->viewport->top; vp.virtual_left = w->viewport->virtual_left; diff --git a/src/ship_cmd.cpp b/src/ship_cmd.cpp index 66f7746ad..c6d5ca47a 100644 --- a/src/ship_cmd.cpp +++ b/src/ship_cmd.cpp @@ -33,6 +33,7 @@ #include "engine_base.h" #include "company_base.h" #include "tunnelbridge_map.h" +#include "zoom_func.h" #include "table/strings.h" @@ -81,7 +82,7 @@ void DrawShipEngine(int left, int right, int preferred_x, int y, EngineID engine { SpriteID sprite = GetShipIcon(engine, image_type); const Sprite *real_sprite = GetSprite(sprite, ST_NORMAL); - preferred_x = Clamp(preferred_x, left - real_sprite->x_offs, right - real_sprite->width - real_sprite->x_offs); + preferred_x = Clamp(preferred_x, left - UnScaleByZoom(real_sprite->x_offs, ZOOM_LVL_GUI), right - UnScaleByZoom(real_sprite->width, ZOOM_LVL_GUI) - UnScaleByZoom(real_sprite->x_offs, ZOOM_LVL_GUI)); DrawSprite(sprite, pal, preferred_x, y); } @@ -95,8 +96,8 @@ void GetShipSpriteSize(EngineID engine, uint &width, uint &height, EngineImageTy { const Sprite *spr = GetSprite(GetShipIcon(engine, image_type), ST_NORMAL); - width = spr->width; - height = spr->height; + width = UnScaleByZoom(spr->width, ZOOM_LVL_GUI); + height = UnScaleByZoom(spr->height, ZOOM_LVL_GUI); } SpriteID Ship::GetImage(Direction direction, EngineImageType image_type) const diff --git a/src/ship_gui.cpp b/src/ship_gui.cpp index 4cdfb5f81..d036cef43 100644 --- a/src/ship_gui.cpp +++ b/src/ship_gui.cpp @@ -17,6 +17,7 @@ #include "strings_func.h" #include "vehicle_func.h" #include "spritecache.h" +#include "zoom_func.h" #include "table/strings.h" @@ -35,14 +36,16 @@ void DrawShipImage(const Vehicle *v, int left, int right, int y, VehicleID selec SpriteID sprite = v->GetImage(rtl ? DIR_E : DIR_W, image_type); const Sprite *real_sprite = GetSprite(sprite, ST_NORMAL); - int x = rtl ? right - real_sprite->width - real_sprite->x_offs : left - real_sprite->x_offs; + int width = UnScaleByZoom(real_sprite->width, ZOOM_LVL_GUI); + int x_offs = UnScaleByZoom(real_sprite->x_offs, ZOOM_LVL_GUI); + int x = rtl ? right - width - x_offs : left - x_offs; DrawSprite(sprite, GetVehiclePalette(v), x, y + 10); if (v->index == selection) { - x += real_sprite->x_offs; - y += real_sprite->y_offs + 10; - DrawFrameRect(x - 1, y - 1, x + real_sprite->width + 1, y + real_sprite->height + 1, COLOUR_WHITE, FR_BORDERONLY); + x += x_offs; + y += UnScaleByZoom(real_sprite->y_offs, ZOOM_LVL_GUI) + 10; + DrawFrameRect(x - 1, y - 1, x + width + 1, y + UnScaleByZoom(real_sprite->height, ZOOM_LVL_GUI) + 1, COLOUR_WHITE, FR_BORDERONLY); } } diff --git a/src/smallmap_gui.cpp b/src/smallmap_gui.cpp index 871fff252..c8b38f86e 100644 --- a/src/smallmap_gui.cpp +++ b/src/smallmap_gui.cpp @@ -618,6 +618,14 @@ class SmallMapWindow : public Window { static const uint8 FORCE_REFRESH_PERIOD = 0x1F; ///< map is redrawn after that many ticks uint8 refresh; ///< refresh counter, zeroed every FORCE_REFRESH_PERIOD ticks + FORCEINLINE Point SmallmapRemapCoords(int x, int y) const + { + Point pt; + pt.x = (y - x) * 2; + pt.y = y + x; + return pt; + } + /** * Remap tile to location on this smallmap. * @param tile_x X coordinate of the tile. @@ -629,13 +637,13 @@ class SmallMapWindow : public Window { int x_offset = tile_x - this->scroll_x / (int)TILE_SIZE; int y_offset = tile_y - this->scroll_y / (int)TILE_SIZE; - if (this->zoom == 1) return RemapCoords(x_offset, y_offset, 0); + if (this->zoom == 1) return SmallmapRemapCoords(x_offset, y_offset); /* For negative offsets, round towards -inf. */ if (x_offset < 0) x_offset -= this->zoom - 1; if (y_offset < 0) y_offset -= this->zoom - 1; - return RemapCoords(x_offset / this->zoom, y_offset / this->zoom, 0); + return SmallmapRemapCoords(x_offset / this->zoom, y_offset / this->zoom); } /** @@ -1505,7 +1513,7 @@ public: void SetNewScroll(int sx, int sy, int sub) { const NWidgetBase *wi = this->GetWidget<NWidgetBase>(SM_WIDGET_MAP); - Point hv = InverseRemapCoords(wi->current_x * TILE_SIZE / 2, wi->current_y * TILE_SIZE / 2); + Point hv = InverseRemapCoords(wi->current_x * ZOOM_LVL_BASE * TILE_SIZE / 2, wi->current_y * ZOOM_LVL_BASE * TILE_SIZE / 2); hv.x *= this->zoom; hv.y *= this->zoom; diff --git a/src/sound.cpp b/src/sound.cpp index fe4ba0057..d572050bf 100644 --- a/src/sound.cpp +++ b/src/sound.cpp @@ -178,7 +178,7 @@ static void StartSound(SoundID sound_id, float pan, uint volume) } -static const byte _vol_factor_by_zoom[] = {255, 190, 134, 87}; +static const byte _vol_factor_by_zoom[] = {255, 255, 255, 190, 134, 87}; assert_compile(lengthof(_vol_factor_by_zoom) == ZOOM_LVL_COUNT); static const byte _sound_base_vol[] = { diff --git a/src/sprite.cpp b/src/sprite.cpp index a991d315f..69a8ed92e 100644 --- a/src/sprite.cpp +++ b/src/sprite.cpp @@ -16,6 +16,7 @@ #include "spritecache.h" #include "core/alloc_func.hpp" #include "core/mem_func.hpp" +#include "zoom_func.h" /** @@ -118,11 +119,11 @@ void DrawCommonTileSeqInGUI(int x, int y, const DrawTileSprites *dts, int32 orig if (dtss->IsParentSprite()) { Point pt = RemapCoords(dtss->delta_x, dtss->delta_y, dtss->delta_z); - DrawSprite(image, pal, x + pt.x, y + pt.y); + DrawSprite(image, pal, x + UnScaleByZoom(pt.x, ZOOM_LVL_GUI), y + UnScaleByZoom(pt.y, ZOOM_LVL_GUI)); const Sprite *spr = GetSprite(image & SPRITE_MASK, ST_NORMAL); - child_offset.x = pt.x + spr->x_offs; - child_offset.y = pt.y + spr->y_offs; + child_offset.x = UnScaleByZoom(pt.x + spr->x_offs, ZOOM_LVL_GUI); + child_offset.y = UnScaleByZoom(pt.y + spr->y_offs, ZOOM_LVL_GUI); } else { int offs_x = child_offset_is_unsigned ? (uint8)dtss->delta_x : dtss->delta_x; int offs_y = child_offset_is_unsigned ? (uint8)dtss->delta_y : dtss->delta_y; diff --git a/src/spritecache.h b/src/spritecache.h index 0b1a08b19..02be3b4ca 100644 --- a/src/spritecache.h +++ b/src/spritecache.h @@ -16,11 +16,11 @@ /** Data structure describing a sprite. */ struct Sprite { - byte height; ///< Height of the sprite. - uint16 width; ///< Width of the sprite. - int16 x_offs; ///< Number of pixels to shift the sprite to the right. - int16 y_offs; ///< Number of pixels to shift the sprite downwards. - byte data[]; ///< Sprite data. + uint16 height; ///< Height of the sprite. + uint16 width; ///< Width of the sprite. + int16 x_offs; ///< Number of pixels to shift the sprite to the right. + int16 y_offs; ///< Number of pixels to shift the sprite downwards. + byte data[]; ///< Sprite data. }; extern uint _sprite_cache_size; diff --git a/src/spriteloader/grf.cpp b/src/spriteloader/grf.cpp index a0f5c8632..2876f2f35 100644 --- a/src/spriteloader/grf.cpp +++ b/src/spriteloader/grf.cpp @@ -95,7 +95,7 @@ bool SpriteLoaderGrf::LoadSprite(SpriteLoader::Sprite *sprite, uint8 file_slot, if (num != 0) return WarnCorruptSprite(file_slot, file_pos, __LINE__); - sprite->AllocateData(sprite->width * sprite->height); + sprite->AllocateData(sprite->width * sprite->height * ZOOM_LVL_BASE * ZOOM_LVL_BASE); /* When there are transparency pixels, this format has another trick.. decode it */ if (type & 0x08) { @@ -163,6 +163,22 @@ bool SpriteLoaderGrf::LoadSprite(SpriteLoader::Sprite *sprite, uint8 file_slot, } } + if (ZOOM_LVL_BASE != 1 && sprite_type == ST_NORMAL) { + /* Simple scaling, back-to-front so that no intermediate buffers are needed. */ + int width = sprite->width * ZOOM_LVL_BASE; + int height = sprite->height * ZOOM_LVL_BASE; + for (int y = height - 1; y >= 0; y--) { + for (int x = width - 1; x >= 0; x--) { + sprite->data[y * width + x] = sprite->data[y / ZOOM_LVL_BASE * sprite->width + x / ZOOM_LVL_BASE]; + } + } + + sprite->width *= ZOOM_LVL_BASE; + sprite->height *= ZOOM_LVL_BASE; + sprite->x_offs *= ZOOM_LVL_BASE; + sprite->y_offs *= ZOOM_LVL_BASE; + } + /* Make sure to mark all transparent pixels transparent on the alpha channel too */ for (int i = 0; i < sprite->width * sprite->height; i++) { if (sprite->data[i].m != 0) sprite->data[i].a = 0xFF; diff --git a/src/spriteloader/png.cpp b/src/spriteloader/png.cpp index 790b2a2c9..abc9592e0 100644 --- a/src/spriteloader/png.cpp +++ b/src/spriteloader/png.cpp @@ -115,7 +115,7 @@ static bool LoadPNG(SpriteLoader::Sprite *sprite, const char *filename, uint32 i } sprite->height = height; sprite->width = width; - sprite->AllocateData(sprite->width * sprite->height); + sprite->AllocateData(sprite->width * sprite->height * ZOOM_LVL_BASE * ZOOM_LVL_BASE); } else if (sprite->height != png_get_image_height(png_ptr, info_ptr) || sprite->width != png_get_image_width(png_ptr, info_ptr)) { /* Make sure the mask image isn't larger than the sprite image. */ DEBUG(misc, 0, "Ignoring mask for SpriteID %d as it isn't the same dimension as the masked sprite", id); @@ -214,6 +214,23 @@ bool SpriteLoaderPNG::LoadSprite(SpriteLoader::Sprite *sprite, uint8 file_slot, const char *filename = FioGetFilename(file_slot); if (!LoadPNG(sprite, filename, (uint32)file_pos, false)) return false; if (!LoadPNG(sprite, filename, (uint32)file_pos, true)) return false; + + if (ZOOM_LVL_BASE != 1 && sprite_type == ST_NORMAL) { + /* Simple scaling, back-to-front so that no intermediate buffers are needed. */ + int width = sprite->width * ZOOM_LVL_BASE; + int height = sprite->height * ZOOM_LVL_BASE; + for (int y = height - 1; y >= 0; y--) { + for (int x = width - 1; x >= 0; x--) { + sprite->data[y * width + x] = sprite->data[y / ZOOM_LVL_BASE * sprite->width + x / ZOOM_LVL_BASE]; + } + } + + sprite->width *= ZOOM_LVL_BASE; + sprite->height *= ZOOM_LVL_BASE; + sprite->x_offs *= ZOOM_LVL_BASE; + sprite->y_offs *= ZOOM_LVL_BASE; + } + return true; } diff --git a/src/table/misc_settings.ini b/src/table/misc_settings.ini index 1a5780018..a3f0f618f 100644 --- a/src/table/misc_settings.ini +++ b/src/table/misc_settings.ini @@ -215,9 +215,9 @@ def = false name = ""sprite_cache_size"" type = SLE_UINT var = _sprite_cache_size -def = 4 +def = 64 min = 1 -max = 64 +max = 512 [SDTG_VAR] name = ""player_face"" diff --git a/src/table/settings.ini b/src/table/settings.ini index 3d57f868f..0e37e7c5b 100644 --- a/src/table/settings.ini +++ b/src/table/settings.ini @@ -2079,7 +2079,7 @@ flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC guiflags = SGF_MULTISTRING def = ZOOM_LVL_MIN min = ZOOM_LVL_MIN -max = ZOOM_LVL_MIN +max = ZOOM_LVL_GUI str = STR_CONFIG_SETTING_ZOOM_MIN strval = STR_CONFIG_SETTING_ZOOM_LVL_MIN proc = ZoomMinMaxChanged @@ -2090,7 +2090,7 @@ type = SLE_UINT8 flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC guiflags = SGF_MULTISTRING def = ZOOM_LVL_MAX -min = ZOOM_LVL_OUT_2X +min = ZOOM_LVL_OUT_8X max = ZOOM_LVL_MAX str = STR_CONFIG_SETTING_ZOOM_MAX strval = STR_CONFIG_SETTING_ZOOM_LVL_OUT_2X diff --git a/src/texteff.cpp b/src/texteff.cpp index 0feb522db..eac45eafb 100644 --- a/src/texteff.cpp +++ b/src/texteff.cpp @@ -102,13 +102,13 @@ void InitTextEffects() void DrawTextEffects(DrawPixelInfo *dpi) { /* Don't draw the text effects when zoomed out a lot */ - if (dpi->zoom > ZOOM_LVL_OUT_2X) return; + if (dpi->zoom > ZOOM_LVL_OUT_8X) return; const TextEffect *end = _text_effects.End(); for (TextEffect *te = _text_effects.Begin(); te != end; te++) { if (te->string_id == INVALID_STRING_ID) continue; if (te->mode == TE_RISING || (_settings_client.gui.loading_indicators && !IsTransparencySet(TO_LOADING))) { - ViewportAddString(dpi, ZOOM_LVL_OUT_2X, te, te->string_id, te->string_id - 1, 0, te->params_1); + ViewportAddString(dpi, ZOOM_LVL_OUT_8X, te, te->string_id, te->string_id - 1, 0, te->params_1); } } } diff --git a/src/train_cmd.cpp b/src/train_cmd.cpp index bd245cafd..0cc2bc745 100644 --- a/src/train_cmd.cpp +++ b/src/train_cmd.cpp @@ -36,6 +36,7 @@ #include "company_base.h" #include "newgrf.h" #include "order_backup.h" +#include "zoom_func.h" #include "table/strings.h" #include "table/train_cmd.h" @@ -516,14 +517,14 @@ void DrawTrainEngine(int left, int right, int preferred_x, int y, EngineID engin const Sprite *real_spritef = GetSprite(spritef, ST_NORMAL); const Sprite *real_spriter = GetSprite(spriter, ST_NORMAL); - preferred_x = Clamp(preferred_x, left - real_spritef->x_offs + 14, right - real_spriter->width - real_spriter->x_offs - 15); + preferred_x = Clamp(preferred_x, left - UnScaleByZoom(real_spritef->x_offs, ZOOM_LVL_GUI) + 14, right - UnScaleByZoom(real_spriter->width, ZOOM_LVL_GUI) - UnScaleByZoom(real_spriter->x_offs, ZOOM_LVL_GUI) - 15); DrawSprite(spritef, pal, preferred_x - 14, yf); DrawSprite(spriter, pal, preferred_x + 15, yr); } else { SpriteID sprite = GetRailIcon(engine, false, y, image_type); const Sprite *real_sprite = GetSprite(sprite, ST_NORMAL); - preferred_x = Clamp(preferred_x, left - real_sprite->x_offs, right - real_sprite->width - real_sprite->x_offs); + preferred_x = Clamp(preferred_x, left - UnScaleByZoom(real_sprite->x_offs, ZOOM_LVL_GUI), right - UnScaleByZoom(real_sprite->width, ZOOM_LVL_GUI) - UnScaleByZoom(real_sprite->x_offs, ZOOM_LVL_GUI)); DrawSprite(sprite, pal, preferred_x, y); } } diff --git a/src/vehicle.cpp b/src/vehicle.cpp index 4d16fc3a7..be9ea58fd 100644 --- a/src/vehicle.cpp +++ b/src/vehicle.cpp @@ -980,8 +980,8 @@ void ViewportAddVehicles(DrawPixelInfo *dpi) /* The hash area to scan */ int xl, xu, yl, yu; - if (dpi->width + 70 < (1 << (7 + 6))) { - xl = GB(l - 70, 7, 6); + if (dpi->width + (70 * ZOOM_LVL_BASE) < (1 << (7 + 6))) { + xl = GB(l - (70 * ZOOM_LVL_BASE), 7, 6); xu = GB(r, 7, 6); } else { /* scan whole hash row */ @@ -989,8 +989,8 @@ void ViewportAddVehicles(DrawPixelInfo *dpi) xu = 0x3F; } - if (dpi->height + 70 < (1 << (6 + 6))) { - yl = GB(t - 70, 6, 6) << 6; + if (dpi->height + (70 * ZOOM_LVL_BASE) < (1 << (6 + 6))) { + yl = GB(t - (70 * ZOOM_LVL_BASE), 6, 6) << 6; yu = GB(b, 6, 6) << 6; } else { /* scan whole column */ @@ -1407,15 +1407,15 @@ void VehicleMove(Vehicle *v, bool update_viewport) Rect old_coord = v->coord; v->coord.left = pt.x; v->coord.top = pt.y; - v->coord.right = pt.x + spr->width + 2; - v->coord.bottom = pt.y + spr->height + 2; + v->coord.right = pt.x + spr->width + 2 * ZOOM_LVL_BASE; + v->coord.bottom = pt.y + spr->height + 2 * ZOOM_LVL_BASE; if (update_viewport) { MarkAllViewportsDirty( min(old_coord.left, v->coord.left), min(old_coord.top, v->coord.top), - max(old_coord.right, v->coord.right) + 1, - max(old_coord.bottom, v->coord.bottom) + 1 + max(old_coord.right, v->coord.right) + 1 * ZOOM_LVL_BASE, + max(old_coord.bottom, v->coord.bottom) + 1 * ZOOM_LVL_BASE ); } } @@ -1430,7 +1430,7 @@ void VehicleMove(Vehicle *v, bool update_viewport) */ void MarkSingleVehicleDirty(const Vehicle *v) { - MarkAllViewportsDirty(v->coord.left, v->coord.top, v->coord.right + 1, v->coord.bottom + 1); + MarkAllViewportsDirty(v->coord.left, v->coord.top, v->coord.right + 1 * ZOOM_LVL_BASE, v->coord.bottom + 1 * ZOOM_LVL_BASE); } /** diff --git a/src/vehicle_gui.cpp b/src/vehicle_gui.cpp index cbf6e1c08..519f39c19 100644 --- a/src/vehicle_gui.cpp +++ b/src/vehicle_gui.cpp @@ -39,6 +39,7 @@ #include "engine_func.h" #include "station_base.h" #include "tilehighlight_func.h" +#include "zoom_func.h" #include "table/strings.h" @@ -2014,7 +2015,7 @@ struct VehicleDetailsWindow : Window { case VLD_WIDGET_MIDDLE_DETAILS: { /* For other vehicles, at the place of the matrix. */ bool rtl = _current_text_dir == TD_RTL; - uint sprite_width = max<uint>(GetSprite(v->GetImage(rtl ? DIR_E : DIR_W, EIT_IN_DETAILS), ST_NORMAL)->width, 70U) + WD_FRAMERECT_LEFT + WD_FRAMERECT_RIGHT; + uint sprite_width = max<uint>(UnScaleByZoom(GetSprite(v->GetImage(rtl ? DIR_E : DIR_W, EIT_IN_DETAILS), ST_NORMAL)->width, ZOOM_LVL_GUI), 70U) + WD_FRAMERECT_LEFT + WD_FRAMERECT_RIGHT; uint text_left = r.left + (rtl ? 0 : sprite_width); uint text_right = r.right - (rtl ? sprite_width : 0); @@ -2551,7 +2552,7 @@ public: case VVW_WIDGET_CENTER_MAIN_VIEH: {// center main view const Window *mainwindow = FindWindowById(WC_MAIN_WINDOW, 0); /* code to allow the main window to 'follow' the vehicle if the ctrl key is pressed */ - if (_ctrl_pressed && mainwindow->viewport->zoom == ZOOM_LVL_NORMAL) { + if (_ctrl_pressed && mainwindow->viewport->zoom <= ZOOM_LVL_OUT_4X) { mainwindow->viewport->follow_vehicle = v->index; } else { ScrollMainWindowTo(v->x_pos, v->y_pos, v->z_pos); @@ -2725,7 +2726,7 @@ int GetVehicleWidth(Vehicle *v, EngineImageType image_type) bool rtl = _current_text_dir == TD_RTL; SpriteID sprite = v->GetImage(rtl ? DIR_E : DIR_W, image_type); const Sprite *real_sprite = GetSprite(sprite, ST_NORMAL); - vehicle_width = real_sprite->width; + vehicle_width = UnScaleByZoom(real_sprite->width, ZOOM_LVL_GUI); break; } diff --git a/src/viewport.cpp b/src/viewport.cpp index b42acfdfc..56b2941aa 100644 --- a/src/viewport.cpp +++ b/src/viewport.cpp @@ -377,8 +377,8 @@ static Point TranslateXYToTileCoord(const ViewPort *vp, int x, int y) return pt; } - x = (ScaleByZoom(x, vp->zoom) + vp->virtual_left) >> 2; - y = (ScaleByZoom(y, vp->zoom) + vp->virtual_top) >> 1; + x = (ScaleByZoom(x, vp->zoom) + vp->virtual_left) >> (2 + ZOOM_LVL_SHIFT); + y = (ScaleByZoom(y, vp->zoom) + vp->virtual_top) >> (1 + ZOOM_LVL_SHIFT); a = y - x; b = y + x; @@ -539,9 +539,9 @@ void DrawGroundSpriteAt(SpriteID image, PaletteID pal, int32 x, int32 y, int z, if (_vd.foundation[_vd.foundation_part] != -1) { Point pt = RemapCoords(x, y, z); - AddChildSpriteToFoundation(image, pal, sub, _vd.foundation_part, pt.x + extra_offs_x, pt.y + extra_offs_y); + AddChildSpriteToFoundation(image, pal, sub, _vd.foundation_part, pt.x + extra_offs_x * ZOOM_LVL_BASE, pt.y + extra_offs_y * ZOOM_LVL_BASE); } else { - AddTileSpriteToDraw(image, pal, _cur_ti->x + x, _cur_ti->y + y, _cur_ti->z + z, sub, extra_offs_x, extra_offs_y); + AddTileSpriteToDraw(image, pal, _cur_ti->x + x, _cur_ti->y + y, _cur_ti->z + z, sub, extra_offs_x * ZOOM_LVL_BASE, extra_offs_y * ZOOM_LVL_BASE); } } @@ -583,8 +583,8 @@ void OffsetGroundSprite(int x, int y) /* _vd.last_child == NULL if foundation sprite was clipped by the viewport bounds */ if (_vd.last_child != NULL) _vd.foundation[_vd.foundation_part] = _vd.parent_sprites_to_draw.Length() - 1; - _vd.foundation_offset[_vd.foundation_part].x = x; - _vd.foundation_offset[_vd.foundation_part].y = y; + _vd.foundation_offset[_vd.foundation_part].x = x * ZOOM_LVL_BASE; + _vd.foundation_offset[_vd.foundation_part].y = y * ZOOM_LVL_BASE; _vd.last_foundation_child[_vd.foundation_part] = _vd.last_child; } @@ -858,7 +858,7 @@ static void DrawSelectionSprite(SpriteID image, PaletteID pal, const TileInfo *t AddTileSpriteToDraw(image, pal, ti->x, ti->y, ti->z + z_offset); } else { /* draw on top of foundation */ - AddChildSpriteToFoundation(image, pal, NULL, foundation_part, 0, -z_offset); + AddChildSpriteToFoundation(image, pal, NULL, foundation_part, 0, -z_offset * ZOOM_LVL_BASE); } } @@ -1040,14 +1040,14 @@ static void ViewportAddLandscape() _cur_ti = &ti; /* Transform into tile coordinates and round to closest full tile */ - x = ((_vd.dpi.top >> 1) - (_vd.dpi.left >> 2)) & ~TILE_UNIT_MASK; - y = ((_vd.dpi.top >> 1) + (_vd.dpi.left >> 2) - TILE_SIZE) & ~TILE_UNIT_MASK; + x = ((_vd.dpi.top >> (1 + ZOOM_LVL_SHIFT)) - (_vd.dpi.left >> (2 + ZOOM_LVL_SHIFT))) & ~TILE_UNIT_MASK; + y = ((_vd.dpi.top >> (1 + ZOOM_LVL_SHIFT)) + (_vd.dpi.left >> (2 + ZOOM_LVL_SHIFT)) - TILE_SIZE) & ~TILE_UNIT_MASK; /* determine size of area */ { Point pt = RemapCoords(x, y, 241); - width = (_vd.dpi.left + _vd.dpi.width - pt.x + 95) >> 6; - height = (_vd.dpi.top + _vd.dpi.height - pt.y) >> 5 << 1; + width = (_vd.dpi.left + _vd.dpi.width - pt.x + 95 * ZOOM_LVL_BASE) >> (6 + ZOOM_LVL_SHIFT); + height = (_vd.dpi.top + _vd.dpi.height - pt.y) >> (5 + ZOOM_LVL_SHIFT) << 1; } assert(width > 0); @@ -1166,7 +1166,7 @@ static void ViewportAddTownNames(DrawPixelInfo *dpi) const Town *t; FOR_ALL_TOWNS(t) { - ViewportAddString(dpi, ZOOM_LVL_OUT_4X, &t->sign, + ViewportAddString(dpi, ZOOM_LVL_OUT_16X, &t->sign, _settings_client.gui.population_in_label ? STR_VIEWPORT_TOWN_POP : STR_VIEWPORT_TOWN, STR_VIEWPORT_TOWN_TINY_WHITE, STR_VIEWPORT_TOWN_TINY_BLACK, t->index, t->population); @@ -1189,7 +1189,7 @@ static void ViewportAddStationNames(DrawPixelInfo *dpi) /* Don't draw if station is owned by another company and competitor station names are hidden. Stations owned by none are never ignored. */ if (!HasBit(_display_opt, DO_SHOW_COMPETITOR_SIGNS) && _local_company != st->owner && st->owner != OWNER_NONE) continue; - ViewportAddString(dpi, ZOOM_LVL_OUT_4X, &st->sign, + ViewportAddString(dpi, ZOOM_LVL_OUT_16X, &st->sign, is_station ? STR_VIEWPORT_STATION : STR_VIEWPORT_WAYPOINT, (is_station ? STR_VIEWPORT_STATION : STR_VIEWPORT_WAYPOINT) + 1, STR_NULL, st->index, st->facilities, (st->owner == OWNER_NONE || !st->IsInUse()) ? COLOUR_GREY : _company_colours[st->owner]); @@ -1209,7 +1209,7 @@ static void ViewportAddSigns(DrawPixelInfo *dpi) * companies can leave OWNER_NONE signs after them. */ if (!HasBit(_display_opt, DO_SHOW_COMPETITOR_SIGNS) && _local_company != si->owner) continue; - ViewportAddString(dpi, ZOOM_LVL_OUT_4X, &si->sign, + ViewportAddString(dpi, ZOOM_LVL_OUT_16X, &si->sign, STR_WHITE_SIGN, IsTransparencySet(TO_SIGNS) ? STR_VIEWPORT_SIGN_SMALL_WHITE : STR_VIEWPORT_SIGN_SMALL_BLACK, STR_NULL, si->index, 0, (si->owner == OWNER_NONE) ? COLOUR_GREY : _company_colours[si->owner]); @@ -1262,7 +1262,7 @@ static void ViewportDrawTileSprites(const TileSpriteToDrawVector *tstdv) { const TileSpriteToDraw *tsend = tstdv->End(); for (const TileSpriteToDraw *ts = tstdv->Begin(); ts != tsend; ++ts) { - DrawSprite(ts->image, ts->pal, ts->x, ts->y, ts->sub); + DrawSpriteViewport(ts->image, ts->pal, ts->x, ts->y, ts->sub); } } @@ -1329,13 +1329,13 @@ static void ViewportDrawParentSprites(const ParentSpriteToSortVector *psd, const const ParentSpriteToDraw * const *psd_end = psd->End(); for (const ParentSpriteToDraw * const *it = psd->Begin(); it != psd_end; it++) { const ParentSpriteToDraw *ps = *it; - if (ps->image != SPR_EMPTY_BOUNDING_BOX) DrawSprite(ps->image, ps->pal, ps->x, ps->y, ps->sub); + if (ps->image != SPR_EMPTY_BOUNDING_BOX) DrawSpriteViewport(ps->image, ps->pal, ps->x, ps->y, ps->sub); int child_idx = ps->first_child; while (child_idx >= 0) { const ChildScreenSpriteToDraw *cs = csstdv->Get(child_idx); child_idx = cs->next; - DrawSprite(cs->image, cs->pal, ps->left + cs->x, ps->top + cs->y, cs->sub); + DrawSpriteViewport(cs->image, cs->pal, ps->left + cs->x, ps->top + cs->y, cs->sub); } } } @@ -1475,7 +1475,7 @@ void ViewportDoDraw(const ViewPort *vp, int left, int top, int right, int bottom */ static void ViewportDrawChk(const ViewPort *vp, int left, int top, int right, int bottom) { - if (ScaleByZoom(bottom - top, vp->zoom) * ScaleByZoom(right - left, vp->zoom) > 180000) { + if (ScaleByZoom(bottom - top, vp->zoom) * ScaleByZoom(right - left, vp->zoom) > 180000 * ZOOM_LVL_BASE * ZOOM_LVL_BASE) { if ((bottom - top) > (right - left)) { int t = (top + bottom) >> 1; ViewportDrawChk(vp, left, top, right, t); @@ -1540,8 +1540,8 @@ static inline void ClampViewportToMap(const ViewPort *vp, int &x, int &y) int vy = x + y * 2; /* clamp to size of map */ - vx = Clamp(vx, 0, MapMaxX() * TILE_SIZE * 4); - vy = Clamp(vy, 0, MapMaxY() * TILE_SIZE * 4); + vx = Clamp(vx, 0, MapMaxX() * TILE_SIZE * 4 * ZOOM_LVL_BASE); + vy = Clamp(vy, 0, MapMaxY() * TILE_SIZE * 4 * ZOOM_LVL_BASE); /* Convert map coordinates to viewport coordinates */ x = (-vx + vy) / 2; @@ -1576,7 +1576,7 @@ void UpdateViewportPosition(Window *w) if (delta_x != 0 || delta_y != 0) { if (_settings_client.gui.smooth_scroll) { - int max_scroll = ScaleByMapSize1D(512); + int max_scroll = ScaleByMapSize1D(512 * ZOOM_LVL_BASE); /* Not at our desired position yet... */ w->viewport->scrollpos_x += Clamp(delta_x / 4, -max_scroll, max_scroll); w->viewport->scrollpos_y += Clamp(delta_y / 4, -max_scroll, max_scroll); @@ -1668,10 +1668,10 @@ void MarkTileDirtyByTile(TileIndex tile) { Point pt = RemapCoords(TileX(tile) * TILE_SIZE, TileY(tile) * TILE_SIZE, GetTilePixelZ(tile)); MarkAllViewportsDirty( - pt.x - 31, - pt.y - 122, - pt.x - 31 + 67, - pt.y - 122 + 154 + pt.x - 31 * ZOOM_LVL_BASE, + pt.y - 122 * ZOOM_LVL_BASE, + pt.x - 31 * ZOOM_LVL_BASE + 67 * ZOOM_LVL_BASE, + pt.y - 122 * ZOOM_LVL_BASE + 154 * ZOOM_LVL_BASE ); } @@ -1748,15 +1748,15 @@ static void SetSelectionTilesDirty() /* the 'x' coordinate of 'top' and 'bot' is the same (and always in the same distance from tile middle), * tile height/slope affects only the 'y' on-screen coordinate! */ - int l = top.x - (TILE_PIXELS - 2); // 'x' coordinate of left side of dirty rectangle + int l = top.x - (TILE_PIXELS - 2) * ZOOM_LVL_BASE; // 'x' coordinate of left side of dirty rectangle int t = top.y; // 'y' coordinate of top side -//- - int r = top.x + (TILE_PIXELS - 2); // right side of dirty rectangle + int r = top.x + (TILE_PIXELS - 2) * ZOOM_LVL_BASE; // right side of dirty rectangle int b = bot.y; // bottom -//- - static const int OVERLAY_WIDTH = 4; // part of selection sprites is drawn outside the selected area + static const int OVERLAY_WIDTH = 4 * ZOOM_LVL_BASE; // part of selection sprites is drawn outside the selected area /* For halftile foundations on SLOPE_STEEP_S the sprite extents some more towards the top */ - MarkAllViewportsDirty(l - OVERLAY_WIDTH, t - OVERLAY_WIDTH - TILE_HEIGHT, r + OVERLAY_WIDTH, b + OVERLAY_WIDTH); + MarkAllViewportsDirty(l - OVERLAY_WIDTH, t - OVERLAY_WIDTH - TILE_HEIGHT * ZOOM_LVL_BASE, r + OVERLAY_WIDTH, b + OVERLAY_WIDTH * ZOOM_LVL_BASE); /* haven't we reached the topmost tile yet? */ if (top_x != x_start) { @@ -1809,7 +1809,7 @@ void SetSelectionRed(bool b) */ static bool CheckClickOnViewportSign(const ViewPort *vp, int x, int y, const ViewportSign *sign) { - bool small = (vp->zoom >= ZOOM_LVL_OUT_4X); + bool small = (vp->zoom >= ZOOM_LVL_OUT_16X); int sign_half_width = ScaleByZoom((small ? sign->width_small : sign->width_normal) / 2, vp->zoom); int sign_height = ScaleByZoom(VPSM_TOP + (small ? FONT_HEIGHT_SMALL : FONT_HEIGHT_NORMAL) + VPSM_BOTTOM, vp->zoom); diff --git a/src/zoom_type.h b/src/zoom_type.h index 8b5761408..37ffc153c 100644 --- a/src/zoom_type.h +++ b/src/zoom_type.h @@ -14,6 +14,9 @@ #include "core/enum_type.hpp" +static int const ZOOM_LVL_SHIFT = 2; +static int const ZOOM_LVL_BASE = 1 << ZOOM_LVL_SHIFT; + /** All zoom levels we know. */ enum ZoomLevel { /* Our possible zoom-levels */ @@ -22,25 +25,28 @@ enum ZoomLevel { ZOOM_LVL_OUT_2X, ///< Zoomed 2 times out. ZOOM_LVL_OUT_4X, ///< Zoomed 4 times out. ZOOM_LVL_OUT_8X, ///< Zoomed 8 times out. + ZOOM_LVL_OUT_16X, ///< Zoomed 16 times out. + ZOOM_LVL_OUT_32X, ///< Zoomed 32 times out. ZOOM_LVL_END, ///< End for iteration. ZOOM_LVL_COUNT = ZOOM_LVL_END - ZOOM_LVL_BEGIN, ///< Number of zoom levels. /* Here we define in which zoom viewports are */ - ZOOM_LVL_VIEWPORT = ZOOM_LVL_NORMAL, ///< Default zoom level for viewports. - ZOOM_LVL_NEWS = ZOOM_LVL_NORMAL, ///< Default zoom level for the news messages. - ZOOM_LVL_INDUSTRY = ZOOM_LVL_OUT_2X, ///< Default zoom level for the industry view. - ZOOM_LVL_TOWN = ZOOM_LVL_OUT_2X, ///< Default zoom level for the town view. - ZOOM_LVL_AIRCRAFT = ZOOM_LVL_NORMAL, ///< Default zoom level for the aircraft view. - ZOOM_LVL_SHIP = ZOOM_LVL_NORMAL, ///< Default zoom level for the ship view. - ZOOM_LVL_TRAIN = ZOOM_LVL_NORMAL, ///< Default zoom level for the train view. - ZOOM_LVL_ROADVEH = ZOOM_LVL_NORMAL, ///< Default zoom level for the road vehicle view. - ZOOM_LVL_WORLD_SCREENSHOT = ZOOM_LVL_NORMAL, ///< Default zoom level for the world screen shot. - - ZOOM_LVL_DETAIL = ZOOM_LVL_OUT_2X, ///< All zoomlevels below or equal to this, will result in details on the screen, like road-work, ... + ZOOM_LVL_VIEWPORT = ZOOM_LVL_OUT_4X, ///< Default zoom level for viewports. + ZOOM_LVL_GUI = ZOOM_LVL_OUT_4X, ///< Default zoom level for GUI sprites. + ZOOM_LVL_NEWS = ZOOM_LVL_OUT_4X, ///< Default zoom level for the news messages. + ZOOM_LVL_INDUSTRY = ZOOM_LVL_OUT_8X, ///< Default zoom level for the industry view. + ZOOM_LVL_TOWN = ZOOM_LVL_OUT_8X, ///< Default zoom level for the town view. + ZOOM_LVL_AIRCRAFT = ZOOM_LVL_OUT_4X, ///< Default zoom level for the aircraft view. + ZOOM_LVL_SHIP = ZOOM_LVL_OUT_4X, ///< Default zoom level for the ship view. + ZOOM_LVL_TRAIN = ZOOM_LVL_OUT_4X, ///< Default zoom level for the train view. + ZOOM_LVL_ROADVEH = ZOOM_LVL_OUT_4X, ///< Default zoom level for the road vehicle view. + ZOOM_LVL_WORLD_SCREENSHOT = ZOOM_LVL_OUT_4X, ///< Default zoom level for the world screen shot. + + ZOOM_LVL_DETAIL = ZOOM_LVL_OUT_8X, ///< All zoomlevels below or equal to this, will result in details on the screen, like road-work, ... ZOOM_LVL_MIN = ZOOM_LVL_NORMAL, ///< Minimum zoom level. - ZOOM_LVL_MAX = ZOOM_LVL_OUT_8X, ///< Maximum zoom level. + ZOOM_LVL_MAX = ZOOM_LVL_OUT_32X, ///< Maximum zoom level. }; DECLARE_POSTFIX_INCREMENT(ZoomLevel) |