From 5331b522261af505a7c47b092675c8dd6733207e Mon Sep 17 00:00:00 2001 From: Bastien Bouclet Date: Thu, 1 Jan 2015 21:13:33 +0100 Subject: [PATCH] STARK: Allow resolving resource references --- engines/stark/archiveloader.cpp | 3 --- engines/stark/resourceprovider.cpp | 31 ++++++++++++++++++++++++-- engines/stark/resourceprovider.h | 6 +++++ engines/stark/resourcereference.cpp | 33 ++++++++++++++++++++++++++++ engines/stark/resourcereference.h | 16 ++++++++++++++ engines/stark/resources/resource.cpp | 13 +++++++++++ engines/stark/resources/resource.h | 13 +++-------- engines/stark/stark.cpp | 12 ++++++++++ engines/stark/stark.h | 16 ++++++++++++++ 9 files changed, 128 insertions(+), 15 deletions(-) diff --git a/engines/stark/archiveloader.cpp b/engines/stark/archiveloader.cpp index ea0b36503cc..d71a9c7e03a 100644 --- a/engines/stark/archiveloader.cpp +++ b/engines/stark/archiveloader.cpp @@ -35,9 +35,6 @@ ArchiveLoader::LoadedArchive::LoadedArchive(const Common::String& archiveName) : } _root = importResources(); - - // Resource lifecycle update - _root->onAllLoaded(); } ArchiveLoader::LoadedArchive::~LoadedArchive() { diff --git a/engines/stark/resourceprovider.cpp b/engines/stark/resourceprovider.cpp index 10f1582586d..281d8cd5c56 100644 --- a/engines/stark/resourceprovider.cpp +++ b/engines/stark/resourceprovider.cpp @@ -46,6 +46,9 @@ void ResourceProvider::initGlobal() { Root *root = _archiveLoader->useRoot("x.xarc"); _global->setRoot(root); + // Resource lifecycle update + root->onAllLoaded(); + // Find the global level node Level *global = root->findChildWithSubtype(1); @@ -58,6 +61,9 @@ void ResourceProvider::initGlobal() { _stateProvider->restoreLevelState(global); _global->setLevel(global); + // Resource lifecycle update + global->onAllLoaded(); + //TODO: Retrieve the inventory and April from the global tree } @@ -82,8 +88,29 @@ Current *ResourceProvider::findLocation(uint16 level, uint16 location) { return nullptr; } +Level *ResourceProvider::getLevel(uint16 level) { + Current *current = findLevel(level); + + if (current) { + return current->getLevel(); + } + + return nullptr; +} + +Location *ResourceProvider::getLocation(uint16 level, uint16 location) { + Current *current = findLocation(level, location); + + if (current) { + return current->getLocation(); + } + + return nullptr; +} + void ResourceProvider::requestLocationChange(uint16 level, uint16 location) { Current *currentLocation = new Current(); + _locations.push_back(currentLocation); // Retrieve the level archive name Root *root = _global->getRoot(); @@ -97,6 +124,7 @@ void ResourceProvider::requestLocationChange(uint16 level, uint16 location) { // If we just loaded a resource tree, restore its state if (newlyLoaded) { _stateProvider->restoreLevelState(currentLocation->getLevel()); + currentLocation->getLevel()->onAllLoaded(); } // Retrieve the location archive name @@ -111,10 +139,9 @@ void ResourceProvider::requestLocationChange(uint16 level, uint16 location) { // If we just loaded a resource tree, restore its state if (newlyLoaded) { _stateProvider->restoreLocationState(currentLocation->getLevel(), currentLocation->getLocation()); + currentLocation->getLocation()->onAllLoaded(); } - _locations.push_back(currentLocation); - _locationChangeRequest = true; } diff --git a/engines/stark/resourceprovider.h b/engines/stark/resourceprovider.h index d4505f7f2f2..2d367ec8d1a 100644 --- a/engines/stark/resourceprovider.h +++ b/engines/stark/resourceprovider.h @@ -131,6 +131,12 @@ public: /** Release the global and current resources */ void shutdown(); + /** Obtain the root resource for a loaded level */ + Level *getLevel(uint16 level); + + /** Obtain the root resource for a loaded location */ + Location *getLocation(uint16 level, uint16 location); + private: typedef Common::List CurrentList; diff --git a/engines/stark/resourcereference.cpp b/engines/stark/resourcereference.cpp index a9201446605..3287506c5fe 100644 --- a/engines/stark/resourcereference.cpp +++ b/engines/stark/resourcereference.cpp @@ -21,7 +21,12 @@ */ #include "engines/stark/resourcereference.h" + #include "engines/stark/debug.h" +#include "engines/stark/resources/level.h" +#include "engines/stark/resources/location.h" +#include "engines/stark/resourceprovider.h" +#include "engines/stark/stark.h" namespace Stark { @@ -41,6 +46,34 @@ void ResourceReference::addPathElement(ResourceType type, uint16 index) { _path.push_back(PathElement(type, index)); } +Resource *ResourceReference::resolve() { + ResourceProvider *resourceProvider = StarkServices::instance().resourceProvider; + Global *global = StarkServices::instance().global; + + Resource *resource = nullptr; + for (uint i = 0; i < _path.size(); i++) { + PathElement element = _path[i]; + + switch (element.getType().get()) { + case ResourceType::kLevel: + if (element.getIndex()) { + resource = resourceProvider->getLevel(element.getIndex()); + } else { + resource = global->getLevel(); + } + break; + case ResourceType::kLocation: + resource = resourceProvider->getLocation(resource->getIndex(), element.getIndex()); + break; + default: + resource = resource->findChildWithIndex(element.getType(), element.getIndex()); + break; + } + } + + return resource; +} + Common::String ResourceReference::describe() { Common::String desc; diff --git a/engines/stark/resourcereference.h b/engines/stark/resourcereference.h index 9fb3934ed9d..076b60fc749 100644 --- a/engines/stark/resourcereference.h +++ b/engines/stark/resourcereference.h @@ -44,6 +44,19 @@ public: Common::String describe(); void addPathElement(ResourceType type, uint16 index); + Resource *resolve(); + + template + T* resolve() { + Resource *resource = resolve(); + + if (resource && resource->getType() != T::TYPE) { + error("Unexpected resource type when resolving reference %s instad of %s", + resource->getType().getName(), ResourceType(T::TYPE).getName()); + } + + return (T *) resource; + } private: class PathElement { @@ -51,6 +64,9 @@ private: PathElement(ResourceType type, uint16 index); Common::String describe(); + ResourceType getType() const { return _type; } + uint16 getIndex() const { return _index; } + private: ResourceType _type; uint16 _index; diff --git a/engines/stark/resources/resource.cpp b/engines/stark/resources/resource.cpp index 1372866677a..151fcf04cf7 100644 --- a/engines/stark/resources/resource.cpp +++ b/engines/stark/resources/resource.cpp @@ -188,6 +188,19 @@ void Resource::print(uint depth) { } } +Resource *Resource::findChildWithIndex(ResourceType type, uint16 index, int subType) { + for (uint i = 0; i < _children.size(); i++) { + if (_children[i]->getType() == type + && (_children[i]->getSubType() == subType || subType == -1) + && _children[i]->getIndex() == index) { + // Found a matching child + return _children[i]; + } + } + + return nullptr; +} + template<> Common::Array Resource::listChildren(int subType) { assert(subType == -1); diff --git a/engines/stark/resources/resource.h b/engines/stark/resources/resource.h index 249a9ae2387..b048a74b596 100644 --- a/engines/stark/resources/resource.h +++ b/engines/stark/resources/resource.h @@ -197,6 +197,8 @@ public: */ virtual void onPreDestroy(); + Resource *findChildWithIndex(ResourceType type, uint16 index, int subType = -1); + template T *findChild(bool mustBeUnique = true); @@ -280,16 +282,7 @@ T *Resource::findChildWithSubtype(int subType, bool mustBeUnique) { template T *Resource::findChildWithIndex(uint16 index, int subType) { - for (uint i = 0; i < _children.size(); i++) { - if (_children[i]->getType() == T::TYPE - && (_children[i]->getSubType() == subType || subType == -1) - && _children[i]->getIndex() == index) { - // Found a matching child - return (T *)_children[i]; - } - } - - return nullptr; + return (T *)findChildWithIndex(T::TYPE, index, subType); } } // End of namespace Stark diff --git a/engines/stark/stark.cpp b/engines/stark/stark.cpp index 3d3fcc9e73b..e676c81ecad 100644 --- a/engines/stark/stark.cpp +++ b/engines/stark/stark.cpp @@ -37,6 +37,10 @@ #include "common/system.h" #include "audio/mixer.h" +namespace Common { +DECLARE_SINGLETON(Stark::StarkServices); +} + namespace Stark { StarkEngine::StarkEngine(OSystem *syst, const ADGameDescription *gameDesc) : @@ -69,6 +73,8 @@ StarkEngine::~StarkEngine() { delete _global; delete _stateProvider; delete _archiveLoader; + + StarkServices::destroy(); } Common::Error StarkEngine::run() { @@ -83,6 +89,12 @@ Common::Error StarkEngine::run() { _global = new Global(); _resourceProvider = new ResourceProvider(_archiveLoader, _stateProvider, _global); + // Setup the public services + StarkServices &services = StarkServices::instance(); + services.archiveLoader = _archiveLoader; + services.resourceProvider = _resourceProvider; + services.global = _global; + // Load global resources _resourceProvider->initGlobal(); diff --git a/engines/stark/stark.h b/engines/stark/stark.h index 2ea1ca97c79..038af9019fa 100644 --- a/engines/stark/stark.h +++ b/engines/stark/stark.h @@ -47,6 +47,22 @@ class ArchiveLoader; class StateProvider; class ResourceProvider; +/** + * Public services available as a singleton + */ +class StarkServices : public Common::Singleton { +public: + StarkServices() { + global = nullptr; + archiveLoader = nullptr; + resourceProvider = nullptr; + } + + Global *global; + ArchiveLoader *archiveLoader; + ResourceProvider *resourceProvider; +}; + class StarkEngine : public Engine { public: StarkEngine(OSystem *syst, const ADGameDescription *gameDesc);