From b21bd9230a0cd169497438aaaa4a7c9052472816 Mon Sep 17 00:00:00 2001 From: Hop311 Date: Mon, 25 Sep 2023 19:19:02 +0100 Subject: Terrain types calculation, label and mapmode --- extension/src/openvic-extension/GameSingleton.cpp | 160 +++++++++++++++++++-- extension/src/openvic-extension/GameSingleton.hpp | 22 +-- .../openvic-extension/LoadGameCompatibility.cpp | 104 -------------- .../src/openvic-extension/LoadGameOpenVic.cpp | 89 ------------ 4 files changed, 154 insertions(+), 221 deletions(-) delete mode 100644 extension/src/openvic-extension/LoadGameCompatibility.cpp delete mode 100644 extension/src/openvic-extension/LoadGameOpenVic.cpp (limited to 'extension/src') diff --git a/extension/src/openvic-extension/GameSingleton.cpp b/extension/src/openvic-extension/GameSingleton.cpp index cdba44c..e0dc14e 100644 --- a/extension/src/openvic-extension/GameSingleton.cpp +++ b/extension/src/openvic-extension/GameSingleton.cpp @@ -4,18 +4,12 @@ #include +#include "openvic-extension/LoadLocalisation.hpp" #include "openvic-extension/Utilities.hpp" using namespace godot; using namespace OpenVic; -TerrainVariant::TerrainVariant(const std::string_view new_identfier, Ref const& new_image) - : HasIdentifier { new_identfier }, image { new_image } {} - -Ref TerrainVariant::get_image() const { - return image; -} - GameSingleton* GameSingleton::singleton = nullptr; void GameSingleton::_bind_methods() { @@ -58,6 +52,7 @@ void GameSingleton::_bind_methods() { ClassDB::bind_static_method("GameSingleton", D_METHOD("get_province_info_province_key"), &GameSingleton::get_province_info_province_key); ClassDB::bind_static_method("GameSingleton", D_METHOD("get_province_info_region_key"), &GameSingleton::get_province_info_region_key); ClassDB::bind_static_method("GameSingleton", D_METHOD("get_province_info_life_rating_key"), &GameSingleton::get_province_info_life_rating_key); + ClassDB::bind_static_method("GameSingleton", D_METHOD("get_province_info_terrain_type_key"), &GameSingleton::get_province_info_terrain_type_key); ClassDB::bind_static_method("GameSingleton", D_METHOD("get_province_info_total_population_key"), &GameSingleton::get_province_info_total_population_key); ClassDB::bind_static_method("GameSingleton", D_METHOD("get_province_info_pop_types_key"), &GameSingleton::get_province_info_pop_types_key); ClassDB::bind_static_method("GameSingleton", D_METHOD("get_province_info_pop_ideologies_key"), &GameSingleton::get_province_info_pop_ideologies_key); @@ -109,8 +104,7 @@ void GameSingleton::_on_state_updated() { /* REQUIREMENTS: * MAP-21, MAP-23, MAP-25, MAP-32, MAP-33, MAP-34 */ -GameSingleton::GameSingleton() : game_manager { [this]() { _on_state_updated(); } }, - terrain_variants { "terrain variants" } { +GameSingleton::GameSingleton() : game_manager { [this]() { _on_state_updated(); } } { ERR_FAIL_COND(singleton != nullptr); singleton = this; } @@ -150,6 +144,10 @@ StringName const& GameSingleton::get_province_info_life_rating_key() { static const StringName key = "life_rating"; return key; } +StringName const& GameSingleton::get_province_info_terrain_type_key() { + static const StringName key = "terrain_type"; + return key; +} StringName const& GameSingleton::get_province_info_total_population_key() { static const StringName key = "total_population"; return key; @@ -234,6 +232,10 @@ Dictionary GameSingleton::get_province_info_from_index(int32_t index) const { if (rgo != nullptr) ret[get_province_info_rgo_key()] = std_to_godot_string(rgo->get_identifier()); ret[get_province_info_life_rating_key()] = province->get_life_rating(); + + TerrainType const* terrain_type = province->get_terrain_type(); + if (terrain_type != nullptr) ret[get_province_info_terrain_type_key()] = std_to_godot_string(terrain_type->get_identifier()); + ret[get_province_info_total_population_key()] = province->get_total_population(); distribution_t const& pop_types = province->get_pop_type_distribution(); if (!pop_types.empty()) ret[get_province_info_pop_types_key()] = _distribution_to_dictionary(pop_types); @@ -391,3 +393,143 @@ String GameSingleton::get_longform_date() const { void GameSingleton::try_tick() { game_manager.get_clock().conditionallyAdvanceGame(); } + +Error GameSingleton::_load_map_images(bool flip_vertical) { + if (province_shape_texture.is_valid()) { + UtilityFunctions::push_error("Map images have already been loaded!"); + return FAILED; + } + + Error err = OK; + + const Vector2i province_dims { + static_cast(game_manager.get_map().get_width()), + static_cast(game_manager.get_map().get_height()) }; + + static constexpr int32_t GPU_DIM_LIMIT = 0x3FFF; + // For each dimension of the image, this finds the small number of equal subdivisions required get the individual texture dims under GPU_DIM_LIMIT + for (int i = 0; i < 2; ++i) + for (image_subdivisions[i] = 1; province_dims[i] / image_subdivisions[i] > GPU_DIM_LIMIT || + province_dims[i] % image_subdivisions[i] != 0; ++image_subdivisions[i]); + + Map::shape_pixel_t const* province_shape_data = game_manager.get_map().get_province_shape_image().data(); + const Vector2i divided_dims = province_dims / image_subdivisions; + Array province_shape_images; + province_shape_images.resize(image_subdivisions.x * image_subdivisions.y); + for (int32_t v = 0; v < image_subdivisions.y; ++v) { + for (int32_t u = 0; u < image_subdivisions.x; ++u) { + PackedByteArray index_data_array; + index_data_array.resize(divided_dims.x * divided_dims.y * sizeof(Map::shape_pixel_t)); + + for (int32_t y = 0; y < divided_dims.y; ++y) + memcpy(index_data_array.ptrw() + y * divided_dims.x * sizeof(Map::shape_pixel_t), + province_shape_data + (v * divided_dims.y + y) * province_dims.x + u * divided_dims.x, + divided_dims.x * sizeof(Map::shape_pixel_t)); + + const Ref province_shape_subimage = Image::create_from_data(divided_dims.x, divided_dims.y, false, Image::FORMAT_RGB8, index_data_array); + if (province_shape_subimage.is_null()) { + UtilityFunctions::push_error("Failed to create province shape image (", u, ", ", v, ")"); + err = FAILED; + } + province_shape_images[u + v * image_subdivisions.x] = province_shape_subimage; + } + } + + province_shape_texture.instantiate(); + if (province_shape_texture->create_from_images(province_shape_images) != OK) { + UtilityFunctions::push_error("Failed to create terrain texture array!"); + err = FAILED; + } + + if (_update_colour_image() != OK) err = FAILED; + + return err; +} + +Error GameSingleton::_load_terrain_variants_compatibility_mode(String const& terrain_texturesheet_path) { + static constexpr int32_t SHEET_DIMS = 8, SHEET_SIZE = SHEET_DIMS * SHEET_DIMS; + + // Load the terrain texture sheet and prepare to slice it up + Ref terrain_sheet = load_godot_image(terrain_texturesheet_path); + if (terrain_sheet.is_null()) { + UtilityFunctions::push_error("Failed to load terrain texture sheet: ", terrain_texturesheet_path); + return FAILED; + } + terrain_sheet->flip_y(); + const int32_t sheet_width = terrain_sheet->get_width(), sheet_height = terrain_sheet->get_height(); + if (sheet_width < 1 || sheet_width % SHEET_DIMS != 0 || sheet_width != sheet_height) { + UtilityFunctions::push_error("Invalid terrain texture sheet dims: ", sheet_width, "x", sheet_height, " (must be square with dims positive multiples of ", SHEET_DIMS, ")"); + return FAILED; + } + const int32_t slice_size = sheet_width / SHEET_DIMS; + + Array terrain_images; + { + static constexpr colour_t TERRAIN_WATER_INDEX_COLOUR = 0xFFFFFF; + Ref water_image = Image::create(slice_size, slice_size, false, terrain_sheet->get_format()); + ERR_FAIL_NULL_V_EDMSG(water_image, FAILED, "Failed to create water terrain image"); + water_image->fill({ 0.1f, 0.1f, 0.5f }); + terrain_images.append(water_image); + } + Error err = OK; + for (int32_t idx = 0; idx < SHEET_SIZE; ++idx) { + const Rect2i slice { (idx % SHEET_DIMS) * slice_size, (7 - (idx / SHEET_DIMS)) * slice_size, slice_size, slice_size }; + const Ref terrain_image = terrain_sheet->get_region(slice); + if (terrain_image.is_null() || terrain_image->is_empty()) { + UtilityFunctions::push_error("Failed to extract terrain texture slice ", slice, " from ", terrain_texturesheet_path); + err = FAILED; + } + terrain_images.append(terrain_image); + } + + terrain_texture.instantiate(); + if (terrain_texture->create_from_images(terrain_images) != OK) { + UtilityFunctions::push_error("Failed to create terrain texture array!"); + return FAILED; + } + return err; +} + +Error GameSingleton::load_defines_compatibility_mode(PackedStringArray const& file_paths) { + static const fs::path terrain_texture_file = "map/terrain/texturesheet.tga"; + + Dataloader::path_vector_t roots; + for (String const& path : file_paths) { + roots.push_back(godot_to_std_string(path)); + } + + Error err = OK; + + if (!dataloader.set_roots(roots)) { + Logger::error("Failed to set dataloader roots!"); + err = FAILED; + } + if (!dataloader.load_defines(game_manager)) { + UtilityFunctions::push_error("Failed to load defines!"); + err = FAILED; + } + if (_load_terrain_variants_compatibility_mode( + std_to_godot_string(dataloader.lookup_file(terrain_texture_file).string()) + ) != OK) { + UtilityFunctions::push_error("Failed to load terrain variants!"); + err = FAILED; + } + if (_load_map_images(true) != OK) { + UtilityFunctions::push_error("Failed to load map images!"); + err = FAILED; + } + if (!game_manager.load_hardcoded_defines()) { + UtilityFunctions::push_error("Failed to hardcoded defines!"); + err = FAILED; + } + if (!dataloader.load_localisation_files(LoadLocalisation::add_message)) { + UtilityFunctions::push_error("Failed to load localisation!"); + err = FAILED; + } + + return err; +} + +String GameSingleton::lookup_file(String const& path) const { + return std_to_godot_string(dataloader.lookup_file(godot_to_std_string(path)).string()); +} diff --git a/extension/src/openvic-extension/GameSingleton.hpp b/extension/src/openvic-extension/GameSingleton.hpp index 2a72e2f..56c9e88 100644 --- a/extension/src/openvic-extension/GameSingleton.hpp +++ b/extension/src/openvic-extension/GameSingleton.hpp @@ -8,22 +8,6 @@ namespace OpenVic { - struct TerrainVariant : HasIdentifier { - friend class GameSingleton; - - private: - const godot::Ref image; - - TerrainVariant(const std::string_view new_identfier, godot::Ref const& new_image); - - public: - static constexpr size_t MAX_TERRIN_VARIANT_COUNT = 1 << (8 * sizeof(TerrainTypeMapping::index_t)); - - TerrainVariant(TerrainVariant&&) = default; - - godot::Ref get_image() const; - }; - class GameSingleton : public godot::Object { GDCLASS(GameSingleton, godot::Object) @@ -37,13 +21,12 @@ namespace OpenVic { godot::Ref province_colour_image; godot::Ref province_colour_texture; Mapmode::index_t mapmode_index = 0; - IdentifierRegistry terrain_variants; godot::Ref terrain_texture; godot::Error _generate_terrain_texture_array(); - godot::Error _load_map_images(godot::String const& province_image_path, godot::String const& terrain_image_path, bool flip_vertical = false); + godot::Error _load_map_images(bool flip_vertical = false); - godot::Error _load_terrain_variants_compatibility_mode(godot::String const& terrain_image_path, godot::String const& terrain_texturesheet_path); + godot::Error _load_terrain_variants_compatibility_mode(godot::String const& terrain_texturesheet_path); /* Generate the province_colour_texture from the current mapmode. */ @@ -87,6 +70,7 @@ namespace OpenVic { static godot::StringName const& get_province_info_province_key(); static godot::StringName const& get_province_info_region_key(); static godot::StringName const& get_province_info_life_rating_key(); + static godot::StringName const& get_province_info_terrain_type_key(); static godot::StringName const& get_province_info_total_population_key(); static godot::StringName const& get_province_info_pop_types_key(); static godot::StringName const& get_province_info_pop_ideologies_key(); diff --git a/extension/src/openvic-extension/LoadGameCompatibility.cpp b/extension/src/openvic-extension/LoadGameCompatibility.cpp deleted file mode 100644 index 0a6cb33..0000000 --- a/extension/src/openvic-extension/LoadGameCompatibility.cpp +++ /dev/null @@ -1,104 +0,0 @@ -#include "GameSingleton.hpp" - -#include -#include - -#include - -#include "openvic-extension/LoadLocalisation.hpp" -#include "openvic-extension/Utilities.hpp" - -using namespace godot; -using namespace OpenVic; - -Error GameSingleton::_load_terrain_variants_compatibility_mode(String const& terrain_image_path, String const& terrain_texturesheet_path) { - static constexpr int32_t SHEET_DIMS = 8, SHEET_SIZE = SHEET_DIMS * SHEET_DIMS; - - // Load the terrain texture sheet and prepare to slice it up - Ref terrain_sheet = load_godot_image(terrain_texturesheet_path); - if (terrain_sheet.is_null()) { - UtilityFunctions::push_error("Failed to load terrain texture sheet: ", terrain_texturesheet_path); - return FAILED; - } - terrain_sheet->flip_y(); - const int32_t sheet_width = terrain_sheet->get_width(), sheet_height = terrain_sheet->get_height(); - if (sheet_width < 1 || sheet_width % SHEET_DIMS != 0 || sheet_width != sheet_height) { - UtilityFunctions::push_error("Invalid terrain texture sheet dims: ", sheet_width, "x", sheet_height, " (must be square with dims positive multiples of ", SHEET_DIMS, ")"); - return FAILED; - } - const int32_t slice_size = sheet_width / SHEET_DIMS; - - { - static constexpr colour_t TERRAIN_WATER_INDEX_COLOUR = 0xFFFFFF; - Ref water_image = Image::create(slice_size, slice_size, false, terrain_sheet->get_format()); - ERR_FAIL_NULL_V_EDMSG(water_image, FAILED, "Failed to create water terrain image"); - water_image->fill({ 0.1f, 0.1f, 0.5f }); - terrain_variants.add_item({ "terrain_water", water_image }); - } - Error err = OK; - for (int32_t idx = 0; idx < SHEET_SIZE; ++idx) { - const Rect2i slice { (idx % SHEET_DIMS) * slice_size, (7 - (idx / SHEET_DIMS)) * slice_size, slice_size, slice_size }; - const Ref terrain_image = terrain_sheet->get_region(slice); - if (terrain_image.is_null() || terrain_image->is_empty()) { - UtilityFunctions::push_error("Failed to extract terrain texture slice ", slice, " from ", terrain_texturesheet_path); - err = FAILED; - continue; - } - if (!terrain_variants.add_item({ "terrain_" + std::to_string(idx), terrain_image })) err = FAILED; - } - terrain_variants.lock(); - if (_generate_terrain_texture_array() != OK) return FAILED; - return err; -} - -Error GameSingleton::load_defines_compatibility_mode(PackedStringArray const& file_paths) { - static const fs::path province_image_file = "map/provinces.bmp"; - static const fs::path terrain_image_file = "map/terrain.bmp"; - static const fs::path terrain_texture_file = "map/terrain/texturesheet.tga"; - - Dataloader::path_vector_t roots; - for (String const& path : file_paths) { - roots.push_back(godot_to_std_string(path)); - } - - Error err = OK; - - if (!dataloader.set_roots(roots)) { - Logger::error("Failed to set dataloader roots!"); - err = FAILED; - } - - if (!dataloader.load_defines(game_manager)) { - UtilityFunctions::push_error("Failed to load defines!"); - err = FAILED; - } - - if (_load_terrain_variants_compatibility_mode( - std_to_godot_string(dataloader.lookup_file(terrain_image_file).string()), - std_to_godot_string(dataloader.lookup_file(terrain_texture_file).string()) - ) != OK) { - UtilityFunctions::push_error("Failed to load terrain variants!"); - err = FAILED; - } - if (_load_map_images( - std_to_godot_string(dataloader.lookup_file(province_image_file).string()), - std_to_godot_string(dataloader.lookup_file(terrain_image_file).string()), - true) != OK) { - UtilityFunctions::push_error("Failed to load map images!"); - err = FAILED; - } - if (!game_manager.load_hardcoded_defines()) { - UtilityFunctions::push_error("Failed to hardcoded defines!"); - err = FAILED; - } - if (!dataloader.load_localisation_files(LoadLocalisation::add_message)) { - UtilityFunctions::push_error("Failed to load localisation!"); - err = FAILED; - } - - return err; -} - -String GameSingleton::lookup_file(String const& path) const { - return std_to_godot_string(dataloader.lookup_file(godot_to_std_string(path)).string()); -} diff --git a/extension/src/openvic-extension/LoadGameOpenVic.cpp b/extension/src/openvic-extension/LoadGameOpenVic.cpp deleted file mode 100644 index b118f87..0000000 --- a/extension/src/openvic-extension/LoadGameOpenVic.cpp +++ /dev/null @@ -1,89 +0,0 @@ -#include "GameSingleton.hpp" - -#include -#include -#include - -#include "openvic-extension/Utilities.hpp" - -using namespace godot; -using namespace OpenVic; - -Error GameSingleton::_generate_terrain_texture_array() { - Error err = OK; - if (terrain_variants.size() == 0) { - UtilityFunctions::push_error("Failed to load terrain textures!"); - return FAILED; - } - // TerrainVariant count is limited by the data type representing it in the map image - if (terrain_variants.size() > TerrainVariant::MAX_TERRIN_VARIANT_COUNT) { - UtilityFunctions::push_error("Too many terrain textures - all after the first ", - static_cast(TerrainVariant::MAX_TERRIN_VARIANT_COUNT), " will be ignored"); - err = FAILED; - } - - Array terrain_images; - for (size_t i = 0; i < terrain_variants.size() && i < TerrainVariant::MAX_TERRIN_VARIANT_COUNT; ++i) { - TerrainVariant const& var = *terrain_variants.get_item_by_index(i); - terrain_images.append(var.get_image()); - } - - terrain_texture.instantiate(); - if (terrain_texture->create_from_images(terrain_images) != OK) { - UtilityFunctions::push_error("Failed to create terrain texture array!"); - return FAILED; - } - return err; -} - -Error GameSingleton::_load_map_images(String const& province_image_path, String const& terrain_image_path, bool flip_vertical) { - if (province_shape_texture.is_valid()) { - UtilityFunctions::push_error("Map images have already been loaded, cannot load: ", province_image_path, " and ", terrain_image_path); - return FAILED; - } - - Error err = OK; - - const Vector2i province_dims { - static_cast(game_manager.get_map().get_width()), - static_cast(game_manager.get_map().get_height()) }; - - static constexpr int32_t GPU_DIM_LIMIT = 0x3FFF; - // For each dimension of the image, this finds the small number of equal subdivisions required get the individual texture dims under GPU_DIM_LIMIT - for (int i = 0; i < 2; ++i) - for (image_subdivisions[i] = 1; province_dims[i] / image_subdivisions[i] > GPU_DIM_LIMIT || - province_dims[i] % image_subdivisions[i] != 0; ++image_subdivisions[i]); - - Map::shape_pixel_t const* province_shape_data = game_manager.get_map().get_province_shape_image().data(); - const Vector2i divided_dims = province_dims / image_subdivisions; - Array province_shape_images; - province_shape_images.resize(image_subdivisions.x * image_subdivisions.y); - for (int32_t v = 0; v < image_subdivisions.y; ++v) { - for (int32_t u = 0; u < image_subdivisions.x; ++u) { - PackedByteArray index_data_array; - index_data_array.resize(divided_dims.x * divided_dims.y * sizeof(Map::shape_pixel_t)); - - for (int32_t y = 0; y < divided_dims.y; ++y) - memcpy(index_data_array.ptrw() + y * divided_dims.x * sizeof(Map::shape_pixel_t), - province_shape_data + (v * divided_dims.y + y) * province_dims.x + u * divided_dims.x, - divided_dims.x * sizeof(Map::shape_pixel_t)); - - const Ref province_shape_subimage = Image::create_from_data(divided_dims.x, divided_dims.y, false, Image::FORMAT_RGB8, index_data_array); - if (province_shape_subimage.is_null()) { - UtilityFunctions::push_error("Failed to create province shape image (", u, ", ", v, ")"); - err = FAILED; - } - province_shape_images[u + v * image_subdivisions.x] = province_shape_subimage; - } - } - - province_shape_texture.instantiate(); - if (province_shape_texture->create_from_images(province_shape_images) != OK) { - UtilityFunctions::push_error("Failed to create terrain texture array!"); - err = FAILED; - } - - if (_update_colour_image() != OK) err = FAILED; - - return err; -} -- cgit v1.2.3-56-ga3b1