You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
486 lines
16 KiB
486 lines
16 KiB
#include "ofxSurfaceManager.h"
|
|
|
|
ofxSurfaceManager::ofxSurfaceManager()
|
|
{
|
|
|
|
}
|
|
|
|
ofxSurfaceManager::~ofxSurfaceManager()
|
|
{
|
|
clear();
|
|
}
|
|
|
|
void ofxSurfaceManager::draw()
|
|
{
|
|
for ( int i=0; i<surfaces.size(); i++ ) {
|
|
surfaces[i]->draw();
|
|
}
|
|
}
|
|
|
|
void ofxSurfaceManager::addSurface(int surfaceType)
|
|
{
|
|
if ( surfaceType == ofxSurfaceType::TRIANGLE_SURFACE ) {
|
|
surfaces.push_back( new ofxTriangleSurface() );
|
|
}
|
|
else if (surfaceType == ofxSurfaceType::QUAD_SURFACE ) {
|
|
surfaces.push_back( new ofxQuadSurface() );
|
|
}
|
|
else {
|
|
throw std::runtime_error("Attempt to add non-existing surface type.");
|
|
}
|
|
}
|
|
|
|
void ofxSurfaceManager::addSurface(int surfaceType, ofTexture* texturePtr)
|
|
{
|
|
if ( surfaceType == ofxSurfaceType::TRIANGLE_SURFACE ) {
|
|
surfaces.push_back( new ofxTriangleSurface() );
|
|
surfaces.back()->setTexture(texturePtr);
|
|
}
|
|
else if (surfaceType == ofxSurfaceType::QUAD_SURFACE ) {
|
|
surfaces.push_back( new ofxQuadSurface() );
|
|
surfaces.back()->setTexture(texturePtr);
|
|
}
|
|
else {
|
|
throw std::runtime_error("Attempt to add non-existing surface type.");
|
|
}
|
|
}
|
|
|
|
void ofxSurfaceManager::addSurface(int surfaceType, vector<ofVec2f> vertices, vector<ofVec2f> texCoords)
|
|
{
|
|
if ( surfaceType == ofxSurfaceType::TRIANGLE_SURFACE ) {
|
|
|
|
if ( vertices.size() < 3 ) {
|
|
throw std::runtime_error("There must be 3 vertices for a triangle surface.");
|
|
} else if (texCoords.size() < 3) {
|
|
throw std::runtime_error("There must be 3 texture coordinates for a triangle surface.");
|
|
}
|
|
|
|
surfaces.push_back( new ofxTriangleSurface() );
|
|
|
|
for ( int i=0; i<3; i++ ) {
|
|
surfaces.back()->setVertex(i, vertices[i]);
|
|
surfaces.back()->setTexCoord(i, texCoords[i]);
|
|
}
|
|
|
|
}
|
|
else if (surfaceType == ofxSurfaceType::QUAD_SURFACE ) {
|
|
if ( vertices.size() < 4 ) {
|
|
throw std::runtime_error("There must be 4 vertices for a quad surface.");
|
|
} else if (texCoords.size() < 4) {
|
|
throw std::runtime_error("There must be 4 texture coordinates for a quad surface.");
|
|
}
|
|
|
|
surfaces.push_back( new ofxQuadSurface() );
|
|
|
|
for ( int i=0; i<4; i++ ) {
|
|
surfaces.back()->setVertex(i, vertices[i]);
|
|
surfaces.back()->setTexCoord(i, texCoords[i]);
|
|
}
|
|
}
|
|
else {
|
|
throw std::runtime_error("Attempt to add non-existing surface type.");
|
|
}
|
|
|
|
}
|
|
|
|
void ofxSurfaceManager::addSurface(int surfaceType, ofTexture* texturePtr, vector<ofVec2f> vertices, vector<ofVec2f> texCoords)
|
|
{
|
|
if ( surfaceType == ofxSurfaceType::TRIANGLE_SURFACE ) {
|
|
|
|
if ( vertices.size() < 3 ) {
|
|
throw std::runtime_error("There must be 3 vertices for a triangle surface.");
|
|
} else if (texCoords.size() < 3) {
|
|
throw std::runtime_error("Thre must be 3 texture coordinates for a triangle surface.");
|
|
}
|
|
|
|
surfaces.push_back( new ofxTriangleSurface() );
|
|
surfaces.back()->setTexture(texturePtr);
|
|
|
|
for ( int i=0; i<3; i++ ) {
|
|
surfaces.back()->setVertex(i, vertices[i]);
|
|
surfaces.back()->setTexCoord(i, texCoords[i]);
|
|
}
|
|
|
|
}
|
|
else if (surfaceType == ofxSurfaceType::QUAD_SURFACE ) {
|
|
if ( vertices.size() < 4 ) {
|
|
throw std::runtime_error("There must be 4 vertices for a quad surface.");
|
|
} else if (texCoords.size() < 4) {
|
|
throw std::runtime_error("Thre must be 4 texture coordinates for a quad surface.");
|
|
}
|
|
|
|
surfaces.push_back( new ofxQuadSurface() );
|
|
surfaces.back()->setTexture(texturePtr);
|
|
|
|
for ( int i=0; i<4; i++ ) {
|
|
surfaces.back()->setVertex(i, vertices[i]);
|
|
surfaces.back()->setTexCoord(i, texCoords[i]);
|
|
}
|
|
}
|
|
else {
|
|
throw std::runtime_error("Attempt to add non-existing surface type.");
|
|
}
|
|
}
|
|
|
|
void ofxSurfaceManager::removeSelectedSurface()
|
|
{
|
|
if ( selectedSurface == NULL ) return;
|
|
|
|
for ( int i=0; i<surfaces.size(); i++ ) {
|
|
if ( surfaces[i] == selectedSurface ) {
|
|
delete surfaces[i];
|
|
surfaces.erase(surfaces.begin()+i);
|
|
selectedSurface = NULL;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
void ofxSurfaceManager::manageMemory()
|
|
{
|
|
// check if each of the sources is assigned to a surface or not
|
|
for ( int i=0; i<loadedImageSources.size(); i++ ) {
|
|
bool bAssigned = false;
|
|
|
|
for ( int j=0; j<surfaces.size(); j++ ) {
|
|
if ( surfaces[j]->getTexture() == &loadedImageSources[i]->getTextureReference() ) {
|
|
bAssigned = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if ( !bAssigned ) {
|
|
// purge the image source from memory
|
|
delete loadedImageSources[i];
|
|
loadedImageSources.erase(loadedImageSources.begin()+i);
|
|
cout << "Deleting image source: " << loadedImageSourceNames[i] << endl;
|
|
loadedImageSourceNames.erase(loadedImageSourceNames.begin()+i);
|
|
i--;
|
|
}
|
|
}
|
|
}
|
|
|
|
void ofxSurfaceManager::clear()
|
|
{
|
|
// delete all extra allocations from the heap
|
|
while ( surfaces.size() ) {
|
|
delete surfaces.back();
|
|
surfaces.pop_back();
|
|
}
|
|
|
|
while ( loadedImageSources.size() ) {
|
|
delete loadedImageSources.back();
|
|
loadedImageSources.pop_back();
|
|
}
|
|
|
|
while ( loadedImageSourceNames.size() ) {
|
|
loadedImageSourceNames.pop_back();
|
|
}
|
|
}
|
|
|
|
// String getTypeString(ofxSurfaceType e)
|
|
// {
|
|
// switch e
|
|
// {
|
|
// case TRINAGLE_SURFACE: return "TRINAGLE_SURFACE";
|
|
// case QUAD_SURFACE: return "QUAD_SURFACE";
|
|
// default: throw Exception("Bad MyEnum");
|
|
// }
|
|
// }
|
|
|
|
void ofxSurfaceManager::saveXmlSettings(string fileName)
|
|
{
|
|
xmlSettings.clear();
|
|
|
|
// save surfaces
|
|
xmlSettings.addTag("surfaces");
|
|
xmlSettings.pushTag("surfaces");
|
|
for ( int i=0; i<surfaces.size(); i++ ) {
|
|
|
|
xmlSettings.addTag("surface");
|
|
xmlSettings.pushTag("surface", i);
|
|
ofxBaseSurface* surface = surfaces[i];
|
|
|
|
xmlSettings.addTag("vertices");
|
|
xmlSettings.pushTag("vertices");
|
|
vector<ofVec3f>* 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<ofVec2f>* texCoords = &surface->getTexCoords();
|
|
for ( int j=0; j<texCoords->size(); j++ ) {
|
|
xmlSettings.addTag("texCoord");
|
|
xmlSettings.pushTag("texCoord", j);
|
|
ofVec2f* 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");
|
|
|
|
xmlSettings.addValue("source-type", "image");
|
|
xmlSettings.addValue("source-name", getSurfaceSourceName(surface));
|
|
//xmlSettings.addValue("source-path", "/root/etc/image.jpg");
|
|
xmlSettings.popTag(); // source
|
|
|
|
|
|
// xmlSettings.addTag("type");
|
|
// xmlSettings.pushTag("type");
|
|
// // surfaceType == ofxSurfaceType::TRIANGLE_SURFACE
|
|
// ofxSurfaceType surfaceType = &surface->getType();
|
|
// xmlSettings.addValue("surface-type", surfaceType);
|
|
// xmlSettings.popTag(); // type
|
|
|
|
xmlSettings.popTag(); // surface
|
|
}
|
|
xmlSettings.popTag(); // surfaces
|
|
|
|
xmlSettings.save(fileName);
|
|
}
|
|
|
|
void ofxSurfaceManager::loadXmlSettings(string fileName)
|
|
{
|
|
|
|
|
|
if (!xmlSettings.loadFile(fileName)){
|
|
ofLog(OF_LOG_WARNING, "Could not load XML settings.");
|
|
return;
|
|
}
|
|
|
|
if (!xmlSettings.tagExists("surfaces")){
|
|
ofLog(OF_LOG_WARNING, "XML settings is empty or has wrong markup.");
|
|
return;
|
|
}
|
|
|
|
xmlSettings.pushTag("surfaces");
|
|
|
|
int numSurfaces = xmlSettings.getNumTags("surface");
|
|
for ( int i=0; i<numSurfaces; i++ ) {
|
|
xmlSettings.pushTag("surface", i);
|
|
// attempt to load surface source
|
|
xmlSettings.pushTag("source");
|
|
string sourceType = xmlSettings.getValue("source-type", "image");
|
|
string sourceName = xmlSettings.getValue("source-name", "none");
|
|
ofTexture* sourceTexture = NULL;
|
|
if ( sourceName != "none" ) {
|
|
stringstream ss;
|
|
ss << "sources/images/" << sourceName; // TODO: reuse constants here
|
|
sourceTexture = loadImageSource(sourceName, ss.str());
|
|
}
|
|
xmlSettings.popTag(); // source
|
|
|
|
// // attempt to load surface type
|
|
// ofLog(OF_LOG_WARNING, "Attempt to load surface type.");
|
|
// xmlSettings.pushTag("type");
|
|
// string surfaceType = xmlSettings.getValue("surface-type", "TRIANGLE_SURFACE");
|
|
// xmlSettings.popTag(); // type
|
|
|
|
|
|
xmlSettings.pushTag("vertices");
|
|
vector<ofVec2f> vertices;
|
|
|
|
int vertexCount = xmlSettings.getNumTags("vertex");
|
|
|
|
|
|
//it's a triangle ?
|
|
if (vertexCount == 3)
|
|
{
|
|
ofLog(OF_LOG_NOTICE, "create Triangle");
|
|
xmlSettings.pushTag("vertex", 0);
|
|
vertices.push_back( ofVec2f( xmlSettings.getValue("x", 0.0f), xmlSettings.getValue("y", 0.0f) ) );
|
|
xmlSettings.popTag();
|
|
|
|
xmlSettings.pushTag("vertex", 1);
|
|
vertices.push_back( ofVec2f( xmlSettings.getValue("x", 100.0f), xmlSettings.getValue("y", 0.0f) ) );
|
|
xmlSettings.popTag();
|
|
|
|
xmlSettings.pushTag("vertex", 2);
|
|
vertices.push_back( ofVec2f( xmlSettings.getValue("x", 0.0f), xmlSettings.getValue("y", 100.0f) ) );
|
|
xmlSettings.popTag();
|
|
|
|
xmlSettings.popTag(); // vertices
|
|
|
|
xmlSettings.pushTag("texCoords");
|
|
|
|
vector<ofVec2f> texCoords;
|
|
|
|
xmlSettings.pushTag("texCoord", 0);
|
|
texCoords.push_back( ofVec2f( xmlSettings.getValue("x", 0.0f), xmlSettings.getValue("y", 0.0f) ) );
|
|
xmlSettings.popTag();
|
|
|
|
xmlSettings.pushTag("texCoord", 1);
|
|
texCoords.push_back( ofVec2f( xmlSettings.getValue("x", 1.0f), xmlSettings.getValue("y", 0.0f) ) );
|
|
xmlSettings.popTag();
|
|
|
|
xmlSettings.pushTag("texCoord", 2);
|
|
texCoords.push_back( ofVec2f( xmlSettings.getValue("x", 0.0f), xmlSettings.getValue("y", 1.0f) ) );
|
|
xmlSettings.popTag();
|
|
|
|
xmlSettings.popTag(); // texCoords
|
|
|
|
|
|
// now we have variables sourceName and sourceTexture
|
|
// by checking those we can use one or another addSurface method
|
|
if ( sourceName != "none" && sourceTexture != NULL ) {
|
|
addSurface(ofxSurfaceType::TRIANGLE_SURFACE, sourceTexture, vertices, texCoords);
|
|
} else {
|
|
addSurface(ofxSurfaceType::TRIANGLE_SURFACE, vertices, texCoords);
|
|
}
|
|
}
|
|
// it's a quad ?
|
|
else if (vertexCount == 4)
|
|
// if (surface-type == QUAD_SURFACE)
|
|
{
|
|
xmlSettings.pushTag("vertex", 0);
|
|
vertices.push_back( ofVec2f( xmlSettings.getValue("x", 0.0f), xmlSettings.getValue("y", 0.0f) ) );
|
|
xmlSettings.popTag();
|
|
|
|
xmlSettings.pushTag("vertex", 1);
|
|
vertices.push_back( ofVec2f( xmlSettings.getValue("x", 100.0f), xmlSettings.getValue("y", 0.0f) ) );
|
|
xmlSettings.popTag();
|
|
|
|
xmlSettings.pushTag("vertex", 2);
|
|
vertices.push_back( ofVec2f( xmlSettings.getValue("x", 100.0f), xmlSettings.getValue("y", 100.0f) ) );
|
|
xmlSettings.popTag();
|
|
|
|
xmlSettings.pushTag("vertex", 3);
|
|
vertices.push_back( ofVec2f( xmlSettings.getValue("x", 0.0f), xmlSettings.getValue("y", 100.0f) ) );
|
|
xmlSettings.popTag();
|
|
|
|
xmlSettings.popTag(); // vertices
|
|
|
|
xmlSettings.pushTag("texCoords");
|
|
|
|
vector<ofVec2f> texCoords;
|
|
|
|
xmlSettings.pushTag("texCoord", 0);
|
|
texCoords.push_back( ofVec2f( xmlSettings.getValue("x", 0.0f), xmlSettings.getValue("y", 0.0f) ) );
|
|
xmlSettings.popTag();
|
|
|
|
xmlSettings.pushTag("texCoord", 1);
|
|
texCoords.push_back( ofVec2f( xmlSettings.getValue("x", 1.0f), xmlSettings.getValue("y", 0.0f) ) );
|
|
xmlSettings.popTag();
|
|
|
|
xmlSettings.pushTag("texCoord", 2);
|
|
texCoords.push_back( ofVec2f( xmlSettings.getValue("x", 1.0f), xmlSettings.getValue("y", 1.0f) ) );
|
|
xmlSettings.popTag();
|
|
|
|
xmlSettings.pushTag("texCoord", 3);
|
|
texCoords.push_back( ofVec2f( xmlSettings.getValue("x", 0.0f), xmlSettings.getValue("y", 1.0f) ) );
|
|
xmlSettings.popTag();
|
|
|
|
xmlSettings.popTag(); // texCoords
|
|
|
|
|
|
// now we have variables sourceName and sourceTexture
|
|
// by checking those we can use one or another addSurface method
|
|
if ( sourceName != "none" && sourceTexture != NULL ) {
|
|
addSurface(ofxSurfaceType::QUAD_SURFACE, sourceTexture, vertices, texCoords);
|
|
} else {
|
|
addSurface(ofxSurfaceType::QUAD_SURFACE, vertices, texCoords);
|
|
}
|
|
|
|
|
|
}
|
|
|
|
xmlSettings.popTag(); // surface
|
|
}
|
|
|
|
xmlSettings.popTag(); // surfaces
|
|
}
|
|
|
|
ofxBaseSurface* ofxSurfaceManager::selectSurface(int index)
|
|
{
|
|
if ( index >= surfaces.size() ) {
|
|
throw std::runtime_error("Surface index out of bounds.");
|
|
}
|
|
|
|
selectedSurface = surfaces[index];
|
|
|
|
// notify that a new surface has been selected
|
|
ofSendMessage("surfaceSelected");
|
|
}
|
|
|
|
ofxBaseSurface* ofxSurfaceManager::getSelectedSurface()
|
|
{
|
|
return selectedSurface;
|
|
}
|
|
|
|
void ofxSurfaceManager::deselectSurface()
|
|
{
|
|
selectedSurface = NULL;
|
|
}
|
|
|
|
ofTexture* ofxSurfaceManager::loadImageSource(string name, string path)
|
|
{
|
|
// check if it is loaded
|
|
for ( int i=0; i<loadedImageSourceNames.size(); i++ ) {
|
|
if ( loadedImageSourceNames[i] == name ) {
|
|
// this image is already loaded
|
|
return &loadedImageSources[i]->getTextureReference();
|
|
}
|
|
}
|
|
|
|
// not loaded - load
|
|
ofImage* image = new ofImage();
|
|
if ( !image->loadImage(path) ){
|
|
return NULL;
|
|
}
|
|
loadedImageSources.push_back(image);
|
|
loadedImageSourceNames.push_back(name);
|
|
return &image->getTextureReference();
|
|
}
|
|
|
|
string ofxSurfaceManager::getSelectedSurfaceSourceName()
|
|
{
|
|
if ( selectedSurface == NULL ) {
|
|
return "none";
|
|
}
|
|
|
|
return getSurfaceSourceName( selectedSurface );
|
|
}
|
|
|
|
string ofxSurfaceManager::getSurfaceSourceName(ofxBaseSurface *surface)
|
|
{
|
|
ofTexture* tex = surface->getTexture();
|
|
for ( int i=0; i<loadedImageSources.size(); i++ ) {
|
|
if (tex == &loadedImageSources[i]->getTextureReference()) {
|
|
return loadedImageSourceNames[i];
|
|
}
|
|
}
|
|
|
|
return "none";
|
|
}
|
|
|
|
ofxBaseSurface* ofxSurfaceManager::getSurface(int index)
|
|
{
|
|
if ( index >= surfaces.size() ) {
|
|
throw std::runtime_error("Surface index out of bounds.");
|
|
return NULL;
|
|
}
|
|
|
|
return surfaces[index];
|
|
}
|
|
|
|
int ofxSurfaceManager::size()
|
|
{
|
|
return surfaces.size();
|
|
}
|
|
|
|
|
|
|
|
|