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

Revision 13331, 104.9 kB (checked in by robert, 41 hours ago)

Improved support for controlling the ShadingModel? via the VolumeSettings? object

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