diff options
24 files changed, 538 insertions, 77 deletions
diff --git a/extension/deps/openvic-simulation b/extension/deps/openvic-simulation -Subproject 068c13ede817d17df599ca3481261bf17ed9560 +Subproject 5216e893ebc5253b123bbf15b7509745d38f5a8 diff --git a/extension/src/openvic-extension/classes/GFXIconTexture.cpp b/extension/src/openvic-extension/classes/GFXIconTexture.cpp index 5d29c07..99df7e4 100644 --- a/extension/src/openvic-extension/classes/GFXIconTexture.cpp +++ b/extension/src/openvic-extension/classes/GFXIconTexture.cpp @@ -3,7 +3,6 @@ #include <godot_cpp/variant/utility_functions.hpp> #include "openvic-extension/singletons/AssetManager.hpp" -#include "openvic-extension/singletons/GameSingleton.hpp" #include "openvic-extension/utility/ClassBindings.hpp" #include "openvic-extension/utility/UITools.hpp" #include "openvic-extension/utility/Utilities.hpp" @@ -11,7 +10,6 @@ using namespace godot; using namespace OpenVic; -using OpenVic::Utilities::godot_to_std_string; using OpenVic::Utilities::std_view_to_godot_string; using OpenVic::Utilities::std_view_to_godot_string_name; diff --git a/extension/src/openvic-extension/classes/GFXPieChartTexture.cpp b/extension/src/openvic-extension/classes/GFXPieChartTexture.cpp index c9a2a72..f4c7851 100644 --- a/extension/src/openvic-extension/classes/GFXPieChartTexture.cpp +++ b/extension/src/openvic-extension/classes/GFXPieChartTexture.cpp @@ -1,16 +1,14 @@ #include "GFXPieChartTexture.hpp" -#include "openvic-extension/singletons/AssetManager.hpp" -#include "openvic-extension/singletons/GameSingleton.hpp" +#include <numbers> + #include "openvic-extension/utility/ClassBindings.hpp" #include "openvic-extension/utility/UITools.hpp" using namespace godot; using namespace OpenVic; -using OpenVic::Utilities::godot_to_std_string; using OpenVic::Utilities::std_view_to_godot_string; -using OpenVic::Utilities::std_view_to_godot_string_name; StringName const& GFXPieChartTexture::_slice_identifier_key() { static StringName const slice_identifier_key = "identifier"; diff --git a/extension/src/openvic-extension/classes/GUINode.cpp b/extension/src/openvic-extension/classes/GUINode.cpp index 89701e0..f95e3cd 100644 --- a/extension/src/openvic-extension/classes/GUINode.cpp +++ b/extension/src/openvic-extension/classes/GUINode.cpp @@ -10,9 +10,6 @@ using namespace godot; using namespace OpenVic; -using OpenVic::Utilities::godot_to_std_string; -using OpenVic::Utilities::std_view_to_godot_string; - #define APPLY_TO_CHILD_TYPES(F) \ F(Button, button) \ F(CheckBox, check_box) \ @@ -28,8 +25,9 @@ using OpenVic::Utilities::std_view_to_godot_string; F(GFXPieChartTexture, gfx_pie_chart_texture) void GUINode::_bind_methods() { - OV_BIND_SMETHOD(generate_gui_element, { "gui_file", "gui_element", "name" }, DEFVAL(String {})); - OV_BIND_METHOD(GUINode::add_gui_element, { "gui_file", "gui_element", "name" }, DEFVAL(String {})); + OV_BIND_SMETHOD(generate_gui_element, { "gui_scene", "gui_element", "name" }, DEFVAL(String {})); + OV_BIND_METHOD(GUINode::add_gui_element, { "gui_scene", "gui_element", "name" }, DEFVAL(String {})); + OV_BIND_SMETHOD(get_gui_position, { "gui_scene", "gui_position" }); #define GET_BINDINGS(type, name) \ OV_BIND_SMETHOD(get_##name##_from_node, { "node" }); \ @@ -55,19 +53,19 @@ GUINode::GUINode() { set_mouse_filter(MOUSE_FILTER_IGNORE); } -Control* GUINode::generate_gui_element(String const& gui_file, String const& gui_element, String const& name) { +Control* GUINode::generate_gui_element(String const& gui_scene, String const& gui_element, String const& name) { Control* result = nullptr; - if (!UITools::generate_gui_element(gui_file, gui_element, name, result)) { - UtilityFunctions::push_error("Error generating GUI element ", gui_element, " from GUI file ", gui_file); + if (!UITools::generate_gui_element(gui_scene, gui_element, name, result)) { + UtilityFunctions::push_error("Error generating GUI element ", gui_element, " from GUI scene ", gui_scene); } return result; } -Error GUINode::add_gui_element(String const& gui_file, String const& gui_element, String const& name) { +Error GUINode::add_gui_element(String const& gui_scene, String const& gui_element, String const& name) { Error err = OK; Control* result = nullptr; - if (!UITools::generate_gui_element(gui_file, gui_element, name, result)) { - UtilityFunctions::push_error("Error generating GUI element ", gui_element, " from GUI file ", gui_file); + if (!UITools::generate_gui_element(gui_scene, gui_element, name, result)) { + UtilityFunctions::push_error("Error generating GUI element ", gui_element, " from GUI scene ", gui_scene); err = FAILED; } if (result != nullptr) { @@ -76,6 +74,12 @@ Error GUINode::add_gui_element(String const& gui_file, String const& gui_element return err; } +Vector2 GUINode::get_gui_position(String const& gui_scene, String const& gui_position) { + GUI::Position const* position = UITools::get_gui_position(gui_scene, gui_position); + ERR_FAIL_NULL_V(position, {}); + return Utilities::to_godot_fvec2(position->get_position()); +} + template<std::derived_from<godot::Node> T> static T* _cast_node(Node* node) { ERR_FAIL_NULL_V(node, nullptr); diff --git a/extension/src/openvic-extension/classes/GUINode.hpp b/extension/src/openvic-extension/classes/GUINode.hpp index e38ed1f..0fbfc66 100644 --- a/extension/src/openvic-extension/classes/GUINode.hpp +++ b/extension/src/openvic-extension/classes/GUINode.hpp @@ -25,13 +25,15 @@ namespace OpenVic { GUINode(); static godot::Control* generate_gui_element( - godot::String const& gui_file, godot::String const& gui_element, godot::String const& name = "" + godot::String const& gui_scene, godot::String const& gui_element, godot::String const& name = "" ); godot::Error add_gui_element( - godot::String const& gui_file, godot::String const& gui_element, godot::String const& name = "" + godot::String const& gui_scene, godot::String const& gui_element, godot::String const& name = "" ); + 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::CheckBox* get_check_box_from_node(godot::Node* node); static godot::Label* get_label_from_node(godot::Node* node); diff --git a/extension/src/openvic-extension/utility/UITools.cpp b/extension/src/openvic-extension/utility/UITools.cpp index e1cd873..1fcc574 100644 --- a/extension/src/openvic-extension/utility/UITools.cpp +++ b/extension/src/openvic-extension/utility/UITools.cpp @@ -37,17 +37,28 @@ GFX::Sprite const* UITools::get_gfx_sprite(godot::String const& gfx_sprite) { return sprite; } -GUI::Element const* UITools::get_gui_element(godot::String const& gui_file, godot::String const& gui_element) { +GUI::Element const* UITools::get_gui_element(godot::String const& gui_scene, godot::String const& gui_element) { GameSingleton const* game_singleton = GameSingleton::get_singleton(); ERR_FAIL_NULL_V(game_singleton, nullptr); GUI::Scene const* scene = - game_singleton->get_game_manager().get_ui_manager().get_scene_by_identifier(godot_to_std_string(gui_file)); - ERR_FAIL_NULL_V_MSG(scene, nullptr, vformat("Failed to find GUI file %s", gui_file)); + game_singleton->get_game_manager().get_ui_manager().get_scene_by_identifier(godot_to_std_string(gui_scene)); + ERR_FAIL_NULL_V_MSG(scene, nullptr, vformat("Failed to find GUI scene %s", gui_scene)); GUI::Element const* element = scene->get_scene_element_by_identifier(godot_to_std_string(gui_element)); - ERR_FAIL_NULL_V_MSG(element, nullptr, vformat("Failed to find GUI element %s in GUI file %s", gui_element, gui_file)); + ERR_FAIL_NULL_V_MSG(element, nullptr, vformat("Failed to find GUI element %s in GUI scene %s", gui_element, gui_scene)); return element; } +GUI::Position const* UITools::get_gui_position(String const& gui_scene, String const& gui_position) { + GameSingleton const* game_singleton = GameSingleton::get_singleton(); + ERR_FAIL_NULL_V(game_singleton, nullptr); + GUI::Scene const* scene = + game_singleton->get_game_manager().get_ui_manager().get_scene_by_identifier(godot_to_std_string(gui_scene)); + ERR_FAIL_NULL_V_MSG(scene, nullptr, vformat("Failed to find GUI scene %s", gui_scene)); + GUI::Position const* position = scene->get_scene_position_by_identifier(godot_to_std_string(gui_position)); + ERR_FAIL_NULL_V_MSG(position, nullptr, vformat("Failed to find GUI position %s in GUI scene %s", gui_position, gui_scene)); + return position; +} + /* GUI::Element tree -> godot::Control tree conversion code below: */ namespace OpenVic { @@ -65,9 +76,9 @@ namespace OpenVic { } template<std::derived_from<Control> T> -static T* new_control(GUI::Element const& element, String const& name) { - T* node = memnew(T); - ERR_FAIL_NULL_V(node, nullptr); +static bool new_control(T*& node, GUI::Element const& element, String const& name) { + node = memnew(T); + ERR_FAIL_NULL_V(node, false); using enum GUI::Element::orientation_t; using enum Control::LayoutPreset; @@ -83,20 +94,32 @@ static T* new_control(GUI::Element const& element, String const& name) { node->set_name(name); } + bool ret = true; const decltype(orientation_map)::const_iterator it = orientation_map.find(element.get_orientation()); if (it != orientation_map.end()) { node->set_anchors_and_offsets_preset(it->second); } else { UtilityFunctions::push_error("Invalid orientation for GUI element ", std_view_to_godot_string(element.get_name())); + ret = false; } + node->set_position(Utilities::to_godot_fvec2(element.get_position())); node->set_h_size_flags(Control::SizeFlags::SIZE_SHRINK_BEGIN); node->set_v_size_flags(Control::SizeFlags::SIZE_SHRINK_BEGIN); node->set_focus_mode(Control::FOCUS_NONE); - return node; + return ret; } +static bool add_theme_stylebox(Control* control, StringName const& theme_name, Ref<Texture2D> const& texture) { + Ref<StyleBoxTexture> stylebox; + stylebox.instantiate(); + ERR_FAIL_NULL_V(stylebox, false); + stylebox->set_texture(texture); + control->add_theme_stylebox_override(theme_name, stylebox); + return true; +}; + static bool generate_icon(generate_gui_args_t&& args) { GUI::Icon const& icon = static_cast<GUI::Icon const&>(args.element); @@ -106,7 +129,8 @@ static bool generate_icon(generate_gui_args_t&& args) { bool ret = true; if (icon.get_sprite() != nullptr) { if (icon.get_sprite()->is_type<GFX::TextureSprite>()) { - TextureRect* godot_texture_rect = new_control<TextureRect>(icon, args.name); + TextureRect* godot_texture_rect = nullptr; + ret &= new_control(godot_texture_rect, icon, args.name); ERR_FAIL_NULL_V_MSG(godot_texture_rect, false, vformat("Failed to create TextureRect for GUI icon %s", icon_name)); GFX::TextureSprite const* texture_sprite = icon.get_sprite()->cast_to<GFX::TextureSprite>(); @@ -120,7 +144,8 @@ static bool generate_icon(generate_gui_args_t&& args) { args.result = godot_texture_rect; } else if (icon.get_sprite()->is_type<GFX::MaskedFlag>()) { - TextureRect* godot_texture_rect = new_control<TextureRect>(icon, args.name); + TextureRect* godot_texture_rect = nullptr; + ret &= new_control(godot_texture_rect, icon, args.name); ERR_FAIL_NULL_V_MSG(godot_texture_rect, false, vformat("Failed to create TextureRect for GUI icon %s", icon_name)); GFX::MaskedFlag const* masked_flag = icon.get_sprite()->cast_to<GFX::MaskedFlag>(); @@ -134,7 +159,8 @@ static bool generate_icon(generate_gui_args_t&& args) { args.result = godot_texture_rect; } else if (icon.get_sprite()->is_type<GFX::ProgressBar>()) { - TextureProgressBar* godot_progress_bar = new_control<TextureProgressBar>(icon, args.name); + TextureProgressBar* godot_progress_bar = nullptr; + ret &= new_control(godot_progress_bar, icon, args.name); ERR_FAIL_NULL_V_MSG( godot_progress_bar, false, vformat("Failed to create TextureProgressBar for GUI icon %s", icon_name) ); @@ -210,7 +236,8 @@ static bool generate_icon(generate_gui_args_t&& args) { args.result = godot_progress_bar; } else if (icon.get_sprite()->is_type<GFX::PieChart>()) { - TextureRect* godot_texture_rect = new_control<TextureRect>(icon, args.name); + TextureRect* godot_texture_rect = nullptr; + ret &= new_control(godot_texture_rect, icon, args.name); ERR_FAIL_NULL_V_MSG(godot_texture_rect, false, vformat("Failed to create TextureRect for GUI icon %s", icon_name)); GFX::PieChart const* pie_chart = icon.get_sprite()->cast_to<GFX::PieChart>(); @@ -219,7 +246,7 @@ static bool generate_icon(generate_gui_args_t&& args) { godot_texture_rect->set_texture(texture); // TODO - work out why this is needed Vector2 pos = godot_texture_rect->get_position(); - pos.x -= texture->get_width() / 2; + pos.x -= texture->get_width() / 2.0f; godot_texture_rect->set_position(pos); } else { UtilityFunctions::push_error("Failed to make GFXPieChartTexture for GUI icon ", icon_name); @@ -228,12 +255,18 @@ static bool generate_icon(generate_gui_args_t&& args) { args.result = godot_texture_rect; } else if (icon.get_sprite()->is_type<GFX::LineChart>()) { - + // TODO - generate line chart } else { UtilityFunctions::push_error("Invalid sprite type ", std_view_to_godot_string(icon.get_sprite()->get_type()), " for GUI icon ", icon_name); ret = false; } + + if (args.result != nullptr) { + const float scale = icon.get_scale(); + args.result->set_scale({ scale, scale }); + // TODO - rotation (may have to translate as godot rotates around the top left corner) + } } else { UtilityFunctions::push_error("Null sprite for GUI icon ", icon_name); ret = false; @@ -247,7 +280,8 @@ static bool generate_button(generate_gui_args_t&& args) { // TODO - shortcut, sprite, text const String button_name = std_view_to_godot_string(button.get_name()); - Button* godot_button = new_control<Button>(button, args.name); + Button* godot_button = nullptr; + bool ret = new_control(godot_button, button, args.name); ERR_FAIL_NULL_V_MSG(godot_button, false, vformat("Failed to create Button for GUI button %s", button_name)); godot_button->set_mouse_filter(Control::MOUSE_FILTER_PASS); @@ -256,8 +290,6 @@ static bool generate_button(generate_gui_args_t&& args) { godot_button->set_text(std_view_to_godot_string(button.get_text())); } - bool ret = true; - using enum GFXButtonStateTexture::ButtonState; static constexpr std::array<GFXButtonStateTexture::ButtonState, 3> button_states { HOVER, PRESSED, DISABLED }; @@ -310,10 +342,10 @@ static bool generate_button(generate_gui_args_t&& args) { }; static const StringName theme_name_normal = "normal"; - ret &= add_stylebox(theme_name_normal, texture); + ret &= add_theme_stylebox(godot_button, theme_name_normal, texture); for (Ref<GFXButtonStateTexture> const& button_state_texture : button_state_textures) { - ret &= add_stylebox(button_state_texture->get_button_state_theme(), button_state_texture); + ret &= add_theme_stylebox(godot_button, button_state_texture->get_button_state_theme(), button_state_texture); } } } else { @@ -350,10 +382,10 @@ static bool generate_checkbox(generate_gui_args_t&& args) { // TODO - shortcut, sprite, text const String checkbox_name = std_view_to_godot_string(checkbox.get_name()); - CheckBox* godot_checkbox = new_control<CheckBox>(checkbox, args.name); + CheckBox* godot_checkbox = nullptr; + bool ret = new_control(godot_checkbox, checkbox, args.name); ERR_FAIL_NULL_V_MSG(godot_checkbox, false, vformat("Failed to create CheckBox for GUI checkbox %s", checkbox_name)); - bool ret = true; if (checkbox.get_sprite() != nullptr) { GFX::TextureSprite const* texture_sprite = checkbox.get_sprite()->cast_to<GFX::TextureSprite>(); if (texture_sprite != nullptr) { @@ -393,7 +425,8 @@ static bool generate_text(generate_gui_args_t&& args) { const String text_name = std_view_to_godot_string(text.get_name()); - Label* godot_label = new_control<Label>(text, args.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(std_view_to_godot_string(text.get_text())); @@ -411,9 +444,9 @@ static bool generate_text(generate_gui_args_t&& args) { godot_label->set_horizontal_alignment(it->second); } else { UtilityFunctions::push_error("Invalid text format (horizontal alignment) for GUI text ", text_name); + ret = false; } - bool ret = true; if (text.get_font() != nullptr) { const StringName font_file = std_view_to_godot_string_name(text.get_font()->get_fontname()); const Ref<Font> font = args.asset_manager.get_font(font_file); @@ -436,29 +469,55 @@ static bool generate_overlapping_elements(generate_gui_args_t&& args) { const String overlapping_elements_name = std_view_to_godot_string(overlapping_elements.get_name()); - GUIOverlappingElementsBox* box = new_control<GUIOverlappingElementsBox>(overlapping_elements, args.name); + GUIOverlappingElementsBox* box = nullptr; + bool ret = new_control(box, overlapping_elements, args.name); ERR_FAIL_NULL_V_MSG( box, false, vformat("Failed to create GUIOverlappingElementsBox for GUI overlapping elements %s", overlapping_elements_name) ); - const bool ret = box->set_gui_overlapping_elements_box(&overlapping_elements) == OK; + ret &= box->set_gui_overlapping_elements_box(&overlapping_elements) == OK; args.result = box; return ret; } -static bool generate_listbox(generate_gui_args_t&& args) { - GUI::ListBox const& listbox = static_cast<GUI::ListBox const&>(args.element); +template<std::derived_from<GUI::Element> T> +requires requires(T const& element) { + { element.get_size() } -> std::same_as<fvec2_t>; +} +static bool generate_placeholder(generate_gui_args_t&& args, Color colour) { + T const& cast_element = static_cast<T const&>(args.element); - const String listbox_name = std_view_to_godot_string(listbox.get_name()); + static const String type_name = std_view_to_godot_string(T::get_type_static()); + const String placeholder_name = std_view_to_godot_string(cast_element.get_name()); + const Vector2 godot_size = Utilities::to_godot_fvec2(cast_element.get_size()); - ColorRect* godot_rect = new_control<ColorRect>(listbox, args.name); - ERR_FAIL_NULL_V_MSG(godot_rect, false, vformat("Failed to create ColorRect for GUI listbox %s", listbox_name)); + UtilityFunctions::push_warning( + "Generating placeholder ColorRect for GUI ", type_name, " ", placeholder_name, " (size ", godot_size, ")" + ); - godot_rect->set_custom_minimum_size(Utilities::to_godot_fvec2(listbox.get_size())); - godot_rect->set_color({ 1.0f, 0.5f, 0.0f, 0.2f }); + ColorRect* godot_rect = nullptr; + bool ret = new_control(godot_rect, cast_element, args.name); + ERR_FAIL_NULL_V_MSG( + godot_rect, false, vformat("Failed to create placeholder ColorRect for GUI %s %s", type_name, placeholder_name) + ); + + godot_rect->set_custom_minimum_size(godot_size); + godot_rect->set_color(colour); args.result = godot_rect; - return true; + return ret; +} + +static bool generate_listbox(generate_gui_args_t&& args) { + return generate_placeholder<GUI::ListBox>(std::move(args), { 0.0f, 0.0f, 1.0f, 0.3f }); +} + +static bool generate_texteditbox(generate_gui_args_t&& args) { + return generate_placeholder<GUI::TextEditBox>(std::move(args), { 0.0f, 1.0f, 0.0f, 0.3f }); +} + +static bool generate_scrollbar(generate_gui_args_t&& args) { + return generate_placeholder<GUI::Scrollbar>(std::move(args), { 1.0f, 0.0f, 0.0f, 0.3f }); } /* Forward declaration for use in generate_window. */ @@ -470,13 +529,13 @@ static bool generate_window(generate_gui_args_t&& args) { // TODO - moveable, fullscreen, dontRender (disable visibility?) const String window_name = std_view_to_godot_string(window.get_name()); - Panel* godot_panel = new_control<Panel>(window, args.name); + Panel* godot_panel = nullptr; + bool ret = new_control(godot_panel, window, args.name); ERR_FAIL_NULL_V_MSG(godot_panel, false, vformat("Failed to create Panel for GUI window %s", window_name)); godot_panel->set_custom_minimum_size(Utilities::to_godot_fvec2(window.get_size())); godot_panel->set_self_modulate({ 1.0f, 1.0f, 1.0f, 0.0f }); - bool ret = true; for (std::unique_ptr<GUI::Element> const& element : window.get_window_elements()) { Control* node = nullptr; const bool element_ret = generate_element(element.get(), "", args.asset_manager, node); @@ -502,6 +561,8 @@ static bool generate_element(GUI::Element const* element, String const& name, As { GUI::Text::get_type_static(), &generate_text }, { GUI::OverlappingElementsBox::get_type_static(), &generate_overlapping_elements }, { GUI::ListBox::get_type_static(), &generate_listbox }, + { GUI::TextEditBox::get_type_static(), &generate_texteditbox }, + { GUI::Scrollbar::get_type_static(), &generate_scrollbar }, { GUI::Window::get_type_static(), &generate_window } }; const decltype(type_map)::const_iterator it = type_map.find(element->get_type()); @@ -521,7 +582,7 @@ bool UITools::generate_gui_element( } bool UITools::generate_gui_element( - godot::String const& gui_file, godot::String const& gui_element, godot::String const& name, godot::Control*& result + godot::String const& gui_scene, godot::String const& gui_element, godot::String const& name, godot::Control*& result ) { - return generate_gui_element(get_gui_element(gui_file, gui_element), name, result); + return generate_gui_element(get_gui_element(gui_scene, gui_element), name, result); } diff --git a/extension/src/openvic-extension/utility/UITools.hpp b/extension/src/openvic-extension/utility/UITools.hpp index 65cf17a..6092853 100644 --- a/extension/src/openvic-extension/utility/UITools.hpp +++ b/extension/src/openvic-extension/utility/UITools.hpp @@ -7,12 +7,13 @@ namespace OpenVic::UITools { GFX::Sprite const* get_gfx_sprite(godot::String const& gfx_sprite); - GUI::Element const* get_gui_element(godot::String const& gui_file, godot::String const& gui_element); + GUI::Element const* get_gui_element(godot::String const& gui_scene, godot::String const& gui_element); + GUI::Position const* get_gui_position(godot::String const& gui_scene, godot::String const& gui_position); bool generate_gui_element( GUI::Element const* element, godot::String const& name, godot::Control*& result ); bool generate_gui_element( - godot::String const& gui_file, godot::String const& gui_element, godot::String const& name, godot::Control*& result + godot::String const& gui_scene, godot::String const& gui_element, godot::String const& name, godot::Control*& result ); } diff --git a/extension/src/openvic-extension/utility/Utilities.cpp b/extension/src/openvic-extension/utility/Utilities.cpp index a3fa40a..5957b70 100644 --- a/extension/src/openvic-extension/utility/Utilities.cpp +++ b/extension/src/openvic-extension/utility/Utilities.cpp @@ -1,7 +1,5 @@ #include "Utilities.hpp" -#include <numbers> - #include <godot_cpp/classes/file_access.hpp> #include <godot_cpp/classes/resource_loader.hpp> #include <godot_cpp/classes/translation_server.hpp> diff --git a/extension/src/openvic-extension/utility/Utilities.hpp b/extension/src/openvic-extension/utility/Utilities.hpp index 9bbc700..9b45abc 100644 --- a/extension/src/openvic-extension/utility/Utilities.hpp +++ b/extension/src/openvic-extension/utility/Utilities.hpp @@ -11,23 +11,23 @@ namespace OpenVic::Utilities { - inline std::string godot_to_std_string(godot::String const& str) { + _FORCE_INLINE_ std::string godot_to_std_string(godot::String const& str) { return str.ascii().get_data(); } - inline godot::String std_to_godot_string(std::string const& str) { + _FORCE_INLINE_ godot::String std_to_godot_string(std::string const& str) { return str.c_str(); } - inline godot::String std_view_to_godot_string(std::string_view str) { + _FORCE_INLINE_ godot::String std_view_to_godot_string(std::string_view const& str) { return std_to_godot_string(static_cast<std::string>(str)); } - inline godot::StringName std_to_godot_string_name(std::string const& str) { + _FORCE_INLINE_ godot::StringName std_to_godot_string_name(std::string const& str) { return str.c_str(); } - inline godot::StringName std_view_to_godot_string_name(std::string_view str) { + _FORCE_INLINE_ godot::StringName std_view_to_godot_string_name(std::string_view const& str) { return std_to_godot_string_name(static_cast<std::string>(str)); } @@ -37,15 +37,15 @@ namespace OpenVic::Utilities { godot::String date_to_formatted_string(Date date); - inline godot::Color to_godot_color(IsColour auto colour) { + _FORCE_INLINE_ godot::Color to_godot_color(IsColour auto colour) { return { colour.redf(), colour.greenf(), colour.bluef(), colour.alphaf() }; } - inline godot::Vector2i to_godot_ivec2(ivec2_t vec) { + _FORCE_INLINE_ godot::Vector2i to_godot_ivec2(ivec2_t vec) { return { vec.x, vec.y }; } - inline godot::Vector2 to_godot_fvec2(fvec2_t vec) { + _FORCE_INLINE_ godot::Vector2 to_godot_fvec2(fvec2_t vec) { return { vec.x, vec.y }; } diff --git a/game/src/Game/Autoload/Events.gd b/game/src/Game/Autoload/Events.gd index 4f38f61..091a122 100644 --- a/game/src/Game/Autoload/Events.gd +++ b/game/src/Game/Autoload/Events.gd @@ -1,9 +1,11 @@ ## Events are exclusively for the purpose of handling global signals ## This is to reduce "signal bubbling" which is when a signal callback is used to "bubble" the signal callbacks up the scene tree. -## It does such by providing a global interface of signals that are connected to and emitted by that are garunteed to exist. +## It does such by providing a global interface of signals that are connected to and emitted by that are guaranteed to exist. extends Node -var Options: OptionsEventsObject +var Options : OptionsEventsObject +var NationManagementScreens : NationManagementScreensEventsObject func _init() -> void: Options = OptionsEventsObject.new() + NationManagementScreens = NationManagementScreensEventsObject.new() diff --git a/game/src/Game/Autoload/Events/NationManagementScreens.gd b/game/src/Game/Autoload/Events/NationManagementScreens.gd new file mode 100644 index 0000000..4bdca6d --- /dev/null +++ b/game/src/Game/Autoload/Events/NationManagementScreens.gd @@ -0,0 +1,25 @@ +class_name NationManagementScreensEventsObject +extends RefCounted + +signal update_active_nation_management_screen(screen : NationManagement.Screen) + +var _current_screen : NationManagement.Screen = NationManagement.Screen.NONE + +# Set the current nation management screen. This emits an update signal to force +# the argument screen to update, even if it was already the current screen. +# Used by miscellaneous screen opening buttons (e.g. in province overview panel) +# and by the close and toggle functions below. +func open_nation_management_screen(screen : NationManagement.Screen) -> void: + _current_screen = screen + update_active_nation_management_screen.emit(_current_screen) + +# Close the screen if it is already open. Used for screens' close buttons. +func close_nation_management_screen(screen : NationManagement.Screen) -> void: + if screen == _current_screen: + open_nation_management_screen(NationManagement.Screen.NONE) + +# Either switch to the screen or close it if it is already open. Used for topbar's buttons. +func toggle_nation_management_screen(screen : NationManagement.Screen) -> void: + if screen == _current_screen: + screen = NationManagement.Screen.NONE + open_nation_management_screen(screen) diff --git a/game/src/Game/GameSession/GameSession.tscn b/game/src/Game/GameSession/GameSession.tscn index c7a8003..d2fc3a3 100644 --- a/game/src/Game/GameSession/GameSession.tscn +++ b/game/src/Game/GameSession/GameSession.tscn @@ -1,4 +1,4 @@ -[gd_scene load_steps=10 format=3 uid="uid://bgnupcshe1m7r"] +[gd_scene load_steps=18 format=3 uid="uid://bgnupcshe1m7r"] [ext_resource type="Script" path="res://src/Game/GameSession/GameSession.gd" id="1_eklvp"] [ext_resource type="PackedScene" uid="uid://cvl76duuym1wq" path="res://src/Game/MusicConductor/MusicPlayer.tscn" id="2_kt6aa"] @@ -6,9 +6,17 @@ [ext_resource type="PackedScene" uid="uid://dvdynl6eir40o" path="res://src/Game/GameSession/GameSessionMenu.tscn" id="3_bvmqh"] [ext_resource type="Script" path="res://src/Game/GameSession/Topbar.gd" id="4_2kbih"] [ext_resource type="PackedScene" uid="uid://dkehmdnuxih2r" path="res://src/Game/GameSession/MapView.tscn" id="4_xkg5j"] +[ext_resource type="Script" path="res://src/Game/GameSession/NationManagementScreen/ProductionMenu.gd" id="5_16755"] [ext_resource type="Script" path="res://src/Game/GameSession/ProvinceOverviewPanel.gd" id="5_lfv8l"] [ext_resource type="PackedScene" uid="uid://cnbfxjy1m6wja" path="res://src/Game/Menu/OptionMenu/OptionsMenu.tscn" id="6_p5mnx"] +[ext_resource type="Script" path="res://src/Game/GameSession/NationManagementScreen/BudgetMenu.gd" id="6_vninv"] +[ext_resource type="Script" path="res://src/Game/GameSession/NationManagementScreen/TechnologyMenu.gd" id="7_r712c"] [ext_resource type="PackedScene" uid="uid://d3g6wbvwflmyk" path="res://src/Game/Menu/SaveLoadMenu/SaveLoadMenu.tscn" id="8_4g7ko"] +[ext_resource type="Script" path="res://src/Game/GameSession/NationManagementScreen/PoliticsMenu.gd" id="8_ppdek"] +[ext_resource type="Script" path="res://src/Game/GameSession/NationManagementScreen/PopulationMenu.gd" id="10_laee7"] +[ext_resource type="Script" path="res://src/Game/GameSession/NationManagementScreen/TradeMenu.gd" id="10_mv1r6"] +[ext_resource type="Script" path="res://src/Game/GameSession/NationManagementScreen/DiplomacyMenu.gd" id="11_fu7ys"] +[ext_resource type="Script" path="res://src/Game/GameSession/NationManagementScreen/MilitaryMenu.gd" id="12_6h6nc"] [node name="GameSession" type="Control" node_paths=PackedStringArray("_game_session_menu")] editor_description = "SS-102, UI-546" @@ -34,6 +42,46 @@ layout_mode = 1 anchors_preset = 15 script = ExtResource("4_2kbih") +[node name="ProductionMenu" type="GUINode" parent="Topbar"] +layout_mode = 1 +anchors_preset = 15 +script = ExtResource("5_16755") + +[node name="BudgetMenu" type="GUINode" parent="Topbar"] +layout_mode = 1 +anchors_preset = 15 +script = ExtResource("6_vninv") + +[node name="TechnologyMenu" type="GUINode" parent="Topbar"] +layout_mode = 1 +anchors_preset = 15 +script = ExtResource("7_r712c") + +[node name="PoliticsMenu" type="GUINode" parent="Topbar"] +layout_mode = 1 +anchors_preset = 15 +script = ExtResource("8_ppdek") + +[node name="PopulationMenu" type="GUINode" parent="Topbar"] +layout_mode = 1 +anchors_preset = 15 +script = ExtResource("10_laee7") + +[node name="TradeMenu" type="GUINode" parent="Topbar"] +layout_mode = 1 +anchors_preset = 15 +script = ExtResource("10_mv1r6") + +[node name="DiplomacyMenu" type="GUINode" parent="Topbar"] +layout_mode = 1 +anchors_preset = 15 +script = ExtResource("11_fu7ys") + +[node name="MilitaryMenu" type="GUINode" parent="Topbar"] +layout_mode = 1 +anchors_preset = 15 +script = ExtResource("12_6h6nc") + [node name="MapControlPanel" parent="." instance=ExtResource("3_afh6d")] layout_mode = 1 anchors_preset = 3 diff --git a/game/src/Game/GameSession/NationManagementScreen/BudgetMenu.gd b/game/src/Game/GameSession/NationManagementScreen/BudgetMenu.gd new file mode 100644 index 0000000..7158333 --- /dev/null +++ b/game/src/Game/GameSession/NationManagementScreen/BudgetMenu.gd @@ -0,0 +1,34 @@ +extends GUINode + +var _active : bool = false + +const _screen : NationManagement.Screen = NationManagement.Screen.BUDGET + +func _ready() -> void: + GameSingleton.gamestate_updated.connect(_update_info) + + Events.NationManagementScreens.update_active_nation_management_screen.connect(_on_update_active_nation_management_screen) + + add_gui_element("country_budget", "country_budget") + + var close_button : Button = get_button_from_nodepath(^"./country_budget/close_button") + if close_button: + close_button.pressed.connect(Events.NationManagementScreens.close_nation_management_screen.bind(_screen)) + + _update_info() + +func _notification(what : int) -> void: + match what: + NOTIFICATION_TRANSLATION_CHANGED: + _update_info() + +func _on_update_active_nation_management_screen(active_screen : NationManagement.Screen) -> void: + _active = active_screen == _screen + _update_info() + +func _update_info() -> void: + if _active: + # TODO - update UI state + show() + else: + hide() diff --git a/game/src/Game/GameSession/NationManagementScreen/DiplomacyMenu.gd b/game/src/Game/GameSession/NationManagementScreen/DiplomacyMenu.gd new file mode 100644 index 0000000..fb11a31 --- /dev/null +++ b/game/src/Game/GameSession/NationManagementScreen/DiplomacyMenu.gd @@ -0,0 +1,34 @@ +extends GUINode + +var _active : bool = false + +const _screen : NationManagement.Screen = NationManagement.Screen.DIPLOMACY + +func _ready() -> void: + GameSingleton.gamestate_updated.connect(_update_info) + + Events.NationManagementScreens.update_active_nation_management_screen.connect(_on_update_active_nation_management_screen) + + add_gui_element("country_diplomacy", "country_diplomacy") + + var close_button : Button = get_button_from_nodepath(^"./country_diplomacy/close_button") + if close_button: + close_button.pressed.connect(Events.NationManagementScreens.close_nation_management_screen.bind(_screen)) + + _update_info() + +func _notification(what : int) -> void: + match what: + NOTIFICATION_TRANSLATION_CHANGED: + _update_info() + +func _on_update_active_nation_management_screen(active_screen : NationManagement.Screen) -> void: + _active = active_screen == _screen + _update_info() + +func _update_info() -> void: + if _active: + # TODO - update UI state + show() + else: + hide() diff --git a/game/src/Game/GameSession/NationManagementScreen/MilitaryMenu.gd b/game/src/Game/GameSession/NationManagementScreen/MilitaryMenu.gd new file mode 100644 index 0000000..f3cc486 --- /dev/null +++ b/game/src/Game/GameSession/NationManagementScreen/MilitaryMenu.gd @@ -0,0 +1,34 @@ +extends GUINode + +var _active : bool = false + +const _screen : NationManagement.Screen = NationManagement.Screen.MILITARY + +func _ready() -> void: + GameSingleton.gamestate_updated.connect(_update_info) + + Events.NationManagementScreens.update_active_nation_management_screen.connect(_on_update_active_nation_management_screen) + + add_gui_element("country_military", "country_military") + + var close_button : Button = get_button_from_nodepath(^"./country_military/close_button") + if close_button: + close_button.pressed.connect(Events.NationManagementScreens.close_nation_management_screen.bind(_screen)) + + _update_info() + +func _notification(what : int) -> void: + match what: + NOTIFICATION_TRANSLATION_CHANGED: + _update_info() + +func _on_update_active_nation_management_screen(active_screen : NationManagement.Screen) -> void: + _active = active_screen == _screen + _update_info() + +func _update_info() -> void: + if _active: + # TODO - update UI state + show() + else: + hide() diff --git a/game/src/Game/GameSession/NationManagementScreen/PoliticsMenu.gd b/game/src/Game/GameSession/NationManagementScreen/PoliticsMenu.gd new file mode 100644 index 0000000..7237bf5 --- /dev/null +++ b/game/src/Game/GameSession/NationManagementScreen/PoliticsMenu.gd @@ -0,0 +1,34 @@ +extends GUINode + +var _active : bool = false + +const _screen : NationManagement.Screen = NationManagement.Screen.POLITICS + +func _ready() -> void: + GameSingleton.gamestate_updated.connect(_update_info) + + Events.NationManagementScreens.update_active_nation_management_screen.connect(_on_update_active_nation_management_screen) + + add_gui_element("country_politics", "country_politics") + + var close_button : Button = get_button_from_nodepath(^"./country_politics/close_button") + if close_button: + close_button.pressed.connect(Events.NationManagementScreens.close_nation_management_screen.bind(_screen)) + + _update_info() + +func _notification(what : int) -> void: + match what: + NOTIFICATION_TRANSLATION_CHANGED: + _update_info() + +func _on_update_active_nation_management_screen(active_screen : NationManagement.Screen) -> void: + _active = active_screen == _screen + _update_info() + +func _update_info() -> void: + if _active: + # TODO - update UI state + show() + else: + hide() diff --git a/game/src/Game/GameSession/NationManagementScreen/PopulationMenu.gd b/game/src/Game/GameSession/NationManagementScreen/PopulationMenu.gd new file mode 100644 index 0000000..29bd56b --- /dev/null +++ b/game/src/Game/GameSession/NationManagementScreen/PopulationMenu.gd @@ -0,0 +1,34 @@ +extends GUINode + +var _active : bool = false + +const _screen : NationManagement.Screen = NationManagement.Screen.POPULATION + +func _ready() -> void: + GameSingleton.gamestate_updated.connect(_update_info) + + Events.NationManagementScreens.update_active_nation_management_screen.connect(_on_update_active_nation_management_screen) + + add_gui_element("country_pops", "country_pop") + + var close_button : Button = get_button_from_nodepath(^"./country_pop/close_button") + if close_button: + close_button.pressed.connect(Events.NationManagementScreens.close_nation_management_screen.bind(_screen)) + + _update_info() + +func _notification(what : int) -> void: + match what: + NOTIFICATION_TRANSLATION_CHANGED: + _update_info() + +func _on_update_active_nation_management_screen(active_screen : NationManagement.Screen) -> void: + _active = active_screen == _screen + _update_info() + +func _update_info() -> void: + if _active: + # TODO - update UI state + show() + else: + hide() diff --git a/game/src/Game/GameSession/NationManagementScreen/ProductionMenu.gd b/game/src/Game/GameSession/NationManagementScreen/ProductionMenu.gd new file mode 100644 index 0000000..938f8e7 --- /dev/null +++ b/game/src/Game/GameSession/NationManagementScreen/ProductionMenu.gd @@ -0,0 +1,34 @@ +extends GUINode + +var _active : bool = false + +const _screen : NationManagement.Screen = NationManagement.Screen.PRODUCTION + +func _ready() -> void: + GameSingleton.gamestate_updated.connect(_update_info) + + Events.NationManagementScreens.update_active_nation_management_screen.connect(_on_update_active_nation_management_screen) + + add_gui_element("country_production", "country_production") + + var close_button : Button = get_button_from_nodepath(^"./country_production/close_button") + if close_button: + close_button.pressed.connect(Events.NationManagementScreens.close_nation_management_screen.bind(_screen)) + + _update_info() + +func _notification(what : int) -> void: + match what: + NOTIFICATION_TRANSLATION_CHANGED: + _update_info() + +func _on_update_active_nation_management_screen(active_screen : NationManagement.Screen) -> void: + _active = active_screen == _screen + _update_info() + +func _update_info() -> void: + if _active: + # TODO - update UI state + show() + else: + hide() diff --git a/game/src/Game/GameSession/NationManagementScreen/TechnologyMenu.gd b/game/src/Game/GameSession/NationManagementScreen/TechnologyMenu.gd new file mode 100644 index 0000000..a80ed1e --- /dev/null +++ b/game/src/Game/GameSession/NationManagementScreen/TechnologyMenu.gd @@ -0,0 +1,34 @@ +extends GUINode + +var _active : bool = false + +const _screen : NationManagement.Screen = NationManagement.Screen.TECHNOLOGY + +func _ready() -> void: + GameSingleton.gamestate_updated.connect(_update_info) + + Events.NationManagementScreens.update_active_nation_management_screen.connect(_on_update_active_nation_management_screen) + + add_gui_element("country_technology", "country_technology") + + var close_button : Button = get_button_from_nodepath(^"./country_technology/close_button") + if close_button: + close_button.pressed.connect(Events.NationManagementScreens.close_nation_management_screen.bind(_screen)) + + _update_info() + +func _notification(what : int) -> void: + match what: + NOTIFICATION_TRANSLATION_CHANGED: + _update_info() + +func _on_update_active_nation_management_screen(active_screen : NationManagement.Screen) -> void: + _active = active_screen == _screen + _update_info() + +func _update_info() -> void: + if _active: + # TODO - update UI state + show() + else: + hide() diff --git a/game/src/Game/GameSession/NationManagementScreen/TradeMenu.gd b/game/src/Game/GameSession/NationManagementScreen/TradeMenu.gd new file mode 100644 index 0000000..775f31a --- /dev/null +++ b/game/src/Game/GameSession/NationManagementScreen/TradeMenu.gd @@ -0,0 +1,34 @@ +extends GUINode + +var _active : bool = false + +const _screen : NationManagement.Screen = NationManagement.Screen.TRADE + +func _ready() -> void: + GameSingleton.gamestate_updated.connect(_update_info) + + Events.NationManagementScreens.update_active_nation_management_screen.connect(_on_update_active_nation_management_screen) + + add_gui_element("country_trade", "country_trade") + + var close_button : Button = get_button_from_nodepath(^"./country_trade/close_button") + if close_button: + close_button.pressed.connect(Events.NationManagementScreens.close_nation_management_screen.bind(_screen)) + + _update_info() + +func _notification(what : int) -> void: + match what: + NOTIFICATION_TRANSLATION_CHANGED: + _update_info() + +func _on_update_active_nation_management_screen(active_screen : NationManagement.Screen) -> void: + _active = active_screen == _screen + _update_info() + +func _update_info() -> void: + if _active: + # TODO - update UI state + show() + else: + hide() diff --git a/game/src/Game/GameSession/ProvinceOverviewPanel.gd b/game/src/Game/GameSession/ProvinceOverviewPanel.gd index 6fe28d7..cb76241 100644 --- a/game/src/Game/GameSession/ProvinceOverviewPanel.gd +++ b/game/src/Game/GameSession/ProvinceOverviewPanel.gd @@ -121,7 +121,7 @@ func _ready() -> void: GameSingleton.province_selected.connect(_on_province_selected) GameSingleton.gamestate_updated.connect(_update_info) - if add_gui_element("province_interface.gui", "province_view") != OK: + if add_gui_element("province_interface", "province_view") != OK: push_error("Failed to generate province overview panel!") return @@ -144,7 +144,7 @@ func _ready() -> void: _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") _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.gui", "prov_state_modifier") != OK: + if _province_modifiers_overlapping_elements_box and _province_modifiers_overlapping_elements_box.set_gui_child_element_name("province_interface", "prov_state_modifier") != OK: _province_modifiers_overlapping_elements_box = null # hide province modifiers box since we can't do anything with it _terrain_type_texture = get_gfx_icon_texture_from_nodepath(^"./province_view/province_view_header/prov_terrain") _life_rating_bar = get_progress_bar_from_nodepath(^"./province_view/province_view_header/liferating") @@ -168,7 +168,7 @@ func _ready() -> void: _pop_cultures_piechart = get_gfx_pie_chart_texture_from_nodepath(^"./province_view/province_statistics/culture_chart") _supply_limit_label = get_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.gui", "province_core") != OK: + 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 _buildings_panel = get_panel_from_nodepath(^"./province_view/province_buildings") @@ -176,7 +176,7 @@ func _ready() -> void: var target_slot_count : int = GameSingleton.get_province_building_count() var slot_y : float = 0.0 for current_slot_count : int in target_slot_count: - var slot := GUINode.generate_gui_element("province_interface.gui", "building", "building_slot_%d" % current_slot_count) + var slot := GUINode.generate_gui_element("province_interface", "building", "building_slot_%d" % current_slot_count) if slot: _buildings_panel.add_child(slot) slot.set_position(Vector2(0.0, slot_y)) diff --git a/game/src/Game/GameSession/Topbar.gd b/game/src/Game/GameSession/Topbar.gd index 05eb985..3cfc0e6 100644 --- a/game/src/Game/GameSession/Topbar.gd +++ b/game/src/Game/GameSession/Topbar.gd @@ -1,5 +1,7 @@ extends GUINode +@export var _outliner_guinode : GUINode + var _speed_up_button : Button var _speed_down_button : Button var _speed_indicator_button : Button @@ -7,11 +9,16 @@ var _speed_indicator_texture : GFXIconTexture var _date_label : Label var _country_name_label : Label +# NationManagement.Screen-Button +var _nation_management_buttons : Dictionary +# NationManagement.Screen-GFXIconTexture +var _nation_management_button_textures : Dictionary + func _ready() -> void: GameSingleton.gamestate_updated.connect(_update_info) GameSingleton.clock_state_changed.connect(_update_speed_controls) - add_gui_element("topbar.gui", "topbar") + add_gui_element("topbar", "topbar") hide_nodes([ ^"./topbar/topbar_outlinerbutton_bg", @@ -20,10 +27,12 @@ func _ready() -> void: const player_country : String = "SLV" + # Player country info var player_flag_texture : GFXMaskedFlagTexture = get_gfx_masked_flag_texture_from_nodepath(^"./topbar/player_flag") if player_flag_texture: player_flag_texture.set_flag_country_name(player_country) + # Time controls _speed_up_button = get_button_from_nodepath(^"./topbar/button_speedup") if _speed_up_button: _speed_up_button.pressed.connect(_on_increase_speed_button_pressed) @@ -47,6 +56,31 @@ func _ready() -> void: _speed_indicator_button.pressed.connect(_on_play_pause_button_pressed) _speed_indicator_texture = GUINode.get_gfx_icon_texture_from_node(_speed_indicator_button) + # Nation management screens + const screen_nodepaths : Dictionary = { + NationManagement.Screen.PRODUCTION : ^"./topbar/topbarbutton_production", + NationManagement.Screen.BUDGET : ^"./topbar/topbarbutton_budget", + NationManagement.Screen.TECHNOLOGY : ^"./topbar/topbarbutton_tech", + NationManagement.Screen.POLITICS : ^"./topbar/topbarbutton_politics", + NationManagement.Screen.POPULATION : ^"./topbar/topbarbutton_pops", + NationManagement.Screen.TRADE : ^"./topbar/topbarbutton_trade", + NationManagement.Screen.DIPLOMACY : ^"./topbar/topbarbutton_diplomacy", + NationManagement.Screen.MILITARY : ^"./topbar/topbarbutton_military" + } + for screen in screen_nodepaths: + var button : Button = get_button_from_nodepath(screen_nodepaths[screen]) + if button: + button.pressed.connect( + Events.NationManagementScreens.toggle_nation_management_screen.bind(screen) + ) + var icon : GFXIconTexture = get_gfx_icon_texture_from_node(button) + if icon: + _nation_management_buttons[screen] = button + _nation_management_button_textures[screen] = icon + Events.NationManagementScreens.update_active_nation_management_screen.connect( + _on_update_active_nation_management_screen + ) + _update_info() _update_speed_controls() @@ -92,3 +126,8 @@ func _on_increase_speed_button_pressed() -> void: func _on_decrease_speed_button_pressed() -> void: print("Speed down!") GameSingleton.decrease_speed() + +func _on_update_active_nation_management_screen(active_screen : NationManagement.Screen) -> void: + for screen in _nation_management_buttons: + _nation_management_button_textures[screen].set_icon_index(1 + int(screen == active_screen)) + _nation_management_buttons[screen].queue_redraw() diff --git a/game/src/Game/GameStart.gd b/game/src/Game/GameStart.gd index 7a52846..0aadbb9 100644 --- a/game/src/Game/GameStart.gd +++ b/game/src/Game/GameStart.gd @@ -48,7 +48,7 @@ func _save_setting(file : ConfigFile) -> void: func _setup_compatibility_mode_paths() -> void: # To test mods, set your base path to Victoria II and then pass mods in reverse order with --mod="mod" for each mod. - + var arg_base_path : String = ArgumentParser.get_argument(&"base-path", "") var arg_search_path : String = ArgumentParser.get_argument(&"search-path", "") diff --git a/game/src/Game/GlobalClass/NationManagement.gd b/game/src/Game/GlobalClass/NationManagement.gd new file mode 100644 index 0000000..3b73bde --- /dev/null +++ b/game/src/Game/GlobalClass/NationManagement.gd @@ -0,0 +1,13 @@ +class_name NationManagement + +enum Screen { + NONE, + PRODUCTION, + BUDGET, + TECHNOLOGY, + POLITICS, + POPULATION, + TRADE, + DIPLOMACY, + MILITARY +} |