#include "SettingsLoader.h" namespace ofx { namespace piMapper { SettingsLoader * SettingsLoader::_instance = 0; SettingsLoader * SettingsLoader::instance(){ if(_instance == 0){ _instance = new ofx::piMapper::SettingsLoader(); } return _instance; } SettingsLoader::SettingsLoader(){ _lastLoadedFilename = "surfaces.xml"; } bool SettingsLoader::load( SurfaceManager & surfaceManager, MediaServer & mediaServer, string fileName){ ofxXmlSettings * xmlSettings = new ofxXmlSettings(); string sourceType = ""; string sourceName = ""; BaseSource * source = 0; if(!xmlSettings->loadFile(fileName)){ ofLogWarning("SettingsLoader::load()") << "Could not load XML settings"; return false; } if(!xmlSettings->tagExists("surfaces")){ xmlSettings->addTag("surfaces"); } // Count tags. unsigned int numPresets = xmlSettings->getNumTags("surfaces"); cout << "numPresets: " << numPresets << endl; // Clear previous presets and surfaces first. surfaceManager.clearPresets(); // Loop through tags in the XML. for(unsigned int i = 0; i < numPresets; ++i){ xmlSettings->pushTag("surfaces", i); SurfaceStack * surfaces = surfaceManager.createPreset(); int numSurfaces = xmlSettings->getNumTags("surface"); for(int i = 0; i < numSurfaces; i++){ if(xmlSettings->tagExists("surface", i)){ SurfaceType type = SurfaceType::NONE; if(xmlSettings->attributeExists("surface", "type")){ type = static_cast( xmlSettings->getAttribute("surface", "type", 0, i)); } xmlSettings->pushTag("surface", i); // attempt to load surface source if(xmlSettings->tagExists("source", 0)){ xmlSettings->pushTag("source"); sourceType = xmlSettings->getValue("source-type", ""); sourceName = xmlSettings->getValue("source-name", ""); if(sourceName != "" && sourceName != "none" && sourceType != ""){ // Load source depending on type SourceType typeEnum = SourceTypeHelper::GetSourceTypeHelperEnum(sourceType); if(typeEnum == SourceType::SOURCE_TYPE_FBO){ // Load FBO source using sourceName source = mediaServer.loadMedia(sourceName, typeEnum); }else{ // Construct full path string dir = mediaServer.getDefaultMediaDir(typeEnum); stringstream pathss; pathss << ofToDataPath(dir, true) << sourceName; string sourcePath = pathss.str(); // Load media by using full path source = mediaServer.loadMedia(sourcePath, typeEnum); } } xmlSettings->popTag(); // source } int vertexCount = 0; if(xmlSettings->tagExists("vertices", 0)){ xmlSettings->pushTag("vertices"); vertexCount = xmlSettings->getNumTags("vertex"); xmlSettings->popTag(); // vertices } if(type == SurfaceType::NONE){ if(vertexCount == 3){ type = SurfaceType::TRIANGLE_SURFACE; }else if(vertexCount == 4){ type = SurfaceType::QUAD_SURFACE; }else if(vertexCount > 4){ type = SurfaceType::GRID_WARP_SURFACE; } } if(type == SurfaceType::TRIANGLE_SURFACE){ BaseSurface * triangleSurface = getTriangleSurface(xmlSettings); if(sourceName != "none" && source != 0){ triangleSurface->setSource(source); } surfaces->push_back(triangleSurface); }else if(type == SurfaceType::QUAD_SURFACE){ BaseSurface * quadSurface = getQuadSurface(xmlSettings); if(sourceName != "none" && source != 0){ quadSurface->setSource(source); } surfaces->push_back(quadSurface); }else if(type == SurfaceType::CIRCLE_SURFACE){ QuadSurface * base = (QuadSurface*)getQuadSurface(xmlSettings); CircleSurface * circleSurface = new CircleSurface(*base); if(sourceName != "none" && source != 0){ circleSurface->setSource(source); } surfaces->push_back(circleSurface); }else if(type == SurfaceType::GRID_WARP_SURFACE){ BaseSurface * gridWarpSurface = getGridWarpSurface(xmlSettings); if(sourceName != "none" && source != 0){ gridWarpSurface->setSource(source); } surfaces->push_back(gridWarpSurface); }else if(type == SurfaceType::HEXAGON_SURFACE){ BaseSurface * hexagonSurface = getHexagonSurface(xmlSettings); if(sourceName != "none" && source != 0){ hexagonSurface->setSource(source); } surfaces->push_back(hexagonSurface); } xmlSettings->popTag(); // surface } } xmlSettings->popTag(); // surfaces } // for _lastLoadedFilename = fileName; return true; } // TODO: Save all presets, not just the active one. bool SettingsLoader::save(SurfaceManager & surfaceManager, string fileName){ ofxXmlSettings * xmlSettings = new ofxXmlSettings(); unsigned int numPresets = surfaceManager.getNumPresets(); for(unsigned int i = 0; i < numPresets; ++i){ SurfaceStack * surfaces = surfaceManager.getPresetAt(i); // Save surfaces xmlSettings->addTag("surfaces"); xmlSettings->pushTag("surfaces", i); for(int i = 0; i < surfaces->size(); i++){ BaseSurface * surface = surfaces->at(i); xmlSettings->addTag("surface"); xmlSettings->addAttribute("surface", "type", surface->getType(), i); xmlSettings->pushTag("surface", i); xmlSettings->addTag("vertices"); xmlSettings->pushTag("vertices"); vector * vertices = &surface->getVertices(); for(int j = 0; j < vertices->size(); j++){ xmlSettings->addTag("vertex"); xmlSettings->pushTag("vertex", j); ofVec3f * vertex = &(*vertices)[j]; xmlSettings->addValue("x", vertex->x); xmlSettings->addValue("y", vertex->y); // we don't need z as it will be 0 anyways xmlSettings->popTag(); // vertex } xmlSettings->popTag(); // vertices xmlSettings->addTag("texCoords"); xmlSettings->pushTag("texCoords"); vector * texCoords = &surface->getTexCoords(); for(int j = 0; j < texCoords->size(); j++){ xmlSettings->addTag("texCoord"); xmlSettings->pushTag("texCoord", j); Vec2 * texCoord = &(*texCoords)[j]; xmlSettings->addValue("x", texCoord->x); xmlSettings->addValue("y", texCoord->y); xmlSettings->popTag(); // texCoord } xmlSettings->popTag(); // texCoords xmlSettings->addTag("source"); xmlSettings->pushTag("source"); string sourceTypeName = SourceTypeHelper::GetSourceTypeHelperName(surface->getSource()->getType()); xmlSettings->addValue("source-type", sourceTypeName); string sourceName = surface->getSource()->getName(); xmlSettings->addValue("source-name", (sourceName == "") ? "none" : sourceName); xmlSettings->popTag(); // source // Save surface options // For now only if quad surface if (surface->getType() == SurfaceType::QUAD_SURFACE || surface->getType() == SurfaceType::CIRCLE_SURFACE) { QuadSurface * qs = (QuadSurface *)surface; if(!xmlSettings->tagExists("properties")){ xmlSettings->addTag("properties"); } xmlSettings->pushTag("properties"); xmlSettings->addValue("perspectiveWarping", qs->getPerspectiveWarping()); xmlSettings->popTag(); // properties }else if(surface->getType() == SurfaceType::GRID_WARP_SURFACE){ GridWarpSurface * gws = (GridWarpSurface *)surface; if(!xmlSettings->tagExists("properties")){ xmlSettings->addTag("properties"); } xmlSettings->pushTag("properties"); xmlSettings->addValue("gridCols", gws->getGridCols()); xmlSettings->addValue("gridRows", gws->getGridRows()); xmlSettings->popTag(); } xmlSettings->popTag(); // surface } xmlSettings->popTag(); // surfaces } // for xmlSettings->save(fileName); } bool SettingsLoader::create(string fileName){ ofxXmlSettings xml; xml.addTag("surfaces"); return xml.save(fileName); } BaseSurface * SettingsLoader::getTriangleSurface(ofxXmlSettings * xmlSettings){ vector vertices; if(xmlSettings->tagExists("vertices")){ xmlSettings->pushTag("vertices"); if(xmlSettings->tagExists("vertex", 0)){ xmlSettings->pushTag("vertex", 0); vertices.push_back(Vec2(xmlSettings->getValue("x", 0.0f), xmlSettings->getValue("y", 0.0f))); xmlSettings->popTag(); } if(xmlSettings->tagExists("vertex", 1)){ xmlSettings->pushTag("vertex", 1); vertices.push_back(Vec2(xmlSettings->getValue("x", 100.0f), xmlSettings->getValue("y", 0.0f))); xmlSettings->popTag(); } if(xmlSettings->tagExists("vertex", 2)){ xmlSettings->pushTag("vertex", 2); vertices.push_back(Vec2(xmlSettings->getValue("x", 0.0f), xmlSettings->getValue("y", 100.0f))); xmlSettings->popTag(); } xmlSettings->popTag(); // vertices } vector texCoords; if(xmlSettings->tagExists("texCoords")){ xmlSettings->pushTag("texCoords"); if(xmlSettings->tagExists("texCoord", 0)){ xmlSettings->pushTag("texCoord", 0); texCoords.push_back(Vec2(xmlSettings->getValue("x", 0.0f), xmlSettings->getValue("y", 0.0f))); xmlSettings->popTag(); } if(xmlSettings->tagExists("texCoord", 1)){ xmlSettings->pushTag("texCoord", 1); texCoords.push_back(Vec2(xmlSettings->getValue("x", 1.0f), xmlSettings->getValue("y", 0.0f))); xmlSettings->popTag(); } if(xmlSettings->tagExists("texCoord", 2)){ xmlSettings->pushTag("texCoord", 2); texCoords.push_back(Vec2(xmlSettings->getValue("x", 0.0f), xmlSettings->getValue("y", 1.0f))); xmlSettings->popTag(); } xmlSettings->popTag(); // texCoords } // Create and add a triangle surface BaseSurface * triangleSurface = SurfaceFactory::instance()->createSurface( SurfaceType::TRIANGLE_SURFACE); triangleSurface->setVertices(vertices); triangleSurface->setTexCoords(texCoords); return triangleSurface; } BaseSurface * SettingsLoader::getQuadSurface(ofxXmlSettings * xmlSettings){ vector vertices; if(xmlSettings->tagExists("vertices")){ xmlSettings->pushTag("vertices"); if(xmlSettings->tagExists("vertex", 0)){ xmlSettings->pushTag("vertex", 0); vertices.push_back(Vec2(xmlSettings->getValue("x", 0.0f), xmlSettings->getValue("y", 0.0f))); xmlSettings->popTag(); } if(xmlSettings->tagExists("vertex", 1)){ xmlSettings->pushTag("vertex", 1); vertices.push_back(Vec2(xmlSettings->getValue("x", 100.0f), xmlSettings->getValue("y", 0.0f))); xmlSettings->popTag(); } if(xmlSettings->tagExists("vertex", 2)){ xmlSettings->pushTag("vertex", 2); vertices.push_back(Vec2(xmlSettings->getValue("x", 100.0f), xmlSettings->getValue("y", 100.0f))); xmlSettings->popTag(); } if(xmlSettings->tagExists("vertex", 3)){ xmlSettings->pushTag("vertex", 3); vertices.push_back(Vec2(xmlSettings->getValue("x", 0.0f), xmlSettings->getValue("y", 100.0f))); xmlSettings->popTag(); } xmlSettings->popTag(); // vertices } vector texCoords; if(xmlSettings->tagExists("texCoords")){ xmlSettings->pushTag("texCoords"); if(xmlSettings->tagExists("texCoord", 0)){ xmlSettings->pushTag("texCoord", 0); texCoords.push_back(Vec2(xmlSettings->getValue("x", 0.0f), xmlSettings->getValue("y", 0.0f))); xmlSettings->popTag(); } if(xmlSettings->tagExists("texCoord", 1)){ xmlSettings->pushTag("texCoord", 1); texCoords.push_back(Vec2(xmlSettings->getValue("x", 1.0f), xmlSettings->getValue("y", 0.0f))); xmlSettings->popTag(); } if(xmlSettings->tagExists("texCoord", 2)){ xmlSettings->pushTag("texCoord", 2); texCoords.push_back(Vec2(xmlSettings->getValue("x", 1.0f), xmlSettings->getValue("y", 1.0f))); xmlSettings->popTag(); } if(xmlSettings->tagExists("texCoord", 3)){ xmlSettings->pushTag("texCoord", 3); texCoords.push_back(Vec2(xmlSettings->getValue("x", 0.0f), xmlSettings->getValue("y", 1.0f))); xmlSettings->popTag(); } xmlSettings->popTag(); // texCoords } // Create and add quad surface BaseSurface * quadSurface = SurfaceFactory::instance()->createSurface( SurfaceType::QUAD_SURFACE); quadSurface->setVertices(vertices); quadSurface->setTexCoords(texCoords); // Read properties // Only perspective warping for now bool perspectiveWarping = false; if(xmlSettings->tagExists("properties")){ xmlSettings->pushTag("properties"); perspectiveWarping = xmlSettings->getValue("perspectiveWarping", false); xmlSettings->popTag(); // properties } QuadSurface * qs = (QuadSurface *)quadSurface; qs->setPerspectiveWarping(perspectiveWarping); return quadSurface; } BaseSurface * SettingsLoader::getGridWarpSurface(ofxXmlSettings * xmlSettings){ vector vertices; if(xmlSettings->tagExists("vertices")){ xmlSettings->pushTag("vertices"); int iv = 0; while(xmlSettings->tagExists("vertex", iv)){ xmlSettings->pushTag("vertex", iv); vertices.push_back(Vec2(xmlSettings->getValue("x", 0.0f), xmlSettings->getValue("y", 0.0f))); xmlSettings->popTag(); ++iv; } xmlSettings->popTag(); // vertices } vector texCoords; if(xmlSettings->tagExists("texCoords")){ xmlSettings->pushTag("texCoords"); int it = 0; while(xmlSettings->tagExists("texCoord", it)){ xmlSettings->pushTag("texCoord", it); texCoords.push_back(Vec2(xmlSettings->getValue("x", 0.0f), xmlSettings->getValue("y", 0.0f))); xmlSettings->popTag(); ++it; } xmlSettings->popTag(); // texCoords } // Read properties // Only perspective warping for now int gridCols = 0; int gridRows = 0; if(xmlSettings->tagExists("properties")){ xmlSettings->pushTag("properties"); gridCols = xmlSettings->getValue("gridCols", 0); gridRows = xmlSettings->getValue("gridRows", 0); xmlSettings->popTag(); // properties } // Create and add quad surface BaseSurface * gridWarpSurface = SurfaceFactory::instance()->createSurface( SurfaceType::GRID_WARP_SURFACE); ((GridWarpSurface *)gridWarpSurface)->setGridCols(gridCols); ((GridWarpSurface *)gridWarpSurface)->setGridRows(gridRows); ((GridWarpSurface *)gridWarpSurface)->createGridMesh(); gridWarpSurface->setVertices(vertices); gridWarpSurface->setTexCoords(texCoords); return gridWarpSurface; } BaseSurface * SettingsLoader::getHexagonSurface(ofxXmlSettings * xmlSettings){ vector vertices; if(xmlSettings->tagExists("vertices")){ xmlSettings->pushTag("vertices"); unsigned int v = 0; while(xmlSettings->tagExists("vertex", v)){ xmlSettings->pushTag("vertex", v); vertices.push_back(Vec2(xmlSettings->getValue("x", 0.0f), xmlSettings->getValue("y", 0.0f))); xmlSettings->popTag(); // vertex v += 1; } xmlSettings->popTag(); // vertices } vector texCoords; if(xmlSettings->tagExists("texCoords")){ xmlSettings->pushTag("texCoords"); unsigned int t = 0; while(xmlSettings->tagExists("texCoord", t)){ xmlSettings->pushTag("texCoord", t); texCoords.push_back(Vec2(xmlSettings->getValue("x", 0.0f), xmlSettings->getValue("y", 0.0f))); xmlSettings->popTag(); // texCoord t += 1; } xmlSettings->popTag(); // texCoords } // Create and add a triangle surface BaseSurface * hexagonSurface = SurfaceFactory::instance()->createSurface( SurfaceType::HEXAGON_SURFACE); hexagonSurface->setVertices(vertices); hexagonSurface->setTexCoords(texCoords); return hexagonSurface; } } // namespace piMapper } // namespace ofx