root/OpenSceneGraph/trunk/src/osgDB/Registry.cpp @ 9717

Revision 9717, 68.3 kB (checked in by robert, 5 years ago)

Removed redundent #pragma

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
RevLine 
[5328]1/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield
[1529]2 *
3 * This library is open source and may be redistributed and/or modified under 
4 * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
5 * (at your option) any later version.  The full license is in LICENSE file
6 * included with this distribution, and on the openscenegraph.org website.
7 *
8 * This library is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11 * OpenSceneGraph Public License for more details.
12*/
[8]13
[7994]14#include <stdio.h>
15#include <string.h>
16
[120]17#include <osg/Notify>
18#include <osg/Object>
19#include <osg/Image>
[7908]20#include <osg/Shader>
[120]21#include <osg/Node>
22#include <osg/Group>
23#include <osg/Geode>
[1610]24#include <osg/ApplicationUsage>
[7216]25#include <osg/Version>
[9024]26#include <osg/Timer>
[8]27
[120]28#include <osgDB/Registry>
29#include <osgDB/FileUtils>
30#include <osgDB/FileNameUtils>
[9124]31#include <osgDB/fstream>
[3580]32#include <osgDB/Archive>
[8]33
34#include <algorithm>
35#include <set>
36
[9475]37#include <stdlib.h>
38
[7243]39#if defined(__sgi)
40    #include <ctype.h>
41#elif defined(__GNUC__) || !defined(WIN32) || defined(__MWERKS__)
42    #include <cctype>
43    using std::tolower;
44#endif
45
[8913]46#ifdef OSG_DEBUG_POSTFIX
47    #define OSG_DEBUG_POSTFIX_WITH_QUOTES ADDQUOTES(OSG_DEBUG_POSTFIX)
48#else
49    #define OSG_DEBUG_POSTFIX_WITH_QUOTES "d"
[8375]50#endif
[7243]51
[8]52using namespace osg;
53using namespace osgDB;
54
[7544]55#if !defined(WIN32) || defined(__CYGWIN__)
56static osg::ApplicationUsageProxy Registry_e0(osg::ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_FILE_PATH <path>[:path]..","Paths for locating datafiles");
57static osg::ApplicationUsageProxy Registry_e1(osg::ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_LIBRARY_PATH <path>[:path]..","Paths for locating libraries/ plugins");
58#else
59static osg::ApplicationUsageProxy Registry_e0(osg::ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_FILE_PATH <path>[;path]..","Paths for locating datafiles");
60static osg::ApplicationUsageProxy Registry_e1(osg::ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_LIBRARY_PATH <path>[;path]..","Paths for locating libraries/ plugins");
61#endif
62
[8541]63static osg::ApplicationUsageProxy Registry_e2(osg::ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_BUILD_KDTREES on/off","Enable/disable the automatic building of KdTrees for each loaded Geometry.");
[7544]64
[8541]65
[3598]66class Registry::AvailableReaderWriterIterator
[2522]67{
68public:
[8929]69    AvailableReaderWriterIterator(Registry::ReaderWriterList& rwList, OpenThreads::ReentrantMutex& pluginMutex):
70        _rwList(rwList),
71        _pluginMutex(pluginMutex) {}
[2522]72
73
74    ReaderWriter& operator * () { return *get(); }
75    ReaderWriter* operator -> () { return get(); }
76   
77    bool valid() { return get()!=0; }
78   
79    void operator ++()
80    {
81        _rwUsed.insert(get());
82    }
83   
84
85protected:
86
[9460]87    AvailableReaderWriterIterator& operator = (const AvailableReaderWriterIterator&) { return *this; }
88
[2522]89    Registry::ReaderWriterList&     _rwList;
[8929]90    OpenThreads::ReentrantMutex&    _pluginMutex;
91   
[2522]92    std::set<ReaderWriter*>         _rwUsed;
93
94    ReaderWriter* get()
95    {
[8929]96        OpenThreads::ScopedLock<OpenThreads::ReentrantMutex> lock(_pluginMutex);
[2522]97        Registry::ReaderWriterList::iterator itr=_rwList.begin();
98        for(;itr!=_rwList.end();++itr)
99        {
100            if (_rwUsed.find(itr->get())==_rwUsed.end())
101            {
102                return itr->get();
103            }
104        }
105        return 0;
106    }
107
108};
109
[2007]110#if 0
111    // temporary test of autoregistering, not compiled by default.
112    enum Methods
113    {
114        SET_1,
115        SET_2,
116        END
117    };
118
119
120    typedef std::pair<Methods,std::string> MethodPair;
121
122    class Proxy
123    {
124    public:
125        Proxy(MethodPair* methods)
126        {
127            std::cout<<"methods "<<methods<<std::endl;
128            for(int i=0;methods[i].first!=END;++i)
129            {
130                std::cout<<"\t"<<methods[i].first<<"\t"<<methods[i].second<<std::endl;
131            }
132        }
133    };
134
135
136    static MethodPair methods[] =
137    {
138        MethodPair(SET_1,"SET_1"),
139        MethodPair(SET_2,"SET_2"),
140        MethodPair(END,"")
141    };
142
143    Proxy myproxy(methods);
144
145#endif
146
[775]147void PrintFilePathList(std::ostream& stream,const FilePathList& filepath)
[773]148{
149    for(FilePathList::const_iterator itr=filepath.begin();
150        itr!=filepath.end();
151        ++itr)
152    {
153        stream << "    "<< *itr<<std::endl;
154    }
155}
[8]156
[2534]157Registry* Registry::instance(bool erase)
[434]158{
[4881]159    static ref_ptr<Registry> s_registry = new Registry;
[2534]160    if (erase)
[6881]161    {   
162        s_registry->destruct();
[4881]163        s_registry = 0;
[2534]164    }
[4881]165    return s_registry.get(); // will return NULL on erase
[434]166}
167
168
[8]169// definition of the Registry
170Registry::Registry()
171{
[7648]172    // comment out because it was causing problems under OSX - causing it to crash osgconv when constructing ostream in osg::notify().
[1983]173    // notify(INFO) << "Constructing osg::Registry"<<std::endl;
[8]174
[8535]175    _buildKdTreesHint = ReaderWriter::Options::NO_PREFERENCE;
176    _kdTreeBuilder = new osg::KdTreeBuilder;
177   
178    const char* kdtree_str = getenv("OSG_BUILD_KDTREES");
179    if (kdtree_str)
180    {
181        bool switchOff = (strcmp(kdtree_str, "off")==0 || strcmp(kdtree_str, "OFF")==0 || strcmp(kdtree_str, "Off")==0 );
182        if (switchOff) _buildKdTreesHint = ReaderWriter::Options::DO_NOT_BUILD_KDTREES;
183        else _buildKdTreesHint = ReaderWriter::Options::BUILD_KDTREES;
184    }
185
[9038]186    const char* fileCachePath = getenv("OSG_FILE_CACHE");
187    if (fileCachePath)
188    {
189        _fileCache = new FileCache(fileCachePath);   
190    }
191
[2408]192    _createNodeFromImage = false;
[8]193    _openingLibrary = false;
[6628]194
195    // add default osga archive extension
196    _archiveExtList.push_back("osga");
[2340]197   
[773]198    initFilePathLists();
[8]199
[8535]200
201
[8]202    // register file extension alias.
[5038]203    const char* flt_str = getenv("OSG_OPEN_FLIGHT_PLUGIN");
204    if (flt_str)
205    {
206        if (strcmp(flt_str, "new")==0)
207        {
208            addFileExtensionAlias("flt", "OpenFlight");
209        }
210    }
[5196]211    else
212    {
213    #ifndef COMPILE_WITH_OLD_OPENFLIGHT_PLUGIN_AS_DEFAULT
214        addFileExtensionAlias("flt", "OpenFlight");
215    #endif
216    }
[5038]217
[7292]218    addFileExtensionAlias("osgs", "osg");
[6212]219    addFileExtensionAlias("shadow""osgShadow");
[7215]220    addFileExtensionAlias("terrain", "osgTerrain");
[6275]221    addFileExtensionAlias("view""osgViewer");
222
[919]223    addFileExtensionAlias("sgi""rgb");
[8]224    addFileExtensionAlias("rgba", "rgb");
225    addFileExtensionAlias("int""rgb");
226    addFileExtensionAlias("inta", "rgb");
227    addFileExtensionAlias("bw",   "rgb");
[2387]228
229    addFileExtensionAlias("ivz",   "gz");
230    addFileExtensionAlias("ozg",   "gz");
[8]231   
[8964]232    addFileExtensionAlias("mag",   "dicom");
233    addFileExtensionAlias("ph",   "dicom");
234    addFileExtensionAlias("ima",   "dicom");
[8782]235    addFileExtensionAlias("dcm",   "dicom");
236    addFileExtensionAlias("dic",   "dicom");
237
[8935]238    addFileExtensionAlias("gl",   "glsl");
239    addFileExtensionAlias("vert",   "glsl");
240    addFileExtensionAlias("frag",   "glsl");
241
[2718]242#if defined(DARWIN_QUICKTIME)
[1632]243    addFileExtensionAlias("jpg""qt");
244    addFileExtensionAlias("jpe""qt");
245    addFileExtensionAlias("jpeg", "qt");
246    addFileExtensionAlias("tif""qt");
247    addFileExtensionAlias("tiff", "qt");
[1696]248    addFileExtensionAlias("gif""qt");
249    addFileExtensionAlias("png""qt");
[4002]250    addFileExtensionAlias("psd""qt");
251    addFileExtensionAlias("tga""qt");
[2815]252    addFileExtensionAlias("mov""qt");
[3869]253    addFileExtensionAlias("avi""qt");
[2815]254    addFileExtensionAlias("mpg""qt");
[7572]255    addFileExtensionAlias("flv""qt");
[2815]256    addFileExtensionAlias("mpv""qt");
257    addFileExtensionAlias("dv",   "qt");
[8213]258    addFileExtensionAlias("mp4""qt");
259    addFileExtensionAlias("m4v""qt");
[8932]260    addFileExtensionAlias("3gp""qt");
[8213]261    // Add QuickTime live support for OSX
262    addFileExtensionAlias("live", "qt");
[1632]263#else
[8]264    addFileExtensionAlias("jpg""jpeg");
265    addFileExtensionAlias("jpe""jpeg");
266    addFileExtensionAlias("tif""tiff");
[3869]267
268    // really need to decide this at runtime...
269    #if defined(USE_XINE)
270        addFileExtensionAlias("mov""xine");
271        addFileExtensionAlias("mpg""xine");
[8828]272        addFileExtensionAlias("ogv""xine");
[3869]273        addFileExtensionAlias("mpv""xine");
274        addFileExtensionAlias("dv",   "xine");
275        addFileExtensionAlias("avi""xine");
[4076]276        addFileExtensionAlias("wmv""xine");
[7572]277        addFileExtensionAlias("flv""xine");
[3869]278    #endif
279
[8213]280    // support QuickTime for Windows
281    #if defined(USE_QUICKTIME)
282        addFileExtensionAlias("mov", "qt");
283        addFileExtensionAlias("live", "qt");
[8466]284        addFileExtensionAlias("mpg", "qt");
285        addFileExtensionAlias("avi", "qt");
[8213]286    #endif
[2815]287#endif
[2798]288
[1244]289    // remove geo to lwo alias as the new Carbon Graphics GEO format
290    // also uses the .geo. It is still possible to load light wave .geo
291    // files via loading the lwo plugin explicitly and then doing a readNodeFile.
292    //addFileExtensionAlias("geo",  "lwo");
[8]293    addFileExtensionAlias("lw",   "lwo");
[773]294
[6541]295    #if defined(USE_VRML)
296        addFileExtensionAlias("wrl",   "vrml");   
297    #elif defined(USE_INVENTOR)
298        addFileExtensionAlias("wrl",   "iv");
299    #endif
[1629]300   
301    // add alias for the text/freetype plugin.
302    addFileExtensionAlias("ttf",   "freetype");  // true type
303    addFileExtensionAlias("ttc",   "freetype");  // true type
304    addFileExtensionAlias("cid",   "freetype");  // Postscript CID-Fonts
305    addFileExtensionAlias("cff",   "freetype");  // OpenType
306    addFileExtensionAlias("cef",   "freetype");  // OpenType
307    addFileExtensionAlias("fon",   "freetype");  // Windows bitmap fonts
308    addFileExtensionAlias("fnt",   "freetype");    // Windows bitmap fonts
309   
[7648]310    // wont't add type1 and type2 until resolve extension collision with Performer binary and ascii files.
[1629]311    // addFileExtensionAlias("pfb",   "freetype");  // type1 binary
312    // addFileExtensionAlias("pfa",   "freetype");  // type2 ascii
[1930]313
314
315    // portable bitmap, greyscale and colour/pixmap image formats
316    addFileExtensionAlias("pbm", "pnm");
317    addFileExtensionAlias("pgm", "pnm");
318    addFileExtensionAlias("ppm", "pnm");
[2340]319   
[8]320}
321
322
323Registry::~Registry()
324{
[6881]325    destruct();
326}
327
328void Registry::destruct()
329{
[8325]330    // osg::notify(osg::NOTICE)<<"Registry::destruct()"<<std::endl;
331
[2631]332    // clean up the SharedStateManager
333    _sharedStateManager = 0;
334   
[3384]335
[9038]336    // clean up the FileCache
337    _fileCache = 0;
338   
339
[2631]340    // object cache clear needed here to prevent crash in unref() of
341    // the objects it contains when running the TXP plugin.
342    // Not sure why, but perhaps there is is something in a TXP plugin
[7648]343    // which deletes the data before its ref count hits zero, perhaps
[2631]344    // even some issue with objects be allocated by a plugin that is
[7648]345    // maintained after that plugin is deleted...  Robert Osfield, Jan 2004.
[3384]346    clearObjectCache();
[3598]347    clearArchiveCache();
348   
[2631]349
[2614]350    // unload all the plugin before we finally destruct.
[2534]351    closeAllLibraries();
[8]352}
353
[4420]354#include <iostream>
[4002]355
[773]356void Registry::initDataFilePathList()
357{
[4419]358    FilePathList filepath;
359    //
360    // set up data file paths
361    //
362    char *ptr;
[4007]363 
[4419]364    if( (ptr = getenv( "OSG_FILE_PATH" )) )
365    {
366        //notify(DEBUG_INFO) << "OSG_FILE_PATH("<<ptr<<")"<<std::endl;
367        convertStringPathIntoFilePathList(ptr, filepath);
368    }
369    else if( (ptr = getenv( "OSGFILEPATH" )) )
370    {
371        //notify(DEBUG_INFO) << "OSGFILEPATH("<<ptr<<")"<<std::endl;
372        convertStringPathIntoFilePathList(ptr, filepath);
373    }
[4002]374
[4420]375    osgDB::appendPlatformSpecificResourceFilePaths(filepath);
[4419]376    setDataFilePathList(filepath);
[4420]377   
[4002]378}
379
[3330]380void Registry::setDataFilePathList(const std::string& paths)
381{
382    _dataFilePath.clear();
383    convertStringPathIntoFilePathList(paths,_dataFilePath);
384}
385
386void Registry::setLibraryFilePathList(const std::string& paths) { _libraryFilePath.clear(); convertStringPathIntoFilePathList(paths,_libraryFilePath); }
387
[1610]388
[3330]389
[773]390void Registry::initLibraryFilePathList()
391{
392    //
393    // set up library paths
394    //
395    char* ptr;
396    if( (ptr = getenv( "OSG_LIBRARY_PATH")) )
397    {
[1983]398        //notify(DEBUG_INFO) << "OSG_LIBRARY_PATH("<<ptr<<")"<<std::endl;
[773]399        setLibraryFilePathList(ptr);
400    }
401    else if( (ptr = getenv( "OSG_LD_LIBRARY_PATH")) )
402    {
[1983]403        //notify(DEBUG_INFO) << "OSG_LD_LIBRARY_PATH("<<ptr<<")"<<std::endl;
[773]404        setLibraryFilePathList(ptr);
405    }
406   
[3330]407    appendPlatformSpecificLibraryFilePaths(_libraryFilePath);
[773]408
409}
410
[3330]411
[1613]412void Registry::readCommandLine(osg::ArgumentParser& arguments)
[1610]413{
[1613]414    // report the usage options.
415    if (arguments.getApplicationUsage())
416    {
417        arguments.getApplicationUsage()->addCommandLineOption("-l <library>","Load the plugin");
418        arguments.getApplicationUsage()->addCommandLineOption("-e <extension>","Load the plugin associated with handling files with specified extension");
419        arguments.getApplicationUsage()->addCommandLineOption("-O <option_string>","Provide an option string to reader/writers used to load databases");
420    }
[1610]421
422    std::string value;
[1613]423    while(arguments.read("-l",value))
[1610]424    {
425        loadLibrary(value);
426    }
427       
[1613]428    while(arguments.read("-e",value))
[1610]429    {
[2016]430        std::string libName = createLibraryNameForExtension(value);
[1610]431        loadLibrary(libName);
432    }
433
[1613]434    while(arguments.read("-O",value))
[1610]435    {
[8535]436        setOptions(new ReaderWriter::Options(value));
[1610]437    }
438}
439
[8]440void Registry::addDotOsgWrapper(DotOsgWrapper* wrapper)
441{
442    if (wrapper==0L) return;
443
[2268]444    //notify(INFO) << "osg::Registry::addDotOsgWrapper("<<wrapper->getName()<<")"<< std::endl;
[8]445    const DotOsgWrapper::Associates& assoc = wrapper->getAssociates();
446   
447    for(DotOsgWrapper::Associates::const_iterator itr=assoc.begin();
448                                                  itr!=assoc.end();
449                                                  ++itr)
450    {
[2268]451        //notify(INFO) << "    ("<<*itr<<")"<< std::endl;
[8]452    }
453
454    const std::string& name = wrapper->getName();
455    const osg::Object* proto = wrapper->getPrototype();
456
457    _objectWrapperMap[name] = wrapper;
[2501]458    if (wrapper->getReadWriteMode()==DotOsgWrapper::READ_AND_WRITE) _classNameWrapperMap[name] = wrapper;
[2174]459   
[8]460    if (proto)
461    {
[742]462        std::string libraryName = proto->libraryName();
463        std::string compositeName = libraryName + "::" + name;
464
[743]465        _objectWrapperMap[compositeName] = wrapper;
[2238]466        if (wrapper->getReadWriteMode()==DotOsgWrapper::READ_AND_WRITE) _classNameWrapperMap[compositeName] = wrapper;
[743]467
[742]468        if (dynamic_cast<const Image*>(proto))
469        {
470            _imageWrapperMap[name] = wrapper;
471            _imageWrapperMap[compositeName] = wrapper;
472        }
473        if (dynamic_cast<const Drawable*>(proto))
474        {
475              _drawableWrapperMap[name] = wrapper;
476              _drawableWrapperMap[compositeName] = wrapper;
477        }
478        if (dynamic_cast<const StateAttribute*>(proto))
479        {
480            _stateAttrWrapperMap[name] = wrapper;
481            _stateAttrWrapperMap[compositeName] = wrapper;
482        }
[4061]483        if (dynamic_cast<const Uniform*>(proto))
484        {
485            _uniformWrapperMap[name] = wrapper;
486            _uniformWrapperMap[compositeName] = wrapper;
487        }
[742]488        if (dynamic_cast<const Node*>(proto))
489        {
490            _nodeWrapperMap[name] = wrapper;
491            _nodeWrapperMap[compositeName] = wrapper;
492        }
[7908]493        if (dynamic_cast<const Shader*>(proto))
494        {
495            _shaderWrapperMap[name] = wrapper;
496            _shaderWrapperMap[compositeName] = wrapper;
497        }
[742]498
499
[8]500    }
501}
502
[742]503// need to change to delete all instances of wrapper, since we
504// now can have a wrapper entered twice with the addition of the
505// library::class composite name.
506void Registry::eraseWrapper(DotOsgWrapperMap& wrappermap,DotOsgWrapper* wrapper)
507{
508    typedef std::vector<DotOsgWrapperMap::iterator> EraseList;
509    EraseList eraseList;
510    for(DotOsgWrapperMap::iterator witr=wrappermap.begin();
511        witr!=wrappermap.end();
512        ++witr)
513    {
514        if (witr->second==wrapper) eraseList.push_back(witr);
515    }
516    for(EraseList::iterator eitr=eraseList.begin();
517        eitr!=eraseList.end();
518        ++eitr)
519    {
520        wrappermap.erase(*eitr);
521    }
[8]522}
[742]523
[8]524void Registry::removeDotOsgWrapper(DotOsgWrapper* wrapper)
525{
526    if (wrapper==0L) return;
527
[742]528    eraseWrapper(_objectWrapperMap,wrapper);
529    eraseWrapper(_classNameWrapperMap,wrapper);
530    eraseWrapper(_imageWrapperMap,wrapper);
531    eraseWrapper(_drawableWrapperMap,wrapper);
[4061]532    eraseWrapper(_uniformWrapperMap,wrapper);
[742]533    eraseWrapper(_stateAttrWrapperMap,wrapper);
534    eraseWrapper(_nodeWrapperMap,wrapper);
[7908]535    eraseWrapper(_shaderWrapperMap,wrapper);
[8]536}
537
538void Registry::addReaderWriter(ReaderWriter* rw)
539{
540    if (rw==0L) return;
541
[2268]542    // notify(INFO) << "osg::Registry::addReaderWriter("<<rw->className()<<")"<< std::endl;
[8]543
[8929]544    OpenThreads::ScopedLock<OpenThreads::ReentrantMutex> lock(_pluginMutex);
545
[8]546    _rwList.push_back(rw);
547
548}
549
550
551void Registry::removeReaderWriter(ReaderWriter* rw)
552{
553    if (rw==0L) return;
554
[211]555//    notify(INFO) << "osg::Registry::removeReaderWriter();"<< std::endl;
[8]556
[8929]557    OpenThreads::ScopedLock<OpenThreads::ReentrantMutex> lock(_pluginMutex);
558
[8]559    ReaderWriterList::iterator rwitr = std::find(_rwList.begin(),_rwList.end(),rw);
560    if (rwitr!=_rwList.end())
561    {
562        _rwList.erase(rwitr);
563    }
564
565}
566
567
568void Registry::addFileExtensionAlias(const std::string mapExt, const std::string toExt)
569{
[4948]570    _extAliasMap[mapExt] = toExt;
[8]571}
572
[6089]573bool Registry::readPluginAliasConfigurationFile( const std::string& file )
574{
575    std::string fileName = osgDB::findDataFile( file );
576    if (fileName.empty())
577    {
578        osg::notify( osg::WARN) << "Can't find plugin alias config file \"" << file << "\"." << std::endl;
579        return false;
580    }
581
[9124]582    osgDB::ifstream ifs;
[6089]583    ifs.open( fileName.c_str() );
584    if (!ifs.good())
585    {
586        osg::notify( osg::WARN) << "Can't open plugin alias config file \"" << fileName << "\"." << std::endl;
587        return false;
588    }
589
590    int lineNum( 0 );
591    while (ifs.good())
592    {
593        std::string raw;
594        ++lineNum;
595        std::getline( ifs, raw );
596        std::string ln = trim( raw );
597        if (ln.empty()) continue;
598        if (ln[0] == '#') continue;
599
600        std::string::size_type spIdx = ln.find_first_of( " \t" );
601        if (spIdx == ln.npos)
602        {
603            // mapExt and toExt must be on the same line, separated by a space.
604            osg::notify( osg::WARN) << file << ", line " << lineNum << ": Syntax error: missing space in \"" << raw << "\"." << std::endl;
605            continue;
606        }
607
608        const std::string mapExt = trim( ln.substr( 0, spIdx ) );
609        const std::string toExt = trim( ln.substr( spIdx+1 ) );
610        addFileExtensionAlias( mapExt, toExt );
611    }
612    return true;
613}
614
615std::string Registry::trim( const std::string& str )
616{
617    if (!str.size()) return str;
618    std::string::size_type first = str.find_first_not_of( " \t" );
619    std::string::size_type last = str.find_last_not_of( "  \t\r\n" );
620    if ((first==str.npos) || (last==str.npos)) return std::string( "" );
621    return str.substr( first, last-first+1 );
622}
623
624
[8]625std::string Registry::createLibraryNameForFile(const std::string& fileName)
626{
[7243]627    return createLibraryNameForExtension(getFileExtension(fileName));
[8]628}
629
[2016]630std::string Registry::createLibraryNameForExtension(const std::string& ext)
[8]631{
[7243]632    std::string lowercase_ext;
[7459]633    for(std::string::const_iterator sitr=ext.begin();
634        sitr!=ext.end();
635        ++sitr)
[7243]636    {
[7459]637        lowercase_ext.push_back(tolower(*sitr));
[7243]638    }
[8]639
[7243]640    ExtensionAliasMap::iterator itr=_extAliasMap.find(lowercase_ext);
[5035]641    if (itr!=_extAliasMap.end() && ext != itr->second) return createLibraryNameForExtension(itr->second);
[8]642
[3767]643#ifdef OSG_JAVA_BUILD
[7216]644    static std::string prepend = std::string("osgPlugins-")+std::string(osgGetVersion())+std::string("/java");
645#elseif defined(__APPLE__)
646    // OSX is rather a mess in FileUtils.cpp w.r.t its appendPlatformSpecificLibraryFilePaths implementation
647    // as it hardwires the plugin name to PlugIns.  This *needs* fixing to use the naming convention as all
648    // other platforms.
649    static std::string prepend = "";
[3767]650#else
[7216]651    static std::string prepend = std::string("osgPlugins-")+std::string(osgGetVersion())+std::string("/");
[3767]652#endif
653
[7544]654#if defined(__CYGWIN__)
[8875]655    #ifdef _DEBUG
[8913]656        return prepend+"cygwin_"+"osgdb_"+lowercase_ext+OSG_DEBUG_POSTFIX_WITH_QUOTES+".dll";
[8875]657    #else
658        return prepend+"cygwin_"+"osgdb_"+lowercase_ext+".dll";
659    #endif
[7544]660#elif defined(__MINGW32__)
661    return prepend+"mingw_"+"osgdb_"+lowercase_ext+".dll";
662#elif defined(WIN32)
663    #ifdef _DEBUG
[8913]664        return prepend+"osgdb_"+lowercase_ext+ OSG_DEBUG_POSTFIX_WITH_QUOTES +".dll";
[796]665    #else
[7544]666        return prepend+"osgdb_"+lowercase_ext+".dll";
[796]667    #endif
668#elif macintosh
[7243]669    return prepend+"osgdb_"+lowercase_ext;
[959]670#elif defined(__hpux__)
671    // why don't we use PLUGIN_EXT from the makefiles here?
[7243]672    return prepend+"osgdb_"+lowercase_ext+".sl";
[796]673#else
[8375]674    #ifdef _DEBUG
[8913]675         return prepend+"osgdb_"+lowercase_ext+ OSG_DEBUG_POSTFIX_WITH_QUOTES + ".so";
[8375]676    #else
677         return prepend+"osgdb_"+lowercase_ext+".so";
678    #endif
[796]679#endif
[8]680
681}
682
[742]683std::string Registry::createLibraryNameForNodeKit(const std::string& name)
684{
[7544]685#if defined(__CYGWIN__)
[2501]686    return "cyg"+name+".dll";
[7544]687#elif defined(__MINGW32__)
688    return "lib"+name+".dll";
689#elif defined(WIN32)
690    #ifdef _DEBUG
[8913]691        return name+OSG_DEBUG_POSTFIX_WITH_QUOTES +".dll";
[796]692    #else
[7548]693        return name+".dll";
[796]694    #endif
695#elif macintosh
[742]696    return name;
[959]697#elif defined(__hpux__)
698    // why don't we use PLUGIN_EXT from the makefiles here?
699    return "lib"+name+".sl";
[796]700#else
[8375]701    #ifdef _DEBUG
[8913]702        return "lib"+name+OSG_DEBUG_POSTFIX_WITH_QUOTES +".so";
[8375]703    #else
704        return "lib"+name+".so";
705    #endif
[796]706#endif
[742]707}
[8]708
[8947]709Registry::LoadStatus Registry::loadLibrary(const std::string& fileName)
[8]710{
[8929]711    OpenThreads::ScopedLock<OpenThreads::ReentrantMutex> lock(_pluginMutex);
[8]712
[8929]713    DynamicLibraryList::iterator ditr = getLibraryItr(fileName);
[8947]714    if (ditr!=_dlList.end()) return PREVIOUSLY_LOADED;
[8929]715
[8]716    _openingLibrary=true;
717
[8929]718    DynamicLibrary* dl = DynamicLibrary::loadLibrary(fileName);
[8]719    _openingLibrary=false;
720
721    if (dl)
722    {
723        _dlList.push_back(dl);
[8947]724        return LOADED;
[8]725    }
[8947]726    return NOT_LOADED;
[8]727}
728
729
730bool Registry::closeLibrary(const std::string& fileName)
731{
[8929]732    OpenThreads::ScopedLock<OpenThreads::ReentrantMutex> lock(_pluginMutex);
[8]733    DynamicLibraryList::iterator ditr = getLibraryItr(fileName);
734    if (ditr!=_dlList.end())
735    {
736        _dlList.erase(ditr);
737        return true;
738    }
739    return false;
740}
741
[2534]742void Registry::closeAllLibraries()
743{
[8325]744    // osg::notify(osg::NOTICE)<<"Registry::closeAllLibraries()"<<std::endl;
[8929]745    OpenThreads::ScopedLock<OpenThreads::ReentrantMutex> lock(_pluginMutex);
[2534]746    _dlList.clear();
747}
[8]748
749Registry::DynamicLibraryList::iterator Registry::getLibraryItr(const std::string& fileName)
750{
751    DynamicLibraryList::iterator ditr = _dlList.begin();
752    for(;ditr!=_dlList.end();++ditr)
753    {
754        if ((*ditr)->getName()==fileName) return ditr;
755    }
756    return _dlList.end();
757}
758
759DynamicLibrary* Registry::getLibrary(const std::string& fileName)
760{
[8929]761    OpenThreads::ScopedLock<OpenThreads::ReentrantMutex> lock(_pluginMutex);
[8]762    DynamicLibraryList::iterator ditr = getLibraryItr(fileName);
763    if (ditr!=_dlList.end()) return ditr->get();
764    else return NULL;
765}
766
[2016]767ReaderWriter* Registry::getReaderWriterForExtension(const std::string& ext)
768{
769    // record the existing reader writer.
770    std::set<ReaderWriter*> rwOriginal;
771
[8929]772    OpenThreads::ScopedLock<OpenThreads::ReentrantMutex> lock(_pluginMutex);
773
[2016]774    // first attemt one of the installed loaders
775    for(ReaderWriterList::iterator itr=_rwList.begin();
776        itr!=_rwList.end();
777        ++itr)
778    {
779        rwOriginal.insert(itr->get());
780        if((*itr)->acceptsExtension(ext)) return (*itr).get();
781    }
[8929]782   
[2016]783    // now look for a plug-in to load the file.
784    std::string libraryName = createLibraryNameForExtension(ext);
785    notify(INFO) << "Now checking for plug-in "<<libraryName<< std::endl;
[8947]786    if (loadLibrary(libraryName)==LOADED)
[2016]787    {
788        for(ReaderWriterList::iterator itr=_rwList.begin();
789            itr!=_rwList.end();
790            ++itr)
791        {
792            if (rwOriginal.find(itr->get())==rwOriginal.end())
[8955]793            {
794                if((*itr)->acceptsExtension(ext)) return (*itr).get();
795            }
[2016]796        }
797    }
798
799    return NULL;
800
801}
802
[2123]803struct concrete_wrapper: basic_type_wrapper
804{
[4461]805    virtual ~concrete_wrapper() {}
[2501]806    concrete_wrapper(const osg::Object *myobj) : myobj_(myobj) {}
807    bool matches(const osg::Object *proto) const
808    {
809        return myobj_->isSameKindAs(proto);
810    }
811    const osg::Object *myobj_;
[2123]812};
[2016]813
[8]814osg::Object* Registry::readObjectOfType(const osg::Object& compObj,Input& fr)
815{
[2501]816    return readObjectOfType(concrete_wrapper(&compObj), fr);
[2057]817}
818
819osg::Object* Registry::readObjectOfType(const basic_type_wrapper &btw,Input& fr)
820{
[8]821    const char *str = fr[0].getStr();
822    if (str==NULL) return NULL;
823
824    if (fr[0].matchWord("Use"))
825    {
826        if (fr[1].isString())
827        {
828            Object* obj = fr.getObjectForUniqueID(fr[1].getStr());
[2057]829            if (obj && btw.matches(obj))
[715]830            {
831                fr+=2;
832                return obj;
833            }
[8]834        }
835        else return NULL;
836
837    }
838
839    std::string name = str;
840    DotOsgWrapperMap::iterator itr = _objectWrapperMap.find(name);
[742]841    if (itr==_objectWrapperMap.end())
[8]842    {
[742]843        // not found so check if a library::class composite name.
844        std::string token = fr[0].getStr();
845        std::string::size_type posDoubleColon = token.rfind("::");
846        if (posDoubleColon != std::string::npos)
847        {
848            // we have a composite name so now strip off the library name
849            // are try to load it, and then retry the readObject to see
[7648]850            // if we can recognize the objects.
[742]851            std::string libraryName = std::string(token,0,posDoubleColon);
852
853            // first try the standard nodekit library.
854            std::string nodeKitLibraryName = createLibraryNameForNodeKit(libraryName);
[8947]855            if (loadLibrary(nodeKitLibraryName)==LOADED) return readObjectOfType(btw,fr);
[742]856           
857            // otherwise try the osgdb_ plugin library.
[2016]858            std::string pluginLibraryName = createLibraryNameForExtension(libraryName);
[8947]859            if (loadLibrary(pluginLibraryName)==LOADED) return readObjectOfType(btw,fr);
[742]860        }
861    }
862    else if (fr[1].isOpenBracket())
863    {
[8]864        DotOsgWrapper* wrapper = itr->second.get();
865        const osg::Object* proto = wrapper->getPrototype();
866        if (proto==NULL)
867        {
[211]868            osg::notify(osg::WARN)<<"Token "<<fr[0].getStr()<<" read, but has no prototype, cannot load."<< std::endl;
[8]869            return NULL;
870        }
871       
[2057]872        if (!btw.matches(proto))
[8]873        {
874            return NULL;
875        }
876
877        // record the number of nested brackets move the input iterator
878        // over the name { tokens.
879        int entry = fr[0].getNoNestedBrackets();
880        fr+=2;
881
882        const DotOsgWrapper::Associates& assoc = wrapper->getAssociates();
[327]883        osg::Object* obj = proto->cloneType();
[8]884
885        while(!fr.eof() && fr[0].getNoNestedBrackets()>entry)
886        {
887            bool iteratorAdvanced = false;
888            if (fr[0].matchWord("UniqueID") && fr[1].isString())
889            {
[7038]890                fr.registerUniqueIDForObject(fr[1].getStr(),obj);
[8]891                fr += 2;
892                iteratorAdvanced = true;
893            }
894
895            // read the local data by iterating through the associate
896            // list, mapping the associate names to DotOsgWrapper's which
897            // in turn have the appropriate functions.
898            for(DotOsgWrapper::Associates::const_iterator aitr=assoc.begin();
899                                                          aitr!=assoc.end();
900                                                          ++aitr)
901            {
902                DotOsgWrapperMap::iterator mitr = _objectWrapperMap.find(*aitr);
[2174]903                if (mitr==_objectWrapperMap.end())
904                {
905                    // not found so check if a library::class composite name.
906                    std::string token = *aitr;
907                    std::string::size_type posDoubleColon = token.rfind("::");
908                    if (posDoubleColon != std::string::npos)
909                    {
910                        // we have a composite name so now strip off the library name
[8955]911                        // and try to load it, and then retry the find to see
[7648]912                        // if we can recognize the objects.
[2174]913                        std::string libraryName = std::string(token,0,posDoubleColon);
914
915                        // first try the standard nodekit library.
916                        std::string nodeKitLibraryName = createLibraryNameForNodeKit(libraryName);
[8955]917                        if (loadLibrary(nodeKitLibraryName)==LOADED)
[2174]918                        {
919                            mitr = _objectWrapperMap.find(*aitr);
[8955]920                            if (mitr==_objectWrapperMap.end())
[2174]921                            {
[8955]922                                // otherwise try the osgdb_ plugin library.
923                                std::string pluginLibraryName = createLibraryNameForExtension(libraryName);
924                                if (loadLibrary(pluginLibraryName)==LOADED)
925                                {
926                                    mitr = _objectWrapperMap.find(*aitr);
927                                }
[2174]928                            }
929                        }
930                    }
931                }
932
[8]933                if (mitr!=_objectWrapperMap.end())
934                {
935                    // get the function to read the data...
936                    DotOsgWrapper::ReadFunc rf = mitr->second->getReadFunc();
937                    if (rf && (*rf)(*obj,fr)) iteratorAdvanced = true;
938                }
939
940            }
941
[741]942            if (!iteratorAdvanced) fr.advanceOverCurrentFieldOrBlock();
[8]943        }
944        ++fr;                        // step over trailing '}'
945       
946        return obj;
947       
948    }
949    return 0L;
950}
951
952//
953// read object from input iterator.
954//
955osg::Object* Registry::readObject(DotOsgWrapperMap& dowMap,Input& fr)
956{
957    const char *str = fr[0].getStr();
958    if (str==NULL) return NULL;
959
960    std::string name = str;
961    DotOsgWrapperMap::iterator itr = dowMap.find(name);
[742]962    if (itr==dowMap.end())
[8]963    {
[742]964        // not found so check if a library::class composite name.
965        std::string token = fr[0].getStr();
966        std::string::size_type posDoubleColon = token.rfind("::");
967        if (posDoubleColon != std::string::npos)
968        {
969            // we have a composite name so now strip off the library name
970            // are try to load it, and then retry the readObject to see
[7648]971            // if we can recognize the objects.
[742]972       
973            std::string libraryName = std::string(token,0,posDoubleColon);
974
975            // first try the standard nodekit library.
976            std::string nodeKitLibraryName = createLibraryNameForNodeKit(libraryName);
[8947]977            if (loadLibrary(nodeKitLibraryName)==LOADED) return readObject(dowMap,fr);
[742]978           
979            // otherwise try the osgdb_ plugin library.
[2016]980            std::string pluginLibraryName = createLibraryNameForExtension(libraryName);
[8947]981            if (loadLibrary(pluginLibraryName)==LOADED) return readObject(dowMap,fr);
[742]982        }
983    }
984    else if (fr[1].isOpenBracket())
985    {
[8]986   
987        DotOsgWrapper* wrapper = itr->second.get();
988        const osg::Object* proto = wrapper->getPrototype();
989        if (proto==NULL)
990        {
[211]991            osg::notify(osg::WARN)<<"Token "<<fr[0].getStr()<<" read, but has no prototype, cannot load."<< std::endl;
[8]992            return NULL;
993        }
994
995        // record the number of nested brackets move the input iterator
996        // over the name { tokens.
997        int entry = fr[0].getNoNestedBrackets();
998        fr+=2;
999
1000        const DotOsgWrapper::Associates& assoc = wrapper->getAssociates();
[327]1001        osg::Object* obj = proto->cloneType();
[8]1002
1003        while(!fr.eof() && fr[0].getNoNestedBrackets()>entry)
1004        {
1005            bool iteratorAdvanced = false;
1006            if (fr[0].matchWord("UniqueID") && fr[1].isString())
1007            {
[7038]1008                fr.registerUniqueIDForObject(fr[1].getStr(),obj);
[8]1009                fr += 2;
1010                iteratorAdvanced = true;
1011            }
1012
1013            // read the local data by iterating through the associate
1014            // list, mapping the associate names to DotOsgWrapper's which
1015            // in turn have the appropriate functions.
1016            for(DotOsgWrapper::Associates::const_iterator aitr=assoc.begin();
1017                                                          aitr!=assoc.end();
1018                                                          ++aitr)
1019            {
1020                DotOsgWrapperMap::iterator mitr = _objectWrapperMap.find(*aitr);
[2174]1021                if (mitr==_objectWrapperMap.end())
1022                {
1023                    // not found so check if a library::class composite name.
1024                    std::string token = *aitr;
1025                    std::string::size_type posDoubleColon = token.rfind("::");
1026                    if (posDoubleColon != std::string::npos)
1027                    {
1028
1029                        // we have a composite name so now strip off the library name
1030                        // are try to load it, and then retry the find to see
[7648]1031                        // if we can recognize the objects.
[2174]1032
1033                        std::string libraryName = std::string(token,0,posDoubleColon);
1034
1035                        // first try the standard nodekit library.
1036                        std::string nodeKitLibraryName = createLibraryNameForNodeKit(libraryName);
[8947]1037                        if (loadLibrary(nodeKitLibraryName)==LOADED)
[2174]1038                        {
1039                            mitr = _objectWrapperMap.find(*aitr);
1040                        }
1041
1042                        if (mitr==_objectWrapperMap.end())
1043                        {
1044                            // otherwise try the osgdb_ plugin library.
1045                            std::string pluginLibraryName = createLibraryNameForExtension(libraryName);
[8947]1046                            if (loadLibrary(pluginLibraryName)==LOADED)
[2174]1047                            {
1048                                mitr = _objectWrapperMap.find(*aitr);
1049                            }
1050                        }
1051
1052                    }
1053                }
1054
[8]1055                if (mitr!=_objectWrapperMap.end())
1056                {
1057                    // get the function to read the data...
1058                    DotOsgWrapper::ReadFunc rf = mitr->second->getReadFunc();
1059                    if (rf && (*rf)(*obj,fr)) iteratorAdvanced = true;
1060                }
1061
1062            }
1063
[741]1064            if (!iteratorAdvanced) fr.advanceOverCurrentFieldOrBlock();
[8]1065        }
1066        ++fr;                        // step over trailing '}'
1067       
1068        return obj;
1069       
1070    }
1071
1072    return 0L;
1073}
1074
1075//
1076// read object from input iterator.
1077//
1078Object* Registry::readObject(Input& fr)
1079{
1080    if (fr[0].matchWord("Use"))
1081    {
1082        if (fr[1].isString())
1083        {
1084            Object* obj = fr.getObjectForUniqueID(fr[1].getStr());
1085            if (obj) fr+=2;
1086            return obj;
1087        }
1088        else return NULL;
1089
1090    }
1091
1092    return readObject(_objectWrapperMap,fr);
1093}
1094
1095
1096//
1097// read image from input iterator.
1098//
1099Image* Registry::readImage(Input& fr)
1100{
1101    if (fr[0].matchWord("Use"))
1102    {
1103        if (fr[1].isString())
1104        {
1105            Image* image = dynamic_cast<Image*>(fr.getObjectForUniqueID(fr[1].getStr()));
1106            if (image) fr+=2;
1107            return image;
1108        }
1109        else return NULL;
1110
1111    }
1112
[480]1113    osg::Object* obj = readObject(_imageWrapperMap,fr);
1114    osg::Image* image = dynamic_cast<Image*>(obj);
1115    if (image) return image;
1116    else if (obj) obj->unref();
1117   
1118    return NULL;
[8]1119}
1120
1121
1122//
1123// read drawable from input iterator.
1124//
1125Drawable* Registry::readDrawable(Input& fr)
1126{
1127    if (fr[0].matchWord("Use"))
1128    {
1129        if (fr[1].isString())
1130        {
1131            Drawable* drawable = dynamic_cast<Drawable*>(fr.getObjectForUniqueID(fr[1].getStr()));
1132            if (drawable) fr+=2;
1133            return drawable;
1134        }
1135        else return NULL;
1136
1137    }
1138
[480]1139    osg::Object* obj = readObject(_drawableWrapperMap,fr);
1140    osg::Drawable* drawable = dynamic_cast<Drawable*>(obj);
1141    if (drawable) return drawable;
1142    else if (obj) obj->unref();
1143   
1144    return NULL;
[8]1145}
1146
1147//
1148// read drawable from input iterator.
1149//
1150StateAttribute* Registry::readStateAttribute(Input& fr)
1151{
1152
1153    if (fr[0].matchWord("Use"))
1154    {
1155        if (fr[1].isString())
1156        {
1157            StateAttribute* attribute = dynamic_cast<StateAttribute*>(fr.getObjectForUniqueID(fr[1].getStr()));
1158            if (attribute) fr+=2;
1159            return attribute;
1160        }
1161        else return NULL;
1162
1163    }
1164
1165    return dynamic_cast<StateAttribute*>(readObject(_stateAttrWrapperMap,fr));
1166}
1167
1168//
[4061]1169// read drawable from input iterator.
1170//
1171Uniform* Registry::readUniform(Input& fr)
1172{
1173
1174    if (fr[0].matchWord("Use"))
1175    {
1176        if (fr[1].isString())
1177        {
1178            Uniform* attribute = dynamic_cast<Uniform*>(fr.getObjectForUniqueID(fr[1].getStr()));
1179            if (attribute) fr+=2;
1180            return attribute;
1181        }
1182        else return NULL;
1183
1184    }
1185
1186    return dynamic_cast<Uniform*>(readObject(_uniformWrapperMap,fr));
1187}
1188
1189//
[8]1190// read node from input iterator.
1191//
1192Node* Registry::readNode(Input& fr)
1193{
1194    if (fr[0].matchWord("Use"))
1195    {
1196        if (fr[1].isString())
1197        {
1198            Node* node = dynamic_cast<Node*>(fr.getObjectForUniqueID(fr[1].getStr()));
1199            if (node) fr+=2;
1200            return node;
1201        }
1202        else return NULL;
1203
1204    }
1205
[480]1206    osg::Object* obj = readObject(_nodeWrapperMap,fr);
1207    osg::Node* node = dynamic_cast<Node*>(obj);
1208    if (node) return node;
1209    else if (obj) obj->unref();
1210   
1211    return NULL;
[8]1212}
1213
1214//
[7908]1215// read image from input iterator.
1216//
1217Shader* Registry::readShader(Input& fr)
1218{
1219    if (fr[0].matchWord("Use"))
1220    {
1221        if (fr[1].isString())
1222        {
1223            Shader* shader = dynamic_cast<Shader*>(fr.getObjectForUniqueID(fr[1].getStr()));
1224            if (shader) fr+=2;
1225            return shader;
1226        }
1227        else return NULL;
1228
1229    }
1230
1231    osg::Object* obj = readObject(_shaderWrapperMap,fr);
1232    osg::Shader* shader = dynamic_cast<Shader*>(obj);
1233    if (shader) return shader;
1234    else if (obj) obj->unref();
1235   
1236    return NULL;
1237}
1238
1239//
[8]1240// Write object to output
1241//
1242bool Registry::writeObject(const osg::Object& obj,Output& fw)
1243{
1244
1245    if (obj.referenceCount()>1)
1246    {
1247        std::string uniqueID;
1248        if (fw.getUniqueIDForObject(&obj,uniqueID))
1249        {
[6629]1250            fw.writeUseID( uniqueID );
[8]1251            return true;
1252        }
1253    }
1254
[6629]1255    const std::string classname( obj.className() );
1256    const std::string libraryName( obj.libraryName() );
1257    const std::string compositeName( libraryName + "::" + classname );
[1061]1258
[2501]1259    // try composite name first
1260    DotOsgWrapperMap::iterator itr = _classNameWrapperMap.find(compositeName);
[1061]1261
1262    if (itr==_classNameWrapperMap.end())
[8]1263    {
[1061]1264        // first try the standard nodekit library.
[6629]1265        std::string nodeKitLibraryName = createLibraryNameForNodeKit(libraryName);
[8947]1266        if (loadLibrary(nodeKitLibraryName)==LOADED) return writeObject(obj,fw);
[1061]1267
1268        // otherwise try the osgdb_ plugin library.
[6629]1269        std::string pluginLibraryName = createLibraryNameForExtension(libraryName);
[8947]1270        if (loadLibrary(pluginLibraryName)==LOADED) return writeObject(obj,fw);
[4635]1271
1272        // otherwise try simple class name
1273        if (itr == _classNameWrapperMap.end())
1274            itr = _classNameWrapperMap.find(classname);
[1061]1275    }
[4635]1276
1277    if (itr!=_classNameWrapperMap.end())
1278    {
[8]1279        DotOsgWrapper* wrapper = itr->second.get();
1280        const DotOsgWrapper::Associates& assoc = wrapper->getAssociates();
1281
[6629]1282        if (libraryName=="osg")
[742]1283        {
1284            // member of the core osg, so no need to have composite library::class name.
[6629]1285            fw.writeBeginObject( wrapper->getName() );
[742]1286        }
1287        else
1288        {
1289            // member of the node kit so must use composite library::class name.
[2180]1290            std::string::size_type posDoubleColon = wrapper->getName().find("::");
1291            if (posDoubleColon != std::string::npos)
1292            {
[6629]1293                fw.writeBeginObject( wrapper->getName() );
[2180]1294            }
1295            else
1296            {
[6629]1297                fw.writeBeginObject( libraryName + "::" + wrapper->getName() );
[2180]1298            }
[742]1299        }
[6629]1300        fw.moveIn();
[8]1301
1302
1303        // write out the unique ID if required.
1304        if (obj.referenceCount()>1)
1305        {
1306            std::string uniqueID;
1307            fw.createUniqueIDForObject(&obj,uniqueID);
1308            fw.registerUniqueIDForObject(&obj,uniqueID);
[6629]1309            fw.writeUniqueID( uniqueID );
[8]1310        }
1311
1312        // read the local data by iterating through the associate
1313        // list, mapping the associate names to DotOsgWrapper's which
1314        // in turn have the appropriate functions.
1315        for(DotOsgWrapper::Associates::const_iterator aitr=assoc.begin();
1316                                                      aitr!=assoc.end();
1317                                                      ++aitr)
1318        {
1319            DotOsgWrapperMap::iterator mitr = _objectWrapperMap.find(*aitr);
[2238]1320            if (mitr==_objectWrapperMap.end())
1321            {
1322                // not found so check if a library::class composite name.
1323                std::string token = *aitr;
1324                std::string::size_type posDoubleColon = token.rfind("::");
1325                if (posDoubleColon != std::string::npos)
1326                {
1327
1328                    // we have a composite name so now strip off the library name
1329                    // are try to load it, and then retry the find to see
[7648]1330                    // if we can recognize the objects.
[2238]1331
1332                    std::string libraryName = std::string(token,0,posDoubleColon);
1333
1334                    // first try the standard nodekit library.
1335                    std::string nodeKitLibraryName = createLibraryNameForNodeKit(libraryName);
[8947]1336                    if (loadLibrary(nodeKitLibraryName)==LOADED)
[2238]1337                    {
1338                        mitr = _objectWrapperMap.find(*aitr);
1339                    }
1340
1341                    if (mitr==_objectWrapperMap.end())
1342                    {
1343                        // otherwise try the osgdb_ plugin library.
1344                        std::string pluginLibraryName = createLibraryNameForExtension(libraryName);
[8947]1345                        if (loadLibrary(pluginLibraryName)==LOADED)
[2238]1346                        {
1347                            mitr = _objectWrapperMap.find(*aitr);
1348                        }
1349                    }
1350
1351                }
1352            }
[8]1353            if (mitr!=_objectWrapperMap.end())
1354            {
1355                // get the function to read the data...
1356                DotOsgWrapper::WriteFunc wf = mitr->second->getWriteFunc();
1357                if (wf) (*wf)(obj,fw);
1358            }
1359
1360        }
1361
1362        fw.moveOut();
[6629]1363        fw.writeEndObject();
[8]1364
1365        return true;
1366    }
[1061]1367   
[8]1368    return false;
1369}
1370
[3580]1371
[3581]1372
[3596]1373struct Registry::ReadObjectFunctor : public Registry::ReadFunctor
[3580]1374{
[3581]1375    ReadObjectFunctor(const std::string& filename, const ReaderWriter::Options* options):ReadFunctor(filename,options) {}
[3580]1376
[3693]1377    virtual ReaderWriter::ReadResult doRead(ReaderWriter& rw) const { return rw.readObject(_filename, _options); }   
[3581]1378    virtual bool isValid(ReaderWriter::ReadResult& readResult) const { return readResult.validObject(); }
1379    virtual bool isValid(osg::Object* object) const { return object!=0;  }
1380};
[3580]1381
[3596]1382struct Registry::ReadImageFunctor : public Registry::ReadFunctor
[3581]1383{
1384    ReadImageFunctor(const std::string& filename, const ReaderWriter::Options* options):ReadFunctor(filename,options) {}
[3580]1385
[3693]1386    virtual ReaderWriter::ReadResult doRead(ReaderWriter& rw)const  { return rw.readImage(_filename, _options); }   
[3581]1387    virtual bool isValid(ReaderWriter::ReadResult& readResult) const { return readResult.validImage(); }
1388    virtual bool isValid(osg::Object* object) const { return dynamic_cast<osg::Image*>(object)!=0;  }
1389};
[3580]1390
[3596]1391struct Registry::ReadHeightFieldFunctor : public Registry::ReadFunctor
[3581]1392{
1393    ReadHeightFieldFunctor(const std::string& filename, const ReaderWriter::Options* options):ReadFunctor(filename,options) {}
[3580]1394
[3693]1395    virtual ReaderWriter::ReadResult doRead(ReaderWriter& rw) const { return rw.readHeightField(_filename, _options); }   
[3581]1396    virtual bool isValid(ReaderWriter::ReadResult& readResult) const { return readResult.validHeightField(); }
1397    virtual bool isValid(osg::Object* object) const { return dynamic_cast<osg::HeightField*>(object)!=0;  }
1398};
1399
[3596]1400struct Registry::ReadNodeFunctor : public Registry::ReadFunctor
[3581]1401{
1402    ReadNodeFunctor(const std::string& filename, const ReaderWriter::Options* options):ReadFunctor(filename,options) {}
1403
[3693]1404    virtual ReaderWriter::ReadResult doRead(ReaderWriter& rw) const { return rw.readNode(_filename, _options); }   
[3581]1405    virtual bool isValid(ReaderWriter::ReadResult& readResult) const { return readResult.validNode(); }
1406    virtual bool isValid(osg::Object* object) const { return dynamic_cast<osg::Node*>(object)!=0;  }
1407
1408};
1409
[3596]1410struct Registry::ReadArchiveFunctor : public Registry::ReadFunctor
[3581]1411{
1412    ReadArchiveFunctor(const std::string& filename, ReaderWriter::ArchiveStatus status, unsigned int indexBlockSizeHint, const ReaderWriter::Options* options):
1413        ReadFunctor(filename,options),
1414        _status(status),
1415        _indexBlockSizeHint(indexBlockSizeHint) {}
[3580]1416       
[3581]1417    ReaderWriter::ArchiveStatus _status;
1418    unsigned int _indexBlockSizeHint;
[3580]1419
[3693]1420    virtual ReaderWriter::ReadResult doRead(ReaderWriter& rw) const { return rw.openArchive(_filename, _status, _indexBlockSizeHint, _options); }
[3581]1421    virtual bool isValid(ReaderWriter::ReadResult& readResult) const { return readResult.validArchive(); }
1422    virtual bool isValid(osg::Object* object) const { return dynamic_cast<osgDB::Archive*>(object)!=0;  }
[3580]1423
[3581]1424};
[3580]1425
[7908]1426struct Registry::ReadShaderFunctor : public Registry::ReadFunctor
1427{
1428    ReadShaderFunctor(const std::string& filename, const ReaderWriter::Options* options):ReadFunctor(filename,options) {}
1429
1430    virtual ReaderWriter::ReadResult doRead(ReaderWriter& rw)const  { return rw.readShader(_filename, _options); }   
1431    virtual bool isValid(ReaderWriter::ReadResult& readResult) const { return readResult.validShader(); }
1432    virtual bool isValid(osg::Object* object) const { return dynamic_cast<osg::Shader*>(object)!=0;  }
1433};
1434
[6628]1435void Registry::addArchiveExtension(const std::string ext)
1436{
1437    for(ArchiveExtensionList::iterator aitr=_archiveExtList.begin();
1438        aitr!=_archiveExtList.end();
1439        ++aitr)
1440    {
1441        if ( (*aitr) == ext)   // extension already in archive extension list
1442            return;
1443    }
1444    _archiveExtList.push_back(ext);
[7375]1445}
[6628]1446
[3581]1447ReaderWriter::ReadResult Registry::read(const ReadFunctor& readFunctor)
[3580]1448{
[6628]1449    for(ArchiveExtensionList::iterator aitr=_archiveExtList.begin();
1450        aitr!=_archiveExtList.end();
1451        ++aitr)
1452    {
[7607]1453        std::string archiveExtension = "." + (*aitr);
[3580]1454
[7607]1455        std::string::size_type positionArchive = readFunctor._filename.find(archiveExtension+'/');
1456        if (positionArchive==std::string::npos) positionArchive = readFunctor._filename.find(archiveExtension+'\\');
[6628]1457        if (positionArchive!=std::string::npos)
1458        {
[7607]1459            std::string::size_type endArchive = positionArchive + archiveExtension.length();
1460            std::string archiveName( readFunctor._filename.substr(0,endArchive));
1461            std::string fileName(readFunctor._filename.substr(endArchive+1,std::string::npos));
[6628]1462            osg::notify(osg::INFO)<<"Contains archive : "<<readFunctor._filename<<std::endl;
1463            osg::notify(osg::INFO)<<"         archive : "<<archiveName<<std::endl;
1464            osg::notify(osg::INFO)<<"         filename : "<<fileName<<std::endl;
[3580]1465       
[6628]1466            ReaderWriter::ReadResult result = openArchiveImplementation(archiveName,ReaderWriter::READ, 4096, readFunctor._options);
[3598]1467       
[6628]1468            if (!result.validArchive()) return result;
[3580]1469
[6628]1470            osgDB::Archive* archive = result.getArchive();
[3580]1471       
[6628]1472            osg::ref_ptr<ReaderWriter::Options> options = new ReaderWriter::Options;
1473            options->setDatabasePath(archiveName);
[3580]1474
[6628]1475            return archive->readObject(fileName,options.get());
1476        }
[3580]1477    }
[9443]1478 
[146]1479    // record the errors reported by readerwriters.
1480    typedef std::vector<ReaderWriter::ReadResult> Results;
1481    Results results;
[8]1482
1483    // first attempt to load the file from existing ReaderWriter's
[8929]1484    AvailableReaderWriterIterator itr(_rwList, _pluginMutex);
[2522]1485    for(;itr.valid();++itr)
[8]1486    {
[3581]1487        ReaderWriter::ReadResult rr = readFunctor.doRead(*itr);
1488        if (readFunctor.isValid(rr)) return rr;
[2520]1489        else results.push_back(rr);
[8]1490    }
1491
[2520]1492    if (!results.empty())
1493    {
1494        unsigned int num_FILE_NOT_HANDLED = 0;
1495        unsigned int num_FILE_NOT_FOUND = 0;
1496        unsigned int num_ERROR_IN_READING_FILE = 0;
1497
[5397]1498        Results::iterator ritr;
1499        for(ritr=results.begin();
[2520]1500            ritr!=results.end();
1501            ++ritr)
1502        {
1503            if (ritr->status()==ReaderWriter::ReadResult::FILE_NOT_HANDLED) ++num_FILE_NOT_HANDLED;
1504            else if (ritr->status()==ReaderWriter::ReadResult::FILE_NOT_FOUND) ++num_FILE_NOT_FOUND;
1505            else if (ritr->status()==ReaderWriter::ReadResult::ERROR_IN_READING_FILE) ++num_ERROR_IN_READING_FILE;
1506        }
1507       
1508        if (num_FILE_NOT_HANDLED!=results.size())
1509        {
[5397]1510            for(ritr=results.begin(); ritr!=results.end(); ++ritr)
[2520]1511            {
[5397]1512                if (ritr->status()==ReaderWriter::ReadResult::ERROR_IN_READING_FILE)
1513                {
[7694]1514                    // osg::notify(osg::NOTICE)<<"Warning: error reading file \""<<readFunctor._filename<<"\""<<std::endl;
[5397]1515                    return *ritr;
1516                }
[2520]1517            }
[5397]1518
[9526]1519            //If the filename is a URL, don't return FILE_NOT_FOUND until the CURL plugin is given a chance
1520            if (!osgDB::containsServerAddress(readFunctor._filename))
[2520]1521            {
[9526]1522                for(ritr=results.begin(); ritr!=results.end(); ++ritr)
[5397]1523                {
[9526]1524                    if (ritr->status()==ReaderWriter::ReadResult::FILE_NOT_FOUND)
1525                    {
1526                        //osg::notify(osg::NOTICE)<<"Warning: could not find file \""<<readFunctor._filename<<"\""<<std::endl;
1527                        return *ritr;
1528                    }
[5397]1529                }
[2520]1530            }
1531        }
1532    }
1533
[5230]1534    results.clear();
1535
[8]1536    // now look for a plug-in to load the file.
[3581]1537    std::string libraryName = createLibraryNameForFile(readFunctor._filename);
[8947]1538    if (loadLibrary(libraryName)!=NOT_LOADED)
[8]1539    {
[2522]1540        for(;itr.valid();++itr)
[8]1541        {
[3581]1542            ReaderWriter::ReadResult rr = readFunctor.doRead(*itr);
1543            if (readFunctor.isValid(rr)) return rr;
[2522]1544            else results.push_back(rr);
[8]1545        }
1546    }
[9443]1547
1548    //If the filename contains a server address and wasn't loaded by any of the plugins, try to use the CURL plugin
1549    //to download the file and use the stream reading functionality of the plugins to load the file
1550    if (containsServerAddress(readFunctor._filename))
1551    {
1552        ReaderWriter* rw = getReaderWriterForExtension("curl");
1553        if (rw)
1554        {
1555            return readFunctor.doRead(*rw);
1556        }
1557        else
1558        {
1559            return  ReaderWriter::ReadResult("Warning: Could not find the .curl plugin to read from server.");
1560        }
1561    }
[146]1562   
[5230]1563    if (!results.empty())
[8]1564    {
[5230]1565        unsigned int num_FILE_NOT_HANDLED = 0;
1566        unsigned int num_FILE_NOT_FOUND = 0;
1567        unsigned int num_ERROR_IN_READING_FILE = 0;
1568
[5396]1569        Results::iterator ritr;
1570        for(ritr=results.begin();
[5230]1571            ritr!=results.end();
1572            ++ritr)
1573        {
1574            if (ritr->status()==ReaderWriter::ReadResult::FILE_NOT_HANDLED) ++num_FILE_NOT_HANDLED;
1575            else if (ritr->status()==ReaderWriter::ReadResult::FILE_NOT_FOUND) ++num_FILE_NOT_FOUND;
1576            else if (ritr->status()==ReaderWriter::ReadResult::ERROR_IN_READING_FILE) ++num_ERROR_IN_READING_FILE;
1577        }
1578       
1579        if (num_FILE_NOT_HANDLED!=results.size())
1580        {
[5396]1581            for(ritr=results.begin(); ritr!=results.end(); ++ritr)
[5230]1582            {
[5396]1583                if (ritr->status()==ReaderWriter::ReadResult::ERROR_IN_READING_FILE)
1584                {
[7694]1585                    // osg::notify(osg::NOTICE)<<"Warning: error reading file \""<<readFunctor._filename<<"\""<<std::endl;
[5396]1586                    return *ritr;
1587                }
[5230]1588            }
[5396]1589
1590            for(ritr=results.begin(); ritr!=results.end(); ++ritr)
[5230]1591            {
[5396]1592                if (ritr->status()==ReaderWriter::ReadResult::FILE_NOT_FOUND)
1593                {
[7694]1594                    // osg::notify(osg::NOTICE)<<"Warning: could not find file \""<<readFunctor._filename<<"\""<<std::endl;
[5396]1595                    return *ritr;
1596                }
[5230]1597            }
1598        }
1599    }
1600    else
1601    {
[3581]1602        return ReaderWriter::ReadResult("Warning: Could not find plugin to read objects from file \""+readFunctor._filename+"\".");
[8]1603    }
[371]1604
1605    return results.front();
[8]1606}
1607
[3598]1608ReaderWriter::ReadResult Registry::readImplementation(const ReadFunctor& readFunctor, bool useObjectCache)
[1708]1609{
[3581]1610    std::string file(readFunctor._filename);
[2877]1611
[3598]1612    if (useObjectCache)
[1708]1613    {
1614        // search for entry in the object cache.
1615        {
[3384]1616            OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_objectCacheMutex);
1617            ObjectCache::iterator oitr=_objectCache.find(file);
1618            if (oitr!=_objectCache.end())
1619            {
1620                notify(INFO)<<"returning cached instanced of "<<file<<std::endl;
[3581]1621                if (readFunctor.isValid(oitr->second.first.get())) return ReaderWriter::ReadResult(oitr->second.first.get(), ReaderWriter::ReadResult::FILE_LOADED_FROM_CACHE);
[3384]1622                else return ReaderWriter::ReadResult("Error file does not contain an osg::Object");
1623            }
[1708]1624        }
[3384]1625       
[3581]1626        ReaderWriter::ReadResult rr = read(readFunctor);
[1708]1627        if (rr.validObject())
1628        {
1629            // update cache with new entry.
[3581]1630            notify(INFO)<<"Adding to object cache "<<file<<std::endl;
[2335]1631            addEntryToObjectCache(file,rr.getObject());
[1708]1632        }
[3598]1633        else
1634        {
1635            notify(INFO)<<"No valid object found for "<<file<<std::endl;
1636        }
1637
[1708]1638        return rr;
1639
1640    }
1641    else
1642    {
1643        ObjectCache tmpObjectCache;
[3384]1644       
1645        {
1646            OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_objectCacheMutex);
1647            tmpObjectCache.swap(_objectCache);
1648        }
1649       
[3581]1650        ReaderWriter::ReadResult rr = read(readFunctor);
[1708]1651
[3384]1652        {
1653            OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_objectCacheMutex);
1654            tmpObjectCache.swap(_objectCache);
1655        }
1656       
[1708]1657        return rr;
1658    }
1659}
1660
[3581]1661
[3689]1662ReaderWriter::ReadResult Registry::openArchiveImplementation(const std::string& fileName, ReaderWriter::ArchiveStatus status, unsigned int indexBlockSizeHint, const ReaderWriter::Options* options)
[3581]1663{
[6636]1664    osgDB::Archive* archive = getFromArchiveCache(fileName);
1665    if (archive) return archive;
[3707]1666
[6636]1667    ReaderWriter::ReadResult result = readImplementation(ReadArchiveFunctor(fileName, status, indexBlockSizeHint, options),false);
1668
[7648]1669    // default to using caching archive if no options structure provided, but if options are provided use archives
[3707]1670    // only if supplied.
[6636]1671    if (result.validArchive() &&
1672        (!options || (options->getObjectCacheHint() & ReaderWriter::Options::CACHE_ARCHIVES)) )
[3598]1673    {
[6636]1674        addToArchiveCache(fileName,result.getArchive());
[3598]1675    }
[6636]1676    return result;
[3581]1677}
1678
1679
[3689]1680ReaderWriter::ReadResult Registry::readObjectImplementation(const std::string& fileName,const ReaderWriter::Options* options)
[3581]1681{
[3689]1682    return readImplementation(ReadObjectFunctor(fileName, options),
[3698]1683                              options ? (options->getObjectCacheHint()&ReaderWriter::Options::CACHE_OBJECTS)!=0: false);
[3581]1684}
1685
[7518]1686ReaderWriter::WriteResult Registry::writeObjectImplementation(const Object& obj,const std::string& fileName,const ReaderWriter::Options* options)
[8]1687{
[146]1688    // record the errors reported by readerwriters.
1689    typedef std::vector<ReaderWriter::WriteResult> Results;
1690    Results results;
1691
[8]1692    // first attempt to load the file from existing ReaderWriter's
[8929]1693    AvailableReaderWriterIterator itr(_rwList, _pluginMutex);
[2522]1694    for(;itr.valid();++itr)
[8]1695    {
[7518]1696        ReaderWriter::WriteResult rr = itr->writeObject(obj,fileName,options);
[147]1697        if (rr.success()) return rr;
[2520]1698        else results.push_back(rr);
[8]1699    }
1700
1701    // now look for a plug-in to save the file.
1702    std::string libraryName = createLibraryNameForFile(fileName);
[8947]1703    if (loadLibrary(libraryName)==LOADED)
[8]1704    {
[2522]1705        for(;itr.valid();++itr)
[8]1706        {
[7518]1707            ReaderWriter::WriteResult rr = itr->writeObject(obj,fileName,options);
[2522]1708            if (rr.success()) return rr;
1709            else results.push_back(rr);
[8]1710        }
1711    }
[146]1712
1713    if (results.empty())
[8]1714    {
[147]1715        return ReaderWriter::WriteResult("Warning: Could not find plugin to write objects to file \""+fileName+"\".");
[8]1716    }
[371]1717
[5697]1718    if (results.front().message().empty())
1719    {
1720        switch(results.front().status())
1721        {
1722            case(ReaderWriter::WriteResult::FILE_NOT_HANDLED): results.front().message() = "Warning: Write to \""+fileName+"\" not supported."; break;
1723            case(ReaderWriter::WriteResult::ERROR_IN_WRITING_FILE): results.front().message() = "Warning: Error in writing to \""+fileName+"\"."; break;
1724            default: break;
1725        }
1726    }
1727
[371]1728    return results.front();
[8]1729}
1730
[3477]1731
1732
[3689]1733ReaderWriter::ReadResult Registry::readImageImplementation(const std::string& fileName,const ReaderWriter::Options* options)
[1708]1734{
[3689]1735    return readImplementation(ReadImageFunctor(fileName, options),
[3698]1736                              options ? (options->getObjectCacheHint()&ReaderWriter::Options::CACHE_IMAGES)!=0: false);
[1708]1737}
1738
[7518]1739ReaderWriter::WriteResult Registry::writeImageImplementation(const Image& image,const std::string& fileName,const ReaderWriter::Options* options)
[8]1740{
[146]1741    // record the errors reported by readerwriters.
1742    typedef std::vector<ReaderWriter::WriteResult> Results;
1743    Results results;
1744
[8]1745    // first attempt to load the file from existing ReaderWriter's
[8929]1746    AvailableReaderWriterIterator itr(_rwList, _pluginMutex);
[2522]1747    for(;itr.valid();++itr)
[8]1748    {
[7518]1749        ReaderWriter::WriteResult rr = itr->writeImage(image,fileName,options);
[147]1750        if (rr.success()) return rr;
[2520]1751        else results.push_back(rr);
[8]1752    }
1753
[5697]1754    results.clear();
1755
[8]1756    // now look for a plug-in to save the file.
1757    std::string libraryName = createLibraryNameForFile(fileName);
[8947]1758    if (loadLibrary(libraryName)==LOADED)
[8]1759    {
[2522]1760        for(;itr.valid();++itr)
[8]1761        {
[7518]1762            ReaderWriter::WriteResult rr = itr->writeImage(image,fileName,options);
[2522]1763            if (rr.success()) return rr;
1764            else results.push_back(rr);
[8]1765        }
1766    }
[146]1767
1768    if (results.empty())
[8]1769    {
[147]1770        return ReaderWriter::WriteResult("Warning: Could not find plugin to write image to file \""+fileName+"\".");
[8]1771    }
[371]1772   
[5697]1773    if (results.front().message().empty())
1774    {
1775        switch(results.front().status())
1776        {
1777            case(ReaderWriter::WriteResult::FILE_NOT_HANDLED): results.front().message() = "Warning: Write to \""+fileName+"\" not supported."; break;
1778            case(ReaderWriter::WriteResult::ERROR_IN_WRITING_FILE): results.front().message() = "Warning: Error in writing to \""+fileName+"\"."; break;
1779            default: break;
1780        }
1781    }
1782
[371]1783    return results.front();
[8]1784}
1785
[3477]1786
[3689]1787ReaderWriter::ReadResult Registry::readHeightFieldImplementation(const std::string& fileName,const ReaderWriter::Options* options)
[2398]1788{
[3689]1789    return readImplementation(ReadHeightFieldFunctor(fileName, options),
[3698]1790                              options ? (options->getObjectCacheHint()&ReaderWriter::Options::CACHE_HEIGHTFIELDS)!=0: false);
[2398]1791}
1792
[7518]1793ReaderWriter::WriteResult Registry::writeHeightFieldImplementation(const HeightField& HeightField,const std::string& fileName,const ReaderWriter::Options* options)
[2398]1794{
1795    // record the errors reported by readerwriters.
1796    typedef std::vector<ReaderWriter::WriteResult> Results;
1797    Results results;
1798
1799    // first attempt to load the file from existing ReaderWriter's
[8929]1800    AvailableReaderWriterIterator itr(_rwList, _pluginMutex);
[2522]1801    for(;itr.valid();++itr)
[2398]1802    {
[7518]1803        ReaderWriter::WriteResult rr = itr->writeHeightField(HeightField,fileName,options);
[2398]1804        if (rr.success()) return rr;
[2520]1805        else results.push_back(rr);
[2398]1806    }
1807
[5697]1808    results.clear();
1809
[2398]1810    // now look for a plug-in to save the file.
1811    std::string libraryName = createLibraryNameForFile(fileName);
[8947]1812    if (loadLibrary(libraryName)==LOADED)
[2398]1813    {
[2522]1814        for(;itr.valid();++itr)
[2398]1815        {
[7518]1816            ReaderWriter::WriteResult rr = itr->writeHeightField(HeightField,fileName,options);
[2522]1817            if (rr.success()) return rr;
1818            else results.push_back(rr);
[2398]1819        }
1820    }
1821
1822    if (results.empty())
1823    {
1824        return ReaderWriter::WriteResult("Warning: Could not find plugin to write HeightField to file \""+fileName+"\".");
1825    }
[5697]1826
1827    if (results.front().message().empty())
1828    {
1829        switch(results.front().status())
1830        {
1831            case(ReaderWriter::WriteResult::FILE_NOT_HANDLED): results.front().message() = "Warning: Write to \""+fileName+"\" not supported."; break;
1832            case(ReaderWriter::WriteResult::ERROR_IN_WRITING_FILE): results.front().message() = "Warning: Error in writing to \""+fileName+"\"."; break;
1833            default: break;
1834        }
1835    }
[2398]1836   
1837    return results.front();
1838}
1839
1840
[3689]1841ReaderWriter::ReadResult Registry::readNodeImplementation(const std::string& fileName,const ReaderWriter::Options* options)
[8]1842{
[9024]1843#if 0
1844
1845    osg::Timer_t startTick = osg::Timer::instance()->tick();
1846    ReaderWriter::ReadResult result = readImplementation(ReadNodeFunctor(fileName, options),
1847                              options ? (options->getObjectCacheHint()&ReaderWriter::Options::CACHE_NODES)!=0: false);
1848    osg::Timer_t endTick = osg::Timer::instance()->tick();
1849    osg::notify(osg::NOTICE)<<"time to load "<<fileName<<" "<<osg::Timer::instance()->delta_m(startTick, endTick)<<"ms"<<std::endl;
1850    return result;
1851
1852#else
1853
[3689]1854    return readImplementation(ReadNodeFunctor(fileName, options),
[3698]1855                              options ? (options->getObjectCacheHint()&ReaderWriter::Options::CACHE_NODES)!=0: false);
[9024]1856                             
1857#endif
[8]1858}
1859
[7518]1860ReaderWriter::WriteResult Registry::writeNodeImplementation(const Node& node,const std::string& fileName,const ReaderWriter::Options* options)
[8]1861{
[146]1862    // record the errors reported by readerwriters.
1863    typedef std::vector<ReaderWriter::WriteResult> Results;
1864    Results results;
1865
[8]1866    // first attempt to write the file from existing ReaderWriter's
[8929]1867    AvailableReaderWriterIterator itr(_rwList, _pluginMutex);
[2522]1868    for(;itr.valid();++itr)
[8]1869    {
[7518]1870        ReaderWriter::WriteResult rr = itr->writeNode(node,fileName,options);
[147]1871        if (rr.success()) return rr;
[2520]1872        else results.push_back(rr);
[8]1873    }
1874
[5697]1875    results.clear();
1876
[8]1877    // now look for a plug-in to save the file.
1878    std::string libraryName = createLibraryNameForFile(fileName);
[5697]1879
1880
[8947]1881    if (loadLibrary(libraryName)==LOADED)
[8]1882    {
[2522]1883        for(;itr.valid();++itr)
[8]1884        {
[7518]1885            ReaderWriter::WriteResult rr = itr->writeNode(node,fileName,options);
[5697]1886   
[2522]1887            if (rr.success()) return rr;
1888            else results.push_back(rr);
[8]1889        }
1890    }
[146]1891
1892    if (results.empty())
[8]1893    {
[147]1894        return ReaderWriter::WriteResult("Warning: Could not find plugin to write nodes to file \""+fileName+"\".");
[8]1895    }
[371]1896
[5697]1897    if (results.front().message().empty())
1898    {
1899        switch(results.front().status())
1900        {
1901            case(ReaderWriter::WriteResult::FILE_NOT_HANDLED): results.front().message() = "Warning: Write to \""+fileName+"\" not supported."; break;
1902            case(ReaderWriter::WriteResult::ERROR_IN_WRITING_FILE): results.front().message() = "Warning: Error in writing to \""+fileName+"\"."; break;
1903            default: break;
1904        }
1905    }
1906
[371]1907    return results.front();
[8]1908}
[773]1909
[7908]1910ReaderWriter::ReadResult Registry::readShaderImplementation(const std::string& fileName,const ReaderWriter::Options* options)
1911{
1912    return readImplementation(ReadShaderFunctor(fileName, options),
1913                              options ? (options->getObjectCacheHint()&ReaderWriter::Options::CACHE_SHADERS)!=0: false);
1914}
[773]1915
[7908]1916ReaderWriter::WriteResult Registry::writeShaderImplementation(const Shader& shader,const std::string& fileName,const ReaderWriter::Options* options)
1917{
1918    // record the errors reported by readerwriters.
1919    typedef std::vector<ReaderWriter::WriteResult> Results;
1920    Results results;
1921
1922    // first attempt to load the file from existing ReaderWriter's
[8929]1923    AvailableReaderWriterIterator itr(_rwList, _pluginMutex);
[7908]1924    for(;itr.valid();++itr)
1925    {
1926        ReaderWriter::WriteResult rr = itr->writeShader(shader,fileName,options);
1927        if (rr.success()) return rr;
1928        else results.push_back(rr);
1929    }
1930
1931    results.clear();
1932
1933    // now look for a plug-in to save the file.
1934    std::string libraryName = createLibraryNameForFile(fileName);
[8947]1935    if (loadLibrary(libraryName)==LOADED)
[7908]1936    {
1937        for(;itr.valid();++itr)
1938        {
1939            ReaderWriter::WriteResult rr = itr->writeShader(shader,fileName,options);
1940            if (rr.success()) return rr;
1941            else results.push_back(rr);
1942        }
1943    }
1944
1945    if (results.empty())
1946    {
1947        return ReaderWriter::WriteResult("Warning: Could not find plugin to write shader to file \""+fileName+"\".");
1948    }
1949   
1950    if (results.front().message().empty())
1951    {
1952        switch(results.front().status())
1953        {
1954            case(ReaderWriter::WriteResult::FILE_NOT_HANDLED): results.front().message() = "Warning: Write to \""+fileName+"\" not supported."; break;
1955            case(ReaderWriter::WriteResult::ERROR_IN_WRITING_FILE): results.front().message() = "Warning: Error in writing to \""+fileName+"\"."; break;
1956            default: break;
1957        }
1958    }
1959
1960    return results.front();
1961}
1962
[2335]1963void Registry::addEntryToObjectCache(const std::string& filename, osg::Object* object, double timestamp)
1964{
[3384]1965    OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_objectCacheMutex);
1966    _objectCache[filename]=ObjectTimeStampPair(object,timestamp);
[2335]1967}
[3876]1968osg::Object* Registry::getFromObjectCache(const std::string& fileName)
1969{
1970    OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_objectCacheMutex);
1971    ObjectCache::iterator itr = _objectCache.find(fileName);
1972    if (itr!=_objectCache.end()) return itr->second.first.get();
1973    else return 0;
1974}
[2335]1975
[7038]1976void Registry::updateTimeStampOfObjectsInCacheWithExternalReferences(double currentTime)
[1708]1977{
[3384]1978    OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_objectCacheMutex);
[1708]1979
1980    // look for objects with external references and update their time stamp.
1981    for(ObjectCache::iterator itr=_objectCache.begin();
1982        itr!=_objectCache.end();
1983        ++itr)
1984    {
1985        // if ref count is greater the 1 the object has an external reference.
1986        if (itr->second.first->referenceCount()>1)
1987        {
1988            // so update it time stamp.
1989            itr->second.second = currentTime;
1990        }
1991    }
1992}
1993
1994void Registry::removeExpiredObjectsInCache(double expiryTime)
1995{
[3384]1996    OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_objectCacheMutex);
1997
[1708]1998    typedef std::vector<std::string> ObjectsToRemove;
1999    ObjectsToRemove objectsToRemove;
2000
[7648]2001    // first collect all the expired entries in the ObjectToRemove list.
[1708]2002    for(ObjectCache::iterator oitr=_objectCache.begin();
2003        oitr!=_objectCache.end();
2004        ++oitr)
2005    {
[2611]2006        if (oitr->second.second<=expiryTime)
[1708]2007        {
2008            // record the filename of the entry to use as key for deleting
2009            // afterwards/
2010            objectsToRemove.push_back(oitr->first);
2011        }
2012    }
2013   
2014    // remove the entries from the _objectCaache.
2015    for(ObjectsToRemove::iterator ritr=objectsToRemove.begin();
2016        ritr!=objectsToRemove.end();
2017        ++ritr)
2018    {
[2631]2019        // std::cout<<"Removing from Registry object cache '"<<*ritr<<"'"<<std::endl;
[1708]2020        _objectCache.erase(*ritr);
2021    }
2022       
2023}
2024
2025void Registry::clearObjectCache()
2026{
[3384]2027    OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_objectCacheMutex);
[1708]2028    _objectCache.clear();
2029}
[2614]2030
[3598]2031void Registry::addToArchiveCache(const std::string& fileName, osgDB::Archive* archive)
2032{
2033    OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_archiveCacheMutex);
2034    _archiveCache[fileName] = archive;
2035}
2036
2037/** Remove archive from cache.*/
2038void Registry::removeFromArchiveCache(const std::string& fileName)
2039{
2040    OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_archiveCacheMutex);
2041    ArchiveCache::iterator itr = _archiveCache.find(fileName);
2042    if (itr!=_archiveCache.end())
2043    {
2044        _archiveCache.erase(itr);
2045    }
2046}
2047
2048osgDB::Archive* Registry::getFromArchiveCache(const std::string& fileName)
2049{
2050    OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_archiveCacheMutex);
2051    ArchiveCache::iterator itr = _archiveCache.find(fileName);
2052    if (itr!=_archiveCache.end()) return itr->second.get();
2053    else return 0;
2054}
2055
2056void Registry::clearArchiveCache()
2057{
2058    OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_archiveCacheMutex);
2059    _archiveCache.clear();
2060}
2061
[4170]2062void Registry::releaseGLObjects(osg::State* state)
2063{
2064    OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_objectCacheMutex);
2065
2066    for(ObjectCache::iterator itr = _objectCache.begin();
2067        itr != _objectCache.end();
2068        ++itr)
2069    {
2070        osg::Object* object = itr->second.first.get();
2071        object->releaseGLObjects(state);
2072    }
2073}
2074
[2631]2075SharedStateManager* Registry::getOrCreateSharedStateManager()
2076{
2077    if (!_sharedStateManager) _sharedStateManager = new SharedStateManager;
2078   
2079    return _sharedStateManager.get();
2080}
Note: See TracBrowser for help on using the browser.