root/OpenSceneGraph/trunk/applications/present3D/ReaderWriterP3D.cpp @ 10207

Revision 10207, 70.1 kB (checked in by robert, 5 years ago)

Integrated support for relative paths, and http hosted presentations

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