GunChleoc has proposed merging lp:~widelands-dev/widelands/bug-794407-soldier-stats into lp:widelands.
Commit message: Improve soldier level graphics and chat menu code - Improve visibility of health bar graphs - Add toggle for soldier level/health bar graphics - Small refactoring for cat menu code Requested reviews: Widelands Developers (widelands-dev) Related bugs: Bug #794407 in widelands: "Improve soldiers status display" https://bugs.launchpad.net/widelands/+bug/794407 Bug #968984 in widelands: "Improve soldiers' health bar graphics" https://bugs.launchpad.net/widelands/+bug/968984 For more details, see: https://code.launchpad.net/~widelands-dev/widelands/bug-794407-soldier-stats/+merge/371952 -- Your team Widelands Developers is requested to review the proposed merge of lp:~widelands-dev/widelands/bug-794407-soldier-stats into lp:widelands.
=== added file 'data/images/wui/menus/toggle_soldier_levels.png' Binary files data/images/wui/menus/toggle_soldier_levels.png 1970-01-01 00:00:00 +0000 and data/images/wui/menus/toggle_soldier_levels.png 2019-08-28 20:08:47 +0000 differ === modified file 'data/tribes/scripting/help/controls.lua' --- data/tribes/scripting/help/controls.lua 2018-04-28 09:24:11 +0000 +++ data/tribes/scripting/help/controls.lua 2019-08-28 20:08:47 +0000 @@ -50,6 +50,8 @@ dl(help_format_hotkey("C"), _"Toggle census") .. -- TRANSLATORS: This is an access key combination. The hotkey is 's' dl(help_format_hotkey("S"), _"Toggle statistics") .. + -- TRANSLATORS: This is an access key combination. The hotkey is 'l' + dl(help_format_hotkey("L"), _"Toggle soldier health bars and level icons") .. toggle_minimap_hotkey .. toggle_building_spaces_hotkey .. -- TRANSLATORS: This is an access key combination. The hotkey is 'o' === modified file 'src/economy/flag.cc' --- src/economy/flag.cc 2019-07-05 11:16:24 +0000 +++ src/economy/flag.cc 2019-08-28 20:08:47 +0000 @@ -785,7 +785,7 @@ } void Flag::draw(uint32_t gametime, - const TextToDraw, + const InfoToDraw, const Vector2f& field_on_dst, const Coords& coords, float scale, === modified file 'src/economy/flag.h' --- src/economy/flag.h 2019-04-24 06:01:37 +0000 +++ src/economy/flag.h 2019-08-28 20:08:47 +0000 @@ -26,7 +26,7 @@ #include "base/macros.h" #include "economy/routing_node.h" -#include "logic/map_objects/draw_text.h" +#include "logic/map_objects/info_to_draw.h" #include "logic/map_objects/immovable.h" #include "logic/map_objects/walkingdir.h" @@ -154,7 +154,7 @@ void cleanup(EditorGameBase&) override; void draw(uint32_t gametime, - TextToDraw draw_text, + InfoToDraw info_to_draw, const Vector2f& point_on_dst, const Coords& coords, float scale, === modified file 'src/economy/portdock.h' --- src/economy/portdock.h 2019-07-05 11:16:24 +0000 +++ src/economy/portdock.h 2019-08-28 20:08:47 +0000 @@ -135,8 +135,12 @@ friend struct Fleet; // Does nothing - we do not show them on the map - void draw(uint32_t, TextToDraw, const Vector2f&, const Coords&, float, RenderTarget*) override { - } + void draw(uint32_t, + InfoToDraw, + const Vector2f&, + const Coords&, + float, + RenderTarget*) override {} void init_fleet(EditorGameBase& egbase); void set_fleet(Fleet* fleet); === modified file 'src/economy/road.h' --- src/economy/road.h 2019-07-05 11:16:24 +0000 +++ src/economy/road.h 2019-08-28 20:08:47 +0000 @@ -132,8 +132,12 @@ private: /** The road is drawn by the terrain renderer via marked fields. */ - void draw(uint32_t, TextToDraw, const Vector2f&, const Coords&, float, RenderTarget*) override { - } + void draw(uint32_t, + InfoToDraw, + const Vector2f&, + const Coords&, + float, + RenderTarget*) override {} void set_path(EditorGameBase&, const Path&); === modified file 'src/editor/editorinteractive.cc' --- src/editor/editorinteractive.cc 2019-08-28 06:12:07 +0000 +++ src/editor/editorinteractive.cc 2019-08-28 20:08:47 +0000 @@ -588,7 +588,7 @@ Widelands::BaseImmovable* const imm = field.fcoords.field->get_immovable(); if (imm != nullptr && imm->get_positions(ebase).front() == field.fcoords) { imm->draw( - gametime, TextToDraw::kNone, field.rendertarget_pixel, field.fcoords, scale, &dst); + gametime, InfoToDraw::kNone, field.rendertarget_pixel, field.fcoords, scale, &dst); } } @@ -596,7 +596,7 @@ for (Widelands::Bob* bob = field.fcoords.field->get_first_bob(); bob; bob = bob->get_next_bob()) { bob->draw( - ebase, TextToDraw::kNone, field.rendertarget_pixel, field.fcoords, scale, &dst); + ebase, InfoToDraw::kNone, field.rendertarget_pixel, field.fcoords, scale, &dst); } } @@ -784,19 +784,10 @@ select_tool(tools_->current(), EditorTool::Third); return true; - case SDLK_SPACE: - toggle_buildhelp(); - return true; - case SDLK_g: toggle_grid(); return true; - case SDLK_c: - set_display_flag( - InteractiveBase::dfShowCensus, !get_display_flag(InteractiveBase::dfShowCensus)); - return true; - case SDLK_h: mainmenu_.toggle(); return true; === modified file 'src/logic/map_objects/CMakeLists.txt' --- src/logic/map_objects/CMakeLists.txt 2019-08-09 17:29:40 +0000 +++ src/logic/map_objects/CMakeLists.txt 2019-08-28 20:08:47 +0000 @@ -29,7 +29,6 @@ buildcost.h checkstep.cc checkstep.h - draw_text.h findbob.cc findbob.h findimmovable.cc === modified file 'src/logic/map_objects/bob.cc' --- src/logic/map_objects/bob.cc 2019-05-11 13:48:12 +0000 +++ src/logic/map_objects/bob.cc 2019-08-28 20:08:47 +0000 @@ -758,7 +758,7 @@ /// Note that the current node is actually the node that we are walking to, not /// the the one that we start from. void Bob::draw(const EditorGameBase& egbase, - const TextToDraw&, + const InfoToDraw&, const Vector2f& field_on_dst, const Widelands::Coords& coords, const float scale, === modified file 'src/logic/map_objects/bob.h' --- src/logic/map_objects/bob.h 2019-04-24 06:01:37 +0000 +++ src/logic/map_objects/bob.h 2019-08-28 20:08:47 +0000 @@ -25,7 +25,7 @@ #include "economy/route.h" #include "graphic/animation.h" #include "graphic/diranimations.h" -#include "logic/map_objects/draw_text.h" +#include "logic/map_objects/info_to_draw.h" #include "logic/map_objects/map_object.h" #include "logic/map_objects/walkingdir.h" #include "logic/widelands_geometry.h" @@ -264,7 +264,7 @@ // starting field) in pixel space of 'dst' (including scale). The 'scale' is // required to draw the bob in the right size. virtual void draw(const EditorGameBase&, - const TextToDraw& draw_text, + const InfoToDraw& info_to_draw, const Vector2f& field_on_dst, const Coords& coords, float scale, === removed file 'src/logic/map_objects/draw_text.h' --- src/logic/map_objects/draw_text.h 2019-03-29 16:27:34 +0000 +++ src/logic/map_objects/draw_text.h 1970-01-01 00:00:00 +0000 @@ -1,44 +0,0 @@ -/* - * Copyright (C) 2006-2019 by the Widelands Development Team - * - * 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; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -#ifndef WL_LOGIC_MAP_OBJECTS_DRAW_TEXT_H -#define WL_LOGIC_MAP_OBJECTS_DRAW_TEXT_H - -// Only declare powers of 2 and adjust the ~ operator below if you add any values to this enum -// class. -enum class TextToDraw { - kNone = 0, - kCensus = 1, - kStatistics = 2, -}; - -inline TextToDraw operator|(TextToDraw a, TextToDraw b) { - return static_cast<TextToDraw>(static_cast<int>(a) | static_cast<int>(b)); -} -inline TextToDraw operator&(TextToDraw a, TextToDraw b) { - return static_cast<TextToDraw>(static_cast<int>(a) & static_cast<int>(b)); -} -inline TextToDraw removeFromTextToDraw(TextToDraw base, TextToDraw remove) { - const int result = static_cast<int>(base) & ~static_cast<int>(remove); - assert(result >= 0); - assert(result <= 2); - return static_cast<TextToDraw>(result); -} - -#endif // end of include guard: WL_LOGIC_MAP_OBJECTS_DRAW_TEXT_H === modified file 'src/logic/map_objects/immovable.cc' --- src/logic/map_objects/immovable.cc 2019-05-28 17:01:30 +0000 +++ src/logic/map_objects/immovable.cc 2019-08-28 20:08:47 +0000 @@ -463,7 +463,7 @@ } void Immovable::draw(uint32_t gametime, - const TextToDraw draw_text, + const InfoToDraw info_to_draw, const Vector2f& point_on_dst, const Widelands::Coords& coords, float scale, @@ -474,15 +474,15 @@ if (!anim_construction_total_) { dst->blit_animation(point_on_dst, coords, scale, anim_, gametime - animstart_); if (former_building_descr_) { - do_draw_info(draw_text, former_building_descr_->descname(), "", point_on_dst, scale, dst); + do_draw_info(info_to_draw, former_building_descr_->descname(), "", point_on_dst, scale, dst); } } else { - draw_construction(gametime, draw_text, point_on_dst, coords, scale, dst); + draw_construction(gametime, info_to_draw, point_on_dst, coords, scale, dst); } } void Immovable::draw_construction(const uint32_t gametime, - const TextToDraw draw_text, + const InfoToDraw info_to_draw, const Vector2f& point_on_dst, const Widelands::Coords& coords, const float scale, @@ -525,7 +525,7 @@ // Additionally, if statistics are enabled, draw a progression string do_draw_info( - draw_text, descr().descname(), + info_to_draw, descr().descname(), g_gr->styles().color_tag((boost::format(_("%i%% built")) % (100 * done / total)).str(), g_gr->styles().building_statistics_style().construction_color()), point_on_dst, scale, dst); === modified file 'src/logic/map_objects/immovable.h' --- src/logic/map_objects/immovable.h 2019-04-24 06:01:37 +0000 +++ src/logic/map_objects/immovable.h 2019-08-28 20:08:47 +0000 @@ -26,7 +26,7 @@ #include "base/macros.h" #include "graphic/animation.h" #include "logic/map_objects/buildcost.h" -#include "logic/map_objects/draw_text.h" +#include "logic/map_objects/info_to_draw.h" #include "logic/map_objects/map_object.h" #include "logic/widelands_geometry.h" #include "notifications/note_ids.h" @@ -97,13 +97,13 @@ virtual PositionList get_positions(const EditorGameBase&) const = 0; // Draw this immovable onto 'dst' choosing the frame appropriate for - // 'gametime'. 'draw_text' decides if census and statistics are written too. + // 'gametime'. 'info_to_draw' decides if census and statistics are written too. // The 'coords_to_draw' are passed one to give objects that occupy multiple // fields a way to only draw themselves once. The 'point_on_dst' determines // the point for the hotspot of the animation and 'scale' determines how big // the immovable will be plotted. virtual void draw(uint32_t gametime, - TextToDraw draw_text, + InfoToDraw info_to_draw, const Vector2f& point_on_dst, const Coords& coords, float scale, @@ -229,7 +229,7 @@ void cleanup(EditorGameBase&) override; void act(Game&, uint32_t data) override; void draw(uint32_t gametime, - TextToDraw draw_text, + InfoToDraw info_to_draw, const Vector2f& point_on_dst, const Coords& coords, float scale, @@ -316,7 +316,7 @@ void increment_program_pointer(); void draw_construction(uint32_t gametime, - TextToDraw draw_text, + InfoToDraw info_to_draw, const Vector2f& point_on_dst, const Widelands::Coords& coords, float scale, === added file 'src/logic/map_objects/info_to_draw.h' --- src/logic/map_objects/info_to_draw.h 1970-01-01 00:00:00 +0000 +++ src/logic/map_objects/info_to_draw.h 2019-08-28 20:08:47 +0000 @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2006-2017 by the Widelands Development Team + * + * 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; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#ifndef WL_LOGIC_MAP_OBJECTS_INFO_TO_DRAW_H +#define WL_LOGIC_MAP_OBJECTS_INFO_TO_DRAW_H + +enum InfoToDraw { + kNone = 0, + kCensus = 1, + kStatistics = 2, + kSoldierLevels = 4, +}; + +inline InfoToDraw operator|(InfoToDraw a, InfoToDraw b) { + return static_cast<InfoToDraw>(static_cast<int>(a) | static_cast<int>(b)); +} + +#endif // end of include guard: WL_LOGIC_MAP_OBJECTS_INFO_TO_DRAW_H === modified file 'src/logic/map_objects/map_object.cc' --- src/logic/map_objects/map_object.cc 2019-05-27 21:04:13 +0000 +++ src/logic/map_objects/map_object.cc 2019-08-28 20:08:47 +0000 @@ -506,20 +506,24 @@ egbase.objects().remove(*this); } -void MapObject::do_draw_info(const TextToDraw& draw_text, +void MapObject::do_draw_info(const InfoToDraw& info_to_draw, const std::string& census, const std::string& statictics, const Vector2f& field_on_dst, float scale, RenderTarget* dst) const { - if (draw_text == TextToDraw::kNone) { + if (!(info_to_draw & (InfoToDraw::kCensus | InfoToDraw::kStatistics))) { return; } // Rendering text is expensive, so let's just do it for only a few sizes. + const float granularity = 4.f; + float text_scale = scale; // The formula is a bit fancy to avoid too much text overlap. - scale = std::round(2.f * (scale > 1.f ? std::sqrt(scale) : std::pow(scale, 2.f))) / 2.f; - if (scale < 1.f) { + text_scale = std::round(granularity * (text_scale > 1.f ? std::sqrt(text_scale) : std::pow(text_scale, 2.f))) / granularity; + + // Skip tiny text for performance reasons + if (text_scale < 0.5f) { return; } @@ -530,11 +534,12 @@ std::shared_ptr<const UI::RenderedText> rendered_census = UI::g_fh->render(as_richtext_paragraph(census, census_font, UI::Align::kCenter), 120 * scale); Vector2i position = field_on_dst.cast<int>() - Vector2i(0, 48) * scale; - if ((draw_text & TextToDraw::kCensus) != TextToDraw::kNone) { + if (info_to_draw & InfoToDraw::kCensus) { rendered_census->draw(*dst, position, UI::Align::kCenter); } - if ((draw_text & TextToDraw::kStatistics) != TextToDraw::kNone && !statictics.empty()) { + // Draw statistics if we want them, they are available and they fill fit + if (info_to_draw & InfoToDraw::kStatistics && !statictics.empty() && scale >= 0.5f) { UI::FontStyleInfo statistics_font( g_gr->styles().building_statistics_style().statistics_font()); statistics_font.set_size(scale * statistics_font.size()); === modified file 'src/logic/map_objects/map_object.h' --- src/logic/map_objects/map_object.h 2019-05-25 08:51:42 +0000 +++ src/logic/map_objects/map_object.h 2019-08-28 20:08:47 +0000 @@ -35,7 +35,7 @@ #include "graphic/color.h" #include "graphic/image.h" #include "logic/cmd_queue.h" -#include "logic/map_objects/draw_text.h" +#include "logic/map_objects/info_to_draw.h" #include "logic/map_objects/tribes/training_attribute.h" #include "logic/widelands.h" #include "scripting/lua_table.h" @@ -407,7 +407,7 @@ virtual void cleanup(EditorGameBase&); /// Draws census and statistics on screen - void do_draw_info(const TextToDraw& draw_text, + void do_draw_info(const InfoToDraw& info_to_draw, const std::string& census, const std::string& statictics, const Vector2f& field_on_dst, === modified file 'src/logic/map_objects/tribes/building.cc' --- src/logic/map_objects/tribes/building.cc 2019-06-25 08:03:30 +0000 +++ src/logic/map_objects/tribes/building.cc 2019-08-28 20:08:47 +0000 @@ -605,7 +605,7 @@ } void Building::draw(uint32_t gametime, - const TextToDraw draw_text, + const InfoToDraw info_to_draw, const Vector2f& point_on_dst, const Widelands::Coords& coords, const float scale, @@ -616,7 +616,7 @@ // door animation? // overlay strings (draw when enabled) - draw_info(draw_text, point_on_dst, scale, dst); + draw_info(info_to_draw, point_on_dst, scale, dst); } /* @@ -624,15 +624,13 @@ Draw overlay help strings when enabled. =============== */ -void Building::draw_info(const TextToDraw draw_text, +void Building::draw_info(const InfoToDraw info_to_draw, const Vector2f& point_on_dst, const float scale, RenderTarget* dst) { const std::string statistics_string = - ((draw_text & TextToDraw::kStatistics) != TextToDraw::kNone) ? - info_string(InfoStringFormat::kStatistics) : - ""; - do_draw_info(draw_text, info_string(InfoStringFormat::kCensus), statistics_string, point_on_dst, + (info_to_draw & InfoToDraw::kStatistics) ? info_string(InfoStringFormat::kStatistics) : ""; + do_draw_info(info_to_draw, info_string(InfoStringFormat::kCensus), statistics_string, point_on_dst, scale, dst); } === modified file 'src/logic/map_objects/tribes/building.h' --- src/logic/map_objects/tribes/building.h 2019-06-23 11:41:17 +0000 +++ src/logic/map_objects/tribes/building.h 2019-08-28 20:08:47 +0000 @@ -344,13 +344,13 @@ void act(Game&, uint32_t data) override; void draw(uint32_t gametime, - TextToDraw draw_text, + InfoToDraw info_to_draw, const Vector2f& point_on_dst, const Coords& coords, float scale, RenderTarget* dst) override; void - draw_info(TextToDraw draw_text, const Vector2f& point_on_dst, float scale, RenderTarget* dst); + draw_info(InfoToDraw info_to_draw, const Vector2f& point_on_dst, float scale, RenderTarget* dst); void set_seeing(bool see); void set_attack_target(AttackTarget* new_attack_target); === modified file 'src/logic/map_objects/tribes/constructionsite.cc' --- src/logic/map_objects/tribes/constructionsite.cc 2019-06-23 11:41:17 +0000 +++ src/logic/map_objects/tribes/constructionsite.cc 2019-08-28 20:08:47 +0000 @@ -603,7 +603,7 @@ =============== */ void ConstructionSite::draw(uint32_t gametime, - TextToDraw draw_text, + InfoToDraw info_to_draw, const Vector2f& point_on_dst, const Widelands::Coords& coords, float scale, @@ -628,6 +628,6 @@ info_.draw(point_on_dst, coords, scale, player_color, dst); // Draw help strings - draw_info(draw_text, point_on_dst, scale, dst); + draw_info(info_to_draw, point_on_dst, scale, dst); } } // namespace Widelands === modified file 'src/logic/map_objects/tribes/constructionsite.h' --- src/logic/map_objects/tribes/constructionsite.h 2019-06-23 11:41:17 +0000 +++ src/logic/map_objects/tribes/constructionsite.h 2019-08-28 20:08:47 +0000 @@ -143,7 +143,7 @@ static void wares_queue_callback(Game&, InputQueue*, DescriptionIndex, Worker*, void* data); void draw(uint32_t gametime, - TextToDraw draw_text, + InfoToDraw info_to_draw, const Vector2f& point_on_dst, const Coords& coords, float scale, === modified file 'src/logic/map_objects/tribes/dismantlesite.cc' --- src/logic/map_objects/tribes/dismantlesite.cc 2019-05-26 17:21:15 +0000 +++ src/logic/map_objects/tribes/dismantlesite.cc 2019-08-28 20:08:47 +0000 @@ -228,7 +228,7 @@ =============== */ void DismantleSite::draw(uint32_t gametime, - const TextToDraw draw_text, + const InfoToDraw info_to_draw, const Vector2f& point_on_dst, const Widelands::Coords& coords, float scale, @@ -244,6 +244,6 @@ &player_color, 100 - ((get_built_per64k() * 100) >> 16)); // Draw help strings - draw_info(draw_text, point_on_dst, scale, dst); + draw_info(info_to_draw, point_on_dst, scale, dst); } } // namespace Widelands === modified file 'src/logic/map_objects/tribes/dismantlesite.h' --- src/logic/map_objects/tribes/dismantlesite.h 2019-05-05 14:05:07 +0000 +++ src/logic/map_objects/tribes/dismantlesite.h 2019-08-28 20:08:47 +0000 @@ -90,7 +90,7 @@ } void draw(uint32_t gametime, - TextToDraw draw_text, + InfoToDraw info_to_draw, const Vector2f& point_on_dst, const Widelands::Coords& coords, float scale, === modified file 'src/logic/map_objects/tribes/productionsite.cc' --- src/logic/map_objects/tribes/productionsite.cc 2019-08-20 17:35:33 +0000 +++ src/logic/map_objects/tribes/productionsite.cc 2019-08-28 20:08:47 +0000 @@ -311,18 +311,20 @@ * Display whether we're occupied. */ void ProductionSite::update_statistics_string(std::string* s) { - uint32_t const nr_working_positions = descr().nr_working_positions(); - uint32_t nr_workers = 0; - for (uint32_t i = nr_working_positions; i;) - nr_workers += working_positions_[--i].worker ? 1 : 0; - - if (nr_workers == 0) { - *s = g_gr->styles().color_tag( - _("(not occupied)"), g_gr->styles().building_statistics_style().low_color()); - return; + uint32_t nr_requests = 0; + uint32_t nr_coming = 0; + for (uint32_t i = 0; i < descr().nr_working_positions(); ++i) { + const Widelands::Request* request = working_positions_[i].worker_request; + if (request) { + if (request->is_open()) { + ++nr_requests; + } else { + ++nr_coming; + } + } } - if (uint32_t const nr_requests = nr_working_positions - nr_workers) { + if (nr_requests > 0) { *s = g_gr->styles().color_tag( (nr_requests == 1 ? /** TRANSLATORS: Productivity label on a building if there is 1 worker missing */ @@ -334,6 +336,18 @@ return; } + if (nr_coming > 0) { + *s = g_gr->styles().color_tag( + (nr_coming == 1 ? + /** TRANSLATORS: Productivity label on a building if there is 1 worker missing */ + _("Worker is coming") : + /** TRANSLATORS: Productivity label on a building if there is more than 1 worker + missing. If you need plural forms here, please let us know. */ + _("Workers are coming")), + g_gr->styles().building_statistics_style().low_color()); + return; + } + if (is_stopped_) { *s = g_gr->styles().color_tag( _("(stopped)"), g_gr->styles().building_statistics_style().neutral_color()); === modified file 'src/logic/map_objects/tribes/ship.cc' --- src/logic/map_objects/tribes/ship.cc 2019-05-27 14:28:34 +0000 +++ src/logic/map_objects/tribes/ship.cc 2019-08-28 20:08:47 +0000 @@ -1020,16 +1020,16 @@ } void Ship::draw(const EditorGameBase& egbase, - const TextToDraw& draw_text, + const InfoToDraw& info_to_draw, const Vector2f& point_on_dst, const Widelands::Coords& coords, const float scale, RenderTarget* dst) const { - Bob::draw(egbase, draw_text, point_on_dst, coords, scale, dst); + Bob::draw(egbase, info_to_draw, point_on_dst, coords, scale, dst); // Show ship name and current activity std::string statistics_string; - if ((draw_text & TextToDraw::kStatistics) != TextToDraw::kNone) { + if (info_to_draw & InfoToDraw::kStatistics) { switch (ship_state_) { case (ShipStates::kTransport): if (destination_.is_set()) { @@ -1066,7 +1066,7 @@ statistics_string, g_gr->styles().building_statistics_style().medium_color()); } - do_draw_info(draw_text, shipname_, statistics_string, calc_drawpos(egbase, point_on_dst, scale), + do_draw_info(info_to_draw, shipname_, statistics_string, calc_drawpos(egbase, point_on_dst, scale), scale, dst); } === modified file 'src/logic/map_objects/tribes/ship.h' --- src/logic/map_objects/tribes/ship.h 2019-04-24 06:51:31 +0000 +++ src/logic/map_objects/tribes/ship.h 2019-08-28 20:08:47 +0000 @@ -236,7 +236,7 @@ protected: void draw(const EditorGameBase&, - const TextToDraw& draw_text, + const InfoToDraw& info_to_draw, const Vector2f& point_on_dst, const Coords& coords, float scale, === modified file 'src/logic/map_objects/tribes/soldier.cc' --- src/logic/map_objects/tribes/soldier.cc 2019-05-27 14:25:47 +0000 +++ src/logic/map_objects/tribes/soldier.cc 2019-08-28 20:08:47 +0000 @@ -57,7 +57,7 @@ namespace Widelands { namespace { - +constexpr int kSoldierHealthBarWidth = 13; constexpr int kRetreatWhenHealthDropsBelowThisPercentage = 50; } // namespace @@ -548,7 +548,7 @@ * Draw this soldier. This basically draws him as a worker, but add health points */ void Soldier::draw(const EditorGameBase& game, - const TextToDraw&, + const InfoToDraw& info_to_draw, const Vector2f& field_on_dst, const Coords& coords, float scale, @@ -562,133 +562,143 @@ draw_info_icon( point_on_dst.cast<int>() - Vector2i(0, (g_gr->animations().get_animation(get_current_anim()).height() - 7) * scale), - scale, true, dst); + scale, InfoMode::kWalkingAround, info_to_draw, dst); draw_inner(game, point_on_dst, coords, scale, dst); } /** * Draw the info icon (level indicators + health bar) for this soldier. + * 'draw_mode' determines whether the soldier info is displayed in a building window + * or on top of a soldier walking around. 'info_to_draw' checks which info the user wants to see + * for soldiers walking around. */ void Soldier::draw_info_icon(Vector2i draw_position, float scale, - const bool anchor_below, + const InfoMode draw_mode, + const InfoToDraw info_to_draw, RenderTarget* dst) const { + if (!(info_to_draw & InfoToDraw::kSoldierLevels)) { + return; + } + // Since the graphics below are all pixel perfect and scaling them as floats - // looks weird, we round to the nearest fullest integer. - scale = std::round(scale); - if (scale == 0.f) { - return; - } - - const Image* healthpic = get_health_level_pic(); - const Image* attackpic = get_attack_level_pic(); - const Image* defensepic = get_defense_level_pic(); - const Image* evadepic = get_evade_level_pic(); + // looks weird, we round to the nearest fullest integer. We do allow half size though. + scale = std::max(0.5f, std::round(scale)); #ifndef NDEBUG - // This function assumes stuff about our data files: level icons are all the - // same size and this is smaller than the width of the healthbar. This - // simplifies the drawing code below a lot. Before it had a lot of if () that - // were never tested - since our data files never changed. - const int dimension = attackpic->width(); - assert(attackpic->height() == dimension); - assert(healthpic->width() == dimension); - assert(healthpic->height() == dimension); - assert(defensepic->width() == dimension); - assert(defensepic->height() == dimension); - assert(evadepic->width() == dimension); - assert(evadepic->height() == dimension); - assert(kSoldierHealthBarWidth > dimension); + { + // This function assumes stuff about our data files: level icons are all the + // same size and this is smaller than the width of the healthbar. This + // simplifies the drawing code below a lot. Before it had a lot of if () that + // were never tested - since our data files never changed. + const Image* healthpic = get_health_level_pic(); + + const Image* attackpic = get_attack_level_pic(); + const Image* defensepic = get_defense_level_pic(); + const Image* evadepic = get_evade_level_pic(); + + const int dimension = attackpic->width(); + assert(attackpic->height() == dimension); + assert(healthpic->width() == dimension); + assert(healthpic->height() == dimension); + assert(defensepic->width() == dimension); + assert(defensepic->height() == dimension); + assert(evadepic->width() == dimension); + assert(evadepic->height() == dimension); + assert(kSoldierHealthBarWidth > dimension); + } #endif - const int icon_size = healthpic->width(); - - if (!anchor_below) { + const int icon_size = get_health_level_pic()->height(); + + // Draw health info in building windows, or if kSoldierLevels is on. + const bool draw_health_bar = draw_mode == InfoMode::kInBuilding || (info_to_draw & InfoToDraw::kSoldierLevels); + + switch (draw_mode) { + case InfoMode::kInBuilding: draw_position.x += kSoldierHealthBarWidth * scale; draw_position.y += 2 * icon_size * scale; - } else { - draw_position.y -= 5 * scale; + break; + case InfoMode::kWalkingAround: + if (draw_health_bar) { + draw_position.y -= 5 * scale; + } } - // Draw energy bar - assert(get_max_health()); - const Recti energy_outer(draw_position - Vector2i(kSoldierHealthBarWidth, 0) * scale, - kSoldierHealthBarWidth * 2 * scale, 5 * scale); - dst->fill_rect(energy_outer, RGBColor(255, 255, 255)); - - // Adjust health to current animation tick - uint32_t health_to_show = current_health_; - if (battle_) { - uint32_t pending_damage = battle_->get_pending_damage(this); - if (pending_damage > 0) { - int32_t timeshift = owner().egbase().get_gametime() - get_animstart(); - timeshift = std::min(std::max(0, timeshift), 1000); - - pending_damage *= timeshift; - pending_damage /= 1000; - - if (pending_damage > health_to_show) { - health_to_show = 0; - } else { - health_to_show -= pending_damage; + if (draw_health_bar) { + // Draw energy bar + assert(get_max_health()); + const RGBColor& color = owner().get_playercolor(); + const uint16_t color_sum = color.r + color.g + color.b; + + // The frame gets a slight tint of player color + const Recti energy_outer(draw_position - Vector2i(kSoldierHealthBarWidth, 0) * scale, + kSoldierHealthBarWidth * 2 * scale, 5 * scale); + dst->fill_rect(energy_outer, color); + dst->brighten_rect(energy_outer, 230 - color_sum / 3); + + + // Adjust health to current animation tick + uint32_t health_to_show = current_health_; + if (battle_) { + uint32_t pending_damage = battle_->get_pending_damage(this); + if (pending_damage > 0) { + int32_t timeshift = owner().egbase().get_gametime() - get_animstart(); + timeshift = std::min(std::max(0, timeshift), 1000); + + pending_damage *= timeshift; + pending_damage /= 1000; + + if (pending_damage > health_to_show) { + health_to_show = 0; + } else { + health_to_show -= pending_damage; + } } } - } - - int health_width = 2 * (kSoldierHealthBarWidth - 1) * health_to_show / get_max_health(); - Recti energy_inner(draw_position + Vector2i(-kSoldierHealthBarWidth + 1, 1) * scale, - health_width * scale, 3 * scale); - Recti energy_complement(energy_inner.origin() + Vector2i(health_width, 0) * scale, - (2 * (kSoldierHealthBarWidth - 1) - health_width) * scale, 3 * scale); - - const RGBColor& color = owner().get_playercolor(); - RGBColor complement_color; - if (static_cast<uint32_t>(color.r) + color.g + color.b > 128 * 3) { - complement_color = RGBColor(32, 32, 32); - } else { - complement_color = RGBColor(224, 224, 224); - } - - dst->fill_rect(energy_inner, color); - dst->fill_rect(energy_complement, complement_color); - - const auto draw_level_image = [icon_size, scale, &draw_position, dst]( - const Vector2i& offset, const Image* image) { - dst->blitrect_scale( - Rectf(draw_position + offset * icon_size * scale, icon_size * scale, icon_size * scale), - image, Recti(0, 0, icon_size, icon_size), 1.f, BlendMode::UseAlpha); - }; - draw_level_image(Vector2i(-1, -2), attackpic); - draw_level_image(Vector2i(0, -2), defensepic); - draw_level_image(Vector2i(-1, -1), healthpic); - draw_level_image(Vector2i(0, -1), evadepic); + + // Now draw the health bar itself + const int health_width = + 2 * (kSoldierHealthBarWidth - 1) * health_to_show / get_max_health(); + + Recti energy_inner(draw_position + Vector2i(-kSoldierHealthBarWidth + 1, 1) * scale, + health_width * scale, 3 * scale); + Recti energy_complement(energy_inner.origin() + Vector2i(health_width, 0) * scale, + (2 * (kSoldierHealthBarWidth - 1) - health_width) * scale, 3 * scale); + + const RGBColor complement_color = color_sum > 128 * 3 ? RGBColor(32, 32, 32) : RGBColor(224, 224, 224); + dst->fill_rect(energy_inner, color); + dst->fill_rect(energy_complement, complement_color); + } + + // Draw level info in building windows, or if kSoldierLevels is on. + if (draw_mode == InfoMode::kInBuilding || (info_to_draw & InfoToDraw::kSoldierLevels)) { + const auto draw_level_image = [icon_size, scale, &draw_position, dst]( + const Vector2i& offset, const Image* image) { + dst->blitrect_scale(Rectf(draw_position + offset * icon_size * scale, icon_size * scale, + icon_size * scale), + image, Recti(0, 0, icon_size, icon_size), 1.f, BlendMode::UseAlpha); + }; + + draw_level_image(Vector2i(-1, -2), get_attack_level_pic()); + draw_level_image(Vector2i(0, -2), get_defense_level_pic()); + draw_level_image(Vector2i(-1, -1), get_health_level_pic()); + draw_level_image(Vector2i(0, -1), get_evade_level_pic()); + } } /** * Compute the size of the info icon (level indicators + health bar) for soldiers of * the given tribe. */ -void Soldier::calc_info_icon_size(const TribeDescr& tribe, uint32_t& w, uint32_t& h) { +void Soldier::calc_info_icon_size(const TribeDescr& tribe, int& w, int& h) { const SoldierDescr* soldierdesc = static_cast<const SoldierDescr*>(tribe.get_worker_descr(tribe.soldier())); - const Image* healthpic = soldierdesc->get_health_level_pic(0); - const Image* attackpic = soldierdesc->get_attack_level_pic(0); - const Image* defensepic = soldierdesc->get_defense_level_pic(0); - const Image* evadepic = soldierdesc->get_evade_level_pic(0); - uint16_t hpw = healthpic->width(); - uint16_t hph = healthpic->height(); - uint16_t atw = attackpic->width(); - uint16_t ath = attackpic->height(); - uint16_t dew = defensepic->width(); - uint16_t deh = defensepic->height(); - uint16_t evw = evadepic->width(); - uint16_t evh = evadepic->height(); - - uint16_t animw; - animw = kSoldierHealthBarWidth; - - w = std::max(std::max(atw + dew, hpw + evw), 2 * animw); - h = 5 + std::max(hph + ath, evh + deh); + // The function draw_info_icon() already assumes that all icons have the same dimensions, + // so we can make the same assumption here too. + const int dimension = soldierdesc->get_health_level_pic(0)->height(); + w = 2 * std::max(dimension, kSoldierHealthBarWidth); + h = 5 + 2 * dimension; } void Soldier::pop_task_or_fight(Game& game) { === modified file 'src/logic/map_objects/tribes/soldier.h' --- src/logic/map_objects/tribes/soldier.h 2019-05-27 14:25:47 +0000 +++ src/logic/map_objects/tribes/soldier.h 2019-08-28 20:08:47 +0000 @@ -210,6 +210,8 @@ MO_DESCR(SoldierDescr) public: + enum class InfoMode { kWalkingAround, kInBuilding }; + explicit Soldier(const SoldierDescr&); bool init(EditorGameBase&) override; @@ -246,20 +248,21 @@ /// Draw this soldier void draw(const EditorGameBase&, - const TextToDraw& draw_text, + const InfoToDraw& info_to_draw, const Vector2f& point_on_dst, const Widelands::Coords& coords, float scale, RenderTarget* dst) const override; - static void calc_info_icon_size(const TribeDescr&, uint32_t& w, uint32_t& h); + static void calc_info_icon_size(const TribeDescr&, int& w, int& h); // Draw the info icon containing health bar and levels. If 'anchor_below' is // true, the icon is drawn horizontally centered above Otherwise, the icon // is drawn below and right of 'draw_position'. void draw_info_icon(Vector2i draw_position, const float scale, - const bool anchor_below, + const InfoMode draw_mode, + const InfoToDraw info_to_draw, RenderTarget*) const; uint32_t get_current_health() const { @@ -371,8 +374,6 @@ std::pair<std::unique_ptr<SoldierLevelRange>, std::unique_ptr<DirAnimations>> walking_animations_cache_; - static constexpr uint8_t kSoldierHealthBarWidth = 13; - /// Number of consecutive blocked signals until the soldiers are considered permanently stuck static constexpr uint8_t kBockCountIsStuck = 10; === modified file 'src/logic/map_objects/tribes/worker.cc' --- src/logic/map_objects/tribes/worker.cc 2019-05-28 17:01:30 +0000 +++ src/logic/map_objects/tribes/worker.cc 2019-08-28 20:08:47 +0000 @@ -3024,7 +3024,7 @@ * Draw the worker, taking the carried ware into account. */ void Worker::draw(const EditorGameBase& egbase, - const TextToDraw&, + const InfoToDraw&, const Vector2f& field_on_dst, const Widelands::Coords& coords, const float scale, === modified file 'src/logic/map_objects/tribes/worker.h' --- src/logic/map_objects/tribes/worker.h 2019-04-24 06:01:37 +0000 +++ src/logic/map_objects/tribes/worker.h 2019-08-28 20:08:47 +0000 @@ -183,7 +183,7 @@ const float scale, RenderTarget* dst) const; void draw(const EditorGameBase&, - const TextToDraw& draw_text, + const InfoToDraw& info_to_draw, const Vector2f& field_on_dst, const Widelands::Coords& coords, float scale, === modified file 'src/network/gameclient.cc' --- src/network/gameclient.cc 2019-08-28 06:12:07 +0000 +++ src/network/gameclient.cc 2019-08-28 20:08:47 +0000 @@ -164,12 +164,12 @@ (boost::format("%s_netclient%u") % kAutosavePrefix % static_cast<unsigned int>(pn)).str()); InteractiveGameBase* igb; if (pn > 0) { - igb = new InteractivePlayer(*game, get_config_section(), pn, true); + igb = new InteractivePlayer(*game, get_config_section(), pn, true, parent); } else { - igb = new InteractiveSpectator(*game, get_config_section(), true); + igb = new InteractiveSpectator(*game, get_config_section(), true, parent); } + game->set_ibase(igb); - igb->set_chat_provider(*parent); if (settings.savegame) { // savegame game->init_savegame(loader, settings); } else { // new map @@ -274,7 +274,6 @@ d->game = &game; InteractiveGameBase* igb = d->init_game(this, loader_ui.get()); d->run_game(igb, loader_ui.get()); - } catch (...) { WLApplication::emergency_save(game); d->game = nullptr; === modified file 'src/network/gamehost.cc' --- src/network/gamehost.cc 2019-08-28 06:12:07 +0000 +++ src/network/gamehost.cc 2019-08-28 20:08:47 +0000 @@ -668,11 +668,10 @@ } if ((pn > 0) && (pn <= UserSettings::highest_playernum())) { - igb = new InteractivePlayer(game, get_config_section(), pn, true); + igb = new InteractivePlayer(game, get_config_section(), pn, true, &d->chat); } else { - igb = new InteractiveSpectator(game, get_config_section(), true); + igb = new InteractiveSpectator(game, get_config_section(), true, &d->chat); } - igb->set_chat_provider(d->chat); game.set_ibase(igb); if (!d->settings.savegame) // new game === modified file 'src/wui/attack_box.cc' --- src/wui/attack_box.cc 2019-05-26 17:21:15 +0000 +++ src/wui/attack_box.cc 2019-08-28 20:08:47 +0000 @@ -403,7 +403,7 @@ 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); + soldiers_[i]->draw_info_icon(location, 1.0f, Soldier::InfoMode::kInBuilding, InfoToDraw::kSoldierLevels, &dst); if (restricted_row_number_) { ++row; if (row >= current_size_) { === modified file 'src/wui/interactive_base.cc' --- src/wui/interactive_base.cc 2019-08-25 14:50:16 +0000 +++ src/wui/interactive_base.cc 2019-08-28 20:08:47 +0000 @@ -178,9 +178,9 @@ workareas_cache_(nullptr), egbase_(the_egbase), #ifndef NDEBUG // not in releases - display_flags_(dfDebug), + display_flags_(dfDebug | kSoldierLevels), #else - display_flags_(0), + display_flags_(kSoldierLevels), #endif lastframe_(SDL_GetTicks()), frametime_(0), @@ -389,16 +389,22 @@ set_sel_pos(get_sel_pos()); // redraw } -TextToDraw InteractiveBase::get_text_to_draw() const { - TextToDraw text_to_draw = TextToDraw::kNone; +InfoToDraw InteractiveBase::get_info_to_draw(bool show) const { + InfoToDraw info_to_draw = InfoToDraw::kNone; + if (!show) { + return info_to_draw; + } auto display_flags = get_display_flags(); if (display_flags & InteractiveBase::dfShowCensus) { - text_to_draw = text_to_draw | TextToDraw::kCensus; + info_to_draw = info_to_draw | InfoToDraw::kCensus; } if (display_flags & InteractiveBase::dfShowStatistics) { - text_to_draw = text_to_draw | TextToDraw::kStatistics; - } - return text_to_draw; + info_to_draw = info_to_draw | InfoToDraw::kStatistics; + } + if (display_flags & InteractiveBase::dfShowSoldierLevels) { + info_to_draw = info_to_draw | InfoToDraw::kSoldierLevels; + } + return info_to_draw; } void InteractiveBase::unset_sel_picture() { @@ -1169,6 +1175,10 @@ this, debugconsole_, *DebugConsole::get_chat_provider()); return true; #endif + // Common shortcuts for InteractivePlayer, InteractiveSpectator and EditorInteractive + case SDLK_SPACE: + toggle_buildhelp(); + return true; case SDLK_m: toggle_minimap(); return true; === modified file 'src/wui/interactive_base.h' --- src/wui/interactive_base.h 2019-08-25 14:50:16 +0000 +++ src/wui/interactive_base.h 2019-08-28 20:08:47 +0000 @@ -61,11 +61,12 @@ class InteractiveBase : public UI::Panel, public DebugConsole::Handler { public: enum { - dfShowCensus = 1, ///< show census report on buildings - dfShowStatistics = 2, ///< show statistics report on buildings - dfDebug = 4, ///< general debugging info + dfShowCensus = 1, /// show census report on buildings + dfShowStatistics = 2, /// show statistics report on buildings + dfShowSoldierLevels = 4, /// show level information above soldiers dfShowWorkareaOverlap = 8, ///< highlight overlapping workareas when placing a constructionsite + dfDebug = 16 /// general debugging info }; // Overlays displayed while a road is under construction. @@ -252,7 +253,8 @@ } // Returns the information which overlay text should currently be drawn. - TextToDraw get_text_to_draw() const; + // Returns InfoToDraw::kNone if not 'show' + InfoToDraw get_info_to_draw(bool show) const; // Returns the current overlays for the work area previews. Workareas get_workarea_overlays(const Widelands::Map& map); === modified file 'src/wui/interactive_gamebase.cc' --- src/wui/interactive_gamebase.cc 2019-08-25 14:50:16 +0000 +++ src/wui/interactive_gamebase.cc 2019-08-28 20:08:47 +0000 @@ -64,9 +64,10 @@ InteractiveGameBase::InteractiveGameBase(Widelands::Game& g, Section& global_s, PlayerType pt, - bool const multiplayer) + bool const multiplayer, + ChatProvider* chat_provider) : InteractiveBase(g, global_s), - chat_provider_(nullptr), + chat_provider_(chat_provider), multiplayer_(multiplayer), playertype_(pt), showhidemenu_(toolbar(), @@ -132,6 +133,10 @@ break; } }); + + if (chat_provider_ != nullptr) { + chat_overlay()->set_chat_provider(*chat_provider_); + } } void InteractiveGameBase::add_main_menu() { @@ -218,11 +223,20 @@ showhidemenu_.add(get_display_flag(dfShowStatistics) ? /** TRANSLATORS: An entry in the game's show/hide menu to toggle whether - * building staristics are shown */ + * building statistics are shown */ _("Hide Statistics") : _("Show Statistics"), ShowHideEntry::kStatistics, g_gr->images().get("images/wui/menus/toggle_statistics.png"), false, "", "s"); + + + showhidemenu_.add(get_display_flag(dfShowSoldierLevels) ? + /** TRANSLATORS: An entry in the game's show/hide menu to toggle whether + * level information is sown above soldiers' heads */ + _("Hide Soldier Levels") : + _("Show Soldier Levels"), + ShowHideEntry::kSoldierLevels, + g_gr->images().get("images/wui/menus/toggle_soldier_levels.png"), false, "", "l"); } void InteractiveGameBase::showhide_menu_selected(ShowHideEntry entry) { @@ -236,6 +250,9 @@ case ShowHideEntry::kStatistics: { set_display_flag(dfShowStatistics, !get_display_flag(dfShowStatistics)); } break; + case ShowHideEntry::kSoldierLevels: { + set_display_flag(dfShowSoldierLevels, !get_display_flag(dfShowSoldierLevels)); + } break; case ShowHideEntry::kWorkareaOverlap: { set_display_flag(dfShowWorkareaOverlap, !get_display_flag(dfShowWorkareaOverlap)); } break; @@ -299,6 +316,15 @@ } } +void InteractiveGameBase::add_chat_ui() { + add_toolbar_button("wui/menus/chat", "chat", _("Chat"), &chat_, true); + chat_.open_window = [this] { + if (chat_provider_) { + GameChatMenu::create_chat_console(this, chat_, *chat_provider_); + } + }; +} + void InteractiveGameBase::increase_gamespeed() { if (GameController* const ctrl = get_game()->game_controller()) { ctrl->set_desired_speed(ctrl->desired_speed() + 1000); @@ -348,6 +374,24 @@ case SDLK_PAGEDOWN: decrease_gamespeed(); return true; + + case SDLK_c: + set_display_flag( + InteractiveBase::dfShowCensus, !get_display_flag(InteractiveBase::dfShowCensus)); + return true; + + case SDLK_l: + set_display_flag(dfShowSoldierLevels, !get_display_flag(dfShowSoldierLevels)); + return true; + + case SDLK_s: + if (code.mod & (KMOD_LCTRL | KMOD_RCTRL)) { + new GameMainMenuSaveGame(*this, menu_windows_.savegame); + } else { + set_display_flag(dfShowStatistics, !get_display_flag(dfShowStatistics)); + } + return true; + default: break; } @@ -364,15 +408,6 @@ return dynamic_cast<Widelands::Game&>(egbase()); } -void InteractiveGameBase::set_chat_provider(ChatProvider& chat) { - chat_provider_ = &chat; - chat_overlay()->set_chat_provider(chat); -} - -ChatProvider* InteractiveGameBase::get_chat_provider() { - return chat_provider_; -} - void InteractiveGameBase::draw_overlay(RenderTarget& dst) { InteractiveBase::draw_overlay(dst); === modified file 'src/wui/interactive_gamebase.h' --- src/wui/interactive_gamebase.h 2019-08-25 14:50:16 +0000 +++ src/wui/interactive_gamebase.h 2019-08-28 20:08:47 +0000 @@ -38,17 +38,14 @@ public: InteractiveGameBase(Widelands::Game&, Section& global_s, - PlayerType pt = NONE, - bool multiplayer = false); + PlayerType pt, + bool multiplayer, + ChatProvider* chat_provider); ~InteractiveGameBase() override { } Widelands::Game* get_game() const; Widelands::Game& game() const; - // Chat messages - void set_chat_provider(ChatProvider&); - ChatProvider* get_chat_provider(); - virtual bool can_see(Widelands::PlayerNumber) const = 0; virtual bool can_act(Widelands::PlayerNumber) const = 0; virtual Widelands::PlayerNumber player_number() const = 0; @@ -90,7 +87,7 @@ protected: // For referencing the items in showhidemenu_ - enum class ShowHideEntry { kBuildingSpaces, kCensus, kStatistics, kWorkareaOverlap }; + enum class ShowHideEntry { kBuildingSpaces, kCensus, kStatistics, kSoldierLevels, kWorkareaOverlap }; // Adds the mapviewmenu_ to the toolbar void add_main_menu(); @@ -100,6 +97,9 @@ // Adds the gamespeedmenu_ to the toolbar void add_gamespeed_menu(); + // Adds a chat toolbar button and registers the chat console window + void add_chat_ui(); + bool handle_key(bool down, SDL_Keysym code) override; void draw_overlay(RenderTarget&) override; @@ -119,6 +119,7 @@ } menu_windows_; ChatProvider* chat_provider_; + UI::UniqueWindow::Registry chat_; bool multiplayer_; PlayerType playertype_; === modified file 'src/wui/interactive_player.cc' --- src/wui/interactive_player.cc 2019-08-25 14:50:16 +0000 +++ src/wui/interactive_player.cc 2019-08-28 20:08:47 +0000 @@ -44,7 +44,6 @@ #include "wui/debugconsole.h" #include "wui/fieldaction.h" #include "wui/game_chat_menu.h" -#include "wui/game_main_menu_save_game.h" #include "wui/game_message_menu.h" #include "wui/game_objectives_menu.h" #include "wui/general_statistics_menu.h" @@ -81,28 +80,28 @@ } return brightness / 255.; } - // Remove statistics from the text to draw if the player does not match the map object's owner -TextToDraw filter_text_to_draw(TextToDraw text_to_draw, +InfoToDraw filter_info_to_draw(InfoToDraw info_to_draw, const Widelands::MapObject* object, const Widelands::Player& player) { - TextToDraw result = text_to_draw; + InfoToDraw result = info_to_draw; const Widelands::Player* owner = object->get_owner(); if (owner != nullptr && !player.see_all() && player.is_hostile(*owner)) { - result = removeFromTextToDraw(result, TextToDraw::kStatistics); + result = static_cast<InfoToDraw>(result & ~InfoToDraw::kStatistics); } return result; } -void draw_immovable_for_visible_field(const Widelands::EditorGameBase& egbase, - const FieldsToDraw::Field& field, - const float scale, - const TextToDraw text_to_draw, - const Widelands::Player& player, - RenderTarget* dst) { + +void draw_immovables_for_visible_field(const Widelands::EditorGameBase& egbase, + const FieldsToDraw::Field& field, + const float scale, + const InfoToDraw info_to_draw, + const Widelands::Player& player, + RenderTarget* dst) { Widelands::BaseImmovable* const imm = field.fcoords.field->get_immovable(); if (imm != nullptr && imm->get_positions(egbase).front() == field.fcoords) { - imm->draw(egbase.get_gametime(), filter_text_to_draw(text_to_draw, imm, player), + imm->draw(egbase.get_gametime(), filter_info_to_draw(info_to_draw, imm, player), field.rendertarget_pixel, field.fcoords, scale, dst); } } @@ -110,12 +109,12 @@ void draw_bobs_for_visible_field(const Widelands::EditorGameBase& egbase, const FieldsToDraw::Field& field, const float scale, - const TextToDraw text_to_draw, + const InfoToDraw info_to_draw, const Widelands::Player& player, RenderTarget* dst) { for (Widelands::Bob* bob = field.fcoords.field->get_first_bob(); bob; bob = bob->get_next_bob()) { - bob->draw(egbase, filter_text_to_draw(text_to_draw, bob, player), field.rendertarget_pixel, + bob->draw(egbase, filter_info_to_draw(info_to_draw, bob, player), field.rendertarget_pixel, field.fcoords, scale, dst); } } @@ -154,8 +153,9 @@ InteractivePlayer::InteractivePlayer(Widelands::Game& g, Section& global_s, Widelands::PlayerNumber const plyn, - bool const multiplayer) - : InteractiveGameBase(g, global_s, NONE, multiplayer), + bool const multiplayer, + ChatProvider* chat_provider) + : InteractiveGameBase(g, global_s, NONE, multiplayer, chat_provider), auto_roadbuild_mode_(global_s.get_bool("auto_roadbuild_mode", true)), flag_to_connect_(Widelands::Coords::null()), statisticsmenu_(toolbar(), @@ -183,12 +183,7 @@ toolbar()->add_space(15); if (multiplayer) { - toggle_chat_ = add_toolbar_button("wui/menus/chat", "chat", _("Chat"), &chat_, true); - chat_.open_window = [this] { - if (chat_provider_) { - GameChatMenu::create_chat_console(this, chat_, *chat_provider_); - } - }; + add_chat_ui(); toolbar()->add_space(15); } @@ -344,10 +339,6 @@ flag_to_connect_ = Widelands::Coords::null(); } } - if (is_multiplayer()) { - toggle_chat_->set_visible(chat_provider_); - toggle_chat_->set_enabled(chat_provider_); - } { char const* msg_icon = "images/wui/menus/message_old.png"; std::string msg_tooltip = _("Messages"); @@ -417,9 +408,9 @@ // Render stuff that belongs to the node. if (f->vision > 1) { - const auto text_to_draw = get_text_to_draw(); - draw_immovable_for_visible_field(gbase, *f, scale, text_to_draw, plr, dst); - draw_bobs_for_visible_field(gbase, *f, scale, text_to_draw, plr, dst); + const auto info_to_draw = get_info_to_draw(!given_map_view->is_animating()); + draw_immovables_for_visible_field(gbase, *f, scale, info_to_draw, plr, dst); + draw_bobs_for_visible_field(gbase, *f, scale, info_to_draw, plr, dst); } else if (f->vision == 1) { // We never show census or statistics for objects in the fog. draw_immovable_for_formerly_visible_field(*f, player_field, scale, dst); @@ -516,9 +507,6 @@ bool InteractivePlayer::handle_key(bool const down, SDL_Keysym const code) { if (down) { switch (code.sym) { - case SDLK_SPACE: - toggle_buildhelp(); - return true; case SDLK_i: menu_windows_.stats_stock.toggle(); @@ -536,10 +524,6 @@ encyclopedia_.toggle(); return true; - case SDLK_c: - set_display_flag(dfShowCensus, !get_display_flag(dfShowCensus)); - return true; - case SDLK_b: if (menu_windows_.stats_buildings.window == nullptr) { new BuildingStatisticsMenu(*this, menu_windows_.stats_buildings); @@ -558,13 +542,6 @@ } return true; - case SDLK_s: - if (code.mod & (KMOD_LCTRL | KMOD_RCTRL)) - new GameMainMenuSaveGame(*this, menu_windows_.savegame); - else - set_display_flag(dfShowStatistics, !get_display_flag(dfShowStatistics)); - return true; - case SDLK_w: set_display_flag(dfShowWorkareaOverlap, !get_display_flag(dfShowWorkareaOverlap)); return true; === modified file 'src/wui/interactive_player.h' --- src/wui/interactive_player.h 2019-08-25 14:50:16 +0000 +++ src/wui/interactive_player.h 2019-08-28 20:08:47 +0000 @@ -42,7 +42,8 @@ InteractivePlayer(Widelands::Game&, Section& global_s, Widelands::PlayerNumber, - bool multiplayer); + bool multiplayer, + ChatProvider* chat_provider = nullptr); bool can_see(Widelands::PlayerNumber) const override; bool can_act(Widelands::PlayerNumber) const override; @@ -96,7 +97,6 @@ bool auto_roadbuild_mode_; Widelands::Coords flag_to_connect_; - UI::Button* toggle_chat_; UI::Button* toggle_message_menu_; // Statistics menu on the toolbar === modified file 'src/wui/interactive_spectator.cc' --- src/wui/interactive_spectator.cc 2019-08-25 14:50:16 +0000 +++ src/wui/interactive_spectator.cc 2019-08-28 20:08:47 +0000 @@ -36,8 +36,9 @@ */ InteractiveSpectator::InteractiveSpectator(Widelands::Game& g, Section& global_s, - bool const multiplayer) - : InteractiveGameBase(g, global_s, OBSERVER, multiplayer) { + bool const multiplayer, + ChatProvider* chat_provider) + : InteractiveGameBase(g, global_s, OBSERVER, multiplayer, chat_provider) { add_main_menu(); add_toolbar_button("wui/menus/statistics_general", "general_stats", _("Statistics"), @@ -55,12 +56,7 @@ toolbar()->add_space(15); if (is_multiplayer()) { - add_toolbar_button("wui/menus/chat", "chat", _("Chat"), &chat_, true); - chat_.open_window = [this] { - if (chat_provider_) { - GameChatMenu::create_chat_console(this, chat_, *chat_provider_); - } - }; + add_chat_ui(); } finalize_toolbar(); @@ -95,7 +91,7 @@ const float scale = 1.f / given_map_view->view().zoom; const uint32_t gametime = the_game.get_gametime(); - const auto text_to_draw = get_text_to_draw(); + const auto info_to_draw = get_info_to_draw(!given_map_view->is_animating()); for (size_t idx = 0; idx < fields_to_draw->size(); ++idx) { const FieldsToDraw::Field& field = fields_to_draw->at(idx); @@ -103,12 +99,12 @@ Widelands::BaseImmovable* const imm = field.fcoords.field->get_immovable(); if (imm != nullptr && imm->get_positions(the_game).front() == field.fcoords) { - imm->draw(gametime, text_to_draw, field.rendertarget_pixel, field.fcoords, scale, dst); + imm->draw(gametime, info_to_draw, field.rendertarget_pixel, field.fcoords, scale, dst); } for (Widelands::Bob* bob = field.fcoords.field->get_first_bob(); bob; bob = bob->get_next_bob()) { - bob->draw(the_game, text_to_draw, field.rendertarget_pixel, field.fcoords, scale, dst); + bob->draw(the_game, info_to_draw, field.rendertarget_pixel, field.fcoords, scale, dst); } // Draw build help. @@ -190,23 +186,8 @@ * Global in-game keypresses: */ bool InteractiveSpectator::handle_key(bool const down, SDL_Keysym const code) { - if (down) + if (down) { switch (code.sym) { - case SDLK_SPACE: - toggle_buildhelp(); - return true; - - case SDLK_c: - set_display_flag(dfShowCensus, !get_display_flag(dfShowCensus)); - return true; - - case SDLK_s: - if (code.mod & (KMOD_LCTRL | KMOD_RCTRL)) { - new GameMainMenuSaveGame(*this, menu_windows_.savegame); - } else - set_display_flag(dfShowStatistics, !get_display_flag(dfShowStatistics)); - return true; - case SDLK_RETURN: case SDLK_KP_ENTER: if (chat_provider_) { @@ -219,6 +200,7 @@ default: break; } + } return InteractiveGameBase::handle_key(down, code); } === modified file 'src/wui/interactive_spectator.h' --- src/wui/interactive_spectator.h 2019-08-25 14:50:16 +0000 +++ src/wui/interactive_spectator.h 2019-08-28 20:08:47 +0000 @@ -38,7 +38,10 @@ * This class provides the UI, runs the game logic, etc. */ struct InteractiveSpectator : public InteractiveGameBase { - InteractiveSpectator(Widelands::Game&, Section& global_s, bool multiplayer = false); + InteractiveSpectator(Widelands::Game&, + Section& global_s, + bool multiplayer = false, + ChatProvider* chat_provider = nullptr); Widelands::Player* get_player() const override; @@ -54,8 +57,6 @@ bool can_act(Widelands::PlayerNumber) const override; Widelands::PlayerNumber player_number() const override; void node_action(const Widelands::NodeAndTriangle<>& node_and_triangle) override; - - UI::UniqueWindow::Registry chat_; }; #endif // end of include guard: WL_WUI_INTERACTIVE_SPECTATOR_H === modified file 'src/wui/soldierlist.cc' --- src/wui/soldierlist.cc 2019-05-26 17:21:15 +0000 +++ src/wui/soldierlist.cc 2019-08-28 20:08:47 +0000 @@ -44,7 +44,7 @@ constexpr uint32_t kMaxColumns = 6; constexpr uint32_t kAnimateSpeed = 300; ///< in pixels per second -constexpr uint32_t kIconBorder = 2; +constexpr int kIconBorder = 2; } // namespace @@ -105,8 +105,8 @@ uint32_t rows_; uint32_t cols_; - uint32_t icon_width_; - uint32_t icon_height_; + int icon_width_; + int icon_height_; int32_t last_animate_time_; }; @@ -296,7 +296,7 @@ continue; constexpr float kNoZoom = 1.f; - soldier->draw_info_icon(icon.pos + Vector2i(kIconBorder, kIconBorder), kNoZoom, false, &dst); + soldier->draw_info_icon(icon.pos + Vector2i(kIconBorder, kIconBorder), kNoZoom, Soldier::InfoMode::kInBuilding, InfoToDraw::kSoldierLevels, &dst); } }
_______________________________________________ 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