diff --git a/descriptor/reader/roadsign_reader.cc b/descriptor/reader/roadsign_reader.cc index ed4883f1..a2819571 100644 --- a/descriptor/reader/roadsign_reader.cc +++ b/descriptor/reader/roadsign_reader.cc @@ -43,8 +43,19 @@ obj_desc_t * roadsign_reader_t::read_node(FILE *fp, obj_node_info_t &node) const uint16 v = decode_uint16(p); const int version = v & 0x8000 ? v & 0x7FFF : 0; - if(version==4) { - // Versioned node, version 3 + if(version==5) { + // Versioned node, version 5 + desc->min_speed = kmh_to_speed(decode_uint16(p)); + desc->price = decode_uint32(p); + desc->flags = decode_uint8(p); + desc->offset_left = decode_sint8(p); + desc->wtyp = decode_uint8(p); + desc->use_frontImage = decode_uint8(p); + desc->intro_date = decode_uint16(p); + desc->retire_date = decode_uint16(p); + } + else if(version==4) { + // Versioned node, version 4 desc->min_speed = kmh_to_speed(decode_uint16(p)); desc->price = decode_uint32(p); desc->flags = decode_uint8(p); @@ -87,6 +98,10 @@ obj_desc_t * roadsign_reader_t::read_node(FILE *fp, obj_node_info_t &node) dbg->fatal("roadsign_reader_t::read_node()","version 0 not supported. File corrupt?"); } + if( version<=4 ) { + desc->use_frontImage = false; + } + 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; diff --git a/descriptor/roadsign_desc.h b/descriptor/roadsign_desc.h index 0bf32f8f..6a3d57f4 100644 --- a/descriptor/roadsign_desc.h +++ b/descriptor/roadsign_desc.h @@ -40,6 +40,8 @@ private: uint16 min_speed; // 0 = no min speed + bool use_frontImage; + public: enum types { NONE = 0, @@ -53,15 +55,22 @@ public: END_OF_CHOOSE_AREA = 1U << 7 }; - image_id get_image_id(ribi_t::dir dir) const + image_id get_image_id(ribi_t::dir dir, bool front = false) const { - image_t const* const image = get_child(2)->get_image(dir); + image_t const* image; + if( !front ) { + image = get_child(2)->get_image(dir); + } else if( use_frontImage ) { + image = get_child(3)->get_image(dir); + } else { + image = NULL; + } return image != NULL ? image->get_id() : IMG_EMPTY; } uint16 get_count() const { return get_child(2)->get_count(); } - skin_desc_t const* get_cursor() const { return get_child(3); } + skin_desc_t const* get_cursor() const { return get_child(use_frontImage?4:3); } uint16 get_min_speed() const { return min_speed; } @@ -94,6 +103,8 @@ public: sint8 get_offset_left() const { return offset_left; } + bool does_use_frontImage() const { return use_frontImage; } + void calc_checksum(checksum_t *chk) const { obj_desc_transport_infrastructure_t::calc_checksum(chk); diff --git a/descriptor/writer/roadsign_writer.cc b/descriptor/writer/roadsign_writer.cc index b46069a3..a40055f4 100644 --- a/descriptor/writer/roadsign_writer.cc +++ b/descriptor/writer/roadsign_writer.cc @@ -12,7 +12,7 @@ using std::string; void roadsign_writer_t::write_obj(FILE* fp, obj_node_t& parent, tabfileobj_t& obj) { - obj_node_t node(this, 15, &parent); + obj_node_t node(this, 16, &parent); uint32 const price = obj.get_int("cost", 500) * 100; uint16 const min_speed = obj.get_int("min_speed", 0); @@ -28,27 +28,34 @@ void roadsign_writer_t::write_obj(FILE* fp, obj_node_t& parent, tabfileobj_t& ob (obj.get_int("is_longblocksignal", 0) > 0 ? roadsign_desc_t::SIGN_LONGBLOCK_SIGNAL : roadsign_desc_t::NONE) | (obj.get_int("end_of_choose", 0) > 0 ? roadsign_desc_t::END_OF_CHOOSE_AREA : roadsign_desc_t::NONE); + string str = obj.get("frontimage[0]"); + uint8 use_frontImage; + if(str.empty() && (flags&roadsign_desc_t::ONLY_BACKIMAGE)==0) { + use_frontImage = 0; + } else { + use_frontImage = 1; + } // Hajo: write version data - node.write_uint16(fp, 0x8004, 0); // version 4 - node.write_uint16(fp, min_speed, 2); - node.write_uint32(fp, price, 4); - node.write_uint8 (fp, flags, 8); - node.write_uint8 (fp, offset_left, 9); - node.write_uint8 (fp, wtyp, 10); + node.write_uint16(fp, 0x8005, 0); // version 5 + node.write_uint16(fp, min_speed, 2); + node.write_uint32(fp, price, 4); + node.write_uint8 (fp, flags, 8); + node.write_uint8 (fp, offset_left, 9); + node.write_uint8 (fp, wtyp, 10); + node.write_uint8 (fp, use_frontImage,11); uint16 intro_date = obj.get_int("intro_year", DEFAULT_INTRO_DATE) * 12; intro_date += obj.get_int("intro_month", 1) - 1; - node.write_uint16(fp, intro_date, 11); + node.write_uint16(fp, intro_date, 12); uint16 retire_date = obj.get_int("retire_year", DEFAULT_RETIRE_DATE) * 12; retire_date += obj.get_int("retire_month", 1) - 1; - node.write_uint16(fp, retire_date, 13); + node.write_uint16(fp, retire_date, 14); write_head(fp, node, obj); // add the images - slist_tpl keys; - string str; + slist_tpl keys, front_keys; for (int i = 0; i < 24; i++) { char buf[40]; @@ -57,11 +64,26 @@ void roadsign_writer_t::write_obj(FILE* fp, obj_node_t& parent, tabfileobj_t& ob str = obj.get(buf); // make sure, there are always 4, 8, 12, ... images (for all directions) if (str.empty() && i % 4 == 0) { - break; + sprintf(buf, "frontimage[%i]", i); + str = obj.get(buf); + if(str.empty()) { + break; + } + sprintf(buf, "image[%i]", i); + str = obj.get(buf); } keys.append(str); + + if( use_frontImage ) { + sprintf(buf, "frontimage[%i]", i); + str = obj.get(buf); + front_keys.append(str); + } } imagelist_writer_t::instance()->write_obj(fp, node, keys); + if( use_frontImage ) { + imagelist_writer_t::instance()->write_obj(fp, node, front_keys); + } // probably add some icons, if defined slist_tpl cursorkeys; diff --git a/obj/roadsign.cc b/obj/roadsign.cc index 3dcdcdd1..037638c5 100644 --- a/obj/roadsign.cc +++ b/obj/roadsign.cc @@ -223,6 +223,8 @@ void roadsign_t::calc_image() after_xoffset = 0; after_yoffset = 0; sint8 xoff = 0, yoff = 0; + image2 = IMG_EMPTY; + foreground_image2 = IMG_EMPTY; // left offsets defined, and image-on-the-left activated const bool left_offsets = desc->get_offset_left() && ( (desc->get_wtyp()==road_wt && welt->get_settings().is_drive_left() ) @@ -241,6 +243,7 @@ void roadsign_t::calc_image() image += 2; } set_image( desc->get_image_id(image) ); + foreground_image = desc->get_image_id(image,true); set_yoff( 0 ); if( hang_diff ) { set_yoff( -(TILE_HEIGHT_STEP*hang_diff)/2 ); @@ -248,7 +251,6 @@ void roadsign_t::calc_image() else { set_yoff( -gr->get_weg_yoff() ); } - foreground_image = IMG_EMPTY; return; } @@ -295,37 +297,43 @@ void roadsign_t::calc_image() if(temp_dir&ribi_t::east) { tmp_image = desc->get_image_id(3); + foreground_image = desc->get_image_id(3,true); xoff += XOFF; yoff += -YOFF; } if(temp_dir&ribi_t::north) { if(tmp_image!=IMG_EMPTY) { - foreground_image = desc->get_image_id(0); + image2 = desc->does_use_frontImage() ? desc->get_image_id(0) : IMG_EMPTY; + foreground_image2 = desc->does_use_frontImage() ? desc->get_image_id(0,true) : desc->get_image_id(0); after_xoffset += -XOFF; after_yoffset += -YOFF; } else { tmp_image = desc->get_image_id(0); + foreground_image = desc->get_image_id(0,true); xoff += -XOFF; yoff += -YOFF; } } if(temp_dir&ribi_t::west) { - foreground_image = desc->get_image_id(2); + image2 = desc->does_use_frontImage() ? desc->get_image_id(2) : IMG_EMPTY; + foreground_image2 = desc->does_use_frontImage() ? desc->get_image_id(2,true) : desc->get_image_id(2); after_xoffset += -XOFF; after_yoffset += YOFF; } if(temp_dir&ribi_t::south) { - if(foreground_image!=IMG_EMPTY) { + if(foreground_image2!=IMG_EMPTY) { tmp_image = desc->get_image_id(1); + foreground_image = desc->get_image_id(1,true); xoff += XOFF; yoff += YOFF; } else { - foreground_image = desc->get_image_id(1); + image2 = desc->does_use_frontImage() ? desc->get_image_id(1) : IMG_EMPTY; + foreground_image2 = desc->does_use_frontImage() ? desc->get_image_id(1,true) : desc->get_image_id(1); after_xoffset += XOFF; after_yoffset += YOFF; } @@ -334,38 +342,48 @@ void roadsign_t::calc_image() else { if(temp_dir&ribi_t::east) { - foreground_image = desc->get_image_id(3); + image2 = desc->does_use_frontImage() ? desc->get_image_id(3) : IMG_EMPTY; + foreground_image2 = desc->does_use_frontImage() ? desc->get_image_id(3,true) : desc->get_image_id(3); } if(temp_dir&ribi_t::north) { - if(foreground_image!=IMG_EMPTY) { + if(foreground_image2!=IMG_EMPTY) { tmp_image = desc->get_image_id(0); + foreground_image = desc->get_image_id(0,true); } else { - foreground_image = desc->get_image_id(0); + image2 = desc->does_use_frontImage() ? desc->get_image_id(0) : IMG_EMPTY; + foreground_image2 = desc->does_use_frontImage() ? desc->get_image_id(0,true) : desc->get_image_id(0); } } if(temp_dir&ribi_t::west) { tmp_image = desc->get_image_id(2); + foreground_image = desc->get_image_id(2,true); } if(temp_dir&ribi_t::south) { if(tmp_image!=IMG_EMPTY) { - foreground_image = desc->get_image_id(1); + image2 = desc->does_use_frontImage() ? desc->get_image_id(1) : IMG_EMPTY; + foreground_image2 = desc->does_use_frontImage() ? desc->get_image_id(1,true) : desc->get_image_id(1); } else { tmp_image = desc->get_image_id(1); + foreground_image = desc->get_image_id(1,true); } } } // some signs on roads must not have a background (but then they have only two rotations) if( desc->get_flags()&roadsign_desc_t::ONLY_BACKIMAGE ) { - if(foreground_image!=IMG_EMPTY) { - tmp_image = foreground_image; + if(desc->does_use_frontImage()) { + if(foreground_image2!=IMG_EMPTY) { + tmp_image = foreground_image2; + } + foreground_image2 = IMG_EMPTY; + } else { + // do nothing. } - foreground_image = IMG_EMPTY; } } else { @@ -382,18 +400,21 @@ void roadsign_t::calc_image() if(weg_dir&ribi_t::north) { if(weg_dir&ribi_t::east) { - foreground_image = desc->get_image_id(6+direction*8); + image2 = desc->does_use_frontImage() ? desc->get_image_id(6+direction*8) : IMG_EMPTY; + foreground_image2 = desc->does_use_frontImage() ? desc->get_image_id(6+direction*8,true) : desc->get_image_id(6+direction*8); after_xoffset += 0; after_yoffset += 0; } else { - foreground_image = desc->get_image_id(1+direction*8); + image2 = desc->does_use_frontImage() ? desc->get_image_id(1+direction*8) : IMG_EMPTY; + foreground_image2 = desc->does_use_frontImage() ? desc->get_image_id(1+direction*8,true) : desc->get_image_id(1+direction*8); after_xoffset += XOFF; after_yoffset += YOFF; } } else if(weg_dir&ribi_t::east) { - foreground_image = desc->get_image_id(2+direction*8); + image2 = desc->does_use_frontImage() ? desc->get_image_id(2+direction*8) : IMG_EMPTY; + foreground_image2 = desc->does_use_frontImage() ? desc->get_image_id(2+direction*8,true) : desc->get_image_id(2+direction*8); after_xoffset += -XOFF; after_yoffset += YOFF; } @@ -401,17 +422,20 @@ void roadsign_t::calc_image() if(weg_dir&ribi_t::west) { if(weg_dir&ribi_t::south) { tmp_image = desc->get_image_id(7+direction*8); + foreground_image = desc->get_image_id(7+direction*8,true); xoff += 0; yoff += 0; } else { tmp_image = desc->get_image_id(3+direction*8); + foreground_image = desc->get_image_id(3+direction*8,true); xoff += XOFF; yoff += -YOFF; } } else if(weg_dir&ribi_t::south) { tmp_image = desc->get_image_id(0+direction*8); + foreground_image = desc->get_image_id(0+direction*8,true); xoff += -XOFF; yoff += -YOFF; } @@ -420,26 +444,32 @@ void roadsign_t::calc_image() // drive right ... if(weg_dir&ribi_t::south) { if(weg_dir&ribi_t::east) { - foreground_image = desc->get_image_id(4+direction*8); + image2 = desc->does_use_frontImage() ? desc->get_image_id(4+direction*8) : IMG_EMPTY; + foreground_image2 = desc->does_use_frontImage() ? desc->get_image_id(4+direction*8,true) : desc->get_image_id(4+direction*8); } else { - foreground_image = desc->get_image_id(0+direction*8); + image2 = desc->does_use_frontImage() ? desc->get_image_id(0+direction*8) : IMG_EMPTY; + foreground_image2 = desc->does_use_frontImage() ? desc->get_image_id(0+direction*8,true) : desc->get_image_id(0+direction*8); } } else if(weg_dir&ribi_t::east) { - foreground_image = desc->get_image_id(2+direction*8); + image2 = desc->does_use_frontImage() ? desc->get_image_id(2+direction*8) : IMG_EMPTY; + foreground_image2 = desc->does_use_frontImage() ? desc->get_image_id(2+direction*8,true) : desc->get_image_id(2+direction*8); } if(weg_dir&ribi_t::west) { if(weg_dir&ribi_t::north) { tmp_image = desc->get_image_id(5+direction*8); + foreground_image = desc->get_image_id(5+direction*8,true); } else { tmp_image = desc->get_image_id(3+direction*8); + foreground_image = desc->get_image_id(3+direction*8,true); } } else if(weg_dir&ribi_t::north) { tmp_image = desc->get_image_id(1+direction*8); + foreground_image = desc->get_image_id(1+direction*8,true); } } @@ -499,6 +529,33 @@ void roadsign_t::rotate90() dir = ribi_t::rotate90( dir ); } +void roadsign_t::display(int xpos, int ypos CLIP_NUM_DEF) const +{ + if( image!=IMG_EMPTY || image2!=IMG_EMPTY ) { + const int raster_width = get_current_tile_raster_width(); + + const int x1 = xpos + tile_raster_scale_x(get_xoff(), raster_width); + const int y1 = ypos + tile_raster_scale_y(get_yoff(), raster_width); + const int x2 = xpos + tile_raster_scale_x(after_xoffset, raster_width); + const int y2 = ypos + tile_raster_scale_y(after_yoffset, raster_width); + + if( get_player_nr() != PLAYER_UNOWNED ) { + if( obj_t::show_owner ) { + display_blend( image, x1, y1, 0, color_idx_to_rgb(get_owner()->get_player_color1()+2) | OUTLINE_FLAG | TRANSPARENT75_FLAG, 0, dirty CLIP_NUM_PAR); + display_blend( image2, x2, y2, 0, color_idx_to_rgb(get_owner()->get_player_color1()+2) | OUTLINE_FLAG | TRANSPARENT75_FLAG, 0, dirty CLIP_NUM_PAR); + } + else { + display_color( image, x1, y1, get_player_nr(), true, get_flag(obj_t::dirty) CLIP_NUM_PAR); + display_color( image2, x2, y2, get_player_nr(), true, get_flag(obj_t::dirty) CLIP_NUM_PAR); + } + } + else { + display_normal( image, x1, y1, 0, true, get_flag(obj_t::dirty) CLIP_NUM_PAR); + display_normal( image2, x2, y2, 0, true, get_flag(obj_t::dirty) CLIP_NUM_PAR); + } + } +} + // to correct offset on slopes #ifdef MULTI_THREAD @@ -507,21 +564,26 @@ void roadsign_t::display_after(int xpos, int ypos, const sint8 clip_num ) const void roadsign_t::display_after(int xpos, int ypos, bool ) const #endif { - if( foreground_image != IMG_EMPTY ) { + if( foreground_image != IMG_EMPTY || foreground_image2 != IMG_EMPTY ) { const int raster_width = get_current_tile_raster_width(); - xpos += tile_raster_scale_x( after_xoffset, raster_width ); - ypos += tile_raster_scale_y( after_yoffset, raster_width ); + const int x1 = xpos + tile_raster_scale_x(get_xoff(), raster_width); + const int y1 = ypos + tile_raster_scale_y(get_yoff(), raster_width); + const int x2 = xpos + tile_raster_scale_x(after_xoffset, raster_width); + const int y2 = ypos + tile_raster_scale_y(after_yoffset, raster_width); // draw with owner if( get_player_nr() != PLAYER_UNOWNED ) { if( obj_t::show_owner ) { - display_blend( foreground_image, xpos, ypos, 0, color_idx_to_rgb(get_owner()->get_player_color1()+2) | OUTLINE_FLAG | TRANSPARENT75_FLAG, 0, dirty CLIP_NUM_PAR); + display_blend( foreground_image, x1, y1, 0, color_idx_to_rgb(get_owner()->get_player_color1()+2) | OUTLINE_FLAG | TRANSPARENT75_FLAG, 0, dirty CLIP_NUM_PAR); + display_blend( foreground_image2, x2, y2, 0, color_idx_to_rgb(get_owner()->get_player_color1()+2) | OUTLINE_FLAG | TRANSPARENT75_FLAG, 0, dirty CLIP_NUM_PAR); } else { - display_color( foreground_image, xpos, ypos, get_player_nr(), true, get_flag(obj_t::dirty) CLIP_NUM_PAR); + display_color( foreground_image, x1, y1, get_player_nr(), true, get_flag(obj_t::dirty) CLIP_NUM_PAR); + display_color( foreground_image2, x2, y2, get_player_nr(), true, get_flag(obj_t::dirty) CLIP_NUM_PAR); } } else { - display_normal( foreground_image, xpos, ypos, 0, true, get_flag(obj_t::dirty) CLIP_NUM_PAR); + display_normal( foreground_image, x1, y1, 0, true, get_flag(obj_t::dirty) CLIP_NUM_PAR); + display_normal( foreground_image2, x2, y2, 0, true, get_flag(obj_t::dirty) CLIP_NUM_PAR); } } } diff --git a/obj/roadsign.h b/obj/roadsign.h index 951f28a4..4389a17b 100644 --- a/obj/roadsign.h +++ b/obj/roadsign.h @@ -25,7 +25,9 @@ class roadsign_t : public obj_t, public sync_steppable { protected: image_id image; + image_id image2; image_id foreground_image; + image_id foreground_image2; enum { SHOW_FONT=1, SHOW_BACK=2, SWITCH_AUTOMATIC=16 }; @@ -122,6 +124,11 @@ public: image_id get_front_image() const { return foreground_image; } /** + * Draw background image of object + */ + void display(int xpos, int ypos CLIP_NUM_DEF) const; + + /** * draw the part overlapping the vehicles * (needed to get the right offset even on hills) * @author V. Meyer diff --git a/obj/signal.cc b/obj/signal.cc index ff06e67c..e9338c2d 100644 --- a/obj/signal.cc +++ b/obj/signal.cc @@ -50,6 +50,8 @@ void signal_t::calc_image() { foreground_image = IMG_EMPTY; image_id image = IMG_EMPTY; + image2 = IMG_EMPTY; + foreground_image2 = IMG_EMPTY; after_xoffset = 0; after_yoffset = 0; @@ -112,37 +114,43 @@ void signal_t::calc_image() if(temp_dir&ribi_t::east) { image = desc->get_image_id(3+state*4+offset); + foreground_image = desc->get_image_id(3+state*4+offset,true); xoff += XOFF; yoff += -YOFF; } if(temp_dir&ribi_t::north) { if(image!=IMG_EMPTY) { - foreground_image = desc->get_image_id(0+state*4+offset); + image2 = desc->does_use_frontImage() ? desc->get_image_id(0+state*4+offset) : IMG_EMPTY; + foreground_image2 = desc->does_use_frontImage() ? desc->get_image_id(0+state*4+offset,true) : desc->get_image_id(0+state*4+offset); after_xoffset += -XOFF; after_yoffset += -YOFF; } else { image = desc->get_image_id(0+state*4+offset); + foreground_image = desc->get_image_id(0+state*4+offset,true); xoff += -XOFF; yoff += -YOFF; } } if(temp_dir&ribi_t::west) { - foreground_image = desc->get_image_id(2+state*4+offset); + image2 = desc->does_use_frontImage() ? desc->get_image_id(2+state*4+offset) : IMG_EMPTY; + foreground_image2 = desc->does_use_frontImage() ? desc->get_image_id(2+state*4+offset,true) : desc->get_image_id(2+state*4+offset); after_xoffset += -XOFF; after_yoffset += YOFF; } if(temp_dir&ribi_t::south) { - if(foreground_image!=IMG_EMPTY) { + if(foreground_image2!=IMG_EMPTY) { image = desc->get_image_id(1+state*4+offset); + foreground_image = desc->get_image_id(1+state*4+offset,true); xoff += XOFF; yoff += YOFF; } else { - foreground_image = desc->get_image_id(1+state*4+offset); + image2 = desc->does_use_frontImage() ? desc->get_image_id(1+state*4+offset) : IMG_EMPTY; + foreground_image2 = desc->does_use_frontImage() ? desc->get_image_id(1+state*4+offset,true) : desc->get_image_id(1+state*4+offset); after_xoffset += XOFF; after_yoffset += YOFF; } @@ -150,28 +158,34 @@ void signal_t::calc_image() } else { if(temp_dir&ribi_t::east) { - foreground_image = desc->get_image_id(3+state*4+offset); + image2 = desc->does_use_frontImage() ? desc->get_image_id(3+state*4+offset) : IMG_EMPTY; + foreground_image2 = desc->does_use_frontImage() ? desc->get_image_id(3+state*4+offset,true) : desc->get_image_id(3+state*4+offset); } if(temp_dir&ribi_t::north) { - if(foreground_image==IMG_EMPTY) { - foreground_image = desc->get_image_id(0+state*4+offset); + if(foreground_image2==IMG_EMPTY) { + image2 = desc->does_use_frontImage() ? desc->get_image_id(0+state*4+offset) : IMG_EMPTY; + foreground_image2 = desc->does_use_frontImage() ? desc->get_image_id(0+state*4+offset,true) : desc->get_image_id(0+state*4+offset); } else { image = desc->get_image_id(0+state*4+offset); + foreground_image = desc->get_image_id(0+state*4+offset,true); } } if(temp_dir&ribi_t::west) { image = desc->get_image_id(2+state*4+offset); + foreground_image = desc->get_image_id(2+state*4+offset,true); } if(temp_dir&ribi_t::south) { if(image==IMG_EMPTY) { image = desc->get_image_id(1+state*4+offset); + foreground_image = desc->get_image_id(1+state*4+offset,true); } else { - foreground_image = desc->get_image_id(1+state*4+offset); + image2 = desc->does_use_frontImage() ? desc->get_image_id(1+state*4+offset) : IMG_EMPTY; + foreground_image2 = desc->does_use_frontImage() ? desc->get_image_id(1+state*4+offset,true) : desc->get_image_id(1+state*4+offset); } } } diff --git a/simobj.h b/simobj.h index c237f8d0..514f0131 100644 --- a/simobj.h +++ b/simobj.h @@ -320,7 +320,7 @@ public: * Draw background image of object * (everything that could be potentially behind vehicles) */ - void display(int xpos, int ypos CLIP_NUM_DEF) const; + virtual void display(int xpos, int ypos CLIP_NUM_DEF) const; /** * Draw foreground image