67 changed files with 3975 additions and 2500 deletions
@ -0,0 +1,76 @@ |
|||
# All variables and this file are optional, if they are not present the PG and the
|
|||
# makefiles will try to parse the correct values from the file system.
|
|||
#
|
|||
# Variables that specify exclusions can use % as a wildcard to specify that anything in
|
|||
# that position will match. A partial path can also be specified to, for example, exclude
|
|||
# a whole folder from the parsed paths from the file system
|
|||
#
|
|||
# Variables can be specified using = or +=
|
|||
# = will clear the contents of that variable both specified from the file or the ones parsed
|
|||
# from the file system
|
|||
# += will add the values to the previous ones in the file or the ones parsed from the file
|
|||
# system
|
|||
#
|
|||
# The PG can be used to detect errors in this file, just create a new project with this addon
|
|||
# and the PG will write to the console the kind of error and in which line it is
|
|||
|
|||
meta: |
|||
ADDON_NAME = ofxPiMapper |
|||
ADDON_DESCRIPTION = Projection Mapping Addon optimized for the Raspberry Pi |
|||
ADDON_AUTHOR = kr15h aspeteRakete |
|||
ADDON_TAGS = "Raspberry Pi" "Projection Mapping" |
|||
ADDON_URL = http://github.com/kr15h/ofxPiMapper |
|||
|
|||
common: |
|||
# dependencies with other addons, a list of them separated by spaces
|
|||
# or use += in several lines
|
|||
ADDON_DEPENDENCIES = ofxIO ofxXmlSettings ofxGui |
|||
|
|||
# include search paths, this will be usually parsed from the file system
|
|||
# but if the addon or addon libraries need special search paths they can be
|
|||
# specified here separated by spaces or one per line using +=
|
|||
# ADDON_INCLUDES =
|
|||
|
|||
# any special flag that should be passed to the compiler when using this
|
|||
# addon
|
|||
# ADDON_CFLAGS =
|
|||
|
|||
# any special flag that should be passed to the linker when using this
|
|||
# addon, also used for system libraries with -lname
|
|||
# ADDON_LDFLAGS =
|
|||
|
|||
# linux only, any library that should be included in the project using
|
|||
# pkg-config
|
|||
# ADDON_PKG_CONFIG_LIBRARIES =
|
|||
|
|||
# osx/iOS only, any framework that should be included in the project
|
|||
# ADDON_FRAMEWORKS =
|
|||
|
|||
# source files, these will be usually parsed from the file system looking
|
|||
# in the src folders in libs and the root of the addon. if your addon needs
|
|||
# to include files in different places or a different set of files per platform
|
|||
# they can be specified here
|
|||
# ADDON_SOURCES =
|
|||
|
|||
# some addons need resources to be copied to the bin/data folder of the project
|
|||
# specify here any files that need to be copied, you can use wildcards like * and ?
|
|||
# ADDON_DATA =
|
|||
|
|||
# when parsing the file system looking for libraries exclude this for all or
|
|||
# a specific platform
|
|||
# ADDON_LIBS_EXCLUDE =
|
|||
|
|||
linux64: |
|||
# binary libraries, these will be usually parsed from the file system but some
|
|||
# libraries need to passed to the linker in a specific order
|
|||
ADDON_LIBS = |
|||
linux: |
|||
ADDON_LIBS = |
|||
win_cb: |
|||
ADDON_LIBS = |
|||
linuxarmv6l: |
|||
ADDON_LIBS = |
|||
linuxarmv7l: |
|||
ADDON_LIBS = |
|||
android/armeabi: |
|||
ADDON_LIBS = |
@ -1,3 +1,5 @@ |
|||
ofxPiMapper |
|||
ofxUI |
|||
ofxIO |
|||
ofxXmlSettings |
|||
ofxGui |
|||
ofxOMXPlayer |
|||
|
Binary file not shown.
@ -1,164 +1,190 @@ |
|||
#include "ofApp.h" |
|||
|
|||
void ofApp::setup() |
|||
{ |
|||
bShowInfo = false; |
|||
|
|||
// check if the surfaces.xml file is there
|
|||
// if not - load defaultSurfaces.xml
|
|||
if ( ofFile::doesFileExist("surfaces.xml") ) { |
|||
surfaceManager.loadXmlSettings("surfaces.xml"); |
|||
} else { |
|||
surfaceManager.loadXmlSettings("defaultSurfaces.xml"); |
|||
} |
|||
|
|||
// Pass the surface manager to the mapper graphical user interface
|
|||
gui.setSurfaceManager( &surfaceManager ); |
|||
|
|||
// Create FBO
|
|||
fbo = new ofFbo(); |
|||
fbo->allocate( 500, 500 ); |
|||
setFboAsTexture(); |
|||
|
|||
// Genereate rects
|
|||
int numRects = 20; // change this to add more or less rects
|
|||
for ( int i=0; i<numRects; i++ ) { |
|||
rects.push_back( ofRectangle(0, ofRandom(fbo->getHeight()), fbo->getWidth(), ofRandom(20)) ); |
|||
rectSpeeds.push_back( (1.0f + ofRandom(5)) ); |
|||
} |
|||
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
|
|||
if (ofFile::doesFileExist("surfaces.xml")) { |
|||
surfaceManager.loadXmlSettings("surfaces.xml"); |
|||
} else { |
|||
surfaceManager.loadXmlSettings("defaultSurfaces.xml"); |
|||
} |
|||
|
|||
// Pass the surface manager to the mapper graphical user interface
|
|||
gui.setSurfaceManager(&surfaceManager); |
|||
|
|||
// Create FBO
|
|||
fbo = new ofFbo(); |
|||
fbo->allocate(500, 500); |
|||
fboSource = new ofx::piMapper::BaseSource(&fbo->getTextureReference()); |
|||
setFboAsSource(); |
|||
|
|||
// Genereate rects
|
|||
int numRects = 20; // change this to add more or less rects
|
|||
for (int i = 0; i < numRects; i++) { |
|||
rects.push_back(ofRectangle(0, ofRandom(fbo->getHeight()), fbo->getWidth(), |
|||
ofRandom(20))); |
|||
rectSpeeds.push_back((1.0f + ofRandom(5))); |
|||
} |
|||
} |
|||
|
|||
void ofApp::update() |
|||
{ |
|||
// Move rects
|
|||
for ( int i=0; i<rects.size(); i++ ) { |
|||
rects[i].y += rectSpeeds[i]; |
|||
if ( rects[i].y > fbo->getHeight() ) { |
|||
rects[i].y = -rects[i].getHeight(); |
|||
} |
|||
} |
|||
|
|||
// Fill FBO
|
|||
fbo->begin(); |
|||
ofClear(0); |
|||
ofBackground(0); |
|||
ofSetColor(255); |
|||
for ( int i=0; i<rects.size(); i++ ) { |
|||
ofRect( rects[i] ); |
|||
void ofApp::update() { |
|||
// Move rects
|
|||
for (int i = 0; i < rects.size(); i++) { |
|||
rects[i].y += rectSpeeds[i]; |
|||
if (rects[i].y > fbo->getHeight()) { |
|||
rects[i].y = -rects[i].getHeight(); |
|||
} |
|||
fbo->end(); |
|||
} |
|||
|
|||
// Fill FBO
|
|||
fbo->begin(); |
|||
ofClear(0); |
|||
ofBackground(0); |
|||
ofSetColor(255); |
|||
for (int i = 0; i < rects.size(); i++) { |
|||
ofRect(rects[i]); |
|||
} |
|||
fbo->end(); |
|||
} |
|||
|
|||
void ofApp::draw() |
|||
{ |
|||
// Draw the piMapper GUI
|
|||
gui.draw(); |
|||
|
|||
if ( bShowInfo ) { |
|||
// Draw instructions
|
|||
stringstream ss; |
|||
ss << "There are 4 modes:\n\n"; |
|||
ss << " 1. Presentation mode\n"; |
|||
ss << " 2. Texture mapping mode\n"; |
|||
ss << " 3. Projection mapping mode\n"; |
|||
ss << " 4. Source selection mode\n\n"; |
|||
ss << "You can switch between the modes by using <1>, <2>, <3> and <4> keys on the keyboard.\n\n"; |
|||
ss << "Press <r> or <n> to add random or normal surface.\n"; |
|||
ss << "Press <q> to add a new quad surface.\n"; |
|||
ss << "Press <s> to save the composition.\n"; |
|||
ss << "Press <f> to toggle fullscreen.\n"; |
|||
ss << "Press <a> to reassign the fbo texture to the first surface\n"; |
|||
ss << "Hit <i> to hide this message."; |
|||
|
|||
ofDrawBitmapStringHighlight(ss.str(), 10, 20, ofColor(0,0,0,100), ofColor(255,255,255,200)); |
|||
} |
|||
void ofApp::draw() { |
|||
// Draw the piMapper GUI
|
|||
gui.draw(); |
|||
|
|||
if (bShowInfo) { |
|||
// Draw instructions
|
|||
stringstream ss; |
|||
ss << "There are 4 modes:\n\n"; |
|||
ss << " 1. Presentation mode\n"; |
|||
ss << " 2. Texture mapping mode\n"; |
|||
ss << " 3. Projection mapping mode\n"; |
|||
ss << " 4. Source selection mode\n\n"; |
|||
ss << "You can switch between the modes by using <1>, <2>, <3> and <4> " |
|||
"keys on the keyboard.\n\n"; |
|||
ss << "Press <r> or <n> to add random or normal surface.\n"; |
|||
ss << "Press <q> to add a new quad surface.\n"; |
|||
ss << "Press <s> to save the composition.\n"; |
|||
ss << "Press <f> to toggle fullscreen.\n"; |
|||
ss << "Press <a> to reassign the fbo texture to the first surface\n"; |
|||
ss << "Hit <i> to hide this message."; |
|||
|
|||
ofDrawBitmapStringHighlight(ss.str(), 10, 20, ofColor(0, 0, 0, 100), |
|||
ofColor(255, 255, 255, 200)); |
|||
} |
|||
} |
|||
|
|||
void ofApp::exit() |
|||
{ |
|||
// Clear FBO from mem
|
|||
delete fbo; |
|||
void ofApp::exit() { |
|||
// Clear FBO from mem
|
|||
delete fbo; |
|||
} |
|||
|
|||
void ofApp::keyPressed(int key) |
|||
{ |
|||
cout << "Key pressed: " << static_cast<char>(key) << endl; |
|||
|
|||
switch (key) { |
|||
case '1': gui.setMode(ofxGuiMode::NONE); break; |
|||
case '2': gui.setMode(ofxGuiMode::TEXTURE_MAPPING); break; |
|||
case '3': gui.setMode(ofxGuiMode::PROJECTION_MAPPING); break; |
|||
case '4': gui.setMode(ofxGuiMode::SOURCE_SELECTION); break; |
|||
case 'i': bShowInfo = !bShowInfo; break; |
|||
case 'r': addRandomSurface(); break; |
|||
case 'q': addQuadSurface(); break; |
|||
case 'n': addSurface(); break; |
|||
case 'f': ofToggleFullscreen(); break; |
|||
case 's': surfaceManager.saveXmlSettings("surfaces.xml"); break; |
|||
case 'a': setFboAsTexture(); break; |
|||
case OF_KEY_BACKSPACE: surfaceManager.removeSelectedSurface(); break; |
|||
default: break; |
|||
} |
|||
void ofApp::keyPressed(int key) { |
|||
cout << "Key pressed: " << static_cast<char>(key) << endl; |
|||
|
|||
switch (key) { |
|||
case '1': |
|||
gui.setMode(ofx::piMapper::GuiMode::NONE); |
|||
break; |
|||
case '2': |
|||
gui.setMode(ofx::piMapper::GuiMode::TEXTURE_MAPPING); |
|||
break; |
|||
case '3': |
|||
gui.setMode(ofx::piMapper::GuiMode::PROJECTION_MAPPING); |
|||
break; |
|||
case '4': |
|||
gui.setMode(ofx::piMapper::GuiMode::SOURCE_SELECTION); |
|||
break; |
|||
case 'i': |
|||
bShowInfo = !bShowInfo; |
|||
break; |
|||
case 'r': |
|||
addRandomSurface(); |
|||
break; |
|||
case 'q': |
|||
addQuadSurface(); |
|||
break; |
|||
case 'n': |
|||
addSurface(); |
|||
break; |
|||
case 'f': |
|||
ofToggleFullscreen(); |
|||
break; |
|||
case 's': |
|||
surfaceManager.saveXmlSettings("surfaces.xml"); |
|||
break; |
|||
case 'a': |
|||
setFboAsSource(); |
|||
break; |
|||
case OF_KEY_BACKSPACE: |
|||
surfaceManager.removeSelectedSurface(); |
|||
break; |
|||
default: |
|||
break; |
|||
} |
|||
} |
|||
|
|||
void ofApp::addRandomSurface() |
|||
{ |
|||
int surfaceType = ofxSurfaceType::TRIANGLE_SURFACE; |
|||
vector<ofVec2f> vertices; |
|||
vertices.push_back( ofVec2f( ofRandomWidth(), ofRandomHeight() ) ); |
|||
vertices.push_back( ofVec2f( ofRandomWidth(), ofRandomHeight() ) ); |
|||
vertices.push_back( ofVec2f( ofRandomWidth(), ofRandomHeight() ) ); |
|||
vector<ofVec2f> texCoords; |
|||
texCoords.push_back( ofVec2f( ofRandomuf(), ofRandomuf() ) ); |
|||
texCoords.push_back( ofVec2f( ofRandomuf(), ofRandomuf() ) ); |
|||
texCoords.push_back( ofVec2f( ofRandomuf(), ofRandomuf() ) ); |
|||
surfaceManager.addSurface(surfaceType, vertices, texCoords); |
|||
|
|||
// select this surface right away
|
|||
surfaceManager.selectSurface(surfaceManager.size()-1); |
|||
void ofApp::addRandomSurface() { |
|||
int surfaceType = ofx::piMapper::SurfaceType::TRIANGLE_SURFACE; |
|||
vector<ofVec2f> vertices; |
|||
vertices.push_back(ofVec2f(ofRandomWidth(), ofRandomHeight())); |
|||
vertices.push_back(ofVec2f(ofRandomWidth(), ofRandomHeight())); |
|||
vertices.push_back(ofVec2f(ofRandomWidth(), ofRandomHeight())); |
|||
vector<ofVec2f> texCoords; |
|||
texCoords.push_back(ofVec2f(ofRandomuf(), ofRandomuf())); |
|||
texCoords.push_back(ofVec2f(ofRandomuf(), ofRandomuf())); |
|||
texCoords.push_back(ofVec2f(ofRandomuf(), ofRandomuf())); |
|||
surfaceManager.addSurface(surfaceType, vertices, texCoords); |
|||
|
|||
// select this surface right away
|
|||
surfaceManager.selectSurface(surfaceManager.size() - 1); |
|||
} |
|||
|
|||
void ofApp::addQuadSurface() |
|||
{ |
|||
int surfaceType = ofxSurfaceType::QUAD_SURFACE; |
|||
vector<ofVec2f> vertices; |
|||
|
|||
int border = 50; |
|||
vertices.push_back( ofVec2f(border, border) ); |
|||
vertices.push_back( ofVec2f(border, ofGetHeight() - border) ); |
|||
vertices.push_back( ofVec2f(ofGetWidth() - border, ofGetHeight() - border) ); |
|||
vertices.push_back( ofVec2f(ofGetWidth() - border, border) ); |
|||
|
|||
vector<ofVec2f> texCoords; |
|||
texCoords.push_back( ofVec2f(ofVec2f(0.0f, 0.0f)) ); |
|||
texCoords.push_back( ofVec2f(ofVec2f(1.0f, 0.0f)) ); |
|||
texCoords.push_back( ofVec2f(ofVec2f(1.0f, 1.0f)) ); |
|||
texCoords.push_back( ofVec2f(ofVec2f(0.0f, 1.0f)) ); |
|||
|
|||
surfaceManager.addSurface(surfaceType, vertices, texCoords); |
|||
|
|||
// select this surface right away
|
|||
surfaceManager.selectSurface(surfaceManager.size()-1); |
|||
void ofApp::addQuadSurface() { |
|||
int surfaceType = ofx::piMapper::SurfaceType::QUAD_SURFACE; |
|||
vector<ofVec2f> vertices; |
|||
|
|||
int border = 50; |
|||
vertices.push_back(ofVec2f(border, border)); |
|||
vertices.push_back(ofVec2f(ofGetWidth() - border, border)); |
|||
vertices.push_back(ofVec2f(ofGetWidth() - border, ofGetHeight() - border)); |
|||
vertices.push_back(ofVec2f(border, ofGetHeight() - border)); |
|||
|
|||
vector<ofVec2f> texCoords; |
|||
texCoords.push_back(ofVec2f(ofVec2f(0.0f, 0.0f))); |
|||
texCoords.push_back(ofVec2f(ofVec2f(1.0f, 0.0f))); |
|||
texCoords.push_back(ofVec2f(ofVec2f(1.0f, 1.0f))); |
|||
texCoords.push_back(ofVec2f(ofVec2f(0.0f, 1.0f))); |
|||
|
|||
surfaceManager.addSurface(surfaceType, vertices, texCoords); |
|||
|
|||
// select this surface right away
|
|||
surfaceManager.selectSurface(surfaceManager.size() - 1); |
|||
} |
|||
|
|||
void ofApp::addSurface() |
|||
{ |
|||
int surfaceType = ofxSurfaceType::TRIANGLE_SURFACE; |
|||
vector<ofVec2f> vertices; |
|||
vertices.push_back( ofVec2f( (float)ofGetWidth()/2.0f, 0.0f ) ); |
|||
vertices.push_back( ofVec2f( (float)ofGetWidth(), (float)ofGetHeight() ) ); |
|||
vertices.push_back( ofVec2f( 0.0f, (float)ofGetHeight() ) ); |
|||
vector<ofVec2f> texCoords; |
|||
texCoords.push_back( ofVec2f( 0.5f, 0.0f ) ); |
|||
texCoords.push_back( ofVec2f( 1.0f, 1.0f ) ); |
|||
texCoords.push_back( ofVec2f( 0.0f, 1.0f ) ); |
|||
surfaceManager.addSurface(surfaceType, vertices, texCoords); |
|||
|
|||
// select this surface right away
|
|||
surfaceManager.selectSurface(surfaceManager.size()-1); |
|||
void ofApp::addSurface() { |
|||
int surfaceType = ofx::piMapper::SurfaceType::TRIANGLE_SURFACE; |
|||
vector<ofVec2f> vertices; |
|||
vertices.push_back(ofVec2f((float)ofGetWidth() / 2.0f, 0.0f)); |
|||
vertices.push_back(ofVec2f((float)ofGetWidth(), (float)ofGetHeight())); |
|||
vertices.push_back(ofVec2f(0.0f, (float)ofGetHeight())); |
|||
vector<ofVec2f> texCoords; |
|||
texCoords.push_back(ofVec2f(0.5f, 0.0f)); |
|||
texCoords.push_back(ofVec2f(1.0f, 1.0f)); |
|||
texCoords.push_back(ofVec2f(0.0f, 1.0f)); |
|||
surfaceManager.addSurface(surfaceType, vertices, texCoords); |
|||
|
|||
// select this surface right away
|
|||
surfaceManager.selectSurface(surfaceManager.size() - 1); |
|||
} |
|||
|
|||
void ofApp::setFboAsTexture() |
|||
{ |
|||
surfaceManager.getSurface(0)->setTexture( &fbo->getTextureReference() ); |
|||
void ofApp::setFboAsSource() { |
|||
surfaceManager.getSurface(0)->setSource(fboSource); |
|||
} |
@ -1,31 +1,30 @@ |
|||
#ifndef H_OF_APP |
|||
#define H_OF_APP |
|||
#pragma once |
|||
|
|||
#include "ofMain.h" |
|||
#include "ofxPiMapper.h" |
|||
#include "BaseSource.h" |
|||
|
|||
class ofApp : public ofBaseApp |
|||
{ |
|||
public: |
|||
void setup(); |
|||
void update(); |
|||
void draw(); |
|||
void exit(); |
|||
class ofApp : public ofBaseApp { |
|||
public: |
|||
void setup(); |
|||
void update(); |
|||
void draw(); |
|||
void exit(); |
|||
|
|||
void keyPressed(int key); |
|||
|
|||
void addRandomSurface(); |
|||
void addQuadSurface(); |
|||
void addSurface(); |
|||
void setFboAsTexture(); |
|||
|
|||
ofImage image; |
|||
ofxSurfaceManager surfaceManager; |
|||
ofxSurfaceManagerGui gui; |
|||
bool bShowInfo; |
|||
ofFbo* fbo; |
|||
vector<ofRectangle> rects; |
|||
vector<float> rectSpeeds; |
|||
}; |
|||
void keyPressed(int key); |
|||
|
|||
#endif |
|||
void addRandomSurface(); |
|||
void addQuadSurface(); |
|||
void addSurface(); |
|||
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<ofRectangle> rects; |
|||
vector<float> rectSpeeds; |
|||
}; |
After Width: | Height: | Size: 41 KiB |
@ -0,0 +1,46 @@ |
|||
//
|
|||
// DirectoryWatcher.cpp
|
|||
// example
|
|||
//
|
|||
// Created by felix on 23.09.14.
|
|||
//
|
|||
//
|
|||
|
|||
#include "DirectoryWatcher.h" |
|||
|
|||
namespace ofx { |
|||
namespace piMapper { |
|||
DirectoryWatcher::DirectoryWatcher(std::string path, int watcherMediaType) { |
|||
mediaType = watcherMediaType; |
|||
// Decide what filter we need depending on media type
|
|||
if (mediaType == SourceType::SOURCE_TYPE_VIDEO) { |
|||
filter = new VideoPathFilter(); |
|||
} else if (mediaType == SourceType::SOURCE_TYPE_IMAGE) { |
|||
filter = new ImagePathFilter(); |
|||
} else { |
|||
ofLogFatalError("DirectoryWatcher::DirectoryWatcher", "Unkonwn media type"); |
|||
std::exit(EXIT_FAILURE); |
|||
} |
|||
dirWatcher.registerAllEvents(this); |
|||
// For some reason the filters are not working,
|
|||
// we leave just the path here and do the filter logic in the listeners
|
|||
dirWatcher.addPath(path); |
|||
// Initial directory listing. Fill the file paths vector.
|
|||
IO::DirectoryUtils::list(path, filePaths, true, filter); |
|||
} |
|||
|
|||
DirectoryWatcher::~DirectoryWatcher() { |
|||
delete filter; |
|||
filter = NULL; |
|||
} |
|||
|
|||
std::vector<std::string>& DirectoryWatcher::getFilePaths() { |
|||
return filePaths; |
|||
} |
|||
|
|||
int DirectoryWatcher::getMediaType() { |
|||
return mediaType; |
|||
} |
|||
|
|||
} // namespace piMapper
|
|||
} // namespace ofx
|
@ -0,0 +1,144 @@ |
|||
//
|
|||
// DirectoryWatcher.h
|
|||
// example
|
|||
//
|
|||
// Created by felix on 23.09.14.
|
|||
//
|
|||
//
|
|||
|
|||
#pragma once |
|||
|
|||
#include "ofMain.h" |
|||
#include "ofxIO.h" |
|||
#include "SourceType.h" |
|||
|
|||
namespace ofx { |
|||
namespace piMapper { |
|||
|
|||
class BasePathFilter : public ofx::IO::AbstractPathFilter { |
|||
public: |
|||
BasePathFilter() {}; |
|||
virtual ~BasePathFilter() {}; |
|||
virtual bool accept(const Poco::Path& path) const {}; |
|||
}; |
|||
|
|||
class VideoPathFilter : public BasePathFilter { |
|||
public: |
|||
VideoPathFilter() {}; |
|||
virtual ~VideoPathFilter() {}; |
|||
|
|||
bool accept(const Poco::Path& path) const { |
|||
return !Poco::File(path).isHidden() && |
|||
(ofIsStringInString(path.toString(), ".mp4") || |
|||
ofIsStringInString(path.toString(), ".h264")|| |
|||
ofIsStringInString(path.toString(), ".mov") || |
|||
ofIsStringInString(path.toString(), ".avi") || |
|||
ofIsStringInString(path.toString(), ".mpeg")); |
|||
} |
|||
}; |
|||
|
|||
class ImagePathFilter : public BasePathFilter { |
|||
public: |
|||
ImagePathFilter() {}; |
|||
virtual ~ImagePathFilter() {}; |
|||
|
|||
bool accept(const Poco::Path& path) const { |
|||
return !Poco::File(path).isHidden() && |
|||
(ofIsStringInString(path.toString(), ".png") || |
|||
ofIsStringInString(path.toString(), ".jpg") || |
|||
ofIsStringInString(path.toString(), ".jpeg")); |
|||
} |
|||
}; |
|||
|
|||
class DirectoryWatcher { |
|||
public: |
|||
DirectoryWatcher(std::string path, int watcherMediaType); |
|||
~DirectoryWatcher(); |
|||
|
|||
// TODO make useful stuff with onDirectoryWatcher*
|
|||
void onDirectoryWatcherItemAdded( |
|||
const ofx::IO::DirectoryWatcherManager::DirectoryEvent& evt) { |
|||
string path = evt.item.path(); |
|||
Poco::Path pocoPath = Poco::Path(path); |
|||
if (!filter->accept(pocoPath)) { |
|||
return; |
|||
} |
|||
filePaths.push_back(path); |
|||
ofNotifyEvent(onItemAdded, path, this); |
|||
} |
|||
|
|||
void onDirectoryWatcherItemRemoved( |
|||
const ofx::IO::DirectoryWatcherManager::DirectoryEvent& evt) { |
|||
string path = evt.item.path(); |
|||
Poco::Path pocoPath = Poco::Path(path); |
|||
if (!filter->accept(pocoPath)) { |
|||
return; |
|||
} |
|||
// Remove path from vector
|
|||
for (int i = 0; i < filePaths.size(); i++) { |
|||
if (path == filePaths[i]) { |
|||
filePaths.erase(filePaths.begin() + i); |
|||
break; |
|||
} |
|||
} |
|||
ofNotifyEvent(onItemRemoved, path, this); |
|||
} |
|||
|
|||
void onDirectoryWatcherItemModified( |
|||
const ofx::IO::DirectoryWatcherManager::DirectoryEvent& evt) { |
|||
string path = evt.item.path(); |
|||
Poco::Path pocoPath = Poco::Path(path); |
|||
if (!filter->accept(pocoPath)) { |
|||
return; |
|||
} |
|||
ofNotifyEvent(onItemModified, path, this); |
|||
} |
|||
|
|||
void onDirectoryWatcherItemMovedFrom( |
|||
const ofx::IO::DirectoryWatcherManager::DirectoryEvent& evt) { |
|||
string path = evt.item.path(); |
|||
Poco::Path pocoPath = Poco::Path(path); |
|||
if (!filter->accept(pocoPath)) { |
|||
return; |
|||
} |
|||
ofLogNotice("ofApp::onDirectoryWatcherItemMovedFrom") |
|||
<< "Moved From: " << path; |
|||
ofNotifyEvent(onItemMovedFrom, path, this); |
|||
} |
|||
|
|||
void onDirectoryWatcherItemMovedTo( |
|||
const ofx::IO::DirectoryWatcherManager::DirectoryEvent& evt) { |
|||
string path = evt.item.path(); |
|||
Poco::Path pocoPath = Poco::Path(path); |
|||
if (!filter->accept(pocoPath)) { |
|||
return; |
|||
} |
|||
ofLogNotice("ofApp::onDirectoryWatcherItemMovedTo") |
|||
<< "Moved To: " << path; |
|||
ofNotifyEvent(onItemMovedTo, path, this); |
|||
} |
|||
|
|||
void onDirectoryWatcherError(const Poco::Exception& exc) { |
|||
ofLogError("ofApp::onDirectoryWatcherError") |
|||
<< "Error: " << exc.displayText(); |
|||
} |
|||
|
|||
// Getters
|
|||
std::vector<std::string>& getFilePaths(); |
|||
int getMediaType(); |
|||
|
|||
// Custom events
|
|||
ofEvent<string> onItemAdded; |
|||
ofEvent<string> onItemRemoved; |
|||
ofEvent<string> onItemModified; |
|||
ofEvent<string> onItemMovedFrom; |
|||
ofEvent<string> onItemMovedTo; |
|||
|
|||
private: |
|||
ofx::IO::DirectoryWatcherManager dirWatcher; |
|||
BasePathFilter* filter; |
|||
std::vector<std::string> filePaths; |
|||
int mediaType; |
|||
}; |
|||
} |
|||
} |
@ -0,0 +1,300 @@ |
|||
//
|
|||
// MediaServer.cpp
|
|||
// example
|
|||
//
|
|||
// Created by felix on 13.09.14.
|
|||
//
|
|||
//
|
|||
|
|||
#include "MediaServer.h" |
|||
|
|||
namespace ofx { |
|||
namespace piMapper { |
|||
|
|||
MediaServer::MediaServer(): |
|||
videoWatcher(ofToDataPath(DEFAULT_VIDEOS_DIR, true), SourceType::SOURCE_TYPE_VIDEO), |
|||
imageWatcher(ofToDataPath(DEFAULT_IMAGES_DIR, true), SourceType::SOURCE_TYPE_IMAGE) { |
|||
addWatcherListeners(); |
|||
} |
|||
|
|||
MediaServer::~MediaServer() { |
|||
removeWatcherListeners(); |
|||
}; |
|||
|
|||
int MediaServer::getNumImages() { return imageWatcher.getFilePaths().size(); } |
|||
int MediaServer::getNumVideos() { return videoWatcher.getFilePaths().size(); } |
|||
|
|||
std::vector<std::string>& MediaServer::getImagePaths() { |
|||
return imageWatcher.getFilePaths(); |
|||
} |
|||
|
|||
std::vector<std::string> MediaServer::getImageNames() { |
|||
std::vector<std::string> imageNames; |
|||
for (int i = 0; i < getNumImages(); i++) { |
|||
// Split image path
|
|||
std::vector<std::string> pathParts = ofSplitString(getImagePaths()[i], "/"); |
|||
// And get only the last piece
|
|||
std::string name = pathParts[pathParts.size()-1]; |
|||
imageNames.push_back(name); |
|||
} |
|||
return imageNames; |
|||
} |
|||
|
|||
std::vector<std::string>& MediaServer::getVideoPaths() { |
|||
return videoWatcher.getFilePaths(); |
|||
} |
|||
|
|||
std::vector<std::string> MediaServer::getVideoNames() { |
|||
std::vector<std::string> videoNames; |
|||
for (int i = 0; i < getNumVideos(); i++) { |
|||
// Split video path
|
|||
std::vector<std::string> pathParts = ofSplitString(getVideoPaths()[i], "/"); |
|||
// And get only the last piece
|
|||
std::string name = pathParts[pathParts.size()-1]; |
|||
videoNames.push_back(name); |
|||
} |
|||
return videoNames; |
|||
} |
|||
|
|||
|
|||
|
|||
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; |
|||
if (loadedSources.count(path)) { |
|||
imageSource = static_cast<ImageSource*>(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); |
|||
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<ImageSource*>(getSourceByPath(path)); |
|||
ofLogNotice("MediaServer") << "Unload image, current reference count: " << source->referenceCount; |
|||
source->referenceCount--; |
|||
// Unload only if reference count is less or equal to 0
|
|||
ofLogNotice("MediaServer") << "New reference count: " << source->referenceCount; |
|||
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)) { |
|||
ofLogNotice("MediaServer") << "Source count BEFORE image removal: " << loadedSources.size() << endl; |
|||
loadedSources[path]->clear(); |
|||
std::map<std::string, BaseSource*>::iterator it = loadedSources.find(path); |
|||
delete it->second; |
|||
loadedSources.erase(it); |
|||
ofLogNotice("MediaServer") << "Source count AFTER image removal: " << loadedSources.size() << endl; |
|||
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) { |
|||
VideoSource* videoSource = NULL; |
|||
// Check if this video is already loaded
|
|||
bool isVideoLoaded = false; |
|||
if (loadedSources.count(path)) { |
|||
videoSource = static_cast<VideoSource*>(loadedSources[path]); |
|||
isVideoLoaded = true; |
|||
} |
|||
// If is loaded
|
|||
if (isVideoLoaded) { |
|||
// Increase reference count of this source
|
|||
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<VideoSource*>(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
|
|||
ofLogNotice("MediaServer") << "Removing video " << path; |
|||
// Distroy video source
|
|||
if (loadedSources.count(path)) { |
|||
ofLogNotice("MediaServer") << "Source count before video removal: " << loadedSources.size() << endl; |
|||
videoSource->clear(); |
|||
std::map<std::string, BaseSource*>::iterator it = loadedSources.find(path); |
|||
delete it->second; |
|||
loadedSources.erase(it); |
|||
ofLogNotice("MediaServer") << "Source count after video removal: " << loadedSources.size() << endl; |
|||
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 { |
|||
// 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); |
|||
} |
|||
} |
|||
|
|||
// Clear all loaded media
|
|||
void MediaServer::clear() { |
|||
typedef std::map<std::string, BaseSource*>::iterator it_type; |
|||
for (it_type i = loadedSources.begin(); i != loadedSources.end(); i++) { |
|||
delete i->second; |
|||
} |
|||
loadedSources.clear(); |
|||
} |
|||
|
|||
BaseSource* MediaServer::getSourceByPath(std::string& mediaPath) { |
|||
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); |
|||
} |
|||
} |
|||
|
|||
void MediaServer::handleImageAdded(string& path) { |
|||
ofNotifyEvent(onImageAdded, path, this); |
|||
} |
|||
void MediaServer::handleImageRemoved(string& path) { |
|||
ofNotifyEvent(onImageRemoved, path, this); |
|||
} |
|||
|
|||
void MediaServer::handleVideoAdded(string& path) { |
|||
ofNotifyEvent(onVideoAdded, path, this); |
|||
} |
|||
void MediaServer::handleVideoRemoved(string& path) { |
|||
ofNotifyEvent(onVideoRemoved, path, this); |
|||
} |
|||
|
|||
void MediaServer::addWatcherListeners() { |
|||
ofAddListener(imageWatcher.onItemAdded, this, &MediaServer::handleImageAdded); |
|||
ofAddListener(imageWatcher.onItemRemoved, this, &MediaServer::handleImageRemoved); |
|||
ofAddListener(videoWatcher.onItemAdded, this, &MediaServer::handleVideoAdded); |
|||
ofAddListener(videoWatcher.onItemRemoved, this, &MediaServer::handleVideoRemoved); |
|||
} |
|||
|
|||
void MediaServer::removeWatcherListeners() { |
|||
ofRemoveListener(imageWatcher.onItemAdded, this, &MediaServer::handleImageAdded); |
|||
ofRemoveListener(imageWatcher.onItemRemoved, this, &MediaServer::handleImageRemoved); |
|||
ofRemoveListener(videoWatcher.onItemAdded, this, &MediaServer::handleVideoAdded); |
|||
ofRemoveListener(videoWatcher.onItemRemoved, this, &MediaServer::handleVideoRemoved); |
|||
} |
|||
|
|||
} // namespace piMapper
|
|||
} // namespace ofx
|
@ -0,0 +1,91 @@ |
|||
//
|
|||
// MediaServer.h
|
|||
// example
|
|||
//
|
|||
// Created by felix on 13.09.14.
|
|||
//
|
|||
//
|
|||
|
|||
#pragma once |
|||
|
|||
#include "ofMain.h" |
|||
#include "DirectoryWatcher.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/" |
|||
|
|||
namespace ofx { |
|||
namespace piMapper { |
|||
|
|||
class MediaServer { |
|||
public: |
|||
MediaServer(); |
|||
virtual ~MediaServer(); |
|||
|
|||
int getNumVideos(); |
|||
int getNumImages(); |
|||
std::vector<std::string>& getVideoPaths(); |
|||
std::vector<std::string> getVideoNames(); |
|||
std::vector<std::string>& getImagePaths(); |
|||
std::vector<std::string> getImageNames(); |
|||
|
|||
BaseSource* loadMedia(string& path, int mediaType); |
|||
BaseSource* loadImage(string& path); |
|||
void unloadImage(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<string> onImageAdded; |
|||
ofEvent<string> onImageRemoved; |
|||
ofEvent<string> onVideoAdded; |
|||
ofEvent<string> onVideoRemoved; |
|||
ofEvent<string> onImageLoaded; |
|||
ofEvent<string> onImageUnloaded; |
|||
ofEvent<string> onVideoLoaded; |
|||
ofEvent<string> onVideoUnloaded; |
|||
|
|||
private: |
|||
// Directory Watchers
|
|||
ofx::piMapper::DirectoryWatcher videoWatcher; |
|||
ofx::piMapper::DirectoryWatcher imageWatcher; |
|||
std::map<std::string, BaseSource*> loadedSources; |
|||
// imageWatcher event listeners
|
|||
void handleImageAdded(string& path); |
|||
void handleImageRemoved(string& path); |
|||
// TODO rest of listeners
|
|||
/*
|
|||
void onImageModified(); |
|||
void onImageMovedFrom(); |
|||
void onImageMovedTo(); |
|||
*/ |
|||
|
|||
// videoWatcher event listeners
|
|||
void handleVideoAdded(string& path); |
|||
void handleVideoRemoved(string& path); |
|||
// TODO rest of listeners
|
|||
/*
|
|||
void onVideoModified(); |
|||
void onVideoMovedFrom(); |
|||
void onVideoMovedTo(); |
|||
*/ |
|||
|
|||
// Add/remove event listeners.
|
|||
// Add event listeners to image and video watcher events.
|
|||
void addWatcherListeners(); |
|||
|
|||
// Remove event listeners to image and video watcher events
|
|||
void removeWatcherListeners(); |
|||
}; |
|||
} // namespace piMapper
|
|||
} // namespace ofx
|
@ -0,0 +1,59 @@ |
|||
#include "BaseSource.h" |
|||
|
|||
namespace ofx { |
|||
namespace piMapper { |
|||
BaseSource::BaseSource() { |
|||
//cout << "BaseSource" << endl;
|
|||
init(); |
|||
} |
|||
|
|||
BaseSource::BaseSource(ofTexture* newTexture) { |
|||
init(); |
|||
texture = newTexture; |
|||
} |
|||
|
|||
BaseSource::~BaseSource() {} |
|||
|
|||
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<string> 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]; |
|||
} |
|||
} |
|||
} |
@ -0,0 +1,36 @@ |
|||
#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
|
|||
~BaseSource(); |
|||
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; |
|||
}; |
|||
} |
|||
} |
@ -0,0 +1,39 @@ |
|||
#include "ImageSource.h" |
|||
|
|||
namespace ofx { |
|||
namespace piMapper { |
|||
ImageSource::ImageSource() { |
|||
//cout << "ImageSource" << endl;
|
|||
loadable = true; |
|||
loaded = false; |
|||
type = SourceType::SOURCE_TYPE_IMAGE; |
|||
} |
|||
|
|||
ImageSource::~ImageSource() {} |
|||
|
|||
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)) { |
|||
ofLogWarning("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; |
|||
} |
|||
|
|||
} |
|||
} |
@ -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; |
|||
}; |
|||
} |
|||
} |
@ -0,0 +1,46 @@ |
|||
#pragma once |
|||
|
|||
#include "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); |
|||
} |
|||
} |
|||
}; |
|||
} |
|||
} |
@ -0,0 +1,74 @@ |
|||
#include "VideoSource.h" |
|||
|
|||
namespace ofx { |
|||
namespace piMapper { |
|||
VideoSource::VideoSource() { |
|||
//cout << "VideoSource constr" << endl;
|
|||
loadable = true; |
|||
loaded = false; |
|||
type = SourceType::SOURCE_TYPE_VIDEO; |
|||
#ifdef TARGET_RASPBERRY_PI |
|||
omxPlayer = NULL; |
|||
#else |
|||
videoPlayer = NULL; |
|||
|
|||
#endif |
|||
} |
|||
|
|||
VideoSource::~VideoSource() {} |
|||
|
|||
void VideoSource::loadVideo(std::string& filePath) { |
|||
path = filePath; |
|||
//cout << "loading video: " << filePath << endl;
|
|||
setNameFromPath(filePath); |
|||
#ifdef TARGET_RASPBERRY_PI |
|||
// Do things with the OMX player
|
|||
ofxOMXPlayerSettings settings; |
|||
settings.videoPath = filePath; |
|||
settings.useHDMIForAudio = true; //default true
|
|||
settings.enableTexture = true; //default true
|
|||
settings.enableLooping = true; //default true
|
|||
settings.enableAudio = false; //default true, save resources by disabling
|
|||
//settings.doFlipTexture = true; //default false
|
|||
omxPlayer = new ofxOMXPlayer(); |
|||
omxPlayer->setup(settings); |
|||
texture = &(omxPlayer->getTextureReference()); |
|||
#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() { |
|||
texture = NULL; |
|||
#ifdef TARGET_RASPBERRY_PI |
|||
omxPlayer->close(); |
|||
delete omxPlayer; |
|||
omxPlayer = NULL; |
|||
#else |
|||
ofRemoveListener(ofEvents().update, this, &VideoSource::update); |
|||
videoPlayer->stop(); |
|||
videoPlayer->close(); |
|||
delete videoPlayer; |
|||
videoPlayer = NULL; |
|||
#endif |
|||
//path = "";
|
|||
//name = "";
|
|||
loaded = false; |
|||
} |
|||
|
|||
#ifndef TARGET_RASPBERRY_PI |
|||
void VideoSource::update(ofEventArgs &args) { |
|||
if (videoPlayer != NULL) { |
|||
videoPlayer->update(); |
|||
} |
|||
} |
|||
#endif |
|||
} |
|||
} |
@ -0,0 +1,48 @@ |
|||
#pragma once |
|||
|
|||
#include "ofMain.h" |
|||
#include "BaseSource.h" |
|||
#ifdef TARGET_RASPBERRY_PI |
|||
/*
|
|||
Notice that if you get an error like this: |
|||
fatal error: libavcodec/opt.h: No such file or directory |
|||
Create a file opt.h in addons/ofxOMXPlayer/libs/ffmpeg/libavcodec/ |
|||
with the following contents: |
|||
|
|||
#ifndef AVCODEC_OPT_H |
|||
#define AVCODEC_OPT_H |
|||
#include "libavcodec/version.h" |
|||
#if FF_API_OPT_H |
|||
#include "libavutil/opt.h" |
|||
#endif |
|||
#endif // AVCODEC_OPT_H
|
|||
|
|||
More here: https://github.com/jvcleave/ofxOMXPlayer/issues/34
|
|||
*/ |
|||
#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(); |
|||
#ifndef TARGET_RASPBERRY_PI |
|||
void update(ofEventArgs& args); |
|||
#endif |
|||
|
|||
private: |
|||
#ifdef TARGET_RASPBERRY_PI |
|||
ofxOMXPlayer* omxPlayer; // Naming different for less confusion
|
|||
#else |
|||
// Go with ofVideoPlayer or
|
|||
// TODO: High Performance Video player on newer Macs
|
|||
ofVideoPlayer* videoPlayer; |
|||
#endif |
|||
}; |
|||
} |
|||
} |
@ -0,0 +1,90 @@ |
|||
#include "BaseSurface.h" |
|||
|
|||
namespace ofx { |
|||
namespace piMapper { |
|||
|
|||
BaseSurface::BaseSurface() { |
|||
ofEnableNormalizedTexCoords(); |
|||
createDefaultTexture(); |
|||
} |
|||
|
|||
BaseSurface::~BaseSurface() { |
|||
delete defaultSource; |
|||
defaultSource = NULL; |
|||
defaultTexture.clear(); |
|||
} |
|||
|
|||
void BaseSurface::createDefaultTexture() { |
|||
ofPixels pixels; |
|||
pixels.allocate(500, 500, 1); |
|||
for (int i = 0; i < pixels.size(); i++) { |
|||
pixels[i] = 255; |
|||
} |
|||
int squareSize = 10; // size of each test pattern square
|
|||
bool sy = false; |
|||
for (int y = 0; y < pixels.getWidth(); y += squareSize) { |
|||
bool sx = false; |
|||
for (int x = 0; x < pixels.getHeight(); x += squareSize) { |
|||
for (int yi = 0; yi < squareSize; yi++) { |
|||
for (int xi = 0; xi < squareSize; xi++) { |
|||
if (sx && sy) |
|||
pixels[(y + yi) * pixels.getWidth() + x + xi] = 255; |
|||
else if (sx && !sy) |
|||
pixels[(y + yi) * pixels.getWidth() + x + xi] = 0; |
|||
else if (!sx && sy) |
|||
pixels[(y + yi) * pixels.getWidth() + x + xi] = 0; |
|||
else |
|||
pixels[(y + yi) * pixels.getWidth() + x + xi] = 255; |
|||
} |
|||
} |
|||
sx = !sx; |
|||
} |
|||
sy = !sy; |
|||
} |
|||
|
|||
// load pixels into texture
|
|||
defaultTexture.loadData(pixels); |
|||
// 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(source->getTexture()->getWidth(), 0.0f)); |
|||
texMesh.addVertex(position + |
|||
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)); |
|||
source->getTexture()->bind(); |
|||
texMesh.draw(); |
|||
source->getTexture()->unbind(); |
|||
} |
|||
|
|||
//void BaseSurface::setTexture(ofTexture* texturePtr) { texture = texturePtr; }
|
|||
void BaseSurface::setSource(BaseSource* newSource) { |
|||
source = newSource; |
|||
} |
|||
|
|||
//ofTexture* BaseSurface::getTexture() { return texture; }
|
|||
BaseSource* BaseSurface::getSource() { |
|||
return source; |
|||
} |
|||
|
|||
//ofTexture* BaseSurface::getDefaultTexture() { return &defaultTexture; }
|
|||
BaseSource* BaseSurface::getDefaultSource() { |
|||
return defaultSource; |
|||
} |
|||
} |
|||
} |
@ -0,0 +1,47 @@ |
|||
#pragma once |
|||
|
|||
#include "ofMain.h" |
|||
#include <string> |
|||
#include "BaseSource.h" |
|||
|
|||
using namespace std; |
|||
|
|||
namespace ofx { |
|||
namespace piMapper { |
|||
class BaseSurface { |
|||
public: |
|||
BaseSurface(); |
|||
~BaseSurface(); |
|||
virtual void setup() {}; |
|||
virtual void draw() {}; |
|||
virtual void setVertex(int index, ofVec2f p) {}; |
|||
virtual void setTexCoord(int index, ofVec2f t) {}; |
|||
virtual void moveBy(ofVec2f v) {}; |
|||
virtual int getType() {}; |
|||
virtual bool hitTest(ofVec2f p) {}; |
|||
virtual ofPolyline getHitArea() {}; |
|||
virtual ofPolyline getTextureHitArea() {}; |
|||
virtual vector<ofVec3f>& getVertices() {}; |
|||
virtual vector<ofVec2f>& getTexCoords() {}; |
|||
|
|||
// Draws a texture using ofMesh
|
|||
void drawTexture(ofVec2f position); |
|||
//void setTexture(ofTexture* texturePtr);
|
|||
void setSource(BaseSource* newSource); |
|||
|
|||
//ofTexture* getTexture();
|
|||
//ofTexture* getDefaultTexture();
|
|||
BaseSource* getSource(); |
|||
BaseSource* getDefaultSource(); |
|||
|
|||
protected: |
|||
ofMesh mesh; |
|||
//ofTexture* texture;
|
|||
ofTexture defaultTexture; |
|||
BaseSource* source; |
|||
BaseSource* defaultSource; |
|||
|
|||
void createDefaultTexture(); |
|||
}; |
|||
} |
|||
} |
@ -0,0 +1,248 @@ |
|||
#include "QuadSurface.h" |
|||
|
|||
namespace ofx { |
|||
namespace piMapper { |
|||
QuadSurface::QuadSurface() { |
|||
cout << "QuadSurface constructor." << endl; |
|||
setup(); |
|||
} |
|||
|
|||
QuadSurface::~QuadSurface() { cout << "QuadSurface destructor." << endl; } |
|||
|
|||
void QuadSurface::setup() { |
|||
// Create 4 points for the 2 triangles
|
|||
ofVec2f p1 = ofVec2f(0, 0); |
|||
ofVec2f p2 = ofVec2f(0, ofGetHeight()); |
|||
ofVec2f p3 = ofVec2f(ofGetWidth(), ofGetHeight()); |
|||
ofVec2f p4 = ofVec2f(ofGetWidth(), 0); |
|||
|
|||
// Create 4 point for the texture coordinates
|
|||
ofVec2f t1 = ofVec2f(ofVec2f(0.0f, 0.0f)); |
|||
ofVec2f t2 = ofVec2f(ofVec2f(1.0f, 0.0f)); |
|||
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, source); |
|||
} |
|||
|
|||
void QuadSurface::setup(ofVec2f p1, ofVec2f p2, ofVec2f p3, ofVec2f p4, |
|||
ofVec2f t1, ofVec2f t2, ofVec2f t3, ofVec2f t4, |
|||
BaseSource* newSource) { |
|||
// Assign texture
|
|||
source = newSource; |
|||
|
|||
// Clear mesh
|
|||
mesh.clear(); |
|||
|
|||
// Create a surface with the points
|
|||
mesh.addVertex(p1); |
|||
mesh.addVertex(p2); |
|||
mesh.addVertex(p3); |
|||
mesh.addVertex(p4); |
|||
|
|||
// Add 2 triangles
|
|||
mesh.addTriangle(0, 2, 3); |
|||
mesh.addTriangle(0, 1, 2); |
|||
|
|||
// Add texture coordinates
|
|||
mesh.addTexCoord(t1); |
|||
mesh.addTexCoord(t2); |
|||
mesh.addTexCoord(t3); |
|||
mesh.addTexCoord(t4); |
|||
|
|||
// Pure GL setup
|
|||
// indices
|
|||
quadIndices[0] = 0; |
|||
quadIndices[1] = 1; |
|||
quadIndices[2] = 2; |
|||
quadIndices[3] = 0; |
|||
quadIndices[4] = 2; |
|||
quadIndices[5] = 3; |
|||
// tex coords (those are alway 0)
|
|||
quadTexCoordinates[2] = 0; |
|||
quadTexCoordinates[6] = 0; |
|||
quadTexCoordinates[10] = 0; |
|||
quadTexCoordinates[14] = 0; |
|||
|
|||
calculate4dTextureCoords(); |
|||
} |
|||
|
|||
void QuadSurface::draw() { |
|||
if (source->getTexture() == NULL) { |
|||
ofLogWarning("QuadSurface") << "Source texture empty. Not drawing."; |
|||
return; |
|||
} |
|||
|
|||
/*if(mesh.haveVertsChanged() || mesh.haveTexCoordsChanged()){
|
|||
calculate4dTextureCoords(); |
|||
}*/ |
|||
glEnableClientState(GL_TEXTURE_COORD_ARRAY); |
|||
glTexCoordPointer(4, GL_FLOAT, 0, quadTexCoordinates); |
|||
glVertexPointer(3, GL_FLOAT, 0, quadVertices); |
|||
|
|||
source->getTexture()->bind(); |
|||
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, quadIndices); |
|||
source->getTexture()->unbind(); |
|||
} |
|||
|
|||
void QuadSurface::setVertex(int index, ofVec2f p) { |
|||
if (index > 3) { |
|||
ofLog() << "Vertex with this index does not exist: " << index << endl; |
|||
return; |
|||
} |
|||
|
|||
mesh.setVertex(index, p); |
|||
calculate4dTextureCoords(); |
|||
} |
|||
|
|||
void QuadSurface::setTexCoord(int index, ofVec2f t) { |
|||
if (index > 3) { |
|||
ofLog() << "Texture coordinate with this index does not exist: " << index |
|||
<< endl; |
|||
return; |
|||
} |
|||
|
|||
mesh.setTexCoord(index, t); |
|||
calculate4dTextureCoords(); |
|||
} |
|||
|
|||
void QuadSurface::moveBy(ofVec2f v) { |
|||
vector<ofVec3f>& vertices = getVertices(); |
|||
for (int i = 0; i < vertices.size(); i++) { |
|||
vertices[i] += v; |
|||
} |
|||
calculate4dTextureCoords(); |
|||
} |
|||
|
|||
int QuadSurface::getType() { return SurfaceType::QUAD_SURFACE; } |
|||
|
|||
bool QuadSurface::hitTest(ofVec2f p) { |
|||
// Construct ofPolyline from vertices
|
|||
ofPolyline line = getHitArea(); |
|||
|
|||
if (line.inside(p.x, p.y)) { |
|||
return true; |
|||
} else { |
|||
return false; |
|||
} |
|||
} |
|||
|
|||
ofVec2f QuadSurface::getVertex(int index) { |
|||
if (index > 3) { |
|||
ofLog() << "Vertex with this index does not exist: " << index << endl; |
|||
throw std::runtime_error("Vertex index out of bounds."); |
|||
} |
|||
|
|||
ofVec3f vert = mesh.getVertex(index); |
|||
return ofVec2f(vert.x, vert.y); |
|||
} |
|||
|
|||
ofVec2f QuadSurface::getTexCoord(int index) { |
|||
if (index > 3) { |
|||
throw std::runtime_error("Texture coordinate index out of bounds."); |
|||
} |
|||
|
|||
return mesh.getTexCoord(index); |
|||
} |
|||
|
|||
ofPolyline QuadSurface::getHitArea() { |
|||
ofPolyline line; |
|||
line.addVertex(ofPoint(mesh.getVertex(0).x, mesh.getVertex(0).y)); |
|||
line.addVertex(ofPoint(mesh.getVertex(1).x, mesh.getVertex(1).y)); |
|||
line.addVertex(ofPoint(mesh.getVertex(2).x, mesh.getVertex(2).y)); |
|||
line.addVertex(ofPoint(mesh.getVertex(3).x, mesh.getVertex(3).y)); |
|||
line.close(); |
|||
|
|||
return line; |
|||
} |
|||
|
|||
ofPolyline QuadSurface::getTextureHitArea() { |
|||
ofPolyline line; |
|||
vector<ofVec2f>& texCoords = mesh.getTexCoords(); |
|||
ofVec2f textureSize = ofVec2f(source->getTexture()->getWidth(), source->getTexture()->getHeight()); |
|||
for (int i = 0; i < texCoords.size(); i++) { |
|||
line.addVertex(ofPoint(texCoords[i] * textureSize)); |
|||
} |
|||
line.close(); |
|||
|
|||
return line; |
|||
} |
|||
|
|||
vector<ofVec3f>& QuadSurface::getVertices() { |
|||
// return only joint vertices
|
|||
return mesh.getVertices(); |
|||
} |
|||
|
|||
vector<ofVec2f>& QuadSurface::getTexCoords() { return mesh.getTexCoords(); } |
|||
|
|||
void QuadSurface::calculate4dTextureCoords() { |
|||
// Perspective Warping with OpenGL Fixed Pipeline and q coordinates
|
|||
// see:
|
|||
// http://www.reedbeta.com/blog/2012/05/26/quadrilateral-interpolation-part-1/
|
|||
// for information on the technique
|
|||
// Pue OpenGL is used because the ofMesh sadly doesn't support ofVec4f as
|
|||
// texture coordinates.
|
|||
// calculate intersection point
|
|||
ofVec3f p0 = mesh.getVertex(0); |
|||
ofVec3f p1 = mesh.getVertex(1); |
|||
ofVec3f p2 = mesh.getVertex(2); |
|||
ofVec3f p3 = mesh.getVertex(3); |
|||
|
|||
ofVec3f t0 = mesh.getTexCoord(0); |
|||
ofVec3f t1 = mesh.getTexCoord(1); |
|||
ofVec3f t2 = mesh.getTexCoord(2); |
|||
ofVec3f t3 = mesh.getTexCoord(3); |
|||
|
|||
ofPoint interSect; |
|||
ofLineSegmentIntersection(ofPoint(p0.x, p0.y), ofPoint(p2.x, p2.y), |
|||
ofPoint(p1.x, p1.y), ofPoint(p3.x, p3.y), |
|||
interSect); |
|||
ofVec3f interSecVec = ofVec3f(interSect.x, interSect.y, 0); |
|||
|
|||
// calculate distances to intersection point
|
|||
float d0 = interSecVec.distance(p0); |
|||
float d1 = interSecVec.distance(p1); |
|||
float d2 = interSecVec.distance(p2); |
|||
float d3 = interSecVec.distance(p3); |
|||
|
|||
// vertices
|
|||
// top left corner
|
|||
quadVertices[0] = p0.x; |
|||
quadVertices[1] = p0.y; |
|||
quadVertices[2] = 0; |
|||
// top right corner
|
|||
quadVertices[3] = p1.x; |
|||
quadVertices[4] = p1.y; |
|||
quadVertices[5] = 0; |
|||
// bottom right corner
|
|||
quadVertices[6] = p2.x; |
|||
quadVertices[7] = p2.y; |
|||
quadVertices[8] = 0; |
|||
// bottom left corner
|
|||
quadVertices[9] = p3.x; |
|||
quadVertices[10] = p3.y; |
|||
quadVertices[11] = 0; |
|||
|
|||
float q0 = (d0 + d2) / (d2); |
|||
float q1 = (d1 + d3) / (d3); |
|||
float q2 = (d2 + d0) / (d0); |
|||
float q3 = (d3 + d1) / (d1); |
|||
|
|||
quadTexCoordinates[0] = t0.x; |
|||
quadTexCoordinates[1] = t0.y; |
|||
quadTexCoordinates[3] = q0; |
|||
|
|||
quadTexCoordinates[4] = t1.x * q1; |
|||
quadTexCoordinates[5] = t1.y; |
|||
quadTexCoordinates[7] = q1; |
|||
|
|||
quadTexCoordinates[8] = t2.x * q2; |
|||
quadTexCoordinates[9] = t2.y * q2; |
|||
quadTexCoordinates[11] = q2; |
|||
|
|||
quadTexCoordinates[12] = t3.x; |
|||
quadTexCoordinates[13] = t3.y * q3; |
|||
quadTexCoordinates[15] = q3; |
|||
} |
|||
} |
|||
} |
@ -0,0 +1,40 @@ |
|||
#pragma once |
|||
|
|||
#include "ofMain.h" |
|||
#include "BaseSurface.h" |
|||
#include "SurfaceType.h" |
|||
|
|||
namespace ofx { |
|||
namespace piMapper { |
|||
class QuadSurface : public BaseSurface { |
|||
public: |
|||
QuadSurface(); |
|||
~QuadSurface(); |
|||
|
|||
void setup(); |
|||
|
|||
void setup(ofVec2f p1, ofVec2f p2, ofVec2f p3, ofVec2f p4, ofVec2f t1, |
|||
ofVec2f t2, ofVec2f t3, ofVec2f t4, BaseSource* newSource); |
|||
|
|||
void draw(); |
|||
void setVertex(int index, ofVec2f p); |
|||
void setTexCoord(int index, ofVec2f t); |
|||
void moveBy(ofVec2f v); |
|||
|
|||
int getType(); |
|||
bool hitTest(ofVec2f p); |
|||
ofVec2f getVertex(int index); |
|||
ofVec2f getTexCoord(int index); |
|||
ofPolyline getHitArea(); |
|||
ofPolyline getTextureHitArea(); |
|||
vector<ofVec3f>& getVertices(); |
|||
vector<ofVec2f>& getTexCoords(); |
|||
|
|||
private: |
|||
void calculate4dTextureCoords(); |
|||
GLfloat quadVertices[12]; |
|||
GLubyte quadIndices[6]; |
|||
GLfloat quadTexCoordinates[16]; |
|||
}; |
|||
} |
|||
} |
@ -0,0 +1,392 @@ |
|||
#include "SurfaceManager.h" |
|||
|
|||
namespace ofx { |
|||
namespace piMapper { |
|||
SurfaceManager::SurfaceManager() { |
|||
// Init variables
|
|||
mediaServer = NULL; |
|||
} |
|||
|
|||
SurfaceManager::~SurfaceManager() { clear(); } |
|||
|
|||
void SurfaceManager::draw() { |
|||
for (int i = 0; i < surfaces.size(); i++) { |
|||
surfaces[i]->draw(); |
|||
} |
|||
} |
|||
|
|||
void SurfaceManager::addSurface(int surfaceType) { |
|||
if (surfaceType == SurfaceType::TRIANGLE_SURFACE) { |
|||
surfaces.push_back(new TriangleSurface()); |
|||
} else if (surfaceType == SurfaceType::QUAD_SURFACE) { |
|||
surfaces.push_back(new QuadSurface()); |
|||
} else { |
|||
ofLogFatalError("SurfaceManager") << "Attempt to add non-existing surface type"; |
|||
std::exit(EXIT_FAILURE); |
|||
} |
|||
} |
|||
|
|||
void SurfaceManager::addSurface(int surfaceType, BaseSource* newSource) { |
|||
if (surfaceType == SurfaceType::TRIANGLE_SURFACE) { |
|||
surfaces.push_back(new TriangleSurface()); |
|||
surfaces.back()->setSource(newSource); |
|||
} else if (surfaceType == SurfaceType::QUAD_SURFACE) { |
|||
surfaces.push_back(new QuadSurface()); |
|||
surfaces.back()->setSource(newSource); |
|||
} else { |
|||
ofLogFatalError("SurfaceManager") << "Attempt to add non-existing surface type"; |
|||
std::exit(EXIT_FAILURE); |
|||
} |
|||
} |
|||
|
|||
void SurfaceManager::addSurface(int surfaceType, vector<ofVec2f> vertices, |
|||
vector<ofVec2f> texCoords) { |
|||
if (surfaceType == SurfaceType::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 TriangleSurface()); |
|||
|
|||
for (int i = 0; i < 3; i++) { |
|||
surfaces.back()->setVertex(i, vertices[i]); |
|||
surfaces.back()->setTexCoord(i, texCoords[i]); |
|||
} |
|||
|
|||
} else if (surfaceType == SurfaceType::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 QuadSurface()); |
|||
|
|||
for (int i = 0; i < 4; i++) { |
|||
surfaces.back()->setVertex(i, vertices[i]); |
|||
surfaces.back()->setTexCoord(i, texCoords[i]); |
|||
} |
|||
} else { |
|||
ofLogFatalError("SurfaceManager") << "Attempt to add non-existing surface type"; |
|||
std::exit(EXIT_FAILURE); |
|||
} |
|||
} |
|||
|
|||
void SurfaceManager::addSurface(int surfaceType, BaseSource* newSource, |
|||
vector<ofVec2f> vertices, |
|||
vector<ofVec2f> texCoords) { |
|||
if (surfaceType == SurfaceType::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 TriangleSurface()); |
|||
surfaces.back()->setSource(newSource); |
|||
|
|||
for (int i = 0; i < 3; i++) { |
|||
surfaces.back()->setVertex(i, vertices[i]); |
|||
surfaces.back()->setTexCoord(i, texCoords[i]); |
|||
} |
|||
|
|||
} else if (surfaceType == SurfaceType::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 QuadSurface()); |
|||
surfaces.back()->setSource(newSource); |
|||
|
|||
for (int i = 0; i < 4; i++) { |
|||
surfaces.back()->setVertex(i, vertices[i]); |
|||
surfaces.back()->setTexCoord(i, texCoords[i]); |
|||
} |
|||
} else { |
|||
ofLogFatalError("SurfaceManager") << "Attempt to add non-existing surface type"; |
|||
std::exit(EXIT_FAILURE); |
|||
} |
|||
} |
|||
|
|||
void SurfaceManager::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 SurfaceManager::clear() { |
|||
// delete all extra allocations from the heap
|
|||
while (surfaces.size()) { |
|||
delete surfaces.back(); |
|||
surfaces.pop_back(); |
|||
} |
|||
} |
|||
|
|||
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
|
|||
xmlSettings.addTag("surfaces"); |
|||
xmlSettings.pushTag("surfaces"); |
|||
for (int i = 0; i < surfaces.size(); i++) { |
|||
xmlSettings.addTag("surface"); |
|||
xmlSettings.pushTag("surface", i); |
|||
BaseSurface* 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"); |
|||
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.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)) { |
|||
ofLogWarning("SurfaceManager") << "Could not load XML settings"; |
|||
return; |
|||
} |
|||
if (!xmlSettings.tagExists("surfaces")) { |
|||
ofLogWarning("SurfaceManager") << "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", ""); |
|||
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
|
|||
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" && source != NULL) { |
|||
addSurface(SurfaceType::TRIANGLE_SURFACE, source, vertices, |
|||
texCoords); |
|||
} else { |
|||
addSurface(SurfaceType::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" && source != NULL) { |
|||
addSurface(SurfaceType::QUAD_SURFACE, source, vertices, |
|||
texCoords); |
|||
} else { |
|||
addSurface(SurfaceType::QUAD_SURFACE, vertices, texCoords); |
|||
} |
|||
} |
|||
|
|||
xmlSettings.popTag(); // surface
|
|||
} |
|||
|
|||
xmlSettings.popTag(); // surfaces
|
|||
} |
|||
|
|||
void SurfaceManager::setMediaServer(MediaServer* newMediaServer) { |
|||
mediaServer = newMediaServer; |
|||
} |
|||
|
|||
BaseSurface* SurfaceManager::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"); |
|||
} |
|||
|
|||
BaseSurface* SurfaceManager::getSelectedSurface() { |
|||
return selectedSurface; |
|||
} |
|||
|
|||
void SurfaceManager::deselectSurface() { |
|||
selectedSurface = NULL; |
|||
} |
|||
|
|||
BaseSurface* SurfaceManager::getSurface(int index) { |
|||
if (index >= surfaces.size()) { |
|||
throw std::runtime_error("Surface index out of bounds."); |
|||
return NULL; |
|||
} |
|||
|
|||
return surfaces[index]; |
|||
} |
|||
|
|||
int SurfaceManager::size() { return surfaces.size(); } |
|||
} |
|||
} |
@ -0,0 +1,49 @@ |
|||
#pragma once |
|||
|
|||
#include "BaseSurface.h" |
|||
#include "TriangleSurface.h" |
|||
#include "QuadSurface.h" |
|||
#include "SurfaceType.h" |
|||
#include "MediaServer.h" |
|||
#include "BaseSource.h" |
|||
#include "SourceType.h" |
|||
|
|||
#include "ofEvents.h" |
|||
#include "ofxXmlSettings.h" |
|||
|
|||
using namespace std; |
|||
|
|||
namespace ofx { |
|||
namespace piMapper { |
|||
class SurfaceManager { |
|||
public: |
|||
SurfaceManager(); |
|||
~SurfaceManager(); |
|||
|
|||
void draw(); |
|||
void addSurface(int surfaceType); |
|||
void addSurface(int surfaceType, BaseSource* newSource); |
|||
void addSurface(int surfaceType, vector<ofVec2f> vertices, |
|||
vector<ofVec2f> texCoords); |
|||
void addSurface(int surfaceType, BaseSource* newSource, |
|||
vector<ofVec2f> vertices, vector<ofVec2f> texCoords); |
|||
void removeSelectedSurface(); |
|||
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(); |
|||
|
|||
private: |
|||
std::vector<BaseSurface*> surfaces; |
|||
BaseSurface* selectedSurface; |
|||
ofxXmlSettings xmlSettings; |
|||
MediaServer* mediaServer; |
|||
}; |
|||
} |
|||
} |
@ -0,0 +1,250 @@ |
|||
#include "SurfaceManagerGui.h" |
|||
|
|||
namespace ofx { |
|||
namespace piMapper { |
|||
SurfaceManagerGui::SurfaceManagerGui() { |
|||
surfaceManager = NULL; |
|||
guiMode = GuiMode::NONE; |
|||
bDrag = false; |
|||
registerMouseEvents(); |
|||
ofHideCursor(); |
|||
} |
|||
|
|||
SurfaceManagerGui::~SurfaceManagerGui() { |
|||
unregisterMouseEvents(); |
|||
surfaceManager = NULL; |
|||
} |
|||
|
|||
void SurfaceManagerGui::registerMouseEvents() { |
|||
ofAddListener(ofEvents().mousePressed, this, |
|||
&SurfaceManagerGui::mousePressed); |
|||
ofAddListener(ofEvents().mouseReleased, this, |
|||
&SurfaceManagerGui::mouseReleased); |
|||
ofAddListener(ofEvents().mouseDragged, this, |
|||
&SurfaceManagerGui::mouseDragged); |
|||
} |
|||
|
|||
void SurfaceManagerGui::unregisterMouseEvents() { |
|||
ofRemoveListener(ofEvents().mousePressed, this, |
|||
&SurfaceManagerGui::mousePressed); |
|||
ofRemoveListener(ofEvents().mouseReleased, this, |
|||
&SurfaceManagerGui::mouseReleased); |
|||
ofRemoveListener(ofEvents().mouseDragged, this, |
|||
&SurfaceManagerGui::mouseDragged); |
|||
} |
|||
|
|||
void SurfaceManagerGui::draw() { |
|||
if (surfaceManager == NULL) return; |
|||
|
|||
if (guiMode == GuiMode::NONE) { |
|||
surfaceManager->draw(); |
|||
} else if (guiMode == GuiMode::TEXTURE_MAPPING) { |
|||
// draw the texture of the selected surface
|
|||
if (surfaceManager->getSelectedSurface() != NULL) { |
|||
surfaceManager->getSelectedSurface()->drawTexture(ofVec2f(0, 0)); |
|||
} |
|||
|
|||
// draw surfaces with opacity
|
|||
ofPushStyle(); |
|||
ofSetColor(255, 255, 255, 200); |
|||
surfaceManager->draw(); |
|||
ofPopStyle(); |
|||
|
|||
// highlight selected surface
|
|||
drawSelectedSurfaceHighlight(); |
|||
|
|||
// hilight selected surface texture
|
|||
drawSelectedSurfaceTextureHighlight(); |
|||
|
|||
// draw texture editing GUI on top
|
|||
textureEditor.draw(); |
|||
|
|||
} else if (guiMode == GuiMode::PROJECTION_MAPPING) { |
|||
// draw projection surfaces first
|
|||
surfaceManager->draw(); |
|||
|
|||
// highlight selected surface
|
|||
drawSelectedSurfaceHighlight(); |
|||
|
|||
// draw projection mapping editing gui
|
|||
projectionEditor.draw(); |
|||
|
|||
} else if (guiMode == GuiMode::SOURCE_SELECTION) { |
|||
// draw projection surfaces first
|
|||
surfaceManager->draw(); |
|||
|
|||
// highlight selected surface
|
|||
drawSelectedSurfaceHighlight(); |
|||
|
|||
sourcesEditor.draw(); |
|||
} |
|||
} |
|||
|
|||
void SurfaceManagerGui::mousePressed(ofMouseEventArgs& args) { |
|||
if (guiMode == GuiMode::NONE) { |
|||
return; |
|||
} else if (guiMode == GuiMode::TEXTURE_MAPPING) { |
|||
bool bSurfaceSelected = false; |
|||
|
|||
CircleJoint* hitJoint = |
|||
textureEditor.hitTestJoints(ofVec2f(args.x, args.y)); |
|||
if (hitJoint != NULL) { |
|||
textureEditor.unselectAllJoints(); |
|||
hitJoint->select(); |
|||
hitJoint->startDrag(); |
|||
bSurfaceSelected = true; |
|||
} else { |
|||
textureEditor.unselectAllJoints(); |
|||
} |
|||
|
|||
if (surfaceManager->getSelectedSurface() != NULL && !bSurfaceSelected) { |
|||
// hittest texture area to see if we are hitting the texture surface
|
|||
if (surfaceManager->getSelectedSurface()->getTextureHitArea().inside( |
|||
args.x, args.y)) { |
|||
clickPosition = ofVec2f(args.x, args.y); |
|||
startDrag(); |
|||
} |
|||
} |
|||
|
|||
} else if (guiMode == GuiMode::PROJECTION_MAPPING) { |
|||
bool bSurfaceSelected = false; |
|||
|
|||
CircleJoint* hitJoint = |
|||
projectionEditor.hitTestJoints(ofVec2f(args.x, args.y)); |
|||
if (hitJoint != NULL) { |
|||
projectionEditor.unselectAllJoints(); |
|||
hitJoint->select(); |
|||
hitJoint->startDrag(); |
|||
bSurfaceSelected = true; |
|||
} |
|||
|
|||
// attempt to select surface, loop from end to beginning
|
|||
if (!bSurfaceSelected) { |
|||
for (int i = surfaceManager->size() - 1; i >= 0; i--) { |
|||
if (surfaceManager->getSurface(i)->hitTest(ofVec2f(args.x, args.y))) { |
|||
projectionEditor.clearJoints(); |
|||
surfaceManager->selectSurface(i); |
|||
projectionEditor.createJoints(); |
|||
bSurfaceSelected = true; |
|||
break; |
|||
} |
|||
} |
|||
} |
|||
|
|||
if (bSurfaceSelected && hitJoint == NULL) { |
|||
// if not hitting the joints, start drag only if we have a selected
|
|||
// surface
|
|||
clickPosition = ofVec2f(args.x, args.y); |
|||
startDrag(); |
|||
} |
|||
|
|||
if (!bSurfaceSelected) { |
|||
// unselect if no surface selected
|
|||
projectionEditor.clearJoints(); |
|||
surfaceManager->deselectSurface(); |
|||
} |
|||
} else if (guiMode == GuiMode::SOURCE_SELECTION) { |
|||
} |
|||
} |
|||
|
|||
void SurfaceManagerGui::mouseReleased(ofMouseEventArgs& args) { |
|||
stopDrag(); |
|||
projectionEditor.stopDragJoints(); |
|||
textureEditor.stopDragJoints(); |
|||
} |
|||
|
|||
void SurfaceManagerGui::mouseDragged(ofMouseEventArgs& args) { |
|||
if (bDrag) { |
|||
ofVec2f mousePosition = ofVec2f(args.x, args.y); |
|||
ofVec2f distance = mousePosition - clickPosition; |
|||
|
|||
if (guiMode == GuiMode::PROJECTION_MAPPING) { |
|||
// add this distance to all vertices in surface
|
|||
projectionEditor.moveSelectedSurface(distance); |
|||
} else if (guiMode == GuiMode::TEXTURE_MAPPING) { |
|||
textureEditor.moveTexCoords(distance); |
|||
} |
|||
clickPosition = mousePosition; |
|||
} |
|||
} |
|||
|
|||
void SurfaceManagerGui::setSurfaceManager(SurfaceManager* newSurfaceManager) { |
|||
surfaceManager = newSurfaceManager; |
|||
projectionEditor.setSurfaceManager(surfaceManager); |
|||
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 && |
|||
newGuiMode != GuiMode::SOURCE_SELECTION) { |
|||
throw std::runtime_error("Trying to set invalid mode."); |
|||
} |
|||
|
|||
if (newGuiMode == GuiMode::NONE) { |
|||
ofHideCursor(); |
|||
} else { |
|||
ofShowCursor(); |
|||
} |
|||
|
|||
guiMode = newGuiMode; |
|||
|
|||
if (guiMode == GuiMode::SOURCE_SELECTION) { |
|||
sourcesEditor.enable(); |
|||
//string sourceName = surfaceManager->getSelectedSurfaceSourceName();
|
|||
//sourcesEditor.selectImageSourceRadioButton(sourceName);
|
|||
} else { |
|||
sourcesEditor.disable(); |
|||
} |
|||
|
|||
if (guiMode == GuiMode::TEXTURE_MAPPING) { |
|||
textureEditor.enable(); |
|||
// refresh texture editor surface reference
|
|||
textureEditor.setSurface(surfaceManager->getSelectedSurface()); |
|||
} else { |
|||
textureEditor.disable(); |
|||
} |
|||
|
|||
if (guiMode == GuiMode::PROJECTION_MAPPING) { |
|||
projectionEditor.enable(); |
|||
} else { |
|||
projectionEditor.disable(); |
|||
} |
|||
} |
|||
|
|||
void SurfaceManagerGui::drawSelectedSurfaceHighlight() { |
|||
if (surfaceManager->getSelectedSurface() == NULL) return; |
|||
|
|||
ofPolyline line = surfaceManager->getSelectedSurface()->getHitArea(); |
|||
|
|||
ofPushStyle(); |
|||
ofSetLineWidth(1); |
|||
ofSetColor(255, 255, 255, 255); |
|||
line.draw(); |
|||
ofPopStyle(); |
|||
} |
|||
|
|||
void SurfaceManagerGui::drawSelectedSurfaceTextureHighlight() { |
|||
if (surfaceManager->getSelectedSurface() == NULL) return; |
|||
|
|||
ofPolyline line = surfaceManager->getSelectedSurface()->getTextureHitArea(); |
|||
|
|||
ofPushStyle(); |
|||
ofSetLineWidth(1); |
|||
ofSetColor(255, 255, 0, 255); |
|||
line.draw(); |
|||
ofPopStyle(); |
|||
} |
|||
|
|||
void SurfaceManagerGui::startDrag() { bDrag = true; } |
|||
|
|||
void SurfaceManagerGui::stopDrag() { bDrag = false; } |
|||
} |
|||
} |
@ -0,0 +1,48 @@ |
|||
#pragma once |
|||
|
|||
// I'm starting to think, maybe we should use ofxStateMachine here.
|
|||
// Would make sense. TODO later.
|
|||
|
|||
#include "ofEvents.h" |
|||
#include "ofGraphics.h" |
|||
|
|||
#include "SurfaceManager.h" |
|||
#include "TextureEditor.h" |
|||
#include "ProjectionEditor.h" |
|||
#include "SourcesEditor.h" |
|||
#include "GuiMode.h" |
|||
|
|||
namespace ofx { |
|||
namespace piMapper { |
|||
class SurfaceManagerGui { |
|||
public: |
|||
SurfaceManagerGui(); |
|||
~SurfaceManagerGui(); |
|||
|
|||
void registerMouseEvents(); |
|||
void unregisterMouseEvents(); |
|||
|
|||
void draw(); |
|||
void mousePressed(ofMouseEventArgs& args); |
|||
void mouseReleased(ofMouseEventArgs& args); |
|||
void mouseDragged(ofMouseEventArgs& args); |
|||
void setSurfaceManager(SurfaceManager* newSurfaceManager); |
|||
void setMediaServer(MediaServer* newMediaServer); |
|||
void setMode(int newGuiMode); |
|||
void drawSelectedSurfaceHighlight(); |
|||
void drawSelectedSurfaceTextureHighlight(); |
|||
void startDrag(); |
|||
void stopDrag(); |
|||
|
|||
private: |
|||
SurfaceManager* surfaceManager; |
|||
MediaServer* mediaServer; |
|||
TextureEditor textureEditor; |
|||
ProjectionEditor projectionEditor; |
|||
SourcesEditor sourcesEditor; |
|||
int guiMode; |
|||
bool bDrag; |
|||
ofVec2f clickPosition; |
|||
}; |
|||
} |
|||
} |
@ -0,0 +1,9 @@ |
|||
#pragma once |
|||
|
|||
namespace ofx { |
|||
namespace piMapper { |
|||
struct SurfaceType { |
|||
enum { TRIANGLE_SURFACE, QUAD_SURFACE }; |
|||
}; |
|||
} |
|||
} |
@ -0,0 +1,141 @@ |
|||
#include "TriangleSurface.h" |
|||
|
|||
namespace ofx { |
|||
namespace piMapper { |
|||
TriangleSurface::TriangleSurface() { |
|||
setup(); |
|||
} |
|||
|
|||
TriangleSurface::~TriangleSurface() {} |
|||
|
|||
void TriangleSurface::setup() { |
|||
// Create 3 points for the triangle
|
|||
ofVec2f p1 = ofVec2f(ofGetWidth() / 2.0f, 0); |
|||
ofVec2f p2 = ofVec2f(ofVec2f(0, ofGetHeight())); |
|||
ofVec2f p3 = ofVec2f(ofGetWidth(), ofGetHeight()); |
|||
|
|||
// Create 3 point for the texture coordinates
|
|||
ofVec2f t1 = ofVec2f(0.5f, 0); |
|||
ofVec2f t2 = ofVec2f(0, 1.0f); |
|||
ofVec2f t3 = ofVec2f(1, 1.0f); |
|||
|
|||
setup(p1, p2, p3, t1, t2, t3, source); |
|||
} |
|||
|
|||
void TriangleSurface::setup(ofVec2f p1, ofVec2f p2, ofVec2f p3, ofVec2f t1, |
|||
ofVec2f t2, ofVec2f t3, BaseSource* newSource) { |
|||
// Assign texture
|
|||
source = newSource; |
|||
|
|||
// Clear mesh
|
|||
mesh.clear(); |
|||
|
|||
// Create a surface with the points
|
|||
mesh.addVertex(p1); |
|||
mesh.addVertex(p2); |
|||
mesh.addVertex(p3); |
|||
|
|||
// Add texture coordinates
|
|||
mesh.addTexCoord(t1); |
|||
mesh.addTexCoord(t2); |
|||
mesh.addTexCoord(t3); |
|||
} |
|||
|
|||
void TriangleSurface::draw() { |
|||
if (source->getTexture() == NULL) { |
|||
ofLogWarning("TriangleSurface") << "Source texture is empty. Not drawing."; |
|||
return; |
|||
} |
|||
|
|||
source->getTexture()->bind(); |
|||
mesh.draw(); |
|||
source->getTexture()->unbind(); |
|||
} |
|||
|
|||
void TriangleSurface::setVertex(int index, ofVec2f p) { |
|||
if (index > 2) { |
|||
ofLog() << "Vertex with this index does not exist: " << index << endl; |
|||
return; |
|||
} |
|||
|
|||
mesh.setVertex(index, p); |
|||
} |
|||
|
|||
void TriangleSurface::setTexCoord(int index, ofVec2f t) { |
|||
if (index > 2) { |
|||
ofLog() << "Texture coordinate with this index does not exist: " << index |
|||
<< endl; |
|||
return; |
|||
} |
|||
|
|||
mesh.setTexCoord(index, t); |
|||
} |
|||
|
|||
void TriangleSurface::moveBy(ofVec2f v) { |
|||
vector<ofVec3f>& vertices = getVertices(); |
|||
for (int i = 0; i < vertices.size(); i++) { |
|||
vertices[i] += v; |
|||
} |
|||
} |
|||
|
|||
int TriangleSurface::getType() { return SurfaceType::TRIANGLE_SURFACE; } |
|||
|
|||
bool TriangleSurface::hitTest(ofVec2f p) { |
|||
// Construct ofPolyline from vertices
|
|||
ofPolyline line = getHitArea(); |
|||
|
|||
if (line.inside(p.x, p.y)) { |
|||
return true; |
|||
} else { |
|||
return false; |
|||
} |
|||
} |
|||
|
|||
ofVec2f TriangleSurface::getVertex(int index) { |
|||
if (index > 2) { |
|||
ofLog() << "Vertex with this index does not exist: " << index << endl; |
|||
throw std::runtime_error("Vertex index out of bounds."); |
|||
} |
|||
|
|||
ofVec3f vert = mesh.getVertex(index); |
|||
return ofVec2f(vert.x, vert.y); |
|||
} |
|||
|
|||
ofVec2f TriangleSurface::getTexCoord(int index) { |
|||
if (index > 2) { |
|||
throw std::runtime_error("Texture coordinate index out of bounds."); |
|||
} |
|||
|
|||
return mesh.getTexCoord(index); |
|||
} |
|||
|
|||
ofPolyline TriangleSurface::getHitArea() { |
|||
ofPolyline line; |
|||
line.addVertex(ofPoint(mesh.getVertex(0).x, mesh.getVertex(0).y)); |
|||
line.addVertex(ofPoint(mesh.getVertex(1).x, mesh.getVertex(1).y)); |
|||
line.addVertex(ofPoint(mesh.getVertex(2).x, mesh.getVertex(2).y)); |
|||
line.close(); |
|||
|
|||
return line; |
|||
} |
|||
|
|||
ofPolyline TriangleSurface::getTextureHitArea() { |
|||
ofPolyline line; |
|||
vector<ofVec2f>& texCoords = mesh.getTexCoords(); |
|||
ofVec2f textureSize = ofVec2f(source->getTexture()->getWidth(), source->getTexture()->getHeight()); |
|||
for (int i = 0; i < texCoords.size(); i++) { |
|||
line.addVertex(ofPoint(texCoords[i] * textureSize)); |
|||
} |
|||
line.close(); |
|||
|
|||
return line; |
|||
} |
|||
|
|||
vector<ofVec3f>& TriangleSurface::getVertices() { |
|||
// return only joint vertices
|
|||
return mesh.getVertices(); |
|||
} |
|||
|
|||
vector<ofVec2f>& TriangleSurface::getTexCoords() { return mesh.getTexCoords(); } |
|||
} |
|||
} |
@ -0,0 +1,32 @@ |
|||
#pragma once |
|||
|
|||
#include "ofMain.h" |
|||
#include "BaseSurface.h" |
|||
#include "SurfaceType.h" |
|||
|
|||
namespace ofx { |
|||
namespace piMapper { |
|||
class TriangleSurface : public BaseSurface { |
|||
public: |
|||
TriangleSurface(); |
|||
~TriangleSurface(); |
|||
|
|||
void setup(); |
|||
void setup(ofVec2f p1, ofVec2f p2, ofVec2f p3, ofVec2f t1, ofVec2f t2, |
|||
ofVec2f t3, BaseSource* newSource); |
|||
void draw(); |
|||
void setVertex(int index, ofVec2f p); |
|||
void setTexCoord(int index, ofVec2f t); |
|||
void moveBy(ofVec2f v); |
|||
|
|||
int getType(); |
|||
bool hitTest(ofVec2f p); |
|||
ofVec2f getVertex(int index); |
|||
ofVec2f getTexCoord(int index); |
|||
ofPolyline getHitArea(); |
|||
ofPolyline getTextureHitArea(); |
|||
vector<ofVec3f>& getVertices(); |
|||
vector<ofVec2f>& getTexCoords(); |
|||
}; |
|||
} |
|||
} |
@ -0,0 +1,72 @@ |
|||
#include "BaseJoint.h" |
|||
|
|||
namespace ofx { |
|||
namespace piMapper { |
|||
|
|||
BaseJoint::BaseJoint() { |
|||
setDefaultColors(); |
|||
setDefaultProperties(); |
|||
registerMouseEvents(); |
|||
} |
|||
|
|||
BaseJoint::~BaseJoint() { unregisterMouseEvents(); } |
|||
|
|||
void BaseJoint::registerMouseEvents() { |
|||
ofAddListener(ofEvents().mousePressed, this, &BaseJoint::mousePressed); |
|||
ofAddListener(ofEvents().mouseDragged, this, &BaseJoint::mouseDragged); |
|||
} |
|||
|
|||
void BaseJoint::unregisterMouseEvents() { |
|||
ofRemoveListener(ofEvents().mousePressed, this, &BaseJoint::mousePressed); |
|||
ofRemoveListener(ofEvents().mouseDragged, this, &BaseJoint::mouseDragged); |
|||
} |
|||
|
|||
void BaseJoint::mousePressed(ofMouseEventArgs& args) { |
|||
if (hitTest(ofVec2f(args.x, args.y))) { |
|||
// selected = true;
|
|||
clickDistance = position - ofVec2f(args.x, args.y); |
|||
// startDrag();
|
|||
} |
|||
} |
|||
|
|||
void BaseJoint::mouseReleased(int x, int y, int button) { stopDrag(); } |
|||
|
|||
void BaseJoint::mouseDragged(ofMouseEventArgs& args) { |
|||
if (!bDrag) return; |
|||
position = ofVec2f(args.x, args.y) + clickDistance; |
|||
} |
|||
|
|||
void BaseJoint::startDrag() { bDrag = true; } |
|||
|
|||
void BaseJoint::stopDrag() { bDrag = false; } |
|||
|
|||
void BaseJoint::select() { selected = true; } |
|||
|
|||
void BaseJoint::unselect() { selected = false; } |
|||
|
|||
void BaseJoint::setClickDistance(ofVec2f newClickDistance) { |
|||
clickDistance = newClickDistance; |
|||
} |
|||
|
|||
bool BaseJoint::isDragged() { return bDrag; } |
|||
|
|||
bool BaseJoint::isSelected() { return selected; } |
|||
|
|||
void BaseJoint::setDefaultColors() { |
|||
fillColor = ofColor(0, 255, 255, 0); |
|||
strokeColor = ofColor(255, 255, 255); |
|||
fillColorSelected = ofColor(255, 255, 0, 0); |
|||
strokeColorSelected = ofColor(255, 0, 0); |
|||
} |
|||
|
|||
void BaseJoint::setDefaultProperties() { |
|||
enabled = true; |
|||
visible = true; |
|||
position = ofVec2f(20.0f, 20.0f); |
|||
clickDistance = ofVec2f(0.0f, 0.0f); |
|||
bDrag = false; |
|||
selected = false; |
|||
strokeWidth = 1.5f; |
|||
} |
|||
} |
|||
} |
@ -0,0 +1,51 @@ |
|||
#pragma once |
|||
|
|||
#include "ofMain.h" |
|||
|
|||
namespace ofx { |
|||
namespace piMapper { |
|||
|
|||
class BaseJoint { |
|||
public: |
|||
BaseJoint(); |
|||
~BaseJoint(); |
|||
|
|||
void registerMouseEvents(); |
|||
void unregisterMouseEvents(); |
|||
|
|||
ofVec2f position; |
|||
bool enabled; |
|||
bool visible; |
|||
bool selected; |
|||
|
|||
void mousePressed(ofMouseEventArgs& args); |
|||
void mouseReleased(int x, int y, int button); |
|||
void mouseDragged(ofMouseEventArgs& args); |
|||
void startDrag(); |
|||
void stopDrag(); |
|||
void select(); |
|||
void unselect(); |
|||
void setClickDistance(ofVec2f newClickDistance); |
|||
bool isDragged(); |
|||
bool isSelected(); |
|||
|
|||
virtual void update() {}; |
|||
virtual void draw() {}; |
|||
virtual bool hitTest(ofVec2f position) {}; |
|||
|
|||
protected: |
|||
ofColor fillColor; |
|||
ofColor strokeColor; |
|||
ofColor fillColorSelected; |
|||
ofColor strokeColorSelected; |
|||
float strokeWidth; |
|||
ofVec2f clickDistance; // How far from the center of the joint the user has
|
|||
// clicked?
|
|||
bool bDrag; |
|||
|
|||
private: |
|||
void setDefaultColors(); |
|||
void setDefaultProperties(); |
|||
}; |
|||
} |
|||
} |
@ -0,0 +1,49 @@ |
|||
#include "CircleJoint.h" |
|||
|
|||
namespace ofx { |
|||
namespace piMapper { |
|||
|
|||
CircleJoint::CircleJoint() { setDefaultProperties(); } |
|||
|
|||
void CircleJoint::update() { |
|||
if (!enabled) return; |
|||
} |
|||
|
|||
void CircleJoint::draw() { |
|||
if (!visible) return; |
|||
if (!enabled) return; |
|||
|
|||
ofPushStyle(); |
|||
ofFill(); |
|||
|
|||
if (selected) { |
|||
ofSetColor(fillColorSelected); |
|||
} else { |
|||
ofSetColor(fillColor); |
|||
} |
|||
|
|||
ofCircle(position.x, position.y, radius); |
|||
ofNoFill(); |
|||
|
|||
if (selected) { |
|||
ofSetColor(strokeColorSelected); |
|||
} else { |
|||
ofSetColor(strokeColor); |
|||
} |
|||
|
|||
ofSetLineWidth(strokeWidth); |
|||
ofCircle(position.x, position.y, radius); |
|||
ofPopStyle(); |
|||
} |
|||
|
|||
void CircleJoint::setDefaultProperties() { radius = 10.0f; } |
|||
|
|||
bool CircleJoint::hitTest(ofVec2f pos) { |
|||
float distance = position.distance(pos); |
|||
if (distance < radius) |
|||
return true; |
|||
else |
|||
return false; |
|||
} |
|||
} |
|||
} |
@ -0,0 +1,22 @@ |
|||
#pragma once |
|||
|
|||
#include "ofMain.h" |
|||
#include "BaseJoint.h" |
|||
|
|||
namespace ofx { |
|||
namespace piMapper { |
|||
class CircleJoint : public BaseJoint { |
|||
public: |
|||
CircleJoint(); |
|||
|
|||
void update(); |
|||
void draw(); |
|||
bool hitTest(ofVec2f position); |
|||
|
|||
private: |
|||
float radius; |
|||
|
|||
void setDefaultProperties(); |
|||
}; |
|||
} |
|||
} |
@ -0,0 +1,9 @@ |
|||
#pragma once |
|||
|
|||
namespace ofx { |
|||
namespace piMapper { |
|||
struct EditorType { |
|||
enum { TEXTURE, PROJECTION }; |
|||
}; |
|||
} |
|||
} |
@ -0,0 +1,9 @@ |
|||
#pragma once |
|||
|
|||
namespace ofx { |
|||
namespace piMapper { |
|||
struct GuiMode { |
|||
enum { NONE, TEXTURE_MAPPING, PROJECTION_MAPPING, SOURCE_SELECTION }; |
|||
}; |
|||
} |
|||
} |
@ -0,0 +1,263 @@ |
|||
#include "ProjectionEditor.h" |
|||
|
|||
namespace ofx { |
|||
namespace piMapper { |
|||
ProjectionEditor::ProjectionEditor() { |
|||
surfaceManager = NULL; |
|||
bShiftKeyDown = false; |
|||
fSnapDistance = 10.0f; |
|||
enable(); |
|||
} |
|||
|
|||
ProjectionEditor::~ProjectionEditor() { |
|||
clearJoints(); |
|||
surfaceManager = NULL; |
|||
disable(); |
|||
} |
|||
|
|||
void ProjectionEditor::registerAppEvents() { |
|||
ofAddListener(ofEvents().update, this, &ProjectionEditor::update); |
|||
ofAddListener(ofEvents().messageEvent, this, &ProjectionEditor::gotMessage); |
|||
} |
|||
|
|||
void ProjectionEditor::unregisterAppEvents() { |
|||
ofRemoveListener(ofEvents().update, this, &ProjectionEditor::update); |
|||
ofRemoveListener(ofEvents().messageEvent, this, |
|||
&ProjectionEditor::gotMessage); |
|||
} |
|||
|
|||
void ProjectionEditor::registerMouseEvents() { |
|||
ofAddListener(ofEvents().mouseDragged, this, &ProjectionEditor::mouseDragged); |
|||
} |
|||
|
|||
void ProjectionEditor::unregisterMouseEvents() { |
|||
ofRemoveListener(ofEvents().mouseDragged, this, |
|||
&ProjectionEditor::mouseDragged); |
|||
} |
|||
|
|||
void ProjectionEditor::registerKeyEvents() { |
|||
ofAddListener(ofEvents().keyPressed, this, &ProjectionEditor::keyPressed); |
|||
ofAddListener(ofEvents().keyReleased, this, &ProjectionEditor::keyReleased); |
|||
} |
|||
|
|||
void ProjectionEditor::unregisterKeyEvents() { |
|||
ofRemoveListener(ofEvents().keyPressed, this, &ProjectionEditor::keyPressed); |
|||
ofRemoveListener(ofEvents().keyReleased, this, |
|||
&ProjectionEditor::keyReleased); |
|||
} |
|||
|
|||
void ProjectionEditor::enable() { |
|||
registerAppEvents(); |
|||
registerMouseEvents(); |
|||
registerKeyEvents(); |
|||
} |
|||
|
|||
void ProjectionEditor::disable() { |
|||
unregisterAppEvents(); |
|||
unregisterMouseEvents(); |
|||
unregisterKeyEvents(); |
|||
} |
|||
|
|||
void ProjectionEditor::update(ofEventArgs& args) { |
|||
// update surface if one of the joints is being dragged
|
|||
for (int i = 0; i < joints.size(); i++) { |
|||
if (joints[i]->isDragged() || joints[i]->isSelected()) { |
|||
if (surfaceManager->getSelectedSurface() != NULL) { |
|||
// update vertex to new location
|
|||
surfaceManager->getSelectedSurface()->setVertex(i, joints[i]->position); |
|||
} else { |
|||
// clear joints if there is no surface selected
|
|||
// as the remove selected surface in the surface manager
|
|||
// is not supposed to access joints here
|
|||
joints.clear(); |
|||
} |
|||
break; |
|||
} |
|||
} |
|||
} |
|||
|
|||
void ProjectionEditor::draw() { |
|||
if (surfaceManager == NULL) return; |
|||
if (surfaceManager->getSelectedSurface() == NULL) return; |
|||
if (joints.size() <= 0) createJoints(); |
|||
drawJoints(); |
|||
} |
|||
|
|||
void ProjectionEditor::mouseDragged(ofMouseEventArgs& args) { |
|||
ofVec2f mousePosition = ofVec2f(args.x, args.y); |
|||
|
|||
// Collect all vertices of the projection surfaces
|
|||
vector<ofVec3f*> allVertices; |
|||
for (int i = 0; i < surfaceManager->size(); i++) { |
|||
BaseSurface* surface = surfaceManager->getSurface(i); |
|||
if (surface == surfaceManager->getSelectedSurface()) { |
|||
continue; // Don't add vertices of selected surface
|
|||
} |
|||
for (int j = 0; j < surface->getVertices().size(); j++) { |
|||
allVertices.push_back(&surface->getVertices()[j]); |
|||
} |
|||
} |
|||
|
|||
// Snap currently dragged joint to nearest vertex
|
|||
for (int i = 0; i < joints.size(); i++) { |
|||
if (joints[i]->isDragged()) { |
|||
// Snap it!
|
|||
for (int j = 0; j < allVertices.size(); j++) { |
|||
float distance = mousePosition.distance(*allVertices[j]); |
|||
// cout << "distance: " << distance << endl;
|
|||
if (distance < fSnapDistance) { |
|||
joints[i]->position = *allVertices[j]; |
|||
ofVec2f clickDistance = joints[i]->position - ofVec2f(args.x, args.y); |
|||
joints[i]->setClickDistance(clickDistance); |
|||
break; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
|||
void ProjectionEditor::keyPressed(ofKeyEventArgs& args) { |
|||
int key = args.key; |
|||
float moveStep; |
|||
|
|||
if (bShiftKeyDown) |
|||
moveStep = 10.0f; |
|||
else |
|||
moveStep = 0.5f; |
|||
|
|||
switch (key) { |
|||
case OF_KEY_LEFT: |
|||
moveSelection(ofVec2f(-moveStep, 0.0f)); |
|||
break; |
|||
case OF_KEY_RIGHT: |
|||
moveSelection(ofVec2f(moveStep, 0.0f)); |
|||
break; |
|||
case OF_KEY_UP: |
|||
moveSelection(ofVec2f(0.0f, -moveStep)); |
|||
break; |
|||
case OF_KEY_DOWN: |
|||
moveSelection(ofVec2f(0.0f, moveStep)); |
|||
break; |
|||
case OF_KEY_SHIFT: |
|||
bShiftKeyDown = true; |
|||
break; |
|||
} |
|||
} |
|||
|
|||
void ProjectionEditor::keyReleased(ofKeyEventArgs& args) { |
|||
int key = args.key; |
|||
switch (key) { |
|||
case OF_KEY_SHIFT: |
|||
bShiftKeyDown = false; |
|||
break; |
|||
} |
|||
} |
|||
|
|||
void ProjectionEditor::gotMessage(ofMessage& msg) { |
|||
if (msg.message == "surfaceSelected") { |
|||
// refresh gui
|
|||
clearJoints(); |
|||
createJoints(); |
|||
} |
|||
} |
|||
|
|||
void ProjectionEditor::setSurfaceManager(SurfaceManager* newSurfaceManager) { |
|||
surfaceManager = newSurfaceManager; |
|||
} |
|||
|
|||
void ProjectionEditor::clearJoints() { |
|||
while (joints.size()) { |
|||
delete joints.back(); |
|||
joints.pop_back(); |
|||
} |
|||
} |
|||
|
|||
void ProjectionEditor::createJoints() { |
|||
if (surfaceManager == NULL) return; |
|||
clearJoints(); |
|||
|
|||
if (surfaceManager->getSelectedSurface() == NULL) { |
|||
ofLog(OF_LOG_WARNING, "Trying to create joints while no surface selected."); |
|||
return; |
|||
} |
|||
|
|||
vector<ofVec3f>& vertices = |
|||
surfaceManager->getSelectedSurface()->getVertices(); |
|||
|
|||
for (int i = 0; i < vertices.size(); i++) { |
|||
joints.push_back(new CircleJoint()); |
|||
joints.back()->position = ofVec2f(vertices[i].x, vertices[i].y); |
|||
} |
|||
} |
|||
|
|||
void ProjectionEditor::updateJoints() { |
|||
vector<ofVec3f>& vertices = |
|||
surfaceManager->getSelectedSurface()->getVertices(); |
|||
for (int i = 0; i < vertices.size(); i++) { |
|||
joints[i]->position = ofVec2f(vertices[i].x, vertices[i].y); |
|||
} |
|||
} |
|||
|
|||
void ProjectionEditor::unselectAllJoints() { |
|||
for (int i = 0; i < joints.size(); i++) { |
|||
joints[i]->unselect(); |
|||
} |
|||
} |
|||
|
|||
void ProjectionEditor::moveSelectedSurface(ofVec2f by) { |
|||
if (surfaceManager == NULL) return; |
|||
if (surfaceManager->getSelectedSurface() == NULL) return; |
|||
surfaceManager->getSelectedSurface()->moveBy(by); |
|||
/*vector<ofVec3f>& vertices =
|
|||
surfaceManager->getSelectedSurface()->getVertices(); |
|||
for (int i=0; i<vertices.size(); i++) { |
|||
vertices[i] += by; |
|||
}*/ |
|||
updateJoints(); |
|||
} |
|||
|
|||
void ProjectionEditor::stopDragJoints() { |
|||
for (int i = 0; i < joints.size(); i++) { |
|||
joints[i]->stopDrag(); |
|||
} |
|||
} |
|||
|
|||
void ProjectionEditor::moveSelection(ofVec2f by) { |
|||
// check if joints selected
|
|||
bool bJointSelected = false; |
|||
BaseJoint* selectedJoint; |
|||
for (int i = 0; i < joints.size(); i++) { |
|||
if (joints[i]->isSelected()) { |
|||
bJointSelected = true; |
|||
selectedJoint = joints[i]; |
|||
break; |
|||
} |
|||
} |
|||
|
|||
if (bJointSelected) { |
|||
selectedJoint->position += by; |
|||
} else { |
|||
moveSelectedSurface(by); |
|||
} |
|||
} |
|||
|
|||
void ProjectionEditor::setSnapDistance(float newSnapDistance) { |
|||
fSnapDistance = newSnapDistance; |
|||
} |
|||
|
|||
CircleJoint* ProjectionEditor::hitTestJoints(ofVec2f pos) { |
|||
for (int i = 0; i < joints.size(); i++) { |
|||
if (joints[i]->hitTest(pos)) { |
|||
return joints[i]; |
|||
} |
|||
} |
|||
return NULL; |
|||
} |
|||
|
|||
void ProjectionEditor::drawJoints() { |
|||
for (int i = 0; i < joints.size(); i++) { |
|||
joints[i]->draw(); |
|||
} |
|||
} |
|||
} |
|||
} |
@ -0,0 +1,50 @@ |
|||
#pragma once |
|||
|
|||
#include "SurfaceManager.h" |
|||
#include "CircleJoint.h" |
|||
|
|||
namespace ofx { |
|||
namespace piMapper { |
|||
class ProjectionEditor { |
|||
public: |
|||
ProjectionEditor(); |
|||
~ProjectionEditor(); |
|||
|
|||
void registerAppEvents(); |
|||
void unregisterAppEvents(); |
|||
void registerMouseEvents(); |
|||
void unregisterMouseEvents(); |
|||
void registerKeyEvents(); |
|||
void unregisterKeyEvents(); |
|||
|
|||
void enable(); |
|||
void disable(); |
|||
|
|||
void update(ofEventArgs& args); |
|||
void draw(); |
|||
void mouseDragged(ofMouseEventArgs& args); |
|||
void keyPressed(ofKeyEventArgs& args); |
|||
void keyReleased(ofKeyEventArgs& args); |
|||
void gotMessage(ofMessage& msg); |
|||
void setSurfaceManager(SurfaceManager* newSurfaceManager); |
|||
void clearJoints(); |
|||
void createJoints(); |
|||
void updateJoints(); |
|||
void unselectAllJoints(); |
|||
void moveSelectedSurface(ofVec2f by); |
|||
void stopDragJoints(); |
|||
void updateVertices(); |
|||
void moveSelection(ofVec2f by); |
|||
void setSnapDistance(float newSnapDistance); |
|||
CircleJoint* hitTestJoints(ofVec2f pos); |
|||
|
|||
private: |
|||
SurfaceManager* surfaceManager; |
|||
vector<CircleJoint*> joints; |
|||
bool bShiftKeyDown; |
|||
float fSnapDistance; |
|||
|
|||
void drawJoints(); |
|||
}; |
|||
} |
|||
} |
@ -0,0 +1,183 @@ |
|||
#include "RadioList.h" |
|||
|
|||
namespace ofx { |
|||
namespace piMapper { |
|||
RadioList::RadioList() { |
|||
storedTitle = ""; |
|||
storedSelectedItem = 0; |
|||
} |
|||
|
|||
RadioList::RadioList(vector<string>& labels, vector<string>& values) { |
|||
RadioList(); |
|||
setup(labels, values); |
|||
} |
|||
|
|||
RadioList::RadioList(string title, vector<string>& labels, vector<string>& values) { |
|||
RadioList(); |
|||
setup(title, labels, values); |
|||
} |
|||
|
|||
RadioList::~RadioList() { clear(); } |
|||
|
|||
void RadioList::setup(vector<string>& labels, vector<string>& values) { |
|||
// Copy incomming labels for later use
|
|||
storedLabels = labels; |
|||
storedValues = values; |
|||
|
|||
// Create toggles with labels from the labels arg
|
|||
int i; |
|||
for (i = 0; i < labels.size(); i++) { |
|||
ofxToggle* toggle = new ofxToggle(); |
|||
toggle->setup(false); |
|||
toggle->setName(labels[i]); |
|||
toggle->addListener(this, &RadioList::onToggleClicked); |
|||
guiGroup.add(toggle); |
|||
#if OF_VERSION_MAJOR == 0 && OF_VERSION_MINOR >= 8 && OF_VERSION_PATCH >= 2 |
|||
toggle->registerMouseEvents(); |
|||
#endif |
|||
} |
|||
} |
|||
|
|||
void RadioList::setup(string title, vector<string>& labels, vector<string>& values) { |
|||
// Store title for later use
|
|||
storedTitle = title; |
|||
guiGroup.setName(title); |
|||
setup(labels, values); |
|||
} |
|||
|
|||
void RadioList::draw() { guiGroup.draw(); } |
|||
|
|||
void RadioList::setTitle(string title) { |
|||
storedTitle = title; |
|||
guiGroup.setName(title); |
|||
} |
|||
|
|||
void RadioList::setPosition(ofPoint p) { guiGroup.setPosition(p); } |
|||
|
|||
void RadioList::setPosition(float x, float y) { guiGroup.setPosition(x, y); } |
|||
|
|||
void RadioList::selectItem(int index) { |
|||
if (index >= guiGroup.getNumControls()) { |
|||
return; |
|||
} |
|||
|
|||
unselectAll(); |
|||
|
|||
ofxToggle* toggle = static_cast<ofxToggle*>(guiGroup.getControl(index)); |
|||
toggle->removeListener(this, &RadioList::onToggleClicked); |
|||
*toggle = true; // Select the specific radio button
|
|||
toggle->addListener(this, &RadioList::onToggleClicked); |
|||
//string name = toggle->getName();
|
|||
// Throw event with value that is image path instead of name
|
|||
string value = storedValues[index]; |
|||
ofNotifyEvent(onRadioSelected, value, this); |
|||
storedSelectedItem = index; |
|||
} |
|||
|
|||
bool RadioList::selectItemByValue(std::string itemValue) { |
|||
if (itemValue == "") { |
|||
ofLogNotice("RadioList") << "Item value empty"; |
|||
return false; |
|||
} |
|||
unselectAll(); |
|||
int itemIndex = -1; |
|||
for (int i = 0; i < storedValues.size(); i++) { |
|||
if (itemValue == storedValues[i]) { |
|||
itemIndex = i; |
|||
break; |
|||
} |
|||
} |
|||
if (itemIndex >= 0) { |
|||
ofxToggle* toggle = static_cast<ofxToggle*>(guiGroup.getControl(itemIndex)); |
|||
toggle->removeListener(this, &RadioList::onToggleClicked); |
|||
*toggle = true; // Select the specific radio button
|
|||
toggle->addListener(this, &RadioList::onToggleClicked); |
|||
return true; |
|||
} |
|||
ofLogNotice("RadioList") << "Item with value " << itemValue << " not found"; |
|||
return false; |
|||
} |
|||
|
|||
void RadioList::enable() { |
|||
if (guiGroup.getNumControls() >= 0) { |
|||
clear(); |
|||
} |
|||
|
|||
// Rebuild everyting
|
|||
setup(storedTitle, storedLabels, storedValues); |
|||
|
|||
// Select the stored selected item without throwing an event
|
|||
ofxToggle* toggle = |
|||
static_cast<ofxToggle*>(guiGroup.getControl(storedSelectedItem)); |
|||
toggle->removeListener(this, &RadioList::onToggleClicked); |
|||
*toggle = true; |
|||
toggle->addListener(this, &RadioList::onToggleClicked); |
|||
|
|||
cout << "num items after enable: " << guiGroup.getNumControls() << endl; |
|||
} |
|||
|
|||
void RadioList::disable() { |
|||
// Just remove everything
|
|||
clear(); |
|||
} |
|||
|
|||
void RadioList::clear() { |
|||
int i; |
|||
for (i = 0; i < guiGroup.getNumControls(); i++) { |
|||
ofxToggle* toggle = static_cast<ofxToggle*>(guiGroup.getControl(i)); |
|||
toggle->removeListener(this, &RadioList::onToggleClicked); |
|||
delete toggle; |
|||
} |
|||
guiGroup.clear(); |
|||
} |
|||
|
|||
void RadioList::unselectAll() { |
|||
int i; |
|||
for (i = 0; i < guiGroup.getNumControls(); i++) { |
|||
ofxToggle* toggle = static_cast<ofxToggle*>(guiGroup.getControl(i)); |
|||
ofParameter<bool>* paramPtr = |
|||
static_cast<ofParameter<bool>*>(&toggle->getParameter()); |
|||
toggle->removeListener(this, &RadioList::onToggleClicked); |
|||
*toggle = false; |
|||
toggle->addListener(this, &RadioList::onToggleClicked); |
|||
} |
|||
} |
|||
|
|||
ofPoint RadioList::getPosition() { return guiGroup.getPosition(); } |
|||
|
|||
float RadioList::getWidth() { return guiGroup.getWidth(); } |
|||
|
|||
float RadioList::getHeight() { return guiGroup.getHeight(); } |
|||
|
|||
string RadioList::getTitle() { return guiGroup.getName(); } |
|||
|
|||
string RadioList::getItemName(int index) { |
|||
if (index >= guiGroup.getNumControls()) { |
|||
return ""; |
|||
} |
|||
|
|||
ofxToggle* toggle = static_cast<ofxToggle*>(guiGroup.getControl(index)); |
|||
return toggle->getName(); |
|||
} |
|||
|
|||
int RadioList::size() { return storedValues.size(); } |
|||
|
|||
void RadioList::onToggleClicked(bool& toggleValue) |
|||
{ |
|||
unselectAll(); |
|||
|
|||
// Search for the actual toggle triggering the event
|
|||
int i; |
|||
for (i = 0; i < guiGroup.getNumControls(); i++) { |
|||
ofxToggle* toggle = static_cast<ofxToggle*>(guiGroup.getControl(i)); |
|||
ofParameter<bool>* paramPtr = |
|||
static_cast<ofParameter<bool>*>(&toggle->getParameter()); |
|||
|
|||
if (&(paramPtr->get()) == &toggleValue) { |
|||
selectItem(i); |
|||
break; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
@ -0,0 +1,53 @@ |
|||
#pragma once |
|||
|
|||
#include "ofGraphics.h" |
|||
#include "ofxGuiGroup.h" |
|||
#include "ofxToggle.h" |
|||
#include "ofxLabel.h" |
|||
|
|||
namespace ofx { |
|||
namespace piMapper { |
|||
class RadioList { |
|||
public: |
|||
RadioList(); |
|||
RadioList(vector<string>& labels, vector<string>& values); |
|||
RadioList(string title, vector<string>& labels, vector<string>& values); |
|||
~RadioList(); |
|||
|
|||
void setup(vector<string> &labels, vector<string>& values); |
|||
void setup(string title, vector<string>& labels, vector<string>& values); |
|||
void draw(); |
|||
void setTitle(string title); |
|||
void setPosition(ofPoint p); |
|||
void setPosition(float x, float y); |
|||
void selectItem(int index); |
|||
bool selectItemByValue(std::string itemValue); |
|||
void enable(); |
|||
void disable(); |
|||
void clear(); |
|||
void unselectAll(); |
|||
ofPoint getPosition(); |
|||
float getWidth(); |
|||
float getHeight(); |
|||
string getTitle(); |
|||
string getItemName(int index); |
|||
int size(); |
|||
|
|||
// This event notifies about a toggle being selected and passes it's name to
|
|||
// the listeners.
|
|||
// Use ofAddListener(RadioListInstance.radioSelectedEvent, listenerClassPtr,
|
|||
// &listenerClass::listenerMethod)
|
|||
// to listen to this. Listner method void listenerMethod(string & radioName)
|
|||
ofEvent<string> onRadioSelected; |
|||
|
|||
private: |
|||
vector<string> storedLabels; |
|||
vector<string> storedValues; |
|||
string storedTitle; |
|||
ofxGuiGroup guiGroup; |
|||
int storedSelectedItem; |
|||
|
|||
void onToggleClicked(bool &toggleValue); |
|||
}; |
|||
} |
|||
} |
@ -0,0 +1,271 @@ |
|||
#include "SourcesEditor.h" |
|||
|
|||
namespace ofx { |
|||
namespace piMapper { |
|||
SourcesEditor::SourcesEditor() { |
|||
init(); |
|||
// Create new MediaServer instance,
|
|||
// we will need to clear this in the deconstr
|
|||
mediaServer = new MediaServer(); |
|||
isMediaServerExternal = false; |
|||
addMediaServerListeners(); |
|||
} |
|||
|
|||
SourcesEditor::SourcesEditor(MediaServer* externalMediaServer) { |
|||
init(); |
|||
// Assign external MediaServer instance pointer
|
|||
mediaServer = externalMediaServer; |
|||
isMediaServerExternal = true; |
|||
addMediaServerListeners(); |
|||
} |
|||
|
|||
SourcesEditor::~SourcesEditor() { |
|||
unregisterAppEvents(); |
|||
delete imageSelector; |
|||
delete videoSelector; |
|||
removeMediaServerListeners(); |
|||
clearMediaServer(); |
|||
} |
|||
|
|||
void SourcesEditor::registerAppEvents() { |
|||
ofAddListener(ofEvents().setup, this, &SourcesEditor::setup); |
|||
} |
|||
|
|||
void SourcesEditor::unregisterAppEvents() { |
|||
ofRemoveListener(ofEvents().setup, this, &SourcesEditor::setup); |
|||
} |
|||
|
|||
void SourcesEditor::setup(ofEventArgs& args) { |
|||
imageSelector = new RadioList(); |
|||
videoSelector = new RadioList(); |
|||
|
|||
// Get media count
|
|||
int numImages = mediaServer->getNumImages(); |
|||
int numVideos = mediaServer->getNumVideos(); |
|||
|
|||
// Depending on media count, decide what to load and initialize
|
|||
if (numImages) { |
|||
// Get image names from media server
|
|||
vector<string> imageNames = mediaServer->getImageNames(); |
|||
imageSelector->setup("Images", imageNames, mediaServer->getImagePaths()); |
|||
ofAddListener(imageSelector->onRadioSelected, this, &SourcesEditor::handleImageSelected); |
|||
} |
|||
if (numVideos) { |
|||
vector<string> videoNames = mediaServer->getVideoNames(); |
|||
videoSelector->setup("Videos", videoNames, mediaServer->getVideoPaths()); |
|||
ofAddListener(videoSelector->onRadioSelected, this, &SourcesEditor::handleVideoSelected); |
|||
} |
|||
|
|||
if (numImages) { |
|||
imageSelector->setPosition(20, 20); |
|||
if (numVideos) { |
|||
videoSelector->setPosition(250, 20); |
|||
} |
|||
} else { |
|||
if (numVideos) { |
|||
videoSelector->setPosition(20, 20); |
|||
} |
|||
} |
|||
|
|||
} |
|||
|
|||
void SourcesEditor::draw() { |
|||
// Don't draw if there is no source selected
|
|||
if (surfaceManager->getSelectedSurface() == NULL) { |
|||
ofLogNotice("SourcesEditor") << "No surface selected"; |
|||
return; |
|||
} |
|||
if (imageSelector->size()) { |
|||
imageSelector->draw(); |
|||
} |
|||
if (videoSelector->size()) { |
|||
videoSelector->draw(); |
|||
} |
|||
|
|||
} |
|||
|
|||
void SourcesEditor::disable() { |
|||
if (imageSelector->size()) { |
|||
imageSelector->disable(); |
|||
} |
|||
if (videoSelector->size()) { |
|||
videoSelector->disable(); |
|||
} |
|||
} |
|||
|
|||
void SourcesEditor::enable() { |
|||
// Don't enable if there is no surface selected
|
|||
if (surfaceManager->getSelectedSurface() == NULL) { |
|||
ofLogNotice("SourcesEditor") << "No surface selected. Not enabling and not showing source list."; |
|||
return; |
|||
} |
|||
if (imageSelector->size()) { |
|||
imageSelector->enable(); |
|||
} |
|||
if (videoSelector->size()) { |
|||
videoSelector->enable(); |
|||
} |
|||
BaseSource* source = surfaceManager->getSelectedSurface()->getSource(); |
|||
selectSourceRadioButton(source->getPath()); |
|||
} |
|||
|
|||
void SourcesEditor::setSurfaceManager(SurfaceManager* newSurfaceManager) { |
|||
surfaceManager = newSurfaceManager; |
|||
} |
|||
|
|||
void SourcesEditor::setMediaServer(MediaServer* newMediaServer) { |
|||
// If the new media server is not valid
|
|||
if (newMediaServer == NULL) { |
|||
// Log an error and return from the routine
|
|||
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::selectSourceRadioButton(std::string& sourcePath) { |
|||
if (sourcePath == "") { |
|||
ofLogNotice("SourcesEditor") << "Path is empty"; |
|||
if (imageSelector->size()) { |
|||
imageSelector->unselectAll(); |
|||
} |
|||
if (videoSelector->size()) { |
|||
videoSelector->unselectAll(); |
|||
} |
|||
return; |
|||
} else { |
|||
// Check image selector first
|
|||
bool imageRadioSelected = false; |
|||
bool videoRadioSelected = false; |
|||
if (imageSelector->size()) { |
|||
imageRadioSelected = imageSelector->selectItemByValue(sourcePath); |
|||
} |
|||
if (videoSelector->size()) { |
|||
videoRadioSelected = videoSelector->selectItemByValue(sourcePath); |
|||
} |
|||
if (imageRadioSelected || videoRadioSelected) { |
|||
return; |
|||
} |
|||
// Log warning if we are still here
|
|||
ofLogWarning("SourcesEditor") << "Could not find option in any of the source lists"; |
|||
} |
|||
} |
|||
|
|||
void SourcesEditor::init() { |
|||
mediaServer = NULL; // Pointers to NULL pointer so we can check later
|
|||
isMediaServerExternal = false; |
|||
registerAppEvents(); |
|||
} |
|||
|
|||
void SourcesEditor::addMediaServerListeners() { |
|||
// Check if the media server is valid
|
|||
if (mediaServer == NULL) { |
|||
ofLogError("SourcesEditor::addMediaServerListeners", "Media server not set"); |
|||
return; |
|||
} |
|||
// Add listeners to custom events of the media server
|
|||
ofAddListener(mediaServer->onImageAdded, this, &SourcesEditor::handleImageAdded); |
|||
ofAddListener(mediaServer->onImageRemoved, this, &SourcesEditor::handleImageRemoved); |
|||
ofAddListener(mediaServer->onVideoAdded, this, &SourcesEditor::handleVideoAdded); |
|||
ofAddListener(mediaServer->onVideoRemoved, this, &SourcesEditor::handleVideoRemoved); |
|||
ofAddListener(mediaServer->onImageLoaded, this, &SourcesEditor::handleImageLoaded); |
|||
ofAddListener(mediaServer->onImageUnloaded, this, &SourcesEditor::handleImageUnloaded); |
|||
|
|||
} |
|||
|
|||
void SourcesEditor::removeMediaServerListeners() { |
|||
// Check if the media server is valid
|
|||
if (mediaServer == NULL) { |
|||
ofLogError("SourcesEditor::addMediaServerListeners", "Media server not set"); |
|||
return; |
|||
} |
|||
// Remove listeners to custom events of the media server
|
|||
ofRemoveListener(mediaServer->onImageAdded, this, &SourcesEditor::handleImageAdded); |
|||
ofRemoveListener(mediaServer->onImageRemoved, this, &SourcesEditor::handleImageRemoved); |
|||
ofRemoveListener(mediaServer->onVideoAdded, this, &SourcesEditor::handleVideoAdded); |
|||
ofRemoveListener(mediaServer->onVideoRemoved, this, &SourcesEditor::handleVideoRemoved); |
|||
ofRemoveListener(mediaServer->onImageLoaded, this, &SourcesEditor::handleImageLoaded); |
|||
ofRemoveListener(mediaServer->onImageUnloaded, this, &SourcesEditor::handleImageUnloaded); |
|||
} |
|||
|
|||
void SourcesEditor::handleImageSelected(string& imagePath) { |
|||
// Unselect video item if any selected
|
|||
videoSelector->unselectAll(); |
|||
BaseSurface* surface = surfaceManager->getSelectedSurface(); |
|||
if (surface == NULL) { |
|||
ofLogNotice("SourcesEditor") << "No surface selected"; |
|||
return; |
|||
} |
|||
// Unload old media
|
|||
BaseSource* source = surface->getSource(); |
|||
if (source->isLoadable()) { |
|||
mediaServer->unloadMedia(source->getPath()); |
|||
} |
|||
// Load new image
|
|||
surface->setSource(mediaServer->loadImage(imagePath)); |
|||
} |
|||
|
|||
void SourcesEditor::handleVideoSelected(string& videoPath) { |
|||
// Unselect image item if any selected
|
|||
imageSelector->unselectAll(); |
|||
BaseSurface* surface = surfaceManager->getSelectedSurface(); |
|||
if (surface == NULL) { |
|||
ofLogNotice("SourcesEditor") << "No surface selected"; |
|||
return; |
|||
} |
|||
// Unload old media
|
|||
BaseSource* source = surface->getSource(); |
|||
if (source->isLoadable()) { |
|||
mediaServer->unloadMedia(source->getPath()); |
|||
} |
|||
// Load new video
|
|||
surface->setSource(mediaServer->loadVideo(videoPath)); |
|||
} |
|||
|
|||
void SourcesEditor::clearMediaServer() { |
|||
// If mediaServer is local, clear it
|
|||
if (!isMediaServerExternal) { |
|||
// Clear all loaded sources
|
|||
mediaServer->clear(); |
|||
// Destroy the pointer and set it to NULL pointer
|
|||
delete mediaServer; |
|||
mediaServer = NULL; |
|||
} |
|||
} |
|||
|
|||
void SourcesEditor::handleImageAdded(string& path) { |
|||
cout << "image added: " << path << endl; |
|||
} |
|||
|
|||
void SourcesEditor::handleImageRemoved(string& path) { |
|||
cout << "image removed: " << path << endl; |
|||
} |
|||
|
|||
void SourcesEditor::handleVideoAdded(string& path) { |
|||
cout << "video added: " << path << endl; |
|||
} |
|||
|
|||
void SourcesEditor::handleVideoRemoved(string& path) { |
|||
cout << "video removed: " << path << endl; |
|||
} |
|||
|
|||
void SourcesEditor::handleImageLoaded(string& path) { |
|||
cout << "Image loaded: " << path << endl; |
|||
|
|||
// Test image unload
|
|||
// mediaServer->unloadImage(path);
|
|||
|
|||
//BaseSource* source = mediaServer->getSourceByPath(path);
|
|||
//surfaceManager->getSelectedSurface()->setSource(source);
|
|||
} |
|||
|
|||
void SourcesEditor::handleImageUnloaded(string& path) { |
|||
cout << "Image unloaded: " << path << endl; |
|||
} |
|||
} |
|||
} |
@ -0,0 +1,73 @@ |
|||
#pragma once |
|||
|
|||
#include "ofGraphics.h" |
|||
#include "ofEvents.h" |
|||
#include "SurfaceManager.h" |
|||
#include "RadioList.h" |
|||
#include "MediaServer.h" |
|||
|
|||
namespace ofx { |
|||
namespace piMapper { |
|||
class SourcesEditor { |
|||
public: |
|||
// Default contructor that initializes media server locally,
|
|||
// thus requiring to delete the media server from memory on deconstr
|
|||
SourcesEditor(); |
|||
|
|||
// Alternative constructor that allows to assign external media server
|
|||
SourcesEditor(MediaServer* externalMediaServer); |
|||
~SourcesEditor(); |
|||
|
|||
void registerAppEvents(); |
|||
void unregisterAppEvents(); |
|||
|
|||
void setup(ofEventArgs& args); |
|||
void draw(); |
|||
void loadImage(string name, string path); |
|||
void disable(); |
|||
void enable(); |
|||
void setSurfaceManager(SurfaceManager* newSurfaceManager); |
|||
|
|||
// Sets external MediaServer
|
|||
void setMediaServer(MediaServer* newMediaServer); |
|||
//void selectImageSourceRadioButton(string name);
|
|||
void selectSourceRadioButton(std::string& sourcePath); |
|||
|
|||
int getLoadedTexCount(); |
|||
ofTexture* getTexture(int index); |
|||
|
|||
private: |
|||
MediaServer* mediaServer; |
|||
SurfaceManager* surfaceManager; |
|||
RadioList* imageSelector; |
|||
RadioList* videoSelector; |
|||
|
|||
// Is the media server pointer local or from somewhere else?
|
|||
// We use this to determine if we are allowed to clear media server locally.
|
|||
bool isMediaServerExternal; |
|||
|
|||
// Init handles variable initialization in all constructors
|
|||
void init(); |
|||
|
|||
// Methods for adding and removing listeners to the media server
|
|||
void addMediaServerListeners(); |
|||
void removeMediaServerListeners(); |
|||
|
|||
// Handles GUI event, whenever someone has clicked on a radio button
|
|||
void handleImageSelected(string& imagePath); |
|||
void handleVideoSelected(string& videoPath); |
|||
|
|||
// Careful clearing of the media server,
|
|||
// clears only if the media server has been initialized locally
|
|||
void clearMediaServer(); |
|||
|
|||
// MediaServer event handlers
|
|||
void handleImageAdded(string& path); |
|||
void handleImageRemoved(string& path); |
|||
void handleVideoAdded(string& path); |
|||
void handleVideoRemoved(string& path); |
|||
void handleImageLoaded(string& path); |
|||
void handleImageUnloaded(string& path); |
|||
}; |
|||
} |
|||
} |
@ -0,0 +1,234 @@ |
|||
#include "TextureEditor.h" |
|||
|
|||
namespace ofx { |
|||
namespace piMapper { |
|||
TextureEditor::TextureEditor() { |
|||
clear(); |
|||
enable(); |
|||
} |
|||
|
|||
TextureEditor::~TextureEditor() { |
|||
clear(); |
|||
disable(); |
|||
} |
|||
|
|||
void TextureEditor::registerAppEvents() { |
|||
ofAddListener(ofEvents().update, this, &TextureEditor::update); |
|||
} |
|||
|
|||
void TextureEditor::unregisterAppEvents() { |
|||
ofRemoveListener(ofEvents().update, this, &TextureEditor::update); |
|||
} |
|||
|
|||
void TextureEditor::registerKeyEvents() { |
|||
ofAddListener(ofEvents().keyPressed, this, &TextureEditor::keyPressed); |
|||
ofAddListener(ofEvents().keyReleased, this, &TextureEditor::keyReleased); |
|||
} |
|||
|
|||
void TextureEditor::unregisterKeyEvents() { |
|||
ofRemoveListener(ofEvents().keyPressed, this, &TextureEditor::keyPressed); |
|||
ofRemoveListener(ofEvents().keyReleased, this, &TextureEditor::keyReleased); |
|||
} |
|||
|
|||
void TextureEditor::enable() { |
|||
registerAppEvents(); |
|||
registerKeyEvents(); |
|||
bShiftKeyDown = false; |
|||
} |
|||
|
|||
void TextureEditor::disable() { |
|||
unregisterAppEvents(); |
|||
unregisterKeyEvents(); |
|||
} |
|||
|
|||
void TextureEditor::update(ofEventArgs& args) { |
|||
if (surface == NULL) return; |
|||
|
|||
// update surface if one of the joints is being dragged
|
|||
ofVec2f textureSize = ofVec2f(surface->getSource()->getTexture()->getWidth(), |
|||
surface->getSource()->getTexture()->getHeight()); |
|||
|
|||
// Get selected joint index
|
|||
int selectedJointIndex = 0; |
|||
bool bJointSelected = false; |
|||
for (int i = 0; i < joints.size(); i++) { |
|||
if (joints[i]->isDragged() || joints[i]->isSelected()) { |
|||
selectedJointIndex = i; |
|||
bJointSelected = true; |
|||
break; |
|||
} |
|||
} // for
|
|||
|
|||
// Constrain quad texture selection
|
|||
if (joints.size() == 4) { |
|||
if (bJointSelected) { |
|||
constrainJointsToQuad(selectedJointIndex); |
|||
|
|||
for (int i = 0; i < joints.size(); i++) { |
|||
surface->setTexCoord(i, joints[i]->position / textureSize); |
|||
} |
|||
} // if
|
|||
} else { |
|||
if (bJointSelected) { |
|||
surface->setTexCoord(selectedJointIndex, joints[selectedJointIndex]->position / textureSize); |
|||
} |
|||
} // else
|
|||
} |
|||
|
|||
void TextureEditor::keyPressed(ofKeyEventArgs& args) { |
|||
int key = args.key; |
|||
float moveStep; |
|||
|
|||
if (bShiftKeyDown) |
|||
moveStep = 10.0f; |
|||
else |
|||
moveStep = 0.5f; |
|||
|
|||
switch (key) { |
|||
case OF_KEY_LEFT: |
|||
moveSelection(ofVec2f(-moveStep, 0.0f)); |
|||
break; |
|||
case OF_KEY_RIGHT: |
|||
moveSelection(ofVec2f(moveStep, 0.0f)); |
|||
break; |
|||
case OF_KEY_UP: |
|||
moveSelection(ofVec2f(0.0f, -moveStep)); |
|||
break; |
|||
case OF_KEY_DOWN: |
|||
moveSelection(ofVec2f(0.0f, moveStep)); |
|||
break; |
|||
case OF_KEY_SHIFT: |
|||
bShiftKeyDown = true; |
|||
break; |
|||
} |
|||
} |
|||
|
|||
void TextureEditor::keyReleased(ofKeyEventArgs& args) { |
|||
int key = args.key; |
|||
switch (key) { |
|||
case OF_KEY_SHIFT: |
|||
bShiftKeyDown = false; |
|||
break; |
|||
} |
|||
} |
|||
|
|||
void TextureEditor::draw() { |
|||
if (surface == NULL) return; |
|||
|
|||
drawJoints(); |
|||
} |
|||
|
|||
void TextureEditor::drawJoints() { |
|||
for (int i = 0; i < joints.size(); i++) { |
|||
joints[i]->draw(); |
|||
} |
|||
} |
|||
|
|||
void TextureEditor::setSurface(BaseSurface* newSurface) { |
|||
surface = newSurface; |
|||
createJoints(); |
|||
} |
|||
|
|||
void TextureEditor::clear() { |
|||
surface = NULL; |
|||
clearJoints(); |
|||
} |
|||
|
|||
void TextureEditor::createJoints() { |
|||
if (surface == NULL) return; |
|||
clearJoints(); |
|||
vector<ofVec2f>& texCoords = surface->getTexCoords(); |
|||
ofVec2f textureSize = ofVec2f(surface->getSource()->getTexture()->getWidth(), |
|||
surface->getSource()->getTexture()->getHeight()); |
|||
|
|||
for (int i = 0; i < texCoords.size(); i++) { |
|||
joints.push_back(new CircleJoint()); |
|||
joints.back()->position = texCoords[i] * textureSize; |
|||
} |
|||
} |
|||
|
|||
void TextureEditor::clearJoints() { |
|||
while (joints.size()) { |
|||
delete joints.back(); |
|||
joints.pop_back(); |
|||
} |
|||
} |
|||
|
|||
void TextureEditor::unselectAllJoints() { |
|||
for (int i = 0; i < joints.size(); i++) { |
|||
joints[i]->unselect(); |
|||
} |
|||
} |
|||
|
|||
void TextureEditor::moveTexCoords(ofVec2f by) { |
|||
if (surface == NULL) return; |
|||
vector<ofVec2f>& texCoords = surface->getTexCoords(); |
|||
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; |
|||
} |
|||
} |
|||
|
|||
void TextureEditor::stopDragJoints() { |
|||
for (int i = 0; i < joints.size(); i++) { |
|||
joints[i]->stopDrag(); |
|||
} |
|||
} |
|||
|
|||
void TextureEditor::moveSelection(ofVec2f by) { |
|||
// check if joints selected
|
|||
bool bJointSelected = false; |
|||
BaseJoint* selectedJoint; |
|||
for (int i = 0; i < joints.size(); i++) { |
|||
if (joints[i]->isSelected()) { |
|||
bJointSelected = true; |
|||
selectedJoint = joints[i]; |
|||
break; |
|||
} |
|||
} |
|||
|
|||
if (bJointSelected) { |
|||
selectedJoint->position += by; |
|||
} else { |
|||
moveTexCoords(by); |
|||
} |
|||
} |
|||
|
|||
void TextureEditor::constrainJointsToQuad(int selectedJointIndex) |
|||
{ |
|||
switch (selectedJointIndex) { |
|||
case 0: |
|||
joints[1]->position = ofVec2f(joints[1]->position.x, joints[0]->position.y); |
|||
joints[2]->position = ofVec2f(joints[1]->position.x, joints[3]->position.y); |
|||
joints[3]->position = ofVec2f(joints[0]->position.x, joints[3]->position.y); |
|||
break; |
|||
case 1: |
|||
joints[0]->position = ofVec2f(joints[0]->position.x, joints[1]->position.y); |
|||
joints[2]->position = ofVec2f(joints[1]->position.x, joints[2]->position.y); |
|||
joints[3]->position = ofVec2f(joints[0]->position.x, joints[2]->position.y); |
|||
break; |
|||
case 2: |
|||
joints[1]->position = ofVec2f(joints[2]->position.x, joints[1]->position.y); |
|||
joints[3]->position = ofVec2f(joints[3]->position.x, joints[2]->position.y); |
|||
joints[0]->position = ofVec2f(joints[3]->position.x, joints[1]->position.y); |
|||
break; |
|||
case 3: |
|||
joints[0]->position = ofVec2f(joints[3]->position.x, joints[0]->position.y); |
|||
joints[2]->position = ofVec2f(joints[2]->position.x, joints[3]->position.y); |
|||
joints[1]->position = ofVec2f(joints[2]->position.x, joints[0]->position.y); |
|||
break; |
|||
} // switch
|
|||
} |
|||
|
|||
CircleJoint* TextureEditor::hitTestJoints(ofVec2f pos) { |
|||
for (int i = 0; i < joints.size(); i++) { |
|||
if (joints[i]->hitTest(pos)) { |
|||
return joints[i]; |
|||
} |
|||
} |
|||
return NULL; |
|||
} |
|||
} |
|||
} |
@ -0,0 +1,44 @@ |
|||
#pragma once |
|||
|
|||
#include "ofEvents.h" |
|||
|
|||
#include "BaseSurface.h" |
|||
#include "CircleJoint.h" |
|||
|
|||
namespace ofx { |
|||
namespace piMapper { |
|||
class TextureEditor { |
|||
public: |
|||
TextureEditor(); |
|||
~TextureEditor(); |
|||
|
|||
void registerAppEvents(); |
|||
void unregisterAppEvents(); |
|||
void registerKeyEvents(); |
|||
void unregisterKeyEvents(); |
|||
void enable(); |
|||
void disable(); |
|||
|
|||
void update(ofEventArgs& args); |
|||
void keyPressed(ofKeyEventArgs& args); |
|||
void keyReleased(ofKeyEventArgs& args); |
|||
void draw(); |
|||
void drawJoints(); |
|||
void setSurface(BaseSurface* newSurface); |
|||
void clear(); |
|||
void createJoints(); |
|||
void clearJoints(); |
|||
void unselectAllJoints(); |
|||
void moveTexCoords(ofVec2f by); |
|||
void stopDragJoints(); |
|||
void moveSelection(ofVec2f by); |
|||
void constrainJointsToQuad(int selectedJointIndex); |
|||
CircleJoint* hitTestJoints(ofVec2f pos); |
|||
|
|||
private: |
|||
BaseSurface* surface; |
|||
vector<CircleJoint*> joints; |
|||
bool bShiftKeyDown; |
|||
}; |
|||
} |
|||
} |
@ -1,99 +0,0 @@ |
|||
#include "ofxBaseJoint.h" |
|||
|
|||
ofxBaseJoint::ofxBaseJoint() |
|||
{ |
|||
setDefaultColors(); |
|||
setDefaultProperties(); |
|||
registerMouseEvents(); |
|||
} |
|||
|
|||
ofxBaseJoint::~ofxBaseJoint() |
|||
{ |
|||
unregisterMouseEvents(); |
|||
} |
|||
|
|||
void ofxBaseJoint::registerMouseEvents() |
|||
{ |
|||
ofAddListener(ofEvents().mousePressed, this, &ofxBaseJoint::mousePressed); |
|||
ofAddListener(ofEvents().mouseDragged, this, &ofxBaseJoint::mouseDragged); |
|||
} |
|||
|
|||
void ofxBaseJoint::unregisterMouseEvents() |
|||
{ |
|||
ofRemoveListener(ofEvents().mousePressed, this, &ofxBaseJoint::mousePressed); |
|||
ofRemoveListener(ofEvents().mouseDragged, this, &ofxBaseJoint::mouseDragged); |
|||
} |
|||
|
|||
void ofxBaseJoint::mousePressed(ofMouseEventArgs& args) |
|||
{ |
|||
if ( hitTest(ofVec2f(args.x, args.y)) ) { |
|||
//selected = true;
|
|||
clickDistance = position - ofVec2f(args.x, args.y); |
|||
//startDrag();
|
|||
} |
|||
} |
|||
|
|||
void ofxBaseJoint::mouseReleased(int x, int y, int button) |
|||
{ |
|||
stopDrag(); |
|||
} |
|||
|
|||
void ofxBaseJoint::mouseDragged(ofMouseEventArgs& args) |
|||
{ |
|||
if ( !bDrag ) return; |
|||
position = ofVec2f(args.x, args.y) + clickDistance; |
|||
} |
|||
|
|||
void ofxBaseJoint::startDrag() |
|||
{ |
|||
bDrag = true; |
|||
} |
|||
|
|||
void ofxBaseJoint::stopDrag() |
|||
{ |
|||
bDrag = false; |
|||
} |
|||
|
|||
void ofxBaseJoint::select() |
|||
{ |
|||
selected = true; |
|||
} |
|||
|
|||
void ofxBaseJoint::unselect() |
|||
{ |
|||
selected = false; |
|||
} |
|||
|
|||
void ofxBaseJoint::setClickDistance(ofVec2f newClickDistance) |
|||
{ |
|||
clickDistance = newClickDistance; |
|||
} |
|||
|
|||
bool ofxBaseJoint::isDragged() |
|||
{ |
|||
return bDrag; |
|||
} |
|||
|
|||
bool ofxBaseJoint::isSelected() |
|||
{ |
|||
return selected; |
|||
} |
|||
|
|||
void ofxBaseJoint::setDefaultColors() |
|||
{ |
|||
fillColor = ofColor(0, 255, 255, 0); |
|||
strokeColor = ofColor(255, 255, 255); |
|||
fillColorSelected = ofColor(255, 255, 0, 0); |
|||
strokeColorSelected = ofColor(255, 0, 0); |
|||
} |
|||
|
|||
void ofxBaseJoint::setDefaultProperties() |
|||
{ |
|||
enabled = true; |
|||
visible = true; |
|||
position = ofVec2f(20.0f, 20.0f); |
|||
clickDistance = ofVec2f(0.0f, 0.0f); |
|||
bDrag = false; |
|||
selected = false; |
|||
strokeWidth = 1.5f; |
|||
} |
@ -1,48 +0,0 @@ |
|||
#ifndef H_OFX_BASE_JOINT |
|||
#define H_OFX_BASE_JOINT |
|||
|
|||
#include "ofMain.h" |
|||
|
|||
class ofxBaseJoint { |
|||
public: |
|||
ofxBaseJoint(); |
|||
~ofxBaseJoint(); |
|||
|
|||
void registerMouseEvents(); |
|||
void unregisterMouseEvents(); |
|||
|
|||
ofVec2f position; |
|||
bool enabled; |
|||
bool visible; |
|||
bool selected; |
|||
|
|||
void mousePressed(ofMouseEventArgs& args); |
|||
void mouseReleased(int x, int y, int button); |
|||
void mouseDragged(ofMouseEventArgs& args); |
|||
void startDrag(); |
|||
void stopDrag(); |
|||
void select(); |
|||
void unselect(); |
|||
void setClickDistance(ofVec2f newClickDistance); |
|||
bool isDragged(); |
|||
bool isSelected(); |
|||
|
|||
virtual void update(){}; |
|||
virtual void draw(){}; |
|||
virtual bool hitTest(ofVec2f position){}; |
|||
|
|||
protected: |
|||
ofColor fillColor; |
|||
ofColor strokeColor; |
|||
ofColor fillColorSelected; |
|||
ofColor strokeColorSelected; |
|||
float strokeWidth; |
|||
ofVec2f clickDistance; // How far from the center of the joint the user has clicked?
|
|||
bool bDrag; |
|||
|
|||
private: |
|||
void setDefaultColors(); |
|||
void setDefaultProperties(); |
|||
}; |
|||
|
|||
#endif |
@ -1,72 +0,0 @@ |
|||
#include "ofxBaseSurface.h" |
|||
|
|||
ofxBaseSurface::ofxBaseSurface() |
|||
{ |
|||
ofEnableNormalizedTexCoords(); |
|||
createDefaultTexture(); |
|||
} |
|||
|
|||
void ofxBaseSurface::createDefaultTexture() |
|||
{ |
|||
ofPixels pixels; |
|||
pixels.allocate(500, 500, 1); |
|||
for ( int i=0; i<pixels.size(); i++ ) { |
|||
pixels[i] = 255; |
|||
} |
|||
int squareSize = 10; // size of each test pattern square
|
|||
bool sy = false; |
|||
for ( int y=0; y<pixels.getWidth(); y+=squareSize ) { |
|||
bool sx = false; |
|||
for ( int x=0; x<pixels.getHeight(); x+=squareSize ) { |
|||
for ( int yi=0; yi<squareSize; yi++ ) { |
|||
for ( int xi=0; xi<squareSize; xi++ ){ |
|||
if ( sx && sy ) pixels[(y+yi)*pixels.getWidth()+x+xi] = 255; |
|||
else if ( sx && !sy ) pixels[(y+yi)*pixels.getWidth()+x+xi] = 0; |
|||
else if ( !sx && sy ) pixels[(y+yi)*pixels.getWidth()+x+xi] = 0; |
|||
else pixels[(y+yi)*pixels.getWidth()+x+xi] = 255; |
|||
} |
|||
} |
|||
sx = !sx; |
|||
} |
|||
sy = !sy; |
|||
} |
|||
|
|||
// load pixels into texture
|
|||
defaultTexture.loadData(pixels); |
|||
|
|||
// Assign default texture to texture pointer
|
|||
texture = &defaultTexture; |
|||
} |
|||
|
|||
void ofxBaseSurface::drawTexture(ofVec2f position) |
|||
{ |
|||
ofMesh texMesh; |
|||
texMesh.addVertex(position); |
|||
texMesh.addVertex(position + ofVec2f(texture->getWidth(), 0.0f)); |
|||
texMesh.addVertex(position + ofVec2f(texture->getWidth(), texture->getHeight())); |
|||
texMesh.addVertex(position + ofVec2f(0.0f, texture->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(); |
|||
texMesh.draw(); |
|||
texture->unbind(); |
|||
} |
|||
|
|||
void ofxBaseSurface::setTexture(ofTexture *texturePtr) |
|||
{ |
|||
texture = texturePtr; |
|||
} |
|||
|
|||
ofTexture* ofxBaseSurface::getTexture() |
|||
{ |
|||
return texture; |
|||
} |
|||
|
|||
ofTexture* ofxBaseSurface::getDefaultTexture() |
|||
{ |
|||
return &defaultTexture; |
|||
} |
@ -1,39 +0,0 @@ |
|||
#ifndef H_OFX_BASE_SURFACE |
|||
#define H_OFX_BASE_SURFACE |
|||
|
|||
#include "ofMain.h" |
|||
#include <string> |
|||
|
|||
using namespace std; |
|||
|
|||
class ofxBaseSurface |
|||
{ |
|||
public: |
|||
ofxBaseSurface(); |
|||
virtual void setup(){}; |
|||
virtual void draw(){}; |
|||
virtual void setVertex(int index, ofVec2f p){}; |
|||
virtual void setTexCoord(int index, ofVec2f t){}; |
|||
virtual int getType(){}; |
|||
virtual bool hitTest(ofVec2f p){}; |
|||
virtual ofPolyline getHitArea(){}; |
|||
virtual ofPolyline getTextureHitArea(){}; |
|||
virtual vector<ofVec3f>& getVertices(){}; |
|||
virtual vector<ofVec2f>& getTexCoords(){}; |
|||
|
|||
// Draws a texture using ofMesh
|
|||
void drawTexture(ofVec2f position); |
|||
void setTexture(ofTexture* texturePtr); |
|||
|
|||
ofTexture* getTexture(); |
|||
ofTexture* getDefaultTexture(); |
|||
|
|||
protected: |
|||
ofMesh mesh; |
|||
ofTexture* texture; |
|||
ofTexture defaultTexture; |
|||
|
|||
void createDefaultTexture(); |
|||
}; |
|||
|
|||
#endif |
@ -1,51 +0,0 @@ |
|||
#include "ofxCircleJoint.h" |
|||
|
|||
ofxCircleJoint::ofxCircleJoint() |
|||
{ |
|||
setDefaultProperties(); |
|||
} |
|||
|
|||
void ofxCircleJoint::update() |
|||
{ |
|||
if (!enabled) return; |
|||
} |
|||
|
|||
void ofxCircleJoint::draw() |
|||
{ |
|||
if (!visible) return; |
|||
if (!enabled) return; |
|||
|
|||
ofPushStyle(); |
|||
ofFill(); |
|||
|
|||
if ( selected ) { |
|||
ofSetColor(fillColorSelected); |
|||
} else { |
|||
ofSetColor(fillColor); |
|||
} |
|||
|
|||
ofCircle(position.x, position.y, radius); |
|||
ofNoFill(); |
|||
|
|||
if ( selected ) { |
|||
ofSetColor(strokeColorSelected); |
|||
} else { |
|||
ofSetColor(strokeColor); |
|||
} |
|||
|
|||
ofSetLineWidth(strokeWidth); |
|||
ofCircle(position.x, position.y, radius); |
|||
ofPopStyle(); |
|||
} |
|||
|
|||
void ofxCircleJoint::setDefaultProperties() |
|||
{ |
|||
radius = 10.0f; |
|||
} |
|||
|
|||
bool ofxCircleJoint::hitTest(ofVec2f pos) |
|||
{ |
|||
float distance = position.distance(pos); |
|||
if ( distance < radius ) return true; |
|||
else return false; |
|||
} |
@ -1,22 +0,0 @@ |
|||
#ifndef H_OFX_CIRCLE_JOINT |
|||
#define H_OFX_CIRCLE_JOINT |
|||
|
|||
#include "ofMain.h" |
|||
#include "ofxBaseJoint.h" |
|||
|
|||
class ofxCircleJoint : public ofxBaseJoint |
|||
{ |
|||
public: |
|||
ofxCircleJoint(); |
|||
|
|||
void update(); |
|||
void draw(); |
|||
bool hitTest(ofVec2f position); |
|||
|
|||
private: |
|||
float radius; |
|||
|
|||
void setDefaultProperties(); |
|||
}; |
|||
|
|||
#endif |
@ -1,12 +0,0 @@ |
|||
#ifndef H_OFX_EDITOR_TYPE |
|||
#define H_OFX_EDITOR_TYPE |
|||
|
|||
struct ofxEditorType |
|||
{ |
|||
enum { |
|||
TEXTURE, |
|||
PROJECTION |
|||
}; |
|||
}; |
|||
|
|||
#endif |
@ -1,14 +0,0 @@ |
|||
#ifndef H_OFX_GUI_MODE |
|||
#define H_OFX_GUI_MODE |
|||
|
|||
struct ofxGuiMode |
|||
{ |
|||
enum { |
|||
NONE, |
|||
TEXTURE_MAPPING, |
|||
PROJECTION_MAPPING, |
|||
SOURCE_SELECTION |
|||
}; |
|||
}; |
|||
|
|||
#endif |
@ -1,7 +1,6 @@ |
|||
#ifndef H_OFX_PI_MAPPER |
|||
#define H_OFX_PI_MAPPER |
|||
#pragma once |
|||
|
|||
#include "ofxSurfaceManager.h" |
|||
#include "ofxSurfaceManagerGui.h" |
|||
#include "SurfaceManager.h" |
|||
#include "SurfaceManagerGui.h" |
|||
|
|||
#endif |
|||
#include "MediaServer.h" |
@ -1,266 +0,0 @@ |
|||
#include "ofxProjectionEditor.h" |
|||
|
|||
ofxProjectionEditor::ofxProjectionEditor() |
|||
{ |
|||
surfaceManager = NULL; |
|||
bShiftKeyDown = false; |
|||
fSnapDistance = 10.0f; |
|||
enable(); |
|||
} |
|||
|
|||
ofxProjectionEditor::~ofxProjectionEditor() |
|||
{ |
|||
clearJoints(); |
|||
surfaceManager = NULL; |
|||
disable(); |
|||
} |
|||
|
|||
void ofxProjectionEditor::registerAppEvents() |
|||
{ |
|||
ofAddListener(ofEvents().update, this, &ofxProjectionEditor::update); |
|||
ofAddListener(ofEvents().messageEvent, this, &ofxProjectionEditor::gotMessage); |
|||
} |
|||
|
|||
void ofxProjectionEditor::unregisterAppEvents() |
|||
{ |
|||
ofRemoveListener(ofEvents().update, this, &ofxProjectionEditor::update); |
|||
ofRemoveListener(ofEvents().messageEvent, this, &ofxProjectionEditor::gotMessage); |
|||
} |
|||
|
|||
void ofxProjectionEditor::registerMouseEvents() |
|||
{ |
|||
ofAddListener(ofEvents().mouseDragged, this, &ofxProjectionEditor::mouseDragged); |
|||
} |
|||
|
|||
void ofxProjectionEditor::unregisterMouseEvents() |
|||
{ |
|||
ofRemoveListener(ofEvents().mouseDragged, this, &ofxProjectionEditor::mouseDragged); |
|||
} |
|||
|
|||
void ofxProjectionEditor::registerKeyEvents() |
|||
{ |
|||
ofAddListener(ofEvents().keyPressed, this, &ofxProjectionEditor::keyPressed); |
|||
ofAddListener(ofEvents().keyReleased, this, &ofxProjectionEditor::keyReleased); |
|||
} |
|||
|
|||
void ofxProjectionEditor::unregisterKeyEvents() |
|||
{ |
|||
ofRemoveListener(ofEvents().keyPressed, this, &ofxProjectionEditor::keyPressed); |
|||
ofRemoveListener(ofEvents().keyReleased, this, &ofxProjectionEditor::keyReleased); |
|||
} |
|||
|
|||
void ofxProjectionEditor::enable() |
|||
{ |
|||
registerAppEvents(); |
|||
registerMouseEvents(); |
|||
registerKeyEvents(); |
|||
} |
|||
|
|||
void ofxProjectionEditor::disable() |
|||
{ |
|||
unregisterAppEvents(); |
|||
unregisterMouseEvents(); |
|||
unregisterKeyEvents(); |
|||
} |
|||
|
|||
void ofxProjectionEditor::update(ofEventArgs &args) |
|||
{ |
|||
// update surface if one of the joints is being dragged
|
|||
for ( int i=0; i<joints.size(); i++ ) { |
|||
if ( joints[i]->isDragged() || joints[i]->isSelected() ) { |
|||
|
|||
if ( surfaceManager->getSelectedSurface() != NULL ) { |
|||
// update vertex to new location
|
|||
surfaceManager->getSelectedSurface()->setVertex(i, joints[i]->position); |
|||
} else { |
|||
// clear joints if there is no surface selected
|
|||
// as the remove selected surface in the surface manager
|
|||
// is not supposed to access joints here
|
|||
joints.clear(); |
|||
} |
|||
break; |
|||
} |
|||
} |
|||
} |
|||
|
|||
void ofxProjectionEditor::draw() |
|||
{ |
|||
if ( surfaceManager == NULL ) return; |
|||
if ( surfaceManager->getSelectedSurface() == NULL ) return; |
|||
if ( joints.size() <= 0 ) createJoints(); |
|||
drawJoints(); |
|||
} |
|||
|
|||
void ofxProjectionEditor::mouseDragged(ofMouseEventArgs &args) |
|||
{ |
|||
ofVec2f mousePosition = ofVec2f(args.x, args.y); |
|||
|
|||
// Collect all vertices of the projection surfaces
|
|||
vector<ofVec3f*> allVertices; |
|||
for ( int i=0; i<surfaceManager->size(); i++ ) { |
|||
ofxBaseSurface* surface = surfaceManager->getSurface(i); |
|||
if ( surface == surfaceManager->getSelectedSurface() ) { |
|||
continue; // Don't add vertices of selected surface
|
|||
} |
|||
for ( int j=0; j<surface->getVertices().size(); j++ ) { |
|||
allVertices.push_back(&surface->getVertices()[j]); |
|||
} |
|||
} |
|||
|
|||
// Snap currently dragged joint to nearest vertex
|
|||
for ( int i=0; i<joints.size(); i++ ) { |
|||
if ( joints[i]->isDragged() ) { |
|||
// Snap it!
|
|||
for ( int j=0; j<allVertices.size(); j++ ) { |
|||
float distance = mousePosition.distance(*allVertices[j]); |
|||
//cout << "distance: " << distance << endl;
|
|||
if ( distance < fSnapDistance ) { |
|||
joints[i]->position = *allVertices[j]; |
|||
ofVec2f clickDistance = joints[i]->position - ofVec2f(args.x, args.y); |
|||
joints[i]->setClickDistance(clickDistance); |
|||
break; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
|||
void ofxProjectionEditor::keyPressed(ofKeyEventArgs &args) |
|||
{ |
|||
int key = args.key; |
|||
float moveStep; |
|||
|
|||
if (bShiftKeyDown) moveStep = 10.0f; |
|||
else moveStep = 0.5f; |
|||
|
|||
switch (key) { |
|||
case OF_KEY_LEFT: moveSelection(ofVec2f(-moveStep,0.0f)); break; |
|||
case OF_KEY_RIGHT: moveSelection(ofVec2f(moveStep,0.0f)); break; |
|||
case OF_KEY_UP: moveSelection(ofVec2f(0.0f,-moveStep)); break; |
|||
case OF_KEY_DOWN: moveSelection(ofVec2f(0.0f,moveStep)); break; |
|||
case OF_KEY_SHIFT: bShiftKeyDown = true; break; |
|||
} |
|||
} |
|||
|
|||
void ofxProjectionEditor::keyReleased(ofKeyEventArgs &args) |
|||
{ |
|||
int key = args.key; |
|||
switch (key) { |
|||
case OF_KEY_SHIFT: bShiftKeyDown = false; break; |
|||
} |
|||
} |
|||
|
|||
void ofxProjectionEditor::gotMessage(ofMessage& msg) |
|||
{ |
|||
if (msg.message == "surfaceSelected") { |
|||
// refresh gui
|
|||
clearJoints(); |
|||
createJoints(); |
|||
} |
|||
} |
|||
|
|||
void ofxProjectionEditor::setSurfaceManager(ofxSurfaceManager *newSurfaceManager) |
|||
{ |
|||
surfaceManager = newSurfaceManager; |
|||
} |
|||
|
|||
void ofxProjectionEditor::clearJoints() |
|||
{ |
|||
while ( joints.size() ) { |
|||
delete joints.back(); |
|||
joints.pop_back(); |
|||
} |
|||
} |
|||
|
|||
void ofxProjectionEditor::createJoints() |
|||
{ |
|||
if ( surfaceManager == NULL ) return; |
|||
clearJoints(); |
|||
|
|||
if ( surfaceManager->getSelectedSurface() == NULL ) { |
|||
ofLog(OF_LOG_WARNING, "Trying to create joints while no surface selected."); |
|||
return; |
|||
} |
|||
|
|||
vector<ofVec3f>& vertices = surfaceManager->getSelectedSurface()->getVertices(); |
|||
|
|||
for ( int i=0; i<vertices.size(); i++ ) { |
|||
joints.push_back( new ofxCircleJoint() ); |
|||
joints.back()->position = ofVec2f(vertices[i].x, vertices[i].y); |
|||
} |
|||
} |
|||
|
|||
void ofxProjectionEditor::updateJoints() |
|||
{ |
|||
vector<ofVec3f>& vertices = surfaceManager->getSelectedSurface()->getVertices(); |
|||
for ( int i=0; i<vertices.size(); i++ ) { |
|||
joints[i]->position = ofVec2f(vertices[i].x, vertices[i].y); |
|||
} |
|||
} |
|||
|
|||
void ofxProjectionEditor::unselectAllJoints() |
|||
{ |
|||
for ( int i=0; i<joints.size(); i++ ) { |
|||
joints[i]->unselect(); |
|||
} |
|||
} |
|||
|
|||
void ofxProjectionEditor::moveSelectedSurface(ofVec2f by) |
|||
{ |
|||
if ( surfaceManager == NULL ) return; |
|||
if ( surfaceManager->getSelectedSurface() == NULL ) return; |
|||
vector<ofVec3f>& vertices = surfaceManager->getSelectedSurface()->getVertices(); |
|||
for (int i=0; i<vertices.size(); i++) { |
|||
vertices[i] += by; |
|||
} |
|||
updateJoints(); |
|||
} |
|||
|
|||
void ofxProjectionEditor::stopDragJoints() |
|||
{ |
|||
for (int i=0; i<joints.size(); i++){ |
|||
joints[i]->stopDrag(); |
|||
} |
|||
} |
|||
|
|||
void ofxProjectionEditor::moveSelection(ofVec2f by) |
|||
{ |
|||
// check if joints selected
|
|||
bool bJointSelected = false; |
|||
ofxBaseJoint* selectedJoint; |
|||
for ( int i=0; i<joints.size(); i++ ) { |
|||
if (joints[i]->isSelected()) { |
|||
bJointSelected = true; |
|||
selectedJoint = joints[i]; |
|||
break; |
|||
} |
|||
} |
|||
|
|||
if ( bJointSelected ) { |
|||
selectedJoint->position += by; |
|||
} else { |
|||
moveSelectedSurface(by); |
|||
} |
|||
} |
|||
|
|||
void ofxProjectionEditor::setSnapDistance(float newSnapDistance) |
|||
{ |
|||
fSnapDistance = newSnapDistance; |
|||
} |
|||
|
|||
ofxCircleJoint* ofxProjectionEditor::hitTestJoints(ofVec2f pos) |
|||
{ |
|||
for ( int i=0; i<joints.size(); i++ ) { |
|||
if ( joints[i]->hitTest(pos) ){ |
|||
return joints[i]; |
|||
} |
|||
} |
|||
return NULL; |
|||
} |
|||
|
|||
void ofxProjectionEditor::drawJoints() |
|||
{ |
|||
for ( int i=0; i<joints.size(); i++ ) { |
|||
joints[i]->draw(); |
|||
} |
|||
} |
@ -1,50 +0,0 @@ |
|||
#ifndef H_OFX_PROJECTION_EDITOR |
|||
#define H_OFX_PROJECTION_EDITOR |
|||
|
|||
#include "ofxSurfaceManager.h" |
|||
#include "ofxCircleJoint.h" |
|||
|
|||
class ofxProjectionEditor |
|||
{ |
|||
public: |
|||
ofxProjectionEditor(); |
|||
~ofxProjectionEditor(); |
|||
|
|||
void registerAppEvents(); |
|||
void unregisterAppEvents(); |
|||
void registerMouseEvents(); |
|||
void unregisterMouseEvents(); |
|||
void registerKeyEvents(); |
|||
void unregisterKeyEvents(); |
|||
|
|||
void enable(); |
|||
void disable(); |
|||
|
|||
void update(ofEventArgs& args); |
|||
void draw(); |
|||
void mouseDragged(ofMouseEventArgs& args); |
|||
void keyPressed(ofKeyEventArgs& args); |
|||
void keyReleased(ofKeyEventArgs& args); |
|||
void gotMessage(ofMessage& msg); |
|||
void setSurfaceManager(ofxSurfaceManager* newSurfaceManager); |
|||
void clearJoints(); |
|||
void createJoints(); |
|||
void updateJoints(); |
|||
void unselectAllJoints(); |
|||
void moveSelectedSurface(ofVec2f by); |
|||
void stopDragJoints(); |
|||
void updateVertices(); |
|||
void moveSelection(ofVec2f by); |
|||
void setSnapDistance(float newSnapDistance); |
|||
ofxCircleJoint* hitTestJoints(ofVec2f pos); |
|||
|
|||
private: |
|||
ofxSurfaceManager* surfaceManager; |
|||
vector<ofxCircleJoint*> joints; |
|||
bool bShiftKeyDown; |
|||
float fSnapDistance; |
|||
|
|||
void drawJoints(); |
|||
}; |
|||
|
|||
#endif |
@ -1,156 +0,0 @@ |
|||
#include "ofxQuadSurface.h" |
|||
|
|||
ofxQuadSurface::ofxQuadSurface() |
|||
{ |
|||
cout << "ofxQuadSurface constructor." << endl; |
|||
setup(); |
|||
} |
|||
|
|||
ofxQuadSurface::~ofxQuadSurface() |
|||
{ |
|||
cout << "ofxQuadSurface destructor." << endl; |
|||
} |
|||
|
|||
void ofxQuadSurface::setup() |
|||
{ |
|||
// Create 4 points for the 2 triangles
|
|||
ofVec2f p1 = ofVec2f(0, 0); |
|||
ofVec2f p2 = ofVec2f(0, ofGetHeight()); |
|||
ofVec2f p3 = ofVec2f(ofGetWidth(), ofGetHeight()); |
|||
ofVec2f p4 = ofVec2f(ofGetWidth(), 0); |
|||
|
|||
// Create 4 point for the texture coordinates
|
|||
ofVec2f t1 = ofVec2f(ofVec2f(0.0f, 0.0f)); |
|||
ofVec2f t2 = ofVec2f(ofVec2f(1.0f, 0.0f)); |
|||
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 ); |
|||
} |
|||
|
|||
void ofxQuadSurface::setup( ofVec2f p1, ofVec2f p2, ofVec2f p3, ofVec2f p4, |
|||
ofVec2f t1, ofVec2f t2, ofVec2f t3, ofVec2f t4, ofTexture* texturePtr ) |
|||
{ |
|||
// Assign texture
|
|||
texture = texturePtr; |
|||
|
|||
// Clear mesh
|
|||
mesh.clear(); |
|||
|
|||
// Create a surface with the points
|
|||
mesh.addVertex( p1 ); |
|||
mesh.addVertex( p2 ); |
|||
mesh.addVertex( p3 ); |
|||
mesh.addVertex( p4 ); |
|||
|
|||
// Add 2 triangles
|
|||
mesh.addTriangle(0, 2, 3); |
|||
mesh.addTriangle(0, 1, 2); |
|||
|
|||
// Add texture coordinates
|
|||
mesh.addTexCoord(t1); |
|||
mesh.addTexCoord(t2); |
|||
mesh.addTexCoord(t3); |
|||
mesh.addTexCoord(t4); |
|||
} |
|||
|
|||
void ofxQuadSurface::draw() |
|||
{ |
|||
texture->bind(); |
|||
mesh.draw(); |
|||
texture->unbind(); |
|||
} |
|||
|
|||
void ofxQuadSurface::setVertex(int index, ofVec2f p) |
|||
{ |
|||
if ( index > 3 ) { |
|||
ofLog() << "Vertex with this index does not exist: " << index << endl; |
|||
return; |
|||
} |
|||
|
|||
mesh.setVertex(index, p); |
|||
} |
|||
|
|||
void ofxQuadSurface::setTexCoord(int index, ofVec2f t) |
|||
{ |
|||
if ( index > 3 ) { |
|||
ofLog() << "Texture coordinate with this index does not exist: " << index << endl; |
|||
return; |
|||
} |
|||
|
|||
mesh.setTexCoord(index, t); |
|||
} |
|||
|
|||
int ofxQuadSurface::getType() |
|||
{ |
|||
return ofxSurfaceType::QUAD_SURFACE; |
|||
} |
|||
|
|||
bool ofxQuadSurface::hitTest(ofVec2f p) |
|||
{ |
|||
// Construct ofPolyline from vertices
|
|||
ofPolyline line = getHitArea(); |
|||
|
|||
if ( line.inside(p.x, p.y) ) { |
|||
return true; |
|||
} else { |
|||
return false; |
|||
} |
|||
} |
|||
|
|||
ofVec2f ofxQuadSurface::getVertex(int index) |
|||
{ |
|||
if ( index > 3 ) { |
|||
ofLog() << "Vertex with this index does not exist: " << index << endl; |
|||
throw std::runtime_error("Vertex index out of bounds."); |
|||
} |
|||
|
|||
ofVec3f vert = mesh.getVertex(index); |
|||
return ofVec2f(vert.x, vert.y); |
|||
} |
|||
|
|||
ofVec2f ofxQuadSurface::getTexCoord(int index) |
|||
{ |
|||
if (index > 3) { |
|||
throw std::runtime_error("Texture coordinate index out of bounds."); |
|||
} |
|||
|
|||
return mesh.getTexCoord(index); |
|||
} |
|||
|
|||
ofPolyline ofxQuadSurface::getHitArea() |
|||
{ |
|||
ofPolyline line; |
|||
line.addVertex( ofPoint( mesh.getVertex(0).x, mesh.getVertex(0).y ) ); |
|||
line.addVertex( ofPoint( mesh.getVertex(1).x, mesh.getVertex(1).y ) ); |
|||
line.addVertex( ofPoint( mesh.getVertex(2).x, mesh.getVertex(2).y ) ); |
|||
line.addVertex( ofPoint( mesh.getVertex(3).x, mesh.getVertex(3).y ) ); |
|||
line.close(); |
|||
|
|||
return line; |
|||
} |
|||
|
|||
ofPolyline ofxQuadSurface::getTextureHitArea() |
|||
{ |
|||
ofPolyline line; |
|||
vector<ofVec2f>& texCoords = mesh.getTexCoords(); |
|||
ofVec2f textureSize = ofVec2f(texture->getWidth(), texture->getHeight()); |
|||
for ( int i=0; i<texCoords.size(); i++ ) { |
|||
line.addVertex( ofPoint( texCoords[i] * textureSize ) ); |
|||
} |
|||
line.close(); |
|||
|
|||
return line; |
|||
} |
|||
|
|||
vector<ofVec3f>& ofxQuadSurface::getVertices() |
|||
{ |
|||
// return only joint vertices
|
|||
return mesh.getVertices(); |
|||
} |
|||
|
|||
vector<ofVec2f>& ofxQuadSurface::getTexCoords() |
|||
{ |
|||
|
|||
return mesh.getTexCoords(); |
|||
} |
@ -1,34 +0,0 @@ |
|||
#ifndef H_OFX_QUAD_SURFACE |
|||
#define H_OFX_QUAD_SURFACE |
|||
|
|||
#include "ofMain.h" |
|||
#include "ofxBaseSurface.h" |
|||
#include "ofxSurfaceType.h" |
|||
|
|||
class ofxQuadSurface : public ofxBaseSurface |
|||
{ |
|||
public: |
|||
ofxQuadSurface(); |
|||
~ofxQuadSurface(); |
|||
|
|||
void setup(); |
|||
|
|||
void setup( ofVec2f p1, ofVec2f p2, ofVec2f p3, ofVec2f p4, |
|||
ofVec2f t1, ofVec2f t2, ofVec2f t3, ofVec2f t4, |
|||
ofTexture* texturePtr ); |
|||
|
|||
void draw(); |
|||
void setVertex( int index, ofVec2f p ); |
|||
void setTexCoord( int index, ofVec2f t ); |
|||
|
|||
int getType(); |
|||
bool hitTest(ofVec2f p); |
|||
ofVec2f getVertex(int index); |
|||
ofVec2f getTexCoord(int index); |
|||
ofPolyline getHitArea(); |
|||
ofPolyline getTextureHitArea(); |
|||
vector<ofVec3f>& getVertices(); |
|||
vector<ofVec2f>& getTexCoords(); |
|||
}; |
|||
|
|||
#endif |
@ -1,153 +0,0 @@ |
|||
#include "ofxSourcesEditor.h" |
|||
|
|||
ofxSourcesEditor::ofxSourcesEditor() |
|||
{ |
|||
defImgDir = DEFAULT_IMAGES_DIR; |
|||
registerAppEvents(); |
|||
} |
|||
|
|||
ofxSourcesEditor::~ofxSourcesEditor() |
|||
{ |
|||
unregisterAppEvents(); |
|||
delete gui; |
|||
while ( images.size() ) { |
|||
delete images.back(); |
|||
images.pop_back(); |
|||
} |
|||
} |
|||
|
|||
void ofxSourcesEditor::registerAppEvents() |
|||
{ |
|||
ofAddListener(ofEvents().setup, this, &ofxSourcesEditor::setup); |
|||
} |
|||
|
|||
void ofxSourcesEditor::unregisterAppEvents() |
|||
{ |
|||
ofRemoveListener(ofEvents().setup, this, &ofxSourcesEditor::setup); |
|||
} |
|||
|
|||
void ofxSourcesEditor::setup(ofEventArgs& args) |
|||
{ |
|||
gui = new ofxUICanvas(); |
|||
gui->disable(); |
|||
gui->disableAppDrawCallback(); |
|||
|
|||
// read directory contents
|
|||
ofDirectory imgDir; |
|||
imgDir.listDir(defImgDir); |
|||
imgDir.sort(); |
|||
|
|||
vector<string> vnames; |
|||
|
|||
for(int i = 0; i < (int)imgDir.size(); i++){ |
|||
//images[i].loadImage(imgDir.getPath(i));
|
|||
vnames.push_back(imgDir.getName(i)); |
|||
} |
|||
|
|||
gui->addLabel(defImgDir, OFX_UI_FONT_SMALL); |
|||
ofxUIRadio *radio = gui->addRadio("images", vnames, OFX_UI_ORIENTATION_VERTICAL); |
|||
radio->activateToggle("image0.png"); |
|||
|
|||
ofAddListener(gui->newGUIEvent,this,&ofxSourcesEditor::guiEvent); |
|||
} |
|||
|
|||
void ofxSourcesEditor::draw() |
|||
{ |
|||
gui->draw(); |
|||
} |
|||
|
|||
void ofxSourcesEditor::loadImage( string name, string path ) |
|||
{ |
|||
images.push_back(new ofImage()); |
|||
images.back()->loadImage(path); |
|||
|
|||
imageNames.push_back(name); |
|||
|
|||
ofSendMessage("imageLoaded"); |
|||
} |
|||
|
|||
void ofxSourcesEditor::disable() |
|||
{ |
|||
gui->disable(); |
|||
} |
|||
|
|||
void ofxSourcesEditor::enable() |
|||
{ |
|||
gui->enable(); |
|||
} |
|||
|
|||
void ofxSourcesEditor::setSurfaceManager(ofxSurfaceManager *newSurfaceManager) |
|||
{ |
|||
surfaceManager = newSurfaceManager; |
|||
} |
|||
|
|||
void ofxSourcesEditor::selectImageSourceRadioButton(string name) |
|||
{ |
|||
vector<ofxUIWidget*> widgets = gui->getWidgets(); |
|||
|
|||
// find radio list item
|
|||
ofxUIRadio* radio; |
|||
for ( int i=0; i<widgets.size(); i++ ) { |
|||
int widgetKind = widgets[i]->getKind(); |
|||
if ( widgetKind == OFX_UI_WIDGET_RADIO ){ |
|||
radio = (ofxUIRadio*)widgets[i]; |
|||
break; |
|||
} |
|||
} |
|||
|
|||
if (name == "none") { |
|||
ofxUIToggle* toggle = (ofxUIToggle*)radio->getActive(); |
|||
if ( toggle != NULL ) { |
|||
toggle->setValue(false); |
|||
} |
|||
return; |
|||
} else { |
|||
for ( int i=0; i<widgets.size(); i++ ) { |
|||
string widgetName = widgets[i]->getName(); |
|||
if ( name == widgetName ) { |
|||
radio->activateToggle(name); |
|||
return; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
|||
int ofxSourcesEditor::getLoadedTexCount() |
|||
{ |
|||
return images.size(); |
|||
} |
|||
|
|||
ofTexture* ofxSourcesEditor::getTexture(int index) |
|||
{ |
|||
if (index >= images.size()){ |
|||
throw std::runtime_error("Texture index out of bounds."); |
|||
} |
|||
|
|||
return &images[index]->getTextureReference(); |
|||
} |
|||
|
|||
void ofxSourcesEditor::guiEvent(ofxUIEventArgs &e) |
|||
{ |
|||
string name = e.widget->getName(); |
|||
int kind = e.widget->getKind(); |
|||
|
|||
if(kind == OFX_UI_WIDGET_TOGGLE){ |
|||
ofxUIToggle *toggle = (ofxUIToggle *) e.widget; |
|||
cout << name << "\t value: " << toggle->getValue() << endl; |
|||
} |
|||
|
|||
if ( surfaceManager->getSelectedSurface() == NULL ) { |
|||
return; |
|||
} |
|||
|
|||
if (name == "images") { |
|||
return; |
|||
} |
|||
|
|||
stringstream ss; |
|||
ss << defImgDir << name; |
|||
cout << "attempt to load image: " << ss.str() << endl; |
|||
ofTexture* texture = surfaceManager->loadImageSource(name, ss.str()); |
|||
surfaceManager->getSelectedSurface()->setTexture(texture); |
|||
surfaceManager->manageMemory(); |
|||
} |
@ -1,43 +0,0 @@ |
|||
#ifndef H_OFX_SOURCES_EDITOR |
|||
#define H_OFX_SOURCES_EDITOR |
|||
|
|||
#include "ofGraphics.h" |
|||
#include "ofEvents.h" |
|||
#include "ofxUI.h" |
|||
#include "ofxSurfaceManager.h" |
|||
|
|||
#define DEFAULT_IMAGES_DIR "sources/images/"; |
|||
|
|||
class ofxSourcesEditor |
|||
{ |
|||
public: |
|||
ofxSourcesEditor(); |
|||
~ofxSourcesEditor(); |
|||
|
|||
void registerAppEvents(); |
|||
void unregisterAppEvents(); |
|||
|
|||
void setup(ofEventArgs& args); |
|||
void draw(); |
|||
void loadImage( string name, string path ); |
|||
void disable(); |
|||
void enable(); |
|||
void setSurfaceManager(ofxSurfaceManager* newSurfaceManager); |
|||
void selectImageSourceRadioButton(string name); |
|||
|
|||
int getLoadedTexCount(); |
|||
ofTexture* getTexture(int index); |
|||
|
|||
private: |
|||
ofxSurfaceManager* surfaceManager; |
|||
string defImgDir; |
|||
ofxUICanvas *gui; |
|||
void guiEvent(ofxUIEventArgs &e); |
|||
vector<ofImage*> images; |
|||
vector<string> imageNames; |
|||
//ofxPanel imgSrcPanel;
|
|||
|
|||
//void onSourceSelect(bool& value);
|
|||
}; |
|||
|
|||
#endif |
@ -1,486 +0,0 @@ |
|||
#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(); |
|||
} |
|||
|
|||
|
|||
|
@ -1,48 +0,0 @@ |
|||
#ifndef H_OFX_SURFACE_MANAGER |
|||
#define H_OFX_SURFACE_MANAGER |
|||
|
|||
#include "ofxBaseSurface.h" |
|||
#include "ofxTriangleSurface.h" |
|||
#include "ofxQuadSurface.h" |
|||
#include "ofxSurfaceType.h" |
|||
#include "ofEvents.h" |
|||
#include "ofxXmlSettings.h" |
|||
|
|||
using namespace std; |
|||
|
|||
class ofxSurfaceManager |
|||
{ |
|||
public: |
|||
ofxSurfaceManager(); |
|||
~ofxSurfaceManager(); |
|||
|
|||
void draw(); |
|||
void addSurface(int surfaceType); |
|||
void addSurface(int surfaceType, ofTexture* texturePtr); |
|||
void addSurface(int surfaceType, vector<ofVec2f> vertices, vector<ofVec2f> texCoords); |
|||
void addSurface(int surfaceType, ofTexture* texturePtr, vector<ofVec2f> vertices, vector<ofVec2f> texCoords); |
|||
void removeSelectedSurface(); |
|||
void manageMemory(); // deletes unasigned sources
|
|||
void clear(); |
|||
void saveXmlSettings(string fileName); |
|||
void loadXmlSettings(string fileName); |
|||
|
|||
ofxBaseSurface* getSurface(int index); |
|||
int size(); |
|||
ofxBaseSurface* selectSurface(int index); |
|||
ofxBaseSurface* getSelectedSurface(); |
|||
void deselectSurface(); |
|||
ofTexture* loadImageSource(string name, string path); |
|||
string getSelectedSurfaceSourceName(); |
|||
string getSurfaceSourceName( ofxBaseSurface* surface ); |
|||
|
|||
private: |
|||
vector<ofxBaseSurface*> surfaces; |
|||
ofxBaseSurface* selectedSurface; |
|||
vector<string> loadedImageSourceNames; |
|||
vector<ofImage*> loadedImageSources; |
|||
ofxXmlSettings xmlSettings; |
|||
|
|||
}; |
|||
|
|||
#endif |
@ -1,254 +0,0 @@ |
|||
#include "ofxSurfaceManagerGui.h" |
|||
|
|||
ofxSurfaceManagerGui::ofxSurfaceManagerGui() |
|||
{ |
|||
surfaceManager = NULL; |
|||
guiMode = ofxGuiMode::NONE; |
|||
bDrag = false; |
|||
registerMouseEvents(); |
|||
ofHideCursor(); |
|||
} |
|||
|
|||
ofxSurfaceManagerGui::~ofxSurfaceManagerGui() |
|||
{ |
|||
unregisterMouseEvents(); |
|||
surfaceManager = NULL; |
|||
} |
|||
|
|||
void ofxSurfaceManagerGui::registerMouseEvents() |
|||
{ |
|||
ofAddListener(ofEvents().mousePressed, this, &ofxSurfaceManagerGui::mousePressed); |
|||
ofAddListener(ofEvents().mouseReleased, this, &ofxSurfaceManagerGui::mouseReleased); |
|||
ofAddListener(ofEvents().mouseDragged, this, &ofxSurfaceManagerGui::mouseDragged); |
|||
} |
|||
|
|||
void ofxSurfaceManagerGui::unregisterMouseEvents() |
|||
{ |
|||
ofRemoveListener(ofEvents().mousePressed, this, &ofxSurfaceManagerGui::mousePressed); |
|||
ofRemoveListener(ofEvents().mouseReleased, this, &ofxSurfaceManagerGui::mouseReleased); |
|||
ofRemoveListener(ofEvents().mouseDragged, this, &ofxSurfaceManagerGui::mouseDragged); |
|||
} |
|||
|
|||
void ofxSurfaceManagerGui::draw() |
|||
{ |
|||
if ( surfaceManager == NULL ) return; |
|||
|
|||
if ( guiMode == ofxGuiMode::NONE ) { |
|||
surfaceManager->draw(); |
|||
} else if ( guiMode == ofxGuiMode::TEXTURE_MAPPING ) { |
|||
|
|||
// draw the texture of the selected surface
|
|||
if ( surfaceManager->getSelectedSurface() != NULL ) { |
|||
surfaceManager->getSelectedSurface()->drawTexture( ofVec2f(0,0) ); |
|||
} |
|||
|
|||
// draw surfaces with opacity
|
|||
ofPushStyle(); |
|||
ofSetColor(255, 255, 255, 200); |
|||
surfaceManager->draw(); |
|||
ofPopStyle(); |
|||
|
|||
// highlight selected surface
|
|||
drawSelectedSurfaceHighlight(); |
|||
|
|||
// hilight selected surface texture
|
|||
drawSelectedSurfaceTextureHighlight(); |
|||
|
|||
// draw texture editing GUI on top
|
|||
textureEditor.draw(); |
|||
|
|||
} else if ( guiMode == ofxGuiMode::PROJECTION_MAPPING ) { |
|||
|
|||
// draw projection surfaces first
|
|||
surfaceManager->draw(); |
|||
|
|||
// highlight selected surface
|
|||
drawSelectedSurfaceHighlight(); |
|||
|
|||
// draw projection mapping editing gui
|
|||
projectionEditor.draw(); |
|||
|
|||
} else if ( guiMode == ofxGuiMode::SOURCE_SELECTION ) { |
|||
// draw projection surfaces first
|
|||
surfaceManager->draw(); |
|||
|
|||
// highlight selected surface
|
|||
drawSelectedSurfaceHighlight(); |
|||
|
|||
sourcesEditor.draw(); |
|||
} |
|||
} |
|||
|
|||
void ofxSurfaceManagerGui::mousePressed(ofMouseEventArgs &args) |
|||
{ |
|||
if ( guiMode == ofxGuiMode::NONE ) { |
|||
return; |
|||
} else if ( guiMode == ofxGuiMode::TEXTURE_MAPPING ) { |
|||
|
|||
bool bSurfaceSelected = false; |
|||
|
|||
ofxCircleJoint* hitJoint = textureEditor.hitTestJoints(ofVec2f(args.x, args.y)); |
|||
if ( hitJoint != NULL ) { |
|||
textureEditor.unselectAllJoints(); |
|||
hitJoint->select(); |
|||
hitJoint->startDrag(); |
|||
bSurfaceSelected = true; |
|||
} else { |
|||
textureEditor.unselectAllJoints(); |
|||
} |
|||
|
|||
if ( surfaceManager->getSelectedSurface() != NULL && !bSurfaceSelected ) { |
|||
// hittest texture area to see if we are hitting the texture surface
|
|||
if ( surfaceManager->getSelectedSurface()->getTextureHitArea().inside(args.x, args.y) ) { |
|||
clickPosition = ofVec2f(args.x, args.y); |
|||
startDrag(); |
|||
} |
|||
} |
|||
|
|||
} else if ( guiMode == ofxGuiMode::PROJECTION_MAPPING ) { |
|||
|
|||
bool bSurfaceSelected = false; |
|||
|
|||
ofxCircleJoint* hitJoint = projectionEditor.hitTestJoints(ofVec2f(args.x, args.y)); |
|||
if ( hitJoint != NULL ) { |
|||
projectionEditor.unselectAllJoints(); |
|||
hitJoint->select(); |
|||
hitJoint->startDrag(); |
|||
bSurfaceSelected = true; |
|||
} |
|||
|
|||
// attempt to select surface, loop from end to beginning
|
|||
if ( !bSurfaceSelected ){ |
|||
for ( int i=surfaceManager->size()-1; i>=0; i-- ) { |
|||
if ( surfaceManager->getSurface(i)->hitTest( ofVec2f(args.x, args.y) ) ) { |
|||
projectionEditor.clearJoints(); |
|||
surfaceManager->selectSurface(i); |
|||
projectionEditor.createJoints(); |
|||
bSurfaceSelected = true; |
|||
break; |
|||
} |
|||
} |
|||
} |
|||
|
|||
if ( bSurfaceSelected && hitJoint == NULL ) { |
|||
// if not hitting the joints, start drag only if we have a selected surface
|
|||
clickPosition = ofVec2f(args.x, args.y); |
|||
startDrag(); |
|||
} |
|||
|
|||
if ( !bSurfaceSelected ) { |
|||
// unselect if no surface selected
|
|||
projectionEditor.clearJoints(); |
|||
surfaceManager->deselectSurface(); |
|||
} |
|||
} else if ( guiMode == ofxGuiMode::SOURCE_SELECTION ) { |
|||
|
|||
} |
|||
} |
|||
|
|||
void ofxSurfaceManagerGui::mouseReleased(ofMouseEventArgs &args) |
|||
{ |
|||
stopDrag(); |
|||
projectionEditor.stopDragJoints(); |
|||
textureEditor.stopDragJoints(); |
|||
} |
|||
|
|||
void ofxSurfaceManagerGui::mouseDragged(ofMouseEventArgs &args) |
|||
{ |
|||
if (bDrag) { |
|||
ofVec2f mousePosition = ofVec2f(args.x, args.y); |
|||
ofVec2f distance = mousePosition - clickPosition; |
|||
|
|||
if ( guiMode == ofxGuiMode::PROJECTION_MAPPING ) { |
|||
// add this distance to all vertices in surface
|
|||
projectionEditor.moveSelectedSurface(distance); |
|||
} else if ( guiMode == ofxGuiMode::TEXTURE_MAPPING ) { |
|||
textureEditor.moveTexCoords(distance); |
|||
} |
|||
clickPosition = mousePosition; |
|||
} |
|||
} |
|||
|
|||
void ofxSurfaceManagerGui::setSurfaceManager(ofxSurfaceManager* newSurfaceManager) |
|||
{ |
|||
surfaceManager = newSurfaceManager; |
|||
projectionEditor.setSurfaceManager( surfaceManager ); |
|||
sourcesEditor.setSurfaceManager( surfaceManager ); |
|||
} |
|||
|
|||
void ofxSurfaceManagerGui::setMode(int newGuiMode) |
|||
{ |
|||
if (newGuiMode != ofxGuiMode::NONE && |
|||
newGuiMode != ofxGuiMode::TEXTURE_MAPPING && |
|||
newGuiMode != ofxGuiMode::PROJECTION_MAPPING && |
|||
newGuiMode != ofxGuiMode::SOURCE_SELECTION) { |
|||
throw std::runtime_error("Trying to set invalid mode."); |
|||
} |
|||
|
|||
if ( newGuiMode == ofxGuiMode::NONE ) { |
|||
ofHideCursor(); |
|||
} else { |
|||
ofShowCursor(); |
|||
} |
|||
|
|||
guiMode = newGuiMode; |
|||
|
|||
if ( guiMode == ofxGuiMode::SOURCE_SELECTION ) { |
|||
sourcesEditor.enable(); |
|||
string sourceName = surfaceManager->getSelectedSurfaceSourceName(); |
|||
sourcesEditor.selectImageSourceRadioButton(sourceName); |
|||
} else { |
|||
sourcesEditor.disable(); |
|||
} |
|||
|
|||
if ( guiMode == ofxGuiMode::TEXTURE_MAPPING ) { |
|||
textureEditor.enable(); |
|||
// refresh texture editor surface reference
|
|||
textureEditor.setSurface(surfaceManager->getSelectedSurface()); |
|||
} else { |
|||
textureEditor.disable(); |
|||
} |
|||
|
|||
if (guiMode == ofxGuiMode::PROJECTION_MAPPING) { |
|||
projectionEditor.enable(); |
|||
} else { |
|||
projectionEditor.disable(); |
|||
} |
|||
} |
|||
|
|||
void ofxSurfaceManagerGui::drawSelectedSurfaceHighlight() |
|||
{ |
|||
if ( surfaceManager->getSelectedSurface() == NULL ) return; |
|||
|
|||
ofPolyline line = surfaceManager->getSelectedSurface()->getHitArea(); |
|||
|
|||
ofPushStyle(); |
|||
ofSetLineWidth(1); |
|||
ofSetColor(255, 255, 255, 255); |
|||
line.draw(); |
|||
ofPopStyle(); |
|||
} |
|||
|
|||
void ofxSurfaceManagerGui::drawSelectedSurfaceTextureHighlight() |
|||
{ |
|||
if ( surfaceManager->getSelectedSurface() == NULL ) return; |
|||
|
|||
ofPolyline line = surfaceManager->getSelectedSurface()->getTextureHitArea(); |
|||
|
|||
ofPushStyle(); |
|||
ofSetLineWidth(1); |
|||
ofSetColor(255, 255, 0, 255); |
|||
line.draw(); |
|||
ofPopStyle(); |
|||
|
|||
} |
|||
|
|||
void ofxSurfaceManagerGui::startDrag() |
|||
{ |
|||
bDrag = true; |
|||
} |
|||
|
|||
void ofxSurfaceManagerGui::stopDrag() |
|||
{ |
|||
bDrag = false; |
|||
} |
@ -1,46 +0,0 @@ |
|||
#ifndef H_OFX_SURFACE_MANAGER_GUI |
|||
#define H_OFX_SURFACE_MANAGER_GUI |
|||
|
|||
// I'm starting to think, maybe we should use ofxStateMachine here.
|
|||
// Would make sense. TODO later.
|
|||
|
|||
#include "ofEvents.h" |
|||
#include "ofxSurfaceManager.h" |
|||
#include "ofxTextureEditor.h" |
|||
#include "ofxProjectionEditor.h" |
|||
#include "ofxSourcesEditor.h" |
|||
#include "ofxGuiMode.h" |
|||
#include "ofGraphics.h" |
|||
|
|||
class ofxSurfaceManagerGui |
|||
{ |
|||
public: |
|||
ofxSurfaceManagerGui(); |
|||
~ofxSurfaceManagerGui(); |
|||
|
|||
void registerMouseEvents(); |
|||
void unregisterMouseEvents(); |
|||
|
|||
void draw(); |
|||
void mousePressed(ofMouseEventArgs& args); |
|||
void mouseReleased(ofMouseEventArgs& args); |
|||
void mouseDragged(ofMouseEventArgs& args); |
|||
void setSurfaceManager(ofxSurfaceManager* newSurfaceManager); |
|||
void setMode(int newGuiMode); |
|||
void drawSelectedSurfaceHighlight(); |
|||
void drawSelectedSurfaceTextureHighlight(); |
|||
void startDrag(); |
|||
void stopDrag(); |
|||
|
|||
private: |
|||
ofxSurfaceManager* surfaceManager; |
|||
ofxTextureEditor textureEditor; |
|||
ofxProjectionEditor projectionEditor; |
|||
ofxSourcesEditor sourcesEditor; |
|||
int guiMode; |
|||
bool bDrag; |
|||
ofVec2f clickPosition; |
|||
|
|||
}; |
|||
|
|||
#endif |
@ -1,12 +0,0 @@ |
|||
#ifndef H_OFX_SURFACE_TYPE |
|||
#define H_OFX_SURFACE_TYPE |
|||
|
|||
struct ofxSurfaceType |
|||
{ |
|||
enum { |
|||
TRIANGLE_SURFACE, |
|||
QUAD_SURFACE |
|||
}; |
|||
}; |
|||
|
|||
#endif |
@ -1,191 +0,0 @@ |
|||
#include "ofxTextureEditor.h" |
|||
|
|||
ofxTextureEditor::ofxTextureEditor() |
|||
{ |
|||
clear(); |
|||
enable(); |
|||
} |
|||
|
|||
ofxTextureEditor::~ofxTextureEditor() |
|||
{ |
|||
clear(); |
|||
disable(); |
|||
} |
|||
|
|||
void ofxTextureEditor::registerAppEvents() |
|||
{ |
|||
ofAddListener(ofEvents().update, this, &ofxTextureEditor::update); |
|||
} |
|||
|
|||
void ofxTextureEditor::unregisterAppEvents() |
|||
{ |
|||
ofRemoveListener(ofEvents().update, this, &ofxTextureEditor::update); |
|||
} |
|||
|
|||
void ofxTextureEditor::registerKeyEvents() |
|||
{ |
|||
ofAddListener(ofEvents().keyPressed, this, &ofxTextureEditor::keyPressed); |
|||
ofAddListener(ofEvents().keyReleased, this, &ofxTextureEditor::keyReleased); |
|||
} |
|||
|
|||
void ofxTextureEditor::unregisterKeyEvents() |
|||
{ |
|||
ofRemoveListener(ofEvents().keyPressed, this, &ofxTextureEditor::keyPressed); |
|||
ofRemoveListener(ofEvents().keyReleased, this, &ofxTextureEditor::keyReleased); |
|||
} |
|||
|
|||
void ofxTextureEditor::enable() |
|||
{ |
|||
registerAppEvents(); |
|||
registerKeyEvents(); |
|||
bShiftKeyDown = false; |
|||
} |
|||
|
|||
void ofxTextureEditor::disable() |
|||
{ |
|||
unregisterAppEvents(); |
|||
unregisterKeyEvents(); |
|||
} |
|||
|
|||
void ofxTextureEditor::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() ); |
|||
for ( int i=0; i<joints.size(); i++ ) { |
|||
if ( joints[i]->isDragged() || joints[i]->isSelected() ) { |
|||
// update vertex to new location
|
|||
surface->setTexCoord(i, joints[i]->position / textureSize); |
|||
break; |
|||
} |
|||
} |
|||
} |
|||
|
|||
void ofxTextureEditor::keyPressed(ofKeyEventArgs &args) |
|||
{ |
|||
int key = args.key; |
|||
float moveStep; |
|||
|
|||
if (bShiftKeyDown) moveStep = 10.0f; |
|||
else moveStep = 0.5f; |
|||
|
|||
switch (key) { |
|||
case OF_KEY_LEFT: moveSelection(ofVec2f(-moveStep,0.0f)); break; |
|||
case OF_KEY_RIGHT: moveSelection(ofVec2f(moveStep,0.0f)); break; |
|||
case OF_KEY_UP: moveSelection(ofVec2f(0.0f,-moveStep)); break; |
|||
case OF_KEY_DOWN: moveSelection(ofVec2f(0.0f,moveStep)); break; |
|||
case OF_KEY_SHIFT: bShiftKeyDown = true; break; |
|||
} |
|||
} |
|||
|
|||
void ofxTextureEditor::keyReleased(ofKeyEventArgs &args) |
|||
{ |
|||
int key = args.key; |
|||
switch (key) { |
|||
case OF_KEY_SHIFT: bShiftKeyDown = false; break; |
|||
} |
|||
} |
|||
|
|||
|
|||
void ofxTextureEditor::draw() |
|||
{ |
|||
if (surface == NULL) return; |
|||
|
|||
drawJoints(); |
|||
} |
|||
|
|||
void ofxTextureEditor::drawJoints() |
|||
{ |
|||
for ( int i=0; i<joints.size(); i++ ) { |
|||
joints[i]->draw(); |
|||
} |
|||
} |
|||
|
|||
void ofxTextureEditor::setSurface(ofxBaseSurface* newSurface) |
|||
{ |
|||
surface = newSurface; |
|||
createJoints(); |
|||
} |
|||
|
|||
void ofxTextureEditor::clear() |
|||
{ |
|||
surface = NULL; |
|||
clearJoints(); |
|||
} |
|||
|
|||
void ofxTextureEditor::createJoints() |
|||
{ |
|||
if ( surface == NULL ) return; |
|||
clearJoints(); |
|||
vector<ofVec2f>& texCoords = surface->getTexCoords(); |
|||
ofVec2f textureSize = ofVec2f(surface->getTexture()->getWidth(), surface->getTexture()->getHeight()); |
|||
|
|||
for ( int i=0; i<texCoords.size(); i++ ) { |
|||
joints.push_back(new ofxCircleJoint()); |
|||
joints.back()->position = texCoords[i] * textureSize; |
|||
} |
|||
} |
|||
|
|||
void ofxTextureEditor::clearJoints() |
|||
{ |
|||
while ( joints.size() ) { |
|||
delete joints.back(); |
|||
joints.pop_back(); |
|||
} |
|||
} |
|||
|
|||
void ofxTextureEditor::unselectAllJoints() |
|||
{ |
|||
for ( int i=0; i<joints.size(); i++ ) { |
|||
joints[i]->unselect(); |
|||
} |
|||
} |
|||
|
|||
void ofxTextureEditor::moveTexCoords(ofVec2f by) |
|||
{ |
|||
if ( surface == NULL ) return; |
|||
vector<ofVec2f>& texCoords = surface->getTexCoords(); |
|||
ofVec2f textureSize = ofVec2f( surface->getTexture()->getWidth(), surface->getTexture()->getHeight() ); |
|||
for (int i=0; i<texCoords.size(); i++) { |
|||
joints[i]->position += by; |
|||
texCoords[i] = joints[i]->position / textureSize; |
|||
} |
|||
} |
|||
|
|||
void ofxTextureEditor::stopDragJoints() |
|||
{ |
|||
for (int i=0; i<joints.size(); i++){ |
|||
joints[i]->stopDrag(); |
|||
} |
|||
} |
|||
|
|||
void ofxTextureEditor::moveSelection(ofVec2f by) |
|||
{ |
|||
// check if joints selected
|
|||
bool bJointSelected = false; |
|||
ofxBaseJoint* selectedJoint; |
|||
for ( int i=0; i<joints.size(); i++ ) { |
|||
if (joints[i]->isSelected()) { |
|||
bJointSelected = true; |
|||
selectedJoint = joints[i]; |
|||
break; |
|||
} |
|||
} |
|||
|
|||
if ( bJointSelected ) { |
|||
selectedJoint->position += by; |
|||
} else { |
|||
moveTexCoords(by); |
|||
} |
|||
} |
|||
|
|||
ofxCircleJoint* ofxTextureEditor::hitTestJoints(ofVec2f pos) |
|||
{ |
|||
for ( int i=0; i<joints.size(); i++ ) { |
|||
if ( joints[i]->hitTest(pos) ){ |
|||
return joints[i]; |
|||
} |
|||
} |
|||
return NULL; |
|||
} |
@ -1,42 +0,0 @@ |
|||
#ifndef H_OFX_TEXTURE_EDITOR |
|||
#define H_OFX_TEXTURE_EDITOR |
|||
|
|||
#include "ofEvents.h" |
|||
#include "ofxBaseSurface.h" |
|||
#include "ofxCircleJoint.h" |
|||
|
|||
class ofxTextureEditor |
|||
{ |
|||
public: |
|||
ofxTextureEditor(); |
|||
~ofxTextureEditor(); |
|||
|
|||
void registerAppEvents(); |
|||
void unregisterAppEvents(); |
|||
void registerKeyEvents(); |
|||
void unregisterKeyEvents(); |
|||
void enable(); |
|||
void disable(); |
|||
|
|||
void update(ofEventArgs& args); |
|||
void keyPressed(ofKeyEventArgs& args); |
|||
void keyReleased(ofKeyEventArgs& args); |
|||
void draw(); |
|||
void drawJoints(); |
|||
void setSurface(ofxBaseSurface* newSurface); |
|||
void clear(); |
|||
void createJoints(); |
|||
void clearJoints(); |
|||
void unselectAllJoints(); |
|||
void moveTexCoords(ofVec2f by); |
|||
void stopDragJoints(); |
|||
void moveSelection(ofVec2f by); |
|||
ofxCircleJoint* hitTestJoints(ofVec2f pos); |
|||
|
|||
private: |
|||
ofxBaseSurface* surface; |
|||
vector<ofxCircleJoint*> joints; |
|||
bool bShiftKeyDown; |
|||
}; |
|||
|
|||
#endif |
@ -1,146 +0,0 @@ |
|||
#include "ofxTriangleSurface.h" |
|||
|
|||
ofxTriangleSurface::ofxTriangleSurface() |
|||
{ |
|||
cout << "ofxTriangleSurface constructor." << endl; |
|||
setup(); |
|||
} |
|||
|
|||
ofxTriangleSurface::~ofxTriangleSurface() |
|||
{ |
|||
cout << "ofxTriangleSurface destructor." << endl; |
|||
} |
|||
|
|||
void ofxTriangleSurface::setup() |
|||
{ |
|||
// Create 3 points for the triangle
|
|||
ofVec2f p1 = ofVec2f(ofGetWidth()/2.0f, 0); |
|||
ofVec2f p2 = ofVec2f(ofVec2f(0, ofGetHeight())); |
|||
ofVec2f p3 = ofVec2f(ofGetWidth(), ofGetHeight()); |
|||
|
|||
// Create 3 point for the texture coordinates
|
|||
ofVec2f t1 = ofVec2f(0.5f, 0); |
|||
ofVec2f t2 = ofVec2f(0, 1.0f); |
|||
ofVec2f t3 = ofVec2f(1, 1.0f); |
|||
|
|||
setup( p1, p2, p3, t1, t2, t3, texture ); |
|||
} |
|||
|
|||
void ofxTriangleSurface::setup( ofVec2f p1, ofVec2f p2, ofVec2f p3, ofVec2f t1, ofVec2f t2, ofVec2f t3, ofTexture* texturePtr ) |
|||
{ |
|||
// Assign texture
|
|||
texture = texturePtr; |
|||
|
|||
// Clear mesh
|
|||
mesh.clear(); |
|||
|
|||
// Create a surface with the points
|
|||
mesh.addVertex( p1 ); |
|||
mesh.addVertex( p2 ); |
|||
mesh.addVertex( p3 ); |
|||
|
|||
// Add texture coordinates
|
|||
mesh.addTexCoord(t1); |
|||
mesh.addTexCoord(t2); |
|||
mesh.addTexCoord(t3); |
|||
} |
|||
|
|||
void ofxTriangleSurface::draw() |
|||
{ |
|||
texture->bind(); |
|||
mesh.draw(); |
|||
texture->unbind(); |
|||
} |
|||
|
|||
void ofxTriangleSurface::setVertex(int index, ofVec2f p) |
|||
{ |
|||
if ( index > 2 ) { |
|||
ofLog() << "Vertex with this index does not exist: " << index << endl; |
|||
return; |
|||
} |
|||
|
|||
mesh.setVertex(index, p); |
|||
} |
|||
|
|||
void ofxTriangleSurface::setTexCoord(int index, ofVec2f t) |
|||
{ |
|||
if ( index > 2 ) { |
|||
ofLog() << "Texture coordinate with this index does not exist: " << index << endl; |
|||
return; |
|||
} |
|||
|
|||
mesh.setTexCoord(index, t); |
|||
} |
|||
|
|||
int ofxTriangleSurface::getType() |
|||
{ |
|||
return ofxSurfaceType::TRIANGLE_SURFACE; |
|||
} |
|||
|
|||
bool ofxTriangleSurface::hitTest(ofVec2f p) |
|||
{ |
|||
// Construct ofPolyline from vertices
|
|||
ofPolyline line = getHitArea(); |
|||
|
|||
if ( line.inside(p.x, p.y) ) { |
|||
return true; |
|||
} else { |
|||
return false; |
|||
} |
|||
} |
|||
|
|||
ofVec2f ofxTriangleSurface::getVertex(int index) |
|||
{ |
|||
if ( index > 2 ) { |
|||
ofLog() << "Vertex with this index does not exist: " << index << endl; |
|||
throw std::runtime_error("Vertex index out of bounds."); |
|||
} |
|||
|
|||
ofVec3f vert = mesh.getVertex(index); |
|||
return ofVec2f(vert.x, vert.y); |
|||
} |
|||
|
|||
ofVec2f ofxTriangleSurface::getTexCoord(int index) |
|||
{ |
|||
if (index > 2) { |
|||
throw std::runtime_error("Texture coordinate index out of bounds."); |
|||
} |
|||
|
|||
return mesh.getTexCoord(index); |
|||
} |
|||
|
|||
ofPolyline ofxTriangleSurface::getHitArea() |
|||
{ |
|||
ofPolyline line; |
|||
line.addVertex( ofPoint( mesh.getVertex(0).x, mesh.getVertex(0).y ) ); |
|||
line.addVertex( ofPoint( mesh.getVertex(1).x, mesh.getVertex(1).y ) ); |
|||
line.addVertex( ofPoint( mesh.getVertex(2).x, mesh.getVertex(2).y ) ); |
|||
line.close(); |
|||
|
|||
return line; |
|||
} |
|||
|
|||
ofPolyline ofxTriangleSurface::getTextureHitArea() |
|||
{ |
|||
ofPolyline line; |
|||
vector<ofVec2f>& texCoords = mesh.getTexCoords(); |
|||
ofVec2f textureSize = ofVec2f(texture->getWidth(), texture->getHeight()); |
|||
for ( int i=0; i<texCoords.size(); i++ ) { |
|||
line.addVertex( ofPoint( texCoords[i] * textureSize ) ); |
|||
} |
|||
line.close(); |
|||
|
|||
return line; |
|||
} |
|||
|
|||
vector<ofVec3f>& ofxTriangleSurface::getVertices() |
|||
{ |
|||
// return only joint vertices
|
|||
return mesh.getVertices(); |
|||
} |
|||
|
|||
vector<ofVec2f>& ofxTriangleSurface::getTexCoords() |
|||
{ |
|||
|
|||
return mesh.getTexCoords(); |
|||
} |
@ -1,30 +0,0 @@ |
|||
#ifndef H_OFX_TRIANGLE_SURFACE |
|||
#define H_OFX_TRIANGLE_SURFACE |
|||
|
|||
#include "ofMain.h" |
|||
#include "ofxBaseSurface.h" |
|||
#include "ofxSurfaceType.h" |
|||
|
|||
class ofxTriangleSurface : public ofxBaseSurface |
|||
{ |
|||
public: |
|||
ofxTriangleSurface(); |
|||
~ofxTriangleSurface(); |
|||
|
|||
void setup(); |
|||
void setup( ofVec2f p1, ofVec2f p2, ofVec2f p3, ofVec2f t1, ofVec2f t2, ofVec2f t3, ofTexture* texturePtr ); |
|||
void draw(); |
|||
void setVertex( int index, ofVec2f p ); |
|||
void setTexCoord( int index, ofVec2f t ); |
|||
|
|||
int getType(); |
|||
bool hitTest(ofVec2f p); |
|||
ofVec2f getVertex(int index); |
|||
ofVec2f getTexCoord(int index); |
|||
ofPolyline getHitArea(); |
|||
ofPolyline getTextureHitArea(); |
|||
vector<ofVec3f>& getVertices(); |
|||
vector<ofVec2f>& getTexCoords(); |
|||
}; |
|||
|
|||
#endif |
Loading…
Reference in new issue