root/OpenSceneGraph/trunk/src/osgPlugins/p3d/ReaderWriterP3D.cpp @ 13205

Revision 13205, 89.7 kB (checked in by robert, 99 minutes ago)

From Jan Ciger, "Here is a little patch to fix a bug in the InfluenceMap? serialization. The names of the maps weren't quoted properly and therefore it was breaking loading of rigged models exported from e.g. Blender. Also names that contained spaces wouldn't have been parsed properly. "

  • Property svn:eol-style set to native
Line 
1    /* -*-c++-*- Present3D - Copyright (C) 1999-2006 Robert Osfield
2 *
3 * This software is open source and may be redistributed and/or modified under
4 * the terms of the GNU General Public License (GPL) version 2.0.
5 * The full license is in LICENSE.txt file included with this distribution,.
6 *
7 * This software is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10 * include LICENSE.txt for more details.
11*/
12
13#include <osg/Notify>
14#include <osg/io_utils>
15#include <osg/PagedLOD>
16
17#include <osgDB/ReaderWriter>
18#include <osgDB/FileNameUtils>
19#include <osgDB/FileUtils>
20#include <osgDB/Registry>
21
22#include <osgWidget/PdfReader>
23
24#include <osgPresentation/SlideShowConstructor>
25
26#include <stdio.h>
27#include <string.h>
28#include <stdlib.h>
29
30#include <osgDB/XmlParser>
31
32#include <sstream>
33#include <iostream>
34
35
36/**
37 * OpenSceneGraph plugin wrapper/converter.
38 */
39class ReaderWriterP3DXML : public osgDB::ReaderWriter
40{
41public:
42    ReaderWriterP3DXML()
43    {
44        _colorMap["WHITE"]  .set(1.0f,1.0f,1.0f,1.0f);
45        _colorMap["BLACK"]  .set(0.0f,0.0f,0.0f,1.0f);
46        _colorMap["PURPLE"] .set(1.0f,0.0f,1.0f,1.0f);
47        _colorMap["BLUE"]   .set(0.0f,0.0f,1.0f,1.0f);
48        _colorMap["RED"]    .set(1.0f,0.0f,0.0f,1.0f);
49        _colorMap["CYAN"]   .set(0.0f,1.0f,1.0f,1.0f);
50        _colorMap["YELLOW"] .set(1.0f,1.0f,0.0f,1.0f);
51        _colorMap["GREEN"]  .set(0.0f,1.0f,0.0f,1.0f);
52        _colorMap["SKY"]    .set(0.2f, 0.2f, 0.4f, 1.0f);
53
54        _layoutMap["LEFT_TO_RIGHT"] = osgText::Text::LEFT_TO_RIGHT;
55        _layoutMap["RIGHT_TO_LEFT"] = osgText::Text::RIGHT_TO_LEFT;
56        _layoutMap["VERTICAL"] = osgText::Text::VERTICAL;
57
58        _alignmentMap["LEFT_TOP"] = osgText::Text::LEFT_TOP;
59        _alignmentMap["LEFT_CENTER"] = osgText::Text::LEFT_CENTER;
60        _alignmentMap["LEFT_BOTTOM"] = osgText::Text::LEFT_BOTTOM;
61
62        _alignmentMap["CENTER_TOP"] = osgText::Text::CENTER_TOP;
63        _alignmentMap["CENTER_CENTER"] = osgText::Text::CENTER_CENTER;
64        _alignmentMap["CENTER_BOTTOM"] = osgText::Text::CENTER_BOTTOM;
65
66        _alignmentMap["RIGHT_TOP"] = osgText::Text::RIGHT_TOP;
67        _alignmentMap["RIGHT_CENTER"] = osgText::Text::RIGHT_CENTER;
68        _alignmentMap["RIGHT_BOTTOM"] = osgText::Text::RIGHT_BOTTOM;
69
70        _alignmentMap["LEFT_BASE_LINE"] = osgText::Text::LEFT_BASE_LINE;
71        _alignmentMap["CENTER_BASE_LINE"] = osgText::Text::CENTER_BASE_LINE;
72        _alignmentMap["RIGHT_BASE_LINE"] = osgText::Text::RIGHT_BASE_LINE;
73        _alignmentMap["BASE_LINE"] = osgText::Text::LEFT_BASE_LINE;
74
75        _characterSizeModeMap["OBJECT_COORDS"] = osgText::Text::OBJECT_COORDS;
76        _characterSizeModeMap["SCREEN_COORDS"] = osgText::Text::SCREEN_COORDS;
77        _characterSizeModeMap["OBJECT_COORDS_WITH_MAXIMUM_SCREEN_SIZE_CAPPED_BY_FONT_HEIGHT"] = osgText::Text::OBJECT_COORDS_WITH_MAXIMUM_SCREEN_SIZE_CAPPED_BY_FONT_HEIGHT;
78
79        _stringKeyMap["Home"]=' ';
80        _stringKeyMap["Start"]= osgGA::GUIEventAdapter::KEY_Home;
81        _stringKeyMap["Next"]= osgGA::GUIEventAdapter::KEY_Page_Down;
82        _stringKeyMap["Previous"]=osgGA::GUIEventAdapter::KEY_Page_Up;
83        _stringKeyMap["Up"]=osgGA::GUIEventAdapter::KEY_Up;
84        _stringKeyMap["Down"]=osgGA::GUIEventAdapter::KEY_Down;
85        _stringKeyMap["End"]=osgGA::GUIEventAdapter::KEY_End;
86        _stringKeyMap["Page Down"]=osgGA::GUIEventAdapter::KEY_Page_Down;
87        _stringKeyMap["Page Up"]=osgGA::GUIEventAdapter::KEY_Page_Up;
88        _stringKeyMap["F1"]=osgGA::GUIEventAdapter::KEY_F1;
89        _stringKeyMap["F2"]=osgGA::GUIEventAdapter::KEY_F2;
90        _stringKeyMap["F3"]=osgGA::GUIEventAdapter::KEY_F3;
91        _stringKeyMap["F4"]=osgGA::GUIEventAdapter::KEY_F4;
92        _stringKeyMap["F5"]=osgGA::GUIEventAdapter::KEY_F5;
93        _stringKeyMap["F6"]=osgGA::GUIEventAdapter::KEY_F6;
94        _stringKeyMap["F7"]=osgGA::GUIEventAdapter::KEY_F7;
95        _stringKeyMap["F8"]=osgGA::GUIEventAdapter::KEY_F8;
96        _stringKeyMap["F9"]=osgGA::GUIEventAdapter::KEY_F9;
97        _stringKeyMap["F10"]=osgGA::GUIEventAdapter::KEY_F10;
98        _stringKeyMap["F11"]=osgGA::GUIEventAdapter::KEY_F11;
99        _stringKeyMap["F12"]=osgGA::GUIEventAdapter::KEY_F12;
100
101
102        _notifyLevel = osg::INFO;
103    }
104
105    virtual const char* className() const
106    {
107        return "present3D XML Reader/Writer";
108    }
109
110    virtual bool acceptsExtension(const std::string& extension) const
111    {
112        return osgDB::equalCaseInsensitive(extension,"p3d") ||
113               osgDB::equalCaseInsensitive(extension,"xml") ;
114    }
115
116    virtual ReadResult readNode(const std::string& fileName,
117                                const osgDB::ReaderWriter::Options* options) const;
118
119    virtual ReadResult readNode(std::istream& fin, const Options* options) const;
120
121    ReadResult readNode(osgDB::XmlNode::Input& input, osgDB::ReaderWriter::Options* options) const;
122
123    osg::Node* parseXmlGraph(osgDB::XmlNode* root, bool readOnlyHoldingPage, osgDB::Options* options) const;
124
125    void parseModel(osgPresentation::SlideShowConstructor& constructor, osgDB::XmlNode*cur) const;
126
127    osg::TransferFunction1D* readTransferFunctionFile(const std::string& filename, float scale) const;
128    void parseVolume(osgPresentation::SlideShowConstructor& constructor, osgDB::XmlNode*cur) const;
129
130    void parseStereoPair(osgPresentation::SlideShowConstructor& constructor, osgDB::XmlNode*cur) const;
131
132    void parseLayer(osgPresentation::SlideShowConstructor& constructor, osgDB::XmlNode*cur) const;
133
134    void parseBullets(osgPresentation::SlideShowConstructor& constructor, osgDB::XmlNode*cur, bool inheritPreviousLayers, bool defineAsBaseLayer) const;
135    void parseText(osgPresentation::SlideShowConstructor& constructor, osgDB::XmlNode*cur, bool inheritPreviousLayers, bool defineAsBaseLayer) const;
136
137    void parsePage (osgPresentation::SlideShowConstructor& constructor, osgDB::XmlNode*cur) const;
138
139    void parseSlide (osgPresentation::SlideShowConstructor& constructor, osgDB::XmlNode*cur, bool parseTitles=true, bool parseLayers=true) const;
140
141    void parsePdfDocument (osgPresentation::SlideShowConstructor& constructor, osgDB::XmlNode*cur) const;
142
143    osg::Vec4 mapStringToColor(const std::string& str) const
144    {
145        ColorMap::const_iterator itr=_colorMap.find(str);
146        if (itr!=_colorMap.end()) return itr->second;
147        osg::Vec4 color;
148        if (read(str,color)) return color;
149        else return osg::Vec4(0.0f,0.0f,0.0f,1.0f);
150    }
151
152    inline osg::Vec4 accumulateRotation(const osg::Vec4& lhs, const osg::Vec4& rhs) const
153    {
154        osg::Quat qlhs,qrhs;
155        qlhs.makeRotate(osg::DegreesToRadians(lhs[0]),lhs[1],lhs[2],lhs[3]);
156        qrhs.makeRotate(osg::DegreesToRadians(rhs[0]),rhs[1],rhs[2],rhs[3]);
157        osg::Quat quat = qlhs*qrhs;
158        osg::Vec4d result;
159        quat.getRotate ( result[0], result[1], result[2], result[3]);
160        result[0] = osg::RadiansToDegrees(result[0]);
161        return result;
162    }
163
164    inline bool read(const char* str, int& value) const;
165    inline bool read(const char* str, float& value) const;
166    inline bool read(const char* str, double& value) const;
167    inline bool read(const char* str, int numberValues, float* values) const;
168    inline bool read(const char* str, osg::Vec2& value) const;
169    inline bool read(const char* str, osg::Vec3& value) const;
170    inline bool read(const char* str, osg::Vec4& value) const;
171
172    inline bool read(const std::string& str, int& value) const;
173    inline bool read(const std::string& str, float& value) const;
174    inline bool read(const std::string& str, double& value) const;
175    inline bool read(const std::string& str, int numberValues, float* values) const;
176    inline bool read(const std::string& str, osg::Vec2& value) const;
177    inline bool read(const std::string& str, osg::Vec3& value) const;
178    inline bool read(const std::string& str, osg::Vec4& value) const;
179
180    bool getProperty(osgDB::XmlNode*cur, const char* token) const;
181    bool getKeyProperty(osgDB::XmlNode*cur, const char* token, int& value) const;
182    bool getProperty(osgDB::XmlNode*cur, const char* token, int& value) const;
183    bool getProperty(osgDB::XmlNode*cur, const char* token, float& value) const;
184    bool getProperty(osgDB::XmlNode*cur, const char* token, double& value) const;
185    bool getProperty(osgDB::XmlNode*cur, const char* token, int numberValues, float* values) const;
186    bool getProperty(osgDB::XmlNode*cur, const char* token, osg::Vec2& value) const;
187    bool getProperty(osgDB::XmlNode*cur, const char* token, osg::Vec3& value) const;
188    bool getProperty(osgDB::XmlNode*cur, const char* token, osg::Vec4& value) const;
189    bool getProperty(osgDB::XmlNode*cur, const char* token, std::string& value) const;
190    bool getTrimmedProperty(osgDB::XmlNode*cur, const char* token, std::string& value) const;
191    bool getProperty(osgDB::XmlNode*cur, const char* token, osgText::Text::Layout& value) const;
192    bool getProperty(osgDB::XmlNode*cur, const char* token, osgText::Text::AlignmentType& value) const;
193    bool getProperty(osgDB::XmlNode*cur, const char* token, osgText::Text::CharacterSizeMode& value) const;
194
195    bool getProperties(osgDB::XmlNode*cur, osgPresentation::SlideShowConstructor::PositionData& value) const;
196    bool getProperties(osgDB::XmlNode*cur, osgPresentation::SlideShowConstructor::FontData& value) const;
197    bool getProperties(osgDB::XmlNode*cur, osgPresentation::SlideShowConstructor::ModelData& value) const;
198    bool getProperties(osgDB::XmlNode*cur, osgPresentation::SlideShowConstructor::ImageData& value) const;
199    bool getJumpProperties(osgDB::XmlNode*cur, osgPresentation::JumpData& jumpData) const;
200
201    bool getKeyPositionInner(osgDB::XmlNode*cur, osgPresentation::KeyPosition& keyPosition) const;
202    bool getKeyPosition(osgDB::XmlNode*cur, osgPresentation::KeyPosition& keyPosition) const;
203
204    typedef std::map<std::string,osg::Vec4> ColorMap;
205    typedef std::map<std::string,osgText::Text::Layout> LayoutMap;
206    typedef std::map<std::string,osgText::Text::AlignmentType> AlignmentMap;
207    typedef std::map<std::string,osgText::Text::CharacterSizeMode> CharacterSizeModeMap;
208    typedef std::map<std::string, unsigned int> StringKeyMap;
209
210    std::string expandEnvVarsInFileName(const std::string& filename) const;
211
212
213    ColorMap                _colorMap;
214    LayoutMap               _layoutMap;
215    AlignmentMap            _alignmentMap;
216    CharacterSizeModeMap    _characterSizeModeMap;
217    StringKeyMap            _stringKeyMap;
218
219    typedef std::map<std::string, osg::ref_ptr<osgDB::XmlNode> > TemplateMap;
220    mutable TemplateMap _templateMap;
221
222    osg::NotifySeverity _notifyLevel;
223
224};
225
226// now register with Registry to instantiate the above
227// reader/writer.
228REGISTER_OSGPLUGIN(p3d, ReaderWriterP3DXML)
229
230std::string ReaderWriterP3DXML::expandEnvVarsInFileName(const std::string& filename) const
231{
232    std::string argument(filename);
233    std::string::size_type start_pos = argument.find("${");
234
235    while (start_pos != std::string::npos)
236    {
237        std::string::size_type end_pos = argument.find("}",start_pos);
238        if (start_pos != std::string::npos)
239        {
240            std::string var = argument.substr(start_pos+2, end_pos-start_pos-2);
241            const char* str = getenv(var.c_str());
242            if (str)
243            {
244                argument.erase(start_pos, end_pos-start_pos+1);
245                argument.insert(start_pos, str);
246            }
247            start_pos = argument.find("${",end_pos);
248        }
249        else
250        {
251            start_pos = std::string::npos;
252        }
253    }
254
255    return argument;
256}
257
258bool ReaderWriterP3DXML::read(const char* str, int& value) const
259{
260    if (!str) return false;
261    std::istringstream iss((const char*)str);
262    iss >> value;
263    return !iss.fail();
264}
265
266bool ReaderWriterP3DXML::read(const char* str, float& value) const
267{
268    if (!str) return false;
269    std::istringstream iss((const char*)str);
270    iss >> value;
271    return !iss.fail();
272}
273
274bool ReaderWriterP3DXML::read(const char* str, double& value) const
275{
276    if (!str) return false;
277    std::istringstream iss((const char*)str);
278    iss >> value;
279    return !iss.fail();
280}
281
282bool ReaderWriterP3DXML::read(const char* str, int numberValues, float* values) const
283{
284    if (!str) return false;
285    std::istringstream iss((const char*)str);
286    for(int i=0; i<numberValues && !iss.fail(); i++)
287    {
288        iss >> *values;
289        ++values;
290    }
291    return !iss.fail();
292}
293
294bool ReaderWriterP3DXML::read(const char* str, osg::Vec2& value) const
295{
296    if (!str) return false;
297    std::istringstream iss((const char*)str);
298    iss >> value.x() >> value.y();
299    return !iss.fail();
300}
301
302bool ReaderWriterP3DXML::read(const char* str, osg::Vec3& value) const
303{
304    if (!str) return false;
305    std::istringstream iss((const char*)str);
306    iss >> value.x() >> value.y() >> value.z();
307    return !iss.fail();
308}
309
310bool ReaderWriterP3DXML::read(const char* str, osg::Vec4& value) const
311{
312    if (!str) return false;
313    std::istringstream iss((const char*)str);
314    iss >> value.x() >> value.y() >> value.z() >> value.w();
315    return !iss.fail();
316}
317
318bool ReaderWriterP3DXML::read(const std::string& str, int& value) const
319{
320    std::istringstream iss(str);
321    iss >> value;
322    return !iss.fail();
323}
324
325bool ReaderWriterP3DXML::read(const std::string& str, float& value) const
326{
327    std::istringstream iss(str);
328    iss >> value;
329    return !iss.fail();
330}
331
332bool ReaderWriterP3DXML::read(const std::string& str, double& value) const
333{
334    std::istringstream iss(str);
335    iss >> value;
336    return !iss.fail();
337}
338
339
340bool ReaderWriterP3DXML::read(const std::string& str, int numberValues, float* values) const
341{
342    std::istringstream iss(str);
343    for(int i=0; i<numberValues && !iss.fail(); i++)
344    {
345        iss >> *values;
346        ++values;
347    }
348    return !iss.fail();
349}
350
351bool ReaderWriterP3DXML::read(const std::string& str, osg::Vec2& value) const
352{
353    std::istringstream iss(str);
354    iss >> value.x() >> value.y();
355    return !iss.fail();
356}
357
358bool ReaderWriterP3DXML::read(const std::string& str, osg::Vec3& value) const
359{
360    std::istringstream iss(str);
361    iss >> value.x() >> value.y() >> value.z();
362    return !iss.fail();
363}
364
365bool ReaderWriterP3DXML::read(const std::string& str, osg::Vec4& value) const
366{
367    std::istringstream iss(str);
368    iss >> value.x() >> value.y() >> value.z() >> value.w();
369    return !iss.fail();
370}
371
372bool ReaderWriterP3DXML::getProperty(osgDB::XmlNode* cur, const char* token) const
373{
374    return cur->properties.count(token)!=0;
375}
376
377bool ReaderWriterP3DXML::getProperty(osgDB::XmlNode*cur, const char* token, int& value) const
378{
379    osgDB::XmlNode::Properties::iterator itr = cur->properties.find(token);
380    if (itr==cur->properties.end()) return false;
381    return read(itr->second,value);
382}
383
384bool ReaderWriterP3DXML::getKeyProperty(osgDB::XmlNode*cur, const char* token, int& value) const
385{
386    osgDB::XmlNode::Properties::iterator itr = cur->properties.find(token);
387    if (itr==cur->properties.end()) return false;
388
389    OSG_NOTICE<<"getKeyProperty()="<<itr->second<<std::endl;
390
391    if (itr->second.empty())
392    {
393        OSG_NOTICE<<"   empty()"<<std::endl;
394        return false;
395    }
396   
397    if (itr->second.find("0x",0,2)!=std::string::npos)
398    {
399        std::istringstream iss(itr->second);
400        iss>>std::hex>>value;
401        return true;
402    }
403    else if (itr->second.size()>1 && (itr->second[0]>='0' && itr->second[0]<='9'))
404    {
405        std::istringstream iss(itr->second);
406        iss>>value;
407        OSG_NOTICE<<"   numeric result = "<<value<<std::endl;
408        return true;
409    }
410    else
411    {
412        value = itr->second[0];
413        OSG_NOTICE<<"   alphanumeric result = "<<value<<std::endl;
414        return true;
415    }
416}
417
418bool ReaderWriterP3DXML::getProperty(osgDB::XmlNode*cur, const char* token, float& value) const
419{
420    osgDB::XmlNode::Properties::iterator itr = cur->properties.find(token);
421    if (itr==cur->properties.end()) return false;
422    return read(itr->second,value);
423}
424
425bool ReaderWriterP3DXML::getProperty(osgDB::XmlNode*cur, const char* token, double& value) const
426{
427    osgDB::XmlNode::Properties::iterator itr = cur->properties.find(token);
428    if (itr==cur->properties.end()) return false;
429    return read(itr->second,value);
430}
431
432bool ReaderWriterP3DXML::getProperty(osgDB::XmlNode*cur, const char* token, int numberValues, float* values) const
433{
434    osgDB::XmlNode::Properties::iterator itr = cur->properties.find(token);
435    if (itr==cur->properties.end()) return false;
436    return read(itr->second, numberValues, values);
437}
438
439bool ReaderWriterP3DXML::getProperty(osgDB::XmlNode*cur, const char* token, osg::Vec2& value) const
440{
441    osgDB::XmlNode::Properties::iterator itr = cur->properties.find(token);
442    if (itr==cur->properties.end()) return false;
443    return read(itr->second,value);
444}
445
446bool ReaderWriterP3DXML::getProperty(osgDB::XmlNode*cur, const char* token, osg::Vec3& value) const
447{
448    osgDB::XmlNode::Properties::iterator itr = cur->properties.find(token);
449    if (itr==cur->properties.end()) return false;
450    return read(itr->second,value);
451}
452
453bool ReaderWriterP3DXML::getProperty(osgDB::XmlNode*cur, const char* token, osg::Vec4& value) const
454{
455    osgDB::XmlNode::Properties::iterator itr = cur->properties.find(token);
456    if (itr==cur->properties.end()) return false;
457    return read(itr->second,value);
458}
459
460bool ReaderWriterP3DXML::getProperty(osgDB::XmlNode*cur, const char* token, std::string& value) const
461{
462    osgDB::XmlNode::Properties::iterator itr = cur->properties.find(token);
463    if (itr==cur->properties.end()) return false;
464    value = itr->second;
465    return true;
466}
467
468bool ReaderWriterP3DXML::getTrimmedProperty(osgDB::XmlNode*cur, const char* token, std::string& value) const
469{
470    osgDB::XmlNode::Properties::iterator itr = cur->properties.find(token);
471    if (itr==cur->properties.end()) return false;
472    value = osgDB::trimEnclosingSpaces(itr->second);
473    return true;
474}
475
476bool ReaderWriterP3DXML::getProperty(osgDB::XmlNode*cur, const char* token, osgText::Text::Layout& value) const
477{
478    osgDB::XmlNode::Properties::iterator pitr = cur->properties.find(token);
479    if (pitr==cur->properties.end()) return false;
480
481    const std::string& str = pitr->second;
482    LayoutMap::const_iterator itr = _layoutMap.find(str);
483    if (itr!=_layoutMap.end())
484    {
485        value = itr->second;
486    }
487    return true;
488}
489
490bool ReaderWriterP3DXML::getProperty(osgDB::XmlNode*cur, const char* token, osgText::Text::AlignmentType& value) const
491{
492    osgDB::XmlNode::Properties::iterator pitr = cur->properties.find(token);
493    if (pitr==cur->properties.end()) return false;
494
495    const std::string& str = pitr->second;
496    AlignmentMap::const_iterator itr = _alignmentMap.find(str);
497    if (itr!=_alignmentMap.end())
498    {
499        value = itr->second;
500    }
501    return true;
502}
503
504bool ReaderWriterP3DXML::getProperty(osgDB::XmlNode*cur, const char* token, osgText::Text::CharacterSizeMode& value) const
505{
506    osgDB::XmlNode::Properties::iterator pitr = cur->properties.find(token);
507    if (pitr==cur->properties.end()) return false;
508
509    const std::string& str = pitr->second;
510    CharacterSizeModeMap::const_iterator itr = _characterSizeModeMap.find(str);
511    if (itr!=_characterSizeModeMap.end())
512    {
513        value = itr->second;
514    }
515    return true;
516}
517
518bool ReaderWriterP3DXML::getProperties(osgDB::XmlNode*cur, osgPresentation::SlideShowConstructor::PositionData& value) const
519{
520    bool propertiesRead=false;
521
522    osg::Vec3 position(0.0f,1.0f,0.0f);
523    osg::Vec4 rotate(0.0f,0.0f,0.0f,1.0f);
524    float scale = 1.0f;
525
526    osg::Vec4 rotation(0.0f,0.0f,0.0f,1.0f);
527
528    // temporary
529    std::string str;
530
531    if (getProperty(cur, "coordinate_frame", str))
532    {
533        propertiesRead = true;
534
535        if (str=="model") value.frame = osgPresentation::SlideShowConstructor::MODEL;
536        else if (str=="slide") value.frame = osgPresentation::SlideShowConstructor::SLIDE;
537        else OSG_NOTIFY(_notifyLevel)<<"Parser error - coordinate_frame=\""<<str<<"\" unrecongonized value"<<std::endl;
538
539        OSG_NOTIFY(_notifyLevel)<<"read coordinate_frame "<< ((value.frame==osgPresentation::SlideShowConstructor::MODEL) ? "osgPresentation::SlideShowConstructor::MODEL" : "osgPresentation::SlideShowConstructor::SLIDE")<<std::endl;
540    }
541
542    if (value.frame==osgPresentation::SlideShowConstructor::SLIDE)
543    {
544
545        if (getProperty(cur, "position", str))
546        {
547            value.position.set(0.5,0.5,0.0);
548
549            propertiesRead = true;
550
551            osg::Vec2 vec2;
552            osg::Vec3 vec3;
553
554            bool fail = false;
555            if (str=="center") value.position.set(0.5f,.5f,0.0f);
556            else if (str=="eye") value.position.set(0.0f,0.0f,1.0f);
557            else if (read(str,vec3)) value.position = vec3;
558            else if (read(str,vec2)) value.position.set(vec3.x(),vec3.y(),0.0f);
559            else fail = true;
560
561            if (fail) { OSG_NOTIFY(_notifyLevel)<<"Parser error - position=\""<<str<<"\" unrecongonized value"<<std::endl; }
562            else { OSG_NOTIFY(_notifyLevel)<<"Read position="<<value.position<<std::endl; }
563        }
564    }
565    else // value.frame==osgPresentation::SlideShowConstructor::MODEL
566    {
567
568        if (getProperty(cur, "position", str))
569        {
570            value.position.set(0.0,0.0,0.0);
571
572            propertiesRead = true;
573
574            bool fail = false;
575            if (str=="center") value.position.set(0.0f,1.0f,0.0f);
576            else if (str=="eye") value.position.set(0.0f,0.0f,0.0f);
577            else if (!read(str,value.position)) fail = true;
578
579            if (fail) { OSG_NOTIFY(_notifyLevel)<<"Parser error - position=\""<<str<<"\" unrecongonized value"<<std::endl; }
580            else { OSG_NOTIFY(_notifyLevel)<<"Read position="<<value.position<<std::endl; }
581        }
582    }
583
584
585    if (getProperty(cur, "scale", scale))
586    {
587        value.scale.set(scale,scale,scale);
588        propertiesRead = true;
589        OSG_NOTIFY(_notifyLevel)<<"scale read "<<scale<<std::endl;
590    }
591
592    if (getProperty(cur, "scale_x", scale) || getProperty(cur, "width", scale))
593    {
594        value.scale.x() = scale;
595        propertiesRead = true;
596        OSG_NOTIFY(_notifyLevel)<<"scale read_x "<<scale<<std::endl;
597    }
598
599    if (getProperty(cur, "scale_y", scale) || getProperty(cur, "height", scale))
600    {
601        value.scale.y() = scale;
602        propertiesRead = true;
603        OSG_NOTIFY(_notifyLevel)<<"scale read_y "<<scale<<std::endl;
604    }
605
606    if (getProperty(cur, "scale_z", scale))
607    {
608        value.scale.z() = scale;
609        propertiesRead = true;
610        OSG_NOTIFY(_notifyLevel)<<"scale read_z "<<scale<<std::endl;
611    }
612
613    if (getProperty(cur, "rotate", rotate))
614    {
615        value.rotate = rotate;
616        propertiesRead = true;
617        OSG_NOTIFY(_notifyLevel)<<"rotate read "<<rotate<<std::endl;
618    }
619
620    if (getProperty(cur, "rotate1", rotate))
621    {
622        // note may need to reverse once Quat * order is sorted out.
623        value.rotate = accumulateRotation(rotate,value.rotate);
624        propertiesRead = true;
625        OSG_NOTIFY(_notifyLevel)<<"rotate1 read "<<rotate<<std::endl;
626    }
627
628    if (getProperty(cur, "rotate2", rotate))
629    {
630        // note may need to reverse once Quat * order is sorted out.
631        value.rotate = accumulateRotation(rotate,value.rotate);
632        propertiesRead = true;
633        OSG_NOTIFY(_notifyLevel)<<"rotate1 read "<<rotate<<std::endl;
634    }
635
636    if (getProperty(cur, "rotate3", rotate))
637    {
638        // note may need to reverse once Quat * order is sorted out.
639        value.rotate = accumulateRotation(rotate,value.rotate);
640        propertiesRead = true;
641        OSG_NOTIFY(_notifyLevel)<<"rotate1 read "<<rotate<<std::endl;
642    }
643
644    if (getProperty(cur, "rotation", rotation))
645    {
646        value.rotation = rotation;
647        OSG_NOTIFY(_notifyLevel)<<"rotation read "<<rotation<<std::endl;
648        propertiesRead = true;
649    }
650
651    if (getProperty(cur, "rotation1", rotation))
652    {
653        value.rotation = accumulateRotation(rotation,value.rotation);
654        OSG_NOTIFY(_notifyLevel)<<"rotation1 read "<<rotation<<std::endl;
655        propertiesRead = true;
656    }
657
658    if (getProperty(cur, "rotation2", rotation))
659    {
660        value.rotation = accumulateRotation(rotation,value.rotation);
661        OSG_NOTIFY(_notifyLevel)<<"rotation2 read "<<rotation<<std::endl;
662        propertiesRead = true;
663    }
664
665    if (getProperty(cur, "rotation3", rotation))
666    {
667        value.rotation = accumulateRotation(rotation,value.rotation);
668        OSG_NOTIFY(_notifyLevel)<<"rotation3 read "<<rotation<<std::endl;
669        propertiesRead = true;
670    }
671
672    if (getTrimmedProperty(cur, "path", str))
673    {
674
675        value.absolute_path = false;
676        value.inverse_path = false;
677        value.path = expandEnvVarsInFileName(str);
678
679        OSG_NOTIFY(_notifyLevel)<<"path read "<<str<<std::endl;
680        propertiesRead = true;
681    }
682
683    if (getTrimmedProperty(cur, "camera_path", str))
684    {
685        value.absolute_path = true;
686        value.inverse_path = true;
687        value.path = expandEnvVarsInFileName(str);
688
689        OSG_NOTIFY(_notifyLevel)<<"camera path read "<<str<<std::endl;
690        propertiesRead = true;
691    }
692
693    if (getProperty(cur, "path_time_offset", value.path_time_offset))
694    {
695        OSG_NOTIFY(_notifyLevel)<<"read path_time_offset"<<value.path_time_offset<<std::endl;
696        propertiesRead = true;
697    }
698
699    if (getProperty(cur, "path_time_multiplier", value.path_time_multiplier))
700    {
701        OSG_NOTIFY(_notifyLevel)<<"read path_time_multiplier"<<value.path_time_multiplier<<std::endl;
702        propertiesRead = true;
703    }
704
705    if (getProperty(cur, "animation_material_time_offset", value.animation_material_time_offset))
706    {
707        OSG_NOTIFY(_notifyLevel)<<"read animation_material_time_offset"<<value.animation_material_time_offset<<std::endl;
708        propertiesRead = true;
709    }
710
711    if (getProperty(cur, "animation_material_time_multiplier", value.animation_material_time_multiplier))
712    {
713        OSG_NOTIFY(_notifyLevel)<<"read animation_material_time_multiplier"<<value.animation_material_time_multiplier<<std::endl;
714        propertiesRead = true;
715    }
716
717    if (getTrimmedProperty(cur, "animation_material", str))
718    {
719        value.animation_material_filename = str;
720
721        OSG_NOTIFY(_notifyLevel)<<"animation_material read "<<str<<std::endl;
722        propertiesRead = true;
723    }
724
725    if (getTrimmedProperty(cur, "animation_name", str))
726    {
727        value.animation_name = str;
728
729        OSG_NOTIFY(_notifyLevel)<<"animation_name "<<str<<std::endl;
730        propertiesRead = true;
731    }
732
733    if (getProperty(cur, "fade", value.fade))
734    {
735        OSG_NOTIFY(_notifyLevel)<<"fade "<<value.fade<<std::endl;
736        propertiesRead = true;
737    }
738
739    if (getProperty(cur, "path_loop_mode", str))
740    {
741        OSG_NOTIFY(_notifyLevel)<<"path_loop_mode "<<str<<std::endl;
742        if (str=="LOOP") value.path_loop_mode=osg::AnimationPath::LOOP;
743        else if (str=="SWING") value.path_loop_mode=osg::AnimationPath::SWING;
744        else if (str=="NO_LOOPING") value.path_loop_mode=osg::AnimationPath::NO_LOOPING;
745        propertiesRead = true;
746    }
747
748    if (getProperty(cur, "animation_material_loop_mode", str))
749    {
750        OSG_NOTIFY(_notifyLevel)<<"animation_material_loop_mode "<<str<<std::endl;
751        if (str=="LOOP") value.animation_material_loop_mode=osgPresentation::AnimationMaterial::LOOP;
752        else if (str=="SWING") value.animation_material_loop_mode=osgPresentation::AnimationMaterial::SWING;
753        else if (str=="NO_LOOPING") value.animation_material_loop_mode=osgPresentation::AnimationMaterial::NO_LOOPING;
754        propertiesRead = true;
755    }
756
757    if (getProperty(cur, "billboard", str))
758    {
759        value.autoRotate = (str != "off" && str != "Off" && str != "OFF");
760        OSG_NOTIFY(_notifyLevel)<<"billboard, str="<<str<<", autoRotate="<<value.autoRotate<<std::endl;
761        propertiesRead = true;
762    }
763
764    if (getProperty(cur, "scale_to_screen",str))
765    {
766        value.autoScale = (str != "off" && str != "Off" && str != "OFF");
767        OSG_NOTIFY(_notifyLevel)<<"scale-to-screen, str="<<str<<", autoRotate="<<value.autoScale<<std::endl;
768        propertiesRead = true;
769    }
770
771    if (getProperty(cur, "hud", str))
772    {
773        value.hud = (str != "off" && str != "Off" && str != "OFF");
774        OSG_NOTIFY(_notifyLevel)<<"hud, str="<<str<<", hud="<<value.hud<<std::endl;
775        propertiesRead = true;
776    }
777
778
779    return propertiesRead;
780}
781
782bool ReaderWriterP3DXML::getProperties(osgDB::XmlNode*cur, osgPresentation::SlideShowConstructor::FontData& value) const
783{
784    bool propertiesRead=false;
785
786    OSG_NOTIFY(_notifyLevel)<<"in getProperties(FontData)"<<std::endl;
787
788    if (getProperty(cur, "font", value.font))
789    {
790        propertiesRead = true;
791        OSG_NOTIFY(_notifyLevel)<<"read font \""<<value.font<<"\""<<std::endl;
792    }
793
794    if (getProperty(cur, "character_size", value.characterSize))
795    {
796        propertiesRead = true;
797        OSG_NOTIFY(_notifyLevel)<<"read height \""<<value.characterSize<<"\""<<std::endl;
798    }
799
800    if (getProperty(cur, "character_size_mode", value.characterSizeMode))
801    {
802        propertiesRead = true;
803
804        OSG_NOTIFY(_notifyLevel)<<"read character_size_mode \""<<value.characterSizeMode<<"\""<<std::endl;
805    }
806
807    if (getProperty(cur, "layout", value.layout))
808    {
809        propertiesRead = true;
810
811        OSG_NOTIFY(_notifyLevel)<<"read layout \""<<value.layout<<"\""<<std::endl;
812    }
813
814    if (getProperty(cur, "alignment", value.alignment))
815    {
816        propertiesRead = true;
817
818        OSG_NOTIFY(_notifyLevel)<<"read alignment \""<<value.alignment<<"\""<<std::endl;
819    }
820
821    return propertiesRead;
822}
823
824bool ReaderWriterP3DXML::getProperties(osgDB::XmlNode*cur, osgPresentation::SlideShowConstructor::ModelData& value) const
825{
826    bool propertiesRead=false;
827
828    OSG_NOTIFY(_notifyLevel)<<"in getProperties(ModelData)"<<std::endl;
829
830    if (getProperty(cur, "effect", value.effect))
831    {
832        propertiesRead = true;
833        OSG_NOTIFY(_notifyLevel)<<"read effect \""<<value.effect<<"\""<<std::endl;
834    }
835
836    if (getProperty(cur, "options", value.options))
837    {
838        propertiesRead = true;
839        OSG_NOTIFY(_notifyLevel)<<"read options \""<<value.options<<"\""<<std::endl;
840    }
841
842    return propertiesRead;
843}
844
845bool ReaderWriterP3DXML::getProperties(osgDB::XmlNode*cur, osgPresentation::SlideShowConstructor::ImageData& value) const
846{
847    bool propertiesRead=false;
848
849    OSG_NOTIFY(_notifyLevel)<<"in getProperties(ImageData)"<<std::endl;
850
851    if (getProperty(cur, "page", value.page))
852    {
853        propertiesRead = true;
854        OSG_NOTIFY(_notifyLevel)<<"read page \""<<value.page<<"\""<<std::endl;
855    }
856
857    if (getProperty(cur, "options", value.options))
858    {
859        propertiesRead = true;
860        OSG_NOTIFY(_notifyLevel)<<"read options \""<<value.options<<"\""<<std::endl;
861    }
862
863    osg::Vec4 bgColour;
864    if (getProperty(cur, "background", value.backgroundColor))
865    {
866        propertiesRead = true;
867        OSG_NOTIFY(_notifyLevel)<<"read background colour \""<<value.backgroundColor<<"\""<<std::endl;
868    }
869
870    if (getProperty(cur, "width", value.width))
871    {
872        propertiesRead = true;
873        OSG_NOTIFY(_notifyLevel)<<"read width \""<<value.width<<"\""<<std::endl;
874    }
875
876    if (getProperty(cur, "height", value.height))
877    {
878        propertiesRead = true;
879        OSG_NOTIFY(_notifyLevel)<<"read height \""<<value.height<<"\""<<std::endl;
880    }
881
882    if (getProperty(cur, "region", value.region))
883    {
884        propertiesRead = true;
885        value.region_in_pixel_coords = false;
886        OSG_NOTIFY(_notifyLevel)<<"read region \""<<value.region<<"\""<<std::endl;
887    }
888
889    if (getProperty(cur, "pixel_region", value.region))
890    {
891        propertiesRead = true;
892        value.region_in_pixel_coords = true;
893        OSG_NOTIFY(_notifyLevel)<<"read pixel_region \""<<value.region<<"\""<<std::endl;
894    }
895
896    std::string str;
897    if (getProperty(cur, "looping", str))
898    {
899        propertiesRead = true;
900        if (str=="ON") value.loopingMode = osg::ImageStream::LOOPING;
901        else value.loopingMode = osg::ImageStream::NO_LOOPING;
902        OSG_NOTIFY(_notifyLevel)<<"looping \""<<str<<"\""<<std::endl;
903    }
904
905    if (getProperty(cur, "fps", value.fps))
906    {
907        propertiesRead = true;
908        OSG_NOTIFY(_notifyLevel)<<"read fps \""<<value.fps<<"\""<<std::endl;
909    }
910
911    if (getProperty(cur, "duration", value.duration))
912    {
913        propertiesRead = true;
914        OSG_NOTIFY(_notifyLevel)<<"read duration \""<<value.duration<<"\""<<std::endl;
915    }
916
917    if (getProperty(cur, "paging_mode", str))
918    {
919        propertiesRead = true;
920        if (str=="PRE_LOAD_ALL_IMAGES") value.imageSequencePagingMode = osg::ImageSequence::PRE_LOAD_ALL_IMAGES;
921        else if (str=="PAGE_AND_RETAIN_IMAGES") value.imageSequencePagingMode = osg::ImageSequence::PAGE_AND_RETAIN_IMAGES;
922        else if (str=="PAGE_AND_DISCARD_USED_IMAGES") value.imageSequencePagingMode = osg::ImageSequence::PAGE_AND_DISCARD_USED_IMAGES;
923
924        OSG_NOTIFY(_notifyLevel)<<"read imageSequencePagingMode \""<<value.imageSequencePagingMode<<"\""<<std::endl;
925    }
926
927    if (getProperty(cur, "interaction_mode", str))
928    {
929        propertiesRead = true;
930
931        if (str=="PLAY_AUTOMATICALLY_LIKE_MOVIE") value.imageSequenceInteractionMode = osgPresentation::SlideShowConstructor::ImageData::PLAY_AUTOMATICALLY_LIKE_MOVIE;
932        else if (str=="USE_MOUSE_X_POSITION") value.imageSequenceInteractionMode = osgPresentation::SlideShowConstructor::ImageData::USE_MOUSE_X_POSITION;
933        else if (str=="USE_MOUSE_Y_POSITION") value.imageSequenceInteractionMode = osgPresentation::SlideShowConstructor::ImageData::USE_MOUSE_Y_POSITION;
934
935        OSG_NOTIFY(_notifyLevel)<<"read imageSequencePagingMode \""<<value.imageSequenceInteractionMode<<"\""<<std::endl;
936    }
937
938    /*
939    if (getProperty(cur, "texcoord_offset", value.texcoord_offset))
940    {
941        propertiesRead = true;
942        OSG_NOTIFY(_notifyLevel)<<"read offset \""<<value.texcoord_offset<<"\""<<std::endl;
943    }
944
945    if (getProperty(cur, "texcoord_scale", value.texcoord_scale))
946    {
947        propertiesRead = true;
948        OSG_NOTIFY(_notifyLevel)<<"read texcoord_scale \""<<value.texcoord_scale<<"\""<<std::endl;
949    }
950
951    if (getProperty(cur, "texcoord_rotate", value.texcoord_rotate))
952    {
953        propertiesRead = true;
954        OSG_NOTIFY(_notifyLevel)<<"read texcoord_rotate \""<<value.texcoord_rotate<<"\""<<std::endl;
955    }
956*/
957    return propertiesRead;
958}
959
960bool ReaderWriterP3DXML::getJumpProperties(osgDB::XmlNode*cur, osgPresentation::JumpData& jumpData) const
961{
962    bool propertyRead = false;
963
964    if (getProperty(cur, "slide_name", jumpData.slideName))
965    {
966        OSG_INFO<<"slide_name "<<jumpData.slideName<<std::endl;
967        propertyRead = true;
968    }
969
970    if (getProperty(cur, "slide", jumpData.slideNum))
971    {
972        OSG_INFO<<"slide "<<jumpData.slideNum<<std::endl;
973        propertyRead = true;
974    }
975
976    if (getProperty(cur, "layer", jumpData.layerNum))
977    {
978        OSG_INFO<<"layer "<<jumpData.layerNum<<std::endl;
979        propertyRead = true;
980    }
981
982    if (getProperty(cur, "layer_name", jumpData.layerName))
983    {
984        OSG_INFO<<"layer_name "<<jumpData.layerName<<std::endl;
985        propertyRead = true;
986    }
987
988    std::string jumpType;
989    if (getProperty(cur, "jump", jumpType))
990    {
991        OSG_INFO<<"jump "<<jumpType<<std::endl;
992        propertyRead = true;
993        jumpData.relativeJump = (jumpType=="relative") || (jumpType=="Relative") || (jumpType=="RELATIVE") ;
994    }
995
996    return propertyRead;
997}
998
999void ReaderWriterP3DXML::parseModel(osgPresentation::SlideShowConstructor& constructor, osgDB::XmlNode*cur) const
1000{
1001
1002    osgPresentation::SlideShowConstructor::PositionData positionData = constructor.getModelPositionData();
1003   bool positionRead = getProperties(cur,positionData);
1004
1005    osgPresentation::SlideShowConstructor::ModelData modelData;// = constructor.getModelData();
1006    getProperties(cur,modelData);
1007
1008    std::string filename = cur->getTrimmedContents();
1009
1010    if (!filename.empty())
1011    {
1012        constructor.addModel(filename,
1013                             positionRead ? positionData : constructor.getModelPositionData(),
1014                             modelData);
1015    }
1016}
1017
1018
1019
1020osg::TransferFunction1D* ReaderWriterP3DXML::readTransferFunctionFile(const std::string& filename, float scale) const
1021{
1022    std::string foundFile = osgDB::findDataFile(filename);
1023    if (foundFile.empty())
1024    {
1025        OSG_NOTICE<<"Error: could not find transfer function file : "<<filename<<std::endl;
1026        return 0;
1027    }
1028
1029    OSG_NOTICE<<"Reading transfer function "<<filename<<std::endl;
1030
1031    osg::TransferFunction1D::ColorMap colorMap;
1032    osgDB::ifstream fin(foundFile.c_str());
1033    while(fin)
1034    {
1035        char readline[4096];
1036        *readline = 0;
1037        fin.getline(readline, sizeof(readline));
1038
1039        if (*readline!=0)
1040        {
1041            std::stringstream str(readline);
1042
1043            float value, red, green, blue, alpha;
1044            str >> value >> red >> green >> blue >> alpha;
1045
1046            *readline = 0;
1047            str.getline(readline, sizeof(readline));
1048
1049            char* comment = readline;
1050            while(*comment==' ' || *comment=='\t' ) ++comment;
1051
1052            if (*comment!=0)
1053            {
1054                OSG_NOTICE<<"value = "<<value<<" ("<<red<<", "<<green<<", "<<blue<<", "<<alpha<<") comment = ["<<comment<<"]"<<std::endl;
1055            }
1056            else
1057            {
1058                OSG_NOTICE<<"value = "<<value<<" ("<<red<<", "<<green<<", "<<blue<<", "<<alpha<<")"<<std::endl;
1059            }
1060            colorMap[value] = osg::Vec4(red*scale,green*scale,blue*scale,alpha*scale);
1061        }
1062    }
1063
1064    if (colorMap.empty())
1065    {
1066        OSG_NOTICE<<"Error: No values read from transfer function file: "<<filename<<std::endl;
1067        return 0;
1068    }
1069
1070    osg::TransferFunction1D* tf = new osg::TransferFunction1D;
1071    tf->assign(colorMap);
1072
1073    return tf;
1074}
1075
1076
1077void ReaderWriterP3DXML::parseVolume(osgPresentation::SlideShowConstructor& constructor, osgDB::XmlNode* cur) const
1078{
1079
1080    osgPresentation::SlideShowConstructor::PositionData positionData = constructor.getModelPositionData();
1081    bool positionRead = getProperties(cur,positionData);
1082
1083    osgPresentation::SlideShowConstructor::VolumeData volumeData;
1084
1085    // check the rendering technique/shading model to use
1086    std::string technique;
1087    if (getProperty(cur, "technique", technique))
1088    {
1089        if      (technique=="standard") volumeData.shadingModel =  osgPresentation::SlideShowConstructor::VolumeData::Standard;
1090        else if (technique=="mip") volumeData.shadingModel =  osgPresentation::SlideShowConstructor::VolumeData::MaximumIntensityProjection;
1091        else if (technique=="isosurface" || technique=="iso" ) volumeData.shadingModel =  osgPresentation::SlideShowConstructor::VolumeData::Isosurface;
1092        else if (technique=="light") volumeData.shadingModel =  osgPresentation::SlideShowConstructor::VolumeData::Light;
1093    }
1094
1095    if (getProperty(cur, "alpha", volumeData.alphaValue)) {}
1096    if (getProperty(cur, "cutoff", volumeData.cutoffValue)) {}
1097    if (getProperty(cur, "region", 6, volumeData.region)) {}
1098    if (getProperty(cur, "sampleDensity", volumeData.sampleDensityValue)) {}
1099    if (getProperty(cur, "sampleDensityWhenMoving", volumeData.sampleDensityWhenMovingValue)) {}
1100
1101
1102    if (getProperty(cur, "colourModulate", volumeData.colorModulate)) {}
1103    if (getProperty(cur, "colorModulate", volumeData.colorModulate)) {}
1104
1105    std::string operation;
1106    if (getProperty(cur, "colorSpaceOperation", operation) || getProperty(cur, "colourSpaceOperation", operation))
1107    {
1108        if (operation=="NO_COLOR_SPACE_OPERATION") volumeData.colorSpaceOperation = osg::NO_COLOR_SPACE_OPERATION;
1109        else if (operation=="MODULATE_ALPHA_BY_LUMINANCE") volumeData.colorSpaceOperation = osg::MODULATE_ALPHA_BY_LUMINANCE;
1110        else if (operation=="MODULATE_ALPHA_BY_COLOR") volumeData.colorSpaceOperation = osg::MODULATE_ALPHA_BY_COLOR;
1111        else if (operation=="REPLACE_ALPHA_WITH_LUMINANCE") volumeData.colorSpaceOperation = osg::REPLACE_ALPHA_WITH_LUMINANCE;
1112        else if (operation=="REPLACE_RGB_WITH_LUMINANCE") volumeData.colorSpaceOperation = osg::REPLACE_RGB_WITH_LUMINANCE;
1113    }
1114   
1115   
1116
1117    // check for any transfer function required
1118    std::string transferFunctionFile;
1119    if (getTrimmedProperty(cur, "tf", transferFunctionFile))
1120    {
1121        volumeData.transferFunction = readTransferFunctionFile(transferFunctionFile, 1.0);
1122    }
1123
1124    if (getTrimmedProperty(cur, "tf-255", transferFunctionFile))
1125    {
1126        volumeData.transferFunction = readTransferFunctionFile(transferFunctionFile, 1.0/255.0);
1127    }
1128
1129    if (getProperty(cur, "options", volumeData.options)) {}
1130
1131    // check for draggers required
1132    std::string dragger;
1133    if (getProperty(cur, "dragger", dragger))
1134    {
1135        if (dragger=="trackball")
1136        {
1137            volumeData.useTabbedDragger = false;
1138            volumeData.useTrackballDragger = true;
1139        }
1140        if (dragger=="trackball-box")
1141        {
1142            volumeData.useTabbedDragger = true;
1143            volumeData.useTrackballDragger = true;
1144        }
1145        else
1146        {
1147            volumeData.useTabbedDragger = true;
1148            volumeData.useTrackballDragger = false;
1149        }
1150    }
1151
1152    std::string filename = cur->getTrimmedContents();
1153    if (!filename.empty())
1154    {
1155        constructor.addVolume(filename,
1156                             positionRead ? positionData : constructor.getModelPositionData(),
1157                             volumeData);
1158    }
1159}
1160
1161void ReaderWriterP3DXML::parseStereoPair(osgPresentation::SlideShowConstructor& constructor, osgDB::XmlNode*cur) const
1162{
1163
1164    OSG_INFO<<"ReaderWriterP3DXML::parseStereoPair()"<<std::endl;
1165
1166
1167    std::string filenameLeft;
1168    std::string filenameRight;
1169
1170    osgPresentation::SlideShowConstructor::PositionData positionData = constructor.getImagePositionData();
1171    bool positionRead = getProperties(cur,positionData);
1172
1173    osgPresentation::SlideShowConstructor::ImageData imageDataLeft;// = constructor.getImageData();
1174    osgPresentation::SlideShowConstructor::ImageData imageDataRight;// = constructor.getImageData();
1175
1176    getProperties(cur,imageDataLeft);
1177    getProperties(cur,imageDataRight);
1178
1179    for(osgDB::XmlNode::Children::iterator itr = cur->children.begin();
1180        itr != cur->children.end();
1181        ++itr)
1182    {
1183        osgDB::XmlNode* child = itr->get();
1184
1185        if (child->name == "image_left")
1186        {
1187            getProperties(child,imageDataLeft);
1188            filenameLeft = child->getTrimmedContents();
1189        }
1190        else if (child->name == "imagesequence_left")
1191        {
1192            imageDataLeft.imageSequence = true;
1193            getProperties(child,imageDataLeft);
1194            filenameLeft = child->getTrimmedContents();
1195        }
1196        else if (child->name == "image_right")
1197        {
1198            getProperties(child,imageDataRight);
1199            filenameRight = child->getTrimmedContents();
1200
1201            getProperties(cur,imageDataRight);
1202        }
1203        else if (child->name == "imagesequence_right")
1204        {
1205            imageDataRight.imageSequence = true;
1206            getProperties(child,imageDataRight);
1207            filenameRight = child->getTrimmedContents();
1208        }
1209    }
1210
1211    OSG_INFO<<"    filenameLeft="<<filenameLeft<<std::endl;
1212    OSG_INFO<<"    filenameRight="<<filenameRight<<std::endl;
1213
1214
1215    if (!filenameLeft.empty() && !filenameRight.empty())
1216        constructor.addStereoImagePair(filenameLeft,imageDataLeft,
1217                                       filenameRight, imageDataRight,
1218                                       positionRead ? positionData : constructor.getImagePositionData());
1219
1220}
1221
1222bool ReaderWriterP3DXML::getKeyPosition(osgDB::XmlNode*cur, osgPresentation::KeyPosition& keyPosition) const
1223{
1224    if (cur->name == "key")
1225    {
1226        return getKeyPositionInner(cur, keyPosition);
1227    }
1228    if (cur->name == "escape" ||
1229        cur->name == "esc" ||
1230        cur->name == "exit")
1231    {
1232        keyPosition.set(osgGA::GUIEventAdapter::KEY_Escape, 0.0f, 0.0f);
1233        return true;
1234    }
1235    return false;
1236}
1237
1238bool ReaderWriterP3DXML::getKeyPositionInner(osgDB::XmlNode*cur, osgPresentation::KeyPosition& keyPosition) const
1239{
1240    // x in range -1 to 1, from left to right
1241    float x = FLT_MAX;
1242    getProperty(cur, "x", x);
1243
1244    // y in range -1 to 1, from bottom to top
1245    float y = FLT_MAX;
1246    getProperty(cur, "y", y);
1247
1248    float h = FLT_MAX;
1249    if (getProperty(cur, "h", h))
1250    {
1251        // h in range 0.0 to 1, from left to right
1252        x = h*2.0f-1.0f;
1253    }
1254
1255    float v = FLT_MAX;
1256    if (getProperty(cur, "v", v))
1257    {
1258        // v in range 0.0 to 1, from bottom to top
1259        y = v*2.0f-1.0f;
1260    }
1261
1262
1263    std::string key = cur->getTrimmedContents();
1264    unsigned int keyValue = 0;
1265
1266    StringKeyMap::const_iterator itr=_stringKeyMap.find(key);
1267    if (itr != _stringKeyMap.end())
1268    {
1269        keyValue = itr->second;
1270    }
1271    else if (key.length()==1)
1272    {
1273        keyValue = key[0];
1274    }
1275    else
1276    {
1277        OSG_NOTICE<<"Warning: invalid key used in <key>"<<key<<"</key>, ignoring tag."<<std::endl;
1278        return false;
1279    }
1280
1281    keyPosition.set(keyValue,x,y);
1282    return true;
1283}
1284
1285
1286
1287
1288void ReaderWriterP3DXML::parseLayer(osgPresentation::SlideShowConstructor& constructor, osgDB::XmlNode* root) const
1289{
1290    // create a keyPosition just in case we need it.
1291    osgPresentation::KeyPosition keyPosition;
1292
1293    OSG_INFO<<std::endl<<"parseLayer"<<std::endl;
1294
1295    float totalIndent = 0.0f;
1296
1297    for(osgDB::XmlNode::Children::iterator itr = root->children.begin();
1298        itr != root->children.end();
1299        ++itr)
1300    {
1301        osgDB::XmlNode* cur = itr->get();
1302        if (cur->name == "run")
1303        {
1304            OSG_INFO<<"run ["<<cur->contents<<"]"<<std::endl;
1305            constructor.addLayerRunString(cur->contents);
1306        }
1307        else if (cur->name == "jump")
1308        {
1309            OSG_INFO<<"Parsed Jump "<<std::endl;
1310
1311            osgPresentation::JumpData jumpData;
1312            if (getJumpProperties(cur, jumpData))
1313            {
1314                OSG_INFO<<"Layer Jump "<<jumpData.relativeJump<<","<< jumpData.slideNum<<", "<<jumpData.layerNum<<std::endl;
1315
1316                constructor.setLayerJump(jumpData);
1317            }
1318        }
1319        else if (cur->name == "click_to_run")
1320        {
1321            osgPresentation::JumpData jumpData;
1322            getJumpProperties(cur, jumpData);
1323
1324            OSG_INFO<<"click_to_run ["<<cur->contents<<"]"<<std::endl;
1325            constructor.layerClickToDoOperation(cur->contents,osgPresentation::RUN, jumpData);
1326        }
1327        else if (cur->name == "click_to_load")
1328        {
1329            osgPresentation::JumpData jumpData;
1330            getJumpProperties(cur, jumpData);
1331
1332            OSG_INFO<<"click_to_load ["<<cur->contents<<"]"<<std::endl;
1333            constructor.layerClickToDoOperation(cur->contents,osgPresentation::LOAD, jumpData);
1334        }
1335
1336        else if (cur->name == "click_to_event")
1337        {
1338            osgPresentation::JumpData jumpData;
1339            getJumpProperties(cur, jumpData);
1340
1341            if (getKeyPositionInner( cur, keyPosition))
1342            {
1343                OSG_INFO<<"click_to_event ["<<keyPosition._key<<"]"<<std::endl;
1344                constructor.layerClickEventOperation(keyPosition, jumpData);
1345            }
1346        }
1347
1348        else if (cur->name == "click_to_jump")
1349        {
1350            osgPresentation::JumpData jumpData;
1351            getJumpProperties(cur, jumpData);
1352
1353            constructor.layerClickEventOperation(osgPresentation::JUMP, jumpData);
1354        }
1355
1356        else if (cur->name == "key_to_run")
1357        {
1358            int key;
1359            if (getKeyProperty(cur, "key", key))
1360            {
1361                osgPresentation::JumpData jumpData;
1362                getJumpProperties(cur, jumpData);
1363
1364                OSG_NOTICE<<"key_to_run ["<<cur->contents<<"], key="<<key<<std::endl;
1365                constructor.keyToDoOperation(osgPresentation::SlideShowConstructor::CURRENT_LAYER, key, cur->contents,osgPresentation::RUN, jumpData);
1366            }
1367        }
1368        else if (cur->name == "key_to_load")
1369        {
1370            int key;
1371            if (getKeyProperty(cur, "key", key))
1372            {
1373                osgPresentation::JumpData jumpData;
1374                getJumpProperties(cur, jumpData);
1375
1376                OSG_NOTICE<<"key_to_load ["<<cur->contents<<"]"<<std::endl;
1377                constructor.keyToDoOperation(osgPresentation::SlideShowConstructor::CURRENT_LAYER, key, cur->contents,osgPresentation::LOAD, jumpData);
1378            }
1379        }
1380
1381        else if (cur->name == "key_to_event")
1382        {
1383            int key;
1384            if (getKeyProperty(cur, "key", key))
1385            {
1386                osgPresentation::JumpData jumpData;
1387                getJumpProperties(cur, jumpData);
1388
1389                if (getKeyPositionInner( cur, keyPosition))
1390                {
1391                    OSG_NOTICE<<"key_to_event ["<<keyPosition._key<<"]"<<std::endl;
1392                    constructor.keyEventOperation(osgPresentation::SlideShowConstructor::CURRENT_LAYER, key, keyPosition, jumpData);
1393                }
1394            }
1395        }
1396
1397        else if (cur->name == "key_to_jump")
1398        {
1399            int key;
1400            if (getKeyProperty(cur, "key", key))
1401            {
1402                osgPresentation::JumpData jumpData;
1403                getJumpProperties(cur, jumpData);
1404
1405                OSG_NOTICE<<"key_to_jump"<<std::endl;
1406
1407                constructor.keyEventOperation(osgPresentation::SlideShowConstructor::CURRENT_LAYER, key, osgPresentation::JUMP, jumpData);
1408            }
1409        }
1410
1411        else if (cur->name == "newline")
1412        {
1413            constructor.translateTextCursor(osg::Vec3(0.0f,-0.05f,0.0f));
1414        }
1415        else if (cur->name == "indent")
1416        {
1417            float localIndent = 0.05f;
1418            constructor.translateTextCursor(osg::Vec3(localIndent,0.0f,0.0f));
1419            totalIndent += localIndent;
1420        }
1421        else if (cur->name == "unindent")
1422        {
1423            float localIndent = -0.05f;
1424            constructor.translateTextCursor(osg::Vec3(localIndent,0.0f,0.0f));
1425            totalIndent += localIndent;
1426        }
1427        else if (cur->name == "bullet")
1428        {
1429            OSG_INFO<<"bullet ["<<cur->contents<<"]"<<std::endl;
1430            osgPresentation::SlideShowConstructor::PositionData positionData = constructor.getTextPositionData();
1431            bool positionRead = getProperties(cur,positionData);
1432
1433            osgPresentation::SlideShowConstructor::FontData fontData = constructor.getTextFontData();
1434            bool fontRead = getProperties(cur,fontData);
1435
1436            constructor.addBullet(cur->contents,
1437                                    positionRead ? positionData : constructor.getTextPositionData(),
1438                                    fontRead ? fontData : constructor.getTextFontData());
1439        }
1440        else if (cur->name == "paragraph")
1441        {
1442            osgPresentation::SlideShowConstructor::PositionData positionData = constructor.getTextPositionData();
1443            bool positionRead = getProperties(cur,positionData);
1444
1445            osgPresentation::SlideShowConstructor::FontData fontData = constructor.getTextFontData();
1446            bool fontRead = getProperties(cur,fontData);
1447
1448            constructor.addParagraph(cur->contents,
1449                                        positionRead ? positionData : constructor.getTextPositionData(),
1450                                        fontRead ? fontData : constructor.getTextFontData());
1451        }
1452        else if (cur->name == "image")
1453        {
1454            osgPresentation::SlideShowConstructor::PositionData positionData = constructor.getImagePositionData();
1455            bool positionRead = getProperties(cur,positionData);
1456
1457            osgPresentation::SlideShowConstructor::ImageData imageData;// = constructor.getImageData();
1458            getProperties(cur,imageData);
1459
1460            constructor.addImage(cur->getTrimmedContents(),
1461                                    positionRead ? positionData : constructor.getImagePositionData(),
1462                                    imageData);
1463        }
1464        else if (cur->name == "imagesequence")
1465        {
1466            osgPresentation::SlideShowConstructor::PositionData positionData = constructor.getImagePositionData();
1467            bool positionRead = getProperties(cur,positionData);
1468
1469            osgPresentation::SlideShowConstructor::ImageData imageData;// = constructor.getImageData();
1470            imageData.imageSequence = true;
1471            getProperties(cur,imageData);
1472
1473            constructor.addImage(cur->getTrimmedContents(),
1474                                    positionRead ? positionData : constructor.getImagePositionData(),
1475                                    imageData);
1476        }
1477        else if (cur->name == "graph")
1478        {
1479            osgPresentation::SlideShowConstructor::PositionData positionData = constructor.getImagePositionData();
1480            bool positionRead = getProperties(cur,positionData);
1481
1482            osgPresentation::SlideShowConstructor::ImageData imageData;// = constructor.getImageData();
1483            getProperties(cur,imageData);
1484
1485            std::string options;
1486            getProperty(cur, "options", options);
1487
1488            constructor.addGraph(cur->getTrimmedContents(),
1489                                 positionRead ? positionData : constructor.getImagePositionData(),
1490                                 imageData);
1491        }
1492        else if (cur->name == "vnc")
1493        {
1494            osgPresentation::SlideShowConstructor::PositionData positionData = constructor.getImagePositionData();
1495            bool positionRead = getProperties(cur,positionData);
1496
1497            osgPresentation::SlideShowConstructor::ImageData imageData;// = constructor.getImageData();
1498            getProperties(cur,imageData);
1499
1500            std::string password;
1501            getProperty(cur, "password", password);
1502
1503            constructor.addVNC(cur->getTrimmedContents(),
1504                                    positionRead ? positionData : constructor.getImagePositionData(),
1505                                    imageData,
1506                                    password
1507                              );
1508        }
1509        else if (cur->name == "browser")
1510        {
1511            osgPresentation::SlideShowConstructor::PositionData positionData = constructor.getImagePositionData();
1512            bool positionRead = getProperties(cur,positionData);
1513
1514            osgPresentation::SlideShowConstructor::ImageData imageData;// = constructor.getImageData();
1515            getProperties(cur,imageData);
1516
1517            constructor.addBrowser(cur->getTrimmedContents(),
1518                                    positionRead ? positionData : constructor.getImagePositionData(),
1519                                    imageData);
1520        }
1521        else if (cur->name == "pdf")
1522        {
1523            osgPresentation::SlideShowConstructor::PositionData positionData = constructor.getImagePositionData();
1524            bool positionRead = getProperties(cur,positionData);
1525
1526            osgPresentation::SlideShowConstructor::ImageData imageData;// = constructor.getImageData();
1527            getProperties(cur,imageData);
1528
1529            constructor.addPDF(cur->getTrimmedContents(),
1530                                    positionRead ? positionData : constructor.getImagePositionData(),
1531                                    imageData);
1532        }
1533        else if (cur->name == "stereo_pair")
1534        {
1535            parseStereoPair(constructor, cur);
1536        }
1537        else if (cur->name == "model")
1538        {
1539            parseModel(constructor, cur);
1540        }
1541        else if (cur->name == "volume")
1542        {
1543            parseVolume(constructor, cur);
1544        }
1545        else if (cur->name == "duration")
1546        {
1547            constructor.setLayerDuration(osg::asciiToDouble(cur->contents.c_str()));
1548        }
1549        else if (getKeyPosition(cur, keyPosition))
1550        {
1551            constructor.addLayerKey(keyPosition);
1552        }
1553    }
1554
1555    if (totalIndent != 0.0f)
1556    {
1557        constructor.translateTextCursor(osg::Vec3(-totalIndent,0.0f,0.0f));
1558    }
1559
1560    std::string name;
1561    if (getProperty(root, "layer_name", name))
1562    {
1563        if (constructor.getCurrentLayer())
1564        {
1565            constructor.getCurrentLayer()->setUserValue("name",name);
1566            OSG_NOTICE<<"Setting current layers name "<<name<<std::endl;
1567        }
1568        else
1569        {
1570            OSG_NOTICE<<"getCurrentSlide() returns NULL, unable to set name "<<std::endl;
1571        }
1572    }
1573}
1574
1575void ReaderWriterP3DXML::parseBullets(osgPresentation::SlideShowConstructor& constructor, osgDB::XmlNode*cur, bool inheritPreviousLayers, bool defineAsBaseLayer) const
1576{
1577    constructor.addLayer(inheritPreviousLayers, defineAsBaseLayer);
1578
1579    OSG_INFO<<"bullets ["<<cur->contents<<"]"<<std::endl;
1580    osgPresentation::SlideShowConstructor::PositionData positionData = constructor.getTextPositionData();
1581    bool positionRead = getProperties(cur,positionData);
1582
1583    osgPresentation::SlideShowConstructor::FontData fontData = constructor.getTextFontData();
1584    bool fontRead = getProperties(cur,fontData);
1585
1586    constructor.addBullet(cur->contents,
1587                            positionRead ? positionData : constructor.getTextPositionData(),
1588                            fontRead ? fontData : constructor.getTextFontData());
1589}
1590
1591
1592void ReaderWriterP3DXML::parseText(osgPresentation::SlideShowConstructor& constructor, osgDB::XmlNode*cur, bool inheritPreviousLayers, bool defineAsBaseLayer) const
1593{
1594    constructor.addLayer(inheritPreviousLayers, defineAsBaseLayer);
1595
1596    OSG_INFO<<"text ["<<cur->contents<<"]"<<std::endl;
1597    osgPresentation::SlideShowConstructor::PositionData positionData = constructor.getTextPositionData();
1598    bool positionRead = getProperties(cur,positionData);
1599
1600    osgPresentation::SlideShowConstructor::FontData fontData = constructor.getTextFontData();
1601    bool fontRead = getProperties(cur,fontData);
1602
1603    constructor.addParagraph(cur->contents,
1604                            positionRead ? positionData : constructor.getTextPositionData(),
1605                            fontRead ? fontData : constructor.getTextFontData());
1606}
1607
1608void ReaderWriterP3DXML::parsePage(osgPresentation::SlideShowConstructor& constructor, osgDB::XmlNode*cur) const
1609{
1610    constructor.addSlide();
1611
1612    std::string title;
1613    getProperty(cur, "title", title);
1614
1615    std::string inherit;
1616    getProperty(cur, "inherit", inherit);
1617
1618    if (!inherit.empty() && _templateMap.count(inherit)!=0)
1619    {
1620        parseSlide(constructor, _templateMap[inherit].get(), true, false);
1621    }
1622
1623    if (!title.empty())
1624    {
1625        constructor.setSlideTitle(title,
1626                                    constructor.getTitlePositionData(),
1627                                    constructor.getTitleFontData());
1628    }
1629
1630    if (!inherit.empty() && _templateMap.count(inherit)!=0)
1631    {
1632        parseSlide(constructor, _templateMap[inherit].get(), false, true);
1633    }
1634
1635    constructor.addLayer(true,false);
1636
1637    osgPresentation::SlideShowConstructor::PositionData positionData = constructor.getTextPositionData();
1638    bool positionRead = getProperties(cur,positionData);
1639
1640    osgPresentation::SlideShowConstructor::FontData fontData = constructor.getTextFontData();
1641    bool fontRead = getProperties(cur,fontData);
1642
1643    constructor.addParagraph(cur->contents,
1644                            positionRead ? positionData : constructor.getTextPositionData(),
1645                            fontRead ? fontData : constructor.getTextFontData());
1646}
1647
1648void ReaderWriterP3DXML::parsePdfDocument(osgPresentation::SlideShowConstructor& constructor, osgDB::XmlNode*cur) const
1649{
1650    std::string title;
1651    getProperty(cur, "title", title);
1652
1653    std::string inherit;
1654    getProperty(cur, "inherit", inherit);
1655
1656    constructor.addSlide();
1657
1658    if (!inherit.empty() && _templateMap.count(inherit)!=0)
1659    {
1660        parseSlide(constructor, _templateMap[inherit].get(), true, false);
1661    }
1662
1663    if (!title.empty())
1664    {
1665        constructor.setSlideTitle(title,
1666                                    constructor.getTitlePositionData(),
1667                                    constructor.getTitleFontData());
1668    }
1669
1670    if (!inherit.empty() && _templateMap.count(inherit)!=0)
1671    {
1672        parseSlide(constructor, _templateMap[inherit].get(), false, true);
1673    }
1674
1675    constructor.addLayer(true,false);
1676
1677    osgPresentation::SlideShowConstructor::PositionData positionData = constructor.getImagePositionData();
1678    getProperties(cur,positionData);
1679
1680    osgPresentation::SlideShowConstructor::ImageData imageData;// = constructor.getImageData();
1681    imageData.page = 0;
1682    getProperties(cur,imageData);
1683
1684    osg::Image* image = constructor.addInteractiveImage(cur->contents, positionData, imageData);
1685    osgWidget::PdfImage* pdfImage = dynamic_cast<osgWidget::PdfImage*>(image);
1686    if (pdfImage)
1687    {
1688        int numPages = pdfImage->getNumOfPages();
1689        OSG_INFO<<"NumOfPages = "<<numPages<<std::endl;
1690
1691        if (numPages>1)
1692        {
1693            for(int pageNum=1; pageNum<numPages; ++pageNum)
1694            {
1695                imageData.page = pageNum;
1696
1697                constructor.addSlide();
1698
1699                if (!inherit.empty() && _templateMap.count(inherit)!=0)
1700                {
1701                    parseSlide(constructor, _templateMap[inherit].get(), true, false);
1702                }
1703
1704                if (!title.empty())
1705                {
1706                    constructor.setSlideTitle(title,
1707                                                constructor.getTitlePositionData(),
1708                                                constructor.getTitleFontData());
1709                }
1710
1711                if (!inherit.empty() && _templateMap.count(inherit)!=0)
1712                {
1713                    parseSlide(constructor, _templateMap[inherit].get(), false, true);
1714                }
1715
1716                constructor.addLayer(true,false);
1717
1718                constructor.addPDF(cur->getTrimmedContents(), positionData, imageData);
1719
1720            }
1721        }
1722    }
1723}
1724
1725void ReaderWriterP3DXML::parseSlide (osgPresentation::SlideShowConstructor& constructor, osgDB::XmlNode* root, bool parseTitles, bool parseLayers) const
1726{
1727
1728    osg::Vec4 previous_bgcolor = constructor.getBackgroundColor();
1729    osg::Vec4 previous_textcolor = constructor.getTextColor();
1730
1731    // create a keyPosition just in case we need it.
1732    osgPresentation::KeyPosition keyPosition;
1733
1734    for(osgDB::XmlNode::Children::iterator itr = root->children.begin();
1735        itr != root->children.end();
1736        ++itr)
1737    {
1738        osgDB::XmlNode* cur = itr->get();
1739
1740        if (parseTitles)
1741        {
1742            if (cur->name == "title")
1743            {
1744                osgPresentation::SlideShowConstructor::PositionData positionData = constructor.getTitlePositionData();
1745                bool positionRead = getProperties(cur,positionData);
1746
1747                osgPresentation::SlideShowConstructor::FontData fontData = constructor.getTitleFontData();
1748                bool fontRead = getProperties(cur,fontData);
1749
1750                constructor.setSlideTitle(cur->contents,
1751                                          positionRead ? positionData : constructor.getTitlePositionData(),
1752                                          fontRead ? fontData : constructor.getTitleFontData());
1753            }
1754            else if (cur->name == "background")
1755            {
1756                constructor.setSlideBackground(cur->contents);
1757
1758                std::string str;
1759                if (getProperty(cur, "hud", str))
1760                {
1761                    bool hud = (str != "off" && str != "Off" && str != "OFF");
1762                    OSG_NOTIFY(_notifyLevel)<<"background hud, str="<<str<<", hud="<<hud<<std::endl;
1763                    constructor.setSlideBackgrondHUD(hud);
1764                }
1765            }
1766            else if (cur->name == "bgcolor")
1767            {
1768                constructor.setBackgroundColor(mapStringToColor(cur->contents),true);
1769            }
1770            else if (cur->name == "textcolor")
1771            {
1772                constructor.setTextColor(mapStringToColor(cur->contents));
1773            }
1774        }
1775        if (parseLayers)
1776        {
1777            if (cur->name == "base")
1778            {
1779                constructor.addLayer(true, true);
1780                parseLayer (constructor, cur);
1781
1782            }
1783            else if (cur->name == "layer")
1784            {
1785                constructor.addLayer(true, false);
1786                parseLayer (constructor, cur);
1787            }
1788            else if (cur->name == "clean_layer")
1789            {
1790                constructor.addLayer(false, false);
1791                parseLayer (constructor, cur);
1792            }
1793            else if (cur->name == "modify_layer")
1794            {
1795                int layerNum;
1796                if (getProperty(cur, "layer", layerNum))
1797                {
1798                    constructor.selectLayer(layerNum);
1799                }
1800                else
1801                {
1802                    constructor.addLayer(true, false);
1803                }
1804
1805                parseLayer (constructor, cur);
1806            }
1807            else if (cur->name == "bullets")
1808            {
1809                parseBullets (constructor, cur,true, false);
1810            }
1811            else if (cur->name == "duration")
1812            {
1813                constructor.setSlideDuration(osg::asciiToDouble(cur->contents.c_str()));
1814            }
1815            else if (getKeyPosition(cur, keyPosition))
1816            {
1817                constructor.addSlideKey(keyPosition);
1818            }
1819        }
1820    }
1821
1822    std::string name;
1823    if (getProperty(root, "slide_name", name))
1824    {
1825        if (constructor.getCurrentSlide())
1826        {
1827            constructor.getCurrentSlide()->setUserValue("name",name);
1828            OSG_NOTICE<<"Setting current slide name "<<name<<std::endl;
1829        }
1830        else
1831        {
1832            OSG_NOTICE<<"getCurrentSlide() returns NULL, unable to set name "<<std::endl;
1833        }
1834    }
1835   
1836    constructor.setBackgroundColor(previous_bgcolor,false);
1837    constructor.setTextColor(previous_textcolor);
1838
1839    return;
1840}
1841
1842#include <iostream>
1843
1844
1845struct MyFindFileCallback : public osgDB::FindFileCallback
1846{
1847    virtual std::string findDataFile(const std::string& filename, const osgDB::Options* options, osgDB::CaseSensitivity caseSensitivity)
1848    {
1849        OSG_INFO<<std::endl<<std::endl<<"find file "<<filename<<std::endl;
1850
1851        const osgDB::FilePathList& paths = options ? options->getDatabasePathList() : osgDB::getDataFilePathList();
1852
1853        for(osgDB::FilePathList::const_iterator itr = paths.begin();
1854            itr != paths.end();
1855            ++itr)
1856        {
1857            const std::string& path = *itr;
1858            std::string newpath = osgDB::concatPaths(path, filename);
1859            if (osgDB::containsServerAddress(path))
1860            {
1861                osgDB::ReaderWriter* rw = osgDB::Registry::instance()->getReaderWriterForExtension("curl");
1862                OSG_INFO<<"  file on server "<<*itr<<", try path "<<newpath<<std::endl;
1863                OSG_INFO<<"  we have curl rw= "<<rw<<std::endl;
1864                if (rw && rw->fileExists(newpath, options))
1865                {
1866                    OSG_INFO<<"  FOUND on server "<<newpath<<std::endl;
1867                    return newpath;
1868                }
1869            }
1870            else
1871            {
1872                if(osgDB::fileExists(newpath))
1873                {
1874                    OSG_INFO<<" FOUND "<<newpath<<std::endl;
1875                    return newpath;
1876                }
1877            }
1878        }
1879
1880        return osgDB::Registry::instance()->findDataFileImplementation(filename, options, caseSensitivity);
1881    }
1882};
1883
1884class MyReadFileCallback : public virtual osgDB::ReadFileCallback
1885{
1886    public:
1887
1888        osgDB::FilePathList _paths;
1889
1890        typedef std::map< std::string, osg::ref_ptr<osg::Object> >  ObjectCache;
1891
1892        enum ObjectType
1893        {
1894            OBJECT,
1895            IMAGE,
1896            HEIGHT_FIELD,
1897            NODE,
1898            SHADER
1899        };
1900
1901        osgDB::ReaderWriter::ReadResult readLocal(ObjectType type, const std::string& filename, const osgDB::Options* options)
1902        {
1903            OSG_INFO<<"Trying local file "<<filename<<std::endl;
1904
1905            switch(type)
1906            {
1907                case(OBJECT): return osgDB::Registry::instance()->readObjectImplementation(filename,options);
1908                case(IMAGE): return osgDB::Registry::instance()->readImageImplementation(filename,options);
1909                case(HEIGHT_FIELD): return osgDB::Registry::instance()->readHeightFieldImplementation(filename,options);
1910                case(NODE): return osgDB::Registry::instance()->readNodeImplementation(filename,options);
1911                case(SHADER): return osgDB::Registry::instance()->readShaderImplementation(filename,options);
1912            }
1913            return osgDB::ReaderWriter::ReadResult::FILE_NOT_HANDLED;
1914        }
1915
1916
1917        osgDB::ReaderWriter::ReadResult readFileCache(ObjectType type, const std::string& filename, const osgDB::Options* options)
1918        {
1919
1920            osgDB::FileCache* fileCache = options ? options->getFileCache() : 0;
1921            if (!fileCache) fileCache = osgDB::Registry::instance()->getFileCache();
1922            if (!fileCache) return osgDB::ReaderWriter::ReadResult::FILE_NOT_FOUND;
1923
1924            OSG_INFO<<"Trying fileCache "<<filename<<std::endl;
1925
1926            osgDB::ReaderWriter::ReadResult result;
1927            if (fileCache && fileCache->isFileAppropriateForFileCache(filename))
1928            {
1929                if (fileCache->existsInCache(filename))
1930                {
1931                    switch(type)
1932                    {
1933                        case(OBJECT):
1934                            result = fileCache->readObject(filename, 0);
1935                            break;
1936                        case(IMAGE):
1937                            result = fileCache->readImage(filename, 0);
1938                            break;
1939                        case(HEIGHT_FIELD):
1940                            result = fileCache->readHeightField(filename, 0);
1941                            break;
1942                        case(NODE):
1943                            result = fileCache->readNode(filename,0);
1944                            break;
1945                        case(SHADER):
1946                            result = fileCache->readShader(filename, 0);
1947                            break;
1948                    }
1949
1950                    if (result.success())
1951                    {
1952                        OSG_INFO<<"   File read from FileCache."<<std::endl;
1953                        return result;
1954                    }
1955
1956                    OSG_INFO<<"   File in FileCache, but not successfully read"<<std::endl;
1957                }
1958                else
1959                {
1960                    OSG_INFO<<"   File does not exist in FileCache: "<<fileCache->createCacheFileName(filename)<<std::endl;
1961                }
1962            }
1963
1964            return osgDB::ReaderWriter::ReadResult::FILE_NOT_FOUND;
1965
1966        }
1967
1968        osgDB::ReaderWriter::ReadResult readServer(ObjectType type, const std::string& filename, const osgDB::Options* options)
1969        {
1970            OSG_INFO<<"Trying server file "<<filename<<std::endl;
1971
1972            osgDB::ReaderWriter::ReadResult result;
1973            osgDB::ReaderWriter* rw = osgDB::Registry::instance()->getReaderWriterForExtension("curl");
1974            if (!rw) return osgDB::ReaderWriter::ReadResult::FILE_NOT_HANDLED;
1975
1976            switch(type)
1977            {
1978                case(OBJECT):
1979                    result = rw->readObject(filename,options);
1980                    break;
1981                case(IMAGE):
1982                    result = rw->readImage(filename,options);
1983                    break;
1984                case(HEIGHT_FIELD):
1985                    result = rw->readHeightField(filename,options);
1986                    break;
1987                case(NODE):
1988                    result = rw->readNode(filename,options);
1989                    break;
1990                case(SHADER):
1991                    result = rw->readShader(filename,options);
1992                    break;
1993            }
1994
1995            if (result.success())
1996            {
1997                osgDB::FileCache* fileCache = options ? options->getFileCache() : 0;
1998                if (!fileCache) fileCache = osgDB::Registry::instance()->getFileCache();
1999
2000                if (fileCache && fileCache->isFileAppropriateForFileCache(filename))
2001                {
2002                    switch(type)
2003                    {
2004                        case(OBJECT):
2005                            fileCache->writeObject(*result.getObject(),filename,options);
2006                            break;
2007                        case(IMAGE):
2008                            result.getImage()->setFileName(filename);
2009                            fileCache->writeImage(*result.getImage(),filename,options);
2010                            break;
2011                        case(HEIGHT_FIELD):
2012                            fileCache->writeHeightField(*result.getHeightField(),filename,options);
2013                            break;
2014                        case(NODE):
2015                            fileCache->writeNode(*result.getNode(),filename,options);
2016                            break;
2017                        case(SHADER):
2018                            fileCache->writeShader(*result.getShader(),filename,options);
2019                            break;
2020                    }
2021                }
2022
2023                return result;
2024            }
2025            return osgDB::ReaderWriter::ReadResult::FILE_NOT_FOUND;
2026        }
2027
2028
2029        osgDB::ReaderWriter::ReadResult read(const osgDB::FilePathList& filePathList, ObjectType type, const std::string& filename, const osgDB::Options* options, bool checkLocalFiles)
2030        {
2031            // go look in http paths
2032            for(osgDB::FilePathList::const_iterator itr = filePathList.begin();
2033                itr != filePathList.end();
2034                ++itr)
2035            {
2036                const std::string& path = *itr;
2037                std::string newpath = path.empty() ? filename : osgDB::concatPaths(path, filename);
2038                osgDB::ReaderWriter::ReadResult result;
2039                if (osgDB::containsServerAddress(newpath))
2040                {
2041                    if (checkLocalFiles) result = readFileCache(type, newpath, options);
2042                    else result = readServer(type, newpath, options);
2043                }
2044                else if (checkLocalFiles && osgDB::fileExists(newpath))
2045                {
2046                    result = readLocal(type, newpath, options);
2047                }
2048
2049                if (result.success())
2050                {
2051                    OSG_INFO<<"   inserting object into file cache "<<filename<<", "<<result.getObject()<<std::endl;
2052                    _objectCache[filename] = result.getObject();
2053
2054                    options->setPluginStringData("filename",newpath);
2055                    return result;
2056                }
2057            }
2058            return osgDB::ReaderWriter::ReadResult::FILE_NOT_FOUND;
2059        }
2060
2061        osgDB::ReaderWriter::ReadResult read(ObjectType type, const std::string& filename, const osgDB::Options* options)
2062        {
2063            osgDB::FileCache* fileCache = options ? options->getFileCache() : 0;
2064            if (!fileCache) fileCache = osgDB::Registry::instance()->getFileCache();
2065            if (fileCache && !fileCache->isFileAppropriateForFileCache(filename)) fileCache = 0;
2066
2067            OSG_INFO<<"MyReadFileCallback::reading file "<<filename<<std::endl;
2068            ObjectCache::iterator itr = _objectCache.find(filename);
2069            if (itr != _objectCache.end())
2070            {
2071                // object is in cache, just retrieve it.
2072                if (itr->second.valid())
2073                {
2074                    OSG_INFO<<"File retrieved from cache, filename="<<filename<<std::endl;
2075                    return itr->second.get();
2076                }
2077                else
2078                {
2079                    OSG_INFO<<"File failed to load previously, won't attempt a second time "<<filename<<std::endl;
2080                    return osgDB::ReaderWriter::ReadResult::FILE_NOT_FOUND;
2081                }
2082            }
2083
2084            OSG_INFO<<"   MyReadFileCallback::reading file A"<<filename<<std::endl;
2085
2086            {
2087                bool checkLocalFiles = true;
2088                osgDB::ReaderWriter::ReadResult result = read(_paths, type, filename, options, checkLocalFiles);
2089                if (result.success()) return result;
2090
2091                if (options && !(options->getDatabasePathList().empty()))
2092                {
2093                    result = read(options->getDatabasePathList(), type, filename, options, checkLocalFiles);
2094                    if (result.success()) return result;
2095                }
2096
2097                result = read(osgDB::Registry::instance()->getDataFilePathList(), type, filename, options, checkLocalFiles);
2098                if (result.success()) return result;
2099            }
2100
2101            OSG_INFO<<"   MyReadFileCallback::reading file B"<<filename<<std::endl;
2102
2103            {
2104                bool checkLocalFiles = false;
2105                osgDB::ReaderWriter::ReadResult result = read(_paths, type, filename, options, checkLocalFiles);
2106                if (result.success()) return result;
2107
2108                if (options && !(options->getDatabasePathList().empty()))
2109                {
2110                    result = read(options->getDatabasePathList(), type, filename, options, checkLocalFiles);
2111                    if (result.success()) return result;
2112                }
2113
2114                result = read(osgDB::Registry::instance()->getDataFilePathList(), type, filename, options, checkLocalFiles);
2115                if (result.success()) return result;
2116            }
2117
2118            OSG_INFO<<"   MyReadFileCallback::reading file C"<<filename<<std::endl;
2119
2120            _objectCache[filename] = 0;
2121
2122            return osgDB::ReaderWriter::ReadResult::FILE_NOT_FOUND;
2123        }
2124
2125        virtual osgDB::ReaderWriter::ReadResult readObject(const std::string& filename, const osgDB::Options* options)
2126        {
2127            return read(OBJECT, filename, options);
2128        }
2129
2130        virtual osgDB::ReaderWriter::ReadResult readImage(const std::string& filename, const osgDB::Options* options)
2131        {
2132            return read(IMAGE, filename, options);
2133        }
2134
2135        virtual osgDB::ReaderWriter::ReadResult readHeightField(const std::string& filename, const osgDB::Options* options)
2136        {
2137            return read(HEIGHT_FIELD, filename, options);
2138        }
2139
2140        virtual osgDB::ReaderWriter::ReadResult readNode(const std::string& filename, const osgDB::Options* options)
2141        {
2142            return read(NODE, filename, options);
2143        }
2144
2145        virtual osgDB::ReaderWriter::ReadResult readShader(const std::string& filename, const osgDB::Options* options)
2146        {
2147            return read(SHADER, filename, options);
2148        }
2149
2150    protected:
2151        virtual ~MyReadFileCallback() {}
2152
2153        ObjectCache _objectCache;
2154};
2155
2156osgDB::ReaderWriter::ReadResult ReaderWriterP3DXML::readNode(const std::string& file,
2157                                                           const osgDB::ReaderWriter::Options* options) const
2158{
2159    OSG_INFO<<"readNode("<<file<<")"<<std::endl;
2160
2161
2162    std::string ext = osgDB::getLowerCaseFileExtension(file);
2163    if (!acceptsExtension(ext)) return ReadResult::FILE_NOT_HANDLED;
2164
2165    std::string fileName = file;
2166
2167    std::string fileNameSansExtension = osgDB::getNameLessExtension(fileName);
2168    std::string nestedExtension = osgDB::getFileExtension(fileNameSansExtension);
2169    std::string fileNameSansNestedExtension = osgDB::getNameLessExtension(fileNameSansExtension);
2170
2171    if (nestedExtension=="preview" || nestedExtension=="main")
2172    {
2173        fileName = fileNameSansNestedExtension + "." + ext;
2174        OSG_INFO<<"Removed nested extension "<<nestedExtension<<" result = "<<fileName<<std::endl;
2175    }
2176
2177    fileName = osgDB::findDataFile( fileName, options );
2178    if (fileName.empty()) return ReadResult::FILE_NOT_FOUND;
2179
2180    // code for setting up the database path so that internally referenced file are searched for on relative paths.
2181    osg::ref_ptr<osgDB::ReaderWriter::Options> local_opt = options ? static_cast<osgDB::ReaderWriter::Options*>(options->clone(osg::CopyOp::SHALLOW_COPY)) : new Options;
2182    local_opt->getDatabasePathList().push_front(osgDB::getFilePath(fileName));
2183    local_opt->setFindFileCallback(new MyFindFileCallback);
2184    local_opt->setPluginStringData("filename",file);
2185
2186    osgDB::XmlNode::Input input;
2187    input.open(fileName);
2188    input.readAllDataIntoBuffer();
2189
2190    return readNode(input, local_opt.get());
2191}
2192
2193osgDB::ReaderWriter::ReadResult ReaderWriterP3DXML::readNode(std::istream& fin, const Options* options) const
2194{
2195    osgDB::XmlNode::Input input;
2196    input.attach(fin);
2197    input.readAllDataIntoBuffer();
2198
2199    osg::ref_ptr<osgDB::ReaderWriter::Options> local_opt = options ? static_cast<osgDB::ReaderWriter::Options*>(options->clone(osg::CopyOp::SHALLOW_COPY)) : new Options;
2200    local_opt->setReadFileCallback(new MyReadFileCallback);
2201
2202    return readNode(input, local_opt.get());
2203}
2204
2205osgDB::ReaderWriter::ReadResult ReaderWriterP3DXML::readNode(osgDB::XmlNode::Input& input, osgDB::ReaderWriter::Options* options) const
2206{
2207    std::string fileName = options ? options->getPluginStringData("filename") : std::string();
2208    std::string extension = osgDB::getFileExtension(fileName);
2209    std::string fileNameSansExtension = osgDB::getNameLessExtension(fileName);
2210    std::string nestedExtension = osgDB::getFileExtension(fileNameSansExtension);
2211    std::string fileNameSansNestedExtension = osgDB::getFileExtension(fileNameSansExtension);
2212
2213    bool readOnlyHoldingPage = nestedExtension=="preview" || (options && options->getOptionString()=="preview");
2214    bool readOnlyMainPresentation = nestedExtension=="main" || (options && options->getOptionString()=="main");
2215
2216    osg::ref_ptr<osgDB::XmlNode> doc = new osgDB::XmlNode;
2217    osgDB::XmlNode* root = 0;
2218
2219    doc->read(input);
2220
2221    OSG_INFO<<"P3D xml file read, now building presentation scene graph."<<std::endl;
2222
2223#if 0
2224    std::ofstream fout("output.p3d");
2225    doc->write(fout);
2226#endif
2227
2228    if (doc == NULL )
2229    {
2230            fprintf(stderr,"Document not parsed successfully. \n");
2231            return ReadResult::FILE_NOT_HANDLED;
2232    }
2233
2234    for(osgDB::XmlNode::Children::iterator itr = doc->children.begin();
2235        itr != doc->children.end() && !root;
2236        ++itr)
2237    {
2238        if ((*itr)->name=="presentation") root = itr->get();
2239    }
2240
2241    if (root == NULL)
2242    {
2243            fprintf(stderr,"empty document\n");
2244            return ReadResult::FILE_NOT_HANDLED;
2245    }
2246
2247    if (root->name!="presentation")
2248    {
2249            fprintf(stderr,"document of the wrong type, root node != presentation");
2250            return ReadResult::FILE_NOT_HANDLED;
2251    }
2252
2253
2254    bool hasHoldingSlide = false;
2255    for(osgDB::XmlNode::Children::iterator itr = root->children.begin();
2256        itr != root->children.end() && !hasHoldingSlide;
2257        ++itr)
2258    {
2259        osgDB::XmlNode* cur = itr->get();
2260        if (cur->name == "holding_slide")
2261        {
2262            hasHoldingSlide = true;
2263        }
2264    }
2265
2266    // if we are looking for a holding slide, but one isn't present return NULL.
2267    if (readOnlyHoldingPage && !hasHoldingSlide) return 0;
2268
2269    OSG_INFO<<"hasHoldingSlide "<<hasHoldingSlide<<std::endl;
2270    OSG_INFO<<"readOnlyHoldingPage "<<readOnlyHoldingPage<<std::endl;
2271    OSG_INFO<<"readOnlyMainPresentation "<<readOnlyMainPresentation<<std::endl;
2272
2273    osg::ref_ptr<osg::Node> presentation_node;
2274
2275
2276    if (!readOnlyHoldingPage && !readOnlyMainPresentation)
2277    {
2278        if (fileName.empty()) hasHoldingSlide = false;
2279
2280        osg::ref_ptr<osg::Node> holdingslide_node = hasHoldingSlide ? parseXmlGraph(root, true, options) : 0;
2281
2282        if (holdingslide_node.valid())
2283        {
2284            double farDistance = 10000.0f;
2285
2286            osg::ref_ptr<osg::PagedLOD> pagedLOD = new osg::PagedLOD;
2287
2288            pagedLOD->setDatabaseOptions(options);
2289
2290            pagedLOD->addChild(holdingslide_node.get());
2291            pagedLOD->setRange(0,farDistance,2.0*farDistance);
2292
2293            std::string fileNameToLoadMainPresentation = fileNameSansExtension + std::string(".main.")+extension;
2294
2295            pagedLOD->setFileName(1,fileNameToLoadMainPresentation);
2296            pagedLOD->setRange(1,0.0,farDistance);
2297
2298            presentation_node = pagedLOD.get();
2299
2300        }
2301        else
2302        {
2303            presentation_node = parseXmlGraph(root, false, options);
2304        }
2305    }
2306    else
2307    {
2308        presentation_node = parseXmlGraph(root, readOnlyHoldingPage, options);
2309    }
2310
2311    if (presentation_node.valid())
2312    {
2313        if (!options || options->getPluginStringData("P3D_EVENTHANDLER")!="none")
2314        {
2315            // if (!readOnlyHoldingPage && !readOnlyMainPresentation)
2316            {
2317                osgPresentation::SlideEventHandler* seh = new osgPresentation::SlideEventHandler;
2318                seh->set(presentation_node.get());
2319                presentation_node->addEventCallback(seh);
2320            }
2321        }
2322        return presentation_node.release();
2323    }
2324    else
2325    {
2326        return osgDB::ReaderWriter::ReadResult::ERROR_IN_READING_FILE;
2327    }
2328}
2329
2330osg::Node* ReaderWriterP3DXML::parseXmlGraph(osgDB::XmlNode* root, bool readOnlyHoldingPage, osgDB::Options* options) const
2331{
2332    osgPresentation::SlideShowConstructor constructor(options);
2333
2334    // create a keyPosition just in case we need it.
2335    osgPresentation::KeyPosition keyPosition;
2336
2337    osgDB::FilePathList previousPaths = osgDB::getDataFilePathList();
2338
2339    for(osgDB::XmlNode::Children::iterator itr = root->children.begin();
2340        itr != root->children.end();
2341        ++itr)
2342    {
2343        osgDB::XmlNode* cur = itr->get();
2344
2345        if (cur->name=="env")
2346        {
2347            char* str = strdup(cur->contents.c_str());
2348            OSG_INFO<<"putenv("<<str<<")"<<std::endl;
2349            putenv(str);
2350        }
2351    }
2352
2353    std::string pathToPresentation;
2354    MyReadFileCallback* readFileCallback = options ? dynamic_cast<MyReadFileCallback*>(options->getReadFileCallback()) : 0;
2355
2356    if (options && !(options->getDatabasePathList().empty()))
2357    {
2358        pathToPresentation = options->getDatabasePathList().front();
2359
2360       if (readFileCallback) readFileCallback->_paths.push_front(pathToPresentation);
2361    }
2362
2363
2364    for(osgDB::XmlNode::Children::iterator itr = root->children.begin();
2365        itr != root->children.end();
2366        ++itr)
2367    {
2368        osgDB::XmlNode* cur = itr->get();
2369
2370        if (cur->name == "path")
2371        {
2372            std::string newpath = expandEnvVarsInFileName(cur->contents);
2373
2374            // now check if an absolue or http path
2375            std::string::size_type colonPos = newpath.find_first_of(':');
2376            std::string::size_type backslashPos = newpath.find_first_of('/');
2377            std::string::size_type forwardslashPos = newpath.find_first_of('\\');
2378            bool relativePath = colonPos == std::string::npos &&
2379                                backslashPos != 0 &&
2380                                forwardslashPos != 0;
2381
2382            if (relativePath && !pathToPresentation.empty())
2383            {
2384                newpath = osgDB::concatPaths(pathToPresentation, newpath);
2385                OSG_INFO<<"relative path = "<<cur->contents<<", newpath="<<newpath<<std::endl;
2386            }
2387            else
2388            {
2389                OSG_INFO<<"absolute path = "<<cur->contents<<", newpath="<<newpath<<std::endl;
2390            }
2391
2392            if (readFileCallback) readFileCallback->_paths.push_back(newpath);
2393            else options->getDatabasePathList().push_back(newpath);
2394        }
2395    }
2396
2397
2398    for(osgDB::XmlNode::Children::iterator itr = root->children.begin();
2399        itr != root->children.end();
2400        ++itr)
2401    {
2402        osgDB::XmlNode* cur = itr->get();
2403
2404        if (cur->name == "name")
2405        {
2406            constructor.setPresentationName(cur->contents);
2407        }
2408        else if (cur->name == "loop")
2409        {
2410            constructor.setLoopPresentation(true);
2411        }
2412        else if (cur->name == "auto")
2413        {
2414            constructor.setAutoSteppingActive(true);
2415        }
2416        else if (cur->name == "title-settings")
2417        {
2418            bool fontRead = getProperties(cur,constructor.getTitleFontDataDefault());
2419            if (fontRead)
2420            {
2421                OSG_INFO<<"Title font details read"<<std::endl;
2422            }
2423        }
2424        else if (cur->name == "text-settings")
2425        {
2426            bool fontRead = getProperties(cur,constructor.getTextFontDataDefault());
2427            if (fontRead)
2428            {
2429                OSG_INFO<<"Text font details read"<<std::endl;
2430            }
2431        }
2432        /*else if (cur->name == "ratio")
2433        {
2434            key = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1);
2435            if (key) constructor.setPresentationAspectRatio(cur->contents);
2436            xmlFree(key);
2437        }*/
2438        else if (cur->name == "path")
2439        {
2440            OSG_INFO<<"Appending search path "<<cur->contents<<std::endl;
2441            osgDB::getDataFilePathList().push_front(expandEnvVarsInFileName(cur->contents));
2442        }
2443        else if (cur->name == "bgcolor")
2444        {
2445            constructor.setBackgroundColor(mapStringToColor(cur->contents),false);
2446        }
2447        else if (cur->name == "textcolor")
2448        {
2449            constructor.setTextColor(mapStringToColor(cur->contents));
2450        }
2451        else if (cur->name == "duration")
2452        {
2453            constructor.setPresentationDuration(osg::asciiToDouble(cur->contents.c_str()));
2454        }
2455        else if (getKeyPosition(cur, keyPosition))
2456        {
2457            constructor.addPresentationKey(keyPosition);
2458        }
2459        else if (readOnlyHoldingPage && cur->name == "holding_slide")
2460        {
2461            constructor.addSlide();
2462            parseSlide (constructor, cur);
2463        }
2464        else if (!readOnlyHoldingPage && cur->name == "slide")
2465        {
2466            constructor.addSlide();
2467
2468            std::string inherit;
2469            if (getProperty(cur, "inherit", inherit) && !inherit.empty() && _templateMap.count(inherit)!=0)
2470            {
2471                parseSlide(constructor, _templateMap[inherit].get(), true, false);
2472                parseSlide (constructor, cur, true, false);
2473                parseSlide(constructor, _templateMap[inherit].get(), false, true);
2474                parseSlide (constructor, cur, false, true);
2475            }
2476            else
2477            {
2478                parseSlide (constructor, cur);
2479            }
2480        }
2481        else if (!readOnlyHoldingPage && cur->name == "modify_slide")
2482        {
2483            int slideNum;
2484            if (getProperty(cur, "slide", slideNum))
2485            {
2486                constructor.selectSlide(slideNum);
2487                parseSlide (constructor, cur);
2488            }
2489            else
2490            {
2491                constructor.addSlide();
2492            }
2493        }
2494        else if (!readOnlyHoldingPage && cur->name == "page")
2495        {
2496            parsePage (constructor, cur);
2497        }
2498        else if (!readOnlyHoldingPage && cur->name == "pdf_document")
2499        {
2500            parsePdfDocument(constructor, cur);
2501        }
2502        else if (!readOnlyHoldingPage && cur->name == "template_slide")
2503        {
2504            std::string name;
2505            if (getProperty(cur, "name", name))
2506            {
2507                _templateMap[name] = cur;
2508                std::cout<<"Defining template slide "<<name<<std::endl;
2509            }
2510        }
2511    }
2512
2513    osgDB::getDataFilePathList() = previousPaths;
2514
2515    return constructor.takePresentation();
2516}
Note: See TracBrowser for help on using the browser.