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

Revision 9880, 68.7 kB (checked in by robert, 5 years ago)

From Eric Wing and Stephan Huber, ImageIO code originally wrote by Eric Wing, and then later conveted into an OSG plugin by Stephan Huber.

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