diff --git a/src/newgrf_canal.cpp b/src/newgrf_canal.cpp index 20355c899c..9bfe410172 100644 --- a/src/newgrf_canal.cpp +++ b/src/newgrf_canal.cpp @@ -96,7 +96,7 @@ SpriteID GetCanalSprite(CanalFeature feature, TileIndex tile) NewCanalResolver(&object, tile, _water_feature[feature].grffile); - group = Resolve(_water_feature[feature].group, &object); + group = SpriteGroup::Resolve(_water_feature[feature].group, &object); if (group == NULL) return 0; return group->GetResult(); diff --git a/src/newgrf_cargo.cpp b/src/newgrf_cargo.cpp index 95f560edc5..843c2ea6fa 100644 --- a/src/newgrf_cargo.cpp +++ b/src/newgrf_cargo.cpp @@ -74,7 +74,7 @@ SpriteID GetCustomCargoSprite(const CargoSpec *cs) NewCargoResolver(&object, cs); - group = Resolve(cs->group, &object); + group = SpriteGroup::Resolve(cs->group, &object); if (group == NULL) return 0; return group->GetResult(); @@ -91,7 +91,7 @@ uint16 GetCargoCallback(CallbackID callback, uint32 param1, uint32 param2, const object.callback_param1 = param1; object.callback_param2 = param2; - group = Resolve(cs->group, &object); + group = SpriteGroup::Resolve(cs->group, &object); if (group == NULL) return CALLBACK_FAILED; return group->GetCallbackResult(); diff --git a/src/newgrf_engine.cpp b/src/newgrf_engine.cpp index 4643488b1b..0878770586 100644 --- a/src/newgrf_engine.cpp +++ b/src/newgrf_engine.cpp @@ -912,7 +912,7 @@ SpriteID GetCustomEngineSprite(EngineID engine, const Vehicle *v, Direction dire NewVehicleResolver(&object, engine, v); - group = Resolve(GetVehicleSpriteGroup(engine, v), &object); + group = SpriteGroup::Resolve(GetVehicleSpriteGroup(engine, v), &object); if (group == NULL || group->GetNumResults() == 0) return 0; return group->GetResult() + (direction % group->GetNumResults()); @@ -934,7 +934,7 @@ SpriteID GetRotorOverrideSprite(EngineID engine, const Aircraft *v, bool info_vi object.info_view = info_view; const SpriteGroup *group = GetWagonOverrideSpriteSet(engine, CT_DEFAULT, engine); - group = Resolve(group, &object); + group = SpriteGroup::Resolve(group, &object); if (group == NULL || group->GetNumResults() == 0) return 0; @@ -975,7 +975,7 @@ uint16 GetVehicleCallback(CallbackID callback, uint32 param1, uint32 param2, Eng object.callback_param1 = param1; object.callback_param2 = param2; - group = Resolve(GetVehicleSpriteGroup(engine, v, false), &object); + group = SpriteGroup::Resolve(GetVehicleSpriteGroup(engine, v, false), &object); if (group == NULL) return CALLBACK_FAILED; return group->GetCallbackResult(); @@ -1004,7 +1004,7 @@ uint16 GetVehicleCallbackParent(CallbackID callback, uint32 param1, uint32 param object.u.vehicle.parent = parent; - group = Resolve(GetVehicleSpriteGroup(engine, v, false), &object); + group = SpriteGroup::Resolve(GetVehicleSpriteGroup(engine, v, false), &object); if (group == NULL) return CALLBACK_FAILED; return group->GetCallbackResult(); @@ -1043,7 +1043,7 @@ static void DoTriggerVehicle(Vehicle *v, VehicleTrigger trigger, byte base_rando object.callback = CBID_RANDOM_TRIGGER; object.trigger = trigger; - group = Resolve(GetVehicleSpriteGroup(v->engine_type, v), &object); + group = SpriteGroup::Resolve(GetVehicleSpriteGroup(v->engine_type, v), &object); if (group == NULL) return; new_random_bits = Random(); diff --git a/src/newgrf_generic.cpp b/src/newgrf_generic.cpp index 0ca9fba771..aa5ee0c225 100644 --- a/src/newgrf_generic.cpp +++ b/src/newgrf_generic.cpp @@ -139,7 +139,7 @@ static uint16 GetGenericCallbackResult(uint8 feature, ResolverObject *object, co /* Test each feature callback sprite group. */ for (GenericCallbackList::const_iterator it = _gcl[feature].begin(); it != _gcl[feature].end(); ++it) { const SpriteGroup *group = it->group; - group = Resolve(group, object); + group = SpriteGroup::Resolve(group, object); if (group == NULL) continue; /* Return NewGRF file if necessary */ diff --git a/src/newgrf_house.cpp b/src/newgrf_house.cpp index f49da4603f..f1585f97e5 100644 --- a/src/newgrf_house.cpp +++ b/src/newgrf_house.cpp @@ -354,7 +354,7 @@ uint16 GetHouseCallback(CallbackID callback, uint32 param1, uint32 param2, House object.callback_param1 = param1; object.callback_param2 = param2; - group = Resolve(GetHouseSpecs(house_id)->spritegroup, &object); + group = SpriteGroup::Resolve(GetHouseSpecs(house_id)->spritegroup, &object); if (group == NULL) return CALLBACK_FAILED; return group->GetCallbackResult(); @@ -422,7 +422,7 @@ void DrawNewHouseTile(TileInfo *ti, HouseID house_id) NewHouseResolver(&object, house_id, ti->tile, GetTownByTile(ti->tile)); - group = Resolve(hs->spritegroup, &object); + group = SpriteGroup::Resolve(hs->spritegroup, &object); if (group == NULL || group->type != SGT_TILELAYOUT) { /* XXX: This is for debugging purposes really, and shouldn't stay. */ DrawGroundSprite(SPR_SHADOW_CELL, PAL_NONE); @@ -601,7 +601,7 @@ static void DoTriggerHouse(TileIndex tile, HouseTrigger trigger, byte base_rando object.callback = CBID_RANDOM_TRIGGER; object.trigger = trigger; - const SpriteGroup *group = Resolve(hs->spritegroup, &object); + const SpriteGroup *group = SpriteGroup::Resolve(hs->spritegroup, &object); if (group == NULL) return; byte new_random_bits = Random(); diff --git a/src/newgrf_industries.cpp b/src/newgrf_industries.cpp index a17f004de7..10ae618fe8 100644 --- a/src/newgrf_industries.cpp +++ b/src/newgrf_industries.cpp @@ -387,7 +387,7 @@ uint16 GetIndustryCallback(CallbackID callback, uint32 param1, uint32 param2, In object.callback_param1 = param1; object.callback_param2 = param2; - group = Resolve(GetIndustrySpec(type)->grf_prop.spritegroup, &object); + group = SpriteGroup::Resolve(GetIndustrySpec(type)->grf_prop.spritegroup, &object); if (group == NULL) return CALLBACK_FAILED; return group->GetCallbackResult(); @@ -461,7 +461,7 @@ bool CheckIfCallBackAllowsCreation(TileIndex tile, IndustryType type, uint itspe object.callback = CBID_INDUSTRY_LOCATION; _industry_creation_random_bits = seed; - group = Resolve(GetIndustrySpec(type)->grf_prop.spritegroup, &object); + group = SpriteGroup::Resolve(GetIndustrySpec(type)->grf_prop.spritegroup, &object); /* 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. */ @@ -531,7 +531,7 @@ void IndustryProductionCallback(Industry *ind, int reason) } SB(object.callback_param2, 8, 16, loop); - const SpriteGroup *tgroup = Resolve(spec->grf_prop.spritegroup, &object); + const SpriteGroup *tgroup = SpriteGroup::Resolve(spec->grf_prop.spritegroup, &object); 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 86a6a8222d..89c4a02799 100644 --- a/src/newgrf_industrytiles.cpp +++ b/src/newgrf_industrytiles.cpp @@ -221,7 +221,7 @@ uint16 GetIndustryTileCallback(CallbackID callback, uint32 param1, uint32 param2 object.callback_param1 = param1; object.callback_param2 = param2; - group = Resolve(GetIndustryTileSpec(gfx_id)->grf_prop.spritegroup, &object); + group = SpriteGroup::Resolve(GetIndustryTileSpec(gfx_id)->grf_prop.spritegroup, &object); if (group == NULL || group->type != SGT_CALLBACK) return CALLBACK_FAILED; return group->GetCallbackResult(); @@ -245,7 +245,7 @@ bool DrawNewIndustryTile(TileInfo *ti, Industry *i, IndustryGfx gfx, const Indus NewIndustryTileResolver(&object, gfx, ti->tile, i); - group = Resolve(inds->grf_prop.spritegroup, &object); + group = SpriteGroup::Resolve(inds->grf_prop.spritegroup, &object); if (group == NULL || group->type != SGT_TILELAYOUT) { return false; } else { @@ -416,7 +416,7 @@ static void DoTriggerIndustryTile(TileIndex tile, IndustryTileTrigger trigger, I object.callback = CBID_RANDOM_TRIGGER; object.trigger = trigger; - const SpriteGroup *group = Resolve(itspec->grf_prop.spritegroup, &object); + const SpriteGroup *group = SpriteGroup::Resolve(itspec->grf_prop.spritegroup, &object); if (group == NULL) return; byte new_random_bits = Random(); diff --git a/src/newgrf_spritegroup.cpp b/src/newgrf_spritegroup.cpp index 03fa75f908..f6dc2aa13e 100644 --- a/src/newgrf_spritegroup.cpp +++ b/src/newgrf_spritegroup.cpp @@ -121,23 +121,23 @@ static U EvalAdjustT(const DeterministicSpriteGroupAdjust *adjust, ResolverObjec } -static inline const SpriteGroup *ResolveVariable(const DeterministicSpriteGroup *group, ResolverObject *object) +const SpriteGroup *DeterministicSpriteGroup::Resolve(ResolverObject *object) const { uint32 last_value = 0; uint32 value = 0; uint i; - object->scope = group->var_scope; + object->scope = this->var_scope; - for (i = 0; i < group->num_adjusts; i++) { - DeterministicSpriteGroupAdjust *adjust = &group->adjusts[i]; + for (i = 0; i < this->num_adjusts; i++) { + DeterministicSpriteGroupAdjust *adjust = &this->adjusts[i]; /* Try to get the variable. We shall assume it is available, unless told otherwise. */ bool available = true; if (adjust->variable == 0x7E) { ResolverObject subobject = *object; subobject.procedure_call = true; - const SpriteGroup *subgroup = Resolve(adjust->subroutine, &subobject); + const SpriteGroup *subgroup = SpriteGroup::Resolve(adjust->subroutine, &subobject); if (subgroup == NULL) { value = CALLBACK_FAILED; } else { @@ -150,10 +150,10 @@ static inline const SpriteGroup *ResolveVariable(const DeterministicSpriteGroup if (!available) { /* Unsupported property: skip further processing and return either * the group from the first range or the default group. */ - return Resolve(group->num_ranges > 0 ? group->ranges[0].group : group->default_group, object); + return SpriteGroup::Resolve(this->num_ranges > 0 ? this->ranges[0].group : this->default_group, object); } - switch (group->size) { + switch (this->size) { case DSG_SIZE_BYTE: value = EvalAdjustT (adjust, object, last_value, value); break; case DSG_SIZE_WORD: value = EvalAdjustT(adjust, object, last_value, value); break; case DSG_SIZE_DWORD: value = EvalAdjustT(adjust, object, last_value, value); break; @@ -164,7 +164,7 @@ static inline const SpriteGroup *ResolveVariable(const DeterministicSpriteGroup object->last_value = last_value; - if (group->num_ranges == 0) { + if (this->num_ranges == 0) { /* nvar == 0 is a special case -- we turn our value into a callback result */ if (value != CALLBACK_FAILED) value = GB(value, 0, 15); static CallbackResultSpriteGroup nvarzero(0); @@ -172,34 +172,34 @@ static inline const SpriteGroup *ResolveVariable(const DeterministicSpriteGroup return &nvarzero; } - for (i = 0; i < group->num_ranges; i++) { - if (group->ranges[i].low <= value && value <= group->ranges[i].high) { - return Resolve(group->ranges[i].group, object); + for (i = 0; i < this->num_ranges; i++) { + if (this->ranges[i].low <= value && value <= this->ranges[i].high) { + return SpriteGroup::Resolve(this->ranges[i].group, object); } } - return Resolve(group->default_group, object); + return SpriteGroup::Resolve(this->default_group, object); } -static inline const SpriteGroup *ResolveRandom(const RandomizedSpriteGroup *group, ResolverObject *object) +const SpriteGroup *RandomizedSpriteGroup::Resolve(ResolverObject *object) const { uint32 mask; byte index; - object->scope = group->var_scope; - object->count = group->count; + object->scope = this->var_scope; + object->count = this->count; if (object->trigger != 0) { /* Handle triggers */ /* Magic code that may or may not do the right things... */ byte waiting_triggers = object->GetTriggers(object); - byte match = group->triggers & (waiting_triggers | object->trigger); - bool res = (group->cmp_mode == RSG_CMP_ANY) ? (match != 0) : (match == group->triggers); + byte match = this->triggers & (waiting_triggers | object->trigger); + bool res = (this->cmp_mode == RSG_CMP_ANY) ? (match != 0) : (match == this->triggers); if (res) { waiting_triggers &= ~match; - object->reseed |= (group->num_groups - 1) << group->lowest_randbit; + object->reseed |= (this->num_groups - 1) << this->lowest_randbit; } else { waiting_triggers |= object->trigger; } @@ -207,23 +207,14 @@ static inline const SpriteGroup *ResolveRandom(const RandomizedSpriteGroup *grou object->SetTriggers(object, waiting_triggers); } - mask = (group->num_groups - 1) << group->lowest_randbit; - index = (object->GetRandomBits(object) & mask) >> group->lowest_randbit; + mask = (this->num_groups - 1) << this->lowest_randbit; + index = (object->GetRandomBits(object) & mask) >> this->lowest_randbit; - return Resolve(group->groups[index], object); + return SpriteGroup::Resolve(this->groups[index], object); } -/* ResolverObject (re)entry point */ -const SpriteGroup *Resolve(const SpriteGroup *group, ResolverObject *object) +const SpriteGroup *RealSpriteGroup::Resolve(ResolverObject *object) const { - /* We're called even if there is no group, so quietly return nothing */ - if (group == NULL) return NULL; - - switch (group->type) { - case SGT_REAL: return object->ResolveReal(object, (RealSpriteGroup *)group); - case SGT_DETERMINISTIC: return ResolveVariable((DeterministicSpriteGroup *)group, object); - case SGT_RANDOMIZED: return ResolveRandom((RandomizedSpriteGroup *)group, object); - default: return group; - } + return object->ResolveReal(object, this); } diff --git a/src/newgrf_spritegroup.h b/src/newgrf_spritegroup.h index 13cfb19c61..e6bbeb9d39 100644 --- a/src/newgrf_spritegroup.h +++ b/src/newgrf_spritegroup.h @@ -50,6 +50,8 @@ extern SpriteGroupPool _spritegroup_pool; struct SpriteGroup : SpriteGroupPool::PoolItem<&_spritegroup_pool> { protected: SpriteGroup(SpriteGroupType type) : type(type) {} + /** Base sprite group resolver */ + virtual const SpriteGroup *Resolve(struct ResolverObject *object) const { return this; }; public: virtual ~SpriteGroup() {} @@ -59,6 +61,20 @@ public: virtual SpriteID GetResult() const { return 0; } virtual byte GetNumResults() const { return 0; } virtual uint16 GetCallbackResult() const { return CALLBACK_FAILED; } + + /** + * ResolverObject (re)entry point. + * This cannot be made a call to a virtual function because virtual functions + * do not like NULL and checking for NULL *everywhere* is more cumbersome than + * this little helper function. + * @param group the group to resolve for + * @param object information needed to resolve the group + * @return the resolved group + */ + static const SpriteGroup *Resolve(const SpriteGroup *group, ResolverObject *object) + { + return group == NULL ? NULL : group->Resolve(object); + } }; @@ -79,6 +95,9 @@ struct RealSpriteGroup : SpriteGroup { byte num_loading; ///< Number of loading groups const SpriteGroup **loaded; ///< List of loaded groups (can be SpriteIDs or Callback results) const SpriteGroup **loading; ///< List of loading groups (can be SpriteIDs or Callback results) + +protected: + const SpriteGroup *Resolve(ResolverObject *object) const; }; /* Shared by deterministic and random groups. */ @@ -159,6 +178,9 @@ struct DeterministicSpriteGroup : SpriteGroup { /* Dynamically allocated, this is the sole owner */ const SpriteGroup *default_group; + +protected: + const SpriteGroup *Resolve(ResolverObject *object) const; }; enum RandomizedSpriteGroupCompareMode { @@ -180,6 +202,9 @@ struct RandomizedSpriteGroup : SpriteGroup { byte num_groups; ///< must be power of 2 const SpriteGroup **groups; ///< Take the group with appropriate index: + +protected: + const SpriteGroup *Resolve(ResolverObject *object) const; }; @@ -316,9 +341,4 @@ struct ResolverObject { ResolverObject() : procedure_call(false) { } }; - -/* Base sprite group resolver */ -const SpriteGroup *Resolve(const SpriteGroup *group, ResolverObject *object); - - #endif /* NEWGRF_SPRITEGROUP_H */ diff --git a/src/newgrf_station.cpp b/src/newgrf_station.cpp index 81ce36c2e4..eb2598c27d 100644 --- a/src/newgrf_station.cpp +++ b/src/newgrf_station.cpp @@ -633,7 +633,7 @@ static const SpriteGroup *ResolveStation(ResolverObject *object) /* Invalidate all cached vars */ _svc.valid = 0; - return Resolve(group, object); + return SpriteGroup::Resolve(group, object); } SpriteID GetCustomStationRelocation(const StationSpec *statspec, const Station *st, TileIndex tile)