> Un nu de Weddervörhersaag: Een bannig dichter Hagel vun Vörslagens ;)

:D

> How do you like the one I implemented now?

Almost awesome. :) 

Some nits though:

The tooltips for the lists hide the line were the soldier’s strength is shown.

If you could change the values to the ones in the diff-comments and add the
space it would look perfect.

See the screenshot:

https://fosuta.org/pics/attack3.png

And don't forget to remove or comment out this line in fieldaction.cc:

static const char* const pic_attack = "images/wui/buildings/menu_attack.png";

Diff comments:

> 
> === modified file 'src/wui/attack_box.cc'
> --- src/wui/attack_box.cc     2019-02-23 11:00:49 +0000
> +++ src/wui/attack_box.cc     2019-05-10 15:14:32 +0000
> @@ -128,48 +180,225 @@
>  void AttackBox::init() {
>       assert(node_coordinates_);
>  
> -     uint32_t max_attackers = get_max_attackers();
> -
> -     UI::Box& linebox = *new UI::Box(this, 0, 0, UI::Box::Horizontal);
> -     add(&linebox);
> -     add_text(linebox, _("Soldiers:"));
> -     linebox.add_space(8);
> -
> -     less_soldiers_ =
> -        add_button(linebox, "0", &AttackBox::send_less_soldiers, _("Send 
> less soldiers"));
> +     std::vector<Widelands::Soldier*> all_attackers = get_max_attackers();
> +     const size_t max_attackers = all_attackers.size();
> +
> +     UI::Box& mainbox = *new UI::Box(this, 0, 0, UI::Box::Vertical);
> +     add(&mainbox);
> +
> +     UI::Box& linebox = *new UI::Box(&mainbox, 0, 0, UI::Box::Horizontal);
> +     mainbox.add(&linebox);
> +
> +     less_soldiers_ = add_button(linebox, "0", 
> &AttackBox::send_less_soldiers,
> +                     _("Send less soldiers. Hold down Ctrl to send no 
> soldiers"));
>  
>       //  Spliter of soldiers
>       UI::Box& columnbox = *new UI::Box(&linebox, 0, 0, UI::Box::Vertical);
>       linebox.add(&columnbox);
>  
> -     const std::string attack_string =
> -        (boost::format(_("%1% / %2%")) % (max_attackers > 0 ? 1 : 0) % 
> max_attackers).str();
> -
> -     soldiers_text_.reset(
> -        &add_text(columnbox, attack_string, UI::Align::kCenter, 
> UI_FONT_SIZE_ULTRASMALL));
> +     soldiers_text_.reset(&add_text(columnbox, slider_heading(max_attackers 
> > 0 ? 1 : 0, max_attackers),
> +                     UI::Align::kCenter, UI_FONT_SIZE_ULTRASMALL));
>  
>       soldiers_slider_ = add_slider(
> -        columnbox, 100, 10, 0, max_attackers, max_attackers > 0 ? 1 : 0, 
> _("Number of soldiers"));
> -
> -     
> soldiers_slider_->changed.connect(boost::bind(&AttackBox::update_attack, 
> this));
> -     more_soldiers_ = add_button(linebox, std::to_string(max_attackers),
> -                                 &AttackBox::send_more_soldiers, _("Send 
> more soldiers"));
> +        columnbox, 250, 20, 0, max_attackers, max_attackers > 0 ? 1 : 0, 
> _("Number of soldiers"));

columnbox, 242, 20, 0, max_attackers, max_attackers > 0 ? 1 : 0, _("Number of 
soldiers"));

> +     soldiers_slider_->changed.connect([this]() { update_attack(false); });
> +
> +     more_soldiers_ = add_button(linebox, std::to_string(max_attackers), 
> &AttackBox::send_more_soldiers,
> +                     _("Send more soldiers. Hold down Ctrl to send as many 
> soldiers as possible"));
> +

+ linebox.add_space(8);

> +     attack_button_.reset(new UI::Button(&linebox, "attack", 8, 8, 34, 34, 
> UI::ButtonStyle::kWuiPrimary,
> +                     
> g_gr->images().get("images/wui/buildings/menu_attack.png"), _("Start 
> attack")));
> +     linebox.add(attack_button_.get());
> +
> +     boost::format tooltip_format("%s<br><p><font size=%d 
> bold=0>%s<br>%s</font></p>");
> +     remaining_soldiers_.reset(new ListOfSoldiers(&mainbox, this, 0, 0, 30, 
> 30,
> +                     (tooltip_format
> +                     % _("Add this soldier to the list of attackers") %
> +                     UI_FONT_SIZE_MESSAGE
> +                     % _("Hold down Ctrl to add all soldiers to the list")
> +                     % _("Hold down Shift to add all soldiers up to the one 
> you're pointing at"))
> +                     .str()));
> +     attacking_soldiers_.reset(new ListOfSoldiers(&mainbox, this, 0, 0, 30, 
> 30,
> +                     (tooltip_format
> +                     % _("Remove this soldier from the list of attackers") %
> +                     UI_FONT_SIZE_MESSAGE
> +                     % _("Hold down Ctrl to remove all soldiers from the 
> list")
> +                     % _("Hold down Shift to remove all soldiers up to the 
> one you're pointing at"))
> +                     .str()));
> +     attacking_soldiers_->set_complement(remaining_soldiers_.get());
> +     remaining_soldiers_->set_complement(attacking_soldiers_.get());
> +     for (const auto& s : all_attackers) {
> +             remaining_soldiers_->add(s);
> +     }
> +
> +     add_text(mainbox, _("Attackers:"));
> +     mainbox.add(attacking_soldiers_.get(), UI::Box::Resizing::kFullSize);
> +     add_text(mainbox, _("Not attacking:"));
> +     mainbox.add(remaining_soldiers_.get(), UI::Box::Resizing::kFullSize);
> +
> +     current_soldier_stats_.reset(new UI::Textarea(&mainbox, "", 
> UI::Align::kCenter));
> +     mainbox.add(current_soldier_stats_.get(), UI::Box::Resizing::kFullSize, 
> UI::Align::kCenter);
>  
>       soldiers_slider_->set_enabled(max_attackers > 0);
>       more_soldiers_->set_enabled(max_attackers > 0);
> -     less_soldiers_->set_enabled(max_attackers > 0);
>  }
>  
>  void AttackBox::send_less_soldiers() {
>       assert(soldiers_slider_.get());
> -     soldiers_slider_->set_value(soldiers_slider_->get_value() - 1);
> +     soldiers_slider_->set_value((SDL_GetModState() & KMOD_CTRL) ? 0 : 
> soldiers_slider_->get_value() - 1);
>  }
>  
>  void AttackBox::send_more_soldiers() {
> -     soldiers_slider_->set_value(soldiers_slider_->get_value() + 1);
> -}
> -
> -uint32_t AttackBox::soldiers() const {
> -     assert(soldiers_slider_.get());
> -     return soldiers_slider_->get_value();
> -}
> +     soldiers_slider_->set_value((SDL_GetModState() & KMOD_CTRL) ? 
> soldiers_slider_->get_max_value() :
> +                     soldiers_slider_->get_value() + 1);
> +}
> +
> +size_t AttackBox::count_soldiers() const {
> +     return attacking_soldiers_->count_soldiers();
> +}
> +
> +std::vector<Widelands::Serial> AttackBox::soldiers() const {
> +     std::vector<Widelands::Serial> result;
> +     for (const auto& s : attacking_soldiers_->get_soldiers()) {
> +             result.push_back(s->serial());
> +     }
> +     return result;
> +}
> +
> +constexpr int kSoldierIconWidth = 30;

constexpr int kSoldierIconWidth = 32;

> +constexpr int kSoldierIconHeight = 29;

constexpr int kSoldierIconHeight = 30;

> +
> +AttackBox::ListOfSoldiers::ListOfSoldiers(UI::Panel* const parent,
> +                AttackBox* parent_box,
> +                int32_t const x,
> +                int32_t const y,
> +                int const w,
> +                int const h,
> +               const std::string& tooltip,
> +               bool restrict_rows)
> +   : UI::Panel(parent, x, y, w, h, tooltip),
> +     restricted_row_number_(restrict_rows),
> +     attack_box_(parent_box) {
> +     update_desired_size();
> +}
> +
> +bool AttackBox::ListOfSoldiers::handle_mousepress(uint8_t btn, int32_t x, 
> int32_t y) {
> +     if (btn != SDL_BUTTON_LEFT || !other_) {
> +             return UI::Panel::handle_mousepress(btn, x, y);
> +     }
> +     if (SDL_GetModState() & KMOD_CTRL) {
> +             for (const auto& s : get_soldiers()) {
> +                     remove(s);
> +                     other_->add(s);
> +             }
> +     } else {
> +             const Widelands::Soldier* soldier = soldier_at(x, y);
> +             if (!soldier) {
> +                     return UI::Panel::handle_mousepress(btn, x, y);
> +             }
> +             if (SDL_GetModState() & KMOD_SHIFT) {
> +                     for (const auto& s : get_soldiers()) {
> +                             remove(s);
> +                             other_->add(s);
> +                             if (s == soldier) {
> +                                     break;
> +                             }
> +                     }
> +             } else {
> +                     remove(soldier);
> +                     other_->add(soldier);
> +             }
> +     }
> +     attack_box_->update_attack(true);
> +     return true;
> +}
> +
> +void AttackBox::ListOfSoldiers::handle_mousein(bool) {
> +     attack_box_->set_soldier_info_text();
> +}
> +
> +bool AttackBox::ListOfSoldiers::handle_mousemove(uint8_t, int32_t x, int32_t 
> y, int32_t, int32_t) {
> +     if (const Widelands::Soldier* soldier = soldier_at(x, y)) {
> +             attack_box_->set_soldier_info_text(
> +                             (boost::format(_("HP: %1$u/%2$u  AT: %3$u/%4$u  
> DE: %5$u/%6$u  EV: %7$u/%8$u")) %
> +                             soldier->get_health_level() % 
> soldier->descr().get_max_health_level() %
> +                             soldier->get_attack_level() % 
> soldier->descr().get_max_attack_level() %
> +                             soldier->get_defense_level() % 
> soldier->descr().get_max_defense_level() %
> +                             soldier->get_evade_level() % 
> soldier->descr().get_max_evade_level())
> +                             .str());
> +     } else {
> +             attack_box_->set_soldier_info_text();
> +     }
> +     return true;
> +}
> +
> +Widelands::Extent AttackBox::ListOfSoldiers::size() const {
> +     const size_t nr_soldiers = count_soldiers();
> +     uint32_t rows = nr_soldiers / current_size_;
> +     if (nr_soldiers == 0 || rows * current_size_ < nr_soldiers) {
> +             ++rows;
> +     }
> +     if (restricted_row_number_) {
> +             return Widelands::Extent(rows, current_size_);
> +     } else {
> +             return Widelands::Extent(current_size_, rows);
> +     }
> +}
> +
> +void AttackBox::ListOfSoldiers::update_desired_size() {
> +     current_size_ = std::max(1, restricted_row_number_ ? get_h() / 
> kSoldierIconHeight : get_w() / kSoldierIconWidth);
> +     const Widelands::Extent e = size();
> +     set_desired_size(e.w * kSoldierIconWidth, e.h * kSoldierIconHeight);
> +}
> +
> +const Widelands::Soldier* AttackBox::ListOfSoldiers::soldier_at(int32_t x, 
> int32_t y) const {
> +     if (x < 0 || y < 0 || soldiers_.empty()) {
> +             return nullptr;
> +     }
> +     const int32_t col = x / kSoldierIconWidth;
> +     const int32_t row = y / kSoldierIconHeight;
> +     assert(col >= 0);
> +     assert(row >= 0);
> +     if ((restricted_row_number_ ? row : col) >= current_size_) {
> +             return nullptr;
> +     }
> +     const int index = restricted_row_number_ ? current_size_ * col + row : 
> current_size_ * row + col;
> +     assert(index >= 0);
> +     return static_cast<unsigned int>(index) < soldiers_.size() ? 
> soldiers_[index] : nullptr;
> +}
> +
> +void AttackBox::ListOfSoldiers::add(const Widelands::Soldier* s) {
> +     soldiers_.push_back(s);
> +     update_desired_size();
> +}
> +
> +void AttackBox::ListOfSoldiers::remove(const Widelands::Soldier* s) {
> +     const auto it = std::find(soldiers_.begin(), soldiers_.end(), s);
> +     assert(it != soldiers_.end());
> +     soldiers_.erase(it);
> +     update_desired_size();
> +}
> +
> +void AttackBox::ListOfSoldiers::draw(RenderTarget& dst) {
> +     const size_t nr_soldiers = soldiers_.size();
> +     int32_t column = 0;
> +     int32_t row = 0;
> +     for (uint32_t i = 0; i < nr_soldiers; ++i) {
> +             Vector2i location(column * kSoldierIconWidth, row * 
> kSoldierIconHeight);
> +             soldiers_[i]->draw_info_icon(location, 1.0f, false, &dst);
> +             if (restricted_row_number_) {
> +                     ++row;
> +                     if (row >= current_size_) {
> +                             row = 0;
> +                             ++column;
> +                     }
> +             } else {
> +                     ++column;
> +                     if (column >= current_size_) {
> +                             column = 0;
> +                             ++row;
> +                     }
> +             }
> +     }
> +}
> +


-- 
https://code.launchpad.net/~widelands-dev/widelands/choose-attack-soldiers/+merge/367041
Your team Widelands Developers is requested to review the proposed merge of 
lp:~widelands-dev/widelands/choose-attack-soldiers into lp:widelands.

_______________________________________________
Mailing list: https://launchpad.net/~widelands-dev
Post to     : widelands-dev@lists.launchpad.net
Unsubscribe : https://launchpad.net/~widelands-dev
More help   : https://help.launchpad.net/ListHelp

Reply via email to