From 4e9764ee29fb7b453862835d5aa3a081b0f9a269 Mon Sep 17 00:00:00 2001 From: hop311 Date: Mon, 18 Dec 2023 23:38:54 +0000 Subject: Back to UI Work - UIAdapter -> UITools with cleaner API - GUIOverlappingElementsBox (for core and modifier icons) - Improved GUINode API - Province building slots - TypeHints for files in the GameSession folder - Incorporate SIM strong colour types --- .../openvic-extension/singletons/AssetManager.cpp | 45 ------- .../openvic-extension/singletons/AssetManager.hpp | 11 -- .../openvic-extension/singletons/GameSingleton.cpp | 135 +++++++++++---------- .../openvic-extension/singletons/GameSingleton.hpp | 6 +- 4 files changed, 73 insertions(+), 124 deletions(-) (limited to 'extension/src/openvic-extension/singletons') diff --git a/extension/src/openvic-extension/singletons/AssetManager.cpp b/extension/src/openvic-extension/singletons/AssetManager.cpp index 8e9eb41..581c7fa 100644 --- a/extension/src/openvic-extension/singletons/AssetManager.cpp +++ b/extension/src/openvic-extension/singletons/AssetManager.cpp @@ -15,11 +15,6 @@ using OpenVic::Utilities::std_to_godot_string; void AssetManager::_bind_methods() { OV_BIND_METHOD(AssetManager::get_image, { "path" }); OV_BIND_METHOD(AssetManager::get_texture, { "path" }); - - OV_BIND_SMETHOD(AssetManager::make_icon, { "texture", "frame", "frame_count" }); - OV_BIND_METHOD(AssetManager::get_icon, { "texture", "frame", "frame_count" }); - - OV_BIND_METHOD(AssetManager::get_texture_or_icon, { "path", "frame", "frame_count" }); OV_BIND_METHOD(AssetManager::get_font, { "name" }); } @@ -96,46 +91,6 @@ Ref AssetManager::get_texture(StringName path) { } } -Ref AssetManager::make_icon(Ref texture, GFX::frame_t frame, GFX::frame_t frame_count) { - ERR_FAIL_NULL_V(texture, nullptr); - - if (frame_count <= GFX::NO_FRAMES) { - UtilityFunctions::push_warning("No frames!"); - frame_count = 1; - } - if (frame <= GFX::NO_FRAMES || frame > frame_count) { - UtilityFunctions::push_warning("Invalid frame index ", frame, " out of count ", frame_count); - frame = frame_count; - } - frame--; - const Vector2i size = texture->get_size(); - const Rect2i region { frame * size.x / frame_count, 0, size.x / frame_count, size.y }; - - Ref atlas; - atlas.instantiate(); - ERR_FAIL_NULL_V(atlas, nullptr); - atlas->set_atlas(texture); - atlas->set_region(region); - return atlas; -} - -Ref AssetManager::get_icon(StringName path, GFX::frame_t frame, GFX::frame_t frame_count) { - Ref texture = get_texture(path); - ERR_FAIL_NULL_V(texture, nullptr); - return make_icon(texture, frame, frame_count); -} - -Ref AssetManager::get_texture_or_icon(StringName path, GFX::frame_t frame, GFX::frame_t frame_count) { - if (frame_count < 2) { - if (frame > frame_count) { - UtilityFunctions::push_warning("Invalid frame index ", frame, " out of count ", frame_count); - } - return get_texture(path); - } else { - return get_icon(path, frame, frame_count); - } -} - Ref AssetManager::get_font(StringName name) { const font_map_t::const_iterator it = fonts.find(name); if (it != fonts.end()) { diff --git a/extension/src/openvic-extension/singletons/AssetManager.hpp b/extension/src/openvic-extension/singletons/AssetManager.hpp index 625944d..e6a7664 100644 --- a/extension/src/openvic-extension/singletons/AssetManager.hpp +++ b/extension/src/openvic-extension/singletons/AssetManager.hpp @@ -44,17 +44,6 @@ namespace OpenVic { * or texture creation fails. */ godot::Ref get_texture(godot::StringName path); - /* Extract the specified frame of the texture, which is treated as a single row of frame_count frames. */ - static godot::Ref make_icon( - godot::Ref texture, GFX::frame_t frame, GFX::frame_t frame_count - ); - - /* Load a texture as with get_texture, and extract the specified frame as with make_icon. */ - godot::Ref get_icon(godot::StringName path, GFX::frame_t frame, GFX::frame_t frame_count); - - /* Load a texture as with get_texture if frame_count <= 1 otherwise as with get_icon. */ - godot::Ref get_texture_or_icon(godot::StringName path, GFX::frame_t frame, GFX::frame_t frame_count); - /* Search for and load a font with the specified name from the game defines' font directory, first checking the * AssetManager's font cache in case it has already been loaded, and returning nullptr if font loading fails. */ godot::Ref get_font(godot::StringName name); diff --git a/extension/src/openvic-extension/singletons/GameSingleton.cpp b/extension/src/openvic-extension/singletons/GameSingleton.cpp index a53ba54..0e64313 100644 --- a/extension/src/openvic-extension/singletons/GameSingleton.cpp +++ b/extension/src/openvic-extension/singletons/GameSingleton.cpp @@ -8,6 +8,8 @@ #include +#include "openvic-extension/classes/GFXPieChartTexture.hpp" +#include "openvic-extension/singletons/AssetManager.hpp" #include "openvic-extension/singletons/LoadLocalisation.hpp" #include "openvic-extension/utility/ClassBindings.hpp" #include "openvic-extension/utility/Utilities.hpp" @@ -48,7 +50,9 @@ void GameSingleton::_bind_methods() { OV_BIND_METHOD(GameSingleton::get_selected_province_index); OV_BIND_METHOD(GameSingleton::set_selected_province, { "index" }); - OV_BIND_METHOD(GameSingleton::expand_building, { "province_index", "building_type_identifier" }); + OV_BIND_METHOD(GameSingleton::get_province_building_count); + OV_BIND_METHOD(GameSingleton::get_province_building_identifier, { "building_index" }); + OV_BIND_METHOD(GameSingleton::expand_selected_province_building, { "building_index" }); OV_BIND_METHOD(GameSingleton::get_slave_pop_icon_index); OV_BIND_METHOD(GameSingleton::get_administrative_pop_icon_index); OV_BIND_METHOD(GameSingleton::get_rgo_owner_pop_icon_index); @@ -135,51 +139,23 @@ int32_t GameSingleton::get_province_index_from_uv_coords(Vector2 const& coords) return game_manager.get_map().get_province_index_at(x_mod_w, y_mod_h); } -template T> -static Array _distribution_to_pie_chart_array(fixed_point_map_t const& dist) { - using entry_t = std::pair; - std::vector sorted_dist; - sorted_dist.reserve(dist.size()); - for (entry_t const& entry : dist) { - if (entry.first != nullptr) { - sorted_dist.push_back(entry); - } else { - UtilityFunctions::push_error("Null distribution key with value ", entry.second.to_float()); - } - } - std::sort(sorted_dist.begin(), sorted_dist.end(), [](entry_t const& lhs, entry_t const& rhs) -> bool { - return lhs.second < rhs.second; - }); - static const StringName identifier_key = "identifier"; - static const StringName colour_key = "colour"; - static const StringName weight_key = "weight"; - Array array; - for (auto const& [key, val] : sorted_dist) { - Dictionary sub_dict; - sub_dict[identifier_key] = std_view_to_godot_string(key->get_identifier()); - sub_dict[colour_key] = Utilities::to_godot_color(key->get_colour()); - sub_dict[weight_key] = val.to_float(); - array.push_back(sub_dict); - } - return array; -} - Dictionary GameSingleton::get_province_info_from_index(int32_t index) const { static const StringName province_info_province_key = "province"; static const StringName province_info_region_key = "region"; - static const StringName province_info_controller_key = "controller"; - static const StringName province_info_life_rating_key = "life_rating"; + static const StringName province_info_slave_status_key = "slave_status"; + static const StringName province_info_colony_status_key = "colony_status"; static const StringName province_info_terrain_type_key = "terrain_type"; + static const StringName province_info_life_rating_key = "life_rating"; + static const StringName province_info_controller_key = "controller"; + static const StringName province_info_rgo_name_key = "rgo_name"; + static const StringName province_info_rgo_icon_key = "rgo_icon"; static const StringName province_info_crime_name_key = "crime_name"; static const StringName province_info_crime_icon_key = "crime_icon"; static const StringName province_info_total_population_key = "total_population"; static const StringName province_info_pop_types_key = "pop_types"; static const StringName province_info_pop_ideologies_key = "pop_ideologies"; static const StringName province_info_pop_cultures_key = "pop_cultures"; - static const StringName province_info_rgo_name_key = "rgo_name"; - static const StringName province_info_rgo_icon_key = "rgo_icon"; - static const StringName province_info_colony_status_key = "colony_status"; - static const StringName province_info_slave_status_key = "slave_status"; + static const StringName province_info_cores_key = "cores"; static const StringName province_info_buildings_key = "buildings"; Province const* province = game_manager.get_map().get_province_by_index(index); @@ -195,6 +171,17 @@ Dictionary GameSingleton::get_province_info_from_index(int32_t index) const { ret[province_info_region_key] = std_view_to_godot_string(region->get_identifier()); } + ret[province_info_slave_status_key] = province->get_slave(); + + ret[province_info_colony_status_key] = static_cast(province->get_colony_status()); + + TerrainType const* terrain_type = province->get_terrain_type(); + if (terrain_type != nullptr) { + ret[province_info_terrain_type_key] = std_view_to_godot_string(terrain_type->get_identifier()); + } + + ret[province_info_life_rating_key] = province->get_life_rating(); + Country const* controller = province->get_controller(); if (controller != nullptr) { ret[province_info_controller_key] = std_view_to_godot_string(controller->get_identifier()); @@ -206,37 +193,39 @@ Dictionary GameSingleton::get_province_info_from_index(int32_t index) const { ret[province_info_rgo_icon_key] = static_cast(rgo->get_index()); } - ret[province_info_life_rating_key] = province->get_life_rating(); - - TerrainType const* terrain_type = province->get_terrain_type(); - if (terrain_type != nullptr) { - ret[province_info_terrain_type_key] = std_view_to_godot_string(terrain_type->get_identifier()); - } - Crime const* crime = province->get_crime(); if (crime != nullptr) { ret[province_info_crime_name_key] = std_view_to_godot_string(crime->get_identifier()); ret[province_info_crime_icon_key] = static_cast(crime->get_icon()); } - ret[province_info_colony_status_key] = static_cast(province->get_colony_status()); - ret[province_info_slave_status_key] = province->get_slave(); - ret[province_info_total_population_key] = province->get_total_population(); + fixed_point_map_t const& pop_types = province->get_pop_type_distribution(); if (!pop_types.empty()) { - ret[province_info_pop_types_key] = _distribution_to_pie_chart_array(pop_types); + ret[province_info_pop_types_key] = GFXPieChartTexture::distribution_to_slices_array(pop_types); } + fixed_point_map_t const& ideologies = province->get_ideology_distribution(); if (!ideologies.empty()) { - ret[province_info_pop_ideologies_key] = _distribution_to_pie_chart_array(ideologies); + ret[province_info_pop_ideologies_key] = GFXPieChartTexture::distribution_to_slices_array(ideologies); } + fixed_point_map_t const& cultures = province->get_culture_distribution(); if (!cultures.empty()) { - ret[province_info_pop_cultures_key] = _distribution_to_pie_chart_array(cultures); + ret[province_info_pop_cultures_key] = GFXPieChartTexture::distribution_to_slices_array(cultures); + } + + std::vector const& cores = province->get_cores(); + if (!cores.empty()) { + PackedStringArray cores_array; + cores_array.resize(cores.size()); + for (size_t idx = 0; idx < cores.size(); ++idx) { + cores_array[idx] = std_view_to_godot_string(cores[idx]->get_identifier()); + } + ret[province_info_cores_key] = cores_array; } - static const StringName building_info_building_key = "building"; static const StringName building_info_level_key = "level"; static const StringName building_info_expansion_state_key = "expansion_state"; static const StringName building_info_start_date_key = "start_date"; @@ -245,13 +234,14 @@ Dictionary GameSingleton::get_province_info_from_index(int32_t index) const { std::vector const& buildings = province->get_buildings(); if (!buildings.empty()) { - Array buildings_array; + /* This system relies on the province buildings all being present in the right order. It will have to + * be changed if we want to support variable combinations and permutations of province buildings. */ + TypedArray buildings_array; buildings_array.resize(buildings.size()); for (size_t idx = 0; idx < buildings.size(); ++idx) { BuildingInstance const& building = buildings[idx]; Dictionary building_dict; - building_dict[building_info_building_key] = std_view_to_godot_string(building.get_identifier()); building_dict[building_info_level_key] = static_cast(building.get_level()); building_dict[building_info_expansion_state_key] = static_cast(building.get_expansion_state()); building_dict[building_info_start_date_key] = std_to_godot_string(building.get_start_date().to_string()); @@ -321,14 +311,14 @@ Error GameSingleton::_update_colour_image() { return FAILED; } /* We reshape the list of colours into a square, as each texture dimensions cannot exceed 16384. */ - static constexpr int32_t PROVINCE_INDEX_SQRT = 1 << (sizeof(Province::index_t) * 4); - static constexpr int32_t colour_image_width = PROVINCE_INDEX_SQRT * sizeof(Mapmode::base_stripe_t) / sizeof(colour_t); + static constexpr int32_t PROVINCE_INDEX_SQRT = 1 << (sizeof(Province::index_t) * CHAR_BIT / 2); + static constexpr int32_t colour_image_width = PROVINCE_INDEX_SQRT * sizeof(Mapmode::base_stripe_t) / sizeof(colour_argb_t); /* Province count + null province, rounded up to next multiple of PROVINCE_INDEX_SQRT. * Rearranged from: (map.get_province_count() + 1) + (PROVINCE_INDEX_SQRT - 1) */ static const int32_t colour_image_height = (map.get_province_count() + PROVINCE_INDEX_SQRT) / PROVINCE_INDEX_SQRT; static PackedByteArray colour_data_array; - static const int64_t colour_data_array_size = colour_image_width * colour_image_height * sizeof(colour_t); + static const int64_t colour_data_array_size = colour_image_width * colour_image_height * sizeof(colour_argb_t); colour_data_array.resize(colour_data_array_size); Error err = OK; @@ -386,12 +376,25 @@ void GameSingleton::set_selected_province(int32_t index) { emit_signal("province_selected", index); } -Error GameSingleton::expand_building(int32_t province_index, String const& building_type_identifier) { - if (!game_manager.expand_building(province_index, godot_to_std_string(building_type_identifier))) { - UtilityFunctions::push_error("Failed to expand ", building_type_identifier, " at province index ", province_index); - return FAILED; +int32_t GameSingleton::get_province_building_count() const { + return game_manager.get_economy_manager().get_building_type_manager().get_province_building_types().size(); +} + +String GameSingleton::get_province_building_identifier(int32_t index) const { + std::vector const& province_building_types = + game_manager.get_economy_manager().get_building_type_manager().get_province_building_types(); + ERR_FAIL_COND_V_MSG( + index < 0 || index >= province_building_types.size(), {}, vformat("Invalid province building index: %d", index) + ); + return std_view_to_godot_string(province_building_types[index]->get_identifier()); +} + +Error GameSingleton::expand_selected_province_building(int32_t building_index) { + const bool ret = game_manager.expand_selected_province_building(building_index); + if (!ret) { + UtilityFunctions::push_error("Failed to expand the currently selected province's building index ", building_index); } - return OK; + return ERR(ret); } int32_t GameSingleton::get_slave_pop_icon_index() const { @@ -493,7 +496,7 @@ Error GameSingleton::_load_map_images(bool flip_vertical) { 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; + TypedArray 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) { @@ -561,12 +564,14 @@ Error GameSingleton::_load_terrain_variants() { } const int32_t slice_size = sheet_width / SHEET_DIMS; - Array terrain_images; + TypedArray 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()); + // TODO - load "map/terrain/water.dds" instead of using a solid colour (issue is that it's 512x512 + // while the texturesheet slices are 256x256, so they can't share a Texture2DArray) + const Ref water_image = Utilities::make_solid_colour_image( + { 0.1f, 0.1f, 0.5f }, slice_size, slice_size, 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; diff --git a/extension/src/openvic-extension/singletons/GameSingleton.hpp b/extension/src/openvic-extension/singletons/GameSingleton.hpp index 5559f1b..1f3905e 100644 --- a/extension/src/openvic-extension/singletons/GameSingleton.hpp +++ b/extension/src/openvic-extension/singletons/GameSingleton.hpp @@ -7,8 +7,6 @@ #include #include -#include "openvic-extension/UIAdapter.hpp" - namespace OpenVic { class GameSingleton : public godot::Object { @@ -95,7 +93,9 @@ namespace OpenVic { int32_t get_selected_province_index() const; void set_selected_province(int32_t index); - godot::Error expand_building(int32_t province_index, godot::String const& building_type_identifier); + int32_t get_province_building_count() const; + godot::String get_province_building_identifier(int32_t building_index) const; + godot::Error expand_selected_province_building(int32_t building_index); int32_t get_slave_pop_icon_index() const; int32_t get_administrative_pop_icon_index() const; int32_t get_rgo_owner_pop_icon_index() const; -- cgit v1.2.3-56-ga3b1