From a9b8b22daf38be899b5fd13e8028b7a9e5f5bcfc Mon Sep 17 00:00:00 2001 From: alberth Date: Sat, 10 Nov 2012 20:40:46 +0000 Subject: [PATCH] (svn r24683) -Codechange: Add resolver classes for objects. --- src/newgrf_object.cpp | 160 +++++++++++++--------------------- src/newgrf_object.h | 44 ++++++++++ src/newgrf_spritegroup.h | 5 -- src/table/newgrf_debug_data.h | 7 +- 4 files changed, 111 insertions(+), 105 deletions(-) diff --git a/src/newgrf_object.cpp b/src/newgrf_object.cpp index ab4ac147e0..f09e94b3b3 100644 --- a/src/newgrf_object.cpp +++ b/src/newgrf_object.cpp @@ -16,8 +16,6 @@ #include "newgrf_class_func.h" #include "newgrf_object.h" #include "newgrf_sound.h" -#include "newgrf_spritegroup.h" -#include "newgrf_town.h" #include "object_base.h" #include "object_map.h" #include "tile_cmd.h" @@ -118,23 +116,19 @@ bool NewGRFClass::IsUIAvailable(uint index) const INSTANTIATE_NEWGRF_CLASS_METHODS(ObjectClass, ObjectSpec, ObjectClassID, OBJECT_CLASS_MAX) - -static uint32 ObjectGetRandomBits(const ResolverObject *object) +ObjectScopeResolver::ObjectScopeResolver(ResolverObject *ro, Object *obj, TileIndex tile, uint8 view) + : ScopeResolver(ro) { - TileIndex t = object->u.object.tile; - return IsValidTile(t) && IsTileType(t, MP_OBJECT) ? GetObjectRandomBits(t) : 0; + this->obj = obj; + this->tile = tile; + this->view = view; } -static uint32 ObjectGetTriggers(const ResolverObject *object) +/* virtual */ uint32 ObjectScopeResolver::GetRandomBits() const { - return 0; + return IsValidTile(this->tile) && IsTileType(this->tile, MP_OBJECT) ? GetObjectRandomBits(this->tile) : 0; } -static void ObjectSetTriggers(const ResolverObject *object, int triggers) -{ -} - - /** * Make an analysis of a tile and get the object type. * @param tile TileIndex of the tile to query @@ -232,21 +226,13 @@ static uint32 GetCountAndDistanceOfClosestInstance(byte local_id, uint32 grfid, } /** Used by the resolver to get values for feature 0F deterministic spritegroups. */ -static uint32 ObjectGetVariable(const ResolverObject *object, byte variable, uint32 parameter, bool *available) +/* virtual */ uint32 ObjectScopeResolver::GetVariable(byte variable, uint32 parameter, bool *available) const { - const Object *o = object->u.object.o; - TileIndex tile = object->u.object.tile; - - if (object->scope == VSG_SCOPE_PARENT) { - /* Pass the request on to the town of the object */ - return TownGetVariable(variable, parameter, available, (o == NULL) ? ClosestTownFromTile(tile, UINT_MAX) : o->town, object->grffile); - } - /* We get the town from the object, or we calculate the closest * town if we need to when there's no object. */ const Town *t = NULL; - if (o == NULL) { + if (this->obj == NULL) { switch (variable) { /* Allow these when there's no object. */ case 0x41: @@ -259,8 +245,8 @@ static uint32 ObjectGetVariable(const ResolverObject *object, byte variable, uin /* Allow these, but find the closest town. */ case 0x45: case 0x46: - if (!IsValidTile(tile)) goto unhandled; - t = ClosestTownFromTile(tile, UINT_MAX); + if (!IsValidTile(this->tile)) goto unhandled; + t = ClosestTownFromTile(this->tile, UINT_MAX); break; /* Construction date */ @@ -270,7 +256,7 @@ static uint32 ObjectGetVariable(const ResolverObject *object, byte variable, uin case 0x44: return _current_company; /* Object view */ - case 0x48: return object->u.object.view; + case 0x48: return this->view; /* * Disallow the rest: @@ -284,62 +270,64 @@ static uint32 ObjectGetVariable(const ResolverObject *object, byte variable, uin } /* If there's an invalid tile, then we don't have enough information at all. */ - if (!IsValidTile(tile)) goto unhandled; + if (!IsValidTile(this->tile)) goto unhandled; } else { - t = o->town; + t = this->obj->town; } switch (variable) { /* Relative position. */ case 0x40: { - uint offset = tile - o->location.tile; + uint offset = this->tile - this->obj->location.tile; uint offset_x = TileX(offset); uint offset_y = TileY(offset); return offset_y << 20 | offset_x << 16 | offset_y << 8 | offset_x; } /* Tile information. */ - case 0x41: return GetTileSlope(tile) << 8 | GetTerrainType(tile); + case 0x41: return GetTileSlope(this->tile) << 8 | GetTerrainType(this->tile); /* Construction date */ - case 0x42: return o->build_date; + case 0x42: return this->obj->build_date; /* Animation counter */ - case 0x43: return GetAnimationFrame(tile); + case 0x43: return GetAnimationFrame(this->tile); /* Object founder information */ - case 0x44: return GetTileOwner(tile); + case 0x44: return GetTileOwner(this->tile); /* Get town zone and Manhattan distance of closest town */ - case 0x45: return GetTownRadiusGroup(t, tile) << 16 | min(DistanceManhattan(tile, t->xy), 0xFFFF); + case 0x45: return GetTownRadiusGroup(t, this->tile) << 16 | min(DistanceManhattan(this->tile, t->xy), 0xFFFF); /* Get square of Euclidian distance of closes town */ - case 0x46: return GetTownRadiusGroup(t, tile) << 16 | min(DistanceSquare(tile, t->xy), 0xFFFF); + case 0x46: return GetTownRadiusGroup(t, this->tile) << 16 | min(DistanceSquare(this->tile, t->xy), 0xFFFF); /* Object colour */ - case 0x47: return o->colour; + case 0x47: return this->obj->colour; /* Object view */ - case 0x48: return o->view; + case 0x48: return this->obj->view; /* Get object ID at offset param */ - case 0x60: return GetObjectIDAtOffset(GetNearbyTile(parameter, tile), object->grffile->grfid); + case 0x60: return GetObjectIDAtOffset(GetNearbyTile(parameter, this->tile), this->ro->grffile->grfid); /* Get random tile bits at offset param */ - case 0x61: - tile = GetNearbyTile(parameter, tile); - return (IsTileType(tile, MP_OBJECT) && Object::GetByTile(tile) == o) ? GetObjectRandomBits(tile) : 0; + case 0x61: { + TileIndex tile = GetNearbyTile(parameter, this->tile); + return (IsTileType(tile, MP_OBJECT) && Object::GetByTile(tile) == this->obj) ? GetObjectRandomBits(tile) : 0; + } /* Land info of nearby tiles */ - case 0x62: return GetNearbyObjectTileInformation(parameter, tile, o == NULL ? INVALID_OBJECT : o->index, object->grffile->grf_version >= 8); + case 0x62: return GetNearbyObjectTileInformation(parameter, this->tile, this->obj == NULL ? INVALID_OBJECT : this->obj->index, this->ro->grffile->grf_version >= 8); /* Animation counter of nearby tile */ - case 0x63: - tile = GetNearbyTile(parameter, tile); - return (IsTileType(tile, MP_OBJECT) && Object::GetByTile(tile) == o) ? GetAnimationFrame(tile) : 0; + case 0x63: { + TileIndex tile = GetNearbyTile(parameter, this->tile); + return (IsTileType(tile, MP_OBJECT) && Object::GetByTile(tile) == this->obj) ? GetAnimationFrame(tile) : 0; + } /* Count of object, distance of closest instance */ - case 0x64: return GetCountAndDistanceOfClosestInstance(parameter, object->grffile->grfid, tile, o); + case 0x64: return GetCountAndDistanceOfClosestInstance(parameter, this->ro->grffile->grfid, this->tile, this->obj); } unhandled: @@ -349,7 +337,7 @@ unhandled: return UINT_MAX; } -static const SpriteGroup *ObjectResolveReal(const ResolverObject *object, const RealSpriteGroup *group) +/* virtual */ const SpriteGroup *ObjectResolverObject::ResolveReal(const RealSpriteGroup *group) const { /* Objects do not have 'real' groups */ return NULL; @@ -373,44 +361,36 @@ static const SpriteGroup *GetObjectSpriteGroup(const ObjectSpec *spec, const Obj } -/** - * Store a value into the persistent storage of the object's parent. - * @param object Object that we want to query. - * @param pos Position in the persistent storage to use. - * @param value Value to store. - */ -void ObjectStorePSA(ResolverObject *object, uint pos, int32 value) +ObjectResolverObject::ObjectResolverObject(const ObjectSpec *spec, Object *obj, TileIndex tile, uint8 view, + CallbackID callback, uint32 param1, uint32 param2) + : ResolverObject(spec->grf_prop.grffile, callback, param1, param2), object_scope(this, obj, tile, view) { - /* Objects have no persistent storage. */ - Object *o = object->u.object.o; - if (object->scope != VSG_SCOPE_PARENT || o == NULL) return; + this->town_scope = NULL; +} - /* Pass the request on to the town of the object */ - TownStorePSA(o->town, object->grffile, pos, value); +ObjectResolverObject::~ObjectResolverObject() +{ + delete this->town_scope; } /** - * Returns a resolver object to be used with feature 0F spritegroups. + * Get the town resolver scope that belongs to this object resolver. + * On the first call, the town scope is created (if possible). + * @return Town scope, if available. */ -static void NewObjectResolver(ResolverObject *res, const ObjectSpec *spec, Object *o, TileIndex tile, uint8 view = 0) +TownScopeResolver *ObjectResolverObject::GetTown() { - res->GetRandomBits = ObjectGetRandomBits; - res->GetTriggers = ObjectGetTriggers; - res->SetTriggers = ObjectSetTriggers; - res->GetVariable = ObjectGetVariable; - res->ResolveRealMethod = ObjectResolveReal; - res->StorePSA = ObjectStorePSA; - - res->u.object.o = o; - res->u.object.tile = tile; - res->u.object.view = view; - - res->callback = CBID_NO_CALLBACK; - res->callback_param1 = 0; - res->callback_param2 = 0; - res->ResetState(); - - res->grffile = spec->grf_prop.grffile; + if (this->town_scope == NULL) { + Town *t; + if (this->object_scope.obj != NULL) { + t = this->object_scope.obj->town; + } else { + t = ClosestTownFromTile(this->object_scope.tile, UINT_MAX); + } + if (t == NULL) return NULL; + this->town_scope = new TownScopeResolver(this, t, this->object_scope.obj == NULL); + } + return this->town_scope; } /** @@ -426,12 +406,7 @@ static void NewObjectResolver(ResolverObject *res, const ObjectSpec *spec, Objec */ uint16 GetObjectCallback(CallbackID callback, uint32 param1, uint32 param2, const ObjectSpec *spec, Object *o, TileIndex tile, uint8 view) { - ResolverObject object; - NewObjectResolver(&object, spec, o, tile, view); - object.callback = callback; - object.callback_param1 = param1; - object.callback_param2 = param2; - + ObjectResolverObject object(spec, o, tile, view, callback, param1, param2); const SpriteGroup *group = SpriteGroup::Resolve(GetObjectSpriteGroup(spec, o), &object); if (group == NULL) return CALLBACK_FAILED; @@ -472,9 +447,8 @@ static void DrawTileLayout(const TileInfo *ti, const TileLayoutSpriteGroup *grou */ void DrawNewObjectTile(TileInfo *ti, const ObjectSpec *spec) { - ResolverObject object; Object *o = Object::GetByTile(ti->tile); - NewObjectResolver(&object, spec, o, ti->tile); + ObjectResolverObject object(spec, o, ti->tile); const SpriteGroup *group = SpriteGroup::Resolve(GetObjectSpriteGroup(spec, o), &object); if (group == NULL || group->type != SGT_TILELAYOUT) return; @@ -491,9 +465,7 @@ void DrawNewObjectTile(TileInfo *ti, const ObjectSpec *spec) */ void DrawNewObjectTileInGUI(int x, int y, const ObjectSpec *spec, uint8 view) { - ResolverObject object; - NewObjectResolver(&object, spec, NULL, INVALID_TILE, view); - + ObjectResolverObject object(spec, NULL, INVALID_TILE, view); const SpriteGroup *group = SpriteGroup::Resolve(GetObjectSpriteGroup(spec, NULL), &object); if (group == NULL || group->type != SGT_TILELAYOUT) return; @@ -588,13 +560,3 @@ void TriggerObjectAnimation(Object *o, ObjectAnimationTrigger trigger, const Obj TriggerObjectTileAnimation(o, tile, trigger, spec); } } - -/** - * Resolve an object's spec and such so we can get a variable. - * @param ro The resolver object to fill. - * @param index The object tile to get the data from. - */ -void GetObjectResolver(ResolverObject *ro, uint index) -{ - NewObjectResolver(ro, ObjectSpec::GetByTile(index), Object::GetByTile(index), index); -} diff --git a/src/newgrf_object.h b/src/newgrf_object.h index bc2f64f3c6..c1b79959de 100644 --- a/src/newgrf_object.h +++ b/src/newgrf_object.h @@ -13,6 +13,8 @@ #define NEWGRF_OBJECT_H #include "newgrf_callbacks.h" +#include "newgrf_spritegroup.h" +#include "newgrf_town.h" #include "economy_func.h" #include "date_type.h" #include "object_type.h" @@ -90,6 +92,48 @@ struct ObjectSpec { static const ObjectSpec *GetByTile(TileIndex tile); }; +struct ObjectScopeResolver : public ScopeResolver { + struct Object *obj; ///< The object the callback is ran for. + TileIndex tile; ///< The tile related to the object. + uint8 view; ///< The view of the object. + + ObjectScopeResolver(ResolverObject *ro, Object *obj, TileIndex tile, uint8 view = 0); + + /* virtual */ uint32 GetRandomBits() const; + /* virtual */ uint32 GetVariable(byte variable, uint32 parameter, bool *available) const; +}; + +/** A resolver object to be used with feature 0F spritegroups. */ +struct ObjectResolverObject : public ResolverObject { + ObjectScopeResolver object_scope; + TownScopeResolver *town_scope; + + ObjectResolverObject(const ObjectSpec *spec, Object *o, TileIndex tile, uint8 view = 0, + CallbackID callback = CBID_NO_CALLBACK, uint32 param1 = 0, uint32 param2 = 0); + ~ObjectResolverObject(); + + /* virtual */ ScopeResolver *GetScope(VarSpriteGroupScope scope = VSG_SCOPE_SELF, byte relative = 0) + { + switch (scope) { + case VSG_SCOPE_SELF: + return &this->object_scope; + + case VSG_SCOPE_PARENT: { + TownScopeResolver *tsr = this->GetTown(); + if (tsr != NULL) return tsr; + /* FALL-THROUGH */ + } + + default: return &this->default_scope; // XXX return &ResolverObject::GetScope(scope, relative); + } + } + + const SpriteGroup *ResolveReal(const RealSpriteGroup *group) const; + +private: + TownScopeResolver *GetTown(); +}; + /** Struct containing information relating to station classes. */ typedef NewGRFClass ObjectClass; diff --git a/src/newgrf_spritegroup.h b/src/newgrf_spritegroup.h index 41a6c2e258..d68f2e316b 100644 --- a/src/newgrf_spritegroup.h +++ b/src/newgrf_spritegroup.h @@ -390,11 +390,6 @@ struct ResolverObject { byte layout; ///< Layout of the airport to build. TileIndex tile; ///< Tile for the callback, only valid for airporttile callbacks. } airport; - struct { - struct Object *o; ///< The object the callback is ran for. - TileIndex tile; ///< The tile related to the object. - uint8 view; ///< The view of the object. - } object; } u; uint32 (*GetRandomBits)(const struct ResolverObject*); diff --git a/src/table/newgrf_debug_data.h b/src/table/newgrf_debug_data.h index c7f9365873..8a669fee58 100644 --- a/src/table/newgrf_debug_data.h +++ b/src/table/newgrf_debug_data.h @@ -361,7 +361,12 @@ class NIHObject : public NIHelper { const void *GetSpec(uint index) const { return ObjectSpec::GetByTile(index); } void SetStringParameters(uint index) const { this->SetObjectAtStringParameters(STR_NEWGRF_INSPECT_CAPTION_OBJECT_AT_OBJECT, INVALID_STRING_ID, index); } uint32 GetGRFID(uint index) const { return (this->IsInspectable(index)) ? ObjectSpec::GetByTile(index)->grf_prop.grffile->grfid : 0; } - void Resolve(ResolverObject *ro, uint32 index) const { extern void GetObjectResolver(ResolverObject *ro, uint index); GetObjectResolver(ro, index); } + + /* virtual */ uint Resolve(uint index, uint var, uint param, bool *avail) const + { + ObjectResolverObject ro(ObjectSpec::GetByTile(index), Object::GetByTile(index), index); + return ro.GetScope(ro.scope)->GetVariable(var, param, avail); + } }; static const NIFeature _nif_object = {