Merge lp:~nordfriese/widelands/workareas into lp:widelands

Proposed by Benedikt Straub
Status: Merged
Merged at revision: 9077
Proposed branch: lp:~nordfriese/widelands/workareas
Merge into: lp:widelands
Diff against target: 741 lines (+371/-46)
19 files modified
data/shaders/workarea.fp (+7/-0)
data/shaders/workarea.vp (+15/-0)
src/editor/editorinteractive.cc (+1/-1)
src/graphic/CMakeLists.txt (+2/-0)
src/graphic/game_renderer.cc (+8/-0)
src/graphic/game_renderer.h (+1/-0)
src/graphic/gl/workarea_program.cc (+134/-0)
src/graphic/gl/workarea_program.h (+78/-0)
src/graphic/render_queue.cc (+10/-0)
src/graphic/render_queue.h (+4/-0)
src/logic/widelands_geometry.h (+4/-0)
src/wui/buildingwindow.cc (+1/-1)
src/wui/interactive_base.cc (+87/-18)
src/wui/interactive_base.h (+5/-4)
src/wui/interactive_player.cc (+8/-10)
src/wui/interactive_player.h (+2/-0)
src/wui/interactive_spectator.cc (+1/-9)
src/wui/mapview.cc (+2/-2)
src/wui/mapview.h (+1/-1)
To merge this branch: bzr merge lp:~nordfriese/widelands/workareas
Reviewer Review Type Date Requested Status
GunChleoc Approve
Review via email: mp+364266@code.launchpad.net

Commit message

Show the work areas of buildings as overlays on triangles

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

A few nits in the comments

Revision history for this message
Toni Förster (stonerl) wrote :

I like it so far, the node markers are a little too thin, IMHO. Why not use the old workarea12.png or workarea1.png? They are small enough.

Revision history for this message
Benedikt Straub (nordfriese) wrote :

Implemented your comment and updated the documentation.

I think the old markers are much too big and bright, I never really liked them. The purpose of these markers now is only to hint at the locations of nodes; IMHO a small, light cross is enough for that. If you want something bigger, you can always enable the buildhelp…

Revision history for this message
GunChleoc (gunchleoc) wrote :

constexpr kWorkareaTransparency = 127; <- this needs a datatype, e.g. int.

Revision history for this message
Toni Förster (stonerl) wrote :

Fair enough. But are they supposed to be a to look like a ++

Just a question; this is in no way related to your changes. I noticed that some military buildings, like the Fortress, have a different colour on the outer layer, what is this supposed to indicate?

Revision history for this message
Toni Förster (stonerl) wrote :

Can't build r9014.

src/graphic/gl/workarea_program.cc:63:11: error: C++ requires a type specifier for all declarations
constexpr kWorkareaTransparency = 127;

Revision history for this message
Benedikt Straub (nordfriese) wrote :

Fixed the typo, should compile now.

The marker is a small star (*) with six beams that point in the six cardinal directions.

The outer circle(s) is/are the enhancement area(s). They indicate the additional area that will be part of the workarea after an upgrade. We already have different overlay images for those in trunk, it´s just more noticeable with the colours now.

Revision history for this message
Toni Förster (stonerl) wrote :

I made two different versions of the marker. You can find them here:

https://fosuta.org/pics/1_grid_marker.png
https://fosuta.org/pics/2_grid_marker.png

Would you give them a try?

Revision history for this message
Benedikt Straub (nordfriese) wrote :

I think version 2 looks like a square with a circle in it, that looks strange. Version 1 is good, a bit too large though IMHO. I uploaded a new image similar to it now, how about this?

Revision history for this message
Toni Förster (stonerl) wrote :

Looks good.

Revision history for this message
bunnybot (widelandsofficial) wrote :

Continuous integration builds have changed state:

Travis build 4585. State: errored. Details: https://travis-ci.org/widelands/widelands/builds/504893428.
Appveyor build 4372. State: failed. Details: https://ci.appveyor.com/project/widelands-dev/widelands/build/_nordfriese_widelands_workareas-4372.

Revision history for this message
GunChleoc (gunchleoc) wrote :

I have done some testing as well and have selected multiple buildings on a slow machine - no problem :)

For the grid, how about having another shader that draws lines on the edges? That would also take care of most of the work for adding a grid to the editor:

https://bugs.launchpad.net/widelands/+bug/1529261

Revision history for this message
kaputtnik (franku) wrote :

Looks very good :)

I wonder why the little stars are missing on the border? For an enhanceable building the stars are at the edge of the bluish area. E.g. compare the workarea when trying to build an empire Outpost the stars are at the edge of the bluish and red area, then try to build an empire Barrier (the one which the Outpost can be enhanced to) on the same spot the stars are one node inside the bluish area.
For farms the stars are also one node inside the bluish area, so not showing all the nodes where fields can be planted.

Revision history for this message
Benedikt Straub (nordfriese) wrote :

Well spotted, pushed a fix for it…

> For the grid, how about having another shader that draws lines on the edges? That would also take care of most of the work for adding a grid to the editor

I´m going to try to take care of that feature soon :)
But I´m against showing a real grid in-game. It´s fine to hint at it by using on-node markers like the buildhelp and these star markers, but IMHO an actual grid is only a tool to make it easier to design the map, and not desirable for the gameplay.

Revision history for this message
bunnybot (widelandsofficial) wrote :

Continuous integration builds have changed state:

Travis build 4599. State: passed. Details: https://travis-ci.org/widelands/widelands/builds/505929624.
Appveyor build 4387. State: failed. Details: https://ci.appveyor.com/project/widelands-dev/widelands/build/_nordfriese_widelands_workareas-4387.

Revision history for this message
Klaus Halfmann (klaus-halfmann) wrote :

Is this for R20?

Revision history for this message
Benedikt Straub (nordfriese) wrote :

Would be nice, but I thought we were in feature freeze ;)

Revision history for this message
GunChleoc (gunchleoc) wrote :

Yes, feature freeze. We're mopping up the remaining bugs right now, so we can't risk merging anything else.

Revision history for this message
bunnybot (widelandsofficial) wrote :

Continuous integration builds have changed state:

Travis build 4645. State: errored. Details: https://travis-ci.org/widelands/widelands/builds/511061362.
Appveyor build 4432. State: success. Details: https://ci.appveyor.com/project/widelands-dev/widelands/build/_nordfriese_widelands_workareas-4432.

Revision history for this message
bunnybot (widelandsofficial) wrote :

Continuous integration builds have changed state:

Travis build 4672. State: passed. Details: https://travis-ci.org/widelands/widelands/builds/516235502.
Appveyor build 4458. State: success. Details: https://ci.appveyor.com/project/widelands-dev/widelands/build/_nordfriese_widelands_workareas-4458.

Revision history for this message
GunChleoc (gunchleoc) wrote :

@Nordfriese: You forgot to set the branch owner to widelands-dev, so I can't merge trunk to it. Can you take care of getting this branch in?

review: Approve
Revision history for this message
Benedikt Straub (nordfriese) wrote :

Merged trunk

@bunnybot merge

Revision history for this message
bunnybot (widelandsofficial) wrote :

Continuous integration builds have changed state:

Travis build 4784. State: errored. Details: https://travis-ci.org/widelands/widelands/builds/524065227.
Appveyor build 4565. State: success. Details: https://ci.appveyor.com/project/widelands-dev/widelands/build/_nordfriese_widelands_workareas-4565.

Revision history for this message
bunnybot (widelandsofficial) wrote :

Refusing to merge, since Travis is not green. Use @bunnybot merge force for merging anyways.

Travis build 4784. State: errored. Details: https://travis-ci.org/widelands/widelands/builds/524065227.

Revision history for this message
GunChleoc (gunchleoc) wrote :

Transient failure on Travis

@bunnybot merge force

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== renamed file 'data/images/wui/overlays/workarea123.png' => 'data/images/wui/buildings/toggle_workarea.png'
2=== added file 'data/images/wui/overlays/grid_marker.png'
3Binary files data/images/wui/overlays/grid_marker.png 1970-01-01 00:00:00 +0000 and data/images/wui/overlays/grid_marker.png 2019-04-24 15:57:58 +0000 differ
4=== removed file 'data/images/wui/overlays/workarea1.png'
5Binary files data/images/wui/overlays/workarea1.png 2019-03-30 06:46:25 +0000 and data/images/wui/overlays/workarea1.png 1970-01-01 00:00:00 +0000 differ
6=== removed file 'data/images/wui/overlays/workarea12.png'
7Binary files data/images/wui/overlays/workarea12.png 2019-03-30 06:46:25 +0000 and data/images/wui/overlays/workarea12.png 1970-01-01 00:00:00 +0000 differ
8=== removed file 'data/images/wui/overlays/workarea2.png'
9Binary files data/images/wui/overlays/workarea2.png 2019-03-30 06:46:25 +0000 and data/images/wui/overlays/workarea2.png 1970-01-01 00:00:00 +0000 differ
10=== removed file 'data/images/wui/overlays/workarea23.png'
11Binary files data/images/wui/overlays/workarea23.png 2019-03-30 06:46:25 +0000 and data/images/wui/overlays/workarea23.png 1970-01-01 00:00:00 +0000 differ
12=== removed file 'data/images/wui/overlays/workarea3.png'
13Binary files data/images/wui/overlays/workarea3.png 2014-12-03 20:13:06 +0000 and data/images/wui/overlays/workarea3.png 1970-01-01 00:00:00 +0000 differ
14=== added file 'data/shaders/workarea.fp'
15--- data/shaders/workarea.fp 1970-01-01 00:00:00 +0000
16+++ data/shaders/workarea.fp 2019-04-24 15:57:58 +0000
17@@ -0,0 +1,7 @@
18+#version 120
19+
20+varying vec4 var_overlay;
21+
22+void main() {
23+ gl_FragColor = var_overlay;
24+}
25
26=== added file 'data/shaders/workarea.vp'
27--- data/shaders/workarea.vp 1970-01-01 00:00:00 +0000
28+++ data/shaders/workarea.vp 2019-04-24 15:57:58 +0000
29@@ -0,0 +1,15 @@
30+#version 120
31+
32+// Attributes.
33+attribute vec2 attr_position;
34+attribute vec4 attr_overlay;
35+
36+uniform float u_z_value;
37+
38+// Output of vertex shader.
39+varying vec4 var_overlay;
40+
41+void main() {
42+ var_overlay = attr_overlay;
43+ gl_Position = vec4(attr_position, u_z_value, 1.);
44+}
45
46=== modified file 'src/editor/editorinteractive.cc'
47--- src/editor/editorinteractive.cc 2019-04-24 07:09:29 +0000
48+++ src/editor/editorinteractive.cc 2019-04-24 15:57:58 +0000
49@@ -262,7 +262,7 @@
50
51 void EditorInteractive::draw(RenderTarget& dst) {
52 const auto& ebase = egbase();
53- auto* fields_to_draw = map_view()->draw_terrain(ebase, &dst);
54+ auto* fields_to_draw = map_view()->draw_terrain(ebase, Workareas(), &dst);
55
56 const float scale = 1.f / map_view()->view().zoom;
57 const uint32_t gametime = ebase.get_gametime();
58
59=== modified file 'src/graphic/CMakeLists.txt'
60--- src/graphic/CMakeLists.txt 2019-04-08 13:32:28 +0000
61+++ src/graphic/CMakeLists.txt 2019-04-24 15:57:58 +0000
62@@ -231,6 +231,8 @@
63 gl/terrain_program.h
64 gl/dither_program.cc
65 gl/dither_program.h
66+ gl/workarea_program.cc
67+ gl/workarea_program.h
68 DEPENDS
69 base_exceptions
70 base_geometry
71
72=== modified file 'src/graphic/game_renderer.cc'
73--- src/graphic/game_renderer.cc 2019-04-24 06:01:37 +0000
74+++ src/graphic/game_renderer.cc 2019-04-24 15:57:58 +0000
75@@ -60,6 +60,7 @@
76 void draw_terrain(const Widelands::EditorGameBase& egbase,
77 const FieldsToDraw& fields_to_draw,
78 const float scale,
79+ Workareas workarea,
80 RenderTarget* dst) {
81 const Recti& bounding_rect = dst->get_rect();
82 const Surface& surface = dst->get_surface();
83@@ -86,6 +87,13 @@
84 i.blend_mode = BlendMode::UseAlpha;
85 RenderQueue::instance().enqueue(i);
86
87+ if (!workarea.empty()) {
88+ // Enqueue the drawing of the workarea overlay layer.
89+ i.program_id = RenderQueue::Program::kTerrainWorkarea;
90+ i.terrain_arguments.workareas = workarea;
91+ RenderQueue::instance().enqueue(i);
92+ }
93+
94 // Enqueue the drawing of the road layer.
95 i.program_id = RenderQueue::Program::kTerrainRoad;
96 RenderQueue::instance().enqueue(i);
97
98=== modified file 'src/graphic/game_renderer.h'
99--- src/graphic/game_renderer.h 2019-02-23 11:00:49 +0000
100+++ src/graphic/game_renderer.h 2019-04-24 15:57:58 +0000
101@@ -33,6 +33,7 @@
102 void draw_terrain(const Widelands::EditorGameBase& egbase,
103 const FieldsToDraw& fields_to_draw,
104 const float scale,
105+ Workareas workarea,
106 RenderTarget* dst);
107
108 // Draw the border stones for 'field' if it is a border and 'visibility' is
109
110=== added file 'src/graphic/gl/workarea_program.cc'
111--- src/graphic/gl/workarea_program.cc 1970-01-01 00:00:00 +0000
112+++ src/graphic/gl/workarea_program.cc 2019-04-24 15:57:58 +0000
113@@ -0,0 +1,134 @@
114+/*
115+ * Copyright (C) 2006-2019 by the Widelands Development Team
116+ *
117+ * This program is free software; you can redistribute it and/or
118+ * modify it under the terms of the GNU General Public License
119+ * as published by the Free Software Foundation; either version 2
120+ * of the License, or (at your option) any later version.
121+ *
122+ * This program is distributed in the hope that it will be useful,
123+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
124+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
125+ * GNU General Public License for more details.
126+ *
127+ * You should have received a copy of the GNU General Public License
128+ * along with this program; if not, write to the Free Software
129+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
130+ *
131+ */
132+
133+#include "graphic/gl/workarea_program.h"
134+
135+#include "graphic/gl/coordinate_conversion.h"
136+#include "graphic/gl/fields_to_draw.h"
137+#include "graphic/gl/utils.h"
138+#include "graphic/texture.h"
139+
140+WorkareaProgram::WorkareaProgram() {
141+ gl_program_.build("workarea");
142+
143+ attr_position_ = glGetAttribLocation(gl_program_.object(), "attr_position");
144+ attr_overlay_ = glGetAttribLocation(gl_program_.object(), "attr_overlay");
145+
146+ u_z_value_ = glGetUniformLocation(gl_program_.object(), "u_z_value");
147+}
148+
149+void WorkareaProgram::gl_draw(int gl_texture, float z_value) {
150+ glUseProgram(gl_program_.object());
151+
152+ auto& gl_state = Gl::State::instance();
153+ gl_state.enable_vertex_attrib_array(
154+ {attr_position_, attr_overlay_});
155+
156+ gl_array_buffer_.bind();
157+ gl_array_buffer_.update(vertices_);
158+
159+ Gl::vertex_attrib_pointer(
160+ attr_position_, 2, sizeof(PerVertexData), offsetof(PerVertexData, gl_x));
161+ Gl::vertex_attrib_pointer(
162+ attr_overlay_, 4, sizeof(PerVertexData), offsetof(PerVertexData, overlay_r));
163+
164+ gl_state.bind(GL_TEXTURE0, gl_texture);
165+
166+ glUniform1f(u_z_value_, z_value);
167+
168+ glDrawArrays(GL_TRIANGLES, 0, vertices_.size());
169+}
170+
171+constexpr uint8_t kWorkareaTransparency = 127;
172+static RGBAColor workarea_colors[] {
173+ RGBAColor(63, 31, 127, kWorkareaTransparency), // All three circles
174+ RGBAColor(127, 63, 0, kWorkareaTransparency), // Medium and outer circle
175+ RGBAColor(0, 127, 0, kWorkareaTransparency), // Outer circle
176+ RGBAColor(63, 0, 127, kWorkareaTransparency), // Inner and medium circle
177+ RGBAColor(127, 0, 0, kWorkareaTransparency), // Medium circle
178+ RGBAColor(0, 0, 127, kWorkareaTransparency), // Inner circle
179+};
180+static inline RGBAColor apply_color(RGBAColor c1, RGBAColor c2) {
181+ uint8_t r = (c1.r * c1.a + c2.r * c2.a) / (c1.a + c2.a);
182+ uint8_t g = (c1.g * c1.a + c2.g * c2.a) / (c1.a + c2.a);
183+ uint8_t b = (c1.b * c1.a + c2.b * c2.a) / (c1.a + c2.a);
184+ uint8_t a = (c1.a + c2.a) / 2;
185+ return RGBAColor(r, g, b, a);
186+}
187+
188+void WorkareaProgram::add_vertex(const FieldsToDraw::Field& field, RGBAColor overlay) {
189+ vertices_.emplace_back();
190+ PerVertexData& back = vertices_.back();
191+
192+ back.gl_x = field.gl_position.x;
193+ back.gl_y = field.gl_position.y;
194+ back.overlay_r = overlay.r / 255.f;
195+ back.overlay_g = overlay.g / 255.f;
196+ back.overlay_b = overlay.b / 255.f;
197+ back.overlay_a = overlay.a / 255.f;
198+}
199+
200+void WorkareaProgram::draw(uint32_t texture_id,
201+ Workareas workarea,
202+ const FieldsToDraw& fields_to_draw,
203+ float z_value) {
204+ vertices_.clear();
205+ vertices_.reserve(fields_to_draw.size() * 3);
206+
207+ for (size_t current_index = 0; current_index < fields_to_draw.size(); ++current_index) {
208+ const FieldsToDraw::Field& field = fields_to_draw.at(current_index);
209+
210+ // The bottom right neighbor fields_to_draw is needed for both triangles
211+ // associated with this field. If it is not in fields_to_draw, there is no need to
212+ // draw any triangles.
213+ if (field.brn_index == FieldsToDraw::kInvalidIndex) {
214+ continue;
215+ }
216+
217+ // Down triangle.
218+ if (field.bln_index != FieldsToDraw::kInvalidIndex) {
219+ RGBAColor color(0, 0, 0, 0);
220+ for (const std::map<Widelands::TCoords<>, uint8_t>& wa_map : workarea) {
221+ const auto it = wa_map.find(Widelands::TCoords<>(field.fcoords, Widelands::TriangleIndex::D));
222+ if (it != wa_map.end()) {
223+ color = apply_color(color, workarea_colors[it->second]);
224+ }
225+ }
226+ add_vertex(fields_to_draw.at(current_index), color);
227+ add_vertex(fields_to_draw.at(field.bln_index), color);
228+ add_vertex(fields_to_draw.at(field.brn_index), color);
229+ }
230+
231+ // Right triangle.
232+ if (field.rn_index != FieldsToDraw::kInvalidIndex) {
233+ RGBAColor color(0, 0, 0, 0);
234+ for (const std::map<Widelands::TCoords<>, uint8_t>& wa_map : workarea) {
235+ const auto it = wa_map.find(Widelands::TCoords<>(field.fcoords, Widelands::TriangleIndex::R));
236+ if (it != wa_map.end()) {
237+ color = apply_color(color, workarea_colors[it->second]);
238+ }
239+ }
240+ add_vertex(fields_to_draw.at(current_index), color);
241+ add_vertex(fields_to_draw.at(field.brn_index), color);
242+ add_vertex(fields_to_draw.at(field.rn_index), color);
243+ }
244+ }
245+
246+ gl_draw(texture_id, z_value);
247+}
248
249=== added file 'src/graphic/gl/workarea_program.h'
250--- src/graphic/gl/workarea_program.h 1970-01-01 00:00:00 +0000
251+++ src/graphic/gl/workarea_program.h 2019-04-24 15:57:58 +0000
252@@ -0,0 +1,78 @@
253+/*
254+ * Copyright (C) 2006-2019 by the Widelands Development Team
255+ *
256+ * This program is free software; you can redistribute it and/or
257+ * modify it under the terms of the GNU General Public License
258+ * as published by the Free Software Foundation; either version 2
259+ * of the License, or (at your option) any later version.
260+ *
261+ * This program is distributed in the hope that it will be useful,
262+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
263+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
264+ * GNU General Public License for more details.
265+ *
266+ * You should have received a copy of the GNU General Public License
267+ * along with this program; if not, write to the Free Software
268+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
269+ *
270+ */
271+
272+#ifndef WL_GRAPHIC_GL_WORKAREA_PROGRAM_H
273+#define WL_GRAPHIC_GL_WORKAREA_PROGRAM_H
274+
275+#include <vector>
276+
277+#include "base/vector.h"
278+#include "graphic/gl/fields_to_draw.h"
279+#include "graphic/gl/utils.h"
280+#include "logic/description_maintainer.h"
281+#include "logic/map_objects/world/terrain_description.h"
282+
283+class WorkareaProgram {
284+public:
285+ // Compiles the program. Throws on errors.
286+ WorkareaProgram();
287+
288+ // Draws the workarea overlay.
289+ void draw(uint32_t texture_id,
290+ Workareas workarea,
291+ const FieldsToDraw& fields_to_draw,
292+ float z_value);
293+
294+private:
295+ struct PerVertexData {
296+ float gl_x;
297+ float gl_y;
298+ float overlay_r;
299+ float overlay_g;
300+ float overlay_b;
301+ float overlay_a;
302+ };
303+ static_assert(sizeof(PerVertexData) == 24, "Wrong padding.");
304+
305+ void gl_draw(int gl_texture, float z_value);
306+
307+ // Adds a vertex to the end of vertices with data from 'field' in order to apply the specified 'overlay'.
308+ void add_vertex(const FieldsToDraw::Field& field, RGBAColor overlay);
309+
310+ // The program used for drawing the workarea overlay.
311+ Gl::Program gl_program_;
312+
313+ // The buffer that will contain 'vertices_' for rendering.
314+ Gl::Buffer<PerVertexData> gl_array_buffer_;
315+
316+ // Attributes.
317+ GLint attr_position_;
318+ GLint attr_overlay_;
319+
320+ // Uniforms.
321+ GLint u_z_value_;
322+
323+ // Objects below are kept around to avoid memory allocations on each frame.
324+ // They could theoretically also be recreated.
325+ std::vector<PerVertexData> vertices_;
326+
327+ DISALLOW_COPY_AND_ASSIGN(WorkareaProgram);
328+};
329+
330+#endif // end of include guard: WL_GRAPHIC_GL_WORKAREA_PROGRAM_H
331
332=== modified file 'src/graphic/render_queue.cc'
333--- src/graphic/render_queue.cc 2019-02-23 11:00:49 +0000
334+++ src/graphic/render_queue.cc 2019-04-24 15:57:58 +0000
335@@ -30,6 +30,7 @@
336 #include "graphic/gl/fill_rect_program.h"
337 #include "graphic/gl/road_program.h"
338 #include "graphic/gl/terrain_program.h"
339+#include "graphic/gl/workarea_program.h"
340
341 namespace {
342
343@@ -142,6 +143,7 @@
344 : next_z_(1),
345 terrain_program_(new TerrainProgram()),
346 dither_program_(new DitherProgram()),
347+ workarea_program_(new WorkareaProgram()),
348 road_program_(new RoadProgram()) {
349 }
350
351@@ -164,6 +166,7 @@
352 case Program::kRect:
353 case Program::kTerrainBase:
354 case Program::kTerrainDither:
355+ case Program::kTerrainWorkarea:
356 case Program::kTerrainRoad:
357 /* all fallthroughs intended */
358 break;
359@@ -251,6 +254,13 @@
360 ++i;
361 } break;
362
363+ case Program::kTerrainWorkarea: {
364+ ScopedScissor scoped_scissor(item.terrain_arguments.destination_rect);
365+ workarea_program_->draw(item.terrain_arguments.terrains->get(0).get_texture(0).blit_data().texture_id,
366+ item.terrain_arguments.workareas, *item.terrain_arguments.fields_to_draw, item.z_value);
367+ ++i;
368+ } break;
369+
370 case Program::kTerrainRoad: {
371 ScopedScissor scoped_scissor(item.terrain_arguments.destination_rect);
372 road_program_->draw(item.terrain_arguments.renderbuffer_width,
373
374=== modified file 'src/graphic/render_queue.h'
375--- src/graphic/render_queue.h 2019-02-23 11:00:49 +0000
376+++ src/graphic/render_queue.h 2019-04-24 15:57:58 +0000
377@@ -38,6 +38,7 @@
378 class DitherProgram;
379 class RoadProgram;
380 class TerrainProgram;
381+class WorkareaProgram;
382
383 // The RenderQueue is a singleton implementing the concept of deferred
384 // rendering: Every rendering call that pretends to draw onto the screen will
385@@ -82,6 +83,7 @@
386 enum Program {
387 kTerrainBase,
388 kTerrainDither,
389+ kTerrainWorkarea,
390 kTerrainRoad,
391 kBlit,
392 kRect,
393@@ -119,6 +121,7 @@
394 int renderbuffer_height = 0;
395 const DescriptionMaintainer<Widelands::TerrainDescription>* terrains = nullptr;
396 const FieldsToDraw* fields_to_draw = nullptr;
397+ Workareas workareas;
398 float scale = 1.f;
399 Rectf destination_rect = Rectf(0.f, 0.f, 0.f, 0.f);
400 };
401@@ -178,6 +181,7 @@
402
403 std::unique_ptr<TerrainProgram> terrain_program_;
404 std::unique_ptr<DitherProgram> dither_program_;
405+ std::unique_ptr<WorkareaProgram> workarea_program_;
406 std::unique_ptr<RoadProgram> road_program_;
407
408 std::vector<Item> blended_items_;
409
410=== modified file 'src/logic/widelands_geometry.h'
411--- src/logic/widelands_geometry.h 2019-02-23 11:00:49 +0000
412+++ src/logic/widelands_geometry.h 2019-04-24 15:57:58 +0000
413@@ -21,6 +21,8 @@
414 #define WL_LOGIC_WIDELANDS_GEOMETRY_H
415
416 #include <cmath>
417+#include <map>
418+#include <set>
419 #include <tuple>
420
421 #include <stdint.h>
422@@ -155,4 +157,6 @@
423 };
424 } // namespace Widelands
425
426+using Workareas = std::set<std::map<Widelands::TCoords<>, uint8_t>>;
427+
428 #endif // end of include guard: WL_LOGIC_WIDELANDS_GEOMETRY_H
429
430=== modified file 'src/wui/buildingwindow.cc'
431--- src/wui/buildingwindow.cc 2019-03-22 18:52:17 +0000
432+++ src/wui/buildingwindow.cc 2019-04-24 15:57:58 +0000
433@@ -320,7 +320,7 @@
434 if (!wa_info->empty()) {
435 toggle_workarea_ =
436 new UI::Button(capsbuttons, "workarea", 0, 0, 34, 34, UI::ButtonStyle::kWuiMenu,
437- g_gr->images().get("images/wui/overlays/workarea123.png"));
438+ g_gr->images().get("images/wui/buildings/toggle_workarea.png"));
439 toggle_workarea_->sigclicked.connect(
440 boost::bind(&BuildingWindow::toggle_workarea, boost::ref(*this)));
441
442
443=== modified file 'src/wui/interactive_base.cc'
444--- src/wui/interactive_base.cc 2019-04-24 06:01:37 +0000
445+++ src/wui/interactive_base.cc 2019-04-24 15:57:58 +0000
446@@ -112,14 +112,7 @@
447 avg_usframetime_(0),
448 buildroad_(nullptr),
449 road_build_player_(0),
450- unique_window_handler_(new UniqueWindowHandler()),
451- // Start at idx 0 for 2 enhancements, idx 3 for 1, idx 5 if none
452- workarea_pics_{g_gr->images().get("images/wui/overlays/workarea123.png"),
453- g_gr->images().get("images/wui/overlays/workarea23.png"),
454- g_gr->images().get("images/wui/overlays/workarea3.png"),
455- g_gr->images().get("images/wui/overlays/workarea12.png"),
456- g_gr->images().get("images/wui/overlays/workarea2.png"),
457- g_gr->images().get("images/wui/overlays/workarea1.png")} {
458+ unique_window_handler_(new UniqueWindowHandler()) {
459
460 // Load the buildhelp icons.
461 {
462@@ -200,8 +193,20 @@
463 return nullptr;
464 }
465
466-bool InteractiveBase::has_workarea_preview(const Widelands::Coords& coords) const {
467- return workarea_previews_.count(coords) == 1;
468+bool InteractiveBase::has_workarea_preview(const Widelands::Coords& coords, const Widelands::Map* map) const {
469+ if (!map) {
470+ return workarea_previews_.count(coords) == 1;
471+ }
472+ for (const auto& pair : workarea_previews_) {
473+ uint32_t radius = 0;
474+ for (const auto& p : *pair.second) {
475+ radius = std::max(radius, p.first);
476+ }
477+ if (map->calc_distance(coords, pair.first) <= radius) {
478+ return true;
479+ }
480+ }
481+ return false;
482 }
483
484 UniqueWindowHandler& InteractiveBase::unique_windows() {
485@@ -303,12 +308,53 @@
486 workarea_previews_[coords] = &workarea_info;
487 }
488
489-std::map<Coords, const Image*>
490-InteractiveBase::get_workarea_overlays(const Widelands::Map& map) const {
491- std::map<Coords, const Image*> result;
492- for (const auto& pair : workarea_previews_) {
493- const Coords& coords = pair.first;
494- const WorkareaInfo* workarea_info = pair.second;
495+/* Helper function to get the correct index for graphic/gl/workarea_program.cc::workarea_colors .
496+ * a, b, c are the indices for the three nodes bordering this triangle.
497+ * This function returns the biggest workarea type that matches all three corners.
498+ * The indices stand for:
499+ * 0 – all three circles
500+ * 1 – medium and outer circle
501+ * 2 – outer circle
502+ * 3 – inner and medium circle
503+ * 4 – medium circle
504+ * 5 – inner circle
505+ * We currently assume that no building will have more than three workarea circles.
506+ */
507+static uint8_t workarea_max(uint8_t a, uint8_t b, uint8_t c) {
508+ // Whether all nodes are part of the inner circle
509+ bool inner = (a == 0 || a == 3 || a == 5) && (b == 0 || b == 3 || b == 5) && (c == 0 || c == 3 || c == 5);
510+ // Whether all nodes are part of the medium circle
511+ bool medium = (a == 0 || a == 1 || a == 3 || a == 4) && (b == 0 || b == 1 || b == 3 || b == 4) &&
512+ (c == 0 || c == 1 || c == 3 || c == 4);
513+ // Whether all nodes are part of the outer circle
514+ bool outer = a <= 2 && b <= 2 && c <= 2;
515+
516+ if (medium) {
517+ if (outer && inner) {
518+ return 0;
519+ } else if (inner) {
520+ return 3;
521+ } else if (outer) {
522+ return 1;
523+ } else {
524+ return 4;
525+ }
526+ } else if (outer) {
527+ assert(!inner);
528+ return 2;
529+ } else {
530+ assert(inner);
531+ return 5;
532+ }
533+}
534+
535+Workareas InteractiveBase::get_workarea_overlays(const Widelands::Map& map) const {
536+ Workareas result_set;
537+ for (const auto& wa_pair : workarea_previews_) {
538+ std::map<Coords, uint8_t> intermediate_result;
539+ const Coords& coords = wa_pair.first;
540+ const WorkareaInfo* workarea_info = wa_pair.second;
541+ intermediate_result[coords] = 0;
542 WorkareaInfo::size_type wa_index;
543 switch (workarea_info->size()) {
544 case 0:
545@@ -335,13 +381,36 @@
546 hollow_area.radius = it->first;
547 Widelands::MapHollowRegion<> mr(map, hollow_area);
548 do {
549- result[mr.location()] = workarea_pics_[wa_index];
550+ intermediate_result[mr.location()] = wa_index;
551 } while (mr.advance(map));
552 wa_index++;
553 hollow_area.hole_radius = hollow_area.radius;
554 }
555+
556+ std::map<TCoords<>, uint8_t> result;
557+ for (const auto& pair : intermediate_result) {
558+ Coords c;
559+ map.get_brn(pair.first, &c);
560+ const auto brn = intermediate_result.find(c);
561+ if (brn == intermediate_result.end()) {
562+ continue;
563+ }
564+ map.get_bln(pair.first, &c);
565+ const auto bln = intermediate_result.find(c);
566+ map.get_rn(pair.first, &c);
567+ const auto rn = intermediate_result.find(c);
568+ if (bln != intermediate_result.end()) {
569+ result[TCoords<>(pair.first, Widelands::TriangleIndex::D)] = workarea_max(
570+ pair.second, brn->second, bln->second);
571+ }
572+ if (rn != intermediate_result.end()) {
573+ result[TCoords<>(pair.first, Widelands::TriangleIndex::R)] = workarea_max(
574+ pair.second, brn->second, rn->second);
575+ }
576+ }
577+ result_set.emplace(result);
578 }
579- return result;
580+ return result_set;
581 }
582
583 void InteractiveBase::hide_workarea(const Widelands::Coords& coords) {
584
585=== modified file 'src/wui/interactive_base.h'
586--- src/wui/interactive_base.h 2019-04-19 07:27:15 +0000
587+++ src/wui/interactive_base.h 2019-04-24 15:57:58 +0000
588@@ -231,7 +231,7 @@
589 TextToDraw get_text_to_draw() const;
590
591 // Returns the current overlays for the work area previews.
592- std::map<Widelands::Coords, const Image*> get_workarea_overlays(const Widelands::Map& map) const;
593+ Workareas get_workarea_overlays(const Widelands::Map& map) const;
594
595 // Returns the 'BuildhelpOverlay' for 'caps' or nullptr if there is no help
596 // to be displayed on this field.
597@@ -241,8 +241,10 @@
598 return road_building_overlays_;
599 }
600
601- /// Returns true if there is a workarea preview being shown at the given coordinates
602- bool has_workarea_preview(const Widelands::Coords& coords) const;
603+ /// Returns true if there is a workarea preview being shown at the given coordinates.
604+ /// If 'map' is 0, checks only if the given coords are the center of a workarea;
605+ /// otherwise checks if the coords are within any workarea.
606+ bool has_workarea_preview(const Widelands::Coords& coords, const Widelands::Map* map = nullptr) const;
607
608 /// Returns true if the current player is allowed to hear sounds from map objects on this field
609 virtual bool player_hears_field(const Widelands::Coords& coords) const = 0;
610@@ -304,7 +306,6 @@
611
612 UI::UniqueWindow::Registry debugconsole_;
613 std::unique_ptr<UniqueWindowHandler> unique_window_handler_;
614- std::vector<const Image*> workarea_pics_;
615 BuildhelpOverlay buildhelp_overlays_[Widelands::Field::Buildhelp_None];
616 };
617
618
619=== modified file 'src/wui/interactive_player.cc'
620--- src/wui/interactive_player.cc 2019-04-24 06:01:37 +0000
621+++ src/wui/interactive_player.cc 2019-04-24 15:57:58 +0000
622@@ -160,7 +160,8 @@
623 bool const multiplayer)
624 : InteractiveGameBase(g, global_s, NONE, multiplayer),
625 auto_roadbuild_mode_(global_s.get_bool("auto_roadbuild_mode", true)),
626- flag_to_connect_(Widelands::Coords::null()) {
627+ flag_to_connect_(Widelands::Coords::null()),
628+ grid_marker_pic_(g_gr->images().get("images/wui/overlays/grid_marker.png")) {
629 add_toolbar_button(
630 "wui/menus/menu_options_menu", "options_menu", _("Main menu"), &options_, true);
631 options_.open_window = [this] { new GameOptionsMenu(*this, options_, main_windows_); };
632@@ -286,9 +287,9 @@
633 const Widelands::Map& map = gbase.map();
634 const uint32_t gametime = gbase.get_gametime();
635
636- auto* fields_to_draw = given_map_view->draw_terrain(gbase, dst);
637+ Workareas workareas = get_workarea_overlays(map);
638+ auto* fields_to_draw = given_map_view->draw_terrain(gbase, workareas, dst);
639 const auto& road_building = road_building_overlays();
640- const std::map<Widelands::Coords, const Image*> workarea_overlays = get_workarea_overlays(map);
641
642 const float scale = 1.f / given_map_view->view().zoom;
643
644@@ -329,13 +330,10 @@
645 }
646 }
647
648- // Draw work area previews.
649- {
650- const auto it = workarea_overlays.find(f->fcoords);
651- if (it != workarea_overlays.end()) {
652- blit_field_overlay(dst, *f, it->second,
653- Vector2i(it->second->width() / 2, it->second->height() / 2), scale);
654- }
655+ // Draw work area markers.
656+ if (has_workarea_preview(f->fcoords, &map)) {
657+ blit_field_overlay(dst, *f, grid_marker_pic_,
658+ Vector2i(grid_marker_pic_->width() / 2, grid_marker_pic_->height() / 2), scale);
659 }
660
661 if (f->vision > 0) {
662
663=== modified file 'src/wui/interactive_player.h'
664--- src/wui/interactive_player.h 2019-03-14 23:06:02 +0000
665+++ src/wui/interactive_player.h 2019-04-24 15:57:58 +0000
666@@ -91,6 +91,8 @@
667 UI::UniqueWindow::Registry objectives_;
668 UI::UniqueWindow::Registry encyclopedia_;
669 UI::UniqueWindow::Registry message_menu_;
670+
671+ const Image* grid_marker_pic_;
672 };
673
674 #endif // end of include guard: WL_WUI_INTERACTIVE_PLAYER_H
675
676=== modified file 'src/wui/interactive_spectator.cc'
677--- src/wui/interactive_spectator.cc 2019-04-24 06:01:37 +0000
678+++ src/wui/interactive_spectator.cc 2019-04-24 15:57:58 +0000
679@@ -116,12 +116,11 @@
680
681 const Widelands::Game& the_game = game();
682 const Widelands::Map& map = the_game.map();
683- auto* fields_to_draw = given_map_view->draw_terrain(the_game, dst);
684+ auto* fields_to_draw = given_map_view->draw_terrain(the_game, get_workarea_overlays(map), dst);
685 const float scale = 1.f / given_map_view->view().zoom;
686 const uint32_t gametime = the_game.get_gametime();
687
688 const auto text_to_draw = get_text_to_draw();
689- const std::map<Widelands::Coords, const Image*> workarea_overlays = get_workarea_overlays(map);
690 for (size_t idx = 0; idx < fields_to_draw->size(); ++idx) {
691 const FieldsToDraw::Field& field = fields_to_draw->at(idx);
692
693@@ -137,13 +136,6 @@
694 bob->draw(the_game, text_to_draw, field.rendertarget_pixel, field.fcoords, scale, dst);
695 }
696
697- // Draw work area previews.
698- const auto it = workarea_overlays.find(field.fcoords);
699- if (it != workarea_overlays.end()) {
700- const Image* pic = it->second;
701- blit_field_overlay(dst, field, pic, Vector2i(pic->width() / 2, pic->height() / 2), scale);
702- }
703-
704 // Draw build help.
705 if (buildhelp()) {
706 auto caps = Widelands::NodeCaps::CAPS_NONE;
707
708=== modified file 'src/wui/mapview.cc'
709--- src/wui/mapview.cc 2019-04-23 16:24:40 +0000
710+++ src/wui/mapview.cc 2019-04-24 15:57:58 +0000
711@@ -339,7 +339,7 @@
712 NEVER_HERE();
713 }
714
715-FieldsToDraw* MapView::draw_terrain(const Widelands::EditorGameBase& egbase, RenderTarget* dst) {
716+FieldsToDraw* MapView::draw_terrain(const Widelands::EditorGameBase& egbase, Workareas workarea, RenderTarget* dst) {
717 uint32_t now = SDL_GetTicks();
718 while (!view_plans_.empty()) {
719 auto& plan = view_plans_.front();
720@@ -383,7 +383,7 @@
721
722 fields_to_draw_.reset(egbase, view_.viewpoint, view_.zoom, dst);
723 const float scale = 1.f / view_.zoom;
724- ::draw_terrain(egbase, fields_to_draw_, scale, dst);
725+ ::draw_terrain(egbase, fields_to_draw_, scale, workarea, dst);
726 return &fields_to_draw_;
727 }
728
729
730=== modified file 'src/wui/mapview.h'
731--- src/wui/mapview.h 2019-03-26 02:56:03 +0000
732+++ src/wui/mapview.h 2019-04-24 15:57:58 +0000
733@@ -172,7 +172,7 @@
734 // Schedules drawing of the terrain of this MapView. The returned value can
735 // be used to override contents of 'fields_to_draw' for player knowledge and
736 // visibility, and to correctly draw map objects, overlays and text.
737- FieldsToDraw* draw_terrain(const Widelands::EditorGameBase& egbase, RenderTarget* dst);
738+ FieldsToDraw* draw_terrain(const Widelands::EditorGameBase& egbase, Workareas workarea, RenderTarget* dst);
739
740 // Not overriden from UI::Panel, instead we expect to be passed the data through.
741 bool handle_mousepress(uint8_t btn, int32_t x, int32_t y);

Subscribers

People subscribed via source and target branches

to status/vote changes: