Add ResourceManager, and use to find sound and model paths.

This commit is contained in:
James Turner
2010-09-05 20:22:12 +01:00
parent 44c587400d
commit 289e768ca5
10 changed files with 229 additions and 35 deletions

View File

@@ -220,6 +220,8 @@
<ClCompile Include="..\..\simgear\misc\tabbed_values.cxx" />
<ClCompile Include="..\..\simgear\misc\texcoord.cxx" />
<ClCompile Include="..\..\simgear\misc\zfstream.cxx" />
<ClCompile Include="..\..\simgear\misc\ResourceManager.cxx" />
<ClCompile Include="..\..\simgear\misc\ResourceManager.hxx" />
<ClCompile Include="..\..\simgear\route\route.cxx" />
<ClCompile Include="..\..\simgear\route\waypoint.cxx" />
<ClCompile Include="..\..\simgear\screen\extensions.cxx" />

View File

@@ -671,6 +671,14 @@
RelativePath="..\..\simgear\misc\zfstream.hxx"
>
</File>
<File
RelativePath="..\..\simgear\misc\ResourceManager.cxx"
>
</File>
<File
RelativePath="..\..\simgear\misc\ResourceManager.hxx"
>
</File>
</Filter>
<Filter
Name="Lib_sgroute"

View File

@@ -13,7 +13,8 @@ include_HEADERS = \
interpolator.hxx \
stdint.hxx \
PathOptions.hxx \
sg_dir.hxx
sg_dir.hxx \
ResourceManager.hxx
libsgmisc_a_SOURCES = \
sg_path.cxx \
@@ -24,7 +25,8 @@ libsgmisc_a_SOURCES = \
zfstream.cxx \
interpolator.cxx \
PathOptions.cxx \
sg_dir.cxx
sg_dir.cxx \
ResourceManager.cxx
#noinst_PROGRAMS = tabbed_value_test swap_test

View File

@@ -0,0 +1,104 @@
// ResourceManager.cxx -- manage finding resources by names/paths
// Copyright (C) 2010 James Turner
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Library General Public
// License as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Library General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
//
// $Id$
#include <simgear_config.h>
#include <simgear/misc/ResourceManager.hxx>
namespace simgear
{
static ResourceManager* static_manager = NULL;
ResourceManager::ResourceManager()
{
}
ResourceManager* ResourceManager::instance()
{
if (!static_manager) {
static_manager = new ResourceManager();
}
return static_manager;
}
/**
* trivial provider using a fixed base path
*/
class BasePathProvider : public ResourceProvider
{
public:
BasePathProvider(const SGPath& aBase, int aPriority) :
ResourceProvider(aPriority),
_base(aBase)
{
}
virtual SGPath resolve(const std::string& aResource, SGPath&) const
{
SGPath p(_base, aResource);
return p.exists() ? p : SGPath();
}
private:
SGPath _base;
};
void ResourceManager::addBasePath(const SGPath& aPath, Priority aPriority)
{
addProvider(new BasePathProvider(aPath, aPriority));
}
void ResourceManager::addProvider(ResourceProvider* aProvider)
{
ProviderVec::iterator it = _providers.begin();
for (; it != _providers.end(); ++it) {
if (aProvider->priority() > (*it)->priority()) {
_providers.insert(it, aProvider);
return;
}
}
// fell out of the iteration, goes to the end of the vec
_providers.push_back(aProvider);
}
SGPath ResourceManager::findPath(const std::string& aResource, SGPath aContext)
{
if (!aContext.isNull()) {
SGPath r(aContext, aResource);
if (r.exists()) {
return r;
}
}
ProviderVec::iterator it = _providers.begin();
for (; it != _providers.end(); ++it) {
SGPath path = (*it)->resolve(aResource, aContext);
if (!path.isNull()) {
return path;
}
}
return SGPath();
}
} // of namespace simgear

View File

@@ -0,0 +1,93 @@
// ResourceManager.hxx -- manage finding resources by names/paths
// Copyright (C) 2010 James Turner
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Library General Public
// License as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Library General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
//
// $Id$
#ifndef SG_RESOURCE_MANAGER_HXX
#define SG_RESOURCE_MANAGER_HXX
#include <vector>
#include <simgear/misc/sg_path.hxx>
namespace simgear
{
class ResourceProvider;
/**
* singleton management of resources
*/
class ResourceManager
{
public:
typedef enum {
PRIORITY_DEFAULT = 0,
PRIORITY_FALLBACK = -100,
PRIORITY_NORMAL = 100,
PRIORITY_HIGH = 1000
} Priority;
static ResourceManager* instance();
/**
* add a simple fixed resource location, to resolve against
*/
void addBasePath(const SGPath& aPath, Priority aPriority = PRIORITY_DEFAULT);
/**
*
*/
void addProvider(ResourceProvider* aProvider);
/**
* given a resource name (or path), find the appropriate real resource
* path.
* @param aContext an optional current location to resolve relative names
* against (e.g a current directory)
*/
SGPath findPath(const std::string& aResource, SGPath aContext = SGPath());
private:
ResourceManager();
typedef std::vector<ResourceProvider*> ProviderVec;
ProviderVec _providers;
};
class ResourceProvider
{
public:
virtual SGPath resolve(const std::string& aResource, SGPath& aContext) const = 0;
virtual int priority() const
{
return _priority;
}
protected:
ResourceProvider(int aPriority) :
_priority(aPriority)
{}
int _priority;
};
} // of simgear namespace
#endif // of header guard

View File

@@ -358,3 +358,8 @@ bool SGPath::isAbsolute() const
return (path[0] == sgDirPathSep);
}
bool SGPath::isNull() const
{
return path.empty() || (path == "");
}

View File

@@ -166,6 +166,11 @@ public:
* I.e starts with a directory seperator, or a single character + colon
*/
bool isAbsolute() const;
/**
* check for default constructed path
*/
bool isNull() const;
private:
void fix();

View File

@@ -30,6 +30,7 @@
#include <simgear/props/props_io.hxx>
#include <simgear/scene/model/model.hxx>
#include <simgear/scene/model/ModelRegistry.hxx>
#include <simgear/misc/ResourceManager.hxx>
#include "SGPagedLOD.hxx"
#include "SGReaderWriterXML.hxx"
@@ -47,7 +48,6 @@ ModelRegistryCallbackProxy<LoadOnlyCallback> g_xmlCallbackProxy("xml");
SGPropertyNode_ptr SGModelLib::static_propRoot;
SGModelLib::panel_func SGModelLib::static_panelFunc = NULL;
SGModelLib::resolve_func SGModelLib::static_resolver = NULL;
////////////////////////////////////////////////////////////////////////
// Implementation of SGModelLib.
@@ -67,33 +67,15 @@ void SGModelLib::setPanelFunc(panel_func pf)
static_panelFunc = pf;
}
void SGModelLib::setResolveFunc(resolve_func rf)
{
static_resolver = rf;
}
std::string SGModelLib::findDataFile(const std::string& file,
const osgDB::ReaderWriter::Options* opts,
SGPath currentPath)
{
// if we have a valid current path, first attempt to resolve relative
// to that path
if (currentPath.exists()) {
SGPath p = currentPath;
p.append(file);
if (p.exists()) {
return p.str();
}
SGPath p = ResourceManager::instance()->findPath(file, currentPath);
if (p.exists()) {
return p.str();
}
// next try the resolve function if one has been defined
if (static_resolver) {
SGPath p = static_resolver(file);
if (p.exists()) {
return p.str();
}
}
// finally hand on to standard OSG behaviour
return osgDB::findDataFile(file, opts);
}

View File

@@ -44,16 +44,12 @@ class SGModelLib
public:
typedef osg::Node *(*panel_func)(SGPropertyNode *);
typedef SGPath (*resolve_func)(const std::string& path);
static void init(const std::string &root_dir);
static void setPropRoot(SGPropertyNode* root);
static void setPanelFunc(panel_func pf);
static void setResolveFunc(resolve_func rf);
// Load a 3D model (any format)
// data->modelLoaded() will be called after the model is loaded
static osg::Node* loadModel(const std::string &path,
@@ -80,7 +76,6 @@ protected:
private:
static SGPropertyNode_ptr static_propRoot;
static panel_func static_panelFunc;
static resolve_func static_resolver;
};

View File

@@ -33,6 +33,7 @@
#include <simgear/structure/exception.hxx>
#include <simgear/misc/sg_path.hxx>
#include <simgear/math/SGMath.hxx>
#include <simgear/misc/ResourceManager.hxx>
#include "soundmgr_openal.hxx"
#include "sample_openal.hxx"
@@ -110,11 +111,8 @@ SGSoundSample::SGSoundSample( const char *path, const char *file ) :
_static_changed(true),
_is_file(true)
{
SGPath samplepath( path );
if ( strlen(file) ) {
samplepath.append( file );
}
_refname = samplepath.str();
SGPath p = simgear::ResourceManager::instance()->findPath(file);
_refname = p.str();
}
// constructor