#include "SessionVisitor.h" #include "Log.h" #include "Scene.h" #include "Decorations.h" #include "Source.h" #include "MediaSource.h" #include "Session.h" #include "SessionSource.h" #include "PatternSource.h" #include "DeviceSource.h" #include "NetworkSource.h" #include "ImageShader.h" #include "ImageProcessingShader.h" #include "MediaPlayer.h" #include #include using namespace tinyxml2; SessionVisitor::SessionVisitor(tinyxml2::XMLDocument *doc, tinyxml2::XMLElement *root, bool recursive) : Visitor(), recursive_(recursive), xmlCurrent_(root) { if (doc == nullptr) xmlDoc_ = new XMLDocument; else xmlDoc_ = doc; } tinyxml2::XMLElement *SessionVisitor::NodeToXML(Node &n, tinyxml2::XMLDocument *doc) { XMLElement *newelement = doc->NewElement("Node"); newelement->SetAttribute("visible", n.visible_); newelement->SetAttribute("id", n.id()); XMLElement *scale = doc->NewElement("scale"); scale->InsertEndChild( XMLElementFromGLM(doc, n.scale_) ); newelement->InsertEndChild(scale); XMLElement *translation = doc->NewElement("translation"); translation->InsertEndChild( XMLElementFromGLM(doc, n.translation_) ); newelement->InsertEndChild(translation); XMLElement *rotation = doc->NewElement("rotation"); rotation->InsertEndChild( XMLElementFromGLM(doc, n.rotation_) ); newelement->InsertEndChild(rotation); XMLElement *crop = doc->NewElement("crop"); crop->InsertEndChild( XMLElementFromGLM(doc, n.crop_) ); newelement->InsertEndChild(crop); return newelement; } void SessionVisitor::visit(Node &n) { XMLElement *newelement = NodeToXML(n, xmlDoc_); // insert into hierarchy xmlCurrent_->InsertEndChild(newelement); // parent for next visits xmlCurrent_ = newelement; } void SessionVisitor::visit(Group &n) { // Node of a different type xmlCurrent_->SetAttribute("type", "Group"); if (recursive_) { // loop over members of a group XMLElement *group = xmlCurrent_; for (NodeSet::iterator node = n.begin(); node != n.end(); node++) { (*node)->accept(*this); // revert to group as current xmlCurrent_ = group; } } } void SessionVisitor::visit(Switch &n) { // Node of a different type xmlCurrent_->SetAttribute("type", "Switch"); xmlCurrent_->SetAttribute("active", n.active()); if (recursive_) { // loop over members of the group XMLElement *group = xmlCurrent_; for(uint i = 0; i < n.numChildren(); i++) { n.child(i)->accept(*this); // revert to group as current xmlCurrent_ = group; } } } void SessionVisitor::visit(Primitive &n) { // Node of a different type xmlCurrent_->SetAttribute("type", "Primitive"); if (recursive_) { // go over members of a primitive XMLElement *Primitive = xmlCurrent_; xmlCurrent_ = xmlDoc_->NewElement("Shader"); n.shader()->accept(*this); Primitive->InsertEndChild(xmlCurrent_); // revert to primitive as current xmlCurrent_ = Primitive; } } void SessionVisitor::visit(Surface &) { } void SessionVisitor::visit(ImageSurface &n) { // Node of a different type xmlCurrent_->SetAttribute("type", "ImageSurface"); XMLText *filename = xmlDoc_->NewText( n.resource().c_str() ); XMLElement *image = xmlDoc_->NewElement("resource"); image->InsertEndChild(filename); xmlCurrent_->InsertEndChild(image); } void SessionVisitor::visit(FrameBufferSurface &) { // Node of a different type xmlCurrent_->SetAttribute("type", "FrameBufferSurface"); } void SessionVisitor::visit(MediaSurface &n) { // Node of a different type xmlCurrent_->SetAttribute("type", "MediaSurface"); n.mediaPlayer()->accept(*this); } void SessionVisitor::visit(MediaPlayer &n) { XMLElement *newelement = xmlDoc_->NewElement("MediaPlayer"); newelement->SetAttribute("id", n.id()); newelement->SetAttribute("play", n.isPlaying()); newelement->SetAttribute("loop", (int) n.loop()); newelement->SetAttribute("speed", n.playSpeed()); // timeline XMLElement *timelineelement = xmlDoc_->NewElement("Timeline"); // gaps in timeline XMLElement *gapselement = xmlDoc_->NewElement("Gaps"); TimeIntervalSet gaps = n.timeline()->gaps(); for( auto it = gaps.begin(); it!= gaps.end(); it++) { XMLElement *g = xmlDoc_->NewElement("Interval"); g->SetAttribute("begin", (*it).begin); g->SetAttribute("end", (*it).end); gapselement->InsertEndChild(g); } timelineelement->InsertEndChild(gapselement); // fading in timeline XMLElement *fadingelement = xmlDoc_->NewElement("Fading"); XMLElement *array = XMLElementEncodeArray(xmlDoc_, n.timeline()->fadingArray(), MAX_TIMELINE_ARRAY * sizeof(float)); fadingelement->InsertEndChild(array); timelineelement->InsertEndChild(fadingelement); newelement->InsertEndChild(timelineelement); xmlCurrent_->InsertEndChild(newelement); } void SessionVisitor::visit(Shader &n) { // Shader of a simple type xmlCurrent_->SetAttribute("type", "Shader"); xmlCurrent_->SetAttribute("id", n.id()); XMLElement *color = xmlDoc_->NewElement("color"); color->InsertEndChild( XMLElementFromGLM(xmlDoc_, n.color) ); xmlCurrent_->InsertEndChild(color); XMLElement *blend = xmlDoc_->NewElement("blending"); blend->SetAttribute("mode", int(n.blending) ); xmlCurrent_->InsertEndChild(blend); } void SessionVisitor::visit(ImageShader &n) { // Shader of a textured type xmlCurrent_->SetAttribute("type", "ImageShader"); xmlCurrent_->SetAttribute("id", n.id()); XMLElement *uniforms = xmlDoc_->NewElement("uniforms"); uniforms->SetAttribute("stipple", n.stipple); xmlCurrent_->InsertEndChild(uniforms); } void SessionVisitor::visit(MaskShader &n) { // Shader of a mask type xmlCurrent_->SetAttribute("type", "MaskShader"); xmlCurrent_->SetAttribute("id", n.id()); xmlCurrent_->SetAttribute("mode", n.mode); xmlCurrent_->SetAttribute("shape", n.shape); XMLElement *uniforms = xmlDoc_->NewElement("uniforms"); uniforms->SetAttribute("blur", n.blur); uniforms->SetAttribute("option", n.option); XMLElement *size = xmlDoc_->NewElement("size"); size->InsertEndChild( XMLElementFromGLM(xmlDoc_, n.size) ); uniforms->InsertEndChild(size); xmlCurrent_->InsertEndChild(uniforms); } void SessionVisitor::visit(ImageProcessingShader &n) { // Shader of a textured type xmlCurrent_->SetAttribute("type", "ImageProcessingShader"); xmlCurrent_->SetAttribute("id", n.id()); XMLElement *filter = xmlDoc_->NewElement("uniforms"); filter->SetAttribute("brightness", n.brightness); filter->SetAttribute("contrast", n.contrast); filter->SetAttribute("saturation", n.saturation); filter->SetAttribute("hueshift", n.hueshift); filter->SetAttribute("threshold", n.threshold); filter->SetAttribute("lumakey", n.lumakey); filter->SetAttribute("nbColors", n.nbColors); filter->SetAttribute("invert", n.invert); filter->SetAttribute("chromadelta", n.chromadelta); filter->SetAttribute("filter", n.filterid); xmlCurrent_->InsertEndChild(filter); XMLElement *gamma = xmlDoc_->NewElement("gamma"); gamma->InsertEndChild( XMLElementFromGLM(xmlDoc_, n.gamma) ); xmlCurrent_->InsertEndChild(gamma); XMLElement *levels = xmlDoc_->NewElement("levels"); levels->InsertEndChild( XMLElementFromGLM(xmlDoc_, n.levels) ); xmlCurrent_->InsertEndChild(levels); XMLElement *chromakey = xmlDoc_->NewElement("chromakey"); chromakey->InsertEndChild( XMLElementFromGLM(xmlDoc_, n.chromakey) ); xmlCurrent_->InsertEndChild(chromakey); } void SessionVisitor::visit(LineStrip &n) { // Node of a different type xmlCurrent_->SetAttribute("type", "LineStrip"); XMLElement *points_node = xmlDoc_->NewElement("points"); std::vector points = n.getPoints(); for(size_t i = 0; i < points.size(); ++i) { XMLElement *p = XMLElementFromGLM(xmlDoc_, points[i]); p->SetAttribute("index", (int) i); points_node->InsertEndChild(p); } xmlCurrent_->InsertEndChild(points_node); XMLElement *colors_node = xmlDoc_->NewElement("colors"); std::vector colors = n.getColors(); for(size_t i = 0; i < colors.size(); ++i) { XMLElement *p = XMLElementFromGLM(xmlDoc_, colors[i]); p->SetAttribute("index", (int) i); colors_node->InsertEndChild(p); } xmlCurrent_->InsertEndChild(colors_node); } void SessionVisitor::visit(LineSquare &) { // Node of a different type xmlCurrent_->SetAttribute("type", "LineSquare"); } void SessionVisitor::visit(LineCircle &) { // Node of a different type xmlCurrent_->SetAttribute("type", "LineCircle"); // XMLElement *color = xmlDoc_->NewElement("color"); // color->InsertEndChild( XMLElementFromGLM(xmlDoc_, n.getColor()) ); // xmlCurrent_->InsertEndChild(color); } void SessionVisitor::visit(Mesh &n) { // Node of a different type xmlCurrent_->SetAttribute("type", "Mesh"); XMLText *filename = xmlDoc_->NewText( n.meshPath().c_str() ); XMLElement *obj = xmlDoc_->NewElement("resource"); obj->InsertEndChild(filename); xmlCurrent_->InsertEndChild(obj); filename = xmlDoc_->NewText( n.texturePath().c_str() ); XMLElement *tex = xmlDoc_->NewElement("texture"); tex->InsertEndChild(filename); xmlCurrent_->InsertEndChild(tex); } void SessionVisitor::visit(Frame &n) { // Node of a different type xmlCurrent_->SetAttribute("type", "Frame"); XMLElement *color = xmlDoc_->NewElement("color"); color->InsertEndChild( XMLElementFromGLM(xmlDoc_, n.color) ); xmlCurrent_->InsertEndChild(color); } void SessionVisitor::visit(Scene &n) { XMLElement *xmlRoot = xmlDoc_->NewElement("Scene"); xmlDoc_->InsertEndChild(xmlRoot); // start recursive traverse from root node recursive_ = true; xmlCurrent_ = xmlRoot; n.root()->accept(*this); } void SessionVisitor::visit (Source& s) { XMLElement *sourceNode = xmlDoc_->NewElement( "Source" ); sourceNode->SetAttribute("id", s.id()); sourceNode->SetAttribute("name", s.name().c_str() ); sourceNode->SetAttribute("locked", s.locked() ); // insert into hierarchy xmlCurrent_->InsertFirstChild(sourceNode); xmlCurrent_ = xmlDoc_->NewElement( "Mixing" ); sourceNode->InsertEndChild(xmlCurrent_); s.groupNode(View::MIXING)->accept(*this); xmlCurrent_ = xmlDoc_->NewElement( "Geometry" ); sourceNode->InsertEndChild(xmlCurrent_); s.groupNode(View::GEOMETRY)->accept(*this); xmlCurrent_ = xmlDoc_->NewElement( "Layer" ); sourceNode->InsertEndChild(xmlCurrent_); s.groupNode(View::LAYER)->accept(*this); xmlCurrent_ = xmlDoc_->NewElement( "Appearance" ); sourceNode->InsertEndChild(xmlCurrent_); s.groupNode(View::APPEARANCE)->accept(*this); xmlCurrent_ = xmlDoc_->NewElement( "Blending" ); sourceNode->InsertEndChild(xmlCurrent_); s.blendingShader()->accept(*this); xmlCurrent_ = xmlDoc_->NewElement( "Mask" ); sourceNode->InsertEndChild(xmlCurrent_); s.maskShader()->accept(*this); // if we are saving a pain mask if (s.maskShader()->mode == MaskShader::PAINT) { // get the mask previously stored FrameBufferImage *img = s.getMask(); if (img != nullptr) { // get the jpeg encoded buffer FrameBufferImage::jpegBuffer jpgimg = img->getJpeg(); if (jpgimg.buffer != nullptr) { // fill the xml array with jpeg buffer XMLElement *array = XMLElementEncodeArray(xmlDoc_, jpgimg.buffer, jpgimg.len); // free the buffer free(jpgimg.buffer); // if we could create the array if (array) { // create an Image node to store the mask image XMLElement *imageelement = xmlDoc_->NewElement("Image"); imageelement->InsertEndChild(array); xmlCurrent_->InsertEndChild(imageelement); } } } } xmlCurrent_ = xmlDoc_->NewElement( "ImageProcessing" ); xmlCurrent_->SetAttribute("enabled", s.imageProcessingEnabled()); sourceNode->InsertEndChild(xmlCurrent_); s.processingShader()->accept(*this); xmlCurrent_ = sourceNode; // parent for next visits (other subtypes of Source) } void SessionVisitor::visit (MediaSource& s) { xmlCurrent_->SetAttribute("type", "MediaSource"); XMLElement *uri = xmlDoc_->NewElement("uri"); xmlCurrent_->InsertEndChild(uri); XMLText *text = xmlDoc_->NewText( s.path().c_str() ); uri->InsertEndChild( text ); s.mediaplayer()->accept(*this); } void SessionVisitor::visit (SessionFileSource& s) { xmlCurrent_->SetAttribute("type", "SessionSource"); XMLElement *path = xmlDoc_->NewElement("path"); xmlCurrent_->InsertEndChild(path); XMLText *text = xmlDoc_->NewText( s.path().c_str() ); path->InsertEndChild( text ); } void SessionVisitor::visit (SessionGroupSource& s) { xmlCurrent_->SetAttribute("type", "GroupSource"); Session *se = s.session(); XMLElement *rootgroup = xmlDoc_->NewElement("Session"); xmlCurrent_->InsertEndChild(rootgroup); for (auto iter = se->begin(); iter != se->end(); iter++){ setRoot(rootgroup); (*iter)->accept(*this); } } void SessionVisitor::visit (RenderSource&) { xmlCurrent_->SetAttribute("type", "RenderSource"); } void SessionVisitor::visit (CloneSource& s) { xmlCurrent_->SetAttribute("type", "CloneSource"); XMLElement *origin = xmlDoc_->NewElement("origin"); xmlCurrent_->InsertEndChild(origin); XMLText *text = xmlDoc_->NewText( s.origin()->name().c_str() ); origin->InsertEndChild( text ); } void SessionVisitor::visit (PatternSource& s) { xmlCurrent_->SetAttribute("type", "PatternSource"); xmlCurrent_->SetAttribute("pattern", s.pattern()->type() ); XMLElement *resolution = xmlDoc_->NewElement("resolution"); resolution->InsertEndChild( XMLElementFromGLM(xmlDoc_, s.pattern()->resolution() ) ); xmlCurrent_->InsertEndChild(resolution); } void SessionVisitor::visit (DeviceSource& s) { xmlCurrent_->SetAttribute("type", "DeviceSource"); xmlCurrent_->SetAttribute("device", s.device().c_str() ); } void SessionVisitor::visit (NetworkSource& s) { xmlCurrent_->SetAttribute("type", "NetworkSource"); xmlCurrent_->SetAttribute("connection", s.connection().c_str() ); }