From e04ca904a9455afc63aa87db775fe4463ab899b7 Mon Sep 17 00:00:00 2001 From: TELK Date: Sun, 5 Jan 2020 01:47:37 +0900 Subject: [PATCH] Feature: Minimap screenshot --- src/console_cmds.cpp | 9 +++- src/gfx_func.h | 6 +++ src/lang/english.txt | 1 + src/screenshot.cpp | 83 ++++++++++++++++++++++++++++++++ src/screenshot.h | 2 + src/screenshot_gui.cpp | 2 + src/script/api/script_window.hpp | 1 + src/smallmap_gui.cpp | 7 --- src/widgets/screenshot_widget.h | 1 + 9 files changed, 103 insertions(+), 9 deletions(-) diff --git a/src/console_cmds.cpp b/src/console_cmds.cpp index f4d0626a5b..343524202b 100644 --- a/src/console_cmds.cpp +++ b/src/console_cmds.cpp @@ -1349,10 +1349,11 @@ DEF_CONSOLE_CMD(ConAlias) DEF_CONSOLE_CMD(ConScreenShot) { if (argc == 0) { - IConsoleHelp("Create a screenshot of the game. Usage: 'screenshot [big | giant | no_con] [file name]'"); + IConsoleHelp("Create a screenshot of the game. Usage: 'screenshot [big | giant | no_con | minimap] [file name]'"); IConsoleHelp("'big' makes a zoomed-in screenshot of the visible area, 'giant' makes a screenshot of the " "whole map, 'no_con' hides the console to create the screenshot. 'big' or 'giant' " - "screenshots are always drawn without console"); + "screenshots are always drawn without console. " + "'minimap' makes a top-viewed minimap screenshot of whole world which represents one tile by one pixel."); return true; } @@ -1370,6 +1371,10 @@ DEF_CONSOLE_CMD(ConScreenShot) /* screenshot giant [filename] */ type = SC_WORLD; if (argc > 2) name = argv[2]; + } else if (strcmp(argv[1], "minimap") == 0) { + /* screenshot minimap [filename] */ + type = SC_MINIMAP; + if (argc > 2) name = argv[2]; } else if (strcmp(argv[1], "no_con") == 0) { /* screenshot no_con [filename] */ IConsoleClose(); diff --git a/src/gfx_func.h b/src/gfx_func.h index 5da0ff0cab..a0b46a477b 100644 --- a/src/gfx_func.h +++ b/src/gfx_func.h @@ -222,4 +222,10 @@ static const uint8 PC_GREEN = 0xD0; ///< Green palette co static const uint8 PC_DARK_BLUE = 0x9D; ///< Dark blue palette colour. static const uint8 PC_LIGHT_BLUE = 0x98; ///< Light blue palette colour. +static const uint8 PC_ROUGH_LAND = 0x52; ///< Dark green palette colour for rough land. +static const uint8 PC_GRASS_LAND = 0x54; ///< Dark green palette colour for grass land. +static const uint8 PC_BARE_LAND = 0x37; ///< Brown palette colour for bare land. +static const uint8 PC_FIELDS = 0x25; ///< Light brown palette colour for fields. +static const uint8 PC_TREES = 0x57; ///< Green palette colour for trees. +static const uint8 PC_WATER = 0xC9; ///< Dark blue palette colour for water. #endif /* GFX_FUNC_H */ diff --git a/src/lang/english.txt b/src/lang/english.txt index 4fd97c5397..36d0199ea6 100644 --- a/src/lang/english.txt +++ b/src/lang/english.txt @@ -4182,6 +4182,7 @@ STR_SCREENSHOT_ZOOMIN_SCREENSHOT :{BLACK}Fully zo STR_SCREENSHOT_DEFAULTZOOM_SCREENSHOT :{BLACK}Default zoom screenshot STR_SCREENSHOT_WORLD_SCREENSHOT :{BLACK}Whole map screenshot STR_SCREENSHOT_HEIGHTMAP_SCREENSHOT :{BLACK}Heightmap screenshot +STR_SCREENSHOT_MINIMAP_SCREENSHOT :{BLACK}Minimap screenshot # AI Parameters STR_AI_SETTINGS_CAPTION :{WHITE}{STRING} Parameters diff --git a/src/screenshot.cpp b/src/screenshot.cpp index 60196cdf07..4a80a0cbfe 100644 --- a/src/screenshot.cpp +++ b/src/screenshot.cpp @@ -16,6 +16,7 @@ #include "zoom_func.h" #include "core/endian_func.hpp" #include "saveload/saveload.h" +#include "company_base.h" #include "company_func.h" #include "strings_func.h" #include "error.h" @@ -66,6 +67,8 @@ struct ScreenshotFormat { ScreenshotHandlerProc *proc; ///< Function for writing the screenshot. }; +#define MKCOLOUR(x) TO_LE32X(x) + /************************************************* **** SCREENSHOT CODE FOR WINDOWS BITMAP (.BMP) *************************************************/ @@ -842,6 +845,10 @@ bool MakeScreenshot(ScreenshotType t, const char *name) break; } + case SC_MINIMAP: + ret = MakeMinimapWorldScreenshot(); + break; + default: NOT_REACHED(); } @@ -855,3 +862,79 @@ bool MakeScreenshot(ScreenshotType t, const char *name) return ret; } + + +/** + * Return the owner of a tile to display it with in the small map in mode "Owner". + * + * @param tile The tile of which we would like to get the colour. + * @return The owner of tile in the small map in mode "Owner" + */ +static Owner GetMinimapOwner(TileIndex tile) +{ + Owner o; + + if (IsTileType(tile, MP_VOID)) { + return OWNER_END; + } else { + switch (GetTileType(tile)) { + case MP_INDUSTRY: o = OWNER_DEITY; break; + case MP_HOUSE: o = OWNER_TOWN; break; + default: o = GetTileOwner(tile); break; + /* FIXME: For MP_ROAD there are multiple owners. + * GetTileOwner returns the rail owner (level crossing) resp. the owner of ROADTYPE_ROAD (normal road), + * even if there are no ROADTYPE_ROAD bits on the tile. + */ + } + + return o; + } +} + +static void MinimapScreenCallback(void *userdata, void *buf, uint y, uint pitch, uint n) +{ + uint32 *ubuf; + uint num, row, col; + byte val; + byte owner_colours[OWNER_END + 1]; + + /* Fill with the company colours */ + for (const Company *c : Company::Iterate()) { + owner_colours[c->index] = MKCOLOUR(_colour_gradient[c->colour][5]); + } + + /* Fill with some special colours */ + owner_colours[OWNER_TOWN] = PC_DARK_RED; + owner_colours[OWNER_NONE] = PC_GRASS_LAND; + owner_colours[OWNER_WATER] = PC_WATER; + owner_colours[OWNER_DEITY] = PC_DARK_GREY; // industry + owner_colours[OWNER_END] = PC_BLACK; + + ubuf = (uint32 *)buf; + num = (pitch * n); + for (uint i = 0; i < num; i++) { + row = y + (int)(i / pitch); + col = (MapSizeX() - 1) - (i % pitch); + + TileIndex tile = TileXY(col, row); + Owner o = GetMinimapOwner(tile); + val = owner_colours[o]; + + uint32 colour_buf = 0; + colour_buf = (_cur_palette.palette[val].b << 0); + colour_buf |= (_cur_palette.palette[val].g << 8); + colour_buf |= (_cur_palette.palette[val].r << 16); + + *ubuf = colour_buf; + *ubuf++; // Skip alpha + } +} + +/** + * Make a minimap screenshot. + */ +bool MakeMinimapWorldScreenshot() +{ + const ScreenshotFormat *sf = _screenshot_formats + _cur_screenshot_format; + return sf->proc(MakeScreenshotName(SCREENSHOT_NAME, sf->extension), MinimapScreenCallback, nullptr, MapSizeX(), MapSizeY(), 32, _cur_palette.palette); +} diff --git a/src/screenshot.h b/src/screenshot.h index 7a08cd4fb6..aea08a8d5f 100644 --- a/src/screenshot.h +++ b/src/screenshot.h @@ -22,11 +22,13 @@ enum ScreenshotType { SC_DEFAULTZOOM, ///< Zoomed to default zoom level screenshot of the visible area. SC_WORLD, ///< World screenshot. SC_HEIGHTMAP, ///< Heightmap of the world. + SC_MINIMAP, ///< Minimap screenshot. }; void SetupScreenshotViewport(ScreenshotType t, struct ViewPort *vp); bool MakeHeightmapScreenshot(const char *filename); bool MakeScreenshot(ScreenshotType t, const char *name); +bool MakeMinimapWorldScreenshot(); extern char _screenshot_format_name[8]; extern uint _num_screenshot_formats; diff --git a/src/screenshot_gui.cpp b/src/screenshot_gui.cpp index bcbb93653e..72e118b51e 100644 --- a/src/screenshot_gui.cpp +++ b/src/screenshot_gui.cpp @@ -41,6 +41,7 @@ struct ScreenshotWindow : Window { case WID_SC_TAKE_DEFAULTZOOM: st = SC_DEFAULTZOOM; break; case WID_SC_TAKE_WORLD: st = SC_WORLD; break; case WID_SC_TAKE_HEIGHTMAP: st = SC_HEIGHTMAP; break; + case WID_SC_TAKE_MINIMAP: st = SC_MINIMAP; break; } TakeScreenshot(st); } @@ -87,6 +88,7 @@ static const NWidgetPart _nested_screenshot[] = { NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_SC_TAKE_DEFAULTZOOM), SetFill(1, 1), SetDataTip(STR_SCREENSHOT_DEFAULTZOOM_SCREENSHOT, 0), SetMinimalTextLines(2, 0), NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_SC_TAKE_WORLD), SetFill(1, 1), SetDataTip(STR_SCREENSHOT_WORLD_SCREENSHOT, 0), SetMinimalTextLines(2, 0), NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_SC_TAKE_HEIGHTMAP), SetFill(1, 1), SetDataTip(STR_SCREENSHOT_HEIGHTMAP_SCREENSHOT, 0), SetMinimalTextLines(2, 0), + NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_SC_TAKE_MINIMAP), SetFill(1, 1), SetDataTip(STR_SCREENSHOT_MINIMAP_SCREENSHOT, 0), SetMinimalTextLines(2, 0), EndContainer(), }; diff --git a/src/script/api/script_window.hpp b/src/script/api/script_window.hpp index 9847f543bc..2b040c8c65 100644 --- a/src/script/api/script_window.hpp +++ b/src/script/api/script_window.hpp @@ -2186,6 +2186,7 @@ public: WID_SC_TAKE_DEFAULTZOOM = ::WID_SC_TAKE_DEFAULTZOOM, ///< Button for taking a screenshot at normal zoom WID_SC_TAKE_WORLD = ::WID_SC_TAKE_WORLD, ///< Button for taking a screenshot of the whole world WID_SC_TAKE_HEIGHTMAP = ::WID_SC_TAKE_HEIGHTMAP, ///< Button for taking a heightmap "screenshot" + WID_SC_TAKE_MINIMAP = ::WID_SC_TAKE_MINIMAP, ///< Button for taking a minimap screenshot }; /* automatically generated from ../../widgets/settings_widget.h */ diff --git a/src/smallmap_gui.cpp b/src/smallmap_gui.cpp index 00f682f635..c4b650fc22 100644 --- a/src/smallmap_gui.cpp +++ b/src/smallmap_gui.cpp @@ -40,13 +40,6 @@ static uint8 _linkstat_colours_in_legenda[] = {0, 1, 3, 5, 7, 9, 11}; static const int NUM_NO_COMPANY_ENTRIES = 4; ///< Number of entries in the owner legend that are not companies. -static const uint8 PC_ROUGH_LAND = 0x52; ///< Dark green palette colour for rough land. -static const uint8 PC_GRASS_LAND = 0x54; ///< Dark green palette colour for grass land. -static const uint8 PC_BARE_LAND = 0x37; ///< Brown palette colour for bare land. -static const uint8 PC_FIELDS = 0x25; ///< Light brown palette colour for fields. -static const uint8 PC_TREES = 0x57; ///< Green palette colour for trees. -static const uint8 PC_WATER = 0xC9; ///< Dark blue palette colour for water. - /** Macro for ordinary entry of LegendAndColour */ #define MK(a, b) {a, b, INVALID_INDUSTRYTYPE, 0, INVALID_COMPANY, true, false, false} diff --git a/src/widgets/screenshot_widget.h b/src/widgets/screenshot_widget.h index 40a0da246c..6f42b784d6 100644 --- a/src/widgets/screenshot_widget.h +++ b/src/widgets/screenshot_widget.h @@ -18,6 +18,7 @@ enum ScreenshotWindowWidgets { WID_SC_TAKE_DEFAULTZOOM, ///< Button for taking a screenshot at normal zoom WID_SC_TAKE_WORLD, ///< Button for taking a screenshot of the whole world WID_SC_TAKE_HEIGHTMAP, ///< Button for taking a heightmap "screenshot" + WID_SC_TAKE_MINIMAP, ///< Button for taking a minimap screenshot };