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

Revision 13041, 82.4 kB (checked in by robert, 3 years ago)

Ran script to remove trailing spaces and tabs

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