(svn r27666) -Codechange: Pass vehicle sprites around using a struct VehicleSpriteSeq.

This commit is contained in:
frosch 2016-10-16 14:57:56 +00:00
parent f5409c713b
commit d2393b4f6c
22 changed files with 249 additions and 161 deletions

View File

@ -93,7 +93,7 @@ struct Aircraft FINAL : public SpecializedVehicle<Aircraft, VEH_AIRCRAFT> {
void UpdateDeltaXY(Direction direction);
ExpensesType GetExpenseType(bool income) const { return income ? EXPENSES_AIRCRAFT_INC : EXPENSES_AIRCRAFT_RUN; }
bool IsPrimaryVehicle() const { return this->IsNormalAircraft(); }
SpriteID GetImage(Direction direction, EngineImageType image_type) const;
void GetImage(Direction direction, EngineImageType image_type, VehicleSpriteSeq *result) const;
int GetDisplaySpeed() const { return this->cur_speed; }
int GetDisplayMaxSpeed() const { return this->vcache.cached_max_speed; }
int GetSpeedOldUnits() const { return this->vcache.cached_max_speed * 10 / 128; }
@ -141,7 +141,7 @@ struct Aircraft FINAL : public SpecializedVehicle<Aircraft, VEH_AIRCRAFT> {
*/
#define FOR_ALL_AIRCRAFT(var) FOR_ALL_VEHICLES_OF_TYPE(Aircraft, var)
SpriteID GetRotorImage(const Aircraft *v, EngineImageType image_type);
void GetRotorImage(const Aircraft *v, EngineImageType image_type, VehicleSpriteSeq *result);
Station *GetTargetAirportIfValid(const Aircraft *v);

View File

@ -152,64 +152,67 @@ static StationID FindNearestHangar(const Aircraft *v)
return index;
}
SpriteID Aircraft::GetImage(Direction direction, EngineImageType image_type) const
void Aircraft::GetImage(Direction direction, EngineImageType image_type, VehicleSpriteSeq *result) const
{
uint8 spritenum = this->spritenum;
if (is_custom_sprite(spritenum)) {
SpriteID sprite = GetCustomVehicleSprite(this, direction, image_type);
if (sprite != 0) return sprite;
GetCustomVehicleSprite(this, direction, image_type, result);
if (result->IsValid()) return;
spritenum = this->GetEngine()->original_image_index;
}
assert(IsValidImageIndex<VEH_AIRCRAFT>(spritenum));
return direction + _aircraft_sprite[spritenum];
result->Set(direction + _aircraft_sprite[spritenum]);
}
SpriteID GetRotorImage(const Aircraft *v, EngineImageType image_type)
void GetRotorImage(const Aircraft *v, EngineImageType image_type, VehicleSpriteSeq *result)
{
assert(v->subtype == AIR_HELICOPTER);
const Aircraft *w = v->Next()->Next();
if (is_custom_sprite(v->spritenum)) {
SpriteID sprite = GetCustomRotorSprite(v, false, image_type);
if (sprite != 0) return sprite;
GetCustomRotorSprite(v, false, image_type, result);
if (result->IsValid()) return;
}
/* Return standard rotor sprites if there are no custom sprites for this helicopter */
return SPR_ROTOR_STOPPED + w->state;
result->Set(SPR_ROTOR_STOPPED + w->state);
}
static SpriteID GetAircraftIcon(EngineID engine, EngineImageType image_type)
static void GetAircraftIcon(EngineID engine, EngineImageType image_type, VehicleSpriteSeq *result)
{
const Engine *e = Engine::Get(engine);
uint8 spritenum = e->u.air.image_index;
if (is_custom_sprite(spritenum)) {
SpriteID sprite = GetCustomVehicleIcon(engine, DIR_W, image_type);
if (sprite != 0) return sprite;
GetCustomVehicleIcon(engine, DIR_W, image_type, result);
if (result->IsValid()) return;
spritenum = e->original_image_index;
}
assert(IsValidImageIndex<VEH_AIRCRAFT>(spritenum));
return DIR_W + _aircraft_sprite[spritenum];
result->Set(DIR_W + _aircraft_sprite[spritenum]);
}
void DrawAircraftEngine(int left, int right, int preferred_x, int y, EngineID engine, PaletteID pal, EngineImageType image_type)
{
SpriteID sprite = GetAircraftIcon(engine, image_type);
const Sprite *real_sprite = GetSprite(sprite, ST_NORMAL);
VehicleSpriteSeq seq;
GetAircraftIcon(engine, image_type, &seq);
const Sprite *real_sprite = GetSprite(seq.sprite, ST_NORMAL);
preferred_x = Clamp(preferred_x,
left - UnScaleGUI(real_sprite->x_offs),
right - UnScaleGUI(real_sprite->width) - UnScaleGUI(real_sprite->x_offs));
DrawSprite(sprite, pal, preferred_x, y);
DrawSprite(seq.sprite, pal, preferred_x, y);
if (!(AircraftVehInfo(engine)->subtype & AIR_CTOL)) {
SpriteID rotor_sprite = GetCustomRotorIcon(engine, image_type);
if (rotor_sprite == 0) rotor_sprite = SPR_ROTOR_STOPPED;
DrawSprite(rotor_sprite, PAL_NONE, preferred_x, y - ScaleGUITrad(5));
VehicleSpriteSeq rotor_seq;
GetCustomRotorIcon(engine, image_type, &rotor_seq);
if (!rotor_seq.IsValid()) rotor_seq.Set(SPR_ROTOR_STOPPED);
DrawSprite(rotor_seq.sprite, PAL_NONE, preferred_x, y - ScaleGUITrad(5));
}
}
@ -224,7 +227,10 @@ void DrawAircraftEngine(int left, int right, int preferred_x, int y, EngineID en
*/
void GetAircraftSpriteSize(EngineID engine, uint &width, uint &height, int &xoffs, int &yoffs, EngineImageType image_type)
{
const Sprite *spr = GetSprite(GetAircraftIcon(engine, image_type), ST_NORMAL);
VehicleSpriteSeq seq;
GetAircraftIcon(engine, image_type, &seq);
const Sprite *spr = GetSprite(seq.sprite, ST_NORMAL);
width = UnScaleGUI(spr->width);
height = UnScaleGUI(spr->height);
@ -317,7 +323,8 @@ CommandCost CmdBuildAircraft(TileIndex tile, DoCommandFlag flags, const Engine *
v->date_of_last_service = _date;
v->build_year = u->build_year = _cur_year;
v->cur_image = u->cur_image = SPR_IMG_QUERY;
v->sprite_seq.Set(SPR_IMG_QUERY);
u->sprite_seq.Set(SPR_IMG_QUERY);
v->random_bits = VehicleRandomBits();
u->random_bits = VehicleRandomBits();
@ -349,7 +356,7 @@ CommandCost CmdBuildAircraft(TileIndex tile, DoCommandFlag flags, const Engine *
w->vehstatus = VS_HIDDEN | VS_UNCLICKABLE;
w->spritenum = 0xFF;
w->subtype = AIR_ROTOR;
w->cur_image = SPR_ROTOR_STOPPED;
w->sprite_seq.Set(SPR_ROTOR_STOPPED);
w->random_bits = VehicleRandomBits();
/* Use rotor's air.state to store the rotor animation frame */
w->state = HRS_ROTOR_STOPPED;
@ -468,21 +475,21 @@ static void HelicopterTickHandler(Aircraft *v)
int tick = ++u->tick_counter;
int spd = u->cur_speed >> 4;
SpriteID img;
VehicleSpriteSeq seq;
if (spd == 0) {
u->state = HRS_ROTOR_STOPPED;
img = GetRotorImage(v, EIT_ON_MAP);
if (u->cur_image == img) return;
GetRotorImage(v, EIT_ON_MAP, &seq);
if (u->sprite_seq == seq) return;
} else if (tick >= spd) {
u->tick_counter = 0;
u->state++;
if (u->state > HRS_ROTOR_MOVING_3) u->state = HRS_ROTOR_MOVING_1;
img = GetRotorImage(v, EIT_ON_MAP);
GetRotorImage(v, EIT_ON_MAP, &seq);
} else {
return;
}
u->cur_image = img;
u->sprite_seq = seq;
u->UpdatePositionAndViewport();
}
@ -502,7 +509,9 @@ void SetAircraftPosition(Aircraft *v, int x, int y, int z)
v->UpdatePosition();
v->UpdateViewport(true, false);
if (v->subtype == AIR_HELICOPTER) v->Next()->Next()->cur_image = GetRotorImage(v, EIT_ON_MAP);
if (v->subtype == AIR_HELICOPTER) {
GetRotorImage(v, EIT_ON_MAP, &v->Next()->Next()->sprite_seq);
}
Aircraft *u = v->Next();
@ -513,7 +522,7 @@ void SetAircraftPosition(Aircraft *v, int x, int y, int z)
safe_y = Clamp(u->y_pos, 0, MapMaxY() * TILE_SIZE);
u->z_pos = GetSlopePixelZ(safe_x, safe_y);
u->cur_image = v->cur_image;
u->sprite_seq.sprite = v->sprite_seq.sprite;
u->UpdatePositionAndViewport();
@ -1237,7 +1246,9 @@ void Aircraft::MarkDirty()
{
this->colourmap = PAL_NONE;
this->UpdateViewport(true, false);
if (this->subtype == AIR_HELICOPTER) this->Next()->Next()->cur_image = GetRotorImage(this, EIT_ON_MAP);
if (this->subtype == AIR_HELICOPTER) {
GetRotorImage(this, EIT_ON_MAP, &this->Next()->Next()->sprite_seq);
}
}

View File

@ -83,8 +83,10 @@ void DrawAircraftImage(const Vehicle *v, int left, int right, int y, VehicleID s
{
bool rtl = _current_text_dir == TD_RTL;
SpriteID sprite = v->GetImage(rtl ? DIR_E : DIR_W, image_type);
const Sprite *real_sprite = GetSprite(sprite, ST_NORMAL);
VehicleSpriteSeq seq;
v->GetImage(rtl ? DIR_E : DIR_W, image_type, &seq);
const Sprite *real_sprite = GetSprite(seq.sprite, ST_NORMAL);
int width = UnScaleGUI(real_sprite->width);
int x_offs = UnScaleGUI(real_sprite->x_offs);
@ -95,13 +97,14 @@ void DrawAircraftImage(const Vehicle *v, int left, int right, int y, VehicleID s
int heli_offs = 0;
PaletteID pal = (v->vehstatus & VS_CRASHED) ? PALETTE_CRASH : GetVehiclePalette(v);
DrawSprite(sprite, pal, x, y + y_offs);
DrawSprite(seq.sprite, pal, x, y + y_offs);
if (helicopter) {
const Aircraft *a = Aircraft::From(v);
SpriteID rotor_sprite = GetCustomRotorSprite(a, true, image_type);
if (rotor_sprite == 0) rotor_sprite = SPR_ROTOR_STOPPED;
VehicleSpriteSeq rotor_seq;
GetCustomRotorSprite(a, true, image_type, &rotor_seq);
if (!rotor_seq.IsValid()) rotor_seq.Set(SPR_ROTOR_STOPPED);
heli_offs = ScaleGUITrad(5);
DrawSprite(rotor_sprite, PAL_NONE, x, y + y_offs - heli_offs);
DrawSprite(rotor_seq.sprite, PAL_NONE, x, y + y_offs - heli_offs);
}
if (v->index == selection) {
x += x_offs;

View File

@ -441,7 +441,7 @@ void AddArticulatedParts(Vehicle *first)
v->max_age = 0;
v->engine_type = engine_type;
v->value = 0;
v->cur_image = SPR_IMG_QUERY;
v->sprite_seq.Set(SPR_IMG_QUERY);
v->random_bits = VehicleRandomBits();
if (flip_image) v->spritenum++;

View File

@ -112,7 +112,7 @@ void DisasterVehicle::UpdateImage()
{
SpriteID img = this->image_override;
if (img == 0) img = _disaster_images[this->subtype][this->direction];
this->cur_image = img;
this->sprite_seq.Set(img);
}
/**
@ -499,7 +499,8 @@ static bool DisasterTick_Helicopter_Rotors(DisasterVehicle *v)
v->tick_counter++;
if (HasBit(v->tick_counter, 0)) return true;
if (++v->cur_image > SPR_ROTOR_MOVING_3) v->cur_image = SPR_ROTOR_MOVING_1;
SpriteID &cur_image = v->sprite_seq.sprite;
if (++cur_image > SPR_ROTOR_MOVING_3) cur_image = SPR_ROTOR_MOVING_1;
v->UpdatePositionAndViewport();

View File

@ -30,8 +30,8 @@
*/
static bool IncrementSprite(EffectVehicle *v, SpriteID last)
{
if (v->cur_image != last) {
v->cur_image++;
if (v->sprite_seq.sprite != last) {
v->sprite_seq.sprite++;
return true;
} else {
return false;
@ -41,7 +41,7 @@ static bool IncrementSprite(EffectVehicle *v, SpriteID last)
static void ChimneySmokeInit(EffectVehicle *v)
{
uint32 r = Random();
v->cur_image = SPR_CHIMNEY_SMOKE_0 + GB(r, 0, 3);
v->sprite_seq.Set(SPR_CHIMNEY_SMOKE_0 + GB(r, 0, 3));
v->progress = GB(r, 16, 3);
}
@ -57,7 +57,7 @@ static bool ChimneySmokeTick(EffectVehicle *v)
}
if (!IncrementSprite(v, SPR_CHIMNEY_SMOKE_7)) {
v->cur_image = SPR_CHIMNEY_SMOKE_0;
v->sprite_seq.Set(SPR_CHIMNEY_SMOKE_0);
}
v->progress = 7;
v->UpdatePositionAndViewport();
@ -68,7 +68,7 @@ static bool ChimneySmokeTick(EffectVehicle *v)
static void SteamSmokeInit(EffectVehicle *v)
{
v->cur_image = SPR_STEAM_SMOKE_0;
v->sprite_seq.Set(SPR_STEAM_SMOKE_0);
v->progress = 12;
}
@ -98,7 +98,7 @@ static bool SteamSmokeTick(EffectVehicle *v)
static void DieselSmokeInit(EffectVehicle *v)
{
v->cur_image = SPR_DIESEL_SMOKE_0;
v->sprite_seq.Set(SPR_DIESEL_SMOKE_0);
v->progress = 0;
}
@ -122,7 +122,7 @@ static bool DieselSmokeTick(EffectVehicle *v)
static void ElectricSparkInit(EffectVehicle *v)
{
v->cur_image = SPR_ELECTRIC_SPARK_0;
v->sprite_seq.Set(SPR_ELECTRIC_SPARK_0);
v->progress = 1;
}
@ -145,7 +145,7 @@ static bool ElectricSparkTick(EffectVehicle *v)
static void SmokeInit(EffectVehicle *v)
{
v->cur_image = SPR_SMOKE_0;
v->sprite_seq.Set(SPR_SMOKE_0);
v->progress = 12;
}
@ -175,7 +175,7 @@ static bool SmokeTick(EffectVehicle *v)
static void ExplosionLargeInit(EffectVehicle *v)
{
v->cur_image = SPR_EXPLOSION_LARGE_0;
v->sprite_seq.Set(SPR_EXPLOSION_LARGE_0);
v->progress = 0;
}
@ -195,7 +195,7 @@ static bool ExplosionLargeTick(EffectVehicle *v)
static void BreakdownSmokeInit(EffectVehicle *v)
{
v->cur_image = SPR_BREAKDOWN_SMOKE_0;
v->sprite_seq.Set(SPR_BREAKDOWN_SMOKE_0);
v->progress = 0;
}
@ -204,7 +204,7 @@ static bool BreakdownSmokeTick(EffectVehicle *v)
v->progress++;
if ((v->progress & 7) == 0) {
if (!IncrementSprite(v, SPR_BREAKDOWN_SMOKE_3)) {
v->cur_image = SPR_BREAKDOWN_SMOKE_0;
v->sprite_seq.Set(SPR_BREAKDOWN_SMOKE_0);
}
v->UpdatePositionAndViewport();
}
@ -220,7 +220,7 @@ static bool BreakdownSmokeTick(EffectVehicle *v)
static void ExplosionSmallInit(EffectVehicle *v)
{
v->cur_image = SPR_EXPLOSION_SMALL_0;
v->sprite_seq.Set(SPR_EXPLOSION_SMALL_0);
v->progress = 0;
}
@ -240,7 +240,7 @@ static bool ExplosionSmallTick(EffectVehicle *v)
static void BulldozerInit(EffectVehicle *v)
{
v->cur_image = SPR_BULLDOZER_NE;
v->sprite_seq.Set(SPR_BULLDOZER_NE);
v->progress = 0;
v->animation_state = 0;
v->animation_substate = 0;
@ -291,7 +291,7 @@ static bool BulldozerTick(EffectVehicle *v)
if ((v->progress & 7) == 0) {
const BulldozerMovement *b = &_bulldozer_movement[v->animation_state];
v->cur_image = SPR_BULLDOZER_NE + b->image;
v->sprite_seq.Set(SPR_BULLDOZER_NE + b->image);
v->x_pos += _inc_by_dir[b->direction].x;
v->y_pos += _inc_by_dir[b->direction].y;
@ -313,7 +313,7 @@ static bool BulldozerTick(EffectVehicle *v)
static void BubbleInit(EffectVehicle *v)
{
v->cur_image = SPR_BUBBLE_GENERATE_0;
v->sprite_seq.Set(SPR_BUBBLE_GENERATE_0);
v->spritenum = 0;
v->progress = 0;
}
@ -476,8 +476,9 @@ static bool BubbleTick(EffectVehicle *v)
if ((v->progress & 3) != 0) return true;
if (v->spritenum == 0) {
v->cur_image++;
if (v->cur_image < SPR_BUBBLE_GENERATE_3) {
SpriteID &cur_image = v->sprite_seq.sprite;
cur_image++;
if (cur_image < SPR_BUBBLE_GENERATE_3) {
v->UpdatePositionAndViewport();
return true;
}
@ -522,7 +523,7 @@ static bool BubbleTick(EffectVehicle *v)
v->x_pos += b->x;
v->y_pos += b->y;
v->z_pos += b->z;
v->cur_image = SPR_BUBBLE_0 + b->image;
v->sprite_seq.Set(SPR_BUBBLE_0 + b->image);
v->UpdatePositionAndViewport();

View File

@ -1023,17 +1023,19 @@ VehicleResolverObject::VehicleResolverObject(EngineID engine_type, const Vehicle
SpriteID GetCustomEngineSprite(EngineID engine, const Vehicle *v, Direction direction, EngineImageType image_type)
void GetCustomEngineSprite(EngineID engine, const Vehicle *v, Direction direction, EngineImageType image_type, VehicleSpriteSeq *result)
{
VehicleResolverObject object(engine, v, VehicleResolverObject::WO_CACHED, false, CBID_NO_CALLBACK, image_type);
const SpriteGroup *group = object.Resolve();
if (group == NULL || group->GetNumResults() == 0) return 0;
result->Clear();
return group->GetResult() + (direction % group->GetNumResults());
const SpriteGroup *group = object.Resolve();
if (group == NULL || group->GetNumResults() == 0) return;
result->Set(group->GetResult() + (direction % group->GetNumResults()));
}
SpriteID GetRotorOverrideSprite(EngineID engine, const Aircraft *v, bool info_view, EngineImageType image_type)
void GetRotorOverrideSprite(EngineID engine, const struct Aircraft *v, bool info_view, EngineImageType image_type, VehicleSpriteSeq *result)
{
const Engine *e = Engine::Get(engine);
@ -1042,13 +1044,14 @@ SpriteID GetRotorOverrideSprite(EngineID engine, const Aircraft *v, bool info_vi
assert(!(e->u.air.subtype & AIR_CTOL));
VehicleResolverObject object(engine, v, VehicleResolverObject::WO_SELF, info_view, CBID_NO_CALLBACK, image_type);
result->Clear();
uint rotor_pos = v == NULL || info_view ? 0 : v->Next()->Next()->state;
const SpriteGroup *group = object.Resolve();
if (group == NULL || group->GetNumResults() == 0) return 0;
if (group == NULL || group->GetNumResults() == 0) return;
if (v == NULL || info_view) return group->GetResult();
return group->GetResult() + (v->Next()->Next()->state % group->GetNumResults());
result->Set(group->GetResult() + (rotor_pos % group->GetNumResults()));
}

View File

@ -64,13 +64,19 @@ static const uint TRAININFO_DEFAULT_VEHICLE_WIDTH = 29;
static const uint ROADVEHINFO_DEFAULT_VEHICLE_WIDTH = 32;
static const uint VEHICLEINFO_FULL_VEHICLE_WIDTH = 32;
struct VehicleSpriteSeq;
void SetWagonOverrideSprites(EngineID engine, CargoID cargo, const struct SpriteGroup *group, EngineID *train_id, uint trains);
const SpriteGroup *GetWagonOverrideSpriteSet(EngineID engine, CargoID cargo, EngineID overriding_engine);
void SetCustomEngineSprites(EngineID engine, byte cargo, const struct SpriteGroup *group);
SpriteID GetCustomEngineSprite(EngineID engine, const Vehicle *v, Direction direction, EngineImageType image_type);
SpriteID GetRotorOverrideSprite(EngineID engine, const struct Aircraft *v, bool info_view, EngineImageType image_type);
#define GetCustomRotorSprite(v, i, image_type) GetRotorOverrideSprite(v->engine_type, v, i, image_type)
#define GetCustomRotorIcon(et, image_type) GetRotorOverrideSprite(et, NULL, true, image_type)
void GetCustomEngineSprite(EngineID engine, const Vehicle *v, Direction direction, EngineImageType image_type, VehicleSpriteSeq *result);
#define GetCustomVehicleSprite(v, direction, image_type, result) GetCustomEngineSprite(v->engine_type, v, direction, image_type, result)
#define GetCustomVehicleIcon(et, direction, image_type, result) GetCustomEngineSprite(et, NULL, direction, image_type, result)
void GetRotorOverrideSprite(EngineID engine, const struct Aircraft *v, bool info_view, EngineImageType image_type, VehicleSpriteSeq *result);
#define GetCustomRotorSprite(v, i, image_type, result) GetRotorOverrideSprite(v->engine_type, v, i, image_type, result)
#define GetCustomRotorIcon(et, image_type, result) GetRotorOverrideSprite(et, NULL, true, image_type, result)
/* Forward declaration of GRFFile, to avoid unnecessary inclusion of newgrf.h
* elsewhere... */
@ -81,8 +87,6 @@ void SetEngineGRF(EngineID engine, const struct GRFFile *file);
uint16 GetVehicleCallback(CallbackID callback, uint32 param1, uint32 param2, EngineID engine, const Vehicle *v);
uint16 GetVehicleCallbackParent(CallbackID callback, uint32 param1, uint32 param2, EngineID engine, const Vehicle *v, const Vehicle *parent);
bool UsesWagonOverride(const Vehicle *v);
#define GetCustomVehicleSprite(v, direction, image_type) GetCustomEngineSprite(v->engine_type, v, direction, image_type)
#define GetCustomVehicleIcon(et, direction, image_type) GetCustomEngineSprite(et, NULL, direction, image_type)
/* Handler to Evaluate callback 36. If the callback fails (i.e. most of the
* time) orig_value is returned */

View File

@ -108,7 +108,7 @@ struct RoadVehicle FINAL : public GroundVehicle<RoadVehicle, VEH_ROAD> {
void UpdateDeltaXY(Direction direction);
ExpensesType GetExpenseType(bool income) const { return income ? EXPENSES_ROADVEH_INC : EXPENSES_ROADVEH_RUN; }
bool IsPrimaryVehicle() const { return this->IsFrontEngine(); }
SpriteID GetImage(Direction direction, EngineImageType image_type) const;
void GetImage(Direction direction, EngineImageType image_type, VehicleSpriteSeq *result) const;
int GetDisplaySpeed() const { return this->gcache.last_speed / 2; }
int GetDisplayMaxSpeed() const { return this->vcache.cached_max_speed / 2; }
Money GetRunningCost() const;

View File

@ -113,40 +113,39 @@ int RoadVehicle::GetDisplayImageWidth(Point *offset) const
return ScaleGUITrad(this->gcache.cached_veh_length * reference_width / VEHICLE_LENGTH);
}
static SpriteID GetRoadVehIcon(EngineID engine, EngineImageType image_type)
static void GetRoadVehIcon(EngineID engine, EngineImageType image_type, VehicleSpriteSeq *result)
{
const Engine *e = Engine::Get(engine);
uint8 spritenum = e->u.road.image_index;
if (is_custom_sprite(spritenum)) {
SpriteID sprite = GetCustomVehicleIcon(engine, DIR_W, image_type);
if (sprite != 0) return sprite;
GetCustomVehicleIcon(engine, DIR_W, image_type, result);
if (result->IsValid()) return;
spritenum = e->original_image_index;
}
assert(IsValidImageIndex<VEH_ROAD>(spritenum));
return DIR_W + _roadveh_images[spritenum];
result->Set(DIR_W + _roadveh_images[spritenum]);
}
SpriteID RoadVehicle::GetImage(Direction direction, EngineImageType image_type) const
void RoadVehicle::GetImage(Direction direction, EngineImageType image_type, VehicleSpriteSeq *result) const
{
uint8 spritenum = this->spritenum;
SpriteID sprite;
if (is_custom_sprite(spritenum)) {
sprite = GetCustomVehicleSprite(this, (Direction)(direction + 4 * IS_CUSTOM_SECONDHEAD_SPRITE(spritenum)), image_type);
if (sprite != 0) return sprite;
GetCustomVehicleSprite(this, (Direction)(direction + 4 * IS_CUSTOM_SECONDHEAD_SPRITE(spritenum)), image_type, result);
if (result->IsValid()) return;
spritenum = this->GetEngine()->original_image_index;
}
assert(IsValidImageIndex<VEH_ROAD>(spritenum));
sprite = direction + _roadveh_images[spritenum];
SpriteID sprite = direction + _roadveh_images[spritenum];
if (this->cargo.StoredCount() >= this->cargo_cap / 2U) sprite += _roadveh_full_adder[spritenum];
return sprite;
result->Set(sprite);
}
/**
@ -160,12 +159,14 @@ SpriteID RoadVehicle::GetImage(Direction direction, EngineImageType image_type)
*/
void DrawRoadVehEngine(int left, int right, int preferred_x, int y, EngineID engine, PaletteID pal, EngineImageType image_type)
{
SpriteID sprite = GetRoadVehIcon(engine, image_type);
const Sprite *real_sprite = GetSprite(sprite, ST_NORMAL);
VehicleSpriteSeq seq;
GetRoadVehIcon(engine, image_type, &seq);
const Sprite *real_sprite = GetSprite(seq.sprite, ST_NORMAL);
preferred_x = Clamp(preferred_x,
left - UnScaleGUI(real_sprite->x_offs),
right - UnScaleGUI(real_sprite->width) - UnScaleGUI(real_sprite->x_offs));
DrawSprite(sprite, pal, preferred_x, y);
DrawSprite(seq.sprite, pal, preferred_x, y);
}
/**
@ -179,7 +180,10 @@ void DrawRoadVehEngine(int left, int right, int preferred_x, int y, EngineID eng
*/
void GetRoadVehSpriteSize(EngineID engine, uint &width, uint &height, int &xoffs, int &yoffs, EngineImageType image_type)
{
const Sprite *spr = GetSprite(GetRoadVehIcon(engine, image_type), ST_NORMAL);
VehicleSpriteSeq seq;
GetRoadVehIcon(engine, image_type, &seq);
const Sprite *spr = GetSprite(seq.sprite, ST_NORMAL);
width = UnScaleGUI(spr->width);
height = UnScaleGUI(spr->height);
@ -306,7 +310,7 @@ CommandCost CmdBuildRoadVehicle(TileIndex tile, DoCommandFlag flags, const Engin
v->date_of_last_service = _date;
v->build_year = _cur_year;
v->cur_image = SPR_IMG_QUERY;
v->sprite_seq.Set(SPR_IMG_QUERY);
v->random_bits = VehicleRandomBits();
v->SetFrontEngine();

View File

@ -149,7 +149,9 @@ void DrawRoadVehImage(const Vehicle *v, int left, int right, int y, VehicleID se
if (rtl ? px + width > 0 : px - width < max_width) {
PaletteID pal = (u->vehstatus & VS_CRASHED) ? PALETTE_CRASH : GetVehiclePalette(u);
DrawSprite(u->GetImage(dir, image_type), pal, px + (rtl ? -offset.x : offset.x), ScaleGUITrad(6) + offset.y);
VehicleSpriteSeq seq;
u->GetImage(dir, image_type, &seq);
DrawSprite(seq.sprite, pal, px + (rtl ? -offset.x : offset.x), ScaleGUITrad(6) + offset.y);
}
px += rtl ? -width : width;

View File

@ -1165,7 +1165,7 @@ static const OldChunks vehicle_chunk[] = {
OCL_SVAR( OC_UINT8, Vehicle, owner ),
OCL_SVAR( OC_TILE, Vehicle, tile ),
OCL_SVAR( OC_FILE_U16 | OC_VAR_U32, Vehicle, cur_image ),
OCL_SVAR( OC_FILE_U16 | OC_VAR_U32, Vehicle, sprite_seq.sprite ),
OCL_NULL( 8 ), ///< Vehicle sprite box, calculated automatically
@ -1258,7 +1258,7 @@ bool LoadOldVehicle(LoadgameState *ls, int num)
if (v == NULL) continue;
v->refit_cap = v->cargo_cap;
SpriteID sprite = v->cur_image;
SpriteID sprite = v->sprite_seq.sprite;
/* no need to override other sprites */
if (IsInsideMM(sprite, 1460, 1465)) {
sprite += 580; // aircraft smoke puff
@ -1269,7 +1269,7 @@ bool LoadOldVehicle(LoadgameState *ls, int num)
} else if (IsInsideMM(sprite, 2516, 2539)) {
sprite += 1385; // rotor or disaster-related vehicles
}
v->cur_image = sprite;
v->sprite_seq.sprite = sprite;
switch (v->type) {
case VEH_TRAIN: {

View File

@ -436,21 +436,21 @@ void AfterLoadVehicles(bool part_of_load)
case VEH_TRAIN:
case VEH_SHIP:
v->cur_image = v->GetImage(v->direction, EIT_ON_MAP);
v->GetImage(v->direction, EIT_ON_MAP, &v->sprite_seq);
break;
case VEH_AIRCRAFT:
if (Aircraft::From(v)->IsNormalAircraft()) {
v->cur_image = v->GetImage(v->direction, EIT_ON_MAP);
v->GetImage(v->direction, EIT_ON_MAP, &v->sprite_seq);
/* The plane's shadow will have the same image as the plane */
/* The plane's shadow will have the same image as the plane, but no colour */
Vehicle *shadow = v->Next();
shadow->cur_image = v->cur_image;
shadow->sprite_seq.sprite = v->sprite_seq.sprite;
/* In the case of a helicopter we will update the rotor sprites */
if (v->subtype == AIR_HELICOPTER) {
Vehicle *rotor = shadow->Next();
rotor->cur_image = GetRotorImage(Aircraft::From(v), EIT_ON_MAP);
GetRotorImage(Aircraft::From(v), EIT_ON_MAP, &rotor->sprite_seq);
}
UpdateAircraftCache(Aircraft::From(v), true);
@ -796,7 +796,7 @@ const SaveLoad *GetVehicleDescription(VehicleType vt)
SLE_CONDVAR(Vehicle, z_pos, SLE_FILE_U8 | SLE_VAR_I32, 0, 163),
SLE_CONDVAR(Vehicle, z_pos, SLE_INT32, 164, SL_MAX_VERSION),
SLE_VAR(Vehicle, cur_image, SLE_FILE_U16 | SLE_VAR_U32),
SLE_VAR(Vehicle, sprite_seq.sprite, SLE_FILE_U16 | SLE_VAR_U32),
SLE_CONDNULL(5, 0, 57),
SLE_VAR(Vehicle, progress, SLE_UINT8),
SLE_VAR(Vehicle, vehstatus, SLE_UINT8),
@ -836,7 +836,7 @@ const SaveLoad *GetVehicleDescription(VehicleType vt)
SLE_CONDVAR(Vehicle, current_order.dest, SLE_FILE_U8 | SLE_VAR_U16, 0, 4),
SLE_CONDVAR(Vehicle, current_order.dest, SLE_UINT16, 5, SL_MAX_VERSION),
SLE_VAR(Vehicle, cur_image, SLE_FILE_U16 | SLE_VAR_U32),
SLE_VAR(Vehicle, sprite_seq.sprite, SLE_FILE_U16 | SLE_VAR_U32),
SLE_CONDVAR(Vehicle, age, SLE_FILE_U16 | SLE_VAR_I32, 0, 30),
SLE_CONDVAR(Vehicle, age, SLE_INT32, 31, SL_MAX_VERSION),
SLE_VAR(Vehicle, tick_counter, SLE_UINT8),

View File

@ -34,7 +34,7 @@ struct Ship FINAL : public SpecializedVehicle<Ship, VEH_SHIP> {
ExpensesType GetExpenseType(bool income) const { return income ? EXPENSES_SHIP_INC : EXPENSES_SHIP_RUN; }
void PlayLeaveStationSound() const;
bool IsPrimaryVehicle() const { return true; }
SpriteID GetImage(Direction direction, EngineImageType image_type) const;
void GetImage(Direction direction, EngineImageType image_type, VehicleSpriteSeq *result) const;
int GetDisplaySpeed() const { return this->cur_speed / 2; }
int GetDisplayMaxSpeed() const { return this->vcache.cached_max_speed / 2; }
int GetCurrentMaxSpeed() const { return min(this->vcache.cached_max_speed, this->current_order.GetMaxSpeed() * 2); }

View File

@ -70,30 +70,32 @@ static inline TrackBits GetTileShipTrackStatus(TileIndex tile)
return TrackStatusToTrackBits(GetTileTrackStatus(tile, TRANSPORT_WATER, 0));
}
static SpriteID GetShipIcon(EngineID engine, EngineImageType image_type)
static void GetShipIcon(EngineID engine, EngineImageType image_type, VehicleSpriteSeq *result)
{
const Engine *e = Engine::Get(engine);
uint8 spritenum = e->u.ship.image_index;
if (is_custom_sprite(spritenum)) {
SpriteID sprite = GetCustomVehicleIcon(engine, DIR_W, image_type);
if (sprite != 0) return sprite;
GetCustomVehicleIcon(engine, DIR_W, image_type, result);
if (result->IsValid()) return;
spritenum = e->original_image_index;
}
assert(IsValidImageIndex<VEH_SHIP>(spritenum));
return DIR_W + _ship_sprites[spritenum];
result->Set(DIR_W + _ship_sprites[spritenum]);
}
void DrawShipEngine(int left, int right, int preferred_x, int y, EngineID engine, PaletteID pal, EngineImageType image_type)
{
SpriteID sprite = GetShipIcon(engine, image_type);
const Sprite *real_sprite = GetSprite(sprite, ST_NORMAL);
VehicleSpriteSeq seq;
GetShipIcon(engine, image_type, &seq);
const Sprite *real_sprite = GetSprite(seq.sprite, ST_NORMAL);
preferred_x = Clamp(preferred_x,
left - UnScaleGUI(real_sprite->x_offs),
right - UnScaleGUI(real_sprite->width) - UnScaleGUI(real_sprite->x_offs));
DrawSprite(sprite, pal, preferred_x, y);
DrawSprite(seq.sprite, pal, preferred_x, y);
}
/**
@ -107,7 +109,10 @@ void DrawShipEngine(int left, int right, int preferred_x, int y, EngineID engine
*/
void GetShipSpriteSize(EngineID engine, uint &width, uint &height, int &xoffs, int &yoffs, EngineImageType image_type)
{
const Sprite *spr = GetSprite(GetShipIcon(engine, image_type), ST_NORMAL);
VehicleSpriteSeq seq;
GetShipIcon(engine, image_type, &seq);
const Sprite *spr = GetSprite(seq.sprite, ST_NORMAL);
width = UnScaleGUI(spr->width);
height = UnScaleGUI(spr->height);
@ -115,19 +120,19 @@ void GetShipSpriteSize(EngineID engine, uint &width, uint &height, int &xoffs, i
yoffs = UnScaleGUI(spr->y_offs);
}
SpriteID Ship::GetImage(Direction direction, EngineImageType image_type) const
void Ship::GetImage(Direction direction, EngineImageType image_type, VehicleSpriteSeq *result) const
{
uint8 spritenum = this->spritenum;
if (is_custom_sprite(spritenum)) {
SpriteID sprite = GetCustomVehicleSprite(this, direction, image_type);
if (sprite != 0) return sprite;
GetCustomVehicleSprite(this, direction, image_type, result);
if (result->IsValid()) return;
spritenum = this->GetEngine()->original_image_index;
}
assert(IsValidImageIndex<VEH_SHIP>(spritenum));
return _ship_sprites[spritenum] + direction;
result->Set(_ship_sprites[spritenum] + direction);
}
static const Depot *FindClosestShipDepot(const Vehicle *v, uint max_distance)
@ -710,7 +715,7 @@ CommandCost CmdBuildShip(TileIndex tile, DoCommandFlag flags, const Engine *e, u
v->SetServiceInterval(Company::Get(_current_company)->settings.vehicle.servint_ships);
v->date_of_last_service = _date;
v->build_year = _cur_year;
v->cur_image = SPR_IMG_QUERY;
v->sprite_seq.Set(SPR_IMG_QUERY);
v->random_bits = VehicleRandomBits();
v->UpdateCache();

View File

@ -35,15 +35,17 @@ void DrawShipImage(const Vehicle *v, int left, int right, int y, VehicleID selec
{
bool rtl = _current_text_dir == TD_RTL;
SpriteID sprite = v->GetImage(rtl ? DIR_E : DIR_W, image_type);
const Sprite *real_sprite = GetSprite(sprite, ST_NORMAL);
VehicleSpriteSeq seq;
v->GetImage(rtl ? DIR_E : DIR_W, image_type, &seq);
const Sprite *real_sprite = GetSprite(seq.sprite, ST_NORMAL);
int width = UnScaleGUI(real_sprite->width);
int x_offs = UnScaleGUI(real_sprite->x_offs);
int x = rtl ? right - width - x_offs : left - x_offs;
y += ScaleGUITrad(10);
DrawSprite(sprite, GetVehiclePalette(v), x, y);
DrawSprite(seq.sprite, GetVehiclePalette(v), x, y);
if (v->index == selection) {
x += x_offs;

View File

@ -114,7 +114,7 @@ struct Train FINAL : public GroundVehicle<Train, VEH_TRAIN> {
ExpensesType GetExpenseType(bool income) const { return income ? EXPENSES_TRAIN_INC : EXPENSES_TRAIN_RUN; }
void PlayLeaveStationSound() const;
bool IsPrimaryVehicle() const { return this->IsFrontEngine(); }
SpriteID GetImage(Direction direction, EngineImageType image_type) const;
void GetImage(Direction direction, EngineImageType image_type, VehicleSpriteSeq *result) const;
int GetDisplaySpeed() const { return this->gcache.last_speed; }
int GetDisplayMaxSpeed() const { return this->vcache.cached_max_speed; }
Money GetRunningCost() const;

View File

@ -482,41 +482,40 @@ static SpriteID GetDefaultTrainSprite(uint8 spritenum, Direction direction)
* @param image_type Visualisation context.
* @return Sprite to display.
*/
SpriteID Train::GetImage(Direction direction, EngineImageType image_type) const
void Train::GetImage(Direction direction, EngineImageType image_type, VehicleSpriteSeq *result) const
{
uint8 spritenum = this->spritenum;
SpriteID sprite;
if (HasBit(this->flags, VRF_REVERSE_DIRECTION)) direction = ReverseDir(direction);
if (is_custom_sprite(spritenum)) {
sprite = GetCustomVehicleSprite(this, (Direction)(direction + 4 * IS_CUSTOM_SECONDHEAD_SPRITE(spritenum)), image_type);
if (sprite != 0) return sprite;
GetCustomVehicleSprite(this, (Direction)(direction + 4 * IS_CUSTOM_SECONDHEAD_SPRITE(spritenum)), image_type, result);
if (result->IsValid()) return;
spritenum = this->GetEngine()->original_image_index;
}
assert(IsValidImageIndex<VEH_TRAIN>(spritenum));
sprite = GetDefaultTrainSprite(spritenum, direction);
SpriteID sprite = GetDefaultTrainSprite(spritenum, direction);
if (this->cargo.StoredCount() >= this->cargo_cap / 2U) sprite += _wagon_full_adder[spritenum];
return sprite;
result->Set(sprite);
}
static SpriteID GetRailIcon(EngineID engine, bool rear_head, int &y, EngineImageType image_type)
static void GetRailIcon(EngineID engine, bool rear_head, int &y, EngineImageType image_type, VehicleSpriteSeq *result)
{
const Engine *e = Engine::Get(engine);
Direction dir = rear_head ? DIR_E : DIR_W;
uint8 spritenum = e->u.rail.image_index;
if (is_custom_sprite(spritenum)) {
SpriteID sprite = GetCustomVehicleIcon(engine, dir, image_type);
if (sprite != 0) {
GetCustomVehicleIcon(engine, dir, image_type, result);
if (result->IsValid()) {
if (e->GetGRF() != NULL) {
y += ScaleGUITrad(e->GetGRF()->traininfo_vehicle_pitch);
}
return sprite;
return;
}
spritenum = Engine::Get(engine)->original_image_index;
@ -524,7 +523,7 @@ static SpriteID GetRailIcon(EngineID engine, bool rear_head, int &y, EngineImage
if (rear_head) spritenum++;
return GetDefaultTrainSprite(spritenum, DIR_W);
result->Set(GetDefaultTrainSprite(spritenum, DIR_W));
}
void DrawTrainEngine(int left, int right, int preferred_x, int y, EngineID engine, PaletteID pal, EngineImageType image_type)
@ -533,24 +532,28 @@ void DrawTrainEngine(int left, int right, int preferred_x, int y, EngineID engin
int yf = y;
int yr = y;
SpriteID spritef = GetRailIcon(engine, false, yf, image_type);
SpriteID spriter = GetRailIcon(engine, true, yr, image_type);
const Sprite *real_spritef = GetSprite(spritef, ST_NORMAL);
const Sprite *real_spriter = GetSprite(spriter, ST_NORMAL);
VehicleSpriteSeq seqf, seqr;
GetRailIcon(engine, false, yf, image_type, &seqf);
GetRailIcon(engine, true, yr, image_type, &seqr);
const Sprite *real_spritef = GetSprite(seqf.sprite, ST_NORMAL);
const Sprite *real_spriter = GetSprite(seqr.sprite, ST_NORMAL);
preferred_x = Clamp(preferred_x,
left - UnScaleGUI(real_spritef->x_offs) + ScaleGUITrad(14),
right - UnScaleGUI(real_spriter->width) - UnScaleGUI(real_spriter->x_offs) - ScaleGUITrad(15));
DrawSprite(spritef, pal, preferred_x - ScaleGUITrad(14), yf);
DrawSprite(spriter, pal, preferred_x + ScaleGUITrad(15), yr);
DrawSprite(seqf.sprite, pal, preferred_x - ScaleGUITrad(14), yf);
DrawSprite(seqr.sprite, pal, preferred_x + ScaleGUITrad(15), yr);
} else {
SpriteID sprite = GetRailIcon(engine, false, y, image_type);
const Sprite *real_sprite = GetSprite(sprite, ST_NORMAL);
VehicleSpriteSeq seq;
GetRailIcon(engine, false, y, image_type, &seq);
const Sprite *real_sprite = GetSprite(seq.sprite, ST_NORMAL);
preferred_x = Clamp(preferred_x,
left - UnScaleGUI(real_sprite->x_offs),
right - UnScaleGUI(real_sprite->width) - UnScaleGUI(real_sprite->x_offs));
DrawSprite(sprite, pal, preferred_x, y);
DrawSprite(seq.sprite, pal, preferred_x, y);
}
}
@ -567,8 +570,10 @@ void GetTrainSpriteSize(EngineID engine, uint &width, uint &height, int &xoffs,
{
int y = 0;
SpriteID sprite = GetRailIcon(engine, false, y, image_type);
const Sprite *real_sprite = GetSprite(sprite, ST_NORMAL);
VehicleSpriteSeq seq;
GetRailIcon(engine, false, y, image_type, &seq);
const Sprite *real_sprite = GetSprite(seq.sprite, ST_NORMAL);
width = UnScaleGUI(real_sprite->width);
height = UnScaleGUI(real_sprite->height);
@ -576,8 +581,8 @@ void GetTrainSpriteSize(EngineID engine, uint &width, uint &height, int &xoffs,
yoffs = UnScaleGUI(real_sprite->y_offs);
if (RailVehInfo(engine)->railveh_type == RAILVEH_MULTIHEAD) {
sprite = GetRailIcon(engine, true, y, image_type);
real_sprite = GetSprite(sprite, ST_NORMAL);
GetRailIcon(engine, true, y, image_type, &seq);
real_sprite = GetSprite(seq.sprite, ST_NORMAL);
/* Calculate values relative to an imaginary center between the two sprites. */
width = ScaleGUITrad(TRAININFO_DEFAULT_VEHICLE_WIDTH) + UnScaleGUI(real_sprite->width) + UnScaleGUI(real_sprite->x_offs) - xoffs;
@ -638,7 +643,7 @@ static CommandCost CmdBuildRailWagon(TileIndex tile, DoCommandFlag flags, const
v->date_of_last_service = _date;
v->build_year = _cur_year;
v->cur_image = SPR_IMG_QUERY;
v->sprite_seq.Set(SPR_IMG_QUERY);
v->random_bits = VehicleRandomBits();
v->group_id = DEFAULT_GROUP;
@ -706,7 +711,7 @@ static void AddRearEngineToMultiheadedTrain(Train *v)
u->engine_type = v->engine_type;
u->date_of_last_service = v->date_of_last_service;
u->build_year = v->build_year;
u->cur_image = SPR_IMG_QUERY;
u->sprite_seq.Set(SPR_IMG_QUERY);
u->random_bits = VehicleRandomBits();
v->SetMultiheaded();
u->SetMultiheaded();
@ -772,7 +777,7 @@ CommandCost CmdBuildRailVehicle(TileIndex tile, DoCommandFlag flags, const Engin
v->SetServiceInterval(Company::Get(_current_company)->settings.vehicle.servint_trains);
v->date_of_last_service = _date;
v->build_year = _cur_year;
v->cur_image = SPR_IMG_QUERY;
v->sprite_seq.Set(SPR_IMG_QUERY);
v->random_bits = VehicleRandomBits();
if (e->flags & ENGINE_EXCLUSIVE_PREVIEW) SetBit(v->vehicle_flags, VF_BUILT_AS_PROTOTYPE);

View File

@ -124,7 +124,9 @@ void DrawTrainImage(const Train *v, int left, int right, int y, VehicleID select
if (rtl ? px + width > 0 : px - width < max_width) {
PaletteID pal = (v->vehstatus & VS_CRASHED) ? PALETTE_CRASH : GetVehiclePalette(v);
DrawSprite(v->GetImage(dir, image_type), pal, px + (rtl ? -offset.x : offset.x), height / 2 + offset.y);
VehicleSpriteSeq seq;
v->GetImage(dir, image_type, &seq);
DrawSprite(seq.sprite, pal, px + (rtl ? -offset.x : offset.x), height / 2 + offset.y);
}
if (!v->IsArticulatedPart()) sel_articulated = false;
@ -383,7 +385,9 @@ void DrawTrainDetails(const Train *v, int left, int right, int y, int vscroll_po
pitch = ScaleGUITrad(e->GetGRF()->traininfo_vehicle_pitch);
}
PaletteID pal = (v->vehstatus & VS_CRASHED) ? PALETTE_CRASH : GetVehiclePalette(v);
DrawSprite(u->GetImage(dir, EIT_IN_DETAILS), pal, px + (rtl ? -offset.x : offset.x), y - line_height * vscroll_pos + sprite_y_offset + pitch);
VehicleSpriteSeq seq;
u->GetImage(dir, EIT_IN_DETAILS, &seq);
DrawSprite(seq.sprite, pal, px + (rtl ? -offset.x : offset.x), y - line_height * vscroll_pos + sprite_y_offset + pitch);
}
px += rtl ? -width : width;
dx += width;

View File

@ -1008,7 +1008,6 @@ void CallVehicleTicks()
*/
static void DoDrawVehicle(const Vehicle *v)
{
SpriteID image = v->cur_image;
PaletteID pal = PAL_NONE;
if (v->vehstatus & VS_DEFPAL) pal = (v->vehstatus & VS_CRASHED) ? PALETTE_CRASH : GetVehiclePalette(v);
@ -1023,7 +1022,7 @@ static void DoDrawVehicle(const Vehicle *v)
if (to != TO_INVALID && (IsTransparencySet(to) || IsInvisibilitySet(to))) return;
}
AddSortableSpriteToDraw(image, pal, v->x_pos + v->x_offs, v->y_pos + v->y_offs,
AddSortableSpriteToDraw(v->sprite_seq.sprite, pal, v->x_pos + v->x_offs, v->y_pos + v->y_offs,
v->x_extent, v->y_extent, v->z_extent, v->z_pos, shadowed, v->x_bb_offs, v->y_bb_offs);
}
@ -1487,10 +1486,9 @@ void Vehicle::UpdatePosition()
*/
void Vehicle::UpdateViewport(bool dirty)
{
int img = this->cur_image;
Point pt = RemapCoords(this->x_pos + this->x_offs, this->y_pos + this->y_offs, this->z_pos);
const Sprite *spr = GetSprite(img, ST_NORMAL);
const Sprite *spr = GetSprite(this->sprite_seq.sprite, ST_NORMAL);
Point pt = RemapCoords(this->x_pos + this->x_offs, this->y_pos + this->y_offs, this->z_pos);
pt.x += spr->x_offs;
pt.y += spr->y_offs;

View File

@ -126,6 +126,45 @@ struct VehicleCache {
byte cached_vis_effect; ///< Visual effect to show (see #VisualEffect)
};
/** Sprite sequence for a vehicle part. */
struct VehicleSpriteSeq {
SpriteID sprite;
bool operator==(const VehicleSpriteSeq &other) const
{
return this->sprite == other.sprite;
}
bool operator!=(const VehicleSpriteSeq &other) const
{
return !this->operator==(other);
}
/**
* Check whether the sequence contains any sprites.
*/
bool IsValid() const
{
return this->sprite != 0;
}
/**
* Clear all information.
*/
void Clear()
{
this->sprite = 0;
}
/**
* Assign a single sprite to the sequence.
*/
void Set(SpriteID sprite)
{
this->sprite = sprite;
}
};
/** A vehicle pool for a little over 1 million vehicles. */
typedef Pool<Vehicle, VehicleID, 512, 0xFF000> VehiclePool;
extern VehiclePool _vehicle_pool;
@ -220,7 +259,7 @@ public:
* 0xff == reserved for another custom sprite
*/
byte spritenum;
SpriteID cur_image; ///< sprite number for this vehicle
VehicleSpriteSeq sprite_seq; ///< Vehicle appearance.
byte x_extent; ///< x-extent of vehicle bounding box
byte y_extent; ///< y-extent of vehicle bounding box
byte z_extent; ///< z-extent of vehicle bounding box
@ -380,9 +419,9 @@ public:
/**
* Gets the sprite to show for the given direction
* @param direction the direction the vehicle is facing
* @return the sprite for the given vehicle in the given direction
* @param [out] result Vehicle sprite sequence.
*/
virtual SpriteID GetImage(Direction direction, EngineImageType image_type) const { return 0; }
virtual void GetImage(Direction direction, EngineImageType image_type, VehicleSpriteSeq *result) const { result->Clear(); }
const GRFFile *GetGRF() const;
uint32 GetGRFID() const;
@ -1079,9 +1118,12 @@ struct SpecializedVehicle : public Vehicle {
/* Explicitly choose method to call to prevent vtable dereference -
* it gives ~3% runtime improvements in games with many vehicles */
if (update_delta) ((T *)this)->T::UpdateDeltaXY(this->direction);
SpriteID old_image = this->cur_image;
this->cur_image = ((T *)this)->T::GetImage(this->direction, EIT_ON_MAP);
if (force_update || this->cur_image != old_image) this->Vehicle::UpdateViewport(true);
VehicleSpriteSeq seq;
((T *)this)->T::GetImage(this->direction, EIT_ON_MAP, &seq);
if (force_update || this->sprite_seq != seq) {
this->sprite_seq = seq;
this->Vehicle::UpdateViewport(true);
}
}
};

View File

@ -2842,8 +2842,9 @@ int GetSingleVehicleWidth(const Vehicle *v, EngineImageType image_type)
default:
bool rtl = _current_text_dir == TD_RTL;
SpriteID sprite = v->GetImage(rtl ? DIR_E : DIR_W, image_type);
const Sprite *real_sprite = GetSprite(sprite, ST_NORMAL);
VehicleSpriteSeq seq;
v->GetImage(rtl ? DIR_E : DIR_W, image_type, &seq);
const Sprite *real_sprite = GetSprite(seq.sprite, ST_NORMAL);
return UnScaleGUI(real_sprite->width);
}
}
@ -2882,8 +2883,10 @@ void SetMouseCursorVehicle(const Vehicle *v, EngineImageType image_type)
if (total_width >= 2 * (int)VEHICLEINFO_FULL_VEHICLE_WIDTH) break;
PaletteID pal = (v->vehstatus & VS_CRASHED) ? PALETTE_CRASH : GetVehiclePalette(v);
VehicleSpriteSeq seq;
v->GetImage(rtl ? DIR_E : DIR_W, image_type, &seq);
_cursor.sprite_seq[_cursor.sprite_count].sprite = v->GetImage(rtl ? DIR_E : DIR_W, image_type);
_cursor.sprite_seq[_cursor.sprite_count].sprite = seq.sprite;
_cursor.sprite_seq[_cursor.sprite_count].pal = pal;
_cursor.sprite_pos[_cursor.sprite_count].x = rtl ? -total_width : total_width;
_cursor.sprite_pos[_cursor.sprite_count].y = 0;