Merge lp:~widelands-dev/widelands/reduce_overlay_manager_use2 into lp:widelands
- reduce_overlay_manager_use2
- Merge into trunk
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 |
Related bugs: |
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 FieldOverlayMan
- Draw field selectors in the draw routine directly, not using the FieldOverlayMan
- Draw work area preview markers in the draw routine directly, not using the FieldOverlayMan
Description of the change
To post a comment you must log in.
Revision history for this message
bunnybot (widelandsofficial) wrote : | # |
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/
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 |
Continuous integration builds have changed state:
Travis build 2649. State: passed. Details: https:/ /travis- ci.org/ widelands/ widelands/ builds/ 271391659. /ci.appveyor. com/project/ widelands- dev/widelands/ build/_ widelands_ dev_widelands_ reduce_ overlay_ manager_ use2-2471.
Appveyor build 2471. State: success. Details: https:/