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

Revision 3330, 55.0 kB (checked in by robert, 10 years ago)

Added a new osgDB::appendPlatformSpecificLibraryFilePaths() method to FileUtils?.cpp
Includes a new OSX code from Eric Wing

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2003 Robert Osfield
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*/
13
14#include <osg/Notify>
15#include <osg/Object>
16#include <osg/Image>
17#include <osg/Node>
18#include <osg/Group>
19#include <osg/Geode>
20#include <osg/ApplicationUsage>
21
22#include <osgDB/Registry>
23#include <osgDB/FileUtils>
24#include <osgDB/FileNameUtils>
25
26#include <stdio.h>
27
28#include <algorithm>
29#include <set>
30
31using namespace osg;
32using namespace osgDB;
33
34class AvailableReaderWriterIterator
35{
36public:
37    AvailableReaderWriterIterator(Registry::ReaderWriterList& rwList):
38        _rwList(rwList) {}
39
40
41    ReaderWriter& operator * () { return *get(); }
42    ReaderWriter* operator -> () { return get(); }
43   
44    bool valid() { return get()!=0; }
45   
46    void operator ++()
47    {
48        _rwUsed.insert(get());
49    }
50   
51
52protected:
53
54    Registry::ReaderWriterList&     _rwList;
55    std::set<ReaderWriter*>         _rwUsed;
56
57    ReaderWriter* get()
58    {
59        Registry::ReaderWriterList::iterator itr=_rwList.begin();
60        for(;itr!=_rwList.end();++itr)
61        {
62            if (_rwUsed.find(itr->get())==_rwUsed.end())
63            {
64                return itr->get();
65            }
66        }
67        return 0;
68    }
69
70};
71
72#if 0
73    // temporary test of autoregistering, not compiled by default.
74    enum Methods
75    {
76        SET_1,
77        SET_2,
78        END
79    };
80
81
82    typedef std::pair<Methods,std::string> MethodPair;
83
84    class Proxy
85    {
86    public:
87        Proxy(MethodPair* methods)
88        {
89            std::cout<<"methods "<<methods<<std::endl;
90            for(int i=0;methods[i].first!=END;++i)
91            {
92                std::cout<<"\t"<<methods[i].first<<"\t"<<methods[i].second<<std::endl;
93            }
94        }
95    };
96
97
98    static MethodPair methods[] =
99    {
100        MethodPair(SET_1,"SET_1"),
101        MethodPair(SET_2,"SET_2"),
102        MethodPair(END,"")
103    };
104
105    Proxy myproxy(methods);
106
107#endif
108
109void PrintFilePathList(std::ostream& stream,const FilePathList& filepath)
110{
111    for(FilePathList::const_iterator itr=filepath.begin();
112        itr!=filepath.end();
113        ++itr)
114    {
115        stream << "    "<< *itr<<std::endl;
116    }
117}
118
119Registry* Registry::instance(bool erase)
120{
121    static ref_ptr<Registry> s_nodeFactory = new Registry;
122    if (erase)
123    {
124        s_nodeFactory->closeAllLibraries();
125        s_nodeFactory = 0;
126    }
127    return s_nodeFactory.get(); // will return NULL on erase
128}
129
130
131// definition of the Registry
132Registry::Registry()
133{
134    // comment out because it was causing problems under OSX - causing it to crash osgconv when constucting ostream in osg::notify().
135    // notify(INFO) << "Constructing osg::Registry"<<std::endl;
136
137    _createNodeFromImage = false;
138    _openingLibrary = false;
139   
140    _useObjectCacheHint = CACHE_NONE;
141
142    initFilePathLists();
143
144    // register file extension alias.
145    addFileExtensionAlias("sgi""rgb");
146    addFileExtensionAlias("rgba", "rgb");
147    addFileExtensionAlias("int""rgb");
148    addFileExtensionAlias("inta", "rgb");
149    addFileExtensionAlias("bw",   "rgb");
150
151    addFileExtensionAlias("ivz",   "gz");
152    addFileExtensionAlias("ozg",   "gz");
153   
154#if defined(DARWIN_QUICKTIME)
155    addFileExtensionAlias("jpg""qt");
156    addFileExtensionAlias("jpe""qt");
157    addFileExtensionAlias("jpeg", "qt");
158    addFileExtensionAlias("tif""qt");
159    addFileExtensionAlias("tiff", "qt");
160    addFileExtensionAlias("gif""qt");
161    addFileExtensionAlias("png""qt");
162    addFileExtensionAlias("mov""qt");
163    addFileExtensionAlias("mpg""qt");
164    addFileExtensionAlias("mpv""qt");
165    addFileExtensionAlias("dv",   "qt");
166#else
167    addFileExtensionAlias("jpg""jpeg");
168    addFileExtensionAlias("jpe""jpeg");
169    addFileExtensionAlias("tif""tiff");
170    addFileExtensionAlias("mpg""mpeg");
171    addFileExtensionAlias("mpv""mpeg");
172#endif
173
174
175    // remove geo to lwo alias as the new Carbon Graphics GEO format
176    // also uses the .geo. It is still possible to load light wave .geo
177    // files via loading the lwo plugin explicitly and then doing a readNodeFile.
178    //addFileExtensionAlias("geo",  "lwo");
179    addFileExtensionAlias("lw",   "lwo");
180
181    addFileExtensionAlias("wrl",   "iv");
182   
183    // add alias for the text/freetype plugin.
184    addFileExtensionAlias("ttf",   "freetype");  // true type
185    addFileExtensionAlias("ttc",   "freetype");  // true type
186    addFileExtensionAlias("cid",   "freetype");  // Postscript CID-Fonts
187    addFileExtensionAlias("cff",   "freetype");  // OpenType
188    addFileExtensionAlias("cef",   "freetype");  // OpenType
189    addFileExtensionAlias("fon",   "freetype");  // Windows bitmap fonts
190    addFileExtensionAlias("fnt",   "freetype");    // Windows bitmap fonts
191   
192    // wont't add type1 and type2 until resolve extension collision with Peformer binary and ascii files.
193    // addFileExtensionAlias("pfb",   "freetype");  // type1 binary
194    // addFileExtensionAlias("pfa",   "freetype");  // type2 ascii
195
196
197    // portable bitmap, greyscale and colour/pixmap image formats
198    addFileExtensionAlias("pbm", "pnm");
199    addFileExtensionAlias("pgm", "pnm");
200    addFileExtensionAlias("ppm", "pnm");
201   
202}
203
204
205Registry::~Registry()
206{
207    // switch off the pager and its associated thread before we clean up
208    // rest of the Registry.
209    _databasePager = 0;
210
211    // clean up the SharedStateManager
212    _sharedStateManager = 0;
213   
214    // object cache clear needed here to prevent crash in unref() of
215    // the objects it contains when running the TXP plugin.
216    // Not sure why, but perhaps there is is something in a TXP plugin
217    // which is deleted the data before its ref count hits zero, perhaps
218    // even some issue with objects be allocated by a plugin that is
219    // mainted after that plugin is deleted...  Robert Osfield, Jan 2004.
220    _objectCache.clear();
221
222
223    // unload all the plugin before we finally destruct.
224    closeAllLibraries();
225}
226
227#ifndef WIN32
228static osg::ApplicationUsageProxy Registry_e0(osg::ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_FILE_PATH <path>[:path]..","Paths for locating datafiles");
229#else
230static osg::ApplicationUsageProxy Registry_e0(osg::ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_FILE_PATH <path>[;path]..","Paths for locating datafiles");
231#endif
232
233void Registry::initDataFilePathList()
234{
235    //
236    // set up data file paths
237    //
238    char *ptr;
239    if( (ptr = getenv( "OSG_FILE_PATH" )) )
240    {
241        //notify(DEBUG_INFO) << "OSG_FILE_PATH("<<ptr<<")"<<std::endl;
242        setDataFilePathList(ptr);
243    }
244    else if( (ptr = getenv( "OSGFILEPATH" )) )
245    {
246        //notify(DEBUG_INFO) << "OSGFILEPATH("<<ptr<<")"<<std::endl;
247        setDataFilePathList(ptr);
248    }
249
250    //osg::notify(INFO)<<"Data FilePathList"<<std::endl;
251    //PrintFilePathList(osg::notify(INFO),getDataFilePathList());
252}
253
254void Registry::setDataFilePathList(const std::string& paths)
255{
256    _dataFilePath.clear();
257    convertStringPathIntoFilePathList(paths,_dataFilePath);
258}
259
260void Registry::setLibraryFilePathList(const std::string& paths) { _libraryFilePath.clear(); convertStringPathIntoFilePathList(paths,_libraryFilePath); }
261
262#ifndef WIN32
263static osg::ApplicationUsageProxy Registry_e1(osg::ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_LIBRARY_PATH <path>[:path]..","Paths for locating libraries/ plugins");
264#else
265static osg::ApplicationUsageProxy Registry_e1(osg::ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_LIBRARY_PATH <path>[;path]..","Paths for locating libraries/ plugins");
266#endif
267
268
269void Registry::initLibraryFilePathList()
270{
271    //
272    // set up library paths
273    //
274    char* ptr;
275    if( (ptr = getenv( "OSG_LIBRARY_PATH")) )
276    {
277        //notify(DEBUG_INFO) << "OSG_LIBRARY_PATH("<<ptr<<")"<<std::endl;
278        setLibraryFilePathList(ptr);
279    }
280    else if( (ptr = getenv( "OSG_LD_LIBRARY_PATH")) )
281    {
282        //notify(DEBUG_INFO) << "OSG_LD_LIBRARY_PATH("<<ptr<<")"<<std::endl;
283        setLibraryFilePathList(ptr);
284    }
285   
286    appendPlatformSpecificLibraryFilePaths(_libraryFilePath);
287
288    //osg::notify(INFO)<<"Library FilePathList"<<std::endl;
289    //PrintFilePathList(osg::notify(INFO),getLibraryFilePathList());
290
291}
292
293
294void Registry::readCommandLine(osg::ArgumentParser& arguments)
295{
296    // report the usage options.
297    if (arguments.getApplicationUsage())
298    {
299        arguments.getApplicationUsage()->addCommandLineOption("-l <library>","Load the plugin");
300        arguments.getApplicationUsage()->addCommandLineOption("-e <extension>","Load the plugin associated with handling files with specified extension");
301        arguments.getApplicationUsage()->addCommandLineOption("-O <option_string>","Provide an option string to reader/writers used to load databases");
302    }
303
304    std::string value;
305    while(arguments.read("-l",value))
306    {
307        loadLibrary(value);
308    }
309       
310    while(arguments.read("-e",value))
311    {
312        std::string libName = createLibraryNameForExtension(value);
313        loadLibrary(libName);
314    }
315
316    while(arguments.read("-O",value))
317    {
318        setOptions(new osgDB::ReaderWriter::Options(value));
319    }
320}
321
322void Registry::addDotOsgWrapper(DotOsgWrapper* wrapper)
323{
324    if (wrapper==0L) return;
325
326    //notify(INFO) << "osg::Registry::addDotOsgWrapper("<<wrapper->getName()<<")"<< std::endl;
327    const DotOsgWrapper::Associates& assoc = wrapper->getAssociates();
328   
329    for(DotOsgWrapper::Associates::const_iterator itr=assoc.begin();
330                                                  itr!=assoc.end();
331                                                  ++itr)
332    {
333        //notify(INFO) << "    ("<<*itr<<")"<< std::endl;
334    }
335
336    const std::string& name = wrapper->getName();
337    const osg::Object* proto = wrapper->getPrototype();
338
339    _objectWrapperMap[name] = wrapper;
340    if (wrapper->getReadWriteMode()==DotOsgWrapper::READ_AND_WRITE) _classNameWrapperMap[name] = wrapper;
341   
342    if (proto)
343    {
344        std::string libraryName = proto->libraryName();
345        std::string compositeName = libraryName + "::" + name;
346
347        _objectWrapperMap[compositeName] = wrapper;
348        if (wrapper->getReadWriteMode()==DotOsgWrapper::READ_AND_WRITE) _classNameWrapperMap[compositeName] = wrapper;
349
350        if (dynamic_cast<const Image*>(proto))
351        {
352            _imageWrapperMap[name] = wrapper;
353            _imageWrapperMap[compositeName] = wrapper;
354        }
355        if (dynamic_cast<const Drawable*>(proto))
356        {
357              _drawableWrapperMap[name] = wrapper;
358              _drawableWrapperMap[compositeName] = wrapper;
359        }
360        if (dynamic_cast<const StateAttribute*>(proto))
361        {
362            _stateAttrWrapperMap[name] = wrapper;
363            _stateAttrWrapperMap[compositeName] = wrapper;
364        }
365        if (dynamic_cast<const Node*>(proto))
366        {
367            _nodeWrapperMap[name] = wrapper;
368            _nodeWrapperMap[compositeName] = wrapper;
369        }
370
371
372    }
373}
374
375// need to change to delete all instances of wrapper, since we
376// now can have a wrapper entered twice with the addition of the
377// library::class composite name.
378void Registry::eraseWrapper(DotOsgWrapperMap& wrappermap,DotOsgWrapper* wrapper)
379{
380    typedef std::vector<DotOsgWrapperMap::iterator> EraseList;
381    EraseList eraseList;
382    for(DotOsgWrapperMap::iterator witr=wrappermap.begin();
383        witr!=wrappermap.end();
384        ++witr)
385    {
386        if (witr->second==wrapper) eraseList.push_back(witr);
387    }
388    for(EraseList::iterator eitr=eraseList.begin();
389        eitr!=eraseList.end();
390        ++eitr)
391    {
392        wrappermap.erase(*eitr);
393    }
394}
395
396void Registry::removeDotOsgWrapper(DotOsgWrapper* wrapper)
397{
398    if (wrapper==0L) return;
399
400    eraseWrapper(_objectWrapperMap,wrapper);
401    eraseWrapper(_classNameWrapperMap,wrapper);
402    eraseWrapper(_imageWrapperMap,wrapper);
403    eraseWrapper(_drawableWrapperMap,wrapper);
404    eraseWrapper(_stateAttrWrapperMap,wrapper);
405    eraseWrapper(_nodeWrapperMap,wrapper);
406}
407
408void Registry::addReaderWriter(ReaderWriter* rw)
409{
410    if (rw==0L) return;
411
412    // notify(INFO) << "osg::Registry::addReaderWriter("<<rw->className()<<")"<< std::endl;
413
414    _rwList.push_back(rw);
415
416}
417
418
419void Registry::removeReaderWriter(ReaderWriter* rw)
420{
421    if (rw==0L) return;
422
423//    notify(INFO) << "osg::Registry::removeReaderWriter();"<< std::endl;
424
425    ReaderWriterList::iterator rwitr = std::find(_rwList.begin(),_rwList.end(),rw);
426    if (rwitr!=_rwList.end())
427    {
428        _rwList.erase(rwitr);
429    }
430
431}
432
433
434void Registry::addFileExtensionAlias(const std::string mapExt, const std::string toExt)
435{
436    if (mapExt!=toExt) _extAliasMap[mapExt] = toExt;
437}
438
439std::string Registry::createLibraryNameForFile(const std::string& fileName)
440{
441    std::string ext = getLowerCaseFileExtension(fileName);
442    return createLibraryNameForExtension(ext);
443}
444
445
446std::string Registry::createLibraryNameForExtension(const std::string& ext)
447{
448
449    ExtensionAliasMap::iterator itr=_extAliasMap.find(ext);
450    if (itr!=_extAliasMap.end()) return createLibraryNameForExtension(itr->second);
451
452#if defined(WIN32)
453    // !! recheck evolving Cygwin DLL extension naming protocols !! NHV
454    #ifdef __CYGWIN__
455        return "cygosgdb_"+ext+".dll";
456    #elif defined(__MINGW32__)
457        return "libosgdb_"+ext+".dll";
458    #else
459        #ifdef _DEBUG
460            return "osgdb_"+ext+"d.dll";
461        #else
462            return "osgdb_"+ext+".dll";
463        #endif
464    #endif
465#elif macintosh
466    return "osgdb_"+ext;
467#elif defined(__hpux__)
468    // why don't we use PLUGIN_EXT from the makefiles here?
469    return "osgdb_"+ext+".sl";
470#else
471    return "osgdb_"+ext+".so";
472#endif
473
474}
475
476std::string Registry::createLibraryNameForNodeKit(const std::string& name)
477{
478#if defined(WIN32)
479    // !! recheck evolving Cygwin DLL extension naming protocols !! NHV
480    #ifdef __CYGWIN__ // [
481    return "cyg"+name+".dll";
482    #elif defined(__MINGW32__)
483        return "lib"+name+".dll";
484    #else
485        #ifdef _DEBUG
486            return name+"d.dll";
487        #else
488            return name+".dll";
489        #endif
490    #endif
491#elif macintosh
492    return name;
493#elif defined(__hpux__)
494    // why don't we use PLUGIN_EXT from the makefiles here?
495    return "lib"+name+".sl";
496#else
497    return "lib"+name+".so";
498#endif
499}
500
501bool Registry::loadLibrary(const std::string& fileName)
502{
503    DynamicLibrary* dl = getLibrary(fileName);
504    if (dl) return false;
505
506    _openingLibrary=true;
507
508    dl = DynamicLibrary::loadLibrary(fileName);
509    _openingLibrary=false;
510
511    if (dl)
512    {
513        _dlList.push_back(dl);
514        return true;
515    }
516    return false;
517}
518
519
520bool Registry::closeLibrary(const std::string& fileName)
521{
522    DynamicLibraryList::iterator ditr = getLibraryItr(fileName);
523    if (ditr!=_dlList.end())
524    {
525        _dlList.erase(ditr);
526        return true;
527    }
528    return false;
529}
530
531void Registry::closeAllLibraries()
532{
533    _dlList.clear();
534}
535
536Registry::DynamicLibraryList::iterator Registry::getLibraryItr(const std::string& fileName)
537{
538    DynamicLibraryList::iterator ditr = _dlList.begin();
539    for(;ditr!=_dlList.end();++ditr)
540    {
541        if ((*ditr)->getName()==fileName) return ditr;
542    }
543    return _dlList.end();
544}
545
546DynamicLibrary* Registry::getLibrary(const std::string& fileName)
547{
548    DynamicLibraryList::iterator ditr = getLibraryItr(fileName);
549    if (ditr!=_dlList.end()) return ditr->get();
550    else return NULL;
551}
552
553ReaderWriter* Registry::getReaderWriterForExtension(const std::string& ext)
554{
555    // record the existing reader writer.
556    std::set<ReaderWriter*> rwOriginal;
557
558    // first attemt one of the installed loaders
559    for(ReaderWriterList::iterator itr=_rwList.begin();
560        itr!=_rwList.end();
561        ++itr)
562    {
563        rwOriginal.insert(itr->get());
564        if((*itr)->acceptsExtension(ext)) return (*itr).get();
565    }
566
567    // now look for a plug-in to load the file.
568    std::string libraryName = createLibraryNameForExtension(ext);
569    notify(INFO) << "Now checking for plug-in "<<libraryName<< std::endl;
570    if (loadLibrary(libraryName))
571    {
572        for(ReaderWriterList::iterator itr=_rwList.begin();
573            itr!=_rwList.end();
574            ++itr)
575        {
576            if (rwOriginal.find(itr->get())==rwOriginal.end())
577          if((*itr)->acceptsExtension(ext)) return (*itr).get();
578        }
579    }
580
581    return NULL;
582
583}
584
585struct concrete_wrapper: basic_type_wrapper
586{
587    concrete_wrapper(const osg::Object *myobj) : myobj_(myobj) {}
588    bool matches(const osg::Object *proto) const
589    {
590        return myobj_->isSameKindAs(proto);
591    }
592    const osg::Object *myobj_;
593};
594
595osg::Object* Registry::readObjectOfType(const osg::Object& compObj,Input& fr)
596{
597    return readObjectOfType(concrete_wrapper(&compObj), fr);
598}
599
600osg::Object* Registry::readObjectOfType(const basic_type_wrapper &btw,Input& fr)
601{
602    const char *str = fr[0].getStr();
603    if (str==NULL) return NULL;
604
605    if (fr[0].matchWord("Use"))
606    {
607        if (fr[1].isString())
608        {
609            Object* obj = fr.getObjectForUniqueID(fr[1].getStr());
610            if (obj && btw.matches(obj))
611            {
612                fr+=2;
613                return obj;
614            }
615        }
616        else return NULL;
617
618    }
619
620    std::string name = str;
621    DotOsgWrapperMap::iterator itr = _objectWrapperMap.find(name);
622    if (itr==_objectWrapperMap.end())
623    {
624        // not found so check if a library::class composite name.
625        std::string token = fr[0].getStr();
626        std::string::size_type posDoubleColon = token.rfind("::");
627        if (posDoubleColon != std::string::npos)
628        {
629            // we have a composite name so now strip off the library name
630            // are try to load it, and then retry the readObject to see
631            // if we can recongise the objects.
632       
633            std::string libraryName = std::string(token,0,posDoubleColon);
634
635            // first try the standard nodekit library.
636            std::string nodeKitLibraryName = createLibraryNameForNodeKit(libraryName);
637            if (loadLibrary(nodeKitLibraryName)) return readObjectOfType(btw,fr);
638           
639            // otherwise try the osgdb_ plugin library.
640            std::string pluginLibraryName = createLibraryNameForExtension(libraryName);
641            if (loadLibrary(pluginLibraryName)) return readObjectOfType(btw,fr);
642        }
643    }
644    else if (fr[1].isOpenBracket())
645    {
646   
647        DotOsgWrapper* wrapper = itr->second.get();
648        const osg::Object* proto = wrapper->getPrototype();
649        if (proto==NULL)
650        {
651            osg::notify(osg::WARN)<<"Token "<<fr[0].getStr()<<" read, but has no prototype, cannot load."<< std::endl;
652            return NULL;
653        }
654       
655        if (!btw.matches(proto))
656        {
657            return NULL;
658        }
659
660        // record the number of nested brackets move the input iterator
661        // over the name { tokens.
662        int entry = fr[0].getNoNestedBrackets();
663        fr+=2;
664
665        const DotOsgWrapper::Associates& assoc = wrapper->getAssociates();
666        osg::Object* obj = proto->cloneType();
667
668        while(!fr.eof() && fr[0].getNoNestedBrackets()>entry)
669        {
670            bool iteratorAdvanced = false;
671            if (fr[0].matchWord("UniqueID") && fr[1].isString())
672            {
673                fr.regisiterUniqueIDForObject(fr[1].getStr(),obj);
674                fr += 2;
675                iteratorAdvanced = true;
676            }
677
678            // read the local data by iterating through the associate
679            // list, mapping the associate names to DotOsgWrapper's which
680            // in turn have the appropriate functions.
681            for(DotOsgWrapper::Associates::const_iterator aitr=assoc.begin();
682                                                          aitr!=assoc.end();
683                                                          ++aitr)
684            {
685                DotOsgWrapperMap::iterator mitr = _objectWrapperMap.find(*aitr);
686                if (mitr==_objectWrapperMap.end())
687                {
688                    // not found so check if a library::class composite name.
689                    std::string token = *aitr;
690                    std::string::size_type posDoubleColon = token.rfind("::");
691                    if (posDoubleColon != std::string::npos)
692                    {
693
694                        // we have a composite name so now strip off the library name
695                        // are try to load it, and then retry the find to see
696                        // if we can recongise the objects.
697
698                        std::string libraryName = std::string(token,0,posDoubleColon);
699
700                        // first try the standard nodekit library.
701                        std::string nodeKitLibraryName = createLibraryNameForNodeKit(libraryName);
702                        if (loadLibrary(nodeKitLibraryName))
703                        {
704                            mitr = _objectWrapperMap.find(*aitr);
705                        }
706
707                        if (mitr==_objectWrapperMap.end())
708                        {
709                            // otherwise try the osgdb_ plugin library.
710                            std::string pluginLibraryName = createLibraryNameForExtension(libraryName);
711                            if (loadLibrary(pluginLibraryName))
712                            {
713                                mitr = _objectWrapperMap.find(*aitr);
714                            }
715                        }
716
717                    }
718                }
719
720                if (mitr!=_objectWrapperMap.end())
721                {
722                    // get the function to read the data...
723                    DotOsgWrapper::ReadFunc rf = mitr->second->getReadFunc();
724                    if (rf && (*rf)(*obj,fr)) iteratorAdvanced = true;
725                }
726
727            }
728
729            if (!iteratorAdvanced) fr.advanceOverCurrentFieldOrBlock();
730        }
731        ++fr;                        // step over trailing '}'
732       
733        return obj;
734       
735    }
736    return 0L;
737}
738
739//
740// read object from input iterator.
741//
742osg::Object* Registry::readObject(DotOsgWrapperMap& dowMap,Input& fr)
743{
744    const char *str = fr[0].getStr();
745    if (str==NULL) return NULL;
746
747    std::string name = str;
748    DotOsgWrapperMap::iterator itr = dowMap.find(name);
749    if (itr==dowMap.end())
750    {
751        // not found so check if a library::class composite name.
752        std::string token = fr[0].getStr();
753        std::string::size_type posDoubleColon = token.rfind("::");
754        if (posDoubleColon != std::string::npos)
755        {
756            // we have a composite name so now strip off the library name
757            // are try to load it, and then retry the readObject to see
758            // if we can recongise the objects.
759       
760            std::string libraryName = std::string(token,0,posDoubleColon);
761
762            // first try the standard nodekit library.
763            std::string nodeKitLibraryName = createLibraryNameForNodeKit(libraryName);
764            if (loadLibrary(nodeKitLibraryName)) return readObject(dowMap,fr);
765           
766            // otherwise try the osgdb_ plugin library.
767            std::string pluginLibraryName = createLibraryNameForExtension(libraryName);
768            if (loadLibrary(pluginLibraryName)) return readObject(dowMap,fr);
769        }
770    }
771    else if (fr[1].isOpenBracket())
772    {
773   
774        DotOsgWrapper* wrapper = itr->second.get();
775        const osg::Object* proto = wrapper->getPrototype();
776        if (proto==NULL)
777        {
778            osg::notify(osg::WARN)<<"Token "<<fr[0].getStr()<<" read, but has no prototype, cannot load."<< std::endl;
779            return NULL;
780        }
781
782        // record the number of nested brackets move the input iterator
783        // over the name { tokens.
784        int entry = fr[0].getNoNestedBrackets();
785        fr+=2;
786
787        const DotOsgWrapper::Associates& assoc = wrapper->getAssociates();
788        osg::Object* obj = proto->cloneType();
789
790        while(!fr.eof() && fr[0].getNoNestedBrackets()>entry)
791        {
792            bool iteratorAdvanced = false;
793            if (fr[0].matchWord("UniqueID") && fr[1].isString())
794            {
795                fr.regisiterUniqueIDForObject(fr[1].getStr(),obj);
796                fr += 2;
797                iteratorAdvanced = true;
798            }
799
800            // read the local data by iterating through the associate
801            // list, mapping the associate names to DotOsgWrapper's which
802            // in turn have the appropriate functions.
803            for(DotOsgWrapper::Associates::const_iterator aitr=assoc.begin();
804                                                          aitr!=assoc.end();
805                                                          ++aitr)
806            {
807                DotOsgWrapperMap::iterator mitr = _objectWrapperMap.find(*aitr);
808                if (mitr==_objectWrapperMap.end())
809                {
810                    // not found so check if a library::class composite name.
811                    std::string token = *aitr;
812                    std::string::size_type posDoubleColon = token.rfind("::");
813                    if (posDoubleColon != std::string::npos)
814                    {
815
816                        // we have a composite name so now strip off the library name
817                        // are try to load it, and then retry the find to see
818                        // if we can recongise the objects.
819
820                        std::string libraryName = std::string(token,0,posDoubleColon);
821
822                        // first try the standard nodekit library.
823                        std::string nodeKitLibraryName = createLibraryNameForNodeKit(libraryName);
824                        if (loadLibrary(nodeKitLibraryName))
825                        {
826                            mitr = _objectWrapperMap.find(*aitr);
827                        }
828
829                        if (mitr==_objectWrapperMap.end())
830                        {
831                            // otherwise try the osgdb_ plugin library.
832                            std::string pluginLibraryName = createLibraryNameForExtension(libraryName);
833                            if (loadLibrary(pluginLibraryName))
834                            {
835                                mitr = _objectWrapperMap.find(*aitr);
836                            }
837                        }
838
839                    }
840                }
841
842                if (mitr!=_objectWrapperMap.end())
843                {
844                    // get the function to read the data...
845                    DotOsgWrapper::ReadFunc rf = mitr->second->getReadFunc();
846                    if (rf && (*rf)(*obj,fr)) iteratorAdvanced = true;
847                }
848
849            }
850
851            if (!iteratorAdvanced) fr.advanceOverCurrentFieldOrBlock();
852        }
853        ++fr;                        // step over trailing '}'
854       
855        return obj;
856       
857    }
858
859    return 0L;
860}
861
862//
863// read object from input iterator.
864//
865Object* Registry::readObject(Input& fr)
866{
867    if (fr[0].matchWord("Use"))
868    {
869        if (fr[1].isString())
870        {
871            Object* obj = fr.getObjectForUniqueID(fr[1].getStr());
872            if (obj) fr+=2;
873            return obj;
874        }
875        else return NULL;
876
877    }
878
879    return readObject(_objectWrapperMap,fr);
880}
881
882
883//
884// read image from input iterator.
885//
886Image* Registry::readImage(Input& fr)
887{
888    if (fr[0].matchWord("Use"))
889    {
890        if (fr[1].isString())
891        {
892            Image* image = dynamic_cast<Image*>(fr.getObjectForUniqueID(fr[1].getStr()));
893            if (image) fr+=2;
894            return image;
895        }
896        else return NULL;
897
898    }
899
900    osg::Object* obj = readObject(_imageWrapperMap,fr);
901    osg::Image* image = dynamic_cast<Image*>(obj);
902    if (image) return image;
903    else if (obj) obj->unref();
904   
905    return NULL;
906}
907
908
909//
910// read drawable from input iterator.
911//
912Drawable* Registry::readDrawable(Input& fr)
913{
914    if (fr[0].matchWord("Use"))
915    {
916        if (fr[1].isString())
917        {
918            Drawable* drawable = dynamic_cast<Drawable*>(fr.getObjectForUniqueID(fr[1].getStr()));
919            if (drawable) fr+=2;
920            return drawable;
921        }
922        else return NULL;
923
924    }
925
926    osg::Object* obj = readObject(_drawableWrapperMap,fr);
927    osg::Drawable* drawable = dynamic_cast<Drawable*>(obj);
928    if (drawable) return drawable;
929    else if (obj) obj->unref();
930   
931    return NULL;
932}
933
934//
935// read drawable from input iterator.
936//
937StateAttribute* Registry::readStateAttribute(Input& fr)
938{
939
940    if (fr[0].matchWord("Use"))
941    {
942        if (fr[1].isString())
943        {
944            StateAttribute* attribute = dynamic_cast<StateAttribute*>(fr.getObjectForUniqueID(fr[1].getStr()));
945            if (attribute) fr+=2;
946            return attribute;
947        }
948        else return NULL;
949
950    }
951
952    return dynamic_cast<StateAttribute*>(readObject(_stateAttrWrapperMap,fr));
953}
954
955//
956// read node from input iterator.
957//
958Node* Registry::readNode(Input& fr)
959{
960    if (fr[0].matchWord("Use"))
961    {
962        if (fr[1].isString())
963        {
964            Node* node = dynamic_cast<Node*>(fr.getObjectForUniqueID(fr[1].getStr()));
965            if (node) fr+=2;
966            return node;
967        }
968        else return NULL;
969
970    }
971
972    osg::Object* obj = readObject(_nodeWrapperMap,fr);
973    osg::Node* node = dynamic_cast<Node*>(obj);
974    if (node) return node;
975    else if (obj) obj->unref();
976   
977    return NULL;
978}
979
980//
981// Write object to output
982//
983bool Registry::writeObject(const osg::Object& obj,Output& fw)
984{
985
986    if (obj.referenceCount()>1)
987    {
988        std::string uniqueID;
989        if (fw.getUniqueIDForObject(&obj,uniqueID))
990        {
991            fw.indent() << "Use " << uniqueID << std::endl;
992            return true;
993        }
994    }
995
996    std::string classname = obj.className();
997    std::string libraryName = obj.libraryName();
998    std::string compositeName = libraryName + "::" + classname;
999
1000    // try composite name first
1001    DotOsgWrapperMap::iterator itr = _classNameWrapperMap.find(compositeName);
1002
1003    // composite name not found, try simple class name
1004    if (itr == _classNameWrapperMap.end()) {
1005        itr = _classNameWrapperMap.find(classname);
1006    }
1007
1008    if (itr==_classNameWrapperMap.end())
1009    {
1010        // first try the standard nodekit library.
1011        std::string nodeKitLibraryName = createLibraryNameForNodeKit(obj.libraryName());
1012        if (loadLibrary(nodeKitLibraryName)) return writeObject(obj,fw);
1013
1014        // otherwise try the osgdb_ plugin library.
1015        std::string pluginLibraryName = createLibraryNameForExtension(obj.libraryName());
1016        if (loadLibrary(pluginLibraryName)) return writeObject(obj,fw);
1017    }
1018    else
1019    {
1020   
1021   
1022        DotOsgWrapper* wrapper = itr->second.get();
1023        const DotOsgWrapper::Associates& assoc = wrapper->getAssociates();
1024
1025        if (strcmp(obj.libraryName(),"osg")==0)
1026        {
1027            // member of the core osg, so no need to have composite library::class name.
1028            fw.indent() << wrapper->getName() << " {"<< std::endl;
1029            fw.moveIn();
1030        }
1031        else
1032        {
1033            // member of the node kit so must use composite library::class name.
1034            std::string::size_type posDoubleColon = wrapper->getName().find("::");
1035            if (posDoubleColon != std::string::npos)
1036            {
1037                fw.indent() << wrapper->getName() << " {"<< std::endl;
1038            }
1039            else
1040            {
1041                fw.indent() << obj.libraryName()<<"::"<< wrapper->getName() << " {"<< std::endl;
1042            }
1043
1044            fw.moveIn();
1045        }
1046
1047
1048        // write out the unique ID if required.
1049        if (obj.referenceCount()>1)
1050        {
1051            std::string uniqueID;
1052            fw.createUniqueIDForObject(&obj,uniqueID);
1053            fw.registerUniqueIDForObject(&obj,uniqueID);
1054            fw.indent() << "UniqueID " << uniqueID << std::endl;
1055        }
1056
1057        // read the local data by iterating through the associate
1058        // list, mapping the associate names to DotOsgWrapper's which
1059        // in turn have the appropriate functions.
1060        for(DotOsgWrapper::Associates::const_iterator aitr=assoc.begin();
1061                                                      aitr!=assoc.end();
1062                                                      ++aitr)
1063        {
1064            DotOsgWrapperMap::iterator mitr = _objectWrapperMap.find(*aitr);
1065            if (mitr==_objectWrapperMap.end())
1066            {
1067                // not found so check if a library::class composite name.
1068                std::string token = *aitr;
1069                std::string::size_type posDoubleColon = token.rfind("::");
1070                if (posDoubleColon != std::string::npos)
1071                {
1072
1073                    // we have a composite name so now strip off the library name
1074                    // are try to load it, and then retry the find to see
1075                    // if we can recongise the objects.
1076
1077                    std::string libraryName = std::string(token,0,posDoubleColon);
1078
1079                    // first try the standard nodekit library.
1080                    std::string nodeKitLibraryName = createLibraryNameForNodeKit(libraryName);
1081                    if (loadLibrary(nodeKitLibraryName))
1082                    {
1083                        mitr = _objectWrapperMap.find(*aitr);
1084                    }
1085
1086                    if (mitr==_objectWrapperMap.end())
1087                    {
1088                        // otherwise try the osgdb_ plugin library.
1089                        std::string pluginLibraryName = createLibraryNameForExtension(libraryName);
1090                        if (loadLibrary(pluginLibraryName))
1091                        {
1092                            mitr = _objectWrapperMap.find(*aitr);
1093                        }
1094                    }
1095
1096                }
1097            }
1098            if (mitr!=_objectWrapperMap.end())
1099            {
1100                // get the function to read the data...
1101                DotOsgWrapper::WriteFunc wf = mitr->second->getWriteFunc();
1102                if (wf) (*wf)(obj,fw);
1103            }
1104
1105        }
1106
1107        fw.moveOut();
1108        fw.indent() << "}"<< std::endl;
1109
1110        return true;
1111    }
1112   
1113    return false;
1114}
1115
1116//
1117// read object from specified file.
1118//
1119ReaderWriter::ReadResult Registry::readObject(const std::string& fileName)
1120{
1121    // record the errors reported by readerwriters.
1122    typedef std::vector<ReaderWriter::ReadResult> Results;
1123    Results results;
1124
1125    // first attempt to load the file from existing ReaderWriter's
1126    AvailableReaderWriterIterator itr(_rwList);
1127    for(;itr.valid();++itr)
1128    {
1129        ReaderWriter::ReadResult rr = itr->readObject(fileName,_options.get());
1130        if (rr.validObject()) return rr;
1131        else results.push_back(rr);
1132    }
1133
1134    if (!results.empty())
1135    {
1136        unsigned int num_FILE_NOT_HANDLED = 0;
1137        unsigned int num_FILE_NOT_FOUND = 0;
1138        unsigned int num_ERROR_IN_READING_FILE = 0;
1139
1140        for(Results::iterator ritr=results.begin();
1141            ritr!=results.end();
1142            ++ritr)
1143        {
1144            if (ritr->status()==ReaderWriter::ReadResult::FILE_NOT_HANDLED) ++num_FILE_NOT_HANDLED;
1145            else if (ritr->status()==ReaderWriter::ReadResult::FILE_NOT_FOUND) ++num_FILE_NOT_FOUND;
1146            else if (ritr->status()==ReaderWriter::ReadResult::ERROR_IN_READING_FILE) ++num_ERROR_IN_READING_FILE;
1147        }
1148       
1149        if (num_FILE_NOT_HANDLED!=results.size())
1150        {
1151            // we've come across a file not found or error in reading file.
1152            if (num_ERROR_IN_READING_FILE)
1153            {
1154                osg::notify(osg::NOTICE)<<"Warning: error reading file \""<<fileName<<"\""<<std::endl;
1155                return NULL;
1156            }
1157            else if (num_FILE_NOT_FOUND)
1158            {
1159                osg::notify(osg::NOTICE)<<"Warning: could not find file \""<<fileName<<"\""<<std::endl;
1160                return NULL;
1161            }
1162        }
1163    }
1164
1165    // now look for a plug-in to load the file.
1166    std::string libraryName = createLibraryNameForFile(fileName);
1167    if (loadLibrary(libraryName))
1168    {
1169        for(;itr.valid();++itr)
1170        {
1171            ReaderWriter::ReadResult rr = itr->readObject(fileName,_options.get());
1172            if (rr.validObject()) return rr;
1173            else results.push_back(rr);
1174        }
1175    }
1176   
1177    if (results.empty())
1178    {
1179        return ReaderWriter::ReadResult("Warning: Could not find plugin to read objects from file \""+fileName+"\".");
1180    }
1181   
1182
1183    return results.front();
1184}
1185
1186ReaderWriter::ReadResult Registry::readObjectImplementation(const std::string& constFile,CacheHintOptions useObjectCache)
1187{
1188    std::string file(constFile);
1189
1190    if (useObjectCache & CACHE_OBJECTS)
1191    {
1192        // search for entry in the object cache.
1193        ObjectCache::iterator oitr=_objectCache.find(file);
1194        if (oitr!=_objectCache.end())
1195        {
1196            notify(INFO)<<"returning cached instanced of "<<file<<std::endl;
1197            osg::Object* object = oitr->second.first.get();
1198            if (object) return ReaderWriter::ReadResult(object, ReaderWriter::ReadResult::FILE_LOADED_FROM_CACHE);
1199            else return ReaderWriter::ReadResult("Error file does not contain an osg::Object");
1200        }
1201
1202        PushAndPopDataPath tmpfile(getFilePath(file));
1203
1204        ReaderWriter::ReadResult rr = readObject(file);
1205        if (rr.validObject())
1206        {
1207            // update cache with new entry.
1208            notify(INFO)<<"Adding to cache object "<<file<<std::endl;
1209            addEntryToObjectCache(file,rr.getObject());
1210        }
1211       
1212        return rr;
1213
1214    }
1215    else
1216    {
1217   
1218        ObjectCache tmpObjectCache;
1219        tmpObjectCache.swap(_objectCache);
1220
1221        PushAndPopDataPath tmpfile(getFilePath(file));
1222
1223        ReaderWriter::ReadResult rr = readObject(file);
1224
1225        tmpObjectCache.swap(_objectCache);
1226
1227        return rr;
1228
1229    }
1230}
1231
1232ReaderWriter::WriteResult Registry::writeObjectImplementation(const Object& obj,const std::string& fileName)
1233{
1234    // record the errors reported by readerwriters.
1235    typedef std::vector<ReaderWriter::WriteResult> Results;
1236    Results results;
1237
1238    // first attempt to load the file from existing ReaderWriter's
1239    AvailableReaderWriterIterator itr(_rwList);
1240    for(;itr.valid();++itr)
1241    {
1242        ReaderWriter::WriteResult rr = itr->writeObject(obj,fileName,_options.get());
1243        if (rr.success()) return rr;
1244        else results.push_back(rr);
1245    }
1246
1247    // now look for a plug-in to save the file.
1248    std::string libraryName = createLibraryNameForFile(fileName);
1249    if (loadLibrary(libraryName))
1250    {
1251        for(;itr.valid();++itr)
1252        {
1253            ReaderWriter::WriteResult rr = itr->writeObject(obj,fileName,_options.get());
1254            if (rr.success()) return rr;
1255            else results.push_back(rr);
1256        }
1257    }
1258
1259    if (results.empty())
1260    {
1261        return ReaderWriter::WriteResult("Warning: Could not find plugin to write objects to file \""+fileName+"\".");
1262    }
1263
1264    return results.front();
1265}
1266
1267ReaderWriter::ReadResult Registry::readImage(const std::string& fileName)
1268{
1269    // record the errors reported by readerwriters.
1270    typedef std::vector<ReaderWriter::ReadResult> Results;
1271    Results results;
1272
1273    // first attempt to load the file from existing ReaderWriter's
1274    AvailableReaderWriterIterator itr(_rwList);
1275    for(;itr.valid();++itr)
1276    {
1277        ReaderWriter::ReadResult rr = itr->readImage(fileName,_options.get());
1278        if (rr.validImage())  return rr;
1279        else results.push_back(rr);
1280    }
1281
1282    if (!results.empty())
1283    {
1284        unsigned int num_FILE_NOT_HANDLED = 0;
1285        unsigned int num_FILE_NOT_FOUND = 0;
1286        unsigned int num_ERROR_IN_READING_FILE = 0;
1287
1288        for(Results::iterator ritr=results.begin();
1289            ritr!=results.end();
1290            ++ritr)
1291        {
1292            if (ritr->status()==ReaderWriter::ReadResult::FILE_NOT_HANDLED) ++num_FILE_NOT_HANDLED;
1293            else if (ritr->status()==ReaderWriter::ReadResult::FILE_NOT_FOUND) ++num_FILE_NOT_FOUND;
1294            else if (ritr->status()==ReaderWriter::ReadResult::ERROR_IN_READING_FILE) ++num_ERROR_IN_READING_FILE;
1295        }
1296       
1297        if (num_FILE_NOT_HANDLED!=results.size())
1298        {
1299            // we've come across a file not found or error in reading file.
1300            if (num_ERROR_IN_READING_FILE)
1301            {
1302                osg::notify(osg::NOTICE)<<"Warning: error reading file \""<<fileName<<"\""<<std::endl;
1303                return NULL;
1304            }
1305            else if (num_FILE_NOT_FOUND)
1306            {
1307                osg::notify(osg::NOTICE)<<"Warning: could not find file \""<<fileName<<"\""<<std::endl;
1308                return NULL;
1309            }
1310        }
1311    }
1312
1313    // now look for a plug-in to load the file.
1314    std::string libraryName = createLibraryNameForFile(fileName);
1315    if (loadLibrary(libraryName))
1316    {
1317        for(;itr.valid();++itr)
1318        {
1319            ReaderWriter::ReadResult rr = itr->readImage(fileName,_options.get());
1320            if (rr.validImage()) return rr;
1321            else results.push_back(rr);
1322        }
1323    }
1324
1325    if (results.empty())
1326    {
1327        return ReaderWriter::ReadResult("Warning: Could not find plugin to read image from file \""+fileName+"\".");
1328    }
1329
1330    return results.front();
1331}
1332
1333
1334ReaderWriter::ReadResult Registry::readImageImplementation(const std::string& file,CacheHintOptions useObjectCache)
1335{
1336    if (useObjectCache & CACHE_IMAGES)
1337    {
1338        // search for entry in the object cache.
1339        ObjectCache::iterator oitr=_objectCache.find(file);
1340        if (oitr!=_objectCache.end())
1341        {
1342            notify(INFO)<< "returning cached instanced of "<<file<<std::endl;
1343            osg::Image* image = dynamic_cast<osg::Image*>(oitr->second.first.get());
1344            if (image) return ReaderWriter::ReadResult(image, ReaderWriter::ReadResult::FILE_LOADED_FROM_CACHE);
1345            else return ReaderWriter::ReadResult("Error file not of type osg::Image");
1346        }
1347
1348        PushAndPopDataPath tmpfile(getFilePath(file));
1349
1350        ReaderWriter::ReadResult rr = readImage(file);
1351        if (rr.validImage())
1352        {
1353            // update cache with new entry.
1354            notify(INFO)<<"Adding to cache image "<<file<<std::endl;
1355            addEntryToObjectCache(file,rr.getObject());
1356        }
1357        else
1358            return ReaderWriter::ReadResult("Warning: file \""+file+"\" not found.");
1359       
1360        return rr;
1361
1362    }
1363    else
1364    {
1365   
1366        ObjectCache tmpObjectCache;
1367        tmpObjectCache.swap(_objectCache);
1368
1369        PushAndPopDataPath tmpfile(getFilePath(file));
1370
1371        ReaderWriter::ReadResult rr = readImage(file);
1372
1373        tmpObjectCache.swap(_objectCache);
1374
1375        return rr;
1376
1377    }
1378}
1379
1380
1381
1382ReaderWriter::WriteResult Registry::writeImageImplementation(const Image& image,const std::string& fileName)
1383{
1384    // record the errors reported by readerwriters.
1385    typedef std::vector<ReaderWriter::WriteResult> Results;
1386    Results results;
1387
1388    // first attempt to load the file from existing ReaderWriter's
1389    AvailableReaderWriterIterator itr(_rwList);
1390    for(;itr.valid();++itr)
1391    {
1392        ReaderWriter::WriteResult rr = itr->writeImage(image,fileName,_options.get());
1393        if (rr.success()) return rr;
1394        else results.push_back(rr);
1395    }
1396
1397    // now look for a plug-in to save the file.
1398    std::string libraryName = createLibraryNameForFile(fileName);
1399    if (loadLibrary(libraryName))
1400    {
1401        for(;itr.valid();++itr)
1402        {
1403            ReaderWriter::WriteResult rr = itr->writeImage(image,fileName,_options.get());
1404            if (rr.success()) return rr;
1405            else results.push_back(rr);
1406        }
1407    }
1408
1409    if (results.empty())
1410    {
1411        return ReaderWriter::WriteResult("Warning: Could not find plugin to write image to file \""+fileName+"\".");
1412    }
1413   
1414    return results.front();
1415}
1416
1417ReaderWriter::ReadResult Registry::readHeightField(const std::string& fileName)
1418{
1419    // record the errors reported by readerwriters.
1420    typedef std::vector<ReaderWriter::ReadResult> Results;
1421    Results results;
1422
1423    // first attempt to load the file from existing ReaderWriter's
1424    AvailableReaderWriterIterator itr(_rwList);
1425    for(;itr.valid();++itr)
1426    {
1427        ReaderWriter::ReadResult rr = itr->readHeightField(fileName,_options.get());
1428        if (rr.validHeightField())  return rr;
1429        else results.push_back(rr);
1430    }
1431
1432    if (!results.empty())
1433    {
1434        unsigned int num_FILE_NOT_HANDLED = 0;
1435        unsigned int num_FILE_NOT_FOUND = 0;
1436        unsigned int num_ERROR_IN_READING_FILE = 0;
1437
1438        for(Results::iterator ritr=results.begin();
1439            ritr!=results.end();
1440            ++ritr)
1441        {
1442            if (ritr->status()==ReaderWriter::ReadResult::FILE_NOT_HANDLED) ++num_FILE_NOT_HANDLED;
1443            else if (ritr->status()==ReaderWriter::ReadResult::FILE_NOT_FOUND) ++num_FILE_NOT_FOUND;
1444            else if (ritr->status()==ReaderWriter::ReadResult::ERROR_IN_READING_FILE) ++num_ERROR_IN_READING_FILE;
1445        }
1446       
1447        if (num_FILE_NOT_HANDLED!=results.size())
1448        {
1449            // we've come across a file not found or error in reading file.
1450            if (num_ERROR_IN_READING_FILE)
1451            {
1452                osg::notify(osg::NOTICE)<<"Warning: error reading file \""<<fileName<<"\""<<std::endl;
1453                return NULL;
1454            }
1455            else if (num_FILE_NOT_FOUND)
1456            {
1457                osg::notify(osg::NOTICE)<<"Warning: could not find file \""<<fileName<<"\""<<std::endl;
1458                return NULL;
1459            }
1460        }
1461    }
1462
1463    // now look for a plug-in to load the file.
1464    std::string libraryName = createLibraryNameForFile(fileName);
1465    if (loadLibrary(libraryName))
1466    {
1467        for(;itr.valid();++itr)
1468        {
1469            ReaderWriter::ReadResult rr = itr->readHeightField(fileName,_options.get());
1470            if (rr.validHeightField()) return rr;
1471            else  results.push_back(rr);
1472        }
1473    }
1474
1475    if (results.empty())
1476    {
1477        return ReaderWriter::ReadResult("Warning: Could not find plugin to read HeightField from file \""+fileName+"\".");
1478    }
1479
1480    return results.front();
1481}
1482
1483
1484ReaderWriter::ReadResult Registry::readHeightFieldImplementation(const std::string& file,CacheHintOptions useObjectCache)
1485{
1486    if (useObjectCache & CACHE_HEIGHTFIELDS)
1487    {
1488        // search for entry in the object cache.
1489        ObjectCache::iterator oitr=_objectCache.find(file);
1490        if (oitr!=_objectCache.end())
1491        {
1492            notify(INFO)<< "returning cached instanced of "<<file<<std::endl;
1493            osg::HeightField* heightField = dynamic_cast<osg::HeightField*>(oitr->second.first.get());
1494            if (heightField) return ReaderWriter::ReadResult(heightField, ReaderWriter::ReadResult::FILE_LOADED_FROM_CACHE);
1495            else return ReaderWriter::ReadResult("Error file not of type osg::HeightField");
1496        }
1497
1498        PushAndPopDataPath tmpfile(getFilePath(file));
1499
1500        ReaderWriter::ReadResult rr = readHeightField(file);
1501        if (rr.validHeightField())
1502        {
1503            // update cache with new entry.
1504            notify(INFO)<<"Adding to cache HeightField "<<file<<std::endl;
1505            addEntryToObjectCache(file,rr.getObject());
1506        }
1507        else
1508            return ReaderWriter::ReadResult("Warning: file \""+file+"\" not found.");
1509       
1510        return rr;
1511
1512    }
1513    else
1514    {
1515   
1516        ObjectCache tmpObjectCache;
1517        tmpObjectCache.swap(_objectCache);
1518
1519        PushAndPopDataPath tmpfile(getFilePath(file));
1520
1521        ReaderWriter::ReadResult rr = readHeightField(file);
1522
1523        tmpObjectCache.swap(_objectCache);
1524
1525        return rr;
1526
1527    }
1528}
1529
1530
1531
1532ReaderWriter::WriteResult Registry::writeHeightFieldImplementation(const HeightField& HeightField,const std::string& fileName)
1533{
1534    // record the errors reported by readerwriters.
1535    typedef std::vector<ReaderWriter::WriteResult> Results;
1536    Results results;
1537
1538    // first attempt to load the file from existing ReaderWriter's
1539    AvailableReaderWriterIterator itr(_rwList);
1540    for(;itr.valid();++itr)
1541    {
1542        ReaderWriter::WriteResult rr = itr->writeHeightField(HeightField,fileName,_options.get());
1543        if (rr.success()) return rr;
1544        else results.push_back(rr);
1545    }
1546
1547    // now look for a plug-in to save the file.
1548    std::string libraryName = createLibraryNameForFile(fileName);
1549    if (loadLibrary(libraryName))
1550    {
1551        for(;itr.valid();++itr)
1552        {
1553            ReaderWriter::WriteResult rr = itr->writeHeightField(HeightField,fileName,_options.get());
1554            if (rr.success()) return rr;
1555            else results.push_back(rr);
1556        }
1557    }
1558
1559    if (results.empty())
1560    {
1561        return ReaderWriter::WriteResult("Warning: Could not find plugin to write HeightField to file \""+fileName+"\".");
1562    }
1563   
1564    return results.front();
1565}
1566
1567
1568
1569ReaderWriter::ReadResult Registry::readNode(const std::string& fileName)
1570{
1571    // record the errors reported by readerwriters.
1572    typedef std::vector<ReaderWriter::ReadResult> Results;
1573    Results results;
1574
1575    AvailableReaderWriterIterator itr(_rwList);
1576    for(;itr.valid();++itr)
1577    {
1578        ReaderWriter::ReadResult rr = itr->readNode(fileName,_options.get());
1579        if (rr.validNode())  return rr;
1580        else results.push_back(rr);
1581    }
1582
1583    if (!results.empty())
1584    {
1585        unsigned int num_FILE_NOT_HANDLED = 0;
1586        unsigned int num_FILE_NOT_FOUND = 0;
1587        unsigned int num_ERROR_IN_READING_FILE = 0;
1588
1589        for(Results::iterator ritr=results.begin();
1590            ritr!=results.end();
1591            ++ritr)
1592        {
1593            if (ritr->status()==ReaderWriter::ReadResult::FILE_NOT_HANDLED) ++num_FILE_NOT_HANDLED;
1594            else if (ritr->status()==ReaderWriter::ReadResult::FILE_NOT_FOUND) ++num_FILE_NOT_FOUND;
1595            else if (ritr->status()==ReaderWriter::ReadResult::ERROR_IN_READING_FILE) ++num_ERROR_IN_READING_FILE;
1596        }
1597       
1598        if (num_FILE_NOT_HANDLED!=results.size())
1599        {
1600            // we've come across a file not found or error in reading file.
1601            if (num_ERROR_IN_READING_FILE)
1602            {
1603                osg::notify(osg::NOTICE)<<"Warning: error reading file \""<<fileName<<"\""<<std::endl;
1604                return NULL;
1605            }
1606            else if (num_FILE_NOT_FOUND)
1607            {
1608                osg::notify(osg::NOTICE)<<"Warning: could not find file \""<<fileName<<"\""<<std::endl;
1609                return NULL;
1610            }
1611        }
1612    }
1613   
1614    // now look for a plug-in to load the file.
1615    std::string libraryName = createLibraryNameForFile(fileName);
1616    notify(INFO) << "Now checking for plug-in "<<libraryName<< std::endl;
1617    if (loadLibrary(libraryName))
1618    {
1619        for(;itr.valid();++itr)
1620        {
1621            ReaderWriter::ReadResult rr = itr->readNode(fileName,_options.get());
1622            if (rr.validNode()) return rr;
1623            else results.push_back(rr);
1624        }
1625    }
1626
1627
1628    // need to sort out.
1629    CacheHintOptions useObjectCache = CACHE_ALL;
1630
1631    if (_createNodeFromImage)
1632    {
1633        ReaderWriter::ReadResult rr = readImage(fileName,useObjectCache);
1634        if (rr.validImage()) return createGeodeForImage(rr.takeImage());
1635        //else results.push_back(rr);
1636    }
1637
1638    if (results.empty())
1639    {
1640        return ReaderWriter::ReadResult("Warning: Could not find plugin to read nodes from file \""+fileName+"\".");
1641    }
1642
1643    return results.front();
1644}
1645
1646ReaderWriter::ReadResult Registry::readNodeImplementation(const std::string& file,CacheHintOptions useObjectCache)
1647{
1648    if (useObjectCache & CACHE_NODES)
1649    {
1650        // search for entry in the object cache.
1651        ObjectCache::iterator oitr=_objectCache.find(file);
1652        if (oitr!=_objectCache.end())
1653        {
1654            notify(INFO)<< "returning cached instanced of "<<file<<std::endl;
1655            osg::Node* node = dynamic_cast<osg::Node*>(oitr->second.first.get());
1656            if (node) return ReaderWriter::ReadResult(node, ReaderWriter::ReadResult::FILE_LOADED_FROM_CACHE);
1657            else return ReaderWriter::ReadResult("Error file not of type osg::Node");
1658        }
1659
1660        PushAndPopDataPath tmpfile(getFilePath(file));
1661
1662        ReaderWriter::ReadResult rr = readNode(file);
1663        if (rr.validNode())
1664        {
1665            // update cache with new entry.
1666            notify(INFO)<<"Adding to cache node "<<file<<std::endl;
1667            addEntryToObjectCache(file,rr.getObject());
1668        }
1669       
1670        return rr;
1671
1672    }
1673    else
1674    {
1675   
1676        ObjectCache tmpObjectCache;
1677        tmpObjectCache.swap(_objectCache);
1678
1679        PushAndPopDataPath tmpfile(getFilePath(file));
1680
1681        ReaderWriter::ReadResult rr = readNode(file);
1682
1683        tmpObjectCache.swap(_objectCache);
1684
1685        return rr;
1686
1687    }
1688}
1689
1690ReaderWriter::WriteResult Registry::writeNodeImplementation(const Node& node,const std::string& fileName)
1691{
1692    // record the errors reported by readerwriters.
1693    typedef std::vector<ReaderWriter::WriteResult> Results;
1694    Results results;
1695
1696    // first attempt to write the file from existing ReaderWriter's
1697    AvailableReaderWriterIterator itr(_rwList);
1698    for(;itr.valid();++itr)
1699    {
1700        ReaderWriter::WriteResult rr = itr->writeNode(node,fileName,_options.get());
1701        if (rr.success()) return rr;
1702        else results.push_back(rr);
1703    }
1704
1705    // now look for a plug-in to save the file.
1706    std::string libraryName = createLibraryNameForFile(fileName);
1707    if (loadLibrary(libraryName))
1708    {
1709        for(;itr.valid();++itr)
1710        {
1711            ReaderWriter::WriteResult rr = itr->writeNode(node,fileName,_options.get());
1712            if (rr.success()) return rr;
1713            else results.push_back(rr);
1714        }
1715    }
1716
1717    if (results.empty())
1718    {
1719        return ReaderWriter::WriteResult("Warning: Could not find plugin to write nodes to file \""+fileName+"\".");
1720    }
1721
1722    return results.front();
1723}
1724
1725
1726void Registry::addEntryToObjectCache(const std::string& filename, osg::Object* object, double timestamp)
1727{
1728     _objectCache[filename]=ObjectTimeStampPair(object,timestamp);
1729}
1730
1731void Registry::updateTimeStampOfObjectsInCacheWithExtenalReferences(double currentTime)
1732{
1733
1734    // look for objects with external references and update their time stamp.
1735    for(ObjectCache::iterator itr=_objectCache.begin();
1736        itr!=_objectCache.end();
1737        ++itr)
1738    {
1739        // if ref count is greater the 1 the object has an external reference.
1740        if (itr->second.first->referenceCount()>1)
1741        {
1742            // so update it time stamp.
1743            itr->second.second = currentTime;
1744        }
1745    }
1746}
1747
1748void Registry::removeExpiredObjectsInCache(double expiryTime)
1749{
1750    typedef std::vector<std::string> ObjectsToRemove;
1751    ObjectsToRemove objectsToRemove;
1752
1753    // first collect all the exprired entries in the ObjectToRemove list.
1754    for(ObjectCache::iterator oitr=_objectCache.begin();
1755        oitr!=_objectCache.end();
1756        ++oitr)
1757    {
1758        if (oitr->second.second<=expiryTime)
1759        {
1760            // record the filename of the entry to use as key for deleting
1761            // afterwards/
1762            objectsToRemove.push_back(oitr->first);
1763        }
1764    }
1765   
1766    // remove the entries from the _objectCaache.
1767    for(ObjectsToRemove::iterator ritr=objectsToRemove.begin();
1768        ritr!=objectsToRemove.end();
1769        ++ritr)
1770    {
1771        // std::cout<<"Removing from Registry object cache '"<<*ritr<<"'"<<std::endl;
1772        _objectCache.erase(*ritr);
1773    }
1774       
1775}
1776
1777void Registry::clearObjectCache()
1778{
1779    _objectCache.clear();
1780}
1781
1782DatabasePager* Registry::getOrCreateDatabasePager()
1783{
1784    if (!_databasePager) _databasePager = new DatabasePager;
1785   
1786    return _databasePager.get();
1787}
1788
1789SharedStateManager* Registry::getOrCreateSharedStateManager()
1790{
1791    if (!_sharedStateManager) _sharedStateManager = new SharedStateManager;
1792   
1793    return _sharedStateManager.get();
1794}
Note: See TracBrowser for help on using the browser.