aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Hop311 <Hop3114@gmail.com>2024-08-30 23:30:12 +0200
committer GitHub <noreply@github.com>2024-08-30 23:30:12 +0200
commit2e0bc5b556b9c6df46a8cdd48d3f109e0ac76b63 (patch)
tree2c521b99fe6cd0a7fd5d6a29e55645b3415792b3
parentf54e454afb90f8868e7c62529e2a388fdaadf20b (diff)
parentbdc2ba527bc02e7cdf977f6040f2ca85aa4f9a94 (diff)
Merge pull request #253 from OpenVicProject/tooltip
Tooltips
-rw-r--r--extension/src/openvic-extension/classes/GFXPieChartTexture.cpp97
-rw-r--r--extension/src/openvic-extension/classes/GFXPieChartTexture.hpp13
-rw-r--r--extension/src/openvic-extension/classes/GUIButton.cpp109
-rw-r--r--extension/src/openvic-extension/classes/GUIButton.hpp28
-rw-r--r--extension/src/openvic-extension/classes/GUIHasTooltip.hpp121
-rw-r--r--extension/src/openvic-extension/classes/GUIIcon.cpp82
-rw-r--r--extension/src/openvic-extension/classes/GUIIcon.hpp34
-rw-r--r--extension/src/openvic-extension/classes/GUIIconButton.cpp86
-rw-r--r--extension/src/openvic-extension/classes/GUIIconButton.hpp36
-rw-r--r--extension/src/openvic-extension/classes/GUILabel.cpp57
-rw-r--r--extension/src/openvic-extension/classes/GUILabel.hpp7
-rw-r--r--extension/src/openvic-extension/classes/GUIListBox.cpp2
-rw-r--r--extension/src/openvic-extension/classes/GUIMaskedFlag.cpp88
-rw-r--r--extension/src/openvic-extension/classes/GUIMaskedFlag.hpp34
-rw-r--r--extension/src/openvic-extension/classes/GUIMaskedFlagButton.cpp88
-rw-r--r--extension/src/openvic-extension/classes/GUIMaskedFlagButton.hpp34
-rw-r--r--extension/src/openvic-extension/classes/GUINode.cpp60
-rw-r--r--extension/src/openvic-extension/classes/GUINode.hpp39
-rw-r--r--extension/src/openvic-extension/classes/GUIPieChart.cpp142
-rw-r--r--extension/src/openvic-extension/classes/GUIPieChart.hpp40
-rw-r--r--extension/src/openvic-extension/classes/GUIProgressBar.cpp114
-rw-r--r--extension/src/openvic-extension/classes/GUIProgressBar.hpp24
-rw-r--r--extension/src/openvic-extension/classes/GUIScrollbar.cpp15
-rw-r--r--extension/src/openvic-extension/classes/GUIScrollbar.hpp4
-rw-r--r--extension/src/openvic-extension/classes/GUITextureRect.cpp16
-rw-r--r--extension/src/openvic-extension/classes/GUITextureRect.hpp21
-rw-r--r--extension/src/openvic-extension/register_types.cpp20
-rw-r--r--extension/src/openvic-extension/singletons/AssetManager.cpp23
-rw-r--r--extension/src/openvic-extension/singletons/AssetManager.hpp6
-rw-r--r--extension/src/openvic-extension/singletons/MenuSingleton.cpp35
-rw-r--r--extension/src/openvic-extension/singletons/MenuSingleton.hpp14
-rw-r--r--extension/src/openvic-extension/utility/UITools.cpp416
-rw-r--r--game/src/Game/GameSession/GameSession.tscn8
-rw-r--r--game/src/Game/GameSession/NationManagementScreen/BudgetMenu.gd51
-rw-r--r--game/src/Game/GameSession/NationManagementScreen/DiplomacyMenu.gd2
-rw-r--r--game/src/Game/GameSession/NationManagementScreen/MilitaryMenu.gd2
-rw-r--r--game/src/Game/GameSession/NationManagementScreen/PoliticsMenu.gd2
-rw-r--r--game/src/Game/GameSession/NationManagementScreen/PopulationMenu.gd281
-rw-r--r--game/src/Game/GameSession/NationManagementScreen/ProductionMenu.gd2
-rw-r--r--game/src/Game/GameSession/NationManagementScreen/TechnologyMenu.gd2
-rw-r--r--game/src/Game/GameSession/NationManagementScreen/TradeMenu.gd2
-rw-r--r--game/src/Game/GameSession/ProvinceOverviewPanel.gd110
-rw-r--r--game/src/Game/GameSession/SearchPanel.gd8
-rw-r--r--game/src/Game/GameSession/Tooltip.gd23
-rw-r--r--game/src/Game/GameSession/Topbar.gd304
45 files changed, 1952 insertions, 750 deletions
diff --git a/extension/src/openvic-extension/classes/GFXPieChartTexture.cpp b/extension/src/openvic-extension/classes/GFXPieChartTexture.cpp
index 417566d..5d955a3 100644
--- a/extension/src/openvic-extension/classes/GFXPieChartTexture.cpp
+++ b/extension/src/openvic-extension/classes/GFXPieChartTexture.cpp
@@ -7,6 +7,7 @@
using namespace godot;
using namespace OpenVic;
+using namespace OpenVic::Utilities::literals;
StringName const& GFXPieChartTexture::_slice_identifier_key() {
static const StringName slice_identifier_key = "identifier";
@@ -21,7 +22,35 @@ StringName const& GFXPieChartTexture::_slice_weight_key() {
return slice_weight_key;
}
-static constexpr float TWO_PI = 2.0f * std::numbers::pi_v<float>;
+GFXPieChartTexture::slice_t const* GFXPieChartTexture::get_slice(Vector2 const& position) const {
+ if (slices.empty() || position.length_squared() > 1.0_real) {
+ return nullptr;
+ }
+
+ static constexpr float TWO_PI = 2.0f * std::numbers::pi_v<float>;
+
+ /* Calculate the anti-clockwise angle between the point and the centre of the image.
+ * The y coordinate is negated as the image coordinate system's y increases downwards. */
+ float theta = atan2(-position.y, position.x);
+ if (theta < 0.0f) {
+ theta += TWO_PI;
+ }
+
+ /* Rescale angle so that total_weight is a full rotation. */
+ theta *= total_weight / TWO_PI;
+
+ /* Find the slice theta lies in. */
+ for (slice_t const& slice : slices) {
+ theta -= slice.weight;
+
+ if (theta <= 0.0f) {
+ return &slice;
+ }
+ }
+
+ /* Default to the first slice in case theta never reaches 0 due to floating point inaccuracy. */
+ return &slices.front();
+}
Error GFXPieChartTexture::_generate_pie_chart_image() {
ERR_FAIL_NULL_V(gfx_pie_chart, FAILED);
@@ -30,60 +59,37 @@ 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();
+ const int32_t pie_chart_radius = gfx_pie_chart->get_size();
+ const int32_t pie_chart_diameter = 2 * pie_chart_radius;
/* 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;
+ const bool can_update = pie_chart_image.is_valid() && pie_chart_image->get_width() == pie_chart_diameter
+ && pie_chart_image->get_height() == pie_chart_diameter;
if (!can_update) {
- pie_chart_image = Image::create(pie_chart_size, pie_chart_size, false, Image::FORMAT_RGBA8);
+ pie_chart_image = Image::create(pie_chart_diameter, pie_chart_diameter, false, Image::FORMAT_RGBA8);
ERR_FAIL_NULL_V(pie_chart_image, FAILED);
}
static const Color background_colour { 0.0f, 0.0f, 0.0f, 0.0f };
if (!slices.empty()) {
- const float pie_chart_radius = gfx_pie_chart->get_size();
-
- const Vector2 centre_translation = Vector2 { 0.5f, 0.5f } - static_cast<Vector2>(pie_chart_image->get_size()) * 0.5f;
-
- for (Vector2i point { 0, 0 }; point.y < pie_chart_image->get_height(); ++point.y) {
-
- for (point.x = 0; point.x < pie_chart_image->get_width(); ++point.x) {
-
- const Vector2 offset = centre_translation + point;
-
- if (offset.length() <= pie_chart_radius) {
-
- /* Calculate the anti-clockwise angle between the point and the centre of the image.
- * The y coordinate is negated as the image coordinate system's y increases downwards. */
- float theta = atan2(-offset.y, offset.x);
- if (theta < 0.0f) {
- theta += TWO_PI;
- }
-
- /* Rescale angle so that total_weight is a full rotation. */
- theta *= total_weight / TWO_PI;
+ for (Vector2i point { 0, 0 }; point.y < pie_chart_diameter; ++point.y) {
- /* Default to the first colour in case theta never reaches 0 due to floating point inaccuracy. */
- Color colour = slices.front().first;
+ for (point.x = 0; point.x < pie_chart_diameter; ++point.x) {
- /* Find the slice theta lies in. */
- for (slice_t const& slice : slices) {
- theta -= slice.second;
+ Vector2 offset = point;
+ // Move to the centre of the pixel
+ offset += Vector2 { 0.5_real, 0.5_real };
+ // Normalise to [0, 2]
+ offset /= pie_chart_radius;
+ // Translate to [-1, 1]
+ offset -= Vector2 { 1.0_real, 1.0_real };
- if (theta <= 0.0f) {
- colour = slice.first;
- break;
- }
- }
+ slice_t const* slice = get_slice(offset);
- pie_chart_image->set_pixelv(point, colour);
- } else {
- pie_chart_image->set_pixelv(point, background_colour);
- }
+ pie_chart_image->set_pixelv(point, slice != nullptr ? slice->colour : background_colour);
}
}
} else {
@@ -107,12 +113,15 @@ Error GFXPieChartTexture::set_slices_array(godot_pie_chart_data_t const& new_sli
for (int32_t i = 0; i < new_slices.size(); ++i) {
Dictionary const& slice_dict = new_slices[i];
ERR_CONTINUE_MSG(
- !slice_dict.has(_slice_colour_key()) || !slice_dict.has(_slice_weight_key()),
+ !slice_dict.has(_slice_identifier_key()) || !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[_slice_colour_key()], slice_dict[_slice_weight_key()]);
- if (slice.second > 0.0f) {
- total_weight += slice.second;
+ const slice_t slice {
+ slice_dict[_slice_identifier_key()], slice_dict[_slice_colour_key()], slice_dict[_slice_weight_key()]
+ };
+ if (slice.weight > 0.0f) {
+ total_weight += slice.weight;
slices.push_back(slice);
}
}
diff --git a/extension/src/openvic-extension/classes/GFXPieChartTexture.hpp b/extension/src/openvic-extension/classes/GFXPieChartTexture.hpp
index 9642f4e..3610efb 100644
--- a/extension/src/openvic-extension/classes/GFXPieChartTexture.hpp
+++ b/extension/src/openvic-extension/classes/GFXPieChartTexture.hpp
@@ -10,11 +10,17 @@ namespace OpenVic {
class GFXPieChartTexture : public godot::ImageTexture {
GDCLASS(GFXPieChartTexture, godot::ImageTexture)
- using slice_t = std::pair<godot::Color, float>;
+ public:
+ struct slice_t {
+ godot::String name;
+ godot::Color colour;
+ float weight;
+ };
+ private:
GFX::PieChart const* PROPERTY(gfx_pie_chart);
std::vector<slice_t> slices;
- float total_weight;
+ float PROPERTY(total_weight);
godot::Ref<godot::Image> pie_chart_image;
static godot::StringName const& _slice_identifier_key();
@@ -29,6 +35,9 @@ namespace OpenVic {
public:
GFXPieChartTexture();
+ // Position must be centred and normalised so that coords are in [-1, 1].
+ slice_t const* get_slice(godot::Vector2 const& position) const;
+
using godot_pie_chart_data_t = godot::TypedArray<godot::Dictionary>;
/* Set slices given an Array of Dictionaries, each with the following key-value entries:
diff --git a/extension/src/openvic-extension/classes/GUIButton.cpp b/extension/src/openvic-extension/classes/GUIButton.cpp
new file mode 100644
index 0000000..e35d67a
--- /dev/null
+++ b/extension/src/openvic-extension/classes/GUIButton.cpp
@@ -0,0 +1,109 @@
+#include "GUIButton.hpp"
+
+#include <array>
+
+#include <godot_cpp/variant/utility_functions.hpp>
+
+#include "openvic-extension/singletons/AssetManager.hpp"
+#include "openvic-extension/utility/Utilities.hpp"
+
+using namespace godot;
+using namespace OpenVic;
+
+GUI_TOOLTIP_IMPLEMENTATIONS(GUIButton)
+
+void GUIButton::_bind_methods() {
+ GUI_TOOLTIP_BIND_METHODS(GUIButton)
+}
+
+void GUIButton::_notification(int what) {
+ _tooltip_notification(what);
+}
+
+GUIButton::GUIButton() : tooltip_active { false } {}
+
+Error GUIButton::set_gfx_button_state_having_texture(Ref<GFXButtonStateHavingTexture> const& texture) {
+ ERR_FAIL_NULL_V(texture, FAILED);
+
+ Error err = OK;
+
+ set_custom_minimum_size(texture->get_size());
+
+ {
+ Ref<StyleBoxTexture> stylebox = AssetManager::make_stylebox_texture(texture);
+
+ if (stylebox.is_valid()) {
+ static const StringName normal_theme = "normal";
+
+ add_theme_stylebox_override(normal_theme, stylebox);
+ } else {
+ UtilityFunctions::push_error("Failed to make StyleBoxTexture for GUIButton ", get_name());
+
+ err = FAILED;
+ }
+ }
+
+ using enum GFXButtonStateTexture::ButtonState;
+
+ for (GFXButtonStateTexture::ButtonState button_state : { HOVER, PRESSED, DISABLED }) {
+ Ref<GFXButtonStateTexture> button_state_texture = texture->get_button_state_texture(button_state);
+
+ if (button_state_texture.is_valid()) {
+ Ref<StyleBoxTexture> stylebox = AssetManager::make_stylebox_texture(button_state_texture);
+
+ if (stylebox.is_valid()) {
+ add_theme_stylebox_override(button_state_texture->get_button_state_name(), stylebox);
+ } else {
+ UtilityFunctions::push_error(
+ "Failed to make ", GFXButtonStateTexture::button_state_to_name(button_state),
+ " StyleBoxTexture for GUIButton ", get_name()
+ );
+
+ err = FAILED;
+ }
+ } else {
+ UtilityFunctions::push_error(
+ "Failed to make ", GFXButtonStateTexture::button_state_to_name(button_state),
+ " GFXButtonStateTexture for GUIButton ", get_name()
+ );
+
+ err = FAILED;
+ }
+ }
+
+ return err;
+}
+
+Error GUIButton::set_gfx_font(GFX::Font const* gfx_font) {
+ ERR_FAIL_NULL_V(gfx_font, FAILED);
+
+ AssetManager* asset_manager = AssetManager::get_singleton();
+ ERR_FAIL_NULL_V(asset_manager, FAILED);
+
+ Error err = OK;
+
+ const StringName font_file = Utilities::std_to_godot_string(gfx_font->get_fontname());
+ const Ref<Font> font = asset_manager->get_font(font_file);
+
+ if (font.is_valid()) {
+ static const StringName font_theme = "font";
+
+ add_theme_font_override(font_theme, font);
+ } else {
+ UtilityFunctions::push_error("Failed to load font \"", font_file, "\" for GUIButton ", get_name());
+
+ err = FAILED;
+ }
+
+ static const std::array<StringName, 5> button_font_themes {
+ "font_color", "font_hover_color", "font_hover_pressed_color", "font_pressed_color", "font_disabled_color"
+ };
+
+ const Color colour = Utilities::to_godot_color(gfx_font->get_colour());
+
+ for (StringName const& theme_name : button_font_themes) {
+ add_theme_color_override(theme_name, colour);
+ }
+
+ return err;
+}
diff --git a/extension/src/openvic-extension/classes/GUIButton.hpp b/extension/src/openvic-extension/classes/GUIButton.hpp
new file mode 100644
index 0000000..3873a4d
--- /dev/null
+++ b/extension/src/openvic-extension/classes/GUIButton.hpp
@@ -0,0 +1,28 @@
+#pragma once
+
+#include <godot_cpp/classes/button.hpp>
+
+#include <openvic-simulation/interface/GFXSprite.hpp>
+
+#include "openvic-extension/classes/GFXButtonStateTexture.hpp"
+#include "openvic-extension/classes/GUIHasTooltip.hpp"
+
+namespace OpenVic {
+ class GUIButton : public godot::Button {
+ GDCLASS(GUIButton, godot::Button)
+
+ GUI_TOOLTIP_DEFINITIONS
+
+ protected:
+ static void _bind_methods();
+
+ void _notification(int what);
+
+ godot::Error set_gfx_button_state_having_texture(godot::Ref<GFXButtonStateHavingTexture> const& texture);
+
+ public:
+ GUIButton();
+
+ godot::Error set_gfx_font(GFX::Font const* gfx_font);
+ };
+}
diff --git a/extension/src/openvic-extension/classes/GUIHasTooltip.hpp b/extension/src/openvic-extension/classes/GUIHasTooltip.hpp
new file mode 100644
index 0000000..22413ec
--- /dev/null
+++ b/extension/src/openvic-extension/classes/GUIHasTooltip.hpp
@@ -0,0 +1,121 @@
+#pragma once
+
+#include <godot_cpp/classes/control.hpp>
+#include <godot_cpp/variant/string.hpp>
+#include <godot_cpp/variant/utility_functions.hpp>
+#include <godot_cpp/variant/vector2.hpp>
+
+#include <openvic-simulation/utility/Getters.hpp>
+
+#include "openvic-extension/singletons/MenuSingleton.hpp"
+#include "openvic-extension/utility/ClassBindings.hpp"
+#include "openvic-extension/utility/Utilities.hpp"
+
+/* To add tooltip functionality to a class:
+ * - the class must be derived from Control.
+ * - add GUI_TOOLTIP_DEFINITIONS to the class definition, bearing in mind that it leaves visibility as private.
+ * - add GUI_TOOLTIP_IMPLEMENTATIONS(CLASS) to the class' source file.
+ * - add GUI_TOOLTIP_BIND_METHODS(CLASS) to the class' _bind_methods implementation.
+ * - call _tooltip_notification from the class' _notification method.
+ * - initialise tooltip_active to false in the class' constructor. */
+
+#define GUI_TOOLTIP_DEFINITIONS \
+ public: \
+ void set_tooltip_string_and_substitution_dict( \
+ godot::String const& new_tooltip_string, godot::Dictionary const& new_tooltip_substitution_dict \
+ ); \
+ void set_tooltip_string(godot::String const& new_tooltip_string); \
+ void set_tooltip_substitution_dict(godot::Dictionary const& new_tooltip_substitution_dict); \
+ void clear_tooltip(); \
+ private: \
+ godot::String PROPERTY(tooltip_string); \
+ godot::Dictionary PROPERTY(tooltip_substitution_dict); \
+ bool PROPERTY_CUSTOM_PREFIX(tooltip_active, is); \
+ void _tooltip_notification(int what); \
+ void _set_tooltip_active(bool new_tooltip_active); \
+ void _set_tooltip_visibility(bool visible);
+
+#define GUI_TOOLTIP_IMPLEMENTATIONS(CLASS) \
+ void CLASS::set_tooltip_string_and_substitution_dict( \
+ String const& new_tooltip_string, Dictionary const& new_tooltip_substitution_dict \
+ ) { \
+ if (get_mouse_filter() == MOUSE_FILTER_IGNORE) { \
+ UtilityFunctions::push_error("Tooltips won't work for \"", get_name(), "\" as it has MOUSE_FILTER_IGNORE"); \
+ } \
+ if (tooltip_string != new_tooltip_string || tooltip_substitution_dict != new_tooltip_substitution_dict) { \
+ tooltip_string = new_tooltip_string; \
+ tooltip_substitution_dict = new_tooltip_substitution_dict; \
+ if (tooltip_active) { \
+ _set_tooltip_visibility(!tooltip_string.is_empty()); \
+ } \
+ } \
+ } \
+ void CLASS::set_tooltip_string(String const& new_tooltip_string) { \
+ if (get_mouse_filter() == MOUSE_FILTER_IGNORE) { \
+ UtilityFunctions::push_error("Tooltips won't work for \"", get_name(), "\" as it has MOUSE_FILTER_IGNORE"); \
+ } \
+ if (tooltip_string != new_tooltip_string) { \
+ tooltip_string = new_tooltip_string; \
+ if (tooltip_active) { \
+ _set_tooltip_visibility(!tooltip_string.is_empty()); \
+ } \
+ } \
+ } \
+ void CLASS::set_tooltip_substitution_dict(Dictionary const& new_tooltip_substitution_dict) { \
+ if (get_mouse_filter() == MOUSE_FILTER_IGNORE) { \
+ UtilityFunctions::push_error("Tooltips won't work for \"", get_name(), "\" as it has MOUSE_FILTER_IGNORE"); \
+ } \
+ if (tooltip_substitution_dict != new_tooltip_substitution_dict) { \
+ tooltip_substitution_dict = new_tooltip_substitution_dict; \
+ if (tooltip_active) { \
+ _set_tooltip_visibility(!tooltip_string.is_empty()); \
+ } \
+ } \
+ } \
+ void CLASS::clear_tooltip() { \
+ set_tooltip_string_and_substitution_dict({}, {}); \
+ } \
+ void CLASS::_tooltip_notification(int what) { \
+ if (what == NOTIFICATION_MOUSE_ENTER_SELF) { \
+ _set_tooltip_active(true); \
+ } else if (what == NOTIFICATION_MOUSE_EXIT_SELF) { \
+ _set_tooltip_active(false); \
+ } \
+ } \
+ void CLASS::_set_tooltip_active(bool new_tooltip_active) { \
+ if (tooltip_active != new_tooltip_active) { \
+ tooltip_active = new_tooltip_active; \
+ if (!tooltip_string.is_empty()) { \
+ _set_tooltip_visibility(tooltip_active); \
+ } \
+ } \
+ } \
+ void CLASS::_set_tooltip_visibility(bool visible) { \
+ MenuSingleton* menu_singleton = MenuSingleton::get_singleton(); \
+ ERR_FAIL_NULL(menu_singleton); \
+ if (visible) { \
+ menu_singleton->show_control_tooltip(tooltip_string, tooltip_substitution_dict, this); \
+ } else { \
+ menu_singleton->hide_tooltip(); \
+ } \
+ }
+
+#define GUI_TOOLTIP_BIND_METHODS(CLASS) \
+ OV_BIND_METHOD(CLASS::get_tooltip_string); \
+ OV_BIND_METHOD(CLASS::set_tooltip_string, { "new_tooltip_string" }); \
+ OV_BIND_METHOD(CLASS::get_tooltip_substitution_dict); \
+ OV_BIND_METHOD(CLASS::set_tooltip_substitution_dict, { "new_tooltip_substitution_dict" }); \
+ OV_BIND_METHOD( \
+ CLASS::set_tooltip_string_and_substitution_dict, { "new_tooltip_string", "new_tooltip_substitution_dict" } \
+ ); \
+ OV_BIND_METHOD(CLASS::clear_tooltip); \
+ OV_BIND_METHOD(CLASS::is_tooltip_active); \
+ ADD_PROPERTY( \
+ PropertyInfo(Variant::STRING, "tooltip_string", PROPERTY_HINT_MULTILINE_TEXT), \
+ "set_tooltip_string", "get_tooltip_string" \
+ ); \
+ ADD_PROPERTY( \
+ PropertyInfo(Variant::DICTIONARY, "tooltip_substitution_dict"), \
+ "set_tooltip_substitution_dict", "get_tooltip_substitution_dict" \
+ ); \
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "tooltip_active"), "", "is_tooltip_active");
diff --git a/extension/src/openvic-extension/classes/GUIIcon.cpp b/extension/src/openvic-extension/classes/GUIIcon.cpp
new file mode 100644
index 0000000..68e7ec4
--- /dev/null
+++ b/extension/src/openvic-extension/classes/GUIIcon.cpp
@@ -0,0 +1,82 @@
+#include "GUIIcon.hpp"
+
+#include "openvic-extension/utility/ClassBindings.hpp"
+
+using namespace godot;
+using namespace OpenVic;
+
+void GUIIcon::_bind_methods() {
+ OV_BIND_METHOD(GUIIcon::get_gfx_sprite_texture);
+
+ OV_BIND_METHOD(GUIIcon::set_gfx_texture_sprite_name, { "gfx_texture_sprite_name", "icon" }, DEFVAL(GFX::NO_FRAMES));
+ OV_BIND_METHOD(GUIIcon::get_gfx_texture_sprite_name);
+
+ OV_BIND_METHOD(GUIIcon::set_icon_index, { "icon_index" });
+ OV_BIND_METHOD(GUIIcon::get_icon_index);
+
+ OV_BIND_METHOD(GUIIcon::set_toggled_icon, { "toggled" });
+}
+
+Error GUIIcon::set_gfx_texture_sprite(GFX::TextureSprite const* gfx_texture_sprite, GFX::frame_t icon) {
+ const bool needs_setting = gfx_sprite_texture.is_null();
+
+ if (needs_setting) {
+ gfx_sprite_texture.instantiate();
+ ERR_FAIL_NULL_V(gfx_sprite_texture, FAILED);
+ }
+
+ const Error err = gfx_sprite_texture->set_gfx_texture_sprite(gfx_texture_sprite, icon);
+
+ if (needs_setting) {
+ set_texture(gfx_sprite_texture);
+ }
+
+ return err;
+}
+
+Ref<GFXSpriteTexture> GUIIcon::get_gfx_sprite_texture() const {
+ ERR_FAIL_NULL_V(gfx_sprite_texture, nullptr);
+
+ return gfx_sprite_texture;
+}
+
+Error GUIIcon::set_gfx_texture_sprite_name(String const& gfx_texture_sprite_name, GFX::frame_t icon) {
+ const bool needs_setting = gfx_sprite_texture.is_null();
+
+ if (needs_setting) {
+ gfx_sprite_texture.instantiate();
+ ERR_FAIL_NULL_V(gfx_sprite_texture, FAILED);
+ }
+
+ const Error err = gfx_sprite_texture->set_gfx_texture_sprite_name(gfx_texture_sprite_name, icon);
+
+ if (needs_setting) {
+ set_texture(gfx_sprite_texture);
+ }
+
+ return err;
+}
+
+String GUIIcon::get_gfx_texture_sprite_name() const {
+ ERR_FAIL_NULL_V(gfx_sprite_texture, {});
+
+ return gfx_sprite_texture->get_gfx_texture_sprite_name();
+}
+
+Error GUIIcon::set_icon_index(GFX::frame_t icon_index) const {
+ ERR_FAIL_NULL_V(gfx_sprite_texture, FAILED);
+
+ return gfx_sprite_texture->set_icon_index(icon_index);
+}
+
+GFX::frame_t GUIIcon::get_icon_index() const {
+ ERR_FAIL_NULL_V(gfx_sprite_texture, FAILED);
+
+ return gfx_sprite_texture->get_icon_index();
+}
+
+Error GUIIcon::set_toggled_icon(bool toggled) const {
+ ERR_FAIL_NULL_V(gfx_sprite_texture, FAILED);
+
+ return gfx_sprite_texture->set_toggled_icon(toggled);
+}
diff --git a/extension/src/openvic-extension/classes/GUIIcon.hpp b/extension/src/openvic-extension/classes/GUIIcon.hpp
new file mode 100644
index 0000000..e8e3014
--- /dev/null
+++ b/extension/src/openvic-extension/classes/GUIIcon.hpp
@@ -0,0 +1,34 @@
+#pragma once
+
+#include "openvic-extension/classes/GFXSpriteTexture.hpp"
+#include "openvic-extension/classes/GUITextureRect.hpp"
+
+namespace OpenVic {
+ class GUIIcon : public GUITextureRect {
+ GDCLASS(GUIIcon, GUITextureRect)
+
+ godot::Ref<GFXSpriteTexture> gfx_sprite_texture;
+
+ protected:
+ static void _bind_methods();
+
+ public:
+ godot::Error set_gfx_texture_sprite(
+ GFX::TextureSprite const* gfx_texture_sprite, GFX::frame_t icon = GFX::NO_FRAMES
+ );
+
+ godot::Ref<GFXSpriteTexture> get_gfx_sprite_texture() const;
+
+ godot::Error set_gfx_texture_sprite_name(
+ godot::String const& gfx_texture_sprite_name, GFX::frame_t icon = GFX::NO_FRAMES
+ );
+
+ godot::String get_gfx_texture_sprite_name() const;
+
+ godot::Error set_icon_index(GFX::frame_t icon_index) const;
+
+ GFX::frame_t get_icon_index() const;
+
+ godot::Error set_toggled_icon(bool toggled) const;
+ };
+}
diff --git a/extension/src/openvic-extension/classes/GUIIconButton.cpp b/extension/src/openvic-extension/classes/GUIIconButton.cpp
new file mode 100644
index 0000000..1bba947
--- /dev/null
+++ b/extension/src/openvic-extension/classes/GUIIconButton.cpp
@@ -0,0 +1,86 @@
+#include "GUIIconButton.hpp"
+
+#include "openvic-extension/utility/ClassBindings.hpp"
+
+using namespace godot;
+using namespace OpenVic;
+
+void GUIIconButton::_bind_methods() {
+ OV_BIND_METHOD(GUIIconButton::get_gfx_sprite_texture);
+
+ OV_BIND_METHOD(GUIIconButton::set_gfx_texture_sprite_name, { "gfx_texture_sprite_name", "icon" }, DEFVAL(GFX::NO_FRAMES));
+ OV_BIND_METHOD(GUIIconButton::get_gfx_texture_sprite_name);
+
+ OV_BIND_METHOD(GUIIconButton::set_icon_index, { "icon_index" });
+ OV_BIND_METHOD(GUIIconButton::get_icon_index);
+
+ OV_BIND_METHOD(GUIIconButton::set_toggled_icon, { "toggled" });
+}
+
+Error GUIIconButton::set_gfx_texture_sprite(GFX::TextureSprite const* gfx_texture_sprite, GFX::frame_t icon) {
+ const bool needs_setting = gfx_sprite_texture.is_null();
+
+ if (needs_setting) {
+ gfx_sprite_texture.instantiate();
+ ERR_FAIL_NULL_V(gfx_sprite_texture, FAILED);
+ }
+
+ Error err = gfx_sprite_texture->set_gfx_texture_sprite(gfx_texture_sprite, icon);
+
+ if (needs_setting && set_gfx_button_state_having_texture(gfx_sprite_texture) != OK) {
+ err = FAILED;
+ }
+
+ return err;
+}
+
+Ref<GFXSpriteTexture> GUIIconButton::get_gfx_sprite_texture() const {
+ ERR_FAIL_NULL_V(gfx_sprite_texture, nullptr);
+
+ return gfx_sprite_texture;
+}
+
+Error GUIIconButton::set_gfx_texture_sprite_name(String const& gfx_texture_sprite_name, GFX::frame_t icon) {
+ const bool needs_setting = gfx_sprite_texture.is_null();
+
+ if (needs_setting) {
+ gfx_sprite_texture.instantiate();
+ ERR_FAIL_NULL_V(gfx_sprite_texture, FAILED);
+ }
+
+ Error err = gfx_sprite_texture->set_gfx_texture_sprite_name(gfx_texture_sprite_name, icon);
+
+ if (needs_setting && set_gfx_button_state_having_texture(gfx_sprite_texture) != OK) {
+ err = FAILED;
+ }
+
+ return err;
+}
+
+String GUIIconButton::get_gfx_texture_sprite_name() const {
+ ERR_FAIL_NULL_V(gfx_sprite_texture, {});
+
+ return gfx_sprite_texture->get_gfx_texture_sprite_name();
+}
+
+Error GUIIconButton::set_icon_index(GFX::frame_t icon_index) const {
+ ERR_FAIL_NULL_V(gfx_sprite_texture, FAILED);
+
+ return gfx_sprite_texture->set_icon_index(icon_index);
+}
+
+GFX::frame_t GUIIconButton::get_icon_index() const {
+ ERR_FAIL_NULL_V(gfx_sprite_texture, FAILED);
+
+ return gfx_sprite_texture->get_icon_index();
+}
+
+Error GUIIconButton::set_toggled_icon(bool toggled) const {
+ ERR_FAIL_NULL_V(gfx_sprite_texture, FAILED);
+
+ return gfx_sprite_texture->set_toggled_icon(toggled);
+}
+
+void GUIIconButton::_toggled(bool toggled_on) {
+ set_toggled_icon(toggled_on);
+}
diff --git a/extension/src/openvic-extension/classes/GUIIconButton.hpp b/extension/src/openvic-extension/classes/GUIIconButton.hpp
new file mode 100644
index 0000000..10fc179
--- /dev/null
+++ b/extension/src/openvic-extension/classes/GUIIconButton.hpp
@@ -0,0 +1,36 @@
+#pragma once
+
+#include "openvic-extension/classes/GFXSpriteTexture.hpp"
+#include "openvic-extension/classes/GUIButton.hpp"
+
+namespace OpenVic {
+ class GUIIconButton : public GUIButton {
+ GDCLASS(GUIIconButton, GUIButton)
+
+ godot::Ref<GFXSpriteTexture> gfx_sprite_texture;
+
+ protected:
+ static void _bind_methods();
+
+ public:
+ godot::Error set_gfx_texture_sprite(
+ GFX::TextureSprite const* gfx_texture_sprite, GFX::frame_t icon = GFX::NO_FRAMES
+ );
+
+ godot::Ref<GFXSpriteTexture> get_gfx_sprite_texture() const;
+
+ godot::Error set_gfx_texture_sprite_name(
+ godot::String const& gfx_texture_sprite_name, GFX::frame_t icon = GFX::NO_FRAMES
+ );
+
+ godot::String get_gfx_texture_sprite_name() const;
+
+ godot::Error set_icon_index(GFX::frame_t icon_index) const;
+
+ GFX::frame_t get_icon_index() const;
+
+ godot::Error set_toggled_icon(bool toggled) const;
+
+ void _toggled(bool toggled_on) override;
+ };
+}
diff --git a/extension/src/openvic-extension/classes/GUILabel.cpp b/extension/src/openvic-extension/classes/GUILabel.cpp
index 9fd6b60..732dec2 100644
--- a/extension/src/openvic-extension/classes/GUILabel.cpp
+++ b/extension/src/openvic-extension/classes/GUILabel.cpp
@@ -14,7 +14,30 @@ using namespace OpenVic::Utilities::literals;
static constexpr int32_t DEFAULT_FONT_SIZE = 16;
+GUI_TOOLTIP_IMPLEMENTATIONS(GUILabel)
+
+String const& GUILabel::get_colour_marker() {
+ static const String COLOUR_MARKER = String::chr(0xA7); // §
+ return COLOUR_MARKER;
+}
+
+String const& GUILabel::get_currency_marker() {
+ static const String CURRENCY_MARKER = String::chr(0xA4); // ¤
+ return CURRENCY_MARKER;
+}
+
+String const& GUILabel::get_substitution_marker() {
+ static const String SUBSTITUTION_MARKER = String::chr(0x24); // $
+ return SUBSTITUTION_MARKER;
+}
+
void GUILabel::_bind_methods() {
+ GUI_TOOLTIP_BIND_METHODS(GUILabel)
+
+ OV_BIND_SMETHOD(get_colour_marker);
+ OV_BIND_SMETHOD(get_currency_marker);
+ OV_BIND_SMETHOD(get_substitution_marker);
+
OV_BIND_METHOD(GUILabel::clear);
OV_BIND_METHOD(GUILabel::get_gui_text_name);
@@ -80,6 +103,8 @@ void GUILabel::_bind_methods() {
}
void GUILabel::_notification(int what) {
+ _tooltip_notification(what);
+
switch (what) {
case NOTIFICATION_RESIZED:
case NOTIFICATION_TRANSLATION_CHANGED: {
@@ -146,7 +171,8 @@ void GUILabel::_notification(int what) {
}
GUILabel::GUILabel()
- : gui_text { nullptr },
+ : tooltip_active { false },
+ gui_text { nullptr },
text {},
substitution_dict {},
horizontal_alignment { HORIZONTAL_ALIGNMENT_LEFT },
@@ -454,29 +480,30 @@ void GUILabel::_update_lines() {
}
String GUILabel::generate_substituted_text(String const& base_text) const {
- static const String SUBSTITUTION_MARKER = String::chr(0x24); // $
-
String result;
int64_t start_pos = 0;
int64_t marker_start_pos;
- while ((marker_start_pos = base_text.find(SUBSTITUTION_MARKER, start_pos)) != -1) {
+ while ((marker_start_pos = base_text.find(get_substitution_marker(), start_pos)) != -1) {
result += base_text.substr(start_pos, marker_start_pos - start_pos);
- int64_t marker_end_pos = base_text.find(SUBSTITUTION_MARKER, marker_start_pos + SUBSTITUTION_MARKER.length());
+ int64_t marker_end_pos = base_text.find(
+ get_substitution_marker(), marker_start_pos + get_substitution_marker().length()
+ );
if (marker_end_pos == -1) {
marker_end_pos = base_text.length();
}
String key = base_text.substr(
- marker_start_pos + SUBSTITUTION_MARKER.length(), marker_end_pos - marker_start_pos - SUBSTITUTION_MARKER.length()
+ marker_start_pos + get_substitution_marker().length(),
+ marker_end_pos - marker_start_pos - get_substitution_marker().length()
);
String value = substitution_dict.get(key, String {});
// Use the un-substituted key if no value is found or the value is empty
result += value.is_empty() ? key : is_auto_translating() ? tr(value) : value;
- start_pos = marker_end_pos + SUBSTITUTION_MARKER.length();
+ start_pos = marker_end_pos + get_substitution_marker().length();
}
if (start_pos < base_text.length()) {
@@ -489,25 +516,23 @@ String GUILabel::generate_substituted_text(String const& base_text) const {
std::pair<String, GUILabel::colour_instructions_t> GUILabel::generate_display_text_and_colour_instructions(
String const& substituted_text
) const {
- static const String COLOUR_MARKER = String::chr(0xA7); // §
-
String result;
colour_instructions_t colour_instructions;
int64_t start_pos = 0;
int64_t marker_pos;
- while ((marker_pos = substituted_text.find(COLOUR_MARKER, start_pos)) != -1) {
+ while ((marker_pos = substituted_text.find(get_colour_marker(), start_pos)) != -1) {
result += substituted_text.substr(start_pos, marker_pos - start_pos);
- if (marker_pos + COLOUR_MARKER.length() < substituted_text.length()) {
- const char32_t colour_code = substituted_text[marker_pos + COLOUR_MARKER.length()];
+ if (marker_pos + get_colour_marker().length() < substituted_text.length()) {
+ const char32_t colour_code = substituted_text[marker_pos + get_colour_marker().length()];
// Check that the colour code can be safely cast to a char
if (colour_code >> sizeof(char) * CHAR_BIT == 0) {
colour_instructions.emplace_back(result.length(), static_cast<char>(colour_code));
}
- start_pos = marker_pos + COLOUR_MARKER.length() + 1;
+ start_pos = marker_pos + get_colour_marker().length() + 1;
} else {
return { std::move(result), std::move(colour_instructions) };
}
@@ -588,8 +613,6 @@ void GUILabel::separate_lines(
void GUILabel::separate_currency_segments(
String const& string, Color const& colour, line_t& line
) const {
- static const String CURRENCY_MARKER = String::chr(0xA4); // ¤
-
const auto push_string_segment = [this, &string, &colour, &line](int64_t start, int64_t end) -> void {
String substring = string.substr(start, end - start);
const real_t width = get_string_width(substring);
@@ -602,7 +625,7 @@ void GUILabel::separate_currency_segments(
const real_t currency_width = currency_texture.is_valid() ? currency_texture->get_width() : 0.0_real;
- while ((marker_pos = string.find(CURRENCY_MARKER, start_pos)) != -1) {
+ while ((marker_pos = string.find(get_currency_marker(), start_pos)) != -1) {
if (start_pos < marker_pos) {
push_string_segment(start_pos, marker_pos);
}
@@ -610,7 +633,7 @@ void GUILabel::separate_currency_segments(
line.segments.push_back(currency_segment_t {});
line.width += currency_width;
- start_pos = marker_pos + CURRENCY_MARKER.length();
+ start_pos = marker_pos + get_currency_marker().length();
}
if (start_pos < string.length()) {
diff --git a/extension/src/openvic-extension/classes/GUILabel.hpp b/extension/src/openvic-extension/classes/GUILabel.hpp
index e0982b2..102ad94 100644
--- a/extension/src/openvic-extension/classes/GUILabel.hpp
+++ b/extension/src/openvic-extension/classes/GUILabel.hpp
@@ -8,11 +8,14 @@
#include <openvic-simulation/interface/GUI.hpp>
#include "openvic-extension/classes/GFXSpriteTexture.hpp"
+#include "openvic-extension/classes/GUIHasTooltip.hpp"
namespace OpenVic {
class GUILabel : public godot::Control {
GDCLASS(GUILabel, godot::Control)
+ GUI_TOOLTIP_DEFINITIONS
+
using colour_instructions_t = std::vector<std::pair<int64_t, char>>;
GUI::Text const* PROPERTY(gui_text);
@@ -55,6 +58,10 @@ namespace OpenVic {
void _notification(int what);
public:
+ static godot::String const& get_colour_marker();
+ static godot::String const& get_currency_marker();
+ static godot::String const& get_substitution_marker();
+
GUILabel();
/* Reset gui_text to nullptr and reset current text. */
diff --git a/extension/src/openvic-extension/classes/GUIListBox.cpp b/extension/src/openvic-extension/classes/GUIListBox.cpp
index 9165b14..958807f 100644
--- a/extension/src/openvic-extension/classes/GUIListBox.cpp
+++ b/extension/src/openvic-extension/classes/GUIListBox.cpp
@@ -146,7 +146,7 @@ Vector2 GUIListBox::_get_minimum_size() const {
}
}
-void GUIListBox::_gui_input(godot::Ref<godot::InputEvent> const& event) {
+void GUIListBox::_gui_input(Ref<InputEvent> const& event) {
ERR_FAIL_NULL(event);
if (scrollbar == nullptr) {
diff --git a/extension/src/openvic-extension/classes/GUIMaskedFlag.cpp b/extension/src/openvic-extension/classes/GUIMaskedFlag.cpp
new file mode 100644
index 0000000..968cebb
--- /dev/null
+++ b/extension/src/openvic-extension/classes/GUIMaskedFlag.cpp
@@ -0,0 +1,88 @@
+#include "GUIMaskedFlag.hpp"
+
+#include "openvic-extension/utility/ClassBindings.hpp"
+
+using namespace godot;
+using namespace OpenVic;
+
+void GUIMaskedFlag::_bind_methods() {
+ OV_BIND_METHOD(GUIMaskedFlag::get_gfx_masked_flag_texture);
+
+ OV_BIND_METHOD(GUIMaskedFlag::set_gfx_masked_flag_name, { "gfx_masked_flag_name" });
+ OV_BIND_METHOD(GUIMaskedFlag::get_gfx_masked_flag_name);
+
+ OV_BIND_METHOD(GUIMaskedFlag::set_flag_country_name_and_type, { "flag_country_name", "flag_type" });
+ OV_BIND_METHOD(GUIMaskedFlag::set_flag_country_name, { "flag_country_name" });
+ OV_BIND_METHOD(GUIMaskedFlag::get_flag_country_name);
+ OV_BIND_METHOD(GUIMaskedFlag::get_flag_type);
+}
+
+Error GUIMaskedFlag::set_gfx_masked_flag(GFX::MaskedFlag const* gfx_masked_flag) {
+ const bool needs_setting = gfx_masked_flag_texture.is_null();
+
+ if (needs_setting) {
+ gfx_masked_flag_texture.instantiate();
+ ERR_FAIL_NULL_V(gfx_masked_flag_texture, FAILED);
+ }
+
+ const Error err = gfx_masked_flag_texture->set_gfx_masked_flag(gfx_masked_flag);
+
+ if (needs_setting) {
+ set_texture(gfx_masked_flag_texture);
+ }
+
+ return err;
+}
+
+Ref<GFXMaskedFlagTexture> GUIMaskedFlag::get_gfx_masked_flag_texture() const {
+ ERR_FAIL_NULL_V(gfx_masked_flag_texture, nullptr);
+
+ return gfx_masked_flag_texture;
+}
+
+Error GUIMaskedFlag::set_gfx_masked_flag_name(String const& gfx_masked_flag_name) {
+ const bool needs_setting = gfx_masked_flag_texture.is_null();
+
+ if (needs_setting) {
+ gfx_masked_flag_texture.instantiate();
+ ERR_FAIL_NULL_V(gfx_masked_flag_texture, FAILED);
+ }
+
+ const Error err = gfx_masked_flag_texture->set_gfx_masked_flag_name(gfx_masked_flag_name);
+
+ if (needs_setting) {
+ set_texture(gfx_masked_flag_texture);
+ }
+
+ return err;
+}
+
+String GUIMaskedFlag::get_gfx_masked_flag_name() const {
+ ERR_FAIL_NULL_V(gfx_masked_flag_texture, {});
+
+ return gfx_masked_flag_texture->get_gfx_masked_flag_name();
+}
+
+Error GUIMaskedFlag::set_flag_country_name_and_type(String const& flag_country_name, StringName const& flag_type) const {
+ ERR_FAIL_NULL_V(gfx_masked_flag_texture, FAILED);
+
+ return gfx_masked_flag_texture->set_flag_country_name_and_type(flag_country_name, flag_type);
+}
+
+Error GUIMaskedFlag::set_flag_country_name(String const& flag_country_name) const {
+ ERR_FAIL_NULL_V(gfx_masked_flag_texture, FAILED);
+
+ return gfx_masked_flag_texture->set_flag_country_name(flag_country_name);
+}
+
+String GUIMaskedFlag::get_flag_country_name() const {
+ ERR_FAIL_NULL_V(gfx_masked_flag_texture, {});
+
+ return gfx_masked_flag_texture->get_flag_country_name();
+}
+
+String GUIMaskedFlag::get_flag_type() const {
+ ERR_FAIL_NULL_V(gfx_masked_flag_texture, {});
+
+ return gfx_masked_flag_texture->get_flag_type();
+}
diff --git a/extension/src/openvic-extension/classes/GUIMaskedFlag.hpp b/extension/src/openvic-extension/classes/GUIMaskedFlag.hpp
new file mode 100644
index 0000000..4bdc6c1
--- /dev/null
+++ b/extension/src/openvic-extension/classes/GUIMaskedFlag.hpp
@@ -0,0 +1,34 @@
+#pragma once
+
+#include "openvic-extension/classes/GFXMaskedFlagTexture.hpp"
+#include "openvic-extension/classes/GUITextureRect.hpp"
+
+namespace OpenVic {
+ class GUIMaskedFlag : public GUITextureRect {
+ GDCLASS(GUIMaskedFlag, GUITextureRect)
+
+ godot::Ref<GFXMaskedFlagTexture> gfx_masked_flag_texture;
+
+ protected:
+ static void _bind_methods();
+
+ public:
+ godot::Error set_gfx_masked_flag(GFX::MaskedFlag const* gfx_masked_flag);
+
+ godot::Ref<GFXMaskedFlagTexture> get_gfx_masked_flag_texture() const;
+
+ godot::Error set_gfx_masked_flag_name(godot::String const& gfx_masked_flag_name);
+
+ godot::String get_gfx_masked_flag_name() const;
+
+ godot::Error set_flag_country_name_and_type(
+ godot::String const& flag_country_name, godot::StringName const& flag_type
+ ) const;
+
+ godot::Error set_flag_country_name(godot::String const& flag_country_name) const;
+
+ godot::String get_flag_country_name() const;
+
+ godot::String get_flag_type() const;
+ };
+}
diff --git a/extension/src/openvic-extension/classes/GUIMaskedFlagButton.cpp b/extension/src/openvic-extension/classes/GUIMaskedFlagButton.cpp
new file mode 100644
index 0000000..8c3c1f8
--- /dev/null
+++ b/extension/src/openvic-extension/classes/GUIMaskedFlagButton.cpp
@@ -0,0 +1,88 @@
+#include "GUIMaskedFlagButton.hpp"
+
+#include "openvic-extension/utility/ClassBindings.hpp"
+
+using namespace godot;
+using namespace OpenVic;
+
+void GUIMaskedFlagButton::_bind_methods() {
+ OV_BIND_METHOD(GUIMaskedFlagButton::get_gfx_masked_flag_texture);
+
+ OV_BIND_METHOD(GUIMaskedFlagButton::set_gfx_masked_flag_name, { "gfx_masked_flag_name" });
+ OV_BIND_METHOD(GUIMaskedFlagButton::get_gfx_masked_flag_name);
+
+ OV_BIND_METHOD(GUIMaskedFlagButton::set_flag_country_name_and_type, { "flag_country_name", "flag_type" });
+ OV_BIND_METHOD(GUIMaskedFlagButton::set_flag_country_name, { "flag_country_name" });
+ OV_BIND_METHOD(GUIMaskedFlagButton::get_flag_country_name);
+ OV_BIND_METHOD(GUIMaskedFlagButton::get_flag_type);
+}
+
+Error GUIMaskedFlagButton::set_gfx_masked_flag(GFX::MaskedFlag const* gfx_masked_flag) {
+ const bool needs_setting = gfx_masked_flag_texture.is_null();
+
+ if (needs_setting) {
+ gfx_masked_flag_texture.instantiate();
+ ERR_FAIL_NULL_V(gfx_masked_flag_texture, FAILED);
+ }
+
+ Error err = gfx_masked_flag_texture->set_gfx_masked_flag(gfx_masked_flag);
+
+ if (needs_setting && set_gfx_button_state_having_texture(gfx_masked_flag_texture) != OK) {
+ err = FAILED;
+ }
+
+ return err;
+}
+
+Ref<GFXMaskedFlagTexture> GUIMaskedFlagButton::get_gfx_masked_flag_texture() const {
+ ERR_FAIL_NULL_V(gfx_masked_flag_texture, nullptr);
+
+ return gfx_masked_flag_texture;
+}
+
+Error GUIMaskedFlagButton::set_gfx_masked_flag_name(String const& gfx_masked_flag_name) {
+ const bool needs_setting = gfx_masked_flag_texture.is_null();
+
+ if (needs_setting) {
+ gfx_masked_flag_texture.instantiate();
+ ERR_FAIL_NULL_V(gfx_masked_flag_texture, FAILED);
+ }
+
+ Error err = gfx_masked_flag_texture->set_gfx_masked_flag_name(gfx_masked_flag_name);
+
+ if (needs_setting && set_gfx_button_state_having_texture(gfx_masked_flag_texture) != OK) {
+ err = FAILED;
+ }
+
+ return err;
+}
+
+String GUIMaskedFlagButton::get_gfx_masked_flag_name() const {
+ ERR_FAIL_NULL_V(gfx_masked_flag_texture, {});
+
+ return gfx_masked_flag_texture->get_gfx_masked_flag_name();
+}
+
+Error GUIMaskedFlagButton::set_flag_country_name_and_type(String const& flag_country_name, StringName const& flag_type) const {
+ ERR_FAIL_NULL_V(gfx_masked_flag_texture, FAILED);
+
+ return gfx_masked_flag_texture->set_flag_country_name_and_type(flag_country_name, flag_type);
+}
+
+Error GUIMaskedFlagButton::set_flag_country_name(String const& flag_country_name) const {
+ ERR_FAIL_NULL_V(gfx_masked_flag_texture, FAILED);
+
+ return gfx_masked_flag_texture->set_flag_country_name(flag_country_name);
+}
+
+String GUIMaskedFlagButton::get_flag_country_name() const {
+ ERR_FAIL_NULL_V(gfx_masked_flag_texture, {});
+
+ return gfx_masked_flag_texture->get_flag_country_name();
+}
+
+String GUIMaskedFlagButton::get_flag_type() const {
+ ERR_FAIL_NULL_V(gfx_masked_flag_texture, {});
+
+ return gfx_masked_flag_texture->get_flag_type();
+}
diff --git a/extension/src/openvic-extension/classes/GUIMaskedFlagButton.hpp b/extension/src/openvic-extension/classes/GUIMaskedFlagButton.hpp
new file mode 100644
index 0000000..131c93d
--- /dev/null
+++ b/extension/src/openvic-extension/classes/GUIMaskedFlagButton.hpp
@@ -0,0 +1,34 @@
+#pragma once
+
+#include "openvic-extension/classes/GFXMaskedFlagTexture.hpp"
+#include "openvic-extension/classes/GUIButton.hpp"
+
+namespace OpenVic {
+ class GUIMaskedFlagButton : public GUIButton {
+ GDCLASS(GUIMaskedFlagButton, GUIButton)
+
+ godot::Ref<GFXMaskedFlagTexture> gfx_masked_flag_texture;
+
+ protected:
+ static void _bind_methods();
+
+ public:
+ godot::Error set_gfx_masked_flag(GFX::MaskedFlag const* gfx_masked_flag);
+
+ godot::Ref<GFXMaskedFlagTexture> get_gfx_masked_flag_texture() const;
+
+ godot::Error set_gfx_masked_flag_name(godot::String const& gfx_masked_flag_name);
+
+ godot::String get_gfx_masked_flag_name() const;
+
+ godot::Error set_flag_country_name_and_type(
+ godot::String const& flag_country_name, godot::StringName const& flag_type
+ ) const;
+
+ godot::Error set_flag_country_name(godot::String const& flag_country_name) const;
+
+ godot::String get_flag_country_name() const;
+
+ godot::String get_flag_type() const;
+ };
+}
diff --git a/extension/src/openvic-extension/classes/GUINode.cpp b/extension/src/openvic-extension/classes/GUINode.cpp
index 25ef821..59bad92 100644
--- a/extension/src/openvic-extension/classes/GUINode.cpp
+++ b/extension/src/openvic-extension/classes/GUINode.cpp
@@ -3,7 +3,6 @@
#include <limits>
#include <godot_cpp/classes/bit_map.hpp>
-#include <godot_cpp/classes/button.hpp>
#include <godot_cpp/classes/canvas_item.hpp>
#include <godot_cpp/classes/check_box.hpp>
#include <godot_cpp/classes/control.hpp>
@@ -17,7 +16,6 @@
#include <godot_cpp/classes/style_box_texture.hpp>
#include <godot_cpp/classes/texture2d.hpp>
#include <godot_cpp/classes/texture_progress_bar.hpp>
-#include <godot_cpp/classes/texture_rect.hpp>
#include <godot_cpp/core/defs.hpp>
#include <godot_cpp/core/error_macros.hpp>
#include <godot_cpp/core/object.hpp>
@@ -39,21 +37,19 @@ using namespace godot;
using namespace OpenVic;
#define APPLY_TO_CHILD_TYPES(F) \
- F(Button, button) \
+ F(GUIIconButton, gui_icon_button) \
+ F(GUIMaskedFlagButton, gui_masked_flag_button) \
F(GUILabel, gui_label) \
F(Panel, panel) \
- F(TextureProgressBar, progress_bar) \
- F(TextureRect, texture_rect) \
+ F(GUIProgressBar, gui_progress_bar) \
+ F(GUIIcon, gui_icon) \
+ F(GUIMaskedFlag, gui_masked_flag) \
+ F(GUIPieChart, gui_pie_chart) \
F(GUIOverlappingElementsBox, gui_overlapping_elements_box) \
F(GUIScrollbar, gui_scrollbar) \
F(GUIListBox, gui_listbox) \
F(LineEdit, line_edit)
-#define APPLY_TO_TEXTURE_TYPES(F) \
- F(GFXSpriteTexture, gfx_sprite_texture) \
- F(GFXMaskedFlagTexture, gfx_masked_flag_texture) \
- F(GFXPieChartTexture, gfx_pie_chart_texture)
-
void GUINode::_bind_methods() {
OV_BIND_SMETHOD(generate_gui_element, { "gui_scene", "gui_element", "name" }, DEFVAL(String {}));
OV_BIND_METHOD(GUINode::add_gui_element, { "gui_scene", "gui_element", "name" }, DEFVAL(String {}));
@@ -74,13 +70,11 @@ void GUINode::_bind_methods() {
APPLY_TO_CHILD_TYPES(GET_BINDINGS)
+#undef GET_BINDINGS
+
OV_BIND_SMETHOD(get_texture_from_node, { "node" });
OV_BIND_METHOD(GUINode::get_texture_from_nodepath, { "path" });
- APPLY_TO_TEXTURE_TYPES(GET_BINDINGS)
-
-#undef GET_BINDINGS
-
OV_BIND_METHOD(GUINode::hide_node, { "path" });
OV_BIND_METHOD(GUINode::hide_nodes, { "paths" });
@@ -151,33 +145,37 @@ APPLY_TO_CHILD_TYPES(CHILD_GET_FUNCTIONS)
#undef CHILD_GET_FUNCTIONS
+#undef APPLY_TO_CHILD_TYPES
+
Ref<Texture2D> GUINode::get_texture_from_node(Node* node) {
ERR_FAIL_NULL_V(node, nullptr);
if (TextureRect const* texture_rect = Object::cast_to<TextureRect>(node); texture_rect != nullptr) {
const Ref<Texture2D> texture = texture_rect->get_texture();
ERR_FAIL_NULL_V_MSG(texture, nullptr, vformat("Failed to get Texture2D from TextureRect %s", node->get_name()));
return texture;
- } else if (Button const* button = Object::cast_to<Button>(node); button != nullptr) {
+ } else if (GUIButton const* button = Object::cast_to<GUIButton>(node); button != nullptr) {
static const StringName theme_name_normal = "normal";
const Ref<StyleBox> stylebox = button->get_theme_stylebox(theme_name_normal);
ERR_FAIL_NULL_V_MSG(
- stylebox, nullptr, vformat("Failed to get StyleBox %s from Button %s", theme_name_normal, node->get_name())
+ stylebox, nullptr, vformat("Failed to get StyleBox %s from GUIButton %s", theme_name_normal, node->get_name())
);
const Ref<StyleBoxTexture> stylebox_texture = stylebox;
ERR_FAIL_NULL_V_MSG(
stylebox_texture, nullptr, vformat(
- "Failed to cast StyleBox %s from Button %s to type StyleBoxTexture", theme_name_normal, node->get_name()
+ "Failed to cast StyleBox %s from GUIButton %s to type StyleBoxTexture", theme_name_normal, node->get_name()
)
);
const Ref<Texture2D> result = stylebox_texture->get_texture();
ERR_FAIL_NULL_V_MSG(
result, nullptr,
- vformat("Failed to get Texture2D from StyleBoxTexture %s from Button %s", theme_name_normal, node->get_name())
+ vformat("Failed to get Texture2D from StyleBoxTexture %s from GUIButton %s", theme_name_normal, node->get_name())
);
return result;
}
ERR_FAIL_V_MSG(
- nullptr, vformat("Failed to cast node %s from type %s to TextureRect or Button", node->get_name(), node->get_class())
+ nullptr, vformat(
+ "Failed to cast node %s from type %s to TextureRect or GUIButton", node->get_name(), node->get_class()
+ )
);
}
@@ -185,30 +183,6 @@ Ref<Texture2D> GUINode::get_texture_from_nodepath(NodePath const& path) const {
return get_texture_from_node(get_node_internal(path));
}
-template<std::derived_from<Texture2D> T>
-static Ref<T> _cast_texture(Ref<Texture2D> const& texture) {
- ERR_FAIL_NULL_V(texture, nullptr);
- const Ref<T> result = texture;
- ERR_FAIL_NULL_V_MSG(
- result, nullptr, vformat("Failed to cast Texture2D from type %s to %s", texture->get_class(), T::get_class_static())
- );
- return result;
-}
-
-#define TEXTURE_GET_FUNCTIONS(type, name) \
- Ref<type> GUINode::get_##name##_from_node(Node* node) { \
- return _cast_texture<type>(get_texture_from_node(node)); \
- } \
- Ref<type> GUINode::get_##name##_from_nodepath(NodePath const& path) const { \
- return _cast_texture<type>(get_texture_from_nodepath(path)); \
- }
-
-APPLY_TO_TEXTURE_TYPES(TEXTURE_GET_FUNCTIONS)
-
-#undef TEXTURE_GET_FUNCTIONS
-
-#undef APPLY_TO_CHILD_TYPES
-
Error GUINode::hide_node(NodePath const& path) const {
CanvasItem* node = _cast_node<CanvasItem>(get_node_internal(path));
ERR_FAIL_NULL_V(node, FAILED);
diff --git a/extension/src/openvic-extension/classes/GUINode.hpp b/extension/src/openvic-extension/classes/GUINode.hpp
index 73ca92b..453263a 100644
--- a/extension/src/openvic-extension/classes/GUINode.hpp
+++ b/extension/src/openvic-extension/classes/GUINode.hpp
@@ -1,7 +1,6 @@
#pragma once
#include <godot_cpp/classes/bit_map.hpp>
-#include <godot_cpp/classes/button.hpp>
#include <godot_cpp/classes/control.hpp>
#include <godot_cpp/classes/image.hpp>
#include <godot_cpp/classes/input_event.hpp>
@@ -10,20 +9,21 @@
#include <godot_cpp/classes/panel.hpp>
#include <godot_cpp/classes/ref.hpp>
#include <godot_cpp/classes/texture2d.hpp>
-#include <godot_cpp/classes/texture_progress_bar.hpp>
-#include <godot_cpp/classes/texture_rect.hpp>
#include <godot_cpp/templates/vector.hpp>
#include <godot_cpp/variant/node_path.hpp>
#include <godot_cpp/variant/rect2.hpp>
#include <godot_cpp/variant/string.hpp>
#include <godot_cpp/variant/vector2.hpp>
-#include "openvic-extension/classes/GFXMaskedFlagTexture.hpp"
-#include "openvic-extension/classes/GFXPieChartTexture.hpp"
-#include "openvic-extension/classes/GFXSpriteTexture.hpp"
+#include "openvic-extension/classes/GUIIcon.hpp"
+#include "openvic-extension/classes/GUIIconButton.hpp"
#include "openvic-extension/classes/GUILabel.hpp"
#include "openvic-extension/classes/GUIListBox.hpp"
+#include "openvic-extension/classes/GUIMaskedFlag.hpp"
+#include "openvic-extension/classes/GUIMaskedFlagButton.hpp"
#include "openvic-extension/classes/GUIOverlappingElementsBox.hpp"
+#include "openvic-extension/classes/GUIPieChart.hpp"
+#include "openvic-extension/classes/GUIProgressBar.hpp"
#include "openvic-extension/classes/GUIScrollbar.hpp"
namespace OpenVic {
@@ -51,36 +51,35 @@ namespace OpenVic {
static godot::Vector2 get_gui_position(godot::String const& gui_scene, godot::String const& gui_position);
- static godot::Button* get_button_from_node(godot::Node* node);
+ static GUIIconButton* get_gui_icon_button_from_node(godot::Node* node);
+ static GUIMaskedFlagButton* get_gui_masked_flag_button_from_node(godot::Node* node);
static GUILabel* get_gui_label_from_node(godot::Node* node);
static godot::Panel* get_panel_from_node(godot::Node* node);
- static godot::TextureProgressBar* get_progress_bar_from_node(godot::Node* node);
- static godot::TextureRect* get_texture_rect_from_node(godot::Node* node);
+ static GUIProgressBar* get_gui_progress_bar_from_node(godot::Node* node);
+ static GUIIcon* get_gui_icon_from_node(godot::Node* node);
+ static GUIMaskedFlag* get_gui_masked_flag_from_node(godot::Node* node);
+ static GUIPieChart* get_gui_pie_chart_from_node(godot::Node* node);
static GUIOverlappingElementsBox* get_gui_overlapping_elements_box_from_node(godot::Node* node);
static GUIScrollbar* get_gui_scrollbar_from_node(godot::Node* node);
static GUIListBox* get_gui_listbox_from_node(godot::Node* node);
static godot::LineEdit* get_line_edit_from_node(godot::Node* node);
- godot::Button* get_button_from_nodepath(godot::NodePath const& path) const;
+ GUIIconButton* get_gui_icon_button_from_nodepath(godot::NodePath const& path) const;
+ GUIMaskedFlagButton* get_gui_masked_flag_button_from_nodepath(godot::NodePath const& path) const;
GUILabel* get_gui_label_from_nodepath(godot::NodePath const& path) const;
godot::Panel* get_panel_from_nodepath(godot::NodePath const& path) const;
- godot::TextureProgressBar* get_progress_bar_from_nodepath(godot::NodePath const& path) const;
- godot::TextureRect* get_texture_rect_from_nodepath(godot::NodePath const& path) const;
+ GUIProgressBar* get_gui_progress_bar_from_nodepath(godot::NodePath const& path) const;
+ GUIIcon* get_gui_icon_from_nodepath(godot::NodePath const& path) const;
+ GUIMaskedFlag* get_gui_masked_flag_from_nodepath(godot::NodePath const& path) const;
+ GUIPieChart* get_gui_pie_chart_from_nodepath(godot::NodePath const& path) const;
GUIOverlappingElementsBox* get_gui_overlapping_elements_box_from_nodepath(godot::NodePath const& path) const;
GUIScrollbar* get_gui_scrollbar_from_nodepath(godot::NodePath const& path) const;
GUIListBox* get_gui_listbox_from_nodepath(godot::NodePath const& path) const;
godot::LineEdit* get_line_edit_from_nodepath(godot::NodePath const& path) const;
- /* Helper functions to get textures from TextureRects and Buttons. */
+ /* Helper functions to get textures from TextureRects and GUIButtons. */
static godot::Ref<godot::Texture2D> get_texture_from_node(godot::Node* node);
- static godot::Ref<GFXSpriteTexture> get_gfx_sprite_texture_from_node(godot::Node* node);
- static godot::Ref<GFXMaskedFlagTexture> get_gfx_masked_flag_texture_from_node(godot::Node* node);
- static godot::Ref<GFXPieChartTexture> get_gfx_pie_chart_texture_from_node(godot::Node* node);
-
godot::Ref<godot::Texture2D> get_texture_from_nodepath(godot::NodePath const& path) const;
- godot::Ref<GFXSpriteTexture> get_gfx_sprite_texture_from_nodepath(godot::NodePath const& path) const;
- godot::Ref<GFXMaskedFlagTexture> get_gfx_masked_flag_texture_from_nodepath(godot::NodePath const& path) const;
- godot::Ref<GFXPieChartTexture> get_gfx_pie_chart_texture_from_nodepath(godot::NodePath const& path) const;
godot::Error hide_node(godot::NodePath const& path) const;
godot::Error hide_nodes(godot::TypedArray<godot::NodePath> const& paths) const;
diff --git a/extension/src/openvic-extension/classes/GUIPieChart.cpp b/extension/src/openvic-extension/classes/GUIPieChart.cpp
new file mode 100644
index 0000000..0688dd3
--- /dev/null
+++ b/extension/src/openvic-extension/classes/GUIPieChart.cpp
@@ -0,0 +1,142 @@
+#include "GUIPieChart.hpp"
+
+#include <godot_cpp/classes/input_event_mouse_motion.hpp>
+
+#include "openvic-extension/classes/GUILabel.hpp"
+#include "openvic-extension/singletons/MenuSingleton.hpp"
+#include "openvic-extension/utility/ClassBindings.hpp"
+
+using namespace godot;
+using namespace OpenVic;
+using namespace OpenVic::Utilities::literals;
+
+void GUIPieChart::_update_tooltip() {
+ MenuSingleton* menu_singleton = MenuSingleton::get_singleton();
+ ERR_FAIL_NULL(menu_singleton);
+
+ if (gfx_pie_chart_texture.is_valid()) {
+ GFXPieChartTexture::slice_t const* slice = gfx_pie_chart_texture->get_slice(tooltip_position);
+
+ if (slice != nullptr) {
+ static const String tooltip_identifier_key = "ID";
+ static const String tooltip_percent_key = "PC";
+ // "§Y$ID$§!: $PC$%"
+ static const String tooltip_string =
+ GUILabel::get_colour_marker() + String { "Y" } + GUILabel::get_substitution_marker() + tooltip_identifier_key
+ + GUILabel::get_substitution_marker() + GUILabel::get_colour_marker() + "!: "
+ + GUILabel::get_substitution_marker() + tooltip_percent_key + GUILabel::get_substitution_marker() + "%";
+
+ Dictionary substitution_dict;
+ substitution_dict[tooltip_identifier_key] = slice->name;
+
+ float percent = slice->weight * 100.0f;
+ if (gfx_pie_chart_texture->get_total_weight() > 0.0f) {
+ percent /= gfx_pie_chart_texture->get_total_weight();
+ }
+ substitution_dict[tooltip_percent_key] = Utilities::float_to_string_dp(percent, 2);
+
+ menu_singleton->show_control_tooltip(tooltip_string, substitution_dict, this);
+
+ tooltip_active = true;
+ return;
+ }
+ }
+
+ menu_singleton->hide_tooltip();
+ tooltip_active = false;
+}
+
+void GUIPieChart::_bind_methods() {
+ OV_BIND_METHOD(GUIPieChart::get_gfx_pie_chart_texture);
+ OV_BIND_METHOD(GUIPieChart::set_gfx_pie_chart_name, { "gfx_pie_chart_name" });
+ OV_BIND_METHOD(GUIPieChart::get_gfx_pie_chart_name);
+ OV_BIND_METHOD(GUIPieChart::set_slices_array, { "new_slices" });
+}
+
+static const Vector2 disabled_tooltip_position { -1.0_real, -1.0_real };
+
+void GUIPieChart::_notification(int what) {
+ if (what == NOTIFICATION_MOUSE_EXIT_SELF) {
+ tooltip_position = disabled_tooltip_position;
+
+ _update_tooltip();
+ }
+}
+
+void GUIPieChart::_gui_input(Ref<InputEvent> const& event) {
+ Ref<InputEventMouseMotion> mm = event;
+
+ if (mm.is_valid()) {
+ tooltip_position = mm->get_position() * 2.0_real / get_size() - Vector2 { 1.0_real, 1.0_real };
+
+ _update_tooltip();
+ }
+}
+
+GUIPieChart::GUIPieChart() : tooltip_active { false }, tooltip_position { disabled_tooltip_position } {}
+
+Error GUIPieChart::set_gfx_pie_chart(GFX::PieChart const* gfx_pie_chart) {
+ const bool needs_setting = gfx_pie_chart_texture.is_null();
+
+ if (needs_setting) {
+ gfx_pie_chart_texture.instantiate();
+ ERR_FAIL_NULL_V(gfx_pie_chart_texture, FAILED);
+ }
+
+ const Error err = gfx_pie_chart_texture->set_gfx_pie_chart(gfx_pie_chart);
+
+ if (needs_setting) {
+ set_texture(gfx_pie_chart_texture);
+ }
+
+ if (tooltip_active) {
+ _update_tooltip();
+ }
+
+ return err;
+}
+
+Ref<GFXPieChartTexture> GUIPieChart::get_gfx_pie_chart_texture() const {
+ ERR_FAIL_NULL_V(gfx_pie_chart_texture, nullptr);
+
+ return gfx_pie_chart_texture;
+}
+
+Error GUIPieChart::set_gfx_pie_chart_name(String const& gfx_pie_chart_name) {
+ const bool needs_setting = gfx_pie_chart_texture.is_null();
+
+ if (needs_setting) {
+ gfx_pie_chart_texture.instantiate();
+ ERR_FAIL_NULL_V(gfx_pie_chart_texture, FAILED);
+ }
+
+ const Error err = gfx_pie_chart_texture->set_gfx_pie_chart_name(gfx_pie_chart_name);
+
+ if (needs_setting) {
+ set_texture(gfx_pie_chart_texture);
+ }
+
+ if (tooltip_active) {
+ _update_tooltip();
+ }
+
+ return err;
+}
+
+String GUIPieChart::get_gfx_pie_chart_name() const {
+ ERR_FAIL_NULL_V(gfx_pie_chart_texture, {});
+
+ return gfx_pie_chart_texture->get_gfx_pie_chart_name();
+}
+
+Error GUIPieChart::set_slices_array(GFXPieChartTexture::godot_pie_chart_data_t const& new_slices) {
+ ERR_FAIL_NULL_V(gfx_pie_chart_texture, FAILED);
+
+ const Error err = gfx_pie_chart_texture->set_slices_array(new_slices);
+
+ if (tooltip_active) {
+ _update_tooltip();
+ }
+
+ return err;
+}
diff --git a/extension/src/openvic-extension/classes/GUIPieChart.hpp b/extension/src/openvic-extension/classes/GUIPieChart.hpp
new file mode 100644
index 0000000..3356dba
--- /dev/null
+++ b/extension/src/openvic-extension/classes/GUIPieChart.hpp
@@ -0,0 +1,40 @@
+#pragma once
+
+#include <godot_cpp/classes/texture_rect.hpp>
+
+#include <openvic-simulation/interface/GFXSprite.hpp>
+
+#include "openvic-extension/classes/GFXPieChartTexture.hpp"
+
+namespace OpenVic {
+ class GUIPieChart : public godot::TextureRect {
+ GDCLASS(GUIPieChart, godot::TextureRect)
+
+ godot::Ref<GFXPieChartTexture> gfx_pie_chart_texture;
+
+ bool tooltip_active;
+ godot::Vector2 tooltip_position;
+
+ void _update_tooltip();
+
+ protected:
+ static void _bind_methods();
+
+ void _notification(int what);
+
+ public:
+ void _gui_input(godot::Ref<godot::InputEvent> const& event) override;
+
+ GUIPieChart();
+
+ godot::Error set_gfx_pie_chart(GFX::PieChart const* gfx_pie_chart);
+
+ godot::Ref<GFXPieChartTexture> get_gfx_pie_chart_texture() const;
+
+ godot::Error set_gfx_pie_chart_name(godot::String const& gfx_pie_chart_name);
+
+ godot::String get_gfx_pie_chart_name() const;
+
+ godot::Error set_slices_array(GFXPieChartTexture::godot_pie_chart_data_t const& new_slices);
+ };
+}
diff --git a/extension/src/openvic-extension/classes/GUIProgressBar.cpp b/extension/src/openvic-extension/classes/GUIProgressBar.cpp
new file mode 100644
index 0000000..d13f455
--- /dev/null
+++ b/extension/src/openvic-extension/classes/GUIProgressBar.cpp
@@ -0,0 +1,114 @@
+#include "GUIProgressBar.hpp"
+
+#include <godot_cpp/variant/utility_functions.hpp>
+
+#include "openvic-extension/singletons/AssetManager.hpp"
+#include "openvic-extension/utility/Utilities.hpp"
+
+using namespace godot;
+using namespace OpenVic;
+
+GUI_TOOLTIP_IMPLEMENTATIONS(GUIProgressBar)
+
+void GUIProgressBar::_bind_methods() {
+ GUI_TOOLTIP_BIND_METHODS(GUIProgressBar)
+}
+
+void GUIProgressBar::_notification(int what) {
+ _tooltip_notification(what);
+}
+
+GUIProgressBar::GUIProgressBar() : tooltip_active { false } {}
+
+Error GUIProgressBar::set_gfx_progress_bar(GFX::ProgressBar const* progress_bar) {
+ ERR_FAIL_NULL_V(progress_bar, FAILED);
+
+ AssetManager* asset_manager = AssetManager::get_singleton();
+ ERR_FAIL_NULL_V(asset_manager, FAILED);
+
+ Error err = OK;
+
+ static constexpr double MIN_VALUE = 0.0, MAX_VALUE = 1.0;
+ static constexpr uint32_t STEPS = 100;
+
+ set_nine_patch_stretch(true);
+ set_step((MAX_VALUE - MIN_VALUE) / STEPS);
+ set_min(MIN_VALUE);
+ set_max(MAX_VALUE);
+
+ using enum AssetManager::LoadFlags;
+
+ Ref<ImageTexture> back_texture;
+ if (!progress_bar->get_back_texture_file().empty()) {
+ const StringName back_texture_file = Utilities::std_to_godot_string(progress_bar->get_back_texture_file());
+ back_texture = asset_manager->get_texture(back_texture_file, LOAD_FLAG_CACHE_TEXTURE | LOAD_FLAG_FLIP_Y);
+ if (back_texture.is_null()) {
+ UtilityFunctions::push_error(
+ "Failed to load sprite back texture ", back_texture_file, " for GUIProgressBar ", get_name()
+ );
+ err = FAILED;
+ }
+ }
+ if (back_texture.is_null()) {
+ const Color back_colour = Utilities::to_godot_color(progress_bar->get_back_colour());
+ back_texture = Utilities::make_solid_colour_texture(
+ back_colour, progress_bar->get_size().x, progress_bar->get_size().y
+ );
+ if (back_texture.is_null()) {
+ UtilityFunctions::push_error(
+ "Failed to generate sprite ", back_colour, " back texture for GUIProgressBar ", get_name()
+ );
+ err = FAILED;
+ }
+ }
+ if (back_texture.is_valid()) {
+ set_under_texture(back_texture);
+ } else {
+ UtilityFunctions::push_error(
+ "Failed to create and set sprite back texture for GUIProgressBar ", get_name()
+ );
+ err = FAILED;
+ }
+
+ Ref<ImageTexture> progress_texture;
+ if (!progress_bar->get_progress_texture_file().empty()) {
+ const StringName progress_texture_file =
+ Utilities::std_to_godot_string(progress_bar->get_progress_texture_file());
+ progress_texture = asset_manager->get_texture(progress_texture_file, LOAD_FLAG_CACHE_TEXTURE | LOAD_FLAG_FLIP_Y);
+ if (progress_texture.is_null()) {
+ UtilityFunctions::push_error(
+ "Failed to load sprite progress texture ", progress_texture_file, " for GUIProgressBar ",
+ get_name()
+ );
+ err = FAILED;
+ }
+ }
+ if (progress_texture.is_null()) {
+ const Color progress_colour = Utilities::to_godot_color(progress_bar->get_progress_colour());
+ progress_texture = Utilities::make_solid_colour_texture(
+ progress_colour, progress_bar->get_size().x, progress_bar->get_size().y
+ );
+ if (progress_texture.is_null()) {
+ UtilityFunctions::push_error(
+ "Failed to generate sprite ", progress_colour, " progress texture for GUIProgressBar ",
+ get_name()
+ );
+ err = FAILED;
+ }
+ }
+ if (progress_texture.is_valid()) {
+ set_progress_texture(progress_texture);
+ } else {
+ UtilityFunctions::push_error(
+ "Failed to create and set sprite progress texture for GUIProgressBar ", get_name()
+ );
+ err = FAILED;
+ }
+
+ // TODO - work out why progress bar is missing bottom border pixel (e.g. province building expansion bar)
+ set_custom_minimum_size(
+ Utilities::to_godot_fvec2(static_cast<fvec2_t>(progress_bar->get_size()))
+ );
+
+ return err;
+}
diff --git a/extension/src/openvic-extension/classes/GUIProgressBar.hpp b/extension/src/openvic-extension/classes/GUIProgressBar.hpp
new file mode 100644
index 0000000..11b677a
--- /dev/null
+++ b/extension/src/openvic-extension/classes/GUIProgressBar.hpp
@@ -0,0 +1,24 @@
+#pragma once
+
+#include <godot_cpp/classes/texture_progress_bar.hpp>
+
+#include "openvic-simulation/interface/GFXSprite.hpp"
+#include "openvic-extension/classes/GUIHasTooltip.hpp"
+
+namespace OpenVic {
+ class GUIProgressBar : public godot::TextureProgressBar {
+ GDCLASS(GUIProgressBar, godot::TextureProgressBar)
+
+ GUI_TOOLTIP_DEFINITIONS
+
+ protected:
+ static void _bind_methods();
+
+ void _notification(int what);
+
+ public:
+ GUIProgressBar();
+
+ godot::Error set_gfx_progress_bar(GFX::ProgressBar const* progress_bar);
+ };
+}
diff --git a/extension/src/openvic-extension/classes/GUIScrollbar.cpp b/extension/src/openvic-extension/classes/GUIScrollbar.cpp
index ddcba7c..6e310d7 100644
--- a/extension/src/openvic-extension/classes/GUIScrollbar.cpp
+++ b/extension/src/openvic-extension/classes/GUIScrollbar.cpp
@@ -18,7 +18,11 @@ StringName const& GUIScrollbar::signal_value_changed() {
return signal_value_changed;
}
+GUI_TOOLTIP_IMPLEMENTATIONS(GUIScrollbar)
+
void GUIScrollbar::_bind_methods() {
+ GUI_TOOLTIP_BIND_METHODS(GUIScrollbar)
+
OV_BIND_METHOD(GUIScrollbar::emit_value_changed);
OV_BIND_METHOD(GUIScrollbar::reset);
OV_BIND_METHOD(GUIScrollbar::clear);
@@ -49,7 +53,7 @@ void GUIScrollbar::_bind_methods() {
ADD_SIGNAL(MethodInfo(signal_value_changed(), PropertyInfo(Variant::INT, "value")));
}
-GUIScrollbar::GUIScrollbar() {
+GUIScrollbar::GUIScrollbar() : tooltip_active { false } {
/* Anything which the constructor might not have default initialised will be set by clear(). */
clear();
}
@@ -587,11 +591,16 @@ void GUIScrollbar::_gui_input(Ref<InputEvent> const& event) {
hover_more = !hover_more;
queue_redraw();
}
+
+ _set_tooltip_active(hover_slider || hover_track || hover_less || hover_more);
+
return;
}
}
void GUIScrollbar::_notification(int what) {
+ // GUIScrollbar doesn't use _tooltip_notification, as we don't want to show tooltips when hovering over transparent parts.
+
switch (what) {
case NOTIFICATION_VISIBILITY_CHANGED:
case NOTIFICATION_MOUSE_EXIT: {
@@ -602,6 +611,10 @@ void GUIScrollbar::_notification(int what) {
queue_redraw();
} break;
+ case NOTIFICATION_MOUSE_EXIT_SELF: {
+ _set_tooltip_active(false);
+ } break;
+
/* Pressing (and holding) less and more buttons. */
case NOTIFICATION_INTERNAL_PHYSICS_PROCESS: {
const double delta = get_physics_process_delta_time();
diff --git a/extension/src/openvic-extension/classes/GUIScrollbar.hpp b/extension/src/openvic-extension/classes/GUIScrollbar.hpp
index 16b2e00..d9b22f1 100644
--- a/extension/src/openvic-extension/classes/GUIScrollbar.hpp
+++ b/extension/src/openvic-extension/classes/GUIScrollbar.hpp
@@ -6,11 +6,14 @@
#include <openvic-simulation/interface/GUI.hpp>
#include "openvic-extension/classes/GFXSpriteTexture.hpp"
+#include "openvic-extension/classes/GUIHasTooltip.hpp"
namespace OpenVic {
class GUIScrollbar : public godot::Control {
GDCLASS(GUIScrollbar, godot::Control)
+ GUI_TOOLTIP_DEFINITIONS
+
GUI::Scrollbar const* PROPERTY(gui_scrollbar);
godot::Ref<GFXSpriteTexture> slider_texture;
@@ -74,6 +77,7 @@ namespace OpenVic {
protected:
static void _bind_methods();
+
void _notification(int what);
public:
diff --git a/extension/src/openvic-extension/classes/GUITextureRect.cpp b/extension/src/openvic-extension/classes/GUITextureRect.cpp
new file mode 100644
index 0000000..fba9b19
--- /dev/null
+++ b/extension/src/openvic-extension/classes/GUITextureRect.cpp
@@ -0,0 +1,16 @@
+#include "GUITextureRect.hpp"
+
+using namespace godot;
+using namespace OpenVic;
+
+GUI_TOOLTIP_IMPLEMENTATIONS(GUITextureRect)
+
+void GUITextureRect::_bind_methods() {
+ GUI_TOOLTIP_BIND_METHODS(GUITextureRect)
+}
+
+void GUITextureRect::_notification(int what) {
+ _tooltip_notification(what);
+}
+
+GUITextureRect::GUITextureRect() : tooltip_active { false } {}
diff --git a/extension/src/openvic-extension/classes/GUITextureRect.hpp b/extension/src/openvic-extension/classes/GUITextureRect.hpp
new file mode 100644
index 0000000..6fc8123
--- /dev/null
+++ b/extension/src/openvic-extension/classes/GUITextureRect.hpp
@@ -0,0 +1,21 @@
+#pragma once
+
+#include <godot_cpp/classes/texture_rect.hpp>
+
+#include "openvic-extension/classes/GUIHasTooltip.hpp"
+
+namespace OpenVic {
+ class GUITextureRect : public godot::TextureRect {
+ GDCLASS(GUITextureRect, godot::TextureRect)
+
+ GUI_TOOLTIP_DEFINITIONS
+
+ protected:
+ static void _bind_methods();
+
+ void _notification(int what);
+
+ public:
+ GUITextureRect();
+ };
+}
diff --git a/extension/src/openvic-extension/register_types.cpp b/extension/src/openvic-extension/register_types.cpp
index bd50e34..7927b22 100644
--- a/extension/src/openvic-extension/register_types.cpp
+++ b/extension/src/openvic-extension/register_types.cpp
@@ -6,11 +6,19 @@
#include "openvic-extension/classes/GFXSpriteTexture.hpp"
#include "openvic-extension/classes/GFXMaskedFlagTexture.hpp"
#include "openvic-extension/classes/GFXPieChartTexture.hpp"
+#include "openvic-extension/classes/GUIButton.hpp"
+#include "openvic-extension/classes/GUIIcon.hpp"
+#include "openvic-extension/classes/GUIIconButton.hpp"
#include "openvic-extension/classes/GUILabel.hpp"
#include "openvic-extension/classes/GUIListBox.hpp"
+#include "openvic-extension/classes/GUIMaskedFlag.hpp"
+#include "openvic-extension/classes/GUIMaskedFlagButton.hpp"
#include "openvic-extension/classes/GUINode.hpp"
#include "openvic-extension/classes/GUIOverlappingElementsBox.hpp"
+#include "openvic-extension/classes/GUIPieChart.hpp"
+#include "openvic-extension/classes/GUIProgressBar.hpp"
#include "openvic-extension/classes/GUIScrollbar.hpp"
+#include "openvic-extension/classes/GUITextureRect.hpp"
#include "openvic-extension/classes/MapMesh.hpp"
#include "openvic-extension/singletons/AssetManager.hpp"
#include "openvic-extension/singletons/Checksum.hpp"
@@ -76,11 +84,23 @@ void initialize_openvic_types(ModuleInitializationLevel p_level) {
ClassDB::register_class<GFXMaskedFlagTexture>();
ClassDB::register_class<GFXPieChartTexture>();
+ ClassDB::register_class<GUIButton>();
ClassDB::register_class<GUILabel>();
ClassDB::register_class<GUIListBox>();
ClassDB::register_class<GUINode>();
ClassDB::register_class<GUIOverlappingElementsBox>();
+ ClassDB::register_class<GUIPieChart>();
+ ClassDB::register_class<GUIProgressBar>();
ClassDB::register_class<GUIScrollbar>();
+ ClassDB::register_class<GUITextureRect>();
+
+ /* Depend on GUITextureRect */
+ ClassDB::register_class<GUIIcon>();
+ ClassDB::register_class<GUIMaskedFlag>();
+
+ /* Depend on GUIButton */
+ ClassDB::register_class<GUIIconButton>();
+ ClassDB::register_class<GUIMaskedFlagButton>();
}
void uninitialize_openvic_types(ModuleInitializationLevel p_level) {
diff --git a/extension/src/openvic-extension/singletons/AssetManager.cpp b/extension/src/openvic-extension/singletons/AssetManager.cpp
index d17edd0..3b37c8c 100644
--- a/extension/src/openvic-extension/singletons/AssetManager.cpp
+++ b/extension/src/openvic-extension/singletons/AssetManager.cpp
@@ -120,6 +120,29 @@ Ref<ImageTexture> AssetManager::get_texture(StringName const& path, LoadFlags lo
}
}
+Ref<StyleBoxTexture> AssetManager::make_stylebox_texture(Ref<Texture2D> const& texture, Vector2 const& border) {
+ ERR_FAIL_NULL_V(texture, nullptr);
+
+ Ref<StyleBoxTexture> stylebox;
+ stylebox.instantiate();
+ ERR_FAIL_NULL_V(stylebox, nullptr);
+
+ stylebox->set_texture(texture);
+
+ static const StringName changed_signal = "changed";
+ static const StringName emit_changed_func = "emit_changed";
+ texture->connect(changed_signal, Callable { *stylebox, emit_changed_func }, Object::CONNECT_PERSIST);
+
+ if (border != Vector2 {}) {
+ stylebox->set_texture_margin(SIDE_LEFT, border.x);
+ stylebox->set_texture_margin(SIDE_RIGHT, border.x);
+ stylebox->set_texture_margin(SIDE_TOP, border.y);
+ stylebox->set_texture_margin(SIDE_BOTTOM, border.y);
+ }
+
+ return stylebox;
+}
+
Ref<FontFile> AssetManager::get_font(StringName const& 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 deca309..96cb880 100644
--- a/extension/src/openvic-extension/singletons/AssetManager.hpp
+++ b/extension/src/openvic-extension/singletons/AssetManager.hpp
@@ -3,7 +3,9 @@
#include <godot_cpp/classes/atlas_texture.hpp>
#include <godot_cpp/classes/font_file.hpp>
#include <godot_cpp/classes/image_texture.hpp>
+#include <godot_cpp/classes/style_box_texture.hpp>
#include <godot_cpp/core/class_db.hpp>
+#include <godot_cpp/variant/vector2.hpp>
#include <openvic-simulation/interface/GFXSprite.hpp>
@@ -68,6 +70,10 @@ namespace OpenVic {
godot::StringName const& path, LoadFlags load_flags = LOAD_FLAG_CACHE_TEXTURE
);
+ static godot::Ref<godot::StyleBoxTexture> make_stylebox_texture(
+ godot::Ref<godot::Texture2D> const& texture, godot::Vector2 const& border = {}
+ );
+
/* 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<godot::FontFile> get_font(godot::StringName const& name);
diff --git a/extension/src/openvic-extension/singletons/MenuSingleton.cpp b/extension/src/openvic-extension/singletons/MenuSingleton.cpp
index 7a5f47f..367462b 100644
--- a/extension/src/openvic-extension/singletons/MenuSingleton.cpp
+++ b/extension/src/openvic-extension/singletons/MenuSingleton.cpp
@@ -30,6 +30,10 @@ StringName const& MenuSingleton::_signal_search_cache_changed() {
static const StringName signal_search_cache_changed = "search_cache_changed";
return signal_search_cache_changed;
}
+StringName const& MenuSingleton::_signal_update_tooltip() {
+ static const StringName signal_update_tooltip = "update_tooltip";
+ return signal_update_tooltip;
+}
String MenuSingleton::get_state_name(State const& state) const {
StateSet const& state_set = state.get_state_set();
@@ -103,6 +107,16 @@ String MenuSingleton::get_country_adjective(CountryInstance const& country) cons
}
void MenuSingleton::_bind_methods() {
+ /* TOOLTIP */
+ OV_BIND_METHOD(MenuSingleton::show_tooltip, { "text", "substitution_dict", "position" });
+ OV_BIND_METHOD(MenuSingleton::show_control_tooltip, { "text", "substitution_dict", "control" });
+ OV_BIND_METHOD(MenuSingleton::hide_tooltip);
+
+ ADD_SIGNAL(MethodInfo(
+ _signal_update_tooltip(), PropertyInfo(Variant::STRING, "text"),
+ PropertyInfo(Variant::DICTIONARY, "substitution_dict"), PropertyInfo(Variant::VECTOR2, "position")
+ ));
+
/* PROVINCE OVERVIEW PANEL */
OV_BIND_METHOD(MenuSingleton::get_province_info_from_index, { "index" });
OV_BIND_METHOD(MenuSingleton::get_province_building_count);
@@ -205,6 +219,25 @@ MenuSingleton::~MenuSingleton() {
singleton = nullptr;
}
+/* TOOLTIP */
+
+void MenuSingleton::show_tooltip(String const& text, Dictionary const& substitution_dict, Vector2 const& position) {
+ emit_signal(_signal_update_tooltip(), text, substitution_dict, position);
+}
+
+void MenuSingleton::show_control_tooltip(String const& text, Dictionary const& substitution_dict, Control const* control) {
+ ERR_FAIL_NULL(control);
+
+ using namespace OpenVic::Utilities::literals;
+ static const Vector2 offset { 0.0_real, 64.0_real };
+
+ show_tooltip(text, substitution_dict, control->get_global_position() + offset);
+}
+
+void MenuSingleton::hide_tooltip() {
+ show_tooltip({}, {}, {});
+}
+
/* PROVINCE OVERVIEW PANEL */
static TypedArray<Dictionary> _make_buildings_dict_array(
@@ -561,7 +594,7 @@ Error MenuSingleton::generate_search_cache() {
return OK;
}
-void MenuSingleton::update_search_results(godot::String const& text) {
+void MenuSingleton::update_search_results(String const& text) {
// Sanatise input
const String search_text = text.strip_edges().to_lower();
diff --git a/extension/src/openvic-extension/singletons/MenuSingleton.hpp b/extension/src/openvic-extension/singletons/MenuSingleton.hpp
index 190e3ea..022bce5 100644
--- a/extension/src/openvic-extension/singletons/MenuSingleton.hpp
+++ b/extension/src/openvic-extension/singletons/MenuSingleton.hpp
@@ -1,5 +1,6 @@
#pragma once
+#include <godot_cpp/classes/control.hpp>
#include <godot_cpp/classes/image.hpp>
#include <openvic-simulation/pop/Pop.hpp>
@@ -95,6 +96,10 @@ namespace OpenVic {
static godot::StringName const& _signal_population_menu_pops_changed();
/* Emitted when the collection of possible search results changes. */
static godot::StringName const& _signal_search_cache_changed();
+ /* Emitted when the current tooltip changes. Arguments: text (godot::String), substitution_dict (godot::Dictionary),
+ * position (godot::Vector2). If text is empty then the tooltip will be hidden, otherwise the text will be shown at
+ * the given position. */
+ static godot::StringName const& _signal_update_tooltip();
godot::String get_state_name(State const& state) const;
godot::String get_country_name(CountryInstance const& country) const;
@@ -110,6 +115,15 @@ namespace OpenVic {
MenuSingleton();
~MenuSingleton();
+ /* TOOLTIP */
+ void show_tooltip(
+ godot::String const& text, godot::Dictionary const& substitution_dict, godot::Vector2 const& position
+ );
+ void show_control_tooltip(
+ godot::String const& text, godot::Dictionary const& substitution_dict, godot::Control const* control
+ );
+ void hide_tooltip();
+
/* PROVINCE OVERVIEW PANEL */
/* Get info to display in Province Overview Panel, packaged in a Dictionary using StringName constants as keys. */
godot::Dictionary get_province_info_from_index(int32_t index) const;
diff --git a/extension/src/openvic-extension/utility/UITools.cpp b/extension/src/openvic-extension/utility/UITools.cpp
index 723fb24..4bd537d 100644
--- a/extension/src/openvic-extension/utility/UITools.cpp
+++ b/extension/src/openvic-extension/utility/UITools.cpp
@@ -1,23 +1,23 @@
#include "UITools.hpp"
-#include <godot_cpp/classes/button.hpp>
#include <godot_cpp/classes/color_rect.hpp>
#include <godot_cpp/classes/line_edit.hpp>
#include <godot_cpp/classes/panel.hpp>
#include <godot_cpp/classes/style_box_empty.hpp>
#include <godot_cpp/classes/style_box_texture.hpp>
-#include <godot_cpp/classes/texture_progress_bar.hpp>
-#include <godot_cpp/classes/texture_rect.hpp>
#include <godot_cpp/classes/theme.hpp>
#include <godot_cpp/variant/utility_functions.hpp>
-#include "openvic-extension/classes/GFXButtonStateTexture.hpp"
-#include "openvic-extension/classes/GFXSpriteTexture.hpp"
-#include "openvic-extension/classes/GFXMaskedFlagTexture.hpp"
-#include "openvic-extension/classes/GFXPieChartTexture.hpp"
+#include "openvic-extension/classes/GUIButton.hpp"
+#include "openvic-extension/classes/GUIIcon.hpp"
+#include "openvic-extension/classes/GUIIconButton.hpp"
#include "openvic-extension/classes/GUILabel.hpp"
#include "openvic-extension/classes/GUIListBox.hpp"
+#include "openvic-extension/classes/GUIMaskedFlag.hpp"
+#include "openvic-extension/classes/GUIMaskedFlagButton.hpp"
#include "openvic-extension/classes/GUIOverlappingElementsBox.hpp"
+#include "openvic-extension/classes/GUIPieChart.hpp"
+#include "openvic-extension/classes/GUIProgressBar.hpp"
#include "openvic-extension/classes/GUIScrollbar.hpp"
#include "openvic-extension/singletons/AssetManager.hpp"
#include "openvic-extension/singletons/GameSingleton.hpp"
@@ -113,29 +113,6 @@ static bool new_control(T*& node, GUI::Element const& element, String const& nam
return ret;
}
-static bool add_theme_stylebox(
- Control* control, StringName const& theme_name, Ref<Texture2D> const& texture, Vector2 border = {}
-) {
- Ref<StyleBoxTexture> stylebox;
- stylebox.instantiate();
- ERR_FAIL_NULL_V(stylebox, false);
- stylebox->set_texture(texture);
-
- static const StringName changed_signal = "changed";
- static const StringName emit_changed_func = "emit_changed";
- texture->connect(changed_signal, Callable { *stylebox, emit_changed_func }, Object::CONNECT_PERSIST);
-
- if (border != Vector2 {}) {
- stylebox->set_texture_margin(SIDE_LEFT, border.x);
- stylebox->set_texture_margin(SIDE_RIGHT, border.x);
- stylebox->set_texture_margin(SIDE_TOP, border.y);
- stylebox->set_texture_margin(SIDE_BOTTOM, border.y);
- }
-
- control->add_theme_stylebox_override(theme_name, stylebox);
- return true;
-};
-
static bool generate_icon(generate_gui_args_t&& args) {
using namespace OpenVic::Utilities::literals;
@@ -146,154 +123,70 @@ static bool generate_icon(generate_gui_args_t&& args) {
/* Change to use sprite type to choose Godot node type! */
bool ret = true;
if (icon.get_sprite() != nullptr) {
- if (icon.get_sprite()->is_type<GFX::IconTextureSprite>()) {
- TextureRect* godot_texture_rect = nullptr;
- ret &= new_control(godot_texture_rect, icon, args.name);
- ERR_FAIL_NULL_V_MSG(godot_texture_rect, false, vformat("Failed to create TextureRect for GUI icon %s", icon_name));
+ if (GFX::IconTextureSprite const* texture_sprite = icon.get_sprite()->cast_to<GFX::IconTextureSprite>()) {
+ GUIIcon* gui_icon = nullptr;
+ ret &= new_control(gui_icon, icon, args.name);
+ ERR_FAIL_NULL_V_MSG(
+ gui_icon, false, vformat("Failed to create GUIIcon for GUI icon %s", icon_name)
+ );
- godot_texture_rect->set_mouse_filter(Control::MOUSE_FILTER_IGNORE);
+ gui_icon->set_mouse_filter(Control::MOUSE_FILTER_IGNORE);
- GFX::IconTextureSprite const* texture_sprite = icon.get_sprite()->cast_to<GFX::IconTextureSprite>();
- Ref<GFXSpriteTexture> texture = GFXSpriteTexture::make_gfx_sprite_texture(texture_sprite, icon.get_frame());
- if (texture.is_valid()) {
- godot_texture_rect->set_texture(texture);
- } else {
- UtilityFunctions::push_error("Failed to make GFXSpriteTexture for GUI icon ", icon_name);
+ if (gui_icon->set_gfx_texture_sprite(texture_sprite, icon.get_frame()) != OK) {
+ UtilityFunctions::push_error("Error setting up GUIIcon for GUI icon ", icon_name);
ret = false;
}
const float scale = icon.get_scale();
- godot_texture_rect->set_scale({ scale, scale });
-
- args.result = godot_texture_rect;
- } else if (icon.get_sprite()->is_type<GFX::MaskedFlag>()) {
- TextureRect* godot_texture_rect = nullptr;
- ret &= new_control(godot_texture_rect, icon, args.name);
- ERR_FAIL_NULL_V_MSG(godot_texture_rect, false, vformat("Failed to create TextureRect for GUI icon %s", icon_name));
-
- GFX::MaskedFlag const* masked_flag = icon.get_sprite()->cast_to<GFX::MaskedFlag>();
- Ref<GFXMaskedFlagTexture> texture = GFXMaskedFlagTexture::make_gfx_masked_flag_texture(masked_flag);
- if (texture.is_valid()) {
- godot_texture_rect->set_texture(texture);
- } else {
- UtilityFunctions::push_error("Failed to make GFXMaskedFlagTexture for GUI icon ", icon_name);
- ret = false;
- }
+ gui_icon->set_scale({ scale, scale });
- args.result = godot_texture_rect;
- } else if (icon.get_sprite()->is_type<GFX::ProgressBar>()) {
- TextureProgressBar* godot_progress_bar = nullptr;
- ret &= new_control(godot_progress_bar, icon, args.name);
+ args.result = gui_icon;
+ } else if (GFX::MaskedFlag const* masked_flag = icon.get_sprite()->cast_to<GFX::MaskedFlag>()) {
+ GUIMaskedFlag* gui_masked_flag = nullptr;
+ ret &= new_control(gui_masked_flag, icon, args.name);
ERR_FAIL_NULL_V_MSG(
- godot_progress_bar, false, vformat("Failed to create TextureProgressBar for GUI icon %s", icon_name)
+ gui_masked_flag, false, vformat("Failed to create GUIMaskedFlag for GUI icon %s", icon_name)
);
- static constexpr double MIN_VALUE = 0.0, MAX_VALUE = 1.0;
- static constexpr uint32_t STEPS = 100;
-
- godot_progress_bar->set_nine_patch_stretch(true);
- godot_progress_bar->set_step((MAX_VALUE - MIN_VALUE) / STEPS);
- godot_progress_bar->set_min(MIN_VALUE);
- godot_progress_bar->set_max(MAX_VALUE);
-
- GFX::ProgressBar const* progress_bar = icon.get_sprite()->cast_to<GFX::ProgressBar>();
-
- using enum AssetManager::LoadFlags;
-
- Ref<ImageTexture> back_texture;
- if (!progress_bar->get_back_texture_file().empty()) {
- const StringName back_texture_file = Utilities::std_to_godot_string(progress_bar->get_back_texture_file());
- back_texture = args.asset_manager.get_texture(back_texture_file, LOAD_FLAG_CACHE_TEXTURE | LOAD_FLAG_FLIP_Y);
- if (back_texture.is_null()) {
- UtilityFunctions::push_error(
- "Failed to load progress bar sprite back texture ", back_texture_file, " for GUI icon ", icon_name
- );
- ret = false;
- }
- }
- if (back_texture.is_null()) {
- const Color back_colour = Utilities::to_godot_color(progress_bar->get_back_colour());
- back_texture = Utilities::make_solid_colour_texture(
- back_colour, progress_bar->get_size().x, progress_bar->get_size().y
- );
- if (back_texture.is_null()) {
- UtilityFunctions::push_error(
- "Failed to generate progress bar sprite ", back_colour, " back texture for GUI icon ", icon_name
- );
- ret = false;
- }
- }
- if (back_texture.is_valid()) {
- godot_progress_bar->set_under_texture(back_texture);
- } else {
- UtilityFunctions::push_error(
- "Failed to create and set progress bar sprite back texture for GUI icon ", icon_name
- );
+ if (gui_masked_flag->set_gfx_masked_flag(masked_flag) != OK) {
+ UtilityFunctions::push_error("Error setting up GUIMaskedFlag for GUI icon ", icon_name);
ret = false;
}
- Ref<ImageTexture> progress_texture;
- if (!progress_bar->get_progress_texture_file().empty()) {
- const StringName progress_texture_file =
- Utilities::std_to_godot_string(progress_bar->get_progress_texture_file());
- progress_texture =
- args.asset_manager.get_texture(progress_texture_file, LOAD_FLAG_CACHE_TEXTURE | LOAD_FLAG_FLIP_Y);
- if (progress_texture.is_null()) {
- UtilityFunctions::push_error(
- "Failed to load progress bar sprite progress texture ", progress_texture_file, " for GUI icon ",
- icon_name
- );
- ret = false;
- }
- }
- if (progress_texture.is_null()) {
- const Color progress_colour = Utilities::to_godot_color(progress_bar->get_progress_colour());
- progress_texture = Utilities::make_solid_colour_texture(
- progress_colour, progress_bar->get_size().x, progress_bar->get_size().y
- );
- if (progress_texture.is_null()) {
- UtilityFunctions::push_error(
- "Failed to generate progress bar sprite ", progress_colour, " progress texture for GUI icon ",
- icon_name
- );
- ret = false;
- }
- }
- if (progress_texture.is_valid()) {
- godot_progress_bar->set_progress_texture(progress_texture);
- } else {
- UtilityFunctions::push_error(
- "Failed to create and set progress bar sprite progress texture for GUI icon ", icon_name
- );
+ args.result = gui_masked_flag;
+ } else if (GFX::ProgressBar const* progress_bar = icon.get_sprite()->cast_to<GFX::ProgressBar>()) {
+ GUIProgressBar* gui_progress_bar = nullptr;
+ ret &= new_control(gui_progress_bar, icon, args.name);
+ ERR_FAIL_NULL_V_MSG(
+ gui_progress_bar, false, vformat("Failed to create GUIProgressBar for GUI icon %s", icon_name)
+ );
+
+ if (gui_progress_bar->set_gfx_progress_bar(progress_bar) != OK) {
+ UtilityFunctions::push_error("Error setting up GUIProgressBar for GUI icon ", icon_name);
ret = false;
}
- // TODO - work out why progress bar is missing bottom border pixel (e.g. province building expansion bar)
- godot_progress_bar->set_custom_minimum_size(
- Utilities::to_godot_fvec2(static_cast<fvec2_t>(progress_bar->get_size()))
+ args.result = gui_progress_bar;
+ } else if (GFX::PieChart const* pie_chart = icon.get_sprite()->cast_to<GFX::PieChart>()) {
+ GUIPieChart* gui_pie_chart = nullptr;
+ ret &= new_control(gui_pie_chart, icon, args.name);
+ ERR_FAIL_NULL_V_MSG(
+ gui_pie_chart, false, vformat("Failed to create GUIPieChart for GUI icon %s", icon_name)
);
- args.result = godot_progress_bar;
- } else if (icon.get_sprite()->is_type<GFX::PieChart>()) {
- TextureRect* godot_texture_rect = nullptr;
- ret &= new_control(godot_texture_rect, icon, args.name);
- ERR_FAIL_NULL_V_MSG(godot_texture_rect, false, vformat("Failed to create TextureRect for GUI icon %s", icon_name));
-
- GFX::PieChart const* pie_chart = icon.get_sprite()->cast_to<GFX::PieChart>();
- Ref<GFXPieChartTexture> texture = GFXPieChartTexture::make_gfx_pie_chart_texture(pie_chart);
- if (texture.is_valid()) {
- godot_texture_rect->set_texture(texture);
- // TODO - work out why this is needed
- Vector2 pos = godot_texture_rect->get_position();
- pos.x -= texture->get_width() / 2.0_real;
- godot_texture_rect->set_position(pos);
+ if (gui_pie_chart->set_gfx_pie_chart(pie_chart) == OK) {
+ // For some reason pie charts are defined by their top-centre position, so we need to subtract
+ // half the width from the x-coordinate to fix this and position the GUIPieChart correctly.
+ Vector2 pos = gui_pie_chart->get_position();
+ pos.x -= gui_pie_chart->get_gfx_pie_chart_texture()->get_width() / 2.0_real;
+ gui_pie_chart->set_position(pos);
} else {
- UtilityFunctions::push_error("Failed to make GFXPieChartTexture for GUI icon ", icon_name);
+ UtilityFunctions::push_error("Error setting up GUIPieChart for GUI icon ", icon_name);
ret = false;
}
- args.result = godot_texture_rect;
- } else if (icon.get_sprite()->is_type<GFX::LineChart>()) {
+ args.result = gui_pie_chart;
+ } else if (GFX::LineChart const* line_chart = icon.get_sprite()->cast_to<GFX::LineChart>()) {
// TODO - generate line chart
} else {
UtilityFunctions::push_error(
@@ -327,86 +220,53 @@ static bool generate_button(generate_gui_args_t&& args) {
// TODO - shortcut, clicksound, rotation (?)
const String button_name = Utilities::std_to_godot_string(button.get_name());
- Button* godot_button = nullptr;
- bool ret = new_control(godot_button, button, args.name);
- ERR_FAIL_NULL_V_MSG(godot_button, false, vformat("Failed to create Button for GUI button %s", button_name));
+ ERR_FAIL_NULL_V_MSG(button.get_sprite(), false, vformat("Null sprite for GUI button %s", button_name));
- godot_button->set_mouse_filter(Control::MOUSE_FILTER_PASS);
+ GUIButton* gui_button = nullptr;
+ bool ret = true;
- godot_button->set_text(Utilities::std_to_godot_string(button.get_text()));
+ if (GFX::IconTextureSprite const* texture_sprite = button.get_sprite()->cast_to<GFX::IconTextureSprite>()) {
+ GUIIconButton* gui_icon_button = nullptr;
+ ret &= new_control(gui_icon_button, button, args.name);
+ ERR_FAIL_NULL_V_MSG(gui_icon_button, false, vformat("Failed to create GUIIconButton for GUI button %s", button_name));
- if (button.get_sprite() != nullptr) {
- Ref<GFXButtonStateHavingTexture> texture;
- if (button.get_sprite()->is_type<GFX::IconTextureSprite>()) {
- GFX::IconTextureSprite const* texture_sprite = button.get_sprite()->cast_to<GFX::IconTextureSprite>();
- texture = GFXSpriteTexture::make_gfx_sprite_texture(texture_sprite);
- if (texture.is_null()) {
- UtilityFunctions::push_error("Failed to make GFXSpriteTexture for GUI button ", button_name);
- ret = false;
- }
- } else if (button.get_sprite()->is_type<GFX::MaskedFlag>()) {
- GFX::MaskedFlag const* masked_flag = button.get_sprite()->cast_to<GFX::MaskedFlag>();
- texture = GFXMaskedFlagTexture::make_gfx_masked_flag_texture(masked_flag);
- if (texture.is_null()) {
- UtilityFunctions::push_error("Failed to make GFXMaskedFlagTexture for GUI button ", button_name);
- ret = false;
- }
- } else {
- UtilityFunctions::push_error(
- "Invalid sprite type ", Utilities::std_to_godot_string(button.get_sprite()->get_type()),
- " for GUI button ", button_name
- );
+ if (gui_icon_button->set_gfx_texture_sprite(texture_sprite) != OK) {
+ UtilityFunctions::push_error("Error setting up GUIIconButton for GUI button ", button_name);
ret = false;
}
- if (texture.is_valid()) {
- godot_button->set_custom_minimum_size(texture->get_size());
-
- static const StringName normal_theme = "normal";
- ret &= add_theme_stylebox(godot_button, normal_theme, texture);
-
- using enum GFXButtonStateTexture::ButtonState;
- for (GFXButtonStateTexture::ButtonState button_state : { HOVER, PRESSED, DISABLED }) {
- Ref<GFXButtonStateTexture> button_state_texture = texture->get_button_state_texture(button_state);
- if (button_state_texture.is_valid()) {
- ret &= add_theme_stylebox(
- godot_button, button_state_texture->get_button_state_name(), button_state_texture
- );
- } else {
- UtilityFunctions::push_error(
- "Failed to make ", GFXButtonStateTexture::button_state_to_name(button_state),
- " GFXButtonStateTexture for GUI button ", button_name
- );
- ret = false;
- }
- }
+ gui_button = gui_icon_button;
+ } else if (GFX::MaskedFlag const* masked_flag = button.get_sprite()->cast_to<GFX::MaskedFlag>()) {
+ GUIMaskedFlagButton* gui_masked_flag_button = nullptr;
+ ret &= new_control(gui_masked_flag_button, button, args.name);
+ ERR_FAIL_NULL_V_MSG(
+ gui_masked_flag_button, false, vformat("Failed to create GUIMaskedFlagButton for GUI button %s", button_name)
+ );
+
+ if (gui_masked_flag_button->set_gfx_masked_flag(masked_flag) != OK) {
+ UtilityFunctions::push_error("Error setting up GUIMaskedFlagButton for GUI button ", button_name);
+ ret = false;
}
+
+ gui_button = gui_masked_flag_button;
} else {
- UtilityFunctions::push_error("Null sprite for GUI button ", button_name);
- ret = false;
+ ERR_FAIL_V_MSG(
+ false, vformat(
+ "Invalid sprite type %s for GUI button %s", Utilities::std_to_godot_string(button.get_sprite()->get_type()),
+ button_name
+ )
+ );
}
- if (button.get_font() != nullptr) {
- const StringName font_file = Utilities::std_to_godot_string(button.get_font()->get_fontname());
- const Ref<Font> font = args.asset_manager.get_font(font_file);
- if (font.is_valid()) {
- static const StringName font_theme = "font";
- godot_button->add_theme_font_override(font_theme, font);
- } else {
- UtilityFunctions::push_error("Failed to load font \"", font_file, "\" for GUI button ", button_name);
- ret = false;
- }
+ gui_button->set_mouse_filter(Control::MOUSE_FILTER_PASS);
- static const std::vector<StringName> button_font_themes {
- "font_color", "font_hover_color", "font_hover_pressed_color", "font_pressed_color", "font_disabled_color"
- };
- const Color colour = Utilities::to_godot_color(button.get_font()->get_colour());
- for (StringName const& theme_name : button_font_themes) {
- godot_button->add_theme_color_override(theme_name, colour);
- }
+ gui_button->set_text(Utilities::std_to_godot_string(button.get_text()));
+
+ if (button.get_font() != nullptr) {
+ ret &= gui_button->set_gfx_font(button.get_font()) == OK;
}
- args.result = godot_button;
+ args.result = gui_button;
return ret;
}
@@ -416,86 +276,37 @@ static bool generate_checkbox(generate_gui_args_t&& args) {
// TODO - shortcut
const String checkbox_name = Utilities::std_to_godot_string(checkbox.get_name());
- Button* godot_button = nullptr;
- bool ret = new_control(godot_button, checkbox, args.name);
- ERR_FAIL_NULL_V_MSG(godot_button, false, vformat("Failed to create Button for GUI checkbutton %s", checkbox_name));
-
- godot_button->set_text(Utilities::std_to_godot_string(checkbox.get_text()));
+ ERR_FAIL_NULL_V_MSG(checkbox.get_sprite(), false, vformat("Null sprite for GUI checkbox %s", checkbox_name));
- godot_button->set_toggle_mode(true);
+ GFX::IconTextureSprite const* texture_sprite = checkbox.get_sprite()->cast_to<GFX::IconTextureSprite>();
- if (checkbox.get_sprite() != nullptr) {
- GFX::IconTextureSprite const* texture_sprite = checkbox.get_sprite()->cast_to<GFX::IconTextureSprite>();
-
- if (texture_sprite != nullptr) {
- Ref<GFXSpriteTexture> texture = GFXSpriteTexture::make_gfx_sprite_texture(texture_sprite);
+ ERR_FAIL_NULL_V_MSG(
+ texture_sprite, false, vformat(
+ "Invalid sprite type %s for GUI checkbox %s", Utilities::std_to_godot_string(checkbox.get_sprite()->get_type()),
+ checkbox_name
+ )
+ );
- if (texture.is_valid()) {
- godot_button->set_custom_minimum_size(texture->get_size());
+ GUIIconButton* gui_icon_button = nullptr;
+ bool ret = new_control(gui_icon_button, checkbox, args.name);
+ ERR_FAIL_NULL_V_MSG(
+ gui_icon_button, false, vformat("Failed to create GUIIconButton for GUI checkbox %s", checkbox_name)
+ );
- if (texture->get_icon_count() > 1) {
- static const StringName toggled_signal = "toggled";
- static const StringName set_toggled_icon_func = "set_toggled_icon";
- godot_button->connect(
- toggled_signal, Callable { *texture, set_toggled_icon_func }, Object::CONNECT_PERSIST
- );
- }
+ gui_icon_button->set_toggle_mode(true);
- static const StringName normal_theme = "normal";
- ret &= add_theme_stylebox(godot_button, normal_theme, texture);
-
- using enum GFXButtonStateTexture::ButtonState;
- for (GFXButtonStateTexture::ButtonState button_state : { HOVER, PRESSED, DISABLED }) {
- Ref<GFXButtonStateTexture> button_state_texture = texture->get_button_state_texture(button_state);
- if (button_state_texture.is_valid()) {
- ret &= add_theme_stylebox(
- godot_button, button_state_texture->get_button_state_name(), button_state_texture
- );
- } else {
- UtilityFunctions::push_error(
- "Failed to make ", GFXButtonStateTexture::button_state_to_name(button_state),
- " GFXButtonStateTexture for GUI checkbox ", checkbox_name
- );
- ret = false;
- }
- }
- } else {
- UtilityFunctions::push_error("Failed to make GFXSpriteTexture for GUI checkbox ", checkbox_name);
- ret = false;
- }
- } else {
- UtilityFunctions::push_error(
- "Invalid sprite type ", Utilities::std_to_godot_string(checkbox.get_sprite()->get_type()),
- " for GUI checkbox ", checkbox_name
- );
- ret = false;
- }
- } else {
- UtilityFunctions::push_error("Null sprite for GUI checkbox ", checkbox_name);
+ if (gui_icon_button->set_gfx_texture_sprite(texture_sprite) != OK) {
+ UtilityFunctions::push_error("Error setting up GUIIconButton for GUI checkbox ", checkbox_name);
ret = false;
}
- if (checkbox.get_font() != nullptr) {
- const StringName font_file = Utilities::std_to_godot_string(checkbox.get_font()->get_fontname());
- const Ref<Font> font = args.asset_manager.get_font(font_file);
- if (font.is_valid()) {
- static const StringName font_theme = "font";
- godot_button->add_theme_font_override(font_theme, font);
- } else {
- UtilityFunctions::push_error("Failed to load font \"", font_file, "\" for GUI checkbox ", checkbox_name);
- ret = false;
- }
+ gui_icon_button->set_text(Utilities::std_to_godot_string(checkbox.get_text()));
- static const std::vector<StringName> checkbox_font_themes {
- "font_color", "font_hover_color", "font_hover_pressed_color", "font_pressed_color", "font_disabled_color"
- };
- const Color colour = Utilities::to_godot_color(checkbox.get_font()->get_colour());
- for (StringName const& theme_name : checkbox_font_themes) {
- godot_button->add_theme_color_override(theme_name, colour);
- }
+ if (checkbox.get_font() != nullptr) {
+ ret &= gui_icon_button->set_gfx_font(checkbox.get_font()) == OK;
}
- args.result = godot_button;
+ args.result = gui_icon_button;
return ret;
}
@@ -615,8 +426,14 @@ static bool generate_texteditbox(generate_gui_args_t&& args) {
Ref<ImageTexture> texture = args.asset_manager.get_texture(texture_file);
if (texture.is_valid()) {
- static const StringName normal_theme = "normal";
- ret &= add_theme_stylebox(godot_line_edit, normal_theme, texture, border_size);
+ Ref<StyleBoxTexture> stylebox = AssetManager::make_stylebox_texture(texture, border_size);
+ if (stylebox.is_valid()) {
+ static const StringName normal_theme = "normal";
+ godot_line_edit->add_theme_stylebox_override(normal_theme, stylebox);
+ } else {
+ UtilityFunctions::push_error("Failed to make StyleBoxTexture for GUI button ", text_edit_box_name);
+ ret = false;
+ }
} else {
UtilityFunctions::push_error(
"Failed to load texture \"", texture_file, "\" for text edit box \"", text_edit_box_name, "\""
@@ -673,7 +490,16 @@ static bool generate_window(generate_gui_args_t&& args) {
ERR_FAIL_NULL_V_MSG(godot_panel, false, vformat("Failed to create Panel for GUI window %s", window_name));
godot_panel->set_custom_minimum_size(Utilities::to_godot_fvec2(window.get_size()));
- godot_panel->set_self_modulate({ 1.0_real, 1.0_real, 1.0_real, 0.0_real });
+
+ Ref<StyleBoxEmpty> stylebox_empty;
+ stylebox_empty.instantiate();
+ if (stylebox_empty.is_valid()) {
+ static const StringName panel_theme = "panel";
+ godot_panel->add_theme_stylebox_override(panel_theme, stylebox_empty);
+ } else {
+ UtilityFunctions::push_error("Failed to create empty style box for background of GUI window ", window_name);
+ ret = false;
+ }
for (std::unique_ptr<GUI::Element> const& element : window.get_window_elements()) {
Control* node = nullptr;
diff --git a/game/src/Game/GameSession/GameSession.tscn b/game/src/Game/GameSession/GameSession.tscn
index 018aad8..5925f3d 100644
--- a/game/src/Game/GameSession/GameSession.tscn
+++ b/game/src/Game/GameSession/GameSession.tscn
@@ -1,4 +1,4 @@
-[gd_scene load_steps=20 format=3 uid="uid://bgnupcshe1m7r"]
+[gd_scene load_steps=21 format=3 uid="uid://bgnupcshe1m7r"]
[ext_resource type="Script" path="res://src/Game/GameSession/GameSession.gd" id="1_eklvp"]
[ext_resource type="PackedScene" uid="uid://cvl76duuym1wq" path="res://src/Game/MusicConductor/MusicPlayer.tscn" id="2_kt6aa"]
@@ -19,6 +19,7 @@
[ext_resource type="Script" path="res://src/Game/GameSession/NationManagementScreen/TradeMenu.gd" id="10_mv1r6"]
[ext_resource type="Script" path="res://src/Game/GameSession/NationManagementScreen/DiplomacyMenu.gd" id="11_fu7ys"]
[ext_resource type="Script" path="res://src/Game/GameSession/NationManagementScreen/MilitaryMenu.gd" id="12_6h6nc"]
+[ext_resource type="Script" path="res://src/Game/GameSession/Tooltip.gd" id="20_3306e"]
[node name="GameSession" type="Control" node_paths=PackedStringArray("_model_manager", "_game_session_menu")]
editor_description = "SS-102, UI-546"
@@ -156,6 +157,11 @@ offset_left = -150.0
offset_right = 0.0
grow_horizontal = 0
+[node name="Tooltip" type="GUINode" parent="UICanvasLayer/UI"]
+layout_mode = 1
+anchors_preset = 15
+script = ExtResource("20_3306e")
+
[connection signal="detailed_view_changed" from="MapView" to="ModelManager" method="set_visible"]
[connection signal="map_view_camera_changed" from="MapView" to="UICanvasLayer/UI/MapControlPanel" method="_on_map_view_camera_changed"]
[connection signal="game_session_menu_button_pressed" from="UICanvasLayer/UI/MapControlPanel" to="." method="_on_game_session_menu_button_pressed"]
diff --git a/game/src/Game/GameSession/NationManagementScreen/BudgetMenu.gd b/game/src/Game/GameSession/NationManagementScreen/BudgetMenu.gd
index 20eb198..021c9f2 100644
--- a/game/src/Game/GameSession/NationManagementScreen/BudgetMenu.gd
+++ b/game/src/Game/GameSession/NationManagementScreen/BudgetMenu.gd
@@ -35,13 +35,19 @@ var _tariff_val_label : GUILabel
var _diplomatic_balance_label : GUILabel
var _balance_label : GUILabel
-var _lower_class_chart : GFXPieChartTexture
-var _middle_class_chart : GFXPieChartTexture
-var _upper_class_chart : GFXPieChartTexture
-var _debt_chart : GFXPieChartTexture
+var _lower_class_chart : GUIPieChart
+var _middle_class_chart : GUIPieChart
+var _upper_class_chart : GUIPieChart
+var _debt_chart : GUIPieChart
const _screen : NationManagement.Screen = NationManagement.Screen.BUDGET
+# TODO - testing function, should be replaced with calls to SIM which trigger UI updates through gamestate_updated
+func _on_tax_slider_changed(slider : GUIScrollbar, label : GUILabel, tooltip : String, value : int) -> void:
+ label.text = "%s¤" % GUINode.float_to_string_dp(value, 3 if abs(value) < 1000 else 1)
+ slider.set_tooltip_string("%s: §Y%s%%" % [tr(tooltip), GUINode.float_to_string_dp(value, 1)])
+
+
func _ready() -> void:
GameSingleton.gamestate_updated.connect(_update_info)
@@ -49,7 +55,7 @@ func _ready() -> void:
add_gui_element("country_budget", "country_budget")
- var close_button : Button = get_button_from_nodepath(^"./country_budget/close_button")
+ var close_button : GUIIconButton = get_gui_icon_button_from_nodepath(^"./country_budget/close_button")
if close_button:
close_button.pressed.connect(Events.NationManagementScreens.close_nation_management_screen.bind(_screen))
@@ -87,15 +93,24 @@ func _ready() -> void:
# income
var _lower_class_slider : GUIScrollbar = get_gui_scrollbar_from_nodepath(^"./country_budget/tax_0_slider")
if _lower_class_slider and _lower_class_label:
- _lower_class_slider.value_changed.connect(func(value : int) -> void: _lower_class_label.text = "%s¤" % GUINode.float_to_string_dp(value, 3 if abs(value) < 1000 else 1))
+ _lower_class_slider.value_changed.connect(
+ func (value : int) -> void:
+ _on_tax_slider_changed(_lower_class_slider, _lower_class_label, "BUDGET_TAX_POOR", value)
+ )
_lower_class_slider.emit_value_changed()
var _middle_class_slider : GUIScrollbar = get_gui_scrollbar_from_nodepath(^"./country_budget/tax_1_slider")
if _middle_class_slider and _middle_class_label:
- _middle_class_slider.value_changed.connect(func(value : int) -> void: _middle_class_label.text = "%s¤" % GUINode.float_to_string_dp(value, 3 if abs(value) < 1000 else 1))
+ _middle_class_slider.value_changed.connect(
+ func (value : int) -> void:
+ _on_tax_slider_changed(_middle_class_slider, _middle_class_label, "BUDGET_TAX_MIDDLE", value)
+ )
_middle_class_slider.emit_value_changed()
var _upper_class_slider : GUIScrollbar = get_gui_scrollbar_from_nodepath(^"./country_budget/tax_2_slider")
if _upper_class_slider and _upper_class_label:
- _upper_class_slider.value_changed.connect(func(value : int) -> void: _upper_class_label.text = "%s¤" % GUINode.float_to_string_dp(value, 3 if abs(value) < 1000 else 1))
+ _upper_class_slider.value_changed.connect(
+ func (value : int) -> void:
+ _on_tax_slider_changed(_upper_class_slider, _upper_class_label, "BUDGET_TAX_RICH", value)
+ )
_upper_class_slider.emit_value_changed()
# costs
@@ -144,30 +159,30 @@ func _ready() -> void:
_tariff_slider.emit_value_changed()
# debt buttons
- var _tab_takenloans_button : Button = get_button_from_nodepath(^"./country_budget/tab_takenloans")
+ var _tab_takenloans_button : GUIIconButton = get_gui_icon_button_from_nodepath(^"./country_budget/tab_takenloans")
if _tab_takenloans_button:
_tab_takenloans_button.pressed.connect(_switch_loans_tab.bind(true))
- var _tab_givenloans_button : Button = get_button_from_nodepath(^"./country_budget/tab_givenloans")
+ var _tab_givenloans_button : GUIIconButton = get_gui_icon_button_from_nodepath(^"./country_budget/tab_givenloans")
if _tab_givenloans_button:
_tab_givenloans_button.pressed.connect(_switch_loans_tab.bind(false))
- var _debt_sort_country_button : Button = get_button_from_nodepath(^"./country_budget/debt_sort_country")
+ var _debt_sort_country_button : GUIIconButton = get_gui_icon_button_from_nodepath(^"./country_budget/debt_sort_country")
if _debt_sort_country_button:
_debt_sort_country_button.pressed.connect(_sort_loans.bind(true))
- var _debt_sort_amount_button : Button = get_button_from_nodepath(^"./country_budget/debt_sort_amount")
+ var _debt_sort_amount_button : GUIIconButton = get_gui_icon_button_from_nodepath(^"./country_budget/debt_sort_amount")
if _debt_sort_amount_button:
_debt_sort_amount_button.pressed.connect(_sort_loans.bind(false))
- var _take_loan_button : Button = get_button_from_nodepath(^"./country_budget/take_loan")
+ var _take_loan_button : GUIIconButton = get_gui_icon_button_from_nodepath(^"./country_budget/take_loan")
if _take_loan_button:
_take_loan_button.pressed.connect(_take_loan)
- var _repay_loan_button : Button = get_button_from_nodepath(^"./country_budget/repay_loan")
+ var _repay_loan_button : GUIIconButton = get_gui_icon_button_from_nodepath(^"./country_budget/repay_loan")
if _repay_loan_button:
_repay_loan_button.pressed.connect(_repay_loan)
# charts
- _lower_class_chart = get_gfx_pie_chart_texture_from_nodepath(^"./country_budget/chart_0")
- _middle_class_chart = get_gfx_pie_chart_texture_from_nodepath(^"./country_budget/chart_1")
- _upper_class_chart = get_gfx_pie_chart_texture_from_nodepath(^"./country_budget/chart_2")
- _debt_chart = get_gfx_pie_chart_texture_from_nodepath(^"./country_budget/chart_debt")
+ _lower_class_chart = get_gui_pie_chart_from_nodepath(^"./country_budget/chart_0")
+ _middle_class_chart = get_gui_pie_chart_from_nodepath(^"./country_budget/chart_1")
+ _upper_class_chart = get_gui_pie_chart_from_nodepath(^"./country_budget/chart_2")
+ _debt_chart = get_gui_pie_chart_from_nodepath(^"./country_budget/chart_debt")
# TODO - generate strata pop type icons
diff --git a/game/src/Game/GameSession/NationManagementScreen/DiplomacyMenu.gd b/game/src/Game/GameSession/NationManagementScreen/DiplomacyMenu.gd
index fb11a31..0926fbb 100644
--- a/game/src/Game/GameSession/NationManagementScreen/DiplomacyMenu.gd
+++ b/game/src/Game/GameSession/NationManagementScreen/DiplomacyMenu.gd
@@ -11,7 +11,7 @@ func _ready() -> void:
add_gui_element("country_diplomacy", "country_diplomacy")
- var close_button : Button = get_button_from_nodepath(^"./country_diplomacy/close_button")
+ var close_button : GUIIconButton = get_gui_icon_button_from_nodepath(^"./country_diplomacy/close_button")
if close_button:
close_button.pressed.connect(Events.NationManagementScreens.close_nation_management_screen.bind(_screen))
diff --git a/game/src/Game/GameSession/NationManagementScreen/MilitaryMenu.gd b/game/src/Game/GameSession/NationManagementScreen/MilitaryMenu.gd
index f3cc486..d57f0dd 100644
--- a/game/src/Game/GameSession/NationManagementScreen/MilitaryMenu.gd
+++ b/game/src/Game/GameSession/NationManagementScreen/MilitaryMenu.gd
@@ -11,7 +11,7 @@ func _ready() -> void:
add_gui_element("country_military", "country_military")
- var close_button : Button = get_button_from_nodepath(^"./country_military/close_button")
+ var close_button : GUIIconButton = get_gui_icon_button_from_nodepath(^"./country_military/close_button")
if close_button:
close_button.pressed.connect(Events.NationManagementScreens.close_nation_management_screen.bind(_screen))
diff --git a/game/src/Game/GameSession/NationManagementScreen/PoliticsMenu.gd b/game/src/Game/GameSession/NationManagementScreen/PoliticsMenu.gd
index 7237bf5..b6b18a5 100644
--- a/game/src/Game/GameSession/NationManagementScreen/PoliticsMenu.gd
+++ b/game/src/Game/GameSession/NationManagementScreen/PoliticsMenu.gd
@@ -11,7 +11,7 @@ func _ready() -> void:
add_gui_element("country_politics", "country_politics")
- var close_button : Button = get_button_from_nodepath(^"./country_politics/close_button")
+ var close_button : GUIIconButton = get_gui_icon_button_from_nodepath(^"./country_politics/close_button")
if close_button:
close_button.pressed.connect(Events.NationManagementScreens.close_nation_management_screen.bind(_screen))
diff --git a/game/src/Game/GameSession/NationManagementScreen/PopulationMenu.gd b/game/src/Game/GameSession/NationManagementScreen/PopulationMenu.gd
index e078934..eb57387 100644
--- a/game/src/Game/GameSession/NationManagementScreen/PopulationMenu.gd
+++ b/game/src/Game/GameSession/NationManagementScreen/PopulationMenu.gd
@@ -13,20 +13,20 @@ var _province_list_scroll_index : int = 0
var _province_list_types : Array[MenuSingleton.ProvinceListEntry]
var _province_list_indices : PackedInt32Array
var _province_list_panels : Array[Panel]
-var _province_list_button_icons : Array[GFXSpriteTexture]
+var _province_list_buttons : Array[GUIIconButton]
var _province_list_name_labels : Array[GUILabel]
var _province_list_size_labels : Array[GUILabel]
-var _province_list_growth_icons : Array[GFXSpriteTexture]
-var _province_list_colony_buttons : Array[Button]
-var _province_list_national_focus_icons : Array[GFXSpriteTexture]
-var _province_list_expand_icons : Array[GFXSpriteTexture]
+var _province_list_growth_icons : Array[GUIIcon]
+var _province_list_colony_buttons : Array[GUIIconButton]
+var _province_list_national_focus_buttons : Array[GUIIconButton]
+var _province_list_expand_buttons : Array[GUIIconButton]
-var _pop_filter_buttons : Array[Button]
+var _pop_filter_buttons : Array[GUIIconButton]
var _pop_filter_icons : Array[GFXSpriteTexture]
var _pop_filter_selected_icons : Array[GFXButtonStateTexture]
var _pop_filter_hover_icons : Array[GFXButtonStateTexture]
-var _distribution_charts : Array[GFXPieChartTexture]
+var _distribution_charts : Array[GUIPieChart]
var _distribution_lists : Array[GUIListBox]
var _pop_list_scrollbar : GUIScrollbar
@@ -34,30 +34,25 @@ var _pop_list_scroll_index : int = 0
var _pop_list_rows : Array[Panel]
var _pop_list_size_labels : Array[GUILabel]
-var _pop_list_type_buttons : Array[Button]
-var _pop_list_type_icons : Array[GFXSpriteTexture]
-var _pop_list_producing_icons : Array[GFXSpriteTexture]
+var _pop_list_type_buttons : Array[GUIIconButton]
+var _pop_list_producing_icons : Array[GUIIcon]
var _pop_list_culture_labels : Array[GUILabel]
-var _pop_list_religion_icons : Array[GFXSpriteTexture]
+var _pop_list_religion_icons : Array[GUIIcon]
var _pop_list_location_labels : Array[GUILabel]
var _pop_list_militancy_labels : Array[GUILabel]
var _pop_list_consciousness_labels : Array[GUILabel]
-var _pop_list_ideology_charts : Array[GFXPieChartTexture]
-var _pop_list_issues_charts : Array[GFXPieChartTexture]
-var _pop_list_unemployment_progressbars : Array[TextureProgressBar]
+var _pop_list_ideology_charts : Array[GUIPieChart]
+var _pop_list_issues_charts : Array[GUIPieChart]
+var _pop_list_unemployment_progressbars : Array[GUIProgressBar]
var _pop_list_cash_labels : Array[GUILabel]
-var _pop_list_life_needs_progressbars : Array[TextureProgressBar]
-var _pop_list_everyday_needs_progressbars : Array[TextureProgressBar]
-var _pop_list_luxury_needs_progressbars : Array[TextureProgressBar]
-var _pop_list_rebel_texture_rects : Array[TextureRect]
-var _pop_list_rebel_icons : Array[GFXSpriteTexture]
-var _pop_list_social_movement_texture_rects : Array[TextureRect]
-var _pop_list_social_movement_icons : Array[GFXSpriteTexture]
-var _pop_list_political_movement_texture_rects : Array[TextureRect]
-var _pop_list_political_movement_icons : Array[GFXSpriteTexture]
-var _pop_list_national_movement_texture_rects : Array[TextureRect]
-var _pop_list_national_movement_flags : Array[GFXMaskedFlagTexture]
-var _pop_list_size_change_icons : Array[GFXSpriteTexture]
+var _pop_list_life_needs_progressbars : Array[GUIProgressBar]
+var _pop_list_everyday_needs_progressbars : Array[GUIProgressBar]
+var _pop_list_luxury_needs_progressbars : Array[GUIProgressBar]
+var _pop_list_rebel_icons : Array[GUIIcon]
+var _pop_list_social_movement_icons : Array[GUIIcon]
+var _pop_list_political_movement_icons : Array[GUIIcon]
+var _pop_list_national_movement_flags : Array[GUIMaskedFlag]
+var _pop_list_size_change_icons : Array[GUIIcon]
var _pop_list_literacy_labels : Array[GUILabel]
func _ready() -> void:
@@ -72,7 +67,7 @@ func _ready() -> void:
add_gui_element(_scene_name, "country_pop")
- var close_button : Button = get_button_from_nodepath(^"./country_pop/close_button")
+ var close_button : GUIIconButton = get_gui_icon_button_from_nodepath(^"./country_pop/close_button")
if close_button:
close_button.pressed.connect(Events.NationManagementScreens.close_nation_management_screen.bind(_screen))
@@ -91,13 +86,13 @@ func _generate_province_list_row(index : int, type : MenuSingleton.ProvinceListE
_province_list_types.push_back(MenuSingleton.LIST_ENTRY_NONE)
_province_list_indices.push_back(-1)
_province_list_panels.push_back(null)
- _province_list_button_icons.push_back(null)
+ _province_list_buttons.push_back(null)
_province_list_name_labels.push_back(null)
_province_list_size_labels.push_back(null)
_province_list_growth_icons.push_back(null)
_province_list_colony_buttons.push_back(null)
- _province_list_national_focus_icons.push_back(null)
- _province_list_expand_icons.push_back(null)
+ _province_list_national_focus_buttons.push_back(null)
+ _province_list_expand_buttons.push_back(null)
if _province_list_types[index] == type:
return OK
@@ -109,13 +104,13 @@ func _generate_province_list_row(index : int, type : MenuSingleton.ProvinceListE
_province_list_types[index] = MenuSingleton.LIST_ENTRY_NONE
_province_list_indices[index] = -1
_province_list_panels[index] = null
- _province_list_button_icons[index] = null
+ _province_list_buttons[index] = null
_province_list_name_labels[index] = null
_province_list_size_labels[index] = null
_province_list_growth_icons[index] = null
_province_list_colony_buttons[index] = null
- _province_list_national_focus_icons[index] = null
- _province_list_expand_icons[index] = null
+ _province_list_national_focus_buttons[index] = null
+ _province_list_expand_buttons[index] = null
if type == MenuSingleton.LIST_ENTRY_NONE:
return OK
@@ -135,33 +130,29 @@ func _generate_province_list_row(index : int, type : MenuSingleton.ProvinceListE
_province_list_panels[index] = entry_panel
- var base_button : Button = GUINode.get_button_from_node(entry_panel.get_node(^"./poplistbutton"))
- if base_button:
- base_button.pressed.connect(
+ _province_list_buttons[index] = GUINode.get_gui_icon_button_from_node(entry_panel.get_node(^"./poplistbutton"))
+ if _province_list_buttons[index]:
+ _province_list_buttons[index].pressed.connect(
func() -> void: MenuSingleton.population_menu_select_province_list_entry(_province_list_indices[index])
)
- _province_list_button_icons[index] = GUINode.get_gfx_sprite_texture_from_node(base_button)
_province_list_name_labels[index] = GUINode.get_gui_label_from_node(entry_panel.get_node(^"./poplist_name"))
_province_list_size_labels[index] = GUINode.get_gui_label_from_node(entry_panel.get_node(^"./poplist_numpops"))
- _province_list_growth_icons[index] = GUINode.get_gfx_sprite_texture_from_node(entry_panel.get_node(^"./growth_indicator"))
+ _province_list_growth_icons[index] = GUINode.get_gui_icon_from_node(entry_panel.get_node(^"./growth_indicator"))
if type == MenuSingleton.LIST_ENTRY_STATE:
- _province_list_colony_buttons[index] = GUINode.get_button_from_node(entry_panel.get_node(^"./colonial_state_icon"))
+ _province_list_colony_buttons[index] = GUINode.get_gui_icon_button_from_node(entry_panel.get_node(^"./colonial_state_icon"))
- var national_focus_button : Button = GUINode.get_button_from_node(entry_panel.get_node(^"./state_focus"))
- if national_focus_button:
- # TODO - connect national focus button to national focus selection submenu
- _province_list_national_focus_icons[index] = GUINode.get_gfx_sprite_texture_from_node(national_focus_button)
+ # TODO - connect national focus button to national focus selection submenu
+ _province_list_national_focus_buttons[index] = GUINode.get_gui_icon_button_from_node(entry_panel.get_node(^"./state_focus"))
- var expand_button : Button = GUINode.get_button_from_node(entry_panel.get_node(^"./expand"))
- if expand_button:
- expand_button.pressed.connect(
+ _province_list_expand_buttons[index] = GUINode.get_gui_icon_button_from_node(entry_panel.get_node(^"./expand"))
+ if _province_list_expand_buttons[index]:
+ _province_list_expand_buttons[index].pressed.connect(
func() -> void: MenuSingleton.population_menu_toggle_expanded(_province_list_indices[index])
)
- _province_list_expand_icons[index] = GUINode.get_gfx_sprite_texture_from_node(expand_button)
_province_listbox.add_child(entry_panel)
_province_listbox.move_child(entry_panel, index)
@@ -206,7 +197,7 @@ func _setup_sort_buttons() -> void:
]
for button_info : Array in sort_button_info:
- var sort_button : Button = get_button_from_nodepath(button_info[0])
+ var sort_button : GUIIconButton = get_gui_icon_button_from_nodepath(button_info[0])
if sort_button:
if button_info[1]:
sort_button.set_text("")
@@ -223,7 +214,7 @@ func _setup_pop_filter_buttons() -> void:
var pop_filter_step : Vector2 = GUINode.get_gui_position(_scene_name, "popfilter_offset")
for index : int in pop_filter_sprite_indices.size():
- var pop_filter_button : Button = GUINode.get_button_from_node(GUINode.generate_gui_element(_scene_name, "pop_filter_button"))
+ var pop_filter_button : GUIIconButton = GUINode.get_gui_icon_button_from_node(GUINode.generate_gui_element(_scene_name, "pop_filter_button"))
var pop_filter_icon : GFXSpriteTexture = null
var pop_filter_selected_icon : GFXButtonStateTexture = null
var pop_filter_hover_icon : GFXButtonStateTexture = null
@@ -232,7 +223,7 @@ func _setup_pop_filter_buttons() -> void:
_pop_screen_panel.add_child(pop_filter_button)
pop_filter_button.set_position(pop_filter_start + pop_filter_step * index)
pop_filter_button.pressed.connect(MenuSingleton.population_menu_toggle_pop_filter.bind(index))
- pop_filter_icon = GUINode.get_gfx_sprite_texture_from_node(pop_filter_button)
+ pop_filter_icon = pop_filter_button.get_gfx_sprite_texture()
if pop_filter_icon:
pop_filter_icon.set_icon_index(pop_filter_sprite_indices[index])
@@ -244,11 +235,11 @@ func _setup_pop_filter_buttons() -> void:
_pop_filter_selected_icons.push_back(pop_filter_selected_icon)
_pop_filter_hover_icons.push_back(pop_filter_hover_icon)
- var select_all_button : Button = get_button_from_nodepath(^"./country_pop/popfilter_ALL")
+ var select_all_button : GUIIconButton = get_gui_icon_button_from_nodepath(^"./country_pop/popfilter_ALL")
if select_all_button:
select_all_button.pressed.connect(MenuSingleton.population_menu_select_all_pop_filters)
- var deselect_all_button : Button = get_button_from_nodepath(^"./country_pop/popfilter_DESELECT_ALL")
+ var deselect_all_button : GUIIconButton = get_gui_icon_button_from_nodepath(^"./country_pop/popfilter_DESELECT_ALL")
if deselect_all_button:
deselect_all_button.pressed.connect(MenuSingleton.population_menu_deselect_all_pop_filters)
@@ -266,7 +257,7 @@ func _setup_distribution_windows() -> void:
for index : int in distribution_names.size():
var distribution_panel : Panel = GUINode.generate_gui_element(_scene_name, "distribution_window")
- var distribution_chart : GFXPieChartTexture = null
+ var distribution_chart : GUIPieChart = null
var distribution_list : GUIListBox = null
if distribution_panel:
@@ -277,7 +268,7 @@ func _setup_distribution_windows() -> void:
if name_label:
name_label.set_text(distribution_names[index])
- distribution_chart = GUINode.get_gfx_pie_chart_texture_from_node(distribution_panel.get_node(^"./chart"))
+ distribution_chart = GUINode.get_gui_pie_chart_from_node(distribution_panel.get_node(^"./chart"))
distribution_list = GUINode.get_gui_listbox_from_node(distribution_panel.get_node(^"./member_names"))
_distribution_charts.push_back(distribution_chart)
@@ -320,77 +311,77 @@ func _setup_pop_list() -> void:
_pop_list_size_labels.push_back(GUINode.get_gui_label_from_node(pop_row_panel.get_node(^"./pop_size")))
- var pop_type_button : Button = GUINode.get_button_from_node(pop_row_panel.get_node(^"./pop_type"))
+ var pop_type_button : GUIIconButton = GUINode.get_gui_icon_button_from_node(pop_row_panel.get_node(^"./pop_type"))
# TODO - open pop details menu on pop type button press
_pop_list_type_buttons.push_back(pop_type_button)
- _pop_list_type_icons.push_back(GUINode.get_gfx_sprite_texture_from_node(pop_type_button))
-
- _pop_list_producing_icons.push_back(GUINode.get_gfx_sprite_texture_from_node(pop_row_panel.get_node(^"./pop_producing_icon")))
+ _pop_list_producing_icons.push_back(GUINode.get_gui_icon_from_node(pop_row_panel.get_node(^"./pop_producing_icon")))
var culture_label : GUILabel = GUINode.get_gui_label_from_node(pop_row_panel.get_node(^"./pop_nation"))
_pop_list_culture_labels.push_back(culture_label)
+ if culture_label:
+ culture_label.set_mouse_filter(MOUSE_FILTER_PASS)
- _pop_list_religion_icons.push_back(GUINode.get_gfx_sprite_texture_from_node(pop_row_panel.get_node(^"./pop_religion")))
+ var religion_icon : GUIIcon = GUINode.get_gui_icon_from_node(pop_row_panel.get_node(^"./pop_religion"))
+ _pop_list_religion_icons.push_back(religion_icon)
+ if religion_icon:
+ religion_icon.set_mouse_filter(MOUSE_FILTER_PASS)
var location_label : GUILabel = GUINode.get_gui_label_from_node(pop_row_panel.get_node(^"./pop_location"))
_pop_list_location_labels.push_back(location_label)
+ if location_label:
+ location_label.set_mouse_filter(MOUSE_FILTER_PASS)
- _pop_list_militancy_labels.push_back(GUINode.get_gui_label_from_node(pop_row_panel.get_node(^"./pop_mil")))
+ var militancy_label : GUILabel = GUINode.get_gui_label_from_node(pop_row_panel.get_node(^"./pop_mil"))
+ _pop_list_militancy_labels.push_back(militancy_label)
+ if militancy_label:
+ militancy_label.set_mouse_filter(MOUSE_FILTER_PASS)
- _pop_list_consciousness_labels.push_back(GUINode.get_gui_label_from_node(pop_row_panel.get_node(^"./pop_con")))
+ var consciousness_label : GUILabel = GUINode.get_gui_label_from_node(pop_row_panel.get_node(^"./pop_con"))
+ _pop_list_consciousness_labels.push_back(consciousness_label)
+ if consciousness_label:
+ consciousness_label.set_mouse_filter(MOUSE_FILTER_PASS)
- _pop_list_ideology_charts.push_back(GUINode.get_gfx_pie_chart_texture_from_node(pop_row_panel.get_node(^"./pop_ideology")))
+ _pop_list_ideology_charts.push_back(GUINode.get_gui_pie_chart_from_node(pop_row_panel.get_node(^"./pop_ideology")))
- _pop_list_issues_charts.push_back(GUINode.get_gfx_pie_chart_texture_from_node(pop_row_panel.get_node(^"./pop_issues")))
+ _pop_list_issues_charts.push_back(GUINode.get_gui_pie_chart_from_node(pop_row_panel.get_node(^"./pop_issues")))
- _pop_list_unemployment_progressbars.push_back(GUINode.get_progress_bar_from_node(pop_row_panel.get_node(^"./pop_unemployment_bar")))
+ _pop_list_unemployment_progressbars.push_back(GUINode.get_gui_progress_bar_from_node(pop_row_panel.get_node(^"./pop_unemployment_bar")))
- _pop_list_cash_labels.push_back(GUINode.get_gui_label_from_node(pop_row_panel.get_node(^"./pop_cash")))
+ var cash_label : GUILabel = GUINode.get_gui_label_from_node(pop_row_panel.get_node(^"./pop_cash"))
+ _pop_list_cash_labels.push_back(cash_label)
+ if cash_label:
+ cash_label.set_mouse_filter(MOUSE_FILTER_PASS)
- var pop_list_life_needs_progressbar : TextureProgressBar = GUINode.get_progress_bar_from_node(pop_row_panel.get_node(^"./lifeneed_progress"))
+ var pop_list_life_needs_progressbar : GUIProgressBar = GUINode.get_gui_progress_bar_from_node(pop_row_panel.get_node(^"./lifeneed_progress"))
+ _pop_list_life_needs_progressbars.push_back(pop_list_life_needs_progressbar)
if pop_list_life_needs_progressbar:
pop_list_life_needs_progressbar.position += Vector2(1, 0)
- _pop_list_life_needs_progressbars.push_back(pop_list_life_needs_progressbar)
- var pop_list_everyday_needs_progressbar : TextureProgressBar = GUINode.get_progress_bar_from_node(pop_row_panel.get_node(^"./eveneed_progress"))
+ var pop_list_everyday_needs_progressbar : GUIProgressBar = GUINode.get_gui_progress_bar_from_node(pop_row_panel.get_node(^"./eveneed_progress"))
+ _pop_list_everyday_needs_progressbars.push_back(pop_list_everyday_needs_progressbar)
if pop_list_everyday_needs_progressbar:
pop_list_everyday_needs_progressbar.position += Vector2(1, 0)
- _pop_list_everyday_needs_progressbars.push_back(pop_list_everyday_needs_progressbar)
- _pop_list_luxury_needs_progressbars.push_back(GUINode.get_progress_bar_from_node(pop_row_panel.get_node(^"./luxneed_progress")))
+ _pop_list_luxury_needs_progressbars.push_back(GUINode.get_gui_progress_bar_from_node(pop_row_panel.get_node(^"./luxneed_progress")))
- var pop_list_rebel_texture_rect : TextureRect = GUINode.get_texture_rect_from_node(pop_row_panel.get_node(^"./pop_revolt"))
- _pop_list_rebel_texture_rects.push_back(pop_list_rebel_texture_rect)
- if pop_list_rebel_texture_rect:
- _pop_list_rebel_icons.push_back(GUINode.get_gfx_sprite_texture_from_node(pop_list_rebel_texture_rect))
- else:
- _pop_list_rebel_icons.push_back(null)
+ _pop_list_rebel_icons.push_back(GUINode.get_gui_icon_from_node(pop_row_panel.get_node(^"./pop_revolt")))
- var pop_list_social_movement_texture_rect : TextureRect = GUINode.get_texture_rect_from_node(pop_row_panel.get_node(^"./pop_movement_social"))
- _pop_list_social_movement_texture_rects.push_back(pop_list_social_movement_texture_rect)
- if pop_list_social_movement_texture_rect:
- _pop_list_social_movement_icons.push_back(GUINode.get_gfx_sprite_texture_from_node(pop_list_social_movement_texture_rect))
- else:
- _pop_list_social_movement_icons.push_back(null)
+ _pop_list_social_movement_icons.push_back(GUINode.get_gui_icon_from_node(pop_row_panel.get_node(^"./pop_movement_social")))
- var pop_list_political_movement_texture_rect : TextureRect = GUINode.get_texture_rect_from_node(pop_row_panel.get_node(^"./pop_movement_political"))
- _pop_list_political_movement_texture_rects.push_back(pop_list_political_movement_texture_rect)
- if pop_list_political_movement_texture_rect:
- _pop_list_political_movement_icons.push_back(GUINode.get_gfx_sprite_texture_from_node(pop_list_political_movement_texture_rect))
- else:
- _pop_list_political_movement_icons.push_back(null)
+ _pop_list_political_movement_icons.push_back(GUINode.get_gui_icon_from_node(pop_row_panel.get_node(^"./pop_movement_political")))
- var pop_list_national_movement_texture_rect : TextureRect = GUINode.get_texture_rect_from_node(pop_row_panel.get_node(^"./pop_movement_flag"))
- _pop_list_national_movement_texture_rects.push_back(pop_list_national_movement_texture_rect)
- if pop_list_national_movement_texture_rect:
- _pop_list_national_movement_flags.push_back(GUINode.get_gfx_masked_flag_texture_from_node(pop_list_national_movement_texture_rect))
- else:
- _pop_list_national_movement_flags.push_back(null)
+ _pop_list_national_movement_flags.push_back(GUINode.get_gui_masked_flag_from_node(pop_row_panel.get_node(^"./pop_movement_flag")))
- _pop_list_size_change_icons.push_back(GUINode.get_gfx_sprite_texture_from_node(pop_row_panel.get_node(^"./growth_indicator")))
+ var size_change_icon : GUIIcon = GUINode.get_gui_icon_from_node(pop_row_panel.get_node(^"./growth_indicator"))
+ _pop_list_size_change_icons.push_back(size_change_icon)
+ if size_change_icon:
+ size_change_icon.set_mouse_filter(MOUSE_FILTER_PASS)
- _pop_list_literacy_labels.push_back(GUINode.get_gui_label_from_node(pop_row_panel.get_node(^"./pop_literacy")))
+ var literacy_label : GUILabel = GUINode.get_gui_label_from_node(pop_row_panel.get_node(^"./pop_literacy"))
+ _pop_list_literacy_labels.push_back(literacy_label)
+ if literacy_label:
+ literacy_label.set_mouse_filter(MOUSE_FILTER_PASS)
func _notification(what : int) -> void:
match what:
@@ -450,8 +441,8 @@ func _update_province_list(scroll_index : int = -1) -> void:
_province_list_indices[index] = province_list_info[index_key]
- if _province_list_button_icons[index]:
- _province_list_button_icons[index].set_icon_index(1 + int(province_list_info[selected_key]))
+ if _province_list_buttons[index]:
+ _province_list_buttons[index].set_icon_index(1 + int(province_list_info[selected_key]))
if _province_list_name_labels[index]:
_province_list_name_labels[index].set_text(
@@ -469,10 +460,10 @@ func _update_province_list(scroll_index : int = -1) -> void:
if _province_list_colony_buttons[index]:
_province_list_colony_buttons[index].set_visible(province_list_info[colony_key])
- if _province_list_expand_icons[index]:
- _province_list_expand_icons[index].set_icon_index(1 + int(province_list_info[expanded_key]))
+ if _province_list_expand_buttons[index]:
+ _province_list_expand_buttons[index].set_icon_index(1 + int(province_list_info[expanded_key]))
- # TODO - set _province_list_national_focus_icons[index]
+ # TODO - set _province_list_national_focus_buttons[index]
# Clear any excess rows
for index : int in range(province_list_info_list.size(), _province_list_types.size()):
@@ -493,7 +484,7 @@ func _update_pop_filters() -> void:
var pop_filter_info : Dictionary = pop_filter_info_list[index]
- var pop_filter_button : Button = _pop_filter_buttons[index]
+ var pop_filter_button : GUIIconButton = _pop_filter_buttons[index]
if not pop_filter_button:
continue
pop_filter_button.disabled = pop_filter_info[pop_filter_count_key] <= 0
@@ -542,9 +533,13 @@ func _update_distributions():
var distribution_row : Dictionary = distribution_info[list_index]
- var colour_icon_rect : TextureRect = GUINode.get_texture_rect_from_node(child.get_node(^"./legend_color"))
- if colour_icon_rect:
- colour_icon_rect.set_modulate(distribution_row[slice_colour_key])
+ var colour_icon : GUIIcon = GUINode.get_gui_icon_from_node(child.get_node(^"./legend_color"))
+ if colour_icon:
+ colour_icon.set_modulate(distribution_row[slice_colour_key])
+ colour_icon.set_mouse_filter(MOUSE_FILTER_PASS)
+ colour_icon.set_tooltip_string_and_substitution_dict("§Y$ID$§!: $PC$%", {
+ "ID": distribution_row[slice_identifier_key], "PC": GUINode.float_to_string_dp(distribution_row[slice_weight_key] * 100.0, 2)
+ })
var identifier_label : GUILabel = GUINode.get_gui_label_from_node(child.get_node(^"./legend_title"))
if identifier_label:
@@ -592,53 +587,89 @@ func _update_pop_list() -> void:
if _pop_list_size_labels[index]:
_pop_list_size_labels[index].set_text(GUINode.int_to_string_suffixed(pop_row[pop_size_key]))
- if _pop_list_type_icons[index]:
- _pop_list_type_icons[index].set_icon_index(pop_row[pop_type_icon_key])
+ if _pop_list_type_buttons[index]:
+ _pop_list_type_buttons[index].set_icon_index(pop_row[pop_type_icon_key])
+ # TODO - replace with actual poptype
+ _pop_list_type_buttons[index].set_tooltip_string("Pop Type #%d" % pop_row[pop_type_icon_key])
if _pop_list_culture_labels[index]:
_pop_list_culture_labels[index].set_text(pop_row[pop_culture_key])
+ _pop_list_culture_labels[index].set_tooltip_string("NO_ASSIM_NOW")
if _pop_list_religion_icons[index]:
_pop_list_religion_icons[index].set_icon_index(pop_row[pop_religion_icon_key])
+ # TODO - replace with actual religion
+ _pop_list_religion_icons[index].set_tooltip_string("Religion #%d" % pop_row[pop_religion_icon_key])
if _pop_list_location_labels[index]:
- _pop_list_location_labels[index].set_text(GUINode.format_province_name(pop_row.get(pop_location_key, "")))
+ var province_name : String = GUINode.format_province_name(pop_row.get(pop_location_key, ""))
+ _pop_list_location_labels[index].set_text(province_name)
+ _pop_list_location_labels[index].set_tooltip_string(province_name)
if _pop_list_militancy_labels[index]:
_pop_list_militancy_labels[index].set_text(GUINode.float_to_string_dp(pop_row[pop_militancy_key], 2))
+ # TODO - test tooltip, add monthly change + source breakdown
+ _pop_list_militancy_labels[index].set_tooltip_string("POP_MIL_TOTAL")
if _pop_list_consciousness_labels[index]:
_pop_list_consciousness_labels[index].set_text(GUINode.float_to_string_dp(pop_row[pop_consciousness_key], 2))
+ # TODO - test tooltip, add monthly change + source breakdown
+ _pop_list_consciousness_labels[index].set_tooltip_string("POP_CON_TOTAL")
if _pop_list_ideology_charts[index]:
_pop_list_ideology_charts[index].set_slices_array(pop_row[pop_ideology_key])
if _pop_list_issues_charts[index]:
_pop_list_issues_charts[index].set_slices_array(pop_row[pop_issues_key])
if _pop_list_unemployment_progressbars[index]:
- _pop_list_unemployment_progressbars[index].set_value_no_signal(pop_row[pop_unemployment_key])
+ var unemployment : float = pop_row[pop_unemployment_key]
+ _pop_list_unemployment_progressbars[index].set_value_no_signal(unemployment)
+ _pop_list_unemployment_progressbars[index].set_tooltip_string("%s: §Y%s%%" % [
+ tr("UNEMPLOYMENT"), GUINode.float_to_string_dp(unemployment * 100.0, 3)
+ ])
if _pop_list_cash_labels[index]:
- _pop_list_cash_labels[index].set_text(GUINode.float_to_string_dp(pop_row[pop_cash_key], 2))
+ _pop_list_cash_labels[index].set_text("%s¤" % GUINode.float_to_string_dp(pop_row[pop_cash_key], 2))
+ _pop_list_cash_labels[index].set_tooltip_string_and_substitution_dict("POP_DAILY_MONEY", {
+ "VAL": GUINode.float_to_string_dp(1.23, 2)
+ })
if _pop_list_life_needs_progressbars[index]:
- _pop_list_life_needs_progressbars[index].set_value_no_signal(pop_row[pop_life_needs_key])
+ var life_needs : float = pop_row[pop_life_needs_key]
+ _pop_list_life_needs_progressbars[index].set_value_no_signal(life_needs)
+ _pop_list_life_needs_progressbars[index].set_tooltip_string_and_substitution_dict("GETTING_NEEDS", {
+ "NEED": "LIFE_NEEDS", "VAL": GUINode.float_to_string_dp(life_needs * 100.0, 1)
+ })
if _pop_list_everyday_needs_progressbars[index]:
- _pop_list_everyday_needs_progressbars[index].set_value_no_signal(pop_row[pop_everyday_needs_key])
+ var everyday_needs : float = pop_row[pop_everyday_needs_key]
+ _pop_list_everyday_needs_progressbars[index].set_value_no_signal(everyday_needs)
+ _pop_list_everyday_needs_progressbars[index].set_tooltip_string_and_substitution_dict("GETTING_NEEDS", {
+ "NEED": "EVERYDAY_NEEDS", "VAL": GUINode.float_to_string_dp(everyday_needs * 100.0, 1)
+ })
if _pop_list_luxury_needs_progressbars[index]:
- _pop_list_luxury_needs_progressbars[index].set_value_no_signal(pop_row[pop_luxury_needs_key])
- if _pop_list_rebel_texture_rects[index]:
+ var luxury_needs : float = pop_row[pop_luxury_needs_key]
+ _pop_list_luxury_needs_progressbars[index].set_value_no_signal(luxury_needs)
+ _pop_list_luxury_needs_progressbars[index].set_tooltip_string_and_substitution_dict("GETTING_NEEDS", {
+ "NEED": "LUXURY_NEEDS", "VAL": GUINode.float_to_string_dp(luxury_needs * 100.0, 1)
+ })
+ if _pop_list_rebel_icons[index]:
var rebel_icon : int = pop_row.get(pop_rebel_icon_key, 0)
if rebel_icon > 0:
- if _pop_list_rebel_icons[index]:
- _pop_list_rebel_icons[index].set_icon_index(rebel_icon)
- _pop_list_rebel_texture_rects[index].show()
+ _pop_list_rebel_icons[index].set_icon_index(rebel_icon)
+ _pop_list_rebel_icons[index].show()
else:
- _pop_list_rebel_texture_rects[index].hide()
+ _pop_list_rebel_icons[index].hide()
# TODO - handle social/political reform and country rebels
- if _pop_list_social_movement_texture_rects[index]:
- _pop_list_social_movement_texture_rects[index].hide()
- if _pop_list_political_movement_texture_rects[index]:
- _pop_list_political_movement_texture_rects[index].hide()
- if _pop_list_national_movement_texture_rects[index]:
- _pop_list_national_movement_texture_rects[index].hide()
+ if _pop_list_social_movement_icons[index]:
+ _pop_list_social_movement_icons[index].hide()
+ if _pop_list_political_movement_icons[index]:
+ _pop_list_political_movement_icons[index].hide()
+ if _pop_list_national_movement_flags[index]:
+ _pop_list_national_movement_flags[index].hide()
if _pop_list_size_change_icons[index]:
- _pop_list_size_change_icons[index].set_icon_index(get_growth_icon_index(pop_row[pop_size_change_key]))
+ var pop_change : int = pop_row[pop_size_change_key]
+ _pop_list_size_change_icons[index].set_icon_index(get_growth_icon_index(pop_change))
+ _pop_list_size_change_icons[index].set_tooltip_string("%s §%s%s" % [
+ tr("POPULATION_CHANGED_BY"), "G+" if pop_change > 0 else "Y+" if pop_change == 0 else "R", str(pop_change)
+ ])
if _pop_list_literacy_labels[index]:
_pop_list_literacy_labels[index].set_text("%s%%" % GUINode.float_to_string_dp(pop_row[pop_literacy_key], 2))
+ _pop_list_literacy_labels[index].set_tooltip_string("%s: §G%s%%" % [
+ tr("LIT_CHANGE"), GUINode.float_to_string_dp(pop_row[pop_literacy_key] / 64.0, 2)
+ ])
_pop_list_rows[index].show()
else:
diff --git a/game/src/Game/GameSession/NationManagementScreen/ProductionMenu.gd b/game/src/Game/GameSession/NationManagementScreen/ProductionMenu.gd
index 938f8e7..25a60df 100644
--- a/game/src/Game/GameSession/NationManagementScreen/ProductionMenu.gd
+++ b/game/src/Game/GameSession/NationManagementScreen/ProductionMenu.gd
@@ -11,7 +11,7 @@ func _ready() -> void:
add_gui_element("country_production", "country_production")
- var close_button : Button = get_button_from_nodepath(^"./country_production/close_button")
+ var close_button : GUIIconButton = get_gui_icon_button_from_nodepath(^"./country_production/close_button")
if close_button:
close_button.pressed.connect(Events.NationManagementScreens.close_nation_management_screen.bind(_screen))
diff --git a/game/src/Game/GameSession/NationManagementScreen/TechnologyMenu.gd b/game/src/Game/GameSession/NationManagementScreen/TechnologyMenu.gd
index a80ed1e..97c3390 100644
--- a/game/src/Game/GameSession/NationManagementScreen/TechnologyMenu.gd
+++ b/game/src/Game/GameSession/NationManagementScreen/TechnologyMenu.gd
@@ -11,7 +11,7 @@ func _ready() -> void:
add_gui_element("country_technology", "country_technology")
- var close_button : Button = get_button_from_nodepath(^"./country_technology/close_button")
+ var close_button : GUIIconButton = get_gui_icon_button_from_nodepath(^"./country_technology/close_button")
if close_button:
close_button.pressed.connect(Events.NationManagementScreens.close_nation_management_screen.bind(_screen))
diff --git a/game/src/Game/GameSession/NationManagementScreen/TradeMenu.gd b/game/src/Game/GameSession/NationManagementScreen/TradeMenu.gd
index 775f31a..2454b96 100644
--- a/game/src/Game/GameSession/NationManagementScreen/TradeMenu.gd
+++ b/game/src/Game/GameSession/NationManagementScreen/TradeMenu.gd
@@ -11,7 +11,7 @@ func _ready() -> void:
add_gui_element("country_trade", "country_trade")
- var close_button : Button = get_button_from_nodepath(^"./country_trade/close_button")
+ var close_button : GUIIconButton = get_gui_icon_button_from_nodepath(^"./country_trade/close_button")
if close_button:
close_button.pressed.connect(Events.NationManagementScreens.close_nation_management_screen.bind(_screen))
diff --git a/game/src/Game/GameSession/ProvinceOverviewPanel.gd b/game/src/Game/GameSession/ProvinceOverviewPanel.gd
index f2669c0..66fd463 100644
--- a/game/src/Game/GameSession/ProvinceOverviewPanel.gd
+++ b/game/src/Game/GameSession/ProvinceOverviewPanel.gd
@@ -3,32 +3,31 @@ extends GUINode
# Header
var _province_name_label : GUILabel
var _state_name_label : GUILabel
-var _slave_status_icon : TextureRect
-var _colony_status_button : Button
-var _colony_status_button_texture : GFXSpriteTexture
+var _slave_status_icon : GUIIcon
+var _colony_status_button : GUIIconButton
var _administrative_percentage_label : GUILabel
var _owner_percentage_label : GUILabel
var _province_modifiers_overlapping_elements_box : GUIOverlappingElementsBox
-var _terrain_type_texture : GFXSpriteTexture
-var _life_rating_bar : TextureProgressBar
-var _controller_flag_texture : GFXMaskedFlagTexture
+var _terrain_type_icon : GUIIcon
+var _life_rating_bar : GUIProgressBar
+var _controller_flag : GUIMaskedFlag
# Statistics
-var _rgo_icon_texture : GFXSpriteTexture
+var _rgo_icon : GUIIcon
var _rgo_produced_label : GUILabel
var _rgo_income_label : GUILabel
-var _rgo_employment_percentage_texture : GFXSpriteTexture
+var _rgo_employment_percentage_icon : GUIIcon
var _rgo_employment_population_label : GUILabel
var _rgo_employment_percentage_label : GUILabel
var _crime_name_label : GUILabel
-var _crime_icon_texture : GFXSpriteTexture
+var _crime_icon : GUIIcon
var _crime_fighting_label : GUILabel
var _total_population_label : GUILabel
var _migration_label : GUILabel
var _population_growth_label : GUILabel
-var _pop_types_piechart : GFXPieChartTexture
-var _pop_ideologies_piechart : GFXPieChartTexture
-var _pop_cultures_piechart : GFXPieChartTexture
+var _pop_types_piechart : GUIPieChart
+var _pop_ideologies_piechart : GUIPieChart
+var _pop_cultures_piechart : GUIPieChart
var _supply_limit_label : GUILabel
var _cores_overlapping_elements_box : GUIOverlappingElementsBox
@@ -44,10 +43,10 @@ class BuildingSlot:
var _slot_index : int
var _slot_node : Control
- var _building_icon : GFXSpriteTexture
- var _expand_button : Button
- var _expanding_icon : TextureRect
- var _expanding_progress_bar : TextureProgressBar
+ var _building_icon : GUIIcon
+ var _expand_button : GUIIconButton
+ var _expanding_icon : GUIIcon
+ var _expanding_progress_bar : GUIProgressBar
var _expanding_label : GUILabel
func _init(new_slot_index : int, new_slot_node : Control) -> void:
@@ -64,18 +63,18 @@ class BuildingSlot:
var icon := _slot_node.get_node("build_icon%d" % icon_index)
if icon:
if icon_index == _slot_index:
- _building_icon = GUINode.get_gfx_sprite_texture_from_node(icon)
+ _building_icon = GUINode.get_gui_icon_from_node(icon)
else:
icon.hide()
var building_name := GUINode.get_gui_label_from_node(_slot_node.get_node(^"./description"))
if building_name:
building_name.text = MenuSingleton.get_province_building_identifier(_slot_index)
- _expand_button = GUINode.get_button_from_node(_slot_node.get_node(^"./expand"))
+ _expand_button = GUINode.get_gui_icon_button_from_node(_slot_node.get_node(^"./expand"))
if _expand_button:
_expand_button.pressed.connect(func() -> void: MenuSingleton.expand_selected_province_building(_slot_index))
- _expanding_icon = GUINode.get_texture_rect_from_node(_slot_node.get_node(^"./underconstruction_icon"))
- _expanding_progress_bar = GUINode.get_progress_bar_from_node(_slot_node.get_node(^"./building_progress"))
+ _expanding_icon = GUINode.get_gui_icon_from_node(_slot_node.get_node(^"./underconstruction_icon"))
+ _expanding_progress_bar = GUINode.get_gui_progress_bar_from_node(_slot_node.get_node(^"./building_progress"))
if _expanding_progress_bar:
_expanding_progress_bar.max_value = 1.0
_expanding_progress_bar.step = _expanding_progress_bar.max_value / 100
@@ -131,7 +130,7 @@ func _ready() -> void:
prov_view.mouse_filter = Control.MOUSE_FILTER_IGNORE
set_click_mask_from_nodepaths([^"./province_view/background"])
- var close_button : Button = get_button_from_nodepath(^"./province_view/close_button")
+ var close_button : GUIIconButton = get_gui_icon_button_from_nodepath(^"./province_view/close_button")
if close_button:
close_button.pressed.connect(_on_close_button_pressed)
@@ -141,41 +140,39 @@ func _ready() -> void:
if _state_name_label:
# State names are already translated in the MenuSingleton
_state_name_label.auto_translate = false
- _slave_status_icon = get_texture_rect_from_nodepath(^"./province_view/province_view_header/slave_state_icon")
- var slave_status_icon_texture : GFXSpriteTexture = get_gfx_sprite_texture_from_nodepath(^"./province_view/province_view_header/slave_state_icon")
- if slave_status_icon_texture:
- slave_status_icon_texture.set_icon_index(MenuSingleton.get_slave_pop_icon_index())
- _colony_status_button = get_button_from_nodepath(^"./province_view/province_view_header/colony_button")
- _colony_status_button_texture = get_gfx_sprite_texture_from_nodepath(^"./province_view/province_view_header/colony_button")
- var admin_icon_texture : GFXSpriteTexture = get_gfx_sprite_texture_from_nodepath(^"./province_view/province_view_header/admin_icon")
- if admin_icon_texture:
- admin_icon_texture.set_icon_index(MenuSingleton.get_administrative_pop_icon_index())
+ _slave_status_icon = get_gui_icon_from_nodepath(^"./province_view/province_view_header/slave_state_icon")
+ if _slave_status_icon:
+ _slave_status_icon.set_icon_index(MenuSingleton.get_slave_pop_icon_index())
+ _colony_status_button = get_gui_icon_button_from_nodepath(^"./province_view/province_view_header/colony_button")
+ var admin_icon : GUIIcon = get_gui_icon_from_nodepath(^"./province_view/province_view_header/admin_icon")
+ if admin_icon:
+ admin_icon.set_icon_index(MenuSingleton.get_administrative_pop_icon_index())
_administrative_percentage_label = get_gui_label_from_nodepath(^"./province_view/province_view_header/admin_efficiency")
_owner_percentage_label = get_gui_label_from_nodepath(^"./province_view/province_view_header/owner_presence")
_province_modifiers_overlapping_elements_box = get_gui_overlapping_elements_box_from_nodepath(^"./province_view/province_view_header/province_modifiers")
if _province_modifiers_overlapping_elements_box and _province_modifiers_overlapping_elements_box.set_gui_child_element_name("province_interface", "prov_state_modifier") != OK:
_province_modifiers_overlapping_elements_box = null # hide province modifiers box since we can't do anything with it
- _terrain_type_texture = get_gfx_sprite_texture_from_nodepath(^"./province_view/province_view_header/prov_terrain")
- _life_rating_bar = get_progress_bar_from_nodepath(^"./province_view/province_view_header/liferating")
- _controller_flag_texture = get_gfx_masked_flag_texture_from_nodepath(^"./province_view/province_view_header/controller_flag")
+ _terrain_type_icon = get_gui_icon_from_nodepath(^"./province_view/province_view_header/prov_terrain")
+ _life_rating_bar = get_gui_progress_bar_from_nodepath(^"./province_view/province_view_header/liferating")
+ _controller_flag = get_gui_masked_flag_from_nodepath(^"./province_view/province_view_header/controller_flag")
# Statistics
- _rgo_icon_texture = get_gfx_sprite_texture_from_nodepath(^"./province_view/province_statistics/goods_type")
+ _rgo_icon = get_gui_icon_from_nodepath(^"./province_view/province_statistics/goods_type")
_rgo_produced_label = get_gui_label_from_nodepath(^"./province_view/province_statistics/produced")
_rgo_income_label = get_gui_label_from_nodepath(^"./province_view/province_statistics/income")
- _rgo_employment_percentage_texture = get_gfx_sprite_texture_from_nodepath(^"./province_view/province_statistics/employment_ratio")
+ _rgo_employment_percentage_icon = get_gui_icon_from_nodepath(^"./province_view/province_statistics/employment_ratio")
_rgo_employment_population_label = get_gui_label_from_nodepath(^"./province_view/province_statistics/rgo_population")
_rgo_employment_percentage_label = get_gui_label_from_nodepath(^"./province_view/province_statistics/rgo_percent")
_crime_name_label = get_gui_label_from_nodepath(^"./province_view/province_statistics/crime_name")
- _crime_icon_texture = get_gfx_sprite_texture_from_nodepath(^"./province_view/province_statistics/crime_icon")
+ _crime_icon = get_gui_icon_from_nodepath(^"./province_view/province_statistics/crime_icon")
_crime_fighting_label = get_gui_label_from_nodepath(^"./province_view/province_statistics/crimefight_percent")
_total_population_label = get_gui_label_from_nodepath(^"./province_view/province_statistics/total_population")
_migration_label = get_gui_label_from_nodepath(^"./province_view/province_statistics/migration")
_population_growth_label = get_gui_label_from_nodepath(^"./province_view/province_statistics/growth")
- _pop_types_piechart = get_gfx_pie_chart_texture_from_nodepath(^"./province_view/province_statistics/workforce_chart")
- _pop_ideologies_piechart = get_gfx_pie_chart_texture_from_nodepath(^"./province_view/province_statistics/ideology_chart")
- _pop_cultures_piechart = get_gfx_pie_chart_texture_from_nodepath(^"./province_view/province_statistics/culture_chart")
- var population_menu_button : Button = get_button_from_nodepath(^"./province_view/province_statistics/open_popscreen")
+ _pop_types_piechart = get_gui_pie_chart_from_nodepath(^"./province_view/province_statistics/workforce_chart")
+ _pop_ideologies_piechart = get_gui_pie_chart_from_nodepath(^"./province_view/province_statistics/ideology_chart")
+ _pop_cultures_piechart = get_gui_pie_chart_from_nodepath(^"./province_view/province_statistics/culture_chart")
+ var population_menu_button : GUIIconButton = get_gui_icon_button_from_nodepath(^"./province_view/province_statistics/open_popscreen")
if population_menu_button:
population_menu_button.pressed.connect(
func() -> void:
@@ -227,11 +224,11 @@ enum ColonyStatus { STATE, PROTECTORATE, COLONY }
# This assumes _cores_overlapping_elements_box is non-null
func _set_core_flag(core_index : int, country : String) -> void:
- var core_flag_texture : GFXMaskedFlagTexture = GUINode.get_gfx_masked_flag_texture_from_node(
+ var core_flag_button : GUIMaskedFlagButton = GUINode.get_gui_masked_flag_button_from_node(
_cores_overlapping_elements_box.get_child(core_index).get_node(^"./country_flag")
)
- if core_flag_texture:
- core_flag_texture.set_flag_country_name(country)
+ if core_flag_button:
+ core_flag_button.set_flag_country_name(country)
func _update_info() -> void:
const _province_info_province_key : StringName = &"province"
@@ -271,8 +268,7 @@ func _update_info() -> void:
if colony_status == ColonyStatus.STATE:
_colony_status_button.hide()
else:
- if _colony_status_button_texture:
- _colony_status_button_texture.set_icon_index(colony_status)
+ _colony_status_button.set_icon_index(colony_status)
_colony_status_button.show()
if _administrative_percentage_label:
@@ -285,28 +281,28 @@ func _update_info() -> void:
# TODO - replace example icons with those from the province's list of modifier instances
_province_modifiers_overlapping_elements_box.set_child_count(8)
for i : int in _province_modifiers_overlapping_elements_box.get_child_count():
- var icon : GFXSpriteTexture = GUINode.get_gfx_sprite_texture_from_node(
+ var button : GUIIconButton = GUINode.get_gui_icon_button_from_node(
_province_modifiers_overlapping_elements_box.get_child(i).get_node(^"./modifier")
)
- if icon:
- icon.set_icon_index(2 * i + (i & 1) + 1)
+ if button:
+ button.set_icon_index(2 * i + (i & 1) + 1)
- if _terrain_type_texture:
+ if _terrain_type_icon:
var terrain_type : String = _province_info.get(_province_info_terrain_type_key, "")
if terrain_type:
const _terrain_type_prefix : String = "GFX_terrainimg_"
- if _terrain_type_texture.set_gfx_texture_sprite_name(_terrain_type_prefix + terrain_type) != OK:
+ if _terrain_type_icon.set_gfx_texture_sprite_name(_terrain_type_prefix + terrain_type) != OK:
push_error("Failed to set terrain type texture: ", terrain_type)
if _life_rating_bar:
_life_rating_bar.value = _province_info.get(_province_info_life_rating_key, 0) / 100.0
- if _controller_flag_texture:
- _controller_flag_texture.set_flag_country_name(_province_info.get(_province_info_controller_key, ""))
+ if _controller_flag:
+ _controller_flag.set_flag_country_name(_province_info.get(_province_info_controller_key, ""))
# Statistics
- if _rgo_icon_texture:
- _rgo_icon_texture.set_icon_index(_province_info.get(_province_info_rgo_icon_key, -1) + 2)
+ if _rgo_icon:
+ _rgo_icon.set_icon_index(_province_info.get(_province_info_rgo_icon_key, -1) + 2)
if _rgo_produced_label:
# TODO - replace name with amount produced
@@ -316,7 +312,7 @@ func _update_info() -> void:
# TODO - add £ sign and replace placeholder with actual value
_rgo_income_label.text = "%s¤" % GUINode.float_to_string_dp(12.34567, 3)
- if _rgo_employment_percentage_texture:
+ if _rgo_employment_percentage_icon:
pass
if _rgo_employment_population_label:
@@ -329,8 +325,8 @@ func _update_info() -> void:
if _crime_name_label:
_crime_name_label.text = _province_info.get(_province_info_crime_name_key, "")
- if _crime_icon_texture:
- _crime_icon_texture.set_icon_index(_province_info.get(_province_info_crime_icon_key, 0) + 1)
+ if _crime_icon:
+ _crime_icon.set_icon_index(_province_info.get(_province_info_crime_icon_key, 0) + 1)
if _crime_fighting_label:
pass
diff --git a/game/src/Game/GameSession/SearchPanel.gd b/game/src/Game/GameSession/SearchPanel.gd
index c41660f..d13c11f 100644
--- a/game/src/Game/GameSession/SearchPanel.gd
+++ b/game/src/Game/GameSession/SearchPanel.gd
@@ -5,7 +5,7 @@ extends GUINode
var _search_panel : Panel
var _search_line_edit : LineEdit
var _results_list_box : GUIListBox
-var _result_buttons : Array[Button]
+var _result_buttons : Array[GUIIconButton]
var _drag_active : bool = false
var _drag_anchor : Vector2
@@ -19,11 +19,11 @@ func _ready() -> void:
_search_panel = get_panel_from_nodepath(^"./goto_box")
- var close_button : Button = get_button_from_nodepath(^"./goto_box/cancel")
+ var close_button : GUIIconButton = get_gui_icon_button_from_nodepath(^"./goto_box/cancel")
if close_button:
close_button.pressed.connect(hide)
- var panel_button : Button = get_button_from_nodepath(^"./goto_box/goto_box")
+ var panel_button : GUIIconButton = get_gui_icon_button_from_nodepath(^"./goto_box/goto_box")
if panel_button:
panel_button.button_down.connect(_start_drag)
panel_button.button_up.connect(_end_drag)
@@ -97,7 +97,7 @@ func _add_result_button() -> bool:
if not child:
return false
- var button : Button = GUINode.get_button_from_node(child.get_node(^"./game"))
+ var button : GUIIconButton = GUINode.get_gui_icon_button_from_node(child.get_node(^"./game"))
if not button:
child.queue_free()
return false
diff --git a/game/src/Game/GameSession/Tooltip.gd b/game/src/Game/GameSession/Tooltip.gd
new file mode 100644
index 0000000..c110e2e
--- /dev/null
+++ b/game/src/Game/GameSession/Tooltip.gd
@@ -0,0 +1,23 @@
+extends GUINode
+
+var _tooltip_label : GUILabel
+
+func _ready() -> void:
+ add_gui_element("core", "ToolTip")
+
+ _tooltip_label = get_gui_label_from_nodepath(^"./ToolTip")
+ if _tooltip_label:
+ _tooltip_label.set_auto_adjust_to_content_size(true)
+
+ MenuSingleton.update_tooltip.connect(update_tooltip)
+
+ hide()
+
+func update_tooltip(text : String, substitution_dict : Dictionary, position : Vector2) -> void:
+ if text:
+ _tooltip_label.set_text(text)
+ _tooltip_label.set_substitution_dict(substitution_dict)
+ _tooltip_label.set_position(position)
+ show()
+ else:
+ hide()
diff --git a/game/src/Game/GameSession/Topbar.gd b/game/src/Game/GameSession/Topbar.gd
index d6cc358..e3e0809 100644
--- a/game/src/Game/GameSession/Topbar.gd
+++ b/game/src/Game/GameSession/Topbar.gd
@@ -1,8 +1,8 @@
extends GUINode
# Country info
-var _country_flag_texture : GFXMaskedFlagTexture
-var _country_flag_overlay_texture : GFXSpriteTexture
+var _country_flag_button : GUIMaskedFlagButton
+var _country_flag_overlay_icon : GUIIcon
var _country_name_label : GUILabel
var _country_rank_label : GUILabel
var _country_prestige_label : GUILabel
@@ -14,41 +14,40 @@ var _country_military_power_rank_label : GUILabel
var _country_colonial_power_label : GUILabel
# Time controls
-var _speed_up_button : Button
-var _speed_down_button : Button
-var _speed_indicator_texture : GFXSpriteTexture
+var _speed_up_button : GUIIconButton
+var _speed_down_button : GUIIconButton
+var _pause_bg_button : GUIButton
+var _speed_indicator_button : GUIIconButton
var _date_label : GUILabel
-# NationManagement.Screen-Button
+# NationManagement.Screen-GUIIconButton
var _nation_management_buttons : Dictionary
-# NationManagement.Screen-GFXSpriteTexture
-var _nation_management_button_textures : Dictionary
# Production
-var _production_top_goods_textures : Array[GFXSpriteTexture]
-var _production_alert_building_texture : GFXSpriteTexture
-var _production_alert_closed_texture : GFXSpriteTexture
-var _production_alert_unemployment_texture : GFXSpriteTexture
+var _production_top_goods_icons : Array[GUIIcon]
+var _production_alert_building_icon : GUIIcon
+var _production_alert_closed_icon : GUIIcon
+var _production_alert_unemployment_icon : GUIIcon
# Budget
# TODO - line chart
var _budget_funds_label : GUILabel
# Technology
-var _technology_progress_bar : TextureProgressBar
+var _technology_progress_bar : GUIProgressBar
var _technology_current_research_label : GUILabel
var _technology_literacy_label : GUILabel
var _technology_research_points_label : GUILabel
# Politics
-var _politics_party_icon : TextureRect
+var _politics_party_icon : GUIIcon
var _politics_party_label : GUILabel
var _politics_suppression_points_label : GUILabel
var _politics_infamy_label : GUILabel
-var _politics_reforms_texture : GFXSpriteTexture
-var _politics_decisions_texture : GFXSpriteTexture
-var _politics_election_texture : GFXSpriteTexture
-var _politics_rebels_texture : GFXSpriteTexture
+var _politics_reforms_button : GUIButton
+var _politics_decisions_button : GUIIconButton
+var _politics_election_icon : GUIIcon
+var _politics_rebels_button : GUIIconButton
# Population
var _population_total_size_label : GUILabel
@@ -57,17 +56,17 @@ var _population_militancy_label : GUILabel
var _population_consciousness_label : GUILabel
# Trade
-var _trade_imported_textures : Array[GFXSpriteTexture]
-var _trade_exported_textures : Array[GFXSpriteTexture]
+var _trade_imported_icons : Array[GUIIcon]
+var _trade_exported_icons : Array[GUIIcon]
# Diplomacy
var _diplomacy_peace_label : GUILabel
var _diplomacy_war_enemies_overlapping_elements_box : GUIOverlappingElementsBox
var _diplomacy_diplomatic_points_label : GUILabel
-var _diplomacy_alert_colony_texture : GFXSpriteTexture
-var _diplomacy_alert_crisis_texture : GFXSpriteTexture
-var _diplomacy_alert_sphere_texture : GFXSpriteTexture
-var _diplomacy_alert_great_power_texture : GFXSpriteTexture
+var _diplomacy_alert_colony_button : GUIIconButton
+var _diplomacy_alert_crisis_icon : GUIIcon
+var _diplomacy_alert_sphere_icon : GUIIcon
+var _diplomacy_alert_great_power_icon : GUIIcon
# Military
var _military_army_size_label : GUILabel
@@ -87,45 +86,61 @@ func _ready() -> void:
])
# Disables all consuming invisible panel
- var topbar := get_panel_from_nodepath(^"./topbar")
+ var topbar : Panel = get_panel_from_nodepath(^"./topbar")
if topbar:
topbar.mouse_filter = Control.MOUSE_FILTER_IGNORE
set_click_mask_from_nodepaths([^"./topbar/topbar_bg", ^"./topbar/topbar_paper"])
# Country info
- var country_flag_button = get_button_from_nodepath(^"./topbar/player_flag")
- if country_flag_button:
- country_flag_button.pressed.connect(
+ _country_flag_button = get_gui_masked_flag_button_from_nodepath(^"./topbar/player_flag")
+ if _country_flag_button:
+ _country_flag_button.pressed.connect(
func() -> void:
# TODO - open the diplomacy menu on the Wars tab
Events.NationManagementScreens.open_nation_management_screen(NationManagement.Screen.DIPLOMACY)
)
- _country_flag_texture = GUINode.get_gfx_masked_flag_texture_from_node(country_flag_button)
- _country_flag_overlay_texture = get_gfx_sprite_texture_from_nodepath(^"./topbar/topbar_flag_overlay")
+ _country_flag_overlay_icon = get_gui_icon_from_nodepath(^"./topbar/topbar_flag_overlay")
_country_name_label = get_gui_label_from_nodepath(^"./topbar/CountryName")
_country_rank_label = get_gui_label_from_nodepath(^"./topbar/nation_totalrank")
+ if _country_rank_label:
+ _country_rank_label.set_mouse_filter(MOUSE_FILTER_PASS)
_country_prestige_label = get_gui_label_from_nodepath(^"./topbar/country_prestige")
+ if _country_prestige_label:
+ _country_prestige_label.set_mouse_filter(MOUSE_FILTER_PASS)
_country_prestige_rank_label = get_gui_label_from_nodepath(^"./topbar/selected_prestige_rank")
+ if _country_prestige_rank_label:
+ _country_prestige_rank_label.set_mouse_filter(MOUSE_FILTER_PASS)
_country_industrial_power_label = get_gui_label_from_nodepath(^"./topbar/country_economic")
+ if _country_industrial_power_label:
+ _country_industrial_power_label.set_mouse_filter(MOUSE_FILTER_PASS)
_country_industrial_power_rank_label = get_gui_label_from_nodepath(^"./topbar/selected_industry_rank")
+ if _country_industrial_power_rank_label:
+ _country_industrial_power_rank_label.set_mouse_filter(MOUSE_FILTER_PASS)
_country_military_power_label = get_gui_label_from_nodepath(^"./topbar/country_military")
+ if _country_military_power_label:
+ _country_military_power_label.set_mouse_filter(MOUSE_FILTER_PASS)
_country_military_power_rank_label = get_gui_label_from_nodepath(^"./topbar/selected_military_rank")
+ if _country_military_power_rank_label:
+ _country_military_power_rank_label.set_mouse_filter(MOUSE_FILTER_PASS)
_country_colonial_power_label = get_gui_label_from_nodepath(^"./topbar/country_colonial_power")
+ if _country_colonial_power_label:
+ _country_colonial_power_label.set_mouse_filter(MOUSE_FILTER_PASS)
# Time controls
- _speed_up_button = get_button_from_nodepath(^"./topbar/button_speedup")
+ _speed_up_button = get_gui_icon_button_from_nodepath(^"./topbar/button_speedup")
if _speed_up_button:
_speed_up_button.pressed.connect(_on_increase_speed_button_pressed)
- _speed_down_button = get_button_from_nodepath(^"./topbar/button_speeddown")
+ _speed_up_button.set_tooltip_string("TOPBAR_INC_SPEED")
+ _speed_down_button = get_gui_icon_button_from_nodepath(^"./topbar/button_speeddown")
if _speed_down_button:
_speed_down_button.pressed.connect(_on_decrease_speed_button_pressed)
- var pause_bg_button : Button = get_button_from_nodepath(^"./topbar/pause_bg")
- if pause_bg_button:
- pause_bg_button.pressed.connect(_on_play_pause_button_pressed)
- var speed_indicator_button = get_button_from_nodepath(^"./topbar/speed_indicator")
- if speed_indicator_button:
- speed_indicator_button.pressed.connect(_on_play_pause_button_pressed)
- _speed_indicator_texture = GUINode.get_gfx_sprite_texture_from_node(speed_indicator_button)
+ _speed_down_button.set_tooltip_string("TOPBAR_DEC_SPEED")
+ _pause_bg_button = get_gui_icon_button_from_nodepath(^"./topbar/pause_bg")
+ if _pause_bg_button:
+ _pause_bg_button.pressed.connect(_on_play_pause_button_pressed)
+ _speed_indicator_button = get_gui_icon_button_from_nodepath(^"./topbar/speed_indicator")
+ if _speed_indicator_button:
+ _speed_indicator_button.pressed.connect(_on_play_pause_button_pressed)
_date_label = get_gui_label_from_nodepath(^"./topbar/DateText")
# Nation management screens
@@ -140,40 +155,54 @@ func _ready() -> void:
NationManagement.Screen.MILITARY : ^"./topbar/topbarbutton_military"
}
for screen : NationManagement.Screen in screen_nodepaths:
- var button : Button = get_button_from_nodepath(screen_nodepaths[screen])
+ var button : GUIIconButton = get_gui_icon_button_from_nodepath(screen_nodepaths[screen])
if button:
button.pressed.connect(
Events.NationManagementScreens.toggle_nation_management_screen.bind(screen)
)
- var icon : GFXSpriteTexture = GUINode.get_gfx_sprite_texture_from_node(button)
- if icon:
- _nation_management_buttons[screen] = button
- _nation_management_button_textures[screen] = icon
+ # TODO - test tooltip, replace with actual shortcut strings
+ button.set_tooltip_string(tr("SHORTCUT") + "F3")
+ _nation_management_buttons[screen] = button
Events.NationManagementScreens.update_active_nation_management_screen.connect(
_on_update_active_nation_management_screen
)
# Production
const PRODUCED_GOOD_COUNT : int = 5
- for idx in PRODUCED_GOOD_COUNT:
- _production_top_goods_textures.push_back(get_gfx_sprite_texture_from_nodepath("./topbar/topbar_produced%d" % idx))
- _production_alert_building_texture = get_gfx_sprite_texture_from_nodepath(^"./topbar/alert_building_factories")
- _production_alert_closed_texture = get_gfx_sprite_texture_from_nodepath(^"./topbar/alert_closed_factories")
- _production_alert_unemployment_texture = get_gfx_sprite_texture_from_nodepath(^"./topbar/alert_unemployed_workers")
+ for idx : int in PRODUCED_GOOD_COUNT:
+ _production_top_goods_icons.push_back(get_gui_icon_from_nodepath("./topbar/topbar_produced%d" % idx))
+ _production_alert_building_icon = get_gui_icon_from_nodepath(^"./topbar/alert_building_factories")
+ _production_alert_closed_icon = get_gui_icon_from_nodepath(^"./topbar/alert_closed_factories")
+ _production_alert_unemployment_icon = get_gui_icon_from_nodepath(^"./topbar/alert_unemployed_workers")
# Budget
_budget_funds_label = get_gui_label_from_nodepath(^"./topbar/budget_funds")
# Technology
- _technology_progress_bar = get_progress_bar_from_nodepath(^"./topbar/topbar_tech_progress")
+ var tech_button : GUIIconButton = _nation_management_buttons[NationManagement.Screen.TECHNOLOGY]
+ _technology_progress_bar = get_gui_progress_bar_from_nodepath(^"./topbar/topbar_tech_progress")
+ if _technology_progress_bar and tech_button:
+ _technology_progress_bar.reparent(tech_button)
_technology_current_research_label = get_gui_label_from_nodepath(^"./topbar/tech_current_research")
+ if _technology_current_research_label:
+ _technology_current_research_label.set_mouse_filter(MOUSE_FILTER_PASS)
+ if tech_button:
+ _technology_current_research_label.reparent(tech_button)
_technology_literacy_label = get_gui_label_from_nodepath(^"./topbar/tech_literacy_value")
+ if _technology_literacy_label:
+ _technology_literacy_label.set_mouse_filter(MOUSE_FILTER_PASS)
+ if tech_button:
+ _technology_literacy_label.reparent(tech_button)
_technology_research_points_label = get_gui_label_from_nodepath(^"./topbar/topbar_researchpoints_value")
+ if _technology_research_points_label:
+ _technology_research_points_label.set_mouse_filter(MOUSE_FILTER_PASS)
+ if tech_button:
+ _technology_research_points_label.reparent(tech_button)
# Politics
- _politics_party_icon = get_texture_rect_from_nodepath(^"./topbar/politics_party_icon")
+ _politics_party_icon = get_gui_icon_from_nodepath(^"./topbar/politics_party_icon")
_politics_party_label = get_gui_label_from_nodepath(^"./topbar/politics_ruling_party")
- var politics_suppression_button : Button = get_button_from_nodepath(^"./topbar/topbar_supression_icon")
+ var politics_suppression_button : GUIIconButton = get_gui_icon_button_from_nodepath(^"./topbar/topbar_supression_icon")
if politics_suppression_button:
politics_suppression_button.pressed.connect(
func() -> void:
@@ -182,31 +211,28 @@ func _ready() -> void:
)
_politics_suppression_points_label = get_gui_label_from_nodepath(^"./topbar/politics_supressionpoints_value")
_politics_infamy_label = get_gui_label_from_nodepath(^"./topbar/politics_infamy_value")
- var politics_reforms_button : Button = get_button_from_nodepath(^"./topbar/alert_can_do_reforms")
- if politics_reforms_button:
- politics_reforms_button.pressed.connect(
+ _politics_reforms_button = get_gui_icon_button_from_nodepath(^"./topbar/alert_can_do_reforms")
+ if _politics_reforms_button:
+ _politics_reforms_button.pressed.connect(
func() -> void:
# TODO - open the politics menu on the Reforms tab
Events.NationManagementScreens.toggle_nation_management_screen(NationManagement.Screen.POLITICS)
)
- _politics_reforms_texture = GUINode.get_gfx_sprite_texture_from_node(politics_reforms_button)
- var politics_decisions_button : Button = get_button_from_nodepath(^"./topbar/alert_can_do_decisions")
- if politics_decisions_button:
- politics_decisions_button.pressed.connect(
+ _politics_decisions_button = get_gui_icon_button_from_nodepath(^"./topbar/alert_can_do_decisions")
+ if _politics_decisions_button:
+ _politics_decisions_button.pressed.connect(
func() -> void:
# TODO - open the politics menu on the Decisions tab
Events.NationManagementScreens.toggle_nation_management_screen(NationManagement.Screen.POLITICS)
)
- _politics_decisions_texture = GUINode.get_gfx_sprite_texture_from_node(politics_decisions_button)
- _politics_election_texture = get_gfx_sprite_texture_from_nodepath(^"./topbar/alert_is_in_election")
- var politics_rebels_button : Button = get_button_from_nodepath(^"./topbar/alert_have_rebels")
- if politics_rebels_button:
- politics_rebels_button.pressed.connect(
+ _politics_election_icon = get_gui_icon_from_nodepath(^"./topbar/alert_is_in_election")
+ _politics_rebels_button = get_gui_icon_button_from_nodepath(^"./topbar/alert_have_rebels")
+ if _politics_rebels_button:
+ _politics_rebels_button.pressed.connect(
func() -> void:
# TODO - open the politics menu on the Movements tab
Events.NationManagementScreens.toggle_nation_management_screen(NationManagement.Screen.POLITICS)
)
- _politics_rebels_texture = GUINode.get_gfx_sprite_texture_from_node(politics_rebels_button)
# Population
_population_total_size_label = get_gui_label_from_nodepath(^"./topbar/population_total_value")
@@ -217,24 +243,23 @@ func _ready() -> void:
# Trade
const TRADE_GOOD_COUNT : int = 3
for idx in TRADE_GOOD_COUNT:
- _trade_imported_textures.push_back(get_gfx_sprite_texture_from_nodepath("./topbar/topbar_import%d" % idx))
- _trade_exported_textures.push_back(get_gfx_sprite_texture_from_nodepath("./topbar/topbar_export%d" % idx))
+ _trade_imported_icons.push_back(get_gui_icon_from_nodepath("./topbar/topbar_import%d" % idx))
+ _trade_exported_icons.push_back(get_gui_icon_from_nodepath("./topbar/topbar_export%d" % idx))
# Diplomacy
_diplomacy_peace_label = get_gui_label_from_nodepath(^"./topbar/diplomacy_status")
_diplomacy_war_enemies_overlapping_elements_box = get_gui_overlapping_elements_box_from_nodepath(^"./topbar/diplomacy_at_war")
_diplomacy_diplomatic_points_label = get_gui_label_from_nodepath(^"./topbar/diplomacy_diplopoints_value")
- var diplomacy_alert_colony_button : Button = get_button_from_nodepath(^"./topbar/alert_colony")
- if diplomacy_alert_colony_button:
- diplomacy_alert_colony_button.pressed.connect(
+ _diplomacy_alert_colony_button = get_gui_icon_button_from_nodepath(^"./topbar/alert_colony")
+ if _diplomacy_alert_colony_button:
+ _diplomacy_alert_colony_button.pressed.connect(
func() -> void:
# TODO - move to and select province in upgradable colony if any exist
Events.NationManagementScreens.open_nation_management_screen(NationManagement.Screen.DIPLOMACY)
)
- _diplomacy_alert_colony_texture = GUINode.get_gfx_sprite_texture_from_node(diplomacy_alert_colony_button)
- _diplomacy_alert_crisis_texture = get_gfx_sprite_texture_from_nodepath(^"./topbar/alert_crisis")
- _diplomacy_alert_sphere_texture = get_gfx_sprite_texture_from_nodepath(^"./topbar/alert_can_increase_opinion")
- _diplomacy_alert_great_power_texture = get_gfx_sprite_texture_from_nodepath(^"./topbar/alert_loosing_gp")
+ _diplomacy_alert_crisis_icon = get_gui_icon_from_nodepath(^"./topbar/alert_crisis")
+ _diplomacy_alert_sphere_icon = get_gui_icon_from_nodepath(^"./topbar/alert_can_increase_opinion")
+ _diplomacy_alert_great_power_icon = get_gui_icon_from_nodepath(^"./topbar/alert_loosing_gp")
# Military
_military_army_size_label = get_gui_label_from_nodepath(^"./topbar/military_army_value")
@@ -249,45 +274,66 @@ func _notification(what : int) -> void:
match what:
NOTIFICATION_TRANSLATION_CHANGED:
_update_info()
+ _update_speed_controls()
func _update_info() -> void:
# Placeholder data
const player_country : String = "ENG"
+ const player_rank : int = 0
+
+ const RANK_NAMES : PackedStringArray = [
+ "DIPLOMACY_GREATNATION_STATUS",
+ "DIPLOMACY_COLONIALNATION_STATUS",
+ "DIPLOMACY_CIVILIZEDNATION_STATUS",
+ "DIPLOMACY_UNCIVILIZEDNATION_STATUS"
+ ]
## Country info
- if _country_flag_texture:
- _country_flag_texture.set_flag_country_name(player_country)
+ if _country_flag_button:
+ _country_flag_button.set_flag_country_name(player_country)
+ _country_flag_button.set_tooltip_string_and_substitution_dict("PLAYER_COUNTRY_TOPBAR_RANK", {
+ "NAME": player_country, "RANK": RANK_NAMES[player_rank]
+ })
- if _country_flag_overlay_texture:
+ if _country_flag_overlay_icon:
# 1 - Great Power
# 2 - Secondary Power
# 3 - Civilised
# 4 - Uncivilised
- _country_flag_overlay_texture.set_icon_index(1)
+ _country_flag_overlay_icon.set_icon_index(1 + player_rank)
if _country_name_label:
_country_name_label.set_text(player_country)
if _country_rank_label:
_country_rank_label.set_text(str(1))
+ _country_rank_label.set_tooltip_string_and_substitution_dict("PLAYER_COUNTRY_TOPBAR_RANK", {
+ "NAME": player_country, "RANK": RANK_NAMES[player_rank]
+ })
if _country_prestige_label:
_country_prestige_label.set_text(str(11))
+ _country_military_power_label.set_tooltip_string("RANK_PRESTIGE")
if _country_prestige_rank_label:
_country_prestige_rank_label.set_text(str(1))
+ _country_military_power_label.set_tooltip_string("RANK_PRESTIGE")
if _country_industrial_power_label:
_country_industrial_power_label.set_text(str(22))
+ _country_military_power_label.set_tooltip_string("RANK_INDUSTRY")
if _country_industrial_power_rank_label:
_country_industrial_power_rank_label.set_text(str(2))
+ _country_military_power_label.set_tooltip_string("RANK_INDUSTRY")
if _country_military_power_label:
_country_military_power_label.set_text(str(33))
+ _country_military_power_label.set_tooltip_string("RANK_MILITARY")
if _country_military_power_rank_label:
_country_military_power_rank_label.set_text(str(3))
+ _country_military_power_rank_label.set_tooltip_string("RANK_MILITARY")
if _country_colonial_power_label:
var available_colonial_power : int = 123
@@ -295,24 +341,25 @@ func _update_info() -> void:
_country_colonial_power_label.set_text(
"§%s%s§!/%s" % ["W" if available_colonial_power > 0 else "R", available_colonial_power, total_colonial_power]
)
+ _country_colonial_power_label.set_tooltip_string("COLONIAL_POINTS")
## Time control
if _date_label:
_date_label.text = MenuSingleton.get_longform_date()
## Production
- for idx : int in _production_top_goods_textures.size():
- if _production_top_goods_textures[idx]:
- _production_top_goods_textures[idx].set_icon_index(idx + 2)
+ for idx : int in _production_top_goods_icons.size():
+ if _production_top_goods_icons[idx]:
+ _production_top_goods_icons[idx].set_icon_index(idx + 2)
- if _production_alert_building_texture:
- _production_alert_building_texture.set_icon_index(2)
+ if _production_alert_building_icon:
+ _production_alert_building_icon.set_icon_index(2)
- if _production_alert_closed_texture:
- _production_alert_closed_texture.set_icon_index(2)
+ if _production_alert_closed_icon:
+ _production_alert_closed_icon.set_icon_index(2)
- if _production_alert_unemployment_texture:
- _production_alert_unemployment_texture.set_icon_index(2)
+ if _production_alert_unemployment_icon:
+ _production_alert_unemployment_icon.set_icon_index(2)
## Budget
if _budget_funds_label:
@@ -331,12 +378,21 @@ func _update_info() -> void:
if _technology_current_research_label:
# TODO - set current research or "unciv_nation" (in red) if uncivilised
_technology_current_research_label.set_text("TB_TECH_NO_CURRENT")
+ _technology_current_research_label.set_tooltip_string("TECHNOLOGYVIEW_NO_RESEARCH_TOOLTIP")
if _technology_literacy_label:
- _technology_literacy_label.set_text("§Y%s§W%%" % GUINode.float_to_string_dp(80.0, 1))
+ var literacy_float : float = 80.0
+ var literacy_string : String = GUINode.float_to_string_dp(80.0, 1)
+ _technology_literacy_label.set_text("§Y%s§W%%" % literacy_string)
+ _technology_literacy_label.set_tooltip_string_and_substitution_dict("TOPBAR_AVG_LITERACY", { "AVG": literacy_string })
if _technology_research_points_label:
_technology_research_points_label.set_text("§Y%s" % GUINode.float_to_string_dp(10.0, 2))
+ # TODO - test tooltip, replace with actual values from the simulation
+ _technology_research_points_label.set_tooltip_string_and_substitution_dict("TECH_DAILY_RESEARCHPOINTS_TOOLTIP", {
+ "POPTYPE": "Clergymen", "VALUE": GUINode.float_to_string_dp(1.42, 2),
+ "FRACTION": GUINode.float_to_string_dp(0.95, 2), "OPTIMAL": GUINode.float_to_string_dp(2, 2)
+ })
## Politics
if _politics_party_icon:
@@ -351,17 +407,17 @@ func _update_info() -> void:
if _politics_infamy_label:
_politics_infamy_label.set_text("§Y%s" % GUINode.float_to_string_dp(0.0, 2))
- if _politics_reforms_texture:
- _politics_reforms_texture.set_icon_index(2)
+ if _politics_reforms_button:
+ _politics_reforms_button.set_icon_index(2)
- if _politics_decisions_texture:
- _politics_decisions_texture.set_icon_index(2)
+ if _politics_decisions_button:
+ _politics_decisions_button.set_icon_index(2)
- if _politics_election_texture:
- _politics_election_texture.set_icon_index(2)
+ if _politics_election_icon:
+ _politics_election_icon.set_icon_index(2)
- if _politics_rebels_texture:
- _politics_rebels_texture.set_icon_index(2)
+ if _politics_rebels_button:
+ _politics_rebels_button.set_icon_index(2)
## Population
if _population_total_size_label:
@@ -386,13 +442,13 @@ func _update_info() -> void:
_population_consciousness_label.set_text("§Y%s" % GUINode.float_to_string_dp(0.05, 2))
## Trade
- for idx : int in _trade_imported_textures.size():
- if _trade_imported_textures[idx]:
- _trade_imported_textures[idx].set_icon_index(idx + 2 + _production_top_goods_textures.size())
+ for idx : int in _trade_imported_icons.size():
+ if _trade_imported_icons[idx]:
+ _trade_imported_icons[idx].set_icon_index(idx + 2 + _production_top_goods_icons.size())
- for idx : int in _trade_exported_textures.size():
- if _trade_exported_textures[idx]:
- _trade_exported_textures[idx].set_icon_index(idx + 2 + _production_top_goods_textures.size() + _trade_imported_textures.size())
+ for idx : int in _trade_exported_icons.size():
+ if _trade_exported_icons[idx]:
+ _trade_exported_icons[idx].set_icon_index(idx + 2 + _production_top_goods_icons.size() + _trade_imported_icons.size())
## Diplomacy
if _diplomacy_peace_label:
@@ -403,17 +459,17 @@ func _update_info() -> void:
if _diplomacy_diplomatic_points_label:
_diplomacy_diplomatic_points_label.set_text("§Y%s" % GUINode.float_to_string_dp(7.4, 0))
- if _diplomacy_alert_colony_texture:
- _diplomacy_alert_colony_texture.set_icon_index(3)
+ if _diplomacy_alert_colony_button:
+ _diplomacy_alert_colony_button.set_icon_index(3)
- if _diplomacy_alert_crisis_texture:
- _diplomacy_alert_crisis_texture.set_icon_index(3)
+ if _diplomacy_alert_crisis_icon:
+ _diplomacy_alert_crisis_icon.set_icon_index(3)
- if _diplomacy_alert_sphere_texture:
- _diplomacy_alert_sphere_texture.set_icon_index(2)
+ if _diplomacy_alert_sphere_icon:
+ _diplomacy_alert_sphere_icon.set_icon_index(2)
- if _diplomacy_alert_great_power_texture:
- _diplomacy_alert_great_power_texture.set_icon_index(2)
+ if _diplomacy_alert_great_power_icon:
+ _diplomacy_alert_great_power_icon.set_icon_index(2)
## Military
if _military_army_size_label:
@@ -429,6 +485,9 @@ func _update_info() -> void:
_military_leadership_points_label.set_text("§Y%d" % 15)
func _update_speed_controls() -> void:
+ var paused : bool = MenuSingleton.is_paused()
+ var speed : int = MenuSingleton.get_speed()
+
# TODO - decide whether to disable these or not
# (they don't appear to get disabled in the base game)
#if _speed_up_button:
@@ -437,11 +496,26 @@ func _update_speed_controls() -> void:
#if _speed_down_button:
# _speed_down_button.disabled = not MenuSingleton.can_decrease_speed()
- if _speed_indicator_texture:
+ if _pause_bg_button:
+ _pause_bg_button.set_tooltip_string("TOPBAR_DATE_IS_PAUSED" if paused else "TOPBAR_DATE")
+
+ if _speed_indicator_button:
var index : int = 1
- if not MenuSingleton.is_paused():
- index += MenuSingleton.get_speed() + 1
- _speed_indicator_texture.set_icon_index(index)
+ if paused:
+ _speed_indicator_button.set_tooltip_string("TOPBAR_PAUSE_INDICATOR")
+ else:
+ index += speed + 1
+ const SPEED_NAMES : PackedStringArray = [
+ "SLOWEST_SPEED",
+ "SLOW_SPEED",
+ "NORMAL_SPEED",
+ "FAST_SPEED",
+ "FASTEST_SPEED"
+ ]
+ _speed_indicator_button.set_tooltip_string_and_substitution_dict(
+ "TOPBAR_SPEED_INDICATOR", { "SPEED": SPEED_NAMES[speed] if speed < SPEED_NAMES.size() else str(speed) }
+ )
+ _speed_indicator_button.set_icon_index(index)
# REQUIREMENTS:
# * UIFUN-71
@@ -463,4 +537,4 @@ func _on_decrease_speed_button_pressed() -> void:
func _on_update_active_nation_management_screen(active_screen : NationManagement.Screen) -> void:
for screen : NationManagement.Screen in _nation_management_buttons:
- _nation_management_button_textures[screen].set_icon_index(1 + int(screen == active_screen))
+ _nation_management_buttons[screen].set_icon_index(1 + int(screen == active_screen))