From efcaefd178410c303ae17db17200c300e4379298 Mon Sep 17 00:00:00 2001 From: frosch Date: Sat, 8 Aug 2009 18:45:12 +0000 Subject: [PATCH] (svn r17121) -Fix [FS#3060]: Update vehicle position cache when the vehicle sprite changes. --- src/aircraft_cmd.cpp | 7 ++----- src/roadveh_cmd.cpp | 35 ++++++++++++----------------------- src/ship_cmd.cpp | 11 +++-------- src/train_cmd.cpp | 22 ++++++---------------- src/vehicle_base.h | 15 +++++++++++++++ 5 files changed, 38 insertions(+), 52 deletions(-) diff --git a/src/aircraft_cmd.cpp b/src/aircraft_cmd.cpp index 87f462fd07..9581f45c61 100644 --- a/src/aircraft_cmd.cpp +++ b/src/aircraft_cmd.cpp @@ -687,11 +687,9 @@ void SetAircraftPosition(Aircraft *v, int x, int y, int z) v->y_pos = y; v->z_pos = z; - v->cur_image = v->GetImage(v->direction); + v->UpdateViewport(true, false); if (v->subtype == AIR_HELICOPTER) v->Next()->Next()->cur_image = GetRotorImage(v); - VehicleMove(v, true); - Aircraft *u = v->Next(); int safe_x = Clamp(x, 0, MapMaxX() * TILE_SIZE); @@ -1278,9 +1276,8 @@ TileIndex Aircraft::GetOrderStationLocation(StationID station) void Aircraft::MarkDirty() { - this->cur_image = this->GetImage(this->direction); + this->UpdateViewport(false, false); if (this->subtype == AIR_HELICOPTER) this->Next()->Next()->cur_image = GetRotorImage(this); - MarkSingleVehicleDirty(this); } static void CrashAirplane(Aircraft *v) diff --git a/src/roadveh_cmd.cpp b/src/roadveh_cmd.cpp index 782e101004..9f160a70e3 100644 --- a/src/roadveh_cmd.cpp +++ b/src/roadveh_cmd.cpp @@ -482,8 +482,7 @@ CommandCost CmdTurnRoadVeh(TileIndex tile, DoCommandFlag flags, uint32 p1, uint3 void RoadVehicle::MarkDirty() { for (Vehicle *v = this; v != NULL; v = v->Next()) { - v->cur_image = v->GetImage(v->direction); - MarkSingleVehicleDirty(v); + v->UpdateViewport(false, false); } } @@ -532,7 +531,7 @@ static void DeleteLastRoadVeh(RoadVehicle *v) delete v; } -static byte SetRoadVehPosition(RoadVehicle *v, int x, int y) +static byte SetRoadVehPosition(RoadVehicle *v, int x, int y, bool turned) { byte new_z, old_z; @@ -544,7 +543,7 @@ static byte SetRoadVehPosition(RoadVehicle *v, int x, int y) old_z = v->z_pos; v->z_pos = new_z; - VehicleMove(v, true); + v->UpdateViewport(true, turned); return old_z; } @@ -558,9 +557,7 @@ static void RoadVehSetRandomDirection(RoadVehicle *v) uint32 r = Random(); v->direction = ChangeDir(v->direction, delta[r & 3]); - v->UpdateDeltaXY(v->direction); - v->cur_image = v->GetImage(v->direction); - SetRoadVehPosition(v, v->x_pos, v->y_pos); + SetRoadVehPosition(v, v->x_pos, v->y_pos, true); } while ((v = v->Next()) != NULL); } @@ -1255,8 +1252,7 @@ static bool RoadVehLeaveDepot(RoadVehicle *v, bool first) v->state = tdir; v->frame = RVC_DEPOT_START_FRAME; - v->UpdateDeltaXY(v->direction); - SetRoadVehPosition(v, x, y); + SetRoadVehPosition(v, x, y, true); InvalidateWindowData(WC_VEHICLE_DEPOT, v->tile); @@ -1383,8 +1379,7 @@ static bool IndividualRoadVehicleController(RoadVehicle *v, const RoadVehicle *p if (IsTileType(gp.new_tile, MP_TUNNELBRIDGE) && HasBit(VehicleEnterTile(v, gp.new_tile, gp.x, gp.y), VETS_ENTERED_WORMHOLE)) { /* Vehicle has just entered a bridge or tunnel */ - v->UpdateDeltaXY(v->direction); - SetRoadVehPosition(v, gp.x, gp.y); + SetRoadVehPosition(v, gp.x, gp.y, true); return true; } @@ -1529,8 +1524,7 @@ again: v->cur_speed -= v->cur_speed >> 2; } - v->UpdateDeltaXY(v->direction); - RoadZPosAffectSpeed(v, SetRoadVehPosition(v, x, y)); + RoadZPosAffectSpeed(v, SetRoadVehPosition(v, x, y, true)); return true; } @@ -1594,8 +1588,7 @@ again: v->cur_speed -= v->cur_speed >> 2; } - v->UpdateDeltaXY(v->direction); - RoadZPosAffectSpeed(v, SetRoadVehPosition(v, x, y)); + RoadZPosAffectSpeed(v, SetRoadVehPosition(v, x, y, true)); return true; } @@ -1634,8 +1627,7 @@ again: v->cur_speed -= (v->cur_speed >> 2); if (old_dir != v->state) { /* The vehicle is in a road stop */ - v->UpdateDeltaXY(v->direction); - SetRoadVehPosition(v, v->x_pos, v->y_pos); + SetRoadVehPosition(v, v->x_pos, v->y_pos, true); /* Note, return here means that the frame counter is not incremented * for vehicles changing direction in a road stop. This causes frames to * be repeated. (XXX) Is this intended? */ @@ -1682,7 +1674,7 @@ again: v->slot_age = 14; v->frame++; - RoadZPosAffectSpeed(v, SetRoadVehPosition(v, x, y)); + RoadZPosAffectSpeed(v, SetRoadVehPosition(v, x, y, false)); return true; } } @@ -1757,8 +1749,7 @@ again: * in a depot or entered a tunnel/bridge */ if (!HasBit(r, VETS_ENTERED_WORMHOLE)) v->frame++; - v->UpdateDeltaXY(v->direction); - RoadZPosAffectSpeed(v, SetRoadVehPosition(v, x, y)); + RoadZPosAffectSpeed(v, SetRoadVehPosition(v, x, y, true)); return true; } @@ -1816,9 +1807,7 @@ static bool RoadVehController(RoadVehicle *v) for (RoadVehicle *u = v; u != NULL; u = u->Next()) { if ((u->vehstatus & VS_HIDDEN) != 0) continue; - uint16 old_image = u->cur_image; - u->cur_image = u->GetImage(u->direction); - if (old_image != u->cur_image) VehicleMove(u, true); + u->UpdateViewport(false, false); } if (v->progress == 0) v->progress = j; diff --git a/src/ship_cmd.cpp b/src/ship_cmd.cpp index 9385259b6e..1a524f67d6 100644 --- a/src/ship_cmd.cpp +++ b/src/ship_cmd.cpp @@ -229,8 +229,7 @@ static void HandleBrokenShip(Vehicle *v) void Ship::MarkDirty() { - this->cur_image = this->GetImage(this->direction); - MarkSingleVehicleDirty(this); + this->UpdateViewport(false, false); } static void PlayShipSound(const Vehicle *v) @@ -283,9 +282,7 @@ void Ship::UpdateDeltaXY(Direction direction) void RecalcShipStuff(Vehicle *v) { - v->UpdateDeltaXY(v->direction); - v->cur_image = v->GetImage(v->direction); - v->MarkDirty(); + v->UpdateViewport(false, true); InvalidateWindow(WC_VEHICLE_DEPOT, v->tile); } @@ -708,9 +705,7 @@ static void ShipController(Ship *v) v->z_pos = GetSlopeZ(gp.x, gp.y); getout: - v->UpdateDeltaXY(dir); - v->cur_image = v->GetImage(dir); - VehicleMove(v, true); + v->UpdateViewport(true, true); return; reverse_direction: diff --git a/src/train_cmd.cpp b/src/train_cmd.cpp index 4c4f142d6b..b0cb85ff41 100644 --- a/src/train_cmd.cpp +++ b/src/train_cmd.cpp @@ -1620,13 +1620,6 @@ void Train::UpdateDeltaXY(Direction direction) this->z_extent = 6; } -static void UpdateVarsAfterSwap(Train *v) -{ - v->UpdateDeltaXY(v->direction); - v->cur_image = v->GetImage(v->direction); - VehicleMove(v, true); -} - static inline void SetLastSpeed(Train *v, int spd) { int old = v->tcache.last_speed; @@ -1714,15 +1707,15 @@ static void ReverseTrainSwapVeh(Train *v, int l, int r) SwapTrainFlags(&a->flags, &b->flags); /* update other vars */ - UpdateVarsAfterSwap(a); - UpdateVarsAfterSwap(b); + a->UpdateViewport(true, true); + b->UpdateViewport(true, true); /* call the proper EnterTile function unless we are in a wormhole */ if (a->track != TRACK_BIT_WORMHOLE) VehicleEnterTile(a, a->tile, a->x_pos, a->y_pos); if (b->track != TRACK_BIT_WORMHOLE) VehicleEnterTile(b, b->tile, b->x_pos, b->y_pos); } else { if (a->track != TRACK_BIT_DEPOT) a->direction = ReverseDir(a->direction); - UpdateVarsAfterSwap(a); + a->UpdateViewport(true, true); if (a->track != TRACK_BIT_WORMHOLE) VehicleEnterTile(a, a->tile, a->x_pos, a->y_pos); } @@ -1948,7 +1941,7 @@ static void ReverseTrainDirection(Train *v) TrainConsistChanged(v, true); /* update all images */ - for (Vehicle *u = v; u != NULL; u = u->Next()) u->cur_image = u->GetImage(u->direction); + for (Vehicle *u = v; u != NULL; u = u->Next()) u->UpdateViewport(false, false); /* update crossing we were approaching */ if (crossing != INVALID_TILE) UpdateLevelCrossing(crossing); @@ -3324,8 +3317,7 @@ void Train::MarkDirty() { Vehicle *v = this; do { - v->cur_image = v->GetImage(v->direction); - MarkSingleVehicleDirty(v); + v->UpdateViewport(false, false); } while ((v = v->Next()) != NULL); /* need to update acceleration and cached values since the goods on the train changed. */ @@ -4450,9 +4442,7 @@ static bool TrainLocoHandler(Train *v, bool mode) for (Train *u = v; u != NULL; u = u->Next()) { if ((u->vehstatus & VS_HIDDEN) != 0) continue; - uint16 old_image = u->cur_image; - u->cur_image = u->GetImage(u->direction); - if (old_image != u->cur_image) VehicleMove(u, true); + u->UpdateViewport(false, false); } if (v->progress == 0) v->progress = j; // Save unused spd for next time, if TrainController didn't set progress diff --git a/src/vehicle_base.h b/src/vehicle_base.h index 751137889e..6a72b5ead3 100644 --- a/src/vehicle_base.h +++ b/src/vehicle_base.h @@ -308,6 +308,21 @@ public: */ virtual void OnNewDay() {}; + /** + * Update vehicle sprite- and position caches + * @param moved Was the vehicle moved? + * @param turned Did the vehicle direction change? + */ + inline void UpdateViewport(bool moved, bool turned) + { + extern void VehicleMove(Vehicle *v, bool update_viewport); + + if (turned) this->UpdateDeltaXY(this->direction); + SpriteID old_image = this->cur_image; + this->cur_image = this->GetImage(this->direction); + if (moved || this->cur_image != old_image) VehicleMove(this, true); + } + /** * Returns the Trackdir on which the vehicle is currently located. * Works for trains and ships.