/* -*-c++-*- Present3D - Copyright (C) 1999-2006 Robert Osfield * * This software is open source and may be redistributed and/or modified under * the terms of the GNU General Public License (GPL) version 2.0. * The full license is in LICENSE.txt file included with this distribution,. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * include LICENSE.txt for more details. */ #include #include #include #include #include #include #include #include "SlideShowConstructor.h" #include #include #include #include #include #include /** * OpenSceneGraph plugin wrapper/converter. */ class ReaderWriterP3DXML : public osgDB::ReaderWriter { public: ReaderWriterP3DXML() { _colorMap["WHITE"] .set(1.0f,1.0f,1.0f,1.0f); _colorMap["BLACK"] .set(0.0f,0.0f,0.0f,1.0f); _colorMap["PURPLE"] .set(1.0f,0.0f,1.0f,1.0f); _colorMap["BLUE"] .set(0.0f,0.0f,1.0f,1.0f); _colorMap["RED"] .set(1.0f,0.0f,0.0f,1.0f); _colorMap["CYAN"] .set(0.0f,1.0f,1.0f,1.0f); _colorMap["YELLOW"] .set(1.0f,1.0f,0.0f,1.0f); _colorMap["GREEN"] .set(0.0f,1.0f,0.0f,1.0f); _colorMap["SKY"] .set(0.2f, 0.2f, 0.4f, 1.0f); _layoutMap["LEFT_TO_RIGHT"] = osgText::Text::LEFT_TO_RIGHT; _layoutMap["RIGHT_TO_LEFT"] = osgText::Text::RIGHT_TO_LEFT; _layoutMap["VERTICAL"] = osgText::Text::VERTICAL; _alignmentMap["LEFT_TOP"] = osgText::Text::LEFT_TOP; _alignmentMap["LEFT_CENTER"] = osgText::Text::LEFT_CENTER; _alignmentMap["LEFT_BOTTOM"] = osgText::Text::LEFT_BOTTOM; _alignmentMap["CENTER_TOP"] = osgText::Text::CENTER_TOP; _alignmentMap["CENTER_CENTER"] = osgText::Text::CENTER_CENTER; _alignmentMap["CENTER_BOTTOM"] = osgText::Text::CENTER_BOTTOM; _alignmentMap["RIGHT_TOP"] = osgText::Text::RIGHT_TOP; _alignmentMap["RIGHT_CENTER"] = osgText::Text::RIGHT_CENTER; _alignmentMap["RIGHT_BOTTOM"] = osgText::Text::RIGHT_BOTTOM; _alignmentMap["LEFT_BASE_LINE"] = osgText::Text::LEFT_BASE_LINE; _alignmentMap["CENTER_BASE_LINE"] = osgText::Text::CENTER_BASE_LINE; _alignmentMap["RIGHT_BASE_LINE"] = osgText::Text::RIGHT_BASE_LINE; _alignmentMap["BASE_LINE"] = osgText::Text::LEFT_BASE_LINE; _stringKeyMap["Home"]=' '; _stringKeyMap["Start"]= osgGA::GUIEventAdapter::KEY_Home; _stringKeyMap["Next"]= osgGA::GUIEventAdapter::KEY_Page_Down; _stringKeyMap["Previous"]=osgGA::GUIEventAdapter::KEY_Page_Up; _stringKeyMap["Up"]=osgGA::GUIEventAdapter::KEY_Up; _stringKeyMap["Down"]=osgGA::GUIEventAdapter::KEY_Down; _stringKeyMap["End"]=osgGA::GUIEventAdapter::KEY_End; _stringKeyMap["Page Down"]=osgGA::GUIEventAdapter::KEY_Page_Down; _stringKeyMap["Page Up"]=osgGA::GUIEventAdapter::KEY_Page_Up; _stringKeyMap["F1"]=osgGA::GUIEventAdapter::KEY_F1; _stringKeyMap["F2"]=osgGA::GUIEventAdapter::KEY_F2; _stringKeyMap["F3"]=osgGA::GUIEventAdapter::KEY_F3; _stringKeyMap["F4"]=osgGA::GUIEventAdapter::KEY_F4; _stringKeyMap["F5"]=osgGA::GUIEventAdapter::KEY_F5; _stringKeyMap["F6"]=osgGA::GUIEventAdapter::KEY_F6; _stringKeyMap["F7"]=osgGA::GUIEventAdapter::KEY_F7; _stringKeyMap["F8"]=osgGA::GUIEventAdapter::KEY_F8; _stringKeyMap["F9"]=osgGA::GUIEventAdapter::KEY_F9; _stringKeyMap["F10"]=osgGA::GUIEventAdapter::KEY_F10; _stringKeyMap["F11"]=osgGA::GUIEventAdapter::KEY_F11; _stringKeyMap["F12"]=osgGA::GUIEventAdapter::KEY_F12; _notifyLevel = osg::INFO; } virtual const char* className() const { return "present3D XML Reader/Writer"; } virtual bool acceptsExtension(const std::string& extension) const { return osgDB::equalCaseInsensitive(extension,"p3d") || osgDB::equalCaseInsensitive(extension,"xml") ; } virtual ReadResult readNode(const std::string& fileName, const osgDB::ReaderWriter::Options* options) const; virtual ReadResult readNode(std::istream& fin, const Options* options) const; ReadResult readNode(osgDB::XmlNode::Input& input, osgDB::ReaderWriter::Options* options) const; void parseModel(osgPresentation::SlideShowConstructor& constructor, osgDB::XmlNode*cur) const; void parseVolume(osgPresentation::SlideShowConstructor& constructor, osgDB::XmlNode*cur) const; void parseStereoPair(osgPresentation::SlideShowConstructor& constructor, osgDB::XmlNode*cur) const; void parseLayer(osgPresentation::SlideShowConstructor& constructor, osgDB::XmlNode*cur) const; void parseBullets(osgPresentation::SlideShowConstructor& constructor, osgDB::XmlNode*cur, bool inheritPreviousLayers, bool defineAsBaseLayer) const; void parseText(osgPresentation::SlideShowConstructor& constructor, osgDB::XmlNode*cur, bool inheritPreviousLayers, bool defineAsBaseLayer) const; void parsePage (osgPresentation::SlideShowConstructor& constructor, osgDB::XmlNode*cur) const; void parseSlide (osgPresentation::SlideShowConstructor& constructor, osgDB::XmlNode*cur, bool parseTitles=true, bool parseLayers=true) const; void parsePdfDocument (osgPresentation::SlideShowConstructor& constructor, osgDB::XmlNode*cur) const; osg::Vec4 mapStringToColor(const std::string& str) const { ColorMap::const_iterator itr=_colorMap.find(str); if (itr!=_colorMap.end()) return itr->second; osg::Vec4 color; if (read(str,color)) return color; else return osg::Vec4(0.0f,0.0f,0.0f,1.0f); } inline osg::Vec4 accumulateRotation(const osg::Vec4& lhs, const osg::Vec4& rhs) const { osg::Quat qlhs,qrhs; qlhs.makeRotate(osg::DegreesToRadians(lhs[0]),lhs[1],lhs[2],lhs[3]); qrhs.makeRotate(osg::DegreesToRadians(rhs[0]),rhs[1],rhs[2],rhs[3]); osg::Quat quat = qlhs*qrhs; osg::Vec4d result; quat.getRotate ( result[0], result[1], result[2], result[3]); result[0] = osg::RadiansToDegrees(result[0]); return result; } inline bool read(const char* str, int& value) const; inline bool read(const char* str, float& value) const; inline bool read(const char* str, double& value) const; inline bool read(const char* str, osg::Vec2& value) const; inline bool read(const char* str, osg::Vec3& value) const; inline bool read(const char* str, osg::Vec4& value) const; inline bool read(const std::string& str, int& value) const; inline bool read(const std::string& str, float& value) const; inline bool read(const std::string& str, double& value) const; inline bool read(const std::string& str, osg::Vec2& value) const; inline bool read(const std::string& str, osg::Vec3& value) const; inline bool read(const std::string& str, osg::Vec4& value) const; bool getProperty(osgDB::XmlNode*cur, const char* token) const; bool getProperty(osgDB::XmlNode*cur, const char* token, int& value) const; bool getProperty(osgDB::XmlNode*cur, const char* token, float& value) const; bool getProperty(osgDB::XmlNode*cur, const char* token, double& value) const; bool getProperty(osgDB::XmlNode*cur, const char* token, osg::Vec2& value) const; bool getProperty(osgDB::XmlNode*cur, const char* token, osg::Vec3& value) const; bool getProperty(osgDB::XmlNode*cur, const char* token, osg::Vec4& value) const; bool getProperty(osgDB::XmlNode*cur, const char* token, std::string& value) const; bool getProperty(osgDB::XmlNode*cur, const char* token, osgText::Text::Layout& value) const; bool getProperty(osgDB::XmlNode*cur, const char* token, osgText::Text::AlignmentType& value) const; bool getProperties(osgDB::XmlNode*cur, osgPresentation::SlideShowConstructor::PositionData& value) const; bool getProperties(osgDB::XmlNode*cur, osgPresentation::SlideShowConstructor::FontData& value) const; bool getProperties(osgDB::XmlNode*cur, osgPresentation::SlideShowConstructor::ModelData& value) const; bool getProperties(osgDB::XmlNode*cur, osgPresentation::SlideShowConstructor::ImageData& value) const; bool getJumpProperties(osgDB::XmlNode*cur, bool& relativeJump, int& slideNum, int& layerNum) const; bool getKeyPositionInner(osgDB::XmlNode*cur, osgPresentation::KeyPosition& keyPosition) const; bool getKeyPosition(osgDB::XmlNode*cur, osgPresentation::KeyPosition& keyPosition) const; typedef std::map ColorMap; typedef std::map LayoutMap; typedef std::map AlignmentMap; typedef std::map StringKeyMap; std::string expandEnvVarsInFileName(const std::string& filename) const; ColorMap _colorMap; LayoutMap _layoutMap; AlignmentMap _alignmentMap; StringKeyMap _stringKeyMap; typedef std::map > TemplateMap; mutable TemplateMap _templateMap; osg::NotifySeverity _notifyLevel; }; // Register with Registry to instantiate the above reader/writer. osgDB::RegisterReaderWriterProxy g_readerWriter_P3DXML_Proxy; std::string ReaderWriterP3DXML::expandEnvVarsInFileName(const std::string& filename) const { std::string argument(filename); std::string::size_type start_pos = argument.find("${"); while (start_pos != std::string::npos) { std::string::size_type end_pos = argument.find("}",start_pos); if (start_pos != std::string::npos) { std::string var = argument.substr(start_pos+2, end_pos-start_pos-2); const char* str = getenv(var.c_str()); if (str) { argument.erase(start_pos, end_pos-start_pos+1); argument.insert(start_pos, str); } start_pos = argument.find("${",end_pos); } else { start_pos = std::string::npos; } } return argument; } bool ReaderWriterP3DXML::read(const char* str, int& value) const { if (!str) return false; std::istringstream iss((const char*)str); iss >> value; return !iss.fail(); } bool ReaderWriterP3DXML::read(const char* str, float& value) const { if (!str) return false; std::istringstream iss((const char*)str); iss >> value; return !iss.fail(); } bool ReaderWriterP3DXML::read(const char* str, double& value) const { if (!str) return false; std::istringstream iss((const char*)str); iss >> value; return !iss.fail(); } bool ReaderWriterP3DXML::read(const char* str, osg::Vec2& value) const { if (!str) return false; std::istringstream iss((const char*)str); iss >> value.x() >> value.y(); return !iss.fail(); } bool ReaderWriterP3DXML::read(const char* str, osg::Vec3& value) const { if (!str) return false; std::istringstream iss((const char*)str); iss >> value.x() >> value.y() >> value.z(); return !iss.fail(); } bool ReaderWriterP3DXML::read(const char* str, osg::Vec4& value) const { if (!str) return false; std::istringstream iss((const char*)str); iss >> value.x() >> value.y() >> value.z() >> value.w(); return !iss.fail(); } bool ReaderWriterP3DXML::read(const std::string& str, int& value) const { std::istringstream iss(str); iss >> value; return !iss.fail(); } bool ReaderWriterP3DXML::read(const std::string& str, float& value) const { std::istringstream iss(str); iss >> value; return !iss.fail(); } bool ReaderWriterP3DXML::read(const std::string& str, double& value) const { std::istringstream iss(str); iss >> value; return !iss.fail(); } bool ReaderWriterP3DXML::read(const std::string& str, osg::Vec2& value) const { std::istringstream iss(str); iss >> value.x() >> value.y(); return !iss.fail(); } bool ReaderWriterP3DXML::read(const std::string& str, osg::Vec3& value) const { std::istringstream iss(str); iss >> value.x() >> value.y() >> value.z(); return !iss.fail(); } bool ReaderWriterP3DXML::read(const std::string& str, osg::Vec4& value) const { std::istringstream iss(str); iss >> value.x() >> value.y() >> value.z() >> value.w(); return !iss.fail(); } bool ReaderWriterP3DXML::getProperty(osgDB::XmlNode* cur, const char* token) const { return cur->properties.count(token)!=0; } bool ReaderWriterP3DXML::getProperty(osgDB::XmlNode*cur, const char* token, int& value) const { osgDB::XmlNode::Properties::iterator itr = cur->properties.find(token); if (itr==cur->properties.end()) return false; return read(itr->second,value); } bool ReaderWriterP3DXML::getProperty(osgDB::XmlNode*cur, const char* token, float& value) const { osgDB::XmlNode::Properties::iterator itr = cur->properties.find(token); if (itr==cur->properties.end()) return false; return read(itr->second,value); } bool ReaderWriterP3DXML::getProperty(osgDB::XmlNode*cur, const char* token, double& value) const { osgDB::XmlNode::Properties::iterator itr = cur->properties.find(token); if (itr==cur->properties.end()) return false; return read(itr->second,value); } bool ReaderWriterP3DXML::getProperty(osgDB::XmlNode*cur, const char* token, osg::Vec2& value) const { osgDB::XmlNode::Properties::iterator itr = cur->properties.find(token); if (itr==cur->properties.end()) return false; return read(itr->second,value); } bool ReaderWriterP3DXML::getProperty(osgDB::XmlNode*cur, const char* token, osg::Vec3& value) const { osgDB::XmlNode::Properties::iterator itr = cur->properties.find(token); if (itr==cur->properties.end()) return false; return read(itr->second,value); } bool ReaderWriterP3DXML::getProperty(osgDB::XmlNode*cur, const char* token, osg::Vec4& value) const { osgDB::XmlNode::Properties::iterator itr = cur->properties.find(token); if (itr==cur->properties.end()) return false; return read(itr->second,value); } bool ReaderWriterP3DXML::getProperty(osgDB::XmlNode*cur, const char* token, std::string& value) const { osgDB::XmlNode::Properties::iterator itr = cur->properties.find(token); if (itr==cur->properties.end()) return false; value = itr->second; return true; } bool ReaderWriterP3DXML::getProperty(osgDB::XmlNode*cur, const char* token, osgText::Text::Layout& value) const { osgDB::XmlNode::Properties::iterator pitr = cur->properties.find(token); if (pitr==cur->properties.end()) return false; const std::string& str = pitr->second; LayoutMap::const_iterator itr = _layoutMap.find(str); if (itr!=_layoutMap.end()) { value = itr->second; } return true; } bool ReaderWriterP3DXML::getProperty(osgDB::XmlNode*cur, const char* token, osgText::Text::AlignmentType& value) const { osgDB::XmlNode::Properties::iterator pitr = cur->properties.find(token); if (pitr==cur->properties.end()) return false; const std::string& str = pitr->second; AlignmentMap::const_iterator itr = _alignmentMap.find(str); if (itr!=_alignmentMap.end()) { value = itr->second; } return true; } bool ReaderWriterP3DXML::getProperties(osgDB::XmlNode*cur, osgPresentation::SlideShowConstructor::PositionData& value) const { bool propertiesRead=false; osg::Vec3 position(0.0f,1.0f,0.0f); osg::Vec4 rotate(0.0f,0.0f,0.0f,1.0f); float scale = 1.0f; osg::Vec4 rotation(0.0f,0.0f,0.0f,1.0f); // temporary std::string str; if (getProperty(cur, "coordinate_frame", str)) { propertiesRead = true; if (str=="model") value.frame = osgPresentation::SlideShowConstructor::MODEL; else if (str=="slide") value.frame = osgPresentation::SlideShowConstructor::SLIDE; else osg::notify(_notifyLevel)<<"Parser error - coordinate_frame=\""<contents; if (!filename.empty()) { constructor.addModel(filename, positionRead ? positionData : constructor.getModelPositionData(), modelData); } } void ReaderWriterP3DXML::parseVolume(osgPresentation::SlideShowConstructor& constructor, osgDB::XmlNode*cur) const { osgPresentation::SlideShowConstructor::PositionData positionData = constructor.getModelPositionData(); bool positionRead = getProperties(cur,positionData); std::string filename = cur->contents; if (!filename.empty()) { constructor.addVolume(filename, positionRead ? positionData : constructor.getModelPositionData()); } } void ReaderWriterP3DXML::parseStereoPair(osgPresentation::SlideShowConstructor& constructor, osgDB::XmlNode*cur) const { std::string filenameLeft; std::string filenameRight; osgPresentation::SlideShowConstructor::PositionData positionData = constructor.getImagePositionData(); bool positionRead = getProperties(cur,positionData); osgPresentation::SlideShowConstructor::ImageData imageDataLeft;// = constructor.getImageData(); osgPresentation::SlideShowConstructor::ImageData imageDataRight;// = constructor.getImageData(); for(osgDB::XmlNode::Children::iterator itr = cur->children.begin(); itr != cur->children.end(); ++itr) { osgDB::XmlNode* child = itr->get(); if (child->name == "image_left") { getProperties(child,imageDataLeft); filenameLeft = child->name; } if (cur->name == "image_right") { getProperties(child,imageDataRight); filenameRight = child->name; getProperties(cur,imageDataRight); } } if (!filenameLeft.empty() && !filenameRight.empty()) constructor.addStereoImagePair(filenameLeft,imageDataLeft, filenameRight, imageDataRight, positionRead ? positionData : constructor.getImagePositionData()); } bool ReaderWriterP3DXML::getKeyPosition(osgDB::XmlNode*cur, osgPresentation::KeyPosition& keyPosition) const { if (cur->name == "key") { return getKeyPositionInner(cur, keyPosition); } if (cur->name == "escape" || cur->name == "esc" || cur->name == "exit") { keyPosition.set(osgGA::GUIEventAdapter::KEY_Escape, 0.0f, 0.0f); return true; } return false; } bool ReaderWriterP3DXML::getKeyPositionInner(osgDB::XmlNode*cur, osgPresentation::KeyPosition& keyPosition) const { // x in range -1 to 1, from left to right float x = FLT_MAX; getProperty(cur, "x", x); // y in range -1 to 1, from bottom to top float y = FLT_MAX; getProperty(cur, "y", y); float h = FLT_MAX; if (getProperty(cur, "h", h)) { // h in range 0.0 to 1, from left to right x = h*2.0f-1.0f; } float v = FLT_MAX; if (getProperty(cur, "v", v)) { // v in range 0.0 to 1, from bottom to top y = v*2.0f-1.0f; } std::string key = cur->contents; unsigned int keyValue = 0; StringKeyMap::const_iterator itr=_stringKeyMap.find(key); if (itr != _stringKeyMap.end()) { keyValue = itr->second; } else if (key.length()==1) { keyValue = key[0]; } else { osg::notify(osg::NOTICE)<<"Warning: unreconginized key sequence '"<children.begin(); itr != root->children.end(); ++itr) { osgDB::XmlNode* cur = itr->get(); if (cur->name == "run") { osg::notify(osg::INFO)<<"run ["<contents<<"]"<contents); } else if (cur->name == "jump") { osg::notify(osg::NOTICE)<<"Parsed Jump "<name == "click_to_run") { bool relativeJump = true; int slideNum = 0; int layerNum = 0; getJumpProperties(cur, relativeJump, slideNum, layerNum); osg::notify(osg::INFO)<<"click_to_run ["<contents<<"]"<contents,osgPresentation::RUN, relativeJump, slideNum, layerNum); } else if (cur->name == "click_to_load") { bool relativeJump = true; int slideNum = 0; int layerNum = 0; getJumpProperties(cur, relativeJump, slideNum, layerNum); osg::notify(osg::INFO)<<"click_to_load ["<contents<<"]"<contents,osgPresentation::LOAD, relativeJump, slideNum, layerNum); } else if (cur->name == "click_to_event") { bool relativeJump = true; int slideNum = 0; int layerNum = 0; getJumpProperties(cur, relativeJump, slideNum, layerNum); if (getKeyPositionInner( cur, keyPosition)) { osg::notify(osg::INFO)<<"click_to_event ["<name == "click_to_jump") { bool relativeJump = true; int slideNum = 0; int layerNum = 0; getJumpProperties(cur, relativeJump, slideNum, layerNum); constructor.layerClickEventOperation(osgPresentation::JUMP, relativeJump, slideNum, layerNum); } else if (cur->name == "newline") { constructor.translateTextCursor(osg::Vec3(0.0f,-0.05f,0.0f)); } else if (cur->name == "indent") { float localIndent = 0.05f; constructor.translateTextCursor(osg::Vec3(localIndent,0.0f,0.0f)); totalIndent += localIndent; } else if (cur->name == "unindent") { float localIndent = -0.05f; constructor.translateTextCursor(osg::Vec3(localIndent,0.0f,0.0f)); totalIndent += localIndent; } else if (cur->name == "bullet") { osg::notify(osg::INFO)<<"bullet ["<contents<<"]"<contents, positionRead ? positionData : constructor.getTextPositionData(), fontRead ? fontData : constructor.getTextFontData()); } else if (cur->name == "paragraph") { osgPresentation::SlideShowConstructor::PositionData positionData = constructor.getTextPositionData(); bool positionRead = getProperties(cur,positionData); osgPresentation::SlideShowConstructor::FontData fontData = constructor.getTextFontData(); bool fontRead = getProperties(cur,fontData); constructor.addParagraph(cur->contents, positionRead ? positionData : constructor.getTextPositionData(), fontRead ? fontData : constructor.getTextFontData()); } else if (cur->name == "image") { osgPresentation::SlideShowConstructor::PositionData positionData = constructor.getImagePositionData(); bool positionRead = getProperties(cur,positionData); osgPresentation::SlideShowConstructor::ImageData imageData;// = constructor.getImageData(); getProperties(cur,imageData); constructor.addImage(cur->contents, positionRead ? positionData : constructor.getImagePositionData(), imageData); } else if (cur->name == "vnc") { osgPresentation::SlideShowConstructor::PositionData positionData = constructor.getImagePositionData(); bool positionRead = getProperties(cur,positionData); osgPresentation::SlideShowConstructor::ImageData imageData;// = constructor.getImageData(); getProperties(cur,imageData); constructor.addVNC(cur->contents, positionRead ? positionData : constructor.getImagePositionData(), imageData); } else if (cur->name == "browser") { osgPresentation::SlideShowConstructor::PositionData positionData = constructor.getImagePositionData(); bool positionRead = getProperties(cur,positionData); osgPresentation::SlideShowConstructor::ImageData imageData;// = constructor.getImageData(); getProperties(cur,imageData); constructor.addBrowser(cur->contents, positionRead ? positionData : constructor.getImagePositionData(), imageData); } else if (cur->name == "pdf") { osgPresentation::SlideShowConstructor::PositionData positionData = constructor.getImagePositionData(); bool positionRead = getProperties(cur,positionData); osgPresentation::SlideShowConstructor::ImageData imageData;// = constructor.getImageData(); getProperties(cur,imageData); constructor.addPDF(cur->contents, positionRead ? positionData : constructor.getImagePositionData(), imageData); } else if (cur->name == "stereo_pair") { parseStereoPair(constructor, cur); } else if (cur->name == "model") { parseModel(constructor, cur); } else if (cur->name == "volume") { parseVolume(constructor, cur); } else if (cur->name == "duration") { constructor.setLayerDuration(atof(cur->contents.c_str())); } else if (getKeyPosition(cur, keyPosition)) { constructor.addLayerKey(keyPosition); } } if (totalIndent != 0.0f) { constructor.translateTextCursor(osg::Vec3(-totalIndent,0.0f,0.0f)); } } void ReaderWriterP3DXML::parseBullets(osgPresentation::SlideShowConstructor& constructor, osgDB::XmlNode*cur, bool inheritPreviousLayers, bool defineAsBaseLayer) const { constructor.addLayer(inheritPreviousLayers, defineAsBaseLayer); osg::notify(osg::INFO)<<"bullets ["<contents<<"]"<contents, positionRead ? positionData : constructor.getTextPositionData(), fontRead ? fontData : constructor.getTextFontData()); } void ReaderWriterP3DXML::parseText(osgPresentation::SlideShowConstructor& constructor, osgDB::XmlNode*cur, bool inheritPreviousLayers, bool defineAsBaseLayer) const { constructor.addLayer(inheritPreviousLayers, defineAsBaseLayer); osg::notify(osg::INFO)<<"text ["<contents<<"]"<contents, positionRead ? positionData : constructor.getTextPositionData(), fontRead ? fontData : constructor.getTextFontData()); } void ReaderWriterP3DXML::parsePage(osgPresentation::SlideShowConstructor& constructor, osgDB::XmlNode*cur) const { constructor.addSlide(); std::string title; getProperty(cur, "title", title); std::string inherit; getProperty(cur, "inherit", inherit); if (!inherit.empty() && _templateMap.count(inherit)!=0) { parseSlide(constructor, _templateMap[inherit].get(), true, false); } if (!title.empty()) { constructor.setSlideTitle(title, constructor.getTitlePositionData(), constructor.getTitleFontData()); } if (!inherit.empty() && _templateMap.count(inherit)!=0) { parseSlide(constructor, _templateMap[inherit].get(), false, true); } constructor.addLayer(true,false); osgPresentation::SlideShowConstructor::PositionData positionData = constructor.getTextPositionData(); bool positionRead = getProperties(cur,positionData); osgPresentation::SlideShowConstructor::FontData fontData = constructor.getTextFontData(); bool fontRead = getProperties(cur,fontData); constructor.addParagraph(cur->contents, positionRead ? positionData : constructor.getTextPositionData(), fontRead ? fontData : constructor.getTextFontData()); } void ReaderWriterP3DXML::parsePdfDocument(osgPresentation::SlideShowConstructor& constructor, osgDB::XmlNode*cur) const { std::string title; getProperty(cur, "title", title); std::string inherit; getProperty(cur, "inherit", inherit); constructor.addSlide(); if (!inherit.empty() && _templateMap.count(inherit)!=0) { parseSlide(constructor, _templateMap[inherit].get(), true, false); } if (!title.empty()) { constructor.setSlideTitle(title, constructor.getTitlePositionData(), constructor.getTitleFontData()); } if (!inherit.empty() && _templateMap.count(inherit)!=0) { parseSlide(constructor, _templateMap[inherit].get(), false, true); } constructor.addLayer(true,false); osgPresentation::SlideShowConstructor::PositionData positionData = constructor.getImagePositionData(); getProperties(cur,positionData); osgPresentation::SlideShowConstructor::ImageData imageData;// = constructor.getImageData(); imageData.page = 0; getProperties(cur,imageData); osg::Image* image = constructor.addInteractiveImage(cur->contents, positionData, imageData); osgWidget::PdfImage* pdfImage = dynamic_cast(image); if (pdfImage) { int numPages = pdfImage->getNumOfPages(); osg::notify(osg::NOTICE)<<"NumOfPages = "<1) { for(int pageNum=1; pageNumcontents, positionData, imageData); } } } } void ReaderWriterP3DXML::parseSlide (osgPresentation::SlideShowConstructor& constructor, osgDB::XmlNode* root, bool parseTitles, bool parseLayers) const { osg::Vec4 previous_bgcolor = constructor.getBackgroundColor(); osg::Vec4 previous_textcolor = constructor.getTextColor(); // create a keyPosition just in case we need it. osgPresentation::KeyPosition keyPosition; for(osgDB::XmlNode::Children::iterator itr = root->children.begin(); itr != root->children.end(); ++itr) { osgDB::XmlNode* cur = itr->get(); if (parseTitles) { if (cur->name == "title") { osgPresentation::SlideShowConstructor::PositionData positionData = constructor.getTitlePositionData(); bool positionRead = getProperties(cur,positionData); osgPresentation::SlideShowConstructor::FontData fontData = constructor.getTitleFontData(); bool fontRead = getProperties(cur,fontData); constructor.setSlideTitle(cur->contents, positionRead ? positionData : constructor.getTitlePositionData(), fontRead ? fontData : constructor.getTitleFontData()); } else if (cur->name == "background") { constructor.setSlideBackground(cur->contents); } else if (cur->name == "bgcolor") { constructor.setBackgroundColor(mapStringToColor(cur->contents),true); } else if (cur->name == "textcolor") { constructor.setTextColor(mapStringToColor(cur->contents)); } } if (parseLayers) { if (cur->name == "base") { constructor.addLayer(true, true); parseLayer (constructor, cur); } else if (cur->name == "layer") { constructor.addLayer(true, false); parseLayer (constructor, cur); } else if (cur->name == "clean_layer") { constructor.addLayer(false, false); parseLayer (constructor, cur); } else if (cur->name == "modify_layer") { int layerNum; if (getProperty(cur, "layer", layerNum)) { constructor.selectLayer(layerNum); } else { constructor.addLayer(true, false); } parseLayer (constructor, cur); } else if (cur->name == "bullets") { parseBullets (constructor, cur,true, false); } else if (cur->name == "duration") { constructor.setSlideDuration(atof(cur->contents.c_str())); } else if (getKeyPosition(cur, keyPosition)) { constructor.addSlideKey(keyPosition); } } } constructor.setBackgroundColor(previous_bgcolor,false); constructor.setTextColor(previous_textcolor); return; } #include struct MyFindFileCallback : public osgDB::FindFileCallback { virtual std::string findDataFile(const std::string& filename, const osgDB::Options* options, osgDB::CaseSensitivity caseSensitivity) { osg::notify(osg::NOTICE)<getDatabasePathList() : osgDB::getDataFilePathList(); for(osgDB::FilePathList::const_iterator itr = paths.begin(); itr != paths.end(); ++itr) { const std::string& path = *itr; std::string newpath = osgDB::concatPaths(path, filename); if (osgDB::containsServerAddress(path)) { osgDB::ReaderWriter* rw = osgDB::Registry::instance()->getReaderWriterForExtension("curl"); osg::notify(osg::NOTICE)<<" file on server "<<*itr<<", try path "<findDataFileImplementation(filename, options, caseSensitivity); } }; class MyReadFileCallback : public virtual osgDB::ReadFileCallback { public: osgDB::FilePathList _paths; typedef std::map< std::string, osg::ref_ptr > ObjectCache; enum ObjectType { OBJECT, IMAGE, HEIGHT_FIELD, NODE, SHADER }; osgDB::ReaderWriter::ReadResult readLocal(ObjectType type, const std::string& filename, const osgDB::Options* options) { osg::notify(osg::INFO)<<"Trying local file "<readObjectImplementation(filename,options); case(IMAGE): return osgDB::Registry::instance()->readImageImplementation(filename,options); case(HEIGHT_FIELD): return osgDB::Registry::instance()->readHeightFieldImplementation(filename,options); case(NODE): return osgDB::Registry::instance()->readNodeImplementation(filename,options); case(SHADER): return osgDB::Registry::instance()->readShaderImplementation(filename,options); } return osgDB::ReaderWriter::ReadResult::FILE_NOT_HANDLED; } osgDB::ReaderWriter::ReadResult readFileCache(ObjectType type, const std::string& filename, const osgDB::Options* options) { osgDB::FileCache* fileCache = options ? options->getFileCache() : 0; if (!fileCache) fileCache = osgDB::Registry::instance()->getFileCache(); if (!fileCache) return osgDB::ReaderWriter::ReadResult::FILE_NOT_FOUND; osg::notify(osg::INFO)<<"Trying fileCache "<isFileAppropriateForFileCache(filename)) { if (fileCache->existsInCache(filename)) { switch(type) { case(OBJECT): result = fileCache->readObject(filename, 0); break; case(IMAGE): result = fileCache->readImage(filename, 0); break; case(HEIGHT_FIELD): result = fileCache->readHeightField(filename, 0); break; case(NODE): result = fileCache->readNode(filename,0); break; case(SHADER): result = fileCache->readShader(filename, 0); break; } if (result.success()) { osg::notify(osg::INFO)<<" File read from FileCache."<createCacheFileName(filename)<getReaderWriterForExtension("curl"); if (!rw) return osgDB::ReaderWriter::ReadResult::FILE_NOT_HANDLED; switch(type) { case(OBJECT): result = rw->readObject(filename,options); break; case(IMAGE): result = rw->readImage(filename,options); break; case(HEIGHT_FIELD): result = rw->readHeightField(filename,options); break; case(NODE): result = rw->readNode(filename,options); break; case(SHADER): result = rw->readShader(filename,options); break; } if (result.success()) { osgDB::FileCache* fileCache = options ? options->getFileCache() : 0; if (!fileCache) fileCache = osgDB::Registry::instance()->getFileCache(); if (fileCache && fileCache->isFileAppropriateForFileCache(filename)) { switch(type) { case(OBJECT): fileCache->writeObject(*result.getObject(),filename,options); break; case(IMAGE): result.getImage()->setFileName(filename); fileCache->writeImage(*result.getImage(),filename,options); break; case(HEIGHT_FIELD): fileCache->writeHeightField(*result.getHeightField(),filename,options); break; case(NODE): fileCache->writeNode(*result.getNode(),filename,options); break; case(SHADER): fileCache->writeShader(*result.getShader(),filename,options); break; } } return result; } return osgDB::ReaderWriter::ReadResult::FILE_NOT_FOUND; } osgDB::ReaderWriter::ReadResult read(const osgDB::FilePathList& filePathList, ObjectType type, const std::string& filename, const osgDB::Options* options, bool checkLocalFiles) { // go look in http paths for(osgDB::FilePathList::const_iterator itr = filePathList.begin(); itr != filePathList.end(); ++itr) { const std::string& path = *itr; std::string newpath = path.empty() ? filename : osgDB::concatPaths(path, filename); osgDB::ReaderWriter::ReadResult result; if (osgDB::containsServerAddress(newpath)) { if (checkLocalFiles) result = readFileCache(type, newpath, options); else result = readServer(type, newpath, options); } else if (checkLocalFiles && osgDB::fileExists(newpath)) { result = readLocal(type, newpath, options); } if (result.success()) { osg::notify(osg::INFO)<<" inserting object into file cache "<setPluginStringData("filename",newpath); return result; } } return osgDB::ReaderWriter::ReadResult::FILE_NOT_FOUND; } osgDB::ReaderWriter::ReadResult read(ObjectType type, const std::string& filename, const osgDB::Options* options) { osgDB::FileCache* fileCache = options ? options->getFileCache() : 0; if (!fileCache) fileCache = osgDB::Registry::instance()->getFileCache(); if (fileCache && !fileCache->isFileAppropriateForFileCache(filename)) fileCache = 0; osg::notify(osg::INFO)<<"reading file "<second.valid()) { osg::notify(osg::INFO)<<"File retrieved from cache, filename="<second.get(); } else { osg::notify(osg::INFO)<<"File failed to load previously, won't attempt a second time "<getDatabasePathList().empty())) { result = read(options->getDatabasePathList(), type, filename, options, checkLocalFiles); if (result.success()) return result; } result = read(osgDB::Registry::instance()->getDataFilePathList(), type, filename, options, checkLocalFiles); if (result.success()) return result; } { bool checkLocalFiles = false; osgDB::ReaderWriter::ReadResult result = read(_paths, type, filename, options, checkLocalFiles); if (result.success()) return result; if (options && !(options->getDatabasePathList().empty())) { result = read(options->getDatabasePathList(), type, filename, options, checkLocalFiles); if (result.success()) return result; } result = read(osgDB::Registry::instance()->getDataFilePathList(), type, filename, options, checkLocalFiles); if (result.success()) return result; } _objectCache[filename] = 0; return osgDB::ReaderWriter::ReadResult::FILE_NOT_FOUND; } virtual osgDB::ReaderWriter::ReadResult readObject(const std::string& filename, const osgDB::Options* options) { return read(OBJECT, filename, options); } virtual osgDB::ReaderWriter::ReadResult readImage(const std::string& filename, const osgDB::Options* options) { return read(IMAGE, filename, options); } virtual osgDB::ReaderWriter::ReadResult readHeightField(const std::string& filename, const osgDB::Options* options) { return read(HEIGHT_FIELD, filename, options); } virtual osgDB::ReaderWriter::ReadResult readNode(const std::string& filename, const osgDB::Options* options) { return read(NODE, filename, options); } virtual osgDB::ReaderWriter::ReadResult readShader(const std::string& filename, const osgDB::Options* options) { return read(SHADER, filename, options); } protected: virtual ~MyReadFileCallback() {} ObjectCache _objectCache; }; osgDB::ReaderWriter::ReadResult ReaderWriterP3DXML::readNode(const std::string& file, const osgDB::ReaderWriter::Options* options) const { std::string ext = osgDB::getLowerCaseFileExtension(file); if (!acceptsExtension(ext)) return ReadResult::FILE_NOT_HANDLED; std::string fileName = osgDB::findDataFile( file ); if (fileName.empty()) return ReadResult::FILE_NOT_FOUND; // code for setting up the database path so that internally referenced file are searched for on relative paths. osg::ref_ptr local_opt = options ? static_cast(options->clone(osg::CopyOp::SHALLOW_COPY)) : new Options; local_opt->getDatabasePathList().push_front(osgDB::getFilePath(fileName)); //local_opt->setFindFileCallback(new MyFindFileCallback); local_opt->setReadFileCallback(new MyReadFileCallback); osgDB::XmlNode::Input input; input.open(fileName); input.readAllDataIntoBuffer(); return readNode(input, local_opt); } osgDB::ReaderWriter::ReadResult ReaderWriterP3DXML::readNode(std::istream& fin, const Options* options) const { osgDB::XmlNode::Input input; input.attach(fin); input.readAllDataIntoBuffer(); osg::ref_ptr local_opt = options ? static_cast(options->clone(osg::CopyOp::SHALLOW_COPY)) : new Options; //local_opt->setFindFileCallback(new MyFindFileCallback); local_opt->setReadFileCallback(new MyReadFileCallback); return readNode(input, local_opt); } osgDB::ReaderWriter::ReadResult ReaderWriterP3DXML::readNode(osgDB::XmlNode::Input& input, osgDB::ReaderWriter::Options* options) const { bool readOnlyHoldingPage = options ? options->getOptionString()=="holding_slide" : false; // create a keyPosition just in case we need it. osgPresentation::KeyPosition keyPosition; osg::ref_ptr doc = new osgDB::XmlNode; osgDB::XmlNode* root = 0; doc->read(input); osg::notify(osg::NOTICE)<<"P3D parsing"<write(std::cout); if (doc == NULL ) { fprintf(stderr,"Document not parsed successfully. \n"); return ReadResult::FILE_NOT_HANDLED; } for(osgDB::XmlNode::Children::iterator itr = doc->children.begin(); itr != doc->children.end() && !root; ++itr) { if ((*itr)->name=="presentation") root = itr->get(); } if (root == NULL) { fprintf(stderr,"empty document\n"); return ReadResult::FILE_NOT_HANDLED; } if (root->name!="presentation") { fprintf(stderr,"document of the wrong type, root node != presentation"); return ReadResult::FILE_NOT_HANDLED; } osgPresentation::SlideShowConstructor constructor(options); osgDB::FilePathList previousPaths = osgDB::getDataFilePathList(); bool readSlide = false; for(osgDB::XmlNode::Children::iterator itr = root->children.begin(); itr != root->children.end(); ++itr) { osgDB::XmlNode* cur = itr->get(); if (cur->name=="env") { char* str = strdup(cur->contents.c_str()); osg::notify(osg::INFO)<<"putenv("<(options->getReadFileCallback()) : 0; if (options && !(options->getDatabasePathList().empty())) { pathToPresentation = options->getDatabasePathList().front(); if (readFileCallback) readFileCallback->_paths.push_front(pathToPresentation); } for(osgDB::XmlNode::Children::iterator itr = root->children.begin(); itr != root->children.end(); ++itr) { osgDB::XmlNode* cur = itr->get(); if (cur->name == "path") { std::string newpath = expandEnvVarsInFileName(cur->contents); // now check if an absolue or http path std::string::size_type colonPos = newpath.find_first_of(':'); std::string::size_type backslashPos = newpath.find_first_of('/'); std::string::size_type forwardslashPos = newpath.find_first_of('\\'); bool relativePath = colonPos == std::string::npos && backslashPos != 0 && forwardslashPos != 0; if (relativePath && !pathToPresentation.empty()) { newpath = osgDB::concatPaths(pathToPresentation, newpath); osg::notify(osg::NOTICE)<<"relative path = "<contents<<", newpath="<contents); } else if (cur->name == "loop") { constructor.setLoopPresentation(true); } else if (cur->name == "auto") { constructor.setAutoSteppingActive(true); } else if (cur->name == "title-settings") { bool fontRead = getProperties(cur,constructor.getTitleFontDataDefault()); if (fontRead) { osg::notify(osg::INFO)<<"Title font details read"<name == "text-settings") { bool fontRead = getProperties(cur,constructor.getTextFontDataDefault()); if (fontRead) { osg::notify(osg::INFO)<<"Text font details read"<name == "ratio") { key = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1); if (key) constructor.setPresentationAspectRatio(cur->contents); xmlFree(key); }*/ else if (cur->name == "path") { osg::notify(osg::INFO)<<"Appending search path "<contents<contents)); } else if (cur->name == "bgcolor") { constructor.setBackgroundColor(mapStringToColor(cur->contents),false); } else if (cur->name == "textcolor") { constructor.setTextColor(mapStringToColor(cur->contents)); } else if (cur->name == "duration") { constructor.setPresentationDuration(atof(cur->contents.c_str())); } else if (getKeyPosition(cur, keyPosition)) { constructor.addPresentationKey(keyPosition); } else if (readOnlyHoldingPage && cur->name == "holding_slide") { readSlide = true; constructor.addSlide(); parseSlide (constructor, cur); } else if (!readOnlyHoldingPage && cur->name == "slide") { readSlide = true; constructor.addSlide(); std::string inherit; if (getProperty(cur, "inherit", inherit) && !inherit.empty() && _templateMap.count(inherit)!=0) { parseSlide(constructor, _templateMap[inherit].get(), true, false); parseSlide (constructor, cur, true, false); parseSlide(constructor, _templateMap[inherit].get(), false, true); parseSlide (constructor, cur, false, true); } else { parseSlide (constructor, cur); } } else if (!readOnlyHoldingPage && cur->name == "modify_slide") { readSlide = true; int slideNum; if (getProperty(cur, "slide", slideNum)) { constructor.selectSlide(slideNum); parseSlide (constructor, cur); } else { constructor.addSlide(); } } else if (!readOnlyHoldingPage && cur->name == "page") { readSlide = true; parsePage (constructor, cur); } else if (!readOnlyHoldingPage && cur->name == "pdf_document") { readSlide = true; parsePdfDocument(constructor, cur); } else if (!readOnlyHoldingPage && cur->name == "template_slide") { readSlide = true; std::string name; if (getProperty(cur, "name", name)) { _templateMap[name] = cur; std::cout<<"Defining template slide "<