diff options
Diffstat (limited to 'extension/src/openvic-extension/classes')
10 files changed, 275 insertions, 32 deletions
diff --git a/extension/src/openvic-extension/classes/GFXButtonStateTexture.cpp b/extension/src/openvic-extension/classes/GFXButtonStateTexture.cpp new file mode 100644 index 0000000..e6dff1f --- /dev/null +++ b/extension/src/openvic-extension/classes/GFXButtonStateTexture.cpp @@ -0,0 +1,106 @@ +#include "GFXButtonStateTexture.hpp" + +#include "openvic-extension/utility/ClassBindings.hpp" + +using namespace OpenVic; +using namespace godot; + +void GFXButtonStateTexture::_bind_methods() { + OV_BIND_METHOD(GFXButtonStateTexture::set_button_state, { "new_button_state" }); + OV_BIND_METHOD(GFXButtonStateTexture::get_button_state); + + OV_BIND_SMETHOD(get_generate_state_image_func_name); + + OV_BIND_SMETHOD(button_state_to_theme_name, { "button_state" }); + OV_BIND_METHOD(GFXButtonStateTexture::get_button_state_theme); + + OV_BIND_METHOD(GFXButtonStateTexture::generate_state_image, { "source_image" }); + + BIND_ENUM_CONSTANT(HOVER); + BIND_ENUM_CONSTANT(PRESSED); + BIND_ENUM_CONSTANT(DISABLED); +} + +GFXButtonStateTexture::GFXButtonStateTexture() : button_state { HOVER } {} + +Ref<GFXButtonStateTexture> GFXButtonStateTexture::make_gfx_button_state_texture( + ButtonState button_state, Ref<Image> const& source_image +) { + Ref<GFXButtonStateTexture> button_state_texture; + button_state_texture.instantiate(); + ERR_FAIL_NULL_V(button_state_texture, nullptr); + button_state_texture->set_button_state(button_state); + if (source_image.is_valid()) { + ERR_FAIL_COND_V(button_state_texture->generate_state_image(source_image) != OK, nullptr); + } + return button_state_texture; +} + +void GFXButtonStateTexture::set_button_state(ButtonState new_button_state) { + ERR_FAIL_COND(new_button_state != HOVER && new_button_state != PRESSED && new_button_state != DISABLED); + button_state = new_button_state; +} + +Error GFXButtonStateTexture::generate_state_image(Ref<Image> const& source_image) { + ERR_FAIL_COND_V(source_image.is_null() || source_image->is_empty(), FAILED); + /* Whether we've already set the ImageTexture to an image of the right dimensions and format, + * and so can update it without creating and setting a new image, or not. */ + const bool can_update = state_image.is_valid() && state_image->get_size() == source_image->get_size() + && state_image->get_format() == source_image->get_format(); + if (!can_update) { + state_image = Image::create(source_image->get_width(), source_image->get_height(), false, source_image->get_format()); + ERR_FAIL_NULL_V(state_image, FAILED); + } + + static constexpr auto hover_colour = [](Color const& colour) -> Color { + return { std::min(colour.r + 0.1f, 1.0f), std::min(colour.g + 0.1f, 1.0f), std::min(colour.b + 0.1f, 1.0f), colour.a }; + }; + static constexpr auto pressed_colour = [](Color const& colour) -> Color { + return { std::max(colour.r - 0.1f, 0.0f), std::max(colour.g - 0.1f, 0.0f), std::max(colour.b - 0.1f, 0.0f), colour.a }; + }; + static constexpr auto disabled_colour = [](Color const& colour) -> Color { + const float luma = colour.get_luminance(); + return { luma, luma, luma, colour.a }; + }; + + const auto colour_func = button_state == HOVER ? hover_colour : button_state == PRESSED ? pressed_colour : disabled_colour; + + for (Vector2i point { 0, 0 }; point.y < state_image->get_height(); ++point.y) { + for (point.x = 0; point.x < state_image->get_width(); ++point.x) { + state_image->set_pixelv(point, colour_func(source_image->get_pixelv(point))); + } + } + + if (can_update) { + update(state_image); + } else { + set_image(state_image); + } + return OK; +} + +StringName const& GFXButtonStateTexture::get_generate_state_image_func_name() { + static const StringName generate_state_image_func_name = "generate_state_image"; + return generate_state_image_func_name; +} + +StringName const& GFXButtonStateTexture::button_state_to_theme_name(ButtonState button_state) { + static const StringName theme_name_hover = "hover"; + static const StringName theme_name_pressed = "pressed"; + static const StringName theme_name_disabled = "disabled"; + static const StringName theme_name_error = ""; + switch (button_state) { + case HOVER: + return theme_name_hover; + case PRESSED: + return theme_name_pressed; + case DISABLED: + return theme_name_disabled; + default: + return theme_name_error; + } +} + +StringName const& GFXButtonStateTexture::get_button_state_theme() const { + return button_state_to_theme_name(button_state); +} diff --git a/extension/src/openvic-extension/classes/GFXButtonStateTexture.hpp b/extension/src/openvic-extension/classes/GFXButtonStateTexture.hpp new file mode 100644 index 0000000..32f4087 --- /dev/null +++ b/extension/src/openvic-extension/classes/GFXButtonStateTexture.hpp @@ -0,0 +1,46 @@ +#pragma once + +#include <godot_cpp/classes/image_texture.hpp> + +#include <openvic-simulation/utility/Getters.hpp> + +namespace OpenVic { + class GFXButtonStateTexture : public godot::ImageTexture { + GDCLASS(GFXButtonStateTexture, godot::ImageTexture) + + public: + enum ButtonState { + HOVER, + PRESSED, + DISABLED + }; + + private: + ButtonState PROPERTY(button_state); + godot::Ref<godot::Image> state_image; + + protected: + static void _bind_methods(); + + public: + GFXButtonStateTexture(); + + /* Create a GFXButtonStateTexture using the specified godot::Image. Returns nullptr if generate_state_image fails. */ + static godot::Ref<GFXButtonStateTexture> make_gfx_button_state_texture( + ButtonState button_state, godot::Ref<godot::Image> const& source_image = nullptr + ); + + /* Set the ButtonState to be generated by this class (calling this does not trigger state image generation). */ + void set_button_state(ButtonState new_button_state); + + /* Generate a modified version of source_image and update the underlying godot::ImageTexture to use it. */ + godot::Error generate_state_image(godot::Ref<godot::Image> const& source_image); + + static godot::StringName const& get_generate_state_image_func_name(); + + static godot::StringName const& button_state_to_theme_name(ButtonState button_state); + godot::StringName const& get_button_state_theme() const; + }; +} + +VARIANT_ENUM_CAST(OpenVic::GFXButtonStateTexture::ButtonState); diff --git a/extension/src/openvic-extension/classes/GFXIconTexture.cpp b/extension/src/openvic-extension/classes/GFXIconTexture.cpp index 895bf6b..5d29c07 100644 --- a/extension/src/openvic-extension/classes/GFXIconTexture.cpp +++ b/extension/src/openvic-extension/classes/GFXIconTexture.cpp @@ -15,6 +15,11 @@ using OpenVic::Utilities::godot_to_std_string; using OpenVic::Utilities::std_view_to_godot_string; using OpenVic::Utilities::std_view_to_godot_string_name; +StringName const& GFXIconTexture::_signal_image_updated() { + static const StringName signal_image_updated = "image_updated"; + return signal_image_updated; +} + void GFXIconTexture::_bind_methods() { OV_BIND_METHOD(GFXIconTexture::clear); @@ -26,16 +31,32 @@ void GFXIconTexture::_bind_methods() { OV_BIND_METHOD(GFXIconTexture::get_icon_count); ADD_PROPERTY(PropertyInfo(Variant::INT, "icon_index"), "set_icon_index", "get_icon_index"); + + ADD_SIGNAL( + MethodInfo(_signal_image_updated(), PropertyInfo(Variant::OBJECT, "source_image", PROPERTY_HINT_RESOURCE_TYPE, "Image")) + ); } GFXIconTexture::GFXIconTexture() : gfx_texture_sprite { nullptr }, icon_index { GFX::NO_FRAMES }, icon_count { GFX::NO_FRAMES } {} -Ref<GFXIconTexture> GFXIconTexture::make_gfx_icon_texture(GFX::TextureSprite const* gfx_texture_sprite, GFX::frame_t icon) { +Ref<GFXIconTexture> GFXIconTexture::make_gfx_icon_texture( + GFX::TextureSprite const* gfx_texture_sprite, GFX::frame_t icon, + std::vector<Ref<GFXButtonStateTexture>> const& button_state_textures +) { Ref<GFXIconTexture> icon_texture; icon_texture.instantiate(); ERR_FAIL_NULL_V(icon_texture, nullptr); - icon_texture->set_gfx_texture_sprite(gfx_texture_sprite, icon); + + for (Ref<GFXButtonStateTexture> const& button_state_texture : button_state_textures) { + icon_texture->connect( + _signal_image_updated(), + Callable { *button_state_texture, GFXButtonStateTexture::get_generate_state_image_func_name() }, + CONNECT_PERSIST + ); + } + + ERR_FAIL_COND_V(icon_texture->set_gfx_texture_sprite(gfx_texture_sprite, icon) != OK, nullptr); return icon_texture; } @@ -57,9 +78,15 @@ Error GFXIconTexture::set_gfx_texture_sprite(GFX::TextureSprite const* new_gfx_t ERR_FAIL_NULL_V(asset_manager, FAILED); const StringName texture_file = std_view_to_godot_string_name(new_gfx_texture_sprite->get_texture_file()); + + /* Needed for GFXButtonStateTexture, AssetManager::get_texture will re-use this image from its internal cache. */ + const Ref<Image> image = asset_manager->get_image(texture_file); + ERR_FAIL_NULL_V_MSG(image, FAILED, vformat("Failed to load image: %s", texture_file)); + const Ref<ImageTexture> texture = asset_manager->get_texture(texture_file); ERR_FAIL_NULL_V_MSG(texture, FAILED, vformat("Failed to load texture: %s", texture_file)); + sprite_image = image; gfx_texture_sprite = new_gfx_texture_sprite; set_atlas(texture); icon_index = GFX::NO_FRAMES; @@ -98,6 +125,7 @@ Error GFXIconTexture::set_icon_index(int32_t new_icon_index) { } icon_index = GFX::NO_FRAMES; set_region({ {}, size }); + emit_signal(_signal_image_updated(), sprite_image); return OK; } if (GFX::NO_FRAMES < new_icon_index && new_icon_index <= icon_count) { @@ -111,5 +139,6 @@ Error GFXIconTexture::set_icon_index(int32_t new_icon_index) { } } set_region({ (icon_index - 1) * size.x / icon_count, 0, size.x / icon_count, size.y }); + emit_signal(_signal_image_updated(), sprite_image->get_region(get_region())); return OK; } diff --git a/extension/src/openvic-extension/classes/GFXIconTexture.hpp b/extension/src/openvic-extension/classes/GFXIconTexture.hpp index 176d855..06dac34 100644 --- a/extension/src/openvic-extension/classes/GFXIconTexture.hpp +++ b/extension/src/openvic-extension/classes/GFXIconTexture.hpp @@ -4,6 +4,8 @@ #include <openvic-simulation/interface/GFX.hpp> +#include "openvic-extension/classes/GFXButtonStateTexture.hpp" + namespace OpenVic { class GFXIconTexture : public godot::AtlasTexture { GDCLASS(GFXIconTexture, godot::AtlasTexture) @@ -16,14 +18,22 @@ namespace OpenVic { GFX::frame_t PROPERTY(icon_index); GFX::frame_t PROPERTY(icon_count); + godot::Ref<godot::Image> sprite_image; + + static godot::StringName const& _signal_image_updated(); + protected: static void _bind_methods(); public: GFXIconTexture(); + /* Create a GFXIconTexture using the specified GFX::TextureSprite and icon index. Returns nullptr if + * set_gfx_texture_sprite fails. Connects the provided GFXButtonStateTextures (if any) to the + * GFXIconTexture's image_updated signal. */ static godot::Ref<GFXIconTexture> make_gfx_icon_texture( - GFX::TextureSprite const* gfx_texture_sprite, GFX::frame_t icon = GFX::NO_FRAMES + GFX::TextureSprite const* gfx_texture_sprite, GFX::frame_t icon = GFX::NO_FRAMES, + std::vector<godot::Ref<GFXButtonStateTexture>> const& button_state_textures = {} ); /* Discard the GFX::TextureSprite, atlas texture and icon index. */ diff --git a/extension/src/openvic-extension/classes/GFXMaskedFlagTexture.cpp b/extension/src/openvic-extension/classes/GFXMaskedFlagTexture.cpp index 424be33..0a44e56 100644 --- a/extension/src/openvic-extension/classes/GFXMaskedFlagTexture.cpp +++ b/extension/src/openvic-extension/classes/GFXMaskedFlagTexture.cpp @@ -13,15 +13,22 @@ using OpenVic::Utilities::godot_to_std_string; using OpenVic::Utilities::std_view_to_godot_string; using OpenVic::Utilities::std_view_to_godot_string_name; +StringName const& GFXMaskedFlagTexture::_signal_image_updated() { + static const StringName signal_image_updated = "image_updated"; + return signal_image_updated; +} + 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()) { + /* Whether we've already set the ImageTexture to an image of the right dimensions and format, + * and so can update it without creating and setting a new image, or not. */ + const bool can_update = combined_image.is_valid() && combined_image->get_size() == overlay_image->get_size() + && combined_image->get_format() == overlay_image->get_format(); + if (!can_update) { 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()) { @@ -55,6 +62,7 @@ Error GFXMaskedFlagTexture::_generate_combined_image() { } else { set_image(combined_image); } + emit_signal(_signal_image_updated(), combined_image); return OK; } @@ -68,14 +76,29 @@ void GFXMaskedFlagTexture::_bind_methods() { OV_BIND_METHOD(GFXMaskedFlagTexture::set_flag_country_name, { "new_flag_country_name" }); OV_BIND_METHOD(GFXMaskedFlagTexture::get_flag_country_name); OV_BIND_METHOD(GFXMaskedFlagTexture::get_flag_type); + + ADD_SIGNAL( + MethodInfo(_signal_image_updated(), PropertyInfo(Variant::OBJECT, "source_image", PROPERTY_HINT_RESOURCE_TYPE, "Image")) + ); } 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> GFXMaskedFlagTexture::make_gfx_masked_flag_texture( + GFX::MaskedFlag const* gfx_masked_flag, std::vector<Ref<GFXButtonStateTexture>> const& button_state_textures +) { Ref<GFXMaskedFlagTexture> masked_flag_texture; masked_flag_texture.instantiate(); ERR_FAIL_NULL_V(masked_flag_texture, nullptr); + + for (Ref<GFXButtonStateTexture> const& button_state_texture : button_state_textures) { + masked_flag_texture->connect( + _signal_image_updated(), + Callable { *button_state_texture, GFXButtonStateTexture::get_generate_state_image_func_name() }, + CONNECT_PERSIST + ); + } + ERR_FAIL_COND_V(masked_flag_texture->set_gfx_masked_flag(gfx_masked_flag) != OK, nullptr); return masked_flag_texture; } diff --git a/extension/src/openvic-extension/classes/GFXMaskedFlagTexture.hpp b/extension/src/openvic-extension/classes/GFXMaskedFlagTexture.hpp index f71a1d7..294b842 100644 --- a/extension/src/openvic-extension/classes/GFXMaskedFlagTexture.hpp +++ b/extension/src/openvic-extension/classes/GFXMaskedFlagTexture.hpp @@ -5,6 +5,8 @@ #include <openvic-simulation/country/Country.hpp> #include <openvic-simulation/interface/GFX.hpp> +#include "openvic-extension/classes/GFXButtonStateTexture.hpp" + namespace OpenVic { class GFXMaskedFlagTexture : public godot::ImageTexture { GDCLASS(GFXMaskedFlagTexture, godot::ImageTexture) @@ -15,6 +17,8 @@ namespace OpenVic { godot::Ref<godot::Image> overlay_image, mask_image, flag_image, combined_image; + static godot::StringName const& _signal_image_updated(); + godot::Error _generate_combined_image(); protected: @@ -23,9 +27,12 @@ namespace OpenVic { 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); + /* Create a GFXMaskedFlagTexture using the specified GFX::MaskedFlag. Returns nullptr if gfx_masked_flag fails. + * Connects the provided GFXButtonStateTextures (if any) to the GFXMaskedFlagTexture's image_updated signal. */ + static godot::Ref<GFXMaskedFlagTexture> make_gfx_masked_flag_texture( + GFX::MaskedFlag const* gfx_masked_flag, + std::vector<godot::Ref<GFXButtonStateTexture>> const& button_state_textures = {} + ); /* 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. */ diff --git a/extension/src/openvic-extension/classes/GFXPieChartTexture.cpp b/extension/src/openvic-extension/classes/GFXPieChartTexture.cpp index 63deeda..c9a2a72 100644 --- a/extension/src/openvic-extension/classes/GFXPieChartTexture.cpp +++ b/extension/src/openvic-extension/classes/GFXPieChartTexture.cpp @@ -12,6 +12,19 @@ using OpenVic::Utilities::godot_to_std_string; using OpenVic::Utilities::std_view_to_godot_string; using OpenVic::Utilities::std_view_to_godot_string_name; +StringName const& GFXPieChartTexture::_slice_identifier_key() { + static StringName const slice_identifier_key = "identifier"; + return slice_identifier_key; +} +StringName const& GFXPieChartTexture::_slice_colour_key() { + static StringName const slice_colour_key = "colour"; + return slice_colour_key; +} +StringName const& GFXPieChartTexture::_slice_weight_key() { + static StringName const slice_weight_key = "weight"; + return slice_weight_key; +} + static constexpr float PI = std::numbers::pi_v<float>; Error GFXPieChartTexture::_generate_pie_chart_image() { @@ -21,14 +34,13 @@ Error GFXPieChartTexture::_generate_pie_chart_image() { vformat("Invalid GFX::PieChart size for GFXPieChartTexture - %d", gfx_pie_chart->get_size()) ); const int32_t pie_chart_size = 2 * gfx_pie_chart->get_size(); - bool can_update = true; - if ( - pie_chart_image.is_null() || pie_chart_image->get_width() != pie_chart_size || - pie_chart_image->get_height() != pie_chart_size - ) { + /* Whether we've already set the ImageTexture to an image of the right dimensions, + * and so can update it without creating and setting a new image, or not. */ + const bool can_update = pie_chart_image.is_valid() && pie_chart_image->get_width() == pie_chart_size + && pie_chart_image->get_height() == pie_chart_size; + if (!can_update) { pie_chart_image = Image::create(pie_chart_size, pie_chart_size, false, Image::FORMAT_RGBA8); ERR_FAIL_NULL_V(pie_chart_image, FAILED); - can_update = false; } static const Color background_colour { 0.0f, 0.0f, 0.0f, 0.0f }; @@ -74,17 +86,14 @@ Error GFXPieChartTexture::_generate_pie_chart_image() { } Error GFXPieChartTexture::set_slices_array(TypedArray<Dictionary> const& new_slices) { - static const StringName colour_key = "colour"; - static const StringName weight_key = "weight"; - slices.clear(); total_weight = 0.0f; for (int32_t i = 0; i < new_slices.size(); ++i) { Dictionary const& slice_dict = new_slices[i]; ERR_CONTINUE_MSG( - !slice_dict.has(colour_key) || !slice_dict.has(weight_key), vformat("Invalid slice keys at index %d", i) + !slice_dict.has(_slice_colour_key()) || !slice_dict.has(_slice_weight_key()), vformat("Invalid slice keys at index %d", i) ); - const slice_t slice = std::make_pair(slice_dict[colour_key], slice_dict[weight_key]); + slice_t slice = std::make_pair(slice_dict[_slice_colour_key()], slice_dict[_slice_weight_key()]); ERR_CONTINUE_MSG(slice.second <= 0.0f, vformat("Invalid slice values at index %d", i)); total_weight += slice.second; slices.emplace_back(std::move(slice)); diff --git a/extension/src/openvic-extension/classes/GFXPieChartTexture.hpp b/extension/src/openvic-extension/classes/GFXPieChartTexture.hpp index ad8e751..f8279e4 100644 --- a/extension/src/openvic-extension/classes/GFXPieChartTexture.hpp +++ b/extension/src/openvic-extension/classes/GFXPieChartTexture.hpp @@ -17,6 +17,10 @@ namespace OpenVic { float total_weight; godot::Ref<godot::Image> pie_chart_image; + static godot::StringName const& _slice_identifier_key(); + static godot::StringName const& _slice_colour_key(); + static godot::StringName const& _slice_weight_key(); + godot::Error _generate_pie_chart_image(); protected: @@ -34,34 +38,31 @@ namespace OpenVic { * The resulting Array of Dictionaries can be used as an argument for set_slices_array. */ template<std::derived_from<HasIdentifierAndColour> T> static godot::TypedArray<godot::Dictionary> distribution_to_slices_array(fixed_point_map_t<T const*> const& dist) { + using namespace godot; using entry_t = std::pair<T const*, fixed_point_t>; std::vector<entry_t> sorted_dist; sorted_dist.reserve(dist.size()); for (entry_t const& entry : dist) { ERR_CONTINUE_MSG( - entry.first == nullptr, godot::vformat("Null distribution key with value %f", entry.second.to_float()) + entry.first == nullptr, vformat("Null distribution key with value %f", entry.second.to_float()) ); sorted_dist.push_back(entry); } std::sort(sorted_dist.begin(), sorted_dist.end(), [](entry_t const& lhs, entry_t const& rhs) -> bool { return lhs.second < rhs.second; }); - static const godot::StringName identifier_key = "identifier"; - static const godot::StringName colour_key = "colour"; - static const godot::StringName weight_key = "weight"; - godot::TypedArray<godot::Dictionary> array; + TypedArray<Dictionary> array; for (auto const& [key, val] : sorted_dist) { - godot::Dictionary sub_dict; - sub_dict[identifier_key] = Utilities::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(); + Dictionary sub_dict; + sub_dict[_slice_identifier_key()] = Utilities::std_view_to_godot_string(key->get_identifier()); + sub_dict[_slice_colour_key()] = Utilities::to_godot_color(key->get_colour()); + sub_dict[_slice_weight_key()] = val.to_float(); array.push_back(sub_dict); } return array; } - /* Create a GFXPieChartTexture using the specific GFX::PieChart. - * Returns nullptr if setting gfx_pie_chart fails. */ + /* Create a GFXPieChartTexture using the specified GFX::PieChart. Returns nullptr if gfx_pie_chart fails. */ static godot::Ref<GFXPieChartTexture> make_gfx_pie_chart_texture(GFX::PieChart const* gfx_pie_chart); /* Reset gfx_pie_chart, flag_country and flag_type to nullptr/an empty string, and unreference all images. diff --git a/extension/src/openvic-extension/classes/GUINode.cpp b/extension/src/openvic-extension/classes/GUINode.cpp index 043f65d..89701e0 100644 --- a/extension/src/openvic-extension/classes/GUINode.cpp +++ b/extension/src/openvic-extension/classes/GUINode.cpp @@ -49,6 +49,9 @@ void GUINode::_bind_methods() { } GUINode::GUINode() { + set_anchors_and_offsets_preset(PRESET_FULL_RECT); + set_h_grow_direction(GROW_DIRECTION_BOTH); + set_v_grow_direction(GROW_DIRECTION_BOTH); set_mouse_filter(MOUSE_FILTER_IGNORE); } diff --git a/extension/src/openvic-extension/classes/GUIOverlappingElementsBox.cpp b/extension/src/openvic-extension/classes/GUIOverlappingElementsBox.cpp index ff88781..921f633 100644 --- a/extension/src/openvic-extension/classes/GUIOverlappingElementsBox.cpp +++ b/extension/src/openvic-extension/classes/GUIOverlappingElementsBox.cpp @@ -120,6 +120,15 @@ Error GUIOverlappingElementsBox::set_child_count(int32_t new_count) { name, child_count, new_count ) ); + + static const StringName set_z_index_func_name = "set_z_index"; + static const StringName mouse_entered_signal_name = "mouse_entered"; + static const StringName mouse_exited_signal_name = "mouse_exited"; + + /* Move the child element in front of its neighbours when moused-over. */ + child->connect(mouse_entered_signal_name, Callable { child, set_z_index_func_name }.bind(1), CONNECT_PERSIST); + child->connect(mouse_exited_signal_name, Callable { child, set_z_index_func_name }.bind(0), CONNECT_PERSIST); + add_child(child); child_count++; } while (child_count < new_count); |