Bring back MP options (patch by lipkab).
This commit is contained in:
parent
311d101fe5
commit
c84e94fe9b
8 changed files with 1029 additions and 15 deletions
|
@ -18946,6 +18946,14 @@
|
|||
RelativePath="..\..\src\mp_game_utils.hpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\src\mp_options.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\src\mp_options.hpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\src\multiplayer.cpp"
|
||||
>
|
||||
|
|
|
@ -769,6 +769,7 @@ set(wesnoth-main_SRC
|
|||
mp_depcheck.cpp
|
||||
mp_game_settings.cpp
|
||||
mp_game_utils.cpp
|
||||
mp_options.cpp
|
||||
multiplayer.cpp
|
||||
multiplayer_configure.cpp
|
||||
multiplayer_connect.cpp
|
||||
|
|
|
@ -437,6 +437,7 @@ wesnoth_sources = Split("""
|
|||
mp_depcheck.cpp
|
||||
mp_game_settings.cpp
|
||||
mp_game_utils.cpp
|
||||
mp_options.cpp
|
||||
multiplayer.cpp
|
||||
multiplayer_configure.cpp
|
||||
multiplayer_connect.cpp
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#include "game_config_manager.hpp"
|
||||
#include "gettext.hpp"
|
||||
#include "log.hpp"
|
||||
#include "mp_options.hpp"
|
||||
#include "replay.hpp"
|
||||
#include "savegame.hpp"
|
||||
#include "tod_manager.hpp"
|
||||
|
@ -81,10 +82,8 @@ config initial_level_config(game_display& disp, const mp_game_settings& params,
|
|||
level.add_child("multiplayer", params.to_config());
|
||||
|
||||
// Convert options to events
|
||||
//FIXME
|
||||
//level.add_child_at("event", mp::options::to_event(
|
||||
// params.options.find_child("multiplayer", "id",
|
||||
// params.mp_scenario)), 0);
|
||||
level.add_child_at("event", options::to_event(params.options.find_child(
|
||||
"multiplayer", "id", params.mp_scenario)), 0);
|
||||
|
||||
level["next_underlying_unit_id"] = 0;
|
||||
n_unit::id_manager::instance().clear();
|
||||
|
@ -126,31 +125,27 @@ config initial_level_config(game_display& disp, const mp_game_settings& params,
|
|||
}
|
||||
else
|
||||
{
|
||||
/*config& cfg =*/
|
||||
level.add_child("era", era_cfg);
|
||||
config& cfg = level.add_child("era", era_cfg);
|
||||
|
||||
const config& custom_side = resources::config_manager->
|
||||
game_config().find_child("multiplayer_side", "id", "Custom");
|
||||
level.child("era").add_child_at("multiplayer_side", custom_side, 0);
|
||||
|
||||
// Convert options to event
|
||||
//FIXME
|
||||
//cfg.add_child_at("event", mp::options::to_event(
|
||||
// params.options.find_child("era", "id", era)), 0);
|
||||
cfg.add_child_at("event", options::to_event(
|
||||
params.options.find_child("era", "id", era)), 0);
|
||||
}
|
||||
|
||||
// Add modifications
|
||||
const std::vector<std::string>& mods = params.active_mods;
|
||||
for (unsigned i = 0; i < mods.size(); i++) {
|
||||
/*config& cfg = */
|
||||
level.add_child("modification",
|
||||
config& cfg = level.add_child("modification",
|
||||
resources::config_manager->
|
||||
game_config().find_child("modification", "id", mods[i]));
|
||||
|
||||
// Convert options to event
|
||||
//FIXME
|
||||
//cfg.add_child_at("event", mp::options::to_event(
|
||||
// params.options.find_child("modification", "id", mods[i])), 0);
|
||||
cfg.add_child_at("event", options::to_event(
|
||||
params.options.find_child("modification", "id", mods[i])), 0);
|
||||
}
|
||||
|
||||
// This will force connecting clients to be using the same version number as us.
|
||||
|
|
602
src/mp_options.cpp
Normal file
602
src/mp_options.cpp
Normal file
|
@ -0,0 +1,602 @@
|
|||
/*
|
||||
Copyright (C) 2012 - 2013 by Boldizsár Lipka <lipkab@zoho.com>
|
||||
Part of the Battle for Wesnoth Project http://www.wesnoth.org/
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY.
|
||||
|
||||
See the COPYING file for more details.
|
||||
*/
|
||||
|
||||
#include "mp_options.hpp"
|
||||
#include "gettext.hpp"
|
||||
#include "gui/auxiliary/find_widget.tpp"
|
||||
#include "gui/auxiliary/window_builder.hpp"
|
||||
#include "gui/dialogs/transient_message.hpp"
|
||||
#include "gui/widgets/button.hpp"
|
||||
#include "gui/widgets/slider.hpp"
|
||||
#include "gui/widgets/text_box.hpp"
|
||||
#include "gui/widgets/toggle_button.hpp"
|
||||
#include <boost/foreach.hpp>
|
||||
#include <boost/bind.hpp>
|
||||
|
||||
static lg::log_domain log_mp_create_options("mp/create/options");
|
||||
#define DBG_MP LOG_STREAM(debug, log_mp_create_options)
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
// helper function
|
||||
config& add_column(config& parent, const std::string& halign = "left",
|
||||
float grow_factor = 0)
|
||||
{
|
||||
config& result = parent.add_child("column");
|
||||
result["horizontal_alignment"] = halign;
|
||||
result["grow_factor"] = grow_factor;
|
||||
result["border"] = "all";
|
||||
result["border_size"] = 5;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
namespace mp
|
||||
{
|
||||
|
||||
namespace options
|
||||
{
|
||||
|
||||
config to_event(const config& cfg)
|
||||
{
|
||||
config result;
|
||||
|
||||
if (!cfg) {
|
||||
return result;
|
||||
}
|
||||
|
||||
result["name"] = "prestart";
|
||||
|
||||
BOOST_FOREACH (const config& c, cfg.child_range("option")) {
|
||||
config ev;
|
||||
ev["name"] = c["id"];
|
||||
ev["value"] = c["value"];
|
||||
result.add_child("set_variable", ev);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void manager::init_info(const config& cfg, const std::string& key)
|
||||
{
|
||||
BOOST_FOREACH (const config& comp, cfg.child_range(key)) {
|
||||
config entry;
|
||||
entry["id"] = comp["id"];
|
||||
entry["name"] = comp["name"];
|
||||
|
||||
if (comp.has_child("options") && comp["allow_new_game"].to_bool(true)) {
|
||||
const config& options = comp.child("options");
|
||||
|
||||
BOOST_FOREACH (const config::any_child& c,
|
||||
options.all_children_range()) {
|
||||
entry.add_child(c.key, c.cfg);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// We need to store components even if they don't have any options in
|
||||
// order to have set_xxx_by_index work properly
|
||||
options_info_.add_child(key, entry);
|
||||
}
|
||||
}
|
||||
|
||||
manager::manager(const config& gamecfg, CVideo& video, const config& values)
|
||||
: options_info_()
|
||||
, values_(values)
|
||||
, video_(video)
|
||||
, era_()
|
||||
, scenario_()
|
||||
, modifications_()
|
||||
{
|
||||
DBG_MP << "Initializing the options manager" << std::endl;
|
||||
init_info(gamecfg, "modification");
|
||||
init_info(gamecfg, "era");
|
||||
init_info(gamecfg, "multiplayer");
|
||||
|
||||
BOOST_FOREACH (const config::any_child& i,
|
||||
options_info_.all_children_range())
|
||||
{
|
||||
BOOST_FOREACH (const config::any_child& j, i.cfg.all_children_range())
|
||||
{
|
||||
if (is_valid_option(j.key, j.cfg)) {
|
||||
config& value = get_value_cfg(j.cfg["id"]);
|
||||
value["value"] = get_stored_value(j.cfg["id"]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void manager::set_values(const config& c)
|
||||
{
|
||||
values_ = c;
|
||||
}
|
||||
|
||||
void manager::set_era(const std::string& era)
|
||||
{
|
||||
era_ = era;
|
||||
}
|
||||
|
||||
void manager::set_era_by_index(int index)
|
||||
{
|
||||
era_ = options_info_.child("era", index)["id"].str();
|
||||
}
|
||||
|
||||
void manager::set_scenario(const std::string& scenario)
|
||||
{
|
||||
scenario_ = scenario;
|
||||
}
|
||||
|
||||
void manager::set_scenario_by_index(int index)
|
||||
{
|
||||
scenario_ = options_info_.child("multiplayer", index - 1)["id"].str();
|
||||
}
|
||||
|
||||
void manager::set_modifications(const std::vector<std::string>& modifications)
|
||||
{
|
||||
modifications_ = modifications;
|
||||
}
|
||||
|
||||
void manager::insert_element(elem_type type, const config& data, int pos)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case SCENARIO:
|
||||
options_info_.add_child_at("multiplayer", data, pos);
|
||||
break;
|
||||
case ERA:
|
||||
options_info_.add_child_at("era", data, pos);
|
||||
break;
|
||||
case MODIFICATION:
|
||||
options_info_.add_child_at("modification", data, pos);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void manager::show_dialog()
|
||||
{
|
||||
DBG_MP << "Building the options dialog" << std::endl;
|
||||
// Constructing the dialog
|
||||
config dialog_cfg;
|
||||
|
||||
dialog_cfg.add_child("resolution");
|
||||
dialog_cfg["definition"] = "default";
|
||||
dialog_cfg["automatic_placement"] = true;
|
||||
dialog_cfg["vertical_placement"] = "center";
|
||||
dialog_cfg["horizontal_placement"] = "center";
|
||||
dialog_cfg.add_child("helptip")["id"] = "tooltip_large";
|
||||
dialog_cfg.add_child("tooltip")["id"] = "tooltip_large";
|
||||
|
||||
config& grid = dialog_cfg.add_child("grid");
|
||||
|
||||
// Adding widgets for available options
|
||||
add_widgets(options_info_.find_child("era", "id", era_), grid);
|
||||
add_widgets(options_info_.find_child("multiplayer", "id", scenario_), grid);
|
||||
|
||||
for (unsigned i = 0; i<modifications_.size(); i++) {
|
||||
add_widgets(
|
||||
options_info_.find_child("modification", "id", modifications_[i]),
|
||||
grid);
|
||||
}
|
||||
|
||||
if (grid.ordered_begin() == grid.ordered_end()) {
|
||||
// No widgets were actually added, we've got nothing to show
|
||||
gui2::show_transient_message(video_, "", _(
|
||||
"None of the selected modifications, era or scenario provide " \
|
||||
"configuration options."));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Dialog buttons
|
||||
config& row = grid.add_child("row");
|
||||
row["grow_factor"] = 0;
|
||||
|
||||
config& column = add_column(row, "", 1);
|
||||
column["horizontal_grow"] = true;
|
||||
|
||||
config& widget_grid = column.add_child("grid");
|
||||
config& widget_row = widget_grid.add_child("row");
|
||||
widget_row["grow_factor"] = 0;
|
||||
|
||||
config& defaults_column = add_column(widget_row, "left", 1);
|
||||
config& ok_column = add_column(widget_row, "right");
|
||||
config& cancel_column = add_column(widget_row);
|
||||
|
||||
config& defaults_button = defaults_column.add_child("button");
|
||||
defaults_button["definition"] = "default";
|
||||
defaults_button["label"] = _("Defaults");
|
||||
defaults_button["id"] = "restore_defaults";
|
||||
|
||||
config& ok_button = ok_column.add_child("button");
|
||||
ok_button["definition"] = "default";
|
||||
ok_button["label"] = _("OK");
|
||||
ok_button["id"] = "ok";
|
||||
|
||||
config& cancel_button = cancel_column.add_child("button");
|
||||
cancel_button["definition"] = "default";
|
||||
cancel_button["label"] = _("Cancel");
|
||||
cancel_button["id"] = "cancel";
|
||||
|
||||
// Building the window
|
||||
gui2::twindow_builder::tresolution resolution(dialog_cfg);
|
||||
gui2::twindow* window = gui2::build(video_, &resolution);
|
||||
|
||||
__tmp_set_checkbox_defaults(window);
|
||||
|
||||
gui2::tbutton* button = gui2::find_widget<gui2::tbutton>
|
||||
(window, "restore_defaults", false, true);
|
||||
|
||||
// Callbacks (well, one callback)
|
||||
button->connect_click_handler(boost::bind(restore_defaults, this, window));
|
||||
|
||||
// Show window
|
||||
DBG_MP << "Showing the dialog" << std::endl;
|
||||
if (window->show() == gui2::twindow::CANCEL) {
|
||||
DBG_MP << "User cancelled changes" << std::endl;
|
||||
delete window;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Saving the results
|
||||
DBG_MP << "User accepted changes, saving values" << std::endl;
|
||||
extract_values("era", era_, window);
|
||||
extract_values("multiplayer", scenario_, window);
|
||||
for (unsigned i = 0; i<modifications_.size(); i++) {
|
||||
extract_values("modification", modifications_[i], window);
|
||||
}
|
||||
|
||||
delete window;
|
||||
}
|
||||
|
||||
void manager::add_widgets(const config& data, config& grid) const
|
||||
{
|
||||
if (!data.has_child("entry") &&
|
||||
!data.has_child("slider") &&
|
||||
!data.has_child("checkbox"))
|
||||
{
|
||||
//Don't display the title if there're no options at all
|
||||
return;
|
||||
}
|
||||
|
||||
{
|
||||
// The title for this section
|
||||
config& row = grid.add_child("row");
|
||||
row["grow_factor"] = 0;
|
||||
config& column = add_column(row, "left", 1);
|
||||
config& caption = column.add_child("label");
|
||||
caption["definition"] = "title";
|
||||
caption["label"] = data["name"];
|
||||
}
|
||||
|
||||
// Adding the widgets
|
||||
BOOST_FOREACH (const config::any_child& c, data.all_children_range()) {
|
||||
if (!is_valid_option(c.key, c.cfg))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
config& row = grid.add_child("row");
|
||||
row["grow_factor"] = 0;
|
||||
config& column = add_column(row, "left", 1);
|
||||
|
||||
if (c.key == "entry") {
|
||||
add_entry(c.cfg, column);
|
||||
} else if (c.key == "slider") {
|
||||
add_slider(c.cfg, column);
|
||||
} else if (c.key == "checkbox") {
|
||||
add_checkbox(c.cfg, column);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void manager::add_entry(const config& data, config& column) const
|
||||
{
|
||||
config& grid = column.add_child("grid");
|
||||
config& row = grid.add_child("row");
|
||||
row["grow_factor"] = 0;
|
||||
|
||||
config& label_column = add_column(row);
|
||||
config& entry_column = add_column(row);
|
||||
|
||||
config& label = label_column.add_child("label");
|
||||
label["definition"] = "default";
|
||||
label["label"] = data["name"];
|
||||
|
||||
config& entry = entry_column.add_child("text_box");
|
||||
entry["id"] = data["id"];
|
||||
entry["definition"] = "default";
|
||||
entry["label"] = get_stored_value(data["id"]);
|
||||
entry["tooltip"] = data["description"];
|
||||
}
|
||||
|
||||
void manager::add_slider(const config& data, config& column) const
|
||||
{
|
||||
config& grid = column.add_child("grid");
|
||||
config& row = grid.add_child("row");
|
||||
row["grow_factor"] = 0;
|
||||
|
||||
config& label_column = add_column(row);
|
||||
config& slider_column = add_column(row);
|
||||
|
||||
config& label = label_column.add_child("label");
|
||||
label["definition"] = "default";
|
||||
label["label"] = data["name"];
|
||||
|
||||
config& slider = slider_column.add_child("slider");
|
||||
slider["id"] = data["id"];
|
||||
slider["definition"] = "default";
|
||||
slider["minimum_value"] = data["min"];
|
||||
slider["maximum_value"] = data["max"];
|
||||
slider["step_size"] = data["step"].to_int() ? data["step"].to_int() : 1;
|
||||
slider["value"] = get_stored_value(data["id"]);
|
||||
slider["tooltip"] = data["description"];
|
||||
}
|
||||
|
||||
void manager::add_checkbox(const config& data, config& column) const
|
||||
{
|
||||
config& grid = column.add_child("grid");
|
||||
config& row = grid.add_child("row");
|
||||
row["grow_factor"] = 0;
|
||||
|
||||
config& box_column = add_column(row);
|
||||
|
||||
config& checkbox = box_column.add_child("toggle_button");
|
||||
checkbox["id"] = data["id"];
|
||||
checkbox["definition"] = "default";
|
||||
checkbox["label"] = data["name"];
|
||||
checkbox["tooltip"] = data["description"];
|
||||
}
|
||||
|
||||
config& manager::get_value_cfg(const std::string& id)
|
||||
{
|
||||
{
|
||||
const config& value_cfg = get_value_cfg_or_empty(id);
|
||||
if (!value_cfg.empty()) {
|
||||
return const_cast<config&>(value_cfg);
|
||||
}
|
||||
}
|
||||
|
||||
config::any_child info = get_option_parent(id);
|
||||
config* parent_cfg;
|
||||
if (!values_.find_child(info.key, "id", info.cfg["id"])) {
|
||||
parent_cfg = &values_.add_child(info.key);
|
||||
(*parent_cfg)["id"] = info.cfg["id"];
|
||||
} else {
|
||||
parent_cfg = &values_.find_child(info.key, "id", info.cfg["id"]);
|
||||
}
|
||||
|
||||
config& value_cfg = parent_cfg->add_child("option");
|
||||
value_cfg["id"] = id;
|
||||
|
||||
return value_cfg;
|
||||
}
|
||||
|
||||
const config& manager::get_value_cfg_or_empty(const std::string& id) const
|
||||
{
|
||||
static const config empty;
|
||||
|
||||
BOOST_FOREACH (const config::any_child& i, values_.all_children_range()) {
|
||||
BOOST_FOREACH (const config& j, i.cfg.child_range("option")) {
|
||||
if (j["id"] == id) {
|
||||
return j;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return empty;
|
||||
}
|
||||
|
||||
config::any_child manager::get_option_parent(const std::string& id) const
|
||||
{
|
||||
static const config empty;
|
||||
static const std::string empty_key = "";
|
||||
static config::any_child not_found(&empty_key, &empty);
|
||||
|
||||
BOOST_FOREACH (const config::any_child& i,
|
||||
options_info_.all_children_range()) {
|
||||
BOOST_FOREACH (const config::any_child& j, i.cfg.all_children_range()) {
|
||||
if (j.cfg["id"] == id) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return not_found;
|
||||
}
|
||||
|
||||
const config& manager::get_option_info_cfg(const std::string& id) const
|
||||
{
|
||||
static const config empty;
|
||||
|
||||
BOOST_FOREACH (const config::any_child& i,
|
||||
options_info_.all_children_range()) {
|
||||
BOOST_FOREACH (const config::any_child& j, i.cfg.all_children_range()) {
|
||||
if (j.cfg["id"] == id) {
|
||||
return j.cfg;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return empty;
|
||||
}
|
||||
|
||||
|
||||
config::attribute_value manager::get_stored_value(const std::string& id) const
|
||||
{
|
||||
const config& valcfg = get_value_cfg_or_empty(id);
|
||||
|
||||
if (!valcfg["value"].empty()) {
|
||||
// There's a saved value for this option
|
||||
return valcfg["value"];
|
||||
}
|
||||
|
||||
// Fall back to the option's default
|
||||
return get_default_value(id);
|
||||
}
|
||||
|
||||
config::attribute_value manager::get_default_value(const std::string& id) const
|
||||
{
|
||||
const config& optinfo = get_option_info_cfg(id);
|
||||
|
||||
return optinfo["default"];
|
||||
}
|
||||
|
||||
int manager::get_slider_value(const std::string& id, gui2::twindow* win) const
|
||||
{
|
||||
gui2::tslider* widget =
|
||||
gui2::find_widget<gui2::tslider>(win, id, false, true);
|
||||
|
||||
return widget->get_value();
|
||||
}
|
||||
|
||||
bool manager::get_checkbox_value
|
||||
(const std::string& id, gui2::twindow* win) const
|
||||
{
|
||||
gui2::ttoggle_button* widget =
|
||||
gui2::find_widget<gui2::ttoggle_button>(win, id, false, true);
|
||||
|
||||
return widget->get_value();
|
||||
}
|
||||
|
||||
std::string manager::get_entry_value(const std::string& id,
|
||||
gui2::twindow* window) const
|
||||
{
|
||||
gui2::ttext_box* widget =
|
||||
gui2::find_widget<gui2::ttext_box>(window, id, false, true);
|
||||
|
||||
return widget->text();
|
||||
}
|
||||
|
||||
void manager::set_slider_value(int val, const std::string& id,
|
||||
gui2::twindow* win) const
|
||||
{
|
||||
gui2::tslider* widget =
|
||||
gui2::find_widget<gui2::tslider>(win, id, false, true);
|
||||
|
||||
widget->set_value(val);
|
||||
}
|
||||
|
||||
void manager::set_checkbox_value(bool val, const std::string& id,
|
||||
gui2::twindow* win) const
|
||||
{
|
||||
gui2::ttoggle_button* widget =
|
||||
gui2::find_widget<gui2::ttoggle_button>(win, id, false, true);
|
||||
|
||||
widget->set_value(val);
|
||||
}
|
||||
|
||||
void manager::set_entry_value(const std::string& val, const std::string& id,
|
||||
gui2::twindow* win) const
|
||||
{
|
||||
gui2::ttext_box* widget =
|
||||
gui2::find_widget<gui2::ttext_box>(win, id, false, true);
|
||||
|
||||
widget->set_value(val);
|
||||
}
|
||||
|
||||
void manager::extract_values(const std::string& key, const std::string& id,
|
||||
gui2::twindow* window)
|
||||
{
|
||||
BOOST_FOREACH (const config::any_child& c,
|
||||
options_info_.find_child(key, "id", id).all_children_range())
|
||||
{
|
||||
if (!is_valid_option(c.key, c.cfg)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
config& out = get_value_cfg(c.cfg["id"].str());
|
||||
|
||||
if (c.key == "entry") {
|
||||
out["value"] = get_entry_value(c.cfg["id"], window);
|
||||
} else if (c.key == "slider") {
|
||||
out["value"] = get_slider_value(c.cfg["id"], window);
|
||||
} else if (c.key == "checkbox") {
|
||||
out["value"] = get_checkbox_value(c.cfg["id"], window);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool manager::is_valid_option(const std::string& key, const config& option)
|
||||
{
|
||||
return (key == "slider" || key == "entry" || key == "checkbox") &&
|
||||
(!option["id"].empty());
|
||||
}
|
||||
|
||||
void manager::restore_defaults(manager* m, gui2::twindow* w)
|
||||
{
|
||||
const config& era = m->options_info_.find_child("era", "id", m->era_);
|
||||
restore_defaults_for_component(era, m, w);
|
||||
|
||||
const config& scen = m->options_info_.find_child("multiplayer", "id",
|
||||
m->scenario_);
|
||||
restore_defaults_for_component(scen, m, w);
|
||||
|
||||
BOOST_FOREACH (const std::string& id, m->modifications_) {
|
||||
const config& mod = m->options_info_.find_child("modification", "id",
|
||||
id);
|
||||
restore_defaults_for_component(mod, m, w);
|
||||
}
|
||||
}
|
||||
|
||||
void manager::restore_defaults_for_component(const config& c, manager* m,
|
||||
gui2::twindow* w)
|
||||
{
|
||||
BOOST_FOREACH (const config::any_child& i, c.all_children_range()) {
|
||||
if (!is_valid_option(i.key, i.cfg)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const std::string id = i.cfg["id"].str();
|
||||
|
||||
if (i.key == "entry") {
|
||||
m->set_entry_value(m->get_default_value(id).str(), id, w);
|
||||
} else if (i.key == "checkbox") {
|
||||
m->set_checkbox_value(m->get_default_value(id).to_bool(), id, w);
|
||||
} else if (i.key == "slider") {
|
||||
m->set_slider_value(m->get_default_value(id).to_int(), id, w);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void manager::__tmp_set_checkbox_defaults(gui2::twindow* window) const
|
||||
{
|
||||
BOOST_FOREACH (const config::any_child& i,
|
||||
options_info_.all_children_range())
|
||||
{
|
||||
BOOST_FOREACH (const config& j, i.cfg.child_range("checkbox"))
|
||||
{
|
||||
if (!is_valid_option("checkbox", j)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
gui2::ttoggle_button* button;
|
||||
button = gui2::find_widget<gui2::ttoggle_button>
|
||||
(window, j["id"].str(), false, false);
|
||||
|
||||
if (button) {
|
||||
button->set_value(get_stored_value(j["id"]).to_bool());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace options
|
||||
|
||||
} // namespace mp
|
||||
|
390
src/mp_options.hpp
Normal file
390
src/mp_options.hpp
Normal file
|
@ -0,0 +1,390 @@
|
|||
/*
|
||||
Copyright (C) 2012 - 2013 by Boldizsár Lipka <lipkab@zoho.com>
|
||||
Part of the Battle for Wesnoth Project http://www.wesnoth.org/
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY.
|
||||
|
||||
See the COPYING file for more details.
|
||||
*/
|
||||
|
||||
#ifndef MP_OPTIONS_HPP_INCLUDED
|
||||
#define MP_OPTIONS_HPP_INCLUDED
|
||||
|
||||
#include <string>
|
||||
#include "config.hpp"
|
||||
#include "video.hpp"
|
||||
#include "gui/widgets/widget.hpp"
|
||||
#include "gui/widgets/window.hpp"
|
||||
|
||||
namespace mp
|
||||
{
|
||||
|
||||
namespace options
|
||||
{
|
||||
|
||||
config to_event(const config& options);
|
||||
|
||||
// TODO: there's an identical enum in mp_depcheck.hpp, maybe we should factor
|
||||
// out?
|
||||
enum elem_type
|
||||
{
|
||||
SCENARIO,
|
||||
ERA,
|
||||
MODIFICATION
|
||||
};
|
||||
|
||||
class manager
|
||||
{
|
||||
public:
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param gamecfg The config object holding all eras, scenarios
|
||||
* and modifications.
|
||||
*
|
||||
* @param video The screen to display the dialog on.
|
||||
*
|
||||
* @param initial_values The initial values for each option.
|
||||
*/
|
||||
manager(const config& gamecfg, CVideo& video, const config& initial_values);
|
||||
|
||||
/**
|
||||
* Set the current values the options. This overrides ALL previously set
|
||||
* values, even if a not all options are provided a new value for.
|
||||
*
|
||||
* @param values The new values for each option.
|
||||
*/
|
||||
void set_values(const config& values);
|
||||
|
||||
/**
|
||||
* Sets the selected era. Whenever show_dialog is called, only
|
||||
* options for the selected era will be displayed.
|
||||
*
|
||||
* @param id The era's id.
|
||||
*/
|
||||
void set_era(const std::string& id);
|
||||
|
||||
/**
|
||||
* Sets the selected era. Whenever show_dialog is called, only
|
||||
* options for the selected era will be displayed.
|
||||
*
|
||||
* @param index The era's index.
|
||||
*/
|
||||
void set_era_by_index(int index);
|
||||
|
||||
/**
|
||||
* Sets the selected scenario. Whenever show_dialog is called, only
|
||||
* options for the selected scenario will be displayed.
|
||||
*
|
||||
* @param id The scenario's id.
|
||||
*/
|
||||
void set_scenario(const std::string& id);
|
||||
|
||||
/**
|
||||
* Sets the selected scenario. Whenever show_dialog is called, only
|
||||
* options for the selected scenario will be displayed.
|
||||
*
|
||||
* @param index The scenario's index.
|
||||
*/
|
||||
void set_scenario_by_index(int index);
|
||||
|
||||
/**
|
||||
* Sets the activated modifications. Whenever show_dialog is called, only
|
||||
* options for the activated modifications will be displayed.
|
||||
*
|
||||
* @param ids The ids of the modifications
|
||||
*/
|
||||
void set_modifications(const std::vector<std::string>& ids);
|
||||
|
||||
/**
|
||||
* Add options information of an era/scenario/modification not yet in the
|
||||
* database.
|
||||
*
|
||||
* @param type The type of the element,
|
||||
*
|
||||
* @param data The config object which holds the
|
||||
* information about the element's options in
|
||||
* an [options] child.
|
||||
*
|
||||
* @param pos The position to insert the element into.
|
||||
*/
|
||||
void insert_element(elem_type type, const config& data, int pos);
|
||||
|
||||
/**
|
||||
* Shows the options dialog and saves the selected values.
|
||||
*/
|
||||
void show_dialog();
|
||||
|
||||
/**
|
||||
* Returns the the values for each option.
|
||||
*
|
||||
* @return A config containing the values.
|
||||
*/
|
||||
const config& get_values() const { return values_; }
|
||||
|
||||
private:
|
||||
/** Stores needed info about each element and their configuration options */
|
||||
config options_info_;
|
||||
|
||||
/** Stores the selected values for each option */
|
||||
config values_;
|
||||
|
||||
/** The screen to display the dialog on */
|
||||
CVideo &video_;
|
||||
|
||||
/** The id of the selected era */
|
||||
std::string era_;
|
||||
|
||||
/** The id of the selected scenario */
|
||||
std::string scenario_;
|
||||
|
||||
/** The ids of the selected modifications */
|
||||
std::vector<std::string> modifications_;
|
||||
|
||||
/**
|
||||
* Adds the necessary information about the specified component
|
||||
* to options_info_.
|
||||
*
|
||||
* @param cfg The component's data.
|
||||
* @param key The component's type.
|
||||
*/
|
||||
void init_info(const config& cfg, const std::string& key);
|
||||
|
||||
/**
|
||||
* Creates a widget layout based on an [options] section.
|
||||
*
|
||||
* @param data The [options] section.
|
||||
* @param grid The grid to create the layout in.
|
||||
*/
|
||||
void add_widgets(const config& data, config& grid) const;
|
||||
|
||||
/**
|
||||
* Creates a slider widget.
|
||||
*
|
||||
* @param data A [slider] config.
|
||||
* @param column The grid cell to add the widget into.
|
||||
*/
|
||||
void add_slider(const config& data, config& column) const;
|
||||
|
||||
/**
|
||||
* Creates a checkbox (toggle button) widget.
|
||||
*
|
||||
* @param data A [checkbox] config.
|
||||
* @param column The grid cell to add the widget into.
|
||||
*/
|
||||
void add_checkbox(const config& data, config& column) const;
|
||||
|
||||
/**
|
||||
* @todo Implement this function (along with a combo box widget, preferably)
|
||||
*
|
||||
* Creates a combo box widget.
|
||||
*
|
||||
* @param data A [combobox] config.
|
||||
* @param column The grid cell to add the widget into.
|
||||
*/
|
||||
void add_combobox(const config& data, config& column) const;
|
||||
|
||||
/**
|
||||
* Creates a text entry widget.
|
||||
*
|
||||
* @param data An [entry] config.
|
||||
* @param column The grid cell to add the widget into.
|
||||
*/
|
||||
void add_entry(const config& data, config& column) const;
|
||||
|
||||
/**
|
||||
* Returns the node which holds the selected value of an option. If that
|
||||
* node is not yet created, the function creates it.
|
||||
*
|
||||
* @param id The id of the option.
|
||||
*
|
||||
* @return A reference to the config which the value
|
||||
* for this option should be written into.
|
||||
*/
|
||||
config& get_value_cfg(const std::string& id);
|
||||
|
||||
/**
|
||||
* Returns the node which holds the selected value of an option. If that
|
||||
* node is not yet created, the function returns an empty config.
|
||||
*
|
||||
* @param id The id of the option.
|
||||
*
|
||||
* @return A reference to the config which the value
|
||||
* for this option should be written into or
|
||||
* an empty config if that doesn't exist.
|
||||
*/
|
||||
const config& get_value_cfg_or_empty(const std::string& id) const;
|
||||
|
||||
/**
|
||||
* Returns the information about an option.
|
||||
*
|
||||
* @param id The id of the option.
|
||||
*
|
||||
* @return The config object which contains the
|
||||
* settings of the option, or an empty config
|
||||
* if the option was not found.
|
||||
*/
|
||||
const config& get_option_info_cfg(const std::string& id) const;
|
||||
|
||||
/**
|
||||
* Finds the parent node of an options.
|
||||
*
|
||||
* @param id The id of the option.
|
||||
*
|
||||
* @return A config::any_child object containing the
|
||||
* key and the data of the parent node, or ""
|
||||
* for the key and an empty config if the
|
||||
* option was not found.
|
||||
*/
|
||||
config::any_child get_option_parent(const std::string& id) const;
|
||||
|
||||
/**
|
||||
* Retrieves the saved value for a certain option, or the default, if
|
||||
* there's no such.
|
||||
*
|
||||
* @param id The id of the option.
|
||||
*
|
||||
* @return The value saved in values_ for this option
|
||||
* or its specified default value if a saved
|
||||
* value can't be found.
|
||||
*/
|
||||
config::attribute_value get_stored_value(const std::string& id) const;
|
||||
|
||||
/**
|
||||
* Retrieves the default value for a certain option.
|
||||
*
|
||||
* @param id The id of the option.
|
||||
*
|
||||
* @return The default value for this option.
|
||||
*/
|
||||
config::attribute_value get_default_value(const std::string& id) const;
|
||||
|
||||
/**
|
||||
* Gets the current value of a slider widget.
|
||||
*
|
||||
* @param id The id of the widget.
|
||||
* @param win The window to find the widget in.
|
||||
*
|
||||
* @return The integer currently set on the slider.
|
||||
*/
|
||||
int get_slider_value(const std::string& id, gui2::twindow* win) const;
|
||||
|
||||
/**
|
||||
* Gets the current value of a checkbox widget.
|
||||
*
|
||||
* @param id The id of the widget.
|
||||
* @param win The window to find the widget in.
|
||||
*
|
||||
* @return True if the box is checked, false if not.
|
||||
*/
|
||||
bool get_checkbox_value(const std::string& id, gui2::twindow* win) const;
|
||||
|
||||
/**
|
||||
* Gets the current value of a text_box widget.
|
||||
*
|
||||
* @param id The id of the widget.
|
||||
* @param win The window to find the widget in.
|
||||
*
|
||||
* @return The text written in the widget.
|
||||
*/
|
||||
std::string get_entry_value(const std::string& id,
|
||||
gui2::twindow* win) const;
|
||||
|
||||
/**
|
||||
* Sets the value of a checkbox widget.
|
||||
*
|
||||
* @param val The new value.
|
||||
* @param id The id of the widget.
|
||||
* @param win The window which the widget is a child of.
|
||||
*/
|
||||
void set_slider_value(int val, const std::string& id,
|
||||
gui2::twindow* win) const;
|
||||
|
||||
/**
|
||||
* Sets the value of a slider widget.
|
||||
*
|
||||
* @param val The new value.
|
||||
* @param id The id of the widget.
|
||||
* @param win The window which the widget is a child of.
|
||||
*/
|
||||
void set_checkbox_value(bool val, const std::string& id,
|
||||
gui2::twindow* win) const;
|
||||
|
||||
/**
|
||||
* Sets the value of a text_box widget.
|
||||
*
|
||||
* @param val The new value.
|
||||
* @param id The id of the widget.
|
||||
* @param win The window which the widget is a child of.
|
||||
*/
|
||||
void set_entry_value(const std::string& val, const std::string& id,
|
||||
gui2::twindow* win) const;
|
||||
|
||||
/**
|
||||
* Writes all the values for the options of a certain component from a
|
||||
* specified window into values_.
|
||||
*
|
||||
* @param key The component's type.
|
||||
* @param id The component's id.
|
||||
* @param window The window.
|
||||
*/
|
||||
void extract_values(const std::string& key, const std::string& id,
|
||||
gui2::twindow* window);
|
||||
|
||||
/**
|
||||
* Decides whether a config is a sane option node or not.
|
||||
* A valid option node:
|
||||
* - Must have an id field.
|
||||
* - Its key must be "slider", "entry" or "checkbox"
|
||||
*
|
||||
* @param key The option's key.
|
||||
* @param option The option's data.
|
||||
*
|
||||
* @return True if the option is valid, false if not.
|
||||
*/
|
||||
static bool is_valid_option(const std::string& key, const config& option);
|
||||
|
||||
/**
|
||||
* Restores every widget's value to its default for a window.
|
||||
*
|
||||
* @param m A pointer to the manager which generated
|
||||
* the window.
|
||||
* @param w A pointer to the window itself.
|
||||
*/
|
||||
static void restore_defaults(manager* m, gui2::twindow* w);
|
||||
|
||||
/**
|
||||
* Finds the widgets representing the options of a certain component in a
|
||||
* window (era, scenario or modification) and sets their value to their
|
||||
* defaults.
|
||||
*
|
||||
* @param comp The config of the component.
|
||||
* @param m A pointer to the manager which generated
|
||||
* the window.
|
||||
* @param w A pointer to the window.
|
||||
*/
|
||||
static void restore_defaults_for_component(const config& comp, manager* m,
|
||||
gui2::twindow* w);
|
||||
|
||||
/**
|
||||
* @todo Implement a way to initialize the checkbox via WML and then
|
||||
* remove this function altogether.
|
||||
*
|
||||
* Sets the default states for all checkbox widgets inside a window. All
|
||||
* required data is fetched from values_ and options_info_.
|
||||
*
|
||||
* @param window The window.
|
||||
*/
|
||||
void __tmp_set_checkbox_defaults(gui2::twindow* window) const;
|
||||
};
|
||||
|
||||
} // namespace options
|
||||
|
||||
} // namespace mp
|
||||
#endif
|
|
@ -95,7 +95,8 @@ configure::configure(game_display& disp, const config &cfg, chat& c, config& gam
|
|||
entry_points_(),
|
||||
show_entry_points_(false),
|
||||
force_use_map_settings_check_(true),
|
||||
parameters_(params)
|
||||
parameters_(params),
|
||||
options_manager_(cfg, disp.video(), preferences::options())
|
||||
{
|
||||
// Build the list of scenarios to play
|
||||
|
||||
|
@ -205,6 +206,10 @@ configure::configure(game_display& disp, const config &cfg, chat& c, config& gam
|
|||
show_entry_points_ = true;
|
||||
}
|
||||
|
||||
options_manager_.set_era(parameters_.mp_era);
|
||||
options_manager_.set_scenario(parameters_.mp_scenario);
|
||||
options_manager_.set_modifications(parameters_.active_mods);
|
||||
|
||||
utils::string_map i18n_symbols;
|
||||
i18n_symbols["login"] = preferences::login();
|
||||
name_entry_.set_text(vgettext("$login|’s game", i18n_symbols));
|
||||
|
@ -286,6 +291,8 @@ const mp_game_settings& configure::get_parameters()
|
|||
parameters_.share_view = vision_combo_.selected() == 0;
|
||||
parameters_.share_maps = vision_combo_.selected() == 1;
|
||||
|
||||
parameters_.options = options_manager_.get_values();
|
||||
|
||||
return parameters_;
|
||||
}
|
||||
|
||||
|
@ -316,6 +323,10 @@ void configure::process_event()
|
|||
, disp_.video());
|
||||
}
|
||||
|
||||
if(options_.pressed()) {
|
||||
options_manager_.show_dialog();
|
||||
}
|
||||
|
||||
if (entry_points_combo_.changed()) {
|
||||
const config& scenario = *entry_points_[entry_points_combo_.selected()];
|
||||
parameters_.scenario_data = scenario;
|
||||
|
@ -577,6 +588,9 @@ void configure::layout_children(const SDL_Rect& rect)
|
|||
countdown_action_bonus_slider_.set_location(xpos, ypos);
|
||||
ypos += countdown_action_bonus_slider_.height() + border_size;
|
||||
|
||||
options_.set_location(xpos, ypos);
|
||||
ypos += options_.height() + border_size;
|
||||
|
||||
if (show_entry_points_) {
|
||||
ypos += border_size;
|
||||
entry_points_label_.set_location(xpos, ypos);
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
#include "widgets/combo.hpp"
|
||||
#include "generators/mapgen.hpp"
|
||||
#include "tooltips.hpp"
|
||||
#include "mp_options.hpp"
|
||||
|
||||
namespace mp {
|
||||
|
||||
|
@ -92,6 +93,8 @@ private:
|
|||
|
||||
bool force_use_map_settings_check_;
|
||||
mp_game_settings parameters_;
|
||||
|
||||
options::manager options_manager_;
|
||||
};
|
||||
|
||||
} // end namespace mp
|
||||
|
|
Loading…
Add table
Reference in a new issue