diff --git a/src/about.cpp b/src/about.cpp index ebb44f70979a..a4c415e7fe9f 100644 --- a/src/about.cpp +++ b/src/about.cpp @@ -15,6 +15,7 @@ #include "about.hpp" #include "config.hpp" +#include "gettext.hpp" #include "serialization/string_utils.hpp" #include @@ -25,77 +26,124 @@ */ namespace about { +namespace +{ +credits_data parsed_credits_data; +std::map> images_campaigns; +std::vector images_general; -static config about_list; -static std::map> images; -static std::vector images_default; +void gather_images(const config& from, std::vector& to) +{ + const auto& im = utils::parenthetical_split(from["images"], ','); + if(!im.empty()) { + to.insert(to.end(), im.begin(), im.end()); + } +} + +} // end anon namespace -const config& get_about_config() +credits_group::credits_group(const config& cfg, bool is_campaign_credits) + : sections() + , id() + , header() { - return about_list; + if(is_campaign_credits) { + id = cfg["id"].str(); + header = cfg["name"].t_str(); + } + + sections.reserve(cfg.child_count("about")); + + for(const config& about : cfg.child_range("about")) { + if(!about.has_child("entry")) { + continue; + } + + sections.emplace_back(about); + + if(is_campaign_credits) { + gather_images(about, images_campaigns[id]); + } else { + gather_images(about, images_general); + } + } + + if(cfg["sort"].to_bool(false)) { + std::sort(sections.begin(), sections.end()); + } } -std::vector get_background_images(const std::string& campaign) +credits_group::about_group::about_group(const config& cfg) + : names() + , title(cfg["title"].t_str()) { - if(!campaign.empty() && !images[campaign].empty()){ - return images[campaign]; + names.reserve(cfg.child_count("entry")); + + for(const config& entry : cfg.child_range("entry")) { + names.push_back(entry["name"].str()); } +} - return images_default; +bool credits_group::about_group::operator<(const about_group& o) +{ + return translation::compare(title.str(), o.title.str()) < 0; } -static void gather_images(const config& from, std::vector& to) +const credits_data& get_credits_data() { - const auto& im = utils::parenthetical_split(from["images"], ','); - if(!im.empty()) { - to.insert(to.end(), im.begin(), im.end()); + return parsed_credits_data; +} + +std::vector get_background_images(const std::string& campaign) +{ + if(!campaign.empty() && !images_campaigns[campaign].empty()){ + return images_campaigns[campaign]; } + + return images_general; } -void set_about(const config &cfg) +void set_about(const config& cfg) { - about_list.clear(); + parsed_credits_data.clear(); + + // TODO: should we reserve space in parsed_credits_data here? - images.clear(); - images_default.clear(); + images_campaigns.clear(); + images_general.clear(); + // + // Parse all [credits_group] tags + // for(const config& group : cfg.child_range("credits_group")) { - if(!group.has_child("about")) { - continue; - } - about_list.add_child("credits_group", group); - gather_images(group, images_default); - for(const config& about : group.child_range("about")) { - gather_images(about, images_default); + if(group.has_child("about")) { + parsed_credits_data.emplace_back(group, false); + + // Not in the credits_group since we don't want to inadvertently + // pick up images from campaigns. + gather_images(group, images_general); } } + // + // Parse all toplevel [about] tags. + // config misc; for(const config& about : cfg.child_range("about")) { misc.add_child("about", about); - gather_images(about, images_default); } + if(!misc.empty()) { - about_list.add_child("credits_group", std::move(misc)); + parsed_credits_data.emplace_back(misc, false); } + // + // Parse all campaign [about] tags. + // for(const config& campaign : cfg.child_range("campaign")) { - if(!campaign.has_child("about")) { - continue; + if(campaign.has_child("about")) { + parsed_credits_data.emplace_back(campaign, true); } - - const std::string& id = campaign["id"]; - - config temp; - temp["title"] = campaign["name"]; - temp["id"] = id; - - for(const config& about : campaign.child_range("about")) { - temp.add_child("about", about); - gather_images(about, images[id]); - } - - about_list.add_child("credits_group", std::move(temp)); } } diff --git a/src/about.hpp b/src/about.hpp index c064d343e1f2..b6d4dc1f8393 100644 --- a/src/about.hpp +++ b/src/about.hpp @@ -14,18 +14,48 @@ #pragma once -class config; +#include "tstring.hpp" #include #include +class config; + namespace about { +struct credits_group +{ + struct about_group + { + explicit about_group(const config& cfg); + + /** Contributor names. */ + std::vector names; + + /** The section title. */ + t_string title; + + bool operator<(const about_group& o); + }; + + credits_group(const config& cfg, bool is_campaign_credits); + + /** The group's sub-groups. Corresponds to each [about] tag .*/ + std::vector sections; + + /** Optional group ID. Currently only used for identifying campaigns. */ + std::string id; + + /** Optional group tite. Currently only used for identifying campaigns. */ + t_string header; +}; + +using credits_data = std::vector; /** * General getter methods for the credits config and image lists by campaign id */ -const config& get_about_config(); +const credits_data& get_credits_data(); std::vector get_background_images(const std::string& campaign); diff --git a/src/gui/dialogs/end_credits.cpp b/src/gui/dialogs/end_credits.cpp index f600a31b24ea..01a58007fd60 100644 --- a/src/gui/dialogs/end_credits.cpp +++ b/src/gui/dialogs/end_credits.cpp @@ -47,19 +47,6 @@ end_credits::end_credits(const std::string& campaign) { } -static void parse_about_tag(const config& cfg, std::stringstream& ss) -{ - if(!cfg.has_child("entry")) { - return; - } - - ss << "\n" << "" << cfg["title"] << "" << "\n"; - - for(const auto& entry : cfg.child_range("entry")) { - ss << entry["name"] << "\n"; - } -} - void end_credits::pre_show(window& window) { window.set_callback_next_draw([this]() @@ -75,28 +62,19 @@ void end_credits::pre_show(window& window) std::stringstream ss; std::stringstream focus_ss; - const config& credits_config = about::get_about_config(); - - for(const auto& group : credits_config.child_range("credits_group")) { - std::stringstream& group_stream = (group["id"] == focus_on_) ? focus_ss : ss; - + for(const about::credits_group& group : about::get_credits_data()) { + std::stringstream& group_stream = (group.id == focus_on_) ? focus_ss : ss; group_stream << "\n"; - if(group.has_attribute("title")) { - group_stream << "" << group["title"] << "" << "\n"; + + if(!group.header.empty()) { + group_stream << "" << group.header << "" << "\n"; } - if(group["sort"].to_bool(false)) { - auto sections = group.child_range("about"); - std::vector sorted(sections.begin(), sections.end()); - std::sort(sorted.begin(), sorted.end(), [](const config& entry1, const config& entry2) { - return translation::compare(entry1["title"].str(), entry2["title"].str()) < 0; - }); - for(const auto& about : sorted) { - parse_about_tag(about, group_stream); - } - } else { - for(const auto& about : group.child_range("about")) { - parse_about_tag(about, group_stream); + for(const about::credits_group::about_group& about : group.sections) { + group_stream << "\n" << "" << about.title << "" << "\n"; + + for(const std::string& entry : about.names) { + group_stream << entry << "\n"; } } }