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

Revision 13204, 89.8 kB (checked in by robert, 4 days ago)

Moved widgets from VolumeEditorWidget? to TransferFunctionWidget?, and widget utilities into WidgetUtils?.

  • 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        osg::ColorSpaceOperation colorOp = osg::NO_COLOUR_SPACE_OPERATION;
1109        if (operation=="NO_COLOUR_SPACE_OPERATION") volumeData.colorSpaceOperation = osg::NO_COLOUR_SPACE_OPERATION;
1110        else if (operation=="MODULATE_ALPHA_BY_LUMINANCE") volumeData.colorSpaceOperation = osg::MODULATE_ALPHA_BY_LUMINANCE;
1111        else if (operation=="MODULATE_ALPHA_BY_COLOUR") volumeData.colorSpaceOperation = osg::MODULATE_ALPHA_BY_COLOUR;
1112        else if (operation=="REPLACE_ALPHA_WITH_LUMINANCE") volumeData.colorSpaceOperation = osg::REPLACE_ALPHA_WITH_LUMINANCE;
1113        else if (operation=="REPLACE_RGB_WITH_LUMINANCE") volumeData.colorSpaceOperation = osg::REPLACE_RGB_WITH_LUMINANCE;
1114    }
1115   
1116   
1117
1118    // check for any transfer function required
1119    std::string transferFunctionFile;
1120    if (getTrimmedProperty(cur, "tf", transferFunctionFile))
1121    {
1122        volumeData.transferFunction = readTransferFunctionFile(transferFunctionFile, 1.0);
1123    }
1124
1125    if (getTrimmedProperty(cur, "tf-255", transferFunctionFile))
1126    {
1127        volumeData.transferFunction = readTransferFunctionFile(transferFunctionFile, 1.0/255.0);
1128    }
1129
1130    if (getProperty(cur, "options", volumeData.options)) {}
1131
1132    // check for draggers required
1133    std::string dragger;
1134    if (getProperty(cur, "dragger", dragger))
1135    {
1136        if (dragger=="trackball")
1137        {
1138            volumeData.useTabbedDragger = false;
1139            volumeData.useTrackballDragger = true;
1140        }
1141        if (dragger=="trackball-box")
1142        {
1143            volumeData.useTabbedDragger = true;
1144            volumeData.useTrackballDragger = true;
1145        }
1146        else
1147        {
1148            volumeData.useTabbedDragger = true;
1149            volumeData.useTrackballDragger = false;
1150        }
1151    }
1152
1153    std::string filename = cur->getTrimmedContents();
1154    if (!filename.empty())
1155    {
1156        constructor.addVolume(filename,
1157                             positionRead ? positionData : constructor.getModelPositionData(),
1158                             volumeData);
1159    }
1160}
1161
1162void ReaderWriterP3DXML::parseStereoPair(osgPresentation::SlideShowConstructor& constructor, osgDB::XmlNode*cur) const
1163{
1164
1165    OSG_INFO<<"ReaderWriterP3DXML::parseStereoPair()"<<std::endl;
1166
1167
1168    std::string filenameLeft;
1169    std::string filenameRight;
1170
1171    osgPresentation::SlideShowConstructor::PositionData positionData = constructor.getImagePositionData();
1172    bool positionRead = getProperties(cur,positionData);
1173
1174    osgPresentation::SlideShowConstructor::ImageData imageDataLeft;// = constructor.getImageData();
1175    osgPresentation::SlideShowConstructor::ImageData imageDataRight;// = constructor.getImageData();
1176
1177    getProperties(cur,imageDataLeft);
1178    getProperties(cur,imageDataRight);
1179
1180    for(osgDB::XmlNode::Children::iterator itr = cur->children.begin();
1181        itr != cur->children.end();
1182        ++itr)
1183    {
1184        osgDB::XmlNode* child = itr->get();
1185
1186        if (child->name == "image_left")
1187        {
1188            getProperties(child,imageDataLeft);
1189            filenameLeft = child->getTrimmedContents();
1190        }
1191        else if (child->name == "imagesequence_left")
1192        {
1193            imageDataLeft.imageSequence = true;
1194            getProperties(child,imageDataLeft);
1195            filenameLeft = child->getTrimmedContents();
1196        }
1197        else if (child->name == "image_right")
1198        {
1199            getProperties(child,imageDataRight);
1200            filenameRight = child->getTrimmedContents();
1201
1202            getProperties(cur,imageDataRight);
1203        }
1204        else if (child->name == "imagesequence_right")
1205        {
1206            imageDataRight.imageSequence = true;
1207            getProperties(child,imageDataRight);
1208            filenameRight = child->getTrimmedContents();
1209        }
1210    }
1211
1212    OSG_INFO<<"    filenameLeft="<<filenameLeft<<std::endl;
1213    OSG_INFO<<"    filenameRight="<<filenameRight<<std::endl;
1214
1215
1216    if (!filenameLeft.empty() && !filenameRight.empty())
1217        constructor.addStereoImagePair(filenameLeft,imageDataLeft,
1218                                       filenameRight, imageDataRight,
1219                                       positionRead ? positionData : constructor.getImagePositionData());
1220
1221}
1222
1223bool ReaderWriterP3DXML::getKeyPosition(osgDB::XmlNode*cur, osgPresentation::KeyPosition& keyPosition) const
1224{
1225    if (cur->name == "key")
1226    {
1227        return getKeyPositionInner(cur, keyPosition);
1228    }
1229    if (cur->name == "escape" ||
1230        cur->name == "esc" ||
1231        cur->name == "exit")
1232    {
1233        keyPosition.set(osgGA::GUIEventAdapter::KEY_Escape, 0.0f, 0.0f);
1234        return true;
1235    }
1236    return false;
1237}
1238
1239bool ReaderWriterP3DXML::getKeyPositionInner(osgDB::XmlNode*cur, osgPresentation::KeyPosition& keyPosition) const
1240{
1241    // x in range -1 to 1, from left to right
1242    float x = FLT_MAX;
1243    getProperty(cur, "x", x);
1244
1245    // y in range -1 to 1, from bottom to top
1246    float y = FLT_MAX;
1247    getProperty(cur, "y", y);
1248
1249    float h = FLT_MAX;
1250    if (getProperty(cur, "h", h))
1251    {
1252        // h in range 0.0 to 1, from left to right
1253        x = h*2.0f-1.0f;
1254    }
1255
1256    float v = FLT_MAX;
1257    if (getProperty(cur, "v", v))
1258    {
1259        // v in range 0.0 to 1, from bottom to top
1260        y = v*2.0f-1.0f;
1261    }
1262
1263
1264    std::string key = cur->getTrimmedContents();
1265    unsigned int keyValue = 0;
1266
1267    StringKeyMap::const_iterator itr=_stringKeyMap.find(key);
1268    if (itr != _stringKeyMap.end())
1269    {
1270        keyValue = itr->second;
1271    }
1272    else if (key.length()==1)
1273    {
1274        keyValue = key[0];
1275    }
1276    else
1277    {
1278        OSG_NOTICE<<"Warning: invalid key used in <key>"<<key<<"</key>, ignoring tag."<<std::endl;
1279        return false;
1280    }
1281
1282    keyPosition.set(keyValue,x,y);
1283    return true;
1284}
1285
1286
1287
1288
1289void ReaderWriterP3DXML::parseLayer(osgPresentation::SlideShowConstructor& constructor, osgDB::XmlNode* root) const
1290{
1291    // create a keyPosition just in case we need it.
1292    osgPresentation::KeyPosition keyPosition;
1293
1294    OSG_INFO<<std::endl<<"parseLayer"<<std::endl;
1295
1296    float totalIndent = 0.0f;
1297
1298    for(osgDB::XmlNode::Children::iterator itr = root->children.begin();
1299        itr != root->children.end();
1300        ++itr)
1301    {
1302        osgDB::XmlNode* cur = itr->get();
1303        if (cur->name == "run")
1304        {
1305            OSG_INFO<<"run ["<<cur->contents<<"]"<<std::endl;
1306            constructor.addLayerRunString(cur->contents);
1307        }
1308        else if (cur->name == "jump")
1309        {
1310            OSG_INFO<<"Parsed Jump "<<std::endl;
1311
1312            osgPresentation::JumpData jumpData;
1313            if (getJumpProperties(cur, jumpData))
1314            {
1315                OSG_INFO<<"Layer Jump "<<jumpData.relativeJump<<","<< jumpData.slideNum<<", "<<jumpData.layerNum<<std::endl;
1316
1317                constructor.setLayerJump(jumpData);
1318            }
1319        }
1320        else if (cur->name == "click_to_run")
1321        {
1322            osgPresentation::JumpData jumpData;
1323            getJumpProperties(cur, jumpData);
1324
1325            OSG_INFO<<"click_to_run ["<<cur->contents<<"]"<<std::endl;
1326            constructor.layerClickToDoOperation(cur->contents,osgPresentation::RUN, jumpData);
1327        }
1328        else if (cur->name == "click_to_load")
1329        {
1330            osgPresentation::JumpData jumpData;
1331            getJumpProperties(cur, jumpData);
1332
1333            OSG_INFO<<"click_to_load ["<<cur->contents<<"]"<<std::endl;
1334            constructor.layerClickToDoOperation(cur->contents,osgPresentation::LOAD, jumpData);
1335        }
1336
1337        else if (cur->name == "click_to_event")
1338        {
1339            osgPresentation::JumpData jumpData;
1340            getJumpProperties(cur, jumpData);
1341
1342            if (getKeyPositionInner( cur, keyPosition))
1343            {
1344                OSG_INFO<<"click_to_event ["<<keyPosition._key<<"]"<<std::endl;
1345                constructor.layerClickEventOperation(keyPosition, jumpData);
1346            }
1347        }
1348
1349        else if (cur->name == "click_to_jump")
1350        {
1351            osgPresentation::JumpData jumpData;
1352            getJumpProperties(cur, jumpData);
1353
1354            constructor.layerClickEventOperation(osgPresentation::JUMP, jumpData);
1355        }
1356
1357        else if (cur->name == "key_to_run")
1358        {
1359            int key;
1360            if (getKeyProperty(cur, "key", key))
1361            {
1362                osgPresentation::JumpData jumpData;
1363                getJumpProperties(cur, jumpData);
1364
1365                OSG_NOTICE<<"key_to_run ["<<cur->contents<<"], key="<<key<<std::endl;
1366                constructor.keyToDoOperation(osgPresentation::SlideShowConstructor::CURRENT_LAYER, key, cur->contents,osgPresentation::RUN, jumpData);
1367            }
1368        }
1369        else if (cur->name == "key_to_load")
1370        {
1371            int key;
1372            if (getKeyProperty(cur, "key", key))
1373            {
1374                osgPresentation::JumpData jumpData;
1375                getJumpProperties(cur, jumpData);
1376
1377                OSG_NOTICE<<"key_to_load ["<<cur->contents<<"]"<<std::endl;
1378                constructor.keyToDoOperation(osgPresentation::SlideShowConstructor::CURRENT_LAYER, key, cur->contents,osgPresentation::LOAD, jumpData);
1379            }
1380        }
1381
1382        else if (cur->name == "key_to_event")
1383        {
1384            int key;
1385            if (getKeyProperty(cur, "key", key))
1386            {
1387                osgPresentation::JumpData jumpData;
1388                getJumpProperties(cur, jumpData);
1389
1390                if (getKeyPositionInner( cur, keyPosition))
1391                {
1392                    OSG_NOTICE<<"key_to_event ["<<keyPosition._key<<"]"<<std::endl;
1393                    constructor.keyEventOperation(osgPresentation::SlideShowConstructor::CURRENT_LAYER, key, keyPosition, jumpData);
1394                }
1395            }
1396        }
1397
1398        else if (cur->name == "key_to_jump")
1399        {
1400            int key;
1401            if (getKeyProperty(cur, "key", key))
1402            {
1403                osgPresentation::JumpData jumpData;
1404                getJumpProperties(cur, jumpData);
1405
1406                OSG_NOTICE<<"key_to_jump"<<std::endl;
1407
1408                constructor.keyEventOperation(osgPresentation::SlideShowConstructor::CURRENT_LAYER, key, osgPresentation::JUMP, jumpData);
1409            }
1410        }
1411
1412        else if (cur->name == "newline")
1413        {
1414            constructor.translateTextCursor(osg::Vec3(0.0f,-0.05f,0.0f));
1415        }
1416        else if (cur->name == "indent")
1417        {
1418            float localIndent = 0.05f;
1419            constructor.translateTextCursor(osg::Vec3(localIndent,0.0f,0.0f));
1420            totalIndent += localIndent;
1421        }
1422        else if (cur->name == "unindent")
1423        {
1424            float localIndent = -0.05f;
1425            constructor.translateTextCursor(osg::Vec3(localIndent,0.0f,0.0f));
1426            totalIndent += localIndent;
1427        }
1428        else if (cur->name == "bullet")
1429        {
1430            OSG_INFO<<"bullet ["<<cur->contents<<"]"<<std::endl;
1431            osgPresentation::SlideShowConstructor::PositionData positionData = constructor.getTextPositionData();
1432            bool positionRead = getProperties(cur,positionData);
1433
1434            osgPresentation::SlideShowConstructor::FontData fontData = constructor.getTextFontData();
1435            bool fontRead = getProperties(cur,fontData);
1436
1437            constructor.addBullet(cur->contents,
1438                                    positionRead ? positionData : constructor.getTextPositionData(),
1439                                    fontRead ? fontData : constructor.getTextFontData());
1440        }
1441        else if (cur->name == "paragraph")
1442        {
1443            osgPresentation::SlideShowConstructor::PositionData positionData = constructor.getTextPositionData();
1444            bool positionRead = getProperties(cur,positionData);
1445
1446            osgPresentation::SlideShowConstructor::FontData fontData = constructor.getTextFontData();
1447            bool fontRead = getProperties(cur,fontData);
1448
1449            constructor.addParagraph(cur->contents,
1450                                        positionRead ? positionData : constructor.getTextPositionData(),
1451                                        fontRead ? fontData : constructor.getTextFontData());
1452        }
1453        else if (cur->name == "image")
1454        {
1455            osgPresentation::SlideShowConstructor::PositionData positionData = constructor.getImagePositionData();
1456            bool positionRead = getProperties(cur,positionData);
1457
1458            osgPresentation::SlideShowConstructor::ImageData imageData;// = constructor.getImageData();
1459            getProperties(cur,imageData);
1460
1461            constructor.addImage(cur->getTrimmedContents(),
1462                                    positionRead ? positionData : constructor.getImagePositionData(),
1463                                    imageData);
1464        }
1465        else if (cur->name == "imagesequence")
1466        {
1467            osgPresentation::SlideShowConstructor::PositionData positionData = constructor.getImagePositionData();
1468            bool positionRead = getProperties(cur,positionData);
1469
1470            osgPresentation::SlideShowConstructor::ImageData imageData;// = constructor.getImageData();
1471            imageData.imageSequence = true;
1472            getProperties(cur,imageData);
1473
1474            constructor.addImage(cur->getTrimmedContents(),
1475                                    positionRead ? positionData : constructor.getImagePositionData(),
1476                                    imageData);
1477        }
1478        else if (cur->name == "graph")
1479        {
1480            osgPresentation::SlideShowConstructor::PositionData positionData = constructor.getImagePositionData();
1481            bool positionRead = getProperties(cur,positionData);
1482
1483            osgPresentation::SlideShowConstructor::ImageData imageData;// = constructor.getImageData();
1484            getProperties(cur,imageData);
1485
1486            std::string options;
1487            getProperty(cur, "options", options);
1488
1489            constructor.addGraph(cur->getTrimmedContents(),
1490                                 positionRead ? positionData : constructor.getImagePositionData(),
1491                                 imageData);
1492        }
1493        else if (cur->name == "vnc")
1494        {
1495            osgPresentation::SlideShowConstructor::PositionData positionData = constructor.getImagePositionData();
1496            bool positionRead = getProperties(cur,positionData);
1497
1498            osgPresentation::SlideShowConstructor::ImageData imageData;// = constructor.getImageData();
1499            getProperties(cur,imageData);
1500
1501            std::string password;
1502            getProperty(cur, "password", password);
1503
1504            constructor.addVNC(cur->getTrimmedContents(),
1505                                    positionRead ? positionData : constructor.getImagePositionData(),
1506                                    imageData,
1507                                    password
1508                              );
1509        }
1510        else if (cur->name == "browser")
1511        {
1512            osgPresentation::SlideShowConstructor::PositionData positionData = constructor.getImagePositionData();
1513            bool positionRead = getProperties(cur,positionData);
1514
1515            osgPresentation::SlideShowConstructor::ImageData imageData;// = constructor.getImageData();
1516            getProperties(cur,imageData);
1517
1518            constructor.addBrowser(cur->getTrimmedContents(),
1519                                    positionRead ? positionData : constructor.getImagePositionData(),
1520                                    imageData);
1521        }
1522        else if (cur->name == "pdf")
1523        {
1524            osgPresentation::SlideShowConstructor::PositionData positionData = constructor.getImagePositionData();
1525            bool positionRead = getProperties(cur,positionData);
1526
1527            osgPresentation::SlideShowConstructor::ImageData imageData;// = constructor.getImageData();
1528            getProperties(cur,imageData);
1529
1530            constructor.addPDF(cur->getTrimmedContents(),
1531                                    positionRead ? positionData : constructor.getImagePositionData(),
1532                                    imageData);
1533        }
1534        else if (cur->name == "stereo_pair")
1535        {
1536            parseStereoPair(constructor, cur);
1537        }
1538        else if (cur->name == "model")
1539        {
1540            parseModel(constructor, cur);
1541        }
1542        else if (cur->name == "volume")
1543        {
1544            parseVolume(constructor, cur);
1545        }
1546        else if (cur->name == "duration")
1547        {
1548            constructor.setLayerDuration(osg::asciiToDouble(cur->contents.c_str()));
1549        }
1550        else if (getKeyPosition(cur, keyPosition))
1551        {
1552            constructor.addLayerKey(keyPosition);
1553        }
1554    }
1555
1556    if (totalIndent != 0.0f)
1557    {
1558        constructor.translateTextCursor(osg::Vec3(-totalIndent,0.0f,0.0f));
1559    }
1560
1561    std::string name;
1562    if (getProperty(root, "layer_name", name))
1563    {
1564        if (constructor.getCurrentLayer())
1565        {
1566            constructor.getCurrentLayer()->setUserValue("name",name);
1567            OSG_NOTICE<<"Setting current layers name "<<name<<std::endl;
1568        }
1569        else
1570        {
1571            OSG_NOTICE<<"getCurrentSlide() returns NULL, unable to set name "<<std::endl;
1572        }
1573    }
1574}
1575
1576void ReaderWriterP3DXML::parseBullets(osgPresentation::SlideShowConstructor& constructor, osgDB::XmlNode*cur, bool inheritPreviousLayers, bool defineAsBaseLayer) const
1577{
1578    constructor.addLayer(inheritPreviousLayers, defineAsBaseLayer);
1579
1580    OSG_INFO<<"bullets ["<<cur->contents<<"]"<<std::endl;
1581    osgPresentation::SlideShowConstructor::PositionData positionData = constructor.getTextPositionData();
1582    bool positionRead = getProperties(cur,positionData);
1583
1584    osgPresentation::SlideShowConstructor::FontData fontData = constructor.getTextFontData();
1585    bool fontRead = getProperties(cur,fontData);
1586
1587    constructor.addBullet(cur->contents,
1588                            positionRead ? positionData : constructor.getTextPositionData(),
1589                            fontRead ? fontData : constructor.getTextFontData());
1590}
1591
1592
1593void ReaderWriterP3DXML::parseText(osgPresentation::SlideShowConstructor& constructor, osgDB::XmlNode*cur, bool inheritPreviousLayers, bool defineAsBaseLayer) const
1594{
1595    constructor.addLayer(inheritPreviousLayers, defineAsBaseLayer);
1596
1597    OSG_INFO<<"text ["<<cur->contents<<"]"<<std::endl;
1598    osgPresentation::SlideShowConstructor::PositionData positionData = constructor.getTextPositionData();
1599    bool positionRead = getProperties(cur,positionData);
1600
1601    osgPresentation::SlideShowConstructor::FontData fontData = constructor.getTextFontData();
1602    bool fontRead = getProperties(cur,fontData);
1603
1604    constructor.addParagraph(cur->contents,
1605                            positionRead ? positionData : constructor.getTextPositionData(),
1606                            fontRead ? fontData : constructor.getTextFontData());
1607}
1608
1609void ReaderWriterP3DXML::parsePage(osgPresentation::SlideShowConstructor& constructor, osgDB::XmlNode*cur) const
1610{
1611    constructor.addSlide();
1612
1613    std::string title;
1614    getProperty(cur, "title", title);
1615
1616    std::string inherit;
1617    getProperty(cur, "inherit", inherit);
1618
1619    if (!inherit.empty() && _templateMap.count(inherit)!=0)
1620    {
1621        parseSlide(constructor, _templateMap[inherit].get(), true, false);
1622    }
1623
1624    if (!title.empty())
1625    {
1626        constructor.setSlideTitle(title,
1627                                    constructor.getTitlePositionData(),
1628                                    constructor.getTitleFontData());
1629    }
1630
1631    if (!inherit.empty() && _templateMap.count(inherit)!=0)
1632    {
1633        parseSlide(constructor, _templateMap[inherit].get(), false, true);
1634    }
1635
1636    constructor.addLayer(true,false);
1637
1638    osgPresentation::SlideShowConstructor::PositionData positionData = constructor.getTextPositionData();
1639    bool positionRead = getProperties(cur,positionData);
1640
1641    osgPresentation::SlideShowConstructor::FontData fontData = constructor.getTextFontData();
1642    bool fontRead = getProperties(cur,fontData);
1643
1644    constructor.addParagraph(cur->contents,
1645                            positionRead ? positionData : constructor.getTextPositionData(),
1646                            fontRead ? fontData : constructor.getTextFontData());
1647}
1648
1649void ReaderWriterP3DXML::parsePdfDocument(osgPresentation::SlideShowConstructor& constructor, osgDB::XmlNode*cur) const
1650{
1651    std::string title;
1652    getProperty(cur, "title", title);
1653
1654    std::string inherit;
1655    getProperty(cur, "inherit", inherit);
1656
1657    constructor.addSlide();
1658
1659    if (!inherit.empty() && _templateMap.count(inherit)!=0)
1660    {
1661        parseSlide(constructor, _templateMap[inherit].get(), true, false);
1662    }
1663
1664    if (!title.empty())
1665    {
1666        constructor.setSlideTitle(title,
1667                                    constructor.getTitlePositionData(),
1668                                    constructor.getTitleFontData());
1669    }
1670
1671    if (!inherit.empty() && _templateMap.count(inherit)!=0)
1672    {
1673        parseSlide(constructor, _templateMap[inherit].get(), false, true);
1674    }
1675
1676    constructor.addLayer(true,false);
1677
1678    osgPresentation::SlideShowConstructor::PositionData positionData = constructor.getImagePositionData();
1679    getProperties(cur,positionData);
1680
1681    osgPresentation::SlideShowConstructor::ImageData imageData;// = constructor.getImageData();
1682    imageData.page = 0;
1683    getProperties(cur,imageData);
1684
1685    osg::Image* image = constructor.addInteractiveImage(cur->contents, positionData, imageData);
1686    osgWidget::PdfImage* pdfImage = dynamic_cast<osgWidget::PdfImage*>(image);
1687    if (pdfImage)
1688    {
1689        int numPages = pdfImage->getNumOfPages();
1690        OSG_INFO<<"NumOfPages = "<<numPages<<std::endl;
1691
1692        if (numPages>1)
1693        {
1694            for(int pageNum=1; pageNum<numPages; ++pageNum)
1695            {
1696                imageData.page = pageNum;
1697
1698                constructor.addSlide();
1699
1700                if (!inherit.empty() && _templateMap.count(inherit)!=0)
1701                {
1702                    parseSlide(constructor, _templateMap[inherit].get(), true, false);
1703                }
1704
1705                if (!title.empty())
1706                {
1707                    constructor.setSlideTitle(title,
1708                                                constructor.getTitlePositionData(),
1709                                                constructor.getTitleFontData());
1710                }
1711
1712                if (!inherit.empty() && _templateMap.count(inherit)!=0)
1713                {
1714                    parseSlide(constructor, _templateMap[inherit].get(), false, true);
1715                }
1716
1717                constructor.addLayer(true,false);
1718
1719                constructor.addPDF(cur->getTrimmedContents(), positionData, imageData);
1720
1721            }
1722        }
1723    }
1724}
1725
1726void ReaderWriterP3DXML::parseSlide (osgPresentation::SlideShowConstructor& constructor, osgDB::XmlNode* root, bool parseTitles, bool parseLayers) const
1727{
1728
1729    osg::Vec4 previous_bgcolor = constructor.getBackgroundColor();
1730    osg::Vec4 previous_textcolor = constructor.getTextColor();
1731
1732    // create a keyPosition just in case we need it.
1733    osgPresentation::KeyPosition keyPosition;
1734
1735    for(osgDB::XmlNode::Children::iterator itr = root->children.begin();
1736        itr != root->children.end();
1737        ++itr)
1738    {
1739        osgDB::XmlNode* cur = itr->get();
1740
1741        if (parseTitles)
1742        {
1743            if (cur->name == "title")
1744            {
1745                osgPresentation::SlideShowConstructor::PositionData positionData = constructor.getTitlePositionData();
1746                bool positionRead = getProperties(cur,positionData);
1747
1748                osgPresentation::SlideShowConstructor::FontData fontData = constructor.getTitleFontData();
1749                bool fontRead = getProperties(cur,fontData);
1750
1751                constructor.setSlideTitle(cur->contents,
1752                                          positionRead ? positionData : constructor.getTitlePositionData(),
1753                                          fontRead ? fontData : constructor.getTitleFontData());
1754            }
1755            else if (cur->name == "background")
1756            {
1757                constructor.setSlideBackground(cur->contents);
1758
1759                std::string str;
1760                if (getProperty(cur, "hud", str))
1761                {
1762                    bool hud = (str != "off" && str != "Off" && str != "OFF");
1763                    OSG_NOTIFY(_notifyLevel)<<"background hud, str="<<str<<", hud="<<hud<<std::endl;
1764                    constructor.setSlideBackgrondHUD(hud);
1765                }
1766            }
1767            else if (cur->name == "bgcolor")
1768            {
1769                constructor.setBackgroundColor(mapStringToColor(cur->contents),true);
1770            }
1771            else if (cur->name == "textcolor")
1772            {
1773                constructor.setTextColor(mapStringToColor(cur->contents));
1774            }
1775        }
1776        if (parseLayers)
1777        {
1778            if (cur->name == "base")
1779            {
1780                constructor.addLayer(true, true);
1781                parseLayer (constructor, cur);
1782
1783            }
1784            else if (cur->name == "layer")
1785            {
1786                constructor.addLayer(true, false);
1787                parseLayer (constructor, cur);
1788            }
1789            else if (cur->name == "clean_layer")
1790            {
1791                constructor.addLayer(false, false);
1792                parseLayer (constructor, cur);
1793            }
1794            else if (cur->name == "modify_layer")
1795            {
1796                int layerNum;
1797                if (getProperty(cur, "layer", layerNum))
1798                {
1799                    constructor.selectLayer(layerNum);
1800                }
1801                else
1802                {
1803                    constructor.addLayer(true, false);
1804                }
1805
1806                parseLayer (constructor, cur);
1807            }
1808            else if (cur->name == "bullets")
1809            {
1810                parseBullets (constructor, cur,true, false);
1811            }
1812            else if (cur->name == "duration")
1813            {
1814                constructor.setSlideDuration(osg::asciiToDouble(cur->contents.c_str()));
1815            }
1816            else if (getKeyPosition(cur, keyPosition))
1817            {
1818                constructor.addSlideKey(keyPosition);
1819            }
1820        }
1821    }
1822
1823    std::string name;
1824    if (getProperty(root, "slide_name", name))
1825    {
1826        if (constructor.getCurrentSlide())
1827        {
1828            constructor.getCurrentSlide()->setUserValue("name",name);
1829            OSG_NOTICE<<"Setting current slide name "<<name<<std::endl;
1830        }
1831        else
1832        {
1833            OSG_NOTICE<<"getCurrentSlide() returns NULL, unable to set name "<<std::endl;
1834        }
1835    }
1836   
1837    constructor.setBackgroundColor(previous_bgcolor,false);
1838    constructor.setTextColor(previous_textcolor);
1839
1840    return;
1841}
1842
1843#include <iostream>
1844
1845
1846struct MyFindFileCallback : public osgDB::FindFileCallback
1847{
1848    virtual std::string findDataFile(const std::string& filename, const osgDB::Options* options, osgDB::CaseSensitivity caseSensitivity)
1849    {
1850        OSG_INFO<<std::endl<<std::endl<<"find file "<<filename<<std::endl;
1851
1852        const osgDB::FilePathList& paths = options ? options->getDatabasePathList() : osgDB::getDataFilePathList();
1853
1854        for(osgDB::FilePathList::const_iterator itr = paths.begin();
1855            itr != paths.end();
1856            ++itr)
1857        {
1858            const std::string& path = *itr;
1859            std::string newpath = osgDB::concatPaths(path, filename);
1860            if (osgDB::containsServerAddress(path))
1861            {
1862                osgDB::ReaderWriter* rw = osgDB::Registry::instance()->getReaderWriterForExtension("curl");
1863                OSG_INFO<<"  file on server "<<*itr<<", try path "<<newpath<<std::endl;
1864                OSG_INFO<<"  we have curl rw= "<<rw<<std::endl;
1865                if (rw && rw->fileExists(newpath, options))
1866                {
1867                    OSG_INFO<<"  FOUND on server "<<newpath<<std::endl;
1868                    return newpath;
1869                }
1870            }
1871            else
1872            {
1873                if(osgDB::fileExists(newpath))
1874                {
1875                    OSG_INFO<<" FOUND "<<newpath<<std::endl;
1876                    return newpath;
1877                }
1878            }
1879        }
1880
1881        return osgDB::Registry::instance()->findDataFileImplementation(filename, options, caseSensitivity);
1882    }
1883};
1884
1885class MyReadFileCallback : public virtual osgDB::ReadFileCallback
1886{
1887    public:
1888
1889        osgDB::FilePathList _paths;
1890
1891        typedef std::map< std::string, osg::ref_ptr<osg::Object> >  ObjectCache;
1892
1893        enum ObjectType
1894        {
1895            OBJECT,
1896            IMAGE,
1897            HEIGHT_FIELD,
1898            NODE,
1899            SHADER
1900        };
1901
1902        osgDB::ReaderWriter::ReadResult readLocal(ObjectType type, const std::string& filename, const osgDB::Options* options)
1903        {
1904            OSG_INFO<<"Trying local file "<<filename<<std::endl;
1905
1906            switch(type)
1907            {
1908                case(OBJECT): return osgDB::Registry::instance()->readObjectImplementation(filename,options);
1909                case(IMAGE): return osgDB::Registry::instance()->readImageImplementation(filename,options);
1910                case(HEIGHT_FIELD): return osgDB::Registry::instance()->readHeightFieldImplementation(filename,options);
1911                case(NODE): return osgDB::Registry::instance()->readNodeImplementation(filename,options);
1912                case(SHADER): return osgDB::Registry::instance()->readShaderImplementation(filename,options);
1913            }
1914            return osgDB::ReaderWriter::ReadResult::FILE_NOT_HANDLED;
1915        }
1916
1917
1918        osgDB::ReaderWriter::ReadResult readFileCache(ObjectType type, const std::string& filename, const osgDB::Options* options)
1919        {
1920
1921            osgDB::FileCache* fileCache = options ? options->getFileCache() : 0;
1922            if (!fileCache) fileCache = osgDB::Registry::instance()->getFileCache();
1923            if (!fileCache) return osgDB::ReaderWriter::ReadResult::FILE_NOT_FOUND;
1924
1925            OSG_INFO<<"Trying fileCache "<<filename<<std::endl;
1926
1927            osgDB::ReaderWriter::ReadResult result;
1928            if (fileCache && fileCache->isFileAppropriateForFileCache(filename))
1929            {
1930                if (fileCache->existsInCache(filename))
1931                {
1932                    switch(type)
1933                    {
1934                        case(OBJECT):
1935                            result = fileCache->readObject(filename, 0);
1936                            break;
1937                        case(IMAGE):
1938                            result = fileCache->readImage(filename, 0);
1939                            break;
1940                        case(HEIGHT_FIELD):
1941                            result = fileCache->readHeightField(filename, 0);
1942                            break;
1943                        case(NODE):
1944                            result = fileCache->readNode(filename,0);
1945                            break;
1946                        case(SHADER):
1947                            result = fileCache->readShader(filename, 0);
1948                            break;
1949                    }
1950
1951                    if (result.success())
1952                    {
1953                        OSG_INFO<<"   File read from FileCache."<<std::endl;
1954                        return result;
1955                    }
1956
1957                    OSG_INFO<<"   File in FileCache, but not successfully read"<<std::endl;
1958                }
1959                else
1960                {
1961                    OSG_INFO<<"   File does not exist in FileCache: "<<fileCache->createCacheFileName(filename)<<std::endl;
1962                }
1963            }
1964
1965            return osgDB::ReaderWriter::ReadResult::FILE_NOT_FOUND;
1966
1967        }
1968
1969        osgDB::ReaderWriter::ReadResult readServer(ObjectType type, const std::string& filename, const osgDB::Options* options)
1970        {
1971            OSG_INFO<<"Trying server file "<<filename<<std::endl;
1972
1973            osgDB::ReaderWriter::ReadResult result;
1974            osgDB::ReaderWriter* rw = osgDB::Registry::instance()->getReaderWriterForExtension("curl");
1975            if (!rw) return osgDB::ReaderWriter::ReadResult::FILE_NOT_HANDLED;
1976
1977            switch(type)
1978            {
1979                case(OBJECT):
1980                    result = rw->readObject(filename,options);
1981                    break;
1982                case(IMAGE):
1983                    result = rw->readImage(filename,options);
1984                    break;
1985                case(HEIGHT_FIELD):
1986                    result = rw->readHeightField(filename,options);
1987                    break;
1988                case(NODE):
1989                    result = rw->readNode(filename,options);
1990                    break;
1991                case(SHADER):
1992                    result = rw->readShader(filename,options);
1993                    break;
1994            }
1995
1996            if (result.success())
1997            {
1998                osgDB::FileCache* fileCache = options ? options->getFileCache() : 0;
1999                if (!fileCache) fileCache = osgDB::Registry::instance()->getFileCache();
2000
2001                if (fileCache && fileCache->isFileAppropriateForFileCache(filename))
2002                {
2003                    switch(type)
2004                    {
2005                        case(OBJECT):
2006                            fileCache->writeObject(*result.getObject(),filename,options);
2007                            break;
2008                        case(IMAGE):
2009                            result.getImage()->setFileName(filename);
2010                            fileCache->writeImage(*result.getImage(),filename,options);
2011                            break;
2012                        case(HEIGHT_FIELD):
2013                            fileCache->writeHeightField(*result.getHeightField(),filename,options);
2014                            break;
2015                        case(NODE):
2016                            fileCache->writeNode(*result.getNode(),filename,options);
2017                            break;
2018                        case(SHADER):
2019                            fileCache->writeShader(*result.getShader(),filename,options);
2020                            break;
2021                    }
2022                }
2023
2024                return result;
2025            }
2026            return osgDB::ReaderWriter::ReadResult::FILE_NOT_FOUND;
2027        }
2028
2029
2030        osgDB::ReaderWriter::ReadResult read(const osgDB::FilePathList& filePathList, ObjectType type, const std::string& filename, const osgDB::Options* options, bool checkLocalFiles)
2031        {
2032            // go look in http paths
2033            for(osgDB::FilePathList::const_iterator itr = filePathList.begin();
2034                itr != filePathList.end();
2035                ++itr)
2036            {
2037                const std::string& path = *itr;
2038                std::string newpath = path.empty() ? filename : osgDB::concatPaths(path, filename);
2039                osgDB::ReaderWriter::ReadResult result;
2040                if (osgDB::containsServerAddress(newpath))
2041                {
2042                    if (checkLocalFiles) result = readFileCache(type, newpath, options);
2043                    else result = readServer(type, newpath, options);
2044                }
2045                else if (checkLocalFiles && osgDB::fileExists(newpath))
2046                {
2047                    result = readLocal(type, newpath, options);
2048                }
2049
2050                if (result.success())
2051                {
2052                    OSG_INFO<<"   inserting object into file cache "<<filename<<", "<<result.getObject()<<std::endl;
2053                    _objectCache[filename] = result.getObject();
2054
2055                    options->setPluginStringData("filename",newpath);
2056                    return result;
2057                }
2058            }
2059            return osgDB::ReaderWriter::ReadResult::FILE_NOT_FOUND;
2060        }
2061
2062        osgDB::ReaderWriter::ReadResult read(ObjectType type, const std::string& filename, const osgDB::Options* options)
2063        {
2064            osgDB::FileCache* fileCache = options ? options->getFileCache() : 0;
2065            if (!fileCache) fileCache = osgDB::Registry::instance()->getFileCache();
2066            if (fileCache && !fileCache->isFileAppropriateForFileCache(filename)) fileCache = 0;
2067
2068            OSG_INFO<<"MyReadFileCallback::reading file "<<filename<<std::endl;
2069            ObjectCache::iterator itr = _objectCache.find(filename);
2070            if (itr != _objectCache.end())
2071            {
2072                // object is in cache, just retrieve it.
2073                if (itr->second.valid())
2074                {
2075                    OSG_INFO<<"File retrieved from cache, filename="<<filename<<std::endl;
2076                    return itr->second.get();
2077                }
2078                else
2079                {
2080                    OSG_INFO<<"File failed to load previously, won't attempt a second time "<<filename<<std::endl;
2081                    return osgDB::ReaderWriter::ReadResult::FILE_NOT_FOUND;
2082                }
2083            }
2084
2085            OSG_INFO<<"   MyReadFileCallback::reading file A"<<filename<<std::endl;
2086
2087            {
2088                bool checkLocalFiles = true;
2089                osgDB::ReaderWriter::ReadResult result = read(_paths, type, filename, options, checkLocalFiles);
2090                if (result.success()) return result;
2091
2092                if (options && !(options->getDatabasePathList().empty()))
2093                {
2094                    result = read(options->getDatabasePathList(), type, filename, options, checkLocalFiles);
2095                    if (result.success()) return result;
2096                }
2097
2098                result = read(osgDB::Registry::instance()->getDataFilePathList(), type, filename, options, checkLocalFiles);
2099                if (result.success()) return result;
2100            }
2101
2102            OSG_INFO<<"   MyReadFileCallback::reading file B"<<filename<<std::endl;
2103
2104            {
2105                bool checkLocalFiles = false;
2106                osgDB::ReaderWriter::ReadResult result = read(_paths, type, filename, options, checkLocalFiles);
2107                if (result.success()) return result;
2108
2109                if (options && !(options->getDatabasePathList().empty()))
2110                {
2111                    result = read(options->getDatabasePathList(), type, filename, options, checkLocalFiles);
2112                    if (result.success()) return result;
2113                }
2114
2115                result = read(osgDB::Registry::instance()->getDataFilePathList(), type, filename, options, checkLocalFiles);
2116                if (result.success()) return result;
2117            }
2118
2119            OSG_INFO<<"   MyReadFileCallback::reading file C"<<filename<<std::endl;
2120
2121            _objectCache[filename] = 0;
2122
2123            return osgDB::ReaderWriter::ReadResult::FILE_NOT_FOUND;
2124        }
2125
2126        virtual osgDB::ReaderWriter::ReadResult readObject(const std::string& filename, const osgDB::Options* options)
2127        {
2128            return read(OBJECT, filename, options);
2129        }
2130
2131        virtual osgDB::ReaderWriter::ReadResult readImage(const std::string& filename, const osgDB::Options* options)
2132        {
2133            return read(IMAGE, filename, options);
2134        }
2135
2136        virtual osgDB::ReaderWriter::ReadResult readHeightField(const std::string& filename, const osgDB::Options* options)
2137        {
2138            return read(HEIGHT_FIELD, filename, options);
2139        }
2140
2141        virtual osgDB::ReaderWriter::ReadResult readNode(const std::string& filename, const osgDB::Options* options)
2142        {
2143            return read(NODE, filename, options);
2144        }
2145
2146        virtual osgDB::ReaderWriter::ReadResult readShader(const std::string& filename, const osgDB::Options* options)
2147        {
2148            return read(SHADER, filename, options);
2149        }
2150
2151    protected:
2152        virtual ~MyReadFileCallback() {}
2153
2154        ObjectCache _objectCache;
2155};
2156
2157osgDB::ReaderWriter::ReadResult ReaderWriterP3DXML::readNode(const std::string& file,
2158                                                           const osgDB::ReaderWriter::Options* options) const
2159{
2160    OSG_INFO<<"readNode("<<file<<")"<<std::endl;
2161
2162
2163    std::string ext = osgDB::getLowerCaseFileExtension(file);
2164    if (!acceptsExtension(ext)) return ReadResult::FILE_NOT_HANDLED;
2165
2166    std::string fileName = file;
2167
2168    std::string fileNameSansExtension = osgDB::getNameLessExtension(fileName);
2169    std::string nestedExtension = osgDB::getFileExtension(fileNameSansExtension);
2170    std::string fileNameSansNestedExtension = osgDB::getNameLessExtension(fileNameSansExtension);
2171
2172    if (nestedExtension=="preview" || nestedExtension=="main")
2173    {
2174        fileName = fileNameSansNestedExtension + "." + ext;
2175        OSG_INFO<<"Removed nested extension "<<nestedExtension<<" result = "<<fileName<<std::endl;
2176    }
2177
2178    fileName = osgDB::findDataFile( fileName, options );
2179    if (fileName.empty()) return ReadResult::FILE_NOT_FOUND;
2180
2181    // code for setting up the database path so that internally referenced file are searched for on relative paths.
2182    osg::ref_ptr<osgDB::ReaderWriter::Options> local_opt = options ? static_cast<osgDB::ReaderWriter::Options*>(options->clone(osg::CopyOp::SHALLOW_COPY)) : new Options;
2183    local_opt->getDatabasePathList().push_front(osgDB::getFilePath(fileName));
2184    local_opt->setFindFileCallback(new MyFindFileCallback);
2185    local_opt->setPluginStringData("filename",file);
2186
2187    osgDB::XmlNode::Input input;
2188    input.open(fileName);
2189    input.readAllDataIntoBuffer();
2190
2191    return readNode(input, local_opt.get());
2192}
2193
2194osgDB::ReaderWriter::ReadResult ReaderWriterP3DXML::readNode(std::istream& fin, const Options* options) const
2195{
2196    osgDB::XmlNode::Input input;
2197    input.attach(fin);
2198    input.readAllDataIntoBuffer();
2199
2200    osg::ref_ptr<osgDB::ReaderWriter::Options> local_opt = options ? static_cast<osgDB::ReaderWriter::Options*>(options->clone(osg::CopyOp::SHALLOW_COPY)) : new Options;
2201    local_opt->setReadFileCallback(new MyReadFileCallback);
2202
2203    return readNode(input, local_opt.get());
2204}
2205
2206osgDB::ReaderWriter::ReadResult ReaderWriterP3DXML::readNode(osgDB::XmlNode::Input& input, osgDB::ReaderWriter::Options* options) const
2207{
2208    std::string fileName = options ? options->getPluginStringData("filename") : std::string();
2209    std::string extension = osgDB::getFileExtension(fileName);
2210    std::string fileNameSansExtension = osgDB::getNameLessExtension(fileName);
2211    std::string nestedExtension = osgDB::getFileExtension(fileNameSansExtension);
2212    std::string fileNameSansNestedExtension = osgDB::getFileExtension(fileNameSansExtension);
2213
2214    bool readOnlyHoldingPage = nestedExtension=="preview" || (options && options->getOptionString()=="preview");
2215    bool readOnlyMainPresentation = nestedExtension=="main" || (options && options->getOptionString()=="main");
2216
2217    osg::ref_ptr<osgDB::XmlNode> doc = new osgDB::XmlNode;
2218    osgDB::XmlNode* root = 0;
2219
2220    doc->read(input);
2221
2222    OSG_INFO<<"P3D xml file read, now building presentation scene graph."<<std::endl;
2223
2224#if 0
2225    std::ofstream fout("output.p3d");
2226    doc->write(fout);
2227#endif
2228
2229    if (doc == NULL )
2230    {
2231            fprintf(stderr,"Document not parsed successfully. \n");
2232            return ReadResult::FILE_NOT_HANDLED;
2233    }
2234
2235    for(osgDB::XmlNode::Children::iterator itr = doc->children.begin();
2236        itr != doc->children.end() && !root;
2237        ++itr)
2238    {
2239        if ((*itr)->name=="presentation") root = itr->get();
2240    }
2241
2242    if (root == NULL)
2243    {
2244            fprintf(stderr,"empty document\n");
2245            return ReadResult::FILE_NOT_HANDLED;
2246    }
2247
2248    if (root->name!="presentation")
2249    {
2250            fprintf(stderr,"document of the wrong type, root node != presentation");
2251            return ReadResult::FILE_NOT_HANDLED;
2252    }
2253
2254
2255    bool hasHoldingSlide = false;
2256    for(osgDB::XmlNode::Children::iterator itr = root->children.begin();
2257        itr != root->children.end() && !hasHoldingSlide;
2258        ++itr)
2259    {
2260        osgDB::XmlNode* cur = itr->get();
2261        if (cur->name == "holding_slide")
2262        {
2263            hasHoldingSlide = true;
2264        }
2265    }
2266
2267    // if we are looking for a holding slide, but one isn't present return NULL.
2268    if (readOnlyHoldingPage && !hasHoldingSlide) return 0;
2269
2270    OSG_INFO<<"hasHoldingSlide "<<hasHoldingSlide<<std::endl;
2271    OSG_INFO<<"readOnlyHoldingPage "<<readOnlyHoldingPage<<std::endl;
2272    OSG_INFO<<"readOnlyMainPresentation "<<readOnlyMainPresentation<<std::endl;
2273
2274    osg::ref_ptr<osg::Node> presentation_node;
2275
2276
2277    if (!readOnlyHoldingPage && !readOnlyMainPresentation)
2278    {
2279        if (fileName.empty()) hasHoldingSlide = false;
2280
2281        osg::ref_ptr<osg::Node> holdingslide_node = hasHoldingSlide ? parseXmlGraph(root, true, options) : 0;
2282
2283        if (holdingslide_node.valid())
2284        {
2285            double farDistance = 10000.0f;
2286
2287            osg::ref_ptr<osg::PagedLOD> pagedLOD = new osg::PagedLOD;
2288
2289            pagedLOD->setDatabaseOptions(options);
2290
2291            pagedLOD->addChild(holdingslide_node.get());
2292            pagedLOD->setRange(0,farDistance,2.0*farDistance);
2293
2294            std::string fileNameToLoadMainPresentation = fileNameSansExtension + std::string(".main.")+extension;
2295
2296            pagedLOD->setFileName(1,fileNameToLoadMainPresentation);
2297            pagedLOD->setRange(1,0.0,farDistance);
2298
2299            presentation_node = pagedLOD.get();
2300
2301        }
2302        else
2303        {
2304            presentation_node = parseXmlGraph(root, false, options);
2305        }
2306    }
2307    else
2308    {
2309        presentation_node = parseXmlGraph(root, readOnlyHoldingPage, options);
2310    }
2311
2312    if (presentation_node.valid())
2313    {
2314        if (!options || options->getPluginStringData("P3D_EVENTHANDLER")!="none")
2315        {
2316            // if (!readOnlyHoldingPage && !readOnlyMainPresentation)
2317            {
2318                osgPresentation::SlideEventHandler* seh = new osgPresentation::SlideEventHandler;
2319                seh->set(presentation_node.get());
2320                presentation_node->addEventCallback(seh);
2321            }
2322        }
2323        return presentation_node.release();
2324    }
2325    else
2326    {
2327        return osgDB::ReaderWriter::ReadResult::ERROR_IN_READING_FILE;
2328    }
2329}
2330
2331osg::Node* ReaderWriterP3DXML::parseXmlGraph(osgDB::XmlNode* root, bool readOnlyHoldingPage, osgDB::Options* options) const
2332{
2333    osgPresentation::SlideShowConstructor constructor(options);
2334
2335    // create a keyPosition just in case we need it.
2336    osgPresentation::KeyPosition keyPosition;
2337
2338    osgDB::FilePathList previousPaths = osgDB::getDataFilePathList();
2339
2340    for(osgDB::XmlNode::Children::iterator itr = root->children.begin();
2341        itr != root->children.end();
2342        ++itr)
2343    {
2344        osgDB::XmlNode* cur = itr->get();
2345
2346        if (cur->name=="env")
2347        {
2348            char* str = strdup(cur->contents.c_str());
2349            OSG_INFO<<"putenv("<<str<<")"<<std::endl;
2350            putenv(str);
2351        }
2352    }
2353
2354    std::string pathToPresentation;
2355    MyReadFileCallback* readFileCallback = options ? dynamic_cast<MyReadFileCallback*>(options->getReadFileCallback()) : 0;
2356
2357    if (options && !(options->getDatabasePathList().empty()))
2358    {
2359        pathToPresentation = options->getDatabasePathList().front();
2360
2361       if (readFileCallback) readFileCallback->_paths.push_front(pathToPresentation);
2362    }
2363
2364
2365    for(osgDB::XmlNode::Children::iterator itr = root->children.begin();
2366        itr != root->children.end();
2367        ++itr)
2368    {
2369        osgDB::XmlNode* cur = itr->get();
2370
2371        if (cur->name == "path")
2372        {
2373            std::string newpath = expandEnvVarsInFileName(cur->contents);
2374
2375            // now check if an absolue or http path
2376            std::string::size_type colonPos = newpath.find_first_of(':');
2377            std::string::size_type backslashPos = newpath.find_first_of('/');
2378            std::string::size_type forwardslashPos = newpath.find_first_of('\\');
2379            bool relativePath = colonPos == std::string::npos &&
2380                                backslashPos != 0 &&
2381                                forwardslashPos != 0;
2382
2383            if (relativePath && !pathToPresentation.empty())
2384            {
2385                newpath = osgDB::concatPaths(pathToPresentation, newpath);
2386                OSG_INFO<<"relative path = "<<cur->contents<<", newpath="<<newpath<<std::endl;
2387            }
2388            else
2389            {
2390                OSG_INFO<<"absolute path = "<<cur->contents<<", newpath="<<newpath<<std::endl;
2391            }
2392
2393            if (readFileCallback) readFileCallback->_paths.push_back(newpath);
2394            else options->getDatabasePathList().push_back(newpath);
2395        }
2396    }
2397
2398
2399    for(osgDB::XmlNode::Children::iterator itr = root->children.begin();
2400        itr != root->children.end();
2401        ++itr)
2402    {
2403        osgDB::XmlNode* cur = itr->get();
2404
2405        if (cur->name == "name")
2406        {
2407            constructor.setPresentationName(cur->contents);
2408        }
2409        else if (cur->name == "loop")
2410        {
2411            constructor.setLoopPresentation(true);
2412        }
2413        else if (cur->name == "auto")
2414        {
2415            constructor.setAutoSteppingActive(true);
2416        }
2417        else if (cur->name == "title-settings")
2418        {
2419            bool fontRead = getProperties(cur,constructor.getTitleFontDataDefault());
2420            if (fontRead)
2421            {
2422                OSG_INFO<<"Title font details read"<<std::endl;
2423            }
2424        }
2425        else if (cur->name == "text-settings")
2426        {
2427            bool fontRead = getProperties(cur,constructor.getTextFontDataDefault());
2428            if (fontRead)
2429            {
2430                OSG_INFO<<"Text font details read"<<std::endl;
2431            }
2432        }
2433        /*else if (cur->name == "ratio")
2434        {
2435            key = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1);
2436            if (key) constructor.setPresentationAspectRatio(cur->contents);
2437            xmlFree(key);
2438        }*/
2439        else if (cur->name == "path")
2440        {
2441            OSG_INFO<<"Appending search path "<<cur->contents<<std::endl;
2442            osgDB::getDataFilePathList().push_front(expandEnvVarsInFileName(cur->contents));
2443        }
2444        else if (cur->name == "bgcolor")
2445        {
2446            constructor.setBackgroundColor(mapStringToColor(cur->contents),false);
2447        }
2448        else if (cur->name == "textcolor")
2449        {
2450            constructor.setTextColor(mapStringToColor(cur->contents));
2451        }
2452        else if (cur->name == "duration")
2453        {
2454            constructor.setPresentationDuration(osg::asciiToDouble(cur->contents.c_str()));
2455        }
2456        else if (getKeyPosition(cur, keyPosition))
2457        {
2458            constructor.addPresentationKey(keyPosition);
2459        }
2460        else if (readOnlyHoldingPage && cur->name == "holding_slide")
2461        {
2462            constructor.addSlide();
2463            parseSlide (constructor, cur);
2464        }
2465        else if (!readOnlyHoldingPage && cur->name == "slide")
2466        {
2467            constructor.addSlide();
2468
2469            std::string inherit;
2470            if (getProperty(cur, "inherit", inherit) && !inherit.empty() && _templateMap.count(inherit)!=0)
2471            {
2472                parseSlide(constructor, _templateMap[inherit].get(), true, false);
2473                parseSlide (constructor, cur, true, false);
2474                parseSlide(constructor, _templateMap[inherit].get(), false, true);
2475                parseSlide (constructor, cur, false, true);
2476            }
2477            else
2478            {
2479                parseSlide (constructor, cur);
2480            }
2481        }
2482        else if (!readOnlyHoldingPage && cur->name == "modify_slide")
2483        {
2484            int slideNum;
2485            if (getProperty(cur, "slide", slideNum))
2486            {
2487                constructor.selectSlide(slideNum);
2488                parseSlide (constructor, cur);
2489            }
2490            else
2491            {
2492                constructor.addSlide();
2493            }
2494        }
2495        else if (!readOnlyHoldingPage && cur->name == "page")
2496        {
2497            parsePage (constructor, cur);
2498        }
2499        else if (!readOnlyHoldingPage && cur->name == "pdf_document")
2500        {
2501            parsePdfDocument(constructor, cur);
2502        }
2503        else if (!readOnlyHoldingPage && cur->name == "template_slide")
2504        {
2505            std::string name;
2506            if (getProperty(cur, "name", name))
2507            {
2508                _templateMap[name] = cur;
2509                std::cout<<"Defining template slide "<<name<<std::endl;
2510            }
2511        }
2512    }
2513
2514    osgDB::getDataFilePathList() = previousPaths;
2515
2516    return constructor.takePresentation();
2517}
Note: See TracBrowser for help on using the browser.