From 8d0156bc8c4ca1a11a377c58246f6bb1b120ba32 Mon Sep 17 00:00:00 2001 From: hop311 Date: Mon, 20 Jan 2025 17:42:22 +0000 Subject: [PATCH] Starting bookmark position, search panel enter, cleanup --- extension/deps/openvic-simulation | 2 +- .../openvic-extension/classes/GUIListBox.cpp | 2 +- .../singletons/GameSingleton.cpp | 35 +++++++++++++++++++ .../singletons/GameSingleton.hpp | 3 ++ .../singletons/MenuSingleton.cpp | 32 ++++++++--------- .../singletons/MenuSingleton.hpp | 2 ++ .../openvic-extension/utility/Utilities.cpp | 19 ++++++---- .../openvic-extension/utility/Utilities.hpp | 2 +- game/src/Game/GameSession/MapView.gd | 20 +++++++---- game/src/Game/GameSession/ModelManager.gd | 18 +++++----- .../NationManagementScreen/BudgetMenu.gd | 9 +++-- .../NationManagementScreen/PopulationMenu.gd | 6 ++-- game/src/Game/GameSession/SearchPanel.gd | 13 ++++--- game/src/Game/GameSession/Topbar.gd | 16 ++++----- game/src/Game/Menu/LobbyMenu/LobbyMenu.gd | 26 +++++++------- .../Game/Menu/LobbyMenu/LobbyPanelButton.gd | 25 ++++++++----- .../Game/Menu/LobbyMenu/LobbyPanelButton.tscn | 18 ++++++++-- .../Game/Menu/SaveLoadMenu/SavePanelButton.gd | 1 - .../Menu/SaveLoadMenu/SavePanelButton.tscn | 4 +-- game/src/Game/Model/UnitModel.gd | 2 +- 20 files changed, 167 insertions(+), 88 deletions(-) diff --git a/extension/deps/openvic-simulation b/extension/deps/openvic-simulation index 859723ce..51e83e38 160000 --- a/extension/deps/openvic-simulation +++ b/extension/deps/openvic-simulation @@ -1 +1 @@ -Subproject commit 859723ced0444339ae3724b2bbfc0a7e99f7990a +Subproject commit 51e83e38986217aa6b5f5a5a1d714aa13a0bff64 diff --git a/extension/src/openvic-extension/classes/GUIListBox.cpp b/extension/src/openvic-extension/classes/GUIListBox.cpp index 958807fd..39ec9746 100644 --- a/extension/src/openvic-extension/classes/GUIListBox.cpp +++ b/extension/src/openvic-extension/classes/GUIListBox.cpp @@ -270,7 +270,7 @@ Error GUIListBox::set_gui_listbox(GUI::ListBox const* new_gui_listbox) { if (scrollbar_control != nullptr) { scrollbar = Object::cast_to(scrollbar_control); if (scrollbar != nullptr) { - add_child(scrollbar, false, INTERNAL_MODE_FRONT); + add_child(scrollbar, false, INTERNAL_MODE_BACK); const Size2 size = Utilities::to_godot_fvec2(gui_listbox->get_size()); Vector2 position = Utilities::to_godot_fvec2(gui_listbox->get_scrollbar_offset()); diff --git a/extension/src/openvic-extension/singletons/GameSingleton.cpp b/extension/src/openvic-extension/singletons/GameSingleton.cpp index d6148008..56d76701 100644 --- a/extension/src/openvic-extension/singletons/GameSingleton.cpp +++ b/extension/src/openvic-extension/singletons/GameSingleton.cpp @@ -47,6 +47,7 @@ void GameSingleton::_bind_methods() { OV_BIND_SMETHOD(search_for_game_path, { "hint_path" }, DEFVAL(String {})); OV_BIND_METHOD(GameSingleton::lookup_file_path, { "path" }); + OV_BIND_METHOD(GameSingleton::get_bookmark_info); OV_BIND_METHOD(GameSingleton::setup_game, { "bookmark_index" }); OV_BIND_METHOD(GameSingleton::start_game_session); @@ -56,6 +57,7 @@ void GameSingleton::_bind_methods() { OV_BIND_METHOD(GameSingleton::get_map_height); OV_BIND_METHOD(GameSingleton::get_map_dims); OV_BIND_METHOD(GameSingleton::get_map_aspect_ratio); + OV_BIND_METHOD(GameSingleton::get_bookmark_start_position); OV_BIND_METHOD(GameSingleton::get_terrain_texture); OV_BIND_METHOD(GameSingleton::get_flag_dims); OV_BIND_METHOD(GameSingleton::get_flag_sheet_texture); @@ -128,6 +130,27 @@ void GameSingleton::setup_logger() { }); } +TypedArray GameSingleton::get_bookmark_info() const { + static const StringName bookmark_info_name_key = "bookmark_name"; + static const StringName bookmark_info_date_key = "bookmark_date"; + + TypedArray results; + + BookmarkManager const& bookmark_manager = + game_manager.get_definition_manager().get_history_manager().get_bookmark_manager(); + + for (Bookmark const& bookmark : bookmark_manager.get_bookmarks()) { + Dictionary bookmark_info; + + bookmark_info[bookmark_info_name_key] = Utilities::std_to_godot_string(bookmark.get_name()); + bookmark_info[bookmark_info_date_key] = Utilities::date_to_formatted_string(bookmark.get_date(), false); + + results.push_back(std::move(bookmark_info)); + } + + return results; +} + Error GameSingleton::setup_game(int32_t bookmark_index) { Bookmark const* bookmark = game_manager.get_definition_manager().get_history_manager().get_bookmark_manager() .get_bookmark_by_index(bookmark_index); @@ -186,6 +209,18 @@ Vector2 GameSingleton::normalise_map_position(fvec2_t const& position) const { return Utilities::to_godot_fvec2(position) / get_map_dims(); } +Vector2 GameSingleton::get_bookmark_start_position() const { + InstanceManager const* instance_manager = get_instance_manager(); + ERR_FAIL_NULL_V(instance_manager, {}); + + // TODO - What if game started from save rather than bookmark? Does a save game store which bookmark it originated from? + + Bookmark const* bookmark = instance_manager->get_bookmark(); + ERR_FAIL_NULL_V(bookmark, {}); + + return normalise_map_position(bookmark->get_initial_camera_position()); +} + Ref GameSingleton::get_terrain_texture() const { return terrain_texture; } diff --git a/extension/src/openvic-extension/singletons/GameSingleton.hpp b/extension/src/openvic-extension/singletons/GameSingleton.hpp index aa801415..e28bfa5c 100644 --- a/extension/src/openvic-extension/singletons/GameSingleton.hpp +++ b/extension/src/openvic-extension/singletons/GameSingleton.hpp @@ -80,6 +80,8 @@ namespace OpenVic { static godot::String search_for_game_path(godot::String const& hint_path = {}); godot::String lookup_file_path(godot::String const& path) const; + godot::TypedArray get_bookmark_info() const; + /* Post-load/restart game setup - reset the game to post-load state and load the specified bookmark. */ godot::Error setup_game(int32_t bookmark_index); godot::Error start_game_session(); @@ -91,6 +93,7 @@ namespace OpenVic { godot::Vector2i get_map_dims() const; float get_map_aspect_ratio() const; godot::Vector2 normalise_map_position(fvec2_t const& position) const; + godot::Vector2 get_bookmark_start_position() const; /* The cosmetic terrain textures stored in a Texture2DArray. */ godot::Ref get_terrain_texture() const; diff --git a/extension/src/openvic-extension/singletons/MenuSingleton.cpp b/extension/src/openvic-extension/singletons/MenuSingleton.cpp index 75d03e5a..854b9bb6 100644 --- a/extension/src/openvic-extension/singletons/MenuSingleton.cpp +++ b/extension/src/openvic-extension/singletons/MenuSingleton.cpp @@ -51,6 +51,7 @@ String MenuSingleton::get_state_name(State const& state) const { if (!named) { // Capital province name + // TODO - confirm capital is never null? name = tr(GUINode::format_province_name(Utilities::std_to_godot_string(state.get_capital()->get_identifier()))); if (!owned) { @@ -117,18 +118,13 @@ String MenuSingleton::make_modifier_effects_tooltip(ModifierValue const& modifie String result; for (auto const& [effect, value] : modifier.get_values()) { - if (!result.is_empty()) { - result += "\n"; - } - - result += tr(Utilities::std_to_godot_string(effect->get_localisation_key())); - static const String post_name_text = ": " + GUILabel::get_colour_marker(); - result += post_name_text; + + result += "\n" + tr(Utilities::std_to_godot_string(effect->get_localisation_key())) + post_name_text; if (value == 0) { result += "Y"; - } else if (effect->is_positive_good() == value > 0) { + } else if (effect->is_positive_good() == (value > 0)) { result += "G"; } else { result += "R"; @@ -183,11 +179,7 @@ String MenuSingleton::make_rules_tooltip(RuleSet const& rules) const { for (auto const& [rule_group, rule_map] : rules.get_rule_groups()) { for (auto const& [rule, enabled] : rule_map) { - if (!result.is_empty()) { - result += "\n"; - } - - result += tr(Utilities::std_to_godot_string(rule->get_localisation_key())) + result += "\n" + tr(Utilities::std_to_godot_string(rule->get_localisation_key())) + (enabled ? enabled_text : disabled_text); } } @@ -730,11 +722,15 @@ Dictionary MenuSingleton::get_topbar_info() const { { String military_power_tooltip; + static const StringName military_power_from_land_key = "MIL_FROM_TROOPS"; + static const StringName military_power_from_sea_key = "MIL_FROM_CAP_SHIPS"; + static const StringName military_power_from_leaders_key = "MIL_FROM_LEADERS"; + for (auto const& [source, power] : { std::pair - { "MIL_FROM_TROOPS", country->get_military_power_from_land() }, - { "MIL_FROM_CAP_SHIPS", country->get_military_power_from_sea() }, - { "MIL_FROM_LEADERS", country->get_military_power_from_leaders() } + { military_power_from_land_key, country->get_military_power_from_land() }, + { military_power_from_sea_key, country->get_military_power_from_sea() }, + { military_power_from_leaders_key, country->get_military_power_from_leaders() } }) { if (power != 0) { military_power_tooltip += "\n" + tr(source) + ": " + GUILabel::get_colour_marker() + "Y" @@ -873,9 +869,11 @@ String MenuSingleton::get_longform_date() const { InstanceManager const* instance_manager = game_singleton->get_instance_manager(); ERR_FAIL_NULL_V(instance_manager, {}); - return Utilities::date_to_formatted_string(instance_manager->get_today()); + return Utilities::date_to_formatted_string(instance_manager->get_today(), true); } +/* Find/Search Panel */ + Error MenuSingleton::generate_search_cache() { GameSingleton const* game_singleton = GameSingleton::get_singleton(); ERR_FAIL_NULL_V(game_singleton, FAILED); diff --git a/extension/src/openvic-extension/singletons/MenuSingleton.hpp b/extension/src/openvic-extension/singletons/MenuSingleton.hpp index 0d38b649..786a277a 100644 --- a/extension/src/openvic-extension/singletons/MenuSingleton.hpp +++ b/extension/src/openvic-extension/singletons/MenuSingleton.hpp @@ -124,6 +124,8 @@ namespace OpenVic { godot::String get_country_name(CountryInstance const& country) const; godot::String get_country_adjective(CountryInstance const& country) const; + // Modifier effect and rule tooltips begin with a newline character (unless they're empty), as they're always + // added after a starting/title section. godot::String make_modifier_effects_tooltip(ModifierValue const& modifier) const; godot::String make_rules_tooltip(RuleSet const& rules) const; diff --git a/extension/src/openvic-extension/utility/Utilities.cpp b/extension/src/openvic-extension/utility/Utilities.cpp index 1fcdea8d..70d2aa34 100644 --- a/extension/src/openvic-extension/utility/Utilities.cpp +++ b/extension/src/openvic-extension/utility/Utilities.cpp @@ -68,15 +68,22 @@ String Utilities::float_to_string_dp_dynamic(float 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()); - const String day_and_year = " " + String::num_int64(date.get_day()) + ", " + String::num_int64(date.get_year()); +/* Date formatted like one of these, with the month localised if possible: + * - "1 January, 1836" (if month_first is false) + * - "January 1, 1836" (if month_first is true) */ +String Utilities::date_to_formatted_string(Date date, bool month_first) { + String day = String::num_int64(date.get_day()); + String month = Utilities::std_to_godot_string(date.get_month_name()); TranslationServer const* server = TranslationServer::get_singleton(); if (server != nullptr) { - return server->translate(month_name) + day_and_year; + month = server->translate(month); + } + String year = String::num_int64(date.get_year()); + + if (month_first) { + return month + " " + day + ", " + year; } else { - return month_name + day_and_year; + return day + " " + month + ", " + year; } } diff --git a/extension/src/openvic-extension/utility/Utilities.hpp b/extension/src/openvic-extension/utility/Utilities.hpp index c1739388..98eabac8 100644 --- a/extension/src/openvic-extension/utility/Utilities.hpp +++ b/extension/src/openvic-extension/utility/Utilities.hpp @@ -39,7 +39,7 @@ namespace OpenVic::Utilities { return static_cast(val); } - godot::String date_to_formatted_string(Date date); + godot::String date_to_formatted_string(Date date, bool month_first); _FORCE_INLINE_ godot::Color to_godot_color(IsColour auto colour) { return { colour.redf(), colour.greenf(), colour.bluef(), colour.alphaf() }; diff --git a/game/src/Game/GameSession/MapView.gd b/game/src/Game/GameSession/MapView.gd index 1d837f85..0326edd8 100644 --- a/game/src/Game/GameSession/MapView.gd +++ b/game/src/Game/GameSession/MapView.gd @@ -34,7 +34,7 @@ var _mouse_over_viewport : bool = true # hence why it is not exported and just has _zoom_target_max as a placeholder. var _zoom_target : float = _zoom_target_max: get: return _zoom_target - set(v): _zoom_target = clamp(v, _zoom_target_min, _zoom_target_max) + set(v): _zoom_target = clampf(v, _zoom_target_min, _zoom_target_max) const _zoom_position_multiplier = 3.14159 # Horizontal movement coefficient during zoom var _zoom_position : Vector2 @@ -72,11 +72,6 @@ func _ready() -> void: push_error("MapView's _camera variable hasn't been set!") return - # Start just under the parchment threshold - _camera.position.y = _zoom_parchment_threshold - _zoom_target_step - _zoom_target = _camera.position.y - _update_view_states(true) - if not _map_mesh_instance: push_error("MapView's _map_mesh_instance variable hasn't been set!") return @@ -108,6 +103,17 @@ func _ready() -> void: GameSingleton.province_selected.connect(_on_province_selected) + # TODO - start looking at the player country's capital (the bookmark start position is meant + # for the lobby map when first selecting the bookmark, not for when actually entering the game) + + # Start at the bookmark's start position + _camera.position = _map_to_world_coords(GameSingleton.get_bookmark_start_position()) + + # Start zoomed out with the parchment map active + _camera.position.y = _zoom_parchment_threshold * 1.5 + _zoom_target = _camera.position.y + _update_view_states(true) + if not _map_background_instance: push_error("MapView's _map_background_instance variable hasn't been set!") return @@ -293,7 +299,7 @@ func _edge_scrolling_vector() -> Vector2: func _clamp_over_map() -> void: _camera.position.x = _map_mesh_corner.x + fposmod(_camera.position.x - _map_mesh_corner.x, _map_mesh_dims.x) - _camera.position.z = clamp(_camera.position.z, _map_mesh_corner.y, _map_mesh_corner.y + _map_mesh_dims.y) + _camera.position.z = clampf(_camera.position.z, _map_mesh_corner.y, _map_mesh_corner.y + _map_mesh_dims.y) func _update_view_states(force_signal : bool) -> void: var new_is_parchment_view : bool = _camera.position.y >= _zoom_parchment_threshold - _zoom_epsilon diff --git a/game/src/Game/GameSession/ModelManager.gd b/game/src/Game/GameSession/ModelManager.gd index 8cec49dc..de9de547 100644 --- a/game/src/Game/GameSession/ModelManager.gd +++ b/game/src/Game/GameSession/ModelManager.gd @@ -32,8 +32,10 @@ func _generate_unit(unit_dict : Dictionary) -> void: # This must be a UnitModel so we can attach the rider to it var mount_model : Node3D = _generate_model(unit_dict[mount_model_key], unit_dict[culture_key], true) if mount_model: - mount_model.attach_model(unit_dict[mount_attach_node_key], model) - model = mount_model + if mount_model.attach_model(unit_dict[mount_attach_node_key], model) == OK: + model = mount_model + else: + mount_model.free() var rotation : float = unit_dict.get(rotation_key, 0.0) @@ -127,8 +129,8 @@ func _generate_model(model_dict : Dictionary, culture : String = "", is_unit : b # Attachments for attachment_dict : Dictionary in model_dict.get(attachments_key, []): var attachment_model : Node3D = _generate_model(attachment_dict[attachment_model_key], culture) - if attachment_model: - model.attach_model(attachment_dict[attachment_node_key], attachment_model) + if attachment_model and model.attach_model(attachment_dict[attachment_node_key], attachment_model) != OK: + attachment_model.free() if culture: const gun_bone_name : String = "GunNode" @@ -136,15 +138,15 @@ func _generate_model(model_dict : Dictionary, culture : String = "", is_unit : b var gun_dict : Dictionary = ModelSingleton.get_cultural_gun_model(culture) if gun_dict: var gun_model : Node3D = _generate_model(gun_dict, culture) - if gun_model: - model.attach_model(gun_bone_name, gun_model) + if gun_model and model.attach_model(gun_bone_name, gun_model) != OK: + gun_model.free() const helmet_bone_name : String = "HelmetNode" if model.has_bone(helmet_bone_name): var helmet_dict : Dictionary = ModelSingleton.get_cultural_helmet_model(culture) if helmet_dict: var helmet_model : Node3D = _generate_model(helmet_dict, culture) - if helmet_model: - model.attach_model(helmet_bone_name, helmet_model) + if helmet_model and model.attach_model(helmet_bone_name, helmet_model) != OK: + helmet_model.free() return model diff --git a/game/src/Game/GameSession/NationManagementScreen/BudgetMenu.gd b/game/src/Game/GameSession/NationManagementScreen/BudgetMenu.gd index 10446e3c..87b63ab0 100644 --- a/game/src/Game/GameSession/NationManagementScreen/BudgetMenu.gd +++ b/game/src/Game/GameSession/NationManagementScreen/BudgetMenu.gd @@ -43,11 +43,10 @@ var _debt_chart : GUIPieChart const _screen : NationManagement.Screen = NationManagement.Screen.BUDGET # TODO - testing function, should be replaced with calls to SIM which trigger UI updates through gamestate_updated -func _on_tax_slider_changed(slider : GUIScrollbar, label : GUILabel, tooltip : String, value : int) -> void: +func _on_tax_slider_changed(slider : GUIScrollbar, label : GUILabel, tooltip : StringName, value : int) -> void: label.text = "%s¤" % GUINode.float_to_string_dp(value, 3 if abs(value) < 1000 else 1) slider.set_tooltip_string("%s: §Y%s%%" % [tr(tooltip), GUINode.float_to_string_dp(value, 1)]) - func _ready() -> void: GameSingleton.gamestate_updated.connect(_update_info) @@ -97,21 +96,21 @@ func _ready() -> void: if _lower_class_slider and _lower_class_label: _lower_class_slider.value_changed.connect( func (value : int) -> void: - _on_tax_slider_changed(_lower_class_slider, _lower_class_label, "BUDGET_TAX_POOR", value) + _on_tax_slider_changed(_lower_class_slider, _lower_class_label, &"BUDGET_TAX_POOR", value) ) _lower_class_slider.emit_value_changed() var _middle_class_slider : GUIScrollbar = get_gui_scrollbar_from_nodepath(^"./country_budget/tax_1_slider") if _middle_class_slider and _middle_class_label: _middle_class_slider.value_changed.connect( func (value : int) -> void: - _on_tax_slider_changed(_middle_class_slider, _middle_class_label, "BUDGET_TAX_MIDDLE", value) + _on_tax_slider_changed(_middle_class_slider, _middle_class_label, &"BUDGET_TAX_MIDDLE", value) ) _middle_class_slider.emit_value_changed() var _upper_class_slider : GUIScrollbar = get_gui_scrollbar_from_nodepath(^"./country_budget/tax_2_slider") if _upper_class_slider and _upper_class_label: _upper_class_slider.value_changed.connect( func (value : int) -> void: - _on_tax_slider_changed(_upper_class_slider, _upper_class_label, "BUDGET_TAX_RICH", value) + _on_tax_slider_changed(_upper_class_slider, _upper_class_label, &"BUDGET_TAX_RICH", value) ) _upper_class_slider.emit_value_changed() diff --git a/game/src/Game/GameSession/NationManagementScreen/PopulationMenu.gd b/game/src/Game/GameSession/NationManagementScreen/PopulationMenu.gd index b872db0f..e9c151f8 100644 --- a/game/src/Game/GameSession/NationManagementScreen/PopulationMenu.gd +++ b/game/src/Game/GameSession/NationManagementScreen/PopulationMenu.gd @@ -600,7 +600,7 @@ func _update_pop_list() -> void: var unemployment : float = pop_row[pop_unemployment_key] _pop_list_unemployment_progressbars[index].set_value_no_signal(unemployment) _pop_list_unemployment_progressbars[index].set_tooltip_string("%s: §Y%s%%" % [ - tr("UNEMPLOYMENT"), GUINode.float_to_string_dp(unemployment * 100.0, 3) + tr(&"UNEMPLOYMENT"), GUINode.float_to_string_dp(unemployment * 100.0, 3) ]) if _pop_list_cash_labels[index]: _pop_list_cash_labels[index].set_text("%s¤" % GUINode.float_to_string_dp(pop_row[pop_cash_key], 2)) @@ -645,12 +645,12 @@ func _update_pop_list() -> void: var pop_change : int = pop_row[pop_size_change_key] _pop_list_size_change_icons[index].set_icon_index(get_growth_icon_index(pop_change)) _pop_list_size_change_icons[index].set_tooltip_string("%s §%s%s" % [ - tr("POPULATION_CHANGED_BY"), "G+" if pop_change > 0 else "Y+" if pop_change == 0 else "R", str(pop_change) + tr(&"POPULATION_CHANGED_BY"), "G+" if pop_change > 0 else "Y+" if pop_change == 0 else "R", str(pop_change) ]) if _pop_list_literacy_labels[index]: _pop_list_literacy_labels[index].set_text("%s%%" % GUINode.float_to_string_dp(pop_row[pop_literacy_key], 2)) _pop_list_literacy_labels[index].set_tooltip_string("%s: §G%s%%" % [ - tr("LIT_CHANGE"), GUINode.float_to_string_dp(pop_row[pop_literacy_key] / 64.0, 2) + tr(&"LIT_CHANGE"), GUINode.float_to_string_dp(pop_row[pop_literacy_key] / 64.0, 2) ]) _pop_list_rows[index].show() diff --git a/game/src/Game/GameSession/SearchPanel.gd b/game/src/Game/GameSession/SearchPanel.gd index 3d96367f..82cbcb03 100644 --- a/game/src/Game/GameSession/SearchPanel.gd +++ b/game/src/Game/GameSession/SearchPanel.gd @@ -36,6 +36,10 @@ func _ready() -> void: _search_line_edit = get_line_edit_from_nodepath(^"./goto_box/goto_edit") if _search_line_edit: _search_line_edit.text_changed.connect(_search_string_updated) + _search_line_edit.text_submitted.connect( + func(new_text : String) -> void: + _result_selected(0) + ) # Restrict to desired size (by default it's a bit too tall, probably due to font size) _search_line_edit.set_size(_search_line_edit.get_minimum_size()) @@ -135,10 +139,11 @@ func _update_results_scroll(scroll_index : int = -1) -> void: _result_buttons[index].set_text(results[index]) func _result_selected(index : int) -> void: - if _map_view: - _map_view.look_at_map_position(MenuSingleton.get_search_result_position(index)) - else: - push_error("SearchPanel missing MapView reference!") + if not _result_buttons.is_empty(): + if _map_view: + _map_view.look_at_map_position(MenuSingleton.get_search_result_position(index)) + else: + push_error("SearchPanel missing MapView reference!") if _search_line_edit: # This triggers a search results update, preventing further get_search_result_position(index) calls diff --git a/game/src/Game/GameSession/Topbar.gd b/game/src/Game/GameSession/Topbar.gd index 11e584cd..4f917d29 100644 --- a/game/src/Game/GameSession/Topbar.gd +++ b/game/src/Game/GameSession/Topbar.gd @@ -153,7 +153,7 @@ func _ready() -> void: Events.NationManagementScreens.toggle_nation_management_screen.bind(screen) ) # TODO - test tooltip, replace with actual shortcut strings - button.set_tooltip_string(tr("SHORTCUT") + "F3") + button.set_tooltip_string(tr(&"SHORTCUT") + "F3") _nation_management_buttons[screen] = button Events.NationManagementScreens.update_active_nation_management_screen.connect( _on_update_active_nation_management_screen @@ -311,7 +311,7 @@ func _update_info() -> void: var country_name : String = MenuSingleton.get_country_name_from_identifier(country_identifier) var country_status : int = topbar_info.get(country_status_key, CountryStatus.UNCIVILISED) - var country_name_rank_tooltip : String = tr("PLAYER_COUNTRY_TOPBAR_RANK") + MenuSingleton.get_tooltip_separator() + tr("RANK_TOTAL_D") + var country_name_rank_tooltip : String = tr(&"PLAYER_COUNTRY_TOPBAR_RANK") + MenuSingleton.get_tooltip_separator() + tr(&"RANK_TOTAL_D") var country_name_rank_dict : Dictionary = { "NAME": country_name, "RANK": COUNTRY_STATUS_NAMES[country_status] @@ -335,7 +335,7 @@ func _update_info() -> void: _country_rank_label.set_text(str(topbar_info.get(total_rank_key, 0))) _country_rank_label.set_tooltip_string_and_substitution_dict(country_name_rank_tooltip, country_name_rank_dict) - var prestige_tooltip : String = tr("RANK_PRESTIGE") + topbar_info.get(prestige_tooltip_key, "") + MenuSingleton.get_tooltip_separator() + tr("RANK_PRESTIGE_D") + var prestige_tooltip : String = tr(&"RANK_PRESTIGE") + topbar_info.get(prestige_tooltip_key, "") + MenuSingleton.get_tooltip_separator() + tr(&"RANK_PRESTIGE_D") if _country_prestige_label: _country_prestige_label.set_text(str(topbar_info.get(prestige_key, 0))) @@ -345,7 +345,7 @@ func _update_info() -> void: _country_prestige_rank_label.set_text(str(topbar_info.get(prestige_rank_key, 0))) _country_prestige_rank_label.set_tooltip_string(prestige_tooltip) - var industrial_power_tooltip : String = tr("RANK_INDUSTRY") + MenuSingleton.get_tooltip_separator() + tr("RANK_INDUSTRY_D") + topbar_info.get(industrial_power_tooltip_key, "") + var industrial_power_tooltip : String = tr(&"RANK_INDUSTRY") + MenuSingleton.get_tooltip_separator() + tr(&"RANK_INDUSTRY_D") + topbar_info.get(industrial_power_tooltip_key, "") if _country_industrial_power_label: _country_industrial_power_label.set_text(str(topbar_info.get(industrial_power_key, 0))) @@ -355,7 +355,7 @@ func _update_info() -> void: _country_industrial_power_rank_label.set_text(str(topbar_info.get(industrial_rank_key, 0))) _country_industrial_power_rank_label.set_tooltip_string(industrial_power_tooltip) - var military_power_tooltip : String = tr("RANK_MILITARY") + MenuSingleton.get_tooltip_separator() + tr("RANK_MILITARY_D") + topbar_info.get(military_power_tooltip_key, "") + var military_power_tooltip : String = tr(&"RANK_MILITARY") + MenuSingleton.get_tooltip_separator() + tr(&"RANK_MILITARY_D") + topbar_info.get(military_power_tooltip_key, "") if _country_military_power_label: _country_military_power_label.set_text(str(topbar_info.get(military_power_key, 0))) @@ -371,8 +371,8 @@ func _update_info() -> void: _country_colonial_power_label.set_text( "§%s%s§!/%s" % ["W" if available_colonial_power > 0 else "R", available_colonial_power, max_colonial_power] ) - _country_colonial_power_label.set_tooltip_string(tr("COLONIAL_POINTS") + MenuSingleton.get_tooltip_separator() + ( - topbar_info.get(colonial_power_tooltip_key, "") if country_status <= CountryStatus.SECONDARY_POWER else tr("NON_COLONIAL_POWER") + _country_colonial_power_label.set_tooltip_string(tr(&"COLONIAL_POINTS") + MenuSingleton.get_tooltip_separator() + ( + topbar_info.get(colonial_power_tooltip_key, "") if country_status <= CountryStatus.SECONDARY_POWER else tr(&"NON_COLONIAL_POWER") )) ## Time control @@ -536,7 +536,7 @@ func _update_info() -> void: _military_mobilisation_size_label.set_text("§Y" + mobilisation_regiments) _military_mobilisation_size_label.set_tooltip_string_and_substitution_dict( - tr("TOPBAR_MOBILIZE_TOOLTIP") + "\n\n" + tr("MOBILIZATION_IMPACT_LIMIT_DESC") + "\n" + tr("MOBILIZATION_IMPACT_LIMIT_DESC2").replace("$CURR$", "$CURR2$"), + tr(&"TOPBAR_MOBILIZE_TOOLTIP") + "\n\n" + tr(&"MOBILIZATION_IMPACT_LIMIT_DESC") + "\n" + tr(&"MOBILIZATION_IMPACT_LIMIT_DESC2").replace("$CURR$", "$CURR2$"), { "CURR": mobilisation_regiments, "IMPACT": mobilisation_impact, "POLICY": topbar_info.get(war_policy_key, ""), "UNITS": str(topbar_info.get(mobilisation_max_regiments_key, 0)), "CURR2": regiment_count diff --git a/game/src/Game/Menu/LobbyMenu/LobbyMenu.gd b/game/src/Game/Menu/LobbyMenu/LobbyMenu.gd index ca6b3fb9..ef845ebb 100644 --- a/game/src/Game/Menu/LobbyMenu/LobbyMenu.gd +++ b/game/src/Game/Menu/LobbyMenu/LobbyMenu.gd @@ -31,14 +31,15 @@ func filter_for_tag(tag : StringName) -> void: child.hide() func _build_date_list() -> void: - var start_date := lobby_panel_button.instantiate() - start_date.set_text(&"1836") - start_date.pressed.connect(_on_start_date_panel_button_pressed.bind(start_date)) - game_select_start_date.add_child(start_date) - start_date = lobby_panel_button.instantiate() - start_date.set_text(&"1863") - start_date.pressed.connect(_on_start_date_panel_button_pressed.bind(start_date)) - game_select_start_date.add_child(start_date) + const bookmark_info_name_key : StringName = &"bookmark_name" + const bookmark_info_date_key : StringName = &"bookmark_date" + + for bookmark_dict : Dictionary in GameSingleton.get_bookmark_info(): + var start_date := lobby_panel_button.instantiate() + start_date.set_name_text(bookmark_dict.get(bookmark_info_name_key, "MISSING BOOKMARK NAME")) + start_date.set_date_text(bookmark_dict.get(bookmark_info_date_key, "MISSING BOOKMARK DATE")) + start_date.pressed.connect(_on_start_date_panel_button_pressed.bind(start_date)) + game_select_start_date.add_child(start_date) var _id_to_tag : Array[StringName] = [] @@ -116,11 +117,12 @@ func _on_session_tag_edit_text_submitted(new_text : String) -> void: _on_start_button_pressed() func _on_session_tag_dialog_confirmed() -> void: - # TODO - get bookmarks from SIM and generated corresponding buttons, - # then use the selected button's bookmark instead of always using 0 + if _start_date_index < 0: + push_error("Cannot setup game, no start date selected!") + return # Game has to be setup (bookmark loaded) before opening the GameSession scene - if GameSingleton.setup_game(0) != OK: + if GameSingleton.setup_game(_start_date_index) != OK: push_error("Failed to setup game") get_tree().change_scene_to_file("res://src/Game/GameSession/GameSession.tscn") @@ -131,7 +133,7 @@ func _on_save_node_delete_requested(node : Control) -> void: delete_dialog.title = tr("GAMELOBBY_DELETE_DIALOG_TITLE").format({ "file_name": _requested_node_to_delete.resource.save_name }) delete_dialog.popup_centered() -var _start_date_index := -1 +var _start_date_index : int = -1 func _on_start_date_panel_button_pressed(node : Control) -> void: if node is LobbyPanelButton and node.get_index(true) == _start_date_index: _on_start_button_pressed() diff --git a/game/src/Game/Menu/LobbyMenu/LobbyPanelButton.gd b/game/src/Game/Menu/LobbyMenu/LobbyPanelButton.gd index b50ee28b..2add942c 100644 --- a/game/src/Game/Menu/LobbyMenu/LobbyPanelButton.gd +++ b/game/src/Game/Menu/LobbyMenu/LobbyPanelButton.gd @@ -16,17 +16,28 @@ func _is_start_date() -> bool: @export_group("Nodes") @export var background_button : BaseButton @export var name_label : Label +@export var date_label : Label -var text : StringName: - get = get_text, - set = set_text +var name_text : String: + get = get_name_text, + set = set_name_text -func get_text() -> StringName: +var date_text : String: + get = get_date_text, + set = set_date_text + +func get_name_text() -> String: return name_label.text -func set_text(value : StringName) -> void: +func set_name_text(value : String) -> void: name_label.text = value +func get_date_text() -> String: + return date_label.text + +func set_date_text(value : String) -> void: + date_label.text = value + func _get_minimum_size() -> Vector2: var result := Vector2() for child : Control in get_children(): @@ -35,9 +46,7 @@ func _get_minimum_size() -> Vector2: if child.top_level: continue - var minsize : Vector2 = child.get_combined_minimum_size() - result.x = max(result.x, minsize.x) - result.y = max(result.y, minsize.y) + result = result.max(child.get_combined_minimum_size()) var draw_style := _get_draw_mode_style() if draw_style != null: diff --git a/game/src/Game/Menu/LobbyMenu/LobbyPanelButton.tscn b/game/src/Game/Menu/LobbyMenu/LobbyPanelButton.tscn index f27ddac2..b9e2d60a 100644 --- a/game/src/Game/Menu/LobbyMenu/LobbyPanelButton.tscn +++ b/game/src/Game/Menu/LobbyMenu/LobbyPanelButton.tscn @@ -1,20 +1,24 @@ -[gd_scene load_steps=2 format=3 uid="uid://k71f5gibwmtc"] +[gd_scene load_steps=3 format=3 uid="uid://k71f5gibwmtc"] [ext_resource type="Script" path="res://src/Game/Menu/LobbyMenu/LobbyPanelButton.gd" id="1_327u2"] -[node name="LobbyPanelButton" type="Container" node_paths=PackedStringArray("background_button", "name_label")] +[sub_resource type="FontVariation" id="FontVariation_xwn8e"] +variation_embolden = 1.0 + +[node name="LobbyPanelButton" type="Container" node_paths=PackedStringArray("background_button", "name_label", "date_label")] editor_description = "UI-41" offset_right = 113.0 offset_bottom = 48.0 script = ExtResource("1_327u2") background_button = NodePath("BackgroundButton") name_label = NodePath("SaveList/NameLabel") +date_label = NodePath("SaveList/DateLabel") [node name="BackgroundButton" type="Button" parent="."] layout_mode = 2 theme_type_variation = &"ButtonContainer" -[node name="SaveList" type="HBoxContainer" parent="."] +[node name="SaveList" type="VBoxContainer" parent="."] layout_mode = 2 size_flags_horizontal = 0 mouse_filter = 2 @@ -22,6 +26,14 @@ mouse_filter = 2 [node name="NameLabel" type="Label" parent="SaveList"] layout_mode = 2 size_flags_vertical = 1 +theme_override_fonts/font = SubResource("FontVariation_xwn8e") +theme_override_font_sizes/font_size = 18 +text = "PLACEHOLDER" +vertical_alignment = 1 + +[node name="DateLabel" type="Label" parent="SaveList"] +layout_mode = 2 +size_flags_vertical = 1 text = "PLACEHOLDER" vertical_alignment = 1 diff --git a/game/src/Game/Menu/SaveLoadMenu/SavePanelButton.gd b/game/src/Game/Menu/SaveLoadMenu/SavePanelButton.gd index 6dc43c9a..69a587d8 100644 --- a/game/src/Game/Menu/SaveLoadMenu/SavePanelButton.gd +++ b/game/src/Game/Menu/SaveLoadMenu/SavePanelButton.gd @@ -5,7 +5,6 @@ signal request_to_delete @export_group("Nodes") @export var country_flag : TextureRect -@export var date_label : Label @export var delete_button : BaseButton var resource : SaveResource: diff --git a/game/src/Game/Menu/SaveLoadMenu/SavePanelButton.tscn b/game/src/Game/Menu/SaveLoadMenu/SavePanelButton.tscn index 94dc8a3a..077025c6 100644 --- a/game/src/Game/Menu/SaveLoadMenu/SavePanelButton.tscn +++ b/game/src/Game/Menu/SaveLoadMenu/SavePanelButton.tscn @@ -2,16 +2,16 @@ [ext_resource type="Script" path="res://src/Game/Menu/SaveLoadMenu/SavePanelButton.gd" id="1_rtuo6"] -[node name="SavePanelButton" type="Container" node_paths=PackedStringArray("country_flag", "date_label", "delete_button", "background_button", "name_label")] +[node name="SavePanelButton" type="Container" node_paths=PackedStringArray("country_flag", "delete_button", "background_button", "name_label", "date_label")] editor_description = "SS-18, UI-40, UI-84, UI-86, UI-91, UI-93" offset_right = 276.0 offset_bottom = 48.0 script = ExtResource("1_rtuo6") country_flag = NodePath("SaveList/CountryFlag") -date_label = NodePath("SaveList/DateLabel") delete_button = NodePath("SaveList/DeleteButton") background_button = NodePath("BackgroundButton") name_label = NodePath("SaveList/NameLabel") +date_label = NodePath("SaveList/DateLabel") [node name="BackgroundButton" type="Button" parent="."] layout_mode = 2 diff --git a/game/src/Game/Model/UnitModel.gd b/game/src/Game/Model/UnitModel.gd index e98d22a4..d482c12f 100644 --- a/game/src/Game/Model/UnitModel.gd +++ b/game/src/Game/Model/UnitModel.gd @@ -138,7 +138,7 @@ func attach_model(bone_name : String, model : Node3D) -> Error: var bone_idx : int = skeleton.find_bone(bone_name) if bone_idx < 0 or bone_idx >= skeleton.get_bone_count(): - push_error("Invalid bone \"", bone_name, "\" (index ", bone_idx, ") for attachment \"", model.get_name(), "\" to UnitModel \"", get_name(), "\"") + push_warning("Invalid bone \"", bone_name, "\" (index ", bone_idx, ") for attachment \"", model.get_name(), "\" to UnitModel \"", get_name(), "\"") return FAILED var bone_attachment := BoneAttachment3D.new()