diff options
13 files changed, 387 insertions, 340 deletions
diff --git a/extension/deps/openvic-simulation b/extension/deps/openvic-simulation -Subproject 8defcd5daa1acd2c61aa1cd0a26478d472fed9b +Subproject dda680ccf0981fe4df70fe903d2fe4ec9dc594a diff --git a/extension/src/openvic-extension/singletons/GameSingleton.cpp b/extension/src/openvic-extension/singletons/GameSingleton.cpp index f258fe1..553d17c 100644 --- a/extension/src/openvic-extension/singletons/GameSingleton.cpp +++ b/extension/src/openvic-extension/singletons/GameSingleton.cpp @@ -33,6 +33,10 @@ StringName const& GameSingleton::_signal_clock_state_changed() { static const StringName signal_clock_state_changed = "clock_state_changed"; return signal_clock_state_changed; } +StringName const& GameSingleton::_signal_mapmode_changed() { + static const StringName signal_mapmode_changed = "mapmode_changed"; + return signal_mapmode_changed; +} void GameSingleton::_bind_methods() { OV_BIND_SMETHOD(setup_logger); @@ -63,7 +67,9 @@ void GameSingleton::_bind_methods() { OV_BIND_METHOD(GameSingleton::get_mapmode_count); OV_BIND_METHOD(GameSingleton::get_mapmode_identifier); - OV_BIND_METHOD(GameSingleton::set_mapmode, { "identifier" }); + OV_BIND_METHOD(GameSingleton::get_mapmode_localisation_key); + OV_BIND_METHOD(GameSingleton::get_current_mapmode_index); + OV_BIND_METHOD(GameSingleton::set_mapmode, { "index" }); OV_BIND_METHOD(GameSingleton::is_parchment_mapmode_allowed); OV_BIND_METHOD(GameSingleton::get_selected_province_index); OV_BIND_METHOD(GameSingleton::set_selected_province, { "index" }); @@ -76,6 +82,7 @@ void GameSingleton::_bind_methods() { ADD_SIGNAL(MethodInfo(_signal_gamestate_updated())); ADD_SIGNAL(MethodInfo(_signal_province_selected(), PropertyInfo(Variant::INT, "index"))); ADD_SIGNAL(MethodInfo(_signal_clock_state_changed())); + ADD_SIGNAL(MethodInfo(_signal_mapmode_changed(), PropertyInfo(Variant::INT, "index"))); } GameSingleton* GameSingleton::get_singleton() { @@ -95,9 +102,11 @@ void GameSingleton::_on_clock_state_changed() { * MAP-21, MAP-23, MAP-25, MAP-32, MAP-33, MAP-34 */ GameSingleton::GameSingleton() - : game_manager { + : game_manager { std::bind(&GameSingleton::_on_gamestate_updated, this), std::bind(&GameSingleton::_on_clock_state_changed, this) - }, viewed_country { nullptr } { + }, + viewed_country { nullptr }, + mapmode { &Mapmode::ERROR_MAPMODE } { ERR_FAIL_COND(singleton != nullptr); singleton = this; } @@ -249,7 +258,7 @@ Error GameSingleton::_update_colour_image() { InstanceManager const* instance_manager = get_instance_manager(); if (instance_manager != nullptr && !get_definition_manager().get_mapmode_manager().generate_mapmode_colours( - instance_manager->get_map_instance(), mapmode_index, colour_data_array.ptrw() + instance_manager->get_map_instance(), mapmode, colour_data_array.ptrw() )) { err = FAILED; } @@ -311,28 +320,37 @@ int32_t GameSingleton::get_mapmode_count() const { } String GameSingleton::get_mapmode_identifier(int32_t index) const { - Mapmode const* mapmode = get_definition_manager().get_mapmode_manager().get_mapmode_by_index(index); - if (mapmode != nullptr) { - return Utilities::std_to_godot_string(mapmode->get_identifier()); + Mapmode const* identifier_mapmode = get_definition_manager().get_mapmode_manager().get_mapmode_by_index(index); + if (identifier_mapmode != nullptr) { + return Utilities::std_to_godot_string(identifier_mapmode->get_identifier()); + } + return String {}; +} + +String GameSingleton::get_mapmode_localisation_key(int32_t index) const { + Mapmode const* localisation_key_mapmode = get_definition_manager().get_mapmode_manager().get_mapmode_by_index(index); + if (localisation_key_mapmode != nullptr) { + return Utilities::std_to_godot_string(localisation_key_mapmode->get_localisation_key()); } return String {}; } -Error GameSingleton::set_mapmode(String const& identifier) { - Mapmode const* mapmode = - get_definition_manager().get_mapmode_manager().get_mapmode_by_identifier(Utilities::godot_to_std_string(identifier)); - ERR_FAIL_NULL_V_MSG(mapmode, FAILED, vformat("Failed to find mapmode with identifier: %s", identifier)); - mapmode_index = mapmode->get_index(); - return _update_colour_image(); +int32_t GameSingleton::get_current_mapmode_index() const { + return mapmode->get_index(); +} + +Error GameSingleton::set_mapmode(int32_t index) { + Mapmode const* new_mapmode = get_definition_manager().get_mapmode_manager().get_mapmode_by_index(index); + ERR_FAIL_NULL_V_MSG(new_mapmode, FAILED, vformat("Failed to find mapmode with index: %d", index)); + mapmode = new_mapmode; + const Error err = _update_colour_image(); + emit_signal(_signal_mapmode_changed(), mapmode->get_index()); + return err; } bool GameSingleton::is_parchment_mapmode_allowed() const { - // TODO - parchment bool per mapmode? - // TODO - move mapmode index to SIM/Map? - /* Disallows parchment mapmode for the cosmetic terrain mapmode */ - static constexpr std::string_view cosmetic_terrain_mapmode = "mapmode_terrain"; - Mapmode const* mapmode = get_definition_manager().get_mapmode_manager().get_mapmode_by_index(mapmode_index); - return mapmode != nullptr && mapmode->get_identifier() != cosmetic_terrain_mapmode; + /* Disallows parchment mapmode, e.g. for the cosmetic terrain mapmode */ + return mapmode->is_parchment_mapmode_allowed(); } int32_t GameSingleton::get_selected_province_index() const { diff --git a/extension/src/openvic-extension/singletons/GameSingleton.hpp b/extension/src/openvic-extension/singletons/GameSingleton.hpp index e737643..aa80141 100644 --- a/extension/src/openvic-extension/singletons/GameSingleton.hpp +++ b/extension/src/openvic-extension/singletons/GameSingleton.hpp @@ -21,7 +21,7 @@ namespace OpenVic { godot::Ref<godot::Texture2DArray> province_shape_texture; godot::Ref<godot::Image> province_colour_image; godot::Ref<godot::ImageTexture> province_colour_texture; - Mapmode::index_t mapmode_index = 0; + Mapmode const* mapmode; // This should never be null, if no mapmode is set then it'll point to Mapmode::ERROR_MAPMODE godot::Ref<godot::Texture2DArray> terrain_texture; static const godot::Vector2i PROPERTY(flag_dims); /* The size in pixels of an individual flag. */ @@ -34,6 +34,7 @@ namespace OpenVic { static godot::StringName const& _signal_gamestate_updated(); static godot::StringName const& _signal_province_selected(); static godot::StringName const& _signal_clock_state_changed(); + static godot::StringName const& _signal_mapmode_changed(); godot::Error _load_map_images(); godot::Error _load_terrain_variants(); @@ -120,7 +121,9 @@ namespace OpenVic { int32_t get_mapmode_count() const; godot::String get_mapmode_identifier(int32_t index) const; - godot::Error set_mapmode(godot::String const& identifier); + godot::String get_mapmode_localisation_key(int32_t index) const; + int32_t get_current_mapmode_index() const; + godot::Error set_mapmode(int32_t index); bool is_parchment_mapmode_allowed() const; int32_t get_selected_province_index() const; void set_selected_province(int32_t index); diff --git a/extension/src/openvic-extension/singletons/MenuSingleton.cpp b/extension/src/openvic-extension/singletons/MenuSingleton.cpp index 81582c2..e5554c3 100644 --- a/extension/src/openvic-extension/singletons/MenuSingleton.cpp +++ b/extension/src/openvic-extension/singletons/MenuSingleton.cpp @@ -482,7 +482,7 @@ Dictionary MenuSingleton::get_province_info_from_index(int32_t index) const { ret[province_info_rgo_output_quantity_yesterday_key] = rgo.get_output_quantity_yesterday().to_float(); ret[province_info_rgo_revenue_yesterday_key] = rgo.get_revenue_yesterday().to_float(); ret[province_info_rgo_total_employees_key] = rgo.get_total_employees_count_cache(); - const Pop::pop_size_t max_employee_count = rgo.get_max_employee_count_cache(); + const pop_size_t max_employee_count = rgo.get_max_employee_count_cache(); if (max_employee_count == 0) { ret[province_info_rgo_employment_percentage_key] = 100.0f; } else { diff --git a/extension/src/openvic-extension/singletons/MenuSingleton.hpp b/extension/src/openvic-extension/singletons/MenuSingleton.hpp index 0dcc8ff..169d519 100644 --- a/extension/src/openvic-extension/singletons/MenuSingleton.hpp +++ b/extension/src/openvic-extension/singletons/MenuSingleton.hpp @@ -1,16 +1,26 @@ #pragma once +#include <variant> + #include <godot_cpp/classes/control.hpp> #include <godot_cpp/classes/image.hpp> -#include <openvic-simulation/pop/Pop.hpp> #include <openvic-simulation/types/IndexedMap.hpp> +#include <openvic-simulation/types/PopSize.hpp> #include <openvic-simulation/types/OrderedContainers.hpp> namespace OpenVic { struct CountryInstance; struct State; struct ProvinceInstance; + struct Pop; + struct PopType; + struct Religion; + struct Ideology; + struct Culture; + struct Issue; + struct CountryParty; + struct RebelType; struct ModifierValue; struct RuleSet; @@ -46,7 +56,7 @@ namespace OpenVic { int32_t visible_province_list_entries = 0; struct pop_filter_t { - Pop::pop_size_t count, promotion_demotion_change; + pop_size_t count, promotion_demotion_change; bool selected; }; ordered_map<PopType const*, pop_filter_t> pop_filters; diff --git a/extension/src/openvic-extension/utility/UITools.cpp b/extension/src/openvic-extension/utility/UITools.cpp index 4bd537d..ecb35a8 100644 --- a/extension/src/openvic-extension/utility/UITools.cpp +++ b/extension/src/openvic-extension/utility/UITools.cpp @@ -482,14 +482,18 @@ static bool generate_window(generate_gui_args_t&& args) { GUI::Window const& window = static_cast<GUI::Window const&>(args.element); - // TODO - moveable, fullscreen, dontRender (disable visibility?) + // TODO - moveable, dontRender (disable visibility?) const String window_name = Utilities::std_to_godot_string(window.get_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())); + if (window.get_fullscreen()) { + godot_panel->set_anchors_preset(godot::Control::PRESET_FULL_RECT); + } else { + godot_panel->set_custom_minimum_size(Utilities::to_godot_fvec2(window.get_size())); + } Ref<StyleBoxEmpty> stylebox_empty; stylebox_empty.instantiate(); diff --git a/game/src/Game/GameSession/GameSession.tscn b/game/src/Game/GameSession/GameSession.tscn index 5925f3d..041e9c0 100644 --- a/game/src/Game/GameSession/GameSession.tscn +++ b/game/src/Game/GameSession/GameSession.tscn @@ -1,8 +1,7 @@ -[gd_scene load_steps=21 format=3 uid="uid://bgnupcshe1m7r"] +[gd_scene load_steps=22 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"] -[ext_resource type="PackedScene" uid="uid://g524p8lr574w" path="res://src/Game/GameSession/MapControlPanel/MapControlPanel.tscn" id="3_afh6d"] [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/ModelManager.gd" id="3_qwk4j"] [ext_resource type="Script" path="res://src/Game/GameSession/Topbar.gd" id="4_2kbih"] @@ -19,7 +18,9 @@ [ext_resource type="Script" path="res://src/Game/GameSession/NationManagementScreen/TradeMenu.gd" id="10_mv1r6"] [ext_resource type="Script" path="res://src/Game/GameSession/NationManagementScreen/DiplomacyMenu.gd" id="11_fu7ys"] [ext_resource type="Script" path="res://src/Game/GameSession/NationManagementScreen/MilitaryMenu.gd" id="12_6h6nc"] +[ext_resource type="Script" path="res://src/Game/GameSession/Ledger.gd" id="15_vhb1p"] [ext_resource type="Script" path="res://src/Game/GameSession/Tooltip.gd" id="20_3306e"] +[ext_resource type="Script" path="res://src/Game/GameSession/Menubar.gd" id="20_s1i71"] [node name="GameSession" type="Control" node_paths=PackedStringArray("_model_manager", "_game_session_menu")] editor_description = "SS-102, UI-546" @@ -103,15 +104,15 @@ layout_mode = 1 anchors_preset = 15 script = ExtResource("12_6h6nc") -[node name="MapControlPanel" parent="UICanvasLayer/UI" instance=ExtResource("3_afh6d")] +[node name="Menubar" type="GUINode" parent="UICanvasLayer/UI"] layout_mode = 1 -anchors_preset = -1 -anchor_left = 1.0 -anchor_top = 1.0 -anchor_right = 1.0 -anchor_bottom = 1.0 -grow_horizontal = 0 -grow_vertical = 0 +anchors_preset = 15 +script = ExtResource("20_s1i71") + +[node name="Ledger" type="GUINode" parent="UICanvasLayer/UI"] +layout_mode = 1 +anchors_preset = 15 +script = ExtResource("15_vhb1p") [node name="SearchPanel" type="GUINode" parent="UICanvasLayer/UI" node_paths=PackedStringArray("_map_view")] layout_mode = 1 @@ -163,12 +164,13 @@ anchors_preset = 15 script = ExtResource("20_3306e") [connection signal="detailed_view_changed" from="MapView" to="ModelManager" method="set_visible"] -[connection signal="map_view_camera_changed" from="MapView" to="UICanvasLayer/UI/MapControlPanel" method="_on_map_view_camera_changed"] -[connection signal="game_session_menu_button_pressed" from="UICanvasLayer/UI/MapControlPanel" to="." method="_on_game_session_menu_button_pressed"] -[connection signal="minimap_clicked" from="UICanvasLayer/UI/MapControlPanel" to="MapView" method="_on_minimap_clicked"] -[connection signal="search_button_pressed" from="UICanvasLayer/UI/MapControlPanel" to="UICanvasLayer/UI/SearchPanel" method="toggle_visibility"] -[connection signal="zoom_in_button_pressed" from="UICanvasLayer/UI/MapControlPanel" to="MapView" method="zoom_in"] -[connection signal="zoom_out_button_pressed" from="UICanvasLayer/UI/MapControlPanel" to="MapView" method="zoom_out"] +[connection signal="map_view_camera_changed" from="MapView" to="UICanvasLayer/UI/Menubar" method="_on_map_view_camera_changed"] +[connection signal="game_session_menu_button_pressed" from="UICanvasLayer/UI/Menubar" to="." method="_on_game_session_menu_button_pressed"] +[connection signal="ledger_button_pressed" from="UICanvasLayer/UI/Menubar" to="UICanvasLayer/UI/Ledger" method="toggle_visibility"] +[connection signal="minimap_clicked" from="UICanvasLayer/UI/Menubar" to="MapView" method="_on_minimap_clicked"] +[connection signal="search_button_pressed" from="UICanvasLayer/UI/Menubar" to="UICanvasLayer/UI/SearchPanel" method="toggle_visibility"] +[connection signal="zoom_in_button_pressed" from="UICanvasLayer/UI/Menubar" to="MapView" method="zoom_in"] +[connection signal="zoom_out_button_pressed" from="UICanvasLayer/UI/Menubar" to="MapView" method="zoom_out"] [connection signal="load_button_pressed" from="UICanvasLayer/UI/GameSessionMenu" to="UICanvasLayer/UI/SaveLoadMenu" method="show_for_load"] [connection signal="options_button_pressed" from="UICanvasLayer/UI/GameSessionMenu" to="UICanvasLayer/UI/OptionsMenu" method="show"] [connection signal="save_button_pressed" from="UICanvasLayer/UI/GameSessionMenu" to="UICanvasLayer/UI/SaveLoadMenu" method="show_for_save"] diff --git a/game/src/Game/GameSession/Ledger.gd b/game/src/Game/GameSession/Ledger.gd new file mode 100644 index 0000000..50bde07 --- /dev/null +++ b/game/src/Game/GameSession/Ledger.gd @@ -0,0 +1,84 @@ +extends GUINode + +enum Page { + NATION_RANKING, + NATIONAL_COMPARISON, + POLITICAL_SYSTEMS, + POLITICAL_REFORMS, + SOCIAL_REFORMS, + COUNTRY_POPULATION, + PROVINCES, + PROVINCE_POPULATION, + PROVINCE_PRODUCTION, + FACTORY_PRODUCTION, + PRICE_HISTORY, + NUMBER_OF_PAGES +} +const _page_titles : PackedStringArray = [ + "LEDGER_HEADER_RANK", + "LEDGER_HEADER_COUNTRYCOMPARE", + "LEDGER_HEADER_COUNTRYPARTY", + "LEDGER_HEADER_COUNTRYPOLITICALREFORMS", + "LEDGER_HEADER_COUNTRYSOCIALREFORMS", + "LEDGER_HEADER_COUNTRY_POPS", + "LEDGER_HEADER_PROVINCES", + "LEDGER_HEADER_PROVINCE_POPS", + "LEDGER_HEADER_PROVINCEPRODUCTION", + "LEDGER_HEADER_FACTORYPRODUCTION", + "LEDGER_HEADER_GOODS_PRICEHISTORY" +] + +var _current_page : Page = Page.NATION_RANKING: + get: return _current_page + set(new_page): + _current_page = new_page + while _current_page < 0: + _current_page += Page.NUMBER_OF_PAGES + _current_page %= Page.NUMBER_OF_PAGES + _update_info() + +var _page_title_label : GUILabel +var _page_number_label : GUILabel +# TODO - add variables to store any nodes you'll need to refer in more than one function call + +func _ready(): + MenuSingleton.search_cache_changed.connect(_update_info) + + add_gui_element("v2ledger", "ledger") + + var close_button : GUIIconButton = get_gui_icon_button_from_nodepath(^"./ledger/close") + if close_button: + close_button.pressed.connect(hide) + + var previous_page_button : GUIIconButton = get_gui_icon_button_from_nodepath(^"./ledger/prev") + if previous_page_button: + previous_page_button.pressed.connect(func() -> void: _current_page -= 1) + + var next_page_button : GUIIconButton = get_gui_icon_button_from_nodepath(^"./ledger/next") + if next_page_button: + next_page_button.pressed.connect(func() -> void: _current_page += 1) + + _page_title_label = get_gui_label_from_nodepath(^"./ledger/ledger_header") + _page_number_label = get_gui_label_from_nodepath(^"./ledger/page_number") + + # TODO - get any nodes that need setting up or caching in the variables above + + hide() + +func toggle_visibility() -> void: + if is_visible(): + hide() + else: + show() + _update_info() + +func _update_info() -> void: + if is_visible(): + if _page_title_label: + _page_title_label.set_text(_page_titles[_current_page]) + + if _page_number_label: + # Pages are indexed from 0 in the code, but from 1 in the UI + _page_number_label.set_text(str(_current_page + 1)) + + # TODO - set contents of current ledger page diff --git a/game/src/Game/GameSession/MapControlPanel/MapControlPanel.gd b/game/src/Game/GameSession/MapControlPanel/MapControlPanel.gd deleted file mode 100644 index 61de6ae..0000000 --- a/game/src/Game/GameSession/MapControlPanel/MapControlPanel.gd +++ /dev/null @@ -1,62 +0,0 @@ -extends PanelContainer - -signal game_session_menu_button_pressed -signal search_button_pressed -signal map_view_camera_changed(near_left : Vector2, far_left : Vector2, far_right : Vector2, near_right : Vector2) -signal minimap_clicked(pos_clicked : Vector2) -signal zoom_in_button_pressed -signal zoom_out_button_pressed - -@export var _mapmodes_grid : GridContainer - -var _mapmode_button_group : ButtonGroup - -# REQUIREMENTS: -# * UI-550, UI-552, UI-554, UI-561, UI-562, UI-563 -func _add_mapmode_button(identifier : String) -> void: - var button := Button.new() - button.text = identifier - button.tooltip_text = identifier - button.toggle_mode = true - button.button_group = _mapmode_button_group - button.mouse_filter = MOUSE_FILTER_PASS - button.focus_mode = FOCUS_NONE - _mapmodes_grid.add_child(button) - if _mapmode_button_group.get_pressed_button() == null: - button.button_pressed = true - -func _ready() -> void: - _mapmode_button_group = ButtonGroup.new() - _mapmode_button_group.pressed.connect(_mapmode_pressed) - for index : int in GameSingleton.get_mapmode_count(): - _add_mapmode_button(GameSingleton.get_mapmode_identifier(index)) - -# REQUIREMENTS: -# * UIFUN-10 -func _on_game_session_menu_button_pressed() -> void: - game_session_menu_button_pressed.emit() - -func _on_search_button_pressed() -> void: - search_button_pressed.emit() - -# REQUIREMENTS: -# * SS-76 -# * UIFUN-129, UIFUN-131, UIFUN-133, UIFUN-140, UIFUN-141, UIFUN-142 -func _mapmode_pressed(button : BaseButton) -> void: - GameSingleton.set_mapmode(button.tooltip_text) - -func _on_map_view_camera_changed(near_left : Vector2, far_left : Vector2, far_right : Vector2, near_right : Vector2) -> void: - map_view_camera_changed.emit(near_left, far_left, far_right, near_right) - -func _on_minimap_clicked(pos_clicked : Vector2) -> void: - minimap_clicked.emit(pos_clicked) - -# REQUIREMENTS: -# * UIFUN-269 -func _on_zoom_in_button_pressed() -> void: - zoom_in_button_pressed.emit() - -# REQUIREMENTS: -# * UIFUN-270 -func _on_zoom_out_button_pressed() -> void: - zoom_out_button_pressed.emit() diff --git a/game/src/Game/GameSession/MapControlPanel/MapControlPanel.tscn b/game/src/Game/GameSession/MapControlPanel/MapControlPanel.tscn deleted file mode 100644 index d49cf61..0000000 --- a/game/src/Game/GameSession/MapControlPanel/MapControlPanel.tscn +++ /dev/null @@ -1,113 +0,0 @@ -[gd_scene load_steps=7 format=3 uid="uid://g524p8lr574w"] - -[ext_resource type="Script" path="res://src/Game/GameSession/MapControlPanel/MapControlPanel.gd" id="1_ign64"] -[ext_resource type="Shader" path="res://src/Game/GameSession/MapControlPanel/Minimap.gdshader" id="2_rinsg"] -[ext_resource type="Script" path="res://src/Game/GameSession/MapControlPanel/Minimap.gd" id="3_s4dml"] - -[sub_resource type="ShaderMaterial" id="ShaderMaterial_bhuqb"] -shader = ExtResource("2_rinsg") -shader_parameter/province_shape_subdivisions = null -shader_parameter/selected_index = null - -[sub_resource type="InputEventAction" id="InputEventAction_5nck3"] -action = &"ui_cancel" - -[sub_resource type="Shortcut" id="Shortcut_fc1tk"] -events = [SubResource("InputEventAction_5nck3")] - -[node name="MapControlPanel" type="PanelContainer" node_paths=PackedStringArray("_mapmodes_grid")] -editor_description = "SS-103, UI-548" -mouse_force_pass_scroll_events = false -script = ExtResource("1_ign64") -_mapmodes_grid = NodePath("MapPanelMargin/MapPanelList/MapDisplayList/MapmodesGrid") - -[node name="MapPanelMargin" type="MarginContainer" parent="."] -layout_mode = 2 -theme_override_constants/margin_left = 5 -theme_override_constants/margin_top = 5 -theme_override_constants/margin_right = 5 -theme_override_constants/margin_bottom = 5 - -[node name="MapPanelList" type="HBoxContainer" parent="MapPanelMargin"] -layout_mode = 2 -theme_override_constants/separation = 6 -alignment = 1 - -[node name="MapDisplayList" type="VBoxContainer" parent="MapPanelMargin/MapPanelList"] -layout_mode = 2 -alignment = 1 - -[node name="MapmodesGrid" type="GridContainer" parent="MapPanelMargin/MapPanelList/MapDisplayList"] -editor_description = "UI-750" -layout_mode = 2 -columns = 7 - -[node name="Minimap" type="PanelContainer" parent="MapPanelMargin/MapPanelList/MapDisplayList"] -editor_description = "UI-549" -layout_mode = 2 -size_flags_horizontal = 4 -size_flags_vertical = 4 -mouse_filter = 1 - -[node name="MinimapTexture" type="ColorRect" parent="MapPanelMargin/MapPanelList/MapDisplayList/Minimap"] -editor_description = "UI-751, FS-338" -material = SubResource("ShaderMaterial_bhuqb") -layout_mode = 2 -color = Color(0.921569, 0.835294, 0.701961, 1) - -[node name="ViewportQuad" type="Control" parent="MapPanelMargin/MapPanelList/MapDisplayList/Minimap" node_paths=PackedStringArray("_minimap_texture")] -layout_mode = 2 -mouse_filter = 1 -script = ExtResource("3_s4dml") -_minimap_texture = NodePath("../MinimapTexture") - -[node name="AuxiliaryPanel" type="VBoxContainer" parent="MapPanelMargin/MapPanelList"] -editor_description = "UI-761" -layout_mode = 2 - -[node name="GameSessionMenuButton" type="Button" parent="MapPanelMargin/MapPanelList/AuxiliaryPanel"] -editor_description = "UI-9" -layout_mode = 2 -focus_mode = 0 -mouse_filter = 1 -shortcut = SubResource("Shortcut_fc1tk") -text = "ESC" - -[node name="LedgerButton" type="Button" parent="MapPanelMargin/MapPanelList/AuxiliaryPanel"] -editor_description = "UI-860" -layout_mode = 2 -focus_mode = 0 -mouse_filter = 1 -text = "L" - -[node name="SearchButton" type="Button" parent="MapPanelMargin/MapPanelList/AuxiliaryPanel"] -editor_description = "UI-861" -layout_mode = 2 -focus_mode = 0 -mouse_filter = 1 -text = "F" - -[node name="ZoomButtonsContainer" type="HBoxContainer" parent="MapPanelMargin/MapPanelList/AuxiliaryPanel"] -layout_mode = 2 -alignment = 1 - -[node name="ZoomInButton" type="Button" parent="MapPanelMargin/MapPanelList/AuxiliaryPanel/ZoomButtonsContainer"] -editor_description = "UI-862" -layout_mode = 2 -focus_mode = 0 -mouse_filter = 1 -text = "+" - -[node name="ZoomOutButton" type="Button" parent="MapPanelMargin/MapPanelList/AuxiliaryPanel/ZoomButtonsContainer"] -editor_description = "UI-863" -layout_mode = 2 -focus_mode = 0 -mouse_filter = 1 -text = "-" - -[connection signal="map_view_camera_changed" from="." to="MapPanelMargin/MapPanelList/MapDisplayList/Minimap/ViewportQuad" method="_on_map_view_camera_changed"] -[connection signal="minimap_clicked" from="MapPanelMargin/MapPanelList/MapDisplayList/Minimap/ViewportQuad" to="." method="_on_minimap_clicked"] -[connection signal="pressed" from="MapPanelMargin/MapPanelList/AuxiliaryPanel/GameSessionMenuButton" to="." method="_on_game_session_menu_button_pressed"] -[connection signal="pressed" from="MapPanelMargin/MapPanelList/AuxiliaryPanel/SearchButton" to="." method="_on_search_button_pressed"] -[connection signal="pressed" from="MapPanelMargin/MapPanelList/AuxiliaryPanel/ZoomButtonsContainer/ZoomInButton" to="." method="_on_zoom_in_button_pressed"] -[connection signal="pressed" from="MapPanelMargin/MapPanelList/AuxiliaryPanel/ZoomButtonsContainer/ZoomOutButton" to="." method="_on_zoom_out_button_pressed"] diff --git a/game/src/Game/GameSession/MapControlPanel/Minimap.gd b/game/src/Game/GameSession/MapControlPanel/Minimap.gd deleted file mode 100644 index 7cf1794..0000000 --- a/game/src/Game/GameSession/MapControlPanel/Minimap.gd +++ /dev/null @@ -1,105 +0,0 @@ -extends Control - -signal minimap_clicked(pos_clicked : Vector2) - -const _action_click : StringName = &"map_click" - -@export var _minimap_texture : Control -var _minimap_shader : ShaderMaterial - -var _viewport_points : PackedVector2Array - -func _ready() -> void: - _minimap_texture.custom_minimum_size = Vector2(GameSingleton.get_map_aspect_ratio(), 1.0) * 150 - var minimap_material := _minimap_texture.get_material() - if GameLoader.ShaderManager.set_up_shader(minimap_material, false) != OK: - push_error("Failed to set up minimap shader") - else: - _minimap_shader = minimap_material - GameSingleton.province_selected.connect(_on_province_selected) - -func _on_province_selected(index : int) -> void: - if _minimap_shader != null: - _minimap_shader.set_shader_parameter(GameLoader.ShaderManager.param_selected_index, index) - -# REQUIREMENTS -# * SS-80 -# * UI-752 -func _draw() -> void: - if _viewport_points.size() > 1: - draw_multiline(_viewport_points, Color.WHITE, -1) - -# REQUIREMENTS -# * SS-81 -# * UIFUN-127 -func _gui_input(event : InputEvent) -> void: - if Input.is_action_pressed(_action_click): - var pos_clicked := get_local_mouse_position() / size - Vector2(0.5, 0.5) - if abs(pos_clicked.x) < 0.5 and abs(pos_clicked.y) < 0.5: - minimap_clicked.emit(pos_clicked) - -# Returns the point on the line going through p and q with the specific x coord -func _intersect_x(p : Vector2, q : Vector2, x : float) -> Vector2: - if p.x == q.x: - return Vector2(x, 0.5 * (p.y + q.y)) - var t := (x - q.x) / (p.x - q.x) - return q + t * (p - q) - -# Returns the point on the line going through p and q with the specific y coord -func _intersect_y(p : Vector2, q : Vector2, y : float) -> Vector2: - if p.y == q.y: - return Vector2(0.5 * (p.x + q.x), y) - var t := (y - q.y) / (p.y - q.y) - return q + t * (p - q) - -const _one_x := Vector2(1, 0) - -func _add_line_looped_over_x(left : Vector2, right : Vector2) -> void: - if left.x < 0: - if right.x < 0: - _viewport_points.push_back(left + _one_x) - _viewport_points.push_back(right + _one_x) - else: - var mid_point := _intersect_x(left, right, 0) - _viewport_points.push_back(mid_point) - _viewport_points.push_back(right) - mid_point.x = 1 - _viewport_points.push_back(left + _one_x) - _viewport_points.push_back(mid_point) - elif right.x > 1: - if left.x > 1: - _viewport_points.push_back(left - _one_x) - _viewport_points.push_back(right - _one_x) - else: - var mid_point := _intersect_x(left, right, 1) - _viewport_points.push_back(left) - _viewport_points.push_back(mid_point) - mid_point.x = 0 - _viewport_points.push_back(mid_point) - _viewport_points.push_back(right - _one_x) - else: - _viewport_points.push_back(left) - _viewport_points.push_back(right) - -# This can break if the viewport is rotated too far! -func _on_map_view_camera_changed(near_left : Vector2, far_left : Vector2, far_right : Vector2, near_right : Vector2) -> void: - # Bound far y coords - if far_left.y < 0: - far_left = _intersect_y(near_left, far_left, 0) - if far_right.y < 0: - far_right = _intersect_y(near_right, far_right, 0) - # Bound near y coords - if near_left.y > 1: - near_left = _intersect_y(near_left, far_left, 1) - if near_right.y > 1: - near_right = _intersect_y(near_right, far_right, 1) - - _viewport_points.clear() - _add_line_looped_over_x(near_left, near_right) - _add_line_looped_over_x(far_left, far_right) - _add_line_looped_over_x(far_left, near_left) - _add_line_looped_over_x(near_right, far_right) - - for i : int in _viewport_points.size(): - _viewport_points[i] *= size - queue_redraw() diff --git a/game/src/Game/GameSession/MapControlPanel/Minimap.gdshader b/game/src/Game/GameSession/MapControlPanel/Minimap.gdshader deleted file mode 100644 index 271b809..0000000 --- a/game/src/Game/GameSession/MapControlPanel/Minimap.gdshader +++ /dev/null @@ -1,18 +0,0 @@ -shader_type canvas_item; - -#include "res://src/Game/GameSession/ProvinceIndexSampler.gdshaderinc" - -// Index of the currently selected province -uniform uint selected_index; - -const vec3 land_colour = vec3(0.5); -const vec3 selected_colour = vec3(1.0, 1.0, 0.0); - -void fragment() { - uvec3 data = read_uvec3(UV); - uint index = uvec2_to_uint(data.rg); - float is_land = float(data.b != 0u); - float is_selected = float(index == selected_index); - COLOR.rgb = mix(COLOR.rgb, land_colour, is_land); - COLOR.rgb = mix(COLOR.rgb, selected_colour, is_selected); -} diff --git a/game/src/Game/GameSession/Menubar.gd b/game/src/Game/GameSession/Menubar.gd new file mode 100644 index 0000000..bff1418 --- /dev/null +++ b/game/src/Game/GameSession/Menubar.gd @@ -0,0 +1,224 @@ +extends GUINode + +signal game_session_menu_button_pressed +signal ledger_button_pressed +signal search_button_pressed +signal zoom_in_button_pressed +signal zoom_out_button_pressed +signal minimap_clicked(pos_clicked : Vector2) + +var _mapmode_button_group : ButtonGroup +# We use this instead of the ButtonGroup's get_buttons() as we can add null +# entries for any missing buttons, ensuring each button is at the right index. +var _mapmode_buttons : Array[GUIIconButton] +var _minimap_icon : GUIIcon +var _viewport_points : PackedVector2Array + +# REQUIREMENTS: +# * UI-550, UI-552, UI-554, UI-561, UI-562, UI-563 +func _add_mapmode_button() -> void: + var index : int = _mapmode_buttons.size() + var button : GUIIconButton = get_gui_icon_button_from_nodepath("./menubar/mapmode_%d" % (index + 1)) + if button: + button.tooltip_string = GameSingleton.get_mapmode_localisation_key(index) + button.toggle_mode = true + button.button_group = _mapmode_button_group + button.pressed.connect(_mapmode_pressed.bind(index)) + _mapmode_buttons.push_back(button) + +func _ready() -> void: + add_gui_element("menubar", "menubar") + + hide_nodes([ + ^"./menubar/messagelog_window", # TODO: implement + ^"./menubar/OPENbutton", # not quite sure what this is + ^"./menubar/menubar_plans_toggle", # TODO: implement, v low priority + ^"./menubar/menubar_plans_open", # TODO: implement, v low priority + ^"./menubar/menubar_mail_bg", # TODO: implement + ^"./menubar/menubar_msg_diplo", # TODO: implement + ^"./menubar/menubar_msg_settings", # TODO: implement + ^"./menubar/menubar_msg_combat", # TODO: implement + ^"./menubar/menubar_msg_diplo", # TODO: implement + ^"./menubar/menubar_msg_unit", # TODO: implement + ^"./menubar/menubar_msg_province", # TODO: implement + ^"./menubar/menubar_msg_event", # TODO: implement + ^"./menubar/menubar_msg_other", # TODO: implement + ^"./menubar/chat_window", # TODO: Multiplayer + ]) + + var menubar : Panel = get_panel_from_nodepath(^"./menubar") + if menubar: + menubar.mouse_filter = Control.MOUSE_FILTER_IGNORE + var minimap_bg : GUIIcon = get_gui_icon_from_nodepath(^"./menubar/minimap_bg") + if minimap_bg: + minimap_bg.mouse_filter = Control.MOUSE_FILTER_PASS + var menubar_bg : GUIIcon = get_gui_icon_from_nodepath(^"./menubar/menubar_bg") + if menubar_bg: + menubar_bg.mouse_filter = Control.MOUSE_FILTER_PASS + + # TODO: add keyboard shortcuts (and shortcut tooltips) where vanilla does by default + use key bindings in settings + + var menu_button : GUIIconButton = get_gui_icon_button_from_nodepath(^"./menubar/menu_button") + if menu_button: + menu_button.tooltip_string = "M_MENU_BUTTON" + menu_button.pressed.connect(_on_game_session_menu_button_pressed) + + # TODO: implement ledger + var ledger_button : GUIIconButton = get_gui_icon_button_from_nodepath(^"./menubar/ledger_button") + if ledger_button: + ledger_button.tooltip_string = "M_LEDGER_BUTTON" + ledger_button.pressed.connect(_on_ledger_button_pressed) + + var search_button : GUIIconButton = get_gui_icon_button_from_nodepath(^"./menubar/button_goto") + if search_button: + search_button.tooltip_string = "M_GOTO_BUTTON" + search_button.pressed.connect(_on_search_button_pressed) + + var zoom_in_button : GUIIconButton = get_gui_icon_button_from_nodepath(^"./menubar/map_zoom_in") + if zoom_in_button: + zoom_in_button.pressed.connect(_on_zoom_in_button_pressed) + + var zoom_out_button : GUIIconButton = get_gui_icon_button_from_nodepath(^"./menubar/map_zoom_out") + if zoom_out_button: + zoom_out_button.pressed.connect(_on_zoom_out_button_pressed) + + _minimap_icon = get_gui_icon_from_node(generate_gui_element("menubar", "minimap_pic")) + if _minimap_icon: + _minimap_icon.mouse_filter = Control.MOUSE_FILTER_PASS + _minimap_icon.gui_input.connect(_minimap_gui_input) + _minimap_icon.draw.connect(_minimap_draw) + add_child(_minimap_icon) + + _mapmode_button_group = ButtonGroup.new() + for index : int in GameSingleton.get_mapmode_count(): + _add_mapmode_button() + + GameSingleton.mapmode_changed.connect(_on_mapmode_changed) + + # This will set the mapmode in GameSingleton which in turn updates the buttons so that the right one is pressed + _mapmode_pressed(0) + +# REQUIREMENTS: +# * UIFUN-10 +func _on_game_session_menu_button_pressed() -> void: + game_session_menu_button_pressed.emit() + +func _on_ledger_button_pressed() -> void: + ledger_button_pressed.emit() + +func _on_search_button_pressed() -> void: + search_button_pressed.emit() + +# REQUIREMENTS: +# * SS-76 +# * UIFUN-129, UIFUN-131, UIFUN-133, UIFUN-140, UIFUN-141, UIFUN-142 +func _mapmode_pressed(index : int) -> void: + GameSingleton.set_mapmode(index) + print("Mapmode set to \"%s\" (index: %d, identifier: %s)" % [ + tr(GameSingleton.get_mapmode_localisation_key(index)), index, GameSingleton.get_mapmode_identifier(index) + ]) + +func _on_mapmode_changed(index : int) -> void: + var current_mapmode_button : GUIIconButton = _mapmode_button_group.get_pressed_button() + var new_mapmode_button : GUIIconButton = _mapmode_buttons[index] if 0 <= index and index < _mapmode_buttons.size() else null + + if current_mapmode_button != new_mapmode_button: + if new_mapmode_button: + # This will also automatically unpress current_mapmode_button (if it isn't null) + new_mapmode_button.button_pressed = true + else: + # current_mapmode_button can't be null as it isn't equal to new_mapmode_button which is null + current_mapmode_button.button_pressed = false + +# REQUIREMENTS: +# * UIFUN-269 +func _on_zoom_in_button_pressed() -> void: + zoom_in_button_pressed.emit() + +# REQUIREMENTS: +# * UIFUN-270 +func _on_zoom_out_button_pressed() -> void: + zoom_out_button_pressed.emit() + +# REQUIREMENTS +# * SS-80 +# * UI-752 +func _minimap_draw() -> void: + if _viewport_points.size() > 1: + _minimap_icon.draw_multiline(_viewport_points, Color.WHITE, -1) + +# REQUIREMENTS +# * SS-81 +# * UIFUN-127 +func _minimap_gui_input(_event : InputEvent) -> void: + const _action_click : StringName = &"map_click" + if Input.is_action_pressed(_action_click): + var pos_clicked : Vector2 = _minimap_icon.get_local_mouse_position() / _minimap_icon.size - Vector2(0.5, 0.5) + if abs(pos_clicked.x) < 0.5 and abs(pos_clicked.y) < 0.5: + minimap_clicked.emit(pos_clicked) + +# Returns the point on the line going through p and q with the specific x coord +func _intersect_x(p : Vector2, q : Vector2, x : float) -> Vector2: + if p.x == q.x: + return Vector2(x, 0.5 * (p.y + q.y)) + var t : float = (x - q.x) / (p.x - q.x) + return q + t * (p - q) + +# Returns the point on the line going through p and q with the specific y coord +func _intersect_y(p : Vector2, q : Vector2, y : float) -> Vector2: + if p.y == q.y: + return Vector2(0.5 * (p.x + q.x), y) + var t : float = (y - q.y) / (p.y - q.y) + return q + t * (p - q) + +func _add_line_looped_over_x(left : Vector2, right : Vector2) -> void: + const _one_x : Vector2 = Vector2(1, 0) + if left.x < 0: + if right.x < 0: + _viewport_points.push_back(left + _one_x) + _viewport_points.push_back(right + _one_x) + else: + var mid_point := _intersect_x(left, right, 0) + _viewport_points.push_back(mid_point) + _viewport_points.push_back(right) + mid_point.x = 1 + _viewport_points.push_back(left + _one_x) + _viewport_points.push_back(mid_point) + elif right.x > 1: + if left.x > 1: + _viewport_points.push_back(left - _one_x) + _viewport_points.push_back(right - _one_x) + else: + var mid_point := _intersect_x(left, right, 1) + _viewport_points.push_back(left) + _viewport_points.push_back(mid_point) + mid_point.x = 0 + _viewport_points.push_back(mid_point) + _viewport_points.push_back(right - _one_x) + else: + _viewport_points.push_back(left) + _viewport_points.push_back(right) + +# This can break if the viewport is rotated too far! +func _on_map_view_camera_changed(near_left : Vector2, far_left : Vector2, far_right : Vector2, near_right : Vector2) -> void: + # Bound far y coords + if far_left.y < 0: + far_left = _intersect_y(near_left, far_left, 0) + if far_right.y < 0: + far_right = _intersect_y(near_right, far_right, 0) + # Bound near y coords + if near_left.y > 1: + near_left = _intersect_y(near_left, far_left, 1) + if near_right.y > 1: + near_right = _intersect_y(near_right, far_right, 1) + + _viewport_points.clear() + _add_line_looped_over_x(near_left, near_right) + _add_line_looped_over_x(far_left, far_right) + _add_line_looped_over_x(far_left, near_left) + _add_line_looped_over_x(near_right, far_right) + + if _minimap_icon: + for i : int in _viewport_points.size(): + _viewport_points[i] *= _minimap_icon.size + _minimap_icon.queue_redraw() |