Integrated support for relative paths, and http hosted presentations
This commit is contained in:
@@ -113,7 +113,7 @@ public:
|
||||
|
||||
virtual ReadResult readNode(std::istream& fin, const Options* options) const;
|
||||
|
||||
ReadResult readNode(osgDB::XmlNode::Input& input, const osgDB::ReaderWriter::Options* options) const;
|
||||
ReadResult readNode(osgDB::XmlNode::Input& input, osgDB::ReaderWriter::Options* options) const;
|
||||
|
||||
void parseModel(osgPresentation::SlideShowConstructor& constructor, osgDB::XmlNode*cur) const;
|
||||
|
||||
@@ -870,10 +870,10 @@ void ReaderWriterP3DXML::parseStereoPair(osgPresentation::SlideShowConstructor&
|
||||
getProperties(cur,imageDataRight);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (!filenameLeft.empty() && !filenameRight.empty())
|
||||
constructor.addStereoImagePair(filenameLeft,imageDataLeft,
|
||||
filenameRight, imageDataRight,
|
||||
filenameRight, imageDataRight,
|
||||
positionRead ? positionData : constructor.getImagePositionData());
|
||||
|
||||
}
|
||||
@@ -1385,6 +1385,312 @@ void ReaderWriterP3DXML::parseSlide (osgPresentation::SlideShowConstructor& cons
|
||||
|
||||
#include <iostream>
|
||||
|
||||
|
||||
struct MyFindFileCallback : public osgDB::FindFileCallback
|
||||
{
|
||||
virtual std::string findDataFile(const std::string& filename, const osgDB::Options* options, osgDB::CaseSensitivity caseSensitivity)
|
||||
{
|
||||
osg::notify(osg::NOTICE)<<std::endl<<std::endl<<"find file "<<filename<<std::endl;
|
||||
|
||||
const osgDB::FilePathList& paths = options ? options->getDatabasePathList() : osgDB::getDataFilePathList();
|
||||
|
||||
for(osgDB::FilePathList::const_iterator itr = paths.begin();
|
||||
itr != paths.end();
|
||||
++itr)
|
||||
{
|
||||
const std::string& path = *itr;
|
||||
std::string newpath = osgDB::concatPaths(path, filename);
|
||||
if (osgDB::containsServerAddress(path))
|
||||
{
|
||||
osgDB::ReaderWriter* rw = osgDB::Registry::instance()->getReaderWriterForExtension("curl");
|
||||
osg::notify(osg::NOTICE)<<" file on server "<<*itr<<", try path "<<newpath<<std::endl;
|
||||
osg::notify(osg::NOTICE)<<" we have curl rw= "<<rw<<std::endl;
|
||||
if (rw && rw->fileExists(newpath, options))
|
||||
{
|
||||
osg::notify(osg::NOTICE)<<" FOUND on server "<<newpath<<std::endl;
|
||||
return newpath;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(osgDB::fileExists(newpath))
|
||||
{
|
||||
osg::notify(osg::NOTICE)<<" FOUND "<<newpath<<std::endl;
|
||||
return newpath;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return osgDB::Registry::instance()->findDataFileImplementation(filename, options, caseSensitivity);
|
||||
}
|
||||
};
|
||||
|
||||
class OSGDB_EXPORT MyReadFileCallback : public virtual osgDB::ReadFileCallback
|
||||
{
|
||||
public:
|
||||
|
||||
osgDB::FilePathList _paths;
|
||||
|
||||
typedef std::map< std::string, osg::ref_ptr<osg::Object> > ObjectCache;
|
||||
|
||||
enum ObjectType
|
||||
{
|
||||
OBJECT,
|
||||
IMAGE,
|
||||
HEIGHT_FIELD,
|
||||
NODE,
|
||||
SHADER
|
||||
};
|
||||
|
||||
osgDB::ReaderWriter::ReadResult readLocal(ObjectType type, const std::string& filename, const osgDB::Options* options)
|
||||
{
|
||||
osg::notify(osg::INFO)<<"Trying local file "<<filename<<std::endl;
|
||||
|
||||
switch(type)
|
||||
{
|
||||
case(OBJECT): return osgDB::Registry::instance()->readObjectImplementation(filename,options);
|
||||
case(IMAGE): return osgDB::Registry::instance()->readImageImplementation(filename,options);
|
||||
case(HEIGHT_FIELD): return osgDB::Registry::instance()->readHeightFieldImplementation(filename,options);
|
||||
case(NODE): return osgDB::Registry::instance()->readNodeImplementation(filename,options);
|
||||
case(SHADER): return osgDB::Registry::instance()->readShaderImplementation(filename,options);
|
||||
}
|
||||
return osgDB::ReaderWriter::ReadResult::FILE_NOT_HANDLED;
|
||||
}
|
||||
|
||||
|
||||
osgDB::ReaderWriter::ReadResult readFileCache(ObjectType type, const std::string& filename, const osgDB::Options* options)
|
||||
{
|
||||
|
||||
osgDB::FileCache* fileCache = options ? options->getFileCache() : 0;
|
||||
if (!fileCache) fileCache = osgDB::Registry::instance()->getFileCache();
|
||||
if (!fileCache) return osgDB::ReaderWriter::ReadResult::FILE_NOT_FOUND;
|
||||
|
||||
osg::notify(osg::INFO)<<"Trying fileCache "<<filename<<std::endl;
|
||||
|
||||
osgDB::ReaderWriter::ReadResult result;
|
||||
if (fileCache && fileCache->isFileAppropriateForFileCache(filename))
|
||||
{
|
||||
if (fileCache->existsInCache(filename))
|
||||
{
|
||||
switch(type)
|
||||
{
|
||||
case(OBJECT):
|
||||
result = fileCache->readObject(filename, 0);
|
||||
break;
|
||||
case(IMAGE):
|
||||
result = fileCache->readImage(filename, 0);
|
||||
break;
|
||||
case(HEIGHT_FIELD):
|
||||
result = fileCache->readHeightField(filename, 0);
|
||||
break;
|
||||
case(NODE):
|
||||
result = fileCache->readNode(filename,0);
|
||||
break;
|
||||
case(SHADER):
|
||||
result = fileCache->readShader(filename, 0);
|
||||
break;
|
||||
}
|
||||
|
||||
if (result.success())
|
||||
{
|
||||
osg::notify(osg::INFO)<<" File read from FileCache."<<std::endl;
|
||||
return result;
|
||||
}
|
||||
|
||||
osg::notify(osg::NOTICE)<<" File in FileCache, but not successfully read"<<std::endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
osg::notify(osg::INFO)<<" File does not exist in FileCache: "<<fileCache->createCacheFileName(filename)<<std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
return osgDB::ReaderWriter::ReadResult::FILE_NOT_FOUND;
|
||||
|
||||
}
|
||||
|
||||
osgDB::ReaderWriter::ReadResult readServer(ObjectType type, const std::string& filename, const osgDB::Options* options)
|
||||
{
|
||||
osg::notify(osg::INFO)<<"Trying server file "<<filename<<std::endl;
|
||||
|
||||
osgDB::ReaderWriter::ReadResult result;
|
||||
osgDB::ReaderWriter* rw = osgDB::Registry::instance()->getReaderWriterForExtension("curl");
|
||||
if (!rw) return osgDB::ReaderWriter::ReadResult::FILE_NOT_HANDLED;
|
||||
|
||||
switch(type)
|
||||
{
|
||||
case(OBJECT):
|
||||
result = rw->readObject(filename,options);
|
||||
break;
|
||||
case(IMAGE):
|
||||
result = rw->readImage(filename,options);
|
||||
break;
|
||||
case(HEIGHT_FIELD):
|
||||
result = rw->readHeightField(filename,options);
|
||||
break;
|
||||
case(NODE):
|
||||
result = rw->readNode(filename,options);
|
||||
break;
|
||||
case(SHADER):
|
||||
result = rw->readShader(filename,options);
|
||||
break;
|
||||
}
|
||||
|
||||
if (result.success())
|
||||
{
|
||||
osgDB::FileCache* fileCache = options ? options->getFileCache() : 0;
|
||||
if (!fileCache) fileCache = osgDB::Registry::instance()->getFileCache();
|
||||
|
||||
if (fileCache && fileCache->isFileAppropriateForFileCache(filename))
|
||||
{
|
||||
switch(type)
|
||||
{
|
||||
case(OBJECT):
|
||||
fileCache->writeObject(*result.getObject(),filename,options);
|
||||
break;
|
||||
case(IMAGE):
|
||||
result.getImage()->setFileName(filename);
|
||||
fileCache->writeImage(*result.getImage(),filename,options);
|
||||
break;
|
||||
case(HEIGHT_FIELD):
|
||||
fileCache->writeHeightField(*result.getHeightField(),filename,options);
|
||||
break;
|
||||
case(NODE):
|
||||
fileCache->writeNode(*result.getNode(),filename,options);
|
||||
break;
|
||||
case(SHADER):
|
||||
fileCache->writeShader(*result.getShader(),filename,options);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
return osgDB::ReaderWriter::ReadResult::FILE_NOT_FOUND;
|
||||
}
|
||||
|
||||
|
||||
osgDB::ReaderWriter::ReadResult read(const osgDB::FilePathList& filePathList, ObjectType type, const std::string& filename, const osgDB::Options* options, bool checkLocalFiles)
|
||||
{
|
||||
// go look in http paths
|
||||
for(osgDB::FilePathList::const_iterator itr = filePathList.begin();
|
||||
itr != filePathList.end();
|
||||
++itr)
|
||||
{
|
||||
const std::string& path = *itr;
|
||||
std::string newpath = path.empty() ? filename : osgDB::concatPaths(path, filename);
|
||||
osgDB::ReaderWriter::ReadResult result;
|
||||
if (osgDB::containsServerAddress(newpath))
|
||||
{
|
||||
if (checkLocalFiles) result = readFileCache(type, newpath, options);
|
||||
else result = readServer(type, newpath, options);
|
||||
}
|
||||
else if (checkLocalFiles && osgDB::fileExists(newpath))
|
||||
{
|
||||
result = readLocal(type, newpath, options);
|
||||
}
|
||||
|
||||
if (result.success())
|
||||
{
|
||||
osg::notify(osg::INFO)<<" inserting object into file cache "<<filename<<", "<<result.getObject()<<std::endl;
|
||||
_objectCache[filename] = result.getObject();
|
||||
|
||||
options->setPluginStringData("filename",newpath);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
return osgDB::ReaderWriter::ReadResult::FILE_NOT_FOUND;
|
||||
}
|
||||
|
||||
osgDB::ReaderWriter::ReadResult read(ObjectType type, const std::string& filename, const osgDB::Options* options)
|
||||
{
|
||||
osgDB::FileCache* fileCache = options ? options->getFileCache() : 0;
|
||||
if (!fileCache) fileCache = osgDB::Registry::instance()->getFileCache();
|
||||
if (fileCache && !fileCache->isFileAppropriateForFileCache(filename)) fileCache = 0;
|
||||
|
||||
osg::notify(osg::INFO)<<"reading file "<<filename<<std::endl;
|
||||
ObjectCache::iterator itr = _objectCache.find(filename);
|
||||
if (itr != _objectCache.end())
|
||||
{
|
||||
// object is in cache, just retrieve it.
|
||||
if (itr->second.valid())
|
||||
{
|
||||
osg::notify(osg::INFO)<<"File retrieved from cache, filename="<<filename<<std::endl;
|
||||
return itr->second.get();
|
||||
}
|
||||
else
|
||||
{
|
||||
osg::notify(osg::INFO)<<"File failed to load previously, won't attempt a second time "<<filename<<std::endl;
|
||||
return osgDB::ReaderWriter::ReadResult::FILE_NOT_FOUND;
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
bool checkLocalFiles = true;
|
||||
osgDB::ReaderWriter::ReadResult result = read(_paths, type, filename, options, checkLocalFiles);
|
||||
if (result.success()) return result;
|
||||
|
||||
if (options && !(options->getDatabasePathList().empty()))
|
||||
{
|
||||
result = read(options->getDatabasePathList(), type, filename, options, checkLocalFiles);
|
||||
if (result.success()) return result;
|
||||
}
|
||||
|
||||
result = read(osgDB::Registry::instance()->getDataFilePathList(), type, filename, options, checkLocalFiles);
|
||||
if (result.success()) return result;
|
||||
}
|
||||
|
||||
{
|
||||
bool checkLocalFiles = false;
|
||||
osgDB::ReaderWriter::ReadResult result = read(_paths, type, filename, options, checkLocalFiles);
|
||||
if (result.success()) return result;
|
||||
|
||||
if (options && !(options->getDatabasePathList().empty()))
|
||||
{
|
||||
result = read(options->getDatabasePathList(), type, filename, options, checkLocalFiles);
|
||||
if (result.success()) return result;
|
||||
}
|
||||
|
||||
result = read(osgDB::Registry::instance()->getDataFilePathList(), type, filename, options, checkLocalFiles);
|
||||
if (result.success()) return result;
|
||||
}
|
||||
|
||||
_objectCache[filename] = 0;
|
||||
|
||||
return osgDB::ReaderWriter::ReadResult::FILE_NOT_FOUND;
|
||||
}
|
||||
|
||||
virtual osgDB::ReaderWriter::ReadResult readObject(const std::string& filename, const osgDB::Options* options)
|
||||
{
|
||||
return read(OBJECT, filename, options);
|
||||
}
|
||||
|
||||
virtual osgDB::ReaderWriter::ReadResult readImage(const std::string& filename, const osgDB::Options* options)
|
||||
{
|
||||
return read(IMAGE, filename, options);
|
||||
}
|
||||
|
||||
virtual osgDB::ReaderWriter::ReadResult readHeightField(const std::string& filename, const osgDB::Options* options)
|
||||
{
|
||||
return read(HEIGHT_FIELD, filename, options);
|
||||
}
|
||||
|
||||
virtual osgDB::ReaderWriter::ReadResult readNode(const std::string& filename, const osgDB::Options* options)
|
||||
{
|
||||
return read(NODE, filename, options);
|
||||
}
|
||||
|
||||
virtual osgDB::ReaderWriter::ReadResult readShader(const std::string& filename, const osgDB::Options* options)
|
||||
{
|
||||
return read(SHADER, filename, options);
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual ~MyReadFileCallback() {}
|
||||
|
||||
ObjectCache _objectCache;
|
||||
};
|
||||
|
||||
osgDB::ReaderWriter::ReadResult ReaderWriterP3DXML::readNode(const std::string& file,
|
||||
const osgDB::ReaderWriter::Options* options) const
|
||||
{
|
||||
@@ -1394,11 +1700,17 @@ osgDB::ReaderWriter::ReadResult ReaderWriterP3DXML::readNode(const std::string&
|
||||
std::string fileName = osgDB::findDataFile( file );
|
||||
if (fileName.empty()) return ReadResult::FILE_NOT_FOUND;
|
||||
|
||||
// code for setting up the database path so that internally referenced file are searched for on relative paths.
|
||||
osg::ref_ptr<osgDB::ReaderWriter::Options> local_opt = options ? static_cast<osgDB::ReaderWriter::Options*>(options->clone(osg::CopyOp::SHALLOW_COPY)) : new Options;
|
||||
local_opt->getDatabasePathList().push_front(osgDB::getFilePath(fileName));
|
||||
//local_opt->setFindFileCallback(new MyFindFileCallback);
|
||||
local_opt->setReadFileCallback(new MyReadFileCallback);
|
||||
|
||||
osgDB::XmlNode::Input input;
|
||||
input.open(fileName);
|
||||
input.readAllDataIntoBuffer();
|
||||
|
||||
return readNode(input, options);
|
||||
return readNode(input, local_opt);
|
||||
}
|
||||
|
||||
osgDB::ReaderWriter::ReadResult ReaderWriterP3DXML::readNode(std::istream& fin, const Options* options) const
|
||||
@@ -1407,10 +1719,14 @@ osgDB::ReaderWriter::ReadResult ReaderWriterP3DXML::readNode(std::istream& fin,
|
||||
input.attach(fin);
|
||||
input.readAllDataIntoBuffer();
|
||||
|
||||
return readNode(input, options);
|
||||
osg::ref_ptr<osgDB::ReaderWriter::Options> local_opt = options ? static_cast<osgDB::ReaderWriter::Options*>(options->clone(osg::CopyOp::SHALLOW_COPY)) : new Options;
|
||||
//local_opt->setFindFileCallback(new MyFindFileCallback);
|
||||
local_opt->setReadFileCallback(new MyReadFileCallback);
|
||||
|
||||
return readNode(input, local_opt);
|
||||
}
|
||||
|
||||
osgDB::ReaderWriter::ReadResult ReaderWriterP3DXML::readNode(osgDB::XmlNode::Input& input, const osgDB::ReaderWriter::Options* options) const
|
||||
osgDB::ReaderWriter::ReadResult ReaderWriterP3DXML::readNode(osgDB::XmlNode::Input& input, osgDB::ReaderWriter::Options* options) const
|
||||
{
|
||||
bool readOnlyHoldingPage = options ? options->getOptionString()=="holding_slide" : false;
|
||||
|
||||
@@ -1423,6 +1739,9 @@ osgDB::ReaderWriter::ReadResult ReaderWriterP3DXML::readNode(osgDB::XmlNode::Inp
|
||||
|
||||
doc->read(input);
|
||||
|
||||
|
||||
osg::notify(osg::NOTICE)<<"P3D parsing"<<std::endl;
|
||||
|
||||
// doc->write(std::cout);
|
||||
|
||||
if (doc == NULL )
|
||||
@@ -1450,12 +1769,72 @@ osgDB::ReaderWriter::ReadResult ReaderWriterP3DXML::readNode(osgDB::XmlNode::Inp
|
||||
return ReadResult::FILE_NOT_HANDLED;
|
||||
}
|
||||
|
||||
osgPresentation::SlideShowConstructor constructor;
|
||||
osgPresentation::SlideShowConstructor constructor(options);
|
||||
|
||||
osgDB::FilePathList previousPaths = osgDB::getDataFilePathList();
|
||||
|
||||
bool readSlide = false;
|
||||
|
||||
|
||||
for(osgDB::XmlNode::Children::iterator itr = root->children.begin();
|
||||
itr != root->children.end();
|
||||
++itr)
|
||||
{
|
||||
osgDB::XmlNode* cur = itr->get();
|
||||
|
||||
if (cur->name=="env")
|
||||
{
|
||||
char* str = strdup(cur->contents.c_str());
|
||||
osg::notify(osg::INFO)<<"putenv("<<str<<")"<<std::endl;
|
||||
putenv(str);
|
||||
}
|
||||
}
|
||||
|
||||
std::string pathToPresentation;
|
||||
MyReadFileCallback* readFileCallback = options ? dynamic_cast<MyReadFileCallback*>(options->getReadFileCallback()) : 0;
|
||||
|
||||
if (options && !(options->getDatabasePathList().empty()))
|
||||
{
|
||||
pathToPresentation = options->getDatabasePathList().front();
|
||||
|
||||
if (readFileCallback) readFileCallback->_paths.push_front(pathToPresentation);
|
||||
}
|
||||
|
||||
|
||||
for(osgDB::XmlNode::Children::iterator itr = root->children.begin();
|
||||
itr != root->children.end();
|
||||
++itr)
|
||||
{
|
||||
osgDB::XmlNode* cur = itr->get();
|
||||
|
||||
if (cur->name == "path")
|
||||
{
|
||||
std::string newpath = expandEnvVarsInFileName(cur->contents);
|
||||
|
||||
// now check if an absolue or http path
|
||||
std::string::size_type colonPos = newpath.find_first_of(':');
|
||||
std::string::size_type backslashPos = newpath.find_first_of('/');
|
||||
std::string::size_type forwardslashPos = newpath.find_first_of('\\');
|
||||
bool relativePath = colonPos == std::string::npos &&
|
||||
backslashPos != 0 &&
|
||||
forwardslashPos != 0;
|
||||
|
||||
if (relativePath && !pathToPresentation.empty())
|
||||
{
|
||||
newpath = osgDB::concatPaths(pathToPresentation, newpath);
|
||||
osg::notify(osg::NOTICE)<<"relative path = "<<cur->contents<<", newpath="<<newpath<<std::endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
osg::notify(osg::NOTICE)<<"absolute path = "<<cur->contents<<", newpath="<<newpath<<std::endl;
|
||||
}
|
||||
|
||||
if (readFileCallback) readFileCallback->_paths.push_back(newpath);
|
||||
else options->getDatabasePathList().push_back(newpath);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
for(osgDB::XmlNode::Children::iterator itr = root->children.begin();
|
||||
itr != root->children.end();
|
||||
++itr)
|
||||
|
||||
Reference in New Issue
Block a user