Made Attack dialog use a unit_preview_pane widget

This also adds the necessary changes to said widget to allow single-unit stats display.
It still needs to be expanded somewhat. Right now it contains the minimum required for
the attack dialog.
This commit is contained in:
Charles Dang 2016-08-01 02:17:03 +11:00
parent 4889fd7534
commit 639548a108
6 changed files with 337 additions and 105 deletions

View file

@ -1930,6 +1930,11 @@
max="1"
super="gui/window/resolution/grid"
[/tag]
[key]
name="image_facing"
type="string"
default="right"
[/key]
[/tag]
[tag]
name="vertical_scrollbar"

View file

@ -254,6 +254,150 @@
[/grid]
#enddef
#define _GUI_UNIT_PREVIEW_PANE_UNIT_MINIMAL_LEFT
[grid]
[row]
grow_factor = 1
[column]
horizontal_alignment = "center"
vertical_alignment = "center"
border = "all"
border_size = 5
[image]
id = "type_image"
[/image]
[/column]
[column]
grow_factor = 1
horizontal_alignment = "right"
[grid]
[row]
grow_factor = 1
[column]
horizontal_alignment = "right"
border = "all"
border_size = 5
[label]
id = "type_details"
definition = "default"
text_alignment = "right"
[/label]
[/column]
[/row]
[row]
[column]
horizontal_alignment = "right"
border = "all"
border_size = 5
[button]
id = "type_profile"
definition = "default"
label = _ "Profile"
[/button]
[/column]
[/row]
[/grid]
[/column]
[/row]
[/grid]
#enddef
#define _GUI_UNIT_PREVIEW_PANE_UNIT_MINIMAL_RIGHT
[grid]
[row]
grow_factor = 1
[column]
grow_factor = 1
horizontal_alignment = "left"
[grid]
[row]
grow_factor = 1
[column]
horizontal_alignment = "left"
border = "all"
border_size = 5
[label]
id = "type_details"
definition = "default"
text_alignment = "left"
[/label]
[/column]
[/row]
[row]
grow_factor = 1
[column]
horizontal_alignment = "left"
border = "all"
border_size = 5
[button]
id = "type_profile"
definition = "default"
label = _ "Profile"
[/button]
[/column]
[/row]
[/grid]
[/column]
[column]
horizontal_alignment = "center"
vertical_alignment = "center"
border = "all"
border_size = 5
[image]
id = "type_image"
[/image]
[/column]
[/row]
[/grid]
#enddef
#define _GUI_RESOLUTION DEFINITION_GRID
[resolution]
@ -301,6 +445,22 @@
{_GUI_RESOLUTION ({_GUI_UNIT_PREVIEW_PANE_MINIMAL})}
[/unit_preview_pane_definition]
[unit_preview_pane_definition]
id = "unit_minimal_left"
description = "A more text-based unit preview pane, used in the attack dialog with the sprite to the left."
{_GUI_RESOLUTION ({_GUI_UNIT_PREVIEW_PANE_UNIT_MINIMAL_LEFT})}
[/unit_preview_pane_definition]
[unit_preview_pane_definition]
id = "unit_minimal_right"
description = "A more text-based unit preview pane, used in the attack dialog with the sprite to the right."
{_GUI_RESOLUTION ({_GUI_UNIT_PREVIEW_PANE_UNIT_MINIMAL_RIGHT})}
[/unit_preview_pane_definition]
#undef _GUI_UNIT_PREVIEW_PANE_FULL
#undef _GUI_UNIT_PREVIEW_PANE_MINIMAL
#undef _GUI_UNIT_PREVIEW_PANE_UNIT_MINIMAL_LEFT
#undef _GUI_UNIT_PREVIEW_PANE_UNIT_MINIMAL_RIGHT
#undef _GUI_RESOLUTION

View file

@ -159,7 +159,13 @@
[column]
grow_factor = 1
horizontal_grow = "true"
{_GUI_BIG_ATTACKER_PANEL}
border = "all"
border_size = 5
[unit_preview_pane]
id = "attacker_pane"
definition = "unit_minimal_left"
[/unit_preview_pane]
[/column]
{GUI_VERTICAL_SPACER_LINE}
@ -167,7 +173,14 @@
[column]
grow_factor = 1
horizontal_grow = "true"
{_GUI_BIG_DEFENDER_PANEL}
border = "all"
border_size = 5
[unit_preview_pane]
id = "defender_pane"
definition = "unit_minimal_right"
image_facing = "left"
[/unit_preview_pane]
[/column]
[/row]

View file

@ -28,6 +28,7 @@
#include "gui/widgets/listbox.hpp"
#endif
#include "gui/widgets/settings.hpp"
#include "gui/widgets/unit_preview_pane.hpp"
#include "gui/widgets/window.hpp"
#include "game_config.hpp"
#include "gettext.hpp"
@ -94,82 +95,6 @@ set_label(twindow& window, const std::string& id, const std::string& label)
}
}
static std::string format_stats(const unit& u)
{
const std::string name = "<span size='large'>" + (!u.name().empty() ? u.name() : " ") + "</span>";
std::string traits;
for(const std::string& trait : u.trait_names()) {
traits += (traits.empty() ? "" : ", ") + trait;
}
if (traits.empty()) {
traits = " ";
}
std::stringstream str;
str << name << "\n";
str << "<small>";
str << "<span color='#f5e6c1'>" << u.type_name() << "</span>" << "\n";
str << "Lvl " << u.level() << "\n";
str << u.alignment() << "\n";
str << traits << "\n";
str << font::span_color(u.hp_color())
<< _("HP: ") << u.hitpoints() << "/" << u.max_hitpoints() << "</span>" << "\n";
str << font::span_color(u.xp_color())
<< _("XP: ") << u.experience() << "/" << u.max_experience() << "</span>";
str << "</small>";
return str.str();
}
static std::string get_image_mods(const unit& u)
{
std::string res
= "~RC(" + u.team_color() + ">" + team::get_side_color_index(u.side()) + ")";
if (u.can_recruit()) {
res += "~BLIT(" + unit::leader_crown() + ")";
}
for(const std::string& overlay : u.overlays()) {
res += "~BLIT(" + overlay + ")";
}
return res;
}
static void set_attacker_info(twindow& window, const unit& u)
{
set_label<timage>(window, "attacker_image", u.absolute_image() + get_image_mods(u));
tcontrol& attacker_name =
find_widget<tcontrol>(&window, "attacker_stats", false);
attacker_name.set_use_markup(true);
attacker_name.set_label(format_stats(u));
}
static void set_defender_info(twindow& window, const unit& u)
{
// Ensure the defender image is always facing left
set_label<timage>(window, "defender_image", u.absolute_image() + "~FL(horiz)" + get_image_mods(u));
tcontrol& defender_name =
find_widget<tcontrol>(&window, "defender_stats", false);
defender_name.set_use_markup(true);
defender_name.set_label(format_stats(u));
}
static void set_weapon_info(twindow& window,
const std::vector<battle_context>& weapons,
const int best_weapon)
@ -265,22 +190,15 @@ void tunit_attack::damage_calc_callback(twindow& window)
void tunit_attack::pre_show(twindow& window)
{
connect_signal_mouse_left_click(
find_widget<tbutton>(&window, "attacker_profile", false),
std::bind(&tunit_attack::profile_button_callback, this, std::ref(window),
(*attacker_itor_).type_id()));
connect_signal_mouse_left_click(
find_widget<tbutton>(&window, "defender_profile", false),
std::bind(&tunit_attack::profile_button_callback, this, std::ref(window),
(*defender_itor_).type_id()));
connect_signal_mouse_left_click(
find_widget<tbutton>(&window, "damage_calculation", false),
std::bind(&tunit_attack::damage_calc_callback, this, std::ref(window)));
set_attacker_info(window, *attacker_itor_);
set_defender_info(window, *defender_itor_);
find_widget<tunit_preview_pane>(&window, "attacker_pane", false)
.set_displayed_unit(&(*attacker_itor_));
find_widget<tunit_preview_pane>(&window, "defender_pane", false)
.set_displayed_unit(&(*defender_itor_));
selected_weapon_ = -1;
set_weapon_info(window, weapons_, best_weapon_);

View file

@ -33,6 +33,7 @@
#include "resources.hpp"
#include "team.hpp"
#include "units/types.hpp"
#include "units/unit.hpp"
#include "utils/functional.hpp"
@ -193,6 +194,115 @@ void tunit_preview_pane::set_displayed_type(const unit_type* type)
}
}
void tunit_preview_pane::set_displayed_unit(const unit* unit)
{
// Sets the current type id for the profile button callback to use
current_type_ = unit->type_id();
if(icon_type_) {
std::string mods
= "~RC(" + unit->team_color() + ">" + team::get_side_color_index(unit->side()) + ")";
if(unit->can_recruit()) {
mods += "~BLIT(" + unit::leader_crown() + ")";
}
for(const std::string& overlay : unit->overlays()) {
mods += "~BLIT(" + overlay + ")";
}
// We assume sprites are always drawn facing right
if(image_facing_ == "left") {
mods += "~FL(horiz)";
}
icon_type_->set_label(unit->absolute_image() + mods);
}
if(label_name_) {
label_name_->set_label("<big>" + unit->type_name() + "</big>");
label_name_->set_use_markup(true);
}
if(label_level_) {
utils::string_map symbols;
symbols["lvl"] = std::to_string(unit->level());
std::string l_str = vgettext("Lvl $lvl", symbols);
label_level_->set_label("<b>" + l_str + "</b>");
label_level_->set_use_markup(true);
}
if(icon_race_) {
icon_race_->set_label("icons/unit-groups/race_" + unit->race()->id() + "_30.png");
icon_race_->set_tooltip(unit->race()->name(unit->gender()));
}
if(icon_alignment_) {
const std::string& alignment_name = unit->alignment().to_string();
icon_alignment_->set_label("icons/alignments/alignment_" + alignment_name + "_30.png");
icon_alignment_->set_tooltip(unit_type::alignment_description(
unit->alignment(),
unit->gender()));
}
// For this, we want to display certain info in the details label if the corresponding
// widgets aren't present in the definiton.
if(label_details_) {
std::stringstream str;
str << "<small>";
if(!label_name_) {
const std::string name = "<span size='large'>" + (!unit->name().empty() ? unit->name() : " ") + "</span>";
str << name << "\n";
}
if(!icon_type_) {
str << "<span color='#f5e6c1'>" << unit->type_name() << "</span>" << "\n";
}
if(!label_level_) {
str << "Lvl " << unit->level() << "\n";
}
if(!icon_alignment_) {
str << unit->alignment() << "\n";
}
std::string traits;
for(const std::string& trait : unit->trait_names()) {
traits += (traits.empty() ? "" : ", ") + trait;
}
if(traits.empty()) {
traits = " ";
}
str << traits << "\n";
str << font::span_color(unit->hp_color())
<< _("HP: ") << unit->hitpoints() << "/" << unit->max_hitpoints() << "</span>" << "\n";
str << font::span_color(unit->xp_color())
<< _("XP: ") << unit->experience() << "/" << unit->max_experience() << "</span>";
// TODO: enable
//str << "\n"
// << _("MP: ") << unit->movement_left() << "/" << unit->total_movement();
str << "</small>";
// TODO: add abilty and attack printouts. Currently the only usecase of a unit display
// (the attack dialog) doesn't need these.
label_details_->set_label(str.str());
label_details_->set_use_markup(true);
}
}
void tunit_preview_pane::profile_button_callback()
{
if(get_window()) {
@ -200,6 +310,15 @@ void tunit_preview_pane::profile_button_callback()
}
}
void tunit_preview_pane::set_image_facing(const std::string& facing)
{
if(facing != "left" && facing != "right") {
return;
}
image_facing_ = facing;
}
void tunit_preview_pane::set_active(const bool /*active*/)
{
/* DO NOTHING */
@ -255,6 +374,7 @@ namespace implementation
tbuilder_unit_preview_pane::tbuilder_unit_preview_pane(const config& cfg)
: tbuilder_control(cfg)
, image_facing_(cfg["image_facing"])
{
}
@ -275,6 +395,7 @@ twidget* tbuilder_unit_preview_pane::build() const
widget->init_grid(conf->grid);
widget->finalize_setup();
widget->set_image_facing(image_facing_);
return widget;
}

View file

@ -18,6 +18,7 @@
#include <string>
class unit;
class unit_type;
namespace gui2
@ -40,28 +41,28 @@ class tunit_preview_pane : public tcontainer_
public:
tunit_preview_pane()
: tcontainer_(1)
: tcontainer_(1)
, current_type_("")
, icon_type_()
, icon_race_()
, icon_alignment_()
, label_name_()
, label_level_()
, label_details_()
, button_profile_()
, icon_type_(nullptr)
, icon_race_(nullptr)
, icon_alignment_(nullptr)
, label_name_(nullptr)
, label_level_(nullptr)
, label_details_(nullptr)
, button_profile_(nullptr)
, image_facing_("right")
{
}
/**
* Initializes the interneral sub-widget pointers.
* Should be called when building the window, so the pointers
* are initilized when set_displayed_type() is called.
*/
void finalize_setup();
/** Displays the stats of a specified unit type */
void set_displayed_type(const unit_type* type);
/** Displays the stats of a specific unit */
void set_displayed_unit(const unit* unit);
/** Sets the facing of the unit image */
void set_image_facing(const std::string& facing);
/** Callback for the profile button */
void profile_button_callback();
@ -74,6 +75,14 @@ public:
/** See @ref tcontrol::get_state. */
virtual unsigned get_state() const override;
protected:
/**
* Initializes the interneral sub-widget pointers.
* Should be called when building the window, so the pointers
* are initilized when set_displayed_type() is called.
*/
void finalize_setup();
private:
std::string current_type_;
@ -87,6 +96,8 @@ private:
tbutton* button_profile_;
std::string image_facing_;
enum tstate {
ENABLED
};
@ -121,11 +132,15 @@ namespace implementation
struct tbuilder_unit_preview_pane : public tbuilder_control
{
public:
explicit tbuilder_unit_preview_pane(const config& cfg);
using tbuilder_control::build;
twidget* build() const;
private:
std::string image_facing_;
};
} // namespace implementation