OpenTTD Source 20260311-master-g511d3794ce
screenshot.cpp
Go to the documentation of this file.
1/*
2 * This file is part of OpenTTD.
3 * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
4 * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
5 * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <https://www.gnu.org/licenses/old-licenses/gpl-2.0>.
6 */
7
9
10#include "stdafx.h"
11#include "core/backup_type.hpp"
12#include "fileio_func.h"
13#include "viewport_func.h"
14#include "gfx_func.h"
15#include "screenshot.h"
16#include "screenshot_gui.h"
17#include "blitter/factory.hpp"
18#include "zoom_func.h"
19#include "saveload/saveload.h"
20#include "company_func.h"
21#include "strings_func.h"
22#include "error.h"
23#include "textbuf_gui.h"
24#include "window_gui.h"
25#include "window_func.h"
26#include "tile_map.h"
27#include "landscape.h"
29#include "smallmap_gui.h"
30#include "screenshot_type.h"
31
32#include "table/strings.h"
33
34#include "safeguards.h"
35
36static const std::string_view SCREENSHOT_NAME = "screenshot";
37static const std::string_view HEIGHTMAP_NAME = "heightmap";
38
40static std::string _screenshot_name;
43
50{
52 if (providers.empty()) return nullptr;
53
54 auto it = std::ranges::find(providers, _screenshot_format_name, &ScreenshotProvider::GetName);
55 if (it != std::end(providers)) return *it;
56
57 return providers.front();
58}
59
65{
66 auto provider = GetScreenshotProvider();
67 if (provider == nullptr) return {};
68
69 return provider->GetName();
70}
71
80static void CurrentScreenCallback(void *buf, uint y, uint pitch, uint n)
81{
83 void *src = blitter->MoveTo(_screen.dst_ptr, 0, y);
84 blitter->CopyImageToBuffer(src, buf, _screen.width, n, pitch);
85}
86
95static void LargeWorldCallback(Viewport &vp, void *buf, uint y, uint pitch, uint n)
96{
97 DrawPixelInfo dpi{
98 .dst_ptr = buf,
99 .left = 0,
100 .top = static_cast<int>(y),
101 .width = vp.width,
102 .height = static_cast<int>(n),
103 .pitch = static_cast<int>(pitch),
105 };
106
107 /* We are no longer rendering to the screen */
108 AutoRestoreBackup screen_backup(_screen, {
109 .dst_ptr = buf,
110 .left = 0,
111 .top = 0,
112 .width = static_cast<int>(pitch),
113 .height = static_cast<int>(n),
114 .pitch = static_cast<int>(pitch),
115 .zoom = ZoomLevel::Min
116 });
117 AutoRestoreBackup disable_anim_backup(_screen_disable_anim, true);
118 AutoRestoreBackup dpi_backup(_cur_dpi, &dpi);
119
120 /* Render viewport in blocks of 1600 pixels width */
121 int left = 0;
122 while (vp.width - left != 0) {
123 int wx = std::min(vp.width - left, 1600);
124 left += wx;
125
126 ViewportDoDraw(vp,
127 ScaleByZoom(left - wx - vp.left, vp.zoom) + vp.virtual_left,
128 ScaleByZoom(y - vp.top, vp.zoom) + vp.virtual_top,
129 ScaleByZoom(left - vp.left, vp.zoom) + vp.virtual_left,
130 ScaleByZoom((y + n) - vp.top, vp.zoom) + vp.virtual_top
131 );
132 }
133}
134
142static std::string_view MakeScreenshotName(std::string_view default_fn, std::string_view ext, bool crashlog = false)
143{
144 bool generate = _screenshot_name.empty();
145
146 if (generate) {
147 if (_game_mode == GM_EDITOR || _game_mode == GM_MENU || _local_company == COMPANY_SPECTATOR) {
148 _screenshot_name = default_fn;
149 } else {
151 }
152 }
153
154 /* Handle user-specified filenames ending in # with automatic numbering */
155 if (_screenshot_name.ends_with("#")) {
156 generate = true;
157 _screenshot_name.pop_back();
158 }
159
160 size_t len = _screenshot_name.size();
161 /* Add extension to screenshot file */
162 format_append(_screenshot_name, ".{}", ext);
163
164 std::string_view screenshot_dir = crashlog ? _personal_dir : FiosGetScreenshotDir();
165
166 for (uint serial = 1;; serial++) {
167 _full_screenshot_path = fmt::format("{}{}", screenshot_dir, _screenshot_name);
168
169 if (!generate) break; // allow overwriting of non-automatic filenames
171 /* If file exists try another one with same name, but just with a higher index */
172 _screenshot_name.erase(len);
173 format_append(_screenshot_name, "#{}.{}", serial, ext);
174 }
175
177}
178
184static bool MakeSmallScreenshot(bool crashlog)
185{
186 auto provider = GetScreenshotProvider();
187 if (provider == nullptr) return false;
188
189 return provider->MakeImage(MakeScreenshotName(SCREENSHOT_NAME, provider->GetName(), crashlog), CurrentScreenCallback, _screen.width, _screen.height,
190 BlitterFactory::GetCurrentBlitter()->GetScreenDepth(), _cur_palette.palette);
191}
192
200static Viewport SetupScreenshotViewport(ScreenshotType t, uint32_t width = 0, uint32_t height = 0)
201{
202 Viewport vp{};
203
204 switch(t) {
205 case SC_VIEWPORT:
206 case SC_CRASHLOG: {
207 assert(width == 0 && height == 0);
208
209 Window *w = GetMainWindow();
210 vp.virtual_left = w->viewport->virtual_left;
211 vp.virtual_top = w->viewport->virtual_top;
212 vp.virtual_width = w->viewport->virtual_width;
213 vp.virtual_height = w->viewport->virtual_height;
214
215 /* Compute pixel coordinates */
216 vp.left = 0;
217 vp.top = 0;
218 vp.width = _screen.width;
219 vp.height = _screen.height;
220 vp.overlay = w->viewport->overlay;
221 break;
222 }
223 case SC_WORLD: {
224 assert(width == 0 && height == 0);
225
226 /* Determine world coordinates of screenshot */
228
229 TileIndex north_tile = _settings_game.construction.freeform_edges ? TileXY(1, 1) : TileXY(0, 0);
230 TileIndex south_tile{Map::Size() - 1};
231
232 /* We need to account for a hill or high building at tile 0,0. */
233 int extra_height_top = TilePixelHeight(north_tile) + 150;
234 /* If there is a hill at the bottom don't create a large black area. */
235 int reclaim_height_bottom = TilePixelHeight(south_tile);
236
237 vp.virtual_left = RemapCoords(TileX(south_tile) * TILE_SIZE, TileY(north_tile) * TILE_SIZE, 0).x;
238 vp.virtual_top = RemapCoords(TileX(north_tile) * TILE_SIZE, TileY(north_tile) * TILE_SIZE, extra_height_top).y;
239 vp.virtual_width = RemapCoords(TileX(north_tile) * TILE_SIZE, TileY(south_tile) * TILE_SIZE, 0).x - vp.virtual_left + 1;
240 vp.virtual_height = RemapCoords(TileX(south_tile) * TILE_SIZE, TileY(south_tile) * TILE_SIZE, reclaim_height_bottom).y - vp.virtual_top + 1;
241
242 /* Compute pixel coordinates */
243 vp.left = 0;
244 vp.top = 0;
247 vp.overlay = nullptr;
248 break;
249 }
250 default: {
251 vp.zoom = (t == SC_ZOOMEDIN) ? _settings_client.gui.zoom_min : ZoomLevel::Viewport;
252
253 Window *w = GetMainWindow();
254 vp.virtual_left = w->viewport->virtual_left;
255 vp.virtual_top = w->viewport->virtual_top;
256
257 if (width == 0 || height == 0) {
258 vp.virtual_width = w->viewport->virtual_width;
259 vp.virtual_height = w->viewport->virtual_height;
260 } else {
261 vp.virtual_width = width << to_underlying(vp.zoom);
262 vp.virtual_height = height << to_underlying(vp.zoom);
263 }
264
265 /* Compute pixel coordinates */
266 vp.left = 0;
267 vp.top = 0;
270 vp.overlay = nullptr;
271 break;
272 }
273 }
274
275 return vp;
276}
277
285static bool MakeLargeWorldScreenshot(ScreenshotType t, uint32_t width = 0, uint32_t height = 0)
286{
287 auto provider = GetScreenshotProvider();
288 if (provider == nullptr) return false;
289
290 Viewport vp = SetupScreenshotViewport(t, width, height);
291
292 return provider->MakeImage(MakeScreenshotName(SCREENSHOT_NAME, provider->GetName()),
293 [&](void *buf, uint y, uint pitch, uint n) {
294 LargeWorldCallback(vp, buf, y, pitch, n);
295 }, vp.width, vp.height, BlitterFactory::GetCurrentBlitter()->GetScreenDepth(), _cur_palette.palette);
296}
297
305static void HeightmapCallback(void *buffer, uint y, uint, uint n)
306{
307 uint8_t *buf = (uint8_t *)buffer;
308 while (n > 0) {
309 TileIndex ti = TileXY(Map::MaxX(), y);
310 for (uint x = Map::MaxX(); true; x--) {
311 *buf = 256 * TileHeight(ti) / (1 + _heightmap_highest_peak);
312 buf++;
313 if (x == 0) break;
314 ti = TileAddXY(ti, -1, 0);
315 }
316 y++;
317 n--;
318 }
319}
320
326bool MakeHeightmapScreenshot(std::string_view filename)
327{
328 auto provider = GetScreenshotProvider();
329 if (provider == nullptr) return false;
330
331 Colour palette[256];
332 for (uint i = 0; i < lengthof(palette); i++) {
333 palette[i].a = 0xff;
334 palette[i].r = i;
335 palette[i].g = i;
336 palette[i].b = i;
337 }
338
340 for (const auto tile : Map::Iterate()) {
341 uint h = TileHeight(tile);
343 }
344
345 return provider->MakeImage(filename, HeightmapCallback, Map::SizeX(), Map::SizeY(), 8, palette);
346}
347
349
354static void ScreenshotConfirmationCallback(Window *, bool confirmed)
355{
356 if (confirmed) MakeScreenshot(_confirmed_screenshot_type, {});
357}
358
366{
368
369 bool heightmap_or_minimap = t == SC_HEIGHTMAP || t == SC_MINIMAP;
370 uint64_t width = (heightmap_or_minimap ? Map::SizeX() : vp.width);
371 uint64_t height = (heightmap_or_minimap ? Map::SizeY() : vp.height);
372
373 if (width * height > 8192 * 8192) {
374 /* Ask for confirmation */
376 ShowQuery(
377 GetEncodedString(STR_WARNING_SCREENSHOT_SIZE_CAPTION),
378 GetEncodedString(STR_WARNING_SCREENSHOT_SIZE_MESSAGE, width, height), nullptr, ScreenshotConfirmationCallback);
379 } else {
380 /* Less than 64M pixels, just do it */
381 MakeScreenshot(t, {});
382 }
383}
384
393static bool RealMakeScreenshot(ScreenshotType t, const std::string &name, uint32_t width, uint32_t height)
394{
395 if (t == SC_VIEWPORT) {
396 /* First draw the dirty parts of the screen and only then change the name
397 * of the screenshot. This way the screenshot will always show the name
398 * of the previous screenshot in the 'successful' message instead of the
399 * name of the new screenshot (or an empty name). */
401 UndrawMouseCursor();
404 }
405
406 _screenshot_name = name;
407
408 bool ret;
409 switch (t) {
410 case SC_VIEWPORT:
411 ret = MakeSmallScreenshot(false);
412 break;
413
414 case SC_CRASHLOG:
415 ret = MakeSmallScreenshot(true);
416 break;
417
418 case SC_ZOOMEDIN:
419 case SC_DEFAULTZOOM:
420 ret = MakeLargeWorldScreenshot(t, width, height);
421 break;
422
423 case SC_WORLD:
425 break;
426
427 case SC_HEIGHTMAP: {
428 auto provider = GetScreenshotProvider();
429 if (provider == nullptr) {
430 ret = false;
431 } else {
432 ret = MakeHeightmapScreenshot(MakeScreenshotName(HEIGHTMAP_NAME, provider->GetName()));
433 }
434 break;
435 }
436
437 case SC_MINIMAP:
439 break;
440
441 default:
442 NOT_REACHED();
443 }
444
445 if (ret) {
446 if (t == SC_HEIGHTMAP) {
447 ShowErrorMessage(GetEncodedString(STR_MESSAGE_HEIGHTMAP_SUCCESSFULLY, _screenshot_name, _heightmap_highest_peak), {}, WL_WARNING);
448 } else {
449 ShowErrorMessage(GetEncodedString(STR_MESSAGE_SCREENSHOT_SUCCESSFULLY, _screenshot_name), {}, WL_WARNING);
450 }
451 } else {
452 ShowErrorMessage(GetEncodedString(STR_ERROR_SCREENSHOT_FAILED), {}, WL_ERROR);
453 }
454
455 return ret;
456}
457
468bool MakeScreenshot(ScreenshotType t, const std::string &name, uint32_t width, uint32_t height)
469{
470 if (t == SC_CRASHLOG) {
471 /* Video buffer might or might not be locked. */
473
474 return RealMakeScreenshot(t, name, width, height);
475 }
476
477 VideoDriver::GetInstance()->QueueOnMainThread([=] { // Capture by value to not break scope.
478 RealMakeScreenshot(t, name, width, height);
479 });
480
481 return true;
482}
483
484
485static void MinimapScreenCallback(void *buf, uint y, uint pitch, uint n)
486{
487 uint32_t *ubuf = (uint32_t *)buf;
488 uint num = (pitch * n);
489 for (uint i = 0; i < num; i++) {
490 uint row = y + (int)(i / pitch);
491 uint col = (Map::SizeX() - 1) - (i % pitch);
492
493 TileIndex tile = TileXY(col, row);
494 uint8_t val = GetSmallMapOwnerPixels(tile, GetTileType(tile), IncludeHeightmap::Never) & 0xFF;
495
496 uint32_t colour_buf = 0;
497 colour_buf = (_cur_palette.palette[val].b << 0);
498 colour_buf |= (_cur_palette.palette[val].g << 8);
499 colour_buf |= (_cur_palette.palette[val].r << 16);
500
501 *ubuf = colour_buf;
502 ubuf++; // Skip alpha
503 }
504}
505
511{
512 auto provider = GetScreenshotProvider();
513 if (provider == nullptr) return false;
514
515 return provider->MakeImage(MakeScreenshotName(SCREENSHOT_NAME, provider->GetName()), MinimapScreenCallback, Map::SizeX(), Map::SizeY(), 32, _cur_palette.palette);
516}
Class for backupping variables and making sure they are restored later.
static Blitter * GetCurrentBlitter()
Get the current active blitter (always set by calling SelectBlitter).
Definition factory.hpp:139
How all blitters should look like.
Definition base.hpp:29
virtual void * MoveTo(void *video, int x, int y)=0
Move the destination pointer the requested amount x and y, keeping in mind any pitch and bpp of the r...
virtual void CopyImageToBuffer(const void *video, void *dst, int width, int height, int dst_pitch)=0
Copy from the screen to a buffer in a palette format for 8bpp and RGBA format for 32bpp.
static std::vector< const TProviderType * > & GetProviders()
Get the currently known providers.
Base interface for a SoundLoader implementation.
void QueueOnMainThread(std::function< void()> &&func)
Queue a function to be called on the main thread with game state lock held and video buffer locked.
static VideoDriver * GetInstance()
Get the currently active instance of the video driver.
CompanyID _local_company
Company controlled by the human player at this client. Can also be COMPANY_SPECTATOR.
Functions related to companies.
static constexpr CompanyID COMPANY_SPECTATOR
The client is spectating.
constexpr std::underlying_type_t< enum_type > to_underlying(enum_type e)
Implementation of std::to_underlying (from C++23).
Definition enum_type.hpp:21
Functions related to errors.
@ WL_WARNING
Other information.
Definition error.h:25
@ WL_ERROR
Errors (eg. saving/loading failed).
Definition error.h:26
void ShowErrorMessage(EncodedString &&summary_msg, int x, int y, CommandCost &cc)
Display an error message in a window.
Factory to 'query' all available blitters.
std::string _personal_dir
custom directory for personal settings, saves, newgrf, etc.
Definition fileio.cpp:878
bool FileExists(std::string_view filename)
Test whether the given filename exists.
Definition fileio.cpp:132
Functions for standard in/out file operations.
std::string_view FiosGetScreenshotDir()
Get the directory for screenshots.
Definition fios.cpp:579
bool _screen_disable_anim
Disable palette animation (important for 32bpp-anim blitter during giant screenshot).
Definition gfx.cpp:47
Functions related to the gfx engine.
Palette _cur_palette
Current palette.
Definition palette.cpp:24
void DrawDirtyBlocks()
Repaints the rectangle blocks which are marked as 'dirty'.
Definition gfx.cpp:1457
Functions related to OTTD's landscape.
Point RemapCoords(int x, int y, int z)
Map 3D world or tile coordinate to equivalent 2D coordinate as used in the viewports and smallmap.
Definition landscape.h:81
TileIndex TileAddXY(TileIndex tile, int x, int y)
Adds a given offset to a tile.
Definition map_func.h:474
static TileIndex TileXY(uint x, uint y)
Returns the TileIndex of a coordinate.
Definition map_func.h:376
static uint TileY(TileIndex tile)
Get the Y component of a tile.
Definition map_func.h:429
static uint TileX(TileIndex tile)
Get the X component of a tile.
Definition map_func.h:419
void ShowQuery(EncodedString &&caption, EncodedString &&message, Window *parent, QueryCallbackProc *callback, bool focus)
Show a confirmation window with standard 'yes' and 'no' buttons The window is aligned to the centre o...
A number of safeguards to prevent using unsafe methods.
std::string GenerateDefaultSaveName()
Get the default name for a savegame or screenshot.
Functions/types related to saving and loading games.
static void ScreenshotConfirmationCallback(Window *, bool confirmed)
Callback on the confirmation window for huge screenshots.
static bool RealMakeScreenshot(ScreenshotType t, const std::string &name, uint32_t width, uint32_t height)
Make a screenshot.
void MakeScreenshotWithConfirm(ScreenshotType t)
Make a screenshot.
static ScreenshotType _confirmed_screenshot_type
Screenshot type the current query is about to confirm.
static const std::string_view HEIGHTMAP_NAME
Default filename of a saved heightmap.
std::string _screenshot_format_name
Extension of the current screenshot format.
static bool MakeSmallScreenshot(bool crashlog)
Make a screenshot of the current screen.
bool MakeMinimapWorldScreenshot()
Make a minimap screenshot.
static void HeightmapCallback(void *buffer, uint y, uint, uint n)
Callback for generating a heightmap.
static bool MakeLargeWorldScreenshot(ScreenshotType t, uint32_t width=0, uint32_t height=0)
Make a screenshot of the map.
std::string_view GetCurrentScreenshotExtension()
Get filename extension of current screenshot file format.
static std::string _screenshot_name
Filename of the screenshot file.
static const ScreenshotProvider * GetScreenshotProvider()
Get the screenshot provider for the selected format.
static void CurrentScreenCallback(void *buf, uint y, uint pitch, uint n)
Callback of the screenshot generator that dumps the current video buffer.
bool MakeScreenshot(ScreenshotType t, const std::string &name, uint32_t width, uint32_t height)
Schedule making a screenshot.
static void LargeWorldCallback(Viewport &vp, void *buf, uint y, uint pitch, uint n)
generate a large piece of the world
std::string _full_screenshot_path
Pathname of the screenshot file.
bool MakeHeightmapScreenshot(std::string_view filename)
Make a heightmap of the current map.
static std::string_view MakeScreenshotName(std::string_view default_fn, std::string_view ext, bool crashlog=false)
Construct a pathname for a screenshot file.
uint _heightmap_highest_peak
When saving a heightmap, this contains the highest peak on the map.
static const std::string_view SCREENSHOT_NAME
Default filename of a saved screenshot.
static Viewport SetupScreenshotViewport(ScreenshotType t, uint32_t width=0, uint32_t height=0)
Configure a Viewport for rendering (a part of) the map into a screenshot.
Functions to make screenshots.
ScreenshotType
Type of requested screenshot.
Definition screenshot.h:16
@ SC_VIEWPORT
Screenshot of viewport.
Definition screenshot.h:17
@ SC_CRASHLOG
Raw screenshot from blitter buffer.
Definition screenshot.h:18
@ SC_ZOOMEDIN
Fully zoomed in screenshot of the visible area.
Definition screenshot.h:19
@ SC_HEIGHTMAP
Heightmap of the world.
Definition screenshot.h:22
@ SC_WORLD
World screenshot.
Definition screenshot.h:21
@ SC_MINIMAP
Minimap screenshot.
Definition screenshot.h:23
@ SC_DEFAULTZOOM
Zoomed to default zoom level screenshot of the visible area.
Definition screenshot.h:20
void SetScreenshotWindowVisibility(bool hide)
Set the visibility of the screenshot window when taking a screenshot.
GUI functions related to screenshots.
Types related to screenshot providers.
GameSettings _settings_game
Game settings of a running game or the scenario editor.
Definition settings.cpp:61
ClientSettings _settings_client
The current settings for this game.
Definition settings.cpp:60
uint32_t GetSmallMapOwnerPixels(TileIndex tile, TileType t, IncludeHeightmap include_heightmap)
Return the colour a tile would be displayed with in the small map in mode "Owner".
Smallmap GUI functions.
@ Never
Never include the heightmap.
Definition of base types and functions in a cross-platform compatible way.
#define lengthof(array)
Return the length of an fixed size array.
Definition stdafx.h:271
EncodedString GetEncodedString(StringID str)
Encode a string with no parameters into an encoded string.
Definition strings.cpp:90
Functions related to OTTD's strings.
Class to backup a specific variable and restore it upon destruction of this object to prevent stack v...
T y
Y coordinate.
T x
X coordinate.
Data about how and where to blit pixels.
Definition gfx_type.h:157
static uint SizeX()
Get the size of the map along the X.
Definition map_func.h:262
static uint SizeY()
Get the size of the map along the Y.
Definition map_func.h:271
static IterateWrapper Iterate()
Returns an iterable ensemble of all Tiles.
Definition map_func.h:366
static uint MaxX()
Gets the maximum X coordinate within the map, including TileType::Void.
Definition map_func.h:289
static uint Size()
Get the size of the map.
Definition map_func.h:280
Helper struct to ensure the video buffer is locked and ready for drawing.
Data structure for viewport, display of a part of the world.
int top
Screen coordinate top edge of the viewport.
int width
Screen width of the viewport.
ZoomLevel zoom
The zoom level of the viewport.
int virtual_top
Virtual top coordinate.
int virtual_left
Virtual left coordinate.
int virtual_width
width << zoom
int left
Screen coordinate left edge of the viewport.
int height
Screen height of the viewport.
int virtual_height
height << zoom
Data structure for an opened window.
Definition window_gui.h:274
std::unique_ptr< ViewportData > viewport
Pointer to viewport data, if present.
Definition window_gui.h:319
Stuff related to the text buffer GUI.
Map writing/reading functions for tiles.
static uint TileHeight(Tile tile)
Returns the height of a tile.
Definition tile_map.h:29
uint TilePixelHeight(Tile tile)
Returns the height of a tile in pixels.
Definition tile_map.h:72
static TileType GetTileType(Tile tile)
Get the tiletype of a given tile.
Definition tile_map.h:96
StrongType::Typedef< uint32_t, struct TileIndexTag, StrongType::Compare, StrongType::Integer, StrongType::Compatible< int32_t >, StrongType::Compatible< int64_t > > TileIndex
The index/ID of a Tile.
Definition tile_type.h:92
static constexpr uint TILE_SIZE
Tile size in world coordinates.
Definition tile_type.h:15
Base of all video drivers.
Functions related to (drawing on) viewports.
std::mutex lock
synchronization for playback status fields
Definition win32_m.cpp:35
Window * GetMainWindow()
Get the main window, i.e.
Definition window.cpp:1195
Window functions not directly related to making/drawing windows.
Functions, definitions and such used only by the GUI.
Functions related to zooming.
int ScaleByZoom(int value, ZoomLevel zoom)
Scale by zoom level, usually shift left (when zoom > ZoomLevel::Min) When shifting right,...
Definition zoom_func.h:22
int UnScaleByZoom(int value, ZoomLevel zoom)
Scale by zoom level, usually shift right (when zoom > ZoomLevel::Min) When shifting right,...
Definition zoom_func.h:34
@ Min
Minimum zoom level.
Definition zoom_type.h:23
@ WorldScreenshot
Default zoom level for the world screen shot.
Definition zoom_type.h:42
@ Viewport
Default zoom level for viewports.
Definition zoom_type.h:34