aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Hop311 <Hop3114@gmail.com>2024-08-30 23:29:57 +0200
committer GitHub <noreply@github.com>2024-08-30 23:29:57 +0200
commitf54e454afb90f8868e7c62529e2a388fdaadf20b (patch)
treef19dbcdfe613397e86dc52cc34e0a443bd0f3e96
parent855e5b087459da19caf230cf22d99462680b268e (diff)
parentd7672f406406eea46625bc725690651f28211e19 (diff)
Merge pull request #251 from OpenVicProject/gui-text-label
Add GUILabel (colour code + currency icon support)
m---------extension/deps/openvic-simulation0
-rw-r--r--extension/src/openvic-extension/classes/GUILabel.cpp774
-rw-r--r--extension/src/openvic-extension/classes/GUILabel.hpp116
-rw-r--r--extension/src/openvic-extension/classes/GUINode.cpp7
-rw-r--r--extension/src/openvic-extension/classes/GUINode.hpp8
-rw-r--r--extension/src/openvic-extension/register_types.cpp10
-rw-r--r--extension/src/openvic-extension/singletons/AssetManager.cpp42
-rw-r--r--extension/src/openvic-extension/singletons/AssetManager.hpp19
-rw-r--r--extension/src/openvic-extension/singletons/GameSingleton.cpp8
-rw-r--r--extension/src/openvic-extension/utility/UITools.cpp60
-rw-r--r--extension/src/openvic-extension/utility/Utilities.cpp5
-rw-r--r--extension/src/openvic-extension/utility/Utilities.hpp3
-rw-r--r--game/src/Game/GameSession/NationManagementScreen/BudgetMenu.gd150
-rw-r--r--game/src/Game/GameSession/NationManagementScreen/PopulationMenu.gd50
-rw-r--r--game/src/Game/GameSession/ProvinceOverviewPanel.gd64
-rw-r--r--game/src/Game/GameSession/Topbar.gd204
-rw-r--r--game/src/Game/GameStart.gd3
17 files changed, 1208 insertions, 315 deletions
diff --git a/extension/deps/openvic-simulation b/extension/deps/openvic-simulation
-Subproject adc7eb8ad07170ba8da18f684321a92d01447c2
+Subproject 5813948cd3ed6432de374664650d68afbff7191
diff --git a/extension/src/openvic-extension/classes/GUILabel.cpp b/extension/src/openvic-extension/classes/GUILabel.cpp
new file mode 100644
index 0000000..9fd6b60
--- /dev/null
+++ b/extension/src/openvic-extension/classes/GUILabel.cpp
@@ -0,0 +1,774 @@
+#include "GUILabel.hpp"
+
+#include <godot_cpp/classes/font_file.hpp>
+#include <godot_cpp/classes/style_box_texture.hpp>
+#include <godot_cpp/variant/utility_functions.hpp>
+
+#include "openvic-extension/singletons/AssetManager.hpp"
+#include "openvic-extension/utility/ClassBindings.hpp"
+#include "openvic-extension/utility/Utilities.hpp"
+
+using namespace OpenVic;
+using namespace godot;
+using namespace OpenVic::Utilities::literals;
+
+static constexpr int32_t DEFAULT_FONT_SIZE = 16;
+
+void GUILabel::_bind_methods() {
+ OV_BIND_METHOD(GUILabel::clear);
+ OV_BIND_METHOD(GUILabel::get_gui_text_name);
+
+ OV_BIND_METHOD(GUILabel::get_text);
+ OV_BIND_METHOD(GUILabel::set_text, { "new_text" });
+
+ OV_BIND_METHOD(GUILabel::get_substitution_dict);
+ OV_BIND_METHOD(GUILabel::add_substitution, { "key", "value" });
+ OV_BIND_METHOD(GUILabel::set_substitution_dict, { "new_substitution_dict" });
+ OV_BIND_METHOD(GUILabel::clear_substitutions);
+
+ OV_BIND_METHOD(GUILabel::get_horizontal_alignment);
+ OV_BIND_METHOD(GUILabel::set_horizontal_alignment, { "new_horizontal_alignment" });
+ OV_BIND_METHOD(GUILabel::get_max_size);
+ OV_BIND_METHOD(GUILabel::set_max_size, { "new_max_size" });
+ OV_BIND_METHOD(GUILabel::get_border_size);
+ OV_BIND_METHOD(GUILabel::set_border_size, { "new_border_size" });
+ OV_BIND_METHOD(GUILabel::get_adjusted_rect);
+ OV_BIND_METHOD(GUILabel::will_auto_adjust_to_content_size);
+ OV_BIND_METHOD(GUILabel::set_auto_adjust_to_content_size, { "new_auto_adjust_to_content_size" });
+
+ OV_BIND_METHOD(GUILabel::get_font);
+ OV_BIND_METHOD(GUILabel::set_font, { "new_font" });
+ OV_BIND_METHOD(GUILabel::set_font_file, { "new_font_file" });
+ OV_BIND_METHOD(GUILabel::get_font_size);
+ OV_BIND_METHOD(GUILabel::set_font_size, { "new_font_size" });
+ OV_BIND_METHOD(GUILabel::get_default_colour);
+ OV_BIND_METHOD(GUILabel::set_default_colour, { "new_default_colour" });
+ OV_BIND_METHOD(GUILabel::get_currency_texture);
+
+ OV_BIND_METHOD(GUILabel::get_background);
+ OV_BIND_METHOD(GUILabel::set_background_texture, { "new_texture" });
+ OV_BIND_METHOD(GUILabel::set_background_stylebox, { "new_stylebox_texture" });
+
+ ADD_PROPERTY(PropertyInfo(Variant::STRING, "text", PROPERTY_HINT_MULTILINE_TEXT), "set_text", "get_text");
+ ADD_PROPERTY(PropertyInfo(Variant::DICTIONARY, "substitution_dict"), "set_substitution_dict", "get_substitution_dict");
+ ADD_PROPERTY(
+ PropertyInfo(Variant::INT, "horizontal_alignment", PROPERTY_HINT_ENUM, "Left,Centre,Right,Fill"),
+ "set_horizontal_alignment", "get_horizontal_alignment"
+ );
+ ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "max_size", PROPERTY_HINT_NONE, "suffix:px"), "set_max_size", "get_max_size");
+ ADD_PROPERTY(
+ PropertyInfo(Variant::VECTOR2, "border_size", PROPERTY_HINT_NONE, "suffix:px"), "set_border_size", "get_border_size"
+ );
+ ADD_PROPERTY(
+ PropertyInfo(Variant::RECT2, "adjusted_rect", PROPERTY_HINT_NONE, "suffix:px"), "", "get_adjusted_rect"
+ );
+ ADD_PROPERTY(
+ PropertyInfo(Variant::BOOL, "auto_adjust_to_content_size"), "set_auto_adjust_to_content_size",
+ "will_auto_adjust_to_content_size"
+ );
+
+ ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "font", PROPERTY_HINT_RESOURCE_TYPE, "Font"), "set_font", "get_font");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "font_size", PROPERTY_HINT_NONE, "suffix:px"), "set_font_size", "get_font_size");
+ ADD_PROPERTY(PropertyInfo(Variant::COLOR, "default_colour"), "set_default_colour", "get_default_colour");
+ ADD_PROPERTY(
+ PropertyInfo(Variant::OBJECT, "currency_texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D"), "", "get_currency_texture"
+ );
+ ADD_PROPERTY(
+ PropertyInfo(Variant::OBJECT, "background", PROPERTY_HINT_RESOURCE_TYPE, "StyleBoxTexture"), "set_background_stylebox",
+ "get_background"
+ );
+}
+
+void GUILabel::_notification(int what) {
+ switch (what) {
+ case NOTIFICATION_RESIZED:
+ case NOTIFICATION_TRANSLATION_CHANGED: {
+ _queue_line_update();
+ } break;
+ case NOTIFICATION_DRAW: {
+ const RID ci = get_canvas_item();
+
+ if (background.is_valid()) {
+ draw_style_box(background, adjusted_rect);
+ }
+
+ if (font.is_null()) {
+ return;
+ }
+
+ // Starting offset needed
+ static const Vector2 base_offset { 1.0_real, -1.0_real };
+ const Vector2 offset = base_offset + adjusted_rect.position + border_size;
+ Vector2 position = offset;
+
+ for (line_t const& line : lines) {
+ position.x = offset.x;
+ switch (horizontal_alignment) {
+ case HORIZONTAL_ALIGNMENT_CENTER: {
+ position.x += (adjusted_rect.size.width - 2 * border_size.width - line.width + 1.0_real) / 2.0_real;
+ } break;
+ case HORIZONTAL_ALIGNMENT_RIGHT: {
+ position.x += adjusted_rect.size.width - 2 * border_size.width - line.width;
+ } break;
+ case HORIZONTAL_ALIGNMENT_LEFT:
+ default:
+ break;
+ }
+
+ position.y += font->get_ascent(font_size);
+
+ for (segment_t const& segment : line.segments) {
+ string_segment_t const* string_segment = std::get_if<string_segment_t>(&segment);
+
+ if (string_segment == nullptr) {
+ if (currency_texture.is_valid()) {
+ currency_texture->draw(
+ ci, position - Vector2 {
+ 1.0_real, static_cast<real_t>(currency_texture->get_height()) * 0.75_real
+ }
+ );
+ position.x += currency_texture->get_width();
+ }
+ } else {
+ font->draw_string(
+ ci, position, string_segment->text, HORIZONTAL_ALIGNMENT_LEFT, -1, font_size,
+ string_segment->colour
+ );
+ position.x += string_segment->width;
+ }
+ }
+
+ position.y += font->get_descent(font_size);
+ }
+
+ } break;
+ }
+}
+
+GUILabel::GUILabel()
+ : gui_text { nullptr },
+ text {},
+ substitution_dict {},
+ horizontal_alignment { HORIZONTAL_ALIGNMENT_LEFT },
+ max_size {},
+ border_size {},
+ adjusted_rect {},
+ auto_adjust_to_content_size { false },
+ font {},
+ font_size { DEFAULT_FONT_SIZE },
+ default_colour {},
+ colour_codes { nullptr },
+ currency_texture {},
+ background {},
+ lines {},
+ line_update_queued { false } {}
+
+void GUILabel::clear() {
+ gui_text = nullptr;
+
+ text = String {};
+ substitution_dict.clear();
+ horizontal_alignment = HORIZONTAL_ALIGNMENT_LEFT;
+ max_size = {};
+ border_size = {};
+ adjusted_rect = {};
+ auto_adjust_to_content_size = false;
+
+ font.unref();
+ font_size = DEFAULT_FONT_SIZE;
+ default_colour = {};
+ colour_codes = nullptr;
+ currency_texture.unref();
+
+ background.unref();
+ lines.clear();
+
+ line_update_queued = false;
+
+ queue_redraw();
+}
+
+String GUILabel::get_gui_text_name() const {
+ return gui_text != nullptr ? Utilities::std_to_godot_string(gui_text->get_name()) : String {};
+}
+
+Error GUILabel::set_gui_text(GUI::Text const* new_gui_text, GFX::Font::colour_codes_t const* override_colour_codes) {
+ if (gui_text == new_gui_text) {
+ return OK;
+ }
+
+ if (new_gui_text == nullptr) {
+ clear();
+ return OK;
+ }
+
+ gui_text = new_gui_text;
+
+ set_text(Utilities::std_to_godot_string(gui_text->get_text()));
+
+ using enum GUI::AlignedElement::format_t;
+ static const ordered_map<GUI::AlignedElement::format_t, HorizontalAlignment> format_map {
+ { left, HORIZONTAL_ALIGNMENT_LEFT },
+ { centre, HORIZONTAL_ALIGNMENT_CENTER },
+ { right, HORIZONTAL_ALIGNMENT_RIGHT }
+ };
+ const decltype(format_map)::const_iterator it = format_map.find(gui_text->get_format());
+ set_horizontal_alignment(it != format_map.end() ? it->second : HORIZONTAL_ALIGNMENT_LEFT);
+
+ set_max_size(Utilities::to_godot_fvec2(gui_text->get_max_size()));
+ set_border_size(Utilities::to_godot_fvec2(gui_text->get_border_size()));
+
+ colour_codes = override_colour_codes != nullptr ? override_colour_codes : &gui_text->get_font()->get_colour_codes();
+ set_default_colour(Utilities::to_godot_color(gui_text->get_font()->get_colour()));
+
+ font.unref();
+ font_size = DEFAULT_FONT_SIZE;
+ currency_texture.unref();
+ background.unref();
+
+ Error err = OK;
+
+ AssetManager* asset_manager = AssetManager::get_singleton();
+ if (asset_manager != nullptr) {
+ const StringName font_filepath = Utilities::std_to_godot_string(gui_text->get_font()->get_fontname());
+ Ref<FontFile> font_file = asset_manager->get_font(font_filepath);
+ if (font_file.is_valid()) {
+ if (set_font_file(font_file) != OK) {
+ err = FAILED;
+ }
+ } else {
+ UtilityFunctions::push_error("Failed to load font \"", font_filepath, "\" for GUILabel");
+ err = FAILED;
+ }
+
+ if (!gui_text->get_texture_file().empty()) {
+ const StringName texture_path = Utilities::std_to_godot_string(gui_text->get_texture_file());
+ Ref<ImageTexture> texture = asset_manager->get_texture(texture_path);
+ if (texture.is_valid()) {
+ set_background_texture(texture);
+ } else {
+ UtilityFunctions::push_error("Failed to load texture \"", texture_path, "\" for GUILabel ", get_name());
+ err = FAILED;
+ }
+ }
+ } else {
+ UtilityFunctions::push_error("Failed to get AssetManager singleton for GUILabel");
+ err = FAILED;
+ }
+
+ _queue_line_update();
+
+ return err;
+}
+
+void GUILabel::set_text(String const& new_text) {
+ if (text != new_text) {
+ text = new_text;
+
+ _queue_line_update();
+ }
+}
+
+void GUILabel::add_substitution(String const& key, String const& value) {
+ Variant& existing_value = substitution_dict[key];
+ if (existing_value != value) {
+ existing_value = value;
+
+ _queue_line_update();
+ }
+}
+
+void GUILabel::set_substitution_dict(Dictionary const& new_substitution_dict) {
+ substitution_dict = new_substitution_dict;
+ _queue_line_update();
+}
+
+void GUILabel::clear_substitutions() {
+ if (!substitution_dict.is_empty()) {
+ substitution_dict.clear();
+
+ _queue_line_update();
+ }
+}
+
+void GUILabel::set_horizontal_alignment(HorizontalAlignment new_horizontal_alignment) {
+ if (horizontal_alignment != new_horizontal_alignment) {
+ horizontal_alignment = new_horizontal_alignment;
+
+ _queue_line_update();
+ }
+}
+
+void GUILabel::set_max_size(Size2 new_max_size) {
+ if (max_size != new_max_size) {
+ max_size = new_max_size;
+
+ set_custom_minimum_size(max_size);
+ set_size(max_size);
+
+ _queue_line_update();
+ }
+}
+
+void GUILabel::set_border_size(Size2 new_border_size) {
+ if (border_size != new_border_size) {
+ border_size = new_border_size;
+
+ update_stylebox_border_size();
+
+ _queue_line_update();
+ }
+}
+
+void GUILabel::set_auto_adjust_to_content_size(bool new_auto_adjust_to_content_size) {
+ if (auto_adjust_to_content_size != new_auto_adjust_to_content_size) {
+ auto_adjust_to_content_size = new_auto_adjust_to_content_size;
+
+ adjust_to_content_size();
+
+ queue_redraw();
+ }
+}
+
+Ref<Font> GUILabel::get_font() const {
+ return font;
+}
+
+void GUILabel::set_font(Ref<Font> const& new_font) {
+ font = new_font;
+
+ _queue_line_update();
+}
+
+Error GUILabel::set_font_file(Ref<FontFile> const& new_font_file) {
+ ERR_FAIL_NULL_V(new_font_file, FAILED);
+
+ set_font(new_font_file);
+
+ return set_font_size(new_font_file->get_fixed_size());
+}
+
+Error GUILabel::set_font_size(int32_t new_font_size) {
+ font_size = new_font_size;
+
+ _queue_line_update();
+
+ AssetManager* asset_manager = AssetManager::get_singleton();
+ ERR_FAIL_NULL_V_MSG(asset_manager, FAILED, "Failed to get AssetManager singleton for GUILabel");
+
+ currency_texture = asset_manager->get_currency_texture(font_size);
+ ERR_FAIL_NULL_V(currency_texture, FAILED);
+
+ return OK;
+}
+
+void GUILabel::set_default_colour(Color const& new_default_colour) {
+ if (default_colour != new_default_colour) {
+ default_colour = new_default_colour;
+ _queue_line_update();
+ }
+}
+
+Ref<GFXSpriteTexture> GUILabel::get_currency_texture() const {
+ return currency_texture;
+}
+
+Ref<StyleBoxTexture> GUILabel::get_background() const {
+ return background;
+}
+
+void GUILabel::set_background_texture(Ref<Texture2D> const& new_texture) {
+ Ref<StyleBoxTexture> new_background;
+
+ if (new_texture.is_valid()) {
+ new_background.instantiate();
+ ERR_FAIL_NULL(new_background);
+
+ new_background->set_texture(new_texture);
+ }
+
+ set_background_stylebox(new_background);
+}
+
+void GUILabel::set_background_stylebox(Ref<StyleBoxTexture> const& new_stylebox_texture) {
+ if (background != new_stylebox_texture) {
+ background = new_stylebox_texture;
+ update_stylebox_border_size();
+ queue_redraw();
+ }
+}
+
+void GUILabel::update_stylebox_border_size() {
+ if (background.is_valid()) {
+ background->set_texture_margin(SIDE_LEFT, border_size.width);
+ background->set_texture_margin(SIDE_RIGHT, border_size.width);
+ background->set_texture_margin(SIDE_TOP, border_size.height);
+ background->set_texture_margin(SIDE_BOTTOM, border_size.height);
+ }
+}
+
+real_t GUILabel::get_string_width(String const& string) const {
+ return font->get_string_size(string, HORIZONTAL_ALIGNMENT_LEFT, -1, font_size).width;
+}
+
+real_t GUILabel::get_segment_width(segment_t const& segment) const {
+ if (string_segment_t const* string_segment = std::get_if<string_segment_t>(&segment)) {
+ return string_segment->width;
+ } else if (currency_texture.is_valid()) {
+ return currency_texture->get_width();
+ } else {
+ return 0.0_real;
+ }
+}
+
+void GUILabel::_queue_line_update() {
+ if (!line_update_queued) {
+ line_update_queued = true;
+
+ callable_mp(this, &GUILabel::_update_lines).call_deferred();
+ }
+}
+
+void GUILabel::_update_lines() {
+ line_update_queued = false;
+ lines.clear();
+
+ if (text.is_empty() || font.is_null()) {
+ queue_redraw();
+ return;
+ }
+
+ String const& base_text = is_auto_translating() ? tr(text) : text;
+
+ String const& substituted_text = generate_substituted_text(base_text);
+
+ auto const& [display_text, colour_instructions] = generate_display_text_and_colour_instructions(substituted_text);
+
+ std::vector<line_t> unwrapped_lines = generate_lines_and_segments(display_text, colour_instructions);
+
+ lines = wrap_lines(unwrapped_lines);
+
+ adjust_to_content_size();
+
+ queue_redraw();
+}
+
+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) {
+ 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());
+ 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()
+ );
+ 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();
+ }
+
+ if (start_pos < base_text.length()) {
+ result += base_text.substr(start_pos);
+ }
+
+ return result;
+}
+
+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) {
+ 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()];
+
+ // 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;
+ } else {
+ return { std::move(result), std::move(colour_instructions) };
+ }
+ }
+
+ result += substituted_text.substr(start_pos);
+
+ return { std::move(result), std::move(colour_instructions) };
+}
+
+std::vector<GUILabel::line_t> GUILabel::generate_lines_and_segments(
+ String const& display_text, colour_instructions_t const& colour_instructions
+) const {
+ static constexpr char RESET_COLOUR_CODE = '!';
+
+ std::vector<line_t> unwrapped_lines;
+ colour_instructions_t::const_iterator colour_it = colour_instructions.begin();
+ Color current_colour = default_colour;
+ int64_t section_start = 0;
+
+ unwrapped_lines.emplace_back();
+
+ for (int64_t idx = 0; idx < display_text.length(); ++idx) {
+ if (colour_it != colour_instructions.end() && idx == colour_it->first) {
+ Color new_colour = current_colour;
+ if (colour_it->second == RESET_COLOUR_CODE) {
+ new_colour = default_colour;
+ } else {
+ const GFX::Font::colour_codes_t::const_iterator it = colour_codes->find(colour_it->second);
+ if (it != colour_codes->end()) {
+ new_colour = Utilities::to_godot_color(it->second);
+ }
+ }
+ ++colour_it;
+
+ if (current_colour != new_colour) {
+ if (section_start < idx) {
+ separate_lines(
+ display_text.substr(section_start, idx - section_start), current_colour, unwrapped_lines
+ );
+ section_start = idx;
+ }
+ current_colour = new_colour;
+ }
+ }
+ }
+
+ if (section_start < display_text.length()) {
+ separate_lines(display_text.substr(section_start), current_colour, unwrapped_lines);
+ }
+
+ return unwrapped_lines;
+}
+
+void GUILabel::separate_lines(
+ String const& string, Color const& colour, std::vector<line_t>& unwrapped_lines
+) const {
+ static const String NEWLINE_MARKER = "\n";
+
+ int64_t start_pos = 0;
+ int64_t newline_pos;
+
+ while ((newline_pos = string.find(NEWLINE_MARKER, start_pos)) != -1) {
+ if (start_pos < newline_pos) {
+ separate_currency_segments(string.substr(start_pos, newline_pos - start_pos), colour, unwrapped_lines.back());
+ }
+
+ unwrapped_lines.emplace_back();
+
+ start_pos = newline_pos + NEWLINE_MARKER.length();
+ }
+
+ if (start_pos < string.length()) {
+ separate_currency_segments(string.substr(start_pos), colour, unwrapped_lines.back());
+ }
+}
+
+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);
+ line.segments.emplace_back(string_segment_t { std::move(substring), colour, width });
+ line.width += width;
+ };
+
+ int64_t start_pos = 0;
+ int64_t marker_pos;
+
+ 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) {
+ if (start_pos < marker_pos) {
+ push_string_segment(start_pos, marker_pos);
+ }
+
+ line.segments.push_back(currency_segment_t {});
+ line.width += currency_width;
+
+ start_pos = marker_pos + CURRENCY_MARKER.length();
+ }
+
+ if (start_pos < string.length()) {
+ push_string_segment(start_pos, string.length());
+ }
+}
+
+std::vector<GUILabel::line_t> GUILabel::wrap_lines(std::vector<line_t>& unwrapped_lines) const {
+ std::vector<line_t> wrapped_lines;
+
+ const Size2 max_content_size = max_size - 2 * border_size;
+
+ for (line_t& line : unwrapped_lines) {
+ if (line.width <= max_content_size.width) {
+ wrapped_lines.push_back(std::move(line));
+ } else {
+ line_t* current_line = &wrapped_lines.emplace_back();
+
+ for (segment_t& segment : line.segments) {
+ const real_t segment_width = get_segment_width(segment);
+
+ if (current_line->width + segment_width <= max_content_size.width) {
+ // Segement on current line
+ current_line->segments.emplace_back(std::move(segment));
+ current_line->width += segment_width;
+ } else if (string_segment_t const* string_segment = std::get_if<string_segment_t>(&segment)) {
+ // String segement wrapped onto new line
+ static const String SPACE_MARKER = " ";
+
+ String const& string = string_segment->text;
+
+ int64_t start_pos = 0;
+
+ while (start_pos < string.length()) {
+ String whole_segment_string = string.substr(start_pos);
+ real_t whole_segment_width = get_string_width(whole_segment_string);
+
+ if (current_line->width + whole_segment_width > max_content_size.width) {
+ String new_segment_string;
+ real_t new_segment_width = 0.0_real;
+
+ int64_t last_marker_pos = 0;
+ int64_t marker_pos;
+
+ while ((marker_pos = whole_segment_string.find(SPACE_MARKER, last_marker_pos)) != -1) {
+ String substring = whole_segment_string.substr(0, marker_pos);
+ const real_t width = get_string_width(substring);
+ if (current_line->width + width <= max_content_size.width) {
+ new_segment_string = std::move(substring);
+ new_segment_width = width;
+ last_marker_pos = marker_pos + SPACE_MARKER.length();
+ } else {
+ break;
+ }
+ }
+
+ if (last_marker_pos != 0 || !current_line->segments.empty()) {
+ if (!new_segment_string.is_empty()) {
+ current_line->segments.emplace_back(string_segment_t {
+ std::move(new_segment_string), string_segment->colour, new_segment_width
+ });
+ current_line->width += new_segment_width;
+ }
+
+ current_line = &wrapped_lines.emplace_back();
+
+ start_pos += last_marker_pos;
+
+ continue;
+ }
+ }
+ current_line->segments.emplace_back(string_segment_t {
+ std::move(whole_segment_string), string_segment->colour, whole_segment_width
+ });
+ current_line->width += whole_segment_width;
+ break;
+ }
+
+ } else {
+ // Currency segement on new line
+ line_t* current_line = &wrapped_lines.emplace_back();
+ current_line->segments.push_back(std::move(segment));
+ current_line->width = segment_width;
+ }
+ }
+ }
+ }
+
+ const auto is_over_max_height = [this, &wrapped_lines, &max_content_size]() -> bool {
+ return wrapped_lines.size() > 1
+ && wrapped_lines.size() * font->get_height(font_size) > max_content_size.height;
+ };
+
+ if (is_over_max_height()) {
+ do {
+ wrapped_lines.pop_back();
+ } while (is_over_max_height());
+
+ static const String ELLIPSIS = "...";
+ const real_t ellipsis_width = get_string_width(ELLIPSIS);
+
+ line_t& last_line = wrapped_lines.back();
+ Color last_colour = default_colour;
+
+ while (last_line.segments.size() > 0 && last_line.width + ellipsis_width > max_content_size.width) {
+ if (string_segment_t* string_segment = std::get_if<string_segment_t>(&last_line.segments.back())) {
+ last_colour = string_segment->colour;
+
+ String& last_string = string_segment->text;
+ if (last_string.length() > 1) {
+ last_string = last_string.substr(0, last_string.length() - 1);
+
+ last_line.width -= string_segment->width;
+ string_segment->width = get_string_width(last_string);
+ last_line.width += string_segment->width;
+ } else {
+ last_line.width -= string_segment->width;
+ last_line.segments.pop_back();
+ }
+ } else {
+ last_line.width -= currency_texture->get_width();
+ last_line.segments.pop_back();
+ }
+ }
+
+ last_line.segments.push_back(string_segment_t { ELLIPSIS, last_colour, ellipsis_width });
+ last_line.width += ellipsis_width;
+ }
+
+ return wrapped_lines;
+}
+
+void GUILabel::adjust_to_content_size() {
+ if (auto_adjust_to_content_size) {
+ adjusted_rect = {};
+
+ for (line_t const& line : lines) {
+ if (adjusted_rect.size.width < line.width) {
+ adjusted_rect.size.width = line.width;
+ }
+ }
+
+ adjusted_rect.size.height = lines.size() * font->get_height(font_size);
+
+ adjusted_rect.size += 2 * border_size;
+
+ switch (horizontal_alignment) {
+ case HORIZONTAL_ALIGNMENT_CENTER: {
+ adjusted_rect.position.x = (max_size.width - adjusted_rect.size.width + 1.0_real) / 2.0_real;
+ } break;
+ case HORIZONTAL_ALIGNMENT_RIGHT: {
+ adjusted_rect.position.x = max_size.width - adjusted_rect.size.width;
+ } break;
+ case HORIZONTAL_ALIGNMENT_LEFT:
+ default:
+ break;
+ }
+ } else {
+ adjusted_rect = { {}, max_size };
+ }
+}
diff --git a/extension/src/openvic-extension/classes/GUILabel.hpp b/extension/src/openvic-extension/classes/GUILabel.hpp
new file mode 100644
index 0000000..e0982b2
--- /dev/null
+++ b/extension/src/openvic-extension/classes/GUILabel.hpp
@@ -0,0 +1,116 @@
+#pragma once
+
+#include <godot_cpp/classes/control.hpp>
+#include <godot_cpp/classes/font.hpp>
+#include <godot_cpp/classes/font_file.hpp>
+#include <godot_cpp/classes/style_box_texture.hpp>
+
+#include <openvic-simulation/interface/GUI.hpp>
+
+#include "openvic-extension/classes/GFXSpriteTexture.hpp"
+
+namespace OpenVic {
+ class GUILabel : public godot::Control {
+ GDCLASS(GUILabel, godot::Control)
+
+ using colour_instructions_t = std::vector<std::pair<int64_t, char>>;
+
+ GUI::Text const* PROPERTY(gui_text);
+
+ godot::String PROPERTY(text);
+ godot::Dictionary PROPERTY(substitution_dict);
+ godot::HorizontalAlignment PROPERTY(horizontal_alignment);
+ godot::Size2 PROPERTY(max_size); // Actual max size is max_size - 2 * border_size
+ godot::Size2 PROPERTY(border_size); // The padding between the Nodes bounding box and the text within it
+ godot::Rect2 PROPERTY(adjusted_rect); // Offset + size after adjustment to fit content size
+ bool PROPERTY_CUSTOM_PREFIX(auto_adjust_to_content_size, will);
+
+ godot::Ref<godot::Font> font;
+ int32_t PROPERTY(font_size);
+ godot::Color PROPERTY(default_colour);
+ GFX::Font::colour_codes_t const* colour_codes;
+ godot::Ref<GFXSpriteTexture> currency_texture;
+
+ godot::Ref<godot::StyleBoxTexture> background;
+
+ struct string_segment_t {
+ godot::String text;
+ godot::Color colour;
+ real_t width;
+ };
+ using currency_segment_t = std::monostate;
+ using segment_t = std::variant<string_segment_t, currency_segment_t>;
+ struct line_t {
+ std::vector<segment_t> segments;
+ real_t width {};
+ };
+
+ std::vector<line_t> lines;
+
+ bool line_update_queued;
+
+ protected:
+ static void _bind_methods();
+
+ void _notification(int what);
+
+ public:
+ GUILabel();
+
+ /* Reset gui_text to nullptr and reset current text. */
+ void clear();
+ /* Return the name of the GUI::Text, or an empty String if it's null. */
+ godot::String get_gui_text_name() const;
+ /* Set the GUI::Text. */
+ godot::Error set_gui_text(
+ GUI::Text const* new_gui_text, GFX::Font::colour_codes_t const* override_colour_codes = nullptr
+ );
+
+ void set_text(godot::String const& new_text);
+
+ void add_substitution(godot::String const& key, godot::String const& value);
+ void set_substitution_dict(godot::Dictionary const& new_substitution_dict);
+ void clear_substitutions();
+
+ void set_horizontal_alignment(godot::HorizontalAlignment new_horizontal_alignment);
+ void set_max_size(godot::Size2 new_max_size);
+ void set_border_size(godot::Size2 new_border_size);
+ void set_auto_adjust_to_content_size(bool new_auto_adjust_to_content_size);
+
+ godot::Ref<godot::Font> get_font() const;
+ void set_font(godot::Ref<godot::Font> const& new_font);
+ godot::Error set_font_file(godot::Ref<godot::FontFile> const& new_font_file);
+ godot::Error set_font_size(int32_t new_font_size);
+ void set_default_colour(godot::Color const& new_default_colour);
+
+ godot::Ref<GFXSpriteTexture> get_currency_texture() const;
+
+ godot::Ref<godot::StyleBoxTexture> get_background() const;
+ void set_background_texture(godot::Ref<godot::Texture2D> const& new_texture);
+ void set_background_stylebox(godot::Ref<godot::StyleBoxTexture> const& new_stylebox_texture);
+
+ private:
+ void update_stylebox_border_size();
+ real_t get_string_width(godot::String const& string) const;
+ real_t get_segment_width(segment_t const& segment) const;
+
+ void _queue_line_update();
+ void _update_lines();
+
+ godot::String generate_substituted_text(godot::String const& base_text) const;
+ std::pair<godot::String, colour_instructions_t> generate_display_text_and_colour_instructions(
+ godot::String const& substituted_text
+ ) const;
+ std::vector<line_t> generate_lines_and_segments(
+ godot::String const& display_text, colour_instructions_t const& colour_instructions
+ ) const;
+ void separate_lines(
+ godot::String const& string, godot::Color const& colour, std::vector<line_t>& lines
+ ) const;
+ void separate_currency_segments(
+ godot::String const& string, godot::Color const& colour, line_t& line
+ ) const;
+ std::vector<line_t> wrap_lines(std::vector<line_t>& unwrapped_lines) const;
+ void adjust_to_content_size();
+ };
+}
diff --git a/extension/src/openvic-extension/classes/GUINode.cpp b/extension/src/openvic-extension/classes/GUINode.cpp
index bd8197b..25ef821 100644
--- a/extension/src/openvic-extension/classes/GUINode.cpp
+++ b/extension/src/openvic-extension/classes/GUINode.cpp
@@ -40,7 +40,7 @@ using namespace OpenVic;
#define APPLY_TO_CHILD_TYPES(F) \
F(Button, button) \
- F(Label, label) \
+ F(GUILabel, gui_label) \
F(Panel, panel) \
F(TextureProgressBar, progress_bar) \
F(TextureRect, texture_rect) \
@@ -90,6 +90,7 @@ void GUINode::_bind_methods() {
OV_BIND_SMETHOD(int_to_string_suffixed, { "val" });
OV_BIND_SMETHOD(float_to_string_suffixed, { "val" });
OV_BIND_SMETHOD(float_to_string_dp, { "val", "decimal_places" });
+ OV_BIND_SMETHOD(float_to_string_dp_dynamic, { "val" });
OV_BIND_SMETHOD(format_province_name, { "province_identifier" });
}
@@ -266,6 +267,10 @@ String GUINode::float_to_string_dp(float val, int32_t decimal_places) {
return Utilities::float_to_string_dp(val, decimal_places);
}
+String GUINode::float_to_string_dp_dynamic(float val) {
+ return Utilities::float_to_string_dp_dynamic(val);
+}
+
String GUINode::format_province_name(String const& province_identifier) {
if (!province_identifier.is_empty()) {
static const String province_prefix = "PROV";
diff --git a/extension/src/openvic-extension/classes/GUINode.hpp b/extension/src/openvic-extension/classes/GUINode.hpp
index f8eb62c..73ca92b 100644
--- a/extension/src/openvic-extension/classes/GUINode.hpp
+++ b/extension/src/openvic-extension/classes/GUINode.hpp
@@ -5,7 +5,6 @@
#include <godot_cpp/classes/control.hpp>
#include <godot_cpp/classes/image.hpp>
#include <godot_cpp/classes/input_event.hpp>
-#include <godot_cpp/classes/label.hpp>
#include <godot_cpp/classes/line_edit.hpp>
#include <godot_cpp/classes/node.hpp>
#include <godot_cpp/classes/panel.hpp>
@@ -22,6 +21,7 @@
#include "openvic-extension/classes/GFXMaskedFlagTexture.hpp"
#include "openvic-extension/classes/GFXPieChartTexture.hpp"
#include "openvic-extension/classes/GFXSpriteTexture.hpp"
+#include "openvic-extension/classes/GUILabel.hpp"
#include "openvic-extension/classes/GUIListBox.hpp"
#include "openvic-extension/classes/GUIOverlappingElementsBox.hpp"
#include "openvic-extension/classes/GUIScrollbar.hpp"
@@ -52,7 +52,7 @@ 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 godot::Label* get_label_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);
@@ -62,7 +62,7 @@ namespace OpenVic {
static godot::LineEdit* get_line_edit_from_node(godot::Node* node);
godot::Button* get_button_from_nodepath(godot::NodePath const& path) const;
- godot::Label* get_label_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;
@@ -91,6 +91,8 @@ namespace OpenVic {
static godot::String int_to_string_suffixed(int64_t val);
static godot::String float_to_string_suffixed(float val);
static godot::String float_to_string_dp(float val, int32_t decimal_places);
+ // 3dp if abs(val) < 2 else 2dp if abs(val) < 10 else 1dp
+ static godot::String float_to_string_dp_dynamic(float val);
static godot::String format_province_name(godot::String const& province_identifier);
godot::Ref<godot::BitMap> get_click_mask() const;
diff --git a/extension/src/openvic-extension/register_types.cpp b/extension/src/openvic-extension/register_types.cpp
index 0b9d779..bd50e34 100644
--- a/extension/src/openvic-extension/register_types.cpp
+++ b/extension/src/openvic-extension/register_types.cpp
@@ -6,6 +6,7 @@
#include "openvic-extension/classes/GFXSpriteTexture.hpp"
#include "openvic-extension/classes/GFXMaskedFlagTexture.hpp"
#include "openvic-extension/classes/GFXPieChartTexture.hpp"
+#include "openvic-extension/classes/GUILabel.hpp"
#include "openvic-extension/classes/GUIListBox.hpp"
#include "openvic-extension/classes/GUINode.hpp"
#include "openvic-extension/classes/GUIOverlappingElementsBox.hpp"
@@ -43,10 +44,6 @@ void initialize_openvic_types(ModuleInitializationLevel p_level) {
_load_localisation = memnew(LoadLocalisation);
Engine::get_singleton()->register_singleton("LoadLocalisation", LoadLocalisation::get_singleton());
- ClassDB::register_class<SoundSingleton>();
- _sound_singleton = memnew(SoundSingleton);
- Engine::get_singleton()->register_singleton("SoundSingleton", SoundSingleton::get_singleton());
-
ClassDB::register_class<GameSingleton>();
_game_singleton = memnew(GameSingleton);
Engine::get_singleton()->register_singleton("GameSingleton", GameSingleton::get_singleton());
@@ -63,6 +60,10 @@ void initialize_openvic_types(ModuleInitializationLevel p_level) {
_asset_manager_singleton = memnew(AssetManager);
Engine::get_singleton()->register_singleton("AssetManager", AssetManager::get_singleton());
+ ClassDB::register_class<SoundSingleton>();
+ _sound_singleton = memnew(SoundSingleton);
+ Engine::get_singleton()->register_singleton("SoundSingleton", SoundSingleton::get_singleton());
+
ClassDB::register_class<MapMesh>();
ClassDB::register_abstract_class<GFXCorneredTileSupportingTexture>();
@@ -75,6 +76,7 @@ void initialize_openvic_types(ModuleInitializationLevel p_level) {
ClassDB::register_class<GFXMaskedFlagTexture>();
ClassDB::register_class<GFXPieChartTexture>();
+ ClassDB::register_class<GUILabel>();
ClassDB::register_class<GUIListBox>();
ClassDB::register_class<GUINode>();
ClassDB::register_class<GUIOverlappingElementsBox>();
diff --git a/extension/src/openvic-extension/singletons/AssetManager.cpp b/extension/src/openvic-extension/singletons/AssetManager.cpp
index eec1ada..d17edd0 100644
--- a/extension/src/openvic-extension/singletons/AssetManager.cpp
+++ b/extension/src/openvic-extension/singletons/AssetManager.cpp
@@ -4,6 +4,7 @@
#include "openvic-extension/singletons/GameSingleton.hpp"
#include "openvic-extension/utility/ClassBindings.hpp"
+#include "openvic-extension/utility/UITools.hpp"
#include "openvic-extension/utility/Utilities.hpp"
using namespace godot;
@@ -119,7 +120,7 @@ Ref<ImageTexture> AssetManager::get_texture(StringName const& path, LoadFlags lo
}
}
-Ref<Font> AssetManager::get_font(StringName const& name) {
+Ref<FontFile> AssetManager::get_font(StringName const& name) {
const font_map_t::const_iterator it = fonts.find(name);
if (it != fonts.end()) {
ERR_FAIL_NULL_V_MSG(it->second, nullptr, vformat("Failed to load font previously: %s", name));
@@ -152,7 +153,7 @@ Ref<Font> AssetManager::get_font(StringName const& name) {
ERR_FAIL_V_MSG(nullptr, vformat("Failed to look up font: %s", font_path));
}
- const Ref<Font> font = Utilities::load_godot_font(lookedup_font_path, image);
+ const Ref<FontFile> font = Utilities::load_godot_font(lookedup_font_path, image);
if (font.is_null()) {
fonts.emplace(name, nullptr);
@@ -165,3 +166,40 @@ Ref<Font> AssetManager::get_font(StringName const& name) {
fonts.emplace(name, font);
return font;
}
+
+Error AssetManager::preload_textures() {
+ static const String currency_sprite_big = "GFX_tooltip_money_big";
+ static const String currency_sprite_medium = "GFX_tooltip_money_small";
+ static const String currency_sprite_small = "GFX_tooltip_money";
+
+ constexpr auto load = [](String const& sprite_name, Ref<GFXSpriteTexture>& texture) -> bool {
+ GFX::Sprite const* sprite = UITools::get_gfx_sprite(sprite_name);
+ ERR_FAIL_NULL_V(sprite, false);
+
+ GFX::IconTextureSprite const* icon_sprite = sprite->cast_to<GFX::IconTextureSprite>();
+ ERR_FAIL_NULL_V(icon_sprite, false);
+
+ texture = GFXSpriteTexture::make_gfx_sprite_texture(icon_sprite);
+ ERR_FAIL_NULL_V(texture, false);
+
+ return true;
+ };
+
+ bool ret = true;
+
+ ret &= load(currency_sprite_big, currency_texture_big);
+ ret &= load(currency_sprite_medium, currency_texture_medium);
+ ret &= load(currency_sprite_small, currency_texture_small);
+
+ return ERR(ret);
+}
+
+Ref<GFXSpriteTexture> const& AssetManager::get_currency_texture(real_t height) const {
+ if (height > currency_texture_big->get_height()) {
+ return currency_texture_big;
+ } else if (height > currency_texture_medium->get_height()) {
+ return currency_texture_medium;
+ } else {
+ return currency_texture_small;
+ }
+}
diff --git a/extension/src/openvic-extension/singletons/AssetManager.hpp b/extension/src/openvic-extension/singletons/AssetManager.hpp
index 0856d05..deca309 100644
--- a/extension/src/openvic-extension/singletons/AssetManager.hpp
+++ b/extension/src/openvic-extension/singletons/AssetManager.hpp
@@ -1,12 +1,14 @@
#pragma once
#include <godot_cpp/classes/atlas_texture.hpp>
-#include <godot_cpp/classes/font.hpp>
+#include <godot_cpp/classes/font_file.hpp>
#include <godot_cpp/classes/image_texture.hpp>
#include <godot_cpp/core/class_db.hpp>
#include <openvic-simulation/interface/GFXSprite.hpp>
+#include "openvic-extension/classes/GFXSpriteTexture.hpp"
+
namespace OpenVic {
class AssetManager : public godot::Object {
GDCLASS(AssetManager, godot::Object)
@@ -32,7 +34,7 @@ namespace OpenVic {
};
/* deque_ordered_map to avoid the need to reallocate. */
using image_asset_map_t = deque_ordered_map<godot::StringName, image_asset_t>;
- using font_map_t = deque_ordered_map<godot::StringName, godot::Ref<godot::Font>>;
+ using font_map_t = deque_ordered_map<godot::StringName, godot::Ref<godot::FontFile>>;
image_asset_map_t image_assets;
font_map_t fonts;
@@ -68,7 +70,18 @@ namespace OpenVic {
/* 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::Font> get_font(godot::StringName const& name);
+ godot::Ref<godot::FontFile> get_font(godot::StringName const& name);
+
+ private:
+ godot::Ref<GFXSpriteTexture> PROPERTY(currency_texture_big); // 32x32
+ godot::Ref<GFXSpriteTexture> PROPERTY(currency_texture_medium); // 24x24
+ godot::Ref<GFXSpriteTexture> PROPERTY(currency_texture_small); // 16x16
+
+ public:
+ godot::Error preload_textures();
+
+ /* Get the largest currency texture with height less than the specified font height. */
+ godot::Ref<GFXSpriteTexture> const& get_currency_texture(real_t height) const;
};
}
diff --git a/extension/src/openvic-extension/singletons/GameSingleton.cpp b/extension/src/openvic-extension/singletons/GameSingleton.cpp
index 5268789..13324d0 100644
--- a/extension/src/openvic-extension/singletons/GameSingleton.cpp
+++ b/extension/src/openvic-extension/singletons/GameSingleton.cpp
@@ -597,7 +597,7 @@ Error GameSingleton::set_compatibility_mode_roots(PackedStringArray const& file_
Error GameSingleton::load_defines_compatibility_mode() {
Error err = OK;
auto add_message = std::bind_front(&LoadLocalisation::add_message, LoadLocalisation::get_singleton());
-
+
if (!game_manager.load_definitions(add_message)) {
UtilityFunctions::push_error("Failed to load defines!");
err = FAILED;
@@ -616,6 +616,12 @@ Error GameSingleton::load_defines_compatibility_mode() {
err = FAILED;
}
+ AssetManager* asset_manager = AssetManager::get_singleton();
+ if (asset_manager == nullptr || asset_manager->preload_textures() != OK) {
+ UtilityFunctions::push_error("Failed to preload assets!");
+ err = FAILED;
+ }
+
return err;
}
diff --git a/extension/src/openvic-extension/utility/UITools.cpp b/extension/src/openvic-extension/utility/UITools.cpp
index cffab22..723fb24 100644
--- a/extension/src/openvic-extension/utility/UITools.cpp
+++ b/extension/src/openvic-extension/utility/UITools.cpp
@@ -2,7 +2,6 @@
#include <godot_cpp/classes/button.hpp>
#include <godot_cpp/classes/color_rect.hpp>
-#include <godot_cpp/classes/label.hpp>
#include <godot_cpp/classes/line_edit.hpp>
#include <godot_cpp/classes/panel.hpp>
#include <godot_cpp/classes/style_box_empty.hpp>
@@ -16,6 +15,7 @@
#include "openvic-extension/classes/GFXSpriteTexture.hpp"
#include "openvic-extension/classes/GFXMaskedFlagTexture.hpp"
#include "openvic-extension/classes/GFXPieChartTexture.hpp"
+#include "openvic-extension/classes/GUILabel.hpp"
#include "openvic-extension/classes/GUIListBox.hpp"
#include "openvic-extension/classes/GUIOverlappingElementsBox.hpp"
#include "openvic-extension/classes/GUIScrollbar.hpp"
@@ -500,55 +500,26 @@ static bool generate_checkbox(generate_gui_args_t&& args) {
}
static bool generate_text(generate_gui_args_t&& args) {
- using namespace OpenVic::Utilities::literals;
-
GUI::Text const& text = static_cast<GUI::Text const&>(args.element);
const String text_name = Utilities::std_to_godot_string(text.get_name());
- Label* godot_label = nullptr;
- bool ret = new_control(godot_label, text, args.name);
- ERR_FAIL_NULL_V_MSG(godot_label, false, vformat("Failed to create Label for GUI text %s", text_name));
-
- godot_label->set_text(Utilities::std_to_godot_string(text.get_text()));
+ GUILabel* gui_label = nullptr;
+ bool ret = new_control(gui_label, text, args.name);
+ ERR_FAIL_NULL_V_MSG(gui_label, false, vformat("Failed to create GUILabel for GUI text %s", text_name));
- static const Vector2 default_padding { 1.0_real, 0.0_real };
- const Vector2 border_size = Utilities::to_godot_fvec2(text.get_border_size()) + default_padding;
- const Vector2 max_size = Utilities::to_godot_fvec2(text.get_max_size());
- godot_label->set_position(godot_label->get_position() + border_size);
- godot_label->set_custom_minimum_size(max_size - 2 * border_size);
+ gui_label->set_mouse_filter(Control::MOUSE_FILTER_IGNORE);
- using enum GUI::AlignedElement::format_t;
- static const ordered_map<GUI::AlignedElement::format_t, HorizontalAlignment> format_map {
- { left, HORIZONTAL_ALIGNMENT_LEFT },
- { centre, HORIZONTAL_ALIGNMENT_CENTER },
- { right, HORIZONTAL_ALIGNMENT_RIGHT }
- };
+ GameSingleton const* game_singleton = GameSingleton::get_singleton();
+ GFX::Font::colour_codes_t const* override_colour_codes = game_singleton != nullptr
+ ? &game_singleton->get_definition_manager().get_ui_manager().get_universal_colour_codes() : nullptr;
- const decltype(format_map)::const_iterator it = format_map.find(text.get_format());
- if (it != format_map.end()) {
- godot_label->set_horizontal_alignment(it->second);
- } else {
- UtilityFunctions::push_error("Invalid text format (horizontal alignment) for GUI text ", text_name);
+ if (gui_label->set_gui_text(&text, override_colour_codes) != OK) {
+ UtilityFunctions::push_error("Error initialising GUILabel for GUI text ", text_name);
ret = false;
}
- if (text.get_font() != nullptr) {
- const StringName font_file = Utilities::std_to_godot_string(text.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_label->add_theme_font_override(font_theme, font);
- } else {
- UtilityFunctions::push_error("Failed to load font \"", font_file, "\" for GUI text ", text_name);
- ret = false;
- }
- const Color colour = Utilities::to_godot_color(text.get_font()->get_colour());
- static const StringName font_color_theme = "font_color";
- godot_label->add_theme_color_override(font_color_theme, colour);
- }
-
- args.result = godot_label;
+ args.result = gui_label;
return ret;
}
@@ -564,7 +535,14 @@ static bool generate_overlapping_elements(generate_gui_args_t&& args) {
vformat("Failed to create GUIOverlappingElementsBox for GUI overlapping elements %s", overlapping_elements_name)
);
box->set_mouse_filter(Control::MOUSE_FILTER_IGNORE);
- ret &= box->set_gui_overlapping_elements_box(&overlapping_elements) == OK;
+
+ if (box->set_gui_overlapping_elements_box(&overlapping_elements) != OK) {
+ UtilityFunctions::push_error(
+ "Error initialising GUIOverlappingElementsBox for GUI overlapping elements ", overlapping_elements_name
+ );
+ ret = false;
+ }
+
args.result = box;
return ret;
}
diff --git a/extension/src/openvic-extension/utility/Utilities.cpp b/extension/src/openvic-extension/utility/Utilities.cpp
index 4a774a7..1fcdea8 100644
--- a/extension/src/openvic-extension/utility/Utilities.cpp
+++ b/extension/src/openvic-extension/utility/Utilities.cpp
@@ -63,6 +63,11 @@ String Utilities::float_to_string_dp(float val, int32_t decimal_places) {
return String::num(val, decimal_places).pad_decimals(decimal_places);
}
+String Utilities::float_to_string_dp_dynamic(float val) {
+ const float abs_val = std::abs(val);
+ return float_to_string_dp(val, abs_val < 2.0f ? 3 : abs_val < 10.0f ? 2 : 1);
+}
+
/* Date formatted like this: "January 1, 1836" (with the month localised, if possible). */
String Utilities::date_to_formatted_string(Date date) {
const String month_name = Utilities::std_to_godot_string(date.get_month_name());
diff --git a/extension/src/openvic-extension/utility/Utilities.hpp b/extension/src/openvic-extension/utility/Utilities.hpp
index 49314ca..48be1e0 100644
--- a/extension/src/openvic-extension/utility/Utilities.hpp
+++ b/extension/src/openvic-extension/utility/Utilities.hpp
@@ -27,6 +27,9 @@ namespace OpenVic::Utilities {
godot::String float_to_string_dp(float val, int32_t decimal_places);
+ // 3dp if abs(val) < 2 else 2dp if abs(val) < 10 else 1dp
+ godot::String float_to_string_dp_dynamic(float val);
+
constexpr real_t to_real_t(std::floating_point auto val) {
return static_cast<real_t>(val);
}
diff --git a/game/src/Game/GameSession/NationManagementScreen/BudgetMenu.gd b/game/src/Game/GameSession/NationManagementScreen/BudgetMenu.gd
index 42f0791..20eb198 100644
--- a/game/src/Game/GameSession/NationManagementScreen/BudgetMenu.gd
+++ b/game/src/Game/GameSession/NationManagementScreen/BudgetMenu.gd
@@ -4,36 +4,36 @@ var _active : bool = false
var _incVal : int = 0 # incremental value to see the UI update, replace later by real values
# income
-var _lower_class_label : Label
-var _middle_class_label : Label
-var _upper_class_label : Label
-var _gold_label : Label
-var _total_inc_label : Label
+var _lower_class_label : GUILabel
+var _middle_class_label : GUILabel
+var _upper_class_label : GUILabel
+var _gold_label : GUILabel
+var _total_inc_label : GUILabel
# debt
-var _national_bank_label : Label
-var _total_funds_label : Label
-var _debt_val_label : Label
-var _interest_val_label : Label
+var _national_bank_label : GUILabel
+var _total_funds_label : GUILabel
+var _debt_val_label : GUILabel
+var _interest_val_label : GUILabel
# costs
-var _nat_stock_val_label : Label
-var _nat_stock_exp_label : Label
-var _mil_cost_val_label : Label
-var _overseas_cost_val_label : Label
-var _ind_sub_val_label : Label
-var _admin_efficiency_label : Label
-var _education_exp_label : Label
-var _administration_exp_label : Label
-var _social_exp_label : Label
-var _military_exp_label : Label
-var _total_exp_label : Label
+var _nat_stock_val_label : GUILabel
+var _nat_stock_exp_label : GUILabel
+var _mil_cost_val_label : GUILabel
+var _overseas_cost_val_label : GUILabel
+var _ind_sub_val_label : GUILabel
+var _admin_efficiency_label : GUILabel
+var _education_exp_label : GUILabel
+var _administration_exp_label : GUILabel
+var _social_exp_label : GUILabel
+var _military_exp_label : GUILabel
+var _total_exp_label : GUILabel
# others
-var _tariffs_percent_label : Label
-var _tariff_val_label : Label
-var _diplomatic_balance_label : Label
-var _balance_label : Label
+var _tariffs_percent_label : GUILabel
+var _tariff_val_label : GUILabel
+var _diplomatic_balance_label : GUILabel
+var _balance_label : GUILabel
var _lower_class_chart : GFXPieChartTexture
var _middle_class_chart : GFXPieChartTexture
@@ -55,92 +55,92 @@ func _ready() -> void:
# labels
# income
- _lower_class_label = get_label_from_nodepath(^"./country_budget/tax_0_inc")
- _middle_class_label = get_label_from_nodepath(^"./country_budget/tax_1_inc")
- _upper_class_label = get_label_from_nodepath(^"./country_budget/tax_2_inc")
- _gold_label = get_label_from_nodepath(^"./country_budget/gold_inc")
- _total_inc_label = get_label_from_nodepath(^"./country_budget/total_inc")
+ _lower_class_label = get_gui_label_from_nodepath(^"./country_budget/tax_0_inc")
+ _middle_class_label = get_gui_label_from_nodepath(^"./country_budget/tax_1_inc")
+ _upper_class_label = get_gui_label_from_nodepath(^"./country_budget/tax_2_inc")
+ _gold_label = get_gui_label_from_nodepath(^"./country_budget/gold_inc")
+ _total_inc_label = get_gui_label_from_nodepath(^"./country_budget/total_inc")
# debt
- _national_bank_label = get_label_from_nodepath(^"./country_budget/national_bank_val")
- _total_funds_label = get_label_from_nodepath(^"./country_budget/total_funds_val")
- _debt_val_label = get_label_from_nodepath(^"./country_budget/debt_val")
- _interest_val_label = get_label_from_nodepath(^"./country_budget/interest_val")
+ _national_bank_label = get_gui_label_from_nodepath(^"./country_budget/national_bank_val")
+ _total_funds_label = get_gui_label_from_nodepath(^"./country_budget/total_funds_val")
+ _debt_val_label = get_gui_label_from_nodepath(^"./country_budget/debt_val")
+ _interest_val_label = get_gui_label_from_nodepath(^"./country_budget/interest_val")
# costs
- _nat_stock_val_label = get_label_from_nodepath(^"./country_budget/nat_stock_val")
- _nat_stock_exp_label = get_label_from_nodepath(^"./country_budget/nat_stock_est")
- _mil_cost_val_label = get_label_from_nodepath(^"./country_budget/mil_cost_val")
- _overseas_cost_val_label = get_label_from_nodepath(^"./country_budget/overseas_cost_val")
- _ind_sub_val_label = get_label_from_nodepath(^"./country_budget/ind_sub_val")
- _admin_efficiency_label = get_label_from_nodepath(^"./country_budget/admin_efficiency")
- _education_exp_label = get_label_from_nodepath(^"./country_budget/exp_val_0")
- _administration_exp_label = get_label_from_nodepath(^"./country_budget/exp_val_1")
- _social_exp_label = get_label_from_nodepath(^"./country_budget/exp_val_2")
- _military_exp_label = get_label_from_nodepath(^"./country_budget/exp_val_3")
- _total_exp_label = get_label_from_nodepath(^"./country_budget/total_exp")
+ _nat_stock_val_label = get_gui_label_from_nodepath(^"./country_budget/nat_stock_val")
+ _nat_stock_exp_label = get_gui_label_from_nodepath(^"./country_budget/nat_stock_est")
+ _mil_cost_val_label = get_gui_label_from_nodepath(^"./country_budget/mil_cost_val")
+ _overseas_cost_val_label = get_gui_label_from_nodepath(^"./country_budget/overseas_cost_val")
+ _ind_sub_val_label = get_gui_label_from_nodepath(^"./country_budget/ind_sub_val")
+ _admin_efficiency_label = get_gui_label_from_nodepath(^"./country_budget/admin_efficiency")
+ _education_exp_label = get_gui_label_from_nodepath(^"./country_budget/exp_val_0")
+ _administration_exp_label = get_gui_label_from_nodepath(^"./country_budget/exp_val_1")
+ _social_exp_label = get_gui_label_from_nodepath(^"./country_budget/exp_val_2")
+ _military_exp_label = get_gui_label_from_nodepath(^"./country_budget/exp_val_3")
+ _total_exp_label = get_gui_label_from_nodepath(^"./country_budget/total_exp")
# others
- _tariffs_percent_label = get_label_from_nodepath(^"./country_budget/tariffs_percent")
- _tariff_val_label = get_label_from_nodepath(^"./country_budget/tariff_val")
- _diplomatic_balance_label = get_label_from_nodepath(^"./country_budget/diplomatic_balance")
- _balance_label = get_label_from_nodepath(^"./country_budget/balance")
+ _tariffs_percent_label = get_gui_label_from_nodepath(^"./country_budget/tariffs_percent")
+ _tariff_val_label = get_gui_label_from_nodepath(^"./country_budget/tariff_val")
+ _diplomatic_balance_label = get_gui_label_from_nodepath(^"./country_budget/diplomatic_balance")
+ _balance_label = get_gui_label_from_nodepath(^"./country_budget/balance")
# sliders
# 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£" % value)
+ _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.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£" % value)
+ _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.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£" % value)
+ _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.emit_value_changed()
# costs
var _land_stockpile_slider : GUIScrollbar = get_gui_scrollbar_from_nodepath(^"./country_budget/land_stockpile_slider")
if _land_stockpile_slider and _mil_cost_val_label:
- _land_stockpile_slider.value_changed.connect(func(value : int) -> void: _mil_cost_val_label.text = "%s£" % value)
+ _land_stockpile_slider.value_changed.connect(func(value : int) -> void: _mil_cost_val_label.text = "%s¤" % GUINode.float_to_string_dp(value, 2))
_land_stockpile_slider.emit_value_changed()
var _naval_stockpile_slider : GUIScrollbar = get_gui_scrollbar_from_nodepath(^"./country_budget/naval_stockpile_slider")
if _naval_stockpile_slider and _overseas_cost_val_label:
- _naval_stockpile_slider.value_changed.connect(func(value : int) -> void: _overseas_cost_val_label.text = "%s£" % value)
+ _naval_stockpile_slider.value_changed.connect(func(value : int) -> void: _overseas_cost_val_label.text = "%s¤" % GUINode.float_to_string_dp(value, 1))
_naval_stockpile_slider.emit_value_changed()
var _projects_stockpile_slider : GUIScrollbar = get_gui_scrollbar_from_nodepath(^"./country_budget/projects_stockpile_slider")
if _projects_stockpile_slider:
if _nat_stock_val_label:
- _projects_stockpile_slider.value_changed.connect(func(value : int) -> void: _nat_stock_val_label.text = "%s£" % value)
+ _projects_stockpile_slider.value_changed.connect(func(value : int) -> void: _nat_stock_val_label.text = "%s¤" % GUINode.float_to_string_dp_dynamic(value))
if _nat_stock_exp_label:
- _projects_stockpile_slider.value_changed.connect(func(value : int) -> void: _nat_stock_exp_label.text = "%s£" % value)
+ _projects_stockpile_slider.value_changed.connect(func(value : int) -> void: _nat_stock_exp_label.text = "%s¤" % GUINode.float_to_string_dp_dynamic(value))
_projects_stockpile_slider.emit_value_changed()
var _exp_0_slider : GUIScrollbar = get_gui_scrollbar_from_nodepath(^"./country_budget/exp_0_slider")
if _exp_0_slider and _education_exp_label:
- _exp_0_slider.value_changed.connect(func(value : int) -> void: _education_exp_label.text = "%s£" % value)
+ _exp_0_slider.value_changed.connect(func(value : int) -> void: _education_exp_label.text = "%s¤" % GUINode.float_to_string_dp_dynamic(value))
_exp_0_slider.emit_value_changed()
var _exp_1_slider : GUIScrollbar = get_gui_scrollbar_from_nodepath(^"./country_budget/exp_1_slider")
if _exp_1_slider:
if _administration_exp_label:
- _exp_1_slider.value_changed.connect(func(value : int) -> void: _administration_exp_label.text = "%s£" % value)
+ _exp_1_slider.value_changed.connect(func(value : int) -> void: _administration_exp_label.text = "%s¤" % GUINode.float_to_string_dp_dynamic(value))
if _admin_efficiency_label:
- _exp_1_slider.value_changed.connect(func(value : int) -> void: _admin_efficiency_label.text = "%s%%" % value)
+ _exp_1_slider.value_changed.connect(func(value : int) -> void: _admin_efficiency_label.text = "%s%%" % GUINode.float_to_string_dp(value, 1))
_exp_1_slider.emit_value_changed()
var _exp_2_slider : GUIScrollbar = get_gui_scrollbar_from_nodepath(^"./country_budget/exp_2_slider")
if _exp_2_slider and _social_exp_label:
- _exp_2_slider.value_changed.connect(func(value : int) -> void: _social_exp_label.text = "%s£" % value)
+ _exp_2_slider.value_changed.connect(func(value : int) -> void: _social_exp_label.text = "%s¤" % GUINode.float_to_string_dp_dynamic(value))
_exp_2_slider.emit_value_changed()
var _exp_3_slider : GUIScrollbar = get_gui_scrollbar_from_nodepath(^"./country_budget/exp_3_slider")
if _exp_3_slider and _military_exp_label:
- _exp_3_slider.value_changed.connect(func(value : int) -> void: _military_exp_label.text = "%s£" % value)
+ _exp_3_slider.value_changed.connect(func(value : int) -> void: _military_exp_label.text = "%s¤" % GUINode.float_to_string_dp_dynamic(value))
_exp_3_slider.emit_value_changed()
# others
var _tariff_slider : GUIScrollbar = get_gui_scrollbar_from_nodepath(^"./country_budget/tariff_slider")
if _tariff_slider:
if _tariff_val_label:
- _tariff_slider.value_changed.connect(func(value : int) -> void: _tariff_val_label.text = "%s£" % value)
+ _tariff_slider.value_changed.connect(func(value : int) -> void: _tariff_val_label.text = "%s¤" % GUINode.float_to_string_dp_dynamic(value))
if _tariffs_percent_label:
- _tariff_slider.value_changed.connect(func(value : int) -> void: _tariffs_percent_label.text = "%s%%" % value)
+ _tariff_slider.value_changed.connect(func(value : int) -> void: _tariffs_percent_label.text = "%s%%" % GUINode.float_to_string_dp(value, 1))
_tariff_slider.emit_value_changed()
# debt buttons
@@ -188,38 +188,36 @@ func _update_info() -> void:
if _active:
if _gold_label:
- _gold_label.text = "%s£" % (_incVal - (_incVal % 7))
+ _gold_label.text = "%s¤" % GUINode.float_to_string_dp(_incVal - (_incVal % 7), 1)
if _total_inc_label:
- _total_inc_label.text = "%s£" % _incVal
+ _total_inc_label.text = "%s¤" % GUINode.float_to_string_dp_dynamic(_incVal)
if _national_bank_label:
- _national_bank_label.text = "%s£" % (_incVal * 2)
+ _national_bank_label.text = "%s¤" % GUINode.float_to_string_suffixed(_incVal * 2)
if _total_funds_label:
- _total_funds_label.text = "%s£" % (_incVal * 3)
+ _total_funds_label.text = "%s¤" % GUINode.float_to_string_suffixed(_incVal * 3)
if _debt_val_label:
- _debt_val_label.text = "%s£" % (_incVal * 4)
+ _debt_val_label.text = "%s¤" % GUINode.float_to_string_dp(_incVal * 4, 1)
if _interest_val_label:
- _interest_val_label.text = "%s£" % (_incVal * 5)
+ _interest_val_label.text = "%s¤" % GUINode.float_to_string_dp(_incVal * 5, 2)
if _ind_sub_val_label:
- _ind_sub_val_label.text = "%s£" % (_incVal * 6)
+ _ind_sub_val_label.text = "%s¤" % GUINode.float_to_string_dp(_incVal * 6, 1)
if _diplomatic_balance_label:
- _diplomatic_balance_label.text = "%s£" % (_incVal * 8)
+ # TODO - check colours and +/- when non-zero
+ _diplomatic_balance_label.text = "§Y%s¤" % GUINode.float_to_string_dp(_incVal * 8, 1)
if _total_exp_label:
- _total_exp_label.text = "%s£" % (_incVal + 1)
+ _total_exp_label.text = "%s¤" % GUINode.float_to_string_dp_dynamic(_incVal + 1)
if _balance_label:
- _balance_label.text = "%s£" % _incVal
- _balance_label.add_theme_color_override(&"font_color",
- Color.DARK_GREEN if _incVal > 0 else
- (Color.RED if _incVal < 0 else Color.BLACK)
- )
+ var balance : float = _incVal * 2.5
+ _balance_label.text = "§%s%s¤" % ["G+" if balance > 0.0 else "R" if balance < 0.0 else "Y+", GUINode.float_to_string_dp_dynamic(balance)]
# TODO - set strata tax and debt charts
# TODO - update sliders to reflect changes in limits
diff --git a/game/src/Game/GameSession/NationManagementScreen/PopulationMenu.gd b/game/src/Game/GameSession/NationManagementScreen/PopulationMenu.gd
index ad15fbb..e078934 100644
--- a/game/src/Game/GameSession/NationManagementScreen/PopulationMenu.gd
+++ b/game/src/Game/GameSession/NationManagementScreen/PopulationMenu.gd
@@ -14,8 +14,8 @@ 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_name_labels : Array[Label]
-var _province_list_size_labels : Array[Label]
+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]
@@ -33,19 +33,19 @@ var _pop_list_scrollbar : GUIScrollbar
var _pop_list_scroll_index : int = 0
var _pop_list_rows : Array[Panel]
-var _pop_list_size_labels : Array[Label]
+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_culture_labels : Array[Label]
+var _pop_list_culture_labels : Array[GUILabel]
var _pop_list_religion_icons : Array[GFXSpriteTexture]
-var _pop_list_location_labels : Array[Label]
-var _pop_list_militancy_labels : Array[Label]
-var _pop_list_consciousness_labels : Array[Label]
+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_cash_labels : Array[Label]
+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]
@@ -58,7 +58,7 @@ 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_literacy_labels : Array[Label]
+var _pop_list_literacy_labels : Array[GUILabel]
func _ready() -> void:
GameSingleton.gamestate_updated.connect(_update_info)
@@ -142,9 +142,9 @@ func _generate_province_list_row(index : int, type : MenuSingleton.ProvinceListE
)
_province_list_button_icons[index] = GUINode.get_gfx_sprite_texture_from_node(base_button)
- _province_list_name_labels[index] = GUINode.get_label_from_node(entry_panel.get_node(^"./poplist_name"))
+ _province_list_name_labels[index] = GUINode.get_gui_label_from_node(entry_panel.get_node(^"./poplist_name"))
- _province_list_size_labels[index] = GUINode.get_label_from_node(entry_panel.get_node(^"./poplist_numpops"))
+ _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"))
@@ -273,9 +273,9 @@ func _setup_distribution_windows() -> void:
_pop_screen_panel.add_child(distribution_panel)
distribution_panel.set_position(distribution_start + distribution_step * Vector2(index % columns, index / columns))
- var name_label : Label = GUINode.get_label_from_node(distribution_panel.get_node(^"./item_name"))
+ var name_label : GUILabel = GUINode.get_gui_label_from_node(distribution_panel.get_node(^"./item_name"))
if name_label:
- name_label.text = distribution_names[index]
+ name_label.set_text(distribution_names[index])
distribution_chart = GUINode.get_gfx_pie_chart_texture_from_node(distribution_panel.get_node(^"./chart"))
distribution_list = GUINode.get_gui_listbox_from_node(distribution_panel.get_node(^"./member_names"))
@@ -318,7 +318,7 @@ func _setup_pop_list() -> void:
height += pop_row_panel.size.y
_pop_list_rows.push_back(pop_row_panel)
- _pop_list_size_labels.push_back(GUINode.get_label_from_node(pop_row_panel.get_node(^"./pop_size")))
+ _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"))
# TODO - open pop details menu on pop type button press
@@ -328,21 +328,17 @@ func _setup_pop_list() -> void:
_pop_list_producing_icons.push_back(GUINode.get_gfx_sprite_texture_from_node(pop_row_panel.get_node(^"./pop_producing_icon")))
- var culture_label : Label = GUINode.get_label_from_node(pop_row_panel.get_node(^"./pop_nation"))
- if culture_label:
- culture_label.set_text_overrun_behavior(TextServer.OVERRUN_TRIM_ELLIPSIS)
+ 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)
_pop_list_religion_icons.push_back(GUINode.get_gfx_sprite_texture_from_node(pop_row_panel.get_node(^"./pop_religion")))
- var location_label : Label = GUINode.get_label_from_node(pop_row_panel.get_node(^"./pop_location"))
- if location_label:
- location_label.set_text_overrun_behavior(TextServer.OVERRUN_TRIM_ELLIPSIS)
+ 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)
- _pop_list_militancy_labels.push_back(GUINode.get_label_from_node(pop_row_panel.get_node(^"./pop_mil")))
+ _pop_list_militancy_labels.push_back(GUINode.get_gui_label_from_node(pop_row_panel.get_node(^"./pop_mil")))
- _pop_list_consciousness_labels.push_back(GUINode.get_label_from_node(pop_row_panel.get_node(^"./pop_con")))
+ _pop_list_consciousness_labels.push_back(GUINode.get_gui_label_from_node(pop_row_panel.get_node(^"./pop_con")))
_pop_list_ideology_charts.push_back(GUINode.get_gfx_pie_chart_texture_from_node(pop_row_panel.get_node(^"./pop_ideology")))
@@ -350,7 +346,7 @@ func _setup_pop_list() -> void:
_pop_list_unemployment_progressbars.push_back(GUINode.get_progress_bar_from_node(pop_row_panel.get_node(^"./pop_unemployment_bar")))
- _pop_list_cash_labels.push_back(GUINode.get_label_from_node(pop_row_panel.get_node(^"./pop_cash")))
+ _pop_list_cash_labels.push_back(GUINode.get_gui_label_from_node(pop_row_panel.get_node(^"./pop_cash")))
var pop_list_life_needs_progressbar : TextureProgressBar = GUINode.get_progress_bar_from_node(pop_row_panel.get_node(^"./lifeneed_progress"))
if pop_list_life_needs_progressbar:
@@ -394,7 +390,7 @@ func _setup_pop_list() -> void:
_pop_list_size_change_icons.push_back(GUINode.get_gfx_sprite_texture_from_node(pop_row_panel.get_node(^"./growth_indicator")))
- _pop_list_literacy_labels.push_back(GUINode.get_label_from_node(pop_row_panel.get_node(^"./pop_literacy")))
+ _pop_list_literacy_labels.push_back(GUINode.get_gui_label_from_node(pop_row_panel.get_node(^"./pop_literacy")))
func _notification(what : int) -> void:
match what:
@@ -462,7 +458,6 @@ func _update_province_list(scroll_index : int = -1) -> void:
GUINode.format_province_name(province_list_info[name_key]) if type == MenuSingleton.LIST_ENTRY_PROVINCE
else province_list_info[name_key]
)
- _province_list_name_labels[index].set_text_overrun_behavior(TextServer.OVERRUN_TRIM_ELLIPSIS)
if _province_list_size_labels[index]:
_province_list_size_labels[index].set_text(GUINode.int_to_string_suffixed(province_list_info[size_key]))
@@ -551,12 +546,11 @@ func _update_distributions():
if colour_icon_rect:
colour_icon_rect.set_modulate(distribution_row[slice_colour_key])
- var identifier_label : Label = GUINode.get_label_from_node(child.get_node(^"./legend_title"))
+ var identifier_label : GUILabel = GUINode.get_gui_label_from_node(child.get_node(^"./legend_title"))
if identifier_label:
- identifier_label.set_text_overrun_behavior(TextServer.OVERRUN_TRIM_ELLIPSIS)
identifier_label.set_text(distribution_row[slice_identifier_key])
- var weight_label : Label = GUINode.get_label_from_node(child.get_node(^"./legend_value"))
+ var weight_label : GUILabel = GUINode.get_gui_label_from_node(child.get_node(^"./legend_value"))
if weight_label:
weight_label.set_text("%s%%" % GUINode.float_to_string_dp(distribution_row[slice_weight_key] * 100.0, 1))
diff --git a/game/src/Game/GameSession/ProvinceOverviewPanel.gd b/game/src/Game/GameSession/ProvinceOverviewPanel.gd
index 864c0e5..f2669c0 100644
--- a/game/src/Game/GameSession/ProvinceOverviewPanel.gd
+++ b/game/src/Game/GameSession/ProvinceOverviewPanel.gd
@@ -1,13 +1,13 @@
extends GUINode
# Header
-var _province_name_label : Label
-var _state_name_label : Label
+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 _administrative_percentage_label : Label
-var _owner_percentage_label : Label
+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
@@ -15,21 +15,21 @@ var _controller_flag_texture : GFXMaskedFlagTexture
# Statistics
var _rgo_icon_texture : GFXSpriteTexture
-var _rgo_produced_label : Label
-var _rgo_income_label : Label
+var _rgo_produced_label : GUILabel
+var _rgo_income_label : GUILabel
var _rgo_employment_percentage_texture : GFXSpriteTexture
-var _rgo_employment_population_label : Label
-var _rgo_employment_percentage_label : Label
-var _crime_name_label : Label
+var _rgo_employment_population_label : GUILabel
+var _rgo_employment_percentage_label : GUILabel
+var _crime_name_label : GUILabel
var _crime_icon_texture : GFXSpriteTexture
-var _crime_fighting_label : Label
-var _total_population_label : Label
-var _migration_label : Label
-var _population_growth_label : Label
+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 _supply_limit_label : Label
+var _supply_limit_label : GUILabel
var _cores_overlapping_elements_box : GUIOverlappingElementsBox
# Buildings
@@ -48,7 +48,7 @@ class BuildingSlot:
var _expand_button : Button
var _expanding_icon : TextureRect
var _expanding_progress_bar : TextureProgressBar
- var _expanding_label : Label
+ var _expanding_label : GUILabel
func _init(new_slot_index : int, new_slot_node : Control) -> void:
if new_slot_index < 0:
@@ -68,7 +68,7 @@ class BuildingSlot:
else:
icon.hide()
- var building_name := GUINode.get_label_from_node(_slot_node.get_node(^"./description"))
+ 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"))
@@ -79,7 +79,7 @@ class BuildingSlot:
if _expanding_progress_bar:
_expanding_progress_bar.max_value = 1.0
_expanding_progress_bar.step = _expanding_progress_bar.max_value / 100
- _expanding_label = GUINode.get_label_from_node(_slot_node.get_node(^"./expand_text"))
+ _expanding_label = GUINode.get_gui_label_from_node(_slot_node.get_node(^"./expand_text"))
enum ExpansionState { CannotExpand, CanExpand, Preparing, Expanding }
@@ -136,8 +136,8 @@ func _ready() -> void:
close_button.pressed.connect(_on_close_button_pressed)
# Header
- _province_name_label = get_label_from_nodepath(^"./province_view/province_view_header/province_name")
- _state_name_label = get_label_from_nodepath(^"./province_view/province_view_header/state_name")
+ _province_name_label = get_gui_label_from_nodepath(^"./province_view/province_view_header/province_name")
+ _state_name_label = get_gui_label_from_nodepath(^"./province_view/province_view_header/state_name")
if _state_name_label:
# State names are already translated in the MenuSingleton
_state_name_label.auto_translate = false
@@ -150,8 +150,8 @@ func _ready() -> void:
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())
- _administrative_percentage_label = get_label_from_nodepath(^"./province_view/province_view_header/admin_efficiency")
- _owner_percentage_label = get_label_from_nodepath(^"./province_view/province_view_header/owner_presence")
+ _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
@@ -161,17 +161,17 @@ func _ready() -> void:
# Statistics
_rgo_icon_texture = get_gfx_sprite_texture_from_nodepath(^"./province_view/province_statistics/goods_type")
- _rgo_produced_label = get_label_from_nodepath(^"./province_view/province_statistics/produced")
- _rgo_income_label = get_label_from_nodepath(^"./province_view/province_statistics/income")
+ _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_population_label = get_label_from_nodepath(^"./province_view/province_statistics/rgo_population")
- _rgo_employment_percentage_label = get_label_from_nodepath(^"./province_view/province_statistics/rgo_percent")
- _crime_name_label = get_label_from_nodepath(^"./province_view/province_statistics/crime_name")
+ _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_fighting_label = get_label_from_nodepath(^"./province_view/province_statistics/crimefight_percent")
- _total_population_label = get_label_from_nodepath(^"./province_view/province_statistics/total_population")
- _migration_label = get_label_from_nodepath(^"./province_view/province_statistics/migration")
- _population_growth_label = get_label_from_nodepath(^"./province_view/province_statistics/growth")
+ _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")
@@ -183,7 +183,7 @@ func _ready() -> void:
_on_close_button_pressed()
Events.NationManagementScreens.open_nation_management_screen(NationManagement.Screen.POPULATION)
)
- _supply_limit_label = get_label_from_nodepath(^"./province_view/province_statistics/supply_limit_label")
+ _supply_limit_label = get_gui_label_from_nodepath(^"./province_view/province_statistics/supply_limit_label")
_cores_overlapping_elements_box = get_gui_overlapping_elements_box_from_nodepath(^"./province_view/province_statistics/core_icons")
if _cores_overlapping_elements_box and _cores_overlapping_elements_box.set_gui_child_element_name("province_interface", "province_core") != OK:
_cores_overlapping_elements_box = null # hide cores box since we can't do anything with it
@@ -314,7 +314,7 @@ func _update_info() -> void:
if _rgo_income_label:
# TODO - add £ sign and replace placeholder with actual value
- _rgo_income_label.text = "%s £" % GUINode.float_to_string_dp(12.34567, 3)
+ _rgo_income_label.text = "%s¤" % GUINode.float_to_string_dp(12.34567, 3)
if _rgo_employment_percentage_texture:
pass
diff --git a/game/src/Game/GameSession/Topbar.gd b/game/src/Game/GameSession/Topbar.gd
index c1fde1c..d6cc358 100644
--- a/game/src/Game/GameSession/Topbar.gd
+++ b/game/src/Game/GameSession/Topbar.gd
@@ -3,21 +3,21 @@ extends GUINode
# Country info
var _country_flag_texture : GFXMaskedFlagTexture
var _country_flag_overlay_texture : GFXSpriteTexture
-var _country_name_label : Label
-var _country_rank_label : Label
-var _country_prestige_label : Label
-var _country_prestige_rank_label : Label
-var _country_industrial_power_label : Label
-var _country_industrial_power_rank_label : Label
-var _country_military_power_label : Label
-var _country_military_power_rank_label : Label
-var _country_colonial_power_label : Label
+var _country_name_label : GUILabel
+var _country_rank_label : GUILabel
+var _country_prestige_label : GUILabel
+var _country_prestige_rank_label : GUILabel
+var _country_industrial_power_label : GUILabel
+var _country_industrial_power_rank_label : GUILabel
+var _country_military_power_label : GUILabel
+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 _date_label : Label
+var _date_label : GUILabel
# NationManagement.Screen-Button
var _nation_management_buttons : Dictionary
@@ -32,53 +32,48 @@ var _production_alert_unemployment_texture : GFXSpriteTexture
# Budget
# TODO - line chart
-var _budget_funds_label : Label
+var _budget_funds_label : GUILabel
# Technology
var _technology_progress_bar : TextureProgressBar
-var _technology_current_research_label : Label
-var _technology_literacy_label : Label
-var _technology_research_points_label : Label
+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_label : Label
-var _politics_suppression_points_label : Label
-var _politics_infamy_label : Label
+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
# Population
-var _population_total_size_label : Label
-var _population_national_foci_label : Label
-var _population_militancy_label : Label
-var _population_consciousness_label : Label
+var _population_total_size_label : GUILabel
+var _population_national_foci_label : GUILabel
+var _population_militancy_label : GUILabel
+var _population_consciousness_label : GUILabel
# Trade
var _trade_imported_textures : Array[GFXSpriteTexture]
var _trade_exported_textures : Array[GFXSpriteTexture]
# Diplomacy
-var _diplomacy_peace_label : Label
+var _diplomacy_peace_label : GUILabel
var _diplomacy_war_enemies_overlapping_elements_box : GUIOverlappingElementsBox
-var _diplomacy_diplomatic_points_label : Label
+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
# Military
-var _military_army_size_label : Label
-var _military_navy_size_label : Label
-var _military_mobilisation_size_label : Label
-var _military_leadership_points_label : Label
-
-# TODO - use GFX file font colour codes
-const FONT_GREEN : Color = Color("009F03")
-const FONT_RED : Color = Color("FF3232")
-const FONT_YELLOW : Color = Color("FFBD00")
+var _military_army_size_label : GUILabel
+var _military_navy_size_label : GUILabel
+var _military_mobilisation_size_label : GUILabel
+var _military_leadership_points_label : GUILabel
func _ready() -> void:
GameSingleton.gamestate_updated.connect(_update_info)
@@ -107,15 +102,15 @@ func _ready() -> void:
)
_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_name_label = get_label_from_nodepath(^"./topbar/CountryName")
- _country_rank_label = get_label_from_nodepath(^"./topbar/nation_totalrank")
- _country_prestige_label = get_label_from_nodepath(^"./topbar/country_prestige")
- _country_prestige_rank_label = get_label_from_nodepath(^"./topbar/selected_prestige_rank")
- _country_industrial_power_label = get_label_from_nodepath(^"./topbar/country_economic")
- _country_industrial_power_rank_label = get_label_from_nodepath(^"./topbar/selected_industry_rank")
- _country_military_power_label = get_label_from_nodepath(^"./topbar/country_military")
- _country_military_power_rank_label = get_label_from_nodepath(^"./topbar/selected_military_rank")
- _country_colonial_power_label = get_label_from_nodepath(^"./topbar/country_colonial_power")
+ _country_name_label = get_gui_label_from_nodepath(^"./topbar/CountryName")
+ _country_rank_label = get_gui_label_from_nodepath(^"./topbar/nation_totalrank")
+ _country_prestige_label = get_gui_label_from_nodepath(^"./topbar/country_prestige")
+ _country_prestige_rank_label = get_gui_label_from_nodepath(^"./topbar/selected_prestige_rank")
+ _country_industrial_power_label = get_gui_label_from_nodepath(^"./topbar/country_economic")
+ _country_industrial_power_rank_label = get_gui_label_from_nodepath(^"./topbar/selected_industry_rank")
+ _country_military_power_label = get_gui_label_from_nodepath(^"./topbar/country_military")
+ _country_military_power_rank_label = get_gui_label_from_nodepath(^"./topbar/selected_military_rank")
+ _country_colonial_power_label = get_gui_label_from_nodepath(^"./topbar/country_colonial_power")
# Time controls
_speed_up_button = get_button_from_nodepath(^"./topbar/button_speedup")
@@ -131,7 +126,7 @@ func _ready() -> void:
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)
- _date_label = get_label_from_nodepath(^"./topbar/DateText")
+ _date_label = get_gui_label_from_nodepath(^"./topbar/DateText")
# Nation management screens
const screen_nodepaths : Dictionary = {
@@ -167,21 +162,17 @@ func _ready() -> void:
_production_alert_unemployment_texture = get_gfx_sprite_texture_from_nodepath(^"./topbar/alert_unemployed_workers")
# Budget
- _budget_funds_label = get_label_from_nodepath(^"./topbar/budget_funds")
+ _budget_funds_label = get_gui_label_from_nodepath(^"./topbar/budget_funds")
# Technology
_technology_progress_bar = get_progress_bar_from_nodepath(^"./topbar/topbar_tech_progress")
- _technology_current_research_label = get_label_from_nodepath(^"./topbar/tech_current_research")
- _technology_literacy_label = get_label_from_nodepath(^"./topbar/tech_literacy_value")
- if _technology_literacy_label:
- _technology_literacy_label.add_theme_color_override(&"font_color", FONT_YELLOW)
- _technology_research_points_label = get_label_from_nodepath(^"./topbar/topbar_researchpoints_value")
- if _technology_research_points_label:
- _technology_research_points_label.add_theme_color_override(&"font_color", FONT_YELLOW)
+ _technology_current_research_label = get_gui_label_from_nodepath(^"./topbar/tech_current_research")
+ _technology_literacy_label = get_gui_label_from_nodepath(^"./topbar/tech_literacy_value")
+ _technology_research_points_label = get_gui_label_from_nodepath(^"./topbar/topbar_researchpoints_value")
# Politics
_politics_party_icon = get_texture_rect_from_nodepath(^"./topbar/politics_party_icon")
- _politics_party_label = get_label_from_nodepath(^"./topbar/politics_ruling_party")
+ _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")
if politics_suppression_button:
politics_suppression_button.pressed.connect(
@@ -189,12 +180,8 @@ func _ready() -> void:
# TODO - open the politics menu on the Movements tab
Events.NationManagementScreens.toggle_nation_management_screen(NationManagement.Screen.POLITICS)
)
- _politics_suppression_points_label = get_label_from_nodepath(^"./topbar/politics_supressionpoints_value")
- if _politics_suppression_points_label:
- _politics_suppression_points_label.add_theme_color_override(&"font_color", FONT_YELLOW)
- _politics_infamy_label = get_label_from_nodepath(^"./topbar/politics_infamy_value")
- if _politics_infamy_label:
- _politics_infamy_label.add_theme_color_override(&"font_color", FONT_YELLOW)
+ _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(
@@ -222,14 +209,10 @@ func _ready() -> void:
_politics_rebels_texture = GUINode.get_gfx_sprite_texture_from_node(politics_rebels_button)
# Population
- _population_total_size_label = get_label_from_nodepath(^"./topbar/population_total_value")
- _population_national_foci_label = get_label_from_nodepath(^"./topbar/topbar_focus_value")
- _population_militancy_label = get_label_from_nodepath(^"./topbar/population_avg_mil_value")
- if _population_militancy_label:
- _population_militancy_label.add_theme_color_override(&"font_color", FONT_YELLOW)
- _population_consciousness_label = get_label_from_nodepath(^"./topbar/population_avg_con_value")
- if _population_consciousness_label:
- _population_consciousness_label.add_theme_color_override(&"font_color", FONT_YELLOW)
+ _population_total_size_label = get_gui_label_from_nodepath(^"./topbar/population_total_value")
+ _population_national_foci_label = get_gui_label_from_nodepath(^"./topbar/topbar_focus_value")
+ _population_militancy_label = get_gui_label_from_nodepath(^"./topbar/population_avg_mil_value")
+ _population_consciousness_label = get_gui_label_from_nodepath(^"./topbar/population_avg_con_value")
# Trade
const TRADE_GOOD_COUNT : int = 3
@@ -238,11 +221,9 @@ func _ready() -> void:
_trade_exported_textures.push_back(get_gfx_sprite_texture_from_nodepath("./topbar/topbar_export%d" % idx))
# Diplomacy
- _diplomacy_peace_label = get_label_from_nodepath(^"./topbar/diplomacy_status")
+ _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_label_from_nodepath(^"./topbar/diplomacy_diplopoints_value")
- if _diplomacy_diplomatic_points_label:
- _diplomacy_diplomatic_points_label.add_theme_color_override(&"font_color", FONT_YELLOW)
+ _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(
@@ -256,18 +237,10 @@ func _ready() -> void:
_diplomacy_alert_great_power_texture = get_gfx_sprite_texture_from_nodepath(^"./topbar/alert_loosing_gp")
# Military
- _military_army_size_label = get_label_from_nodepath(^"./topbar/military_army_value")
- if _military_army_size_label:
- _military_army_size_label.add_theme_color_override(&"font_color", FONT_YELLOW)
- _military_navy_size_label = get_label_from_nodepath(^"./topbar/military_navy_value")
- if _military_navy_size_label:
- _military_navy_size_label.add_theme_color_override(&"font_color", FONT_YELLOW)
- _military_mobilisation_size_label = get_label_from_nodepath(^"./topbar/military_manpower_value")
- if _military_mobilisation_size_label:
- _military_mobilisation_size_label.add_theme_color_override(&"font_color", FONT_YELLOW)
- _military_leadership_points_label = get_label_from_nodepath(^"./topbar/military_leadership_value")
- if _military_leadership_points_label:
- _military_leadership_points_label.add_theme_color_override(&"font_color", FONT_YELLOW)
+ _military_army_size_label = get_gui_label_from_nodepath(^"./topbar/military_army_value")
+ _military_navy_size_label = get_gui_label_from_nodepath(^"./topbar/military_navy_value")
+ _military_mobilisation_size_label = get_gui_label_from_nodepath(^"./topbar/military_manpower_value")
+ _military_leadership_points_label = get_gui_label_from_nodepath(^"./topbar/military_leadership_value")
_update_info()
_update_speed_controls()
@@ -296,8 +269,7 @@ func _update_info() -> void:
_country_name_label.set_text(player_country)
if _country_rank_label:
- # TODO - fix label alignment
- _country_rank_label.set_text(" %d" % 1)
+ _country_rank_label.set_text(str(1))
if _country_prestige_label:
_country_prestige_label.set_text(str(11))
@@ -318,8 +290,11 @@ func _update_info() -> void:
_country_military_power_rank_label.set_text(str(3))
if _country_colonial_power_label:
- # TODO - colour (first number is red if non-positive)
- _country_colonial_power_label.set_text("%s/%s" % [123, 456])
+ var available_colonial_power : int = 123
+ var total_colonial_power : int = 456
+ _country_colonial_power_label.set_text(
+ "§%s%s§!/%s" % ["W" if available_colonial_power > 0 else "R", available_colonial_power, total_colonial_power]
+ )
## Time control
if _date_label:
@@ -343,13 +318,11 @@ func _update_info() -> void:
if _budget_funds_label:
var cash : float = 0.0
var earnings : float = 0.0
- _budget_funds_label.set_text("%s £ (%s%s £ )" % [
+ _budget_funds_label.set_text("§Y%s§!¤(§%s%s§!¤)" % [
GUINode.float_to_string_suffixed(cash),
- "+" if earnings >= 0.0 else "",
+ "G+" if earnings > 0.0 else "R" if earnings < 0.0 else "Y+",
GUINode.float_to_string_suffixed(earnings)
])
- # TODO - set colours: cash yellow, earnings red (-), yellow (0) or green (+)
- _budget_funds_label.add_theme_color_override(&"font_color", FONT_YELLOW)
## Technology
if _technology_progress_bar:
@@ -357,26 +330,13 @@ func _update_info() -> void:
if _technology_current_research_label:
# TODO - set current research or "unciv_nation" (in red) if uncivilised
- # TODO - process colour markers in localisation for "TB_TECH_NO_CURRENT"
-
- # Remove § symbols + colour codes from string
- var no_research : String = tr("TB_TECH_NO_CURRENT")
- while true:
- const COLOUR_CHAR : String = "\u00A7"
- var pos : int = no_research.find(COLOUR_CHAR)
- if pos >= 0:
- no_research = no_research.erase(pos, 2)
- else:
- break
-
- _technology_current_research_label.set_text(no_research)
- _technology_current_research_label.add_theme_color_override(&"font_color", FONT_RED)
+ _technology_current_research_label.set_text("TB_TECH_NO_CURRENT")
if _technology_literacy_label:
- _technology_literacy_label.set_text("%s%%" % GUINode.float_to_string_dp(80.0, 1))
+ _technology_literacy_label.set_text("§Y%s§W%%" % GUINode.float_to_string_dp(80.0, 1))
if _technology_research_points_label:
- _technology_research_points_label.set_text(GUINode.float_to_string_dp(10.0, 2))
+ _technology_research_points_label.set_text("§Y%s" % GUINode.float_to_string_dp(10.0, 2))
## Politics
if _politics_party_icon:
@@ -386,10 +346,10 @@ func _update_info() -> void:
_politics_party_label.set_text("ENG_liberal")
if _politics_suppression_points_label:
- _politics_suppression_points_label.set_text(GUINode.float_to_string_dp(2.5, 1))
+ _politics_suppression_points_label.set_text("§Y%s" % GUINode.float_to_string_dp(2.5, 1))
if _politics_infamy_label:
- _politics_infamy_label.set_text(GUINode.float_to_string_dp(0.0, 2))
+ _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)
@@ -405,25 +365,25 @@ func _update_info() -> void:
## Population
if _population_total_size_label:
- _population_total_size_label.set_text("%s(%s)" % [
- GUINode.int_to_string_suffixed(16000000),
- GUINode.int_to_string_suffixed(1500),
+ # TODO - suffixes on both numbers should be white!
+ var total_population : int = 16000000
+ var growth : int = 1500
+ _population_total_size_label.set_text("§Y%s§!(§%s%s§!)" % [
+ GUINode.int_to_string_suffixed(total_population),
+ "G" if growth >= 0 else "R",
+ GUINode.int_to_string_suffixed(growth),
])
- # TODO - set colours: yellow total population number, green or red change number (both numbers with a white suffix!)
- _population_total_size_label.add_theme_color_override(&"font_color", FONT_YELLOW)
-
if _population_national_foci_label:
var foci_used : int = 1
var max_foci : int = 1
- _population_national_foci_label.set_text("%d/%d" % [foci_used, max_foci])
- _population_national_foci_label.add_theme_color_override(&"font_color", FONT_RED if foci_used < max_foci else FONT_GREEN)
+ _population_national_foci_label.set_text("§%s%d/%d" % ["R" if foci_used < max_foci else "G", foci_used, max_foci])
if _population_militancy_label:
- _population_militancy_label.set_text(GUINode.float_to_string_dp(1.5, 2))
+ _population_militancy_label.set_text("§Y%s" % GUINode.float_to_string_dp(1.5, 2))
if _population_consciousness_label:
- _population_consciousness_label.set_text(GUINode.float_to_string_dp(0.05, 2))
+ _population_consciousness_label.set_text("§Y%s" % GUINode.float_to_string_dp(0.05, 2))
## Trade
for idx : int in _trade_imported_textures.size():
@@ -441,7 +401,7 @@ func _update_info() -> void:
# TODO - add war enemy flags to _diplomacy_war_enemies_overlapping_elements_box
if _diplomacy_diplomatic_points_label:
- _diplomacy_diplomatic_points_label.set_text(GUINode.float_to_string_dp(7.4, 0))
+ _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)
@@ -457,16 +417,16 @@ func _update_info() -> void:
## Military
if _military_army_size_label:
- _military_army_size_label.set_text("%d/%d" % [57, 120])
+ _military_army_size_label.set_text("§Y%d/%d" % [57, 120])
if _military_navy_size_label:
- _military_navy_size_label.set_text("%d/%d" % [123, 267])
+ _military_navy_size_label.set_text("§Y%d/%d" % [123, 267])
if _military_mobilisation_size_label:
- _military_mobilisation_size_label.set_text(str(38))
+ _military_mobilisation_size_label.set_text("§Y%d" % 38)
if _military_leadership_points_label:
- _military_leadership_points_label.set_text(str(15))
+ _military_leadership_points_label.set_text("§Y%d" % 15)
func _update_speed_controls() -> void:
# TODO - decide whether to disable these or not
diff --git a/game/src/Game/GameStart.gd b/game/src/Game/GameStart.gd
index 3c046a0..837e712 100644
--- a/game/src/Game/GameStart.gd
+++ b/game/src/Game/GameStart.gd
@@ -112,7 +112,7 @@ func _load_compatibility_mode() -> void:
if GameSingleton.load_defines_compatibility_mode() != OK:
push_error("Errors loading game defines!")
-
+
SoundSingleton.load_sounds()
SoundSingleton.load_music()
MusicConductor.add_compat_songs()
@@ -130,7 +130,6 @@ func setup_title_theme() -> void:
push_error("No song available to play")
else:
MusicConductor.call_deferred("start_current_song")
-
# REQUIREMENTS
# * FS-333, FS-334, FS-335, FS-341