diff --git a/src/lang/english.txt b/src/lang/english.txt index bfc92aaa59..0c02bcf0a2 100644 --- a/src/lang/english.txt +++ b/src/lang/english.txt @@ -756,6 +756,7 @@ STR_SMALLMAP_INDUSTRY :{TINY_FONT}{STR STR_SMALLMAP_LINKSTATS :{TINY_FONT}{STRING} STR_SMALLMAP_COMPANY :{TINY_FONT}{COMPANY} STR_SMALLMAP_TOWN :{TINY_FONT}{WHITE}{TOWN} +STR_SMALLMAP_SCREENSHOT :{BLACK}Screenshot STR_SMALLMAP_DISABLE_ALL :{BLACK}Disable all STR_SMALLMAP_ENABLE_ALL :{BLACK}Enable all STR_SMALLMAP_SHOW_HEIGHT :{BLACK}Show height diff --git a/src/screenshot.cpp b/src/screenshot.cpp index a24cc6b211..66297e39fe 100644 --- a/src/screenshot.cpp +++ b/src/screenshot.cpp @@ -25,6 +25,7 @@ #include "window_func.h" #include "tile_map.h" #include "landscape.h" +#include "smallmap_gui.h" #include "table/strings.h" @@ -810,6 +811,20 @@ bool MakeHeightmapScreenshot(const char *filename) return sf->proc(filename, HeightmapCallback, NULL, MapSizeX(), MapSizeY(), 8, palette); } +/** + * Show a a success or failure message indicating the result of a screenshot action + * @param ret whether the screenshot action was successful + */ +static void ShowScreenshotResultMessage(bool ret) +{ + if (ret) { + SetDParamStr(0, _screenshot_name); + ShowErrorMessage(STR_MESSAGE_SCREENSHOT_SUCCESSFULLY, INVALID_STRING_ID, WL_WARNING); + } else { + ShowErrorMessage(STR_ERROR_SCREENSHOT_FAILED, INVALID_STRING_ID, WL_ERROR); + } +} + /** * Make an actual screenshot. * @param t the type of screenshot to make. @@ -856,12 +871,37 @@ bool MakeScreenshot(ScreenshotType t, const char *name) NOT_REACHED(); } - if (ret) { - SetDParamStr(0, _screenshot_name); - ShowErrorMessage(STR_MESSAGE_SCREENSHOT_SUCCESSFULLY, INVALID_STRING_ID, WL_WARNING); - } else { - ShowErrorMessage(STR_ERROR_SCREENSHOT_FAILED, INVALID_STRING_ID, WL_ERROR); - } + ShowScreenshotResultMessage(ret); return ret; } + +/** + * Callback for generating a smallmap screenshot. + * @param userdata SmallMapWindow window pointer + * @param buf Videobuffer with same bitdepth as current blitter + * @param y First line to render + * @param pitch Pitch of the videobuffer + * @param n Number of lines to render + */ +static void SmallMapCallback(void *userdata, void *buf, uint y, uint pitch, uint n) +{ + SmallMapWindow *window = static_cast(userdata); + window->ScreenshotCallbackHandler(buf, y, pitch, n); +} + +/** + * Make a screenshot of the smallmap + * @param width the width of the screenshot + * @param height the height of the screenshot + * @param window a pointer to the smallmap window to use, the current mode and zoom status of the window is used for the screenshot + * @return true iff the screenshot was made successfully + */ +bool MakeSmallMapScreenshot(unsigned int width, unsigned int height, SmallMapWindow *window) +{ + _screenshot_name[0] = '\0'; + const ScreenshotFormat *sf = _screenshot_formats + _cur_screenshot_format; + bool ret = sf->proc(MakeScreenshotName(SCREENSHOT_NAME, sf->extension), SmallMapCallback, window, width, height, BlitterFactory::GetCurrentBlitter()->GetScreenDepth(), _cur_palette.palette); + ShowScreenshotResultMessage(ret); + return ret; +} diff --git a/src/screenshot.h b/src/screenshot.h index ee03d8aff7..2ff372400f 100644 --- a/src/screenshot.h +++ b/src/screenshot.h @@ -26,8 +26,11 @@ enum ScreenshotType { SC_HEIGHTMAP, ///< Heightmap of the world. }; +class SmallMapWindow; + void SetupScreenshotViewport(ScreenshotType t, struct ViewPort *vp); bool MakeHeightmapScreenshot(const char *filename); +bool MakeSmallMapScreenshot(unsigned int width, unsigned int height, SmallMapWindow *window); bool MakeScreenshot(ScreenshotType t, const char *name); extern char _screenshot_format_name[8]; diff --git a/src/smallmap_gui.cpp b/src/smallmap_gui.cpp index 80d4ae2a89..2d316caf92 100644 --- a/src/smallmap_gui.cpp +++ b/src/smallmap_gui.cpp @@ -23,6 +23,7 @@ #include "sound_func.h" #include "window_func.h" #include "company_base.h" +#include "screenshot.h" #include "smallmap_gui.h" @@ -936,7 +937,7 @@ void SmallMapWindow::DrawMapIndicators() const * * @param dpi pointer to pixel to write onto */ -void SmallMapWindow::DrawSmallMap(DrawPixelInfo *dpi) const +void SmallMapWindow::DrawSmallMap(DrawPixelInfo *dpi, bool draw_indicators) const { Blitter *blitter = BlitterFactory::GetCurrentBlitter(); DrawPixelInfo *old_dpi; @@ -992,7 +993,7 @@ void SmallMapWindow::DrawSmallMap(DrawPixelInfo *dpi) const if (this->show_towns) this->DrawTowns(dpi); /* Draw map indicators */ - this->DrawMapIndicators(); + if (draw_indicators) this->DrawMapIndicators(); _cur_dpi = old_dpi; } @@ -1487,6 +1488,10 @@ int SmallMapWindow::GetPositionOnLegend(Point pt) this->SetWidgetLoweredState(WID_SM_SHOW_HEIGHT, _smallmap_show_heightmap); this->SetDirty(); break; + + case WID_SM_SCREENSHOT: + TakeScreenshot(); + break; } } @@ -1650,6 +1655,71 @@ Point SmallMapWindow::GetStationMiddle(const Station *st) const return ret; } +/** + * Take a screenshot of the contents of the smallmap window, at the current zoom level and mode + * This calls MakeSmallMapScreenshot which uses ScreenshotCallbackHandler as the screenshot callback + */ +void SmallMapWindow::TakeScreenshot() +{ + int32 width = ((MapMaxX() + MapMaxY()) * 2) / this->zoom; + int32 height = (MapMaxX() + MapMaxY() + 1) / this->zoom; + + int32 saved_scroll_x = this->scroll_x; + int32 saved_scroll_y = this->scroll_y; + int32 saved_subscroll = this->subscroll; + this->subscroll = 0; + MakeSmallMapScreenshot(width, height, this); + this->scroll_x = saved_scroll_x; + this->scroll_y = saved_scroll_y; + this->subscroll = saved_subscroll; +} + +/** + * Callback called by the screenshot code to draw a section of the smallmap to the output buffer + * @param buf Videobuffer with same bitdepth as current blitter + * @param y First line to render + * @param pitch Pitch of the videobuffer + * @param n Number of lines to render + */ +void SmallMapWindow::ScreenshotCallbackHandler(void *buf, uint y, uint pitch, uint n) +{ + DrawPixelInfo dpi, *old_dpi; + + /* We are no longer rendering to the screen */ + DrawPixelInfo old_screen = _screen; + bool old_disable_anim = _screen_disable_anim; + + _screen.dst_ptr = buf; + _screen.width = pitch; + _screen.height = n; + _screen.pitch = pitch; + _screen_disable_anim = true; + + old_dpi = _cur_dpi; + _cur_dpi = &dpi; + + dpi.dst_ptr = buf; + dpi.height = n; + dpi.width = ((MapMaxX() + MapMaxY()) * 2) / this->zoom; + dpi.pitch = pitch; + dpi.zoom = ZOOM_LVL_NORMAL; + dpi.left = 0; + dpi.top = y; + + int32 pos = (((int32)MapMaxX() + 1) * TILE_PIXELS) / 4; + this->scroll_x = pos; + this->scroll_y = -pos; + + /* make the screenshot */ + this->DrawSmallMap(&dpi, false); + + _cur_dpi = old_dpi; + + /* Switch back to rendering to the screen */ + _screen = old_screen; + _screen_disable_anim = old_disable_anim; +} + SmallMapWindow::SmallMapType SmallMapWindow::map_type = SMT_CONTOUR; bool SmallMapWindow::show_towns = true; int SmallMapWindow::max_heightlevel = -1; @@ -1798,6 +1868,7 @@ static const NWidgetPart _nested_smallmap_widgets[] = { NWidgetFunction(SmallMapDisplay), // Smallmap display and legend bar + image buttons. /* Bottom button row and resize box. */ NWidget(NWID_HORIZONTAL), + NWidget(WWT_PUSHTXTBTN, COLOUR_BROWN, WID_SM_SCREENSHOT), SetDataTip(STR_SMALLMAP_SCREENSHOT, STR_NULL), NWidget(NWID_SELECTION, INVALID_COLOUR, WID_SM_SELECT_BUTTONS), NWidget(NWID_HORIZONTAL, NC_EQUALSIZE), NWidget(WWT_PUSHTXTBTN, COLOUR_BROWN, WID_SM_ENABLE_ALL), SetDataTip(STR_SMALLMAP_ENABLE_ALL, STR_NULL), diff --git a/src/smallmap_gui.h b/src/smallmap_gui.h index 2903544a69..8e54531019 100644 --- a/src/smallmap_gui.h +++ b/src/smallmap_gui.h @@ -157,7 +157,7 @@ protected: void DrawSmallMapColumn(void *dst, uint xc, uint yc, int pitch, int reps, int start_pos, int end_pos, Blitter *blitter) const; void DrawVehicles(const DrawPixelInfo *dpi, Blitter *blitter) const; void DrawTowns(const DrawPixelInfo *dpi) const; - void DrawSmallMap(DrawPixelInfo *dpi) const; + void DrawSmallMap(DrawPixelInfo *dpi, bool draw_indicators = true) const; Point RemapTile(int tile_x, int tile_y) const; Point PixelToTile(int px, int py, int *sub, bool add_sub = true) const; @@ -189,6 +189,9 @@ public: virtual void OnTick(); virtual void OnScroll(Point delta); virtual void OnMouseOver(Point pt, int widget); + + void TakeScreenshot(); + void ScreenshotCallbackHandler(void *buf, uint y, uint pitch, uint n); }; #endif /* SMALLMAP_GUI_H */ diff --git a/src/widgets/smallmap_widget.h b/src/widgets/smallmap_widget.h index 0b1daea03f..9665c63892 100644 --- a/src/widgets/smallmap_widget.h +++ b/src/widgets/smallmap_widget.h @@ -34,6 +34,7 @@ enum SmallMapWidgets { WID_SM_ENABLE_ALL, ///< Button to enable display of all legend entries. WID_SM_DISABLE_ALL, ///< Button to disable display of all legend entries. WID_SM_SHOW_HEIGHT, ///< Show heightmap toggle button. + WID_SM_SCREENSHOT, ///< Button to take smallmap screenshots }; #endif /* WIDGETS_SMALLMAP_WIDGET_H */