diff --git a/example/bin/data/sources/videos/test.mov b/example/bin/data/sources/videos/test.mov new file mode 100644 index 0000000..48a307b Binary files /dev/null and b/example/bin/data/sources/videos/test.mov differ diff --git a/example/bin/data/sources/videos/test.mp4 b/example/bin/data/sources/videos/test.mp4 deleted file mode 100644 index e69de29..0000000 diff --git a/example/src/ofApp.cpp b/example/src/ofApp.cpp index 260ebfe..101e14e 100755 --- a/example/src/ofApp.cpp +++ b/example/src/ofApp.cpp @@ -2,6 +2,12 @@ void ofApp::setup() { bShowInfo = false; + + // Pass pointers to our media server instance to both: + // surface manager and it's gui, only then we will be able to + // load surface data from xml settings files + surfaceManager.setMediaServer(&mediaServer); + gui.setMediaServer(&mediaServer); // check if the surfaces.xml file is there // if not - load defaultSurfaces.xml @@ -17,7 +23,8 @@ void ofApp::setup() { // Create FBO fbo = new ofFbo(); fbo->allocate(500, 500); - setFboAsTexture(); + fboSource = new ofx::piMapper::BaseSource(&fbo->getTextureReference()); + setFboAsSource(); // Genereate rects int numRects = 20; // change this to add more or less rects @@ -114,7 +121,7 @@ void ofApp::keyPressed(int key) { surfaceManager.saveXmlSettings("surfaces.xml"); break; case 'a': - setFboAsTexture(); + setFboAsSource(); break; case OF_KEY_BACKSPACE: surfaceManager.removeSelectedSurface(); @@ -178,6 +185,6 @@ void ofApp::addSurface() { surfaceManager.selectSurface(surfaceManager.size() - 1); } -void ofApp::setFboAsTexture() { - surfaceManager.getSurface(0)->setTexture(&fbo->getTextureReference()); +void ofApp::setFboAsSource() { + surfaceManager.getSurface(0)->setSource(fboSource); } \ No newline at end of file diff --git a/example/src/ofApp.h b/example/src/ofApp.h index 1a81109..b3455a3 100755 --- a/example/src/ofApp.h +++ b/example/src/ofApp.h @@ -2,6 +2,7 @@ #include "ofMain.h" #include "ofxPiMapper.h" +#include "BaseSource.h" class ofApp : public ofBaseApp { public: @@ -15,13 +16,15 @@ class ofApp : public ofBaseApp { void addRandomSurface(); void addQuadSurface(); void addSurface(); - void setFboAsTexture(); + void setFboAsSource(); ofImage image; + ofx::piMapper::MediaServer mediaServer; ofx::piMapper::SurfaceManager surfaceManager; ofx::piMapper::SurfaceManagerGui gui; bool bShowInfo; ofFbo* fbo; + ofx::piMapper::BaseSource* fboSource; vector rects; vector rectSpeeds; }; \ No newline at end of file diff --git a/src/MediaServer/DirectoryWatcher.cpp b/src/MediaServer/DirectoryWatcher.cpp index db3e757..e55fa79 100644 --- a/src/MediaServer/DirectoryWatcher.cpp +++ b/src/MediaServer/DirectoryWatcher.cpp @@ -13,9 +13,9 @@ namespace ofx { DirectoryWatcher::DirectoryWatcher(std::string path, int watcherMediaType) { mediaType = watcherMediaType; // Decide what filter we need depending on media type - if (mediaType == MediaType::MEDIA_TYPE_VIDEO) { + if (mediaType == SourceType::SOURCE_TYPE_VIDEO) { filter = new VideoPathFilter(); - } else if (mediaType == MediaType::MEDIA_TYPE_IMAGE) { + } else if (mediaType == SourceType::SOURCE_TYPE_IMAGE) { filter = new ImagePathFilter(); } else { ofLogFatalError("DirectoryWatcher::DirectoryWatcher", "Unkonwn media type"); diff --git a/src/MediaServer/DirectoryWatcher.h b/src/MediaServer/DirectoryWatcher.h index 7571b64..8df11bb 100644 --- a/src/MediaServer/DirectoryWatcher.h +++ b/src/MediaServer/DirectoryWatcher.h @@ -10,7 +10,7 @@ #include "ofMain.h" #include "ofxIO.h" -#include "MediaType.h" +#include "SourceType.h" namespace ofx { namespace piMapper { diff --git a/src/MediaServer/MediaServer.cpp b/src/MediaServer/MediaServer.cpp index eb032db..4d1e7cb 100644 --- a/src/MediaServer/MediaServer.cpp +++ b/src/MediaServer/MediaServer.cpp @@ -12,12 +12,13 @@ namespace ofx { namespace piMapper { MediaServer::MediaServer(): - videoWatcher(ofToDataPath(DEFAULT_VIDEOS_DIR, true), MediaType::MEDIA_TYPE_VIDEO), - imageWatcher(ofToDataPath(DEFAULT_IMAGES_DIR, true), MediaType::MEDIA_TYPE_IMAGE) { + videoWatcher(ofToDataPath(DEFAULT_VIDEOS_DIR, true), SourceType::SOURCE_TYPE_VIDEO), + imageWatcher(ofToDataPath(DEFAULT_IMAGES_DIR, true), SourceType::SOURCE_TYPE_IMAGE) { addWatcherListeners(); } MediaServer::~MediaServer() { + cout << "Media server is over" << endl; removeWatcherListeners(); }; @@ -43,67 +44,215 @@ namespace piMapper { return imageNames; } - void MediaServer::loadImage(string& path) { + BaseSource* MediaServer::loadMedia(string &path, int mediaType) { + // Chose load method depending on type + if (mediaType == SourceType::SOURCE_TYPE_IMAGE) { + return loadImage(path); + } else if (mediaType == SourceType::SOURCE_TYPE_VIDEO) { + return loadVideo(path); + } else { + std::stringstream ss; + ss << "Can not load media of unknown type: " << mediaType; + ofLogFatalError("MediaServer") << ss.str(); + std::exit(EXIT_FAILURE); + } + return NULL; + } + + BaseSource* MediaServer::loadImage(string& path) { + ImageSource* imageSource = NULL; // Check if this image is already loaded bool isImageLoaded = false; - for (int i = 0; i < loadedImagePaths.size(); i++) { - if (path == loadedImagePaths[i]) { - isImageLoaded = true; - break; - } + if (loadedSources.count(path)) { + imageSource = static_cast(loadedSources[path]); + isImageLoaded = true; } // If image is loaded if (isImageLoaded) { + // Increase reference count of this source + //referenceCount[path]++; + imageSource->referenceCount++; + std::stringstream refss; + refss << "Current reference count for " << path << " = " << imageSource->referenceCount; + ofLogNotice("MediaServer") << refss.str(); // Notify objects registered to onImageLoaded event std::stringstream ss; ss << "Image " << path << " already loaded"; ofLogNotice("MediaServer") << ss.str(); ofNotifyEvent(onImageLoaded, path, this); - } else { - // Load image and add to vector if loading success - ofImage image; - if (image.loadImage(path)) { - loadedImages.push_back(image); - loadedImagePaths.push_back(path); // Save also path - // Notify objects registered to onImageLoaded event - ofNotifyEvent(onImageLoaded, path, this); + return imageSource; + } + // Else load fresh + imageSource = new ImageSource(); + imageSource->loadImage(path); + loadedSources[path] = imageSource; + // Set reference count of this image path to 1 + //referenceCount[path] = 1; + std::stringstream refss; + refss << "Initialized reference count of " << path << " to " << imageSource->referenceCount; + ofLogNotice("MediaServer") << refss.str(); + // Notify objects registered to onImageLoaded event + ofNotifyEvent(onImageLoaded, path, this); + return imageSource; + } + + void MediaServer::unloadImage(string& path) { + + ImageSource* source = static_cast(getSourceByPath(path)); + // Decrease reference count of the image + //referenceCount[path]--; + source->referenceCount--; + // Unload only if reference count is less or equal to 0 + cout << "referenceCount: " << source->referenceCount << endl; + if (source->referenceCount > 0) { + ofLogNotice("MediaServer") << "Not unloading image as it is being referenced elsewhere"; + return; + } + // Reference count 0 or less, unload image + std::stringstream ss; + ss << "Removing image " << path; + ofLogNotice("MediaServer") << ss.str(); + // Destroy image source + if (loadedSources.count(path)) { + //loadedSources[path]->clear(); + delete loadedSources[path]; + loadedSources.erase(path); + ofNotifyEvent(onImageUnloaded, path, this); + return; + } + // Something wrong here, we should be out of the routine by now + std::stringstream failss; + failss << "Failed to remove image source: " << path; + ofLogFatalError("MediaServer") << failss.str(); + std::exit(EXIT_FAILURE); + } + + BaseSource* MediaServer::loadVideo(string& path) { + cout << "loading video: " << path << endl; + VideoSource* videoSource = NULL; + // Check if this video is already loaded + bool isVideoLoaded = false; + if (loadedSources.count(path)) { + videoSource = static_cast(loadedSources[path]); + isVideoLoaded = true; + } + // If is loaded + if (isVideoLoaded) { + // Increase reference count of this source + //referenceCount[path]++; + videoSource->referenceCount++; + std::stringstream refss; + refss << "Current reference count for " << path << " = " << videoSource->referenceCount; + ofLogNotice("MediaServer") << refss.str(); + // Notify objects registered to onImageLoaded event + std::stringstream ss; + ss << "Video " << path << " already loaded"; + ofLogNotice("MediaServer") << ss.str(); + ofNotifyEvent(onVideoLoaded, path, this); + return videoSource; + } + // Else load fresh + videoSource = new VideoSource(); + videoSource->loadVideo(path); + loadedSources[path] = videoSource; + // Set reference count of this image path to 1 + //referenceCount[path] = 1; + std::stringstream refss; + refss << "Initialized reference count of " << path << " to " << videoSource->referenceCount; + ofLogNotice("MediaServer") << refss.str(); + ofNotifyEvent(onVideoLoaded, path, this); + return videoSource; + } + + void MediaServer::unloadVideo(string& path) { + VideoSource* videoSource = static_cast(getSourceByPath(path)); + // Decrease reference count of the video + //referenceCount[path]--; + videoSource->referenceCount--; + // Unload only if reference count is less or equal to 0 + if (videoSource->referenceCount > 0) { + ofLogNotice("MediaServer") << "Not unloading video as it is being referenced elsewhere"; + return; + } + // Reference count 0 or less, let's unload the video + std::stringstream ss; + ss << "Removing video " << path; + ofLogNotice("MediaServer") << ss.str(); + // Distroy video source + if (loadedSources.count(path)) { + loadedSources[path]->clear(); + delete loadedSources[path]; + loadedSources.erase(path); + ofNotifyEvent(onVideoUnloaded, path, this); + return; + } + // Something wrong here, we should be out of the routine by now + std::stringstream failss; + failss << "Failed to remove video source: " << path; + ofLogFatalError("MediaServer") << failss.str(); + std::exit(EXIT_FAILURE); + } + + void MediaServer::unloadMedia(string &path) { + if (loadedSources.count(path)) { + BaseSource* mediaSource = getSourceByPath(path); + if (mediaSource->getType() == SourceType::SOURCE_TYPE_IMAGE) { + unloadImage(path); + } else if (mediaSource->getType() == SourceType::SOURCE_TYPE_VIDEO) { + unloadVideo(path); } else { - ofLogFatalError("MediaServer") << "Failed to load image"; + // Oh my god, what to do!? Relax and exit. + ofLogFatalError("MediaServer") << "Attempt to unload media of unknown type"; std::exit(EXIT_FAILURE); } + } else { + std:stringstream ss; + ss << "Media with path " << path << " is not loaded and thus can't be unloaded"; + ofLogFatalError("MediaServer") << ss.str(); + std::exit(EXIT_FAILURE); } } - void MediaServer::unloadImage(string& path) { - // Search for given path in loaded image paths - for (int i = 0; i < loadedImagePaths.size(); i++) { - // If found - if (loadedImagePaths[i] == path) { - // Remove path and unload image as well as remove it from storage - loadedImagePaths.erase(loadedImagePaths.begin() + i); - loadedImages[i].clear(); - loadedImages.erase(loadedImages.begin() + i); - ofNotifyEvent(onImageUnloaded, path, this); - break; - } + // Clear all loaded media + void MediaServer::clear() { + typedef std::map::iterator it_type; + for (it_type i = loadedSources.begin(); i != loadedSources.end(); i++) { + delete i->second; } + loadedSources.clear(); } - ofTexture* MediaServer::getImageTexture(string &path) { - - // Find image index by path - for (int i = 0; i < loadedImagePaths.size(); i++) { - if (path == loadedImagePaths[i]) { - if (loadedImages[i].isAllocated()) { - return &loadedImages[i].getTextureReference(); - } - } + BaseSource* MediaServer::getSourceByPath(std::string& mediaPath) { + cout << "num loaded sources: " << loadedSources.size() << endl; + if (loadedSources.count(mediaPath)) { + return loadedSources[mediaPath]; + } + // Source not found, exit with error + std::stringstream ss; + ss << "Could not find source by path: " << mediaPath; + ofLogFatalError("MediaServer") << ss.str(); + std::exit(EXIT_FAILURE); + } + + std::string MediaServer::getDefaultImageDir() { + return DEFAULT_IMAGES_DIR; + } + + std::string MediaServer::getDefaultVideoDir() { + return DEFAULT_VIDEOS_DIR; + } + + std::string MediaServer::getDefaultMediaDir(int sourceType) { + if (sourceType == SourceType::SOURCE_TYPE_IMAGE) { + return getDefaultImageDir(); + } else if (sourceType == SourceType::SOURCE_TYPE_VIDEO) { + return getDefaultVideoDir(); + } else { + std::stringstream ss; + ss << "Could not get default media dir. Unknown source type: " << sourceType; + ofLogFatalError("MediaServer") << ss.str(); + std::exit(EXIT_FAILURE); } - - // If we havent returned yet, that means that there is no image - // and we need to sort this out somehow - ofLogError("MediaServer::getImageTexture", "Image not found"); - return NULL; } void MediaServer::handleImageAdded(string& path) { diff --git a/src/MediaServer/MediaServer.h b/src/MediaServer/MediaServer.h index 5f5e131..8cb3bfd 100644 --- a/src/MediaServer/MediaServer.h +++ b/src/MediaServer/MediaServer.h @@ -10,7 +10,10 @@ #include "ofMain.h" #include "DirectoryWatcher.h" -#include "MediaType.h" +#include "BaseSource.h" +#include "ImageSource.h" +#include "VideoSource.h" +#include "SourceType.h" #define DEFAULT_IMAGES_DIR "sources/images/" #define DEFAULT_VIDEOS_DIR "sources/videos/" @@ -29,10 +32,17 @@ class MediaServer { std::vector& getImagePaths(); std::vector getImageNames(); - // Image loading and handling - void loadImage(string& path); + BaseSource* loadMedia(string& path, int mediaType); + BaseSource* loadImage(string& path); void unloadImage(string& path); - ofTexture* getImageTexture(string& path); + BaseSource* loadVideo(string& path); + void unloadVideo(string& path); + void unloadMedia(string& path); + void clear(); // Force all loaded source unload + BaseSource* getSourceByPath(std::string& mediaPath); + std::string getDefaultImageDir(); + std::string getDefaultVideoDir(); + std::string getDefaultMediaDir(int sourceType); // Custom events ofEvent onImageAdded; @@ -41,16 +51,14 @@ class MediaServer { ofEvent onVideoRemoved; ofEvent onImageLoaded; ofEvent onImageUnloaded; + ofEvent onVideoLoaded; + ofEvent onVideoUnloaded; private: // Directory Watchers ofx::piMapper::DirectoryWatcher videoWatcher; ofx::piMapper::DirectoryWatcher imageWatcher; - - // Loaded media - vector loadedImages; - vector loadedImagePaths; - + std::map loadedSources; // imageWatcher event listeners void handleImageAdded(string& path); void handleImageRemoved(string& path); diff --git a/src/MediaServer/MediaType.h b/src/MediaServer/MediaType.h deleted file mode 100644 index fca54b9..0000000 --- a/src/MediaServer/MediaType.h +++ /dev/null @@ -1,9 +0,0 @@ -#pragma once - -namespace ofx { - namespace piMapper { - struct MediaType { - enum { MEDIA_TYPE_IMAGE, MEDIA_TYPE_VIDEO }; - }; - } -} \ No newline at end of file diff --git a/src/Sources/BaseSource.cpp b/src/Sources/BaseSource.cpp new file mode 100644 index 0000000..66f7691 --- /dev/null +++ b/src/Sources/BaseSource.cpp @@ -0,0 +1,57 @@ +#include "BaseSource.h" + +namespace ofx { + namespace piMapper { + BaseSource::BaseSource() { + //cout << "BaseSource" << endl; + init(); + } + + BaseSource::BaseSource(ofTexture* newTexture) { + init(); + texture = newTexture; + } + + ofTexture* BaseSource::getTexture() { + return texture; + } + + std::string& BaseSource::getName() { + return name; + } + + bool BaseSource::isLoadable() { + return loadable; + } + + bool BaseSource::isLoaded() { + return loaded; + } + + int BaseSource::getType() { + return type; + } + + std::string& BaseSource::getPath() { + return path; + } + + void BaseSource::init() { + texture = NULL; + name = ""; + path = ""; + loadable = false; + loaded = false; + type = SourceType::SOURCE_TYPE_NONE; + referenceCount = 1; // We have one instance on init + } + + void BaseSource::setNameFromPath(std::string& fullPath) { + std::vector pathParts; + //cout << "fullPath: " << fullPath << endl; + pathParts = ofSplitString(fullPath, "/"); // Maybe on win "/" is "\", have to test + //cout << "lastPathPart: " << pathParts[pathParts.size() - 1] << endl; + name = pathParts[pathParts.size() - 1]; + } + } +} \ No newline at end of file diff --git a/src/Sources/BaseSource.h b/src/Sources/BaseSource.h new file mode 100644 index 0000000..4970c5e --- /dev/null +++ b/src/Sources/BaseSource.h @@ -0,0 +1,35 @@ +#pragma once + +#include "ofMain.h" +#include "SourceType.h" + +namespace ofx { + namespace piMapper { + // Use this for adding generative sources to your surfaces + class BaseSource { + public: + BaseSource(); + BaseSource(ofTexture* newTexture); // Only one clean way of passing the texture + ofTexture* getTexture(); + std::string& getName(); + bool isLoadable(); // Maybe the loading features shoud go to a derrived class + bool isLoaded(); // as BaseSourceLoadable + int getType(); + std::string& getPath(); + virtual void clear() {}; + int referenceCount; + + private: + void init(); + + protected: + void setNameFromPath(std::string& fullPath); + ofTexture* texture; + std::string name; + std::string path; // This is set only if loadable is true + bool loadable; // If the source can be loaded from disk like image and video + bool loaded; // Is the source loaded? + int type; + }; + } +} diff --git a/src/Sources/ImageSource.cpp b/src/Sources/ImageSource.cpp new file mode 100644 index 0000000..8042baf --- /dev/null +++ b/src/Sources/ImageSource.cpp @@ -0,0 +1,41 @@ +#include "ImageSource.h" + +namespace ofx { + namespace piMapper { + ImageSource::ImageSource() { + //cout << "ImageSource" << endl; + loadable = true; + loaded = false; + type = SourceType::SOURCE_TYPE_IMAGE; + } + + ImageSource::~ImageSource() { + clear(); + } + + void ImageSource::loadImage(std::string& filePath) { + path = filePath; + cout << "loading image: " << filePath << endl; + setNameFromPath(filePath); + cout << "path: " << path << endl; + image = new ofImage(); + if (!image->loadImage(filePath)) { + ofLogFatalError("ImageSource") << "Could not load image"; + std::exit(EXIT_FAILURE); + } + texture = &image->getTextureReference(); + loaded = true; + } + + void ImageSource::clear() { + texture = NULL; + image->clear(); + delete image; + image = NULL; + path = ""; + name = ""; + loaded = false; + } + + } +} \ No newline at end of file diff --git a/src/Sources/ImageSource.h b/src/Sources/ImageSource.h new file mode 100644 index 0000000..29a5d79 --- /dev/null +++ b/src/Sources/ImageSource.h @@ -0,0 +1,18 @@ +#pragma once + +#include "BaseSource.h" + +namespace ofx { + namespace piMapper { + class ImageSource : public BaseSource { + public: + ImageSource(); + ~ImageSource(); + std::string& getPath(); + void loadImage(std::string& filePath); + void clear(); + private: + ofImage* image; + }; + } +} \ No newline at end of file diff --git a/src/Sources/SourceType.h b/src/Sources/SourceType.h new file mode 100644 index 0000000..b37daa1 --- /dev/null +++ b/src/Sources/SourceType.h @@ -0,0 +1,46 @@ +#pragma once + +#import "ofLog.h" + +#define SOURCE_TYPE_NAME_NONE "none" +#define SOURCE_TYPE_NAME_IMAGE "image" +#define SOURCE_TYPE_NAME_VIDEO "video" + +namespace ofx { + namespace piMapper { + class SourceType { + public: + enum { SOURCE_TYPE_NONE, SOURCE_TYPE_IMAGE, SOURCE_TYPE_VIDEO }; + + static std::string GetSourceTypeName(int sourceTypeEnum) { + if (sourceTypeEnum == SOURCE_TYPE_IMAGE) { + return SOURCE_TYPE_NAME_IMAGE; + } else if (sourceTypeEnum == SOURCE_TYPE_VIDEO) { + return SOURCE_TYPE_NAME_VIDEO; + } else if (sourceTypeEnum == SOURCE_TYPE_NONE) { + return SOURCE_TYPE_NAME_NONE; + } else { + std::stringstream ss; + ss << "Invalid source type: " << sourceTypeEnum; + ofLogFatalError("SourceType") << ss.str(); + std::exit(EXIT_FAILURE); + } + }; + + static int GetSourceTypeEnum(std::string sourceTypeName) { + if (sourceTypeName == SOURCE_TYPE_NAME_IMAGE) { + return SOURCE_TYPE_IMAGE; + } else if (sourceTypeName == SOURCE_TYPE_NAME_VIDEO) { + return SOURCE_TYPE_VIDEO; + } else if (sourceTypeName == SOURCE_TYPE_NAME_NONE) { + return SOURCE_TYPE_NONE; + } else { + std::stringstream ss; + ss << "Invalid source type name: " << sourceTypeName; + ofLogFatalError("SourceType") << ss.str(); + std::exit(EXIT_FAILURE); + } + } + }; + } +} \ No newline at end of file diff --git a/src/Sources/VideoSource.cpp b/src/Sources/VideoSource.cpp new file mode 100644 index 0000000..1c3fcb4 --- /dev/null +++ b/src/Sources/VideoSource.cpp @@ -0,0 +1,66 @@ +#include "VideoSource.h" + +namespace ofx { + namespace piMapper { + VideoSource::VideoSource() { + loadable = true; + loaded = false; + type = SourceType::SOURCE_TYPE_VIDEO; + } + + VideoSource::~VideoSource() { + clear(); + } + + void VideoSource::loadVideo(std::string& filePath) { + path = filePath; + //cout << "loading video: " << filePath << endl; + setNameFromPath(filePath); +#ifdef TARGET_RASPBERRY_PI + // TODO: do omx player + // + // + // +#else + // regular ofVideoPlayer + videoPlayer = new ofVideoPlayer(); + videoPlayer->loadMovie(filePath); + videoPlayer->setLoopState(OF_LOOP_NORMAL); + videoPlayer->play(); + texture = &(videoPlayer->getTextureReference()); + ofAddListener(ofEvents().update, this, &VideoSource::update); +#endif + loaded = true; + } + + void VideoSource::clear() { + ofRemoveListener(ofEvents().update, this, &VideoSource::update); + texture = NULL; +#ifdef TARGET_RASPBERRY_PI + // TODO: do omx player + // + // + // +#else + videoPlayer->stop(); + videoPlayer->close(); + delete videoPlayer; + videoPlayer = NULL; +#endif + path = ""; + name = ""; + loaded = false; + } + + void VideoSource::update(ofEventArgs &args) { +#ifdef TARGET_RASPBERRY_PI + // TODO: do omx player + // + // probably needs updating as well + // +#else + videoPlayer->update(); +#endif + } + } +} \ No newline at end of file diff --git a/src/Sources/VideoSource.h b/src/Sources/VideoSource.h new file mode 100644 index 0000000..453eb06 --- /dev/null +++ b/src/Sources/VideoSource.h @@ -0,0 +1,32 @@ +#pragma once + +#include "ofMain.h" +#include "BaseSource.h" +#ifdef TARGET_RASPBERRY_PI + #include "ofxOMXPlayer.h" +#endif + +namespace ofx { + namespace piMapper { + class VideoSource : public BaseSource { + public: + VideoSource(); + ~VideoSource(); + std::string& getPath(); + void loadVideo(std::string& path); + void clear(); + void update(ofEventArgs& args); + private: +#ifdef TARGET_RASPBERRY_PI + // TODO: implement ofxOMXPlayer + // + // + // +#else + // Go with ofVideoPlayer or + // TODO: High Performance Video player on newer Macs + ofVideoPlayer* videoPlayer; +#endif + }; + } +} \ No newline at end of file diff --git a/src/SourcesEditor.cpp b/src/SourcesEditor.cpp index 3bf7b51..1d3d0fc 100644 --- a/src/SourcesEditor.cpp +++ b/src/SourcesEditor.cpp @@ -87,9 +87,7 @@ namespace piMapper { void SourcesEditor::loadImage(string name, string path) { images.push_back(new ofImage()); images.back()->loadImage(path); - imageNames.push_back(name); - ofSendMessage("imageLoaded"); } @@ -113,13 +111,15 @@ namespace piMapper { // If the new media server is not valid if (newMediaServer == NULL) { // Log an error and return from the routine - ofLogError("SourcesEditor::setMediaServer", "New media server is NULL"); - return; + ofLogFatalError("SourcesEditor") << "New media server is NULL"; + std::exit(EXIT_FAILURE); } - // Attempt to clear existing media server and assign new one clearMediaServer(); + cout << "old ms addr: " << mediaServer << endl; + cout << "new ms addr: " << newMediaServer << endl; mediaServer = newMediaServer; + isMediaServerExternal = true; } void SourcesEditor::selectImageSourceRadioButton(string name) { @@ -188,22 +188,22 @@ namespace piMapper { } void SourcesEditor::handleRadioSelected(string& sourcePath) { - if (surfaceManager->getSelectedSurface() == NULL) { + BaseSurface* surface = surfaceManager->getSelectedSurface(); + if (surface == NULL) { return; } - - cout << "Attempt to load image: " << sourcePath << endl; - mediaServer->loadImage(sourcePath); + BaseSource* source = surface->getSource(); + if (source->isLoadable()) { + mediaServer->unloadMedia(source->getPath()); + } + surface->setSource(mediaServer->loadImage(sourcePath)); } void SourcesEditor::clearMediaServer() { - // If mediaServer is local, clear it - if (isMediaServerExternal) { - + if (!isMediaServerExternal) { // Clear all loaded sources - //mediaServer->clear() - + mediaServer->clear(); // Destroy the pointer and set it to NULL pointer delete mediaServer; mediaServer = NULL; @@ -232,8 +232,8 @@ namespace piMapper { // Test image unload // mediaServer->unloadImage(path); - ofTexture* texture = mediaServer->getImageTexture(path); - surfaceManager->getSelectedSurface()->setTexture(texture); + BaseSource* source = mediaServer->getSourceByPath(path); + surfaceManager->getSelectedSurface()->setSource(source); } void SourcesEditor::handleImageUnloaded(string& path) { diff --git a/src/SurfaceManager.cpp b/src/SurfaceManager.cpp index b4da419..c2c8c68 100644 --- a/src/SurfaceManager.cpp +++ b/src/SurfaceManager.cpp @@ -2,7 +2,10 @@ namespace ofx { namespace piMapper { -SurfaceManager::SurfaceManager() {} + SurfaceManager::SurfaceManager() { + // Init variables + mediaServer = NULL; + } SurfaceManager::~SurfaceManager() { clear(); } @@ -18,19 +21,21 @@ void SurfaceManager::addSurface(int surfaceType) { } else if (surfaceType == SurfaceType::QUAD_SURFACE) { surfaces.push_back(new QuadSurface()); } else { - throw std::runtime_error("Attempt to add non-existing surface type."); + ofLogFatalError("SurfaceManager") << "Attempt to add non-existing surface type"; + std::exit(EXIT_FAILURE); } } -void SurfaceManager::addSurface(int surfaceType, ofTexture* texturePtr) { +void SurfaceManager::addSurface(int surfaceType, BaseSource* newSource) { if (surfaceType == SurfaceType::TRIANGLE_SURFACE) { surfaces.push_back(new TriangleSurface()); - surfaces.back()->setTexture(texturePtr); + surfaces.back()->setSource(newSource); } else if (surfaceType == SurfaceType::QUAD_SURFACE) { surfaces.push_back(new QuadSurface()); - surfaces.back()->setTexture(texturePtr); + surfaces.back()->setSource(newSource); } else { - throw std::runtime_error("Attempt to add non-existing surface type."); + ofLogFatalError("SurfaceManager") << "Attempt to add non-existing surface type"; + std::exit(EXIT_FAILURE); } } @@ -67,11 +72,12 @@ void SurfaceManager::addSurface(int surfaceType, vector vertices, surfaces.back()->setTexCoord(i, texCoords[i]); } } else { - throw std::runtime_error("Attempt to add non-existing surface type."); + ofLogFatalError("SurfaceManager") << "Attempt to add non-existing surface type"; + std::exit(EXIT_FAILURE); } } -void SurfaceManager::addSurface(int surfaceType, ofTexture* texturePtr, +void SurfaceManager::addSurface(int surfaceType, BaseSource* newSource, vector vertices, vector texCoords) { if (surfaceType == SurfaceType::TRIANGLE_SURFACE) { @@ -84,7 +90,7 @@ void SurfaceManager::addSurface(int surfaceType, ofTexture* texturePtr, } surfaces.push_back(new TriangleSurface()); - surfaces.back()->setTexture(texturePtr); + surfaces.back()->setSource(newSource); for (int i = 0; i < 3; i++) { surfaces.back()->setVertex(i, vertices[i]); @@ -100,20 +106,22 @@ void SurfaceManager::addSurface(int surfaceType, ofTexture* texturePtr, } surfaces.push_back(new QuadSurface()); - surfaces.back()->setTexture(texturePtr); + surfaces.back()->setSource(newSource); 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."); + ofLogFatalError("SurfaceManager") << "Attempt to add non-existing surface type"; + std::exit(EXIT_FAILURE); } } void SurfaceManager::removeSelectedSurface() { - if (selectedSurface == NULL) return; - + if (selectedSurface == NULL) { + return; + } for (int i = 0; i < surfaces.size(); i++) { if (surfaces[i] == selectedSurface) { delete surfaces[i]; @@ -124,61 +132,23 @@ void SurfaceManager::removeSelectedSurface() { } } -void SurfaceManager::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 SurfaceManager::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(SurfaceType e) -// { -// switch e -// { -// case TRINAGLE_SURFACE: return "TRINAGLE_SURFACE"; -// case QUAD_SURFACE: return "QUAD_SURFACE"; -// default: throw Exception("Bad MyEnum"); -// } -// } - void SurfaceManager::saveXmlSettings(string fileName) { + // Exit if mediaServer not set + if (mediaServer == NULL) { + ofLogFatalError("SurfaceManager") << "Media server not set"; + std::exit(EXIT_FAILURE); + } + // We need a fresh copy of the xml settings object xmlSettings.clear(); - - // save surfaces + // Save surfaces xmlSettings.addTag("surfaces"); xmlSettings.pushTag("surfaces"); for (int i = 0; i < surfaces.size(); i++) { @@ -214,37 +184,31 @@ void SurfaceManager::saveXmlSettings(string fileName) { 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"); + string sourceTypeName = SourceType::GetSourceTypeName(surface->getSource()->getType()); + cout << "sourceTypeName: " << sourceTypeName << endl; + xmlSettings.addValue("source-type", sourceTypeName); + xmlSettings.addValue("source-name", surface->getSource()->getName()); xmlSettings.popTag(); // source - - // xmlSettings.addTag("type"); - // xmlSettings.pushTag("type"); - // // surfaceType == SurfaceType::TRIANGLE_SURFACE - // SurfaceType surfaceType = &surface->getType(); - // xmlSettings.addValue("surface-type", surfaceType); - // xmlSettings.popTag(); // type - xmlSettings.popTag(); // surface } xmlSettings.popTag(); // surfaces - xmlSettings.save(fileName); } void SurfaceManager::loadXmlSettings(string fileName) { + // Exit if there is no media server + if (mediaServer == NULL) { + ofLogFatalError("SurfaceManager") << "Media server not set"; + std::exit(EXIT_FAILURE); + } if (!xmlSettings.loadFile(fileName)) { - ofLog(OF_LOG_WARNING, "Could not load XML settings."); + ofLogWarning("SurfaceManager") << "Could not load XML settings"; return; } - if (!xmlSettings.tagExists("surfaces")) { - ofLog(OF_LOG_WARNING, "XML settings is empty or has wrong markup."); + ofLogWarning("SurfaceManager") << "XML settings is empty or has wrong markup"; return; } @@ -255,28 +219,24 @@ void SurfaceManager::loadXmlSettings(string fileName) { 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()); + string sourceType = xmlSettings.getValue("source-type", ""); + string sourceName = xmlSettings.getValue("source-name", ""); + BaseSource* source = NULL; + if (sourceName != "" && sourceName != "none" && sourceType != "") { + // Load source depending on type + int typeEnum = SourceType::GetSourceTypeEnum(sourceType); + // Construct full path + string dir = mediaServer->getDefaultMediaDir(typeEnum); + std::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 - - // // 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 vertices; - int vertexCount = xmlSettings.getNumTags("vertex"); - // it's a triangle ? if (vertexCount == 3) { //ofLog(OF_LOG_NOTICE, "create Triangle"); @@ -320,8 +280,8 @@ void SurfaceManager::loadXmlSettings(string fileName) { // now we have variables sourceName and sourceTexture // by checking those we can use one or another addSurface method - if (sourceName != "none" && sourceTexture != NULL) { - addSurface(SurfaceType::TRIANGLE_SURFACE, sourceTexture, vertices, + if (sourceName != "none" && source != NULL) { + addSurface(SurfaceType::TRIANGLE_SURFACE, source, vertices, texCoords); } else { addSurface(SurfaceType::TRIANGLE_SURFACE, vertices, texCoords); @@ -381,8 +341,8 @@ void SurfaceManager::loadXmlSettings(string fileName) { // now we have variables sourceName and sourceTexture // by checking those we can use one or another addSurface method - if (sourceName != "none" && sourceTexture != NULL) { - addSurface(SurfaceType::QUAD_SURFACE, sourceTexture, vertices, + if (sourceName != "none" && source != NULL) { + addSurface(SurfaceType::QUAD_SURFACE, source, vertices, texCoords); } else { addSurface(SurfaceType::QUAD_SURFACE, vertices, texCoords); @@ -394,6 +354,10 @@ void SurfaceManager::loadXmlSettings(string fileName) { xmlSettings.popTag(); // surfaces } + + void SurfaceManager::setMediaServer(MediaServer* newMediaServer) { + mediaServer = newMediaServer; + } BaseSurface* SurfaceManager::selectSurface(int index) { if (index >= surfaces.size()) { @@ -406,46 +370,12 @@ BaseSurface* SurfaceManager::selectSurface(int index) { ofSendMessage("surfaceSelected"); } -BaseSurface* SurfaceManager::getSelectedSurface() { return selectedSurface; } - -void SurfaceManager::deselectSurface() { selectedSurface = NULL; } - -ofTexture* SurfaceManager::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(); +BaseSurface* SurfaceManager::getSelectedSurface() { + return selectedSurface; } -string SurfaceManager::getSelectedSurfaceSourceName() { - if (selectedSurface == NULL) { - return "none"; - } - - return getSurfaceSourceName(selectedSurface); -} - -string SurfaceManager::getSurfaceSourceName(BaseSurface* surface) { - ofTexture* tex = surface->getTexture(); - for (int i = 0; i < loadedImageSources.size(); i++) { - if (tex == &loadedImageSources[i]->getTextureReference()) { - return loadedImageSourceNames[i]; - } - } - - return "none"; +void SurfaceManager::deselectSurface() { + selectedSurface = NULL; } BaseSurface* SurfaceManager::getSurface(int index) { diff --git a/src/SurfaceManager.h b/src/SurfaceManager.h index 38af95f..2e6eb6f 100755 --- a/src/SurfaceManager.h +++ b/src/SurfaceManager.h @@ -4,6 +4,9 @@ #include "TriangleSurface.h" #include "QuadSurface.h" #include "SurfaceType.h" +#include "MediaServer.h" +#include "BaseSource.h" +#include "SourceType.h" #include "ofEvents.h" #include "ofxXmlSettings.h" @@ -19,32 +22,28 @@ class SurfaceManager { void draw(); void addSurface(int surfaceType); - void addSurface(int surfaceType, ofTexture* texturePtr); + void addSurface(int surfaceType, BaseSource* newSource); void addSurface(int surfaceType, vector vertices, vector texCoords); - void addSurface(int surfaceType, ofTexture* texturePtr, + void addSurface(int surfaceType, BaseSource* newSource, vector vertices, vector texCoords); void removeSelectedSurface(); - void manageMemory(); // deletes unasigned sources void clear(); void saveXmlSettings(string fileName); void loadXmlSettings(string fileName); + void setMediaServer(MediaServer* newMediaServer); BaseSurface* getSurface(int index); int size(); BaseSurface* selectSurface(int index); BaseSurface* getSelectedSurface(); void deselectSurface(); - ofTexture* loadImageSource(string name, string path); - string getSelectedSurfaceSourceName(); - string getSurfaceSourceName(BaseSurface* surface); private: - vector surfaces; + std::vector surfaces; BaseSurface* selectedSurface; - vector loadedImageSourceNames; - vector loadedImageSources; ofxXmlSettings xmlSettings; + MediaServer* mediaServer; }; } } \ No newline at end of file diff --git a/src/SurfaceManagerGui.cpp b/src/SurfaceManagerGui.cpp index ce73e99..dee1584 100644 --- a/src/SurfaceManagerGui.cpp +++ b/src/SurfaceManagerGui.cpp @@ -174,6 +174,13 @@ void SurfaceManagerGui::setSurfaceManager(SurfaceManager* newSurfaceManager) { sourcesEditor.setSurfaceManager(surfaceManager); } + // Set external media server so we can access it from wherever we need + void SurfaceManagerGui::setMediaServer(MediaServer* newMediaServer) { + mediaServer = newMediaServer; + // Set the media server of the sources editor here + sourcesEditor.setMediaServer(mediaServer); + } + void SurfaceManagerGui::setMode(int newGuiMode) { if (newGuiMode != GuiMode::NONE && newGuiMode != GuiMode::TEXTURE_MAPPING && newGuiMode != GuiMode::PROJECTION_MAPPING && @@ -191,8 +198,8 @@ void SurfaceManagerGui::setMode(int newGuiMode) { if (guiMode == GuiMode::SOURCE_SELECTION) { sourcesEditor.enable(); - string sourceName = surfaceManager->getSelectedSurfaceSourceName(); - sourcesEditor.selectImageSourceRadioButton(sourceName); + //string sourceName = surfaceManager->getSelectedSurfaceSourceName(); + //sourcesEditor.selectImageSourceRadioButton(sourceName); } else { sourcesEditor.disable(); } diff --git a/src/SurfaceManagerGui.h b/src/SurfaceManagerGui.h index 1c62cf6..7e998a8 100644 --- a/src/SurfaceManagerGui.h +++ b/src/SurfaceManagerGui.h @@ -27,6 +27,7 @@ class SurfaceManagerGui { void mouseReleased(ofMouseEventArgs& args); void mouseDragged(ofMouseEventArgs& args); void setSurfaceManager(SurfaceManager* newSurfaceManager); + void setMediaServer(MediaServer* newMediaServer); void setMode(int newGuiMode); void drawSelectedSurfaceHighlight(); void drawSelectedSurfaceTextureHighlight(); @@ -35,6 +36,7 @@ class SurfaceManagerGui { private: SurfaceManager* surfaceManager; + MediaServer* mediaServer; TextureEditor textureEditor; ProjectionEditor projectionEditor; SourcesEditor sourcesEditor; diff --git a/src/BaseSurface.cpp b/src/Surfaces/BaseSurface.cpp similarity index 57% rename from src/BaseSurface.cpp rename to src/Surfaces/BaseSurface.cpp index b674cd8..d6a1ce5 100644 --- a/src/BaseSurface.cpp +++ b/src/Surfaces/BaseSurface.cpp @@ -7,6 +7,12 @@ BaseSurface::BaseSurface() { ofEnableNormalizedTexCoords(); createDefaultTexture(); } + + BaseSurface::~BaseSurface() { + delete defaultSource; + defaultSource = NULL; + defaultTexture.clear(); + } void BaseSurface::createDefaultTexture() { ofPixels pixels; @@ -38,33 +44,47 @@ void BaseSurface::createDefaultTexture() { // load pixels into texture defaultTexture.loadData(pixels); - - // Assign default texture to texture pointer - texture = &defaultTexture; + // Create new source to be the default + defaultSource = new BaseSource(&defaultTexture); + source = defaultSource; } void BaseSurface::drawTexture(ofVec2f position) { + if (source->getTexture() == NULL) { + ofLogWarning("BaseSurface") << "Source texture empty. Not drawing."; + return; + } + ofMesh texMesh; texMesh.addVertex(position); - texMesh.addVertex(position + ofVec2f(texture->getWidth(), 0.0f)); + texMesh.addVertex(position + ofVec2f(source->getTexture()->getWidth(), 0.0f)); texMesh.addVertex(position + - ofVec2f(texture->getWidth(), texture->getHeight())); - texMesh.addVertex(position + ofVec2f(0.0f, texture->getHeight())); + ofVec2f(source->getTexture()->getWidth(), source->getTexture()->getHeight())); + texMesh.addVertex(position + ofVec2f(0.0f, source->getTexture()->getHeight())); texMesh.addTriangle(0, 2, 3); texMesh.addTriangle(0, 1, 2); texMesh.addTexCoord(ofVec2f(0.0f, 0.0f)); texMesh.addTexCoord(ofVec2f(1.0f, 0.0f)); texMesh.addTexCoord(ofVec2f(1.0f, 1.0f)); texMesh.addTexCoord(ofVec2f(0.0f, 1.0f)); - texture->bind(); + source->getTexture()->bind(); texMesh.draw(); - texture->unbind(); + source->getTexture()->unbind(); } -void BaseSurface::setTexture(ofTexture* texturePtr) { texture = texturePtr; } + //void BaseSurface::setTexture(ofTexture* texturePtr) { texture = texturePtr; } + void BaseSurface::setSource(BaseSource* newSource) { + source = newSource; + } -ofTexture* BaseSurface::getTexture() { return texture; } + //ofTexture* BaseSurface::getTexture() { return texture; } + BaseSource* BaseSurface::getSource() { + return source; + } -ofTexture* BaseSurface::getDefaultTexture() { return &defaultTexture; } + //ofTexture* BaseSurface::getDefaultTexture() { return &defaultTexture; } + BaseSource* BaseSurface::getDefaultSource() { + return defaultSource; + } } } \ No newline at end of file diff --git a/src/BaseSurface.h b/src/Surfaces/BaseSurface.h similarity index 69% rename from src/BaseSurface.h rename to src/Surfaces/BaseSurface.h index bf6703f..28b8b52 100644 --- a/src/BaseSurface.h +++ b/src/Surfaces/BaseSurface.h @@ -2,6 +2,7 @@ #include "ofMain.h" #include +#include "BaseSource.h" using namespace std; @@ -10,6 +11,7 @@ namespace piMapper { class BaseSurface { public: BaseSurface(); + ~BaseSurface(); virtual void setup() {}; virtual void draw() {}; virtual void setVertex(int index, ofVec2f p) {}; @@ -24,16 +26,21 @@ class BaseSurface { // Draws a texture using ofMesh void drawTexture(ofVec2f position); - void setTexture(ofTexture* texturePtr); - - ofTexture* getTexture(); - ofTexture* getDefaultTexture(); - + //void setTexture(ofTexture* texturePtr); + void setSource(BaseSource* newSource); + + //ofTexture* getTexture(); + //ofTexture* getDefaultTexture(); + BaseSource* getSource(); + BaseSource* getDefaultSource(); + protected: ofMesh mesh; - ofTexture* texture; + //ofTexture* texture; ofTexture defaultTexture; - + BaseSource* source; + BaseSource* defaultSource; + void createDefaultTexture(); }; } diff --git a/src/QuadSurface.cpp b/src/Surfaces/QuadSurface.cpp similarity index 90% rename from src/QuadSurface.cpp rename to src/Surfaces/QuadSurface.cpp index c72587c..cffd145 100644 --- a/src/QuadSurface.cpp +++ b/src/Surfaces/QuadSurface.cpp @@ -22,14 +22,14 @@ void QuadSurface::setup() { ofVec2f t3 = ofVec2f(ofVec2f(1.0f, 1.0f)); ofVec2f t4 = ofVec2f(ofVec2f(0.0f, 1.0f)); - setup(p1, p2, p3, p4, t1, t2, t3, t4, texture); + setup(p1, p2, p3, p4, t1, t2, t3, t4, source); } void QuadSurface::setup(ofVec2f p1, ofVec2f p2, ofVec2f p3, ofVec2f p4, ofVec2f t1, ofVec2f t2, ofVec2f t3, ofVec2f t4, - ofTexture* texturePtr) { + BaseSource* newSource) { // Assign texture - texture = texturePtr; + source = newSource; // Clear mesh mesh.clear(); @@ -68,6 +68,11 @@ void QuadSurface::setup(ofVec2f p1, ofVec2f p2, ofVec2f p3, ofVec2f p4, } void QuadSurface::draw() { + if (source->getTexture() == NULL) { + ofLogWarning("QuadSurface") << "Source texture empty. Not drawing."; + return; + } + /*if(mesh.haveVertsChanged() || mesh.haveTexCoordsChanged()){ calculate4dTextureCoords(); }*/ @@ -75,9 +80,9 @@ void QuadSurface::draw() { glTexCoordPointer(4, GL_FLOAT, 0, quadTexCoordinates); glVertexPointer(3, GL_FLOAT, 0, quadVertices); - texture->bind(); + source->getTexture()->bind(); glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, quadIndices); - texture->unbind(); + source->getTexture()->unbind(); } void QuadSurface::setVertex(int index, ofVec2f p) { @@ -154,7 +159,7 @@ ofPolyline QuadSurface::getHitArea() { ofPolyline QuadSurface::getTextureHitArea() { ofPolyline line; vector& texCoords = mesh.getTexCoords(); - ofVec2f textureSize = ofVec2f(texture->getWidth(), texture->getHeight()); + ofVec2f textureSize = ofVec2f(source->getTexture()->getWidth(), source->getTexture()->getHeight()); for (int i = 0; i < texCoords.size(); i++) { line.addVertex(ofPoint(texCoords[i] * textureSize)); } diff --git a/src/QuadSurface.h b/src/Surfaces/QuadSurface.h similarity index 87% rename from src/QuadSurface.h rename to src/Surfaces/QuadSurface.h index 223e367..6422a6f 100755 --- a/src/QuadSurface.h +++ b/src/Surfaces/QuadSurface.h @@ -14,7 +14,7 @@ class QuadSurface : public BaseSurface { void setup(); void setup(ofVec2f p1, ofVec2f p2, ofVec2f p3, ofVec2f p4, ofVec2f t1, - ofVec2f t2, ofVec2f t3, ofVec2f t4, ofTexture* texturePtr); + ofVec2f t2, ofVec2f t3, ofVec2f t4, BaseSource* newSource); void draw(); void setVertex(int index, ofVec2f p); diff --git a/src/TriangleSurface.cpp b/src/Surfaces/TriangleSurface.cpp similarity index 87% rename from src/TriangleSurface.cpp rename to src/Surfaces/TriangleSurface.cpp index 12da4c0..f370080 100644 --- a/src/TriangleSurface.cpp +++ b/src/Surfaces/TriangleSurface.cpp @@ -19,13 +19,13 @@ void TriangleSurface::setup() { ofVec2f t2 = ofVec2f(0, 1.0f); ofVec2f t3 = ofVec2f(1, 1.0f); - setup(p1, p2, p3, t1, t2, t3, texture); + setup(p1, p2, p3, t1, t2, t3, source); } void TriangleSurface::setup(ofVec2f p1, ofVec2f p2, ofVec2f p3, ofVec2f t1, - ofVec2f t2, ofVec2f t3, ofTexture* texturePtr) { + ofVec2f t2, ofVec2f t3, BaseSource* newSource) { // Assign texture - texture = texturePtr; + source = newSource; // Clear mesh mesh.clear(); @@ -42,9 +42,14 @@ void TriangleSurface::setup(ofVec2f p1, ofVec2f p2, ofVec2f p3, ofVec2f t1, } void TriangleSurface::draw() { - texture->bind(); + if (source->getTexture() == NULL) { + ofLogWarning("TriangleSurface") << "Source texture is empty. Not drawing."; + return; + } + + source->getTexture()->bind(); mesh.draw(); - texture->unbind(); + source->getTexture()->unbind(); } void TriangleSurface::setVertex(int index, ofVec2f p) { @@ -117,7 +122,7 @@ ofPolyline TriangleSurface::getHitArea() { ofPolyline TriangleSurface::getTextureHitArea() { ofPolyline line; vector& texCoords = mesh.getTexCoords(); - ofVec2f textureSize = ofVec2f(texture->getWidth(), texture->getHeight()); + ofVec2f textureSize = ofVec2f(source->getTexture()->getWidth(), source->getTexture()->getHeight()); for (int i = 0; i < texCoords.size(); i++) { line.addVertex(ofPoint(texCoords[i] * textureSize)); } diff --git a/src/TriangleSurface.h b/src/Surfaces/TriangleSurface.h similarity index 93% rename from src/TriangleSurface.h rename to src/Surfaces/TriangleSurface.h index c3e968c..073719b 100644 --- a/src/TriangleSurface.h +++ b/src/Surfaces/TriangleSurface.h @@ -13,7 +13,7 @@ class TriangleSurface : public BaseSurface { void setup(); void setup(ofVec2f p1, ofVec2f p2, ofVec2f p3, ofVec2f t1, ofVec2f t2, - ofVec2f t3, ofTexture* texturePtr); + ofVec2f t3, BaseSource* newSource); void draw(); void setVertex(int index, ofVec2f p); void setTexCoord(int index, ofVec2f t); diff --git a/src/TextureEditor.cpp b/src/TextureEditor.cpp index f86d464..f7be105 100755 --- a/src/TextureEditor.cpp +++ b/src/TextureEditor.cpp @@ -45,8 +45,8 @@ void TextureEditor::update(ofEventArgs& args) { if (surface == NULL) return; // update surface if one of the joints is being dragged - ofVec2f textureSize = ofVec2f(surface->getTexture()->getWidth(), - surface->getTexture()->getHeight()); + ofVec2f textureSize = ofVec2f(surface->getSource()->getTexture()->getWidth(), + surface->getSource()->getTexture()->getHeight()); // Get selected joint index int selectedJointIndex = 0; @@ -138,8 +138,8 @@ void TextureEditor::createJoints() { if (surface == NULL) return; clearJoints(); vector& texCoords = surface->getTexCoords(); - ofVec2f textureSize = ofVec2f(surface->getTexture()->getWidth(), - surface->getTexture()->getHeight()); + ofVec2f textureSize = ofVec2f(surface->getSource()->getTexture()->getWidth(), + surface->getSource()->getTexture()->getHeight()); for (int i = 0; i < texCoords.size(); i++) { joints.push_back(new CircleJoint()); @@ -163,8 +163,8 @@ void TextureEditor::unselectAllJoints() { void TextureEditor::moveTexCoords(ofVec2f by) { if (surface == NULL) return; vector& texCoords = surface->getTexCoords(); - ofVec2f textureSize = ofVec2f(surface->getTexture()->getWidth(), - surface->getTexture()->getHeight()); + ofVec2f textureSize = ofVec2f(surface->getSource()->getTexture()->getWidth(), + surface->getSource()->getTexture()->getHeight()); for (int i = 0; i < texCoords.size(); i++) { joints[i]->position += by; texCoords[i] = joints[i]->position / textureSize;