Merge branch 'extra_large_maps' into extra_large_maps-sx

Conflicts:
	src/genworld_gui.cpp
	src/map_type.h
	src/newgrf_debug_gui.cpp
This commit is contained in:
Jonathan G Rennison
2015-09-11 22:39:01 +01:00
6 changed files with 104 additions and 18 deletions

View File

@@ -20,6 +20,7 @@
#include "sound_func.h" #include "sound_func.h"
#include "fios.h" #include "fios.h"
#include "string_func.h" #include "string_func.h"
#include "gui.h"
#include "widgets/dropdown_type.h" #include "widgets/dropdown_type.h"
#include "widgets/dropdown_func.h" #include "widgets/dropdown_func.h"
#include "querystring_gui.h" #include "querystring_gui.h"
@@ -281,12 +282,37 @@ static void LandscapeGenerationCallback(Window *w, bool confirmed)
if (confirmed) StartGeneratingLandscape((GenerateLandscapeWindowMode)w->window_number); if (confirmed) StartGeneratingLandscape((GenerateLandscapeWindowMode)w->window_number);
} }
static DropDownList *BuildMapsizeDropDown() /**
* Check if map size set lies in allowed boundaries.
* @param print_warning If set to true, messagebox with warning is printed out if size is outside limits.
* @return true if size is ok, false otherwise.
*/
static bool CheckMapSize(bool print_warning = true)
{
uint64 tiles = 1ULL << (_settings_newgame.game_creation.map_x + _settings_newgame.game_creation.map_y);
if (_settings_newgame.game_creation.map_x + _settings_newgame.game_creation.map_y > MAX_MAP_TILES_BITS) {
if (print_warning) {
SetDParam(0, MAX_MAP_TILES);
SetDParam(1, tiles);
ShowErrorMessage(STR_MAPGEN_TOO_MANY_TILES_MESSAGE, INVALID_STRING_ID, WL_ERROR, 0, 0);
}
return false;
}
return true;
}
/**
* Build dropdown list with map sizes
* Dimension selected in the other dropdown is used to suggest which choices are 'valid'
* @param other_dimension Dimension specified by the second dropdown.
*/
static DropDownList *BuildMapsizeDropDown(int other_dimension)
{ {
DropDownList *list = new DropDownList(); DropDownList *list = new DropDownList();
for (uint i = MIN_MAP_SIZE_BITS; i <= MAX_MAP_SIZE_BITS; i++) { for (uint i = MIN_MAP_SIZE_BITS; i <= MAX_MAP_SIZE_BITS; i++) {
DropDownListParamStringItem *item = new DropDownListParamStringItem(STR_JUST_INT, i, false); DropDownListParamStringItem *item = new DropDownListParamStringItem((i + other_dimension > MAX_MAP_TILES_BITS) ? STR_RED_INT : STR_JUST_INT, i, false);
item->SetParam(0, 1 << i); item->SetParam(0, 1 << i);
*list->Append() = item; *list->Append() = item;
} }
@@ -314,6 +340,14 @@ struct GenerateLandscapeWindow : public Window {
char name[64]; char name[64];
GenerateLandscapeWindowMode mode; GenerateLandscapeWindowMode mode;
void SetDropDownColor()
{
/* Draw sizes in mapsize selection dropdowns in red if too large size is selected */
bool mapsize_valid = CheckMapSize(false);
this->GetWidget<NWidgetCore>(WID_GL_MAPSIZE_X_PULLDOWN)->widget_data = mapsize_valid ? STR_JUST_INT : STR_RED_INT;
this->GetWidget<NWidgetCore>(WID_GL_MAPSIZE_Y_PULLDOWN)->widget_data = mapsize_valid ? STR_JUST_INT : STR_RED_INT;
}
GenerateLandscapeWindow(WindowDesc *desc, WindowNumber number = 0) : Window(desc) GenerateLandscapeWindow(WindowDesc *desc, WindowNumber number = 0) : Window(desc)
{ {
this->InitNested(number); this->InitNested(number);
@@ -322,6 +356,8 @@ struct GenerateLandscapeWindow : public Window {
this->mode = (GenerateLandscapeWindowMode)this->window_number; this->mode = (GenerateLandscapeWindowMode)this->window_number;
SetDropDownColor();
/* Disable town, industry and trees in SE */ /* Disable town, industry and trees in SE */
this->SetWidgetDisabledState(WID_GL_TOWN_PULLDOWN, _game_mode == GM_EDITOR); this->SetWidgetDisabledState(WID_GL_TOWN_PULLDOWN, _game_mode == GM_EDITOR);
this->SetWidgetDisabledState(WID_GL_INDUSTRY_PULLDOWN, _game_mode == GM_EDITOR); this->SetWidgetDisabledState(WID_GL_INDUSTRY_PULLDOWN, _game_mode == GM_EDITOR);
@@ -538,11 +574,11 @@ struct GenerateLandscapeWindow : public Window {
break; break;
case WID_GL_MAPSIZE_X_PULLDOWN: // Mapsize X case WID_GL_MAPSIZE_X_PULLDOWN: // Mapsize X
ShowDropDownList(this, BuildMapsizeDropDown(), _settings_newgame.game_creation.map_x, WID_GL_MAPSIZE_X_PULLDOWN); ShowDropDownList(this, BuildMapsizeDropDown(_settings_newgame.game_creation.map_y), _settings_newgame.game_creation.map_x, WID_GL_MAPSIZE_X_PULLDOWN);
break; break;
case WID_GL_MAPSIZE_Y_PULLDOWN: // Mapsize Y case WID_GL_MAPSIZE_Y_PULLDOWN: // Mapsize Y
ShowDropDownList(this, BuildMapsizeDropDown(), _settings_newgame.game_creation.map_y, WID_GL_MAPSIZE_Y_PULLDOWN); ShowDropDownList(this, BuildMapsizeDropDown(_settings_newgame.game_creation.map_x), _settings_newgame.game_creation.map_y, WID_GL_MAPSIZE_Y_PULLDOWN);
break; break;
case WID_GL_TOWN_PULLDOWN: // Number of towns case WID_GL_TOWN_PULLDOWN: // Number of towns
@@ -554,6 +590,7 @@ struct GenerateLandscapeWindow : public Window {
break; break;
case WID_GL_GENERATE_BUTTON: { // Generate case WID_GL_GENERATE_BUTTON: { // Generate
if (!CheckMapSize()) break;
/* Get rotated map size. */ /* Get rotated map size. */
uint map_x; uint map_x;
uint map_y; uint map_y;
@@ -716,8 +753,14 @@ struct GenerateLandscapeWindow : public Window {
virtual void OnDropdownSelect(int widget, int index) virtual void OnDropdownSelect(int widget, int index)
{ {
switch (widget) { switch (widget) {
case WID_GL_MAPSIZE_X_PULLDOWN: _settings_newgame.game_creation.map_x = index; break; case WID_GL_MAPSIZE_X_PULLDOWN:
case WID_GL_MAPSIZE_Y_PULLDOWN: _settings_newgame.game_creation.map_y = index; break; _settings_newgame.game_creation.map_x = index;
SetDropDownColor();
break;
case WID_GL_MAPSIZE_Y_PULLDOWN:
_settings_newgame.game_creation.map_y = index;
SetDropDownColor();
break;
case WID_GL_TREE_PULLDOWN: _settings_newgame.game_creation.tree_placer = index; break; case WID_GL_TREE_PULLDOWN: _settings_newgame.game_creation.tree_placer = index; break;
case WID_GL_RIVER_PULLDOWN: _settings_newgame.game_creation.amount_of_rivers = index; break; case WID_GL_RIVER_PULLDOWN: _settings_newgame.game_creation.amount_of_rivers = index; break;
case WID_GL_SMOOTHNESS_PULLDOWN: _settings_newgame.game_creation.tgen_smoothness = index; break; case WID_GL_SMOOTHNESS_PULLDOWN: _settings_newgame.game_creation.tgen_smoothness = index; break;
@@ -881,10 +924,19 @@ struct CreateScenarioWindow : public Window
{ {
uint widget_id; uint widget_id;
void SetDropDownColor()
{
/* Draw sizes in mapsize selection dropdowns in red if too large size is selected */
bool mapsize_valid = CheckMapSize(false);
this->GetWidget<NWidgetCore>(WID_CS_MAPSIZE_X_PULLDOWN)->widget_data = mapsize_valid ? STR_JUST_INT : STR_RED_INT;
this->GetWidget<NWidgetCore>(WID_CS_MAPSIZE_Y_PULLDOWN)->widget_data = mapsize_valid ? STR_JUST_INT : STR_RED_INT;
}
CreateScenarioWindow(WindowDesc *desc, WindowNumber window_number) : Window(desc) CreateScenarioWindow(WindowDesc *desc, WindowNumber window_number) : Window(desc)
{ {
this->InitNested(window_number); this->InitNested(window_number);
this->LowerWidget(_settings_newgame.game_creation.landscape + WID_CS_TEMPERATE); this->LowerWidget(_settings_newgame.game_creation.landscape + WID_CS_TEMPERATE);
SetDropDownColor();
} }
virtual void SetStringParameters(int widget) const virtual void SetStringParameters(int widget) const
@@ -908,6 +960,8 @@ struct CreateScenarioWindow : public Window
} }
} }
virtual void OnPaint() virtual void OnPaint()
{ {
this->SetWidgetDisabledState(WID_CS_START_DATE_DOWN, _settings_newgame.game_creation.starting_year <= MIN_YEAR); this->SetWidgetDisabledState(WID_CS_START_DATE_DOWN, _settings_newgame.game_creation.starting_year <= MIN_YEAR);
@@ -961,18 +1015,20 @@ struct CreateScenarioWindow : public Window
break; break;
case WID_CS_MAPSIZE_X_PULLDOWN: // Mapsize X case WID_CS_MAPSIZE_X_PULLDOWN: // Mapsize X
ShowDropDownList(this, BuildMapsizeDropDown(), _settings_newgame.game_creation.map_x, WID_CS_MAPSIZE_X_PULLDOWN); ShowDropDownList(this, BuildMapsizeDropDown(_settings_newgame.game_creation.map_y), _settings_newgame.game_creation.map_x, WID_CS_MAPSIZE_X_PULLDOWN);
break; break;
case WID_CS_MAPSIZE_Y_PULLDOWN: // Mapsize Y case WID_CS_MAPSIZE_Y_PULLDOWN: // Mapsize Y
ShowDropDownList(this, BuildMapsizeDropDown(), _settings_newgame.game_creation.map_y, WID_CS_MAPSIZE_Y_PULLDOWN); ShowDropDownList(this, BuildMapsizeDropDown(_settings_newgame.game_creation.map_x), _settings_newgame.game_creation.map_y, WID_CS_MAPSIZE_Y_PULLDOWN);
break; break;
case WID_CS_EMPTY_WORLD: // Empty world / flat world case WID_CS_EMPTY_WORLD: // Empty world / flat world
if (!CheckMapSize()) break;
StartGeneratingLandscape(GLWM_SCENARIO); StartGeneratingLandscape(GLWM_SCENARIO);
break; break;
case WID_CS_RANDOM_WORLD: // Generate case WID_CS_RANDOM_WORLD: // Generate
if (!CheckMapSize()) break;
ShowGenerateLandscape(); ShowGenerateLandscape();
break; break;
@@ -1031,6 +1087,8 @@ struct CreateScenarioWindow : public Window
case WID_CS_MAPSIZE_X_PULLDOWN: _settings_newgame.game_creation.map_x = index; break; case WID_CS_MAPSIZE_X_PULLDOWN: _settings_newgame.game_creation.map_x = index; break;
case WID_CS_MAPSIZE_Y_PULLDOWN: _settings_newgame.game_creation.map_y = index; break; case WID_CS_MAPSIZE_Y_PULLDOWN: _settings_newgame.game_creation.map_y = index; break;
} }
SetDropDownColor();
this->SetDirty(); this->SetDirty();
} }

View File

@@ -2753,6 +2753,7 @@ STR_MAPGEN_HEIGHTMAP_ROTATION :{BLACK}Heightma
STR_MAPGEN_HEIGHTMAP_NAME :{BLACK}Heightmap name: STR_MAPGEN_HEIGHTMAP_NAME :{BLACK}Heightmap name:
STR_MAPGEN_HEIGHTMAP_SIZE_LABEL :{BLACK}Size: STR_MAPGEN_HEIGHTMAP_SIZE_LABEL :{BLACK}Size:
STR_MAPGEN_HEIGHTMAP_SIZE :{ORANGE}{NUM} x {NUM} STR_MAPGEN_HEIGHTMAP_SIZE :{ORANGE}{NUM} x {NUM}
STR_MAPGEN_TOO_MANY_TILES_MESSAGE :{YELLOW}Too many tiles in map. Maximum number of tiles is {NUM}, you have selected {NUM}
STR_MAPGEN_MAX_HEIGHTLEVEL_QUERY_CAPT :{WHITE}Change maximum map height STR_MAPGEN_MAX_HEIGHTLEVEL_QUERY_CAPT :{WHITE}Change maximum map height
STR_MAPGEN_SNOW_LINE_QUERY_CAPT :{WHITE}Change snow line height STR_MAPGEN_SNOW_LINE_QUERY_CAPT :{WHITE}Change snow line height
@@ -4940,6 +4941,7 @@ STR_DATE_LONG_SMALL :{TINY_FONT}{BLA
STR_TINY_GROUP :{TINY_FONT}{GROUP} STR_TINY_GROUP :{TINY_FONT}{GROUP}
STR_BLACK_INT :{BLACK}{NUM} STR_BLACK_INT :{BLACK}{NUM}
STR_ORANGE_INT :{ORANGE}{NUM} STR_ORANGE_INT :{ORANGE}{NUM}
STR_RED_INT :{RED}{NUM}
STR_WHITE_SIGN :{WHITE}{SIGN} STR_WHITE_SIGN :{WHITE}{SIGN}
STR_TINY_BLACK_STATION :{TINY_FONT}{BLACK}{STATION} STR_TINY_BLACK_STATION :{TINY_FONT}{BLACK}{STATION}
STR_BLACK_STRING :{BLACK}{STRING} STR_BLACK_STRING :{BLACK}{STRING}

View File

@@ -40,17 +40,19 @@ TileExtended *_me = NULL; ///< Extended Tiles of the map
*/ */
void AllocateMap(uint size_x, uint size_y) void AllocateMap(uint size_x, uint size_y)
{ {
DEBUG(map, 2, "Min/max map size %d/%d, max map tiles %d", MIN_MAP_SIZE, MAX_MAP_SIZE, MAX_MAP_TILES);
DEBUG(map, 1, "Allocating map of size %dx%d", size_x, size_y);
/* Make sure that the map size is within the limits and that /* Make sure that the map size is within the limits and that
* size of both axes is a power of 2. */ * size of both axes is a power of 2. */
if (!IsInsideMM(size_x, MIN_MAP_SIZE, MAX_MAP_SIZE + 1) || if (size_x * size_y > MAX_MAP_TILES ||
!IsInsideMM(size_y, MIN_MAP_SIZE, MAX_MAP_SIZE + 1) || size_x < MIN_MAP_SIZE ||
size_y < MIN_MAP_SIZE ||
(size_x & (size_x - 1)) != 0 || (size_x & (size_x - 1)) != 0 ||
(size_y & (size_y - 1)) != 0) { (size_y & (size_y - 1)) != 0) {
error("Invalid map size"); error("Invalid map size");
} }
DEBUG(map, 1, "Allocating map of size %dx%d", size_x, size_y);
_map_log_x = FindFirstBit(size_x); _map_log_x = FindFirstBit(size_x);
_map_log_y = FindFirstBit(size_y); _map_log_y = FindFirstBit(size_y);
_map_size_x = size_x; _map_size_x = size_x;

View File

@@ -62,9 +62,11 @@ struct TileIndexDiffC {
/** Minimal and maximal map width and height */ /** Minimal and maximal map width and height */
static const uint MIN_MAP_SIZE_BITS = 6; ///< Minimal size of map is equal to 2 ^ MIN_MAP_SIZE_BITS static const uint MIN_MAP_SIZE_BITS = 6; ///< Minimal size of map is equal to 2 ^ MIN_MAP_SIZE_BITS
static const uint MAX_MAP_SIZE_BITS = 12; ///< Maximal size of map is equal to 2 ^ MAX_MAP_SIZE_BITS static const uint MAX_MAP_SIZE_BITS = 20; ///< Maximal size of map is equal to 2 ^ MAX_MAP_SIZE_BITS
static const uint MAX_MAP_TILES_BITS = 26; ///< Maximal number of tiles in a map is equal to 2 ^ MAX_MAP_TILES_BITS.
static const uint MIN_MAP_SIZE = 1 << MIN_MAP_SIZE_BITS; ///< Minimal map size = 64 static const uint MIN_MAP_SIZE = 1 << MIN_MAP_SIZE_BITS; ///< Minimal map size = 64
static const uint MAX_MAP_SIZE = 1 << MAX_MAP_SIZE_BITS; ///< Maximal map size = 4096 static const uint MAX_MAP_SIZE = 1 << MAX_MAP_SIZE_BITS; ///< Maximal map size = 1M
static const uint MAX_MAP_TILES = 1 << MAX_MAP_TILES_BITS;///< Maximal number of tiles in a map = 64M
/** /**
* Approximation of the length of a straight track, relative to a diagonal * Approximation of the length of a straight track, relative to a diagonal

View File

@@ -56,7 +56,7 @@ NewGrfDebugSpritePicker _newgrf_debug_sprite_picker = { SPM_NONE, NULL, 0, Small
*/ */
static inline uint GetFeatureIndex(uint window_number) static inline uint GetFeatureIndex(uint window_number)
{ {
return GB(window_number, 0, 24); return GB(window_number, 0, 27);
} }
/** /**
@@ -68,8 +68,8 @@ static inline uint GetFeatureIndex(uint window_number)
*/ */
static inline uint GetInspectWindowNumber(GrfSpecFeature feature, uint index) static inline uint GetInspectWindowNumber(GrfSpecFeature feature, uint index)
{ {
assert((index >> 24) == 0); assert((index >> 27) == 0);
return (feature << 24) | index; return (feature << 27) | index;
} }
/** /**
@@ -246,7 +246,7 @@ struct NIFeature {
*/ */
static inline GrfSpecFeature GetFeatureNum(uint window_number) static inline GrfSpecFeature GetFeatureNum(uint window_number)
{ {
return (GrfSpecFeature)GB(window_number, 24, 8); return (GrfSpecFeature)GB(window_number, 27, 5);
} }
/** /**

View File

@@ -962,6 +962,24 @@ static void MakeNewGameDone()
MarkWholeScreenDirty(); MarkWholeScreenDirty();
} }
/*
* Too large size may be stored in settings (especially if switching between between OpenTTD
* versions with different map size limits), we have to check if it is valid before generating world.
* Simple separate checking of X and Y map sizes is not enough, as their sum is what counts for the limit.
* Check the size and decrease the larger of the sizes till the size is in limit.
*/
static void FixConfigMapSize()
{
while (_settings_game.game_creation.map_x + _settings_game.game_creation.map_y > MAX_MAP_TILES_BITS) {
/* Repeat reducing larger of X/Y dimensions until the map size is within allowable limits */
if (_settings_game.game_creation.map_x > _settings_game.game_creation.map_y) {
_settings_game.game_creation.map_x--;
} else {
_settings_game.game_creation.map_y--;
}
}
}
static void MakeNewGame(bool from_heightmap, bool reset_settings) static void MakeNewGame(bool from_heightmap, bool reset_settings)
{ {
_game_mode = GM_NORMAL; _game_mode = GM_NORMAL;
@@ -969,6 +987,7 @@ static void MakeNewGame(bool from_heightmap, bool reset_settings)
ResetGRFConfig(true); ResetGRFConfig(true);
GenerateWorldSetCallback(&MakeNewGameDone); GenerateWorldSetCallback(&MakeNewGameDone);
FixConfigMapSize();
GenerateWorld(from_heightmap ? GWM_HEIGHTMAP : GWM_NEWGAME, 1 << _settings_game.game_creation.map_x, 1 << _settings_game.game_creation.map_y, reset_settings); GenerateWorld(from_heightmap ? GWM_HEIGHTMAP : GWM_NEWGAME, 1 << _settings_game.game_creation.map_x, 1 << _settings_game.game_creation.map_y, reset_settings);
} }
@@ -984,6 +1003,7 @@ static void MakeNewEditorWorld()
ResetGRFConfig(true); ResetGRFConfig(true);
GenerateWorldSetCallback(&MakeNewEditorWorldDone); GenerateWorldSetCallback(&MakeNewEditorWorldDone);
FixConfigMapSize();
GenerateWorld(GWM_EMPTY, 1 << _settings_game.game_creation.map_x, 1 << _settings_game.game_creation.map_y); GenerateWorld(GWM_EMPTY, 1 << _settings_game.game_creation.map_x, 1 << _settings_game.game_creation.map_y);
} }
@@ -1129,6 +1149,7 @@ void SwitchToMode(SwitchMode new_mode)
case SM_LOAD_HEIGHTMAP: // Load heightmap from scenario editor case SM_LOAD_HEIGHTMAP: // Load heightmap from scenario editor
SetLocalCompany(OWNER_NONE); SetLocalCompany(OWNER_NONE);
FixConfigMapSize();
GenerateWorld(GWM_HEIGHTMAP, 1 << _settings_game.game_creation.map_x, 1 << _settings_game.game_creation.map_y); GenerateWorld(GWM_HEIGHTMAP, 1 << _settings_game.game_creation.map_x, 1 << _settings_game.game_creation.map_y);
MarkWholeScreenDirty(); MarkWholeScreenDirty();
break; break;
@@ -1171,6 +1192,7 @@ void SwitchToMode(SwitchMode new_mode)
case SM_GENRANDLAND: // Generate random land within scenario editor case SM_GENRANDLAND: // Generate random land within scenario editor
SetLocalCompany(OWNER_NONE); SetLocalCompany(OWNER_NONE);
FixConfigMapSize();
GenerateWorld(GWM_RANDOM, 1 << _settings_game.game_creation.map_x, 1 << _settings_game.game_creation.map_y); GenerateWorld(GWM_RANDOM, 1 << _settings_game.game_creation.map_x, 1 << _settings_game.game_creation.map_y);
/* XXX: set date */ /* XXX: set date */
MarkWholeScreenDirty(); MarkWholeScreenDirty();