mirror of https://github.com/OpenTTD/OpenTTD.git
(svn r24367) -Feature: [NewGRF] Customisable signals for rail types.
This commit is contained in:
parent
a6244ed0dc
commit
b0d21d2fad
|
@ -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.
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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,
|
||||
/* 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)];
|
||||
|
||||
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
|
||||
};
|
||||
|
||||
this->DrawSignalSprite(widget, _signal_lookup[widget - WID_BS_SEMAPHORE_NORM]);
|
||||
this->DrawSignalSprite(widget, sprite);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -38,4 +38,14 @@ enum SignalType {
|
|||
template <> struct EnumPropsT<SignalType> : MakeEnumPropsT<SignalType, byte, SIGTYPE_NORMAL, SIGTYPE_END, SIGTYPE_END, 3> {};
|
||||
|
||||
|
||||
/**
|
||||
* 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 */
|
||||
|
|
Loading…
Reference in New Issue