aboutsummaryrefslogtreecommitdiff
path: root/extension/src/openvic-extension/classes/GFXMaskedFlagTexture.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'extension/src/openvic-extension/classes/GFXMaskedFlagTexture.cpp')
-rw-r--r--extension/src/openvic-extension/classes/GFXMaskedFlagTexture.cpp183
1 files changed, 183 insertions, 0 deletions
diff --git a/extension/src/openvic-extension/classes/GFXMaskedFlagTexture.cpp b/extension/src/openvic-extension/classes/GFXMaskedFlagTexture.cpp
new file mode 100644
index 0000000..3636855
--- /dev/null
+++ b/extension/src/openvic-extension/classes/GFXMaskedFlagTexture.cpp
@@ -0,0 +1,183 @@
+#include "GFXMaskedFlagTexture.hpp"
+
+#include <godot_cpp/variant/utility_functions.hpp>
+
+#include "openvic-extension/singletons/AssetManager.hpp"
+#include "openvic-extension/singletons/GameSingleton.hpp"
+#include "openvic-extension/utility/ClassBindings.hpp"
+#include "openvic-extension/utility/Utilities.hpp"
+
+using namespace godot;
+using namespace OpenVic;
+
+using OpenVic::Utilities::godot_to_std_string;
+using OpenVic::Utilities::std_view_to_godot_string;
+using OpenVic::Utilities::std_view_to_godot_string_name;
+
+Error GFXMaskedFlagTexture::_generate_combined_image() {
+ ERR_FAIL_NULL_V(overlay_image, FAILED);
+ bool can_update = true;
+ if (combined_image.is_null() || combined_image->get_size() != overlay_image->get_size()) {
+ combined_image = Image::create(
+ overlay_image->get_width(), overlay_image->get_height(), false, overlay_image->get_format()
+ );
+ ERR_FAIL_NULL_V(combined_image, FAILED);
+ can_update = false;
+ }
+
+ if (mask_image.is_valid() && flag_image.is_valid()) {
+ const Vector2i centre_translation = (mask_image->get_size() - combined_image->get_size()) / 2;
+ for (Vector2i combined_image_point { 0, 0 }; combined_image_point.y < combined_image->get_height(); ++combined_image_point.y) {
+ for (combined_image_point.x = 0; combined_image_point.x < combined_image->get_width(); ++combined_image_point.x) {
+ const Color overlay_image_colour = overlay_image->get_pixelv(combined_image_point);
+ // Translate to mask_image coordinates, keeping the centres of each image aligned.
+ const Vector2i mask_image_point = combined_image_point + centre_translation;
+ if (
+ 0 <= mask_image_point.x && mask_image_point.x < mask_image->get_width() &&
+ 0 <= mask_image_point.y && mask_image_point.y < mask_image->get_height()
+ ) {
+ const Color mask_image_colour = mask_image->get_pixelv(mask_image_point);
+ // Rescale from mask_image to flag_image coordinates.
+ const Vector2i flag_image_point = mask_image_point * flag_image->get_size() / mask_image->get_size();
+ Color flag_image_colour = flag_image->get_pixelv(flag_image_point);
+ flag_image_colour.a = mask_image_colour.a;
+ combined_image->set_pixelv(combined_image_point, flag_image_colour.blend(overlay_image_colour));
+ } else {
+ combined_image->set_pixelv(combined_image_point, overlay_image_colour);
+ }
+ }
+ }
+ } else {
+ combined_image->blit_rect(overlay_image, overlay_image->get_used_rect(), {});
+ }
+
+ if (can_update) {
+ update(combined_image);
+ } else {
+ set_image(combined_image);
+ }
+ return OK;
+}
+
+void GFXMaskedFlagTexture::_bind_methods() {
+ OV_BIND_METHOD(GFXMaskedFlagTexture::clear);
+
+ OV_BIND_METHOD(GFXMaskedFlagTexture::set_gfx_masked_flag_name, { "gfx_masked_flag_name" });
+ OV_BIND_METHOD(GFXMaskedFlagTexture::get_gfx_masked_flag_name);
+
+ OV_BIND_METHOD(GFXMaskedFlagTexture::set_flag_country_name_and_type, { "new_flag_country_name", "new_flag_type" });
+ OV_BIND_METHOD(GFXMaskedFlagTexture::get_flag_country_name);
+ OV_BIND_METHOD(GFXMaskedFlagTexture::get_flag_type);
+}
+
+GFXMaskedFlagTexture::GFXMaskedFlagTexture() : gfx_masked_flag { nullptr }, flag_country { nullptr } {}
+
+Ref<GFXMaskedFlagTexture> GFXMaskedFlagTexture::make_gfx_masked_flag_texture(GFX::MaskedFlag const* gfx_masked_flag) {
+ Ref<GFXMaskedFlagTexture> masked_flag_texture;
+ masked_flag_texture.instantiate();
+ ERR_FAIL_NULL_V(masked_flag_texture, nullptr);
+ if (masked_flag_texture->set_gfx_masked_flag(gfx_masked_flag) == OK) {
+ return masked_flag_texture;
+ } else {
+ return nullptr;
+ }
+}
+
+void GFXMaskedFlagTexture::clear() {
+ gfx_masked_flag = nullptr;
+ flag_country = nullptr;
+ flag_type = String {};
+
+ overlay_image.unref();
+ mask_image.unref();
+ flag_image.unref();
+}
+
+Error GFXMaskedFlagTexture::set_gfx_masked_flag(GFX::MaskedFlag const* new_gfx_masked_flag) {
+ if (gfx_masked_flag == new_gfx_masked_flag) {
+ return OK;
+ }
+ if (new_gfx_masked_flag == nullptr) {
+ clear();
+ return OK;
+ }
+ AssetManager* asset_manager = AssetManager::get_singleton();
+ ERR_FAIL_NULL_V(asset_manager, FAILED);
+
+ const StringName overlay_file = std_view_to_godot_string_name(new_gfx_masked_flag->get_overlay_file());
+ const Ref<Image> new_overlay_image = asset_manager->get_image(overlay_file);
+ ERR_FAIL_NULL_V_MSG(new_overlay_image, FAILED, vformat("Failed to load flag overlay image: %s", overlay_file));
+
+ const StringName mask_file = std_view_to_godot_string_name(new_gfx_masked_flag->get_mask_file());
+ const Ref<Image> new_mask_image = asset_manager->get_image(mask_file);
+ ERR_FAIL_NULL_V_MSG(new_mask_image, FAILED, vformat("Failed to load flag mask image: %s", mask_file));
+
+ gfx_masked_flag = new_gfx_masked_flag;
+ overlay_image = new_overlay_image;
+ mask_image = new_mask_image;
+
+ return _generate_combined_image();
+}
+
+Error GFXMaskedFlagTexture::set_gfx_masked_flag_name(String const& gfx_masked_flag_name) {
+ if (gfx_masked_flag_name.is_empty()) {
+ return set_gfx_masked_flag(nullptr);
+ }
+ GameSingleton* game_singleton = GameSingleton::get_singleton();
+ ERR_FAIL_NULL_V(game_singleton, FAILED);
+ GFX::Sprite const* sprite = game_singleton->get_game_manager().get_ui_manager().get_sprite_by_identifier(
+ godot_to_std_string(gfx_masked_flag_name)
+ );
+ ERR_FAIL_NULL_V_MSG(sprite, FAILED, vformat("GFX sprite not found: %s", gfx_masked_flag_name));
+ GFX::MaskedFlag const* new_masked_flag = sprite->cast_to<GFX::MaskedFlag>();
+ ERR_FAIL_NULL_V_MSG(
+ new_masked_flag, FAILED, vformat(
+ "Invalid type for GFX sprite %s: %s (expected %s)", gfx_masked_flag_name,
+ std_view_to_godot_string(sprite->get_type()), std_view_to_godot_string(GFX::MaskedFlag::get_type_static())
+ )
+ );
+ return set_gfx_masked_flag(new_masked_flag);
+}
+
+String GFXMaskedFlagTexture::get_gfx_masked_flag_name() const {
+ return gfx_masked_flag != nullptr ? std_view_to_godot_string(gfx_masked_flag->get_name()) : String {};
+}
+
+Error GFXMaskedFlagTexture::set_flag_country_and_type(Country const* new_flag_country, StringName const& new_flag_type) {
+ if (flag_country == new_flag_country && flag_type == new_flag_type) {
+ return OK;
+ }
+ if (new_flag_country != nullptr) {
+ GameSingleton* game_singleton = GameSingleton::get_singleton();
+ ERR_FAIL_NULL_V(game_singleton, FAILED);
+
+ const Ref<Image> new_flag_image = game_singleton->get_flag_image(new_flag_country, new_flag_type);
+ ERR_FAIL_NULL_V(new_flag_image, FAILED);
+
+ flag_country = new_flag_country;
+ flag_type = new_flag_type;
+ flag_image = new_flag_image;
+ } else {
+ flag_country = nullptr;
+ flag_type = String {};
+ flag_image.unref();
+ }
+ return _generate_combined_image();
+}
+
+Error GFXMaskedFlagTexture::set_flag_country_name_and_type(String const& new_flag_country_name, StringName const& new_flag_type) {
+ if (new_flag_country_name.is_empty()) {
+ return set_flag_country_and_type(nullptr, {});
+ }
+ GameSingleton* game_singleton = GameSingleton::get_singleton();
+ ERR_FAIL_NULL_V(game_singleton, FAILED);
+ Country const* new_flag_country = game_singleton->get_game_manager().get_country_manager().get_country_by_identifier(
+ godot_to_std_string(new_flag_country_name)
+ );
+ ERR_FAIL_NULL_V_MSG(new_flag_country, FAILED, vformat("Country not found: %s", new_flag_country_name));
+ return set_flag_country_and_type(new_flag_country, new_flag_type);
+}
+
+String GFXMaskedFlagTexture::get_flag_country_name() const {
+ return flag_country != nullptr ? std_view_to_godot_string(flag_country->get_identifier()) : String {};
+}