> 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