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

Proposed by SirVer
Status: Merged
Merged at revision: 7305
Proposed branch: lp:~widelands-dev/widelands/cleanup_game_renderer
Merge into: lp:widelands
Prerequisite: lp:~widelands-dev/widelands/use_sdl_image_in_one_place
Diff against target: 1238 lines (+349/-509)
16 files modified
src/editor/CMakeLists.txt (+2/-0)
src/game_io/CMakeLists.txt (+3/-0)
src/graphic/CMakeLists.txt (+44/-17)
src/graphic/colormap.cc (+0/-58)
src/graphic/colormap.h (+0/-51)
src/graphic/game_renderer.cc (+218/-73)
src/graphic/game_renderer.h (+39/-49)
src/graphic/gl/game_renderer.cc (+0/-191)
src/graphic/gl/game_renderer.h (+0/-48)
src/graphic/rendertarget.cc (+0/-1)
src/logic/CMakeLists.txt (+3/-0)
src/map_io/CMakeLists.txt (+1/-0)
src/scripting/CMakeLists.txt (+1/-0)
src/sound/CMakeLists.txt (+1/-0)
src/wui/CMakeLists.txt (+27/-6)
src/wui/mapview.cc (+10/-15)
To merge this branch: bzr merge lp:~widelands-dev/widelands/cleanup_game_renderer
Reviewer Review Type Date Requested Status
GunChleoc Approve
Review via email: mp+243124@code.launchpad.net

Description of the change

This is bart of some chained branches. The base branches need to be merged before this.

Suggested commit message:
- Consolidated GameRenderer and its only base class into one.
- Pulled map renderer and minimap renderer into their own library. It becomes clear that we have basic graphics library and a widelands aware one.
- Removed unused files.

---
We should think about changing the directory layout of src. We have at least a wl/ui (wui) base/ui (ui_basic), wl/scripting (most of it), base/scripting (LuaTable at least) , wl/graphic (game renderer, minimap renderer) and base/graphic (surfaces, texture_atlas and so on).

I do not like the name base/ for the "basic" libraries. The separation is "could be useful for other projects" and "is widelands aware". Suggestions for cool names?

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

global? general? wl-lib? common? core? root? shared?

While we're restructuring, should we separate wl/game and wl/editor?

Revision history for this message
SirVer (sirver) wrote :

I like core and base. I like base the most, but we already have a base/. however, nothing stops use from using base/ui base/graphic and so on and just keep the current base directories in base/

Revision history for this message
GunChleoc (gunchleoc) wrote :

Sounds good to me. Do you want o change the directories in this branch, or shall we have a new branch for that?

Revision history for this message
SirVer (sirver) wrote :

other branch, definitively. this change already got bigger than i wanted it to be and I also want to ships this asap.

Revision history for this message
GunChleoc (gunchleoc) wrote :

Fixed 2 nits myself + tested. LGTM.

I love these graphic changes, Widelands is now noticeably faster on my machine.

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

Thanks for the review and the fixes. :)

> I love these graphic changes, Widelands is now noticeably faster on my machine.

Great, that keeps me motivated.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'src/editor/CMakeLists.txt'
2--- src/editor/CMakeLists.txt 2014-10-13 15:04:50 +0000
3+++ src/editor/CMakeLists.txt 2014-12-04 20:54:56 +0000
4@@ -104,4 +104,6 @@
5 ui_fsmenu
6 widelands_ball_of_mud
7 wui
8+ wui_mapview_pixelfunctions
9+ wui_overlay_manager
10 )
11
12=== modified file 'src/game_io/CMakeLists.txt'
13--- src/game_io/CMakeLists.txt 2014-11-24 06:31:16 +0000
14+++ src/game_io/CMakeLists.txt 2014-12-04 20:54:56 +0000
15@@ -27,6 +27,7 @@
16 base_time_string
17 economy
18 graphic
19+ graphic_minimap_renderer
20 io_fileread
21 io_filesystem
22 logic
23@@ -36,4 +37,6 @@
24 profile
25 scripting
26 wui
27+ wui_mapview_pixelfunctions
28+ wui_overlay_manager
29 )
30
31=== modified file 'src/graphic/CMakeLists.txt'
32--- src/graphic/CMakeLists.txt 2014-12-03 19:14:07 +0000
33+++ src/graphic/CMakeLists.txt 2014-12-04 20:54:56 +0000
34@@ -1,5 +1,8 @@
35 add_subdirectory(text)
36
37+# TODO(sirver): Separate this directory into a base directory and one
38+# that is Widelands aware (can include logic stuff).
39+
40 wl_library(graphic_color
41 SRCS
42 color.h
43@@ -77,14 +80,52 @@
44 graphic_surface
45 )
46
47+wl_library(graphic_game_renderer
48+ SRCS
49+ game_renderer.cc
50+ game_renderer.h
51+ gl/dither_program.cc
52+ gl/dither_program.h
53+ gl/fields_to_draw.h
54+ gl/road_program.cc
55+ gl/road_program.h
56+ gl/terrain_program.cc
57+ gl/terrain_program.h
58+ DEPENDS
59+ base_exceptions
60+ base_geometry
61+ base_log
62+ base_macros
63+ graphic
64+ graphic_image_io
65+ graphic_surface
66+ io_filesystem
67+ logic
68+ wui_mapview_pixelfunctions
69+ wui_overlay_manager
70+)
71+
72+wl_library(graphic_minimap_renderer
73+ SRCS
74+ minimap_renderer.cc
75+ minimap_renderer.h
76+ DEPENDS
77+ base_geometry
78+ base_macros
79+ economy
80+ graphic
81+ graphic_image
82+ graphic_surface
83+ logic
84+ wui_mapview_pixelfunctions
85+)
86+
87 wl_library(graphic
88 SRCS
89 align.cc
90 align.h
91 animation.cc
92 animation.h
93- colormap.cc
94- colormap.h
95 default_resolution.h
96 diranimations.h
97 font.cc
98@@ -93,34 +134,21 @@
99 font_handler.h
100 font_handler1.cc
101 font_handler1.h
102- game_renderer.cc
103- game_renderer.h
104 gl/blit_program.cc
105 gl/blit_program.h
106- gl/dither_program.cc
107- gl/dither_program.h
108 gl/draw_line_program.cc
109 gl/draw_line_program.h
110 gl/draw_rect_program.cc
111 gl/draw_rect_program.h
112- gl/fields_to_draw.h
113 gl/fill_rect_program.cc
114 gl/fill_rect_program.h
115- gl/game_renderer.cc
116- gl/game_renderer.h
117- gl/road_program.cc
118- gl/road_program.h
119 gl/system_headers.h
120- gl/terrain_program.cc
121- gl/terrain_program.h
122 graphic.cc
123 graphic.h
124 image_transformations.cc
125 image_transformations.h
126 in_memory_image.cc
127 in_memory_image.h
128- minimap_renderer.cc
129- minimap_renderer.h
130 rendertarget.cc
131 rendertarget.h
132 richtext.cc
133@@ -139,7 +167,6 @@
134 base_log
135 base_macros
136 build_info
137- economy
138 graphic_color
139 graphic_image
140 graphic_image_io
141@@ -154,6 +181,6 @@
142 profile
143 scripting
144 sound
145- wui
146+ wui_overlay_manager
147 wui_text_layout
148 )
149
150=== removed file 'src/graphic/colormap.cc'
151--- src/graphic/colormap.cc 2014-07-17 13:26:23 +0000
152+++ src/graphic/colormap.cc 1970-01-01 00:00:00 +0000
153@@ -1,58 +0,0 @@
154-/*
155- * Copyright (C) 2002-2004, 2006, 2009 by the Widelands Development Team
156- *
157- * This program is free software; you can redistribute it and/or
158- * modify it under the terms of the GNU General Public License
159- * as published by the Free Software Foundation; either version 2
160- * of the License, or (at your option) any later version.
161- *
162- * This program is distributed in the hope that it will be useful,
163- * but WITHOUT ANY WARRANTY; without even the implied warranty of
164- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
165- * GNU General Public License for more details.
166- *
167- * You should have received a copy of the GNU General Public License
168- * along with this program; if not, write to the Free Software
169- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
170- *
171- */
172-
173-#include "graphic/colormap.h"
174-
175-#include <algorithm>
176-#include <cassert>
177-#include <cstdlib>
178-#include <cstring>
179-
180-/**
181- * Create a new Colormap, taking the palette as a parameter.
182- * It automatically creates the colormap for shading.
183- */
184-Colormap::Colormap (const SDL_Color & pal, const SDL_PixelFormat & format) {
185- memcpy(palette, &pal, sizeof(palette));
186-
187- assert(format.BytesPerPixel == 4);
188- colormap = malloc(format.BytesPerPixel * 65536);
189-
190- for (int i = 0; i < 256; ++i)
191- for (int j = 0; j < 256; ++j) {
192- int32_t shade = (j < 128) ? j : (j - 256);
193- shade = 256 + 2 * shade;
194-
195- const uint32_t r = std::min<uint32_t>((palette[i].r * shade) >> 8, 255);
196- const uint32_t g = std::min<uint32_t>((palette[i].g * shade) >> 8, 255);
197- const uint32_t b = std::min<uint32_t>((palette[i].b * shade) >> 8, 255);
198-
199- const uint32_t value =
200- SDL_MapRGB(&const_cast<SDL_PixelFormat &>(format), r, g, b);
201- static_cast<uint32_t *>(colormap)[(j << 8) | i] = value;
202- }
203-}
204-
205-/**
206- * Clean up.
207- */
208-Colormap::~Colormap ()
209-{
210- free(colormap);
211-}
212
213=== removed file 'src/graphic/colormap.h'
214--- src/graphic/colormap.h 2014-07-12 12:25:21 +0000
215+++ src/graphic/colormap.h 1970-01-01 00:00:00 +0000
216@@ -1,51 +0,0 @@
217-/*
218- * Copyright (C) 2002-2004, 2006, 2008 by the Widelands Development Team
219- *
220- * This program is free software; you can redistribute it and/or
221- * modify it under the terms of the GNU General Public License
222- * as published by the Free Software Foundation; either version 2
223- * of the License, or (at your option) any later version.
224- *
225- * This program is distributed in the hope that it will be useful,
226- * but WITHOUT ANY WARRANTY; without even the implied warranty of
227- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
228- * GNU General Public License for more details.
229- *
230- * You should have received a copy of the GNU General Public License
231- * along with this program; if not, write to the Free Software
232- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
233- *
234- */
235-
236-#ifndef WL_GRAPHIC_COLORMAP_H
237-#define WL_GRAPHIC_COLORMAP_H
238-
239-#include <SDL_video.h>
240-
241-#include "graphic/color.h"
242-
243-/**
244- * Colormap contains a palette and lookup table for use with ground textures.
245-*/
246-class Colormap {
247-public:
248- Colormap (const SDL_Color &, const SDL_PixelFormat & fmt);
249- ~Colormap ();
250-
251- // Returns the palette of this colormap (256 entries of RGB Colors);
252- SDL_Color * get_palette() {return palette;}
253-
254- // Returns the internally calculated colormap used in the renderer.
255- void * get_colormap () const {return colormap;}
256-
257-private:
258- SDL_Color palette[256];
259-
260- /// maps 8 bit color and brightness value to the shaded color.
261- /// \note Brightness is currently 8 bits. Restricting brightness to 64 or
262- /// less shades would greatly reduce the size of this table, and thus
263- /// improve memory cache impact inside the renderer.
264- void * colormap;
265-};
266-
267-#endif // end of include guard: WL_GRAPHIC_COLORMAP_H
268
269=== modified file 'src/graphic/game_renderer.cc'
270--- src/graphic/game_renderer.cc 2014-09-27 18:53:55 +0000
271+++ src/graphic/game_renderer.cc 2014-12-04 20:54:56 +0000
272@@ -19,82 +19,227 @@
273
274 #include "graphic/game_renderer.h"
275
276-#include "base/macros.h"
277+#include <memory>
278+
279+#include "graphic/gl/dither_program.h"
280+#include "graphic/gl/fields_to_draw.h"
281+#include "graphic/gl/road_program.h"
282+#include "graphic/gl/terrain_program.h"
283 #include "graphic/graphic.h"
284 #include "graphic/rendertarget.h"
285+#include "graphic/surface.h"
286 #include "logic/editor_game_base.h"
287 #include "logic/player.h"
288+#include "logic/world/world.h"
289+#include "wui/mapviewpixelconstants.h"
290 #include "wui/mapviewpixelfunctions.h"
291 #include "wui/overlay_manager.h"
292
293+// Explanation of how drawing works:
294+// Schematic of triangle neighborhood:
295+//
296+// *
297+// / \
298+// / u \
299+// (f)/ \
300+// *------*------* (r)
301+// \ l / \ r / \
302+// \ / \ / \
303+// \/ d \/ rr \
304+// *------*------* (br)
305+// \ dd /
306+// \ /
307+// \/
308+// *
309+//
310+// Each field (f) owns two triangles: (r)ight & (d)own. When we look at the
311+// field, we have to make sure to schedule drawing the triangles. This is done
312+// by of these triangles is done by TerrainProgram.
313+//
314+// To draw dithered edges, we have to look at the neighboring triangles for the
315+// two triangles too: If a neighboring triangle has another texture and our
316+// dither layer is smaller, we have to draw a dithering triangle too - this lets the neighboring
317+// texture
318+// bleed into our triangle.
319+//
320+// The dither triangle is the triangle that should be partially (either r or
321+// d). Example: if r and d have different textures and r.dither_layer >
322+// d.dither_layer, then we will repaint d with the dither texture as mask.
323+
324+std::unique_ptr<TerrainProgram> GameRenderer::terrain_program_;
325+std::unique_ptr<DitherProgram> GameRenderer::dither_program_;
326+std::unique_ptr<RoadProgram> GameRenderer::road_program_;
327+
328+namespace {
329+
330 using namespace Widelands;
331
332-GameRenderer::GameRenderer()
333-{
334-}
335-
336-GameRenderer::~GameRenderer()
337-{
338-}
339-
340-void GameRenderer::rendermap
341- (RenderTarget & dst,
342- const Widelands::EditorGameBase & egbase,
343- const Widelands::Player & player,
344- const Point & viewofs)
345-{
346- m_dst = &dst;
347- m_dst_offset = -viewofs;
348- m_egbase = &egbase;
349- m_player = &player;
350-
351- draw_wrapper();
352-}
353-
354-void GameRenderer::rendermap
355- (RenderTarget & dst,
356- const Widelands::EditorGameBase & egbase,
357- const Point & viewofs)
358-{
359- m_dst = &dst;
360- m_dst_offset = -viewofs;
361- m_egbase = &egbase;
362- m_player = nullptr;
363-
364- draw_wrapper();
365-}
366-
367-void GameRenderer::draw_wrapper()
368-{
369- Point tl_map = m_dst->get_offset() - m_dst_offset;
370+// Returns the brightness value in [0, 1.] for 'fcoords' at 'gametime' for
371+// 'player' (which can be nullptr).
372+float field_brightness(const FCoords& fcoords,
373+ const uint32_t gametime,
374+ const Map& map,
375+ const Player* const player) {
376+ uint32_t brightness = 144 + fcoords.field->get_brightness();
377+ brightness = std::min<uint32_t>(255, (brightness * 255) / 160);
378+
379+ if (player && !player->see_all()) {
380+ const Player::Field& pf = player->fields()[Map::get_index(fcoords, map.get_width())];
381+ if (pf.vision == 0) {
382+ return 0.;
383+ } else if (pf.vision == 1) {
384+ static const uint32_t kDecayTimeInMs = 20000;
385+ const Duration time_ago = gametime - pf.time_node_last_unseen;
386+ if (time_ago < kDecayTimeInMs) {
387+ brightness = (brightness * (2 * kDecayTimeInMs - time_ago)) / (2 * kDecayTimeInMs);
388+ } else {
389+ brightness = brightness / 2;
390+ }
391+ }
392+ }
393+ return brightness / 255.;
394+}
395+
396+// Returns the road that should be rendered here. The format is like in field,
397+// but this is not the physically present road, but the one that should be
398+// drawn (i.e. taking into account if there is fog of war involved or road
399+// building overlays enabled).
400+uint8_t field_roads(const FCoords& coords, const Map& map, const Player* const player) {
401+ uint8_t roads;
402+ if (player && !player->see_all()) {
403+ const Player::Field& pf = player->fields()[Map::get_index(coords, map.get_width())];
404+ roads = pf.roads | map.overlay_manager().get_road_overlay(coords);
405+ } else {
406+ roads = coords.field->get_roads();
407+ }
408+ roads |= map.overlay_manager().get_road_overlay(coords);
409+ return roads;
410+}
411+
412+} // namespace
413+
414+GameRenderer::GameRenderer() {
415+}
416+
417+GameRenderer::~GameRenderer() {
418+}
419+
420+void GameRenderer::rendermap(RenderTarget& dst,
421+ const Widelands::EditorGameBase& egbase,
422+ const Point& view_offset,
423+
424+ const Widelands::Player& player) {
425+ draw(dst, egbase, view_offset, &player);
426+}
427+
428+void GameRenderer::rendermap(RenderTarget& dst,
429+ const Widelands::EditorGameBase& egbase,
430+ const Point& view_offset) {
431+ draw(dst, egbase, view_offset, nullptr);
432+}
433+
434+void GameRenderer::draw(RenderTarget& dst,
435+ const EditorGameBase& egbase,
436+ const Point& view_offset,
437+ const Player* player) {
438+ if (terrain_program_ == nullptr) {
439+ terrain_program_.reset(new TerrainProgram());
440+ dither_program_.reset(new DitherProgram());
441+ road_program_.reset(new RoadProgram());
442+ }
443+
444+ Point tl_map = dst.get_offset() + view_offset;
445
446 assert(tl_map.x >= 0); // divisions involving negative numbers are bad
447 assert(tl_map.y >= 0);
448
449- m_minfx = tl_map.x / TRIANGLE_WIDTH - 1;
450- m_minfy = tl_map.y / TRIANGLE_HEIGHT - 1;
451- m_maxfx = (tl_map.x + m_dst->get_rect().w + (TRIANGLE_WIDTH / 2)) / TRIANGLE_WIDTH;
452- m_maxfy = (tl_map.y + m_dst->get_rect().h) / TRIANGLE_HEIGHT;
453+ int minfx = tl_map.x / TRIANGLE_WIDTH - 1;
454+ int minfy = tl_map.y / TRIANGLE_HEIGHT - 1;
455+ int maxfx = (tl_map.x + dst.get_rect().w + (TRIANGLE_WIDTH / 2)) / TRIANGLE_WIDTH;
456+ int maxfy = (tl_map.y + dst.get_rect().h) / TRIANGLE_HEIGHT;
457
458 // fudge for triangle boundary effects and for height differences
459- m_minfx -= 1;
460- m_minfy -= 1;
461- m_maxfx += 1;
462- m_maxfy += 10;
463-
464- draw();
465+ minfx -= 1;
466+ minfy -= 1;
467+ maxfx += 1;
468+ maxfy += 10;
469+
470+
471+ Surface* surface = dst.get_surface();
472+ if (!surface)
473+ return;
474+
475+ const Rect& bounding_rect = dst.get_rect();
476+ const Point surface_offset = bounding_rect.top_left() + dst.get_offset() - view_offset;
477+
478+ glScissor(bounding_rect.x,
479+ surface->height() - bounding_rect.y - bounding_rect.h,
480+ bounding_rect.w,
481+ bounding_rect.h);
482+ glEnable(GL_SCISSOR_TEST);
483+
484+ Map& map = egbase.map();
485+ const uint32_t gametime = egbase.get_gametime();
486+
487+ FieldsToDraw fields_to_draw(minfx, maxfx, minfy, maxfy);
488+ for (int32_t fy = minfy; fy <= maxfy; ++fy) {
489+ for (int32_t fx = minfx; fx <= maxfx; ++fx) {
490+ FieldsToDraw::Field& f =
491+ *fields_to_draw.mutable_field(fields_to_draw.calculate_index(fx, fy));
492+
493+ f.fx = fx;
494+ f.fy = fy;
495+
496+ Coords coords(fx, fy);
497+ int x, y;
498+ MapviewPixelFunctions::get_basepix(coords, x, y);
499+
500+ map.normalize_coords(coords);
501+ const FCoords& fcoords = map.get_fcoords(coords);
502+
503+ f.texture_x = float(x) / kTextureSideLength;
504+ f.texture_y = float(y) / kTextureSideLength;
505+
506+ f.gl_x = f.pixel_x = x + surface_offset.x;
507+ f.gl_y = f.pixel_y = y + surface_offset.y - fcoords.field->get_height() * HEIGHT_FACTOR;
508+ surface->pixel_to_gl(&f.gl_x, &f.gl_y);
509+
510+ f.ter_d = fcoords.field->terrain_d();
511+ f.ter_r = fcoords.field->terrain_r();
512+
513+ f.brightness = field_brightness(fcoords, gametime, map, player);
514+
515+ f.roads = field_roads(fcoords, map, player);
516+ }
517+ }
518+
519+ const World& world = egbase.world();
520+ terrain_program_->draw(gametime, world.terrains(), fields_to_draw);
521+ dither_program_->draw(gametime, world.terrains(), fields_to_draw);
522+ road_program_->draw(*surface, fields_to_draw);
523+
524+ draw_objects(dst, egbase, view_offset, player, minfx, maxfx, minfy, maxfy);
525+
526+ glDisable(GL_SCISSOR_TEST);
527 }
528
529-void GameRenderer::draw_objects()
530-{
531+void GameRenderer::draw_objects(RenderTarget& dst,
532+ const EditorGameBase& egbase,
533+ const Point& view_offset,
534+ const Player* player,
535+ int minfx,
536+ int maxfx,
537+ int minfy,
538+ int maxfy) {
539+ // TODO(sirver): this should use FieldsToDraw. Would simplify this function a lot.
540 static const uint32_t F = 0;
541 static const uint32_t R = 1;
542 static const uint32_t BL = 2;
543 static const uint32_t BR = 3;
544- const Map & map = m_egbase->map();
545+ const Map & map = egbase.map();
546
547- for (int32_t fy = m_minfy; fy <= m_maxfy; ++fy) {
548- for (int32_t fx = m_minfx; fx <= m_maxfx; ++fx) {
549+ for (int32_t fy = minfy; fy <= maxfy; ++fy) {
550+ for (int32_t fx = minfx; fx <= maxfx; ++fx) {
551 Coords ncoords(fx, fy);
552 map.normalize_coords(ncoords);
553 FCoords coords[4];
554@@ -109,7 +254,7 @@
555 MapviewPixelFunctions::get_basepix(Coords(fx + (fy & 1), fy + 1), pos[BR].x, pos[BR].y);
556 for (uint32_t d = 0; d < 4; ++d) {
557 pos[d].y -= coords[d].field->get_height() * HEIGHT_FACTOR;
558- pos[d] += m_dst_offset;
559+ pos[d] -= view_offset;
560 }
561
562 PlayerNumber owner_number[4];
563@@ -120,9 +265,9 @@
564 for (uint32_t d = 0; d < 4; ++d)
565 isborder[d] = coords[d].field->is_border();
566
567- if (m_player && !m_player->see_all()) {
568+ if (player && !player->see_all()) {
569 for (uint32_t d = 0; d < 4; ++d) {
570- const Player::Field & pf = m_player->fields()[map.get_index(coords[d], map.get_width())];
571+ const Player::Field & pf = player->fields()[map.get_index(coords[d], map.get_width())];
572 vision[d] = pf.vision;
573 if (pf.vision == 1) {
574 owner_number[d] = pf.owner;
575@@ -132,32 +277,32 @@
576 }
577
578 if (isborder[F]) {
579- const Player & owner = m_egbase->player(owner_number[F]);
580+ const Player & owner = egbase.player(owner_number[F]);
581 uint32_t const anim_idx = owner.tribe().frontier_animation();
582 if (vision[F])
583- m_dst->drawanim(pos[F], anim_idx, 0, &owner);
584+ dst.drawanim(pos[F], anim_idx, 0, &owner);
585 for (uint32_t d = 1; d < 4; ++d) {
586 if
587 ((vision[F] || vision[d]) &&
588 isborder[d] &&
589 (owner_number[d] == owner_number[F] || !owner_number[d]))
590 {
591- m_dst->drawanim(middle(pos[F], pos[d]), anim_idx, 0, &owner);
592+ dst.drawanim(middle(pos[F], pos[d]), anim_idx, 0, &owner);
593 }
594 }
595 }
596
597 if (1 < vision[F]) { // Render stuff that belongs to the node.
598 if (BaseImmovable * const imm = coords[F].field->get_immovable())
599- imm->draw(*m_egbase, *m_dst, coords[F], pos[F]);
600+ imm->draw(egbase, dst, coords[F], pos[F]);
601 for
602 (Bob * bob = coords[F].field->get_first_bob();
603 bob;
604 bob = bob->get_next_bob())
605- bob->draw(*m_egbase, *m_dst, pos[F]);
606+ bob->draw(egbase, dst, pos[F]);
607 } else if (vision[F] == 1) {
608- const Player::Field & f_pl = m_player->fields()[map.get_index(coords[F], map.get_width())];
609- const Player * owner = owner_number[F] ? m_egbase->get_player(owner_number[F]) : nullptr;
610+ const Player::Field & f_pl = player->fields()[map.get_index(coords[F], map.get_width())];
611+ const Player * owner = owner_number[F] ? egbase.get_player(owner_number[F]) : nullptr;
612 if
613 (const MapObjectDescr * const map_object_descr =
614 f_pl.map_object_descr[TCoords<>::None])
615@@ -193,7 +338,7 @@
616
617 if (cur_frame) // not the first frame
618 // draw the prev frame from top to where next image will be drawing
619- m_dst->drawanimrect
620+ dst.drawanimrect
621 (pos[F], anim_idx, tanim - FRAME_LENGTH, owner, Rect(Point(0, 0), w, h - lines));
622 else if (csinf.was) {
623 // Is the first frame, but there was another building here before,
624@@ -204,11 +349,11 @@
625 } catch (MapObjectDescr::AnimationNonexistent &) {
626 a = csinf.was->get_animation("idle");
627 }
628- m_dst->drawanimrect
629+ dst.drawanimrect
630 (pos[F], a, tanim - FRAME_LENGTH, owner, Rect(Point(0, 0), w, h - lines));
631 }
632 assert(lines <= h);
633- m_dst->drawanimrect(pos[F], anim_idx, tanim, owner, Rect(Point(0, h - lines), w, lines));
634+ dst.drawanimrect(pos[F], anim_idx, tanim, owner, Rect(Point(0, h - lines), w, lines));
635 } else if (upcast(const BuildingDescr, building, map_object_descr)) {
636 // this is a building therefore we either draw unoccupied or idle animation
637 uint32_t pic;
638@@ -217,11 +362,11 @@
639 } catch (MapObjectDescr::AnimationNonexistent &) {
640 pic = building->get_animation("idle");
641 }
642- m_dst->drawanim(pos[F], pic, 0, owner);
643+ dst.drawanim(pos[F], pic, 0, owner);
644 } else if (const uint32_t pic = map_object_descr->main_animation()) {
645- m_dst->drawanim(pos[F], pic, 0, owner);
646+ dst.drawanim(pos[F], pic, 0, owner);
647 } else if (map_object_descr->type() == MapObjectType::FLAG) {
648- m_dst->drawanim(pos[F], owner->tribe().flag_animation(), 0, owner);
649+ dst.drawanim(pos[F], owner->tribe().flag_animation(), 0, owner);
650 }
651 }
652 }
653@@ -239,7 +384,7 @@
654 (const OverlayManager::OverlayInfo * it = overlay_info;
655 it < end;
656 ++it)
657- m_dst->blit(pos[F] - it->hotspot, it->pic);
658+ dst.blit(pos[F] - it->hotspot, it->pic);
659 }
660
661 {
662@@ -259,7 +404,7 @@
663 (OverlayManager::OverlayInfo const * it = overlay_info;
664 it < end;
665 ++it)
666- m_dst->blit(tripos - it->hotspot, it->pic);
667+ dst.blit(tripos - it->hotspot, it->pic);
668 }
669
670 {
671@@ -279,7 +424,7 @@
672 (OverlayManager::OverlayInfo const * it = overlay_info;
673 it < end;
674 ++it)
675- m_dst->blit(tripos - it->hotspot, it->pic);
676+ dst.blit(tripos - it->hotspot, it->pic);
677 }
678 }
679 }
680
681=== modified file 'src/graphic/game_renderer.h'
682--- src/graphic/game_renderer.h 2014-09-27 18:53:55 +0000
683+++ src/graphic/game_renderer.h 2014-12-04 20:54:56 +0000
684@@ -20,17 +20,22 @@
685 #ifndef WL_GRAPHIC_GAME_RENDERER_H
686 #define WL_GRAPHIC_GAME_RENDERER_H
687
688-#include <boost/utility.hpp>
689+#include <memory>
690
691 #include "base/macros.h"
692 #include "base/point.h"
693+#include "graphic/gl/utils.h"
694
695 namespace Widelands {
696 class Player;
697 class EditorGameBase;
698 }
699
700+class DitherProgram;
701 class RenderTarget;
702+class RoadProgram;
703+class TerrainProgram;
704+
705
706 /**
707 * This abstract base class renders the main game view into an
708@@ -45,56 +50,41 @@
709 class GameRenderer {
710 public:
711 GameRenderer();
712- virtual ~GameRenderer();
713-
714- /**
715- * Renders the map from a player's point of view into the
716- * given drawing window.
717- *
718- * @param viewofs is the offset of the upper left corner of
719- * the window into the map, in pixels.
720- */
721- void rendermap
722- (RenderTarget & dst,
723- const Widelands::EditorGameBase & egbase,
724- const Widelands::Player & player,
725- const Point & viewofs);
726-
727- /**
728- * Renders the map from an omniscient perspective.
729- * This is used for spectators, players that see all, and in the editor.
730- */
731- void rendermap
732- (RenderTarget & dst,
733- const Widelands::EditorGameBase & egbase,
734- const Point & viewofs);
735-
736-protected:
737- virtual void draw() = 0;
738-
739- void draw_objects();
740-
741- /**
742- * The following variables, which are setup by @ref rendermap,
743- * are only valid during rendering,
744- * and should be treated as read-only by derived classes.
745- */
746- /*@{*/
747- RenderTarget * m_dst;
748- Widelands::EditorGameBase const * m_egbase;
749- Widelands::Player const * m_player;
750-
751- /// Translation from map pixel coordinates to @ref m_dst pixel coordinates
752- Point m_dst_offset;
753-
754- int32_t m_minfx;
755- int32_t m_minfy;
756- int32_t m_maxfx;
757- int32_t m_maxfy;
758- /*@}*/
759+ ~GameRenderer();
760+
761+ // Renders the map from a player's point of view into the given
762+ // drawing window. 'view_offset' is the offset of the upper left
763+ // corner of the window into the map, in pixels.
764+ void rendermap(RenderTarget& dst,
765+ const Widelands::EditorGameBase& egbase,
766+ const Point& view_offset,
767+ const Widelands::Player& player);
768+
769+ // Renders the map from an omniscient perspective. This is used
770+ // for spectators, players that see all, and in the editor.
771+ void rendermap(RenderTarget& dst, const Widelands::EditorGameBase& egbase, const Point& view_offset);
772
773 private:
774- void draw_wrapper();
775+ static std::unique_ptr<TerrainProgram> terrain_program_;
776+ static std::unique_ptr<DitherProgram> dither_program_;
777+ static std::unique_ptr<RoadProgram> road_program_;
778+
779+ // Draw the map for the given parameters (see rendermap). 'player'
780+ // can be nullptr in which case the whole map is drawn.
781+ void draw(RenderTarget& dst,
782+ const Widelands::EditorGameBase& egbase,
783+ const Point& view_offset,
784+ const Widelands::Player* player);
785+
786+ // Draws the objects (animations & overlays).
787+ void draw_objects(RenderTarget& dst,
788+ const Widelands::EditorGameBase& egbase,
789+ const Point& view_offset,
790+ const Widelands::Player* player,
791+ int minfx,
792+ int maxfx,
793+ int minfy,
794+ int maxfy);
795
796 DISALLOW_COPY_AND_ASSIGN(GameRenderer);
797 };
798
799=== removed file 'src/graphic/gl/game_renderer.cc'
800--- src/graphic/gl/game_renderer.cc 2014-11-28 05:40:53 +0000
801+++ src/graphic/gl/game_renderer.cc 1970-01-01 00:00:00 +0000
802@@ -1,191 +0,0 @@
803-/*
804- * Copyright (C) 2011-2013 by the Widelands Development Team
805- *
806- * This program is free software; you can redistribute it and/or
807- * modify it under the terms of the GNU General Public License
808- * as published by the Free Software Foundation; either version 2
809- * of the License, or (at your option) any later version.
810- *
811- * This program is distributed in the hope that it will be useful,
812- * but WITHOUT ANY WARRANTY; without even the implied warranty of
813- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
814- * GNU General Public License for more details.
815- *
816- * You should have received a copy of the GNU General Public License
817- * along with this program; if not, write to the Free Software
818- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
819- *
820- */
821-
822-#include "graphic/gl/game_renderer.h"
823-
824-#include <memory>
825-
826-#include "graphic/gl/dither_program.h"
827-#include "graphic/gl/fields_to_draw.h"
828-#include "graphic/gl/road_program.h"
829-#include "graphic/gl/terrain_program.h"
830-#include "graphic/graphic.h"
831-#include "graphic/rendertarget.h"
832-#include "graphic/surface.h"
833-#include "logic/editor_game_base.h"
834-#include "logic/player.h"
835-#include "logic/world/world.h"
836-#include "wui/mapviewpixelconstants.h"
837-#include "wui/mapviewpixelfunctions.h"
838-#include "wui/overlay_manager.h"
839-
840-namespace {
841-
842-using namespace Widelands;
843-
844-// Returns the brightness value in [0, 1.] for 'fcoords' at 'gametime' for
845-// 'player' (which can be nullptr).
846-float field_brightness(const FCoords& fcoords,
847- const uint32_t gametime,
848- const Map& map,
849- const Player* const player) {
850- uint32_t brightness = 144 + fcoords.field->get_brightness();
851- brightness = std::min<uint32_t>(255, (brightness * 255) / 160);
852-
853- if (player && !player->see_all()) {
854- const Player::Field& pf = player->fields()[Map::get_index(fcoords, map.get_width())];
855- if (pf.vision == 0) {
856- return 0.;
857- } else if (pf.vision == 1) {
858- static const uint32_t kDecayTimeInMs = 20000;
859- const Duration time_ago = gametime - pf.time_node_last_unseen;
860- if (time_ago < kDecayTimeInMs) {
861- brightness = (brightness * (2 * kDecayTimeInMs - time_ago)) / (2 * kDecayTimeInMs);
862- } else {
863- brightness = brightness / 2;
864- }
865- }
866- }
867- return brightness / 255.;
868-}
869-
870-// Returns the road that should be rendered here. The format is like in field,
871-// but this is not the physically present road, but the one that should be
872-// drawn (i.e. taking into account if there is fog of war involved or road
873-// building overlays enabled).
874-uint8_t field_roads(const FCoords& coords, const Map& map, const Player* const player) {
875- uint8_t roads;
876- if (player && !player->see_all()) {
877- const Player::Field& pf = player->fields()[Map::get_index(coords, map.get_width())];
878- roads = pf.roads | map.overlay_manager().get_road_overlay(coords);
879- } else {
880- roads = coords.field->get_roads();
881- }
882- roads |= map.overlay_manager().get_road_overlay(coords);
883- return roads;
884-}
885-
886-} // namespace
887-
888-// Explanation of how drawing works:
889-// Schematic of triangle neighborhood:
890-//
891-// *
892-// / \
893-// / u \
894-// (f)/ \
895-// *------*------* (r)
896-// \ l / \ r / \
897-// \ / \ / \
898-// \/ d \/ rr \
899-// *------*------* (br)
900-// \ dd /
901-// \ /
902-// \/
903-// *
904-//
905-// Each field (f) owns two triangles: (r)ight & (d)own. When we look at the
906-// field, we have to make sure to schedule drawing the triangles. This is done
907-// by of these triangles is done by TerrainProgram.
908-//
909-// To draw dithered edges, we have to look at the neighboring triangles for the
910-// two triangles too: If a neighboring triangle has another texture and our
911-// dither layer is smaller, we have to draw a dithering triangle too - this lets the neighboring
912-// texture
913-// bleed into our triangle.
914-//
915-// The dither triangle is the triangle that should be partially (either r or
916-// d). Example: if r and d have different textures and r.dither_layer >
917-// d.dither_layer, then we will repaint d with the dither texture as mask.
918-
919-
920-std::unique_ptr<TerrainProgram> GlGameRenderer::terrain_program_;
921-std::unique_ptr<DitherProgram> GlGameRenderer::dither_program_;
922-std::unique_ptr<RoadProgram> GlGameRenderer::road_program_;
923-
924-GlGameRenderer::GlGameRenderer() {
925-}
926-
927-GlGameRenderer::~GlGameRenderer() {
928-}
929-
930-void GlGameRenderer::draw() {
931- if (terrain_program_ == nullptr) {
932- terrain_program_.reset(new TerrainProgram());
933- dither_program_.reset(new DitherProgram());
934- road_program_.reset(new RoadProgram());
935- }
936-
937- Surface* surface = m_dst->get_surface();
938- if (!surface)
939- return;
940-
941- const Rect& bounding_rect = m_dst->get_rect();
942- const Point surface_offset = m_dst_offset + bounding_rect.top_left() + m_dst->get_offset();
943-
944- glScissor(bounding_rect.x,
945- surface->height() - bounding_rect.y - bounding_rect.h,
946- bounding_rect.w,
947- bounding_rect.h);
948- glEnable(GL_SCISSOR_TEST);
949-
950- Map& map = m_egbase->map();
951- const uint32_t gametime = m_egbase->get_gametime();
952-
953- FieldsToDraw fields_to_draw(m_minfx, m_maxfx, m_minfy, m_maxfy);
954- for (int32_t fy = m_minfy; fy <= m_maxfy; ++fy) {
955- for (int32_t fx = m_minfx; fx <= m_maxfx; ++fx) {
956- FieldsToDraw::Field& f =
957- *fields_to_draw.mutable_field(fields_to_draw.calculate_index(fx, fy));
958-
959- f.fx = fx;
960- f.fy = fy;
961-
962- Coords coords(fx, fy);
963- int x, y;
964- MapviewPixelFunctions::get_basepix(coords, x, y);
965-
966- map.normalize_coords(coords);
967- const FCoords& fcoords = map.get_fcoords(coords);
968-
969- f.texture_x = float(x) / kTextureSideLength;
970- f.texture_y = float(y) / kTextureSideLength;
971-
972- f.gl_x = f.pixel_x = x + surface_offset.x;
973- f.gl_y = f.pixel_y = y + surface_offset.y - fcoords.field->get_height() * HEIGHT_FACTOR;
974- surface->pixel_to_gl(&f.gl_x, &f.gl_y);
975-
976- f.ter_d = fcoords.field->terrain_d();
977- f.ter_r = fcoords.field->terrain_r();
978-
979- f.brightness = field_brightness(fcoords, gametime, map, m_player);
980-
981- f.roads = field_roads(fcoords, map, m_player);
982- }
983- }
984-
985- const World& world = m_egbase->world();
986- terrain_program_->draw(gametime, world.terrains(), fields_to_draw);
987- dither_program_->draw(gametime, world.terrains(), fields_to_draw);
988- road_program_->draw(*surface, fields_to_draw);
989-
990- draw_objects();
991-
992- glDisable(GL_SCISSOR_TEST);
993-}
994
995=== removed file 'src/graphic/gl/game_renderer.h'
996--- src/graphic/gl/game_renderer.h 2014-11-01 20:40:39 +0000
997+++ src/graphic/gl/game_renderer.h 1970-01-01 00:00:00 +0000
998@@ -1,48 +0,0 @@
999-/*
1000- * Copyright (C) 2011-2013 by the Widelands Development Team
1001- *
1002- * This program is free software; you can redistribute it and/or
1003- * modify it under the terms of the GNU General Public License
1004- * as published by the Free Software Foundation; either version 2
1005- * of the License, or (at your option) any later version.
1006- *
1007- * This program is distributed in the hope that it will be useful,
1008- * but WITHOUT ANY WARRANTY; without even the implied warranty of
1009- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1010- * GNU General Public License for more details.
1011- *
1012- * You should have received a copy of the GNU General Public License
1013- * along with this program; if not, write to the Free Software
1014- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
1015- *
1016- */
1017-
1018-#ifndef WL_GRAPHIC_GL_GAME_RENDERER_H
1019-#define WL_GRAPHIC_GL_GAME_RENDERER_H
1020-
1021-#include <memory>
1022-
1023-#include "graphic/game_renderer.h"
1024-#include "graphic/gl/utils.h"
1025-
1026-class TerrainProgram;
1027-class DitherProgram;
1028-class RoadProgram;
1029-
1030-/**
1031- * OpenGL implementation of @ref GameRenderer.
1032- */
1033-class GlGameRenderer : public GameRenderer {
1034-public:
1035- GlGameRenderer();
1036- virtual ~GlGameRenderer();
1037-
1038-private:
1039- static std::unique_ptr<TerrainProgram> terrain_program_;
1040- static std::unique_ptr<DitherProgram> dither_program_;
1041- static std::unique_ptr<RoadProgram> road_program_;
1042-
1043- void draw() override;
1044-};
1045-
1046-#endif // end of include guard: WL_GRAPHIC_GL_GAME_RENDERER_H
1047
1048=== modified file 'src/graphic/rendertarget.cc'
1049--- src/graphic/rendertarget.cc 2014-12-02 19:00:52 +0000
1050+++ src/graphic/rendertarget.cc 2014-12-04 20:54:56 +0000
1051@@ -27,7 +27,6 @@
1052 #include "graphic/surface.h"
1053 #include "logic/player.h"
1054 #include "logic/tribe.h"
1055-#include "wui/mapviewpixelconstants.h"
1056 #include "wui/overlay_manager.h"
1057
1058 using Widelands::BaseImmovable;
1059
1060=== modified file 'src/logic/CMakeLists.txt'
1061--- src/logic/CMakeLists.txt 2014-12-01 21:28:21 +0000
1062+++ src/logic/CMakeLists.txt 2014-12-04 20:54:56 +0000
1063@@ -6,6 +6,7 @@
1064 base_log
1065 graphic
1066 graphic_image_io
1067+ graphic_minimap_renderer
1068 graphic_surface
1069 io_fileread
1070 io_filesystem
1071@@ -250,5 +251,7 @@
1072 ui_basic
1073 widelands_ball_of_mud
1074 wui
1075+ wui_mapview_pixelfunctions
1076+ wui_overlay_manager
1077 wui_text_layout
1078 )
1079
1080=== modified file 'src/map_io/CMakeLists.txt'
1081--- src/map_io/CMakeLists.txt 2014-12-01 21:31:00 +0000
1082+++ src/map_io/CMakeLists.txt 2014-12-04 20:54:56 +0000
1083@@ -93,6 +93,7 @@
1084 economy
1085 graphic
1086 graphic_image_io
1087+ graphic_minimap_renderer
1088 graphic_surface
1089 helper
1090 io_fileread
1091
1092=== modified file 'src/scripting/CMakeLists.txt'
1093--- src/scripting/CMakeLists.txt 2014-11-28 16:40:55 +0000
1094+++ src/scripting/CMakeLists.txt 2014-12-04 20:54:56 +0000
1095@@ -57,4 +57,5 @@
1096 third_party_eris
1097 ui_basic
1098 wui
1099+ wui_mapview_pixelfunctions
1100 )
1101
1102=== modified file 'src/sound/CMakeLists.txt'
1103--- src/sound/CMakeLists.txt 2014-11-28 16:40:55 +0000
1104+++ src/sound/CMakeLists.txt 2014-12-04 20:54:56 +0000
1105@@ -21,4 +21,5 @@
1106 profile
1107 random
1108 wui
1109+ wui_mapview_pixelfunctions
1110 )
1111
1112=== modified file 'src/wui/CMakeLists.txt'
1113--- src/wui/CMakeLists.txt 2014-11-28 16:40:55 +0000
1114+++ src/wui/CMakeLists.txt 2014-12-04 20:54:56 +0000
1115@@ -29,6 +29,29 @@
1116 wui
1117 )
1118
1119+wl_library(wui_overlay_manager
1120+ SRCS
1121+ overlay_manager.cc
1122+ overlay_manager.h
1123+ DEPENDS
1124+ base_geometry
1125+ graphic
1126+ logic
1127+ logic_widelands_geometry
1128+)
1129+
1130+wl_library(wui_mapview_pixelfunctions
1131+ SRCS
1132+ mapviewpixelconstants.h
1133+ mapviewpixelfunctions.cc
1134+ mapviewpixelfunctions.h
1135+ vector.h
1136+ DEPENDS
1137+ base_geometry
1138+ logic
1139+ logic_widelands_geometry
1140+)
1141+
1142 wl_library(wui
1143 SRCS
1144 actionconfirm.cc
1145@@ -83,16 +106,11 @@
1146 logmessage.h
1147 mapview.cc
1148 mapview.h
1149- mapviewpixelconstants.h
1150- mapviewpixelfunctions.cc
1151- mapviewpixelfunctions.h
1152 militarysitewindow.cc
1153 minimap.cc
1154 minimap.h
1155 multiplayersetupgroup.cc
1156 multiplayersetupgroup.h
1157- overlay_manager.cc
1158- overlay_manager.h
1159 playerdescrgroup.cc
1160 playerdescrgroup.h
1161 plot_area.cc
1162@@ -117,7 +135,6 @@
1163 transport_ui.cc
1164 unique_window_handler.cc
1165 unique_window_handler.h
1166- vector.h
1167 ware_statistics_menu.cc
1168 ware_statistics_menu.h
1169 warehousewindow.cc
1170@@ -140,7 +157,9 @@
1171 game_io
1172 graphic
1173 graphic_color
1174+ graphic_game_renderer
1175 graphic_image
1176+ graphic_minimap_renderer
1177 graphic_surface
1178 io_fileread
1179 io_filesystem
1180@@ -157,5 +176,7 @@
1181 ui_fsmenu
1182 widelands_ball_of_mud
1183 wui_chat_ui
1184+ wui_mapview_pixelfunctions
1185+ wui_overlay_manager
1186 wui_text_layout
1187 )
1188
1189=== modified file 'src/wui/mapview.cc'
1190--- src/wui/mapview.cc 2014-11-22 18:36:33 +0000
1191+++ src/wui/mapview.cc 2014-12-04 20:54:56 +0000
1192@@ -20,7 +20,7 @@
1193 #include "wui/mapview.h"
1194
1195 #include "base/macros.h"
1196-#include "graphic/gl/game_renderer.h"
1197+#include "graphic/game_renderer.h"
1198 #include "graphic/graphic.h"
1199 #include "graphic/rendertarget.h"
1200 #include "logic/map.h"
1201@@ -31,16 +31,14 @@
1202 #include "wui/mapviewpixelfunctions.h"
1203 #include "wui/overlay_manager.h"
1204
1205-MapView::MapView
1206- (UI::Panel * parent,
1207- int32_t x, int32_t y, uint32_t w, uint32_t h,
1208- InteractiveBase & player)
1209-:
1210-UI::Panel (parent, x, y, w, h),
1211-m_intbase (player),
1212-m_viewpoint (Point(0, 0)),
1213-m_dragging (false)
1214-{}
1215+MapView::MapView(
1216+ UI::Panel* parent, int32_t x, int32_t y, uint32_t w, uint32_t h, InteractiveBase& player)
1217+ : UI::Panel(parent, x, y, w, h),
1218+ m_renderer(new GameRenderer()),
1219+ m_intbase(player),
1220+ m_viewpoint(Point(0, 0)),
1221+ m_dragging(false) {
1222+}
1223
1224 MapView::~MapView()
1225 {
1226@@ -90,11 +88,8 @@
1227
1228 egbase.map().overlay_manager().load_graphics();
1229
1230- if (!m_renderer) {
1231- m_renderer.reset(new GlGameRenderer());
1232- }
1233 if (upcast(InteractivePlayer const, interactive_player, &intbase())) {
1234- m_renderer->rendermap(dst, egbase, interactive_player->player(), m_viewpoint);
1235+ m_renderer->rendermap(dst, egbase, m_viewpoint, interactive_player->player());
1236 } else {
1237 m_renderer->rendermap(dst, egbase, m_viewpoint);
1238 }

Subscribers

People subscribed via source and target branches

to status/vote changes: