53 changed files with 2685 additions and 2825 deletions
@ -1,164 +1,183 @@ |
|||||
#include "ofApp.h" |
#include "ofApp.h" |
||||
|
|
||||
void ofApp::setup() |
void ofApp::setup() { |
||||
{ |
bShowInfo = false; |
||||
bShowInfo = false; |
|
||||
|
// check if the surfaces.xml file is there
|
||||
// check if the surfaces.xml file is there
|
// if not - load defaultSurfaces.xml
|
||||
// if not - load defaultSurfaces.xml
|
if (ofFile::doesFileExist("surfaces.xml")) { |
||||
if ( ofFile::doesFileExist("surfaces.xml") ) { |
surfaceManager.loadXmlSettings("surfaces.xml"); |
||||
surfaceManager.loadXmlSettings("surfaces.xml"); |
} else { |
||||
} else { |
surfaceManager.loadXmlSettings("defaultSurfaces.xml"); |
||||
surfaceManager.loadXmlSettings("defaultSurfaces.xml"); |
} |
||||
} |
|
||||
|
// Pass the surface manager to the mapper graphical user interface
|
||||
// Pass the surface manager to the mapper graphical user interface
|
gui.setSurfaceManager(&surfaceManager); |
||||
gui.setSurfaceManager( &surfaceManager ); |
|
||||
|
// Create FBO
|
||||
// Create FBO
|
fbo = new ofFbo(); |
||||
fbo = new ofFbo(); |
fbo->allocate(500, 500); |
||||
fbo->allocate( 500, 500 ); |
setFboAsTexture(); |
||||
setFboAsTexture(); |
|
||||
|
// Genereate rects
|
||||
// Genereate rects
|
int numRects = 20; // change this to add more or less rects
|
||||
int numRects = 20; // change this to add more or less rects
|
for (int i = 0; i < numRects; i++) { |
||||
for ( int i=0; i<numRects; i++ ) { |
rects.push_back(ofRectangle(0, ofRandom(fbo->getHeight()), fbo->getWidth(), |
||||
rects.push_back( ofRectangle(0, ofRandom(fbo->getHeight()), fbo->getWidth(), ofRandom(20)) ); |
ofRandom(20))); |
||||
rectSpeeds.push_back( (1.0f + ofRandom(5)) ); |
rectSpeeds.push_back((1.0f + ofRandom(5))); |
||||
} |
} |
||||
} |
} |
||||
|
|
||||
void ofApp::update() |
void ofApp::update() { |
||||
{ |
// Move rects
|
||||
// Move rects
|
for (int i = 0; i < rects.size(); i++) { |
||||
for ( int i=0; i<rects.size(); i++ ) { |
rects[i].y += rectSpeeds[i]; |
||||
rects[i].y += rectSpeeds[i]; |
if (rects[i].y > fbo->getHeight()) { |
||||
if ( rects[i].y > fbo->getHeight() ) { |
rects[i].y = -rects[i].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] ); |
|
||||
} |
} |
||||
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() |
void ofApp::draw() { |
||||
{ |
// Draw the piMapper GUI
|
||||
// Draw the piMapper GUI
|
gui.draw(); |
||||
gui.draw(); |
|
||||
|
if (bShowInfo) { |
||||
if ( bShowInfo ) { |
// Draw instructions
|
||||
// Draw instructions
|
stringstream ss; |
||||
stringstream ss; |
ss << "There are 4 modes:\n\n"; |
||||
ss << "There are 4 modes:\n\n"; |
ss << " 1. Presentation mode\n"; |
||||
ss << " 1. Presentation mode\n"; |
ss << " 2. Texture mapping mode\n"; |
||||
ss << " 2. Texture mapping mode\n"; |
ss << " 3. Projection mapping mode\n"; |
||||
ss << " 3. Projection mapping mode\n"; |
ss << " 4. Source selection mode\n\n"; |
||||
ss << " 4. Source selection mode\n\n"; |
ss << "You can switch between the modes by using <1>, <2>, <3> and <4> " |
||||
ss << "You can switch between the modes by using <1>, <2>, <3> and <4> keys on the keyboard.\n\n"; |
"keys on the keyboard.\n\n"; |
||||
ss << "Press <r> or <n> to add random or normal surface.\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 <q> to add a new quad surface.\n"; |
||||
ss << "Press <s> to save the composition.\n"; |
ss << "Press <s> to save the composition.\n"; |
||||
ss << "Press <f> to toggle fullscreen.\n"; |
ss << "Press <f> to toggle fullscreen.\n"; |
||||
ss << "Press <a> to reassign the fbo texture to the first surface\n"; |
ss << "Press <a> to reassign the fbo texture to the first surface\n"; |
||||
ss << "Hit <i> to hide this message."; |
ss << "Hit <i> to hide this message."; |
||||
|
|
||||
ofDrawBitmapStringHighlight(ss.str(), 10, 20, ofColor(0,0,0,100), ofColor(255,255,255,200)); |
ofDrawBitmapStringHighlight(ss.str(), 10, 20, ofColor(0, 0, 0, 100), |
||||
} |
ofColor(255, 255, 255, 200)); |
||||
|
} |
||||
} |
} |
||||
|
|
||||
void ofApp::exit() |
void ofApp::exit() { |
||||
{ |
// Clear FBO from mem
|
||||
// Clear FBO from mem
|
delete fbo; |
||||
delete fbo; |
|
||||
} |
} |
||||
|
|
||||
void ofApp::keyPressed(int key) |
void ofApp::keyPressed(int key) { |
||||
{ |
cout << "Key pressed: " << static_cast<char>(key) << endl; |
||||
cout << "Key pressed: " << static_cast<char>(key) << endl; |
|
||||
|
switch (key) { |
||||
switch (key) { |
case '1': |
||||
case '1': gui.setMode(ofxGuiMode::NONE); break; |
gui.setMode(ofx::piMapper::GuiMode::NONE); |
||||
case '2': gui.setMode(ofxGuiMode::TEXTURE_MAPPING); break; |
break; |
||||
case '3': gui.setMode(ofxGuiMode::PROJECTION_MAPPING); break; |
case '2': |
||||
case '4': gui.setMode(ofxGuiMode::SOURCE_SELECTION); break; |
gui.setMode(ofx::piMapper::GuiMode::TEXTURE_MAPPING); |
||||
case 'i': bShowInfo = !bShowInfo; break; |
break; |
||||
case 'r': addRandomSurface(); break; |
case '3': |
||||
case 'q': addQuadSurface(); break; |
gui.setMode(ofx::piMapper::GuiMode::PROJECTION_MAPPING); |
||||
case 'n': addSurface(); break; |
break; |
||||
case 'f': ofToggleFullscreen(); break; |
case '4': |
||||
case 's': surfaceManager.saveXmlSettings("surfaces.xml"); break; |
gui.setMode(ofx::piMapper::GuiMode::SOURCE_SELECTION); |
||||
case 'a': setFboAsTexture(); break; |
break; |
||||
case OF_KEY_BACKSPACE: surfaceManager.removeSelectedSurface(); break; |
case 'i': |
||||
default: break; |
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::addRandomSurface() |
void ofApp::addRandomSurface() { |
||||
{ |
int surfaceType = ofx::piMapper::SurfaceType::TRIANGLE_SURFACE; |
||||
int surfaceType = ofxSurfaceType::TRIANGLE_SURFACE; |
vector<ofVec2f> vertices; |
||||
vector<ofVec2f> vertices; |
vertices.push_back(ofVec2f(ofRandomWidth(), ofRandomHeight())); |
||||
vertices.push_back( ofVec2f( ofRandomWidth(), ofRandomHeight() ) ); |
vertices.push_back(ofVec2f(ofRandomWidth(), ofRandomHeight())); |
||||
vertices.push_back( ofVec2f( ofRandomWidth(), ofRandomHeight() ) ); |
vertices.push_back(ofVec2f(ofRandomWidth(), ofRandomHeight())); |
||||
vertices.push_back( ofVec2f( ofRandomWidth(), ofRandomHeight() ) ); |
vector<ofVec2f> texCoords; |
||||
vector<ofVec2f> texCoords; |
texCoords.push_back(ofVec2f(ofRandomuf(), ofRandomuf())); |
||||
texCoords.push_back( ofVec2f( ofRandomuf(), ofRandomuf() ) ); |
texCoords.push_back(ofVec2f(ofRandomuf(), ofRandomuf())); |
||||
texCoords.push_back( ofVec2f( ofRandomuf(), ofRandomuf() ) ); |
texCoords.push_back(ofVec2f(ofRandomuf(), ofRandomuf())); |
||||
texCoords.push_back( ofVec2f( ofRandomuf(), ofRandomuf() ) ); |
surfaceManager.addSurface(surfaceType, vertices, texCoords); |
||||
surfaceManager.addSurface(surfaceType, vertices, texCoords); |
|
||||
|
// select this surface right away
|
||||
// select this surface right away
|
surfaceManager.selectSurface(surfaceManager.size() - 1); |
||||
surfaceManager.selectSurface(surfaceManager.size()-1); |
|
||||
} |
} |
||||
|
|
||||
void ofApp::addQuadSurface() |
void ofApp::addQuadSurface() { |
||||
{ |
int surfaceType = ofx::piMapper::SurfaceType::QUAD_SURFACE; |
||||
int surfaceType = ofxSurfaceType::QUAD_SURFACE; |
vector<ofVec2f> vertices; |
||||
vector<ofVec2f> vertices; |
|
||||
|
int border = 50; |
||||
int border = 50; |
vertices.push_back(ofVec2f(border, border)); |
||||
vertices.push_back(ofVec2f(border, border)); |
vertices.push_back(ofVec2f(ofGetWidth() - border, border)); |
||||
vertices.push_back(ofVec2f(ofGetWidth() - border, border)); |
vertices.push_back(ofVec2f(ofGetWidth() - border, ofGetHeight() - border)); |
||||
vertices.push_back(ofVec2f(ofGetWidth() - border, ofGetHeight() - border)); |
vertices.push_back(ofVec2f(border, ofGetHeight() - border)); |
||||
vertices.push_back(ofVec2f(border, ofGetHeight() - border)); |
|
||||
|
vector<ofVec2f> texCoords; |
||||
vector<ofVec2f> texCoords; |
texCoords.push_back(ofVec2f(ofVec2f(0.0f, 0.0f))); |
||||
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, 0.0f))); |
texCoords.push_back(ofVec2f(ofVec2f(1.0f, 1.0f))); |
||||
texCoords.push_back(ofVec2f(ofVec2f(1.0f, 1.0f))); |
texCoords.push_back(ofVec2f(ofVec2f(0.0f, 1.0f))); |
||||
texCoords.push_back(ofVec2f(ofVec2f(0.0f, 1.0f))); |
|
||||
|
surfaceManager.addSurface(surfaceType, vertices, texCoords); |
||||
surfaceManager.addSurface(surfaceType, vertices, texCoords); |
|
||||
|
// select this surface right away
|
||||
// select this surface right away
|
surfaceManager.selectSurface(surfaceManager.size() - 1); |
||||
surfaceManager.selectSurface(surfaceManager.size()-1); |
|
||||
} |
} |
||||
|
|
||||
void ofApp::addSurface() |
void ofApp::addSurface() { |
||||
{ |
int surfaceType = ofx::piMapper::SurfaceType::TRIANGLE_SURFACE; |
||||
int surfaceType = ofxSurfaceType::TRIANGLE_SURFACE; |
vector<ofVec2f> vertices; |
||||
vector<ofVec2f> vertices; |
vertices.push_back(ofVec2f((float)ofGetWidth() / 2.0f, 0.0f)); |
||||
vertices.push_back( ofVec2f( (float)ofGetWidth()/2.0f, 0.0f ) ); |
vertices.push_back(ofVec2f((float)ofGetWidth(), (float)ofGetHeight())); |
||||
vertices.push_back( ofVec2f( (float)ofGetWidth(), (float)ofGetHeight() ) ); |
vertices.push_back(ofVec2f(0.0f, (float)ofGetHeight())); |
||||
vertices.push_back( ofVec2f( 0.0f, (float)ofGetHeight() ) ); |
vector<ofVec2f> texCoords; |
||||
vector<ofVec2f> texCoords; |
texCoords.push_back(ofVec2f(0.5f, 0.0f)); |
||||
texCoords.push_back( ofVec2f( 0.5f, 0.0f ) ); |
texCoords.push_back(ofVec2f(1.0f, 1.0f)); |
||||
texCoords.push_back( ofVec2f( 1.0f, 1.0f ) ); |
texCoords.push_back(ofVec2f(0.0f, 1.0f)); |
||||
texCoords.push_back( ofVec2f( 0.0f, 1.0f ) ); |
surfaceManager.addSurface(surfaceType, vertices, texCoords); |
||||
surfaceManager.addSurface(surfaceType, vertices, texCoords); |
|
||||
|
// select this surface right away
|
||||
// select this surface right away
|
surfaceManager.selectSurface(surfaceManager.size() - 1); |
||||
surfaceManager.selectSurface(surfaceManager.size()-1); |
|
||||
} |
} |
||||
|
|
||||
void ofApp::setFboAsTexture() |
void ofApp::setFboAsTexture() { |
||||
{ |
surfaceManager.getSurface(0)->setTexture(&fbo->getTextureReference()); |
||||
surfaceManager.getSurface(0)->setTexture( &fbo->getTextureReference() ); |
|
||||
} |
} |
@ -1,31 +1,27 @@ |
|||||
#ifndef H_OF_APP |
#pragma once |
||||
#define H_OF_APP |
|
||||
|
|
||||
#include "ofMain.h" |
#include "ofMain.h" |
||||
#include "ofxPiMapper.h" |
#include "ofxPiMapper.h" |
||||
|
|
||||
class ofApp : public ofBaseApp |
class ofApp : public ofBaseApp { |
||||
{ |
public: |
||||
public: |
void setup(); |
||||
void setup(); |
void update(); |
||||
void update(); |
void draw(); |
||||
void draw(); |
void exit(); |
||||
void exit(); |
|
||||
|
|
||||
void keyPressed(int key); |
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; |
|
||||
}; |
|
||||
|
|
||||
#endif |
void addRandomSurface(); |
||||
|
void addQuadSurface(); |
||||
|
void addSurface(); |
||||
|
void setFboAsTexture(); |
||||
|
|
||||
|
ofImage image; |
||||
|
ofx::piMapper::SurfaceManager surfaceManager; |
||||
|
ofx::piMapper::SurfaceManagerGui gui; |
||||
|
bool bShowInfo; |
||||
|
ofFbo* fbo; |
||||
|
vector<ofRectangle> rects; |
||||
|
vector<float> rectSpeeds; |
||||
|
}; |
@ -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,70 @@ |
|||||
|
#include "BaseSurface.h" |
||||
|
|
||||
|
namespace ofx { |
||||
|
namespace piMapper { |
||||
|
|
||||
|
BaseSurface::BaseSurface() { |
||||
|
ofEnableNormalizedTexCoords(); |
||||
|
createDefaultTexture(); |
||||
|
} |
||||
|
|
||||
|
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); |
||||
|
|
||||
|
// Assign default texture to texture pointer
|
||||
|
texture = &defaultTexture; |
||||
|
} |
||||
|
|
||||
|
void BaseSurface::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 BaseSurface::setTexture(ofTexture* texturePtr) { texture = texturePtr; } |
||||
|
|
||||
|
ofTexture* BaseSurface::getTexture() { return texture; } |
||||
|
|
||||
|
ofTexture* BaseSurface::getDefaultTexture() { return &defaultTexture; } |
||||
|
} |
||||
|
} |
@ -0,0 +1,40 @@ |
|||||
|
#pragma once |
||||
|
|
||||
|
#include "ofMain.h" |
||||
|
#include <string> |
||||
|
|
||||
|
using namespace std; |
||||
|
|
||||
|
namespace ofx { |
||||
|
namespace piMapper { |
||||
|
class BaseSurface { |
||||
|
public: |
||||
|
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); |
||||
|
|
||||
|
ofTexture* getTexture(); |
||||
|
ofTexture* getDefaultTexture(); |
||||
|
|
||||
|
protected: |
||||
|
ofMesh mesh; |
||||
|
ofTexture* texture; |
||||
|
ofTexture defaultTexture; |
||||
|
|
||||
|
void createDefaultTexture(); |
||||
|
}; |
||||
|
} |
||||
|
} |
@ -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,243 @@ |
|||||
|
#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, texture); |
||||
|
} |
||||
|
|
||||
|
void QuadSurface::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); |
||||
|
|
||||
|
// 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(mesh.haveVertsChanged() || mesh.haveTexCoordsChanged()){
|
||||
|
calculate4dTextureCoords(); |
||||
|
}*/ |
||||
|
glEnableClientState(GL_TEXTURE_COORD_ARRAY); |
||||
|
glTexCoordPointer(4, GL_FLOAT, 0, quadTexCoordinates); |
||||
|
glVertexPointer(3, GL_FLOAT, 0, quadVertices); |
||||
|
|
||||
|
texture->bind(); |
||||
|
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, quadIndices); |
||||
|
texture->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(texture->getWidth(), texture->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, ofTexture* texturePtr); |
||||
|
|
||||
|
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,121 @@ |
|||||
|
#include "SourcesEditor.h" |
||||
|
|
||||
|
namespace ofx { |
||||
|
namespace piMapper { |
||||
|
SourcesEditor::SourcesEditor() { |
||||
|
defImgDir = DEFAULT_IMAGES_DIR; |
||||
|
registerAppEvents(); |
||||
|
} |
||||
|
|
||||
|
SourcesEditor::~SourcesEditor() { |
||||
|
unregisterAppEvents(); |
||||
|
delete gui; |
||||
|
while (images.size()) { |
||||
|
delete images.back(); |
||||
|
images.pop_back(); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
void SourcesEditor::registerAppEvents() { |
||||
|
ofAddListener(ofEvents().setup, this, &SourcesEditor::setup); |
||||
|
} |
||||
|
|
||||
|
void SourcesEditor::unregisterAppEvents() { |
||||
|
ofRemoveListener(ofEvents().setup, this, &SourcesEditor::setup); |
||||
|
} |
||||
|
|
||||
|
void SourcesEditor::setup(ofEventArgs& args) { |
||||
|
gui = new RadioList(); |
||||
|
|
||||
|
// 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->setup("Images", vnames); |
||||
|
gui->setPosition(20, 20); |
||||
|
ofAddListener(gui->radioSelectedEvent, this, &SourcesEditor::guiEvent); |
||||
|
} |
||||
|
|
||||
|
void SourcesEditor::draw() { |
||||
|
// Don't draw if there is no source selected
|
||||
|
if (surfaceManager->getSelectedSurface() == NULL) { |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
gui->draw(); |
||||
|
} |
||||
|
|
||||
|
void SourcesEditor::loadImage(string name, string path) { |
||||
|
images.push_back(new ofImage()); |
||||
|
images.back()->loadImage(path); |
||||
|
|
||||
|
imageNames.push_back(name); |
||||
|
|
||||
|
ofSendMessage("imageLoaded"); |
||||
|
} |
||||
|
|
||||
|
void SourcesEditor::disable() { gui->disable(); } |
||||
|
|
||||
|
void SourcesEditor::enable() { |
||||
|
// Don't enable if there is no surface selected
|
||||
|
if (surfaceManager->getSelectedSurface() == NULL) { |
||||
|
cout << "No surface selected. Not enable()ing source list." << endl; |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
gui->enable(); |
||||
|
} |
||||
|
|
||||
|
void SourcesEditor::setSurfaceManager(SurfaceManager* newSurfaceManager) { |
||||
|
surfaceManager = newSurfaceManager; |
||||
|
} |
||||
|
|
||||
|
void SourcesEditor::selectImageSourceRadioButton(string name) { |
||||
|
if (name == "none") { |
||||
|
gui->unselectAll(); |
||||
|
return; |
||||
|
} else { |
||||
|
int i; |
||||
|
for (i = 0; i < gui->size(); i++) { |
||||
|
if (gui->getItemName(i) == name) { |
||||
|
gui->selectItem(i); |
||||
|
return; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
int SourcesEditor::getLoadedTexCount() { return images.size(); } |
||||
|
|
||||
|
ofTexture* SourcesEditor::getTexture(int index) { |
||||
|
if (index >= images.size()) { |
||||
|
throw std::runtime_error("Texture index out of bounds."); |
||||
|
} |
||||
|
|
||||
|
return &images[index]->getTextureReference(); |
||||
|
} |
||||
|
|
||||
|
void SourcesEditor::guiEvent(string& imageName) { |
||||
|
string name = imageName; |
||||
|
|
||||
|
if (surfaceManager->getSelectedSurface() == NULL) { |
||||
|
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(); |
||||
|
} |
||||
|
} |
||||
|
} |
@ -0,0 +1,40 @@ |
|||||
|
#pragma once |
||||
|
|
||||
|
#include "ofGraphics.h" |
||||
|
#include "ofEvents.h" |
||||
|
#include "SurfaceManager.h" |
||||
|
#include "RadioList.h" |
||||
|
|
||||
|
#define DEFAULT_IMAGES_DIR "sources/images/"; |
||||
|
|
||||
|
namespace ofx { |
||||
|
namespace piMapper { |
||||
|
class SourcesEditor { |
||||
|
public: |
||||
|
SourcesEditor(); |
||||
|
~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); |
||||
|
void selectImageSourceRadioButton(string name); |
||||
|
|
||||
|
int getLoadedTexCount(); |
||||
|
ofTexture* getTexture(int index); |
||||
|
|
||||
|
private: |
||||
|
SurfaceManager* surfaceManager; |
||||
|
RadioList* gui; |
||||
|
string defImgDir; |
||||
|
void guiEvent(string& imageName); |
||||
|
vector<ofImage*> images; |
||||
|
vector<string> imageNames; |
||||
|
}; |
||||
|
} |
||||
|
} |
@ -0,0 +1,462 @@ |
|||||
|
#include "SurfaceManager.h" |
||||
|
|
||||
|
namespace ofx { |
||||
|
namespace piMapper { |
||||
|
SurfaceManager::SurfaceManager() {} |
||||
|
|
||||
|
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 { |
||||
|
throw std::runtime_error("Attempt to add non-existing surface type."); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
void SurfaceManager::addSurface(int surfaceType, ofTexture* texturePtr) { |
||||
|
if (surfaceType == SurfaceType::TRIANGLE_SURFACE) { |
||||
|
surfaces.push_back(new TriangleSurface()); |
||||
|
surfaces.back()->setTexture(texturePtr); |
||||
|
} else if (surfaceType == SurfaceType::QUAD_SURFACE) { |
||||
|
surfaces.push_back(new QuadSurface()); |
||||
|
surfaces.back()->setTexture(texturePtr); |
||||
|
} else { |
||||
|
throw std::runtime_error("Attempt to add non-existing surface type."); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
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 { |
||||
|
throw std::runtime_error("Attempt to add non-existing surface type."); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
void SurfaceManager::addSurface(int surfaceType, ofTexture* texturePtr, |
||||
|
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()->setTexture(texturePtr); |
||||
|
|
||||
|
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()->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 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::manageMemory() { |
||||
|
// check if each of the sources is assigned to a surface or not
|
||||
|
for (int i = 0; i < loadedImageSources.size(); i++) { |
||||
|
bool bAssigned = false; |
||||
|
|
||||
|
for (int j = 0; j < surfaces.size(); j++) { |
||||
|
if (surfaces[j]->getTexture() == |
||||
|
&loadedImageSources[i]->getTextureReference()) { |
||||
|
bAssigned = true; |
||||
|
break; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
if (!bAssigned) { |
||||
|
// purge the image source from memory
|
||||
|
delete loadedImageSources[i]; |
||||
|
loadedImageSources.erase(loadedImageSources.begin() + i); |
||||
|
cout << "Deleting image source: " << loadedImageSourceNames[i] << endl; |
||||
|
loadedImageSourceNames.erase(loadedImageSourceNames.begin() + i); |
||||
|
i--; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
void SurfaceManager::clear() { |
||||
|
// delete all extra allocations from the heap
|
||||
|
while (surfaces.size()) { |
||||
|
delete surfaces.back(); |
||||
|
surfaces.pop_back(); |
||||
|
} |
||||
|
|
||||
|
while (loadedImageSources.size()) { |
||||
|
delete loadedImageSources.back(); |
||||
|
loadedImageSources.pop_back(); |
||||
|
} |
||||
|
|
||||
|
while (loadedImageSourceNames.size()) { |
||||
|
loadedImageSourceNames.pop_back(); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
// String getTypeString(SurfaceType e)
|
||||
|
// {
|
||||
|
// switch e
|
||||
|
// {
|
||||
|
// case TRINAGLE_SURFACE: return "TRINAGLE_SURFACE";
|
||||
|
// case QUAD_SURFACE: return "QUAD_SURFACE";
|
||||
|
// default: throw Exception("Bad MyEnum");
|
||||
|
// }
|
||||
|
// }
|
||||
|
|
||||
|
void SurfaceManager::saveXmlSettings(string fileName) { |
||||
|
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"); |
||||
|
|
||||
|
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 == SurfaceType::TRIANGLE_SURFACE
|
||||
|
// SurfaceType surfaceType = &surface->getType();
|
||||
|
// xmlSettings.addValue("surface-type", surfaceType);
|
||||
|
// xmlSettings.popTag(); // type
|
||||
|
|
||||
|
xmlSettings.popTag(); // surface
|
||||
|
} |
||||
|
xmlSettings.popTag(); // surfaces
|
||||
|
|
||||
|
xmlSettings.save(fileName); |
||||
|
} |
||||
|
|
||||
|
void SurfaceManager::loadXmlSettings(string fileName) { |
||||
|
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(SurfaceType::TRIANGLE_SURFACE, sourceTexture, 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" && sourceTexture != NULL) { |
||||
|
addSurface(SurfaceType::QUAD_SURFACE, sourceTexture, vertices, |
||||
|
texCoords); |
||||
|
} else { |
||||
|
addSurface(SurfaceType::QUAD_SURFACE, vertices, texCoords); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
xmlSettings.popTag(); // surface
|
||||
|
} |
||||
|
|
||||
|
xmlSettings.popTag(); // surfaces
|
||||
|
} |
||||
|
|
||||
|
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; } |
||||
|
|
||||
|
ofTexture* SurfaceManager::loadImageSource(string name, string path) { |
||||
|
// check if it is loaded
|
||||
|
for (int i = 0; i < loadedImageSourceNames.size(); i++) { |
||||
|
if (loadedImageSourceNames[i] == name) { |
||||
|
// this image is already loaded
|
||||
|
return &loadedImageSources[i]->getTextureReference(); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
// not loaded - load
|
||||
|
ofImage* image = new ofImage(); |
||||
|
if (!image->loadImage(path)) { |
||||
|
return NULL; |
||||
|
} |
||||
|
loadedImageSources.push_back(image); |
||||
|
loadedImageSourceNames.push_back(name); |
||||
|
return &image->getTextureReference(); |
||||
|
} |
||||
|
|
||||
|
string SurfaceManager::getSelectedSurfaceSourceName() { |
||||
|
if (selectedSurface == NULL) { |
||||
|
return "none"; |
||||
|
} |
||||
|
|
||||
|
return getSurfaceSourceName(selectedSurface); |
||||
|
} |
||||
|
|
||||
|
string SurfaceManager::getSurfaceSourceName(BaseSurface* surface) { |
||||
|
ofTexture* tex = surface->getTexture(); |
||||
|
for (int i = 0; i < loadedImageSources.size(); i++) { |
||||
|
if (tex == &loadedImageSources[i]->getTextureReference()) { |
||||
|
return loadedImageSourceNames[i]; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
return "none"; |
||||
|
} |
||||
|
|
||||
|
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,50 @@ |
|||||
|
#pragma once |
||||
|
|
||||
|
#include "BaseSurface.h" |
||||
|
#include "TriangleSurface.h" |
||||
|
#include "QuadSurface.h" |
||||
|
#include "SurfaceType.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, 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); |
||||
|
|
||||
|
BaseSurface* getSurface(int index); |
||||
|
int size(); |
||||
|
BaseSurface* selectSurface(int index); |
||||
|
BaseSurface* getSelectedSurface(); |
||||
|
void deselectSurface(); |
||||
|
ofTexture* loadImageSource(string name, string path); |
||||
|
string getSelectedSurfaceSourceName(); |
||||
|
string getSurfaceSourceName(BaseSurface* surface); |
||||
|
|
||||
|
private: |
||||
|
vector<BaseSurface*> surfaces; |
||||
|
BaseSurface* selectedSurface; |
||||
|
vector<string> loadedImageSourceNames; |
||||
|
vector<ofImage*> loadedImageSources; |
||||
|
ofxXmlSettings xmlSettings; |
||||
|
}; |
||||
|
} |
||||
|
} |
@ -0,0 +1,243 @@ |
|||||
|
#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); |
||||
|
} |
||||
|
|
||||
|
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,46 @@ |
|||||
|
#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 setMode(int newGuiMode); |
||||
|
void drawSelectedSurfaceHighlight(); |
||||
|
void drawSelectedSurfaceTextureHighlight(); |
||||
|
void startDrag(); |
||||
|
void stopDrag(); |
||||
|
|
||||
|
private: |
||||
|
SurfaceManager* surfaceManager; |
||||
|
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,189 @@ |
|||||
|
#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->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 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->getTexture()->getWidth(), |
||||
|
surface->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->getTexture()->getWidth(), |
||||
|
surface->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); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
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,43 @@ |
|||||
|
#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); |
||||
|
CircleJoint* hitTestJoints(ofVec2f pos); |
||||
|
|
||||
|
private: |
||||
|
BaseSurface* surface; |
||||
|
vector<CircleJoint*> joints; |
||||
|
bool bShiftKeyDown; |
||||
|
}; |
||||
|
} |
||||
|
} |
@ -0,0 +1,139 @@ |
|||||
|
#include "TriangleSurface.h" |
||||
|
|
||||
|
namespace ofx { |
||||
|
namespace piMapper { |
||||
|
TriangleSurface::TriangleSurface() { |
||||
|
cout << "TriangleSurface constructor." << endl; |
||||
|
setup(); |
||||
|
} |
||||
|
|
||||
|
TriangleSurface::~TriangleSurface() { |
||||
|
cout << "TriangleSurface destructor." << endl; |
||||
|
} |
||||
|
|
||||
|
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, texture); |
||||
|
} |
||||
|
|
||||
|
void TriangleSurface::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 TriangleSurface::draw() { |
||||
|
texture->bind(); |
||||
|
mesh.draw(); |
||||
|
texture->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(texture->getWidth(), texture->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, ofTexture* texturePtr); |
||||
|
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(); |
||||
|
}; |
||||
|
} |
||||
|
} |
@ -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,40 +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 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); |
|
||||
|
|
||||
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,4 @@ |
|||||
#ifndef H_OFX_PI_MAPPER |
#pragma once |
||||
#define H_OFX_PI_MAPPER |
|
||||
|
|
||||
#include "ofxSurfaceManager.h" |
#include "SurfaceManager.h" |
||||
#include "ofxSurfaceManagerGui.h" |
#include "SurfaceManagerGui.h" |
||||
|
|
||||
#endif |
|
@ -1,267 +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; |
|
||||
surfaceManager->getSelectedSurface()->moveBy(by); |
|
||||
/*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,262 +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); |
|
||||
|
|
||||
// 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 ofxQuadSurface::draw() |
|
||||
{ |
|
||||
/*if(mesh.haveVertsChanged() || mesh.haveTexCoordsChanged()){
|
|
||||
calculate4dTextureCoords(); |
|
||||
}*/ |
|
||||
glEnableClientState(GL_TEXTURE_COORD_ARRAY); |
|
||||
glTexCoordPointer(4, GL_FLOAT, 0, quadTexCoordinates); |
|
||||
glVertexPointer(3, GL_FLOAT, 0, quadVertices); |
|
||||
|
|
||||
texture->bind(); |
|
||||
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, quadIndices); |
|
||||
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); |
|
||||
calculate4dTextureCoords(); |
|
||||
} |
|
||||
|
|
||||
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); |
|
||||
calculate4dTextureCoords(); |
|
||||
} |
|
||||
|
|
||||
void ofxQuadSurface::moveBy(ofVec2f v) |
|
||||
{ |
|
||||
vector<ofVec3f>& vertices = getVertices(); |
|
||||
for (int i=0; i<vertices.size(); i++) { |
|
||||
vertices[i] += v; |
|
||||
} |
|
||||
calculate4dTextureCoords(); |
|
||||
} |
|
||||
|
|
||||
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(); |
|
||||
} |
|
||||
|
|
||||
void ofxQuadSurface::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; |
|
||||
|
|
||||
} |
|
@ -1,40 +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 ); |
|
||||
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]; |
|
||||
}; |
|
||||
|
|
||||
#endif |
|
@ -1,135 +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 ofxRadioList(); |
|
||||
|
|
||||
// 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->setup("Images", vnames); |
|
||||
gui->setPosition(20, 20); |
|
||||
ofAddListener(gui->radioSelectedEvent, this, &ofxSourcesEditor::guiEvent); |
|
||||
} |
|
||||
|
|
||||
void ofxSourcesEditor::draw() |
|
||||
{ |
|
||||
// Don't draw if there is no source selected
|
|
||||
if ( surfaceManager->getSelectedSurface() == NULL ) { |
|
||||
return; |
|
||||
} |
|
||||
|
|
||||
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() |
|
||||
{ |
|
||||
// Don't enable if there is no surface selected
|
|
||||
if ( surfaceManager->getSelectedSurface() == NULL ) { |
|
||||
cout << "No surface selected. Not enable()ing source list." << endl; |
|
||||
return; |
|
||||
} |
|
||||
|
|
||||
gui->enable(); |
|
||||
} |
|
||||
|
|
||||
void ofxSourcesEditor::setSurfaceManager(ofxSurfaceManager *newSurfaceManager) |
|
||||
{ |
|
||||
surfaceManager = newSurfaceManager; |
|
||||
} |
|
||||
|
|
||||
void ofxSourcesEditor::selectImageSourceRadioButton(string name) |
|
||||
{ |
|
||||
if (name == "none") { |
|
||||
gui->unselectAll(); |
|
||||
return; |
|
||||
} else { |
|
||||
int i; |
|
||||
for (i = 0; i < gui->size(); i++) { |
|
||||
if (gui->getItemName(i) == name) { |
|
||||
gui->selectItem(i); |
|
||||
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(string &imageName) |
|
||||
{ |
|
||||
string name = imageName; |
|
||||
|
|
||||
if ( surfaceManager->getSelectedSurface() == NULL ) { |
|
||||
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,40 +0,0 @@ |
|||||
#ifndef H_OFX_SOURCES_EDITOR |
|
||||
#define H_OFX_SOURCES_EDITOR |
|
||||
|
|
||||
#include "ofGraphics.h" |
|
||||
#include "ofEvents.h" |
|
||||
#include "ofxSurfaceManager.h" |
|
||||
#include "ofxRadioList.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; |
|
||||
ofxRadioList* gui; |
|
||||
string defImgDir; |
|
||||
void guiEvent(string &imageName); |
|
||||
vector<ofImage*> images; |
|
||||
vector<string> imageNames; |
|
||||
}; |
|
||||
|
|
||||
#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,154 +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); |
|
||||
} |
|
||||
|
|
||||
void ofxTriangleSurface::moveBy(ofVec2f v) |
|
||||
{ |
|
||||
vector<ofVec3f>& vertices = getVertices(); |
|
||||
for (int i=0; i<vertices.size(); i++) { |
|
||||
vertices[i] += v; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
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,31 +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 ); |
|
||||
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(); |
|
||||
}; |
|
||||
|
|
||||
#endif |
|
@ -0,0 +1,155 @@ |
|||||
|
#include "RadioList.h" |
||||
|
|
||||
|
namespace ofx { |
||||
|
namespace piMapper { |
||||
|
RadioList::RadioList() { |
||||
|
storedTitle = ""; |
||||
|
storedSelectedItem = 0; |
||||
|
} |
||||
|
|
||||
|
RadioList::RadioList(vector<string>& labels) { |
||||
|
RadioList(); |
||||
|
setup(labels); |
||||
|
} |
||||
|
|
||||
|
RadioList::RadioList(string title, vector<string>& labels) { |
||||
|
RadioList(); |
||||
|
setup(title, labels); |
||||
|
} |
||||
|
|
||||
|
RadioList::~RadioList() { clear(); } |
||||
|
|
||||
|
void RadioList::setup(vector<string>& labels) { |
||||
|
// Copy incomming labels for later use
|
||||
|
storedLabels = labels; |
||||
|
|
||||
|
// 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); |
||||
|
} |
||||
|
|
||||
|
cout << "num items: " << guiGroup.getNumControls() << endl; |
||||
|
} |
||||
|
|
||||
|
void RadioList::setup(string title, vector<string>& labels) { |
||||
|
// Store title for later use
|
||||
|
storedTitle = title; |
||||
|
guiGroup.setName(title); |
||||
|
setup(labels); |
||||
|
} |
||||
|
|
||||
|
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(); |
||||
|
ofNotifyEvent(radioSelectedEvent, name, this); |
||||
|
|
||||
|
storedSelectedItem = index; |
||||
|
} |
||||
|
|
||||
|
void RadioList::enable() { |
||||
|
if (guiGroup.getNumControls() >= 0) { |
||||
|
clear(); |
||||
|
} |
||||
|
|
||||
|
// Rebuild everyting
|
||||
|
setup(storedTitle, storedLabels); |
||||
|
|
||||
|
// 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 guiGroup.getNumControls(); } |
||||
|
|
||||
|
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,51 @@ |
|||||
|
#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); |
||||
|
RadioList(string title, vector<string> &labels); |
||||
|
~RadioList(); |
||||
|
|
||||
|
void setup(vector<string> &labels); |
||||
|
void setup(string title, vector<string> &labels); |
||||
|
void draw(); |
||||
|
void setTitle(string title); |
||||
|
void setPosition(ofPoint p); |
||||
|
void setPosition(float x, float y); |
||||
|
void selectItem(int index); |
||||
|
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> radioSelectedEvent; |
||||
|
|
||||
|
private: |
||||
|
vector<string> storedLabels; |
||||
|
string storedTitle; |
||||
|
ofxGuiGroup guiGroup; |
||||
|
int storedSelectedItem; |
||||
|
|
||||
|
void onToggleClicked(bool &toggleValue); |
||||
|
}; |
||||
|
} |
||||
|
} |
@ -1,188 +0,0 @@ |
|||||
#include "ofxRadioList.h" |
|
||||
|
|
||||
ofxRadioList::ofxRadioList() |
|
||||
{ |
|
||||
storedTitle = ""; |
|
||||
storedSelectedItem = 0; |
|
||||
} |
|
||||
|
|
||||
ofxRadioList::ofxRadioList(vector<string> &labels) |
|
||||
{ |
|
||||
ofxRadioList(); |
|
||||
setup(labels); |
|
||||
} |
|
||||
|
|
||||
ofxRadioList::ofxRadioList(string title, vector<string> &labels) |
|
||||
{ |
|
||||
ofxRadioList(); |
|
||||
setup(title, labels); |
|
||||
} |
|
||||
|
|
||||
ofxRadioList::~ofxRadioList() |
|
||||
{ |
|
||||
clear(); |
|
||||
} |
|
||||
|
|
||||
void ofxRadioList::setup(vector<string> &labels) |
|
||||
{ |
|
||||
// Copy incomming labels for later use
|
|
||||
storedLabels = labels; |
|
||||
|
|
||||
// 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, &ofxRadioList::onToggleClicked); |
|
||||
guiGroup.add(toggle); |
|
||||
} |
|
||||
|
|
||||
cout << "num items: " << guiGroup.getNumControls() << endl; |
|
||||
} |
|
||||
|
|
||||
void ofxRadioList::setup(string title, vector<string> &labels) |
|
||||
{ |
|
||||
// Store title for later use
|
|
||||
storedTitle = title; |
|
||||
guiGroup.setName(title); |
|
||||
setup(labels); |
|
||||
} |
|
||||
|
|
||||
void ofxRadioList::draw() |
|
||||
{ |
|
||||
guiGroup.draw(); |
|
||||
} |
|
||||
|
|
||||
void ofxRadioList::setTitle(string title) |
|
||||
{ |
|
||||
storedTitle = title; |
|
||||
guiGroup.setName(title); |
|
||||
} |
|
||||
|
|
||||
void ofxRadioList::setPosition(ofPoint p) |
|
||||
{ |
|
||||
guiGroup.setPosition(p); |
|
||||
} |
|
||||
|
|
||||
void ofxRadioList::setPosition(float x, float y) |
|
||||
{ |
|
||||
guiGroup.setPosition(x, y); |
|
||||
} |
|
||||
|
|
||||
void ofxRadioList::selectItem(int index) |
|
||||
{ |
|
||||
if (index >= guiGroup.getNumControls()) { |
|
||||
return; |
|
||||
} |
|
||||
|
|
||||
unselectAll(); |
|
||||
|
|
||||
ofxToggle* toggle = static_cast<ofxToggle*>(guiGroup.getControl(index)); |
|
||||
toggle->removeListener(this, &ofxRadioList::onToggleClicked); |
|
||||
*toggle = true; // Select the specific radio button
|
|
||||
toggle->addListener(this, &ofxRadioList::onToggleClicked); |
|
||||
string name = toggle->getName(); |
|
||||
ofNotifyEvent(radioSelectedEvent, name, this); |
|
||||
|
|
||||
storedSelectedItem = index; |
|
||||
} |
|
||||
|
|
||||
void ofxRadioList::enable() |
|
||||
{ |
|
||||
if (guiGroup.getNumControls() >= 0) { |
|
||||
clear(); |
|
||||
} |
|
||||
|
|
||||
// Rebuild everyting
|
|
||||
setup(storedTitle, storedLabels); |
|
||||
|
|
||||
// Select the stored selected item without throwing an event
|
|
||||
ofxToggle* toggle = static_cast<ofxToggle*>(guiGroup.getControl(storedSelectedItem)); |
|
||||
toggle->removeListener(this, &ofxRadioList::onToggleClicked); |
|
||||
*toggle = true; |
|
||||
toggle->addListener(this, &ofxRadioList::onToggleClicked); |
|
||||
|
|
||||
cout << "num items after enable: " << guiGroup.getNumControls() << endl; |
|
||||
} |
|
||||
|
|
||||
void ofxRadioList::disable() |
|
||||
{ |
|
||||
// Just remove everything
|
|
||||
clear(); |
|
||||
} |
|
||||
|
|
||||
void ofxRadioList::clear() |
|
||||
{ |
|
||||
int i; |
|
||||
for (i = 0; i < guiGroup.getNumControls(); i++) { |
|
||||
ofxToggle* toggle = static_cast<ofxToggle*>(guiGroup.getControl(i)); |
|
||||
toggle->removeListener(this, &ofxRadioList::onToggleClicked); |
|
||||
delete toggle; |
|
||||
} |
|
||||
guiGroup.clear(); |
|
||||
} |
|
||||
|
|
||||
void ofxRadioList::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, &ofxRadioList::onToggleClicked); |
|
||||
*toggle = false; |
|
||||
toggle->addListener(this, &ofxRadioList::onToggleClicked); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
ofPoint ofxRadioList::getPosition() |
|
||||
{ |
|
||||
return guiGroup.getPosition(); |
|
||||
} |
|
||||
|
|
||||
float ofxRadioList::getWidth() |
|
||||
{ |
|
||||
return guiGroup.getWidth(); |
|
||||
} |
|
||||
|
|
||||
float ofxRadioList::getHeight() |
|
||||
{ |
|
||||
return guiGroup.getHeight(); |
|
||||
} |
|
||||
|
|
||||
string ofxRadioList::getTitle() |
|
||||
{ |
|
||||
return guiGroup.getName(); |
|
||||
} |
|
||||
|
|
||||
string ofxRadioList::getItemName(int index) |
|
||||
{ |
|
||||
if (index >= guiGroup.getNumControls()) { |
|
||||
return ""; |
|
||||
} |
|
||||
|
|
||||
ofxToggle* toggle = static_cast<ofxToggle*>(guiGroup.getControl(index)); |
|
||||
return toggle->getName(); |
|
||||
} |
|
||||
|
|
||||
int ofxRadioList::size() |
|
||||
{ |
|
||||
return guiGroup.getNumControls(); |
|
||||
} |
|
||||
|
|
||||
void ofxRadioList::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; |
|
||||
} |
|
||||
} |
|
||||
} |
|
@ -1,46 +0,0 @@ |
|||||
#pragma once |
|
||||
|
|
||||
#include "ofGraphics.h" |
|
||||
#include "ofxGuiGroup.h" |
|
||||
#include "ofxToggle.h" |
|
||||
#include "ofxLabel.h" |
|
||||
|
|
||||
class ofxRadioList |
|
||||
{ |
|
||||
public: |
|
||||
ofxRadioList(); |
|
||||
ofxRadioList(vector<string> &labels); |
|
||||
ofxRadioList(string title, vector<string> &labels); |
|
||||
~ofxRadioList(); |
|
||||
|
|
||||
void setup(vector<string> &labels); |
|
||||
void setup(string title, vector<string> &labels); |
|
||||
void draw(); |
|
||||
void setTitle(string title); |
|
||||
void setPosition(ofPoint p); |
|
||||
void setPosition(float x, float y); |
|
||||
void selectItem(int index); |
|
||||
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(ofxRadioListInstance.radioSelectedEvent, listenerClassPtr, &listenerClass::listenerMethod)
|
|
||||
// to listen to this. Listner method void listenerMethod(string & radioName)
|
|
||||
ofEvent<string> radioSelectedEvent; |
|
||||
|
|
||||
private: |
|
||||
vector<string> storedLabels; |
|
||||
string storedTitle; |
|
||||
ofxGuiGroup guiGroup; |
|
||||
int storedSelectedItem; |
|
||||
|
|
||||
void onToggleClicked(bool &toggleValue); |
|
||||
}; |
|
Loading…
Reference in new issue