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

Revision 13205, 89.7 kB (checked in by robert, 7 hours ago)

Added simple test script for osgUI's TabWidget?

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