mirror of https://github.com/OpenTTD/OpenTTD.git
Codechange: create MutableSpriteCache to remove the need to cast Vehicle to a mutable type in render methods
This commit is contained in:
parent
eeb88e87d8
commit
9b28b15e67
|
@ -341,8 +341,8 @@ CommandCost CmdBuildAircraft(TileIndex tile, DoCommandFlag flags, const Engine *
|
|||
v->date_of_last_service = _date;
|
||||
v->build_year = u->build_year = _cur_year;
|
||||
|
||||
v->sprite_seq.Set(SPR_IMG_QUERY);
|
||||
u->sprite_seq.Set(SPR_IMG_QUERY);
|
||||
v->sprite_cache.sprite_seq.Set(SPR_IMG_QUERY);
|
||||
u->sprite_cache.sprite_seq.Set(SPR_IMG_QUERY);
|
||||
|
||||
v->random_bits = VehicleRandomBits();
|
||||
u->random_bits = VehicleRandomBits();
|
||||
|
@ -374,7 +374,7 @@ CommandCost CmdBuildAircraft(TileIndex tile, DoCommandFlag flags, const Engine *
|
|||
w->vehstatus = VS_HIDDEN | VS_UNCLICKABLE;
|
||||
w->spritenum = 0xFF;
|
||||
w->subtype = AIR_ROTOR;
|
||||
w->sprite_seq.Set(SPR_ROTOR_STOPPED);
|
||||
w->sprite_cache.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;
|
||||
|
@ -497,7 +497,7 @@ static void HelicopterTickHandler(Aircraft *v)
|
|||
if (spd == 0) {
|
||||
u->state = HRS_ROTOR_STOPPED;
|
||||
GetRotorImage(v, EIT_ON_MAP, &seq);
|
||||
if (u->sprite_seq == seq) return;
|
||||
if (u->sprite_cache.sprite_seq == seq) return;
|
||||
} else if (tick >= spd) {
|
||||
u->tick_counter = 0;
|
||||
u->state++;
|
||||
|
@ -507,7 +507,7 @@ static void HelicopterTickHandler(Aircraft *v)
|
|||
return;
|
||||
}
|
||||
|
||||
u->sprite_seq = seq;
|
||||
u->sprite_cache.sprite_seq = seq;
|
||||
|
||||
u->UpdatePositionAndViewport();
|
||||
}
|
||||
|
@ -528,7 +528,7 @@ void SetAircraftPosition(Aircraft *v, int x, int y, int z)
|
|||
v->UpdatePosition();
|
||||
v->UpdateViewport(true, false);
|
||||
if (v->subtype == AIR_HELICOPTER) {
|
||||
GetRotorImage(v, EIT_ON_MAP, &v->Next()->Next()->sprite_seq);
|
||||
GetRotorImage(v, EIT_ON_MAP, &v->Next()->Next()->sprite_cache.sprite_seq);
|
||||
}
|
||||
|
||||
Aircraft *u = v->Next();
|
||||
|
@ -540,7 +540,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->sprite_seq.CopyWithoutPalette(v->sprite_seq); // the shadow is never coloured
|
||||
u->sprite_cache.sprite_seq.CopyWithoutPalette(v->sprite_cache.sprite_seq); // the shadow is never coloured
|
||||
|
||||
u->UpdatePositionAndViewport();
|
||||
|
||||
|
@ -1278,7 +1278,7 @@ void Aircraft::MarkDirty()
|
|||
this->colourmap = PAL_NONE;
|
||||
this->UpdateViewport(true, false);
|
||||
if (this->subtype == AIR_HELICOPTER) {
|
||||
GetRotorImage(this, EIT_ON_MAP, &this->Next()->Next()->sprite_seq);
|
||||
GetRotorImage(this, EIT_ON_MAP, &this->Next()->Next()->sprite_cache.sprite_seq);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -439,7 +439,7 @@ void AddArticulatedParts(Vehicle *first)
|
|||
v->max_age = 0;
|
||||
v->engine_type = engine_type;
|
||||
v->value = 0;
|
||||
v->sprite_seq.Set(SPR_IMG_QUERY);
|
||||
v->sprite_cache.sprite_seq.Set(SPR_IMG_QUERY);
|
||||
v->random_bits = VehicleRandomBits();
|
||||
|
||||
if (flip_image) v->spritenum++;
|
||||
|
|
|
@ -110,7 +110,7 @@ void DisasterVehicle::UpdateImage()
|
|||
{
|
||||
SpriteID img = this->image_override;
|
||||
if (img == 0) img = _disaster_images[this->subtype][this->direction];
|
||||
this->sprite_seq.Set(img);
|
||||
this->sprite_cache.sprite_seq.Set(img);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -498,7 +498,7 @@ static bool DisasterTick_Helicopter_Rotors(DisasterVehicle *v)
|
|||
v->tick_counter++;
|
||||
if (HasBit(v->tick_counter, 0)) return true;
|
||||
|
||||
SpriteID &cur_image = v->sprite_seq.seq[0].sprite;
|
||||
SpriteID &cur_image = v->sprite_cache.sprite_seq.seq[0].sprite;
|
||||
if (++cur_image > SPR_ROTOR_MOVING_3) cur_image = SPR_ROTOR_MOVING_1;
|
||||
|
||||
v->UpdatePositionAndViewport();
|
||||
|
|
|
@ -28,8 +28,8 @@
|
|||
*/
|
||||
static bool IncrementSprite(EffectVehicle *v, SpriteID last)
|
||||
{
|
||||
if (v->sprite_seq.seq[0].sprite != last) {
|
||||
v->sprite_seq.seq[0].sprite++;
|
||||
if (v->sprite_cache.sprite_seq.seq[0].sprite != last) {
|
||||
v->sprite_cache.sprite_seq.seq[0].sprite++;
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
|
@ -39,7 +39,7 @@ static bool IncrementSprite(EffectVehicle *v, SpriteID last)
|
|||
static void ChimneySmokeInit(EffectVehicle *v)
|
||||
{
|
||||
uint32 r = Random();
|
||||
v->sprite_seq.Set(SPR_CHIMNEY_SMOKE_0 + GB(r, 0, 3));
|
||||
v->sprite_cache.sprite_seq.Set(SPR_CHIMNEY_SMOKE_0 + GB(r, 0, 3));
|
||||
v->progress = GB(r, 16, 3);
|
||||
}
|
||||
|
||||
|
@ -55,7 +55,7 @@ static bool ChimneySmokeTick(EffectVehicle *v)
|
|||
}
|
||||
|
||||
if (!IncrementSprite(v, SPR_CHIMNEY_SMOKE_7)) {
|
||||
v->sprite_seq.Set(SPR_CHIMNEY_SMOKE_0);
|
||||
v->sprite_cache.sprite_seq.Set(SPR_CHIMNEY_SMOKE_0);
|
||||
}
|
||||
v->progress = 7;
|
||||
v->UpdatePositionAndViewport();
|
||||
|
@ -66,7 +66,7 @@ static bool ChimneySmokeTick(EffectVehicle *v)
|
|||
|
||||
static void SteamSmokeInit(EffectVehicle *v)
|
||||
{
|
||||
v->sprite_seq.Set(SPR_STEAM_SMOKE_0);
|
||||
v->sprite_cache.sprite_seq.Set(SPR_STEAM_SMOKE_0);
|
||||
v->progress = 12;
|
||||
}
|
||||
|
||||
|
@ -96,7 +96,7 @@ static bool SteamSmokeTick(EffectVehicle *v)
|
|||
|
||||
static void DieselSmokeInit(EffectVehicle *v)
|
||||
{
|
||||
v->sprite_seq.Set(SPR_DIESEL_SMOKE_0);
|
||||
v->sprite_cache.sprite_seq.Set(SPR_DIESEL_SMOKE_0);
|
||||
v->progress = 0;
|
||||
}
|
||||
|
||||
|
@ -120,7 +120,7 @@ static bool DieselSmokeTick(EffectVehicle *v)
|
|||
|
||||
static void ElectricSparkInit(EffectVehicle *v)
|
||||
{
|
||||
v->sprite_seq.Set(SPR_ELECTRIC_SPARK_0);
|
||||
v->sprite_cache.sprite_seq.Set(SPR_ELECTRIC_SPARK_0);
|
||||
v->progress = 1;
|
||||
}
|
||||
|
||||
|
@ -143,7 +143,7 @@ static bool ElectricSparkTick(EffectVehicle *v)
|
|||
|
||||
static void SmokeInit(EffectVehicle *v)
|
||||
{
|
||||
v->sprite_seq.Set(SPR_SMOKE_0);
|
||||
v->sprite_cache.sprite_seq.Set(SPR_SMOKE_0);
|
||||
v->progress = 12;
|
||||
}
|
||||
|
||||
|
@ -173,7 +173,7 @@ static bool SmokeTick(EffectVehicle *v)
|
|||
|
||||
static void ExplosionLargeInit(EffectVehicle *v)
|
||||
{
|
||||
v->sprite_seq.Set(SPR_EXPLOSION_LARGE_0);
|
||||
v->sprite_cache.sprite_seq.Set(SPR_EXPLOSION_LARGE_0);
|
||||
v->progress = 0;
|
||||
}
|
||||
|
||||
|
@ -193,7 +193,7 @@ static bool ExplosionLargeTick(EffectVehicle *v)
|
|||
|
||||
static void BreakdownSmokeInit(EffectVehicle *v)
|
||||
{
|
||||
v->sprite_seq.Set(SPR_BREAKDOWN_SMOKE_0);
|
||||
v->sprite_cache.sprite_seq.Set(SPR_BREAKDOWN_SMOKE_0);
|
||||
v->progress = 0;
|
||||
}
|
||||
|
||||
|
@ -202,7 +202,7 @@ static bool BreakdownSmokeTick(EffectVehicle *v)
|
|||
v->progress++;
|
||||
if ((v->progress & 7) == 0) {
|
||||
if (!IncrementSprite(v, SPR_BREAKDOWN_SMOKE_3)) {
|
||||
v->sprite_seq.Set(SPR_BREAKDOWN_SMOKE_0);
|
||||
v->sprite_cache.sprite_seq.Set(SPR_BREAKDOWN_SMOKE_0);
|
||||
}
|
||||
v->UpdatePositionAndViewport();
|
||||
}
|
||||
|
@ -218,7 +218,7 @@ static bool BreakdownSmokeTick(EffectVehicle *v)
|
|||
|
||||
static void ExplosionSmallInit(EffectVehicle *v)
|
||||
{
|
||||
v->sprite_seq.Set(SPR_EXPLOSION_SMALL_0);
|
||||
v->sprite_cache.sprite_seq.Set(SPR_EXPLOSION_SMALL_0);
|
||||
v->progress = 0;
|
||||
}
|
||||
|
||||
|
@ -238,7 +238,7 @@ static bool ExplosionSmallTick(EffectVehicle *v)
|
|||
|
||||
static void BulldozerInit(EffectVehicle *v)
|
||||
{
|
||||
v->sprite_seq.Set(SPR_BULLDOZER_NE);
|
||||
v->sprite_cache.sprite_seq.Set(SPR_BULLDOZER_NE);
|
||||
v->progress = 0;
|
||||
v->animation_state = 0;
|
||||
v->animation_substate = 0;
|
||||
|
@ -289,7 +289,7 @@ static bool BulldozerTick(EffectVehicle *v)
|
|||
if ((v->progress & 7) == 0) {
|
||||
const BulldozerMovement *b = &_bulldozer_movement[v->animation_state];
|
||||
|
||||
v->sprite_seq.Set(SPR_BULLDOZER_NE + b->image);
|
||||
v->sprite_cache.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;
|
||||
|
@ -311,7 +311,7 @@ static bool BulldozerTick(EffectVehicle *v)
|
|||
|
||||
static void BubbleInit(EffectVehicle *v)
|
||||
{
|
||||
v->sprite_seq.Set(SPR_BUBBLE_GENERATE_0);
|
||||
v->sprite_cache.sprite_seq.Set(SPR_BUBBLE_GENERATE_0);
|
||||
v->spritenum = 0;
|
||||
v->progress = 0;
|
||||
}
|
||||
|
@ -474,8 +474,8 @@ static bool BubbleTick(EffectVehicle *v)
|
|||
if ((v->progress & 3) != 0) return true;
|
||||
|
||||
if (v->spritenum == 0) {
|
||||
v->sprite_seq.seq[0].sprite++;
|
||||
if (v->sprite_seq.seq[0].sprite < SPR_BUBBLE_GENERATE_3) {
|
||||
v->sprite_cache.sprite_seq.seq[0].sprite++;
|
||||
if (v->sprite_cache.sprite_seq.seq[0].sprite < SPR_BUBBLE_GENERATE_3) {
|
||||
v->UpdatePositionAndViewport();
|
||||
return true;
|
||||
}
|
||||
|
@ -520,7 +520,7 @@ static bool BubbleTick(EffectVehicle *v)
|
|||
v->x_pos += b->x;
|
||||
v->y_pos += b->y;
|
||||
v->z_pos += b->z;
|
||||
v->sprite_seq.Set(SPR_BUBBLE_0 + b->image);
|
||||
v->sprite_cache.sprite_seq.Set(SPR_BUBBLE_0 + b->image);
|
||||
|
||||
v->UpdatePositionAndViewport();
|
||||
|
||||
|
|
|
@ -301,7 +301,7 @@ CommandCost CmdBuildRoadVehicle(TileIndex tile, DoCommandFlag flags, const Engin
|
|||
v->date_of_last_service = _date;
|
||||
v->build_year = _cur_year;
|
||||
|
||||
v->sprite_seq.Set(SPR_IMG_QUERY);
|
||||
v->sprite_cache.sprite_seq.Set(SPR_IMG_QUERY);
|
||||
v->random_bits = VehicleRandomBits();
|
||||
v->SetFrontEngine();
|
||||
|
||||
|
|
|
@ -1153,7 +1153,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, sprite_seq.seq[0].sprite ),
|
||||
OCL_SVAR( OC_FILE_U16 | OC_VAR_U32, Vehicle, sprite_cache.sprite_seq.seq[0].sprite ),
|
||||
|
||||
OCL_NULL( 8 ), ///< Vehicle sprite box, calculated automatically
|
||||
|
||||
|
@ -1246,7 +1246,7 @@ bool LoadOldVehicle(LoadgameState *ls, int num)
|
|||
if (v == nullptr) continue;
|
||||
v->refit_cap = v->cargo_cap;
|
||||
|
||||
SpriteID sprite = v->sprite_seq.seq[0].sprite;
|
||||
SpriteID sprite = v->sprite_cache.sprite_seq.seq[0].sprite;
|
||||
/* no need to override other sprites */
|
||||
if (IsInsideMM(sprite, 1460, 1465)) {
|
||||
sprite += 580; // aircraft smoke puff
|
||||
|
@ -1257,7 +1257,7 @@ bool LoadOldVehicle(LoadgameState *ls, int num)
|
|||
} else if (IsInsideMM(sprite, 2516, 2539)) {
|
||||
sprite += 1385; // rotor or disaster-related vehicles
|
||||
}
|
||||
v->sprite_seq.seq[0].sprite = sprite;
|
||||
v->sprite_cache.sprite_seq.seq[0].sprite = sprite;
|
||||
|
||||
switch (v->type) {
|
||||
case VEH_TRAIN: {
|
||||
|
|
|
@ -445,21 +445,21 @@ void AfterLoadVehicles(bool part_of_load)
|
|||
case VEH_ROAD:
|
||||
case VEH_TRAIN:
|
||||
case VEH_SHIP:
|
||||
v->GetImage(v->direction, EIT_ON_MAP, &v->sprite_seq);
|
||||
v->GetImage(v->direction, EIT_ON_MAP, &v->sprite_cache.sprite_seq);
|
||||
break;
|
||||
|
||||
case VEH_AIRCRAFT:
|
||||
if (Aircraft::From(v)->IsNormalAircraft()) {
|
||||
v->GetImage(v->direction, EIT_ON_MAP, &v->sprite_seq);
|
||||
v->GetImage(v->direction, EIT_ON_MAP, &v->sprite_cache.sprite_seq);
|
||||
|
||||
/* The plane's shadow will have the same image as the plane, but no colour */
|
||||
Vehicle *shadow = v->Next();
|
||||
shadow->sprite_seq.CopyWithoutPalette(v->sprite_seq);
|
||||
shadow->sprite_cache.sprite_seq.CopyWithoutPalette(v->sprite_cache.sprite_seq);
|
||||
|
||||
/* In the case of a helicopter we will update the rotor sprites */
|
||||
if (v->subtype == AIR_HELICOPTER) {
|
||||
Vehicle *rotor = shadow->Next();
|
||||
GetRotorImage(Aircraft::From(v), EIT_ON_MAP, &rotor->sprite_seq);
|
||||
GetRotorImage(Aircraft::From(v), EIT_ON_MAP, &rotor->sprite_cache.sprite_seq);
|
||||
}
|
||||
|
||||
UpdateAircraftCache(Aircraft::From(v), true);
|
||||
|
@ -808,7 +808,7 @@ const SaveLoad *GetVehicleDescription(VehicleType vt)
|
|||
SLE_CONDVAR(Vehicle, z_pos, SLE_FILE_U8 | SLE_VAR_I32, SL_MIN_VERSION, SLV_164),
|
||||
SLE_CONDVAR(Vehicle, z_pos, SLE_INT32, SLV_164, SL_MAX_VERSION),
|
||||
|
||||
SLE_VAR(Vehicle, sprite_seq.seq[0].sprite, SLE_FILE_U16 | SLE_VAR_U32),
|
||||
SLE_VAR(Vehicle, sprite_cache.sprite_seq.seq[0].sprite, SLE_FILE_U16 | SLE_VAR_U32),
|
||||
SLE_CONDNULL(5, SL_MIN_VERSION, SLV_59),
|
||||
SLE_VAR(Vehicle, progress, SLE_UINT8),
|
||||
SLE_VAR(Vehicle, vehstatus, SLE_UINT8),
|
||||
|
@ -848,7 +848,7 @@ const SaveLoad *GetVehicleDescription(VehicleType vt)
|
|||
SLE_CONDVAR(Vehicle, current_order.dest, SLE_FILE_U8 | SLE_VAR_U16, SL_MIN_VERSION, SLV_5),
|
||||
SLE_CONDVAR(Vehicle, current_order.dest, SLE_UINT16, SLV_5, SL_MAX_VERSION),
|
||||
|
||||
SLE_VAR(Vehicle, sprite_seq.seq[0].sprite, SLE_FILE_U16 | SLE_VAR_U32),
|
||||
SLE_VAR(Vehicle, sprite_cache.sprite_seq.seq[0].sprite, SLE_FILE_U16 | SLE_VAR_U32),
|
||||
SLE_CONDVAR(Vehicle, age, SLE_FILE_U16 | SLE_VAR_I32, SL_MIN_VERSION, SLV_31),
|
||||
SLE_CONDVAR(Vehicle, age, SLE_INT32, SLV_31, SL_MAX_VERSION),
|
||||
SLE_VAR(Vehicle, tick_counter, SLE_UINT8),
|
||||
|
|
|
@ -864,7 +864,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->sprite_seq.Set(SPR_IMG_QUERY);
|
||||
v->sprite_cache.sprite_seq.Set(SPR_IMG_QUERY);
|
||||
v->random_bits = VehicleRandomBits();
|
||||
|
||||
v->UpdateCache();
|
||||
|
|
|
@ -624,7 +624,7 @@ static CommandCost CmdBuildRailWagon(TileIndex tile, DoCommandFlag flags, const
|
|||
|
||||
v->date_of_last_service = _date;
|
||||
v->build_year = _cur_year;
|
||||
v->sprite_seq.Set(SPR_IMG_QUERY);
|
||||
v->sprite_cache.sprite_seq.Set(SPR_IMG_QUERY);
|
||||
v->random_bits = VehicleRandomBits();
|
||||
|
||||
v->group_id = DEFAULT_GROUP;
|
||||
|
@ -690,7 +690,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->sprite_seq.Set(SPR_IMG_QUERY);
|
||||
u->sprite_cache.sprite_seq.Set(SPR_IMG_QUERY);
|
||||
u->random_bits = VehicleRandomBits();
|
||||
v->SetMultiheaded();
|
||||
u->SetMultiheaded();
|
||||
|
@ -756,7 +756,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->sprite_seq.Set(SPR_IMG_QUERY);
|
||||
v->sprite_cache.sprite_seq.Set(SPR_IMG_QUERY);
|
||||
v->random_bits = VehicleRandomBits();
|
||||
|
||||
if (e->flags & ENGINE_EXCLUSIVE_PREVIEW) SetBit(v->vehicle_flags, VF_BUILT_AS_PROTOTYPE);
|
||||
|
|
|
@ -1094,25 +1094,19 @@ static void DoDrawVehicle(const Vehicle *v)
|
|||
/*
|
||||
* If the vehicle sprite was not updated despite further viewport changes, we need
|
||||
* to update it before drawing.
|
||||
*
|
||||
* I'm not keen on casting to mutable - it's the approach JGR uses in JGRPP but I
|
||||
* wonder if there's a cleaner option (even though we can only take the decision
|
||||
* whether to update once we already know the vehicle is going to appear in a
|
||||
* viewport)
|
||||
*/
|
||||
if (v->rstate.sprite_has_viewport_changes) {
|
||||
Vehicle* v_mutable = const_cast<Vehicle*>(v);
|
||||
if (v->sprite_cache.sprite_has_viewport_changes) {
|
||||
VehicleSpriteSeq seq;
|
||||
v_mutable->GetImage(v_mutable->direction, EIT_ON_MAP, &seq);
|
||||
v_mutable->sprite_seq = seq;
|
||||
v_mutable->rstate.sprite_has_viewport_changes = false;
|
||||
v->GetImage(v->direction, EIT_ON_MAP, &seq);
|
||||
v->sprite_cache.sprite_seq = seq;
|
||||
v->sprite_cache.sprite_has_viewport_changes = false;
|
||||
}
|
||||
|
||||
StartSpriteCombine();
|
||||
for (uint i = 0; i < v->sprite_seq.count; ++i) {
|
||||
PaletteID pal2 = v->sprite_seq.seq[i].pal;
|
||||
for (uint i = 0; i < v->sprite_cache.sprite_seq.count; ++i) {
|
||||
PaletteID pal2 = v->sprite_cache.sprite_seq.seq[i].pal;
|
||||
if (!pal2 || (v->vehstatus & VS_CRASHED)) pal2 = pal;
|
||||
AddSortableSpriteToDraw(v->sprite_seq.seq[i].sprite, pal2, v->x_pos + v->x_offs, v->y_pos + v->y_offs,
|
||||
AddSortableSpriteToDraw(v->sprite_cache.sprite_seq.seq[i].sprite, pal2, 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);
|
||||
}
|
||||
EndSpriteCombine();
|
||||
|
@ -1175,10 +1169,10 @@ void ViewportAddVehicles(DrawPixelInfo *dpi)
|
|||
* are part of a newgrf vehicle set which changes bounding boxes within a
|
||||
* single vehicle direction.
|
||||
*
|
||||
* TODO: is there a cleaner solution than casting to a mutable type?
|
||||
* TODO: this will consider too many false positives, use the bounding box
|
||||
* information or something which better narrows down the candidates.
|
||||
*/
|
||||
Vehicle* v_mutable = const_cast<Vehicle*>(v);
|
||||
v_mutable->rstate.is_viewport_candidate = true;
|
||||
v->sprite_cache.is_viewport_candidate = true;
|
||||
}
|
||||
|
||||
v = v->hash_viewport_next;
|
||||
|
@ -1605,7 +1599,7 @@ void Vehicle::UpdatePosition()
|
|||
void Vehicle::UpdateViewport(bool dirty)
|
||||
{
|
||||
Rect new_coord;
|
||||
this->sprite_seq.GetBounds(&new_coord);
|
||||
this->sprite_cache.sprite_seq.GetBounds(&new_coord);
|
||||
|
||||
Point pt = RemapCoords(this->x_pos + this->x_offs, this->y_pos + this->y_offs, this->z_pos);
|
||||
new_coord.left += pt.x;
|
||||
|
|
|
@ -124,13 +124,6 @@ struct VehicleCache {
|
|||
byte cached_vis_effect; ///< Visual effect to show (see #VisualEffect)
|
||||
};
|
||||
|
||||
/** Values for controlling how a vehicle's sprites are refreshed */
|
||||
struct VehicleSpriteRefreshState {
|
||||
Direction last_direction; ///< Last direction we obtained sprites for
|
||||
bool is_viewport_candidate; ///< The vehicle has been in the hash for a shown viewport recently
|
||||
bool sprite_has_viewport_changes; ///< There have been viewport changes since the sprite was last updated
|
||||
};
|
||||
|
||||
/** Sprite sequence for a vehicle part. */
|
||||
struct VehicleSpriteSeq {
|
||||
PalSpriteID seq[4];
|
||||
|
@ -188,6 +181,17 @@ struct VehicleSpriteSeq {
|
|||
void Draw(int x, int y, PaletteID default_pal, bool force_pal) const;
|
||||
};
|
||||
|
||||
/**
|
||||
* Cache for vehicle sprites and values relating to whether they should be updated before drawing,
|
||||
* or calculating the viewport.
|
||||
*/
|
||||
struct MutableSpriteCache {
|
||||
Direction last_direction; ///< Last direction we obtained sprites for
|
||||
mutable bool is_viewport_candidate; ///< The vehicle has been in the hash for a shown viewport recently
|
||||
mutable bool sprite_has_viewport_changes; ///< There have been viewport changes since the sprite was last updated
|
||||
mutable VehicleSpriteSeq sprite_seq; ///< Vehicle appearance.
|
||||
};
|
||||
|
||||
/** A vehicle pool for a little over 1 million vehicles. */
|
||||
typedef Pool<Vehicle, VehicleID, 512, 0xFF000> VehiclePool;
|
||||
extern VehiclePool _vehicle_pool;
|
||||
|
@ -282,7 +286,6 @@ public:
|
|||
* 0xff == reserved for another custom sprite
|
||||
*/
|
||||
byte spritenum;
|
||||
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
|
||||
|
@ -334,7 +337,7 @@ public:
|
|||
NewGRFCache grf_cache; ///< Cache of often used calculated NewGRF values
|
||||
VehicleCache vcache; ///< Cache of often used vehicle values.
|
||||
|
||||
VehicleSpriteRefreshState rstate; ///< Values relating to whether sprites should be refreshed, see #VehicleSpriteRefreshState
|
||||
MutableSpriteCache sprite_cache; ///< Cache of sprites and values related to recalculating them, see #MutableSpriteCache
|
||||
|
||||
Vehicle(VehicleType type = VEH_INVALID);
|
||||
|
||||
|
@ -1044,7 +1047,7 @@ struct SpecializedVehicle : public Vehicle {
|
|||
*/
|
||||
inline SpecializedVehicle<T, Type>() : Vehicle(Type)
|
||||
{
|
||||
this->sprite_seq.count = 1;
|
||||
this->sprite_cache.sprite_seq.count = 1;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1193,24 +1196,24 @@ struct SpecializedVehicle : public Vehicle {
|
|||
* there won't be enough change in bounding box or offsets to need
|
||||
* to resolve a new sprite.
|
||||
*/
|
||||
if (this->direction != this->rstate.last_direction || this->rstate.is_viewport_candidate) {
|
||||
if (this->direction != this->sprite_cache.last_direction || this->sprite_cache.is_viewport_candidate) {
|
||||
VehicleSpriteSeq seq;
|
||||
|
||||
((T*)this)->T::GetImage(this->direction, EIT_ON_MAP, &seq);
|
||||
if (this->sprite_seq != seq) {
|
||||
if (this->sprite_cache.sprite_seq != seq) {
|
||||
sprite_has_changed = true;
|
||||
this->sprite_seq = seq;
|
||||
this->sprite_cache.sprite_seq = seq;
|
||||
}
|
||||
|
||||
this->rstate.last_direction = this->direction;
|
||||
this->rstate.is_viewport_candidate = false;
|
||||
this->rstate.sprite_has_viewport_changes = false;
|
||||
this->sprite_cache.last_direction = this->direction;
|
||||
this->sprite_cache.is_viewport_candidate = false;
|
||||
this->sprite_cache.sprite_has_viewport_changes = false;
|
||||
} else {
|
||||
/*
|
||||
* Changes could still be relevant when we render the vehicle even if
|
||||
* they don't alter the bounding box
|
||||
*/
|
||||
this->rstate.sprite_has_viewport_changes = true;
|
||||
this->sprite_cache.sprite_has_viewport_changes = true;
|
||||
}
|
||||
|
||||
if (force_update || sprite_has_changed) {
|
||||
|
|
Loading…
Reference in New Issue