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

Revision 10415, 70.4 kB (checked in by robert, 5 years ago)

From Mathias Froehlich, "We are currently getting issues with locale settings and some osg plugins.
Therefore I have changed all the occurances of atof by asciiToFloat or
asciiToDouble.

I believe that it is safe to do so at least for all the plugins.
Included here are also asciiToFloat conversion of environment variables. One
might argue that these should be locale dependent. But IMO these should be
set and interpreted by osg independent of the current locale.
"

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
16#include <osgDB/ReaderWriter>
17#include <osgDB/FileNameUtils>
18#include <osgDB/FileUtils>
19#include <osgDB/Registry>
20
21#include <osgWidget/PdfReader>
22
23#include <osgPresentation/SlideShowConstructor>
24
25#include <stdio.h>
26#include <string.h>
27#include <stdlib.h>
28
29#include <osgDB/XmlParser>
30
31#include <sstream>
32#include <iostream>
33
34
35/**
36 * OpenSceneGraph plugin wrapper/converter.
37 */
38class ReaderWriterP3DXML : public osgDB::ReaderWriter
39{
40public:
41    ReaderWriterP3DXML()
42    {
43        _colorMap["WHITE"]  .set(1.0f,1.0f,1.0f,1.0f);
44        _colorMap["BLACK"]  .set(0.0f,0.0f,0.0f,1.0f);
45        _colorMap["PURPLE"] .set(1.0f,0.0f,1.0f,1.0f);
46        _colorMap["BLUE"]   .set(0.0f,0.0f,1.0f,1.0f);
47        _colorMap["RED"]    .set(1.0f,0.0f,0.0f,1.0f);
48        _colorMap["CYAN"]   .set(0.0f,1.0f,1.0f,1.0f);
49        _colorMap["YELLOW"] .set(1.0f,1.0f,0.0f,1.0f);
50        _colorMap["GREEN"]  .set(0.0f,1.0f,0.0f,1.0f);
51        _colorMap["SKY"]    .set(0.2f, 0.2f, 0.4f, 1.0f);
52
53        _layoutMap["LEFT_TO_RIGHT"] = osgText::Text::LEFT_TO_RIGHT;
54        _layoutMap["RIGHT_TO_LEFT"] = osgText::Text::RIGHT_TO_LEFT;
55        _layoutMap["VERTICAL"] = osgText::Text::VERTICAL;
56
57        _alignmentMap["LEFT_TOP"] = osgText::Text::LEFT_TOP;
58        _alignmentMap["LEFT_CENTER"] = osgText::Text::LEFT_CENTER;
59        _alignmentMap["LEFT_BOTTOM"] = osgText::Text::LEFT_BOTTOM;
60
61        _alignmentMap["CENTER_TOP"] = osgText::Text::CENTER_TOP;
62        _alignmentMap["CENTER_CENTER"] = osgText::Text::CENTER_CENTER;
63        _alignmentMap["CENTER_BOTTOM"] = osgText::Text::CENTER_BOTTOM;
64
65        _alignmentMap["RIGHT_TOP"] = osgText::Text::RIGHT_TOP;
66        _alignmentMap["RIGHT_CENTER"] = osgText::Text::RIGHT_CENTER;
67        _alignmentMap["RIGHT_BOTTOM"] = osgText::Text::RIGHT_BOTTOM;
68       
69        _alignmentMap["LEFT_BASE_LINE"] = osgText::Text::LEFT_BASE_LINE;
70        _alignmentMap["CENTER_BASE_LINE"] = osgText::Text::CENTER_BASE_LINE;
71        _alignmentMap["RIGHT_BASE_LINE"] = osgText::Text::RIGHT_BASE_LINE;
72        _alignmentMap["BASE_LINE"] = osgText::Text::LEFT_BASE_LINE;
73
74        _stringKeyMap["Home"]=' ';
75        _stringKeyMap["Start"]= osgGA::GUIEventAdapter::KEY_Home;
76        _stringKeyMap["Next"]= osgGA::GUIEventAdapter::KEY_Page_Down;
77        _stringKeyMap["Previous"]=osgGA::GUIEventAdapter::KEY_Page_Up;
78        _stringKeyMap["Up"]=osgGA::GUIEventAdapter::KEY_Up;
79        _stringKeyMap["Down"]=osgGA::GUIEventAdapter::KEY_Down;
80        _stringKeyMap["End"]=osgGA::GUIEventAdapter::KEY_End;
81        _stringKeyMap["Page Down"]=osgGA::GUIEventAdapter::KEY_Page_Down;
82        _stringKeyMap["Page Up"]=osgGA::GUIEventAdapter::KEY_Page_Up;
83        _stringKeyMap["F1"]=osgGA::GUIEventAdapter::KEY_F1;
84        _stringKeyMap["F2"]=osgGA::GUIEventAdapter::KEY_F2;
85        _stringKeyMap["F3"]=osgGA::GUIEventAdapter::KEY_F3;
86        _stringKeyMap["F4"]=osgGA::GUIEventAdapter::KEY_F4;
87        _stringKeyMap["F5"]=osgGA::GUIEventAdapter::KEY_F5;
88        _stringKeyMap["F6"]=osgGA::GUIEventAdapter::KEY_F6;
89        _stringKeyMap["F7"]=osgGA::GUIEventAdapter::KEY_F7;
90        _stringKeyMap["F8"]=osgGA::GUIEventAdapter::KEY_F8;
91        _stringKeyMap["F9"]=osgGA::GUIEventAdapter::KEY_F9;
92        _stringKeyMap["F10"]=osgGA::GUIEventAdapter::KEY_F10;
93        _stringKeyMap["F11"]=osgGA::GUIEventAdapter::KEY_F11;
94        _stringKeyMap["F12"]=osgGA::GUIEventAdapter::KEY_F12;
95
96
97        _notifyLevel = osg::INFO;
98    }
99   
100    virtual const char* className() const
101    {
102        return "present3D XML Reader/Writer";
103    }
104
105    virtual bool acceptsExtension(const std::string& extension) const
106    {
107        return osgDB::equalCaseInsensitive(extension,"p3d") ||
108               osgDB::equalCaseInsensitive(extension,"xml") ;
109    }
110
111    virtual ReadResult readNode(const std::string& fileName,
112                                const osgDB::ReaderWriter::Options* options) const;
113
114    virtual ReadResult readNode(std::istream& fin, const Options* options) const;
115
116    ReadResult readNode(osgDB::XmlNode::Input& input, osgDB::ReaderWriter::Options* options) const;
117
118    void parseModel(osgPresentation::SlideShowConstructor& constructor, osgDB::XmlNode*cur) const;
119
120    void parseVolume(osgPresentation::SlideShowConstructor& constructor, osgDB::XmlNode*cur) const;
121
122    void parseStereoPair(osgPresentation::SlideShowConstructor& constructor, osgDB::XmlNode*cur) const;
123
124    void parseLayer(osgPresentation::SlideShowConstructor& constructor, osgDB::XmlNode*cur) const;
125 
126    void parseBullets(osgPresentation::SlideShowConstructor& constructor, osgDB::XmlNode*cur, bool inheritPreviousLayers, bool defineAsBaseLayer) const;
127    void parseText(osgPresentation::SlideShowConstructor& constructor, osgDB::XmlNode*cur, bool inheritPreviousLayers, bool defineAsBaseLayer) const;
128
129    void parsePage (osgPresentation::SlideShowConstructor& constructor, osgDB::XmlNode*cur) const;
130   
131    void parseSlide (osgPresentation::SlideShowConstructor& constructor, osgDB::XmlNode*cur, bool parseTitles=true, bool parseLayers=true) const;
132
133    void parsePdfDocument (osgPresentation::SlideShowConstructor& constructor, osgDB::XmlNode*cur) const;
134
135    osg::Vec4 mapStringToColor(const std::string& str) const
136    {
137        ColorMap::const_iterator itr=_colorMap.find(str);
138        if (itr!=_colorMap.end()) return itr->second;
139        osg::Vec4 color;
140        if (read(str,color)) return color;
141        else return osg::Vec4(0.0f,0.0f,0.0f,1.0f);
142    }
143   
144    inline osg::Vec4 accumulateRotation(const osg::Vec4& lhs, const osg::Vec4& rhs) const
145    {
146        osg::Quat qlhs,qrhs;
147        qlhs.makeRotate(osg::DegreesToRadians(lhs[0]),lhs[1],lhs[2],lhs[3]);
148        qrhs.makeRotate(osg::DegreesToRadians(rhs[0]),rhs[1],rhs[2],rhs[3]);
149        osg::Quat quat = qlhs*qrhs;
150        osg::Vec4d result;
151        quat.getRotate ( result[0], result[1], result[2], result[3]);
152        result[0] = osg::RadiansToDegrees(result[0]);
153        return result;
154    }
155   
156    inline bool read(const char* str, int& value) const;
157    inline bool read(const char* str, float& value) const;
158    inline bool read(const char* str, double& value) const;
159    inline bool read(const char* str, osg::Vec2& value) const;
160    inline bool read(const char* str, osg::Vec3& value) const;
161    inline bool read(const char* str, osg::Vec4& value) const;
162   
163    inline bool read(const std::string& str, int& value) const;
164    inline bool read(const std::string& str, float& value) const;
165    inline bool read(const std::string& str, double& value) const;
166    inline bool read(const std::string& str, osg::Vec2& value) const;
167    inline bool read(const std::string& str, osg::Vec3& value) const;
168    inline bool read(const std::string& str, osg::Vec4& value) const;
169
170    bool getProperty(osgDB::XmlNode*cur, const char* token) const;
171    bool getProperty(osgDB::XmlNode*cur, const char* token, int& value) const;
172    bool getProperty(osgDB::XmlNode*cur, const char* token, float& value) const;
173    bool getProperty(osgDB::XmlNode*cur, const char* token, double& value) const;
174    bool getProperty(osgDB::XmlNode*cur, const char* token, osg::Vec2& value) const;
175    bool getProperty(osgDB::XmlNode*cur, const char* token, osg::Vec3& value) const;
176    bool getProperty(osgDB::XmlNode*cur, const char* token, osg::Vec4& value) const;
177    bool getProperty(osgDB::XmlNode*cur, const char* token, std::string& value) const;
178    bool getProperty(osgDB::XmlNode*cur, const char* token, osgText::Text::Layout& value) const;
179    bool getProperty(osgDB::XmlNode*cur, const char* token, osgText::Text::AlignmentType& value) const;
180   
181    bool getProperties(osgDB::XmlNode*cur, osgPresentation::SlideShowConstructor::PositionData& value) const;
182    bool getProperties(osgDB::XmlNode*cur, osgPresentation::SlideShowConstructor::FontData& value) const;
183    bool getProperties(osgDB::XmlNode*cur, osgPresentation::SlideShowConstructor::ModelData& value) const;
184    bool getProperties(osgDB::XmlNode*cur, osgPresentation::SlideShowConstructor::ImageData& value) const;
185    bool getJumpProperties(osgDB::XmlNode*cur, bool& relativeJump, int& slideNum, int& layerNum) const;
186 
187    bool getKeyPositionInner(osgDB::XmlNode*cur, osgPresentation::KeyPosition& keyPosition) const;
188    bool getKeyPosition(osgDB::XmlNode*cur, osgPresentation::KeyPosition& keyPosition) const;
189
190    typedef std::map<std::string,osg::Vec4> ColorMap;
191    typedef std::map<std::string,osgText::Text::Layout> LayoutMap;
192    typedef std::map<std::string,osgText::Text::AlignmentType> AlignmentMap;
193    typedef std::map<std::string, unsigned int> StringKeyMap;
194
195    std::string expandEnvVarsInFileName(const std::string& filename) const;
196
197
198    ColorMap            _colorMap;
199    LayoutMap           _layoutMap;
200    AlignmentMap        _alignmentMap;
201    StringKeyMap        _stringKeyMap;
202   
203    typedef std::map<std::string, osg::ref_ptr<osgDB::XmlNode> > TemplateMap;
204    mutable TemplateMap _templateMap;
205
206    osg::NotifySeverity _notifyLevel;
207
208};
209
210// now register with Registry to instantiate the above
211// reader/writer.
212REGISTER_OSGPLUGIN(p3d, ReaderWriterP3DXML)
213
214
215std::string ReaderWriterP3DXML::expandEnvVarsInFileName(const std::string& filename) const
216{
217    std::string argument(filename);
218    std::string::size_type start_pos = argument.find("${");
219   
220    while (start_pos != std::string::npos)
221    {       
222        std::string::size_type end_pos = argument.find("}",start_pos);
223        if (start_pos != std::string::npos)
224        {
225            std::string var = argument.substr(start_pos+2, end_pos-start_pos-2);
226            const char* str = getenv(var.c_str());
227            if (str)
228            {
229                argument.erase(start_pos, end_pos-start_pos+1);
230                argument.insert(start_pos, str);
231            }
232            start_pos = argument.find("${",end_pos);
233        }
234        else
235        {
236            start_pos = std::string::npos;
237        }
238       
239    }
240   
241    return argument;
242}
243
244bool ReaderWriterP3DXML::read(const char* str, int& value) const
245{
246    if (!str) return false;
247    std::istringstream iss((const char*)str);
248    iss >> value;
249    return !iss.fail();
250}
251
252bool ReaderWriterP3DXML::read(const char* str, float& value) const
253{
254    if (!str) return false;
255    std::istringstream iss((const char*)str);
256    iss >> value;
257    return !iss.fail();
258}
259
260bool ReaderWriterP3DXML::read(const char* str, double& value) const
261{
262    if (!str) return false;
263    std::istringstream iss((const char*)str);
264    iss >> value;
265    return !iss.fail();
266}
267
268bool ReaderWriterP3DXML::read(const char* str, osg::Vec2& value) const
269{
270    if (!str) return false;
271    std::istringstream iss((const char*)str);
272    iss >> value.x() >> value.y();
273    return !iss.fail();
274}
275
276bool ReaderWriterP3DXML::read(const char* str, osg::Vec3& value) const
277{
278    if (!str) return false;
279    std::istringstream iss((const char*)str);
280    iss >> value.x() >> value.y() >> value.z();
281    return !iss.fail();
282}
283
284bool ReaderWriterP3DXML::read(const char* str, osg::Vec4& value) const
285{
286    if (!str) return false;
287    std::istringstream iss((const char*)str);
288    iss >> value.x() >> value.y() >> value.z() >> value.w();
289    return !iss.fail();
290}
291
292bool ReaderWriterP3DXML::read(const std::string& str, int& value) const
293{
294    std::istringstream iss(str);
295    iss >> value;
296    return !iss.fail();
297}
298
299bool ReaderWriterP3DXML::read(const std::string& str, float& value) const
300{
301    std::istringstream iss(str);
302    iss >> value;
303    return !iss.fail();
304}
305
306bool ReaderWriterP3DXML::read(const std::string& str, double& value) const
307{
308    std::istringstream iss(str);
309    iss >> value;
310    return !iss.fail();
311}
312
313bool ReaderWriterP3DXML::read(const std::string& str, osg::Vec2& value) const
314{
315    std::istringstream iss(str);
316    iss >> value.x() >> value.y();
317    return !iss.fail();
318}
319
320bool ReaderWriterP3DXML::read(const std::string& str, osg::Vec3& value) const
321{
322    std::istringstream iss(str);
323    iss >> value.x() >> value.y() >> value.z();
324    return !iss.fail();
325}
326
327bool ReaderWriterP3DXML::read(const std::string& str, osg::Vec4& value) const
328{
329    std::istringstream iss(str);
330    iss >> value.x() >> value.y() >> value.z() >> value.w();
331    return !iss.fail();
332}
333
334bool ReaderWriterP3DXML::getProperty(osgDB::XmlNode* cur, const char* token) const
335{
336    return cur->properties.count(token)!=0;
337}
338
339bool ReaderWriterP3DXML::getProperty(osgDB::XmlNode*cur, const char* token, int& value) const
340{
341    osgDB::XmlNode::Properties::iterator itr = cur->properties.find(token);
342    if (itr==cur->properties.end()) return false;
343    return read(itr->second,value);
344}
345
346bool ReaderWriterP3DXML::getProperty(osgDB::XmlNode*cur, const char* token, float& value) const
347{
348    osgDB::XmlNode::Properties::iterator itr = cur->properties.find(token);
349    if (itr==cur->properties.end()) return false;
350    return read(itr->second,value);
351}
352
353bool ReaderWriterP3DXML::getProperty(osgDB::XmlNode*cur, const char* token, double& value) const
354{
355    osgDB::XmlNode::Properties::iterator itr = cur->properties.find(token);
356    if (itr==cur->properties.end()) return false;
357    return read(itr->second,value);
358}
359
360bool ReaderWriterP3DXML::getProperty(osgDB::XmlNode*cur, const char* token, osg::Vec2& value) const
361{
362    osgDB::XmlNode::Properties::iterator itr = cur->properties.find(token);
363    if (itr==cur->properties.end()) return false;
364    return read(itr->second,value);
365}
366
367bool ReaderWriterP3DXML::getProperty(osgDB::XmlNode*cur, const char* token, osg::Vec3& value) const
368{
369    osgDB::XmlNode::Properties::iterator itr = cur->properties.find(token);
370    if (itr==cur->properties.end()) return false;
371    return read(itr->second,value);
372}
373
374bool ReaderWriterP3DXML::getProperty(osgDB::XmlNode*cur, const char* token, osg::Vec4& value) const
375{
376    osgDB::XmlNode::Properties::iterator itr = cur->properties.find(token);
377    if (itr==cur->properties.end()) return false;
378    return read(itr->second,value);
379}
380
381bool ReaderWriterP3DXML::getProperty(osgDB::XmlNode*cur, const char* token, std::string& value) const
382{
383    osgDB::XmlNode::Properties::iterator itr = cur->properties.find(token);
384    if (itr==cur->properties.end()) return false;
385    value = itr->second;
386    return true;
387}
388
389bool ReaderWriterP3DXML::getProperty(osgDB::XmlNode*cur, const char* token, osgText::Text::Layout& value) const
390{
391    osgDB::XmlNode::Properties::iterator pitr = cur->properties.find(token);
392    if (pitr==cur->properties.end()) return false;
393
394    const std::string& str = pitr->second;
395    LayoutMap::const_iterator itr = _layoutMap.find(str);
396    if (itr!=_layoutMap.end())
397    {
398        value = itr->second;
399    }
400    return true;
401}
402
403bool ReaderWriterP3DXML::getProperty(osgDB::XmlNode*cur, const char* token, osgText::Text::AlignmentType& value) const
404{
405    osgDB::XmlNode::Properties::iterator pitr = cur->properties.find(token);
406    if (pitr==cur->properties.end()) return false;
407
408    const std::string& str = pitr->second;
409    AlignmentMap::const_iterator itr = _alignmentMap.find(str);
410    if (itr!=_alignmentMap.end())
411    {
412        value = itr->second;
413    }
414    return true;
415}
416
417bool ReaderWriterP3DXML::getProperties(osgDB::XmlNode*cur, osgPresentation::SlideShowConstructor::PositionData& value) const
418{
419    bool propertiesRead=false;   
420
421    osg::Vec3 position(0.0f,1.0f,0.0f);
422    osg::Vec4 rotate(0.0f,0.0f,0.0f,1.0f);
423    float scale = 1.0f;
424
425    osg::Vec4 rotation(0.0f,0.0f,0.0f,1.0f);
426
427    // temporary
428    std::string str;
429
430    if (getProperty(cur, "coordinate_frame", str))
431    {
432        propertiesRead = true;
433
434        if (str=="model") value.frame = osgPresentation::SlideShowConstructor::MODEL;
435        else if (str=="slide") value.frame = osgPresentation::SlideShowConstructor::SLIDE;
436        else osg::notify(_notifyLevel)<<"Parser error - coordinate_frame=\""<<str<<"\" unrecongonized value"<<std::endl;
437       
438        osg::notify(_notifyLevel)<<"read coordinate_frame "<< ((value.frame==osgPresentation::SlideShowConstructor::MODEL) ? "osgPresentation::SlideShowConstructor::MODEL" : "osgPresentation::SlideShowConstructor::SLIDE")<<std::endl;
439    }
440
441    if (value.frame==osgPresentation::SlideShowConstructor::SLIDE)
442    {
443       
444        if (getProperty(cur, "position", str))
445        {
446            value.position.set(0.5,0.5,0.0);
447
448            propertiesRead = true;
449
450            osg::Vec2 vec2;
451            osg::Vec3 vec3;
452       
453            bool fail = false;
454            if (str=="center") value.position.set(0.5f,.5f,0.0f);
455            else if (str=="eye") value.position.set(0.0f,0.0f,1.0f);
456            else if (read(str,vec3)) value.position = vec3;
457            else if (read(str,vec2)) value.position.set(vec3.x(),vec3.y(),0.0f);
458            else fail = true;
459
460            if (fail) osg::notify(_notifyLevel)<<"Parser error - position=\""<<str<<"\" unrecongonized value"<<std::endl;
461            else osg::notify(_notifyLevel)<<"Read position="<<value.position<<std::endl;
462        }
463    }
464    else // value.frame==osgPresentation::SlideShowConstructor::MODEL
465    {
466
467        if (getProperty(cur, "position", str))
468        {
469            value.position.set(0.0,0.0,0.0);
470
471            propertiesRead = true;
472           
473            bool fail = false;
474            if (str=="center") value.position.set(0.0f,1.0f,0.0f);
475            else if (str=="eye") value.position.set(0.0f,0.0f,0.0f);
476            else if (!read(str,value.position)) fail = true;
477
478            if (fail) osg::notify(_notifyLevel)<<"Parser error - position=\""<<str<<"\" unrecongonized value"<<std::endl;
479            else osg::notify(_notifyLevel)<<"Read position="<<value.position<<std::endl;
480        }
481    }
482
483   
484    if (getProperty(cur, "scale", scale))
485    {
486        value.scale.set(scale,scale,scale);
487        propertiesRead = true;
488        osg::notify(_notifyLevel)<<"scale read "<<scale<<std::endl;
489    }
490
491    if (getProperty(cur, "scale_x", scale) || getProperty(cur, "width", scale))
492    {
493        value.scale.x() = scale;
494        propertiesRead = true;
495        osg::notify(_notifyLevel)<<"scale read_x "<<scale<<std::endl;
496    }
497
498    if (getProperty(cur, "scale_y", scale) || getProperty(cur, "height", scale))
499    {
500        value.scale.y() = scale;
501        propertiesRead = true;
502        osg::notify(_notifyLevel)<<"scale read_y "<<scale<<std::endl;
503    }
504
505    if (getProperty(cur, "scale_z", scale))
506    {
507        value.scale.z() = scale;
508        propertiesRead = true;
509        osg::notify(_notifyLevel)<<"scale read_z "<<scale<<std::endl;
510    }
511
512    if (getProperty(cur, "rotate", rotate))
513    {
514        value.rotate = rotate;
515        propertiesRead = true;
516        osg::notify(_notifyLevel)<<"rotate read "<<rotate<<std::endl;
517    }
518
519    if (getProperty(cur, "rotate1", rotate))
520    {
521        // note may need to reverse once Quat * order is sorted out.
522        value.rotate = accumulateRotation(rotate,value.rotate);
523        propertiesRead = true;
524        osg::notify(_notifyLevel)<<"rotate1 read "<<rotate<<std::endl;
525    }
526
527    if (getProperty(cur, "rotate2", rotate))
528    {
529        // note may need to reverse once Quat * order is sorted out.
530        value.rotate = accumulateRotation(rotate,value.rotate);
531        propertiesRead = true;
532        osg::notify(_notifyLevel)<<"rotate1 read "<<rotate<<std::endl;
533    }
534
535    if (getProperty(cur, "rotate3", rotate))
536    {
537        // note may need to reverse once Quat * order is sorted out.
538        value.rotate = accumulateRotation(rotate,value.rotate);
539        propertiesRead = true;
540        osg::notify(_notifyLevel)<<"rotate1 read "<<rotate<<std::endl;
541    }
542
543    if (getProperty(cur, "rotation", rotation))
544    {
545        value.rotation = rotation;
546        osg::notify(_notifyLevel)<<"rotation read "<<rotation<<std::endl;
547        propertiesRead = true;
548    }
549
550    if (getProperty(cur, "rotation1", rotation))
551    {
552        value.rotation = accumulateRotation(rotation,value.rotation);
553        osg::notify(_notifyLevel)<<"rotation1 read "<<rotation<<std::endl;
554        propertiesRead = true;
555    }
556
557    if (getProperty(cur, "rotation2", rotation))
558    {
559        value.rotation = accumulateRotation(rotation,value.rotation);
560        osg::notify(_notifyLevel)<<"rotation2 read "<<rotation<<std::endl;
561        propertiesRead = true;
562    }
563
564    if (getProperty(cur, "rotation3", rotation))
565    {
566        value.rotation = accumulateRotation(rotation,value.rotation);
567        osg::notify(_notifyLevel)<<"rotation3 read "<<rotation<<std::endl;
568        propertiesRead = true;
569    }
570
571    if (getProperty(cur, "path", str))
572    {
573   
574        value.absolute_path = false;
575        value.inverse_path = false;
576        value.path = expandEnvVarsInFileName(str);
577
578        osg::notify(_notifyLevel)<<"path read "<<str<<std::endl;
579        propertiesRead = true;
580    }
581
582    if (getProperty(cur, "camera_path", str))
583    {
584        value.absolute_path = true;
585        value.inverse_path = true;
586        value.path = expandEnvVarsInFileName(str);
587
588        osg::notify(_notifyLevel)<<"camera path read "<<str<<std::endl;
589        propertiesRead = true;
590    }
591
592    if (getProperty(cur, "path_time_offset", value.path_time_offset))
593    {
594        osg::notify(_notifyLevel)<<"read path_time_offset"<<value.path_time_offset<<std::endl;
595        propertiesRead = true;
596    }
597
598    if (getProperty(cur, "path_time_multiplier", value.path_time_multiplier))
599    {
600        osg::notify(_notifyLevel)<<"read path_time_multiplier"<<value.path_time_multiplier<<std::endl;
601        propertiesRead = true;
602    }
603
604    if (getProperty(cur, "animation_material_time_offset", value.animation_material_time_offset))
605    {
606        osg::notify(_notifyLevel)<<"read animation_material_time_offset"<<value.animation_material_time_offset<<std::endl;
607        propertiesRead = true;
608    }
609
610    if (getProperty(cur, "animation_material_time_multiplier", value.animation_material_time_multiplier))
611    {
612        osg::notify(_notifyLevel)<<"read animation_material_time_multiplier"<<value.animation_material_time_multiplier<<std::endl;
613        propertiesRead = true;
614    }
615
616    if (getProperty(cur, "animation_material", str))
617    {
618        value.animation_material_filename = str;
619
620        osg::notify(_notifyLevel)<<"animation_material read "<<str<<std::endl;
621        propertiesRead = true;
622    }
623
624    if (getProperty(cur, "animation_name", str))
625    {
626        value.animation_name = str;
627
628        osg::notify(_notifyLevel)<<"animation_name "<<str<<std::endl;
629        propertiesRead = true;
630    }
631
632    if (getProperty(cur, "fade", value.fade))
633    {
634        osg::notify(_notifyLevel)<<"fade "<<value.fade<<std::endl;
635        propertiesRead = true;
636    }
637
638    if (getProperty(cur, "path_loop_mode", str))
639    {
640        osg::notify(_notifyLevel)<<"path_loop_mode "<<str<<std::endl;
641        if (str=="LOOP") value.path_loop_mode=osg::AnimationPath::LOOP;
642        else if (str=="SWING") value.path_loop_mode=osg::AnimationPath::SWING;
643        else if (str=="NO_LOOPING") value.path_loop_mode=osg::AnimationPath::NO_LOOPING;
644        propertiesRead = true;
645    }
646
647    if (getProperty(cur, "animation_material_loop_mode", str))
648    {
649        osg::notify(_notifyLevel)<<"animation_material_loop_mode "<<str<<std::endl;
650        if (str=="LOOP") value.animation_material_loop_mode=osgPresentation::AnimationMaterial::LOOP;
651        else if (str=="SWING") value.animation_material_loop_mode=osgPresentation::AnimationMaterial::SWING;
652        else if (str=="NO_LOOPING") value.animation_material_loop_mode=osgPresentation::AnimationMaterial::NO_LOOPING;
653        propertiesRead = true;
654    }
655
656    return propertiesRead;
657}
658
659bool ReaderWriterP3DXML::getProperties(osgDB::XmlNode*cur, osgPresentation::SlideShowConstructor::FontData& value) const
660{
661    bool propertiesRead=false;   
662   
663    osg::notify(_notifyLevel)<<"in getProperties(FontData)"<<std::endl;
664
665    if (getProperty(cur, "font", value.font))
666    {
667        propertiesRead = true;
668        osg::notify(_notifyLevel)<<"read font \""<<value.font<<"\""<<std::endl;
669    }
670
671    if (getProperty(cur, "character_size", value.characterSize))
672    {
673        propertiesRead = true;
674        osg::notify(_notifyLevel)<<"read height \""<<value.characterSize<<"\""<<std::endl;
675    }
676
677    if (getProperty(cur, "layout", value.layout))
678    {
679        propertiesRead = true;
680       
681        osg::notify(_notifyLevel)<<"read layout \""<<value.layout<<"\""<<std::endl;
682    }
683
684    if (getProperty(cur, "alignment", value.alignment))
685    {
686        propertiesRead = true;
687       
688        osg::notify(_notifyLevel)<<"read alignment \""<<value.alignment<<"\""<<std::endl;
689    }
690
691    return propertiesRead;
692}
693
694bool ReaderWriterP3DXML::getProperties(osgDB::XmlNode*cur, osgPresentation::SlideShowConstructor::ModelData& value) const
695{
696    bool propertiesRead=false;   
697   
698    osg::notify(_notifyLevel)<<"in getProperties(ModelData)"<<std::endl;
699
700    if (getProperty(cur, "effect", value.effect))
701    {
702        propertiesRead = true;
703        osg::notify(_notifyLevel)<<"read effect \""<<value.effect<<"\""<<std::endl;
704    }
705
706    return propertiesRead;
707}
708
709bool ReaderWriterP3DXML::getProperties(osgDB::XmlNode*cur, osgPresentation::SlideShowConstructor::ImageData& value) const
710{
711    bool propertiesRead=false;   
712   
713    osg::notify(_notifyLevel)<<"in getProperties(ImageData)"<<std::endl;
714
715    if (getProperty(cur, "page", value.page))
716    {
717        propertiesRead = true;
718        osg::notify(_notifyLevel)<<"read page \""<<value.page<<"\""<<std::endl;
719    }
720
721    osg::Vec4 bgColour;
722    if (getProperty(cur, "background", value.backgroundColor))
723    {
724        propertiesRead = true;
725        osg::notify(_notifyLevel)<<"read background colour \""<<value.backgroundColor<<"\""<<std::endl;
726    }
727
728    if (getProperty(cur, "width", value.width))
729    {
730        propertiesRead = true;
731        osg::notify(_notifyLevel)<<"read width \""<<value.width<<"\""<<std::endl;
732    }
733
734    if (getProperty(cur, "height", value.height))
735    {
736        propertiesRead = true;
737        osg::notify(_notifyLevel)<<"read height \""<<value.height<<"\""<<std::endl;
738    }
739
740    if (getProperty(cur, "region", value.region))
741    {
742        propertiesRead = true;
743        value.region_in_pixel_coords = false;
744        osg::notify(_notifyLevel)<<"read region \""<<value.region<<"\""<<std::endl;
745    }
746
747    if (getProperty(cur, "pixel_region", value.region))
748    {
749        propertiesRead = true;
750        value.region_in_pixel_coords = true;
751        osg::notify(_notifyLevel)<<"read pixel_region \""<<value.region<<"\""<<std::endl;
752    }
753
754    std::string str;
755    if (getProperty(cur, "looping", str))
756    {
757        propertiesRead = true;
758        if (str=="ON") value.loopingMode = osg::ImageStream::LOOPING;
759        else value.loopingMode = osg::ImageStream::NO_LOOPING;
760        osg::notify(_notifyLevel)<<"looping \""<<str<<"\""<<std::endl;
761    }
762
763/*
764    if (getProperty(cur, "texcoord_offset", value.texcoord_offset))
765    {
766        propertiesRead = true;
767        osg::notify(_notifyLevel)<<"read offset \""<<value.texcoord_offset<<"\""<<std::endl;
768    }
769
770    if (getProperty(cur, "texcoord_scale", value.texcoord_scale))
771    {
772        propertiesRead = true;
773        osg::notify(_notifyLevel)<<"read texcoord_scale \""<<value.texcoord_scale<<"\""<<std::endl;
774    }
775   
776    if (getProperty(cur, "texcoord_rotate", value.texcoord_rotate))
777    {
778        propertiesRead = true;
779        osg::notify(_notifyLevel)<<"read texcoord_rotate \""<<value.texcoord_rotate<<"\""<<std::endl;
780    }
781*/
782    return propertiesRead;
783}
784
785bool ReaderWriterP3DXML::getJumpProperties(osgDB::XmlNode*cur, bool& relativeJump, int& slideNum, int& layerNum) const
786{
787    bool propertyRead = false;
788
789    if (getProperty(cur, "slide", slideNum))
790    {
791        osg::notify(osg::NOTICE)<<"slide "<<slideNum<<std::endl;
792        propertyRead = true;
793    }
794
795    if (getProperty(cur, "layer", layerNum))
796    {
797        osg::notify(osg::NOTICE)<<"layer "<<layerNum<<std::endl;
798        propertyRead = true;
799    }
800
801    std::string jumpType;
802    if (getProperty(cur, "jump", jumpType))
803    {
804        osg::notify(osg::NOTICE)<<"jump "<<jumpType<<std::endl;
805        propertyRead = true;
806        relativeJump = (jumpType=="relative") || (jumpType=="Relative") || (jumpType=="RELATIVE") ;
807    }
808
809    return propertyRead;
810}
811
812void ReaderWriterP3DXML::parseModel(osgPresentation::SlideShowConstructor& constructor, osgDB::XmlNode*cur) const
813{
814
815    osgPresentation::SlideShowConstructor::PositionData positionData = constructor.getModelPositionData();
816   bool positionRead = getProperties(cur,positionData);
817
818    osgPresentation::SlideShowConstructor::ModelData modelData;// = constructor.getModelData();
819    getProperties(cur,modelData);
820
821    std::string filename = cur->contents;
822
823    if (!filename.empty())
824    {
825        constructor.addModel(filename,
826                             positionRead ? positionData : constructor.getModelPositionData(),
827                             modelData);
828    }
829}
830
831void ReaderWriterP3DXML::parseVolume(osgPresentation::SlideShowConstructor& constructor, osgDB::XmlNode*cur) const
832{
833
834    osgPresentation::SlideShowConstructor::PositionData positionData = constructor.getModelPositionData();
835    bool positionRead = getProperties(cur,positionData);
836
837    std::string filename = cur->contents;
838
839    if (!filename.empty())
840    {
841        constructor.addVolume(filename,
842                             positionRead ? positionData : constructor.getModelPositionData());
843    }
844}
845
846void ReaderWriterP3DXML::parseStereoPair(osgPresentation::SlideShowConstructor& constructor, osgDB::XmlNode*cur) const
847{
848    std::string filenameLeft;
849    std::string filenameRight;
850
851    osgPresentation::SlideShowConstructor::PositionData positionData = constructor.getImagePositionData();
852    bool positionRead = getProperties(cur,positionData);
853
854    osgPresentation::SlideShowConstructor::ImageData imageDataLeft;// = constructor.getImageData();
855    osgPresentation::SlideShowConstructor::ImageData imageDataRight;// = constructor.getImageData();
856
857    for(osgDB::XmlNode::Children::iterator itr = cur->children.begin();
858        itr != cur->children.end();
859        ++itr)
860    {
861        osgDB::XmlNode* child = itr->get();
862
863        if (child->name == "image_left")
864        {
865            getProperties(child,imageDataLeft);
866            filenameLeft = child->name;
867        }
868        if (cur->name == "image_right")
869        {
870            getProperties(child,imageDataRight);
871            filenameRight = child->name;
872            getProperties(cur,imageDataRight);
873        }
874    }
875
876    if (!filenameLeft.empty() && !filenameRight.empty())
877        constructor.addStereoImagePair(filenameLeft,imageDataLeft,
878                                       filenameRight, imageDataRight,
879                                       positionRead ? positionData : constructor.getImagePositionData());
880
881}
882
883bool ReaderWriterP3DXML::getKeyPosition(osgDB::XmlNode*cur, osgPresentation::KeyPosition& keyPosition) const
884{
885    if (cur->name == "key")
886    {
887        return getKeyPositionInner(cur, keyPosition);
888    }
889    if (cur->name == "escape" ||
890        cur->name == "esc" ||
891        cur->name == "exit")
892    {
893        keyPosition.set(osgGA::GUIEventAdapter::KEY_Escape, 0.0f, 0.0f);
894        return true;
895    }
896    return false;
897}
898
899bool ReaderWriterP3DXML::getKeyPositionInner(osgDB::XmlNode*cur, osgPresentation::KeyPosition& keyPosition) const
900{
901    // x in range -1 to 1, from left to right
902    float x = FLT_MAX;
903    getProperty(cur, "x", x);
904
905    // y in range -1 to 1, from bottom to top
906    float y = FLT_MAX;
907    getProperty(cur, "y", y);
908
909    float h = FLT_MAX;
910    if (getProperty(cur, "h", h))
911    {
912        // h in range 0.0 to 1, from left to right
913        x = h*2.0f-1.0f;
914    }
915
916    float v = FLT_MAX;
917    if (getProperty(cur, "v", v))
918    {
919        // v in range 0.0 to 1, from bottom to top
920        y = v*2.0f-1.0f;
921    }
922
923
924    std::string key = cur->contents;
925    unsigned int keyValue = 0;
926
927    StringKeyMap::const_iterator itr=_stringKeyMap.find(key);
928    if (itr != _stringKeyMap.end())
929    {
930        keyValue = itr->second;
931    }
932    else if (key.length()==1)
933    {
934        keyValue = key[0];
935    }
936    else
937    {
938        osg::notify(osg::NOTICE)<<"Warning: unreconginized key sequence '"<<key<<"'"<<std::endl;
939    }
940
941    keyPosition.set(keyValue,x,y);
942    return true;
943}
944
945
946
947
948void ReaderWriterP3DXML::parseLayer(osgPresentation::SlideShowConstructor& constructor, osgDB::XmlNode* root) const
949{
950    // create a keyPosition just in case we need it.
951    osgPresentation::KeyPosition keyPosition;
952
953    osg::notify(osg::INFO)<<std::endl<<"parseLayer"<<std::endl;
954
955    float totalIndent = 0.0f;
956
957    for(osgDB::XmlNode::Children::iterator itr = root->children.begin();
958        itr != root->children.end();
959        ++itr)
960    {
961        osgDB::XmlNode* cur = itr->get();
962        if (cur->name == "run")
963        {
964            osg::notify(osg::INFO)<<"run ["<<cur->contents<<"]"<<std::endl;
965            constructor.addLayerRunString(cur->contents);
966        }
967        else if (cur->name == "jump")
968        {
969            osg::notify(osg::NOTICE)<<"Parsed Jump "<<std::endl;
970
971            bool relativeJump = true;
972            int slideNum = 0;
973            int layerNum = 0;
974            if (getJumpProperties(cur, relativeJump, slideNum, layerNum))
975            {
976                osg::notify(osg::NOTICE)<<"Layer Jump "<<relativeJump<<","<< slideNum<<", "<<layerNum<<std::endl;
977           
978                constructor.setLayerJump(relativeJump, slideNum, layerNum);
979            }
980        }
981        else if (cur->name == "click_to_run")
982        {
983            bool relativeJump = true;
984            int slideNum = 0;
985            int layerNum = 0;
986            getJumpProperties(cur, relativeJump, slideNum, layerNum);
987
988            osg::notify(osg::INFO)<<"click_to_run ["<<cur->contents<<"]"<<std::endl;
989            constructor.layerClickToDoOperation(cur->contents,osgPresentation::RUN, relativeJump, slideNum, layerNum);
990        }
991        else if (cur->name == "click_to_load")
992        {
993            bool relativeJump = true;
994            int slideNum = 0;
995            int layerNum = 0;
996            getJumpProperties(cur, relativeJump, slideNum, layerNum);
997
998            osg::notify(osg::INFO)<<"click_to_load ["<<cur->contents<<"]"<<std::endl;
999            constructor.layerClickToDoOperation(cur->contents,osgPresentation::LOAD, relativeJump, slideNum, layerNum);
1000        }
1001
1002        else if (cur->name == "click_to_event")
1003        {
1004            bool relativeJump = true;
1005            int slideNum = 0;
1006            int layerNum = 0;
1007            getJumpProperties(cur, relativeJump, slideNum, layerNum);
1008
1009            if (getKeyPositionInner( cur, keyPosition))
1010            {
1011                osg::notify(osg::INFO)<<"click_to_event ["<<keyPosition._key<<"]"<<std::endl;
1012                constructor.layerClickEventOperation(keyPosition, relativeJump, slideNum, layerNum);
1013            }
1014        }
1015
1016        else if (cur->name == "click_to_jump")
1017        {
1018            bool relativeJump = true;
1019            int slideNum = 0;
1020            int layerNum = 0;
1021            getJumpProperties(cur, relativeJump, slideNum, layerNum);
1022
1023            constructor.layerClickEventOperation(osgPresentation::JUMP, relativeJump, slideNum, layerNum);
1024        }
1025
1026        else if (cur->name == "newline")
1027        {
1028            constructor.translateTextCursor(osg::Vec3(0.0f,-0.05f,0.0f));
1029        }
1030        else if (cur->name == "indent")
1031        {
1032            float localIndent = 0.05f;
1033            constructor.translateTextCursor(osg::Vec3(localIndent,0.0f,0.0f));
1034            totalIndent += localIndent;
1035        }
1036        else if (cur->name == "unindent")
1037        {
1038            float localIndent = -0.05f;
1039            constructor.translateTextCursor(osg::Vec3(localIndent,0.0f,0.0f));
1040            totalIndent += localIndent;
1041        }
1042        else if (cur->name == "bullet")
1043        {
1044            osg::notify(osg::INFO)<<"bullet ["<<cur->contents<<"]"<<std::endl;
1045            osgPresentation::SlideShowConstructor::PositionData positionData = constructor.getTextPositionData();
1046            bool positionRead = getProperties(cur,positionData);
1047
1048            osgPresentation::SlideShowConstructor::FontData fontData = constructor.getTextFontData();
1049            bool fontRead = getProperties(cur,fontData);
1050
1051            constructor.addBullet(cur->contents,
1052                                    positionRead ? positionData : constructor.getTextPositionData(),
1053                                    fontRead ? fontData : constructor.getTextFontData());
1054        }
1055        else if (cur->name == "paragraph")
1056        {
1057            osgPresentation::SlideShowConstructor::PositionData positionData = constructor.getTextPositionData();
1058            bool positionRead = getProperties(cur,positionData);
1059
1060            osgPresentation::SlideShowConstructor::FontData fontData = constructor.getTextFontData();
1061            bool fontRead = getProperties(cur,fontData);
1062
1063            constructor.addParagraph(cur->contents,
1064                                        positionRead ? positionData : constructor.getTextPositionData(),
1065                                        fontRead ? fontData : constructor.getTextFontData());
1066        }
1067        else if (cur->name == "image")
1068        {
1069            osgPresentation::SlideShowConstructor::PositionData positionData = constructor.getImagePositionData();
1070            bool positionRead = getProperties(cur,positionData);
1071
1072            osgPresentation::SlideShowConstructor::ImageData imageData;// = constructor.getImageData();
1073            getProperties(cur,imageData);
1074
1075            constructor.addImage(cur->contents,
1076                                    positionRead ? positionData : constructor.getImagePositionData(),
1077                                    imageData);
1078        }
1079        else if (cur->name == "vnc")
1080        {
1081            osgPresentation::SlideShowConstructor::PositionData positionData = constructor.getImagePositionData();
1082            bool positionRead = getProperties(cur,positionData);
1083
1084            osgPresentation::SlideShowConstructor::ImageData imageData;// = constructor.getImageData();
1085            getProperties(cur,imageData);
1086
1087            constructor.addVNC(cur->contents,
1088                                    positionRead ? positionData : constructor.getImagePositionData(),
1089                                    imageData);
1090        }
1091        else if (cur->name == "browser")
1092        {
1093            osgPresentation::SlideShowConstructor::PositionData positionData = constructor.getImagePositionData();
1094            bool positionRead = getProperties(cur,positionData);
1095
1096            osgPresentation::SlideShowConstructor::ImageData imageData;// = constructor.getImageData();
1097            getProperties(cur,imageData);
1098
1099            constructor.addBrowser(cur->contents,
1100                                    positionRead ? positionData : constructor.getImagePositionData(),
1101                                    imageData);
1102        }
1103        else if (cur->name == "pdf")
1104        {
1105            osgPresentation::SlideShowConstructor::PositionData positionData = constructor.getImagePositionData();
1106            bool positionRead = getProperties(cur,positionData);
1107
1108            osgPresentation::SlideShowConstructor::ImageData imageData;// = constructor.getImageData();
1109            getProperties(cur,imageData);
1110
1111            constructor.addPDF(cur->contents,
1112                                    positionRead ? positionData : constructor.getImagePositionData(),
1113                                    imageData);
1114        }
1115        else if (cur->name == "stereo_pair")
1116        {
1117            parseStereoPair(constructor, cur);
1118        }
1119        else if (cur->name == "model")
1120        {
1121            parseModel(constructor, cur);
1122        }
1123        else if (cur->name == "volume")
1124        {
1125            parseVolume(constructor, cur);
1126        }
1127        else if (cur->name == "duration")
1128        {
1129            constructor.setLayerDuration(osg::asciiToDouble(cur->contents.c_str()));
1130        }
1131        else if (getKeyPosition(cur, keyPosition))
1132        {
1133            constructor.addLayerKey(keyPosition);
1134        }
1135    }
1136
1137    if (totalIndent != 0.0f)
1138    {
1139        constructor.translateTextCursor(osg::Vec3(-totalIndent,0.0f,0.0f));
1140    }
1141
1142}
1143
1144void ReaderWriterP3DXML::parseBullets(osgPresentation::SlideShowConstructor& constructor, osgDB::XmlNode*cur, bool inheritPreviousLayers, bool defineAsBaseLayer) const
1145{
1146    constructor.addLayer(inheritPreviousLayers, defineAsBaseLayer);
1147
1148    osg::notify(osg::INFO)<<"bullets ["<<cur->contents<<"]"<<std::endl;
1149    osgPresentation::SlideShowConstructor::PositionData positionData = constructor.getTextPositionData();
1150    bool positionRead = getProperties(cur,positionData);
1151
1152    osgPresentation::SlideShowConstructor::FontData fontData = constructor.getTextFontData();
1153    bool fontRead = getProperties(cur,fontData);
1154
1155    constructor.addBullet(cur->contents,
1156                            positionRead ? positionData : constructor.getTextPositionData(),
1157                            fontRead ? fontData : constructor.getTextFontData());
1158}
1159
1160
1161void ReaderWriterP3DXML::parseText(osgPresentation::SlideShowConstructor& constructor, osgDB::XmlNode*cur, bool inheritPreviousLayers, bool defineAsBaseLayer) const
1162{
1163    constructor.addLayer(inheritPreviousLayers, defineAsBaseLayer);
1164
1165    osg::notify(osg::INFO)<<"text ["<<cur->contents<<"]"<<std::endl;
1166    osgPresentation::SlideShowConstructor::PositionData positionData = constructor.getTextPositionData();
1167    bool positionRead = getProperties(cur,positionData);
1168
1169    osgPresentation::SlideShowConstructor::FontData fontData = constructor.getTextFontData();
1170    bool fontRead = getProperties(cur,fontData);
1171
1172    constructor.addParagraph(cur->contents,
1173                            positionRead ? positionData : constructor.getTextPositionData(),
1174                            fontRead ? fontData : constructor.getTextFontData());
1175}
1176
1177void ReaderWriterP3DXML::parsePage(osgPresentation::SlideShowConstructor& constructor, osgDB::XmlNode*cur) const
1178{
1179    constructor.addSlide();
1180
1181    std::string title;
1182    getProperty(cur, "title", title);
1183
1184    std::string inherit;
1185    getProperty(cur, "inherit", inherit);
1186
1187    if (!inherit.empty() && _templateMap.count(inherit)!=0)
1188    {
1189        parseSlide(constructor, _templateMap[inherit].get(), true, false);
1190    }
1191
1192    if (!title.empty())
1193    {
1194        constructor.setSlideTitle(title,
1195                                    constructor.getTitlePositionData(),
1196                                    constructor.getTitleFontData());
1197    }
1198
1199    if (!inherit.empty() && _templateMap.count(inherit)!=0)
1200    {
1201        parseSlide(constructor, _templateMap[inherit].get(), false, true);
1202    }
1203
1204    constructor.addLayer(true,false);
1205
1206    osgPresentation::SlideShowConstructor::PositionData positionData = constructor.getTextPositionData();
1207    bool positionRead = getProperties(cur,positionData);
1208
1209    osgPresentation::SlideShowConstructor::FontData fontData = constructor.getTextFontData();
1210    bool fontRead = getProperties(cur,fontData);
1211
1212    constructor.addParagraph(cur->contents,
1213                            positionRead ? positionData : constructor.getTextPositionData(),
1214                            fontRead ? fontData : constructor.getTextFontData());
1215}
1216
1217void ReaderWriterP3DXML::parsePdfDocument(osgPresentation::SlideShowConstructor& constructor, osgDB::XmlNode*cur) const
1218{
1219    std::string title;
1220    getProperty(cur, "title", title);
1221
1222    std::string inherit;
1223    getProperty(cur, "inherit", inherit);
1224
1225    constructor.addSlide();
1226
1227    if (!inherit.empty() && _templateMap.count(inherit)!=0)
1228    {
1229        parseSlide(constructor, _templateMap[inherit].get(), true, false);
1230    }
1231
1232    if (!title.empty())
1233    {
1234        constructor.setSlideTitle(title,
1235                                    constructor.getTitlePositionData(),
1236                                    constructor.getTitleFontData());
1237    }
1238
1239    if (!inherit.empty() && _templateMap.count(inherit)!=0)
1240    {
1241        parseSlide(constructor, _templateMap[inherit].get(), false, true);
1242    }
1243
1244    constructor.addLayer(true,false);
1245
1246    osgPresentation::SlideShowConstructor::PositionData positionData = constructor.getImagePositionData();
1247    getProperties(cur,positionData);
1248
1249    osgPresentation::SlideShowConstructor::ImageData imageData;// = constructor.getImageData();
1250    imageData.page = 0;
1251    getProperties(cur,imageData);
1252
1253    osg::Image* image = constructor.addInteractiveImage(cur->contents, positionData, imageData);
1254    osgWidget::PdfImage* pdfImage = dynamic_cast<osgWidget::PdfImage*>(image);
1255    if (pdfImage)
1256    {
1257        int numPages = pdfImage->getNumOfPages();
1258        osg::notify(osg::NOTICE)<<"NumOfPages = "<<numPages<<std::endl;
1259
1260        if (numPages>1)
1261        {
1262            for(int pageNum=1; pageNum<numPages; ++pageNum)
1263            {
1264                imageData.page = pageNum;
1265
1266                constructor.addSlide();
1267
1268                if (!inherit.empty() && _templateMap.count(inherit)!=0)
1269                {
1270                    parseSlide(constructor, _templateMap[inherit].get(), true, false);
1271                }
1272
1273                if (!title.empty())
1274                {
1275                    constructor.setSlideTitle(title,
1276                                                constructor.getTitlePositionData(),
1277                                                constructor.getTitleFontData());
1278                }
1279
1280                if (!inherit.empty() && _templateMap.count(inherit)!=0)
1281                {
1282                    parseSlide(constructor, _templateMap[inherit].get(), false, true);
1283                }
1284
1285                constructor.addLayer(true,false);
1286
1287                constructor.addPDF(cur->contents, positionData, imageData);
1288
1289            }
1290        }
1291    }
1292}
1293
1294void ReaderWriterP3DXML::parseSlide (osgPresentation::SlideShowConstructor& constructor, osgDB::XmlNode* root, bool parseTitles, bool parseLayers) const
1295{
1296
1297    osg::Vec4 previous_bgcolor = constructor.getBackgroundColor();
1298    osg::Vec4 previous_textcolor = constructor.getTextColor();
1299
1300    // create a keyPosition just in case we need it.
1301    osgPresentation::KeyPosition keyPosition;
1302
1303    for(osgDB::XmlNode::Children::iterator itr = root->children.begin();
1304        itr != root->children.end();
1305        ++itr)
1306    {
1307        osgDB::XmlNode* cur = itr->get();
1308
1309        if (parseTitles)
1310        {
1311            if (cur->name == "title")
1312            {
1313                osgPresentation::SlideShowConstructor::PositionData positionData = constructor.getTitlePositionData();
1314                bool positionRead = getProperties(cur,positionData);
1315
1316                osgPresentation::SlideShowConstructor::FontData fontData = constructor.getTitleFontData();
1317                bool fontRead = getProperties(cur,fontData);
1318
1319                constructor.setSlideTitle(cur->contents,
1320                                          positionRead ? positionData : constructor.getTitlePositionData(),
1321                                          fontRead ? fontData : constructor.getTitleFontData());
1322            }
1323            else if (cur->name == "background")
1324            {
1325                constructor.setSlideBackground(cur->contents);
1326            }
1327            else if (cur->name == "bgcolor")
1328            {
1329                constructor.setBackgroundColor(mapStringToColor(cur->contents),true);
1330            }
1331            else if (cur->name == "textcolor")
1332            {
1333                constructor.setTextColor(mapStringToColor(cur->contents));
1334            }
1335        }
1336        if (parseLayers)
1337        {
1338            if (cur->name == "base")
1339            {
1340                constructor.addLayer(true, true);
1341                parseLayer (constructor, cur);
1342            }
1343            else if (cur->name == "layer")
1344            {
1345                constructor.addLayer(true, false);
1346                parseLayer (constructor, cur);
1347            }
1348            else if (cur->name == "clean_layer")
1349            {
1350                constructor.addLayer(false, false);
1351                parseLayer (constructor, cur);
1352            }
1353            else if (cur->name == "modify_layer")
1354            {
1355                int layerNum;
1356                if (getProperty(cur, "layer", layerNum))
1357                {           
1358                    constructor.selectLayer(layerNum);
1359                }
1360                else
1361                {
1362                    constructor.addLayer(true, false);
1363                }
1364
1365                parseLayer (constructor, cur);
1366            }
1367            else if (cur->name == "bullets")
1368            {
1369                parseBullets (constructor, cur,true, false);
1370            }
1371            else if (cur->name == "duration")
1372            {
1373                constructor.setSlideDuration(osg::asciiToDouble(cur->contents.c_str()));
1374            }
1375            else if (getKeyPosition(cur, keyPosition))
1376            {
1377                constructor.addSlideKey(keyPosition);
1378            }
1379        }
1380    }
1381
1382    constructor.setBackgroundColor(previous_bgcolor,false);
1383    constructor.setTextColor(previous_textcolor);
1384
1385    return;
1386}
1387
1388#include <iostream>
1389
1390
1391struct MyFindFileCallback : public osgDB::FindFileCallback
1392{
1393    virtual std::string findDataFile(const std::string& filename, const osgDB::Options* options, osgDB::CaseSensitivity caseSensitivity)
1394    {
1395        osg::notify(osg::NOTICE)<<std::endl<<std::endl<<"find file "<<filename<<std::endl;
1396
1397        const osgDB::FilePathList& paths = options ? options->getDatabasePathList() : osgDB::getDataFilePathList();
1398
1399        for(osgDB::FilePathList::const_iterator itr = paths.begin();
1400            itr != paths.end();
1401            ++itr)
1402        {
1403            const std::string& path = *itr;
1404            std::string newpath = osgDB::concatPaths(path, filename);
1405            if (osgDB::containsServerAddress(path))
1406            {
1407                osgDB::ReaderWriter* rw = osgDB::Registry::instance()->getReaderWriterForExtension("curl");
1408                osg::notify(osg::NOTICE)<<"  file on server "<<*itr<<", try path "<<newpath<<std::endl;
1409                osg::notify(osg::NOTICE)<<"  we have curl rw= "<<rw<<std::endl;
1410                if (rw && rw->fileExists(newpath, options))
1411                {
1412                    osg::notify(osg::NOTICE)<<"  FOUND on server "<<newpath<<std::endl;
1413                    return newpath;
1414                }
1415            }
1416            else
1417            {
1418                if(osgDB::fileExists(newpath))
1419                {
1420                    osg::notify(osg::NOTICE)<<" FOUND "<<newpath<<std::endl;
1421                    return newpath;
1422                }
1423            }
1424        }
1425
1426        return osgDB::Registry::instance()->findDataFileImplementation(filename, options, caseSensitivity);
1427    }
1428};
1429
1430class MyReadFileCallback : public virtual osgDB::ReadFileCallback
1431{
1432    public:
1433
1434        osgDB::FilePathList _paths;
1435
1436        typedef std::map< std::string, osg::ref_ptr<osg::Object> >  ObjectCache;
1437
1438        enum ObjectType
1439        {
1440            OBJECT,
1441            IMAGE,
1442            HEIGHT_FIELD,
1443            NODE,
1444            SHADER
1445        };
1446
1447        osgDB::ReaderWriter::ReadResult readLocal(ObjectType type, const std::string& filename, const osgDB::Options* options)
1448        {
1449            osg::notify(osg::INFO)<<"Trying local file "<<filename<<std::endl;
1450
1451            switch(type)
1452            {
1453                case(OBJECT): return osgDB::Registry::instance()->readObjectImplementation(filename,options);
1454                case(IMAGE): return osgDB::Registry::instance()->readImageImplementation(filename,options);
1455                case(HEIGHT_FIELD): return osgDB::Registry::instance()->readHeightFieldImplementation(filename,options);
1456                case(NODE): return osgDB::Registry::instance()->readNodeImplementation(filename,options);
1457                case(SHADER): return osgDB::Registry::instance()->readShaderImplementation(filename,options);
1458            }
1459            return osgDB::ReaderWriter::ReadResult::FILE_NOT_HANDLED;
1460        }
1461
1462       
1463        osgDB::ReaderWriter::ReadResult readFileCache(ObjectType type, const std::string& filename, const osgDB::Options* options)
1464        {
1465
1466            osgDB::FileCache* fileCache = options ? options->getFileCache() : 0;
1467            if (!fileCache) fileCache = osgDB::Registry::instance()->getFileCache();
1468            if (!fileCache) return osgDB::ReaderWriter::ReadResult::FILE_NOT_FOUND;
1469
1470            osg::notify(osg::INFO)<<"Trying fileCache "<<filename<<std::endl;
1471
1472            osgDB::ReaderWriter::ReadResult result;
1473            if (fileCache && fileCache->isFileAppropriateForFileCache(filename))
1474            {
1475                if (fileCache->existsInCache(filename))
1476                {
1477                    switch(type)
1478                    {
1479                        case(OBJECT):
1480                            result = fileCache->readObject(filename, 0);
1481                            break;
1482                        case(IMAGE):
1483                            result = fileCache->readImage(filename, 0);
1484                            break;
1485                        case(HEIGHT_FIELD):
1486                            result = fileCache->readHeightField(filename, 0);
1487                            break;
1488                        case(NODE):
1489                            result = fileCache->readNode(filename,0);
1490                            break;
1491                        case(SHADER):
1492                            result = fileCache->readShader(filename, 0);
1493                            break;
1494                    }
1495
1496                    if (result.success())
1497                    {
1498                        osg::notify(osg::INFO)<<"   File read from FileCache."<<std::endl;
1499                        return result;
1500                    }
1501
1502                    osg::notify(osg::NOTICE)<<"   File in FileCache, but not successfully read"<<std::endl;
1503                }
1504                else
1505                {
1506                    osg::notify(osg::INFO)<<"   File does not exist in FileCache: "<<fileCache->createCacheFileName(filename)<<std::endl;
1507                }
1508            }
1509
1510            return osgDB::ReaderWriter::ReadResult::FILE_NOT_FOUND;
1511
1512        }
1513
1514        osgDB::ReaderWriter::ReadResult readServer(ObjectType type, const std::string& filename, const osgDB::Options* options)
1515        {
1516            osg::notify(osg::INFO)<<"Trying server file "<<filename<<std::endl;
1517
1518            osgDB::ReaderWriter::ReadResult result;
1519            osgDB::ReaderWriter* rw = osgDB::Registry::instance()->getReaderWriterForExtension("curl");
1520            if (!rw) return osgDB::ReaderWriter::ReadResult::FILE_NOT_HANDLED;
1521
1522            switch(type)
1523            {
1524                case(OBJECT):
1525                    result = rw->readObject(filename,options);
1526                    break;
1527                case(IMAGE):
1528                    result = rw->readImage(filename,options);
1529                    break;
1530                case(HEIGHT_FIELD):
1531                    result = rw->readHeightField(filename,options);
1532                    break;
1533                case(NODE):
1534                    result = rw->readNode(filename,options);
1535                    break;
1536                case(SHADER):
1537                    result = rw->readShader(filename,options);
1538                    break;
1539            }
1540
1541            if (result.success())
1542            {
1543                osgDB::FileCache* fileCache = options ? options->getFileCache() : 0;
1544                if (!fileCache) fileCache = osgDB::Registry::instance()->getFileCache();
1545
1546                if (fileCache && fileCache->isFileAppropriateForFileCache(filename))
1547                {
1548                    switch(type)
1549                    {
1550                        case(OBJECT):
1551                            fileCache->writeObject(*result.getObject(),filename,options);
1552                            break;
1553                        case(IMAGE):
1554                            result.getImage()->setFileName(filename);
1555                            fileCache->writeImage(*result.getImage(),filename,options);
1556                            break;
1557                        case(HEIGHT_FIELD):
1558                            fileCache->writeHeightField(*result.getHeightField(),filename,options);
1559                            break;
1560                        case(NODE):
1561                            fileCache->writeNode(*result.getNode(),filename,options);
1562                            break;
1563                        case(SHADER):
1564                            fileCache->writeShader(*result.getShader(),filename,options);
1565                            break;
1566                    }
1567                }
1568
1569                return result;
1570            }
1571            return osgDB::ReaderWriter::ReadResult::FILE_NOT_FOUND;
1572        }
1573
1574
1575        osgDB::ReaderWriter::ReadResult read(const osgDB::FilePathList& filePathList, ObjectType type, const std::string& filename, const osgDB::Options* options, bool checkLocalFiles)
1576        {
1577            // go look in http paths
1578            for(osgDB::FilePathList::const_iterator itr = filePathList.begin();
1579                itr != filePathList.end();
1580                ++itr)
1581            {
1582                const std::string& path = *itr;
1583                std::string newpath = path.empty() ? filename : osgDB::concatPaths(path, filename);
1584                osgDB::ReaderWriter::ReadResult result;
1585                if (osgDB::containsServerAddress(newpath))
1586                {
1587                    if (checkLocalFiles) result = readFileCache(type, newpath, options);
1588                    else result = readServer(type, newpath, options);
1589                }
1590                else if (checkLocalFiles && osgDB::fileExists(newpath))
1591                {
1592                    result = readLocal(type, newpath, options);
1593                }
1594
1595                if (result.success())
1596                {
1597                    osg::notify(osg::INFO)<<"   inserting object into file cache "<<filename<<", "<<result.getObject()<<std::endl;
1598                    _objectCache[filename] = result.getObject();
1599
1600                    options->setPluginStringData("filename",newpath);
1601                    return result;
1602                }
1603            }
1604            return osgDB::ReaderWriter::ReadResult::FILE_NOT_FOUND;
1605        }
1606
1607        osgDB::ReaderWriter::ReadResult read(ObjectType type, const std::string& filename, const osgDB::Options* options)
1608        {
1609            osgDB::FileCache* fileCache = options ? options->getFileCache() : 0;
1610            if (!fileCache) fileCache = osgDB::Registry::instance()->getFileCache();
1611            if (fileCache && !fileCache->isFileAppropriateForFileCache(filename)) fileCache = 0;
1612
1613            osg::notify(osg::INFO)<<"reading file "<<filename<<std::endl;
1614            ObjectCache::iterator itr = _objectCache.find(filename);
1615            if (itr != _objectCache.end())
1616            {
1617                // object is in cache, just retrieve it.
1618                if (itr->second.valid())
1619                {
1620                    osg::notify(osg::INFO)<<"File retrieved from cache, filename="<<filename<<std::endl;
1621                    return itr->second.get();
1622                }
1623                else
1624                {
1625                    osg::notify(osg::INFO)<<"File failed to load previously, won't attempt a second time "<<filename<<std::endl;
1626                    return osgDB::ReaderWriter::ReadResult::FILE_NOT_FOUND;
1627                }
1628            }
1629
1630            {
1631                bool checkLocalFiles = true;
1632                osgDB::ReaderWriter::ReadResult result = read(_paths, type, filename, options, checkLocalFiles);
1633                if (result.success()) return result;
1634
1635                if (options && !(options->getDatabasePathList().empty()))
1636                {
1637                    result = read(options->getDatabasePathList(), type, filename, options, checkLocalFiles);
1638                    if (result.success()) return result;
1639                }
1640
1641                result = read(osgDB::Registry::instance()->getDataFilePathList(), type, filename, options, checkLocalFiles);
1642                if (result.success()) return result;
1643            }
1644
1645            {
1646                bool checkLocalFiles = false;
1647                osgDB::ReaderWriter::ReadResult result = read(_paths, type, filename, options, checkLocalFiles);
1648                if (result.success()) return result;
1649
1650                if (options && !(options->getDatabasePathList().empty()))
1651                {
1652                    result = read(options->getDatabasePathList(), type, filename, options, checkLocalFiles);
1653                    if (result.success()) return result;
1654                }
1655
1656                result = read(osgDB::Registry::instance()->getDataFilePathList(), type, filename, options, checkLocalFiles);
1657                if (result.success()) return result;
1658            }
1659
1660            _objectCache[filename] = 0;
1661
1662            return osgDB::ReaderWriter::ReadResult::FILE_NOT_FOUND;
1663        }
1664
1665        virtual osgDB::ReaderWriter::ReadResult readObject(const std::string& filename, const osgDB::Options* options)
1666        {
1667            return read(OBJECT, filename, options);
1668        }
1669
1670        virtual osgDB::ReaderWriter::ReadResult readImage(const std::string& filename, const osgDB::Options* options)
1671        {
1672            return read(IMAGE, filename, options);
1673        }
1674
1675        virtual osgDB::ReaderWriter::ReadResult readHeightField(const std::string& filename, const osgDB::Options* options)
1676        {
1677            return read(HEIGHT_FIELD, filename, options);
1678        }
1679
1680        virtual osgDB::ReaderWriter::ReadResult readNode(const std::string& filename, const osgDB::Options* options)
1681        {
1682            return read(NODE, filename, options);
1683        }
1684
1685        virtual osgDB::ReaderWriter::ReadResult readShader(const std::string& filename, const osgDB::Options* options)
1686        {
1687            return read(SHADER, filename, options);
1688        }
1689
1690    protected:
1691        virtual ~MyReadFileCallback() {}
1692
1693        ObjectCache _objectCache;
1694};
1695
1696osgDB::ReaderWriter::ReadResult ReaderWriterP3DXML::readNode(const std::string& file,
1697                                                           const osgDB::ReaderWriter::Options* options) const
1698{
1699    std::string ext = osgDB::getLowerCaseFileExtension(file);
1700    if (!acceptsExtension(ext)) return ReadResult::FILE_NOT_HANDLED;
1701
1702    std::string fileName = osgDB::findDataFile( file );
1703    if (fileName.empty()) return ReadResult::FILE_NOT_FOUND;
1704
1705    // code for setting up the database path so that internally referenced file are searched for on relative paths.
1706    osg::ref_ptr<osgDB::ReaderWriter::Options> local_opt = options ? static_cast<osgDB::ReaderWriter::Options*>(options->clone(osg::CopyOp::SHALLOW_COPY)) : new Options;
1707    local_opt->getDatabasePathList().push_front(osgDB::getFilePath(fileName));
1708    //local_opt->setFindFileCallback(new MyFindFileCallback);
1709    local_opt->setReadFileCallback(new MyReadFileCallback);
1710
1711    osgDB::XmlNode::Input input;
1712    input.open(fileName);
1713    input.readAllDataIntoBuffer();
1714
1715    return readNode(input, local_opt.get());
1716}
1717
1718osgDB::ReaderWriter::ReadResult ReaderWriterP3DXML::readNode(std::istream& fin, const Options* options) const
1719{
1720    osgDB::XmlNode::Input input;
1721    input.attach(fin);
1722    input.readAllDataIntoBuffer();
1723
1724    osg::ref_ptr<osgDB::ReaderWriter::Options> local_opt = options ? static_cast<osgDB::ReaderWriter::Options*>(options->clone(osg::CopyOp::SHALLOW_COPY)) : new Options;
1725    //local_opt->setFindFileCallback(new MyFindFileCallback);
1726    local_opt->setReadFileCallback(new MyReadFileCallback);
1727
1728    return readNode(input, local_opt.get());
1729}
1730
1731osgDB::ReaderWriter::ReadResult ReaderWriterP3DXML::readNode(osgDB::XmlNode::Input& input, osgDB::ReaderWriter::Options* options) const
1732{
1733    bool readOnlyHoldingPage = options ? options->getOptionString()=="holding_slide" : false;
1734
1735    // create a keyPosition just in case we need it.
1736    osgPresentation::KeyPosition keyPosition;
1737
1738    osg::ref_ptr<osgDB::XmlNode> doc = new osgDB::XmlNode;
1739    osgDB::XmlNode* root = 0;
1740
1741
1742    doc->read(input);
1743
1744    osg::notify(osg::INFO)<<"P3D xml file read, now building presentation scene graph."<<std::endl;
1745
1746    // doc->write(std::cout);
1747
1748    if (doc == NULL )
1749    {
1750            fprintf(stderr,"Document not parsed successfully. \n");
1751            return ReadResult::FILE_NOT_HANDLED;
1752    }
1753
1754    for(osgDB::XmlNode::Children::iterator itr = doc->children.begin();
1755        itr != doc->children.end() && !root;
1756        ++itr)
1757    {
1758        if ((*itr)->name=="presentation") root = itr->get();
1759    }
1760
1761    if (root == NULL)
1762    {
1763            fprintf(stderr,"empty document\n");
1764            return ReadResult::FILE_NOT_HANDLED;
1765    }
1766
1767    if (root->name!="presentation")
1768    {
1769            fprintf(stderr,"document of the wrong type, root node != presentation");
1770            return ReadResult::FILE_NOT_HANDLED;
1771    }
1772
1773    osgPresentation::SlideShowConstructor constructor(options);
1774
1775    osgDB::FilePathList previousPaths = osgDB::getDataFilePathList();
1776
1777    bool readSlide = false;
1778
1779
1780    for(osgDB::XmlNode::Children::iterator itr = root->children.begin();
1781        itr != root->children.end();
1782        ++itr)
1783    {
1784        osgDB::XmlNode* cur = itr->get();
1785
1786        if (cur->name=="env")
1787        {
1788            char* str = strdup(cur->contents.c_str());
1789            osg::notify(osg::INFO)<<"putenv("<<str<<")"<<std::endl;
1790            putenv(str);
1791        }
1792    }
1793
1794    std::string pathToPresentation;
1795    MyReadFileCallback* readFileCallback = options ? dynamic_cast<MyReadFileCallback*>(options->getReadFileCallback()) : 0;
1796
1797    if (options && !(options->getDatabasePathList().empty()))
1798    {
1799        pathToPresentation = options->getDatabasePathList().front();
1800
1801       if (readFileCallback) readFileCallback->_paths.push_front(pathToPresentation);
1802    }
1803
1804
1805    for(osgDB::XmlNode::Children::iterator itr = root->children.begin();
1806        itr != root->children.end();
1807        ++itr)
1808    {
1809        osgDB::XmlNode* cur = itr->get();
1810
1811        if (cur->name == "path")
1812        {
1813            std::string newpath = expandEnvVarsInFileName(cur->contents);
1814
1815            // now check if an absolue or http path
1816            std::string::size_type colonPos = newpath.find_first_of(':');
1817            std::string::size_type backslashPos = newpath.find_first_of('/');
1818            std::string::size_type forwardslashPos = newpath.find_first_of('\\');
1819            bool relativePath = colonPos == std::string::npos &&
1820                                backslashPos != 0 &&
1821                                forwardslashPos != 0;
1822
1823            if (relativePath && !pathToPresentation.empty())
1824            {
1825                newpath = osgDB::concatPaths(pathToPresentation, newpath);
1826                osg::notify(osg::NOTICE)<<"relative path = "<<cur->contents<<", newpath="<<newpath<<std::endl;
1827            }
1828            else
1829            {
1830                osg::notify(osg::NOTICE)<<"absolute path = "<<cur->contents<<", newpath="<<newpath<<std::endl;
1831            }
1832
1833            if (readFileCallback) readFileCallback->_paths.push_back(newpath);
1834            else options->getDatabasePathList().push_back(newpath);
1835        }
1836    }
1837
1838
1839    for(osgDB::XmlNode::Children::iterator itr = root->children.begin();
1840        itr != root->children.end();
1841        ++itr)
1842    {
1843        osgDB::XmlNode* cur = itr->get();
1844
1845        if (cur->name == "name")
1846        {
1847            constructor.setPresentationName(cur->contents);
1848        }
1849        else if (cur->name == "loop")
1850        {
1851            constructor.setLoopPresentation(true);
1852        }
1853        else if (cur->name == "auto")
1854        {
1855            constructor.setAutoSteppingActive(true);
1856        }
1857        else if (cur->name == "title-settings")
1858        {
1859            bool fontRead = getProperties(cur,constructor.getTitleFontDataDefault());
1860            if (fontRead)
1861            {
1862                osg::notify(osg::INFO)<<"Title font details read"<<std::endl;
1863            }
1864        }
1865        else if (cur->name == "text-settings")
1866        {
1867            bool fontRead = getProperties(cur,constructor.getTextFontDataDefault());
1868            if (fontRead)
1869            {
1870                osg::notify(osg::INFO)<<"Text font details read"<<std::endl;
1871            }
1872        }
1873        /*else if (cur->name == "ratio")
1874        {
1875            key = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1);
1876            if (key) constructor.setPresentationAspectRatio(cur->contents);
1877            xmlFree(key);
1878        }*/
1879        else if (cur->name == "path")
1880        {
1881            osg::notify(osg::INFO)<<"Appending search path "<<cur->contents<<std::endl;
1882            osgDB::getDataFilePathList().push_front(expandEnvVarsInFileName(cur->contents));
1883        }
1884        else if (cur->name == "bgcolor")
1885        {
1886            constructor.setBackgroundColor(mapStringToColor(cur->contents),false);
1887        }
1888        else if (cur->name == "textcolor")
1889        {
1890            constructor.setTextColor(mapStringToColor(cur->contents));
1891        }
1892        else if (cur->name == "duration")
1893        {
1894            constructor.setPresentationDuration(osg::asciiToDouble(cur->contents.c_str()));
1895        }
1896        else if (getKeyPosition(cur, keyPosition))
1897        {
1898            constructor.addPresentationKey(keyPosition);
1899        }
1900        else if (readOnlyHoldingPage && cur->name == "holding_slide")
1901        {
1902            readSlide = true;
1903            constructor.addSlide();
1904            parseSlide (constructor, cur);
1905        }
1906        else if (!readOnlyHoldingPage && cur->name == "slide")
1907        {
1908            readSlide = true;
1909            constructor.addSlide();
1910
1911            std::string inherit;
1912            if (getProperty(cur, "inherit", inherit) && !inherit.empty() && _templateMap.count(inherit)!=0)
1913            {
1914                parseSlide(constructor, _templateMap[inherit].get(), true, false);
1915                parseSlide (constructor, cur, true, false);
1916                parseSlide(constructor, _templateMap[inherit].get(), false, true);
1917                parseSlide (constructor, cur, false, true);
1918            }
1919            else
1920            {
1921                parseSlide (constructor, cur);
1922            }
1923        }
1924        else if (!readOnlyHoldingPage && cur->name == "modify_slide")
1925        {
1926            readSlide = true;
1927            int slideNum;
1928            if (getProperty(cur, "slide", slideNum))
1929            {           
1930                constructor.selectSlide(slideNum);
1931                parseSlide (constructor, cur);
1932            }
1933            else
1934            {
1935                constructor.addSlide();
1936            }
1937        }
1938        else if (!readOnlyHoldingPage && cur->name == "page")
1939        {
1940            readSlide = true;
1941            parsePage (constructor, cur);
1942        }
1943        else if (!readOnlyHoldingPage && cur->name == "pdf_document")
1944        {
1945            readSlide = true;
1946            parsePdfDocument(constructor, cur);
1947        }
1948        else if (!readOnlyHoldingPage && cur->name == "template_slide")
1949        {
1950            readSlide = true;
1951            std::string name;
1952            if (getProperty(cur, "name", name))
1953            {           
1954                _templateMap[name] = cur;
1955                std::cout<<"Defining template slide "<<name<<std::endl;
1956            }
1957        }
1958    }
1959
1960
1961    osgDB::getDataFilePathList() = previousPaths;
1962   
1963
1964    osg::ref_ptr<osg::Node> presentation_node = constructor.takePresentation();
1965
1966
1967    if (!options || options->getPluginStringData("P3D_EVENTHANDLER")!="none")
1968    {
1969        osgPresentation::SlideEventHandler* seh = new osgPresentation::SlideEventHandler;
1970        seh->set(presentation_node.get());
1971        presentation_node->setEventCallback(seh);
1972    }
1973    return presentation_node.release();
1974}
Note: See TracBrowser for help on using the browser.