From 898e879bd90e34505cd7083acecf341fd798d02c Mon Sep 17 00:00:00 2001 From: peter1138 Date: Sun, 7 Feb 2010 22:22:54 +0000 Subject: (svn r19056) -Add: [NewGRF] Action 3/2/1 (i.e. new graphics) support for rail types. (To be documented...) --- src/rail_cmd.cpp | 256 ++++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 236 insertions(+), 20 deletions(-) (limited to 'src/rail_cmd.cpp') diff --git a/src/rail_cmd.cpp b/src/rail_cmd.cpp index c9e2c3916..7de13a03a 100644 --- a/src/rail_cmd.cpp +++ b/src/rail_cmd.cpp @@ -19,6 +19,8 @@ #include "pathfinder/yapf/yapf_cache.h" #include "newgrf_engine.h" #include "landscape_type.h" +#include "newgrf_railtype.h" +#include "newgrf_commons.h" #include "train.h" #include "variables.h" #include "autoslope.h" @@ -52,6 +54,37 @@ void ResetRailTypes() memcpy(_railtypes, _original_railtypes, sizeof(_original_railtypes)); } +void ResolveRailTypeGUISprites(RailtypeInfo *rti) +{ + SpriteID cursors_base = GetCustomRailSprite(rti, INVALID_TILE, RTSG_CURSORS); + if (cursors_base != 0) { + rti->gui_sprites.build_ns_rail = cursors_base + 0; + rti->gui_sprites.build_x_rail = cursors_base + 1; + rti->gui_sprites.build_ew_rail = cursors_base + 2; + rti->gui_sprites.build_y_rail = cursors_base + 3; + rti->gui_sprites.auto_rail = cursors_base + 4; + rti->gui_sprites.build_depot = cursors_base + 5; + rti->gui_sprites.build_tunnel = cursors_base + 6; + rti->gui_sprites.convert_rail = cursors_base + 7; + rti->cursor.rail_ns = cursors_base + 8; + rti->cursor.rail_swne = cursors_base + 9; + rti->cursor.rail_ew = cursors_base + 10; + rti->cursor.rail_nwse = cursors_base + 11; + rti->cursor.autorail = cursors_base + 12; + rti->cursor.depot = cursors_base + 13; + rti->cursor.tunnel = cursors_base + 14; + rti->cursor.convert = cursors_base + 15; + } +} + +void InitRailTypes() +{ + for (RailType rt = RAILTYPE_BEGIN; rt != RAILTYPE_END; rt++) { + RailtypeInfo *rti = &_railtypes[rt]; + ResolveRailTypeGUISprites(rti); + } +} + RailType AllocateRailType(RailTypeLabel label) { for (RailType rt = RAILTYPE_BEGIN; rt != RAILTYPE_END; rt++) { @@ -1709,10 +1742,11 @@ static void DrawTrackFence_WE_2(const TileInfo *ti, SpriteID base_image) } -static void DrawTrackDetails(const TileInfo *ti) +static void DrawTrackDetails(const TileInfo *ti, const RailtypeInfo *rti) { /* Base sprite for track fences. */ - SpriteID base_image = SPR_TRACK_FENCE_FLAT_X; + SpriteID base_image = GetCustomRailSprite(rti, ti->tile, RTSG_FENCES); + if (base_image == 0) base_image = SPR_TRACK_FENCE_FLAT_X; switch (GetRailGroundType(ti->tile)) { case RAIL_GROUND_FENCE_NW: DrawTrackFence_NW(ti, base_image); break; @@ -1747,6 +1781,162 @@ static void DrawTrackDetails(const TileInfo *ti) } } +/* SubSprite for drawing the track halftile of 'three-corners-raised'-sloped rail sprites. */ +static const int INF = 1000; // big number compared to tilesprite size +static const SubSprite _halftile_sub_sprite[4] = { + { -INF , -INF , 32 - 33, INF }, // CORNER_W, clip 33 pixels from right + { -INF , 0 + 7, INF , INF }, // CORNER_S, clip 7 pixels from top + { -31 + 33, -INF , INF , INF }, // CORNER_E, clip 33 pixels from left + { -INF , -INF , INF , 30 - 23 } // CORNER_N, clip 23 pixels from bottom +}; + +static inline void DrawTrackSprite(SpriteID sprite, PaletteID pal, const TileInfo *ti, Slope s) +{ + DrawGroundSprite(sprite, pal, NULL, 0, (ti->tileh & s) ? -8 : 0); +} + +static void DrawTrackBitsOverlay(TileInfo *ti, TrackBits track, const RailtypeInfo *rti) +{ + RailGroundType rgt = GetRailGroundType(ti->tile); + Foundation f = GetRailFoundation(ti->tileh, track); + Corner halftile_corner = CORNER_INVALID; + + if (IsNonContinuousFoundation(f)) { + /* Save halftile corner */ + halftile_corner = (f == FOUNDATION_STEEP_BOTH ? GetHighestSlopeCorner(ti->tileh) : GetHalftileFoundationCorner(f)); + /* Draw lower part first */ + track &= ~CornerToTrackBits(halftile_corner); + f = (f == FOUNDATION_STEEP_BOTH ? FOUNDATION_STEEP_LOWER : FOUNDATION_NONE); + } + + DrawFoundation(ti, f); + /* DrawFoundation modifies ti */ + + /* Draw ground */ + if (track == TRACK_BIT_NONE && rgt == RAIL_GROUND_WATER) { + if (IsSteepSlope(ti->tileh)) { + DrawShoreTile(ti->tileh); + } else { + DrawGroundSprite(SPR_FLAT_WATER_TILE, PAL_NONE); + } + } else { + SpriteID image; + + switch (rgt) { + case RAIL_GROUND_BARREN: image = SPR_FLAT_BARE_LAND; break; + case RAIL_GROUND_ICE_DESERT: image = SPR_FLAT_SNOW_DESERT_TILE; break; + default: image = SPR_FLAT_GRASS_TILE; break; + } + + image += _tileh_to_sprite[ti->tileh]; + + DrawGroundSprite(image, PAL_NONE); + } + + SpriteID overlay = GetCustomRailSprite(rti, ti->tile, RTSG_OVERLAY); + SpriteID ground = GetCustomRailSprite(rti, ti->tile, RTSG_GROUND); + TrackBits pbs = _settings_client.gui.show_track_reservation ? GetRailReservationTrackBits(ti->tile) : TRACK_BIT_NONE; + + if (track == TRACK_BIT_NONE) { + /* Half-tile foundation, no track here? */ + } else if (ti->tileh == SLOPE_NW && track == TRACK_BIT_Y) { + DrawGroundSprite(ground + RTO_SLOPE_NW, PAL_NONE); + if (pbs != TRACK_BIT_NONE) DrawGroundSprite(overlay + 9, PALETTE_CRASH); + } else if (ti->tileh == SLOPE_NE && track == TRACK_BIT_X) { + DrawGroundSprite(ground + RTO_SLOPE_NE, PAL_NONE); + if (pbs != TRACK_BIT_NONE) DrawGroundSprite(overlay + 6, PALETTE_CRASH); + } else if (ti->tileh == SLOPE_SE && track == TRACK_BIT_Y) { + DrawGroundSprite(ground + RTO_SLOPE_SE, PAL_NONE); + if (pbs != TRACK_BIT_NONE) DrawGroundSprite(overlay + 7, PALETTE_CRASH); + } else if (ti->tileh == SLOPE_SW && track == TRACK_BIT_X) { + DrawGroundSprite(ground + RTO_SLOPE_SW, PAL_NONE); + if (pbs != TRACK_BIT_NONE) DrawGroundSprite(overlay + 8, PALETTE_CRASH); + } else { + switch (track) { + /* Draw single ground sprite when not overlapping. No track overlay + * is necessary for these sprites. */ + case TRACK_BIT_X: DrawGroundSprite(ground + RTO_X, PAL_NONE); break; + case TRACK_BIT_Y: DrawGroundSprite(ground + RTO_Y, PAL_NONE); break; + case TRACK_BIT_UPPER: DrawTrackSprite(ground + RTO_N, PAL_NONE, ti, SLOPE_N); break; + case TRACK_BIT_LOWER: DrawTrackSprite(ground + RTO_S, PAL_NONE, ti, SLOPE_S); break; + case TRACK_BIT_RIGHT: DrawTrackSprite(ground + RTO_E, PAL_NONE, ti, SLOPE_E); break; + case TRACK_BIT_LEFT: DrawTrackSprite(ground + RTO_W, PAL_NONE, ti, SLOPE_W); break; + case TRACK_BIT_CROSS: DrawGroundSprite(ground + RTO_CROSSING_XY, PAL_NONE); break; + case TRACK_BIT_HORZ: DrawTrackSprite(ground + RTO_N, PAL_NONE, ti, SLOPE_N); + DrawTrackSprite(ground + RTO_S, PAL_NONE, ti, SLOPE_S); break; + case TRACK_BIT_VERT: DrawTrackSprite(ground + RTO_E, PAL_NONE, ti, SLOPE_E); + DrawTrackSprite(ground + RTO_W, PAL_NONE, ti, SLOPE_W); break; + + default: + /* We're drawing a junction tile */ + if ((track & TRACK_BIT_3WAY_NE) == 0) { + DrawGroundSprite(ground + RTO_JUNCTION_SW, PAL_NONE); + } else if ((track & TRACK_BIT_3WAY_SW) == 0) { + DrawGroundSprite(ground + RTO_JUNCTION_NE, PAL_NONE); + } else if ((track & TRACK_BIT_3WAY_NW) == 0) { + DrawGroundSprite(ground + RTO_JUNCTION_SE, PAL_NONE); + } else if ((track & TRACK_BIT_3WAY_SE) == 0) { + DrawGroundSprite(ground + RTO_JUNCTION_NW, PAL_NONE); + } else { + DrawGroundSprite(ground + RTO_JUNCTION_NSEW, PAL_NONE); + } + + /* Mask out PBS bits as we shall draw them afterwards anyway. */ + track &= ~pbs; + + /* Draw regular track bits */ + if (track & TRACK_BIT_X) DrawGroundSprite(overlay + RTO_X, PAL_NONE); + if (track & TRACK_BIT_Y) DrawGroundSprite(overlay + RTO_Y, PAL_NONE); + if (track & TRACK_BIT_UPPER) DrawGroundSprite(overlay + RTO_N, PAL_NONE); + if (track & TRACK_BIT_LOWER) DrawGroundSprite(overlay + RTO_S, PAL_NONE); + if (track & TRACK_BIT_RIGHT) DrawGroundSprite(overlay + RTO_E, PAL_NONE); + if (track & TRACK_BIT_LEFT) DrawGroundSprite(overlay + RTO_W, PAL_NONE); + } + + /* Draw reserved track bits */ + if (pbs & TRACK_BIT_X) DrawGroundSprite(overlay + RTO_X, PALETTE_CRASH); + if (pbs & TRACK_BIT_Y) DrawGroundSprite(overlay + RTO_Y, PALETTE_CRASH); + if (pbs & TRACK_BIT_UPPER) DrawTrackSprite(overlay + RTO_N, PALETTE_CRASH, ti, SLOPE_N); + if (pbs & TRACK_BIT_LOWER) DrawTrackSprite(overlay + RTO_S, PALETTE_CRASH, ti, SLOPE_S); + if (pbs & TRACK_BIT_RIGHT) DrawTrackSprite(overlay + RTO_E, PALETTE_CRASH, ti, SLOPE_E); + if (pbs & TRACK_BIT_LEFT) DrawTrackSprite(overlay + RTO_W, PALETTE_CRASH, ti, SLOPE_W); + } + + if (IsValidCorner(halftile_corner)) { + DrawFoundation(ti, HalftileFoundation(halftile_corner)); + + /* Draw higher halftile-overlay: Use the sloped sprites with three corners raised. They probably best fit the lightning. */ + Slope fake_slope = SlopeWithThreeCornersRaised(OppositeCorner(halftile_corner)); + + SpriteID image; + switch (rgt) { + case RAIL_GROUND_BARREN: image = SPR_FLAT_BARE_LAND; break; + case RAIL_GROUND_ICE_DESERT: + case RAIL_GROUND_HALF_SNOW: image = SPR_FLAT_SNOW_DESERT_TILE; break; + default: image = SPR_FLAT_GRASS_TILE; break; + } + + image += _tileh_to_sprite[fake_slope]; + + DrawGroundSprite(image, PAL_NONE, &(_halftile_sub_sprite[halftile_corner])); + + track = CornerToTrackBits(halftile_corner); + + int offset; + switch (track) { + default: NOT_REACHED(); + case TRACK_BIT_UPPER: offset = RTO_N; break; + case TRACK_BIT_LOWER: offset = RTO_S; break; + case TRACK_BIT_RIGHT: offset = RTO_E; break; + case TRACK_BIT_LEFT: offset = RTO_W; break; + } + + DrawTrackSprite(ground + offset, PAL_NONE, ti, fake_slope); + if (HasReservedTracks(ti->tile, track)) { + DrawTrackSprite(overlay + offset, PALETTE_CRASH, ti, fake_slope); + } + } +} /** * Draw ground sprite and track bits @@ -1755,16 +1945,13 @@ static void DrawTrackDetails(const TileInfo *ti) */ static void DrawTrackBits(TileInfo *ti, TrackBits track) { - /* SubSprite for drawing the track halftile of 'three-corners-raised'-sloped rail sprites. */ - static const int INF = 1000; // big number compared to tilesprite size - static const SubSprite _halftile_sub_sprite[4] = { - { -INF , -INF , 32 - 33, INF }, // CORNER_W, clip 33 pixels from right - { -INF , 0 + 7, INF , INF }, // CORNER_S, clip 7 pixels from top - { -31 + 33, -INF , INF , INF }, // CORNER_E, clip 33 pixels from left - { -INF , -INF , INF , 30 - 23 } // CORNER_N, clip 23 pixels from bottom - }; - const RailtypeInfo *rti = GetRailTypeInfo(GetRailType(ti->tile)); + + if (rti->UsesOverlay()) { + DrawTrackBitsOverlay(ti, track, rti); + return; + } + RailGroundType rgt = GetRailGroundType(ti->tile); Foundation f = GetRailFoundation(ti->tileh, track); Corner halftile_corner = CORNER_INVALID; @@ -1960,7 +2147,7 @@ static void DrawTile_Track(TileInfo *ti) DrawTrackBits(ti, rails); - if (HasBit(_display_opt, DO_FULL_DETAIL)) DrawTrackDetails(ti); + if (HasBit(_display_opt, DO_FULL_DETAIL)) DrawTrackDetails(ti, rti); if (HasCatenaryDrawn(GetRailType(ti->tile))) DrawCatenary(ti); @@ -1969,6 +2156,7 @@ static void DrawTile_Track(TileInfo *ti) /* draw depot */ const DrawTileSprites *dts; PaletteID pal = PAL_NONE; + SpriteID relocation; if (ti->tileh != SLOPE_FLAT) DrawFoundation(ti, FOUNDATION_LEVELED); @@ -1979,8 +2167,12 @@ static void DrawTile_Track(TileInfo *ti) dts = &_depot_gfx_table[GetRailDepotDirection(ti->tile)]; } - image = dts->ground.sprite; - if (image != SPR_FLAT_GRASS_TILE) image += rti->total_offset; + if (rti->UsesOverlay()) { + image = SPR_FLAT_GRASS_TILE; + } else { + image = dts->ground.sprite; + if (image != SPR_FLAT_GRASS_TILE) image += rti->total_offset; + } /* adjust ground tile for desert * don't adjust for snow, because snow in depots looks weird */ @@ -1994,19 +2186,43 @@ static void DrawTile_Track(TileInfo *ti) DrawGroundSprite(image, GroundSpritePaletteTransform(image, pal, _drawtile_track_palette)); - /* PBS debugging, draw reserved tracks darker */ - if (_game_mode != GM_MENU && _settings_client.gui.show_track_reservation && HasDepotReservation(ti->tile)) { + if (rti->UsesOverlay()) { + SpriteID ground = GetCustomRailSprite(rti, ti->tile, RTSG_GROUND); + switch (GetRailDepotDirection(ti->tile)) { - case DIAGDIR_SW: DrawGroundSprite(rti->base_sprites.single_x, PALETTE_CRASH); break; - case DIAGDIR_SE: DrawGroundSprite(rti->base_sprites.single_y, PALETTE_CRASH); break; + case DIAGDIR_SW: DrawGroundSprite(ground + RTO_X, PAL_NONE); break; + case DIAGDIR_SE: DrawGroundSprite(ground + RTO_Y, PAL_NONE); break; default: break; } + + if (_settings_client.gui.show_track_reservation && HasDepotReservation(ti->tile)) { + SpriteID overlay = GetCustomRailSprite(rti, ti->tile, RTSG_OVERLAY); + + switch (GetRailDepotDirection(ti->tile)) { + case DIAGDIR_SW: DrawGroundSprite(overlay + RTO_X, PALETTE_CRASH); break; + case DIAGDIR_SE: DrawGroundSprite(overlay + RTO_Y, PALETTE_CRASH); break; + default: break; + } + } + + relocation = GetCustomRailSprite(rti, ti->tile, RTSG_DEPOT); + relocation -= SPR_RAIL_DEPOT_SE_1; + } else { + /* PBS debugging, draw reserved tracks darker */ + if (_game_mode != GM_MENU && _settings_client.gui.show_track_reservation && HasDepotReservation(ti->tile)) { + switch (GetRailDepotDirection(ti->tile)) { + case DIAGDIR_SW: DrawGroundSprite(rti->base_sprites.single_y, PALETTE_CRASH); break; + case DIAGDIR_SE: DrawGroundSprite(rti->base_sprites.single_x, PALETTE_CRASH); break; + default: break; + } + } + + relocation = rti->total_offset; } if (HasCatenaryDrawn(GetRailType(ti->tile))) DrawCatenary(ti); - /* No NewGRF depots, so no relocation */ - DrawRailTileSeq(ti, dts, TO_BUILDINGS, rti->total_offset, 0, _drawtile_track_palette); + DrawRailTileSeq(ti, dts, TO_BUILDINGS, relocation, 0, _drawtile_track_palette); } DrawBridgeMiddle(ti); } -- cgit v1.2.3-54-g00ecf