Merge lp:~widelands-dev/widelands/reduce_overlay_manager_use2 into lp:widelands

Proposed by SirVer
Status: Merged
Merged at revision: 8449
Proposed branch: lp:~widelands-dev/widelands/reduce_overlay_manager_use2
Merge into: lp:widelands
Diff against target: 838 lines (+278/-186)
14 files modified
src/editor/editorinteractive.cc (+57/-2)
src/logic/map_objects/tribes/building.h (+4/-0)
src/logic/map_objects/tribes/workarea_info.h (+2/-5)
src/logic/maptriangleregion.cc (+0/-1)
src/logic/widelands_geometry.h (+3/-0)
src/scripting/lua_map.cc (+1/-1)
src/wui/buildingwindow.cc (+23/-23)
src/wui/buildingwindow.h (+13/-6)
src/wui/field_overlay_manager.h (+0/-1)
src/wui/fieldaction.cc (+11/-12)
src/wui/interactive_base.cc (+57/-77)
src/wui/interactive_base.h (+50/-41)
src/wui/interactive_player.cc (+32/-10)
src/wui/interactive_spectator.cc (+25/-7)
To merge this branch: bzr merge lp:~widelands-dev/widelands/reduce_overlay_manager_use2
Reviewer Review Type Date Requested Status
kaputtnik (community) testing Approve
GunChleoc Approve
Review via email: mp+330125@code.launchpad.net

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.

To post a comment you must log in.
Revision history for this message
bunnybot (widelandsofficial) wrote :

Continuous integration builds have changed state:

Travis build 2649. State: passed. Details: https://travis-ci.org/widelands/widelands/builds/271391659.
Appveyor build 2471. State: success. Details: https://ci.appveyor.com/project/widelands-dev/widelands/build/_widelands_dev_widelands_reduce_overlay_manager_use2-2471.

Revision history for this message
GunChleoc (gunchleoc) wrote :

Code LGTM, 2 nits.

Needs testing.

review: Approve
Revision history for this message
SirVer (sirver) wrote :

Fixed the typo and answered the question.

Revision history for this message
SirVer (sirver) wrote :

friendly ping on testing? I have a few more dependant branches in the pipe and I'll soon not have much time for Widelands again.

Revision history for this message
GunChleoc (gunchleoc) wrote :

Sorry, I'm mostly without internet this month.

Thanks for your reply, I overlooked that one. Code is good :)

Revision history for this message
kaputtnik (franku) wrote :

I have tested this branch. Don't know where to have a special look at though.

Editor test: Placing terrains/critters/immovables/
Play test: Workarea LGTM.

review: Approve (testing)
Revision history for this message
GunChleoc (gunchleoc) wrote :

Thanks!

@bunnybot merge

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'src/editor/editorinteractive.cc'
2--- src/editor/editorinteractive.cc 2017-09-02 19:34:45 +0000
3+++ src/editor/editorinteractive.cc 2017-09-07 18:19:58 +0000
4@@ -43,6 +43,7 @@
5 #include "logic/map_objects/tribes/tribes.h"
6 #include "logic/map_objects/world/resource_description.h"
7 #include "logic/map_objects/world/world.h"
8+#include "logic/maptriangleregion.h"
9 #include "logic/player.h"
10 #include "map_io/map_loader.h"
11 #include "map_io/widelands_map_loader.h"
12@@ -274,6 +275,22 @@
13 starting_positions[map.get_starting_pos(i)] = i;
14 }
15
16+ // Figure out which fields are currently under the selection.
17+ std::set<Widelands::Coords> selected_nodes;
18+ std::set<Widelands::TCoords<>> selected_triangles;
19+ if (!get_sel_triangles()) {
20+ Widelands::MapRegion<> mr(map, Widelands::Area<>(get_sel_pos().node, get_sel_radius()));
21+ do {
22+ selected_nodes.emplace(mr.location());
23+ } while (mr.advance(map));
24+ } else {
25+ Widelands::MapTriangleRegion<> mr(
26+ map, Widelands::Area<Widelands::TCoords<>>(get_sel_pos().triangle, get_sel_radius()));
27+ do {
28+ selected_triangles.emplace(mr.location());
29+ } while (mr.advance(map));
30+ }
31+
32 const auto& world = ebase.world();
33 for (size_t idx = 0; idx < fields_to_draw->size(); ++idx) {
34 const FieldsToDraw::Field& field = fields_to_draw->at(idx);
35@@ -291,12 +308,17 @@
36 }
37 }
38
39- const auto blit_overlay = [&dst, &field, scale](const Image* pic, const Vector2i& hotspot) {
40- dst.blitrect_scale(Rectf(field.rendertarget_pixel - hotspot.cast<float>() * scale,
41+ const auto blit = [&dst, &field, scale](
42+ const Image* pic, const Vector2f& position, const Vector2i& hotspot) {
43+ dst.blitrect_scale(Rectf(position - hotspot.cast<float>() * scale,
44 pic->width() * scale, pic->height() * scale),
45 pic, Recti(0, 0, pic->width(), pic->height()), 1.f,
46 BlendMode::UseAlpha);
47 };
48+ const auto blit_overlay = [&dst, &field, scale, &blit](
49+ const Image* pic, const Vector2i& hotspot) {
50+ blit(pic, field.rendertarget_pixel, hotspot);
51+ };
52
53 // Draw resource overlay.
54 uint8_t const amount = field.fcoords.field->get_resources_amount();
55@@ -322,6 +344,39 @@
56 constexpr int kStartingPosHotspotY = 55;
57 blit_overlay(player_image, Vector2i(player_image->width() / 2, kStartingPosHotspotY));
58 }
59+
60+ // Draw selection markers on the field.
61+ if (selected_nodes.count(field.fcoords) > 0) {
62+ const Image* pic = get_sel_picture();
63+ blit_overlay(pic, Vector2i(pic->width() / 2, pic->height() / 2));
64+ }
65+
66+ // Draw selection markers on the triangles.
67+ if (field.all_neighbors_valid()) {
68+ const FieldsToDraw::Field& rn = fields_to_draw->at(field.rn_index);
69+ const FieldsToDraw::Field& brn = fields_to_draw->at(field.brn_index);
70+ const FieldsToDraw::Field& bln = fields_to_draw->at(field.bln_index);
71+ if (selected_triangles.count(
72+ Widelands::TCoords<>(field.fcoords, Widelands::TriangleIndex::R))) {
73+ const Vector2f tripos(
74+ (field.rendertarget_pixel.x + rn.rendertarget_pixel.x + brn.rendertarget_pixel.x) /
75+ 3.f,
76+ (field.rendertarget_pixel.y + rn.rendertarget_pixel.y + brn.rendertarget_pixel.y) /
77+ 3.f);
78+ const Image* pic = get_sel_picture();
79+ blit(pic, tripos, Vector2i(pic->width() / 2, pic->height() / 2));
80+ }
81+ if (selected_triangles.count(
82+ Widelands::TCoords<>(field.fcoords, Widelands::TriangleIndex::D))) {
83+ const Vector2f tripos(
84+ (field.rendertarget_pixel.x + bln.rendertarget_pixel.x + brn.rendertarget_pixel.x) /
85+ 3.f,
86+ (field.rendertarget_pixel.y + bln.rendertarget_pixel.y + brn.rendertarget_pixel.y) /
87+ 3.f);
88+ const Image* pic = get_sel_picture();
89+ blit(pic, tripos, Vector2i(pic->width() / 2, pic->height() / 2));
90+ }
91+ }
92 }
93 }
94
95
96=== modified file 'src/logic/map_objects/tribes/building.h'
97--- src/logic/map_objects/tribes/building.h 2017-08-09 17:55:34 +0000
98+++ src/logic/map_objects/tribes/building.h 2017-09-07 18:19:58 +0000
99@@ -155,6 +155,10 @@
100 virtual uint32_t get_conquers() const;
101 virtual uint32_t vision_range() const;
102
103+ const WorkareaInfo& workarea_info() const { return workarea_info_; }
104+
105+ // TODO(sirver): This should not be public. It is mutated by other classes
106+ // in many places.
107 WorkareaInfo workarea_info_;
108
109 bool suitability(const Map&, const FCoords&) const;
110
111=== modified file 'src/logic/map_objects/tribes/workarea_info.h'
112--- src/logic/map_objects/tribes/workarea_info.h 2017-01-25 18:55:59 +0000
113+++ src/logic/map_objects/tribes/workarea_info.h 2017-09-07 18:19:58 +0000
114@@ -39,11 +39,8 @@
115 * See LuaBuildingDescription::get_workarea_radius, InteractiveBase::show_work_area
116 */
117
118-// TODO(Hasi50): LuaBuildingDescription::get_workarea_radius will only give us the very first
119-// size found, which seems to be correct but depends on the std:map implementation
120-//
121-// We could just use a unit8 as base for the map?
122-// We should document (as const) the expected stings.
123+// TODO(Hasi50): We could just use a unit8 as base for the map? We should
124+// document (as const) the expected stings.
125
126 using WorkareaInfo = std::map<uint32_t, std::set<std::string>>;
127
128
129=== modified file 'src/logic/maptriangleregion.cc'
130--- src/logic/maptriangleregion.cc 2017-08-31 10:55:45 +0000
131+++ src/logic/maptriangleregion.cc 2017-09-07 18:19:58 +0000
132@@ -144,7 +144,6 @@
133 template <>
134 MapTriangleRegion<TCoords<FCoords>>::MapTriangleRegion(const Map& map, Area<TCoords<FCoords>> area)
135 : radius_is_odd_(area.radius & 1), location_(area) {
136- assert(area.t == TriangleIndex::R || area.t == TriangleIndex::D);
137 const uint16_t radius_plus_1 = area.radius + 1;
138 const uint16_t half_radius_rounded_down = area.radius / 2;
139 row_length_ = radius_plus_1;
140
141=== modified file 'src/logic/widelands_geometry.h'
142--- src/logic/widelands_geometry.h 2017-09-02 19:51:07 +0000
143+++ src/logic/widelands_geometry.h 2017-09-07 18:19:58 +0000
144@@ -126,6 +126,9 @@
145 bool operator!=(const TCoords& other) const {
146 return !(*this == other);
147 }
148+ bool operator<(const TCoords& other) const {
149+ return std::forward_as_tuple(node, t) < std::forward_as_tuple(other.node, other.t);
150+ }
151
152 CoordsType node;
153 TriangleIndex t;
154
155=== modified file 'src/scripting/lua_map.cc'
156--- src/scripting/lua_map.cc 2017-08-31 15:22:21 +0000
157+++ src/scripting/lua_map.cc 2017-09-07 18:19:58 +0000
158@@ -2133,7 +2133,7 @@
159 nil in case bulding has no workareas
160 */
161 int LuaBuildingDescription::get_workarea_radius(lua_State* L) {
162- const WorkareaInfo& workareaInfo = get()->workarea_info_;
163+ const WorkareaInfo& workareaInfo = get()->workarea_info();
164 if (!workareaInfo.empty()) {
165 lua_pushinteger(L, workareaInfo.begin()->first);
166 } else {
167
168=== modified file 'src/wui/buildingwindow.cc'
169--- src/wui/buildingwindow.cc 2017-08-17 15:34:45 +0000
170+++ src/wui/buildingwindow.cc 2017-09-07 18:19:58 +0000
171@@ -53,7 +53,8 @@
172 is_dying_(false),
173 parent_(&parent),
174 building_(b),
175- workarea_overlay_id_(0),
176+ building_position_(b.get_position()),
177+ showing_workarea_(false),
178 avoid_fastclick_(avoid_fastclick),
179 expeditionbtn_(nullptr) {
180 buildingnotes_subscriber_ = Notifications::subscribe<Widelands::NoteBuilding>(
181@@ -61,9 +62,7 @@
182 }
183
184 BuildingWindow::~BuildingWindow() {
185- if (workarea_overlay_id_) {
186- igbase()->mutable_field_overlay_manager()->remove_overlay(workarea_overlay_id_);
187- }
188+ hide_workarea();
189 }
190
191 void BuildingWindow::on_building_note(const Widelands::NoteBuilding& note) {
192@@ -77,7 +76,7 @@
193 break;
194 // The building is no more
195 case Widelands::NoteBuilding::Action::kStartWarp:
196- igbase()->add_wanted_building_window(building().get_position(), get_pos(), is_minimal());
197+ igbase()->add_wanted_building_window(building_position_, get_pos(), is_minimal());
198 FALLS_THROUGH;
199 case Widelands::NoteBuilding::Action::kDeleted:
200 die();
201@@ -116,6 +115,7 @@
202 // Stop everybody from thinking to avoid segfaults
203 void BuildingWindow::die() {
204 is_dying_ = true;
205+ hide_workarea();
206 set_thinks(false);
207 vbox_.reset(nullptr);
208 UniqueWindow::die();
209@@ -287,13 +287,13 @@
210 }
211
212 if (can_see) {
213- WorkareaInfo wa_info;
214+ const WorkareaInfo* wa_info;
215 if (upcast(Widelands::ConstructionSite, csite, &building_)) {
216- wa_info = csite->building().workarea_info_;
217+ wa_info = &csite->building().workarea_info();
218 } else {
219- wa_info = building_.descr().workarea_info_;
220+ wa_info = &building_.descr().workarea_info();
221 }
222- if (!wa_info.empty()) {
223+ if (!wa_info->empty()) {
224 toggle_workarea_ = new UI::Button(
225 capsbuttons, "workarea", 0, 0, 34, 34, g_gr->images().get("images/ui_basic/but4.png"),
226 g_gr->images().get("images/wui/overlays/workarea123.png"), _("Hide work area"));
227@@ -419,26 +419,27 @@
228 ===============
229 */
230 void BuildingWindow::act_debug() {
231- show_field_debug(*igbase(), igbase()->game().map().get_fcoords(building_.get_position()));
232+ show_field_debug(*igbase(), igbase()->game().map().get_fcoords(building_position_));
233 }
234
235 /**
236 * Show the building's workarea (if it has one).
237 */
238 void BuildingWindow::show_workarea() {
239- if (workarea_overlay_id_) {
240+ if (showing_workarea_) {
241 return; // already shown, nothing to be done
242 }
243- WorkareaInfo workarea_info;
244+ const WorkareaInfo* workarea_info;
245 if (upcast(Widelands::ConstructionSite, csite, &building_)) {
246- workarea_info = csite->building().workarea_info_;
247+ workarea_info = &csite->building().workarea_info();
248 } else {
249- workarea_info = building_.descr().workarea_info_;
250+ workarea_info = &building_.descr().workarea_info();
251 }
252- if (workarea_info.empty()) {
253+ if (workarea_info->empty()) {
254 return;
255 }
256- workarea_overlay_id_ = igbase()->show_work_area(workarea_info, building_.get_position());
257+ igbase()->show_work_area(*workarea_info, building_position_);
258+ showing_workarea_ = true;
259
260 configure_workarea_button();
261 }
262@@ -447,10 +448,9 @@
263 * Hide the workarea from view.
264 */
265 void BuildingWindow::hide_workarea() {
266- if (workarea_overlay_id_) {
267- igbase()->hide_work_area(workarea_overlay_id_);
268- workarea_overlay_id_ = 0;
269-
270+ if (showing_workarea_) {
271+ igbase()->hide_work_area(building_position_);
272+ showing_workarea_ = false;
273 configure_workarea_button();
274 }
275 }
276@@ -460,7 +460,7 @@
277 */
278 void BuildingWindow::configure_workarea_button() {
279 if (toggle_workarea_) {
280- if (workarea_overlay_id_) {
281+ if (showing_workarea_) {
282 toggle_workarea_->set_tooltip(_("Hide work area"));
283 toggle_workarea_->set_perm_pressed(true);
284 } else {
285@@ -471,7 +471,7 @@
286 }
287
288 void BuildingWindow::toggle_workarea() {
289- if (workarea_overlay_id_) {
290+ if (showing_workarea_) {
291 hide_workarea();
292 } else {
293 show_workarea();
294@@ -491,7 +491,7 @@
295 * for the corresponding button.
296 */
297 void BuildingWindow::clicked_goto() {
298- igbase()->map_view()->scroll_to_field(building().get_position(), MapView::Transition::Smooth);
299+ igbase()->map_view()->scroll_to_field(building_position_, MapView::Transition::Smooth);
300 }
301
302 void BuildingWindow::update_expedition_button(bool expedition_was_canceled) {
303
304=== modified file 'src/wui/buildingwindow.h'
305--- src/wui/buildingwindow.h 2017-06-06 05:37:57 +0000
306+++ src/wui/buildingwindow.h 2017-09-07 18:19:58 +0000
307@@ -90,11 +90,21 @@
308 bool is_dying_;
309
310 private:
311+ // Actions performed when a NoteBuilding is received.
312+ void on_building_note(const Widelands::NoteBuilding& note);
313+
314+ // For ports only.
315+ void update_expedition_button(bool expedition_was_canceled);
316+
317 InteractiveGameBase* parent_;
318- /// Actions performed when a NoteBuilding is received.
319- void on_building_note(const Widelands::NoteBuilding& note);
320+
321 Widelands::Building& building_;
322
323+ // We require this to unregister overlays when we are closed. Since the
324+ // building might have been destroyed by then we have to keep a copy of its
325+ // position around.
326+ const Widelands::Coords building_position_;
327+
328 std::unique_ptr<UI::Box> vbox_;
329
330 UI::TabPanel* tabs_;
331@@ -107,12 +117,9 @@
332 Widelands::PlayerNumber capscache_player_number_;
333 bool caps_setup_;
334
335- FieldOverlayManager::OverlayId workarea_overlay_id_;
336+ bool showing_workarea_;
337 bool avoid_fastclick_;
338
339- // For ports only.
340- void update_expedition_button(bool expedition_was_canceled);
341-
342 UI::Button* expeditionbtn_;
343 std::unique_ptr<Notifications::Subscriber<Widelands::NoteExpeditionCanceled>>
344 expedition_canceled_subscriber_;
345
346=== modified file 'src/wui/field_overlay_manager.h'
347--- src/wui/field_overlay_manager.h 2017-08-28 13:37:51 +0000
348+++ src/wui/field_overlay_manager.h 2017-09-07 18:19:58 +0000
349@@ -53,7 +53,6 @@
350 // drawn below the buildhelp, everything higher above.
351 enum class OverlayLevel {
352 kWorkAreaPreview = 0,
353- kSelection = 7,
354 kRoadBuildSlope = 8,
355 };
356
357
358=== modified file 'src/wui/fieldaction.cc'
359--- src/wui/fieldaction.cc 2017-08-30 10:29:46 +0000
360+++ src/wui/fieldaction.cc 2017-09-07 18:19:58 +0000
361@@ -196,14 +196,13 @@
362
363 Widelands::Player* player_;
364 const Widelands::Map& map_;
365- FieldOverlayManager& field_overlay_manager_;
366
367 Widelands::FCoords node_;
368
369 UI::TabPanel tabpanel_;
370 bool fastclick_; // if true, put the mouse over first button in first tab
371 uint32_t best_tab_;
372- FieldOverlayManager::OverlayId workarea_preview_overlay_id_;
373+ bool showing_workarea_preview_;
374
375 /// Variables to use with attack dialog.
376 AttackBox* attack_box_;
377@@ -247,20 +246,19 @@
378 : UI::UniqueWindow(ib, "field_action", registry, 68, 34, _("Action")),
379 player_(plr),
380 map_(ib->egbase().map()),
381- field_overlay_manager_(*ib->mutable_field_overlay_manager()),
382 node_(ib->get_sel_pos().node, &map_[ib->get_sel_pos().node]),
383 tabpanel_(this, g_gr->images().get("images/ui_basic/but1.png")),
384 fastclick_(true),
385 best_tab_(0),
386- workarea_preview_overlay_id_(0),
387+ showing_workarea_preview_(false),
388 attack_box_(nullptr) {
389 ib->set_sel_freeze(true);
390 set_center_panel(&tabpanel_);
391 }
392
393 FieldActionWindow::~FieldActionWindow() {
394- if (workarea_preview_overlay_id_)
395- field_overlay_manager_.remove_overlay(workarea_preview_overlay_id_);
396+ if (showing_workarea_preview_)
397+ ibase().hide_work_area(node_);
398 ibase().set_sel_freeze(false);
399 delete attack_box_;
400 }
401@@ -685,17 +683,18 @@
402 }
403
404 void FieldActionWindow::building_icon_mouse_out(Widelands::DescriptionIndex) {
405- if (workarea_preview_overlay_id_) {
406- field_overlay_manager_.remove_overlay(workarea_preview_overlay_id_);
407- workarea_preview_overlay_id_ = 0;
408+ if (showing_workarea_preview_) {
409+ ibase().hide_work_area(node_);
410+ showing_workarea_preview_ = false;
411 }
412 }
413
414 void FieldActionWindow::building_icon_mouse_in(const Widelands::DescriptionIndex idx) {
415- if (ibase().show_workarea_preview_ && !workarea_preview_overlay_id_) {
416+ if (ibase().show_workarea_preview_ && !showing_workarea_preview_) {
417 const WorkareaInfo& workarea_info =
418- player_->tribe().get_building_descr(Widelands::DescriptionIndex(idx))->workarea_info_;
419- workarea_preview_overlay_id_ = ibase().show_work_area(workarea_info, node_);
420+ player_->tribe().get_building_descr(Widelands::DescriptionIndex(idx))->workarea_info();
421+ ibase().show_work_area(workarea_info, node_);
422+ showing_workarea_preview_ = true;
423 }
424 }
425
426
427=== modified file 'src/wui/interactive_base.cc'
428--- src/wui/interactive_base.cc 2017-09-02 19:36:19 +0000
429+++ src/wui/interactive_base.cc 2017-09-07 18:19:58 +0000
430@@ -151,44 +151,20 @@
431
432 void InteractiveBase::set_sel_pos(Widelands::NodeAndTriangle<> const center) {
433 const Map& map = egbase().map();
434-
435- // Remove old sel pointer
436- if (sel_.jobid)
437- field_overlay_manager_->remove_overlay(sel_.jobid);
438- const FieldOverlayManager::OverlayId jobid = sel_.jobid =
439- field_overlay_manager_->next_overlay_id();
440-
441 sel_.pos = center;
442
443- // register sel overlay position
444- if (sel_.triangles) {
445- assert(center.triangle.t == Widelands::TriangleIndex::D ||
446- center.triangle.t == Widelands::TriangleIndex::R);
447- Widelands::MapTriangleRegion<> mr(map, Area<TCoords<>>(center.triangle, sel_.radius));
448- do
449- field_overlay_manager_->register_overlay(
450- mr.location().node, sel_.pic, OverlayLevel::kSelection, Vector2i::invalid(), jobid);
451- while (mr.advance(map));
452- } else {
453- Widelands::MapRegion<> mr(map, Area<>(center.node, sel_.radius));
454- do
455- field_overlay_manager_->register_overlay(
456- mr.location(), sel_.pic, OverlayLevel::kSelection, Vector2i::invalid(), jobid);
457- while (mr.advance(map));
458- if (upcast(InteractiveGameBase const, igbase, this))
459- if (upcast(Widelands::ProductionSite, productionsite, map[center.node].get_immovable())) {
460- if (upcast(InteractivePlayer const, iplayer, igbase)) {
461- const Widelands::Player& player = iplayer->player();
462- if (!player.see_all() &&
463- (1 >= player.vision(Widelands::Map::get_index(center.node, map.get_width())) ||
464- player.is_hostile(*productionsite->get_owner())))
465- return set_tooltip("");
466- }
467- set_tooltip(
468- productionsite->info_string(Widelands::Building::InfoStringFormat::kTooltip));
469- return;
470+ if (upcast(InteractiveGameBase const, igbase, this))
471+ if (upcast(Widelands::ProductionSite, productionsite, map[center.node].get_immovable())) {
472+ if (upcast(InteractivePlayer const, iplayer, igbase)) {
473+ const Widelands::Player& player = iplayer->player();
474+ if (!player.see_all() &&
475+ (1 >= player.vision(Widelands::Map::get_index(center.node, map.get_width())) ||
476+ player.is_hostile(*productionsite->get_owner())))
477+ return set_tooltip("");
478 }
479- }
480+ set_tooltip(productionsite->info_string(Widelands::Building::InfoStringFormat::kTooltip));
481+ return;
482+ }
483 set_tooltip("");
484 }
485
486@@ -263,48 +239,52 @@
487 }
488
489 // Show the given workareas at the given coords and returns the overlay job id associated
490-FieldOverlayManager::OverlayId InteractiveBase::show_work_area(const WorkareaInfo& workarea_info,
491- Widelands::Coords coords) {
492- const uint8_t workareas_nrs = workarea_info.size();
493- WorkareaInfo::size_type wa_index;
494- switch (workareas_nrs) {
495- case 0:
496- return 0; // no workarea
497- case 1:
498- wa_index = 5;
499- break;
500- case 2:
501- wa_index = 3;
502- break;
503- case 3:
504- wa_index = 0;
505- break;
506- default:
507- throw wexception("Encountered unexpected WorkareaInfo size %i", workareas_nrs);
508- }
509- const Widelands::Map& map = egbase_.map();
510- FieldOverlayManager::OverlayId overlay_id = field_overlay_manager_->next_overlay_id();
511-
512- Widelands::HollowArea<> hollow_area(Widelands::Area<>(coords, 0), 0);
513-
514- // Iterate through the work areas, from building to its enhancement
515- WorkareaInfo::const_iterator it = workarea_info.begin();
516- for (; it != workarea_info.end(); ++it) {
517- hollow_area.radius = it->first;
518- Widelands::MapHollowRegion<> mr(map, hollow_area);
519- do
520- field_overlay_manager_->register_overlay(mr.location(), workarea_pics_[wa_index],
521- OverlayLevel::kWorkAreaPreview,
522- Vector2i::invalid(), overlay_id);
523- while (mr.advance(map));
524- wa_index++;
525- hollow_area.hole_radius = hollow_area.radius;
526- }
527- return overlay_id;
528-}
529-
530-void InteractiveBase::hide_work_area(FieldOverlayManager::OverlayId overlay_id) {
531- field_overlay_manager_->remove_overlay(overlay_id);
532+void InteractiveBase::show_work_area(const WorkareaInfo& workarea_info, Widelands::Coords coords) {
533+ work_area_previews_[coords] = &workarea_info;
534+}
535+
536+std::map<Coords, const Image*> InteractiveBase::get_work_area_overlays(const Widelands::Map& map) const {
537+ std::map<Coords, const Image*> result;
538+ for (const auto& pair : work_area_previews_) {
539+ const Coords& coords = pair.first;
540+ const WorkareaInfo* workarea_info = pair.second;
541+ WorkareaInfo::size_type wa_index;
542+ switch (workarea_info->size()) {
543+ case 0:
544+ continue; // no workarea
545+ case 1:
546+ wa_index = 5;
547+ break;
548+ case 2:
549+ wa_index = 3;
550+ break;
551+ case 3:
552+ wa_index = 0;
553+ break;
554+ default:
555+ throw wexception(
556+ "Encountered unexpected WorkareaInfo size %i", static_cast<int>(workarea_info->size()));
557+ }
558+
559+ Widelands::HollowArea<> hollow_area(Widelands::Area<>(coords, 0), 0);
560+
561+ // Iterate through the work areas, from building to its enhancement
562+ WorkareaInfo::const_iterator it = workarea_info->begin();
563+ for (; it != workarea_info->end(); ++it) {
564+ hollow_area.radius = it->first;
565+ Widelands::MapHollowRegion<> mr(map, hollow_area);
566+ do {
567+ result[mr.location()] = workarea_pics_[wa_index];
568+ } while (mr.advance(map));
569+ wa_index++;
570+ hollow_area.hole_radius = hollow_area.radius;
571+ }
572+ }
573+ return result;
574+}
575+
576+void InteractiveBase::hide_work_area(const Widelands::Coords& coords) {
577+ work_area_previews_.erase(coords);
578 }
579
580 /**
581
582=== modified file 'src/wui/interactive_base.h'
583--- src/wui/interactive_base.h 2017-09-02 19:36:19 +0000
584+++ src/wui/interactive_base.h 2017-09-07 18:19:58 +0000
585@@ -75,9 +75,9 @@
586
587 // TODO(sirver): This should be private.
588 bool show_workarea_preview_;
589- FieldOverlayManager::OverlayId show_work_area(const WorkareaInfo& workarea_info,
590+ void show_work_area(const WorkareaInfo& workarea_info,
591 Widelands::Coords coords);
592- void hide_work_area(FieldOverlayManager::OverlayId overlay_id);
593+ void hide_work_area(const Widelands::Coords& coords);
594
595 // point of view for drawing
596 virtual Widelands::Player* get_player() const = 0;
597@@ -198,6 +198,7 @@
598
599 void unset_sel_picture();
600 void set_sel_picture(const Image* image);
601+ const Image* get_sel_picture() { return sel_.pic; }
602 void adjust_toolbar_position() {
603 toolbar_.set_pos(Vector2i((get_inner_w() - toolbar_.get_w()) >> 1, get_inner_h() - 34));
604 }
605@@ -213,6 +214,10 @@
606 // Returns the information which overlay text should currently be drawn.
607 TextToDraw get_text_to_draw() const;
608
609+ // Returns the current overlays for the work area previews.
610+ std::map<Widelands::Coords, const Image*>
611+ get_work_area_overlays(const Widelands::Map& map) const;
612+
613 private:
614 int32_t stereo_position(Widelands::Coords position_map);
615 void resize_chat_overlay();
616@@ -239,45 +244,49 @@
617 uint32_t radius;
618 const Image* pic;
619 FieldOverlayManager::OverlayId jobid;
620- } sel_;
621-
622- MapView map_view_;
623- ChatOverlay* chat_overlay_;
624-
625- // These get collected by add_toolbar_button
626- // so we can call unassign_toggle_button on them in the destructor.
627- std::vector<UI::UniqueWindow::Registry> registries_;
628-
629- UI::Box toolbar_;
630- // No unique_ptr on purpose: 'minimap_' is a UniqueWindow, its parent will
631- // delete it.
632- MiniMap* minimap_;
633- MiniMap::Registry minimap_registry_;
634- QuickNavigation quick_navigation_;
635-
636- std::unique_ptr<FieldOverlayManager> field_overlay_manager_;
637-
638- // The roads that are displayed while a road is being build. They are not
639- // yet logically in the game, but need to be displayed for the user as
640- // visual guide. The data type is the same as for Field::road.
641- std::map<Widelands::Coords, uint8_t> road_building_preview_;
642-
643- std::unique_ptr<Notifications::Subscriber<GraphicResolutionChanged>>
644- graphic_resolution_changed_subscriber_;
645- std::unique_ptr<Notifications::Subscriber<NoteSound>> sound_subscriber_;
646- Widelands::EditorGameBase& egbase_;
647- uint32_t display_flags_;
648- uint32_t lastframe_; // system time (milliseconds)
649- uint32_t frametime_; // in millseconds
650- uint32_t avg_usframetime_; // in microseconds!
651-
652- FieldOverlayManager::OverlayId road_buildhelp_overlay_jobid_;
653- Widelands::CoordPath* buildroad_; // path for the new road
654- Widelands::PlayerNumber road_build_player_;
655-
656- UI::UniqueWindow::Registry debugconsole_;
657- std::unique_ptr<UniqueWindowHandler> unique_window_handler_;
658- std::vector<const Image*> workarea_pics_;
659+ } sel_;
660+
661+ MapView map_view_;
662+ ChatOverlay* chat_overlay_;
663+
664+ // These get collected by add_toolbar_button
665+ // so we can call unassign_toggle_button on them in the destructor.
666+ std::vector<UI::UniqueWindow::Registry> registries_;
667+
668+ UI::Box toolbar_;
669+ // No unique_ptr on purpose: 'minimap_' is a UniqueWindow, its parent will
670+ // delete it.
671+ MiniMap* minimap_;
672+ MiniMap::Registry minimap_registry_;
673+ QuickNavigation quick_navigation_;
674+
675+ std::unique_ptr<FieldOverlayManager> field_overlay_manager_;
676+
677+ // The currently enabled work area previews. They are keyed by the
678+ // coordinate that the building that shows the work area is positioned.
679+ std::map<Widelands::Coords, const WorkareaInfo*> work_area_previews_;
680+
681+ // The roads that are displayed while a road is being built. They are not
682+ // yet logically in the game, but need to be displayed for the user as
683+ // visual guide. The data type is the same as for Field::road.
684+ std::map<Widelands::Coords, uint8_t> road_building_preview_;
685+
686+ std::unique_ptr<Notifications::Subscriber<GraphicResolutionChanged>>
687+ graphic_resolution_changed_subscriber_;
688+ std::unique_ptr<Notifications::Subscriber<NoteSound>> sound_subscriber_;
689+ Widelands::EditorGameBase& egbase_;
690+ uint32_t display_flags_;
691+ uint32_t lastframe_; // system time (milliseconds)
692+ uint32_t frametime_; // in millseconds
693+ uint32_t avg_usframetime_; // in microseconds!
694+
695+ FieldOverlayManager::OverlayId road_buildhelp_overlay_jobid_;
696+ Widelands::CoordPath* buildroad_; // path for the new road
697+ Widelands::PlayerNumber road_build_player_;
698+
699+ UI::UniqueWindow::Registry debugconsole_;
700+ std::unique_ptr<UniqueWindowHandler> unique_window_handler_;
701+ std::vector<const Image*> workarea_pics_;
702 };
703
704 #endif // end of include guard: WL_WUI_INTERACTIVE_BASE_H
705
706=== modified file 'src/wui/interactive_player.cc'
707--- src/wui/interactive_player.cc 2017-09-02 19:34:45 +0000
708+++ src/wui/interactive_player.cc 2017-09-07 18:19:58 +0000
709@@ -320,6 +320,10 @@
710 }
711
712 void InteractivePlayer::draw_map_view(MapView* given_map_view, RenderTarget* dst) {
713+ // In-game, selection can never be on triangles or have a radius.
714+ assert(get_sel_radius() == 0);
715+ assert(!get_sel_triangles());
716+
717 const Widelands::Player& plr = player();
718 const auto& gbase = egbase();
719 const Widelands::Map& map = gbase.map();
720@@ -327,6 +331,7 @@
721
722 auto* fields_to_draw = given_map_view->draw_terrain(gbase, dst);
723 const auto& roads_preview = road_building_preview();
724+ const std::map<Widelands::Coords, const Image*> work_area_overlays = get_work_area_overlays(map);
725
726 for (size_t idx = 0; idx < fields_to_draw->size(); ++idx) {
727 auto* f = fields_to_draw->mutable_field(idx);
728@@ -349,9 +354,11 @@
729 }
730
731 // Add road building overlays if applicable.
732- const auto it = roads_preview.find(f->fcoords);
733- if (it != roads_preview.end()) {
734- f->roads |= it->second;
735+ {
736+ const auto it = roads_preview.find(f->fcoords);
737+ if (it != roads_preview.end()) {
738+ f->roads |= it->second;
739+ }
740 }
741
742 const float scale = 1.f / given_map_view->view().zoom;
743@@ -367,15 +374,30 @@
744 draw_immovables_for_formerly_visible_field(*f, player_field, scale, dst);
745 }
746
747+ const auto blit_overlay = [dst, f, scale](const Image* pic, const Vector2i& hotspot) {
748+ dst->blitrect_scale(Rectf(f->rendertarget_pixel - hotspot.cast<float>() * scale,
749+ pic->width() * scale, pic->height() * scale),
750+ pic, Recti(0, 0, pic->width(), pic->height()), 1.f,
751+ BlendMode::UseAlpha);
752+ };
753+
754+ // Draw work area previews.
755+ {
756+ const auto it = work_area_overlays.find(f->fcoords);
757+ if (it != work_area_overlays.end()) {
758+ blit_overlay(it->second, Vector2i(it->second->width() / 2, it->second->height() / 2));
759+ }
760+ }
761+
762 // TODO(sirver): Do not use the field_overlay_manager, instead draw the
763 // overlays we are interested in here directly.
764- field_overlay_manager().foreach_overlay(
765- f->fcoords, [dst, f, scale](const Image* pic, const Vector2i& hotspot) {
766- dst->blitrect_scale(Rectf(f->rendertarget_pixel - hotspot.cast<float>() * scale,
767- pic->width() * scale, pic->height() * scale),
768- pic, Recti(0, 0, pic->width(), pic->height()), 1.f,
769- BlendMode::UseAlpha);
770- });
771+ field_overlay_manager().foreach_overlay(f->fcoords, blit_overlay);
772+
773+ // Blit the selection marker.
774+ if (f->fcoords == get_sel_pos().node) {
775+ const Image* pic = get_sel_picture();
776+ blit_overlay(pic, Vector2i(pic->width() / 2, pic->height() / 2));
777+ }
778 }
779 }
780
781
782=== modified file 'src/wui/interactive_spectator.cc'
783--- src/wui/interactive_spectator.cc 2017-08-28 12:44:08 +0000
784+++ src/wui/interactive_spectator.cc 2017-09-07 18:19:58 +0000
785@@ -111,6 +111,9 @@
786 void InteractiveSpectator::draw_map_view(MapView* given_map_view, RenderTarget* dst) {
787 // A spectator cannot build roads.
788 assert(road_building_preview().empty());
789+ // In-game, selection can never be on triangles or have a radius.
790+ assert(get_sel_radius() == 0);
791+ assert(!get_sel_triangles());
792
793 const auto& gbase = egbase();
794 auto* fields_to_draw = given_map_view->draw_terrain(gbase, dst);
795@@ -118,6 +121,8 @@
796 const uint32_t gametime = gbase.get_gametime();
797
798 const auto text_to_draw = get_text_to_draw();
799+ const std::map<Widelands::Coords, const Image*> work_area_overlays =
800+ get_work_area_overlays(gbase.map());
801 for (size_t idx = 0; idx < fields_to_draw->size(); ++idx) {
802 const FieldsToDraw::Field& field = fields_to_draw->at(idx);
803
804@@ -133,15 +138,28 @@
805 bob->draw(gbase, text_to_draw, field.rendertarget_pixel, scale, dst);
806 }
807
808+ const auto blit_overlay = [dst, &field, scale](const Image* pic, const Vector2i& hotspot) {
809+ dst->blitrect_scale(Rectf(field.rendertarget_pixel - hotspot.cast<float>() * scale,
810+ pic->width() * scale, pic->height() * scale),
811+ pic, Recti(0, 0, pic->width(), pic->height()), 1.f,
812+ BlendMode::UseAlpha);
813+ };
814+
815+ const auto it = work_area_overlays.find(field.fcoords);
816+ if (it != work_area_overlays.end()) {
817+ const Image* pic = it->second;
818+ blit_overlay(pic, Vector2i(pic->width() / 2, pic->height() / 2));
819+ }
820+
821 // TODO(sirver): Do not use the field_overlay_manager, instead draw the
822 // overlays we are interested in here directly.
823- field_overlay_manager().foreach_overlay(
824- field.fcoords, [dst, &field, scale](const Image* pic, const Vector2i& hotspot) {
825- dst->blitrect_scale(Rectf(field.rendertarget_pixel - hotspot.cast<float>() * scale,
826- pic->width() * scale, pic->height() * scale),
827- pic, Recti(0, 0, pic->width(), pic->height()), 1.f,
828- BlendMode::UseAlpha);
829- });
830+ field_overlay_manager().foreach_overlay(field.fcoords, blit_overlay);
831+
832+ // Blit the selection marker.
833+ if (field.fcoords == get_sel_pos().node) {
834+ const Image* pic = get_sel_picture();
835+ blit_overlay(pic, Vector2i(pic->width() / 2, pic->height() / 2));
836+ }
837 }
838 }
839

Subscribers

People subscribed via source and target branches

to status/vote changes: