Browse Source
- Add UndoableCommand base class - Add CommandManager that handles undoing - Add test to main ofxPiMapper filesmaster
11 changed files with 407 additions and 221 deletions
@ -0,0 +1,42 @@ |
|||||
|
// Command base class for separating ofxPiMapper available commands from the core.
|
||||
|
// Created by Krisjanis Rijnieks 2015-03-23
|
||||
|
|
||||
|
// Good example
|
||||
|
// http://gameprogrammingpatterns.com/command.html
|
||||
|
|
||||
|
#pragma once |
||||
|
|
||||
|
namespace ofx{ |
||||
|
namespace piMapper{ |
||||
|
|
||||
|
// Base class for all commands
|
||||
|
class BaseCommand{ |
||||
|
|
||||
|
public: |
||||
|
virtual ~BaseCommand(){}; |
||||
|
virtual void execute() = 0; |
||||
|
virtual bool isUndoable(){return false;} |
||||
|
|
||||
|
protected: |
||||
|
BaseCommand(){}; |
||||
|
}; |
||||
|
|
||||
|
// Base class for all undoable commands
|
||||
|
class BaseUndoableCommand : public BaseCommand{ |
||||
|
|
||||
|
public: |
||||
|
virtual void undo() = 0; |
||||
|
virtual bool isUndoable(){return true;} |
||||
|
|
||||
|
protected: |
||||
|
BaseUndoableCommand(){}; |
||||
|
}; |
||||
|
|
||||
|
} // namespace piMapper
|
||||
|
} // namespace ofx
|
||||
|
|
||||
|
// Ideas for command classes
|
||||
|
// SelectSurfaceCommand
|
||||
|
// MoveSurfaceCommand
|
||||
|
// SelectSourceMapCommand
|
||||
|
// MoveSourceMapCommand
|
@ -1,9 +0,0 @@ |
|||||
// Command base class for separating ofxPiMapper available commands from the core.
|
|
||||
// Created by Krisjanis Rijnieks 2015-03-23
|
|
||||
|
|
||||
#pragma once |
|
||||
|
|
||||
class Command{ |
|
||||
public: |
|
||||
virtual void execute() = 0; |
|
||||
}; |
|
@ -0,0 +1,27 @@ |
|||||
|
#include "CommandManager.h" |
||||
|
|
||||
|
namespace ofx{ |
||||
|
namespace piMapper{ |
||||
|
|
||||
|
void CommandManager::executeCommand(BaseCommand * cmd){ |
||||
|
cmd->execute(); |
||||
|
if (cmd->isUndoable()){ |
||||
|
commandStack.push_back(static_cast<BaseUndoableCommand *>(cmd)); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
void CommandManager::undo(){ |
||||
|
if (commandStack.size() > 0){ |
||||
|
BaseUndoableCommand * cmd = commandStack.back(); |
||||
|
cmd->undo(); |
||||
|
|
||||
|
// Delete last command for now
|
||||
|
// TODO: Enable redo func and that means we do not destroy last command,
|
||||
|
// we move the stack pointer instead.
|
||||
|
delete commandStack.back(); |
||||
|
commandStack.pop_back(); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
} // namespace piMapper
|
||||
|
} // namespace ofx
|
@ -0,0 +1,23 @@ |
|||||
|
// CommandManager class to keep a stack of commands for undo functionality
|
||||
|
// Created by Krisjanis Rijnieks 2015-03-24
|
||||
|
|
||||
|
#pragma once |
||||
|
|
||||
|
#import <deque> |
||||
|
#import "BaseCommand.h" |
||||
|
|
||||
|
namespace ofx{ |
||||
|
namespace piMapper{ |
||||
|
|
||||
|
class CommandManager{ |
||||
|
|
||||
|
public: |
||||
|
void executeCommand(BaseCommand * cmd); |
||||
|
void undo(); |
||||
|
|
||||
|
private: |
||||
|
std::deque<BaseUndoableCommand *> commandStack; |
||||
|
}; |
||||
|
|
||||
|
} // namespace piMapper
|
||||
|
} // namespace ofx
|
@ -1,10 +1,17 @@ |
|||||
# include "TestCommand.h" |
# include "TestCommand.h" |
||||
|
|
||||
TestCommand::TestCommand(ofxPiMapper * a){ |
namespace ofx{ |
||||
_application = a; |
namespace piMapper{ |
||||
} |
|
||||
|
TestCommand::TestCommand(ofxPiMapper * a){ |
||||
|
_application = a; |
||||
|
} |
||||
|
|
||||
|
void TestCommand::execute(){ |
||||
|
string name = "Hugo"; |
||||
|
_application->testCommand(name); |
||||
|
} |
||||
|
|
||||
|
} // namespace piMapper
|
||||
|
} // namespace ofx
|
||||
|
|
||||
void TestCommand::execute(){ |
|
||||
string name = "Hugo"; |
|
||||
_application->testCommand(name); |
|
||||
} |
|
@ -0,0 +1,21 @@ |
|||||
|
#include "TestUndoCommand.h" |
||||
|
|
||||
|
namespace ofx{ |
||||
|
namespace piMapper{ |
||||
|
|
||||
|
TestUndoCommand::TestUndoCommand(ofxPiMapper * a){ |
||||
|
_application = a; |
||||
|
} |
||||
|
|
||||
|
void TestUndoCommand::execute(){ |
||||
|
increase = 2; |
||||
|
_application->testUndoableCommand(increase); |
||||
|
} |
||||
|
|
||||
|
void TestUndoCommand::undo(){ |
||||
|
_application->testUndoableCommand(-increase); |
||||
|
} |
||||
|
|
||||
|
} // namespace piMapper
|
||||
|
} // namespace ofx
|
||||
|
|
@ -0,0 +1,27 @@ |
|||||
|
// Created by Krisjanis Rijnieks 2015-03-25
|
||||
|
|
||||
|
#pragma once |
||||
|
|
||||
|
#include "ofxPiMapper.h" |
||||
|
#include "BaseCommand.h" |
||||
|
|
||||
|
class ofxPiMapper; |
||||
|
|
||||
|
namespace ofx{ |
||||
|
namespace piMapper{ |
||||
|
|
||||
|
class TestUndoCommand : public BaseUndoableCommand{ |
||||
|
|
||||
|
public: |
||||
|
TestUndoCommand(ofxPiMapper * a); |
||||
|
void execute(); |
||||
|
void undo(); |
||||
|
|
||||
|
private: |
||||
|
ofxPiMapper * _application; |
||||
|
int increase; |
||||
|
}; |
||||
|
|
||||
|
} // namespace piMapper
|
||||
|
} // namespace ofx
|
||||
|
|
@ -1,173 +1,184 @@ |
|||||
#include "ofxPiMapper.h" |
#include "ofxPiMapper.h" |
||||
|
|
||||
ofxPiMapper::ofxPiMapper(): |
ofxPiMapper::ofxPiMapper(): bShowInfo(false), isSetUp(false){ |
||||
bShowInfo(false), |
ofAddListener(ofEvents().keyPressed, this, &ofxPiMapper::keyPressed); |
||||
isSetUp(false){ |
|
||||
ofAddListener(ofEvents().keyPressed, this, &ofxPiMapper::keyPressed); |
|
||||
} |
} |
||||
|
|
||||
ofxPiMapper::~ofxPiMapper() { |
ofxPiMapper::~ofxPiMapper(){ |
||||
ofRemoveListener(ofEvents().keyPressed, this, &ofxPiMapper::keyPressed); |
ofRemoveListener(ofEvents().keyPressed, this, &ofxPiMapper::keyPressed); |
||||
} |
} |
||||
|
|
||||
void ofxPiMapper::setup() { |
void ofxPiMapper::setup(){ |
||||
ofLogNotice("ofxPiMapper") << "Setting up..."; |
ofLogNotice("ofxPiMapper") << "Setting up..."; |
||||
|
|
||||
// Assign media server to other pi mapper components
|
// Assign media server to other pi mapper components
|
||||
surfaceManager.setMediaServer(&mediaServer); |
surfaceManager.setMediaServer(&mediaServer); |
||||
gui.setMediaServer(&mediaServer); |
gui.setMediaServer(&mediaServer); |
||||
|
|
||||
// Check if we have user surfaces defined, if not - load default
|
// Check if we have user surfaces defined, if not - load default
|
||||
if (ofFile::doesFileExist(PIMAPPER_USER_SURFACES_XML_FILE)) { |
if (ofFile::doesFileExist(PIMAPPER_USER_SURFACES_XML_FILE)){ |
||||
ofLogNotice("ofxPiMapper") << "Loading user surfaces from " << PIMAPPER_USER_SURFACES_XML_FILE; |
ofLogNotice("ofxPiMapper") << "Loading user surfaces from " << PIMAPPER_USER_SURFACES_XML_FILE; |
||||
surfaceManager.loadXmlSettings(PIMAPPER_USER_SURFACES_XML_FILE); |
surfaceManager.loadXmlSettings(PIMAPPER_USER_SURFACES_XML_FILE); |
||||
} else { |
} else { |
||||
ofLogNotice("ofxPiMapper") << "Loading default surfaces from " << PIMAPPER_DEF_SURFACES_XML_FILE; |
ofLogNotice("ofxPiMapper") << "Loading default surfaces from " << PIMAPPER_DEF_SURFACES_XML_FILE; |
||||
surfaceManager.loadXmlSettings(PIMAPPER_DEF_SURFACES_XML_FILE); |
surfaceManager.loadXmlSettings(PIMAPPER_DEF_SURFACES_XML_FILE); |
||||
} |
} |
||||
|
|
||||
// The GUI needs something to interface with
|
// The GUI needs something to interface with
|
||||
gui.setSurfaceManager(&surfaceManager); |
gui.setSurfaceManager(&surfaceManager); |
||||
|
|
||||
isSetUp = true; |
isSetUp = true; |
||||
|
|
||||
ofLogNotice("ofxPiMapper") << "Done setting up"; |
ofLogNotice("ofxPiMapper") << "Done setting up"; |
||||
|
|
||||
// Initialize TestCommand
|
// Initialize undo test vars
|
||||
ofxPiMapper * app = this; |
undoTestValue = 0; |
||||
aTestCommand = new TestCommand(app); |
|
||||
} |
} |
||||
|
|
||||
void ofxPiMapper::draw() { |
void ofxPiMapper::draw(){ |
||||
if (!isSetUp) { |
if (!isSetUp) { |
||||
return; |
return; |
||||
} |
} |
||||
|
|
||||
// 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 <t> to add new triangle surface\n"; |
ss << "Press <t> to add new triangle surface\n"; |
||||
ss << "Press <q> to add new quad surface\n"; |
ss << "Press <q> to add 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 <i> to hide this message"; |
ss << "Press <i> to hide this message"; |
||||
|
|
||||
ofDrawBitmapStringHighlight(ss.str(), 10, 20, ofColor(0, 0, 0, 100), |
ofDrawBitmapStringHighlight(ss.str(), 10, 20, ofColor(0, 0, 0, 100), |
||||
ofColor(255, 255, 255, 200)); |
ofColor(255, 255, 255, 200)); |
||||
} |
} |
||||
|
|
||||
|
ofDrawBitmapStringHighlight(ofToString(undoTestValue), 200, 200); |
||||
|
|
||||
} // draw
|
} // draw
|
||||
|
|
||||
void ofxPiMapper::keyPressed(ofKeyEventArgs &args) { |
void ofxPiMapper::keyPressed(ofKeyEventArgs &args){ |
||||
ofLogNotice("ofxPiMapper") << "Key pressed: " << static_cast<char>(args.key); |
ofLogNotice("ofxPiMapper") << "Key pressed: " << static_cast<char>(args.key); |
||||
|
|
||||
switch (args.key) { |
switch (args.key) { |
||||
case '1': |
|
||||
gui.setMode(ofx::piMapper::GuiMode::NONE); |
case '1': |
||||
break; |
gui.setMode(ofx::piMapper::GuiMode::NONE); |
||||
case '2': |
break; |
||||
gui.setMode(ofx::piMapper::GuiMode::TEXTURE_MAPPING); |
case '2': |
||||
break; |
gui.setMode(ofx::piMapper::GuiMode::TEXTURE_MAPPING); |
||||
case '3': |
break; |
||||
gui.setMode(ofx::piMapper::GuiMode::PROJECTION_MAPPING); |
case '3': |
||||
break; |
gui.setMode(ofx::piMapper::GuiMode::PROJECTION_MAPPING); |
||||
case '4': |
break; |
||||
gui.setMode(ofx::piMapper::GuiMode::SOURCE_SELECTION); |
case '4': |
||||
break; |
gui.setMode(ofx::piMapper::GuiMode::SOURCE_SELECTION); |
||||
case 'i': |
break; |
||||
bShowInfo = !bShowInfo; |
case 'i': |
||||
break; |
bShowInfo = !bShowInfo; |
||||
case 'q': |
break; |
||||
addQuadSurface(); |
case 'q': |
||||
break; |
addQuadSurface(); |
||||
case 't': |
break; |
||||
addTriangleSurface(); |
case 't': |
||||
break; |
addTriangleSurface(); |
||||
case 'f': |
break; |
||||
ofToggleFullscreen(); |
case 'f': |
||||
break; |
ofToggleFullscreen(); |
||||
case 's': |
break; |
||||
surfaceManager.saveXmlSettings(PIMAPPER_USER_SURFACES_XML_FILE); |
case 's': |
||||
break; |
surfaceManager.saveXmlSettings(PIMAPPER_USER_SURFACES_XML_FILE); |
||||
case OF_KEY_BACKSPACE: |
break; |
||||
surfaceManager.removeSelectedSurface(); |
case OF_KEY_BACKSPACE: |
||||
break; |
surfaceManager.removeSelectedSurface(); |
||||
// TODO: Remove the following case when Command test done.
|
break; |
||||
case '0': |
// TODO: Remove the following case when Command test done.
|
||||
aTestCommand->execute(); |
case '9': |
||||
break; |
commandManager.executeCommand(new ofx::piMapper::TestUndoCommand((ofxPiMapper *)this)); |
||||
default: |
break; |
||||
break; |
case '0': |
||||
} |
commandManager.executeCommand(new ofx::piMapper::TestCommand((ofxPiMapper *)this)); |
||||
|
break; |
||||
|
case 'u': |
||||
|
// undo
|
||||
|
commandManager.undo(); |
||||
|
break; |
||||
|
default: |
||||
|
break; |
||||
|
} |
||||
} // keyPressed
|
} // keyPressed
|
||||
|
|
||||
void ofxPiMapper::addFboSource(ofx::piMapper::FboSource &fboSource) { |
void ofxPiMapper::addFboSource(ofx::piMapper::FboSource &fboSource){ |
||||
mediaServer.addFboSource(fboSource); |
mediaServer.addFboSource(fboSource); |
||||
} // addFboSource
|
} // addFboSource
|
||||
|
|
||||
void ofxPiMapper::addTriangleSurface() { |
void ofxPiMapper::addTriangleSurface(){ |
||||
int surfaceType = ofx::piMapper::SurfaceType::TRIANGLE_SURFACE; |
int surfaceType = ofx::piMapper::SurfaceType::TRIANGLE_SURFACE; |
||||
|
|
||||
vector<ofVec2f> vertices; |
vector<ofVec2f> vertices; |
||||
float margin = 50.0f; |
float margin = 50.0f; |
||||
vertices.push_back(ofVec2f((float)ofGetWidth() / 2.0f, margin)); |
vertices.push_back(ofVec2f((float)ofGetWidth() / 2.0f, margin)); |
||||
vertices.push_back(ofVec2f((float)ofGetWidth() - margin, (float)ofGetHeight() - margin)); |
vertices.push_back(ofVec2f((float)ofGetWidth() - margin, (float)ofGetHeight() - margin)); |
||||
vertices.push_back(ofVec2f(margin, (float)ofGetHeight() - margin)); |
vertices.push_back(ofVec2f(margin, (float)ofGetHeight() - margin)); |
||||
|
|
||||
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); |
||||
|
|
||||
} // addTriangleSurface
|
} // addTriangleSurface
|
||||
|
|
||||
void ofxPiMapper::addQuadSurface() { |
void ofxPiMapper::addQuadSurface(){ |
||||
|
|
||||
int surfaceType = ofx::piMapper::SurfaceType::QUAD_SURFACE; |
int surfaceType = ofx::piMapper::SurfaceType::QUAD_SURFACE; |
||||
|
|
||||
vector<ofVec2f> vertices; |
vector<ofVec2f> vertices; |
||||
float margin = 50.0f; |
float margin = 50.0f; |
||||
vertices.push_back(ofVec2f(margin, margin)); |
vertices.push_back(ofVec2f(margin, margin)); |
||||
vertices.push_back(ofVec2f((float)ofGetWidth() - margin, margin)); |
vertices.push_back(ofVec2f((float)ofGetWidth() - margin, margin)); |
||||
vertices.push_back(ofVec2f((float)ofGetWidth() - margin, (float)ofGetHeight() - margin)); |
vertices.push_back(ofVec2f((float)ofGetWidth() - margin, (float)ofGetHeight() - margin)); |
||||
vertices.push_back(ofVec2f(margin, (float)ofGetHeight() - margin)); |
vertices.push_back(ofVec2f(margin, (float)ofGetHeight() - margin)); |
||||
|
|
||||
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); |
||||
|
|
||||
} // addQuadSurface
|
} // addQuadSurface
|
||||
|
|
||||
ofx::piMapper::MediaServer& ofxPiMapper::getMediaServer() { |
ofx::piMapper::MediaServer& ofxPiMapper::getMediaServer(){ |
||||
return mediaServer; |
return mediaServer; |
||||
} |
} |
||||
|
|
||||
ofx::piMapper::SurfaceManager& ofxPiMapper::getSurfaceManager() { |
ofx::piMapper::SurfaceManager& ofxPiMapper::getSurfaceManager(){ |
||||
return surfaceManager; |
return surfaceManager; |
||||
} |
} |
||||
|
|
||||
// TODO: remove this when done testing and everything works
|
// TODO: remove this when done testing and everything works
|
||||
void ofxPiMapper::testCommand(string name){ |
void ofxPiMapper::testCommand(string name){ |
||||
ofLogNotice("ofxPiMapper", name); |
ofLogNotice("ofxPiMapper", name); |
||||
|
} |
||||
|
|
||||
|
void ofxPiMapper::testUndoableCommand(int increase){ |
||||
|
undoTestValue += increase; |
||||
} |
} |
Loading…
Reference in new issue