From de2017128313b9a322eb59c40a4180099d9c18b7 Mon Sep 17 00:00:00 2001 From: Hop311 Date: Sun, 24 Sep 2023 22:45:37 +0100 Subject: DDS load + moved terrain (type) loading to sim --- .gitmodules | 3 ++ SConstruct | 9 ++-- extension/deps/openvic-simulation | 2 +- extension/src/openvic-extension/GameSingleton.cpp | 11 +++-- extension/src/openvic-extension/GameSingleton.hpp | 9 ++-- .../openvic-extension/LoadGameCompatibility.cpp | 19 ++------- .../src/openvic-extension/LoadGameOpenVic.cpp | 49 ++-------------------- extension/src/openvic-extension/Utilities.cpp | 38 +++++++++++++++++ 8 files changed, 65 insertions(+), 75 deletions(-) diff --git a/.gitmodules b/.gitmodules index e7ef8d9..96db130 100644 --- a/.gitmodules +++ b/.gitmodules @@ -7,3 +7,6 @@ [submodule "scripts"] path = scripts url = https://github.com/OpenVicProject/scripts +[submodule "extension/deps/gli"] + path = extension/deps/gli + url = https://github.com/g-truc/gli diff --git a/SConstruct b/SConstruct index db5d150..ee7be9d 100644 --- a/SConstruct +++ b/SConstruct @@ -36,9 +36,10 @@ SConscript("extension/deps/SCsub", "env") # - LINKFLAGS are for linking flags # tweak this if you want to use different folders, or more folders, to store your source code in. -paths = ["extension/src"] -env.Append(CPPPATH=[[env.Dir(p) for p in paths]]) -sources = env.GlobRecursive("*.cpp", paths) +source_paths = ["extension/src"] +include_paths = ["extension/deps/gli", "extension/deps/gli/external"] +env.Append(CPPPATH=[[env.Dir(p) for p in source_paths + include_paths]]) +sources = env.GlobRecursive("*.cpp", source_paths) env.extension_sources = sources # Remove unassociated intermediate binary files if allowed, usually the result of a renamed or deleted source file @@ -49,7 +50,7 @@ if env["intermediate_delete"]: return file[:file.rindex(".")] found_one = False - for path in paths: + for path in source_paths: for obj_file in [file[:-len(".os")] for file in glob(path + "*.os", recursive=True)]: found = False for source_file in sources: diff --git a/extension/deps/openvic-simulation b/extension/deps/openvic-simulation index 05b6db7..8256fe4 160000 --- a/extension/deps/openvic-simulation +++ b/extension/deps/openvic-simulation @@ -1 +1 @@ -Subproject commit 05b6db7305398e12363f727a50315972cc9a5a54 +Subproject commit 8256fe4c9468e23f5397d92796a741893b9469bc diff --git a/extension/src/openvic-extension/GameSingleton.cpp b/extension/src/openvic-extension/GameSingleton.cpp index 2d6f784..cdba44c 100644 --- a/extension/src/openvic-extension/GameSingleton.cpp +++ b/extension/src/openvic-extension/GameSingleton.cpp @@ -9,10 +9,8 @@ using namespace godot; using namespace OpenVic; -TerrainVariant::TerrainVariant(const std::string_view new_identfier, - colour_t new_colour, Ref const& new_image) - : HasIdentifierAndColour { new_identfier, new_colour, true, false }, - image { new_image } {} +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; @@ -81,6 +79,7 @@ void GameSingleton::_bind_methods() { "shadow_displacement", "shadow_tightness", "shadow_radius", "shadow_thickness", "trim_colour", "trim_size", "gradient_falloff", "gradient_base", "donut", "donut_inner_trim", "donut_inner_radius"), &GameSingleton::draw_pie_chart); + ClassDB::bind_static_method("GameSingleton", D_METHOD("load_image", "path"), &GameSingleton::load_image); } void GameSingleton::draw_pie_chart(Ref image, @@ -94,6 +93,10 @@ void GameSingleton::draw_pie_chart(Ref image, donut, donut_inner_trim, donut_inner_radius); } +Ref GameSingleton::load_image(String const& path) { + return load_godot_image(path); +} + GameSingleton* GameSingleton::get_singleton() { return singleton; } diff --git a/extension/src/openvic-extension/GameSingleton.hpp b/extension/src/openvic-extension/GameSingleton.hpp index 4d9e912..2a72e2f 100644 --- a/extension/src/openvic-extension/GameSingleton.hpp +++ b/extension/src/openvic-extension/GameSingleton.hpp @@ -8,17 +8,16 @@ namespace OpenVic { - struct TerrainVariant : HasIdentifierAndColour { + struct TerrainVariant : HasIdentifier { friend class GameSingleton; private: const godot::Ref image; - TerrainVariant(const std::string_view new_identfier, colour_t new_colour, - godot::Ref const& new_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(Map::terrain_t)); + static constexpr size_t MAX_TERRIN_VARIANT_COUNT = 1 << (8 * sizeof(TerrainTypeMapping::index_t)); TerrainVariant(TerrainVariant&&) = default; @@ -39,7 +38,6 @@ namespace OpenVic { godot::Ref province_colour_texture; Mapmode::index_t mapmode_index = 0; IdentifierRegistry terrain_variants; - Map::terrain_variant_map_t terrain_variant_map; godot::Ref terrain_texture; godot::Error _generate_terrain_texture_array(); @@ -63,6 +61,7 @@ namespace OpenVic { godot::Vector2 shadow_displacement, float shadow_tightness, float shadow_radius, float shadow_thickness, godot::Color trim_colour, float trim_size, float gradient_falloff, float gradient_base, bool donut, bool donut_inner_trim, float donut_inner_radius); + static godot::Ref load_image(godot::String const& path); static GameSingleton* get_singleton(); diff --git a/extension/src/openvic-extension/LoadGameCompatibility.cpp b/extension/src/openvic-extension/LoadGameCompatibility.cpp index b696315..0a6cb33 100644 --- a/extension/src/openvic-extension/LoadGameCompatibility.cpp +++ b/extension/src/openvic-extension/LoadGameCompatibility.cpp @@ -12,18 +12,7 @@ using namespace godot; using namespace OpenVic; Error GameSingleton::_load_terrain_variants_compatibility_mode(String const& terrain_image_path, String const& terrain_texturesheet_path) { - // Read BMP's palette to determine terrain variant colours which texture they're associated with - BMP bmp; - if (!(bmp.open(godot_to_std_string(terrain_image_path).c_str()) && bmp.read_header() && bmp.read_palette())) { - UtilityFunctions::push_error("Failed to read BMP palette from compatibility mode terrain image: ", terrain_image_path); - return FAILED; - } - std::vector const& palette = bmp.get_palette(); - static constexpr int32_t SHEET_DIMS = 8, PALETTE_SIZE = SHEET_DIMS * SHEET_DIMS; - if (palette.size() == 0 || palette.size() < PALETTE_SIZE) { - UtilityFunctions::push_error("Invalid BMP palette size for terrain image: ", static_cast(palette.size()), " (expected ", PALETTE_SIZE, ")"); - return FAILED; - } + 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); @@ -44,10 +33,10 @@ Error GameSingleton::_load_terrain_variants_compatibility_mode(String const& ter 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", TERRAIN_WATER_INDEX_COLOUR, water_image }); + terrain_variants.add_item({ "terrain_water", water_image }); } Error err = OK; - for (int32_t idx = 0; idx < PALETTE_SIZE; ++idx) { + 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()) { @@ -55,7 +44,7 @@ Error GameSingleton::_load_terrain_variants_compatibility_mode(String const& ter err = FAILED; continue; } - if (!terrain_variants.add_item({ "terrain_" + std::to_string(idx), palette[idx], terrain_image })) err = FAILED; + 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; diff --git a/extension/src/openvic-extension/LoadGameOpenVic.cpp b/extension/src/openvic-extension/LoadGameOpenVic.cpp index c34411c..b118f87 100644 --- a/extension/src/openvic-extension/LoadGameOpenVic.cpp +++ b/extension/src/openvic-extension/LoadGameOpenVic.cpp @@ -25,7 +25,6 @@ Error GameSingleton::_generate_terrain_texture_array() { 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_variant_map[var.get_colour()] = i; terrain_images.append(var.get_image()); } @@ -43,53 +42,11 @@ Error GameSingleton::_load_map_images(String const& province_image_path, String return FAILED; } - // Load images - Ref province_image = load_godot_image(province_image_path); - if (province_image.is_null()) { - UtilityFunctions::push_error("Failed to load province image: ", province_image_path); - return FAILED; - } - Ref terrain_image = load_godot_image(terrain_image_path); - if (terrain_image.is_null()) { - UtilityFunctions::push_error("Failed to load terrain image: ", terrain_image_path); - return FAILED; - } - - if (flip_vertical) { - province_image->flip_y(); - terrain_image->flip_y(); - } - - // Validate dimensions and format Error err = OK; - const Vector2i province_dims = province_image->get_size(), terrain_dims = terrain_image->get_size(); - if (province_dims.x < 1 || province_dims.y < 1) { - UtilityFunctions::push_error("Invalid dimensions (", province_dims.x, "x", province_dims.y, ") for province image: ", province_image_path); - err = FAILED; - } - if (province_dims != terrain_dims) { - UtilityFunctions::push_error("Invalid dimensions (", terrain_dims.x, "x", terrain_dims.y, ") for terrain image: ", - terrain_image_path, " (must match province image: (", province_dims.x, "x", province_dims.x, "))"); - err = FAILED; - } - static constexpr Image::Format expected_format = Image::FORMAT_RGB8; - if (province_image->get_format() == Image::FORMAT_RGBA8) province_image->convert(expected_format); - if (terrain_image->get_format() == Image::FORMAT_RGBA8) terrain_image->convert(expected_format); - if (province_image->get_format() != expected_format) { - UtilityFunctions::push_error("Invalid format (", province_image->get_format(), ", should be ", expected_format, ") for province image: ", province_image_path); - err = FAILED; - } - if (terrain_image->get_format() != expected_format) { - UtilityFunctions::push_error("Invalid format (", terrain_image->get_format(), ", should be ", expected_format, ") for terrain image: ", terrain_image_path); - err = FAILED; - } - if (err != OK) return err; - // Generate interleaved province and terrain ID image - if (!game_manager.get_map().generate_province_shape_image(province_dims.x, province_dims.y, - province_image->get_data().ptr(), terrain_image->get_data().ptr(), terrain_variant_map, - false /* <-- whether to print detailed map errors or not (specific missing/unrecognised colours) */ - )) err = FAILED; + 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 diff --git a/extension/src/openvic-extension/Utilities.cpp b/extension/src/openvic-extension/Utilities.cpp index 4ca6855..649550f 100644 --- a/extension/src/openvic-extension/Utilities.cpp +++ b/extension/src/openvic-extension/Utilities.cpp @@ -2,17 +2,55 @@ #include +#include #include #include +#include +#include + using namespace godot; using namespace OpenVic; +static Ref load_dds_image(String const& path) { + gli::texture2d texture { gli::load_dds(godot_to_std_string(path)) }; + if (texture.empty()) { + UtilityFunctions::push_error("Failed to load DDS file: ", path); + return {}; + } + + static constexpr gli::format expected_format = gli::FORMAT_BGRA8_UNORM_PACK8; + const bool needs_bgr_to_rgb = texture.format() == expected_format; + if (!needs_bgr_to_rgb) { + texture = gli::convert(texture, expected_format); + if (texture.empty()) { + UtilityFunctions::push_error("Failed to convert DDS file: ", path); + return {}; + } + } + + PackedByteArray pixels; + pixels.resize(texture.size()); + memcpy(pixels.ptrw(), texture.data(), pixels.size()); + UtilityFunctions::print("needs_bgr_to_rgb = ", needs_bgr_to_rgb); + if (needs_bgr_to_rgb) { + for (size_t i = 0; i < pixels.size(); i += 4) { + std::swap(pixels[i], pixels[i+2]); + } + } + + const gli::texture2d::extent_type extent { texture.extent() }; + return Image::create_from_data(extent.x, extent.y, false, Image::FORMAT_RGBA8, pixels); +} + Ref OpenVic::load_godot_image(String const& path) { if (path.begins_with("res://")) { ResourceLoader* loader = ResourceLoader::get_singleton(); return loader ? loader->load(path) : nullptr; } else { + if (path.ends_with(".dds")) { + return load_dds_image(path); + } return Image::load_from_file(path); } } -- cgit v1.2.3-56-ga3b1 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 ------------ game/localisation/en_GB/mapmodes.csv | 1 + game/localisation/en_GB/menus.csv | 1 + .../ProvinceOverviewPanel/ProvinceOverviewPanel.gd | 4 +- .../ProvinceOverviewPanel.tscn | 8 +- 8 files changed, 166 insertions(+), 223 deletions(-) delete mode 100644 extension/src/openvic-extension/LoadGameCompatibility.cpp delete mode 100644 extension/src/openvic-extension/LoadGameOpenVic.cpp 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; -} diff --git a/game/localisation/en_GB/mapmodes.csv b/game/localisation/en_GB/mapmodes.csv index bcb466f..2aa4cd2 100644 --- a/game/localisation/en_GB/mapmodes.csv +++ b/game/localisation/en_GB/mapmodes.csv @@ -4,6 +4,7 @@ mapmode_province;Province mapmode_region;Region mapmode_terrain;Terrain mapmode_index;Index +mapmode_terrain_type;Terrain Type mapmode_rgo;RGO mapmode_infrastructure;Infrastructure mapmode_population;Population Density diff --git a/game/localisation/en_GB/menus.csv b/game/localisation/en_GB/menus.csv index 57994ad..f81decf 100644 --- a/game/localisation/en_GB/menus.csv +++ b/game/localisation/en_GB/menus.csv @@ -123,6 +123,7 @@ DIALOG_SAVE_AND_QUIT;Save and Quit province_MISSING;No Province region_MISSING;No Region LIFE_RATING_TOOLTIP;Liferating: {life_rating} +terrain_type_MISSING;No Terrain Type total_population_MISSING;No Population PROVINCE_POPULATION_TOOLTIP;Province population rgo_MISSING;No RGO diff --git a/game/src/Game/GameSession/ProvinceOverviewPanel/ProvinceOverviewPanel.gd b/game/src/Game/GameSession/ProvinceOverviewPanel/ProvinceOverviewPanel.gd index 01175d0..ae42450 100644 --- a/game/src/Game/GameSession/ProvinceOverviewPanel/ProvinceOverviewPanel.gd +++ b/game/src/Game/GameSession/ProvinceOverviewPanel/ProvinceOverviewPanel.gd @@ -3,6 +3,7 @@ extends PanelContainer @export var _province_name_label : Label @export var _region_name_label : Label @export var _life_rating_bar : ProgressBar +@export var _terrain_type_name_label : Label @export var _total_population_label : Label @export var _rgo_icon_texture_rect : TextureRect @export var _rgo_name_label : Label @@ -108,11 +109,12 @@ func _update_info() -> void: GameSingleton.get_province_info_province_key() + _missing_suffix) _region_name_label.text = _province_info.get(GameSingleton.get_province_info_region_key(), GameSingleton.get_province_info_region_key() + _missing_suffix) - _life_rating_bar.value = _province_info.get(GameSingleton.get_province_info_life_rating_key(), 0) _life_rating_bar.tooltip_text = tr("LIFE_RATING_TOOLTIP").format({ "life_rating": Localisation.tr_number(_life_rating_bar.value) }) + _terrain_type_name_label.text = _province_info.get(GameSingleton.get_province_info_terrain_type_key(), + GameSingleton.get_province_info_terrain_type_key() + _missing_suffix) _total_population_label.text = Localisation.tr_number(_province_info.get(GameSingleton.get_province_info_total_population_key(), 0)) diff --git a/game/src/Game/GameSession/ProvinceOverviewPanel/ProvinceOverviewPanel.tscn b/game/src/Game/GameSession/ProvinceOverviewPanel/ProvinceOverviewPanel.tscn index 7a982e9..bbd0b95 100644 --- a/game/src/Game/GameSession/ProvinceOverviewPanel/ProvinceOverviewPanel.tscn +++ b/game/src/Game/GameSession/ProvinceOverviewPanel/ProvinceOverviewPanel.tscn @@ -3,7 +3,7 @@ [ext_resource type="Script" path="res://src/Game/GameSession/ProvinceOverviewPanel/ProvinceOverviewPanel.gd" id="1_3n8k5"] [ext_resource type="PackedScene" uid="uid://cr7p1k2xm7mum" path="res://src/Game/Theme/PieChart/PieChart.tscn" id="2_3oytt"] -[node name="ProvinceOverviewPanel" type="PanelContainer" node_paths=PackedStringArray("_province_name_label", "_region_name_label", "_life_rating_bar", "_total_population_label", "_rgo_icon_texture_rect", "_rgo_name_label", "_buildings_container", "_pop_type_chart", "_pop_ideology_chart", "_pop_culture_chart")] +[node name="ProvinceOverviewPanel" type="PanelContainer" node_paths=PackedStringArray("_province_name_label", "_region_name_label", "_life_rating_bar", "_terrain_type_name_label", "_total_population_label", "_rgo_icon_texture_rect", "_rgo_name_label", "_buildings_container", "_pop_type_chart", "_pop_ideology_chart", "_pop_culture_chart")] editor_description = "UI-56" anchors_preset = 2 anchor_top = 1.0 @@ -16,6 +16,7 @@ script = ExtResource("1_3n8k5") _province_name_label = NodePath("PanelList/TopBarList/NameList/ProvinceName") _region_name_label = NodePath("PanelList/TopBarList/NameList/RegionName") _life_rating_bar = NodePath("PanelList/TopBarList/NameList/LifeRatingBar") +_terrain_type_name_label = NodePath("PanelList/TopBarList/NameList/TerrainTypeName") _total_population_label = NodePath("PanelList/InteractList/TotalPopulation") _rgo_icon_texture_rect = NodePath("PanelList/InteractList/RGOInfo/RGOIcon") _rgo_name_label = NodePath("PanelList/InteractList/RGOInfo/RGOName") @@ -52,6 +53,11 @@ editor_description = "UI-62" layout_mode = 2 mouse_filter = 1 +[node name="TerrainTypeName" type="Label" parent="PanelList/TopBarList/NameList"] +layout_mode = 2 +text = "terrain_type_MISSING" +vertical_alignment = 1 + [node name="CloseButton" type="Button" parent="PanelList/TopBarList"] custom_minimum_size = Vector2(30, 30) layout_mode = 2 -- cgit v1.2.3-56-ga3b1 From a53a1891c63cbf809c4fc5481238de6a8b12f8c1 Mon Sep 17 00:00:00 2001 From: Hop311 Date: Tue, 26 Sep 2023 20:32:51 +0100 Subject: Updated scripts + fixed GLI submodules --- extension/deps/gli | 1 + scripts | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) create mode 160000 extension/deps/gli diff --git a/extension/deps/gli b/extension/deps/gli new file mode 160000 index 0000000..779b99a --- /dev/null +++ b/extension/deps/gli @@ -0,0 +1 @@ +Subproject commit 779b99ac6656e4d30c3b24e96e0136a59649a869 diff --git a/scripts b/scripts index 925a38d..3060e56 160000 --- a/scripts +++ b/scripts @@ -1 +1 @@ -Subproject commit 925a38d4d8aef200823f50345dfa2570891454c4 +Subproject commit 3060e56388ac00d90deb6693ec19d47bad52deb2 -- cgit v1.2.3-56-ga3b1 From 90c90f2ece542c05df9e87cdf7398bbf54a87697 Mon Sep 17 00:00:00 2001 From: Hop311 Date: Thu, 28 Sep 2023 23:28:12 +0100 Subject: Scons rearrangement --- SConstruct | 9 ++++----- extension/deps/SCsub | 9 ++++++++- 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/SConstruct b/SConstruct index ee7be9d..db5d150 100644 --- a/SConstruct +++ b/SConstruct @@ -36,10 +36,9 @@ SConscript("extension/deps/SCsub", "env") # - LINKFLAGS are for linking flags # tweak this if you want to use different folders, or more folders, to store your source code in. -source_paths = ["extension/src"] -include_paths = ["extension/deps/gli", "extension/deps/gli/external"] -env.Append(CPPPATH=[[env.Dir(p) for p in source_paths + include_paths]]) -sources = env.GlobRecursive("*.cpp", source_paths) +paths = ["extension/src"] +env.Append(CPPPATH=[[env.Dir(p) for p in paths]]) +sources = env.GlobRecursive("*.cpp", paths) env.extension_sources = sources # Remove unassociated intermediate binary files if allowed, usually the result of a renamed or deleted source file @@ -50,7 +49,7 @@ if env["intermediate_delete"]: return file[:file.rindex(".")] found_one = False - for path in source_paths: + for path in paths: for obj_file in [file[:-len(".os")] for file in glob(path + "*.os", recursive=True)]: found = False for source_file in sources: diff --git a/extension/deps/SCsub b/extension/deps/SCsub index 25a3286..6a7a48d 100644 --- a/extension/deps/SCsub +++ b/extension/deps/SCsub @@ -9,4 +9,11 @@ def build_openvic_simulation(env): env.Append(CPPPATH=ovsim_env.openvic_simulation["INCPATH"]) env.openvic_simulation = ovsim_env.openvic_simulation -build_openvic_simulation(env) \ No newline at end of file +def build_gli(env): + gli_includes = ["gli", "gli/external"] + env.gli_loader = {} + env.gli_loader["INCPATH"] = [env.Dir(p) for p in gli_includes] + env.Append(CPPPATH=env.gli_loader["INCPATH"]) + +build_openvic_simulation(env) +build_gli(env) -- cgit v1.2.3-56-ga3b1 From 86dd609511b643a6556c42622ec891c092366c66 Mon Sep 17 00:00:00 2001 From: Hop311 Date: Fri, 29 Sep 2023 00:08:15 +0100 Subject: Updated SIM submodule + building info wrapper --- extension/deps/openvic-simulation | 2 +- extension/src/openvic-extension/GameSingleton.cpp | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/extension/deps/openvic-simulation b/extension/deps/openvic-simulation index 8256fe4..0479592 160000 --- a/extension/deps/openvic-simulation +++ b/extension/deps/openvic-simulation @@ -1 +1 @@ -Subproject commit 8256fe4c9468e23f5397d92796a741893b9469bc +Subproject commit 04795924456062db1631686a90f13d963791ad34 diff --git a/extension/src/openvic-extension/GameSingleton.cpp b/extension/src/openvic-extension/GameSingleton.cpp index e0dc14e..ade6ec9 100644 --- a/extension/src/openvic-extension/GameSingleton.cpp +++ b/extension/src/openvic-extension/GameSingleton.cpp @@ -232,7 +232,7 @@ 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()); @@ -244,16 +244,16 @@ Dictionary GameSingleton::get_province_info_from_index(int32_t index) const { distribution_t const& cultures = province->get_culture_distribution(); if (!cultures.empty()) ret[get_province_info_pop_cultures_key()] = _distribution_to_dictionary(cultures); - std::vector const& buildings = province->get_buildings(); + std::vector const& buildings = province->get_buildings(); if (!buildings.empty()) { Array buildings_array; buildings_array.resize(buildings.size()); for (size_t idx = 0; idx < buildings.size(); ++idx) { - Building const& building = buildings[idx]; + BuildingInstance const& building = buildings[idx]; Dictionary building_dict; building_dict[get_building_info_building_key()] = std_to_godot_string(building.get_identifier()); - building_dict[get_building_info_level_key()] = static_cast(building.get_level()); + building_dict[get_building_info_level_key()] = static_cast(building.get_current_level()); building_dict[get_building_info_expansion_state_key()] = static_cast(building.get_expansion_state()); building_dict[get_building_info_start_date_key()] = std_to_godot_string(building.get_start_date().to_string()); building_dict[get_building_info_end_date_key()] = std_to_godot_string(building.get_end_date().to_string()); -- cgit v1.2.3-56-ga3b1