(svn r16402) -Codechange: make Resolve a function of SpriteGroup

This commit is contained in:
rubidium 2009-05-23 15:25:52 +00:00
parent 8d072585ae
commit f2317d0d9d
10 changed files with 67 additions and 56 deletions

View File

@ -96,7 +96,7 @@ SpriteID GetCanalSprite(CanalFeature feature, TileIndex tile)
NewCanalResolver(&object, tile, _water_feature[feature].grffile); 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; if (group == NULL) return 0;
return group->GetResult(); return group->GetResult();

View File

@ -74,7 +74,7 @@ SpriteID GetCustomCargoSprite(const CargoSpec *cs)
NewCargoResolver(&object, cs); NewCargoResolver(&object, cs);
group = Resolve(cs->group, &object); group = SpriteGroup::Resolve(cs->group, &object);
if (group == NULL) return 0; if (group == NULL) return 0;
return group->GetResult(); return group->GetResult();
@ -91,7 +91,7 @@ uint16 GetCargoCallback(CallbackID callback, uint32 param1, uint32 param2, const
object.callback_param1 = param1; object.callback_param1 = param1;
object.callback_param2 = param2; object.callback_param2 = param2;
group = Resolve(cs->group, &object); group = SpriteGroup::Resolve(cs->group, &object);
if (group == NULL) return CALLBACK_FAILED; if (group == NULL) return CALLBACK_FAILED;
return group->GetCallbackResult(); return group->GetCallbackResult();

View File

@ -912,7 +912,7 @@ SpriteID GetCustomEngineSprite(EngineID engine, const Vehicle *v, Direction dire
NewVehicleResolver(&object, engine, v); 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; if (group == NULL || group->GetNumResults() == 0) return 0;
return group->GetResult() + (direction % group->GetNumResults()); 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; object.info_view = info_view;
const SpriteGroup *group = GetWagonOverrideSpriteSet(engine, CT_DEFAULT, engine); 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; 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_param1 = param1;
object.callback_param2 = param2; 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; if (group == NULL) return CALLBACK_FAILED;
return group->GetCallbackResult(); return group->GetCallbackResult();
@ -1004,7 +1004,7 @@ uint16 GetVehicleCallbackParent(CallbackID callback, uint32 param1, uint32 param
object.u.vehicle.parent = parent; 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; if (group == NULL) return CALLBACK_FAILED;
return group->GetCallbackResult(); return group->GetCallbackResult();
@ -1043,7 +1043,7 @@ static void DoTriggerVehicle(Vehicle *v, VehicleTrigger trigger, byte base_rando
object.callback = CBID_RANDOM_TRIGGER; object.callback = CBID_RANDOM_TRIGGER;
object.trigger = 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; if (group == NULL) return;
new_random_bits = Random(); new_random_bits = Random();

View File

@ -139,7 +139,7 @@ static uint16 GetGenericCallbackResult(uint8 feature, ResolverObject *object, co
/* Test each feature callback sprite group. */ /* Test each feature callback sprite group. */
for (GenericCallbackList::const_iterator it = _gcl[feature].begin(); it != _gcl[feature].end(); ++it) { for (GenericCallbackList::const_iterator it = _gcl[feature].begin(); it != _gcl[feature].end(); ++it) {
const SpriteGroup *group = it->group; const SpriteGroup *group = it->group;
group = Resolve(group, object); group = SpriteGroup::Resolve(group, object);
if (group == NULL) continue; if (group == NULL) continue;
/* Return NewGRF file if necessary */ /* Return NewGRF file if necessary */

View File

@ -354,7 +354,7 @@ uint16 GetHouseCallback(CallbackID callback, uint32 param1, uint32 param2, House
object.callback_param1 = param1; object.callback_param1 = param1;
object.callback_param2 = param2; 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; if (group == NULL) return CALLBACK_FAILED;
return group->GetCallbackResult(); return group->GetCallbackResult();
@ -422,7 +422,7 @@ void DrawNewHouseTile(TileInfo *ti, HouseID house_id)
NewHouseResolver(&object, house_id, ti->tile, GetTownByTile(ti->tile)); 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) { if (group == NULL || group->type != SGT_TILELAYOUT) {
/* XXX: This is for debugging purposes really, and shouldn't stay. */ /* XXX: This is for debugging purposes really, and shouldn't stay. */
DrawGroundSprite(SPR_SHADOW_CELL, PAL_NONE); 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.callback = CBID_RANDOM_TRIGGER;
object.trigger = trigger; object.trigger = trigger;
const SpriteGroup *group = Resolve(hs->spritegroup, &object); const SpriteGroup *group = SpriteGroup::Resolve(hs->spritegroup, &object);
if (group == NULL) return; if (group == NULL) return;
byte new_random_bits = Random(); byte new_random_bits = Random();

View File

@ -387,7 +387,7 @@ uint16 GetIndustryCallback(CallbackID callback, uint32 param1, uint32 param2, In
object.callback_param1 = param1; object.callback_param1 = param1;
object.callback_param2 = param2; 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; if (group == NULL) return CALLBACK_FAILED;
return group->GetCallbackResult(); return group->GetCallbackResult();
@ -461,7 +461,7 @@ bool CheckIfCallBackAllowsCreation(TileIndex tile, IndustryType type, uint itspe
object.callback = CBID_INDUSTRY_LOCATION; object.callback = CBID_INDUSTRY_LOCATION;
_industry_creation_random_bits = seed; _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 /* 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. */ * 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); 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; if (tgroup == NULL || tgroup->type != SGT_INDUSTRY_PRODUCTION) break;
const IndustryProductionSpriteGroup *group = (const IndustryProductionSpriteGroup *)tgroup; const IndustryProductionSpriteGroup *group = (const IndustryProductionSpriteGroup *)tgroup;

View File

@ -221,7 +221,7 @@ uint16 GetIndustryTileCallback(CallbackID callback, uint32 param1, uint32 param2
object.callback_param1 = param1; object.callback_param1 = param1;
object.callback_param2 = param2; 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; if (group == NULL || group->type != SGT_CALLBACK) return CALLBACK_FAILED;
return group->GetCallbackResult(); return group->GetCallbackResult();
@ -245,7 +245,7 @@ bool DrawNewIndustryTile(TileInfo *ti, Industry *i, IndustryGfx gfx, const Indus
NewIndustryTileResolver(&object, gfx, ti->tile, i); 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) { if (group == NULL || group->type != SGT_TILELAYOUT) {
return false; return false;
} else { } else {
@ -416,7 +416,7 @@ static void DoTriggerIndustryTile(TileIndex tile, IndustryTileTrigger trigger, I
object.callback = CBID_RANDOM_TRIGGER; object.callback = CBID_RANDOM_TRIGGER;
object.trigger = 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; if (group == NULL) return;
byte new_random_bits = Random(); byte new_random_bits = Random();

View File

@ -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 last_value = 0;
uint32 value = 0; uint32 value = 0;
uint i; uint i;
object->scope = group->var_scope; object->scope = this->var_scope;
for (i = 0; i < group->num_adjusts; i++) { for (i = 0; i < this->num_adjusts; i++) {
DeterministicSpriteGroupAdjust *adjust = &group->adjusts[i]; DeterministicSpriteGroupAdjust *adjust = &this->adjusts[i];
/* Try to get the variable. We shall assume it is available, unless told otherwise. */ /* Try to get the variable. We shall assume it is available, unless told otherwise. */
bool available = true; bool available = true;
if (adjust->variable == 0x7E) { if (adjust->variable == 0x7E) {
ResolverObject subobject = *object; ResolverObject subobject = *object;
subobject.procedure_call = true; subobject.procedure_call = true;
const SpriteGroup *subgroup = Resolve(adjust->subroutine, &subobject); const SpriteGroup *subgroup = SpriteGroup::Resolve(adjust->subroutine, &subobject);
if (subgroup == NULL) { if (subgroup == NULL) {
value = CALLBACK_FAILED; value = CALLBACK_FAILED;
} else { } else {
@ -150,10 +150,10 @@ static inline const SpriteGroup *ResolveVariable(const DeterministicSpriteGroup
if (!available) { if (!available) {
/* Unsupported property: skip further processing and return either /* Unsupported property: skip further processing and return either
* the group from the first range or the default group. */ * 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<uint8, int8> (adjust, object, last_value, value); break; case DSG_SIZE_BYTE: value = EvalAdjustT<uint8, int8> (adjust, object, last_value, value); break;
case DSG_SIZE_WORD: value = EvalAdjustT<uint16, int16>(adjust, object, last_value, value); break; case DSG_SIZE_WORD: value = EvalAdjustT<uint16, int16>(adjust, object, last_value, value); break;
case DSG_SIZE_DWORD: value = EvalAdjustT<uint32, int32>(adjust, object, last_value, value); break; case DSG_SIZE_DWORD: value = EvalAdjustT<uint32, int32>(adjust, object, last_value, value); break;
@ -164,7 +164,7 @@ static inline const SpriteGroup *ResolveVariable(const DeterministicSpriteGroup
object->last_value = last_value; 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 */ /* nvar == 0 is a special case -- we turn our value into a callback result */
if (value != CALLBACK_FAILED) value = GB(value, 0, 15); if (value != CALLBACK_FAILED) value = GB(value, 0, 15);
static CallbackResultSpriteGroup nvarzero(0); static CallbackResultSpriteGroup nvarzero(0);
@ -172,34 +172,34 @@ static inline const SpriteGroup *ResolveVariable(const DeterministicSpriteGroup
return &nvarzero; return &nvarzero;
} }
for (i = 0; i < group->num_ranges; i++) { for (i = 0; i < this->num_ranges; i++) {
if (group->ranges[i].low <= value && value <= group->ranges[i].high) { if (this->ranges[i].low <= value && value <= this->ranges[i].high) {
return Resolve(group->ranges[i].group, object); 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; uint32 mask;
byte index; byte index;
object->scope = group->var_scope; object->scope = this->var_scope;
object->count = group->count; object->count = this->count;
if (object->trigger != 0) { if (object->trigger != 0) {
/* Handle triggers */ /* Handle triggers */
/* Magic code that may or may not do the right things... */ /* Magic code that may or may not do the right things... */
byte waiting_triggers = object->GetTriggers(object); byte waiting_triggers = object->GetTriggers(object);
byte match = group->triggers & (waiting_triggers | object->trigger); byte match = this->triggers & (waiting_triggers | object->trigger);
bool res = (group->cmp_mode == RSG_CMP_ANY) ? (match != 0) : (match == group->triggers); bool res = (this->cmp_mode == RSG_CMP_ANY) ? (match != 0) : (match == this->triggers);
if (res) { if (res) {
waiting_triggers &= ~match; waiting_triggers &= ~match;
object->reseed |= (group->num_groups - 1) << group->lowest_randbit; object->reseed |= (this->num_groups - 1) << this->lowest_randbit;
} else { } else {
waiting_triggers |= object->trigger; waiting_triggers |= object->trigger;
} }
@ -207,23 +207,14 @@ static inline const SpriteGroup *ResolveRandom(const RandomizedSpriteGroup *grou
object->SetTriggers(object, waiting_triggers); object->SetTriggers(object, waiting_triggers);
} }
mask = (group->num_groups - 1) << group->lowest_randbit; mask = (this->num_groups - 1) << this->lowest_randbit;
index = (object->GetRandomBits(object) & mask) >> group->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 *RealSpriteGroup::Resolve(ResolverObject *object) const
const SpriteGroup *Resolve(const SpriteGroup *group, ResolverObject *object)
{ {
/* We're called even if there is no group, so quietly return nothing */ return object->ResolveReal(object, this);
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;
}
} }

View File

@ -50,6 +50,8 @@ extern SpriteGroupPool _spritegroup_pool;
struct SpriteGroup : SpriteGroupPool::PoolItem<&_spritegroup_pool> { struct SpriteGroup : SpriteGroupPool::PoolItem<&_spritegroup_pool> {
protected: protected:
SpriteGroup(SpriteGroupType type) : type(type) {} SpriteGroup(SpriteGroupType type) : type(type) {}
/** Base sprite group resolver */
virtual const SpriteGroup *Resolve(struct ResolverObject *object) const { return this; };
public: public:
virtual ~SpriteGroup() {} virtual ~SpriteGroup() {}
@ -59,6 +61,20 @@ public:
virtual SpriteID GetResult() const { return 0; } virtual SpriteID GetResult() const { return 0; }
virtual byte GetNumResults() const { return 0; } virtual byte GetNumResults() const { return 0; }
virtual uint16 GetCallbackResult() const { return CALLBACK_FAILED; } 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 byte num_loading; ///< Number of loading groups
const SpriteGroup **loaded; ///< List of loaded groups (can be SpriteIDs or Callback results) 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) 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. */ /* Shared by deterministic and random groups. */
@ -159,6 +178,9 @@ struct DeterministicSpriteGroup : SpriteGroup {
/* Dynamically allocated, this is the sole owner */ /* Dynamically allocated, this is the sole owner */
const SpriteGroup *default_group; const SpriteGroup *default_group;
protected:
const SpriteGroup *Resolve(ResolverObject *object) const;
}; };
enum RandomizedSpriteGroupCompareMode { enum RandomizedSpriteGroupCompareMode {
@ -180,6 +202,9 @@ struct RandomizedSpriteGroup : SpriteGroup {
byte num_groups; ///< must be power of 2 byte num_groups; ///< must be power of 2
const SpriteGroup **groups; ///< Take the group with appropriate index: 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) { } ResolverObject() : procedure_call(false) { }
}; };
/* Base sprite group resolver */
const SpriteGroup *Resolve(const SpriteGroup *group, ResolverObject *object);
#endif /* NEWGRF_SPRITEGROUP_H */ #endif /* NEWGRF_SPRITEGROUP_H */

View File

@ -633,7 +633,7 @@ static const SpriteGroup *ResolveStation(ResolverObject *object)
/* Invalidate all cached vars */ /* Invalidate all cached vars */
_svc.valid = 0; _svc.valid = 0;
return Resolve(group, object); return SpriteGroup::Resolve(group, object);
} }
SpriteID GetCustomStationRelocation(const StationSpec *statspec, const Station *st, TileIndex tile) SpriteID GetCustomStationRelocation(const StationSpec *statspec, const Station *st, TileIndex tile)