STARK: Allow resolving resource references

This commit is contained in:
Bastien Bouclet 2015-01-01 21:13:33 +01:00
parent 51730689c1
commit 5331b52226
9 changed files with 128 additions and 15 deletions

View file

@ -35,9 +35,6 @@ ArchiveLoader::LoadedArchive::LoadedArchive(const Common::String& archiveName) :
} }
_root = importResources(); _root = importResources();
// Resource lifecycle update
_root->onAllLoaded();
} }
ArchiveLoader::LoadedArchive::~LoadedArchive() { ArchiveLoader::LoadedArchive::~LoadedArchive() {

View file

@ -46,6 +46,9 @@ void ResourceProvider::initGlobal() {
Root *root = _archiveLoader->useRoot<Root>("x.xarc"); Root *root = _archiveLoader->useRoot<Root>("x.xarc");
_global->setRoot(root); _global->setRoot(root);
// Resource lifecycle update
root->onAllLoaded();
// Find the global level node // Find the global level node
Level *global = root->findChildWithSubtype<Level>(1); Level *global = root->findChildWithSubtype<Level>(1);
@ -58,6 +61,9 @@ void ResourceProvider::initGlobal() {
_stateProvider->restoreLevelState(global); _stateProvider->restoreLevelState(global);
_global->setLevel(global); _global->setLevel(global);
// Resource lifecycle update
global->onAllLoaded();
//TODO: Retrieve the inventory and April from the global tree //TODO: Retrieve the inventory and April from the global tree
} }
@ -82,8 +88,29 @@ Current *ResourceProvider::findLocation(uint16 level, uint16 location) {
return nullptr; 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) { void ResourceProvider::requestLocationChange(uint16 level, uint16 location) {
Current *currentLocation = new Current(); Current *currentLocation = new Current();
_locations.push_back(currentLocation);
// Retrieve the level archive name // Retrieve the level archive name
Root *root = _global->getRoot(); 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 we just loaded a resource tree, restore its state
if (newlyLoaded) { if (newlyLoaded) {
_stateProvider->restoreLevelState(currentLocation->getLevel()); _stateProvider->restoreLevelState(currentLocation->getLevel());
currentLocation->getLevel()->onAllLoaded();
} }
// Retrieve the location archive name // 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 we just loaded a resource tree, restore its state
if (newlyLoaded) { if (newlyLoaded) {
_stateProvider->restoreLocationState(currentLocation->getLevel(), currentLocation->getLocation()); _stateProvider->restoreLocationState(currentLocation->getLevel(), currentLocation->getLocation());
currentLocation->getLocation()->onAllLoaded();
} }
_locations.push_back(currentLocation);
_locationChangeRequest = true; _locationChangeRequest = true;
} }

View file

@ -131,6 +131,12 @@ public:
/** Release the global and current resources */ /** Release the global and current resources */
void shutdown(); 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: private:
typedef Common::List<Current *> CurrentList; typedef Common::List<Current *> CurrentList;

View file

@ -21,7 +21,12 @@
*/ */
#include "engines/stark/resourcereference.h" #include "engines/stark/resourcereference.h"
#include "engines/stark/debug.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 { namespace Stark {
@ -41,6 +46,34 @@ void ResourceReference::addPathElement(ResourceType type, uint16 index) {
_path.push_back(PathElement(type, 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 ResourceReference::describe() {
Common::String desc; Common::String desc;

View file

@ -44,6 +44,19 @@ public:
Common::String describe(); Common::String describe();
void addPathElement(ResourceType type, uint16 index); void addPathElement(ResourceType type, uint16 index);
Resource *resolve();
template <class T>
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: private:
class PathElement { class PathElement {
@ -51,6 +64,9 @@ private:
PathElement(ResourceType type, uint16 index); PathElement(ResourceType type, uint16 index);
Common::String describe(); Common::String describe();
ResourceType getType() const { return _type; }
uint16 getIndex() const { return _index; }
private: private:
ResourceType _type; ResourceType _type;
uint16 _index; uint16 _index;

View file

@ -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<> template<>
Common::Array<Resource *> Resource::listChildren<Resource>(int subType) { Common::Array<Resource *> Resource::listChildren<Resource>(int subType) {
assert(subType == -1); assert(subType == -1);

View file

@ -197,6 +197,8 @@ public:
*/ */
virtual void onPreDestroy(); virtual void onPreDestroy();
Resource *findChildWithIndex(ResourceType type, uint16 index, int subType = -1);
template<class T> template<class T>
T *findChild(bool mustBeUnique = true); T *findChild(bool mustBeUnique = true);
@ -280,16 +282,7 @@ T *Resource::findChildWithSubtype(int subType, bool mustBeUnique) {
template <class T> template <class T>
T *Resource::findChildWithIndex(uint16 index, int subType) { T *Resource::findChildWithIndex(uint16 index, int subType) {
for (uint i = 0; i < _children.size(); i++) { return (T *)findChildWithIndex(T::TYPE, index, subType);
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;
} }
} // End of namespace Stark } // End of namespace Stark

View file

@ -37,6 +37,10 @@
#include "common/system.h" #include "common/system.h"
#include "audio/mixer.h" #include "audio/mixer.h"
namespace Common {
DECLARE_SINGLETON(Stark::StarkServices);
}
namespace Stark { namespace Stark {
StarkEngine::StarkEngine(OSystem *syst, const ADGameDescription *gameDesc) : StarkEngine::StarkEngine(OSystem *syst, const ADGameDescription *gameDesc) :
@ -69,6 +73,8 @@ StarkEngine::~StarkEngine() {
delete _global; delete _global;
delete _stateProvider; delete _stateProvider;
delete _archiveLoader; delete _archiveLoader;
StarkServices::destroy();
} }
Common::Error StarkEngine::run() { Common::Error StarkEngine::run() {
@ -83,6 +89,12 @@ Common::Error StarkEngine::run() {
_global = new Global(); _global = new Global();
_resourceProvider = new ResourceProvider(_archiveLoader, _stateProvider, _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 // Load global resources
_resourceProvider->initGlobal(); _resourceProvider->initGlobal();

View file

@ -47,6 +47,22 @@ class ArchiveLoader;
class StateProvider; class StateProvider;
class ResourceProvider; class ResourceProvider;
/**
* Public services available as a singleton
*/
class StarkServices : public Common::Singleton<StarkServices> {
public:
StarkServices() {
global = nullptr;
archiveLoader = nullptr;
resourceProvider = nullptr;
}
Global *global;
ArchiveLoader *archiveLoader;
ResourceProvider *resourceProvider;
};
class StarkEngine : public Engine { class StarkEngine : public Engine {
public: public:
StarkEngine(OSystem *syst, const ADGameDescription *gameDesc); StarkEngine(OSystem *syst, const ADGameDescription *gameDesc);