Add unit variation selection to the Create Unit dialog
Surprisingly, this involves quite a few API changes to enable the Create Unit command to specify a unit variation id.
This commit is contained in:
parent
c489ffab59
commit
be4b927fd8
8 changed files with 120 additions and 19 deletions
|
@ -201,10 +201,32 @@
|
|||
|
||||
[column]
|
||||
grow_factor = 1
|
||||
horizontal_grow = true
|
||||
horizontal_alignment = "right"
|
||||
[grid]
|
||||
[row]
|
||||
grow_factor=0
|
||||
[column]
|
||||
border = "all"
|
||||
border_size = 5
|
||||
horizontal_alignment = "left"
|
||||
|
||||
[label]
|
||||
definition = "default"
|
||||
label= _ "Variation:"
|
||||
[/label]
|
||||
[/column]
|
||||
|
||||
[column]
|
||||
border = "all"
|
||||
border_size = 5
|
||||
horizontal_alignment = "left"
|
||||
|
||||
[menu_button]
|
||||
id = "variation_box"
|
||||
definition = "default"
|
||||
[/menu_button]
|
||||
[/column]
|
||||
|
||||
[column]
|
||||
border = "all"
|
||||
border_size = 5
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
#include "gui/widgets/image.hpp"
|
||||
#include "gui/widgets/label.hpp"
|
||||
#include "gui/widgets/grid.hpp"
|
||||
#include "gui/widgets/menu_button.hpp"
|
||||
#include "gui/widgets/text_box.hpp"
|
||||
#include "gui/widgets/toggle_button.hpp"
|
||||
#include "gui/widgets/unit_preview_pane.hpp"
|
||||
|
@ -37,6 +38,7 @@
|
|||
#include <boost/dynamic_bitset.hpp>
|
||||
|
||||
static std::string last_chosen_type_id = "";
|
||||
static std::string last_variation = "";
|
||||
static unit_race::GENDER last_gender = unit_race::MALE;
|
||||
|
||||
namespace gui2
|
||||
|
@ -77,6 +79,7 @@ REGISTER_DIALOG(unit_create)
|
|||
unit_create::unit_create()
|
||||
: gender_(last_gender)
|
||||
, choice_(last_chosen_type_id)
|
||||
, variation_(last_variation)
|
||||
, last_words_()
|
||||
{
|
||||
set_restore(true);
|
||||
|
@ -97,6 +100,10 @@ void unit_create::pre_show(window& window)
|
|||
gender_toggle.set_callback_on_value_change(
|
||||
std::bind(&unit_create::gender_toggle_callback, this));
|
||||
|
||||
menu_button& var_box = find_widget<menu_button>(&window, "variation_box", false);
|
||||
|
||||
connect_signal_notify_modified(var_box, std::bind(&unit_create::variation_menu_callback, this));
|
||||
|
||||
listbox& list = find_widget<listbox>(&window, "unit_type_list", false);
|
||||
|
||||
text_box* filter
|
||||
|
@ -175,6 +182,7 @@ void unit_create::post_show(window& window)
|
|||
|
||||
last_chosen_type_id = choice_ = units_[selected_row]->id();
|
||||
last_gender = gender_;
|
||||
last_variation = variation_;
|
||||
}
|
||||
|
||||
void unit_create::update_displayed_type() const
|
||||
|
@ -188,8 +196,17 @@ void unit_create::update_displayed_type() const
|
|||
return;
|
||||
}
|
||||
|
||||
find_widget<unit_preview_pane>(w, "unit_details", false)
|
||||
.set_displayed_type(units_[selected_row]->get_gender_unit_type(gender_));
|
||||
const unit_type* ut = &units_[selected_row]->get_gender_unit_type(gender_);
|
||||
|
||||
if(!variation_.empty()) {
|
||||
const auto& variations = units_[selected_row]->variation_types();
|
||||
auto vi = variations.find(variation_);
|
||||
if(vi != variations.end()) {
|
||||
ut = &vi->second.get_gender_unit_type(gender_);
|
||||
}
|
||||
}
|
||||
|
||||
find_widget<unit_preview_pane>(w, "unit_details", false).set_displayed_type(*ut);
|
||||
}
|
||||
|
||||
void unit_create::list_item_clicked(window& window)
|
||||
|
@ -206,6 +223,45 @@ void unit_create::list_item_clicked(window& window)
|
|||
gender_toggle.set_members_enabled([&](const unit_race::GENDER& gender)->bool {
|
||||
return units_[selected_row]->has_gender_variation(gender);
|
||||
});
|
||||
|
||||
menu_button& var_box = find_widget<menu_button>(&window, "variation_box", false);
|
||||
std::vector<config> var_box_values;
|
||||
var_box_values.emplace_back("label", _("unit_variation^Default"), "variation_id", "");
|
||||
|
||||
const auto& ut = *units_[selected_row];
|
||||
const auto& uvars = ut.variation_types();
|
||||
|
||||
var_box.set_active(!uvars.empty());
|
||||
|
||||
unsigned n = 0, selection = 0;
|
||||
|
||||
for(const auto& pair : uvars) {
|
||||
++n;
|
||||
|
||||
const std::string& uv_id = pair.first;
|
||||
const unit_type& uv = pair.second;
|
||||
|
||||
std::string uv_label;
|
||||
if(!uv.type_name().empty() && uv.type_name() != ut.type_name()) {
|
||||
uv_label = uv.type_name() + " (" + uv_id + ")";
|
||||
} else {
|
||||
uv_label = uv_id;
|
||||
}
|
||||
|
||||
var_box_values.emplace_back("label", uv_label, "variation_id", uv_id);
|
||||
|
||||
if(uv_id == variation_) {
|
||||
selection = n;
|
||||
}
|
||||
}
|
||||
|
||||
// If we didn't find the variation selection again then the new selected
|
||||
// unit type doesn't have that variation id.
|
||||
if(!selection) {
|
||||
variation_.clear();
|
||||
}
|
||||
|
||||
var_box.set_values(var_box_values, selection);
|
||||
}
|
||||
|
||||
void unit_create::filter_text_changed(text_box_base* textbox, const std::string& text)
|
||||
|
@ -262,5 +318,15 @@ void unit_create::gender_toggle_callback()
|
|||
|
||||
update_displayed_type();
|
||||
}
|
||||
|
||||
void unit_create::variation_menu_callback()
|
||||
{
|
||||
window& window = *this->get_window();
|
||||
menu_button& var_box = find_widget<menu_button>(&window, "variation_box", false);
|
||||
variation_ = var_box.get_value_config()["variation_id"].str();
|
||||
|
||||
update_displayed_type();
|
||||
}
|
||||
|
||||
} // namespace dialogs
|
||||
} // namespace gui2
|
||||
|
|
|
@ -27,6 +27,7 @@ class unit_type;
|
|||
namespace gui2
|
||||
{
|
||||
|
||||
class menu_button;
|
||||
class text_box_base;
|
||||
|
||||
namespace dialogs
|
||||
|
@ -55,6 +56,12 @@ public:
|
|||
return gender_;
|
||||
}
|
||||
|
||||
/** Variation choice from the user. */
|
||||
std::string variation() const
|
||||
{
|
||||
return variation_;
|
||||
}
|
||||
|
||||
private:
|
||||
std::vector<const unit_type*> units_;
|
||||
|
||||
|
@ -62,6 +69,8 @@ private:
|
|||
|
||||
std::string choice_;
|
||||
|
||||
std::string variation_;
|
||||
|
||||
std::vector<std::string> last_words_;
|
||||
|
||||
/** Inherited from modal_dialog, implemented by REGISTER_DIALOG. */
|
||||
|
@ -77,6 +86,7 @@ private:
|
|||
void list_item_clicked(window& window);
|
||||
void filter_text_changed(text_box_base* textbox, const std::string& text);
|
||||
void gender_toggle_callback();
|
||||
void variation_menu_callback();
|
||||
|
||||
void update_displayed_type() const;
|
||||
|
||||
|
|
|
@ -689,7 +689,7 @@ unit_map::iterator menu_handler::current_unit()
|
|||
namespace
|
||||
{
|
||||
/// Allows a function to return both a type and a gender.
|
||||
typedef std::pair<const unit_type*, unit_race::GENDER> type_and_gender;
|
||||
typedef std::tuple<const unit_type*, unit_race::GENDER, std::string> type_gender_variation;
|
||||
|
||||
/**
|
||||
* Allows the user to select a type of unit, using GUI2.
|
||||
|
@ -698,7 +698,7 @@ typedef std::pair<const unit_type*, unit_race::GENDER> type_and_gender;
|
|||
* @returns the selected type and gender. If this is canceled, the
|
||||
* returned type is nullptr.
|
||||
*/
|
||||
type_and_gender choose_unit()
|
||||
type_gender_variation choose_unit()
|
||||
{
|
||||
//
|
||||
// The unit creation dialog makes sure unit types
|
||||
|
@ -708,14 +708,14 @@ type_and_gender choose_unit()
|
|||
create_dlg.show();
|
||||
|
||||
if(create_dlg.no_choice()) {
|
||||
return type_and_gender(nullptr, unit_race::NUM_GENDERS);
|
||||
return type_gender_variation(nullptr, unit_race::NUM_GENDERS, "");
|
||||
}
|
||||
|
||||
const std::string& ut_id = create_dlg.choice();
|
||||
const unit_type* utp = unit_types.find(ut_id);
|
||||
if(!utp) {
|
||||
ERR_NG << "Create unit dialog returned nonexistent or unusable unit_type id '" << ut_id << "'." << std::endl;
|
||||
return type_and_gender(static_cast<const unit_type*>(nullptr), unit_race::NUM_GENDERS);
|
||||
return type_gender_variation(static_cast<const unit_type*>(nullptr), unit_race::NUM_GENDERS, "");
|
||||
}
|
||||
const unit_type& ut = *utp;
|
||||
|
||||
|
@ -727,7 +727,7 @@ type_and_gender choose_unit()
|
|||
gender = ut.genders().front();
|
||||
}
|
||||
|
||||
return type_and_gender(utp, gender);
|
||||
return type_gender_variation(utp, gender, create_dlg.variation());
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -739,7 +739,8 @@ void create_and_place(game_display&,
|
|||
unit_map&,
|
||||
const map_location& loc,
|
||||
const unit_type& u_type,
|
||||
unit_race::GENDER gender = unit_race::NUM_GENDERS)
|
||||
unit_race::GENDER gender = unit_race::NUM_GENDERS,
|
||||
const std::string& variation = "")
|
||||
{
|
||||
synced_context::run_and_throw("debug_create_unit",
|
||||
config {
|
||||
|
@ -747,6 +748,7 @@ void create_and_place(game_display&,
|
|||
"y", loc.wml_y(),
|
||||
"type", u_type.id(),
|
||||
"gender", gender_string(gender),
|
||||
"variation", variation,
|
||||
}
|
||||
);
|
||||
}
|
||||
|
@ -764,10 +766,10 @@ void menu_handler::create_unit(mouse_handler& mousehandler)
|
|||
assert(gui_ != nullptr);
|
||||
|
||||
// Let the user select the kind of unit to create.
|
||||
type_and_gender selection = choose_unit();
|
||||
if(selection.first != nullptr) {
|
||||
type_gender_variation selection = choose_unit();
|
||||
if(std::get<0>(selection) != nullptr) {
|
||||
// Make it so.
|
||||
create_and_place(*gui_, map(), units(), destination, *selection.first, selection.second);
|
||||
create_and_place(*gui_, map(), units(), destination, *std::get<0>(selection), std::get<1>(selection), std::get<2>(selection));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -536,6 +536,7 @@ SYNCED_COMMAND_HANDLER_FUNCTION(debug_create_unit, child, use_undo, /*show*/, e
|
|||
debug_notification(N_("A unit was created using debug mode during $player’s turn"));
|
||||
map_location loc(child);
|
||||
resources::whiteboard->on_kill_unit();
|
||||
const std::string& variation = child["variation"].str();
|
||||
const unit_race::GENDER gender = string_gender(child["gender"], unit_race::NUM_GENDERS);
|
||||
const unit_type *u_type = unit_types.find(child["type"]);
|
||||
if (!u_type) {
|
||||
|
@ -547,7 +548,7 @@ SYNCED_COMMAND_HANDLER_FUNCTION(debug_create_unit, child, use_undo, /*show*/, e
|
|||
? resources::controller->current_side() : 1;
|
||||
|
||||
// Create the unit.
|
||||
unit_ptr created = unit::create(*u_type, side_num, true, gender);
|
||||
unit_ptr created = unit::create(*u_type, side_num, true, gender, variation);
|
||||
created->new_turn();
|
||||
|
||||
unit_map::unit_iterator unit_it;
|
||||
|
|
|
@ -308,7 +308,7 @@ private:
|
|||
std::string debug_id_; /// A suffix for id_, used when logging messages.
|
||||
std::string parent_id_; /// The id of the top ancestor of this unit_type.
|
||||
/// from [base_unit]
|
||||
std::string base_unit_id_;
|
||||
std::string base_unit_id_;
|
||||
t_string type_name_;
|
||||
t_string description_;
|
||||
std::vector<t_string> special_notes_;
|
||||
|
|
|
@ -725,11 +725,11 @@ void unit::clear_status_caches()
|
|||
units_with_cache.clear();
|
||||
}
|
||||
|
||||
void unit::init(const unit_type& u_type, int side, bool real_unit, unit_race::GENDER gender)
|
||||
void unit::init(const unit_type& u_type, int side, bool real_unit, unit_race::GENDER gender, const std::string& variation)
|
||||
{
|
||||
type_ = &u_type;
|
||||
race_ = &unit_race::null_race;
|
||||
variation_ = type_->default_variation();
|
||||
variation_ = variation.empty() ? type_->default_variation() : variation;
|
||||
side_ = side;
|
||||
gender_ = gender != unit_race::NUM_GENDERS ? gender : generate_gender(u_type, real_unit);
|
||||
facing_ = static_cast<map_location::DIRECTION>(randomness::rng::default_instance().get_random_int(0, map_location::NDIRECTIONS-1));
|
||||
|
|
|
@ -140,7 +140,7 @@ public:
|
|||
private:
|
||||
void init(const config& cfg, bool use_traits = false, const vconfig* vcfg = nullptr);
|
||||
|
||||
void init(const unit_type& t, int side, bool real_unit, unit_race::GENDER gender = unit_race::NUM_GENDERS);
|
||||
void init(const unit_type& t, int side, bool real_unit, unit_race::GENDER gender = unit_race::NUM_GENDERS, const std::string& variation = "");
|
||||
|
||||
// Copy constructor
|
||||
unit(const unit& u);
|
||||
|
@ -194,10 +194,10 @@ public:
|
|||
*
|
||||
* Only real_unit-s should have random traits, name and gender (to prevent OOS caused by RNG calls)
|
||||
*/
|
||||
static unit_ptr create(const unit_type& t, int side, bool real_unit, unit_race::GENDER gender = unit_race::NUM_GENDERS)
|
||||
static unit_ptr create(const unit_type& t, int side, bool real_unit, unit_race::GENDER gender = unit_race::NUM_GENDERS, const std::string& variation = "")
|
||||
{
|
||||
unit_ptr res(new unit());
|
||||
res->init(t, side, real_unit, gender);
|
||||
res->init(t, side, real_unit, gender, variation);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue