aboutsummaryrefslogtreecommitdiff
path: root/extension/src/openvic-extension/singletons
diff options
context:
space:
mode:
author hop311 <hop3114@gmail.com>2024-07-30 01:02:35 +0200
committer hop311 <hop3114@gmail.com>2024-07-30 01:07:56 +0200
commit70f3c3cf6f9c1563d95ffb8c25bf8cd2bb7a1ad0 (patch)
tree5f96f7520816721a058bef8e59929c961d4c7ef2 /extension/src/openvic-extension/singletons
parentbf4d061b06374cd696f1f1644548f4d7af86f5ec (diff)
Search panel + text edit box UI generationsearch-panel
Diffstat (limited to 'extension/src/openvic-extension/singletons')
-rw-r--r--extension/src/openvic-extension/singletons/GameSingleton.cpp2
-rw-r--r--extension/src/openvic-extension/singletons/GameSingleton.hpp2
-rw-r--r--extension/src/openvic-extension/singletons/MenuSingleton.cpp186
-rw-r--r--extension/src/openvic-extension/singletons/MenuSingleton.hpp23
-rw-r--r--extension/src/openvic-extension/singletons/ModelSingleton.cpp4
-rw-r--r--extension/src/openvic-extension/singletons/PopulationMenu.cpp2
6 files changed, 212 insertions, 7 deletions
diff --git a/extension/src/openvic-extension/singletons/GameSingleton.cpp b/extension/src/openvic-extension/singletons/GameSingleton.cpp
index c1a811e..33d70da 100644
--- a/extension/src/openvic-extension/singletons/GameSingleton.cpp
+++ b/extension/src/openvic-extension/singletons/GameSingleton.cpp
@@ -170,7 +170,7 @@ float GameSingleton::get_map_aspect_ratio() const {
return static_cast<float>(get_map_width()) / static_cast<float>(get_map_height());
}
-Vector2 GameSingleton::map_position_to_world_coords(fvec2_t const& position) const {
+Vector2 GameSingleton::normalise_map_position(fvec2_t const& position) const {
return Utilities::to_godot_fvec2(position) / get_map_dims();
}
diff --git a/extension/src/openvic-extension/singletons/GameSingleton.hpp b/extension/src/openvic-extension/singletons/GameSingleton.hpp
index b29e588..e7f12bd 100644
--- a/extension/src/openvic-extension/singletons/GameSingleton.hpp
+++ b/extension/src/openvic-extension/singletons/GameSingleton.hpp
@@ -86,7 +86,7 @@ namespace OpenVic {
int32_t get_map_height() const;
godot::Vector2i get_map_dims() const;
float get_map_aspect_ratio() const;
- godot::Vector2 map_position_to_world_coords(fvec2_t const& position) const;
+ godot::Vector2 normalise_map_position(fvec2_t const& position) const;
/* The cosmetic terrain textures stored in a Texture2DArray. */
godot::Ref<godot::Texture2DArray> get_terrain_texture() const;
diff --git a/extension/src/openvic-extension/singletons/MenuSingleton.cpp b/extension/src/openvic-extension/singletons/MenuSingleton.cpp
index 1c3b6ec..885915c 100644
--- a/extension/src/openvic-extension/singletons/MenuSingleton.cpp
+++ b/extension/src/openvic-extension/singletons/MenuSingleton.cpp
@@ -28,6 +28,10 @@ StringName const& MenuSingleton::_signal_population_menu_pops_changed() {
static const StringName signal_population_menu_pops_changed = "population_menu_pops_changed";
return signal_population_menu_pops_changed;
}
+StringName const& MenuSingleton::_signal_search_cache_changed() {
+ static const StringName signal_search_cache_changed = "search_cache_changed";
+ return signal_search_cache_changed;
+}
String MenuSingleton::get_state_name(State const& state) const {
StateSet const& state_set = state.get_state_set();
@@ -59,14 +63,47 @@ String MenuSingleton::get_state_name(State const& state) const {
if (owned && split) {
// COUNTRY STATE/CAPITAL
- return tr(std_view_to_godot_string(StringUtils::append_string_views(state.get_owner()->get_identifier(), "_ADJ")))
- + " " + name;
+ return get_country_adjective(*state.get_owner()) + " " + name;
}
// STATE/CAPITAL
return name;
}
+String MenuSingleton::get_country_name(CountryInstance const& country) const {
+ if (country.get_government_type() != nullptr && !country.get_government_type()->get_identifier().empty()) {
+ const String government_name_key = std_to_godot_string(StringUtils::append_string_views(
+ country.get_identifier(), "_", country.get_government_type()->get_identifier()
+ ));
+
+ String government_name = tr(government_name_key);
+
+ if (government_name != government_name_key) {
+ return government_name;
+ }
+ }
+
+ return tr(std_view_to_godot_string(country.get_identifier()));
+}
+
+String MenuSingleton::get_country_adjective(CountryInstance const& country) const {
+ static constexpr std::string_view adjective = "_ADJ";
+
+ if (country.get_government_type() != nullptr && !country.get_government_type()->get_identifier().empty()) {
+ const String government_adjective_key = std_to_godot_string(StringUtils::append_string_views(
+ country.get_identifier(), "_", country.get_government_type()->get_identifier(), adjective
+ ));
+
+ String government_adjective = tr(government_adjective_key);
+
+ if (government_adjective != government_adjective_key) {
+ return government_adjective;
+ }
+ }
+
+ return tr(std_to_godot_string(StringUtils::append_string_views(country.get_identifier(), adjective)));
+}
+
void MenuSingleton::_bind_methods() {
/* PROVINCE OVERVIEW PANEL */
OV_BIND_METHOD(MenuSingleton::get_province_info_from_index, { "index" });
@@ -142,6 +179,15 @@ void MenuSingleton::_bind_methods() {
BIND_ENUM_CONSTANT(SORT_REBEL_FACTION);
BIND_ENUM_CONSTANT(SORT_SIZE_CHANGE);
BIND_ENUM_CONSTANT(SORT_LITERACY);
+
+ /* Find/Search Panel */
+ OV_BIND_METHOD(MenuSingleton::generate_search_cache);
+ OV_BIND_METHOD(MenuSingleton::update_search_results, { "text" });
+ OV_BIND_METHOD(MenuSingleton::get_search_result_rows, { "start", "count" });
+ OV_BIND_METHOD(MenuSingleton::get_search_result_row_count);
+ OV_BIND_METHOD(MenuSingleton::get_search_result_position, { "result_index" });
+
+ ADD_SIGNAL(MethodInfo(_signal_search_cache_changed()));
}
MenuSingleton* MenuSingleton::get_singleton() {
@@ -442,3 +488,139 @@ String MenuSingleton::get_longform_date() const {
return Utilities::date_to_formatted_string(instance_manager->get_today());
}
+
+Error MenuSingleton::generate_search_cache() {
+ GameSingleton const* game_singleton = GameSingleton::get_singleton();
+ ERR_FAIL_NULL_V(game_singleton, FAILED);
+ InstanceManager const* instance_manager = game_singleton->get_instance_manager();
+ ERR_FAIL_NULL_V(instance_manager, FAILED);
+
+ search_panel.entry_cache.clear();
+
+ std::vector<ProvinceInstance> const& provinces = instance_manager->get_map_instance().get_province_instances();
+ std::vector<StateSet> const& state_sets = instance_manager->get_map_instance().get_state_manager().get_state_sets();
+ std::vector<CountryInstance> const& countries = instance_manager->get_country_instance_manager().get_country_instances();
+
+ // TODO - reserve actual state count rather than state set count (maybe use a vector of pointers to all states?)
+ search_panel.entry_cache.reserve(provinces.size() + state_sets.size() + countries.size());
+
+ for (ProvinceInstance const& province : provinces) {
+ String identifier = std_view_to_godot_string(province.get_identifier());
+ String display_name = tr(GUINode::format_province_name(identifier));
+ String search_name = display_name.to_lower();
+
+ search_panel.entry_cache.push_back({
+ &province, std::move(display_name), std::move(search_name), identifier.to_lower()
+ });
+ }
+
+ for (StateSet const& state_set : state_sets) {
+ for (State const& state : state_set.get_states()) {
+ String display_name = get_state_name(state);
+ String search_name = display_name.to_lower();
+
+ search_panel.entry_cache.push_back({
+ // TODO - include state identifier? (region and/or split?)
+ &state, std::move(display_name), std::move(search_name), {}
+ });
+ }
+ }
+
+ for (CountryInstance const& country : countries) {
+ // TODO - replace with a proper "exists" check
+ if (country.get_capital() != nullptr) {
+ String display_name = get_country_name(country);
+ String search_name = display_name.to_lower();
+
+ search_panel.entry_cache.push_back({
+ &country, std::move(display_name), std::move(search_name),
+ std_view_to_godot_string(country.get_identifier()).to_lower()
+ });
+ }
+ }
+
+ std::sort(search_panel.entry_cache.begin(), search_panel.entry_cache.end(), [](auto const& a, auto const& b) -> bool {
+ return a.search_name < b.search_name;
+ });
+
+ emit_signal(_signal_search_cache_changed());
+
+ return OK;
+}
+
+void MenuSingleton::update_search_results(godot::String const& text) {
+ // Sanatise input
+ const String search_text = text.strip_edges().to_lower();
+
+ search_panel.result_indices.clear();
+
+ if (!search_text.is_empty()) {
+ // Search through cache
+ for (size_t idx = 0; idx < search_panel.entry_cache.size(); ++idx) {
+ search_panel_t::entry_t const& entry = search_panel.entry_cache[idx];
+
+ if (entry.search_name.begins_with(search_text) || entry.identifier == search_text) {
+ search_panel.result_indices.push_back(idx);
+ }
+ }
+ }
+}
+
+PackedStringArray MenuSingleton::get_search_result_rows(int32_t start, int32_t count) const {
+ if (search_panel.result_indices.empty()) {
+ return {};
+ }
+
+ ERR_FAIL_INDEX_V_MSG(
+ start, search_panel.result_indices.size(), {},
+ vformat("Invalid start for search panel result rows: %d", start)
+ );
+ ERR_FAIL_COND_V_MSG(count <= 0, {}, vformat("Invalid count for search panel result rows: %d", count));
+
+ if (start + count > search_panel.result_indices.size()) {
+ UtilityFunctions::push_warning(
+ "Requested search result rows beyond the end of the result indices (", start, " + ", count, " > ",
+ static_cast<int64_t>(search_panel.result_indices.size()), "), limiting to ",
+ static_cast<int64_t>(search_panel.result_indices.size() - start), " rows."
+ );
+ count = search_panel.result_indices.size() - start;
+ }
+
+ PackedStringArray results;
+ results.resize(count);
+
+ for (size_t idx = 0; idx < count; ++idx) {
+ results[idx] = search_panel.entry_cache[search_panel.result_indices[start + idx]].display_name;
+ }
+
+ return results;
+}
+
+int32_t MenuSingleton::get_search_result_row_count() const {
+ return search_panel.result_indices.size();
+}
+
+Vector2 MenuSingleton::get_search_result_position(int32_t result_index) const {
+ ERR_FAIL_INDEX_V(result_index, search_panel.result_indices.size(), {});
+
+ GameSingleton const* game_singleton = GameSingleton::get_singleton();
+ ERR_FAIL_NULL_V(game_singleton, {});
+
+ struct entry_visitor_t {
+ fvec2_t operator()(ProvinceInstance const* province) {
+ return province->get_province_definition().get_centre();
+ }
+
+ fvec2_t operator()(State const* state) {
+ return (*this)(state->get_capital());
+ }
+
+ fvec2_t operator()(CountryInstance const* country) {
+ return (*this)(country->get_capital());
+ }
+ } entry_visitor;
+
+ return game_singleton->normalise_map_position(
+ std::visit(entry_visitor, search_panel.entry_cache[search_panel.result_indices[result_index]].target)
+ );
+}
diff --git a/extension/src/openvic-extension/singletons/MenuSingleton.hpp b/extension/src/openvic-extension/singletons/MenuSingleton.hpp
index 54891bc..190e3ea 100644
--- a/extension/src/openvic-extension/singletons/MenuSingleton.hpp
+++ b/extension/src/openvic-extension/singletons/MenuSingleton.hpp
@@ -73,8 +73,18 @@ namespace OpenVic {
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();
@@ -83,8 +93,12 @@ namespace OpenVic {
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();
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;
protected:
static void _bind_methods();
@@ -145,6 +159,15 @@ namespace OpenVic {
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;
};
}
diff --git a/extension/src/openvic-extension/singletons/ModelSingleton.cpp b/extension/src/openvic-extension/singletons/ModelSingleton.cpp
index 5fb9cf8..0e90a00 100644
--- a/extension/src/openvic-extension/singletons/ModelSingleton.cpp
+++ b/extension/src/openvic-extension/singletons/ModelSingleton.cpp
@@ -295,7 +295,7 @@ bool ModelSingleton::add_unit_dict(
}
dict[position_key] =
- game_singleton->map_position_to_world_coords(unit.get_position()->get_province_definition().get_unit_position());
+ game_singleton->normalise_map_position(unit.get_position()->get_province_definition().get_unit_position());
if (display_unit_type->get_unit_category() != UnitType::unit_category_t::INFANTRY) {
dict[rotation_key] = -0.25f * std::numbers::pi_v<float>;
@@ -433,7 +433,7 @@ bool ModelSingleton::add_building_dict(
dict[model_key] = make_model_dict(*actor);
- dict[position_key] = game_singleton->map_position_to_world_coords(
+ dict[position_key] = game_singleton->normalise_map_position(
position_ptr != nullptr ? *position_ptr : province_definition.get_centre()
);
diff --git a/extension/src/openvic-extension/singletons/PopulationMenu.cpp b/extension/src/openvic-extension/singletons/PopulationMenu.cpp
index df5b6b1..65987ad 100644
--- a/extension/src/openvic-extension/singletons/PopulationMenu.cpp
+++ b/extension/src/openvic-extension/singletons/PopulationMenu.cpp
@@ -110,7 +110,7 @@ TypedArray<Dictionary> MenuSingleton::get_population_menu_province_list_rows(int
country_dict[type_key] = population_menu_t::LIST_ENTRY_COUNTRY;
country_dict[index_key] = index;
- country_dict[name_key] = std_view_to_godot_string(country_entry.country.get_identifier());
+ country_dict[name_key] = menu_singleton.get_country_name(country_entry.country);
country_dict[size_key] = country_entry.country.get_total_population();
country_dict[change_key] = 0;
country_dict[selected_key] = country_entry.selected;