From b0d21d2fadc9e7df11a2758e3e5cc411af2b0452 Mon Sep 17 00:00:00 2001 From: michi_cc Date: Sun, 1 Jul 2012 23:12:50 +0000 Subject: (svn r24367) -Feature: [NewGRF] Customisable signals for rail types. --- src/newgrf_railtype.cpp | 32 ++++++++++++++++++++--- src/newgrf_railtype.h | 1 + src/rail.h | 3 +++ src/rail_cmd.cpp | 69 ++++++++++++++++++++++++++++--------------------- src/rail_gui.cpp | 19 +++++--------- src/rail_map.h | 10 ------- src/signal_type.h | 10 +++++++ 7 files changed, 89 insertions(+), 55 deletions(-) diff --git a/src/newgrf_railtype.cpp b/src/newgrf_railtype.cpp index d4f6dcd4c..5f4c3d921 100644 --- a/src/newgrf_railtype.cpp +++ b/src/newgrf_railtype.cpp @@ -77,7 +77,7 @@ static const SpriteGroup *RailTypeResolveReal(const ResolverObject *object, cons return NULL; } -static inline void NewRailTypeResolver(ResolverObject *res, TileIndex tile, TileContext context, const GRFFile *grffile) +static inline void NewRailTypeResolver(ResolverObject *res, TileIndex tile, TileContext context, const GRFFile *grffile, uint32 param1 = 0, uint32 param2 = 0) { res->GetRandomBits = &RailTypeGetRandomBits; res->GetTriggers = &RailTypeGetTriggers; @@ -89,8 +89,8 @@ static inline void NewRailTypeResolver(ResolverObject *res, TileIndex tile, Tile res->u.routes.context = context; res->callback = CBID_NO_CALLBACK; - res->callback_param1 = 0; - res->callback_param2 = 0; + res->callback_param1 = param1; + res->callback_param2 = param2; res->ResetState(); res->grffile = grffile; @@ -121,6 +121,32 @@ SpriteID GetCustomRailSprite(const RailtypeInfo *rti, TileIndex tile, RailTypeSp return group->GetResult(); } +/** + * Get the sprite to draw for a given signal. + * @param rti The rail type data (spec). + * @param tile The tile to get the sprite for. + * @param type Signal type. + * @param var Signal variant. + * @param state Signal state. + * @param gui Is the sprite being used on the map or in the GUI? + * @return The sprite to draw. + */ +SpriteID GetCustomSignalSprite(const RailtypeInfo *rti, TileIndex tile, SignalType type, SignalVariant var, SignalState state, bool gui) +{ + if (rti->group[RTSG_SIGNALS] == NULL) return 0; + + ResolverObject object; + + uint32 param1 = gui ? 0x10 : 0x00; + uint32 param2 = (type << 16) | (var << 8) | state; + NewRailTypeResolver(&object, tile, TCX_NORMAL, rti->grffile[RTSG_SIGNALS], param1, param2); + + const SpriteGroup *group = SpriteGroup::Resolve(rti->group[RTSG_SIGNALS], &object); + if (group == NULL || group->GetNumResults() == 0) return 0; + + return group->GetResult(); +} + /** * Perform a reverse railtype lookup to get the GRF internal ID. * @param railtype The global (OpenTTD) railtype. diff --git a/src/newgrf_railtype.h b/src/newgrf_railtype.h index 0c57f7e49..5b3baf0f3 100644 --- a/src/newgrf_railtype.h +++ b/src/newgrf_railtype.h @@ -16,6 +16,7 @@ #include "newgrf_commons.h" SpriteID GetCustomRailSprite(const RailtypeInfo *rti, TileIndex tile, RailTypeSpriteGroup rtsg, TileContext context = TCX_NORMAL); +SpriteID GetCustomSignalSprite(const RailtypeInfo *rti, TileIndex tile, SignalType type, SignalVariant var, SignalState state, bool gui = false); uint8 GetReverseRailTypeTranslation(RailType railtype, const GRFFile *grffile); diff --git a/src/rail.h b/src/rail.h index eb0b46c4c..0a6a15381 100644 --- a/src/rail.h +++ b/src/rail.h @@ -20,6 +20,7 @@ #include "slope_type.h" #include "strings_type.h" #include "date_type.h" +#include "signal_type.h" /** Railtype flags. */ enum RailTypeFlags { @@ -47,6 +48,7 @@ enum RailTypeSpriteGroup { RTSG_DEPOT, ///< Depot images RTSG_FENCES, ///< Fence images RTSG_TUNNEL_PORTAL, ///< Tunnel portal overlay + RTSG_SIGNALS, ///< Signal images RTSG_END, }; @@ -136,6 +138,7 @@ struct RailtypeInfo { SpriteID build_depot; ///< button for building depots SpriteID build_tunnel; ///< button for building a tunnel SpriteID convert_rail; ///< button for converting rail + SpriteID signals[SIGTYPE_END][2][2]; ///< signal GUI sprites (type, variant, state) } gui_sprites; struct { diff --git a/src/rail_cmd.cpp b/src/rail_cmd.cpp index 12be60f35..ffa42de82 100644 --- a/src/rail_cmd.cpp +++ b/src/rail_cmd.cpp @@ -44,6 +44,18 @@ RailtypeInfo _railtypes[RAILTYPE_END]; assert_compile(sizeof(_original_railtypes) <= sizeof(_railtypes)); +/** Enum holding the signal offset in the sprite sheet according to the side it is representing. */ +enum SignalOffsets { + SIGNAL_TO_SOUTHWEST, + SIGNAL_TO_NORTHEAST, + SIGNAL_TO_SOUTHEAST, + SIGNAL_TO_NORTHWEST, + SIGNAL_TO_EAST, + SIGNAL_TO_WEST, + SIGNAL_TO_SOUTH, + SIGNAL_TO_NORTH, +}; + /** * Reset all rail type information to its default values. */ @@ -74,6 +86,24 @@ void ResolveRailTypeGUISprites(RailtypeInfo *rti) rti->cursor.tunnel = cursors_base + 14; rti->cursor.convert = cursors_base + 15; } + + /* Array of default GUI signal sprite numbers. */ + const SpriteID _signal_lookup[2][SIGTYPE_END] = { + {SPR_IMG_SIGNAL_ELECTRIC_NORM, SPR_IMG_SIGNAL_ELECTRIC_ENTRY, SPR_IMG_SIGNAL_ELECTRIC_EXIT, + SPR_IMG_SIGNAL_ELECTRIC_COMBO, SPR_IMG_SIGNAL_ELECTRIC_PBS, SPR_IMG_SIGNAL_ELECTRIC_PBS_OWAY}, + + {SPR_IMG_SIGNAL_SEMAPHORE_NORM, SPR_IMG_SIGNAL_SEMAPHORE_ENTRY, SPR_IMG_SIGNAL_SEMAPHORE_EXIT, + SPR_IMG_SIGNAL_SEMAPHORE_COMBO, SPR_IMG_SIGNAL_SEMAPHORE_PBS, SPR_IMG_SIGNAL_SEMAPHORE_PBS_OWAY}, + }; + + for (SignalType type = SIGTYPE_NORMAL; type < SIGTYPE_END; type = (SignalType)(type + 1)) { + for (SignalVariant var = SIG_ELECTRIC; var <= SIG_SEMAPHORE; var = (SignalVariant)(var + 1)) { + SpriteID red = GetCustomSignalSprite(rti, INVALID_TILE, type, var, SIGNAL_STATE_RED, true); + SpriteID green = GetCustomSignalSprite(rti, INVALID_TILE, type, var, SIGNAL_STATE_GREEN, true); + rti->gui_sprites.signals[type][var][0] = (red != 0) ? red + SIGNAL_TO_SOUTH : _signal_lookup[var][type]; + rti->gui_sprites.signals[type][var][1] = (green != 0) ? green + SIGNAL_TO_SOUTH : _signal_lookup[var][type] + 1; + } + } } /** @@ -1798,7 +1828,7 @@ static uint GetSaveSlopeZ(uint x, uint y, Track track) return GetSlopePixelZ(x, y); } -static void DrawSingleSignal(TileIndex tile, Track track, byte condition, uint image, uint pos) +static void DrawSingleSignal(TileIndex tile, const RailtypeInfo *rti, Track track, SignalState condition, SignalOffsets image, uint pos) { bool side; switch (_settings_game.construction.train_signal_side) { @@ -1823,17 +1853,16 @@ static void DrawSingleSignal(TileIndex tile, Track track, byte condition, uint i uint x = TileX(tile) * TILE_SIZE + SignalPositions[side][pos].x; uint y = TileY(tile) * TILE_SIZE + SignalPositions[side][pos].y; - SpriteID sprite; - SignalType type = GetSignalType(tile, track); SignalVariant variant = GetSignalVariant(tile, track); - if (type == SIGTYPE_NORMAL && variant == SIG_ELECTRIC) { - /* Normal electric signals are picked from original sprites. */ - sprite = SPR_ORIGINAL_SIGNALS_BASE + image + condition; + SpriteID sprite = GetCustomSignalSprite(rti, tile, type, variant, condition); + if (sprite != 0) { + sprite += image; } else { - /* All other signals are picked from add on sprites. */ - sprite = SPR_SIGNALS_BASE + (type - 1) * 16 + variant * 64 + image + condition + (type > SIGTYPE_LAST_NOPBS ? 64 : 0); + /* Normal electric signals are stored in a different sprite block than all other signals. */ + sprite = (type == SIGTYPE_NORMAL && variant == SIG_ELECTRIC) ? SPR_ORIGINAL_SIGNALS_BASE : SPR_SIGNALS_BASE - 16; + sprite += type * 16 + variant * 64 + image * 2 + condition + (type > SIGTYPE_LAST_NOPBS ? 64 : 0); } AddSortableSpriteToDraw(sprite, PAL_NONE, x, y, 1, 1, BB_HEIGHT_UNDER_BRIDGE, GetSaveSlopeZ(x, y, track)); @@ -2277,27 +2306,9 @@ static void DrawTrackBits(TileInfo *ti, TrackBits track) } } -/** - * Enums holding the offsets from base signal sprite, - * according to the side it is representing. - * The addtion of 2 per enum is necessary in order to "jump" over the - * green state sprite, all signal sprites being in pair, - * starting with the off-red state - */ -enum SignalOffsets { - SIGNAL_TO_SOUTHWEST = 0, - SIGNAL_TO_NORTHEAST = 2, - SIGNAL_TO_SOUTHEAST = 4, - SIGNAL_TO_NORTHWEST = 6, - SIGNAL_TO_EAST = 8, - SIGNAL_TO_WEST = 10, - SIGNAL_TO_SOUTH = 12, - SIGNAL_TO_NORTH = 14, -}; - -static void DrawSignals(TileIndex tile, TrackBits rails) +static void DrawSignals(TileIndex tile, TrackBits rails, const RailtypeInfo *rti) { -#define MAYBE_DRAW_SIGNAL(x, y, z, t) if (IsSignalPresent(tile, x)) DrawSingleSignal(tile, t, GetSingleSignalState(tile, x), y, z) +#define MAYBE_DRAW_SIGNAL(x, y, z, t) if (IsSignalPresent(tile, x)) DrawSingleSignal(tile, rti, t, GetSingleSignalState(tile, x), y, z) if (!(rails & TRACK_BIT_Y)) { if (!(rails & TRACK_BIT_X)) { @@ -2342,7 +2353,7 @@ static void DrawTile_Track(TileInfo *ti) if (HasCatenaryDrawn(GetRailType(ti->tile))) DrawCatenary(ti); - if (HasSignals(ti->tile)) DrawSignals(ti->tile, rails); + if (HasSignals(ti->tile)) DrawSignals(ti->tile, rails, rti); } else { /* draw depot */ const DrawTileSprites *dts; diff --git a/src/rail_gui.cpp b/src/rail_gui.cpp index 4ce0d1785..d038af4df 100644 --- a/src/rail_gui.cpp +++ b/src/rail_gui.cpp @@ -1445,16 +1445,13 @@ struct BuildSignalWindow : public PickerWindowBase { private: /** * Draw dynamic a signal-sprite in a button in the signal GUI - * Draw the sprite +1px to the right and down if the button is lowered and change the sprite to sprite + 1 (red to green light) + * Draw the sprite +1px to the right and down if the button is lowered * * @param widget_index index of this widget in the window * @param image the sprite to draw */ void DrawSignalSprite(byte widget_index, SpriteID image) const { - /* First get the right image, which is one later for 'green' signals. */ - image += this->IsWidgetLowered(widget_index); - /* Next get the actual sprite so we can calculate the right offsets. */ const Sprite *sprite = GetSprite(image, ST_NORMAL); @@ -1501,16 +1498,12 @@ public: virtual void DrawWidget(const Rect &r, int widget) const { if (IsInsideMM(widget, WID_BS_SEMAPHORE_NORM, WID_BS_ELECTRIC_PBS_OWAY + 1)) { - /* We need to do some custom sprite widget drawing for the signals. */ - const SpriteID _signal_lookup[] = { - SPR_IMG_SIGNAL_SEMAPHORE_NORM, SPR_IMG_SIGNAL_SEMAPHORE_ENTRY, SPR_IMG_SIGNAL_SEMAPHORE_EXIT, - SPR_IMG_SIGNAL_SEMAPHORE_COMBO, SPR_IMG_SIGNAL_SEMAPHORE_PBS, SPR_IMG_SIGNAL_SEMAPHORE_PBS_OWAY, - - SPR_IMG_SIGNAL_ELECTRIC_NORM, SPR_IMG_SIGNAL_ELECTRIC_ENTRY, SPR_IMG_SIGNAL_ELECTRIC_EXIT, - SPR_IMG_SIGNAL_ELECTRIC_COMBO, SPR_IMG_SIGNAL_ELECTRIC_PBS, SPR_IMG_SIGNAL_ELECTRIC_PBS_OWAY - }; + /* Extract signal from widget number. */ + int type = (widget - WID_BS_SEMAPHORE_NORM) % SIGTYPE_END; + int var = SIG_SEMAPHORE - (widget - WID_BS_SEMAPHORE_NORM) / SIGTYPE_END; // SignalVariant order is reversed compared to the widgets. + SpriteID sprite = GetRailTypeInfo(_cur_railtype)->gui_sprites.signals[type][var][this->IsWidgetLowered(widget)]; - this->DrawSignalSprite(widget, _signal_lookup[widget - WID_BS_SEMAPHORE_NORM]); + this->DrawSignalSprite(widget, sprite); } } diff --git a/src/rail_map.h b/src/rail_map.h index bdd4dadfd..c8033a311 100644 --- a/src/rail_map.h +++ b/src/rail_map.h @@ -345,16 +345,6 @@ static inline void SetSignalVariant(TileIndex t, Track track, SignalVariant v) if (track == INVALID_TRACK) SB(_m[t].m2, 7, 1, v); } -/** - * These are states in which a signal can be. Currently these are only two, so - * simple boolean logic will do. But do try to compare to this enum instead of - * normal boolean evaluation, since that will make future additions easier. - */ -enum SignalState { - SIGNAL_STATE_RED = 0, ///< The signal is red - SIGNAL_STATE_GREEN = 1, ///< The signal is green -}; - /** * Set the states of the signals (Along/AgainstTrackDir) * @param tile the tile to set the states for diff --git a/src/signal_type.h b/src/signal_type.h index ec1630db1..c7d06072a 100644 --- a/src/signal_type.h +++ b/src/signal_type.h @@ -38,4 +38,14 @@ enum SignalType { template <> struct EnumPropsT : MakeEnumPropsT {}; +/** + * These are states in which a signal can be. Currently these are only two, so + * simple boolean logic will do. But do try to compare to this enum instead of + * normal boolean evaluation, since that will make future additions easier. + */ +enum SignalState { + SIGNAL_STATE_RED = 0, ///< The signal is red + SIGNAL_STATE_GREEN = 1, ///< The signal is green +}; + #endif /* SIGNAL_TYPE_H */ -- cgit v1.2.3-70-g09d2