Load Game: display all human-controlled leaders
This also includes a fix for leader images sometimes not being shown in the dialog. If the save_index was deleted or altered at a time other than when creating a save, the image path would be empty in the game load dialog. This ensures the image path is only saved in binary-path independent form if the path isn't empty. In that case, the plain image path from the savefile is saved. Either way, the image path is checked in-dialog, first plain, then as binary-path independent. If both fail, a fallback image is shown.
This commit is contained in:
parent
5497b09321
commit
ca58a6b7c3
3 changed files with 157 additions and 78 deletions
|
@ -26,6 +26,11 @@
|
|||
fixed_width = "true"
|
||||
[/linked_group]
|
||||
|
||||
[linked_group]
|
||||
id = "leader_image"
|
||||
fixed_width = "true"
|
||||
[/linked_group]
|
||||
|
||||
[tooltip]
|
||||
id = "tooltip"
|
||||
[/tooltip]
|
||||
|
@ -84,9 +89,10 @@
|
|||
|
||||
border = "all"
|
||||
border_size = 5
|
||||
horizontal_alignment = "right"
|
||||
vertical_grow = "true"
|
||||
horizontal_grow = "true"
|
||||
|
||||
{GUI_FORCE_WIDGET_MINIMUM_SIZE 200 200 (
|
||||
{GUI_FORCE_WIDGET_MINIMUM_SIZE 250 200 (
|
||||
[minimap]
|
||||
id = "minimap"
|
||||
definition = "no_size"
|
||||
|
@ -137,24 +143,83 @@
|
|||
|
||||
[/row]
|
||||
|
||||
{GUI_HORIZONTAL_SPACER_LINE}
|
||||
|
||||
[row]
|
||||
grow_factor = 1
|
||||
|
||||
[column]
|
||||
grow_factor = 1
|
||||
|
||||
border = "all"
|
||||
border_size = 5
|
||||
horizontal_grow = "true"
|
||||
vertical_grow = "true"
|
||||
|
||||
[image]
|
||||
id = "imgLeader"
|
||||
definition = "default"
|
||||
[/image]
|
||||
border = "all"
|
||||
border_size = 5
|
||||
|
||||
[listbox]
|
||||
id = "leader_list"
|
||||
has_minimum = "false"
|
||||
|
||||
[list_definition]
|
||||
|
||||
[row]
|
||||
|
||||
[column]
|
||||
grow_factor = 1
|
||||
horizontal_grow = "true"
|
||||
|
||||
[toggle_panel]
|
||||
definition = "default"
|
||||
|
||||
[grid]
|
||||
|
||||
[row]
|
||||
|
||||
[column]
|
||||
grow_factor = 0
|
||||
|
||||
border = "all"
|
||||
border_size = 5
|
||||
horizontal_grow = "true"
|
||||
vertical_grow = "true"
|
||||
|
||||
[image]
|
||||
id = "imgLeader"
|
||||
definition = "default"
|
||||
linked_group = "leader_image"
|
||||
[/image]
|
||||
|
||||
[/column]
|
||||
|
||||
[column]
|
||||
grow_factor = 1
|
||||
|
||||
border = "all"
|
||||
border_size = 5
|
||||
horizontal_grow = "true"
|
||||
|
||||
[label]
|
||||
id = "leader_name"
|
||||
definition = "default"
|
||||
[/label]
|
||||
|
||||
[/column]
|
||||
|
||||
[/row]
|
||||
|
||||
[/grid]
|
||||
|
||||
[/toggle_panel]
|
||||
|
||||
[/column]
|
||||
|
||||
[/row]
|
||||
|
||||
[/list_definition]
|
||||
|
||||
[/listbox]
|
||||
|
||||
[/column]
|
||||
|
||||
|
||||
[/row]
|
||||
|
||||
[/grid]
|
||||
|
@ -330,7 +395,7 @@
|
|||
horizontal_grow = "true"
|
||||
|
||||
[grid]
|
||||
|
||||
|
||||
[row]
|
||||
|
||||
[column]
|
||||
|
@ -348,7 +413,7 @@
|
|||
[/toggle_button]
|
||||
|
||||
[/column]
|
||||
|
||||
|
||||
[column]
|
||||
grow_factor = 0
|
||||
horizontal_alignment = "right"
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
|
||||
#include "gui/dialogs/game_load.hpp"
|
||||
|
||||
#include "filesystem.hpp"
|
||||
#include "formula/string_utils.hpp"
|
||||
#include "gettext.hpp"
|
||||
#include "game_config.hpp"
|
||||
|
@ -38,6 +39,7 @@
|
|||
#include "gui/widgets/text_box.hpp"
|
||||
#include "gui/widgets/toggle_button.hpp"
|
||||
#include "gui/widgets/window.hpp"
|
||||
#include "image.hpp"
|
||||
#include "language.hpp"
|
||||
#include "savegame.hpp"
|
||||
#include "serialization/string_utils.hpp"
|
||||
|
@ -170,15 +172,41 @@ void tgame_load::display_savegame(twindow& window)
|
|||
|
||||
const config& summary = game.summary();
|
||||
|
||||
find_widget<timage>(&window, "imgLeader", false)
|
||||
.set_label(summary["leader_image"]);
|
||||
|
||||
find_widget<tminimap>(&window, "minimap", false)
|
||||
.set_map_data(summary["map_data"]);
|
||||
|
||||
find_widget<tlabel>(&window, "lblScenario", false)
|
||||
.set_label(summary["label"]);
|
||||
|
||||
tlistbox& leader_list = find_widget<tlistbox>(&window, "leader_list", false);
|
||||
|
||||
leader_list.clear();
|
||||
|
||||
for(const auto& leader : summary.child_range("leader")) {
|
||||
std::map<std::string, string_map> data;
|
||||
string_map item;
|
||||
|
||||
// First, we evaluate whether the leader image as provided exists.
|
||||
// If not, we try getting a binary-path independent path. If that still doesn't
|
||||
// work, we fallback on unknown-unit.png.
|
||||
std::string leader_image = leader["leader_image"].str();
|
||||
if(!image::exists(leader_image)) {
|
||||
leader_image = filesystem::get_independent_image_path(leader_image);
|
||||
}
|
||||
|
||||
if(leader_image.empty()) {
|
||||
leader_image = "units/unknown-unit.png";
|
||||
}
|
||||
|
||||
item["label"] = leader_image;
|
||||
data.emplace("imgLeader", item);
|
||||
|
||||
item["label"] = leader["leader_name"];
|
||||
data.emplace("leader_name", item);
|
||||
|
||||
leader_list.add_row(data);
|
||||
}
|
||||
|
||||
std::stringstream str;
|
||||
str << game.format_time_local() << "\n";
|
||||
evaluate_summary_string(str, summary);
|
||||
|
|
|
@ -333,13 +333,13 @@ save_info create_save_info::operator()(const std::string& filename) const
|
|||
|
||||
void extract_summary_from_config(config& cfg_save, config& cfg_summary)
|
||||
{
|
||||
const config &cfg_snapshot = cfg_save.child("snapshot");
|
||||
const config& cfg_snapshot = cfg_save.child("snapshot");
|
||||
//Servergenerated replays contain [scenario] and no [replay_start]
|
||||
const config &cfg_replay_start = cfg_save.child("replay_start") ? cfg_save.child("replay_start") : cfg_save.child("scenario") ;
|
||||
const config& cfg_replay_start = cfg_save.child("replay_start") ? cfg_save.child("replay_start") : cfg_save.child("scenario") ;
|
||||
|
||||
const config &cfg_replay = cfg_save.child("replay");
|
||||
const config& cfg_replay = cfg_save.child("replay");
|
||||
const bool has_replay = cfg_replay && !cfg_replay.empty();
|
||||
const bool has_snapshot = cfg_snapshot && cfg_snapshot.child("side");
|
||||
const bool has_snapshot = cfg_snapshot && cfg_snapshot.has_child("side");
|
||||
|
||||
cfg_summary["replay"] = has_replay;
|
||||
cfg_summary["snapshot"] = has_snapshot;
|
||||
|
@ -356,84 +356,70 @@ void extract_summary_from_config(config& cfg_save, config& cfg_summary)
|
|||
cfg_summary["difficulty"] = cfg_save["difficulty"];
|
||||
cfg_summary["random_mode"] = cfg_save["random_mode"];
|
||||
|
||||
|
||||
cfg_summary["campaign"] = cfg_save["campaign"];
|
||||
cfg_summary["version"] = cfg_save["version"];
|
||||
cfg_summary["corrupt"] = "";
|
||||
|
||||
if(has_snapshot) {
|
||||
cfg_summary["turn"] = cfg_snapshot["turn_at"];
|
||||
if (cfg_snapshot["turns"] != "-1") {
|
||||
if(cfg_snapshot["turns"] != "-1") {
|
||||
cfg_summary["turn"] = cfg_summary["turn"].str() + "/" + cfg_snapshot["turns"].str();
|
||||
}
|
||||
}
|
||||
|
||||
// Find the first human leader so we can display their icon in the load menu.
|
||||
|
||||
/** @todo Ideally we should grab all leaders if there's more than 1 human player? */
|
||||
std::string leader;
|
||||
std::string leader_image;
|
||||
std::string leader_image_tc_modifier;
|
||||
|
||||
//for (const config &p : cfg_save.child_range("player"))
|
||||
//{
|
||||
// if (p["canrecruit"].to_bool(false))) {
|
||||
// leader = p["save_id"];
|
||||
// }
|
||||
//}
|
||||
// Find the human leaders so we can display their icons and names in the load menu.
|
||||
config leader_config;
|
||||
|
||||
bool shrouded = false;
|
||||
|
||||
//if (!leader.empty())
|
||||
//{
|
||||
if (const config &snapshot = *(has_snapshot ? &cfg_snapshot : &cfg_replay_start))
|
||||
{
|
||||
for (const config &side : snapshot.child_range("side"))
|
||||
{
|
||||
if (side["controller"] != team::CONTROLLER::enum_to_string(team::CONTROLLER::HUMAN)) {
|
||||
if(const config& snapshot = *(has_snapshot ? &cfg_snapshot : &cfg_replay_start)) {
|
||||
for(const config &side : snapshot.child_range("side")) {
|
||||
std::string leader;
|
||||
std::string leader_image;
|
||||
std::string leader_image_tc_modifier;
|
||||
std::string leader_name;
|
||||
|
||||
if(side["controller"] != team::CONTROLLER::enum_to_string(team::CONTROLLER::HUMAN)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if(side["shroud"].to_bool()) {
|
||||
shrouded = true;
|
||||
}
|
||||
|
||||
for(const config &u : side.child_range("unit")) {
|
||||
if(!u["canrecruit"].to_bool()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (side["shroud"].to_bool()) {
|
||||
shrouded = true;
|
||||
}
|
||||
leader = u["id"].str();
|
||||
leader_name = u["name"].str();
|
||||
leader_image = u["image"].str();
|
||||
leader_image_tc_modifier = "~RC(" + u["flag_rgb"].str() + ">" + u["side"].str() + ")";
|
||||
|
||||
if (side["canrecruit"].to_bool())
|
||||
{
|
||||
leader = side["id"].str();
|
||||
leader_image = side["image"].str();
|
||||
leader_image_tc_modifier = "~RC(magenta>" + side["color"].str() + ")"; // Hardcode magenta
|
||||
break;
|
||||
}
|
||||
|
||||
for (const config &u : side.child_range("unit"))
|
||||
{
|
||||
if (u["canrecruit"].to_bool()) {
|
||||
leader = u["id"].str();
|
||||
leader_image = u["image"].str();
|
||||
if(!u["flag_rgb"].empty()) {
|
||||
leader_image_tc_modifier = "~RC(" + u["flag_rgb"].str() + ">" + u["side"].str() + ")";
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Exit on first human leader
|
||||
break;
|
||||
}
|
||||
|
||||
// We need a binary path-independent path to the leader image here so it can be displayed
|
||||
// for campaign-specific units even when the campaign isn't loaded yet.
|
||||
std::string leader_image_path = filesystem::get_independent_image_path(leader_image);
|
||||
|
||||
// If the image path was found, we append the leader TC modifier. If it's not (such as in
|
||||
// the case where the binary path hasn't been loaded yet, perhaps due to save_index being
|
||||
// deleted), the unaltered image path is used and will be parsed by get_independent_image_path
|
||||
// at runtime.
|
||||
if(!leader_image_path.empty()) {
|
||||
leader_image_path += leader_image_tc_modifier;
|
||||
|
||||
leader_image = leader_image_path;
|
||||
}
|
||||
|
||||
leader_config["leader"] = leader;
|
||||
leader_config["leader_name"] = leader_name;
|
||||
leader_config["leader_image"] = leader_image;
|
||||
|
||||
cfg_summary.add_child("leader", leader_config);
|
||||
}
|
||||
//}
|
||||
|
||||
cfg_summary["leader"] = leader;
|
||||
|
||||
// We need a binary path-independent path to the leader image here
|
||||
// so it can be displayed for campaign-specific units in the dialog
|
||||
// even when the campaign isn't loaded yet.
|
||||
cfg_summary["leader_image"] = filesystem::get_independent_image_path(leader_image);
|
||||
|
||||
// Append the leader image's team coloring
|
||||
if(!cfg_summary["leader_image"].empty()) {
|
||||
cfg_summary["leader_image"] = cfg_summary["leader_image"].str() + leader_image_tc_modifier;
|
||||
}
|
||||
|
||||
if(!shrouded) {
|
||||
|
|
Loading…
Add table
Reference in a new issue