-
Notifications
You must be signed in to change notification settings - Fork 27
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Big UI commit - GUINode, MaskedFlag, PieChart, etc
- Loading branch information
Showing
23 changed files
with
1,241 additions
and
319 deletions.
There are no files selected for viewing
Submodule openvic-simulation
updated
82 files
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
183 changes: 183 additions & 0 deletions
183
extension/src/openvic-extension/classes/GFXMaskedFlagTexture.cpp
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 {}; | ||
} |
55 changes: 55 additions & 0 deletions
55
extension/src/openvic-extension/classes/GFXMaskedFlagTexture.hpp
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
#pragma once | ||
|
||
#include <godot_cpp/classes/image_texture.hpp> | ||
|
||
#include <openvic-simulation/country/Country.hpp> | ||
#include <openvic-simulation/interface/GFX.hpp> | ||
|
||
namespace OpenVic { | ||
class GFXMaskedFlagTexture : public godot::ImageTexture { | ||
GDCLASS(GFXMaskedFlagTexture, godot::ImageTexture) | ||
|
||
GFX::MaskedFlag const* PROPERTY(gfx_masked_flag); | ||
Country const* PROPERTY(flag_country); | ||
godot::StringName PROPERTY(flag_type); | ||
|
||
godot::Ref<godot::Image> overlay_image, mask_image, flag_image, combined_image; | ||
|
||
godot::Error _generate_combined_image(); | ||
|
||
protected: | ||
static void _bind_methods(); | ||
|
||
public: | ||
GFXMaskedFlagTexture(); | ||
|
||
/* Create a GFXMaskedFlagTexture using the specific GFX::MaskedFlag. | ||
* Returns nullptr if setting gfx_masked_flag fails. */ | ||
static godot::Ref<GFXMaskedFlagTexture> make_gfx_masked_flag_texture(GFX::MaskedFlag const* gfx_masked_flag); | ||
|
||
/* Reset gfx_masked_flag, flag_country and flag_type to nullptr/an empty string, and unreference all images. | ||
* This does not affect the godot::ImageTexture, which cannot be reset to a null or empty image. */ | ||
void clear(); | ||
|
||
/* Set the GFX::MaskedFlag, load its overlay and mask textures, and regenerate the combined image. */ | ||
godot::Error set_gfx_masked_flag(GFX::MaskedFlag const* new_gfx_masked_flag); | ||
|
||
/* Search for a GFX::MaskedFlag with the specfied name and, if successful, set it using set_gfx_masked_flag. */ | ||
godot::Error set_gfx_masked_flag_name(godot::String const& gfx_masked_flag_name); | ||
|
||
/* Return the name of the GFX::MaskedFlag, or an empty String if it's null */ | ||
godot::String get_gfx_masked_flag_name() const; | ||
|
||
/* Set flag_country and flag_type and update the combined image to use that flag, or no flag if it doesn't exist. */ | ||
godot::Error set_flag_country_and_type(Country const* new_flag_country, godot::StringName const& new_flag_type); | ||
|
||
/* Look up the country with the specified identifier, then call set_flag_country_and_type with the country and | ||
* specified flag_type as arguments. */ | ||
godot::Error set_flag_country_name_and_type( | ||
godot::String const& new_flag_country_name, godot::StringName const& new_flag_type | ||
); | ||
|
||
/* Return the name of the selected flag's country, or an empty String if it's null */ | ||
godot::String get_flag_country_name() const; | ||
}; | ||
} |
Oops, something went wrong.