widelands-dev team mailing list archive
-
widelands-dev team
-
Mailing list archive
-
Message #11115
[Merge] lp:~widelands-dev/widelands/reduce_overlay_manager_use2 into lp:widelands
SirVer has proposed merging lp:~widelands-dev/widelands/reduce_overlay_manager_use2 into lp:widelands.
Commit message:
Further reduce the use of the FieldOverlayManager.
- Draw field selectors in the draw routine directly, not using the FieldOverlayManager.
- Draw work area preview markers in the draw routine directly, not using the FieldOverlayManager.
Requested reviews:
Widelands Developers (widelands-dev)
Related bugs:
Bug #1711394 in widelands: "Terrain tool no longer displays the selection on the triangles, but on the nodes"
https://bugs.launchpad.net/widelands/+bug/1711394
For more details, see:
https://code.launchpad.net/~widelands-dev/widelands/reduce_overlay_manager_use2/+merge/330125
--
Your team Widelands Developers is requested to review the proposed merge of lp:~widelands-dev/widelands/reduce_overlay_manager_use2 into lp:widelands.
=== modified file 'src/editor/editorinteractive.cc'
--- src/editor/editorinteractive.cc 2017-09-02 19:34:45 +0000
+++ src/editor/editorinteractive.cc 2017-09-03 13:04:48 +0000
@@ -43,6 +43,7 @@
#include "logic/map_objects/tribes/tribes.h"
#include "logic/map_objects/world/resource_description.h"
#include "logic/map_objects/world/world.h"
+#include "logic/maptriangleregion.h"
#include "logic/player.h"
#include "map_io/map_loader.h"
#include "map_io/widelands_map_loader.h"
@@ -274,6 +275,22 @@
starting_positions[map.get_starting_pos(i)] = i;
}
+ // Figure out which fields are currently under the selection.
+ std::set<Widelands::Coords> selected_nodes;
+ std::set<Widelands::TCoords<>> selected_triangles;
+ if (!get_sel_triangles()) {
+ Widelands::MapRegion<> mr(map, Widelands::Area<>(get_sel_pos().node, get_sel_radius()));
+ do {
+ selected_nodes.emplace(mr.location());
+ } while (mr.advance(map));
+ } else {
+ Widelands::MapTriangleRegion<> mr(
+ map, Widelands::Area<Widelands::TCoords<>>(get_sel_pos().triangle, get_sel_radius()));
+ do {
+ selected_triangles.emplace(mr.location());
+ } while (mr.advance(map));
+ }
+
const auto& world = ebase.world();
for (size_t idx = 0; idx < fields_to_draw->size(); ++idx) {
const FieldsToDraw::Field& field = fields_to_draw->at(idx);
@@ -291,12 +308,17 @@
}
}
- const auto blit_overlay = [&dst, &field, scale](const Image* pic, const Vector2i& hotspot) {
- dst.blitrect_scale(Rectf(field.rendertarget_pixel - hotspot.cast<float>() * scale,
+ const auto blit = [&dst, &field, scale](
+ const Image* pic, const Vector2f& position, const Vector2i& hotspot) {
+ dst.blitrect_scale(Rectf(position - hotspot.cast<float>() * scale,
pic->width() * scale, pic->height() * scale),
pic, Recti(0, 0, pic->width(), pic->height()), 1.f,
BlendMode::UseAlpha);
};
+ const auto blit_overlay = [&dst, &field, scale, &blit](
+ const Image* pic, const Vector2i& hotspot) {
+ blit(pic, field.rendertarget_pixel, hotspot);
+ };
// Draw resource overlay.
uint8_t const amount = field.fcoords.field->get_resources_amount();
@@ -322,6 +344,39 @@
constexpr int kStartingPosHotspotY = 55;
blit_overlay(player_image, Vector2i(player_image->width() / 2, kStartingPosHotspotY));
}
+
+ // Draw selection markers on the field.
+ if (selected_nodes.count(field.fcoords) > 0) {
+ const Image* pic = get_sel_picture();
+ blit_overlay(pic, Vector2i(pic->width() / 2, pic->height() / 2));
+ }
+
+ // Draw selection markers on the triangles.
+ if (field.all_neighbors_valid()) {
+ const FieldsToDraw::Field& rn = fields_to_draw->at(field.rn_index);
+ const FieldsToDraw::Field& brn = fields_to_draw->at(field.brn_index);
+ const FieldsToDraw::Field& bln = fields_to_draw->at(field.bln_index);
+ if (selected_triangles.count(
+ Widelands::TCoords<>(field.fcoords, Widelands::TriangleIndex::R))) {
+ const Vector2f tripos(
+ (field.rendertarget_pixel.x + rn.rendertarget_pixel.x + brn.rendertarget_pixel.x) /
+ 3.f,
+ (field.rendertarget_pixel.y + rn.rendertarget_pixel.y + brn.rendertarget_pixel.y) /
+ 3.f);
+ const Image* pic = get_sel_picture();
+ blit(pic, tripos, Vector2i(pic->width() / 2, pic->height() / 2));
+ }
+ if (selected_triangles.count(
+ Widelands::TCoords<>(field.fcoords, Widelands::TriangleIndex::D))) {
+ const Vector2f tripos(
+ (field.rendertarget_pixel.x + bln.rendertarget_pixel.x + brn.rendertarget_pixel.x) /
+ 3.f,
+ (field.rendertarget_pixel.y + bln.rendertarget_pixel.y + brn.rendertarget_pixel.y) /
+ 3.f);
+ const Image* pic = get_sel_picture();
+ blit(pic, tripos, Vector2i(pic->width() / 2, pic->height() / 2));
+ }
+ }
}
}
=== modified file 'src/logic/map_objects/tribes/building.h'
--- src/logic/map_objects/tribes/building.h 2017-08-09 17:55:34 +0000
+++ src/logic/map_objects/tribes/building.h 2017-09-03 13:04:48 +0000
@@ -155,6 +155,10 @@
virtual uint32_t get_conquers() const;
virtual uint32_t vision_range() const;
+ const WorkareaInfo& workarea_info() const { return workarea_info_; }
+
+ // TODO(sirver): This should not be public. It is mutated by other classes
+ // in many places.
WorkareaInfo workarea_info_;
bool suitability(const Map&, const FCoords&) const;
=== modified file 'src/logic/map_objects/tribes/workarea_info.h'
--- src/logic/map_objects/tribes/workarea_info.h 2017-01-25 18:55:59 +0000
+++ src/logic/map_objects/tribes/workarea_info.h 2017-09-03 13:04:48 +0000
@@ -39,11 +39,8 @@
* See LuaBuildingDescription::get_workarea_radius, InteractiveBase::show_work_area
*/
-// TODO(Hasi50): LuaBuildingDescription::get_workarea_radius will only give us the very first
-// size found, which seems to be correct but depends on the std:map implementation
-//
-// We could just use a unit8 as base for the map?
-// We should document (as const) the expected stings.
+// TODO(Hasi50): We could just use a unit8 as base for the map? We should
+// document (as const) the expected stings.
using WorkareaInfo = std::map<uint32_t, std::set<std::string>>;
=== modified file 'src/logic/maptriangleregion.cc'
--- src/logic/maptriangleregion.cc 2017-08-31 10:55:45 +0000
+++ src/logic/maptriangleregion.cc 2017-09-03 13:04:48 +0000
@@ -144,7 +144,6 @@
template <>
MapTriangleRegion<TCoords<FCoords>>::MapTriangleRegion(const Map& map, Area<TCoords<FCoords>> area)
: radius_is_odd_(area.radius & 1), location_(area) {
- assert(area.t == TriangleIndex::R || area.t == TriangleIndex::D);
const uint16_t radius_plus_1 = area.radius + 1;
const uint16_t half_radius_rounded_down = area.radius / 2;
row_length_ = radius_plus_1;
=== modified file 'src/logic/widelands_geometry.h'
--- src/logic/widelands_geometry.h 2017-09-02 19:51:07 +0000
+++ src/logic/widelands_geometry.h 2017-09-03 13:04:48 +0000
@@ -126,6 +126,9 @@
bool operator!=(const TCoords& other) const {
return !(*this == other);
}
+ bool operator<(const TCoords& other) const {
+ return std::forward_as_tuple(node, t) < std::forward_as_tuple(other.node, other.t);
+ }
CoordsType node;
TriangleIndex t;
=== modified file 'src/scripting/lua_map.cc'
--- src/scripting/lua_map.cc 2017-08-31 15:22:21 +0000
+++ src/scripting/lua_map.cc 2017-09-03 13:04:48 +0000
@@ -2133,7 +2133,7 @@
nil in case bulding has no workareas
*/
int LuaBuildingDescription::get_workarea_radius(lua_State* L) {
- const WorkareaInfo& workareaInfo = get()->workarea_info_;
+ const WorkareaInfo& workareaInfo = get()->workarea_info();
if (!workareaInfo.empty()) {
lua_pushinteger(L, workareaInfo.begin()->first);
} else {
=== modified file 'src/wui/buildingwindow.cc'
--- src/wui/buildingwindow.cc 2017-08-17 15:34:45 +0000
+++ src/wui/buildingwindow.cc 2017-09-03 13:04:48 +0000
@@ -53,7 +53,8 @@
is_dying_(false),
parent_(&parent),
building_(b),
- workarea_overlay_id_(0),
+ building_position_(b.get_position()),
+ showing_workarea_(false),
avoid_fastclick_(avoid_fastclick),
expeditionbtn_(nullptr) {
buildingnotes_subscriber_ = Notifications::subscribe<Widelands::NoteBuilding>(
@@ -61,9 +62,7 @@
}
BuildingWindow::~BuildingWindow() {
- if (workarea_overlay_id_) {
- igbase()->mutable_field_overlay_manager()->remove_overlay(workarea_overlay_id_);
- }
+ hide_workarea();
}
void BuildingWindow::on_building_note(const Widelands::NoteBuilding& note) {
@@ -77,7 +76,7 @@
break;
// The building is no more
case Widelands::NoteBuilding::Action::kStartWarp:
- igbase()->add_wanted_building_window(building().get_position(), get_pos(), is_minimal());
+ igbase()->add_wanted_building_window(building_position_, get_pos(), is_minimal());
FALLS_THROUGH;
case Widelands::NoteBuilding::Action::kDeleted:
die();
@@ -116,6 +115,7 @@
// Stop everybody from thinking to avoid segfaults
void BuildingWindow::die() {
is_dying_ = true;
+ hide_workarea();
set_thinks(false);
vbox_.reset(nullptr);
UniqueWindow::die();
@@ -287,13 +287,13 @@
}
if (can_see) {
- WorkareaInfo wa_info;
+ const WorkareaInfo* wa_info;
if (upcast(Widelands::ConstructionSite, csite, &building_)) {
- wa_info = csite->building().workarea_info_;
+ wa_info = &csite->building().workarea_info();
} else {
- wa_info = building_.descr().workarea_info_;
+ wa_info = &building_.descr().workarea_info();
}
- if (!wa_info.empty()) {
+ if (!wa_info->empty()) {
toggle_workarea_ = new UI::Button(
capsbuttons, "workarea", 0, 0, 34, 34, g_gr->images().get("images/ui_basic/but4.png"),
g_gr->images().get("images/wui/overlays/workarea123.png"), _("Hide work area"));
@@ -419,26 +419,27 @@
===============
*/
void BuildingWindow::act_debug() {
- show_field_debug(*igbase(), igbase()->game().map().get_fcoords(building_.get_position()));
+ show_field_debug(*igbase(), igbase()->game().map().get_fcoords(building_position_));
}
/**
* Show the building's workarea (if it has one).
*/
void BuildingWindow::show_workarea() {
- if (workarea_overlay_id_) {
+ if (showing_workarea_) {
return; // already shown, nothing to be done
}
- WorkareaInfo workarea_info;
+ const WorkareaInfo* workarea_info;
if (upcast(Widelands::ConstructionSite, csite, &building_)) {
- workarea_info = csite->building().workarea_info_;
+ workarea_info = &csite->building().workarea_info();
} else {
- workarea_info = building_.descr().workarea_info_;
+ workarea_info = &building_.descr().workarea_info();
}
- if (workarea_info.empty()) {
+ if (workarea_info->empty()) {
return;
}
- workarea_overlay_id_ = igbase()->show_work_area(workarea_info, building_.get_position());
+ igbase()->show_work_area(*workarea_info, building_position_);
+ showing_workarea_ = true;
configure_workarea_button();
}
@@ -447,10 +448,9 @@
* Hide the workarea from view.
*/
void BuildingWindow::hide_workarea() {
- if (workarea_overlay_id_) {
- igbase()->hide_work_area(workarea_overlay_id_);
- workarea_overlay_id_ = 0;
-
+ if (showing_workarea_) {
+ igbase()->hide_work_area(building_position_);
+ showing_workarea_ = false;
configure_workarea_button();
}
}
@@ -460,7 +460,7 @@
*/
void BuildingWindow::configure_workarea_button() {
if (toggle_workarea_) {
- if (workarea_overlay_id_) {
+ if (showing_workarea_) {
toggle_workarea_->set_tooltip(_("Hide work area"));
toggle_workarea_->set_perm_pressed(true);
} else {
@@ -471,7 +471,7 @@
}
void BuildingWindow::toggle_workarea() {
- if (workarea_overlay_id_) {
+ if (showing_workarea_) {
hide_workarea();
} else {
show_workarea();
@@ -491,7 +491,7 @@
* for the corresponding button.
*/
void BuildingWindow::clicked_goto() {
- igbase()->map_view()->scroll_to_field(building().get_position(), MapView::Transition::Smooth);
+ igbase()->map_view()->scroll_to_field(building_position_, MapView::Transition::Smooth);
}
void BuildingWindow::update_expedition_button(bool expedition_was_canceled) {
=== modified file 'src/wui/buildingwindow.h'
--- src/wui/buildingwindow.h 2017-06-06 05:37:57 +0000
+++ src/wui/buildingwindow.h 2017-09-03 13:04:48 +0000
@@ -90,11 +90,21 @@
bool is_dying_;
private:
+ // Actions performed when a NoteBuilding is received.
+ void on_building_note(const Widelands::NoteBuilding& note);
+
+ // For ports only.
+ void update_expedition_button(bool expedition_was_canceled);
+
InteractiveGameBase* parent_;
- /// Actions performed when a NoteBuilding is received.
- void on_building_note(const Widelands::NoteBuilding& note);
+
Widelands::Building& building_;
+ // We require this to unregister overlays when we are closed. Since the
+ // building might have been destroyed by then we have to keep a copy of its
+ // position around.
+ const Widelands::Coords building_position_;
+
std::unique_ptr<UI::Box> vbox_;
UI::TabPanel* tabs_;
@@ -107,12 +117,9 @@
Widelands::PlayerNumber capscache_player_number_;
bool caps_setup_;
- FieldOverlayManager::OverlayId workarea_overlay_id_;
+ bool showing_workarea_;
bool avoid_fastclick_;
- // For ports only.
- void update_expedition_button(bool expedition_was_canceled);
-
UI::Button* expeditionbtn_;
std::unique_ptr<Notifications::Subscriber<Widelands::NoteExpeditionCanceled>>
expedition_canceled_subscriber_;
=== modified file 'src/wui/field_overlay_manager.h'
--- src/wui/field_overlay_manager.h 2017-08-28 13:37:51 +0000
+++ src/wui/field_overlay_manager.h 2017-09-03 13:04:48 +0000
@@ -53,7 +53,6 @@
// drawn below the buildhelp, everything higher above.
enum class OverlayLevel {
kWorkAreaPreview = 0,
- kSelection = 7,
kRoadBuildSlope = 8,
};
=== modified file 'src/wui/fieldaction.cc'
--- src/wui/fieldaction.cc 2017-08-30 10:29:46 +0000
+++ src/wui/fieldaction.cc 2017-09-03 13:04:48 +0000
@@ -196,14 +196,13 @@
Widelands::Player* player_;
const Widelands::Map& map_;
- FieldOverlayManager& field_overlay_manager_;
Widelands::FCoords node_;
UI::TabPanel tabpanel_;
bool fastclick_; // if true, put the mouse over first button in first tab
uint32_t best_tab_;
- FieldOverlayManager::OverlayId workarea_preview_overlay_id_;
+ bool showing_workarea_preview_;
/// Variables to use with attack dialog.
AttackBox* attack_box_;
@@ -247,20 +246,19 @@
: UI::UniqueWindow(ib, "field_action", registry, 68, 34, _("Action")),
player_(plr),
map_(ib->egbase().map()),
- field_overlay_manager_(*ib->mutable_field_overlay_manager()),
node_(ib->get_sel_pos().node, &map_[ib->get_sel_pos().node]),
tabpanel_(this, g_gr->images().get("images/ui_basic/but1.png")),
fastclick_(true),
best_tab_(0),
- workarea_preview_overlay_id_(0),
+ showing_workarea_preview_(false),
attack_box_(nullptr) {
ib->set_sel_freeze(true);
set_center_panel(&tabpanel_);
}
FieldActionWindow::~FieldActionWindow() {
- if (workarea_preview_overlay_id_)
- field_overlay_manager_.remove_overlay(workarea_preview_overlay_id_);
+ if (showing_workarea_preview_)
+ ibase().hide_work_area(node_);
ibase().set_sel_freeze(false);
delete attack_box_;
}
@@ -685,17 +683,18 @@
}
void FieldActionWindow::building_icon_mouse_out(Widelands::DescriptionIndex) {
- if (workarea_preview_overlay_id_) {
- field_overlay_manager_.remove_overlay(workarea_preview_overlay_id_);
- workarea_preview_overlay_id_ = 0;
+ if (showing_workarea_preview_) {
+ ibase().hide_work_area(node_);
+ showing_workarea_preview_ = false;
}
}
void FieldActionWindow::building_icon_mouse_in(const Widelands::DescriptionIndex idx) {
- if (ibase().show_workarea_preview_ && !workarea_preview_overlay_id_) {
+ if (ibase().show_workarea_preview_ && !showing_workarea_preview_) {
const WorkareaInfo& workarea_info =
- player_->tribe().get_building_descr(Widelands::DescriptionIndex(idx))->workarea_info_;
- workarea_preview_overlay_id_ = ibase().show_work_area(workarea_info, node_);
+ player_->tribe().get_building_descr(Widelands::DescriptionIndex(idx))->workarea_info();
+ ibase().show_work_area(workarea_info, node_);
+ showing_workarea_preview_ = true;
}
}
=== modified file 'src/wui/interactive_base.cc'
--- src/wui/interactive_base.cc 2017-09-02 19:36:19 +0000
+++ src/wui/interactive_base.cc 2017-09-03 13:04:48 +0000
@@ -151,44 +151,20 @@
void InteractiveBase::set_sel_pos(Widelands::NodeAndTriangle<> const center) {
const Map& map = egbase().map();
-
- // Remove old sel pointer
- if (sel_.jobid)
- field_overlay_manager_->remove_overlay(sel_.jobid);
- const FieldOverlayManager::OverlayId jobid = sel_.jobid =
- field_overlay_manager_->next_overlay_id();
-
sel_.pos = center;
- // register sel overlay position
- if (sel_.triangles) {
- assert(center.triangle.t == Widelands::TriangleIndex::D ||
- center.triangle.t == Widelands::TriangleIndex::R);
- Widelands::MapTriangleRegion<> mr(map, Area<TCoords<>>(center.triangle, sel_.radius));
- do
- field_overlay_manager_->register_overlay(
- mr.location().node, sel_.pic, OverlayLevel::kSelection, Vector2i::invalid(), jobid);
- while (mr.advance(map));
- } else {
- Widelands::MapRegion<> mr(map, Area<>(center.node, sel_.radius));
- do
- field_overlay_manager_->register_overlay(
- mr.location(), sel_.pic, OverlayLevel::kSelection, Vector2i::invalid(), jobid);
- while (mr.advance(map));
- if (upcast(InteractiveGameBase const, igbase, this))
- if (upcast(Widelands::ProductionSite, productionsite, map[center.node].get_immovable())) {
- if (upcast(InteractivePlayer const, iplayer, igbase)) {
- const Widelands::Player& player = iplayer->player();
- if (!player.see_all() &&
- (1 >= player.vision(Widelands::Map::get_index(center.node, map.get_width())) ||
- player.is_hostile(*productionsite->get_owner())))
- return set_tooltip("");
- }
- set_tooltip(
- productionsite->info_string(Widelands::Building::InfoStringFormat::kTooltip));
- return;
+ if (upcast(InteractiveGameBase const, igbase, this))
+ if (upcast(Widelands::ProductionSite, productionsite, map[center.node].get_immovable())) {
+ if (upcast(InteractivePlayer const, iplayer, igbase)) {
+ const Widelands::Player& player = iplayer->player();
+ if (!player.see_all() &&
+ (1 >= player.vision(Widelands::Map::get_index(center.node, map.get_width())) ||
+ player.is_hostile(*productionsite->get_owner())))
+ return set_tooltip("");
}
- }
+ set_tooltip(productionsite->info_string(Widelands::Building::InfoStringFormat::kTooltip));
+ return;
+ }
set_tooltip("");
}
@@ -263,48 +239,52 @@
}
// Show the given workareas at the given coords and returns the overlay job id associated
-FieldOverlayManager::OverlayId InteractiveBase::show_work_area(const WorkareaInfo& workarea_info,
- Widelands::Coords coords) {
- const uint8_t workareas_nrs = workarea_info.size();
- WorkareaInfo::size_type wa_index;
- switch (workareas_nrs) {
- case 0:
- return 0; // no workarea
- case 1:
- wa_index = 5;
- break;
- case 2:
- wa_index = 3;
- break;
- case 3:
- wa_index = 0;
- break;
- default:
- throw wexception("Encountered unexpected WorkareaInfo size %i", workareas_nrs);
- }
- const Widelands::Map& map = egbase_.map();
- FieldOverlayManager::OverlayId overlay_id = field_overlay_manager_->next_overlay_id();
-
- Widelands::HollowArea<> hollow_area(Widelands::Area<>(coords, 0), 0);
-
- // Iterate through the work areas, from building to its enhancement
- WorkareaInfo::const_iterator it = workarea_info.begin();
- for (; it != workarea_info.end(); ++it) {
- hollow_area.radius = it->first;
- Widelands::MapHollowRegion<> mr(map, hollow_area);
- do
- field_overlay_manager_->register_overlay(mr.location(), workarea_pics_[wa_index],
- OverlayLevel::kWorkAreaPreview,
- Vector2i::invalid(), overlay_id);
- while (mr.advance(map));
- wa_index++;
- hollow_area.hole_radius = hollow_area.radius;
- }
- return overlay_id;
-}
-
-void InteractiveBase::hide_work_area(FieldOverlayManager::OverlayId overlay_id) {
- field_overlay_manager_->remove_overlay(overlay_id);
+void InteractiveBase::show_work_area(const WorkareaInfo& workarea_info, Widelands::Coords coords) {
+ work_area_previews_[coords] = &workarea_info;
+}
+
+std::map<Coords, const Image*> InteractiveBase::get_work_area_overlays(const Widelands::Map& map) const {
+ std::map<Coords, const Image*> result;
+ for (const auto& pair : work_area_previews_) {
+ const Coords& coords = pair.first;
+ const WorkareaInfo* workarea_info = pair.second;
+ WorkareaInfo::size_type wa_index;
+ switch (workarea_info->size()) {
+ case 0:
+ continue; // no workarea
+ case 1:
+ wa_index = 5;
+ break;
+ case 2:
+ wa_index = 3;
+ break;
+ case 3:
+ wa_index = 0;
+ break;
+ default:
+ throw wexception(
+ "Encountered unexpected WorkareaInfo size %i", static_cast<int>(workarea_info->size()));
+ }
+
+ Widelands::HollowArea<> hollow_area(Widelands::Area<>(coords, 0), 0);
+
+ // Iterate through the work areas, from building to its enhancement
+ WorkareaInfo::const_iterator it = workarea_info->begin();
+ for (; it != workarea_info->end(); ++it) {
+ hollow_area.radius = it->first;
+ Widelands::MapHollowRegion<> mr(map, hollow_area);
+ do {
+ result[mr.location()] = workarea_pics_[wa_index];
+ } while (mr.advance(map));
+ wa_index++;
+ hollow_area.hole_radius = hollow_area.radius;
+ }
+ }
+ return result;
+}
+
+void InteractiveBase::hide_work_area(const Widelands::Coords& coords) {
+ work_area_previews_.erase(coords);
}
/**
=== modified file 'src/wui/interactive_base.h'
--- src/wui/interactive_base.h 2017-09-02 19:36:19 +0000
+++ src/wui/interactive_base.h 2017-09-03 13:04:48 +0000
@@ -75,9 +75,9 @@
// TODO(sirver): This should be private.
bool show_workarea_preview_;
- FieldOverlayManager::OverlayId show_work_area(const WorkareaInfo& workarea_info,
+ void show_work_area(const WorkareaInfo& workarea_info,
Widelands::Coords coords);
- void hide_work_area(FieldOverlayManager::OverlayId overlay_id);
+ void hide_work_area(const Widelands::Coords& coords);
// point of view for drawing
virtual Widelands::Player* get_player() const = 0;
@@ -198,6 +198,7 @@
void unset_sel_picture();
void set_sel_picture(const Image* image);
+ const Image* get_sel_picture() { return sel_.pic; }
void adjust_toolbar_position() {
toolbar_.set_pos(Vector2i((get_inner_w() - toolbar_.get_w()) >> 1, get_inner_h() - 34));
}
@@ -213,6 +214,10 @@
// Returns the information which overlay text should currently be drawn.
TextToDraw get_text_to_draw() const;
+ // Returns the current overlays for the work area previews.
+ std::map<Widelands::Coords, const Image*>
+ get_work_area_overlays(const Widelands::Map& map) const;
+
private:
int32_t stereo_position(Widelands::Coords position_map);
void resize_chat_overlay();
@@ -239,45 +244,49 @@
uint32_t radius;
const Image* pic;
FieldOverlayManager::OverlayId jobid;
- } sel_;
-
- MapView map_view_;
- ChatOverlay* chat_overlay_;
-
- // These get collected by add_toolbar_button
- // so we can call unassign_toggle_button on them in the destructor.
- std::vector<UI::UniqueWindow::Registry> registries_;
-
- UI::Box toolbar_;
- // No unique_ptr on purpose: 'minimap_' is a UniqueWindow, its parent will
- // delete it.
- MiniMap* minimap_;
- MiniMap::Registry minimap_registry_;
- QuickNavigation quick_navigation_;
-
- std::unique_ptr<FieldOverlayManager> field_overlay_manager_;
-
- // The roads that are displayed while a road is being build. They are not
- // yet logically in the game, but need to be displayed for the user as
- // visual guide. The data type is the same as for Field::road.
- std::map<Widelands::Coords, uint8_t> road_building_preview_;
-
- std::unique_ptr<Notifications::Subscriber<GraphicResolutionChanged>>
- graphic_resolution_changed_subscriber_;
- std::unique_ptr<Notifications::Subscriber<NoteSound>> sound_subscriber_;
- Widelands::EditorGameBase& egbase_;
- uint32_t display_flags_;
- uint32_t lastframe_; // system time (milliseconds)
- uint32_t frametime_; // in millseconds
- uint32_t avg_usframetime_; // in microseconds!
-
- FieldOverlayManager::OverlayId road_buildhelp_overlay_jobid_;
- Widelands::CoordPath* buildroad_; // path for the new road
- Widelands::PlayerNumber road_build_player_;
-
- UI::UniqueWindow::Registry debugconsole_;
- std::unique_ptr<UniqueWindowHandler> unique_window_handler_;
- std::vector<const Image*> workarea_pics_;
+ } sel_;
+
+ MapView map_view_;
+ ChatOverlay* chat_overlay_;
+
+ // These get collected by add_toolbar_button
+ // so we can call unassign_toggle_button on them in the destructor.
+ std::vector<UI::UniqueWindow::Registry> registries_;
+
+ UI::Box toolbar_;
+ // No unique_ptr on purpose: 'minimap_' is a UniqueWindow, its parent will
+ // delete it.
+ MiniMap* minimap_;
+ MiniMap::Registry minimap_registry_;
+ QuickNavigation quick_navigation_;
+
+ std::unique_ptr<FieldOverlayManager> field_overlay_manager_;
+
+ // The currently enabled work area previews. They are keyed by the
+ // coordinate that the building that shows the work area is positioned.
+ std::map<Widelands::Coords, const WorkareaInfo*> work_area_previews_;
+
+ // The roads that are displayed while a road is being build. They are not
+ // yet logically in the game, but need to be displayed for the user as
+ // visual guide. The data type is the same as for Field::road.
+ std::map<Widelands::Coords, uint8_t> road_building_preview_;
+
+ std::unique_ptr<Notifications::Subscriber<GraphicResolutionChanged>>
+ graphic_resolution_changed_subscriber_;
+ std::unique_ptr<Notifications::Subscriber<NoteSound>> sound_subscriber_;
+ Widelands::EditorGameBase& egbase_;
+ uint32_t display_flags_;
+ uint32_t lastframe_; // system time (milliseconds)
+ uint32_t frametime_; // in millseconds
+ uint32_t avg_usframetime_; // in microseconds!
+
+ FieldOverlayManager::OverlayId road_buildhelp_overlay_jobid_;
+ Widelands::CoordPath* buildroad_; // path for the new road
+ Widelands::PlayerNumber road_build_player_;
+
+ UI::UniqueWindow::Registry debugconsole_;
+ std::unique_ptr<UniqueWindowHandler> unique_window_handler_;
+ std::vector<const Image*> workarea_pics_;
};
#endif // end of include guard: WL_WUI_INTERACTIVE_BASE_H
=== modified file 'src/wui/interactive_player.cc'
--- src/wui/interactive_player.cc 2017-09-02 19:34:45 +0000
+++ src/wui/interactive_player.cc 2017-09-03 13:04:48 +0000
@@ -320,6 +320,10 @@
}
void InteractivePlayer::draw_map_view(MapView* given_map_view, RenderTarget* dst) {
+ // In-game, selection can never be on triangles or have a radius.
+ assert(get_sel_radius() == 0);
+ assert(!get_sel_triangles());
+
const Widelands::Player& plr = player();
const auto& gbase = egbase();
const Widelands::Map& map = gbase.map();
@@ -327,6 +331,7 @@
auto* fields_to_draw = given_map_view->draw_terrain(gbase, dst);
const auto& roads_preview = road_building_preview();
+ const std::map<Widelands::Coords, const Image*> work_area_overlays = get_work_area_overlays(map);
for (size_t idx = 0; idx < fields_to_draw->size(); ++idx) {
auto* f = fields_to_draw->mutable_field(idx);
@@ -349,9 +354,11 @@
}
// Add road building overlays if applicable.
- const auto it = roads_preview.find(f->fcoords);
- if (it != roads_preview.end()) {
- f->roads |= it->second;
+ {
+ const auto it = roads_preview.find(f->fcoords);
+ if (it != roads_preview.end()) {
+ f->roads |= it->second;
+ }
}
const float scale = 1.f / given_map_view->view().zoom;
@@ -367,15 +374,30 @@
draw_immovables_for_formerly_visible_field(*f, player_field, scale, dst);
}
+ const auto blit_overlay = [dst, f, scale](const Image* pic, const Vector2i& hotspot) {
+ dst->blitrect_scale(Rectf(f->rendertarget_pixel - hotspot.cast<float>() * scale,
+ pic->width() * scale, pic->height() * scale),
+ pic, Recti(0, 0, pic->width(), pic->height()), 1.f,
+ BlendMode::UseAlpha);
+ };
+
+ // Draw work area previews.
+ {
+ const auto it = work_area_overlays.find(f->fcoords);
+ if (it != work_area_overlays.end()) {
+ blit_overlay(it->second, Vector2i(it->second->width() / 2, it->second->height() / 2));
+ }
+ }
+
// TODO(sirver): Do not use the field_overlay_manager, instead draw the
// overlays we are interested in here directly.
- field_overlay_manager().foreach_overlay(
- f->fcoords, [dst, f, scale](const Image* pic, const Vector2i& hotspot) {
- dst->blitrect_scale(Rectf(f->rendertarget_pixel - hotspot.cast<float>() * scale,
- pic->width() * scale, pic->height() * scale),
- pic, Recti(0, 0, pic->width(), pic->height()), 1.f,
- BlendMode::UseAlpha);
- });
+ field_overlay_manager().foreach_overlay(f->fcoords, blit_overlay);
+
+ // Blit the selection marker.
+ if (f->fcoords == get_sel_pos().node) {
+ const Image* pic = get_sel_picture();
+ blit_overlay(pic, Vector2i(pic->width() / 2, pic->height() / 2));
+ }
}
}
=== modified file 'src/wui/interactive_spectator.cc'
--- src/wui/interactive_spectator.cc 2017-08-28 12:44:08 +0000
+++ src/wui/interactive_spectator.cc 2017-09-03 13:04:48 +0000
@@ -111,6 +111,9 @@
void InteractiveSpectator::draw_map_view(MapView* given_map_view, RenderTarget* dst) {
// A spectator cannot build roads.
assert(road_building_preview().empty());
+ // In-game, selection can never be on triangles or have a radius.
+ assert(get_sel_radius() == 0);
+ assert(!get_sel_triangles());
const auto& gbase = egbase();
auto* fields_to_draw = given_map_view->draw_terrain(gbase, dst);
@@ -118,6 +121,8 @@
const uint32_t gametime = gbase.get_gametime();
const auto text_to_draw = get_text_to_draw();
+ const std::map<Widelands::Coords, const Image*> work_area_overlays =
+ get_work_area_overlays(gbase.map());
for (size_t idx = 0; idx < fields_to_draw->size(); ++idx) {
const FieldsToDraw::Field& field = fields_to_draw->at(idx);
@@ -133,15 +138,28 @@
bob->draw(gbase, text_to_draw, field.rendertarget_pixel, scale, dst);
}
+ const auto blit_overlay = [dst, &field, scale](const Image* pic, const Vector2i& hotspot) {
+ dst->blitrect_scale(Rectf(field.rendertarget_pixel - hotspot.cast<float>() * scale,
+ pic->width() * scale, pic->height() * scale),
+ pic, Recti(0, 0, pic->width(), pic->height()), 1.f,
+ BlendMode::UseAlpha);
+ };
+
+ const auto it = work_area_overlays.find(field.fcoords);
+ if (it != work_area_overlays.end()) {
+ const Image* pic = it->second;
+ blit_overlay(pic, Vector2i(pic->width() / 2, pic->height() / 2));
+ }
+
// TODO(sirver): Do not use the field_overlay_manager, instead draw the
// overlays we are interested in here directly.
- field_overlay_manager().foreach_overlay(
- field.fcoords, [dst, &field, scale](const Image* pic, const Vector2i& hotspot) {
- dst->blitrect_scale(Rectf(field.rendertarget_pixel - hotspot.cast<float>() * scale,
- pic->width() * scale, pic->height() * scale),
- pic, Recti(0, 0, pic->width(), pic->height()), 1.f,
- BlendMode::UseAlpha);
- });
+ field_overlay_manager().foreach_overlay(field.fcoords, blit_overlay);
+
+ // Blit the selection marker.
+ if (field.fcoords == get_sel_pos().node) {
+ const Image* pic = get_sel_picture();
+ blit_overlay(pic, Vector2i(pic->width() / 2, pic->height() / 2));
+ }
}
}
Follow ups