← Back to team overview

widelands-dev team mailing list archive

[Merge] lp:~widelands-dev/widelands/split_overlay_manager into lp:~widelands-dev/widelands/render_queue

 

SirVer has proposed merging lp:~widelands-dev/widelands/split_overlay_manager into lp:~widelands-dev/widelands/render_queue.

Requested reviews:
  Widelands Developers (widelands-dev)
Related bugs:
  Bug #536606 in widelands: "Split overlay manager"
  https://bugs.launchpad.net/widelands/+bug/536606

For more details, see:
https://code.launchpad.net/~widelands-dev/widelands/split_overlay_manager/+merge/254496

I needed something to test my new keyboard on - so I used the weekend to scratch an itch that I was been having for a long time now, namely the horrible OverlayManager.

Suggested commit message:

- Split OverlayManager into FieldOverlayManager and EdgeOverlayManager.
- They are both now owned by InteractiveBase instead of Map.
- Removed caching of field-nodes calculation. This is so quick, there is no benefit in caching.
- Refactorings and API modernization of the OverlayManager.
-- 
Your team Widelands Developers is requested to review the proposed merge of lp:~widelands-dev/widelands/split_overlay_manager into lp:~widelands-dev/widelands/render_queue.
=== modified file 'src/ai/ai_hints.cc'
--- src/ai/ai_hints.cc	2015-03-26 06:59:37 +0000
+++ src/ai/ai_hints.cc	2015-03-29 18:13:50 +0000
@@ -48,7 +48,8 @@
 		} else {
 			if (!strcmp(section ? section->get_string("trainingsite_type", "basic") : "basic", "basic")) {
 				trainingsite_type_ =  TrainingSiteType::kBasic;
-			} else if (!strcmp(section ? section->get_string("trainingsite_type", "basic") : "basic", "advanced")) {
+			} else if (!strcmp(section ? section->get_string("trainingsite_type", "basic") : "basic",
+			                   "advanced")) {
 				trainingsite_type_ =  TrainingSiteType::kAdvanced;
 			} else {
 				trainingsite_type_ = TrainingSiteType::kNoTS;

=== modified file 'src/economy/portdock.cc'
--- src/economy/portdock.cc	2015-02-16 20:23:15 +0000
+++ src/economy/portdock.cc	2015-03-29 18:13:50 +0000
@@ -218,7 +218,6 @@
 		if (!wh->m_cleanup_in_progress){
 			if (upcast(Game, game, &egbase)) {
 				if (game->is_loaded()) { //do not attempt when shutting down
-					Player& player = owner();
 					wh->restore_portdock_or_destroy(egbase);
 				}
 			}

=== modified file 'src/economy/ware_instance.cc'
--- src/economy/ware_instance.cc	2014-11-30 18:49:38 +0000
+++ src/economy/ware_instance.cc	2015-03-29 18:13:50 +0000
@@ -646,7 +646,7 @@
 		throw wexception("WareInstance: %s", e.what());
 	}
 
-	return nullptr; // Should never be reached
+	throw wexception("Unreachable code was reached. Please report a bug.");
 }
 
 }

=== modified file 'src/editor/CMakeLists.txt'
--- src/editor/CMakeLists.txt	2015-01-31 16:03:59 +0000
+++ src/editor/CMakeLists.txt	2015-03-29 18:13:50 +0000
@@ -102,6 +102,6 @@
     ui_fsmenu
     widelands_ball_of_mud
     wui
+    wui_field_overlay_manager
     wui_mapview_pixelfunctions
-    wui_overlay_manager
 )

=== modified file 'src/editor/editorinteractive.cc'
--- src/editor/editorinteractive.cc	2015-02-05 23:39:23 +0000
+++ src/editor/editorinteractive.cc	2015-03-29 18:13:50 +0000
@@ -49,9 +49,9 @@
 #include "ui_basic/messagebox.h"
 #include "ui_basic/progresswindow.h"
 #include "wlapplication.h"
+#include "wui/field_overlay_manager.h"
 #include "wui/game_tips.h"
 #include "wui/interactive_base.h"
-#include "wui/overlay_manager.h"
 
 namespace {
 
@@ -152,21 +152,20 @@
 		if (Widelands::Coords const sp = map.get_starting_pos(p)) {
 			const Image* pic = g_gr->images().get(fname);
 			assert(pic);
-			map.overlay_manager().register_overlay
+			mutable_field_overlay_manager()->register_overlay
 				(sp, pic, 8, Point(pic->width() / 2, STARTING_POS_HOTSPOT_Y));
 		}
 	}
 
 	//  Resources: we do not calculate default resources, therefore we do not
 	//  expect to meet them here.
-	OverlayManager& overlay_manager = map.overlay_manager();
 	Widelands::Extent const extent = map.extent();
 	iterate_Map_FCoords(map, extent, fc) {
 		if (uint8_t const amount = fc.field->get_resources_amount()) {
 			const std::string& immname =
 			   egbase().world().get_resource(fc.field->get_resources())->get_editor_pic(amount);
 			if (immname.size())
-				overlay_manager.register_overlay(fc, g_gr->images().get(immname), 4);
+				mutable_field_overlay_manager()->register_overlay(fc, g_gr->images().get(immname), 4);
 		}
 	}
 }
@@ -224,7 +223,7 @@
 	} catch (LuaScriptNotExistingError &) {
 		// do nothing.
 	}
-	egbase().map().overlay_manager().show_buildhelp(true);
+	show_buildhelp(true);
 }
 
 
@@ -303,11 +302,6 @@
 		map_clicked(true);
 }
 
-void EditorInteractive::toggle_buildhelp() {
-	egbase().map().overlay_manager().toggle_buildhelp();
-}
-
-
 void EditorInteractive::tool_menu_btn() {
 	if (m_toolmenu.window)
 		delete m_toolmenu.window;
@@ -502,7 +496,7 @@
 		Widelands::Map & map = egbase().map();
 		//  A new tool has been selected. Remove all registered overlay callback
 		//  functions.
-		map.overlay_manager().remove_overlay_callback_function();
+		mutable_field_overlay_manager()->register_overlay_callback_function(nullptr);
 		map.recalc_whole_map(egbase().world());
 	}
 	tools.current_pointer = &primary;

=== modified file 'src/editor/editorinteractive.h'
--- src/editor/editorinteractive.h	2014-10-14 06:30:20 +0000
+++ src/editor/editorinteractive.h	2015-03-29 18:13:50 +0000
@@ -121,7 +121,6 @@
 	void set_need_save(bool const t) {m_need_save = t;}
 
 private:
-	void toggle_buildhelp();
 	void tool_menu_btn();
 	void toolsize_menu_btn();
 	void toggle_mainmenu();

=== modified file 'src/editor/tools/editor_decrease_resources_tool.cc'
--- src/editor/tools/editor_decrease_resources_tool.cc	2015-03-01 09:21:20 +0000
+++ src/editor/tools/editor_decrease_resources_tool.cc	2015-03-29 18:13:50 +0000
@@ -28,7 +28,7 @@
 #include "logic/widelands_geometry.h"
 #include "logic/world/resource_description.h"
 #include "logic/world/world.h"
-#include "wui/overlay_manager.h"
+#include "wui/field_overlay_manager.h"
 
 
 /**
@@ -39,7 +39,7 @@
 EditorDecreaseResourcesTool::handle_click_impl(Widelands::Map& map,
                                                   const Widelands::World& world,
                                                   Widelands::NodeAndTriangle<> const center,
-                                                  EditorInteractive& /* parent */,
+                                                  EditorInteractive& parent,
                                                   EditorActionArgs& args) {
 	Widelands::MapRegion<Widelands::Area<Widelands::FCoords> > mr
 	(map,
@@ -63,7 +63,8 @@
 			    world.get_resource(res)->get_editor_pic
 			    (mr.location().field->get_resources_amount());
 			const Image* pic = g_gr->images().get(str);
-			map.overlay_manager().remove_overlay(mr.location(), pic);
+			auto* overlay_manager = parent.mutable_field_overlay_manager();
+			overlay_manager->remove_overlay(mr.location(), pic);
 			if (!amount) {
 				mr.location().field->set_resources(0, 0);
 				mr.location().field->set_initial_res_amount(0);
@@ -73,7 +74,7 @@
 				//  set new overlay
 				str = world.get_resource(args.cur_res)->get_editor_pic(amount);
 				pic = g_gr->images().get(str);
-				map.overlay_manager().register_overlay(mr.location(), pic, 4);
+				overlay_manager->register_overlay(mr.location(), pic, 4);
 				map.recalc_for_field_area(
 				   world, Widelands::Area<Widelands::FCoords>(mr.location(), 0));
 			}

=== modified file 'src/editor/tools/editor_increase_resources_tool.cc'
--- src/editor/tools/editor_increase_resources_tool.cc	2015-02-24 13:51:38 +0000
+++ src/editor/tools/editor_increase_resources_tool.cc	2015-03-29 18:13:50 +0000
@@ -26,7 +26,7 @@
 #include "logic/world/resource_description.h"
 #include "logic/world/terrain_description.h"
 #include "logic/world/world.h"
-#include "wui/overlay_manager.h"
+#include "wui/field_overlay_manager.h"
 
 using Widelands::TCoords;
 
@@ -84,13 +84,12 @@
 there is not already another resource there.
 ===========
 */
-int32_t
-EditorIncreaseResourcesTool::handle_click_impl(Widelands::Map& map,
-                                                  const Widelands::World& world,
-                                                  Widelands::NodeAndTriangle<> const center,
-                                                  EditorInteractive& /* parent */,
-                                                  EditorActionArgs& args) {
-	OverlayManager & overlay_manager = map.overlay_manager();
+int32_t EditorIncreaseResourcesTool::handle_click_impl(Widelands::Map& map,
+                                                       const Widelands::World& world,
+                                                       Widelands::NodeAndTriangle<> const center,
+                                                       EditorInteractive& parent,
+                                                       EditorActionArgs& args) {
+	FieldOverlayManager& overlay_manager = *parent.mutable_field_overlay_manager();
 	Widelands::MapRegion<Widelands::Area<Widelands::FCoords> > mr
 		(map,
 			Widelands::Area<Widelands::FCoords>

=== modified file 'src/editor/tools/editor_set_origin_tool.cc'
--- src/editor/tools/editor_set_origin_tool.cc	2014-09-10 14:08:25 +0000
+++ src/editor/tools/editor_set_origin_tool.cc	2015-03-29 18:13:50 +0000
@@ -22,7 +22,6 @@
 #include "editor/editorinteractive.h"
 #include "logic/map.h"
 #include "wui/mapviewpixelconstants.h"
-#include "wui/overlay_manager.h"
 
 int32_t EditorSetOriginTool::handle_click_impl(Widelands::Map& map,
                                                   const Widelands::World&,

=== modified file 'src/editor/tools/editor_set_port_space_tool.cc'
--- src/editor/tools/editor_set_port_space_tool.cc	2014-09-20 09:37:47 +0000
+++ src/editor/tools/editor_set_port_space_tool.cc	2015-03-29 18:13:50 +0000
@@ -25,7 +25,6 @@
 #include "logic/map.h"
 #include "logic/mapfringeregion.h"
 #include "logic/mapregion.h"
-#include "wui/overlay_manager.h"
 
 using namespace Widelands;
 

=== modified file 'src/editor/tools/editor_set_resources_tool.cc'
--- src/editor/tools/editor_set_resources_tool.cc	2014-12-01 21:47:22 +0000
+++ src/editor/tools/editor_set_resources_tool.cc	2015-03-29 18:13:50 +0000
@@ -27,7 +27,7 @@
 #include "logic/mapregion.h"
 #include "logic/world/resource_description.h"
 #include "logic/world/world.h"
-#include "wui/overlay_manager.h"
+#include "wui/field_overlay_manager.h"
 
 /**
  * Sets the resources of the current to a fixed value
@@ -35,9 +35,9 @@
 int32_t EditorSetResourcesTool::handle_click_impl(Widelands::Map& map,
                                                      const Widelands::World& world,
                                                      Widelands::NodeAndTriangle<> const center,
-                                                     EditorInteractive& /* parent */,
+                                                     EditorInteractive& parent,
                                                      EditorActionArgs& args) {
-	OverlayManager & overlay_manager = map.overlay_manager();
+	FieldOverlayManager& field_overlay_manager = *parent.mutable_field_overlay_manager();
 	Widelands::MapRegion<Widelands::Area<Widelands::FCoords> > mr
 	(map,
 	 Widelands::Area<Widelands::FCoords>
@@ -59,7 +59,7 @@
 			//  Ok, we're doing something. First remove the current overlays.
 			const Image* pic = g_gr->images().get
 				(world.get_resource(res)->get_editor_pic (mr.location().field->get_resources_amount()));
-			overlay_manager.remove_overlay(mr.location(), pic);
+			field_overlay_manager.remove_overlay(mr.location(), pic);
 
 			if (!amount) {
 				mr.location().field->set_resources(0, 0);
@@ -70,7 +70,7 @@
 				//  set new overlay
 				pic =
 				    g_gr->images().get(world.get_resource(args.cur_res)->get_editor_pic(amount));
-				overlay_manager.register_overlay(mr.location(), pic, 4);
+				field_overlay_manager.register_overlay(mr.location(), pic, 4);
 				map.recalc_for_field_area(world, Widelands::Area<Widelands::FCoords>(mr.location(), 0));
 			}
 		}
@@ -80,11 +80,11 @@
 
 int32_t
 EditorSetResourcesTool::handle_undo_impl(Widelands::Map& map,
-                                            const Widelands::World& world,
-                                            Widelands::NodeAndTriangle<Widelands::Coords> center,
-                                            EditorInteractive& /* parent */,
-                                            EditorActionArgs& args) {
-	OverlayManager & overlay_manager = map.overlay_manager();
+                                         const Widelands::World& world,
+                                         Widelands::NodeAndTriangle<Widelands::Coords> center,
+                                         EditorInteractive& parent,
+                                         EditorActionArgs& args) {
+	FieldOverlayManager& overlay_manager = *parent.mutable_field_overlay_manager();
 	Widelands::MapRegion<Widelands::Area<Widelands::FCoords> > mr
 	(map,
 	 Widelands::Area<Widelands::FCoords>

=== modified file 'src/editor/tools/editor_set_starting_pos_tool.cc'
--- src/editor/tools/editor_set_starting_pos_tool.cc	2014-09-20 09:37:47 +0000
+++ src/editor/tools/editor_set_starting_pos_tool.cc	2015-03-29 18:13:50 +0000
@@ -24,7 +24,6 @@
 #include "graphic/graphic.h"
 #include "logic/building.h"
 #include "logic/map.h"
-#include "wui/overlay_manager.h"
 
 // global variable to pass data from callback to class
 static int32_t m_current_player;
@@ -63,10 +62,10 @@
 }
 
 int32_t EditorSetStartingPosTool::handle_click_impl(Widelands::Map& map,
-                                                        const Widelands::World&,
-                                                        Widelands::NodeAndTriangle<> const center,
-                                                        EditorInteractive&,
-                                                        EditorActionArgs&) {
+                                                    const Widelands::World&,
+                                                    Widelands::NodeAndTriangle<> const center,
+                                                    EditorInteractive& parent,
+                                                    EditorActionArgs&) {
 	assert(0 <= center.node.x);
 	assert(center.node.x < map.get_width());
 	assert(0 <= center.node.y);
@@ -89,7 +88,7 @@
 
 		//  check if field is valid
 		if (editor_tool_set_starting_pos_callback(map.get_fcoords(center.node), map)) {
-			OverlayManager & overlay_manager = map.overlay_manager();
+			FieldOverlayManager& overlay_manager = *parent.mutable_field_overlay_manager();
 			//  remove old overlay if any
 			overlay_manager.remove_overlay(old_sp, pic);
 

=== modified file 'src/editor/ui_menus/editor_main_menu_load_map.cc'
--- src/editor/ui_menus/editor_main_menu_load_map.cc	2014-11-30 18:49:38 +0000
+++ src/editor/ui_menus/editor_main_menu_load_map.cc	2015-03-29 18:13:50 +0000
@@ -42,7 +42,6 @@
 #include "ui_basic/multilinetextarea.h"
 #include "ui_basic/progresswindow.h"
 #include "ui_basic/textarea.h"
-#include "wui/overlay_manager.h"
 
 using Widelands::WidelandsMapLoader;
 

=== modified file 'src/editor/ui_menus/editor_player_menu.cc'
--- src/editor/ui_menus/editor_player_menu.cc	2014-11-30 18:49:38 +0000
+++ src/editor/ui_menus/editor_player_menu.cc	2015-03-29 18:13:50 +0000
@@ -34,7 +34,7 @@
 #include "ui_basic/editbox.h"
 #include "ui_basic/messagebox.h"
 #include "ui_basic/textarea.h"
-#include "wui/overlay_manager.h"
+#include "wui/field_overlay_manager.h"
 
 #define UNDEFINED_TRIBE_NAME "<undefined>"
 
@@ -219,7 +219,8 @@
 
 
 void EditorPlayerMenu::clicked_remove_last_player() {
-	Widelands::Map & map = eia().egbase().map();
+	EditorInteractive& editor_interactive = eia();
+	Widelands::Map& map = editor_interactive.egbase().map();
 	Widelands::PlayerNumber const old_nr_players = map.get_nrplayers();
 	Widelands::PlayerNumber const nr_players     = old_nr_players - 1;
 	assert(1 <= nr_players);
@@ -230,8 +231,8 @@
 			char picsname[] = "pics/editor_player_00_starting_pos.png";
 			picsname[19] += old_nr_players / 10;
 			picsname[20] += old_nr_players % 10;
-			map.overlay_manager().remove_overlay
-				(sp, g_gr->images().get(picsname));
+			editor_interactive.mutable_field_overlay_manager()->remove_overlay(
+			   sp, g_gr->images().get(picsname));
 		}
 	}
 	map.set_nrplayers(nr_players);
@@ -350,7 +351,7 @@
 
 	//  Register callback function to make sure that only valid locations are
 	//  selected.
-	map.overlay_manager().register_overlay_callback_function(
+	menu.mutable_field_overlay_manager()->register_overlay_callback_function(
 	   boost::bind(&editor_tool_set_starting_pos_callback, _1, boost::ref(map)));
 	map.recalc_whole_map(menu.egbase().world());
 	update();
@@ -377,13 +378,12 @@
  * Make infrastructure button clicked
  */
 void EditorPlayerMenu::make_infrastructure_clicked(uint8_t n) {
-	EditorInteractive & parent =
-		dynamic_cast<EditorInteractive &>(*get_parent());
+	EditorInteractive & parent = eia();
    // Check if starting position is valid (was checked before
    // so must be true)
 	Widelands::EditorGameBase & egbase = parent.egbase();
 	Widelands::Map & map = egbase.map();
-	OverlayManager & overlay_manager = map.overlay_manager();
+	FieldOverlayManager & overlay_manager = *eia().mutable_field_overlay_manager();
 	const Widelands::Coords start_pos = map.get_starting_pos(n);
 	assert(start_pos);
 

=== modified file 'src/editor/ui_menus/editor_tool_change_resources_options_menu.cc'
--- src/editor/ui_menus/editor_tool_change_resources_options_menu.cc	2014-12-07 20:13:27 +0000
+++ src/editor/ui_menus/editor_tool_change_resources_options_menu.cc	2015-03-29 18:13:50 +0000
@@ -32,7 +32,7 @@
 #include "logic/world/resource_description.h"
 #include "logic/world/world.h"
 #include "ui_basic/button.h"
-#include "wui/overlay_manager.h"
+#include "wui/field_overlay_manager.h"
 
 const static int BUTTON_WIDTH = 20;
 const static int BUTTON_HEIGHT = 20;
@@ -218,10 +218,11 @@
 	m_increase_tool.set_cur_res(n);
 	m_increase_tool.decrease_tool().set_cur_res(n);
 
-	Widelands::EditorGameBase& egbase = eia().egbase();
+	EditorInteractive& editor_interactive = eia();
+	Widelands::EditorGameBase& egbase = editor_interactive.egbase();
 	Widelands::Map & map = egbase.map();
-	map.overlay_manager().register_overlay_callback_function(
-	   boost::bind(&editor_change_resource_tool_callback, _1, boost::ref(map), boost::ref(egbase.world()), n));
+	editor_interactive.mutable_field_overlay_manager()->register_overlay_callback_function(boost::bind(
+	   &editor_change_resource_tool_callback, _1, boost::ref(map), boost::ref(egbase.world()), n));
 	map.recalc_whole_map(egbase.world());
 	select_correct_tool();
 

=== modified file 'src/editor/ui_menus/editor_tool_menu.cc'
--- src/editor/ui_menus/editor_tool_menu.cc	2014-11-30 18:49:38 +0000
+++ src/editor/ui_menus/editor_tool_menu.cc	2015-03-29 18:13:50 +0000
@@ -141,8 +141,8 @@
 	if (current_tool_pointer == &parent.tools.set_port_space) {
 		// Set correct overlay
 		Widelands::Map & map = parent.egbase().map();
-		map.overlay_manager().register_overlay_callback_function(
-				boost::bind(&editor_Tool_set_port_space_callback, _1, boost::ref(map)));
+		parent.mutable_field_overlay_manager()->register_overlay_callback_function(
+		   boost::bind(&editor_Tool_set_port_space_callback, _1, boost::ref(map)));
 		map.recalc_whole_map(parent.egbase().world());
 		update();
 	}

=== modified file 'src/game_io/CMakeLists.txt'
--- src/game_io/CMakeLists.txt	2015-01-31 16:03:59 +0000
+++ src/game_io/CMakeLists.txt	2015-03-29 18:13:50 +0000
@@ -39,5 +39,4 @@
     scripting_lua_table
     wui
     wui_mapview_pixelfunctions
-    wui_overlay_manager
 )

=== modified file 'src/game_io/game_interactive_player_packet.cc'
--- src/game_io/game_interactive_player_packet.cc	2014-09-20 09:37:47 +0000
+++ src/game_io/game_interactive_player_packet.cc	2015-03-29 18:13:50 +0000
@@ -27,7 +27,6 @@
 #include "logic/tribe.h"
 #include "wui/interactive_player.h"
 #include "wui/mapview.h"
-#include "wui/overlay_manager.h"
 
 namespace Widelands {
 

=== modified file 'src/graphic/CMakeLists.txt'
--- src/graphic/CMakeLists.txt	2015-02-20 20:04:28 +0000
+++ src/graphic/CMakeLists.txt	2015-03-29 18:13:50 +0000
@@ -177,8 +177,10 @@
     graphic_surface
     graphic_terrain_programs
     logic
+    wui
+    wui_edge_overlay_manager
+    wui_field_overlay_manager
     wui_mapview_pixelfunctions
-    wui_overlay_manager
 )
 
 wl_library(graphic_minimap_renderer
@@ -247,5 +249,4 @@
     profile
     scripting_lua_table
     sound
-    wui_overlay_manager
 )

=== modified file 'src/graphic/game_renderer.cc'
--- src/graphic/game_renderer.cc	2015-03-29 15:50:39 +0000
+++ src/graphic/game_renderer.cc	2015-03-29 18:13:50 +0000
@@ -29,9 +29,11 @@
 #include "logic/editor_game_base.h"
 #include "logic/player.h"
 #include "logic/world/world.h"
+#include "wui/edge_overlay_manager.h"
+#include "wui/field_overlay_manager.h"
+#include "wui/interactive_base.h"
 #include "wui/mapviewpixelconstants.h"
 #include "wui/mapviewpixelfunctions.h"
-#include "wui/overlay_manager.h"
 
 // Explanation of how drawing works:
 // Schematic of triangle neighborhood:
@@ -98,15 +100,18 @@
 // but this is not the physically present road, but the one that should be
 // drawn (i.e. taking into account if there is fog of war involved or road
 // building overlays enabled).
-uint8_t field_roads(const FCoords& coords, const Map& map, const Player* const player) {
+uint8_t field_roads(const FCoords& coords,
+                    const Map& map,
+                    const EdgeOverlayManager& edge_overlay_manager,
+                    const Player* const player) {
 	uint8_t roads;
 	if (player && !player->see_all()) {
 		const Player::Field& pf = player->fields()[Map::get_index(coords, map.get_width())];
-		roads = pf.roads | map.overlay_manager().get_road_overlay(coords);
+		roads = pf.roads | edge_overlay_manager.get_overlay(coords);
 	} else {
 		roads = coords.field->get_roads();
 	}
-	roads |= map.overlay_manager().get_road_overlay(coords);
+	roads |= edge_overlay_manager.get_overlay(coords);
 	return roads;
 }
 
@@ -163,6 +168,7 @@
 	const int surface_height = surface->height();
 
 	Map& map = egbase.map();
+	const EdgeOverlayManager& edge_overlay_manager = egbase.get_ibase()->edge_overlay_manager();
 	const uint32_t gametime = egbase.get_gametime();
 
 	fields_to_draw_.reset(minfx, maxfx, minfy, maxfy);
@@ -200,7 +206,7 @@
 				f.road_textures = nullptr;
 			}
 
-			f.roads = field_roads(fcoords, map, player);
+			f.roads = field_roads(fcoords, map, edge_overlay_manager, player);
 		}
 	}
 
@@ -247,6 +253,7 @@
 	static const uint32_t BR = 3;
 	const Map & map = egbase.map();
 
+	std::vector<FieldOverlayManager::OverlayInfo> overlay_info;
 	for (int32_t fy = minfy; fy <= maxfy; ++fy) {
 		for (int32_t fx = minfx; fx <= maxfx; ++fx) {
 			Coords ncoords(fx, fy);
@@ -380,60 +387,37 @@
 				}
 			}
 
+			const FieldOverlayManager& overlay_manager = egbase.get_ibase()->field_overlay_manager();
 			{
-				// Render overlays on the node
-				OverlayManager::OverlayInfo overlay_info[MAX_OVERLAYS_PER_NODE];
-
-				const OverlayManager::OverlayInfo * const end =
-					overlay_info
-					+
-					map.overlay_manager().get_overlays(coords[F], overlay_info);
-
-				for
-					(const OverlayManager::OverlayInfo * it = overlay_info;
-					 it < end;
-					 ++it)
-					dst.blit(pos[F] - it->hotspot, it->pic);
+				overlay_info.clear();
+				overlay_manager.get_overlays(coords[F], &overlay_info);
+				for (const auto& overlay : overlay_info) {
+					dst.blit(pos[F] - overlay.hotspot, overlay.pic);
+				}
 			}
 
 			{
 				// Render overlays on the R triangle
-				OverlayManager::OverlayInfo overlay_info[MAX_OVERLAYS_PER_TRIANGLE];
-				OverlayManager::OverlayInfo const * end =
-					overlay_info
-					+
-					map.overlay_manager().get_overlays
-							 	(TCoords<>(coords[F], TCoords<>::R), overlay_info);
-
-				Point tripos
-					((pos[F].x + pos[R].x + pos[BR].x) / 3,
-					 (pos[F].y + pos[R].y + pos[BR].y) / 3);
-
-				for
-					(OverlayManager::OverlayInfo const * it = overlay_info;
-					 it < end;
-					 ++it)
-					dst.blit(tripos - it->hotspot, it->pic);
+				overlay_info.clear();
+				overlay_manager.get_overlays(TCoords<>(coords[F], TCoords<>::R), &overlay_info);
+
+				Point tripos(
+				   (pos[F].x + pos[R].x + pos[BR].x) / 3, (pos[F].y + pos[R].y + pos[BR].y) / 3);
+				for (const auto& overlay : overlay_info) {
+					dst.blit(tripos - overlay.hotspot, overlay.pic);
+				}
 			}
 
 			{
 				// Render overlays on the D triangle
-				OverlayManager::OverlayInfo overlay_info[MAX_OVERLAYS_PER_TRIANGLE];
-				OverlayManager::OverlayInfo const * end =
-					overlay_info
-					+
-					map.overlay_manager().get_overlays
-							 	(TCoords<>(coords[F], TCoords<>::D), overlay_info);
-
-				Point tripos
-					((pos[F].x + pos[BL].x + pos[BR].x) / 3,
-					 (pos[F].y + pos[BL].y + pos[BR].y) / 3);
-
-				for
-					(OverlayManager::OverlayInfo const * it = overlay_info;
-					 it < end;
-					 ++it)
-					dst.blit(tripos - it->hotspot, it->pic);
+				overlay_info.clear();
+				overlay_manager.get_overlays(TCoords<>(coords[F], TCoords<>::D), &overlay_info);
+
+				Point tripos(
+				   (pos[F].x + pos[BL].x + pos[BR].x) / 3, (pos[F].y + pos[BL].y + pos[BR].y) / 3);
+				for (const auto& overlay : overlay_info) {
+					dst.blit(tripos - overlay.hotspot, overlay.pic);
+				}
 			}
 		}
 	}

=== modified file 'src/graphic/game_renderer.h'
--- src/graphic/game_renderer.h	2015-02-18 08:09:42 +0000
+++ src/graphic/game_renderer.h	2015-03-29 18:13:50 +0000
@@ -58,7 +58,9 @@
 
 	// Renders the map from an omniscient perspective. This is used
 	// for spectators, players that see all, and in the editor.
-	void rendermap(RenderTarget& dst, const Widelands::EditorGameBase& egbase, const Point& view_offset);
+	void rendermap(RenderTarget& dst,
+	               const Widelands::EditorGameBase& egbase,
+	               const Point& view_offset);
 
 private:
 	// Draw the map for the given parameters (see rendermap). 'player'

=== modified file 'src/graphic/gl/road_program.h'
--- src/graphic/gl/road_program.h	2015-03-01 09:23:10 +0000
+++ src/graphic/gl/road_program.h	2015-03-29 18:13:50 +0000
@@ -39,7 +39,10 @@
 
 	// Draws the roads. The dimensions of the renderbuffer are needed to convert from pixel to GL
 	// space.
-	void draw(int renderbuffer_width, int renderbuffer_height, const FieldsToDraw& fields_to_draw, float z_value);
+	void draw(int renderbuffer_width,
+	          int renderbuffer_height,
+	          const FieldsToDraw& fields_to_draw,
+	          float z_value);
 
 private:
 	struct PerVertexData {

=== modified file 'src/graphic/render_queue.cc'
--- src/graphic/render_queue.cc	2015-02-20 20:22:48 +0000
+++ src/graphic/render_queue.cc	2015-03-29 18:13:50 +0000
@@ -48,8 +48,7 @@
 //   - we batch up by program to have maximal batching.
 //   - and we want to render frontmost objects first, so that we do not render
 //     any pixel more than once.
-static_assert(RenderQueue::Program::HIGHEST_PROGRAM_ID <= 8,
-              "Need to change sorting keys.");  // 4 bits.
+static_assert(RenderQueue::Program::HIGHEST_PROGRAM_ID <= 8, "Please fix make_key_*.");
 
 uint64_t
 make_key_opaque(const uint64_t program_id, const uint64_t z_value, const uint64_t extra_value) {

=== modified file 'src/graphic/rendertarget.cc'
--- src/graphic/rendertarget.cc	2015-01-29 05:56:51 +0000
+++ src/graphic/rendertarget.cc	2015-03-29 18:13:50 +0000
@@ -26,7 +26,6 @@
 #include "graphic/surface.h"
 #include "logic/player.h"
 #include "logic/tribe.h"
-#include "wui/overlay_manager.h"
 
 using Widelands::BaseImmovable;
 using Widelands::Coords;

=== modified file 'src/logic/CMakeLists.txt'
--- src/logic/CMakeLists.txt	2015-02-20 20:04:28 +0000
+++ src/logic/CMakeLists.txt	2015-03-29 18:13:50 +0000
@@ -261,5 +261,4 @@
     widelands_ball_of_mud
     wui
     wui_mapview_pixelfunctions
-    wui_overlay_manager
 )

=== modified file 'src/logic/field.h'
--- src/logic/field.h	2015-01-24 11:04:49 +0000
+++ src/logic/field.h	2015-03-29 18:13:50 +0000
@@ -115,7 +115,6 @@
 	BaseImmovable * immovable;
 
 	uint8_t caps                    : 7;
-	uint8_t buildhelp_overlay_index : 3;
 	uint8_t roads                   : 6;
 
 	Height height;
@@ -191,11 +190,6 @@
 			(owner_info_and_selections & ~Border_Bitmask) | (b << Border_Bit);
 	}
 
-	uint8_t get_buildhelp_overlay_index() const {return buildhelp_overlay_index;}
-	void set_buildhelp_overlay_index(BuildhelpIndex const i) {
-		buildhelp_overlay_index = i;
-	}
-
 	int32_t get_roads() const {return roads;}
 	int32_t get_road(int32_t const dir) const {
 		return (roads >> dir) & RoadType::kMask;

=== modified file 'src/logic/map.cc'
--- src/logic/map.cc	2015-02-24 13:51:38 +0000
+++ src/logic/map.cc	2015-03-29 18:13:50 +0000
@@ -47,7 +47,6 @@
 #include "map_io/s2map.h"
 #include "map_io/widelands_map_loader.h"
 #include "notifications/notifications.h"
-#include "wui/overlay_manager.h"
 
 namespace Widelands {
 
@@ -114,7 +113,6 @@
 	assert(area.y < m_height);
 	assert(m_fields.get() <= area.field);
 	assert            (area.field < m_fields.get() + max_index());
-	assert(m_overlay_manager);
 
 	{ //  First pass.
 		MapRegion<Area<FCoords> > mr(*this, area);
@@ -129,12 +127,6 @@
 		MapRegion<Area<FCoords> > mr(*this, area);
 		do recalc_nodecaps_pass2(world, mr.location()); while (mr.advance(*this));
 	}
-
-	{ //  Now only recaluclate the overlays.
-		OverlayManager & om = overlay_manager();
-		MapRegion<Area<FCoords> > mr(*this, area);
-		do om.recalc_field_overlays(mr.location()); while (mr.advance(*this));
-	}
 }
 
 
@@ -149,8 +141,6 @@
 */
 void Map::recalc_whole_map(const World& world)
 {
-	assert(m_overlay_manager);
-
 	//  Post process the map in the necessary two passes to calculate
 	//  brightness and building caps
 	FCoords f;
@@ -170,11 +160,6 @@
 			f = get_fcoords(Coords(x, y));
 			recalc_nodecaps_pass2(world, f);
 		}
-
-	//  Now only recaluclate the overlays.
-	for (int16_t y = 0; y < m_height; ++y)
-		for (int16_t x = 0; x < m_width; ++x)
-			overlay_manager().recalc_field_overlays(get_fcoords(Coords(x, y)));
 }
 
 /*
@@ -303,7 +288,6 @@
 	m_hint = std::string();
 	m_background = std::string();
 
-	m_overlay_manager.reset();
 	objectives_.clear();
 
 	m_port_spaces.clear();
@@ -411,8 +395,6 @@
 		new_port_spaces.insert(temp);
 	}
 	m_port_spaces = new_port_spaces;
-
-	m_overlay_manager.reset(new OverlayManager());
 }
 
 
@@ -434,8 +416,6 @@
 	memset(m_fields.get(), 0, sizeof(Field) * w * h);
 
 	m_pathfieldmgr->set_size(w * h);
-
-	m_overlay_manager.reset(new OverlayManager());
 }
 
 /*

=== modified file 'src/logic/map.h'
--- src/logic/map.h	2014-10-29 06:00:52 +0000
+++ src/logic/map.h	2015-03-29 18:13:50 +0000
@@ -40,7 +40,6 @@
 
 class FileSystem;
 class Image;
-struct OverlayManager;
 struct S2MapLoader;
 
 namespace Widelands {
@@ -163,11 +162,6 @@
 	Map ();
 	virtual ~Map();
 
-	OverlayManager * get_overlay_manager()       {return m_overlay_manager.get();}
-	OverlayManager * get_overlay_manager() const {return m_overlay_manager.get();}
-	const OverlayManager & overlay_manager() const {return *m_overlay_manager;}
-	OverlayManager       & overlay_manager()       {return *m_overlay_manager;}
-
 	/// Returns the correct initialized loader for the given mapfile
 	std::unique_ptr<MapLoader> get_correct_loader(const std::string& filename);
 
@@ -413,8 +407,6 @@
 
 	std::unique_ptr<Field[]> m_fields;
 
-	std::unique_ptr<OverlayManager> m_overlay_manager;
-
 	std::unique_ptr<PathfieldManager> m_pathfieldmgr;
 	std::vector<std::string> m_scenario_tribes;
 	std::vector<std::string> m_scenario_names;

=== modified file 'src/wui/CMakeLists.txt'
--- src/wui/CMakeLists.txt	2015-01-31 16:03:59 +0000
+++ src/wui/CMakeLists.txt	2015-03-29 18:13:50 +0000
@@ -20,10 +20,10 @@
     wui
 )
 
-wl_library(wui_overlay_manager
+wl_library(wui_field_overlay_manager
   SRCS
-    overlay_manager.cc
-    overlay_manager.h
+    field_overlay_manager.cc
+    field_overlay_manager.h
   DEPENDS
     base_geometry
     graphic
@@ -31,6 +31,15 @@
     logic_widelands_geometry
 )
 
+wl_library(wui_edge_overlay_manager
+  SRCS
+    edge_overlay_manager.cc
+    edge_overlay_manager.h
+  DEPENDS
+    base_macros
+    logic_widelands_geometry
+)
+
 wl_library(wui_mapview_pixelfunctions
   SRCS
     mapviewpixelconstants.h
@@ -169,6 +178,7 @@
     ui_fsmenu
     widelands_ball_of_mud
     wui_chat_ui
+    wui_edge_overlay_manager
+    wui_field_overlay_manager
     wui_mapview_pixelfunctions
-    wui_overlay_manager
 )

=== modified file 'src/wui/buildingwindow.cc'
--- src/wui/buildingwindow.cc	2014-12-06 16:14:53 +0000
+++ src/wui/buildingwindow.cc	2015-03-29 18:13:50 +0000
@@ -57,7 +57,7 @@
 		 b.descr().descname()),
 	m_registry(registry),
 	m_building       (b),
-	m_workarea_job_id(0),
+	m_workarea_overlay_id(0),
 	m_avoid_fastclick(false)
 {
 	delete m_registry;
@@ -96,9 +96,9 @@
 
 BuildingWindow::~BuildingWindow()
 {
-	if (m_workarea_job_id)
-		igbase().egbase().map().overlay_manager().remove_overlay
-			(m_workarea_job_id);
+	if (m_workarea_overlay_id) {
+		igbase().mutable_field_overlay_manager()->remove_overlay(m_workarea_overlay_id);
+	}
 	m_registry = nullptr;
 }
 
@@ -467,7 +467,7 @@
  */
 void BuildingWindow::show_workarea()
 {
-	if (m_workarea_job_id) {
+	if (m_workarea_overlay_id) {
 		return; // already shown, nothing to be done
 	}
 	WorkareaInfo workarea_info;
@@ -479,7 +479,7 @@
 	if (workarea_info.empty()) {
 		return;
 	}
-	m_workarea_job_id = igbase().show_work_area(workarea_info, m_building.get_position());
+	m_workarea_overlay_id = igbase().show_work_area(workarea_info, m_building.get_position());
 
 	configure_workarea_button();
 }
@@ -489,9 +489,9 @@
  */
 void BuildingWindow::hide_workarea()
 {
-	if (m_workarea_job_id) {
-		igbase().hide_work_area(m_workarea_job_id);
-		m_workarea_job_id = 0;
+	if (m_workarea_overlay_id) {
+		igbase().hide_work_area(m_workarea_overlay_id);
+		m_workarea_overlay_id = 0;
 
 		configure_workarea_button();
 	}
@@ -503,7 +503,7 @@
 void BuildingWindow::configure_workarea_button()
 {
 	if (m_toggle_workarea) {
-		if (m_workarea_job_id) {
+		if (m_workarea_overlay_id) {
 			m_toggle_workarea->set_tooltip(_("Hide work area"));
 			m_toggle_workarea->set_perm_pressed(true);
 		} else {
@@ -515,7 +515,7 @@
 
 
 void BuildingWindow::toggle_workarea() {
-	if (m_workarea_job_id) {
+	if (m_workarea_overlay_id) {
 		hide_workarea();
 	} else {
 		show_workarea();

=== modified file 'src/wui/buildingwindow.h'
--- src/wui/buildingwindow.h	2014-11-30 18:49:38 +0000
+++ src/wui/buildingwindow.h	2015-03-29 18:13:50 +0000
@@ -22,9 +22,10 @@
 
 #include <cstdlib>
 
-#include "wui/interactive_gamebase.h"
 #include "ui_basic/button.h"
 #include "ui_basic/window.h"
+#include "wui/field_overlay_manager.h"
+#include "wui/interactive_gamebase.h"
 #include "wui/waresdisplay.h"
 
 /**
@@ -89,7 +90,7 @@
 	Widelands::PlayerNumber m_capscache_player_number;
 	bool m_caps_setup;
 
-	OverlayManager::JobId m_workarea_job_id;
+	FieldOverlayManager::OverlayId m_workarea_overlay_id;
 	bool m_avoid_fastclick;
 };
 

=== added file 'src/wui/edge_overlay_manager.cc'
--- src/wui/edge_overlay_manager.cc	1970-01-01 00:00:00 +0000
+++ src/wui/edge_overlay_manager.cc	2015-03-29 18:13:50 +0000
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2006-2015 by the Widelands Development Team
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#include "wui/edge_overlay_manager.h"
+
+EdgeOverlayManager::EdgeOverlayManager() : m_current_overlay_id(0) {
+}
+
+EdgeOverlayManager::OverlayId EdgeOverlayManager::next_overlay_id() {
+	++m_current_overlay_id;
+	return m_current_overlay_id;
+}
+
+void EdgeOverlayManager::register_overlay
+	(Widelands::Coords const c, uint8_t const where, OverlayId const overlay_id)
+{
+	const RegisteredRoadOverlays overlay = {overlay_id, where};
+	RegisteredRoadOverlaysMap::iterator it = m_overlays.find(c);
+	if (it == m_overlays.end())
+		m_overlays.insert
+			(std::pair<const Widelands::Coords,
+			 RegisteredRoadOverlays>(c, overlay));
+	else
+		it->second = overlay;
+}
+
+void EdgeOverlayManager::remove_overlay(const Widelands::Coords c) {
+	const RegisteredRoadOverlaysMap::iterator it = m_overlays.find(c);
+	if (it != m_overlays.end())
+		m_overlays.erase(it);
+}
+
+void EdgeOverlayManager::remove_overlay(OverlayId const overlay_id) {
+	RegisteredRoadOverlaysMap::iterator it = m_overlays.begin();
+	const RegisteredRoadOverlaysMap::const_iterator end =
+		m_overlays.end();
+	while (it != end)
+		if (it->second.overlay_id == overlay_id)
+			m_overlays.erase(it++); //  Necessary!
+		else
+			++it;
+}
+
+uint8_t EdgeOverlayManager::get_overlay(const Widelands::Coords c) const {
+	RegisteredRoadOverlaysMap::const_iterator const it = m_overlays.find(c);
+	if (it != m_overlays.end())
+		return it->second.where;
+	return 0;
+}

=== added file 'src/wui/edge_overlay_manager.h'
--- src/wui/edge_overlay_manager.h	1970-01-01 00:00:00 +0000
+++ src/wui/edge_overlay_manager.h	2015-03-29 18:13:50 +0000
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2006-2015 by the Widelands Development Team
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#ifndef WL_WUI_EDGE_OVERLAY_MANAGER_H
+#define WL_WUI_EDGE_OVERLAY_MANAGER_H
+
+#include <map>
+
+#include "base/macros.h"
+#include "logic/widelands_geometry.h"
+
+// Similar to FieldOverlayManager, this class cares for overlays that are drawn
+// onto the edges of triangles.
+class EdgeOverlayManager {
+public:
+	// A unique id identifying a registered overlay.
+	using OverlayId = uint32_t;
+
+	EdgeOverlayManager();
+
+	/// Get a unique, unused job id.
+	OverlayId next_overlay_id();
+
+	//  When a road overlay information is requested the same data as for a
+	//  field is returned (a uint8_t which needs to be ANDed).
+	void register_overlay
+		(Widelands::Coords, uint8_t where, OverlayId overlay_id = 0);
+	void remove_overlay(Widelands::Coords);
+	void remove_overlay(OverlayId overlay_id);
+	uint8_t get_overlay(Widelands::Coords c) const;
+
+private:
+	struct RegisteredRoadOverlays {
+		OverlayId overlay_id;
+		uint8_t where;
+	};
+
+	using RegisteredRoadOverlaysMap =
+	   std::map<const Widelands::Coords, RegisteredRoadOverlays, Widelands::Coords::OrderingFunctor>;
+
+	OverlayId m_current_overlay_id;
+	RegisteredRoadOverlaysMap m_overlays;
+
+	DISALLOW_COPY_AND_ASSIGN(EdgeOverlayManager);
+};
+
+
+
+#endif  // end of include guard: WL_WUI_EDGE_OVERLAY_MANAGER_H

=== renamed file 'src/wui/overlay_manager.cc' => 'src/wui/field_overlay_manager.cc'
--- src/wui/overlay_manager.cc	2014-09-14 11:31:58 +0000
+++ src/wui/field_overlay_manager.cc	2015-03-29 18:13:50 +0000
@@ -17,7 +17,7 @@
  *
  */
 
-#include "wui/overlay_manager.h"
+#include "wui/field_overlay_manager.h"
 
 #include <algorithm>
 
@@ -26,110 +26,102 @@
 #include "graphic/graphic.h"
 #include "logic/field.h"
 
-OverlayManager::OverlayManager() :
-	m_are_graphics_loaded(false), m_showbuildhelp(false), m_current_job_id(0) {
-}
-
-/**
- * \returns the currently registered overlays and the buildhelp for a node.
- */
-uint8_t OverlayManager::get_overlays
-	(Widelands::FCoords const c, OverlayInfo * const overlays) const
-{
-	assert(m_are_graphics_loaded);
-
-	uint8_t num_ret = 0;
-
+FieldOverlayManager::FieldOverlayManager() : m_current_overlay_id(0) {
+	OverlayInfo * buildhelp_info = m_buildhelp_infos;
+	const char * filenames[] = {
+		"pics/set_flag.png",
+		"pics/small.png",
+		"pics/medium.png",
+		"pics/big.png",
+		"pics/mine.png",
+		"pics/port.png"
+	};
+	const char * const * filename = filenames;
+
+	//  Special case for flag, which has a different formula for hotspot_y.
+	buildhelp_info->pic = g_gr->images().get(*filename);
+	buildhelp_info->hotspot = Point(buildhelp_info->pic->width() / 2, buildhelp_info->pic->height() - 1);
+
+	const OverlayInfo * const buildhelp_infos_end =
+		buildhelp_info + Widelands::Field::Buildhelp_None;
+	for (;;) { // The other buildhelp overlays.
+		++buildhelp_info, ++filename;
+		if (buildhelp_info == buildhelp_infos_end)
+			break;
+		buildhelp_info->pic = g_gr->images().get(*filename);
+		buildhelp_info->hotspot = Point(buildhelp_info->pic->width() / 2, buildhelp_info->pic->height() / 2);
+	}
+
+}
+
+bool FieldOverlayManager::buildhelp() const {
+	return m_buildhelp;
+}
+
+void FieldOverlayManager::show_buildhelp(const bool value) {
+	m_buildhelp = value;
+}
+
+void FieldOverlayManager::get_overlays(Widelands::FCoords const c,
+                                          std::vector<OverlayInfo>* result) const {
 	const RegisteredOverlaysMap & overlay_map = m_overlays[Widelands::TCoords<>::None];
 	RegisteredOverlaysMap::const_iterator it = overlay_map.lower_bound(c);
-	while (it != overlay_map.end() && it->first == c && it->second.level <= MAX_OVERLAYS_PER_NODE)
-	{
-		overlays[num_ret].pic = it->second.pic;
-		overlays[num_ret].hotspot = it->second.hotspot;
-		if (++num_ret == MAX_OVERLAYS_PER_NODE)
-			goto end;
+
+	while (it != overlay_map.end() && it->first == c && it->second.level <= kLevelForBuildHelp) {
+		result->emplace_back(it->second.pic, it->second.hotspot);
 		++it;
 	}
-	if (m_showbuildhelp) {
-		const uint8_t buildhelp_overlay_index =
-			c.field->get_buildhelp_overlay_index();
+
+	if (m_buildhelp) {
+		int buildhelp_overlay_index = get_buildhelp_overlay(c);
 		if (buildhelp_overlay_index < Widelands::Field::Buildhelp_None) {
-			overlays[num_ret] = m_buildhelp_infos[buildhelp_overlay_index];
-			if (++num_ret == MAX_OVERLAYS_PER_NODE)
-				goto end;
-		}
+		   result->emplace_back(m_buildhelp_infos[buildhelp_overlay_index]);
+	   }
 	}
+
 	while (it != overlay_map.end() && it->first == c) {
-		overlays[num_ret].pic = it->second.pic;
-		overlays[num_ret].hotspot = it->second.hotspot;
-		if (++num_ret == MAX_OVERLAYS_PER_NODE)
-			goto end;
+		result->emplace_back(it->second.pic, it->second.hotspot);
 		++it;
 	}
-end:
-	return num_ret;
 }
 
-/**
- * \returns the currently registered overlays for a triangle.
- */
-uint8_t OverlayManager::get_overlays
-	(Widelands::TCoords<> const c, OverlayInfo * const overlays) const
-{
-	assert(m_are_graphics_loaded);
+void FieldOverlayManager::get_overlays(Widelands::TCoords<> const c,
+                                       std::vector<OverlayInfo>* result) const {
 	assert(c.t == Widelands::TCoords<>::D || c.t == Widelands::TCoords<>::R);
 
-	uint8_t num_ret = 0;
 
 	const RegisteredOverlaysMap & overlay_map = m_overlays[c.t];
 	RegisteredOverlaysMap::const_iterator it = overlay_map.lower_bound(c);
-	while
-		(it != overlay_map.end()
-		 &&
-		 it->first == c
-		 &&
-		 num_ret < MAX_OVERLAYS_PER_TRIANGLE)
-	{
-		overlays[num_ret].pic = it->second.pic;
-		overlays[num_ret].hotspot = it->second.hotspot;
-		++num_ret;
+	while (it != overlay_map.end() && it->first == c) {
+		result->emplace_back(it->second.pic, it->second.hotspot);
 		++it;
 	}
-	return num_ret;
 }
 
-/**
- * Recalculates all calculatable overlays for fields
- */
-void OverlayManager::recalc_field_overlays(const Widelands::FCoords fc) {
+int FieldOverlayManager::get_buildhelp_overlay(const Widelands::FCoords& fc) const {
 	Widelands::NodeCaps const caps =
 	   m_callback ? static_cast<Widelands::NodeCaps>(m_callback(fc)) : fc.field->nodecaps();
 
-	fc.field->set_buildhelp_overlay_index
-		(caps & Widelands::BUILDCAPS_MINE                                      ?
-		 Widelands::Field::Buildhelp_Mine                                      :
-		 (caps & Widelands::BUILDCAPS_SIZEMASK) == Widelands::BUILDCAPS_BIG    ?
-			(caps & Widelands::BUILDCAPS_PORT ?
-			 Widelands::Field::Buildhelp_Port :
-			 Widelands::Field::Buildhelp_Big)
-		 :
-		 (caps & Widelands::BUILDCAPS_SIZEMASK) == Widelands::BUILDCAPS_MEDIUM ?
-		 Widelands::Field::Buildhelp_Medium                                    :
-		 (caps & Widelands::BUILDCAPS_SIZEMASK) == Widelands::BUILDCAPS_SMALL  ?
-		 Widelands::Field::Buildhelp_Small                                     :
-		 caps & Widelands::BUILDCAPS_FLAG                                      ?
-		 Widelands::Field::Buildhelp_Flag : Widelands::Field::Buildhelp_None);
+	const int value = caps & Widelands::BUILDCAPS_MINE ?
+	               Widelands::Field::Buildhelp_Mine :
+	               (caps & Widelands::BUILDCAPS_SIZEMASK) == Widelands::BUILDCAPS_BIG ?
+	               (caps & Widelands::BUILDCAPS_PORT ? Widelands::Field::Buildhelp_Port :
+	                                                   Widelands::Field::Buildhelp_Big) :
+	               (caps & Widelands::BUILDCAPS_SIZEMASK) == Widelands::BUILDCAPS_MEDIUM ?
+	               Widelands::Field::Buildhelp_Medium :
+	               (caps & Widelands::BUILDCAPS_SIZEMASK) == Widelands::BUILDCAPS_SMALL ?
+	               Widelands::Field::Buildhelp_Small :
+	               caps & Widelands::BUILDCAPS_FLAG ? Widelands::Field::Buildhelp_Flag :
+	                                                  Widelands::Field::Buildhelp_None;
+	return value;
 }
 
-/**
- * finally, register a new overlay
- */
-void OverlayManager::register_overlay
+void FieldOverlayManager::register_overlay
 	(Widelands::TCoords<> const c,
 	 const Image* pic,
 	 int32_t              const level,
 	 Point                      hotspot,
-	 JobId               const jobid)
+	 OverlayId               const overlay_id)
 {
 	assert(c.t <= 2);
 	assert(level != 5); //  level == 5 is undefined behavior
@@ -150,13 +142,13 @@
 			 &&
 			 it->second.level   == level)
 		{
-			it->second.jobids.insert(jobid);
+			it->second.overlay_ids.insert(overlay_id);
 			return;
 		}
 
 	overlay_map.insert
 		(std::pair<Widelands::Coords const, RegisteredOverlays>
-		 	(c, RegisteredOverlays(jobid, pic, hotspot, level)));
+		 	(c, RegisteredOverlays(overlay_id, pic, hotspot, level)));
 
 	//  Now manually sort, so that they are ordered
 	//    * first by c (done by std::multimap)
@@ -180,10 +172,7 @@
 	} while (it->first == c);
 }
 
-/**
- * remove one (or many) overlays from a node or triangle
- */
-void OverlayManager::remove_overlay
+void FieldOverlayManager::remove_overlay
 	(Widelands::TCoords<> const c, const Image* pic)
 {
 	assert(c.t <= 2);
@@ -203,109 +192,23 @@
 	}
 }
 
-/**
- * remove all overlays with this jobid
- */
-void OverlayManager::remove_overlay(const JobId jobid) {
+void FieldOverlayManager::remove_overlay(const OverlayId overlay_id) {
 	const RegisteredOverlaysMap * const overlays_end = m_overlays + 3;
 	for (RegisteredOverlaysMap * j = m_overlays; j != overlays_end; ++j)
 		for (RegisteredOverlaysMap::iterator it = j->begin(); it != j->end();) {
-			it->second.jobids.erase(jobid);
-			if (it->second.jobids.empty())
+			it->second.overlay_ids.erase(overlay_id);
+			if (it->second.overlay_ids.empty())
 				j->erase(it++); //  This is necessary!
 			else
 				++it;
 		}
 }
 
-/**
- * Register road overlays
- */
-void OverlayManager::register_road_overlay
-	(Widelands::Coords const c, uint8_t const where, JobId const jobid)
-{
-	const RegisteredRoadOverlays overlay = {jobid, where};
-	RegisteredRoadOverlaysMap::iterator it = m_road_overlays.find(c);
-	if (it == m_road_overlays.end())
-		m_road_overlays.insert
-			(std::pair<const Widelands::Coords,
-			 RegisteredRoadOverlays>(c, overlay));
-	else
-		it->second = overlay;
-}
-
-/**
- * Remove road overlay
- */
-void OverlayManager::remove_road_overlay(const Widelands::Coords c) {
-	const RegisteredRoadOverlaysMap::iterator it = m_road_overlays.find(c);
-	if (it != m_road_overlays.end())
-		m_road_overlays.erase(it);
-}
-
-/**
- * remove all overlays with this jobid
- */
-void OverlayManager::remove_road_overlay(JobId const jobid) {
-	RegisteredRoadOverlaysMap::iterator it = m_road_overlays.begin();
-	const RegisteredRoadOverlaysMap::const_iterator end =
-		m_road_overlays.end();
-	while (it != end)
-		if (it->second.jobid == jobid)
-			m_road_overlays.erase(it++); //  Necessary!
-		else
-			++it;
-}
-
-/**
- * call cleanup and then, when graphic is reloaded
- * overlay_manager calls this for himself and everything should be fine
- *
- * Load all the needed graphics
- */
-void OverlayManager::load_graphics() {
-	if (m_are_graphics_loaded)
-		return;
-
-	OverlayInfo * buildhelp_info = m_buildhelp_infos;
-	static const char * filenames[] = {
-		"pics/set_flag.png",
-		"pics/small.png",
-		"pics/medium.png",
-		"pics/big.png",
-		"pics/mine.png",
-		"pics/port.png"
-	};
-	const char * const * filename = filenames;
-
-	//  Special case for flag, which has a different formula for hotspot_y.
-	buildhelp_info->pic = g_gr->images().get(*filename);
-	buildhelp_info->hotspot = Point(buildhelp_info->pic->width() / 2, buildhelp_info->pic->height() - 1);
-
-	const OverlayInfo * const buildhelp_infos_end =
-		buildhelp_info + Widelands::Field::Buildhelp_None;
-	for (;;) { // The other buildhelp overlays.
-		++buildhelp_info, ++filename;
-		if (buildhelp_info == buildhelp_infos_end)
-			break;
-		buildhelp_info->pic = g_gr->images().get(*filename);
-		buildhelp_info->hotspot = Point(buildhelp_info->pic->width() / 2, buildhelp_info->pic->height() / 2);
-	}
-
-	m_are_graphics_loaded = true;
-}
-
-void OverlayManager::register_overlay_callback_function(CallbackFn function) {
+void FieldOverlayManager::register_overlay_callback_function(CallbackFn function) {
 	m_callback = function;
 }
 
-void OverlayManager::remove_overlay_callback_function() {
-	m_callback.clear();
-}
-
-OverlayManager::JobId OverlayManager::get_a_job_id() {
-	++m_current_job_id;
-	if (m_current_job_id == 0)
-		++m_current_job_id;
-	return m_current_job_id;
+FieldOverlayManager::OverlayId FieldOverlayManager::next_overlay_id() {
+	++m_current_overlay_id;
+	return m_current_overlay_id;
 }

=== renamed file 'src/wui/overlay_manager.h' => 'src/wui/field_overlay_manager.h'
--- src/wui/overlay_manager.h	2014-09-14 11:31:58 +0000
+++ src/wui/field_overlay_manager.h	2015-03-29 18:13:50 +0000
@@ -17,14 +17,13 @@
  *
  */
 
-#ifndef WL_WUI_OVERLAY_MANAGER_H
-#define WL_WUI_OVERLAY_MANAGER_H
+#ifndef WL_WUI_FIELD_OVERLAY_MANAGER_H
+#define WL_WUI_FIELD_OVERLAY_MANAGER_H
 
+#include <functional>
 #include <map>
 #include <set>
-
-#include <boost/bind.hpp>
-#include <boost/function.hpp>
+#include <vector>
 
 #include "logic/field.h"
 #include "logic/widelands_geometry.h"
@@ -37,134 +36,105 @@
  * manages overlays in the following way:
  *   - When someone registered one (or more) special overlays
  *     for a field he draws them accordingly
- *   - If nothing was registered for this field, the Overlay Manager
- *     automatically returns
- *        - buildhelp (if activated)
  *
  *    about the level variable:
- *     the level describe when the overlay should be drawn
- *     buildhelp graphics have a level of 5, lower means the
- *     buildhelp will cover the old overlays, otherways the new
- *     overlay will cover the buildhelp.
+ *     the level describe when the overlay should be drawn, lower means drawn
+ *     earlier.
  *
- *    about jobid:
- *     the jobid can be given to the register function, whenever
+ *    about overlay_id:
+ *     the overlay_id can be given to the register function, whenever
  *     the job is finished or canceled, a simple remove_overlay
- *     with the jobid can be called and all overlays created in the
+ *     with the overlay_id can be called and all overlays created in the
  *     job are removed. This is useful for interactive road building.
  */
-#define MAX_OVERLAYS_PER_NODE 6
-#define MAX_OVERLAYS_PER_TRIANGLE 3
-
-
-struct OverlayManager {
-	using JobId = uint32_t;
-
+constexpr int kLevelForBuildHelp = 5;
+struct FieldOverlayManager {
+	/// A unique id identifying a registered overlay.
+	using OverlayId = uint32_t;
+
+	/// A overlay as drawn onto the screen.
 	struct OverlayInfo {
+		OverlayInfo() = default;
+		OverlayInfo(const Image* init_pic, const Point& init_hotspot)
+		   : pic(init_pic), hotspot(init_hotspot) {
+		}
+
 		const Image* pic;
 		Point hotspot;
 	};
 
+	/// A function returning Field::nodecaps() for the build overlay. This can be
+	/// registered to hide or change some of the nodecaps during rendering.
 	using CallbackFn =
-		boost::function<int32_t(const Widelands::TCoords<Widelands::FCoords>& coordinates)>;
-
-	OverlayManager();
-
-	//  register callback function (see data below for description)
+	   std::function<int32_t(const Widelands::TCoords<Widelands::FCoords>& coordinates)>;
+
+	FieldOverlayManager();
+
+	/// Returns true if the buildhelp is currently shown.
+	bool buildhelp() const;
+
+	/// Defines if the buildhelp should be shown.
+	void show_buildhelp(bool t);
+
+	/// Register callback function.
 	void register_overlay_callback_function(CallbackFn function);
-	void remove_overlay_callback_function();
-
-	/// Get a unique, unused job id.
-	uint32_t get_a_job_id();
-
-	void load_graphics();
+
+	/// Get a unique, unused id that can be passed to register_overlay.
+	OverlayId next_overlay_id();
 
 	/// Register an overlay at a location (node or triangle). hotspot is the point
 	/// of the picture that will be exactly over the location. If hotspot is
 	/// Point::invalid(), the center of the picture will be used as hotspot.
-	void register_overlay
-		(Widelands::TCoords<>,
-		 const Image* pic,
-		 int32_t level,
-		 Point   hotspot = Point::invalid(),
-		 JobId jobid = 0);
+	void register_overlay(const Widelands::TCoords<> coords,
+	                      const Image* pic,
+	                      int32_t level,
+	                      Point hotspot = Point::invalid(),
+	                      OverlayId overlay_id = 0);
 
-	// removes all overlays when pic is zero
+	/// removes all overlays when pic is nullptr.
 	void remove_overlay(Widelands::TCoords<>, const Image* pic);
-	void remove_overlay(JobId jobid);
-
-	uint8_t get_overlays(Widelands::FCoords c, OverlayInfo *) const;
-	uint8_t get_overlays(Widelands::TCoords<>, OverlayInfo *) const;
-
-	boost::function<void(bool)> onBuildHelpToggle;
-	bool buildhelp() {return m_showbuildhelp;}
-	void show_buildhelp(bool const t) {
-		if (m_showbuildhelp != t) {
-			m_showbuildhelp = t;
-			if (onBuildHelpToggle) onBuildHelpToggle(m_showbuildhelp);
-		}
-	}
-	void toggle_buildhelp() {
-		m_showbuildhelp = !m_showbuildhelp;
-		if (onBuildHelpToggle) onBuildHelpToggle(m_showbuildhelp);
-	}
-
-	void recalc_field_overlays(Widelands::FCoords);
-
-	//  Road overlays are registered like normal overlays and removed like
-	//  normal overlays but they use are handled internally completely
-	//  different. When a road overlay information is requested the same data a
-	//  s for a field is returned (a uint8_t which needs to be ANDed).
-	void register_road_overlay
-		(Widelands::Coords, uint8_t where, JobId jobid = 0);
-	void remove_road_overlay(Widelands::Coords);
-	void remove_road_overlay(JobId jobid);
-	uint8_t get_road_overlay(const Widelands::Coords c) const {
-		RegisteredRoadOverlaysMap::const_iterator const it =
-			m_road_overlays.find(c);
-		if (it != m_road_overlays.end())
-			return it->second.where;
-		return 0;
-	}
+
+	/// remove all overlays with this overlay_id
+	void remove_overlay(OverlayId overlay_id);
+
+	/// Returns the currently registered overlays and the buildhelp for a node.
+	void get_overlays(Widelands::FCoords c, std::vector<OverlayInfo>* result) const;
+
+	/// Returns the currently registered overlays for a triangle.
+	void get_overlays(Widelands::TCoords<>, std::vector<OverlayInfo>* result) const;
 
 private:
 	struct RegisteredOverlays {
-		RegisteredOverlays(const JobId init_jobid,
+		RegisteredOverlays(const OverlayId init_overlay_id,
 		                    const Image* init_pic,
 		                    const Point init_hotspot,
 		                    const int init_level)
 		   : pic(init_pic), hotspot(init_hotspot), level(init_level) {
-			jobids.insert(init_jobid);
+			overlay_ids.insert(init_overlay_id);
 		}
-		std::set<JobId> jobids;
+		std::set<OverlayId> overlay_ids;
 		const Image* pic;
 		Point hotspot;
 		int level;
 	};
 
-	struct RegisteredRoadOverlays {
-		JobId jobid;
-		uint8_t where;
-	};
-
-	using RegisteredRoadOverlaysMap =
-		std::map<const Widelands::Coords, RegisteredRoadOverlays, Widelands::Coords::OrderingFunctor>;
-
-	RegisteredRoadOverlaysMap m_road_overlays;
-
-	using RegisteredOverlaysMap =
-		std::multimap<const Widelands::Coords, RegisteredOverlays, Widelands::Coords::OrderingFunctor>;
+	using RegisteredOverlaysMap = std::multimap<const Widelands::Coords,
+	                                                      RegisteredOverlays,
+	                                                      Widelands::Coords::OrderingFunctor>;
+
+	// Returns the index into m_buildhelp_infos for the correct fieldcaps for
+	// 'fc' according to the current 'm_callback'.
+	int get_buildhelp_overlay(const Widelands::FCoords& fc) const;
 
 	//  indexed by TCoords<>::TriangleIndex
 	RegisteredOverlaysMap m_overlays[3];
 
 	OverlayInfo m_buildhelp_infos[Widelands::Field::Buildhelp_None];
-	bool m_are_graphics_loaded;
-	bool m_showbuildhelp;
+	bool m_buildhelp;
 
 	// this callback is used to define where overlays are drawn.
 	CallbackFn m_callback;
-	uint32_t m_current_job_id;
+	OverlayId m_current_overlay_id;
 };
 
-#endif  // end of include guard: WL_WUI_OVERLAY_MANAGER_H
+#endif  // end of include guard: WL_WUI_FIELD_OVERLAY_MANAGER_H

=== modified file 'src/wui/fieldaction.cc'
--- src/wui/fieldaction.cc	2014-12-06 16:14:53 +0000
+++ src/wui/fieldaction.cc	2015-03-29 18:13:50 +0000
@@ -40,9 +40,9 @@
 #include "ui_basic/unique_window.h"
 #include "wui/actionconfirm.h"
 #include "wui/attack_box.h"
+#include "wui/field_overlay_manager.h"
 #include "wui/game_debug_ui.h"
 #include "wui/interactive_player.h"
-#include "wui/overlay_manager.h"
 #include "wui/waresdisplay.h"
 #include "wui/watchwindow.h"
 
@@ -215,14 +215,14 @@
 
 	Widelands::Player * m_plr;
 	Widelands::Map    * m_map;
-	OverlayManager & m_overlay_manager;
+	FieldOverlayManager & m_field_overlay_manager;
 
 	Widelands::FCoords  m_node;
 
 	UI::TabPanel      m_tabpanel;
 	bool m_fastclick; // if true, put the mouse over first button in first tab
 	uint32_t m_best_tab;
-	OverlayManager::JobId m_workarea_preview_job_id;
+	FieldOverlayManager::OverlayId m_workarea_preview_overlay_id;
 
 	/// Variables to use with attack dialog.
 	AttackBox * m_attack_box;
@@ -275,12 +275,12 @@
 	UI::UniqueWindow(ib, "field_action", registry, 68, 34, _("Action")),
 	m_plr(plr),
 	m_map(&ib->egbase().map()),
-	m_overlay_manager(*m_map->get_overlay_manager()),
+	m_field_overlay_manager(*ib->mutable_field_overlay_manager()),
 	m_node(ib->get_sel_pos().node, &(*m_map)[ib->get_sel_pos().node]),
 	m_tabpanel(this, 0, 0, g_gr->images().get("pics/but1.png")),
 	m_fastclick(true),
 	m_best_tab(0),
-	m_workarea_preview_job_id(0),
+	m_workarea_preview_overlay_id(0),
 	m_attack_box(nullptr)
 {
 	ib->set_sel_freeze(true);
@@ -292,8 +292,8 @@
 
 FieldActionWindow::~FieldActionWindow()
 {
-	if (m_workarea_preview_job_id)
-		m_overlay_manager.remove_overlay(m_workarea_preview_job_id);
+	if (m_workarea_preview_overlay_id)
+		m_field_overlay_manager.remove_overlay(m_workarea_preview_overlay_id);
 	ibase().set_sel_freeze(false);
 	delete m_attack_box;
 }
@@ -813,9 +813,9 @@
 void FieldActionWindow::building_icon_mouse_out
 	(Widelands::BuildingIndex)
 {
-	if (m_workarea_preview_job_id) {
-		m_overlay_manager.remove_overlay(m_workarea_preview_job_id);
-		m_workarea_preview_job_id = 0;
+	if (m_workarea_preview_overlay_id) {
+		m_field_overlay_manager.remove_overlay(m_workarea_preview_overlay_id);
+		m_workarea_preview_overlay_id = 0;
 	}
 }
 
@@ -823,11 +823,11 @@
 void FieldActionWindow::building_icon_mouse_in
 	(const Widelands::BuildingIndex idx)
 {
-	if (ibase().m_show_workarea_preview && !m_workarea_preview_job_id) {
+	if (ibase().m_show_workarea_preview && !m_workarea_preview_overlay_id) {
 		const WorkareaInfo & workarea_info =
 			m_plr->tribe().get_building_descr(Widelands::BuildingIndex(idx))
 			->m_workarea_info;
-		m_workarea_preview_job_id = ibase().show_work_area(workarea_info, m_node);
+		m_workarea_preview_overlay_id = ibase().show_work_area(workarea_info, m_node);
 	}
 }
 

=== modified file 'src/wui/interactive_base.cc'
--- src/wui/interactive_base.cc	2015-02-16 19:04:26 +0000
+++ src/wui/interactive_base.cc	2015-03-29 18:13:50 +0000
@@ -46,6 +46,8 @@
 #include "profile/profile.h"
 #include "scripting/lua_interface.h"
 #include "wlapplication.h"
+#include "wui/edge_overlay_manager.h"
+#include "wui/field_overlay_manager.h"
 #include "wui/game_chat_menu.h"
 #include "wui/game_debug_ui.h"
 #include "wui/interactive_player.h"
@@ -53,7 +55,6 @@
 #include "wui/mapviewpixelconstants.h"
 #include "wui/mapviewpixelfunctions.h"
 #include "wui/minimap.h"
-#include "wui/overlay_manager.h"
 #include "wui/quicknavigation.h"
 #include "wui/unique_window_handler.h"
 
@@ -85,6 +86,8 @@
      m_chatOverlay(new ChatOverlay(this, 10, 25, get_w() / 2, get_h() - 25)),
      m_toolbar(this, 0, 0, UI::Box::Horizontal),
      m(new InteractiveBaseInternals(new QuickNavigation(the_egbase, get_w(), get_h()))),
+	  m_field_overlay_manager(new FieldOverlayManager()),
+	  m_edge_overlay_manager(new EdgeOverlayManager()),
      m_egbase(the_egbase),
 #ifndef NDEBUG //  not in releases
      m_display_flags(dfDebug),
@@ -156,13 +159,12 @@
 void InteractiveBase::set_sel_pos(Widelands::NodeAndTriangle<> const center)
 {
 	Map & map = egbase().map();
-	OverlayManager & overlay_manager = map.overlay_manager();
 
 	// Remove old sel pointer
 	if (m_sel.jobid)
-		overlay_manager.remove_overlay(m_sel.jobid);
-	const OverlayManager::JobId jobid =
-		m_sel.jobid = overlay_manager.get_a_job_id();
+		m_field_overlay_manager->remove_overlay(m_sel.jobid);
+	const FieldOverlayManager::OverlayId jobid =
+		m_sel.jobid = m_field_overlay_manager->next_overlay_id();
 
 	m_sel.pos = center;
 
@@ -174,13 +176,13 @@
 		Widelands::MapTriangleRegion<> mr
 			(map, Area<TCoords<> >(center.triangle, m_sel.radius));
 		do
-			overlay_manager.register_overlay
+			m_field_overlay_manager->register_overlay
 				(mr.location(), m_sel.pic, 7, Point::invalid(), jobid);
 		while (mr.advance(map));
 	} else {
 		Widelands::MapRegion<> mr(map, Area<>(center.node, m_sel.radius));
 		do
-			overlay_manager.register_overlay
+			m_field_overlay_manager->register_overlay
 				(mr.location(), m_sel.pic, 7, Point::invalid(), jobid);
 		while (mr.advance(map));
 		if (upcast(InteractiveGameBase const, igbase, this))
@@ -232,21 +234,25 @@
 	set_sel_picture("pics/fsel.png");
 }
 
+bool InteractiveBase::buildhelp() const {
+	return m_field_overlay_manager->buildhelp();
+}
+
+void InteractiveBase::show_buildhelp(bool t) {
+	m_field_overlay_manager->show_buildhelp(t);
+	on_buildhelp_changed(t);
+}
 
 void InteractiveBase::toggle_buildhelp() {
-	egbase().map().overlay_manager().toggle_buildhelp();
-}
-bool InteractiveBase::buildhelp() {
-	return egbase().map().overlay_manager().buildhelp();
-}
-void InteractiveBase::show_buildhelp(bool t) {
-	egbase().map().overlay_manager().show_buildhelp(t);
+	m_field_overlay_manager->show_buildhelp(!m_field_overlay_manager->buildhelp());
+}
+
+void InteractiveBase::on_buildhelp_changed(bool /* value */) {
 }
 
 // Show the given workareas at the given coords and returns the overlay job id associated
-OverlayManager::JobId InteractiveBase::show_work_area
-	(const WorkareaInfo & workarea_info, Widelands::Coords coords)
-{
+FieldOverlayManager::OverlayId InteractiveBase::show_work_area(const WorkareaInfo& workarea_info,
+                                                               Widelands::Coords coords) {
 	const uint8_t workareas_nrs = workarea_info.size();
 	WorkareaInfo::size_type wa_index;
 	switch (workareas_nrs) {
@@ -258,8 +264,7 @@
 			throw wexception("Encountered unexpected WorkareaInfo size %i", workareas_nrs);
 	}
 	Widelands::Map & map = m_egbase.map();
-	OverlayManager & overlay_manager = map.overlay_manager();
-	OverlayManager::JobId job_id = overlay_manager.get_a_job_id();
+	FieldOverlayManager::OverlayId overlay_id = m_field_overlay_manager->next_overlay_id();
 
 	Widelands::HollowArea<> hollow_area(Widelands::Area<>(coords, 0), 0);
 
@@ -269,23 +274,21 @@
 		hollow_area.radius = it->first;
 		Widelands::MapHollowRegion<> mr(map, hollow_area);
 		do
-			overlay_manager.register_overlay
+			m_field_overlay_manager->register_overlay
 				(mr.location(),
 					m_workarea_pics[wa_index],
 					0,
 					Point::invalid(),
-					job_id);
+					overlay_id);
 		while (mr.advance(map));
 		wa_index++;
 		hollow_area.hole_radius = hollow_area.radius;
 	}
-	return job_id;
+	return overlay_id;
 }
 
-void InteractiveBase::hide_work_area(OverlayManager::JobId job_id) {
-	Widelands::Map & map = m_egbase.map();
-	OverlayManager & overlay_manager = map.overlay_manager();
-	overlay_manager.remove_overlay(job_id);
+void InteractiveBase::hide_work_area(FieldOverlayManager::OverlayId overlay_id) {
+	m_field_overlay_manager->remove_overlay(overlay_id);
 }
 
 
@@ -749,11 +752,10 @@
 	//log("Add overlay\n");
 
 	Map & map = egbase().map();
-	OverlayManager & overlay_manager = map.overlay_manager();
 
 	// preview of the road
 	assert(!m_jobid);
-	m_jobid = overlay_manager.get_a_job_id();
+	m_jobid = m_field_overlay_manager->next_overlay_id();
 	const CoordPath::StepVector::size_type nr_steps = m_buildroad->get_nsteps();
 	for (CoordPath::StepVector::size_type idx = 0; idx < nr_steps; ++idx) {
 		Widelands::Direction dir = (*m_buildroad)[idx];
@@ -766,16 +768,16 @@
 
 		int32_t const shift = 2 * (dir - Widelands::WALK_E);
 
-		uint8_t set_to = overlay_manager.get_road_overlay(c);
+		uint8_t set_to = m_edge_overlay_manager->get_overlay(c);
 		set_to |=  Widelands::RoadType::kNormal << shift;
-		overlay_manager.register_road_overlay(c, set_to, m_jobid);
+		m_edge_overlay_manager->register_overlay(c, set_to, m_jobid);
 	}
 
 	// build hints
 	Widelands::FCoords endpos = map.get_fcoords(m_buildroad->get_end());
 
 	assert(!m_road_buildhelp_overlay_jobid);
-	m_road_buildhelp_overlay_jobid = overlay_manager.get_a_job_id();
+	m_road_buildhelp_overlay_jobid = m_field_overlay_manager->next_overlay_id();
 	for (int32_t dir = 1; dir <= 6; ++dir) {
 		Widelands::FCoords neighb;
 		int32_t caps;
@@ -828,7 +830,7 @@
 		else
 			name = "pics/roadb_red.png";
 
-		egbase().map().overlay_manager().register_overlay
+		m_field_overlay_manager->register_overlay
 			(neighb,
 			 g_gr->images().get(name),
 			 7,
@@ -849,14 +851,15 @@
 	//log("Remove overlay\n");
 
 	//  preview of the road
-	OverlayManager & overlay_manager = egbase().map().overlay_manager();
-	if (m_jobid)
-		overlay_manager.remove_road_overlay(m_jobid);
+	if (m_jobid) {
+		m_edge_overlay_manager->remove_overlay(m_jobid);
+	}
 	m_jobid = 0;
 
 	// build hints
-	if (m_road_buildhelp_overlay_jobid)
-		overlay_manager.remove_overlay(m_road_buildhelp_overlay_jobid);
+	if (m_road_buildhelp_overlay_jobid) {
+		m_field_overlay_manager->remove_overlay(m_road_buildhelp_overlay_jobid);
+	}
 	m_road_buildhelp_overlay_jobid = 0;
 }
 

=== modified file 'src/wui/interactive_base.h'
--- src/wui/interactive_base.h	2014-11-30 12:23:45 +0000
+++ src/wui/interactive_base.h	2015-03-29 18:13:50 +0000
@@ -33,13 +33,15 @@
 #include "ui_basic/unique_window.h"
 #include "wui/chatoverlay.h"
 #include "wui/debugconsole.h"
+#include "wui/edge_overlay_manager.h"
+#include "wui/field_overlay_manager.h"
 #include "wui/mapview.h"
-#include "wui/overlay_manager.h"
 
 namespace Widelands {struct CoordPath;}
 
+class EdgeOverlayManager;
+class UniqueWindowHandler;
 struct InteractiveBaseInternals;
-class UniqueWindowHandler;
 
 /**
  * This is used to represent the code that InteractivePlayer and
@@ -65,8 +67,9 @@
 	virtual void reference_player_tribe(Widelands::PlayerNumber, const void * const) {}
 
 	bool m_show_workarea_preview;
-	OverlayManager::JobId show_work_area(const WorkareaInfo & workarea_info, Widelands::Coords coords);
-	void hide_work_area(OverlayManager::JobId job_id);
+	FieldOverlayManager::OverlayId show_work_area(const WorkareaInfo& workarea_info,
+	                                              Widelands::Coords coords);
+	void hide_work_area(FieldOverlayManager::OverlayId overlay_id);
 
 	//  point of view for drawing
 	virtual Widelands::Player * get_player() const = 0;
@@ -79,9 +82,11 @@
 	}
 	bool get_sel_freeze() const {return m_sel.freeze;}
 
-	bool buildhelp();
+	// Returns true if the buildhelp is currently displayed.
+	bool buildhelp() const;
+
+	// Sets if the buildhelp should be displayed. Will also call on_buildhelp_changed().
 	void show_buildhelp(bool t);
-	void toggle_buildhelp ();
 
 	/**
 	 * sel_triangles determines whether the mouse pointer selects triangles.
@@ -127,7 +132,22 @@
 		log_message(std::string(message));
 	}
 
+	const FieldOverlayManager& field_overlay_manager() const {
+		return *m_field_overlay_manager;
+	}
+	FieldOverlayManager* mutable_field_overlay_manager() {
+		return m_field_overlay_manager.get();
+	}
+
+	const EdgeOverlayManager& edge_overlay_manager() const {
+		return *m_edge_overlay_manager;
+	}
+
 protected:
+	// Will be called whenever the buildhelp is changed with the new 'value'.
+	virtual void on_buildhelp_changed(bool value);
+
+	void toggle_buildhelp();
 	void toggle_minimap();
 	void hide_minimap();
 	UI::UniqueWindow::Registry & minimap_registry();
@@ -165,7 +185,7 @@
 			 		 	(Widelands::Coords(0, 0), Widelands::TCoords<>::D)),
 			 const uint32_t Radius                   = 0,
 			 const Image* Pic                     = nullptr,
-			 const OverlayManager::JobId Jobid = 0)
+			 const FieldOverlayManager::OverlayId Jobid = 0)
 			:
 			freeze(Freeze), triangles(Triangles), pos(Pos), radius(Radius),
 			pic(Pic), jobid(Jobid)
@@ -175,11 +195,14 @@
 		Widelands::NodeAndTriangle<>     pos;
 		uint32_t              radius;
 		const Image* pic;
-		OverlayManager::JobId jobid;
+		FieldOverlayManager::OverlayId jobid;
 	} m_sel;
 
 	std::unique_ptr<InteractiveBaseInternals> m;
 
+	std::unique_ptr<FieldOverlayManager> m_field_overlay_manager;
+	std::unique_ptr<EdgeOverlayManager> m_edge_overlay_manager;
+
 	std::unique_ptr<Notifications::Subscriber<GraphicResolutionChanged>>
 	   graphic_resolution_changed_subscriber_;
 	Widelands::EditorGameBase & m_egbase;
@@ -188,8 +211,8 @@
 	uint32_t          m_frametime;         //  in millseconds
 	uint32_t          m_avg_usframetime;   //  in microseconds!
 
-	OverlayManager::JobId m_jobid;
-	OverlayManager::JobId m_road_buildhelp_overlay_jobid;
+	EdgeOverlayManager::OverlayId m_jobid;
+	FieldOverlayManager::OverlayId m_road_buildhelp_overlay_jobid;
 	Widelands::CoordPath  * m_buildroad;         //  path for the new road
 	Widelands::PlayerNumber m_road_build_player;
 

=== modified file 'src/wui/interactive_gamebase.cc'
--- src/wui/interactive_gamebase.cc	2015-02-14 22:11:44 +0000
+++ src/wui/interactive_gamebase.cc	2015-03-29 18:13:50 +0000
@@ -135,18 +135,13 @@
  */
 void InteractiveGameBase::postload() {
 	Widelands::Map & map = egbase().map();
-	OverlayManager & overlay_manager = map.overlay_manager();
-	overlay_manager.show_buildhelp(false);
-	overlay_manager.register_overlay_callback_function
+	auto* overlay_manager = mutable_field_overlay_manager();
+	show_buildhelp(false);
+	m_toggle_buildhelp.set_perm_pressed(buildhelp());
+
+	overlay_manager->register_overlay_callback_function
 			(boost::bind(&InteractiveGameBase::calculate_buildcaps, this, _1));
 
-	// Connect buildhelp button to reflect build help state. Needs to be
-	// done here rather than in the constructor as the map is not present then.
-	// This code assumes that the InteractivePlayer object lives longer than
-	// the overlay_manager. Otherwise remove the hook in the deconstructor.
-	egbase().map().overlay_manager().onBuildHelpToggle =
-		boost::bind(&UI::Button::set_perm_pressed, &m_toggle_buildhelp, _1);
-	m_toggle_buildhelp.set_perm_pressed(buildhelp());
 
 	// Recalc whole map for changed owner stuff
 	map.recalc_whole_map(egbase().world());
@@ -158,6 +153,9 @@
 	hide_minimap();
 }
 
+void InteractiveGameBase::on_buildhelp_changed(const bool value) {
+	m_toggle_buildhelp.set_perm_pressed(value);
+}
 
 /**
  * See if we can reasonably open a ship window at the current selection position.

=== modified file 'src/wui/interactive_gamebase.h'
--- src/wui/interactive_gamebase.h	2015-03-26 06:47:36 +0000
+++ src/wui/interactive_gamebase.h	2015-03-29 18:13:50 +0000
@@ -101,6 +101,9 @@
 	UI::UniqueWindow::Registry m_game_summary;
 
 	UI::Button m_toggle_buildhelp;
+
+private:
+	void on_buildhelp_changed(const bool value) override;
 };
 
 #endif  // end of include guard: WL_WUI_INTERACTIVE_GAMEBASE_H

=== modified file 'src/wui/interactive_player.cc'
--- src/wui/interactive_player.cc	2015-02-14 22:11:44 +0000
+++ src/wui/interactive_player.cc	2015-03-29 18:13:50 +0000
@@ -54,7 +54,6 @@
 #include "wui/game_objectives_menu.h"
 #include "wui/game_options_menu.h"
 #include "wui/general_statistics_menu.h"
-#include "wui/overlay_manager.h"
 #include "wui/stock_menu.h"
 #include "wui/ware_statistics_menu.h"
 
@@ -397,22 +396,11 @@
 		return;
 	}
 
-	DebugConsole::write
-		(str
-			(boost::format("Switching from #%1% to #%2%.")
-		 	 % static_cast<int>(m_player_number) % n));
+	DebugConsole::write(
+	   str(boost::format("Switching from #%1% to #%2%.") % static_cast<int>(m_player_number) % n));
 	m_player_number = n;
-	Map              &       map             = egbase().map();
-	OverlayManager  &       overlay_manager = map.overlay_manager();
-	Widelands::Extent  const extent          = map.extent         ();
-	for (uint16_t y = 0; y < extent.h; ++y)
-		for (uint16_t x = 0; x < extent.w; ++x)
-			overlay_manager.recalc_field_overlays
-				(map.get_fcoords(Widelands::Coords(x, y)));
-	if
-		(UI::UniqueWindow * const building_statistics_window =
-		 	m_mainm_windows.building_stats.window)
-		dynamic_cast<BuildingStatisticsMenu&>
-			(*building_statistics_window)
-			.update();
+
+	if (UI::UniqueWindow* const building_statistics_window = m_mainm_windows.building_stats.window) {
+		dynamic_cast<BuildingStatisticsMenu&>(*building_statistics_window).update();
+	}
 }

=== modified file 'src/wui/mapview.cc'
--- src/wui/mapview.cc	2015-02-20 20:04:28 +0000
+++ src/wui/mapview.cc	2015-03-29 18:13:50 +0000
@@ -29,7 +29,6 @@
 #include "wui/interactive_base.h"
 #include "wui/interactive_player.h"
 #include "wui/mapviewpixelfunctions.h"
-#include "wui/overlay_manager.h"
 
 MapView::MapView(
    UI::Panel* parent, int32_t x, int32_t y, uint32_t w, uint32_t h, InteractiveBase& player)
@@ -86,8 +85,6 @@
 			return;
 	}
 
-	egbase.map().overlay_manager().load_graphics();
-
 	if (upcast(InteractivePlayer const, interactive_player, &intbase())) {
 		m_renderer->rendermap(dst, egbase, m_viewpoint, interactive_player->player());
 	} else {


Follow ups