diff --git a/src/aircraft_cmd.cpp b/src/aircraft_cmd.cpp index f4557851e1..d52d179afc 100644 --- a/src/aircraft_cmd.cpp +++ b/src/aircraft_cmd.cpp @@ -208,8 +208,7 @@ void DrawAircraftEngine(int left, int right, int preferred_x, int y, EngineID en VehicleSpriteSeq seq; GetAircraftIcon(engine, image_type, &seq); - Rect rect; - seq.GetBounds(&rect); + Rect16 rect = seq.GetBounds(); preferred_x = Clamp(preferred_x, left - UnScaleGUI(rect.left), right - UnScaleGUI(rect.right)); @@ -238,8 +237,7 @@ void GetAircraftSpriteSize(EngineID engine, uint &width, uint &height, int &xoff VehicleSpriteSeq seq; GetAircraftIcon(engine, image_type, &seq); - Rect rect; - seq.GetBounds(&rect); + Rect16 rect = seq.GetBounds(); width = UnScaleGUI(rect.right - rect.left + 1); height = UnScaleGUI(rect.bottom - rect.top + 1); @@ -371,6 +369,7 @@ CommandCost CmdBuildAircraft(TileIndex tile, DoCommandFlag flags, const Engine * w->spritenum = 0xFF; w->subtype = AIR_ROTOR; w->sprite_seq.Set(SPR_ROTOR_STOPPED); + w->UpdateSpriteSeqBound(); w->random_bits = VehicleRandomBits(); /* Use rotor's air.state to store the rotor animation frame */ w->state = HRS_ROTOR_STOPPED; @@ -504,6 +503,7 @@ static void HelicopterTickHandler(Aircraft *v) } u->sprite_seq = seq; + u->UpdateSpriteSeqBound(); u->UpdatePositionAndViewport(); } @@ -524,7 +524,9 @@ 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); + Aircraft *rotor = v->Next()->Next(); + GetRotorImage(v, EIT_ON_MAP, &rotor->sprite_seq); + rotor->UpdateSpriteSeqBound(); } Aircraft *u = v->Next(); @@ -537,6 +539,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_seq_bounds = v->sprite_seq_bounds; u->UpdatePositionAndViewport(); @@ -1308,7 +1311,9 @@ void Aircraft::MarkDirty() this->cur_image_valid_dir = INVALID_DIR; this->UpdateViewport(true, false); if (this->subtype == AIR_HELICOPTER) { - GetRotorImage(this, EIT_ON_MAP, &this->Next()->Next()->sprite_seq); + Aircraft *rotor = this->Next()->Next(); + GetRotorImage(this, EIT_ON_MAP, &rotor->sprite_seq); + rotor->UpdateSpriteSeqBound(); } } diff --git a/src/aircraft_gui.cpp b/src/aircraft_gui.cpp index 6693b1f8ad..302a29773a 100644 --- a/src/aircraft_gui.cpp +++ b/src/aircraft_gui.cpp @@ -86,8 +86,7 @@ void DrawAircraftImage(const Vehicle *v, int left, int right, int y, VehicleID s VehicleSpriteSeq seq; v->GetImage(rtl ? DIR_E : DIR_W, image_type, &seq); - Rect rect; - seq.GetBounds(&rect); + Rect16 rect = seq.GetBounds(); int width = UnScaleGUI(rect.right - rect.left + 1); int x_offs = UnScaleGUI(rect.left); diff --git a/src/effectvehicle.cpp b/src/effectvehicle.cpp index 5921cd190e..4cc886bfbe 100644 --- a/src/effectvehicle.cpp +++ b/src/effectvehicle.cpp @@ -32,6 +32,7 @@ static bool IncrementSprite(EffectVehicle *v, SpriteID last) { if (v->sprite_seq.seq[0].sprite != last) { v->sprite_seq.seq[0].sprite++; + v->UpdateSpriteSeqBound(); return true; } else { return false; @@ -42,6 +43,7 @@ static void ChimneySmokeInit(EffectVehicle *v) { uint32 r = Random(); v->sprite_seq.Set(SPR_CHIMNEY_SMOKE_0 + GB(r, 0, 3)); + v->UpdateSpriteSeqBound(); v->progress = GB(r, 16, 3); } @@ -59,6 +61,7 @@ static bool ChimneySmokeTick(EffectVehicle *v) if (!IncrementSprite(v, SPR_CHIMNEY_SMOKE_7)) { v->sprite_seq.Set(SPR_CHIMNEY_SMOKE_0); } + v->UpdateSpriteSeqBound(); v->progress = 7; v->UpdatePositionAndViewport(); } @@ -69,6 +72,7 @@ static bool ChimneySmokeTick(EffectVehicle *v) static void SteamSmokeInit(EffectVehicle *v) { v->sprite_seq.Set(SPR_STEAM_SMOKE_0); + v->UpdateSpriteSeqBound(); v->progress = 12; } @@ -88,6 +92,7 @@ static bool SteamSmokeTick(EffectVehicle *v) delete v; return false; } + v->UpdateSpriteSeqBound(); moved = true; } @@ -99,6 +104,7 @@ static bool SteamSmokeTick(EffectVehicle *v) static void DieselSmokeInit(EffectVehicle *v) { v->sprite_seq.Set(SPR_DIESEL_SMOKE_0); + v->UpdateSpriteSeqBound(); v->progress = 0; } @@ -114,6 +120,7 @@ static bool DieselSmokeTick(EffectVehicle *v) delete v; return false; } + v->UpdateSpriteSeqBound(); v->UpdatePositionAndViewport(); } @@ -123,6 +130,7 @@ static bool DieselSmokeTick(EffectVehicle *v) static void ElectricSparkInit(EffectVehicle *v) { v->sprite_seq.Set(SPR_ELECTRIC_SPARK_0); + v->UpdateSpriteSeqBound(); v->progress = 1; } @@ -137,6 +145,7 @@ static bool ElectricSparkTick(EffectVehicle *v) delete v; return false; } + v->UpdateSpriteSeqBound(); v->UpdatePositionAndViewport(); } @@ -146,6 +155,7 @@ static bool ElectricSparkTick(EffectVehicle *v) static void SmokeInit(EffectVehicle *v) { v->sprite_seq.Set(SPR_SMOKE_0); + v->UpdateSpriteSeqBound(); v->progress = 12; } @@ -165,6 +175,7 @@ static bool SmokeTick(EffectVehicle *v) delete v; return false; } + v->UpdateSpriteSeqBound(); moved = true; } @@ -176,6 +187,7 @@ static bool SmokeTick(EffectVehicle *v) static void ExplosionLargeInit(EffectVehicle *v) { v->sprite_seq.Set(SPR_EXPLOSION_LARGE_0); + v->UpdateSpriteSeqBound(); v->progress = 0; } @@ -187,6 +199,7 @@ static bool ExplosionLargeTick(EffectVehicle *v) delete v; return false; } + v->UpdateSpriteSeqBound(); v->UpdatePositionAndViewport(); } @@ -196,6 +209,7 @@ static bool ExplosionLargeTick(EffectVehicle *v) static void BreakdownSmokeInit(EffectVehicle *v) { v->sprite_seq.Set(SPR_BREAKDOWN_SMOKE_0); + v->UpdateSpriteSeqBound(); v->progress = 0; } @@ -206,6 +220,7 @@ static bool BreakdownSmokeTick(EffectVehicle *v) if (!IncrementSprite(v, SPR_BREAKDOWN_SMOKE_3)) { v->sprite_seq.Set(SPR_BREAKDOWN_SMOKE_0); } + v->UpdateSpriteSeqBound(); v->UpdatePositionAndViewport(); } @@ -221,6 +236,7 @@ static bool BreakdownSmokeTick(EffectVehicle *v) static void ExplosionSmallInit(EffectVehicle *v) { v->sprite_seq.Set(SPR_EXPLOSION_SMALL_0); + v->UpdateSpriteSeqBound(); v->progress = 0; } @@ -232,6 +248,7 @@ static bool ExplosionSmallTick(EffectVehicle *v) delete v; return false; } + v->UpdateSpriteSeqBound(); v->UpdatePositionAndViewport(); } @@ -241,6 +258,7 @@ static bool ExplosionSmallTick(EffectVehicle *v) static void BulldozerInit(EffectVehicle *v) { v->sprite_seq.Set(SPR_BULLDOZER_NE); + v->UpdateSpriteSeqBound(); v->progress = 0; v->animation_state = 0; v->animation_substate = 0; @@ -292,6 +310,7 @@ static bool BulldozerTick(EffectVehicle *v) const BulldozerMovement *b = &_bulldozer_movement[v->animation_state]; v->sprite_seq.Set(SPR_BULLDOZER_NE + b->image); + v->UpdateSpriteSeqBound(); v->x_pos += _inc_by_dir[b->direction].x; v->y_pos += _inc_by_dir[b->direction].y; @@ -314,6 +333,7 @@ static bool BulldozerTick(EffectVehicle *v) static void BubbleInit(EffectVehicle *v) { v->sprite_seq.Set(SPR_BUBBLE_GENERATE_0); + v->UpdateSpriteSeqBound(); v->spritenum = 0; v->progress = 0; } @@ -477,6 +497,7 @@ static bool BubbleTick(EffectVehicle *v) if (v->spritenum == 0) { v->sprite_seq.seq[0].sprite++; + v->UpdateSpriteSeqBound(); if (v->sprite_seq.seq[0].sprite < SPR_BUBBLE_GENERATE_3) { v->UpdatePositionAndViewport(); return true; @@ -523,6 +544,7 @@ static bool BubbleTick(EffectVehicle *v) v->y_pos += b->y; v->z_pos += b->z; v->sprite_seq.Set(SPR_BUBBLE_0 + b->image); + v->UpdateSpriteSeqBound(); v->UpdatePositionAndViewport(); diff --git a/src/roadveh_cmd.cpp b/src/roadveh_cmd.cpp index d6b605bae1..b08e879530 100644 --- a/src/roadveh_cmd.cpp +++ b/src/roadveh_cmd.cpp @@ -151,8 +151,7 @@ void DrawRoadVehEngine(int left, int right, int preferred_x, int y, EngineID eng VehicleSpriteSeq seq; GetRoadVehIcon(engine, image_type, &seq); - Rect rect; - seq.GetBounds(&rect); + Rect16 rect = seq.GetBounds(); preferred_x = Clamp(preferred_x, left - UnScaleGUI(rect.left), right - UnScaleGUI(rect.right)); @@ -174,8 +173,7 @@ void GetRoadVehSpriteSize(EngineID engine, uint &width, uint &height, int &xoffs VehicleSpriteSeq seq; GetRoadVehIcon(engine, image_type, &seq); - Rect rect; - seq.GetBounds(&rect); + Rect16 rect = seq.GetBounds(); width = UnScaleGUI(rect.right - rect.left + 1); height = UnScaleGUI(rect.bottom - rect.top + 1); diff --git a/src/saveload/oldloader_sl.cpp b/src/saveload/oldloader_sl.cpp index 907f4b2c45..ed5e3a3657 100644 --- a/src/saveload/oldloader_sl.cpp +++ b/src/saveload/oldloader_sl.cpp @@ -1270,6 +1270,7 @@ bool LoadOldVehicle(LoadgameState *ls, int num) sprite += 1385; // rotor or disaster-related vehicles } v->sprite_seq.seq[0].sprite = sprite; + v->UpdateSpriteSeqBound(); switch (v->type) { case VEH_TRAIN: { diff --git a/src/saveload/vehicle_sl.cpp b/src/saveload/vehicle_sl.cpp index db028cb36f..51779ca317 100644 --- a/src/saveload/vehicle_sl.cpp +++ b/src/saveload/vehicle_sl.cpp @@ -439,20 +439,24 @@ void AfterLoadVehicles(bool part_of_load) case VEH_TRAIN: case VEH_SHIP: v->GetImage(v->direction, EIT_ON_MAP, &v->sprite_seq); + v->UpdateSpriteSeqBound(); break; case VEH_AIRCRAFT: if (Aircraft::From(v)->IsNormalAircraft()) { v->GetImage(v->direction, EIT_ON_MAP, &v->sprite_seq); + v->UpdateSpriteSeqBound(); /* 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_seq_bounds = v->sprite_seq_bounds; /* 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); + rotor->UpdateSpriteSeqBound(); } UpdateAircraftCache(Aircraft::From(v), true); diff --git a/src/ship_cmd.cpp b/src/ship_cmd.cpp index 41f2fe7343..e20ba80e78 100644 --- a/src/ship_cmd.cpp +++ b/src/ship_cmd.cpp @@ -94,8 +94,7 @@ void DrawShipEngine(int left, int right, int preferred_x, int y, EngineID engine VehicleSpriteSeq seq; GetShipIcon(engine, image_type, &seq); - Rect rect; - seq.GetBounds(&rect); + Rect16 rect = seq.GetBounds(); preferred_x = Clamp(preferred_x, left - UnScaleGUI(rect.left), right - UnScaleGUI(rect.right)); @@ -117,8 +116,7 @@ void GetShipSpriteSize(EngineID engine, uint &width, uint &height, int &xoffs, i VehicleSpriteSeq seq; GetShipIcon(engine, image_type, &seq); - Rect rect; - seq.GetBounds(&rect); + Rect16 rect = seq.GetBounds(); width = UnScaleGUI(rect.right - rect.left + 1); height = UnScaleGUI(rect.bottom - rect.top + 1); diff --git a/src/ship_gui.cpp b/src/ship_gui.cpp index c6bf342d97..b105dcee7a 100644 --- a/src/ship_gui.cpp +++ b/src/ship_gui.cpp @@ -38,8 +38,7 @@ void DrawShipImage(const Vehicle *v, int left, int right, int y, VehicleID selec VehicleSpriteSeq seq; v->GetImage(rtl ? DIR_E : DIR_W, image_type, &seq); - Rect rect; - seq.GetBounds(&rect); + Rect16 rect = seq.GetBounds(); int width = UnScaleGUI(rect.right - rect.left + 1); int x_offs = UnScaleGUI(rect.left); diff --git a/src/train_cmd.cpp b/src/train_cmd.cpp index 27b81fca36..94cf1c6a4b 100644 --- a/src/train_cmd.cpp +++ b/src/train_cmd.cpp @@ -609,9 +609,8 @@ void DrawTrainEngine(int left, int right, int preferred_x, int y, EngineID engin GetRailIcon(engine, false, yf, image_type, &seqf); GetRailIcon(engine, true, yr, image_type, &seqr); - Rect rectf, rectr; - seqf.GetBounds(&rectf); - seqr.GetBounds(&rectr); + Rect16 rectf = seqf.GetBounds(); + Rect16 rectr = seqr.GetBounds(); preferred_x = SoftClamp(preferred_x, left - UnScaleGUI(rectf.left) + ScaleGUITrad(14), @@ -623,8 +622,7 @@ void DrawTrainEngine(int left, int right, int preferred_x, int y, EngineID engin VehicleSpriteSeq seq; GetRailIcon(engine, false, y, image_type, &seq); - Rect rect; - seq.GetBounds(&rect); + Rect16 rect = seq.GetBounds(); preferred_x = Clamp(preferred_x, left - UnScaleGUI(rect.left), right - UnScaleGUI(rect.right)); @@ -649,8 +647,7 @@ void GetTrainSpriteSize(EngineID engine, uint &width, uint &height, int &xoffs, VehicleSpriteSeq seq; GetRailIcon(engine, false, y, image_type, &seq); - Rect rect; - seq.GetBounds(&rect); + Rect16 rect = seq.GetBounds(); width = UnScaleGUI(rect.right - rect.left + 1); height = UnScaleGUI(rect.bottom - rect.top + 1); @@ -659,7 +656,7 @@ void GetTrainSpriteSize(EngineID engine, uint &width, uint &height, int &xoffs, if (RailVehInfo(engine)->railveh_type == RAILVEH_MULTIHEAD) { GetRailIcon(engine, true, y, image_type, &seq); - seq.GetBounds(&rect); + rect = seq.GetBounds(); /* Calculate values relative to an imaginary center between the two sprites. */ width = ScaleGUITrad(TRAININFO_DEFAULT_VEHICLE_WIDTH) + UnScaleGUI(rect.right) - xoffs; diff --git a/src/vehicle.cpp b/src/vehicle.cpp index de616667bc..99fce03adb 100644 --- a/src/vehicle.cpp +++ b/src/vehicle.cpp @@ -83,25 +83,27 @@ static btree::btree_set _vehicles_to_pay_repair; * Determine shared bounds of all sprites. * @param [out] bounds Shared bounds. */ -void VehicleSpriteSeq::GetBounds(Rect *bounds) const +Rect16 VehicleSpriteSeq::GetBounds() const { - bounds->left = bounds->top = bounds->right = bounds->bottom = 0; + Rect16 bounds; + bounds.left = bounds.top = bounds.right = bounds.bottom = 0; for (uint i = 0; i < this->count; ++i) { const Sprite *spr = GetSprite(this->seq[i].sprite, ST_NORMAL); if (i == 0) { - bounds->left = spr->x_offs; - bounds->top = spr->y_offs; - bounds->right = spr->width + spr->x_offs - 1; - bounds->bottom = spr->height + spr->y_offs - 1; + bounds.left = spr->x_offs; + bounds.top = spr->y_offs; + bounds.right = spr->width + spr->x_offs - 1; + bounds.bottom = spr->height + spr->y_offs - 1; } else { - if (spr->x_offs < bounds->left) bounds->left = spr->x_offs; - if (spr->y_offs < bounds->top) bounds->top = spr->y_offs; + if (spr->x_offs < bounds.left) bounds.left = spr->x_offs; + if (spr->y_offs < bounds.top) bounds.top = spr->y_offs; int right = spr->width + spr->x_offs - 1; int bottom = spr->height + spr->y_offs - 1; - if (right > bounds->right) bounds->right = right; - if (bottom > bounds->bottom) bounds->bottom = bottom; + if (right > bounds.right) bounds.right = right; + if (bottom > bounds.bottom) bounds.bottom = bottom; } } + return bounds; } /** @@ -2013,8 +2015,7 @@ void Vehicle::UpdatePosition() */ void Vehicle::UpdateViewport(bool dirty) { - Rect new_coord; - this->sprite_seq.GetBounds(&new_coord); + Rect new_coord = ConvertRect(this->sprite_seq_bounds); Point pt = RemapCoords(this->x_pos + this->x_offs, this->y_pos + this->y_offs, this->z_pos); new_coord.left += pt.x; diff --git a/src/vehicle_base.h b/src/vehicle_base.h index 97bc451be0..6477e1654b 100644 --- a/src/vehicle_base.h +++ b/src/vehicle_base.h @@ -191,7 +191,7 @@ struct VehicleSpriteSeq { } } - void GetBounds(Rect *bounds) const; + Rect16 GetBounds() const; void Draw(int x, int y, PaletteID default_pal, bool force_pal) const; }; @@ -288,6 +288,7 @@ public: */ byte spritenum; VehicleSpriteSeq sprite_seq; ///< Vehicle appearance. + Rect16 sprite_seq_bounds; 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 @@ -1054,6 +1055,11 @@ public: } bool IsDrawn() const; + + inline void UpdateSpriteSeqBound() + { + this->sprite_seq_bounds = this->sprite_seq.GetBounds(); + } }; /** @@ -1236,6 +1242,7 @@ struct SpecializedVehicle : public Vehicle { _sprite_group_resolve_check_veh_check = false; if (force_update || this->sprite_seq != seq) { this->sprite_seq = seq; + this->UpdateSpriteSeqBound(); this->Vehicle::UpdateViewport(true); } } else if (force_update) { diff --git a/src/vehicle_gui.cpp b/src/vehicle_gui.cpp index 9501d8158f..80599c3a65 100644 --- a/src/vehicle_gui.cpp +++ b/src/vehicle_gui.cpp @@ -3487,8 +3487,7 @@ int GetSingleVehicleWidth(const Vehicle *v, EngineImageType image_type) bool rtl = _current_text_dir == TD_RTL; VehicleSpriteSeq seq; v->GetImage(rtl ? DIR_E : DIR_W, image_type, &seq); - Rect rec; - seq.GetBounds(&rec); + Rect16 rec = seq.GetBounds(); return UnScaleGUI(rec.right - rec.left + 1); } }