aboutsummaryrefslogtreecommitdiff
path: root/extension/src/openvic-extension/singletons/MenuSingleton.hpp
blob: 713026c95940d853819233b565e44bb3f0988eaf (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
#pragma once

#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/OrderedContainers.hpp>

namespace OpenVic {
   struct CountryInstance;
   struct State;
   struct ProvinceInstance;
   struct ModifierValue;
   struct RuleSet;

   class MenuSingleton : public godot::Object {
      GDCLASS(MenuSingleton, godot::Object)

      static inline MenuSingleton* singleton = nullptr;

   public:
      struct population_menu_t {
         enum ProvinceListEntry {
            LIST_ENTRY_NONE, LIST_ENTRY_COUNTRY, LIST_ENTRY_STATE, LIST_ENTRY_PROVINCE
         };

         struct country_entry_t {
            CountryInstance const& country;
            bool selected = true;
         };

         struct state_entry_t {
            State const& state;
            bool selected = true, expanded = false;
         };

         struct province_entry_t {
            ProvinceInstance const& province;
            bool selected = true;
         };

         using province_list_entry_t = std::variant<country_entry_t, state_entry_t, province_entry_t>;

         std::vector<province_list_entry_t> province_list_entries;
         int32_t visible_province_list_entries = 0;

         struct pop_filter_t {
            Pop::pop_size_t count, promotion_demotion_change;
            bool selected;
         };
         ordered_map<PopType const*, pop_filter_t> pop_filters;

         static constexpr int32_t DISTRIBUTION_COUNT = 6;
         /* Distributions:
          *  - Workforce (PopType)
          *  - Religion
          *  - Ideology
          *  - Nationality (Culture)
          *  - Issues
          *  - Vote */
         fixed_point_map_t<PopType const*> workforce_distribution;
         fixed_point_map_t<Religion const*> religion_distribution;
         fixed_point_map_t<Ideology const*> ideology_distribution;
         fixed_point_map_t<Culture const*> culture_distribution;
         fixed_point_map_t<Issue const*> issue_distribution;
         fixed_point_map_t<CountryParty const*> vote_distribution;

         enum PopSortKey {
            NONE, SORT_SIZE, SORT_TYPE, SORT_CULTURE, SORT_RELIGION, SORT_LOCATION, SORT_MILITANCY, SORT_CONSCIOUSNESS,
            SORT_IDEOLOGY, SORT_ISSUES, SORT_UNEMPLOYMENT, SORT_CASH, SORT_LIFE_NEEDS, SORT_EVERYDAY_NEEDS,
            SORT_LUXURY_NEEDS, SORT_REBEL_FACTION, SORT_SIZE_CHANGE, SORT_LITERACY, MAX_SORT_KEY
         } sort_key = NONE;
         bool sort_descending = true;
         IndexedMap<PopType, size_t> pop_type_sort_cache;
         IndexedMap<Culture, size_t> culture_sort_cache;
         IndexedMap<Religion, size_t> religion_sort_cache;
         IndexedMap<ProvinceInstance, size_t> province_sort_cache;
         IndexedMap<RebelType, size_t> rebel_type_sort_cache;

         std::vector<Pop const*> pops, filtered_pops;
      };

      struct search_panel_t {
         struct entry_t {
            std::variant<ProvinceInstance const*, State const*, CountryInstance const*> target;
            godot::String display_name, search_name, identifier;
         };
         std::vector<entry_t> entry_cache;
         std::vector<size_t> result_indices;
      };

   private:
      population_menu_t population_menu;
      search_panel_t search_panel;

      /* Emitted when the number of visible province list rows changes (list generated or state entry expanded).*/
      static godot::StringName const& _signal_population_menu_province_list_changed();
      /* Emitted when the state of visible province list rows changes (selection changes). Provides an integer argument
       * which, if not negative, the province list scroll index should be updated to. */
      static godot::StringName const& _signal_population_menu_province_list_selected_changed();
      /* Emitted when the selected/filtered collection of pops changes. */
      static godot::StringName const& _signal_population_menu_pops_changed();
      /* Emitted when the collection of possible search results changes. */
      static godot::StringName const& _signal_search_cache_changed();
      /* Emitted when the current tooltip changes. Arguments: text (godot::String), substitution_dict (godot::Dictionary),
       * position (godot::Vector2). If text is empty then the tooltip will be hidden, otherwise the text will be shown at
       * the given position. */
      static godot::StringName const& _signal_update_tooltip();

      godot::String get_state_name(State const& state) const;
      godot::String get_country_name(CountryInstance const& country) const;
      godot::String get_country_adjective(CountryInstance const& country) const;

      godot::String make_modifier_effects_tooltip(ModifierValue const& modifier) const;
      godot::String make_rules_tooltip(RuleSet const& rules) const;

   protected:
      static void _bind_methods();

   public:
      godot::String get_test_tooltip(int32_t line) const;

      static MenuSingleton* get_singleton();

      /* This should only be called AFTER GameSingleton has been initialised! */
      MenuSingleton();
      ~MenuSingleton();

      static godot::String get_tooltip_separator();
      godot::String get_country_name_from_identifier(godot::String const& country_identifier) const;
      godot::String get_country_adjective_from_identifier(godot::String const& country_identifier) const;

      /* TOOLTIP */
      void show_tooltip(
         godot::String const& text, godot::Dictionary const& substitution_dict, godot::Vector2 const& position
      );
      void show_control_tooltip(
         godot::String const& text, godot::Dictionary const& substitution_dict, godot::Control const* control
      );
      void hide_tooltip();

      /* PROVINCE OVERVIEW PANEL */
      /* Get info to display in Province Overview Panel, packaged in a Dictionary using StringName constants as keys. */
      godot::Dictionary get_province_info_from_index(int32_t index) const;
      int32_t get_province_building_count() const;
      godot::String get_province_building_identifier(int32_t building_index) const;
      godot::Error expand_selected_province_building(int32_t building_index);
      int32_t get_slave_pop_icon_index() const;
      int32_t get_administrative_pop_icon_index() const;
      int32_t get_rgo_owner_pop_icon_index() const;

      /* TOPBAR */
      godot::Dictionary get_topbar_info() const;

      /* TIME/SPEED CONTROL PANEL */
      void set_paused(bool paused);
      void toggle_paused();
      bool is_paused() const;
      void increase_speed();
      void decrease_speed();
      int32_t get_speed() const;
      bool can_increase_speed() const;
      bool can_decrease_speed() const;
      godot::String get_longform_date() const;

      /* POPULATION MENU */
      godot::Error _population_menu_update_provinces();
      int32_t get_population_menu_province_list_row_count() const;
      godot::TypedArray<godot::Dictionary> get_population_menu_province_list_rows(int32_t start, int32_t count) const;
      godot::Error population_menu_select_province_list_entry(int32_t select_index, bool set_scroll_index = false);
      godot::Error population_menu_select_province(int32_t province_index);
      godot::Error population_menu_toggle_expanded(int32_t toggle_index, bool emit_selected_changed = true);

      godot::Error _population_menu_update_pops();
      godot::Error _population_menu_update_filtered_pops();
      using sort_func_t = std::function<bool(Pop const*, Pop const*)>;
      sort_func_t _get_population_menu_sort_func(population_menu_t::PopSortKey sort_key) const;
      godot::Error _population_menu_sort_pops();
      godot::Error population_menu_update_locale_sort_cache();
      godot::Error population_menu_select_sort_key(population_menu_t::PopSortKey sort_key);
      godot::TypedArray<godot::Dictionary> get_population_menu_pop_rows(int32_t start, int32_t count) const;
      int32_t get_population_menu_pop_row_count() const;

      godot::Error _population_menu_generate_pop_filters();
      godot::PackedInt32Array get_population_menu_pop_filter_setup_info();
      godot::TypedArray<godot::Dictionary> get_population_menu_pop_filter_info() const;
      godot::Error population_menu_toggle_pop_filter(int32_t filter_index);
      godot::Error population_menu_select_all_pop_filters();
      godot::Error population_menu_deselect_all_pop_filters();

      godot::PackedStringArray get_population_menu_distribution_setup_info() const;
      /* Array of GFXPieChartTexture::godot_pie_chart_data_t. */
      godot::TypedArray<godot::Array> get_population_menu_distribution_info() const;

      /* Find/Search Panel */
      // TODO - update on country government type change and state creation/destruction
      // (which automatically includes country creation/destruction)
      godot::Error generate_search_cache();
      void update_search_results(godot::String const& text);
      godot::PackedStringArray get_search_result_rows(int32_t start, int32_t count) const;
      int32_t get_search_result_row_count() const;
      godot::Vector2 get_search_result_position(int32_t result_index) const;
   };
}

VARIANT_ENUM_CAST(OpenVic::MenuSingleton::population_menu_t::ProvinceListEntry);
VARIANT_ENUM_CAST(OpenVic::MenuSingleton::population_menu_t::PopSortKey);