Index: src/simutrans/descriptor/reader/roadsign_reader.cc
===================================================================
--- src/simutrans/descriptor/reader/roadsign_reader.cc	(revisión: 12130)
+++ src/simutrans/descriptor/reader/roadsign_reader.cc	(copia de trabajo)
@@ -107,6 +107,10 @@
 		dbg->fatal( "roadsign_reader_t::read_node()", "Cannot handle too new node version %i", version );
 	}
 
+	// the diagonal images are an additional node behind the cursor,
+	// so a fifth child means they are there
+	desc->has_diagonal = node.nchildren > 4;
+
 	if(  version<=3  &&  (  desc->is_choose_sign() ||  desc->is_private_way()  )  &&  desc->get_waytype() == road_wt  ) {
 		// do not shift these signs to the left for compatibility
 		desc->offset_left = 0;
Index: src/simutrans/descriptor/roadsign_desc.h
===================================================================
--- src/simutrans/descriptor/roadsign_desc.h	(revisión: 12130)
+++ src/simutrans/descriptor/roadsign_desc.h	(copia de trabajo)
@@ -22,6 +22,8 @@
  *  0   Name
  *  1   Copyright
  *  2   Image list
+ *  3   Cursor and icon
+ *  4   Diagonal image list (optional)
  */
 class roadsign_desc_t : public obj_desc_transport_infrastructure_t {
 	friend class roadsign_reader_t;
@@ -33,6 +35,10 @@
 
 	uint16 min_speed; // 0 = no min speed
 
+	// set from the number of children when loading, so it is not part of the
+	// node data and does not change the checksum of signs already published
+	bool has_diagonal = false;
+
 public:
 	enum types {
 		NONE                  = 0,
@@ -53,6 +59,29 @@
 		return image != NULL ? image->get_id() : IMG_EMPTY;
 	}
 
+	// asks for the straight image, whatever the way below looks like
+	static const uint16 NO_DIAGONAL = 0xFFFF;
+
+	// two entries per normal one: a direction needs a different image in each of the
+	// two bends it can appear in, and the bend of the way picks between them
+	image_id get_image_id(ribi_t::dir dir, uint16 diagonal) const
+	{
+		if(  diagonal == NO_DIAGONAL  ||  !has_diagonal  ) {
+			return get_image_id(dir);
+		}
+		image_t const* const image = get_child<image_list_t>(4)->get_image(diagonal);
+		if(  image == NULL  ||  image->get_id() == IMG_EMPTY  ) {
+			// falling back keeps the sign visible, and keeps its front/back order
+			// and its offsets exactly as they are without diagonals
+			return get_image_id(dir);
+		}
+		return image->get_id();
+	}
+
+	bool has_diagonal_image() const { return has_diagonal; }
+
+	// only the normal list: this count decides whether a sign is a traffic light
+	// and whether it has electrified images, so the diagonals must stay out of it
 	uint16 get_count() const { return get_child<image_list_t>(2)->get_count(); }
 
 	skin_desc_t const* get_cursor() const { return get_child<skin_desc_t>(3); }
Index: src/simutrans/descriptor/writer/roadsign_writer.cc
===================================================================
--- src/simutrans/descriptor/writer/roadsign_writer.cc	(revisión: 12130)
+++ src/simutrans/descriptor/writer/roadsign_writer.cc	(copia de trabajo)
@@ -59,17 +59,17 @@
 }
 
 
-// parse "image[number]" syntax
-void parse_images_numbered(slist_tpl<std::string>& keys, tabfileobj_t& obj)
+// parse "<name>[number]" syntax
+void parse_images_numbered(slist_tpl<std::string>& keys, tabfileobj_t& obj, const char* name)
 {
 	for (int i = 0; i < 32; i++) {
 		char buf[40];
-		sprintf(buf, "image[%i]", i);
+		sprintf(buf, "%s[%i]", name, i);
 		const char *str = obj.get(buf);
 		// make sure, there are always 4, 8, 12, ... images (for all directions)
 		if(  !*str  ) {
 			if(  i % 4  ) {
-				dbg->fatal("roadsign_writer", "image count is %d but must be multiple of 4!", i);
+				dbg->fatal("roadsign_writer", "%s count is %d but must be multiple of 4!", name, i);
 			}
 			break;
 		}
@@ -135,11 +135,12 @@
 
 	// add the images
 	slist_tpl<std::string> keys;
+	slist_tpl<std::string> diagonal_keys;
 
 	if(  *obj.get("image[0]")  ) {
 		// image[0] is defined.
 		// assume that images are defined in image[number] syntax.
-		parse_images_numbered(keys, obj);
+		parse_images_numbered(keys, obj, "image");
 	}
 	else {
 		// image[0] is not defined.
@@ -146,6 +147,13 @@
 		// assume that images are defined in image[direction][state] syntax.
 		parse_images_2d(keys, obj, flags);
 	}
+	// the diagonal entries are places and not directions, two for each direction, so the
+	// [direction][state] syntax cannot name them and they are always numbered
+	parse_images_numbered(diagonal_keys, obj, "diagonal");
+	// any other length would silently shift the images instead of failing here
+	if(  !diagonal_keys.empty()  &&  diagonal_keys.get_count()!=2*keys.get_count()  ) {
+		dbg->fatal("roadsign_writer", "%i diagonal images given, but the sign needs %i!", diagonal_keys.get_count(), 2*keys.get_count());
+	}
 	imagelist_writer_t::instance()->write_obj(fp, node, keys);
 
 	// probably add some icons, if defined
@@ -154,9 +162,16 @@
 	const char *c = obj.get("cursor"), *i=obj.get("icon");
 	cursorkeys.append(c);
 	cursorkeys.append(i);
-	if (*c || *i) {
+	if (*c || *i || !diagonal_keys.empty()) {
+		// when diagonals follow, this node has to be written even if it is empty:
+		// the diagonal list is found by its position, and would take this one otherwise
 		cursorskin_writer_t::instance()->write_obj(fp, node, obj, cursorkeys);
 	}
 
+	// last child, so that older versions of Simutrans just ignore it
+	if(  !diagonal_keys.empty()  ) {
+		imagelist_writer_t::instance()->write_obj(fp, node, diagonal_keys);
+	}
+
 	node.check_and_write_header(fp);
 }
Index: src/simutrans/obj/roadsign.cc
===================================================================
--- src/simutrans/obj/roadsign.cc	(revisión: 12130)
+++ src/simutrans/obj/roadsign.cc	(copia de trabajo)
@@ -236,6 +236,21 @@
 }
 
 
+void roadsign_t::calc_diagonal_index(uint16 idx[4], ribi_t::ribi way_ribi, uint16 base)
+{
+	// the image list is ordered north, south, west, east
+	static const ribi_t::ribi order[4] = { ribi_t::north, ribi_t::south, ribi_t::west, ribi_t::east };
+	assert(ribi_t::is_bend(way_ribi));
+	// the lower ribi of the bend takes the first of its two images, and the bends are
+	// numbered with ribi/3-1, the same way the ways number their diagonals
+	const ribi_t::ribi low = way_ribi & (~way_ribi + 1);
+	const uint16 bend = base + 2*(way_ribi/3 - 1);
+	for(  uint8 i = 0;  i < 4;  i++  ) {
+		idx[i] = (way_ribi & order[i]) ? bend + (order[i]==low ? 0 : 1) : roadsign_desc_t::NO_DIAGONAL;
+	}
+}
+
+
 // could be still better aligned for drive_left settings ...
 void roadsign_t::calc_image()
 {
@@ -247,6 +262,14 @@
 		return;
 	}
 
+	// signs on a bend use the diagonal images. The bend comes from the unmasked ribi:
+	// a one way sign masks a direction away, and a single direction is not a bend
+	uint16 diag[4] = { roadsign_desc_t::NO_DIAGONAL, roadsign_desc_t::NO_DIAGONAL, roadsign_desc_t::NO_DIAGONAL, roadsign_desc_t::NO_DIAGONAL };
+	const weg_t *w = gr->get_weg(desc->get_wtyp()!=tram_wt ? desc->get_wtyp() : track_wt);
+	if(  w != NULL  &&  w->is_diagonal()  &&  desc->has_diagonal_image()  ) {
+		calc_diagonal_index( diag, w->get_ribi_unmasked(), 0 );
+	}
+
 	after_xoffset = 0;
 	after_yoffset = 0;
 	sint8 xoff = 0, yoff = 0;
@@ -321,7 +344,7 @@
 			const sint16 YOFF = desc->get_offset_left();
 
 			if(temp_dir&ribi_t::east) {
-				tmp_image = desc->get_image_id(3);
+				tmp_image = desc->get_image_id(3, diag[3]);
 				xoff += XOFF;
 				yoff += -YOFF;
 			}
@@ -328,12 +351,12 @@
 
 			if(temp_dir&ribi_t::north) {
 				if(tmp_image!=IMG_EMPTY) {
-					foreground_image = desc->get_image_id(0);
+					foreground_image = desc->get_image_id(0, diag[0]);
 					after_xoffset += -XOFF;
 					after_yoffset += -YOFF;
 				}
 				else {
-					tmp_image = desc->get_image_id(0);
+					tmp_image = desc->get_image_id(0, diag[0]);
 					xoff += -XOFF;
 					yoff += -YOFF;
 				}
@@ -340,7 +363,7 @@
 			}
 
 			if(temp_dir&ribi_t::west) {
-				foreground_image = desc->get_image_id(2);
+				foreground_image = desc->get_image_id(2, diag[2]);
 				after_xoffset += -XOFF;
 				after_yoffset += YOFF;
 			}
@@ -347,12 +370,12 @@
 
 			if(temp_dir&ribi_t::south) {
 				if(foreground_image!=IMG_EMPTY) {
-					tmp_image = desc->get_image_id(1);
+					tmp_image = desc->get_image_id(1, diag[1]);
 					xoff += XOFF;
 					yoff += YOFF;
 				}
 				else {
-					foreground_image = desc->get_image_id(1);
+					foreground_image = desc->get_image_id(1, diag[1]);
 					after_xoffset += XOFF;
 					after_yoffset += YOFF;
 				}
@@ -361,28 +384,28 @@
 		else {
 
 			if(temp_dir&ribi_t::east) {
-				foreground_image = desc->get_image_id(3);
+				foreground_image = desc->get_image_id(3, diag[3]);
 			}
 
 			if(temp_dir&ribi_t::north) {
 				if(foreground_image!=IMG_EMPTY) {
-					tmp_image = desc->get_image_id(0);
+					tmp_image = desc->get_image_id(0, diag[0]);
 				}
 				else {
-					foreground_image = desc->get_image_id(0);
+					foreground_image = desc->get_image_id(0, diag[0]);
 				}
 			}
 
 			if(temp_dir&ribi_t::west) {
-				tmp_image = desc->get_image_id(2);
+				tmp_image = desc->get_image_id(2, diag[2]);
 			}
 
 			if(temp_dir&ribi_t::south) {
 				if(tmp_image!=IMG_EMPTY) {
-					foreground_image = desc->get_image_id(1);
+					foreground_image = desc->get_image_id(1, diag[1]);
 				}
 				else {
-					tmp_image = desc->get_image_id(1);
+					tmp_image = desc->get_image_id(1, diag[1]);
 				}
 			}
 		}
Index: src/simutrans/obj/roadsign.h
===================================================================
--- src/simutrans/obj/roadsign.h	(revisión: 12130)
+++ src/simutrans/obj/roadsign.h	(copia de trabajo)
@@ -39,6 +39,10 @@
 	uint8 automatic:1;
 	uint8 preview:1;
 
+	// diagonal image of each direction, ordered as the image list has them: north, south,
+	// west, east. base is where the row of this state and electrification starts
+	static void calc_diagonal_index(uint16 idx[4], ribi_t::ribi way_ribi, uint16 base);
+
 	/*
 	 * Many things go in these...
 	 *   Traffic lights -> intended usage
Index: src/simutrans/obj/signal.cc
===================================================================
--- src/simutrans/obj/signal.cc	(revisión: 12130)
+++ src/simutrans/obj/signal.cc	(copia de trabajo)
@@ -47,6 +47,7 @@
 {
 	foreground_image = IMG_EMPTY;
 	image_id image = IMG_EMPTY;
+	uint16 diag[4] = { roadsign_desc_t::NO_DIAGONAL, roadsign_desc_t::NO_DIAGONAL, roadsign_desc_t::NO_DIAGONAL, roadsign_desc_t::NO_DIAGONAL };
 
 	after_xoffset = 0;
 	after_yoffset = 0;
@@ -70,6 +71,12 @@
 				offset = (desc->is_pre_signal()  ||  desc->is_priority_signal()) ? 12 : 8;
 			}
 
+			// the bend comes from the unmasked ribi: a one way signal masks a direction away,
+			// and a single direction is not a bend. The diagonal rows are twice as long
+			if(  sch->is_diagonal()  &&  desc->has_diagonal_image()  ) {
+				calc_diagonal_index( diag, sch->get_ribi_unmasked(), state*8 + offset*2 );
+			}
+
 			// vertical offset of the signal positions
 			if(full_hang==slope_t::flat) {
 				yoff = -gr->get_weg_yoff();
@@ -108,7 +115,7 @@
 				const sint16 YOFF = desc->get_offset_left();
 
 				if(temp_dir&ribi_t::east) {
-					image = desc->get_image_id(3+state*4+offset);
+					image = desc->get_image_id(3+state*4+offset, diag[3]);
 					xoff += XOFF;
 					yoff += -YOFF;
 				}
@@ -115,12 +122,12 @@
 
 				if(temp_dir&ribi_t::north) {
 					if(image!=IMG_EMPTY) {
-						foreground_image = desc->get_image_id(0+state*4+offset);
+						foreground_image = desc->get_image_id(0+state*4+offset, diag[0]);
 						after_xoffset += -XOFF;
 						after_yoffset += -YOFF;
 					}
 					else {
-						image = desc->get_image_id(0+state*4+offset);
+						image = desc->get_image_id(0+state*4+offset, diag[0]);
 						xoff += -XOFF;
 						yoff += -YOFF;
 					}
@@ -127,7 +134,7 @@
 				}
 
 				if(temp_dir&ribi_t::west) {
-					foreground_image = desc->get_image_id(2+state*4+offset);
+					foreground_image = desc->get_image_id(2+state*4+offset, diag[2]);
 					after_xoffset += -XOFF;
 					after_yoffset += YOFF;
 				}
@@ -134,12 +141,12 @@
 
 				if(temp_dir&ribi_t::south) {
 					if(foreground_image!=IMG_EMPTY) {
-						image = desc->get_image_id(1+state*4+offset);
+						image = desc->get_image_id(1+state*4+offset, diag[1]);
 						xoff += XOFF;
 						yoff += YOFF;
 					}
 					else {
-						foreground_image = desc->get_image_id(1+state*4+offset);
+						foreground_image = desc->get_image_id(1+state*4+offset, diag[1]);
 						after_xoffset += XOFF;
 						after_yoffset += YOFF;
 					}
@@ -147,28 +154,28 @@
 			}
 			else {
 				if(temp_dir&ribi_t::east) {
-					foreground_image = desc->get_image_id(3+state*4+offset);
+					foreground_image = desc->get_image_id(3+state*4+offset, diag[3]);
 				}
 
 				if(temp_dir&ribi_t::north) {
 					if(foreground_image==IMG_EMPTY) {
-						foreground_image = desc->get_image_id(0+state*4+offset);
+						foreground_image = desc->get_image_id(0+state*4+offset, diag[0]);
 					}
 					else {
-						image = desc->get_image_id(0+state*4+offset);
+						image = desc->get_image_id(0+state*4+offset, diag[0]);
 					}
 				}
 
 				if(temp_dir&ribi_t::west) {
-					image = desc->get_image_id(2+state*4+offset);
+					image = desc->get_image_id(2+state*4+offset, diag[2]);
 				}
 
 				if(temp_dir&ribi_t::south) {
 					if(image==IMG_EMPTY) {
-						image = desc->get_image_id(1+state*4+offset);
+						image = desc->get_image_id(1+state*4+offset, diag[1]);
 					}
 					else {
-						foreground_image = desc->get_image_id(1+state*4+offset);
+						foreground_image = desc->get_image_id(1+state*4+offset, diag[1]);
 					}
 				}
 			}
