Changeset - r24570:4fa1d23595bf
[Not reviewed]
master
0 11 0
Matt Kimber - 4 years ago 2021-01-03 13:32:58
github@mattkimber.org.uk
Codechange: create MutableSpriteCache to remove the need to cast Vehicle to a mutable type in render methods
11 files changed with 74 insertions and 77 deletions:
0 comments (0 inline, 0 general)
src/aircraft_cmd.cpp
Show inline comments
 
@@ -338,14 +338,14 @@ CommandCost CmdBuildAircraft(TileIndex t
 

	
 
		v->SetServiceInterval(Company::Get(_current_company)->settings.vehicle.servint_aircraft);
 

	
 
		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();
 

	
 
		v->vehicle_flags = 0;
 
		if (e->flags & ENGINE_EXCLUSIVE_PREVIEW) SetBit(v->vehicle_flags, VF_BUILT_AS_PROTOTYPE);
 
@@ -371,13 +371,13 @@ CommandCost CmdBuildAircraft(TileIndex t
 
			w->x_pos = v->x_pos;
 
			w->y_pos = v->y_pos;
 
			w->z_pos = v->z_pos + ROTOR_Z_OFFSET;
 
			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;
 
			w->UpdateDeltaXY();
 

	
 
			u->SetNext(w);
 
@@ -494,23 +494,23 @@ static void HelicopterTickHandler(Aircra
 
	int spd = u->cur_speed >> 4;
 

	
 
	VehicleSpriteSeq seq;
 
	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++;
 
		if (u->state > HRS_ROTOR_MOVING_3) u->state = HRS_ROTOR_MOVING_1;
 
		GetRotorImage(v, EIT_ON_MAP, &seq);
 
	} else {
 
		return;
 
	}
 

	
 
	u->sprite_seq = seq;
 
	u->sprite_cache.sprite_seq = seq;
 

	
 
	u->UpdatePositionAndViewport();
 
}
 

	
 
/**
 
 * Set aircraft position.
 
@@ -525,25 +525,25 @@ void SetAircraftPosition(Aircraft *v, in
 
	v->y_pos = y;
 
	v->z_pos = 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();
 

	
 
	int safe_x = Clamp(x, 0, MapMaxX() * TILE_SIZE);
 
	int safe_y = Clamp(y - 1, 0, MapMaxY() * TILE_SIZE);
 
	u->x_pos = x;
 
	u->y_pos = y - ((v->z_pos - GetSlopePixelZ(safe_x, safe_y)) >> 3);
 

	
 
	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();
 

	
 
	u = u->Next();
 
	if (u != nullptr) {
 
		u->x_pos = x;
 
@@ -1275,13 +1275,13 @@ TileIndex Aircraft::GetOrderStationLocat
 

	
 
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);
 
	}
 
}
 

	
 

	
 
uint Aircraft::Crash(bool flooded)
 
{
src/articulated_vehicles.cpp
Show inline comments
 
@@ -436,13 +436,13 @@ void AddArticulatedParts(Vehicle *first)
 
		v->vehstatus = first->vehstatus & ~VS_STOPPED;
 

	
 
		v->cargo_subtype = 0;
 
		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++;
 

	
 
		v->UpdatePosition();
 
	}
src/disaster_vehicle.cpp
Show inline comments
 
@@ -107,13 +107,13 @@ static const SpriteID * const _disaster_
 
};
 

	
 
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);
 
}
 

	
 
/**
 
 * Construct the disaster vehicle.
 
 * @param x         The X coordinate.
 
 * @param y         The Y coordinate.
 
@@ -495,13 +495,13 @@ static bool DisasterTick_Helicopter(Disa
 
/** Helicopter rotor blades; keep these spinning */
 
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();
 

	
 
	return true;
 
}
src/effectvehicle.cpp
Show inline comments
 
@@ -25,24 +25,24 @@
 
 * @param v Vehicle to increment sprite of.
 
 * @param last Last sprite of animation.
 
 * @return true if the sprite was incremented, false if the end was reached.
 
 */
 
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;
 
	}
 
}
 

	
 
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);
 
}
 

	
 
static bool ChimneySmokeTick(EffectVehicle *v)
 
{
 
	if (v->progress > 0) {
 
@@ -52,24 +52,24 @@ static bool ChimneySmokeTick(EffectVehic
 
		if (!IsTileType(tile, MP_INDUSTRY)) {
 
			delete v;
 
			return false;
 
		}
 

	
 
		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();
 
	}
 

	
 
	return true;
 
}
 

	
 
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;
 
}
 

	
 
static bool SteamSmokeTick(EffectVehicle *v)
 
{
 
	bool moved = false;
 
@@ -93,13 +93,13 @@ static bool SteamSmokeTick(EffectVehicle
 

	
 
	return true;
 
}
 

	
 
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;
 
}
 

	
 
static bool DieselSmokeTick(EffectVehicle *v)
 
{
 
	v->progress++;
 
@@ -117,13 +117,13 @@ static bool DieselSmokeTick(EffectVehicl
 

	
 
	return true;
 
}
 

	
 
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;
 
}
 

	
 
static bool ElectricSparkTick(EffectVehicle *v)
 
{
 
	if (v->progress < 2) {
 
@@ -140,13 +140,13 @@ static bool ElectricSparkTick(EffectVehi
 

	
 
	return true;
 
}
 

	
 
static void SmokeInit(EffectVehicle *v)
 
{
 
	v->sprite_seq.Set(SPR_SMOKE_0);
 
	v->sprite_cache.sprite_seq.Set(SPR_SMOKE_0);
 
	v->progress = 12;
 
}
 

	
 
static bool SmokeTick(EffectVehicle *v)
 
{
 
	bool moved = false;
 
@@ -170,13 +170,13 @@ static bool SmokeTick(EffectVehicle *v)
 

	
 
	return true;
 
}
 

	
 
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;
 
}
 

	
 
static bool ExplosionLargeTick(EffectVehicle *v)
 
{
 
	v->progress++;
 
@@ -190,22 +190,22 @@ static bool ExplosionLargeTick(EffectVeh
 

	
 
	return true;
 
}
 

	
 
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;
 
}
 

	
 
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();
 
	}
 

	
 
	v->animation_state--;
 
	if (v->animation_state == 0) {
 
@@ -215,13 +215,13 @@ static bool BreakdownSmokeTick(EffectVeh
 

	
 
	return true;
 
}
 

	
 
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;
 
}
 

	
 
static bool ExplosionSmallTick(EffectVehicle *v)
 
{
 
	v->progress++;
 
@@ -235,13 +235,13 @@ static bool ExplosionSmallTick(EffectVeh
 

	
 
	return true;
 
}
 

	
 
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;
 
}
 

	
 
struct BulldozerMovement {
 
@@ -286,13 +286,13 @@ static const struct {
 
static bool BulldozerTick(EffectVehicle *v)
 
{
 
	v->progress++;
 
	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;
 

	
 
		v->animation_substate++;
 
		if (v->animation_substate >= b->duration) {
 
@@ -308,13 +308,13 @@ static bool BulldozerTick(EffectVehicle 
 

	
 
	return true;
 
}
 

	
 
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;
 
}
 

	
 
struct BubbleMovement {
 
	int8 x:4;
 
@@ -471,14 +471,14 @@ static bool BubbleTick(EffectVehicle *v)
 
	uint anim_state;
 

	
 
	v->progress++;
 
	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;
 
		}
 
		if (v->animation_substate != 0) {
 
			v->spritenum = GB(Random(), 0, 2) + 1;
 
		} else {
 
@@ -517,13 +517,13 @@ static bool BubbleTick(EffectVehicle *v)
 
	v->animation_state = anim_state;
 
	b = &_bubble_movement[v->spritenum - 1][anim_state];
 

	
 
	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();
 

	
 
	return true;
 
}
 

	
src/roadveh_cmd.cpp
Show inline comments
 
@@ -298,13 +298,13 @@ CommandCost CmdBuildRoadVehicle(TileInde
 

	
 
		v->SetServiceInterval(Company::Get(v->owner)->settings.vehicle.servint_roadveh);
 

	
 
		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();
 

	
 
		v->roadtype = rt;
 
		v->compatible_roadtypes = rti->powered_roadtypes;
 
		v->gcache.cached_veh_length = VEHICLE_LENGTH;
src/saveload/oldloader_sl.cpp
Show inline comments
 
@@ -1150,13 +1150,13 @@ static const OldChunks vehicle_chunk[] =
 
	OCL_NULL( 2 ),         ///< x_offs and y_offs, calculated automatically
 
	OCL_NULL( 2 ),         ///< x_extent and y_extent, calculated automatically
 
	OCL_NULL( 1 ),         ///< z_extent, calculated automatically
 

	
 
	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
 

	
 
	OCL_SVAR( OC_FILE_U16 | OC_VAR_U8, Vehicle, vehstatus ),
 
	OCL_SVAR( OC_TTD | OC_UINT16, Vehicle, cur_speed ),
 
	OCL_SVAR( OC_TTO | OC_FILE_U8 | OC_VAR_U16, Vehicle, cur_speed ),
 
@@ -1243,24 +1243,24 @@ bool LoadOldVehicle(LoadgameState *ls, i
 
			}
 

	
 
			if (!LoadChunk(ls, v, vehicle_chunk)) return false;
 
			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
 
			} else if (IsInsideMM(sprite, 2096, 2115)) {
 
				sprite += 977; // special effects part 1
 
			} else if (IsInsideMM(sprite, 2396, 2436)) {
 
				sprite += 1305; // special effects part 2
 
			} 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: {
 
					static const byte spriteset_rail[] = {
 
						  0,   2,   4,   4,   8,  10,  12,  14,  16,  18,  20,  22,  40,  42,  44,  46,
 
						 48,  52,  54,  66,  68,  70,  72,  74,  76,  78,  80,  82,  84,  86, 120, 122,
src/saveload/vehicle_sl.cpp
Show inline comments
 
@@ -442,27 +442,27 @@ void AfterLoadVehicles(bool part_of_load
 

	
 
	for (Vehicle *v : Vehicle::Iterate()) {
 
		switch (v->type) {
 
			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);
 
				}
 
				break;
 
			default: break;
 
@@ -805,13 +805,13 @@ const SaveLoad *GetVehicleDescription(Ve
 
		 SLE_CONDVAR(Vehicle, x_pos,                 SLE_INT32,                    SLV_6, SL_MAX_VERSION),
 
		 SLE_CONDVAR(Vehicle, y_pos,                 SLE_FILE_I16 | SLE_VAR_I32,   SL_MIN_VERSION,   SLV_6),
 
		 SLE_CONDVAR(Vehicle, y_pos,                 SLE_INT32,                    SLV_6, SL_MAX_VERSION),
 
		 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),
 

	
 
		     SLE_VAR(EffectVehicle, animation_state,    SLE_UINT16),
 
		     SLE_VAR(EffectVehicle, animation_substate, SLE_UINT8),
 
@@ -845,13 +845,13 @@ const SaveLoad *GetVehicleDescription(Ve
 
		SLE_CONDNULL(5,                                                            SL_MIN_VERSION,  SLV_58),
 
		     SLE_VAR(Vehicle, owner,                 SLE_UINT8),
 
		     SLE_VAR(Vehicle, vehstatus,             SLE_UINT8),
 
		 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),
 

	
 
		 SLE_CONDVAR(DisasterVehicle, image_override,            SLE_FILE_U16 | SLE_VAR_U32,   SL_MIN_VERSION, SLV_191),
 
		 SLE_CONDVAR(DisasterVehicle, image_override,            SLE_UINT32,                 SLV_191, SL_MAX_VERSION),
src/ship_cmd.cpp
Show inline comments
 
@@ -861,13 +861,13 @@ CommandCost CmdBuildShip(TileIndex tile,
 

	
 
		v->state = TRACK_BIT_DEPOT;
 

	
 
		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();
 

	
 
		if (e->flags & ENGINE_EXCLUSIVE_PREVIEW) SetBit(v->vehicle_flags, VF_BUILT_AS_PROTOTYPE);
 
		v->SetServiceIntervalIsPercent(Company::Get(_current_company)->settings.vehicle.servint_ispercent);
src/train_cmd.cpp
Show inline comments
 
@@ -621,13 +621,13 @@ static CommandCost CmdBuildRailWagon(Til
 
		v->refit_cap = 0;
 

	
 
		v->railtype = rvi->railtype;
 

	
 
		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;
 

	
 
		AddArticulatedParts(v);
 

	
 
@@ -687,13 +687,13 @@ static void AddRearEngineToMultiheadedTr
 
	u->cargo_cap = v->cargo_cap;
 
	u->refit_cap = v->refit_cap;
 
	u->railtype = v->railtype;
 
	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();
 
	v->SetNext(u);
 
	u->UpdatePosition();
 

	
 
@@ -753,13 +753,13 @@ CommandCost CmdBuildRailVehicle(TileInde
 
		v->railtype = rvi->railtype;
 
		_new_vehicle_id = v->index;
 

	
 
		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);
 
		v->SetServiceIntervalIsPercent(Company::Get(_current_company)->settings.vehicle.servint_ispercent);
 

	
 
		v->group_id = DEFAULT_GROUP;
src/vehicle.cpp
Show inline comments
 
@@ -1091,31 +1091,25 @@ static void DoDrawVehicle(const Vehicle 
 
		if (to != TO_INVALID && (IsTransparencySet(to) || IsInvisibilitySet(to))) return;
 
	}
 

	
 
	/*
 
	 * 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();
 
}
 

	
 
/**
 
@@ -1172,16 +1166,16 @@ void ViewportAddVehicles(DrawPixelInfo *
 
					 * displayed.
 
					 *
 
					 * This reduces the chances of flicker when sprites enter the screen, if they
 
					 * 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;
 
			}
 

	
 
			if (x == xu) break;
 
@@ -1602,13 +1596,13 @@ void Vehicle::UpdatePosition()
 
 *  new coordinates.
 
 * @param dirty Mark the (new and old) coordinates of the vehicle as dirty.
 
 */
 
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;
 
	new_coord.top    += pt.y;
 
	new_coord.right  += pt.x + 2 * ZOOM_LVL_BASE;
 
	new_coord.bottom += pt.y + 2 * ZOOM_LVL_BASE;
src/vehicle_base.h
Show inline comments
 
@@ -121,19 +121,12 @@ struct VehicleCache {
 
	uint16 cached_max_speed;        ///< Maximum speed of the consist (minimum of the max speed of all vehicles in the consist).
 
	uint16 cached_cargo_age_period; ///< Number of ticks before carried cargo is aged.
 

	
 
	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];
 
	uint count;
 

	
 
	bool operator==(const VehicleSpriteSeq &other) const
 
@@ -185,12 +178,23 @@ struct VehicleSpriteSeq {
 
	}
 

	
 
	void GetBounds(Rect *bounds) const;
 
	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;
 

	
 
/* Some declarations of functions, so we can make them friendly */
 
struct SaveLoad;
 
@@ -279,13 +283,12 @@ public:
 
	/**
 
	 * currently displayed sprite index
 
	 * 0xfd == custom sprite, 0xfe == custom second head sprite
 
	 * 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
 
	int8 x_bb_offs;                     ///< x offset of vehicle bounding box
 
	int8 y_bb_offs;                     ///< y offset of vehicle bounding box
 
	int8 x_offs;                        ///< x offset for vehicle sprite
 
@@ -331,13 +334,13 @@ public:
 
	GroupID group_id;                   ///< Index of group Pool array
 
	byte subtype;                       ///< subtype (Filled with values from #AircraftSubType/#DisasterSubType/#EffectVehicleType/#GroundVehicleSubtypeFlags)
 

	
 
	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);
 

	
 
	void PreDestructor();
 
	/** We want to 'destruct' the right class. */
 
	virtual ~Vehicle();
 
@@ -1041,13 +1044,13 @@ struct SpecializedVehicle : public Vehic
 

	
 
	/**
 
	 * Set vehicle type correctly
 
	 */
 
	inline SpecializedVehicle<T, Type>() : Vehicle(Type)
 
	{
 
		this->sprite_seq.count = 1;
 
		this->sprite_cache.sprite_seq.count = 1;
 
	}
 

	
 
	/**
 
	 * Get the first vehicle in the chain
 
	 * @return first vehicle in the chain
 
	 */
 
@@ -1190,30 +1193,30 @@ struct SpecializedVehicle : public Vehic
 
		/*
 
		 * Only check for a new sprite sequence if the vehicle direction
 
		 * has changed since we last checked it, assuming that otherwise
 
		 * 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) {
 
			this->Vehicle::UpdateViewport(true);
 
		}
 
	}
0 comments (0 inline, 0 general)