Cache sprite sequence bounds for vehicles

pull/59/head
Jonathan G Rennison 6 years ago
parent 5b226adc75
commit d730cfd51d

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

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

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

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

@ -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: {

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

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

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

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

@ -83,25 +83,27 @@ static btree::btree_set<Vehicle *> _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<Rect16, Rect>(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;

@ -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) {

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

Loading…
Cancel
Save