diff --git a/src/openrct2/windows/land.c b/src/openrct2/windows/land.c index b54501a815..4907310415 100644 --- a/src/openrct2/windows/land.c +++ b/src/openrct2/windows/land.c @@ -98,13 +98,13 @@ static rct_window_event_list window_land_events = { NULL }; -static char window_land_floor_texture_order[] = { +static char FloorTextureOrder[] = { TERRAIN_SAND_DARK, TERRAIN_SAND_LIGHT, TERRAIN_DIRT, TERRAIN_GRASS_CLUMPS, TERRAIN_GRASS, TERRAIN_ROCK, TERRAIN_SAND, TERRAIN_MARTIAN, TERRAIN_CHECKERBOARD, TERRAIN_ICE, TERRAIN_GRID_RED, TERRAIN_GRID_YELLOW, TERRAIN_GRID_BLUE, TERRAIN_GRID_GREEN }; -static char window_land_wall_texture_order[] = { +static char WallTextureOrder[] = { TERRAIN_EDGE_ROCK, TERRAIN_EDGE_WOOD_RED, TERRAIN_EDGE_WOOD_BLACK, TERRAIN_EDGE_ICE, 0, 0 @@ -212,8 +212,8 @@ static void window_land_mousedown(sint32 widgetIndex, rct_window*w, rct_widget* case WIDX_FLOOR: for (i = 0; i < 14; i++) { gDropdownItemsFormat[i] = -1; - gDropdownItemsArgs[i] = SPR_FLOOR_TEXTURE_GRASS + window_land_floor_texture_order[i]; - if (window_land_floor_texture_order[i] == _selectedFloorTexture) + gDropdownItemsArgs[i] = SPR_FLOOR_TEXTURE_GRASS + FloorTextureOrder[i]; + if (FloorTextureOrder[i] == _selectedFloorTexture) defaultIndex = i; } window_dropdown_show_image( @@ -230,8 +230,8 @@ static void window_land_mousedown(sint32 widgetIndex, rct_window*w, rct_widget* case WIDX_WALL: for (i = 0; i < 4; i++) { gDropdownItemsFormat[i] = -1; - gDropdownItemsArgs[i] = SPR_WALL_TEXTURE_ROCK + window_land_wall_texture_order[i]; - if (window_land_wall_texture_order[i] == _selectedWallTexture) + gDropdownItemsArgs[i] = SPR_WALL_TEXTURE_ROCK + WallTextureOrder[i]; + if (WallTextureOrder[i] == _selectedWallTexture) defaultIndex = i; } window_dropdown_show_image( diff --git a/src/openrct2/windows/mapgen.c b/src/openrct2/windows/mapgen.c index 632110c111..1334ac443c 100644 --- a/src/openrct2/windows/mapgen.c +++ b/src/openrct2/windows/mapgen.c @@ -85,6 +85,12 @@ enum { WIDX_SIMPLEX_WATER_LEVEL_DOWN, WIDX_SIMPLEX_FLOOR_TEXTURE, WIDX_SIMPLEX_WALL_TEXTURE, + + WIDX_HEIGHTMAP_SMOOTH = TAB_BEGIN, + WIDX_HEIGHTMAP_STRONG, + WIDX_HEIGHTMAP_WATER_LEVEL, + WIDX_HEIGHTMAP_WATER_LEVEL_UP, + WIDX_HEIGHTMAP_WATER_LEVEL_DOWN, }; #pragma region Widgets @@ -186,7 +192,14 @@ static rct_widget HeightmapWidgets[] = { { WWT_TAB, 1, 65, 95, 17, 43, 0x20000000 | SPR_TAB, STR_NONE }, { WWT_TAB, 1, 96, 126, 17, 43, 0x20000000 | SPR_TAB, STR_NONE }, - { WWT_DROPDOWN_BUTTON, 1, 104, 198, 52, 63, STR_MAPGEN_ACTION_GENERATE, STR_NONE }, + { WWT_DROPDOWN_BUTTON, 1, 104, 198, 52, 63, STR_MAPGEN_ACTION_GENERATE, STR_NONE }, // WIDX_GENERATE + + { WWT_CHECKBOX, 1, 4, 103, 52, 63, STR_MAPGEN_SMOOTH_TILE, STR_NONE }, // WIDX_HEIGHTMAP_SMOOTH + { WWT_CHECKBOX, 1, 4, 103, 70, 81, STR_MAPGEN_SMOOTH_STRONG, STR_NONE }, // WIDX_HEIGHTMAP_STRONG + + { WWT_SPINNER, 1, 104, 198, 124, 135, STR_NONE, STR_NONE }, // WIDX_HEIGHTMAP_WATER_LEVEL + { WWT_DROPDOWN_BUTTON, 1, 187, 197, 125, 129, STR_NUMERIC_UP, STR_NONE }, // WIDX_HEIGHTMAP_WATER_LEVEL_UP + { WWT_DROPDOWN_BUTTON, 1, 187, 197, 130, 134, STR_NUMERIC_DOWN, STR_NONE }, // WIDX_HEIGHTMAP_WATER_LEVEL_DOWN { WIDGETS_END }, }; @@ -426,7 +439,12 @@ static uint32 PageEnabledWidgets[] = { (1ULL << WIDX_TAB_2) | (1ULL << WIDX_TAB_3) | (1ULL << WIDX_TAB_4) | - (1ULL << WIDX_GENERATE) + (1ULL << WIDX_GENERATE) | + (1ULL << WIDX_HEIGHTMAP_SMOOTH) | + (1ULL << WIDX_HEIGHTMAP_STRONG) | + (1ULL << WIDX_HEIGHTMAP_WATER_LEVEL) | + (1ULL << WIDX_HEIGHTMAP_WATER_LEVEL_UP) | + (1ULL << WIDX_HEIGHTMAP_WATER_LEVEL_DOWN) }; static uint32 window_mapgen_page_hold_down_widgets[] = { @@ -450,12 +468,16 @@ static uint32 window_mapgen_page_hold_down_widgets[] = { (1 << WIDX_SIMPLEX_MAP_SIZE_UP) | (1 << WIDX_SIMPLEX_MAP_SIZE_DOWN) | (1 << WIDX_SIMPLEX_WATER_LEVEL_UP) | - (1 << WIDX_SIMPLEX_WATER_LEVEL_DOWN) + (1 << WIDX_SIMPLEX_WATER_LEVEL_DOWN), + + 0 }; #pragma endregion -const sint32 window_mapgen_tab_animation_loops[] = { 16, 16, 16 }; +static const sint32 TabAnimationLoops[] = { + 16, 16, 16, 16 +}; #define MINIMUM_MAP_SIZE_TECHNICAL 15 #define MAXIMUM_MAP_SIZE_TECHNICAL 256 @@ -471,13 +493,13 @@ static void window_mapgen_set_pressed_tab(rct_window *w); static void window_mapgen_anchor_border_widgets(rct_window *w); static void window_mapgen_draw_tab_images(rct_drawpixelinfo *dpi, rct_window *w); -static char window_land_floor_texture_order[] = { +static char FloorTextureOrder[] = { TERRAIN_SAND_DARK, TERRAIN_SAND_LIGHT, TERRAIN_DIRT, TERRAIN_GRASS_CLUMPS, TERRAIN_GRASS, TERRAIN_ROCK, TERRAIN_SAND, TERRAIN_MARTIAN, TERRAIN_CHECKERBOARD, TERRAIN_ICE, TERRAIN_GRID_RED, TERRAIN_GRID_YELLOW, TERRAIN_GRID_BLUE, TERRAIN_GRID_GREEN }; -static char window_land_wall_texture_order[] = { +static char WallTextureOrder[] = { TERRAIN_EDGE_ROCK, TERRAIN_EDGE_WOOD_RED, TERRAIN_EDGE_WOOD_BLACK, TERRAIN_EDGE_ICE, 0, 0 @@ -491,10 +513,10 @@ static sint32 _wallTexture = TERRAIN_EDGE_ROCK; static sint32 _randomTerrrain = 1; static sint32 _placeTrees = 1; -static sint32 _simplex_low = 6; -static sint32 _simplex_high = 10; +static sint32 _simplex_low = 6; +static sint32 _simplex_high = 10; static sint32 _simplex_base_freq = 60; -static sint32 _simplex_octaves = 4; +static sint32 _simplex_octaves = 4; rct_window *window_mapgen_open() { @@ -545,7 +567,7 @@ static void window_mapgen_base_mouseup(rct_window *w, sint32 widgetIndex) case WIDX_GENERATE: mapgenSettings.mapSize = _mapSize; mapgenSettings.height = _baseHeight + 2; - mapgenSettings.waterLevel = _waterLevel + 2; + mapgenSettings.water_level = _waterLevel + 2; mapgenSettings.floor = _floorTexture; mapgenSettings.wall = _wallTexture; @@ -603,8 +625,8 @@ static void window_mapgen_base_mousedown(sint32 widgetIndex, rct_window *w, rct_ case WIDX_FLOOR_TEXTURE: for (i = 0; i < 14; i++) { gDropdownItemsFormat[i] = -1; - gDropdownItemsArgs[i] = SPR_FLOOR_TEXTURE_GRASS + window_land_floor_texture_order[i]; - if (window_land_floor_texture_order[i] == _floorTexture) + gDropdownItemsArgs[i] = SPR_FLOOR_TEXTURE_GRASS + FloorTextureOrder[i]; + if (FloorTextureOrder[i] == _floorTexture) defaultIndex = i; } window_dropdown_show_image( @@ -621,8 +643,8 @@ static void window_mapgen_base_mousedown(sint32 widgetIndex, rct_window *w, rct_ case WIDX_WALL_TEXTURE: for (i = 0; i < 4; i++) { gDropdownItemsFormat[i] = -1; - gDropdownItemsArgs[i] = SPR_WALL_TEXTURE_ROCK + window_land_wall_texture_order[i]; - if (window_land_wall_texture_order[i] == _wallTexture) + gDropdownItemsArgs[i] = SPR_WALL_TEXTURE_ROCK + WallTextureOrder[i]; + if (WallTextureOrder[i] == _wallTexture) defaultIndex = i; } window_dropdown_show_image( @@ -682,7 +704,7 @@ static void window_mapgen_base_dropdown(rct_window *w, sint32 widgetIndex, sint3 static void window_mapgen_base_update(rct_window *w) { // Tab animation - if (++w->frame_no >= window_mapgen_tab_animation_loops[w->page]) + if (++w->frame_no >= TabAnimationLoops[w->page]) w->frame_no = 0; widget_invalidate(w, WIDX_TAB_1); } @@ -780,7 +802,7 @@ static void window_mapgen_random_mouseup(rct_window *w, sint32 widgetIndex) case WIDX_GENERATE: mapgenSettings.mapSize = _mapSize; mapgenSettings.height = _baseHeight + 2; - mapgenSettings.waterLevel = _waterLevel + 2; + mapgenSettings.water_level = _waterLevel + 2; mapgenSettings.floor = _randomTerrrain ? -1 : _floorTexture; mapgenSettings.wall = _randomTerrrain ? -1 : _wallTexture; mapgenSettings.trees = _placeTrees; @@ -810,7 +832,7 @@ static void window_mapgen_random_mousedown(sint32 widgetIndex, rct_window *w, rc static void window_mapgen_random_update(rct_window *w) { // Tab animation - if (++w->frame_no >= window_mapgen_tab_animation_loops[w->page]) + if (++w->frame_no >= TabAnimationLoops[w->page]) w->frame_no = 0; widget_invalidate(w, WIDX_TAB_2); } @@ -868,7 +890,7 @@ static void window_mapgen_simplex_mouseup(rct_window *w, sint32 widgetIndex) mapgenSettings.mapSize = _mapSize; mapgenSettings.height = _baseHeight; - mapgenSettings.waterLevel = _waterLevel + 2; + mapgenSettings.water_level = _waterLevel + 2; mapgenSettings.floor = _floorTexture; mapgenSettings.wall = _wallTexture; mapgenSettings.trees = 0; @@ -940,8 +962,8 @@ static void window_mapgen_simplex_mousedown(sint32 widgetIndex, rct_window *w, r case WIDX_SIMPLEX_FLOOR_TEXTURE: for (i = 0; i < 14; i++) { gDropdownItemsFormat[i] = -1; - gDropdownItemsArgs[i] = SPR_FLOOR_TEXTURE_GRASS + window_land_floor_texture_order[i]; - if (window_land_floor_texture_order[i] == _floorTexture) + gDropdownItemsArgs[i] = SPR_FLOOR_TEXTURE_GRASS + FloorTextureOrder[i]; + if (FloorTextureOrder[i] == _floorTexture) defaultIndex = i; } window_dropdown_show_image( @@ -958,8 +980,8 @@ static void window_mapgen_simplex_mousedown(sint32 widgetIndex, rct_window *w, r case WIDX_SIMPLEX_WALL_TEXTURE: for (i = 0; i < 4; i++) { gDropdownItemsFormat[i] = -1; - gDropdownItemsArgs[i] = SPR_WALL_TEXTURE_ROCK + window_land_wall_texture_order[i]; - if (window_land_wall_texture_order[i] == _wallTexture) + gDropdownItemsArgs[i] = SPR_WALL_TEXTURE_ROCK + WallTextureOrder[i]; + if (WallTextureOrder[i] == _wallTexture) defaultIndex = i; } window_dropdown_show_image( @@ -1021,7 +1043,7 @@ static void window_mapgen_simplex_dropdown(rct_window *w, sint32 widgetIndex, si static void window_mapgen_simplex_update(rct_window *w) { // Tab animation - if (++w->frame_no >= window_mapgen_tab_animation_loops[w->page]) + if (++w->frame_no >= TabAnimationLoops[w->page]) w->frame_no = 0; widget_invalidate(w, WIDX_TAB_3); } @@ -1075,6 +1097,8 @@ static void window_mapgen_simplex_paint(rct_window *w, rct_drawpixelinfo *dpi) static void window_mapgen_heightmap_mouseup(rct_window *w, sint32 widgetIndex) { + mapgen_settings mapgenSettings; + switch (widgetIndex) { case WIDX_CLOSE: @@ -1087,9 +1111,24 @@ static void window_mapgen_heightmap_mouseup(rct_window *w, sint32 widgetIndex) window_mapgen_set_page(w, widgetIndex - WIDX_TAB_1); break; case WIDX_GENERATE: - mapgen_generate_from_heightmap(); + mapgenSettings.water_level = _waterLevel; + mapgenSettings.smooth = widget_is_pressed(w, WIDX_HEIGHTMAP_SMOOTH); + mapgenSettings.strong_smooth = widget_is_pressed(w, WIDX_HEIGHTMAP_STRONG); + mapgen_generate_from_heightmap(&mapgenSettings); gfx_invalidate_screen(); break; + case WIDX_HEIGHTMAP_SMOOTH: + case WIDX_HEIGHTMAP_STRONG: + widget_set_checkbox_value(w, widgetIndex, !widget_is_pressed(w, widgetIndex)); + break; + case WIDX_HEIGHTMAP_WATER_LEVEL_UP: + _waterLevel = min(_waterLevel + 2, 54); + window_invalidate(w); + break; + case WIDX_HEIGHTMAP_WATER_LEVEL_DOWN: + _waterLevel = max(_waterLevel - 2, 0); + window_invalidate(w); + break; } } @@ -1111,6 +1150,10 @@ static void window_mapgen_heightmap_paint(rct_window *w, rct_drawpixelinfo *dpi) { window_draw_widgets(w, dpi); window_mapgen_draw_tab_images(dpi, w); + + // water level label and value + gfx_draw_string_left(dpi, STR_WATER_LEVEL_LABEL, NULL, COLOUR_BLACK, w->x + 5, w->y + w->widgets[WIDX_HEIGHTMAP_WATER_LEVEL].top + 1); + gfx_draw_string_left(dpi, STR_COMMA16, &_waterLevel, w->colours[1], w->x + w->widgets[WIDX_HEIGHTMAP_WATER_LEVEL].left + 1, w->y + w->widgets[WIDX_HEIGHTMAP_WATER_LEVEL].top + 1); } #pragma endregion diff --git a/src/openrct2/world/map_helpers.c b/src/openrct2/world/map_helpers.c index 9354b4c5b7..e11ef8ed76 100644 --- a/src/openrct2/world/map_helpers.c +++ b/src/openrct2/world/map_helpers.c @@ -373,10 +373,10 @@ sint32 tile_smooth(sint32 x, sint32 y) sint8 thresholdSW = clamp(neighbourHeightOffset.S, 0, 1) + clamp(neighbourHeightOffset.SW, 0, 1) + clamp(neighbourHeightOffset.W, 0, 1); uint8 slope = 0; - slope |= (thresholdNW >= 1) << 1; - slope |= (thresholdNE >= 1) << 2; - slope |= (thresholdSE >= 1) << 3; - slope |= (thresholdSW >= 1) << 0; + slope |= (thresholdNW >= 1) ? (1 << 1) : 0; + slope |= (thresholdNE >= 1) ? (1 << 2) : 0; + slope |= (thresholdSE >= 1) ? (1 << 3) : 0; + slope |= (thresholdSW >= 1) ? (1 << 0) : 0; // Set diagonal when three corners have been raised, and the middle one can be raised one more if ((slope == 0b0111 && neighbourHeightOffset.NW >= 4) || (slope == 0b1011 && neighbourHeightOffset.SW >= 4) || diff --git a/src/openrct2/world/mapgen.c b/src/openrct2/world/mapgen.c index 0cb2c32a9e..75bdb09f1b 100644 --- a/src/openrct2/world/mapgen.c +++ b/src/openrct2/world/mapgen.c @@ -116,7 +116,7 @@ void mapgen_generate_blank(mapgen_settings *settings) } } - mapgen_set_water_level(settings->waterLevel); + mapgen_set_water_level(settings->water_level); } void mapgen_generate(mapgen_settings *settings) @@ -129,7 +129,7 @@ void mapgen_generate(mapgen_settings *settings) mapSize = settings->mapSize; floorTexture = settings->floor; wallTexture = settings->wall; - waterLevel = settings->waterLevel; + waterLevel = settings->water_level; if (floorTexture == -1) floorTexture = BaseTerrain[util_rand() % countof(BaseTerrain)]; @@ -767,7 +767,7 @@ static void mapgen_simplex(mapgen_settings *settings) #pragma region Heightmap -void mapgen_generate_from_heightmap() +void mapgen_generate_from_heightmap(mapgen_settings *settings) { SDL_Surface *bitmap = SDL_LoadBMP("test_blurry.bmp"); if (bitmap == NULL) @@ -795,20 +795,38 @@ void mapgen_generate_from_heightmap() surfaceElement->base_height *= 2; surfaceElement->clearance_height = surfaceElement->base_height; - const sint32 water_level = 24; // TODO: Get as setting - if (surfaceElement->base_height < water_level) + // Set water level + if (surfaceElement->base_height < settings->water_level) { - surfaceElement->properties.surface.terrain |= water_level / 2; + surfaceElement->properties.surface.terrain |= settings->water_level / 2; } } } - // smooth the entire map - for (uint32 y = 1; y <= height; y++) + // Smooth map + if (settings->smooth) { - for (uint32 x = 1; x <= width; x++) + if (settings->strong_smooth) { - tile_smooth(x, y); + map_smooth(1, 1, width, height); + } + else + { + // Keep smoothing the entire map until no tiles are changed anymore + while (true) + { + sint32 numTilesChanged = 0; + for (uint32 y = 1; y <= height; y++) + { + for (uint32 x = 1; x <= width; x++) + { + numTilesChanged += tile_smooth(x, y); + } + } + + if (numTilesChanged == 0) + break; + } } } diff --git a/src/openrct2/world/mapgen.h b/src/openrct2/world/mapgen.h index d11a69c0b2..42efdf3c98 100644 --- a/src/openrct2/world/mapgen.h +++ b/src/openrct2/world/mapgen.h @@ -21,7 +21,7 @@ typedef struct mapgen_settings { // Base sint32 mapSize; sint32 height; - sint32 waterLevel; + sint32 water_level; sint32 floor; sint32 wall; @@ -33,11 +33,15 @@ typedef struct mapgen_settings { sint32 simplex_high; float simplex_base_freq; sint32 simplex_octaves; + + // Height map settings + bool smooth; + bool strong_smooth; } mapgen_settings; void mapgen_generate_blank(mapgen_settings *settings); void mapgen_generate(mapgen_settings *settings); void mapgen_generate_custom_simplex(mapgen_settings *settings); -void mapgen_generate_from_heightmap(); +void mapgen_generate_from_heightmap(mapgen_settings *settings); #endif