diff --git a/projects/VC100/SimGear.vcxproj b/projects/VC100/SimGear.vcxproj
index 9e8d5226..8729073b 100644
--- a/projects/VC100/SimGear.vcxproj
+++ b/projects/VC100/SimGear.vcxproj
@@ -220,6 +220,8 @@
+
+
diff --git a/projects/VC90/SimGear.vcproj b/projects/VC90/SimGear.vcproj
index 8de61f5b..8a245af3 100644
--- a/projects/VC90/SimGear.vcproj
+++ b/projects/VC90/SimGear.vcproj
@@ -671,6 +671,14 @@
RelativePath="..\..\simgear\misc\zfstream.hxx"
>
+
+
+
+
+
+#include
+
+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
diff --git a/simgear/misc/ResourceManager.hxx b/simgear/misc/ResourceManager.hxx
new file mode 100644
index 00000000..bfaa5310
--- /dev/null
+++ b/simgear/misc/ResourceManager.hxx
@@ -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
+
+#include
+
+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 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
diff --git a/simgear/misc/sg_path.cxx b/simgear/misc/sg_path.cxx
index 0de0d925..73475b0c 100644
--- a/simgear/misc/sg_path.cxx
+++ b/simgear/misc/sg_path.cxx
@@ -358,3 +358,8 @@ bool SGPath::isAbsolute() const
return (path[0] == sgDirPathSep);
}
+
+bool SGPath::isNull() const
+{
+ return path.empty() || (path == "");
+}
diff --git a/simgear/misc/sg_path.hxx b/simgear/misc/sg_path.hxx
index 6f8968b7..69dd5944 100644
--- a/simgear/misc/sg_path.hxx
+++ b/simgear/misc/sg_path.hxx
@@ -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();
diff --git a/simgear/scene/model/modellib.cxx b/simgear/scene/model/modellib.cxx
index cdcb724f..ae90f1a4 100644
--- a/simgear/scene/model/modellib.cxx
+++ b/simgear/scene/model/modellib.cxx
@@ -30,6 +30,7 @@
#include
#include
#include
+#include
#include "SGPagedLOD.hxx"
#include "SGReaderWriterXML.hxx"
@@ -47,7 +48,6 @@ ModelRegistryCallbackProxy 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);
}
diff --git a/simgear/scene/model/modellib.hxx b/simgear/scene/model/modellib.hxx
index d28f692b..63358855 100644
--- a/simgear/scene/model/modellib.hxx
+++ b/simgear/scene/model/modellib.hxx
@@ -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;
};
diff --git a/simgear/sound/openal_test2.cxx b/simgear/sound/openal_test2.cxx
index eb0da57e..13a62d63 100644
--- a/simgear/sound/openal_test2.cxx
+++ b/simgear/sound/openal_test2.cxx
@@ -26,7 +26,9 @@ int main( int argc, char *argv[] ) {
smgr->set_position( SGVec3d::fromGeod(pos), pos );
smgr->activate();
- SGSoundSample *sample1 = new SGSoundSample( SRC_DIR, "jet.wav" );
+ SGPath srcDir(SRC_DIR);
+
+ SGSoundSample *sample1 = new SGSoundSample("jet.wav", srcDir);
sample1->set_volume(1.0);
sample1->set_pitch(1.0);
sample1->play_looped();
@@ -35,7 +37,7 @@ int main( int argc, char *argv[] ) {
printf("playing sample1\n");
sleep(1);
- SGSoundSample *sample2 = new SGSoundSample( SRC_DIR, "jet.wav" );
+ SGSoundSample *sample2 = new SGSoundSample("jet.wav", srcDir);
sample2->set_volume(0.5);
sample2->set_pitch(0.4);
sample2->play_looped();
@@ -44,7 +46,7 @@ int main( int argc, char *argv[] ) {
printf("playing sample2\n");
sleep(1);
- SGSoundSample *sample3 = new SGSoundSample( SRC_DIR, "jet.wav" );
+ SGSoundSample *sample3 = new SGSoundSample("jet.wav", srcDir);
sample3->set_volume(0.5);
sample3->set_pitch(0.8);
sample3->play_looped();
@@ -53,7 +55,7 @@ int main( int argc, char *argv[] ) {
printf("playing sample3\n");
sleep(1);
- SGSoundSample *sample4 = new SGSoundSample( SRC_DIR, "jet.wav" );
+ SGSoundSample *sample4 = new SGSoundSample("jet.wav", srcDir);
sample4->set_volume(0.5);
sample4->set_pitch(1.2);
sample4->play_looped();
@@ -62,7 +64,7 @@ int main( int argc, char *argv[] ) {
printf("playing sample4\n");
sleep(1);
- SGSoundSample *sample5 = new SGSoundSample( SRC_DIR, "jet.wav" );
+ SGSoundSample *sample5 = new SGSoundSample("jet.wav", srcDir);
sample5->set_volume(0.5);
sample5->set_pitch(1.6);
sample5->play_looped();
@@ -71,7 +73,7 @@ int main( int argc, char *argv[] ) {
printf("playing sample5\n");
sleep(1);
- SGSoundSample *sample6 = new SGSoundSample( SRC_DIR, "jet.wav" );
+ SGSoundSample *sample6 = new SGSoundSample("jet.wav", srcDir);
sample6->set_volume(0.5);
sample6->set_pitch(2.0);
sample6->play_looped();
diff --git a/simgear/sound/openal_test3.cxx b/simgear/sound/openal_test3.cxx
index 96a57a04..fafb4045 100644
--- a/simgear/sound/openal_test3.cxx
+++ b/simgear/sound/openal_test3.cxx
@@ -25,8 +25,10 @@ int main( int argc, char *argv[] ) {
smgr->set_volume(0.9);
smgr->activate();
+ SGPath srcDir(SRC_DIR);
+
printf("default position and orientation\n");
- SGSoundSample *sample1 = new SGSoundSample( SRC_DIR, "jet.wav" );
+ SGSoundSample *sample1 = new SGSoundSample("jet.wav", srcDir);
sample1->set_volume(1.0);
sample1->set_pitch(1.0);
sample1->play_looped();
diff --git a/simgear/sound/sample_openal.cxx b/simgear/sound/sample_openal.cxx
index 7b355002..3c9cb864 100644
--- a/simgear/sound/sample_openal.cxx
+++ b/simgear/sound/sample_openal.cxx
@@ -33,6 +33,7 @@
#include
#include
#include
+#include
#include "soundmgr_openal.hxx"
#include "sample_openal.hxx"
@@ -78,7 +79,7 @@ SGSoundSample::SGSoundSample() :
}
// constructor
-SGSoundSample::SGSoundSample( const char *path, const char *file ) :
+SGSoundSample::SGSoundSample(const char *file, const SGPath& currentDir) :
_absolute_pos(SGVec3d::zeros()),
_relative_pos(SGVec3d::zeros()),
_direction(SGVec3d::zeros()),
@@ -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, currentDir);
+ _refname = p.str();
}
// constructor
diff --git a/simgear/sound/sample_openal.hxx b/simgear/sound/sample_openal.hxx
index 491ba572..b2afba4f 100644
--- a/simgear/sound/sample_openal.hxx
+++ b/simgear/sound/sample_openal.hxx
@@ -60,11 +60,10 @@ public:
/**
* Constructor
- * @param path Path name to sound
* @param file File name of sound
Buffer data is freed by the sample group
*/
- SGSoundSample( const char *path, const char *file );
+ SGSoundSample(const char *file, const SGPath& currentDir);
/**
* Constructor.
diff --git a/simgear/sound/xmlsound.cxx b/simgear/sound/xmlsound.cxx
index 616d9514..2ca9cdfa 100644
--- a/simgear/sound/xmlsound.cxx
+++ b/simgear/sound/xmlsound.cxx
@@ -84,7 +84,7 @@ SGXmlSound::~SGXmlSound()
void
SGXmlSound::init(SGPropertyNode *root, SGPropertyNode *node,
SGSampleGroup *sgrp, SGSampleGroup *avionics,
- const string &path)
+ const SGPath& currentDir)
{
//
@@ -272,7 +272,7 @@ SGXmlSound::init(SGPropertyNode *root, SGPropertyNode *node,
} else {
_sgrp = sgrp;
}
- _sample = new SGSoundSample( path.c_str(), node->getStringValue("path", ""));
+ _sample = new SGSoundSample(node->getStringValue("path", ""), currentDir);
if (!_sample->file_path().exists()) {
throw sg_io_exception("XML sound: couldn't find file: " + _sample->file_path().str());
}
diff --git a/simgear/sound/xmlsound.hxx b/simgear/sound/xmlsound.hxx
index 141f5eef..f3635b08 100644
--- a/simgear/sound/xmlsound.hxx
+++ b/simgear/sound/xmlsound.hxx
@@ -104,7 +104,7 @@ public:
* @param path The path where the audio files remain.
*/
virtual void init (SGPropertyNode *, SGPropertyNode *, SGSampleGroup *,
- SGSampleGroup *, const string &);
+ SGSampleGroup *, const SGPath& currentDir);
/**
* Check whether an event has happened and if action has to be taken.