diff --git a/src/newgrf_airport.cpp b/src/newgrf_airport.cpp index 4c5b21a6bd..4201fc6221 100644 --- a/src/newgrf_airport.cpp +++ b/src/newgrf_airport.cpp @@ -237,6 +237,7 @@ AirportResolverObject::AirportResolverObject(TileIndex tile, Station *st, byte a CallbackID callback, uint32 param1, uint32 param2) : ResolverObject(AirportSpec::Get(airport_id)->grf_prop.grffile, callback, param1, param2), airport_scope(*this, tile, st, airport_id, layout) { + this->root_spritegroup = AirportSpec::Get(airport_id)->grf_prop.spritegroup[0]; } /** @@ -258,7 +259,7 @@ AirportScopeResolver::AirportScopeResolver(ResolverObject &ro, TileIndex tile, S SpriteID GetCustomAirportSprite(const AirportSpec *as, byte layout) { AirportResolverObject object(INVALID_TILE, NULL, as->GetIndex(), layout); - const SpriteGroup *group = SpriteGroup::Resolve(as->grf_prop.spritegroup[0], object); + const SpriteGroup *group = object.Resolve(); if (group == NULL) return as->preview_sprite; return group->GetResult(); @@ -267,10 +268,7 @@ SpriteID GetCustomAirportSprite(const AirportSpec *as, byte layout) uint16 GetAirportCallback(CallbackID callback, uint32 param1, uint32 param2, Station *st, TileIndex tile) { AirportResolverObject object(tile, st, st->airport.type, st->airport.layout, callback, param1, param2); - const SpriteGroup *group = SpriteGroup::Resolve(st->airport.GetSpec()->grf_prop.spritegroup[0], object); - if (group == NULL) return CALLBACK_FAILED; - - return group->GetCallbackResult(); + return object.ResolveCallback(); } /** @@ -283,8 +281,7 @@ uint16 GetAirportCallback(CallbackID callback, uint32 param1, uint32 param2, Sta StringID GetAirportTextCallback(const AirportSpec *as, byte layout, uint16 callback) { AirportResolverObject object(INVALID_TILE, NULL, as->GetIndex(), layout, (CallbackID)callback); - const SpriteGroup *group = SpriteGroup::Resolve(as->grf_prop.spritegroup[0], object); - uint16 cb_res = (group != NULL) ? group->GetCallbackResult() : CALLBACK_FAILED; + uint16 cb_res = object.ResolveCallback(); if (cb_res == CALLBACK_FAILED || cb_res == 0x400) return STR_UNDEFINED; if (cb_res > 0x400) { ErrorUnknownCallbackResult(as->grf_prop.grffile->grfid, callback, cb_res); diff --git a/src/newgrf_airporttiles.cpp b/src/newgrf_airporttiles.cpp index cc9471c80a..323fb6cc16 100644 --- a/src/newgrf_airporttiles.cpp +++ b/src/newgrf_airporttiles.cpp @@ -217,6 +217,7 @@ AirportTileResolverObject::AirportTileResolverObject(const AirportTileSpec *ats, CallbackID callback, uint32 callback_param1, uint32 callback_param2) : ResolverObject(ats->grf_prop.grffile, callback, callback_param1, callback_param2), tiles_scope(*this, ats, tile, st) { + this->root_spritegroup = ats->grf_prop.spritegroup[0]; } /** @@ -237,10 +238,7 @@ AirportTileScopeResolver::AirportTileScopeResolver(ResolverObject &ro, const Air uint16 GetAirportTileCallback(CallbackID callback, uint32 param1, uint32 param2, const AirportTileSpec *ats, Station *st, TileIndex tile, int extra_data = 0) { AirportTileResolverObject object(ats, tile, st, callback, param1, param2); - const SpriteGroup *group = SpriteGroup::Resolve(ats->grf_prop.spritegroup[0], object); - if (group == NULL) return CALLBACK_FAILED; - - return group->GetCallbackResult(); + return object.ResolveCallback(); } static void AirportDrawTileLayout(const TileInfo *ti, const TileLayoutSpriteGroup *group, byte colour, StationGfx gfx) @@ -275,7 +273,7 @@ bool DrawNewAirportTile(TileInfo *ti, Station *st, StationGfx gfx, const Airport } AirportTileResolverObject object(airts, ti->tile, st); - const SpriteGroup *group = SpriteGroup::Resolve(airts->grf_prop.spritegroup[0], object); + const SpriteGroup *group = object.Resolve(); if (group == NULL || group->type != SGT_TILELAYOUT) { return false; } diff --git a/src/newgrf_canal.cpp b/src/newgrf_canal.cpp index 7310186c09..8f81fd0d8a 100644 --- a/src/newgrf_canal.cpp +++ b/src/newgrf_canal.cpp @@ -33,7 +33,7 @@ struct CanalScopeResolver : public ScopeResolver { struct CanalResolverObject : public ResolverObject { CanalScopeResolver canal_scope; - CanalResolverObject(const GRFFile *grffile, TileIndex tile, + CanalResolverObject(CanalFeature feature, TileIndex tile, CallbackID callback = CBID_NO_CALLBACK, uint32 callback_param1 = 0, uint32 callback_param2 = 0); /* virtual */ ScopeResolver *GetScope(VarSpriteGroupScope scope = VSG_SCOPE_SELF, byte relative = 0) @@ -115,16 +115,17 @@ CanalScopeResolver::CanalScopeResolver(ResolverObject &ro, TileIndex tile) : Sco /** * Canal resolver constructor. - * @param grffile Grf file. + * @param feature Which canal feature we want. * @param tile Tile index of canal. * @param callback Callback ID. * @param callback_param1 First parameter (var 10) of the callback. * @param callback_param2 Second parameter (var 18) of the callback. */ -CanalResolverObject::CanalResolverObject(const GRFFile *grffile, TileIndex tile, +CanalResolverObject::CanalResolverObject(CanalFeature feature, TileIndex tile, CallbackID callback, uint32 callback_param1, uint32 callback_param2) - : ResolverObject(grffile, callback, callback_param1, callback_param2), canal_scope(*this, tile) + : ResolverObject(_water_feature[feature].grffile, callback, callback_param1, callback_param2), canal_scope(*this, tile) { + this->root_spritegroup = _water_feature[feature].group; } /** @@ -135,8 +136,8 @@ CanalResolverObject::CanalResolverObject(const GRFFile *grffile, TileIndex tile, */ SpriteID GetCanalSprite(CanalFeature feature, TileIndex tile) { - CanalResolverObject object(_water_feature[feature].grffile, tile); - const SpriteGroup *group = SpriteGroup::Resolve(_water_feature[feature].group, object); + CanalResolverObject object(feature, tile); + const SpriteGroup *group = object.Resolve(); if (group == NULL) return 0; return group->GetResult(); @@ -153,11 +154,8 @@ SpriteID GetCanalSprite(CanalFeature feature, TileIndex tile) */ static uint16 GetCanalCallback(CallbackID callback, uint32 param1, uint32 param2, CanalFeature feature, TileIndex tile) { - CanalResolverObject object(_water_feature[feature].grffile, tile, callback, param1, param2); - const SpriteGroup *group = SpriteGroup::Resolve(_water_feature[feature].group, object); - if (group == NULL) return CALLBACK_FAILED; - - return group->GetCallbackResult(); + CanalResolverObject object(feature, tile, callback, param1, param2); + return object.ResolveCallback(); } /** diff --git a/src/newgrf_cargo.cpp b/src/newgrf_cargo.cpp index 4186b53f6a..0166985233 100644 --- a/src/newgrf_cargo.cpp +++ b/src/newgrf_cargo.cpp @@ -40,6 +40,7 @@ struct CargoResolverObject : public ResolverObject { CargoResolverObject::CargoResolverObject(const CargoSpec *cs, CallbackID callback, uint32 callback_param1, uint32 callback_param2) : ResolverObject(cs->grffile, callback, callback_param1, callback_param2) { + this->root_spritegroup = cs->group; } /** @@ -50,7 +51,7 @@ CargoResolverObject::CargoResolverObject(const CargoSpec *cs, CallbackID callbac SpriteID GetCustomCargoSprite(const CargoSpec *cs) { CargoResolverObject object(cs); - const SpriteGroup *group = SpriteGroup::Resolve(cs->group, object); + const SpriteGroup *group = object.Resolve(); if (group == NULL) return 0; return group->GetResult(); @@ -60,10 +61,7 @@ SpriteID GetCustomCargoSprite(const CargoSpec *cs) uint16 GetCargoCallback(CallbackID callback, uint32 param1, uint32 param2, const CargoSpec *cs) { CargoResolverObject object(cs, callback, param1, param2); - const SpriteGroup *group = SpriteGroup::Resolve(cs->group, object); - if (group == NULL) return CALLBACK_FAILED; - - return group->GetCallbackResult(); + return object.ResolveCallback(); } /** diff --git a/src/newgrf_engine.cpp b/src/newgrf_engine.cpp index 309decb722..5d3af41054 100644 --- a/src/newgrf_engine.cpp +++ b/src/newgrf_engine.cpp @@ -973,12 +973,13 @@ static const GRFFile *GetEngineGrfFile(EngineID engine_type) * Resolver of a vehicle (chain). * @param engine_type Engine type * @param v %Vehicle being resolved. + * @param wagon_override Application of wagon overrides. * @param info_view Indicates if the item is being drawn in an info window. * @param callback Callback ID. * @param callback_param1 First parameter (var 10) of the callback. * @param callback_param2 Second parameter (var 18) of the callback. */ -VehicleResolverObject::VehicleResolverObject(EngineID engine_type, const Vehicle *v, bool info_view, +VehicleResolverObject::VehicleResolverObject(EngineID engine_type, const Vehicle *v, WagonOverride wagon_override, bool info_view, CallbackID callback, uint32 callback_param1, uint32 callback_param2) : ResolverObject(GetEngineGrfFile(engine_type), callback, callback_param1, callback_param2), self_scope(*this, engine_type, v, info_view), @@ -986,55 +987,37 @@ VehicleResolverObject::VehicleResolverObject(EngineID engine_type, const Vehicle relative_scope(*this, engine_type, v, info_view), cached_relative_count(0) { -} - -/** - * Retrieve the SpriteGroup for the specified vehicle. - * If the vehicle is not specified, the purchase list group for the engine is - * chosen. For trains, an additional engine override lookup is performed. - * @param engine Engine type of the vehicle. - * @param v The vehicle itself. - * @param use_cache Use cached override - * @returns The selected SpriteGroup for the vehicle. - */ -static const SpriteGroup *GetVehicleSpriteGroup(EngineID engine, const Vehicle *v, bool use_cache = true) -{ - const SpriteGroup *group; - CargoID cargo; - - if (v == NULL) { - cargo = CT_PURCHASE; + if (wagon_override == WO_SELF) { + this->root_spritegroup = GetWagonOverrideSpriteSet(engine_type, CT_DEFAULT, engine_type); } else { - cargo = v->cargo_type; + if (wagon_override != WO_NONE && v != NULL && v->IsGroundVehicle()) { + assert(v->engine_type == engine_type); // overrides make little sense with fake scopes - if (v->IsGroundVehicle()) { /* For trains we always use cached value, except for callbacks because the override spriteset * to use may be different than the one cached. It happens for callback 0x15 (refit engine), * as v->cargo_type is temporary changed to the new type */ - if (use_cache && v->type == VEH_TRAIN) { - group = Train::From(v)->tcache.cached_override; + if (wagon_override == WO_CACHED && v->type == VEH_TRAIN) { + this->root_spritegroup = Train::From(v)->tcache.cached_override; } else { - group = GetWagonOverrideSpriteSet(v->engine_type, v->cargo_type, v->GetGroundVehicleCache()->first_engine); + this->root_spritegroup = GetWagonOverrideSpriteSet(v->engine_type, v->cargo_type, v->GetGroundVehicleCache()->first_engine); } - if (group != NULL) return group; + } + + if (this->root_spritegroup == NULL) { + const Engine *e = Engine::Get(engine_type); + CargoID cargo = v != NULL ? v->cargo_type : CT_PURCHASE; + assert(cargo < lengthof(e->grf_prop.spritegroup)); + this->root_spritegroup = e->grf_prop.spritegroup[cargo] != NULL ? e->grf_prop.spritegroup[cargo] : e->grf_prop.spritegroup[CT_DEFAULT]; } } - - const Engine *e = Engine::Get(engine); - - assert(cargo < lengthof(e->grf_prop.spritegroup)); - group = e->grf_prop.spritegroup[cargo]; - if (group != NULL) return group; - - /* Fall back to the default set if the selected cargo type is not defined */ - return e->grf_prop.spritegroup[CT_DEFAULT]; } + SpriteID GetCustomEngineSprite(EngineID engine, const Vehicle *v, Direction direction, EngineImageType image_type) { - VehicleResolverObject object(engine, v, false, CBID_NO_CALLBACK, image_type); - const SpriteGroup *group = SpriteGroup::Resolve(GetVehicleSpriteGroup(engine, v), object); + VehicleResolverObject object(engine, v, VehicleResolverObject::WO_CACHED, false, CBID_NO_CALLBACK, image_type); + const SpriteGroup *group = object.Resolve(); if (group == NULL || group->GetNumResults() == 0) return 0; return group->GetResult() + (direction % group->GetNumResults()); @@ -1049,15 +1032,14 @@ SpriteID GetRotorOverrideSprite(EngineID engine, const Aircraft *v, bool info_vi assert(e->type == VEH_AIRCRAFT); assert(!(e->u.air.subtype & AIR_CTOL)); - VehicleResolverObject object(engine, v, info_view, CBID_NO_CALLBACK, image_type); - const SpriteGroup *group = GetWagonOverrideSpriteSet(engine, CT_DEFAULT, engine); - group = SpriteGroup::Resolve(group, object); + VehicleResolverObject object(engine, v, VehicleResolverObject::WO_SELF, info_view, CBID_NO_CALLBACK, image_type); + const SpriteGroup *group = object.Resolve(); if (group == NULL || group->GetNumResults() == 0) return 0; - if (v == NULL) return group->GetResult(); + if (v == NULL || info_view) return group->GetResult(); - return group->GetResult() + (info_view ? 0 : (v->Next()->Next()->state % group->GetNumResults())); + return group->GetResult() + (v->Next()->Next()->state % group->GetNumResults()); } @@ -1083,11 +1065,8 @@ bool UsesWagonOverride(const Vehicle *v) */ uint16 GetVehicleCallback(CallbackID callback, uint32 param1, uint32 param2, EngineID engine, const Vehicle *v) { - VehicleResolverObject object(engine, v, false, callback, param1, param2); - const SpriteGroup *group = SpriteGroup::Resolve(GetVehicleSpriteGroup(engine, v, false), object); - if (group == NULL) return CALLBACK_FAILED; - - return group->GetCallbackResult(); + VehicleResolverObject object(engine, v, VehicleResolverObject::WO_UNCACHED, false, callback, param1, param2); + return object.ResolveCallback(); } /** @@ -1102,13 +1081,9 @@ uint16 GetVehicleCallback(CallbackID callback, uint32 param1, uint32 param2, Eng */ uint16 GetVehicleCallbackParent(CallbackID callback, uint32 param1, uint32 param2, EngineID engine, const Vehicle *v, const Vehicle *parent) { - VehicleResolverObject object(engine, v, false, callback, param1, param2); + VehicleResolverObject object(engine, v, VehicleResolverObject::WO_NONE, false, callback, param1, param2); object.parent_scope.SetVehicle(parent); - - const SpriteGroup *group = SpriteGroup::Resolve(GetVehicleSpriteGroup(engine, v, false), object); - if (group == NULL) return CALLBACK_FAILED; - - return group->GetCallbackResult(); + return object.ResolveCallback(); } @@ -1133,10 +1108,10 @@ static void DoTriggerVehicle(Vehicle *v, VehicleTrigger trigger, byte base_rando /* We can't trigger a non-existent vehicle... */ assert(v != NULL); - VehicleResolverObject object(v->engine_type, v, false, CBID_RANDOM_TRIGGER); + VehicleResolverObject object(v->engine_type, v, VehicleResolverObject::WO_CACHED, false, CBID_RANDOM_TRIGGER); object.trigger = trigger; - const SpriteGroup *group = SpriteGroup::Resolve(GetVehicleSpriteGroup(v->engine_type, v), object); + const SpriteGroup *group = object.Resolve(); if (group == NULL) return; byte new_random_bits = Random(); @@ -1300,7 +1275,7 @@ void CommitVehicleListOrderChanges() */ void FillNewGRFVehicleCache(const Vehicle *v) { - VehicleResolverObject ro(v->engine_type, v); + VehicleResolverObject ro(v->engine_type, v, VehicleResolverObject::WO_NONE); /* These variables we have to check; these are the ones with a cache. */ static const int cache_entries[][2] = { diff --git a/src/newgrf_engine.h b/src/newgrf_engine.h index 5e1661ccaa..4a6f211c49 100644 --- a/src/newgrf_engine.h +++ b/src/newgrf_engine.h @@ -38,13 +38,21 @@ struct VehicleScopeResolver : public ScopeResolver { /** Resolver for a vehicle (chain) */ struct VehicleResolverObject : public ResolverObject { + /** Application of 'wagon overrides'. */ + enum WagonOverride { + WO_NONE, //!< Resolve no wagon overrides. + WO_UNCACHED, //!< Resolve wagon overrides. + WO_CACHED, //!< Resolve wagon overrides using TrainCache::cached_override. + WO_SELF, //!< Resolve self-override (helicopter rotors and such). + }; + VehicleScopeResolver self_scope; ///< Scope resolver for the indicated vehicle. VehicleScopeResolver parent_scope; ///< Scope resolver for its parent vehicle. VehicleScopeResolver relative_scope; ///< Scope resolver for an other vehicle in the chain. byte cached_relative_count; ///< Relative position of the other vehicle. - VehicleResolverObject(EngineID engine_type, const Vehicle *v, bool info_view = false, + VehicleResolverObject(EngineID engine_type, const Vehicle *v, WagonOverride wagon_override, bool info_view = false, CallbackID callback = CBID_NO_CALLBACK, uint32 callback_param1 = 0, uint32 callback_param2 = 0); /* virtual */ ScopeResolver *GetScope(VarSpriteGroupScope scope = VSG_SCOPE_SELF, byte relative = 0); diff --git a/src/newgrf_generic.cpp b/src/newgrf_generic.cpp index f1305636d1..55eee6d23e 100644 --- a/src/newgrf_generic.cpp +++ b/src/newgrf_generic.cpp @@ -179,17 +179,17 @@ static uint16 GetGenericCallbackResult(uint8 feature, ResolverObject &object, ui /* Test each feature callback sprite group. */ for (GenericCallbackList::const_iterator it = _gcl[feature].begin(); it != _gcl[feature].end(); ++it) { - const SpriteGroup *group = it->group; object.grffile = it->file; + object.root_spritegroup = it->group; /* Set callback param based on GRF version. */ object.callback_param1 = it->file->grf_version >= 8 ? param1_grfv8 : param1_grfv7; - group = SpriteGroup::Resolve(group, object); - if (group == NULL || group->GetCallbackResult() == CALLBACK_FAILED) continue; + uint16 result = object.ResolveCallback(); + if (result == CALLBACK_FAILED) continue; /* Return NewGRF file if necessary */ if (file != NULL) *file = it->file; - return group->GetCallbackResult(); + return result; } /* No callback returned a valid result, so we've failed. */ diff --git a/src/newgrf_house.cpp b/src/newgrf_house.cpp index a31ac4bc4e..c660fe3ab7 100644 --- a/src/newgrf_house.cpp +++ b/src/newgrf_house.cpp @@ -81,6 +81,7 @@ HouseResolverObject::HouseResolverObject(HouseID house_id, TileIndex tile, Town house_scope(*this, house_id, tile, town, not_yet_constructed, initial_random_bits, watched_cargo_triggers), town_scope(*this, town, not_yet_constructed) // Don't access StorePSA if house is not yet constructed. { + this->root_spritegroup = HouseSpec::Get(house_id)->grf_prop.spritegroup[0]; } HouseClassID AllocateHouseClassID(byte grf_class_id, uint32 grfid) @@ -439,11 +440,7 @@ uint16 GetHouseCallback(CallbackID callback, uint32 param1, uint32 param2, House HouseResolverObject object(house_id, tile, town, callback, param1, param2, not_yet_constructed, initial_random_bits, watched_cargo_triggers); - - const SpriteGroup *group = SpriteGroup::Resolve(HouseSpec::Get(house_id)->grf_prop.spritegroup[0], object); - if (group == NULL) return CALLBACK_FAILED; - - return group->GetCallbackResult(); + return object.ResolveCallback(); } static void DrawTileLayout(const TileInfo *ti, const TileLayoutSpriteGroup *group, byte stage, HouseID house_id) @@ -490,7 +487,7 @@ void DrawNewHouseTile(TileInfo *ti, HouseID house_id) HouseResolverObject object(house_id, ti->tile, Town::GetByTile(ti->tile)); - const SpriteGroup *group = SpriteGroup::Resolve(hs->grf_prop.spritegroup[0], object); + const SpriteGroup *group = object.Resolve(); if (group != NULL && group->type == SGT_TILELAYOUT) { /* Limit the building stage to the number of stages supplied. */ const TileLayoutSpriteGroup *tlgroup = (const TileLayoutSpriteGroup *)group; @@ -615,7 +612,7 @@ static void DoTriggerHouse(TileIndex tile, HouseTrigger trigger, byte base_rando HouseResolverObject object(hid, tile, Town::GetByTile(tile), CBID_RANDOM_TRIGGER); object.trigger = trigger; - const SpriteGroup *group = SpriteGroup::Resolve(hs->grf_prop.spritegroup[0], object); + const SpriteGroup *group = object.Resolve(); if (group == NULL) return; byte new_random_bits = Random(); diff --git a/src/newgrf_industries.cpp b/src/newgrf_industries.cpp index dfc615b299..725373d105 100644 --- a/src/newgrf_industries.cpp +++ b/src/newgrf_industries.cpp @@ -432,6 +432,7 @@ IndustriesResolverObject::IndustriesResolverObject(TileIndex tile, Industry *ind industries_scope(*this, tile, indus, type, random_bits), town_scope(NULL) { + this->root_spritegroup = GetIndustrySpec(type)->grf_prop.spritegroup[0]; } IndustriesResolverObject::~IndustriesResolverObject() @@ -490,10 +491,7 @@ IndustriesScopeResolver::IndustriesScopeResolver(ResolverObject &ro, TileIndex t uint16 GetIndustryCallback(CallbackID callback, uint32 param1, uint32 param2, Industry *industry, IndustryType type, TileIndex tile) { IndustriesResolverObject object(tile, industry, type, 0, callback, param1, param2); - const SpriteGroup *group = SpriteGroup::Resolve(GetIndustrySpec(type)->grf_prop.spritegroup[0], object); - if (group == NULL) return CALLBACK_FAILED; - - return group->GetCallbackResult(); + return object.ResolveCallback(); } /** @@ -523,12 +521,10 @@ CommandCost CheckIfCallBackAllowsCreation(TileIndex tile, IndustryType type, uin ind.psa = NULL; IndustriesResolverObject object(tile, &ind, type, seed, CBID_INDUSTRY_LOCATION, 0, creation_type); - const SpriteGroup *group = SpriteGroup::Resolve(GetIndustrySpec(type)->grf_prop.spritegroup[0], object); + uint16 result = object.ResolveCallback(); /* Unlike the "normal" cases, not having a valid result means we allow * the building of the industry, as that's how it's done in TTDP. */ - if (group == NULL) return CommandCost(); - uint16 result = group->GetCallbackResult(); if (result == CALLBACK_FAILED) return CommandCost(); return GetErrorMessageFromLocationCallbackResult(result, indspec->grf_prop.grffile, STR_ERROR_SITE_UNSUITABLE); @@ -596,7 +592,7 @@ void IndustryProductionCallback(Industry *ind, int reason) } SB(object.callback_param2, 8, 16, loop); - const SpriteGroup *tgroup = SpriteGroup::Resolve(spec->grf_prop.spritegroup[0], object); + const SpriteGroup *tgroup = object.Resolve(); if (tgroup == NULL || tgroup->type != SGT_INDUSTRY_PRODUCTION) break; const IndustryProductionSpriteGroup *group = (const IndustryProductionSpriteGroup *)tgroup; diff --git a/src/newgrf_industrytiles.cpp b/src/newgrf_industrytiles.cpp index 7e31c1bc45..f22514a03f 100644 --- a/src/newgrf_industrytiles.cpp +++ b/src/newgrf_industrytiles.cpp @@ -147,6 +147,7 @@ IndustryTileResolverObject::IndustryTileResolverObject(IndustryGfx gfx, TileInde indtile_scope(*this, indus, tile), ind_scope(*this, tile, indus, indus->type) { + this->root_spritegroup = GetIndustryTileSpec(gfx)->grf_prop.spritegroup[0]; } /** @@ -190,10 +191,7 @@ uint16 GetIndustryTileCallback(CallbackID callback, uint32 param1, uint32 param2 assert(industry->index == INVALID_INDUSTRY || IsTileType(tile, MP_INDUSTRY)); IndustryTileResolverObject object(gfx_id, tile, industry, callback, param1, param2); - const SpriteGroup *group = SpriteGroup::Resolve(GetIndustryTileSpec(gfx_id)->grf_prop.spritegroup[0], object); - if (group == NULL || group->type != SGT_CALLBACK) return CALLBACK_FAILED; - - return group->GetCallbackResult(); + return object.ResolveCallback(); } bool DrawNewIndustryTile(TileInfo *ti, Industry *i, IndustryGfx gfx, const IndustryTileSpec *inds) @@ -211,7 +209,7 @@ bool DrawNewIndustryTile(TileInfo *ti, Industry *i, IndustryGfx gfx, const Indus IndustryTileResolverObject object(gfx, ti->tile, i); - const SpriteGroup *group = SpriteGroup::Resolve(inds->grf_prop.spritegroup[0], object); + const SpriteGroup *group = object.Resolve(); if (group == NULL || group->type != SGT_TILELAYOUT) return false; /* Limit the building stage to the number of stages supplied. */ @@ -328,7 +326,7 @@ static void DoTriggerIndustryTile(TileIndex tile, IndustryTileTrigger trigger, I IndustryTileResolverObject object(gfx, tile, ind, CBID_RANDOM_TRIGGER); object.trigger = trigger; - const SpriteGroup *group = SpriteGroup::Resolve(itspec->grf_prop.spritegroup[0], object); + const SpriteGroup *group = object.Resolve(); if (group == NULL) return; byte new_random_bits = Random(); diff --git a/src/newgrf_object.cpp b/src/newgrf_object.cpp index 3917b65102..6f7e3f0ff8 100644 --- a/src/newgrf_object.cpp +++ b/src/newgrf_object.cpp @@ -355,24 +355,6 @@ unhandled: return UINT_MAX; } -/** - * Get the object's sprite group. - * @param spec The specification to get the sprite group from. - * @param o The object to get he sprite group for. - * @return The resolved sprite group. - */ -static const SpriteGroup *GetObjectSpriteGroup(const ObjectSpec *spec, const Object *o) -{ - const SpriteGroup *group = NULL; - - if (o == NULL) group = spec->grf_prop.spritegroup[CT_PURCHASE_OBJECT]; - if (group != NULL) return group; - - /* Fall back to the default set if the selected cargo type is not defined */ - return spec->grf_prop.spritegroup[0]; - -} - /** * Constructor of the object resolver. * @param obj Object being resolved. @@ -387,6 +369,8 @@ ObjectResolverObject::ObjectResolverObject(const ObjectSpec *spec, Object *obj, : ResolverObject(spec->grf_prop.grffile, callback, param1, param2), object_scope(*this, obj, tile, view) { this->town_scope = NULL; + this->root_spritegroup = (obj == NULL && spec->grf_prop.spritegroup[CT_PURCHASE_OBJECT] != NULL) ? + spec->grf_prop.spritegroup[CT_PURCHASE_OBJECT] : spec->grf_prop.spritegroup[0]; } ObjectResolverObject::~ObjectResolverObject() @@ -428,10 +412,7 @@ TownScopeResolver *ObjectResolverObject::GetTown() uint16 GetObjectCallback(CallbackID callback, uint32 param1, uint32 param2, const ObjectSpec *spec, Object *o, TileIndex tile, uint8 view) { ObjectResolverObject object(spec, o, tile, view, callback, param1, param2); - const SpriteGroup *group = SpriteGroup::Resolve(GetObjectSpriteGroup(spec, o), object); - if (group == NULL) return CALLBACK_FAILED; - - return group->GetCallbackResult(); + return object.ResolveCallback(); } /** @@ -471,7 +452,7 @@ void DrawNewObjectTile(TileInfo *ti, const ObjectSpec *spec) Object *o = Object::GetByTile(ti->tile); ObjectResolverObject object(spec, o, ti->tile); - const SpriteGroup *group = SpriteGroup::Resolve(GetObjectSpriteGroup(spec, o), object); + const SpriteGroup *group = object.Resolve(); if (group == NULL || group->type != SGT_TILELAYOUT) return; DrawTileLayout(ti, (const TileLayoutSpriteGroup *)group, spec); @@ -487,7 +468,7 @@ void DrawNewObjectTile(TileInfo *ti, const ObjectSpec *spec) void DrawNewObjectTileInGUI(int x, int y, const ObjectSpec *spec, uint8 view) { ObjectResolverObject object(spec, NULL, INVALID_TILE, view); - const SpriteGroup *group = SpriteGroup::Resolve(GetObjectSpriteGroup(spec, NULL), object); + const SpriteGroup *group = object.Resolve(); if (group == NULL || group->type != SGT_TILELAYOUT) return; const DrawTileSprites *dts = ((const TileLayoutSpriteGroup *)group)->ProcessRegisters(NULL); diff --git a/src/newgrf_railtype.cpp b/src/newgrf_railtype.cpp index de735193f5..f43689698e 100644 --- a/src/newgrf_railtype.cpp +++ b/src/newgrf_railtype.cpp @@ -79,15 +79,17 @@ RailTypeScopeResolver::RailTypeScopeResolver(ResolverObject &ro, TileIndex tile, /** * Resolver object for rail types. + * @param rti Railtype. NULL in NewGRF Inspect window. * @param tile %Tile containing the track. For track on a bridge this is the southern bridgehead. * @param context Are we resolving sprites for the upper halftile, or on a bridge? - * @param grffile The GRF to do the lookup for. + * @param rtsg Railpart of interest * @param param1 Extra parameter (first parameter of the callback, except railtypes do not have callbacks). * @param param2 Extra parameter (second parameter of the callback, except railtypes do not have callbacks). */ -RailTypeResolverObject::RailTypeResolverObject(TileIndex tile, TileContext context, const GRFFile *grffile, uint32 param1, uint32 param2) - : ResolverObject(grffile, CBID_NO_CALLBACK, param1, param2), railtype_scope(*this, tile, context) +RailTypeResolverObject::RailTypeResolverObject(const RailtypeInfo *rti, TileIndex tile, TileContext context, RailTypeSpriteGroup rtsg, uint32 param1, uint32 param2) + : ResolverObject(rti != NULL ? rti->grffile[rtsg] : NULL, CBID_NO_CALLBACK, param1, param2), railtype_scope(*this, tile, context) { + this->root_spritegroup = rti != NULL ? rti->group[rtsg] : NULL; } /** @@ -104,8 +106,8 @@ SpriteID GetCustomRailSprite(const RailtypeInfo *rti, TileIndex tile, RailTypeSp if (rti->group[rtsg] == NULL) return 0; - RailTypeResolverObject object(tile, context, rti->grffile[rtsg]); - const SpriteGroup *group = SpriteGroup::Resolve(rti->group[rtsg], object); + RailTypeResolverObject object(rti, tile, context, rtsg); + const SpriteGroup *group = object.Resolve(); if (group == NULL || group->GetNumResults() == 0) return 0; return group->GetResult(); @@ -127,9 +129,9 @@ SpriteID GetCustomSignalSprite(const RailtypeInfo *rti, TileIndex tile, SignalTy uint32 param1 = gui ? 0x10 : 0x00; uint32 param2 = (type << 16) | (var << 8) | state; - RailTypeResolverObject object(tile, TCX_NORMAL, rti->grffile[RTSG_SIGNALS], param1, param2); + RailTypeResolverObject object(rti, tile, TCX_NORMAL, RTSG_SIGNALS, param1, param2); - const SpriteGroup *group = SpriteGroup::Resolve(rti->group[RTSG_SIGNALS], object); + const SpriteGroup *group = object.Resolve(); if (group == NULL || group->GetNumResults() == 0) return 0; return group->GetResult(); diff --git a/src/newgrf_railtype.h b/src/newgrf_railtype.h index 8c5bce8438..9b00bf5bff 100644 --- a/src/newgrf_railtype.h +++ b/src/newgrf_railtype.h @@ -31,7 +31,7 @@ struct RailTypeScopeResolver : public ScopeResolver { struct RailTypeResolverObject : public ResolverObject { RailTypeScopeResolver railtype_scope; ///< Resolver for the railtype scope. - RailTypeResolverObject(TileIndex tile, TileContext context, const GRFFile *grffile, uint32 param1 = 0, uint32 param2 = 0); + RailTypeResolverObject(const RailtypeInfo *rti, TileIndex tile, TileContext context, RailTypeSpriteGroup rtsg, uint32 param1 = 0, uint32 param2 = 0); /* virtual */ ScopeResolver *GetScope(VarSpriteGroupScope scope = VSG_SCOPE_SELF, byte relative = 0) { diff --git a/src/newgrf_spritegroup.cpp b/src/newgrf_spritegroup.cpp index b3a0a829f1..59fc70fe45 100644 --- a/src/newgrf_spritegroup.cpp +++ b/src/newgrf_spritegroup.cpp @@ -150,6 +150,7 @@ ResolverObject::ResolverObject(const GRFFile *grffile, CallbackID callback, uint this->ResetState(); this->grffile = grffile; + this->root_spritegroup = NULL; } ResolverObject::~ResolverObject() {} diff --git a/src/newgrf_spritegroup.h b/src/newgrf_spritegroup.h index c3753dcfdb..0a7705d667 100644 --- a/src/newgrf_spritegroup.h +++ b/src/newgrf_spritegroup.h @@ -321,6 +321,26 @@ struct ResolverObject { uint32 reseed[VSG_END]; ///< Collects bits to rerandomise while triggering triggers. const GRFFile *grffile; ///< GRFFile the resolved SpriteGroup belongs to + const SpriteGroup *root_spritegroup; ///< Root SpriteGroup to use for resolving + + /** + * Resolve SpriteGroup. + * @return Result spritegroup. + */ + const SpriteGroup *Resolve() + { + return SpriteGroup::Resolve(this->root_spritegroup, *this); + } + + /** + * Resolve callback. + * @return Callback result. + */ + uint16 ResolveCallback() + { + const SpriteGroup *result = Resolve(); + return result != NULL ? result->GetCallbackResult() : CALLBACK_FAILED; + } virtual const SpriteGroup *ResolveReal(const RealSpriteGroup *group) const; diff --git a/src/newgrf_station.cpp b/src/newgrf_station.cpp index 85277337de..647e8781aa 100644 --- a/src/newgrf_station.cpp +++ b/src/newgrf_station.cpp @@ -550,6 +550,32 @@ StationResolverObject::StationResolverObject(const StationSpec *statspec, BaseSt { /* Invalidate all cached vars */ _svc.valid = 0; + + CargoID ctype = CT_DEFAULT_NA; + + if (this->station_scope.st == NULL) { + /* No station, so we are in a purchase list */ + ctype = CT_PURCHASE; + } else if (Station::IsExpected(this->station_scope.st)) { + const Station *st = Station::From(this->station_scope.st); + /* Pick the first cargo that we have waiting */ + const CargoSpec *cs; + FOR_ALL_CARGOSPECS(cs) { + if (this->station_scope.statspec->grf_prop.spritegroup[cs->Index()] != NULL && + st->goods[cs->Index()].cargo.TotalCount() > 0) { + ctype = cs->Index(); + break; + } + } + } + + if (this->station_scope.statspec->grf_prop.spritegroup[ctype] == NULL) { + ctype = CT_DEFAULT; + } + + /* Remember the cargo type we've picked */ + this->station_scope.cargo_type = ctype; + this->root_spritegroup = this->station_scope.statspec->grf_prop.spritegroup[this->station_scope.cargo_type]; } StationResolverObject::~StationResolverObject() @@ -574,39 +600,6 @@ StationScopeResolver::StationScopeResolver(ResolverObject &ro, const StationSpec this->axis = INVALID_AXIS; } -static const SpriteGroup *ResolveStation(StationResolverObject &object) -{ - CargoID ctype = CT_DEFAULT_NA; - - if (object.station_scope.st == NULL) { - /* No station, so we are in a purchase list */ - ctype = CT_PURCHASE; - } else if (Station::IsExpected(object.station_scope.st)) { - const Station *st = Station::From(object.station_scope.st); - /* Pick the first cargo that we have waiting */ - const CargoSpec *cs; - FOR_ALL_CARGOSPECS(cs) { - if (object.station_scope.statspec->grf_prop.spritegroup[cs->Index()] != NULL && - st->goods[cs->Index()].cargo.TotalCount() > 0) { - ctype = cs->Index(); - break; - } - } - } - - const SpriteGroup *group = object.station_scope.statspec->grf_prop.spritegroup[ctype]; - if (group == NULL) { - ctype = CT_DEFAULT; - group = object.station_scope.statspec->grf_prop.spritegroup[ctype]; - if (group == NULL) return NULL; - } - - /* Remember the cargo type we've picked */ - object.station_scope.cargo_type = ctype; - - return SpriteGroup::Resolve(group, object); -} - /** * Resolve sprites for drawing a station tile. * @param statspec Station spec @@ -618,7 +611,7 @@ static const SpriteGroup *ResolveStation(StationResolverObject &object) SpriteID GetCustomStationRelocation(const StationSpec *statspec, BaseStation *st, TileIndex tile, uint32 var10) { StationResolverObject object(statspec, st, tile, CBID_NO_CALLBACK, var10); - const SpriteGroup *group = ResolveStation(object); + const SpriteGroup *group = object.Resolve(); if (group == NULL || group->type != SGT_RESULT) return 0; return group->GetResult() - 0x42D; } @@ -637,7 +630,7 @@ SpriteID GetCustomStationFoundationRelocation(const StationSpec *statspec, BaseS /* callback_param1 == 2 means we are resolving the foundation sprites. */ StationResolverObject object(statspec, st, tile, CBID_NO_CALLBACK, 2, layout | (edge_info << 16)); - const SpriteGroup *group = ResolveStation(object); + const SpriteGroup *group = object.Resolve(); if (group == NULL || group->type != SGT_RESULT) return 0; /* Note: SpriteGroup::Resolve zeroes all registers, so register 0x100 is initialised to 0. (compatibility) */ @@ -648,9 +641,7 @@ SpriteID GetCustomStationFoundationRelocation(const StationSpec *statspec, BaseS uint16 GetStationCallback(CallbackID callback, uint32 param1, uint32 param2, const StationSpec *statspec, BaseStation *st, TileIndex tile) { StationResolverObject object(statspec, st, tile, callback, param1, param2); - const SpriteGroup *group = ResolveStation(object); - if (group == NULL) return CALLBACK_FAILED; - return group->GetCallbackResult(); + return object.ResolveCallback(); } /** @@ -673,8 +664,7 @@ CommandCost PerformStationTileSlopeCheck(TileIndex north_tile, TileIndex cur_til (numtracks << 24) | (plat_len << 16) | (axis == AXIS_Y ? TileX(diff) << 8 | TileY(diff) : TileY(diff) << 8 | TileX(diff))); object.station_scope.axis = axis; - const SpriteGroup *group = ResolveStation(object); - uint16 cb_res = group != NULL ? group->GetCallbackResult() : CALLBACK_FAILED; + uint16 cb_res = object.ResolveCallback(); /* Failed callback means success. */ if (cb_res == CALLBACK_FAILED) return CommandCost(); @@ -1024,7 +1014,7 @@ void TriggerStationRandomisation(Station *st, TileIndex tile, StationRandomTrigg StationResolverObject object(ss, st, tile, CBID_RANDOM_TRIGGER, 0); object.trigger = trigger_bit; - const SpriteGroup *group = ResolveStation(object); + const SpriteGroup *group = object.Resolve(); if (group == NULL) continue; uint32 reseed = object.GetReseedSum(); diff --git a/src/table/newgrf_debug_data.h b/src/table/newgrf_debug_data.h index b4756882ff..4814ae50ce 100644 --- a/src/table/newgrf_debug_data.h +++ b/src/table/newgrf_debug_data.h @@ -79,7 +79,7 @@ class NIHVehicle : public NIHelper { /* virtual */ uint Resolve(uint index, uint var, uint param, bool *avail) const { Vehicle *v = Vehicle::Get(index); - VehicleResolverObject ro(v->engine_type, v); + VehicleResolverObject ro(v->engine_type, v, VehicleResolverObject::WO_CACHED); return ro.GetScope(VSG_SCOPE_SELF)->GetVariable(var, param, avail); } }; @@ -429,7 +429,7 @@ class NIHRailType : public NIHelper { { /* There is no unique GRFFile for the tile. Multiple GRFs can define different parts of the railtype. * However, currently the NewGRF Debug GUI does not display variables depending on the GRF (like 0x7F) anyway. */ - RailTypeResolverObject ro(index, TCX_NORMAL, NULL); + RailTypeResolverObject ro(NULL, index, TCX_NORMAL, RTSG_END); return ro.GetScope(VSG_SCOPE_SELF)->GetVariable(var, param, avail); } };